Line data Source code
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 16 : int memfd_new(const char *name) {
23 16 : _cleanup_free_ char *g = NULL;
24 : int fd;
25 :
26 16 : if (!name) {
27 1 : 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 1 : assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
34 :
35 1 : if (isempty(pr))
36 0 : name = "sd";
37 : else {
38 1 : _cleanup_free_ char *e = NULL;
39 :
40 1 : e = utf8_escape_invalid(pr);
41 1 : if (!e)
42 0 : return -ENOMEM;
43 :
44 1 : g = strjoin("sd-", e);
45 1 : if (!g)
46 0 : return -ENOMEM;
47 :
48 1 : name = g;
49 : }
50 : }
51 :
52 16 : fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
53 16 : if (fd < 0)
54 0 : return -errno;
55 :
56 16 : return fd;
57 : }
58 :
59 0 : int memfd_map(int fd, uint64_t offset, size_t size, void **p) {
60 : void *q;
61 : int sealed;
62 :
63 0 : assert(fd >= 0);
64 0 : assert(size > 0);
65 0 : assert(p);
66 :
67 0 : sealed = memfd_get_sealed(fd);
68 0 : if (sealed < 0)
69 0 : return sealed;
70 :
71 0 : if (sealed)
72 0 : q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset);
73 : else
74 0 : q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
75 :
76 0 : if (q == MAP_FAILED)
77 0 : return -errno;
78 :
79 0 : *p = q;
80 0 : return 0;
81 : }
82 :
83 15 : int memfd_set_sealed(int fd) {
84 : int r;
85 :
86 15 : assert(fd >= 0);
87 :
88 15 : r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
89 15 : if (r < 0)
90 0 : return -errno;
91 :
92 15 : return 0;
93 : }
94 :
95 0 : int memfd_get_sealed(int fd) {
96 : int r;
97 :
98 0 : assert(fd >= 0);
99 :
100 0 : r = fcntl(fd, F_GET_SEALS);
101 0 : if (r < 0)
102 0 : return -errno;
103 :
104 0 : return r == (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
105 : }
106 :
107 0 : int memfd_get_size(int fd, uint64_t *sz) {
108 : struct stat stat;
109 : int r;
110 :
111 0 : assert(fd >= 0);
112 0 : assert(sz);
113 :
114 0 : r = fstat(fd, &stat);
115 0 : if (r < 0)
116 0 : return -errno;
117 :
118 0 : *sz = stat.st_size;
119 0 : return 0;
120 : }
121 :
122 0 : int memfd_set_size(int fd, uint64_t sz) {
123 : int r;
124 :
125 0 : assert(fd >= 0);
126 :
127 0 : r = ftruncate(fd, sz);
128 0 : if (r < 0)
129 0 : return -errno;
130 :
131 0 : return 0;
132 : }
133 :
134 0 : int memfd_new_and_map(const char *name, size_t sz, void **p) {
135 0 : _cleanup_close_ int fd = -1;
136 : int r;
137 :
138 0 : assert(sz > 0);
139 0 : assert(p);
140 :
141 0 : fd = memfd_new(name);
142 0 : if (fd < 0)
143 0 : return fd;
144 :
145 0 : r = memfd_set_size(fd, sz);
146 0 : if (r < 0)
147 0 : return r;
148 :
149 0 : r = memfd_map(fd, 0, sz, p);
150 0 : if (r < 0)
151 0 : return r;
152 :
153 0 : return TAKE_FD(fd);
154 : }
|