From defde8be686e6145979598e959b62814a64d8b7a Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sun, 13 May 2018 17:50:30 +1000 Subject: [PATCH] IPC: do not use alloca() in Solaris doors backend --- lib/ipc/server.c | 50 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/lib/ipc/server.c b/lib/ipc/server.c index 87031d2a8..fc1f5c04c 100644 --- a/lib/ipc/server.c +++ b/lib/ipc/server.c @@ -1138,12 +1138,15 @@ heim_sipc_service_unix(const char *service, #ifdef HAVE_DOOR_CREATE #include -#include #ifdef HAVE_SYS_MMAN_H #include #endif +#include "heim_threads.h" + +static HEIMDAL_thread_key door_key; + struct door_call { heim_idata in; door_desc_t *dp; @@ -1163,26 +1166,61 @@ door_release(heim_sipc ctx) return 0; } +static void +door_reply_destroy(void *data) +{ + free(data); +} + +static void +door_key_create(void *key) +{ + int ret; + + HEIMDAL_key_create((HEIMDAL_thread_key *)key, door_reply_destroy, ret); +} + static void door_complete(heim_sipc_call ctx, int returnvalue, heim_idata *reply) { + static heim_base_once_t once = HEIM_BASE_ONCE_INIT; struct door_call *cs = (struct door_call *)ctx; - size_t rlen = offsetof(struct door_reply, data); - struct door_reply *r; + size_t rlen; + struct door_reply *r = NULL; + union { + struct door_reply reply; + char buffer[offsetof(struct door_reply, data) + BUFSIZ]; + } replyBuf; + int ret; + heim_base_once_f(&once, &door_key, door_key_create); + + /* free previously saved reply, if any */ + free(HEIMDAL_getspecific(door_key)); + + rlen = offsetof(struct door_reply, data); if (returnvalue == 0) rlen += reply->length; - r = alloca(rlen); - r->returnvalue = returnvalue; + /* long replies (> BUFSIZ) are allocated from the heap */ + if (rlen > BUFSIZ) { + r = malloc(rlen); + if (r == NULL) + returnvalue = EAGAIN; + } - if (returnvalue == 0) { + if (r == NULL) + r = &replyBuf.reply; + + r->returnvalue = returnvalue; + if (r->returnvalue == 0) { r->length = reply->length; memcpy(r->data, reply->data, reply->length); } /* door_return() doesn't return; don't leak cred */ heim_ipc_free_cred(cs->cred); + HEIMDAL_setspecific(door_key, r == &replyBuf.reply ? NULL : r, ret); door_return((char *)r, rlen, NULL, 0); }