systemd: merge branch systemd into master

This commit is contained in:
Thomas Haller
2019-12-15 14:28:45 +01:00
31 changed files with 1602 additions and 110 deletions

View File

@@ -101,3 +101,11 @@ static inline bool ERRNO_IS_PRIVILEGE(int r) {
EACCES,
EPERM);
}
/* Three difference errors for "not enough disk space" */
static inline bool ERRNO_IS_DISK_SPACE(int r) {
return IN_SET(abs(r),
ENOSPC,
EDQUOT,
EFBIG);
}

View File

@@ -551,6 +551,7 @@ int get_files_in_directory(const char *path, char ***list) {
return n;
}
#endif /* NM_IGNORED */
static int getenv_tmp_dir(const char **ret_path) {
const char *n;
@@ -622,6 +623,7 @@ static int tmp_dir_internal(const char *def, const char **ret) {
return 0;
}
#if 0 /* NM_IGNORED */
int var_tmp_dir(const char **ret) {
/* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
@@ -631,6 +633,7 @@ int var_tmp_dir(const char **ret) {
return tmp_dir_internal("/var/tmp", ret);
}
#endif /* NM_IGNORED */
int tmp_dir(const char **ret) {
@@ -640,6 +643,7 @@ int tmp_dir(const char **ret) {
return tmp_dir_internal("/tmp", ret);
}
#if 0 /* NM_IGNORED */
int unlink_or_warn(const char *filename) {
if (unlink(filename) < 0 && errno != ENOENT)
/* If the file doesn't exist and the fs simply was read-only (in which

View File

@@ -172,6 +172,11 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
/* align to next higher power-of-2 (except for: 0 => 0, overflow => 0) */
static inline unsigned long ALIGN_POWER2(unsigned long u) {
/* Avoid subtraction overflow */
if (u == 0)
return 0;
/* clz(0) is undefined */
if (u == 1)
return 1;
@@ -183,6 +188,29 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
return 1UL << (sizeof(u) * 8 - __builtin_clzl(u - 1UL));
}
static inline size_t GREEDY_ALLOC_ROUND_UP(size_t l) {
size_t m;
/* Round up allocation sizes a bit to some reasonable, likely larger value. This is supposed to be
* used for cases which are likely called in an allocation loop of some form, i.e. that repetitively
* grow stuff, for example strv_extend() and suchlike.
*
* Note the difference to GREEDY_REALLOC() here, as this helper operates on a single size value only,
* and rounds up to next multiple of 2, needing no further counter.
*
* Note the benefits of direct ALIGN_POWER2() usage: type-safety for size_t, sane handling for very
* small (i.e. <= 2) and safe handling for very large (i.e. > SSIZE_MAX) values. */
if (l <= 2)
return 2; /* Never allocate less than 2 of something. */
m = ALIGN_POWER2(l);
if (m == 0) /* overflow? */
return l;
return m;
}
#ifndef __COVERITY__
# define VOID_0 ((void)0)
#else

View File

@@ -80,14 +80,21 @@ static inline void* explicit_bzero_safe(void *p, size_t l) {
void *explicit_bzero_safe(void *p, size_t l);
#endif
static inline void erase_and_freep(void *p) {
void *ptr = *(void**) p;
static inline void* erase_and_free(void *p) {
size_t l;
if (ptr) {
size_t l = malloc_usable_size(ptr);
explicit_bzero_safe(ptr, l);
free(ptr);
}
if (!p)
return NULL;
l = malloc_usable_size(p);
explicit_bzero_safe(p, l);
free(p);
return NULL;
}
static inline void erase_and_freep(void *p) {
erase_and_free(*(void**) p);
}
/* Use with _cleanup_ to erase a single 'char' when leaving scope */

View File

@@ -0,0 +1,574 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/* Missing glibc definitions to access certain kernel APIs */
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#ifdef ARCH_MIPS
#include <asm/sgidefs.h>
#endif
#include "missing_keyctl.h"
#include "missing_stat.h"
#if 0 /* NM_IGNORED */
/* linux/kcmp.h */
#ifndef KCMP_FILE /* 3f4994cfc15f38a3159c6e3a4b3ab2e1481a6b02 (3.19) */
#define KCMP_FILE 0
#endif
#if !HAVE_PIVOT_ROOT
static inline int missing_pivot_root(const char *new_root, const char *put_old) {
return syscall(__NR_pivot_root, new_root, put_old);
}
# define pivot_root missing_pivot_root
#endif
/* ======================================================================= */
#if !HAVE_MEMFD_CREATE
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_memfd_create && __NR_memfd_create >= 0)
# if defined __NR_memfd_create
# undef __NR_memfd_create
# endif
# if defined __x86_64__
# define __NR_memfd_create 319
# elif defined __arm__
# define __NR_memfd_create 385
# elif defined __aarch64__
# define __NR_memfd_create 279
# elif defined __s390__
# define __NR_memfd_create 350
# elif defined _MIPS_SIM
# if _MIPS_SIM == _MIPS_SIM_ABI32
# define __NR_memfd_create 4354
# endif
# if _MIPS_SIM == _MIPS_SIM_NABI32
# define __NR_memfd_create 6318
# endif
# if _MIPS_SIM == _MIPS_SIM_ABI64
# define __NR_memfd_create 5314
# endif
# elif defined __i386__
# define __NR_memfd_create 356
# elif defined __arc__
# define __NR_memfd_create 279
# else
# warning "__NR_memfd_create unknown for your architecture"
# endif
# endif
static inline int missing_memfd_create(const char *name, unsigned int flags) {
# ifdef __NR_memfd_create
return syscall(__NR_memfd_create, name, flags);
# else
errno = ENOSYS;
return -1;
# endif
}
# define memfd_create missing_memfd_create
#endif
/* ======================================================================= */
#if !HAVE_GETRANDOM
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_getrandom && __NR_getrandom >= 0)
# if defined __NR_getrandom
# undef __NR_getrandom
# endif
# if defined __x86_64__
# define __NR_getrandom 318
# elif defined(__i386__)
# define __NR_getrandom 355
# elif defined(__arm__)
# define __NR_getrandom 384
# elif defined(__aarch64__)
# define __NR_getrandom 278
# elif defined(__ia64__)
# define __NR_getrandom 1339
# elif defined(__m68k__)
# define __NR_getrandom 352
# elif defined(__s390x__)
# define __NR_getrandom 349
# elif defined(__powerpc__)
# define __NR_getrandom 359
# elif defined _MIPS_SIM
# if _MIPS_SIM == _MIPS_SIM_ABI32
# define __NR_getrandom 4353
# endif
# if _MIPS_SIM == _MIPS_SIM_NABI32
# define __NR_getrandom 6317
# endif
# if _MIPS_SIM == _MIPS_SIM_ABI64
# define __NR_getrandom 5313
# endif
# elif defined(__arc__)
# define __NR_getrandom 278
# else
# warning "__NR_getrandom unknown for your architecture"
# endif
# endif
static inline int missing_getrandom(void *buffer, size_t count, unsigned flags) {
# ifdef __NR_getrandom
return syscall(__NR_getrandom, buffer, count, flags);
# else
errno = ENOSYS;
return -1;
# endif
}
# define getrandom missing_getrandom
#endif
/* ======================================================================= */
#if !HAVE_GETTID
static inline pid_t missing_gettid(void) {
return (pid_t) syscall(__NR_gettid);
}
# define gettid missing_gettid
#endif
/* ======================================================================= */
#if !HAVE_NAME_TO_HANDLE_AT
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_name_to_handle_at && __NR_name_to_handle_at >= 0)
# if defined __NR_name_to_handle_at
# undef __NR_name_to_handle_at
# endif
# if defined(__x86_64__)
# define __NR_name_to_handle_at 303
# elif defined(__i386__)
# define __NR_name_to_handle_at 341
# elif defined(__arm__)
# define __NR_name_to_handle_at 370
# elif defined(__powerpc__)
# define __NR_name_to_handle_at 345
# elif defined(__arc__)
# define __NR_name_to_handle_at 264
# else
# error "__NR_name_to_handle_at is not defined"
# endif
# endif
struct file_handle {
unsigned int handle_bytes;
int handle_type;
unsigned char f_handle[0];
};
static inline int missing_name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) {
# ifdef __NR_name_to_handle_at
return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags);
# else
errno = ENOSYS;
return -1;
# endif
}
# define name_to_handle_at missing_name_to_handle_at
#endif
/* ======================================================================= */
#if !HAVE_SETNS
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_setns && __NR_setns >= 0)
# if defined __NR_setns
# undef __NR_setns
# endif
# if defined(__x86_64__)
# define __NR_setns 308
# elif defined(__i386__)
# define __NR_setns 346
# elif defined(__arc__)
# define __NR_setns 268
# else
# error "__NR_setns is not defined"
# endif
# endif
static inline int missing_setns(int fd, int nstype) {
# ifdef __NR_setns
return syscall(__NR_setns, fd, nstype);
# else
errno = ENOSYS;
return -1;
# endif
}
# define setns missing_setns
#endif
/* ======================================================================= */
static inline pid_t raw_getpid(void) {
#if defined(__alpha__)
return (pid_t) syscall(__NR_getxpid);
#else
return (pid_t) syscall(__NR_getpid);
#endif
}
/* ======================================================================= */
#if !HAVE_RENAMEAT2
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_renameat2 && __NR_renameat2 >= 0)
# if defined __NR_renameat2
# undef __NR_renameat2
# endif
# if defined __x86_64__
# define __NR_renameat2 316
# elif defined __arm__
# define __NR_renameat2 382
# elif defined __aarch64__
# define __NR_renameat2 276
# elif defined _MIPS_SIM
# if _MIPS_SIM == _MIPS_SIM_ABI32
# define __NR_renameat2 4351
# endif
# if _MIPS_SIM == _MIPS_SIM_NABI32
# define __NR_renameat2 6315
# endif
# if _MIPS_SIM == _MIPS_SIM_ABI64
# define __NR_renameat2 5311
# endif
# elif defined __i386__
# define __NR_renameat2 353
# elif defined __powerpc64__
# define __NR_renameat2 357
# elif defined __s390__ || defined __s390x__
# define __NR_renameat2 347
# elif defined __arc__
# define __NR_renameat2 276
# else
# warning "__NR_renameat2 unknown for your architecture"
# endif
# endif
static inline int missing_renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) {
# ifdef __NR_renameat2
return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags);
# else
errno = ENOSYS;
return -1;
# endif
}
# define renameat2 missing_renameat2
#endif
/* ======================================================================= */
#if !HAVE_KCMP
static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
# if defined __NR_kcmp && __NR_kcmp >= 0
return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
# else
errno = ENOSYS;
return -1;
# endif
}
# define kcmp missing_kcmp
#endif
/* ======================================================================= */
#if !HAVE_KEYCTL
static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) {
# if defined __NR_keyctl && __NR_keyctl >= 0
return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
# else
errno = ENOSYS;
return -1;
# endif
# define keyctl missing_keyctl
}
static inline key_serial_t missing_add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
# if defined __NR_add_key && __NR_add_key >= 0
return syscall(__NR_add_key, type, description, payload, plen, ringid);
# else
errno = ENOSYS;
return -1;
# endif
# define add_key missing_add_key
}
static inline key_serial_t missing_request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
# if defined __NR_request_key && __NR_request_key >= 0
return syscall(__NR_request_key, type, description, callout_info, destringid);
# else
errno = ENOSYS;
return -1;
# endif
# define request_key missing_request_key
}
#endif
/* ======================================================================= */
#if !HAVE_COPY_FILE_RANGE
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_copy_file_range && __NR_copy_file_range >= 0)
# if defined __NR_copy_file_range
# undef __NR_copy_file_range
# endif
# if defined(__x86_64__)
# define __NR_copy_file_range 326
# elif defined(__i386__)
# define __NR_copy_file_range 377
# elif defined __s390__
# define __NR_copy_file_range 375
# elif defined __arm__
# define __NR_copy_file_range 391
# elif defined __aarch64__
# define __NR_copy_file_range 285
# elif defined __powerpc__
# define __NR_copy_file_range 379
# elif defined __arc__
# define __NR_copy_file_range 285
# else
# warning "__NR_copy_file_range not defined for your architecture"
# endif
# endif
static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in,
int fd_out, loff_t *off_out,
size_t len,
unsigned int flags) {
# ifdef __NR_copy_file_range
return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags);
# else
errno = ENOSYS;
return -1;
# endif
}
# define copy_file_range missing_copy_file_range
#endif
/* ======================================================================= */
#if !HAVE_BPF
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_bpf && __NR_bpf >= 0)
# if defined __NR_bpf
# undef __NR_bpf
# endif
# if defined __i386__
# define __NR_bpf 357
# elif defined __x86_64__
# define __NR_bpf 321
# elif defined __aarch64__
# define __NR_bpf 280
# elif defined __arm__
# define __NR_bpf 386
# elif defined __sparc__
# define __NR_bpf 349
# elif defined __s390__
# define __NR_bpf 351
# elif defined __tilegx__
# define __NR_bpf 280
# else
# warning "__NR_bpf not defined for your architecture"
# endif
# endif
union bpf_attr;
static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) {
#ifdef __NR_bpf
return (int) syscall(__NR_bpf, cmd, attr, size);
#else
errno = ENOSYS;
return -1;
#endif
}
# define bpf missing_bpf
#endif
/* ======================================================================= */
#ifndef __IGNORE_pkey_mprotect
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_pkey_mprotect && __NR_pkey_mprotect >= 0)
# if defined __NR_pkey_mprotect
# undef __NR_pkey_mprotect
# endif
# if defined __i386__
# define __NR_pkey_mprotect 380
# elif defined __x86_64__
# define __NR_pkey_mprotect 329
# elif defined __arm__
# define __NR_pkey_mprotect 394
# elif defined __aarch64__
# define __NR_pkey_mprotect 394
# elif defined __powerpc__
# define __NR_pkey_mprotect 386
# elif defined __s390__
# define __NR_pkey_mprotect 384
# elif defined _MIPS_SIM
# if _MIPS_SIM == _MIPS_SIM_ABI32
# define __NR_pkey_mprotect 4363
# endif
# if _MIPS_SIM == _MIPS_SIM_NABI32
# define __NR_pkey_mprotect 6327
# endif
# if _MIPS_SIM == _MIPS_SIM_ABI64
# define __NR_pkey_mprotect 5323
# endif
# else
# warning "__NR_pkey_mprotect not defined for your architecture"
# endif
# endif
#endif
/* ======================================================================= */
#if !HAVE_STATX
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_statx && __NR_statx >= 0)
# if defined __NR_statx
# undef __NR_statx
# endif
# if defined __aarch64__ || defined __arm__
# define __NR_statx 397
# elif defined __alpha__
# define __NR_statx 522
# elif defined __i386__ || defined __powerpc64__
# define __NR_statx 383
# elif defined __sparc__
# define __NR_statx 360
# elif defined __x86_64__
# define __NR_statx 332
# else
# warning "__NR_statx not defined for your architecture"
# endif
# endif
struct statx;
#endif
/* This typedef is supposed to be always defined. */
typedef struct statx struct_statx;
#if !HAVE_STATX
static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flags, unsigned int mask, struct statx *buffer) {
# ifdef __NR_statx
return syscall(__NR_statx, dfd, filename, flags, mask, buffer);
# else
errno = ENOSYS;
return -1;
# endif
}
# define statx missing_statx
#endif
#if !HAVE_SET_MEMPOLICY
enum {
MPOL_DEFAULT,
MPOL_PREFERRED,
MPOL_BIND,
MPOL_INTERLEAVE,
MPOL_LOCAL,
};
static inline long missing_set_mempolicy(int mode, const unsigned long *nodemask,
unsigned long maxnode) {
long i;
# if defined __NR_set_mempolicy && __NR_set_mempolicy >= 0
i = syscall(__NR_set_mempolicy, mode, nodemask, maxnode);
# else
errno = ENOSYS;
i = -1;
# endif
return i;
}
# define set_mempolicy missing_set_mempolicy
#endif
#if !HAVE_GET_MEMPOLICY
static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask,
unsigned long maxnode, void *addr,
unsigned long flags) {
long i;
# ifdef __NR_get_mempolicy
i = syscall(__NR_get_mempolicy, mode, nodemask, maxnode, addr, flags);
# else
errno = ENOSYS;
i = -1;
# endif
return i;
}
#define get_mempolicy missing_get_mempolicy
#endif
#endif /* NM_IGNORED */
#if !HAVE_PIDFD_OPEN
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_pidfd_open && __NR_pidfd_open >= 0)
# if defined __NR_pidfd_open
# undef __NR_pidfd_open
# endif
# define __NR_pidfd_open 434
#endif
static inline int pidfd_open(pid_t pid, unsigned flags) {
#ifdef __NR_pidfd_open
return syscall(__NR_pidfd_open, pid, flags);
#else
errno = ENOSYS;
return -1;
#endif
}
#endif
#if !HAVE_PIDFD_SEND_SIGNAL
/* may be (invalid) negative number due to libseccomp, see PR 13319 */
# if ! (defined __NR_pidfd_send_signal && __NR_pidfd_send_signal >= 0)
# if defined __NR_pidfd_send_signal
# undef __NR_pidfd_send_signal
# endif
# define __NR_pidfd_send_signal 424
#endif
static inline int pidfd_send_signal(int fd, int sig, siginfo_t *info, unsigned flags) {
#ifdef __NR_pidfd_open
return syscall(__NR_pidfd_send_signal, fd, sig, info, flags);
#else
errno = ENOSYS;
return -1;
#endif
}
#endif
#if !HAVE_RT_SIGQUEUEINFO
static inline int rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info) {
return syscall(__NR_rt_sigqueueinfo, tgid, sig, info);
}
#endif

