NetBSD/sys/kern/kern_prot.c

714 lines
18 KiB
C
Raw Normal View History

/* $NetBSD: kern_prot.c,v 1.96 2006/11/01 10:17:58 yamt Exp $ */
1994-05-17 08:21:49 +04:00
/*
1994-05-19 09:57:44 +04:00
* Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
* The Regents of the University of California. All rights reserved.
1994-05-17 08:21:49 +04:00
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
1994-05-17 08:21:49 +04:00
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
1998-03-01 05:20:01 +03:00
* @(#)kern_prot.c 8.9 (Berkeley) 2/14/95
1994-05-17 08:21:49 +04:00
*/
/*
* System calls related to processes and protection
*/
2001-11-12 18:25:01 +03:00
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.96 2006/11/01 10:17:58 yamt Exp $");
2001-11-12 18:25:01 +03:00
1998-12-10 18:07:01 +03:00
#include "opt_compat_43.h"
1998-06-26 02:49:18 +04:00
1994-05-17 08:21:49 +04:00
#include <sys/param.h>
#include <sys/acct.h>
#include <sys/systm.h>
#include <sys/ucred.h>
#include <sys/proc.h>
#include <sys/timeb.h>
#include <sys/times.h>
#include <sys/pool.h>
#include <sys/syslog.h>
#include <sys/resourcevar.h>
2006-05-15 01:15:11 +04:00
#include <sys/kauth.h>
1994-05-17 08:21:49 +04:00
#include <sys/mount.h>
2003-01-18 13:06:22 +03:00
#include <sys/sa.h>
#include <sys/syscallargs.h>
2006-05-15 01:15:11 +04:00
#include <sys/malloc.h>
2003-01-18 13:06:22 +03:00
int sys_getpid(struct lwp *, void *, register_t *);
int sys_getpid_with_ppid(struct lwp *, void *, register_t *);
int sys_getuid(struct lwp *, void *, register_t *);
int sys_getuid_with_euid(struct lwp *, void *, register_t *);
int sys_getgid(struct lwp *, void *, register_t *);
int sys_getgid_with_egid(struct lwp *, void *, register_t *);
2000-12-09 10:17:32 +03:00
static int grsortu(gid_t *, int);
1994-05-17 08:21:49 +04:00
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_getpid(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
2003-01-18 13:06:22 +03:00
struct proc *p = l->l_proc;
1994-05-17 08:21:49 +04:00
*retval = p->p_pid;
return (0);
}
/* ARGSUSED */
int
sys_getpid_with_ppid(struct lwp *l, void *v, register_t *retval)
{
2003-01-18 13:06:22 +03:00
struct proc *p = l->l_proc;
retval[0] = p->p_pid;
retval[1] = p->p_pptr->p_pid;
1994-05-17 08:21:49 +04:00
return (0);
}
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_getppid(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
2003-01-18 13:06:22 +03:00
struct proc *p = l->l_proc;
1994-05-17 08:21:49 +04:00
*retval = p->p_pptr->p_pid;
return (0);
}
/* Get process group ID; note that POSIX getpgrp takes no parameter */
1996-02-04 05:15:01 +03:00
int
sys_getpgrp(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
2003-01-18 13:06:22 +03:00
struct proc *p = l->l_proc;
1994-05-17 08:21:49 +04:00
*retval = p->p_pgrp->pg_id;
return (0);
}
/*
* Return the process group ID of the session leader (session ID)
* for the specified process.
*/
int
2003-02-18 11:37:41 +03:00
sys_getsid(struct lwp *l, void *v, register_t *retval)
{
struct sys_getsid_args /* {
syscalldarg(pid_t) pid;
} */ *uap = v;
2003-01-18 13:06:22 +03:00
struct proc *p = l->l_proc;
if (SCARG(uap, pid) == 0)
goto found;
if ((p = pfind(SCARG(uap, pid))) == 0)
return (ESRCH);
found:
*retval = p->p_session->s_sid;
2000-10-18 03:38:55 +04:00
return (0);
}
int
2003-02-18 11:37:41 +03:00
sys_getpgid(struct lwp *l, void *v, register_t *retval)
{
2000-03-30 13:27:11 +04:00
struct sys_getpgid_args /* {
syscallarg(pid_t) pid;
} */ *uap = v;
2003-01-18 13:06:22 +03:00
struct proc *p = l->l_proc;
if (SCARG(uap, pid) == 0)
goto found;
if ((p = pfind(SCARG(uap, pid))) == 0)
return (ESRCH);
found:
*retval = p->p_pgid;
2000-10-18 03:38:55 +04:00
return (0);
}
1994-05-17 08:21:49 +04:00
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_getuid(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
*retval = kauth_cred_getuid(l->l_cred);
return (0);
}
/* ARGSUSED */
int
sys_getuid_with_euid(struct lwp *l, void *v, register_t *retval)
{
retval[0] = kauth_cred_getuid(l->l_cred);
retval[1] = kauth_cred_geteuid(l->l_cred);
1994-05-17 08:21:49 +04:00
return (0);
}
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_geteuid(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
*retval = kauth_cred_geteuid(l->l_cred);
1994-05-17 08:21:49 +04:00
return (0);
}
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_getgid(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
*retval = kauth_cred_getgid(l->l_cred);
return (0);
}
/* ARGSUSED */
int
sys_getgid_with_egid(struct lwp *l, void *v, register_t *retval)
{
retval[0] = kauth_cred_getgid(l->l_cred);
retval[1] = kauth_cred_getegid(l->l_cred);
1994-05-17 08:21:49 +04:00
return (0);
}
/*
* Get effective group ID. The "egid" is groups[0], and could be obtained
* via getgroups. This syscall exists because it is somewhat painful to do
* correctly in a library function.
*/
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_getegid(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
2003-03-01 02:24:40 +03:00
*retval = kauth_cred_getegid(l->l_cred);
1994-05-17 08:21:49 +04:00
return (0);
}
1996-02-04 05:15:01 +03:00
int
2003-02-18 11:37:41 +03:00
sys_getgroups(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
2000-03-30 13:27:11 +04:00
struct sys_getgroups_args /* {
syscallarg(int) gidsetsize;
syscallarg(gid_t *) gidset;
} */ *uap = v;
kauth_cred_t cred = l->l_cred;
u_int ngrp;
1994-05-17 08:21:49 +04:00
int error;
2006-05-15 01:15:11 +04:00
gid_t *grbuf;
1994-05-17 08:21:49 +04:00
if (SCARG(uap, gidsetsize) == 0) {
*retval = kauth_cred_ngroups(cred);
1994-05-17 08:21:49 +04:00
return (0);
} else if (SCARG(uap, gidsetsize) < 0)
return (EINVAL);
ngrp = SCARG(uap, gidsetsize);
if (ngrp < kauth_cred_ngroups(cred))
1994-05-17 08:21:49 +04:00
return (EINVAL);
ngrp = kauth_cred_ngroups(cred);
2006-05-15 01:15:11 +04:00
grbuf = malloc(ngrp * sizeof(*grbuf), M_TEMP, M_WAITOK);
kauth_cred_getgroups(cred, grbuf, ngrp);
2006-05-15 01:15:11 +04:00
error = copyout(grbuf, (caddr_t)SCARG(uap, gidset),
ngrp * sizeof(gid_t));
free(grbuf, M_TEMP);
1996-02-04 05:15:01 +03:00
if (error)
1994-05-17 08:21:49 +04:00
return (error);
*retval = ngrp;
return (0);
}
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_setsid(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
2003-01-18 13:06:22 +03:00
struct proc *p = l->l_proc;
1994-05-17 08:21:49 +04:00
if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
return (EPERM);
} else {
1994-05-19 09:57:44 +04:00
(void)enterpgrp(p, p->p_pid, 1);
1994-05-17 08:21:49 +04:00
*retval = p->p_pid;
return (0);
}
}
/*
* set process group (setpgid/old setpgrp)
*
* caller does setpgid(targpid, targpgid)
*
* pgid must be in valid range (EINVAL)
1994-05-17 08:21:49 +04:00
* pid must be caller or child of caller (ESRCH)
* if a child
* pid must be in same session (EPERM)
* pid can't have done an exec (EACCES)
* if pgid != pid
* there must exist some pid in same session having pgid (EPERM)
* pid must not be session leader (EPERM)
*
* Permission checks now in enterpgrp()
1994-05-17 08:21:49 +04:00
*/
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_setpgid(struct lwp *l, void *v, register_t *retval)
{
2000-03-30 13:27:11 +04:00
struct sys_setpgid_args /* {
syscallarg(int) pid;
syscallarg(int) pgid;
} */ *uap = v;
2003-01-18 13:06:22 +03:00
struct proc *curp = l->l_proc;
2000-03-30 13:27:11 +04:00
struct proc *targp; /* target process */
1994-05-17 08:21:49 +04:00
if (SCARG(uap, pgid) < 0)
return EINVAL;
/* XXX MP - there is a horrid race here with targp exiting! */
if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != curp->p_pid) {
targp = pfind(SCARG(uap, pid));
if (targp == NULL)
return ESRCH;
1994-05-17 08:21:49 +04:00
} else
targp = curp;
if (SCARG(uap, pgid) == 0)
SCARG(uap, pgid) = targp->p_pid;
return enterpgrp(targp, SCARG(uap, pgid), 0);
1994-05-17 08:21:49 +04:00
}
/*
* Set real, effective and saved uids to the requested values.
* non-root callers can only ever change uids to values that match
* one of the processes current uid values.
* This is further restricted by the flags argument.
*/
int
do_setresuid(struct lwp *l, uid_t r, uid_t e, uid_t sv, u_int flags)
{
struct proc *p = l->l_proc;
kauth_cred_t cred;
/* Get a write lock on the process credential. */
proc_crmod_enter(p);
cred = p->p_cred;
/*
* Check that the new value is one of the allowed existing values,
* or that we have root privilege.
*/
if ((r != -1
&& !((flags & ID_R_EQ_R) && r == kauth_cred_getuid(cred))
&& !((flags & ID_R_EQ_E) && r == kauth_cred_geteuid(cred))
&& !((flags & ID_R_EQ_S) && r == kauth_cred_getsvuid(cred))) ||
(e != -1
&& !((flags & ID_E_EQ_R) && e == kauth_cred_getuid(cred))
&& !((flags & ID_E_EQ_E) && e == kauth_cred_geteuid(cred))
&& !((flags & ID_E_EQ_S) && e == kauth_cred_getsvuid(cred))) ||
(sv != -1
&& !((flags & ID_S_EQ_R) && sv == kauth_cred_getuid(cred))
&& !((flags & ID_S_EQ_E) && sv == kauth_cred_geteuid(cred))
&& !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvuid(cred)))) {
int error;
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID,
p, NULL, NULL, NULL);
if (error != 0) {
proc_crmod_leave(p, cred, NULL);
return error;
}
}
/* If nothing has changed, short circuit the request */
2006-05-15 01:15:11 +04:00
if ((r == -1 || r == kauth_cred_getuid(cred))
&& (e == -1 || e == kauth_cred_geteuid(cred))
&& (sv == -1 || sv == kauth_cred_getsvuid(cred))) {
proc_crmod_leave(p, cred, NULL);
return 0;
}
cred = kauth_cred_dup(cred);
2006-05-15 01:15:11 +04:00
if (r != -1 && r != kauth_cred_getuid(cred)) {
/* Update count of processes for this user */
2006-05-15 01:15:11 +04:00
(void)chgproccnt(kauth_cred_getuid(cred), -1);
(void)chgproccnt(r, 1);
2006-05-15 01:15:11 +04:00
kauth_cred_setuid(cred, r);
}
if (sv != -1)
2006-05-15 01:15:11 +04:00
kauth_cred_setsvuid(cred, sv);
if (e != -1)
2006-05-15 01:15:11 +04:00
kauth_cred_seteuid(cred, e);
/* Mark process as having changed credentials, stops tracing etc. */
p_sugid(p);
/* Broadcast our credentials to the process and other LWPs. */
proc_crmod_leave(p, cred, p->p_cred);
/* Update our copy of the credentials. */
lwp_update_creds(l);
return 0;
}
/*
* Set real, effective and saved gids to the requested values.
* non-root callers can only ever change gids to values that match
* one of the processes current gid values.
* This is further restricted by the flags argument.
*/
int
do_setresgid(struct lwp *l, gid_t r, gid_t e, gid_t sv, u_int flags)
{
struct proc *p = l->l_proc;
kauth_cred_t cred;
/* Get a write lock on the process credential. */
proc_crmod_enter(p);
cred = p->p_cred;
/*
* check new value is one of the allowed existing values.
* otherwise, check if we have root privilege.
*/
if ((r != -1
&& !((flags & ID_R_EQ_R) && r == kauth_cred_getgid(cred))
&& !((flags & ID_R_EQ_E) && r == kauth_cred_getegid(cred))
&& !((flags & ID_R_EQ_S) && r == kauth_cred_getsvgid(cred))) ||
(e != -1
&& !((flags & ID_E_EQ_R) && e == kauth_cred_getgid(cred))
&& !((flags & ID_E_EQ_E) && e == kauth_cred_getegid(cred))
&& !((flags & ID_E_EQ_S) && e == kauth_cred_getsvgid(cred))) ||
(sv != -1
&& !((flags & ID_S_EQ_R) && sv == kauth_cred_getgid(cred))
&& !((flags & ID_S_EQ_E) && sv == kauth_cred_getegid(cred))
&& !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvgid(cred)))) {
int error;
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID,
p, NULL, NULL, NULL);
if (error != 0) {
proc_crmod_leave(p, cred, NULL);
return error;
}
}
/* If nothing has changed, short circuit the request */
2006-05-15 01:15:11 +04:00
if ((r == -1 || r == kauth_cred_getgid(cred))
&& (e == -1 || e == kauth_cred_getegid(cred))
&& (sv == -1 || sv == kauth_cred_getsvgid(cred))) {
proc_crmod_leave(p, cred, NULL);
return 0;
}
cred = kauth_cred_dup(cred);
if (r != -1)
2006-05-15 01:15:11 +04:00
kauth_cred_setgid(cred, r);
if (sv != -1)
2006-05-15 01:15:11 +04:00
kauth_cred_setsvgid(cred, sv);
if (e != -1)
2006-05-15 01:15:11 +04:00
kauth_cred_setegid(cred, e);
/* Mark process as having changed credentials, stops tracing etc. */
p_sugid(p);
/* Broadcast our credentials to the process and other LWPs. */
proc_crmod_leave(p, cred, p->p_cred);
/* Update our copy of the credentials. */
lwp_update_creds(l);
return 0;
}
1994-05-17 08:21:49 +04:00
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_setuid(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
struct sys_setuid_args /* {
syscallarg(uid_t) uid;
} */ *uap = v;
uid_t uid = SCARG(uap, uid);
1994-05-17 08:21:49 +04:00
return do_setresuid(l, uid, uid, uid,
ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R);
1994-05-17 08:21:49 +04:00
}
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_seteuid(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
struct sys_seteuid_args /* {
syscallarg(uid_t) euid;
} */ *uap = v;
return do_setresuid(l, -1, SCARG(uap, euid), -1, ID_E_EQ_R | ID_E_EQ_S);
1994-05-17 08:21:49 +04:00
}
int
sys_setreuid(struct lwp *l, void *v, register_t *retval)
{
struct sys_setreuid_args /* {
syscallarg(uid_t) ruid;
syscallarg(uid_t) euid;
} */ *uap = v;
kauth_cred_t cred = l->l_cred;
uid_t ruid, euid, svuid;
ruid = SCARG(uap, ruid);
euid = SCARG(uap, euid);
if (ruid == -1)
ruid = kauth_cred_getuid(cred);
if (euid == -1)
euid = kauth_cred_geteuid(cred);
/* Saved uid is set to the new euid if the ruid changed */
svuid = (ruid == kauth_cred_getuid(cred)) ? -1 : euid;
return do_setresuid(l, ruid, euid, svuid,
ID_R_EQ_R | ID_R_EQ_E |
ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S);
}
1994-05-17 08:21:49 +04:00
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_setgid(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
struct sys_setgid_args /* {
syscallarg(gid_t) gid;
} */ *uap = v;
gid_t gid = SCARG(uap, gid);
return do_setresgid(l, gid, gid, gid,
ID_R_EQ_R | ID_E_EQ_R | ID_S_EQ_R);
1994-05-17 08:21:49 +04:00
}
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_setegid(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
struct sys_setegid_args /* {
syscallarg(gid_t) egid;
} */ *uap = v;
return do_setresgid(l, -1, SCARG(uap, egid), -1, ID_E_EQ_R | ID_E_EQ_S);
1994-05-17 08:21:49 +04:00
}
int
sys_setregid(struct lwp *l, void *v, register_t *retval)
{
struct sys_setregid_args /* {
syscallarg(gid_t) rgid;
syscallarg(gid_t) egid;
} */ *uap = v;
kauth_cred_t cred = l->l_cred;
gid_t rgid, egid, svgid;
rgid = SCARG(uap, rgid);
egid = SCARG(uap, egid);
if (rgid == -1)
rgid = kauth_cred_getgid(cred);
if (egid == -1)
egid = kauth_cred_getegid(cred);
/* Saved gid is set to the new egid if the rgid changed */
svgid = rgid == kauth_cred_getgid(cred) ? -1 : egid;
return do_setresgid(l, rgid, egid, svgid,
ID_R_EQ_R | ID_R_EQ_E |
ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S);
}
int
sys_issetugid(struct lwp *l, void *v, register_t *retval)
{
2003-01-18 13:06:22 +03:00
struct proc *p = l->l_proc;
2003-03-01 02:24:40 +03:00
/*
* Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
* we use P_SUGID because we consider changing the owners as
* "tainting" as well.
* This is significant for procs that start as root and "become"
* a user without an exec - programs cannot know *everything*
* that libc *might* have put in their data segment.
*/
*retval = (p->p_flag & P_SUGID) != 0;
2000-10-18 03:38:55 +04:00
return (0);
}
/*
* sort -u for groups.
*/
static int
grsortu(gid_t *grp, int ngrp)
{
const gid_t *src, *end;
gid_t *dst;
gid_t group;
int i, j;
/* bubble sort */
for (i = 0; i < ngrp; i++)
for (j = i + 1; j < ngrp; j++)
if (grp[i] > grp[j]) {
gid_t tmp = grp[i];
grp[i] = grp[j];
grp[j] = tmp;
}
/* uniq */
end = grp + ngrp;
src = grp;
dst = grp;
while (src < end) {
group = *src++;
while (src < end && *src == group)
src++;
*dst++ = group;
}
#ifdef DIAGNOSTIC
/* zero out the rest of the array */
(void)memset(dst, 0, sizeof(*grp) * (end - dst));
#endif
return dst - grp;
}
1994-05-19 09:57:44 +04:00
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys_setgroups(struct lwp *l, void *v, register_t *retval)
{
struct sys_setgroups_args /* {
syscallarg(int) gidsetsize;
syscallarg(const gid_t *) gidset;
} */ *uap = v;
kauth_cred_t cred;
struct proc *p = l->l_proc;
2000-03-30 13:27:11 +04:00
int ngrp;
1994-05-19 09:57:44 +04:00
int error;
gid_t grp[NGROUPS];
size_t grsize;
1994-05-17 08:21:49 +04:00
proc_crmod_enter(p);
cred = p->p_cred;
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
if ((error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID,
p, NULL, NULL, NULL)) != 0)
goto bad;
ngrp = SCARG(uap, gidsetsize);
if ((u_int)ngrp > NGROUPS) {
error = EINVAL;
goto bad;
}
grsize = ngrp * sizeof(gid_t);
error = copyin(SCARG(uap, gidset), grp, grsize);
1996-02-04 05:15:01 +03:00
if (error)
goto bad;
ngrp = grsortu(grp, ngrp);
cred = kauth_cred_dup(cred);
kauth_cred_setgroups(cred, grp, ngrp, -1);
/* Mark process as having changed credentials, stops tracing etc. */
p_sugid(p);
/* Broadcast our credentials to the process and other LWPs. */
proc_crmod_leave(p, cred, p->p_cred);
/* Update our copy of the credentials. */
lwp_update_creds(l);
1994-05-17 08:21:49 +04:00
return (0);
bad:
proc_crmod_leave(p, cred, NULL);
return (error);
1994-05-17 08:21:49 +04:00
}
/*
* Get login name, if available.
*/
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys___getlogin(struct lwp *l, void *v, register_t *retval)
{
struct sys___getlogin_args /* {
syscallarg(char *) namebuf;
syscallarg(size_t) namelen;
} */ *uap = v;
2003-01-18 13:06:22 +03:00
struct proc *p = l->l_proc;
1994-05-17 08:21:49 +04:00
if (SCARG(uap, namelen) > sizeof(p->p_pgrp->pg_session->s_login))
SCARG(uap, namelen) = sizeof(p->p_pgrp->pg_session->s_login);
1994-05-17 08:21:49 +04:00
return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
(caddr_t) SCARG(uap, namebuf), SCARG(uap, namelen)));
1994-05-17 08:21:49 +04:00
}
/*
* Set login name.
*/
/* ARGSUSED */
1996-02-04 05:15:01 +03:00
int
sys___setlogin(struct lwp *l, void *v, register_t *retval)
1994-05-17 08:21:49 +04:00
{
2003-01-18 13:06:22 +03:00
struct sys___setlogin_args /* {
syscallarg(const char *) namebuf;
} */ *uap = v;
2003-01-18 13:06:22 +03:00
struct proc *p = l->l_proc;
struct session *s = p->p_pgrp->pg_session;
char newname[sizeof s->s_login + 1];
1994-05-17 08:21:49 +04:00
int error;
First take at security model abstraction. - Add a few scopes to the kernel: system, network, and machdep. - Add a few more actions/sub-actions (requests), and start using them as opposed to the KAUTH_GENERIC_ISSUSER place-holders. - Introduce a basic set of listeners that implement our "traditional" security model, called "bsd44". This is the default (and only) model we have at the moment. - Update all relevant documentation. - Add some code and docs to help folks who want to actually use this stuff: * There's a sample overlay model, sitting on-top of "bsd44", for fast experimenting with tweaking just a subset of an existing model. This is pretty cool because it's *really* straightforward to do stuff you had to use ugly hacks for until now... * And of course, documentation describing how to do the above for quick reference, including code samples. All of these changes were tested for regressions using a Python-based testsuite that will be (I hope) available soon via pkgsrc. Information about the tests, and how to write new ones, can be found on: http://kauth.linbsd.org/kauthwiki NOTE FOR DEVELOPERS: *PLEASE* don't add any code that does any of the following: - Uses a KAUTH_GENERIC_ISSUSER kauth(9) request, - Checks 'securelevel' directly, - Checks a uid/gid directly. (or if you feel you have to, contact me first) This is still work in progress; It's far from being done, but now it'll be a lot easier. Relevant mailing list threads: http://mail-index.netbsd.org/tech-security/2006/01/25/0011.html http://mail-index.netbsd.org/tech-security/2006/03/24/0001.html http://mail-index.netbsd.org/tech-security/2006/04/18/0000.html http://mail-index.netbsd.org/tech-security/2006/05/15/0000.html http://mail-index.netbsd.org/tech-security/2006/08/01/0000.html http://mail-index.netbsd.org/tech-security/2006/08/25/0000.html Many thanks to YAMAMOTO Takashi, Matt Thomas, and Christos Zoulas for help stablizing kauth(9). Full credit for the regression tests, making sure these changes didn't break anything, goes to Matt Fleming and Jaime Fournier. Happy birthday Randi! :)
2006-09-09 00:58:56 +04:00
if ((error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_SETID,
p, NULL, NULL, NULL)) != 0)
1994-05-17 08:21:49 +04:00
return (error);
error = copyinstr(SCARG(uap, namebuf), &newname, sizeof newname, NULL);
if (error != 0)
2003-03-01 02:24:40 +03:00
return (error == ENAMETOOLONG ? EINVAL : error);
if (s->s_flags & S_LOGIN_SET && p->p_pid != s->s_sid &&
strncmp(newname, s->s_login, sizeof s->s_login) != 0)
log(LOG_WARNING, "%s (pid %d) changing logname from "
"%.*s to %s\n", p->p_comm, p->p_pid,
(int)sizeof s->s_login, s->s_login, newname);
s->s_flags |= S_LOGIN_SET;
strncpy(s->s_login, newname, sizeof s->s_login);
2003-03-01 02:24:40 +03:00
return (0);
1994-05-17 08:21:49 +04:00
}