| .. | .. | 
|---|
| 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; | 
|---|