diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/dummy.c | 52 | ||||
-rw-r--r-- | security/seclvl.c | 2 | ||||
-rw-r--r-- | security/selinux/avc.c | 4 | ||||
-rw-r--r-- | security/selinux/hooks.c | 180 | ||||
-rw-r--r-- | security/selinux/include/security.h | 3 | ||||
-rw-r--r-- | security/selinux/netlink.c | 6 | ||||
-rw-r--r-- | security/selinux/nlmsgtab.c | 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 |
16 files changed, 524 insertions, 437 deletions
diff --git a/security/dummy.c b/security/dummy.c index 6ff887586479..9623a61dfc76 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -258,16 +258,16 @@ static void dummy_inode_free_security (struct inode *inode) | |||
258 | return; | 258 | return; |
259 | } | 259 | } |
260 | 260 | ||
261 | static int dummy_inode_create (struct inode *inode, struct dentry *dentry, | 261 | static int dummy_inode_init_security (struct inode *inode, struct inode *dir, |
262 | int mask) | 262 | char **name, void **value, size_t *len) |
263 | { | 263 | { |
264 | return 0; | 264 | return -EOPNOTSUPP; |
265 | } | 265 | } |
266 | 266 | ||
267 | static void dummy_inode_post_create (struct inode *inode, struct dentry *dentry, | 267 | static int dummy_inode_create (struct inode *inode, struct dentry *dentry, |
268 | int mask) | 268 | int mask) |
269 | { | 269 | { |
270 | return; | 270 | return 0; |
271 | } | 271 | } |
272 | 272 | ||
273 | static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode, | 273 | static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode, |
@@ -276,13 +276,6 @@ static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode, | |||
276 | return 0; | 276 | return 0; |
277 | } | 277 | } |
278 | 278 | ||
279 | static void dummy_inode_post_link (struct dentry *old_dentry, | ||
280 | struct inode *inode, | ||
281 | struct dentry *new_dentry) | ||
282 | { | ||
283 | return; | ||
284 | } | ||
285 | |||
286 | static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry) | 279 | static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry) |
287 | { | 280 | { |
288 | return 0; | 281 | return 0; |
@@ -294,24 +287,12 @@ static int dummy_inode_symlink (struct inode *inode, struct dentry *dentry, | |||
294 | return 0; | 287 | return 0; |
295 | } | 288 | } |
296 | 289 | ||
297 | static void dummy_inode_post_symlink (struct inode *inode, | ||
298 | struct dentry *dentry, const char *name) | ||
299 | { | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry, | 290 | static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry, |
304 | int mask) | 291 | int mask) |
305 | { | 292 | { |
306 | return 0; | 293 | return 0; |
307 | } | 294 | } |
308 | 295 | ||
309 | static void dummy_inode_post_mkdir (struct inode *inode, struct dentry *dentry, | ||
310 | int mask) | ||
311 | { | ||
312 | return; | ||
313 | } | ||
314 | |||
315 | static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry) | 296 | static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry) |
316 | { | 297 | { |
317 | return 0; | 298 | return 0; |
@@ -323,12 +304,6 @@ static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry, | |||
323 | return 0; | 304 | return 0; |
324 | } | 305 | } |
325 | 306 | ||
326 | static void dummy_inode_post_mknod (struct inode *inode, struct dentry *dentry, | ||
327 | int mode, dev_t dev) | ||
328 | { | ||
329 | return; | ||
330 | } | ||
331 | |||
332 | static int dummy_inode_rename (struct inode *old_inode, | 307 | static int dummy_inode_rename (struct inode *old_inode, |
333 | struct dentry *old_dentry, | 308 | struct dentry *old_dentry, |
334 | struct inode *new_inode, | 309 | struct inode *new_inode, |
@@ -337,14 +312,6 @@ static int dummy_inode_rename (struct inode *old_inode, | |||
337 | return 0; | 312 | return 0; |
338 | } | 313 | } |
339 | 314 | ||
340 | static void dummy_inode_post_rename (struct inode *old_inode, | ||
341 | struct dentry *old_dentry, | ||
342 | struct inode *new_inode, | ||
343 | struct dentry *new_dentry) | ||
344 | { | ||
345 | return; | ||
346 | } | ||
347 | |||
348 | static int dummy_inode_readlink (struct dentry *dentry) | 315 | static int dummy_inode_readlink (struct dentry *dentry) |
349 | { | 316 | { |
350 | return 0; | 317 | return 0; |
@@ -886,20 +853,15 @@ void security_fixup_ops (struct security_operations *ops) | |||
886 | set_to_dummy_if_null(ops, sb_post_pivotroot); | 853 | set_to_dummy_if_null(ops, sb_post_pivotroot); |
887 | set_to_dummy_if_null(ops, inode_alloc_security); | 854 | set_to_dummy_if_null(ops, inode_alloc_security); |
888 | set_to_dummy_if_null(ops, inode_free_security); | 855 | set_to_dummy_if_null(ops, inode_free_security); |
856 | set_to_dummy_if_null(ops, inode_init_security); | ||
889 | set_to_dummy_if_null(ops, inode_create); | 857 | set_to_dummy_if_null(ops, inode_create); |
890 | set_to_dummy_if_null(ops, inode_post_create); | ||
891 | set_to_dummy_if_null(ops, inode_link); | 858 | set_to_dummy_if_null(ops, inode_link); |
892 | set_to_dummy_if_null(ops, inode_post_link); | ||
893 | set_to_dummy_if_null(ops, inode_unlink); | 859 | set_to_dummy_if_null(ops, inode_unlink); |
894 | set_to_dummy_if_null(ops, inode_symlink); | 860 | set_to_dummy_if_null(ops, inode_symlink); |
895 | set_to_dummy_if_null(ops, inode_post_symlink); | ||
896 | set_to_dummy_if_null(ops, inode_mkdir); | 861 | set_to_dummy_if_null(ops, inode_mkdir); |
897 | set_to_dummy_if_null(ops, inode_post_mkdir); | ||
898 | set_to_dummy_if_null(ops, inode_rmdir); | 862 | set_to_dummy_if_null(ops, inode_rmdir); |
899 | set_to_dummy_if_null(ops, inode_mknod); | 863 | set_to_dummy_if_null(ops, inode_mknod); |
900 | set_to_dummy_if_null(ops, inode_post_mknod); | ||
901 | set_to_dummy_if_null(ops, inode_rename); | 864 | set_to_dummy_if_null(ops, inode_rename); |
902 | set_to_dummy_if_null(ops, inode_post_rename); | ||
903 | set_to_dummy_if_null(ops, inode_readlink); | 865 | set_to_dummy_if_null(ops, inode_readlink); |
904 | set_to_dummy_if_null(ops, inode_follow_link); | 866 | set_to_dummy_if_null(ops, inode_follow_link); |
905 | set_to_dummy_if_null(ops, inode_permission); | 867 | set_to_dummy_if_null(ops, inode_permission); |
diff --git a/security/seclvl.c b/security/seclvl.c index c8e87b22c9bd..96b1f2122f67 100644 --- a/security/seclvl.c +++ b/security/seclvl.c | |||
@@ -321,7 +321,7 @@ plaintext_to_sha1(unsigned char *hash, const char *plaintext, int len) | |||
321 | "bytes.\n", len, PAGE_SIZE); | 321 | "bytes.\n", len, PAGE_SIZE); |
322 | return -ENOMEM; | 322 | return -ENOMEM; |
323 | } | 323 | } |
324 | tfm = crypto_alloc_tfm("sha1", 0); | 324 | tfm = crypto_alloc_tfm("sha1", CRYPTO_TFM_REQ_MAY_SLEEP); |
325 | if (tfm == NULL) { | 325 | if (tfm == NULL) { |
326 | seclvl_printk(0, KERN_ERR, | 326 | seclvl_printk(0, KERN_ERR, |
327 | "Failed to load transform for SHA1\n"); | 327 | "Failed to load transform for SHA1\n"); |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 2d088bb65ee8..12e4fb72bf0f 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -490,7 +490,7 @@ out: | |||
490 | } | 490 | } |
491 | 491 | ||
492 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | 492 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, |
493 | struct in6_addr *addr, u16 port, | 493 | struct in6_addr *addr, __be16 port, |
494 | char *name1, char *name2) | 494 | char *name1, char *name2) |
495 | { | 495 | { |
496 | if (!ipv6_addr_any(addr)) | 496 | if (!ipv6_addr_any(addr)) |
@@ -501,7 +501,7 @@ static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | |||
501 | } | 501 | } |
502 | 502 | ||
503 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr, | 503 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr, |
504 | u16 port, char *name1, char *name2) | 504 | __be16 port, char *name1, char *name2) |
505 | { | 505 | { |
506 | if (addr) | 506 | if (addr) |
507 | audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr)); | 507 | 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 9f9463000683..6e4937fe062b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -659,7 +659,7 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc | |||
659 | return SECCLASS_NETLINK_ROUTE_SOCKET; | 659 | return SECCLASS_NETLINK_ROUTE_SOCKET; |
660 | case NETLINK_FIREWALL: | 660 | case NETLINK_FIREWALL: |
661 | return SECCLASS_NETLINK_FIREWALL_SOCKET; | 661 | return SECCLASS_NETLINK_FIREWALL_SOCKET; |
662 | case NETLINK_TCPDIAG: | 662 | case NETLINK_INET_DIAG: |
663 | return SECCLASS_NETLINK_TCPDIAG_SOCKET; | 663 | return SECCLASS_NETLINK_TCPDIAG_SOCKET; |
664 | case NETLINK_NFLOG: | 664 | case NETLINK_NFLOG: |
665 | return SECCLASS_NETLINK_NFLOG_SOCKET; | 665 | return SECCLASS_NETLINK_NFLOG_SOCKET; |
@@ -1265,85 +1265,6 @@ static int inode_security_set_sid(struct inode *inode, u32 sid) | |||
1265 | return 0; | 1265 | return 0; |
1266 | } | 1266 | } |
1267 | 1267 | ||
1268 | /* Set the security attributes on a newly created file. */ | ||
1269 | static int post_create(struct inode *dir, | ||
1270 | struct dentry *dentry) | ||
1271 | { | ||
1272 | |||
1273 | struct task_security_struct *tsec; | ||
1274 | struct inode *inode; | ||
1275 | struct inode_security_struct *dsec; | ||
1276 | struct superblock_security_struct *sbsec; | ||
1277 | u32 newsid; | ||
1278 | char *context; | ||
1279 | unsigned int len; | ||
1280 | int rc; | ||
1281 | |||
1282 | tsec = current->security; | ||
1283 | dsec = dir->i_security; | ||
1284 | sbsec = dir->i_sb->s_security; | ||
1285 | |||
1286 | inode = dentry->d_inode; | ||
1287 | if (!inode) { | ||
1288 | /* Some file system types (e.g. NFS) may not instantiate | ||
1289 | a dentry for all create operations (e.g. symlink), | ||
1290 | so we have to check to see if the inode is non-NULL. */ | ||
1291 | printk(KERN_WARNING "post_create: no inode, dir (dev=%s, " | ||
1292 | "ino=%ld)\n", dir->i_sb->s_id, dir->i_ino); | ||
1293 | return 0; | ||
1294 | } | ||
1295 | |||
1296 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | ||
1297 | newsid = tsec->create_sid; | ||
1298 | } else { | ||
1299 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
1300 | inode_mode_to_security_class(inode->i_mode), | ||
1301 | &newsid); | ||
1302 | if (rc) { | ||
1303 | printk(KERN_WARNING "post_create: " | ||
1304 | "security_transition_sid failed, rc=%d (dev=%s " | ||
1305 | "ino=%ld)\n", | ||
1306 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
1307 | return rc; | ||
1308 | } | ||
1309 | } | ||
1310 | |||
1311 | rc = inode_security_set_sid(inode, newsid); | ||
1312 | if (rc) { | ||
1313 | printk(KERN_WARNING "post_create: inode_security_set_sid " | ||
1314 | "failed, rc=%d (dev=%s ino=%ld)\n", | ||
1315 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
1316 | return rc; | ||
1317 | } | ||
1318 | |||
1319 | if (sbsec->behavior == SECURITY_FS_USE_XATTR && | ||
1320 | inode->i_op->setxattr) { | ||
1321 | /* Use extended attributes. */ | ||
1322 | rc = security_sid_to_context(newsid, &context, &len); | ||
1323 | if (rc) { | ||
1324 | printk(KERN_WARNING "post_create: sid_to_context " | ||
1325 | "failed, rc=%d (dev=%s ino=%ld)\n", | ||
1326 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
1327 | return rc; | ||
1328 | } | ||
1329 | down(&inode->i_sem); | ||
1330 | rc = inode->i_op->setxattr(dentry, | ||
1331 | XATTR_NAME_SELINUX, | ||
1332 | context, len, 0); | ||
1333 | up(&inode->i_sem); | ||
1334 | kfree(context); | ||
1335 | if (rc < 0) { | ||
1336 | printk(KERN_WARNING "post_create: setxattr failed, " | ||
1337 | "rc=%d (dev=%s ino=%ld)\n", | ||
1338 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
1339 | return rc; | ||
1340 | } | ||
1341 | } | ||
1342 | |||
1343 | return 0; | ||
1344 | } | ||
1345 | |||
1346 | |||
1347 | /* Hook functions begin here. */ | 1268 | /* Hook functions begin here. */ |
1348 | 1269 | ||
1349 | static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) | 1270 | 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) | |||
1673 | struct avc_audit_data ad; | 1594 | struct avc_audit_data ad; |
1674 | struct file *file, *devnull = NULL; | 1595 | struct file *file, *devnull = NULL; |
1675 | struct tty_struct *tty = current->signal->tty; | 1596 | struct tty_struct *tty = current->signal->tty; |
1597 | struct fdtable *fdt; | ||
1676 | long j = -1; | 1598 | long j = -1; |
1677 | 1599 | ||
1678 | if (tty) { | 1600 | if (tty) { |
@@ -1706,9 +1628,10 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
1706 | 1628 | ||
1707 | j++; | 1629 | j++; |
1708 | i = j * __NFDBITS; | 1630 | i = j * __NFDBITS; |
1709 | if (i >= files->max_fds || i >= files->max_fdset) | 1631 | fdt = files_fdtable(files); |
1632 | if (i >= fdt->max_fds || i >= fdt->max_fdset) | ||
1710 | break; | 1633 | break; |
1711 | set = files->open_fds->fds_bits[j]; | 1634 | set = fdt->open_fds->fds_bits[j]; |
1712 | if (!set) | 1635 | if (!set) |
1713 | continue; | 1636 | continue; |
1714 | spin_unlock(&files->file_lock); | 1637 | spin_unlock(&files->file_lock); |
@@ -1729,7 +1652,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
1729 | continue; | 1652 | continue; |
1730 | } | 1653 | } |
1731 | if (devnull) { | 1654 | if (devnull) { |
1732 | atomic_inc(&devnull->f_count); | 1655 | rcuref_inc(&devnull->f_count); |
1733 | } else { | 1656 | } else { |
1734 | devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); | 1657 | devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); |
1735 | if (!devnull) { | 1658 | if (!devnull) { |
@@ -2018,14 +1941,64 @@ static void selinux_inode_free_security(struct inode *inode) | |||
2018 | inode_free_security(inode); | 1941 | inode_free_security(inode); |
2019 | } | 1942 | } |
2020 | 1943 | ||
2021 | static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) | 1944 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, |
1945 | char **name, void **value, | ||
1946 | size_t *len) | ||
2022 | { | 1947 | { |
2023 | return may_create(dir, dentry, SECCLASS_FILE); | 1948 | struct task_security_struct *tsec; |
1949 | struct inode_security_struct *dsec; | ||
1950 | struct superblock_security_struct *sbsec; | ||
1951 | struct inode_security_struct *isec; | ||
1952 | u32 newsid, clen; | ||
1953 | int rc; | ||
1954 | char *namep = NULL, *context; | ||
1955 | |||
1956 | tsec = current->security; | ||
1957 | dsec = dir->i_security; | ||
1958 | sbsec = dir->i_sb->s_security; | ||
1959 | isec = inode->i_security; | ||
1960 | |||
1961 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | ||
1962 | newsid = tsec->create_sid; | ||
1963 | } else { | ||
1964 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
1965 | inode_mode_to_security_class(inode->i_mode), | ||
1966 | &newsid); | ||
1967 | if (rc) { | ||
1968 | printk(KERN_WARNING "%s: " | ||
1969 | "security_transition_sid failed, rc=%d (dev=%s " | ||
1970 | "ino=%ld)\n", | ||
1971 | __FUNCTION__, | ||
1972 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
1973 | return rc; | ||
1974 | } | ||
1975 | } | ||
1976 | |||
1977 | inode_security_set_sid(inode, newsid); | ||
1978 | |||
1979 | if (name) { | ||
1980 | namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL); | ||
1981 | if (!namep) | ||
1982 | return -ENOMEM; | ||
1983 | *name = namep; | ||
1984 | } | ||
1985 | |||
1986 | if (value && len) { | ||
1987 | rc = security_sid_to_context(newsid, &context, &clen); | ||
1988 | if (rc) { | ||
1989 | kfree(namep); | ||
1990 | return rc; | ||
1991 | } | ||
1992 | *value = context; | ||
1993 | *len = clen; | ||
1994 | } | ||
1995 | |||
1996 | return 0; | ||
2024 | } | 1997 | } |
2025 | 1998 | ||
2026 | static void selinux_inode_post_create(struct inode *dir, struct dentry *dentry, int mask) | 1999 | static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) |
2027 | { | 2000 | { |
2028 | post_create(dir, dentry); | 2001 | return may_create(dir, dentry, SECCLASS_FILE); |
2029 | } | 2002 | } |
2030 | 2003 | ||
2031 | static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) | 2004 | 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 | |||
2038 | return may_link(dir, old_dentry, MAY_LINK); | 2011 | return may_link(dir, old_dentry, MAY_LINK); |
2039 | } | 2012 | } |
2040 | 2013 | ||
2041 | static void selinux_inode_post_link(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry) | ||
2042 | { | ||
2043 | return; | ||
2044 | } | ||
2045 | |||
2046 | static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) | 2014 | static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) |
2047 | { | 2015 | { |
2048 | int rc; | 2016 | int rc; |
@@ -2058,21 +2026,11 @@ static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const | |||
2058 | return may_create(dir, dentry, SECCLASS_LNK_FILE); | 2026 | return may_create(dir, dentry, SECCLASS_LNK_FILE); |
2059 | } | 2027 | } |
2060 | 2028 | ||
2061 | static void selinux_inode_post_symlink(struct inode *dir, struct dentry *dentry, const char *name) | ||
2062 | { | ||
2063 | post_create(dir, dentry); | ||
2064 | } | ||
2065 | |||
2066 | static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) | 2029 | static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) |
2067 | { | 2030 | { |
2068 | return may_create(dir, dentry, SECCLASS_DIR); | 2031 | return may_create(dir, dentry, SECCLASS_DIR); |
2069 | } | 2032 | } |
2070 | 2033 | ||
2071 | static void selinux_inode_post_mkdir(struct inode *dir, struct dentry *dentry, int mask) | ||
2072 | { | ||
2073 | post_create(dir, dentry); | ||
2074 | } | ||
2075 | |||
2076 | static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) | 2034 | static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) |
2077 | { | 2035 | { |
2078 | return may_link(dir, dentry, MAY_RMDIR); | 2036 | return may_link(dir, dentry, MAY_RMDIR); |
@@ -2089,23 +2047,12 @@ static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mod | |||
2089 | return may_create(dir, dentry, inode_mode_to_security_class(mode)); | 2047 | return may_create(dir, dentry, inode_mode_to_security_class(mode)); |
2090 | } | 2048 | } |
2091 | 2049 | ||
2092 | static void selinux_inode_post_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | ||
2093 | { | ||
2094 | post_create(dir, dentry); | ||
2095 | } | ||
2096 | |||
2097 | static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, | 2050 | static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, |
2098 | struct inode *new_inode, struct dentry *new_dentry) | 2051 | struct inode *new_inode, struct dentry *new_dentry) |
2099 | { | 2052 | { |
2100 | return may_rename(old_inode, old_dentry, new_inode, new_dentry); | 2053 | return may_rename(old_inode, old_dentry, new_inode, new_dentry); |
2101 | } | 2054 | } |
2102 | 2055 | ||
2103 | static void selinux_inode_post_rename(struct inode *old_inode, struct dentry *old_dentry, | ||
2104 | struct inode *new_inode, struct dentry *new_dentry) | ||
2105 | { | ||
2106 | return; | ||
2107 | } | ||
2108 | |||
2109 | static int selinux_inode_readlink(struct dentry *dentry) | 2056 | static int selinux_inode_readlink(struct dentry *dentry) |
2110 | { | 2057 | { |
2111 | return dentry_has_perm(current, NULL, dentry, FILE__READ); | 2058 | return dentry_has_perm(current, NULL, dentry, FILE__READ); |
@@ -4298,20 +4245,15 @@ static struct security_operations selinux_ops = { | |||
4298 | 4245 | ||
4299 | .inode_alloc_security = selinux_inode_alloc_security, | 4246 | .inode_alloc_security = selinux_inode_alloc_security, |
4300 | .inode_free_security = selinux_inode_free_security, | 4247 | .inode_free_security = selinux_inode_free_security, |
4248 | .inode_init_security = selinux_inode_init_security, | ||
4301 | .inode_create = selinux_inode_create, | 4249 | .inode_create = selinux_inode_create, |
4302 | .inode_post_create = selinux_inode_post_create, | ||
4303 | .inode_link = selinux_inode_link, | 4250 | .inode_link = selinux_inode_link, |
4304 | .inode_post_link = selinux_inode_post_link, | ||
4305 | .inode_unlink = selinux_inode_unlink, | 4251 | .inode_unlink = selinux_inode_unlink, |
4306 | .inode_symlink = selinux_inode_symlink, | 4252 | .inode_symlink = selinux_inode_symlink, |
4307 | .inode_post_symlink = selinux_inode_post_symlink, | ||
4308 | .inode_mkdir = selinux_inode_mkdir, | 4253 | .inode_mkdir = selinux_inode_mkdir, |
4309 | .inode_post_mkdir = selinux_inode_post_mkdir, | ||
4310 | .inode_rmdir = selinux_inode_rmdir, | 4254 | .inode_rmdir = selinux_inode_rmdir, |
4311 | .inode_mknod = selinux_inode_mknod, | 4255 | .inode_mknod = selinux_inode_mknod, |
4312 | .inode_post_mknod = selinux_inode_post_mknod, | ||
4313 | .inode_rename = selinux_inode_rename, | 4256 | .inode_rename = selinux_inode_rename, |
4314 | .inode_post_rename = selinux_inode_post_rename, | ||
4315 | .inode_readlink = selinux_inode_readlink, | 4257 | .inode_readlink = selinux_inode_readlink, |
4316 | .inode_follow_link = selinux_inode_follow_link, | 4258 | .inode_follow_link = selinux_inode_follow_link, |
4317 | .inode_permission = selinux_inode_permission, | 4259 | .inode_permission = selinux_inode_permission, |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 71c0a19c9753..5f016c98056f 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -23,10 +23,11 @@ | |||
23 | #define POLICYDB_VERSION_NLCLASS 18 | 23 | #define POLICYDB_VERSION_NLCLASS 18 |
24 | #define POLICYDB_VERSION_VALIDATETRANS 19 | 24 | #define POLICYDB_VERSION_VALIDATETRANS 19 |
25 | #define POLICYDB_VERSION_MLS 19 | 25 | #define POLICYDB_VERSION_MLS 19 |
26 | #define POLICYDB_VERSION_AVTAB 20 | ||
26 | 27 | ||
27 | /* Range of policy versions we understand*/ | 28 | /* Range of policy versions we understand*/ |
28 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE | 29 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
29 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_MLS | 30 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB |
30 | 31 | ||
31 | #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM | 32 | #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM |
32 | extern int selinux_enabled; | 33 | extern int selinux_enabled; |
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 18d08acafa78..e203883406dd 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c | |||
@@ -80,7 +80,8 @@ static void selnl_notify(int msgtype, void *data) | |||
80 | nlh = NLMSG_PUT(skb, 0, 0, msgtype, len); | 80 | nlh = NLMSG_PUT(skb, 0, 0, msgtype, len); |
81 | selnl_add_payload(nlh, len, msgtype, data); | 81 | selnl_add_payload(nlh, len, msgtype, data); |
82 | nlh->nlmsg_len = skb->tail - tmp; | 82 | nlh->nlmsg_len = skb->tail - tmp; |
83 | netlink_broadcast(selnl, skb, 0, SELNL_GRP_AVC, GFP_USER); | 83 | NETLINK_CB(skb).dst_group = SELNLGRP_AVC; |
84 | netlink_broadcast(selnl, skb, 0, SELNLGRP_AVC, GFP_USER); | ||
84 | out: | 85 | out: |
85 | return; | 86 | return; |
86 | 87 | ||
@@ -103,7 +104,8 @@ void selnl_notify_policyload(u32 seqno) | |||
103 | 104 | ||
104 | static int __init selnl_init(void) | 105 | static int __init selnl_init(void) |
105 | { | 106 | { |
106 | selnl = netlink_kernel_create(NETLINK_SELINUX, NULL); | 107 | selnl = netlink_kernel_create(NETLINK_SELINUX, SELNLGRP_MAX, NULL, |
108 | THIS_MODULE); | ||
107 | if (selnl == NULL) | 109 | if (selnl == NULL) |
108 | panic("SELinux: Cannot create netlink socket."); | 110 | panic("SELinux: Cannot create netlink socket."); |
109 | netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV); | 111 | netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV); |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 92b057becb4b..69b9329b2054 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
17 | #include <linux/if.h> | 17 | #include <linux/if.h> |
18 | #include <linux/netfilter_ipv4/ip_queue.h> | 18 | #include <linux/netfilter_ipv4/ip_queue.h> |
19 | #include <linux/tcp_diag.h> | 19 | #include <linux/inet_diag.h> |
20 | #include <linux/xfrm.h> | 20 | #include <linux/xfrm.h> |
21 | #include <linux/audit.h> | 21 | #include <linux/audit.h> |
22 | 22 | ||
@@ -76,6 +76,7 @@ static struct nlmsg_perm nlmsg_firewall_perms[] = | |||
76 | static struct nlmsg_perm nlmsg_tcpdiag_perms[] = | 76 | static struct nlmsg_perm nlmsg_tcpdiag_perms[] = |
77 | { | 77 | { |
78 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, | 78 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, |
79 | { DCCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, | ||
79 | }; | 80 | }; |
80 | 81 | ||
81 | static struct nlmsg_perm nlmsg_xfrm_perms[] = | 82 | static struct nlmsg_perm nlmsg_xfrm_perms[] = |
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index f238c034c44e..dde094feb20d 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 | |||
58 | { | 58 | { |
59 | int hvalue; | 59 | int hvalue; |
60 | struct avtab_node *prev, *cur, *newnode; | 60 | struct avtab_node *prev, *cur, *newnode; |
61 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); | ||
61 | 62 | ||
62 | if (!h) | 63 | if (!h) |
63 | return -EINVAL; | 64 | return -EINVAL; |
@@ -69,7 +70,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat | |||
69 | if (key->source_type == cur->key.source_type && | 70 | if (key->source_type == cur->key.source_type && |
70 | key->target_type == cur->key.target_type && | 71 | key->target_type == cur->key.target_type && |
71 | key->target_class == cur->key.target_class && | 72 | key->target_class == cur->key.target_class && |
72 | (datum->specified & cur->datum.specified)) | 73 | (specified & cur->key.specified)) |
73 | return -EEXIST; | 74 | return -EEXIST; |
74 | if (key->source_type < cur->key.source_type) | 75 | if (key->source_type < cur->key.source_type) |
75 | break; | 76 | break; |
@@ -98,6 +99,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da | |||
98 | { | 99 | { |
99 | int hvalue; | 100 | int hvalue; |
100 | struct avtab_node *prev, *cur, *newnode; | 101 | struct avtab_node *prev, *cur, *newnode; |
102 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); | ||
101 | 103 | ||
102 | if (!h) | 104 | if (!h) |
103 | return NULL; | 105 | return NULL; |
@@ -108,7 +110,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da | |||
108 | if (key->source_type == cur->key.source_type && | 110 | if (key->source_type == cur->key.source_type && |
109 | key->target_type == cur->key.target_type && | 111 | key->target_type == cur->key.target_type && |
110 | key->target_class == cur->key.target_class && | 112 | key->target_class == cur->key.target_class && |
111 | (datum->specified & cur->datum.specified)) | 113 | (specified & cur->key.specified)) |
112 | break; | 114 | break; |
113 | if (key->source_type < cur->key.source_type) | 115 | if (key->source_type < cur->key.source_type) |
114 | break; | 116 | break; |
@@ -125,10 +127,11 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da | |||
125 | return newnode; | 127 | return newnode; |
126 | } | 128 | } |
127 | 129 | ||
128 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified) | 130 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) |
129 | { | 131 | { |
130 | int hvalue; | 132 | int hvalue; |
131 | struct avtab_node *cur; | 133 | struct avtab_node *cur; |
134 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); | ||
132 | 135 | ||
133 | if (!h) | 136 | if (!h) |
134 | return NULL; | 137 | return NULL; |
@@ -138,7 +141,7 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int spe | |||
138 | if (key->source_type == cur->key.source_type && | 141 | if (key->source_type == cur->key.source_type && |
139 | key->target_type == cur->key.target_type && | 142 | key->target_type == cur->key.target_type && |
140 | key->target_class == cur->key.target_class && | 143 | key->target_class == cur->key.target_class && |
141 | (specified & cur->datum.specified)) | 144 | (specified & cur->key.specified)) |
142 | return &cur->datum; | 145 | return &cur->datum; |
143 | 146 | ||
144 | if (key->source_type < cur->key.source_type) | 147 | 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 | |||
159 | * conjunction with avtab_search_next_node() | 162 | * conjunction with avtab_search_next_node() |
160 | */ | 163 | */ |
161 | struct avtab_node* | 164 | struct avtab_node* |
162 | avtab_search_node(struct avtab *h, struct avtab_key *key, int specified) | 165 | avtab_search_node(struct avtab *h, struct avtab_key *key) |
163 | { | 166 | { |
164 | int hvalue; | 167 | int hvalue; |
165 | struct avtab_node *cur; | 168 | struct avtab_node *cur; |
169 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); | ||
166 | 170 | ||
167 | if (!h) | 171 | if (!h) |
168 | return NULL; | 172 | return NULL; |
@@ -172,7 +176,7 @@ avtab_search_node(struct avtab *h, struct avtab_key *key, int specified) | |||
172 | if (key->source_type == cur->key.source_type && | 176 | if (key->source_type == cur->key.source_type && |
173 | key->target_type == cur->key.target_type && | 177 | key->target_type == cur->key.target_type && |
174 | key->target_class == cur->key.target_class && | 178 | key->target_class == cur->key.target_class && |
175 | (specified & cur->datum.specified)) | 179 | (specified & cur->key.specified)) |
176 | return cur; | 180 | return cur; |
177 | 181 | ||
178 | if (key->source_type < cur->key.source_type) | 182 | if (key->source_type < cur->key.source_type) |
@@ -196,11 +200,12 @@ avtab_search_node_next(struct avtab_node *node, int specified) | |||
196 | if (!node) | 200 | if (!node) |
197 | return NULL; | 201 | return NULL; |
198 | 202 | ||
203 | specified &= ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); | ||
199 | for (cur = node->next; cur; cur = cur->next) { | 204 | for (cur = node->next; cur; cur = cur->next) { |
200 | if (node->key.source_type == cur->key.source_type && | 205 | if (node->key.source_type == cur->key.source_type && |
201 | node->key.target_type == cur->key.target_type && | 206 | node->key.target_type == cur->key.target_type && |
202 | node->key.target_class == cur->key.target_class && | 207 | node->key.target_class == cur->key.target_class && |
203 | (specified & cur->datum.specified)) | 208 | (specified & cur->key.specified)) |
204 | return cur; | 209 | return cur; |
205 | 210 | ||
206 | if (node->key.source_type < cur->key.source_type) | 211 | if (node->key.source_type < cur->key.source_type) |
@@ -278,76 +283,129 @@ void avtab_hash_eval(struct avtab *h, char *tag) | |||
278 | max_chain_len); | 283 | max_chain_len); |
279 | } | 284 | } |
280 | 285 | ||
281 | int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey) | 286 | static uint16_t spec_order[] = { |
287 | AVTAB_ALLOWED, | ||
288 | AVTAB_AUDITDENY, | ||
289 | AVTAB_AUDITALLOW, | ||
290 | AVTAB_TRANSITION, | ||
291 | AVTAB_CHANGE, | ||
292 | AVTAB_MEMBER | ||
293 | }; | ||
294 | |||
295 | int avtab_read_item(void *fp, u32 vers, struct avtab *a, | ||
296 | int (*insertf)(struct avtab *a, struct avtab_key *k, | ||
297 | struct avtab_datum *d, void *p), | ||
298 | void *p) | ||
282 | { | 299 | { |
283 | u32 buf[7]; | 300 | __le16 buf16[4]; |
284 | u32 items, items2; | 301 | u16 enabled; |
285 | int rc; | 302 | __le32 buf32[7]; |
303 | u32 items, items2, val; | ||
304 | struct avtab_key key; | ||
305 | struct avtab_datum datum; | ||
306 | int i, rc; | ||
307 | |||
308 | memset(&key, 0, sizeof(struct avtab_key)); | ||
309 | memset(&datum, 0, sizeof(struct avtab_datum)); | ||
310 | |||
311 | if (vers < POLICYDB_VERSION_AVTAB) { | ||
312 | rc = next_entry(buf32, fp, sizeof(u32)); | ||
313 | if (rc < 0) { | ||
314 | printk(KERN_ERR "security: avtab: truncated entry\n"); | ||
315 | return -1; | ||
316 | } | ||
317 | items2 = le32_to_cpu(buf32[0]); | ||
318 | if (items2 > ARRAY_SIZE(buf32)) { | ||
319 | printk(KERN_ERR "security: avtab: entry overflow\n"); | ||
320 | return -1; | ||
286 | 321 | ||
287 | memset(avkey, 0, sizeof(struct avtab_key)); | 322 | } |
288 | memset(avdatum, 0, sizeof(struct avtab_datum)); | 323 | rc = next_entry(buf32, fp, sizeof(u32)*items2); |
324 | if (rc < 0) { | ||
325 | printk(KERN_ERR "security: avtab: truncated entry\n"); | ||
326 | return -1; | ||
327 | } | ||
328 | items = 0; | ||
289 | 329 | ||
290 | rc = next_entry(buf, fp, sizeof(u32)); | 330 | val = le32_to_cpu(buf32[items++]); |
291 | if (rc < 0) { | 331 | key.source_type = (u16)val; |
292 | printk(KERN_ERR "security: avtab: truncated entry\n"); | 332 | if (key.source_type != val) { |
293 | goto bad; | 333 | printk("security: avtab: truncated source type\n"); |
294 | } | 334 | return -1; |
295 | items2 = le32_to_cpu(buf[0]); | 335 | } |
296 | if (items2 > ARRAY_SIZE(buf)) { | 336 | val = le32_to_cpu(buf32[items++]); |
297 | printk(KERN_ERR "security: avtab: entry overflow\n"); | 337 | key.target_type = (u16)val; |
298 | goto bad; | 338 | if (key.target_type != val) { |
339 | printk("security: avtab: truncated target type\n"); | ||
340 | return -1; | ||
341 | } | ||
342 | val = le32_to_cpu(buf32[items++]); | ||
343 | key.target_class = (u16)val; | ||
344 | if (key.target_class != val) { | ||
345 | printk("security: avtab: truncated target class\n"); | ||
346 | return -1; | ||
347 | } | ||
348 | |||
349 | val = le32_to_cpu(buf32[items++]); | ||
350 | enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; | ||
351 | |||
352 | if (!(val & (AVTAB_AV | AVTAB_TYPE))) { | ||
353 | printk("security: avtab: null entry\n"); | ||
354 | return -1; | ||
355 | } | ||
356 | if ((val & AVTAB_AV) && | ||
357 | (val & AVTAB_TYPE)) { | ||
358 | printk("security: avtab: entry has both access vectors and types\n"); | ||
359 | return -1; | ||
360 | } | ||
361 | |||
362 | for (i = 0; i < sizeof(spec_order)/sizeof(u16); i++) { | ||
363 | if (val & spec_order[i]) { | ||
364 | key.specified = spec_order[i] | enabled; | ||
365 | datum.data = le32_to_cpu(buf32[items++]); | ||
366 | rc = insertf(a, &key, &datum, p); | ||
367 | if (rc) return rc; | ||
368 | } | ||
369 | } | ||
370 | |||
371 | if (items != items2) { | ||
372 | printk("security: avtab: entry only had %d items, expected %d\n", items2, items); | ||
373 | return -1; | ||
374 | } | ||
375 | return 0; | ||
299 | } | 376 | } |
300 | rc = next_entry(buf, fp, sizeof(u32)*items2); | 377 | |
378 | rc = next_entry(buf16, fp, sizeof(u16)*4); | ||
301 | if (rc < 0) { | 379 | if (rc < 0) { |
302 | printk(KERN_ERR "security: avtab: truncated entry\n"); | 380 | printk("security: avtab: truncated entry\n"); |
303 | goto bad; | 381 | return -1; |
304 | } | 382 | } |
383 | |||
305 | items = 0; | 384 | items = 0; |
306 | avkey->source_type = le32_to_cpu(buf[items++]); | 385 | key.source_type = le16_to_cpu(buf16[items++]); |
307 | avkey->target_type = le32_to_cpu(buf[items++]); | 386 | key.target_type = le16_to_cpu(buf16[items++]); |
308 | avkey->target_class = le32_to_cpu(buf[items++]); | 387 | key.target_class = le16_to_cpu(buf16[items++]); |
309 | avdatum->specified = le32_to_cpu(buf[items++]); | 388 | key.specified = le16_to_cpu(buf16[items++]); |
310 | if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) { | 389 | |
311 | printk(KERN_ERR "security: avtab: null entry\n"); | 390 | rc = next_entry(buf32, fp, sizeof(u32)); |
312 | goto bad; | 391 | if (rc < 0) { |
313 | } | 392 | printk("security: avtab: truncated entry\n"); |
314 | if ((avdatum->specified & AVTAB_AV) && | 393 | return -1; |
315 | (avdatum->specified & AVTAB_TYPE)) { | ||
316 | printk(KERN_ERR "security: avtab: entry has both access vectors and types\n"); | ||
317 | goto bad; | ||
318 | } | ||
319 | if (avdatum->specified & AVTAB_AV) { | ||
320 | if (avdatum->specified & AVTAB_ALLOWED) | ||
321 | avtab_allowed(avdatum) = le32_to_cpu(buf[items++]); | ||
322 | if (avdatum->specified & AVTAB_AUDITDENY) | ||
323 | avtab_auditdeny(avdatum) = le32_to_cpu(buf[items++]); | ||
324 | if (avdatum->specified & AVTAB_AUDITALLOW) | ||
325 | avtab_auditallow(avdatum) = le32_to_cpu(buf[items++]); | ||
326 | } else { | ||
327 | if (avdatum->specified & AVTAB_TRANSITION) | ||
328 | avtab_transition(avdatum) = le32_to_cpu(buf[items++]); | ||
329 | if (avdatum->specified & AVTAB_CHANGE) | ||
330 | avtab_change(avdatum) = le32_to_cpu(buf[items++]); | ||
331 | if (avdatum->specified & AVTAB_MEMBER) | ||
332 | avtab_member(avdatum) = le32_to_cpu(buf[items++]); | ||
333 | } | ||
334 | if (items != items2) { | ||
335 | printk(KERN_ERR "security: avtab: entry only had %d items, expected %d\n", | ||
336 | items2, items); | ||
337 | goto bad; | ||
338 | } | 394 | } |
395 | datum.data = le32_to_cpu(*buf32); | ||
396 | return insertf(a, &key, &datum, p); | ||
397 | } | ||
339 | 398 | ||
340 | return 0; | 399 | static int avtab_insertf(struct avtab *a, struct avtab_key *k, |
341 | bad: | 400 | struct avtab_datum *d, void *p) |
342 | return -1; | 401 | { |
402 | return avtab_insert(a, k, d); | ||
343 | } | 403 | } |
344 | 404 | ||
345 | int avtab_read(struct avtab *a, void *fp, u32 config) | 405 | int avtab_read(struct avtab *a, void *fp, u32 vers) |
346 | { | 406 | { |
347 | int rc; | 407 | int rc; |
348 | struct avtab_key avkey; | 408 | __le32 buf[1]; |
349 | struct avtab_datum avdatum; | ||
350 | u32 buf[1]; | ||
351 | u32 nel, i; | 409 | u32 nel, i; |
352 | 410 | ||
353 | 411 | ||
@@ -363,16 +421,14 @@ int avtab_read(struct avtab *a, void *fp, u32 config) | |||
363 | goto bad; | 421 | goto bad; |
364 | } | 422 | } |
365 | for (i = 0; i < nel; i++) { | 423 | for (i = 0; i < nel; i++) { |
366 | if (avtab_read_item(fp, &avdatum, &avkey)) { | 424 | rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL); |
367 | rc = -EINVAL; | ||
368 | goto bad; | ||
369 | } | ||
370 | rc = avtab_insert(a, &avkey, &avdatum); | ||
371 | if (rc) { | 425 | if (rc) { |
372 | if (rc == -ENOMEM) | 426 | if (rc == -ENOMEM) |
373 | printk(KERN_ERR "security: avtab: out of memory\n"); | 427 | printk(KERN_ERR "security: avtab: out of memory\n"); |
374 | if (rc == -EEXIST) | 428 | else if (rc == -EEXIST) |
375 | printk(KERN_ERR "security: avtab: duplicate entry\n"); | 429 | printk(KERN_ERR "security: avtab: duplicate entry\n"); |
430 | else | ||
431 | rc = -EINVAL; | ||
376 | goto bad; | 432 | goto bad; |
377 | } | 433 | } |
378 | } | 434 | } |
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 519d4f6dc655..0a90d939af93 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h | |||
@@ -21,12 +21,9 @@ | |||
21 | #define _SS_AVTAB_H_ | 21 | #define _SS_AVTAB_H_ |
22 | 22 | ||
23 | struct avtab_key { | 23 | struct avtab_key { |
24 | u32 source_type; /* source type */ | 24 | u16 source_type; /* source type */ |
25 | u32 target_type; /* target type */ | 25 | u16 target_type; /* target type */ |
26 | u32 target_class; /* target object class */ | 26 | u16 target_class; /* target object class */ |
27 | }; | ||
28 | |||
29 | struct avtab_datum { | ||
30 | #define AVTAB_ALLOWED 1 | 27 | #define AVTAB_ALLOWED 1 |
31 | #define AVTAB_AUDITALLOW 2 | 28 | #define AVTAB_AUDITALLOW 2 |
32 | #define AVTAB_AUDITDENY 4 | 29 | #define AVTAB_AUDITDENY 4 |
@@ -35,15 +32,13 @@ struct avtab_datum { | |||
35 | #define AVTAB_MEMBER 32 | 32 | #define AVTAB_MEMBER 32 |
36 | #define AVTAB_CHANGE 64 | 33 | #define AVTAB_CHANGE 64 |
37 | #define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) | 34 | #define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) |
38 | #define AVTAB_ENABLED 0x80000000 /* reserved for used in cond_avtab */ | 35 | #define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */ |
39 | u32 specified; /* what fields are specified */ | 36 | #define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ |
40 | u32 data[3]; /* access vectors or types */ | 37 | u16 specified; /* what field is specified */ |
41 | #define avtab_allowed(x) (x)->data[0] | 38 | }; |
42 | #define avtab_auditdeny(x) (x)->data[1] | 39 | |
43 | #define avtab_auditallow(x) (x)->data[2] | 40 | struct avtab_datum { |
44 | #define avtab_transition(x) (x)->data[0] | 41 | u32 data; /* access vector or type value */ |
45 | #define avtab_change(x) (x)->data[1] | ||
46 | #define avtab_member(x) (x)->data[2] | ||
47 | }; | 42 | }; |
48 | 43 | ||
49 | struct avtab_node { | 44 | struct avtab_node { |
@@ -58,17 +53,21 @@ struct avtab { | |||
58 | }; | 53 | }; |
59 | 54 | ||
60 | int avtab_init(struct avtab *); | 55 | int avtab_init(struct avtab *); |
61 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k, int specified); | 56 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k); |
62 | void avtab_destroy(struct avtab *h); | 57 | void avtab_destroy(struct avtab *h); |
63 | void avtab_hash_eval(struct avtab *h, char *tag); | 58 | void avtab_hash_eval(struct avtab *h, char *tag); |
64 | 59 | ||
65 | int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey); | 60 | int avtab_read_item(void *fp, uint32_t vers, struct avtab *a, |
66 | int avtab_read(struct avtab *a, void *fp, u32 config); | 61 | int (*insert)(struct avtab *a, struct avtab_key *k, |
62 | struct avtab_datum *d, void *p), | ||
63 | void *p); | ||
64 | |||
65 | int avtab_read(struct avtab *a, void *fp, u32 vers); | ||
67 | 66 | ||
68 | struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, | 67 | struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, |
69 | struct avtab_datum *datum); | 68 | struct avtab_datum *datum); |
70 | 69 | ||
71 | struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key, int specified); | 70 | struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key); |
72 | 71 | ||
73 | struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); | 72 | struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); |
74 | 73 | ||
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index e2057f5a411a..daf288007460 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) | |||
100 | /* turn the rules on or off */ | 100 | /* turn the rules on or off */ |
101 | for (cur = node->true_list; cur != NULL; cur = cur->next) { | 101 | for (cur = node->true_list; cur != NULL; cur = cur->next) { |
102 | if (new_state <= 0) { | 102 | if (new_state <= 0) { |
103 | cur->node->datum.specified &= ~AVTAB_ENABLED; | 103 | cur->node->key.specified &= ~AVTAB_ENABLED; |
104 | } else { | 104 | } else { |
105 | cur->node->datum.specified |= AVTAB_ENABLED; | 105 | cur->node->key.specified |= AVTAB_ENABLED; |
106 | } | 106 | } |
107 | } | 107 | } |
108 | 108 | ||
109 | for (cur = node->false_list; cur != NULL; cur = cur->next) { | 109 | for (cur = node->false_list; cur != NULL; cur = cur->next) { |
110 | /* -1 or 1 */ | 110 | /* -1 or 1 */ |
111 | if (new_state) { | 111 | if (new_state) { |
112 | cur->node->datum.specified &= ~AVTAB_ENABLED; | 112 | cur->node->key.specified &= ~AVTAB_ENABLED; |
113 | } else { | 113 | } else { |
114 | cur->node->datum.specified |= AVTAB_ENABLED; | 114 | cur->node->key.specified |= AVTAB_ENABLED; |
115 | } | 115 | } |
116 | } | 116 | } |
117 | } | 117 | } |
@@ -216,7 +216,8 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) | |||
216 | { | 216 | { |
217 | char *key = NULL; | 217 | char *key = NULL; |
218 | struct cond_bool_datum *booldatum; | 218 | struct cond_bool_datum *booldatum; |
219 | u32 buf[3], len; | 219 | __le32 buf[3]; |
220 | u32 len; | ||
220 | int rc; | 221 | int rc; |
221 | 222 | ||
222 | booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); | 223 | booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); |
@@ -252,104 +253,127 @@ err: | |||
252 | return -1; | 253 | return -1; |
253 | } | 254 | } |
254 | 255 | ||
255 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, | 256 | struct cond_insertf_data |
256 | struct cond_av_list *other) | ||
257 | { | 257 | { |
258 | struct cond_av_list *list, *last = NULL, *cur; | 258 | struct policydb *p; |
259 | struct avtab_key key; | 259 | struct cond_av_list *other; |
260 | struct avtab_datum datum; | 260 | struct cond_av_list *head; |
261 | struct cond_av_list *tail; | ||
262 | }; | ||
263 | |||
264 | static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr) | ||
265 | { | ||
266 | struct cond_insertf_data *data = ptr; | ||
267 | struct policydb *p = data->p; | ||
268 | struct cond_av_list *other = data->other, *list, *cur; | ||
261 | struct avtab_node *node_ptr; | 269 | struct avtab_node *node_ptr; |
262 | int rc; | ||
263 | u32 buf[1], i, len; | ||
264 | u8 found; | 270 | u8 found; |
265 | 271 | ||
266 | *ret_list = NULL; | ||
267 | |||
268 | len = 0; | ||
269 | rc = next_entry(buf, fp, sizeof buf); | ||
270 | if (rc < 0) | ||
271 | return -1; | ||
272 | |||
273 | len = le32_to_cpu(buf[0]); | ||
274 | if (len == 0) { | ||
275 | return 0; | ||
276 | } | ||
277 | 272 | ||
278 | for (i = 0; i < len; i++) { | 273 | /* |
279 | if (avtab_read_item(fp, &datum, &key)) | 274 | * For type rules we have to make certain there aren't any |
275 | * conflicting rules by searching the te_avtab and the | ||
276 | * cond_te_avtab. | ||
277 | */ | ||
278 | if (k->specified & AVTAB_TYPE) { | ||
279 | if (avtab_search(&p->te_avtab, k)) { | ||
280 | printk("security: type rule already exists outside of a conditional."); | ||
280 | goto err; | 281 | goto err; |
281 | 282 | } | |
282 | /* | 283 | /* |
283 | * For type rules we have to make certain there aren't any | 284 | * If we are reading the false list other will be a pointer to |
284 | * conflicting rules by searching the te_avtab and the | 285 | * the true list. We can have duplicate entries if there is only |
285 | * cond_te_avtab. | 286 | * 1 other entry and it is in our true list. |
287 | * | ||
288 | * If we are reading the true list (other == NULL) there shouldn't | ||
289 | * be any other entries. | ||
286 | */ | 290 | */ |
287 | if (datum.specified & AVTAB_TYPE) { | 291 | if (other) { |
288 | if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) { | 292 | node_ptr = avtab_search_node(&p->te_cond_avtab, k); |
289 | printk("security: type rule already exists outside of a conditional."); | 293 | if (node_ptr) { |
290 | goto err; | 294 | if (avtab_search_node_next(node_ptr, k->specified)) { |
291 | } | 295 | printk("security: too many conflicting type rules."); |
292 | /* | 296 | goto err; |
293 | * If we are reading the false list other will be a pointer to | 297 | } |
294 | * the true list. We can have duplicate entries if there is only | 298 | found = 0; |
295 | * 1 other entry and it is in our true list. | 299 | for (cur = other; cur != NULL; cur = cur->next) { |
296 | * | 300 | if (cur->node == node_ptr) { |
297 | * If we are reading the true list (other == NULL) there shouldn't | 301 | found = 1; |
298 | * be any other entries. | 302 | break; |
299 | */ | ||
300 | if (other) { | ||
301 | node_ptr = avtab_search_node(&p->te_cond_avtab, &key, AVTAB_TYPE); | ||
302 | if (node_ptr) { | ||
303 | if (avtab_search_node_next(node_ptr, AVTAB_TYPE)) { | ||
304 | printk("security: too many conflicting type rules."); | ||
305 | goto err; | ||
306 | } | ||
307 | found = 0; | ||
308 | for (cur = other; cur != NULL; cur = cur->next) { | ||
309 | if (cur->node == node_ptr) { | ||
310 | found = 1; | ||
311 | break; | ||
312 | } | ||
313 | } | ||
314 | if (!found) { | ||
315 | printk("security: conflicting type rules."); | ||
316 | goto err; | ||
317 | } | 303 | } |
318 | } | 304 | } |
319 | } else { | 305 | if (!found) { |
320 | if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) { | 306 | printk("security: conflicting type rules.\n"); |
321 | printk("security: conflicting type rules when adding type rule for true."); | ||
322 | goto err; | 307 | goto err; |
323 | } | 308 | } |
324 | } | 309 | } |
310 | } else { | ||
311 | if (avtab_search(&p->te_cond_avtab, k)) { | ||
312 | printk("security: conflicting type rules when adding type rule for true.\n"); | ||
313 | goto err; | ||
314 | } | ||
325 | } | 315 | } |
326 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum); | 316 | } |
327 | if (!node_ptr) { | ||
328 | printk("security: could not insert rule."); | ||
329 | goto err; | ||
330 | } | ||
331 | |||
332 | list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL); | ||
333 | if (!list) | ||
334 | goto err; | ||
335 | memset(list, 0, sizeof(struct cond_av_list)); | ||
336 | |||
337 | list->node = node_ptr; | ||
338 | if (i == 0) | ||
339 | *ret_list = list; | ||
340 | else | ||
341 | last->next = list; | ||
342 | last = list; | ||
343 | 317 | ||
318 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); | ||
319 | if (!node_ptr) { | ||
320 | printk("security: could not insert rule."); | ||
321 | goto err; | ||
344 | } | 322 | } |
345 | 323 | ||
324 | list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL); | ||
325 | if (!list) | ||
326 | goto err; | ||
327 | memset(list, 0, sizeof(*list)); | ||
328 | |||
329 | list->node = node_ptr; | ||
330 | if (!data->head) | ||
331 | data->head = list; | ||
332 | else | ||
333 | data->tail->next = list; | ||
334 | data->tail = list; | ||
346 | return 0; | 335 | return 0; |
336 | |||
347 | err: | 337 | err: |
348 | cond_av_list_destroy(*ret_list); | 338 | cond_av_list_destroy(data->head); |
349 | *ret_list = NULL; | 339 | data->head = NULL; |
350 | return -1; | 340 | return -1; |
351 | } | 341 | } |
352 | 342 | ||
343 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) | ||
344 | { | ||
345 | int i, rc; | ||
346 | __le32 buf[1]; | ||
347 | u32 len; | ||
348 | struct cond_insertf_data data; | ||
349 | |||
350 | *ret_list = NULL; | ||
351 | |||
352 | len = 0; | ||
353 | rc = next_entry(buf, fp, sizeof(u32)); | ||
354 | if (rc < 0) | ||
355 | return -1; | ||
356 | |||
357 | len = le32_to_cpu(buf[0]); | ||
358 | if (len == 0) { | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | data.p = p; | ||
363 | data.other = other; | ||
364 | data.head = NULL; | ||
365 | data.tail = NULL; | ||
366 | for (i = 0; i < len; i++) { | ||
367 | rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data); | ||
368 | if (rc) | ||
369 | return rc; | ||
370 | |||
371 | } | ||
372 | |||
373 | *ret_list = data.head; | ||
374 | return 0; | ||
375 | } | ||
376 | |||
353 | static int expr_isvalid(struct policydb *p, struct cond_expr *expr) | 377 | static int expr_isvalid(struct policydb *p, struct cond_expr *expr) |
354 | { | 378 | { |
355 | if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { | 379 | 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) | |||
366 | 390 | ||
367 | static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) | 391 | static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) |
368 | { | 392 | { |
369 | u32 buf[2], len, i; | 393 | __le32 buf[2]; |
394 | u32 len, i; | ||
370 | int rc; | 395 | int rc; |
371 | struct cond_expr *expr = NULL, *last = NULL; | 396 | struct cond_expr *expr = NULL, *last = NULL; |
372 | 397 | ||
@@ -424,7 +449,8 @@ err: | |||
424 | int cond_read_list(struct policydb *p, void *fp) | 449 | int cond_read_list(struct policydb *p, void *fp) |
425 | { | 450 | { |
426 | struct cond_node *node, *last = NULL; | 451 | struct cond_node *node, *last = NULL; |
427 | u32 buf[1], i, len; | 452 | __le32 buf[1]; |
453 | u32 i, len; | ||
428 | int rc; | 454 | int rc; |
429 | 455 | ||
430 | rc = next_entry(buf, fp, sizeof buf); | 456 | rc = next_entry(buf, fp, sizeof buf); |
@@ -452,6 +478,7 @@ int cond_read_list(struct policydb *p, void *fp) | |||
452 | return 0; | 478 | return 0; |
453 | err: | 479 | err: |
454 | cond_list_destroy(p->cond_list); | 480 | cond_list_destroy(p->cond_list); |
481 | p->cond_list = NULL; | ||
455 | return -1; | 482 | return -1; |
456 | } | 483 | } |
457 | 484 | ||
@@ -465,22 +492,22 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi | |||
465 | if(!ctab || !key || !avd) | 492 | if(!ctab || !key || !avd) |
466 | return; | 493 | return; |
467 | 494 | ||
468 | for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL; | 495 | for(node = avtab_search_node(ctab, key); node != NULL; |
469 | node = avtab_search_node_next(node, AVTAB_AV)) { | 496 | node = avtab_search_node_next(node, key->specified)) { |
470 | if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) == | 497 | if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) == |
471 | (node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) | 498 | (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) |
472 | avd->allowed |= avtab_allowed(&node->datum); | 499 | avd->allowed |= node->datum.data; |
473 | if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) == | 500 | if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) == |
474 | (node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) | 501 | (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) |
475 | /* Since a '0' in an auditdeny mask represents a | 502 | /* Since a '0' in an auditdeny mask represents a |
476 | * permission we do NOT want to audit (dontaudit), we use | 503 | * permission we do NOT want to audit (dontaudit), we use |
477 | * the '&' operand to ensure that all '0's in the mask | 504 | * the '&' operand to ensure that all '0's in the mask |
478 | * are retained (much unlike the allow and auditallow cases). | 505 | * are retained (much unlike the allow and auditallow cases). |
479 | */ | 506 | */ |
480 | avd->auditdeny &= avtab_auditdeny(&node->datum); | 507 | avd->auditdeny &= node->datum.data; |
481 | if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == | 508 | if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == |
482 | (node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) | 509 | (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) |
483 | avd->auditallow |= avtab_auditallow(&node->datum); | 510 | avd->auditallow |= node->datum.data; |
484 | } | 511 | } |
485 | return; | 512 | return; |
486 | } | 513 | } |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index d8ce9cc0b9f1..d515154128cc 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) | |||
196 | { | 196 | { |
197 | int rc; | 197 | int rc; |
198 | struct ebitmap_node *n, *l; | 198 | struct ebitmap_node *n, *l; |
199 | u32 buf[3], mapsize, count, i; | 199 | __le32 buf[3]; |
200 | u64 map; | 200 | u32 mapsize, count, i; |
201 | __le64 map; | ||
201 | 202 | ||
202 | ebitmap_init(e); | 203 | ebitmap_init(e); |
203 | 204 | ||
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index 471370233fd9..8bf41055a6cb 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h | |||
@@ -32,11 +32,41 @@ struct ebitmap { | |||
32 | #define ebitmap_length(e) ((e)->highbit) | 32 | #define ebitmap_length(e) ((e)->highbit) |
33 | #define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) | 33 | #define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) |
34 | 34 | ||
35 | static inline unsigned int ebitmap_start(struct ebitmap *e, | ||
36 | struct ebitmap_node **n) | ||
37 | { | ||
38 | *n = e->node; | ||
39 | return ebitmap_startbit(e); | ||
40 | } | ||
41 | |||
35 | static inline void ebitmap_init(struct ebitmap *e) | 42 | static inline void ebitmap_init(struct ebitmap *e) |
36 | { | 43 | { |
37 | memset(e, 0, sizeof(*e)); | 44 | memset(e, 0, sizeof(*e)); |
38 | } | 45 | } |
39 | 46 | ||
47 | static inline unsigned int ebitmap_next(struct ebitmap_node **n, | ||
48 | unsigned int bit) | ||
49 | { | ||
50 | if ((bit == ((*n)->startbit + MAPSIZE - 1)) && | ||
51 | (*n)->next) { | ||
52 | *n = (*n)->next; | ||
53 | return (*n)->startbit; | ||
54 | } | ||
55 | |||
56 | return (bit+1); | ||
57 | } | ||
58 | |||
59 | static inline int ebitmap_node_get_bit(struct ebitmap_node * n, | ||
60 | unsigned int bit) | ||
61 | { | ||
62 | if (n->map & (MAPBIT << (bit - n->startbit))) | ||
63 | return 1; | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | #define ebitmap_for_each_bit(e, n, bit) \ | ||
68 | for (bit = ebitmap_start(e, &n); bit < ebitmap_length(e); bit = ebitmap_next(&n, bit)) \ | ||
69 | |||
40 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); | 70 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); |
41 | int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); | 71 | int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); |
42 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); | 72 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index d4c32c39ccc9..aaefac2921f1 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -27,6 +27,7 @@ | |||
27 | int mls_compute_context_len(struct context * context) | 27 | int mls_compute_context_len(struct context * context) |
28 | { | 28 | { |
29 | int i, l, len, range; | 29 | int i, l, len, range; |
30 | struct ebitmap_node *node; | ||
30 | 31 | ||
31 | if (!selinux_mls_enabled) | 32 | if (!selinux_mls_enabled) |
32 | return 0; | 33 | return 0; |
@@ -36,24 +37,24 @@ int mls_compute_context_len(struct context * context) | |||
36 | range = 0; | 37 | range = 0; |
37 | len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); | 38 | len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); |
38 | 39 | ||
39 | for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) { | 40 | ebitmap_for_each_bit(&context->range.level[l].cat, node, i) { |
40 | if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) { | 41 | if (ebitmap_node_get_bit(node, i)) { |
41 | if (range) { | 42 | if (range) { |
42 | range++; | 43 | range++; |
43 | continue; | 44 | continue; |
44 | } | 45 | } |
45 | 46 | ||
46 | len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; | 47 | len += strlen(policydb.p_cat_val_to_name[i]) + 1; |
47 | range++; | 48 | range++; |
48 | } else { | 49 | } else { |
49 | if (range > 1) | 50 | if (range > 1) |
50 | len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1; | 51 | len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; |
51 | range = 0; | 52 | range = 0; |
52 | } | 53 | } |
53 | } | 54 | } |
54 | /* Handle case where last category is the end of range */ | 55 | /* Handle case where last category is the end of range */ |
55 | if (range > 1) | 56 | if (range > 1) |
56 | len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1; | 57 | len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; |
57 | 58 | ||
58 | if (l == 0) { | 59 | if (l == 0) { |
59 | if (mls_level_eq(&context->range.level[0], | 60 | if (mls_level_eq(&context->range.level[0], |
@@ -77,6 +78,7 @@ void mls_sid_to_context(struct context *context, | |||
77 | { | 78 | { |
78 | char *scontextp; | 79 | char *scontextp; |
79 | int i, l, range, wrote_sep; | 80 | int i, l, range, wrote_sep; |
81 | struct ebitmap_node *node; | ||
80 | 82 | ||
81 | if (!selinux_mls_enabled) | 83 | if (!selinux_mls_enabled) |
82 | return; | 84 | return; |
@@ -94,8 +96,8 @@ void mls_sid_to_context(struct context *context, | |||
94 | scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); | 96 | scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); |
95 | 97 | ||
96 | /* categories */ | 98 | /* categories */ |
97 | for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) { | 99 | ebitmap_for_each_bit(&context->range.level[l].cat, node, i) { |
98 | if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) { | 100 | if (ebitmap_node_get_bit(node, i)) { |
99 | if (range) { | 101 | if (range) { |
100 | range++; | 102 | range++; |
101 | continue; | 103 | continue; |
@@ -106,8 +108,8 @@ void mls_sid_to_context(struct context *context, | |||
106 | wrote_sep = 1; | 108 | wrote_sep = 1; |
107 | } else | 109 | } else |
108 | *scontextp++ = ','; | 110 | *scontextp++ = ','; |
109 | strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); | 111 | strcpy(scontextp, policydb.p_cat_val_to_name[i]); |
110 | scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); | 112 | scontextp += strlen(policydb.p_cat_val_to_name[i]); |
111 | range++; | 113 | range++; |
112 | } else { | 114 | } else { |
113 | if (range > 1) { | 115 | if (range > 1) { |
@@ -116,8 +118,8 @@ void mls_sid_to_context(struct context *context, | |||
116 | else | 118 | else |
117 | *scontextp++ = ','; | 119 | *scontextp++ = ','; |
118 | 120 | ||
119 | strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]); | 121 | strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); |
120 | scontextp += strlen(policydb.p_cat_val_to_name[i - 2]); | 122 | scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); |
121 | } | 123 | } |
122 | range = 0; | 124 | range = 0; |
123 | } | 125 | } |
@@ -130,8 +132,8 @@ void mls_sid_to_context(struct context *context, | |||
130 | else | 132 | else |
131 | *scontextp++ = ','; | 133 | *scontextp++ = ','; |
132 | 134 | ||
133 | strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]); | 135 | strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); |
134 | scontextp += strlen(policydb.p_cat_val_to_name[i - 2]); | 136 | scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); |
135 | } | 137 | } |
136 | 138 | ||
137 | if (l == 0) { | 139 | if (l == 0) { |
@@ -157,6 +159,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c) | |||
157 | { | 159 | { |
158 | struct level_datum *levdatum; | 160 | struct level_datum *levdatum; |
159 | struct user_datum *usrdatum; | 161 | struct user_datum *usrdatum; |
162 | struct ebitmap_node *node; | ||
160 | int i, l; | 163 | int i, l; |
161 | 164 | ||
162 | if (!selinux_mls_enabled) | 165 | if (!selinux_mls_enabled) |
@@ -179,11 +182,11 @@ int mls_context_isvalid(struct policydb *p, struct context *c) | |||
179 | if (!levdatum) | 182 | if (!levdatum) |
180 | return 0; | 183 | return 0; |
181 | 184 | ||
182 | for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) { | 185 | ebitmap_for_each_bit(&c->range.level[l].cat, node, i) { |
183 | if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) { | 186 | if (ebitmap_node_get_bit(node, i)) { |
184 | if (i > p->p_cats.nprim) | 187 | if (i > p->p_cats.nprim) |
185 | return 0; | 188 | return 0; |
186 | if (!ebitmap_get_bit(&levdatum->level->cat, i - 1)) | 189 | if (!ebitmap_get_bit(&levdatum->level->cat, i)) |
187 | /* | 190 | /* |
188 | * Category may not be associated with | 191 | * Category may not be associated with |
189 | * sensitivity in low level. | 192 | * sensitivity in low level. |
@@ -468,6 +471,7 @@ int mls_convert_context(struct policydb *oldp, | |||
468 | struct level_datum *levdatum; | 471 | struct level_datum *levdatum; |
469 | struct cat_datum *catdatum; | 472 | struct cat_datum *catdatum; |
470 | struct ebitmap bitmap; | 473 | struct ebitmap bitmap; |
474 | struct ebitmap_node *node; | ||
471 | int l, i; | 475 | int l, i; |
472 | 476 | ||
473 | if (!selinux_mls_enabled) | 477 | if (!selinux_mls_enabled) |
@@ -482,12 +486,12 @@ int mls_convert_context(struct policydb *oldp, | |||
482 | c->range.level[l].sens = levdatum->level->sens; | 486 | c->range.level[l].sens = levdatum->level->sens; |
483 | 487 | ||
484 | ebitmap_init(&bitmap); | 488 | ebitmap_init(&bitmap); |
485 | for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) { | 489 | ebitmap_for_each_bit(&c->range.level[l].cat, node, i) { |
486 | if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) { | 490 | if (ebitmap_node_get_bit(node, i)) { |
487 | int rc; | 491 | int rc; |
488 | 492 | ||
489 | catdatum = hashtab_search(newp->p_cats.table, | 493 | catdatum = hashtab_search(newp->p_cats.table, |
490 | oldp->p_cat_val_to_name[i - 1]); | 494 | oldp->p_cat_val_to_name[i]); |
491 | if (!catdatum) | 495 | if (!catdatum) |
492 | return -EINVAL; | 496 | return -EINVAL; |
493 | rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1); | 497 | rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1); |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 785c33cf4864..0a758323a9cf 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -91,6 +91,11 @@ static struct policydb_compat_info policydb_compat[] = { | |||
91 | .sym_num = SYM_NUM, | 91 | .sym_num = SYM_NUM, |
92 | .ocon_num = OCON_NUM, | 92 | .ocon_num = OCON_NUM, |
93 | }, | 93 | }, |
94 | { | ||
95 | .version = POLICYDB_VERSION_AVTAB, | ||
96 | .sym_num = SYM_NUM, | ||
97 | .ocon_num = OCON_NUM, | ||
98 | }, | ||
94 | }; | 99 | }; |
95 | 100 | ||
96 | static struct policydb_compat_info *policydb_lookup_compat(int version) | 101 | static struct policydb_compat_info *policydb_lookup_compat(int version) |
@@ -584,6 +589,9 @@ void policydb_destroy(struct policydb *p) | |||
584 | struct ocontext *c, *ctmp; | 589 | struct ocontext *c, *ctmp; |
585 | struct genfs *g, *gtmp; | 590 | struct genfs *g, *gtmp; |
586 | int i; | 591 | int i; |
592 | struct role_allow *ra, *lra = NULL; | ||
593 | struct role_trans *tr, *ltr = NULL; | ||
594 | struct range_trans *rt, *lrt = NULL; | ||
587 | 595 | ||
588 | for (i = 0; i < SYM_NUM; i++) { | 596 | for (i = 0; i < SYM_NUM; i++) { |
589 | hashtab_map(p->symtab[i].table, destroy_f[i], NULL); | 597 | hashtab_map(p->symtab[i].table, destroy_f[i], NULL); |
@@ -624,6 +632,28 @@ void policydb_destroy(struct policydb *p) | |||
624 | 632 | ||
625 | cond_policydb_destroy(p); | 633 | cond_policydb_destroy(p); |
626 | 634 | ||
635 | for (tr = p->role_tr; tr; tr = tr->next) { | ||
636 | if (ltr) kfree(ltr); | ||
637 | ltr = tr; | ||
638 | } | ||
639 | if (ltr) kfree(ltr); | ||
640 | |||
641 | for (ra = p->role_allow; ra; ra = ra -> next) { | ||
642 | if (lra) kfree(lra); | ||
643 | lra = ra; | ||
644 | } | ||
645 | if (lra) kfree(lra); | ||
646 | |||
647 | for (rt = p->range_tr; rt; rt = rt -> next) { | ||
648 | if (lrt) kfree(lrt); | ||
649 | lrt = rt; | ||
650 | } | ||
651 | if (lrt) kfree(lrt); | ||
652 | |||
653 | for (i = 0; i < p->p_types.nprim; i++) | ||
654 | ebitmap_destroy(&p->type_attr_map[i]); | ||
655 | kfree(p->type_attr_map); | ||
656 | |||
627 | return; | 657 | return; |
628 | } | 658 | } |
629 | 659 | ||
@@ -714,7 +744,8 @@ int policydb_context_isvalid(struct policydb *p, struct context *c) | |||
714 | */ | 744 | */ |
715 | static int mls_read_range_helper(struct mls_range *r, void *fp) | 745 | static int mls_read_range_helper(struct mls_range *r, void *fp) |
716 | { | 746 | { |
717 | u32 buf[2], items; | 747 | __le32 buf[2]; |
748 | u32 items; | ||
718 | int rc; | 749 | int rc; |
719 | 750 | ||
720 | rc = next_entry(buf, fp, sizeof(u32)); | 751 | rc = next_entry(buf, fp, sizeof(u32)); |
@@ -775,7 +806,7 @@ static int context_read_and_validate(struct context *c, | |||
775 | struct policydb *p, | 806 | struct policydb *p, |
776 | void *fp) | 807 | void *fp) |
777 | { | 808 | { |
778 | u32 buf[3]; | 809 | __le32 buf[3]; |
779 | int rc; | 810 | int rc; |
780 | 811 | ||
781 | rc = next_entry(buf, fp, sizeof buf); | 812 | rc = next_entry(buf, fp, sizeof buf); |
@@ -815,7 +846,8 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) | |||
815 | char *key = NULL; | 846 | char *key = NULL; |
816 | struct perm_datum *perdatum; | 847 | struct perm_datum *perdatum; |
817 | int rc; | 848 | int rc; |
818 | u32 buf[2], len; | 849 | __le32 buf[2]; |
850 | u32 len; | ||
819 | 851 | ||
820 | perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL); | 852 | perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL); |
821 | if (!perdatum) { | 853 | if (!perdatum) { |
@@ -855,7 +887,8 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) | |||
855 | { | 887 | { |
856 | char *key = NULL; | 888 | char *key = NULL; |
857 | struct common_datum *comdatum; | 889 | struct common_datum *comdatum; |
858 | u32 buf[4], len, nel; | 890 | __le32 buf[4]; |
891 | u32 len, nel; | ||
859 | int i, rc; | 892 | int i, rc; |
860 | 893 | ||
861 | comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL); | 894 | comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL); |
@@ -909,7 +942,8 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons, | |||
909 | { | 942 | { |
910 | struct constraint_node *c, *lc; | 943 | struct constraint_node *c, *lc; |
911 | struct constraint_expr *e, *le; | 944 | struct constraint_expr *e, *le; |
912 | u32 buf[3], nexpr; | 945 | __le32 buf[3]; |
946 | u32 nexpr; | ||
913 | int rc, i, j, depth; | 947 | int rc, i, j, depth; |
914 | 948 | ||
915 | lc = NULL; | 949 | lc = NULL; |
@@ -993,7 +1027,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
993 | { | 1027 | { |
994 | char *key = NULL; | 1028 | char *key = NULL; |
995 | struct class_datum *cladatum; | 1029 | struct class_datum *cladatum; |
996 | u32 buf[6], len, len2, ncons, nel; | 1030 | __le32 buf[6]; |
1031 | u32 len, len2, ncons, nel; | ||
997 | int i, rc; | 1032 | int i, rc; |
998 | 1033 | ||
999 | cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL); | 1034 | cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL); |
@@ -1087,7 +1122,8 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1087 | char *key = NULL; | 1122 | char *key = NULL; |
1088 | struct role_datum *role; | 1123 | struct role_datum *role; |
1089 | int rc; | 1124 | int rc; |
1090 | u32 buf[2], len; | 1125 | __le32 buf[2]; |
1126 | u32 len; | ||
1091 | 1127 | ||
1092 | role = kmalloc(sizeof(*role), GFP_KERNEL); | 1128 | role = kmalloc(sizeof(*role), GFP_KERNEL); |
1093 | if (!role) { | 1129 | if (!role) { |
@@ -1147,7 +1183,8 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1147 | char *key = NULL; | 1183 | char *key = NULL; |
1148 | struct type_datum *typdatum; | 1184 | struct type_datum *typdatum; |
1149 | int rc; | 1185 | int rc; |
1150 | u32 buf[3], len; | 1186 | __le32 buf[3]; |
1187 | u32 len; | ||
1151 | 1188 | ||
1152 | typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL); | 1189 | typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL); |
1153 | if (!typdatum) { | 1190 | if (!typdatum) { |
@@ -1191,7 +1228,7 @@ bad: | |||
1191 | */ | 1228 | */ |
1192 | static int mls_read_level(struct mls_level *lp, void *fp) | 1229 | static int mls_read_level(struct mls_level *lp, void *fp) |
1193 | { | 1230 | { |
1194 | u32 buf[1]; | 1231 | __le32 buf[1]; |
1195 | int rc; | 1232 | int rc; |
1196 | 1233 | ||
1197 | memset(lp, 0, sizeof(*lp)); | 1234 | memset(lp, 0, sizeof(*lp)); |
@@ -1219,7 +1256,8 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1219 | char *key = NULL; | 1256 | char *key = NULL; |
1220 | struct user_datum *usrdatum; | 1257 | struct user_datum *usrdatum; |
1221 | int rc; | 1258 | int rc; |
1222 | u32 buf[2], len; | 1259 | __le32 buf[2]; |
1260 | u32 len; | ||
1223 | 1261 | ||
1224 | usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL); | 1262 | usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL); |
1225 | if (!usrdatum) { | 1263 | if (!usrdatum) { |
@@ -1273,7 +1311,8 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1273 | char *key = NULL; | 1311 | char *key = NULL; |
1274 | struct level_datum *levdatum; | 1312 | struct level_datum *levdatum; |
1275 | int rc; | 1313 | int rc; |
1276 | u32 buf[2], len; | 1314 | __le32 buf[2]; |
1315 | u32 len; | ||
1277 | 1316 | ||
1278 | levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC); | 1317 | levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC); |
1279 | if (!levdatum) { | 1318 | if (!levdatum) { |
@@ -1324,7 +1363,8 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1324 | char *key = NULL; | 1363 | char *key = NULL; |
1325 | struct cat_datum *catdatum; | 1364 | struct cat_datum *catdatum; |
1326 | int rc; | 1365 | int rc; |
1327 | u32 buf[3], len; | 1366 | __le32 buf[3]; |
1367 | u32 len; | ||
1328 | 1368 | ||
1329 | catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC); | 1369 | catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC); |
1330 | if (!catdatum) { | 1370 | if (!catdatum) { |
@@ -1387,7 +1427,8 @@ int policydb_read(struct policydb *p, void *fp) | |||
1387 | struct ocontext *l, *c, *newc; | 1427 | struct ocontext *l, *c, *newc; |
1388 | struct genfs *genfs_p, *genfs, *newgenfs; | 1428 | struct genfs *genfs_p, *genfs, *newgenfs; |
1389 | int i, j, rc; | 1429 | int i, j, rc; |
1390 | u32 buf[8], len, len2, config, nprim, nel, nel2; | 1430 | __le32 buf[8]; |
1431 | u32 len, len2, config, nprim, nel, nel2; | ||
1391 | char *policydb_str; | 1432 | char *policydb_str; |
1392 | struct policydb_compat_info *info; | 1433 | struct policydb_compat_info *info; |
1393 | struct range_trans *rt, *lrt; | 1434 | struct range_trans *rt, *lrt; |
@@ -1403,17 +1444,14 @@ int policydb_read(struct policydb *p, void *fp) | |||
1403 | if (rc < 0) | 1444 | if (rc < 0) |
1404 | goto bad; | 1445 | goto bad; |
1405 | 1446 | ||
1406 | for (i = 0; i < 2; i++) | 1447 | if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) { |
1407 | buf[i] = le32_to_cpu(buf[i]); | ||
1408 | |||
1409 | if (buf[0] != POLICYDB_MAGIC) { | ||
1410 | printk(KERN_ERR "security: policydb magic number 0x%x does " | 1448 | printk(KERN_ERR "security: policydb magic number 0x%x does " |
1411 | "not match expected magic number 0x%x\n", | 1449 | "not match expected magic number 0x%x\n", |
1412 | buf[0], POLICYDB_MAGIC); | 1450 | le32_to_cpu(buf[0]), POLICYDB_MAGIC); |
1413 | goto bad; | 1451 | goto bad; |
1414 | } | 1452 | } |
1415 | 1453 | ||
1416 | len = buf[1]; | 1454 | len = le32_to_cpu(buf[1]); |
1417 | if (len != strlen(POLICYDB_STRING)) { | 1455 | if (len != strlen(POLICYDB_STRING)) { |
1418 | printk(KERN_ERR "security: policydb string length %d does not " | 1456 | printk(KERN_ERR "security: policydb string length %d does not " |
1419 | "match expected length %Zu\n", | 1457 | "match expected length %Zu\n", |
@@ -1448,19 +1486,17 @@ int policydb_read(struct policydb *p, void *fp) | |||
1448 | rc = next_entry(buf, fp, sizeof(u32)*4); | 1486 | rc = next_entry(buf, fp, sizeof(u32)*4); |
1449 | if (rc < 0) | 1487 | if (rc < 0) |
1450 | goto bad; | 1488 | goto bad; |
1451 | for (i = 0; i < 4; i++) | ||
1452 | buf[i] = le32_to_cpu(buf[i]); | ||
1453 | 1489 | ||
1454 | p->policyvers = buf[0]; | 1490 | p->policyvers = le32_to_cpu(buf[0]); |
1455 | if (p->policyvers < POLICYDB_VERSION_MIN || | 1491 | if (p->policyvers < POLICYDB_VERSION_MIN || |
1456 | p->policyvers > POLICYDB_VERSION_MAX) { | 1492 | p->policyvers > POLICYDB_VERSION_MAX) { |
1457 | printk(KERN_ERR "security: policydb version %d does not match " | 1493 | printk(KERN_ERR "security: policydb version %d does not match " |
1458 | "my version range %d-%d\n", | 1494 | "my version range %d-%d\n", |
1459 | buf[0], POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); | 1495 | le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); |
1460 | goto bad; | 1496 | goto bad; |
1461 | } | 1497 | } |
1462 | 1498 | ||
1463 | if ((buf[1] & POLICYDB_CONFIG_MLS)) { | 1499 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { |
1464 | if (ss_initialized && !selinux_mls_enabled) { | 1500 | if (ss_initialized && !selinux_mls_enabled) { |
1465 | printk(KERN_ERR "Cannot switch between non-MLS and MLS " | 1501 | printk(KERN_ERR "Cannot switch between non-MLS and MLS " |
1466 | "policies\n"); | 1502 | "policies\n"); |
@@ -1489,9 +1525,11 @@ int policydb_read(struct policydb *p, void *fp) | |||
1489 | goto bad; | 1525 | goto bad; |
1490 | } | 1526 | } |
1491 | 1527 | ||
1492 | if (buf[2] != info->sym_num || buf[3] != info->ocon_num) { | 1528 | if (le32_to_cpu(buf[2]) != info->sym_num || |
1529 | le32_to_cpu(buf[3]) != info->ocon_num) { | ||
1493 | printk(KERN_ERR "security: policydb table sizes (%d,%d) do " | 1530 | printk(KERN_ERR "security: policydb table sizes (%d,%d) do " |
1494 | "not match mine (%d,%d)\n", buf[2], buf[3], | 1531 | "not match mine (%d,%d)\n", le32_to_cpu(buf[2]), |
1532 | le32_to_cpu(buf[3]), | ||
1495 | info->sym_num, info->ocon_num); | 1533 | info->sym_num, info->ocon_num); |
1496 | goto bad; | 1534 | goto bad; |
1497 | } | 1535 | } |
@@ -1511,7 +1549,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1511 | p->symtab[i].nprim = nprim; | 1549 | p->symtab[i].nprim = nprim; |
1512 | } | 1550 | } |
1513 | 1551 | ||
1514 | rc = avtab_read(&p->te_avtab, fp, config); | 1552 | rc = avtab_read(&p->te_avtab, fp, p->policyvers); |
1515 | if (rc) | 1553 | if (rc) |
1516 | goto bad; | 1554 | goto bad; |
1517 | 1555 | ||
@@ -1825,6 +1863,21 @@ int policydb_read(struct policydb *p, void *fp) | |||
1825 | } | 1863 | } |
1826 | } | 1864 | } |
1827 | 1865 | ||
1866 | p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); | ||
1867 | if (!p->type_attr_map) | ||
1868 | goto bad; | ||
1869 | |||
1870 | for (i = 0; i < p->p_types.nprim; i++) { | ||
1871 | ebitmap_init(&p->type_attr_map[i]); | ||
1872 | if (p->policyvers >= POLICYDB_VERSION_AVTAB) { | ||
1873 | if (ebitmap_read(&p->type_attr_map[i], fp)) | ||
1874 | goto bad; | ||
1875 | } | ||
1876 | /* add the type itself as the degenerate case */ | ||
1877 | if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) | ||
1878 | goto bad; | ||
1879 | } | ||
1880 | |||
1828 | rc = 0; | 1881 | rc = 0; |
1829 | out: | 1882 | out: |
1830 | return rc; | 1883 | return rc; |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 2470e2a1a1c3..b1340711f721 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -237,6 +237,9 @@ struct policydb { | |||
237 | /* range transitions */ | 237 | /* range transitions */ |
238 | struct range_trans *range_tr; | 238 | struct range_trans *range_tr; |
239 | 239 | ||
240 | /* type -> attribute reverse mapping */ | ||
241 | struct ebitmap *type_attr_map; | ||
242 | |||
240 | unsigned int policyvers; | 243 | unsigned int policyvers; |
241 | }; | 244 | }; |
242 | 245 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 45d317044cb2..aecdded55e74 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -266,8 +266,11 @@ static int context_struct_compute_av(struct context *scontext, | |||
266 | struct constraint_node *constraint; | 266 | struct constraint_node *constraint; |
267 | struct role_allow *ra; | 267 | struct role_allow *ra; |
268 | struct avtab_key avkey; | 268 | struct avtab_key avkey; |
269 | struct avtab_datum *avdatum; | 269 | struct avtab_node *node; |
270 | struct class_datum *tclass_datum; | 270 | struct class_datum *tclass_datum; |
271 | struct ebitmap *sattr, *tattr; | ||
272 | struct ebitmap_node *snode, *tnode; | ||
273 | unsigned int i, j; | ||
271 | 274 | ||
272 | /* | 275 | /* |
273 | * Remap extended Netlink classes for old policy versions. | 276 | * Remap extended Netlink classes for old policy versions. |
@@ -300,21 +303,34 @@ static int context_struct_compute_av(struct context *scontext, | |||
300 | * If a specific type enforcement rule was defined for | 303 | * If a specific type enforcement rule was defined for |
301 | * this permission check, then use it. | 304 | * this permission check, then use it. |
302 | */ | 305 | */ |
303 | avkey.source_type = scontext->type; | ||
304 | avkey.target_type = tcontext->type; | ||
305 | avkey.target_class = tclass; | 306 | avkey.target_class = tclass; |
306 | avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV); | 307 | avkey.specified = AVTAB_AV; |
307 | if (avdatum) { | 308 | sattr = &policydb.type_attr_map[scontext->type - 1]; |
308 | if (avdatum->specified & AVTAB_ALLOWED) | 309 | tattr = &policydb.type_attr_map[tcontext->type - 1]; |
309 | avd->allowed = avtab_allowed(avdatum); | 310 | ebitmap_for_each_bit(sattr, snode, i) { |
310 | if (avdatum->specified & AVTAB_AUDITDENY) | 311 | if (!ebitmap_node_get_bit(snode, i)) |
311 | avd->auditdeny = avtab_auditdeny(avdatum); | 312 | continue; |
312 | if (avdatum->specified & AVTAB_AUDITALLOW) | 313 | ebitmap_for_each_bit(tattr, tnode, j) { |
313 | avd->auditallow = avtab_auditallow(avdatum); | 314 | if (!ebitmap_node_get_bit(tnode, j)) |
314 | } | 315 | continue; |
316 | avkey.source_type = i + 1; | ||
317 | avkey.target_type = j + 1; | ||
318 | for (node = avtab_search_node(&policydb.te_avtab, &avkey); | ||
319 | node != NULL; | ||
320 | node = avtab_search_node_next(node, avkey.specified)) { | ||
321 | if (node->key.specified == AVTAB_ALLOWED) | ||
322 | avd->allowed |= node->datum.data; | ||
323 | else if (node->key.specified == AVTAB_AUDITALLOW) | ||
324 | avd->auditallow |= node->datum.data; | ||
325 | else if (node->key.specified == AVTAB_AUDITDENY) | ||
326 | avd->auditdeny &= node->datum.data; | ||
327 | } | ||
315 | 328 | ||
316 | /* Check conditional av table for additional permissions */ | 329 | /* Check conditional av table for additional permissions */ |
317 | cond_compute_av(&policydb.te_cond_avtab, &avkey, avd); | 330 | cond_compute_av(&policydb.te_cond_avtab, &avkey, avd); |
331 | |||
332 | } | ||
333 | } | ||
318 | 334 | ||
319 | /* | 335 | /* |
320 | * Remove any permissions prohibited by a constraint (this includes | 336 | * Remove any permissions prohibited by a constraint (this includes |
@@ -797,7 +813,6 @@ static int security_compute_sid(u32 ssid, | |||
797 | struct avtab_key avkey; | 813 | struct avtab_key avkey; |
798 | struct avtab_datum *avdatum; | 814 | struct avtab_datum *avdatum; |
799 | struct avtab_node *node; | 815 | struct avtab_node *node; |
800 | unsigned int type_change = 0; | ||
801 | int rc = 0; | 816 | int rc = 0; |
802 | 817 | ||
803 | if (!ss_initialized) { | 818 | if (!ss_initialized) { |
@@ -862,33 +877,23 @@ static int security_compute_sid(u32 ssid, | |||
862 | avkey.source_type = scontext->type; | 877 | avkey.source_type = scontext->type; |
863 | avkey.target_type = tcontext->type; | 878 | avkey.target_type = tcontext->type; |
864 | avkey.target_class = tclass; | 879 | avkey.target_class = tclass; |
865 | avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE); | 880 | avkey.specified = specified; |
881 | avdatum = avtab_search(&policydb.te_avtab, &avkey); | ||
866 | 882 | ||
867 | /* If no permanent rule, also check for enabled conditional rules */ | 883 | /* If no permanent rule, also check for enabled conditional rules */ |
868 | if(!avdatum) { | 884 | if(!avdatum) { |
869 | node = avtab_search_node(&policydb.te_cond_avtab, &avkey, specified); | 885 | node = avtab_search_node(&policydb.te_cond_avtab, &avkey); |
870 | for (; node != NULL; node = avtab_search_node_next(node, specified)) { | 886 | for (; node != NULL; node = avtab_search_node_next(node, specified)) { |
871 | if (node->datum.specified & AVTAB_ENABLED) { | 887 | if (node->key.specified & AVTAB_ENABLED) { |
872 | avdatum = &node->datum; | 888 | avdatum = &node->datum; |
873 | break; | 889 | break; |
874 | } | 890 | } |
875 | } | 891 | } |
876 | } | 892 | } |
877 | 893 | ||
878 | type_change = (avdatum && (avdatum->specified & specified)); | 894 | if (avdatum) { |
879 | if (type_change) { | ||
880 | /* Use the type from the type transition/member/change rule. */ | 895 | /* Use the type from the type transition/member/change rule. */ |
881 | switch (specified) { | 896 | newcontext.type = avdatum->data; |
882 | case AVTAB_TRANSITION: | ||
883 | newcontext.type = avtab_transition(avdatum); | ||
884 | break; | ||
885 | case AVTAB_MEMBER: | ||
886 | newcontext.type = avtab_member(avdatum); | ||
887 | break; | ||
888 | case AVTAB_CHANGE: | ||
889 | newcontext.type = avtab_change(avdatum); | ||
890 | break; | ||
891 | } | ||
892 | } | 897 | } |
893 | 898 | ||
894 | /* Check for class-specific changes. */ | 899 | /* Check for class-specific changes. */ |
@@ -1502,6 +1507,7 @@ int security_get_user_sids(u32 fromsid, | |||
1502 | struct user_datum *user; | 1507 | struct user_datum *user; |
1503 | struct role_datum *role; | 1508 | struct role_datum *role; |
1504 | struct av_decision avd; | 1509 | struct av_decision avd; |
1510 | struct ebitmap_node *rnode, *tnode; | ||
1505 | int rc = 0, i, j; | 1511 | int rc = 0, i, j; |
1506 | 1512 | ||
1507 | if (!ss_initialized) { | 1513 | if (!ss_initialized) { |
@@ -1532,13 +1538,13 @@ int security_get_user_sids(u32 fromsid, | |||
1532 | } | 1538 | } |
1533 | memset(mysids, 0, maxnel*sizeof(*mysids)); | 1539 | memset(mysids, 0, maxnel*sizeof(*mysids)); |
1534 | 1540 | ||
1535 | for (i = ebitmap_startbit(&user->roles); i < ebitmap_length(&user->roles); i++) { | 1541 | ebitmap_for_each_bit(&user->roles, rnode, i) { |
1536 | if (!ebitmap_get_bit(&user->roles, i)) | 1542 | if (!ebitmap_node_get_bit(rnode, i)) |
1537 | continue; | 1543 | continue; |
1538 | role = policydb.role_val_to_struct[i]; | 1544 | role = policydb.role_val_to_struct[i]; |
1539 | usercon.role = i+1; | 1545 | usercon.role = i+1; |
1540 | for (j = ebitmap_startbit(&role->types); j < ebitmap_length(&role->types); j++) { | 1546 | ebitmap_for_each_bit(&role->types, tnode, j) { |
1541 | if (!ebitmap_get_bit(&role->types, j)) | 1547 | if (!ebitmap_node_get_bit(tnode, j)) |
1542 | continue; | 1548 | continue; |
1543 | usercon.type = j+1; | 1549 | usercon.type = j+1; |
1544 | 1550 | ||