• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 14785896885

01 May 2025 10:34AM UTC coverage: 72.243% (+0.02%) from 72.225%
14785896885

push

github

yuwata
build(deps): bump softprops/action-gh-release from 2.2.1 to 2.2.2

Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.2.1 to 2.2.2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/c95fe1489...da05d5525)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 2.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

297212 of 411406 relevant lines covered (72.24%)

692806.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.05
/src/basic/pidfd-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <sys/ioctl.h>
4
#include <threads.h>
5
#include <unistd.h>
6

7
#include "errno-util.h"
8
#include "fd-util.h"
9
#include "fileio.h"
10
#include "log.h"
11
#include "macro.h"
12
#include "memory-util.h"
13
#include "missing_fs.h"
14
#include "missing_magic.h"
15
#include "mountpoint-util.h"
16
#include "parse-util.h"
17
#include "path-util.h"
18
#include "pidfd-util.h"
19
#include "process-util.h"
20
#include "stat-util.h"
21
#include "string-util.h"
22

23
static int have_pidfs = -1;
24

25
static int pidfd_check_pidfs(int pid_fd) {
39,600✔
26

27
        /* NB: the passed fd *must* be acquired via pidfd_open(), i.e. must be a true pidfd! */
28

29
        if (have_pidfs >= 0)
39,600✔
30
                return have_pidfs;
31

32
        return (have_pidfs = fd_is_fs_type(pid_fd, PID_FS_MAGIC));
18,951✔
33
}
34

35
int pidfd_get_namespace(int fd, unsigned long ns_type_cmd) {
8,191✔
36
        static bool cached_supported = true;
8,191✔
37

38
        /* Obtain the namespace fd from pidfd directly through ioctl(PIDFD_GET_*_NAMESPACE).
39
         *
40
         * Returns -EOPNOTSUPP if ioctl on pidfds are not supported, -ENOPKG if the requested namespace
41
         * is disabled in kernel. (The errno used are different from what kernel returns via ioctl(),
42
         * see below) */
43

44
        assert(fd >= 0);
8,191✔
45

46
        /* If we know ahead of time that pidfs is unavailable, shortcut things. But otherwise we don't
47
         * call pidfd_check_pidfs() here, which is kinda extraneous and our own cache is required
48
         * anyways (pidfs is introduced in kernel 6.9 while ioctl support there is added in 6.11). */
49
        if (have_pidfs == 0 || !cached_supported)
8,191✔
50
                return -EOPNOTSUPP;
51

52
        int nsfd = ioctl(fd, ns_type_cmd);
7,755✔
53
        if (nsfd < 0) {
7,755✔
54
                /* Kernel returns EOPNOTSUPP if the ns type in question is disabled. Hence we need to look
55
                 * at precise errno instead of generic ERRNO_IS_(IOCTL_)NOT_SUPPORTED. */
56
                if (IN_SET(errno, ENOTTY, EINVAL)) {
17✔
57
                        cached_supported = false;
17✔
58
                        return -EOPNOTSUPP;
17✔
59
                }
60
                if (errno == EOPNOTSUPP) /* Translate to something more recognizable */
×
61
                        return -ENOPKG;
62

63
                return -errno;
×
64
        }
65

66
        return nsfd;
67
}
68

69
static int pidfd_get_info(int fd, struct pidfd_info *info) {
51,389✔
70
        static bool cached_supported = true;
51,389✔
71

72
        assert(fd >= 0);
51,389✔
73
        assert(info);
51,389✔
74

75
        if (have_pidfs == 0 || !cached_supported)
51,389✔
76
                return -EOPNOTSUPP;
77

78
        if (ioctl(fd, PIDFD_GET_INFO, info) < 0) {
37,093✔
79
                if (ERRNO_IS_IOCTL_NOT_SUPPORTED(errno)) {
3,127✔
80
                        cached_supported = false;
2,569✔
81
                        return -EOPNOTSUPP;
2,569✔
82
                }
83

84
                return -errno;
558✔
85
        }
86

87
        return 0;
88
}
89

