From e07bbb7c503dca966b307e7af21e2efbc6f45b89 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Fri, 15 Aug 2014 18:21:18 +0200 Subject: sd-event: fix missing needs_rearm --- src/libsystemd/sd-event/sd-event.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 1e3afaeacc..3a9d934aad 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -894,6 +894,8 @@ _public_ int sd_event_add_time( s->userdata = userdata; s->enabled = SD_EVENT_ONESHOT; + d->needs_rearm = true; + r = prioq_put(d->earliest, s, &s->time.earliest_index); if (r < 0) goto fail; @@ -902,8 +904,6 @@ _public_ int sd_event_add_time( if (r < 0) goto fail; - d->needs_rearm = true; - if (ret) *ret = s; @@ -1872,6 +1872,7 @@ static int process_timer( prioq_reshuffle(d->earliest, s, &s->time.earliest_index); prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; } return 0; -- cgit v1.2.3-54-g00ecf From 050f74f286b12945e3eb13a45dca92783fa65bb8 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Fri, 15 Aug 2014 19:15:30 +0200 Subject: sd-event: return 'r' rather than '-errno' --- src/libsystemd/sd-event/sd-event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 3a9d934aad..7917ab934a 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -779,7 +779,7 @@ _public_ int sd_event_add_io( r = source_io_register(s, s->enabled, events); if (r < 0) { source_free(s); - return -errno; + return r; } if (ret) @@ -1060,7 +1060,7 @@ _public_ int sd_event_add_child( r = event_update_signal_fd(e); if (r < 0) { source_free(s); - return -errno; + return r; } } -- cgit v1.2.3-54-g00ecf From f1e3bee216b9eac1d5b00415617cb2ff5e894c10 Mon Sep 17 00:00:00 2001 From: Thomas Hindoe Paaboel Andersen Date: Sat, 16 Aug 2014 00:31:23 +0200 Subject: sd-bus,log: remove unused variables --- src/libsystemd/sd-bus/bus-objects.c | 1 - src/shared/log.c | 1 - 2 files changed, 2 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c index 78dab8048d..00e8e9655b 100644 --- a/src/libsystemd/sd-bus/bus-objects.c +++ b/src/libsystemd/sd-bus/bus-objects.c @@ -287,7 +287,6 @@ static int node_callbacks_run( #define CAPABILITY_SHIFT(x) (((x) >> __builtin_ctzll(_SD_BUS_VTABLE_CAPABILITY_MASK)) & 0xFFFF) static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; uint64_t cap; int r; diff --git a/src/shared/log.c b/src/shared/log.c index b730ac921a..26c604afd8 100644 --- a/src/shared/log.c +++ b/src/shared/log.c @@ -908,7 +908,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { } void log_parse_environment(void) { - _cleanup_free_ char *line = NULL; const char *e; parse_proc_cmdline(parse_proc_cmdline_item); -- cgit v1.2.3-54-g00ecf From a6a4f528899b1dab47408733b4a423c66ea40f7a Mon Sep 17 00:00:00 2001 From: Thomas Hindoe Paaboel Andersen Date: Sat, 16 Aug 2014 23:18:32 +0200 Subject: networkctl: use safe_qsort in case no links are present Unlikely to happen but still... --- src/network/networkctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 6253cbf582..2a7a1daf0f 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -141,7 +141,7 @@ static int decode_and_sort_links(sd_rtnl_message *m, LinkInfo **ret) { c++; } - qsort(links, c, sizeof(LinkInfo), link_info_compare); + qsort_safe(links, c, sizeof(LinkInfo), link_info_compare); *ret = links; links = NULL; -- cgit v1.2.3-54-g00ecf From a6082d778ee4b97ec3eb6d3266cefc024c5d60f7 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Tue, 13 May 2014 01:28:09 +0200 Subject: kdbus: switch over to generic memfd implementation (ABI+API break) --- Makefile.am | 4 - src/libsystemd/sd-bus/PORTING-DBUS1 | 40 -------- src/libsystemd/sd-bus/bus-kernel.c | 21 +--- src/libsystemd/sd-bus/bus-message.c | 10 +- src/libsystemd/sd-bus/kdbus.h | 51 ---------- src/libsystemd/sd-bus/sd-memfd.c | 54 ++++------ src/libsystemd/sd-bus/test-bus-memfd.c | 180 --------------------------------- src/shared/missing.h | 44 ++++++++ src/systemd/sd-memfd.h | 2 +- 9 files changed, 73 insertions(+), 333 deletions(-) delete mode 100644 src/libsystemd/sd-bus/test-bus-memfd.c diff --git a/Makefile.am b/Makefile.am index b95ddf2b4c..cfa51cc3b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2571,7 +2571,6 @@ tests += \ test-bus-kernel \ test-bus-kernel-bloom \ test-bus-kernel-benchmark \ - test-bus-memfd \ test-bus-zero-copy \ test-bus-introspect \ test-bus-objects \ @@ -2725,9 +2724,6 @@ test_bus_kernel_benchmark_LDADD = \ libsystemd-internal.la \ libsystemd-shared.la -test_bus_memfd_SOURCES = \ - src/libsystemd/sd-bus/test-bus-memfd.c - test_bus_memfd_LDADD = \ libsystemd-internal.la \ libsystemd-shared.la diff --git a/src/libsystemd/sd-bus/PORTING-DBUS1 b/src/libsystemd/sd-bus/PORTING-DBUS1 index 6205e32736..9f0a91d695 100644 --- a/src/libsystemd/sd-bus/PORTING-DBUS1 +++ b/src/libsystemd/sd-bus/PORTING-DBUS1 @@ -362,46 +362,6 @@ ioctl()s are added for a single match strings. MEMFDS -The "memfd" concept is used for zero-copy data transfers (see -above). memfds are file descriptors to memory chunks of arbitrary -sizes. If you have a memfd you can mmap() it to get access to the data -it contains or write to it. They are comparable to file descriptors to -unlinked files on a tmpfs, or to anonymous memory that one may refer -to with an fd. They have one particular property: they can be -"sealed". A memfd that is "sealed" is protected from alteration. Only -memfds that are currently not mapped and to which a single fd refers -may be sealed (they may also be unsealed in that case). - -The concept of "sealing" makes memfds useful for using them as -transport for kdbus messages: only when the receiver knows that the -message it has received cannot change while looking at, it can safely -parse it without having to copy it to a safe memory area. memfds can also -be reused in multiple messages. A sender may send the same memfd to -multiple peers, and since it is sealed, it can be sure that the receiver -will not be able to modify it. "Sealing" hence provides both sides of -a transaction with the guarantee that the data stays constant and is -reusable. - -memfds are a generic concept that can be used outside of the immediate -kdbus usecase. You can send them across AF_UNIX sockets too, sealed or -unsealed. In kdbus themselves, they can be used to send zero-copy -payloads, but may also be sent as normal fds. - -memfds are allocated with the KDBUS_CMD_MEMFD_NEW ioctl. After allocation, -simply memory map them and write to them. To set their size, use -KDBUS_CMD_MEMFD_SIZE_SET. Note that memfds will be increased in size -automatically if you touch previously unallocated pages. However, the -size will only be increased in multiples of the page size in that -case. Thus, in almost all cases, an explicit KDBUS_CMD_MEMFD_SIZE_SET -is necessary, since it allows setting memfd sizes in finer -granularity. To seal a memfd use the KDBUS_CMD_MEMFD_SEAL_SET ioctl -call. It will only succeed if the caller has the only fd reference to -the memfd open, and if the memfd is currently unmapped. - -If memfds are shared, keep in mind that the file pointer used by -write/read/seek is shared too, only pread/pwrite are safe to use -in that case. - memfds may be sent across kdbus via KDBUS_ITEM_PAYLOAD_MEMFD items attached to messages. If this is done, the data included in the memfd is considered part of the payload stream of a message, and are treated diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index 8b961c38eb..4156b90265 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -1111,9 +1111,6 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *al if (bus->n_memfd_cache <= 0) { _cleanup_free_ char *g = NULL; - struct kdbus_cmd_memfd_make *cmd; - struct kdbus_item *item; - size_t l, sz; int r; assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0); @@ -1124,26 +1121,14 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *al if (!g) return -ENOMEM; - l = strlen(g); - sz = ALIGN8(offsetof(struct kdbus_cmd_memfd_make, items)) + - ALIGN8(offsetof(struct kdbus_item, str)) + - l + 1; - cmd = alloca0(sz); - cmd->size = sz; - - item = cmd->items; - item->size = ALIGN8(offsetof(struct kdbus_item, str)) + l + 1; - item->type = KDBUS_ITEM_MEMFD_NAME; - memcpy(item->str, g, l + 1); - - r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, cmd); + r = memfd_create(g, 0, MFD_ALLOW_SEALING); if (r < 0) return -errno; *address = NULL; *mapped = 0; *allocated = 0; - return cmd->fd; + return r; } c = &bus->memfd_cache[--bus->n_memfd_cache]; @@ -1195,7 +1180,7 @@ void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, si /* If overly long, let's return a bit to the OS */ if (mapped > max_mapped) { - assert_se(ioctl(fd, KDBUS_CMD_MEMFD_SIZE_SET, &max_mapped) >= 0); + assert_se(ftruncate(fd, max_mapped) >= 0); assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0); c->mapped = c->allocated = max_mapped; } else { diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 4768a1fa9e..79dc471d41 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -1076,7 +1076,7 @@ static int part_make_space( uint64_t new_allocated; new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1); - r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &new_allocated); + r = ftruncate(part->memfd, new_allocated); if (r < 0) { m->poisoned = true; return -errno; @@ -2546,7 +2546,7 @@ _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, if (m->poisoned) return -ESTALE; - r = sd_memfd_set_sealed(memfd, true); + r = sd_memfd_set_sealed(memfd); if (r < 0) return r; @@ -2606,7 +2606,7 @@ _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *mem assert_return(!m->sealed, -EPERM); assert_return(!m->poisoned, -ESTALE); - r = sd_memfd_set_sealed(memfd, true); + r = sd_memfd_set_sealed(memfd); if (r < 0) return r; @@ -2799,11 +2799,11 @@ int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) { /* Then, sync up real memfd size */ sz = part->size; - if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &sz) < 0) + if (ftruncate(part->memfd, sz) < 0) return -errno; /* Finally, try to seal */ - if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0) + if (fcntl(part->memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE) >= 0) part->sealed = true; } } diff --git a/src/libsystemd/sd-bus/kdbus.h b/src/libsystemd/sd-bus/kdbus.h index b060330cb6..3751f9ca24 100644 --- a/src/libsystemd/sd-bus/kdbus.h +++ b/src/libsystemd/sd-bus/kdbus.h @@ -733,24 +733,6 @@ struct kdbus_cmd_match { struct kdbus_item items[0]; } __attribute__((aligned(8))); -/** - * struct kdbus_cmd_memfd_make - create a kdbus memfd - * @size: The total size of the struct - * @file_size: The initial file size - * @fd: The returned file descriptor number - * @__pad: Padding to ensure proper alignement - * @items: A list of items for additional information - * - * This structure is used with the KDBUS_CMD_MEMFD_NEW ioctl. - */ -struct kdbus_cmd_memfd_make { - __u64 size; - __u64 file_size; - int fd; - __u32 __pad; - struct kdbus_item items[0]; -} __attribute__((aligned(8))); - /** * enum kdbus_ioctl_type - Ioctl API * @KDBUS_CMD_BUS_MAKE: After opening the "control" device node, this @@ -801,32 +783,6 @@ struct kdbus_cmd_memfd_make { * @KDBUS_CMD_MATCH_ADD: Install a match which broadcast messages should * be delivered to the connection. * @KDBUS_CMD_MATCH_REMOVE: Remove a current match for broadcast messages. - * @KDBUS_CMD_MEMFD_NEW: Return a new file descriptor which provides an - * anonymous shared memory file and which can be - * used to pass around larger chunks of data. - * Kdbus memfd files can be sealed, which allows - * the receiver to trust the data it has received. - * Kdbus memfd files expose only very limited - * operations, they can be mmap()ed, seek()ed, - * (p)read(v)() and (p)write(v)(); most other - * common file operations are not implemented. - * Special caution needs to be taken with - * read(v)()/write(v)() on a shared file; the - * underlying file position is always shared - * between all users of the file and race against - * each other, pread(v)()/pwrite(v)() avoid these - * issues. - * @KDBUS_CMD_MEMFD_SIZE_GET: Return the size of the underlying file, which - * changes with write(). - * @KDBUS_CMD_MEMFD_SIZE_SET: Truncate the underlying file to the specified - * size. - * @KDBUS_CMD_MEMFD_SEAL_GET: Return the state of the file sealing. - * @KDBUS_CMD_MEMFD_SEAL_SET: Seal or break a seal of the file. Only files - * which are not shared with other processes and - * which are currently not mapped can be sealed. - * The current process needs to be the one and - * single owner of the file, the sealing cannot - * be changed as long as the file is shared. */ enum kdbus_ioctl_type { KDBUS_CMD_BUS_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x00, @@ -866,13 +822,6 @@ enum kdbus_ioctl_type { struct kdbus_cmd_match), KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOCTL_MAGIC, 0x81, struct kdbus_cmd_match), - - KDBUS_CMD_MEMFD_NEW = _IOWR(KDBUS_IOCTL_MAGIC, 0xc0, - struct kdbus_cmd_memfd_make), - KDBUS_CMD_MEMFD_SIZE_GET = _IOR(KDBUS_IOCTL_MAGIC, 0xc1, __u64 *), - KDBUS_CMD_MEMFD_SIZE_SET = _IOW(KDBUS_IOCTL_MAGIC, 0xc2, __u64 *), - KDBUS_CMD_MEMFD_SEAL_GET = _IOR(KDBUS_IOCTL_MAGIC, 0xc3, int *), - KDBUS_CMD_MEMFD_SEAL_SET = _IO(KDBUS_IOCTL_MAGIC, 0xc4), }; /* diff --git a/src/libsystemd/sd-bus/sd-memfd.c b/src/libsystemd/sd-bus/sd-memfd.c index fcf3e73124..16d09e3e14 100644 --- a/src/libsystemd/sd-bus/sd-memfd.c +++ b/src/libsystemd/sd-bus/sd-memfd.c @@ -26,8 +26,8 @@ #include #include "util.h" -#include "kdbus.h" #include "bus-label.h" +#include "missing.h" #include "sd-memfd.h" #include "sd-bus.h" @@ -39,11 +39,8 @@ struct sd_memfd { _public_ int sd_memfd_new(sd_memfd **m, const char *name) { - struct kdbus_cmd_memfd_make *cmd; - struct kdbus_item *item; _cleanup_close_ int kdbus = -1; _cleanup_free_ char *g = NULL; - size_t sz, l; sd_memfd *n; assert_return(m, -EINVAL); @@ -89,42 +86,28 @@ _public_ int sd_memfd_new(sd_memfd **m, const char *name) { } } - l = strlen(name); - sz = ALIGN8(offsetof(struct kdbus_cmd_memfd_make, items)) + - ALIGN8(offsetof(struct kdbus_item, str)) + - l + 1; - - cmd = alloca0(sz); - cmd->size = sz; - - item = cmd->items; - item->size = ALIGN8(offsetof(struct kdbus_item, str)) + l + 1; - item->type = KDBUS_ITEM_MEMFD_NAME; - memcpy(item->str, name, l + 1); - - if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, cmd) < 0) - return -errno; - n = new0(struct sd_memfd, 1); - if (!n) { - safe_close(cmd->fd); + if (!n) return -ENOMEM; + + n->fd = memfd_create(name, 0, MFD_ALLOW_SEALING); + if (n->fd < 0) { + free(n); + return -errno; } - n->fd = cmd->fd; *m = n; return 0; } _public_ int sd_memfd_new_from_fd(sd_memfd **m, int fd) { sd_memfd *n; - uint64_t sz; assert_return(m, -EINVAL); assert_return(fd >= 0, -EINVAL); - /* Check if this is a valid memfd */ - if (ioctl(fd, KDBUS_CMD_MEMFD_SIZE_GET, &sz) < 0) + /* Check if this is a sealable fd */ + if (fcntl(fd, F_GET_SEALS) < 0) return -ENOTTY; n = new0(struct sd_memfd, 1); @@ -193,7 +176,7 @@ _public_ int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) { if (sealed < 0) return sealed; - q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, offset); + q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_PRIVATE, m->fd, offset); if (q == MAP_FAILED) return -errno; @@ -201,12 +184,12 @@ _public_ int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) { return 0; } -_public_ int sd_memfd_set_sealed(sd_memfd *m, int b) { +_public_ int sd_memfd_set_sealed(sd_memfd *m) { int r; assert_return(m, -EINVAL); - r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_SET, b); + r = fcntl(m->fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); if (r < 0) return -errno; @@ -214,27 +197,30 @@ _public_ int sd_memfd_set_sealed(sd_memfd *m, int b) { } _public_ int sd_memfd_get_sealed(sd_memfd *m) { - int r, b; + int r; assert_return(m, -EINVAL); - r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_GET, &b); + r = fcntl(m->fd, F_GET_SEALS); if (r < 0) return -errno; - return !!b; + return (r & (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE)) == + (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); } _public_ int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) { int r; + struct stat stat; assert_return(m, -EINVAL); assert_return(sz, -EINVAL); - r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_GET, sz); + r = fstat(m->fd, &stat); if (r < 0) return -errno; + *sz = stat.st_size; return r; } @@ -243,7 +229,7 @@ _public_ int sd_memfd_set_size(sd_memfd *m, uint64_t sz) { assert_return(m, -EINVAL); - r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz); + r = ftruncate(m->fd, sz); if (r < 0) return -errno; diff --git a/src/libsystemd/sd-bus/test-bus-memfd.c b/src/libsystemd/sd-bus/test-bus-memfd.c deleted file mode 100644 index 3462732546..0000000000 --- a/src/libsystemd/sd-bus/test-bus-memfd.c +++ /dev/null @@ -1,180 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include - -#include "log.h" -#include "macro.h" -#include "util.h" - -#include "sd-memfd.h" - -int main(int argc, char *argv[]) { - sd_memfd *m; - char *s, *name; - uint64_t sz; - int r, fd; - FILE *f = NULL; - char buf[3] = {}; - struct iovec iov[3] = {}; - char bufv[3][3] = {}; - - log_set_max_level(LOG_DEBUG); - - r = sd_memfd_new(&m, NULL); - if (r == -ENOENT) - return EXIT_TEST_SKIP; - - assert_se(r >= 0); - - assert_se(sd_memfd_get_name(m, &name) >= 0); - log_info("name: %s", name); - free(name); - - r = sd_memfd_map(m, 0, 12, (void**) &s); - assert_se(r >= 0); - - strcpy(s, "----- world"); - - r = sd_memfd_set_sealed(m, 1); - assert_se(r == -ETXTBSY); - - assert_se(write(sd_memfd_get_fd(m), "he", 2) == 2); - assert_se(write(sd_memfd_get_fd(m), "XXX", 3) == 3); - assert_se(streq(s, "heXXX world")); - - /* fix "hello" */ - assert_se(lseek(sd_memfd_get_fd(m), 2, SEEK_SET) == 2); - assert_se(write(sd_memfd_get_fd(m), "ll", 2) == 2); - - assert_se(sd_memfd_get_file(m, &f) >= 0); - fputc('o', f); - fflush(f); - - /* check content */ - assert_se(streq(s, "hello world")); - - assert_se(munmap(s, 12) == 0); - - r = sd_memfd_get_sealed(m); - assert_se(r == 0); - - r = sd_memfd_get_size(m, &sz); - assert_se(r >= 0); - assert_se(sz = page_size()); - - /* truncate it */ - r = sd_memfd_set_size(m, 6); - assert_se(r >= 0); - - /* get back new value */ - r = sd_memfd_get_size(m, &sz); - assert_se(r >= 0); - assert_se(sz == 6); - - r = sd_memfd_set_sealed(m, 1); - assert_se(r >= 0); - - r = sd_memfd_get_sealed(m); - assert_se(r == 1); - - fd = sd_memfd_dup_fd(m); - assert_se(fd >= 0); - - sd_memfd_free(m); - - /* new sd_memfd, same underlying memfd */ - r = sd_memfd_new_from_fd(&m, fd); - assert_se(r >= 0); - - /* we did truncate it to 6 */ - r = sd_memfd_get_size(m, &sz); - assert_se(r >= 0 && sz == 6); - - /* map it, check content */ - r = sd_memfd_map(m, 0, 12, (void **)&s); - assert_se(r >= 0); - - /* we only see the truncated size */ - assert_se(streq(s, "hello ")); - - /* it was already sealed */ - r = sd_memfd_set_sealed(m, 1); - assert_se(r == -EALREADY); - - /* we cannot break the seal, it is mapped */ - r = sd_memfd_set_sealed(m, 0); - assert_se(r == -ETXTBSY); - - /* unmap it; become the single owner */ - assert_se(munmap(s, 12) == 0); - - /* now we can do flip the sealing */ - r = sd_memfd_set_sealed(m, 0); - assert_se(r == 0); - r = sd_memfd_get_sealed(m); - assert_se(r == 0); - - r = sd_memfd_set_sealed(m, 1); - assert_se(r == 0); - r = sd_memfd_get_sealed(m); - assert_se(r == 1); - - r = sd_memfd_set_sealed(m, 0); - assert_se(r == 0); - r = sd_memfd_get_sealed(m); - assert_se(r == 0); - - /* seek at 2, read() 2 bytes */ - assert_se(lseek(fd, 2, SEEK_SET) == 2); - assert_se(read(fd, buf, 2) == 2); - - /* check content */ - assert_se(memcmp(buf, "ll", 2) == 0); - - /* writev it out*/ - iov[0].iov_base = (char *)"ABC"; - iov[0].iov_len = 3; - iov[1].iov_base = (char *)"DEF"; - iov[1].iov_len = 3; - iov[2].iov_base = (char *)"GHI"; - iov[2].iov_len = 3; - assert_se(pwritev(fd, iov, 3, 0) == 9); - - /* readv it back */ - iov[0].iov_base = bufv[0]; - iov[0].iov_len = 3; - iov[1].iov_base = bufv[1]; - iov[1].iov_len = 3; - iov[2].iov_base = bufv[2]; - iov[2].iov_len = 3; - assert_se(preadv(fd, iov, 3, 0) == 9); - - /* check content */ - assert_se(memcmp(bufv[0], "ABC", 3) == 0); - assert_se(memcmp(bufv[1], "DEF", 3) == 0); - assert_se(memcmp(bufv[2], "GHI", 3) == 0); - - sd_memfd_free(m); - - return 0; -} diff --git a/src/shared/missing.h b/src/shared/missing.h index 195edfc672..3a7e67e384 100644 --- a/src/shared/missing.h +++ b/src/shared/missing.h @@ -64,6 +64,34 @@ #define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8) #endif +#ifndef F_ADD_SEALS +#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) +#endif + +#ifndef F_GET_SEALS +#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) +#endif + +#ifndef F_SEAL_SEAL +#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ +#endif + +#ifndef F_SEAL_SHRINK +#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ +#endif + +#ifndef F_SEAL_GROW +#define F_SEAL_GROW 0x0004 /* prevent file from growing */ +#endif + +#ifndef F_SEAL_WRITE +#define F_SEAL_WRITE 0x0008 /* prevent writes */ +#endif + +#ifndef MFD_ALLOW_SEALING +#define MFD_ALLOW_SEALING 0x0002ULL +#endif + #ifndef IP_FREEBIND #define IP_FREEBIND 15 #endif @@ -109,6 +137,13 @@ static inline int pivot_root(const char *new_root, const char *put_old) { # ifndef __NR_fanotify_mark # define __NR_fanotify_mark 301 # endif +# ifndef __NR_memfd_create +# define __NR_memfd_create 319 +# endif +#elif defined __arm__ +# ifndef __NR_memfd_create +# define __NR_memfd_create 385 +# endif #elif defined _MIPS_SIM # if _MIPS_SIM == _MIPS_SIM_ABI32 # ifndef __NR_fanotify_init @@ -139,6 +174,9 @@ static inline int pivot_root(const char *new_root, const char *put_old) { # ifndef __NR_fanotify_mark # define __NR_fanotify_mark 339 # endif +# ifndef __NR_memfd_create +# define __NR_memfd_create 356 +# endif #endif #ifndef HAVE_FANOTIFY_INIT @@ -166,6 +204,12 @@ static inline int fanotify_mark(int fanotify_fd, unsigned int flags, uint64_t ma } #endif +#ifndef HAVE_MEMFD_CREATE +static inline int memfd_create(const char *name, uint64_t size, uint64_t flags) { + return syscall(__NR_memfd_create, name, size, flags); +} +#endif + #ifndef BTRFS_IOCTL_MAGIC #define BTRFS_IOCTL_MAGIC 0x94 #endif diff --git a/src/systemd/sd-memfd.h b/src/systemd/sd-memfd.h index 753ed68cd8..6de045c1d7 100644 --- a/src/systemd/sd-memfd.h +++ b/src/systemd/sd-memfd.h @@ -44,7 +44,7 @@ int sd_memfd_get_file(sd_memfd *m, FILE **f); int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p); -int sd_memfd_set_sealed(sd_memfd *m, int b); +int sd_memfd_set_sealed(sd_memfd *m); int sd_memfd_get_sealed(sd_memfd *m); int sd_memfd_get_size(sd_memfd *m, uint64_t *sz); -- cgit v1.2.3-54-g00ecf From 93bd9b2ecfdafcf0bd895336634c40d68b06d54e Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 18 Aug 2014 10:45:49 +0200 Subject: Makefile.am: test-bus-memfd went away. Kill its residues in Makefile.am --- Makefile.am | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index cfa51cc3b7..dbaed73bd5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2724,10 +2724,6 @@ test_bus_kernel_benchmark_LDADD = \ libsystemd-internal.la \ libsystemd-shared.la -test_bus_memfd_LDADD = \ - libsystemd-internal.la \ - libsystemd-shared.la - test_bus_zero_copy_SOURCES = \ src/libsystemd/sd-bus/test-bus-zero-copy.c -- cgit v1.2.3-54-g00ecf From 43bde981ccc57c744f164a9d95d46c7ce8f21808 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 18 Aug 2014 10:55:49 +0200 Subject: memfd: move code from public library to src/shared Don't expose generic kernel API via libsystemd, but keep the code internal for our own usage. --- Makefile.am | 5 +- src/libsystemd/libsystemd.sym.m4 | 14 -- src/libsystemd/sd-bus/sd-memfd.c | 308 ----------------------------- src/libsystemd/sd-bus/test-bus-zero-copy.c | 2 +- src/shared/memfd.c | 308 +++++++++++++++++++++++++++++ src/shared/memfd.h | 57 ++++++ src/systemd/sd-bus.h | 2 +- src/systemd/sd-memfd.h | 57 ------ 8 files changed, 369 insertions(+), 384 deletions(-) delete mode 100644 src/libsystemd/sd-bus/sd-memfd.c create mode 100644 src/shared/memfd.c create mode 100644 src/shared/memfd.h delete mode 100644 src/systemd/sd-memfd.h diff --git a/Makefile.am b/Makefile.am index dbaed73bd5..b9deaa653b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -860,6 +860,8 @@ libsystemd_shared_la_SOURCES = \ src/shared/copy.h \ src/shared/base-filesystem.c \ src/shared/base-filesystem.h \ + src/shared/memfd.c \ + src/shared/memfd.h \ src/shared/nss-util.h nodist_libsystemd_shared_la_SOURCES = \ @@ -2382,7 +2384,6 @@ libsystemd_internal_la_SOURCES = \ src/systemd/sd-bus.h \ src/systemd/sd-bus-protocol.h \ src/systemd/sd-bus-vtable.h \ - src/systemd/sd-memfd.h \ src/systemd/sd-utf8.h \ src/systemd/sd-event.h \ src/systemd/sd-rtnl.h \ @@ -2432,7 +2433,6 @@ libsystemd_internal_la_SOURCES = \ src/libsystemd/sd-bus/bus-slot.h \ src/libsystemd/sd-bus/bus-protocol.h \ src/libsystemd/sd-bus/kdbus.h \ - src/libsystemd/sd-bus/sd-memfd.c \ src/libsystemd/sd-utf8/sd-utf8.c \ src/libsystemd/sd-event/sd-event.c \ src/libsystemd/sd-event/event-util.h \ @@ -2550,7 +2550,6 @@ pkginclude_HEADERS += \ src/systemd/sd-bus.h \ src/systemd/sd-bus-protocol.h \ src/systemd/sd-bus-vtable.h \ - src/systemd/sd-memfd.h \ src/systemd/sd-utf8.h \ src/systemd/sd-event.h \ src/systemd/sd-rtnl.h \ diff --git a/src/libsystemd/libsystemd.sym.m4 b/src/libsystemd/libsystemd.sym.m4 index 1c24cad105..415d89afbe 100644 --- a/src/libsystemd/libsystemd.sym.m4 +++ b/src/libsystemd/libsystemd.sym.m4 @@ -359,20 +359,6 @@ global: sd_bus_track_first; sd_bus_track_next; - /* sd-memfd */ - sd_memfd_new; - sd_memfd_new_and_map; - sd_memfd_free; - sd_memfd_get_fd; - sd_memfd_get_file; - sd_memfd_dup_fd; - sd_memfd_map; - sd_memfd_set_sealed; - sd_memfd_get_sealed; - sd_memfd_get_size; - sd_memfd_set_size; - sd_memfd_get_name; - /* sd-event */ sd_event_default; sd_event_new; diff --git a/src/libsystemd/sd-bus/sd-memfd.c b/src/libsystemd/sd-bus/sd-memfd.c deleted file mode 100644 index 16d09e3e14..0000000000 --- a/src/libsystemd/sd-bus/sd-memfd.c +++ /dev/null @@ -1,308 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2013 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include -#include -#include - -#include "util.h" -#include "bus-label.h" -#include "missing.h" - -#include "sd-memfd.h" -#include "sd-bus.h" - -struct sd_memfd { - int fd; - FILE *f; -}; - -_public_ int sd_memfd_new(sd_memfd **m, const char *name) { - - _cleanup_close_ int kdbus = -1; - _cleanup_free_ char *g = NULL; - sd_memfd *n; - - assert_return(m, -EINVAL); - - kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC); - if (kdbus < 0) - return -errno; - - if (name) { - /* The kernel side is pretty picky about the character - * set here, let's do the usual bus escaping to deal - * with that. */ - - g = bus_label_escape(name); - if (!g) - return -ENOMEM; - - name = g; - - } else { - char pr[17] = {}; - - /* If no name is specified we generate one. We include - * a hint indicating our library implementation, and - * add the thread name to it */ - - assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0); - - if (isempty(pr)) - name = "sd"; - else { - _cleanup_free_ char *e = NULL; - - e = bus_label_escape(pr); - if (!e) - return -ENOMEM; - - g = strappend("sd-", e); - if (!g) - return -ENOMEM; - - name = g; - } - } - - n = new0(struct sd_memfd, 1); - if (!n) - return -ENOMEM; - - n->fd = memfd_create(name, 0, MFD_ALLOW_SEALING); - if (n->fd < 0) { - free(n); - return -errno; - } - - *m = n; - return 0; -} - -_public_ int sd_memfd_new_from_fd(sd_memfd **m, int fd) { - sd_memfd *n; - - assert_return(m, -EINVAL); - assert_return(fd >= 0, -EINVAL); - - /* Check if this is a sealable fd */ - if (fcntl(fd, F_GET_SEALS) < 0) - return -ENOTTY; - - n = new0(struct sd_memfd, 1); - if (!n) - return -ENOMEM; - - n->fd = fd; - *m = n; - - return 0; -} - -_public_ void sd_memfd_free(sd_memfd *m) { - if (!m) - return; - - if (m->f) - fclose(m->f); - else - safe_close(m->fd); - - free(m); -} - -_public_ int sd_memfd_get_fd(sd_memfd *m) { - assert_return(m, -EINVAL); - - return m->fd; -} - -_public_ int sd_memfd_get_file(sd_memfd *m, FILE **f) { - assert_return(m, -EINVAL); - assert_return(f, -EINVAL); - - if (!m->f) { - m->f = fdopen(m->fd, "r+"); - if (!m->f) - return -errno; - } - - *f = m->f; - return 0; -} - -_public_ int sd_memfd_dup_fd(sd_memfd *m) { - int fd; - - assert_return(m, -EINVAL); - - fd = fcntl(m->fd, F_DUPFD_CLOEXEC, 3); - if (fd < 0) - return -errno; - - return fd; -} - -_public_ int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) { - void *q; - int sealed; - - assert_return(m, -EINVAL); - assert_return(size > 0, -EINVAL); - assert_return(p, -EINVAL); - - sealed = sd_memfd_get_sealed(m); - if (sealed < 0) - return sealed; - - q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_PRIVATE, m->fd, offset); - if (q == MAP_FAILED) - return -errno; - - *p = q; - return 0; -} - -_public_ int sd_memfd_set_sealed(sd_memfd *m) { - int r; - - assert_return(m, -EINVAL); - - r = fcntl(m->fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); - if (r < 0) - return -errno; - - return 0; -} - -_public_ int sd_memfd_get_sealed(sd_memfd *m) { - int r; - - assert_return(m, -EINVAL); - - r = fcntl(m->fd, F_GET_SEALS); - if (r < 0) - return -errno; - - return (r & (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE)) == - (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); -} - -_public_ int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) { - int r; - struct stat stat; - - assert_return(m, -EINVAL); - assert_return(sz, -EINVAL); - - r = fstat(m->fd, &stat); - if (r < 0) - return -errno; - - *sz = stat.st_size; - return r; -} - -_public_ int sd_memfd_set_size(sd_memfd *m, uint64_t sz) { - int r; - - assert_return(m, -EINVAL); - - r = ftruncate(m->fd, sz); - if (r < 0) - return -errno; - - return r; -} - -_public_ int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p) { - sd_memfd *n; - int r; - - r = sd_memfd_new(&n, name); - if (r < 0) - return r; - - r = sd_memfd_set_size(n, sz); - if (r < 0) { - sd_memfd_free(n); - return r; - } - - r = sd_memfd_map(n, 0, sz, p); - if (r < 0) { - sd_memfd_free(n); - return r; - } - - *m = n; - return 0; -} - -_public_ int sd_memfd_get_name(sd_memfd *m, char **name) { - char path[sizeof("/proc/self/fd/") + DECIMAL_STR_MAX(int)], buf[FILENAME_MAX+1], *e; - const char *delim, *end; - _cleanup_free_ char *n = NULL; - ssize_t k; - - assert_return(m, -EINVAL); - assert_return(name, -EINVAL); - - sprintf(path, "/proc/self/fd/%i", m->fd); - - k = readlink(path, buf, sizeof(buf)); - if (k < 0) - return -errno; - - if ((size_t) k >= sizeof(buf)) - return -E2BIG; - - buf[k] = 0; - - delim = strstr(buf, ":["); - if (!delim) - return -EIO; - - delim = strchr(delim + 2, ':'); - if (!delim) - return -EIO; - - delim++; - - end = strchr(delim, ']'); - if (!end) - return -EIO; - - n = strndup(delim, end - delim); - if (!n) - return -ENOMEM; - - e = bus_label_unescape(n); - if (!e) - return -ENOMEM; - - *name = e; - - return 0; -} diff --git a/src/libsystemd/sd-bus/test-bus-zero-copy.c b/src/libsystemd/sd-bus/test-bus-zero-copy.c index 29e40aa0af..e4a87ab3c5 100644 --- a/src/libsystemd/sd-bus/test-bus-zero-copy.c +++ b/src/libsystemd/sd-bus/test-bus-zero-copy.c @@ -24,9 +24,9 @@ #include "util.h" #include "log.h" +#include "memfd.h" #include "sd-bus.h" -#include "sd-memfd.h" #include "bus-message.h" #include "bus-error.h" #include "bus-kernel.h" diff --git a/src/shared/memfd.c b/src/shared/memfd.c new file mode 100644 index 0000000000..4dd70a2473 --- /dev/null +++ b/src/shared/memfd.c @@ -0,0 +1,308 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include + +#include "util.h" +#include "bus-label.h" +#include "missing.h" +#include "memfd.h" + +#include "sd-bus.h" + +struct sd_memfd { + int fd; + FILE *f; +}; + +int sd_memfd_new(sd_memfd **m, const char *name) { + + _cleanup_close_ int kdbus = -1; + _cleanup_free_ char *g = NULL; + sd_memfd *n; + + assert_return(m, -EINVAL); + + kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC); + if (kdbus < 0) + return -errno; + + if (name) { + /* The kernel side is pretty picky about the character + * set here, let's do the usual bus escaping to deal + * with that. */ + + g = bus_label_escape(name); + if (!g) + return -ENOMEM; + + name = g; + + } else { + char pr[17] = {}; + + /* If no name is specified we generate one. We include + * a hint indicating our library implementation, and + * add the thread name to it */ + + assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0); + + if (isempty(pr)) + name = "sd"; + else { + _cleanup_free_ char *e = NULL; + + e = bus_label_escape(pr); + if (!e) + return -ENOMEM; + + g = strappend("sd-", e); + if (!g) + return -ENOMEM; + + name = g; + } + } + + n = new0(struct sd_memfd, 1); + if (!n) + return -ENOMEM; + + n->fd = memfd_create(name, 0, MFD_ALLOW_SEALING); + if (n->fd < 0) { + free(n); + return -errno; + } + + *m = n; + return 0; +} + +int sd_memfd_new_from_fd(sd_memfd **m, int fd) { + sd_memfd *n; + + assert_return(m, -EINVAL); + assert_return(fd >= 0, -EINVAL); + + /* Check if this is a sealable fd */ + if (fcntl(fd, F_GET_SEALS) < 0) + return -ENOTTY; + + n = new0(struct sd_memfd, 1); + if (!n) + return -ENOMEM; + + n->fd = fd; + *m = n; + + return 0; +} + +void sd_memfd_free(sd_memfd *m) { + if (!m) + return; + + if (m->f) + fclose(m->f); + else + safe_close(m->fd); + + free(m); +} + +int sd_memfd_get_fd(sd_memfd *m) { + assert_return(m, -EINVAL); + + return m->fd; +} + +int sd_memfd_get_file(sd_memfd *m, FILE **f) { + assert_return(m, -EINVAL); + assert_return(f, -EINVAL); + + if (!m->f) { + m->f = fdopen(m->fd, "r+"); + if (!m->f) + return -errno; + } + + *f = m->f; + return 0; +} + +int sd_memfd_dup_fd(sd_memfd *m) { + int fd; + + assert_return(m, -EINVAL); + + fd = fcntl(m->fd, F_DUPFD_CLOEXEC, 3); + if (fd < 0) + return -errno; + + return fd; +} + +int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) { + void *q; + int sealed; + + assert_return(m, -EINVAL); + assert_return(size > 0, -EINVAL); + assert_return(p, -EINVAL); + + sealed = sd_memfd_get_sealed(m); + if (sealed < 0) + return sealed; + + q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_PRIVATE, m->fd, offset); + if (q == MAP_FAILED) + return -errno; + + *p = q; + return 0; +} + +int sd_memfd_set_sealed(sd_memfd *m) { + int r; + + assert_return(m, -EINVAL); + + r = fcntl(m->fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); + if (r < 0) + return -errno; + + return 0; +} + +int sd_memfd_get_sealed(sd_memfd *m) { + int r; + + assert_return(m, -EINVAL); + + r = fcntl(m->fd, F_GET_SEALS); + if (r < 0) + return -errno; + + return (r & (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE)) == + (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); +} + +int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) { + int r; + struct stat stat; + + assert_return(m, -EINVAL); + assert_return(sz, -EINVAL); + + r = fstat(m->fd, &stat); + if (r < 0) + return -errno; + + *sz = stat.st_size; + return r; +} + +int sd_memfd_set_size(sd_memfd *m, uint64_t sz) { + int r; + + assert_return(m, -EINVAL); + + r = ftruncate(m->fd, sz); + if (r < 0) + return -errno; + + return r; +} + +int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p) { + sd_memfd *n; + int r; + + r = sd_memfd_new(&n, name); + if (r < 0) + return r; + + r = sd_memfd_set_size(n, sz); + if (r < 0) { + sd_memfd_free(n); + return r; + } + + r = sd_memfd_map(n, 0, sz, p); + if (r < 0) { + sd_memfd_free(n); + return r; + } + + *m = n; + return 0; +} + +int sd_memfd_get_name(sd_memfd *m, char **name) { + char path[sizeof("/proc/self/fd/") + DECIMAL_STR_MAX(int)], buf[FILENAME_MAX+1], *e; + const char *delim, *end; + _cleanup_free_ char *n = NULL; + ssize_t k; + + assert_return(m, -EINVAL); + assert_return(name, -EINVAL); + + sprintf(path, "/proc/self/fd/%i", m->fd); + + k = readlink(path, buf, sizeof(buf)); + if (k < 0) + return -errno; + + if ((size_t) k >= sizeof(buf)) + return -E2BIG; + + buf[k] = 0; + + delim = strstr(buf, ":["); + if (!delim) + return -EIO; + + delim = strchr(delim + 2, ':'); + if (!delim) + return -EIO; + + delim++; + + end = strchr(delim, ']'); + if (!end) + return -EIO; + + n = strndup(delim, end - delim); + if (!n) + return -ENOMEM; + + e = bus_label_unescape(n); + if (!e) + return -ENOMEM; + + *name = e; + + return 0; +} diff --git a/src/shared/memfd.h b/src/shared/memfd.h new file mode 100644 index 0000000000..6de045c1d7 --- /dev/null +++ b/src/shared/memfd.h @@ -0,0 +1,57 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#ifndef foosdmemfdhfoo +#define foosdmemfdhfoo + +/*** + This file is part of systemd. + + Copyright 2013 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_memfd sd_memfd; + +int sd_memfd_new(sd_memfd **m, const char *name); +int sd_memfd_new_from_fd(sd_memfd **m, int fd); +int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p); + +void sd_memfd_free(sd_memfd *m); + +int sd_memfd_get_fd(sd_memfd *m); +int sd_memfd_dup_fd(sd_memfd *n); +int sd_memfd_get_file(sd_memfd *m, FILE **f); + +int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p); + +int sd_memfd_set_sealed(sd_memfd *m); +int sd_memfd_get_sealed(sd_memfd *m); + +int sd_memfd_get_size(sd_memfd *m, uint64_t *sz); +int sd_memfd_set_size(sd_memfd *m, uint64_t sz); + +int sd_memfd_get_name(sd_memfd *m, char **name); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 3eedb4450b..a69cafbe84 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -28,7 +28,7 @@ #include "sd-id128.h" #include "sd-event.h" -#include "sd-memfd.h" +#include "memfd.h" #include "_sd-common.h" _SD_BEGIN_DECLARATIONS; diff --git a/src/systemd/sd-memfd.h b/src/systemd/sd-memfd.h deleted file mode 100644 index 6de045c1d7..0000000000 --- a/src/systemd/sd-memfd.h +++ /dev/null @@ -1,57 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -#ifndef foosdmemfdhfoo -#define foosdmemfdhfoo - -/*** - This file is part of systemd. - - Copyright 2013 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include -#include - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -typedef struct sd_memfd sd_memfd; - -int sd_memfd_new(sd_memfd **m, const char *name); -int sd_memfd_new_from_fd(sd_memfd **m, int fd); -int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p); - -void sd_memfd_free(sd_memfd *m); - -int sd_memfd_get_fd(sd_memfd *m); -int sd_memfd_dup_fd(sd_memfd *n); -int sd_memfd_get_file(sd_memfd *m, FILE **f); - -int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p); - -int sd_memfd_set_sealed(sd_memfd *m); -int sd_memfd_get_sealed(sd_memfd *m); - -int sd_memfd_get_size(sd_memfd *m, uint64_t *sz); -int sd_memfd_set_size(sd_memfd *m, uint64_t sz); - -int sd_memfd_get_name(sd_memfd *m, char **name); - -_SD_END_DECLARATIONS; - -#endif -- cgit v1.2.3-54-g00ecf From 4632777024b7ba210e4efe5cfabc8cd0b5991045 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 18 Aug 2014 12:24:04 +0200 Subject: memfd: fix memfd_create() syscall wrapper Unlike earlier versions, the syscall only takes 2 arguments in its final version, not 3. --- src/libsystemd/sd-bus/bus-kernel.c | 2 +- src/shared/memfd.c | 2 +- src/shared/missing.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index 4156b90265..d384f846b9 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -1121,7 +1121,7 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *al if (!g) return -ENOMEM; - r = memfd_create(g, 0, MFD_ALLOW_SEALING); + r = memfd_create(g, MFD_ALLOW_SEALING); if (r < 0) return -errno; diff --git a/src/shared/memfd.c b/src/shared/memfd.c index 4dd70a2473..dcebfc9d6f 100644 --- a/src/shared/memfd.c +++ b/src/shared/memfd.c @@ -90,7 +90,7 @@ int sd_memfd_new(sd_memfd **m, const char *name) { if (!n) return -ENOMEM; - n->fd = memfd_create(name, 0, MFD_ALLOW_SEALING); + n->fd = memfd_create(name, MFD_ALLOW_SEALING); if (n->fd < 0) { free(n); return -errno; diff --git a/src/shared/missing.h b/src/shared/missing.h index 3a7e67e384..3ff1a21720 100644 --- a/src/shared/missing.h +++ b/src/shared/missing.h @@ -205,8 +205,8 @@ static inline int fanotify_mark(int fanotify_fd, unsigned int flags, uint64_t ma #endif #ifndef HAVE_MEMFD_CREATE -static inline int memfd_create(const char *name, uint64_t size, uint64_t flags) { - return syscall(__NR_memfd_create, name, size, flags); +static inline int memfd_create(const char *name, uint64_t flags) { + return syscall(__NR_memfd_create, name, flags); } #endif -- cgit v1.2.3-54-g00ecf From 7e2ce386ca9ed825aaac2babe09946380af6bb94 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Mon, 18 Aug 2014 12:57:03 +0200 Subject: memfd: internalize header Fix the memfd.h header to use handy features like #pragma, cleanup-funcs and util.h. Also drop the EXTERN-C macros. --- src/shared/memfd.h | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/shared/memfd.h b/src/shared/memfd.h index 6de045c1d7..452fb508f8 100644 --- a/src/shared/memfd.h +++ b/src/shared/memfd.h @@ -1,7 +1,6 @@ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ -#ifndef foosdmemfdhfoo -#define foosdmemfdhfoo +#pragma once /*** This file is part of systemd. @@ -25,10 +24,8 @@ #include #include #include - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; +#include "macro.h" +#include "util.h" typedef struct sd_memfd sd_memfd; @@ -38,6 +35,8 @@ int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p); void sd_memfd_free(sd_memfd *m); +DEFINE_TRIVIAL_CLEANUP_FUNC(sd_memfd*, sd_memfd_free); + int sd_memfd_get_fd(sd_memfd *m); int sd_memfd_dup_fd(sd_memfd *n); int sd_memfd_get_file(sd_memfd *m, FILE **f); @@ -51,7 +50,3 @@ int sd_memfd_get_size(sd_memfd *m, uint64_t *sz); int sd_memfd_set_size(sd_memfd *m, uint64_t sz); int sd_memfd_get_name(sd_memfd *m, char **name); - -_SD_END_DECLARATIONS; - -#endif -- cgit v1.2.3-54-g00ecf From 302e4b4963c471baefa60b220e3e05f93a49de45 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Mon, 18 Aug 2014 12:57:55 +0200 Subject: memfd: don't open kdbus for memfd No reason to open /dev/kdbus/control if we want memfds. memfd_create() is always available. --- src/shared/memfd.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/shared/memfd.c b/src/shared/memfd.c index dcebfc9d6f..6a2e12196a 100644 --- a/src/shared/memfd.c +++ b/src/shared/memfd.c @@ -39,16 +39,11 @@ struct sd_memfd { int sd_memfd_new(sd_memfd **m, const char *name) { - _cleanup_close_ int kdbus = -1; _cleanup_free_ char *g = NULL; sd_memfd *n; assert_return(m, -EINVAL); - kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC); - if (kdbus < 0) - return -errno; - if (name) { /* The kernel side is pretty picky about the character * set here, let's do the usual bus escaping to deal -- cgit v1.2.3-54-g00ecf From c7dab73a5fa6e775813765fe925caaa7c4e549fa Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Mon, 18 Aug 2014 13:03:09 +0200 Subject: memfd: disallow importing memfds without sealing We use memfds for sealing. Lets not bother with memfds created without MFD_ALLOW_SEALING for now. They're equivalent to random shmem files, so don't bother treating them as sealable memfds. --- src/shared/memfd.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/shared/memfd.c b/src/shared/memfd.c index 6a2e12196a..6804b42361 100644 --- a/src/shared/memfd.c +++ b/src/shared/memfd.c @@ -97,12 +97,17 @@ int sd_memfd_new(sd_memfd **m, const char *name) { int sd_memfd_new_from_fd(sd_memfd **m, int fd) { sd_memfd *n; + int r; assert_return(m, -EINVAL); assert_return(fd >= 0, -EINVAL); - /* Check if this is a sealable fd */ - if (fcntl(fd, F_GET_SEALS) < 0) + /* Check if this is a sealable fd. The kernel sets F_SEAL_SEAL on memfds + * that don't support sealing, so check for that, too. A file with + * *only* F_SEAL_SEAL set is the same as a random shmem file, so no + * reason to allow opening it as memfd. */ + r = fcntl(fd, F_GET_SEALS); + if (r < 0 || r == F_SEAL_SEAL) return -ENOTTY; n = new0(struct sd_memfd, 1); -- cgit v1.2.3-54-g00ecf From 23972f4244f7609658c2a17f85508d50e4739990 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Mon, 18 Aug 2014 13:05:48 +0200 Subject: memfd: map unsealed files as MAP_SHARED We need to map sealed files as MAP_PRIVATE so far as the kernel treats MAP_SHARED as writable mapping (you can run mprotect(PROT_WRITE) at any time on those). However, unsealed files must be mapped as MAP_SHARED. Otherwise, we never end up writing to the real file. --- src/shared/memfd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/shared/memfd.c b/src/shared/memfd.c index 6804b42361..d94c6268dd 100644 --- a/src/shared/memfd.c +++ b/src/shared/memfd.c @@ -176,7 +176,11 @@ int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) { if (sealed < 0) return sealed; - q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_PRIVATE, m->fd, offset); + if (sealed) + q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, m->fd, offset); + else + q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, m->fd, offset); + if (q == MAP_FAILED) return -errno; -- cgit v1.2.3-54-g00ecf From 8a02decaf1e81bad3c06752e998734c96ab11260 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Mon, 18 Aug 2014 13:07:43 +0200 Subject: memfd: use _cleanup_ if applicable We now have a sd_memfd_freep helper, use it if applicable. --- src/shared/memfd.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/shared/memfd.c b/src/shared/memfd.c index d94c6268dd..e246f915ca 100644 --- a/src/shared/memfd.c +++ b/src/shared/memfd.c @@ -241,7 +241,7 @@ int sd_memfd_set_size(sd_memfd *m, uint64_t sz) { } int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p) { - sd_memfd *n; + _cleanup_(sd_memfd_freep) sd_memfd *n = NULL; int r; r = sd_memfd_new(&n, name); @@ -249,18 +249,15 @@ int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p) { return r; r = sd_memfd_set_size(n, sz); - if (r < 0) { - sd_memfd_free(n); + if (r < 0) return r; - } r = sd_memfd_map(n, 0, sz, p); - if (r < 0) { - sd_memfd_free(n); + if (r < 0) return r; - } *m = n; + n = NULL; return 0; } -- cgit v1.2.3-54-g00ecf From fac9c0d508f72cc5d469c969a4acc3694247c03b Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 18 Aug 2014 13:28:43 +0200 Subject: memfd: internalize functions, drop sd_memfd type Remove the sd_ prefix from internal functions and get rid of the sd_memfd type. As a memfd is now just a native file descriptor, we can get rid of our own wrapper type, and also use close() and dup() on them directly. --- man/sd_bus_message_append_array.xml | 2 +- man/sd_bus_message_append_string_memfd.xml | 2 +- src/libsystemd/sd-bus/bus-message.c | 20 ++-- src/libsystemd/sd-bus/test-bus-zero-copy.c | 14 +-- src/shared/memfd.c | 146 +++++++---------------------- src/shared/memfd.h | 27 ++---- src/systemd/sd-bus.h | 4 +- 7 files changed, 62 insertions(+), 153 deletions(-) diff --git a/man/sd_bus_message_append_array.xml b/man/sd_bus_message_append_array.xml index e0f6767ec2..ab1fcd26cb 100644 --- a/man/sd_bus_message_append_array.xml +++ b/man/sd_bus_message_append_array.xml @@ -68,7 +68,7 @@ along with systemd; If not, see . int sd_bus_message_append_array_memfd sd_bus_message *m char type - sd_memfd *memfd + int memfd diff --git a/man/sd_bus_message_append_string_memfd.xml b/man/sd_bus_message_append_string_memfd.xml index fd857ccb19..d18ca1a858 100644 --- a/man/sd_bus_message_append_string_memfd.xml +++ b/man/sd_bus_message_append_string_memfd.xml @@ -58,7 +58,7 @@ along with systemd; If not, see . int sd_bus_message_append_string_memfd sd_bus_message *m - sd_memfd *memfd + int memfd diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 79dc471d41..3e60842172 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -2527,7 +2527,7 @@ _public_ int sd_bus_message_append_array_iovec( _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, - sd_memfd *memfd) { + int memfd) { _cleanup_close_ int copy_fd = -1; struct bus_body_part *part; ssize_t align, sz; @@ -2537,7 +2537,7 @@ _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, if (!m) return -EINVAL; - if (!memfd) + if (memfd < 0) return -EINVAL; if (m->sealed) return -EPERM; @@ -2546,15 +2546,15 @@ _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, if (m->poisoned) return -ESTALE; - r = sd_memfd_set_sealed(memfd); + r = memfd_set_sealed(memfd); if (r < 0) return r; - copy_fd = sd_memfd_dup_fd(memfd); + copy_fd = dup(memfd); if (copy_fd < 0) return copy_fd; - r = sd_memfd_get_size(memfd, &size); + r = memfd_get_size(memfd, &size); if (r < 0) return r; @@ -2593,7 +2593,7 @@ _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, return sd_bus_message_close_container(m); } -_public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *memfd) { +_public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) { _cleanup_close_ int copy_fd = -1; struct bus_body_part *part; struct bus_container *c; @@ -2602,19 +2602,19 @@ _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *mem int r; assert_return(m, -EINVAL); - assert_return(memfd, -EINVAL); + assert_return(memfd >= 0, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->poisoned, -ESTALE); - r = sd_memfd_set_sealed(memfd); + r = memfd_set_sealed(memfd); if (r < 0) return r; - copy_fd = sd_memfd_dup_fd(memfd); + copy_fd = dup(memfd); if (copy_fd < 0) return copy_fd; - r = sd_memfd_get_size(memfd, &size); + r = memfd_get_size(memfd, &size); if (r < 0) return r; diff --git a/src/libsystemd/sd-bus/test-bus-zero-copy.c b/src/libsystemd/sd-bus/test-bus-zero-copy.c index e4a87ab3c5..1d279e6032 100644 --- a/src/libsystemd/sd-bus/test-bus-zero-copy.c +++ b/src/libsystemd/sd-bus/test-bus-zero-copy.c @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) { sd_bus *a, *b; int r, bus_ref; sd_bus_message *m; - sd_memfd *f; + int f; uint64_t sz; uint32_t u32; size_t i, l; @@ -93,7 +93,7 @@ int main(int argc, char *argv[]) { memset(p+1, 'L', FIRST_ARRAY-2); p[FIRST_ARRAY-1] = '>'; - r = sd_memfd_new_and_map(&f, NULL, STRING_SIZE, (void**) &s); + r = memfd_new_and_map(&f, NULL, STRING_SIZE, (void**) &s); assert_se(r >= 0); s[0] = '<'; @@ -103,16 +103,16 @@ int main(int argc, char *argv[]) { s[STRING_SIZE-1] = 0; munmap(s, STRING_SIZE); - r = sd_memfd_get_size(f, &sz); + r = memfd_get_size(f, &sz); assert_se(r >= 0); assert_se(sz == STRING_SIZE); r = sd_bus_message_append_string_memfd(m, f); assert_se(r >= 0); - sd_memfd_free(f); + close(f); - r = sd_memfd_new_and_map(&f, NULL, SECOND_ARRAY, (void**) &p); + r = memfd_new_and_map(&f, NULL, SECOND_ARRAY, (void**) &p); assert_se(r >= 0); p[0] = '<'; @@ -120,14 +120,14 @@ int main(int argc, char *argv[]) { p[SECOND_ARRAY-1] = '>'; munmap(p, SECOND_ARRAY); - r = sd_memfd_get_size(f, &sz); + r = memfd_get_size(f, &sz); assert_se(r >= 0); assert_se(sz == SECOND_ARRAY); r = sd_bus_message_append_array_memfd(m, 'y', f); assert_se(r >= 0); - sd_memfd_free(f); + close(f); r = sd_bus_message_close_container(m); assert_se(r >= 0); diff --git a/src/shared/memfd.c b/src/shared/memfd.c index e246f915ca..2b0d26d9ed 100644 --- a/src/shared/memfd.c +++ b/src/shared/memfd.c @@ -32,17 +32,12 @@ #include "sd-bus.h" -struct sd_memfd { - int fd; - FILE *f; -}; - -int sd_memfd_new(sd_memfd **m, const char *name) { +int memfd_new(int *fd, const char *name) { _cleanup_free_ char *g = NULL; - sd_memfd *n; + int n; - assert_return(m, -EINVAL); + assert_return(fd, -EINVAL); if (name) { /* The kernel side is pretty picky about the character @@ -81,105 +76,30 @@ int sd_memfd_new(sd_memfd **m, const char *name) { } } - n = new0(struct sd_memfd, 1); - if (!n) - return -ENOMEM; - - n->fd = memfd_create(name, MFD_ALLOW_SEALING); - if (n->fd < 0) { - free(n); + n = memfd_create(name, MFD_ALLOW_SEALING); + if (n < 0) return -errno; - } - *m = n; + *fd = n; return 0; } -int sd_memfd_new_from_fd(sd_memfd **m, int fd) { - sd_memfd *n; - int r; - - assert_return(m, -EINVAL); - assert_return(fd >= 0, -EINVAL); - - /* Check if this is a sealable fd. The kernel sets F_SEAL_SEAL on memfds - * that don't support sealing, so check for that, too. A file with - * *only* F_SEAL_SEAL set is the same as a random shmem file, so no - * reason to allow opening it as memfd. */ - r = fcntl(fd, F_GET_SEALS); - if (r < 0 || r == F_SEAL_SEAL) - return -ENOTTY; - - n = new0(struct sd_memfd, 1); - if (!n) - return -ENOMEM; - - n->fd = fd; - *m = n; - - return 0; -} - -void sd_memfd_free(sd_memfd *m) { - if (!m) - return; - - if (m->f) - fclose(m->f); - else - safe_close(m->fd); - - free(m); -} - -int sd_memfd_get_fd(sd_memfd *m) { - assert_return(m, -EINVAL); - - return m->fd; -} - -int sd_memfd_get_file(sd_memfd *m, FILE **f) { - assert_return(m, -EINVAL); - assert_return(f, -EINVAL); - - if (!m->f) { - m->f = fdopen(m->fd, "r+"); - if (!m->f) - return -errno; - } - - *f = m->f; - return 0; -} - -int sd_memfd_dup_fd(sd_memfd *m) { - int fd; - - assert_return(m, -EINVAL); - - fd = fcntl(m->fd, F_DUPFD_CLOEXEC, 3); - if (fd < 0) - return -errno; - - return fd; -} - -int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) { +int memfd_map(int fd, uint64_t offset, size_t size, void **p) { void *q; int sealed; - assert_return(m, -EINVAL); + assert_return(fd >= 0, -EINVAL); assert_return(size > 0, -EINVAL); assert_return(p, -EINVAL); - sealed = sd_memfd_get_sealed(m); + sealed = memfd_get_sealed(fd); if (sealed < 0) return sealed; if (sealed) - q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, m->fd, offset); + q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset); else - q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, m->fd, offset); + q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset); if (q == MAP_FAILED) return -errno; @@ -188,24 +108,24 @@ int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) { return 0; } -int sd_memfd_set_sealed(sd_memfd *m) { +int memfd_set_sealed(int fd) { int r; - assert_return(m, -EINVAL); + assert_return(fd >= 0, -EINVAL); - r = fcntl(m->fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); + r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); if (r < 0) return -errno; return 0; } -int sd_memfd_get_sealed(sd_memfd *m) { +int memfd_get_sealed(int fd) { int r; - assert_return(m, -EINVAL); + assert_return(fd >= 0, -EINVAL); - r = fcntl(m->fd, F_GET_SEALS); + r = fcntl(fd, F_GET_SEALS); if (r < 0) return -errno; @@ -213,14 +133,14 @@ int sd_memfd_get_sealed(sd_memfd *m) { (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); } -int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) { +int memfd_get_size(int fd, uint64_t *sz) { int r; struct stat stat; - assert_return(m, -EINVAL); + assert_return(fd >= 0, -EINVAL); assert_return(sz, -EINVAL); - r = fstat(m->fd, &stat); + r = fstat(fd, &stat); if (r < 0) return -errno; @@ -228,49 +148,49 @@ int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) { return r; } -int sd_memfd_set_size(sd_memfd *m, uint64_t sz) { +int memfd_set_size(int fd, uint64_t sz) { int r; - assert_return(m, -EINVAL); + assert_return(fd >= 0, -EINVAL); - r = ftruncate(m->fd, sz); + r = ftruncate(fd, sz); if (r < 0) return -errno; return r; } -int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p) { - _cleanup_(sd_memfd_freep) sd_memfd *n = NULL; +int memfd_new_and_map(int *fd, const char *name, size_t sz, void **p) { + _cleanup_close_ int n = -1; int r; - r = sd_memfd_new(&n, name); + r = memfd_new(&n, name); if (r < 0) return r; - r = sd_memfd_set_size(n, sz); + r = memfd_set_size(n, sz); if (r < 0) return r; - r = sd_memfd_map(n, 0, sz, p); + r = memfd_map(n, 0, sz, p); if (r < 0) return r; - *m = n; - n = NULL; + *fd = n; + n = -1; return 0; } -int sd_memfd_get_name(sd_memfd *m, char **name) { +int memfd_get_name(int fd, char **name) { char path[sizeof("/proc/self/fd/") + DECIMAL_STR_MAX(int)], buf[FILENAME_MAX+1], *e; const char *delim, *end; _cleanup_free_ char *n = NULL; ssize_t k; - assert_return(m, -EINVAL); + assert_return(fd >= 0, -EINVAL); assert_return(name, -EINVAL); - sprintf(path, "/proc/self/fd/%i", m->fd); + sprintf(path, "/proc/self/fd/%i", fd); k = readlink(path, buf, sizeof(buf)); if (k < 0) diff --git a/src/shared/memfd.h b/src/shared/memfd.h index 452fb508f8..02cb3978fa 100644 --- a/src/shared/memfd.h +++ b/src/shared/memfd.h @@ -27,26 +27,15 @@ #include "macro.h" #include "util.h" -typedef struct sd_memfd sd_memfd; +int memfd_new(int *fd, const char *name); +int memfd_new_and_map(int *fd, const char *name, size_t sz, void **p); -int sd_memfd_new(sd_memfd **m, const char *name); -int sd_memfd_new_from_fd(sd_memfd **m, int fd); -int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p); +int memfd_map(int fd, uint64_t offset, size_t size, void **p); -void sd_memfd_free(sd_memfd *m); +int memfd_set_sealed(int fd); +int memfd_get_sealed(int fd); -DEFINE_TRIVIAL_CLEANUP_FUNC(sd_memfd*, sd_memfd_free); +int memfd_get_size(int fd, uint64_t *sz); +int memfd_set_size(int fd, uint64_t sz); -int sd_memfd_get_fd(sd_memfd *m); -int sd_memfd_dup_fd(sd_memfd *n); -int sd_memfd_get_file(sd_memfd *m, FILE **f); - -int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p); - -int sd_memfd_set_sealed(sd_memfd *m); -int sd_memfd_get_sealed(sd_memfd *m); - -int sd_memfd_get_size(sd_memfd *m, uint64_t *sz); -int sd_memfd_set_size(sd_memfd *m, uint64_t sz); - -int sd_memfd_get_name(sd_memfd *m, char **name); +int memfd_get_name(int fd, char **name); diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index a69cafbe84..c601093a85 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -226,10 +226,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_memfd(sd_bus_message *m, char type, sd_memfd *memfd); +int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, int memfd); 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, sd_memfd* memfd); +int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd); 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); -- cgit v1.2.3-54-g00ecf From e0fbf1fcffe014d5af6767b29f9108c2f2444888 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Mon, 18 Aug 2014 12:29:45 +0200 Subject: networkd: warn when ignoring unsupported tuntap options The interface for creating tuntap devices should be ported to rtnl so it would support the same settings as other kinds. In the meantime, the best one can do is to drop in a .link file to set the desired options. --- man/systemd.netdev.xml | 5 ++++- src/network/networkd-netdev-tuntap.c | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index acd845498c..275ee528a0 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -177,7 +177,9 @@ The maximum transmission unit in bytes to set for the device. The usual suffixes K, M, G, are supported and are understood to the base of - 1024. + 1024. This key is not currently suported for + tun or tap devices. + @@ -187,6 +189,7 @@ If none is given, one is generated based on the interface name and the machine-id5. + This key is not currently suported for tun or tap devices. diff --git a/src/network/networkd-netdev-tuntap.c b/src/network/networkd-netdev-tuntap.c index dd3bd96dbb..eef8747210 100644 --- a/src/network/networkd-netdev-tuntap.c +++ b/src/network/networkd-netdev-tuntap.c @@ -172,9 +172,35 @@ static void tuntap_done(NetDev *netdev) { t->group_name = NULL; } +static int tuntap_verify(NetDev *netdev, const char *filename) { + TunTap *t = NULL; + + assert(netdev); + + if (netdev->kind == NETDEV_KIND_TUN) + t = TUN(netdev); + else + t = TAP(netdev); + + assert(t); + + if (netdev->mtu) { + log_warning_netdev(netdev, "MTU configured for %s, ignoring", + netdev_kind_to_string(netdev->kind)); + } + + if (netdev->mac) { + log_warning_netdev(netdev, "MAC configured for %s, ignoring", + netdev_kind_to_string(netdev->kind)); + } + + return 0; +} + const NetDevVTable tun_vtable = { .object_size = sizeof(TunTap), .sections = "Match\0NetDev\0Tun\0", + .config_verify = tuntap_verify, .done = tuntap_done, .create = netdev_create_tuntap, .create_type = NETDEV_CREATE_INDEPENDENT, @@ -183,6 +209,7 @@ const NetDevVTable tun_vtable = { const NetDevVTable tap_vtable = { .object_size = sizeof(TunTap), .sections = "Match\0NetDev\0Tap\0", + .config_verify = tuntap_verify, .done = tuntap_done, .create = netdev_create_tuntap, .create_type = NETDEV_CREATE_INDEPENDENT, -- cgit v1.2.3-54-g00ecf