- djm@cvs.openbsd.org 2011/06/22 21:57:01

[servconf.c servconf.h sshd.c sshd_config.5 sandbox-rlimit.c]
     [sandbox-systrace.c sandbox.h configure.ac Makefile.in]
     introduce sandboxing of the pre-auth privsep child using systrace(4).

     This introduces a new "UsePrivilegeSeparation=sandbox" option for
     sshd_config that applies mandatory restrictions on the syscalls the
     privsep child can perform. This prevents a compromised privsep child
     from being used to attack other hosts (by opening sockets and proxying)
     or probing local kernel attack surface.

     The sandbox is implemented using systrace(4) in unsupervised "fast-path"
     mode, where a list of permitted syscalls is supplied. Any syscall not
     on the list results in SIGKILL being sent to the privsep child. Note
     that this requires a kernel with the new SYSTR_POLICY_KILL option.

     UsePrivilegeSeparation=sandbox will become the default in the future
     so please start testing it now.

     feedback dtucker@; ok markus@
This commit is contained in:
Damien Miller 2011-06-23 08:30:03 +10:00
parent 82c558761d
commit 69ff1df952
10 changed files with 417 additions and 15 deletions

View File

@ -3,6 +3,26 @@
- djm@cvs.openbsd.org 2011/06/22 21:47:28 - djm@cvs.openbsd.org 2011/06/22 21:47:28
[servconf.c] [servconf.c]
reuse the multistate option arrays to pretty-print options for "sshd -T" reuse the multistate option arrays to pretty-print options for "sshd -T"
- djm@cvs.openbsd.org 2011/06/22 21:57:01
[servconf.c servconf.h sshd.c sshd_config.5]
[configure.ac Makefile.in]
introduce sandboxing of the pre-auth privsep child using systrace(4).
This introduces a new "UsePrivilegeSeparation=sandbox" option for
sshd_config that applies mandatory restrictions on the syscalls the
privsep child can perform. This prevents a compromised privsep child
from being used to attack other hosts (by opening sockets and proxying)
or probing local kernel attack surface.
The sandbox is implemented using systrace(4) in unsupervised "fast-path"
mode, where a list of permitted syscalls is supplied. Any syscall not
on the list results in SIGKILL being sent to the privsep child. Note
that this requires a kernel with the new SYSTR_POLICY_KILL option.
UsePrivilegeSeparation=sandbox will become the default in the future
so please start testing it now.
feedback dtucker@; ok markus@
20110620 20110620
- OpenBSD CVS Sync - OpenBSD CVS Sync

View File

@ -1,4 +1,4 @@
# $Id: Makefile.in,v 1.322 2011/05/05 03:48:37 djm Exp $ # $Id: Makefile.in,v 1.323 2011/06/22 22:30:03 djm Exp $
# uncomment if you run a non bourne compatable shell. Ie. csh # uncomment if you run a non bourne compatable shell. Ie. csh
#SHELL = @SH@ #SHELL = @SH@
@ -89,7 +89,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
auth2-gss.o gss-serv.o gss-serv-krb5.o \ auth2-gss.o gss-serv.o gss-serv-krb5.o \
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
sftp-server.o sftp-common.o \ sftp-server.o sftp-common.o \
roaming_common.o roaming_serv.o roaming_common.o roaming_serv.o \
sandbox-null.o sandbox-rlimit.o sandbox-systrace.o
MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5

View File

