Branch data 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 : 64 : int memfd_new(const char *name) {
23 : 64 : _cleanup_free_ char *g = NULL;
24 : : int fd;
25 : :
26 [ + + ]: 64 : if (!name) {
27 : 4 : 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 [ - + ]: 4 : assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
34 : :
35 [ - + ]: 4 : if (isempty(pr))
36 : 0 : name = "sd";
37 : : else {
38 [ + - ]: 4 : _cleanup_free_ char *e = NULL;
39 : :
40 : 4 : e = utf8_escape_invalid(pr);
41 [ - + ]: 4 : if (!e)
42 : 0 : return -ENOMEM;
43 : :
44 : 4 : g = strjoin("sd-", e);
45 [ - + ]: 4 : if (!g)
46 : 0 : return -ENOMEM;
47 : :
48 : 4 : name = g;
49 : : }
50 : : }
51 : :
52 : 64 : fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
53 [ - + ]: 64 : if (fd < 0)
54 : 0 : return -errno;
55 : :
56 : 64 : 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 : 60 : int memfd_set_sealed(int fd) {
84 : : int r;
85 : :
86 [ - + ]: 60 : assert(fd >= 0);
87 : :
88 : 60 : r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
89 [ - + ]: 60 : if (r < 0)
90 : 0 : return -errno;
91 : :
92 : 60 : 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 : : }
|