@ -119,17 +119,34 @@ EXPORT_SYMBOL(cad_pid);
void ( * pm_power_off_prepare ) ( void ) ;
/*
* Returns true if current ' s euid is same as p ' s uid or euid ,
* or has CAP_SYS_NICE to p ' s user_ns .
*
* Called with rcu_read_lock , creds are safe
*/
static bool set_one_prio_perm ( struct task_struct * p )
{
const struct cred * cred = current_cred ( ) , * pcred = __task_cred ( p ) ;
if ( pcred - > user - > user_ns = = cred - > user - > user_ns & &
( pcred - > uid = = cred - > euid | |
pcred - > euid = = cred - > euid ) )
return true ;
if ( ns_capable ( pcred - > user - > user_ns , CAP_SYS_NICE ) )
return true ;
return false ;
}
/*
* set the priority of a task
* - the caller must hold the RCU read lock
*/
static int set_one_prio ( struct task_struct * p , int niceval , int error )
{
const struct cred * cred = current_cred ( ) , * pcred = __task_cred ( p ) ;
int no_nice ;
if ( pcred - > uid ! = cred - > euid & &
pcred - > euid ! = cred - > euid & & ! capable ( CAP_SYS_NICE ) ) {
if ( ! set_one_prio_perm ( p ) ) {
error = - EPERM ;
goto out ;
}
@ -506,7 +523,7 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid)
if ( rgid ! = ( gid_t ) - 1 ) {
if ( old - > gid = = rgid | |
old - > egid = = rgid | |
capable ( CAP_SETGID ) )
nsown_ capable( CAP_SETGID ) )
new - > gid = rgid ;
else
goto error ;
@ -515,7 +532,7 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid)
if ( old - > gid = = egid | |
old - > egid = = egid | |
old - > sgid = = egid | |
capable ( CAP_SETGID ) )
nsown_ capable( CAP_SETGID ) )
new - > egid = egid ;
else
goto error ;
@ -550,7 +567,7 @@ SYSCALL_DEFINE1(setgid, gid_t, gid)
old = current_cred ( ) ;
retval = - EPERM ;
if ( capable ( CAP_SETGID ) )
if ( nsown_ capable( CAP_SETGID ) )
new - > gid = new - > egid = new - > sgid = new - > fsgid = gid ;
else if ( gid = = old - > gid | | gid = = old - > sgid )
new - > egid = new - > fsgid = gid ;
@ -617,7 +634,7 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
new - > uid = ruid ;
if ( old - > uid ! = ruid & &
old - > euid ! = ruid & &
! capable ( CAP_SETUID ) )
! nsown_ capable( CAP_SETUID ) )
goto error ;
}
@ -626,7 +643,7 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
if ( old - > uid ! = euid & &
old - > euid ! = euid & &
old - > suid ! = euid & &
! capable ( CAP_SETUID ) )
! nsown_ capable( CAP_SETUID ) )
goto error ;
}
@ -674,7 +691,7 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
old = current_cred ( ) ;
retval = - EPERM ;
if ( capable ( CAP_SETUID ) ) {
if ( nsown_ capable( CAP_SETUID ) ) {
new - > suid = new - > uid = uid ;
if ( uid ! = old - > uid ) {
retval = set_user ( new ) ;
@ -716,7 +733,7 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
old = current_cred ( ) ;
retval = - EPERM ;
if ( ! capable ( CAP_SETUID ) ) {
if ( ! nsown_ capable( CAP_SETUID ) ) {
if ( ruid ! = ( uid_t ) - 1 & & ruid ! = old - > uid & &
ruid ! = old - > euid & & ruid ! = old - > suid )
goto error ;
@ -780,7 +797,7 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
old = current_cred ( ) ;
retval = - EPERM ;
if ( ! capable ( CAP_SETGID ) ) {
if ( ! nsown_ capable( CAP_SETGID ) ) {
if ( rgid ! = ( gid_t ) - 1 & & rgid ! = old - > gid & &
rgid ! = old - > egid & & rgid ! = old - > sgid )
goto error ;
@ -840,7 +857,7 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
if ( uid = = old - > uid | | uid = = old - > euid | |
uid = = old - > suid | | uid = = old - > fsuid | |
capable ( CAP_SETUID ) ) {
nsown_ capable( CAP_SETUID ) ) {
if ( uid ! = old_fsuid ) {
new - > fsuid = uid ;
if ( security_task_fix_setuid ( new , old , LSM_SETID_FS ) = = 0 )
@ -873,7 +890,7 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
if ( gid = = old - > gid | | gid = = old - > egid | |
gid = = old - > sgid | | gid = = old - > fsgid | |
capable ( CAP_SETGID ) ) {
nsown_ capable( CAP_SETGID ) ) {
if ( gid ! = old_fsgid ) {
new - > fsgid = gid ;
goto change_okay ;
@ -1183,6 +1200,7 @@ SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
if ( ! ns_capable ( current - > nsproxy - > uts_ns - > user_ns , CAP_SYS_ADMIN ) )
return - EPERM ;
if ( len < 0 | | len > __NEW_UTS_LEN )
return - EINVAL ;
down_write ( & uts_sem ) ;
@ -1230,7 +1248,7 @@ SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len)
int errno ;
char tmp [ __NEW_UTS_LEN ] ;
if ( ! capable ( CAP_SYS_ADMIN ) )
if ( ! ns_ capable( current - > nsproxy - > uts_ns - > user_ns , CAP_SYS_ADMIN ) )
return - EPERM ;
if ( len < 0 | | len > __NEW_UTS_LEN )
return - EINVAL ;
@ -1345,6 +1363,8 @@ int do_prlimit(struct task_struct *tsk, unsigned int resource,
rlim = tsk - > signal - > rlim + resource ;
task_lock ( tsk - > group_leader ) ;
if ( new_rlim ) {
/* Keep the capable check against init_user_ns until
cgroups can contain all limits */
if ( new_rlim - > rlim_max > rlim - > rlim_max & &
! capable ( CAP_SYS_RESOURCE ) )
retval = - EPERM ;
@ -1388,19 +1408,22 @@ static int check_prlimit_permission(struct task_struct *task)
{
const struct cred * cred = current_cred ( ) , * tcred ;
tcred = __task_cred ( task ) ;
if ( current ! = task & &
( cred - > uid ! = tcred - > euid | |
cred - > uid ! = tcred - > suid | |
cred - > uid ! = tcred - > uid | |
cred - > gid ! = tcred - > egid | |
cred - > gid ! = tcred - > sgid | |
cred - > gid ! = tcred - > gid ) & &
! capable ( CAP_SYS_RESOURCE ) ) {
return - EPERM ;
}
if ( current = = task )
return 0 ;
return 0 ;
tcred = __task_cred ( task ) ;
if ( cred - > user - > user_ns = = tcred - > user - > user_ns & &
( cred - > uid = = tcred - > euid & &
cred - > uid = = tcred - > suid & &
cred - > uid = = tcred - > uid & &
cred - > gid = = tcred - > egid & &
cred - > gid = = tcred - > sgid & &
cred - > gid = = tcred - > gid ) )
return 0 ;
if ( ns_capable ( tcred - > user - > user_ns , CAP_SYS_RESOURCE ) )
return 0 ;
return - EPERM ;
}
SYSCALL_DEFINE4 ( prlimit64 , pid_t , pid , unsigned int , resource ,