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>
29 #include "bus-label.h"
40 int sd_memfd_new(sd_memfd **m, const char *name) {
42 _cleanup_close_ int kdbus = -1;
43 _cleanup_free_ char *g = NULL;
46 assert_return(m, -EINVAL);
48 kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
53 /* The kernel side is pretty picky about the character
54 * set here, let's do the usual bus escaping to deal
57 g = bus_label_escape(name);
66 /* If no name is specified we generate one. We include
67 * a hint indicating our library implementation, and
68 * add the thread name to it */
70 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
75 _cleanup_free_ char *e = NULL;
77 e = bus_label_escape(pr);
81 g = strappend("sd-", e);
89 n = new0(struct sd_memfd, 1);
93 n->fd = memfd_create(name, MFD_ALLOW_SEALING);
103 int sd_memfd_new_from_fd(sd_memfd **m, int fd) {
106 assert_return(m, -EINVAL);
107 assert_return(fd >= 0, -EINVAL);
109 /* Check if this is a sealable fd */
110 if (fcntl(fd, F_GET_SEALS) < 0)
113 n = new0(struct sd_memfd, 1);
123 void sd_memfd_free(sd_memfd *m) {
135 int sd_memfd_get_fd(sd_memfd *m) {
136 assert_return(m, -EINVAL);
141 int sd_memfd_get_file(sd_memfd *m, FILE **f) {
142 assert_return(m, -EINVAL);
143 assert_return(f, -EINVAL);
146 m->f = fdopen(m->fd, "r+");
155 int sd_memfd_dup_fd(sd_memfd *m) {
158 assert_return(m, -EINVAL);
160 fd = fcntl(m->fd, F_DUPFD_CLOEXEC, 3);
167 int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) {
171 assert_return(m, -EINVAL);
172 assert_return(size > 0, -EINVAL);
173 assert_return(p, -EINVAL);
175 sealed = sd_memfd_get_sealed(m);
179 q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_PRIVATE, m->fd, offset);
187 int sd_memfd_set_sealed(sd_memfd *m) {
190 assert_return(m, -EINVAL);
192 r = fcntl(m->fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
199 int sd_memfd_get_sealed(sd_memfd *m) {
202 assert_return(m, -EINVAL);
204 r = fcntl(m->fd, F_GET_SEALS);
208 return (r & (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE)) ==
209 (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
212 int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) {
216 assert_return(m, -EINVAL);
217 assert_return(sz, -EINVAL);
219 r = fstat(m->fd, &stat);
227 int sd_memfd_set_size(sd_memfd *m, uint64_t sz) {
230 assert_return(m, -EINVAL);
232 r = ftruncate(m->fd, sz);
239 int sd_memfd_new_and_map(sd_memfd **m, const char *name, size_t sz, void **p) {
243 r = sd_memfd_new(&n, name);
247 r = sd_memfd_set_size(n, sz);
253 r = sd_memfd_map(n, 0, sz, p);
263 int sd_memfd_get_name(sd_memfd *m, char **name) {
264 char path[sizeof("/proc/self/fd/") + DECIMAL_STR_MAX(int)], buf[FILENAME_MAX+1], *e;
265 const char *delim, *end;
266 _cleanup_free_ char *n = NULL;
269 assert_return(m, -EINVAL);
270 assert_return(name, -EINVAL);
272 sprintf(path, "/proc/self/fd/%i", m->fd);
274 k = readlink(path, buf, sizeof(buf));
278 if ((size_t) k >= sizeof(buf))
283 delim = strstr(buf, ":[");
287 delim = strchr(delim + 2, ':');
293 end = strchr(delim, ']');
297 n = strndup(delim, end - delim);
301 e = bus_label_unescape(n);