Module Name: src Committed By: pooka Date: Thu Dec 16 17:05:45 UTC 2010
Modified Files: src/lib/librumpclient: rumpclient.c src/lib/librumpuser: rumpuser_sp.c sp_common.c Log Message: Have the client and server perform some sort of handshake first. It's pretty much a placeholder for now. One plan for the future is to require some sort of authentication for superuser clients. The code will need a little massage then, though, to prevent DoS attacks. To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/lib/librumpclient/rumpclient.c cvs rdiff -u -r1.26 -r1.27 src/lib/librumpuser/rumpuser_sp.c cvs rdiff -u -r1.16 -r1.17 src/lib/librumpuser/sp_common.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/librumpclient/rumpclient.c diff -u src/lib/librumpclient/rumpclient.c:1.9 src/lib/librumpclient/rumpclient.c:1.10 --- src/lib/librumpclient/rumpclient.c:1.9 Thu Dec 16 12:38:21 2010 +++ src/lib/librumpclient/rumpclient.c Thu Dec 16 17:05:44 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpclient.c,v 1.9 2010/12/16 12:38:21 pooka Exp $ */ +/* $NetBSD: rumpclient.c,v 1.10 2010/12/16 17:05:44 pooka Exp $ */ /* * Copyright (c) 2010 Antti Kantee. All Rights Reserved. @@ -87,6 +87,36 @@ } static int +handshake_req(struct spclient *spc) +{ + struct rsp_hdr rhdr; + struct respwait rw; + int rv; + + /* performs server handshake */ + rhdr.rsp_len = sizeof(rhdr); + rhdr.rsp_class = RUMPSP_REQ; + rhdr.rsp_type = RUMPSP_HANDSHAKE; + rhdr.rsp_handshake = HANDSHAKE_GUEST; + + putwait(spc, &rw, &rhdr); + rv = dosend(spc, &rhdr, sizeof(rhdr)); + if (rv != 0) { + unputwait(spc, &rw); + return rv; + } + + rv = waitresp(spc, &rw); + if (rv) + return rv; + + rv = *(int *)rw.rw_data; + free(rw.rw_data); + + return rv; +} + +static int send_copyin_resp(struct spclient *spc, uint64_t reqno, void *data, size_t dlen, int wantstr) { @@ -235,19 +265,10 @@ return -1; } - if ((error = parsetab[idx].connhook(s)) != 0) { - error = errno; - fprintf(stderr, "rump_sp: connect hook failed\n"); - errno = error; - return -1; - } - clispc.spc_fd = s; - TAILQ_INIT(&clispc.spc_respwait); - pthread_mutex_init(&clispc.spc_mtx, NULL); - pthread_cond_init(&clispc.spc_cv, NULL); - if ((n = read(s, banner, sizeof(banner)-1)) < 0) { + error = errno; fprintf(stderr, "rump_sp: failed to read banner\n"); + errno = error; return -1; } @@ -260,5 +281,23 @@ /* parse the banner some day */ - return 0; + if ((error = parsetab[idx].connhook(s)) != 0) { + error = errno; + fprintf(stderr, "rump_sp: connect hook failed\n"); + errno = error; + return -1; + } + + pthread_mutex_init(&clispc.spc_mtx, NULL); + pthread_cond_init(&clispc.spc_cv, NULL); + clispc.spc_fd = s; + TAILQ_INIT(&clispc.spc_respwait); + + error = handshake_req(&clispc); + if (error) { + pthread_mutex_destroy(&clispc.spc_mtx); + pthread_cond_destroy(&clispc.spc_cv); + close(s); + } + return error; } Index: src/lib/librumpuser/rumpuser_sp.c diff -u src/lib/librumpuser/rumpuser_sp.c:1.26 src/lib/librumpuser/rumpuser_sp.c:1.27 --- src/lib/librumpuser/rumpuser_sp.c:1.26 Thu Dec 16 12:38:20 2010 +++ src/lib/librumpuser/rumpuser_sp.c Thu Dec 16 17:05:44 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpuser_sp.c,v 1.26 2010/12/16 12:38:20 pooka Exp $ */ +/* $NetBSD: rumpuser_sp.c,v 1.27 2010/12/16 17:05:44 pooka Exp $ */ /* * Copyright (c) 2010 Antti Kantee. All Rights Reserved. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: rumpuser_sp.c,v 1.26 2010/12/16 12:38:20 pooka Exp $"); +__RCSID("$NetBSD: rumpuser_sp.c,v 1.27 2010/12/16 17:05:44 pooka Exp $"); #include <sys/types.h> #include <sys/atomic.h> @@ -198,6 +198,26 @@ } static int +send_handshake_resp(struct spclient *spc, uint64_t reqno, int error) +{ + struct rsp_hdr rhdr; + int rv; + + rhdr.rsp_len = sizeof(rhdr) + sizeof(error); + rhdr.rsp_reqno = reqno; + rhdr.rsp_class = RUMPSP_RESP; + rhdr.rsp_type = RUMPSP_HANDSHAKE; + rhdr.rsp_error = 0; + + sendlock(spc); + rv = dosend(spc, &rhdr, sizeof(rhdr)); + rv = dosend(spc, &error, sizeof(error)); + sendunlock(spc); + + return rv; +} + +static int send_syscall_resp(struct spclient *spc, uint64_t reqno, int error, register_t *retval) { @@ -355,7 +375,7 @@ close(spc->spc_fd); spc->spc_fd = -1; - spc->spc_dying = 0; + spc->spc_state = SPCSTATE_NEW; atomic_inc_uint(&disco); } @@ -370,7 +390,7 @@ pfdlist[idx].fd = -1; pfdlist[idx].revents = 0; pthread_mutex_lock(&spc->spc_mtx); - spc->spc_dying = 1; + spc->spc_state = SPCSTATE_DYING; kickall(spc); pthread_mutex_unlock(&spc->spc_mtx); @@ -439,7 +459,7 @@ /* find empty slot the simple way */ for (i = 0; i < MAXCLI; i++) { - if (pfdlist[i].fd == -1 && spclist[i].spc_dying == 0) + if (pfdlist[i].fd == -1 && spclist[i].spc_state == SPCSTATE_NEW) break; } @@ -647,7 +667,24 @@ { struct sysbouncearg *sba; pthread_t pt; - int retries; + int retries, rv; + + if (__predict_false(spc->spc_state == SPCSTATE_NEW)) { + if (spc->spc_hdr.rsp_type != RUMPSP_HANDSHAKE) { + send_error_resp(spc, spc->spc_hdr.rsp_reqno, EAUTH); + spcfreebuf(spc); + return; + } + + rv = send_handshake_resp(spc, spc->spc_hdr.rsp_reqno, 0); + spcfreebuf(spc); + if (rv) { + shutdown(spc->spc_fd, SHUT_RDWR); + return; + } + spc->spc_state = SPCSTATE_RUNNING; + return; + } if (__predict_false(spc->spc_hdr.rsp_type != RUMPSP_SYSCALL)) { send_error_resp(spc, spc->spc_hdr.rsp_reqno, EINVAL); Index: src/lib/librumpuser/sp_common.c diff -u src/lib/librumpuser/sp_common.c:1.16 src/lib/librumpuser/sp_common.c:1.17 --- src/lib/librumpuser/sp_common.c:1.16 Thu Dec 16 12:38:20 2010 +++ src/lib/librumpuser/sp_common.c Thu Dec 16 17:05:44 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: sp_common.c,v 1.16 2010/12/16 12:38:20 pooka Exp $ */ +/* $NetBSD: sp_common.c,v 1.17 2010/12/16 17:05:44 pooka Exp $ */ /* * Copyright (c) 2010 Antti Kantee. All Rights Reserved. @@ -76,11 +76,14 @@ */ enum { RUMPSP_REQ, RUMPSP_RESP, RUMPSP_ERROR }; -enum { RUMPSP_SYSCALL, +enum { RUMPSP_HANDSHAKE, + RUMPSP_SYSCALL, RUMPSP_COPYIN, RUMPSP_COPYINSTR, RUMPSP_COPYOUT, RUMPSP_COPYOUTSTR, RUMPSP_ANONMMAP }; +enum { HANDSHAKE_GUEST, HANDSHAKE_AUTH }; /* more to come */ + struct rsp_hdr { uint64_t rsp_len; uint64_t rsp_reqno; @@ -93,11 +96,13 @@ union { uint32_t sysnum; uint32_t error; + uint32_t handshake; } u; }; #define HDRSZ sizeof(struct rsp_hdr) #define rsp_sysnum u.sysnum #define rsp_error u.error +#define rsp_handshake u.handshake #define MAXBANNER 96 @@ -132,7 +137,7 @@ struct spclient { int spc_fd; int spc_refcnt; - int spc_dying; + int spc_state; pthread_mutex_t spc_mtx; pthread_cond_t spc_cv; @@ -157,6 +162,10 @@ #define SPCSTATUS_BUSY 1 #define SPCSTATUS_WANTED 2 +#define SPCSTATE_NEW 0 +#define SPCSTATE_RUNNING 1 +#define SPCSTATE_DYING 2 + typedef int (*addrparse_fn)(const char *, struct sockaddr **, int); typedef int (*connecthook_fn)(int); typedef void (*cleanup_fn)(struct sockaddr *); @@ -334,7 +343,8 @@ sendunlockl(spc); rw->rw_error = 0; - while (rw->rw_data == NULL && rw->rw_error == 0 && spc->spc_dying == 0){ + while (rw->rw_data == NULL && rw->rw_error == 0 + && spc->spc_state != SPCSTATE_DYING){ /* are we free to receive? */ if (spc->spc_istatus == SPCSTATUS_FREE) { int gotresp; @@ -352,7 +362,7 @@ continue; case -1: rv = errno; - spc->spc_dying = 1; + spc->spc_state = SPCSTATE_DYING; goto cleanup; default: break; @@ -391,7 +401,7 @@ if (rv) return rv; - if (spc->spc_dying) + if (spc->spc_state == SPCSTATE_DYING) return ENOTCONN; return rw->rw_error; }