chiark
/
gitweb
/
~ianmdlvl
/
elogind.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
bus: fix memfd-cache regarding memfd offsets
[elogind.git]
/
src
/
libsystemd
/
sd-bus
/
bus-message.c
diff --git
a/src/libsystemd/sd-bus/bus-message.c
b/src/libsystemd/sd-bus/bus-message.c
index 9fdf0d7e8117d842b6d98add0e893bf7bd676f76..0803999e070fc81e24dcd072b6ec53e7a674e4f9 100644
(file)
--- a/
src/libsystemd/sd-bus/bus-message.c
+++ b/
src/libsystemd/sd-bus/bus-message.c
@@
-65,17
+65,19
@@
static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
/* If we can reuse the memfd, try that. For that it
* can't be sealed yet. */
/* If we can reuse the memfd, try that. For that it
* can't be sealed yet. */
- if (!part->sealed)
+ if (!part->sealed) {
+ assert(part->memfd_offset == 0);
+ assert(part->data == part->mmap_begin);
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);
}
} 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);
@@
-429,10
+431,10
@@
int bus_message_from_header(
if (m->creds.pid > 0)
m->creds.mask |= SD_BUS_CREDS_PID;
if (m->creds.pid > 0)
m->creds.mask |= SD_BUS_CREDS_PID;
- if (m->creds.uid !=
(uid_t) -1
)
+ if (m->creds.uid !=
UID_INVALID
)
m->creds.mask |= SD_BUS_CREDS_UID;
m->creds.mask |= SD_BUS_CREDS_UID;
- if (m->creds.gid !=
(gid_t) -1
)
+ if (m->creds.gid !=
GID_INVALID
)
m->creds.mask |= SD_BUS_CREDS_GID;
}
m->creds.mask |= SD_BUS_CREDS_GID;
}
@@
-1103,8
+1105,10
@@
static int part_make_space(
if (m->poisoned)
return -ENOMEM;
if (m->poisoned)
return -ENOMEM;
- if (!part->data && part->memfd < 0)
+ if (!part->data && part->memfd < 0)
{
part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
+ part->mmap_begin = part->data;
+ }
if (part->memfd >= 0) {
if (part->memfd >= 0) {
@@
-1128,15
+1132,16
@@
static int part_make_space(
if (part->mapped <= 0)
n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
else
if (part->mapped <= 0)
n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
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;
@@
-2063,6
+2068,7
@@
static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c)
assert(m);
assert(c);
assert(m);
assert(c);
+ assert(c->signature);
if (!BUS_MESSAGE_IS_GVARIANT(m))
return 0;
if (!BUS_MESSAGE_IS_GVARIANT(m))
return 0;
@@
-2502,10
+2508,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;
@@
-2561,26
+2568,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)
@@
-2590,16
+2597,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;
@@
-2619,6
+2634,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 = offset;
part->sealed = true;
part->size = size;
copy_fd = -1;
part->sealed = true;
part->size = size;
copy_fd = -1;
@@
-2629,16
+2645,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);
@@
-2650,10
+2672,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;
@@
-2694,6
+2721,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 = offset;
part->sealed = true;
part->size = size;
copy_fd = -1;
part->sealed = true;
part->size = size;
copy_fd = -1;
@@
-2857,7
+2885,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);
@@
-2874,10
+2902,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,
0
);
+ 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
@@
-2887,7
+2916,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;
@@
-2900,14
+2930,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;
@@
-5333,35
+5364,57
@@
_public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
return 1;
}
return 1;
}
-const char* bus_message_get_arg(sd_bus_message *m, unsigned i) {
- int r;
- const char *t = NULL;
+int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
+ const char *contents;
unsigned j;
unsigned j;
+ char type;
+ int r;
assert(m);
assert(m);
+ assert(str);
+ assert(strv);
r = sd_bus_message_rewind(m, true);
if (r < 0)
r = sd_bus_message_rewind(m, true);
if (r < 0)
- return
NULL
;
+ return
r
;
- for (j = 0; j <= i; j++) {
- char type;
+ for (j = 0;; j++) {
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ENXIO;
+
+ /* Don't match against arguments after the first one we don't understand */
+ if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
+ !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
+ return -ENXIO;
+
+ if (j >= i)
+ break;
- r = sd_bus_message_
peek_type(m, &type
, NULL);
+ r = sd_bus_message_
skip(m
, NULL);
if (r < 0)
if (r < 0)
- return NULL;
+ return r;
+ }
- if (type != SD_BUS_TYPE_STRING &&
- type != SD_BUS_TYPE_OBJECT_PATH &&
- type != SD_BUS_TYPE_SIGNATURE)
- return NULL;
+ if (type == SD_BUS_TYPE_ARRAY) {
- r = sd_bus_message_read_
basic(m, type, &t
);
+ r = sd_bus_message_read_
strv(m, strv
);
if (r < 0)
if (r < 0)
- return NULL;
+ return r;
+
+ *str = NULL;
+
+ } else {
+ r = sd_bus_message_read_basic(m, type, str);
+ if (r < 0)
+ return r;
+
+ *strv = NULL;
}
}
- return
t
;
+ return
0
;
}
bool bus_header_is_complete(struct bus_header *h, size_t size) {
}
bool bus_header_is_complete(struct bus_header *h, size_t size) {