]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/memfd-util.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / basic / memfd-util.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
ddeb4241
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
11c3a366 21#include <errno.h>
ddeb4241 22#include <fcntl.h>
11c3a366
TA
23#include <sys/stat.h>
24#include <unistd.h>
349cc4a5 25#if HAVE_LINUX_MEMFD_H
07630cea 26#include <linux/memfd.h>
27c64db6 27#endif
07630cea
LP
28#include <stdio.h>
29#include <sys/mman.h>
30#include <sys/prctl.h>
27c64db6 31
b5efdb8a 32#include "alloc-util.h"
3ffd4af2 33#include "fd-util.h"
93cc7779 34#include "macro.h"
3ffd4af2 35#include "memfd-util.h"
07630cea
LP
36#include "missing.h"
37#include "string-util.h"
38#include "utf8.h"
ddeb4241 39
4531a9bc 40int memfd_new(const char *name) {
7f96b1d8 41 _cleanup_free_ char *g = NULL;
4531a9bc 42 int fd;
ddeb4241 43
5755381f 44 if (!name) {
7f96b1d8
LP
45 char pr[17] = {};
46
47 /* If no name is specified we generate one. We include
48 * a hint indicating our library implementation, and
49 * add the thread name to it */
50
51 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
52
53 if (isempty(pr))
54 name = "sd";
55 else {
5755381f
LP
56 _cleanup_free_ char *e = NULL;
57
58 e = utf8_escape_invalid(pr);
59 if (!e)
60 return -ENOMEM;
61
62 g = strappend("sd-", e);
7f96b1d8
LP
63 if (!g)
64 return -ENOMEM;
65
66 name = g;
67 }
68 }
69
45071fca 70 fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
4531a9bc 71 if (fd < 0)
a6082d77 72 return -errno;
ddeb4241 73
4531a9bc 74 return fd;
ddeb4241
LP
75}
76
fac9c0d5 77int memfd_map(int fd, uint64_t offset, size_t size, void **p) {
ddeb4241
LP
78 void *q;
79 int sealed;
80
4531a9bc
LP
81 assert(fd >= 0);
82 assert(size > 0);
83 assert(p);
ddeb4241 84
fac9c0d5 85 sealed = memfd_get_sealed(fd);
ddeb4241
LP
86 if (sealed < 0)
87 return sealed;
88
23972f42 89 if (sealed)
fac9c0d5 90 q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset);
23972f42 91 else
fac9c0d5 92 q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
23972f42 93
ddeb4241
LP
94 if (q == MAP_FAILED)
95 return -errno;
96
97 *p = q;
98 return 0;
99}
100
fac9c0d5 101int memfd_set_sealed(int fd) {
ddeb4241
LP
102 int r;
103
4531a9bc 104 assert(fd >= 0);
ddeb4241 105
db74cc0d 106 r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
ddeb4241
LP
107 if (r < 0)
108 return -errno;
109
110 return 0;
111}
112
fac9c0d5 113int memfd_get_sealed(int fd) {
a6082d77 114 int r;
ddeb4241 115
4531a9bc 116 assert(fd >= 0);
ddeb4241 117
fac9c0d5 118 r = fcntl(fd, F_GET_SEALS);
ddeb4241
LP
119 if (r < 0)
120 return -errno;
121
db74cc0d 122 return r == (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
ddeb4241
LP
123}
124
fac9c0d5 125int memfd_get_size(int fd, uint64_t *sz) {
a6082d77 126 struct stat stat;
4531a9bc 127 int r;
ddeb4241 128
4531a9bc
LP
129 assert(fd >= 0);
130 assert(sz);
ddeb4241 131
fac9c0d5 132 r = fstat(fd, &stat);
ddeb4241
LP
133 if (r < 0)
134 return -errno;
135
a6082d77 136 *sz = stat.st_size;
5755381f 137 return 0;
ddeb4241
LP
138}
139
fac9c0d5 140int memfd_set_size(int fd, uint64_t sz) {
ddeb4241
LP
141 int r;
142
4531a9bc 143 assert(fd >= 0);
ddeb4241 144
fac9c0d5 145 r = ftruncate(fd, sz);
ddeb4241
LP
146 if (r < 0)
147 return -errno;
148
5755381f 149 return 0;
ddeb4241 150}
453a0c29 151
4531a9bc
LP
152int memfd_new_and_map(const char *name, size_t sz, void **p) {
153 _cleanup_close_ int fd = -1;
453a0c29
LP
154 int r;
155
4531a9bc
LP
156 assert(sz > 0);
157 assert(p);
158
159 fd = memfd_new(name);
160 if (fd < 0)
161 return fd;
453a0c29 162
4531a9bc 163 r = memfd_set_size(fd, sz);
8a02deca 164 if (r < 0)
453a0c29 165 return r;
453a0c29 166
4531a9bc 167 r = memfd_map(fd, 0, sz, p);
8a02deca 168 if (r < 0)
453a0c29 169 return r;
453a0c29 170
4531a9bc
LP
171 r = fd;
172 fd = -1;
173
174 return r;
453a0c29 175}