diff options
Diffstat (limited to 'security/selinux')
| -rw-r--r-- | security/selinux/avc.c | 205 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 318 | ||||
| -rw-r--r-- | security/selinux/include/av_inherit.h | 1 | ||||
| -rw-r--r-- | security/selinux/include/av_perm_to_string.h | 1 | ||||
| -rw-r--r-- | security/selinux/include/av_permissions.h | 23 | ||||
| -rw-r--r-- | security/selinux/include/avc.h | 55 | ||||
| -rw-r--r-- | security/selinux/include/class_to_string.h | 1 | ||||
| -rw-r--r-- | security/selinux/include/flask.h | 1 | ||||
| -rw-r--r-- | security/selinux/include/netlabel.h | 4 | ||||
| -rw-r--r-- | security/selinux/include/xfrm.h | 8 | ||||
| -rw-r--r-- | security/selinux/netlabel.c | 2 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 142 | ||||
| -rw-r--r-- | security/selinux/xfrm.c | 4 |
13 files changed, 442 insertions, 323 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index b2ab60859832..e3d19014259b 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
| @@ -137,7 +137,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) | |||
| 137 | * @tclass: target security class | 137 | * @tclass: target security class |
| 138 | * @av: access vector | 138 | * @av: access vector |
| 139 | */ | 139 | */ |
| 140 | void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) | 140 | static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) |
| 141 | { | 141 | { |
| 142 | const char **common_pts = NULL; | 142 | const char **common_pts = NULL; |
| 143 | u32 common_base = 0; | 143 | u32 common_base = 0; |
| @@ -492,23 +492,35 @@ out: | |||
| 492 | return node; | 492 | return node; |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | 495 | /** |
| 496 | struct in6_addr *addr, __be16 port, | 496 | * avc_audit_pre_callback - SELinux specific information |
| 497 | char *name1, char *name2) | 497 | * will be called by generic audit code |
| 498 | * @ab: the audit buffer | ||
| 499 | * @a: audit_data | ||
| 500 | */ | ||
| 501 | static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) | ||
| 498 | { | 502 | { |
| 499 | if (!ipv6_addr_any(addr)) | 503 | struct common_audit_data *ad = a; |
| 500 | audit_log_format(ab, " %s=%pI6", name1, addr); | 504 | audit_log_format(ab, "avc: %s ", |
| 501 | if (port) | 505 | ad->selinux_audit_data.denied ? "denied" : "granted"); |
| 502 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 506 | avc_dump_av(ab, ad->selinux_audit_data.tclass, |
| 507 | ad->selinux_audit_data.audited); | ||
| 508 | audit_log_format(ab, " for "); | ||
| 503 | } | 509 | } |
| 504 | 510 | ||
| 505 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr, | 511 | /** |
| 506 | __be16 port, char *name1, char *name2) | 512 | * avc_audit_post_callback - SELinux specific information |
| 513 | * will be called by generic audit code | ||
| 514 | * @ab: the audit buffer | ||
| 515 | * @a: audit_data | ||
| 516 | */ | ||
| 517 | static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | ||
| 507 | { | 518 | { |
| 508 | if (addr) | 519 | struct common_audit_data *ad = a; |
| 509 | audit_log_format(ab, " %s=%pI4", name1, &addr); | 520 | audit_log_format(ab, " "); |
| 510 | if (port) | 521 | avc_dump_query(ab, ad->selinux_audit_data.ssid, |
| 511 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 522 | ad->selinux_audit_data.tsid, |
| 523 | ad->selinux_audit_data.tclass); | ||
| 512 | } | 524 | } |
| 513 | 525 | ||
| 514 | /** | 526 | /** |
| @@ -532,13 +544,10 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr, | |||
| 532 | */ | 544 | */ |
| 533 | void avc_audit(u32 ssid, u32 tsid, | 545 | void avc_audit(u32 ssid, u32 tsid, |
| 534 | u16 tclass, u32 requested, | 546 | u16 tclass, u32 requested, |
| 535 | struct av_decision *avd, int result, struct avc_audit_data *a) | 547 | struct av_decision *avd, int result, struct common_audit_data *a) |
| 536 | { | 548 | { |
| 537 | struct task_struct *tsk = current; | 549 | struct common_audit_data stack_data; |
| 538 | struct inode *inode = NULL; | ||
| 539 | u32 denied, audited; | 550 | u32 denied, audited; |
| 540 | struct audit_buffer *ab; | ||
| 541 | |||
| 542 | denied = requested & ~avd->allowed; | 551 | denied = requested & ~avd->allowed; |
| 543 | if (denied) { | 552 | if (denied) { |
| 544 | audited = denied; | 553 | audited = denied; |
| @@ -551,144 +560,20 @@ void avc_audit(u32 ssid, u32 tsid, | |||
| 551 | if (!(audited & avd->auditallow)) | 560 | if (!(audited & avd->auditallow)) |
| 552 | return; | 561 | return; |
| 553 | } | 562 | } |
| 554 | 563 | if (!a) { | |
| 555 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); | 564 | a = &stack_data; |
| 556 | if (!ab) | 565 | memset(a, 0, sizeof(*a)); |
| 557 | return; /* audit_panic has been called */ | 566 | a->type = LSM_AUDIT_NO_AUDIT; |
| 558 | audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted"); | ||
| 559 | avc_dump_av(ab, tclass, audited); | ||
| 560 | audit_log_format(ab, " for "); | ||
| 561 | if (a && a->tsk) | ||
| 562 | tsk = a->tsk; | ||
| 563 | if (tsk && tsk->pid) { | ||
| 564 | audit_log_format(ab, " pid=%d comm=", tsk->pid); | ||
| 565 | audit_log_untrustedstring(ab, tsk->comm); | ||
| 566 | } | 567 | } |
| 567 | if (a) { | 568 | a->selinux_audit_data.tclass = tclass; |
| 568 | switch (a->type) { | 569 | a->selinux_audit_data.requested = requested; |
| 569 | case AVC_AUDIT_DATA_IPC: | 570 | a->selinux_audit_data.ssid = ssid; |
| 570 | audit_log_format(ab, " key=%d", a->u.ipc_id); | 571 | a->selinux_audit_data.tsid = tsid; |
| 571 | break; | 572 | a->selinux_audit_data.audited = audited; |
| 572 | case AVC_AUDIT_DATA_CAP: | 573 | a->selinux_audit_data.denied = denied; |
| 573 | audit_log_format(ab, " capability=%d", a->u.cap); | 574 | a->lsm_pre_audit = avc_audit_pre_callback; |
| 574 | break; | 575 | a->lsm_post_audit = avc_audit_post_callback; |
| 575 | case AVC_AUDIT_DATA_FS: | 576 | common_lsm_audit(a); |
| 576 | if (a->u.fs.path.dentry) { | ||
| 577 | struct dentry *dentry = a->u.fs.path.dentry; | ||
| 578 | if (a->u.fs.path.mnt) { | ||
| 579 | audit_log_d_path(ab, "path=", | ||
| 580 | &a->u.fs.path); | ||
| 581 | } else { | ||
| 582 | audit_log_format(ab, " name="); | ||
| 583 | audit_log_untrustedstring(ab, dentry->d_name.name); | ||
| 584 | } | ||
| 585 | inode = dentry->d_inode; | ||
| 586 | } else if (a->u.fs.inode) { | ||
| 587 | struct dentry *dentry; | ||
| 588 | inode = a->u.fs.inode; | ||
| 589 | dentry = d_find_alias(inode); | ||
| 590 | if (dentry) { | ||
| 591 | audit_log_format(ab, " name="); | ||
| 592 | audit_log_untrustedstring(ab, dentry->d_name.name); | ||
| 593 | dput(dentry); | ||
| 594 | } | ||
| 595 | } | ||
| 596 | if (inode) | ||
| 597 | audit_log_format(ab, " dev=%s ino=%lu", | ||
| 598 | inode->i_sb->s_id, | ||
| 599 | inode->i_ino); | ||
| 600 | break; | ||
| 601 | case AVC_AUDIT_DATA_NET: | ||
| 602 | if (a->u.net.sk) { | ||
| 603 | struct sock *sk = a->u.net.sk; | ||
| 604 | struct unix_sock *u; | ||
| 605 | int len = 0; | ||
| 606 | char *p = NULL; | ||
| 607 | |||
| 608 | switch (sk->sk_family) { | ||
| 609 | case AF_INET: { | ||
| 610 | struct inet_sock *inet = inet_sk(sk); | ||
| 611 | |||
| 612 | avc_print_ipv4_addr(ab, inet->rcv_saddr, | ||
| 613 | inet->sport, | ||
| 614 | "laddr", "lport"); | ||
| 615 | avc_print_ipv4_addr(ab, inet->daddr, | ||
| 616 | inet->dport, | ||
| 617 | "faddr", "fport"); | ||
| 618 | break; | ||
| 619 | } | ||
| 620 | case AF_INET6: { | ||
| 621 | struct inet_sock *inet = inet_sk(sk); | ||
| 622 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | ||
| 623 | |||
| 624 | avc_print_ipv6_addr(ab, &inet6->rcv_saddr, | ||
| 625 | inet->sport, | ||
| 626 | "laddr", "lport"); | ||
| 627 | avc_print_ipv6_addr(ab, &inet6->daddr, | ||
| 628 | inet->dport, | ||
| 629 | "faddr", "fport"); | ||
| 630 | break; | ||
| 631 | } | ||
| 632 | case AF_UNIX: | ||
| 633 | u = unix_sk(sk); | ||
| 634 | if (u->dentry) { | ||
| 635 | struct path path = { | ||
| 636 | .dentry = u->dentry, | ||
| 637 | .mnt = u->mnt | ||
| 638 | }; | ||
| 639 | audit_log_d_path(ab, "path=", | ||
| 640 | &path); | ||
| 641 | break; | ||
| 642 | } | ||
| 643 | if (!u->addr) | ||
| 644 | break; | ||
| 645 | len = u->addr->len-sizeof(short); | ||
| 646 | p = &u->addr->name->sun_path[0]; | ||
| 647 | audit_log_format(ab, " path="); | ||
| 648 | if (*p) | ||
| 649 | audit_log_untrustedstring(ab, p); | ||
| 650 | else | ||
| 651 | audit_log_n_hex(ab, p, len); | ||
| 652 | break; | ||
| 653 | } | ||
| 654 | } | ||
| 655 | |||
| 656 | switch (a->u.net.family) { | ||
| 657 | case AF_INET: | ||
| 658 | avc_print_ipv4_addr(ab, a->u.net.v4info.saddr, | ||
| 659 | a->u.net.sport, | ||
| 660 | "saddr", "src"); | ||
| 661 | avc_print_ipv4_addr(ab, a->u.net.v4info.daddr, | ||
| 662 | a->u.net.dport, | ||
| 663 | "daddr", "dest"); | ||
| 664 | break; | ||
| 665 | case AF_INET6: | ||
| 666 | avc_print_ipv6_addr(ab, &a->u.net.v6info.saddr, | ||
| 667 | a->u.net.sport, | ||
| 668 | "saddr", "src"); | ||
| 669 | avc_print_ipv6_addr(ab, &a->u.net.v6info.daddr, | ||
| 670 | a->u.net.dport, | ||
| 671 | "daddr", "dest"); | ||
| 672 | break; | ||
| 673 | } | ||
| 674 | if (a->u.net.netif > 0) { | ||
| 675 | struct net_device *dev; | ||
| 676 | |||
| 677 | /* NOTE: we always use init's namespace */ | ||
| 678 | dev = dev_get_by_index(&init_net, | ||
| 679 | a->u.net.netif); | ||
| 680 | if (dev) { | ||
| 681 | audit_log_format(ab, " netif=%s", | ||
| 682 | dev->name); | ||
| 683 | dev_put(dev); | ||
| 684 | } | ||
| 685 | } | ||
| 686 | break; | ||
| 687 | } | ||
| 688 | } | ||
| 689 | audit_log_format(ab, " "); | ||
| 690 | avc_dump_query(ab, ssid, tsid, tclass); | ||
| 691 | audit_log_end(ab); | ||
| 692 | } | 577 | } |
| 693 | 578 | ||
| 694 | /** | 579 | /** |
| @@ -956,7 +841,7 @@ out: | |||
| 956 | * another -errno upon other errors. | 841 | * another -errno upon other errors. |
| 957 | */ | 842 | */ |
| 958 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, | 843 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, |
| 959 | u32 requested, struct avc_audit_data *auditdata) | 844 | u32 requested, struct common_audit_data *auditdata) |
| 960 | { | 845 | { |
| 961 | struct av_decision avd; | 846 | struct av_decision avd; |
| 962 | int rc; | 847 | int rc; |
| @@ -970,3 +855,9 @@ u32 avc_policy_seqno(void) | |||
| 970 | { | 855 | { |
| 971 | return avc_cache.latest_notif; | 856 | return avc_cache.latest_notif; |
| 972 | } | 857 | } |
| 858 | |||
| 859 | void avc_disable(void) | ||
| 860 | { | ||
| 861 | if (avc_node_cachep) | ||
| 862 | kmem_cache_destroy(avc_node_cachep); | ||
| 863 | } | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8d8b69c5664e..417f7c994522 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | * Eric Paris <eparis@redhat.com> | 13 | * Eric Paris <eparis@redhat.com> |
| 14 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. | 14 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. |
| 15 | * <dgoeddel@trustedcs.com> | 15 | * <dgoeddel@trustedcs.com> |
| 16 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 16 | * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P. |
| 17 | * Paul Moore <paul.moore@hp.com> | 17 | * Paul Moore <paul.moore@hp.com> |
| 18 | * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. | 18 | * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. |
| 19 | * Yuichi Nakamura <ynakam@hitachisoft.jp> | 19 | * Yuichi Nakamura <ynakam@hitachisoft.jp> |
| 20 | * | 20 | * |
| @@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb) | |||
| 448 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) | 448 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) |
| 449 | sbsec->flags &= ~SE_SBLABELSUPP; | 449 | sbsec->flags &= ~SE_SBLABELSUPP; |
| 450 | 450 | ||
| 451 | /* Special handling for sysfs. Is genfs but also has setxattr handler*/ | ||
| 452 | if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0) | ||
| 453 | sbsec->flags |= SE_SBLABELSUPP; | ||
| 454 | |||
| 451 | /* Initialize the root inode. */ | 455 | /* Initialize the root inode. */ |
| 452 | rc = inode_doinit_with_dentry(root_inode, root); | 456 | rc = inode_doinit_with_dentry(root_inode, root); |
| 453 | 457 | ||
| @@ -1479,14 +1483,14 @@ static int task_has_capability(struct task_struct *tsk, | |||
| 1479 | const struct cred *cred, | 1483 | const struct cred *cred, |
| 1480 | int cap, int audit) | 1484 | int cap, int audit) |
| 1481 | { | 1485 | { |
| 1482 | struct avc_audit_data ad; | 1486 | struct common_audit_data ad; |
| 1483 | struct av_decision avd; | 1487 | struct av_decision avd; |
| 1484 | u16 sclass; | 1488 | u16 sclass; |
| 1485 | u32 sid = cred_sid(cred); | 1489 | u32 sid = cred_sid(cred); |
| 1486 | u32 av = CAP_TO_MASK(cap); | 1490 | u32 av = CAP_TO_MASK(cap); |
| 1487 | int rc; | 1491 | int rc; |
| 1488 | 1492 | ||
| 1489 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 1493 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
| 1490 | ad.tsk = tsk; | 1494 | ad.tsk = tsk; |
| 1491 | ad.u.cap = cap; | 1495 | ad.u.cap = cap; |
| 1492 | 1496 | ||
| @@ -1525,12 +1529,14 @@ static int task_has_system(struct task_struct *tsk, | |||
| 1525 | static int inode_has_perm(const struct cred *cred, | 1529 | static int inode_has_perm(const struct cred *cred, |
| 1526 | struct inode *inode, | 1530 | struct inode *inode, |
| 1527 | u32 perms, | 1531 | u32 perms, |
| 1528 | struct avc_audit_data *adp) | 1532 | struct common_audit_data *adp) |
| 1529 | { | 1533 | { |
| 1530 | struct inode_security_struct *isec; | 1534 | struct inode_security_struct *isec; |
| 1531 | struct avc_audit_data ad; | 1535 | struct common_audit_data ad; |
| 1532 | u32 sid; | 1536 | u32 sid; |
| 1533 | 1537 | ||
| 1538 | validate_creds(cred); | ||
| 1539 | |||
| 1534 | if (unlikely(IS_PRIVATE(inode))) | 1540 | if (unlikely(IS_PRIVATE(inode))) |
| 1535 | return 0; | 1541 | return 0; |
| 1536 | 1542 | ||
| @@ -1539,7 +1545,7 @@ static int inode_has_perm(const struct cred *cred, | |||
| 1539 | 1545 | ||
| 1540 | if (!adp) { | 1546 | if (!adp) { |
| 1541 | adp = &ad; | 1547 | adp = &ad; |
| 1542 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1548 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 1543 | ad.u.fs.inode = inode; | 1549 | ad.u.fs.inode = inode; |
| 1544 | } | 1550 | } |
| 1545 | 1551 | ||
| @@ -1555,9 +1561,9 @@ static inline int dentry_has_perm(const struct cred *cred, | |||
| 1555 | u32 av) | 1561 | u32 av) |
| 1556 | { | 1562 | { |
| 1557 | struct inode *inode = dentry->d_inode; | 1563 | struct inode *inode = dentry->d_inode; |
| 1558 | struct avc_audit_data ad; | 1564 | struct common_audit_data ad; |
| 1559 | 1565 | ||
| 1560 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1566 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 1561 | ad.u.fs.path.mnt = mnt; | 1567 | ad.u.fs.path.mnt = mnt; |
| 1562 | ad.u.fs.path.dentry = dentry; | 1568 | ad.u.fs.path.dentry = dentry; |
| 1563 | return inode_has_perm(cred, inode, av, &ad); | 1569 | return inode_has_perm(cred, inode, av, &ad); |
| @@ -1577,11 +1583,11 @@ static int file_has_perm(const struct cred *cred, | |||
| 1577 | { | 1583 | { |
| 1578 | struct file_security_struct *fsec = file->f_security; | 1584 | struct file_security_struct *fsec = file->f_security; |
| 1579 | struct inode *inode = file->f_path.dentry->d_inode; | 1585 | struct inode *inode = file->f_path.dentry->d_inode; |
| 1580 | struct avc_audit_data ad; | 1586 | struct common_audit_data ad; |
| 1581 | u32 sid = cred_sid(cred); | 1587 | u32 sid = cred_sid(cred); |
| 1582 | int rc; | 1588 | int rc; |
| 1583 | 1589 | ||
| 1584 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1590 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 1585 | ad.u.fs.path = file->f_path; | 1591 | ad.u.fs.path = file->f_path; |
| 1586 | 1592 | ||
| 1587 | if (sid != fsec->sid) { | 1593 | if (sid != fsec->sid) { |
| @@ -1612,7 +1618,7 @@ static int may_create(struct inode *dir, | |||
| 1612 | struct inode_security_struct *dsec; | 1618 | struct inode_security_struct *dsec; |
| 1613 | struct superblock_security_struct *sbsec; | 1619 | struct superblock_security_struct *sbsec; |
| 1614 | u32 sid, newsid; | 1620 | u32 sid, newsid; |
| 1615 | struct avc_audit_data ad; | 1621 | struct common_audit_data ad; |
| 1616 | int rc; | 1622 | int rc; |
| 1617 | 1623 | ||
| 1618 | dsec = dir->i_security; | 1624 | dsec = dir->i_security; |
| @@ -1621,7 +1627,7 @@ static int may_create(struct inode *dir, | |||
| 1621 | sid = tsec->sid; | 1627 | sid = tsec->sid; |
| 1622 | newsid = tsec->create_sid; | 1628 | newsid = tsec->create_sid; |
| 1623 | 1629 | ||
| 1624 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1630 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 1625 | ad.u.fs.path.dentry = dentry; | 1631 | ad.u.fs.path.dentry = dentry; |
| 1626 | 1632 | ||
| 1627 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1633 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
| @@ -1665,7 +1671,7 @@ static int may_link(struct inode *dir, | |||
| 1665 | 1671 | ||
| 1666 | { | 1672 | { |
| 1667 | struct inode_security_struct *dsec, *isec; | 1673 | struct inode_security_struct *dsec, *isec; |
| 1668 | struct avc_audit_data ad; | 1674 | struct common_audit_data ad; |
| 1669 | u32 sid = current_sid(); | 1675 | u32 sid = current_sid(); |
| 1670 | u32 av; | 1676 | u32 av; |
| 1671 | int rc; | 1677 | int rc; |
| @@ -1673,7 +1679,7 @@ static int may_link(struct inode *dir, | |||
| 1673 | dsec = dir->i_security; | 1679 | dsec = dir->i_security; |
| 1674 | isec = dentry->d_inode->i_security; | 1680 | isec = dentry->d_inode->i_security; |
| 1675 | 1681 | ||
| 1676 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1682 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 1677 | ad.u.fs.path.dentry = dentry; | 1683 | ad.u.fs.path.dentry = dentry; |
| 1678 | 1684 | ||
| 1679 | av = DIR__SEARCH; | 1685 | av = DIR__SEARCH; |
| @@ -1708,7 +1714,7 @@ static inline int may_rename(struct inode *old_dir, | |||
| 1708 | struct dentry *new_dentry) | 1714 | struct dentry *new_dentry) |
| 1709 | { | 1715 | { |
| 1710 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; | 1716 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; |
| 1711 | struct avc_audit_data ad; | 1717 | struct common_audit_data ad; |
| 1712 | u32 sid = current_sid(); | 1718 | u32 sid = current_sid(); |
| 1713 | u32 av; | 1719 | u32 av; |
| 1714 | int old_is_dir, new_is_dir; | 1720 | int old_is_dir, new_is_dir; |
| @@ -1719,7 +1725,7 @@ static inline int may_rename(struct inode *old_dir, | |||
| 1719 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 1725 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
| 1720 | new_dsec = new_dir->i_security; | 1726 | new_dsec = new_dir->i_security; |
| 1721 | 1727 | ||
| 1722 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1728 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 1723 | 1729 | ||
| 1724 | ad.u.fs.path.dentry = old_dentry; | 1730 | ad.u.fs.path.dentry = old_dentry; |
| 1725 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 1731 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, |
| @@ -1761,7 +1767,7 @@ static inline int may_rename(struct inode *old_dir, | |||
| 1761 | static int superblock_has_perm(const struct cred *cred, | 1767 | static int superblock_has_perm(const struct cred *cred, |
| 1762 | struct super_block *sb, | 1768 | struct super_block *sb, |
| 1763 | u32 perms, | 1769 | u32 perms, |
| 1764 | struct avc_audit_data *ad) | 1770 | struct common_audit_data *ad) |
| 1765 | { | 1771 | { |
| 1766 | struct superblock_security_struct *sbsec; | 1772 | struct superblock_security_struct *sbsec; |
| 1767 | u32 sid = cred_sid(cred); | 1773 | u32 sid = cred_sid(cred); |
| @@ -1855,12 +1861,12 @@ static inline u32 open_file_to_av(struct file *file) | |||
| 1855 | 1861 | ||
| 1856 | /* Hook functions begin here. */ | 1862 | /* Hook functions begin here. */ |
| 1857 | 1863 | ||
| 1858 | static int selinux_ptrace_may_access(struct task_struct *child, | 1864 | static int selinux_ptrace_access_check(struct task_struct *child, |
| 1859 | unsigned int mode) | 1865 | unsigned int mode) |
| 1860 | { | 1866 | { |
| 1861 | int rc; | 1867 | int rc; |
| 1862 | 1868 | ||
| 1863 | rc = cap_ptrace_may_access(child, mode); | 1869 | rc = cap_ptrace_access_check(child, mode); |
| 1864 | if (rc) | 1870 | if (rc) |
| 1865 | return rc; | 1871 | return rc; |
| 1866 | 1872 | ||
| @@ -2101,7 +2107,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
| 2101 | const struct task_security_struct *old_tsec; | 2107 | const struct task_security_struct *old_tsec; |
| 2102 | struct task_security_struct *new_tsec; | 2108 | struct task_security_struct *new_tsec; |
| 2103 | struct inode_security_struct *isec; | 2109 | struct inode_security_struct *isec; |
| 2104 | struct avc_audit_data ad; | 2110 | struct common_audit_data ad; |
| 2105 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | 2111 | struct inode *inode = bprm->file->f_path.dentry->d_inode; |
| 2106 | int rc; | 2112 | int rc; |
| 2107 | 2113 | ||
| @@ -2139,7 +2145,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
| 2139 | return rc; | 2145 | return rc; |
| 2140 | } | 2146 | } |
| 2141 | 2147 | ||
| 2142 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2148 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 2143 | ad.u.fs.path = bprm->file->f_path; | 2149 | ad.u.fs.path = bprm->file->f_path; |
| 2144 | 2150 | ||
| 2145 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 2151 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) |
| @@ -2232,7 +2238,7 @@ extern struct dentry *selinux_null; | |||
| 2232 | static inline void flush_unauthorized_files(const struct cred *cred, | 2238 | static inline void flush_unauthorized_files(const struct cred *cred, |
| 2233 | struct files_struct *files) | 2239 | struct files_struct *files) |
| 2234 | { | 2240 | { |
| 2235 | struct avc_audit_data ad; | 2241 | struct common_audit_data ad; |
| 2236 | struct file *file, *devnull = NULL; | 2242 | struct file *file, *devnull = NULL; |
| 2237 | struct tty_struct *tty; | 2243 | struct tty_struct *tty; |
| 2238 | struct fdtable *fdt; | 2244 | struct fdtable *fdt; |
| @@ -2266,7 +2272,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
| 2266 | 2272 | ||
| 2267 | /* Revalidate access to inherited open files. */ | 2273 | /* Revalidate access to inherited open files. */ |
| 2268 | 2274 | ||
| 2269 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2275 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 2270 | 2276 | ||
| 2271 | spin_lock(&files->file_lock); | 2277 | spin_lock(&files->file_lock); |
| 2272 | for (;;) { | 2278 | for (;;) { |
| @@ -2515,7 +2521,7 @@ out: | |||
| 2515 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | 2521 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) |
| 2516 | { | 2522 | { |
| 2517 | const struct cred *cred = current_cred(); | 2523 | const struct cred *cred = current_cred(); |
| 2518 | struct avc_audit_data ad; | 2524 | struct common_audit_data ad; |
| 2519 | int rc; | 2525 | int rc; |
| 2520 | 2526 | ||
| 2521 | rc = superblock_doinit(sb, data); | 2527 | rc = superblock_doinit(sb, data); |
| @@ -2526,7 +2532,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
| 2526 | if (flags & MS_KERNMOUNT) | 2532 | if (flags & MS_KERNMOUNT) |
| 2527 | return 0; | 2533 | return 0; |
| 2528 | 2534 | ||
| 2529 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2535 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 2530 | ad.u.fs.path.dentry = sb->s_root; | 2536 | ad.u.fs.path.dentry = sb->s_root; |
| 2531 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); | 2537 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
| 2532 | } | 2538 | } |
| @@ -2534,9 +2540,9 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
| 2534 | static int selinux_sb_statfs(struct dentry *dentry) | 2540 | static int selinux_sb_statfs(struct dentry *dentry) |
| 2535 | { | 2541 | { |
| 2536 | const struct cred *cred = current_cred(); | 2542 | const struct cred *cred = current_cred(); |
| 2537 | struct avc_audit_data ad; | 2543 | struct common_audit_data ad; |
| 2538 | 2544 | ||
| 2539 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2545 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 2540 | ad.u.fs.path.dentry = dentry->d_sb->s_root; | 2546 | ad.u.fs.path.dentry = dentry->d_sb->s_root; |
| 2541 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); | 2547 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); |
| 2542 | } | 2548 | } |
| @@ -2711,12 +2717,18 @@ static int selinux_inode_permission(struct inode *inode, int mask) | |||
| 2711 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2717 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
| 2712 | { | 2718 | { |
| 2713 | const struct cred *cred = current_cred(); | 2719 | const struct cred *cred = current_cred(); |
| 2720 | unsigned int ia_valid = iattr->ia_valid; | ||
| 2721 | |||
| 2722 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ | ||
| 2723 | if (ia_valid & ATTR_FORCE) { | ||
| 2724 | ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE | | ||
| 2725 | ATTR_FORCE); | ||
| 2726 | if (!ia_valid) | ||
| 2727 | return 0; | ||
| 2728 | } | ||
| 2714 | 2729 | ||
| 2715 | if (iattr->ia_valid & ATTR_FORCE) | 2730 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | |
| 2716 | return 0; | 2731 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) |
| 2717 | |||
| 2718 | if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | | ||
| 2719 | ATTR_ATIME_SET | ATTR_MTIME_SET)) | ||
| 2720 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); | 2732 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); |
| 2721 | 2733 | ||
| 2722 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); | 2734 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); |
| @@ -2756,7 +2768,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
| 2756 | struct inode *inode = dentry->d_inode; | 2768 | struct inode *inode = dentry->d_inode; |
| 2757 | struct inode_security_struct *isec = inode->i_security; | 2769 | struct inode_security_struct *isec = inode->i_security; |
| 2758 | struct superblock_security_struct *sbsec; | 2770 | struct superblock_security_struct *sbsec; |
| 2759 | struct avc_audit_data ad; | 2771 | struct common_audit_data ad; |
| 2760 | u32 newsid, sid = current_sid(); | 2772 | u32 newsid, sid = current_sid(); |
| 2761 | int rc = 0; | 2773 | int rc = 0; |
| 2762 | 2774 | ||
| @@ -2770,7 +2782,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
| 2770 | if (!is_owner_or_cap(inode)) | 2782 | if (!is_owner_or_cap(inode)) |
| 2771 | return -EPERM; | 2783 | return -EPERM; |
| 2772 | 2784 | ||
| 2773 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2785 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
| 2774 | ad.u.fs.path.dentry = dentry; | 2786 | ad.u.fs.path.dentry = dentry; |
| 2775 | 2787 | ||
| 2776 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 2788 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
| @@ -2915,6 +2927,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
| 2915 | return rc; | 2927 | return rc; |
| 2916 | 2928 | ||
| 2917 | isec->sid = newsid; | 2929 | isec->sid = newsid; |
| 2930 | isec->initialized = 1; | ||
| 2918 | return 0; | 2931 | return 0; |
| 2919 | } | 2932 | } |
| 2920 | 2933 | ||
| @@ -2939,11 +2952,6 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
| 2939 | const struct cred *cred = current_cred(); | 2952 | const struct cred *cred = current_cred(); |
| 2940 | struct inode *inode = file->f_path.dentry->d_inode; | 2953 | struct inode *inode = file->f_path.dentry->d_inode; |
| 2941 | 2954 | ||
| 2942 | if (!mask) { | ||
| 2943 | /* No permission to check. Existence test. */ | ||
| 2944 | return 0; | ||
| 2945 | } | ||
| 2946 | |||
| 2947 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ | 2955 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ |
| 2948 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) | 2956 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) |
| 2949 | mask |= MAY_APPEND; | 2957 | mask |= MAY_APPEND; |
| @@ -2954,10 +2962,20 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
| 2954 | 2962 | ||
| 2955 | static int selinux_file_permission(struct file *file, int mask) | 2963 | static int selinux_file_permission(struct file *file, int mask) |
| 2956 | { | 2964 | { |
| 2965 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 2966 | struct file_security_struct *fsec = file->f_security; | ||
| 2967 | struct inode_security_struct *isec = inode->i_security; | ||
| 2968 | u32 sid = current_sid(); | ||
| 2969 | |||
| 2957 | if (!mask) | 2970 | if (!mask) |
| 2958 | /* No permission to check. Existence test. */ | 2971 | /* No permission to check. Existence test. */ |
| 2959 | return 0; | 2972 | return 0; |
| 2960 | 2973 | ||
| 2974 | if (sid == fsec->sid && fsec->isid == isec->sid && | ||
| 2975 | fsec->pseqno == avc_policy_seqno()) | ||
| 2976 | /* No change since dentry_open check. */ | ||
| 2977 | return 0; | ||
| 2978 | |||
| 2961 | return selinux_revalidate_file_permission(file, mask); | 2979 | return selinux_revalidate_file_permission(file, mask); |
| 2962 | } | 2980 | } |
| 2963 | 2981 | ||
| @@ -3220,12 +3238,29 @@ static int selinux_task_create(unsigned long clone_flags) | |||
| 3220 | } | 3238 | } |
| 3221 | 3239 | ||
| 3222 | /* | 3240 | /* |
| 3241 | * allocate the SELinux part of blank credentials | ||
| 3242 | */ | ||
| 3243 | static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp) | ||
| 3244 | { | ||
| 3245 | struct task_security_struct *tsec; | ||
| 3246 | |||
| 3247 | tsec = kzalloc(sizeof(struct task_security_struct), gfp); | ||
| 3248 | if (!tsec) | ||
| 3249 | return -ENOMEM; | ||
| 3250 | |||
| 3251 | cred->security = tsec; | ||
| 3252 | return 0; | ||
| 3253 | } | ||
| 3254 | |||
| 3255 | /* | ||
| 3223 | * detach and free the LSM part of a set of credentials | 3256 | * detach and free the LSM part of a set of credentials |
| 3224 | */ | 3257 | */ |
| 3225 | static void selinux_cred_free(struct cred *cred) | 3258 | static void selinux_cred_free(struct cred *cred) |
| 3226 | { | 3259 | { |
| 3227 | struct task_security_struct *tsec = cred->security; | 3260 | struct task_security_struct *tsec = cred->security; |
| 3228 | cred->security = NULL; | 3261 | |
| 3262 | BUG_ON((unsigned long) cred->security < PAGE_SIZE); | ||
| 3263 | cred->security = (void *) 0x7UL; | ||
| 3229 | kfree(tsec); | 3264 | kfree(tsec); |
| 3230 | } | 3265 | } |
| 3231 | 3266 | ||
| @@ -3249,6 +3284,17 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old, | |||
| 3249 | } | 3284 | } |
| 3250 | 3285 | ||
| 3251 | /* | 3286 | /* |
| 3287 | * transfer the SELinux data to a blank set of creds | ||
| 3288 | */ | ||
| 3289 | static void selinux_cred_transfer(struct cred *new, const struct cred *old) | ||
| 3290 | { | ||
| 3291 | const struct task_security_struct *old_tsec = old->security; | ||
| 3292 | struct task_security_struct *tsec = new->security; | ||
| 3293 | |||
| 3294 | *tsec = *old_tsec; | ||
| 3295 | } | ||
| 3296 | |||
| 3297 | /* | ||
| 3252 | * set the security data for a kernel service | 3298 | * set the security data for a kernel service |
| 3253 | * - all the creation contexts are set to unlabelled | 3299 | * - all the creation contexts are set to unlabelled |
| 3254 | */ | 3300 | */ |
| @@ -3292,6 +3338,11 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
| 3292 | return 0; | 3338 | return 0; |
| 3293 | } | 3339 | } |
| 3294 | 3340 | ||
| 3341 | static int selinux_kernel_module_request(void) | ||
| 3342 | { | ||
| 3343 | return task_has_system(current, SYSTEM__MODULE_REQUEST); | ||
| 3344 | } | ||
| 3345 | |||
| 3295 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3346 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
| 3296 | { | 3347 | { |
| 3297 | return current_has_perm(p, PROCESS__SETPGID); | 3348 | return current_has_perm(p, PROCESS__SETPGID); |
| @@ -3409,7 +3460,7 @@ static void selinux_task_to_inode(struct task_struct *p, | |||
| 3409 | 3460 | ||
| 3410 | /* Returns error only if unable to parse addresses */ | 3461 | /* Returns error only if unable to parse addresses */ |
| 3411 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, | 3462 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, |
| 3412 | struct avc_audit_data *ad, u8 *proto) | 3463 | struct common_audit_data *ad, u8 *proto) |
| 3413 | { | 3464 | { |
| 3414 | int offset, ihlen, ret = -EINVAL; | 3465 | int offset, ihlen, ret = -EINVAL; |
| 3415 | struct iphdr _iph, *ih; | 3466 | struct iphdr _iph, *ih; |
| @@ -3490,7 +3541,7 @@ out: | |||
| 3490 | 3541 | ||
| 3491 | /* Returns error only if unable to parse addresses */ | 3542 | /* Returns error only if unable to parse addresses */ |
| 3492 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, | 3543 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, |
| 3493 | struct avc_audit_data *ad, u8 *proto) | 3544 | struct common_audit_data *ad, u8 *proto) |
| 3494 | { | 3545 | { |
| 3495 | u8 nexthdr; | 3546 | u8 nexthdr; |
| 3496 | int ret = -EINVAL, offset; | 3547 | int ret = -EINVAL, offset; |
| @@ -3561,7 +3612,7 @@ out: | |||
| 3561 | 3612 | ||
| 3562 | #endif /* IPV6 */ | 3613 | #endif /* IPV6 */ |
| 3563 | 3614 | ||
| 3564 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, | 3615 | static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, |
| 3565 | char **_addrp, int src, u8 *proto) | 3616 | char **_addrp, int src, u8 *proto) |
| 3566 | { | 3617 | { |
| 3567 | char *addrp; | 3618 | char *addrp; |
| @@ -3643,7 +3694,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, | |||
| 3643 | u32 perms) | 3694 | u32 perms) |
| 3644 | { | 3695 | { |
| 3645 | struct inode_security_struct *isec; | 3696 | struct inode_security_struct *isec; |
| 3646 | struct avc_audit_data ad; | 3697 | struct common_audit_data ad; |
| 3647 | u32 sid; | 3698 | u32 sid; |
| 3648 | int err = 0; | 3699 | int err = 0; |
| 3649 | 3700 | ||
| @@ -3653,7 +3704,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, | |||
| 3653 | goto out; | 3704 | goto out; |
| 3654 | sid = task_sid(task); | 3705 | sid = task_sid(task); |
| 3655 | 3706 | ||
| 3656 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3707 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3657 | ad.u.net.sk = sock->sk; | 3708 | ad.u.net.sk = sock->sk; |
| 3658 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 3709 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
| 3659 | 3710 | ||
| @@ -3740,7 +3791,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 3740 | if (family == PF_INET || family == PF_INET6) { | 3791 | if (family == PF_INET || family == PF_INET6) { |
| 3741 | char *addrp; | 3792 | char *addrp; |
| 3742 | struct inode_security_struct *isec; | 3793 | struct inode_security_struct *isec; |
| 3743 | struct avc_audit_data ad; | 3794 | struct common_audit_data ad; |
| 3744 | struct sockaddr_in *addr4 = NULL; | 3795 | struct sockaddr_in *addr4 = NULL; |
| 3745 | struct sockaddr_in6 *addr6 = NULL; | 3796 | struct sockaddr_in6 *addr6 = NULL; |
| 3746 | unsigned short snum; | 3797 | unsigned short snum; |
| @@ -3769,7 +3820,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 3769 | snum, &sid); | 3820 | snum, &sid); |
| 3770 | if (err) | 3821 | if (err) |
| 3771 | goto out; | 3822 | goto out; |
| 3772 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3823 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3773 | ad.u.net.sport = htons(snum); | 3824 | ad.u.net.sport = htons(snum); |
| 3774 | ad.u.net.family = family; | 3825 | ad.u.net.family = family; |
| 3775 | err = avc_has_perm(isec->sid, sid, | 3826 | err = avc_has_perm(isec->sid, sid, |
| @@ -3802,7 +3853,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
| 3802 | if (err) | 3853 | if (err) |
| 3803 | goto out; | 3854 | goto out; |
| 3804 | 3855 | ||
| 3805 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3856 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3806 | ad.u.net.sport = htons(snum); | 3857 | ad.u.net.sport = htons(snum); |
| 3807 | ad.u.net.family = family; | 3858 | ad.u.net.family = family; |
| 3808 | 3859 | ||
| @@ -3836,7 +3887,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
| 3836 | isec = SOCK_INODE(sock)->i_security; | 3887 | isec = SOCK_INODE(sock)->i_security; |
| 3837 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3888 | if (isec->sclass == SECCLASS_TCP_SOCKET || |
| 3838 | isec->sclass == SECCLASS_DCCP_SOCKET) { | 3889 | isec->sclass == SECCLASS_DCCP_SOCKET) { |
| 3839 | struct avc_audit_data ad; | 3890 | struct common_audit_data ad; |
| 3840 | struct sockaddr_in *addr4 = NULL; | 3891 | struct sockaddr_in *addr4 = NULL; |
| 3841 | struct sockaddr_in6 *addr6 = NULL; | 3892 | struct sockaddr_in6 *addr6 = NULL; |
| 3842 | unsigned short snum; | 3893 | unsigned short snum; |
| @@ -3861,7 +3912,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
| 3861 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3912 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? |
| 3862 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3913 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
| 3863 | 3914 | ||
| 3864 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3915 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3865 | ad.u.net.dport = htons(snum); | 3916 | ad.u.net.dport = htons(snum); |
| 3866 | ad.u.net.family = sk->sk_family; | 3917 | ad.u.net.family = sk->sk_family; |
| 3867 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3918 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); |
| @@ -3951,13 +4002,13 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, | |||
| 3951 | struct sk_security_struct *ssec; | 4002 | struct sk_security_struct *ssec; |
| 3952 | struct inode_security_struct *isec; | 4003 | struct inode_security_struct *isec; |
| 3953 | struct inode_security_struct *other_isec; | 4004 | struct inode_security_struct *other_isec; |
| 3954 | struct avc_audit_data ad; | 4005 | struct common_audit_data ad; |
| 3955 | int err; | 4006 | int err; |
| 3956 | 4007 | ||
| 3957 | isec = SOCK_INODE(sock)->i_security; | 4008 | isec = SOCK_INODE(sock)->i_security; |
| 3958 | other_isec = SOCK_INODE(other)->i_security; | 4009 | other_isec = SOCK_INODE(other)->i_security; |
| 3959 | 4010 | ||
| 3960 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4011 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3961 | ad.u.net.sk = other->sk; | 4012 | ad.u.net.sk = other->sk; |
| 3962 | 4013 | ||
| 3963 | err = avc_has_perm(isec->sid, other_isec->sid, | 4014 | err = avc_has_perm(isec->sid, other_isec->sid, |
| @@ -3983,13 +4034,13 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
| 3983 | { | 4034 | { |
| 3984 | struct inode_security_struct *isec; | 4035 | struct inode_security_struct *isec; |
| 3985 | struct inode_security_struct *other_isec; | 4036 | struct inode_security_struct *other_isec; |
| 3986 | struct avc_audit_data ad; | 4037 | struct common_audit_data ad; |
| 3987 | int err; | 4038 | int err; |
| 3988 | 4039 | ||
| 3989 | isec = SOCK_INODE(sock)->i_security; | 4040 | isec = SOCK_INODE(sock)->i_security; |
| 3990 | other_isec = SOCK_INODE(other)->i_security; | 4041 | other_isec = SOCK_INODE(other)->i_security; |
| 3991 | 4042 | ||
| 3992 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4043 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 3993 | ad.u.net.sk = other->sk; | 4044 | ad.u.net.sk = other->sk; |
| 3994 | 4045 | ||
| 3995 | err = avc_has_perm(isec->sid, other_isec->sid, | 4046 | err = avc_has_perm(isec->sid, other_isec->sid, |
| @@ -4002,7 +4053,7 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
| 4002 | 4053 | ||
| 4003 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 4054 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
| 4004 | u32 peer_sid, | 4055 | u32 peer_sid, |
| 4005 | struct avc_audit_data *ad) | 4056 | struct common_audit_data *ad) |
| 4006 | { | 4057 | { |
| 4007 | int err; | 4058 | int err; |
| 4008 | u32 if_sid; | 4059 | u32 if_sid; |
| @@ -4030,10 +4081,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
| 4030 | struct sk_security_struct *sksec = sk->sk_security; | 4081 | struct sk_security_struct *sksec = sk->sk_security; |
| 4031 | u32 peer_sid; | 4082 | u32 peer_sid; |
| 4032 | u32 sk_sid = sksec->sid; | 4083 | u32 sk_sid = sksec->sid; |
| 4033 | struct avc_audit_data ad; | 4084 | struct common_audit_data ad; |
| 4034 | char *addrp; | 4085 | char *addrp; |
| 4035 | 4086 | ||
| 4036 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4087 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 4037 | ad.u.net.netif = skb->iif; | 4088 | ad.u.net.netif = skb->iif; |
| 4038 | ad.u.net.family = family; | 4089 | ad.u.net.family = family; |
| 4039 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4090 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
| @@ -4071,7 +4122,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 4071 | struct sk_security_struct *sksec = sk->sk_security; | 4122 | struct sk_security_struct *sksec = sk->sk_security; |
| 4072 | u16 family = sk->sk_family; | 4123 | u16 family = sk->sk_family; |
| 4073 | u32 sk_sid = sksec->sid; | 4124 | u32 sk_sid = sksec->sid; |
| 4074 | struct avc_audit_data ad; | 4125 | struct common_audit_data ad; |
| 4075 | char *addrp; | 4126 | char *addrp; |
| 4076 | u8 secmark_active; | 4127 | u8 secmark_active; |
| 4077 | u8 peerlbl_active; | 4128 | u8 peerlbl_active; |
| @@ -4095,7 +4146,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 4095 | if (!secmark_active && !peerlbl_active) | 4146 | if (!secmark_active && !peerlbl_active) |
| 4096 | return 0; | 4147 | return 0; |
| 4097 | 4148 | ||
| 4098 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4149 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 4099 | ad.u.net.netif = skb->iif; | 4150 | ad.u.net.netif = skb->iif; |
| 4100 | ad.u.net.family = family; | 4151 | ad.u.net.family = family; |
| 4101 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4152 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
| @@ -4309,6 +4360,59 @@ static void selinux_req_classify_flow(const struct request_sock *req, | |||
| 4309 | fl->secid = req->secid; | 4360 | fl->secid = req->secid; |
| 4310 | } | 4361 | } |
| 4311 | 4362 | ||
| 4363 | static int selinux_tun_dev_create(void) | ||
| 4364 | { | ||
| 4365 | u32 sid = current_sid(); | ||
| 4366 | |||
| 4367 | /* we aren't taking into account the "sockcreate" SID since the socket | ||
| 4368 | * that is being created here is not a socket in the traditional sense, | ||
| 4369 | * instead it is a private sock, accessible only to the kernel, and | ||
| 4370 | * representing a wide range of network traffic spanning multiple | ||
| 4371 | * connections unlike traditional sockets - check the TUN driver to | ||
| 4372 | * get a better understanding of why this socket is special */ | ||
| 4373 | |||
| 4374 | return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, | ||
| 4375 | NULL); | ||
| 4376 | } | ||
| 4377 | |||
| 4378 | static void selinux_tun_dev_post_create(struct sock *sk) | ||
| 4379 | { | ||
| 4380 | struct sk_security_struct *sksec = sk->sk_security; | ||
| 4381 | |||
| 4382 | /* we don't currently perform any NetLabel based labeling here and it | ||
| 4383 | * isn't clear that we would want to do so anyway; while we could apply | ||
| 4384 | * labeling without the support of the TUN user the resulting labeled | ||
| 4385 | * traffic from the other end of the connection would almost certainly | ||
| 4386 | * cause confusion to the TUN user that had no idea network labeling | ||
| 4387 | * protocols were being used */ | ||
| 4388 | |||
| 4389 | /* see the comments in selinux_tun_dev_create() about why we don't use | ||
| 4390 | * the sockcreate SID here */ | ||
| 4391 | |||
| 4392 | sksec->sid = current_sid(); | ||
| 4393 | sksec->sclass = SECCLASS_TUN_SOCKET; | ||
| 4394 | } | ||
| 4395 | |||
| 4396 | static int selinux_tun_dev_attach(struct sock *sk) | ||
| 4397 | { | ||
| 4398 | struct sk_security_struct *sksec = sk->sk_security; | ||
| 4399 | u32 sid = current_sid(); | ||
| 4400 | int err; | ||
| 4401 | |||
| 4402 | err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET, | ||
| 4403 | TUN_SOCKET__RELABELFROM, NULL); | ||
| 4404 | if (err) | ||
| 4405 | return err; | ||
| 4406 | err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, | ||
| 4407 | TUN_SOCKET__RELABELTO, NULL); | ||
| 4408 | if (err) | ||
| 4409 | return err; | ||
| 4410 | |||
| 4411 | sksec->sid = sid; | ||
| 4412 | |||
| 4413 | return 0; | ||
| 4414 | } | ||
| 4415 | |||
| 4312 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | 4416 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) |
| 4313 | { | 4417 | { |
| 4314 | int err = 0; | 4418 | int err = 0; |
| @@ -4353,7 +4457,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
| 4353 | int err; | 4457 | int err; |
| 4354 | char *addrp; | 4458 | char *addrp; |
| 4355 | u32 peer_sid; | 4459 | u32 peer_sid; |
| 4356 | struct avc_audit_data ad; | 4460 | struct common_audit_data ad; |
| 4357 | u8 secmark_active; | 4461 | u8 secmark_active; |
| 4358 | u8 netlbl_active; | 4462 | u8 netlbl_active; |
| 4359 | u8 peerlbl_active; | 4463 | u8 peerlbl_active; |
| @@ -4370,7 +4474,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
| 4370 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | 4474 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) |
| 4371 | return NF_DROP; | 4475 | return NF_DROP; |
| 4372 | 4476 | ||
| 4373 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4477 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 4374 | ad.u.net.netif = ifindex; | 4478 | ad.u.net.netif = ifindex; |
| 4375 | ad.u.net.family = family; | 4479 | ad.u.net.family = family; |
| 4376 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) | 4480 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) |
| @@ -4458,7 +4562,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
| 4458 | { | 4562 | { |
| 4459 | struct sock *sk = skb->sk; | 4563 | struct sock *sk = skb->sk; |
| 4460 | struct sk_security_struct *sksec; | 4564 | struct sk_security_struct *sksec; |
| 4461 | struct avc_audit_data ad; | 4565 | struct common_audit_data ad; |
| 4462 | char *addrp; | 4566 | char *addrp; |
| 4463 | u8 proto; | 4567 | u8 proto; |
| 4464 | 4568 | ||
| @@ -4466,7 +4570,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
| 4466 | return NF_ACCEPT; | 4570 | return NF_ACCEPT; |
| 4467 | sksec = sk->sk_security; | 4571 | sksec = sk->sk_security; |
| 4468 | 4572 | ||
| 4469 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4573 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 4470 | ad.u.net.netif = ifindex; | 4574 | ad.u.net.netif = ifindex; |
| 4471 | ad.u.net.family = family; | 4575 | ad.u.net.family = family; |
| 4472 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) | 4576 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) |
| @@ -4490,7 +4594,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
| 4490 | u32 secmark_perm; | 4594 | u32 secmark_perm; |
| 4491 | u32 peer_sid; | 4595 | u32 peer_sid; |
| 4492 | struct sock *sk; | 4596 | struct sock *sk; |
| 4493 | struct avc_audit_data ad; | 4597 | struct common_audit_data ad; |
| 4494 | char *addrp; | 4598 | char *addrp; |
| 4495 | u8 secmark_active; | 4599 | u8 secmark_active; |
| 4496 | u8 peerlbl_active; | 4600 | u8 peerlbl_active; |
| @@ -4549,7 +4653,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
| 4549 | secmark_perm = PACKET__SEND; | 4653 | secmark_perm = PACKET__SEND; |
| 4550 | } | 4654 | } |
| 4551 | 4655 | ||
| 4552 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4656 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
| 4553 | ad.u.net.netif = ifindex; | 4657 | ad.u.net.netif = ifindex; |
| 4554 | ad.u.net.family = family; | 4658 | ad.u.net.family = family; |
| 4555 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) | 4659 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) |
| @@ -4619,13 +4723,13 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
| 4619 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) | 4723 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) |
| 4620 | { | 4724 | { |
| 4621 | int err; | 4725 | int err; |
| 4622 | struct avc_audit_data ad; | 4726 | struct common_audit_data ad; |
| 4623 | 4727 | ||
| 4624 | err = cap_netlink_recv(skb, capability); | 4728 | err = cap_netlink_recv(skb, capability); |
| 4625 | if (err) | 4729 | if (err) |
| 4626 | return err; | 4730 | return err; |
| 4627 | 4731 | ||
| 4628 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 4732 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
| 4629 | ad.u.cap = capability; | 4733 | ad.u.cap = capability; |
| 4630 | 4734 | ||
| 4631 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, | 4735 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, |
| @@ -4684,12 +4788,12 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | |||
| 4684 | u32 perms) | 4788 | u32 perms) |
| 4685 | { | 4789 | { |
| 4686 | struct ipc_security_struct *isec; | 4790 | struct ipc_security_struct *isec; |
| 4687 | struct avc_audit_data ad; | 4791 | struct common_audit_data ad; |
| 4688 | u32 sid = current_sid(); | 4792 | u32 sid = current_sid(); |
| 4689 | 4793 | ||
| 4690 | isec = ipc_perms->security; | 4794 | isec = ipc_perms->security; |
| 4691 | 4795 | ||
| 4692 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4796 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
| 4693 | ad.u.ipc_id = ipc_perms->key; | 4797 | ad.u.ipc_id = ipc_perms->key; |
| 4694 | 4798 | ||
| 4695 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 4799 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
| @@ -4709,7 +4813,7 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg) | |||
| 4709 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | 4813 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) |
| 4710 | { | 4814 | { |
| 4711 | struct ipc_security_struct *isec; | 4815 | struct ipc_security_struct *isec; |
| 4712 | struct avc_audit_data ad; | 4816 | struct common_audit_data ad; |
| 4713 | u32 sid = current_sid(); | 4817 | u32 sid = current_sid(); |
| 4714 | int rc; | 4818 | int rc; |
| 4715 | 4819 | ||
| @@ -4719,7 +4823,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
| 4719 | 4823 | ||
| 4720 | isec = msq->q_perm.security; | 4824 | isec = msq->q_perm.security; |
| 4721 | 4825 | ||
| 4722 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4826 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
| 4723 | ad.u.ipc_id = msq->q_perm.key; | 4827 | ad.u.ipc_id = msq->q_perm.key; |
| 4724 | 4828 | ||
| 4725 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4829 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
| @@ -4739,12 +4843,12 @@ static void selinux_msg_queue_free_security(struct msg_queue *msq) | |||
| 4739 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) | 4843 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) |
| 4740 | { | 4844 | { |
| 4741 | struct ipc_security_struct *isec; | 4845 | struct ipc_security_struct *isec; |
| 4742 | struct avc_audit_data ad; | 4846 | struct common_audit_data ad; |
| 4743 | u32 sid = current_sid(); | 4847 | u32 sid = current_sid(); |
| 4744 | 4848 | ||
| 4745 | isec = msq->q_perm.security; | 4849 | isec = msq->q_perm.security; |
| 4746 | 4850 | ||
| 4747 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4851 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
| 4748 | ad.u.ipc_id = msq->q_perm.key; | 4852 | ad.u.ipc_id = msq->q_perm.key; |
| 4749 | 4853 | ||
| 4750 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4854 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
| @@ -4783,7 +4887,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
| 4783 | { | 4887 | { |
| 4784 | struct ipc_security_struct *isec; | 4888 | struct ipc_security_struct *isec; |
| 4785 | struct msg_security_struct *msec; | 4889 | struct msg_security_struct *msec; |
| 4786 | struct avc_audit_data ad; | 4890 | struct common_audit_data ad; |
| 4787 | u32 sid = current_sid(); | 4891 | u32 sid = current_sid(); |
| 4788 | int rc; | 4892 | int rc; |
| 4789 | 4893 | ||
| @@ -4804,7 +4908,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
| 4804 | return rc; | 4908 | return rc; |
| 4805 | } | 4909 | } |
| 4806 | 4910 | ||
| 4807 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4911 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
| 4808 | ad.u.ipc_id = msq->q_perm.key; | 4912 | ad.u.ipc_id = msq->q_perm.key; |
| 4809 | 4913 | ||
| 4810 | /* Can this process write to the queue? */ | 4914 | /* Can this process write to the queue? */ |
| @@ -4828,14 +4932,14 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
| 4828 | { | 4932 | { |
| 4829 | struct ipc_security_struct *isec; | 4933 | struct ipc_security_struct *isec; |
| 4830 | struct msg_security_struct *msec; | 4934 | struct msg_security_struct *msec; |
| 4831 | struct avc_audit_data ad; | 4935 | struct common_audit_data ad; |
| 4832 | u32 sid = task_sid(target); | 4936 | u32 sid = task_sid(target); |
| 4833 | int rc; | 4937 | int rc; |
| 4834 | 4938 | ||
| 4835 | isec = msq->q_perm.security; | 4939 | isec = msq->q_perm.security; |
| 4836 | msec = msg->security; | 4940 | msec = msg->security; |
| 4837 | 4941 | ||
| 4838 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4942 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
| 4839 | ad.u.ipc_id = msq->q_perm.key; | 4943 | ad.u.ipc_id = msq->q_perm.key; |
| 4840 | 4944 | ||
| 4841 | rc = avc_has_perm(sid, isec->sid, | 4945 | rc = avc_has_perm(sid, isec->sid, |
| @@ -4850,7 +4954,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
| 4850 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) | 4954 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) |
| 4851 | { | 4955 | { |
| 4852 | struct ipc_security_struct *isec; | 4956 | struct ipc_security_struct *isec; |
| 4853 | struct avc_audit_data ad; | 4957 | struct common_audit_data ad; |
| 4854 | u32 sid = current_sid(); | 4958 | u32 sid = current_sid(); |
| 4855 | int rc; | 4959 | int rc; |
| 4856 | 4960 | ||
| @@ -4860,7 +4964,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
| 4860 | 4964 | ||
| 4861 | isec = shp->shm_perm.security; | 4965 | isec = shp->shm_perm.security; |
| 4862 | 4966 | ||
| 4863 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4967 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
| 4864 | ad.u.ipc_id = shp->shm_perm.key; | 4968 | ad.u.ipc_id = shp->shm_perm.key; |
| 4865 | 4969 | ||
| 4866 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4970 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
| @@ -4880,12 +4984,12 @@ static void selinux_shm_free_security(struct shmid_kernel *shp) | |||
| 4880 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) | 4984 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) |
| 4881 | { | 4985 | { |
| 4882 | struct ipc_security_struct *isec; | 4986 | struct ipc_security_struct *isec; |
| 4883 | struct avc_audit_data ad; | 4987 | struct common_audit_data ad; |
| 4884 | u32 sid = current_sid(); | 4988 | u32 sid = current_sid(); |
| 4885 | 4989 | ||
| 4886 | isec = shp->shm_perm.security; | 4990 | isec = shp->shm_perm.security; |
| 4887 | 4991 | ||
| 4888 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4992 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
| 4889 | ad.u.ipc_id = shp->shm_perm.key; | 4993 | ad.u.ipc_id = shp->shm_perm.key; |
| 4890 | 4994 | ||
| 4891 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4995 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
| @@ -4942,7 +5046,7 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, | |||
| 4942 | static int selinux_sem_alloc_security(struct sem_array *sma) | 5046 | static int selinux_sem_alloc_security(struct sem_array *sma) |
| 4943 | { | 5047 | { |
| 4944 | struct ipc_security_struct *isec; | 5048 | struct ipc_security_struct *isec; |
| 4945 | struct avc_audit_data ad; | 5049 | struct common_audit_data ad; |
| 4946 | u32 sid = current_sid(); | 5050 | u32 sid = current_sid(); |
| 4947 | int rc; | 5051 | int rc; |
| 4948 | 5052 | ||
| @@ -4952,7 +5056,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
| 4952 | 5056 | ||
| 4953 | isec = sma->sem_perm.security; | 5057 | isec = sma->sem_perm.security; |
| 4954 | 5058 | ||
| 4955 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5059 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
| 4956 | ad.u.ipc_id = sma->sem_perm.key; | 5060 | ad.u.ipc_id = sma->sem_perm.key; |
| 4957 | 5061 | ||
| 4958 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5062 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
| @@ -4972,12 +5076,12 @@ static void selinux_sem_free_security(struct sem_array *sma) | |||
| 4972 | static int selinux_sem_associate(struct sem_array *sma, int semflg) | 5076 | static int selinux_sem_associate(struct sem_array *sma, int semflg) |
| 4973 | { | 5077 | { |
| 4974 | struct ipc_security_struct *isec; | 5078 | struct ipc_security_struct *isec; |
| 4975 | struct avc_audit_data ad; | 5079 | struct common_audit_data ad; |
| 4976 | u32 sid = current_sid(); | 5080 | u32 sid = current_sid(); |
| 4977 | 5081 | ||
| 4978 | isec = sma->sem_perm.security; | 5082 | isec = sma->sem_perm.security; |
| 4979 | 5083 | ||
| 4980 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5084 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
| 4981 | ad.u.ipc_id = sma->sem_perm.key; | 5085 | ad.u.ipc_id = sma->sem_perm.key; |
| 4982 | 5086 | ||
| 4983 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5087 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
| @@ -5195,7 +5299,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
| 5195 | 5299 | ||
| 5196 | /* Only allow single threaded processes to change context */ | 5300 | /* Only allow single threaded processes to change context */ |
| 5197 | error = -EPERM; | 5301 | error = -EPERM; |
| 5198 | if (!is_single_threaded(p)) { | 5302 | if (!current_is_single_threaded()) { |
| 5199 | error = security_bounded_transition(tsec->sid, sid); | 5303 | error = security_bounded_transition(tsec->sid, sid); |
| 5200 | if (error) | 5304 | if (error) |
| 5201 | goto abort_change; | 5305 | goto abort_change; |
| @@ -5252,6 +5356,32 @@ static void selinux_release_secctx(char *secdata, u32 seclen) | |||
| 5252 | kfree(secdata); | 5356 | kfree(secdata); |
| 5253 | } | 5357 | } |
| 5254 | 5358 | ||
| 5359 | /* | ||
| 5360 | * called with inode->i_mutex locked | ||
| 5361 | */ | ||
| 5362 | static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
| 5363 | { | ||
| 5364 | return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0); | ||
| 5365 | } | ||
| 5366 | |||
| 5367 | /* | ||
| 5368 | * called with inode->i_mutex locked | ||
| 5369 | */ | ||
| 5370 | static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
| 5371 | { | ||
| 5372 | return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0); | ||
| 5373 | } | ||
| 5374 | |||
| 5375 | static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
| 5376 | { | ||
| 5377 | int len = 0; | ||
| 5378 | len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX, | ||
| 5379 | ctx, true); | ||
| 5380 | if (len < 0) | ||
| 5381 | return len; | ||
| 5382 | *ctxlen = len; | ||
| 5383 | return 0; | ||
| 5384 | } | ||
| 5255 | #ifdef CONFIG_KEYS | 5385 | #ifdef CONFIG_KEYS |
| 5256 | 5386 | ||
| 5257 | static int selinux_key_alloc(struct key *k, const struct cred *cred, | 5387 | static int selinux_key_alloc(struct key *k, const struct cred *cred, |
| @@ -5323,7 +5453,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
| 5323 | static struct security_operations selinux_ops = { | 5453 | static struct security_operations selinux_ops = { |
| 5324 | .name = "selinux", | 5454 | .name = "selinux", |
| 5325 | 5455 | ||
| 5326 | .ptrace_may_access = selinux_ptrace_may_access, | 5456 | .ptrace_access_check = selinux_ptrace_access_check, |
| 5327 | .ptrace_traceme = selinux_ptrace_traceme, | 5457 | .ptrace_traceme = selinux_ptrace_traceme, |
| 5328 | .capget = selinux_capget, | 5458 | .capget = selinux_capget, |
| 5329 | .capset = selinux_capset, | 5459 | .capset = selinux_capset, |
| @@ -5396,10 +5526,13 @@ static struct security_operations selinux_ops = { | |||
| 5396 | .dentry_open = selinux_dentry_open, | 5526 | .dentry_open = selinux_dentry_open, |
| 5397 | 5527 | ||
| 5398 | .task_create = selinux_task_create, | 5528 | .task_create = selinux_task_create, |
| 5529 | .cred_alloc_blank = selinux_cred_alloc_blank, | ||
| 5399 | .cred_free = selinux_cred_free, | 5530 | .cred_free = selinux_cred_free, |
| 5400 | .cred_prepare = selinux_cred_prepare, | 5531 | .cred_prepare = selinux_cred_prepare, |
| 5532 | .cred_transfer = selinux_cred_transfer, | ||
| 5401 | .kernel_act_as = selinux_kernel_act_as, | 5533 | .kernel_act_as = selinux_kernel_act_as, |
| 5402 | .kernel_create_files_as = selinux_kernel_create_files_as, | 5534 | .kernel_create_files_as = selinux_kernel_create_files_as, |
| 5535 | .kernel_module_request = selinux_kernel_module_request, | ||
| 5403 | .task_setpgid = selinux_task_setpgid, | 5536 | .task_setpgid = selinux_task_setpgid, |
| 5404 | .task_getpgid = selinux_task_getpgid, | 5537 | .task_getpgid = selinux_task_getpgid, |
| 5405 | .task_getsid = selinux_task_getsid, | 5538 | .task_getsid = selinux_task_getsid, |
| @@ -5448,6 +5581,9 @@ static struct security_operations selinux_ops = { | |||
| 5448 | .secid_to_secctx = selinux_secid_to_secctx, | 5581 | .secid_to_secctx = selinux_secid_to_secctx, |
| 5449 | .secctx_to_secid = selinux_secctx_to_secid, | 5582 | .secctx_to_secid = selinux_secctx_to_secid, |
| 5450 | .release_secctx = selinux_release_secctx, | 5583 | .release_secctx = selinux_release_secctx, |
| 5584 | .inode_notifysecctx = selinux_inode_notifysecctx, | ||
| 5585 | .inode_setsecctx = selinux_inode_setsecctx, | ||
| 5586 | .inode_getsecctx = selinux_inode_getsecctx, | ||
| 5451 | 5587 | ||
| 5452 | .unix_stream_connect = selinux_socket_unix_stream_connect, | 5588 | .unix_stream_connect = selinux_socket_unix_stream_connect, |
| 5453 | .unix_may_send = selinux_socket_unix_may_send, | 5589 | .unix_may_send = selinux_socket_unix_may_send, |
| @@ -5477,6 +5613,9 @@ static struct security_operations selinux_ops = { | |||
| 5477 | .inet_csk_clone = selinux_inet_csk_clone, | 5613 | .inet_csk_clone = selinux_inet_csk_clone, |
| 5478 | .inet_conn_established = selinux_inet_conn_established, | 5614 | .inet_conn_established = selinux_inet_conn_established, |
| 5479 | .req_classify_flow = selinux_req_classify_flow, | 5615 | .req_classify_flow = selinux_req_classify_flow, |
| 5616 | .tun_dev_create = selinux_tun_dev_create, | ||
| 5617 | .tun_dev_post_create = selinux_tun_dev_post_create, | ||
| 5618 | .tun_dev_attach = selinux_tun_dev_attach, | ||
| 5480 | 5619 | ||
| 5481 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 5620 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
| 5482 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, | 5621 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, |
| @@ -5691,6 +5830,9 @@ int selinux_disable(void) | |||
| 5691 | selinux_disabled = 1; | 5830 | selinux_disabled = 1; |
| 5692 | selinux_enabled = 0; | 5831 | selinux_enabled = 0; |
| 5693 | 5832 | ||
| 5833 | /* Try to destroy the avc node cache */ | ||
| 5834 | avc_disable(); | ||
| 5835 | |||
| 5694 | /* Reset security_ops to the secondary module, dummy or capability. */ | 5836 | /* Reset security_ops to the secondary module, dummy or capability. */ |
| 5695 | security_ops = secondary_ops; | 5837 | security_ops = secondary_ops; |
| 5696 | 5838 | ||
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h index 8377a4ba3b95..abedcd704dae 100644 --- a/security/selinux/include/av_inherit.h +++ b/security/selinux/include/av_inherit.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | S_(SECCLASS_KEY_SOCKET, socket, 0x00400000UL) | 15 | S_(SECCLASS_KEY_SOCKET, socket, 0x00400000UL) |
| 16 | S_(SECCLASS_UNIX_STREAM_SOCKET, socket, 0x00400000UL) | 16 | S_(SECCLASS_UNIX_STREAM_SOCKET, socket, 0x00400000UL) |
| 17 | S_(SECCLASS_UNIX_DGRAM_SOCKET, socket, 0x00400000UL) | 17 | S_(SECCLASS_UNIX_DGRAM_SOCKET, socket, 0x00400000UL) |
| 18 | S_(SECCLASS_TUN_SOCKET, socket, 0x00400000UL) | ||
| 18 | S_(SECCLASS_IPC, ipc, 0x00000200UL) | 19 | S_(SECCLASS_IPC, ipc, 0x00000200UL) |
| 19 | S_(SECCLASS_SEM, ipc, 0x00000200UL) | 20 | S_(SECCLASS_SEM, ipc, 0x00000200UL) |
| 20 | S_(SECCLASS_MSGQ, ipc, 0x00000200UL) | 21 | S_(SECCLASS_MSGQ, ipc, 0x00000200UL) |
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 31df1d7c1aee..2b683ad83d21 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h | |||
| @@ -107,6 +107,7 @@ | |||
| 107 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") | 107 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") |
| 108 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") | 108 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") |
| 109 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") | 109 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") |
| 110 | S_(SECCLASS_SYSTEM, SYSTEM__MODULE_REQUEST, "module_request") | ||
| 110 | S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") | 111 | S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") |
| 111 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override") | 112 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override") |
| 112 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search") | 113 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search") |
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index d645192ee950..0546d616ccac 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h | |||
| @@ -423,6 +423,28 @@ | |||
| 423 | #define UNIX_DGRAM_SOCKET__RECV_MSG 0x00080000UL | 423 | #define UNIX_DGRAM_SOCKET__RECV_MSG 0x00080000UL |
| 424 | #define UNIX_DGRAM_SOCKET__SEND_MSG 0x00100000UL | 424 | #define UNIX_DGRAM_SOCKET__SEND_MSG 0x00100000UL |
| 425 | #define UNIX_DGRAM_SOCKET__NAME_BIND 0x00200000UL | 425 | #define UNIX_DGRAM_SOCKET__NAME_BIND 0x00200000UL |
| 426 | #define TUN_SOCKET__IOCTL 0x00000001UL | ||
| 427 | #define TUN_SOCKET__READ 0x00000002UL | ||
| 428 | #define TUN_SOCKET__WRITE 0x00000004UL | ||
| 429 | #define TUN_SOCKET__CREATE 0x00000008UL | ||
| 430 | #define TUN_SOCKET__GETATTR 0x00000010UL | ||
| 431 | #define TUN_SOCKET__SETATTR 0x00000020UL | ||
| 432 | #define TUN_SOCKET__LOCK 0x00000040UL | ||
| 433 | #define TUN_SOCKET__RELABELFROM 0x00000080UL | ||
| 434 | #define TUN_SOCKET__RELABELTO 0x00000100UL | ||
| 435 | #define TUN_SOCKET__APPEND 0x00000200UL | ||
| 436 | #define TUN_SOCKET__BIND 0x00000400UL | ||
| 437 | #define TUN_SOCKET__CONNECT 0x00000800UL | ||
| 438 | #define TUN_SOCKET__LISTEN 0x00001000UL | ||
| 439 | #define TUN_SOCKET__ACCEPT 0x00002000UL | ||
| 440 | #define TUN_SOCKET__GETOPT 0x00004000UL | ||
| 441 | #define TUN_SOCKET__SETOPT 0x00008000UL | ||
| 442 | #define TUN_SOCKET__SHUTDOWN 0x00010000UL | ||
| 443 | #define TUN_SOCKET__RECVFROM 0x00020000UL | ||
| 444 | #define TUN_SOCKET__SENDTO 0x00040000UL | ||
| 445 | #define TUN_SOCKET__RECV_MSG 0x00080000UL | ||
| 446 | #define TUN_SOCKET__SEND_MSG 0x00100000UL | ||
| 447 | #define TUN_SOCKET__NAME_BIND 0x00200000UL | ||
| 426 | #define PROCESS__FORK 0x00000001UL | 448 | #define PROCESS__FORK 0x00000001UL |
| 427 | #define PROCESS__TRANSITION 0x00000002UL | 449 | #define PROCESS__TRANSITION 0x00000002UL |
| 428 | #define PROCESS__SIGCHLD 0x00000004UL | 450 | #define PROCESS__SIGCHLD 0x00000004UL |
| @@ -508,6 +530,7 @@ | |||
| 508 | #define SYSTEM__SYSLOG_READ 0x00000002UL | 530 | #define SYSTEM__SYSLOG_READ 0x00000002UL |
| 509 | #define SYSTEM__SYSLOG_MOD 0x00000004UL | 531 | #define SYSTEM__SYSLOG_MOD 0x00000004UL |
| 510 | #define SYSTEM__SYSLOG_CONSOLE 0x00000008UL | 532 | #define SYSTEM__SYSLOG_CONSOLE 0x00000008UL |
| 533 | #define SYSTEM__MODULE_REQUEST 0x00000010UL | ||
| 511 | #define CAPABILITY__CHOWN 0x00000001UL | 534 | #define CAPABILITY__CHOWN 0x00000001UL |
| 512 | #define CAPABILITY__DAC_OVERRIDE 0x00000002UL | 535 | #define CAPABILITY__DAC_OVERRIDE 0x00000002UL |
| 513 | #define CAPABILITY__DAC_READ_SEARCH 0x00000004UL | 536 | #define CAPABILITY__DAC_READ_SEARCH 0x00000004UL |
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index d12ff1a9c0aa..e94e82f73818 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/audit.h> | 15 | #include <linux/audit.h> |
| 16 | #include <linux/lsm_audit.h> | ||
| 16 | #include <linux/in6.h> | 17 | #include <linux/in6.h> |
| 17 | #include <linux/path.h> | 18 | #include <linux/path.h> |
| 18 | #include <asm/system.h> | 19 | #include <asm/system.h> |
| @@ -36,48 +37,6 @@ struct inode; | |||
| 36 | struct sock; | 37 | struct sock; |
| 37 | struct sk_buff; | 38 | struct sk_buff; |
| 38 | 39 | ||
| 39 | /* Auxiliary data to use in generating the audit record. */ | ||
| 40 | struct avc_audit_data { | ||
| 41 | char type; | ||
| 42 | #define AVC_AUDIT_DATA_FS 1 | ||
| 43 | #define AVC_AUDIT_DATA_NET 2 | ||
| 44 | #define AVC_AUDIT_DATA_CAP 3 | ||
| 45 | #define AVC_AUDIT_DATA_IPC 4 | ||
| 46 | struct task_struct *tsk; | ||
| 47 | union { | ||
| 48 | struct { | ||
| 49 | struct path path; | ||
| 50 | struct inode *inode; | ||
| 51 | } fs; | ||
| 52 | struct { | ||
| 53 | int netif; | ||
| 54 | struct sock *sk; | ||
| 55 | u16 family; | ||
| 56 | __be16 dport; | ||
| 57 | __be16 sport; | ||
| 58 | union { | ||
| 59 | struct { | ||
| 60 | __be32 daddr; | ||
| 61 | __be32 saddr; | ||
| 62 | } v4; | ||
| 63 | struct { | ||
| 64 | struct in6_addr daddr; | ||
| 65 | struct in6_addr saddr; | ||
| 66 | } v6; | ||
| 67 | } fam; | ||
| 68 | } net; | ||
| 69 | int cap; | ||
| 70 | int ipc_id; | ||
| 71 | } u; | ||
| 72 | }; | ||
| 73 | |||
| 74 | #define v4info fam.v4 | ||
| 75 | #define v6info fam.v6 | ||
| 76 | |||
| 77 | /* Initialize an AVC audit data structure. */ | ||
| 78 | #define AVC_AUDIT_DATA_INIT(_d,_t) \ | ||
| 79 | { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; } | ||
| 80 | |||
| 81 | /* | 40 | /* |
| 82 | * AVC statistics | 41 | * AVC statistics |
| 83 | */ | 42 | */ |
| @@ -98,7 +57,9 @@ void __init avc_init(void); | |||
| 98 | 57 | ||
| 99 | void avc_audit(u32 ssid, u32 tsid, | 58 | void avc_audit(u32 ssid, u32 tsid, |
| 100 | u16 tclass, u32 requested, | 59 | u16 tclass, u32 requested, |
| 101 | struct av_decision *avd, int result, struct avc_audit_data *auditdata); | 60 | struct av_decision *avd, |
| 61 | int result, | ||
| 62 | struct common_audit_data *a); | ||
| 102 | 63 | ||
| 103 | #define AVC_STRICT 1 /* Ignore permissive mode. */ | 64 | #define AVC_STRICT 1 /* Ignore permissive mode. */ |
| 104 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 65 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, |
| @@ -108,7 +69,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
| 108 | 69 | ||
| 109 | int avc_has_perm(u32 ssid, u32 tsid, | 70 | int avc_has_perm(u32 ssid, u32 tsid, |
| 110 | u16 tclass, u32 requested, | 71 | u16 tclass, u32 requested, |
| 111 | struct avc_audit_data *auditdata); | 72 | struct common_audit_data *auditdata); |
| 112 | 73 | ||
| 113 | u32 avc_policy_seqno(void); | 74 | u32 avc_policy_seqno(void); |
| 114 | 75 | ||
| @@ -127,13 +88,13 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | |||
| 127 | u32 events, u32 ssid, u32 tsid, | 88 | u32 events, u32 ssid, u32 tsid, |
| 128 | u16 tclass, u32 perms); | 89 | u16 tclass, u32 perms); |
| 129 | 90 | ||
| 130 | /* Shows permission in human readable form */ | ||
| 131 | void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av); | ||
| 132 | |||
| 133 | /* Exported to selinuxfs */ | 91 | /* Exported to selinuxfs */ |
| 134 | int avc_get_hash_stats(char *page); | 92 | int avc_get_hash_stats(char *page); |
| 135 | extern unsigned int avc_cache_threshold; | 93 | extern unsigned int avc_cache_threshold; |
| 136 | 94 | ||
| 95 | /* Attempt to free avc node cache */ | ||
| 96 | void avc_disable(void); | ||
| 97 | |||
| 137 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS | 98 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS |
| 138 | DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); | 99 | DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); |
| 139 | #endif | 100 | #endif |
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index 21ec786611d4..7ab9299bfb6b 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h | |||
| @@ -77,3 +77,4 @@ | |||
| 77 | S_(NULL) | 77 | S_(NULL) |
| 78 | S_(NULL) | 78 | S_(NULL) |
| 79 | S_("kernel_service") | 79 | S_("kernel_service") |
| 80 | S_("tun_socket") | ||
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index 882f27d66fac..f248500a1e3c 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #define SECCLASS_PEER 68 | 53 | #define SECCLASS_PEER 68 |
| 54 | #define SECCLASS_CAPABILITY2 69 | 54 | #define SECCLASS_CAPABILITY2 69 |
| 55 | #define SECCLASS_KERNEL_SERVICE 74 | 55 | #define SECCLASS_KERNEL_SERVICE 74 |
| 56 | #define SECCLASS_TUN_SOCKET 75 | ||
| 56 | 57 | ||
| 57 | /* | 58 | /* |
| 58 | * Security identifier indices for initial entities | 59 | * Security identifier indices for initial entities |
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index b4b5b9b2f0be..8d7384280a7a 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h | |||
| @@ -59,7 +59,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family); | |||
| 59 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 59 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
| 60 | struct sk_buff *skb, | 60 | struct sk_buff *skb, |
| 61 | u16 family, | 61 | u16 family, |
| 62 | struct avc_audit_data *ad); | 62 | struct common_audit_data *ad); |
| 63 | int selinux_netlbl_socket_setsockopt(struct socket *sock, | 63 | int selinux_netlbl_socket_setsockopt(struct socket *sock, |
| 64 | int level, | 64 | int level, |
| 65 | int optname); | 65 | int optname); |
| @@ -129,7 +129,7 @@ static inline int selinux_netlbl_socket_post_create(struct sock *sk, | |||
| 129 | static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 129 | static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
| 130 | struct sk_buff *skb, | 130 | struct sk_buff *skb, |
| 131 | u16 family, | 131 | u16 family, |
| 132 | struct avc_audit_data *ad) | 132 | struct common_audit_data *ad) |
| 133 | { | 133 | { |
| 134 | return 0; | 134 | return 0; |
| 135 | } | 135 | } |
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 289e24b39e3e..13128f9a3e5a 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
| @@ -41,9 +41,9 @@ static inline int selinux_xfrm_enabled(void) | |||
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, | 43 | int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, |
| 44 | struct avc_audit_data *ad); | 44 | struct common_audit_data *ad); |
| 45 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 45 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
| 46 | struct avc_audit_data *ad, u8 proto); | 46 | struct common_audit_data *ad, u8 proto); |
| 47 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); | 47 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); |
| 48 | 48 | ||
| 49 | static inline void selinux_xfrm_notify_policyload(void) | 49 | static inline void selinux_xfrm_notify_policyload(void) |
| @@ -57,13 +57,13 @@ static inline int selinux_xfrm_enabled(void) | |||
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 59 | static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, |
| 60 | struct avc_audit_data *ad) | 60 | struct common_audit_data *ad) |
| 61 | { | 61 | { |
| 62 | return 0; | 62 | return 0; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 65 | static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
| 66 | struct avc_audit_data *ad, u8 proto) | 66 | struct common_audit_data *ad, u8 proto) |
| 67 | { | 67 | { |
| 68 | return 0; | 68 | return 0; |
| 69 | } | 69 | } |
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 2e984413c7b2..e68823741ad5 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
| @@ -342,7 +342,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) | |||
| 342 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 342 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
| 343 | struct sk_buff *skb, | 343 | struct sk_buff *skb, |
| 344 | u16 family, | 344 | u16 family, |
| 345 | struct avc_audit_data *ad) | 345 | struct common_audit_data *ad) |
| 346 | { | 346 | { |
| 347 | int rc; | 347 | int rc; |
| 348 | u32 nlbl_sid; | 348 | u32 nlbl_sid; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 500e6f78e115..ff17820d35ec 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -22,6 +22,11 @@ | |||
| 22 | * | 22 | * |
| 23 | * Added validation of kernel classes and permissions | 23 | * Added validation of kernel classes and permissions |
| 24 | * | 24 | * |
| 25 | * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
| 26 | * | ||
| 27 | * Added support for bounds domain and audit messaged on masked permissions | ||
| 28 | * | ||
| 29 | * Copyright (C) 2008, 2009 NEC Corporation | ||
| 25 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 30 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. |
| 26 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. | 31 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
| 27 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC | 32 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC |
| @@ -279,6 +284,95 @@ mls_ops: | |||
| 279 | } | 284 | } |
| 280 | 285 | ||
| 281 | /* | 286 | /* |
| 287 | * security_dump_masked_av - dumps masked permissions during | ||
| 288 | * security_compute_av due to RBAC, MLS/Constraint and Type bounds. | ||
| 289 | */ | ||
| 290 | static int dump_masked_av_helper(void *k, void *d, void *args) | ||
| 291 | { | ||
| 292 | struct perm_datum *pdatum = d; | ||
| 293 | char **permission_names = args; | ||
| 294 | |||
| 295 | BUG_ON(pdatum->value < 1 || pdatum->value > 32); | ||
| 296 | |||
| 297 | permission_names[pdatum->value - 1] = (char *)k; | ||
| 298 | |||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | |||
| 302 | static void security_dump_masked_av(struct context *scontext, | ||
| 303 | struct context *tcontext, | ||
| 304 | u16 tclass, | ||
| 305 | u32 permissions, | ||
| 306 | const char *reason) | ||
| 307 | { | ||
| 308 | struct common_datum *common_dat; | ||
| 309 | struct class_datum *tclass_dat; | ||
| 310 | struct audit_buffer *ab; | ||
| 311 | char *tclass_name; | ||
| 312 | char *scontext_name = NULL; | ||
| 313 | char *tcontext_name = NULL; | ||
| 314 | char *permission_names[32]; | ||
| 315 | int index, length; | ||
| 316 | bool need_comma = false; | ||
| 317 | |||
| 318 | if (!permissions) | ||
| 319 | return; | ||
| 320 | |||
| 321 | tclass_name = policydb.p_class_val_to_name[tclass - 1]; | ||
| 322 | tclass_dat = policydb.class_val_to_struct[tclass - 1]; | ||
| 323 | common_dat = tclass_dat->comdatum; | ||
| 324 | |||
| 325 | /* init permission_names */ | ||
| 326 | if (common_dat && | ||
| 327 | hashtab_map(common_dat->permissions.table, | ||
| 328 | dump_masked_av_helper, permission_names) < 0) | ||
| 329 | goto out; | ||
| 330 | |||
| 331 | if (hashtab_map(tclass_dat->permissions.table, | ||
| 332 | dump_masked_av_helper, permission_names) < 0) | ||
| 333 | goto out; | ||
| 334 | |||
| 335 | /* get scontext/tcontext in text form */ | ||
| 336 | if (context_struct_to_string(scontext, | ||
| 337 | &scontext_name, &length) < 0) | ||
| 338 | goto out; | ||
| 339 | |||
| 340 | if (context_struct_to_string(tcontext, | ||
| 341 | &tcontext_name, &length) < 0) | ||
| 342 | goto out; | ||
| 343 | |||
| 344 | /* audit a message */ | ||
| 345 | ab = audit_log_start(current->audit_context, | ||
| 346 | GFP_ATOMIC, AUDIT_SELINUX_ERR); | ||
| 347 | if (!ab) | ||
| 348 | goto out; | ||
| 349 | |||
| 350 | audit_log_format(ab, "op=security_compute_av reason=%s " | ||
| 351 | "scontext=%s tcontext=%s tclass=%s perms=", | ||
| 352 | reason, scontext_name, tcontext_name, tclass_name); | ||
| 353 | |||
| 354 | for (index = 0; index < 32; index++) { | ||
| 355 | u32 mask = (1 << index); | ||
| 356 | |||
| 357 | if ((mask & permissions) == 0) | ||
| 358 | continue; | ||
| 359 | |||
| 360 | audit_log_format(ab, "%s%s", | ||
| 361 | need_comma ? "," : "", | ||
| 362 | permission_names[index] | ||
| 363 | ? permission_names[index] : "????"); | ||
| 364 | need_comma = true; | ||
| 365 | } | ||
| 366 | audit_log_end(ab); | ||
| 367 | out: | ||
| 368 | /* release scontext/tcontext */ | ||
| 369 | kfree(tcontext_name); | ||
| 370 | kfree(scontext_name); | ||
| 371 | |||
| 372 | return; | ||
| 373 | } | ||
| 374 | |||
| 375 | /* | ||
| 282 | * security_boundary_permission - drops violated permissions | 376 | * security_boundary_permission - drops violated permissions |
| 283 | * on boundary constraint. | 377 | * on boundary constraint. |
| 284 | */ | 378 | */ |
| @@ -347,28 +441,12 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
| 347 | } | 441 | } |
| 348 | 442 | ||
| 349 | if (masked) { | 443 | if (masked) { |
| 350 | struct audit_buffer *ab; | ||
| 351 | char *stype_name | ||
| 352 | = policydb.p_type_val_to_name[source->value - 1]; | ||
| 353 | char *ttype_name | ||
| 354 | = policydb.p_type_val_to_name[target->value - 1]; | ||
| 355 | char *tclass_name | ||
| 356 | = policydb.p_class_val_to_name[tclass - 1]; | ||
| 357 | |||
| 358 | /* mask violated permissions */ | 444 | /* mask violated permissions */ |
| 359 | avd->allowed &= ~masked; | 445 | avd->allowed &= ~masked; |
| 360 | 446 | ||
| 361 | /* notice to userspace via audit message */ | 447 | /* audit masked permissions */ |
| 362 | ab = audit_log_start(current->audit_context, | 448 | security_dump_masked_av(scontext, tcontext, |
| 363 | GFP_ATOMIC, AUDIT_SELINUX_ERR); | 449 | tclass, masked, "bounds"); |
| 364 | if (!ab) | ||
| 365 | return; | ||
| 366 | |||
| 367 | audit_log_format(ab, "av boundary violation: " | ||
| 368 | "source=%s target=%s tclass=%s", | ||
| 369 | stype_name, ttype_name, tclass_name); | ||
| 370 | avc_dump_av(ab, tclass, masked); | ||
| 371 | audit_log_end(ab); | ||
| 372 | } | 450 | } |
| 373 | } | 451 | } |
| 374 | 452 | ||
| @@ -480,7 +558,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
| 480 | if ((constraint->permissions & (avd->allowed)) && | 558 | if ((constraint->permissions & (avd->allowed)) && |
| 481 | !constraint_expr_eval(scontext, tcontext, NULL, | 559 | !constraint_expr_eval(scontext, tcontext, NULL, |
| 482 | constraint->expr)) { | 560 | constraint->expr)) { |
| 483 | avd->allowed = (avd->allowed) & ~(constraint->permissions); | 561 | avd->allowed &= ~(constraint->permissions); |
| 484 | } | 562 | } |
| 485 | constraint = constraint->next; | 563 | constraint = constraint->next; |
| 486 | } | 564 | } |
| @@ -499,8 +577,8 @@ static int context_struct_compute_av(struct context *scontext, | |||
| 499 | break; | 577 | break; |
| 500 | } | 578 | } |
| 501 | if (!ra) | 579 | if (!ra) |
| 502 | avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | | 580 | avd->allowed &= ~(PROCESS__TRANSITION | |
| 503 | PROCESS__DYNTRANSITION); | 581 | PROCESS__DYNTRANSITION); |
| 504 | } | 582 | } |
| 505 | 583 | ||
| 506 | /* | 584 | /* |
| @@ -687,6 +765,26 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
| 687 | } | 765 | } |
| 688 | index = type->bounds; | 766 | index = type->bounds; |
| 689 | } | 767 | } |
| 768 | |||
| 769 | if (rc) { | ||
| 770 | char *old_name = NULL; | ||
| 771 | char *new_name = NULL; | ||
| 772 | int length; | ||
| 773 | |||
| 774 | if (!context_struct_to_string(old_context, | ||
| 775 | &old_name, &length) && | ||
| 776 | !context_struct_to_string(new_context, | ||
| 777 | &new_name, &length)) { | ||
| 778 | audit_log(current->audit_context, | ||
| 779 | GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
| 780 | "op=security_bounded_transition " | ||
| 781 | "result=denied " | ||
| 782 | "oldcontext=%s newcontext=%s", | ||
| 783 | old_name, new_name); | ||
| 784 | } | ||
| 785 | kfree(new_name); | ||
| 786 | kfree(old_name); | ||
| 787 | } | ||
| 690 | out: | 788 | out: |
| 691 | read_unlock(&policy_rwlock); | 789 | read_unlock(&policy_rwlock); |
| 692 | 790 | ||
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 72b18452e1a1..f3cb9ed731a9 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
| @@ -401,7 +401,7 @@ int selinux_xfrm_state_delete(struct xfrm_state *x) | |||
| 401 | * gone thru the IPSec process. | 401 | * gone thru the IPSec process. |
| 402 | */ | 402 | */ |
| 403 | int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 403 | int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, |
| 404 | struct avc_audit_data *ad) | 404 | struct common_audit_data *ad) |
| 405 | { | 405 | { |
| 406 | int i, rc = 0; | 406 | int i, rc = 0; |
| 407 | struct sec_path *sp; | 407 | struct sec_path *sp; |
| @@ -442,7 +442,7 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | |||
| 442 | * checked in the selinux_xfrm_state_pol_flow_match hook above. | 442 | * checked in the selinux_xfrm_state_pol_flow_match hook above. |
| 443 | */ | 443 | */ |
| 444 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 444 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, |
| 445 | struct avc_audit_data *ad, u8 proto) | 445 | struct common_audit_data *ad, u8 proto) |
| 446 | { | 446 | { |
| 447 | struct dst_entry *dst; | 447 | struct dst_entry *dst; |
| 448 | int rc = 0; | 448 | int rc = 0; |
