.. | .. |
---|
644 | 644 | struct cred *new; |
---|
645 | 645 | int retval; |
---|
646 | 646 | kuid_t kruid, keuid, ksuid; |
---|
| 647 | + bool ruid_new, euid_new, suid_new; |
---|
647 | 648 | |
---|
648 | 649 | kruid = make_kuid(ns, ruid); |
---|
649 | 650 | keuid = make_kuid(ns, euid); |
---|
.. | .. |
---|
658 | 659 | if ((suid != (uid_t) -1) && !uid_valid(ksuid)) |
---|
659 | 660 | return -EINVAL; |
---|
660 | 661 | |
---|
| 662 | + old = current_cred(); |
---|
| 663 | + |
---|
| 664 | + /* check for no-op */ |
---|
| 665 | + if ((ruid == (uid_t) -1 || uid_eq(kruid, old->uid)) && |
---|
| 666 | + (euid == (uid_t) -1 || (uid_eq(keuid, old->euid) && |
---|
| 667 | + uid_eq(keuid, old->fsuid))) && |
---|
| 668 | + (suid == (uid_t) -1 || uid_eq(ksuid, old->suid))) |
---|
| 669 | + return 0; |
---|
| 670 | + |
---|
| 671 | + ruid_new = ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) && |
---|
| 672 | + !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid); |
---|
| 673 | + euid_new = euid != (uid_t) -1 && !uid_eq(keuid, old->uid) && |
---|
| 674 | + !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid); |
---|
| 675 | + suid_new = suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) && |
---|
| 676 | + !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid); |
---|
| 677 | + if ((ruid_new || euid_new || suid_new) && |
---|
| 678 | + !ns_capable_setid(old->user_ns, CAP_SETUID)) |
---|
| 679 | + return -EPERM; |
---|
| 680 | + |
---|
661 | 681 | new = prepare_creds(); |
---|
662 | 682 | if (!new) |
---|
663 | 683 | return -ENOMEM; |
---|
664 | | - |
---|
665 | | - old = current_cred(); |
---|
666 | | - |
---|
667 | | - retval = -EPERM; |
---|
668 | | - if (!ns_capable_setid(old->user_ns, CAP_SETUID)) { |
---|
669 | | - if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) && |
---|
670 | | - !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid)) |
---|
671 | | - goto error; |
---|
672 | | - if (euid != (uid_t) -1 && !uid_eq(keuid, old->uid) && |
---|
673 | | - !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid)) |
---|
674 | | - goto error; |
---|
675 | | - if (suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) && |
---|
676 | | - !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid)) |
---|
677 | | - goto error; |
---|
678 | | - } |
---|
679 | 684 | |
---|
680 | 685 | if (ruid != (uid_t) -1) { |
---|
681 | 686 | new->uid = kruid; |
---|
.. | .. |
---|
736 | 741 | struct cred *new; |
---|
737 | 742 | int retval; |
---|
738 | 743 | kgid_t krgid, kegid, ksgid; |
---|
| 744 | + bool rgid_new, egid_new, sgid_new; |
---|
739 | 745 | |
---|
740 | 746 | krgid = make_kgid(ns, rgid); |
---|
741 | 747 | kegid = make_kgid(ns, egid); |
---|
.. | .. |
---|
748 | 754 | if ((sgid != (gid_t) -1) && !gid_valid(ksgid)) |
---|
749 | 755 | return -EINVAL; |
---|
750 | 756 | |
---|
| 757 | + old = current_cred(); |
---|
| 758 | + |
---|
| 759 | + /* check for no-op */ |
---|
| 760 | + if ((rgid == (gid_t) -1 || gid_eq(krgid, old->gid)) && |
---|
| 761 | + (egid == (gid_t) -1 || (gid_eq(kegid, old->egid) && |
---|
| 762 | + gid_eq(kegid, old->fsgid))) && |
---|
| 763 | + (sgid == (gid_t) -1 || gid_eq(ksgid, old->sgid))) |
---|
| 764 | + return 0; |
---|
| 765 | + |
---|
| 766 | + rgid_new = rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) && |
---|
| 767 | + !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid); |
---|
| 768 | + egid_new = egid != (gid_t) -1 && !gid_eq(kegid, old->gid) && |
---|
| 769 | + !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid); |
---|
| 770 | + sgid_new = sgid != (gid_t) -1 && !gid_eq(ksgid, old->gid) && |
---|
| 771 | + !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid); |
---|
| 772 | + if ((rgid_new || egid_new || sgid_new) && |
---|
| 773 | + !ns_capable_setid(old->user_ns, CAP_SETGID)) |
---|
| 774 | + return -EPERM; |
---|
| 775 | + |
---|
751 | 776 | new = prepare_creds(); |
---|
752 | 777 | if (!new) |
---|
753 | 778 | return -ENOMEM; |
---|
754 | | - old = current_cred(); |
---|
755 | | - |
---|
756 | | - retval = -EPERM; |
---|
757 | | - if (!ns_capable_setid(old->user_ns, CAP_SETGID)) { |
---|
758 | | - if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) && |
---|
759 | | - !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid)) |
---|
760 | | - goto error; |
---|
761 | | - if (egid != (gid_t) -1 && !gid_eq(kegid, old->gid) && |
---|
762 | | - !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid)) |
---|
763 | | - goto error; |
---|
764 | | - if (sgid != (gid_t) -1 && !gid_eq(ksgid, old->gid) && |
---|
765 | | - !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid)) |
---|
766 | | - goto error; |
---|
767 | | - } |
---|
768 | 779 | |
---|
769 | 780 | if (rgid != (gid_t) -1) |
---|
770 | 781 | new->gid = krgid; |
---|
.. | .. |
---|
1558 | 1569 | |
---|
1559 | 1570 | if (resource >= RLIM_NLIMITS) |
---|
1560 | 1571 | return -EINVAL; |
---|
| 1572 | + resource = array_index_nospec(resource, RLIM_NLIMITS); |
---|
| 1573 | + |
---|
1561 | 1574 | if (new_rlim) { |
---|
1562 | 1575 | if (new_rlim->rlim_cur > new_rlim->rlim_max) |
---|
1563 | 1576 | return -EINVAL; |
---|