aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /security/selinux
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/Kconfig97
-rw-r--r--security/selinux/Makefile12
-rw-r--r--security/selinux/avc.c949
-rw-r--r--security/selinux/hooks.c4565
-rw-r--r--security/selinux/include/av_inherit.h30
-rw-r--r--security/selinux/include/av_perm_to_string.h232
-rw-r--r--security/selinux/include/av_permissions.h902
-rw-r--r--security/selinux/include/avc.h137
-rw-r--r--security/selinux/include/avc_ss.h14
-rw-r--r--security/selinux/include/class_to_string.h58
-rw-r--r--security/selinux/include/common_perm_to_string.h58
-rw-r--r--security/selinux/include/conditional.h22
-rw-r--r--security/selinux/include/flask.h95
-rw-r--r--security/selinux/include/initial_sid_to_string.h33
-rw-r--r--security/selinux/include/netif.h21
-rw-r--r--security/selinux/include/objsec.h112
-rw-r--r--security/selinux/include/security.h97
-rw-r--r--security/selinux/netif.c270
-rw-r--r--security/selinux/netlink.c113
-rw-r--r--security/selinux/nlmsgtab.c156
-rw-r--r--security/selinux/selinuxfs.c1340
-rw-r--r--security/selinux/ss/Makefile9
-rw-r--r--security/selinux/ss/avtab.c399
-rw-r--r--security/selinux/ss/avtab.h85
-rw-r--r--security/selinux/ss/conditional.c489
-rw-r--r--security/selinux/ss/conditional.h77
-rw-r--r--security/selinux/ss/constraint.h61
-rw-r--r--security/selinux/ss/context.h107
-rw-r--r--security/selinux/ss/ebitmap.c293
-rw-r--r--security/selinux/ss/ebitmap.h48
-rw-r--r--security/selinux/ss/hashtab.c167
-rw-r--r--security/selinux/ss/hashtab.h87
-rw-r--r--security/selinux/ss/mls.c527
-rw-r--r--security/selinux/ss/mls.h42
-rw-r--r--security/selinux/ss/mls_types.h56
-rw-r--r--security/selinux/ss/policydb.c1843
-rw-r--r--security/selinux/ss/policydb.h275
-rw-r--r--security/selinux/ss/services.c1777
-rw-r--r--security/selinux/ss/services.h15
-rw-r--r--security/selinux/ss/sidtab.c305
-rw-r--r--security/selinux/ss/sidtab.h59
-rw-r--r--security/selinux/ss/symtab.c44
-rw-r--r--security/selinux/ss/symtab.h23
43 files changed, 16101 insertions, 0 deletions
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
new file mode 100644
index 00000000000..b59582b9228
--- /dev/null
+++ b/security/selinux/Kconfig
@@ -0,0 +1,97 @@
1config SECURITY_SELINUX
2 bool "NSA SELinux Support"
3 depends on SECURITY && NET && INET
4 default n
5 help
6 This selects NSA Security-Enhanced Linux (SELinux).
7 You will also need a policy configuration and a labeled filesystem.
8 You can obtain the policy compiler (checkpolicy), the utility for
9 labeling filesystems (setfiles), and an example policy configuration
10 from <http://www.nsa.gov/selinux/>.
11 If you are unsure how to answer this question, answer N.
12
13config SECURITY_SELINUX_BOOTPARAM
14 bool "NSA SELinux boot parameter"
15 depends on SECURITY_SELINUX
16 default n
17 help
18 This option adds a kernel parameter 'selinux', which allows SELinux
19 to be disabled at boot. If this option is selected, SELinux
20 functionality can be disabled with selinux=0 on the kernel
21 command line. The purpose of this option is to allow a single
22 kernel image to be distributed with SELinux built in, but not
23 necessarily enabled.
24
25 If you are unsure how to answer this question, answer N.
26
27config SECURITY_SELINUX_BOOTPARAM_VALUE
28 int "NSA SELinux boot parameter default value"
29 depends on SECURITY_SELINUX_BOOTPARAM
30 range 0 1
31 default 1
32 help
33 This option sets the default value for the kernel parameter
34 'selinux', which allows SELinux to be disabled at boot. If this
35 option is set to 0 (zero), the SELinux kernel parameter will
36 default to 0, disabling SELinux at bootup. If this option is
37 set to 1 (one), the SELinux kernel parameter will default to 1,
38 enabling SELinux at bootup.
39
40 If you are unsure how to answer this question, answer 1.
41
42config SECURITY_SELINUX_DISABLE
43 bool "NSA SELinux runtime disable"
44 depends on SECURITY_SELINUX
45 default n
46 help
47 This option enables writing to a selinuxfs node 'disable', which
48 allows SELinux to be disabled at runtime prior to the policy load.
49 SELinux will then remain disabled until the next boot.
50 This option is similar to the selinux=0 boot parameter, but is to
51 support runtime disabling of SELinux, e.g. from /sbin/init, for
52 portability across platforms where boot parameters are difficult
53 to employ.
54
55 If you are unsure how to answer this question, answer N.
56
57config SECURITY_SELINUX_DEVELOP
58 bool "NSA SELinux Development Support"
59 depends on SECURITY_SELINUX
60 default y
61 help
62 This enables the development support option of NSA SELinux,
63 which is useful for experimenting with SELinux and developing
64 policies. If unsure, say Y. With this option enabled, the
65 kernel will start in permissive mode (log everything, deny nothing)
66 unless you specify enforcing=1 on the kernel command line. You
67 can interactively toggle the kernel between enforcing mode and
68 permissive mode (if permitted by the policy) via /selinux/enforce.
69
70config SECURITY_SELINUX_AVC_STATS
71 bool "NSA SELinux AVC Statistics"
72 depends on SECURITY_SELINUX
73 default y
74 help
75 This option collects access vector cache statistics to
76 /selinux/avc/cache_stats, which may be monitored via
77 tools such as avcstat.
78
79config SECURITY_SELINUX_CHECKREQPROT_VALUE
80 int "NSA SELinux checkreqprot default value"
81 depends on SECURITY_SELINUX
82 range 0 1
83 default 1
84 help
85 This option sets the default value for the 'checkreqprot' flag
86 that determines whether SELinux checks the protection requested
87 by the application or the protection that will be applied by the
88 kernel (including any implied execute for read-implies-exec) for
89 mmap and mprotect calls. If this option is set to 0 (zero),
90 SELinux will default to checking the protection that will be applied
91 by the kernel. If this option is set to 1 (one), SELinux will
92 default to checking the protection requested by the application.
93 The checkreqprot flag may be changed from the default via the
94 'checkreqprot=' boot parameter. It may also be changed at runtime
95 via /selinux/checkreqprot if authorized by policy.
96
97 If you are unsure how to answer this question, answer 1.
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
new file mode 100644
index 00000000000..b038cd0fae2
--- /dev/null
+++ b/security/selinux/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile for building the SELinux module as part of the kernel tree.
3#
4
5obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
6
7selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o
8
9selinux-$(CONFIG_SECURITY_NETWORK) += netif.o
10
11EXTRA_CFLAGS += -Isecurity/selinux/include
12
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
new file mode 100644
index 00000000000..fe6285e5c68
--- /dev/null
+++ b/security/selinux/avc.c
@@ -0,0 +1,949 @@
1/*
2 * Implementation of the kernel access vector cache (AVC).
3 *
4 * Authors: Stephen Smalley, <sds@epoch.ncsc.mil>
5 * James Morris <jmorris@redhat.com>
6 *
7 * Update: KaiGai, Kohei <kaigai@ak.jp.nec.com>
8 * Replaced the avc_lock spinlock by RCU.
9 *
10 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2,
14 * as published by the Free Software Foundation.
15 */
16#include <linux/types.h>
17#include <linux/stddef.h>
18#include <linux/kernel.h>
19#include <linux/slab.h>
20#include <linux/fs.h>
21#include <linux/dcache.h>
22#include <linux/init.h>
23#include <linux/skbuff.h>
24#include <linux/percpu.h>
25#include <net/sock.h>
26#include <linux/un.h>
27#include <net/af_unix.h>
28#include <linux/ip.h>
29#include <linux/audit.h>
30#include <linux/ipv6.h>
31#include <net/ipv6.h>
32#include "avc.h"
33#include "avc_ss.h"
34
35static const struct av_perm_to_string
36{
37 u16 tclass;
38 u32 value;
39 const char *name;
40} av_perm_to_string[] = {
41#define S_(c, v, s) { c, v, s },
42#include "av_perm_to_string.h"
43#undef S_
44};
45
46#ifdef CONFIG_AUDIT
47static const char *class_to_string[] = {
48#define S_(s) s,
49#include "class_to_string.h"
50#undef S_
51};
52#endif
53
54#define TB_(s) static const char * s [] = {
55#define TE_(s) };
56#define S_(s) s,
57#include "common_perm_to_string.h"
58#undef TB_
59#undef TE_
60#undef S_
61
62static const struct av_inherit
63{
64 u16 tclass;
65 const char **common_pts;
66 u32 common_base;
67} av_inherit[] = {
68#define S_(c, i, b) { c, common_##i##_perm_to_string, b },
69#include "av_inherit.h"
70#undef S_
71};
72
73#define AVC_CACHE_SLOTS 512
74#define AVC_DEF_CACHE_THRESHOLD 512
75#define AVC_CACHE_RECLAIM 16
76
77#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
78#define avc_cache_stats_incr(field) \
79do { \
80 per_cpu(avc_cache_stats, get_cpu()).field++; \
81 put_cpu(); \
82} while (0)
83#else
84#define avc_cache_stats_incr(field) do {} while (0)
85#endif
86
87struct avc_entry {
88 u32 ssid;
89 u32 tsid;
90 u16 tclass;
91 struct av_decision avd;
92 atomic_t used; /* used recently */
93};
94
95struct avc_node {
96 struct avc_entry ae;
97 struct list_head list;
98 struct rcu_head rhead;
99};
100
101struct avc_cache {
102 struct list_head slots[AVC_CACHE_SLOTS];
103 spinlock_t slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */
104 atomic_t lru_hint; /* LRU hint for reclaim scan */
105 atomic_t active_nodes;
106 u32 latest_notif; /* latest revocation notification */
107};
108
109struct avc_callback_node {
110 int (*callback) (u32 event, u32 ssid, u32 tsid,
111 u16 tclass, u32 perms,
112 u32 *out_retained);
113 u32 events;
114 u32 ssid;
115 u32 tsid;
116 u16 tclass;
117 u32 perms;
118 struct avc_callback_node *next;
119};
120
121/* Exported via selinufs */
122unsigned int avc_cache_threshold = AVC_DEF_CACHE_THRESHOLD;
123
124#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
125DEFINE_PER_CPU(struct avc_cache_stats, avc_cache_stats) = { 0 };
126#endif
127
128static struct avc_cache avc_cache;
129static struct avc_callback_node *avc_callbacks;
130static kmem_cache_t *avc_node_cachep;
131
132static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
133{
134 return (ssid ^ (tsid<<2) ^ (tclass<<4)) & (AVC_CACHE_SLOTS - 1);
135}
136
137/**
138 * avc_dump_av - Display an access vector in human-readable form.
139 * @tclass: target security class
140 * @av: access vector
141 */
142static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
143{
144 const char **common_pts = NULL;
145 u32 common_base = 0;
146 int i, i2, perm;
147
148 if (av == 0) {
149 audit_log_format(ab, " null");
150 return;
151 }
152
153 for (i = 0; i < ARRAY_SIZE(av_inherit); i++) {
154 if (av_inherit[i].tclass == tclass) {
155 common_pts = av_inherit[i].common_pts;
156 common_base = av_inherit[i].common_base;
157 break;
158 }
159 }
160
161 audit_log_format(ab, " {");
162 i = 0;
163 perm = 1;
164 while (perm < common_base) {
165 if (perm & av) {
166 audit_log_format(ab, " %s", common_pts[i]);
167 av &= ~perm;
168 }
169 i++;
170 perm <<= 1;
171 }
172
173 while (i < sizeof(av) * 8) {
174 if (perm & av) {
175 for (i2 = 0; i2 < ARRAY_SIZE(av_perm_to_string); i2++) {
176 if ((av_perm_to_string[i2].tclass == tclass) &&
177 (av_perm_to_string[i2].value == perm))
178 break;
179 }
180 if (i2 < ARRAY_SIZE(av_perm_to_string)) {
181 audit_log_format(ab, " %s",
182 av_perm_to_string[i2].name);
183 av &= ~perm;
184 }
185 }
186 i++;
187 perm <<= 1;
188 }
189
190 if (av)
191 audit_log_format(ab, " 0x%x", av);
192
193 audit_log_format(ab, " }");
194}
195
196/**
197 * avc_dump_query - Display a SID pair and a class in human-readable form.
198 * @ssid: source security identifier
199 * @tsid: target security identifier
200 * @tclass: target security class
201 */
202static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass)
203{
204 int rc;
205 char *scontext;
206 u32 scontext_len;
207
208 rc = security_sid_to_context(ssid, &scontext, &scontext_len);
209 if (rc)
210 audit_log_format(ab, "ssid=%d", ssid);
211 else {
212 audit_log_format(ab, "scontext=%s", scontext);
213 kfree(scontext);
214 }
215
216 rc = security_sid_to_context(tsid, &scontext, &scontext_len);
217 if (rc)
218 audit_log_format(ab, " tsid=%d", tsid);
219 else {
220 audit_log_format(ab, " tcontext=%s", scontext);
221 kfree(scontext);
222 }
223 audit_log_format(ab, " tclass=%s", class_to_string[tclass]);
224}
225
226/**
227 * avc_init - Initialize the AVC.
228 *
229 * Initialize the access vector cache.
230 */
231void __init avc_init(void)
232{
233 int i;
234
235 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
236 INIT_LIST_HEAD(&avc_cache.slots[i]);
237 spin_lock_init(&avc_cache.slots_lock[i]);
238 }
239 atomic_set(&avc_cache.active_nodes, 0);
240 atomic_set(&avc_cache.lru_hint, 0);
241
242 avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
243 0, SLAB_PANIC, NULL, NULL);
244
245 audit_log(current->audit_context, "AVC INITIALIZED\n");
246}
247
248int avc_get_hash_stats(char *page)
249{
250 int i, chain_len, max_chain_len, slots_used;
251 struct avc_node *node;
252
253 rcu_read_lock();
254
255 slots_used = 0;
256 max_chain_len = 0;
257 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
258 if (!list_empty(&avc_cache.slots[i])) {
259 slots_used++;
260 chain_len = 0;
261 list_for_each_entry_rcu(node, &avc_cache.slots[i], list)
262 chain_len++;
263 if (chain_len > max_chain_len)
264 max_chain_len = chain_len;
265 }
266 }
267
268 rcu_read_unlock();
269
270 return scnprintf(page, PAGE_SIZE, "entries: %d\nbuckets used: %d/%d\n"
271 "longest chain: %d\n",
272 atomic_read(&avc_cache.active_nodes),
273 slots_used, AVC_CACHE_SLOTS, max_chain_len);
274}
275
276static void avc_node_free(struct rcu_head *rhead)
277{
278 struct avc_node *node = container_of(rhead, struct avc_node, rhead);
279 kmem_cache_free(avc_node_cachep, node);
280 avc_cache_stats_incr(frees);
281}
282
283static void avc_node_delete(struct avc_node *node)
284{
285 list_del_rcu(&node->list);
286 call_rcu(&node->rhead, avc_node_free);
287 atomic_dec(&avc_cache.active_nodes);
288}
289
290static void avc_node_kill(struct avc_node *node)
291{
292 kmem_cache_free(avc_node_cachep, node);
293 avc_cache_stats_incr(frees);
294 atomic_dec(&avc_cache.active_nodes);
295}
296
297static void avc_node_replace(struct avc_node *new, struct avc_node *old)
298{
299 list_replace_rcu(&old->list, &new->list);
300 call_rcu(&old->rhead, avc_node_free);
301 atomic_dec(&avc_cache.active_nodes);
302}
303
304static inline int avc_reclaim_node(void)
305{
306 struct avc_node *node;
307 int hvalue, try, ecx;
308 unsigned long flags;
309
310 for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++ ) {
311 hvalue = atomic_inc_return(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
312
313 if (!spin_trylock_irqsave(&avc_cache.slots_lock[hvalue], flags))
314 continue;
315
316 list_for_each_entry(node, &avc_cache.slots[hvalue], list) {
317 if (atomic_dec_and_test(&node->ae.used)) {
318 /* Recently Unused */
319 avc_node_delete(node);
320 avc_cache_stats_incr(reclaims);
321 ecx++;
322 if (ecx >= AVC_CACHE_RECLAIM) {
323 spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
324 goto out;
325 }
326 }
327 }
328 spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
329 }
330out:
331 return ecx;
332}
333
334static struct avc_node *avc_alloc_node(void)
335{
336 struct avc_node *node;
337
338 node = kmem_cache_alloc(avc_node_cachep, SLAB_ATOMIC);
339 if (!node)
340 goto out;
341
342 memset(node, 0, sizeof(*node));
343 INIT_RCU_HEAD(&node->rhead);
344 INIT_LIST_HEAD(&node->list);
345 atomic_set(&node->ae.used, 1);
346 avc_cache_stats_incr(allocations);
347
348 if (atomic_inc_return(&avc_cache.active_nodes) > avc_cache_threshold)
349 avc_reclaim_node();
350
351out:
352 return node;
353}
354
355static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae)
356{
357 node->ae.ssid = ssid;
358 node->ae.tsid = tsid;
359 node->ae.tclass = tclass;
360 memcpy(&node->ae.avd, &ae->avd, sizeof(node->ae.avd));
361}
362
363static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass)
364{
365 struct avc_node *node, *ret = NULL;
366 int hvalue;
367
368 hvalue = avc_hash(ssid, tsid, tclass);
369 list_for_each_entry_rcu(node, &avc_cache.slots[hvalue], list) {
370 if (ssid == node->ae.ssid &&
371 tclass == node->ae.tclass &&
372 tsid == node->ae.tsid) {
373 ret = node;
374 break;
375 }
376 }
377
378 if (ret == NULL) {
379 /* cache miss */
380 goto out;
381 }
382
383 /* cache hit */
384 if (atomic_read(&ret->ae.used) != 1)
385 atomic_set(&ret->ae.used, 1);
386out:
387 return ret;
388}
389
390/**
391 * avc_lookup - Look up an AVC entry.
392 * @ssid: source security identifier
393 * @tsid: target security identifier
394 * @tclass: target security class
395 * @requested: requested permissions, interpreted based on @tclass
396 *
397 * Look up an AVC entry that is valid for the
398 * @requested permissions between the SID pair
399 * (@ssid, @tsid), interpreting the permissions
400 * based on @tclass. If a valid AVC entry exists,
401 * then this function return the avc_node.
402 * Otherwise, this function returns NULL.
403 */
404static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass, u32 requested)
405{
406 struct avc_node *node;
407
408 avc_cache_stats_incr(lookups);
409 node = avc_search_node(ssid, tsid, tclass);
410
411 if (node && ((node->ae.avd.decided & requested) == requested)) {
412 avc_cache_stats_incr(hits);
413 goto out;
414 }
415
416 node = NULL;
417 avc_cache_stats_incr(misses);
418out:
419 return node;
420}
421
422static int avc_latest_notif_update(int seqno, int is_insert)
423{
424 int ret = 0;
425 static DEFINE_SPINLOCK(notif_lock);
426 unsigned long flag;
427
428 spin_lock_irqsave(&notif_lock, flag);
429 if (is_insert) {
430 if (seqno < avc_cache.latest_notif) {
431 printk(KERN_WARNING "avc: seqno %d < latest_notif %d\n",
432 seqno, avc_cache.latest_notif);
433 ret = -EAGAIN;
434 }
435 } else {
436 if (seqno > avc_cache.latest_notif)
437 avc_cache.latest_notif = seqno;
438 }
439 spin_unlock_irqrestore(&notif_lock, flag);
440
441 return ret;
442}
443
444/**
445 * avc_insert - Insert an AVC entry.
446 * @ssid: source security identifier
447 * @tsid: target security identifier
448 * @tclass: target security class
449 * @ae: AVC entry
450 *
451 * Insert an AVC entry for the SID pair
452 * (@ssid, @tsid) and class @tclass.
453 * The access vectors and the sequence number are
454 * normally provided by the security server in
455 * response to a security_compute_av() call. If the
456 * sequence number @ae->avd.seqno is not less than the latest
457 * revocation notification, then the function copies
458 * the access vectors into a cache entry, returns
459 * avc_node inserted. Otherwise, this function returns NULL.
460 */
461static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae)
462{
463 struct avc_node *pos, *node = NULL;
464 int hvalue;
465 unsigned long flag;
466
467 if (avc_latest_notif_update(ae->avd.seqno, 1))
468 goto out;
469
470 node = avc_alloc_node();
471 if (node) {
472 hvalue = avc_hash(ssid, tsid, tclass);
473 avc_node_populate(node, ssid, tsid, tclass, ae);
474
475 spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
476 list_for_each_entry(pos, &avc_cache.slots[hvalue], list) {
477 if (pos->ae.ssid == ssid &&
478 pos->ae.tsid == tsid &&
479 pos->ae.tclass == tclass) {
480 avc_node_replace(node, pos);
481 goto found;
482 }
483 }
484 list_add_rcu(&node->list, &avc_cache.slots[hvalue]);
485found:
486 spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag);
487 }
488out:
489 return node;
490}
491
492static inline void avc_print_ipv6_addr(struct audit_buffer *ab,
493 struct in6_addr *addr, u16 port,
494 char *name1, char *name2)
495{
496 if (!ipv6_addr_any(addr))
497 audit_log_format(ab, " %s=%04x:%04x:%04x:%04x:%04x:"
498 "%04x:%04x:%04x", name1, NIP6(*addr));
499 if (port)
500 audit_log_format(ab, " %s=%d", name2, ntohs(port));
501}
502
503static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr,
504 u16 port, char *name1, char *name2)
505{
506 if (addr)
507 audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr));
508 if (port)
509 audit_log_format(ab, " %s=%d", name2, ntohs(port));
510}
511
512/**
513 * avc_audit - Audit the granting or denial of permissions.
514 * @ssid: source security identifier
515 * @tsid: target security identifier
516 * @tclass: target security class
517 * @requested: requested permissions
518 * @avd: access vector decisions
519 * @result: result from avc_has_perm_noaudit
520 * @a: auxiliary audit data
521 *
522 * Audit the granting or denial of permissions in accordance
523 * with the policy. This function is typically called by
524 * avc_has_perm() after a permission check, but can also be
525 * called directly by callers who use avc_has_perm_noaudit()
526 * in order to separate the permission check from the auditing.
527 * For example, this separation is useful when the permission check must
528 * be performed under a lock, to allow the lock to be released
529 * before calling the auditing code.
530 */
531void avc_audit(u32 ssid, u32 tsid,
532 u16 tclass, u32 requested,
533 struct av_decision *avd, int result, struct avc_audit_data *a)
534{
535 struct task_struct *tsk = current;
536 struct inode *inode = NULL;
537 u32 denied, audited;
538 struct audit_buffer *ab;
539
540 denied = requested & ~avd->allowed;
541 if (denied) {
542 audited = denied;
543 if (!(audited & avd->auditdeny))
544 return;
545 } else if (result) {
546 audited = denied = requested;
547 } else {
548 audited = requested;
549 if (!(audited & avd->auditallow))
550 return;
551 }
552
553 ab = audit_log_start(current->audit_context);
554 if (!ab)
555 return; /* audit_panic has been called */
556 audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted");
557 avc_dump_av(ab, tclass,audited);
558 audit_log_format(ab, " for ");
559 if (a && a->tsk)
560 tsk = a->tsk;
561 if (tsk && tsk->pid) {
562 struct mm_struct *mm;
563 struct vm_area_struct *vma;
564 audit_log_format(ab, " pid=%d", tsk->pid);
565 if (tsk == current)
566 mm = current->mm;
567 else
568 mm = get_task_mm(tsk);
569 if (mm) {
570 if (down_read_trylock(&mm->mmap_sem)) {
571 vma = mm->mmap;
572 while (vma) {
573 if ((vma->vm_flags & VM_EXECUTABLE) &&
574 vma->vm_file) {
575 audit_log_d_path(ab, "exe=",
576 vma->vm_file->f_dentry,
577 vma->vm_file->f_vfsmnt);
578 break;
579 }
580 vma = vma->vm_next;
581 }
582 up_read(&mm->mmap_sem);
583 } else {
584 audit_log_format(ab, " comm=%s", tsk->comm);
585 }
586 if (tsk != current)
587 mmput(mm);
588 } else {
589 audit_log_format(ab, " comm=%s", tsk->comm);
590 }
591 }
592 if (a) {
593 switch (a->type) {
594 case AVC_AUDIT_DATA_IPC:
595 audit_log_format(ab, " key=%d", a->u.ipc_id);
596 break;
597 case AVC_AUDIT_DATA_CAP:
598 audit_log_format(ab, " capability=%d", a->u.cap);
599 break;
600 case AVC_AUDIT_DATA_FS:
601 if (a->u.fs.dentry) {
602 struct dentry *dentry = a->u.fs.dentry;
603 if (a->u.fs.mnt) {
604 audit_log_d_path(ab, "path=", dentry,
605 a->u.fs.mnt);
606 } else {
607 audit_log_format(ab, " name=%s",
608 dentry->d_name.name);
609 }
610 inode = dentry->d_inode;
611 } else if (a->u.fs.inode) {
612 struct dentry *dentry;
613 inode = a->u.fs.inode;
614 dentry = d_find_alias(inode);
615 if (dentry) {
616 audit_log_format(ab, " name=%s",
617 dentry->d_name.name);
618 dput(dentry);
619 }
620 }
621 if (inode)
622 audit_log_format(ab, " dev=%s ino=%ld",
623 inode->i_sb->s_id,
624 inode->i_ino);
625 break;
626 case AVC_AUDIT_DATA_NET:
627 if (a->u.net.sk) {
628 struct sock *sk = a->u.net.sk;
629 struct unix_sock *u;
630 int len = 0;
631 char *p = NULL;
632
633 switch (sk->sk_family) {
634 case AF_INET: {
635 struct inet_sock *inet = inet_sk(sk);
636
637 avc_print_ipv4_addr(ab, inet->rcv_saddr,
638 inet->sport,
639 "laddr", "lport");
640 avc_print_ipv4_addr(ab, inet->daddr,
641 inet->dport,
642 "faddr", "fport");
643 break;
644 }
645 case AF_INET6: {
646 struct inet_sock *inet = inet_sk(sk);
647 struct ipv6_pinfo *inet6 = inet6_sk(sk);
648
649 avc_print_ipv6_addr(ab, &inet6->rcv_saddr,
650 inet->sport,
651 "laddr", "lport");
652 avc_print_ipv6_addr(ab, &inet6->daddr,
653 inet->dport,
654 "faddr", "fport");
655 break;
656 }
657 case AF_UNIX:
658 u = unix_sk(sk);
659 if (u->dentry) {
660 audit_log_d_path(ab, "path=",
661 u->dentry, u->mnt);
662 break;
663 }
664 if (!u->addr)
665 break;
666 len = u->addr->len-sizeof(short);
667 p = &u->addr->name->sun_path[0];
668 if (*p)
669 audit_log_format(ab,
670 "path=%*.*s", len,
671 len, p);
672 else
673 audit_log_format(ab,
674 "path=@%*.*s", len-1,
675 len-1, p+1);
676 break;
677 }
678 }
679
680 switch (a->u.net.family) {
681 case AF_INET:
682 avc_print_ipv4_addr(ab, a->u.net.v4info.saddr,
683 a->u.net.sport,
684 "saddr", "src");
685 avc_print_ipv4_addr(ab, a->u.net.v4info.daddr,
686 a->u.net.dport,
687 "daddr", "dest");
688 break;
689 case AF_INET6:
690 avc_print_ipv6_addr(ab, &a->u.net.v6info.saddr,
691 a->u.net.sport,
692 "saddr", "src");
693 avc_print_ipv6_addr(ab, &a->u.net.v6info.daddr,
694 a->u.net.dport,
695 "daddr", "dest");
696 break;
697 }
698 if (a->u.net.netif)
699 audit_log_format(ab, " netif=%s",
700 a->u.net.netif);
701 break;
702 }
703 }
704 audit_log_format(ab, " ");
705 avc_dump_query(ab, ssid, tsid, tclass);
706 audit_log_end(ab);
707}
708
709/**
710 * avc_add_callback - Register a callback for security events.
711 * @callback: callback function
712 * @events: security events
713 * @ssid: source security identifier or %SECSID_WILD
714 * @tsid: target security identifier or %SECSID_WILD
715 * @tclass: target security class
716 * @perms: permissions
717 *
718 * Register a callback function for events in the set @events
719 * related to the SID pair (@ssid, @tsid) and
720 * and the permissions @perms, interpreting
721 * @perms based on @tclass. Returns %0 on success or
722 * -%ENOMEM if insufficient memory exists to add the callback.
723 */
724int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
725 u16 tclass, u32 perms,
726 u32 *out_retained),
727 u32 events, u32 ssid, u32 tsid,
728 u16 tclass, u32 perms)
729{
730 struct avc_callback_node *c;
731 int rc = 0;
732
733 c = kmalloc(sizeof(*c), GFP_ATOMIC);
734 if (!c) {
735 rc = -ENOMEM;
736 goto out;
737 }
738
739 c->callback = callback;
740 c->events = events;
741 c->ssid = ssid;
742 c->tsid = tsid;
743 c->perms = perms;
744 c->next = avc_callbacks;
745 avc_callbacks = c;
746out:
747 return rc;
748}
749
750static inline int avc_sidcmp(u32 x, u32 y)
751{
752 return (x == y || x == SECSID_WILD || y == SECSID_WILD);
753}
754
755/**
756 * avc_update_node Update an AVC entry
757 * @event : Updating event
758 * @perms : Permission mask bits
759 * @ssid,@tsid,@tclass : identifier of an AVC entry
760 *
761 * if a valid AVC entry doesn't exist,this function returns -ENOENT.
762 * if kmalloc() called internal returns NULL, this function returns -ENOMEM.
763 * otherwise, this function update the AVC entry. The original AVC-entry object
764 * will release later by RCU.
765 */
766static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass)
767{
768 int hvalue, rc = 0;
769 unsigned long flag;
770 struct avc_node *pos, *node, *orig = NULL;
771
772 node = avc_alloc_node();
773 if (!node) {
774 rc = -ENOMEM;
775 goto out;
776 }
777
778 /* Lock the target slot */
779 hvalue = avc_hash(ssid, tsid, tclass);
780 spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
781
782 list_for_each_entry(pos, &avc_cache.slots[hvalue], list){
783 if ( ssid==pos->ae.ssid &&
784 tsid==pos->ae.tsid &&
785 tclass==pos->ae.tclass ){
786 orig = pos;
787 break;
788 }
789 }
790
791 if (!orig) {
792 rc = -ENOENT;
793 avc_node_kill(node);
794 goto out_unlock;
795 }
796
797 /*
798 * Copy and replace original node.
799 */
800
801 avc_node_populate(node, ssid, tsid, tclass, &orig->ae);
802
803 switch (event) {
804 case AVC_CALLBACK_GRANT:
805 node->ae.avd.allowed |= perms;
806 break;
807 case AVC_CALLBACK_TRY_REVOKE:
808 case AVC_CALLBACK_REVOKE:
809 node->ae.avd.allowed &= ~perms;
810 break;
811 case AVC_CALLBACK_AUDITALLOW_ENABLE:
812 node->ae.avd.auditallow |= perms;
813 break;
814 case AVC_CALLBACK_AUDITALLOW_DISABLE:
815 node->ae.avd.auditallow &= ~perms;
816 break;
817 case AVC_CALLBACK_AUDITDENY_ENABLE:
818 node->ae.avd.auditdeny |= perms;
819 break;
820 case AVC_CALLBACK_AUDITDENY_DISABLE:
821 node->ae.avd.auditdeny &= ~perms;
822 break;
823 }
824 avc_node_replace(node, orig);
825out_unlock:
826 spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag);
827out:
828 return rc;
829}
830
831/**
832 * avc_ss_reset - Flush the cache and revalidate migrated permissions.
833 * @seqno: policy sequence number
834 */
835int avc_ss_reset(u32 seqno)
836{
837 struct avc_callback_node *c;
838 int i, rc = 0;
839 unsigned long flag;
840 struct avc_node *node;
841
842 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
843 spin_lock_irqsave(&avc_cache.slots_lock[i], flag);
844 list_for_each_entry(node, &avc_cache.slots[i], list)
845 avc_node_delete(node);
846 spin_unlock_irqrestore(&avc_cache.slots_lock[i], flag);
847 }
848
849 for (c = avc_callbacks; c; c = c->next) {
850 if (c->events & AVC_CALLBACK_RESET) {
851 rc = c->callback(AVC_CALLBACK_RESET,
852 0, 0, 0, 0, NULL);
853 if (rc)
854 goto out;
855 }
856 }
857
858 avc_latest_notif_update(seqno, 0);
859out:
860 return rc;
861}
862
863/**
864 * avc_has_perm_noaudit - Check permissions but perform no auditing.
865 * @ssid: source security identifier
866 * @tsid: target security identifier
867 * @tclass: target security class
868 * @requested: requested permissions, interpreted based on @tclass
869 * @avd: access vector decisions
870 *
871 * Check the AVC to determine whether the @requested permissions are granted
872 * for the SID pair (@ssid, @tsid), interpreting the permissions
873 * based on @tclass, and call the security server on a cache miss to obtain
874 * a new decision and add it to the cache. Return a copy of the decisions
875 * in @avd. Return %0 if all @requested permissions are granted,
876 * -%EACCES if any permissions are denied, or another -errno upon
877 * other errors. This function is typically called by avc_has_perm(),
878 * but may also be called directly to separate permission checking from
879 * auditing, e.g. in cases where a lock must be held for the check but
880 * should be released for the auditing.
881 */
882int avc_has_perm_noaudit(u32 ssid, u32 tsid,
883 u16 tclass, u32 requested,
884 struct av_decision *avd)
885{
886 struct avc_node *node;
887 struct avc_entry entry, *p_ae;
888 int rc = 0;
889 u32 denied;
890
891 rcu_read_lock();
892
893 node = avc_lookup(ssid, tsid, tclass, requested);
894 if (!node) {
895 rcu_read_unlock();
896 rc = security_compute_av(ssid,tsid,tclass,requested,&entry.avd);
897 if (rc)
898 goto out;
899 rcu_read_lock();
900 node = avc_insert(ssid,tsid,tclass,&entry);
901 }
902
903 p_ae = node ? &node->ae : &entry;
904
905 if (avd)
906 memcpy(avd, &p_ae->avd, sizeof(*avd));
907
908 denied = requested & ~(p_ae->avd.allowed);
909
910 if (!requested || denied) {
911 if (selinux_enforcing)
912 rc = -EACCES;
913 else
914 if (node)
915 avc_update_node(AVC_CALLBACK_GRANT,requested,
916 ssid,tsid,tclass);
917 }
918
919 rcu_read_unlock();
920out:
921 return rc;
922}
923
924/**
925 * avc_has_perm - Check permissions and perform any appropriate auditing.
926 * @ssid: source security identifier
927 * @tsid: target security identifier
928 * @tclass: target security class
929 * @requested: requested permissions, interpreted based on @tclass
930 * @auditdata: auxiliary audit data
931 *
932 * Check the AVC to determine whether the @requested permissions are granted
933 * for the SID pair (@ssid, @tsid), interpreting the permissions
934 * based on @tclass, and call the security server on a cache miss to obtain
935 * a new decision and add it to the cache. Audit the granting or denial of
936 * permissions in accordance with the policy. Return %0 if all @requested
937 * permissions are granted, -%EACCES if any permissions are denied, or
938 * another -errno upon other errors.
939 */
940int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
941 u32 requested, struct avc_audit_data *auditdata)
942{
943 struct av_decision avd;
944 int rc;
945
946 rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd);
947 avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
948 return rc;
949}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
new file mode 100644
index 00000000000..8a2cc75b394
--- /dev/null
+++ b/security/selinux/hooks.c
@@ -0,0 +1,4565 @@
1/*
2 * NSA Security-Enhanced Linux (SELinux) security module
3 *
4 * This file contains the SELinux hook function implementations.
5 *
6 * Authors: Stephen Smalley, <sds@epoch.ncsc.mil>
7 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
10 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
14 * <dgoeddel@trustedcs.com>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License version 2,
18 * as published by the Free Software Foundation.
19 */
20
21#include <linux/config.h>
22#include <linux/module.h>
23#include <linux/init.h>
24#include <linux/kernel.h>
25#include <linux/ptrace.h>
26#include <linux/errno.h>
27#include <linux/sched.h>
28#include <linux/security.h>
29#include <linux/xattr.h>
30#include <linux/capability.h>
31#include <linux/unistd.h>
32#include <linux/mm.h>
33#include <linux/mman.h>
34#include <linux/slab.h>
35#include <linux/pagemap.h>
36#include <linux/swap.h>
37#include <linux/smp_lock.h>
38#include <linux/spinlock.h>
39#include <linux/syscalls.h>
40#include <linux/file.h>
41#include <linux/namei.h>
42#include <linux/mount.h>
43#include <linux/ext2_fs.h>
44#include <linux/proc_fs.h>
45#include <linux/kd.h>
46#include <linux/netfilter_ipv4.h>
47#include <linux/netfilter_ipv6.h>
48#include <linux/tty.h>
49#include <net/icmp.h>
50#include <net/ip.h> /* for sysctl_local_port_range[] */
51#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
52#include <asm/uaccess.h>
53#include <asm/semaphore.h>
54#include <asm/ioctls.h>
55#include <linux/bitops.h>
56#include <linux/interrupt.h>
57#include <linux/netdevice.h> /* for network interface checks */
58#include <linux/netlink.h>
59#include <linux/tcp.h>
60#include <linux/udp.h>
61#include <linux/quota.h>
62#include <linux/un.h> /* for Unix socket types */
63#include <net/af_unix.h> /* for Unix socket types */
64#include <linux/parser.h>
65#include <linux/nfs_mount.h>
66#include <net/ipv6.h>
67#include <linux/hugetlb.h>
68#include <linux/personality.h>
69#include <linux/sysctl.h>
70#include <linux/audit.h>
71
72#include "avc.h"
73#include "objsec.h"
74#include "netif.h"
75
76#define XATTR_SELINUX_SUFFIX "selinux"
77#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
78
79extern unsigned int policydb_loaded_version;
80extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
81
82#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
83int selinux_enforcing = 0;
84
85static int __init enforcing_setup(char *str)
86{
87 selinux_enforcing = simple_strtol(str,NULL,0);
88 return 1;
89}
90__setup("enforcing=", enforcing_setup);
91#endif
92
93#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
94int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
95
96static int __init selinux_enabled_setup(char *str)
97{
98 selinux_enabled = simple_strtol(str, NULL, 0);
99 return 1;
100}
101__setup("selinux=", selinux_enabled_setup);
102#endif
103
104/* Original (dummy) security module. */
105static struct security_operations *original_ops = NULL;
106
107/* Minimal support for a secondary security module,
108 just to allow the use of the dummy or capability modules.
109 The owlsm module can alternatively be used as a secondary
110 module as long as CONFIG_OWLSM_FD is not enabled. */
111static struct security_operations *secondary_ops = NULL;
112
113/* Lists of inode and superblock security structures initialized
114 before the policy was loaded. */
115static LIST_HEAD(superblock_security_head);
116static DEFINE_SPINLOCK(sb_security_lock);
117
118/* Allocate and free functions for each kind of security blob. */
119
120static int task_alloc_security(struct task_struct *task)
121{
122 struct task_security_struct *tsec;
123
124 tsec = kmalloc(sizeof(struct task_security_struct), GFP_KERNEL);
125 if (!tsec)
126 return -ENOMEM;
127
128 memset(tsec, 0, sizeof(struct task_security_struct));
129 tsec->magic = SELINUX_MAGIC;
130 tsec->task = task;
131 tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED;
132 task->security = tsec;
133
134 return 0;
135}
136
137static void task_free_security(struct task_struct *task)
138{
139 struct task_security_struct *tsec = task->security;
140
141 if (!tsec || tsec->magic != SELINUX_MAGIC)
142 return;
143
144 task->security = NULL;
145 kfree(tsec);
146}
147
148static int inode_alloc_security(struct inode *inode)
149{
150 struct task_security_struct *tsec = current->security;
151 struct inode_security_struct *isec;
152
153 isec = kmalloc(sizeof(struct inode_security_struct), GFP_KERNEL);
154 if (!isec)
155 return -ENOMEM;
156
157 memset(isec, 0, sizeof(struct inode_security_struct));
158 init_MUTEX(&isec->sem);
159 INIT_LIST_HEAD(&isec->list);
160 isec->magic = SELINUX_MAGIC;
161 isec->inode = inode;
162 isec->sid = SECINITSID_UNLABELED;
163 isec->sclass = SECCLASS_FILE;
164 if (tsec && tsec->magic == SELINUX_MAGIC)
165 isec->task_sid = tsec->sid;
166 else
167 isec->task_sid = SECINITSID_UNLABELED;
168 inode->i_security = isec;
169
170 return 0;
171}
172
173static void inode_free_security(struct inode *inode)
174{
175 struct inode_security_struct *isec = inode->i_security;
176 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
177
178 if (!isec || isec->magic != SELINUX_MAGIC)
179 return;
180
181 spin_lock(&sbsec->isec_lock);
182 if (!list_empty(&isec->list))
183 list_del_init(&isec->list);
184 spin_unlock(&sbsec->isec_lock);
185
186 inode->i_security = NULL;
187 kfree(isec);
188}
189
190static int file_alloc_security(struct file *file)
191{
192 struct task_security_struct *tsec = current->security;
193 struct file_security_struct *fsec;
194
195 fsec = kmalloc(sizeof(struct file_security_struct), GFP_ATOMIC);
196 if (!fsec)
197 return -ENOMEM;
198
199 memset(fsec, 0, sizeof(struct file_security_struct));
200 fsec->magic = SELINUX_MAGIC;
201 fsec->file = file;
202 if (tsec && tsec->magic == SELINUX_MAGIC) {
203 fsec->sid = tsec->sid;
204 fsec->fown_sid = tsec->sid;
205 } else {
206 fsec->sid = SECINITSID_UNLABELED;
207 fsec->fown_sid = SECINITSID_UNLABELED;
208 }
209 file->f_security = fsec;
210
211 return 0;
212}
213
214static void file_free_security(struct file *file)
215{
216 struct file_security_struct *fsec = file->f_security;
217
218 if (!fsec || fsec->magic != SELINUX_MAGIC)
219 return;
220
221 file->f_security = NULL;
222 kfree(fsec);
223}
224
225static int superblock_alloc_security(struct super_block *sb)
226{
227 struct superblock_security_struct *sbsec;
228
229 sbsec = kmalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
230 if (!sbsec)
231 return -ENOMEM;
232
233 memset(sbsec, 0, sizeof(struct superblock_security_struct));
234 init_MUTEX(&sbsec->sem);
235 INIT_LIST_HEAD(&sbsec->list);
236 INIT_LIST_HEAD(&sbsec->isec_head);
237 spin_lock_init(&sbsec->isec_lock);
238 sbsec->magic = SELINUX_MAGIC;
239 sbsec->sb = sb;
240 sbsec->sid = SECINITSID_UNLABELED;
241 sbsec->def_sid = SECINITSID_FILE;
242 sb->s_security = sbsec;
243
244 return 0;
245}
246
247static void superblock_free_security(struct super_block *sb)
248{
249 struct superblock_security_struct *sbsec = sb->s_security;
250
251 if (!sbsec || sbsec->magic != SELINUX_MAGIC)
252 return;
253
254 spin_lock(&sb_security_lock);
255 if (!list_empty(&sbsec->list))
256 list_del_init(&sbsec->list);
257 spin_unlock(&sb_security_lock);
258
259 sb->s_security = NULL;
260 kfree(sbsec);
261}
262
263#ifdef CONFIG_SECURITY_NETWORK
264static int sk_alloc_security(struct sock *sk, int family, int priority)
265{
266 struct sk_security_struct *ssec;
267
268 if (family != PF_UNIX)
269 return 0;
270
271 ssec = kmalloc(sizeof(*ssec), priority);
272 if (!ssec)
273 return -ENOMEM;
274
275 memset(ssec, 0, sizeof(*ssec));
276 ssec->magic = SELINUX_MAGIC;
277 ssec->sk = sk;
278 ssec->peer_sid = SECINITSID_UNLABELED;
279 sk->sk_security = ssec;
280
281 return 0;
282}
283
284static void sk_free_security(struct sock *sk)
285{
286 struct sk_security_struct *ssec = sk->sk_security;
287
288 if (sk->sk_family != PF_UNIX || ssec->magic != SELINUX_MAGIC)
289 return;
290
291 sk->sk_security = NULL;
292 kfree(ssec);
293}
294#endif /* CONFIG_SECURITY_NETWORK */
295
296/* The security server must be initialized before
297 any labeling or access decisions can be provided. */
298extern int ss_initialized;
299
300/* The file system's label must be initialized prior to use. */
301
302static char *labeling_behaviors[6] = {
303 "uses xattr",
304 "uses transition SIDs",
305 "uses task SIDs",
306 "uses genfs_contexts",
307 "not configured for labeling",
308 "uses mountpoint labeling",
309};
310
311static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
312
313static inline int inode_doinit(struct inode *inode)
314{
315 return inode_doinit_with_dentry(inode, NULL);
316}
317
318enum {
319 Opt_context = 1,
320 Opt_fscontext = 2,
321 Opt_defcontext = 4,
322};
323
324static match_table_t tokens = {
325 {Opt_context, "context=%s"},
326 {Opt_fscontext, "fscontext=%s"},
327 {Opt_defcontext, "defcontext=%s"},
328};
329
330#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
331
332static int try_context_mount(struct super_block *sb, void *data)
333{
334 char *context = NULL, *defcontext = NULL;
335 const char *name;
336 u32 sid;
337 int alloc = 0, rc = 0, seen = 0;
338 struct task_security_struct *tsec = current->security;
339 struct superblock_security_struct *sbsec = sb->s_security;
340
341 if (!data)
342 goto out;
343
344 name = sb->s_type->name;
345
346 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {
347
348 /* NFS we understand. */
349 if (!strcmp(name, "nfs")) {
350 struct nfs_mount_data *d = data;
351
352 if (d->version < NFS_MOUNT_VERSION)
353 goto out;
354
355 if (d->context[0]) {
356 context = d->context;
357 seen |= Opt_context;
358 }
359 } else
360 goto out;
361
362 } else {
363 /* Standard string-based options. */
364 char *p, *options = data;
365
366 while ((p = strsep(&options, ",")) != NULL) {
367 int token;
368 substring_t args[MAX_OPT_ARGS];
369
370 if (!*p)
371 continue;
372
373 token = match_token(p, tokens, args);
374
375 switch (token) {
376 case Opt_context:
377 if (seen) {
378 rc = -EINVAL;
379 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
380 goto out_free;
381 }
382 context = match_strdup(&args[0]);
383 if (!context) {
384 rc = -ENOMEM;
385 goto out_free;
386 }
387 if (!alloc)
388 alloc = 1;
389 seen |= Opt_context;
390 break;
391
392 case Opt_fscontext:
393 if (seen & (Opt_context|Opt_fscontext)) {
394 rc = -EINVAL;
395 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
396 goto out_free;
397 }
398 context = match_strdup(&args[0]);
399 if (!context) {
400 rc = -ENOMEM;
401 goto out_free;
402 }
403 if (!alloc)
404 alloc = 1;
405 seen |= Opt_fscontext;
406 break;
407
408 case Opt_defcontext:
409 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
410 rc = -EINVAL;
411 printk(KERN_WARNING "SELinux: "
412 "defcontext option is invalid "
413 "for this filesystem type\n");
414 goto out_free;
415 }
416 if (seen & (Opt_context|Opt_defcontext)) {
417 rc = -EINVAL;
418 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
419 goto out_free;
420 }
421 defcontext = match_strdup(&args[0]);
422 if (!defcontext) {
423 rc = -ENOMEM;
424 goto out_free;
425 }
426 if (!alloc)
427 alloc = 1;
428 seen |= Opt_defcontext;
429 break;
430
431 default:
432 rc = -EINVAL;
433 printk(KERN_WARNING "SELinux: unknown mount "
434 "option\n");
435 goto out_free;
436
437 }
438 }
439 }
440
441 if (!seen)
442 goto out;
443
444 if (context) {
445 rc = security_context_to_sid(context, strlen(context), &sid);
446 if (rc) {
447 printk(KERN_WARNING "SELinux: security_context_to_sid"
448 "(%s) failed for (dev %s, type %s) errno=%d\n",
449 context, sb->s_id, name, rc);
450 goto out_free;
451 }
452
453 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
454 FILESYSTEM__RELABELFROM, NULL);
455 if (rc)
456 goto out_free;
457
458 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
459 FILESYSTEM__RELABELTO, NULL);
460 if (rc)
461 goto out_free;
462
463 sbsec->sid = sid;
464
465 if (seen & Opt_context)
466 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
467 }
468
469 if (defcontext) {
470 rc = security_context_to_sid(defcontext, strlen(defcontext), &sid);
471 if (rc) {
472 printk(KERN_WARNING "SELinux: security_context_to_sid"
473 "(%s) failed for (dev %s, type %s) errno=%d\n",
474 defcontext, sb->s_id, name, rc);
475 goto out_free;
476 }
477
478 if (sid == sbsec->def_sid)
479 goto out_free;
480
481 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
482 FILESYSTEM__RELABELFROM, NULL);
483 if (rc)
484 goto out_free;
485
486 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
487 FILESYSTEM__ASSOCIATE, NULL);
488 if (rc)
489 goto out_free;
490
491 sbsec->def_sid = sid;
492 }
493
494out_free:
495 if (alloc) {
496 kfree(context);
497 kfree(defcontext);
498 }
499out:
500 return rc;
501}
502
503static int superblock_doinit(struct super_block *sb, void *data)
504{
505 struct superblock_security_struct *sbsec = sb->s_security;
506 struct dentry *root = sb->s_root;
507 struct inode *inode = root->d_inode;
508 int rc = 0;
509
510 down(&sbsec->sem);
511 if (sbsec->initialized)
512 goto out;
513
514 if (!ss_initialized) {
515 /* Defer initialization until selinux_complete_init,
516 after the initial policy is loaded and the security
517 server is ready to handle calls. */
518 spin_lock(&sb_security_lock);
519 if (list_empty(&sbsec->list))
520 list_add(&sbsec->list, &superblock_security_head);
521 spin_unlock(&sb_security_lock);
522 goto out;
523 }
524
525 /* Determine the labeling behavior to use for this filesystem type. */
526 rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
527 if (rc) {
528 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
529 __FUNCTION__, sb->s_type->name, rc);
530 goto out;
531 }
532
533 rc = try_context_mount(sb, data);
534 if (rc)
535 goto out;
536
537 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
538 /* Make sure that the xattr handler exists and that no
539 error other than -ENODATA is returned by getxattr on
540 the root directory. -ENODATA is ok, as this may be
541 the first boot of the SELinux kernel before we have
542 assigned xattr values to the filesystem. */
543 if (!inode->i_op->getxattr) {
544 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
545 "xattr support\n", sb->s_id, sb->s_type->name);
546 rc = -EOPNOTSUPP;
547 goto out;
548 }
549 rc = inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
550 if (rc < 0 && rc != -ENODATA) {
551 if (rc == -EOPNOTSUPP)
552 printk(KERN_WARNING "SELinux: (dev %s, type "
553 "%s) has no security xattr handler\n",
554 sb->s_id, sb->s_type->name);
555 else
556 printk(KERN_WARNING "SELinux: (dev %s, type "
557 "%s) getxattr errno %d\n", sb->s_id,
558 sb->s_type->name, -rc);
559 goto out;
560 }
561 }
562
563 if (strcmp(sb->s_type->name, "proc") == 0)
564 sbsec->proc = 1;
565
566 sbsec->initialized = 1;
567
568 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) {
569 printk(KERN_INFO "SELinux: initialized (dev %s, type %s), unknown behavior\n",
570 sb->s_id, sb->s_type->name);
571 }
572 else {
573 printk(KERN_INFO "SELinux: initialized (dev %s, type %s), %s\n",
574 sb->s_id, sb->s_type->name,
575 labeling_behaviors[sbsec->behavior-1]);
576 }
577
578 /* Initialize the root inode. */
579 rc = inode_doinit_with_dentry(sb->s_root->d_inode, sb->s_root);
580
581 /* Initialize any other inodes associated with the superblock, e.g.
582 inodes created prior to initial policy load or inodes created
583 during get_sb by a pseudo filesystem that directly
584 populates itself. */
585 spin_lock(&sbsec->isec_lock);
586next_inode:
587 if (!list_empty(&sbsec->isec_head)) {
588 struct inode_security_struct *isec =
589 list_entry(sbsec->isec_head.next,
590 struct inode_security_struct, list);
591 struct inode *inode = isec->inode;
592 spin_unlock(&sbsec->isec_lock);
593 inode = igrab(inode);
594 if (inode) {
595 if (!IS_PRIVATE (inode))
596 inode_doinit(inode);
597 iput(inode);
598 }
599 spin_lock(&sbsec->isec_lock);
600 list_del_init(&isec->list);
601 goto next_inode;
602 }
603 spin_unlock(&sbsec->isec_lock);
604out:
605 up(&sbsec->sem);
606 return rc;
607}
608
609static inline u16 inode_mode_to_security_class(umode_t mode)
610{
611 switch (mode & S_IFMT) {
612 case S_IFSOCK:
613 return SECCLASS_SOCK_FILE;
614 case S_IFLNK:
615 return SECCLASS_LNK_FILE;
616 case S_IFREG:
617 return SECCLASS_FILE;
618 case S_IFBLK:
619 return SECCLASS_BLK_FILE;
620 case S_IFDIR:
621 return SECCLASS_DIR;
622 case S_IFCHR:
623 return SECCLASS_CHR_FILE;
624 case S_IFIFO:
625 return SECCLASS_FIFO_FILE;
626
627 }
628
629 return SECCLASS_FILE;
630}
631
632static inline u16 socket_type_to_security_class(int family, int type, int protocol)
633{
634 switch (family) {
635 case PF_UNIX:
636 switch (type) {
637 case SOCK_STREAM:
638 case SOCK_SEQPACKET:
639 return SECCLASS_UNIX_STREAM_SOCKET;
640 case SOCK_DGRAM:
641 return SECCLASS_UNIX_DGRAM_SOCKET;
642 }
643 break;
644 case PF_INET:
645 case PF_INET6:
646 switch (type) {
647 case SOCK_STREAM:
648 return SECCLASS_TCP_SOCKET;
649 case SOCK_DGRAM:
650 return SECCLASS_UDP_SOCKET;
651 case SOCK_RAW:
652 return SECCLASS_RAWIP_SOCKET;
653 }
654 break;
655 case PF_NETLINK:
656 switch (protocol) {
657 case NETLINK_ROUTE:
658 return SECCLASS_NETLINK_ROUTE_SOCKET;
659 case NETLINK_FIREWALL:
660 return SECCLASS_NETLINK_FIREWALL_SOCKET;
661 case NETLINK_TCPDIAG:
662 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
663 case NETLINK_NFLOG:
664 return SECCLASS_NETLINK_NFLOG_SOCKET;
665 case NETLINK_XFRM:
666 return SECCLASS_NETLINK_XFRM_SOCKET;
667 case NETLINK_SELINUX:
668 return SECCLASS_NETLINK_SELINUX_SOCKET;
669 case NETLINK_AUDIT:
670 return SECCLASS_NETLINK_AUDIT_SOCKET;
671 case NETLINK_IP6_FW:
672 return SECCLASS_NETLINK_IP6FW_SOCKET;
673 case NETLINK_DNRTMSG:
674 return SECCLASS_NETLINK_DNRT_SOCKET;
675 default:
676 return SECCLASS_NETLINK_SOCKET;
677 }
678 case PF_PACKET:
679 return SECCLASS_PACKET_SOCKET;
680 case PF_KEY:
681 return SECCLASS_KEY_SOCKET;
682 }
683
684 return SECCLASS_SOCKET;
685}
686
687#ifdef CONFIG_PROC_FS
688static int selinux_proc_get_sid(struct proc_dir_entry *de,
689 u16 tclass,
690 u32 *sid)
691{
692 int buflen, rc;
693 char *buffer, *path, *end;
694
695 buffer = (char*)__get_free_page(GFP_KERNEL);
696 if (!buffer)
697 return -ENOMEM;
698
699 buflen = PAGE_SIZE;
700 end = buffer+buflen;
701 *--end = '\0';
702 buflen--;
703 path = end-1;
704 *path = '/';
705 while (de && de != de->parent) {
706 buflen -= de->namelen + 1;
707 if (buflen < 0)
708 break;
709 end -= de->namelen;
710 memcpy(end, de->name, de->namelen);
711 *--end = '/';
712 path = end;
713 de = de->parent;
714 }
715 rc = security_genfs_sid("proc", path, tclass, sid);
716 free_page((unsigned long)buffer);
717 return rc;
718}
719#else
720static int selinux_proc_get_sid(struct proc_dir_entry *de,
721 u16 tclass,
722 u32 *sid)
723{
724 return -EINVAL;
725}
726#endif
727
728/* The inode's security attributes must be initialized before first use. */
729static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
730{
731 struct superblock_security_struct *sbsec = NULL;
732 struct inode_security_struct *isec = inode->i_security;
733 u32 sid;
734 struct dentry *dentry;
735#define INITCONTEXTLEN 255
736 char *context = NULL;
737 unsigned len = 0;
738 int rc = 0;
739 int hold_sem = 0;
740
741 if (isec->initialized)
742 goto out;
743
744 down(&isec->sem);
745 hold_sem = 1;
746 if (isec->initialized)
747 goto out;
748
749 sbsec = inode->i_sb->s_security;
750 if (!sbsec->initialized) {
751 /* Defer initialization until selinux_complete_init,
752 after the initial policy is loaded and the security
753 server is ready to handle calls. */
754 spin_lock(&sbsec->isec_lock);
755 if (list_empty(&isec->list))
756 list_add(&isec->list, &sbsec->isec_head);
757 spin_unlock(&sbsec->isec_lock);
758 goto out;
759 }
760
761 switch (sbsec->behavior) {
762 case SECURITY_FS_USE_XATTR:
763 if (!inode->i_op->getxattr) {
764 isec->sid = sbsec->def_sid;
765 break;
766 }
767
768 /* Need a dentry, since the xattr API requires one.
769 Life would be simpler if we could just pass the inode. */
770 if (opt_dentry) {
771 /* Called from d_instantiate or d_splice_alias. */
772 dentry = dget(opt_dentry);
773 } else {
774 /* Called from selinux_complete_init, try to find a dentry. */
775 dentry = d_find_alias(inode);
776 }
777 if (!dentry) {
778 printk(KERN_WARNING "%s: no dentry for dev=%s "
779 "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id,
780 inode->i_ino);
781 goto out;
782 }
783
784 len = INITCONTEXTLEN;
785 context = kmalloc(len, GFP_KERNEL);
786 if (!context) {
787 rc = -ENOMEM;
788 dput(dentry);
789 goto out;
790 }
791 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
792 context, len);
793 if (rc == -ERANGE) {
794 /* Need a larger buffer. Query for the right size. */
795 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
796 NULL, 0);
797 if (rc < 0) {
798 dput(dentry);
799 goto out;
800 }
801 kfree(context);
802 len = rc;
803 context = kmalloc(len, GFP_KERNEL);
804 if (!context) {
805 rc = -ENOMEM;
806 dput(dentry);
807 goto out;
808 }
809 rc = inode->i_op->getxattr(dentry,
810 XATTR_NAME_SELINUX,
811 context, len);
812 }
813 dput(dentry);
814 if (rc < 0) {
815 if (rc != -ENODATA) {
816 printk(KERN_WARNING "%s: getxattr returned "
817 "%d for dev=%s ino=%ld\n", __FUNCTION__,
818 -rc, inode->i_sb->s_id, inode->i_ino);
819 kfree(context);
820 goto out;
821 }
822 /* Map ENODATA to the default file SID */
823 sid = sbsec->def_sid;
824 rc = 0;
825 } else {
826 rc = security_context_to_sid(context, rc, &sid);
827 if (rc) {
828 printk(KERN_WARNING "%s: context_to_sid(%s) "
829 "returned %d for dev=%s ino=%ld\n",
830 __FUNCTION__, context, -rc,
831 inode->i_sb->s_id, inode->i_ino);
832 kfree(context);
833 /* Leave with the unlabeled SID */
834 rc = 0;
835 break;
836 }
837 }
838 kfree(context);
839 isec->sid = sid;
840 break;
841 case SECURITY_FS_USE_TASK:
842 isec->sid = isec->task_sid;
843 break;
844 case SECURITY_FS_USE_TRANS:
845 /* Default to the fs SID. */
846 isec->sid = sbsec->sid;
847
848 /* Try to obtain a transition SID. */
849 isec->sclass = inode_mode_to_security_class(inode->i_mode);
850 rc = security_transition_sid(isec->task_sid,
851 sbsec->sid,
852 isec->sclass,
853 &sid);
854 if (rc)
855 goto out;
856 isec->sid = sid;
857 break;
858 default:
859 /* Default to the fs SID. */
860 isec->sid = sbsec->sid;
861
862 if (sbsec->proc) {
863 struct proc_inode *proci = PROC_I(inode);
864 if (proci->pde) {
865 isec->sclass = inode_mode_to_security_class(inode->i_mode);
866 rc = selinux_proc_get_sid(proci->pde,
867 isec->sclass,
868 &sid);
869 if (rc)
870 goto out;
871 isec->sid = sid;
872 }
873 }
874 break;
875 }
876
877 isec->initialized = 1;
878
879out:
880 if (isec->sclass == SECCLASS_FILE)
881 isec->sclass = inode_mode_to_security_class(inode->i_mode);
882
883 if (hold_sem)
884 up(&isec->sem);
885 return rc;
886}
887
888/* Convert a Linux signal to an access vector. */
889static inline u32 signal_to_av(int sig)
890{
891 u32 perm = 0;
892
893 switch (sig) {
894 case SIGCHLD:
895 /* Commonly granted from child to parent. */
896 perm = PROCESS__SIGCHLD;
897 break;
898 case SIGKILL:
899 /* Cannot be caught or ignored */
900 perm = PROCESS__SIGKILL;
901 break;
902 case SIGSTOP:
903 /* Cannot be caught or ignored */
904 perm = PROCESS__SIGSTOP;
905 break;
906 default:
907 /* All other signals. */
908 perm = PROCESS__SIGNAL;
909 break;
910 }
911
912 return perm;
913}
914
915/* Check permission betweeen a pair of tasks, e.g. signal checks,
916 fork check, ptrace check, etc. */
917static int task_has_perm(struct task_struct *tsk1,
918 struct task_struct *tsk2,
919 u32 perms)
920{
921 struct task_security_struct *tsec1, *tsec2;
922
923 tsec1 = tsk1->security;
924 tsec2 = tsk2->security;
925 return avc_has_perm(tsec1->sid, tsec2->sid,
926 SECCLASS_PROCESS, perms, NULL);
927}
928
929/* Check whether a task is allowed to use a capability. */
930static int task_has_capability(struct task_struct *tsk,
931 int cap)
932{
933 struct task_security_struct *tsec;
934 struct avc_audit_data ad;
935
936 tsec = tsk->security;
937
938 AVC_AUDIT_DATA_INIT(&ad,CAP);
939 ad.tsk = tsk;
940 ad.u.cap = cap;
941
942 return avc_has_perm(tsec->sid, tsec->sid,
943 SECCLASS_CAPABILITY, CAP_TO_MASK(cap), &ad);
944}
945
946/* Check whether a task is allowed to use a system operation. */
947static int task_has_system(struct task_struct *tsk,
948 u32 perms)
949{
950 struct task_security_struct *tsec;
951
952 tsec = tsk->security;
953
954 return avc_has_perm(tsec->sid, SECINITSID_KERNEL,
955 SECCLASS_SYSTEM, perms, NULL);
956}
957
958/* Check whether a task has a particular permission to an inode.
959 The 'adp' parameter is optional and allows other audit
960 data to be passed (e.g. the dentry). */
961static int inode_has_perm(struct task_struct *tsk,
962 struct inode *inode,
963 u32 perms,
964 struct avc_audit_data *adp)
965{
966 struct task_security_struct *tsec;
967 struct inode_security_struct *isec;
968 struct avc_audit_data ad;
969
970 tsec = tsk->security;
971 isec = inode->i_security;
972
973 if (!adp) {
974 adp = &ad;
975 AVC_AUDIT_DATA_INIT(&ad, FS);
976 ad.u.fs.inode = inode;
977 }
978
979 return avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, adp);
980}
981
982/* Same as inode_has_perm, but pass explicit audit data containing
983 the dentry to help the auditing code to more easily generate the
984 pathname if needed. */
985static inline int dentry_has_perm(struct task_struct *tsk,
986 struct vfsmount *mnt,
987 struct dentry *dentry,
988 u32 av)
989{
990 struct inode *inode = dentry->d_inode;
991 struct avc_audit_data ad;
992 AVC_AUDIT_DATA_INIT(&ad,FS);
993 ad.u.fs.mnt = mnt;
994 ad.u.fs.dentry = dentry;
995 return inode_has_perm(tsk, inode, av, &ad);
996}
997
998/* Check whether a task can use an open file descriptor to
999 access an inode in a given way. Check access to the
1000 descriptor itself, and then use dentry_has_perm to
1001 check a particular permission to the file.
1002 Access to the descriptor is implicitly granted if it
1003 has the same SID as the process. If av is zero, then
1004 access to the file is not checked, e.g. for cases
1005 where only the descriptor is affected like seek. */
1006static inline int file_has_perm(struct task_struct *tsk,
1007 struct file *file,
1008 u32 av)
1009{
1010 struct task_security_struct *tsec = tsk->security;
1011 struct file_security_struct *fsec = file->f_security;
1012 struct vfsmount *mnt = file->f_vfsmnt;
1013 struct dentry *dentry = file->f_dentry;
1014 struct inode *inode = dentry->d_inode;
1015 struct avc_audit_data ad;
1016 int rc;
1017
1018 AVC_AUDIT_DATA_INIT(&ad, FS);
1019 ad.u.fs.mnt = mnt;
1020 ad.u.fs.dentry = dentry;
1021
1022 if (tsec->sid != fsec->sid) {
1023 rc = avc_has_perm(tsec->sid, fsec->sid,
1024 SECCLASS_FD,
1025 FD__USE,
1026 &ad);
1027 if (rc)
1028 return rc;
1029 }
1030
1031 /* av is zero if only checking access to the descriptor. */
1032 if (av)
1033 return inode_has_perm(tsk, inode, av, &ad);
1034
1035 return 0;
1036}
1037
1038/* Check whether a task can create a file. */
1039static int may_create(struct inode *dir,
1040 struct dentry *dentry,
1041 u16 tclass)
1042{
1043 struct task_security_struct *tsec;
1044 struct inode_security_struct *dsec;
1045 struct superblock_security_struct *sbsec;
1046 u32 newsid;
1047 struct avc_audit_data ad;
1048 int rc;
1049
1050 tsec = current->security;
1051 dsec = dir->i_security;
1052 sbsec = dir->i_sb->s_security;
1053
1054 AVC_AUDIT_DATA_INIT(&ad, FS);
1055 ad.u.fs.dentry = dentry;
1056
1057 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR,
1058 DIR__ADD_NAME | DIR__SEARCH,
1059 &ad);
1060 if (rc)
1061 return rc;
1062
1063 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1064 newsid = tsec->create_sid;
1065 } else {
1066 rc = security_transition_sid(tsec->sid, dsec->sid, tclass,
1067 &newsid);
1068 if (rc)
1069 return rc;
1070 }
1071
1072 rc = avc_has_perm(tsec->sid, newsid, tclass, FILE__CREATE, &ad);
1073 if (rc)
1074 return rc;
1075
1076 return avc_has_perm(newsid, sbsec->sid,
1077 SECCLASS_FILESYSTEM,
1078 FILESYSTEM__ASSOCIATE, &ad);
1079}
1080
1081#define MAY_LINK 0
1082#define MAY_UNLINK 1
1083#define MAY_RMDIR 2
1084
1085/* Check whether a task can link, unlink, or rmdir a file/directory. */
1086static int may_link(struct inode *dir,
1087 struct dentry *dentry,
1088 int kind)
1089
1090{
1091 struct task_security_struct *tsec;
1092 struct inode_security_struct *dsec, *isec;
1093 struct avc_audit_data ad;
1094 u32 av;
1095 int rc;
1096
1097 tsec = current->security;
1098 dsec = dir->i_security;
1099 isec = dentry->d_inode->i_security;
1100
1101 AVC_AUDIT_DATA_INIT(&ad, FS);
1102 ad.u.fs.dentry = dentry;
1103
1104 av = DIR__SEARCH;
1105 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
1106 rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, av, &ad);
1107 if (rc)
1108 return rc;
1109
1110 switch (kind) {
1111 case MAY_LINK:
1112 av = FILE__LINK;
1113 break;
1114 case MAY_UNLINK:
1115 av = FILE__UNLINK;
1116 break;
1117 case MAY_RMDIR:
1118 av = DIR__RMDIR;
1119 break;
1120 default:
1121 printk(KERN_WARNING "may_link: unrecognized kind %d\n", kind);
1122 return 0;
1123 }
1124
1125 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, av, &ad);
1126 return rc;
1127}
1128
1129static inline int may_rename(struct inode *old_dir,
1130 struct dentry *old_dentry,
1131 struct inode *new_dir,
1132 struct dentry *new_dentry)
1133{
1134 struct task_security_struct *tsec;
1135 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
1136 struct avc_audit_data ad;
1137 u32 av;
1138 int old_is_dir, new_is_dir;
1139 int rc;
1140
1141 tsec = current->security;
1142 old_dsec = old_dir->i_security;
1143 old_isec = old_dentry->d_inode->i_security;
1144 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1145 new_dsec = new_dir->i_security;
1146
1147 AVC_AUDIT_DATA_INIT(&ad, FS);
1148
1149 ad.u.fs.dentry = old_dentry;
1150 rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR,
1151 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1152 if (rc)
1153 return rc;
1154 rc = avc_has_perm(tsec->sid, old_isec->sid,
1155 old_isec->sclass, FILE__RENAME, &ad);
1156 if (rc)
1157 return rc;
1158 if (old_is_dir && new_dir != old_dir) {
1159 rc = avc_has_perm(tsec->sid, old_isec->sid,
1160 old_isec->sclass, DIR__REPARENT, &ad);
1161 if (rc)
1162 return rc;
1163 }
1164
1165 ad.u.fs.dentry = new_dentry;
1166 av = DIR__ADD_NAME | DIR__SEARCH;
1167 if (new_dentry->d_inode)
1168 av |= DIR__REMOVE_NAME;
1169 rc = avc_has_perm(tsec->sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
1170 if (rc)
1171 return rc;
1172 if (new_dentry->d_inode) {
1173 new_isec = new_dentry->d_inode->i_security;
1174 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
1175 rc = avc_has_perm(tsec->sid, new_isec->sid,
1176 new_isec->sclass,
1177 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1178 if (rc)
1179 return rc;
1180 }
1181
1182 return 0;
1183}
1184
1185/* Check whether a task can perform a filesystem operation. */
1186static int superblock_has_perm(struct task_struct *tsk,
1187 struct super_block *sb,
1188 u32 perms,
1189 struct avc_audit_data *ad)
1190{
1191 struct task_security_struct *tsec;
1192 struct superblock_security_struct *sbsec;
1193
1194 tsec = tsk->security;
1195 sbsec = sb->s_security;
1196 return avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
1197 perms, ad);
1198}
1199
1200/* Convert a Linux mode and permission mask to an access vector. */
1201static inline u32 file_mask_to_av(int mode, int mask)
1202{
1203 u32 av = 0;
1204
1205 if ((mode & S_IFMT) != S_IFDIR) {
1206 if (mask & MAY_EXEC)
1207 av |= FILE__EXECUTE;
1208 if (mask & MAY_READ)
1209 av |= FILE__READ;
1210
1211 if (mask & MAY_APPEND)
1212 av |= FILE__APPEND;
1213 else if (mask & MAY_WRITE)
1214 av |= FILE__WRITE;
1215
1216 } else {
1217 if (mask & MAY_EXEC)
1218 av |= DIR__SEARCH;
1219 if (mask & MAY_WRITE)
1220 av |= DIR__WRITE;
1221 if (mask & MAY_READ)
1222 av |= DIR__READ;
1223 }
1224
1225 return av;
1226}
1227
1228/* Convert a Linux file to an access vector. */
1229static inline u32 file_to_av(struct file *file)
1230{
1231 u32 av = 0;
1232
1233 if (file->f_mode & FMODE_READ)
1234 av |= FILE__READ;
1235 if (file->f_mode & FMODE_WRITE) {
1236 if (file->f_flags & O_APPEND)
1237 av |= FILE__APPEND;
1238 else
1239 av |= FILE__WRITE;
1240 }
1241
1242 return av;
1243}
1244
1245/* Set an inode's SID to a specified value. */
1246static int inode_security_set_sid(struct inode *inode, u32 sid)
1247{
1248 struct inode_security_struct *isec = inode->i_security;
1249 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
1250
1251 if (!sbsec->initialized) {
1252 /* Defer initialization to selinux_complete_init. */
1253 return 0;
1254 }
1255
1256 down(&isec->sem);
1257 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1258 isec->sid = sid;
1259 isec->initialized = 1;
1260 up(&isec->sem);
1261 return 0;
1262}
1263
1264/* Set the security attributes on a newly created file. */
1265static int post_create(struct inode *dir,
1266 struct dentry *dentry)
1267{
1268
1269 struct task_security_struct *tsec;
1270 struct inode *inode;
1271 struct inode_security_struct *dsec;
1272 struct superblock_security_struct *sbsec;
1273 u32 newsid;
1274 char *context;
1275 unsigned int len;
1276 int rc;
1277
1278 tsec = current->security;
1279 dsec = dir->i_security;
1280 sbsec = dir->i_sb->s_security;
1281
1282 inode = dentry->d_inode;
1283 if (!inode) {
1284 /* Some file system types (e.g. NFS) may not instantiate
1285 a dentry for all create operations (e.g. symlink),
1286 so we have to check to see if the inode is non-NULL. */
1287 printk(KERN_WARNING "post_create: no inode, dir (dev=%s, "
1288 "ino=%ld)\n", dir->i_sb->s_id, dir->i_ino);
1289 return 0;
1290 }
1291
1292 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1293 newsid = tsec->create_sid;
1294 } else {
1295 rc = security_transition_sid(tsec->sid, dsec->sid,
1296 inode_mode_to_security_class(inode->i_mode),
1297 &newsid);
1298 if (rc) {
1299 printk(KERN_WARNING "post_create: "
1300 "security_transition_sid failed, rc=%d (dev=%s "
1301 "ino=%ld)\n",
1302 -rc, inode->i_sb->s_id, inode->i_ino);
1303 return rc;
1304 }
1305 }
1306
1307 rc = inode_security_set_sid(inode, newsid);
1308 if (rc) {
1309 printk(KERN_WARNING "post_create: inode_security_set_sid "
1310 "failed, rc=%d (dev=%s ino=%ld)\n",
1311 -rc, inode->i_sb->s_id, inode->i_ino);
1312 return rc;
1313 }
1314
1315 if (sbsec->behavior == SECURITY_FS_USE_XATTR &&
1316 inode->i_op->setxattr) {
1317 /* Use extended attributes. */
1318 rc = security_sid_to_context(newsid, &context, &len);
1319 if (rc) {
1320 printk(KERN_WARNING "post_create: sid_to_context "
1321 "failed, rc=%d (dev=%s ino=%ld)\n",
1322 -rc, inode->i_sb->s_id, inode->i_ino);
1323 return rc;
1324 }
1325 down(&inode->i_sem);
1326 rc = inode->i_op->setxattr(dentry,
1327 XATTR_NAME_SELINUX,
1328 context, len, 0);
1329 up(&inode->i_sem);
1330 kfree(context);
1331 if (rc < 0) {
1332 printk(KERN_WARNING "post_create: setxattr failed, "
1333 "rc=%d (dev=%s ino=%ld)\n",
1334 -rc, inode->i_sb->s_id, inode->i_ino);
1335 return rc;
1336 }
1337 }
1338
1339 return 0;
1340}
1341
1342
1343/* Hook functions begin here. */
1344
1345static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
1346{
1347 struct task_security_struct *psec = parent->security;
1348 struct task_security_struct *csec = child->security;
1349 int rc;
1350
1351 rc = secondary_ops->ptrace(parent,child);
1352 if (rc)
1353 return rc;
1354
1355 rc = task_has_perm(parent, child, PROCESS__PTRACE);
1356 /* Save the SID of the tracing process for later use in apply_creds. */
1357 if (!rc)
1358 csec->ptrace_sid = psec->sid;
1359 return rc;
1360}
1361
1362static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
1363 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1364{
1365 int error;
1366
1367 error = task_has_perm(current, target, PROCESS__GETCAP);
1368 if (error)
1369 return error;
1370
1371 return secondary_ops->capget(target, effective, inheritable, permitted);
1372}
1373
1374static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
1375 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1376{
1377 int error;
1378
1379 error = secondary_ops->capset_check(target, effective, inheritable, permitted);
1380 if (error)
1381 return error;
1382
1383 return task_has_perm(current, target, PROCESS__SETCAP);
1384}
1385
1386static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
1387 kernel_cap_t *inheritable, kernel_cap_t *permitted)
1388{
1389 secondary_ops->capset_set(target, effective, inheritable, permitted);
1390}
1391
1392static int selinux_capable(struct task_struct *tsk, int cap)
1393{
1394 int rc;
1395
1396 rc = secondary_ops->capable(tsk, cap);
1397 if (rc)
1398 return rc;
1399
1400 return task_has_capability(tsk,cap);
1401}
1402
1403static int selinux_sysctl(ctl_table *table, int op)
1404{
1405 int error = 0;
1406 u32 av;
1407 struct task_security_struct *tsec;
1408 u32 tsid;
1409 int rc;
1410
1411 rc = secondary_ops->sysctl(table, op);
1412 if (rc)
1413 return rc;
1414
1415 tsec = current->security;
1416
1417 rc = selinux_proc_get_sid(table->de, (op == 001) ?
1418 SECCLASS_DIR : SECCLASS_FILE, &tsid);
1419 if (rc) {
1420 /* Default to the well-defined sysctl SID. */
1421 tsid = SECINITSID_SYSCTL;
1422 }
1423
1424 /* The op values are "defined" in sysctl.c, thereby creating
1425 * a bad coupling between this module and sysctl.c */
1426 if(op == 001) {
1427 error = avc_has_perm(tsec->sid, tsid,
1428 SECCLASS_DIR, DIR__SEARCH, NULL);
1429 } else {
1430 av = 0;
1431 if (op & 004)
1432 av |= FILE__READ;
1433 if (op & 002)
1434 av |= FILE__WRITE;
1435 if (av)
1436 error = avc_has_perm(tsec->sid, tsid,
1437 SECCLASS_FILE, av, NULL);
1438 }
1439
1440 return error;
1441}
1442
1443static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1444{
1445 int rc = 0;
1446
1447 if (!sb)
1448 return 0;
1449
1450 switch (cmds) {
1451 case Q_SYNC:
1452 case Q_QUOTAON:
1453 case Q_QUOTAOFF:
1454 case Q_SETINFO:
1455 case Q_SETQUOTA:
1456 rc = superblock_has_perm(current,
1457 sb,
1458 FILESYSTEM__QUOTAMOD, NULL);
1459 break;
1460 case Q_GETFMT:
1461 case Q_GETINFO:
1462 case Q_GETQUOTA:
1463 rc = superblock_has_perm(current,
1464 sb,
1465 FILESYSTEM__QUOTAGET, NULL);
1466 break;
1467 default:
1468 rc = 0; /* let the kernel handle invalid cmds */
1469 break;
1470 }
1471 return rc;
1472}
1473
1474static int selinux_quota_on(struct dentry *dentry)
1475{
1476 return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
1477}
1478
1479static int selinux_syslog(int type)
1480{
1481 int rc;
1482
1483 rc = secondary_ops->syslog(type);
1484 if (rc)
1485 return rc;
1486
1487 switch (type) {
1488 case 3: /* Read last kernel messages */
1489 case 10: /* Return size of the log buffer */
1490 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1491 break;
1492 case 6: /* Disable logging to console */
1493 case 7: /* Enable logging to console */
1494 case 8: /* Set level of messages printed to console */
1495 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1496 break;
1497 case 0: /* Close log */
1498 case 1: /* Open log */
1499 case 2: /* Read from log */
1500 case 4: /* Read/clear last kernel messages */
1501 case 5: /* Clear ring buffer */
1502 default:
1503 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1504 break;
1505 }
1506 return rc;
1507}
1508
1509/*
1510 * Check that a process has enough memory to allocate a new virtual
1511 * mapping. 0 means there is enough memory for the allocation to
1512 * succeed and -ENOMEM implies there is not.
1513 *
1514 * Note that secondary_ops->capable and task_has_perm_noaudit return 0
1515 * if the capability is granted, but __vm_enough_memory requires 1 if
1516 * the capability is granted.
1517 *
1518 * Do not audit the selinux permission check, as this is applied to all
1519 * processes that allocate mappings.
1520 */
1521static int selinux_vm_enough_memory(long pages)
1522{
1523 int rc, cap_sys_admin = 0;
1524 struct task_security_struct *tsec = current->security;
1525
1526 rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
1527 if (rc == 0)
1528 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
1529 SECCLASS_CAPABILITY,
1530 CAP_TO_MASK(CAP_SYS_ADMIN),
1531 NULL);
1532
1533 if (rc == 0)
1534 cap_sys_admin = 1;
1535
1536 return __vm_enough_memory(pages, cap_sys_admin);
1537}
1538
1539/* binprm security operations */
1540
1541static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
1542{
1543 struct bprm_security_struct *bsec;
1544
1545 bsec = kmalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
1546 if (!bsec)
1547 return -ENOMEM;
1548
1549 memset(bsec, 0, sizeof *bsec);
1550 bsec->magic = SELINUX_MAGIC;
1551 bsec->bprm = bprm;
1552 bsec->sid = SECINITSID_UNLABELED;
1553 bsec->set = 0;
1554
1555 bprm->security = bsec;
1556 return 0;
1557}
1558
1559static int selinux_bprm_set_security(struct linux_binprm *bprm)
1560{
1561 struct task_security_struct *tsec;
1562 struct inode *inode = bprm->file->f_dentry->d_inode;
1563 struct inode_security_struct *isec;
1564 struct bprm_security_struct *bsec;
1565 u32 newsid;
1566 struct avc_audit_data ad;
1567 int rc;
1568
1569 rc = secondary_ops->bprm_set_security(bprm);
1570 if (rc)
1571 return rc;
1572
1573 bsec = bprm->security;
1574
1575 if (bsec->set)
1576 return 0;
1577
1578 tsec = current->security;
1579 isec = inode->i_security;
1580
1581 /* Default to the current task SID. */
1582 bsec->sid = tsec->sid;
1583
1584 /* Reset create SID on execve. */
1585 tsec->create_sid = 0;
1586
1587 if (tsec->exec_sid) {
1588 newsid = tsec->exec_sid;
1589 /* Reset exec SID on execve. */
1590 tsec->exec_sid = 0;
1591 } else {
1592 /* Check for a default transition on this program. */
1593 rc = security_transition_sid(tsec->sid, isec->sid,
1594 SECCLASS_PROCESS, &newsid);
1595 if (rc)
1596 return rc;
1597 }
1598
1599 AVC_AUDIT_DATA_INIT(&ad, FS);
1600 ad.u.fs.mnt = bprm->file->f_vfsmnt;
1601 ad.u.fs.dentry = bprm->file->f_dentry;
1602
1603 if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)
1604 newsid = tsec->sid;
1605
1606 if (tsec->sid == newsid) {
1607 rc = avc_has_perm(tsec->sid, isec->sid,
1608 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
1609 if (rc)
1610 return rc;
1611 } else {
1612 /* Check permissions for the transition. */
1613 rc = avc_has_perm(tsec->sid, newsid,
1614 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
1615 if (rc)
1616 return rc;
1617
1618 rc = avc_has_perm(newsid, isec->sid,
1619 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
1620 if (rc)
1621 return rc;
1622
1623 /* Clear any possibly unsafe personality bits on exec: */
1624 current->personality &= ~PER_CLEAR_ON_SETID;
1625
1626 /* Set the security field to the new SID. */
1627 bsec->sid = newsid;
1628 }
1629
1630 bsec->set = 1;
1631 return 0;
1632}
1633
1634static int selinux_bprm_check_security (struct linux_binprm *bprm)
1635{
1636 return secondary_ops->bprm_check_security(bprm);
1637}
1638
1639
1640static int selinux_bprm_secureexec (struct linux_binprm *bprm)
1641{
1642 struct task_security_struct *tsec = current->security;
1643 int atsecure = 0;
1644
1645 if (tsec->osid != tsec->sid) {
1646 /* Enable secure mode for SIDs transitions unless
1647 the noatsecure permission is granted between
1648 the two SIDs, i.e. ahp returns 0. */
1649 atsecure = avc_has_perm(tsec->osid, tsec->sid,
1650 SECCLASS_PROCESS,
1651 PROCESS__NOATSECURE, NULL);
1652 }
1653
1654 return (atsecure || secondary_ops->bprm_secureexec(bprm));
1655}
1656
1657static void selinux_bprm_free_security(struct linux_binprm *bprm)
1658{
1659 struct bprm_security_struct *bsec = bprm->security;
1660 bprm->security = NULL;
1661 kfree(bsec);
1662}
1663
1664extern struct vfsmount *selinuxfs_mount;
1665extern struct dentry *selinux_null;
1666
1667/* Derived from fs/exec.c:flush_old_files. */
1668static inline void flush_unauthorized_files(struct files_struct * files)
1669{
1670 struct avc_audit_data ad;
1671 struct file *file, *devnull = NULL;
1672 struct tty_struct *tty = current->signal->tty;
1673 long j = -1;
1674
1675 if (tty) {
1676 file_list_lock();
1677 file = list_entry(tty->tty_files.next, typeof(*file), f_list);
1678 if (file) {
1679 /* Revalidate access to controlling tty.
1680 Use inode_has_perm on the tty inode directly rather
1681 than using file_has_perm, as this particular open
1682 file may belong to another process and we are only
1683 interested in the inode-based check here. */
1684 struct inode *inode = file->f_dentry->d_inode;
1685 if (inode_has_perm(current, inode,
1686 FILE__READ | FILE__WRITE, NULL)) {
1687 /* Reset controlling tty. */
1688 current->signal->tty = NULL;
1689 current->signal->tty_old_pgrp = 0;
1690 }
1691 }
1692 file_list_unlock();
1693 }
1694
1695 /* Revalidate access to inherited open files. */
1696
1697 AVC_AUDIT_DATA_INIT(&ad,FS);
1698
1699 spin_lock(&files->file_lock);
1700 for (;;) {
1701 unsigned long set, i;
1702 int fd;
1703
1704 j++;
1705 i = j * __NFDBITS;
1706 if (i >= files->max_fds || i >= files->max_fdset)
1707 break;
1708 set = files->open_fds->fds_bits[j];
1709 if (!set)
1710 continue;
1711 spin_unlock(&files->file_lock);
1712 for ( ; set ; i++,set >>= 1) {
1713 if (set & 1) {
1714 file = fget(i);
1715 if (!file)
1716 continue;
1717 if (file_has_perm(current,
1718 file,
1719 file_to_av(file))) {
1720 sys_close(i);
1721 fd = get_unused_fd();
1722 if (fd != i) {
1723 if (fd >= 0)
1724 put_unused_fd(fd);
1725 fput(file);
1726 continue;
1727 }
1728 if (devnull) {
1729 atomic_inc(&devnull->f_count);
1730 } else {
1731 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
1732 if (!devnull) {
1733 put_unused_fd(fd);
1734 fput(file);
1735 continue;
1736 }
1737 }
1738 fd_install(fd, devnull);
1739 }
1740 fput(file);
1741 }
1742 }
1743 spin_lock(&files->file_lock);
1744
1745 }
1746 spin_unlock(&files->file_lock);
1747}
1748
1749static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
1750{
1751 struct task_security_struct *tsec;
1752 struct bprm_security_struct *bsec;
1753 u32 sid;
1754 int rc;
1755
1756 secondary_ops->bprm_apply_creds(bprm, unsafe);
1757
1758 tsec = current->security;
1759
1760 bsec = bprm->security;
1761 sid = bsec->sid;
1762
1763 tsec->osid = tsec->sid;
1764 bsec->unsafe = 0;
1765 if (tsec->sid != sid) {
1766 /* Check for shared state. If not ok, leave SID
1767 unchanged and kill. */
1768 if (unsafe & LSM_UNSAFE_SHARE) {
1769 rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
1770 PROCESS__SHARE, NULL);
1771 if (rc) {
1772 bsec->unsafe = 1;
1773 return;
1774 }
1775 }
1776
1777 /* Check for ptracing, and update the task SID if ok.
1778 Otherwise, leave SID unchanged and kill. */
1779 if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
1780 rc = avc_has_perm(tsec->ptrace_sid, sid,
1781 SECCLASS_PROCESS, PROCESS__PTRACE,
1782 NULL);
1783 if (rc) {
1784 bsec->unsafe = 1;
1785 return;
1786 }
1787 }
1788 tsec->sid = sid;
1789 }
1790}
1791
1792/*
1793 * called after apply_creds without the task lock held
1794 */
1795static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
1796{
1797 struct task_security_struct *tsec;
1798 struct rlimit *rlim, *initrlim;
1799 struct itimerval itimer;
1800 struct bprm_security_struct *bsec;
1801 int rc, i;
1802
1803 tsec = current->security;
1804 bsec = bprm->security;
1805
1806 if (bsec->unsafe) {
1807 force_sig_specific(SIGKILL, current);
1808 return;
1809 }
1810 if (tsec->osid == tsec->sid)
1811 return;
1812
1813 /* Close files for which the new task SID is not authorized. */
1814 flush_unauthorized_files(current->files);
1815
1816 /* Check whether the new SID can inherit signal state
1817 from the old SID. If not, clear itimers to avoid
1818 subsequent signal generation and flush and unblock
1819 signals. This must occur _after_ the task SID has
1820 been updated so that any kill done after the flush
1821 will be checked against the new SID. */
1822 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
1823 PROCESS__SIGINH, NULL);
1824 if (rc) {
1825 memset(&itimer, 0, sizeof itimer);
1826 for (i = 0; i < 3; i++)
1827 do_setitimer(i, &itimer, NULL);
1828 flush_signals(current);
1829 spin_lock_irq(&current->sighand->siglock);
1830 flush_signal_handlers(current, 1);
1831 sigemptyset(&current->blocked);
1832 recalc_sigpending();
1833 spin_unlock_irq(&current->sighand->siglock);
1834 }
1835
1836 /* Check whether the new SID can inherit resource limits
1837 from the old SID. If not, reset all soft limits to
1838 the lower of the current task's hard limit and the init
1839 task's soft limit. Note that the setting of hard limits
1840 (even to lower them) can be controlled by the setrlimit
1841 check. The inclusion of the init task's soft limit into
1842 the computation is to avoid resetting soft limits higher
1843 than the default soft limit for cases where the default
1844 is lower than the hard limit, e.g. RLIMIT_CORE or
1845 RLIMIT_STACK.*/
1846 rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
1847 PROCESS__RLIMITINH, NULL);
1848 if (rc) {
1849 for (i = 0; i < RLIM_NLIMITS; i++) {
1850 rlim = current->signal->rlim + i;
1851 initrlim = init_task.signal->rlim+i;
1852 rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
1853 }
1854 if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
1855 /*
1856 * This will cause RLIMIT_CPU calculations
1857 * to be refigured.
1858 */
1859 current->it_prof_expires = jiffies_to_cputime(1);
1860 }
1861 }
1862
1863 /* Wake up the parent if it is waiting so that it can
1864 recheck wait permission to the new task SID. */
1865 wake_up_interruptible(&current->parent->signal->wait_chldexit);
1866}
1867
1868/* superblock security operations */
1869
1870static int selinux_sb_alloc_security(struct super_block *sb)
1871{
1872 return superblock_alloc_security(sb);
1873}
1874
1875static void selinux_sb_free_security(struct super_block *sb)
1876{
1877 superblock_free_security(sb);
1878}
1879
1880static inline int match_prefix(char *prefix, int plen, char *option, int olen)
1881{
1882 if (plen > olen)
1883 return 0;
1884
1885 return !memcmp(prefix, option, plen);
1886}
1887
1888static inline int selinux_option(char *option, int len)
1889{
1890 return (match_prefix("context=", sizeof("context=")-1, option, len) ||
1891 match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
1892 match_prefix("defcontext=", sizeof("defcontext=")-1, option, len));
1893}
1894
1895static inline void take_option(char **to, char *from, int *first, int len)
1896{
1897 if (!*first) {
1898 **to = ',';
1899 *to += 1;
1900 }
1901 else
1902 *first = 0;
1903 memcpy(*to, from, len);
1904 *to += len;
1905}
1906
1907static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy)
1908{
1909 int fnosec, fsec, rc = 0;
1910 char *in_save, *in_curr, *in_end;
1911 char *sec_curr, *nosec_save, *nosec;
1912
1913 in_curr = orig;
1914 sec_curr = copy;
1915
1916 /* Binary mount data: just copy */
1917 if (type->fs_flags & FS_BINARY_MOUNTDATA) {
1918 copy_page(sec_curr, in_curr);
1919 goto out;
1920 }
1921
1922 nosec = (char *)get_zeroed_page(GFP_KERNEL);
1923 if (!nosec) {
1924 rc = -ENOMEM;
1925 goto out;
1926 }
1927
1928 nosec_save = nosec;
1929 fnosec = fsec = 1;
1930 in_save = in_end = orig;
1931
1932 do {
1933 if (*in_end == ',' || *in_end == '\0') {
1934 int len = in_end - in_curr;
1935
1936 if (selinux_option(in_curr, len))
1937 take_option(&sec_curr, in_curr, &fsec, len);
1938 else
1939 take_option(&nosec, in_curr, &fnosec, len);
1940
1941 in_curr = in_end + 1;
1942 }
1943 } while (*in_end++);
1944
1945 copy_page(in_save, nosec_save);
1946out:
1947 return rc;
1948}
1949
1950static int selinux_sb_kern_mount(struct super_block *sb, void *data)
1951{
1952 struct avc_audit_data ad;
1953 int rc;
1954
1955 rc = superblock_doinit(sb, data);
1956 if (rc)
1957 return rc;
1958
1959 AVC_AUDIT_DATA_INIT(&ad,FS);
1960 ad.u.fs.dentry = sb->s_root;
1961 return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
1962}
1963
1964static int selinux_sb_statfs(struct super_block *sb)
1965{
1966 struct avc_audit_data ad;
1967
1968 AVC_AUDIT_DATA_INIT(&ad,FS);
1969 ad.u.fs.dentry = sb->s_root;
1970 return superblock_has_perm(current, sb, FILESYSTEM__GETATTR, &ad);
1971}
1972
1973static int selinux_mount(char * dev_name,
1974 struct nameidata *nd,
1975 char * type,
1976 unsigned long flags,
1977 void * data)
1978{
1979 int rc;
1980
1981 rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
1982 if (rc)
1983 return rc;
1984
1985 if (flags & MS_REMOUNT)
1986 return superblock_has_perm(current, nd->mnt->mnt_sb,
1987 FILESYSTEM__REMOUNT, NULL);
1988 else
1989 return dentry_has_perm(current, nd->mnt, nd->dentry,
1990 FILE__MOUNTON);
1991}
1992
1993static int selinux_umount(struct vfsmount *mnt, int flags)
1994{
1995 int rc;
1996
1997 rc = secondary_ops->sb_umount(mnt, flags);
1998 if (rc)
1999 return rc;
2000
2001 return superblock_has_perm(current,mnt->mnt_sb,
2002 FILESYSTEM__UNMOUNT,NULL);
2003}
2004
2005/* inode security operations */
2006
2007static int selinux_inode_alloc_security(struct inode *inode)
2008{
2009 return inode_alloc_security(inode);
2010}
2011
2012static void selinux_inode_free_security(struct inode *inode)
2013{
2014 inode_free_security(inode);
2015}
2016
2017static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
2018{
2019 return may_create(dir, dentry, SECCLASS_FILE);
2020}
2021
2022static void selinux_inode_post_create(struct inode *dir, struct dentry *dentry, int mask)
2023{
2024 post_create(dir, dentry);
2025}
2026
2027static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2028{
2029 int rc;
2030
2031 rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
2032 if (rc)
2033 return rc;
2034 return may_link(dir, old_dentry, MAY_LINK);
2035}
2036
2037static void selinux_inode_post_link(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry)
2038{
2039 return;
2040}
2041
2042static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2043{
2044 int rc;
2045
2046 rc = secondary_ops->inode_unlink(dir, dentry);
2047 if (rc)
2048 return rc;
2049 return may_link(dir, dentry, MAY_UNLINK);
2050}
2051
2052static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2053{
2054 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2055}
2056
2057static void selinux_inode_post_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2058{
2059 post_create(dir, dentry);
2060}
2061
2062static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
2063{
2064 return may_create(dir, dentry, SECCLASS_DIR);
2065}
2066
2067static void selinux_inode_post_mkdir(struct inode *dir, struct dentry *dentry, int mask)
2068{
2069 post_create(dir, dentry);
2070}
2071
2072static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2073{
2074 return may_link(dir, dentry, MAY_RMDIR);
2075}
2076
2077static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2078{
2079 int rc;
2080
2081 rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
2082 if (rc)
2083 return rc;
2084
2085 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2086}
2087
2088static void selinux_inode_post_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2089{
2090 post_create(dir, dentry);
2091}
2092
2093static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
2094 struct inode *new_inode, struct dentry *new_dentry)
2095{
2096 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2097}
2098
2099static void selinux_inode_post_rename(struct inode *old_inode, struct dentry *old_dentry,
2100 struct inode *new_inode, struct dentry *new_dentry)
2101{
2102 return;
2103}
2104
2105static int selinux_inode_readlink(struct dentry *dentry)
2106{
2107 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2108}
2109
2110static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2111{
2112 int rc;
2113
2114 rc = secondary_ops->inode_follow_link(dentry,nameidata);
2115 if (rc)
2116 return rc;
2117 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2118}
2119
2120static int selinux_inode_permission(struct inode *inode, int mask,
2121 struct nameidata *nd)
2122{
2123 int rc;
2124
2125 rc = secondary_ops->inode_permission(inode, mask, nd);
2126 if (rc)
2127 return rc;
2128
2129 if (!mask) {
2130 /* No permission to check. Existence test. */
2131 return 0;
2132 }
2133
2134 return inode_has_perm(current, inode,
2135 file_mask_to_av(inode->i_mode, mask), NULL);
2136}
2137
2138static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2139{
2140 int rc;
2141
2142 rc = secondary_ops->inode_setattr(dentry, iattr);
2143 if (rc)
2144 return rc;
2145
2146 if (iattr->ia_valid & ATTR_FORCE)
2147 return 0;
2148
2149 if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2150 ATTR_ATIME_SET | ATTR_MTIME_SET))
2151 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2152
2153 return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
2154}
2155
2156static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2157{
2158 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
2159}
2160
2161static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
2162{
2163 struct task_security_struct *tsec = current->security;
2164 struct inode *inode = dentry->d_inode;
2165 struct inode_security_struct *isec = inode->i_security;
2166 struct superblock_security_struct *sbsec;
2167 struct avc_audit_data ad;
2168 u32 newsid;
2169 int rc = 0;
2170
2171 if (strcmp(name, XATTR_NAME_SELINUX)) {
2172 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2173 sizeof XATTR_SECURITY_PREFIX - 1) &&
2174 !capable(CAP_SYS_ADMIN)) {
2175 /* A different attribute in the security namespace.
2176 Restrict to administrator. */
2177 return -EPERM;
2178 }
2179
2180 /* Not an attribute we recognize, so just check the
2181 ordinary setattr permission. */
2182 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2183 }
2184
2185 sbsec = inode->i_sb->s_security;
2186 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2187 return -EOPNOTSUPP;
2188
2189 if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
2190 return -EPERM;
2191
2192 AVC_AUDIT_DATA_INIT(&ad,FS);
2193 ad.u.fs.dentry = dentry;
2194
2195 rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
2196 FILE__RELABELFROM, &ad);
2197 if (rc)
2198 return rc;
2199
2200 rc = security_context_to_sid(value, size, &newsid);
2201 if (rc)
2202 return rc;
2203
2204 rc = avc_has_perm(tsec->sid, newsid, isec->sclass,
2205 FILE__RELABELTO, &ad);
2206 if (rc)
2207 return rc;
2208
2209 rc = security_validate_transition(isec->sid, newsid, tsec->sid,
2210 isec->sclass);
2211 if (rc)
2212 return rc;
2213
2214 return avc_has_perm(newsid,
2215 sbsec->sid,
2216 SECCLASS_FILESYSTEM,
2217 FILESYSTEM__ASSOCIATE,
2218 &ad);
2219}
2220
2221static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
2222 void *value, size_t size, int flags)
2223{
2224 struct inode *inode = dentry->d_inode;
2225 struct inode_security_struct *isec = inode->i_security;
2226 u32 newsid;
2227 int rc;
2228
2229 if (strcmp(name, XATTR_NAME_SELINUX)) {
2230 /* Not an attribute we recognize, so nothing to do. */
2231 return;
2232 }
2233
2234 rc = security_context_to_sid(value, size, &newsid);
2235 if (rc) {
2236 printk(KERN_WARNING "%s: unable to obtain SID for context "
2237 "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
2238 return;
2239 }
2240
2241 isec->sid = newsid;
2242 return;
2243}
2244
2245static int selinux_inode_getxattr (struct dentry *dentry, char *name)
2246{
2247 struct inode *inode = dentry->d_inode;
2248 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
2249
2250 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
2251 return -EOPNOTSUPP;
2252
2253 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2254}
2255
2256static int selinux_inode_listxattr (struct dentry *dentry)
2257{
2258 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
2259}
2260
2261static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2262{
2263 if (strcmp(name, XATTR_NAME_SELINUX)) {
2264 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2265 sizeof XATTR_SECURITY_PREFIX - 1) &&
2266 !capable(CAP_SYS_ADMIN)) {
2267 /* A different attribute in the security namespace.
2268 Restrict to administrator. */
2269 return -EPERM;
2270 }
2271
2272 /* Not an attribute we recognize, so just check the
2273 ordinary setattr permission. Might want a separate
2274 permission for removexattr. */
2275 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2276 }
2277
2278 /* No one is allowed to remove a SELinux security label.
2279 You can change the label, but all data must be labeled. */
2280 return -EACCES;
2281}
2282
2283static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size)
2284{
2285 struct inode_security_struct *isec = inode->i_security;
2286 char *context;
2287 unsigned len;
2288 int rc;
2289
2290 /* Permission check handled by selinux_inode_getxattr hook.*/
2291
2292 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2293 return -EOPNOTSUPP;
2294
2295 rc = security_sid_to_context(isec->sid, &context, &len);
2296 if (rc)
2297 return rc;
2298
2299 if (!buffer || !size) {
2300 kfree(context);
2301 return len;
2302 }
2303 if (size < len) {
2304 kfree(context);
2305 return -ERANGE;
2306 }
2307 memcpy(buffer, context, len);
2308 kfree(context);
2309 return len;
2310}
2311
2312static int selinux_inode_setsecurity(struct inode *inode, const char *name,
2313 const void *value, size_t size, int flags)
2314{
2315 struct inode_security_struct *isec = inode->i_security;
2316 u32 newsid;
2317 int rc;
2318
2319 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2320 return -EOPNOTSUPP;
2321
2322 if (!value || !size)
2323 return -EACCES;
2324
2325 rc = security_context_to_sid((void*)value, size, &newsid);
2326 if (rc)
2327 return rc;
2328
2329 isec->sid = newsid;
2330 return 0;
2331}
2332
2333static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2334{
2335 const int len = sizeof(XATTR_NAME_SELINUX);
2336 if (buffer && len <= buffer_size)
2337 memcpy(buffer, XATTR_NAME_SELINUX, len);
2338 return len;
2339}
2340
2341/* file security operations */
2342
2343static int selinux_file_permission(struct file *file, int mask)
2344{
2345 struct inode *inode = file->f_dentry->d_inode;
2346
2347 if (!mask) {
2348 /* No permission to check. Existence test. */
2349 return 0;
2350 }
2351
2352 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2353 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2354 mask |= MAY_APPEND;
2355
2356 return file_has_perm(current, file,
2357 file_mask_to_av(inode->i_mode, mask));
2358}
2359
2360static int selinux_file_alloc_security(struct file *file)
2361{
2362 return file_alloc_security(file);
2363}
2364
2365static void selinux_file_free_security(struct file *file)
2366{
2367 file_free_security(file);
2368}
2369
2370static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2371 unsigned long arg)
2372{
2373 int error = 0;
2374
2375 switch (cmd) {
2376 case FIONREAD:
2377 /* fall through */
2378 case FIBMAP:
2379 /* fall through */
2380 case FIGETBSZ:
2381 /* fall through */
2382 case EXT2_IOC_GETFLAGS:
2383 /* fall through */
2384 case EXT2_IOC_GETVERSION:
2385 error = file_has_perm(current, file, FILE__GETATTR);
2386 break;
2387
2388 case EXT2_IOC_SETFLAGS:
2389 /* fall through */
2390 case EXT2_IOC_SETVERSION:
2391 error = file_has_perm(current, file, FILE__SETATTR);
2392 break;
2393
2394 /* sys_ioctl() checks */
2395 case FIONBIO:
2396 /* fall through */
2397 case FIOASYNC:
2398 error = file_has_perm(current, file, 0);
2399 break;
2400
2401 case KDSKBENT:
2402 case KDSKBSENT:
2403 error = task_has_capability(current,CAP_SYS_TTY_CONFIG);
2404 break;
2405
2406 /* default case assumes that the command will go
2407 * to the file's ioctl() function.
2408 */
2409 default:
2410 error = file_has_perm(current, file, FILE__IOCTL);
2411
2412 }
2413 return error;
2414}
2415
2416static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
2417{
2418#ifndef CONFIG_PPC32
2419 if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
2420 /*
2421 * We are making executable an anonymous mapping or a
2422 * private file mapping that will also be writable.
2423 * This has an additional check.
2424 */
2425 int rc = task_has_perm(current, current, PROCESS__EXECMEM);
2426 if (rc)
2427 return rc;
2428 }
2429#endif
2430
2431 if (file) {
2432 /* read access is always possible with a mapping */
2433 u32 av = FILE__READ;
2434
2435 /* write access only matters if the mapping is shared */
2436 if (shared && (prot & PROT_WRITE))
2437 av |= FILE__WRITE;
2438
2439 if (prot & PROT_EXEC)
2440 av |= FILE__EXECUTE;
2441
2442 return file_has_perm(current, file, av);
2443 }
2444 return 0;
2445}
2446
2447static int selinux_file_mmap(struct file *file, unsigned long reqprot,
2448 unsigned long prot, unsigned long flags)
2449{
2450 int rc;
2451
2452 rc = secondary_ops->file_mmap(file, reqprot, prot, flags);
2453 if (rc)
2454 return rc;
2455
2456 if (selinux_checkreqprot)
2457 prot = reqprot;
2458
2459 return file_map_prot_check(file, prot,
2460 (flags & MAP_TYPE) == MAP_SHARED);
2461}
2462
2463static int selinux_file_mprotect(struct vm_area_struct *vma,
2464 unsigned long reqprot,
2465 unsigned long prot)
2466{
2467 int rc;
2468
2469 rc = secondary_ops->file_mprotect(vma, reqprot, prot);
2470 if (rc)
2471 return rc;
2472
2473 if (selinux_checkreqprot)
2474 prot = reqprot;
2475
2476#ifndef CONFIG_PPC32
2477 if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) {
2478 /*
2479 * We are making executable a file mapping that has
2480 * had some COW done. Since pages might have been written,
2481 * check ability to execute the possibly modified content.
2482 * This typically should only occur for text relocations.
2483 */
2484 int rc = file_has_perm(current, vma->vm_file, FILE__EXECMOD);
2485 if (rc)
2486 return rc;
2487 }
2488#endif
2489
2490 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
2491}
2492
2493static int selinux_file_lock(struct file *file, unsigned int cmd)
2494{
2495 return file_has_perm(current, file, FILE__LOCK);
2496}
2497
2498static int selinux_file_fcntl(struct file *file, unsigned int cmd,
2499 unsigned long arg)
2500{
2501 int err = 0;
2502
2503 switch (cmd) {
2504 case F_SETFL:
2505 if (!file->f_dentry || !file->f_dentry->d_inode) {
2506 err = -EINVAL;
2507 break;
2508 }
2509
2510 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
2511 err = file_has_perm(current, file,FILE__WRITE);
2512 break;
2513 }
2514 /* fall through */
2515 case F_SETOWN:
2516 case F_SETSIG:
2517 case F_GETFL:
2518 case F_GETOWN:
2519 case F_GETSIG:
2520 /* Just check FD__USE permission */
2521 err = file_has_perm(current, file, 0);
2522 break;
2523 case F_GETLK:
2524 case F_SETLK:
2525 case F_SETLKW:
2526#if BITS_PER_LONG == 32
2527 case F_GETLK64:
2528 case F_SETLK64:
2529 case F_SETLKW64:
2530#endif
2531 if (!file->f_dentry || !file->f_dentry->d_inode) {
2532 err = -EINVAL;
2533 break;
2534 }
2535 err = file_has_perm(current, file, FILE__LOCK);
2536 break;
2537 }
2538
2539 return err;
2540}
2541
2542static int selinux_file_set_fowner(struct file *file)
2543{
2544 struct task_security_struct *tsec;
2545 struct file_security_struct *fsec;
2546
2547 tsec = current->security;
2548 fsec = file->f_security;
2549 fsec->fown_sid = tsec->sid;
2550
2551 return 0;
2552}
2553
2554static int selinux_file_send_sigiotask(struct task_struct *tsk,
2555 struct fown_struct *fown, int signum)
2556{
2557 struct file *file;
2558 u32 perm;
2559 struct task_security_struct *tsec;
2560 struct file_security_struct *fsec;
2561
2562 /* struct fown_struct is never outside the context of a struct file */
2563 file = (struct file *)((long)fown - offsetof(struct file,f_owner));
2564
2565 tsec = tsk->security;
2566 fsec = file->f_security;
2567
2568 if (!signum)
2569 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
2570 else
2571 perm = signal_to_av(signum);
2572
2573 return avc_has_perm(fsec->fown_sid, tsec->sid,
2574 SECCLASS_PROCESS, perm, NULL);
2575}
2576
2577static int selinux_file_receive(struct file *file)
2578{
2579 return file_has_perm(current, file, file_to_av(file));
2580}
2581
2582/* task security operations */
2583
2584static int selinux_task_create(unsigned long clone_flags)
2585{
2586 int rc;
2587
2588 rc = secondary_ops->task_create(clone_flags);
2589 if (rc)
2590 return rc;
2591
2592 return task_has_perm(current, current, PROCESS__FORK);
2593}
2594
2595static int selinux_task_alloc_security(struct task_struct *tsk)
2596{
2597 struct task_security_struct *tsec1, *tsec2;
2598 int rc;
2599
2600 tsec1 = current->security;
2601
2602 rc = task_alloc_security(tsk);
2603 if (rc)
2604 return rc;
2605 tsec2 = tsk->security;
2606
2607 tsec2->osid = tsec1->osid;
2608 tsec2->sid = tsec1->sid;
2609
2610 /* Retain the exec and create SIDs across fork */
2611 tsec2->exec_sid = tsec1->exec_sid;
2612 tsec2->create_sid = tsec1->create_sid;
2613
2614 /* Retain ptracer SID across fork, if any.
2615 This will be reset by the ptrace hook upon any
2616 subsequent ptrace_attach operations. */
2617 tsec2->ptrace_sid = tsec1->ptrace_sid;
2618
2619 return 0;
2620}
2621
2622static void selinux_task_free_security(struct task_struct *tsk)
2623{
2624 task_free_security(tsk);
2625}
2626
2627static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
2628{
2629 /* Since setuid only affects the current process, and
2630 since the SELinux controls are not based on the Linux
2631 identity attributes, SELinux does not need to control
2632 this operation. However, SELinux does control the use
2633 of the CAP_SETUID and CAP_SETGID capabilities using the
2634 capable hook. */
2635 return 0;
2636}
2637
2638static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
2639{
2640 return secondary_ops->task_post_setuid(id0,id1,id2,flags);
2641}
2642
2643static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
2644{
2645 /* See the comment for setuid above. */
2646 return 0;
2647}
2648
2649static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
2650{
2651 return task_has_perm(current, p, PROCESS__SETPGID);
2652}
2653
2654static int selinux_task_getpgid(struct task_struct *p)
2655{
2656 return task_has_perm(current, p, PROCESS__GETPGID);
2657}
2658
2659static int selinux_task_getsid(struct task_struct *p)
2660{
2661 return task_has_perm(current, p, PROCESS__GETSESSION);
2662}
2663
2664static int selinux_task_setgroups(struct group_info *group_info)
2665{
2666 /* See the comment for setuid above. */
2667 return 0;
2668}
2669
2670static int selinux_task_setnice(struct task_struct *p, int nice)
2671{
2672 int rc;
2673
2674 rc = secondary_ops->task_setnice(p, nice);
2675 if (rc)
2676 return rc;
2677
2678 return task_has_perm(current,p, PROCESS__SETSCHED);
2679}
2680
2681static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
2682{
2683 struct rlimit *old_rlim = current->signal->rlim + resource;
2684 int rc;
2685
2686 rc = secondary_ops->task_setrlimit(resource, new_rlim);
2687 if (rc)
2688 return rc;
2689
2690 /* Control the ability to change the hard limit (whether
2691 lowering or raising it), so that the hard limit can
2692 later be used as a safe reset point for the soft limit
2693 upon context transitions. See selinux_bprm_apply_creds. */
2694 if (old_rlim->rlim_max != new_rlim->rlim_max)
2695 return task_has_perm(current, current, PROCESS__SETRLIMIT);
2696
2697 return 0;
2698}
2699
2700static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
2701{
2702 return task_has_perm(current, p, PROCESS__SETSCHED);
2703}
2704
2705static int selinux_task_getscheduler(struct task_struct *p)
2706{
2707 return task_has_perm(current, p, PROCESS__GETSCHED);
2708}
2709
2710static int selinux_task_kill(struct task_struct *p, struct siginfo *info, int sig)
2711{
2712 u32 perm;
2713 int rc;
2714
2715 rc = secondary_ops->task_kill(p, info, sig);
2716 if (rc)
2717 return rc;
2718
2719 if (info && ((unsigned long)info == 1 ||
2720 (unsigned long)info == 2 || SI_FROMKERNEL(info)))
2721 return 0;
2722
2723 if (!sig)
2724 perm = PROCESS__SIGNULL; /* null signal; existence test */
2725 else
2726 perm = signal_to_av(sig);
2727
2728 return task_has_perm(current, p, perm);
2729}
2730
2731static int selinux_task_prctl(int option,
2732 unsigned long arg2,
2733 unsigned long arg3,
2734 unsigned long arg4,
2735 unsigned long arg5)
2736{
2737 /* The current prctl operations do not appear to require
2738 any SELinux controls since they merely observe or modify
2739 the state of the current process. */
2740 return 0;
2741}
2742
2743static int selinux_task_wait(struct task_struct *p)
2744{
2745 u32 perm;
2746
2747 perm = signal_to_av(p->exit_signal);
2748
2749 return task_has_perm(p, current, perm);
2750}
2751
2752static void selinux_task_reparent_to_init(struct task_struct *p)
2753{
2754 struct task_security_struct *tsec;
2755
2756 secondary_ops->task_reparent_to_init(p);
2757
2758 tsec = p->security;
2759 tsec->osid = tsec->sid;
2760 tsec->sid = SECINITSID_KERNEL;
2761 return;
2762}
2763
2764static void selinux_task_to_inode(struct task_struct *p,
2765 struct inode *inode)
2766{
2767 struct task_security_struct *tsec = p->security;
2768 struct inode_security_struct *isec = inode->i_security;
2769
2770 isec->sid = tsec->sid;
2771 isec->initialized = 1;
2772 return;
2773}
2774
2775#ifdef CONFIG_SECURITY_NETWORK
2776
2777/* Returns error only if unable to parse addresses */
2778static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad)
2779{
2780 int offset, ihlen, ret = -EINVAL;
2781 struct iphdr _iph, *ih;
2782
2783 offset = skb->nh.raw - skb->data;
2784 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
2785 if (ih == NULL)
2786 goto out;
2787
2788 ihlen = ih->ihl * 4;
2789 if (ihlen < sizeof(_iph))
2790 goto out;
2791
2792 ad->u.net.v4info.saddr = ih->saddr;
2793 ad->u.net.v4info.daddr = ih->daddr;
2794 ret = 0;
2795
2796 switch (ih->protocol) {
2797 case IPPROTO_TCP: {
2798 struct tcphdr _tcph, *th;
2799
2800 if (ntohs(ih->frag_off) & IP_OFFSET)
2801 break;
2802
2803 offset += ihlen;
2804 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
2805 if (th == NULL)
2806 break;
2807
2808 ad->u.net.sport = th->source;
2809 ad->u.net.dport = th->dest;
2810 break;
2811 }
2812
2813 case IPPROTO_UDP: {
2814 struct udphdr _udph, *uh;
2815
2816 if (ntohs(ih->frag_off) & IP_OFFSET)
2817 break;
2818
2819 offset += ihlen;
2820 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
2821 if (uh == NULL)
2822 break;
2823
2824 ad->u.net.sport = uh->source;
2825 ad->u.net.dport = uh->dest;
2826 break;
2827 }
2828
2829 default:
2830 break;
2831 }
2832out:
2833 return ret;
2834}
2835
2836#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
2837
2838/* Returns error only if unable to parse addresses */
2839static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad)
2840{
2841 u8 nexthdr;
2842 int ret = -EINVAL, offset;
2843 struct ipv6hdr _ipv6h, *ip6;
2844
2845 offset = skb->nh.raw - skb->data;
2846 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
2847 if (ip6 == NULL)
2848 goto out;
2849
2850 ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
2851 ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
2852 ret = 0;
2853
2854 nexthdr = ip6->nexthdr;
2855 offset += sizeof(_ipv6h);
2856 offset = ipv6_skip_exthdr(skb, offset, &nexthdr,
2857 skb->tail - skb->head - offset);
2858 if (offset < 0)
2859 goto out;
2860
2861 switch (nexthdr) {
2862 case IPPROTO_TCP: {
2863 struct tcphdr _tcph, *th;
2864
2865 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
2866 if (th == NULL)
2867 break;
2868
2869 ad->u.net.sport = th->source;
2870 ad->u.net.dport = th->dest;
2871 break;
2872 }
2873
2874 case IPPROTO_UDP: {
2875 struct udphdr _udph, *uh;
2876
2877 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
2878 if (uh == NULL)
2879 break;
2880
2881 ad->u.net.sport = uh->source;
2882 ad->u.net.dport = uh->dest;
2883 break;
2884 }
2885
2886 /* includes fragments */
2887 default:
2888 break;
2889 }
2890out:
2891 return ret;
2892}
2893
2894#endif /* IPV6 */
2895
2896static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
2897 char **addrp, int *len, int src)
2898{
2899 int ret = 0;
2900
2901 switch (ad->u.net.family) {
2902 case PF_INET:
2903 ret = selinux_parse_skb_ipv4(skb, ad);
2904 if (ret || !addrp)
2905 break;
2906 *len = 4;
2907 *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
2908 &ad->u.net.v4info.daddr);
2909 break;
2910
2911#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
2912 case PF_INET6:
2913 ret = selinux_parse_skb_ipv6(skb, ad);
2914 if (ret || !addrp)
2915 break;
2916 *len = 16;
2917 *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
2918 &ad->u.net.v6info.daddr);
2919 break;
2920#endif /* IPV6 */
2921 default:
2922 break;
2923 }
2924
2925 return ret;
2926}
2927
2928/* socket security operations */
2929static int socket_has_perm(struct task_struct *task, struct socket *sock,
2930 u32 perms)
2931{
2932 struct inode_security_struct *isec;
2933 struct task_security_struct *tsec;
2934 struct avc_audit_data ad;
2935 int err = 0;
2936
2937 tsec = task->security;
2938 isec = SOCK_INODE(sock)->i_security;
2939
2940 if (isec->sid == SECINITSID_KERNEL)
2941 goto out;
2942
2943 AVC_AUDIT_DATA_INIT(&ad,NET);
2944 ad.u.net.sk = sock->sk;
2945 err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
2946
2947out:
2948 return err;
2949}
2950
2951static int selinux_socket_create(int family, int type,
2952 int protocol, int kern)
2953{
2954 int err = 0;
2955 struct task_security_struct *tsec;
2956
2957 if (kern)
2958 goto out;
2959
2960 tsec = current->security;
2961 err = avc_has_perm(tsec->sid, tsec->sid,
2962 socket_type_to_security_class(family, type,
2963 protocol), SOCKET__CREATE, NULL);
2964
2965out:
2966 return err;
2967}
2968
2969static void selinux_socket_post_create(struct socket *sock, int family,
2970 int type, int protocol, int kern)
2971{
2972 struct inode_security_struct *isec;
2973 struct task_security_struct *tsec;
2974
2975 isec = SOCK_INODE(sock)->i_security;
2976
2977 tsec = current->security;
2978 isec->sclass = socket_type_to_security_class(family, type, protocol);
2979 isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
2980 isec->initialized = 1;
2981
2982 return;
2983}
2984
2985/* Range of port numbers used to automatically bind.
2986 Need to determine whether we should perform a name_bind
2987 permission check between the socket and the port number. */
2988#define ip_local_port_range_0 sysctl_local_port_range[0]
2989#define ip_local_port_range_1 sysctl_local_port_range[1]
2990
2991static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
2992{
2993 u16 family;
2994 int err;
2995
2996 err = socket_has_perm(current, sock, SOCKET__BIND);
2997 if (err)
2998 goto out;
2999
3000 /*
3001 * If PF_INET or PF_INET6, check name_bind permission for the port.
3002 */
3003 family = sock->sk->sk_family;
3004 if (family == PF_INET || family == PF_INET6) {
3005 char *addrp;
3006 struct inode_security_struct *isec;
3007 struct task_security_struct *tsec;
3008 struct avc_audit_data ad;
3009 struct sockaddr_in *addr4 = NULL;
3010 struct sockaddr_in6 *addr6 = NULL;
3011 unsigned short snum;
3012 struct sock *sk = sock->sk;
3013 u32 sid, node_perm, addrlen;
3014
3015 tsec = current->security;
3016 isec = SOCK_INODE(sock)->i_security;
3017
3018 if (family == PF_INET) {
3019 addr4 = (struct sockaddr_in *)address;
3020 snum = ntohs(addr4->sin_port);
3021 addrlen = sizeof(addr4->sin_addr.s_addr);
3022 addrp = (char *)&addr4->sin_addr.s_addr;
3023 } else {
3024 addr6 = (struct sockaddr_in6 *)address;
3025 snum = ntohs(addr6->sin6_port);
3026 addrlen = sizeof(addr6->sin6_addr.s6_addr);
3027 addrp = (char *)&addr6->sin6_addr.s6_addr;
3028 }
3029
3030 if (snum&&(snum < max(PROT_SOCK,ip_local_port_range_0) ||
3031 snum > ip_local_port_range_1)) {
3032 err = security_port_sid(sk->sk_family, sk->sk_type,
3033 sk->sk_protocol, snum, &sid);
3034 if (err)
3035 goto out;
3036 AVC_AUDIT_DATA_INIT(&ad,NET);
3037 ad.u.net.sport = htons(snum);
3038 ad.u.net.family = family;
3039 err = avc_has_perm(isec->sid, sid,
3040 isec->sclass,
3041 SOCKET__NAME_BIND, &ad);
3042 if (err)
3043 goto out;
3044 }
3045
3046 switch(sk->sk_protocol) {
3047 case IPPROTO_TCP:
3048 node_perm = TCP_SOCKET__NODE_BIND;
3049 break;
3050
3051 case IPPROTO_UDP:
3052 node_perm = UDP_SOCKET__NODE_BIND;
3053 break;
3054
3055 default:
3056 node_perm = RAWIP_SOCKET__NODE_BIND;
3057 break;
3058 }
3059
3060 err = security_node_sid(family, addrp, addrlen, &sid);
3061 if (err)
3062 goto out;
3063
3064 AVC_AUDIT_DATA_INIT(&ad,NET);
3065 ad.u.net.sport = htons(snum);
3066 ad.u.net.family = family;
3067
3068 if (family == PF_INET)
3069 ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
3070 else
3071 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3072
3073 err = avc_has_perm(isec->sid, sid,
3074 isec->sclass, node_perm, &ad);
3075 if (err)
3076 goto out;
3077 }
3078out:
3079 return err;
3080}
3081
3082static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3083{
3084 struct inode_security_struct *isec;
3085 int err;
3086
3087 err = socket_has_perm(current, sock, SOCKET__CONNECT);
3088 if (err)
3089 return err;
3090
3091 /*
3092 * If a TCP socket, check name_connect permission for the port.
3093 */
3094 isec = SOCK_INODE(sock)->i_security;
3095 if (isec->sclass == SECCLASS_TCP_SOCKET) {
3096 struct sock *sk = sock->sk;
3097 struct avc_audit_data ad;
3098 struct sockaddr_in *addr4 = NULL;
3099 struct sockaddr_in6 *addr6 = NULL;
3100 unsigned short snum;
3101 u32 sid;
3102
3103 if (sk->sk_family == PF_INET) {
3104 addr4 = (struct sockaddr_in *)address;
3105 if (addrlen != sizeof(struct sockaddr_in))
3106 return -EINVAL;
3107 snum = ntohs(addr4->sin_port);
3108 } else {
3109 addr6 = (struct sockaddr_in6 *)address;
3110 if (addrlen != sizeof(struct sockaddr_in6))
3111 return -EINVAL;
3112 snum = ntohs(addr6->sin6_port);
3113 }
3114
3115 err = security_port_sid(sk->sk_family, sk->sk_type,
3116 sk->sk_protocol, snum, &sid);
3117 if (err)
3118 goto out;
3119
3120 AVC_AUDIT_DATA_INIT(&ad,NET);
3121 ad.u.net.dport = htons(snum);
3122 ad.u.net.family = sk->sk_family;
3123 err = avc_has_perm(isec->sid, sid, isec->sclass,
3124 TCP_SOCKET__NAME_CONNECT, &ad);
3125 if (err)
3126 goto out;
3127 }
3128
3129out:
3130 return err;
3131}
3132
3133static int selinux_socket_listen(struct socket *sock, int backlog)
3134{
3135 return socket_has_perm(current, sock, SOCKET__LISTEN);
3136}
3137
3138static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3139{
3140 int err;
3141 struct inode_security_struct *isec;
3142 struct inode_security_struct *newisec;
3143
3144 err = socket_has_perm(current, sock, SOCKET__ACCEPT);
3145 if (err)
3146 return err;
3147
3148 newisec = SOCK_INODE(newsock)->i_security;
3149
3150 isec = SOCK_INODE(sock)->i_security;
3151 newisec->sclass = isec->sclass;
3152 newisec->sid = isec->sid;
3153 newisec->initialized = 1;
3154
3155 return 0;
3156}
3157
3158static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3159 int size)
3160{
3161 return socket_has_perm(current, sock, SOCKET__WRITE);
3162}
3163
3164static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3165 int size, int flags)
3166{
3167 return socket_has_perm(current, sock, SOCKET__READ);
3168}
3169
3170static int selinux_socket_getsockname(struct socket *sock)
3171{
3172 return socket_has_perm(current, sock, SOCKET__GETATTR);
3173}
3174
3175static int selinux_socket_getpeername(struct socket *sock)
3176{
3177 return socket_has_perm(current, sock, SOCKET__GETATTR);
3178}
3179
3180static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
3181{
3182 return socket_has_perm(current, sock, SOCKET__SETOPT);
3183}
3184
3185static int selinux_socket_getsockopt(struct socket *sock, int level,
3186 int optname)
3187{
3188 return socket_has_perm(current, sock, SOCKET__GETOPT);
3189}
3190
3191static int selinux_socket_shutdown(struct socket *sock, int how)
3192{
3193 return socket_has_perm(current, sock, SOCKET__SHUTDOWN);
3194}
3195
3196static int selinux_socket_unix_stream_connect(struct socket *sock,
3197 struct socket *other,
3198 struct sock *newsk)
3199{
3200 struct sk_security_struct *ssec;
3201 struct inode_security_struct *isec;
3202 struct inode_security_struct *other_isec;
3203 struct avc_audit_data ad;
3204 int err;
3205
3206 err = secondary_ops->unix_stream_connect(sock, other, newsk);
3207 if (err)
3208 return err;
3209
3210 isec = SOCK_INODE(sock)->i_security;
3211 other_isec = SOCK_INODE(other)->i_security;
3212
3213 AVC_AUDIT_DATA_INIT(&ad,NET);
3214 ad.u.net.sk = other->sk;
3215
3216 err = avc_has_perm(isec->sid, other_isec->sid,
3217 isec->sclass,
3218 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
3219 if (err)
3220 return err;
3221
3222 /* connecting socket */
3223 ssec = sock->sk->sk_security;
3224 ssec->peer_sid = other_isec->sid;
3225
3226 /* server child socket */
3227 ssec = newsk->sk_security;
3228 ssec->peer_sid = isec->sid;
3229
3230 return 0;
3231}
3232
3233static int selinux_socket_unix_may_send(struct socket *sock,
3234 struct socket *other)
3235{
3236 struct inode_security_struct *isec;
3237 struct inode_security_struct *other_isec;
3238 struct avc_audit_data ad;
3239 int err;
3240
3241 isec = SOCK_INODE(sock)->i_security;
3242 other_isec = SOCK_INODE(other)->i_security;
3243
3244 AVC_AUDIT_DATA_INIT(&ad,NET);
3245 ad.u.net.sk = other->sk;
3246
3247 err = avc_has_perm(isec->sid, other_isec->sid,
3248 isec->sclass, SOCKET__SENDTO, &ad);
3249 if (err)
3250 return err;
3251
3252 return 0;
3253}
3254
3255static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3256{
3257 u16 family;
3258 char *addrp;
3259 int len, err = 0;
3260 u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
3261 u32 sock_sid = 0;
3262 u16 sock_class = 0;
3263 struct socket *sock;
3264 struct net_device *dev;
3265 struct avc_audit_data ad;
3266
3267 family = sk->sk_family;
3268 if (family != PF_INET && family != PF_INET6)
3269 goto out;
3270
3271 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
3272 if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
3273 family = PF_INET;
3274
3275 read_lock_bh(&sk->sk_callback_lock);
3276 sock = sk->sk_socket;
3277 if (sock) {
3278 struct inode *inode;
3279 inode = SOCK_INODE(sock);
3280 if (inode) {
3281 struct inode_security_struct *isec;
3282 isec = inode->i_security;
3283 sock_sid = isec->sid;
3284 sock_class = isec->sclass;
3285 }
3286 }
3287 read_unlock_bh(&sk->sk_callback_lock);
3288 if (!sock_sid)
3289 goto out;
3290
3291 dev = skb->dev;
3292 if (!dev)
3293 goto out;
3294
3295 err = sel_netif_sids(dev, &if_sid, NULL);
3296 if (err)
3297 goto out;
3298
3299 switch (sock_class) {
3300 case SECCLASS_UDP_SOCKET:
3301 netif_perm = NETIF__UDP_RECV;
3302 node_perm = NODE__UDP_RECV;
3303 recv_perm = UDP_SOCKET__RECV_MSG;
3304 break;
3305
3306 case SECCLASS_TCP_SOCKET:
3307 netif_perm = NETIF__TCP_RECV;
3308 node_perm = NODE__TCP_RECV;
3309 recv_perm = TCP_SOCKET__RECV_MSG;
3310 break;
3311
3312 default:
3313 netif_perm = NETIF__RAWIP_RECV;
3314 node_perm = NODE__RAWIP_RECV;
3315 break;
3316 }
3317
3318 AVC_AUDIT_DATA_INIT(&ad, NET);
3319 ad.u.net.netif = dev->name;
3320 ad.u.net.family = family;
3321
3322 err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
3323 if (err)
3324 goto out;
3325
3326 err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, &ad);
3327 if (err)
3328 goto out;
3329
3330 /* Fixme: this lookup is inefficient */
3331 err = security_node_sid(family, addrp, len, &node_sid);
3332 if (err)
3333 goto out;
3334
3335 err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, &ad);
3336 if (err)
3337 goto out;
3338
3339 if (recv_perm) {
3340 u32 port_sid;
3341
3342 /* Fixme: make this more efficient */
3343 err = security_port_sid(sk->sk_family, sk->sk_type,
3344 sk->sk_protocol, ntohs(ad.u.net.sport),
3345 &port_sid);
3346 if (err)
3347 goto out;
3348
3349 err = avc_has_perm(sock_sid, port_sid,
3350 sock_class, recv_perm, &ad);
3351 }
3352out:
3353 return err;
3354}
3355
3356static int selinux_socket_getpeersec(struct socket *sock, char __user *optval,
3357 int __user *optlen, unsigned len)
3358{
3359 int err = 0;
3360 char *scontext;
3361 u32 scontext_len;
3362 struct sk_security_struct *ssec;
3363 struct inode_security_struct *isec;
3364
3365 isec = SOCK_INODE(sock)->i_security;
3366 if (isec->sclass != SECCLASS_UNIX_STREAM_SOCKET) {
3367 err = -ENOPROTOOPT;
3368 goto out;
3369 }
3370
3371 ssec = sock->sk->sk_security;
3372
3373 err = security_sid_to_context(ssec->peer_sid, &scontext, &scontext_len);
3374 if (err)
3375 goto out;
3376
3377 if (scontext_len > len) {
3378 err = -ERANGE;
3379 goto out_len;
3380 }
3381
3382 if (copy_to_user(optval, scontext, scontext_len))
3383 err = -EFAULT;
3384
3385out_len:
3386 if (put_user(scontext_len, optlen))
3387 err = -EFAULT;
3388
3389 kfree(scontext);
3390out:
3391 return err;
3392}
3393
3394static int selinux_sk_alloc_security(struct sock *sk, int family, int priority)
3395{
3396 return sk_alloc_security(sk, family, priority);
3397}
3398
3399static void selinux_sk_free_security(struct sock *sk)
3400{
3401 sk_free_security(sk);
3402}
3403
3404static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
3405{
3406 int err = 0;
3407 u32 perm;
3408 struct nlmsghdr *nlh;
3409 struct socket *sock = sk->sk_socket;
3410 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
3411
3412 if (skb->len < NLMSG_SPACE(0)) {
3413 err = -EINVAL;
3414 goto out;
3415 }
3416 nlh = (struct nlmsghdr *)skb->data;
3417
3418 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
3419 if (err) {
3420 if (err == -EINVAL) {
3421 audit_log(current->audit_context,
3422 "SELinux: unrecognized netlink message"
3423 " type=%hu for sclass=%hu\n",
3424 nlh->nlmsg_type, isec->sclass);
3425 if (!selinux_enforcing)
3426 err = 0;
3427 }
3428
3429 /* Ignore */
3430 if (err == -ENOENT)
3431 err = 0;
3432 goto out;
3433 }
3434
3435 err = socket_has_perm(current, sock, perm);
3436out:
3437 return err;
3438}
3439
3440#ifdef CONFIG_NETFILTER
3441
3442static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3443 struct sk_buff **pskb,
3444 const struct net_device *in,
3445 const struct net_device *out,
3446 int (*okfn)(struct sk_buff *),
3447 u16 family)
3448{
3449 char *addrp;
3450 int len, err = NF_ACCEPT;
3451 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
3452 struct sock *sk;
3453 struct socket *sock;
3454 struct inode *inode;
3455 struct sk_buff *skb = *pskb;
3456 struct inode_security_struct *isec;
3457 struct avc_audit_data ad;
3458 struct net_device *dev = (struct net_device *)out;
3459
3460 sk = skb->sk;
3461 if (!sk)
3462 goto out;
3463
3464 sock = sk->sk_socket;
3465 if (!sock)
3466 goto out;
3467
3468 inode = SOCK_INODE(sock);
3469 if (!inode)
3470 goto out;
3471
3472 err = sel_netif_sids(dev, &if_sid, NULL);
3473 if (err)
3474 goto out;
3475
3476 isec = inode->i_security;
3477
3478 switch (isec->sclass) {
3479 case SECCLASS_UDP_SOCKET:
3480 netif_perm = NETIF__UDP_SEND;
3481 node_perm = NODE__UDP_SEND;
3482 send_perm = UDP_SOCKET__SEND_MSG;
3483 break;
3484
3485 case SECCLASS_TCP_SOCKET:
3486 netif_perm = NETIF__TCP_SEND;
3487 node_perm = NODE__TCP_SEND;
3488 send_perm = TCP_SOCKET__SEND_MSG;
3489 break;
3490
3491 default:
3492 netif_perm = NETIF__RAWIP_SEND;
3493 node_perm = NODE__RAWIP_SEND;
3494 break;
3495 }
3496
3497
3498 AVC_AUDIT_DATA_INIT(&ad, NET);
3499 ad.u.net.netif = dev->name;
3500 ad.u.net.family = family;
3501
3502 err = selinux_parse_skb(skb, &ad, &addrp,
3503 &len, 0) ? NF_DROP : NF_ACCEPT;
3504 if (err != NF_ACCEPT)
3505 goto out;
3506
3507 err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF,
3508 netif_perm, &ad) ? NF_DROP : NF_ACCEPT;
3509 if (err != NF_ACCEPT)
3510 goto out;
3511
3512 /* Fixme: this lookup is inefficient */
3513 err = security_node_sid(family, addrp, len,
3514 &node_sid) ? NF_DROP : NF_ACCEPT;
3515 if (err != NF_ACCEPT)
3516 goto out;
3517
3518 err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE,
3519 node_perm, &ad) ? NF_DROP : NF_ACCEPT;
3520 if (err != NF_ACCEPT)
3521 goto out;
3522
3523 if (send_perm) {
3524 u32 port_sid;
3525
3526 /* Fixme: make this more efficient */
3527 err = security_port_sid(sk->sk_family,
3528 sk->sk_type,
3529 sk->sk_protocol,
3530 ntohs(ad.u.net.dport),
3531 &port_sid) ? NF_DROP : NF_ACCEPT;
3532 if (err != NF_ACCEPT)
3533 goto out;
3534
3535 err = avc_has_perm(isec->sid, port_sid, isec->sclass,
3536 send_perm, &ad) ? NF_DROP : NF_ACCEPT;
3537 }
3538
3539out:
3540 return err;
3541}
3542
3543static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum,
3544 struct sk_buff **pskb,
3545 const struct net_device *in,
3546 const struct net_device *out,
3547 int (*okfn)(struct sk_buff *))
3548{
3549 return selinux_ip_postroute_last(hooknum, pskb, in, out, okfn, PF_INET);
3550}
3551
3552#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3553
3554static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum,
3555 struct sk_buff **pskb,
3556 const struct net_device *in,
3557 const struct net_device *out,
3558 int (*okfn)(struct sk_buff *))
3559{
3560 return selinux_ip_postroute_last(hooknum, pskb, in, out, okfn, PF_INET6);
3561}
3562
3563#endif /* IPV6 */
3564
3565#endif /* CONFIG_NETFILTER */
3566
3567#else
3568
3569static inline int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
3570{
3571 return 0;
3572}
3573
3574#endif /* CONFIG_SECURITY_NETWORK */
3575
3576static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
3577{
3578 struct task_security_struct *tsec;
3579 struct av_decision avd;
3580 int err;
3581
3582 err = secondary_ops->netlink_send(sk, skb);
3583 if (err)
3584 return err;
3585
3586 tsec = current->security;
3587
3588 avd.allowed = 0;
3589 avc_has_perm_noaudit(tsec->sid, tsec->sid,
3590 SECCLASS_CAPABILITY, ~0, &avd);
3591 cap_mask(NETLINK_CB(skb).eff_cap, avd.allowed);
3592
3593 if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS)
3594 err = selinux_nlmsg_perm(sk, skb);
3595
3596 return err;
3597}
3598
3599static int selinux_netlink_recv(struct sk_buff *skb)
3600{
3601 if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
3602 return -EPERM;
3603 return 0;
3604}
3605
3606static int ipc_alloc_security(struct task_struct *task,
3607 struct kern_ipc_perm *perm,
3608 u16 sclass)
3609{
3610 struct task_security_struct *tsec = task->security;
3611 struct ipc_security_struct *isec;
3612
3613 isec = kmalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
3614 if (!isec)
3615 return -ENOMEM;
3616
3617 memset(isec, 0, sizeof(struct ipc_security_struct));
3618 isec->magic = SELINUX_MAGIC;
3619 isec->sclass = sclass;
3620 isec->ipc_perm = perm;
3621 if (tsec) {
3622 isec->sid = tsec->sid;
3623 } else {
3624 isec->sid = SECINITSID_UNLABELED;
3625 }
3626 perm->security = isec;
3627
3628 return 0;
3629}
3630
3631static void ipc_free_security(struct kern_ipc_perm *perm)
3632{
3633 struct ipc_security_struct *isec = perm->security;
3634 if (!isec || isec->magic != SELINUX_MAGIC)
3635 return;
3636
3637 perm->security = NULL;
3638 kfree(isec);
3639}
3640
3641static int msg_msg_alloc_security(struct msg_msg *msg)
3642{
3643 struct msg_security_struct *msec;
3644
3645 msec = kmalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
3646 if (!msec)
3647 return -ENOMEM;
3648
3649 memset(msec, 0, sizeof(struct msg_security_struct));
3650 msec->magic = SELINUX_MAGIC;
3651 msec->msg = msg;
3652 msec->sid = SECINITSID_UNLABELED;
3653 msg->security = msec;
3654
3655 return 0;
3656}
3657
3658static void msg_msg_free_security(struct msg_msg *msg)
3659{
3660 struct msg_security_struct *msec = msg->security;
3661 if (!msec || msec->magic != SELINUX_MAGIC)
3662 return;
3663
3664 msg->security = NULL;
3665 kfree(msec);
3666}
3667
3668static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
3669 u16 sclass, u32 perms)
3670{
3671 struct task_security_struct *tsec;
3672 struct ipc_security_struct *isec;
3673 struct avc_audit_data ad;
3674
3675 tsec = current->security;
3676 isec = ipc_perms->security;
3677
3678 AVC_AUDIT_DATA_INIT(&ad, IPC);
3679 ad.u.ipc_id = ipc_perms->key;
3680
3681 return avc_has_perm(tsec->sid, isec->sid, sclass, perms, &ad);
3682}
3683
3684static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
3685{
3686 return msg_msg_alloc_security(msg);
3687}
3688
3689static void selinux_msg_msg_free_security(struct msg_msg *msg)
3690{
3691 msg_msg_free_security(msg);
3692}
3693
3694/* message queue security operations */
3695static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
3696{
3697 struct task_security_struct *tsec;
3698 struct ipc_security_struct *isec;
3699 struct avc_audit_data ad;
3700 int rc;
3701
3702 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
3703 if (rc)
3704 return rc;
3705
3706 tsec = current->security;
3707 isec = msq->q_perm.security;
3708
3709 AVC_AUDIT_DATA_INIT(&ad, IPC);
3710 ad.u.ipc_id = msq->q_perm.key;
3711
3712 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
3713 MSGQ__CREATE, &ad);
3714 if (rc) {
3715 ipc_free_security(&msq->q_perm);
3716 return rc;
3717 }
3718 return 0;
3719}
3720
3721static void selinux_msg_queue_free_security(struct msg_queue *msq)
3722{
3723 ipc_free_security(&msq->q_perm);
3724}
3725
3726static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
3727{
3728 struct task_security_struct *tsec;
3729 struct ipc_security_struct *isec;
3730 struct avc_audit_data ad;
3731
3732 tsec = current->security;
3733 isec = msq->q_perm.security;
3734
3735 AVC_AUDIT_DATA_INIT(&ad, IPC);
3736 ad.u.ipc_id = msq->q_perm.key;
3737
3738 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
3739 MSGQ__ASSOCIATE, &ad);
3740}
3741
3742static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
3743{
3744 int err;
3745 int perms;
3746
3747 switch(cmd) {
3748 case IPC_INFO:
3749 case MSG_INFO:
3750 /* No specific object, just general system-wide information. */
3751 return task_has_system(current, SYSTEM__IPC_INFO);
3752 case IPC_STAT:
3753 case MSG_STAT:
3754 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
3755 break;
3756 case IPC_SET:
3757 perms = MSGQ__SETATTR;
3758 break;
3759 case IPC_RMID:
3760 perms = MSGQ__DESTROY;
3761 break;
3762 default:
3763 return 0;
3764 }
3765
3766 err = ipc_has_perm(&msq->q_perm, SECCLASS_MSGQ, perms);
3767 return err;
3768}
3769
3770static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
3771{
3772 struct task_security_struct *tsec;
3773 struct ipc_security_struct *isec;
3774 struct msg_security_struct *msec;
3775 struct avc_audit_data ad;
3776 int rc;
3777
3778 tsec = current->security;
3779 isec = msq->q_perm.security;
3780 msec = msg->security;
3781
3782 /*
3783 * First time through, need to assign label to the message
3784 */
3785 if (msec->sid == SECINITSID_UNLABELED) {
3786 /*
3787 * Compute new sid based on current process and
3788 * message queue this message will be stored in
3789 */
3790 rc = security_transition_sid(tsec->sid,
3791 isec->sid,
3792 SECCLASS_MSG,
3793 &msec->sid);
3794 if (rc)
3795 return rc;
3796 }
3797
3798 AVC_AUDIT_DATA_INIT(&ad, IPC);
3799 ad.u.ipc_id = msq->q_perm.key;
3800
3801 /* Can this process write to the queue? */
3802 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
3803 MSGQ__WRITE, &ad);
3804 if (!rc)
3805 /* Can this process send the message */
3806 rc = avc_has_perm(tsec->sid, msec->sid,
3807 SECCLASS_MSG, MSG__SEND, &ad);
3808 if (!rc)
3809 /* Can the message be put in the queue? */
3810 rc = avc_has_perm(msec->sid, isec->sid,
3811 SECCLASS_MSGQ, MSGQ__ENQUEUE, &ad);
3812
3813 return rc;
3814}
3815
3816static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
3817 struct task_struct *target,
3818 long type, int mode)
3819{
3820 struct task_security_struct *tsec;
3821 struct ipc_security_struct *isec;
3822 struct msg_security_struct *msec;
3823 struct avc_audit_data ad;
3824 int rc;
3825
3826 tsec = target->security;
3827 isec = msq->q_perm.security;
3828 msec = msg->security;
3829
3830 AVC_AUDIT_DATA_INIT(&ad, IPC);
3831 ad.u.ipc_id = msq->q_perm.key;
3832
3833 rc = avc_has_perm(tsec->sid, isec->sid,
3834 SECCLASS_MSGQ, MSGQ__READ, &ad);
3835 if (!rc)
3836 rc = avc_has_perm(tsec->sid, msec->sid,
3837 SECCLASS_MSG, MSG__RECEIVE, &ad);
3838 return rc;
3839}
3840
3841/* Shared Memory security operations */
3842static int selinux_shm_alloc_security(struct shmid_kernel *shp)
3843{
3844 struct task_security_struct *tsec;
3845 struct ipc_security_struct *isec;
3846 struct avc_audit_data ad;
3847 int rc;
3848
3849 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
3850 if (rc)
3851 return rc;
3852
3853 tsec = current->security;
3854 isec = shp->shm_perm.security;
3855
3856 AVC_AUDIT_DATA_INIT(&ad, IPC);
3857 ad.u.ipc_id = shp->shm_perm.key;
3858
3859 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
3860 SHM__CREATE, &ad);
3861 if (rc) {
3862 ipc_free_security(&shp->shm_perm);
3863 return rc;
3864 }
3865 return 0;
3866}
3867
3868static void selinux_shm_free_security(struct shmid_kernel *shp)
3869{
3870 ipc_free_security(&shp->shm_perm);
3871}
3872
3873static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
3874{
3875 struct task_security_struct *tsec;
3876 struct ipc_security_struct *isec;
3877 struct avc_audit_data ad;
3878
3879 tsec = current->security;
3880 isec = shp->shm_perm.security;
3881
3882 AVC_AUDIT_DATA_INIT(&ad, IPC);
3883 ad.u.ipc_id = shp->shm_perm.key;
3884
3885 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
3886 SHM__ASSOCIATE, &ad);
3887}
3888
3889/* Note, at this point, shp is locked down */
3890static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
3891{
3892 int perms;
3893 int err;
3894
3895 switch(cmd) {
3896 case IPC_INFO:
3897 case SHM_INFO:
3898 /* No specific object, just general system-wide information. */
3899 return task_has_system(current, SYSTEM__IPC_INFO);
3900 case IPC_STAT:
3901 case SHM_STAT:
3902 perms = SHM__GETATTR | SHM__ASSOCIATE;
3903 break;
3904 case IPC_SET:
3905 perms = SHM__SETATTR;
3906 break;
3907 case SHM_LOCK:
3908 case SHM_UNLOCK:
3909 perms = SHM__LOCK;
3910 break;
3911 case IPC_RMID:
3912 perms = SHM__DESTROY;
3913 break;
3914 default:
3915 return 0;
3916 }
3917
3918 err = ipc_has_perm(&shp->shm_perm, SECCLASS_SHM, perms);
3919 return err;
3920}
3921
3922static int selinux_shm_shmat(struct shmid_kernel *shp,
3923 char __user *shmaddr, int shmflg)
3924{
3925 u32 perms;
3926 int rc;
3927
3928 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
3929 if (rc)
3930 return rc;
3931
3932 if (shmflg & SHM_RDONLY)
3933 perms = SHM__READ;
3934 else
3935 perms = SHM__READ | SHM__WRITE;
3936
3937 return ipc_has_perm(&shp->shm_perm, SECCLASS_SHM, perms);
3938}
3939
3940/* Semaphore security operations */
3941static int selinux_sem_alloc_security(struct sem_array *sma)
3942{
3943 struct task_security_struct *tsec;
3944 struct ipc_security_struct *isec;
3945 struct avc_audit_data ad;
3946 int rc;
3947
3948 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
3949 if (rc)
3950 return rc;
3951
3952 tsec = current->security;
3953 isec = sma->sem_perm.security;
3954
3955 AVC_AUDIT_DATA_INIT(&ad, IPC);
3956 ad.u.ipc_id = sma->sem_perm.key;
3957
3958 rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
3959 SEM__CREATE, &ad);
3960 if (rc) {
3961 ipc_free_security(&sma->sem_perm);
3962 return rc;
3963 }
3964 return 0;
3965}
3966
3967static void selinux_sem_free_security(struct sem_array *sma)
3968{
3969 ipc_free_security(&sma->sem_perm);
3970}
3971
3972static int selinux_sem_associate(struct sem_array *sma, int semflg)
3973{
3974 struct task_security_struct *tsec;
3975 struct ipc_security_struct *isec;
3976 struct avc_audit_data ad;
3977
3978 tsec = current->security;
3979 isec = sma->sem_perm.security;
3980
3981 AVC_AUDIT_DATA_INIT(&ad, IPC);
3982 ad.u.ipc_id = sma->sem_perm.key;
3983
3984 return avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
3985 SEM__ASSOCIATE, &ad);
3986}
3987
3988/* Note, at this point, sma is locked down */
3989static int selinux_sem_semctl(struct sem_array *sma, int cmd)
3990{
3991 int err;
3992 u32 perms;
3993
3994 switch(cmd) {
3995 case IPC_INFO:
3996 case SEM_INFO:
3997 /* No specific object, just general system-wide information. */
3998 return task_has_system(current, SYSTEM__IPC_INFO);
3999 case GETPID:
4000 case GETNCNT:
4001 case GETZCNT:
4002 perms = SEM__GETATTR;
4003 break;
4004 case GETVAL:
4005 case GETALL:
4006 perms = SEM__READ;
4007 break;
4008 case SETVAL:
4009 case SETALL:
4010 perms = SEM__WRITE;
4011 break;
4012 case IPC_RMID:
4013 perms = SEM__DESTROY;
4014 break;
4015 case IPC_SET:
4016 perms = SEM__SETATTR;
4017 break;
4018 case IPC_STAT:
4019 case SEM_STAT:
4020 perms = SEM__GETATTR | SEM__ASSOCIATE;
4021 break;
4022 default:
4023 return 0;
4024 }
4025
4026 err = ipc_has_perm(&sma->sem_perm, SECCLASS_SEM, perms);
4027 return err;
4028}
4029
4030static int selinux_sem_semop(struct sem_array *sma,
4031 struct sembuf *sops, unsigned nsops, int alter)
4032{
4033 u32 perms;
4034
4035 if (alter)
4036 perms = SEM__READ | SEM__WRITE;
4037 else
4038 perms = SEM__READ;
4039
4040 return ipc_has_perm(&sma->sem_perm, SECCLASS_SEM, perms);
4041}
4042
4043static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
4044{
4045 struct ipc_security_struct *isec = ipcp->security;
4046 u16 sclass = SECCLASS_IPC;
4047 u32 av = 0;
4048
4049 if (isec && isec->magic == SELINUX_MAGIC)
4050 sclass = isec->sclass;
4051
4052 av = 0;
4053 if (flag & S_IRUGO)
4054 av |= IPC__UNIX_READ;
4055 if (flag & S_IWUGO)
4056 av |= IPC__UNIX_WRITE;
4057
4058 if (av == 0)
4059 return 0;
4060
4061 return ipc_has_perm(ipcp, sclass, av);
4062}
4063
4064/* module stacking operations */
4065static int selinux_register_security (const char *name, struct security_operations *ops)
4066{
4067 if (secondary_ops != original_ops) {
4068 printk(KERN_INFO "%s: There is already a secondary security "
4069 "module registered.\n", __FUNCTION__);
4070 return -EINVAL;
4071 }
4072
4073 secondary_ops = ops;
4074
4075 printk(KERN_INFO "%s: Registering secondary module %s\n",
4076 __FUNCTION__,
4077 name);
4078
4079 return 0;
4080}
4081
4082static int selinux_unregister_security (const char *name, struct security_operations *ops)
4083{
4084 if (ops != secondary_ops) {
4085 printk (KERN_INFO "%s: trying to unregister a security module "
4086 "that is not registered.\n", __FUNCTION__);
4087 return -EINVAL;
4088 }
4089
4090 secondary_ops = original_ops;
4091
4092 return 0;
4093}
4094
4095static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
4096{
4097 if (inode)
4098 inode_doinit_with_dentry(inode, dentry);
4099}
4100
4101static int selinux_getprocattr(struct task_struct *p,
4102 char *name, void *value, size_t size)
4103{
4104 struct task_security_struct *tsec;
4105 u32 sid, len;
4106 char *context;
4107 int error;
4108
4109 if (current != p) {
4110 error = task_has_perm(current, p, PROCESS__GETATTR);
4111 if (error)
4112 return error;
4113 }
4114
4115 if (!size)
4116 return -ERANGE;
4117
4118 tsec = p->security;
4119
4120 if (!strcmp(name, "current"))
4121 sid = tsec->sid;
4122 else if (!strcmp(name, "prev"))
4123 sid = tsec->osid;
4124 else if (!strcmp(name, "exec"))
4125 sid = tsec->exec_sid;
4126 else if (!strcmp(name, "fscreate"))
4127 sid = tsec->create_sid;
4128 else
4129 return -EINVAL;
4130
4131 if (!sid)
4132 return 0;
4133
4134 error = security_sid_to_context(sid, &context, &len);
4135 if (error)
4136 return error;
4137 if (len > size) {
4138 kfree(context);
4139 return -ERANGE;
4140 }
4141 memcpy(value, context, len);
4142 kfree(context);
4143 return len;
4144}
4145
4146static int selinux_setprocattr(struct task_struct *p,
4147 char *name, void *value, size_t size)
4148{
4149 struct task_security_struct *tsec;
4150 u32 sid = 0;
4151 int error;
4152 char *str = value;
4153
4154 if (current != p) {
4155 /* SELinux only allows a process to change its own
4156 security attributes. */
4157 return -EACCES;
4158 }
4159
4160 /*
4161 * Basic control over ability to set these attributes at all.
4162 * current == p, but we'll pass them separately in case the
4163 * above restriction is ever removed.
4164 */
4165 if (!strcmp(name, "exec"))
4166 error = task_has_perm(current, p, PROCESS__SETEXEC);
4167 else if (!strcmp(name, "fscreate"))
4168 error = task_has_perm(current, p, PROCESS__SETFSCREATE);
4169 else if (!strcmp(name, "current"))
4170 error = task_has_perm(current, p, PROCESS__SETCURRENT);
4171 else
4172 error = -EINVAL;
4173 if (error)
4174 return error;
4175
4176 /* Obtain a SID for the context, if one was specified. */
4177 if (size && str[1] && str[1] != '\n') {
4178 if (str[size-1] == '\n') {
4179 str[size-1] = 0;
4180 size--;
4181 }
4182 error = security_context_to_sid(value, size, &sid);
4183 if (error)
4184 return error;
4185 }
4186
4187 /* Permission checking based on the specified context is
4188 performed during the actual operation (execve,
4189 open/mkdir/...), when we know the full context of the
4190 operation. See selinux_bprm_set_security for the execve
4191 checks and may_create for the file creation checks. The
4192 operation will then fail if the context is not permitted. */
4193 tsec = p->security;
4194 if (!strcmp(name, "exec"))
4195 tsec->exec_sid = sid;
4196 else if (!strcmp(name, "fscreate"))
4197 tsec->create_sid = sid;
4198 else if (!strcmp(name, "current")) {
4199 struct av_decision avd;
4200
4201 if (sid == 0)
4202 return -EINVAL;
4203
4204 /* Only allow single threaded processes to change context */
4205 if (atomic_read(&p->mm->mm_users) != 1) {
4206 struct task_struct *g, *t;
4207 struct mm_struct *mm = p->mm;
4208 read_lock(&tasklist_lock);
4209 do_each_thread(g, t)
4210 if (t->mm == mm && t != p) {
4211 read_unlock(&tasklist_lock);
4212 return -EPERM;
4213 }
4214 while_each_thread(g, t);
4215 read_unlock(&tasklist_lock);
4216 }
4217
4218 /* Check permissions for the transition. */
4219 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
4220 PROCESS__DYNTRANSITION, NULL);
4221 if (error)
4222 return error;
4223
4224 /* Check for ptracing, and update the task SID if ok.
4225 Otherwise, leave SID unchanged and fail. */
4226 task_lock(p);
4227 if (p->ptrace & PT_PTRACED) {
4228 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
4229 SECCLASS_PROCESS,
4230 PROCESS__PTRACE, &avd);
4231 if (!error)
4232 tsec->sid = sid;
4233 task_unlock(p);
4234 avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
4235 PROCESS__PTRACE, &avd, error, NULL);
4236 if (error)
4237 return error;
4238 } else {
4239 tsec->sid = sid;
4240 task_unlock(p);
4241 }
4242 }
4243 else
4244 return -EINVAL;
4245
4246 return size;
4247}
4248
4249static struct security_operations selinux_ops = {
4250 .ptrace = selinux_ptrace,
4251 .capget = selinux_capget,
4252 .capset_check = selinux_capset_check,
4253 .capset_set = selinux_capset_set,
4254 .sysctl = selinux_sysctl,
4255 .capable = selinux_capable,
4256 .quotactl = selinux_quotactl,
4257 .quota_on = selinux_quota_on,
4258 .syslog = selinux_syslog,
4259 .vm_enough_memory = selinux_vm_enough_memory,
4260
4261 .netlink_send = selinux_netlink_send,
4262 .netlink_recv = selinux_netlink_recv,
4263
4264 .bprm_alloc_security = selinux_bprm_alloc_security,
4265 .bprm_free_security = selinux_bprm_free_security,
4266 .bprm_apply_creds = selinux_bprm_apply_creds,
4267 .bprm_post_apply_creds = selinux_bprm_post_apply_creds,
4268 .bprm_set_security = selinux_bprm_set_security,
4269 .bprm_check_security = selinux_bprm_check_security,
4270 .bprm_secureexec = selinux_bprm_secureexec,
4271
4272 .sb_alloc_security = selinux_sb_alloc_security,
4273 .sb_free_security = selinux_sb_free_security,
4274 .sb_copy_data = selinux_sb_copy_data,
4275 .sb_kern_mount = selinux_sb_kern_mount,
4276 .sb_statfs = selinux_sb_statfs,
4277 .sb_mount = selinux_mount,
4278 .sb_umount = selinux_umount,
4279
4280 .inode_alloc_security = selinux_inode_alloc_security,
4281 .inode_free_security = selinux_inode_free_security,
4282 .inode_create = selinux_inode_create,
4283 .inode_post_create = selinux_inode_post_create,
4284 .inode_link = selinux_inode_link,
4285 .inode_post_link = selinux_inode_post_link,
4286 .inode_unlink = selinux_inode_unlink,
4287 .inode_symlink = selinux_inode_symlink,
4288 .inode_post_symlink = selinux_inode_post_symlink,
4289 .inode_mkdir = selinux_inode_mkdir,
4290 .inode_post_mkdir = selinux_inode_post_mkdir,
4291 .inode_rmdir = selinux_inode_rmdir,
4292 .inode_mknod = selinux_inode_mknod,
4293 .inode_post_mknod = selinux_inode_post_mknod,
4294 .inode_rename = selinux_inode_rename,
4295 .inode_post_rename = selinux_inode_post_rename,
4296 .inode_readlink = selinux_inode_readlink,
4297 .inode_follow_link = selinux_inode_follow_link,
4298 .inode_permission = selinux_inode_permission,
4299 .inode_setattr = selinux_inode_setattr,
4300 .inode_getattr = selinux_inode_getattr,
4301 .inode_setxattr = selinux_inode_setxattr,
4302 .inode_post_setxattr = selinux_inode_post_setxattr,
4303 .inode_getxattr = selinux_inode_getxattr,
4304 .inode_listxattr = selinux_inode_listxattr,
4305 .inode_removexattr = selinux_inode_removexattr,
4306 .inode_getsecurity = selinux_inode_getsecurity,
4307 .inode_setsecurity = selinux_inode_setsecurity,
4308 .inode_listsecurity = selinux_inode_listsecurity,
4309
4310 .file_permission = selinux_file_permission,
4311 .file_alloc_security = selinux_file_alloc_security,
4312 .file_free_security = selinux_file_free_security,
4313 .file_ioctl = selinux_file_ioctl,
4314 .file_mmap = selinux_file_mmap,
4315 .file_mprotect = selinux_file_mprotect,
4316 .file_lock = selinux_file_lock,
4317 .file_fcntl = selinux_file_fcntl,
4318 .file_set_fowner = selinux_file_set_fowner,
4319 .file_send_sigiotask = selinux_file_send_sigiotask,
4320 .file_receive = selinux_file_receive,
4321
4322 .task_create = selinux_task_create,
4323 .task_alloc_security = selinux_task_alloc_security,
4324 .task_free_security = selinux_task_free_security,
4325 .task_setuid = selinux_task_setuid,
4326 .task_post_setuid = selinux_task_post_setuid,
4327 .task_setgid = selinux_task_setgid,
4328 .task_setpgid = selinux_task_setpgid,
4329 .task_getpgid = selinux_task_getpgid,
4330 .task_getsid = selinux_task_getsid,
4331 .task_setgroups = selinux_task_setgroups,
4332 .task_setnice = selinux_task_setnice,
4333 .task_setrlimit = selinux_task_setrlimit,
4334 .task_setscheduler = selinux_task_setscheduler,
4335 .task_getscheduler = selinux_task_getscheduler,
4336 .task_kill = selinux_task_kill,
4337 .task_wait = selinux_task_wait,
4338 .task_prctl = selinux_task_prctl,
4339 .task_reparent_to_init = selinux_task_reparent_to_init,
4340 .task_to_inode = selinux_task_to_inode,
4341
4342 .ipc_permission = selinux_ipc_permission,
4343
4344 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
4345 .msg_msg_free_security = selinux_msg_msg_free_security,
4346
4347 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
4348 .msg_queue_free_security = selinux_msg_queue_free_security,
4349 .msg_queue_associate = selinux_msg_queue_associate,
4350 .msg_queue_msgctl = selinux_msg_queue_msgctl,
4351 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
4352 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
4353
4354 .shm_alloc_security = selinux_shm_alloc_security,
4355 .shm_free_security = selinux_shm_free_security,
4356 .shm_associate = selinux_shm_associate,
4357 .shm_shmctl = selinux_shm_shmctl,
4358 .shm_shmat = selinux_shm_shmat,
4359
4360 .sem_alloc_security = selinux_sem_alloc_security,
4361 .sem_free_security = selinux_sem_free_security,
4362 .sem_associate = selinux_sem_associate,
4363 .sem_semctl = selinux_sem_semctl,
4364 .sem_semop = selinux_sem_semop,
4365
4366 .register_security = selinux_register_security,
4367 .unregister_security = selinux_unregister_security,
4368
4369 .d_instantiate = selinux_d_instantiate,
4370
4371 .getprocattr = selinux_getprocattr,
4372 .setprocattr = selinux_setprocattr,
4373
4374#ifdef CONFIG_SECURITY_NETWORK
4375 .unix_stream_connect = selinux_socket_unix_stream_connect,
4376 .unix_may_send = selinux_socket_unix_may_send,
4377
4378 .socket_create = selinux_socket_create,
4379 .socket_post_create = selinux_socket_post_create,
4380 .socket_bind = selinux_socket_bind,
4381 .socket_connect = selinux_socket_connect,
4382 .socket_listen = selinux_socket_listen,
4383 .socket_accept = selinux_socket_accept,
4384 .socket_sendmsg = selinux_socket_sendmsg,
4385 .socket_recvmsg = selinux_socket_recvmsg,
4386 .socket_getsockname = selinux_socket_getsockname,
4387 .socket_getpeername = selinux_socket_getpeername,
4388 .socket_getsockopt = selinux_socket_getsockopt,
4389 .socket_setsockopt = selinux_socket_setsockopt,
4390 .socket_shutdown = selinux_socket_shutdown,
4391 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
4392 .socket_getpeersec = selinux_socket_getpeersec,
4393 .sk_alloc_security = selinux_sk_alloc_security,
4394 .sk_free_security = selinux_sk_free_security,
4395#endif
4396};
4397
4398static __init int selinux_init(void)
4399{
4400 struct task_security_struct *tsec;
4401
4402 if (!selinux_enabled) {
4403 printk(KERN_INFO "SELinux: Disabled at boot.\n");
4404 return 0;
4405 }
4406
4407 printk(KERN_INFO "SELinux: Initializing.\n");
4408
4409 /* Set the security state for the initial task. */
4410 if (task_alloc_security(current))
4411 panic("SELinux: Failed to initialize initial task.\n");
4412 tsec = current->security;
4413 tsec->osid = tsec->sid = SECINITSID_KERNEL;
4414
4415 avc_init();
4416
4417 original_ops = secondary_ops = security_ops;
4418 if (!secondary_ops)
4419 panic ("SELinux: No initial security operations\n");
4420 if (register_security (&selinux_ops))
4421 panic("SELinux: Unable to register with kernel.\n");
4422
4423 if (selinux_enforcing) {
4424 printk(KERN_INFO "SELinux: Starting in enforcing mode\n");
4425 } else {
4426 printk(KERN_INFO "SELinux: Starting in permissive mode\n");
4427 }
4428 return 0;
4429}
4430
4431void selinux_complete_init(void)
4432{
4433 printk(KERN_INFO "SELinux: Completing initialization.\n");
4434
4435 /* Set up any superblocks initialized prior to the policy load. */
4436 printk(KERN_INFO "SELinux: Setting up existing superblocks.\n");
4437 spin_lock(&sb_security_lock);
4438next_sb:
4439 if (!list_empty(&superblock_security_head)) {
4440 struct superblock_security_struct *sbsec =
4441 list_entry(superblock_security_head.next,
4442 struct superblock_security_struct,
4443 list);
4444 struct super_block *sb = sbsec->sb;
4445 spin_lock(&sb_lock);
4446 sb->s_count++;
4447 spin_unlock(&sb_lock);
4448 spin_unlock(&sb_security_lock);
4449 down_read(&sb->s_umount);
4450 if (sb->s_root)
4451 superblock_doinit(sb, NULL);
4452 drop_super(sb);
4453 spin_lock(&sb_security_lock);
4454 list_del_init(&sbsec->list);
4455 goto next_sb;
4456 }
4457 spin_unlock(&sb_security_lock);
4458}
4459
4460/* SELinux requires early initialization in order to label
4461 all processes and objects when they are created. */
4462security_initcall(selinux_init);
4463
4464#if defined(CONFIG_SECURITY_NETWORK) && defined(CONFIG_NETFILTER)
4465
4466static struct nf_hook_ops selinux_ipv4_op = {
4467 .hook = selinux_ipv4_postroute_last,
4468 .owner = THIS_MODULE,
4469 .pf = PF_INET,
4470 .hooknum = NF_IP_POST_ROUTING,
4471 .priority = NF_IP_PRI_SELINUX_LAST,
4472};
4473
4474#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4475
4476static struct nf_hook_ops selinux_ipv6_op = {
4477 .hook = selinux_ipv6_postroute_last,
4478 .owner = THIS_MODULE,
4479 .pf = PF_INET6,
4480 .hooknum = NF_IP6_POST_ROUTING,
4481 .priority = NF_IP6_PRI_SELINUX_LAST,
4482};
4483
4484#endif /* IPV6 */
4485
4486static int __init selinux_nf_ip_init(void)
4487{
4488 int err = 0;
4489
4490 if (!selinux_enabled)
4491 goto out;
4492
4493 printk(KERN_INFO "SELinux: Registering netfilter hooks\n");
4494
4495 err = nf_register_hook(&selinux_ipv4_op);
4496 if (err)
4497 panic("SELinux: nf_register_hook for IPv4: error %d\n", err);
4498
4499#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4500
4501 err = nf_register_hook(&selinux_ipv6_op);
4502 if (err)
4503 panic("SELinux: nf_register_hook for IPv6: error %d\n", err);
4504
4505#endif /* IPV6 */
4506out:
4507 return err;
4508}
4509
4510__initcall(selinux_nf_ip_init);
4511
4512#ifdef CONFIG_SECURITY_SELINUX_DISABLE
4513static void selinux_nf_ip_exit(void)
4514{
4515 printk(KERN_INFO "SELinux: Unregistering netfilter hooks\n");
4516
4517 nf_unregister_hook(&selinux_ipv4_op);
4518#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4519 nf_unregister_hook(&selinux_ipv6_op);
4520#endif /* IPV6 */
4521}
4522#endif
4523
4524#else /* CONFIG_SECURITY_NETWORK && CONFIG_NETFILTER */
4525
4526#ifdef CONFIG_SECURITY_SELINUX_DISABLE
4527#define selinux_nf_ip_exit()
4528#endif
4529
4530#endif /* CONFIG_SECURITY_NETWORK && CONFIG_NETFILTER */
4531
4532#ifdef CONFIG_SECURITY_SELINUX_DISABLE
4533int selinux_disable(void)
4534{
4535 extern void exit_sel_fs(void);
4536 static int selinux_disabled = 0;
4537
4538 if (ss_initialized) {
4539 /* Not permitted after initial policy load. */
4540 return -EINVAL;
4541 }
4542
4543 if (selinux_disabled) {
4544 /* Only do this once. */
4545 return -EINVAL;
4546 }
4547
4548 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
4549
4550 selinux_disabled = 1;
4551
4552 /* Reset security_ops to the secondary module, dummy or capability. */
4553 security_ops = secondary_ops;
4554
4555 /* Unregister netfilter hooks. */
4556 selinux_nf_ip_exit();
4557
4558 /* Unregister selinuxfs. */
4559 exit_sel_fs();
4560
4561 return 0;
4562}
4563#endif
4564
4565
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h
new file mode 100644
index 00000000000..9facb27822a
--- /dev/null
+++ b/security/selinux/include/av_inherit.h
@@ -0,0 +1,30 @@
1/* This file is automatically generated. Do not edit. */
2 S_(SECCLASS_DIR, file, 0x00020000UL)
3 S_(SECCLASS_FILE, file, 0x00020000UL)
4 S_(SECCLASS_LNK_FILE, file, 0x00020000UL)
5 S_(SECCLASS_CHR_FILE, file, 0x00020000UL)
6 S_(SECCLASS_BLK_FILE, file, 0x00020000UL)
7 S_(SECCLASS_SOCK_FILE, file, 0x00020000UL)
8 S_(SECCLASS_FIFO_FILE, file, 0x00020000UL)
9 S_(SECCLASS_SOCKET, socket, 0x00400000UL)
10 S_(SECCLASS_TCP_SOCKET, socket, 0x00400000UL)
11 S_(SECCLASS_UDP_SOCKET, socket, 0x00400000UL)
12 S_(SECCLASS_RAWIP_SOCKET, socket, 0x00400000UL)
13 S_(SECCLASS_NETLINK_SOCKET, socket, 0x00400000UL)
14 S_(SECCLASS_PACKET_SOCKET, socket, 0x00400000UL)
15 S_(SECCLASS_KEY_SOCKET, socket, 0x00400000UL)
16 S_(SECCLASS_UNIX_STREAM_SOCKET, socket, 0x00400000UL)
17 S_(SECCLASS_UNIX_DGRAM_SOCKET, socket, 0x00400000UL)
18 S_(SECCLASS_IPC, ipc, 0x00000200UL)
19 S_(SECCLASS_SEM, ipc, 0x00000200UL)
20 S_(SECCLASS_MSGQ, ipc, 0x00000200UL)
21 S_(SECCLASS_SHM, ipc, 0x00000200UL)
22 S_(SECCLASS_NETLINK_ROUTE_SOCKET, socket, 0x00400000UL)
23 S_(SECCLASS_NETLINK_FIREWALL_SOCKET, socket, 0x00400000UL)
24 S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, socket, 0x00400000UL)
25 S_(SECCLASS_NETLINK_NFLOG_SOCKET, socket, 0x00400000UL)
26 S_(SECCLASS_NETLINK_XFRM_SOCKET, socket, 0x00400000UL)
27 S_(SECCLASS_NETLINK_SELINUX_SOCKET, socket, 0x00400000UL)
28 S_(SECCLASS_NETLINK_AUDIT_SOCKET, socket, 0x00400000UL)
29 S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL)
30 S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL)
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
new file mode 100644
index 00000000000..903e8b3cc2e
--- /dev/null
+++ b/security/selinux/include/av_perm_to_string.h
@@ -0,0 +1,232 @@
1/* This file is automatically generated. Do not edit. */
2 S_(SECCLASS_FILESYSTEM, FILESYSTEM__MOUNT, "mount")
3 S_(SECCLASS_FILESYSTEM, FILESYSTEM__REMOUNT, "remount")
4 S_(SECCLASS_FILESYSTEM, FILESYSTEM__UNMOUNT, "unmount")
5 S_(SECCLASS_FILESYSTEM, FILESYSTEM__GETATTR, "getattr")
6 S_(SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, "relabelfrom")
7 S_(SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, "relabelto")
8 S_(SECCLASS_FILESYSTEM, FILESYSTEM__TRANSITION, "transition")
9 S_(SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, "associate")
10 S_(SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAMOD, "quotamod")
11 S_(SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAGET, "quotaget")
12 S_(SECCLASS_DIR, DIR__ADD_NAME, "add_name")
13 S_(SECCLASS_DIR, DIR__REMOVE_NAME, "remove_name")
14 S_(SECCLASS_DIR, DIR__REPARENT, "reparent")
15 S_(SECCLASS_DIR, DIR__SEARCH, "search")
16 S_(SECCLASS_DIR, DIR__RMDIR, "rmdir")
17 S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans")
18 S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
19 S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
20 S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans")
21 S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint")
22 S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
23 S_(SECCLASS_FD, FD__USE, "use")
24 S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto")
25 S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn")
26 S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__ACCEPTFROM, "acceptfrom")
27 S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NODE_BIND, "node_bind")
28 S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NAME_CONNECT, "name_connect")
29 S_(SECCLASS_UDP_SOCKET, UDP_SOCKET__NODE_BIND, "node_bind")
30 S_(SECCLASS_RAWIP_SOCKET, RAWIP_SOCKET__NODE_BIND, "node_bind")
31 S_(SECCLASS_NODE, NODE__TCP_RECV, "tcp_recv")
32 S_(SECCLASS_NODE, NODE__TCP_SEND, "tcp_send")
33 S_(SECCLASS_NODE, NODE__UDP_RECV, "udp_recv")
34 S_(SECCLASS_NODE, NODE__UDP_SEND, "udp_send")
35 S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv")
36 S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send")
37 S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest")
38 S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv")
39 S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send")
40 S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv")
41 S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send")
42 S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv")
43 S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send")
44 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto")
45 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn")
46 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom")
47 S_(SECCLASS_PROCESS, PROCESS__FORK, "fork")
48 S_(SECCLASS_PROCESS, PROCESS__TRANSITION, "transition")
49 S_(SECCLASS_PROCESS, PROCESS__SIGCHLD, "sigchld")
50 S_(SECCLASS_PROCESS, PROCESS__SIGKILL, "sigkill")
51 S_(SECCLASS_PROCESS, PROCESS__SIGSTOP, "sigstop")
52 S_(SECCLASS_PROCESS, PROCESS__SIGNULL, "signull")
53 S_(SECCLASS_PROCESS, PROCESS__SIGNAL, "signal")
54 S_(SECCLASS_PROCESS, PROCESS__PTRACE, "ptrace")
55 S_(SECCLASS_PROCESS, PROCESS__GETSCHED, "getsched")
56 S_(SECCLASS_PROCESS, PROCESS__SETSCHED, "setsched")
57 S_(SECCLASS_PROCESS, PROCESS__GETSESSION, "getsession")
58 S_(SECCLASS_PROCESS, PROCESS__GETPGID, "getpgid")
59 S_(SECCLASS_PROCESS, PROCESS__SETPGID, "setpgid")
60 S_(SECCLASS_PROCESS, PROCESS__GETCAP, "getcap")
61 S_(SECCLASS_PROCESS, PROCESS__SETCAP, "setcap")
62 S_(SECCLASS_PROCESS, PROCESS__SHARE, "share")
63 S_(SECCLASS_PROCESS, PROCESS__GETATTR, "getattr")
64 S_(SECCLASS_PROCESS, PROCESS__SETEXEC, "setexec")
65 S_(SECCLASS_PROCESS, PROCESS__SETFSCREATE, "setfscreate")
66 S_(SECCLASS_PROCESS, PROCESS__NOATSECURE, "noatsecure")
67 S_(SECCLASS_PROCESS, PROCESS__SIGINH, "siginh")
68 S_(SECCLASS_PROCESS, PROCESS__SETRLIMIT, "setrlimit")
69 S_(SECCLASS_PROCESS, PROCESS__RLIMITINH, "rlimitinh")
70 S_(SECCLASS_PROCESS, PROCESS__DYNTRANSITION, "dyntransition")
71 S_(SECCLASS_PROCESS, PROCESS__SETCURRENT, "setcurrent")
72 S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem")
73 S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue")
74 S_(SECCLASS_MSG, MSG__SEND, "send")
75 S_(SECCLASS_MSG, MSG__RECEIVE, "receive")
76 S_(SECCLASS_SHM, SHM__LOCK, "lock")
77 S_(SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av")
78 S_(SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, "compute_create")
79 S_(SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, "compute_member")
80 S_(SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, "check_context")
81 S_(SECCLASS_SECURITY, SECURITY__LOAD_POLICY, "load_policy")
82 S_(SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, "compute_relabel")
83 S_(SECCLASS_SECURITY, SECURITY__COMPUTE_USER, "compute_user")
84 S_(SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce")
85 S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool")
86 S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam")
87 S_(SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, "setcheckreqprot")
88 S_(SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info")
89 S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read")
90 S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod")
91 S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console")
92 S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown")
93 S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override")
94 S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search")
95 S_(SECCLASS_CAPABILITY, CAPABILITY__FOWNER, "fowner")
96 S_(SECCLASS_CAPABILITY, CAPABILITY__FSETID, "fsetid")
97 S_(SECCLASS_CAPABILITY, CAPABILITY__KILL, "kill")
98 S_(SECCLASS_CAPABILITY, CAPABILITY__SETGID, "setgid")
99 S_(SECCLASS_CAPABILITY, CAPABILITY__SETUID, "setuid")
100 S_(SECCLASS_CAPABILITY, CAPABILITY__SETPCAP, "setpcap")
101 S_(SECCLASS_CAPABILITY, CAPABILITY__LINUX_IMMUTABLE, "linux_immutable")
102 S_(SECCLASS_CAPABILITY, CAPABILITY__NET_BIND_SERVICE, "net_bind_service")
103 S_(SECCLASS_CAPABILITY, CAPABILITY__NET_BROADCAST, "net_broadcast")
104 S_(SECCLASS_CAPABILITY, CAPABILITY__NET_ADMIN, "net_admin")
105 S_(SECCLASS_CAPABILITY, CAPABILITY__NET_RAW, "net_raw")
106 S_(SECCLASS_CAPABILITY, CAPABILITY__IPC_LOCK, "ipc_lock")
107 S_(SECCLASS_CAPABILITY, CAPABILITY__IPC_OWNER, "ipc_owner")
108 S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_MODULE, "sys_module")
109 S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_RAWIO, "sys_rawio")
110 S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_CHROOT, "sys_chroot")
111 S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_PTRACE, "sys_ptrace")
112 S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_PACCT, "sys_pacct")
113 S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_ADMIN, "sys_admin")
114 S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_BOOT, "sys_boot")
115 S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_NICE, "sys_nice")
116 S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_RESOURCE, "sys_resource")
117 S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_TIME, "sys_time")
118 S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_TTY_CONFIG, "sys_tty_config")
119 S_(SECCLASS_CAPABILITY, CAPABILITY__MKNOD, "mknod")
120 S_(SECCLASS_CAPABILITY, CAPABILITY__LEASE, "lease")
121 S_(SECCLASS_PASSWD, PASSWD__PASSWD, "passwd")
122 S_(SECCLASS_PASSWD, PASSWD__CHFN, "chfn")
123 S_(SECCLASS_PASSWD, PASSWD__CHSH, "chsh")
124 S_(SECCLASS_PASSWD, PASSWD__ROOTOK, "rootok")
125 S_(SECCLASS_PASSWD, PASSWD__CRONTAB, "crontab")
126 S_(SECCLASS_DRAWABLE, DRAWABLE__CREATE, "create")
127 S_(SECCLASS_DRAWABLE, DRAWABLE__DESTROY, "destroy")
128 S_(SECCLASS_DRAWABLE, DRAWABLE__DRAW, "draw")
129 S_(SECCLASS_DRAWABLE, DRAWABLE__COPY, "copy")
130 S_(SECCLASS_DRAWABLE, DRAWABLE__GETATTR, "getattr")
131 S_(SECCLASS_GC, GC__CREATE, "create")
132 S_(SECCLASS_GC, GC__FREE, "free")
133 S_(SECCLASS_GC, GC__GETATTR, "getattr")
134 S_(SECCLASS_GC, GC__SETATTR, "setattr")
135 S_(SECCLASS_WINDOW, WINDOW__ADDCHILD, "addchild")
136 S_(SECCLASS_WINDOW, WINDOW__CREATE, "create")
137 S_(SECCLASS_WINDOW, WINDOW__DESTROY, "destroy")
138 S_(SECCLASS_WINDOW, WINDOW__MAP, "map")
139 S_(SECCLASS_WINDOW, WINDOW__UNMAP, "unmap")
140 S_(SECCLASS_WINDOW, WINDOW__CHSTACK, "chstack")
141 S_(SECCLASS_WINDOW, WINDOW__CHPROPLIST, "chproplist")
142 S_(SECCLASS_WINDOW, WINDOW__CHPROP, "chprop")
143 S_(SECCLASS_WINDOW, WINDOW__LISTPROP, "listprop")
144 S_(SECCLASS_WINDOW, WINDOW__GETATTR, "getattr")
145 S_(SECCLASS_WINDOW, WINDOW__SETATTR, "setattr")
146 S_(SECCLASS_WINDOW, WINDOW__SETFOCUS, "setfocus")
147 S_(SECCLASS_WINDOW, WINDOW__MOVE, "move")
148 S_(SECCLASS_WINDOW, WINDOW__CHSELECTION, "chselection")
149 S_(SECCLASS_WINDOW, WINDOW__CHPARENT, "chparent")
150 S_(SECCLASS_WINDOW, WINDOW__CTRLLIFE, "ctrllife")
151 S_(SECCLASS_WINDOW, WINDOW__ENUMERATE, "enumerate")
152 S_(SECCLASS_WINDOW, WINDOW__TRANSPARENT, "transparent")
153 S_(SECCLASS_WINDOW, WINDOW__MOUSEMOTION, "mousemotion")
154 S_(SECCLASS_WINDOW, WINDOW__CLIENTCOMEVENT, "clientcomevent")
155 S_(SECCLASS_WINDOW, WINDOW__INPUTEVENT, "inputevent")
156 S_(SECCLASS_WINDOW, WINDOW__DRAWEVENT, "drawevent")
157 S_(SECCLASS_WINDOW, WINDOW__WINDOWCHANGEEVENT, "windowchangeevent")
158 S_(SECCLASS_WINDOW, WINDOW__WINDOWCHANGEREQUEST, "windowchangerequest")
159 S_(SECCLASS_WINDOW, WINDOW__SERVERCHANGEEVENT, "serverchangeevent")
160 S_(SECCLASS_WINDOW, WINDOW__EXTENSIONEVENT, "extensionevent")
161 S_(SECCLASS_FONT, FONT__LOAD, "load")
162 S_(SECCLASS_FONT, FONT__FREE, "free")
163 S_(SECCLASS_FONT, FONT__GETATTR, "getattr")
164 S_(SECCLASS_FONT, FONT__USE, "use")
165 S_(SECCLASS_COLORMAP, COLORMAP__CREATE, "create")
166 S_(SECCLASS_COLORMAP, COLORMAP__FREE, "free")
167 S_(SECCLASS_COLORMAP, COLORMAP__INSTALL, "install")
168 S_(SECCLASS_COLORMAP, COLORMAP__UNINSTALL, "uninstall")
169 S_(SECCLASS_COLORMAP, COLORMAP__LIST, "list")
170 S_(SECCLASS_COLORMAP, COLORMAP__READ, "read")
171 S_(SECCLASS_COLORMAP, COLORMAP__STORE, "store")
172 S_(SECCLASS_COLORMAP, COLORMAP__GETATTR, "getattr")
173 S_(SECCLASS_COLORMAP, COLORMAP__SETATTR, "setattr")
174 S_(SECCLASS_PROPERTY, PROPERTY__CREATE, "create")
175 S_(SECCLASS_PROPERTY, PROPERTY__FREE, "free")
176 S_(SECCLASS_PROPERTY, PROPERTY__READ, "read")
177 S_(SECCLASS_PROPERTY, PROPERTY__WRITE, "write")
178 S_(SECCLASS_CURSOR, CURSOR__CREATE, "create")
179 S_(SECCLASS_CURSOR, CURSOR__CREATEGLYPH, "createglyph")
180 S_(SECCLASS_CURSOR, CURSOR__FREE, "free")
181 S_(SECCLASS_CURSOR, CURSOR__ASSIGN, "assign")
182 S_(SECCLASS_CURSOR, CURSOR__SETATTR, "setattr")
183 S_(SECCLASS_XCLIENT, XCLIENT__KILL, "kill")
184 S_(SECCLASS_XINPUT, XINPUT__LOOKUP, "lookup")
185 S_(SECCLASS_XINPUT, XINPUT__GETATTR, "getattr")
186 S_(SECCLASS_XINPUT, XINPUT__SETATTR, "setattr")
187 S_(SECCLASS_XINPUT, XINPUT__SETFOCUS, "setfocus")
188 S_(SECCLASS_XINPUT, XINPUT__WARPPOINTER, "warppointer")
189 S_(SECCLASS_XINPUT, XINPUT__ACTIVEGRAB, "activegrab")
190 S_(SECCLASS_XINPUT, XINPUT__PASSIVEGRAB, "passivegrab")
191 S_(SECCLASS_XINPUT, XINPUT__UNGRAB, "ungrab")
192 S_(SECCLASS_XINPUT, XINPUT__BELL, "bell")
193 S_(SECCLASS_XINPUT, XINPUT__MOUSEMOTION, "mousemotion")
194 S_(SECCLASS_XINPUT, XINPUT__RELABELINPUT, "relabelinput")
195 S_(SECCLASS_XSERVER, XSERVER__SCREENSAVER, "screensaver")
196 S_(SECCLASS_XSERVER, XSERVER__GETHOSTLIST, "gethostlist")
197 S_(SECCLASS_XSERVER, XSERVER__SETHOSTLIST, "sethostlist")
198 S_(SECCLASS_XSERVER, XSERVER__GETFONTPATH, "getfontpath")
199 S_(SECCLASS_XSERVER, XSERVER__SETFONTPATH, "setfontpath")
200 S_(SECCLASS_XSERVER, XSERVER__GETATTR, "getattr")
201 S_(SECCLASS_XSERVER, XSERVER__GRAB, "grab")
202 S_(SECCLASS_XSERVER, XSERVER__UNGRAB, "ungrab")
203 S_(SECCLASS_XEXTENSION, XEXTENSION__QUERY, "query")
204 S_(SECCLASS_XEXTENSION, XEXTENSION__USE, "use")
205 S_(SECCLASS_PAX, PAX__PAGEEXEC, "pageexec")
206 S_(SECCLASS_PAX, PAX__EMUTRAMP, "emutramp")
207 S_(SECCLASS_PAX, PAX__MPROTECT, "mprotect")
208 S_(SECCLASS_PAX, PAX__RANDMMAP, "randmmap")
209 S_(SECCLASS_PAX, PAX__RANDEXEC, "randexec")
210 S_(SECCLASS_PAX, PAX__SEGMEXEC, "segmexec")
211 S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_READ, "nlmsg_read")
212 S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_WRITE, "nlmsg_write")
213 S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_READ, "nlmsg_read")
214 S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE, "nlmsg_write")
215 S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_READ, "nlmsg_read")
216 S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE, "nlmsg_write")
217 S_(SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_READ, "nlmsg_read")
218 S_(SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_WRITE, "nlmsg_write")
219 S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READ, "nlmsg_read")
220 S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write")
221 S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read")
222 S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write")
223 S_(SECCLASS_DBUS, DBUS__ACQUIRE_SVC, "acquire_svc")
224 S_(SECCLASS_DBUS, DBUS__SEND_MSG, "send_msg")
225 S_(SECCLASS_NSCD, NSCD__GETPWD, "getpwd")
226 S_(SECCLASS_NSCD, NSCD__GETGRP, "getgrp")
227 S_(SECCLASS_NSCD, NSCD__GETHOST, "gethost")
228 S_(SECCLASS_NSCD, NSCD__GETSTAT, "getstat")
229 S_(SECCLASS_NSCD, NSCD__ADMIN, "admin")
230 S_(SECCLASS_NSCD, NSCD__SHMEMPWD, "shmempwd")
231 S_(SECCLASS_NSCD, NSCD__SHMEMGRP, "shmemgrp")
232 S_(SECCLASS_NSCD, NSCD__SHMEMHOST, "shmemhost")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
new file mode 100644
index 00000000000..b0a12ac8f7e
--- /dev/null
+++ b/security/selinux/include/av_permissions.h
@@ -0,0 +1,902 @@
1/* This file is automatically generated. Do not edit. */
2#define COMMON_FILE__IOCTL 0x00000001UL
3#define COMMON_FILE__READ 0x00000002UL
4#define COMMON_FILE__WRITE 0x00000004UL
5#define COMMON_FILE__CREATE 0x00000008UL
6#define COMMON_FILE__GETATTR 0x00000010UL
7#define COMMON_FILE__SETATTR 0x00000020UL
8#define COMMON_FILE__LOCK 0x00000040UL
9#define COMMON_FILE__RELABELFROM 0x00000080UL
10#define COMMON_FILE__RELABELTO 0x00000100UL
11#define COMMON_FILE__APPEND 0x00000200UL
12#define COMMON_FILE__UNLINK 0x00000400UL
13#define COMMON_FILE__LINK 0x00000800UL
14#define COMMON_FILE__RENAME 0x00001000UL
15#define COMMON_FILE__EXECUTE 0x00002000UL
16#define COMMON_FILE__SWAPON 0x00004000UL
17#define COMMON_FILE__QUOTAON 0x00008000UL
18#define COMMON_FILE__MOUNTON 0x00010000UL
19
20#define COMMON_SOCKET__IOCTL 0x00000001UL
21#define COMMON_SOCKET__READ 0x00000002UL
22#define COMMON_SOCKET__WRITE 0x00000004UL
23#define COMMON_SOCKET__CREATE 0x00000008UL
24#define COMMON_SOCKET__GETATTR 0x00000010UL
25#define COMMON_SOCKET__SETATTR 0x00000020UL
26#define COMMON_SOCKET__LOCK 0x00000040UL
27#define COMMON_SOCKET__RELABELFROM 0x00000080UL
28#define COMMON_SOCKET__RELABELTO 0x00000100UL
29#define COMMON_SOCKET__APPEND 0x00000200UL
30#define COMMON_SOCKET__BIND 0x00000400UL
31#define COMMON_SOCKET__CONNECT 0x00000800UL
32#define COMMON_SOCKET__LISTEN 0x00001000UL
33#define COMMON_SOCKET__ACCEPT 0x00002000UL
34#define COMMON_SOCKET__GETOPT 0x00004000UL
35#define COMMON_SOCKET__SETOPT 0x00008000UL
36#define COMMON_SOCKET__SHUTDOWN 0x00010000UL
37#define COMMON_SOCKET__RECVFROM 0x00020000UL
38#define COMMON_SOCKET__SENDTO 0x00040000UL
39#define COMMON_SOCKET__RECV_MSG 0x00080000UL
40#define COMMON_SOCKET__SEND_MSG 0x00100000UL
41#define COMMON_SOCKET__NAME_BIND 0x00200000UL
42
43#define COMMON_IPC__CREATE 0x00000001UL
44#define COMMON_IPC__DESTROY 0x00000002UL
45#define COMMON_IPC__GETATTR 0x00000004UL
46#define COMMON_IPC__SETATTR 0x00000008UL
47#define COMMON_IPC__READ 0x00000010UL
48#define COMMON_IPC__WRITE 0x00000020UL
49#define COMMON_IPC__ASSOCIATE 0x00000040UL
50#define COMMON_IPC__UNIX_READ 0x00000080UL
51#define COMMON_IPC__UNIX_WRITE 0x00000100UL
52
53#define FILESYSTEM__MOUNT 0x00000001UL
54#define FILESYSTEM__REMOUNT 0x00000002UL
55#define FILESYSTEM__UNMOUNT 0x00000004UL
56#define FILESYSTEM__GETATTR 0x00000008UL
57#define FILESYSTEM__RELABELFROM 0x00000010UL
58#define FILESYSTEM__RELABELTO 0x00000020UL
59#define FILESYSTEM__TRANSITION 0x00000040UL
60#define FILESYSTEM__ASSOCIATE 0x00000080UL
61#define FILESYSTEM__QUOTAMOD 0x00000100UL
62#define FILESYSTEM__QUOTAGET 0x00000200UL
63
64#define DIR__IOCTL 0x00000001UL
65#define DIR__READ 0x00000002UL
66#define DIR__WRITE 0x00000004UL
67#define DIR__CREATE 0x00000008UL
68#define DIR__GETATTR 0x00000010UL
69#define DIR__SETATTR 0x00000020UL
70#define DIR__LOCK 0x00000040UL
71#define DIR__RELABELFROM 0x00000080UL
72#define DIR__RELABELTO 0x00000100UL
73#define DIR__APPEND 0x00000200UL
74#define DIR__UNLINK 0x00000400UL
75#define DIR__LINK 0x00000800UL
76#define DIR__RENAME 0x00001000UL
77#define DIR__EXECUTE 0x00002000UL
78#define DIR__SWAPON 0x00004000UL
79#define DIR__QUOTAON 0x00008000UL
80#define DIR__MOUNTON 0x00010000UL
81
82#define DIR__ADD_NAME 0x00020000UL
83#define DIR__REMOVE_NAME 0x00040000UL
84#define DIR__REPARENT 0x00080000UL
85#define DIR__SEARCH 0x00100000UL
86#define DIR__RMDIR 0x00200000UL
87
88#define FILE__IOCTL 0x00000001UL
89#define FILE__READ 0x00000002UL
90#define FILE__WRITE 0x00000004UL
91#define FILE__CREATE 0x00000008UL
92#define FILE__GETATTR 0x00000010UL
93#define FILE__SETATTR 0x00000020UL
94#define FILE__LOCK 0x00000040UL
95#define FILE__RELABELFROM 0x00000080UL
96#define FILE__RELABELTO 0x00000100UL
97#define FILE__APPEND 0x00000200UL
98#define FILE__UNLINK 0x00000400UL
99#define FILE__LINK 0x00000800UL
100#define FILE__RENAME 0x00001000UL
101#define FILE__EXECUTE 0x00002000UL
102#define FILE__SWAPON 0x00004000UL
103#define FILE__QUOTAON 0x00008000UL
104#define FILE__MOUNTON 0x00010000UL
105
106#define FILE__EXECUTE_NO_TRANS 0x00020000UL
107#define FILE__ENTRYPOINT 0x00040000UL
108#define FILE__EXECMOD 0x00080000UL
109
110#define LNK_FILE__IOCTL 0x00000001UL
111#define LNK_FILE__READ 0x00000002UL
112#define LNK_FILE__WRITE 0x00000004UL
113#define LNK_FILE__CREATE 0x00000008UL
114#define LNK_FILE__GETATTR 0x00000010UL
115#define LNK_FILE__SETATTR 0x00000020UL
116#define LNK_FILE__LOCK 0x00000040UL
117#define LNK_FILE__RELABELFROM 0x00000080UL
118#define LNK_FILE__RELABELTO 0x00000100UL
119#define LNK_FILE__APPEND 0x00000200UL
120#define LNK_FILE__UNLINK 0x00000400UL
121#define LNK_FILE__LINK 0x00000800UL
122#define LNK_FILE__RENAME 0x00001000UL
123#define LNK_FILE__EXECUTE 0x00002000UL
124#define LNK_FILE__SWAPON 0x00004000UL
125#define LNK_FILE__QUOTAON 0x00008000UL
126#define LNK_FILE__MOUNTON 0x00010000UL
127
128#define CHR_FILE__IOCTL 0x00000001UL
129#define CHR_FILE__READ 0x00000002UL
130#define CHR_FILE__WRITE 0x00000004UL
131#define CHR_FILE__CREATE 0x00000008UL
132#define CHR_FILE__GETATTR 0x00000010UL
133#define CHR_FILE__SETATTR 0x00000020UL
134#define CHR_FILE__LOCK 0x00000040UL
135#define CHR_FILE__RELABELFROM 0x00000080UL
136#define CHR_FILE__RELABELTO 0x00000100UL
137#define CHR_FILE__APPEND 0x00000200UL
138#define CHR_FILE__UNLINK 0x00000400UL
139#define CHR_FILE__LINK 0x00000800UL
140#define CHR_FILE__RENAME 0x00001000UL
141#define CHR_FILE__EXECUTE 0x00002000UL
142#define CHR_FILE__SWAPON 0x00004000UL
143#define CHR_FILE__QUOTAON 0x00008000UL
144#define CHR_FILE__MOUNTON 0x00010000UL
145
146#define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL
147#define CHR_FILE__ENTRYPOINT 0x00040000UL
148#define CHR_FILE__EXECMOD 0x00080000UL
149
150#define BLK_FILE__IOCTL 0x00000001UL
151#define BLK_FILE__READ 0x00000002UL
152#define BLK_FILE__WRITE 0x00000004UL
153#define BLK_FILE__CREATE 0x00000008UL
154#define BLK_FILE__GETATTR 0x00000010UL
155#define BLK_FILE__SETATTR 0x00000020UL
156#define BLK_FILE__LOCK 0x00000040UL
157#define BLK_FILE__RELABELFROM 0x00000080UL
158#define BLK_FILE__RELABELTO 0x00000100UL
159#define BLK_FILE__APPEND 0x00000200UL
160#define BLK_FILE__UNLINK 0x00000400UL
161#define BLK_FILE__LINK 0x00000800UL
162#define BLK_FILE__RENAME 0x00001000UL
163#define BLK_FILE__EXECUTE 0x00002000UL
164#define BLK_FILE__SWAPON 0x00004000UL
165#define BLK_FILE__QUOTAON 0x00008000UL
166#define BLK_FILE__MOUNTON 0x00010000UL
167
168#define SOCK_FILE__IOCTL 0x00000001UL
169#define SOCK_FILE__READ 0x00000002UL
170#define SOCK_FILE__WRITE 0x00000004UL
171#define SOCK_FILE__CREATE 0x00000008UL
172#define SOCK_FILE__GETATTR 0x00000010UL
173#define SOCK_FILE__SETATTR 0x00000020UL
174#define SOCK_FILE__LOCK 0x00000040UL
175#define SOCK_FILE__RELABELFROM 0x00000080UL
176#define SOCK_FILE__RELABELTO 0x00000100UL
177#define SOCK_FILE__APPEND 0x00000200UL
178#define SOCK_FILE__UNLINK 0x00000400UL
179#define SOCK_FILE__LINK 0x00000800UL
180#define SOCK_FILE__RENAME 0x00001000UL
181#define SOCK_FILE__EXECUTE 0x00002000UL
182#define SOCK_FILE__SWAPON 0x00004000UL
183#define SOCK_FILE__QUOTAON 0x00008000UL
184#define SOCK_FILE__MOUNTON 0x00010000UL
185
186#define FIFO_FILE__IOCTL 0x00000001UL
187#define FIFO_FILE__READ 0x00000002UL
188#define FIFO_FILE__WRITE 0x00000004UL
189#define FIFO_FILE__CREATE 0x00000008UL
190#define FIFO_FILE__GETATTR 0x00000010UL
191#define FIFO_FILE__SETATTR 0x00000020UL
192#define FIFO_FILE__LOCK 0x00000040UL
193#define FIFO_FILE__RELABELFROM 0x00000080UL
194#define FIFO_FILE__RELABELTO 0x00000100UL
195#define FIFO_FILE__APPEND 0x00000200UL
196#define FIFO_FILE__UNLINK 0x00000400UL
197#define FIFO_FILE__LINK 0x00000800UL
198#define FIFO_FILE__RENAME 0x00001000UL
199#define FIFO_FILE__EXECUTE 0x00002000UL
200#define FIFO_FILE__SWAPON 0x00004000UL
201#define FIFO_FILE__QUOTAON 0x00008000UL
202#define FIFO_FILE__MOUNTON 0x00010000UL
203
204#define FD__USE 0x00000001UL
205
206#define SOCKET__IOCTL 0x00000001UL
207#define SOCKET__READ 0x00000002UL
208#define SOCKET__WRITE 0x00000004UL
209#define SOCKET__CREATE 0x00000008UL
210#define SOCKET__GETATTR 0x00000010UL
211#define SOCKET__SETATTR 0x00000020UL
212#define SOCKET__LOCK 0x00000040UL
213#define SOCKET__RELABELFROM 0x00000080UL
214#define SOCKET__RELABELTO 0x00000100UL
215#define SOCKET__APPEND 0x00000200UL
216#define SOCKET__BIND 0x00000400UL
217#define SOCKET__CONNECT 0x00000800UL
218#define SOCKET__LISTEN 0x00001000UL
219#define SOCKET__ACCEPT 0x00002000UL
220#define SOCKET__GETOPT 0x00004000UL
221#define SOCKET__SETOPT 0x00008000UL
222#define SOCKET__SHUTDOWN 0x00010000UL
223#define SOCKET__RECVFROM 0x00020000UL
224#define SOCKET__SENDTO 0x00040000UL
225#define SOCKET__RECV_MSG 0x00080000UL
226#define SOCKET__SEND_MSG 0x00100000UL
227#define SOCKET__NAME_BIND 0x00200000UL
228
229#define TCP_SOCKET__IOCTL 0x00000001UL
230#define TCP_SOCKET__READ 0x00000002UL
231#define TCP_SOCKET__WRITE 0x00000004UL
232#define TCP_SOCKET__CREATE 0x00000008UL
233#define TCP_SOCKET__GETATTR 0x00000010UL
234#define TCP_SOCKET__SETATTR 0x00000020UL
235#define TCP_SOCKET__LOCK 0x00000040UL
236#define TCP_SOCKET__RELABELFROM 0x00000080UL
237#define TCP_SOCKET__RELABELTO 0x00000100UL
238#define TCP_SOCKET__APPEND 0x00000200UL
239#define TCP_SOCKET__BIND 0x00000400UL
240#define TCP_SOCKET__CONNECT 0x00000800UL
241#define TCP_SOCKET__LISTEN 0x00001000UL
242#define TCP_SOCKET__ACCEPT 0x00002000UL
243#define TCP_SOCKET__GETOPT 0x00004000UL
244#define TCP_SOCKET__SETOPT 0x00008000UL
245#define TCP_SOCKET__SHUTDOWN 0x00010000UL
246#define TCP_SOCKET__RECVFROM 0x00020000UL
247#define TCP_SOCKET__SENDTO 0x00040000UL
248#define TCP_SOCKET__RECV_MSG 0x00080000UL
249#define TCP_SOCKET__SEND_MSG 0x00100000UL
250#define TCP_SOCKET__NAME_BIND 0x00200000UL
251
252#define TCP_SOCKET__CONNECTTO 0x00400000UL
253#define TCP_SOCKET__NEWCONN 0x00800000UL
254#define TCP_SOCKET__ACCEPTFROM 0x01000000UL
255#define TCP_SOCKET__NODE_BIND 0x02000000UL
256#define TCP_SOCKET__NAME_CONNECT 0x04000000UL
257
258#define UDP_SOCKET__IOCTL 0x00000001UL
259#define UDP_SOCKET__READ 0x00000002UL
260#define UDP_SOCKET__WRITE 0x00000004UL
261#define UDP_SOCKET__CREATE 0x00000008UL
262#define UDP_SOCKET__GETATTR 0x00000010UL
263#define UDP_SOCKET__SETATTR 0x00000020UL
264#define UDP_SOCKET__LOCK 0x00000040UL
265#define UDP_SOCKET__RELABELFROM 0x00000080UL
266#define UDP_SOCKET__RELABELTO 0x00000100UL
267#define UDP_SOCKET__APPEND 0x00000200UL
268#define UDP_SOCKET__BIND 0x00000400UL
269#define UDP_SOCKET__CONNECT 0x00000800UL
270#define UDP_SOCKET__LISTEN 0x00001000UL
271#define UDP_SOCKET__ACCEPT 0x00002000UL
272#define UDP_SOCKET__GETOPT 0x00004000UL
273#define UDP_SOCKET__SETOPT 0x00008000UL
274#define UDP_SOCKET__SHUTDOWN 0x00010000UL
275#define UDP_SOCKET__RECVFROM 0x00020000UL
276#define UDP_SOCKET__SENDTO 0x00040000UL
277#define UDP_SOCKET__RECV_MSG 0x00080000UL
278#define UDP_SOCKET__SEND_MSG 0x00100000UL
279#define UDP_SOCKET__NAME_BIND 0x00200000UL
280
281#define UDP_SOCKET__NODE_BIND 0x00400000UL
282
283#define RAWIP_SOCKET__IOCTL 0x00000001UL
284#define RAWIP_SOCKET__READ 0x00000002UL
285#define RAWIP_SOCKET__WRITE 0x00000004UL
286#define RAWIP_SOCKET__CREATE 0x00000008UL
287#define RAWIP_SOCKET__GETATTR 0x00000010UL
288#define RAWIP_SOCKET__SETATTR 0x00000020UL
289#define RAWIP_SOCKET__LOCK 0x00000040UL
290#define RAWIP_SOCKET__RELABELFROM 0x00000080UL
291#define RAWIP_SOCKET__RELABELTO 0x00000100UL
292#define RAWIP_SOCKET__APPEND 0x00000200UL
293#define RAWIP_SOCKET__BIND 0x00000400UL
294#define RAWIP_SOCKET__CONNECT 0x00000800UL
295#define RAWIP_SOCKET__LISTEN 0x00001000UL
296#define RAWIP_SOCKET__ACCEPT 0x00002000UL
297#define RAWIP_SOCKET__GETOPT 0x00004000UL
298#define RAWIP_SOCKET__SETOPT 0x00008000UL
299#define RAWIP_SOCKET__SHUTDOWN 0x00010000UL
300#define RAWIP_SOCKET__RECVFROM 0x00020000UL
301#define RAWIP_SOCKET__SENDTO 0x00040000UL
302#define RAWIP_SOCKET__RECV_MSG 0x00080000UL
303#define RAWIP_SOCKET__SEND_MSG 0x00100000UL
304#define RAWIP_SOCKET__NAME_BIND 0x00200000UL
305
306#define RAWIP_SOCKET__NODE_BIND 0x00400000UL
307
308#define NODE__TCP_RECV 0x00000001UL
309#define NODE__TCP_SEND 0x00000002UL
310#define NODE__UDP_RECV 0x00000004UL
311#define NODE__UDP_SEND 0x00000008UL
312#define NODE__RAWIP_RECV 0x00000010UL
313#define NODE__RAWIP_SEND 0x00000020UL
314#define NODE__ENFORCE_DEST 0x00000040UL
315
316#define NETIF__TCP_RECV 0x00000001UL
317#define NETIF__TCP_SEND 0x00000002UL
318#define NETIF__UDP_RECV 0x00000004UL
319#define NETIF__UDP_SEND 0x00000008UL
320#define NETIF__RAWIP_RECV 0x00000010UL
321#define NETIF__RAWIP_SEND 0x00000020UL
322
323#define NETLINK_SOCKET__IOCTL 0x00000001UL
324#define NETLINK_SOCKET__READ 0x00000002UL
325#define NETLINK_SOCKET__WRITE 0x00000004UL
326#define NETLINK_SOCKET__CREATE 0x00000008UL
327#define NETLINK_SOCKET__GETATTR 0x00000010UL
328#define NETLINK_SOCKET__SETATTR 0x00000020UL
329#define NETLINK_SOCKET__LOCK 0x00000040UL
330#define NETLINK_SOCKET__RELABELFROM 0x00000080UL
331#define NETLINK_SOCKET__RELABELTO 0x00000100UL
332#define NETLINK_SOCKET__APPEND 0x00000200UL
333#define NETLINK_SOCKET__BIND 0x00000400UL
334#define NETLINK_SOCKET__CONNECT 0x00000800UL
335#define NETLINK_SOCKET__LISTEN 0x00001000UL
336#define NETLINK_SOCKET__ACCEPT 0x00002000UL
337#define NETLINK_SOCKET__GETOPT 0x00004000UL
338#define NETLINK_SOCKET__SETOPT 0x00008000UL
339#define NETLINK_SOCKET__SHUTDOWN 0x00010000UL
340#define NETLINK_SOCKET__RECVFROM 0x00020000UL
341#define NETLINK_SOCKET__SENDTO 0x00040000UL
342#define NETLINK_SOCKET__RECV_MSG 0x00080000UL
343#define NETLINK_SOCKET__SEND_MSG 0x00100000UL
344#define NETLINK_SOCKET__NAME_BIND 0x00200000UL
345
346#define PACKET_SOCKET__IOCTL 0x00000001UL
347#define PACKET_SOCKET__READ 0x00000002UL
348#define PACKET_SOCKET__WRITE 0x00000004UL
349#define PACKET_SOCKET__CREATE 0x00000008UL
350#define PACKET_SOCKET__GETATTR 0x00000010UL
351#define PACKET_SOCKET__SETATTR 0x00000020UL
352#define PACKET_SOCKET__LOCK 0x00000040UL
353#define PACKET_SOCKET__RELABELFROM 0x00000080UL
354#define PACKET_SOCKET__RELABELTO 0x00000100UL
355#define PACKET_SOCKET__APPEND 0x00000200UL
356#define PACKET_SOCKET__BIND 0x00000400UL
357#define PACKET_SOCKET__CONNECT 0x00000800UL
358#define PACKET_SOCKET__LISTEN 0x00001000UL
359#define PACKET_SOCKET__ACCEPT 0x00002000UL
360#define PACKET_SOCKET__GETOPT 0x00004000UL
361#define PACKET_SOCKET__SETOPT 0x00008000UL
362#define PACKET_SOCKET__SHUTDOWN 0x00010000UL
363#define PACKET_SOCKET__RECVFROM 0x00020000UL
364#define PACKET_SOCKET__SENDTO 0x00040000UL
365#define PACKET_SOCKET__RECV_MSG 0x00080000UL
366#define PACKET_SOCKET__SEND_MSG 0x00100000UL
367#define PACKET_SOCKET__NAME_BIND 0x00200000UL
368
369#define KEY_SOCKET__IOCTL 0x00000001UL
370#define KEY_SOCKET__READ 0x00000002UL
371#define KEY_SOCKET__WRITE 0x00000004UL
372#define KEY_SOCKET__CREATE 0x00000008UL
373#define KEY_SOCKET__GETATTR 0x00000010UL
374#define KEY_SOCKET__SETATTR 0x00000020UL
375#define KEY_SOCKET__LOCK 0x00000040UL
376#define KEY_SOCKET__RELABELFROM 0x00000080UL
377#define KEY_SOCKET__RELABELTO 0x00000100UL
378#define KEY_SOCKET__APPEND 0x00000200UL
379#define KEY_SOCKET__BIND 0x00000400UL
380#define KEY_SOCKET__CONNECT 0x00000800UL
381#define KEY_SOCKET__LISTEN 0x00001000UL
382#define KEY_SOCKET__ACCEPT 0x00002000UL
383#define KEY_SOCKET__GETOPT 0x00004000UL
384#define KEY_SOCKET__SETOPT 0x00008000UL
385#define KEY_SOCKET__SHUTDOWN 0x00010000UL
386#define KEY_SOCKET__RECVFROM 0x00020000UL
387#define KEY_SOCKET__SENDTO 0x00040000UL
388#define KEY_SOCKET__RECV_MSG 0x00080000UL
389#define KEY_SOCKET__SEND_MSG 0x00100000UL
390#define KEY_SOCKET__NAME_BIND 0x00200000UL
391
392#define UNIX_STREAM_SOCKET__IOCTL 0x00000001UL
393#define UNIX_STREAM_SOCKET__READ 0x00000002UL
394#define UNIX_STREAM_SOCKET__WRITE 0x00000004UL
395#define UNIX_STREAM_SOCKET__CREATE 0x00000008UL
396#define UNIX_STREAM_SOCKET__GETATTR 0x00000010UL
397#define UNIX_STREAM_SOCKET__SETATTR 0x00000020UL
398#define UNIX_STREAM_SOCKET__LOCK 0x00000040UL
399#define UNIX_STREAM_SOCKET__RELABELFROM 0x00000080UL
400#define UNIX_STREAM_SOCKET__RELABELTO 0x00000100UL
401#define UNIX_STREAM_SOCKET__APPEND 0x00000200UL
402#define UNIX_STREAM_SOCKET__BIND 0x00000400UL
403#define UNIX_STREAM_SOCKET__CONNECT 0x00000800UL
404#define UNIX_STREAM_SOCKET__LISTEN 0x00001000UL
405#define UNIX_STREAM_SOCKET__ACCEPT 0x00002000UL
406#define UNIX_STREAM_SOCKET__GETOPT 0x00004000UL
407#define UNIX_STREAM_SOCKET__SETOPT 0x00008000UL
408#define UNIX_STREAM_SOCKET__SHUTDOWN 0x00010000UL
409#define UNIX_STREAM_SOCKET__RECVFROM 0x00020000UL
410#define UNIX_STREAM_SOCKET__SENDTO 0x00040000UL
411#define UNIX_STREAM_SOCKET__RECV_MSG 0x00080000UL
412#define UNIX_STREAM_SOCKET__SEND_MSG 0x00100000UL
413#define UNIX_STREAM_SOCKET__NAME_BIND 0x00200000UL
414
415#define UNIX_STREAM_SOCKET__CONNECTTO 0x00400000UL
416#define UNIX_STREAM_SOCKET__NEWCONN 0x00800000UL
417#define UNIX_STREAM_SOCKET__ACCEPTFROM 0x01000000UL
418
419#define UNIX_DGRAM_SOCKET__IOCTL 0x00000001UL
420#define UNIX_DGRAM_SOCKET__READ 0x00000002UL
421#define UNIX_DGRAM_SOCKET__WRITE 0x00000004UL
422#define UNIX_DGRAM_SOCKET__CREATE 0x00000008UL
423#define UNIX_DGRAM_SOCKET__GETATTR 0x00000010UL
424#define UNIX_DGRAM_SOCKET__SETATTR 0x00000020UL
425#define UNIX_DGRAM_SOCKET__LOCK 0x00000040UL
426#define UNIX_DGRAM_SOCKET__RELABELFROM 0x00000080UL
427#define UNIX_DGRAM_SOCKET__RELABELTO 0x00000100UL
428#define UNIX_DGRAM_SOCKET__APPEND 0x00000200UL
429#define UNIX_DGRAM_SOCKET__BIND 0x00000400UL
430#define UNIX_DGRAM_SOCKET__CONNECT 0x00000800UL
431#define UNIX_DGRAM_SOCKET__LISTEN 0x00001000UL
432#define UNIX_DGRAM_SOCKET__ACCEPT 0x00002000UL
433#define UNIX_DGRAM_SOCKET__GETOPT 0x00004000UL
434#define UNIX_DGRAM_SOCKET__SETOPT 0x00008000UL
435#define UNIX_DGRAM_SOCKET__SHUTDOWN 0x00010000UL
436#define UNIX_DGRAM_SOCKET__RECVFROM 0x00020000UL
437#define UNIX_DGRAM_SOCKET__SENDTO 0x00040000UL
438#define UNIX_DGRAM_SOCKET__RECV_MSG 0x00080000UL
439#define UNIX_DGRAM_SOCKET__SEND_MSG 0x00100000UL
440#define UNIX_DGRAM_SOCKET__NAME_BIND 0x00200000UL
441
442#define PROCESS__FORK 0x00000001UL
443#define PROCESS__TRANSITION 0x00000002UL
444#define PROCESS__SIGCHLD 0x00000004UL
445#define PROCESS__SIGKILL 0x00000008UL
446#define PROCESS__SIGSTOP 0x00000010UL
447#define PROCESS__SIGNULL 0x00000020UL
448#define PROCESS__SIGNAL 0x00000040UL
449#define PROCESS__PTRACE 0x00000080UL
450#define PROCESS__GETSCHED 0x00000100UL
451#define PROCESS__SETSCHED 0x00000200UL
452#define PROCESS__GETSESSION 0x00000400UL
453#define PROCESS__GETPGID 0x00000800UL
454#define PROCESS__SETPGID 0x00001000UL
455#define PROCESS__GETCAP 0x00002000UL
456#define PROCESS__SETCAP 0x00004000UL
457#define PROCESS__SHARE 0x00008000UL
458#define PROCESS__GETATTR 0x00010000UL
459#define PROCESS__SETEXEC 0x00020000UL
460#define PROCESS__SETFSCREATE 0x00040000UL
461#define PROCESS__NOATSECURE 0x00080000UL
462#define PROCESS__SIGINH 0x00100000UL
463#define PROCESS__SETRLIMIT 0x00200000UL
464#define PROCESS__RLIMITINH 0x00400000UL
465#define PROCESS__DYNTRANSITION 0x00800000UL
466#define PROCESS__SETCURRENT 0x01000000UL
467#define PROCESS__EXECMEM 0x02000000UL
468
469#define IPC__CREATE 0x00000001UL
470#define IPC__DESTROY 0x00000002UL
471#define IPC__GETATTR 0x00000004UL
472#define IPC__SETATTR 0x00000008UL
473#define IPC__READ 0x00000010UL
474#define IPC__WRITE 0x00000020UL
475#define IPC__ASSOCIATE 0x00000040UL
476#define IPC__UNIX_READ 0x00000080UL
477#define IPC__UNIX_WRITE 0x00000100UL
478
479#define SEM__CREATE 0x00000001UL
480#define SEM__DESTROY 0x00000002UL
481#define SEM__GETATTR 0x00000004UL
482#define SEM__SETATTR 0x00000008UL
483#define SEM__READ 0x00000010UL
484#define SEM__WRITE 0x00000020UL
485#define SEM__ASSOCIATE 0x00000040UL
486#define SEM__UNIX_READ 0x00000080UL
487#define SEM__UNIX_WRITE 0x00000100UL
488
489#define MSGQ__CREATE 0x00000001UL
490#define MSGQ__DESTROY 0x00000002UL
491#define MSGQ__GETATTR 0x00000004UL
492#define MSGQ__SETATTR 0x00000008UL
493#define MSGQ__READ 0x00000010UL
494#define MSGQ__WRITE 0x00000020UL
495#define MSGQ__ASSOCIATE 0x00000040UL
496#define MSGQ__UNIX_READ 0x00000080UL
497#define MSGQ__UNIX_WRITE 0x00000100UL
498
499#define MSGQ__ENQUEUE 0x00000200UL
500
501#define MSG__SEND 0x00000001UL
502#define MSG__RECEIVE 0x00000002UL
503
504#define SHM__CREATE 0x00000001UL
505#define SHM__DESTROY 0x00000002UL
506#define SHM__GETATTR 0x00000004UL
507#define SHM__SETATTR 0x00000008UL
508#define SHM__READ 0x00000010UL
509#define SHM__WRITE 0x00000020UL
510#define SHM__ASSOCIATE 0x00000040UL
511#define SHM__UNIX_READ 0x00000080UL
512#define SHM__UNIX_WRITE 0x00000100UL
513
514#define SHM__LOCK 0x00000200UL
515
516#define SECURITY__COMPUTE_AV 0x00000001UL
517#define SECURITY__COMPUTE_CREATE 0x00000002UL
518#define SECURITY__COMPUTE_MEMBER 0x00000004UL
519#define SECURITY__CHECK_CONTEXT 0x00000008UL
520#define SECURITY__LOAD_POLICY 0x00000010UL
521#define SECURITY__COMPUTE_RELABEL 0x00000020UL
522#define SECURITY__COMPUTE_USER 0x00000040UL
523#define SECURITY__SETENFORCE 0x00000080UL
524#define SECURITY__SETBOOL 0x00000100UL
525#define SECURITY__SETSECPARAM 0x00000200UL
526#define SECURITY__SETCHECKREQPROT 0x00000400UL
527
528#define SYSTEM__IPC_INFO 0x00000001UL
529#define SYSTEM__SYSLOG_READ 0x00000002UL
530#define SYSTEM__SYSLOG_MOD 0x00000004UL
531#define SYSTEM__SYSLOG_CONSOLE 0x00000008UL
532
533#define CAPABILITY__CHOWN 0x00000001UL
534#define CAPABILITY__DAC_OVERRIDE 0x00000002UL
535#define CAPABILITY__DAC_READ_SEARCH 0x00000004UL
536#define CAPABILITY__FOWNER 0x00000008UL
537#define CAPABILITY__FSETID 0x00000010UL
538#define CAPABILITY__KILL 0x00000020UL
539#define CAPABILITY__SETGID 0x00000040UL
540#define CAPABILITY__SETUID 0x00000080UL
541#define CAPABILITY__SETPCAP 0x00000100UL
542#define CAPABILITY__LINUX_IMMUTABLE 0x00000200UL
543#define CAPABILITY__NET_BIND_SERVICE 0x00000400UL
544#define CAPABILITY__NET_BROADCAST 0x00000800UL
545#define CAPABILITY__NET_ADMIN 0x00001000UL
546#define CAPABILITY__NET_RAW 0x00002000UL
547#define CAPABILITY__IPC_LOCK 0x00004000UL
548#define CAPABILITY__IPC_OWNER 0x00008000UL
549#define CAPABILITY__SYS_MODULE 0x00010000UL
550#define CAPABILITY__SYS_RAWIO 0x00020000UL
551#define CAPABILITY__SYS_CHROOT 0x00040000UL
552#define CAPABILITY__SYS_PTRACE 0x00080000UL
553#define CAPABILITY__SYS_PACCT 0x00100000UL
554#define CAPABILITY__SYS_ADMIN 0x00200000UL
555#define CAPABILITY__SYS_BOOT 0x00400000UL
556#define CAPABILITY__SYS_NICE 0x00800000UL
557#define CAPABILITY__SYS_RESOURCE 0x01000000UL
558#define CAPABILITY__SYS_TIME 0x02000000UL
559#define CAPABILITY__SYS_TTY_CONFIG 0x04000000UL
560#define CAPABILITY__MKNOD 0x08000000UL
561#define CAPABILITY__LEASE 0x10000000UL
562
563#define PASSWD__PASSWD 0x00000001UL
564#define PASSWD__CHFN 0x00000002UL
565#define PASSWD__CHSH 0x00000004UL
566#define PASSWD__ROOTOK 0x00000008UL
567#define PASSWD__CRONTAB 0x00000010UL
568
569#define DRAWABLE__CREATE 0x00000001UL
570#define DRAWABLE__DESTROY 0x00000002UL
571#define DRAWABLE__DRAW 0x00000004UL
572#define DRAWABLE__COPY 0x00000008UL
573#define DRAWABLE__GETATTR 0x00000010UL
574
575#define GC__CREATE 0x00000001UL
576#define GC__FREE 0x00000002UL
577#define GC__GETATTR 0x00000004UL
578#define GC__SETATTR 0x00000008UL
579
580#define WINDOW__ADDCHILD 0x00000001UL
581#define WINDOW__CREATE 0x00000002UL
582#define WINDOW__DESTROY 0x00000004UL
583#define WINDOW__MAP 0x00000008UL
584#define WINDOW__UNMAP 0x00000010UL
585#define WINDOW__CHSTACK 0x00000020UL
586#define WINDOW__CHPROPLIST 0x00000040UL
587#define WINDOW__CHPROP 0x00000080UL
588#define WINDOW__LISTPROP 0x00000100UL
589#define WINDOW__GETATTR 0x00000200UL
590#define WINDOW__SETATTR 0x00000400UL
591#define WINDOW__SETFOCUS 0x00000800UL
592#define WINDOW__MOVE 0x00001000UL
593#define WINDOW__CHSELECTION 0x00002000UL
594#define WINDOW__CHPARENT 0x00004000UL
595#define WINDOW__CTRLLIFE 0x00008000UL
596#define WINDOW__ENUMERATE 0x00010000UL
597#define WINDOW__TRANSPARENT 0x00020000UL
598#define WINDOW__MOUSEMOTION 0x00040000UL
599#define WINDOW__CLIENTCOMEVENT 0x00080000UL
600#define WINDOW__INPUTEVENT 0x00100000UL
601#define WINDOW__DRAWEVENT 0x00200000UL
602#define WINDOW__WINDOWCHANGEEVENT 0x00400000UL
603#define WINDOW__WINDOWCHANGEREQUEST 0x00800000UL
604#define WINDOW__SERVERCHANGEEVENT 0x01000000UL
605#define WINDOW__EXTENSIONEVENT 0x02000000UL
606
607#define FONT__LOAD 0x00000001UL
608#define FONT__FREE 0x00000002UL
609#define FONT__GETATTR 0x00000004UL
610#define FONT__USE 0x00000008UL
611
612#define COLORMAP__CREATE 0x00000001UL
613#define COLORMAP__FREE 0x00000002UL
614#define COLORMAP__INSTALL 0x00000004UL
615#define COLORMAP__UNINSTALL 0x00000008UL
616#define COLORMAP__LIST 0x00000010UL
617#define COLORMAP__READ 0x00000020UL
618#define COLORMAP__STORE 0x00000040UL
619#define COLORMAP__GETATTR 0x00000080UL
620#define COLORMAP__SETATTR 0x00000100UL
621
622#define PROPERTY__CREATE 0x00000001UL
623#define PROPERTY__FREE 0x00000002UL
624#define PROPERTY__READ 0x00000004UL
625#define PROPERTY__WRITE 0x00000008UL
626
627#define CURSOR__CREATE 0x00000001UL
628#define CURSOR__CREATEGLYPH 0x00000002UL
629#define CURSOR__FREE 0x00000004UL
630#define CURSOR__ASSIGN 0x00000008UL
631#define CURSOR__SETATTR 0x00000010UL
632
633#define XCLIENT__KILL 0x00000001UL
634
635#define XINPUT__LOOKUP 0x00000001UL
636#define XINPUT__GETATTR 0x00000002UL
637#define XINPUT__SETATTR 0x00000004UL
638#define XINPUT__SETFOCUS 0x00000008UL
639#define XINPUT__WARPPOINTER 0x00000010UL
640#define XINPUT__ACTIVEGRAB 0x00000020UL
641#define XINPUT__PASSIVEGRAB 0x00000040UL
642#define XINPUT__UNGRAB 0x00000080UL
643#define XINPUT__BELL 0x00000100UL
644#define XINPUT__MOUSEMOTION 0x00000200UL
645#define XINPUT__RELABELINPUT 0x00000400UL
646
647#define XSERVER__SCREENSAVER 0x00000001UL
648#define XSERVER__GETHOSTLIST 0x00000002UL
649#define XSERVER__SETHOSTLIST 0x00000004UL
650#define XSERVER__GETFONTPATH 0x00000008UL
651#define XSERVER__SETFONTPATH 0x00000010UL
652#define XSERVER__GETATTR 0x00000020UL
653#define XSERVER__GRAB 0x00000040UL
654#define XSERVER__UNGRAB 0x00000080UL
655
656#define XEXTENSION__QUERY 0x00000001UL
657#define XEXTENSION__USE 0x00000002UL
658
659#define PAX__PAGEEXEC 0x00000001UL
660#define PAX__EMUTRAMP 0x00000002UL
661#define PAX__MPROTECT 0x00000004UL
662#define PAX__RANDMMAP 0x00000008UL
663#define PAX__RANDEXEC 0x00000010UL
664#define PAX__SEGMEXEC 0x00000020UL
665
666#define NETLINK_ROUTE_SOCKET__IOCTL 0x00000001UL
667#define NETLINK_ROUTE_SOCKET__READ 0x00000002UL
668#define NETLINK_ROUTE_SOCKET__WRITE 0x00000004UL
669#define NETLINK_ROUTE_SOCKET__CREATE 0x00000008UL
670#define NETLINK_ROUTE_SOCKET__GETATTR 0x00000010UL
671#define NETLINK_ROUTE_SOCKET__SETATTR 0x00000020UL
672#define NETLINK_ROUTE_SOCKET__LOCK 0x00000040UL
673#define NETLINK_ROUTE_SOCKET__RELABELFROM 0x00000080UL
674#define NETLINK_ROUTE_SOCKET__RELABELTO 0x00000100UL
675#define NETLINK_ROUTE_SOCKET__APPEND 0x00000200UL
676#define NETLINK_ROUTE_SOCKET__BIND 0x00000400UL
677#define NETLINK_ROUTE_SOCKET__CONNECT 0x00000800UL
678#define NETLINK_ROUTE_SOCKET__LISTEN 0x00001000UL
679#define NETLINK_ROUTE_SOCKET__ACCEPT 0x00002000UL
680#define NETLINK_ROUTE_SOCKET__GETOPT 0x00004000UL
681#define NETLINK_ROUTE_SOCKET__SETOPT 0x00008000UL
682#define NETLINK_ROUTE_SOCKET__SHUTDOWN 0x00010000UL
683#define NETLINK_ROUTE_SOCKET__RECVFROM 0x00020000UL
684#define NETLINK_ROUTE_SOCKET__SENDTO 0x00040000UL
685#define NETLINK_ROUTE_SOCKET__RECV_MSG 0x00080000UL
686#define NETLINK_ROUTE_SOCKET__SEND_MSG 0x00100000UL
687#define NETLINK_ROUTE_SOCKET__NAME_BIND 0x00200000UL
688
689#define NETLINK_ROUTE_SOCKET__NLMSG_READ 0x00400000UL
690#define NETLINK_ROUTE_SOCKET__NLMSG_WRITE 0x00800000UL
691
692#define NETLINK_FIREWALL_SOCKET__IOCTL 0x00000001UL
693#define NETLINK_FIREWALL_SOCKET__READ 0x00000002UL
694#define NETLINK_FIREWALL_SOCKET__WRITE 0x00000004UL
695#define NETLINK_FIREWALL_SOCKET__CREATE 0x00000008UL
696#define NETLINK_FIREWALL_SOCKET__GETATTR 0x00000010UL
697#define NETLINK_FIREWALL_SOCKET__SETATTR 0x00000020UL
698#define NETLINK_FIREWALL_SOCKET__LOCK 0x00000040UL
699#define NETLINK_FIREWALL_SOCKET__RELABELFROM 0x00000080UL
700#define NETLINK_FIREWALL_SOCKET__RELABELTO 0x00000100UL
701#define NETLINK_FIREWALL_SOCKET__APPEND 0x00000200UL
702#define NETLINK_FIREWALL_SOCKET__BIND 0x00000400UL
703#define NETLINK_FIREWALL_SOCKET__CONNECT 0x00000800UL
704#define NETLINK_FIREWALL_SOCKET__LISTEN 0x00001000UL
705#define NETLINK_FIREWALL_SOCKET__ACCEPT 0x00002000UL
706#define NETLINK_FIREWALL_SOCKET__GETOPT 0x00004000UL
707#define NETLINK_FIREWALL_SOCKET__SETOPT 0x00008000UL
708#define NETLINK_FIREWALL_SOCKET__SHUTDOWN 0x00010000UL
709#define NETLINK_FIREWALL_SOCKET__RECVFROM 0x00020000UL
710#define NETLINK_FIREWALL_SOCKET__SENDTO 0x00040000UL
711#define NETLINK_FIREWALL_SOCKET__RECV_MSG 0x00080000UL
712#define NETLINK_FIREWALL_SOCKET__SEND_MSG 0x00100000UL
713#define NETLINK_FIREWALL_SOCKET__NAME_BIND 0x00200000UL
714
715#define NETLINK_FIREWALL_SOCKET__NLMSG_READ 0x00400000UL
716#define NETLINK_FIREWALL_SOCKET__NLMSG_WRITE 0x00800000UL
717
718#define NETLINK_TCPDIAG_SOCKET__IOCTL 0x00000001UL
719#define NETLINK_TCPDIAG_SOCKET__READ 0x00000002UL
720#define NETLINK_TCPDIAG_SOCKET__WRITE 0x00000004UL
721#define NETLINK_TCPDIAG_SOCKET__CREATE 0x00000008UL
722#define NETLINK_TCPDIAG_SOCKET__GETATTR 0x00000010UL
723#define NETLINK_TCPDIAG_SOCKET__SETATTR 0x00000020UL
724#define NETLINK_TCPDIAG_SOCKET__LOCK 0x00000040UL
725#define NETLINK_TCPDIAG_SOCKET__RELABELFROM 0x00000080UL
726#define NETLINK_TCPDIAG_SOCKET__RELABELTO 0x00000100UL
727#define NETLINK_TCPDIAG_SOCKET__APPEND 0x00000200UL
728#define NETLINK_TCPDIAG_SOCKET__BIND 0x00000400UL
729#define NETLINK_TCPDIAG_SOCKET__CONNECT 0x00000800UL
730#define NETLINK_TCPDIAG_SOCKET__LISTEN 0x00001000UL
731#define NETLINK_TCPDIAG_SOCKET__ACCEPT 0x00002000UL
732#define NETLINK_TCPDIAG_SOCKET__GETOPT 0x00004000UL
733#define NETLINK_TCPDIAG_SOCKET__SETOPT 0x00008000UL
734#define NETLINK_TCPDIAG_SOCKET__SHUTDOWN 0x00010000UL
735#define NETLINK_TCPDIAG_SOCKET__RECVFROM 0x00020000UL
736#define NETLINK_TCPDIAG_SOCKET__SENDTO 0x00040000UL
737#define NETLINK_TCPDIAG_SOCKET__RECV_MSG 0x00080000UL
738#define NETLINK_TCPDIAG_SOCKET__SEND_MSG 0x00100000UL
739#define NETLINK_TCPDIAG_SOCKET__NAME_BIND 0x00200000UL
740
741#define NETLINK_TCPDIAG_SOCKET__NLMSG_READ 0x00400000UL
742#define NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE 0x00800000UL
743
744#define NETLINK_NFLOG_SOCKET__IOCTL 0x00000001UL
745#define NETLINK_NFLOG_SOCKET__READ 0x00000002UL
746#define NETLINK_NFLOG_SOCKET__WRITE 0x00000004UL
747#define NETLINK_NFLOG_SOCKET__CREATE 0x00000008UL
748#define NETLINK_NFLOG_SOCKET__GETATTR 0x00000010UL
749#define NETLINK_NFLOG_SOCKET__SETATTR 0x00000020UL
750#define NETLINK_NFLOG_SOCKET__LOCK 0x00000040UL
751#define NETLINK_NFLOG_SOCKET__RELABELFROM 0x00000080UL
752#define NETLINK_NFLOG_SOCKET__RELABELTO 0x00000100UL
753#define NETLINK_NFLOG_SOCKET__APPEND 0x00000200UL
754#define NETLINK_NFLOG_SOCKET__BIND 0x00000400UL
755#define NETLINK_NFLOG_SOCKET__CONNECT 0x00000800UL
756#define NETLINK_NFLOG_SOCKET__LISTEN 0x00001000UL
757#define NETLINK_NFLOG_SOCKET__ACCEPT 0x00002000UL
758#define NETLINK_NFLOG_SOCKET__GETOPT 0x00004000UL
759#define NETLINK_NFLOG_SOCKET__SETOPT 0x00008000UL
760#define NETLINK_NFLOG_SOCKET__SHUTDOWN 0x00010000UL
761#define NETLINK_NFLOG_SOCKET__RECVFROM 0x00020000UL
762#define NETLINK_NFLOG_SOCKET__SENDTO 0x00040000UL
763#define NETLINK_NFLOG_SOCKET__RECV_MSG 0x00080000UL
764#define NETLINK_NFLOG_SOCKET__SEND_MSG 0x00100000UL
765#define NETLINK_NFLOG_SOCKET__NAME_BIND 0x00200000UL
766
767#define NETLINK_XFRM_SOCKET__IOCTL 0x00000001UL
768#define NETLINK_XFRM_SOCKET__READ 0x00000002UL
769#define NETLINK_XFRM_SOCKET__WRITE 0x00000004UL
770#define NETLINK_XFRM_SOCKET__CREATE 0x00000008UL
771#define NETLINK_XFRM_SOCKET__GETATTR 0x00000010UL
772#define NETLINK_XFRM_SOCKET__SETATTR 0x00000020UL
773#define NETLINK_XFRM_SOCKET__LOCK 0x00000040UL
774#define NETLINK_XFRM_SOCKET__RELABELFROM 0x00000080UL
775#define NETLINK_XFRM_SOCKET__RELABELTO 0x00000100UL
776#define NETLINK_XFRM_SOCKET__APPEND 0x00000200UL
777#define NETLINK_XFRM_SOCKET__BIND 0x00000400UL
778#define NETLINK_XFRM_SOCKET__CONNECT 0x00000800UL
779#define NETLINK_XFRM_SOCKET__LISTEN 0x00001000UL
780#define NETLINK_XFRM_SOCKET__ACCEPT 0x00002000UL
781#define NETLINK_XFRM_SOCKET__GETOPT 0x00004000UL
782#define NETLINK_XFRM_SOCKET__SETOPT 0x00008000UL
783#define NETLINK_XFRM_SOCKET__SHUTDOWN 0x00010000UL
784#define NETLINK_XFRM_SOCKET__RECVFROM 0x00020000UL
785#define NETLINK_XFRM_SOCKET__SENDTO 0x00040000UL
786#define NETLINK_XFRM_SOCKET__RECV_MSG 0x00080000UL
787#define NETLINK_XFRM_SOCKET__SEND_MSG 0x00100000UL
788#define NETLINK_XFRM_SOCKET__NAME_BIND 0x00200000UL
789
790#define NETLINK_XFRM_SOCKET__NLMSG_READ 0x00400000UL
791#define NETLINK_XFRM_SOCKET__NLMSG_WRITE 0x00800000UL
792
793#define NETLINK_SELINUX_SOCKET__IOCTL 0x00000001UL
794#define NETLINK_SELINUX_SOCKET__READ 0x00000002UL
795#define NETLINK_SELINUX_SOCKET__WRITE 0x00000004UL
796#define NETLINK_SELINUX_SOCKET__CREATE 0x00000008UL
797#define NETLINK_SELINUX_SOCKET__GETATTR 0x00000010UL
798#define NETLINK_SELINUX_SOCKET__SETATTR 0x00000020UL
799#define NETLINK_SELINUX_SOCKET__LOCK 0x00000040UL
800#define NETLINK_SELINUX_SOCKET__RELABELFROM 0x00000080UL
801#define NETLINK_SELINUX_SOCKET__RELABELTO 0x00000100UL
802#define NETLINK_SELINUX_SOCKET__APPEND 0x00000200UL
803#define NETLINK_SELINUX_SOCKET__BIND 0x00000400UL
804#define NETLINK_SELINUX_SOCKET__CONNECT 0x00000800UL
805#define NETLINK_SELINUX_SOCKET__LISTEN 0x00001000UL
806#define NETLINK_SELINUX_SOCKET__ACCEPT 0x00002000UL
807#define NETLINK_SELINUX_SOCKET__GETOPT 0x00004000UL
808#define NETLINK_SELINUX_SOCKET__SETOPT 0x00008000UL
809#define NETLINK_SELINUX_SOCKET__SHUTDOWN 0x00010000UL
810#define NETLINK_SELINUX_SOCKET__RECVFROM 0x00020000UL
811#define NETLINK_SELINUX_SOCKET__SENDTO 0x00040000UL
812#define NETLINK_SELINUX_SOCKET__RECV_MSG 0x00080000UL
813#define NETLINK_SELINUX_SOCKET__SEND_MSG 0x00100000UL
814#define NETLINK_SELINUX_SOCKET__NAME_BIND 0x00200000UL
815
816#define NETLINK_AUDIT_SOCKET__IOCTL 0x00000001UL
817#define NETLINK_AUDIT_SOCKET__READ 0x00000002UL
818#define NETLINK_AUDIT_SOCKET__WRITE 0x00000004UL
819#define NETLINK_AUDIT_SOCKET__CREATE 0x00000008UL
820#define NETLINK_AUDIT_SOCKET__GETATTR 0x00000010UL
821#define NETLINK_AUDIT_SOCKET__SETATTR 0x00000020UL
822#define NETLINK_AUDIT_SOCKET__LOCK 0x00000040UL
823#define NETLINK_AUDIT_SOCKET__RELABELFROM 0x00000080UL
824#define NETLINK_AUDIT_SOCKET__RELABELTO 0x00000100UL
825#define NETLINK_AUDIT_SOCKET__APPEND 0x00000200UL
826#define NETLINK_AUDIT_SOCKET__BIND 0x00000400UL
827#define NETLINK_AUDIT_SOCKET__CONNECT 0x00000800UL
828#define NETLINK_AUDIT_SOCKET__LISTEN 0x00001000UL
829#define NETLINK_AUDIT_SOCKET__ACCEPT 0x00002000UL
830#define NETLINK_AUDIT_SOCKET__GETOPT 0x00004000UL
831#define NETLINK_AUDIT_SOCKET__SETOPT 0x00008000UL
832#define NETLINK_AUDIT_SOCKET__SHUTDOWN 0x00010000UL
833#define NETLINK_AUDIT_SOCKET__RECVFROM 0x00020000UL
834#define NETLINK_AUDIT_SOCKET__SENDTO 0x00040000UL
835#define NETLINK_AUDIT_SOCKET__RECV_MSG 0x00080000UL
836#define NETLINK_AUDIT_SOCKET__SEND_MSG 0x00100000UL
837#define NETLINK_AUDIT_SOCKET__NAME_BIND 0x00200000UL
838
839#define NETLINK_AUDIT_SOCKET__NLMSG_READ 0x00400000UL
840#define NETLINK_AUDIT_SOCKET__NLMSG_WRITE 0x00800000UL
841
842#define NETLINK_IP6FW_SOCKET__IOCTL 0x00000001UL
843#define NETLINK_IP6FW_SOCKET__READ 0x00000002UL
844#define NETLINK_IP6FW_SOCKET__WRITE 0x00000004UL
845#define NETLINK_IP6FW_SOCKET__CREATE 0x00000008UL
846#define NETLINK_IP6FW_SOCKET__GETATTR 0x00000010UL
847#define NETLINK_IP6FW_SOCKET__SETATTR 0x00000020UL
848#define NETLINK_IP6FW_SOCKET__LOCK 0x00000040UL
849#define NETLINK_IP6FW_SOCKET__RELABELFROM 0x00000080UL
850#define NETLINK_IP6FW_SOCKET__RELABELTO 0x00000100UL
851#define NETLINK_IP6FW_SOCKET__APPEND 0x00000200UL
852#define NETLINK_IP6FW_SOCKET__BIND 0x00000400UL
853#define NETLINK_IP6FW_SOCKET__CONNECT 0x00000800UL
854#define NETLINK_IP6FW_SOCKET__LISTEN 0x00001000UL
855#define NETLINK_IP6FW_SOCKET__ACCEPT 0x00002000UL
856#define NETLINK_IP6FW_SOCKET__GETOPT 0x00004000UL
857#define NETLINK_IP6FW_SOCKET__SETOPT 0x00008000UL
858#define NETLINK_IP6FW_SOCKET__SHUTDOWN 0x00010000UL
859#define NETLINK_IP6FW_SOCKET__RECVFROM 0x00020000UL
860#define NETLINK_IP6FW_SOCKET__SENDTO 0x00040000UL
861#define NETLINK_IP6FW_SOCKET__RECV_MSG 0x00080000UL
862#define NETLINK_IP6FW_SOCKET__SEND_MSG 0x00100000UL
863#define NETLINK_IP6FW_SOCKET__NAME_BIND 0x00200000UL
864
865#define NETLINK_IP6FW_SOCKET__NLMSG_READ 0x00400000UL
866#define NETLINK_IP6FW_SOCKET__NLMSG_WRITE 0x00800000UL
867
868#define NETLINK_DNRT_SOCKET__IOCTL 0x00000001UL
869#define NETLINK_DNRT_SOCKET__READ 0x00000002UL
870#define NETLINK_DNRT_SOCKET__WRITE 0x00000004UL
871#define NETLINK_DNRT_SOCKET__CREATE 0x00000008UL
872#define NETLINK_DNRT_SOCKET__GETATTR 0x00000010UL
873#define NETLINK_DNRT_SOCKET__SETATTR 0x00000020UL
874#define NETLINK_DNRT_SOCKET__LOCK 0x00000040UL
875#define NETLINK_DNRT_SOCKET__RELABELFROM 0x00000080UL
876#define NETLINK_DNRT_SOCKET__RELABELTO 0x00000100UL
877#define NETLINK_DNRT_SOCKET__APPEND 0x00000200UL
878#define NETLINK_DNRT_SOCKET__BIND 0x00000400UL
879#define NETLINK_DNRT_SOCKET__CONNECT 0x00000800UL
880#define NETLINK_DNRT_SOCKET__LISTEN 0x00001000UL
881#define NETLINK_DNRT_SOCKET__ACCEPT 0x00002000UL
882#define NETLINK_DNRT_SOCKET__GETOPT 0x00004000UL
883#define NETLINK_DNRT_SOCKET__SETOPT 0x00008000UL
884#define NETLINK_DNRT_SOCKET__SHUTDOWN 0x00010000UL
885#define NETLINK_DNRT_SOCKET__RECVFROM 0x00020000UL
886#define NETLINK_DNRT_SOCKET__SENDTO 0x00040000UL
887#define NETLINK_DNRT_SOCKET__RECV_MSG 0x00080000UL
888#define NETLINK_DNRT_SOCKET__SEND_MSG 0x00100000UL
889#define NETLINK_DNRT_SOCKET__NAME_BIND 0x00200000UL
890
891#define DBUS__ACQUIRE_SVC 0x00000001UL
892#define DBUS__SEND_MSG 0x00000002UL
893
894#define NSCD__GETPWD 0x00000001UL
895#define NSCD__GETGRP 0x00000002UL
896#define NSCD__GETHOST 0x00000004UL
897#define NSCD__GETSTAT 0x00000008UL
898#define NSCD__ADMIN 0x00000010UL
899#define NSCD__SHMEMPWD 0x00000020UL
900#define NSCD__SHMEMGRP 0x00000040UL
901#define NSCD__SHMEMHOST 0x00000080UL
902
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
new file mode 100644
index 00000000000..960ef18ddc4
--- /dev/null
+++ b/security/selinux/include/avc.h
@@ -0,0 +1,137 @@
1/*
2 * Access vector cache interface for object managers.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6#ifndef _SELINUX_AVC_H_
7#define _SELINUX_AVC_H_
8
9#include <linux/stddef.h>
10#include <linux/errno.h>
11#include <linux/kernel.h>
12#include <linux/kdev_t.h>
13#include <linux/spinlock.h>
14#include <linux/init.h>
15#include <linux/in6.h>
16#include <asm/system.h>
17#include "flask.h"
18#include "av_permissions.h"
19#include "security.h"
20
21#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
22extern int selinux_enforcing;
23#else
24#define selinux_enforcing 1
25#endif
26
27/*
28 * An entry in the AVC.
29 */
30struct avc_entry;
31
32struct task_struct;
33struct vfsmount;
34struct dentry;
35struct inode;
36struct sock;
37struct sk_buff;
38
39/* Auxiliary data to use in generating the audit record. */
40struct avc_audit_data {
41 char type;
42#define AVC_AUDIT_DATA_FS 1
43#define AVC_AUDIT_DATA_NET 2
44#define AVC_AUDIT_DATA_CAP 3
45#define AVC_AUDIT_DATA_IPC 4
46 struct task_struct *tsk;
47 union {
48 struct {
49 struct vfsmount *mnt;
50 struct dentry *dentry;
51 struct inode *inode;
52 } fs;
53 struct {
54 char *netif;
55 struct sock *sk;
56 u16 family;
57 u16 dport;
58 u16 sport;
59 union {
60 struct {
61 u32 daddr;
62 u32 saddr;
63 } v4;
64 struct {
65 struct in6_addr daddr;
66 struct in6_addr saddr;
67 } v6;
68 } fam;
69 } net;
70 int cap;
71 int ipc_id;
72 } u;
73};
74
75#define v4info fam.v4
76#define v6info fam.v6
77
78/* Initialize an AVC audit data structure. */
79#define AVC_AUDIT_DATA_INIT(_d,_t) \
80 { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; }
81
82/*
83 * AVC statistics
84 */
85struct avc_cache_stats
86{
87 unsigned int lookups;
88 unsigned int hits;
89 unsigned int misses;
90 unsigned int allocations;
91 unsigned int reclaims;
92 unsigned int frees;
93};
94
95/*
96 * AVC operations
97 */
98
99void __init avc_init(void);
100
101void avc_audit(u32 ssid, u32 tsid,
102 u16 tclass, u32 requested,
103 struct av_decision *avd, int result, struct avc_audit_data *auditdata);
104
105int avc_has_perm_noaudit(u32 ssid, u32 tsid,
106 u16 tclass, u32 requested,
107 struct av_decision *avd);
108
109int avc_has_perm(u32 ssid, u32 tsid,
110 u16 tclass, u32 requested,
111 struct avc_audit_data *auditdata);
112
113#define AVC_CALLBACK_GRANT 1
114#define AVC_CALLBACK_TRY_REVOKE 2
115#define AVC_CALLBACK_REVOKE 4
116#define AVC_CALLBACK_RESET 8
117#define AVC_CALLBACK_AUDITALLOW_ENABLE 16
118#define AVC_CALLBACK_AUDITALLOW_DISABLE 32
119#define AVC_CALLBACK_AUDITDENY_ENABLE 64
120#define AVC_CALLBACK_AUDITDENY_DISABLE 128
121
122int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
123 u16 tclass, u32 perms,
124 u32 *out_retained),
125 u32 events, u32 ssid, u32 tsid,
126 u16 tclass, u32 perms);
127
128/* Exported to selinuxfs */
129int avc_get_hash_stats(char *page);
130extern unsigned int avc_cache_threshold;
131
132#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
133DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats);
134#endif
135
136#endif /* _SELINUX_AVC_H_ */
137
diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h
new file mode 100644
index 00000000000..450a2831e2e
--- /dev/null
+++ b/security/selinux/include/avc_ss.h
@@ -0,0 +1,14 @@
1/*
2 * Access vector cache interface for the security server.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6#ifndef _SELINUX_AVC_SS_H_
7#define _SELINUX_AVC_SS_H_
8
9#include "flask.h"
10
11int avc_ss_reset(u32 seqno);
12
13#endif /* _SELINUX_AVC_SS_H_ */
14
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
new file mode 100644
index 00000000000..519a77d7394
--- /dev/null
+++ b/security/selinux/include/class_to_string.h
@@ -0,0 +1,58 @@
1/* This file is automatically generated. Do not edit. */
2/*
3 * Security object class definitions
4 */
5 S_("null")
6 S_("security")
7 S_("process")
8 S_("system")
9 S_("capability")
10 S_("filesystem")
11 S_("file")
12 S_("dir")
13 S_("fd")
14 S_("lnk_file")
15 S_("chr_file")
16 S_("blk_file")
17 S_("sock_file")
18 S_("fifo_file")
19 S_("socket")
20 S_("tcp_socket")
21 S_("udp_socket")
22 S_("rawip_socket")
23 S_("node")
24 S_("netif")
25 S_("netlink_socket")
26 S_("packet_socket")
27 S_("key_socket")
28 S_("unix_stream_socket")
29 S_("unix_dgram_socket")
30 S_("sem")
31 S_("msg")
32 S_("msgq")
33 S_("shm")
34 S_("ipc")
35 S_("passwd")
36 S_("drawable")
37 S_("window")
38 S_("gc")
39 S_("font")
40 S_("colormap")
41 S_("property")
42 S_("cursor")
43 S_("xclient")
44 S_("xinput")
45 S_("xserver")
46 S_("xextension")
47 S_("pax")
48 S_("netlink_route_socket")
49 S_("netlink_firewall_socket")
50 S_("netlink_tcpdiag_socket")
51 S_("netlink_nflog_socket")
52 S_("netlink_xfrm_socket")
53 S_("netlink_selinux_socket")
54 S_("netlink_audit_socket")
55 S_("netlink_ip6fw_socket")
56 S_("netlink_dnrt_socket")
57 S_("dbus")
58 S_("nscd")
diff --git a/security/selinux/include/common_perm_to_string.h b/security/selinux/include/common_perm_to_string.h
new file mode 100644
index 00000000000..ce5b6e2fe9d
--- /dev/null
+++ b/security/selinux/include/common_perm_to_string.h
@@ -0,0 +1,58 @@
1/* This file is automatically generated. Do not edit. */
2TB_(common_file_perm_to_string)
3 S_("ioctl")
4 S_("read")
5 S_("write")
6 S_("create")
7 S_("getattr")
8 S_("setattr")
9 S_("lock")
10 S_("relabelfrom")
11 S_("relabelto")
12 S_("append")
13 S_("unlink")
14 S_("link")
15 S_("rename")
16 S_("execute")
17 S_("swapon")
18 S_("quotaon")
19 S_("mounton")
20TE_(common_file_perm_to_string)
21
22TB_(common_socket_perm_to_string)
23 S_("ioctl")
24 S_("read")
25 S_("write")
26 S_("create")
27 S_("getattr")
28 S_("setattr")
29 S_("lock")
30 S_("relabelfrom")
31 S_("relabelto")
32 S_("append")
33 S_("bind")
34 S_("connect")
35 S_("listen")
36 S_("accept")
37 S_("getopt")
38 S_("setopt")
39 S_("shutdown")
40 S_("recvfrom")
41 S_("sendto")
42 S_("recv_msg")
43 S_("send_msg")
44 S_("name_bind")
45TE_(common_socket_perm_to_string)
46
47TB_(common_ipc_perm_to_string)
48 S_("create")
49 S_("destroy")
50 S_("getattr")
51 S_("setattr")
52 S_("read")
53 S_("write")
54 S_("associate")
55 S_("unix_read")
56 S_("unix_write")
57TE_(common_ipc_perm_to_string)
58
diff --git a/security/selinux/include/conditional.h b/security/selinux/include/conditional.h
new file mode 100644
index 00000000000..67ce7a8d830
--- /dev/null
+++ b/security/selinux/include/conditional.h
@@ -0,0 +1,22 @@
1/*
2 * Interface to booleans in the security server. This is exported
3 * for the selinuxfs.
4 *
5 * Author: Karl MacMillan <kmacmillan@tresys.com>
6 *
7 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, version 2.
11 */
12
13#ifndef _SELINUX_CONDITIONAL_H_
14#define _SELINUX_CONDITIONAL_H_
15
16int security_get_bools(int *len, char ***names, int **values);
17
18int security_set_bools(int len, int *values);
19
20int security_get_bool_value(int bool);
21
22#endif
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h
new file mode 100644
index 00000000000..4eef1b654e9
--- /dev/null
+++ b/security/selinux/include/flask.h
@@ -0,0 +1,95 @@
1/* This file is automatically generated. Do not edit. */
2#ifndef _SELINUX_FLASK_H_
3#define _SELINUX_FLASK_H_
4
5/*
6 * Security object class definitions
7 */
8#define SECCLASS_SECURITY 1
9#define SECCLASS_PROCESS 2
10#define SECCLASS_SYSTEM 3
11#define SECCLASS_CAPABILITY 4
12#define SECCLASS_FILESYSTEM 5
13#define SECCLASS_FILE 6
14#define SECCLASS_DIR 7
15#define SECCLASS_FD 8
16#define SECCLASS_LNK_FILE 9
17#define SECCLASS_CHR_FILE 10
18#define SECCLASS_BLK_FILE 11
19#define SECCLASS_SOCK_FILE 12
20#define SECCLASS_FIFO_FILE 13
21#define SECCLASS_SOCKET 14
22#define SECCLASS_TCP_SOCKET 15
23#define SECCLASS_UDP_SOCKET 16
24#define SECCLASS_RAWIP_SOCKET 17
25#define SECCLASS_NODE 18
26#define SECCLASS_NETIF 19
27#define SECCLASS_NETLINK_SOCKET 20
28#define SECCLASS_PACKET_SOCKET 21
29#define SECCLASS_KEY_SOCKET 22
30#define SECCLASS_UNIX_STREAM_SOCKET 23
31#define SECCLASS_UNIX_DGRAM_SOCKET 24
32#define SECCLASS_SEM 25
33#define SECCLASS_MSG 26
34#define SECCLASS_MSGQ 27
35#define SECCLASS_SHM 28
36#define SECCLASS_IPC 29
37#define SECCLASS_PASSWD 30
38#define SECCLASS_DRAWABLE 31
39#define SECCLASS_WINDOW 32
40#define SECCLASS_GC 33
41#define SECCLASS_FONT 34
42#define SECCLASS_COLORMAP 35
43#define SECCLASS_PROPERTY 36
44#define SECCLASS_CURSOR 37
45#define SECCLASS_XCLIENT 38
46#define SECCLASS_XINPUT 39
47#define SECCLASS_XSERVER 40
48#define SECCLASS_XEXTENSION 41
49#define SECCLASS_PAX 42
50#define SECCLASS_NETLINK_ROUTE_SOCKET 43
51#define SECCLASS_NETLINK_FIREWALL_SOCKET 44
52#define SECCLASS_NETLINK_TCPDIAG_SOCKET 45
53#define SECCLASS_NETLINK_NFLOG_SOCKET 46
54#define SECCLASS_NETLINK_XFRM_SOCKET 47
55#define SECCLASS_NETLINK_SELINUX_SOCKET 48
56#define SECCLASS_NETLINK_AUDIT_SOCKET 49
57#define SECCLASS_NETLINK_IP6FW_SOCKET 50
58#define SECCLASS_NETLINK_DNRT_SOCKET 51
59#define SECCLASS_DBUS 52
60#define SECCLASS_NSCD 53
61
62/*
63 * Security identifier indices for initial entities
64 */
65#define SECINITSID_KERNEL 1
66#define SECINITSID_SECURITY 2
67#define SECINITSID_UNLABELED 3
68#define SECINITSID_FS 4
69#define SECINITSID_FILE 5
70#define SECINITSID_FILE_LABELS 6
71#define SECINITSID_INIT 7
72#define SECINITSID_ANY_SOCKET 8
73#define SECINITSID_PORT 9
74#define SECINITSID_NETIF 10
75#define SECINITSID_NETMSG 11
76#define SECINITSID_NODE 12
77#define SECINITSID_IGMP_PACKET 13
78#define SECINITSID_ICMP_SOCKET 14
79#define SECINITSID_TCP_SOCKET 15
80#define SECINITSID_SYSCTL_MODPROBE 16
81#define SECINITSID_SYSCTL 17
82#define SECINITSID_SYSCTL_FS 18
83#define SECINITSID_SYSCTL_KERNEL 19
84#define SECINITSID_SYSCTL_NET 20
85#define SECINITSID_SYSCTL_NET_UNIX 21
86#define SECINITSID_SYSCTL_VM 22
87#define SECINITSID_SYSCTL_DEV 23
88#define SECINITSID_KMOD 24
89#define SECINITSID_POLICY 25
90#define SECINITSID_SCMP_PACKET 26
91#define SECINITSID_DEVNULL 27
92
93#define SECINITSID_NUM 27
94
95#endif
diff --git a/security/selinux/include/initial_sid_to_string.h b/security/selinux/include/initial_sid_to_string.h
new file mode 100644
index 00000000000..d4fac82793a
--- /dev/null
+++ b/security/selinux/include/initial_sid_to_string.h
@@ -0,0 +1,33 @@
1/* This file is automatically generated. Do not edit. */
2static char *initial_sid_to_string[] =
3{
4 "null",
5 "kernel",
6 "security",
7 "unlabeled",
8 "fs",
9 "file",
10 "file_labels",
11 "init",
12 "any_socket",
13 "port",
14 "netif",
15 "netmsg",
16 "node",
17 "igmp_packet",
18 "icmp_socket",
19 "tcp_socket",
20 "sysctl_modprobe",
21 "sysctl",
22 "sysctl_fs",
23 "sysctl_kernel",
24 "sysctl_net",
25 "sysctl_net_unix",
26 "sysctl_vm",
27 "sysctl_dev",
28 "kmod",
29 "policy",
30 "scmp_packet",
31 "devnull",
32};
33
diff --git a/security/selinux/include/netif.h b/security/selinux/include/netif.h
new file mode 100644
index 00000000000..8bd6f9992d2
--- /dev/null
+++ b/security/selinux/include/netif.h
@@ -0,0 +1,21 @@
1/*
2 * Network interface table.
3 *
4 * Network interfaces (devices) do not have a security field, so we
5 * maintain a table associating each interface with a SID.
6 *
7 * Author: James Morris <jmorris@redhat.com>
8 *
9 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2,
13 * as published by the Free Software Foundation.
14 */
15#ifndef _SELINUX_NETIF_H_
16#define _SELINUX_NETIF_H_
17
18int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid);
19
20#endif /* _SELINUX_NETIF_H_ */
21
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
new file mode 100644
index 00000000000..887937c8134
--- /dev/null
+++ b/security/selinux/include/objsec.h
@@ -0,0 +1,112 @@
1/*
2 * NSA Security-Enhanced Linux (SELinux) security module
3 *
4 * This file contains the SELinux security data structures for kernel objects.
5 *
6 * Author(s): Stephen Smalley, <sds@epoch.ncsc.mil>
7 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
10 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2,
16 * as published by the Free Software Foundation.
17 */
18#ifndef _SELINUX_OBJSEC_H_
19#define _SELINUX_OBJSEC_H_
20
21#include <linux/list.h>
22#include <linux/sched.h>
23#include <linux/fs.h>
24#include <linux/binfmts.h>
25#include <linux/in.h>
26#include "flask.h"
27#include "avc.h"
28
29struct task_security_struct {
30 unsigned long magic; /* magic number for this module */
31 struct task_struct *task; /* back pointer to task object */
32 u32 osid; /* SID prior to last execve */
33 u32 sid; /* current SID */
34 u32 exec_sid; /* exec SID */
35 u32 create_sid; /* fscreate SID */
36 u32 ptrace_sid; /* SID of ptrace parent */
37};
38
39struct inode_security_struct {
40 unsigned long magic; /* magic number for this module */
41 struct inode *inode; /* back pointer to inode object */
42 struct list_head list; /* list of inode_security_struct */
43 u32 task_sid; /* SID of creating task */
44 u32 sid; /* SID of this object */
45 u16 sclass; /* security class of this object */
46 unsigned char initialized; /* initialization flag */
47 struct semaphore sem;
48 unsigned char inherit; /* inherit SID from parent entry */
49};
50
51struct file_security_struct {
52 unsigned long magic; /* magic number for this module */
53 struct file *file; /* back pointer to file object */
54 u32 sid; /* SID of open file description */
55 u32 fown_sid; /* SID of file owner (for SIGIO) */
56};
57
58struct superblock_security_struct {
59 unsigned long magic; /* magic number for this module */
60 struct super_block *sb; /* back pointer to sb object */
61 struct list_head list; /* list of superblock_security_struct */
62 u32 sid; /* SID of file system */
63 u32 def_sid; /* default SID for labeling */
64 unsigned int behavior; /* labeling behavior */
65 unsigned char initialized; /* initialization flag */
66 unsigned char proc; /* proc fs */
67 struct semaphore sem;
68 struct list_head isec_head;
69 spinlock_t isec_lock;
70};
71
72struct msg_security_struct {
73 unsigned long magic; /* magic number for this module */
74 struct msg_msg *msg; /* back pointer */
75 u32 sid; /* SID of message */
76};
77
78struct ipc_security_struct {
79 unsigned long magic; /* magic number for this module */
80 struct kern_ipc_perm *ipc_perm; /* back pointer */
81 u16 sclass; /* security class of this object */
82 u32 sid; /* SID of IPC resource */
83};
84
85struct bprm_security_struct {
86 unsigned long magic; /* magic number for this module */
87 struct linux_binprm *bprm; /* back pointer to bprm object */
88 u32 sid; /* SID for transformed process */
89 unsigned char set;
90
91 /*
92 * unsafe is used to share failure information from bprm_apply_creds()
93 * to bprm_post_apply_creds().
94 */
95 char unsafe;
96};
97
98struct netif_security_struct {
99 struct net_device *dev; /* back pointer */
100 u32 if_sid; /* SID for this interface */
101 u32 msg_sid; /* default SID for messages received on this interface */
102};
103
104struct sk_security_struct {
105 unsigned long magic; /* magic number for this module */
106 struct sock *sk; /* back pointer to sk object */
107 u32 peer_sid; /* SID of peer */
108};
109
110extern unsigned int selinux_checkreqprot;
111
112#endif /* _SELINUX_OBJSEC_H_ */
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
new file mode 100644
index 00000000000..fa187c9a351
--- /dev/null
+++ b/security/selinux/include/security.h
@@ -0,0 +1,97 @@
1/*
2 * Security server interface.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 *
6 */
7
8#ifndef _SELINUX_SECURITY_H_
9#define _SELINUX_SECURITY_H_
10
11#include "flask.h"
12
13#define SECSID_NULL 0x00000000 /* unspecified SID */
14#define SECSID_WILD 0xffffffff /* wildcard SID */
15#define SECCLASS_NULL 0x0000 /* no class */
16
17#define SELINUX_MAGIC 0xf97cff8c
18
19/* Identify specific policy version changes */
20#define POLICYDB_VERSION_BASE 15
21#define POLICYDB_VERSION_BOOL 16
22#define POLICYDB_VERSION_IPV6 17
23#define POLICYDB_VERSION_NLCLASS 18
24#define POLICYDB_VERSION_VALIDATETRANS 19
25#define POLICYDB_VERSION_MLS 19
26
27/* Range of policy versions we understand*/
28#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
29#define POLICYDB_VERSION_MAX POLICYDB_VERSION_MLS
30
31#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
32extern int selinux_enabled;
33#else
34#define selinux_enabled 1
35#endif
36
37extern int selinux_mls_enabled;
38
39int security_load_policy(void * data, size_t len);
40
41struct av_decision {
42 u32 allowed;
43 u32 decided;
44 u32 auditallow;
45 u32 auditdeny;
46 u32 seqno;
47};
48
49int security_compute_av(u32 ssid, u32 tsid,
50 u16 tclass, u32 requested,
51 struct av_decision *avd);
52
53int security_transition_sid(u32 ssid, u32 tsid,
54 u16 tclass, u32 *out_sid);
55
56int security_member_sid(u32 ssid, u32 tsid,
57 u16 tclass, u32 *out_sid);
58
59int security_change_sid(u32 ssid, u32 tsid,
60 u16 tclass, u32 *out_sid);
61
62int security_sid_to_context(u32 sid, char **scontext,
63 u32 *scontext_len);
64
65int security_context_to_sid(char *scontext, u32 scontext_len,
66 u32 *out_sid);
67
68int security_get_user_sids(u32 callsid, char *username,
69 u32 **sids, u32 *nel);
70
71int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port,
72 u32 *out_sid);
73
74int security_netif_sid(char *name, u32 *if_sid,
75 u32 *msg_sid);
76
77int security_node_sid(u16 domain, void *addr, u32 addrlen,
78 u32 *out_sid);
79
80int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
81 u16 tclass);
82
83#define SECURITY_FS_USE_XATTR 1 /* use xattr */
84#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
85#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */
86#define SECURITY_FS_USE_GENFS 4 /* use the genfs support */
87#define SECURITY_FS_USE_NONE 5 /* no labeling support */
88#define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */
89
90int security_fs_use(const char *fstype, unsigned int *behavior,
91 u32 *sid);
92
93int security_genfs_sid(const char *fstype, char *name, u16 sclass,
94 u32 *sid);
95
96#endif /* _SELINUX_SECURITY_H_ */
97
diff --git a/security/selinux/netif.c b/security/selinux/netif.c
new file mode 100644
index 00000000000..718d7be9f4d
--- /dev/null
+++ b/security/selinux/netif.c
@@ -0,0 +1,270 @@
1/*
2 * Network interface table.
3 *
4 * Network interfaces (devices) do not have a security field, so we
5 * maintain a table associating each interface with a SID.
6 *
7 * Author: James Morris <jmorris@redhat.com>
8 *
9 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2,
13 * as published by the Free Software Foundation.
14 */
15#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/stddef.h>
18#include <linux/kernel.h>
19#include <linux/list.h>
20#include <linux/notifier.h>
21#include <linux/netdevice.h>
22#include <linux/rcupdate.h>
23
24#include "security.h"
25#include "objsec.h"
26#include "netif.h"
27
28#define SEL_NETIF_HASH_SIZE 64
29#define SEL_NETIF_HASH_MAX 1024
30
31#undef DEBUG
32
33#ifdef DEBUG
34#define DEBUGP printk
35#else
36#define DEBUGP(format, args...)
37#endif
38
39struct sel_netif
40{
41 struct list_head list;
42 struct netif_security_struct nsec;
43 struct rcu_head rcu_head;
44};
45
46static u32 sel_netif_total;
47static LIST_HEAD(sel_netif_list);
48static DEFINE_SPINLOCK(sel_netif_lock);
49static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE];
50
51static inline u32 sel_netif_hasfn(struct net_device *dev)
52{
53 return (dev->ifindex & (SEL_NETIF_HASH_SIZE - 1));
54}
55
56/*
57 * All of the devices should normally fit in the hash, so we optimize
58 * for that case.
59 */
60static inline struct sel_netif *sel_netif_find(struct net_device *dev)
61{
62 struct list_head *pos;
63 int idx = sel_netif_hasfn(dev);
64
65 __list_for_each_rcu(pos, &sel_netif_hash[idx]) {
66 struct sel_netif *netif = list_entry(pos,
67 struct sel_netif, list);
68 if (likely(netif->nsec.dev == dev))
69 return netif;
70 }
71 return NULL;
72}
73
74static int sel_netif_insert(struct sel_netif *netif)
75{
76 int idx, ret = 0;
77
78 if (sel_netif_total >= SEL_NETIF_HASH_MAX) {
79 ret = -ENOSPC;
80 goto out;
81 }
82
83 idx = sel_netif_hasfn(netif->nsec.dev);
84 list_add_rcu(&netif->list, &sel_netif_hash[idx]);
85 sel_netif_total++;
86out:
87 return ret;
88}
89
90static void sel_netif_free(struct rcu_head *p)
91{
92 struct sel_netif *netif = container_of(p, struct sel_netif, rcu_head);
93
94 DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name);
95 kfree(netif);
96}
97
98static void sel_netif_destroy(struct sel_netif *netif)
99{
100 DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name);
101
102 list_del_rcu(&netif->list);
103 sel_netif_total--;
104 call_rcu(&netif->rcu_head, sel_netif_free);
105}
106
107static struct sel_netif *sel_netif_lookup(struct net_device *dev)
108{
109 int ret;
110 struct sel_netif *netif, *new;
111 struct netif_security_struct *nsec;
112
113 netif = sel_netif_find(dev);
114 if (likely(netif != NULL))
115 goto out;
116
117 new = kmalloc(sizeof(*new), GFP_ATOMIC);
118 if (!new) {
119 netif = ERR_PTR(-ENOMEM);
120 goto out;
121 }
122
123 memset(new, 0, sizeof(*new));
124 nsec = &new->nsec;
125
126 ret = security_netif_sid(dev->name, &nsec->if_sid, &nsec->msg_sid);
127 if (ret < 0) {
128 kfree(new);
129 netif = ERR_PTR(ret);
130 goto out;
131 }
132
133 nsec->dev = dev;
134
135 spin_lock_bh(&sel_netif_lock);
136
137 netif = sel_netif_find(dev);
138 if (netif) {
139 spin_unlock_bh(&sel_netif_lock);
140 kfree(new);
141 goto out;
142 }
143
144 ret = sel_netif_insert(new);
145 spin_unlock_bh(&sel_netif_lock);
146
147 if (ret) {
148 kfree(new);
149 netif = ERR_PTR(ret);
150 goto out;
151 }
152
153 netif = new;
154
155 DEBUGP("new: ifindex=%u name=%s if_sid=%u msg_sid=%u\n", dev->ifindex, dev->name,
156 nsec->if_sid, nsec->msg_sid);
157out:
158 return netif;
159}
160
161static void sel_netif_assign_sids(u32 if_sid_in, u32 msg_sid_in, u32 *if_sid_out, u32 *msg_sid_out)
162{
163 if (if_sid_out)
164 *if_sid_out = if_sid_in;
165 if (msg_sid_out)
166 *msg_sid_out = msg_sid_in;
167}
168
169static int sel_netif_sids_slow(struct net_device *dev, u32 *if_sid, u32 *msg_sid)
170{
171 int ret = 0;
172 u32 tmp_if_sid, tmp_msg_sid;
173
174 ret = security_netif_sid(dev->name, &tmp_if_sid, &tmp_msg_sid);
175 if (!ret)
176 sel_netif_assign_sids(tmp_if_sid, tmp_msg_sid, if_sid, msg_sid);
177 return ret;
178}
179
180int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid)
181{
182 int ret = 0;
183 struct sel_netif *netif;
184
185 rcu_read_lock();
186 netif = sel_netif_lookup(dev);
187 if (IS_ERR(netif)) {
188 rcu_read_unlock();
189 ret = sel_netif_sids_slow(dev, if_sid, msg_sid);
190 goto out;
191 }
192 sel_netif_assign_sids(netif->nsec.if_sid, netif->nsec.msg_sid, if_sid, msg_sid);
193 rcu_read_unlock();
194out:
195 return ret;
196}
197
198static void sel_netif_kill(struct net_device *dev)
199{
200 struct sel_netif *netif;
201
202 spin_lock_bh(&sel_netif_lock);
203 netif = sel_netif_find(dev);
204 if (netif)
205 sel_netif_destroy(netif);
206 spin_unlock_bh(&sel_netif_lock);
207}
208
209static void sel_netif_flush(void)
210{
211 int idx;
212
213 spin_lock_bh(&sel_netif_lock);
214 for (idx = 0; idx < SEL_NETIF_HASH_SIZE; idx++) {
215 struct sel_netif *netif;
216
217 list_for_each_entry(netif, &sel_netif_hash[idx], list)
218 sel_netif_destroy(netif);
219 }
220 spin_unlock_bh(&sel_netif_lock);
221}
222
223static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid,
224 u16 class, u32 perms, u32 *retained)
225{
226 if (event == AVC_CALLBACK_RESET) {
227 sel_netif_flush();
228 synchronize_net();
229 }
230 return 0;
231}
232
233static int sel_netif_netdev_notifier_handler(struct notifier_block *this,
234 unsigned long event, void *ptr)
235{
236 struct net_device *dev = ptr;
237
238 if (event == NETDEV_DOWN)
239 sel_netif_kill(dev);
240
241 return NOTIFY_DONE;
242}
243
244static struct notifier_block sel_netif_netdev_notifier = {
245 .notifier_call = sel_netif_netdev_notifier_handler,
246};
247
248static __init int sel_netif_init(void)
249{
250 int i, err = 0;
251
252 if (!selinux_enabled)
253 goto out;
254
255 for (i = 0; i < SEL_NETIF_HASH_SIZE; i++)
256 INIT_LIST_HEAD(&sel_netif_hash[i]);
257
258 register_netdevice_notifier(&sel_netif_netdev_notifier);
259
260 err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET,
261 SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
262 if (err)
263 panic("avc_add_callback() failed, error %d\n", err);
264
265out:
266 return err;
267}
268
269__initcall(sel_netif_init);
270
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c
new file mode 100644
index 00000000000..18d08acafa7
--- /dev/null
+++ b/security/selinux/netlink.c
@@ -0,0 +1,113 @@
1/*
2 * Netlink event notifications for SELinux.
3 *
4 * Author: James Morris <jmorris@redhat.com>
5 *
6 * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2,
10 * as published by the Free Software Foundation.
11 */
12#include <linux/init.h>
13#include <linux/types.h>
14#include <linux/stddef.h>
15#include <linux/kernel.h>
16#include <linux/list.h>
17#include <linux/skbuff.h>
18#include <linux/netlink.h>
19#include <linux/selinux_netlink.h>
20
21static struct sock *selnl;
22
23static int selnl_msglen(int msgtype)
24{
25 int ret = 0;
26
27 switch (msgtype) {
28 case SELNL_MSG_SETENFORCE:
29 ret = sizeof(struct selnl_msg_setenforce);
30 break;
31
32 case SELNL_MSG_POLICYLOAD:
33 ret = sizeof(struct selnl_msg_policyload);
34 break;
35
36 default:
37 BUG();
38 }
39 return ret;
40}
41
42static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void *data)
43{
44 switch (msgtype) {
45 case SELNL_MSG_SETENFORCE: {
46 struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
47
48 memset(msg, 0, len);
49 msg->val = *((int *)data);
50 break;
51 }
52
53 case SELNL_MSG_POLICYLOAD: {
54 struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
55
56 memset(msg, 0, len);
57 msg->seqno = *((u32 *)data);
58 break;
59 }
60
61 default:
62 BUG();
63 }
64}
65
66static void selnl_notify(int msgtype, void *data)
67{
68 int len;
69 unsigned char *tmp;
70 struct sk_buff *skb;
71 struct nlmsghdr *nlh;
72
73 len = selnl_msglen(msgtype);
74
75 skb = alloc_skb(NLMSG_SPACE(len), GFP_USER);
76 if (!skb)
77 goto oom;
78
79 tmp = skb->tail;
80 nlh = NLMSG_PUT(skb, 0, 0, msgtype, len);
81 selnl_add_payload(nlh, len, msgtype, data);
82 nlh->nlmsg_len = skb->tail - tmp;
83 netlink_broadcast(selnl, skb, 0, SELNL_GRP_AVC, GFP_USER);
84out:
85 return;
86
87nlmsg_failure:
88 kfree_skb(skb);
89oom:
90 printk(KERN_ERR "SELinux: OOM in %s\n", __FUNCTION__);
91 goto out;
92}
93
94void selnl_notify_setenforce(int val)
95{
96 selnl_notify(SELNL_MSG_SETENFORCE, &val);
97}
98
99void selnl_notify_policyload(u32 seqno)
100{
101 selnl_notify(SELNL_MSG_POLICYLOAD, &seqno);
102}
103
104static int __init selnl_init(void)
105{
106 selnl = netlink_kernel_create(NETLINK_SELINUX, NULL);
107 if (selnl == NULL)
108 panic("SELinux: Cannot create netlink socket.");
109 netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);
110 return 0;
111}
112
113__initcall(selnl_init);
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
new file mode 100644
index 00000000000..fa7fa030e6e
--- /dev/null
+++ b/security/selinux/nlmsgtab.c
@@ -0,0 +1,156 @@
1/*
2 * Netlink message type permission tables, for user generated messages.
3 *
4 * Author: James Morris <jmorris@redhat.com>
5 *
6 * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2,
10 * as published by the Free Software Foundation.
11 */
12#include <linux/types.h>
13#include <linux/kernel.h>
14#include <linux/skbuff.h>
15#include <linux/netlink.h>
16#include <linux/rtnetlink.h>
17#include <linux/if.h>
18#include <linux/netfilter_ipv4/ip_queue.h>
19#include <linux/tcp_diag.h>
20#include <linux/xfrm.h>
21#include <linux/audit.h>
22
23#include "flask.h"
24#include "av_permissions.h"
25
26struct nlmsg_perm
27{
28 u16 nlmsg_type;
29 u32 perm;
30};
31
32static struct nlmsg_perm nlmsg_route_perms[] =
33{
34 { RTM_NEWLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
35 { RTM_DELLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
36 { RTM_GETLINK, NETLINK_ROUTE_SOCKET__NLMSG_READ },
37 { RTM_SETLINK, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
38 { RTM_NEWADDR, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
39 { RTM_DELADDR, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
40 { RTM_GETADDR, NETLINK_ROUTE_SOCKET__NLMSG_READ },
41 { RTM_NEWROUTE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
42 { RTM_DELROUTE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
43 { RTM_GETROUTE, NETLINK_ROUTE_SOCKET__NLMSG_READ },
44 { RTM_NEWNEIGH, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
45 { RTM_DELNEIGH, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
46 { RTM_GETNEIGH, NETLINK_ROUTE_SOCKET__NLMSG_READ },
47 { RTM_NEWRULE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
48 { RTM_DELRULE, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
49 { RTM_GETRULE, NETLINK_ROUTE_SOCKET__NLMSG_READ },
50 { RTM_NEWQDISC, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
51 { RTM_DELQDISC, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
52 { RTM_GETQDISC, NETLINK_ROUTE_SOCKET__NLMSG_READ },
53 { RTM_NEWTCLASS, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
54 { RTM_DELTCLASS, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
55 { RTM_GETTCLASS, NETLINK_ROUTE_SOCKET__NLMSG_READ },
56 { RTM_NEWTFILTER, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
57 { RTM_DELTFILTER, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
58 { RTM_GETTFILTER, NETLINK_ROUTE_SOCKET__NLMSG_READ },
59 { RTM_NEWACTION, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
60 { RTM_DELACTION, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
61 { RTM_GETACTION, NETLINK_ROUTE_SOCKET__NLMSG_READ },
62 { RTM_NEWPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
63 { RTM_GETPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_READ },
64 { RTM_GETMULTICAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
65 { RTM_GETANYCAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
66};
67
68static struct nlmsg_perm nlmsg_firewall_perms[] =
69{
70 { IPQM_MODE, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE },
71 { IPQM_VERDICT, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE },
72};
73
74static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
75{
76 { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
77};
78
79static struct nlmsg_perm nlmsg_xfrm_perms[] =
80{
81 { XFRM_MSG_NEWSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
82 { XFRM_MSG_DELSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
83 { XFRM_MSG_GETSA, NETLINK_XFRM_SOCKET__NLMSG_READ },
84 { XFRM_MSG_NEWPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
85 { XFRM_MSG_DELPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
86 { XFRM_MSG_GETPOLICY, NETLINK_XFRM_SOCKET__NLMSG_READ },
87 { XFRM_MSG_ALLOCSPI, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
88 { XFRM_MSG_UPDPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
89 { XFRM_MSG_UPDSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
90};
91
92static struct nlmsg_perm nlmsg_audit_perms[] =
93{
94 { AUDIT_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ },
95 { AUDIT_SET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
96 { AUDIT_LIST, NETLINK_AUDIT_SOCKET__NLMSG_READ },
97 { AUDIT_ADD, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
98 { AUDIT_DEL, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
99 { AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
100 { AUDIT_LOGIN, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
101};
102
103
104static int nlmsg_perm(u16 nlmsg_type, u32 *perm, struct nlmsg_perm *tab, size_t tabsize)
105{
106 int i, err = -EINVAL;
107
108 for (i = 0; i < tabsize/sizeof(struct nlmsg_perm); i++)
109 if (nlmsg_type == tab[i].nlmsg_type) {
110 *perm = tab[i].perm;
111 err = 0;
112 break;
113 }
114
115 return err;
116}
117
118int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
119{
120 int err = 0;
121
122 switch (sclass) {
123 case SECCLASS_NETLINK_ROUTE_SOCKET:
124 err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms,
125 sizeof(nlmsg_route_perms));
126 break;
127
128 case SECCLASS_NETLINK_FIREWALL_SOCKET:
129 case NETLINK_IP6_FW:
130 err = nlmsg_perm(nlmsg_type, perm, nlmsg_firewall_perms,
131 sizeof(nlmsg_firewall_perms));
132 break;
133
134 case SECCLASS_NETLINK_TCPDIAG_SOCKET:
135 err = nlmsg_perm(nlmsg_type, perm, nlmsg_tcpdiag_perms,
136 sizeof(nlmsg_tcpdiag_perms));
137 break;
138
139 case SECCLASS_NETLINK_XFRM_SOCKET:
140 err = nlmsg_perm(nlmsg_type, perm, nlmsg_xfrm_perms,
141 sizeof(nlmsg_xfrm_perms));
142 break;
143
144 case SECCLASS_NETLINK_AUDIT_SOCKET:
145 err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
146 sizeof(nlmsg_audit_perms));
147 break;
148
149 /* No messaging from userspace, or class unknown/unhandled */
150 default:
151 err = -ENOENT;
152 break;
153 }
154
155 return err;
156}
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
new file mode 100644
index 00000000000..07221568b50
--- /dev/null
+++ b/security/selinux/selinuxfs.c
@@ -0,0 +1,1340 @@
1/* Updated: Karl MacMillan <kmacmillan@tresys.com>
2 *
3 * Added conditional policy language extensions
4 *
5 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
6 * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 2.
10 */
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/pagemap.h>
15#include <linux/slab.h>
16#include <linux/vmalloc.h>
17#include <linux/fs.h>
18#include <linux/init.h>
19#include <linux/string.h>
20#include <linux/security.h>
21#include <linux/major.h>
22#include <linux/seq_file.h>
23#include <linux/percpu.h>
24#include <asm/uaccess.h>
25#include <asm/semaphore.h>
26
27/* selinuxfs pseudo filesystem for exporting the security policy API.
28 Based on the proc code and the fs/nfsd/nfsctl.c code. */
29
30#include "flask.h"
31#include "avc.h"
32#include "avc_ss.h"
33#include "security.h"
34#include "objsec.h"
35#include "conditional.h"
36
37unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
38
39static int __init checkreqprot_setup(char *str)
40{
41 selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
42 return 1;
43}
44__setup("checkreqprot=", checkreqprot_setup);
45
46
47static DECLARE_MUTEX(sel_sem);
48
49/* global data for booleans */
50static struct dentry *bool_dir = NULL;
51static int bool_num = 0;
52static int *bool_pending_values = NULL;
53
54extern void selnl_notify_setenforce(int val);
55
56/* Check whether a task is allowed to use a security operation. */
57static int task_has_security(struct task_struct *tsk,
58 u32 perms)
59{
60 struct task_security_struct *tsec;
61
62 tsec = tsk->security;
63 if (!tsec)
64 return -EACCES;
65
66 return avc_has_perm(tsec->sid, SECINITSID_SECURITY,
67 SECCLASS_SECURITY, perms, NULL);
68}
69
70enum sel_inos {
71 SEL_ROOT_INO = 2,
72 SEL_LOAD, /* load policy */
73 SEL_ENFORCE, /* get or set enforcing status */
74 SEL_CONTEXT, /* validate context */
75 SEL_ACCESS, /* compute access decision */
76 SEL_CREATE, /* compute create labeling decision */
77 SEL_RELABEL, /* compute relabeling decision */
78 SEL_USER, /* compute reachable user contexts */
79 SEL_POLICYVERS, /* return policy version for this kernel */
80 SEL_COMMIT_BOOLS, /* commit new boolean values */
81 SEL_MLS, /* return if MLS policy is enabled */
82 SEL_DISABLE, /* disable SELinux until next reboot */
83 SEL_AVC, /* AVC management directory */
84 SEL_MEMBER, /* compute polyinstantiation membership decision */
85 SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
86};
87
88#define TMPBUFLEN 12
89static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
90 size_t count, loff_t *ppos)
91{
92 char tmpbuf[TMPBUFLEN];
93 ssize_t length;
94
95 length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_enforcing);
96 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
97}
98
99#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
100static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
101 size_t count, loff_t *ppos)
102
103{
104 char *page;
105 ssize_t length;
106 int new_value;
107
108 if (count < 0 || count >= PAGE_SIZE)
109 return -ENOMEM;
110 if (*ppos != 0) {
111 /* No partial writes. */
112 return -EINVAL;
113 }
114 page = (char*)get_zeroed_page(GFP_KERNEL);
115 if (!page)
116 return -ENOMEM;
117 length = -EFAULT;
118 if (copy_from_user(page, buf, count))
119 goto out;
120
121 length = -EINVAL;
122 if (sscanf(page, "%d", &new_value) != 1)
123 goto out;
124
125 if (new_value != selinux_enforcing) {
126 length = task_has_security(current, SECURITY__SETENFORCE);
127 if (length)
128 goto out;
129 selinux_enforcing = new_value;
130 if (selinux_enforcing)
131 avc_ss_reset(0);
132 selnl_notify_setenforce(selinux_enforcing);
133 }
134 length = count;
135out:
136 free_page((unsigned long) page);
137 return length;
138}
139#else
140#define sel_write_enforce NULL
141#endif
142
143static struct file_operations sel_enforce_ops = {
144 .read = sel_read_enforce,
145 .write = sel_write_enforce,
146};
147
148#ifdef CONFIG_SECURITY_SELINUX_DISABLE
149static ssize_t sel_write_disable(struct file * file, const char __user * buf,
150 size_t count, loff_t *ppos)
151
152{
153 char *page;
154 ssize_t length;
155 int new_value;
156 extern int selinux_disable(void);
157
158 if (count < 0 || count >= PAGE_SIZE)
159 return -ENOMEM;
160 if (*ppos != 0) {
161 /* No partial writes. */
162 return -EINVAL;
163 }
164 page = (char*)get_zeroed_page(GFP_KERNEL);
165 if (!page)
166 return -ENOMEM;
167 length = -EFAULT;
168 if (copy_from_user(page, buf, count))
169 goto out;
170
171 length = -EINVAL;
172 if (sscanf(page, "%d", &new_value) != 1)
173 goto out;
174
175 if (new_value) {
176 length = selinux_disable();
177 if (length < 0)
178 goto out;
179 }
180
181 length = count;
182out:
183 free_page((unsigned long) page);
184 return length;
185}
186#else
187#define sel_write_disable NULL
188#endif
189
190static struct file_operations sel_disable_ops = {
191 .write = sel_write_disable,
192};
193
194static ssize_t sel_read_policyvers(struct file *filp, char __user *buf,
195 size_t count, loff_t *ppos)
196{
197 char tmpbuf[TMPBUFLEN];
198 ssize_t length;
199
200 length = scnprintf(tmpbuf, TMPBUFLEN, "%u", POLICYDB_VERSION_MAX);
201 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
202}
203
204static struct file_operations sel_policyvers_ops = {
205 .read = sel_read_policyvers,
206};
207
208/* declaration for sel_write_load */
209static int sel_make_bools(void);
210
211static ssize_t sel_read_mls(struct file *filp, char __user *buf,
212 size_t count, loff_t *ppos)
213{
214 char tmpbuf[TMPBUFLEN];
215 ssize_t length;
216
217 length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled);
218 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
219}
220
221static struct file_operations sel_mls_ops = {
222 .read = sel_read_mls,
223};
224
225static ssize_t sel_write_load(struct file * file, const char __user * buf,
226 size_t count, loff_t *ppos)
227
228{
229 int ret;
230 ssize_t length;
231 void *data = NULL;
232
233 down(&sel_sem);
234
235 length = task_has_security(current, SECURITY__LOAD_POLICY);
236 if (length)
237 goto out;
238
239 if (*ppos != 0) {
240 /* No partial writes. */
241 length = -EINVAL;
242 goto out;
243 }
244
245 if ((count < 0) || (count > 64 * 1024 * 1024)
246 || (data = vmalloc(count)) == NULL) {
247 length = -ENOMEM;
248 goto out;
249 }
250
251 length = -EFAULT;
252 if (copy_from_user(data, buf, count) != 0)
253 goto out;
254
255 length = security_load_policy(data, count);
256 if (length)
257 goto out;
258
259 ret = sel_make_bools();
260 if (ret)
261 length = ret;
262 else
263 length = count;
264out:
265 up(&sel_sem);
266 vfree(data);
267 return length;
268}
269
270static struct file_operations sel_load_ops = {
271 .write = sel_write_load,
272};
273
274
275static ssize_t sel_write_context(struct file * file, const char __user * buf,
276 size_t count, loff_t *ppos)
277
278{
279 char *page;
280 u32 sid;
281 ssize_t length;
282
283 length = task_has_security(current, SECURITY__CHECK_CONTEXT);
284 if (length)
285 return length;
286
287 if (count < 0 || count >= PAGE_SIZE)
288 return -ENOMEM;
289 if (*ppos != 0) {
290 /* No partial writes. */
291 return -EINVAL;
292 }
293 page = (char*)get_zeroed_page(GFP_KERNEL);
294 if (!page)
295 return -ENOMEM;
296 length = -EFAULT;
297 if (copy_from_user(page, buf, count))
298 goto out;
299
300 length = security_context_to_sid(page, count, &sid);
301 if (length < 0)
302 goto out;
303
304 length = count;
305out:
306 free_page((unsigned long) page);
307 return length;
308}
309
310static struct file_operations sel_context_ops = {
311 .write = sel_write_context,
312};
313
314static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
315 size_t count, loff_t *ppos)
316{
317 char tmpbuf[TMPBUFLEN];
318 ssize_t length;
319
320 length = scnprintf(tmpbuf, TMPBUFLEN, "%u", selinux_checkreqprot);
321 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
322}
323
324static ssize_t sel_write_checkreqprot(struct file * file, const char __user * buf,
325 size_t count, loff_t *ppos)
326{
327 char *page;
328 ssize_t length;
329 unsigned int new_value;
330
331 length = task_has_security(current, SECURITY__SETCHECKREQPROT);
332 if (length)
333 return length;
334
335 if (count < 0 || count >= PAGE_SIZE)
336 return -ENOMEM;
337 if (*ppos != 0) {
338 /* No partial writes. */
339 return -EINVAL;
340 }
341 page = (char*)get_zeroed_page(GFP_KERNEL);
342 if (!page)
343 return -ENOMEM;
344 length = -EFAULT;
345 if (copy_from_user(page, buf, count))
346 goto out;
347
348 length = -EINVAL;
349 if (sscanf(page, "%u", &new_value) != 1)
350 goto out;
351
352 selinux_checkreqprot = new_value ? 1 : 0;
353 length = count;
354out:
355 free_page((unsigned long) page);
356 return length;
357}
358static struct file_operations sel_checkreqprot_ops = {
359 .read = sel_read_checkreqprot,
360 .write = sel_write_checkreqprot,
361};
362
363/*
364 * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
365 */
366static ssize_t sel_write_access(struct file * file, char *buf, size_t size);
367static ssize_t sel_write_create(struct file * file, char *buf, size_t size);
368static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size);
369static ssize_t sel_write_user(struct file * file, char *buf, size_t size);
370static ssize_t sel_write_member(struct file * file, char *buf, size_t size);
371
372static ssize_t (*write_op[])(struct file *, char *, size_t) = {
373 [SEL_ACCESS] = sel_write_access,
374 [SEL_CREATE] = sel_write_create,
375 [SEL_RELABEL] = sel_write_relabel,
376 [SEL_USER] = sel_write_user,
377 [SEL_MEMBER] = sel_write_member,
378};
379
380static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
381{
382 ino_t ino = file->f_dentry->d_inode->i_ino;
383 char *data;
384 ssize_t rv;
385
386 if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
387 return -EINVAL;
388
389 data = simple_transaction_get(file, buf, size);
390 if (IS_ERR(data))
391 return PTR_ERR(data);
392
393 rv = write_op[ino](file, data, size);
394 if (rv>0) {
395 simple_transaction_set(file, rv);
396 rv = size;
397 }
398 return rv;
399}
400
401static struct file_operations transaction_ops = {
402 .write = selinux_transaction_write,
403 .read = simple_transaction_read,
404 .release = simple_transaction_release,
405};
406
407/*
408 * payload - write methods
409 * If the method has a response, the response should be put in buf,
410 * and the length returned. Otherwise return 0 or and -error.
411 */
412
413static ssize_t sel_write_access(struct file * file, char *buf, size_t size)
414{
415 char *scon, *tcon;
416 u32 ssid, tsid;
417 u16 tclass;
418 u32 req;
419 struct av_decision avd;
420 ssize_t length;
421
422 length = task_has_security(current, SECURITY__COMPUTE_AV);
423 if (length)
424 return length;
425
426 length = -ENOMEM;
427 scon = kmalloc(size+1, GFP_KERNEL);
428 if (!scon)
429 return length;
430 memset(scon, 0, size+1);
431
432 tcon = kmalloc(size+1, GFP_KERNEL);
433 if (!tcon)
434 goto out;
435 memset(tcon, 0, size+1);
436
437 length = -EINVAL;
438 if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4)
439 goto out2;
440
441 length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
442 if (length < 0)
443 goto out2;
444 length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
445 if (length < 0)
446 goto out2;
447
448 length = security_compute_av(ssid, tsid, tclass, req, &avd);
449 if (length < 0)
450 goto out2;
451
452 length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
453 "%x %x %x %x %u",
454 avd.allowed, avd.decided,
455 avd.auditallow, avd.auditdeny,
456 avd.seqno);
457out2:
458 kfree(tcon);
459out:
460 kfree(scon);
461 return length;
462}
463
464static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
465{
466 char *scon, *tcon;
467 u32 ssid, tsid, newsid;
468 u16 tclass;
469 ssize_t length;
470 char *newcon;
471 u32 len;
472
473 length = task_has_security(current, SECURITY__COMPUTE_CREATE);
474 if (length)
475 return length;
476
477 length = -ENOMEM;
478 scon = kmalloc(size+1, GFP_KERNEL);
479 if (!scon)
480 return length;
481 memset(scon, 0, size+1);
482
483 tcon = kmalloc(size+1, GFP_KERNEL);
484 if (!tcon)
485 goto out;
486 memset(tcon, 0, size+1);
487
488 length = -EINVAL;
489 if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
490 goto out2;
491
492 length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
493 if (length < 0)
494 goto out2;
495 length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
496 if (length < 0)
497 goto out2;
498
499 length = security_transition_sid(ssid, tsid, tclass, &newsid);
500 if (length < 0)
501 goto out2;
502
503 length = security_sid_to_context(newsid, &newcon, &len);
504 if (length < 0)
505 goto out2;
506
507 if (len > SIMPLE_TRANSACTION_LIMIT) {
508 printk(KERN_ERR "%s: context size (%u) exceeds payload "
509 "max\n", __FUNCTION__, len);
510 length = -ERANGE;
511 goto out3;
512 }
513
514 memcpy(buf, newcon, len);
515 length = len;
516out3:
517 kfree(newcon);
518out2:
519 kfree(tcon);
520out:
521 kfree(scon);
522 return length;
523}
524
525static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size)
526{
527 char *scon, *tcon;
528 u32 ssid, tsid, newsid;
529 u16 tclass;
530 ssize_t length;
531 char *newcon;
532 u32 len;
533
534 length = task_has_security(current, SECURITY__COMPUTE_RELABEL);
535 if (length)
536 return length;
537
538 length = -ENOMEM;
539 scon = kmalloc(size+1, GFP_KERNEL);
540 if (!scon)
541 return length;
542 memset(scon, 0, size+1);
543
544 tcon = kmalloc(size+1, GFP_KERNEL);
545 if (!tcon)
546 goto out;
547 memset(tcon, 0, size+1);
548
549 length = -EINVAL;
550 if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
551 goto out2;
552
553 length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
554 if (length < 0)
555 goto out2;
556 length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
557 if (length < 0)
558 goto out2;
559
560 length = security_change_sid(ssid, tsid, tclass, &newsid);
561 if (length < 0)
562 goto out2;
563
564 length = security_sid_to_context(newsid, &newcon, &len);
565 if (length < 0)
566 goto out2;
567
568 if (len > SIMPLE_TRANSACTION_LIMIT) {
569 length = -ERANGE;
570 goto out3;
571 }
572
573 memcpy(buf, newcon, len);
574 length = len;
575out3:
576 kfree(newcon);
577out2:
578 kfree(tcon);
579out:
580 kfree(scon);
581 return length;
582}
583
584static ssize_t sel_write_user(struct file * file, char *buf, size_t size)
585{
586 char *con, *user, *ptr;
587 u32 sid, *sids;
588 ssize_t length;
589 char *newcon;
590 int i, rc;
591 u32 len, nsids;
592
593 length = task_has_security(current, SECURITY__COMPUTE_USER);
594 if (length)
595 return length;
596
597 length = -ENOMEM;
598 con = kmalloc(size+1, GFP_KERNEL);
599 if (!con)
600 return length;
601 memset(con, 0, size+1);
602
603 user = kmalloc(size+1, GFP_KERNEL);
604 if (!user)
605 goto out;
606 memset(user, 0, size+1);
607
608 length = -EINVAL;
609 if (sscanf(buf, "%s %s", con, user) != 2)
610 goto out2;
611
612 length = security_context_to_sid(con, strlen(con)+1, &sid);
613 if (length < 0)
614 goto out2;
615
616 length = security_get_user_sids(sid, user, &sids, &nsids);
617 if (length < 0)
618 goto out2;
619
620 length = sprintf(buf, "%u", nsids) + 1;
621 ptr = buf + length;
622 for (i = 0; i < nsids; i++) {
623 rc = security_sid_to_context(sids[i], &newcon, &len);
624 if (rc) {
625 length = rc;
626 goto out3;
627 }
628 if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) {
629 kfree(newcon);
630 length = -ERANGE;
631 goto out3;
632 }
633 memcpy(ptr, newcon, len);
634 kfree(newcon);
635 ptr += len;
636 length += len;
637 }
638out3:
639 kfree(sids);
640out2:
641 kfree(user);
642out:
643 kfree(con);
644 return length;
645}
646
647static ssize_t sel_write_member(struct file * file, char *buf, size_t size)
648{
649 char *scon, *tcon;
650 u32 ssid, tsid, newsid;
651 u16 tclass;
652 ssize_t length;
653 char *newcon;
654 u32 len;
655
656 length = task_has_security(current, SECURITY__COMPUTE_MEMBER);
657 if (length)
658 return length;
659
660 length = -ENOMEM;
661 scon = kmalloc(size+1, GFP_KERNEL);
662 if (!scon)
663 return length;
664 memset(scon, 0, size+1);
665
666 tcon = kmalloc(size+1, GFP_KERNEL);
667 if (!tcon)
668 goto out;
669 memset(tcon, 0, size+1);
670
671 length = -EINVAL;
672 if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
673 goto out2;
674
675 length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
676 if (length < 0)
677 goto out2;
678 length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
679 if (length < 0)
680 goto out2;
681
682 length = security_member_sid(ssid, tsid, tclass, &newsid);
683 if (length < 0)
684 goto out2;
685
686 length = security_sid_to_context(newsid, &newcon, &len);
687 if (length < 0)
688 goto out2;
689
690 if (len > SIMPLE_TRANSACTION_LIMIT) {
691 printk(KERN_ERR "%s: context size (%u) exceeds payload "
692 "max\n", __FUNCTION__, len);
693 length = -ERANGE;
694 goto out3;
695 }
696
697 memcpy(buf, newcon, len);
698 length = len;
699out3:
700 kfree(newcon);
701out2:
702 kfree(tcon);
703out:
704 kfree(scon);
705 return length;
706}
707
708static struct inode *sel_make_inode(struct super_block *sb, int mode)
709{
710 struct inode *ret = new_inode(sb);
711
712 if (ret) {
713 ret->i_mode = mode;
714 ret->i_uid = ret->i_gid = 0;
715 ret->i_blksize = PAGE_CACHE_SIZE;
716 ret->i_blocks = 0;
717 ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
718 }
719 return ret;
720}
721
722#define BOOL_INO_OFFSET 30
723
724static ssize_t sel_read_bool(struct file *filep, char __user *buf,
725 size_t count, loff_t *ppos)
726{
727 char *page = NULL;
728 ssize_t length;
729 ssize_t end;
730 ssize_t ret;
731 int cur_enforcing;
732 struct inode *inode;
733
734 down(&sel_sem);
735
736 ret = -EFAULT;
737
738 /* check to see if this file has been deleted */
739 if (!filep->f_op)
740 goto out;
741
742 if (count < 0 || count > PAGE_SIZE) {
743 ret = -EINVAL;
744 goto out;
745 }
746 if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) {
747 ret = -ENOMEM;
748 goto out;
749 }
750
751 inode = filep->f_dentry->d_inode;
752 cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET);
753 if (cur_enforcing < 0) {
754 ret = cur_enforcing;
755 goto out;
756 }
757
758 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
759 bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]);
760 if (length < 0) {
761 ret = length;
762 goto out;
763 }
764
765 if (*ppos >= length) {
766 ret = 0;
767 goto out;
768 }
769 if (count + *ppos > length)
770 count = length - *ppos;
771 end = count + *ppos;
772 if (copy_to_user(buf, (char *) page + *ppos, count)) {
773 ret = -EFAULT;
774 goto out;
775 }
776 *ppos = end;
777 ret = count;
778out:
779 up(&sel_sem);
780 if (page)
781 free_page((unsigned long)page);
782 return ret;
783}
784
785static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
786 size_t count, loff_t *ppos)
787{
788 char *page = NULL;
789 ssize_t length = -EFAULT;
790 int new_value;
791 struct inode *inode;
792
793 down(&sel_sem);
794
795 length = task_has_security(current, SECURITY__SETBOOL);
796 if (length)
797 goto out;
798
799 /* check to see if this file has been deleted */
800 if (!filep->f_op)
801 goto out;
802
803 if (count < 0 || count >= PAGE_SIZE) {
804 length = -ENOMEM;
805 goto out;
806 }
807 if (*ppos != 0) {
808 /* No partial writes. */
809 goto out;
810 }
811 page = (char*)get_zeroed_page(GFP_KERNEL);
812 if (!page) {
813 length = -ENOMEM;
814 goto out;
815 }
816
817 if (copy_from_user(page, buf, count))
818 goto out;
819
820 length = -EINVAL;
821 if (sscanf(page, "%d", &new_value) != 1)
822 goto out;
823
824 if (new_value)
825 new_value = 1;
826
827 inode = filep->f_dentry->d_inode;
828 bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value;
829 length = count;
830
831out:
832 up(&sel_sem);
833 if (page)
834 free_page((unsigned long) page);
835 return length;
836}
837
838static struct file_operations sel_bool_ops = {
839 .read = sel_read_bool,
840 .write = sel_write_bool,
841};
842
843static ssize_t sel_commit_bools_write(struct file *filep,
844 const char __user *buf,
845 size_t count, loff_t *ppos)
846{
847 char *page = NULL;
848 ssize_t length = -EFAULT;
849 int new_value;
850
851 down(&sel_sem);
852
853 length = task_has_security(current, SECURITY__SETBOOL);
854 if (length)
855 goto out;
856
857 /* check to see if this file has been deleted */
858 if (!filep->f_op)
859 goto out;
860
861 if (count < 0 || count >= PAGE_SIZE) {
862 length = -ENOMEM;
863 goto out;
864 }
865 if (*ppos != 0) {
866 /* No partial writes. */
867 goto out;
868 }
869 page = (char*)get_zeroed_page(GFP_KERNEL);
870 if (!page) {
871 length = -ENOMEM;
872 goto out;
873 }
874
875 if (copy_from_user(page, buf, count))
876 goto out;
877
878 length = -EINVAL;
879 if (sscanf(page, "%d", &new_value) != 1)
880 goto out;
881
882 if (new_value) {
883 security_set_bools(bool_num, bool_pending_values);
884 }
885
886 length = count;
887
888out:
889 up(&sel_sem);
890 if (page)
891 free_page((unsigned long) page);
892 return length;
893}
894
895static struct file_operations sel_commit_bools_ops = {
896 .write = sel_commit_bools_write,
897};
898
899/* delete booleans - partial revoke() from
900 * fs/proc/generic.c proc_kill_inodes */
901static void sel_remove_bools(struct dentry *de)
902{
903 struct list_head *p, *node;
904 struct super_block *sb = de->d_sb;
905
906 spin_lock(&dcache_lock);
907 node = de->d_subdirs.next;
908 while (node != &de->d_subdirs) {
909 struct dentry *d = list_entry(node, struct dentry, d_child);
910 list_del_init(node);
911
912 if (d->d_inode) {
913 d = dget_locked(d);
914 spin_unlock(&dcache_lock);
915 d_delete(d);
916 simple_unlink(de->d_inode, d);
917 dput(d);
918 spin_lock(&dcache_lock);
919 }
920 node = de->d_subdirs.next;
921 }
922
923 spin_unlock(&dcache_lock);
924
925 file_list_lock();
926 list_for_each(p, &sb->s_files) {
927 struct file * filp = list_entry(p, struct file, f_list);
928 struct dentry * dentry = filp->f_dentry;
929
930 if (dentry->d_parent != de) {
931 continue;
932 }
933 filp->f_op = NULL;
934 }
935 file_list_unlock();
936}
937
938#define BOOL_DIR_NAME "booleans"
939
940static int sel_make_bools(void)
941{
942 int i, ret = 0;
943 ssize_t len;
944 struct dentry *dentry = NULL;
945 struct dentry *dir = bool_dir;
946 struct inode *inode = NULL;
947 struct inode_security_struct *isec;
948 char **names = NULL, *page;
949 int num;
950 int *values = NULL;
951 u32 sid;
952
953 /* remove any existing files */
954 if (bool_pending_values)
955 kfree(bool_pending_values);
956
957 sel_remove_bools(dir);
958
959 if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
960 return -ENOMEM;
961
962 ret = security_get_bools(&num, &names, &values);
963 if (ret != 0)
964 goto out;
965
966 for (i = 0; i < num; i++) {
967 dentry = d_alloc_name(dir, names[i]);
968 if (!dentry) {
969 ret = -ENOMEM;
970 goto err;
971 }
972 inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR);
973 if (!inode) {
974 ret = -ENOMEM;
975 goto err;
976 }
977
978 len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]);
979 if (len < 0) {
980 ret = -EINVAL;
981 goto err;
982 } else if (len >= PAGE_SIZE) {
983 ret = -ENAMETOOLONG;
984 goto err;
985 }
986 isec = (struct inode_security_struct*)inode->i_security;
987 if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid)))
988 goto err;
989 isec->sid = sid;
990 isec->initialized = 1;
991 inode->i_fop = &sel_bool_ops;
992 inode->i_ino = i + BOOL_INO_OFFSET;
993 d_add(dentry, inode);
994 }
995 bool_num = num;
996 bool_pending_values = values;
997out:
998 free_page((unsigned long)page);
999 if (names) {
1000 for (i = 0; i < num; i++) {
1001 if (names[i])
1002 kfree(names[i]);
1003 }
1004 kfree(names);
1005 }
1006 return ret;
1007err:
1008 d_genocide(dir);
1009 ret = -ENOMEM;
1010 goto out;
1011}
1012
1013#define NULL_FILE_NAME "null"
1014
1015struct dentry *selinux_null = NULL;
1016
1017static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
1018 size_t count, loff_t *ppos)
1019{
1020 char tmpbuf[TMPBUFLEN];
1021 ssize_t length;
1022
1023 length = scnprintf(tmpbuf, TMPBUFLEN, "%u", avc_cache_threshold);
1024 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
1025}
1026
1027static ssize_t sel_write_avc_cache_threshold(struct file * file,
1028 const char __user * buf,
1029 size_t count, loff_t *ppos)
1030
1031{
1032 char *page;
1033 ssize_t ret;
1034 int new_value;
1035
1036 if (count < 0 || count >= PAGE_SIZE) {
1037 ret = -ENOMEM;
1038 goto out;
1039 }
1040
1041 if (*ppos != 0) {
1042 /* No partial writes. */
1043 ret = -EINVAL;
1044 goto out;
1045 }
1046
1047 page = (char*)get_zeroed_page(GFP_KERNEL);
1048 if (!page) {
1049 ret = -ENOMEM;
1050 goto out;
1051 }
1052
1053 if (copy_from_user(page, buf, count)) {
1054 ret = -EFAULT;
1055 goto out_free;
1056 }
1057
1058 if (sscanf(page, "%u", &new_value) != 1) {
1059 ret = -EINVAL;
1060 goto out;
1061 }
1062
1063 if (new_value != avc_cache_threshold) {
1064 ret = task_has_security(current, SECURITY__SETSECPARAM);
1065 if (ret)
1066 goto out_free;
1067 avc_cache_threshold = new_value;
1068 }
1069 ret = count;
1070out_free:
1071 free_page((unsigned long)page);
1072out:
1073 return ret;
1074}
1075
1076static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf,
1077 size_t count, loff_t *ppos)
1078{
1079 char *page;
1080 ssize_t ret = 0;
1081
1082 page = (char *)__get_free_page(GFP_KERNEL);
1083 if (!page) {
1084 ret = -ENOMEM;
1085 goto out;
1086 }
1087 ret = avc_get_hash_stats(page);
1088 if (ret >= 0)
1089 ret = simple_read_from_buffer(buf, count, ppos, page, ret);
1090 free_page((unsigned long)page);
1091out:
1092 return ret;
1093}
1094
1095static struct file_operations sel_avc_cache_threshold_ops = {
1096 .read = sel_read_avc_cache_threshold,
1097 .write = sel_write_avc_cache_threshold,
1098};
1099
1100static struct file_operations sel_avc_hash_stats_ops = {
1101 .read = sel_read_avc_hash_stats,
1102};
1103
1104#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
1105static struct avc_cache_stats *sel_avc_get_stat_idx(loff_t *idx)
1106{
1107 int cpu;
1108
1109 for (cpu = *idx; cpu < NR_CPUS; ++cpu) {
1110 if (!cpu_possible(cpu))
1111 continue;
1112 *idx = cpu + 1;
1113 return &per_cpu(avc_cache_stats, cpu);
1114 }
1115 return NULL;
1116}
1117
1118static void *sel_avc_stats_seq_start(struct seq_file *seq, loff_t *pos)
1119{
1120 loff_t n = *pos - 1;
1121
1122 if (*pos == 0)
1123 return SEQ_START_TOKEN;
1124
1125 return sel_avc_get_stat_idx(&n);
1126}
1127
1128static void *sel_avc_stats_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1129{
1130 return sel_avc_get_stat_idx(pos);
1131}
1132
1133static int sel_avc_stats_seq_show(struct seq_file *seq, void *v)
1134{
1135 struct avc_cache_stats *st = v;
1136
1137 if (v == SEQ_START_TOKEN)
1138 seq_printf(seq, "lookups hits misses allocations reclaims "
1139 "frees\n");
1140 else
1141 seq_printf(seq, "%u %u %u %u %u %u\n", st->lookups,
1142 st->hits, st->misses, st->allocations,
1143 st->reclaims, st->frees);
1144 return 0;
1145}
1146
1147static void sel_avc_stats_seq_stop(struct seq_file *seq, void *v)
1148{ }
1149
1150static struct seq_operations sel_avc_cache_stats_seq_ops = {
1151 .start = sel_avc_stats_seq_start,
1152 .next = sel_avc_stats_seq_next,
1153 .show = sel_avc_stats_seq_show,
1154 .stop = sel_avc_stats_seq_stop,
1155};
1156
1157static int sel_open_avc_cache_stats(struct inode *inode, struct file *file)
1158{
1159 return seq_open(file, &sel_avc_cache_stats_seq_ops);
1160}
1161
1162static struct file_operations sel_avc_cache_stats_ops = {
1163 .open = sel_open_avc_cache_stats,
1164 .read = seq_read,
1165 .llseek = seq_lseek,
1166 .release = seq_release,
1167};
1168#endif
1169
1170static int sel_make_avc_files(struct dentry *dir)
1171{
1172 int i, ret = 0;
1173 static struct tree_descr files[] = {
1174 { "cache_threshold",
1175 &sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR },
1176 { "hash_stats", &sel_avc_hash_stats_ops, S_IRUGO },
1177#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
1178 { "cache_stats", &sel_avc_cache_stats_ops, S_IRUGO },
1179#endif
1180 };
1181
1182 for (i = 0; i < sizeof (files) / sizeof (files[0]); i++) {
1183 struct inode *inode;
1184 struct dentry *dentry;
1185
1186 dentry = d_alloc_name(dir, files[i].name);
1187 if (!dentry) {
1188 ret = -ENOMEM;
1189 goto err;
1190 }
1191
1192 inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode);
1193 if (!inode) {
1194 ret = -ENOMEM;
1195 goto err;
1196 }
1197 inode->i_fop = files[i].ops;
1198 d_add(dentry, inode);
1199 }
1200out:
1201 return ret;
1202err:
1203 d_genocide(dir);
1204 goto out;
1205}
1206
1207static int sel_make_dir(struct super_block *sb, struct dentry *dentry)
1208{
1209 int ret = 0;
1210 struct inode *inode;
1211
1212 inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO);
1213 if (!inode) {
1214 ret = -ENOMEM;
1215 goto out;
1216 }
1217 inode->i_op = &simple_dir_inode_operations;
1218 inode->i_fop = &simple_dir_operations;
1219 d_add(dentry, inode);
1220out:
1221 return ret;
1222}
1223
1224static int sel_fill_super(struct super_block * sb, void * data, int silent)
1225{
1226 int ret;
1227 struct dentry *dentry;
1228 struct inode *inode;
1229 struct inode_security_struct *isec;
1230
1231 static struct tree_descr selinux_files[] = {
1232 [SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
1233 [SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUGO|S_IWUSR},
1234 [SEL_CONTEXT] = {"context", &sel_context_ops, S_IRUGO|S_IWUGO},
1235 [SEL_ACCESS] = {"access", &transaction_ops, S_IRUGO|S_IWUGO},
1236 [SEL_CREATE] = {"create", &transaction_ops, S_IRUGO|S_IWUGO},
1237 [SEL_RELABEL] = {"relabel", &transaction_ops, S_IRUGO|S_IWUGO},
1238 [SEL_USER] = {"user", &transaction_ops, S_IRUGO|S_IWUGO},
1239 [SEL_POLICYVERS] = {"policyvers", &sel_policyvers_ops, S_IRUGO},
1240 [SEL_COMMIT_BOOLS] = {"commit_pending_bools", &sel_commit_bools_ops, S_IWUSR},
1241 [SEL_MLS] = {"mls", &sel_mls_ops, S_IRUGO},
1242 [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
1243 [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
1244 [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
1245 /* last one */ {""}
1246 };
1247 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
1248 if (ret)
1249 return ret;
1250
1251 dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME);
1252 if (!dentry)
1253 return -ENOMEM;
1254
1255 inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO);
1256 if (!inode)
1257 goto out;
1258 inode->i_op = &simple_dir_inode_operations;
1259 inode->i_fop = &simple_dir_operations;
1260 d_add(dentry, inode);
1261 bool_dir = dentry;
1262 ret = sel_make_bools();
1263 if (ret)
1264 goto out;
1265
1266 dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME);
1267 if (!dentry)
1268 return -ENOMEM;
1269
1270 inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
1271 if (!inode)
1272 goto out;
1273 isec = (struct inode_security_struct*)inode->i_security;
1274 isec->sid = SECINITSID_DEVNULL;
1275 isec->sclass = SECCLASS_CHR_FILE;
1276 isec->initialized = 1;
1277
1278 init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
1279 d_add(dentry, inode);
1280 selinux_null = dentry;
1281
1282 dentry = d_alloc_name(sb->s_root, "avc");
1283 if (!dentry)
1284 return -ENOMEM;
1285
1286 ret = sel_make_dir(sb, dentry);
1287 if (ret)
1288 goto out;
1289
1290 ret = sel_make_avc_files(dentry);
1291 if (ret)
1292 goto out;
1293
1294 return 0;
1295out:
1296 dput(dentry);
1297 printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__);
1298 return -ENOMEM;
1299}
1300
1301static struct super_block *sel_get_sb(struct file_system_type *fs_type,
1302 int flags, const char *dev_name, void *data)
1303{
1304 return get_sb_single(fs_type, flags, data, sel_fill_super);
1305}
1306
1307static struct file_system_type sel_fs_type = {
1308 .name = "selinuxfs",
1309 .get_sb = sel_get_sb,
1310 .kill_sb = kill_litter_super,
1311};
1312
1313struct vfsmount *selinuxfs_mount;
1314
1315static int __init init_sel_fs(void)
1316{
1317 int err;
1318
1319 if (!selinux_enabled)
1320 return 0;
1321 err = register_filesystem(&sel_fs_type);
1322 if (!err) {
1323 selinuxfs_mount = kern_mount(&sel_fs_type);
1324 if (IS_ERR(selinuxfs_mount)) {
1325 printk(KERN_ERR "selinuxfs: could not mount!\n");
1326 err = PTR_ERR(selinuxfs_mount);
1327 selinuxfs_mount = NULL;
1328 }
1329 }
1330 return err;
1331}
1332
1333__initcall(init_sel_fs);
1334
1335#ifdef CONFIG_SECURITY_SELINUX_DISABLE
1336void exit_sel_fs(void)
1337{
1338 unregister_filesystem(&sel_fs_type);
1339}
1340#endif
diff --git a/security/selinux/ss/Makefile b/security/selinux/ss/Makefile
new file mode 100644
index 00000000000..bad78779b9b
--- /dev/null
+++ b/security/selinux/ss/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for building the SELinux security server as part of the kernel tree.
3#
4
5EXTRA_CFLAGS += -Isecurity/selinux/include
6obj-y := ss.o
7
8ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o
9
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
new file mode 100644
index 00000000000..f238c034c44
--- /dev/null
+++ b/security/selinux/ss/avtab.c
@@ -0,0 +1,399 @@
1/*
2 * Implementation of the access vector table type.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6
7/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
8 *
9 * Added conditional policy language extensions
10 *
11 * Copyright (C) 2003 Tresys Technology, LLC
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, version 2.
15 */
16
17#include <linux/kernel.h>
18#include <linux/slab.h>
19#include <linux/vmalloc.h>
20#include <linux/errno.h>
21
22#include "avtab.h"
23#include "policydb.h"
24
25#define AVTAB_HASH(keyp) \
26((keyp->target_class + \
27 (keyp->target_type << 2) + \
28 (keyp->source_type << 9)) & \
29 AVTAB_HASH_MASK)
30
31static kmem_cache_t *avtab_node_cachep;
32
33static struct avtab_node*
34avtab_insert_node(struct avtab *h, int hvalue,
35 struct avtab_node * prev, struct avtab_node * cur,
36 struct avtab_key *key, struct avtab_datum *datum)
37{
38 struct avtab_node * newnode;
39 newnode = kmem_cache_alloc(avtab_node_cachep, SLAB_KERNEL);
40 if (newnode == NULL)
41 return NULL;
42 memset(newnode, 0, sizeof(struct avtab_node));
43 newnode->key = *key;
44 newnode->datum = *datum;
45 if (prev) {
46 newnode->next = prev->next;
47 prev->next = newnode;
48 } else {
49 newnode->next = h->htable[hvalue];
50 h->htable[hvalue] = newnode;
51 }
52
53 h->nel++;
54 return newnode;
55}
56
57static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
58{
59 int hvalue;
60 struct avtab_node *prev, *cur, *newnode;
61
62 if (!h)
63 return -EINVAL;
64
65 hvalue = AVTAB_HASH(key);
66 for (prev = NULL, cur = h->htable[hvalue];
67 cur;
68 prev = cur, cur = cur->next) {
69 if (key->source_type == cur->key.source_type &&
70 key->target_type == cur->key.target_type &&
71 key->target_class == cur->key.target_class &&
72 (datum->specified & cur->datum.specified))
73 return -EEXIST;
74 if (key->source_type < cur->key.source_type)
75 break;
76 if (key->source_type == cur->key.source_type &&
77 key->target_type < cur->key.target_type)
78 break;
79 if (key->source_type == cur->key.source_type &&
80 key->target_type == cur->key.target_type &&
81 key->target_class < cur->key.target_class)
82 break;
83 }
84
85 newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
86 if(!newnode)
87 return -ENOMEM;
88
89 return 0;
90}
91
92/* Unlike avtab_insert(), this function allow multiple insertions of the same
93 * key/specified mask into the table, as needed by the conditional avtab.
94 * It also returns a pointer to the node inserted.
95 */
96struct avtab_node *
97avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_datum * datum)
98{
99 int hvalue;
100 struct avtab_node *prev, *cur, *newnode;
101
102 if (!h)
103 return NULL;
104 hvalue = AVTAB_HASH(key);
105 for (prev = NULL, cur = h->htable[hvalue];
106 cur;
107 prev = cur, cur = cur->next) {
108 if (key->source_type == cur->key.source_type &&
109 key->target_type == cur->key.target_type &&
110 key->target_class == cur->key.target_class &&
111 (datum->specified & cur->datum.specified))
112 break;
113 if (key->source_type < cur->key.source_type)
114 break;
115 if (key->source_type == cur->key.source_type &&
116 key->target_type < cur->key.target_type)
117 break;
118 if (key->source_type == cur->key.source_type &&
119 key->target_type == cur->key.target_type &&
120 key->target_class < cur->key.target_class)
121 break;
122 }
123 newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
124
125 return newnode;
126}
127
128struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified)
129{
130 int hvalue;
131 struct avtab_node *cur;
132
133 if (!h)
134 return NULL;
135
136 hvalue = AVTAB_HASH(key);
137 for (cur = h->htable[hvalue]; cur; cur = cur->next) {
138 if (key->source_type == cur->key.source_type &&
139 key->target_type == cur->key.target_type &&
140 key->target_class == cur->key.target_class &&
141 (specified & cur->datum.specified))
142 return &cur->datum;
143
144 if (key->source_type < cur->key.source_type)
145 break;
146 if (key->source_type == cur->key.source_type &&
147 key->target_type < cur->key.target_type)
148 break;
149 if (key->source_type == cur->key.source_type &&
150 key->target_type == cur->key.target_type &&
151 key->target_class < cur->key.target_class)
152 break;
153 }
154
155 return NULL;
156}
157
158/* This search function returns a node pointer, and can be used in
159 * conjunction with avtab_search_next_node()
160 */
161struct avtab_node*
162avtab_search_node(struct avtab *h, struct avtab_key *key, int specified)
163{
164 int hvalue;
165 struct avtab_node *cur;
166
167 if (!h)
168 return NULL;
169
170 hvalue = AVTAB_HASH(key);
171 for (cur = h->htable[hvalue]; cur; cur = cur->next) {
172 if (key->source_type == cur->key.source_type &&
173 key->target_type == cur->key.target_type &&
174 key->target_class == cur->key.target_class &&
175 (specified & cur->datum.specified))
176 return cur;
177
178 if (key->source_type < cur->key.source_type)
179 break;
180 if (key->source_type == cur->key.source_type &&
181 key->target_type < cur->key.target_type)
182 break;
183 if (key->source_type == cur->key.source_type &&
184 key->target_type == cur->key.target_type &&
185 key->target_class < cur->key.target_class)
186 break;
187 }
188 return NULL;
189}
190
191struct avtab_node*
192avtab_search_node_next(struct avtab_node *node, int specified)
193{
194 struct avtab_node *cur;
195
196 if (!node)
197 return NULL;
198
199 for (cur = node->next; cur; cur = cur->next) {
200 if (node->key.source_type == cur->key.source_type &&
201 node->key.target_type == cur->key.target_type &&
202 node->key.target_class == cur->key.target_class &&
203 (specified & cur->datum.specified))
204 return cur;
205
206 if (node->key.source_type < cur->key.source_type)
207 break;
208 if (node->key.source_type == cur->key.source_type &&
209 node->key.target_type < cur->key.target_type)
210 break;
211 if (node->key.source_type == cur->key.source_type &&
212 node->key.target_type == cur->key.target_type &&
213 node->key.target_class < cur->key.target_class)
214 break;
215 }
216 return NULL;
217}
218
219void avtab_destroy(struct avtab *h)
220{
221 int i;
222 struct avtab_node *cur, *temp;
223
224 if (!h || !h->htable)
225 return;
226
227 for (i = 0; i < AVTAB_SIZE; i++) {
228 cur = h->htable[i];
229 while (cur != NULL) {
230 temp = cur;
231 cur = cur->next;
232 kmem_cache_free(avtab_node_cachep, temp);
233 }
234 h->htable[i] = NULL;
235 }
236 vfree(h->htable);
237 h->htable = NULL;
238}
239
240
241int avtab_init(struct avtab *h)
242{
243 int i;
244
245 h->htable = vmalloc(sizeof(*(h->htable)) * AVTAB_SIZE);
246 if (!h->htable)
247 return -ENOMEM;
248 for (i = 0; i < AVTAB_SIZE; i++)
249 h->htable[i] = NULL;
250 h->nel = 0;
251 return 0;
252}
253
254void avtab_hash_eval(struct avtab *h, char *tag)
255{
256 int i, chain_len, slots_used, max_chain_len;
257 struct avtab_node *cur;
258
259 slots_used = 0;
260 max_chain_len = 0;
261 for (i = 0; i < AVTAB_SIZE; i++) {
262 cur = h->htable[i];
263 if (cur) {
264 slots_used++;
265 chain_len = 0;
266 while (cur) {
267 chain_len++;
268 cur = cur->next;
269 }
270
271 if (chain_len > max_chain_len)
272 max_chain_len = chain_len;
273 }
274 }
275
276 printk(KERN_INFO "%s: %d entries and %d/%d buckets used, longest "
277 "chain length %d\n", tag, h->nel, slots_used, AVTAB_SIZE,
278 max_chain_len);
279}
280
281int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey)
282{
283 u32 buf[7];
284 u32 items, items2;
285 int rc;
286
287 memset(avkey, 0, sizeof(struct avtab_key));
288 memset(avdatum, 0, sizeof(struct avtab_datum));
289
290 rc = next_entry(buf, fp, sizeof(u32));
291 if (rc < 0) {
292 printk(KERN_ERR "security: avtab: truncated entry\n");
293 goto bad;
294 }
295 items2 = le32_to_cpu(buf[0]);
296 if (items2 > ARRAY_SIZE(buf)) {
297 printk(KERN_ERR "security: avtab: entry overflow\n");
298 goto bad;
299 }
300 rc = next_entry(buf, fp, sizeof(u32)*items2);
301 if (rc < 0) {
302 printk(KERN_ERR "security: avtab: truncated entry\n");
303 goto bad;
304 }
305 items = 0;
306 avkey->source_type = le32_to_cpu(buf[items++]);
307 avkey->target_type = le32_to_cpu(buf[items++]);
308 avkey->target_class = le32_to_cpu(buf[items++]);
309 avdatum->specified = le32_to_cpu(buf[items++]);
310 if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) {
311 printk(KERN_ERR "security: avtab: null entry\n");
312 goto bad;
313 }
314 if ((avdatum->specified & AVTAB_AV) &&
315 (avdatum->specified & AVTAB_TYPE)) {
316 printk(KERN_ERR "security: avtab: entry has both access vectors and types\n");
317 goto bad;
318 }
319 if (avdatum->specified & AVTAB_AV) {
320 if (avdatum->specified & AVTAB_ALLOWED)
321 avtab_allowed(avdatum) = le32_to_cpu(buf[items++]);
322 if (avdatum->specified & AVTAB_AUDITDENY)
323 avtab_auditdeny(avdatum) = le32_to_cpu(buf[items++]);
324 if (avdatum->specified & AVTAB_AUDITALLOW)
325 avtab_auditallow(avdatum) = le32_to_cpu(buf[items++]);
326 } else {
327 if (avdatum->specified & AVTAB_TRANSITION)
328 avtab_transition(avdatum) = le32_to_cpu(buf[items++]);
329 if (avdatum->specified & AVTAB_CHANGE)
330 avtab_change(avdatum) = le32_to_cpu(buf[items++]);
331 if (avdatum->specified & AVTAB_MEMBER)
332 avtab_member(avdatum) = le32_to_cpu(buf[items++]);
333 }
334 if (items != items2) {
335 printk(KERN_ERR "security: avtab: entry only had %d items, expected %d\n",
336 items2, items);
337 goto bad;
338 }
339
340 return 0;
341bad:
342 return -1;
343}
344
345int avtab_read(struct avtab *a, void *fp, u32 config)
346{
347 int rc;
348 struct avtab_key avkey;
349 struct avtab_datum avdatum;
350 u32 buf[1];
351 u32 nel, i;
352
353
354 rc = next_entry(buf, fp, sizeof(u32));
355 if (rc < 0) {
356 printk(KERN_ERR "security: avtab: truncated table\n");
357 goto bad;
358 }
359 nel = le32_to_cpu(buf[0]);
360 if (!nel) {
361 printk(KERN_ERR "security: avtab: table is empty\n");
362 rc = -EINVAL;
363 goto bad;
364 }
365 for (i = 0; i < nel; i++) {
366 if (avtab_read_item(fp, &avdatum, &avkey)) {
367 rc = -EINVAL;
368 goto bad;
369 }
370 rc = avtab_insert(a, &avkey, &avdatum);
371 if (rc) {
372 if (rc == -ENOMEM)
373 printk(KERN_ERR "security: avtab: out of memory\n");
374 if (rc == -EEXIST)
375 printk(KERN_ERR "security: avtab: duplicate entry\n");
376 goto bad;
377 }
378 }
379
380 rc = 0;
381out:
382 return rc;
383
384bad:
385 avtab_destroy(a);
386 goto out;
387}
388
389void avtab_cache_init(void)
390{
391 avtab_node_cachep = kmem_cache_create("avtab_node",
392 sizeof(struct avtab_node),
393 0, SLAB_PANIC, NULL, NULL);
394}
395
396void avtab_cache_destroy(void)
397{
398 kmem_cache_destroy (avtab_node_cachep);
399}
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
new file mode 100644
index 00000000000..519d4f6dc65
--- /dev/null
+++ b/security/selinux/ss/avtab.h
@@ -0,0 +1,85 @@
1/*
2 * An access vector table (avtab) is a hash table
3 * of access vectors and transition types indexed
4 * by a type pair and a class. An access vector
5 * table is used to represent the type enforcement
6 * tables.
7 *
8 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
9 */
10
11/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
12 *
13 * Added conditional policy language extensions
14 *
15 * Copyright (C) 2003 Tresys Technology, LLC
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, version 2.
19 */
20#ifndef _SS_AVTAB_H_
21#define _SS_AVTAB_H_
22
23struct avtab_key {
24 u32 source_type; /* source type */
25 u32 target_type; /* target type */
26 u32 target_class; /* target object class */
27};
28
29struct avtab_datum {
30#define AVTAB_ALLOWED 1
31#define AVTAB_AUDITALLOW 2
32#define AVTAB_AUDITDENY 4
33#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
34#define AVTAB_TRANSITION 16
35#define AVTAB_MEMBER 32
36#define AVTAB_CHANGE 64
37#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
38#define AVTAB_ENABLED 0x80000000 /* reserved for used in cond_avtab */
39 u32 specified; /* what fields are specified */
40 u32 data[3]; /* access vectors or types */
41#define avtab_allowed(x) (x)->data[0]
42#define avtab_auditdeny(x) (x)->data[1]
43#define avtab_auditallow(x) (x)->data[2]
44#define avtab_transition(x) (x)->data[0]
45#define avtab_change(x) (x)->data[1]
46#define avtab_member(x) (x)->data[2]
47};
48
49struct avtab_node {
50 struct avtab_key key;
51 struct avtab_datum datum;
52 struct avtab_node *next;
53};
54
55struct avtab {
56 struct avtab_node **htable;
57 u32 nel; /* number of elements */
58};
59
60int avtab_init(struct avtab *);
61struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k, int specified);
62void avtab_destroy(struct avtab *h);
63void avtab_hash_eval(struct avtab *h, char *tag);
64
65int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey);
66int avtab_read(struct avtab *a, void *fp, u32 config);
67
68struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
69 struct avtab_datum *datum);
70
71struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key, int specified);
72
73struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified);
74
75void avtab_cache_init(void);
76void avtab_cache_destroy(void);
77
78#define AVTAB_HASH_BITS 15
79#define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS)
80#define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1)
81
82#define AVTAB_SIZE AVTAB_HASH_BUCKETS
83
84#endif /* _SS_AVTAB_H_ */
85
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
new file mode 100644
index 00000000000..b53441184ac
--- /dev/null
+++ b/security/selinux/ss/conditional.c
@@ -0,0 +1,489 @@
1/* Authors: Karl MacMillan <kmacmillan@tresys.com>
2 * Frank Mayer <mayerf@tresys.com>
3 *
4 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 2.
8 */
9
10#include <linux/kernel.h>
11#include <linux/errno.h>
12#include <linux/string.h>
13#include <linux/spinlock.h>
14#include <asm/semaphore.h>
15#include <linux/slab.h>
16
17#include "security.h"
18#include "conditional.h"
19
20/*
21 * cond_evaluate_expr evaluates a conditional expr
22 * in reverse polish notation. It returns true (1), false (0),
23 * or undefined (-1). Undefined occurs when the expression
24 * exceeds the stack depth of COND_EXPR_MAXDEPTH.
25 */
26static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
27{
28
29 struct cond_expr *cur;
30 int s[COND_EXPR_MAXDEPTH];
31 int sp = -1;
32
33 for (cur = expr; cur != NULL; cur = cur->next) {
34 switch (cur->expr_type) {
35 case COND_BOOL:
36 if (sp == (COND_EXPR_MAXDEPTH - 1))
37 return -1;
38 sp++;
39 s[sp] = p->bool_val_to_struct[cur->bool - 1]->state;
40 break;
41 case COND_NOT:
42 if (sp < 0)
43 return -1;
44 s[sp] = !s[sp];
45 break;
46 case COND_OR:
47 if (sp < 1)
48 return -1;
49 sp--;
50 s[sp] |= s[sp + 1];
51 break;
52 case COND_AND:
53 if (sp < 1)
54 return -1;
55 sp--;
56 s[sp] &= s[sp + 1];
57 break;
58 case COND_XOR:
59 if (sp < 1)
60 return -1;
61 sp--;
62 s[sp] ^= s[sp + 1];
63 break;
64 case COND_EQ:
65 if (sp < 1)
66 return -1;
67 sp--;
68 s[sp] = (s[sp] == s[sp + 1]);
69 break;
70 case COND_NEQ:
71 if (sp < 1)
72 return -1;
73 sp--;
74 s[sp] = (s[sp] != s[sp + 1]);
75 break;
76 default:
77 return -1;
78 }
79 }
80 return s[0];
81}
82
83/*
84 * evaluate_cond_node evaluates the conditional stored in
85 * a struct cond_node and if the result is different than the
86 * current state of the node it sets the rules in the true/false
87 * list appropriately. If the result of the expression is undefined
88 * all of the rules are disabled for safety.
89 */
90int evaluate_cond_node(struct policydb *p, struct cond_node *node)
91{
92 int new_state;
93 struct cond_av_list* cur;
94
95 new_state = cond_evaluate_expr(p, node->expr);
96 if (new_state != node->cur_state) {
97 node->cur_state = new_state;
98 if (new_state == -1)
99 printk(KERN_ERR "security: expression result was undefined - disabling all rules.\n");
100 /* turn the rules on or off */
101 for (cur = node->true_list; cur != NULL; cur = cur->next) {
102 if (new_state <= 0) {
103 cur->node->datum.specified &= ~AVTAB_ENABLED;
104 } else {
105 cur->node->datum.specified |= AVTAB_ENABLED;
106 }
107 }
108
109 for (cur = node->false_list; cur != NULL; cur = cur->next) {
110 /* -1 or 1 */
111 if (new_state) {
112 cur->node->datum.specified &= ~AVTAB_ENABLED;
113 } else {
114 cur->node->datum.specified |= AVTAB_ENABLED;
115 }
116 }
117 }
118 return 0;
119}
120
121int cond_policydb_init(struct policydb *p)
122{
123 p->bool_val_to_struct = NULL;
124 p->cond_list = NULL;
125 if (avtab_init(&p->te_cond_avtab))
126 return -1;
127
128 return 0;
129}
130
131static void cond_av_list_destroy(struct cond_av_list *list)
132{
133 struct cond_av_list *cur, *next;
134 for (cur = list; cur != NULL; cur = next) {
135 next = cur->next;
136 /* the avtab_ptr_t node is destroy by the avtab */
137 kfree(cur);
138 }
139}
140
141static void cond_node_destroy(struct cond_node *node)
142{
143 struct cond_expr *cur_expr, *next_expr;
144
145 for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) {
146 next_expr = cur_expr->next;
147 kfree(cur_expr);
148 }
149 cond_av_list_destroy(node->true_list);
150 cond_av_list_destroy(node->false_list);
151 kfree(node);
152}
153
154static void cond_list_destroy(struct cond_node *list)
155{
156 struct cond_node *next, *cur;
157
158 if (list == NULL)
159 return;
160
161 for (cur = list; cur != NULL; cur = next) {
162 next = cur->next;
163 cond_node_destroy(cur);
164 }
165}
166
167void cond_policydb_destroy(struct policydb *p)
168{
169 if (p->bool_val_to_struct != NULL)
170 kfree(p->bool_val_to_struct);
171 avtab_destroy(&p->te_cond_avtab);
172 cond_list_destroy(p->cond_list);
173}
174
175int cond_init_bool_indexes(struct policydb *p)
176{
177 if (p->bool_val_to_struct)
178 kfree(p->bool_val_to_struct);
179 p->bool_val_to_struct = (struct cond_bool_datum**)
180 kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum*), GFP_KERNEL);
181 if (!p->bool_val_to_struct)
182 return -1;
183 return 0;
184}
185
186int cond_destroy_bool(void *key, void *datum, void *p)
187{
188 if (key)
189 kfree(key);
190 kfree(datum);
191 return 0;
192}
193
194int cond_index_bool(void *key, void *datum, void *datap)
195{
196 struct policydb *p;
197 struct cond_bool_datum *booldatum;
198
199 booldatum = datum;
200 p = datap;
201
202 if (!booldatum->value || booldatum->value > p->p_bools.nprim)
203 return -EINVAL;
204
205 p->p_bool_val_to_name[booldatum->value - 1] = key;
206 p->bool_val_to_struct[booldatum->value -1] = booldatum;
207
208 return 0;
209}
210
211static int bool_isvalid(struct cond_bool_datum *b)
212{
213 if (!(b->state == 0 || b->state == 1))
214 return 0;
215 return 1;
216}
217
218int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
219{
220 char *key = NULL;
221 struct cond_bool_datum *booldatum;
222 u32 buf[3], len;
223 int rc;
224
225 booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
226 if (!booldatum)
227 return -1;
228 memset(booldatum, 0, sizeof(struct cond_bool_datum));
229
230 rc = next_entry(buf, fp, sizeof buf);
231 if (rc < 0)
232 goto err;
233
234 booldatum->value = le32_to_cpu(buf[0]);
235 booldatum->state = le32_to_cpu(buf[1]);
236
237 if (!bool_isvalid(booldatum))
238 goto err;
239
240 len = le32_to_cpu(buf[2]);
241
242 key = kmalloc(len + 1, GFP_KERNEL);
243 if (!key)
244 goto err;
245 rc = next_entry(key, fp, len);
246 if (rc < 0)
247 goto err;
248 key[len] = 0;
249 if (hashtab_insert(h, key, booldatum))
250 goto err;
251
252 return 0;
253err:
254 cond_destroy_bool(key, booldatum, NULL);
255 return -1;
256}
257
258static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list,
259 struct cond_av_list *other)
260{
261 struct cond_av_list *list, *last = NULL, *cur;
262 struct avtab_key key;
263 struct avtab_datum datum;
264 struct avtab_node *node_ptr;
265 int rc;
266 u32 buf[1], i, len;
267 u8 found;
268
269 *ret_list = NULL;
270
271 len = 0;
272 rc = next_entry(buf, fp, sizeof buf);
273 if (rc < 0)
274 return -1;
275
276 len = le32_to_cpu(buf[0]);
277 if (len == 0) {
278 return 0;
279 }
280
281 for (i = 0; i < len; i++) {
282 if (avtab_read_item(fp, &datum, &key))
283 goto err;
284
285 /*
286 * For type rules we have to make certain there aren't any
287 * conflicting rules by searching the te_avtab and the
288 * cond_te_avtab.
289 */
290 if (datum.specified & AVTAB_TYPE) {
291 if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) {
292 printk("security: type rule already exists outside of a conditional.");
293 goto err;
294 }
295 /*
296 * If we are reading the false list other will be a pointer to
297 * the true list. We can have duplicate entries if there is only
298 * 1 other entry and it is in our true list.
299 *
300 * If we are reading the true list (other == NULL) there shouldn't
301 * be any other entries.
302 */
303 if (other) {
304 node_ptr = avtab_search_node(&p->te_cond_avtab, &key, AVTAB_TYPE);
305 if (node_ptr) {
306 if (avtab_search_node_next(node_ptr, AVTAB_TYPE)) {
307 printk("security: too many conflicting type rules.");
308 goto err;
309 }
310 found = 0;
311 for (cur = other; cur != NULL; cur = cur->next) {
312 if (cur->node == node_ptr) {
313 found = 1;
314 break;
315 }
316 }
317 if (!found) {
318 printk("security: conflicting type rules.");
319 goto err;
320 }
321 }
322 } else {
323 if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) {
324 printk("security: conflicting type rules when adding type rule for true.");
325 goto err;
326 }
327 }
328 }
329 node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum);
330 if (!node_ptr) {
331 printk("security: could not insert rule.");
332 goto err;
333 }
334
335 list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL);
336 if (!list)
337 goto err;
338 memset(list, 0, sizeof(struct cond_av_list));
339
340 list->node = node_ptr;
341 if (i == 0)
342 *ret_list = list;
343 else
344 last->next = list;
345 last = list;
346
347 }
348
349 return 0;
350err:
351 cond_av_list_destroy(*ret_list);
352 *ret_list = NULL;
353 return -1;
354}
355
356static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
357{
358 if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
359 printk("security: conditional expressions uses unknown operator.\n");
360 return 0;
361 }
362
363 if (expr->bool > p->p_bools.nprim) {
364 printk("security: conditional expressions uses unknown bool.\n");
365 return 0;
366 }
367 return 1;
368}
369
370static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
371{
372 u32 buf[2], len, i;
373 int rc;
374 struct cond_expr *expr = NULL, *last = NULL;
375
376 rc = next_entry(buf, fp, sizeof(u32));
377 if (rc < 0)
378 return -1;
379
380 node->cur_state = le32_to_cpu(buf[0]);
381
382 len = 0;
383 rc = next_entry(buf, fp, sizeof(u32));
384 if (rc < 0)
385 return -1;
386
387 /* expr */
388 len = le32_to_cpu(buf[0]);
389
390 for (i = 0; i < len; i++ ) {
391 rc = next_entry(buf, fp, sizeof(u32) * 2);
392 if (rc < 0)
393 goto err;
394
395 expr = kmalloc(sizeof(struct cond_expr), GFP_KERNEL);
396 if (!expr) {
397 goto err;
398 }
399 memset(expr, 0, sizeof(struct cond_expr));
400
401 expr->expr_type = le32_to_cpu(buf[0]);
402 expr->bool = le32_to_cpu(buf[1]);
403
404 if (!expr_isvalid(p, expr)) {
405 kfree(expr);
406 goto err;
407 }
408
409 if (i == 0) {
410 node->expr = expr;
411 } else {
412 last->next = expr;
413 }
414 last = expr;
415 }
416
417 if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0)
418 goto err;
419 if (cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0)
420 goto err;
421 return 0;
422err:
423 cond_node_destroy(node);
424 return -1;
425}
426
427int cond_read_list(struct policydb *p, void *fp)
428{
429 struct cond_node *node, *last = NULL;
430 u32 buf[1], i, len;
431 int rc;
432
433 rc = next_entry(buf, fp, sizeof buf);
434 if (rc < 0)
435 return -1;
436
437 len = le32_to_cpu(buf[0]);
438
439 for (i = 0; i < len; i++) {
440 node = kmalloc(sizeof(struct cond_node), GFP_KERNEL);
441 if (!node)
442 goto err;
443 memset(node, 0, sizeof(struct cond_node));
444
445 if (cond_read_node(p, node, fp) != 0)
446 goto err;
447
448 if (i == 0) {
449 p->cond_list = node;
450 } else {
451 last->next = node;
452 }
453 last = node;
454 }
455 return 0;
456err:
457 cond_list_destroy(p->cond_list);
458 return -1;
459}
460
461/* Determine whether additional permissions are granted by the conditional
462 * av table, and if so, add them to the result
463 */
464void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd)
465{
466 struct avtab_node *node;
467
468 if(!ctab || !key || !avd)
469 return;
470
471 for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL;
472 node = avtab_search_node_next(node, AVTAB_AV)) {
473 if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
474 (node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
475 avd->allowed |= avtab_allowed(&node->datum);
476 if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
477 (node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
478 /* Since a '0' in an auditdeny mask represents a
479 * permission we do NOT want to audit (dontaudit), we use
480 * the '&' operand to ensure that all '0's in the mask
481 * are retained (much unlike the allow and auditallow cases).
482 */
483 avd->auditdeny &= avtab_auditdeny(&node->datum);
484 if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
485 (node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
486 avd->auditallow |= avtab_auditallow(&node->datum);
487 }
488 return;
489}
diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h
new file mode 100644
index 00000000000..f3a1fc6e5d6
--- /dev/null
+++ b/security/selinux/ss/conditional.h
@@ -0,0 +1,77 @@
1/* Authors: Karl MacMillan <kmacmillan@tresys.com>
2 * Frank Mayer <mayerf@tresys.com>
3 *
4 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 2.
8 */
9
10#ifndef _CONDITIONAL_H_
11#define _CONDITIONAL_H_
12
13#include "avtab.h"
14#include "symtab.h"
15#include "policydb.h"
16
17#define COND_EXPR_MAXDEPTH 10
18
19/*
20 * A conditional expression is a list of operators and operands
21 * in reverse polish notation.
22 */
23struct cond_expr {
24#define COND_BOOL 1 /* plain bool */
25#define COND_NOT 2 /* !bool */
26#define COND_OR 3 /* bool || bool */
27#define COND_AND 4 /* bool && bool */
28#define COND_XOR 5 /* bool ^ bool */
29#define COND_EQ 6 /* bool == bool */
30#define COND_NEQ 7 /* bool != bool */
31#define COND_LAST 8
32 __u32 expr_type;
33 __u32 bool;
34 struct cond_expr *next;
35};
36
37/*
38 * Each cond_node contains a list of rules to be enabled/disabled
39 * depending on the current value of the conditional expression. This
40 * struct is for that list.
41 */
42struct cond_av_list {
43 struct avtab_node *node;
44 struct cond_av_list *next;
45};
46
47/*
48 * A cond node represents a conditional block in a policy. It
49 * contains a conditional expression, the current state of the expression,
50 * two lists of rules to enable/disable depending on the value of the
51 * expression (the true list corresponds to if and the false list corresponds
52 * to else)..
53 */
54struct cond_node {
55 int cur_state;
56 struct cond_expr *expr;
57 struct cond_av_list *true_list;
58 struct cond_av_list *false_list;
59 struct cond_node *next;
60};
61
62int cond_policydb_init(struct policydb* p);
63void cond_policydb_destroy(struct policydb* p);
64
65int cond_init_bool_indexes(struct policydb* p);
66int cond_destroy_bool(void *key, void *datum, void *p);
67
68int cond_index_bool(void *key, void *datum, void *datap);
69
70int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp);
71int cond_read_list(struct policydb *p, void *fp);
72
73void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd);
74
75int evaluate_cond_node(struct policydb *p, struct cond_node *node);
76
77#endif /* _CONDITIONAL_H_ */
diff --git a/security/selinux/ss/constraint.h b/security/selinux/ss/constraint.h
new file mode 100644
index 00000000000..149dda731fd
--- /dev/null
+++ b/security/selinux/ss/constraint.h
@@ -0,0 +1,61 @@
1/*
2 * A constraint is a condition that must be satisfied in
3 * order for one or more permissions to be granted.
4 * Constraints are used to impose additional restrictions
5 * beyond the type-based rules in `te' or the role-based
6 * transition rules in `rbac'. Constraints are typically
7 * used to prevent a process from transitioning to a new user
8 * identity or role unless it is in a privileged type.
9 * Constraints are likewise typically used to prevent a
10 * process from labeling an object with a different user
11 * identity.
12 *
13 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
14 */
15#ifndef _SS_CONSTRAINT_H_
16#define _SS_CONSTRAINT_H_
17
18#include "ebitmap.h"
19
20#define CEXPR_MAXDEPTH 5
21
22struct constraint_expr {
23#define CEXPR_NOT 1 /* not expr */
24#define CEXPR_AND 2 /* expr and expr */
25#define CEXPR_OR 3 /* expr or expr */
26#define CEXPR_ATTR 4 /* attr op attr */
27#define CEXPR_NAMES 5 /* attr op names */
28 u32 expr_type; /* expression type */
29
30#define CEXPR_USER 1 /* user */
31#define CEXPR_ROLE 2 /* role */
32#define CEXPR_TYPE 4 /* type */
33#define CEXPR_TARGET 8 /* target if set, source otherwise */
34#define CEXPR_XTARGET 16 /* special 3rd target for validatetrans rule */
35#define CEXPR_L1L2 32 /* low level 1 vs. low level 2 */
36#define CEXPR_L1H2 64 /* low level 1 vs. high level 2 */
37#define CEXPR_H1L2 128 /* high level 1 vs. low level 2 */
38#define CEXPR_H1H2 256 /* high level 1 vs. high level 2 */
39#define CEXPR_L1H1 512 /* low level 1 vs. high level 1 */
40#define CEXPR_L2H2 1024 /* low level 2 vs. high level 2 */
41 u32 attr; /* attribute */
42
43#define CEXPR_EQ 1 /* == or eq */
44#define CEXPR_NEQ 2 /* != */
45#define CEXPR_DOM 3 /* dom */
46#define CEXPR_DOMBY 4 /* domby */
47#define CEXPR_INCOMP 5 /* incomp */
48 u32 op; /* operator */
49
50 struct ebitmap names; /* names */
51
52 struct constraint_expr *next; /* next expression */
53};
54
55struct constraint_node {
56 u32 permissions; /* constrained permissions */
57 struct constraint_expr *expr; /* constraint on permissions */
58 struct constraint_node *next; /* next constraint */
59};
60
61#endif /* _SS_CONSTRAINT_H_ */
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
new file mode 100644
index 00000000000..0562bacb7b9
--- /dev/null
+++ b/security/selinux/ss/context.h
@@ -0,0 +1,107 @@
1/*
2 * A security context is a set of security attributes
3 * associated with each subject and object controlled
4 * by the security policy. Security contexts are
5 * externally represented as variable-length strings
6 * that can be interpreted by a user or application
7 * with an understanding of the security policy.
8 * Internally, the security server uses a simple
9 * structure. This structure is private to the
10 * security server and can be changed without affecting
11 * clients of the security server.
12 *
13 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
14 */
15#ifndef _SS_CONTEXT_H_
16#define _SS_CONTEXT_H_
17
18#include "ebitmap.h"
19#include "mls_types.h"
20#include "security.h"
21
22/*
23 * A security context consists of an authenticated user
24 * identity, a role, a type and a MLS range.
25 */
26struct context {
27 u32 user;
28 u32 role;
29 u32 type;
30 struct mls_range range;
31};
32
33static inline void mls_context_init(struct context *c)
34{
35 memset(&c->range, 0, sizeof(c->range));
36}
37
38static inline int mls_context_cpy(struct context *dst, struct context *src)
39{
40 int rc;
41
42 if (!selinux_mls_enabled)
43 return 0;
44
45 dst->range.level[0].sens = src->range.level[0].sens;
46 rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
47 if (rc)
48 goto out;
49
50 dst->range.level[1].sens = src->range.level[1].sens;
51 rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat);
52 if (rc)
53 ebitmap_destroy(&dst->range.level[0].cat);
54out:
55 return rc;
56}
57
58static inline int mls_context_cmp(struct context *c1, struct context *c2)
59{
60 if (!selinux_mls_enabled)
61 return 1;
62
63 return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
64 ebitmap_cmp(&c1->range.level[0].cat,&c2->range.level[0].cat) &&
65 (c1->range.level[1].sens == c2->range.level[1].sens) &&
66 ebitmap_cmp(&c1->range.level[1].cat,&c2->range.level[1].cat));
67}
68
69static inline void mls_context_destroy(struct context *c)
70{
71 if (!selinux_mls_enabled)
72 return;
73
74 ebitmap_destroy(&c->range.level[0].cat);
75 ebitmap_destroy(&c->range.level[1].cat);
76 mls_context_init(c);
77}
78
79static inline void context_init(struct context *c)
80{
81 memset(c, 0, sizeof(*c));
82}
83
84static inline int context_cpy(struct context *dst, struct context *src)
85{
86 dst->user = src->user;
87 dst->role = src->role;
88 dst->type = src->type;
89 return mls_context_cpy(dst, src);
90}
91
92static inline void context_destroy(struct context *c)
93{
94 c->user = c->role = c->type = 0;
95 mls_context_destroy(c);
96}
97
98static inline int context_cmp(struct context *c1, struct context *c2)
99{
100 return ((c1->user == c2->user) &&
101 (c1->role == c2->role) &&
102 (c1->type == c2->type) &&
103 mls_context_cmp(c1, c2));
104}
105
106#endif /* _SS_CONTEXT_H_ */
107
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
new file mode 100644
index 00000000000..d8ce9cc0b9f
--- /dev/null
+++ b/security/selinux/ss/ebitmap.c
@@ -0,0 +1,293 @@
1/*
2 * Implementation of the extensible bitmap type.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6#include <linux/kernel.h>
7#include <linux/slab.h>
8#include <linux/errno.h>
9#include "ebitmap.h"
10#include "policydb.h"
11
12int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
13{
14 struct ebitmap_node *n1, *n2;
15
16 if (e1->highbit != e2->highbit)
17 return 0;
18
19 n1 = e1->node;
20 n2 = e2->node;
21 while (n1 && n2 &&
22 (n1->startbit == n2->startbit) &&
23 (n1->map == n2->map)) {
24 n1 = n1->next;
25 n2 = n2->next;
26 }
27
28 if (n1 || n2)
29 return 0;
30
31 return 1;
32}
33
34int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
35{
36 struct ebitmap_node *n, *new, *prev;
37
38 ebitmap_init(dst);
39 n = src->node;
40 prev = NULL;
41 while (n) {
42 new = kmalloc(sizeof(*new), GFP_ATOMIC);
43 if (!new) {
44 ebitmap_destroy(dst);
45 return -ENOMEM;
46 }
47 memset(new, 0, sizeof(*new));
48 new->startbit = n->startbit;
49 new->map = n->map;
50 new->next = NULL;
51 if (prev)
52 prev->next = new;
53 else
54 dst->node = new;
55 prev = new;
56 n = n->next;
57 }
58
59 dst->highbit = src->highbit;
60 return 0;
61}
62
63int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
64{
65 struct ebitmap_node *n1, *n2;
66
67 if (e1->highbit < e2->highbit)
68 return 0;
69
70 n1 = e1->node;
71 n2 = e2->node;
72 while (n1 && n2 && (n1->startbit <= n2->startbit)) {
73 if (n1->startbit < n2->startbit) {
74 n1 = n1->next;
75 continue;
76 }
77 if ((n1->map & n2->map) != n2->map)
78 return 0;
79
80 n1 = n1->next;
81 n2 = n2->next;
82 }
83
84 if (n2)
85 return 0;
86
87 return 1;
88}
89
90int ebitmap_get_bit(struct ebitmap *e, unsigned long bit)
91{
92 struct ebitmap_node *n;
93
94 if (e->highbit < bit)
95 return 0;
96
97 n = e->node;
98 while (n && (n->startbit <= bit)) {
99 if ((n->startbit + MAPSIZE) > bit) {
100 if (n->map & (MAPBIT << (bit - n->startbit)))
101 return 1;
102 else
103 return 0;
104 }
105 n = n->next;
106 }
107
108 return 0;
109}
110
111int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
112{
113 struct ebitmap_node *n, *prev, *new;
114
115 prev = NULL;
116 n = e->node;
117 while (n && n->startbit <= bit) {
118 if ((n->startbit + MAPSIZE) > bit) {
119 if (value) {
120 n->map |= (MAPBIT << (bit - n->startbit));
121 } else {
122 n->map &= ~(MAPBIT << (bit - n->startbit));
123 if (!n->map) {
124 /* drop this node from the bitmap */
125
126 if (!n->next) {
127 /*
128 * this was the highest map
129 * within the bitmap
130 */
131 if (prev)
132 e->highbit = prev->startbit + MAPSIZE;
133 else
134 e->highbit = 0;
135 }
136 if (prev)
137 prev->next = n->next;
138 else
139 e->node = n->next;
140
141 kfree(n);
142 }
143 }
144 return 0;
145 }
146 prev = n;
147 n = n->next;
148 }
149
150 if (!value)
151 return 0;
152
153 new = kmalloc(sizeof(*new), GFP_ATOMIC);
154 if (!new)
155 return -ENOMEM;
156 memset(new, 0, sizeof(*new));
157
158 new->startbit = bit & ~(MAPSIZE - 1);
159 new->map = (MAPBIT << (bit - new->startbit));
160
161 if (!n)
162 /* this node will be the highest map within the bitmap */
163 e->highbit = new->startbit + MAPSIZE;
164
165 if (prev) {
166 new->next = prev->next;
167 prev->next = new;
168 } else {
169 new->next = e->node;
170 e->node = new;
171 }
172
173 return 0;
174}
175
176void ebitmap_destroy(struct ebitmap *e)
177{
178 struct ebitmap_node *n, *temp;
179
180 if (!e)
181 return;
182
183 n = e->node;
184 while (n) {
185 temp = n;
186 n = n->next;
187 kfree(temp);
188 }
189
190 e->highbit = 0;
191 e->node = NULL;
192 return;
193}
194
195int ebitmap_read(struct ebitmap *e, void *fp)
196{
197 int rc;
198 struct ebitmap_node *n, *l;
199 u32 buf[3], mapsize, count, i;
200 u64 map;
201
202 ebitmap_init(e);
203
204 rc = next_entry(buf, fp, sizeof buf);
205 if (rc < 0)
206 goto out;
207
208 mapsize = le32_to_cpu(buf[0]);
209 e->highbit = le32_to_cpu(buf[1]);
210 count = le32_to_cpu(buf[2]);
211
212 if (mapsize != MAPSIZE) {
213 printk(KERN_ERR "security: ebitmap: map size %u does not "
214 "match my size %Zd (high bit was %d)\n", mapsize,
215 MAPSIZE, e->highbit);
216 goto bad;
217 }
218 if (!e->highbit) {
219 e->node = NULL;
220 goto ok;
221 }
222 if (e->highbit & (MAPSIZE - 1)) {
223 printk(KERN_ERR "security: ebitmap: high bit (%d) is not a "
224 "multiple of the map size (%Zd)\n", e->highbit, MAPSIZE);
225 goto bad;
226 }
227 l = NULL;
228 for (i = 0; i < count; i++) {
229 rc = next_entry(buf, fp, sizeof(u32));
230 if (rc < 0) {
231 printk(KERN_ERR "security: ebitmap: truncated map\n");
232 goto bad;
233 }
234 n = kmalloc(sizeof(*n), GFP_KERNEL);
235 if (!n) {
236 printk(KERN_ERR "security: ebitmap: out of memory\n");
237 rc = -ENOMEM;
238 goto bad;
239 }
240 memset(n, 0, sizeof(*n));
241
242 n->startbit = le32_to_cpu(buf[0]);
243
244 if (n->startbit & (MAPSIZE - 1)) {
245 printk(KERN_ERR "security: ebitmap start bit (%d) is "
246 "not a multiple of the map size (%Zd)\n",
247 n->startbit, MAPSIZE);
248 goto bad_free;
249 }
250 if (n->startbit > (e->highbit - MAPSIZE)) {
251 printk(KERN_ERR "security: ebitmap start bit (%d) is "
252 "beyond the end of the bitmap (%Zd)\n",
253 n->startbit, (e->highbit - MAPSIZE));
254 goto bad_free;
255 }
256 rc = next_entry(&map, fp, sizeof(u64));
257 if (rc < 0) {
258 printk(KERN_ERR "security: ebitmap: truncated map\n");
259 goto bad_free;
260 }
261 n->map = le64_to_cpu(map);
262
263 if (!n->map) {
264 printk(KERN_ERR "security: ebitmap: null map in "
265 "ebitmap (startbit %d)\n", n->startbit);
266 goto bad_free;
267 }
268 if (l) {
269 if (n->startbit <= l->startbit) {
270 printk(KERN_ERR "security: ebitmap: start "
271 "bit %d comes after start bit %d\n",
272 n->startbit, l->startbit);
273 goto bad_free;
274 }
275 l->next = n;
276 } else
277 e->node = n;
278
279 l = n;
280 }
281
282ok:
283 rc = 0;
284out:
285 return rc;
286bad_free:
287 kfree(n);
288bad:
289 if (!rc)
290 rc = -EINVAL;
291 ebitmap_destroy(e);
292 goto out;
293}
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
new file mode 100644
index 00000000000..471370233fd
--- /dev/null
+++ b/security/selinux/ss/ebitmap.h
@@ -0,0 +1,48 @@
1/*
2 * An extensible bitmap is a bitmap that supports an
3 * arbitrary number of bits. Extensible bitmaps are
4 * used to represent sets of values, such as types,
5 * roles, categories, and classes.
6 *
7 * Each extensible bitmap is implemented as a linked
8 * list of bitmap nodes, where each bitmap node has
9 * an explicitly specified starting bit position within
10 * the total bitmap.
11 *
12 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
13 */
14#ifndef _SS_EBITMAP_H_
15#define _SS_EBITMAP_H_
16
17#define MAPTYPE u64 /* portion of bitmap in each node */
18#define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */
19#define MAPBIT 1ULL /* a bit in the node bitmap */
20
21struct ebitmap_node {
22 u32 startbit; /* starting position in the total bitmap */
23 MAPTYPE map; /* this node's portion of the bitmap */
24 struct ebitmap_node *next;
25};
26
27struct ebitmap {
28 struct ebitmap_node *node; /* first node in the bitmap */
29 u32 highbit; /* highest position in the total bitmap */
30};
31
32#define ebitmap_length(e) ((e)->highbit)
33#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
34
35static inline void ebitmap_init(struct ebitmap *e)
36{
37 memset(e, 0, sizeof(*e));
38}
39
40int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
41int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
42int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
43int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
44int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
45void ebitmap_destroy(struct ebitmap *e);
46int ebitmap_read(struct ebitmap *e, void *fp);
47
48#endif /* _SS_EBITMAP_H_ */
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
new file mode 100644
index 00000000000..26661fcc00c
--- /dev/null
+++ b/security/selinux/ss/hashtab.c
@@ -0,0 +1,167 @@
1/*
2 * Implementation of the hash table type.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6#include <linux/kernel.h>
7#include <linux/slab.h>
8#include <linux/errno.h>
9#include "hashtab.h"
10
11struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
12 int (*keycmp)(struct hashtab *h, void *key1, void *key2),
13 u32 size)
14{
15 struct hashtab *p;
16 u32 i;
17
18 p = kmalloc(sizeof(*p), GFP_KERNEL);
19 if (p == NULL)
20 return p;
21
22 memset(p, 0, sizeof(*p));
23 p->size = size;
24 p->nel = 0;
25 p->hash_value = hash_value;
26 p->keycmp = keycmp;
27 p->htable = kmalloc(sizeof(*(p->htable)) * size, GFP_KERNEL);
28 if (p->htable == NULL) {
29 kfree(p);
30 return NULL;
31 }
32
33 for (i = 0; i < size; i++)
34 p->htable[i] = NULL;
35
36 return p;
37}
38
39int hashtab_insert(struct hashtab *h, void *key, void *datum)
40{
41 u32 hvalue;
42 struct hashtab_node *prev, *cur, *newnode;
43
44 if (!h || h->nel == HASHTAB_MAX_NODES)
45 return -EINVAL;
46
47 hvalue = h->hash_value(h, key);
48 prev = NULL;
49 cur = h->htable[hvalue];
50 while (cur && h->keycmp(h, key, cur->key) > 0) {
51 prev = cur;
52 cur = cur->next;
53 }
54
55 if (cur && (h->keycmp(h, key, cur->key) == 0))
56 return -EEXIST;
57
58 newnode = kmalloc(sizeof(*newnode), GFP_KERNEL);
59 if (newnode == NULL)
60 return -ENOMEM;
61 memset(newnode, 0, sizeof(*newnode));
62 newnode->key = key;
63 newnode->datum = datum;
64 if (prev) {
65 newnode->next = prev->next;
66 prev->next = newnode;
67 } else {
68 newnode->next = h->htable[hvalue];
69 h->htable[hvalue] = newnode;
70 }
71
72 h->nel++;
73 return 0;
74}
75
76void *hashtab_search(struct hashtab *h, void *key)
77{
78 u32 hvalue;
79 struct hashtab_node *cur;
80
81 if (!h)
82 return NULL;
83
84 hvalue = h->hash_value(h, key);
85 cur = h->htable[hvalue];
86 while (cur != NULL && h->keycmp(h, key, cur->key) > 0)
87 cur = cur->next;
88
89 if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
90 return NULL;
91
92 return cur->datum;
93}
94
95void hashtab_destroy(struct hashtab *h)
96{
97 u32 i;
98 struct hashtab_node *cur, *temp;
99
100 if (!h)
101 return;
102
103 for (i = 0; i < h->size; i++) {
104 cur = h->htable[i];
105 while (cur != NULL) {
106 temp = cur;
107 cur = cur->next;
108 kfree(temp);
109 }
110 h->htable[i] = NULL;
111 }
112
113 kfree(h->htable);
114 h->htable = NULL;
115
116 kfree(h);
117}
118
119int hashtab_map(struct hashtab *h,
120 int (*apply)(void *k, void *d, void *args),
121 void *args)
122{
123 u32 i;
124 int ret;
125 struct hashtab_node *cur;
126
127 if (!h)
128 return 0;
129
130 for (i = 0; i < h->size; i++) {
131 cur = h->htable[i];
132 while (cur != NULL) {
133 ret = apply(cur->key, cur->datum, args);
134 if (ret)
135 return ret;
136 cur = cur->next;
137 }
138 }
139 return 0;
140}
141
142
143void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
144{
145 u32 i, chain_len, slots_used, max_chain_len;
146 struct hashtab_node *cur;
147
148 slots_used = 0;
149 max_chain_len = 0;
150 for (slots_used = max_chain_len = i = 0; i < h->size; i++) {
151 cur = h->htable[i];
152 if (cur) {
153 slots_used++;
154 chain_len = 0;
155 while (cur) {
156 chain_len++;
157 cur = cur->next;
158 }
159
160 if (chain_len > max_chain_len)
161 max_chain_len = chain_len;
162 }
163 }
164
165 info->slots_used = slots_used;
166 info->max_chain_len = max_chain_len;
167}
diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h
new file mode 100644
index 00000000000..4cc85816a71
--- /dev/null
+++ b/security/selinux/ss/hashtab.h
@@ -0,0 +1,87 @@
1/*
2 * A hash table (hashtab) maintains associations between
3 * key values and datum values. The type of the key values
4 * and the type of the datum values is arbitrary. The
5 * functions for hash computation and key comparison are
6 * provided by the creator of the table.
7 *
8 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
9 */
10#ifndef _SS_HASHTAB_H_
11#define _SS_HASHTAB_H_
12
13#define HASHTAB_MAX_NODES 0xffffffff
14
15struct hashtab_node {
16 void *key;
17 void *datum;
18 struct hashtab_node *next;
19};
20
21struct hashtab {
22 struct hashtab_node **htable; /* hash table */
23 u32 size; /* number of slots in hash table */
24 u32 nel; /* number of elements in hash table */
25 u32 (*hash_value)(struct hashtab *h, void *key);
26 /* hash function */
27 int (*keycmp)(struct hashtab *h, void *key1, void *key2);
28 /* key comparison function */
29};
30
31struct hashtab_info {
32 u32 slots_used;
33 u32 max_chain_len;
34};
35
36/*
37 * Creates a new hash table with the specified characteristics.
38 *
39 * Returns NULL if insufficent space is available or
40 * the new hash table otherwise.
41 */
42struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
43 int (*keycmp)(struct hashtab *h, void *key1, void *key2),
44 u32 size);
45
46/*
47 * Inserts the specified (key, datum) pair into the specified hash table.
48 *
49 * Returns -ENOMEM on memory allocation error,
50 * -EEXIST if there is already an entry with the same key,
51 * -EINVAL for general errors or
52 * 0 otherwise.
53 */
54int hashtab_insert(struct hashtab *h, void *k, void *d);
55
56/*
57 * Searches for the entry with the specified key in the hash table.
58 *
59 * Returns NULL if no entry has the specified key or
60 * the datum of the entry otherwise.
61 */
62void *hashtab_search(struct hashtab *h, void *k);
63
64/*
65 * Destroys the specified hash table.
66 */
67void hashtab_destroy(struct hashtab *h);
68
69/*
70 * Applies the specified apply function to (key,datum,args)
71 * for each entry in the specified hash table.
72 *
73 * The order in which the function is applied to the entries
74 * is dependent upon the internal structure of the hash table.
75 *
76 * If apply returns a non-zero status, then hashtab_map will cease
77 * iterating through the hash table and will propagate the error
78 * return to its caller.
79 */
80int hashtab_map(struct hashtab *h,
81 int (*apply)(void *k, void *d, void *args),
82 void *args);
83
84/* Fill info with some hash table statistics */
85void hashtab_stat(struct hashtab *h, struct hashtab_info *info);
86
87#endif /* _SS_HASHTAB_H */
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
new file mode 100644
index 00000000000..756036bcc24
--- /dev/null
+++ b/security/selinux/ss/mls.c
@@ -0,0 +1,527 @@
1/*
2 * Implementation of the multi-level security (MLS) policy.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6/*
7 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
8 *
9 * Support for enhanced MLS infrastructure.
10 *
11 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
12 */
13
14#include <linux/kernel.h>
15#include <linux/slab.h>
16#include <linux/string.h>
17#include <linux/errno.h>
18#include "mls.h"
19#include "policydb.h"
20#include "services.h"
21
22/*
23 * Return the length in bytes for the MLS fields of the
24 * security context string representation of `context'.
25 */
26int mls_compute_context_len(struct context * context)
27{
28 int i, l, len, range;
29
30 if (!selinux_mls_enabled)
31 return 0;
32
33 len = 1; /* for the beginning ":" */
34 for (l = 0; l < 2; l++) {
35 range = 0;
36 len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
37
38 for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) {
39 if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) {
40 if (range) {
41 range++;
42 continue;
43 }
44
45 len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
46 range++;
47 } else {
48 if (range > 1)
49 len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1;
50 range = 0;
51 }
52 }
53 /* Handle case where last category is the end of range */
54 if (range > 1)
55 len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1;
56
57 if (l == 0) {
58 if (mls_level_eq(&context->range.level[0],
59 &context->range.level[1]))
60 break;
61 else
62 len++;
63 }
64 }
65
66 return len;
67}
68
69/*
70 * Write the security context string representation of
71 * the MLS fields of `context' into the string `*scontext'.
72 * Update `*scontext' to point to the end of the MLS fields.
73 */
74void mls_sid_to_context(struct context *context,
75 char **scontext)
76{
77 char *scontextp;
78 int i, l, range, wrote_sep;
79
80 if (!selinux_mls_enabled)
81 return;
82
83 scontextp = *scontext;
84
85 *scontextp = ':';
86 scontextp++;
87
88 for (l = 0; l < 2; l++) {
89 range = 0;
90 wrote_sep = 0;
91 strcpy(scontextp,
92 policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
93 scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
94
95 /* categories */
96 for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) {
97 if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) {
98 if (range) {
99 range++;
100 continue;
101 }
102
103 if (!wrote_sep) {
104 *scontextp++ = ':';
105 wrote_sep = 1;
106 } else
107 *scontextp++ = ',';
108 strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
109 scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
110 range++;
111 } else {
112 if (range > 1) {
113 if (range > 2)
114 *scontextp++ = '.';
115 else
116 *scontextp++ = ',';
117
118 strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]);
119 scontextp += strlen(policydb.p_cat_val_to_name[i - 2]);
120 }
121 range = 0;
122 }
123 }
124
125 /* Handle case where last category is the end of range */
126 if (range > 1) {
127 if (range > 2)
128 *scontextp++ = '.';
129 else
130 *scontextp++ = ',';
131
132 strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]);
133 scontextp += strlen(policydb.p_cat_val_to_name[i - 2]);
134 }
135
136 if (l == 0) {
137 if (mls_level_eq(&context->range.level[0],
138 &context->range.level[1]))
139 break;
140 else {
141 *scontextp = '-';
142 scontextp++;
143 }
144 }
145 }
146
147 *scontext = scontextp;
148 return;
149}
150
151/*
152 * Return 1 if the MLS fields in the security context
153 * structure `c' are valid. Return 0 otherwise.
154 */
155int mls_context_isvalid(struct policydb *p, struct context *c)
156{
157 struct level_datum *levdatum;
158 struct user_datum *usrdatum;
159 int i, l;
160
161 if (!selinux_mls_enabled)
162 return 1;
163
164 /*
165 * MLS range validity checks: high must dominate low, low level must
166 * be valid (category set <-> sensitivity check), and high level must
167 * be valid (category set <-> sensitivity check)
168 */
169 if (!mls_level_dom(&c->range.level[1], &c->range.level[0]))
170 /* High does not dominate low. */
171 return 0;
172
173 for (l = 0; l < 2; l++) {
174 if (!c->range.level[l].sens || c->range.level[l].sens > p->p_levels.nprim)
175 return 0;
176 levdatum = hashtab_search(p->p_levels.table,
177 p->p_sens_val_to_name[c->range.level[l].sens - 1]);
178 if (!levdatum)
179 return 0;
180
181 for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) {
182 if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) {
183 if (i > p->p_cats.nprim)
184 return 0;
185 if (!ebitmap_get_bit(&levdatum->level->cat, i - 1))
186 /*
187 * Category may not be associated with
188 * sensitivity in low level.
189 */
190 return 0;
191 }
192 }
193 }
194
195 if (c->role == OBJECT_R_VAL)
196 return 1;
197
198 /*
199 * User must be authorized for the MLS range.
200 */
201 if (!c->user || c->user > p->p_users.nprim)
202 return 0;
203 usrdatum = p->user_val_to_struct[c->user - 1];
204 if (!mls_range_contains(usrdatum->range, c->range))
205 return 0; /* user may not be associated with range */
206
207 return 1;
208}
209
210/*
211 * Set the MLS fields in the security context structure
212 * `context' based on the string representation in
213 * the string `*scontext'. Update `*scontext' to
214 * point to the end of the string representation of
215 * the MLS fields.
216 *
217 * This function modifies the string in place, inserting
218 * NULL characters to terminate the MLS fields.
219 */
220int mls_context_to_sid(char oldc,
221 char **scontext,
222 struct context *context)
223{
224
225 char delim;
226 char *scontextp, *p, *rngptr;
227 struct level_datum *levdatum;
228 struct cat_datum *catdatum, *rngdatum;
229 int l, rc = -EINVAL;
230
231 if (!selinux_mls_enabled)
232 return 0;
233
234 /* No MLS component to the security context. */
235 if (!oldc)
236 goto out;
237
238 /* Extract low sensitivity. */
239 scontextp = p = *scontext;
240 while (*p && *p != ':' && *p != '-')
241 p++;
242
243 delim = *p;
244 if (delim != 0)
245 *p++ = 0;
246
247 for (l = 0; l < 2; l++) {
248 levdatum = hashtab_search(policydb.p_levels.table, scontextp);
249 if (!levdatum) {
250 rc = -EINVAL;
251 goto out;
252 }
253
254 context->range.level[l].sens = levdatum->level->sens;
255
256 if (delim == ':') {
257 /* Extract category set. */
258 while (1) {
259 scontextp = p;
260 while (*p && *p != ',' && *p != '-')
261 p++;
262 delim = *p;
263 if (delim != 0)
264 *p++ = 0;
265
266 /* Separate into range if exists */
267 if ((rngptr = strchr(scontextp, '.')) != NULL) {
268 /* Remove '.' */
269 *rngptr++ = 0;
270 }
271
272 catdatum = hashtab_search(policydb.p_cats.table,
273 scontextp);
274 if (!catdatum) {
275 rc = -EINVAL;
276 goto out;
277 }
278
279 rc = ebitmap_set_bit(&context->range.level[l].cat,
280 catdatum->value - 1, 1);
281 if (rc)
282 goto out;
283
284 /* If range, set all categories in range */
285 if (rngptr) {
286 int i;
287
288 rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
289 if (!rngdatum) {
290 rc = -EINVAL;
291 goto out;
292 }
293
294 if (catdatum->value >= rngdatum->value) {
295 rc = -EINVAL;
296 goto out;
297 }
298
299 for (i = catdatum->value; i < rngdatum->value; i++) {
300 rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
301 if (rc)
302 goto out;
303 }
304 }
305
306 if (delim != ',')
307 break;
308 }
309 }
310 if (delim == '-') {
311 /* Extract high sensitivity. */
312 scontextp = p;
313 while (*p && *p != ':')
314 p++;
315
316 delim = *p;
317 if (delim != 0)
318 *p++ = 0;
319 } else
320 break;
321 }
322
323 if (l == 0) {
324 context->range.level[1].sens = context->range.level[0].sens;
325 rc = ebitmap_cpy(&context->range.level[1].cat,
326 &context->range.level[0].cat);
327 if (rc)
328 goto out;
329 }
330 *scontext = ++p;
331 rc = 0;
332out:
333 return rc;
334}
335
336/*
337 * Copies the MLS range from `src' into `dst'.
338 */
339static inline int mls_copy_context(struct context *dst,
340 struct context *src)
341{
342 int l, rc = 0;
343
344 /* Copy the MLS range from the source context */
345 for (l = 0; l < 2; l++) {
346 dst->range.level[l].sens = src->range.level[l].sens;
347 rc = ebitmap_cpy(&dst->range.level[l].cat,
348 &src->range.level[l].cat);
349 if (rc)
350 break;
351 }
352
353 return rc;
354}
355
356/*
357 * Copies the effective MLS range from `src' into `dst'.
358 */
359static inline int mls_scopy_context(struct context *dst,
360 struct context *src)
361{
362 int l, rc = 0;
363
364 /* Copy the MLS range from the source context */
365 for (l = 0; l < 2; l++) {
366 dst->range.level[l].sens = src->range.level[0].sens;
367 rc = ebitmap_cpy(&dst->range.level[l].cat,
368 &src->range.level[0].cat);
369 if (rc)
370 break;
371 }
372
373 return rc;
374}
375
376/*
377 * Copies the MLS range `range' into `context'.
378 */
379static inline int mls_range_set(struct context *context,
380 struct mls_range *range)
381{
382 int l, rc = 0;
383
384 /* Copy the MLS range into the context */
385 for (l = 0; l < 2; l++) {
386 context->range.level[l].sens = range->level[l].sens;
387 rc = ebitmap_cpy(&context->range.level[l].cat,
388 &range->level[l].cat);
389 if (rc)
390 break;
391 }
392
393 return rc;
394}
395
396int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
397 struct context *usercon)
398{
399 if (selinux_mls_enabled) {
400 struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
401 struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
402 struct mls_level *user_low = &(user->range.level[0]);
403 struct mls_level *user_clr = &(user->range.level[1]);
404 struct mls_level *user_def = &(user->dfltlevel);
405 struct mls_level *usercon_sen = &(usercon->range.level[0]);
406 struct mls_level *usercon_clr = &(usercon->range.level[1]);
407
408 /* Honor the user's default level if we can */
409 if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) {
410 *usercon_sen = *user_def;
411 } else if (mls_level_between(fromcon_sen, user_def, user_clr)) {
412 *usercon_sen = *fromcon_sen;
413 } else if (mls_level_between(fromcon_clr, user_low, user_def)) {
414 *usercon_sen = *user_low;
415 } else
416 return -EINVAL;
417
418 /* Lower the clearance of available contexts
419 if the clearance of "fromcon" is lower than
420 that of the user's default clearance (but
421 only if the "fromcon" clearance dominates
422 the user's computed sensitivity level) */
423 if (mls_level_dom(user_clr, fromcon_clr)) {
424 *usercon_clr = *fromcon_clr;
425 } else if (mls_level_dom(fromcon_clr, user_clr)) {
426 *usercon_clr = *user_clr;
427 } else
428 return -EINVAL;
429 }
430
431 return 0;
432}
433
434/*
435 * Convert the MLS fields in the security context
436 * structure `c' from the values specified in the
437 * policy `oldp' to the values specified in the policy `newp'.
438 */
439int mls_convert_context(struct policydb *oldp,
440 struct policydb *newp,
441 struct context *c)
442{
443 struct level_datum *levdatum;
444 struct cat_datum *catdatum;
445 struct ebitmap bitmap;
446 int l, i;
447
448 if (!selinux_mls_enabled)
449 return 0;
450
451 for (l = 0; l < 2; l++) {
452 levdatum = hashtab_search(newp->p_levels.table,
453 oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
454
455 if (!levdatum)
456 return -EINVAL;
457 c->range.level[l].sens = levdatum->level->sens;
458
459 ebitmap_init(&bitmap);
460 for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) {
461 if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) {
462 int rc;
463
464 catdatum = hashtab_search(newp->p_cats.table,
465 oldp->p_cat_val_to_name[i - 1]);
466 if (!catdatum)
467 return -EINVAL;
468 rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
469 if (rc)
470 return rc;
471 }
472 }
473 ebitmap_destroy(&c->range.level[l].cat);
474 c->range.level[l].cat = bitmap;
475 }
476
477 return 0;
478}
479
480int mls_compute_sid(struct context *scontext,
481 struct context *tcontext,
482 u16 tclass,
483 u32 specified,
484 struct context *newcontext)
485{
486 if (!selinux_mls_enabled)
487 return 0;
488
489 switch (specified) {
490 case AVTAB_TRANSITION:
491 if (tclass == SECCLASS_PROCESS) {
492 struct range_trans *rangetr;
493 /* Look for a range transition rule. */
494 for (rangetr = policydb.range_tr; rangetr;
495 rangetr = rangetr->next) {
496 if (rangetr->dom == scontext->type &&
497 rangetr->type == tcontext->type) {
498 /* Set the range from the rule */
499 return mls_range_set(newcontext,
500 &rangetr->range);
501 }
502 }
503 }
504 /* Fallthrough */
505 case AVTAB_CHANGE:
506 if (tclass == SECCLASS_PROCESS)
507 /* Use the process MLS attributes. */
508 return mls_copy_context(newcontext, scontext);
509 else
510 /* Use the process effective MLS attributes. */
511 return mls_scopy_context(newcontext, scontext);
512 case AVTAB_MEMBER:
513 /* Only polyinstantiate the MLS attributes if
514 the type is being polyinstantiated */
515 if (newcontext->type != tcontext->type) {
516 /* Use the process effective MLS attributes. */
517 return mls_scopy_context(newcontext, scontext);
518 } else {
519 /* Use the related object MLS attributes. */
520 return mls_copy_context(newcontext, tcontext);
521 }
522 default:
523 return -EINVAL;
524 }
525 return -EINVAL;
526}
527
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
new file mode 100644
index 00000000000..0d37beaa85e
--- /dev/null
+++ b/security/selinux/ss/mls.h
@@ -0,0 +1,42 @@
1/*
2 * Multi-level security (MLS) policy operations.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6/*
7 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
8 *
9 * Support for enhanced MLS infrastructure.
10 *
11 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
12 */
13
14#ifndef _SS_MLS_H_
15#define _SS_MLS_H_
16
17#include "context.h"
18#include "policydb.h"
19
20int mls_compute_context_len(struct context *context);
21void mls_sid_to_context(struct context *context, char **scontext);
22int mls_context_isvalid(struct policydb *p, struct context *c);
23
24int mls_context_to_sid(char oldc,
25 char **scontext,
26 struct context *context);
27
28int mls_convert_context(struct policydb *oldp,
29 struct policydb *newp,
30 struct context *context);
31
32int mls_compute_sid(struct context *scontext,
33 struct context *tcontext,
34 u16 tclass,
35 u32 specified,
36 struct context *newcontext);
37
38int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
39 struct context *usercon);
40
41#endif /* _SS_MLS_H */
42
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h
new file mode 100644
index 00000000000..0c692d58d48
--- /dev/null
+++ b/security/selinux/ss/mls_types.h
@@ -0,0 +1,56 @@
1/*
2 * Type definitions for the multi-level security (MLS) policy.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6/*
7 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
8 *
9 * Support for enhanced MLS infrastructure.
10 *
11 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
12 */
13
14#ifndef _SS_MLS_TYPES_H_
15#define _SS_MLS_TYPES_H_
16
17#include "security.h"
18
19struct mls_level {
20 u32 sens; /* sensitivity */
21 struct ebitmap cat; /* category set */
22};
23
24struct mls_range {
25 struct mls_level level[2]; /* low == level[0], high == level[1] */
26};
27
28static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
29{
30 if (!selinux_mls_enabled)
31 return 1;
32
33 return ((l1->sens == l2->sens) &&
34 ebitmap_cmp(&l1->cat, &l2->cat));
35}
36
37static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
38{
39 if (!selinux_mls_enabled)
40 return 1;
41
42 return ((l1->sens >= l2->sens) &&
43 ebitmap_contains(&l1->cat, &l2->cat));
44}
45
46#define mls_level_incomp(l1, l2) \
47(!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1)))
48
49#define mls_level_between(l1, l2, l3) \
50(mls_level_dom((l1), (l2)) && mls_level_dom((l3), (l1)))
51
52#define mls_range_contains(r1, r2) \
53(mls_level_dom(&(r2).level[0], &(r1).level[0]) && \
54 mls_level_dom(&(r1).level[1], &(r2).level[1]))
55
56#endif /* _SS_MLS_TYPES_H_ */
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
new file mode 100644
index 00000000000..14190efbf33
--- /dev/null
+++ b/security/selinux/ss/policydb.c
@@ -0,0 +1,1843 @@
1/*
2 * Implementation of the policy database.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6
7/*
8 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
9 *
10 * Support for enhanced MLS infrastructure.
11 *
12 * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
13 *
14 * Added conditional policy language extensions
15 *
16 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
17 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation, version 2.
21 */
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/string.h>
26#include <linux/errno.h>
27#include "security.h"
28
29#include "policydb.h"
30#include "conditional.h"
31#include "mls.h"
32
33#define _DEBUG_HASHES
34
35#ifdef DEBUG_HASHES
36static char *symtab_name[SYM_NUM] = {
37 "common prefixes",
38 "classes",
39 "roles",
40 "types",
41 "users",
42 "bools",
43 "levels",
44 "categories",
45};
46#endif
47
48int selinux_mls_enabled = 0;
49
50static unsigned int symtab_sizes[SYM_NUM] = {
51 2,
52 32,
53 16,
54 512,
55 128,
56 16,
57 16,
58 16,
59};
60
61struct policydb_compat_info {
62 int version;
63 int sym_num;
64 int ocon_num;
65};
66
67/* These need to be updated if SYM_NUM or OCON_NUM changes */
68static struct policydb_compat_info policydb_compat[] = {
69 {
70 .version = POLICYDB_VERSION_BASE,
71 .sym_num = SYM_NUM - 3,
72 .ocon_num = OCON_NUM - 1,
73 },
74 {
75 .version = POLICYDB_VERSION_BOOL,
76 .sym_num = SYM_NUM - 2,
77 .ocon_num = OCON_NUM - 1,
78 },
79 {
80 .version = POLICYDB_VERSION_IPV6,
81 .sym_num = SYM_NUM - 2,
82 .ocon_num = OCON_NUM,
83 },
84 {
85 .version = POLICYDB_VERSION_NLCLASS,
86 .sym_num = SYM_NUM - 2,
87 .ocon_num = OCON_NUM,
88 },
89 {
90 .version = POLICYDB_VERSION_MLS,
91 .sym_num = SYM_NUM,
92 .ocon_num = OCON_NUM,
93 },
94};
95
96static struct policydb_compat_info *policydb_lookup_compat(int version)
97{
98 int i;
99 struct policydb_compat_info *info = NULL;
100
101 for (i = 0; i < sizeof(policydb_compat)/sizeof(*info); i++) {
102 if (policydb_compat[i].version == version) {
103 info = &policydb_compat[i];
104 break;
105 }
106 }
107 return info;
108}
109
110/*
111 * Initialize the role table.
112 */
113static int roles_init(struct policydb *p)
114{
115 char *key = NULL;
116 int rc;
117 struct role_datum *role;
118
119 role = kmalloc(sizeof(*role), GFP_KERNEL);
120 if (!role) {
121 rc = -ENOMEM;
122 goto out;
123 }
124 memset(role, 0, sizeof(*role));
125 role->value = ++p->p_roles.nprim;
126 if (role->value != OBJECT_R_VAL) {
127 rc = -EINVAL;
128 goto out_free_role;
129 }
130 key = kmalloc(strlen(OBJECT_R)+1,GFP_KERNEL);
131 if (!key) {
132 rc = -ENOMEM;
133 goto out_free_role;
134 }
135 strcpy(key, OBJECT_R);
136 rc = hashtab_insert(p->p_roles.table, key, role);
137 if (rc)
138 goto out_free_key;
139out:
140 return rc;
141
142out_free_key:
143 kfree(key);
144out_free_role:
145 kfree(role);
146 goto out;
147}
148
149/*
150 * Initialize a policy database structure.
151 */
152static int policydb_init(struct policydb *p)
153{
154 int i, rc;
155
156 memset(p, 0, sizeof(*p));
157
158 for (i = 0; i < SYM_NUM; i++) {
159 rc = symtab_init(&p->symtab[i], symtab_sizes[i]);
160 if (rc)
161 goto out_free_symtab;
162 }
163
164 rc = avtab_init(&p->te_avtab);
165 if (rc)
166 goto out_free_symtab;
167
168 rc = roles_init(p);
169 if (rc)
170 goto out_free_avtab;
171
172 rc = cond_policydb_init(p);
173 if (rc)
174 goto out_free_avtab;
175
176out:
177 return rc;
178
179out_free_avtab:
180 avtab_destroy(&p->te_avtab);
181
182out_free_symtab:
183 for (i = 0; i < SYM_NUM; i++)
184 hashtab_destroy(p->symtab[i].table);
185 goto out;
186}
187
188/*
189 * The following *_index functions are used to
190 * define the val_to_name and val_to_struct arrays
191 * in a policy database structure. The val_to_name
192 * arrays are used when converting security context
193 * structures into string representations. The
194 * val_to_struct arrays are used when the attributes
195 * of a class, role, or user are needed.
196 */
197
198static int common_index(void *key, void *datum, void *datap)
199{
200 struct policydb *p;
201 struct common_datum *comdatum;
202
203 comdatum = datum;
204 p = datap;
205 if (!comdatum->value || comdatum->value > p->p_commons.nprim)
206 return -EINVAL;
207 p->p_common_val_to_name[comdatum->value - 1] = key;
208 return 0;
209}
210
211static int class_index(void *key, void *datum, void *datap)
212{
213 struct policydb *p;
214 struct class_datum *cladatum;
215
216 cladatum = datum;
217 p = datap;
218 if (!cladatum->value || cladatum->value > p->p_classes.nprim)
219 return -EINVAL;
220 p->p_class_val_to_name[cladatum->value - 1] = key;
221 p->class_val_to_struct[cladatum->value - 1] = cladatum;
222 return 0;
223}
224
225static int role_index(void *key, void *datum, void *datap)
226{
227 struct policydb *p;
228 struct role_datum *role;
229
230 role = datum;
231 p = datap;
232 if (!role->value || role->value > p->p_roles.nprim)
233 return -EINVAL;
234 p->p_role_val_to_name[role->value - 1] = key;
235 p->role_val_to_struct[role->value - 1] = role;
236 return 0;
237}
238
239static int type_index(void *key, void *datum, void *datap)
240{
241 struct policydb *p;
242 struct type_datum *typdatum;
243
244 typdatum = datum;
245 p = datap;
246
247 if (typdatum->primary) {
248 if (!typdatum->value || typdatum->value > p->p_types.nprim)
249 return -EINVAL;
250 p->p_type_val_to_name[typdatum->value - 1] = key;
251 }
252
253 return 0;
254}
255
256static int user_index(void *key, void *datum, void *datap)
257{
258 struct policydb *p;
259 struct user_datum *usrdatum;
260
261 usrdatum = datum;
262 p = datap;
263 if (!usrdatum->value || usrdatum->value > p->p_users.nprim)
264 return -EINVAL;
265 p->p_user_val_to_name[usrdatum->value - 1] = key;
266 p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
267 return 0;
268}
269
270static int sens_index(void *key, void *datum, void *datap)
271{
272 struct policydb *p;
273 struct level_datum *levdatum;
274
275 levdatum = datum;
276 p = datap;
277
278 if (!levdatum->isalias) {
279 if (!levdatum->level->sens ||
280 levdatum->level->sens > p->p_levels.nprim)
281 return -EINVAL;
282 p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
283 }
284
285 return 0;
286}
287
288static int cat_index(void *key, void *datum, void *datap)
289{
290 struct policydb *p;
291 struct cat_datum *catdatum;
292
293 catdatum = datum;
294 p = datap;
295
296 if (!catdatum->isalias) {
297 if (!catdatum->value || catdatum->value > p->p_cats.nprim)
298 return -EINVAL;
299 p->p_cat_val_to_name[catdatum->value - 1] = key;
300 }
301
302 return 0;
303}
304
305static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
306{
307 common_index,
308 class_index,
309 role_index,
310 type_index,
311 user_index,
312 cond_index_bool,
313 sens_index,
314 cat_index,
315};
316
317/*
318 * Define the common val_to_name array and the class
319 * val_to_name and val_to_struct arrays in a policy
320 * database structure.
321 *
322 * Caller must clean up upon failure.
323 */
324static int policydb_index_classes(struct policydb *p)
325{
326 int rc;
327
328 p->p_common_val_to_name =
329 kmalloc(p->p_commons.nprim * sizeof(char *), GFP_KERNEL);
330 if (!p->p_common_val_to_name) {
331 rc = -ENOMEM;
332 goto out;
333 }
334
335 rc = hashtab_map(p->p_commons.table, common_index, p);
336 if (rc)
337 goto out;
338
339 p->class_val_to_struct =
340 kmalloc(p->p_classes.nprim * sizeof(*(p->class_val_to_struct)), GFP_KERNEL);
341 if (!p->class_val_to_struct) {
342 rc = -ENOMEM;
343 goto out;
344 }
345
346 p->p_class_val_to_name =
347 kmalloc(p->p_classes.nprim * sizeof(char *), GFP_KERNEL);
348 if (!p->p_class_val_to_name) {
349 rc = -ENOMEM;
350 goto out;
351 }
352
353 rc = hashtab_map(p->p_classes.table, class_index, p);
354out:
355 return rc;
356}
357
358#ifdef DEBUG_HASHES
359static void symtab_hash_eval(struct symtab *s)
360{
361 int i;
362
363 for (i = 0; i < SYM_NUM; i++) {
364 struct hashtab *h = s[i].table;
365 struct hashtab_info info;
366
367 hashtab_stat(h, &info);
368 printk(KERN_INFO "%s: %d entries and %d/%d buckets used, "
369 "longest chain length %d\n", symtab_name[i], h->nel,
370 info.slots_used, h->size, info.max_chain_len);
371 }
372}
373#endif
374
375/*
376 * Define the other val_to_name and val_to_struct arrays
377 * in a policy database structure.
378 *
379 * Caller must clean up on failure.
380 */
381static int policydb_index_others(struct policydb *p)
382{
383 int i, rc = 0;
384
385 printk(KERN_INFO "security: %d users, %d roles, %d types, %d bools",
386 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
387 if (selinux_mls_enabled)
388 printk(", %d sens, %d cats", p->p_levels.nprim,
389 p->p_cats.nprim);
390 printk("\n");
391
392 printk(KERN_INFO "security: %d classes, %d rules\n",
393 p->p_classes.nprim, p->te_avtab.nel);
394
395#ifdef DEBUG_HASHES
396 avtab_hash_eval(&p->te_avtab, "rules");
397 symtab_hash_eval(p->symtab);
398#endif
399
400 p->role_val_to_struct =
401 kmalloc(p->p_roles.nprim * sizeof(*(p->role_val_to_struct)),
402 GFP_KERNEL);
403 if (!p->role_val_to_struct) {
404 rc = -ENOMEM;
405 goto out;
406 }
407
408 p->user_val_to_struct =
409 kmalloc(p->p_users.nprim * sizeof(*(p->user_val_to_struct)),
410 GFP_KERNEL);
411 if (!p->user_val_to_struct) {
412 rc = -ENOMEM;
413 goto out;
414 }
415
416 if (cond_init_bool_indexes(p)) {
417 rc = -ENOMEM;
418 goto out;
419 }
420
421 for (i = SYM_ROLES; i < SYM_NUM; i++) {
422 p->sym_val_to_name[i] =
423 kmalloc(p->symtab[i].nprim * sizeof(char *), GFP_KERNEL);
424 if (!p->sym_val_to_name[i]) {
425 rc = -ENOMEM;
426 goto out;
427 }
428 rc = hashtab_map(p->symtab[i].table, index_f[i], p);
429 if (rc)
430 goto out;
431 }
432
433out:
434 return rc;
435}
436
437/*
438 * The following *_destroy functions are used to
439 * free any memory allocated for each kind of
440 * symbol data in the policy database.
441 */
442
443static int perm_destroy(void *key, void *datum, void *p)
444{
445 kfree(key);
446 kfree(datum);
447 return 0;
448}
449
450static int common_destroy(void *key, void *datum, void *p)
451{
452 struct common_datum *comdatum;
453
454 kfree(key);
455 comdatum = datum;
456 hashtab_map(comdatum->permissions.table, perm_destroy, NULL);
457 hashtab_destroy(comdatum->permissions.table);
458 kfree(datum);
459 return 0;
460}
461
462static int class_destroy(void *key, void *datum, void *p)
463{
464 struct class_datum *cladatum;
465 struct constraint_node *constraint, *ctemp;
466 struct constraint_expr *e, *etmp;
467
468 kfree(key);
469 cladatum = datum;
470 hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
471 hashtab_destroy(cladatum->permissions.table);
472 constraint = cladatum->constraints;
473 while (constraint) {
474 e = constraint->expr;
475 while (e) {
476 ebitmap_destroy(&e->names);
477 etmp = e;
478 e = e->next;
479 kfree(etmp);
480 }
481 ctemp = constraint;
482 constraint = constraint->next;
483 kfree(ctemp);
484 }
485
486 constraint = cladatum->validatetrans;
487 while (constraint) {
488 e = constraint->expr;
489 while (e) {
490 ebitmap_destroy(&e->names);
491 etmp = e;
492 e = e->next;
493 kfree(etmp);
494 }
495 ctemp = constraint;
496 constraint = constraint->next;
497 kfree(ctemp);
498 }
499
500 kfree(cladatum->comkey);
501 kfree(datum);
502 return 0;
503}
504
505static int role_destroy(void *key, void *datum, void *p)
506{
507 struct role_datum *role;
508
509 kfree(key);
510 role = datum;
511 ebitmap_destroy(&role->dominates);
512 ebitmap_destroy(&role->types);
513 kfree(datum);
514 return 0;
515}
516
517static int type_destroy(void *key, void *datum, void *p)
518{
519 kfree(key);
520 kfree(datum);
521 return 0;
522}
523
524static int user_destroy(void *key, void *datum, void *p)
525{
526 struct user_datum *usrdatum;
527
528 kfree(key);
529 usrdatum = datum;
530 ebitmap_destroy(&usrdatum->roles);
531 ebitmap_destroy(&usrdatum->range.level[0].cat);
532 ebitmap_destroy(&usrdatum->range.level[1].cat);
533 ebitmap_destroy(&usrdatum->dfltlevel.cat);
534 kfree(datum);
535 return 0;
536}
537
538static int sens_destroy(void *key, void *datum, void *p)
539{
540 struct level_datum *levdatum;
541
542 kfree(key);
543 levdatum = datum;
544 ebitmap_destroy(&levdatum->level->cat);
545 kfree(levdatum->level);
546 kfree(datum);
547 return 0;
548}
549
550static int cat_destroy(void *key, void *datum, void *p)
551{
552 kfree(key);
553 kfree(datum);
554 return 0;
555}
556
557static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
558{
559 common_destroy,
560 class_destroy,
561 role_destroy,
562 type_destroy,
563 user_destroy,
564 cond_destroy_bool,
565 sens_destroy,
566 cat_destroy,
567};
568
569static void ocontext_destroy(struct ocontext *c, int i)
570{
571 context_destroy(&c->context[0]);
572 context_destroy(&c->context[1]);
573 if (i == OCON_ISID || i == OCON_FS ||
574 i == OCON_NETIF || i == OCON_FSUSE)
575 kfree(c->u.name);
576 kfree(c);
577}
578
579/*
580 * Free any memory allocated by a policy database structure.
581 */
582void policydb_destroy(struct policydb *p)
583{
584 struct ocontext *c, *ctmp;
585 struct genfs *g, *gtmp;
586 int i;
587
588 for (i = 0; i < SYM_NUM; i++) {
589 hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
590 hashtab_destroy(p->symtab[i].table);
591 }
592
593 for (i = 0; i < SYM_NUM; i++) {
594 if (p->sym_val_to_name[i])
595 kfree(p->sym_val_to_name[i]);
596 }
597
598 if (p->class_val_to_struct)
599 kfree(p->class_val_to_struct);
600 if (p->role_val_to_struct)
601 kfree(p->role_val_to_struct);
602 if (p->user_val_to_struct)
603 kfree(p->user_val_to_struct);
604
605 avtab_destroy(&p->te_avtab);
606
607 for (i = 0; i < OCON_NUM; i++) {
608 c = p->ocontexts[i];
609 while (c) {
610 ctmp = c;
611 c = c->next;
612 ocontext_destroy(ctmp,i);
613 }
614 }
615
616 g = p->genfs;
617 while (g) {
618 kfree(g->fstype);
619 c = g->head;
620 while (c) {
621 ctmp = c;
622 c = c->next;
623 ocontext_destroy(ctmp,OCON_FSUSE);
624 }
625 gtmp = g;
626 g = g->next;
627 kfree(gtmp);
628 }
629
630 cond_policydb_destroy(p);
631
632 return;
633}
634
635/*
636 * Load the initial SIDs specified in a policy database
637 * structure into a SID table.
638 */
639int policydb_load_isids(struct policydb *p, struct sidtab *s)
640{
641 struct ocontext *head, *c;
642 int rc;
643
644 rc = sidtab_init(s);
645 if (rc) {
646 printk(KERN_ERR "security: out of memory on SID table init\n");
647 goto out;
648 }
649
650 head = p->ocontexts[OCON_ISID];
651 for (c = head; c; c = c->next) {
652 if (!c->context[0].user) {
653 printk(KERN_ERR "security: SID %s was never "
654 "defined.\n", c->u.name);
655 rc = -EINVAL;
656 goto out;
657 }
658 if (sidtab_insert(s, c->sid[0], &c->context[0])) {
659 printk(KERN_ERR "security: unable to load initial "
660 "SID %s.\n", c->u.name);
661 rc = -EINVAL;
662 goto out;
663 }
664 }
665out:
666 return rc;
667}
668
669/*
670 * Return 1 if the fields in the security context
671 * structure `c' are valid. Return 0 otherwise.
672 */
673int policydb_context_isvalid(struct policydb *p, struct context *c)
674{
675 struct role_datum *role;
676 struct user_datum *usrdatum;
677
678 if (!c->role || c->role > p->p_roles.nprim)
679 return 0;
680
681 if (!c->user || c->user > p->p_users.nprim)
682 return 0;
683
684 if (!c->type || c->type > p->p_types.nprim)
685 return 0;
686
687 if (c->role != OBJECT_R_VAL) {
688 /*
689 * Role must be authorized for the type.
690 */
691 role = p->role_val_to_struct[c->role - 1];
692 if (!ebitmap_get_bit(&role->types,
693 c->type - 1))
694 /* role may not be associated with type */
695 return 0;
696
697 /*
698 * User must be authorized for the role.
699 */
700 usrdatum = p->user_val_to_struct[c->user - 1];
701 if (!usrdatum)
702 return 0;
703
704 if (!ebitmap_get_bit(&usrdatum->roles,
705 c->role - 1))
706 /* user may not be associated with role */
707 return 0;
708 }
709
710 if (!mls_context_isvalid(p, c))
711 return 0;
712
713 return 1;
714}
715
716/*
717 * Read a MLS range structure from a policydb binary
718 * representation file.
719 */
720static int mls_read_range_helper(struct mls_range *r, void *fp)
721{
722 u32 buf[2], items;
723 int rc;
724
725 rc = next_entry(buf, fp, sizeof(u32));
726 if (rc < 0)
727 goto out;
728
729 items = le32_to_cpu(buf[0]);
730 if (items > ARRAY_SIZE(buf)) {
731 printk(KERN_ERR "security: mls: range overflow\n");
732 rc = -EINVAL;
733 goto out;
734 }
735 rc = next_entry(buf, fp, sizeof(u32) * items);
736 if (rc < 0) {
737 printk(KERN_ERR "security: mls: truncated range\n");
738 goto out;
739 }
740 r->level[0].sens = le32_to_cpu(buf[0]);
741 if (items > 1)
742 r->level[1].sens = le32_to_cpu(buf[1]);
743 else
744 r->level[1].sens = r->level[0].sens;
745
746 rc = ebitmap_read(&r->level[0].cat, fp);
747 if (rc) {
748 printk(KERN_ERR "security: mls: error reading low "
749 "categories\n");
750 goto out;
751 }
752 if (items > 1) {
753 rc = ebitmap_read(&r->level[1].cat, fp);
754 if (rc) {
755 printk(KERN_ERR "security: mls: error reading high "
756 "categories\n");
757 goto bad_high;
758 }
759 } else {
760 rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
761 if (rc) {
762 printk(KERN_ERR "security: mls: out of memory\n");
763 goto bad_high;
764 }
765 }
766
767 rc = 0;
768out:
769 return rc;
770bad_high:
771 ebitmap_destroy(&r->level[0].cat);
772 goto out;
773}
774
775/*
776 * Read and validate a security context structure
777 * from a policydb binary representation file.
778 */
779static int context_read_and_validate(struct context *c,
780 struct policydb *p,
781 void *fp)
782{
783 u32 buf[3];
784 int rc;
785
786 rc = next_entry(buf, fp, sizeof buf);
787 if (rc < 0) {
788 printk(KERN_ERR "security: context truncated\n");
789 goto out;
790 }
791 c->user = le32_to_cpu(buf[0]);
792 c->role = le32_to_cpu(buf[1]);
793 c->type = le32_to_cpu(buf[2]);
794 if (p->policyvers >= POLICYDB_VERSION_MLS) {
795 if (mls_read_range_helper(&c->range, fp)) {
796 printk(KERN_ERR "security: error reading MLS range of "
797 "context\n");
798 rc = -EINVAL;
799 goto out;
800 }
801 }
802
803 if (!policydb_context_isvalid(p, c)) {
804 printk(KERN_ERR "security: invalid security context\n");
805 context_destroy(c);
806 rc = -EINVAL;
807 }
808out:
809 return rc;
810}
811
812/*
813 * The following *_read functions are used to
814 * read the symbol data from a policy database
815 * binary representation file.
816 */
817
818static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
819{
820 char *key = NULL;
821 struct perm_datum *perdatum;
822 int rc;
823 u32 buf[2], len;
824
825 perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL);
826 if (!perdatum) {
827 rc = -ENOMEM;
828 goto out;
829 }
830 memset(perdatum, 0, sizeof(*perdatum));
831
832 rc = next_entry(buf, fp, sizeof buf);
833 if (rc < 0)
834 goto bad;
835
836 len = le32_to_cpu(buf[0]);
837 perdatum->value = le32_to_cpu(buf[1]);
838
839 key = kmalloc(len + 1,GFP_KERNEL);
840 if (!key) {
841 rc = -ENOMEM;
842 goto bad;
843 }
844 rc = next_entry(key, fp, len);
845 if (rc < 0)
846 goto bad;
847 key[len] = 0;
848
849 rc = hashtab_insert(h, key, perdatum);
850 if (rc)
851 goto bad;
852out:
853 return rc;
854bad:
855 perm_destroy(key, perdatum, NULL);
856 goto out;
857}
858
859static int common_read(struct policydb *p, struct hashtab *h, void *fp)
860{
861 char *key = NULL;
862 struct common_datum *comdatum;
863 u32 buf[4], len, nel;
864 int i, rc;
865
866 comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL);
867 if (!comdatum) {
868 rc = -ENOMEM;
869 goto out;
870 }
871 memset(comdatum, 0, sizeof(*comdatum));
872
873 rc = next_entry(buf, fp, sizeof buf);
874 if (rc < 0)
875 goto bad;
876
877 len = le32_to_cpu(buf[0]);
878 comdatum->value = le32_to_cpu(buf[1]);
879
880 rc = symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE);
881 if (rc)
882 goto bad;
883 comdatum->permissions.nprim = le32_to_cpu(buf[2]);
884 nel = le32_to_cpu(buf[3]);
885
886 key = kmalloc(len + 1,GFP_KERNEL);
887 if (!key) {
888 rc = -ENOMEM;
889 goto bad;
890 }
891 rc = next_entry(key, fp, len);
892 if (rc < 0)
893 goto bad;
894 key[len] = 0;
895
896 for (i = 0; i < nel; i++) {
897 rc = perm_read(p, comdatum->permissions.table, fp);
898 if (rc)
899 goto bad;
900 }
901
902 rc = hashtab_insert(h, key, comdatum);
903 if (rc)
904 goto bad;
905out:
906 return rc;
907bad:
908 common_destroy(key, comdatum, NULL);
909 goto out;
910}
911
912static int read_cons_helper(struct constraint_node **nodep, int ncons,
913 int allowxtarget, void *fp)
914{
915 struct constraint_node *c, *lc;
916 struct constraint_expr *e, *le;
917 u32 buf[3], nexpr;
918 int rc, i, j, depth;
919
920 lc = NULL;
921 for (i = 0; i < ncons; i++) {
922 c = kmalloc(sizeof(*c), GFP_KERNEL);
923 if (!c)
924 return -ENOMEM;
925 memset(c, 0, sizeof(*c));
926
927 if (lc) {
928 lc->next = c;
929 } else {
930 *nodep = c;
931 }
932
933 rc = next_entry(buf, fp, (sizeof(u32) * 2));
934 if (rc < 0)
935 return rc;
936 c->permissions = le32_to_cpu(buf[0]);
937 nexpr = le32_to_cpu(buf[1]);
938 le = NULL;
939 depth = -1;
940 for (j = 0; j < nexpr; j++) {
941 e = kmalloc(sizeof(*e), GFP_KERNEL);
942 if (!e)
943 return -ENOMEM;
944 memset(e, 0, sizeof(*e));
945
946 if (le) {
947 le->next = e;
948 } else {
949 c->expr = e;
950 }
951
952 rc = next_entry(buf, fp, (sizeof(u32) * 3));
953 if (rc < 0)
954 return rc;
955 e->expr_type = le32_to_cpu(buf[0]);
956 e->attr = le32_to_cpu(buf[1]);
957 e->op = le32_to_cpu(buf[2]);
958
959 switch (e->expr_type) {
960 case CEXPR_NOT:
961 if (depth < 0)
962 return -EINVAL;
963 break;
964 case CEXPR_AND:
965 case CEXPR_OR:
966 if (depth < 1)
967 return -EINVAL;
968 depth--;
969 break;
970 case CEXPR_ATTR:
971 if (depth == (CEXPR_MAXDEPTH - 1))
972 return -EINVAL;
973 depth++;
974 break;
975 case CEXPR_NAMES:
976 if (!allowxtarget && (e->attr & CEXPR_XTARGET))
977 return -EINVAL;
978 if (depth == (CEXPR_MAXDEPTH - 1))
979 return -EINVAL;
980 depth++;
981 if (ebitmap_read(&e->names, fp))
982 return -EINVAL;
983 break;
984 default:
985 return -EINVAL;
986 }
987 le = e;
988 }
989 if (depth != 0)
990 return -EINVAL;
991 lc = c;
992 }
993
994 return 0;
995}
996
997static int class_read(struct policydb *p, struct hashtab *h, void *fp)
998{
999 char *key = NULL;
1000 struct class_datum *cladatum;
1001 u32 buf[6], len, len2, ncons, nel;
1002 int i, rc;
1003
1004 cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL);
1005 if (!cladatum) {
1006 rc = -ENOMEM;
1007 goto out;
1008 }
1009 memset(cladatum, 0, sizeof(*cladatum));
1010
1011 rc = next_entry(buf, fp, sizeof(u32)*6);
1012 if (rc < 0)
1013 goto bad;
1014
1015 len = le32_to_cpu(buf[0]);
1016 len2 = le32_to_cpu(buf[1]);
1017 cladatum->value = le32_to_cpu(buf[2]);
1018
1019 rc = symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE);
1020 if (rc)
1021 goto bad;
1022 cladatum->permissions.nprim = le32_to_cpu(buf[3]);
1023 nel = le32_to_cpu(buf[4]);
1024
1025 ncons = le32_to_cpu(buf[5]);
1026
1027 key = kmalloc(len + 1,GFP_KERNEL);
1028 if (!key) {
1029 rc = -ENOMEM;
1030 goto bad;
1031 }
1032 rc = next_entry(key, fp, len);
1033 if (rc < 0)
1034 goto bad;
1035 key[len] = 0;
1036
1037 if (len2) {
1038 cladatum->comkey = kmalloc(len2 + 1,GFP_KERNEL);
1039 if (!cladatum->comkey) {
1040 rc = -ENOMEM;
1041 goto bad;
1042 }
1043 rc = next_entry(cladatum->comkey, fp, len2);
1044 if (rc < 0)
1045 goto bad;
1046 cladatum->comkey[len2] = 0;
1047
1048 cladatum->comdatum = hashtab_search(p->p_commons.table,
1049 cladatum->comkey);
1050 if (!cladatum->comdatum) {
1051 printk(KERN_ERR "security: unknown common %s\n",
1052 cladatum->comkey);
1053 rc = -EINVAL;
1054 goto bad;
1055 }
1056 }
1057 for (i = 0; i < nel; i++) {
1058 rc = perm_read(p, cladatum->permissions.table, fp);
1059 if (rc)
1060 goto bad;
1061 }
1062
1063 rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
1064 if (rc)
1065 goto bad;
1066
1067 if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) {
1068 /* grab the validatetrans rules */
1069 rc = next_entry(buf, fp, sizeof(u32));
1070 if (rc < 0)
1071 goto bad;
1072 ncons = le32_to_cpu(buf[0]);
1073 rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
1074 if (rc)
1075 goto bad;
1076 }
1077
1078 rc = hashtab_insert(h, key, cladatum);
1079 if (rc)
1080 goto bad;
1081
1082 rc = 0;
1083out:
1084 return rc;
1085bad:
1086 class_destroy(key, cladatum, NULL);
1087 goto out;
1088}
1089
1090static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1091{
1092 char *key = NULL;
1093 struct role_datum *role;
1094 int rc;
1095 u32 buf[2], len;
1096
1097 role = kmalloc(sizeof(*role), GFP_KERNEL);
1098 if (!role) {
1099 rc = -ENOMEM;
1100 goto out;
1101 }
1102 memset(role, 0, sizeof(*role));
1103
1104 rc = next_entry(buf, fp, sizeof buf);
1105 if (rc < 0)
1106 goto bad;
1107
1108 len = le32_to_cpu(buf[0]);
1109 role->value = le32_to_cpu(buf[1]);
1110
1111 key = kmalloc(len + 1,GFP_KERNEL);
1112 if (!key) {
1113 rc = -ENOMEM;
1114 goto bad;
1115 }
1116 rc = next_entry(key, fp, len);
1117 if (rc < 0)
1118 goto bad;
1119 key[len] = 0;
1120
1121 rc = ebitmap_read(&role->dominates, fp);
1122 if (rc)
1123 goto bad;
1124
1125 rc = ebitmap_read(&role->types, fp);
1126 if (rc)
1127 goto bad;
1128
1129 if (strcmp(key, OBJECT_R) == 0) {
1130 if (role->value != OBJECT_R_VAL) {
1131 printk(KERN_ERR "Role %s has wrong value %d\n",
1132 OBJECT_R, role->value);
1133 rc = -EINVAL;
1134 goto bad;
1135 }
1136 rc = 0;
1137 goto bad;
1138 }
1139
1140 rc = hashtab_insert(h, key, role);
1141 if (rc)
1142 goto bad;
1143out:
1144 return rc;
1145bad:
1146 role_destroy(key, role, NULL);
1147 goto out;
1148}
1149
1150static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1151{
1152 char *key = NULL;
1153 struct type_datum *typdatum;
1154 int rc;
1155 u32 buf[3], len;
1156
1157 typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL);
1158 if (!typdatum) {
1159 rc = -ENOMEM;
1160 return rc;
1161 }
1162 memset(typdatum, 0, sizeof(*typdatum));
1163
1164 rc = next_entry(buf, fp, sizeof buf);
1165 if (rc < 0)
1166 goto bad;
1167
1168 len = le32_to_cpu(buf[0]);
1169 typdatum->value = le32_to_cpu(buf[1]);
1170 typdatum->primary = le32_to_cpu(buf[2]);
1171
1172 key = kmalloc(len + 1,GFP_KERNEL);
1173 if (!key) {
1174 rc = -ENOMEM;
1175 goto bad;
1176 }
1177 rc = next_entry(key, fp, len);
1178 if (rc < 0)
1179 goto bad;
1180 key[len] = 0;
1181
1182 rc = hashtab_insert(h, key, typdatum);
1183 if (rc)
1184 goto bad;
1185out:
1186 return rc;
1187bad:
1188 type_destroy(key, typdatum, NULL);
1189 goto out;
1190}
1191
1192
1193/*
1194 * Read a MLS level structure from a policydb binary
1195 * representation file.
1196 */
1197static int mls_read_level(struct mls_level *lp, void *fp)
1198{
1199 u32 buf[1];
1200 int rc;
1201
1202 memset(lp, 0, sizeof(*lp));
1203
1204 rc = next_entry(buf, fp, sizeof buf);
1205 if (rc < 0) {
1206 printk(KERN_ERR "security: mls: truncated level\n");
1207 goto bad;
1208 }
1209 lp->sens = le32_to_cpu(buf[0]);
1210
1211 if (ebitmap_read(&lp->cat, fp)) {
1212 printk(KERN_ERR "security: mls: error reading level "
1213 "categories\n");
1214 goto bad;
1215 }
1216 return 0;
1217
1218bad:
1219 return -EINVAL;
1220}
1221
1222static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1223{
1224 char *key = NULL;
1225 struct user_datum *usrdatum;
1226 int rc;
1227 u32 buf[2], len;
1228
1229 usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL);
1230 if (!usrdatum) {
1231 rc = -ENOMEM;
1232 goto out;
1233 }
1234 memset(usrdatum, 0, sizeof(*usrdatum));
1235
1236 rc = next_entry(buf, fp, sizeof buf);
1237 if (rc < 0)
1238 goto bad;
1239
1240 len = le32_to_cpu(buf[0]);
1241 usrdatum->value = le32_to_cpu(buf[1]);
1242
1243 key = kmalloc(len + 1,GFP_KERNEL);
1244 if (!key) {
1245 rc = -ENOMEM;
1246 goto bad;
1247 }
1248 rc = next_entry(key, fp, len);
1249 if (rc < 0)
1250 goto bad;
1251 key[len] = 0;
1252
1253 rc = ebitmap_read(&usrdatum->roles, fp);
1254 if (rc)
1255 goto bad;
1256
1257 if (p->policyvers >= POLICYDB_VERSION_MLS) {
1258 rc = mls_read_range_helper(&usrdatum->range, fp);
1259 if (rc)
1260 goto bad;
1261 rc = mls_read_level(&usrdatum->dfltlevel, fp);
1262 if (rc)
1263 goto bad;
1264 }
1265
1266 rc = hashtab_insert(h, key, usrdatum);
1267 if (rc)
1268 goto bad;
1269out:
1270 return rc;
1271bad:
1272 user_destroy(key, usrdatum, NULL);
1273 goto out;
1274}
1275
1276static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
1277{
1278 char *key = NULL;
1279 struct level_datum *levdatum;
1280 int rc;
1281 u32 buf[2], len;
1282
1283 levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
1284 if (!levdatum) {
1285 rc = -ENOMEM;
1286 goto out;
1287 }
1288 memset(levdatum, 0, sizeof(*levdatum));
1289
1290 rc = next_entry(buf, fp, sizeof buf);
1291 if (rc < 0)
1292 goto bad;
1293
1294 len = le32_to_cpu(buf[0]);
1295 levdatum->isalias = le32_to_cpu(buf[1]);
1296
1297 key = kmalloc(len + 1,GFP_ATOMIC);
1298 if (!key) {
1299 rc = -ENOMEM;
1300 goto bad;
1301 }
1302 rc = next_entry(key, fp, len);
1303 if (rc < 0)
1304 goto bad;
1305 key[len] = 0;
1306
1307 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
1308 if (!levdatum->level) {
1309 rc = -ENOMEM;
1310 goto bad;
1311 }
1312 if (mls_read_level(levdatum->level, fp)) {
1313 rc = -EINVAL;
1314 goto bad;
1315 }
1316
1317 rc = hashtab_insert(h, key, levdatum);
1318 if (rc)
1319 goto bad;
1320out:
1321 return rc;
1322bad:
1323 sens_destroy(key, levdatum, NULL);
1324 goto out;
1325}
1326
1327static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
1328{
1329 char *key = NULL;
1330 struct cat_datum *catdatum;
1331 int rc;
1332 u32 buf[3], len;
1333
1334 catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
1335 if (!catdatum) {
1336 rc = -ENOMEM;
1337 goto out;
1338 }
1339 memset(catdatum, 0, sizeof(*catdatum));
1340
1341 rc = next_entry(buf, fp, sizeof buf);
1342 if (rc < 0)
1343 goto bad;
1344
1345 len = le32_to_cpu(buf[0]);
1346 catdatum->value = le32_to_cpu(buf[1]);
1347 catdatum->isalias = le32_to_cpu(buf[2]);
1348
1349 key = kmalloc(len + 1,GFP_ATOMIC);
1350 if (!key) {
1351 rc = -ENOMEM;
1352 goto bad;
1353 }
1354 rc = next_entry(key, fp, len);
1355 if (rc < 0)
1356 goto bad;
1357 key[len] = 0;
1358
1359 rc = hashtab_insert(h, key, catdatum);
1360 if (rc)
1361 goto bad;
1362out:
1363 return rc;
1364
1365bad:
1366 cat_destroy(key, catdatum, NULL);
1367 goto out;
1368}
1369
1370static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) =
1371{
1372 common_read,
1373 class_read,
1374 role_read,
1375 type_read,
1376 user_read,
1377 cond_read_bool,
1378 sens_read,
1379 cat_read,
1380};
1381
1382extern int ss_initialized;
1383
1384/*
1385 * Read the configuration data from a policy database binary
1386 * representation file into a policy database structure.
1387 */
1388int policydb_read(struct policydb *p, void *fp)
1389{
1390 struct role_allow *ra, *lra;
1391 struct role_trans *tr, *ltr;
1392 struct ocontext *l, *c, *newc;
1393 struct genfs *genfs_p, *genfs, *newgenfs;
1394 int i, j, rc;
1395 u32 buf[8], len, len2, config, nprim, nel, nel2;
1396 char *policydb_str;
1397 struct policydb_compat_info *info;
1398 struct range_trans *rt, *lrt;
1399
1400 config = 0;
1401
1402 rc = policydb_init(p);
1403 if (rc)
1404 goto out;
1405
1406 /* Read the magic number and string length. */
1407 rc = next_entry(buf, fp, sizeof(u32)* 2);
1408 if (rc < 0)
1409 goto bad;
1410
1411 for (i = 0; i < 2; i++)
1412 buf[i] = le32_to_cpu(buf[i]);
1413
1414 if (buf[0] != POLICYDB_MAGIC) {
1415 printk(KERN_ERR "security: policydb magic number 0x%x does "
1416 "not match expected magic number 0x%x\n",
1417 buf[0], POLICYDB_MAGIC);
1418 goto bad;
1419 }
1420
1421 len = buf[1];
1422 if (len != strlen(POLICYDB_STRING)) {
1423 printk(KERN_ERR "security: policydb string length %d does not "
1424 "match expected length %Zu\n",
1425 len, strlen(POLICYDB_STRING));
1426 goto bad;
1427 }
1428 policydb_str = kmalloc(len + 1,GFP_KERNEL);
1429 if (!policydb_str) {
1430 printk(KERN_ERR "security: unable to allocate memory for policydb "
1431 "string of length %d\n", len);
1432 rc = -ENOMEM;
1433 goto bad;
1434 }
1435 rc = next_entry(policydb_str, fp, len);
1436 if (rc < 0) {
1437 printk(KERN_ERR "security: truncated policydb string identifier\n");
1438 kfree(policydb_str);
1439 goto bad;
1440 }
1441 policydb_str[len] = 0;
1442 if (strcmp(policydb_str, POLICYDB_STRING)) {
1443 printk(KERN_ERR "security: policydb string %s does not match "
1444 "my string %s\n", policydb_str, POLICYDB_STRING);
1445 kfree(policydb_str);
1446 goto bad;
1447 }
1448 /* Done with policydb_str. */
1449 kfree(policydb_str);
1450 policydb_str = NULL;
1451
1452 /* Read the version, config, and table sizes. */
1453 rc = next_entry(buf, fp, sizeof(u32)*4);
1454 if (rc < 0)
1455 goto bad;
1456 for (i = 0; i < 4; i++)
1457 buf[i] = le32_to_cpu(buf[i]);
1458
1459 p->policyvers = buf[0];
1460 if (p->policyvers < POLICYDB_VERSION_MIN ||
1461 p->policyvers > POLICYDB_VERSION_MAX) {
1462 printk(KERN_ERR "security: policydb version %d does not match "
1463 "my version range %d-%d\n",
1464 buf[0], POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
1465 goto bad;
1466 }
1467
1468 if ((buf[1] & POLICYDB_CONFIG_MLS)) {
1469 if (ss_initialized && !selinux_mls_enabled) {
1470 printk(KERN_ERR "Cannot switch between non-MLS and MLS "
1471 "policies\n");
1472 goto bad;
1473 }
1474 selinux_mls_enabled = 1;
1475 config |= POLICYDB_CONFIG_MLS;
1476
1477 if (p->policyvers < POLICYDB_VERSION_MLS) {
1478 printk(KERN_ERR "security policydb version %d (MLS) "
1479 "not backwards compatible\n", p->policyvers);
1480 goto bad;
1481 }
1482 } else {
1483 if (ss_initialized && selinux_mls_enabled) {
1484 printk(KERN_ERR "Cannot switch between MLS and non-MLS "
1485 "policies\n");
1486 goto bad;
1487 }
1488 }
1489
1490 info = policydb_lookup_compat(p->policyvers);
1491 if (!info) {
1492 printk(KERN_ERR "security: unable to find policy compat info "
1493 "for version %d\n", p->policyvers);
1494 goto bad;
1495 }
1496
1497 if (buf[2] != info->sym_num || buf[3] != info->ocon_num) {
1498 printk(KERN_ERR "security: policydb table sizes (%d,%d) do "
1499 "not match mine (%d,%d)\n", buf[2], buf[3],
1500 info->sym_num, info->ocon_num);
1501 goto bad;
1502 }
1503
1504 for (i = 0; i < info->sym_num; i++) {
1505 rc = next_entry(buf, fp, sizeof(u32)*2);
1506 if (rc < 0)
1507 goto bad;
1508 nprim = le32_to_cpu(buf[0]);
1509 nel = le32_to_cpu(buf[1]);
1510 for (j = 0; j < nel; j++) {
1511 rc = read_f[i](p, p->symtab[i].table, fp);
1512 if (rc)
1513 goto bad;
1514 }
1515
1516 p->symtab[i].nprim = nprim;
1517 }
1518
1519 rc = avtab_read(&p->te_avtab, fp, config);
1520 if (rc)
1521 goto bad;
1522
1523 if (p->policyvers >= POLICYDB_VERSION_BOOL) {
1524 rc = cond_read_list(p, fp);
1525 if (rc)
1526 goto bad;
1527 }
1528
1529 rc = next_entry(buf, fp, sizeof(u32));
1530 if (rc < 0)
1531 goto bad;
1532 nel = le32_to_cpu(buf[0]);
1533 ltr = NULL;
1534 for (i = 0; i < nel; i++) {
1535 tr = kmalloc(sizeof(*tr), GFP_KERNEL);
1536 if (!tr) {
1537 rc = -ENOMEM;
1538 goto bad;
1539 }
1540 memset(tr, 0, sizeof(*tr));
1541 if (ltr) {
1542 ltr->next = tr;
1543 } else {
1544 p->role_tr = tr;
1545 }
1546 rc = next_entry(buf, fp, sizeof(u32)*3);
1547 if (rc < 0)
1548 goto bad;
1549 tr->role = le32_to_cpu(buf[0]);
1550 tr->type = le32_to_cpu(buf[1]);
1551 tr->new_role = le32_to_cpu(buf[2]);
1552 ltr = tr;
1553 }
1554
1555 rc = next_entry(buf, fp, sizeof(u32));
1556 if (rc < 0)
1557 goto bad;
1558 nel = le32_to_cpu(buf[0]);
1559 lra = NULL;
1560 for (i = 0; i < nel; i++) {
1561 ra = kmalloc(sizeof(*ra), GFP_KERNEL);
1562 if (!ra) {
1563 rc = -ENOMEM;
1564 goto bad;
1565 }
1566 memset(ra, 0, sizeof(*ra));
1567 if (lra) {
1568 lra->next = ra;
1569 } else {
1570 p->role_allow = ra;
1571 }
1572 rc = next_entry(buf, fp, sizeof(u32)*2);
1573 if (rc < 0)
1574 goto bad;
1575 ra->role = le32_to_cpu(buf[0]);
1576 ra->new_role = le32_to_cpu(buf[1]);
1577 lra = ra;
1578 }
1579
1580 rc = policydb_index_classes(p);
1581 if (rc)
1582 goto bad;
1583
1584 rc = policydb_index_others(p);
1585 if (rc)
1586 goto bad;
1587
1588 for (i = 0; i < info->ocon_num; i++) {
1589 rc = next_entry(buf, fp, sizeof(u32));
1590 if (rc < 0)
1591 goto bad;
1592 nel = le32_to_cpu(buf[0]);
1593 l = NULL;
1594 for (j = 0; j < nel; j++) {
1595 c = kmalloc(sizeof(*c), GFP_KERNEL);
1596 if (!c) {
1597 rc = -ENOMEM;
1598 goto bad;
1599 }
1600 memset(c, 0, sizeof(*c));
1601 if (l) {
1602 l->next = c;
1603 } else {
1604 p->ocontexts[i] = c;
1605 }
1606 l = c;
1607 rc = -EINVAL;
1608 switch (i) {
1609 case OCON_ISID:
1610 rc = next_entry(buf, fp, sizeof(u32));
1611 if (rc < 0)
1612 goto bad;
1613 c->sid[0] = le32_to_cpu(buf[0]);
1614 rc = context_read_and_validate(&c->context[0], p, fp);
1615 if (rc)
1616 goto bad;
1617 break;
1618 case OCON_FS:
1619 case OCON_NETIF:
1620 rc = next_entry(buf, fp, sizeof(u32));
1621 if (rc < 0)
1622 goto bad;
1623 len = le32_to_cpu(buf[0]);
1624 c->u.name = kmalloc(len + 1,GFP_KERNEL);
1625 if (!c->u.name) {
1626 rc = -ENOMEM;
1627 goto bad;
1628 }
1629 rc = next_entry(c->u.name, fp, len);
1630 if (rc < 0)
1631 goto bad;
1632 c->u.name[len] = 0;
1633 rc = context_read_and_validate(&c->context[0], p, fp);
1634 if (rc)
1635 goto bad;
1636 rc = context_read_and_validate(&c->context[1], p, fp);
1637 if (rc)
1638 goto bad;
1639 break;
1640 case OCON_PORT:
1641 rc = next_entry(buf, fp, sizeof(u32)*3);
1642 if (rc < 0)
1643 goto bad;
1644 c->u.port.protocol = le32_to_cpu(buf[0]);
1645 c->u.port.low_port = le32_to_cpu(buf[1]);
1646 c->u.port.high_port = le32_to_cpu(buf[2]);
1647 rc = context_read_and_validate(&c->context[0], p, fp);
1648 if (rc)
1649 goto bad;
1650 break;
1651 case OCON_NODE:
1652 rc = next_entry(buf, fp, sizeof(u32)* 2);
1653 if (rc < 0)
1654 goto bad;
1655 c->u.node.addr = le32_to_cpu(buf[0]);
1656 c->u.node.mask = le32_to_cpu(buf[1]);
1657 rc = context_read_and_validate(&c->context[0], p, fp);
1658 if (rc)
1659 goto bad;
1660 break;
1661 case OCON_FSUSE:
1662 rc = next_entry(buf, fp, sizeof(u32)*2);
1663 if (rc < 0)
1664 goto bad;
1665 c->v.behavior = le32_to_cpu(buf[0]);
1666 if (c->v.behavior > SECURITY_FS_USE_NONE)
1667 goto bad;
1668 len = le32_to_cpu(buf[1]);
1669 c->u.name = kmalloc(len + 1,GFP_KERNEL);
1670 if (!c->u.name) {
1671 rc = -ENOMEM;
1672 goto bad;
1673 }
1674 rc = next_entry(c->u.name, fp, len);
1675 if (rc < 0)
1676 goto bad;
1677 c->u.name[len] = 0;
1678 rc = context_read_and_validate(&c->context[0], p, fp);
1679 if (rc)
1680 goto bad;
1681 break;
1682 case OCON_NODE6: {
1683 int k;
1684
1685 rc = next_entry(buf, fp, sizeof(u32) * 8);
1686 if (rc < 0)
1687 goto bad;
1688 for (k = 0; k < 4; k++)
1689 c->u.node6.addr[k] = le32_to_cpu(buf[k]);
1690 for (k = 0; k < 4; k++)
1691 c->u.node6.mask[k] = le32_to_cpu(buf[k+4]);
1692 if (context_read_and_validate(&c->context[0], p, fp))
1693 goto bad;
1694 break;
1695 }
1696 }
1697 }
1698 }
1699
1700 rc = next_entry(buf, fp, sizeof(u32));
1701 if (rc < 0)
1702 goto bad;
1703 nel = le32_to_cpu(buf[0]);
1704 genfs_p = NULL;
1705 rc = -EINVAL;
1706 for (i = 0; i < nel; i++) {
1707 rc = next_entry(buf, fp, sizeof(u32));
1708 if (rc < 0)
1709 goto bad;
1710 len = le32_to_cpu(buf[0]);
1711 newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL);
1712 if (!newgenfs) {
1713 rc = -ENOMEM;
1714 goto bad;
1715 }
1716 memset(newgenfs, 0, sizeof(*newgenfs));
1717
1718 newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL);
1719 if (!newgenfs->fstype) {
1720 rc = -ENOMEM;
1721 kfree(newgenfs);
1722 goto bad;
1723 }
1724 rc = next_entry(newgenfs->fstype, fp, len);
1725 if (rc < 0) {
1726 kfree(newgenfs->fstype);
1727 kfree(newgenfs);
1728 goto bad;
1729 }
1730 newgenfs->fstype[len] = 0;
1731 for (genfs_p = NULL, genfs = p->genfs; genfs;
1732 genfs_p = genfs, genfs = genfs->next) {
1733 if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
1734 printk(KERN_ERR "security: dup genfs "
1735 "fstype %s\n", newgenfs->fstype);
1736 kfree(newgenfs->fstype);
1737 kfree(newgenfs);
1738 goto bad;
1739 }
1740 if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
1741 break;
1742 }
1743 newgenfs->next = genfs;
1744 if (genfs_p)
1745 genfs_p->next = newgenfs;
1746 else
1747 p->genfs = newgenfs;
1748 rc = next_entry(buf, fp, sizeof(u32));
1749 if (rc < 0)
1750 goto bad;
1751 nel2 = le32_to_cpu(buf[0]);
1752 for (j = 0; j < nel2; j++) {
1753 rc = next_entry(buf, fp, sizeof(u32));
1754 if (rc < 0)
1755 goto bad;
1756 len = le32_to_cpu(buf[0]);
1757
1758 newc = kmalloc(sizeof(*newc), GFP_KERNEL);
1759 if (!newc) {
1760 rc = -ENOMEM;
1761 goto bad;
1762 }
1763 memset(newc, 0, sizeof(*newc));
1764
1765 newc->u.name = kmalloc(len + 1,GFP_KERNEL);
1766 if (!newc->u.name) {
1767 rc = -ENOMEM;
1768 goto bad_newc;
1769 }
1770 rc = next_entry(newc->u.name, fp, len);
1771 if (rc < 0)
1772 goto bad_newc;
1773 newc->u.name[len] = 0;
1774 rc = next_entry(buf, fp, sizeof(u32));
1775 if (rc < 0)
1776 goto bad_newc;
1777 newc->v.sclass = le32_to_cpu(buf[0]);
1778 if (context_read_and_validate(&newc->context[0], p, fp))
1779 goto bad_newc;
1780 for (l = NULL, c = newgenfs->head; c;
1781 l = c, c = c->next) {
1782 if (!strcmp(newc->u.name, c->u.name) &&
1783 (!c->v.sclass || !newc->v.sclass ||
1784 newc->v.sclass == c->v.sclass)) {
1785 printk(KERN_ERR "security: dup genfs "
1786 "entry (%s,%s)\n",
1787 newgenfs->fstype, c->u.name);
1788 goto bad_newc;
1789 }
1790 len = strlen(newc->u.name);
1791 len2 = strlen(c->u.name);
1792 if (len > len2)
1793 break;
1794 }
1795
1796 newc->next = c;
1797 if (l)
1798 l->next = newc;
1799 else
1800 newgenfs->head = newc;
1801 }
1802 }
1803
1804 if (p->policyvers >= POLICYDB_VERSION_MLS) {
1805 rc = next_entry(buf, fp, sizeof(u32));
1806 if (rc < 0)
1807 goto bad;
1808 nel = le32_to_cpu(buf[0]);
1809 lrt = NULL;
1810 for (i = 0; i < nel; i++) {
1811 rt = kmalloc(sizeof(*rt), GFP_KERNEL);
1812 if (!rt) {
1813 rc = -ENOMEM;
1814 goto bad;
1815 }
1816 memset(rt, 0, sizeof(*rt));
1817 if (lrt)
1818 lrt->next = rt;
1819 else
1820 p->range_tr = rt;
1821 rc = next_entry(buf, fp, (sizeof(u32) * 2));
1822 if (rc < 0)
1823 goto bad;
1824 rt->dom = le32_to_cpu(buf[0]);
1825 rt->type = le32_to_cpu(buf[1]);
1826 rc = mls_read_range_helper(&rt->range, fp);
1827 if (rc)
1828 goto bad;
1829 lrt = rt;
1830 }
1831 }
1832
1833 rc = 0;
1834out:
1835 return rc;
1836bad_newc:
1837 ocontext_destroy(newc,OCON_FSUSE);
1838bad:
1839 if (!rc)
1840 rc = -EINVAL;
1841 policydb_destroy(p);
1842 goto out;
1843}
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
new file mode 100644
index 00000000000..2470e2a1a1c
--- /dev/null
+++ b/security/selinux/ss/policydb.h
@@ -0,0 +1,275 @@
1/*
2 * A policy database (policydb) specifies the
3 * configuration data for the security policy.
4 *
5 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
6 */
7
8/*
9 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
10 *
11 * Support for enhanced MLS infrastructure.
12 *
13 * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
14 *
15 * Added conditional policy language extensions
16 *
17 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
18 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation, version 2.
22 */
23
24#ifndef _SS_POLICYDB_H_
25#define _SS_POLICYDB_H_
26
27#include "symtab.h"
28#include "avtab.h"
29#include "sidtab.h"
30#include "context.h"
31#include "constraint.h"
32
33/*
34 * A datum type is defined for each kind of symbol
35 * in the configuration data: individual permissions,
36 * common prefixes for access vectors, classes,
37 * users, roles, types, sensitivities, categories, etc.
38 */
39
40/* Permission attributes */
41struct perm_datum {
42 u32 value; /* permission bit + 1 */
43};
44
45/* Attributes of a common prefix for access vectors */
46struct common_datum {
47 u32 value; /* internal common value */
48 struct symtab permissions; /* common permissions */
49};
50
51/* Class attributes */
52struct class_datum {
53 u32 value; /* class value */
54 char *comkey; /* common name */
55 struct common_datum *comdatum; /* common datum */
56 struct symtab permissions; /* class-specific permission symbol table */
57 struct constraint_node *constraints; /* constraints on class permissions */
58 struct constraint_node *validatetrans; /* special transition rules */
59};
60
61/* Role attributes */
62struct role_datum {
63 u32 value; /* internal role value */
64 struct ebitmap dominates; /* set of roles dominated by this role */
65 struct ebitmap types; /* set of authorized types for role */
66};
67
68struct role_trans {
69 u32 role; /* current role */
70 u32 type; /* program executable type */
71 u32 new_role; /* new role */
72 struct role_trans *next;
73};
74
75struct role_allow {
76 u32 role; /* current role */
77 u32 new_role; /* new role */
78 struct role_allow *next;
79};
80
81/* Type attributes */
82struct type_datum {
83 u32 value; /* internal type value */
84 unsigned char primary; /* primary name? */
85};
86
87/* User attributes */
88struct user_datum {
89 u32 value; /* internal user value */
90 struct ebitmap roles; /* set of authorized roles for user */
91 struct mls_range range; /* MLS range (min - max) for user */
92 struct mls_level dfltlevel; /* default login MLS level for user */
93};
94
95
96/* Sensitivity attributes */
97struct level_datum {
98 struct mls_level *level; /* sensitivity and associated categories */
99 unsigned char isalias; /* is this sensitivity an alias for another? */
100};
101
102/* Category attributes */
103struct cat_datum {
104 u32 value; /* internal category bit + 1 */
105 unsigned char isalias; /* is this category an alias for another? */
106};
107
108struct range_trans {
109 u32 dom; /* current process domain */
110 u32 type; /* program executable type */
111 struct mls_range range; /* new range */
112 struct range_trans *next;
113};
114
115/* Boolean data type */
116struct cond_bool_datum {
117 __u32 value; /* internal type value */
118 int state;
119};
120
121struct cond_node;
122
123/*
124 * The configuration data includes security contexts for
125 * initial SIDs, unlabeled file systems, TCP and UDP port numbers,
126 * network interfaces, and nodes. This structure stores the
127 * relevant data for one such entry. Entries of the same kind
128 * (e.g. all initial SIDs) are linked together into a list.
129 */
130struct ocontext {
131 union {
132 char *name; /* name of initial SID, fs, netif, fstype, path */
133 struct {
134 u8 protocol;
135 u16 low_port;
136 u16 high_port;
137 } port; /* TCP or UDP port information */
138 struct {
139 u32 addr;
140 u32 mask;
141 } node; /* node information */
142 struct {
143 u32 addr[4];
144 u32 mask[4];
145 } node6; /* IPv6 node information */
146 } u;
147 union {
148 u32 sclass; /* security class for genfs */
149 u32 behavior; /* labeling behavior for fs_use */
150 } v;
151 struct context context[2]; /* security context(s) */
152 u32 sid[2]; /* SID(s) */
153 struct ocontext *next;
154};
155
156struct genfs {
157 char *fstype;
158 struct ocontext *head;
159 struct genfs *next;
160};
161
162/* symbol table array indices */
163#define SYM_COMMONS 0
164#define SYM_CLASSES 1
165#define SYM_ROLES 2
166#define SYM_TYPES 3
167#define SYM_USERS 4
168#define SYM_BOOLS 5
169#define SYM_LEVELS 6
170#define SYM_CATS 7
171#define SYM_NUM 8
172
173/* object context array indices */
174#define OCON_ISID 0 /* initial SIDs */
175#define OCON_FS 1 /* unlabeled file systems */
176#define OCON_PORT 2 /* TCP and UDP port numbers */
177#define OCON_NETIF 3 /* network interfaces */
178#define OCON_NODE 4 /* nodes */
179#define OCON_FSUSE 5 /* fs_use */
180#define OCON_NODE6 6 /* IPv6 nodes */
181#define OCON_NUM 7
182
183/* The policy database */
184struct policydb {
185 /* symbol tables */
186 struct symtab symtab[SYM_NUM];
187#define p_commons symtab[SYM_COMMONS]
188#define p_classes symtab[SYM_CLASSES]
189#define p_roles symtab[SYM_ROLES]
190#define p_types symtab[SYM_TYPES]
191#define p_users symtab[SYM_USERS]
192#define p_bools symtab[SYM_BOOLS]
193#define p_levels symtab[SYM_LEVELS]
194#define p_cats symtab[SYM_CATS]
195
196 /* symbol names indexed by (value - 1) */
197 char **sym_val_to_name[SYM_NUM];
198#define p_common_val_to_name sym_val_to_name[SYM_COMMONS]
199#define p_class_val_to_name sym_val_to_name[SYM_CLASSES]
200#define p_role_val_to_name sym_val_to_name[SYM_ROLES]
201#define p_type_val_to_name sym_val_to_name[SYM_TYPES]
202#define p_user_val_to_name sym_val_to_name[SYM_USERS]
203#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
204#define p_sens_val_to_name sym_val_to_name[SYM_LEVELS]
205#define p_cat_val_to_name sym_val_to_name[SYM_CATS]
206
207 /* class, role, and user attributes indexed by (value - 1) */
208 struct class_datum **class_val_to_struct;
209 struct role_datum **role_val_to_struct;
210 struct user_datum **user_val_to_struct;
211
212 /* type enforcement access vectors and transitions */
213 struct avtab te_avtab;
214
215 /* role transitions */
216 struct role_trans *role_tr;
217
218 /* bools indexed by (value - 1) */
219 struct cond_bool_datum **bool_val_to_struct;
220 /* type enforcement conditional access vectors and transitions */
221 struct avtab te_cond_avtab;
222 /* linked list indexing te_cond_avtab by conditional */
223 struct cond_node* cond_list;
224
225 /* role allows */
226 struct role_allow *role_allow;
227
228 /* security contexts of initial SIDs, unlabeled file systems,
229 TCP or UDP port numbers, network interfaces and nodes */
230 struct ocontext *ocontexts[OCON_NUM];
231
232 /* security contexts for files in filesystems that cannot support
233 a persistent label mapping or use another
234 fixed labeling behavior. */
235 struct genfs *genfs;
236
237 /* range transitions */
238 struct range_trans *range_tr;
239
240 unsigned int policyvers;
241};
242
243extern void policydb_destroy(struct policydb *p);
244extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
245extern int policydb_context_isvalid(struct policydb *p, struct context *c);
246extern int policydb_read(struct policydb *p, void *fp);
247
248#define PERM_SYMTAB_SIZE 32
249
250#define POLICYDB_CONFIG_MLS 1
251
252#define OBJECT_R "object_r"
253#define OBJECT_R_VAL 1
254
255#define POLICYDB_MAGIC SELINUX_MAGIC
256#define POLICYDB_STRING "SE Linux"
257
258struct policy_file {
259 char *data;
260 size_t len;
261};
262
263static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
264{
265 if (bytes > fp->len)
266 return -EINVAL;
267
268 memcpy(buf, fp->data, bytes);
269 fp->data += bytes;
270 fp->len -= bytes;
271 return 0;
272}
273
274#endif /* _SS_POLICYDB_H_ */
275
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
new file mode 100644
index 00000000000..5a820cf88c9
--- /dev/null
+++ b/security/selinux/ss/services.c
@@ -0,0 +1,1777 @@
1/*
2 * Implementation of the security services.
3 *
4 * Authors : Stephen Smalley, <sds@epoch.ncsc.mil>
5 * James Morris <jmorris@redhat.com>
6 *
7 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
8 *
9 * Support for enhanced MLS infrastructure.
10 *
11 * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
12 *
13 * Added conditional policy language extensions
14 *
15 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
16 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
17 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation, version 2.
21 */
22#include <linux/kernel.h>
23#include <linux/slab.h>
24#include <linux/string.h>
25#include <linux/spinlock.h>
26#include <linux/errno.h>
27#include <linux/in.h>
28#include <linux/sched.h>
29#include <linux/audit.h>
30#include <asm/semaphore.h>
31#include "flask.h"
32#include "avc.h"
33#include "avc_ss.h"
34#include "security.h"
35#include "context.h"
36#include "policydb.h"
37#include "sidtab.h"
38#include "services.h"
39#include "conditional.h"
40#include "mls.h"
41
42extern void selnl_notify_policyload(u32 seqno);
43unsigned int policydb_loaded_version;
44
45static DEFINE_RWLOCK(policy_rwlock);
46#define POLICY_RDLOCK read_lock(&policy_rwlock)
47#define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
48#define POLICY_RDUNLOCK read_unlock(&policy_rwlock)
49#define POLICY_WRUNLOCK write_unlock_irq(&policy_rwlock)
50
51static DECLARE_MUTEX(load_sem);
52#define LOAD_LOCK down(&load_sem)
53#define LOAD_UNLOCK up(&load_sem)
54
55static struct sidtab sidtab;
56struct policydb policydb;
57int ss_initialized = 0;
58
59/*
60 * The largest sequence number that has been used when
61 * providing an access decision to the access vector cache.
62 * The sequence number only changes when a policy change
63 * occurs.
64 */
65static u32 latest_granting = 0;
66
67/* Forward declaration. */
68static int context_struct_to_string(struct context *context, char **scontext,
69 u32 *scontext_len);
70
71/*
72 * Return the boolean value of a constraint expression
73 * when it is applied to the specified source and target
74 * security contexts.
75 *
76 * xcontext is a special beast... It is used by the validatetrans rules
77 * only. For these rules, scontext is the context before the transition,
78 * tcontext is the context after the transition, and xcontext is the context
79 * of the process performing the transition. All other callers of
80 * constraint_expr_eval should pass in NULL for xcontext.
81 */
82static int constraint_expr_eval(struct context *scontext,
83 struct context *tcontext,
84 struct context *xcontext,
85 struct constraint_expr *cexpr)
86{
87 u32 val1, val2;
88 struct context *c;
89 struct role_datum *r1, *r2;
90 struct mls_level *l1, *l2;
91 struct constraint_expr *e;
92 int s[CEXPR_MAXDEPTH];
93 int sp = -1;
94
95 for (e = cexpr; e; e = e->next) {
96 switch (e->expr_type) {
97 case CEXPR_NOT:
98 BUG_ON(sp < 0);
99 s[sp] = !s[sp];
100 break;
101 case CEXPR_AND:
102 BUG_ON(sp < 1);
103 sp--;
104 s[sp] &= s[sp+1];
105 break;
106 case CEXPR_OR:
107 BUG_ON(sp < 1);
108 sp--;
109 s[sp] |= s[sp+1];
110 break;
111 case CEXPR_ATTR:
112 if (sp == (CEXPR_MAXDEPTH-1))
113 return 0;
114 switch (e->attr) {
115 case CEXPR_USER:
116 val1 = scontext->user;
117 val2 = tcontext->user;
118 break;
119 case CEXPR_TYPE:
120 val1 = scontext->type;
121 val2 = tcontext->type;
122 break;
123 case CEXPR_ROLE:
124 val1 = scontext->role;
125 val2 = tcontext->role;
126 r1 = policydb.role_val_to_struct[val1 - 1];
127 r2 = policydb.role_val_to_struct[val2 - 1];
128 switch (e->op) {
129 case CEXPR_DOM:
130 s[++sp] = ebitmap_get_bit(&r1->dominates,
131 val2 - 1);
132 continue;
133 case CEXPR_DOMBY:
134 s[++sp] = ebitmap_get_bit(&r2->dominates,
135 val1 - 1);
136 continue;
137 case CEXPR_INCOMP:
138 s[++sp] = ( !ebitmap_get_bit(&r1->dominates,
139 val2 - 1) &&
140 !ebitmap_get_bit(&r2->dominates,
141 val1 - 1) );
142 continue;
143 default:
144 break;
145 }
146 break;
147 case CEXPR_L1L2:
148 l1 = &(scontext->range.level[0]);
149 l2 = &(tcontext->range.level[0]);
150 goto mls_ops;
151 case CEXPR_L1H2:
152 l1 = &(scontext->range.level[0]);
153 l2 = &(tcontext->range.level[1]);
154 goto mls_ops;
155 case CEXPR_H1L2:
156 l1 = &(scontext->range.level[1]);
157 l2 = &(tcontext->range.level[0]);
158 goto mls_ops;
159 case CEXPR_H1H2:
160 l1 = &(scontext->range.level[1]);
161 l2 = &(tcontext->range.level[1]);
162 goto mls_ops;
163 case CEXPR_L1H1:
164 l1 = &(scontext->range.level[0]);
165 l2 = &(scontext->range.level[1]);
166 goto mls_ops;
167 case CEXPR_L2H2:
168 l1 = &(tcontext->range.level[0]);
169 l2 = &(tcontext->range.level[1]);
170 goto mls_ops;
171mls_ops:
172 switch (e->op) {
173 case CEXPR_EQ:
174 s[++sp] = mls_level_eq(l1, l2);
175 continue;
176 case CEXPR_NEQ:
177 s[++sp] = !mls_level_eq(l1, l2);
178 continue;
179 case CEXPR_DOM:
180 s[++sp] = mls_level_dom(l1, l2);
181 continue;
182 case CEXPR_DOMBY:
183 s[++sp] = mls_level_dom(l2, l1);
184 continue;
185 case CEXPR_INCOMP:
186 s[++sp] = mls_level_incomp(l2, l1);
187 continue;
188 default:
189 BUG();
190 return 0;
191 }
192 break;
193 default:
194 BUG();
195 return 0;
196 }
197
198 switch (e->op) {
199 case CEXPR_EQ:
200 s[++sp] = (val1 == val2);
201 break;
202 case CEXPR_NEQ:
203 s[++sp] = (val1 != val2);
204 break;
205 default:
206 BUG();
207 return 0;
208 }
209 break;
210 case CEXPR_NAMES:
211 if (sp == (CEXPR_MAXDEPTH-1))
212 return 0;
213 c = scontext;
214 if (e->attr & CEXPR_TARGET)
215 c = tcontext;
216 else if (e->attr & CEXPR_XTARGET) {
217 c = xcontext;
218 if (!c) {
219 BUG();
220 return 0;
221 }
222 }
223 if (e->attr & CEXPR_USER)
224 val1 = c->user;
225 else if (e->attr & CEXPR_ROLE)
226 val1 = c->role;
227 else if (e->attr & CEXPR_TYPE)
228 val1 = c->type;
229 else {
230 BUG();
231 return 0;
232 }
233
234 switch (e->op) {
235 case CEXPR_EQ:
236 s[++sp] = ebitmap_get_bit(&e->names, val1 - 1);
237 break;
238 case CEXPR_NEQ:
239 s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1);
240 break;
241 default:
242 BUG();
243 return 0;
244 }
245 break;
246 default:
247 BUG();
248 return 0;
249 }
250 }
251
252 BUG_ON(sp != 0);
253 return s[0];
254}
255
256/*
257 * Compute access vectors based on a context structure pair for
258 * the permissions in a particular class.
259 */
260static int context_struct_compute_av(struct context *scontext,
261 struct context *tcontext,
262 u16 tclass,
263 u32 requested,
264 struct av_decision *avd)
265{
266 struct constraint_node *constraint;
267 struct role_allow *ra;
268 struct avtab_key avkey;
269 struct avtab_datum *avdatum;
270 struct class_datum *tclass_datum;
271
272 /*
273 * Remap extended Netlink classes for old policy versions.
274 * Do this here rather than socket_type_to_security_class()
275 * in case a newer policy version is loaded, allowing sockets
276 * to remain in the correct class.
277 */
278 if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS)
279 if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET &&
280 tclass <= SECCLASS_NETLINK_DNRT_SOCKET)
281 tclass = SECCLASS_NETLINK_SOCKET;
282
283 if (!tclass || tclass > policydb.p_classes.nprim) {
284 printk(KERN_ERR "security_compute_av: unrecognized class %d\n",
285 tclass);
286 return -EINVAL;
287 }
288 tclass_datum = policydb.class_val_to_struct[tclass - 1];
289
290 /*
291 * Initialize the access vectors to the default values.
292 */
293 avd->allowed = 0;
294 avd->decided = 0xffffffff;
295 avd->auditallow = 0;
296 avd->auditdeny = 0xffffffff;
297 avd->seqno = latest_granting;
298
299 /*
300 * If a specific type enforcement rule was defined for
301 * this permission check, then use it.
302 */
303 avkey.source_type = scontext->type;
304 avkey.target_type = tcontext->type;
305 avkey.target_class = tclass;
306 avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV);
307 if (avdatum) {
308 if (avdatum->specified & AVTAB_ALLOWED)
309 avd->allowed = avtab_allowed(avdatum);
310 if (avdatum->specified & AVTAB_AUDITDENY)
311 avd->auditdeny = avtab_auditdeny(avdatum);
312 if (avdatum->specified & AVTAB_AUDITALLOW)
313 avd->auditallow = avtab_auditallow(avdatum);
314 }
315
316 /* Check conditional av table for additional permissions */
317 cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
318
319 /*
320 * Remove any permissions prohibited by a constraint (this includes
321 * the MLS policy).
322 */
323 constraint = tclass_datum->constraints;
324 while (constraint) {
325 if ((constraint->permissions & (avd->allowed)) &&
326 !constraint_expr_eval(scontext, tcontext, NULL,
327 constraint->expr)) {
328 avd->allowed = (avd->allowed) & ~(constraint->permissions);
329 }
330 constraint = constraint->next;
331 }
332
333 /*
334 * If checking process transition permission and the
335 * role is changing, then check the (current_role, new_role)
336 * pair.
337 */
338 if (tclass == SECCLASS_PROCESS &&
339 (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) &&
340 scontext->role != tcontext->role) {
341 for (ra = policydb.role_allow; ra; ra = ra->next) {
342 if (scontext->role == ra->role &&
343 tcontext->role == ra->new_role)
344 break;
345 }
346 if (!ra)
347 avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION |
348 PROCESS__DYNTRANSITION);
349 }
350
351 return 0;
352}
353
354static int security_validtrans_handle_fail(struct context *ocontext,
355 struct context *ncontext,
356 struct context *tcontext,
357 u16 tclass)
358{
359 char *o = NULL, *n = NULL, *t = NULL;
360 u32 olen, nlen, tlen;
361
362 if (context_struct_to_string(ocontext, &o, &olen) < 0)
363 goto out;
364 if (context_struct_to_string(ncontext, &n, &nlen) < 0)
365 goto out;
366 if (context_struct_to_string(tcontext, &t, &tlen) < 0)
367 goto out;
368 audit_log(current->audit_context,
369 "security_validate_transition: denied for"
370 " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
371 o, n, t, policydb.p_class_val_to_name[tclass-1]);
372out:
373 kfree(o);
374 kfree(n);
375 kfree(t);
376
377 if (!selinux_enforcing)
378 return 0;
379 return -EPERM;
380}
381
382int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
383 u16 tclass)
384{
385 struct context *ocontext;
386 struct context *ncontext;
387 struct context *tcontext;
388 struct class_datum *tclass_datum;
389 struct constraint_node *constraint;
390 int rc = 0;
391
392 if (!ss_initialized)
393 return 0;
394
395 POLICY_RDLOCK;
396
397 /*
398 * Remap extended Netlink classes for old policy versions.
399 * Do this here rather than socket_type_to_security_class()
400 * in case a newer policy version is loaded, allowing sockets
401 * to remain in the correct class.
402 */
403 if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS)
404 if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET &&
405 tclass <= SECCLASS_NETLINK_DNRT_SOCKET)
406 tclass = SECCLASS_NETLINK_SOCKET;
407
408 if (!tclass || tclass > policydb.p_classes.nprim) {
409 printk(KERN_ERR "security_validate_transition: "
410 "unrecognized class %d\n", tclass);
411 rc = -EINVAL;
412 goto out;
413 }
414 tclass_datum = policydb.class_val_to_struct[tclass - 1];
415
416 ocontext = sidtab_search(&sidtab, oldsid);
417 if (!ocontext) {
418 printk(KERN_ERR "security_validate_transition: "
419 " unrecognized SID %d\n", oldsid);
420 rc = -EINVAL;
421 goto out;
422 }
423
424 ncontext = sidtab_search(&sidtab, newsid);
425 if (!ncontext) {
426 printk(KERN_ERR "security_validate_transition: "
427 " unrecognized SID %d\n", newsid);
428 rc = -EINVAL;
429 goto out;
430 }
431
432 tcontext = sidtab_search(&sidtab, tasksid);
433 if (!tcontext) {
434 printk(KERN_ERR "security_validate_transition: "
435 " unrecognized SID %d\n", tasksid);
436 rc = -EINVAL;
437 goto out;
438 }
439
440 constraint = tclass_datum->validatetrans;
441 while (constraint) {
442 if (!constraint_expr_eval(ocontext, ncontext, tcontext,
443 constraint->expr)) {
444 rc = security_validtrans_handle_fail(ocontext, ncontext,
445 tcontext, tclass);
446 goto out;
447 }
448 constraint = constraint->next;
449 }
450
451out:
452 POLICY_RDUNLOCK;
453 return rc;
454}
455
456/**
457 * security_compute_av - Compute access vector decisions.
458 * @ssid: source security identifier
459 * @tsid: target security identifier
460 * @tclass: target security class
461 * @requested: requested permissions
462 * @avd: access vector decisions
463 *
464 * Compute a set of access vector decisions based on the
465 * SID pair (@ssid, @tsid) for the permissions in @tclass.
466 * Return -%EINVAL if any of the parameters are invalid or %0
467 * if the access vector decisions were computed successfully.
468 */
469int security_compute_av(u32 ssid,
470 u32 tsid,
471 u16 tclass,
472 u32 requested,
473 struct av_decision *avd)
474{
475 struct context *scontext = NULL, *tcontext = NULL;
476 int rc = 0;
477
478 if (!ss_initialized) {
479 avd->allowed = requested;
480 avd->decided = requested;
481 avd->auditallow = 0;
482 avd->auditdeny = 0xffffffff;
483 avd->seqno = latest_granting;
484 return 0;
485 }
486
487 POLICY_RDLOCK;
488
489 scontext = sidtab_search(&sidtab, ssid);
490 if (!scontext) {
491 printk(KERN_ERR "security_compute_av: unrecognized SID %d\n",
492 ssid);
493 rc = -EINVAL;
494 goto out;
495 }
496 tcontext = sidtab_search(&sidtab, tsid);
497 if (!tcontext) {
498 printk(KERN_ERR "security_compute_av: unrecognized SID %d\n",
499 tsid);
500 rc = -EINVAL;
501 goto out;
502 }
503
504 rc = context_struct_compute_av(scontext, tcontext, tclass,
505 requested, avd);
506out:
507 POLICY_RDUNLOCK;
508 return rc;
509}
510
511/*
512 * Write the security context string representation of
513 * the context structure `context' into a dynamically
514 * allocated string of the correct size. Set `*scontext'
515 * to point to this string and set `*scontext_len' to
516 * the length of the string.
517 */
518static int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len)
519{
520 char *scontextp;
521
522 *scontext = NULL;
523 *scontext_len = 0;
524
525 /* Compute the size of the context. */
526 *scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1;
527 *scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1;
528 *scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
529 *scontext_len += mls_compute_context_len(context);
530
531 /* Allocate space for the context; caller must free this space. */
532 scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
533 if (!scontextp) {
534 return -ENOMEM;
535 }
536 *scontext = scontextp;
537
538 /*
539 * Copy the user name, role name and type name into the context.
540 */
541 sprintf(scontextp, "%s:%s:%s",
542 policydb.p_user_val_to_name[context->user - 1],
543 policydb.p_role_val_to_name[context->role - 1],
544 policydb.p_type_val_to_name[context->type - 1]);
545 scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
546 1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
547 1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
548
549 mls_sid_to_context(context, &scontextp);
550
551 *scontextp = 0;
552
553 return 0;
554}
555
556#include "initial_sid_to_string.h"
557
558/**
559 * security_sid_to_context - Obtain a context for a given SID.
560 * @sid: security identifier, SID
561 * @scontext: security context
562 * @scontext_len: length in bytes
563 *
564 * Write the string representation of the context associated with @sid
565 * into a dynamically allocated string of the correct size. Set @scontext
566 * to point to this string and set @scontext_len to the length of the string.
567 */
568int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
569{
570 struct context *context;
571 int rc = 0;
572
573 if (!ss_initialized) {
574 if (sid <= SECINITSID_NUM) {
575 char *scontextp;
576
577 *scontext_len = strlen(initial_sid_to_string[sid]) + 1;
578 scontextp = kmalloc(*scontext_len,GFP_ATOMIC);
579 strcpy(scontextp, initial_sid_to_string[sid]);
580 *scontext = scontextp;
581 goto out;
582 }
583 printk(KERN_ERR "security_sid_to_context: called before initial "
584 "load_policy on unknown SID %d\n", sid);
585 rc = -EINVAL;
586 goto out;
587 }
588 POLICY_RDLOCK;
589 context = sidtab_search(&sidtab, sid);
590 if (!context) {
591 printk(KERN_ERR "security_sid_to_context: unrecognized SID "
592 "%d\n", sid);
593 rc = -EINVAL;
594 goto out_unlock;
595 }
596 rc = context_struct_to_string(context, scontext, scontext_len);
597out_unlock:
598 POLICY_RDUNLOCK;
599out:
600 return rc;
601
602}
603
604/**
605 * security_context_to_sid - Obtain a SID for a given security context.
606 * @scontext: security context
607 * @scontext_len: length in bytes
608 * @sid: security identifier, SID
609 *
610 * Obtains a SID associated with the security context that
611 * has the string representation specified by @scontext.
612 * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
613 * memory is available, or 0 on success.
614 */
615int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
616{
617 char *scontext2;
618 struct context context;
619 struct role_datum *role;
620 struct type_datum *typdatum;
621 struct user_datum *usrdatum;
622 char *scontextp, *p, oldc;
623 int rc = 0;
624
625 if (!ss_initialized) {
626 int i;
627
628 for (i = 1; i < SECINITSID_NUM; i++) {
629 if (!strcmp(initial_sid_to_string[i], scontext)) {
630 *sid = i;
631 goto out;
632 }
633 }
634 *sid = SECINITSID_KERNEL;
635 goto out;
636 }
637 *sid = SECSID_NULL;
638
639 /* Copy the string so that we can modify the copy as we parse it.
640 The string should already by null terminated, but we append a
641 null suffix to the copy to avoid problems with the existing
642 attr package, which doesn't view the null terminator as part
643 of the attribute value. */
644 scontext2 = kmalloc(scontext_len+1,GFP_KERNEL);
645 if (!scontext2) {
646 rc = -ENOMEM;
647 goto out;
648 }
649 memcpy(scontext2, scontext, scontext_len);
650 scontext2[scontext_len] = 0;
651
652 context_init(&context);
653 *sid = SECSID_NULL;
654
655 POLICY_RDLOCK;
656
657 /* Parse the security context. */
658
659 rc = -EINVAL;
660 scontextp = (char *) scontext2;
661
662 /* Extract the user. */
663 p = scontextp;
664 while (*p && *p != ':')
665 p++;
666
667 if (*p == 0)
668 goto out_unlock;
669
670 *p++ = 0;
671
672 usrdatum = hashtab_search(policydb.p_users.table, scontextp);
673 if (!usrdatum)
674 goto out_unlock;
675
676 context.user = usrdatum->value;
677
678 /* Extract role. */
679 scontextp = p;
680 while (*p && *p != ':')
681 p++;
682
683 if (*p == 0)
684 goto out_unlock;
685
686 *p++ = 0;
687
688 role = hashtab_search(policydb.p_roles.table, scontextp);
689 if (!role)
690 goto out_unlock;
691 context.role = role->value;
692
693 /* Extract type. */
694 scontextp = p;
695 while (*p && *p != ':')
696 p++;
697 oldc = *p;
698 *p++ = 0;
699
700 typdatum = hashtab_search(policydb.p_types.table, scontextp);
701 if (!typdatum)
702 goto out_unlock;
703
704 context.type = typdatum->value;
705
706 rc = mls_context_to_sid(oldc, &p, &context);
707 if (rc)
708 goto out_unlock;
709
710 if ((p - scontext2) < scontext_len) {
711 rc = -EINVAL;
712 goto out_unlock;
713 }
714
715 /* Check the validity of the new context. */
716 if (!policydb_context_isvalid(&policydb, &context)) {
717 rc = -EINVAL;
718 goto out_unlock;
719 }
720 /* Obtain the new sid. */
721 rc = sidtab_context_to_sid(&sidtab, &context, sid);
722out_unlock:
723 POLICY_RDUNLOCK;
724 context_destroy(&context);
725 kfree(scontext2);
726out:
727 return rc;
728}
729
730static int compute_sid_handle_invalid_context(
731 struct context *scontext,
732 struct context *tcontext,
733 u16 tclass,
734 struct context *newcontext)
735{
736 char *s = NULL, *t = NULL, *n = NULL;
737 u32 slen, tlen, nlen;
738
739 if (context_struct_to_string(scontext, &s, &slen) < 0)
740 goto out;
741 if (context_struct_to_string(tcontext, &t, &tlen) < 0)
742 goto out;
743 if (context_struct_to_string(newcontext, &n, &nlen) < 0)
744 goto out;
745 audit_log(current->audit_context,
746 "security_compute_sid: invalid context %s"
747 " for scontext=%s"
748 " tcontext=%s"
749 " tclass=%s",
750 n, s, t, policydb.p_class_val_to_name[tclass-1]);
751out:
752 kfree(s);
753 kfree(t);
754 kfree(n);
755 if (!selinux_enforcing)
756 return 0;
757 return -EACCES;
758}
759
760static int security_compute_sid(u32 ssid,
761 u32 tsid,
762 u16 tclass,
763 u32 specified,
764 u32 *out_sid)
765{
766 struct context *scontext = NULL, *tcontext = NULL, newcontext;
767 struct role_trans *roletr = NULL;
768 struct avtab_key avkey;
769 struct avtab_datum *avdatum;
770 struct avtab_node *node;
771 unsigned int type_change = 0;
772 int rc = 0;
773
774 if (!ss_initialized) {
775 switch (tclass) {
776 case SECCLASS_PROCESS:
777 *out_sid = ssid;
778 break;
779 default:
780 *out_sid = tsid;
781 break;
782 }
783 goto out;
784 }
785
786 POLICY_RDLOCK;
787
788 scontext = sidtab_search(&sidtab, ssid);
789 if (!scontext) {
790 printk(KERN_ERR "security_compute_sid: unrecognized SID %d\n",
791 ssid);
792 rc = -EINVAL;
793 goto out_unlock;
794 }
795 tcontext = sidtab_search(&sidtab, tsid);
796 if (!tcontext) {
797 printk(KERN_ERR "security_compute_sid: unrecognized SID %d\n",
798 tsid);
799 rc = -EINVAL;
800 goto out_unlock;
801 }
802
803 context_init(&newcontext);
804
805 /* Set the user identity. */
806 switch (specified) {
807 case AVTAB_TRANSITION:
808 case AVTAB_CHANGE:
809 /* Use the process user identity. */
810 newcontext.user = scontext->user;
811 break;
812 case AVTAB_MEMBER:
813 /* Use the related object owner. */
814 newcontext.user = tcontext->user;
815 break;
816 }
817
818 /* Set the role and type to default values. */
819 switch (tclass) {
820 case SECCLASS_PROCESS:
821 /* Use the current role and type of process. */
822 newcontext.role = scontext->role;
823 newcontext.type = scontext->type;
824 break;
825 default:
826 /* Use the well-defined object role. */
827 newcontext.role = OBJECT_R_VAL;
828 /* Use the type of the related object. */
829 newcontext.type = tcontext->type;
830 }
831
832 /* Look for a type transition/member/change rule. */
833 avkey.source_type = scontext->type;
834 avkey.target_type = tcontext->type;
835 avkey.target_class = tclass;
836 avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE);
837
838 /* If no permanent rule, also check for enabled conditional rules */
839 if(!avdatum) {
840 node = avtab_search_node(&policydb.te_cond_avtab, &avkey, specified);
841 for (; node != NULL; node = avtab_search_node_next(node, specified)) {
842 if (node->datum.specified & AVTAB_ENABLED) {
843 avdatum = &node->datum;
844 break;
845 }
846 }
847 }
848
849 type_change = (avdatum && (avdatum->specified & specified));
850 if (type_change) {
851 /* Use the type from the type transition/member/change rule. */
852 switch (specified) {
853 case AVTAB_TRANSITION:
854 newcontext.type = avtab_transition(avdatum);
855 break;
856 case AVTAB_MEMBER:
857 newcontext.type = avtab_member(avdatum);
858 break;
859 case AVTAB_CHANGE:
860 newcontext.type = avtab_change(avdatum);
861 break;
862 }
863 }
864
865 /* Check for class-specific changes. */
866 switch (tclass) {
867 case SECCLASS_PROCESS:
868 if (specified & AVTAB_TRANSITION) {
869 /* Look for a role transition rule. */
870 for (roletr = policydb.role_tr; roletr;
871 roletr = roletr->next) {
872 if (roletr->role == scontext->role &&
873 roletr->type == tcontext->type) {
874 /* Use the role transition rule. */
875 newcontext.role = roletr->new_role;
876 break;
877 }
878 }
879 }
880 break;
881 default:
882 break;
883 }
884
885 /* Set the MLS attributes.
886 This is done last because it may allocate memory. */
887 rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext);
888 if (rc)
889 goto out_unlock;
890
891 /* Check the validity of the context. */
892 if (!policydb_context_isvalid(&policydb, &newcontext)) {
893 rc = compute_sid_handle_invalid_context(scontext,
894 tcontext,
895 tclass,
896 &newcontext);
897 if (rc)
898 goto out_unlock;
899 }
900 /* Obtain the sid for the context. */
901 rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
902out_unlock:
903 POLICY_RDUNLOCK;
904 context_destroy(&newcontext);
905out:
906 return rc;
907}
908
909/**
910 * security_transition_sid - Compute the SID for a new subject/object.
911 * @ssid: source security identifier
912 * @tsid: target security identifier
913 * @tclass: target security class
914 * @out_sid: security identifier for new subject/object
915 *
916 * Compute a SID to use for labeling a new subject or object in the
917 * class @tclass based on a SID pair (@ssid, @tsid).
918 * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
919 * if insufficient memory is available, or %0 if the new SID was
920 * computed successfully.
921 */
922int security_transition_sid(u32 ssid,
923 u32 tsid,
924 u16 tclass,
925 u32 *out_sid)
926{
927 return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid);
928}
929
930/**
931 * security_member_sid - Compute the SID for member selection.
932 * @ssid: source security identifier
933 * @tsid: target security identifier
934 * @tclass: target security class
935 * @out_sid: security identifier for selected member
936 *
937 * Compute a SID to use when selecting a member of a polyinstantiated
938 * object of class @tclass based on a SID pair (@ssid, @tsid).
939 * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
940 * if insufficient memory is available, or %0 if the SID was
941 * computed successfully.
942 */
943int security_member_sid(u32 ssid,
944 u32 tsid,
945 u16 tclass,
946 u32 *out_sid)
947{
948 return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid);
949}
950
951/**
952 * security_change_sid - Compute the SID for object relabeling.
953 * @ssid: source security identifier
954 * @tsid: target security identifier
955 * @tclass: target security class
956 * @out_sid: security identifier for selected member
957 *
958 * Compute a SID to use for relabeling an object of class @tclass
959 * based on a SID pair (@ssid, @tsid).
960 * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
961 * if insufficient memory is available, or %0 if the SID was
962 * computed successfully.
963 */
964int security_change_sid(u32 ssid,
965 u32 tsid,
966 u16 tclass,
967 u32 *out_sid)
968{
969 return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid);
970}
971
972/*
973 * Verify that each permission that is defined under the
974 * existing policy is still defined with the same value
975 * in the new policy.
976 */
977static int validate_perm(void *key, void *datum, void *p)
978{
979 struct hashtab *h;
980 struct perm_datum *perdatum, *perdatum2;
981 int rc = 0;
982
983
984 h = p;
985 perdatum = datum;
986
987 perdatum2 = hashtab_search(h, key);
988 if (!perdatum2) {
989 printk(KERN_ERR "security: permission %s disappeared",
990 (char *)key);
991 rc = -ENOENT;
992 goto out;
993 }
994 if (perdatum->value != perdatum2->value) {
995 printk(KERN_ERR "security: the value of permission %s changed",
996 (char *)key);
997 rc = -EINVAL;
998 }
999out:
1000 return rc;
1001}
1002
1003/*
1004 * Verify that each class that is defined under the
1005 * existing policy is still defined with the same
1006 * attributes in the new policy.
1007 */
1008static int validate_class(void *key, void *datum, void *p)
1009{
1010 struct policydb *newp;
1011 struct class_datum *cladatum, *cladatum2;
1012 int rc;
1013
1014 newp = p;
1015 cladatum = datum;
1016
1017 cladatum2 = hashtab_search(newp->p_classes.table, key);
1018 if (!cladatum2) {
1019 printk(KERN_ERR "security: class %s disappeared\n",
1020 (char *)key);
1021 rc = -ENOENT;
1022 goto out;
1023 }
1024 if (cladatum->value != cladatum2->value) {
1025 printk(KERN_ERR "security: the value of class %s changed\n",
1026 (char *)key);
1027 rc = -EINVAL;
1028 goto out;
1029 }
1030 if ((cladatum->comdatum && !cladatum2->comdatum) ||
1031 (!cladatum->comdatum && cladatum2->comdatum)) {
1032 printk(KERN_ERR "security: the inherits clause for the access "
1033 "vector definition for class %s changed\n", (char *)key);
1034 rc = -EINVAL;
1035 goto out;
1036 }
1037 if (cladatum->comdatum) {
1038 rc = hashtab_map(cladatum->comdatum->permissions.table, validate_perm,
1039 cladatum2->comdatum->permissions.table);
1040 if (rc) {
1041 printk(" in the access vector definition for class "
1042 "%s\n", (char *)key);
1043 goto out;
1044 }
1045 }
1046 rc = hashtab_map(cladatum->permissions.table, validate_perm,
1047 cladatum2->permissions.table);
1048 if (rc)
1049 printk(" in access vector definition for class %s\n",
1050 (char *)key);
1051out:
1052 return rc;
1053}
1054
1055/* Clone the SID into the new SID table. */
1056static int clone_sid(u32 sid,
1057 struct context *context,
1058 void *arg)
1059{
1060 struct sidtab *s = arg;
1061
1062 return sidtab_insert(s, sid, context);
1063}
1064
1065static inline int convert_context_handle_invalid_context(struct context *context)
1066{
1067 int rc = 0;
1068
1069 if (selinux_enforcing) {
1070 rc = -EINVAL;
1071 } else {
1072 char *s;
1073 u32 len;
1074
1075 context_struct_to_string(context, &s, &len);
1076 printk(KERN_ERR "security: context %s is invalid\n", s);
1077 kfree(s);
1078 }
1079 return rc;
1080}
1081
1082struct convert_context_args {
1083 struct policydb *oldp;
1084 struct policydb *newp;
1085};
1086
1087/*
1088 * Convert the values in the security context
1089 * structure `c' from the values specified
1090 * in the policy `p->oldp' to the values specified
1091 * in the policy `p->newp'. Verify that the
1092 * context is valid under the new policy.
1093 */
1094static int convert_context(u32 key,
1095 struct context *c,
1096 void *p)
1097{
1098 struct convert_context_args *args;
1099 struct context oldc;
1100 struct role_datum *role;
1101 struct type_datum *typdatum;
1102 struct user_datum *usrdatum;
1103 char *s;
1104 u32 len;
1105 int rc;
1106
1107 args = p;
1108
1109 rc = context_cpy(&oldc, c);
1110 if (rc)
1111 goto out;
1112
1113 rc = -EINVAL;
1114
1115 /* Convert the user. */
1116 usrdatum = hashtab_search(args->newp->p_users.table,
1117 args->oldp->p_user_val_to_name[c->user - 1]);
1118 if (!usrdatum) {
1119 goto bad;
1120 }
1121 c->user = usrdatum->value;
1122
1123 /* Convert the role. */
1124 role = hashtab_search(args->newp->p_roles.table,
1125 args->oldp->p_role_val_to_name[c->role - 1]);
1126 if (!role) {
1127 goto bad;
1128 }
1129 c->role = role->value;
1130
1131 /* Convert the type. */
1132 typdatum = hashtab_search(args->newp->p_types.table,
1133 args->oldp->p_type_val_to_name[c->type - 1]);
1134 if (!typdatum) {
1135 goto bad;
1136 }
1137 c->type = typdatum->value;
1138
1139 rc = mls_convert_context(args->oldp, args->newp, c);
1140 if (rc)
1141 goto bad;
1142
1143 /* Check the validity of the new context. */
1144 if (!policydb_context_isvalid(args->newp, c)) {
1145 rc = convert_context_handle_invalid_context(&oldc);
1146 if (rc)
1147 goto bad;
1148 }
1149
1150 context_destroy(&oldc);
1151out:
1152 return rc;
1153bad:
1154 context_struct_to_string(&oldc, &s, &len);
1155 context_destroy(&oldc);
1156 printk(KERN_ERR "security: invalidating context %s\n", s);
1157 kfree(s);
1158 goto out;
1159}
1160
1161extern void selinux_complete_init(void);
1162
1163/**
1164 * security_load_policy - Load a security policy configuration.
1165 * @data: binary policy data
1166 * @len: length of data in bytes
1167 *
1168 * Load a new set of security policy configuration data,
1169 * validate it and convert the SID table as necessary.
1170 * This function will flush the access vector cache after
1171 * loading the new policy.
1172 */
1173int security_load_policy(void *data, size_t len)
1174{
1175 struct policydb oldpolicydb, newpolicydb;
1176 struct sidtab oldsidtab, newsidtab;
1177 struct convert_context_args args;
1178 u32 seqno;
1179 int rc = 0;
1180 struct policy_file file = { data, len }, *fp = &file;
1181
1182 LOAD_LOCK;
1183
1184 if (!ss_initialized) {
1185 avtab_cache_init();
1186 if (policydb_read(&policydb, fp)) {
1187 LOAD_UNLOCK;
1188 avtab_cache_destroy();
1189 return -EINVAL;
1190 }
1191 if (policydb_load_isids(&policydb, &sidtab)) {
1192 LOAD_UNLOCK;
1193 policydb_destroy(&policydb);
1194 avtab_cache_destroy();
1195 return -EINVAL;
1196 }
1197 policydb_loaded_version = policydb.policyvers;
1198 ss_initialized = 1;
1199
1200 LOAD_UNLOCK;
1201 selinux_complete_init();
1202 return 0;
1203 }
1204
1205#if 0
1206 sidtab_hash_eval(&sidtab, "sids");
1207#endif
1208
1209 if (policydb_read(&newpolicydb, fp)) {
1210 LOAD_UNLOCK;
1211 return -EINVAL;
1212 }
1213
1214 sidtab_init(&newsidtab);
1215
1216 /* Verify that the existing classes did not change. */
1217 if (hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb)) {
1218 printk(KERN_ERR "security: the definition of an existing "
1219 "class changed\n");
1220 rc = -EINVAL;
1221 goto err;
1222 }
1223
1224 /* Clone the SID table. */
1225 sidtab_shutdown(&sidtab);
1226 if (sidtab_map(&sidtab, clone_sid, &newsidtab)) {
1227 rc = -ENOMEM;
1228 goto err;
1229 }
1230
1231 /* Convert the internal representations of contexts
1232 in the new SID table and remove invalid SIDs. */
1233 args.oldp = &policydb;
1234 args.newp = &newpolicydb;
1235 sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
1236
1237 /* Save the old policydb and SID table to free later. */
1238 memcpy(&oldpolicydb, &policydb, sizeof policydb);
1239 sidtab_set(&oldsidtab, &sidtab);
1240
1241 /* Install the new policydb and SID table. */
1242 POLICY_WRLOCK;
1243 memcpy(&policydb, &newpolicydb, sizeof policydb);
1244 sidtab_set(&sidtab, &newsidtab);
1245 seqno = ++latest_granting;
1246 policydb_loaded_version = policydb.policyvers;
1247 POLICY_WRUNLOCK;
1248 LOAD_UNLOCK;
1249
1250 /* Free the old policydb and SID table. */
1251 policydb_destroy(&oldpolicydb);
1252 sidtab_destroy(&oldsidtab);
1253
1254 avc_ss_reset(seqno);
1255 selnl_notify_policyload(seqno);
1256
1257 return 0;
1258
1259err:
1260 LOAD_UNLOCK;
1261 sidtab_destroy(&newsidtab);
1262 policydb_destroy(&newpolicydb);
1263 return rc;
1264
1265}
1266
1267/**
1268 * security_port_sid - Obtain the SID for a port.
1269 * @domain: communication domain aka address family
1270 * @type: socket type
1271 * @protocol: protocol number
1272 * @port: port number
1273 * @out_sid: security identifier
1274 */
1275int security_port_sid(u16 domain,
1276 u16 type,
1277 u8 protocol,
1278 u16 port,
1279 u32 *out_sid)
1280{
1281 struct ocontext *c;
1282 int rc = 0;
1283
1284 POLICY_RDLOCK;
1285
1286 c = policydb.ocontexts[OCON_PORT];
1287 while (c) {
1288 if (c->u.port.protocol == protocol &&
1289 c->u.port.low_port <= port &&
1290 c->u.port.high_port >= port)
1291 break;
1292 c = c->next;
1293 }
1294
1295 if (c) {
1296 if (!c->sid[0]) {
1297 rc = sidtab_context_to_sid(&sidtab,
1298 &c->context[0],
1299 &c->sid[0]);
1300 if (rc)
1301 goto out;
1302 }
1303 *out_sid = c->sid[0];
1304 } else {
1305 *out_sid = SECINITSID_PORT;
1306 }
1307
1308out:
1309 POLICY_RDUNLOCK;
1310 return rc;
1311}
1312
1313/**
1314 * security_netif_sid - Obtain the SID for a network interface.
1315 * @name: interface name
1316 * @if_sid: interface SID
1317 * @msg_sid: default SID for received packets
1318 */
1319int security_netif_sid(char *name,
1320 u32 *if_sid,
1321 u32 *msg_sid)
1322{
1323 int rc = 0;
1324 struct ocontext *c;
1325
1326 POLICY_RDLOCK;
1327
1328 c = policydb.ocontexts[OCON_NETIF];
1329 while (c) {
1330 if (strcmp(name, c->u.name) == 0)
1331 break;
1332 c = c->next;
1333 }
1334
1335 if (c) {
1336 if (!c->sid[0] || !c->sid[1]) {
1337 rc = sidtab_context_to_sid(&sidtab,
1338 &c->context[0],
1339 &c->sid[0]);
1340 if (rc)
1341 goto out;
1342 rc = sidtab_context_to_sid(&sidtab,
1343 &c->context[1],
1344 &c->sid[1]);
1345 if (rc)
1346 goto out;
1347 }
1348 *if_sid = c->sid[0];
1349 *msg_sid = c->sid[1];
1350 } else {
1351 *if_sid = SECINITSID_NETIF;
1352 *msg_sid = SECINITSID_NETMSG;
1353 }
1354
1355out:
1356 POLICY_RDUNLOCK;
1357 return rc;
1358}
1359
1360static int match_ipv6_addrmask(u32 *input, u32 *addr, u32 *mask)
1361{
1362 int i, fail = 0;
1363
1364 for(i = 0; i < 4; i++)
1365 if(addr[i] != (input[i] & mask[i])) {
1366 fail = 1;
1367 break;
1368 }
1369
1370 return !fail;
1371}
1372
1373/**
1374 * security_node_sid - Obtain the SID for a node (host).
1375 * @domain: communication domain aka address family
1376 * @addrp: address
1377 * @addrlen: address length in bytes
1378 * @out_sid: security identifier
1379 */
1380int security_node_sid(u16 domain,
1381 void *addrp,
1382 u32 addrlen,
1383 u32 *out_sid)
1384{
1385 int rc = 0;
1386 struct ocontext *c;
1387
1388 POLICY_RDLOCK;
1389
1390 switch (domain) {
1391 case AF_INET: {
1392 u32 addr;
1393
1394 if (addrlen != sizeof(u32)) {
1395 rc = -EINVAL;
1396 goto out;
1397 }
1398
1399 addr = *((u32 *)addrp);
1400
1401 c = policydb.ocontexts[OCON_NODE];
1402 while (c) {
1403 if (c->u.node.addr == (addr & c->u.node.mask))
1404 break;
1405 c = c->next;
1406 }
1407 break;
1408 }
1409
1410 case AF_INET6:
1411 if (addrlen != sizeof(u64) * 2) {
1412 rc = -EINVAL;
1413 goto out;
1414 }
1415 c = policydb.ocontexts[OCON_NODE6];
1416 while (c) {
1417 if (match_ipv6_addrmask(addrp, c->u.node6.addr,
1418 c->u.node6.mask))
1419 break;
1420 c = c->next;
1421 }
1422 break;
1423
1424 default:
1425 *out_sid = SECINITSID_NODE;
1426 goto out;
1427 }
1428
1429 if (c) {
1430 if (!c->sid[0]) {
1431 rc = sidtab_context_to_sid(&sidtab,
1432 &c->context[0],
1433 &c->sid[0]);
1434 if (rc)
1435 goto out;
1436 }
1437 *out_sid = c->sid[0];
1438 } else {
1439 *out_sid = SECINITSID_NODE;
1440 }
1441
1442out:
1443 POLICY_RDUNLOCK;
1444 return rc;
1445}
1446
1447#define SIDS_NEL 25
1448
1449/**
1450 * security_get_user_sids - Obtain reachable SIDs for a user.
1451 * @fromsid: starting SID
1452 * @username: username
1453 * @sids: array of reachable SIDs for user
1454 * @nel: number of elements in @sids
1455 *
1456 * Generate the set of SIDs for legal security contexts
1457 * for a given user that can be reached by @fromsid.
1458 * Set *@sids to point to a dynamically allocated
1459 * array containing the set of SIDs. Set *@nel to the
1460 * number of elements in the array.
1461 */
1462
1463int security_get_user_sids(u32 fromsid,
1464 char *username,
1465 u32 **sids,
1466 u32 *nel)
1467{
1468 struct context *fromcon, usercon;
1469 u32 *mysids, *mysids2, sid;
1470 u32 mynel = 0, maxnel = SIDS_NEL;
1471 struct user_datum *user;
1472 struct role_datum *role;
1473 struct av_decision avd;
1474 int rc = 0, i, j;
1475
1476 if (!ss_initialized) {
1477 *sids = NULL;
1478 *nel = 0;
1479 goto out;
1480 }
1481
1482 POLICY_RDLOCK;
1483
1484 fromcon = sidtab_search(&sidtab, fromsid);
1485 if (!fromcon) {
1486 rc = -EINVAL;
1487 goto out_unlock;
1488 }
1489
1490 user = hashtab_search(policydb.p_users.table, username);
1491 if (!user) {
1492 rc = -EINVAL;
1493 goto out_unlock;
1494 }
1495 usercon.user = user->value;
1496
1497 mysids = kmalloc(maxnel*sizeof(*mysids), GFP_ATOMIC);
1498 if (!mysids) {
1499 rc = -ENOMEM;
1500 goto out_unlock;
1501 }
1502 memset(mysids, 0, maxnel*sizeof(*mysids));
1503
1504 for (i = ebitmap_startbit(&user->roles); i < ebitmap_length(&user->roles); i++) {
1505 if (!ebitmap_get_bit(&user->roles, i))
1506 continue;
1507 role = policydb.role_val_to_struct[i];
1508 usercon.role = i+1;
1509 for (j = ebitmap_startbit(&role->types); j < ebitmap_length(&role->types); j++) {
1510 if (!ebitmap_get_bit(&role->types, j))
1511 continue;
1512 usercon.type = j+1;
1513
1514 if (mls_setup_user_range(fromcon, user, &usercon))
1515 continue;
1516
1517 rc = context_struct_compute_av(fromcon, &usercon,
1518 SECCLASS_PROCESS,
1519 PROCESS__TRANSITION,
1520 &avd);
1521 if (rc || !(avd.allowed & PROCESS__TRANSITION))
1522 continue;
1523 rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
1524 if (rc) {
1525 kfree(mysids);
1526 goto out_unlock;
1527 }
1528 if (mynel < maxnel) {
1529 mysids[mynel++] = sid;
1530 } else {
1531 maxnel += SIDS_NEL;
1532 mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC);
1533 if (!mysids2) {
1534 rc = -ENOMEM;
1535 kfree(mysids);
1536 goto out_unlock;
1537 }
1538 memset(mysids2, 0, maxnel*sizeof(*mysids2));
1539 memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
1540 kfree(mysids);
1541 mysids = mysids2;
1542 mysids[mynel++] = sid;
1543 }
1544 }
1545 }
1546
1547 *sids = mysids;
1548 *nel = mynel;
1549
1550out_unlock:
1551 POLICY_RDUNLOCK;
1552out:
1553 return rc;
1554}
1555
1556/**
1557 * security_genfs_sid - Obtain a SID for a file in a filesystem
1558 * @fstype: filesystem type
1559 * @path: path from root of mount
1560 * @sclass: file security class
1561 * @sid: SID for path
1562 *
1563 * Obtain a SID to use for a file in a filesystem that
1564 * cannot support xattr or use a fixed labeling behavior like
1565 * transition SIDs or task SIDs.
1566 */
1567int security_genfs_sid(const char *fstype,
1568 char *path,
1569 u16 sclass,
1570 u32 *sid)
1571{
1572 int len;
1573 struct genfs *genfs;
1574 struct ocontext *c;
1575 int rc = 0, cmp = 0;
1576
1577 POLICY_RDLOCK;
1578
1579 for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
1580 cmp = strcmp(fstype, genfs->fstype);
1581 if (cmp <= 0)
1582 break;
1583 }
1584
1585 if (!genfs || cmp) {
1586 *sid = SECINITSID_UNLABELED;
1587 rc = -ENOENT;
1588 goto out;
1589 }
1590
1591 for (c = genfs->head; c; c = c->next) {
1592 len = strlen(c->u.name);
1593 if ((!c->v.sclass || sclass == c->v.sclass) &&
1594 (strncmp(c->u.name, path, len) == 0))
1595 break;
1596 }
1597
1598 if (!c) {
1599 *sid = SECINITSID_UNLABELED;
1600 rc = -ENOENT;
1601 goto out;
1602 }
1603
1604 if (!c->sid[0]) {
1605 rc = sidtab_context_to_sid(&sidtab,
1606 &c->context[0],
1607 &c->sid[0]);
1608 if (rc)
1609 goto out;
1610 }
1611
1612 *sid = c->sid[0];
1613out:
1614 POLICY_RDUNLOCK;
1615 return rc;
1616}
1617
1618/**
1619 * security_fs_use - Determine how to handle labeling for a filesystem.
1620 * @fstype: filesystem type
1621 * @behavior: labeling behavior
1622 * @sid: SID for filesystem (superblock)
1623 */
1624int security_fs_use(
1625 const char *fstype,
1626 unsigned int *behavior,
1627 u32 *sid)
1628{
1629 int rc = 0;
1630 struct ocontext *c;
1631
1632 POLICY_RDLOCK;
1633
1634 c = policydb.ocontexts[OCON_FSUSE];
1635 while (c) {
1636 if (strcmp(fstype, c->u.name) == 0)
1637 break;
1638 c = c->next;
1639 }
1640
1641 if (c) {
1642 *behavior = c->v.behavior;
1643 if (!c->sid[0]) {
1644 rc = sidtab_context_to_sid(&sidtab,
1645 &c->context[0],
1646 &c->sid[0]);
1647 if (rc)
1648 goto out;
1649 }
1650 *sid = c->sid[0];
1651 } else {
1652 rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
1653 if (rc) {
1654 *behavior = SECURITY_FS_USE_NONE;
1655 rc = 0;
1656 } else {
1657 *behavior = SECURITY_FS_USE_GENFS;
1658 }
1659 }
1660
1661out:
1662 POLICY_RDUNLOCK;
1663 return rc;
1664}
1665
1666int security_get_bools(int *len, char ***names, int **values)
1667{
1668 int i, rc = -ENOMEM;
1669
1670 POLICY_RDLOCK;
1671 *names = NULL;
1672 *values = NULL;
1673
1674 *len = policydb.p_bools.nprim;
1675 if (!*len) {
1676 rc = 0;
1677 goto out;
1678 }
1679
1680 *names = (char**)kmalloc(sizeof(char*) * *len, GFP_ATOMIC);
1681 if (!*names)
1682 goto err;
1683 memset(*names, 0, sizeof(char*) * *len);
1684
1685 *values = (int*)kmalloc(sizeof(int) * *len, GFP_ATOMIC);
1686 if (!*values)
1687 goto err;
1688
1689 for (i = 0; i < *len; i++) {
1690 size_t name_len;
1691 (*values)[i] = policydb.bool_val_to_struct[i]->state;
1692 name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
1693 (*names)[i] = (char*)kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
1694 if (!(*names)[i])
1695 goto err;
1696 strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
1697 (*names)[i][name_len - 1] = 0;
1698 }
1699 rc = 0;
1700out:
1701 POLICY_RDUNLOCK;
1702 return rc;
1703err:
1704 if (*names) {
1705 for (i = 0; i < *len; i++)
1706 if ((*names)[i])
1707 kfree((*names)[i]);
1708 }
1709 if (*values)
1710 kfree(*values);
1711 goto out;
1712}
1713
1714
1715int security_set_bools(int len, int *values)
1716{
1717 int i, rc = 0;
1718 int lenp, seqno = 0;
1719 struct cond_node *cur;
1720
1721 POLICY_WRLOCK;
1722
1723 lenp = policydb.p_bools.nprim;
1724 if (len != lenp) {
1725 rc = -EFAULT;
1726 goto out;
1727 }
1728
1729 printk(KERN_INFO "security: committed booleans { ");
1730 for (i = 0; i < len; i++) {
1731 if (values[i]) {
1732 policydb.bool_val_to_struct[i]->state = 1;
1733 } else {
1734 policydb.bool_val_to_struct[i]->state = 0;
1735 }
1736 if (i != 0)
1737 printk(", ");
1738 printk("%s:%d", policydb.p_bool_val_to_name[i],
1739 policydb.bool_val_to_struct[i]->state);
1740 }
1741 printk(" }\n");
1742
1743 for (cur = policydb.cond_list; cur != NULL; cur = cur->next) {
1744 rc = evaluate_cond_node(&policydb, cur);
1745 if (rc)
1746 goto out;
1747 }
1748
1749 seqno = ++latest_granting;
1750
1751out:
1752 POLICY_WRUNLOCK;
1753 if (!rc) {
1754 avc_ss_reset(seqno);
1755 selnl_notify_policyload(seqno);
1756 }
1757 return rc;
1758}
1759
1760int security_get_bool_value(int bool)
1761{
1762 int rc = 0;
1763 int len;
1764
1765 POLICY_RDLOCK;
1766
1767 len = policydb.p_bools.nprim;
1768 if (bool >= len) {
1769 rc = -EFAULT;
1770 goto out;
1771 }
1772
1773 rc = policydb.bool_val_to_struct[bool]->state;
1774out:
1775 POLICY_RDUNLOCK;
1776 return rc;
1777}
diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h
new file mode 100644
index 00000000000..e8d907e903c
--- /dev/null
+++ b/security/selinux/ss/services.h
@@ -0,0 +1,15 @@
1/*
2 * Implementation of the security services.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6#ifndef _SS_SERVICES_H_
7#define _SS_SERVICES_H_
8
9#include "policydb.h"
10#include "sidtab.h"
11
12extern struct policydb policydb;
13
14#endif /* _SS_SERVICES_H_ */
15
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
new file mode 100644
index 00000000000..871c33bd074
--- /dev/null
+++ b/security/selinux/ss/sidtab.c
@@ -0,0 +1,305 @@
1/*
2 * Implementation of the SID table type.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6#include <linux/kernel.h>
7#include <linux/slab.h>
8#include <linux/spinlock.h>
9#include <linux/errno.h>
10#include <linux/sched.h>
11#include "flask.h"
12#include "security.h"
13#include "sidtab.h"
14
15#define SIDTAB_HASH(sid) \
16(sid & SIDTAB_HASH_MASK)
17
18#define INIT_SIDTAB_LOCK(s) spin_lock_init(&s->lock)
19#define SIDTAB_LOCK(s, x) spin_lock_irqsave(&s->lock, x)
20#define SIDTAB_UNLOCK(s, x) spin_unlock_irqrestore(&s->lock, x)
21
22int sidtab_init(struct sidtab *s)
23{
24 int i;
25
26 s->htable = kmalloc(sizeof(*(s->htable)) * SIDTAB_SIZE, GFP_ATOMIC);
27 if (!s->htable)
28 return -ENOMEM;
29 for (i = 0; i < SIDTAB_SIZE; i++)
30 s->htable[i] = NULL;
31 s->nel = 0;
32 s->next_sid = 1;
33 s->shutdown = 0;
34 INIT_SIDTAB_LOCK(s);
35 return 0;
36}
37
38int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
39{
40 int hvalue, rc = 0;
41 struct sidtab_node *prev, *cur, *newnode;
42
43 if (!s) {
44 rc = -ENOMEM;
45 goto out;
46 }
47
48 hvalue = SIDTAB_HASH(sid);
49 prev = NULL;
50 cur = s->htable[hvalue];
51 while (cur != NULL && sid > cur->sid) {
52 prev = cur;
53 cur = cur->next;
54 }
55
56 if (cur && sid == cur->sid) {
57 rc = -EEXIST;
58 goto out;
59 }
60
61 newnode = kmalloc(sizeof(*newnode), GFP_ATOMIC);
62 if (newnode == NULL) {
63 rc = -ENOMEM;
64 goto out;
65 }
66 newnode->sid = sid;
67 if (context_cpy(&newnode->context, context)) {
68 kfree(newnode);
69 rc = -ENOMEM;
70 goto out;
71 }
72
73 if (prev) {
74 newnode->next = prev->next;
75 wmb();
76 prev->next = newnode;
77 } else {
78 newnode->next = s->htable[hvalue];
79 wmb();
80 s->htable[hvalue] = newnode;
81 }
82
83 s->nel++;
84 if (sid >= s->next_sid)
85 s->next_sid = sid + 1;
86out:
87 return rc;
88}
89
90struct context *sidtab_search(struct sidtab *s, u32 sid)
91{
92 int hvalue;
93 struct sidtab_node *cur;
94
95 if (!s)
96 return NULL;
97
98 hvalue = SIDTAB_HASH(sid);
99 cur = s->htable[hvalue];
100 while (cur != NULL && sid > cur->sid)
101 cur = cur->next;
102
103 if (cur == NULL || sid != cur->sid) {
104 /* Remap invalid SIDs to the unlabeled SID. */
105 sid = SECINITSID_UNLABELED;
106 hvalue = SIDTAB_HASH(sid);
107 cur = s->htable[hvalue];
108 while (cur != NULL && sid > cur->sid)
109 cur = cur->next;
110 if (!cur || sid != cur->sid)
111 return NULL;
112 }
113
114 return &cur->context;
115}
116
117int sidtab_map(struct sidtab *s,
118 int (*apply) (u32 sid,
119 struct context *context,
120 void *args),
121 void *args)
122{
123 int i, rc = 0;
124 struct sidtab_node *cur;
125
126 if (!s)
127 goto out;
128
129 for (i = 0; i < SIDTAB_SIZE; i++) {
130 cur = s->htable[i];
131 while (cur != NULL) {
132 rc = apply(cur->sid, &cur->context, args);
133 if (rc)
134 goto out;
135 cur = cur->next;
136 }
137 }
138out:
139 return rc;
140}
141
142void sidtab_map_remove_on_error(struct sidtab *s,
143 int (*apply) (u32 sid,
144 struct context *context,
145 void *args),
146 void *args)
147{
148 int i, ret;
149 struct sidtab_node *last, *cur, *temp;
150
151 if (!s)
152 return;
153
154 for (i = 0; i < SIDTAB_SIZE; i++) {
155 last = NULL;
156 cur = s->htable[i];
157 while (cur != NULL) {
158 ret = apply(cur->sid, &cur->context, args);
159 if (ret) {
160 if (last) {
161 last->next = cur->next;
162 } else {
163 s->htable[i] = cur->next;
164 }
165
166 temp = cur;
167 cur = cur->next;
168 context_destroy(&temp->context);
169 kfree(temp);
170 s->nel--;
171 } else {
172 last = cur;
173 cur = cur->next;
174 }
175 }
176 }
177
178 return;
179}
180
181static inline u32 sidtab_search_context(struct sidtab *s,
182 struct context *context)
183{
184 int i;
185 struct sidtab_node *cur;
186
187 for (i = 0; i < SIDTAB_SIZE; i++) {
188 cur = s->htable[i];
189 while (cur != NULL) {
190 if (context_cmp(&cur->context, context))
191 return cur->sid;
192 cur = cur->next;
193 }
194 }
195 return 0;
196}
197
198int sidtab_context_to_sid(struct sidtab *s,
199 struct context *context,
200 u32 *out_sid)
201{
202 u32 sid;
203 int ret = 0;
204 unsigned long flags;
205
206 *out_sid = SECSID_NULL;
207
208 sid = sidtab_search_context(s, context);
209 if (!sid) {
210 SIDTAB_LOCK(s, flags);
211 /* Rescan now that we hold the lock. */
212 sid = sidtab_search_context(s, context);
213 if (sid)
214 goto unlock_out;
215 /* No SID exists for the context. Allocate a new one. */
216 if (s->next_sid == UINT_MAX || s->shutdown) {
217 ret = -ENOMEM;
218 goto unlock_out;
219 }
220 sid = s->next_sid++;
221 ret = sidtab_insert(s, sid, context);
222 if (ret)
223 s->next_sid--;
224unlock_out:
225 SIDTAB_UNLOCK(s, flags);
226 }
227
228 if (ret)
229 return ret;
230
231 *out_sid = sid;
232 return 0;
233}
234
235void sidtab_hash_eval(struct sidtab *h, char *tag)
236{
237 int i, chain_len, slots_used, max_chain_len;
238 struct sidtab_node *cur;
239
240 slots_used = 0;
241 max_chain_len = 0;
242 for (i = 0; i < SIDTAB_SIZE; i++) {
243 cur = h->htable[i];
244 if (cur) {
245 slots_used++;
246 chain_len = 0;
247 while (cur) {
248 chain_len++;
249 cur = cur->next;
250 }
251
252 if (chain_len > max_chain_len)
253 max_chain_len = chain_len;
254 }
255 }
256
257 printk(KERN_INFO "%s: %d entries and %d/%d buckets used, longest "
258 "chain length %d\n", tag, h->nel, slots_used, SIDTAB_SIZE,
259 max_chain_len);
260}
261
262void sidtab_destroy(struct sidtab *s)
263{
264 int i;
265 struct sidtab_node *cur, *temp;
266
267 if (!s)
268 return;
269
270 for (i = 0; i < SIDTAB_SIZE; i++) {
271 cur = s->htable[i];
272 while (cur != NULL) {
273 temp = cur;
274 cur = cur->next;
275 context_destroy(&temp->context);
276 kfree(temp);
277 }
278 s->htable[i] = NULL;
279 }
280 kfree(s->htable);
281 s->htable = NULL;
282 s->nel = 0;
283 s->next_sid = 1;
284}
285
286void sidtab_set(struct sidtab *dst, struct sidtab *src)
287{
288 unsigned long flags;
289
290 SIDTAB_LOCK(src, flags);
291 dst->htable = src->htable;
292 dst->nel = src->nel;
293 dst->next_sid = src->next_sid;
294 dst->shutdown = 0;
295 SIDTAB_UNLOCK(src, flags);
296}
297
298void sidtab_shutdown(struct sidtab *s)
299{
300 unsigned long flags;
301
302 SIDTAB_LOCK(s, flags);
303 s->shutdown = 1;
304 SIDTAB_UNLOCK(s, flags);
305}
diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h
new file mode 100644
index 00000000000..2fe9dfa3eb3
--- /dev/null
+++ b/security/selinux/ss/sidtab.h
@@ -0,0 +1,59 @@
1/*
2 * A security identifier table (sidtab) is a hash table
3 * of security context structures indexed by SID value.
4 *
5 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
6 */
7#ifndef _SS_SIDTAB_H_
8#define _SS_SIDTAB_H_
9
10#include "context.h"
11
12struct sidtab_node {
13 u32 sid; /* security identifier */
14 struct context context; /* security context structure */
15 struct sidtab_node *next;
16};
17
18#define SIDTAB_HASH_BITS 7
19#define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS)
20#define SIDTAB_HASH_MASK (SIDTAB_HASH_BUCKETS-1)
21
22#define SIDTAB_SIZE SIDTAB_HASH_BUCKETS
23
24struct sidtab {
25 struct sidtab_node **htable;
26 unsigned int nel; /* number of elements */
27 unsigned int next_sid; /* next SID to allocate */
28 unsigned char shutdown;
29 spinlock_t lock;
30};
31
32int sidtab_init(struct sidtab *s);
33int sidtab_insert(struct sidtab *s, u32 sid, struct context *context);
34struct context *sidtab_search(struct sidtab *s, u32 sid);
35
36int sidtab_map(struct sidtab *s,
37 int (*apply) (u32 sid,
38 struct context *context,
39 void *args),
40 void *args);
41
42void sidtab_map_remove_on_error(struct sidtab *s,
43 int (*apply) (u32 sid,
44 struct context *context,
45 void *args),
46 void *args);
47
48int sidtab_context_to_sid(struct sidtab *s,
49 struct context *context,
50 u32 *sid);
51
52void sidtab_hash_eval(struct sidtab *h, char *tag);
53void sidtab_destroy(struct sidtab *s);
54void sidtab_set(struct sidtab *dst, struct sidtab *src);
55void sidtab_shutdown(struct sidtab *s);
56
57#endif /* _SS_SIDTAB_H_ */
58
59
diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c
new file mode 100644
index 00000000000..24a10d36d3b
--- /dev/null
+++ b/security/selinux/ss/symtab.c
@@ -0,0 +1,44 @@
1/*
2 * Implementation of the symbol table type.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6#include <linux/kernel.h>
7#include <linux/slab.h>
8#include <linux/string.h>
9#include <linux/errno.h>
10#include "symtab.h"
11
12static unsigned int symhash(struct hashtab *h, void *key)
13{
14 char *p, *keyp;
15 unsigned int size;
16 unsigned int val;
17
18 val = 0;
19 keyp = key;
20 size = strlen(keyp);
21 for (p = keyp; (p - keyp) < size; p++)
22 val = (val << 4 | (val >> (8*sizeof(unsigned int)-4))) ^ (*p);
23 return val & (h->size - 1);
24}
25
26static int symcmp(struct hashtab *h, void *key1, void *key2)
27{
28 char *keyp1, *keyp2;
29
30 keyp1 = key1;
31 keyp2 = key2;
32 return strcmp(keyp1, keyp2);
33}
34
35
36int symtab_init(struct symtab *s, unsigned int size)
37{
38 s->table = hashtab_create(symhash, symcmp, size);
39 if (!s->table)
40 return -1;
41 s->nprim = 0;
42 return 0;
43}
44
diff --git a/security/selinux/ss/symtab.h b/security/selinux/ss/symtab.h
new file mode 100644
index 00000000000..ca422b42fbc
--- /dev/null
+++ b/security/selinux/ss/symtab.h
@@ -0,0 +1,23 @@
1/*
2 * A symbol table (symtab) maintains associations between symbol
3 * strings and datum values. The type of the datum values
4 * is arbitrary. The symbol table type is implemented
5 * using the hash table type (hashtab).
6 *
7 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
8 */
9#ifndef _SS_SYMTAB_H_
10#define _SS_SYMTAB_H_
11
12#include "hashtab.h"
13
14struct symtab {
15 struct hashtab *table; /* hash table (keyed on a string) */
16 u32 nprim; /* number of primary names in table */
17};
18
19int symtab_init(struct symtab *s, unsigned int size);
20
21#endif /* _SS_SYMTAB_H_ */
22
23