summaryrefslogtreecommitdiffstats
path: root/source3
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2014-06-24 07:39:05 +0200
committerMichael Adam <obnox@samba.org>2014-09-24 08:44:11 +0200
commit64d140197e7d668a773ac2f85c9cabd8c59e4804 (patch)
tree6f26ff1c365c33957508891b0461d53676e5e0f2 /source3
parent1b35d2ed631631f470dc5a7cff54068a832bfafc (diff)
downloadsamba-64d140197e7d668a773ac2f85c9cabd8c59e4804.tar.gz
samba-64d140197e7d668a773ac2f85c9cabd8c59e4804.tar.xz
samba-64d140197e7d668a773ac2f85c9cabd8c59e4804.zip
s3:messaging: make it possible to receive a fd array from another process
In order to receive the fd array the caller needs to use messaging_filtered_read_send/recv(). For all higher level methods we silently close/ignore the fd array. Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Michael Adam <obnox@samba.org>
Diffstat (limited to 'source3')
-rw-r--r--source3/lib/dbwrap/dbwrap_watch.c3
-rw-r--r--source3/lib/messages.c77
-rw-r--r--source3/lib/messages_dgm.c14
-rw-r--r--source3/lib/messages_dgm.h2
-rw-r--r--source3/librpc/idl/messaging.idl2
5 files changed, 85 insertions, 13 deletions
diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c
index a5f1ebd5bf..9ff8fc24b4 100644
--- a/source3/lib/dbwrap/dbwrap_watch.c
+++ b/source3/lib/dbwrap/dbwrap_watch.c
@@ -299,6 +299,9 @@ static bool dbwrap_record_watch_filter(struct messaging_rec *rec,
if (rec->msg_type != MSG_DBWRAP_MODIFIED) {
return false;
}
+ if (rec->num_fds != 0) {
+ return false;
+ }
if (rec->buf.length != state->w_key.dsize) {
return false;
}
diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 0e0259236e..56108abd21 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -204,6 +204,7 @@ bool message_send_all(struct messaging_context *msg_ctx,
}
static void messaging_recv_cb(const uint8_t *msg, size_t msg_len,
+ const int *fds, size_t num_fds,
void *private_data)
{
struct messaging_context *msg_ctx = talloc_get_type_abort(
@@ -211,19 +212,38 @@ static void messaging_recv_cb(const uint8_t *msg, size_t msg_len,
const struct messaging_hdr *hdr;
struct server_id_buf idbuf;
struct messaging_rec rec;
+ int64_t fds64[MIN(num_fds, INT8_MAX)];
+ size_t i;
if (msg_len < sizeof(*hdr)) {
+ for (i=0; i < num_fds; i++) {
+ close(fds[i]);
+ }
DEBUG(1, ("message too short: %u\n", (unsigned)msg_len));
return;
}
+ if (num_fds > INT8_MAX) {
+ for (i=0; i < num_fds; i++) {
+ close(fds[i]);
+ }
+ DEBUG(1, ("too many fds: %u\n", (unsigned)num_fds));
+ return;
+ }
+
+ for (i=0; i < num_fds; i++) {
+ fds64[i] = fds[i];
+ }
+
/*
* messages_dgm guarantees alignment, so we can cast here
*/
hdr = (const struct messaging_hdr *)msg;
- DEBUG(10, ("%s: Received message 0x%x len %u from %s\n", __func__,
- (unsigned)hdr->msg_type, (unsigned)(msg_len - sizeof(*hdr)),
+ DEBUG(10, ("%s: Received message 0x%x len %u (num_fds:%u) from %s\n",
+ __func__, (unsigned)hdr->msg_type,
+ (unsigned)(msg_len - sizeof(*hdr)),
+ (unsigned)num_fds,
server_id_str_buf(hdr->src, &idbuf)));
rec = (struct messaging_rec) {
@@ -232,7 +252,9 @@ static void messaging_recv_cb(const uint8_t *msg, size_t msg_len,
.src = hdr->src,
.dest = hdr->dst,
.buf.data = discard_const_p(uint8, msg) + sizeof(*hdr),
- .buf.length = msg_len - sizeof(*hdr)
+ .buf.length = msg_len - sizeof(*hdr),
+ .num_fds = num_fds,
+ .fds = fds64,
};
messaging_dispatch_rec(msg_ctx, &rec);
@@ -501,9 +523,10 @@ static struct messaging_rec *messaging_rec_dup(TALLOC_CTX *mem_ctx,
struct messaging_rec *rec)
{
struct messaging_rec *result;
+ size_t fds_size = sizeof(int64_t) * rec->num_fds;
- result = talloc_pooled_object(mem_ctx, struct messaging_rec,
- 1, rec->buf.length);
+ result = talloc_pooled_object(mem_ctx, struct messaging_rec, 2,
+ rec->buf.length + fds_size);
if (result == NULL) {
return NULL;
}
@@ -513,6 +536,13 @@ static struct messaging_rec *messaging_rec_dup(TALLOC_CTX *mem_ctx,
result->buf.data = talloc_memdup(result, rec->buf.data,
rec->buf.length);
+
+ result->fds = NULL;
+ if (result->num_fds > 0) {
+ result->fds = talloc_array(result, int64_t, result->num_fds);
+ memcpy(result->fds, rec->fds, fds_size);
+ }
+
return result;
}
@@ -692,6 +722,10 @@ static bool messaging_read_filter(struct messaging_rec *rec,
struct messaging_read_state *state = talloc_get_type_abort(
private_data, struct messaging_read_state);
+ if (rec->num_fds != 0) {
+ return false;
+ }
+
return rec->msg_type == state->msg_type;
}
@@ -825,6 +859,7 @@ void messaging_dispatch_rec(struct messaging_context *msg_ctx,
{
struct messaging_callback *cb, *next;
unsigned i;
+ size_t j;
for (cb = msg_ctx->callbacks; cb != NULL; cb = next) {
next = cb->next;
@@ -832,6 +867,16 @@ void messaging_dispatch_rec(struct messaging_context *msg_ctx,
continue;
}
+ /*
+ * the old style callbacks don't support fd passing
+ */
+ for (j=0; j < rec->num_fds; j++) {
+ int fd = rec->fds[j];
+ close(fd);
+ }
+ rec->num_fds = 0;
+ rec->fds = NULL;
+
if (server_id_same_process(&rec->src, &rec->dest)) {
/*
* This is a self-send. We are called here from
@@ -859,6 +904,12 @@ void messaging_dispatch_rec(struct messaging_context *msg_ctx,
}
if (!messaging_append_new_waiters(msg_ctx)) {
+ for (j=0; j < rec->num_fds; j++) {
+ int fd = rec->fds[j];
+ close(fd);
+ }
+ rec->num_fds = 0;
+ rec->fds = NULL;
return;
}
@@ -889,10 +940,26 @@ void messaging_dispatch_rec(struct messaging_context *msg_ctx,
req, struct messaging_filtered_read_state);
if (state->filter(rec, state->private_data)) {
messaging_filtered_read_done(req, rec);
+
+ /*
+ * Only the first one gets the fd-array
+ */
+ rec->num_fds = 0;
+ rec->fds = NULL;
}
i += 1;
}
+
+ /*
+ * If the fd-array isn't used, just close it.
+ */
+ for (j=0; j < rec->num_fds; j++) {
+ int fd = rec->fds[j];
+ close(fd);
+ }
+ rec->num_fds = 0;
+ rec->fds = NULL;
}
static int mess_parent_dgm_cleanup(void *private_data);
diff --git a/source3/lib/messages_dgm.c b/source3/lib/messages_dgm.c
index 7ba79fcfd0..68307698a5 100644
--- a/source3/lib/messages_dgm.c
+++ b/source3/lib/messages_dgm.c
@@ -44,6 +44,8 @@ struct messaging_dgm_context {
void (*recv_cb)(const uint8_t *msg,
size_t msg_len,
+ const int *fds,
+ size_t num_fds,
void *private_data);
void *recv_cb_private_data;
@@ -179,6 +181,8 @@ int messaging_dgm_init(struct tevent_context *ev,
uid_t dir_owner,
void (*recv_cb)(const uint8_t *msg,
size_t msg_len,
+ const int *fds,
+ size_t num_fds,
void *private_data),
void *recv_cb_private_data)
{
@@ -330,15 +334,9 @@ static void messaging_dgm_recv(struct unix_msg_ctx *ctx,
{
struct messaging_dgm_context *dgm_ctx = talloc_get_type_abort(
private_data, struct messaging_dgm_context);
- size_t i;
- /* for now we ignore passed file descriptors */
- for (i = 0; i < num_fds; i++) {
- close(fds[i]);
- fds[i] = -1;
- }
-
- dgm_ctx->recv_cb(msg, msg_len, dgm_ctx->recv_cb_private_data);
+ dgm_ctx->recv_cb(msg, msg_len, fds, num_fds,
+ dgm_ctx->recv_cb_private_data);
}
int messaging_dgm_cleanup(pid_t pid)
diff --git a/source3/lib/messages_dgm.h b/source3/lib/messages_dgm.h
index 169d863219..3c915c18ef 100644
--- a/source3/lib/messages_dgm.h
+++ b/source3/lib/messages_dgm.h
@@ -26,6 +26,8 @@ int messaging_dgm_init(struct tevent_context *ev,
uid_t dir_owner,
void (*recv_cb)(const uint8_t *msg,
size_t msg_len,
+ const int *fds,
+ size_t num_fds,
void *private_data),
void *recv_cb_private_data);
void messaging_dgm_destroy(void);
diff --git a/source3/librpc/idl/messaging.idl b/source3/librpc/idl/messaging.idl
index 66d4ae598c..ce40a7bb25 100644
--- a/source3/librpc/idl/messaging.idl
+++ b/source3/librpc/idl/messaging.idl
@@ -130,5 +130,7 @@ interface messaging
server_id dest;
server_id src;
DATA_BLOB buf;
+ uint8 num_fds;
+ dlong fds[num_fds];
} messaging_rec;
}