2006-11-01 13:17:58 +03:00
|
|
|
/* $NetBSD: kern_prot.c,v 1.96 2006/11/01 10:17:58 yamt Exp $ */
|
1994-06-29 10:29:24 +04:00
|
|
|
|
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.
|
2003-08-07 20:26:28 +04:00
|
|
|
* 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>
|
2006-11-01 13:17:58 +03:00
|
|
|
__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>
|
2004-04-25 20:42:40 +04:00
|
|
|
#include <sys/pool.h>
|
2003-02-15 21:10:15 +03:00
|
|
|
#include <sys/syslog.h>
|
2004-04-17 19:15:29 +04:00
|
|
|
#include <sys/resourcevar.h>
|
2006-05-15 01:15:11 +04:00
|
|
|
#include <sys/kauth.h>
|
1994-05-17 08:21:49 +04:00
|
|
|
|
1994-10-20 07:22:35 +03:00
|
|
|
#include <sys/mount.h>
|
2003-01-18 13:06:22 +03:00
|
|
|
#include <sys/sa.h>
|
1994-10-20 07:22:35 +03:00
|
|
|
#include <sys/syscallargs.h>
|
|
|
|
|
2006-05-15 01:15:11 +04:00
|
|
|
#include <sys/malloc.h>
|
2003-02-01 09:23:35 +03:00
|
|
|
|
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
|
|
|
|
2005-08-23 11:58:58 +04: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
|
2006-11-01 13:17:58 +03:00
|
|
|
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;
|
2000-12-09 10:04:47 +03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_getpid_with_ppid(struct lwp *l, void *v, register_t *retval)
|
2000-12-09 10:04:47 +03:00
|
|
|
{
|
2003-01-18 13:06:22 +03:00
|
|
|
struct proc *p = l->l_proc;
|
2000-12-09 10:04:47 +03:00
|
|
|
|
|
|
|
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
|
2006-11-01 13:17:58 +03:00
|
|
|
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
|
2006-11-01 13:17:58 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
1998-02-14 04:17:51 +03:00
|
|
|
/*
|
|
|
|
* 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)
|
1998-02-14 04:17:51 +03:00
|
|
|
{
|
|
|
|
struct sys_getsid_args /* {
|
|
|
|
syscalldarg(pid_t) pid;
|
|
|
|
} */ *uap = v;
|
2003-01-18 13:06:22 +03:00
|
|
|
struct proc *p = l->l_proc;
|
1998-02-14 04:17:51 +03:00
|
|
|
|
|
|
|
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);
|
1998-02-14 04:17:51 +03:00
|
|
|
}
|
|
|
|
|
1996-08-09 14:30:23 +04:00
|
|
|
int
|
2003-02-18 11:37:41 +03:00
|
|
|
sys_getpgid(struct lwp *l, void *v, register_t *retval)
|
1996-08-09 14:30:23 +04:00
|
|
|
{
|
2000-03-30 13:27:11 +04:00
|
|
|
struct sys_getpgid_args /* {
|
1996-08-09 14:30:23 +04:00
|
|
|
syscallarg(pid_t) pid;
|
|
|
|
} */ *uap = v;
|
2003-01-18 13:06:22 +03:00
|
|
|
struct proc *p = l->l_proc;
|
1996-08-09 14:30:23 +04:00
|
|
|
|
|
|
|
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);
|
1996-08-09 14:30:23 +04:00
|
|
|
}
|
|
|
|
|
1994-05-17 08:21:49 +04:00
|
|
|
/* ARGSUSED */
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_getuid(struct lwp *l, void *v, register_t *retval)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
|
|
|
|
2006-07-20 01:11:37 +04:00
|
|
|
*retval = kauth_cred_getuid(l->l_cred);
|
2000-12-09 10:04:47 +03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_getuid_with_euid(struct lwp *l, void *v, register_t *retval)
|
2000-12-09 10:04:47 +03:00
|
|
|
{
|
|
|
|
|
2006-07-20 01:11:37 +04:00
|
|
|
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
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_geteuid(struct lwp *l, void *v, register_t *retval)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
|
|
|
|
2006-07-20 01:11:37 +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
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_getgid(struct lwp *l, void *v, register_t *retval)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
|
|
|
|
2006-07-20 01:11:37 +04:00
|
|
|
*retval = kauth_cred_getgid(l->l_cred);
|
2000-12-09 10:04:47 +03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_getgid_with_egid(struct lwp *l, void *v, register_t *retval)
|
2000-12-09 10:04:47 +03:00
|
|
|
{
|
|
|
|
|
2006-07-20 01:11:37 +04:00
|
|
|
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
|
2006-11-01 13:17:58 +03:00
|
|
|
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
|
|
|
|
2006-07-20 01:11:37 +04: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 /* {
|
1997-11-05 00:24:14 +03:00
|
|
|
syscallarg(int) gidsetsize;
|
1995-09-20 01:40:36 +04:00
|
|
|
syscallarg(gid_t *) gidset;
|
|
|
|
} */ *uap = v;
|
2006-07-20 01:11:37 +04:00
|
|
|
kauth_cred_t cred = l->l_cred;
|
2002-08-26 01:30:40 +04:00
|
|
|
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
|
|
|
|
2002-08-26 01:30:40 +04:00
|
|
|
if (SCARG(uap, gidsetsize) == 0) {
|
2006-07-20 01:11:37 +04:00
|
|
|
*retval = kauth_cred_ngroups(cred);
|
1994-05-17 08:21:49 +04:00
|
|
|
return (0);
|
2002-08-26 01:30:40 +04:00
|
|
|
} else if (SCARG(uap, gidsetsize) < 0)
|
|
|
|
return (EINVAL);
|
|
|
|
ngrp = SCARG(uap, gidsetsize);
|
2006-07-20 01:11:37 +04:00
|
|
|
if (ngrp < kauth_cred_ngroups(cred))
|
1994-05-17 08:21:49 +04:00
|
|
|
return (EINVAL);
|
2006-07-20 01:11:37 +04:00
|
|
|
ngrp = kauth_cred_ngroups(cred);
|
2006-05-15 01:15:11 +04:00
|
|
|
|
|
|
|
grbuf = malloc(ngrp * sizeof(*grbuf), M_TEMP, M_WAITOK);
|
2006-07-20 01:11:37 +04:00
|
|
|
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
|
2006-11-01 13:17:58 +03:00
|
|
|
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)
|
|
|
|
*
|
1997-03-27 09:14:03 +03:00
|
|
|
* 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)
|
2003-03-19 14:36:32 +03:00
|
|
|
*
|
|
|
|
* Permission checks now in enterpgrp()
|
1994-05-17 08:21:49 +04:00
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_setpgid(struct lwp *l, void *v, register_t *retval)
|
1995-09-20 01:40:36 +04:00
|
|
|
{
|
2000-03-30 13:27:11 +04:00
|
|
|
struct sys_setpgid_args /* {
|
1994-10-20 07:22:35 +03:00
|
|
|
syscallarg(int) pid;
|
|
|
|
syscallarg(int) pgid;
|
1995-09-20 01:40:36 +04:00
|
|
|
} */ *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
|
|
|
|
1997-03-27 09:14:03 +03:00
|
|
|
if (SCARG(uap, pgid) < 0)
|
2003-03-19 14:36:32 +03:00
|
|
|
return EINVAL;
|
1997-03-27 09:14:03 +03:00
|
|
|
|
2003-03-19 14:36:32 +03:00
|
|
|
/* XXX MP - there is a horrid race here with targp exiting! */
|
1994-10-20 07:22:35 +03:00
|
|
|
if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != curp->p_pid) {
|
2003-03-19 14:36:32 +03:00
|
|
|
targp = pfind(SCARG(uap, pid));
|
|
|
|
if (targp == NULL)
|
|
|
|
return ESRCH;
|
1994-05-17 08:21:49 +04:00
|
|
|
} else
|
|
|
|
targp = curp;
|
2003-03-19 14:36:32 +03:00
|
|
|
|
1994-10-20 07:22:35 +03:00
|
|
|
if (SCARG(uap, pgid) == 0)
|
|
|
|
SCARG(uap, pgid) = targp->p_pid;
|
2003-03-19 14:36:32 +03:00
|
|
|
return enterpgrp(targp, SCARG(uap, pgid), 0);
|
1994-05-17 08:21:49 +04:00
|
|
|
}
|
|
|
|
|
2003-03-05 21:42:19 +03: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)
|
|
|
|
{
|
2006-07-31 01:58:11 +04:00
|
|
|
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;
|
2003-03-05 21:42:19 +03:00
|
|
|
|
2006-07-15 10:31:34 +04:00
|
|
|
/*
|
2006-07-31 01:58:11 +04:00
|
|
|
* Check that the new value is one of the allowed existing values,
|
|
|
|
* or that we have root privilege.
|
2006-07-15 10:31:34 +04:00
|
|
|
*/
|
|
|
|
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);
|
2006-07-15 10:31:34 +04:00
|
|
|
if (error != 0) {
|
2006-07-31 01:58:11 +04:00
|
|
|
proc_crmod_leave(p, cred, NULL);
|
2003-03-05 21:42:19 +03:00
|
|
|
return error;
|
2006-07-15 10:31:34 +04:00
|
|
|
}
|
2003-03-05 21:42:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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))
|
2006-07-15 10:31:34 +04:00
|
|
|
&& (sv == -1 || sv == kauth_cred_getsvuid(cred))) {
|
2006-07-31 01:58:11 +04:00
|
|
|
proc_crmod_leave(p, cred, NULL);
|
2003-03-05 21:42:19 +03:00
|
|
|
return 0;
|
2006-07-15 10:31:34 +04:00
|
|
|
}
|
2003-03-05 21:42:19 +03:00
|
|
|
|
2006-07-31 01:58:11 +04:00
|
|
|
cred = kauth_cred_dup(cred);
|
2006-07-17 19:29:06 +04:00
|
|
|
|
2006-05-15 01:15:11 +04:00
|
|
|
if (r != -1 && r != kauth_cred_getuid(cred)) {
|
2003-03-05 21:42:19 +03:00
|
|
|
/* Update count of processes for this user */
|
2006-05-15 01:15:11 +04:00
|
|
|
(void)chgproccnt(kauth_cred_getuid(cred), -1);
|
2003-03-05 21:42:19 +03:00
|
|
|
(void)chgproccnt(r, 1);
|
2006-05-15 01:15:11 +04:00
|
|
|
kauth_cred_setuid(cred, r);
|
2003-03-05 21:42:19 +03:00
|
|
|
}
|
|
|
|
if (sv != -1)
|
2006-05-15 01:15:11 +04:00
|
|
|
kauth_cred_setsvuid(cred, sv);
|
2006-07-17 19:29:06 +04:00
|
|
|
if (e != -1)
|
2006-05-15 01:15:11 +04:00
|
|
|
kauth_cred_seteuid(cred, e);
|
2003-03-05 21:42:19 +03:00
|
|
|
|
2006-07-31 01:58:11 +04:00
|
|
|
/* Mark process as having changed credentials, stops tracing etc. */
|
|
|
|
p_sugid(p);
|
|
|
|
|
2006-07-20 01:11:37 +04:00
|
|
|
/* Broadcast our credentials to the process and other LWPs. */
|
2006-07-31 01:58:11 +04:00
|
|
|
proc_crmod_leave(p, cred, p->p_cred);
|
|
|
|
|
|
|
|
/* Update our copy of the credentials. */
|
|
|
|
lwp_update_creds(l);
|
2006-07-20 01:11:37 +04:00
|
|
|
|
2003-03-05 21:42:19 +03:00
|
|
|
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)
|
|
|
|
{
|
2006-07-31 01:58:11 +04:00
|
|
|
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;
|
2003-03-05 21:42:19 +03:00
|
|
|
|
2006-07-15 10:31:34 +04:00
|
|
|
/*
|
|
|
|
* 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);
|
2006-07-15 10:31:34 +04:00
|
|
|
if (error != 0) {
|
2006-07-31 01:58:11 +04:00
|
|
|
proc_crmod_leave(p, cred, NULL);
|
2003-03-05 21:42:19 +03:00
|
|
|
return error;
|
2006-07-15 10:31:34 +04:00
|
|
|
}
|
2003-03-05 21:42:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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))
|
2006-07-15 10:31:34 +04:00
|
|
|
&& (sv == -1 || sv == kauth_cred_getsvgid(cred))) {
|
2006-07-31 01:58:11 +04:00
|
|
|
proc_crmod_leave(p, cred, NULL);
|
2003-03-05 21:42:19 +03:00
|
|
|
return 0;
|
2006-07-15 10:31:34 +04:00
|
|
|
}
|
2003-03-05 21:42:19 +03:00
|
|
|
|
2006-07-31 01:58:11 +04:00
|
|
|
cred = kauth_cred_dup(cred);
|
2006-07-17 19:29:06 +04:00
|
|
|
|
2003-03-05 21:42:19 +03:00
|
|
|
if (r != -1)
|
2006-05-15 01:15:11 +04:00
|
|
|
kauth_cred_setgid(cred, r);
|
2003-03-05 21:42:19 +03:00
|
|
|
if (sv != -1)
|
2006-05-15 01:15:11 +04:00
|
|
|
kauth_cred_setsvgid(cred, sv);
|
2006-07-17 19:29:06 +04:00
|
|
|
if (e != -1)
|
2006-05-15 01:15:11 +04:00
|
|
|
kauth_cred_setegid(cred, e);
|
2003-03-05 21:42:19 +03:00
|
|
|
|
2006-07-31 01:58:11 +04:00
|
|
|
/* Mark process as having changed credentials, stops tracing etc. */
|
|
|
|
p_sugid(p);
|
|
|
|
|
2006-07-20 01:11:37 +04:00
|
|
|
/* Broadcast our credentials to the process and other LWPs. */
|
2006-07-31 01:58:11 +04:00
|
|
|
proc_crmod_leave(p, cred, p->p_cred);
|
|
|
|
|
|
|
|
/* Update our copy of the credentials. */
|
|
|
|
lwp_update_creds(l);
|
2006-07-20 01:11:37 +04:00
|
|
|
|
2003-03-05 21:42:19 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1994-05-17 08:21:49 +04:00
|
|
|
/* ARGSUSED */
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_setuid(struct lwp *l, void *v, register_t *retval)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
1995-10-07 09:25:19 +03:00
|
|
|
struct sys_setuid_args /* {
|
1995-09-20 01:40:36 +04:00
|
|
|
syscallarg(uid_t) uid;
|
|
|
|
} */ *uap = v;
|
2003-03-05 21:42:19 +03:00
|
|
|
uid_t uid = SCARG(uap, uid);
|
1994-05-17 08:21:49 +04:00
|
|
|
|
2003-03-05 21:42:19 +03: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
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_seteuid(struct lwp *l, void *v, register_t *retval)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
1995-10-07 09:25:19 +03:00
|
|
|
struct sys_seteuid_args /* {
|
1995-09-20 01:40:36 +04:00
|
|
|
syscallarg(uid_t) euid;
|
|
|
|
} */ *uap = v;
|
2000-10-18 00:53:45 +04:00
|
|
|
|
2003-03-05 21:42:19 +03:00
|
|
|
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
|
|
|
}
|
|
|
|
|
1996-06-23 15:04:11 +04:00
|
|
|
int
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_setreuid(struct lwp *l, void *v, register_t *retval)
|
1996-06-23 15:04:11 +04:00
|
|
|
{
|
|
|
|
struct sys_setreuid_args /* {
|
|
|
|
syscallarg(uid_t) ruid;
|
|
|
|
syscallarg(uid_t) euid;
|
|
|
|
} */ *uap = v;
|
2006-07-20 01:11:37 +04:00
|
|
|
kauth_cred_t cred = l->l_cred;
|
2003-03-05 21:42:19 +03:00
|
|
|
uid_t ruid, euid, svuid;
|
1996-06-23 15:04:11 +04:00
|
|
|
|
|
|
|
ruid = SCARG(uap, ruid);
|
|
|
|
euid = SCARG(uap, euid);
|
2006-07-20 01:11:37 +04:00
|
|
|
|
2003-03-05 21:42:19 +03:00
|
|
|
if (ruid == -1)
|
2006-07-20 01:11:37 +04:00
|
|
|
ruid = kauth_cred_getuid(cred);
|
2003-03-05 21:42:19 +03:00
|
|
|
if (euid == -1)
|
2006-07-20 01:11:37 +04:00
|
|
|
euid = kauth_cred_geteuid(cred);
|
|
|
|
|
2003-03-05 21:42:19 +03:00
|
|
|
/* Saved uid is set to the new euid if the ruid changed */
|
2006-07-20 01:11:37 +04:00
|
|
|
svuid = (ruid == kauth_cred_getuid(cred)) ? -1 : euid;
|
2003-03-05 21:42:19 +03:00
|
|
|
|
|
|
|
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);
|
1996-06-23 15:04:11 +04:00
|
|
|
}
|
|
|
|
|
1994-05-17 08:21:49 +04:00
|
|
|
/* ARGSUSED */
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_setgid(struct lwp *l, void *v, register_t *retval)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
1995-10-07 09:25:19 +03:00
|
|
|
struct sys_setgid_args /* {
|
1995-09-20 01:40:36 +04:00
|
|
|
syscallarg(gid_t) gid;
|
|
|
|
} */ *uap = v;
|
2003-03-05 21:42:19 +03:00
|
|
|
gid_t gid = SCARG(uap, gid);
|
2000-10-18 00:53:45 +04:00
|
|
|
|
2003-03-05 21:42:19 +03:00
|
|
|
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
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_setegid(struct lwp *l, void *v, register_t *retval)
|
1994-05-17 08:21:49 +04:00
|
|
|
{
|
1995-10-07 09:25:19 +03:00
|
|
|
struct sys_setegid_args /* {
|
1995-09-20 01:40:36 +04:00
|
|
|
syscallarg(gid_t) egid;
|
|
|
|
} */ *uap = v;
|
2000-10-18 00:53:45 +04:00
|
|
|
|
2003-03-05 21:42:19 +03:00
|
|
|
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
|
|
|
}
|
|
|
|
|
1996-06-23 15:04:11 +04:00
|
|
|
int
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_setregid(struct lwp *l, void *v, register_t *retval)
|
1996-06-23 15:04:11 +04:00
|
|
|
{
|
|
|
|
struct sys_setregid_args /* {
|
|
|
|
syscallarg(gid_t) rgid;
|
|
|
|
syscallarg(gid_t) egid;
|
|
|
|
} */ *uap = v;
|
2006-07-20 01:11:37 +04:00
|
|
|
kauth_cred_t cred = l->l_cred;
|
2003-03-05 21:42:19 +03:00
|
|
|
gid_t rgid, egid, svgid;
|
1996-06-23 15:04:11 +04:00
|
|
|
|
|
|
|
rgid = SCARG(uap, rgid);
|
|
|
|
egid = SCARG(uap, egid);
|
2006-07-20 01:11:37 +04:00
|
|
|
|
2003-03-05 21:42:19 +03:00
|
|
|
if (rgid == -1)
|
2006-07-20 01:11:37 +04:00
|
|
|
rgid = kauth_cred_getgid(cred);
|
2003-03-05 21:42:19 +03:00
|
|
|
if (egid == -1)
|
2006-07-20 01:11:37 +04:00
|
|
|
egid = kauth_cred_getegid(cred);
|
|
|
|
|
2003-03-05 21:42:19 +03:00
|
|
|
/* Saved gid is set to the new egid if the rgid changed */
|
2006-07-20 01:11:37 +04:00
|
|
|
svgid = rgid == kauth_cred_getgid(cred) ? -1 : egid;
|
2003-03-05 21:42:19 +03:00
|
|
|
|
|
|
|
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);
|
1996-06-23 15:04:11 +04:00
|
|
|
}
|
|
|
|
|
2000-04-21 20:15:39 +04:00
|
|
|
int
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_issetugid(struct lwp *l, void *v, register_t *retval)
|
2000-04-21 20:15:39 +04:00
|
|
|
{
|
2003-01-18 13:06:22 +03:00
|
|
|
struct proc *p = l->l_proc;
|
2003-03-01 02:24:40 +03:00
|
|
|
|
2000-04-21 20:15:39 +04: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);
|
2000-04-21 20:15:39 +04:00
|
|
|
}
|
|
|
|
|
2005-08-23 11:58:58 +04:00
|
|
|
/*
|
|
|
|
* sort -u for groups.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
grsortu(gid_t *grp, int ngrp)
|
|
|
|
{
|
2005-09-03 00:51:53 +04:00
|
|
|
const gid_t *src, *end;
|
|
|
|
gid_t *dst;
|
|
|
|
gid_t group;
|
|
|
|
int i, j;
|
2005-08-23 11:58:58 +04:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
2005-09-03 00:51:53 +04:00
|
|
|
|
2005-08-23 11:58:58 +04:00
|
|
|
/* uniq */
|
2005-09-03 00:51:53 +04:00
|
|
|
end = grp + ngrp;
|
|
|
|
src = grp;
|
|
|
|
dst = grp;
|
|
|
|
while (src < end) {
|
|
|
|
group = *src++;
|
|
|
|
while (src < end && *src == group)
|
|
|
|
src++;
|
|
|
|
*dst++ = group;
|
|
|
|
}
|
|
|
|
|
2005-08-23 11:58:58 +04:00
|
|
|
#ifdef DIAGNOSTIC
|
2005-09-03 00:51:53 +04:00
|
|
|
/* zero out the rest of the array */
|
|
|
|
(void)memset(dst, 0, sizeof(*grp) * (end - dst));
|
2005-08-23 11:58:58 +04:00
|
|
|
#endif
|
2005-09-03 00:51:53 +04:00
|
|
|
|
|
|
|
return dst - grp;
|
2005-08-23 11:58:58 +04:00
|
|
|
}
|
|
|
|
|
1994-05-19 09:57:44 +04:00
|
|
|
/* ARGSUSED */
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
2006-11-01 13:17:58 +03:00
|
|
|
sys_setgroups(struct lwp *l, void *v, register_t *retval)
|
1995-09-20 01:40:36 +04:00
|
|
|
{
|
1995-10-07 09:25:19 +03:00
|
|
|
struct sys_setgroups_args /* {
|
1997-11-05 00:24:14 +03:00
|
|
|
syscallarg(int) gidsetsize;
|
1996-12-22 13:21:06 +03:00
|
|
|
syscallarg(const gid_t *) gidset;
|
1995-09-20 01:40:36 +04:00
|
|
|
} */ *uap = v;
|
2006-07-31 01:58:11 +04:00
|
|
|
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;
|
2000-10-18 00:53:45 +04:00
|
|
|
gid_t grp[NGROUPS];
|
|
|
|
size_t grsize;
|
1994-05-17 08:21:49 +04:00
|
|
|
|
2006-07-31 01:58:11 +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)
|
2006-07-31 01:58:11 +04:00
|
|
|
goto bad;
|
2000-10-18 00:53:45 +04:00
|
|
|
|
1994-10-20 07:22:35 +03:00
|
|
|
ngrp = SCARG(uap, gidsetsize);
|
2006-07-31 01:58:11 +04:00
|
|
|
if ((u_int)ngrp > NGROUPS) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto bad;
|
|
|
|
}
|
2000-10-18 00:53:45 +04:00
|
|
|
|
|
|
|
grsize = ngrp * sizeof(gid_t);
|
|
|
|
error = copyin(SCARG(uap, gidset), grp, grsize);
|
1996-02-04 05:15:01 +03:00
|
|
|
if (error)
|
2006-07-31 01:58:11 +04:00
|
|
|
goto bad;
|
2005-08-23 11:58:58 +04:00
|
|
|
|
|
|
|
ngrp = grsortu(grp, ngrp);
|
2006-07-31 01:58:11 +04:00
|
|
|
cred = kauth_cred_dup(cred);
|
2006-07-20 01:11:37 +04:00
|
|
|
kauth_cred_setgroups(cred, grp, ngrp, -1);
|
|
|
|
|
2006-07-31 01:58:11 +04:00
|
|
|
/* Mark process as having changed credentials, stops tracing etc. */
|
|
|
|
p_sugid(p);
|
|
|
|
|
2006-07-20 01:11:37 +04:00
|
|
|
/* Broadcast our credentials to the process and other LWPs. */
|
2006-07-31 01:58:11 +04:00
|
|
|
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);
|
2006-07-31 01:58:11 +04:00
|
|
|
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
|
2006-11-01 13:17:58 +03:00
|
|
|
sys___getlogin(struct lwp *l, void *v, register_t *retval)
|
1995-09-20 01:40:36 +04:00
|
|
|
{
|
1996-09-19 08:52:12 +04:00
|
|
|
struct sys___getlogin_args /* {
|
1994-10-20 07:22:35 +03:00
|
|
|
syscallarg(char *) namebuf;
|
1999-03-28 21:34:33 +04:00
|
|
|
syscallarg(size_t) namelen;
|
1995-09-20 01:40:36 +04:00
|
|
|
} */ *uap = v;
|
2003-01-18 13:06:22 +03:00
|
|
|
struct proc *p = l->l_proc;
|
1994-05-17 08:21:49 +04:00
|
|
|
|
1998-08-01 02:50:48 +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,
|
1994-10-20 07:22:35 +03:00
|
|
|
(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
|
2006-11-01 13:17:58 +03:00
|
|
|
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 /* {
|
1996-12-22 13:21:06 +03:00
|
|
|
syscallarg(const char *) namebuf;
|
1995-09-20 01:40:36 +04:00
|
|
|
} */ *uap = v;
|
2003-01-18 13:06:22 +03:00
|
|
|
struct proc *p = l->l_proc;
|
2003-02-15 21:10:15 +03:00
|
|
|
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);
|
2003-02-15 21:10:15 +03:00
|
|
|
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);
|
2003-02-15 21:10:15 +03:00
|
|
|
|
|
|
|
if (s->s_flags & S_LOGIN_SET && p->p_pid != s->s_sid &&
|
|
|
|
strncmp(newname, s->s_login, sizeof s->s_login) != 0)
|
2003-02-18 22:26:23 +03:00
|
|
|
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);
|
2003-02-15 21:10:15 +03:00
|
|
|
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
|
|
|
}
|