1
0
mirror of https://github.com/systemd/systemd.git synced 2024-11-02 02:21:44 +03:00

sd-bus: properly support passing memfds around with offset/size parameters

This commit is contained in:
Lennart Poettering 2014-12-09 18:07:46 +01:00
parent 77adde6382
commit 7dcd79c295
4 changed files with 75 additions and 40 deletions

View File

@ -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); bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
else { else {
if (part->mapped > 0) 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); safe_close(part->memfd);
} }
} else if (part->munmap_this) } else if (part->munmap_this)
munmap(part->data, part->mapped); munmap(part->mmap_begin, part->mapped);
else if (part->free_this) else if (part->free_this)
free(part->data); free(part->data);
@ -1126,17 +1126,18 @@ static int part_make_space(
psz = PAGE_ALIGN(sz > 0 ? sz : 1); psz = PAGE_ALIGN(sz > 0 ? sz : 1);
if (part->mapped <= 0) 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) { if (n == MAP_FAILED) {
m->poisoned = true; m->poisoned = true;
return -errno; 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, _public_ int sd_bus_message_append_array(
char type, sd_bus_message *m,
const void *ptr, char type,
size_t size) { const void *ptr,
size_t size) {
int r; int r;
void *p; 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, _public_ int sd_bus_message_append_array_memfd(
char type, sd_bus_message *m,
int memfd) { char type,
int memfd,
uint64_t offset,
uint64_t size) {
_cleanup_close_ int copy_fd = -1; _cleanup_close_ int copy_fd = -1;
struct bus_body_part *part; struct bus_body_part *part;
ssize_t align, sz; ssize_t align, sz;
uint64_t size; uint64_t real_size;
void *a; void *a;
int r; int r;
if (!m) assert_return(m, -EINVAL);
return -EINVAL; assert_return(memfd >= 0, -EINVAL);
if (memfd < 0) assert_return(bus_type_is_trivial(type), -EINVAL);
return -EINVAL; assert_return(size > 0, -EINVAL);
if (m->sealed) assert_return(!m->sealed, -EPERM);
return -EPERM; assert_return(!m->poisoned, -ESTALE);
if (!bus_type_is_trivial(type))
return -EINVAL;
if (m->poisoned)
return -ESTALE;
r = memfd_set_sealed(memfd); r = memfd_set_sealed(memfd);
if (r < 0) if (r < 0)
@ -2591,16 +2593,24 @@ _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
if (copy_fd < 0) if (copy_fd < 0)
return copy_fd; return copy_fd;
r = memfd_get_size(memfd, &size); r = memfd_get_size(memfd, &real_size);
if (r < 0) if (r < 0)
return r; 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); align = bus_type_get_alignment(type);
sz = bus_type_get_size(type); sz = bus_type_get_size(type);
assert_se(align > 0); assert_se(align > 0);
assert_se(sz > 0); assert_se(sz > 0);
if (offset % align != 0)
return -EINVAL;
if (size % sz != 0) if (size % sz != 0)
return -EINVAL; return -EINVAL;
@ -2620,7 +2630,7 @@ _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m,
return -ENOMEM; return -ENOMEM;
part->memfd = copy_fd; part->memfd = copy_fd;
part->memfd_offset = 0; part->memfd_offset = offset;
part->sealed = true; part->sealed = true;
part->size = size; part->size = size;
copy_fd = -1; 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; _cleanup_close_ int copy_fd = -1;
struct bus_body_part *part; struct bus_body_part *part;
struct bus_container *c; struct bus_container *c;
uint64_t size; uint64_t real_size;
void *a; void *a;
int r; int r;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
assert_return(memfd >= 0, -EINVAL); assert_return(memfd >= 0, -EINVAL);
assert_return(size > 0, -EINVAL);
assert_return(!m->sealed, -EPERM); assert_return(!m->sealed, -EPERM);
assert_return(!m->poisoned, -ESTALE); 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) if (copy_fd < 0)
return copy_fd; return copy_fd;
r = memfd_get_size(memfd, &size); r = memfd_get_size(memfd, &real_size);
if (r < 0) if (r < 0)
return r; 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 */ /* We require this to be NUL terminated */
if (size == 0) if (size == 0)
return -EINVAL; return -EINVAL;
@ -2696,7 +2717,7 @@ _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) {
return -ENOMEM; return -ENOMEM;
part->memfd = copy_fd; part->memfd = copy_fd;
part->memfd_offset = 0; part->memfd_offset = offset;
part->sealed = true; part->sealed = true;
part->size = size; part->size = size;
copy_fd = -1; 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) { int bus_body_part_map(struct bus_body_part *part) {
void *p; 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) else if (part->is_zero)
p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
else else
@ -2890,7 +2912,8 @@ int bus_body_part_map(struct bus_body_part *part) {
return -errno; return -errno;
part->mapped = psz; part->mapped = psz;
part->data = p; part->mmap_begin = p;
part->data = (uint8_t*) p + shift;
part->munmap_this = true; part->munmap_this = true;
return 0; return 0;
@ -2903,14 +2926,15 @@ void bus_body_part_unmap(struct bus_body_part *part) {
if (part->memfd < 0) if (part->memfd < 0)
return; return;
if (!part->data) if (!part->mmap_begin)
return; return;
if (!part->munmap_this) if (!part->munmap_this)
return; 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->data = NULL;
part->mapped = 0; part->mapped = 0;
part->munmap_this = false; part->munmap_this = false;

View File

@ -55,10 +55,11 @@ struct bus_container {
struct bus_body_part { struct bus_body_part {
struct bus_body_part *next; struct bus_body_part *next;
void *data; void *data;
void *mmap_begin;
size_t size; size_t size;
size_t mapped; size_t mapped;
size_t allocated; size_t allocated;
size_t memfd_offset; uint64_t memfd_offset;
int memfd; int memfd;
bool free_this:1; bool free_this:1;
bool munmap_this:1; bool munmap_this:1;

View File

@ -48,6 +48,7 @@ int main(int argc, char *argv[]) {
uint32_t u32; uint32_t u32;
size_t i, l; size_t i, l;
char *s; 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(r >= 0);
assert_se(sz == STRING_SIZE); 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); assert_se(r >= 0);
close(f); close(f);
@ -124,7 +125,7 @@ int main(int argc, char *argv[]) {
assert_se(r >= 0); assert_se(r >= 0);
assert_se(sz == SECOND_ARRAY); 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); assert_se(r >= 0);
close(f); close(f);
@ -135,6 +136,11 @@ int main(int argc, char *argv[]) {
r = sd_bus_message_append(m, "u", 4711); r = sd_bus_message_append(m, "u", 4711);
assert_se(r >= 0); 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); r = bus_message_seal(m, 55, 99*USEC_PER_SEC);
assert_se(r >= 0); assert_se(r >= 0);
@ -188,6 +194,10 @@ int main(int argc, char *argv[]) {
assert_se(r > 0); assert_se(r > 0);
assert_se(u32 == 4711); 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_message_unref(m);
sd_bus_unref(a); sd_bus_unref(a);

View File

@ -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(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_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_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_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_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_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_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_close_container(sd_bus_message *m);