]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/memfd-util.c
tree-wide: remove Lennart's copyright lines
[thirdparty/systemd.git] / src / basic / memfd-util.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
ddeb4241 2
11c3a366 3#include <errno.h>
ddeb4241 4#include <fcntl.h>
11c3a366
TA
5#include <sys/stat.h>
6#include <unistd.h>
349cc4a5 7#if HAVE_LINUX_MEMFD_H
07630cea 8#include <linux/memfd.h>
27c64db6 9#endif
07630cea
LP
10#include <stdio.h>
11#include <sys/mman.h>
12#include <sys/prctl.h>
27c64db6 13
b5efdb8a 14#include "alloc-util.h"
3ffd4af2 15#include "fd-util.h"
93cc7779 16#include "macro.h"
3ffd4af2 17#include "memfd-util.h"
07630cea
LP
18#include "missing.h"
19#include "string-util.h"
20#include "utf8.h"
ddeb4241 21
4531a9bc 22int memfd_new(const char *name) {
7f96b1d8 23 _cleanup_free_ char *g = NULL;
4531a9bc 24 int fd;
ddeb4241 25
5755381f 26 if (!name) {
7f96b1d8
LP
27 char pr[17] = {};
28
29 /* If no name is specified we generate one. We include
30 * a hint indicating our library implementation, and
31 * add the thread name to it */
32
33 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
34
35 if (isempty(pr))
36 name = "sd";
37 else {
5755381f
LP
38 _cleanup_free_ char *e = NULL;
39
40 e = utf8_escape_invalid(pr);
41 if (!e)
42 return -ENOMEM;
43
44 g = strappend("sd-", e);
7f96b1d8
LP
45 if (!g)
46 return -ENOMEM;
47
48 name = g;
49 }
50 }
51
45071fca 52 fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
4531a9bc 53 if (fd < 0)
a6082d77 54 return -errno;
ddeb4241 55
4531a9bc 56 return fd;
ddeb4241
LP
57}
58
fac9c0d5 59int memfd_map(int fd, uint64_t offset, size_t size, void **p) {
ddeb4241
LP
60 void *q;
61 int sealed;
62
4531a9bc
LP
63 assert(fd >= 0);
64 assert(size > 0);
65 assert(p);
ddeb4241 66
fac9c0d5 67 sealed = memfd_get_sealed(fd);
ddeb4241
LP
68 if (sealed < 0)
69 return sealed;
70
23972f42 71 if (sealed)
fac9c0d5 72 q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset);
23972f42 73 else
fac9c0d5 74 q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
23972f42 75
ddeb4241
LP
76 if (q == MAP_FAILED)
77 return -errno;
78
79 *p = q;
80 return 0;
81}
82
fac9c0d5 83int memfd_set_sealed(int fd) {
ddeb4241
LP
84 int r;
85
4531a9bc 86 assert(fd >= 0);
ddeb4241 87
db74cc0d 88 r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
ddeb4241
LP
89 if (r < 0)
90 return -errno;
91
92 return 0;
93}
94
fac9c0d5 95int memfd_get_sealed(int fd) {
a6082d77 96 int r;
ddeb4241 97
4531a9bc 98 assert(fd >= 0);
ddeb4241 99
fac9c0d5 100 r = fcntl(fd, F_GET_SEALS);
ddeb4241
LP
101 if (r < 0)
102 return -errno;
103
db74cc0d 104 return r == (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
ddeb4241
LP
105}
106
fac9c0d5 107int memfd_get_size(int fd, uint64_t *sz) {
a6082d77 108 struct stat stat;
4531a9bc 109 int r;
ddeb4241 110
4531a9bc
LP
111 assert(fd >= 0);
112 assert(sz);
ddeb4241 113
fac9c0d5 114 r = fstat(fd, &stat);
ddeb4241
LP
115 if (r < 0)
116 return -errno;
117
a6082d77 118 *sz = stat.st_size;
5755381f 119 return 0;
ddeb4241
LP
120}
121
fac9c0d5 122int memfd_set_size(int fd, uint64_t sz) {
ddeb4241
LP
123 int r;
124
4531a9bc 125 assert(fd >= 0);
ddeb4241 126
fac9c0d5 127 r = ftruncate(fd, sz);
ddeb4241
LP
128 if (r < 0)
129 return -errno;
130
5755381f 131 return 0;
ddeb4241 132}
453a0c29 133
4531a9bc
LP
134int memfd_new_and_map(const char *name, size_t sz, void **p) {
135 _cleanup_close_ int fd = -1;
453a0c29
LP
136 int r;
137
4531a9bc
LP
138 assert(sz > 0);
139 assert(p);
140
141 fd = memfd_new(name);
142 if (fd < 0)
143 return fd;
453a0c29 144
4531a9bc 145 r = memfd_set_size(fd, sz);
8a02deca 146 if (r < 0)
453a0c29 147 return r;
453a0c29 148
4531a9bc 149 r = memfd_map(fd, 0, sz, p);
8a02deca 150 if (r < 0)
453a0c29 151 return r;
453a0c29 152
c10d6bdb 153 return TAKE_FD(fd);
453a0c29 154}