diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2016-11-22 14:12:56 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2016-11-26 14:49:24 +0000 |
commit | a434634703d530e1a12fdabde4691c73a93ca8b5 (patch) | |
tree | ed4cf9954365af5b3bec0ecbbc6108cd5b56ef6f | |
parent | 91bad8da9e9cc8662d6c49ddbdc16359f2502be4 (diff) | |
download | illumos-joyent-a434634703d530e1a12fdabde4691c73a93ca8b5.tar.gz |
OS-5802 LTP setpriority02 now failing
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Approved by: Patrick Mooney <patrick.mooney@joyent.com>
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/Makefile.com | 1 | ||||
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/lx_brand.c | 8 | ||||
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/priority.c | 117 | ||||
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_syscall.c | 8 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_syscalls.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_priority.c | 192 | ||||
-rw-r--r-- | usr/src/uts/common/disp/priocntl.c | 4 | ||||
-rw-r--r-- | usr/src/uts/intel/Makefile.files | 1 |
9 files changed, 205 insertions, 131 deletions
diff --git a/usr/src/lib/brand/lx/lx_brand/Makefile.com b/usr/src/lib/brand/lx/lx_brand/Makefile.com index 53f5246834..262356884f 100644 --- a/usr/src/lib/brand/lx/lx_brand/Makefile.com +++ b/usr/src/lib/brand/lx/lx_brand/Makefile.com @@ -43,7 +43,6 @@ COBJS = aio.o \ module.o \ mount.o \ mount_nfs.o \ - priority.o \ ptrace.o \ sendfile.o \ signal.o \ diff --git a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c index 5724b6cbba..200df187ae 100644 --- a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c +++ b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c @@ -1151,8 +1151,8 @@ static lx_syscall_handler_t lx_handlers[] = { lx_statfs, /* 137: statfs */ lx_fstatfs, /* 138: fstatfs */ lx_sysfs, /* 139: sysfs */ - lx_getpriority, /* 140: getpriority */ - lx_setpriority, /* 141: setpriority */ + NULL, /* 140: getpriority */ + NULL, /* 141: setpriority */ NULL, /* 142: sched_setparam */ NULL, /* 143: sched_getparam */ NULL, /* 144: sched_setscheduler */ @@ -1438,8 +1438,8 @@ static lx_syscall_handler_t lx_handlers[] = { lx_ftruncate, /* 93: ftruncate */ NULL, /* 94: fchmod */ NULL, /* 95: fchown16 */ - lx_getpriority, /* 96: getpriority */ - lx_setpriority, /* 97: setpriority */ + NULL, /* 96: getpriority */ + NULL, /* 97: setpriority */ NULL, /* 98: profil */ lx_statfs, /* 99: statfs */ lx_fstatfs, /* 100: fstatfs */ diff --git a/usr/src/lib/brand/lx/lx_brand/common/priority.c b/usr/src/lib/brand/lx/lx_brand/common/priority.c deleted file mode 100644 index 5974abe40e..0000000000 --- a/usr/src/lib/brand/lx/lx_brand/common/priority.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * Copyright 2015 Joyent, Inc. All rights reserved. - */ - -#include <errno.h> -#include <sys/types.h> -#include <sys/lx_debug.h> -#include <sys/lx_misc.h> -#include <sys/lx_syscall.h> -#include <sys/lx_types.h> -#include <sys/resource.h> -#include <sys/lx_misc.h> -#include <sched.h> - -/* - * The Linux syscall returns priorities in the range (lowest) 40-1 (highest) - * and then glibc adjusts these to the range -20 - 19. - */ -long -lx_getpriority(uintptr_t p1, uintptr_t p2) -{ - int which = (int)p1; - id_t who = (id_t)p2; - int ret; - - /* - * The only valid values for 'which' are positive integers, and unlike - * Solaris, linux doesn't support anything past PRIO_USER. - */ - if (which < 0 || which > PRIO_USER) - return (-EINVAL); - - lx_debug("\tgetpriority(%d, %d)", which, who); - - errno = 0; - - if ((which == PRIO_PROCESS) && (who == 1)) - who = zoneinit_pid; - - ret = getpriority(which, who); - if (ret == -1 && errno != 0) { - pid_t mypid = getpid(); - - if (which == PRIO_PROCESS && - (who == mypid || who == 0 || who == P_MYID) && - sched_getscheduler(mypid) == SCHED_RR) { - /* - * The getpriority kernel handling will always return - * an error if we're in the RT class. The zone itself - * won't be able to put itself or any of its processes - * into RT but if we put the whole zone into RT via - * the scheduling-class property, then getpriority will - * always fail. This breaks pam and prevents any login. - * Just pretend to be the highest priority. - */ - return (1); - } - - /* - * Linux does not return EINVAL for invalid 'who' values, it - * returns ESRCH instead. We already validated 'which' above. - */ - if (errno == EINVAL) - errno = ESRCH; - return (-errno); - } - - /* - * The return value of the getpriority syscall is biased by 20 to avoid - * returning negative values when successful. - */ - return (20 - ret); -} - -long -lx_setpriority(uintptr_t p1, uintptr_t p2, uintptr_t p3) -{ - int which = (int)p1; - id_t who = (id_t)p2; - int prio = (int)p3; - int rval; - - if (which > PRIO_USER) - return (-EINVAL); - - lx_debug("\tsetpriority(%d, %d, %d)", which, who, prio); - - if ((which == PRIO_PROCESS) && (who == 1)) - who = zoneinit_pid; - - rval = setpriority(which, who, prio); - - return ((rval == -1) ? -errno : rval); -} diff --git a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h index 64e1ca6ab8..efcbef8f70 100644 --- a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h +++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h @@ -157,9 +157,6 @@ extern long lx_fork(void); extern long lx_vfork(void); extern long lx_exec(uintptr_t, uintptr_t, uintptr_t); -extern long lx_getpriority(uintptr_t, uintptr_t); -extern long lx_setpriority(uintptr_t, uintptr_t, uintptr_t); - extern long lx_ptrace(uintptr_t, uintptr_t, uintptr_t, uintptr_t); extern long lx_xattr2(uintptr_t, uintptr_t); diff --git a/usr/src/uts/common/brand/lx/os/lx_syscall.c b/usr/src/uts/common/brand/lx/os/lx_syscall.c index 7cb29f1004..3a558d89b0 100644 --- a/usr/src/uts/common/brand/lx/os/lx_syscall.c +++ b/usr/src/uts/common/brand/lx/os/lx_syscall.c @@ -615,8 +615,8 @@ lx_sysent_t lx_sysent32[] = { {"ftruncate", NULL, 0, 2}, /* 93 */ {"fchmod", lx_fchmod, 0, 2}, /* 94 */ {"fchown16", lx_fchown16, 0, 3}, /* 95 */ - {"getpriority", NULL, 0, 2}, /* 96 */ - {"setpriority", NULL, 0, 3}, /* 97 */ + {"getpriority", lx_getpriority, 0, 2}, /* 96 */ + {"setpriority", lx_setpriority, 0, 3}, /* 97 */ {"profil", NULL, NOSYS_NO_EQUIV, 0}, /* 98 */ {"statfs", NULL, 0, 2}, /* 99 */ {"fstatfs", NULL, 0, 2}, /* 100 */ @@ -1030,8 +1030,8 @@ lx_sysent_t lx_sysent64[] = { {"statfs", NULL, 0, 2}, /* 137 */ {"fstatfs", NULL, 0, 2}, /* 138 */ {"sysfs", NULL, 0, 3}, /* 139 */ - {"getpriority", NULL, 0, 2}, /* 140 */ - {"setpriority", NULL, 0, 3}, /* 141 */ + {"getpriority", lx_getpriority, 0, 2}, /* 140 */ + {"setpriority", lx_setpriority, 0, 3}, /* 141 */ {"sched_setparam", lx_sched_setparam, 0, 2}, /* 142 */ {"sched_getparam", lx_sched_getparam, 0, 2}, /* 143 */ {"sched_setscheduler", lx_sched_setscheduler, 0, 3}, /* 144 */ diff --git a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h index f8fb1c145d..63afc0e795 100644 --- a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h +++ b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h @@ -102,6 +102,7 @@ extern long lx_getpgrp(); extern long lx_getsockname(); extern long lx_getpid(); extern long lx_getppid(); +extern long lx_getpriority(); extern long lx_getrandom(); extern long lx_getresgid(); extern long lx_getresgid16(); @@ -203,6 +204,7 @@ extern long lx_setgid(); extern long lx_setgid16(); extern long lx_sethostname(); extern long lx_setpgid(); +extern long lx_setpriority(); extern long lx_setregid(); extern long lx_setregid16(); extern long lx_setresgid(); diff --git a/usr/src/uts/common/brand/lx/syscall/lx_priority.c b/usr/src/uts/common/brand/lx/syscall/lx_priority.c new file mode 100644 index 0000000000..44c60b66bf --- /dev/null +++ b/usr/src/uts/common/brand/lx/syscall/lx_priority.c @@ -0,0 +1,192 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2016 Joyent, Inc. + */ + +#include <sys/systm.h> +#include <sys/procset.h> +#include <sys/resource.h> +#include <sys/priocntl.h> +#include <sys/param.h> +#include <sys/policy.h> +#include <sys/brand.h> +#include <sys/lx_brand.h> + +/* From uts/common/disp/priocntl.c */ +extern int donice(procset_t *, pcnice_t *); + +/* + * The Linux syscall returns priorities in the range (highest) 40-1 (lowest) + * and then glibc adjusts these to the range -20 - 19. + */ +long +lx_getpriority(int which, id_t who) +{ + int rval; + idtype_t idtype; + id_t id, lid; + pcnice_t pcnice; + procset_t procset; + + switch (which) { + case PRIO_PROCESS: + idtype = P_PID; + if (who > 0 && lx_lpid_to_spair(who, &who, &lid) < 0) + return (set_errno(ESRCH)); + break; + case PRIO_PGRP: + idtype = P_PGID; + break; + case PRIO_USER: + idtype = P_UID; + break; + default: + return (set_errno(EINVAL)); + } + + /* Linux fails with a different errno on a negative id */ + if (who < 0) + return (set_errno(ESRCH)); + + id = (who == 0 ? P_MYID : who); + + pcnice.pc_val = 0; + pcnice.pc_op = PC_GETNICE; + + setprocset(&procset, POP_AND, idtype, id, P_ALL, 0); + + rval = donice(&procset, &pcnice); + if (rval != 0) { + if (which == PRIO_PROCESS && + (who == curproc->p_pid || who == 0) && + strcmp(sclass[curthread->t_cid].cl_name, "RT") == 0) { + /* + * donice() will always return EINVAL if we're in the + * RT class. The zone won't be able to put itself or any + * of its processes into RT, but if we put the whole + * zone into RT via the scheduling-class property, then + * getpriority would always fail. This breaks pam and + * prevents any login. Just pretend to be the highest + * priority. + */ + return (40); + } + + /* + * Linux does not return EINVAL for invalid 'who' values, it + * returns ESRCH instead. We already validated 'which' above. + */ + if (rval == EINVAL) + rval = ESRCH; + return (set_errno(rval)); + } + + /* + * The return value of the getpriority syscall is biased by 20 to avoid + * returning negative values when successful (-20 internally is our + * highest priority and 19 is our lowest). + */ + return (20 - pcnice.pc_val); +} + +/* + * Return EPERM if the current process is not allowed to operate on the target + * process (which is part of the procset for setpriority). + */ +/* ARGSUSED */ +static int +lx_chk_pripriv(proc_t *pp, char *dummy) +{ + ASSERT(MUTEX_HELD(&pidlock)); + mutex_enter(&pp->p_lock); + if (!prochasprocperm(pp, curproc, CRED())) { + mutex_exit(&pp->p_lock); + return (EPERM); + } + mutex_exit(&pp->p_lock); + return (0); +} + +long +lx_setpriority(int which, id_t who, int prio) +{ + int rval; + idtype_t idtype; + id_t id, lid; + pcnice_t pcnice; + procset_t procset; + + switch (which) { + case PRIO_PROCESS: + idtype = P_PID; + if (who > 0 && lx_lpid_to_spair(who, &who, &lid) < 0) + return (set_errno(ESRCH)); + break; + case PRIO_PGRP: + idtype = P_PGID; + break; + case PRIO_USER: + idtype = P_UID; + break; + default: + return (set_errno(EINVAL)); + } + + /* Linux fails with a different errno on a negative id */ + if (who < 0) + return (set_errno(ESRCH)); + + id = (who == 0 ? P_MYID : who); + + if (prio > NZERO - 1) { + prio = NZERO - 1; + } else if (prio < -NZERO) { + prio = -NZERO; + } + + pcnice.pc_val = prio; + pcnice.pc_op = PC_SETNICE; + + setprocset(&procset, POP_AND, idtype, id, P_ALL, 0); + + rval = donice(&procset, &pcnice); + if (rval != 0) { + /* + * Once we fully support Linux capabilities, we should update + * the following check to look at the CAP_SYS_NICE capability. + */ + if (rval == EPERM && crgetuid(CRED()) != 0) { + /* + * donice() returns EPERM under two conditions: + * 1) if either the real or eff. uid don't match + * 2) we lack the privileges to raise the priority + * + * However, setpriority() must return a different errno + * based on the following: + * EPERM - real or eff. uid did not match + * EACCES - trying to increase priority + * + * We use lx_chk_pripriv to determine which case we hit. + * + * Note that the native setpriority(3C) code has the + * same race on re-checking. + */ + if (dotoprocs(&procset, lx_chk_pripriv, NULL) != EPERM) + rval = EACCES; + } + + return (set_errno(rval)); + } + + return (0); +} diff --git a/usr/src/uts/common/disp/priocntl.c b/usr/src/uts/common/disp/priocntl.c index 0101d12432..fb48f15306 100644 --- a/usr/src/uts/common/disp/priocntl.c +++ b/usr/src/uts/common/disp/priocntl.c @@ -113,7 +113,7 @@ copyin_vaparms32(caddr_t arg, pc_vaparms_t *vap, uio_seg_t seg) #endif -static int donice(procset_t *, pcnice_t *); +int donice(procset_t *, pcnice_t *); static int doprio(procset_t *, pcprio_t *); static int proccmp(proc_t *, struct pcmpargs *); static int setparms(proc_t *, struct stprmargs *); @@ -990,7 +990,7 @@ setprocnice(proc_t *pp, pcnice_t *pcnice) /* * Update the nice value of the specified LWP or set of processes. */ -static int +int donice(procset_t *procset, pcnice_t *pcnice) { int err_proc = 0; diff --git a/usr/src/uts/intel/Makefile.files b/usr/src/uts/intel/Makefile.files index aeddaa9203..5e819809fd 100644 --- a/usr/src/uts/intel/Makefile.files +++ b/usr/src/uts/intel/Makefile.files @@ -346,6 +346,7 @@ LX_BRAND_OBJS = \ lx_pipe.o \ lx_poll.o \ lx_prctl.o \ + lx_priority.o \ lx_ptrace.o \ lx_rename.o \ lx_rlimit.o \ |