2222static struct avtab_node * get_avtab_node (struct policydb * db , struct avtab_key * key ,
2323 struct avtab_extended_perms * xperms );
2424
25+ static bool is_redundant_avtab_node (struct avtab_node * node );
26+
27+ static bool remove_avtab_node (struct policydb * db , struct avtab_node * node );
28+
2529static bool add_rule (struct policydb * db , const char * s , const char * t , const char * c , const char * p , int effect ,
2630 bool invert );
2731
28- static void add_rule_raw (struct policydb * db , struct type_datum * src , struct type_datum * tgt , struct class_datum * cls ,
32+ static bool add_rule_raw (struct policydb * db , struct type_datum * src , struct type_datum * tgt , struct class_datum * cls ,
2933 struct perm_datum * perm , int effect , bool invert );
3034
3135static void add_xperm_rule_raw (struct policydb * db , struct type_datum * src , struct type_datum * tgt ,
@@ -114,6 +118,8 @@ static struct avtab_node *get_avtab_node(struct policydb *db, struct avtab_key *
114118 }
115119 /* this is used to get the node - insertion is actually unique */
116120 node = avtab_insert_nonunique (& db -> te_avtab , key , & avdatum );
121+ if (!node )
122+ return NULL ;
117123
118124 int grow_size = sizeof (struct avtab_key );
119125 grow_size += sizeof (struct avtab_datum );
@@ -128,6 +134,61 @@ static struct avtab_node *get_avtab_node(struct policydb *db, struct avtab_key *
128134 return node ;
129135}
130136
137+ static bool is_redundant_avtab_node (struct avtab_node * node )
138+ {
139+ if (node -> key .specified & AVTAB_XPERMS )
140+ return node -> datum .u .xperms == NULL ;
141+ if (!(node -> key .specified & AVTAB_AV ))
142+ return false;
143+ if (node -> key .specified & AVTAB_AUDITDENY )
144+ return node -> datum .u .data == ~0U ;
145+ return node -> datum .u .data == 0U ;
146+ }
147+
148+ static bool remove_avtab_node (struct policydb * db , struct avtab_node * node )
149+ {
150+ int i ;
151+ int ret ;
152+ int shrink_size = sizeof (struct avtab_key ) + sizeof (struct avtab_datum );
153+ struct avtab removed = {};
154+ struct avtab_node * n ;
155+ struct avtab_node * prev ;
156+
157+ ret = avtab_alloc (& removed , 1 );
158+ if (ret < 0 )
159+ return false;
160+
161+ for (i = 0 ; i < db -> te_avtab .nslot ; i ++ ) {
162+ prev = NULL ;
163+ for (n = db -> te_avtab .htable [i ]; n ; prev = n , n = n -> next ) {
164+ if (n != node )
165+ continue ;
166+
167+ if (prev )
168+ prev -> next = n -> next ;
169+ else
170+ db -> te_avtab .htable [i ] = n -> next ;
171+
172+ if (db -> te_avtab .nel > 0 )
173+ db -> te_avtab .nel -- ;
174+
175+ if ((n -> key .specified & AVTAB_XPERMS ) && n -> datum .u .xperms ) {
176+ shrink_size += sizeof (u8 ) + sizeof (u8 ) + sizeof (u32 ) * ARRAY_SIZE (n -> datum .u .xperms -> perms .p );
177+ }
178+ n -> next = NULL ;
179+ removed .htable [0 ] = n ;
180+ removed .nel = 1 ;
181+ avtab_destroy (& removed );
182+ if (db -> len >= shrink_size )
183+ db -> len -= shrink_size ;
184+ return true;
185+ }
186+ }
187+
188+ avtab_destroy (& removed );
189+ return false;
190+ }
191+
131192static bool add_rule (struct policydb * db , const char * s , const char * t , const char * c , const char * p , int effect ,
132193 bool invert )
133194{
@@ -174,26 +235,27 @@ static bool add_rule(struct policydb *db, const char *s, const char *t, const ch
174235 return false;
175236 }
176237 }
177- add_rule_raw (db , src , tgt , cls , perm , effect , invert );
178- return true;
238+ return add_rule_raw (db , src , tgt , cls , perm , effect , invert );
179239}
180240
181- static void add_rule_raw (struct policydb * db , struct type_datum * src , struct type_datum * tgt , struct class_datum * cls ,
241+ static bool add_rule_raw (struct policydb * db , struct type_datum * src , struct type_datum * tgt , struct class_datum * cls ,
182242 struct perm_datum * perm , int effect , bool invert )
183243{
244+ bool success = true;
245+
184246 if (src == NULL ) {
185247 struct hashtab_node * node ;
186248 if (strip_av (effect , invert )) {
187249 ksu_hashtab_for_each (db -> p_types .table , node )
188250 {
189- add_rule_raw (db , (struct type_datum * )node -> datum , tgt , cls , perm , effect , invert );
251+ success &= add_rule_raw (db , (struct type_datum * )node -> datum , tgt , cls , perm , effect , invert );
190252 };
191253 } else {
192254 ksu_hashtab_for_each (db -> p_types .table , node )
193255 {
194256 struct type_datum * type = (struct type_datum * )(node -> datum );
195257 if (type -> attribute ) {
196- add_rule_raw (db , type , tgt , cls , perm , effect , invert );
258+ success &= add_rule_raw (db , type , tgt , cls , perm , effect , invert );
197259 }
198260 };
199261 }
@@ -202,31 +264,42 @@ static void add_rule_raw(struct policydb *db, struct type_datum *src, struct typ
202264 if (strip_av (effect , invert )) {
203265 ksu_hashtab_for_each (db -> p_types .table , node )
204266 {
205- add_rule_raw (db , src , (struct type_datum * )node -> datum , cls , perm , effect , invert );
267+ success &= add_rule_raw (db , src , (struct type_datum * )node -> datum , cls , perm , effect , invert );
206268 };
207269 } else {
208270 ksu_hashtab_for_each (db -> p_types .table , node )
209271 {
210272 struct type_datum * type = (struct type_datum * )(node -> datum );
211273 if (type -> attribute ) {
212- add_rule_raw (db , src , type , cls , perm , effect , invert );
274+ success &= add_rule_raw (db , src , type , cls , perm , effect , invert );
213275 }
214276 };
215277 }
216278 } else if (cls == NULL ) {
217279 struct hashtab_node * node ;
218280 ksu_hashtab_for_each (db -> p_classes .table , node )
219281 {
220- add_rule_raw (db , src , tgt , (struct class_datum * )node -> datum , perm , effect , invert );
282+ success &= add_rule_raw (db , src , tgt , (struct class_datum * )node -> datum , perm , effect , invert );
221283 }
222284 } else {
223285 struct avtab_key key ;
286+ struct avtab_node * node ;
287+
224288 key .source_type = src -> value ;
225289 key .target_type = tgt -> value ;
226290 key .target_class = cls -> value ;
227291 key .specified = effect ;
228292
229- struct avtab_node * node = get_avtab_node (db , & key , NULL );
293+ if (invert && effect != AVTAB_AUDITDENY ) {
294+ node = avtab_search_node (& db -> te_avtab , & key );
295+ if (!node )
296+ return true;
297+ } else {
298+ node = get_avtab_node (db , & key , NULL );
299+ if (!node )
300+ return false;
301+ }
302+
230303 if (invert ) {
231304 if (perm )
232305 node -> datum .u .data &= ~(1U << (perm -> value - 1 ));
@@ -238,7 +311,11 @@ static void add_rule_raw(struct policydb *db, struct type_datum *src, struct typ
238311 else
239312 node -> datum .u .data = ~0U ;
240313 }
314+ if (is_redundant_avtab_node (node ))
315+ return remove_avtab_node (db , node );
241316 }
317+
318+ return success ;
242319}
243320
244321#define ioctl_driver (x ) (x >> 8 & 0xFF)
@@ -410,6 +487,8 @@ static bool add_type_rule(struct policydb *db, const char *s, const char *t, con
410487 key .specified = effect ;
411488
412489 struct avtab_node * node = get_avtab_node (db , & key , NULL );
490+ if (!node )
491+ return false;
413492 node -> datum .u .data = def -> value ;
414493
415494 return true;
0 commit comments