View File

@@ -369,7 +369,6 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
unsigned long l;
assert(s);
assert(ret_u);
assert(base <= 16);
/* strtoul() is happy to parse negative values, and silently
@@ -393,7 +392,9 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
if ((unsigned long) (unsigned) l != l)
return -ERANGE;
*ret_u = (unsigned) l;
if (ret_u)
*ret_u = (unsigned) l;
return 0;
}
@@ -402,7 +403,6 @@ int safe_atoi(const char *s, int *ret_i) {
long l;
assert(s);
assert(ret_i);
errno = 0;
l = strtol(s, &x, 0);
@@ -413,7 +413,9 @@ int safe_atoi(const char *s, int *ret_i) {
if ((long) (int) l != l)
return -ERANGE;
*ret_i = (int) l;
if (ret_i)
*ret_i = (int) l;
return 0;
}
@@ -422,7 +424,6 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
unsigned long long l;
assert(s);
assert(ret_llu);
s += strspn(s, WHITESPACE);
@@ -435,7 +436,9 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
if (*s == '-')
return -ERANGE;
*ret_llu = l;
if (ret_llu)
*ret_llu = l;
return 0;
}
@@ -444,7 +447,6 @@ int safe_atolli(const char *s, long long int *ret_lli) {
long long l;
assert(s);
assert(ret_lli);
errno = 0;
l = strtoll(s, &x, 0);
@@ -453,7 +455,9 @@ int safe_atolli(const char *s, long long int *ret_lli) {
if (!x || x == s || *x != 0)
return -EINVAL;
*ret_lli = l;
if (ret_lli)
*ret_lli = l;
return 0;
}
@@ -462,7 +466,6 @@ int safe_atou8(const char *s, uint8_t *ret) {
unsigned long l;
assert(s);
assert(ret);
s += strspn(s, WHITESPACE);
@@ -477,7 +480,8 @@ int safe_atou8(const char *s, uint8_t *ret) {
if ((unsigned long) (uint8_t) l != l)
return -ERANGE;
*ret = (uint8_t) l;
if (ret)
*ret = (uint8_t) l;
return 0;
}
@@ -511,7 +515,6 @@ int safe_atoi16(const char *s, int16_t *ret) {
long l;
assert(s);
assert(ret);
errno = 0;
l = strtol(s, &x, 0);
@@ -522,7 +525,9 @@ int safe_atoi16(const char *s, int16_t *ret) {
if ((long) (int16_t) l != l)
return -ERANGE;
*ret = (int16_t) l;
if (ret)
*ret = (int16_t) l;
return 0;
}
@@ -533,7 +538,6 @@ int safe_atod(const char *s, double *ret_d) {
double d = 0;
assert(s);
assert(ret_d);
loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
if (loc == (locale_t) 0)
@@ -546,7 +550,9 @@ int safe_atod(const char *s, double *ret_d) {
if (!x || x == s || *x != 0)
return -EINVAL;
*ret_d = (double) d;
if (ret_d)
*ret_d = (double) d;
return 0;
}

View File

@@ -540,6 +540,7 @@ bool path_equal(const char *a, const char *b) {
bool path_equal_or_files_same(const char *a, const char *b, int flags) {
return path_equal(a, b) || files_same(a, b, flags) > 0;
}
#endif /* NM_IGNORED */
char* path_join_internal(const char *first, ...) {
char *joined, *q;
@@ -599,6 +600,7 @@ char* path_join_internal(const char *first, ...) {
return joined;
}
#if 0 /* NM_IGNORED */
int find_binary(const char *name, char **ret) {
int last_error, r;
const char *p;

View File

@@ -44,6 +44,7 @@
#include "rlimit-util.h"
#include "signal-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "string-table.h"
#include "string-util.h"
#include "terminal-util.h"
@@ -1347,6 +1348,12 @@ int safe_fork_full(
log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
_exit(EXIT_FAILURE);
}
} else if (flags & FORK_STDOUT_TO_STDERR) {
if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
log_full_errno(prio, errno, "Failed to connect stdout to stderr: %m");
_exit(EXIT_FAILURE);
}
}
if (flags & FORK_RLIMIT_NOFILE_SAFE) {
@@ -1498,6 +1505,38 @@ int set_oom_score_adjust(int value) {
WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
}
int pidfd_get_pid(int fd, pid_t *ret) {
char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *fdinfo = NULL;
char *p;
int r;
if (fd < 0)
return -EBADF;
xsprintf(path, "/proc/self/fdinfo/%i", fd);
r = read_full_file(path, &fdinfo, NULL);
if (r == -ENOENT) /* if fdinfo doesn't exist we assume the process does not exist */
return -ESRCH;
if (r < 0)
return r;
p = startswith(fdinfo, "Pid:");
if (!p) {
p = strstr(fdinfo, "\nPid:");
if (!p)
return -ENOTTY; /* not a pidfd? */
p += 5;
}
p += strspn(p, WHITESPACE);
p[strcspn(p, WHITESPACE)] = 0;
return parse_pid(p, ret);
}
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",

View File

@@ -149,16 +149,17 @@ void reset_cached_pid(void);
int must_be_root(void);
typedef enum ForkFlags {
FORK_RESET_SIGNALS = 1 << 0, /* Reset all signal handlers and signal mask */
FORK_CLOSE_ALL_FDS = 1 << 1, /* Close all open file descriptors in the child, except for 0,1,2 */
FORK_DEATHSIG = 1 << 2, /* Set PR_DEATHSIG in the child */
FORK_NULL_STDIO = 1 << 3, /* Connect 0,1,2 to /dev/null */
FORK_REOPEN_LOG = 1 << 4, /* Reopen log connection */
FORK_LOG = 1 << 5, /* Log above LOG_DEBUG log level about failures */
FORK_WAIT = 1 << 6, /* Wait until child exited */
FORK_NEW_MOUNTNS = 1 << 7, /* Run child in its own mount namespace */
FORK_MOUNTNS_SLAVE = 1 << 8, /* Make child's mount namespace MS_SLAVE */
FORK_RLIMIT_NOFILE_SAFE = 1 << 9, /* Set RLIMIT_NOFILE soft limit to 1K for select() compat */
FORK_RESET_SIGNALS = 1 << 0, /* Reset all signal handlers and signal mask */
FORK_CLOSE_ALL_FDS = 1 << 1, /* Close all open file descriptors in the child, except for 0,1,2 */
FORK_DEATHSIG = 1 << 2, /* Set PR_DEATHSIG in the child */
FORK_NULL_STDIO = 1 << 3, /* Connect 0,1,2 to /dev/null */
FORK_REOPEN_LOG = 1 << 4, /* Reopen log connection */
FORK_LOG = 1 << 5, /* Log above LOG_DEBUG log level about failures */
FORK_WAIT = 1 << 6, /* Wait until child exited */
FORK_NEW_MOUNTNS = 1 << 7, /* Run child in its own mount namespace */
FORK_MOUNTNS_SLAVE = 1 << 8, /* Make child's mount namespace MS_SLAVE */
FORK_RLIMIT_NOFILE_SAFE = 1 << 9, /* Set RLIMIT_NOFILE soft limit to 1K for select() compat */
FORK_STDOUT_TO_STDERR = 1 << 10, /* Make stdout a copy of stderr */
} ForkFlags;
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
@@ -199,3 +200,5 @@ assert_cc(TASKS_MAX <= (unsigned long) PID_T_MAX);
(pid) = 0; \
_pid_; \
})
int pidfd_get_pid(int fd, pid_t *ret);

