diff options
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/avc.c | 4 | ||||
-rw-r--r-- | security/selinux/hooks.c | 178 | ||||
-rw-r--r-- | security/selinux/include/security.h | 3 | ||||
-rw-r--r-- | security/selinux/ss/avtab.c | 196 | ||||
-rw-r--r-- | security/selinux/ss/avtab.h | 37 | ||||
-rw-r--r-- | security/selinux/ss/conditional.c | 215 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.c | 5 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.h | 30 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 42 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 107 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 3 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 76 |
12 files changed, 509 insertions, 387 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 451502467a9..cf6020f8540 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -490,7 +490,7 @@ out: } static inline void avc_print_ipv6_addr(struct audit_buffer *ab, - struct in6_addr *addr, u16 port, + struct in6_addr *addr, __be16 port, char *name1, char *name2) { if (!ipv6_addr_any(addr)) @@ -501,7 +501,7 @@ static inline void avc_print_ipv6_addr(struct audit_buffer *ab, } static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr, - u16 port, char *name1, char *name2) + __be16 port, char *name1, char *name2) { if (addr) audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr)); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8641f8894b4..f40c8221ec1 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1265,85 +1265,6 @@ static int inode_security_set_sid(struct inode *inode, u32 sid) return 0; } -/* Set the security attributes on a newly created file. */ -static int post_create(struct inode *dir, - struct dentry *dentry) -{ - - struct task_security_struct *tsec; - struct inode *inode; - struct inode_security_struct *dsec; - struct superblock_security_struct *sbsec; - u32 newsid; - char *context; - unsigned int len; - int rc; - - tsec = current->security; - dsec = dir->i_security; - sbsec = dir->i_sb->s_security; - - inode = dentry->d_inode; - if (!inode) { - /* Some file system types (e.g. NFS) may not instantiate - a dentry for all create operations (e.g. symlink), - so we have to check to see if the inode is non-NULL. */ - printk(KERN_WARNING "post_create: no inode, dir (dev=%s, " - "ino=%ld)\n", dir->i_sb->s_id, dir->i_ino); - return 0; - } - - if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { - newsid = tsec->create_sid; - } else { - rc = security_transition_sid(tsec->sid, dsec->sid, - inode_mode_to_security_class(inode->i_mode), - &newsid); - if (rc) { - printk(KERN_WARNING "post_create: " - "security_transition_sid failed, rc=%d (dev=%s " - "ino=%ld)\n", - -rc, inode->i_sb->s_id, inode->i_ino); - return rc; - } - } - - rc = inode_security_set_sid(inode, newsid); - if (rc) { - printk(KERN_WARNING "post_create: inode_security_set_sid " - "failed, rc=%d (dev=%s ino=%ld)\n", - -rc, inode->i_sb->s_id, inode->i_ino); - return rc; - } - - if (sbsec->behavior == SECURITY_FS_USE_XATTR && - inode->i_op->setxattr) { - /* Use extended attributes. */ - rc = security_sid_to_context(newsid, &context, &len); - if (rc) { - printk(KERN_WARNING "post_create: sid_to_context " - "failed, rc=%d (dev=%s ino=%ld)\n", - -rc, inode->i_sb->s_id, inode->i_ino); - return rc; - } - down(&inode->i_sem); - rc = inode->i_op->setxattr(dentry, - XATTR_NAME_SELINUX, - context, len, 0); - up(&inode->i_sem); - kfree(context); - if (rc < 0) { - printk(KERN_WARNING "post_create: setxattr failed, " - "rc=%d (dev=%s ino=%ld)\n", - -rc, inode->i_sb->s_id, inode->i_ino); - return rc; - } - } - - return 0; -} - - /* Hook functions begin here. */ static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) @@ -1673,6 +1594,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) struct avc_audit_data ad; struct file *file, *devnull = NULL; struct tty_struct *tty = current->signal->tty; + struct fdtable *fdt; long j = -1; if (tty) { @@ -1706,9 +1628,10 @@ static inline void flush_unauthorized_files(struct files_struct * files) j++; i = j * __NFDBITS; - if (i >= files->max_fds || i >= files->max_fdset) + fdt = files_fdtable(files); + if (i >= fdt->max_fds || i >= fdt->max_fdset) break; - set = files->open_fds->fds_bits[j]; + set = fdt->open_fds->fds_bits[j]; if (!set) continue; spin_unlock(&files->file_lock); @@ -1729,7 +1652,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) continue; } if (devnull) { - atomic_inc(&devnull->f_count); + rcuref_inc(&devnull->f_count); } else { devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); if (!devnull) { @@ -2018,14 +1941,64 @@ static void selinux_inode_free_security(struct inode *inode) inode_free_security(inode); } -static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) +static int selinux_inode_init_security(struct inode *inode, struct inode *dir, + char **name, void **value, + size_t *len) { - return may_create(dir, dentry, SECCLASS_FILE); + struct task_security_struct *tsec; + struct inode_security_struct *dsec; + struct superblock_security_struct *sbsec; + struct inode_security_struct *isec; + u32 newsid, clen; + int rc; + char *namep = NULL, *context; + + tsec = current->security; + dsec = dir->i_security; + sbsec = dir->i_sb->s_security; + isec = inode->i_security; + + if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { + newsid = tsec->create_sid; + } else { + rc = security_transition_sid(tsec->sid, dsec->sid, + inode_mode_to_security_class(inode->i_mode), + &newsid); + if (rc) { + printk(KERN_WARNING "%s: " + "security_transition_sid failed, rc=%d (dev=%s " + "ino=%ld)\n", + __FUNCTION__, + -rc, inode->i_sb->s_id, inode->i_ino); + return rc; + } + } + + inode_security_set_sid(inode, newsid); + + if (name) { + namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL); + if (!namep) + return -ENOMEM; + *name = namep; + } + + if (value && len) { + rc = security_sid_to_context(newsid, &context, &clen); + if (rc) { + kfree(namep); + return rc; + } + *value = context; + *len = clen; + } + + return 0; } -static void selinux_inode_post_create(struct inode *dir, struct dentry *dentry, int mask) +static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) { - post_create(dir, dentry); + return may_create(dir, dentry, SECCLASS_FILE); } static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) @@ -2038,11 +2011,6 @@ static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, stru return may_link(dir, old_dentry, MAY_LINK); } -static void selinux_inode_post_link(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry) -{ - return; -} - static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) { int rc; @@ -2058,21 +2026,11 @@ static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const return may_create(dir, dentry, SECCLASS_LNK_FILE); } -static void selinux_inode_post_symlink(struct inode *dir, struct dentry *dentry, const char *name) -{ - post_create(dir, dentry); -} - static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) { return may_create(dir, dentry, SECCLASS_DIR); } -static void selinux_inode_post_mkdir(struct inode *dir, struct dentry *dentry, int mask) -{ - post_create(dir, dentry); -} - static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) { return may_link(dir, dentry, MAY_RMDIR); @@ -2089,23 +2047,12 @@ static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mod return may_create(dir, dentry, inode_mode_to_security_class(mode)); } -static void selinux_inode_post_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) -{ - post_create(dir, dentry); -} - static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry) { return may_rename(old_inode, old_dentry, new_inode, new_dentry); } -static void selinux_inode_post_rename(struct inode *old_inode, struct dentry *old_dentry, - struct inode *new_inode, struct dentry *new_dentry) -{ - return; -} - static int selinux_inode_readlink(struct dentry *dentry) { return dentry_has_perm(current, NULL, dentry, FILE__READ); @@ -4298,20 +4245,15 @@ static struct security_operations selinux_ops = { .inode_alloc_security = selinux_inode_alloc_security, .inode_free_security = selinux_inode_free_security, + .inode_init_security = selinux_inode_init_security, .inode_create = selinux_inode_create, - .inode_post_create = selinux_inode_post_create, .inode_link = selinux_inode_link, - .inode_post_link = selinux_inode_post_link, .inode_unlink = selinux_inode_unlink, .inode_symlink = selinux_inode_symlink, - .inode_post_symlink = selinux_inode_post_symlink, .inode_mkdir = selinux_inode_mkdir, - .inode_post_mkdir = selinux_inode_post_mkdir, .inode_rmdir = selinux_inode_rmdir, .inode_mknod = selinux_inode_mknod, - .inode_post_mknod = selinux_inode_post_mknod, .inode_rename = selinux_inode_rename, - .inode_post_rename = selinux_inode_post_rename, .inode_readlink = selinux_inode_readlink, .inode_follow_link = selinux_inode_follow_link, .inode_permission = selinux_inode_permission, diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 71c0a19c975..5f016c98056 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -23,10 +23,11 @@ #define POLICYDB_VERSION_NLCLASS 18 #define POLICYDB_VERSION_VALIDATETRANS 19 #define POLICYDB_VERSION_MLS 19 +#define POLICYDB_VERSION_AVTAB 20 /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_MLS +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM extern int selinux_enabled; diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index f238c034c44..dde094feb20 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -58,6 +58,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat { int hvalue; struct avtab_node *prev, *cur, *newnode; + u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); if (!h) return -EINVAL; @@ -69,7 +70,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && - (datum->specified & cur->datum.specified)) + (specified & cur->key.specified)) return -EEXIST; if (key->source_type < cur->key.source_type) break; @@ -98,6 +99,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da { int hvalue; struct avtab_node *prev, *cur, *newnode; + u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); if (!h) return NULL; @@ -108,7 +110,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && - (datum->specified & cur->datum.specified)) + (specified & cur->key.specified)) break; if (key->source_type < cur->key.source_type) break; @@ -125,10 +127,11 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da return newnode; } -struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified) +struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) { int hvalue; struct avtab_node *cur; + u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); if (!h) return NULL; @@ -138,7 +141,7 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int spe if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && - (specified & cur->datum.specified)) + (specified & cur->key.specified)) return &cur->datum; if (key->source_type < cur->key.source_type) @@ -159,10 +162,11 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int spe * conjunction with avtab_search_next_node() */ struct avtab_node* -avtab_search_node(struct avtab *h, struct avtab_key *key, int specified) +avtab_search_node(struct avtab *h, struct avtab_key *key) { int hvalue; struct avtab_node *cur; + u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); if (!h) return NULL; @@ -172,7 +176,7 @@ avtab_search_node(struct avtab *h, struct avtab_key *key, int specified) if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && - (specified & cur->datum.specified)) + (specified & cur->key.specified)) return cur; if (key->source_type < cur->key.source_type) @@ -196,11 +200,12 @@ avtab_search_node_next(struct avtab_node *node, int specified) if (!node) return NULL; + specified &= ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); for (cur = node->next; cur; cur = cur->next) { if (node->key.source_type == cur->key.source_type && node->key.target_type == cur->key.target_type && node->key.target_class == cur->key.target_class && - (specified & cur->datum.specified)) + (specified & cur->key.specified)) return cur; if (node->key.source_type < cur->key.source_type) @@ -278,76 +283,129 @@ void avtab_hash_eval(struct avtab *h, char *tag) max_chain_len); } -int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey) +static uint16_t spec_order[] = { + AVTAB_ALLOWED, + AVTAB_AUDITDENY, + AVTAB_AUDITALLOW, + AVTAB_TRANSITION, + AVTAB_CHANGE, + AVTAB_MEMBER +}; + +int avtab_read_item(void *fp, u32 vers, struct avtab *a, + int (*insertf)(struct avtab *a, struct avtab_key *k, + struct avtab_datum *d, void *p), + void *p) { - u32 buf[7]; - u32 items, items2; - int rc; + __le16 buf16[4]; + u16 enabled; + __le32 buf32[7]; + u32 items, items2, val; + struct avtab_key key; + struct avtab_datum datum; + int i, rc; + + memset(&key, 0, sizeof(struct avtab_key)); + memset(&datum, 0, sizeof(struct avtab_datum)); + + if (vers < POLICYDB_VERSION_AVTAB) { + rc = next_entry(buf32, fp, sizeof(u32)); + if (rc < 0) { + printk(KERN_ERR "security: avtab: truncated entry\n"); + return -1; + } + items2 = le32_to_cpu(buf32[0]); + if (items2 > ARRAY_SIZE(buf32)) { + printk(KERN_ERR "security: avtab: entry overflow\n"); + return -1; - memset(avkey, 0, sizeof(struct avtab_key)); - memset(avdatum, 0, sizeof(struct avtab_datum)); + } + rc = next_entry(buf32, fp, sizeof(u32)*items2); + if (rc < 0) { + printk(KERN_ERR "security: avtab: truncated entry\n"); + return -1; + } + items = 0; - rc = next_entry(buf, fp, sizeof(u32)); - if (rc < 0) { - printk(KERN_ERR "security: avtab: truncated entry\n"); - goto bad; - } - items2 = le32_to_cpu(buf[0]); - if (items2 > ARRAY_SIZE(buf)) { - printk(KERN_ERR "security: avtab: entry overflow\n"); - goto bad; + val = le32_to_cpu(buf32[items++]); + key.source_type = (u16)val; + if (key.source_type != val) { + printk("security: avtab: truncated source type\n"); + return -1; + } + val = le32_to_cpu(buf32[items++]); + key.target_type = (u16)val; + if (key.target_type != val) { + printk("security: avtab: truncated target type\n"); + return -1; + } + val = le32_to_cpu(buf32[items++]); + key.target_class = (u16)val; + if (key.target_class != val) { + printk("security: avtab: truncated target class\n"); + return -1; + } + + val = le32_to_cpu(buf32[items++]); + enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; + + if (!(val & (AVTAB_AV | AVTAB_TYPE))) { + printk("security: avtab: null entry\n"); + return -1; + } + if ((val & AVTAB_AV) && + (val & AVTAB_TYPE)) { + printk("security: avtab: entry has both access vectors and types\n"); + return -1; + } + + for (i = 0; i < sizeof(spec_order)/sizeof(u16); i++) { + if (val & spec_order[i]) { + key.specified = spec_order[i] | enabled; + datum.data = le32_to_cpu(buf32[items++]); + rc = insertf(a, &key, &datum, p); + if (rc) return rc; + } + } + + if (items != items2) { + printk("security: avtab: entry only had %d items, expected %d\n", items2, items); + return -1; + } + return 0; } - rc = next_entry(buf, fp, sizeof(u32)*items2); + + rc = next_entry(buf16, fp, sizeof(u16)*4); if (rc < 0) { - printk(KERN_ERR "security: avtab: truncated entry\n"); - goto bad; + printk("security: avtab: truncated entry\n"); + return -1; } + items = 0; - avkey->source_type = le32_to_cpu(buf[items++]); - avkey->target_type = le32_to_cpu(buf[items++]); - avkey->target_class = le32_to_cpu(buf[items++]); - avdatum->specified = le32_to_cpu(buf[items++]); - if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) { - printk(KERN_ERR "security: avtab: null entry\n"); - goto bad; - } - if ((avdatum->specified & AVTAB_AV) && - (avdatum->specified & AVTAB_TYPE)) { - printk(KERN_ERR "security: avtab: entry has both access vectors and types\n"); - goto bad; - } - if (avdatum->specified & AVTAB_AV) { - if (avdatum->specified & AVTAB_ALLOWED) - avtab_allowed(avdatum) = le32_to_cpu(buf[items++]); - if (avdatum->specified & AVTAB_AUDITDENY) - avtab_auditdeny(avdatum) = le32_to_cpu(buf[items++]); - if (avdatum->specified & AVTAB_AUDITALLOW) - avtab_auditallow(avdatum) = le32_to_cpu(buf[items++]); - } else { - if (avdatum->specified & AVTAB_TRANSITION) - avtab_transition(avdatum) = le32_to_cpu(buf[items++]); - if (avdatum->specified & AVTAB_CHANGE) - avtab_change(avdatum) = le32_to_cpu(buf[items++]); - if (avdatum->specified & AVTAB_MEMBER) - avtab_member(avdatum) = le32_to_cpu(buf[items++]); - } - if (items != items2) { - printk(KERN_ERR "security: avtab: entry only had %d items, expected %d\n", - items2, items); - goto bad; + key.source_type = le16_to_cpu(buf16[items++]); + key.target_type = le16_to_cpu(buf16[items++]); + key.target_class = le16_to_cpu(buf16[items++]); + key.specified = le16_to_cpu(buf16[items++]); + + rc = next_entry(buf32, fp, sizeof(u32)); + if (rc < 0) { + printk("security: avtab: truncated entry\n"); + return -1; } + datum.data = le32_to_cpu(*buf32); + return insertf(a, &key, &datum, p); +} - return 0; -bad: - return -1; +static int avtab_insertf(struct avtab *a, struct avtab_key *k, + struct avtab_datum *d, void *p) +{ + return avtab_insert(a, k, d); } -int avtab_read(struct avtab *a, void *fp, u32 config) +int avtab_read(struct avtab *a, void *fp, u32 vers) { int rc; - struct avtab_key avkey; - struct avtab_datum avdatum; - u32 buf[1]; + __le32 buf[1]; u32 nel, i; @@ -363,16 +421,14 @@ int avtab_read(struct avtab *a, void *fp, u32 config) goto bad; } for (i = 0; i < nel; i++) { - if (avtab_read_item(fp, &avdatum, &avkey)) { - rc = -EINVAL; - goto bad; - } - rc = avtab_insert(a, &avkey, &avdatum); + rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL); if (rc) { if (rc == -ENOMEM) printk(KERN_ERR "security: avtab: out of memory\n"); - if (rc == -EEXIST) + else if (rc == -EEXIST) printk(KERN_ERR "security: avtab: duplicate entry\n"); + else + rc = -EINVAL; goto bad; } } diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 519d4f6dc65..0a90d939af9 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -21,12 +21,9 @@ #define _SS_AVTAB_H_ struct avtab_key { - u32 source_type; /* source type */ - u32 target_type; /* target type */ - u32 target_class; /* target object class */ -}; - -struct avtab_datum { + u16 source_type; /* source type */ + u16 target_type; /* target type */ + u16 target_class; /* target object class */ #define AVTAB_ALLOWED 1 #define AVTAB_AUDITALLOW 2 #define AVTAB_AUDITDENY 4 @@ -35,15 +32,13 @@ struct avtab_datum { #define AVTAB_MEMBER 32 #define AVTAB_CHANGE 64 #define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) -#define AVTAB_ENABLED 0x80000000 /* reserved for used in cond_avtab */ - u32 specified; /* what fields are specified */ - u32 data[3]; /* access vectors or types */ -#define avtab_allowed(x) (x)->data[0] -#define avtab_auditdeny(x) (x)->data[1] -#define avtab_auditallow(x) (x)->data[2] -#define avtab_transition(x) (x)->data[0] -#define avtab_change(x) (x)->data[1] -#define avtab_member(x) (x)->data[2] +#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ +#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ + u16 specified; /* what field is specified */ +}; + +struct avtab_datum { + u32 data; /* access vector or type value */ }; struct avtab_node { @@ -58,17 +53,21 @@ struct avtab { }; int avtab_init(struct avtab *); -struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k, int specified); +struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k); void avtab_destroy(struct avtab *h); void avtab_hash_eval(struct avtab *h, char *tag); -int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey); -int avtab_read(struct avtab *a, void *fp, u32 config); +int avtab_read_item(void *fp, uint32_t vers, struct avtab *a, + int (*insert)(struct avtab *a, struct avtab_key *k, + struct avtab_datum *d, void *p), + void *p); + +int avtab_read(struct avtab *a, void *fp, u32 vers); struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum); -struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key, int specified); +struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key); struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index e2057f5a411..daf28800746 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -100,18 +100,18 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node) /* turn the rules on or off */ for (cur = node->true_list; cur != NULL; cur = cur->next) { if (new_state <= 0) { - cur->node->datum.specified &= ~AVTAB_ENABLED; + cur->node->key.specified &= ~AVTAB_ENABLED; } else { - cur->node->datum.specified |= AVTAB_ENABLED; + cur->node->key.specified |= AVTAB_ENABLED; } } for (cur = node->false_list; cur != NULL; cur = cur->next) { /* -1 or 1 */ if (new_state) { - cur->node->datum.specified &= ~AVTAB_ENABLED; + cur->node->key.specified &= ~AVTAB_ENABLED; } else { - cur->node->datum.specified |= AVTAB_ENABLED; + cur->node->key.specified |= AVTAB_ENABLED; } } } @@ -216,7 +216,8 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) { char *key = NULL; struct cond_bool_datum *booldatum; - u32 buf[3], len; + __le32 buf[3]; + u32 len; int rc; booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); @@ -252,104 +253,127 @@ err: return -1; } -static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, - struct cond_av_list *other) +struct cond_insertf_data { - struct cond_av_list *list, *last = NULL, *cur; - struct avtab_key key; - struct avtab_datum datum; + struct policydb *p; + struct cond_av_list *other; + struct cond_av_list *head; + struct cond_av_list *tail; +}; + +static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr) +{ + struct cond_insertf_data *data = ptr; + struct policydb *p = data->p; + struct cond_av_list *other = data->other, *list, *cur; struct avtab_node *node_ptr; - int rc; - u32 buf[1], i, len; u8 found; - *ret_list = NULL; - - len = 0; - rc = next_entry(buf, fp, sizeof buf); - if (rc < 0) - return -1; - - len = le32_to_cpu(buf[0]); - if (len == 0) { - return 0; - } - for (i = 0; i < len; i++) { - if (avtab_read_item(fp, &datum, &key)) + /* + * For type rules we have to make certain there aren't any + * conflicting rules by searching the te_avtab and the + * cond_te_avtab. + */ + if (k->specified & AVTAB_TYPE) { + if (avtab_search(&p->te_avtab, k)) { + printk("security: type rule already exists outside of a conditional."); goto err; - + } /* - * For type rules we have to make certain there aren't any - * conflicting rules by searching the te_avtab and the - * cond_te_avtab. + * If we are reading the false list other will be a pointer to + * the true list. We can have duplicate entries if there is only + * 1 other entry and it is in our true list. + * + * If we are reading the true list (other == NULL) there shouldn't + * be any other entries. */ - if (datum.specified & AVTAB_TYPE) { - if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) { - printk("security: type rule already exists outside of a conditional."); - goto err; - } - /* - * If we are reading the false list other will be a pointer to - * the true list. We can have duplicate entries if there is only - * 1 other entry and it is in our true list. - * - * If we are reading the true list (other == NULL) there shouldn't - * be any other entries. - */ - if (other) { - node_ptr = avtab_search_node(&p->te_cond_avtab, &key, AVTAB_TYPE); - if (node_ptr) { - if (avtab_search_node_next(node_ptr, AVTAB_TYPE)) { - printk("security: too many conflicting type rules."); - goto err; - } - found = 0; - for (cur = other; cur != NULL; cur = cur->next) { - if (cur->node == node_ptr) { - found = 1; - break; - } - } - if (!found) { - printk("security: conflicting type rules."); - goto err; + if (other) { + node_ptr = avtab_search_node(&p->te_cond_avtab, k); + if (node_ptr) { + if (avtab_search_node_next(node_ptr, k->specified)) { + printk("security: too many conflicting type rules."); + goto err; + } + found = 0; + for (cur = other; cur != NULL; cur = cur->next) { + if (cur->node == node_ptr) { + found = 1; + break; } } - } else { - if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) { - printk("security: conflicting type rules when adding type rule for true."); + if (!found) { + printk("security: conflicting type rules.\n"); goto err; } } + } else { + if (avtab_search(&p->te_cond_avtab, k)) { + printk("security: conflicting type rules when adding type rule for true.\n"); + goto err; + } } - node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum); - if (!node_ptr) { - printk("security: could not insert rule."); - goto err; - } - - list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL); - if (!list) - goto err; - memset(list, 0, sizeof(struct cond_av_list)); - - list->node = node_ptr; - if (i == 0) - *ret_list = list; - else - last->next = list; - last = list; + } + node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); + if (!node_ptr) { + printk("security: could not insert rule."); + goto err; } + list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL); + if (!list) + goto err; + memset(list, 0, sizeof(*list)); + + list->node = node_ptr; + if (!data->head) + data->head = list; + else + data->tail->next = list; + data->tail = list; return 0; + err: - cond_av_list_destroy(*ret_list); - *ret_list = NULL; + cond_av_list_destroy(data->head); + data->head = NULL; return -1; } +static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) +{ + int i, rc; + __le32 buf[1]; + u32 len; + struct cond_insertf_data data; + + *ret_list = NULL; + + len = 0; + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) + return -1; + + len = le32_to_cpu(buf[0]); + if (len == 0) { + return 0; + } + + data.p = p; + data.other = other; + data.head = NULL; + data.tail = NULL; + for (i = 0; i < len; i++) { + rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data); + if (rc) + return rc; + + } + + *ret_list = data.head; + return 0; +} + static int expr_isvalid(struct policydb *p, struct cond_expr *expr) { if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { @@ -366,7 +390,8 @@ static int expr_isvalid(struct policydb *p, struct cond_expr *expr) static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) { - u32 buf[2], len, i; + __le32 buf[2]; + u32 len, i; int rc; struct cond_expr *expr = NULL, *last = NULL; @@ -424,7 +449,8 @@ err: int cond_read_list(struct policydb *p, void *fp) { struct cond_node *node, *last = NULL; - u32 buf[1], i, len; + __le32 buf[1]; + u32 i, len; int rc; rc = next_entry(buf, fp, sizeof buf); @@ -452,6 +478,7 @@ int cond_read_list(struct policydb *p, void *fp) return 0; err: cond_list_destroy(p->cond_list); + p->cond_list = NULL; return -1; } @@ -465,22 +492,22 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi if(!ctab || !key || !avd) return; - for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL; - node = avtab_search_node_next(node, AVTAB_AV)) { - if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) == - (node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) - avd->allowed |= avtab_allowed(&node->datum); - if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) == - (node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) + for(node = avtab_search_node(ctab, key); node != NULL; + node = avtab_search_node_next(node, key->specified)) { + if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) == + (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) + avd->allowed |= node->datum.data; + if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) == + (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) /* Since a '0' in an auditdeny mask represents a * permission we do NOT want to audit (dontaudit), we use * the '&' operand to ensure that all '0's in the mask * are retained (much unlike the allow and auditallow cases). */ - avd->auditdeny &= avtab_auditdeny(&node->datum); - if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == - (node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) - avd->auditallow |= avtab_auditallow(&node->datum); + avd->auditdeny &= node->datum.data; + if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == + (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) + avd->auditallow |= node->datum.data; } return; } diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index d8ce9cc0b9f..d515154128c 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -196,8 +196,9 @@ int ebitmap_read(struct ebitmap *e, void *fp) { int rc; struct ebitmap_node *n, *l; - u32 buf[3], mapsize, count, i; - u64 map; + __le32 buf[3]; |