Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6:
SELinux: add more validity checks on policy load
SELinux: fix bug in new ebitmap code.
SELinux: suppress a warning for 64k pages.

+126 -45
+28 -4
security/selinux/ss/avtab.c
··· 325 325 AVTAB_MEMBER 326 326 }; 327 327 328 - int avtab_read_item(void *fp, u32 vers, struct avtab *a, 328 + int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, 329 329 int (*insertf)(struct avtab *a, struct avtab_key *k, 330 330 struct avtab_datum *d, void *p), 331 331 void *p) ··· 333 333 __le16 buf16[4]; 334 334 u16 enabled; 335 335 __le32 buf32[7]; 336 - u32 items, items2, val; 336 + u32 items, items2, val, vers = pol->policyvers; 337 337 struct avtab_key key; 338 338 struct avtab_datum datum; 339 339 int i, rc; 340 + unsigned set; 340 341 341 342 memset(&key, 0, sizeof(struct avtab_key)); 342 343 memset(&datum, 0, sizeof(struct avtab_datum)); ··· 421 420 key.target_class = le16_to_cpu(buf16[items++]); 422 421 key.specified = le16_to_cpu(buf16[items++]); 423 422 423 + if (!policydb_type_isvalid(pol, key.source_type) || 424 + !policydb_type_isvalid(pol, key.target_type) || 425 + !policydb_class_isvalid(pol, key.target_class)) { 426 + printk(KERN_WARNING "security: avtab: invalid type or class\n"); 427 + return -1; 428 + } 429 + 430 + set = 0; 431 + for (i = 0; i < ARRAY_SIZE(spec_order); i++) { 432 + if (key.specified & spec_order[i]) 433 + set++; 434 + } 435 + if (!set || set > 1) { 436 + printk(KERN_WARNING 437 + "security: avtab: more than one specifier\n"); 438 + return -1; 439 + } 440 + 424 441 rc = next_entry(buf32, fp, sizeof(u32)); 425 442 if (rc < 0) { 426 443 printk("security: avtab: truncated entry\n"); 427 444 return -1; 428 445 } 429 446 datum.data = le32_to_cpu(*buf32); 447 + if ((key.specified & AVTAB_TYPE) && 448 + !policydb_type_isvalid(pol, datum.data)) { 449 + printk(KERN_WARNING "security: avtab: invalid type\n"); 450 + return -1; 451 + } 430 452 return insertf(a, &key, &datum, p); 431 453 } 432 454 ··· 459 435 return avtab_insert(a, k, d); 460 436 } 461 437 462 - int avtab_read(struct avtab *a, void *fp, u32 vers) 438 + int avtab_read(struct avtab *a, void *fp, struct policydb *pol) 463 439 { 464 440 int rc; 465 441 __le32 buf[1]; ··· 483 459 goto bad; 484 460 485 461 for (i = 0; i < nel; i++) { 486 - rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL); 462 + rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL); 487 463 if (rc) { 488 464 if (rc == -ENOMEM) 489 465 printk(KERN_ERR "security: avtab: out of memory\n");
+3 -2
security/selinux/ss/avtab.h
··· 64 64 void avtab_destroy(struct avtab *h); 65 65 void avtab_hash_eval(struct avtab *h, char *tag); 66 66 67 - int avtab_read_item(void *fp, uint32_t vers, struct avtab *a, 67 + struct policydb; 68 + int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, 68 69 int (*insert)(struct avtab *a, struct avtab_key *k, 69 70 struct avtab_datum *d, void *p), 70 71 void *p); 71 72 72 - int avtab_read(struct avtab *a, void *fp, u32 vers); 73 + int avtab_read(struct avtab *a, void *fp, struct policydb *pol); 73 74 74 75 struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, 75 76 struct avtab_datum *datum);
+2 -1
security/selinux/ss/conditional.c
··· 362 362 data.head = NULL; 363 363 data.tail = NULL; 364 364 for (i = 0; i < len; i++) { 365 - rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data); 365 + rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf, 366 + &data); 366 367 if (rc) 367 368 return rc; 368 369
+1 -1
security/selinux/ss/ebitmap.c
··· 129 129 cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; 130 130 c_iter->bitmap[cmap_idx] 131 131 |= e_iter->maps[cmap_idx] << cmap_sft; 132 - e_iter = e_iter->next; 133 132 } 133 + e_iter = e_iter->next; 134 134 } 135 135 136 136 return 0;
+36 -30
security/selinux/ss/mls.c
··· 157 157 return; 158 158 } 159 159 160 + int mls_level_isvalid(struct policydb *p, struct mls_level *l) 161 + { 162 + struct level_datum *levdatum; 163 + struct ebitmap_node *node; 164 + int i; 165 + 166 + if (!l->sens || l->sens > p->p_levels.nprim) 167 + return 0; 168 + levdatum = hashtab_search(p->p_levels.table, 169 + p->p_sens_val_to_name[l->sens - 1]); 170 + if (!levdatum) 171 + return 0; 172 + 173 + ebitmap_for_each_positive_bit(&l->cat, node, i) { 174 + if (i > p->p_cats.nprim) 175 + return 0; 176 + if (!ebitmap_get_bit(&levdatum->level->cat, i)) { 177 + /* 178 + * Category may not be associated with 179 + * sensitivity. 180 + */ 181 + return 0; 182 + } 183 + } 184 + 185 + return 1; 186 + } 187 + 188 + int mls_range_isvalid(struct policydb *p, struct mls_range *r) 189 + { 190 + return (mls_level_isvalid(p, &r->level[0]) && 191 + mls_level_isvalid(p, &r->level[1]) && 192 + mls_level_dom(&r->level[1], &r->level[0])); 193 + } 194 + 160 195 /* 161 196 * Return 1 if the MLS fields in the security context 162 197 * structure `c' are valid. Return 0 otherwise. 163 198 */ 164 199 int mls_context_isvalid(struct policydb *p, struct context *c) 165 200 { 166 - struct level_datum *levdatum; 167 201 struct user_datum *usrdatum; 168 - struct ebitmap_node *node; 169 - int i, l; 170 202 171 203 if (!selinux_mls_enabled) 172 204 return 1; 173 205 174 - /* 175 - * MLS range validity checks: high must dominate low, low level must 176 - * be valid (category set <-> sensitivity check), and high level must 177 - * be valid (category set <-> sensitivity check) 178 - */ 179 - if (!mls_level_dom(&c->range.level[1], &c->range.level[0])) 180 - /* High does not dominate low. */ 206 + if (!mls_range_isvalid(p, &c->range)) 181 207 return 0; 182 - 183 - for (l = 0; l < 2; l++) { 184 - if (!c->range.level[l].sens || c->range.level[l].sens > p->p_levels.nprim) 185 - return 0; 186 - levdatum = hashtab_search(p->p_levels.table, 187 - p->p_sens_val_to_name[c->range.level[l].sens - 1]); 188 - if (!levdatum) 189 - return 0; 190 - 191 - ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) { 192 - if (i > p->p_cats.nprim) 193 - return 0; 194 - if (!ebitmap_get_bit(&levdatum->level->cat, i)) 195 - /* 196 - * Category may not be associated with 197 - * sensitivity in low level. 198 - */ 199 - return 0; 200 - } 201 - } 202 208 203 209 if (c->role == OBJECT_R_VAL) 204 210 return 1;
+2
security/selinux/ss/mls.h
··· 27 27 int mls_compute_context_len(struct context *context); 28 28 void mls_sid_to_context(struct context *context, char **scontext); 29 29 int mls_context_isvalid(struct policydb *p, struct context *c); 30 + int mls_range_isvalid(struct policydb *p, struct mls_range *r); 31 + int mls_level_isvalid(struct policydb *p, struct mls_level *l); 30 32 31 33 int mls_context_to_sid(char oldc, 32 34 char **scontext,
+44 -1
security/selinux/ss/policydb.c
··· 713 713 return rc; 714 714 } 715 715 716 + int policydb_class_isvalid(struct policydb *p, unsigned int class) 717 + { 718 + if (!class || class > p->p_classes.nprim) 719 + return 0; 720 + return 1; 721 + } 722 + 723 + int policydb_role_isvalid(struct policydb *p, unsigned int role) 724 + { 725 + if (!role || role > p->p_roles.nprim) 726 + return 0; 727 + return 1; 728 + } 729 + 730 + int policydb_type_isvalid(struct policydb *p, unsigned int type) 731 + { 732 + if (!type || type > p->p_types.nprim) 733 + return 0; 734 + return 1; 735 + } 736 + 716 737 /* 717 738 * Return 1 if the fields in the security context 718 739 * structure `c' are valid. Return 0 otherwise. ··· 1281 1260 "categories\n"); 1282 1261 goto bad; 1283 1262 } 1263 + 1284 1264 return 0; 1285 1265 1286 1266 bad: ··· 1585 1563 p->symtab[i].nprim = nprim; 1586 1564 } 1587 1565 1588 - rc = avtab_read(&p->te_avtab, fp, p->policyvers); 1566 + rc = avtab_read(&p->te_avtab, fp, p); 1589 1567 if (rc) 1590 1568 goto bad; 1591 1569 ··· 1617 1595 tr->role = le32_to_cpu(buf[0]); 1618 1596 tr->type = le32_to_cpu(buf[1]); 1619 1597 tr->new_role = le32_to_cpu(buf[2]); 1598 + if (!policydb_role_isvalid(p, tr->role) || 1599 + !policydb_type_isvalid(p, tr->type) || 1600 + !policydb_role_isvalid(p, tr->new_role)) { 1601 + rc = -EINVAL; 1602 + goto bad; 1603 + } 1620 1604 ltr = tr; 1621 1605 } 1622 1606 ··· 1647 1619 goto bad; 1648 1620 ra->role = le32_to_cpu(buf[0]); 1649 1621 ra->new_role = le32_to_cpu(buf[1]); 1622 + if (!policydb_role_isvalid(p, ra->role) || 1623 + !policydb_role_isvalid(p, ra->new_role)) { 1624 + rc = -EINVAL; 1625 + goto bad; 1626 + } 1650 1627 lra = ra; 1651 1628 } 1652 1629 ··· 1905 1872 rt->target_class = le32_to_cpu(buf[0]); 1906 1873 } else 1907 1874 rt->target_class = SECCLASS_PROCESS; 1875 + if (!policydb_type_isvalid(p, rt->source_type) || 1876 + !policydb_type_isvalid(p, rt->target_type) || 1877 + !policydb_class_isvalid(p, rt->target_class)) { 1878 + rc = -EINVAL; 1879 + goto bad; 1880 + } 1908 1881 rc = mls_read_range_helper(&rt->target_range, fp); 1909 1882 if (rc) 1910 1883 goto bad; 1884 + if (!mls_range_isvalid(p, &rt->target_range)) { 1885 + printk(KERN_WARNING "security: rangetrans: invalid range\n"); 1886 + goto bad; 1887 + } 1911 1888 lrt = rt; 1912 1889 } 1913 1890 }
+3
security/selinux/ss/policydb.h
··· 251 251 extern void policydb_destroy(struct policydb *p); 252 252 extern int policydb_load_isids(struct policydb *p, struct sidtab *s); 253 253 extern int policydb_context_isvalid(struct policydb *p, struct context *c); 254 + extern int policydb_class_isvalid(struct policydb *p, unsigned int class); 255 + extern int policydb_type_isvalid(struct policydb *p, unsigned int type); 256 + extern int policydb_role_isvalid(struct policydb *p, unsigned int role); 254 257 extern int policydb_read(struct policydb *p, void *fp); 255 258 256 259 #define PERM_SYMTAB_SIZE 32
+7 -6
security/selinux/xfrm.c
··· 211 211 if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX) 212 212 return -EINVAL; 213 213 214 - if (uctx->ctx_len >= PAGE_SIZE) 214 + str_len = uctx->ctx_len; 215 + if (str_len >= PAGE_SIZE) 215 216 return -ENOMEM; 216 217 217 218 *ctxp = ctx = kmalloc(sizeof(*ctx) + 218 - uctx->ctx_len + 1, 219 + str_len + 1, 219 220 GFP_KERNEL); 220 221 221 222 if (!ctx) 222 223 return -ENOMEM; 223 224 224 225 ctx->ctx_doi = uctx->ctx_doi; 225 - ctx->ctx_len = uctx->ctx_len; 226 + ctx->ctx_len = str_len; 226 227 ctx->ctx_alg = uctx->ctx_alg; 227 228 228 229 memcpy(ctx->ctx_str, 229 230 uctx+1, 230 - ctx->ctx_len); 231 - ctx->ctx_str[ctx->ctx_len] = 0; 231 + str_len); 232 + ctx->ctx_str[str_len] = 0; 232 233 rc = security_context_to_sid(ctx->ctx_str, 233 - ctx->ctx_len, 234 + str_len, 234 235 &ctx->ctx_sid); 235 236 236 237 if (rc)