1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/ioctl.h>
26 #include <sys/prctl.h>
30 #include "bus-label.h"
40 _public_ int sd_memfd_new(sd_memfd **m, const char *name) {
42 struct kdbus_cmd_memfd_make *cmd;
43 struct kdbus_item *item;
44 _cleanup_close_ int kdbus = -1;
45 _cleanup_free_ char *g = NULL;
49 assert_return(m, -EINVAL);
51 kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
56 /* The kernel side is pretty picky about the character
57 * set here, let's do the usual bus escaping to deal
60 g = bus_label_escape(name);
69 /* If no name is specified we generate one. We include
70 * a hint indicating our library implementation, and
71 * add the thread name to it */
73 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
78 _cleanup_free_ char *e = NULL;
80 e = bus_label_escape(pr);
84 g = strappend("sd-", e);
93 sz = ALIGN8(offsetof(struct kdbus_cmd_memfd_make, items)) +
94 ALIGN8(offsetof(struct kdbus_item, str)) +
101 item->size = ALIGN8(offsetof(struct kdbus_item, str)) + l + 1;
102 item->type = KDBUS_ITEM_MEMFD_NAME;
103 memcpy(item->str, name, l + 1);
105 if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, cmd) < 0)
108 n = new0(struct sd_memfd, 1);
110 close_nointr_nofail(cmd->fd);
119 _public_ int sd_memfd_new_from_fd(sd_memfd **m, int fd) {
123 assert_return(m, -EINVAL);
124 assert_return(fd >= 0, -EINVAL);
126 /* Check if this is a valid memfd */
127 if (ioctl(fd, KDBUS_CMD_MEMFD_SIZE_GET, &sz) < 0)
130 n = new0(struct sd_memfd, 1);
140 _public_ void sd_memfd_free(sd_memfd *m) {
147 close_nointr_nofail(m->fd);
152 _public_ int sd_memfd_get_fd(sd_memfd *m) {
153 assert_return(m, -EINVAL);
158 _public_ int sd_memfd_get_file(sd_memfd *m, FILE **f) {
159 assert_return(m, -EINVAL);
160 assert_return(f, -EINVAL);
163 m->f = fdopen(m->fd, "r+");
172 _public_ int sd_memfd_dup_fd(sd_memfd *m) {
175 assert_return(m, -EINVAL);
177 fd = fcntl(m->fd, F_DUPFD_CLOEXEC, 3);
184 _public_ int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) {
188 assert_return(m, -EINVAL);
189 assert_return(size > 0, -EINVAL);
190 assert_return(p, -EINVAL);
192 sealed = sd_memfd_get_sealed(m);
196 q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, offset);
204 _public_ int sd_memfd_set_sealed(sd_memfd *m, int b) {
207 assert_return(m, -EINVAL);
209 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_SET, b);
216 _public_ int sd_memfd_get_sealed(sd_memfd *m) {
219 assert_return(m, -EINVAL);
221 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_GET, &b);
228 _public_ int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) {
231 assert_return(m, -EINVAL);
232 assert_return(sz, -EINVAL);
234 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_GET, sz);
241 _public_ int sd_memfd_set_size(sd_memfd *m, uint64_t sz) {
244 assert_return(m, -EINVAL);
246 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
253 _public_ int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p) {
257 r = sd_memfd_new(&n, name);
261 r = sd_memfd_set_size(n, sz);
267 r = sd_memfd_map(n, 0, sz, p);
277 _public_ int sd_memfd_get_name(sd_memfd *m, char **name) {
278 char path[sizeof("/proc/self/fd/") + DECIMAL_STR_MAX(int)], buf[FILENAME_MAX+1], *e;
279 const char *delim, *end;
280 _cleanup_free_ char *n = NULL;
283 assert_return(m, -EINVAL);
284 assert_return(name, -EINVAL);
286 sprintf(path, "/proc/self/fd/%i", m->fd);
288 k = readlink(path, buf, sizeof(buf));
292 if ((size_t) k >= sizeof(buf))
297 delim = strstr(buf, ":[");
301 delim = strchr(delim + 2, ':');
307 end = strchr(delim, ']');
311 n = strndup(delim, end - delim);
315 e = bus_label_unescape(n);