@ -1,4 +1,4 @@
# $Id: configure.ac,v 1.476 2011/06/03 02:11:38 djm Exp $ # $Id: configure.ac,v 1.477 2011/06/22 22:30:03 djm Exp $
# #
# Copyright (c) 1999-2004 Damien Miller # Copyright (c) 1999-2004 Damien Miller
# #
@ -15,7 +15,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org]) AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org])
AC_REVISION($Revision: 1.476 $) AC_REVISION($Revision: 1.477 $)
AC_CONFIG_SRCDIR([ssh.c]) AC_CONFIG_SRCDIR([ssh.c])
AC_LANG([C]) AC_LANG([C])
@ -106,6 +106,16 @@ AC_SUBST([LD])
AC_C_INLINE AC_C_INLINE
AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], , [#include <limits.h>]) AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], , [#include <limits.h>])
AC_CHECK_DECL([SYSTR_POLICY_KILL], [have_systr_policy_kill=1], , [
#include <sys/types.h>
#include <sys/param.h>
#include <dev/systrace.h>
])
AC_CHECK_DECL([RLIMIT_NPROC],
[AC_DEFINE([HAVE_RLIMIT_NPROC], [], [sys/resource.h has RLIMIT_NPROC])], , [
#include <sys/types.h>
#include <sys/resource.h>
])
use_stack_protector=1 use_stack_protector=1
AC_ARG_WITH([stackprotect], AC_ARG_WITH([stackprotect],
@ -2461,6 +2471,34 @@ AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"],
[non-privileged user for privilege separation]) [non-privileged user for privilege separation])
AC_SUBST([SSH_PRIVSEP_USER]) AC_SUBST([SSH_PRIVSEP_USER])
# Decide which sandbox style to use
sandbox_arg=""
AC_ARG_WITH([sandbox],
[ --with-sandbox=style Specify privilege separation sandbox (no, rlimit, systrace)],
[
if test "x$withval" = "xyes" ; then
sandbox_arg=""
else
sandbox_arg="$withval"
fi
]
)
if test "x$sandbox_arg" = "xsystrace" || \
( test -z "$sandbox_arg" && test "x$have_systr_policy_kill" = "x1" ) ; then
SANDBOX_STYLE="systrace"
AC_DEFINE([SANDBOX_SYSTRACE], [1], [Sandbox using systrace(4)])
elif test "x$sandbox_arg" = "xrlimit" || \
( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" ) ; then
SANDBOX_STYLE="rlimit"
AC_DEFINE([SANDBOX_RLIMIT], [1], [Sandbox using setrlimit(2)])
elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \
test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then
SANDBOX_STYLE="none"
AC_DEFINE([SANDBOX_NULL], [1], [no privsep sandboxing])
else
AC_MSG_ERROR([unsupported -with-sandbox])
fi
# Cheap hack to ensure NEWS-OS libraries are arranged right. # Cheap hack to ensure NEWS-OS libraries are arranged right.
if test ! -z "$SONY" ; then if test ! -z "$SONY" ; then
LIBS="$LIBS -liberty"; LIBS="$LIBS -liberty";
@ -4191,6 +4229,7 @@ echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
echo " BSD Auth support: $BSD_AUTH_MSG" echo " BSD Auth support: $BSD_AUTH_MSG"
echo " Random number source: $RAND_MSG" echo " Random number source: $RAND_MSG"
echo " Privsep sandbox style: $SANDBOX_STYLE"
echo "" echo ""

92
sandbox-rlimit.c Normal file
View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifdef SANDBOX_RLIMIT
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "log.h"
#include "sandbox.h"
#include "xmalloc.h"
/* Minimal sandbox that sets zero nfiles, nprocs and filesize rlimits */
struct ssh_sandbox {
pid_t child_pid;
};
struct ssh_sandbox *
ssh_sandbox_init(void)
{
struct ssh_sandbox *box;
/*
* Strictly, we don't need to maintain any state here but we need
* to return non-NULL to satisfy the API.
*/
debug3("%s: preparing rlimit sandbox", __func__);
box = xcalloc(1, sizeof(*box));
box->child_pid = 0;
return box;
}
void
ssh_sandbox_child(struct ssh_sandbox *box)
{
struct rlimit rl_zero;
rl_zero.rlim_cur = rl_zero.rlim_max = 0;
if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1)
fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s",
__func__, strerror(errno));
if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1)
fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s",
__func__, strerror(errno));
#ifdef HAVE_RLIMIT_NPROC
if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1)
fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s",
__func__, strerror(errno));
#endif
}
void
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
{
free(box);
debug3("%s: finished", __func__);
}
void
ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
{
box->child_pid = child_pid;
}
#endif /* SANDBOX_RLIMIT */

187
sandbox-systrace.c Normal file
View File

