mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 16:37:19 +09:00
So here's the thing. One library we use (libselinux) is opening fds behind our back when we initialize it and keeps it open. On the other hand we want to automatically pick up all fds passed in to us, so that we can distribute them to our services and close the rest. We pick them up very early in our code, to ensure that we don't get confused by open fds at that point. Except that libselinux insists on being initialized even earlier. So suddenly we might take possession of libselinux' fds, and then close them later when we decide no service wants them. Then during shutdown we close down selinux and selinux closes its fds, but since already closed long ago this ight close our fds instead. Hilarity ensues. I wish low-level software wouldn't do such things behind our back, but well, let's make the best of it. This changes the fd pick-up logic to only pick up fds that have O_CLOEXEC unset. O_CLOEXEC must be unset for any fds passed in to us over execve() after all. And for all our own fds we should set O_CLOEXEC since we generally don't want to litter fd tables for execve(). Also, libselinux thankfully appears to set O_CLOEXEC correctly on its fds, hence the filter works. Fixes: #27491
48 lines
1.2 KiB
C
48 lines
1.2 KiB
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "hashmap.h"
|
|
#include "macro.h"
|
|
#include "set.h"
|
|
|
|
typedef struct FDSet FDSet;
|
|
|
|
FDSet* fdset_new(void);
|
|
FDSet* fdset_free(FDSet *s);
|
|
|
|
int fdset_put(FDSet *s, int fd);
|
|
int fdset_consume(FDSet *s, int fd);
|
|
int fdset_put_dup(FDSet *s, int fd);
|
|
|
|
bool fdset_contains(FDSet *s, int fd);
|
|
int fdset_remove(FDSet *s, int fd);
|
|
|
|
int fdset_new_array(FDSet **ret, const int *fds, size_t n_fds);
|
|
int fdset_new_fill(int filter_cloexec, FDSet **ret);
|
|
int fdset_new_listen_fds(FDSet **ret, bool unset);
|
|
|
|
int fdset_cloexec(FDSet *fds, bool b);
|
|
|
|
int fdset_to_array(FDSet *fds, int **ret);
|
|
|
|
int fdset_close_others(FDSet *fds);
|
|
|
|
unsigned fdset_size(FDSet *fds);
|
|
bool fdset_isempty(FDSet *fds);
|
|
|
|
int fdset_iterate(FDSet *s, Iterator *i);
|
|
|
|
int fdset_steal_first(FDSet *fds);
|
|
|
|
void fdset_close(FDSet *fds);
|
|
|
|
#define _FDSET_FOREACH(fd, fds, i) \
|
|
for (Iterator i = ITERATOR_FIRST; ((fd) = fdset_iterate((fds), &i)) >= 0; )
|
|
#define FDSET_FOREACH(fd, fds) \
|
|
_FDSET_FOREACH(fd, fds, UNIQ_T(i, UNIQ))
|
|
|
|
DEFINE_TRIVIAL_CLEANUP_FUNC(FDSet*, fdset_free);
|
|
#define _cleanup_fdset_free_ _cleanup_(fdset_freep)
|