aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/avc.c
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2009-09-30 13:37:50 -0400
committerJames Morris <jmorris@namei.org>2009-10-07 06:56:42 -0400
commitc6d3aaa4e35c71a32a86ececacd4eea7ecfc316c (patch)
tree1a5475b4370655a22670fd6eb35e54d8b131b362 /security/selinux/avc.c
parent23acb98de5a4109a60b5fe3f0439389218b039d7 (diff)
selinux: dynamic class/perm discovery
Modify SELinux to dynamically discover class and permission values upon policy load, based on the dynamic object class/perm discovery logic from libselinux. A mapping is created between kernel-private class and permission indices used outside the security server and the policy values used within the security server. The mappings are only applied upon kernel-internal computations; similar mappings for the private indices of userspace object managers is handled on a per-object manager basis by the userspace AVC. The interfaces for compute_av and transition_sid are split for kernel vs. userspace; the userspace functions are distinguished by a _user suffix. The kernel-private class indices are no longer tied to the policy values and thus do not need to skip indices for userspace classes; thus the kernel class index values are compressed. The flask.h definitions were regenerated by deleting the userspace classes from refpolicy's definitions and then regenerating the headers. Going forward, we can just maintain the flask.h, av_permissions.h, and classmap.h definitions separately from policy as they are no longer tied to the policy values. The next patch introduces a utility to automate generation of flask.h and av_permissions.h from the classmap.h definitions. The older kernel class and permission string tables are removed and replaced by a single security class mapping table that is walked at policy load to generate the mapping. The old kernel class validation logic is completely replaced by the mapping logic. The handle unknown logic is reworked. reject_unknown=1 is handled when the mappings are computed at policy load time, similar to the old handling by the class validation logic. allow_unknown=1 is handled when computing and mapping decisions - if the permission was not able to be mapped (i.e. undefined, mapped to zero), then it is automatically added to the allowed vector. If the class was not able to be mapped (i.e. undefined, mapped to zero), then all permissions are allowed for it if allow_unknown=1. avc_audit leverages the new security class mapping table to lookup the class and permission names from the kernel-private indices. The mdp program is updated to use the new table when generating the class definitions and allow rules for a minimal boot policy for the kernel. It should be noted that this policy will not include any userspace classes, nor will its policy index values for the kernel classes correspond with the ones in refpolicy (they will instead match the kernel-private indices). Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/avc.c')
-rw-r--r--security/selinux/avc.c76
1 files changed, 8 insertions, 68 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index b4b5da1c0a42..18f4103e02b7 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -31,43 +31,7 @@
31#include <net/ipv6.h> 31#include <net/ipv6.h>
32#include "avc.h" 32#include "avc.h"
33#include "avc_ss.h" 33#include "avc_ss.h"
34 34#include "classmap.h"
35static const struct av_perm_to_string av_perm_to_string[] = {
36#define S_(c, v, s) { c, v, s },
37#include "av_perm_to_string.h"
38#undef S_
39};
40
41static const char *class_to_string[] = {
42#define S_(s) s,
43#include "class_to_string.h"
44#undef S_
45};
46
47#define TB_(s) static const char *s[] = {
48#define TE_(s) };
49#define S_(s) s,
50#include "common_perm_to_string.h"
51#undef TB_
52#undef TE_
53#undef S_
54
55static const struct av_inherit av_inherit[] = {
56#define S_(c, i, b) { .tclass = c,\
57 .common_pts = common_##i##_perm_to_string,\
58 .common_base = b },
59#include "av_inherit.h"
60#undef S_
61};
62
63const struct selinux_class_perm selinux_class_perm = {
64 .av_perm_to_string = av_perm_to_string,
65 .av_pts_len = ARRAY_SIZE(av_perm_to_string),
66 .class_to_string = class_to_string,
67 .cts_len = ARRAY_SIZE(class_to_string),
68 .av_inherit = av_inherit,
69 .av_inherit_len = ARRAY_SIZE(av_inherit)
70};
71 35
72#define AVC_CACHE_SLOTS 512 36#define AVC_CACHE_SLOTS 512
73#define AVC_DEF_CACHE_THRESHOLD 512 37#define AVC_DEF_CACHE_THRESHOLD 512
@@ -139,52 +103,28 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
139 */ 103 */
140static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) 104static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
141{ 105{
142 const char **common_pts = NULL; 106 const char **perms;
143 u32 common_base = 0; 107 int i, perm;
144 int i, i2, perm;
145 108
146 if (av == 0) { 109 if (av == 0) {
147 audit_log_format(ab, " null"); 110 audit_log_format(ab, " null");
148 return; 111 return;
149 } 112 }
150 113
151 for (i = 0; i < ARRAY_SIZE(av_inherit); i++) { 114 perms = secclass_map[tclass-1].perms;
152 if (av_inherit[i].tclass == tclass) {
153 common_pts = av_inherit[i].common_pts;
154 common_base = av_inherit[i].common_base;
155 break;
156 }
157 }
158 115
159 audit_log_format(ab, " {"); 116 audit_log_format(ab, " {");
160 i = 0; 117 i = 0;
161 perm = 1; 118 perm = 1;
162 while (perm < common_base) { 119 while (i < (sizeof(av) * 8)) {
163 if (perm & av) { 120 if (perm & av) {
164 audit_log_format(ab, " %s", common_pts[i]); 121 audit_log_format(ab, " %s", perms[i]);
165 av &= ~perm; 122 av &= ~perm;
166 } 123 }
167 i++; 124 i++;
168 perm <<= 1; 125 perm <<= 1;
169 } 126 }
170 127
171 while (i < sizeof(av) * 8) {
172 if (perm & av) {
173 for (i2 = 0; i2 < ARRAY_SIZE(av_perm_to_string); i2++) {
174 if ((av_perm_to_string[i2].tclass == tclass) &&
175 (av_perm_to_string[i2].value == perm))
176 break;
177 }
178 if (i2 < ARRAY_SIZE(av_perm_to_string)) {
179 audit_log_format(ab, " %s",
180 av_perm_to_string[i2].name);
181 av &= ~perm;
182 }
183 }
184 i++;
185 perm <<= 1;
186 }
187
188 if (av) 128 if (av)
189 audit_log_format(ab, " 0x%x", av); 129 audit_log_format(ab, " 0x%x", av);
190 130
@@ -219,8 +159,8 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla
219 kfree(scontext); 159 kfree(scontext);
220 } 160 }
221 161
222 BUG_ON(tclass >= ARRAY_SIZE(class_to_string) || !class_to_string[tclass]); 162 BUG_ON(tclass >= ARRAY_SIZE(secclass_map));
223 audit_log_format(ab, " tclass=%s", class_to_string[tclass]); 163 audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name);
224} 164}
225 165
226/** 166/**