diff options
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/avc.c | 130 | ||||
-rw-r--r-- | security/selinux/hooks.c | 283 | ||||
-rw-r--r-- | security/selinux/include/avc.h | 100 | ||||
-rw-r--r-- | security/selinux/include/security.h | 4 | ||||
-rw-r--r-- | security/selinux/netif.c | 6 | ||||
-rw-r--r-- | security/selinux/netnode.c | 6 | ||||
-rw-r--r-- | security/selinux/netport.c | 6 | ||||
-rw-r--r-- | security/selinux/nlmsgtab.c | 13 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 47 | ||||
-rw-r--r-- | security/selinux/ss/context.h | 20 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 24 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 44 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 14 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 56 |
14 files changed, 398 insertions, 355 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 8ee42b2a5f19..68d82daed257 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -65,14 +65,8 @@ struct avc_cache { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct avc_callback_node { | 67 | struct avc_callback_node { |
68 | int (*callback) (u32 event, u32 ssid, u32 tsid, | 68 | int (*callback) (u32 event); |
69 | u16 tclass, u32 perms, | ||
70 | u32 *out_retained); | ||
71 | u32 events; | 69 | u32 events; |
72 | u32 ssid; | ||
73 | u32 tsid; | ||
74 | u16 tclass; | ||
75 | u32 perms; | ||
76 | struct avc_callback_node *next; | 70 | struct avc_callback_node *next; |
77 | }; | 71 | }; |
78 | 72 | ||
@@ -436,9 +430,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) | |||
436 | { | 430 | { |
437 | struct common_audit_data *ad = a; | 431 | struct common_audit_data *ad = a; |
438 | audit_log_format(ab, "avc: %s ", | 432 | audit_log_format(ab, "avc: %s ", |
439 | ad->selinux_audit_data->slad->denied ? "denied" : "granted"); | 433 | ad->selinux_audit_data->denied ? "denied" : "granted"); |
440 | avc_dump_av(ab, ad->selinux_audit_data->slad->tclass, | 434 | avc_dump_av(ab, ad->selinux_audit_data->tclass, |
441 | ad->selinux_audit_data->slad->audited); | 435 | ad->selinux_audit_data->audited); |
442 | audit_log_format(ab, " for "); | 436 | audit_log_format(ab, " for "); |
443 | } | 437 | } |
444 | 438 | ||
@@ -452,25 +446,23 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | |||
452 | { | 446 | { |
453 | struct common_audit_data *ad = a; | 447 | struct common_audit_data *ad = a; |
454 | audit_log_format(ab, " "); | 448 | audit_log_format(ab, " "); |
455 | avc_dump_query(ab, ad->selinux_audit_data->slad->ssid, | 449 | avc_dump_query(ab, ad->selinux_audit_data->ssid, |
456 | ad->selinux_audit_data->slad->tsid, | 450 | ad->selinux_audit_data->tsid, |
457 | ad->selinux_audit_data->slad->tclass); | 451 | ad->selinux_audit_data->tclass); |
458 | } | 452 | } |
459 | 453 | ||
460 | /* This is the slow part of avc audit with big stack footprint */ | 454 | /* This is the slow part of avc audit with big stack footprint */ |
461 | static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, | 455 | noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, |
462 | u32 requested, u32 audited, u32 denied, | 456 | u32 requested, u32 audited, u32 denied, |
463 | struct common_audit_data *a, | 457 | struct common_audit_data *a, |
464 | unsigned flags) | 458 | unsigned flags) |
465 | { | 459 | { |
466 | struct common_audit_data stack_data; | 460 | struct common_audit_data stack_data; |
467 | struct selinux_audit_data sad = {0,}; | 461 | struct selinux_audit_data sad; |
468 | struct selinux_late_audit_data slad; | ||
469 | 462 | ||
470 | if (!a) { | 463 | if (!a) { |
471 | a = &stack_data; | 464 | a = &stack_data; |
472 | COMMON_AUDIT_DATA_INIT(a, NONE); | 465 | a->type = LSM_AUDIT_DATA_NONE; |
473 | a->selinux_audit_data = &sad; | ||
474 | } | 466 | } |
475 | 467 | ||
476 | /* | 468 | /* |
@@ -484,104 +476,34 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, | |||
484 | (flags & MAY_NOT_BLOCK)) | 476 | (flags & MAY_NOT_BLOCK)) |
485 | return -ECHILD; | 477 | return -ECHILD; |
486 | 478 | ||
487 | slad.tclass = tclass; | 479 | sad.tclass = tclass; |
488 | slad.requested = requested; | 480 | sad.requested = requested; |
489 | slad.ssid = ssid; | 481 | sad.ssid = ssid; |
490 | slad.tsid = tsid; | 482 | sad.tsid = tsid; |
491 | slad.audited = audited; | 483 | sad.audited = audited; |
492 | slad.denied = denied; | 484 | sad.denied = denied; |
485 | |||
486 | a->selinux_audit_data = &sad; | ||
493 | 487 | ||
494 | a->selinux_audit_data->slad = &slad; | ||
495 | common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback); | 488 | common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback); |
496 | return 0; | 489 | return 0; |
497 | } | 490 | } |
498 | 491 | ||
499 | /** | 492 | /** |
500 | * avc_audit - Audit the granting or denial of permissions. | ||
501 | * @ssid: source security identifier | ||
502 | * @tsid: target security identifier | ||
503 | * @tclass: target security class | ||
504 | * @requested: requested permissions | ||
505 | * @avd: access vector decisions | ||
506 | * @result: result from avc_has_perm_noaudit | ||
507 | * @a: auxiliary audit data | ||
508 | * @flags: VFS walk flags | ||
509 | * | ||
510 | * Audit the granting or denial of permissions in accordance | ||
511 | * with the policy. This function is typically called by | ||
512 | * avc_has_perm() after a permission check, but can also be | ||
513 | * called directly by callers who use avc_has_perm_noaudit() | ||
514 | * in order to separate the permission check from the auditing. | ||
515 | * For example, this separation is useful when the permission check must | ||
516 | * be performed under a lock, to allow the lock to be released | ||
517 | * before calling the auditing code. | ||
518 | */ | ||
519 | inline int avc_audit(u32 ssid, u32 tsid, | ||
520 | u16 tclass, u32 requested, | ||
521 | struct av_decision *avd, int result, struct common_audit_data *a, | ||
522 | unsigned flags) | ||
523 | { | ||
524 | u32 denied, audited; | ||
525 | denied = requested & ~avd->allowed; | ||
526 | if (unlikely(denied)) { | ||
527 | audited = denied & avd->auditdeny; | ||
528 | /* | ||
529 | * a->selinux_audit_data->auditdeny is TRICKY! Setting a bit in | ||
530 | * this field means that ANY denials should NOT be audited if | ||
531 | * the policy contains an explicit dontaudit rule for that | ||
532 | * permission. Take notice that this is unrelated to the | ||
533 | * actual permissions that were denied. As an example lets | ||
534 | * assume: | ||
535 | * | ||
536 | * denied == READ | ||
537 | * avd.auditdeny & ACCESS == 0 (not set means explicit rule) | ||
538 | * selinux_audit_data->auditdeny & ACCESS == 1 | ||
539 | * | ||
540 | * We will NOT audit the denial even though the denied | ||
541 | * permission was READ and the auditdeny checks were for | ||
542 | * ACCESS | ||
543 | */ | ||
544 | if (a && | ||
545 | a->selinux_audit_data->auditdeny && | ||
546 | !(a->selinux_audit_data->auditdeny & avd->auditdeny)) | ||
547 | audited = 0; | ||
548 | } else if (result) | ||
549 | audited = denied = requested; | ||
550 | else | ||
551 | audited = requested & avd->auditallow; | ||
552 | if (likely(!audited)) | ||
553 | return 0; | ||
554 | |||
555 | return slow_avc_audit(ssid, tsid, tclass, | ||
556 | requested, audited, denied, | ||
557 | a, flags); | ||
558 | } | ||
559 | |||
560 | /** | ||
561 | * avc_add_callback - Register a callback for security events. | 493 | * avc_add_callback - Register a callback for security events. |
562 | * @callback: callback function | 494 | * @callback: callback function |
563 | * @events: security events | 495 | * @events: security events |
564 | * @ssid: source security identifier or %SECSID_WILD | ||
565 | * @tsid: target security identifier or %SECSID_WILD | ||
566 | * @tclass: target security class | ||
567 | * @perms: permissions | ||
568 | * | 496 | * |
569 | * Register a callback function for events in the set @events | 497 | * Register a callback function for events in the set @events. |
570 | * related to the SID pair (@ssid, @tsid) | 498 | * Returns %0 on success or -%ENOMEM if insufficient memory |
571 | * and the permissions @perms, interpreting | 499 | * exists to add the callback. |
572 | * @perms based on @tclass. Returns %0 on success or | ||
573 | * -%ENOMEM if insufficient memory exists to add the callback. | ||
574 | */ | 500 | */ |
575 | int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | 501 | int __init avc_add_callback(int (*callback)(u32 event), u32 events) |
576 | u16 tclass, u32 perms, | ||
577 | u32 *out_retained), | ||
578 | u32 events, u32 ssid, u32 tsid, | ||
579 | u16 tclass, u32 perms) | ||
580 | { | 502 | { |
581 | struct avc_callback_node *c; | 503 | struct avc_callback_node *c; |
582 | int rc = 0; | 504 | int rc = 0; |
583 | 505 | ||
584 | c = kmalloc(sizeof(*c), GFP_ATOMIC); | 506 | c = kmalloc(sizeof(*c), GFP_KERNEL); |
585 | if (!c) { | 507 | if (!c) { |
586 | rc = -ENOMEM; | 508 | rc = -ENOMEM; |
587 | goto out; | 509 | goto out; |
@@ -589,9 +511,6 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | |||
589 | 511 | ||
590 | c->callback = callback; | 512 | c->callback = callback; |
591 | c->events = events; | 513 | c->events = events; |
592 | c->ssid = ssid; | ||
593 | c->tsid = tsid; | ||
594 | c->perms = perms; | ||
595 | c->next = avc_callbacks; | 514 | c->next = avc_callbacks; |
596 | avc_callbacks = c; | 515 | avc_callbacks = c; |
597 | out: | 516 | out: |
@@ -731,8 +650,7 @@ int avc_ss_reset(u32 seqno) | |||
731 | 650 | ||
732 | for (c = avc_callbacks; c; c = c->next) { | 651 | for (c = avc_callbacks; c; c = c->next) { |
733 | if (c->events & AVC_CALLBACK_RESET) { | 652 | if (c->events & AVC_CALLBACK_RESET) { |
734 | tmprc = c->callback(AVC_CALLBACK_RESET, | 653 | tmprc = c->callback(AVC_CALLBACK_RESET); |
735 | 0, 0, 0, 0, NULL); | ||
736 | /* save the first error encountered for the return | 654 | /* save the first error encountered for the return |
737 | value and continue processing the callbacks */ | 655 | value and continue processing the callbacks */ |
738 | if (!rc) | 656 | if (!rc) |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d85b793c9321..372ec6502aa8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -1420,16 +1420,13 @@ static int cred_has_capability(const struct cred *cred, | |||
1420 | int cap, int audit) | 1420 | int cap, int audit) |
1421 | { | 1421 | { |
1422 | struct common_audit_data ad; | 1422 | struct common_audit_data ad; |
1423 | struct selinux_audit_data sad = {0,}; | ||
1424 | struct av_decision avd; | 1423 | struct av_decision avd; |
1425 | u16 sclass; | 1424 | u16 sclass; |
1426 | u32 sid = cred_sid(cred); | 1425 | u32 sid = cred_sid(cred); |
1427 | u32 av = CAP_TO_MASK(cap); | 1426 | u32 av = CAP_TO_MASK(cap); |
1428 | int rc; | 1427 | int rc; |
1429 | 1428 | ||
1430 | COMMON_AUDIT_DATA_INIT(&ad, CAP); | 1429 | ad.type = LSM_AUDIT_DATA_CAP; |
1431 | ad.selinux_audit_data = &sad; | ||
1432 | ad.tsk = current; | ||
1433 | ad.u.cap = cap; | 1430 | ad.u.cap = cap; |
1434 | 1431 | ||
1435 | switch (CAP_TO_INDEX(cap)) { | 1432 | switch (CAP_TO_INDEX(cap)) { |
@@ -1488,20 +1485,6 @@ static int inode_has_perm(const struct cred *cred, | |||
1488 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); | 1485 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); |
1489 | } | 1486 | } |
1490 | 1487 | ||
1491 | static int inode_has_perm_noadp(const struct cred *cred, | ||
1492 | struct inode *inode, | ||
1493 | u32 perms, | ||
1494 | unsigned flags) | ||
1495 | { | ||
1496 | struct common_audit_data ad; | ||
1497 | struct selinux_audit_data sad = {0,}; | ||
1498 | |||
1499 | COMMON_AUDIT_DATA_INIT(&ad, INODE); | ||
1500 | ad.u.inode = inode; | ||
1501 | ad.selinux_audit_data = &sad; | ||
1502 | return inode_has_perm(cred, inode, perms, &ad, flags); | ||
1503 | } | ||
1504 | |||
1505 | /* Same as inode_has_perm, but pass explicit audit data containing | 1488 | /* Same as inode_has_perm, but pass explicit audit data containing |
1506 | the dentry to help the auditing code to more easily generate the | 1489 | the dentry to help the auditing code to more easily generate the |
1507 | pathname if needed. */ | 1490 | pathname if needed. */ |
@@ -1511,11 +1494,9 @@ static inline int dentry_has_perm(const struct cred *cred, | |||
1511 | { | 1494 | { |
1512 | struct inode *inode = dentry->d_inode; | 1495 | struct inode *inode = dentry->d_inode; |
1513 | struct common_audit_data ad; | 1496 | struct common_audit_data ad; |
1514 | struct selinux_audit_data sad = {0,}; | ||
1515 | 1497 | ||
1516 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1498 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1517 | ad.u.dentry = dentry; | 1499 | ad.u.dentry = dentry; |
1518 | ad.selinux_audit_data = &sad; | ||
1519 | return inode_has_perm(cred, inode, av, &ad, 0); | 1500 | return inode_has_perm(cred, inode, av, &ad, 0); |
1520 | } | 1501 | } |
1521 | 1502 | ||
@@ -1528,11 +1509,9 @@ static inline int path_has_perm(const struct cred *cred, | |||
1528 | { | 1509 | { |
1529 | struct inode *inode = path->dentry->d_inode; | 1510 | struct inode *inode = path->dentry->d_inode; |
1530 | struct common_audit_data ad; | 1511 | struct common_audit_data ad; |
1531 | struct selinux_audit_data sad = {0,}; | ||
1532 | 1512 | ||
1533 | COMMON_AUDIT_DATA_INIT(&ad, PATH); | 1513 | ad.type = LSM_AUDIT_DATA_PATH; |
1534 | ad.u.path = *path; | 1514 | ad.u.path = *path; |
1535 | ad.selinux_audit_data = &sad; | ||
1536 | return inode_has_perm(cred, inode, av, &ad, 0); | 1515 | return inode_has_perm(cred, inode, av, &ad, 0); |
1537 | } | 1516 | } |
1538 | 1517 | ||
@@ -1551,13 +1530,11 @@ static int file_has_perm(const struct cred *cred, | |||
1551 | struct file_security_struct *fsec = file->f_security; | 1530 | struct file_security_struct *fsec = file->f_security; |
1552 | struct inode *inode = file->f_path.dentry->d_inode; | 1531 | struct inode *inode = file->f_path.dentry->d_inode; |
1553 | struct common_audit_data ad; | 1532 | struct common_audit_data ad; |
1554 | struct selinux_audit_data sad = {0,}; | ||
1555 | u32 sid = cred_sid(cred); | 1533 | u32 sid = cred_sid(cred); |
1556 | int rc; | 1534 | int rc; |
1557 | 1535 | ||
1558 | COMMON_AUDIT_DATA_INIT(&ad, PATH); | 1536 | ad.type = LSM_AUDIT_DATA_PATH; |
1559 | ad.u.path = file->f_path; | 1537 | ad.u.path = file->f_path; |
1560 | ad.selinux_audit_data = &sad; | ||
1561 | 1538 | ||
1562 | if (sid != fsec->sid) { | 1539 | if (sid != fsec->sid) { |
1563 | rc = avc_has_perm(sid, fsec->sid, | 1540 | rc = avc_has_perm(sid, fsec->sid, |
@@ -1587,7 +1564,6 @@ static int may_create(struct inode *dir, | |||
1587 | struct superblock_security_struct *sbsec; | 1564 | struct superblock_security_struct *sbsec; |
1588 | u32 sid, newsid; | 1565 | u32 sid, newsid; |
1589 | struct common_audit_data ad; | 1566 | struct common_audit_data ad; |
1590 | struct selinux_audit_data sad = {0,}; | ||
1591 | int rc; | 1567 | int rc; |
1592 | 1568 | ||
1593 | dsec = dir->i_security; | 1569 | dsec = dir->i_security; |
@@ -1596,9 +1572,8 @@ static int may_create(struct inode *dir, | |||
1596 | sid = tsec->sid; | 1572 | sid = tsec->sid; |
1597 | newsid = tsec->create_sid; | 1573 | newsid = tsec->create_sid; |
1598 | 1574 | ||
1599 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1575 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1600 | ad.u.dentry = dentry; | 1576 | ad.u.dentry = dentry; |
1601 | ad.selinux_audit_data = &sad; | ||
1602 | 1577 | ||
1603 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1578 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
1604 | DIR__ADD_NAME | DIR__SEARCH, | 1579 | DIR__ADD_NAME | DIR__SEARCH, |
@@ -1643,7 +1618,6 @@ static int may_link(struct inode *dir, | |||
1643 | { | 1618 | { |
1644 | struct inode_security_struct *dsec, *isec; | 1619 | struct inode_security_struct *dsec, *isec; |
1645 | struct common_audit_data ad; | 1620 | struct common_audit_data ad; |
1646 | struct selinux_audit_data sad = {0,}; | ||
1647 | u32 sid = current_sid(); | 1621 | u32 sid = current_sid(); |
1648 | u32 av; | 1622 | u32 av; |
1649 | int rc; | 1623 | int rc; |
@@ -1651,9 +1625,8 @@ static int may_link(struct inode *dir, | |||
1651 | dsec = dir->i_security; | 1625 | dsec = dir->i_security; |
1652 | isec = dentry->d_inode->i_security; | 1626 | isec = dentry->d_inode->i_security; |
1653 | 1627 | ||
1654 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1628 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1655 | ad.u.dentry = dentry; | 1629 | ad.u.dentry = dentry; |
1656 | ad.selinux_audit_data = &sad; | ||
1657 | 1630 | ||
1658 | av = DIR__SEARCH; | 1631 | av = DIR__SEARCH; |
1659 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); | 1632 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); |
@@ -1688,7 +1661,6 @@ static inline int may_rename(struct inode *old_dir, | |||
1688 | { | 1661 | { |
1689 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; | 1662 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; |
1690 | struct common_audit_data ad; | 1663 | struct common_audit_data ad; |
1691 | struct selinux_audit_data sad = {0,}; | ||
1692 | u32 sid = current_sid(); | 1664 | u32 sid = current_sid(); |
1693 | u32 av; | 1665 | u32 av; |
1694 | int old_is_dir, new_is_dir; | 1666 | int old_is_dir, new_is_dir; |
@@ -1699,8 +1671,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1699 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 1671 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
1700 | new_dsec = new_dir->i_security; | 1672 | new_dsec = new_dir->i_security; |
1701 | 1673 | ||
1702 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 1674 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1703 | ad.selinux_audit_data = &sad; | ||
1704 | 1675 | ||
1705 | ad.u.dentry = old_dentry; | 1676 | ad.u.dentry = old_dentry; |
1706 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 1677 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, |
@@ -1986,7 +1957,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
1986 | struct task_security_struct *new_tsec; | 1957 | struct task_security_struct *new_tsec; |
1987 | struct inode_security_struct *isec; | 1958 | struct inode_security_struct *isec; |
1988 | struct common_audit_data ad; | 1959 | struct common_audit_data ad; |
1989 | struct selinux_audit_data sad = {0,}; | ||
1990 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | 1960 | struct inode *inode = bprm->file->f_path.dentry->d_inode; |
1991 | int rc; | 1961 | int rc; |
1992 | 1962 | ||
@@ -2016,6 +1986,13 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2016 | new_tsec->sid = old_tsec->exec_sid; | 1986 | new_tsec->sid = old_tsec->exec_sid; |
2017 | /* Reset exec SID on execve. */ | 1987 | /* Reset exec SID on execve. */ |
2018 | new_tsec->exec_sid = 0; | 1988 | new_tsec->exec_sid = 0; |
1989 | |||
1990 | /* | ||
1991 | * Minimize confusion: if no_new_privs and a transition is | ||
1992 | * explicitly requested, then fail the exec. | ||
1993 | */ | ||
1994 | if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) | ||
1995 | return -EPERM; | ||
2019 | } else { | 1996 | } else { |
2020 | /* Check for a default transition on this program. */ | 1997 | /* Check for a default transition on this program. */ |
2021 | rc = security_transition_sid(old_tsec->sid, isec->sid, | 1998 | rc = security_transition_sid(old_tsec->sid, isec->sid, |
@@ -2025,11 +2002,11 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2025 | return rc; | 2002 | return rc; |
2026 | } | 2003 | } |
2027 | 2004 | ||
2028 | COMMON_AUDIT_DATA_INIT(&ad, PATH); | 2005 | ad.type = LSM_AUDIT_DATA_PATH; |
2029 | ad.selinux_audit_data = &sad; | ||
2030 | ad.u.path = bprm->file->f_path; | 2006 | ad.u.path = bprm->file->f_path; |
2031 | 2007 | ||
2032 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 2008 | if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) || |
2009 | (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) | ||
2033 | new_tsec->sid = old_tsec->sid; | 2010 | new_tsec->sid = old_tsec->sid; |
2034 | 2011 | ||
2035 | if (new_tsec->sid == old_tsec->sid) { | 2012 | if (new_tsec->sid == old_tsec->sid) { |
@@ -2115,8 +2092,6 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm) | |||
2115 | static inline void flush_unauthorized_files(const struct cred *cred, | 2092 | static inline void flush_unauthorized_files(const struct cred *cred, |
2116 | struct files_struct *files) | 2093 | struct files_struct *files) |
2117 | { | 2094 | { |
2118 | struct common_audit_data ad; | ||
2119 | struct selinux_audit_data sad = {0,}; | ||
2120 | struct file *file, *devnull = NULL; | 2095 | struct file *file, *devnull = NULL; |
2121 | struct tty_struct *tty; | 2096 | struct tty_struct *tty; |
2122 | struct fdtable *fdt; | 2097 | struct fdtable *fdt; |
@@ -2128,21 +2103,17 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2128 | spin_lock(&tty_files_lock); | 2103 | spin_lock(&tty_files_lock); |
2129 | if (!list_empty(&tty->tty_files)) { | 2104 | if (!list_empty(&tty->tty_files)) { |
2130 | struct tty_file_private *file_priv; | 2105 | struct tty_file_private *file_priv; |
2131 | struct inode *inode; | ||
2132 | 2106 | ||
2133 | /* Revalidate access to controlling tty. | 2107 | /* Revalidate access to controlling tty. |
2134 | Use inode_has_perm on the tty inode directly rather | 2108 | Use path_has_perm on the tty path directly rather |
2135 | than using file_has_perm, as this particular open | 2109 | than using file_has_perm, as this particular open |
2136 | file may belong to another process and we are only | 2110 | file may belong to another process and we are only |
2137 | interested in the inode-based check here. */ | 2111 | interested in the inode-based check here. */ |
2138 | file_priv = list_first_entry(&tty->tty_files, | 2112 | file_priv = list_first_entry(&tty->tty_files, |
2139 | struct tty_file_private, list); | 2113 | struct tty_file_private, list); |
2140 | file = file_priv->file; | 2114 | file = file_priv->file; |
2141 | inode = file->f_path.dentry->d_inode; | 2115 | if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE)) |
2142 | if (inode_has_perm_noadp(cred, inode, | ||
2143 | FILE__READ | FILE__WRITE, 0)) { | ||
2144 | drop_tty = 1; | 2116 | drop_tty = 1; |
2145 | } | ||
2146 | } | 2117 | } |
2147 | spin_unlock(&tty_files_lock); | 2118 | spin_unlock(&tty_files_lock); |
2148 | tty_kref_put(tty); | 2119 | tty_kref_put(tty); |
@@ -2152,10 +2123,6 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2152 | no_tty(); | 2123 | no_tty(); |
2153 | 2124 | ||
2154 | /* Revalidate access to inherited open files. */ | 2125 | /* Revalidate access to inherited open files. */ |
2155 | |||
2156 | COMMON_AUDIT_DATA_INIT(&ad, INODE); | ||
2157 | ad.selinux_audit_data = &sad; | ||
2158 | |||
2159 | spin_lock(&files->file_lock); | 2126 | spin_lock(&files->file_lock); |
2160 | for (;;) { | 2127 | for (;;) { |
2161 | unsigned long set, i; | 2128 | unsigned long set, i; |
@@ -2492,7 +2459,6 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2492 | { | 2459 | { |
2493 | const struct cred *cred = current_cred(); | 2460 | const struct cred *cred = current_cred(); |
2494 | struct common_audit_data ad; | 2461 | struct common_audit_data ad; |
2495 | struct selinux_audit_data sad = {0,}; | ||
2496 | int rc; | 2462 | int rc; |
2497 | 2463 | ||
2498 | rc = superblock_doinit(sb, data); | 2464 | rc = superblock_doinit(sb, data); |
@@ -2503,8 +2469,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2503 | if (flags & MS_KERNMOUNT) | 2469 | if (flags & MS_KERNMOUNT) |
2504 | return 0; | 2470 | return 0; |
2505 | 2471 | ||
2506 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 2472 | ad.type = LSM_AUDIT_DATA_DENTRY; |
2507 | ad.selinux_audit_data = &sad; | ||
2508 | ad.u.dentry = sb->s_root; | 2473 | ad.u.dentry = sb->s_root; |
2509 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); | 2474 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
2510 | } | 2475 | } |
@@ -2513,10 +2478,8 @@ static int selinux_sb_statfs(struct dentry *dentry) | |||
2513 | { | 2478 | { |
2514 | const struct cred *cred = current_cred(); | 2479 | const struct cred *cred = current_cred(); |
2515 | struct common_audit_data ad; | 2480 | struct common_audit_data ad; |
2516 | struct selinux_audit_data sad = {0,}; | ||
2517 | 2481 | ||
2518 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 2482 | ad.type = LSM_AUDIT_DATA_DENTRY; |
2519 | ad.selinux_audit_data = &sad; | ||
2520 | ad.u.dentry = dentry->d_sb->s_root; | 2483 | ad.u.dentry = dentry->d_sb->s_root; |
2521 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); | 2484 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); |
2522 | } | 2485 | } |
@@ -2676,14 +2639,35 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | |||
2676 | return dentry_has_perm(cred, dentry, FILE__READ); | 2639 | return dentry_has_perm(cred, dentry, FILE__READ); |
2677 | } | 2640 | } |
2678 | 2641 | ||
2642 | static noinline int audit_inode_permission(struct inode *inode, | ||
2643 | u32 perms, u32 audited, u32 denied, | ||
2644 | unsigned flags) | ||
2645 | { | ||
2646 | struct common_audit_data ad; | ||
2647 | struct inode_security_struct *isec = inode->i_security; | ||
2648 | int rc; | ||
2649 | |||
2650 | ad.type = LSM_AUDIT_DATA_INODE; | ||
2651 | ad.u.inode = inode; | ||
2652 | |||
2653 | rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms, | ||
2654 | audited, denied, &ad, flags); | ||
2655 | if (rc) | ||
2656 | return rc; | ||
2657 | return 0; | ||
2658 | } | ||
2659 | |||
2679 | static int selinux_inode_permission(struct inode *inode, int mask) | 2660 | static int selinux_inode_permission(struct inode *inode, int mask) |
2680 | { | 2661 | { |
2681 | const struct cred *cred = current_cred(); | 2662 | const struct cred *cred = current_cred(); |
2682 | struct common_audit_data ad; | ||
2683 | struct selinux_audit_data sad = {0,}; | ||
2684 | u32 perms; | 2663 | u32 perms; |
2685 | bool from_access; | 2664 | bool from_access; |
2686 | unsigned flags = mask & MAY_NOT_BLOCK; | 2665 | unsigned flags = mask & MAY_NOT_BLOCK; |
2666 | struct inode_security_struct *isec; | ||
2667 | u32 sid; | ||
2668 | struct av_decision avd; | ||
2669 | int rc, rc2; | ||
2670 | u32 audited, denied; | ||
2687 | 2671 | ||
2688 | from_access = mask & MAY_ACCESS; | 2672 | from_access = mask & MAY_ACCESS; |
2689 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); | 2673 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
@@ -2692,22 +2676,34 @@ static int selinux_inode_permission(struct inode *inode, int mask) | |||
2692 | if (!mask) | 2676 | if (!mask) |
2693 | return 0; | 2677 | return 0; |
2694 | 2678 | ||
2695 | COMMON_AUDIT_DATA_INIT(&ad, INODE); | 2679 | validate_creds(cred); |
2696 | ad.selinux_audit_data = &sad; | ||
2697 | ad.u.inode = inode; | ||
2698 | 2680 | ||
2699 | if (from_access) | 2681 | if (unlikely(IS_PRIVATE(inode))) |
2700 | ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS; | 2682 | return 0; |
2701 | 2683 | ||
2702 | perms = file_mask_to_av(inode->i_mode, mask); | 2684 | perms = file_mask_to_av(inode->i_mode, mask); |
2703 | 2685 | ||
2704 | return inode_has_perm(cred, inode, perms, &ad, flags); | 2686 | sid = cred_sid(cred); |
2687 | isec = inode->i_security; | ||
2688 | |||
2689 | rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd); | ||
2690 | audited = avc_audit_required(perms, &avd, rc, | ||
2691 | from_access ? FILE__AUDIT_ACCESS : 0, | ||
2692 | &denied); | ||
2693 | if (likely(!audited)) | ||
2694 | return rc; | ||
2695 | |||
2696 | rc2 = audit_inode_permission(inode, perms, audited, denied, flags); | ||
2697 | if (rc2) | ||
2698 | return rc2; | ||
2699 | return rc; | ||
2705 | } | 2700 | } |
2706 | 2701 | ||
2707 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2702 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
2708 | { | 2703 | { |
2709 | const struct cred *cred = current_cred(); | 2704 | const struct cred *cred = current_cred(); |
2710 | unsigned int ia_valid = iattr->ia_valid; | 2705 | unsigned int ia_valid = iattr->ia_valid; |
2706 | __u32 av = FILE__WRITE; | ||
2711 | 2707 | ||
2712 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ | 2708 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ |
2713 | if (ia_valid & ATTR_FORCE) { | 2709 | if (ia_valid & ATTR_FORCE) { |
@@ -2721,7 +2717,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | |||
2721 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) | 2717 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) |
2722 | return dentry_has_perm(cred, dentry, FILE__SETATTR); | 2718 | return dentry_has_perm(cred, dentry, FILE__SETATTR); |
2723 | 2719 | ||
2724 | return dentry_has_perm(cred, dentry, FILE__WRITE); | 2720 | if (ia_valid & ATTR_SIZE) |
2721 | av |= FILE__OPEN; | ||
2722 | |||
2723 | return dentry_has_perm(cred, dentry, av); | ||
2725 | } | 2724 | } |
2726 | 2725 | ||
2727 | static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | 2726 | static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
@@ -2763,7 +2762,6 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2763 | struct inode_security_struct *isec = inode->i_security; | 2762 | struct inode_security_struct *isec = inode->i_security; |
2764 | struct superblock_security_struct *sbsec; | 2763 | struct superblock_security_struct *sbsec; |
2765 | struct common_audit_data ad; | 2764 | struct common_audit_data ad; |
2766 | struct selinux_audit_data sad = {0,}; | ||
2767 | u32 newsid, sid = current_sid(); | 2765 | u32 newsid, sid = current_sid(); |
2768 | int rc = 0; | 2766 | int rc = 0; |
2769 | 2767 | ||
@@ -2777,8 +2775,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2777 | if (!inode_owner_or_capable(inode)) | 2775 | if (!inode_owner_or_capable(inode)) |
2778 | return -EPERM; | 2776 | return -EPERM; |
2779 | 2777 | ||
2780 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); | 2778 | ad.type = LSM_AUDIT_DATA_DENTRY; |
2781 | ad.selinux_audit_data = &sad; | ||
2782 | ad.u.dentry = dentry; | 2779 | ad.u.dentry = dentry; |
2783 | 2780 | ||
2784 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 2781 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
@@ -2788,8 +2785,25 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2788 | 2785 | ||
2789 | rc = security_context_to_sid(value, size, &newsid); | 2786 | rc = security_context_to_sid(value, size, &newsid); |
2790 | if (rc == -EINVAL) { | 2787 | if (rc == -EINVAL) { |
2791 | if (!capable(CAP_MAC_ADMIN)) | 2788 | if (!capable(CAP_MAC_ADMIN)) { |
2789 | struct audit_buffer *ab; | ||
2790 | size_t audit_size; | ||
2791 | const char *str; | ||
2792 | |||
2793 | /* We strip a nul only if it is at the end, otherwise the | ||
2794 | * context contains a nul and we should audit that */ | ||
2795 | str = value; | ||
2796 | if (str[size - 1] == '\0') | ||
2797 | audit_size = size - 1; | ||
2798 | else | ||
2799 | audit_size = size; | ||
2800 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR); | ||
2801 | audit_log_format(ab, "op=setxattr invalid_context="); | ||
2802 | audit_log_n_untrustedstring(ab, value, audit_size); | ||
2803 | audit_log_end(ab); | ||
2804 | |||
2792 | return rc; | 2805 | return rc; |
2806 | } | ||
2793 | rc = security_context_to_sid_force(value, size, &newsid); | 2807 | rc = security_context_to_sid_force(value, size, &newsid); |
2794 | } | 2808 | } |
2795 | if (rc) | 2809 | if (rc) |
@@ -2969,7 +2983,7 @@ static int selinux_file_permission(struct file *file, int mask) | |||
2969 | 2983 | ||
2970 | if (sid == fsec->sid && fsec->isid == isec->sid && | 2984 | if (sid == fsec->sid && fsec->isid == isec->sid && |
2971 | fsec->pseqno == avc_policy_seqno()) | 2985 | fsec->pseqno == avc_policy_seqno()) |
2972 | /* No change since dentry_open check. */ | 2986 | /* No change since file_open check. */ |
2973 | return 0; | 2987 | return 0; |
2974 | 2988 | ||
2975 | return selinux_revalidate_file_permission(file, mask); | 2989 | return selinux_revalidate_file_permission(file, mask); |
@@ -3069,9 +3083,7 @@ error: | |||
3069 | return rc; | 3083 | return rc; |
3070 | } | 3084 | } |
3071 | 3085 | ||
3072 | static int selinux_file_mmap(struct file *file, unsigned long reqprot, | 3086 | static int selinux_mmap_addr(unsigned long addr) |
3073 | unsigned long prot, unsigned long flags, | ||
3074 | unsigned long addr, unsigned long addr_only) | ||
3075 | { | 3087 | { |
3076 | int rc = 0; | 3088 | int rc = 0; |
3077 | u32 sid = current_sid(); | 3089 | u32 sid = current_sid(); |
@@ -3090,10 +3102,12 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot, | |||
3090 | } | 3102 | } |
3091 | 3103 | ||
3092 | /* do DAC check on address space usage */ | 3104 | /* do DAC check on address space usage */ |
3093 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | 3105 | return cap_mmap_addr(addr); |
3094 | if (rc || addr_only) | 3106 | } |
3095 | return rc; | ||
3096 | 3107 | ||
3108 | static int selinux_mmap_file(struct file *file, unsigned long reqprot, | ||
3109 | unsigned long prot, unsigned long flags) | ||
3110 | { | ||
3097 | if (selinux_checkreqprot) | 3111 | if (selinux_checkreqprot) |
3098 | prot = reqprot; | 3112 | prot = reqprot; |
3099 | 3113 | ||
@@ -3228,15 +3242,13 @@ static int selinux_file_receive(struct file *file) | |||
3228 | return file_has_perm(cred, file, file_to_av(file)); | 3242 | return file_has_perm(cred, file, file_to_av(file)); |
3229 | } | 3243 | } |
3230 | 3244 | ||
3231 | static int selinux_dentry_open(struct file *file, const struct cred *cred) | 3245 | static int selinux_file_open(struct file *file, const struct cred *cred) |
3232 | { | 3246 | { |
3233 | struct file_security_struct *fsec; | 3247 | struct file_security_struct *fsec; |
3234 | struct inode *inode; | ||
3235 | struct inode_security_struct *isec; | 3248 | struct inode_security_struct *isec; |
3236 | 3249 | ||
3237 | inode = file->f_path.dentry->d_inode; | ||
3238 | fsec = file->f_security; | 3250 | fsec = file->f_security; |
3239 | isec = inode->i_security; | 3251 | isec = file->f_path.dentry->d_inode->i_security; |
3240 | /* | 3252 | /* |
3241 | * Save inode label and policy sequence number | 3253 | * Save inode label and policy sequence number |
3242 | * at open-time so that selinux_file_permission | 3254 | * at open-time so that selinux_file_permission |
@@ -3254,7 +3266,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred) | |||
3254 | * new inode label or new policy. | 3266 | * new inode label or new policy. |
3255 | * This check is not redundant - do not remove. | 3267 | * This check is not redundant - do not remove. |
3256 | */ | 3268 | */ |
3257 | return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0); | 3269 | return path_has_perm(cred, &file->f_path, open_file_to_av(file)); |
3258 | } | 3270 | } |
3259 | 3271 | ||
3260 | /* task security operations */ | 3272 | /* task security operations */ |
@@ -3373,12 +3385,10 @@ static int selinux_kernel_module_request(char *kmod_name) | |||
3373 | { | 3385 | { |
3374 | u32 sid; | 3386 | u32 sid; |
3375 | struct common_audit_data ad; | 3387 | struct common_audit_data ad; |
3376 | struct selinux_audit_data sad = {0,}; | ||
3377 | 3388 | ||
3378 | sid = task_sid(current); | 3389 | sid = task_sid(current); |
3379 | 3390 | ||
3380 | COMMON_AUDIT_DATA_INIT(&ad, KMOD); | 3391 | ad.type = LSM_AUDIT_DATA_KMOD; |
3381 | ad.selinux_audit_data = &sad; | ||
3382 | ad.u.kmod_name = kmod_name; | 3392 | ad.u.kmod_name = kmod_name; |
3383 | 3393 | ||
3384 | return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, | 3394 | return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, |
@@ -3751,15 +3761,13 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) | |||
3751 | { | 3761 | { |
3752 | struct sk_security_struct *sksec = sk->sk_security; | 3762 | struct sk_security_struct *sksec = sk->sk_security; |
3753 | struct common_audit_data ad; | 3763 | struct common_audit_data ad; |
3754 | struct selinux_audit_data sad = {0,}; | ||
3755 | struct lsm_network_audit net = {0,}; | 3764 | struct lsm_network_audit net = {0,}; |
3756 | u32 tsid = task_sid(task); | 3765 | u32 tsid = task_sid(task); |
3757 | 3766 | ||
3758 | if (sksec->sid == SECINITSID_KERNEL) | 3767 | if (sksec->sid == SECINITSID_KERNEL) |
3759 | return 0; | 3768 | return 0; |
3760 | 3769 | ||
3761 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3770 | ad.type = LSM_AUDIT_DATA_NET; |
3762 | ad.selinux_audit_data = &sad; | ||
3763 | ad.u.net = &net; | 3771 | ad.u.net = &net; |
3764 | ad.u.net->sk = sk; | 3772 | ad.u.net->sk = sk; |
3765 | 3773 | ||
@@ -3839,7 +3847,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3839 | char *addrp; | 3847 | char *addrp; |
3840 | struct sk_security_struct *sksec = sk->sk_security; | 3848 | struct sk_security_struct *sksec = sk->sk_security; |
3841 | struct common_audit_data ad; | 3849 | struct common_audit_data ad; |
3842 | struct selinux_audit_data sad = {0,}; | ||
3843 | struct lsm_network_audit net = {0,}; | 3850 | struct lsm_network_audit net = {0,}; |
3844 | struct sockaddr_in *addr4 = NULL; | 3851 | struct sockaddr_in *addr4 = NULL; |
3845 | struct sockaddr_in6 *addr6 = NULL; | 3852 | struct sockaddr_in6 *addr6 = NULL; |
@@ -3866,8 +3873,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3866 | snum, &sid); | 3873 | snum, &sid); |
3867 | if (err) | 3874 | if (err) |
3868 | goto out; | 3875 | goto out; |
3869 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3876 | ad.type = LSM_AUDIT_DATA_NET; |
3870 | ad.selinux_audit_data = &sad; | ||
3871 | ad.u.net = &net; | 3877 | ad.u.net = &net; |
3872 | ad.u.net->sport = htons(snum); | 3878 | ad.u.net->sport = htons(snum); |
3873 | ad.u.net->family = family; | 3879 | ad.u.net->family = family; |
@@ -3901,8 +3907,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3901 | if (err) | 3907 | if (err) |
3902 | goto out; | 3908 | goto out; |
3903 | 3909 | ||
3904 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3910 | ad.type = LSM_AUDIT_DATA_NET; |
3905 | ad.selinux_audit_data = &sad; | ||
3906 | ad.u.net = &net; | 3911 | ad.u.net = &net; |
3907 | ad.u.net->sport = htons(snum); | 3912 | ad.u.net->sport = htons(snum); |
3908 | ad.u.net->family = family; | 3913 | ad.u.net->family = family; |
@@ -3937,7 +3942,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3937 | if (sksec->sclass == SECCLASS_TCP_SOCKET || | 3942 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
3938 | sksec->sclass == SECCLASS_DCCP_SOCKET) { | 3943 | sksec->sclass == SECCLASS_DCCP_SOCKET) { |
3939 | struct common_audit_data ad; | 3944 | struct common_audit_data ad; |
3940 | struct selinux_audit_data sad = {0,}; | ||
3941 | struct lsm_network_audit net = {0,}; | 3945 | struct lsm_network_audit net = {0,}; |
3942 | struct sockaddr_in *addr4 = NULL; | 3946 | struct sockaddr_in *addr4 = NULL; |
3943 | struct sockaddr_in6 *addr6 = NULL; | 3947 | struct sockaddr_in6 *addr6 = NULL; |
@@ -3963,8 +3967,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3963 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? | 3967 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? |
3964 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3968 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3965 | 3969 | ||
3966 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 3970 | ad.type = LSM_AUDIT_DATA_NET; |
3967 | ad.selinux_audit_data = &sad; | ||
3968 | ad.u.net = &net; | 3971 | ad.u.net = &net; |
3969 | ad.u.net->dport = htons(snum); | 3972 | ad.u.net->dport = htons(snum); |
3970 | ad.u.net->family = sk->sk_family; | 3973 | ad.u.net->family = sk->sk_family; |
@@ -4056,12 +4059,10 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, | |||
4056 | struct sk_security_struct *sksec_other = other->sk_security; | 4059 | struct sk_security_struct *sksec_other = other->sk_security; |
4057 | struct sk_security_struct *sksec_new = newsk->sk_security; | 4060 | struct sk_security_struct *sksec_new = newsk->sk_security; |
4058 | struct common_audit_data ad; | 4061 | struct common_audit_data ad; |
4059 | struct selinux_audit_data sad = {0,}; | ||
4060 | struct lsm_network_audit net = {0,}; | 4062 | struct lsm_network_audit net = {0,}; |
4061 | int err; | 4063 | int err; |
4062 | 4064 | ||
4063 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4065 | ad.type = LSM_AUDIT_DATA_NET; |
4064 | ad.selinux_audit_data = &sad; | ||
4065 | ad.u.net = &net; | 4066 | ad.u.net = &net; |
4066 | ad.u.net->sk = other; | 4067 | ad.u.net->sk = other; |
4067 | 4068 | ||
@@ -4090,11 +4091,9 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
4090 | struct sk_security_struct *ssec = sock->sk->sk_security; | 4091 | struct sk_security_struct *ssec = sock->sk->sk_security; |
4091 | struct sk_security_struct *osec = other->sk->sk_security; | 4092 | struct sk_security_struct *osec = other->sk->sk_security; |
4092 | struct common_audit_data ad; | 4093 | struct common_audit_data ad; |
4093 | struct selinux_audit_data sad = {0,}; | ||
4094 | struct lsm_network_audit net = {0,}; | 4094 | struct lsm_network_audit net = {0,}; |
4095 | 4095 | ||
4096 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4096 | ad.type = LSM_AUDIT_DATA_NET; |
4097 | ad.selinux_audit_data = &sad; | ||
4098 | ad.u.net = &net; | 4097 | ad.u.net = &net; |
4099 | ad.u.net->sk = other->sk; | 4098 | ad.u.net->sk = other->sk; |
4100 | 4099 | ||
@@ -4132,12 +4131,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4132 | struct sk_security_struct *sksec = sk->sk_security; | 4131 | struct sk_security_struct *sksec = sk->sk_security; |
4133 | u32 sk_sid = sksec->sid; | 4132 | u32 sk_sid = sksec->sid; |
4134 | struct common_audit_data ad; | 4133 | struct common_audit_data ad; |
4135 | struct selinux_audit_data sad = {0,}; | ||
4136 | struct lsm_network_audit net = {0,}; | 4134 | struct lsm_network_audit net = {0,}; |
4137 | char *addrp; | 4135 | char *addrp; |
4138 | 4136 | ||
4139 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4137 | ad.type = LSM_AUDIT_DATA_NET; |
4140 | ad.selinux_audit_data = &sad; | ||
4141 | ad.u.net = &net; | 4138 | ad.u.net = &net; |
4142 | ad.u.net->netif = skb->skb_iif; | 4139 | ad.u.net->netif = skb->skb_iif; |
4143 | ad.u.net->family = family; | 4140 | ad.u.net->family = family; |
@@ -4167,7 +4164,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4167 | u16 family = sk->sk_family; | 4164 | u16 family = sk->sk_family; |
4168 | u32 sk_sid = sksec->sid; | 4165 | u32 sk_sid = sksec->sid; |
4169 | struct common_audit_data ad; | 4166 | struct common_audit_data ad; |
4170 | struct selinux_audit_data sad = {0,}; | ||
4171 | struct lsm_network_audit net = {0,}; | 4167 | struct lsm_network_audit net = {0,}; |
4172 | char *addrp; | 4168 | char *addrp; |
4173 | u8 secmark_active; | 4169 | u8 secmark_active; |
@@ -4192,8 +4188,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4192 | if (!secmark_active && !peerlbl_active) | 4188 | if (!secmark_active && !peerlbl_active) |
4193 | return 0; | 4189 | return 0; |
4194 | 4190 | ||
4195 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4191 | ad.type = LSM_AUDIT_DATA_NET; |
4196 | ad.selinux_audit_data = &sad; | ||
4197 | ad.u.net = &net; | 4192 | ad.u.net = &net; |
4198 | ad.u.net->netif = skb->skb_iif; | 4193 | ad.u.net->netif = skb->skb_iif; |
4199 | ad.u.net->family = family; | 4194 | ad.u.net->family = family; |
@@ -4531,7 +4526,6 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4531 | char *addrp; | 4526 | char *addrp; |
4532 | u32 peer_sid; | 4527 | u32 peer_sid; |
4533 | struct common_audit_data ad; | 4528 | struct common_audit_data ad; |
4534 | struct selinux_audit_data sad = {0,}; | ||
4535 | struct lsm_network_audit net = {0,}; | 4529 | struct lsm_network_audit net = {0,}; |
4536 | u8 secmark_active; | 4530 | u8 secmark_active; |
4537 | u8 netlbl_active; | 4531 | u8 netlbl_active; |
@@ -4549,8 +4543,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4549 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | 4543 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) |
4550 | return NF_DROP; | 4544 | return NF_DROP; |
4551 | 4545 | ||
4552 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4546 | ad.type = LSM_AUDIT_DATA_NET; |
4553 | ad.selinux_audit_data = &sad; | ||
4554 | ad.u.net = &net; | 4547 | ad.u.net = &net; |
4555 | ad.u.net->netif = ifindex; | 4548 | ad.u.net->netif = ifindex; |
4556 | ad.u.net->family = family; | 4549 | ad.u.net->family = family; |
@@ -4640,7 +4633,6 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4640 | struct sock *sk = skb->sk; | 4633 | struct sock *sk = skb->sk; |
4641 | struct sk_security_struct *sksec; | 4634 | struct sk_security_struct *sksec; |
4642 | struct common_audit_data ad; | 4635 | struct common_audit_data ad; |
4643 | struct selinux_audit_data sad = {0,}; | ||
4644 | struct lsm_network_audit net = {0,}; | 4636 | struct lsm_network_audit net = {0,}; |
4645 | char *addrp; | 4637 | char *addrp; |
4646 | u8 proto; | 4638 | u8 proto; |
@@ -4649,8 +4641,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4649 | return NF_ACCEPT; | 4641 | return NF_ACCEPT; |
4650 | sksec = sk->sk_security; | 4642 | sksec = sk->sk_security; |
4651 | 4643 | ||
4652 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4644 | ad.type = LSM_AUDIT_DATA_NET; |
4653 | ad.selinux_audit_data = &sad; | ||
4654 | ad.u.net = &net; | 4645 | ad.u.net = &net; |
4655 | ad.u.net->netif = ifindex; | 4646 | ad.u.net->netif = ifindex; |
4656 | ad.u.net->family = family; | 4647 | ad.u.net->family = family; |
@@ -4675,7 +4666,6 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4675 | u32 peer_sid; | 4666 | u32 peer_sid; |
4676 | struct sock *sk; | 4667 | struct sock *sk; |
4677 | struct common_audit_data ad; | 4668 | struct common_audit_data ad; |
4678 | struct selinux_audit_data sad = {0,}; | ||
4679 | struct lsm_network_audit net = {0,}; | 4669 | struct lsm_network_audit net = {0,}; |
4680 | char *addrp; | 4670 | char *addrp; |
4681 | u8 secmark_active; | 4671 | u8 secmark_active; |
@@ -4722,8 +4712,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4722 | secmark_perm = PACKET__SEND; | 4712 | secmark_perm = PACKET__SEND; |
4723 | } | 4713 | } |
4724 | 4714 | ||
4725 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4715 | ad.type = LSM_AUDIT_DATA_NET; |
4726 | ad.selinux_audit_data = &sad; | ||
4727 | ad.u.net = &net; | 4716 | ad.u.net = &net; |
4728 | ad.u.net->netif = ifindex; | 4717 | ad.u.net->netif = ifindex; |
4729 | ad.u.net->family = family; | 4718 | ad.u.net->family = family; |
@@ -4841,13 +4830,11 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | |||
4841 | { | 4830 | { |
4842 | struct ipc_security_struct *isec; | 4831 | struct ipc_security_struct *isec; |
4843 | struct common_audit_data ad; | 4832 | struct common_audit_data ad; |
4844 | struct selinux_audit_data sad = {0,}; | ||
4845 | u32 sid = current_sid(); | 4833 | u32 sid = current_sid(); |
4846 | 4834 | ||
4847 | isec = ipc_perms->security; | 4835 | isec = ipc_perms->security; |
4848 | 4836 | ||
4849 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4837 | ad.type = LSM_AUDIT_DATA_IPC; |
4850 | ad.selinux_audit_data = &sad; | ||
4851 | ad.u.ipc_id = ipc_perms->key; | 4838 | ad.u.ipc_id = ipc_perms->key; |
4852 | 4839 | ||
4853 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 4840 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
@@ -4868,7 +4855,6 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
4868 | { | 4855 | { |
4869 | struct ipc_security_struct *isec; | 4856 | struct ipc_security_struct *isec; |
4870 | struct common_audit_data ad; | 4857 | struct common_audit_data ad; |
4871 | struct selinux_audit_data sad = {0,}; | ||
4872 | u32 sid = current_sid(); | 4858 | u32 sid = current_sid(); |
4873 | int rc; | 4859 | int rc; |
4874 | 4860 | ||
@@ -4878,8 +4864,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
4878 | 4864 | ||
4879 | isec = msq->q_perm.security; | 4865 | isec = msq->q_perm.security; |
4880 | 4866 | ||
4881 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4867 | ad.type = LSM_AUDIT_DATA_IPC; |
4882 | ad.selinux_audit_data = &sad; | ||
4883 | ad.u.ipc_id = msq->q_perm.key; | 4868 | ad.u.ipc_id = msq->q_perm.key; |
4884 | 4869 | ||
4885 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4870 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4900,13 +4885,11 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) | |||
4900 | { | 4885 | { |
4901 | struct ipc_security_struct *isec; | 4886 | struct ipc_security_struct *isec; |
4902 | struct common_audit_data ad; | 4887 | struct common_audit_data ad; |
4903 | struct selinux_audit_data sad = {0,}; | ||
4904 | u32 sid = current_sid(); | 4888 | u32 sid = current_sid(); |
4905 | 4889 | ||
4906 | isec = msq->q_perm.security; | 4890 | isec = msq->q_perm.security; |
4907 | 4891 | ||
4908 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4892 | ad.type = LSM_AUDIT_DATA_IPC; |
4909 | ad.selinux_audit_data = &sad; | ||
4910 | ad.u.ipc_id = msq->q_perm.key; | 4893 | ad.u.ipc_id = msq->q_perm.key; |
4911 | 4894 | ||
4912 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4895 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4946,7 +4929,6 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4946 | struct ipc_security_struct *isec; | 4929 | struct ipc_security_struct *isec; |
4947 | struct msg_security_struct *msec; | 4930 | struct msg_security_struct *msec; |
4948 | struct common_audit_data ad; | 4931 | struct common_audit_data ad; |
4949 | struct selinux_audit_data sad = {0,}; | ||
4950 | u32 sid = current_sid(); | 4932 | u32 sid = current_sid(); |
4951 | int rc; | 4933 | int rc; |
4952 | 4934 | ||
@@ -4967,8 +4949,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4967 | return rc; | 4949 | return rc; |
4968 | } | 4950 | } |
4969 | 4951 | ||
4970 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4952 | ad.type = LSM_AUDIT_DATA_IPC; |
4971 | ad.selinux_audit_data = &sad; | ||
4972 | ad.u.ipc_id = msq->q_perm.key; | 4953 | ad.u.ipc_id = msq->q_perm.key; |
4973 | 4954 | ||
4974 | /* Can this process write to the queue? */ | 4955 | /* Can this process write to the queue? */ |
@@ -4993,15 +4974,13 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4993 | struct ipc_security_struct *isec; | 4974 | struct ipc_security_struct *isec; |
4994 | struct msg_security_struct *msec; | 4975 | struct msg_security_struct *msec; |
4995 | struct common_audit_data ad; | 4976 | struct common_audit_data ad; |
4996 | struct selinux_audit_data sad = {0,}; | ||
4997 | u32 sid = task_sid(target); | 4977 | u32 sid = task_sid(target); |
4998 | int rc; | 4978 | int rc; |
4999 | 4979 | ||
5000 | isec = msq->q_perm.security; | 4980 | isec = msq->q_perm.security; |
5001 | msec = msg->security; | 4981 | msec = msg->security; |
5002 | 4982 | ||
5003 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 4983 | ad.type = LSM_AUDIT_DATA_IPC; |
5004 | ad.selinux_audit_data = &sad; | ||
5005 | ad.u.ipc_id = msq->q_perm.key; | 4984 | ad.u.ipc_id = msq->q_perm.key; |
5006 | 4985 | ||
5007 | rc = avc_has_perm(sid, isec->sid, | 4986 | rc = avc_has_perm(sid, isec->sid, |
@@ -5017,7 +4996,6 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
5017 | { | 4996 | { |
5018 | struct ipc_security_struct *isec; | 4997 | struct ipc_security_struct *isec; |
5019 | struct common_audit_data ad; | 4998 | struct common_audit_data ad; |
5020 | struct selinux_audit_data sad = {0,}; | ||
5021 | u32 sid = current_sid(); | 4999 | u32 sid = current_sid(); |
5022 | int rc; | 5000 | int rc; |
5023 | 5001 | ||
@@ -5027,8 +5005,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
5027 | 5005 | ||
5028 | isec = shp->shm_perm.security; | 5006 | isec = shp->shm_perm.security; |
5029 | 5007 | ||
5030 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 5008 | ad.type = LSM_AUDIT_DATA_IPC; |
5031 | ad.selinux_audit_data = &sad; | ||
5032 | ad.u.ipc_id = shp->shm_perm.key; | 5009 | ad.u.ipc_id = shp->shm_perm.key; |
5033 | 5010 | ||
5034 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 5011 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -5049,13 +5026,11 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) | |||
5049 | { | 5026 | { |
5050 | struct ipc_security_struct *isec; | 5027 | struct ipc_security_struct *isec; |
5051 | struct common_audit_data ad; | 5028 | struct common_audit_data ad; |
5052 | struct selinux_audit_data sad = {0,}; | ||
5053 | u32 sid = current_sid(); | 5029 | u32 sid = current_sid(); |
5054 | 5030 | ||
5055 | isec = shp->shm_perm.security; | 5031 | isec = shp->shm_perm.security; |
5056 | 5032 | ||
5057 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 5033 | ad.type = LSM_AUDIT_DATA_IPC; |
5058 | ad.selinux_audit_data = &sad; | ||
5059 | ad.u.ipc_id = shp->shm_perm.key; | 5034 | ad.u.ipc_id = shp->shm_perm.key; |
5060 | 5035 | ||
5061 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 5036 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -5113,7 +5088,6 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
5113 | { | 5088 | { |
5114 | struct ipc_security_struct *isec; | 5089 | struct ipc_security_struct *isec; |
5115 | struct common_audit_data ad; | 5090 | struct common_audit_data ad; |
5116 | struct selinux_audit_data sad = {0,}; | ||
5117 | u32 sid = current_sid(); | 5091 | u32 sid = current_sid(); |
5118 | int rc; | 5092 | int rc; |
5119 | 5093 | ||
@@ -5123,8 +5097,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
5123 | 5097 | ||
5124 | isec = sma->sem_perm.security; | 5098 | isec = sma->sem_perm.security; |
5125 | 5099 | ||
5126 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 5100 | ad.type = LSM_AUDIT_DATA_IPC; |
5127 | ad.selinux_audit_data = &sad; | ||
5128 | ad.u.ipc_id = sma->sem_perm.key; | 5101 | ad.u.ipc_id = sma->sem_perm.key; |
5129 | 5102 | ||
5130 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5103 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -5145,13 +5118,11 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg) | |||
5145 | { | 5118 | { |
5146 | struct ipc_security_struct *isec; | 5119 | struct ipc_security_struct *isec; |
5147 | struct common_audit_data ad; | 5120 | struct common_audit_data ad; |
5148 | struct selinux_audit_data sad = {0,}; | ||
5149 | u32 sid = current_sid(); | 5121 | u32 sid = current_sid(); |
5150 | 5122 | ||
5151 | isec = sma->sem_perm.security; | 5123 | isec = sma->sem_perm.security; |
5152 | 5124 | ||
5153 | COMMON_AUDIT_DATA_INIT(&ad, IPC); | 5125 | ad.type = LSM_AUDIT_DATA_IPC; |
5154 | ad.selinux_audit_data = &sad; | ||
5155 | ad.u.ipc_id = sma->sem_perm.key; | 5126 | ad.u.ipc_id = sma->sem_perm.key; |
5156 | 5127 | ||
5157 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5128 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -5331,8 +5302,23 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5331 | } | 5302 | } |
5332 | error = security_context_to_sid(value, size, &sid); | 5303 | error = security_context_to_sid(value, size, &sid); |
5333 | if (error == -EINVAL && !strcmp(name, "fscreate")) { | 5304 | if (error == -EINVAL && !strcmp(name, "fscreate")) { |
5334 | if (!capable(CAP_MAC_ADMIN)) | 5305 | if (!capable(CAP_MAC_ADMIN)) { |
5306 | struct audit_buffer *ab; | ||
5307 | size_t audit_size; | ||
5308 | |||
5309 | /* We strip a nul only if it is at the end, otherwise the | ||
5310 | * context contains a nul and we should audit that */ | ||
5311 | if (str[size - 1] == '\0') | ||
5312 | audit_size = size - 1; | ||
5313 | else | ||
5314 | audit_size = size; | ||
5315 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR); | ||
5316 | audit_log_format(ab, "op=fscreate invalid_context="); | ||
5317 | audit_log_n_untrustedstring(ab, value, audit_size); | ||
5318 | audit_log_end(ab); | ||
5319 | |||
5335 | return error; | 5320 | return error; |
5321 | } | ||
5336 | error = security_context_to_sid_force(value, size, | 5322 | error = security_context_to_sid_force(value, size, |
5337 | &sid); | 5323 | &sid); |
5338 | } | 5324 | } |
@@ -5584,7 +5570,8 @@ static struct security_operations selinux_ops = { | |||
5584 | .file_alloc_security = selinux_file_alloc_security, | 5570 | .file_alloc_security = selinux_file_alloc_security, |
5585 | .file_free_security = selinux_file_free_security, | 5571 | .file_free_security = selinux_file_free_security, |
5586 | .file_ioctl = selinux_file_ioctl, | 5572 | .file_ioctl = selinux_file_ioctl, |
5587 | .file_mmap = selinux_file_mmap, | 5573 | .mmap_file = selinux_mmap_file, |
5574 | .mmap_addr = selinux_mmap_addr, | ||
5588 | .file_mprotect = selinux_file_mprotect, | 5575 | .file_mprotect = selinux_file_mprotect, |
5589 | .file_lock = selinux_file_lock, | 5576 | .file_lock = selinux_file_lock, |
5590 | .file_fcntl = selinux_file_fcntl, | 5577 | .file_fcntl = selinux_file_fcntl, |
@@ -5592,7 +5579,7 @@ static struct security_operations selinux_ops = { | |||
5592 | .file_send_sigiotask = selinux_file_send_sigiotask, | 5579 | .file_send_sigiotask = selinux_file_send_sigiotask, |
5593 | .file_receive = selinux_file_receive, | 5580 | .file_receive = selinux_file_receive, |
5594 | 5581 | ||
5595 | .dentry_open = selinux_dentry_open, | 5582 | .file_open = selinux_file_open, |
5596 | 5583 | ||
5597 | .task_create = selinux_task_create, | 5584 | .task_create = selinux_task_create, |
5598 | .cred_alloc_blank = selinux_cred_alloc_blank, | 5585 | .cred_alloc_blank = selinux_cred_alloc_blank, |
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 1931370233d7..92d0ab561db8 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h | |||
@@ -49,7 +49,7 @@ struct avc_cache_stats { | |||
49 | /* | 49 | /* |
50 | * We only need this data after we have decided to send an audit message. | 50 | * We only need this data after we have decided to send an audit message. |
51 | */ | 51 | */ |
52 | struct selinux_late_audit_data { | 52 | struct selinux_audit_data { |
53 | u32 ssid; | 53 | u32 ssid; |
54 | u32 tsid; | 54 | u32 tsid; |
55 | u16 tclass; | 55 | u16 tclass; |
@@ -60,28 +60,86 @@ struct selinux_late_audit_data { | |||
60 | }; | 60 | }; |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * We collect this at the beginning or during an selinux security operation | ||
64 | */ | ||
65 | struct selinux_audit_data { | ||
66 | /* | ||
67 | * auditdeny is a bit tricky and unintuitive. See the | ||
68 | * comments in avc.c for it's meaning and usage. | ||
69 | */ | ||
70 | u32 auditdeny; | ||
71 | struct selinux_late_audit_data *slad; | ||
72 | }; | ||
73 | |||
74 | /* | ||
75 | * AVC operations | 63 | * AVC operations |
76 | */ | 64 | */ |
77 | 65 | ||
78 | void __init avc_init(void); | 66 | void __init avc_init(void); |
79 | 67 | ||
80 | int avc_audit(u32 ssid, u32 tsid, | 68 | static inline u32 avc_audit_required(u32 requested, |
81 | u16 tclass, u32 requested, | 69 | struct av_decision *avd, |
82 | struct av_decision *avd, | 70 | int result, |
83 | int result, | 71 | u32 auditdeny, |
84 | struct common_audit_data *a, unsigned flags); | 72 | u32 *deniedp) |
73 | { | ||
74 | u32 denied, audited; | ||
75 | denied = requested & ~avd->allowed; | ||
76 | if (unlikely(denied)) { | ||
77 | audited = denied & avd->auditdeny; | ||
78 | /* | ||
79 | * auditdeny is TRICKY! Setting a bit in | ||
80 | * this field means that ANY denials should NOT be audited if | ||
81 | * the policy contains an explicit dontaudit rule for that | ||
82 | * permission. Take notice that this is unrelated to the | ||
83 | * actual permissions that were denied. As an example lets | ||
84 | * assume: | ||
85 | * | ||
86 | * denied == READ | ||
87 | * avd.auditdeny & ACCESS == 0 (not set means explicit rule) | ||
88 | * auditdeny & ACCESS == 1 | ||
89 | * | ||
90 | * We will NOT audit the denial even though the denied | ||
91 | * permission was READ and the auditdeny checks were for | ||
92 | * ACCESS | ||
93 | */ | ||
94 | if (auditdeny && !(auditdeny & avd->auditdeny)) | ||
95 | audited = 0; | ||
96 | } else if (result) | ||
97 | audited = denied = requested; | ||
98 | else | ||
99 | audited = requested & avd->auditallow; | ||
100 | *deniedp = denied; | ||
101 | return audited; | ||
102 | } | ||
103 | |||
104 | int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, | ||
105 | u32 requested, u32 audited, u32 denied, | ||
106 | struct common_audit_data *a, | ||
107 | unsigned flags); | ||
108 | |||
109 | /** | ||
110 | * avc_audit - Audit the granting or denial of permissions. | ||
111 | * @ssid: source security identifier | ||
112 | * @tsid: target security identifier | ||
113 | * @tclass: target security class | ||
114 | * @requested: requested permissions | ||
115 | * @avd: access vector decisions | ||
116 | * @result: result from avc_has_perm_noaudit | ||
117 | * @a: auxiliary audit data | ||
118 | * @flags: VFS walk flags | ||
119 | * | ||
120 | * Audit the granting or denial of permissions in accordance | ||
121 | * with the policy. This function is typically called by | ||
122 | * avc_has_perm() after a permission check, but can also be | ||
123 | * called directly by callers who use avc_has_perm_noaudit() | ||
124 | * in order to separate the permission check from the auditing. | ||
125 | * For example, this separation is useful when the permission check must | ||
126 | * be performed under a lock, to allow the lock to be released | ||
127 | * before calling the auditing code. | ||
128 | */ | ||
129 | static inline int avc_audit(u32 ssid, u32 tsid, | ||
130 | u16 tclass, u32 requested, | ||
131 | struct av_decision *avd, | ||
132 | int result, | ||
133 | struct common_audit_data *a, unsigned flags) | ||
134 | { | ||
135 | u32 audited, denied; | ||
136 | audited = avc_audit_required(requested, avd, result, 0, &denied); | ||
137 | if (likely(!audited)) | ||
138 | return 0; | ||
139 | return slow_avc_audit(ssid, tsid, tclass, | ||
140 | requested, audited, denied, | ||
141 | a, flags); | ||
142 | } | ||
85 | 143 | ||
86 | #define AVC_STRICT 1 /* Ignore permissive mode. */ | 144 | #define AVC_STRICT 1 /* Ignore permissive mode. */ |
87 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 145 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, |
@@ -112,11 +170,7 @@ u32 avc_policy_seqno(void); | |||
112 | #define AVC_CALLBACK_AUDITDENY_ENABLE 64 | 170 | #define AVC_CALLBACK_AUDITDENY_ENABLE 64 |
113 | #define AVC_CALLBACK_AUDITDENY_DISABLE 128 | 171 | #define AVC_CALLBACK_AUDITDENY_DISABLE 128 |
114 | 172 | ||
115 | int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | 173 | int avc_add_callback(int (*callback)(u32 event), u32 events); |
116 | u16 tclass, u32 perms, | ||
117 | u32 *out_retained), | ||
118 | u32 events, u32 ssid, u32 tsid, | ||
119 | u16 tclass, u32 perms); | ||
120 | 174 | ||
121 | /* Exported to selinuxfs */ | 175 | /* Exported to selinuxfs */ |
122 | int avc_get_hash_stats(char *page); | 176 | int avc_get_hash_stats(char *page); |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index d871e8ad2103..dde2005407aa 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -31,13 +31,15 @@ | |||
31 | #define POLICYDB_VERSION_BOUNDARY 24 | 31 | #define POLICYDB_VERSION_BOUNDARY 24 |
32 | #define POLICYDB_VERSION_FILENAME_TRANS 25 | 32 | #define POLICYDB_VERSION_FILENAME_TRANS 25 |
33 | #define POLICYDB_VERSION_ROLETRANS 26 | 33 | #define POLICYDB_VERSION_ROLETRANS 26 |
34 | #define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27 | ||
35 | #define POLICYDB_VERSION_DEFAULT_TYPE 28 | ||
34 | 36 | ||
35 | /* Range of policy versions we understand*/ | 37 | /* Range of policy versions we understand*/ |
36 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE | 38 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
37 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX | 39 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX |
38 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE | 40 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE |
39 | #else | 41 | #else |
40 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_ROLETRANS | 42 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_DEFAULT_TYPE |
41 | #endif | 43 | #endif |
42 | 44 | ||
43 | /* Mask for just the mount related flags */ | 45 | /* Mask for just the mount related flags */ |
diff --git a/security/selinux/netif.c b/security/selinux/netif.c index 326f22cbe405..47a49d1a6f6a 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c | |||
@@ -252,8 +252,7 @@ static void sel_netif_flush(void) | |||
252 | spin_unlock_bh(&sel_netif_lock); | 252 | spin_unlock_bh(&sel_netif_lock); |
253 | } | 253 | } |
254 | 254 | ||
255 | static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid, | 255 | static int sel_netif_avc_callback(u32 event) |
256 | u16 class, u32 perms, u32 *retained) | ||
257 | { | 256 | { |
258 | if (event == AVC_CALLBACK_RESET) { | 257 | if (event == AVC_CALLBACK_RESET) { |
259 | sel_netif_flush(); | 258 | sel_netif_flush(); |
@@ -292,8 +291,7 @@ static __init int sel_netif_init(void) | |||
292 | 291 | ||
293 | register_netdevice_notifier(&sel_netif_netdev_notifier); | 292 | register_netdevice_notifier(&sel_netif_netdev_notifier); |
294 | 293 | ||
295 | err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET, | 294 | err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET); |
296 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | ||
297 | if (err) | 295 | if (err) |
298 | panic("avc_add_callback() failed, error %d\n", err); | 296 | panic("avc_add_callback() failed, error %d\n", err); |
299 | 297 | ||
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 86365857c088..28f911cdd7c7 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c | |||
@@ -297,8 +297,7 @@ static void sel_netnode_flush(void) | |||
297 | spin_unlock_bh(&sel_netnode_lock); | 297 | spin_unlock_bh(&sel_netnode_lock); |
298 | } | 298 | } |
299 | 299 | ||
300 | static int sel_netnode_avc_callback(u32 event, u32 ssid, u32 tsid, | 300 | static int sel_netnode_avc_callback(u32 event) |
301 | u16 class, u32 perms, u32 *retained) | ||
302 | { | 301 | { |
303 | if (event == AVC_CALLBACK_RESET) { | 302 | if (event == AVC_CALLBACK_RESET) { |
304 | sel_netnode_flush(); | 303 | sel_netnode_flush(); |
@@ -320,8 +319,7 @@ static __init int sel_netnode_init(void) | |||
320 | sel_netnode_hash[iter].size = 0; | 319 | sel_netnode_hash[iter].size = 0; |
321 | } | 320 | } |
322 | 321 | ||
323 | ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET, | 322 | ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET); |
324 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | ||
325 | if (ret != 0) | 323 | if (ret != 0) |
326 | panic("avc_add_callback() failed, error %d\n", ret); | 324 | panic("avc_add_callback() failed, error %d\n", ret); |
327 | 325 | ||
diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 7b9eb1faf68b..d35379781c2c 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c | |||
@@ -234,8 +234,7 @@ static void sel_netport_flush(void) | |||
234 | spin_unlock_bh(&sel_netport_lock); | 234 | spin_unlock_bh(&sel_netport_lock); |
235 | } | 235 | } |
236 | 236 | ||
237 | static int sel_netport_avc_callback(u32 event, u32 ssid, u32 tsid, | 237 | static int sel_netport_avc_callback(u32 event) |
238 | u16 class, u32 perms, u32 *retained) | ||
239 | { | 238 | { |
240 | if (event == AVC_CALLBACK_RESET) { | 239 | if (event == AVC_CALLBACK_RESET) { |
241 | sel_netport_flush(); | 240 | sel_netport_flush(); |
@@ -257,8 +256,7 @@ static __init int sel_netport_init(void) | |||
257 | sel_netport_hash[iter].size = 0; | 256 | sel_netport_hash[iter].size = 0; |
258 | } | 257 | } |
259 | 258 | ||
260 | ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET, | 259 | ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET); |
261 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | ||
262 | if (ret != 0) | 260 | if (ret != 0) |
263 | panic("avc_add_callback() failed, error %d\n", ret); | 261 | panic("avc_add_callback() failed, error %d\n", ret); |
264 | 262 | ||
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 0920ea3bf599..d309e7f472d8 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/netlink.h> | 14 | #include <linux/netlink.h> |
15 | #include <linux/rtnetlink.h> | 15 | #include <linux/rtnetlink.h> |
16 | #include <linux/if.h> | 16 | #include <linux/if.h> |
17 | #include <linux/netfilter_ipv4/ip_queue.h> | ||
18 | #include <linux/inet_diag.h> | 17 | #include <linux/inet_diag.h> |
19 | #include <linux/xfrm.h> | 18 | #include <linux/xfrm.h> |
20 | #include <linux/audit.h> | 19 | #include <linux/audit.h> |
@@ -70,12 +69,6 @@ static struct nlmsg_perm nlmsg_route_perms[] = | |||
70 | { RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, | 69 | { RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, |
71 | }; | 70 | }; |
72 | 71 | ||
73 | static struct nlmsg_perm nlmsg_firewall_perms[] = | ||
74 | { | ||
75 | { IPQM_MODE, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE }, | ||
76 | { IPQM_VERDICT, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE }, | ||
77 | }; | ||
78 | |||
79 | static struct nlmsg_perm nlmsg_tcpdiag_perms[] = | 72 | static struct nlmsg_perm nlmsg_tcpdiag_perms[] = |
80 | { | 73 | { |
81 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, | 74 | { TCPDIAG_GETSOCK, NETLINK_TCPDIAG_SOCKET__NLMSG_READ }, |
@@ -145,12 +138,6 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm) | |||
145 | sizeof(nlmsg_route_perms)); | 138 | sizeof(nlmsg_route_perms)); |
146 | break; | 139 | break; |
147 | 140 | ||
148 | case SECCLASS_NETLINK_FIREWALL_SOCKET: | ||
149 | case SECCLASS_NETLINK_IP6FW_SOCKET: | ||
150 | err = nlmsg_perm(nlmsg_type, perm, nlmsg_firewall_perms, | ||
151 | sizeof(nlmsg_firewall_perms)); | ||
152 | break; | ||
153 | |||
154 | case SECCLASS_NETLINK_TCPDIAG_SOCKET: | 141 | case SECCLASS_NETLINK_TCPDIAG_SOCKET: |
155 | err = nlmsg_perm(nlmsg_type, perm, nlmsg_tcpdiag_perms, | 142 | err = nlmsg_perm(nlmsg_type, perm, nlmsg_tcpdiag_perms, |
156 | sizeof(nlmsg_tcpdiag_perms)); | 143 | sizeof(nlmsg_tcpdiag_perms)); |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index d7018bfa1f00..3ad290251288 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -496,6 +496,7 @@ static const struct file_operations sel_policy_ops = { | |||
496 | .read = sel_read_policy, | 496 | .read = sel_read_policy, |
497 | .mmap = sel_mmap_policy, | 497 | .mmap = sel_mmap_policy, |
498 | .release = sel_release_policy, | 498 | .release = sel_release_policy, |
499 | .llseek = generic_file_llseek, | ||
499 | }; | 500 | }; |
500 | 501 | ||
501 | static ssize_t sel_write_load(struct file *file, const char __user *buf, | 502 | static ssize_t sel_write_load(struct file *file, const char __user *buf, |
@@ -1232,6 +1233,7 @@ static int sel_make_bools(void) | |||
1232 | kfree(bool_pending_names[i]); | 1233 | kfree(bool_pending_names[i]); |
1233 | kfree(bool_pending_names); | 1234 | kfree(bool_pending_names); |
1234 | kfree(bool_pending_values); | 1235 | kfree(bool_pending_values); |
1236 | bool_num = 0; | ||
1235 | bool_pending_names = NULL; | 1237 | bool_pending_names = NULL; |
1236 | bool_pending_values = NULL; | 1238 | bool_pending_values = NULL; |
1237 | 1239 | ||
@@ -1257,12 +1259,8 @@ static int sel_make_bools(void) | |||
1257 | if (!inode) | 1259 | if (!inode) |
1258 | goto out; | 1260 | goto out; |
1259 | 1261 | ||
1260 | ret = -EINVAL; | ||
1261 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); | ||
1262 | if (len < 0) | ||
1263 | goto out; | ||
1264 | |||
1265 | ret = -ENAMETOOLONG; | 1262 | ret = -ENAMETOOLONG; |
1263 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); | ||
1266 | if (len >= PAGE_SIZE) | 1264 | if (len >= PAGE_SIZE) |
1267 | goto out; | 1265 | goto out; |
1268 | 1266 | ||
@@ -1532,11 +1530,6 @@ static int sel_make_initcon_files(struct dentry *dir) | |||
1532 | return 0; | 1530 | return 0; |
1533 | } | 1531 | } |
1534 | 1532 | ||
1535 | static inline unsigned int sel_div(unsigned long a, unsigned long b) | ||
1536 | { | ||
1537 | return a / b - (a % b < 0); | ||
1538 | } | ||
1539 | |||
1540 | static inline unsigned long sel_class_to_ino(u16 class) | 1533 | static inline unsigned long sel_class_to_ino(u16 class) |
1541 | { | 1534 | { |
1542 | return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET; | 1535 | return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET; |
@@ -1544,7 +1537,7 @@ static inline unsigned long sel_class_to_ino(u16 class) | |||
1544 | 1537 | ||
1545 | static inline u16 sel_ino_to_class(unsigned long ino) | 1538 | static inline u16 sel_ino_to_class(unsigned long ino) |
1546 | { | 1539 | { |
1547 | return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1); | 1540 | return (ino & SEL_INO_MASK) / (SEL_VEC_MAX + 1); |
1548 | } | 1541 | } |
1549 | 1542 | ||
1550 | static inline unsigned long sel_perm_to_ino(u16 class, u32 perm) | 1543 | static inline unsigned long sel_perm_to_ino(u16 class, u32 perm) |
@@ -1560,19 +1553,10 @@ static inline u32 sel_ino_to_perm(unsigned long ino) | |||
1560 | static ssize_t sel_read_class(struct file *file, char __user *buf, | 1553 | static ssize_t sel_read_class(struct file *file, char __user *buf, |
1561 | size_t count, loff_t *ppos) | 1554 | size_t count, loff_t *ppos) |
1562 | { | 1555 | { |
1563 | ssize_t rc, len; | ||
1564 | char *page; | ||
1565 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1556 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
1566 | 1557 | char res[TMPBUFLEN]; | |
1567 | page = (char *)__get_free_page(GFP_KERNEL); | 1558 | ssize_t len = snprintf(res, sizeof(res), "%d", sel_ino_to_class(ino)); |
1568 | if (!page) | 1559 | return simple_read_from_buffer(buf, count, ppos, res, len); |
1569 | return -ENOMEM; | ||
1570 | |||
1571 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino)); | ||
1572 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | ||
1573 | free_page((unsigned long)page); | ||
1574 | |||
1575 | return rc; | ||
1576 | } | 1560 | } |
1577 | 1561 | ||
1578 | static const struct file_operations sel_class_ops = { | 1562 | static const struct file_operations sel_class_ops = { |
@@ -1583,19 +1567,10 @@ static const struct file_operations sel_class_ops = { | |||
1583 | static ssize_t sel_read_perm(struct file *file, char __user *buf, | 1567 | static ssize_t sel_read_perm(struct file *file, char __user *buf, |
1584 | size_t count, loff_t *ppos) | 1568 | size_t count, loff_t *ppos) |
1585 | { | 1569 | { |
1586 | ssize_t rc, len; | ||
1587 | char *page; | ||
1588 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1570 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
1589 | 1571 | char res[TMPBUFLEN]; | |
1590 | page = (char *)__get_free_page(GFP_KERNEL); | 1572 | ssize_t len = snprintf(res, sizeof(res), "%d", sel_ino_to_perm(ino)); |
1591 | if (!page) | 1573 | return simple_read_from_buffer(buf, count, ppos, res, len); |
1592 | return -ENOMEM; | ||
1593 | |||
1594 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino)); | ||
1595 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | ||
1596 | free_page((unsigned long)page); | ||
1597 | |||
1598 | return rc; | ||
1599 | } | 1574 | } |
1600 | 1575 | ||
1601 | static const struct file_operations sel_perm_ops = { | 1576 | static const struct file_operations sel_perm_ops = { |
@@ -1831,7 +1806,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1831 | [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, | 1806 | [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, |
1832 | [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, | 1807 | [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, |
1833 | [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO}, | 1808 | [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO}, |
1834 | [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUSR}, | 1809 | [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO}, |
1835 | /* last one */ {""} | 1810 | /* last one */ {""} |
1836 | }; | 1811 | }; |
1837 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); | 1812 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); |
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h index 45e8fb0515f8..212e3479a0d9 100644 --- a/security/selinux/ss/context.h +++ b/security/selinux/ss/context.h | |||
@@ -74,6 +74,26 @@ out: | |||
74 | return rc; | 74 | return rc; |
75 | } | 75 | } |
76 | 76 | ||
77 | /* | ||
78 | * Sets both levels in the MLS range of 'dst' to the high level of 'src'. | ||
79 | */ | ||
80 | static inline int mls_context_cpy_high(struct context *dst, struct context *src) | ||
81 | { | ||
82 | int rc; | ||
83 | |||
84 | dst->range.level[0].sens = src->range.level[1].sens; | ||
85 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[1].cat); | ||
86 | if (rc) | ||
87 | goto out; | ||
88 | |||
89 | dst->range.level[1].sens = src->range.level[1].sens; | ||
90 | rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat); | ||
91 | if (rc) | ||
92 | ebitmap_destroy(&dst->range.level[0].cat); | ||
93 | out: | ||
94 | return rc; | ||
95 | } | ||
96 | |||
77 | static inline int mls_context_cmp(struct context *c1, struct context *c2) | 97 | static inline int mls_context_cmp(struct context *c1, struct context *c2) |
78 | { | 98 | { |
79 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && | 99 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index fbf9c5816c71..40de8d3f208e 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -517,6 +517,8 @@ int mls_compute_sid(struct context *scontext, | |||
517 | { | 517 | { |
518 | struct range_trans rtr; | 518 | struct range_trans rtr; |
519 | struct mls_range *r; | 519 | struct mls_range *r; |
520 | struct class_datum *cladatum; | ||
521 | int default_range = 0; | ||
520 | 522 | ||
521 | if (!policydb.mls_enabled) | 523 | if (!policydb.mls_enabled) |
522 | return 0; | 524 | return 0; |
@@ -530,6 +532,28 @@ int mls_compute_sid(struct context *scontext, | |||
530 | r = hashtab_search(policydb.range_tr, &rtr); | 532 | r = hashtab_search(policydb.range_tr, &rtr); |
531 | if (r) | 533 | if (r) |
532 | return mls_range_set(newcontext, r); | 534 | return mls_range_set(newcontext, r); |
535 | |||
536 | if (tclass && tclass <= policydb.p_classes.nprim) { | ||
537 | cladatum = policydb.class_val_to_struct[tclass - 1]; | ||
538 | if (cladatum) | ||
539 | default_range = cladatum->default_range; | ||
540 | } | ||
541 | |||
542 | switch (default_range) { | ||
543 | case DEFAULT_SOURCE_LOW: | ||
544 | return mls_context_cpy_low(newcontext, scontext); | ||
545 | case DEFAULT_SOURCE_HIGH: | ||
546 | return mls_context_cpy_high(newcontext, scontext); | ||
547 | case DEFAULT_SOURCE_LOW_HIGH: | ||
548 | return mls_context_cpy(newcontext, scontext); | ||
549 | case DEFAULT_TARGET_LOW: | ||
550 | return mls_context_cpy_low(newcontext, tcontext); | ||
551 | case DEFAULT_TARGET_HIGH: | ||
552 | return mls_context_cpy_high(newcontext, tcontext); | ||
553 | case DEFAULT_TARGET_LOW_HIGH: | ||
554 | return mls_context_cpy(newcontext, tcontext); | ||
555 | } | ||
556 | |||
533 | /* Fallthrough */ | 557 | /* Fallthrough */ |
534 | case AVTAB_CHANGE: | 558 | case AVTAB_CHANGE: |
535 | if ((tclass == policydb.process_class) || (sock == true)) | 559 | if ((tclass == policydb.process_class) || (sock == true)) |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index a7f61d52f05c..9cd9b7c661ec 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -133,6 +133,16 @@ static struct policydb_compat_info policydb_compat[] = { | |||
133 | .sym_num = SYM_NUM, | 133 | .sym_num = SYM_NUM, |
134 | .ocon_num = OCON_NUM, | 134 | .ocon_num = OCON_NUM, |
135 | }, | 135 | }, |
136 | { | ||
137 | .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, | ||
138 | .sym_num = SYM_NUM, | ||
139 | .ocon_num = OCON_NUM, | ||
140 | }, | ||
141 | { | ||
142 | .version = POLICYDB_VERSION_DEFAULT_TYPE, | ||
143 | .sym_num = SYM_NUM, | ||
144 | .ocon_num = OCON_NUM, | ||
145 | }, | ||
136 | }; | 146 | }; |
137 | 147 | ||
138 | static struct policydb_compat_info *policydb_lookup_compat(int version) | 148 | static struct policydb_compat_info *policydb_lookup_compat(int version) |
@@ -1306,6 +1316,23 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
1306 | goto bad; | 1316 | goto bad; |
1307 | } | 1317 | } |
1308 | 1318 | ||
1319 | if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) { | ||
1320 | rc = next_entry(buf, fp, sizeof(u32) * 3); | ||
1321 | if (rc) | ||
1322 | goto bad; | ||
1323 | |||
1324 | cladatum->default_user = le32_to_cpu(buf[0]); | ||
1325 | cladatum->default_role = le32_to_cpu(buf[1]); | ||
1326 | cladatum->default_range = le32_to_cpu(buf[2]); | ||
1327 | } | ||
1328 | |||
1329 | if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) { | ||
1330 | rc = next_entry(buf, fp, sizeof(u32) * 1); | ||
1331 | if (rc) | ||
1332 | goto bad; | ||
1333 | cladatum->default_type = le32_to_cpu(buf[0]); | ||
1334 | } | ||
1335 | |||
1309 | rc = hashtab_insert(h, key, cladatum); | 1336 | rc = hashtab_insert(h, key, cladatum); |
1310 | if (rc) | 1337 | if (rc) |
1311 | goto bad; | 1338 | goto bad; |
@@ -2832,6 +2859,23 @@ static int class_write(void *vkey, void *datum, void *ptr) | |||
2832 | if (rc) | 2859 | if (rc) |
2833 | return rc; | 2860 | return rc; |
2834 | 2861 | ||
2862 | if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) { | ||
2863 | buf[0] = cpu_to_le32(cladatum->default_user); | ||
2864 | buf[1] = cpu_to_le32(cladatum->default_role); | ||
2865 | buf[2] = cpu_to_le32(cladatum->default_range); | ||
2866 | |||
2867 | rc = put_entry(buf, sizeof(uint32_t), 3, fp); | ||
2868 | if (rc) | ||
2869 | return rc; | ||
2870 | } | ||
2871 | |||
2872 | if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) { | ||
2873 | buf[0] = cpu_to_le32(cladatum->default_type); | ||
2874 | rc = put_entry(buf, sizeof(uint32_t), 1, fp); | ||
2875 | if (rc) | ||
2876 | return rc; | ||
2877 | } | ||
2878 | |||
2835 | return 0; | 2879 | return 0; |
2836 | } | 2880 | } |
2837 | 2881 | ||
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index b846c0387180..da637471d4ce 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -60,6 +60,20 @@ struct class_datum { | |||
60 | struct symtab permissions; /* class-specific permission symbol table */ | 60 | struct symtab permissions; /* class-specific permission symbol table */ |
61 | struct constraint_node *constraints; /* constraints on class permissions */ | 61 | struct constraint_node *constraints; /* constraints on class permissions */ |
62 | struct constraint_node *validatetrans; /* special transition rules */ | 62 | struct constraint_node *validatetrans; /* special transition rules */ |
63 | /* Options how a new object user, role, and type should be decided */ | ||
64 | #define DEFAULT_SOURCE 1 | ||
65 | #define DEFAULT_TARGET 2 | ||
66 | char default_user; | ||
67 | char default_role; | ||
68 | char default_type; | ||
69 | /* Options how a new object range should be decided */ | ||
70 | #define DEFAULT_SOURCE_LOW 1 | ||
71 | #define DEFAULT_SOURCE_HIGH 2 | ||
72 | #define DEFAULT_SOURCE_LOW_HIGH 3 | ||
73 | #define DEFAULT_TARGET_LOW 4 | ||
74 | #define DEFAULT_TARGET_HIGH 5 | ||
75 | #define DEFAULT_TARGET_LOW_HIGH 6 | ||
76 | char default_range; | ||
63 | }; | 77 | }; |
64 | 78 | ||
65 | /* Role attributes */ | 79 | /* Role attributes */ |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 185f849a26f6..4321b8fc8863 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -1018,9 +1018,11 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 | |||
1018 | 1018 | ||
1019 | if (context->len) { | 1019 | if (context->len) { |
1020 | *scontext_len = context->len; | 1020 | *scontext_len = context->len; |
1021 | *scontext = kstrdup(context->str, GFP_ATOMIC); | 1021 | if (scontext) { |
1022 | if (!(*scontext)) | 1022 | *scontext = kstrdup(context->str, GFP_ATOMIC); |
1023 | return -ENOMEM; | 1023 | if (!(*scontext)) |
1024 | return -ENOMEM; | ||
1025 | } | ||
1024 | return 0; | 1026 | return 0; |
1025 | } | 1027 | } |
1026 | 1028 | ||
@@ -1389,6 +1391,7 @@ static int security_compute_sid(u32 ssid, | |||
1389 | u32 *out_sid, | 1391 | u32 *out_sid, |
1390 | bool kern) | 1392 | bool kern) |
1391 | { | 1393 | { |
1394 | struct class_datum *cladatum = NULL; | ||
1392 | struct context *scontext = NULL, *tcontext = NULL, newcontext; | 1395 | struct context *scontext = NULL, *tcontext = NULL, newcontext; |
1393 | struct role_trans *roletr = NULL; | 1396 | struct role_trans *roletr = NULL; |
1394 | struct avtab_key avkey; | 1397 | struct avtab_key avkey; |
@@ -1437,12 +1440,20 @@ static int security_compute_sid(u32 ssid, | |||
1437 | goto out_unlock; | 1440 | goto out_unlock; |
1438 | } | 1441 | } |
1439 | 1442 | ||
1443 | if (tclass && tclass <= policydb.p_classes.nprim) | ||
1444 | cladatum = policydb.class_val_to_struct[tclass - 1]; | ||
1445 | |||
1440 | /* Set the user identity. */ | 1446 | /* Set the user identity. */ |
1441 | switch (specified) { | 1447 | switch (specified) { |
1442 | case AVTAB_TRANSITION: | 1448 | case AVTAB_TRANSITION: |
1443 | case AVTAB_CHANGE: | 1449 | case AVTAB_CHANGE: |
1444 | /* Use the process user identity. */ | 1450 | if (cladatum && cladatum->default_user == DEFAULT_TARGET) { |
1445 | newcontext.user = scontext->user; | 1451 | newcontext.user = tcontext->user; |
1452 | } else { | ||
1453 | /* notice this gets both DEFAULT_SOURCE and unset */ | ||
1454 | /* Use the process user identity. */ | ||
1455 | newcontext.user = scontext->user; | ||
1456 | } | ||
1446 | break; | 1457 | break; |
1447 | case AVTAB_MEMBER: | 1458 | case AVTAB_MEMBER: |
1448 | /* Use the related object owner. */ | 1459 | /* Use the related object owner. */ |
@@ -1450,16 +1461,31 @@ static int security_compute_sid(u32 ssid, | |||
1450 | break; | 1461 | break; |
1451 | } | 1462 | } |
1452 | 1463 | ||
1453 | /* Set the role and type to default values. */ | 1464 | /* Set the role to default values. */ |
1454 | if ((tclass == policydb.process_class) || (sock == true)) { | 1465 | if (cladatum && cladatum->default_role == DEFAULT_SOURCE) { |
1455 | /* Use the current role and type of process. */ | ||
1456 | newcontext.role = scontext->role; | 1466 | newcontext.role = scontext->role; |
1457 | newcontext.type = scontext->type; | 1467 | } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) { |
1468 | newcontext.role = tcontext->role; | ||
1458 | } else { | 1469 | } else { |
1459 | /* Use the well-defined object role. */ | 1470 | if ((tclass == policydb.process_class) || (sock == true)) |
1460 | newcontext.role = OBJECT_R_VAL; | 1471 | newcontext.role = scontext->role; |
1461 | /* Use the type of the related object. */ | 1472 | else |
1473 | newcontext.role = OBJECT_R_VAL; | ||
1474 | } | ||
1475 | |||
1476 | /* Set the type to default values. */ | ||
1477 | if (cladatum && cladatum->default_type == DEFAULT_SOURCE) { | ||
1478 | newcontext.type = scontext->type; | ||
1479 | } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) { | ||
1462 | newcontext.type = tcontext->type; | 1480 | newcontext.type = tcontext->type; |
1481 | } else { | ||
1482 | if ((tclass == policydb.process_class) || (sock == true)) { | ||
1483 | /* Use the type of process. */ | ||
1484 | newcontext.type = scontext->type; | ||
1485 | } else { | ||
1486 | /* Use the type of the related object. */ | ||
1487 | newcontext.type = tcontext->type; | ||
1488 | } | ||
1463 | } | 1489 | } |
1464 | 1490 | ||
1465 | /* Look for a type transition/member/change rule. */ | 1491 | /* Look for a type transition/member/change rule. */ |
@@ -3018,8 +3044,7 @@ out: | |||
3018 | 3044 | ||
3019 | static int (*aurule_callback)(void) = audit_update_lsm_rules; | 3045 | static int (*aurule_callback)(void) = audit_update_lsm_rules; |
3020 | 3046 | ||
3021 | static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, | 3047 | static int aurule_avc_callback(u32 event) |
3022 | u16 class, u32 perms, u32 *retained) | ||
3023 | { | 3048 | { |
3024 | int err = 0; | 3049 | int err = 0; |
3025 | 3050 | ||
@@ -3032,8 +3057,7 @@ static int __init aurule_init(void) | |||
3032 | { | 3057 | { |
3033 | int err; | 3058 | int err; |
3034 | 3059 | ||
3035 | err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET, | 3060 | err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET); |
3036 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | ||
3037 | if (err) | 3061 | if (err) |
3038 | panic("avc_add_callback() failed, error %d\n", err); | 3062 | panic("avc_add_callback() failed, error %d\n", err); |
3039 | 3063 | ||