View File

@@ -0,0 +1,308 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "nm-sd-adapt-shared.h"
#include <errno.h>
#include <stdarg.h>
#include "macro.h"
#include "parse-util.h"
#include "signal-util.h"
#include "stdio-util.h"
#include "string-table.h"
#include "string-util.h"
#if 0 /* NM_IGNORED */
int reset_all_signal_handlers(void) {
static const struct sigaction sa = {
.sa_handler = SIG_DFL,
.sa_flags = SA_RESTART,
};
int sig, r = 0;
for (sig = 1; sig < _NSIG; sig++) {
/* These two cannot be caught... */
if (IN_SET(sig, SIGKILL, SIGSTOP))
continue;
/* On Linux the first two RT signals are reserved by
* glibc, and sigaction() will return EINVAL for them. */
if (sigaction(sig, &sa, NULL) < 0)
if (errno != EINVAL && r >= 0)
r = -errno;
}
return r;
}
int reset_signal_mask(void) {
sigset_t ss;
if (sigemptyset(&ss) < 0)
return -errno;
if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0)
return -errno;
return 0;
}
static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) {
int r = 0;
/* negative signal ends the list. 0 signal is skipped. */
if (sig < 0)
return 0;
if (sig > 0) {
if (sigaction(sig, sa, NULL) < 0)
r = -errno;
}
while ((sig = va_arg(ap, int)) >= 0) {
if (sig == 0)
continue;
if (sigaction(sig, sa, NULL) < 0) {
if (r >= 0)
r = -errno;
}
}
return r;
}
int sigaction_many(const struct sigaction *sa, ...) {
va_list ap;
int r;
va_start(ap, sa);
r = sigaction_many_ap(sa, 0, ap);
va_end(ap);
return r;
}
int ignore_signals(int sig, ...) {
static const struct sigaction sa = {
.sa_handler = SIG_IGN,
.sa_flags = SA_RESTART,
};
va_list ap;
int r;
va_start(ap, sig);
r = sigaction_many_ap(&sa, sig, ap);
va_end(ap);
return r;
}
int default_signals(int sig, ...) {
static const struct sigaction sa = {
.sa_handler = SIG_DFL,
.sa_flags = SA_RESTART,
};
va_list ap;
int r;
va_start(ap, sig);
r = sigaction_many_ap(&sa, sig, ap);
va_end(ap);
return r;
}
static int sigset_add_many_ap(sigset_t *ss, va_list ap) {
int sig, r = 0;
assert(ss);
while ((sig = va_arg(ap, int)) >= 0) {
if (sig == 0)
continue;
if (sigaddset(ss, sig) < 0) {
if (r >= 0)
r = -errno;
}
}
return r;
}
int sigset_add_many(sigset_t *ss, ...) {
va_list ap;
int r;
va_start(ap, ss);
r = sigset_add_many_ap(ss, ap);
va_end(ap);
return r;
}
int sigprocmask_many(int how, sigset_t *old, ...) {
va_list ap;
sigset_t ss;
int r;
if (sigemptyset(&ss) < 0)
return -errno;
va_start(ap, old);
r = sigset_add_many_ap(&ss, ap);
va_end(ap);
if (r < 0)
return r;
if (sigprocmask(how, &ss, old) < 0)
return -errno;
return 0;
}
static const char *const __signal_table[] = {
[SIGHUP] = "HUP",
[SIGINT] = "INT",
[SIGQUIT] = "QUIT",
[SIGILL] = "ILL",
[SIGTRAP] = "TRAP",
[SIGABRT] = "ABRT",
[SIGBUS] = "BUS",
[SIGFPE] = "FPE",
[SIGKILL] = "KILL",
[SIGUSR1] = "USR1",
[SIGSEGV] = "SEGV",
[SIGUSR2] = "USR2",
[SIGPIPE] = "PIPE",
[SIGALRM] = "ALRM",
[SIGTERM] = "TERM",
#ifdef SIGSTKFLT
[SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */
#endif
[SIGCHLD] = "CHLD",
[SIGCONT] = "CONT",
[SIGSTOP] = "STOP",
[SIGTSTP] = "TSTP",
[SIGTTIN] = "TTIN",
[SIGTTOU] = "TTOU",
[SIGURG] = "URG",
[SIGXCPU] = "XCPU",
[SIGXFSZ] = "XFSZ",
[SIGVTALRM] = "VTALRM",
[SIGPROF] = "PROF",
[SIGWINCH] = "WINCH",
[SIGIO] = "IO",
[SIGPWR] = "PWR",
[SIGSYS] = "SYS"
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
const char *signal_to_string(int signo) {
static thread_local char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int) + 1];
const char *name;
name = __signal_to_string(signo);
if (name)
return name;
if (signo >= SIGRTMIN && signo <= SIGRTMAX)
xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN);
else
xsprintf(buf, "%d", signo);
return buf;
}
int signal_from_string(const char *s) {
const char *p;
int signo, r;
/* Check that the input is a signal number. */
if (safe_atoi(s, &signo) >= 0) {
if (SIGNAL_VALID(signo))
return signo;
else
return -ERANGE;
}
/* Drop "SIG" prefix. */
if (startswith(s, "SIG"))
s += 3;
/* Check that the input is a signal name. */
signo = __signal_from_string(s);
if (signo > 0)
return signo;
/* Check that the input is RTMIN or
* RTMIN+n (0 <= n <= SIGRTMAX-SIGRTMIN). */
p = startswith(s, "RTMIN");
if (p) {
if (*p == '\0')
return SIGRTMIN;
if (*p != '+')
return -EINVAL;
r = safe_atoi(p, &signo);
if (r < 0)
return r;
if (signo < 0 || signo > SIGRTMAX - SIGRTMIN)
return -ERANGE;
return signo + SIGRTMIN;
}
/* Check that the input is RTMAX or
* RTMAX-n (0 <= n <= SIGRTMAX-SIGRTMIN). */
p = startswith(s, "RTMAX");
if (p) {
if (*p == '\0')
return SIGRTMAX;
if (*p != '-')
return -EINVAL;
r = safe_atoi(p, &signo);
if (r < 0)
return r;
if (signo > 0 || signo < SIGRTMIN - SIGRTMAX)
return -ERANGE;
return signo + SIGRTMAX;
}
return -EINVAL;
}
void nop_signal_handler(int sig) {
/* nothing here */
}
#endif /* NM_IGNORED */
int signal_is_blocked(int sig) {
sigset_t ss;
int r;
r = pthread_sigmask(SIG_SETMASK, NULL, &ss);
if (r != 0)
return -r;
r = sigismember(&ss, sig);
if (r < 0)
return -errno;
return r;
}

