180708Sjake/*-
280708Sjake * Copyright (c) 2001 Jake Burkholder.
380708Sjake * All rights reserved.
480708Sjake *
580708Sjake * Redistribution and use in source and binary forms, with or without
680708Sjake * modification, are permitted provided that the following conditions
780708Sjake * are met:
880708Sjake * 1. Redistributions of source code must retain the above copyright
980708Sjake *    notice, this list of conditions and the following disclaimer.
1080708Sjake * 2. Redistributions in binary form must reproduce the above copyright
1180708Sjake *    notice, this list of conditions and the following disclaimer in the
1280708Sjake *    documentation and/or other materials provided with the distribution.
1380708Sjake *
1481337Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1580708Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1680708Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1781337Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1880708Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1980708Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2080708Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2180708Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2280708Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2380708Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2480708Sjake * SUCH DAMAGE.
2580708Sjake *
2680708Sjake * $FreeBSD$
2780708Sjake */
2880708Sjake
29223692Sjonathan#include "opt_capsicum.h"
30223692Sjonathan
3180708Sjake#include <sys/param.h>
3288782Sjake#include <sys/systm.h>
33223692Sjonathan#include <sys/capability.h>
34114029Sjhb#include <sys/lock.h>
3588782Sjake#include <sys/malloc.h>
36114029Sjhb#include <sys/mutex.h>
3780708Sjake#include <sys/proc.h>
3880708Sjake#include <sys/sysproto.h>
3980708Sjake
40140485Sjhb#include <machine/md_var.h>
4188782Sjake#include <machine/utrap.h>
4288782Sjake#include <machine/sysarch.h>
4388782Sjake
4495744Sjakestatic int sparc_sigtramp_install(struct thread *td, char *args);
4588782Sjakestatic int sparc_utrap_install(struct thread *td, char *args);
4688782Sjake
4780708Sjake#ifndef	_SYS_SYSPROTO_H_
4883088Sobrienstruct sysarch_args {
4980708Sjake	int	op;
5080708Sjake	char	*parms;
5180708Sjake};
5280708Sjake#endif
5380708Sjake
5480708Sjakeint
5583366Sjuliansysarch(struct thread *td, struct sysarch_args *uap)
5680708Sjake{
5788782Sjake	int error;
5888782Sjake
59223692Sjonathan#ifdef CAPABILITY_MODE
60223692Sjonathan	/*
61223692Sjonathan	 * When adding new operations, add a new case statement here to
62223692Sjonathan	 * explicitly indicate whether or not the operation is safe to
63223692Sjonathan	 * perform in capability mode.
64223692Sjonathan	 */
65223692Sjonathan	if (IN_CAPABILITY_MODE(td)) {
66223692Sjonathan		switch (uap->op) {
67223692Sjonathan		case SPARC_SIGTRAMP_INSTALL:
68223692Sjonathan		case SPARC_UTRAP_INSTALL:
69223692Sjonathan			break;
70223692Sjonathan
71223692Sjonathan		default:
72223692Sjonathan			return (ECAPMODE);
73223692Sjonathan		}
74223692Sjonathan	}
75223692Sjonathan#endif
76223692Sjonathan
77114029Sjhb	mtx_lock(&Giant);
7888782Sjake	switch (uap->op) {
7995744Sjake	case SPARC_SIGTRAMP_INSTALL:
8095744Sjake		error = sparc_sigtramp_install(td, uap->parms);
8195744Sjake		break;
8288782Sjake	case SPARC_UTRAP_INSTALL:
8388782Sjake		error = sparc_utrap_install(td, uap->parms);
8488782Sjake		break;
8588782Sjake	default:
8688782Sjake		error = EINVAL;
8788782Sjake		break;
8888782Sjake	}
89114029Sjhb	mtx_unlock(&Giant);
9088782Sjake	return (error);
9180708Sjake}
9288782Sjake
9388782Sjakestatic int
9495744Sjakesparc_sigtramp_install(struct thread *td, char *args)
9595744Sjake{
9695744Sjake	struct sparc_sigtramp_install_args sia;
9795744Sjake	struct proc *p;
9895744Sjake	int error;
9995744Sjake
10095744Sjake	p = td->td_proc;
10195744Sjake	if ((error = copyin(args, &sia, sizeof(sia))) != 0)
10295744Sjake		return (error);
10395744Sjake	if (sia.sia_old != NULL) {
10495744Sjake		if (suword(sia.sia_old, (long)p->p_md.md_sigtramp) != 0)
10595744Sjake			return (EFAULT);
10695744Sjake	}
10795744Sjake	p->p_md.md_sigtramp = sia.sia_new;
10895744Sjake	return (0);
10995744Sjake}
11095744Sjake
11195744Sjakestatic int
11288782Sjakesparc_utrap_install(struct thread *td, char *args)
11388782Sjake{
11488782Sjake	struct sparc_utrap_install_args uia;
11588782Sjake	struct sparc_utrap_args ua;
11688782Sjake	struct md_utrap *ut;
11788782Sjake	int error;
11888782Sjake	int i;
11988782Sjake
12088782Sjake	ut = td->td_proc->p_md.md_utrap;
12188782Sjake	if ((error = copyin(args, &uia, sizeof(uia))) != 0)
12288782Sjake		return (error);
12388782Sjake	if (uia.num < 0 || uia.num > UT_MAX ||
12488782Sjake	    (uia.handlers == NULL && uia.num > 0))
12588782Sjake		return (EINVAL);
12688782Sjake	for (i = 0; i < uia.num; i++) {
12788782Sjake		if ((error = copyin(&uia.handlers[i], &ua, sizeof(ua))) != 0)
12888782Sjake			return (error);
12988782Sjake		if (ua.type != UTH_NOCHANGE &&
13088782Sjake		    (ua.type < 0 || ua.type >= UT_MAX))
13188782Sjake			return (EINVAL);
13288782Sjake		if (ua.old_deferred != NULL) {
13388782Sjake			if ((error = suword(ua.old_deferred, 0)) != 0)
13488782Sjake				return (error);
13588782Sjake		}
13688782Sjake		if (ua.old_precise != NULL) {
13788782Sjake			error = suword(ua.old_precise,
13888782Sjake			    ut != NULL ? (long)ut->ut_precise[ua.type] : 0);
13988782Sjake			if (error != 0)
14088782Sjake				return (error);
14188782Sjake		}
14288782Sjake		if (ua.type != UTH_NOCHANGE) {
14388782Sjake			if (ut == NULL) {
144140485Sjhb				ut = utrap_alloc();
14588782Sjake				td->td_proc->p_md.md_utrap = ut;
14688782Sjake			}
14788782Sjake			ut->ut_precise[ua.type] = ua.new_precise;
14888782Sjake		}
14988782Sjake	}
15088782Sjake	return (0);
15188782Sjake}
152