xref: /freebsd/sys/kern/p1003_1b.c (revision 64e55bf47b27fa7c7a225f41dc46770807d76896)
18a6472b7SPeter Dufault /*
28a6472b7SPeter Dufault  * Copyright (c) 1996, 1997, 1998
38a6472b7SPeter Dufault  *	HD Associates, Inc.  All rights reserved.
48a6472b7SPeter Dufault  *
58a6472b7SPeter Dufault  * Redistribution and use in source and binary forms, with or without
68a6472b7SPeter Dufault  * modification, are permitted provided that the following conditions
78a6472b7SPeter Dufault  * are met:
88a6472b7SPeter Dufault  * 1. Redistributions of source code must retain the above copyright
98a6472b7SPeter Dufault  *    notice, this list of conditions and the following disclaimer.
108a6472b7SPeter Dufault  * 2. Redistributions in binary form must reproduce the above copyright
118a6472b7SPeter Dufault  *    notice, this list of conditions and the following disclaimer in the
128a6472b7SPeter Dufault  *    documentation and/or other materials provided with the distribution.
138a6472b7SPeter Dufault  * 3. All advertising materials mentioning features or use of this software
148a6472b7SPeter Dufault  *    must display the following acknowledgement:
158a6472b7SPeter Dufault  *	This product includes software developed by HD Associates, Inc
168a6472b7SPeter Dufault  * 4. Neither the name of the author nor the names of any co-contributors
178a6472b7SPeter Dufault  *    may be used to endorse or promote products derived from this software
188a6472b7SPeter Dufault  *    without specific prior written permission.
198a6472b7SPeter Dufault  *
208a6472b7SPeter Dufault  * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND
218a6472b7SPeter Dufault  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
228a6472b7SPeter Dufault  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238a6472b7SPeter Dufault  * ARE DISCLAIMED.  IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
248a6472b7SPeter Dufault  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
258a6472b7SPeter Dufault  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
268a6472b7SPeter Dufault  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
278a6472b7SPeter Dufault  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
288a6472b7SPeter Dufault  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
298a6472b7SPeter Dufault  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
308a6472b7SPeter Dufault  * SUCH DAMAGE.
318a6472b7SPeter Dufault  *
32365c5db0SPeter Wemm  * $FreeBSD$
338a6472b7SPeter Dufault  */
348a6472b7SPeter Dufault 
358a6472b7SPeter Dufault /* p1003_1b: Real Time common code.
368a6472b7SPeter Dufault  */
378a6472b7SPeter Dufault 
388a6472b7SPeter Dufault #include <sys/param.h>
398a6472b7SPeter Dufault #include <sys/systm.h>
408a6472b7SPeter Dufault #include <sys/kernel.h>
41fb919e4dSMark Murray #include <sys/lock.h>
428a6472b7SPeter Dufault #include <sys/module.h>
43fb919e4dSMark Murray #include <sys/mutex.h>
44fb919e4dSMark Murray #include <sys/proc.h>
458a6472b7SPeter Dufault #include <sys/sysctl.h>
46fb919e4dSMark Murray #include <sys/sysent.h>
47fb919e4dSMark Murray #include <sys/syslog.h>
48fb919e4dSMark Murray #include <sys/sysproto.h>
498a6472b7SPeter Dufault 
508a6472b7SPeter Dufault #include <posix4/posix4.h>
518a6472b7SPeter Dufault 
528a6472b7SPeter Dufault MALLOC_DEFINE(M_P31B, "p1003.1b", "Posix 1003.1B");
538a6472b7SPeter Dufault 
548a6472b7SPeter Dufault /* p31b_proc: Return a proc struct corresponding to a pid to operate on.
558a6472b7SPeter Dufault  *
568a6472b7SPeter Dufault  * Enforce permission policy.
578a6472b7SPeter Dufault  *
588a6472b7SPeter Dufault  * The policy is the same as for sending signals except there
598a6472b7SPeter Dufault  * is no notion of process groups.
608a6472b7SPeter Dufault  *
618a6472b7SPeter Dufault  * pid == 0 means my process.
628a6472b7SPeter Dufault  *
638a6472b7SPeter Dufault  * This is disabled until I've got a permission gate in again:
648a6472b7SPeter Dufault  * only root can do this.
658a6472b7SPeter Dufault  */
668a6472b7SPeter Dufault 
678a6472b7SPeter Dufault #if 0
688a6472b7SPeter Dufault /*
698a6472b7SPeter Dufault  * This is stolen from CANSIGNAL in kern_sig:
708a6472b7SPeter Dufault  *
71b1fc0ec1SRobert Watson  * Can process with credential cr1 do "write flavor" operations to credential
72b1fc0ec1SRobert Watson  * cr2.  This check needs to use generalized checks.
738a6472b7SPeter Dufault  */
74b1fc0ec1SRobert Watson #define CAN_AFFECT(cr1, cr2) \
75b1fc0ec1SRobert Watson 	(!suser_xxx(cr1, NULL, PRISON_ROOT) || \
76b1fc0ec1SRobert Watson 	    (c1)->cr_ruid == (cr2)->cr_ruid || \
77b1fc0ec1SRobert Watson 	    (c1)->cr_uid == (cr2)->cr_ruid || \
78b1fc0ec1SRobert Watson 	    (c1)->cr_ruid == (cr2)->cr_uid || \
79b1fc0ec1SRobert Watson 	    (c1)->cr_uid == (cr2)->cr_uid)
808a6472b7SPeter Dufault #else
81b1fc0ec1SRobert Watson #define CAN_AFFECT(cr1, cr2) (!suser_xxx(cr1, NULL, PRISON_ROOT))
828a6472b7SPeter Dufault #endif
838a6472b7SPeter Dufault 
848a6472b7SPeter Dufault /*
858a6472b7SPeter Dufault  * p31b_proc: Look up a proc from a PID.  If proc is 0 it is
868a6472b7SPeter Dufault  * my own proc.
878a6472b7SPeter Dufault  */
888a6472b7SPeter Dufault int p31b_proc(struct proc *p, pid_t pid, struct proc **pp)
898a6472b7SPeter Dufault {
908a6472b7SPeter Dufault 	int ret = 0;
918a6472b7SPeter Dufault 	struct proc *other_proc = 0;
928a6472b7SPeter Dufault 
9333a9ed9dSJohn Baldwin 	if (pid == 0) {
948a6472b7SPeter Dufault 		other_proc = p;
9533a9ed9dSJohn Baldwin 		PROC_LOCK(p);
9633a9ed9dSJohn Baldwin 	} else
978a6472b7SPeter Dufault 		other_proc = pfind(pid);
988a6472b7SPeter Dufault 
998a6472b7SPeter Dufault 	if (other_proc)
1008a6472b7SPeter Dufault 	{
1018a6472b7SPeter Dufault 		/* Enforce permission policy.
1028a6472b7SPeter Dufault 		 */
103b1fc0ec1SRobert Watson 		if (CAN_AFFECT(p->p_ucred, other_proc->p_ucred))
1048a6472b7SPeter Dufault 			*pp = other_proc;
1058a6472b7SPeter Dufault 		else
1068a6472b7SPeter Dufault 			ret = EPERM;
10733a9ed9dSJohn Baldwin 		PROC_UNLOCK(other_proc);
1088a6472b7SPeter Dufault 	}
1098a6472b7SPeter Dufault 	else
1108a6472b7SPeter Dufault 		ret = ESRCH;
1118a6472b7SPeter Dufault 
1128a6472b7SPeter Dufault 	return ret;
1138a6472b7SPeter Dufault }
1148a6472b7SPeter Dufault 
1152a61a110SPeter Dufault /* The system calls return ENOSYS if an entry is called that is
1162a61a110SPeter Dufault  * not run-time supported.  I am also logging since some programs
1172a61a110SPeter Dufault  * start to use this when they shouldn't.  That will be removed if annoying.
1182a61a110SPeter Dufault  */
1198a6472b7SPeter Dufault int
1208a6472b7SPeter Dufault syscall_not_present(struct proc *p, const char *s, struct nosys_args *uap)
1218a6472b7SPeter Dufault {
1228a6472b7SPeter Dufault 	log(LOG_ERR, "cmd %s pid %d tried to use non-present %s\n",
1238a6472b7SPeter Dufault 			p->p_comm, p->p_pid, s);
1242a61a110SPeter Dufault 
1252a61a110SPeter Dufault 	/* a " return nosys(p, uap); " here causes a core dump.
1262a61a110SPeter Dufault 	 */
1272a61a110SPeter Dufault 
1282a61a110SPeter Dufault 	return ENOSYS;
1298a6472b7SPeter Dufault }
1308a6472b7SPeter Dufault 
1318a6472b7SPeter Dufault #if !defined(_KPOSIX_PRIORITY_SCHEDULING)
1328a6472b7SPeter Dufault 
133e9189611SPeter Wemm /* Not configured but loadable via a module:
1348a6472b7SPeter Dufault  */
1358a6472b7SPeter Dufault 
1368a6472b7SPeter Dufault static int sched_attach(void)
1378a6472b7SPeter Dufault {
1388a6472b7SPeter Dufault 	return 0;
1398a6472b7SPeter Dufault }
1408a6472b7SPeter Dufault 
1418a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_setparam)
1428a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_getparam)
1438a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_setscheduler)
1448a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_getscheduler)
1458a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_yield)
1468a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_get_priority_max)
1478a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_get_priority_min)
1488a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_rr_get_interval)
1498a6472b7SPeter Dufault 
1508a6472b7SPeter Dufault #else
1518a6472b7SPeter Dufault 
1528a6472b7SPeter Dufault /* Configured in kernel version:
1538a6472b7SPeter Dufault  */
1548a6472b7SPeter Dufault static struct ksched *ksched;
1558a6472b7SPeter Dufault 
1568a6472b7SPeter Dufault static int sched_attach(void)
1578a6472b7SPeter Dufault {
1588a6472b7SPeter Dufault 	int ret = ksched_attach(&ksched);
1598a6472b7SPeter Dufault 
1608a6472b7SPeter Dufault 	if (ret == 0)
1618a6472b7SPeter Dufault 		p31b_setcfg(CTL_P1003_1B_PRIORITY_SCHEDULING, 1);
1628a6472b7SPeter Dufault 
1638a6472b7SPeter Dufault 	return ret;
1648a6472b7SPeter Dufault }
1658a6472b7SPeter Dufault 
1668a6472b7SPeter Dufault int sched_setparam(struct proc *p,
1678a6472b7SPeter Dufault 	struct sched_setparam_args *uap)
1688a6472b7SPeter Dufault {
1698a6472b7SPeter Dufault 	int e;
1708a6472b7SPeter Dufault 
171aebde782SPeter Dufault 	struct sched_param sched_param;
172e8f7a952SRobert Watson 	e = copyin(uap->param, &sched_param, sizeof(sched_param));
173e8f7a952SRobert Watson 	if (e)
174e8f7a952SRobert Watson 		return (e);
175aebde782SPeter Dufault 
17664e55bf4SRobert Watson 	e = p31b_proc(p, uap->pid, &p);
17764e55bf4SRobert Watson 	if (e)
17864e55bf4SRobert Watson 		return (e);
17964e55bf4SRobert Watson 	e = ksched_setparam(&p->p_retval[0], ksched, p,
18064e55bf4SRobert Watson 		(const struct sched_param *)&sched_param);
18164e55bf4SRobert Watson 	return (e);
1828a6472b7SPeter Dufault }
1838a6472b7SPeter Dufault 
1848a6472b7SPeter Dufault int sched_getparam(struct proc *p,
1858a6472b7SPeter Dufault 	struct sched_getparam_args *uap)
1868a6472b7SPeter Dufault {
1878a6472b7SPeter Dufault 	int e;
188aebde782SPeter Dufault 	struct sched_param sched_param;
1898a6472b7SPeter Dufault 
19064e55bf4SRobert Watson 	e = p31b_proc(p, uap->pid, &p);
19164e55bf4SRobert Watson 	if (e)
19264e55bf4SRobert Watson 		return (e);
19364e55bf4SRobert Watson 	e = ksched_getparam(&p->p_retval[0], ksched, p, &sched_param);
19464e55bf4SRobert Watson 	if (e)
19564e55bf4SRobert Watson 		return (e);
1968a6472b7SPeter Dufault 
19764e55bf4SRobert Watson 	e = copyout(&sched_param, uap->param, sizeof(sched_param));
19864e55bf4SRobert Watson 	return (e);
1998a6472b7SPeter Dufault }
2008a6472b7SPeter Dufault int sched_setscheduler(struct proc *p,
2018a6472b7SPeter Dufault 	struct sched_setscheduler_args *uap)
2028a6472b7SPeter Dufault {
2038a6472b7SPeter Dufault 	int e;
204aebde782SPeter Dufault 
205aebde782SPeter Dufault 	struct sched_param sched_param;
206e8f7a952SRobert Watson 	e = copyin(uap->param, &sched_param, sizeof(sched_param));
207e8f7a952SRobert Watson 	if (e)
208e8f7a952SRobert Watson 		return (e);
209aebde782SPeter Dufault 
21064e55bf4SRobert Watson 	e = p31b_proc(p, uap->pid, &p);
21164e55bf4SRobert Watson 	if (e)
21264e55bf4SRobert Watson 		return (e);
21364e55bf4SRobert Watson 	e = ksched_setscheduler(&p->p_retval[0], ksched, p, uap->policy,
21464e55bf4SRobert Watson 		(const struct sched_param *)&sched_param);
2158a6472b7SPeter Dufault 
21664e55bf4SRobert Watson 	return (e);
2178a6472b7SPeter Dufault }
2188a6472b7SPeter Dufault int sched_getscheduler(struct proc *p,
2198a6472b7SPeter Dufault 	struct sched_getscheduler_args *uap)
2208a6472b7SPeter Dufault {
2218a6472b7SPeter Dufault 	int e;
2228a6472b7SPeter Dufault 
22364e55bf4SRobert Watson 	e = p31b_proc(p, uap->pid, &p);
22464e55bf4SRobert Watson 	if (e)
22564e55bf4SRobert Watson 		return (e);
22664e55bf4SRobert Watson 	e = ksched_getscheduler(&p->p_retval[0], ksched, p);
22764e55bf4SRobert Watson 
22864e55bf4SRobert Watson 	return (e);
2298a6472b7SPeter Dufault }
2308a6472b7SPeter Dufault int sched_yield(struct proc *p,
2318a6472b7SPeter Dufault 	struct sched_yield_args *uap)
2328a6472b7SPeter Dufault {
2338a6472b7SPeter Dufault 	return ksched_yield(&p->p_retval[0], ksched);
2348a6472b7SPeter Dufault }
2358a6472b7SPeter Dufault int sched_get_priority_max(struct proc *p,
2368a6472b7SPeter Dufault 	struct sched_get_priority_max_args *uap)
2378a6472b7SPeter Dufault {
2388a6472b7SPeter Dufault 	return ksched_get_priority_max(&p->p_retval[0],
2398a6472b7SPeter Dufault 	ksched, uap->policy);
2408a6472b7SPeter Dufault }
2418a6472b7SPeter Dufault int sched_get_priority_min(struct proc *p,
2428a6472b7SPeter Dufault 	struct sched_get_priority_min_args *uap)
2438a6472b7SPeter Dufault {
2448a6472b7SPeter Dufault 	return ksched_get_priority_min(&p->p_retval[0],
2458a6472b7SPeter Dufault 	ksched, uap->policy);
2468a6472b7SPeter Dufault }
2478a6472b7SPeter Dufault int sched_rr_get_interval(struct proc *p,
2488a6472b7SPeter Dufault 	struct sched_rr_get_interval_args *uap)
2498a6472b7SPeter Dufault {
2508a6472b7SPeter Dufault 	int e;
2518a6472b7SPeter Dufault 
25264e55bf4SRobert Watson 	e = p31b_proc(p, uap->pid, &p);
25364e55bf4SRobert Watson 	if (e)
25464e55bf4SRobert Watson 		return (e);
25564e55bf4SRobert Watson 	e = ksched_rr_get_interval(&p->p_retval[0], ksched, p, uap->interval);
2568a6472b7SPeter Dufault 
25764e55bf4SRobert Watson 	return (e);
2588a6472b7SPeter Dufault }
2598a6472b7SPeter Dufault 
2608a6472b7SPeter Dufault #endif
2618a6472b7SPeter Dufault 
2628a6472b7SPeter Dufault static void p31binit(void *notused)
2638a6472b7SPeter Dufault {
2648a6472b7SPeter Dufault 	(void) sched_attach();
265ce47711dSPeter Dufault 	p31b_setcfg(CTL_P1003_1B_PAGESIZE, PAGE_SIZE);
2668a6472b7SPeter Dufault }
2678a6472b7SPeter Dufault 
2688a6472b7SPeter Dufault SYSINIT(p31b, SI_SUB_P1003_1B, SI_ORDER_FIRST, p31binit, NULL);
269