]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/memfd-util.c
tree-wide: remove Lennart's copyright lines
[thirdparty/systemd.git] / src / basic / memfd-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 #if HAVE_LINUX_MEMFD_H
8 #include <linux/memfd.h>
9 #endif
10 #include <stdio.h>
11 #include <sys/mman.h>
12 #include <sys/prctl.h>
13
14 #include "alloc-util.h"
15 #include "fd-util.h"
16 #include "macro.h"
17 #include "memfd-util.h"
18 #include "missing.h"
19 #include "string-util.h"
20 #include "utf8.h"
21
22 int memfd_new(const char *name) {
23 _cleanup_free_ char *g = NULL;
24 int fd;
25
26 if (!name) {
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 {
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);
45 if (!g)
46 return -ENOMEM;
47
48 name = g;
49 }
50 }
51
52 fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
53 if (fd < 0)
54 return -errno;
55
56 return fd;
57 }
58
59 int memfd_map(int fd, uint64_t offset, size_t size, void **p) {
60 void *q;
61 int sealed;
62
63 assert(fd >= 0);
64 assert(size > 0);
65 assert(p);
66
67 sealed = memfd_get_sealed(fd);
68 if (sealed < 0)
69 return sealed;
70
71 if (sealed)
72 q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset);
73 else
74 q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
75
76 if (q == MAP_FAILED)
77 return -errno;
78
79 *p = q;
80 return 0;
81 }
82
83 int memfd_set_sealed(int fd) {
84 int r;
85
86 assert(fd >= 0);
87
88 r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
89 if (r < 0)
90 return -errno;
91
92 return 0;
93 }
94
95 int memfd_get_sealed(int fd) {
96 int r;
97
98 assert(fd >= 0);
99
100 r = fcntl(fd, F_GET_SEALS);
101 if (r < 0)
102 return -errno;
103
104 return r == (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
105 }
106
107 int memfd_get_size(int fd, uint64_t *sz) {
108 struct stat stat;
109 int r;
110
111 assert(fd >= 0);
112 assert(sz);
113
114 r = fstat(fd, &stat);
115 if (r < 0)
116 return -errno;
117
118 *sz = stat.st_size;
119 return 0;
120 }
121
122 int memfd_set_size(int fd, uint64_t sz) {
123 int r;
124
125 assert(fd >= 0);
126
127 r = ftruncate(fd, sz);
128 if (r < 0)
129 return -errno;
130
131 return 0;
132 }
133
134 int memfd_new_and_map(const char *name, size_t sz, void **p) {
135 _cleanup_close_ int fd = -1;
136 int r;
137
138 assert(sz > 0);
139 assert(p);
140
141 fd = memfd_new(name);
142 if (fd < 0)
143 return fd;
144
145 r = memfd_set_size(fd, sz);
146 if (r < 0)
147 return r;
148
149 r = memfd_map(fd, 0, sz, p);
150 if (r < 0)
151 return r;
152
153 return TAKE_FD(fd);
154 }