View File

@@ -41,3 +41,5 @@ static inline const char* signal_to_string_with_check(int n) {
return signal_to_string(n);
}
int signal_is_blocked(int sig);

View File

@@ -31,6 +31,7 @@ int is_symlink(const char *path) {
return !!S_ISLNK(info.st_mode);
}
#endif /* NM_IGNORED */
int is_dir(const char* path, bool follow) {
struct stat st;
@@ -48,6 +49,7 @@ int is_dir(const char* path, bool follow) {
return !!S_ISDIR(st.st_mode);
}
#if 0 /* NM_IGNORED */
int is_dir_fd(int fd) {
struct stat st;

View File

@@ -1072,3 +1072,15 @@ bool string_is_safe(const char *p) {
return true;
}
#if 0 /* NM_IGNORED */
char* string_erase(char *x) {
if (!x)
return NULL;
/* A delicious drop of snake-oil! To be called on memory where we stored passphrases or so, after we
* used them. */
explicit_bzero_safe(x, strlen(x));
return x;
}
#endif /* NM_IGNORED */

View File

@@ -278,3 +278,5 @@ static inline char* str_realloc(char **p) {
return (*p = t);
}
char* string_erase(char *x);

View File

@@ -195,7 +195,10 @@ int strv_extend_strv(char ***a, char **b, bool filter_duplicates) {
p = strv_length(*a);
q = strv_length(b);
t = reallocarray(*a, p + q + 1, sizeof(char *));
if (p >= SIZE_MAX - q)
return -ENOMEM;
t = reallocarray(*a, GREEDY_ALLOC_ROUND_UP(p + q + 1), sizeof(char *));
if (!t)
return -ENOMEM;
@@ -389,19 +392,18 @@ char *strv_join_prefix(char **l, const char *separator, const char *prefix) {
int strv_push(char ***l, char *value) {
char **c;
size_t n, m;
size_t n;
if (!value)
return 0;
n = strv_length(*l);
/* Increase and check for overflow */
m = n + 2;
if (m < n)
/* Check for overflow */
if (n > SIZE_MAX-2)
return -ENOMEM;
c = reallocarray(*l, m, sizeof(char*));
c = reallocarray(*l, GREEDY_ALLOC_ROUND_UP(n + 2), sizeof(char*));
if (!c)
return -ENOMEM;
@@ -414,19 +416,19 @@ int strv_push(char ***l, char *value) {
int strv_push_pair(char ***l, char *a, char *b) {
char **c;
size_t n, m;
size_t n;
if (!a && !b)
return 0;
n = strv_length(*l);
/* increase and check for overflow */
m = n + !!a + !!b + 1;
if (m < n)
/* Check for overflow */
if (n > SIZE_MAX-3)
return -ENOMEM;
c = reallocarray(*l, m, sizeof(char*));
/* increase and check for overflow */
c = reallocarray(*l, GREEDY_ALLOC_ROUND_UP(n + !!a + !!b + 1), sizeof(char*));
if (!c)
return -ENOMEM;
@@ -856,8 +858,10 @@ int strv_extend_n(char ***l, const char *value, size_t n) {
/* Adds the value n times to l */
k = strv_length(*l);
if (n >= SIZE_MAX - k)
return -ENOMEM;
nl = reallocarray(*l, k + n + 1, sizeof(char *));
nl = reallocarray(*l, GREEDY_ALLOC_ROUND_UP(k + n + 1), sizeof(char *));
if (!nl)
return -ENOMEM;

View File

@@ -21,50 +21,60 @@
#include "tmpfile-util.h"
#include "umask-util.h"
int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
FILE *f;
char *t;
int r, fd;
int fopen_temporary(const char *path, FILE **ret_f, char **ret_temp_path) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *t = NULL;
_cleanup_close_ int fd = -1;
int r;
assert(path);
assert(_f);
assert(_temp_path);
if (path) {
r = tempfn_xxxxxx(path, NULL, &t);
if (r < 0)
return r;
} else {
const char *d;
r = tempfn_xxxxxx(path, NULL, &t);
if (r < 0)
return r;
r = tmp_dir(&d);
if (r < 0)
return r;
t = path_join(d, "XXXXXX");
if (!t)
return -ENOMEM;
}
fd = mkostemp_safe(t);
if (fd < 0) {
free(t);
if (fd < 0)
return -errno;
}
/* This assumes that returned FILE object is short-lived and used within the same single-threaded
* context and never shared externally, hence locking is not necessary. */
r = fdopen_unlocked(fd, "w", &f);
if (r < 0) {
unlink(t);
free(t);
safe_close(fd);
(void) unlink(t);
return r;
}
*_f = f;
*_temp_path = t;
TAKE_FD(fd);
if (ret_f)
*ret_f = TAKE_PTR(f);
if (ret_temp_path)
*ret_temp_path = TAKE_PTR(t);
return 0;
}
/* This is much like mkostemp() but is subject to umask(). */
int mkostemp_safe(char *pattern) {
_unused_ _cleanup_umask_ mode_t u = umask(0077);
int fd;
int fd = -1; /* avoid false maybe-uninitialized warning */
assert(pattern);
fd = mkostemp(pattern, O_CLOEXEC);
RUN_WITH_UMASK(0077)
fd = mkostemp(pattern, O_CLOEXEC);
if (fd < 0)
return -errno;