Coverage Report

Created: 2019-06-19 13:33

/src/systemd/src/basic/memfd-util.c
Line
Count
Source (jump to first uncovered line)
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
5.28k
int memfd_new(const char *name) {
23
5.28k
        _cleanup_free_ char *g = NULL;
24
5.28k
        int fd;
25
5.28k
26
5.28k
        if (!name) {
27
983
                char pr[17] = {};
28
983
29
983
                /* If no name is specified we generate one. We include
30
983
                 * a hint indicating our library implementation, and
31
983
                 * add the thread name to it */
32
983
33
983
                assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
34
983
35
983
                if (isempty(pr))
36
0
                        name = "sd";
37
983
                else {
38
983
                        _cleanup_free_ char *e = NULL;
39
983
40
983
                        e = utf8_escape_invalid(pr);
41
983
                        if (!e)
42
0
                                return -ENOMEM;
43
983
44
983
                        g = strappend("sd-", e);
45
983
                        if (!g)
46
0
                                return -ENOMEM;
47
983
48
983
                        name = g;
49
983
                }
50
983
        }
51
5.28k
52
5.28k
        fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
53
5.28k
        if (fd < 0)
54
0
                return -errno;
55
5.28k
56
5.28k
        return fd;
57
5.28k
}
58
59
4.30k
int memfd_map(int fd, uint64_t offset, size_t size, void **p) {
60
4.30k
        void *q;
61
4.30k
        int sealed;
62
4.30k
63
4.30k
        assert(fd >= 0);
64
4.30k
        assert(size > 0);
65
4.30k
        assert(p);
66
4.30k
67
4.30k
        sealed = memfd_get_sealed(fd);
68
4.30k
        if (sealed < 0)
69
0
                return sealed;
70
4.30k
71
4.30k
        if (sealed)
72
0
                q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset);
73
4.30k
        else
74
4.30k
                q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
75
4.30k
76
4.30k
        if (q == MAP_FAILED)
77
4.30k
                return -errno;
78
4.30k
79
4.30k
        *p = q;
80
4.30k
        return 0;
81
4.30k
}
82
83
983
int memfd_set_sealed(int fd) {
84
983
        int r;
85
983
86
983
        assert(fd >= 0);
87
983
88
983
        r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
89
983
        if (r < 0)
90
0
                return -errno;
91
983
92
983
        return 0;
93
983
}
94
95
6.27k
int memfd_get_sealed(int fd) {
96
6.27k
        int r;
97
6.27k
98
6.27k
        assert(fd >= 0);
99
6.27k
100
6.27k
        r = fcntl(fd, F_GET_SEALS);
101
6.27k
        if (r < 0)
102
983
                return -errno;
103
5.28k
104
5.28k
        return r == (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
105
5.28k
}
106
107
0
int memfd_get_size(int fd, uint64_t *sz) {
108
0
        struct stat stat;
109
0
        int r;
110
0
111
0
        assert(fd >= 0);
112
0
        assert(sz);
113
0
114
0
        r = fstat(fd, &stat);
115
0
        if (r < 0)
116
0
                return -errno;
117
0
118
0
        *sz = stat.st_size;
119
0
        return 0;
120
0
}
121
122
4.30k
int memfd_set_size(int fd, uint64_t sz) {
123
4.30k
        int r;
124
4.30k
125
4.30k
        assert(fd >= 0);
126
4.30k
127
4.30k
        r = ftruncate(fd, sz);
128
4.30k
        if (r < 0)
129
0
                return -errno;
130
4.30k
131
4.30k
        return 0;
132
4.30k
}
133
134
4.30k
int memfd_new_and_map(const char *name, size_t sz, void **p) {
135
4.30k
        _cleanup_close_ int fd = -1;
136
4.30k
        int r;
137
4.30k
138
4.30k
        assert(sz > 0);
139
4.30k
        assert(p);
140
4.30k
141
4.30k
        fd = memfd_new(name);
142
4.30k
        if (fd < 0)
143
0
                return fd;
144
4.30k
145
4.30k
        r = memfd_set_size(fd, sz);
146
4.30k
        if (r < 0)
147
0
                return r;
148
4.30k
149
4.30k
        r = memfd_map(fd, 0, sz, p);
150
4.30k
        if (r < 0)
151
0
                return r;
152
4.30k
153
4.30k
        return TAKE_FD(fd);
154
4.30k
}