Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib A bunch of changes which essentially make sshd work with...
details: https://anonhg.NetBSD.org/src/rev/937cffb2a0be
branches: trunk
changeset: 762053:937cffb2a0be
user: pooka <pooka%NetBSD.org@localhost>
date: Mon Feb 14 14:56:23 2011 +0000
description:
A bunch of changes which essentially make sshd work with a hijacked
rump tcp/ip stack:
* sshd likes to fork and then re-exec itself
==> trap execve() and augment the env with the current parameters
essential to a rump kernel (kernel communication fd, information
about dup2'd file descriptors)
* sshd likes to play lots of games with pipes, socketpairs and dup{,2}()
==> make sure we do not close essential rump client descriptors:
dup() them to a safe place, except for F_CLOSEM where we
simply leave them alone. also, partially solved by the above,
make sure the process's set of rump kernel descriptors persists
over exec()
* sshd likes to chdir() before exec
==> for unix-style rump_sp(7) sockets save the full path on the
initial exec and use it afterwards. thread the path through
the environment in execve()
diffstat:
lib/librumpclient/rumpclient.c | 158 ++++++++++++++++++++++++++++++++++++++--
lib/librumpclient/rumpclient.h | 10 ++-
lib/librumphijack/hijack.c | 86 +++++++++++++++++++--
lib/librumpuser/sp_common.c | 11 ++-
4 files changed, 245 insertions(+), 20 deletions(-)
diffs (truncated from 464 to 300 lines):
diff -r 23a4ad52680e -r 937cffb2a0be lib/librumpclient/rumpclient.c
--- a/lib/librumpclient/rumpclient.c Mon Feb 14 14:15:25 2011 +0000
+++ b/lib/librumpclient/rumpclient.c Mon Feb 14 14:56:23 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpclient.c,v 1.27 2011/02/09 14:29:58 pooka Exp $ */
+/* $NetBSD: rumpclient.c,v 1.28 2011/02/14 14:56:23 pooka Exp $ */
/*
* Copyright (c) 2010, 2011 Antti Kantee. All Rights Reserved.
@@ -198,6 +198,10 @@
rv = host_kevent(kq, NULL, 0,
kev, __arraycount(kev), NULL);
+ if (__predict_false(rv == -1)) {
+ goto cleanup;
+ }
+
/*
* XXX: don't know how this can
* happen (timeout cannot expire
@@ -546,15 +550,19 @@
/* dup until we get a "good" fd which does not collide with stdio */
static int
-dupgood(int myfd)
+dupgood(int myfd, int mustchange)
{
- int ofds[3];
+ int ofds[4];
int i;
- for (i = 0; myfd <= 2 && myfd != -1; i++) {
+ for (i = 0; (myfd <= 2 || mustchange) && myfd != -1; i++) {
assert(i < __arraycount(ofds));
ofds[i] = myfd;
myfd = host_dup(myfd);
+ if (mustchange) {
+ i--; /* prevent closing old fd */
+ mustchange = 0;
+ }
}
for (i--; i >= 0; i--) {
@@ -611,7 +619,7 @@
free(clispc.spc_buf);
clispc.spc_off = 0;
- s = dupgood(host_socket(parsetab[ptab_idx].domain, SOCK_STREAM, 0));
+ s = dupgood(host_socket(parsetab[ptab_idx].domain, SOCK_STREAM, 0), 0);
if (s == -1)
return -1;
@@ -666,7 +674,7 @@
clispc.spc_reconnecting = 0;
/* setup kqueue, we want all signals and the fd */
- if ((kq = dupgood(host_kqueue())) == -1) {
+ if ((kq = dupgood(host_kqueue(), 0)) == -1) {
error = errno;
if (noisy)
fprintf(stderr, "rump_sp: cannot setup kqueue");
@@ -742,9 +750,11 @@
#undef FINDSYM
#undef FINDSY2
- if ((p = getenv("RUMP_SERVER")) == NULL) {
- errno = ENOENT;
- return -1;
+ if ((p = getenv("RUMP__PARSEDSERVER")) == NULL) {
+ if ((p = getenv("RUMP_SERVER")) == NULL) {
+ errno = ENOENT;
+ return -1;
+ }
}
if ((error = parseurl(p, &serv_sa, &ptab_idx, 0)) != 0) {
@@ -754,6 +764,13 @@
if (doinit() == -1)
return -1;
+
+ if ((p = getenv("RUMPCLIENT__EXECFD")) != NULL) {
+ sscanf(p, "%d,%d", &clispc.spc_fd, &kq);
+ unsetenv("RUMPCLIENT__EXECFD");
+ return 0;
+ }
+
if (doconnect(true) == -1)
return -1;
@@ -839,3 +856,126 @@
retrytimo = timeout;
}
+
+int
+rumpclient__closenotify(int *fdp, enum rumpclient_closevariant variant)
+{
+ int fd = *fdp;
+ int untilfd, rv;
+ int newfd;
+
+ switch (variant) {
+ case RUMPCLIENT_CLOSE_FCLOSEM:
+ untilfd = MAX(clispc.spc_fd, kq);
+ for (; fd <= untilfd; fd++) {
+ if (fd == clispc.spc_fd || fd == kq)
+ continue;
+ rv = host_close(fd);
+ if (rv == -1)
+ return -1;
+ }
+ *fdp = fd;
+ break;
+
+ case RUMPCLIENT_CLOSE_CLOSE:
+ case RUMPCLIENT_CLOSE_DUP2:
+ if (fd == clispc.spc_fd) {
+ struct kevent kev[2];
+
+ newfd = dupgood(clispc.spc_fd, 1);
+ if (newfd == -1)
+ return -1;
+ /*
+ * now, we have a new socket number, so change
+ * the file descriptor that kqueue is
+ * monitoring. remove old and add new.
+ */
+ EV_SET(&kev[0], clispc.spc_fd,
+ EVFILT_READ, EV_DELETE, 0, 0, 0);
+ EV_SET(&kev[1], newfd,
+ EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0);
+ if (host_kevent(kq, kev, 2, NULL, 0, NULL) == -1) {
+ int sverrno = errno;
+ host_close(newfd);
+ errno = sverrno;
+ return -1;
+ }
+ clispc.spc_fd = newfd;
+ }
+ if (fd == kq) {
+ newfd = dupgood(kq, 1);
+ if (newfd == -1)
+ return -1;
+ kq = newfd;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Process is about to exec. Save info about our existing connection
+ * in the env. rumpclient will check for this info in init().
+ * This is mostly for the benefit of rumphijack, but regular applications
+ * may use it as well.
+ */
+int
+rumpclient__exec_augmentenv(char *const oenv1[], char *const oenv2[],
+ char ***newenvp)
+{
+ char buf[4096];
+ char **newenv;
+ char *envstr, *envstr2;
+ size_t nelem1, nelem2;
+
+ snprintf(buf, sizeof(buf), "RUMPCLIENT__EXECFD=%d,%d",
+ clispc.spc_fd, kq);
+ envstr = malloc(strlen(buf)+1);
+ if (envstr == NULL) {
+ return ENOMEM;
+ }
+ strcpy(envstr, buf);
+
+ /* do we have a fully parsed url we want to forward in the env? */
+ if (*parsedurl != '\0') {
+ snprintf(buf, sizeof(buf),
+ "RUMP__PARSEDSERVER=%s", parsedurl);
+ envstr2 = malloc(strlen(buf)+1);
+ if (envstr2 == NULL) {
+ free(envstr);
+ return ENOMEM;
+ }
+ strcpy(envstr2, buf);
+ } else {
+ envstr2 = NULL;
+ }
+
+ nelem1 = 0;
+ if (oenv1) {
+ for (; oenv1[nelem1]; nelem1++)
+ continue;
+ }
+ nelem2 = 0;
+ if (oenv2) {
+ for (; oenv2[nelem2]; nelem2++)
+ continue;
+ }
+
+ newenv = malloc(sizeof(*newenv) * nelem1+nelem2+3);
+ if (newenv == NULL) {
+ free(envstr2);
+ free(envstr);
+ return ENOMEM;
+ }
+ memcpy(&newenv[0], oenv1, sizeof(*oenv1) * nelem1);
+ memcpy(&newenv[nelem1], oenv2, sizeof(*oenv2) * nelem2);
+
+ newenv[nelem1+nelem2] = envstr;
+ newenv[nelem1+nelem2+1] = envstr2;
+ newenv[nelem1+nelem2+2] = NULL;
+
+ *newenvp = newenv;
+
+ return 0;
+}
diff -r 23a4ad52680e -r 937cffb2a0be lib/librumpclient/rumpclient.h
--- a/lib/librumpclient/rumpclient.h Mon Feb 14 14:15:25 2011 +0000
+++ b/lib/librumpclient/rumpclient.h Mon Feb 14 14:56:23 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpclient.h,v 1.5 2011/02/07 14:49:32 pooka Exp $ */
+/* $NetBSD: rumpclient.h,v 1.6 2011/02/14 14:56:23 pooka Exp $ */
/*-
* Copyright (c) 2010 Antti Kantee. All Rights Reserved.
@@ -44,6 +44,14 @@
#define RUMPCLIENT_RETRYCONN_DIE ((time_t)-3)
void rumpclient_setconnretry(time_t);
+enum rumpclient_closevariant {
+ RUMPCLIENT_CLOSE_CLOSE,
+ RUMPCLIENT_CLOSE_DUP2,
+ RUMPCLIENT_CLOSE_FCLOSEM
+};
+int rumpclient__closenotify(int *, enum rumpclient_closevariant);
+int rumpclient__exec_augmentenv(char *const[], char *const[], char ***);
+
__END_DECLS
#endif /* _RUMP_RUMPCLIENT_H_ */
diff -r 23a4ad52680e -r 937cffb2a0be lib/librumphijack/hijack.c
--- a/lib/librumphijack/hijack.c Mon Feb 14 14:15:25 2011 +0000
+++ b/lib/librumphijack/hijack.c Mon Feb 14 14:56:23 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hijack.c,v 1.38 2011/02/12 10:25:46 pooka Exp $ */
+/* $NetBSD: hijack.c,v 1.39 2011/02/14 14:56:23 pooka Exp $ */
/*-
* Copyright (c) 2011 Antti Kantee. All Rights Reserved.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: hijack.c,v 1.38 2011/02/12 10:25:46 pooka Exp $");
+__RCSID("$NetBSD: hijack.c,v 1.39 2011/02/14 14:56:23 pooka Exp $");
#define __ssp_weak_name(fun) _hijack_ ## fun
@@ -140,9 +140,10 @@
pid_t (*host_fork)(void);
int (*host_daemon)(int, int);
+int (*host_execve)(const char *, char *const[], char *const[]);
static unsigned dup2mask;
-#define ISDUP2D(fd) (1<<(fd) & dup2mask)
+#define ISDUP2D(fd) ((fd < 32) && (1<<(fd) & dup2mask))
//#define DEBUGJACK
#ifdef DEBUGJACK
@@ -217,6 +218,7 @@
rumpclient_dlsym = hijackdlsym;
host_fork = dlsym(RTLD_NEXT, "fork");
host_daemon = dlsym(RTLD_NEXT, "daemon");
+ host_execve = dlsym(RTLD_NEXT, "execve");
/*
* In theory cannot print anything during lookups because
@@ -273,6 +275,10 @@
rumpclient_setconnretry(timeout);
}
}
+
+ if (getenv_r("RUMPHIJACK__DUP2MASK", buf, sizeof(buf)) == 0) {
+ dup2mask = atoi(buf);
+ }
}
/* XXX: need runtime selection. low for now due to FD_SETSIZE */
@@ -397,6 +403,10 @@
op_fcntl = GETSYSCALL(rump, FCNTL);
} else {
op_fcntl = GETSYSCALL(host, FCNTL);
+ if (cmd == F_CLOSEM)
+ if (rumpclient__closenotify(&fd,
+ RUMPCLIENT_CLOSE_FCLOSEM) == -1)
+ return -1;
}
Home |
Main Index |
Thread Index |
Old Index