systemd: merge branch systemd into master
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
574
shared/systemd/src/basic/missing_syscall.h
Normal file
574
shared/systemd/src/basic/missing_syscall.h
Normal 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
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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",
|
||||
|
@@ -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);
|
||||
|
308
shared/systemd/src/basic/signal-util.c
Normal file
308
shared/systemd/src/basic/signal-util.c
Normal 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;
|
||||
}
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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 */
|
||||
|
@@ -278,3 +278,5 @@ static inline char* str_realloc(char **p) {
|
||||
|
||||
return (*p = t);
|
||||
}
|
||||
|
||||
char* string_erase(char *x);
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user