mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-10 01:17:44 +03:00
bus: add new API for kdbus memfd functionality
This commit is contained in:
parent
72455f9bf0
commit
ddeb424198
2
.gitignore
vendored
2
.gitignore
vendored
@ -85,6 +85,7 @@
|
||||
/test-bus-kernel
|
||||
/test-bus-marshal
|
||||
/test-bus-match
|
||||
/test-bus-memfd
|
||||
/test-bus-signature
|
||||
/test-bus-server
|
||||
/test-calendarspec
|
||||
@ -97,6 +98,7 @@
|
||||
/test-engine
|
||||
/test-env-replace
|
||||
/test-fileio
|
||||
/test-hashmap
|
||||
/test-hostname
|
||||
/test-id128
|
||||
/test-inhibit
|
||||
|
17
Makefile.am
17
Makefile.am
@ -1718,6 +1718,7 @@ EXTRA_DIST += \
|
||||
libsystemd_bus_la_SOURCES = \
|
||||
src/systemd/sd-bus.h \
|
||||
src/systemd/sd-bus-protocol.h \
|
||||
src/systemd/sd-memfd.h \
|
||||
src/libsystemd-bus/sd-bus.c \
|
||||
src/libsystemd-bus/bus-control.c \
|
||||
src/libsystemd-bus/bus-control.h \
|
||||
@ -1739,7 +1740,8 @@ libsystemd_bus_la_SOURCES = \
|
||||
src/libsystemd-bus/bus-match.h \
|
||||
src/libsystemd-bus/bus-bloom.c \
|
||||
src/libsystemd-bus/bus-bloom.h \
|
||||
src/libsystemd-bus/kdbus.h
|
||||
src/libsystemd-bus/kdbus.h \
|
||||
src/libsystemd-bus/sd-memfd.c
|
||||
|
||||
libsystemd_bus_la_LIBADD = \
|
||||
libsystemd-id128-internal.la \
|
||||
@ -1755,7 +1757,8 @@ tests += \
|
||||
test-bus-chat \
|
||||
test-bus-server \
|
||||
test-bus-match \
|
||||
test-bus-kernel
|
||||
test-bus-kernel \
|
||||
test-bus-memfd
|
||||
|
||||
noinst_PROGRAMS += \
|
||||
busctl
|
||||
@ -1827,6 +1830,16 @@ test_bus_kernel_LDADD = \
|
||||
libsystemd-bus.la \
|
||||
libsystemd-id128-internal.la
|
||||
|
||||
test_bus_memfd_SOURCES = \
|
||||
src/libsystemd-bus/test-bus-memfd.c
|
||||
|
||||
test_bus_memfd_CFLAGS = \
|
||||
$(AM_CFLAGS)
|
||||
|
||||
test_bus_memfd_LDADD = \
|
||||
libsystemd-shared.la \
|
||||
libsystemd-bus.la
|
||||
|
||||
busctl_SOURCES = \
|
||||
src/libsystemd-bus/busctl.c
|
||||
|
||||
|
@ -424,7 +424,7 @@ enum kdbus_cmd {
|
||||
|
||||
/* kdbus memfd commands: */
|
||||
KDBUS_CMD_MEMFD_SIZE_GET = _IOWR(KDBUS_IOC_MAGIC, 0x81, __u64 *),
|
||||
KDBUS_CMD_MEMFD_SIZE_SET = _IOWR(KDBUS_IOC_MAGIC, 0x82, __u64),
|
||||
KDBUS_CMD_MEMFD_SIZE_SET = _IOWR(KDBUS_IOC_MAGIC, 0x82, __u64 *),
|
||||
KDBUS_CMD_MEMFD_SEAL_GET = _IOWR(KDBUS_IOC_MAGIC, 0x83, int *),
|
||||
KDBUS_CMD_MEMFD_SEAL_SET = _IOWR(KDBUS_IOC_MAGIC, 0x84, int),
|
||||
};
|
||||
|
207
src/libsystemd-bus/sd-memfd.c
Normal file
207
src/libsystemd-bus/sd-memfd.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*-*- 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 <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "kdbus.h"
|
||||
|
||||
#include "sd-memfd.h"
|
||||
|
||||
struct sd_memfd {
|
||||
int fd;
|
||||
FILE *f;
|
||||
};
|
||||
|
||||
int sd_memfd_new(sd_memfd **m) {
|
||||
_cleanup_close_ int kdbus = -1;
|
||||
sd_memfd *n;
|
||||
int fd;
|
||||
|
||||
if (!m)
|
||||
return -EINVAL;
|
||||
|
||||
kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, &fd) < 0)
|
||||
return -errno;
|
||||
|
||||
n = new0(struct sd_memfd, 1);
|
||||
if (!n)
|
||||
return -ENOMEM;
|
||||
|
||||
n->fd = fd;
|
||||
*m = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_memfd_make(int fd, sd_memfd **m) {
|
||||
sd_memfd *n;
|
||||
uint64_t sz;
|
||||
|
||||
if (!m)
|
||||
return -EINVAL;
|
||||
if (fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check if this is a valid memfd */
|
||||
if (ioctl(fd, KDBUS_CMD_MEMFD_SIZE_GET, &sz) < 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
|
||||
close_nointr_nofail(m->fd);
|
||||
|
||||
free(m);
|
||||
}
|
||||
|
||||
int sd_memfd_get_fd(sd_memfd *m) {
|
||||
if (!m)
|
||||
return -EINVAL;
|
||||
|
||||
return m->fd;
|
||||
}
|
||||
|
||||
int sd_memfd_get_file(sd_memfd *m, FILE **f) {
|
||||
if (!m)
|
||||
return -EINVAL;
|
||||
if (!f)
|
||||
return -EINVAL;
|
||||
|
||||
if (!m->fd) {
|
||||
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;
|
||||
|
||||
if (!m)
|
||||
return -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;
|
||||
|
||||
if (!m)
|
||||
return -EINVAL;
|
||||
if (size <= 0)
|
||||
return -EINVAL;
|
||||
if (!p)
|
||||
return -EINVAL;
|
||||
|
||||
sealed = sd_memfd_get_sealed(m);
|
||||
if (sealed < 0)
|
||||
return sealed;
|
||||
|
||||
q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, offset);
|
||||
if (q == MAP_FAILED)
|
||||
return -errno;
|
||||
|
||||
*p = q;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_memfd_set_sealed(sd_memfd *m, int b) {
|
||||
int r;
|
||||
|
||||
if (!m)
|
||||
return -EINVAL;
|
||||
|
||||
r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_SET, b);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_memfd_get_sealed(sd_memfd *m) {
|
||||
int r, b;
|
||||
|
||||
if (!m)
|
||||
return -EINVAL;
|
||||
|
||||
r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_GET, &b);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return !!b;
|
||||
}
|
||||
|
||||
int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) {
|
||||
int r;
|
||||
|
||||
if (!m)
|
||||
return -EINVAL;
|
||||
if (!sz)
|
||||
return -EINVAL;
|
||||
|
||||
r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_GET, sz);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_memfd_set_size(sd_memfd *m, uint64_t sz) {
|
||||
int r;
|
||||
|
||||
if (!m)
|
||||
return -EINVAL;
|
||||
|
||||
r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return r;
|
||||
}
|
85
src/libsystemd-bus/test-bus-memfd.c
Normal file
85
src/libsystemd-bus/test-bus-memfd.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*-*- 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 <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "sd-memfd.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
sd_memfd *m;
|
||||
char *s;
|
||||
uint64_t sz;
|
||||
int r, fd;
|
||||
|
||||
log_set_max_level(LOG_DEBUG);
|
||||
|
||||
r = sd_memfd_new(&m);
|
||||
if (r == -ENOENT)
|
||||
return EXIT_TEST_SKIP;
|
||||
|
||||
r = sd_memfd_map(m, 0, 6, (void**) &s);
|
||||
assert_se(r >= 0);
|
||||
|
||||
strcpy(s, "hallo");
|
||||
assert_se(munmap(s, 6) == 0);
|
||||
|
||||
assert_se(write(sd_memfd_get_fd(m), "he", 2) == 2);
|
||||
|
||||
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_get_size(m, &sz);
|
||||
assert_se(r >= 0);
|
||||
assert_se(sz = page_size());
|
||||
|
||||
r = sd_memfd_set_size(m, 6);
|
||||
assert_se(r >= 0);
|
||||
|
||||
fd = sd_memfd_dup_fd(m);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
sd_memfd_free(m);
|
||||
|
||||
r = sd_memfd_make(fd, &m);
|
||||
assert_se(r >= 0);
|
||||
|
||||
r = sd_memfd_get_size(m, &sz);
|
||||
assert_se(r >= 0);
|
||||
assert_se(sz = 6);
|
||||
|
||||
r = sd_memfd_map(m, 0, 6, (void**) &s);
|
||||
assert_se(r >= 0);
|
||||
|
||||
assert_se(streq(s, "hello"));
|
||||
assert_se(munmap(s, 6) == 0);
|
||||
|
||||
return 0;
|
||||
}
|
56
src/systemd/sd-memfd.h
Normal file
56
src/systemd/sd-memfd.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*-*- 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 <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct sd_memfd sd_memfd;
|
||||
|
||||
int sd_memfd_new(sd_memfd **m);
|
||||
int sd_memfd_make(int fd, sd_memfd **m);
|
||||
|
||||
void sd_memfd_free(sd_memfd *m);
|
||||
|
||||
int sd_memfd_get_fd(sd_memfd *m);
|
||||
int sd_memfd_get_file(sd_memfd *m, FILE **f);
|
||||
int sd_memfd_dup_fd(sd_memfd *n);
|
||||
|
||||
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_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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user