commit aa081897ac57658482143f29f4b88b1ebbddede3
parent 5b4cf1798bfaf7be1dfaea36614757db80cae23d
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date: Tue, 6 Jan 2015 00:31:40 +0000
- Bugfixes in unixmessage/skaclient (short writes / fd leakage / DoS)
- ABI change: unixmessage protocol header is now 6 bytes (was 8)
- API change: skaclient_start(_async) now takes an "options" argument
- version increase to 2.1.0.0
Diffstat:
17 files changed, 199 insertions(+), 81 deletions(-)
diff --git a/doc/index.html b/doc/index.html
@@ -59,7 +59,7 @@ with a standard C development environment </li>
<h3> Download </h3>
<ul>
- <li> The current released version of skalibs is <a href="skalibs-2.0.0.0.tar.gz">2.0.0.0</a>. </li>
+ <li> The current released version of skalibs is <a href="skalibs-2.1.0.0.tar.gz">2.1.0.0</a>. </li>
<li> Alternatively, you can checkout a copy of the skalibs git repository:
<pre> git clone git://git.skarnet.org/skalibs </pre> </li>
</ul>
diff --git a/doc/license.html b/doc/license.html
@@ -73,7 +73,7 @@ color, or different text font. </li>
<p>
<em>I am aware that the previous restrictions sound completely
ridiculous while the official skalibs documentation is incomplete.
-As of 2.0.0.0, I'm not going to enforce those restrictions, but if you're
+As of 2.1.0.0, I'm not going to enforce those restrictions, but if you're
going to provide documentation for skalibs, don't keep it to yourself,
please send it to me instead. :-) </em>
</p>
diff --git a/doc/upgrade.html b/doc/upgrade.html
@@ -17,6 +17,15 @@
<h1> What has changed in skalibs </h1>
+<h2> in 2.1.0.0 </h2>
+
+<ul>
+ <li> unixmessage_drop added, part of unixmessage/skaclient hardening against fd leakage </li>
+ <li> unixmessage_sender_flush return code aligned with the convention in the rest of skalibs </li>
+ <li> unixmessage_sender_flush now handles short writes </li>
+ <li> skaclient_start(_async) prototype changed: now takes an option argument </li>
+</ul>
+
<h2> in 2.0.0.0 </h2>
<ul>
diff --git a/package/deps.mak b/package/deps.mak
@@ -55,7 +55,7 @@ src/include/skalibs/unirandomegd.h: src/include/skalibs/unirandom.h
src/include/skalibs/unisurf.h: src/include/skalibs/unirandom.h
src/include/skalibs/unix-timed.h: src/include/skalibs/bufalloc.h src/include/skalibs/buffer.h src/include/skalibs/functypes.h src/include/skalibs/stralloc.h src/include/skalibs/tai.h
src/include/skalibs/unix-transactional.h: src/include/skalibs/stralloc.h src/include/skalibs/uint64.h
-src/include/skalibs/unixmessage.h: src/include/skalibs/buffer.h src/include/skalibs/cbuffer.h src/include/skalibs/gccattributes.h src/include/skalibs/genalloc.h src/include/skalibs/siovec.h src/include/skalibs/stralloc.h src/include/skalibs/tai.h
+src/include/skalibs/unixmessage.h: src/include/skalibs/buffer.h src/include/skalibs/cbuffer.h src/include/skalibs/gccattributes.h src/include/skalibs/genalloc.h src/include/skalibs/siovec.h src/include/skalibs/stralloc.h src/include/skalibs/tai.h src/include/skalibs/uint16.h src/include/skalibs/uint32.h
src/include/skalibs/unixonacid.h: src/include/skalibs/kolbak.h src/include/skalibs/skaclient.h src/include/skalibs/unix-timed.h src/include/skalibs/unix-transactional.h src/include/skalibs/unixmessage.h
src/include/skalibs/webipc.h: src/include/skalibs/djbunix.h src/include/skalibs/tai.h
src/libdatastruct/avlnode-internal.h: src/include/skalibs/avlnode.h
@@ -744,13 +744,13 @@ src/libunixonacid/unixmessage_bits_closeall.o src/libunixonacid/unixmessage_bits
src/libunixonacid/unixmessage_bits_closenone.o src/libunixonacid/unixmessage_bits_closenone.lo: src/libunixonacid/unixmessage_bits_closenone.c src/include/skalibs/bitarray.h src/include/skalibs/unixmessage.h
src/libunixonacid/unixmessage_drop.o src/libunixonacid/unixmessage_drop.lo: src/libunixonacid/unixmessage_drop.c src/include/skalibs/djbunix.h src/include/skalibs/unixmessage.h
src/libunixonacid/unixmessage_handle.o src/libunixonacid/unixmessage_handle.lo: src/libunixonacid/unixmessage_handle.c src/include/skalibs/unixmessage.h
-src/libunixonacid/unixmessage_put.o src/libunixonacid/unixmessage_put.lo: src/libunixonacid/unixmessage_put.c src/include/skalibs/bitarray.h src/include/skalibs/bytestr.h src/include/skalibs/diuint.h src/include/skalibs/genalloc.h src/include/skalibs/siovec.h src/include/skalibs/stralloc.h src/include/skalibs/sysdeps.h src/include/skalibs/unixmessage.h
-src/libunixonacid/unixmessage_receive.o src/libunixonacid/unixmessage_receive.lo: src/libunixonacid/unixmessage_receive.c src/include/skalibs/allreadwrite.h src/include/skalibs/cbuffer.h src/include/skalibs/djbunix.h src/include/skalibs/error.h src/include/skalibs/nonposix.h src/include/skalibs/siovec.h src/include/skalibs/stralloc.h src/include/skalibs/sysdeps.h src/include/skalibs/uint.h src/include/skalibs/unixmessage.h
+src/libunixonacid/unixmessage_put.o src/libunixonacid/unixmessage_put.lo: src/libunixonacid/unixmessage_put.c src/include/skalibs/bitarray.h src/include/skalibs/bytestr.h src/include/skalibs/diuint.h src/include/skalibs/error.h src/include/skalibs/genalloc.h src/include/skalibs/siovec.h src/include/skalibs/stralloc.h src/include/skalibs/sysdeps.h src/include/skalibs/unixmessage.h
+src/libunixonacid/unixmessage_receive.o src/libunixonacid/unixmessage_receive.lo: src/libunixonacid/unixmessage_receive.c src/include/skalibs/allreadwrite.h src/include/skalibs/cbuffer.h src/include/skalibs/djbunix.h src/include/skalibs/error.h src/include/skalibs/nonposix.h src/include/skalibs/siovec.h src/include/skalibs/stralloc.h src/include/skalibs/sysdeps.h src/include/skalibs/uint16.h src/include/skalibs/uint32.h src/include/skalibs/unixmessage.h
src/libunixonacid/unixmessage_receiver_0.o src/libunixonacid/unixmessage_receiver_0.lo: src/libunixonacid/unixmessage_receiver_0.c src/include/skalibs/unixmessage.h
-src/libunixonacid/unixmessage_receiver_free.o src/libunixonacid/unixmessage_receiver_free.lo: src/libunixonacid/unixmessage_receiver_free.c src/include/skalibs/stralloc.h src/include/skalibs/unixmessage.h
+src/libunixonacid/unixmessage_receiver_free.o src/libunixonacid/unixmessage_receiver_free.lo: src/libunixonacid/unixmessage_receiver_free.c src/include/skalibs/djbunix.h src/include/skalibs/stralloc.h src/include/skalibs/unixmessage.h
src/libunixonacid/unixmessage_receiver_init.o src/libunixonacid/unixmessage_receiver_init.lo: src/libunixonacid/unixmessage_receiver_init.c src/include/skalibs/cbuffer.h src/include/skalibs/stralloc.h src/include/skalibs/unixmessage.h
src/libunixonacid/unixmessage_sender_1.o src/libunixonacid/unixmessage_sender_1.lo: src/libunixonacid/unixmessage_sender_1.c src/include/skalibs/unixmessage.h
-src/libunixonacid/unixmessage_sender_flush.o src/libunixonacid/unixmessage_sender_flush.lo: src/libunixonacid/unixmessage_sender_flush.c src/include/skalibs/diuint.h src/include/skalibs/djbunix.h src/include/skalibs/genalloc.h src/include/skalibs/nonposix.h src/include/skalibs/stralloc.h src/include/skalibs/sysdeps.h src/include/skalibs/uint.h src/include/skalibs/unixmessage.h
+src/libunixonacid/unixmessage_sender_flush.o src/libunixonacid/unixmessage_sender_flush.lo: src/libunixonacid/unixmessage_sender_flush.c src/include/skalibs/allreadwrite.h src/include/skalibs/diuint.h src/include/skalibs/djbunix.h src/include/skalibs/genalloc.h src/include/skalibs/nonposix.h src/include/skalibs/sysdeps.h src/include/skalibs/uint16.h src/include/skalibs/uint32.h src/include/skalibs/unixmessage.h
src/libunixonacid/unixmessage_sender_free.o src/libunixonacid/unixmessage_sender_free.lo: src/libunixonacid/unixmessage_sender_free.c src/include/skalibs/diuint.h src/include/skalibs/genalloc.h src/include/skalibs/stralloc.h src/include/skalibs/sysdeps.h src/include/skalibs/unixmessage.h
src/libunixonacid/unixmessage_sender_getfd.o src/libunixonacid/unixmessage_sender_getfd.lo: src/libunixonacid/unixmessage_sender_getfd.c src/include/skalibs/unixmessage.h
src/libunixonacid/unixmessage_sender_init.o src/libunixonacid/unixmessage_sender_init.lo: src/libunixonacid/unixmessage_sender_init.c src/include/skalibs/genalloc.h src/include/skalibs/stralloc.h src/include/skalibs/unixmessage.h
diff --git a/package/info b/package/info
@@ -1,4 +1,4 @@
package=skalibs
-version=2.0.0.0
+version=2.1.0.0
category=prog
package_macro_name=SKALIBS
diff --git a/src/include/skalibs/skaclient.h b/src/include/skalibs/skaclient.h
@@ -25,23 +25,13 @@ extern int skaclient_server_init (unixmessage_receiver_t *, unixmessage_sender_t
#define SKACLIENT_KOLBAK_SIZE 64
#define SKACLIENT_OPTION_WAITPID 0x00000001U
+#define SKACLIENT_OPTION_ASYNC_ACCEPT_FDS 0x00000002U
+#define SKACLIENT_OPTION_SYNC_ACCEPT_FDS 0x00000004U
#define skaclient_buffer_type(bufsn, auxbufsn, bufan, auxbufan, qlen) struct { char bufs[bufsn] ; char auxbufs[auxbufsn] ; char bufa[bufan] ; char auxbufa[auxbufan] ; kolbak_closure_t q[qlen] ; }
typedef skaclient_buffer_type(UNIXMESSAGE_BUFSIZE, UNIXMESSAGE_AUXBUFSIZE, UNIXMESSAGE_BUFSIZE, UNIXMESSAGE_AUXBUFSIZE, SKACLIENT_KOLBAK_SIZE) skaclient_buffer_t, *skaclient_buffer_t_ref ;
- /* Callback data for init */
-
-typedef struct skaclient_cbdata_s skaclient_cbdata_t, *skaclient_cbdata_t_ref ;
-struct skaclient_cbdata_s
-{
- unixmessage_receiver_t *asyncin ;
- unixmessage_sender_t *asyncout ;
- char const *after ;
- unsigned int afterlen ;
-} ;
-
-
/* User structure */
typedef struct skaclient_s skaclient_t, *skaclient_t_ref ;
@@ -58,23 +48,40 @@ struct skaclient_s
#define SKACLIENT_ZERO { .syncin = UNIXMESSAGE_RECEIVER_ZERO, .syncout = UNIXMESSAGE_SENDER_ZERO, .kq = KOLBAK_QUEUE_ZERO, .asyncin = UNIXMESSAGE_RECEIVER_ZERO, .asyncout = UNIXMESSAGE_SENDER_ZERO, .pid = 0, .options = 0 }
extern skaclient_t const skaclient_zero ;
+
+ /* Callback data for init */
+
+typedef struct skaclient_cbdata_s skaclient_cbdata_t, *skaclient_cbdata_t_ref ;
+struct skaclient_cbdata_s
+{
+ skaclient_t *a ;
+ char const *after ;
+ unsigned int afterlen ;
+} ;
+
+
+ /* Starting and ending */
+
extern void skaclient_end (skaclient_t *) ;
-extern int skaclient_start_async (skaclient_t *, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, char const *, unsigned int, char const *, unsigned int, skaclient_cbdata_t *) ;
-#define skaclient_start_async_b(a, sb, path, before, beforelen, after, afterlen, blah) skaclient_start_async(a, (sb)->bufs, sizeof((sb)->bufs), (sb)->auxbufs, sizeof((sb)->auxbufs), (sb)->bufa, sizeof((sb)->bufa), (sb)->auxbufa, sizeof((sb)->auxbufa), (sb)->q, sizeof((sb)->q), path, before, beforelen, after, afterlen, blah)
+extern int skaclient_start_async (skaclient_t *, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, uint32, char const *, unsigned int, char const *, unsigned int, skaclient_cbdata_t *) ;
+#define skaclient_start_async_b(a, sb, path, options, before, beforelen, after, afterlen, blah) skaclient_start_async(a, (sb)->bufs, sizeof((sb)->bufs), (sb)->auxbufs, sizeof((sb)->auxbufs), (sb)->bufa, sizeof((sb)->bufa), (sb)->auxbufa, sizeof((sb)->auxbufa), (sb)->q, sizeof((sb)->q), path, options, before, beforelen, after, afterlen, blah)
extern int skaclient_startf_async (skaclient_t *, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, char const *const *, char const *const *, uint32, char const *, unsigned int, char const *, unsigned int, skaclient_cbdata_t *) ;
#define skaclient_startf_async_b(a, sb, prog, argv, envp, options, before, beforelen, after, afterlen, blah) skaclient_startf_async(a, (sb)->bufs, sizeof((sb)->bufs), (sb)->auxbufs, sizeof((sb)->auxbufs), (sb)->bufa, sizeof((sb)->bufa), (sb)->auxbufa, sizeof((sb)->auxbufa), (sb)->q, sizeof((sb)->q) / sizeof(kolbak_closure_t), prog, argv, envp, options, before, beforelen, after, afterlen, blah)
-extern int skaclient_start (skaclient_t *, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, char const *, unsigned int, char const *, unsigned int, tain_t const *, tain_t *) ;
-#define skaclient_start_b(a, sb, path, before, beforelen, after, afterlen, deadline, stamp) skaclient_start(a, (sb)->bufs, sizeof((sb)->bufs), (sb)->auxbufs, sizeof((sb)->auxbufs), (sb)->bufa, sizeof((sb)->bufa), (sb)->auxbufa, sizeof((sb)->auxbufa), (sb)->q, sizeof((sb)->q) / sizeof(kolbak_closure_t), path, before, beforelen, after, afterlen, deadline, stamp)
-#define skaclient_start_g(a, bufs, bufsn, auxbufs, auxbufsn, bufa, bufan, auxbufa, auxbufan, q, qlen, path, before, beforelen, after, afterlen, deadline) skaclient_start(a, bufs, bufsn, auxbufs, auxbufsn, bufa, bufan, auxbufa, auxbufan, q, qlen, path, before, beforelen, after, afterlen, (deadline), &STAMP)
-#define skaclient_start_b_g(a, sb, path, before, beforelen, after, afterlen, deadline) skaclient_start_b(a, sb, path, before, beforelen, after, afterlen, (deadline), &STAMP)
+extern int skaclient_start (skaclient_t *, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, uint32, char const *, unsigned int, char const *, unsigned int, tain_t const *, tain_t *) ;
+#define skaclient_start_b(a, sb, path, options, before, beforelen, after, afterlen, deadline, stamp) skaclient_start(a, (sb)->bufs, sizeof((sb)->bufs), (sb)->auxbufs, sizeof((sb)->auxbufs), (sb)->bufa, sizeof((sb)->bufa), (sb)->auxbufa, sizeof((sb)->auxbufa), (sb)->q, sizeof((sb)->q) / sizeof(kolbak_closure_t), path, options, before, beforelen, after, afterlen, deadline, stamp)
+#define skaclient_start_g(a, bufs, bufsn, auxbufs, auxbufsn, bufa, bufan, auxbufa, auxbufan, q, qlen, path, options, before, beforelen, after, afterlen, deadline) skaclient_start(a, bufs, bufsn, auxbufs, auxbufsn, bufa, bufan, auxbufa, auxbufan, q, qlen, path, options, before, beforelen, after, afterlen, (deadline), &STAMP)
+#define skaclient_start_b_g(a, sb, path, options, before, beforelen, after, afterlen, deadline) skaclient_start_b(a, sb, path, options, before, beforelen, after, afterlen, (deadline), &STAMP)
extern int skaclient_startf (skaclient_t *, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, char const *const *, char const *const *, uint32, char const *, unsigned int, char const *, unsigned int, tain_t const *, tain_t *) ;
#define skaclient_startf_b(a, sb, prog, argv, envp, options, before, beforelen, after, afterlen, deadline, stamp) skaclient_startf(a, (sb)->bufs, sizeof((sb)->bufs), (sb)->auxbufs, sizeof((sb)->auxbufs), (sb)->bufa, sizeof((sb)->bufa), (sb)->auxbufa, sizeof((sb)->auxbufa), (sb)->q, sizeof((sb)->q) / sizeof(kolbak_closure_t), prog, argv, envp, options, before, beforelen, after, afterlen, deadline, stamp)
#define skaclient_startf_g(a, bufs, bufsn, auxbufs, auxbufsn, bufa, bufan, auxbufa, auxbufan, q, qlen, prog, argv, envp, options, before, beforelen, after, afterlen, deadline) skaclient_startf(a, bufs, bufsn, auxbufs, auxbufsn, bufa, bufan, auxbufa, auxbufan, q, qlen, prog, argv, envp, options, before, beforelen, after, afterlen, (deadline), &STAMP)
#define skaclient_startf_b_g(a, sb, prog, argv, envp, options, before, beforelen, after, afterlen, deadline) skaclient_startf_b(a, sb, prog, argv, envp, options, before, beforelen, after, afterlen, (deadline), &STAMP)
+
+ /* Writing */
+
extern int skaclient_putmsg_and_close (skaclient_t *, unixmessage_t const *, unsigned char const *, unixmessage_handler_func_t *, void *) ;
#define skaclient_putmsg(a, m, cb, result) skaclient_putmsg_and_close(a, m, unixmessage_bits_closenone, cb, result)
extern int skaclient_putmsgv_and_close (skaclient_t *, unixmessage_v_t const *, unsigned char const *, unixmessage_handler_func_t *, void *) ;
@@ -83,6 +90,9 @@ extern int skaclient_putmsgv_and_close (skaclient_t *, unixmessage_v_t const *,
extern int skaclient_put (skaclient_t *, char const *, unsigned int, unixmessage_handler_func_t *, void *) ;
extern int skaclient_putv (skaclient_t *, siovec_t const *, unsigned int, unixmessage_handler_func_t *, void *) ;
+
+ /* Writing and flushing */
+
extern int skaclient_sendmsg_and_close (skaclient_t *, unixmessage_t const *, unsigned char const *, unixmessage_handler_func_t *, void *, tain_t const *, tain_t *) ;
#define skaclient_sendmsg_and_close_g(a, m, bits, cb, result, deadline) skaclient_sendmsg_and_close(a, m, bits, cb, result, (deadline), &STAMP)
#define skaclient_sendmsg(a, m, cb, result, deadline, stamp) skaclient_sendmsg_and_close(a, m, unixmessage_bits_closenone, cb, result, deadline, stamp)
@@ -98,6 +108,9 @@ extern int skaclient_send (skaclient_t *, char const *, unsigned int, unixmessag
extern int skaclient_sendv (skaclient_t *, siovec_t const *, unsigned int, unixmessage_handler_func_t *, void *, tain_t const *, tain_t *) ;
#define skaclient_sendv_g(a, v, vlen, cb, result, deadline) skaclient_sendv(a, v, vlen, cb, result, (deadline), &STAMP)
+
+ /* Helpers for full async */
+
#define skaclient_sfd(a) unixmessage_receiver_fd(&(a)->syncin)
#define skaclient_siswritable(a) (!unixmessage_sender_isempty(&(a)->syncout))
#define skaclient_flush(a) unixmessage_sender_flush(&(a)->syncout)
@@ -117,6 +130,9 @@ extern int skaclient_syncify (skaclient_t *, tain_t const *, tain_t *) ;
extern unixmessage_handler_func_t skaclient_default_cb ;
+
+ /* When asyncout is actually used (skabus...) */
+
#define skaclient_aiswritable(a) (!unixmessage_sender_isempty(&(a)->asyncout))
#define skaclient_aput_and_close(a, m, bits) unixmessage_put_and_close(&(a)->asyncout, m, bits)
#define skaclient_aputv_and_close(a, m, bits) unixmessage_putv_and_close(&(a)->asyncout, m, bits)
diff --git a/src/include/skalibs/unixmessage.h b/src/include/skalibs/unixmessage.h
@@ -3,6 +3,8 @@
#ifndef UNIXMESSAGE_H
#define UNIXMESSAGE_H
+#include <skalibs/uint16.h>
+#include <skalibs/uint32.h>
#include <skalibs/buffer.h>
#include <skalibs/cbuffer.h>
#include <skalibs/gccattributes.h>
@@ -39,8 +41,9 @@ struct unixmessage_v_s
#define UNIXMESSAGE_V_ZERO { .v = 0, .vlen = 0, .fds = 0, .nfds = 0 }
extern unixmessage_v_t const unixmessage_v_zero ;
-#define UNIXMESSAGE_BUFSIZE 2048
+#define UNIXMESSAGE_MAXSIZE (2U << 27)
#define UNIXMESSAGE_MAXFDS 255
+#define UNIXMESSAGE_BUFSIZE 2048
#define UNIXMESSAGE_AUXBUFSIZE (sizeof(int) * UNIXMESSAGE_MAXFDS + 1)
#define UNIXMESSAGE_MAXREADS 32
@@ -55,9 +58,10 @@ struct unixmessage_sender_s
genalloc fds ; /* int */
genalloc offsets ; /* diuint */
unsigned int head ;
+ unsigned int shorty ;
} ;
#define UNIXMESSAGE_SENDER_ZERO UNIXMESSAGE_SENDER_INIT(-1)
-#define UNIXMESSAGE_SENDER_INIT(s) { .fd = (s), .data = STRALLOC_ZERO, .fds = GENALLOC_ZERO, .offsets = GENALLOC_ZERO, .head = 0 }
+#define UNIXMESSAGE_SENDER_INIT(s) { .fd = (s), .data = STRALLOC_ZERO, .fds = GENALLOC_ZERO, .offsets = GENALLOC_ZERO, .head = 0, .shorty = 0 }
extern unixmessage_sender_t const unixmessage_sender_zero ;
extern void unixmessage_sender_init (unixmessage_sender_t *, int) ;
@@ -87,21 +91,23 @@ struct unixmessage_receiver_s
int fd ;
cbuffer_t mainb ;
cbuffer_t auxb ;
- unsigned int mainlen ;
- unsigned int auxlen ;
stralloc maindata ;
stralloc auxdata ;
+ uint32 mainlen ;
+ uint16 auxlen ;
+ unsigned int fds_ok : 2 ;
} ;
-#define UNIXMESSAGE_RECEIVER_ZERO { .fd = -1, .mainb = CBUFFER_ZERO, .auxb = CBUFFER_ZERO, .mainlen = 0, .auxlen = 0, .maindata = STRALLOC_ZERO, .auxdata = STRALLOC_ZERO }
+#define UNIXMESSAGE_RECEIVER_ZERO { .fd = -1, .mainb = CBUFFER_ZERO, .auxb = CBUFFER_ZERO, .maindata = STRALLOC_ZERO, .auxdata = STRALLOC_ZERO, .mainlen = 0, .auxlen = 0, .fds_ok = 3 }
#define UNIXMESSAGE_RECEIVER_INIT(d, mains, mainn, auxs, auxn) \
{ \
.fd = d, \
.mainb = CBUFFER_INIT(mains, mainn), \
.auxb = CBUFFER_INIT(auxs, auxn), \
+ .maindata = STRALLOC_ZERO, \
+ .auxdata = STRALLOC_ZERO, \
.mainlen = 0, \
.auxlen = 0, \
- .maindata = STRALLOC_ZERO, \
- .auxdata = STRALLOC_ZERO \
+ .fds_ok = 3 \
}
extern int unixmessage_receiver_init (unixmessage_receiver_t *, int, char *, unsigned int, char *, unsigned int) ;
extern void unixmessage_receiver_free (unixmessage_receiver_t *) ;
@@ -113,6 +119,10 @@ extern int unixmessage_receive (unixmessage_receiver_t *, unixmessage_t *) ;
extern int unixmessage_timed_receive (unixmessage_receiver_t *, unixmessage_t *, tain_t const *, tain_t *) ;
#define unixmessage_timed_receive_g(receiver, msg, deadline) unixmessage_timed_receive(receiver, msg, (deadline), &STAMP)
+#define unixmessage_receiver_accept_fds(b) ((b)->fds_ok = 3)
+#define unixmessage_receiver_refuse_fds(b) ((b)->fds_ok = 1)
+#define unixmessage_receiver_ignore_fds(b) ((b)->fds_ok = 0)
+
typedef int unixmessage_handler_func_t (unixmessage_t const *, void *) ;
typedef unixmessage_handler_func_t *unixmessage_handler_func_t_ref ;
@@ -121,6 +131,7 @@ extern int unixmessage_timed_handle (unixmessage_receiver_t *, unixmessage_handl
#define unixmessage_timed_handle_g(b, f, p, deadline) unixmessage_timed_handle(b, f, p, (deadline), &STAMP)
+
/* Globals */
extern unixmessage_receiver_t unixmessage_receiver_0_ ;
diff --git a/src/libunixonacid/skaclient-internal.h b/src/libunixonacid/skaclient-internal.h
@@ -4,12 +4,10 @@
#define SKACLIENT_INTERNAL_H
#include <skalibs/kolbak.h>
-#include <skalibs/skaclient.h>
#include <skalibs/unixmessage.h>
+#include <skalibs/skaclient.h>
extern int skaclient_init (skaclient_t *, int, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, unsigned int) ;
-extern int skaclient_start_async_th (skaclient_t *, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, char const *, unsigned int) ;
-extern int skaclient_startf_async_th (skaclient_t *, char *, unsigned int, char *, unsigned int, char *, unsigned int, char *, unsigned int, kolbak_closure_t *, unsigned int, char const *, char const *const *, char const *const *, uint32, char const *, unsigned int) ;
extern int skaclient_start_cb (unixmessage_t const *, skaclient_cbdata_t *) ;
#endif
diff --git a/src/libunixonacid/skaclient_start.c b/src/libunixonacid/skaclient_start.c
@@ -1,6 +1,7 @@
/* ISC license. */
#include <errno.h>
+#include <skalibs/uint32.h>
#include <skalibs/kolbak.h>
#include <skalibs/skaclient.h>
#include <skalibs/tai.h>
@@ -19,6 +20,7 @@ int skaclient_start (
kolbak_closure_t *q,
unsigned int qlen,
char const *path,
+ uint32 options,
char const *before,
unsigned int beforelen,
char const *after,
@@ -29,7 +31,7 @@ int skaclient_start (
skaclient_cbdata_t blah ;
unixmessage_t m ;
register int r ;
- if (!skaclient_start_async(a, bufss, bufsn, auxbufss, auxbufsn, bufas, bufan, auxbufas, auxbufan, q, qlen, path, before, beforelen, after, afterlen, &blah)) return 0 ;
+ if (!skaclient_start_async(a, bufss, bufsn, auxbufss, auxbufsn, bufas, bufan, auxbufas, auxbufan, q, qlen, path, options, before, beforelen, after, afterlen, &blah)) return 0 ;
if (!skaclient_timed_flush(a, deadline, stamp))
{
register int e = errno ;
diff --git a/src/libunixonacid/skaclient_start_async.c b/src/libunixonacid/skaclient_start_async.c
@@ -1,6 +1,7 @@
/* ISC license. */
#include <errno.h>
+#include <skalibs/uint32.h>
#include <skalibs/error.h>
#include <skalibs/kolbak.h>
#include <skalibs/skaclient.h>
@@ -21,6 +22,7 @@ int skaclient_start_async (
kolbak_closure_t *q,
unsigned int qlen,
char const *path,
+ uint32 options,
char const *before,
unsigned int beforelen,
char const *after,
@@ -38,14 +40,13 @@ int skaclient_start_async (
return 0 ;
}
a->pid = 0 ;
- a->options = 0 ;
+ a->options = options & ~SKACLIENT_OPTION_WAITPID ;
if (!kolbak_enqueue(&a->kq, (unixmessage_handler_func_t_ref)&skaclient_start_cb, blah))
{
skaclient_end(a) ;
return 0 ;
}
- blah->asyncin = &a->asyncin ;
- blah->asyncout = &a->asyncout ;
+ blah->a = a ;
blah->after = after ;
blah->afterlen = afterlen ;
return 1 ;
diff --git a/src/libunixonacid/skaclient_start_cb.c b/src/libunixonacid/skaclient_start_cb.c
@@ -3,16 +3,24 @@
#include <errno.h>
#include <skalibs/bytestr.h>
#include <skalibs/error.h>
-#include <skalibs/skaclient.h>
#include <skalibs/unixmessage.h>
+#include <skalibs/skaclient.h>
#include "skaclient-internal.h"
int skaclient_start_cb (unixmessage_t const *m, skaclient_cbdata_t *blah)
{
if (m->len != blah->afterlen
|| byte_diff(m->s, m->len, blah->after)
- || m->nfds != 1) return (errno = EPROTO, 0) ;
- blah->asyncin->fd = m->fds[0] ;
- blah->asyncout->fd = m->fds[0] ;
+ || m->nfds != 1)
+ {
+ unixmessage_drop(m) ;
+ return (errno = EPROTO, 0) ;
+ }
+ blah->a->asyncin.fd = m->fds[0] ;
+ blah->a->asyncout.fd = m->fds[0] ;
+ if (!(blah->a->options & SKACLIENT_OPTION_ASYNC_ACCEPT_FDS))
+ unixmessage_receiver_refuse_fds(&blah->a->asyncin) ;
+ if (!(blah->a->options & SKACLIENT_OPTION_SYNC_ACCEPT_FDS))
+ unixmessage_receiver_refuse_fds(&blah->a->syncin) ;
return 1 ;
}
diff --git a/src/libunixonacid/skaclient_startf_async.c b/src/libunixonacid/skaclient_startf_async.c
@@ -53,8 +53,7 @@ int skaclient_startf_async (
skaclient_end(a) ;
return 0 ;
}
- blah->asyncin = &a->asyncin ;
- blah->asyncout = &a->asyncout ;
+ blah->a = a ;
blah->after = after ;
blah->afterlen = afterlen ;
return 1 ;
diff --git a/src/libunixonacid/unixmessage_put.c b/src/libunixonacid/unixmessage_put.c
@@ -8,6 +8,7 @@
#include <skalibs/bitarray.h>
#include <skalibs/bytestr.h>
#include <skalibs/diuint.h>
+#include <skalibs/error.h>
#include <skalibs/stralloc.h>
#include <skalibs/genalloc.h>
#include <skalibs/siovec.h>
@@ -49,6 +50,8 @@ static inline int copyfds (char *s, int const *fds, unsigned int n, unsigned cha
static int reserve_and_copy (unixmessage_sender_t *b, unsigned int len, int const *fds, unsigned int nfds, unsigned char const *bits)
{
diuint cur = { .left = b->data.len, .right = b->fds.len } ;
+ if (len > UNIXMESSAGE_MAXSIZE || nfds > UNIXMESSAGE_MAXFDS)
+ return (errno = EPROTO, 0) ;
if (!genalloc_readyplus(diuint, &b->offsets, 1)
|| !genalloc_readyplus(int, &b->fds, nfds)
|| !stralloc_readyplus(&b->data, len))
diff --git a/src/libunixonacid/unixmessage_receive.c b/src/libunixonacid/unixmessage_receive.c
@@ -5,7 +5,8 @@
#include <errno.h>
#include <sys/socket.h>
#include <sys/uio.h>
-#include <skalibs/uint.h>
+#include <skalibs/uint16.h>
+#include <skalibs/uint32.h>
#include <skalibs/cbuffer.h>
#include <skalibs/djbunix.h>
#include <skalibs/error.h>
@@ -45,12 +46,12 @@ static int unixmessage_receiver_fill (unixmessage_receiver_t *b)
.msg_iov = iov,
.msg_iovlen = 2,
.msg_flags = 0,
- .msg_control = ancilbuf,
- .msg_controllen = sizeof(ancilbuf)
+ .msg_control = b->fds_ok & 1 ? ancilbuf : 0,
+ .msg_controllen = b->fds_ok & 1 ? sizeof(ancilbuf) : 0
} ;
unsigned int auxlen ;
int r = -1 ;
- if (cbuffer_isfull(&b->mainb) || cbuffer_isfull(&b->auxb))
+ if (cbuffer_isfull(&b->mainb) || ((b->fds_ok & 1) && cbuffer_isfull(&b->auxb)))
return (errno = ENOBUFS, -1) ;
{
siovec_t v[2] ;
@@ -62,6 +63,7 @@ static int unixmessage_receiver_fill (unixmessage_receiver_t *b)
r = recvmsg(b->fd, &msghdr, awesomeflags) ;
if (!r || (r < 0 && errno != EINTR)) return r ;
}
+ if (b->fds_ok & 1)
{
struct cmsghdr *c = CMSG_FIRSTHDR(&msghdr) ;
if (c)
@@ -69,16 +71,32 @@ static int unixmessage_receiver_fill (unixmessage_receiver_t *b)
if (c->cmsg_level != SOL_SOCKET
|| c->cmsg_type != SCM_RIGHTS) return (errno = EPROTO, -1) ;
auxlen = (unsigned int)(c->cmsg_len - (CMSG_DATA(c) - (unsigned char *)c)) ;
+ if (auxlen && !(b->fds_ok & 2))
+ {
+ register unsigned int i = auxlen/sizeof(int) ;
+ while (i--) fd_close(((int *)CMSG_DATA(c))[i]) ;
+ return (errno = EPROTO, -1) ;
+ }
#ifndef SKALIBS_HASCMSGCLOEXEC
{
register unsigned int i = 0 ;
for (; i < auxlen/sizeof(int) ; i++)
- if (coe(((int *)CMSG_DATA(c))[i]) < 0) return -1 ;
+ if (coe(((int *)CMSG_DATA(c))[i]) < 0)
+ {
+ int e = errno ;
+ i++ ;
+ while (i--) fd_close(((int *)CMSG_DATA(c))[i]) ;
+ errno = e ;
+ return -1 ;
+ }
}
#endif
- if (msghdr.msg_flags & MSG_CTRUNC) return (errno = EPROTO, -1) ;
- if (cbuffer_put(&b->auxb, (char *)CMSG_DATA(c), auxlen) < auxlen)
+ if ((msghdr.msg_flags & MSG_CTRUNC) || cbuffer_put(&b->auxb, (char *)CMSG_DATA(c), auxlen) < auxlen)
+ {
+ register unsigned int i = auxlen/sizeof(int) ;
+ while (i--) fd_close(((int *)CMSG_DATA(c))[i]) ;
return (errno = ENOBUFS, -1) ;
+ }
}
}
cbuffer_WSEEK(&b->mainb, r) ;
@@ -89,21 +107,25 @@ int unixmessage_receive (unixmessage_receiver_t *b, unixmessage_t *m)
{
if (b->maindata.len == b->mainlen && b->auxdata.len == b->auxlen)
{
- char pack[sizeof(unsigned int) << 1] ;
- if (cbuffer_len(&b->mainb) < sizeof(unsigned int) << 1)
+ char pack[6] ;
+ if (cbuffer_len(&b->mainb) < 6)
{
register int r = sanitize_read(unixmessage_receiver_fill(b)) ;
if (r <= 0) return r ;
- if (cbuffer_len(&b->mainb) < sizeof(unsigned int) << 1)
- return (errno = EWOULDBLOCK, 0) ;
+ if (cbuffer_len(&b->mainb) < 6) return (errno = EWOULDBLOCK, 0) ;
}
- cbuffer_get(&b->mainb, pack, sizeof(unsigned int) << 1) ;
- uint_unpack_big(pack, &b->mainlen) ;
- uint_unpack_big(pack + sizeof(unsigned int), &b->auxlen) ;
+ cbuffer_get(&b->mainb, pack, 6) ;
+ uint32_unpack_big(pack, &b->mainlen) ;
+ if (b->fds_ok & 1) uint16_unpack_big(pack + 4, &b->auxlen) ;
+ else b->auxlen = 0 ;
b->auxlen *= sizeof(int) ;
- if (!stralloc_ready(&b->maindata, b->mainlen)) return -1 ;
+ if (b->mainlen > UNIXMESSAGE_MAXSIZE
+ || b->auxlen > ((b->fds_ok & 2) ? UNIXMESSAGE_MAXFDS * sizeof(int) : 0))
+ return (errno = EPROTO, -1) ;
+ if (!stralloc_ready(&b->maindata, b->mainlen)
+ || !stralloc_ready(&b->auxdata, b->auxlen))
+ return -1 ;
b->maindata.len = 0 ;
- if (!stralloc_ready(&b->auxdata, b->auxlen)) return -1 ;
b->auxdata.len = 0 ;
}
@@ -124,6 +146,6 @@ int unixmessage_receive (unixmessage_receiver_t *b, unixmessage_t *m)
m->s = b->maindata.s ;
m->len = b->maindata.len ;
m->fds = (int *)b->auxdata.s ;
- m->nfds = b->auxlen / sizeof(int) ;
+ m->nfds = b->auxdata.len / sizeof(int) ;
return 1 ;
}
diff --git a/src/libunixonacid/unixmessage_receiver_free.c b/src/libunixonacid/unixmessage_receiver_free.c
@@ -1,12 +1,29 @@
/* ISC license. */
#include <skalibs/stralloc.h>
+#include <skalibs/djbunix.h>
#include <skalibs/unixmessage.h>
void unixmessage_receiver_free (unixmessage_receiver_t *b)
{
+ register unsigned int h = b->maindata.len ;
b->fd = -1 ;
stralloc_free(&b->maindata) ;
+ h = h != b->mainlen || b->auxdata.len != b->auxlen || cbuffer_len(&b->auxb) ;
+ if (h)
+ {
+ register unsigned int n = b->auxdata.len / sizeof(int) ;
+ while (n--) fd_close(((int *)b->auxdata.s)[n]) ;
+ }
stralloc_free(&b->auxdata) ;
- b->mainlen = b->auxlen = 0 ;
+ if (h)
+ {
+ register unsigned int n = cbuffer_len(&b->auxb) / sizeof(int) ;
+ if (n)
+ {
+ int fds[n] ;
+ cbuffer_get(&b->auxb, (char *)fds, n * sizeof(int)) ;
+ while (n--) fd_close(fds[n]) ;
+ }
+ }
}
diff --git a/src/libunixonacid/unixmessage_receiver_init.c b/src/libunixonacid/unixmessage_receiver_init.c
@@ -13,5 +13,6 @@ int unixmessage_receiver_init (unixmessage_receiver_t *b, int fd, char *mainbuf,
b->mainlen = b->auxlen = 0 ;
b->maindata = stralloc_zero ;
b->auxdata = stralloc_zero ;
+ b->fds_ok = 3 ;
return 1 ;
}
diff --git a/src/libunixonacid/unixmessage_sender_flush.c b/src/libunixonacid/unixmessage_sender_flush.c
@@ -6,9 +6,10 @@
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
-#include <skalibs/uint.h>
+#include <skalibs/uint16.h>
+#include <skalibs/uint32.h>
#include <skalibs/diuint.h>
-#include <skalibs/stralloc.h>
+#include <skalibs/allreadwrite.h>
#include <skalibs/genalloc.h>
#include <skalibs/djbunix.h>
#include <skalibs/unixmessage.h>
@@ -18,21 +19,51 @@
#define MSG_NOSIGNAL 0
#endif
+ /*
+ XXX: sendmsg/recvmsg is badly, badly specified.
+ XXX: We assume ancillary data is attached to the first byte.
+ */
+
int unixmessage_sender_flush (unixmessage_sender_t *b)
{
- diuint last = { .left = b->data.len, .right = genalloc_len(int, &b->fds) } ;
+ diuint last = { .left = (uint32)b->data.len, .right = genalloc_len(int, &b->fds) } ;
diuint *offsets = genalloc_s(diuint, &b->offsets) ;
unsigned int n = genalloc_len(diuint, &b->offsets) ;
- unsigned int oldhead = b->head ;
+ register int r ;
+
+ if (b->shorty) /* we had a short write, gotta send the remainder first */
+ {
+ diuint *next = b->head+1 < n ? offsets + b->head+1 : &last ;
+ unsigned int len = next->left - offsets[b->head].left ;
+ if (b->shorty <= len)
+ r = fd_write(b->fd, b->data.s + offsets[b->head].left + (len - b->shorty), b->shorty) ;
+ else
+ {
+ unsigned int nfds = next->right - offsets[b->head].right ;
+ char pack[6] ;
+ struct iovec v[2] =
+ {
+ { .iov_base = pack + 6 - (b->shorty - len), .iov_len = b->shorty - len },
+ { .iov_base = b->data.s + offsets[b->head].left, .iov_len = len }
+ } ;
+ uint32_pack_big(pack, (uint32)len) ;
+ uint16_pack_big(pack + 4, (uint16)nfds) ;
+ r = fd_writev(b->fd, v, 2) ;
+ }
+ if (r <= 0) return 0 ;
+ b->shorty -= r ;
+ if (b->shorty) return (errno = EWOULDBLOCK, 0) ;
+ }
+
for (; b->head < n ; b->head++)
{
diuint *next = b->head+1 < n ? offsets + b->head+1 : &last ;
unsigned int len = next->left - offsets[b->head].left ;
unsigned int nfds = next->right - offsets[b->head].right ;
- char pack[sizeof(unsigned int) << 1] ;
+ char pack[6] ;
struct iovec v[2] =
{
- { .iov_base = pack, .iov_len = sizeof(unsigned int) << 1 },
+ { .iov_base = pack, .iov_len = 6 },
{ .iov_base = b->data.s + offsets[b->head].left, .iov_len = len }
} ;
char ancilbuf[CMSG_SPACE(nfds * sizeof(int))] ;
@@ -45,8 +76,8 @@ int unixmessage_sender_flush (unixmessage_sender_t *b)
.msg_control = nfds ? ancilbuf : 0,
.msg_controllen = nfds ? sizeof(ancilbuf) : 0
} ;
- uint_pack_big(pack, len) ;
- uint_pack_big(pack + sizeof(unsigned int), nfds) ;
+ uint32_pack_big(pack, (uint32)len) ;
+ uint16_pack_big(pack + 4, (uint16)nfds) ;
if (nfds)
{
struct cmsghdr *cp = CMSG_FIRSTHDR(&hdr) ;
@@ -60,14 +91,9 @@ int unixmessage_sender_flush (unixmessage_sender_t *b)
((int *)CMSG_DATA(cp))[i] = fd < 0 ? -(fd+1) : fd ;
}
}
- for (;;)
- {
- register int r = sendmsg(b->fd, &hdr, MSG_NOSIGNAL) ;
- if (r == -1 && errno == EINTR) continue ;
- if (r < (int)(len + (sizeof(unsigned int) << 1)))
- return -(int)(b->head-oldhead)-1 ;
- break ;
- }
+ do r = sendmsg(b->fd, &hdr, MSG_NOSIGNAL) ;
+ while (r < 0 && errno == EINTR) ;
+ if (r <= 0) return 0 ;
#ifndef SKALIBS_HASANCILAUTOCLOSE
if (nfds)
{
@@ -79,10 +105,15 @@ int unixmessage_sender_flush (unixmessage_sender_t *b)
}
}
#endif
+ if ((unsigned int)r < 6 + len)
+ {
+ b->shorty = 6 + len - r ;
+ return (errno = EWOULDBLOCK, 0) ;
+ }
}
b->data.len = 0 ;
genalloc_setlen(int, &b->fds, 0) ;
genalloc_setlen(diuint, &b->offsets, 0) ;
b->head = 0 ;
- return (int)(n - oldhead) ;
+ return 1 ;
}