@ -0,0 +1,187 @@
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifdef SANDBOX_SYSTRACE
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <dev/systrace.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "atomicio.h"
#include "log.h"
#include "sandbox.h"
#include "xmalloc.h"
static const int preauth_policy[] = {
SYS___sysctl,
SYS_close,
SYS_exit,
SYS_getpid,
SYS_gettimeofday,
SYS_madvise,
SYS_mmap,
SYS_mprotect,
SYS_poll,
SYS_munmap,
SYS_read,
SYS_select,
SYS_sigprocmask,
SYS_write,
-1
};
struct ssh_sandbox {
int child_sock;
int parent_sock;
int systrace_fd;
pid_t child_pid;
struct systrace_policy policy;
};
struct ssh_sandbox *
ssh_sandbox_init(void)
{
struct ssh_sandbox *box;
int s[2];
debug3("%s: preparing systrace sandbox", __func__);
box = xcalloc(1, sizeof(*box));
if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1)
fatal("%s: socketpair: %s", __func__, strerror(errno));
box->child_sock = s[0];
box->parent_sock = s[1];
box->systrace_fd = -1;
box->child_pid = 0;
return box;
}
void
ssh_sandbox_child(struct ssh_sandbox *box)
{
char whatever = 0;
close(box->parent_sock);
/* Signal parent that we are ready */
debug3("%s: ready", __func__);
if (atomicio(vwrite, box->child_sock, &whatever, 1) != 1)
fatal("%s: write: %s", __func__, strerror(errno));
/* Wait for parent to signal for us to go */
if (atomicio(read, box->child_sock, &whatever, 1) != 1)
fatal("%s: read: %s", __func__, strerror(errno));
debug3("%s: started", __func__);
close(box->child_sock);
}
static void
ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid,
const int *allowed_syscalls)
{
int dev_systrace, i, j, found;
char whatever = 0;
debug3("%s: wait for child %ld", __func__, (long)child_pid);
box->child_pid = child_pid;
close(box->child_sock);
/* Wait for child to signal that it is ready */
if (atomicio(read, box->parent_sock, &whatever, 1) != 1)
fatal("%s: read: %s", __func__, strerror(errno));
debug3("%s: child %ld ready", __func__, (long)child_pid);
/* Set up systracing of child */
if ((dev_systrace = open("/dev/systrace", O_RDONLY)) == -1)
fatal("%s: open(\"/dev/systrace\"): %s", __func__,
strerror(errno));
if (ioctl(dev_systrace, STRIOCCLONE, &box->systrace_fd) == -1)
fatal("%s: ioctl(STRIOCCLONE, %d): %s", __func__,
dev_systrace, strerror(errno));
close(dev_systrace);
debug3("%s: systrace attach, fd=%d", __func__, box->systrace_fd);
if (ioctl(box->systrace_fd, STRIOCATTACH, &child_pid) == -1)
fatal("%s: ioctl(%d, STRIOCATTACH, %d): %s", __func__,
box->systrace_fd, child_pid, strerror(errno));
/* Allocate and assign policy */
bzero(&box->policy, sizeof(box->policy));
box->policy.strp_op = SYSTR_POLICY_NEW;
box->policy.strp_maxents = SYS_MAXSYSCALL;
if (ioctl(box->systrace_fd, STRIOCPOLICY, &box->policy) == -1)
fatal("%s: ioctl(%d, STRIOCPOLICY (new)): %s", __func__,
box->systrace_fd, strerror(errno));
box->policy.strp_op = SYSTR_POLICY_ASSIGN;
box->policy.strp_pid = box->child_pid;
if (ioctl(box->systrace_fd, STRIOCPOLICY, &box->policy) == -1)
fatal("%s: ioctl(%d, STRIOCPOLICY (assign)): %s",
__func__, box->systrace_fd, strerror(errno));
/* Set per-syscall policy */
for (i = 0; i < SYS_MAXSYSCALL; i++) {
for (j = found = 0; allowed_syscalls[j] != -1 && !found; j++) {
if (allowed_syscalls[j] == i)
found = 1;
}
box->policy.strp_op = SYSTR_POLICY_MODIFY;
box->policy.strp_code = i;
box->policy.strp_policy = found ?
SYSTR_POLICY_PERMIT : SYSTR_POLICY_KILL;
if (found)
debug3("%s: policy: enable syscall %d", __func__, i);
if (ioctl(box->systrace_fd, STRIOCPOLICY,
&box->policy) == -1)
fatal("%s: ioctl(%d, STRIOCPOLICY (modify)): %s",
__func__, box->systrace_fd, strerror(errno));
}
/* Signal the child to start running */
debug3("%s: start child %ld", __func__, (long)child_pid);
if (atomicio(vwrite, box->parent_sock, &whatever, 1) != 1)
fatal("%s: write: %s", __func__, strerror(errno));
close(box->parent_sock);
}
void
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
{
/* Closing this before the child exits will terminate it */
close(box->systrace_fd);
free(box);
debug3("%s: finished", __func__);
}
void
ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
{
ssh_sandbox_parent(box, child_pid, preauth_policy);
}
#endif /* SANDBOX_SYSTRACE */

