11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Implementation of the access vector table type. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Author : Stephen Smalley, <sds@epoch.ncsc.mil> 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds /* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * Added conditional policy language extensions 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * Copyright (C) 2003 Tresys Technology, LLC 121da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 131da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 141da177e4SLinus Torvalds * the Free Software Foundation, version 2. 151da177e4SLinus Torvalds */ 161da177e4SLinus Torvalds 171da177e4SLinus Torvalds #include <linux/kernel.h> 181da177e4SLinus Torvalds #include <linux/slab.h> 191da177e4SLinus Torvalds #include <linux/vmalloc.h> 201da177e4SLinus Torvalds #include <linux/errno.h> 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds #include "avtab.h" 231da177e4SLinus Torvalds #include "policydb.h" 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds #define AVTAB_HASH(keyp) \ 261da177e4SLinus Torvalds ((keyp->target_class + \ 271da177e4SLinus Torvalds (keyp->target_type << 2) + \ 281da177e4SLinus Torvalds (keyp->source_type << 9)) & \ 291da177e4SLinus Torvalds AVTAB_HASH_MASK) 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds static kmem_cache_t *avtab_node_cachep; 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds static struct avtab_node* 341da177e4SLinus Torvalds avtab_insert_node(struct avtab *h, int hvalue, 351da177e4SLinus Torvalds struct avtab_node * prev, struct avtab_node * cur, 361da177e4SLinus Torvalds struct avtab_key *key, struct avtab_datum *datum) 371da177e4SLinus Torvalds { 381da177e4SLinus Torvalds struct avtab_node * newnode; 391da177e4SLinus Torvalds newnode = kmem_cache_alloc(avtab_node_cachep, SLAB_KERNEL); 401da177e4SLinus Torvalds if (newnode == NULL) 411da177e4SLinus Torvalds return NULL; 421da177e4SLinus Torvalds memset(newnode, 0, sizeof(struct avtab_node)); 431da177e4SLinus Torvalds newnode->key = *key; 441da177e4SLinus Torvalds newnode->datum = *datum; 451da177e4SLinus Torvalds if (prev) { 461da177e4SLinus Torvalds newnode->next = prev->next; 471da177e4SLinus Torvalds prev->next = newnode; 481da177e4SLinus Torvalds } else { 491da177e4SLinus Torvalds newnode->next = h->htable[hvalue]; 501da177e4SLinus Torvalds h->htable[hvalue] = newnode; 511da177e4SLinus Torvalds } 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds h->nel++; 541da177e4SLinus Torvalds return newnode; 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum) 581da177e4SLinus Torvalds { 591da177e4SLinus Torvalds int hvalue; 601da177e4SLinus Torvalds struct avtab_node *prev, *cur, *newnode; 61782ebb99SStephen Smalley u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds if (!h) 641da177e4SLinus Torvalds return -EINVAL; 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds hvalue = AVTAB_HASH(key); 671da177e4SLinus Torvalds for (prev = NULL, cur = h->htable[hvalue]; 681da177e4SLinus Torvalds cur; 691da177e4SLinus Torvalds prev = cur, cur = cur->next) { 701da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 711da177e4SLinus Torvalds key->target_type == cur->key.target_type && 721da177e4SLinus Torvalds key->target_class == cur->key.target_class && 73782ebb99SStephen Smalley (specified & cur->key.specified)) 741da177e4SLinus Torvalds return -EEXIST; 751da177e4SLinus Torvalds if (key->source_type < cur->key.source_type) 761da177e4SLinus Torvalds break; 771da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 781da177e4SLinus Torvalds key->target_type < cur->key.target_type) 791da177e4SLinus Torvalds break; 801da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 811da177e4SLinus Torvalds key->target_type == cur->key.target_type && 821da177e4SLinus Torvalds key->target_class < cur->key.target_class) 831da177e4SLinus Torvalds break; 841da177e4SLinus Torvalds } 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum); 871da177e4SLinus Torvalds if(!newnode) 881da177e4SLinus Torvalds return -ENOMEM; 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds return 0; 911da177e4SLinus Torvalds } 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds /* Unlike avtab_insert(), this function allow multiple insertions of the same 941da177e4SLinus Torvalds * key/specified mask into the table, as needed by the conditional avtab. 951da177e4SLinus Torvalds * It also returns a pointer to the node inserted. 961da177e4SLinus Torvalds */ 971da177e4SLinus Torvalds struct avtab_node * 981da177e4SLinus Torvalds avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_datum * datum) 991da177e4SLinus Torvalds { 1001da177e4SLinus Torvalds int hvalue; 1011da177e4SLinus Torvalds struct avtab_node *prev, *cur, *newnode; 102782ebb99SStephen Smalley u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds if (!h) 1051da177e4SLinus Torvalds return NULL; 1061da177e4SLinus Torvalds hvalue = AVTAB_HASH(key); 1071da177e4SLinus Torvalds for (prev = NULL, cur = h->htable[hvalue]; 1081da177e4SLinus Torvalds cur; 1091da177e4SLinus Torvalds prev = cur, cur = cur->next) { 1101da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 1111da177e4SLinus Torvalds key->target_type == cur->key.target_type && 1121da177e4SLinus Torvalds key->target_class == cur->key.target_class && 113782ebb99SStephen Smalley (specified & cur->key.specified)) 1141da177e4SLinus Torvalds break; 1151da177e4SLinus Torvalds if (key->source_type < cur->key.source_type) 1161da177e4SLinus Torvalds break; 1171da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 1181da177e4SLinus Torvalds key->target_type < cur->key.target_type) 1191da177e4SLinus Torvalds break; 1201da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 1211da177e4SLinus Torvalds key->target_type == cur->key.target_type && 1221da177e4SLinus Torvalds key->target_class < cur->key.target_class) 1231da177e4SLinus Torvalds break; 1241da177e4SLinus Torvalds } 1251da177e4SLinus Torvalds newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum); 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds return newnode; 1281da177e4SLinus Torvalds } 1291da177e4SLinus Torvalds 130782ebb99SStephen Smalley struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) 1311da177e4SLinus Torvalds { 1321da177e4SLinus Torvalds int hvalue; 1331da177e4SLinus Torvalds struct avtab_node *cur; 134782ebb99SStephen Smalley u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds if (!h) 1371da177e4SLinus Torvalds return NULL; 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds hvalue = AVTAB_HASH(key); 1401da177e4SLinus Torvalds for (cur = h->htable[hvalue]; cur; cur = cur->next) { 1411da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 1421da177e4SLinus Torvalds key->target_type == cur->key.target_type && 1431da177e4SLinus Torvalds key->target_class == cur->key.target_class && 144782ebb99SStephen Smalley (specified & cur->key.specified)) 1451da177e4SLinus Torvalds return &cur->datum; 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds if (key->source_type < cur->key.source_type) 1481da177e4SLinus Torvalds break; 1491da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 1501da177e4SLinus Torvalds key->target_type < cur->key.target_type) 1511da177e4SLinus Torvalds break; 1521da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 1531da177e4SLinus Torvalds key->target_type == cur->key.target_type && 1541da177e4SLinus Torvalds key->target_class < cur->key.target_class) 1551da177e4SLinus Torvalds break; 1561da177e4SLinus Torvalds } 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds return NULL; 1591da177e4SLinus Torvalds } 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds /* This search function returns a node pointer, and can be used in 1621da177e4SLinus Torvalds * conjunction with avtab_search_next_node() 1631da177e4SLinus Torvalds */ 1641da177e4SLinus Torvalds struct avtab_node* 165782ebb99SStephen Smalley avtab_search_node(struct avtab *h, struct avtab_key *key) 1661da177e4SLinus Torvalds { 1671da177e4SLinus Torvalds int hvalue; 1681da177e4SLinus Torvalds struct avtab_node *cur; 169782ebb99SStephen Smalley u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds if (!h) 1721da177e4SLinus Torvalds return NULL; 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds hvalue = AVTAB_HASH(key); 1751da177e4SLinus Torvalds for (cur = h->htable[hvalue]; cur; cur = cur->next) { 1761da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 1771da177e4SLinus Torvalds key->target_type == cur->key.target_type && 1781da177e4SLinus Torvalds key->target_class == cur->key.target_class && 179782ebb99SStephen Smalley (specified & cur->key.specified)) 1801da177e4SLinus Torvalds return cur; 1811da177e4SLinus Torvalds 1821da177e4SLinus Torvalds if (key->source_type < cur->key.source_type) 1831da177e4SLinus Torvalds break; 1841da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 1851da177e4SLinus Torvalds key->target_type < cur->key.target_type) 1861da177e4SLinus Torvalds break; 1871da177e4SLinus Torvalds if (key->source_type == cur->key.source_type && 1881da177e4SLinus Torvalds key->target_type == cur->key.target_type && 1891da177e4SLinus Torvalds key->target_class < cur->key.target_class) 1901da177e4SLinus Torvalds break; 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds return NULL; 1931da177e4SLinus Torvalds } 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds struct avtab_node* 1961da177e4SLinus Torvalds avtab_search_node_next(struct avtab_node *node, int specified) 1971da177e4SLinus Torvalds { 1981da177e4SLinus Torvalds struct avtab_node *cur; 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds if (!node) 2011da177e4SLinus Torvalds return NULL; 2021da177e4SLinus Torvalds 203782ebb99SStephen Smalley specified &= ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 2041da177e4SLinus Torvalds for (cur = node->next; cur; cur = cur->next) { 2051da177e4SLinus Torvalds if (node->key.source_type == cur->key.source_type && 2061da177e4SLinus Torvalds node->key.target_type == cur->key.target_type && 2071da177e4SLinus Torvalds node->key.target_class == cur->key.target_class && 208782ebb99SStephen Smalley (specified & cur->key.specified)) 2091da177e4SLinus Torvalds return cur; 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds if (node->key.source_type < cur->key.source_type) 2121da177e4SLinus Torvalds break; 2131da177e4SLinus Torvalds if (node->key.source_type == cur->key.source_type && 2141da177e4SLinus Torvalds node->key.target_type < cur->key.target_type) 2151da177e4SLinus Torvalds break; 2161da177e4SLinus Torvalds if (node->key.source_type == cur->key.source_type && 2171da177e4SLinus Torvalds node->key.target_type == cur->key.target_type && 2181da177e4SLinus Torvalds node->key.target_class < cur->key.target_class) 2191da177e4SLinus Torvalds break; 2201da177e4SLinus Torvalds } 2211da177e4SLinus Torvalds return NULL; 2221da177e4SLinus Torvalds } 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds void avtab_destroy(struct avtab *h) 2251da177e4SLinus Torvalds { 2261da177e4SLinus Torvalds int i; 2271da177e4SLinus Torvalds struct avtab_node *cur, *temp; 2281da177e4SLinus Torvalds 2291da177e4SLinus Torvalds if (!h || !h->htable) 2301da177e4SLinus Torvalds return; 2311da177e4SLinus Torvalds 2321da177e4SLinus Torvalds for (i = 0; i < AVTAB_SIZE; i++) { 2331da177e4SLinus Torvalds cur = h->htable[i]; 2341da177e4SLinus Torvalds while (cur != NULL) { 2351da177e4SLinus Torvalds temp = cur; 2361da177e4SLinus Torvalds cur = cur->next; 2371da177e4SLinus Torvalds kmem_cache_free(avtab_node_cachep, temp); 2381da177e4SLinus Torvalds } 2391da177e4SLinus Torvalds h->htable[i] = NULL; 2401da177e4SLinus Torvalds } 2411da177e4SLinus Torvalds vfree(h->htable); 2421da177e4SLinus Torvalds h->htable = NULL; 2431da177e4SLinus Torvalds } 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds int avtab_init(struct avtab *h) 2471da177e4SLinus Torvalds { 2481da177e4SLinus Torvalds int i; 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds h->htable = vmalloc(sizeof(*(h->htable)) * AVTAB_SIZE); 2511da177e4SLinus Torvalds if (!h->htable) 2521da177e4SLinus Torvalds return -ENOMEM; 2531da177e4SLinus Torvalds for (i = 0; i < AVTAB_SIZE; i++) 2541da177e4SLinus Torvalds h->htable[i] = NULL; 2551da177e4SLinus Torvalds h->nel = 0; 2561da177e4SLinus Torvalds return 0; 2571da177e4SLinus Torvalds } 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds void avtab_hash_eval(struct avtab *h, char *tag) 2601da177e4SLinus Torvalds { 2611da177e4SLinus Torvalds int i, chain_len, slots_used, max_chain_len; 2621da177e4SLinus Torvalds struct avtab_node *cur; 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds slots_used = 0; 2651da177e4SLinus Torvalds max_chain_len = 0; 2661da177e4SLinus Torvalds for (i = 0; i < AVTAB_SIZE; i++) { 2671da177e4SLinus Torvalds cur = h->htable[i]; 2681da177e4SLinus Torvalds if (cur) { 2691da177e4SLinus Torvalds slots_used++; 2701da177e4SLinus Torvalds chain_len = 0; 2711da177e4SLinus Torvalds while (cur) { 2721da177e4SLinus Torvalds chain_len++; 2731da177e4SLinus Torvalds cur = cur->next; 2741da177e4SLinus Torvalds } 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds if (chain_len > max_chain_len) 2771da177e4SLinus Torvalds max_chain_len = chain_len; 2781da177e4SLinus Torvalds } 2791da177e4SLinus Torvalds } 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds printk(KERN_INFO "%s: %d entries and %d/%d buckets used, longest " 2821da177e4SLinus Torvalds "chain length %d\n", tag, h->nel, slots_used, AVTAB_SIZE, 2831da177e4SLinus Torvalds max_chain_len); 2841da177e4SLinus Torvalds } 2851da177e4SLinus Torvalds 286782ebb99SStephen Smalley static uint16_t spec_order[] = { 287782ebb99SStephen Smalley AVTAB_ALLOWED, 288782ebb99SStephen Smalley AVTAB_AUDITDENY, 289782ebb99SStephen Smalley AVTAB_AUDITALLOW, 290782ebb99SStephen Smalley AVTAB_TRANSITION, 291782ebb99SStephen Smalley AVTAB_CHANGE, 292782ebb99SStephen Smalley AVTAB_MEMBER 293782ebb99SStephen Smalley }; 294782ebb99SStephen Smalley 295782ebb99SStephen Smalley int avtab_read_item(void *fp, u32 vers, struct avtab *a, 296782ebb99SStephen Smalley int (*insertf)(struct avtab *a, struct avtab_key *k, 297782ebb99SStephen Smalley struct avtab_datum *d, void *p), 298782ebb99SStephen Smalley void *p) 2991da177e4SLinus Torvalds { 300b5bf6c55SAlexey Dobriyan __le16 buf16[4]; 301b5bf6c55SAlexey Dobriyan u16 enabled; 302b5bf6c55SAlexey Dobriyan __le32 buf32[7]; 303b5bf6c55SAlexey Dobriyan u32 items, items2, val; 304782ebb99SStephen Smalley struct avtab_key key; 305782ebb99SStephen Smalley struct avtab_datum datum; 306782ebb99SStephen Smalley int i, rc; 3071da177e4SLinus Torvalds 308782ebb99SStephen Smalley memset(&key, 0, sizeof(struct avtab_key)); 309782ebb99SStephen Smalley memset(&datum, 0, sizeof(struct avtab_datum)); 3101da177e4SLinus Torvalds 311782ebb99SStephen Smalley if (vers < POLICYDB_VERSION_AVTAB) { 312782ebb99SStephen Smalley rc = next_entry(buf32, fp, sizeof(u32)); 3131da177e4SLinus Torvalds if (rc < 0) { 3141da177e4SLinus Torvalds printk(KERN_ERR "security: avtab: truncated entry\n"); 315782ebb99SStephen Smalley return -1; 3161da177e4SLinus Torvalds } 317782ebb99SStephen Smalley items2 = le32_to_cpu(buf32[0]); 318782ebb99SStephen Smalley if (items2 > ARRAY_SIZE(buf32)) { 3191da177e4SLinus Torvalds printk(KERN_ERR "security: avtab: entry overflow\n"); 320782ebb99SStephen Smalley return -1; 321782ebb99SStephen Smalley 3221da177e4SLinus Torvalds } 323782ebb99SStephen Smalley rc = next_entry(buf32, fp, sizeof(u32)*items2); 3241da177e4SLinus Torvalds if (rc < 0) { 3251da177e4SLinus Torvalds printk(KERN_ERR "security: avtab: truncated entry\n"); 326782ebb99SStephen Smalley return -1; 3271da177e4SLinus Torvalds } 3281da177e4SLinus Torvalds items = 0; 3291da177e4SLinus Torvalds 330782ebb99SStephen Smalley val = le32_to_cpu(buf32[items++]); 331782ebb99SStephen Smalley key.source_type = (u16)val; 332782ebb99SStephen Smalley if (key.source_type != val) { 333782ebb99SStephen Smalley printk("security: avtab: truncated source type\n"); 334782ebb99SStephen Smalley return -1; 335782ebb99SStephen Smalley } 336782ebb99SStephen Smalley val = le32_to_cpu(buf32[items++]); 337782ebb99SStephen Smalley key.target_type = (u16)val; 338782ebb99SStephen Smalley if (key.target_type != val) { 339782ebb99SStephen Smalley printk("security: avtab: truncated target type\n"); 340782ebb99SStephen Smalley return -1; 341782ebb99SStephen Smalley } 342782ebb99SStephen Smalley val = le32_to_cpu(buf32[items++]); 343782ebb99SStephen Smalley key.target_class = (u16)val; 344782ebb99SStephen Smalley if (key.target_class != val) { 345782ebb99SStephen Smalley printk("security: avtab: truncated target class\n"); 3461da177e4SLinus Torvalds return -1; 3471da177e4SLinus Torvalds } 3481da177e4SLinus Torvalds 349782ebb99SStephen Smalley val = le32_to_cpu(buf32[items++]); 350782ebb99SStephen Smalley enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; 351782ebb99SStephen Smalley 352782ebb99SStephen Smalley if (!(val & (AVTAB_AV | AVTAB_TYPE))) { 353782ebb99SStephen Smalley printk("security: avtab: null entry\n"); 354782ebb99SStephen Smalley return -1; 355782ebb99SStephen Smalley } 356782ebb99SStephen Smalley if ((val & AVTAB_AV) && 357782ebb99SStephen Smalley (val & AVTAB_TYPE)) { 358782ebb99SStephen Smalley printk("security: avtab: entry has both access vectors and types\n"); 359782ebb99SStephen Smalley return -1; 360782ebb99SStephen Smalley } 361782ebb99SStephen Smalley 36232725ad8STobias Klauser for (i = 0; i < ARRAY_SIZE(spec_order); i++) { 363782ebb99SStephen Smalley if (val & spec_order[i]) { 364782ebb99SStephen Smalley key.specified = spec_order[i] | enabled; 365782ebb99SStephen Smalley datum.data = le32_to_cpu(buf32[items++]); 366782ebb99SStephen Smalley rc = insertf(a, &key, &datum, p); 367782ebb99SStephen Smalley if (rc) return rc; 368782ebb99SStephen Smalley } 369782ebb99SStephen Smalley } 370782ebb99SStephen Smalley 371782ebb99SStephen Smalley if (items != items2) { 372782ebb99SStephen Smalley printk("security: avtab: entry only had %d items, expected %d\n", items2, items); 373782ebb99SStephen Smalley return -1; 374782ebb99SStephen Smalley } 375782ebb99SStephen Smalley return 0; 376782ebb99SStephen Smalley } 377782ebb99SStephen Smalley 378782ebb99SStephen Smalley rc = next_entry(buf16, fp, sizeof(u16)*4); 379782ebb99SStephen Smalley if (rc < 0) { 380782ebb99SStephen Smalley printk("security: avtab: truncated entry\n"); 381782ebb99SStephen Smalley return -1; 382782ebb99SStephen Smalley } 383782ebb99SStephen Smalley 384782ebb99SStephen Smalley items = 0; 385782ebb99SStephen Smalley key.source_type = le16_to_cpu(buf16[items++]); 386782ebb99SStephen Smalley key.target_type = le16_to_cpu(buf16[items++]); 387782ebb99SStephen Smalley key.target_class = le16_to_cpu(buf16[items++]); 388782ebb99SStephen Smalley key.specified = le16_to_cpu(buf16[items++]); 389782ebb99SStephen Smalley 390782ebb99SStephen Smalley rc = next_entry(buf32, fp, sizeof(u32)); 391782ebb99SStephen Smalley if (rc < 0) { 392782ebb99SStephen Smalley printk("security: avtab: truncated entry\n"); 393782ebb99SStephen Smalley return -1; 394782ebb99SStephen Smalley } 395782ebb99SStephen Smalley datum.data = le32_to_cpu(*buf32); 396782ebb99SStephen Smalley return insertf(a, &key, &datum, p); 397782ebb99SStephen Smalley } 398782ebb99SStephen Smalley 399782ebb99SStephen Smalley static int avtab_insertf(struct avtab *a, struct avtab_key *k, 400782ebb99SStephen Smalley struct avtab_datum *d, void *p) 401782ebb99SStephen Smalley { 402782ebb99SStephen Smalley return avtab_insert(a, k, d); 403782ebb99SStephen Smalley } 404782ebb99SStephen Smalley 405782ebb99SStephen Smalley int avtab_read(struct avtab *a, void *fp, u32 vers) 4061da177e4SLinus Torvalds { 4071da177e4SLinus Torvalds int rc; 408b5bf6c55SAlexey Dobriyan __le32 buf[1]; 4091da177e4SLinus Torvalds u32 nel, i; 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds 4121da177e4SLinus Torvalds rc = next_entry(buf, fp, sizeof(u32)); 4131da177e4SLinus Torvalds if (rc < 0) { 4141da177e4SLinus Torvalds printk(KERN_ERR "security: avtab: truncated table\n"); 4151da177e4SLinus Torvalds goto bad; 4161da177e4SLinus Torvalds } 4171da177e4SLinus Torvalds nel = le32_to_cpu(buf[0]); 4181da177e4SLinus Torvalds if (!nel) { 4191da177e4SLinus Torvalds printk(KERN_ERR "security: avtab: table is empty\n"); 4201da177e4SLinus Torvalds rc = -EINVAL; 4211da177e4SLinus Torvalds goto bad; 4221da177e4SLinus Torvalds } 4231da177e4SLinus Torvalds for (i = 0; i < nel; i++) { 424782ebb99SStephen Smalley rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL); 4251da177e4SLinus Torvalds if (rc) { 4261da177e4SLinus Torvalds if (rc == -ENOMEM) 4271da177e4SLinus Torvalds printk(KERN_ERR "security: avtab: out of memory\n"); 428782ebb99SStephen Smalley else if (rc == -EEXIST) 4291da177e4SLinus Torvalds printk(KERN_ERR "security: avtab: duplicate entry\n"); 430782ebb99SStephen Smalley else 431782ebb99SStephen Smalley rc = -EINVAL; 4321da177e4SLinus Torvalds goto bad; 4331da177e4SLinus Torvalds } 4341da177e4SLinus Torvalds } 4351da177e4SLinus Torvalds 4361da177e4SLinus Torvalds rc = 0; 4371da177e4SLinus Torvalds out: 4381da177e4SLinus Torvalds return rc; 4391da177e4SLinus Torvalds 4401da177e4SLinus Torvalds bad: 4411da177e4SLinus Torvalds avtab_destroy(a); 4421da177e4SLinus Torvalds goto out; 4431da177e4SLinus Torvalds } 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds void avtab_cache_init(void) 4461da177e4SLinus Torvalds { 4471da177e4SLinus Torvalds avtab_node_cachep = kmem_cache_create("avtab_node", 4481da177e4SLinus Torvalds sizeof(struct avtab_node), 4491da177e4SLinus Torvalds 0, SLAB_PANIC, NULL, NULL); 4501da177e4SLinus Torvalds } 4511da177e4SLinus Torvalds 4521da177e4SLinus Torvalds void avtab_cache_destroy(void) 4531da177e4SLinus Torvalds { 4541da177e4SLinus Torvalds kmem_cache_destroy (avtab_node_cachep); 4551da177e4SLinus Torvalds } 456