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>
39 _public_ int sd_memfd_new(const char *name, sd_memfd **m) {
41 struct kdbus_cmd_memfd_make *cmd;
42 struct kdbus_item *item;
43 _cleanup_close_ int kdbus = -1;
44 _cleanup_free_ char *g = NULL;
48 assert_return(m, -EINVAL);
50 kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
55 /* The kernel side is pretty picky about the character
56 * set here, let's do the usual bus escaping to deal
59 g = sd_bus_label_escape(name);
68 /* If no name is specified we generate one. We include
69 * a hint indicating our library implementation, and
70 * add the thread name to it */
72 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
77 _cleanup_free_ char *e = NULL;
79 e = sd_bus_label_escape(pr);
83 g = strappend("sd-", e);
92 sz = ALIGN8(offsetof(struct kdbus_cmd_memfd_make, items)) +
93 ALIGN8(offsetof(struct kdbus_item, str)) +
100 item->size = ALIGN8(offsetof(struct kdbus_item, str)) + l + 1;
101 item->type = KDBUS_ITEM_MEMFD_NAME;
102 memcpy(item->str, name, l + 1);
104 if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, cmd) < 0)
107 n = new0(struct sd_memfd, 1);
109 close_nointr_nofail(cmd->fd);
118 _public_ int sd_memfd_make(int fd, sd_memfd **m) {
122 assert_return(m, -EINVAL);
123 assert_return(fd >= 0, -EINVAL);
125 /* Check if this is a valid memfd */
126 if (ioctl(fd, KDBUS_CMD_MEMFD_SIZE_GET, &sz) < 0)
129 n = new0(struct sd_memfd, 1);
139 _public_ void sd_memfd_free(sd_memfd *m) {
146 close_nointr_nofail(m->fd);
151 _public_ int sd_memfd_get_fd(sd_memfd *m) {
152 assert_return(m, -EINVAL);
157 _public_ int sd_memfd_get_file(sd_memfd *m, FILE **f) {
158 assert_return(m, -EINVAL);
159 assert_return(f, -EINVAL);
162 m->f = fdopen(m->fd, "r+");
171 _public_ int sd_memfd_dup_fd(sd_memfd *m) {
174 assert_return(m, -EINVAL);
176 fd = fcntl(m->fd, F_DUPFD_CLOEXEC, 3);
183 _public_ int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) {
187 assert_return(m, -EINVAL);
188 assert_return(size > 0, -EINVAL);
189 assert_return(p, -EINVAL);
191 sealed = sd_memfd_get_sealed(m);
195 q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, offset);
203 _public_ int sd_memfd_set_sealed(sd_memfd *m, int b) {
206 assert_return(m, -EINVAL);
208 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_SET, b);
215 _public_ int sd_memfd_get_sealed(sd_memfd *m) {
218 assert_return(m, -EINVAL);
220 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_GET, &b);
227 _public_ int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) {
230 assert_return(m, -EINVAL);
231 assert_return(sz, -EINVAL);
233 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_GET, sz);
240 _public_ int sd_memfd_set_size(sd_memfd *m, uint64_t sz) {
243 assert_return(m, -EINVAL);
245 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
252 _public_ int sd_memfd_new_and_map(const char *name, sd_memfd **m, size_t sz, void **p) {
256 r = sd_memfd_new(name, &n);
260 r = sd_memfd_set_size(n, sz);
266 r = sd_memfd_map(n, 0, sz, p);
276 _public_ int sd_memfd_get_name(sd_memfd *m, char **name) {
277 char path[sizeof("/proc/self/fd/") + DECIMAL_STR_MAX(int)], buf[FILENAME_MAX+1], *e;
278 const char *delim, *end;
279 _cleanup_free_ char *n = NULL;
282 assert_return(m, -EINVAL);
283 assert_return(name, -EINVAL);
285 sprintf(path, "/proc/self/fd/%i", m->fd);
287 k = readlink(path, buf, sizeof(buf));
291 if ((size_t) k >= sizeof(buf))
296 delim = strstr(buf, ":[");
300 delim = strchr(delim + 2, ':');
306 end = strchr(delim, ']');
310 n = strndup(delim, end - delim);
314 e = sd_bus_label_unescape(n);