90
static int pidfd_get_pid_fdinfo(int fd, pid_t *ret) {
15,472✔
91
        char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
15,472✔
92
        _cleanup_free_ char *p = NULL;
15,472✔
93
        int r;
15,472✔
94

95
        assert(fd >= 0);
15,472✔
96

97
        xsprintf(path, "/proc/self/fdinfo/%i", fd);
15,472✔
98

99
        r = get_proc_field(path, "Pid", &p);
15,472✔
100
        if (r == -ENOENT)
15,472✔
101
                return -EBADF;
102
        if (r == -ENODATA) /* not a pidfd? */
15,472✔
103
                return -ENOTTY;
104
        if (r < 0)
15,472✔
105
                return r;
106

107
        if (streq(p, "0"))
15,472✔
108
                return -EREMOTE; /* PID is in foreign PID namespace? */
109
        if (streq(p, "-1"))
15,472✔
110
                return -ESRCH;   /* refers to reaped process? */
111

112
        return parse_pid(p, ret);
14,083✔
113
}
114

115
static int pidfd_get_pid_ioctl(int fd, pid_t *ret) {
48,940✔
116
        struct pidfd_info info = { .mask = PIDFD_INFO_PID };
48,940✔
117
        int r;
48,940✔
118

119
        assert(fd >= 0);
48,940✔
120

121
        r = pidfd_get_info(fd, &info);
48,940✔
122
        if (r < 0)
48,940✔
123
                return r;
48,940✔
124

125
        assert(FLAGS_SET(info.mask, PIDFD_INFO_PID));
32,910✔
126

127
        if (ret)
32,910✔
128
                *ret = info.pid;
32,910✔
129
        return 0;
130
}
131

132
int pidfd_get_pid(int fd, pid_t *ret) {
48,940✔
133
        int r;
48,940✔
134

135
        /* Converts a pidfd into a pid. We try ioctl(PIDFD_GET_INFO) (kernel 6.13+) first,
136
         * /proc/self/fdinfo/ as fallback. Well known errors:
137
         *
138
         *    -EBADF   → fd invalid
139
         *    -ESRCH   → fd valid, but process is already reaped
140
         *
141
         * pidfd_get_pid_fdinfo() might additionally fail for other reasons:
142
         *
143
         *    -ENOSYS  → /proc/ not mounted
144
         *    -ENOTTY  → fd valid, but not a pidfd
145
         *    -EREMOTE → fd valid, but pid is in another namespace we cannot translate to the local one
146
         *               (when using PIDFD_GET_INFO this is indistinguishable from -ESRCH)
147
         */
148

149
        assert(fd >= 0);
48,940✔
150

151
        r = pidfd_get_pid_ioctl(fd, ret);
48,940✔
152
        if (r != -EOPNOTSUPP)
48,940✔
153
                return r;
154

155
        return pidfd_get_pid_fdinfo(fd, ret);
15,472✔
156
}
157

158
int pidfd_verify_pid(int pidfd, pid_t pid) {
32,301✔
159
        pid_t current_pid;
32,301✔
160
        int r;
32,301✔
161

162
        assert(pidfd >= 0);
32,301✔
163
        assert(pid > 0);
32,301✔
164

165
        r = pidfd_get_pid(pidfd, &current_pid);
32,301✔
166
        if (r < 0)
32,301✔
167
                return r;
32,301✔
168

169
        return current_pid != pid ? -ESRCH : 0;
30,354✔
170
}
171

172
int pidfd_get_ppid(int fd, pid_t *ret) {
2,395✔
173
        struct pidfd_info info = { .mask = PIDFD_INFO_PID };
2,395✔
174
        int r;
2,395✔
175

176
        assert(fd >= 0);
2,395✔
177

178
        r = pidfd_get_info(fd, &info);
2,395✔
179
        if (r < 0)
2,395✔
180
                return r;
2,395✔
181

182
        assert(FLAGS_SET(info.mask, PIDFD_INFO_PID));
1,011✔
183

184
        if (info.ppid == 0) /* See comments in pid_get_ppid() */
1,011✔
185
                return -EADDRNOTAVAIL;
186

187
        if (ret)
1,011✔
188
                *ret = info.ppid;
1,011✔
189
        return 0;
190
}
191

192
int pidfd_get_uid(int fd, uid_t *ret) {
54✔
193
        struct pidfd_info info = { .mask = PIDFD_INFO_CREDS };
54✔
194
        int r;
54✔
195

196
        assert(fd >= 0);
54✔
197

198
        r = pidfd_get_info(fd, &info);
54✔
199
        if (r < 0)
54✔
200
                return r;
54✔
201

202
        assert(FLAGS_SET(info.mask, PIDFD_INFO_CREDS));
45✔
203

204
        if (ret)
45✔
205
                *ret = info.ruid;
45✔
206
        return 0;
207
}
208