23
sandbox.h Executable file
View File

@ -0,0 +1,23 @@
/* $OpenBSD: sandbox.h,v 1.2 2011/06/22 22:14:05 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct ssh_sandbox;
struct ssh_sandbox *ssh_sandbox_init(void);
void ssh_sandbox_child(struct ssh_sandbox *);
void ssh_sandbox_parent_finish(struct ssh_sandbox *);
void ssh_sandbox_parent_preauth(struct ssh_sandbox *, pid_t);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.c,v 1.221 2011/06/22 21:47:28 djm Exp $ */ /* $OpenBSD: servconf.c,v 1.222 2011/06/22 21:57:01 djm Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -280,7 +280,7 @@ fill_default_server_options(ServerOptions *options)
/* Turn privilege separation on by default */ /* Turn privilege separation on by default */
if (use_privsep == -1) if (use_privsep == -1)
use_privsep = 1; use_privsep = PRIVSEP_ON;
#ifndef HAVE_MMAP #ifndef HAVE_MMAP
if (use_privsep && options->compression == 1) { if (use_privsep && options->compression == 1) {
@ -701,6 +701,12 @@ static const struct multistate multistate_gatewayports[] = {
{ "no", 0 }, { "no", 0 },
{ NULL, -1 } { NULL, -1 }
}; };
static const struct multistate multistate_privsep[] = {
{ "sandbox", PRIVSEP_SANDBOX },
{ "yes", PRIVSEP_ON },
{ "no", PRIVSEP_OFF },
{ NULL, -1 }
};
int int
process_server_config_line(ServerOptions *options, char *line, process_server_config_line(ServerOptions *options, char *line,
@ -1066,7 +1072,8 @@ process_server_config_line(ServerOptions *options, char *line,
case sUsePrivilegeSeparation: case sUsePrivilegeSeparation:
intptr = &use_privsep; intptr = &use_privsep;
goto parse_flag; multistate_ptr = multistate_privsep;
goto parse_multistate;
case sAllowUsers: case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') { while ((arg = strdelim(&cp)) && *arg != '\0') {
@ -1574,6 +1581,8 @@ fmt_intarg(ServerOpCodes code, int val)
return fmt_multistate_int(val, multistate_gatewayports); return fmt_multistate_int(val, multistate_gatewayports);
case sCompression: case sCompression:
return fmt_multistate_int(val, multistate_compression); return fmt_multistate_int(val, multistate_compression);
case sUsePrivilegeSeparation:
return fmt_multistate_int(val, multistate_privsep);
case sProtocol: case sProtocol:
switch (val) { switch (val) {
case SSH_PROTO_1: case SSH_PROTO_1:

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.98 2011/05/23 03:30:07 djm Exp $ */ /* $OpenBSD: servconf.h,v 1.99 2011/06/22 21:57:01 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -36,6 +36,11 @@
#define PERMIT_NO_PASSWD 2 #define PERMIT_NO_PASSWD 2
#define PERMIT_YES 3 #define PERMIT_YES 3
/* use_privsep */
#define PRIVSEP_OFF 0
#define PRIVSEP_ON 1
#define PRIVSEP_SANDBOX 2
#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */
#define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ #define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */

30
sshd.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.383 2011/06/17 21:44:31 djm Exp $ */ /* $OpenBSD: sshd.c,v 1.384 2011/06/22 21:57:01 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -118,6 +118,7 @@
#endif #endif
#include "monitor_wrap.h" #include "monitor_wrap.h"
#include "roaming.h" #include "roaming.h"
#include "sandbox.h"
#include "version.h" #include "version.h"
#ifdef LIBWRAP #ifdef LIBWRAP
@ -624,18 +625,23 @@ privsep_preauth(Authctxt *authctxt)
{ {
int status; int status;
pid_t pid; pid_t pid;
struct ssh_sandbox *box = NULL;
/* Set up unprivileged child process to deal with network data */ /* Set up unprivileged child process to deal with network data */
pmonitor = monitor_init(); pmonitor = monitor_init();
/* Store a pointer to the kex for later rekeying */ /* Store a pointer to the kex for later rekeying */
pmonitor->m_pkex = &xxx_kex; pmonitor->m_pkex = &xxx_kex;
if (use_privsep == PRIVSEP_SANDBOX)
box = ssh_sandbox_init();
pid = fork(); pid = fork();
if (pid == -1) { if (pid == -1) {
fatal("fork of unprivileged child failed"); fatal("fork of unprivileged child failed");
} else if (pid != 0) { } else if (pid != 0) {
debug2("Network child is on pid %ld", (long)pid); debug2("Network child is on pid %ld", (long)pid);
if (box != NULL)
ssh_sandbox_parent_preauth(box, pid);
pmonitor->m_pid = pid; pmonitor->m_pid = pid;
monitor_child_preauth(authctxt, pmonitor); monitor_child_preauth(authctxt, pmonitor);
@ -643,10 +649,21 @@ privsep_preauth(Authctxt *authctxt)
monitor_sync(pmonitor); monitor_sync(pmonitor);
/* Wait for the child's exit status */ /* Wait for the child's exit status */
while (waitpid(pid, &status, 0) < 0) while (waitpid(pid, &status, 0) < 0) {
if (errno != EINTR) if (errno != EINTR)
break; fatal("%s: waitpid: %s", __func__,
return (1); strerror(errno));
}
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0)
fatal("%s: preauth child exited with status %d",
__func__, WEXITSTATUS(status));
} else if (WIFSIGNALED(status))
fatal("%s: preauth child terminated by signal %d",
__func__, WTERMSIG(status));
if (box != NULL)
ssh_sandbox_parent_finish(box);
return 1;
} else { } else {
/* child */ /* child */
close(pmonitor->m_sendfd); close(pmonitor->m_sendfd);
@ -659,8 +676,11 @@ privsep_preauth(Authctxt *authctxt)
if (getuid() == 0 || geteuid() == 0) if (getuid() == 0 || geteuid() == 0)
privsep_preauth_child(); privsep_preauth_child();
setproctitle("%s", "[net]"); setproctitle("%s", "[net]");
if (box != NULL)
ssh_sandbox_child(box);
return 0;
} }
return (0);
} }
static void static void

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: sshd_config.5,v 1.133 2011/05/23 07:10:21 jmc Exp $ .\" $OpenBSD: sshd_config.5,v 1.134 2011/06/22 21:57:01 djm Exp $
.Dd $Mdocdate: May 23 2011 $ .Dd $Mdocdate: June 22 2011 $
.Dt SSHD_CONFIG 5 .Dt SSHD_CONFIG 5
.Os .Os
.Sh NAME .Sh NAME
@ -1071,6 +1071,12 @@ The goal of privilege separation is to prevent privilege
escalation by containing any corruption within the unprivileged processes. escalation by containing any corruption within the unprivileged processes.
The default is The default is
.Dq yes . .Dq yes .
If
.Cm UsePrivilegeSeparation
is set to
.Dq sandbox
then the pre-authentication unprivileged process is subject to additional
restrictions.
.It Cm X11DisplayOffset .It Cm X11DisplayOffset
Specifies the first display number available for Specifies the first display number available for
.Xr sshd 8 Ns 's .Xr sshd 8 Ns 's