···2424#include "policydb.h"25252626static struct kmem_cache *avtab_node_cachep;2727+static struct kmem_cache *avtab_xperms_cachep;27282829/* Based on MurmurHash3, written by Austin Appleby and placed in the2930 * public domain.···7170 struct avtab_key *key, struct avtab_datum *datum)7271{7372 struct avtab_node *newnode;7373+ struct avtab_extended_perms *xperms;7474 newnode = kmem_cache_zalloc(avtab_node_cachep, GFP_KERNEL);7575 if (newnode == NULL)7676 return NULL;7777 newnode->key = *key;7878- newnode->datum = *datum;7878+7979+ if (key->specified & AVTAB_XPERMS) {8080+ xperms = kmem_cache_zalloc(avtab_xperms_cachep, GFP_KERNEL);8181+ if (xperms == NULL) {8282+ kmem_cache_free(avtab_node_cachep, newnode);8383+ return NULL;8484+ }8585+ *xperms = *(datum->u.xperms);8686+ newnode->datum.u.xperms = xperms;8787+ } else {8888+ newnode->datum.u.data = datum->u.data;8989+ }9090+7991 if (prev) {8092 newnode->next = prev->next;8193 prev->next = newnode;···121107 if (key->source_type == cur->key.source_type &&122108 key->target_type == cur->key.target_type &&123109 key->target_class == cur->key.target_class &&124124- (specified & cur->key.specified))110110+ (specified & cur->key.specified)) {111111+ /* extended perms may not be unique */112112+ if (specified & AVTAB_XPERMS)113113+ break;125114 return -EEXIST;115115+ }126116 if (key->source_type < cur->key.source_type)127117 break;128118 if (key->source_type == cur->key.source_type &&···289271 while (cur) {290272 temp = cur;291273 cur = cur->next;274274+ if (temp->key.specified & AVTAB_XPERMS)275275+ kmem_cache_free(avtab_xperms_cachep,276276+ temp->datum.u.xperms);292277 kmem_cache_free(avtab_node_cachep, temp);293278 }294279 }···380359 AVTAB_AUDITALLOW,381360 AVTAB_TRANSITION,382361 AVTAB_CHANGE,383383- AVTAB_MEMBER362362+ AVTAB_MEMBER,363363+ AVTAB_XPERMS_ALLOWED,364364+ AVTAB_XPERMS_AUDITALLOW,365365+ AVTAB_XPERMS_DONTAUDIT384366};385367386368int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,···393369{394370 __le16 buf16[4];395371 u16 enabled;396396- __le32 buf32[7];397372 u32 items, items2, val, vers = pol->policyvers;398373 struct avtab_key key;399374 struct avtab_datum datum;375375+ struct avtab_extended_perms xperms;376376+ __le32 buf32[ARRAY_SIZE(xperms.perms.p)];400377 int i, rc;401378 unsigned set;402379···454429 printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n");455430 return -EINVAL;456431 }432432+ if (val & AVTAB_XPERMS) {433433+ printk(KERN_ERR "SELinux: avtab: entry has extended permissions\n");434434+ return -EINVAL;435435+ }457436458437 for (i = 0; i < ARRAY_SIZE(spec_order); i++) {459438 if (val & spec_order[i]) {460439 key.specified = spec_order[i] | enabled;461461- datum.data = le32_to_cpu(buf32[items++]);440440+ datum.u.data = le32_to_cpu(buf32[items++]);462441 rc = insertf(a, &key, &datum, p);463442 if (rc)464443 return rc;···505476 return -EINVAL;506477 }507478508508- rc = next_entry(buf32, fp, sizeof(u32));509509- if (rc) {510510- printk(KERN_ERR "SELinux: avtab: truncated entry\n");511511- return rc;479479+ if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) &&480480+ (key.specified & AVTAB_XPERMS)) {481481+ printk(KERN_ERR "SELinux: avtab: policy version %u does not "482482+ "support extended permissions rules and one "483483+ "was specified\n", vers);484484+ return -EINVAL;485485+ } else if (key.specified & AVTAB_XPERMS) {486486+ memset(&xperms, 0, sizeof(struct avtab_extended_perms));487487+ rc = next_entry(&xperms.specified, fp, sizeof(u8));488488+ if (rc) {489489+ printk(KERN_ERR "SELinux: avtab: truncated entry\n");490490+ return rc;491491+ }492492+ rc = next_entry(&xperms.driver, fp, sizeof(u8));493493+ if (rc) {494494+ printk(KERN_ERR "SELinux: avtab: truncated entry\n");495495+ return rc;496496+ }497497+ rc = next_entry(buf32, fp, sizeof(u32)*ARRAY_SIZE(xperms.perms.p));498498+ if (rc) {499499+ printk(KERN_ERR "SELinux: avtab: truncated entry\n");500500+ return rc;501501+ }502502+ for (i = 0; i < ARRAY_SIZE(xperms.perms.p); i++)503503+ xperms.perms.p[i] = le32_to_cpu(buf32[i]);504504+ datum.u.xperms = &xperms;505505+ } else {506506+ rc = next_entry(buf32, fp, sizeof(u32));507507+ if (rc) {508508+ printk(KERN_ERR "SELinux: avtab: truncated entry\n");509509+ return rc;510510+ }511511+ datum.u.data = le32_to_cpu(*buf32);512512 }513513- datum.data = le32_to_cpu(*buf32);514513 if ((key.specified & AVTAB_TYPE) &&515515- !policydb_type_isvalid(pol, datum.data)) {514514+ !policydb_type_isvalid(pol, datum.u.data)) {516515 printk(KERN_ERR "SELinux: avtab: invalid type\n");517516 return -EINVAL;518517 }···600543int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp)601544{602545 __le16 buf16[4];603603- __le32 buf32[1];546546+ __le32 buf32[ARRAY_SIZE(cur->datum.u.xperms->perms.p)];604547 int rc;548548+ unsigned int i;605549606550 buf16[0] = cpu_to_le16(cur->key.source_type);607551 buf16[1] = cpu_to_le16(cur->key.target_type);···611553 rc = put_entry(buf16, sizeof(u16), 4, fp);612554 if (rc)613555 return rc;614614- buf32[0] = cpu_to_le32(cur->datum.data);615615- rc = put_entry(buf32, sizeof(u32), 1, fp);556556+557557+ if (cur->key.specified & AVTAB_XPERMS) {558558+ rc = put_entry(&cur->datum.u.xperms->specified, sizeof(u8), 1, fp);559559+ if (rc)560560+ return rc;561561+ rc = put_entry(&cur->datum.u.xperms->driver, sizeof(u8), 1, fp);562562+ if (rc)563563+ return rc;564564+ for (i = 0; i < ARRAY_SIZE(cur->datum.u.xperms->perms.p); i++)565565+ buf32[i] = cpu_to_le32(cur->datum.u.xperms->perms.p[i]);566566+ rc = put_entry(buf32, sizeof(u32),567567+ ARRAY_SIZE(cur->datum.u.xperms->perms.p), fp);568568+ } else {569569+ buf32[0] = cpu_to_le32(cur->datum.u.data);570570+ rc = put_entry(buf32, sizeof(u32), 1, fp);571571+ }616572 if (rc)617573 return rc;618574 return 0;···660588 avtab_node_cachep = kmem_cache_create("avtab_node",661589 sizeof(struct avtab_node),662590 0, SLAB_PANIC, NULL);591591+ avtab_xperms_cachep = kmem_cache_create("avtab_extended_perms",592592+ sizeof(struct avtab_extended_perms),593593+ 0, SLAB_PANIC, NULL);663594}664595665596void avtab_cache_destroy(void)666597{667598 kmem_cache_destroy(avtab_node_cachep);599599+ kmem_cache_destroy(avtab_xperms_cachep);668600}
+32-1
security/selinux/ss/avtab.h
···2323#ifndef _SS_AVTAB_H_2424#define _SS_AVTAB_H_25252626+#include "security.h"2627#include <linux/flex_array.h>27282829struct avtab_key {···3837#define AVTAB_MEMBER 0x00203938#define AVTAB_CHANGE 0x00404039#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)4040+/* extended permissions */4141+#define AVTAB_XPERMS_ALLOWED 0x01004242+#define AVTAB_XPERMS_AUDITALLOW 0x02004343+#define AVTAB_XPERMS_DONTAUDIT 0x04004444+#define AVTAB_XPERMS (AVTAB_XPERMS_ALLOWED | \4545+ AVTAB_XPERMS_AUDITALLOW | \4646+ AVTAB_XPERMS_DONTAUDIT)4147#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */4248#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */4349 u16 specified; /* what field is specified */4450};45515252+/*5353+ * For operations that require more than the 32 permissions provided by the avc5454+ * extended permissions may be used to provide 256 bits of permissions.5555+ */5656+struct avtab_extended_perms {5757+/* These are not flags. All 256 values may be used */5858+#define AVTAB_XPERMS_IOCTLFUNCTION 0x015959+#define AVTAB_XPERMS_IOCTLDRIVER 0x026060+ /* extension of the avtab_key specified */6161+ u8 specified; /* ioctl, netfilter, ... */6262+ /*6363+ * if 256 bits is not adequate as is often the case with ioctls, then6464+ * multiple extended perms may be used and the driver field6565+ * specifies which permissions are included.6666+ */6767+ u8 driver;6868+ /* 256 bits of permissions */6969+ struct extended_perms_data perms;7070+};7171+4672struct avtab_datum {4747- u32 data; /* access vector or type value */7373+ union {7474+ u32 data; /* access vector or type value */7575+ struct avtab_extended_perms *xperms;7676+ } u;4877};49785079struct avtab_node {
+30-8
security/selinux/ss/conditional.c
···15151616#include "security.h"1717#include "conditional.h"1818+#include "services.h"18191920/*2021 * cond_evaluate_expr evaluates a conditional expr···613612614613 return 0;615614}616616-/* Determine whether additional permissions are granted by the conditional617617- * av table, and if so, add them to the result618618- */619619-void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd)615615+616616+void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key,617617+ struct extended_perms_decision *xpermd)620618{621619 struct avtab_node *node;622620623623- if (!ctab || !key || !avd)621621+ if (!ctab || !key || !xpermd)622622+ return;623623+624624+ for (node = avtab_search_node(ctab, key); node;625625+ node = avtab_search_node_next(node, key->specified)) {626626+ if (node->key.specified & AVTAB_ENABLED)627627+ services_compute_xperms_decision(xpermd, node);628628+ }629629+ return;630630+631631+}632632+/* Determine whether additional permissions are granted by the conditional633633+ * av table, and if so, add them to the result634634+ */635635+void cond_compute_av(struct avtab *ctab, struct avtab_key *key,636636+ struct av_decision *avd, struct extended_perms *xperms)637637+{638638+ struct avtab_node *node;639639+640640+ if (!ctab || !key || !avd || !xperms)624641 return;625642626643 for (node = avtab_search_node(ctab, key); node;627644 node = avtab_search_node_next(node, key->specified)) {628645 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) ==629646 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))630630- avd->allowed |= node->datum.data;647647+ avd->allowed |= node->datum.u.data;631648 if ((u16)(AVTAB_AUDITDENY|AVTAB_ENABLED) ==632649 (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))633650 /* Since a '0' in an auditdeny mask represents a···653634 * the '&' operand to ensure that all '0's in the mask654635 * are retained (much unlike the allow and auditallow cases).655636 */656656- avd->auditdeny &= node->datum.data;637637+ avd->auditdeny &= node->datum.u.data;657638 if ((u16)(AVTAB_AUDITALLOW|AVTAB_ENABLED) ==658639 (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))659659- avd->auditallow |= node->datum.data;640640+ avd->auditallow |= node->datum.u.data;641641+ if ((node->key.specified & AVTAB_ENABLED) &&642642+ (node->key.specified & AVTAB_XPERMS))643643+ services_compute_xperms_drivers(xperms, node);660644 }661645 return;662646}