209
int pidfd_get_cgroupid(int fd, uint64_t *ret) {
×
210
        struct pidfd_info info = { .mask = PIDFD_INFO_CGROUPID };
×
211
        int r;
×
212

213
        assert(fd >= 0);
×
214

215
        r = pidfd_get_info(fd, &info);
×
216
        if (r < 0)
×
217
                return r;
×
218

219
        assert(FLAGS_SET(info.mask, PIDFD_INFO_CGROUPID));
×
220

221
        if (ret)
×
222
                *ret = info.cgroupid;
×
223
        return 0;
224
}
225

226
int pidfd_get_inode_id(int fd, uint64_t *ret) {
39,600✔
227
        static bool file_handle_supported = true;
39,600✔
228
        int r;
39,600✔
229

230
        assert(fd >= 0);
39,600✔
231

232
        r = pidfd_check_pidfs(fd);
39,600✔
233
        if (r < 0)
39,600✔
234
                return r;
39,600✔
235
        if (r == 0)
39,600✔
236
                return -EOPNOTSUPP;
237

238
        if (file_handle_supported) {
39,600✔
239
                union {
37,553✔
240
                        struct file_handle file_handle;
241
                        uint8_t space[offsetof(struct file_handle, f_handle) + sizeof(uint64_t)];
242
                } fh = {
37,553✔
243
                        .file_handle.handle_bytes = sizeof(uint64_t),
244
                        .file_handle.handle_type = FILEID_KERNFS,
245
                };
246
                int mnt_id;
37,553✔
247

248
                r = RET_NERRNO(name_to_handle_at(fd, "", &fh.file_handle, &mnt_id, AT_EMPTY_PATH));
37,553✔
249
                if (r >= 0) {
3,603✔
250
                        if (ret)
33,950✔
251
                                *ret = *(uint64_t*) fh.file_handle.f_handle;
33,950✔
252
                        return 0;
33,950✔
253
                }
254
                assert(r != -EOVERFLOW);
3,603✔
255
                if (is_name_to_handle_at_fatal_error(r))
3,603✔
256
                        return r;
257

258
                file_handle_supported = false;
3,603✔
259
        }
260

261
#if SIZEOF_INO_T == 8
262
        struct stat st;
5,650✔
263
        if (fstat(fd, &st) < 0)
5,650✔
264
                return -errno;
×
265

266
        if (ret)
5,650✔
267
                *ret = (uint64_t) st.st_ino;
5,650✔
268
        return 0;
269

270
#elif SIZEOF_INO_T == 4
271
        /* On 32-bit systems (where sizeof(ino_t) == 4), the inode id returned by fstat() cannot be used to
272
         * reliably identify the process, nor can we communicate the origin of the id with the clients.
273
         * Hence let's just refuse to acquire pidfdid through fstat() here. All clients shall also insist on
274
         * the 64-bit id from name_to_handle_at(). */
275
        return -EOPNOTSUPP;
276
#else
277
#  error Unsupported ino_t size
278
#endif
279
}
280

281
int pidfd_get_inode_id_self_cached(uint64_t *ret) {
39,068✔
282
        static thread_local uint64_t cached = 0;
39,068✔
283
        static thread_local pid_t initialized = 0; /* < 0: cached error; == 0: invalid; > 0: valid and pid that was current */
39,068✔
284
        int r;
39,068✔
285

286
        assert(ret);
39,068✔
287

288
        if (initialized == getpid_cached()) {
39,068✔
289
                *ret = cached;
4,666✔
290
                return 0;
4,666✔
291
        }
292
        if (initialized < 0)
34,402✔
293
                return initialized;
294

295
        _cleanup_close_ int fd = pidfd_open(getpid_cached(), 0);
73,470✔
296
        if (fd < 0)
34,402✔
297
                return -errno;
×
298

299
        r = pidfd_get_inode_id(fd, &cached);
34,402✔
300
        if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
34,402✔
301
                return (initialized = -EOPNOTSUPP);
×
302
        if (r < 0)
34,402✔
303
                return r;
304

305
        *ret = cached;
34,402✔
306
        initialized = getpid_cached();
34,402✔
307
        return 0;
34,402✔
308
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc