chiark
/
gitweb
/
~ianmdlvl
/
elogind.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
|
inline
| side by side (parent:
77adde6
)
sd-bus: properly support passing memfds around with offset/size parameters
author
Lennart Poettering
<lennart@poettering.net>
Tue, 9 Dec 2014 17:07:46 +0000
(18:07 +0100)
committer
Lennart Poettering
<lennart@poettering.net>
Tue, 9 Dec 2014 17:07:46 +0000
(18:07 +0100)
src/libsystemd/sd-bus/bus-message.c
patch
|
blob
|
history
src/libsystemd/sd-bus/bus-message.h
patch
|
blob
|
history
src/libsystemd/sd-bus/test-bus-zero-copy.c
patch
|
blob
|
history
src/systemd/sd-bus.h
patch
|
blob
|
history
diff --git
a/src/libsystemd/sd-bus/bus-message.c
b/src/libsystemd/sd-bus/bus-message.c
index ad417c0f100bc6d6f209d5018f109f3ec55d2df6..06d8d770fdba6e0f8d4b86064c6408b8cd495b92 100644
(file)
--- a/
src/libsystemd/sd-bus/bus-message.c
+++ b/
src/libsystemd/sd-bus/bus-message.c
@@
-69,13
+69,13
@@
static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
else {
if (part->mapped > 0)
bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
else {
if (part->mapped > 0)
- assert_se(munmap(part->
data
, part->mapped) == 0);
+ assert_se(munmap(part->
mmap_begin
, part->mapped) == 0);
safe_close(part->memfd);
}
} else if (part->munmap_this)
safe_close(part->memfd);
}
} else if (part->munmap_this)
- munmap(part->
data
, part->mapped);
+ munmap(part->
mmap_begin
, part->mapped);
else if (part->free_this)
free(part->data);
else if (part->free_this)
free(part->data);
@@
-1126,17
+1126,18
@@
static int part_make_space(
psz = PAGE_ALIGN(sz > 0 ? sz : 1);
if (part->mapped <= 0)
psz = PAGE_ALIGN(sz > 0 ? sz : 1);
if (part->mapped <= 0)
- n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd,
part->memfd_offset
);
+ n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd,
0
);
else
else
- n = mremap(part->
data
, part->mapped, psz, MREMAP_MAYMOVE);
+ n = mremap(part->
mmap_begin
, part->mapped, psz, MREMAP_MAYMOVE);
if (n == MAP_FAILED) {
m->poisoned = true;
return -errno;
}
if (n == MAP_FAILED) {
m->poisoned = true;
return -errno;
}
+ part->mmap_begin = part->data = n;
part->mapped = psz;
part->mapped = psz;
- part->
data = n
;
+ part->
memfd_offset = 0
;
}
part->munmap_this = true;
}
part->munmap_this = true;
@@
-2503,10
+2504,11
@@
_public_ int sd_bus_message_append_array_space(
return 0;
}
return 0;
}
-_public_ int sd_bus_message_append_array(sd_bus_message *m,
- char type,
- const void *ptr,
- size_t size) {
+_public_ int sd_bus_message_append_array(
+ sd_bus_message *m,
+ char type,
+ const void *ptr,
+ size_t size) {
int r;
void *p;
int r;
void *p;
@@
-2562,26
+2564,26
@@
_public_ int sd_bus_message_append_array_iovec(
return 0;
}
return 0;
}
-_public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
- char type,
- int memfd) {
+_public_ int sd_bus_message_append_array_memfd(
+ sd_bus_message *m,
+ char type,
+ int memfd,
+ uint64_t offset,
+ uint64_t size) {
+
_cleanup_close_ int copy_fd = -1;
struct bus_body_part *part;
ssize_t align, sz;
_cleanup_close_ int copy_fd = -1;
struct bus_body_part *part;
ssize_t align, sz;
- uint64_t size;
+ uint64_t
real_
size;
void *a;
int r;
void *a;
int r;
- if (!m)
- return -EINVAL;
- if (memfd < 0)
- return -EINVAL;
- if (m->sealed)
- return -EPERM;
- if (!bus_type_is_trivial(type))
- return -EINVAL;
- if (m->poisoned)
- return -ESTALE;
+ assert_return(m, -EINVAL);
+ assert_return(memfd >= 0, -EINVAL);
+ assert_return(bus_type_is_trivial(type), -EINVAL);
+ assert_return(size > 0, -EINVAL);
+ assert_return(!m->sealed, -EPERM);
+ assert_return(!m->poisoned, -ESTALE);
r = memfd_set_sealed(memfd);
if (r < 0)
r = memfd_set_sealed(memfd);
if (r < 0)
@@
-2591,16
+2593,24
@@
_public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
if (copy_fd < 0)
return copy_fd;
if (copy_fd < 0)
return copy_fd;
- r = memfd_get_size(memfd, &size);
+ r = memfd_get_size(memfd, &
real_
size);
if (r < 0)
return r;
if (r < 0)
return r;
+ if (offset == 0 && size == (uint64_t) -1)
+ size = real_size;
+ else if (offset + size > real_size)
+ return -EMSGSIZE;
+
align = bus_type_get_alignment(type);
sz = bus_type_get_size(type);
assert_se(align > 0);
assert_se(sz > 0);
align = bus_type_get_alignment(type);
sz = bus_type_get_size(type);
assert_se(align > 0);
assert_se(sz > 0);
+ if (offset % align != 0)
+ return -EINVAL;
+
if (size % sz != 0)
return -EINVAL;
if (size % sz != 0)
return -EINVAL;
@@
-2620,7
+2630,7
@@
_public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
return -ENOMEM;
part->memfd = copy_fd;
return -ENOMEM;
part->memfd = copy_fd;
- part->memfd_offset =
0
;
+ part->memfd_offset =
offset
;
part->sealed = true;
part->size = size;
copy_fd = -1;
part->sealed = true;
part->size = size;
copy_fd = -1;
@@
-2631,16
+2641,22
@@
_public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
return sd_bus_message_close_container(m);
}
return sd_bus_message_close_container(m);
}
-_public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) {
+_public_ int sd_bus_message_append_string_memfd(
+ sd_bus_message *m,
+ int memfd,
+ uint64_t offset,
+ uint64_t size) {
+
_cleanup_close_ int copy_fd = -1;
struct bus_body_part *part;
struct bus_container *c;
_cleanup_close_ int copy_fd = -1;
struct bus_body_part *part;
struct bus_container *c;
- uint64_t size;
+ uint64_t
real_
size;
void *a;
int r;
assert_return(m, -EINVAL);
assert_return(memfd >= 0, -EINVAL);
void *a;
int r;
assert_return(m, -EINVAL);
assert_return(memfd >= 0, -EINVAL);
+ assert_return(size > 0, -EINVAL);
assert_return(!m->sealed, -EPERM);
assert_return(!m->poisoned, -ESTALE);
assert_return(!m->sealed, -EPERM);
assert_return(!m->poisoned, -ESTALE);
@@
-2652,10
+2668,15
@@
_public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) {
if (copy_fd < 0)
return copy_fd;
if (copy_fd < 0)
return copy_fd;
- r = memfd_get_size(memfd, &size);
+ r = memfd_get_size(memfd, &
real_
size);
if (r < 0)
return r;
if (r < 0)
return r;
+ if (offset == 0 && size == (uint64_t) -1)
+ size = real_size;
+ else if (offset + size > real_size)
+ return -EMSGSIZE;
+
/* We require this to be NUL terminated */
if (size == 0)
return -EINVAL;
/* We require this to be NUL terminated */
if (size == 0)
return -EINVAL;
@@
-2696,7
+2717,7
@@
_public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) {
return -ENOMEM;
part->memfd = copy_fd;
return -ENOMEM;
part->memfd = copy_fd;
- part->memfd_offset =
0
;
+ part->memfd_offset =
offset
;
part->sealed = true;
part->size = size;
copy_fd = -1;
part->sealed = true;
part->size = size;
copy_fd = -1;
@@
-2860,7
+2881,7
@@
int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
int bus_body_part_map(struct bus_body_part *part) {
void *p;
int bus_body_part_map(struct bus_body_part *part) {
void *p;
- size_t psz;
+ size_t psz
, shift
;
assert_se(part);
assert_se(part);
@@
-2877,10
+2898,11
@@
int bus_body_part_map(struct bus_body_part *part) {
return 0;
}
return 0;
}
- psz = PAGE_ALIGN(part->size);
+ shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
+ psz = PAGE_ALIGN(part->size + shift);
if (part->memfd >= 0)
if (part->memfd >= 0)
- p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset);
+ p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset
- shift
);
else if (part->is_zero)
p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
else
else if (part->is_zero)
p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
else
@@
-2890,7
+2912,8
@@
int bus_body_part_map(struct bus_body_part *part) {
return -errno;
part->mapped = psz;
return -errno;
part->mapped = psz;
- part->data = p;
+ part->mmap_begin = p;
+ part->data = (uint8_t*) p + shift;
part->munmap_this = true;
return 0;
part->munmap_this = true;
return 0;
@@
-2903,14
+2926,15
@@
void bus_body_part_unmap(struct bus_body_part *part) {
if (part->memfd < 0)
return;
if (part->memfd < 0)
return;
- if (!part->
data
)
+ if (!part->
mmap_begin
)
return;
if (!part->munmap_this)
return;
return;
if (!part->munmap_this)
return;
- assert_se(munmap(part->
data
, part->mapped) == 0);
+ assert_se(munmap(part->
mmap_begin
, part->mapped) == 0);
+ part->mmap_begin = NULL;
part->data = NULL;
part->mapped = 0;
part->munmap_this = false;
part->data = NULL;
part->mapped = 0;
part->munmap_this = false;
diff --git
a/src/libsystemd/sd-bus/bus-message.h
b/src/libsystemd/sd-bus/bus-message.h
index db5f90c5de226341e7d5b7ecab1d48099e8f643c..4dd280dcf04ea25c7e1cc8c15ae949e62f662177 100644
(file)
--- a/
src/libsystemd/sd-bus/bus-message.h
+++ b/
src/libsystemd/sd-bus/bus-message.h
@@
-55,10
+55,11
@@
struct bus_container {
struct bus_body_part {
struct bus_body_part *next;
void *data;
struct bus_body_part {
struct bus_body_part *next;
void *data;
+ void *mmap_begin;
size_t size;
size_t mapped;
size_t allocated;
size_t size;
size_t mapped;
size_t allocated;
-
size
_t memfd_offset;
+
uint64
_t memfd_offset;
int memfd;
bool free_this:1;
bool munmap_this:1;
int memfd;
bool free_this:1;
bool munmap_this:1;
diff --git
a/src/libsystemd/sd-bus/test-bus-zero-copy.c
b/src/libsystemd/sd-bus/test-bus-zero-copy.c
index 2cc671b16d16932be0d316cb8f91ac2a622f4f27..a054f74bf3b74da5d7427aebe763aada9ca0c3bb 100644
(file)
--- a/
src/libsystemd/sd-bus/test-bus-zero-copy.c
+++ b/
src/libsystemd/sd-bus/test-bus-zero-copy.c
@@
-48,6
+48,7
@@
int main(int argc, char *argv[]) {
uint32_t u32;
size_t i, l;
char *s;
uint32_t u32;
size_t i, l;
char *s;
+ _cleanup_close_ int sfd = -1;
log_set_max_level(LOG_DEBUG);
log_set_max_level(LOG_DEBUG);
@@
-107,7
+108,7
@@
int main(int argc, char *argv[]) {
assert_se(r >= 0);
assert_se(sz == STRING_SIZE);
assert_se(r >= 0);
assert_se(sz == STRING_SIZE);
- r = sd_bus_message_append_string_memfd(m, f);
+ r = sd_bus_message_append_string_memfd(m, f
, 0, (uint64_t) -1
);
assert_se(r >= 0);
close(f);
assert_se(r >= 0);
close(f);
@@
-124,7
+125,7
@@
int main(int argc, char *argv[]) {
assert_se(r >= 0);
assert_se(sz == SECOND_ARRAY);
assert_se(r >= 0);
assert_se(sz == SECOND_ARRAY);
- r = sd_bus_message_append_array_memfd(m, 'y', f);
+ r = sd_bus_message_append_array_memfd(m, 'y', f
, 0, (uint64_t) -1
);
assert_se(r >= 0);
close(f);
assert_se(r >= 0);
close(f);
@@
-135,6
+136,11
@@
int main(int argc, char *argv[]) {
r = sd_bus_message_append(m, "u", 4711);
assert_se(r >= 0);
r = sd_bus_message_append(m, "u", 4711);
assert_se(r >= 0);
+ assert_se((sfd = memfd_new_and_map(NULL, 6, (void**) &p)) >= 0);
+ memcpy(p, "abcd\0", 6);
+ munmap(p, 6);
+ assert_se(sd_bus_message_append_string_memfd(m, sfd, 1, 4) >= 0);
+
r = bus_message_seal(m, 55, 99*USEC_PER_SEC);
assert_se(r >= 0);
r = bus_message_seal(m, 55, 99*USEC_PER_SEC);
assert_se(r >= 0);
@@
-188,6
+194,10
@@
int main(int argc, char *argv[]) {
assert_se(r > 0);
assert_se(u32 == 4711);
assert_se(r > 0);
assert_se(u32 == 4711);
+ r = sd_bus_message_read(m, "s", &s);
+ assert_se(r > 0);
+ assert_se(streq_ptr(s, "bcd"));
+
sd_bus_message_unref(m);
sd_bus_unref(a);
sd_bus_message_unref(m);
sd_bus_unref(a);
diff --git
a/src/systemd/sd-bus.h
b/src/systemd/sd-bus.h
index f5fd37a6628bea7487ca5c710410c6360a1ea3b5..3636d66fbb2fb152c24b2b7a3c1c0d2fe79376f2 100644
(file)
--- a/
src/systemd/sd-bus.h
+++ b/
src/systemd/sd-bus.h
@@
-261,10
+261,10
@@
int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p);
int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size);
int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size, void **ptr);
int sd_bus_message_append_array_iovec(sd_bus_message *m, char type, const struct iovec *iov, unsigned n);
int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size);
int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size, void **ptr);
int sd_bus_message_append_array_iovec(sd_bus_message *m, char type, const struct iovec *iov, unsigned n);
-int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, int memfd);
+int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, int memfd
, uint64_t offset, uint64_t size
);
int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s);
int sd_bus_message_append_string_iovec(sd_bus_message *m, const struct iovec *iov, unsigned n);
int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s);
int sd_bus_message_append_string_iovec(sd_bus_message *m, const struct iovec *iov, unsigned n);
-int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd);
+int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd
, uint64_t offset, uint64_t size
);
int sd_bus_message_append_strv(sd_bus_message *m, char **l);
int sd_bus_message_open_container(sd_bus_message *m, char type, const char *contents);
int sd_bus_message_close_container(sd_bus_message *m);
int sd_bus_message_append_strv(sd_bus_message *m, char **l);
int sd_bus_message_open_container(sd_bus_message *m, char type, const char *contents);
int sd_bus_message_close_container(sd_bus_message *m);