Files
systemd/src/basic/sysctl-util.h
T
Lennart Poettering 05383201c4 sysctl-util: add sysctl_read_int() and friends
Quite a few places read an integer sysctl and parse it manually, each in
its own way: some via read_one_line_file() on a hand-built /proc/sys/
path, some via sysctl_read() followed by safe_atoX(), parse_boolean() or
even a plain string comparison, and parsing into various integer types
(int, unsigned, unsigned long, uint64_t).

Add three helpers, sysctl_read_int(), sysctl_read_unsigned() and
sysctl_read_uint64(), plus a sysctl_read_uint32() alias for
sysctl_read_unsigned() for places where the value is stored in a
strictly 32-bit type (such as uid_t/gid_t), and a sysctl_read_lu()
wrapper that maps to sysctl_read_uint32() or sysctl_read_uint64(),
depending on the size of unsigned long. Then port all these users over:

  - kernel.cap_last_cap (cap_last_cap() and test-capability-util)
  - kernel.random.poolsize (random_pool_size())
  - fs.nr_open (read_nr_open())
  - kernel.pid_max and kernel.threads-max (procfs_get_pid_max(),
    procfs_get_threads_max())
  - net.unix.max_dgram_qlen (PID 1's bump_unix_max_dgram_qlen())
  - kernel.overflowuid and kernel.overflowgid (PID 1's taint logic)
  - fs.protected_hardlinks (tmpfiles)
  - kernel.apparmor_restrict_unprivileged_userns (test-execute)

Note that fs.protected_hardlinks is read as integer instead of boolean
now, since the kernel exposes it as such (even if it only accepts 0 and
1 for now). This matters even more for its siblings fs.protected_regular
and fs.protected_fifos which accept 0, 1 and 2, and hence cannot be
parsed via parse_boolean().

PID 1 keeps tainting itself if kernel.overflowuid/kernel.overflowgid
cannot be parsed, as before, but not if they cannot be read at all.

(cherry picked from commit 9ccd43072e)
(cherry picked from commit 334c06a1ba)
2026-11-05 14:48:10 +00:00

51 lines
2.5 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "basic-forward.h"
#include "stdio-util.h"
char* sysctl_normalize(char *s);
int sysctl_read(const char *property, char **ret);
int sysctl_read_int(const char *property, int *ret);
int sysctl_read_unsigned(const char *property, unsigned *ret);
#define sysctl_read_uint32(property, ret) sysctl_read_unsigned(property, ret)
int sysctl_read_uint64(const char *property, uint64_t *ret);
#if LONG_MAX == INT_MAX
static inline int sysctl_read_lu(const char *property, unsigned long *ret) {
assert_cc(sizeof(unsigned long) == sizeof(uint32_t));
return sysctl_read_uint32(property, (uint32_t*) ret);
}
#else
static inline int sysctl_read_lu(const char *property, unsigned long *ret) {
assert_cc(sizeof(unsigned long) == sizeof(uint64_t));
return sysctl_read_uint64(property, (uint64_t*) ret);
}
#endif
int sysctl_write_full(const char *property, const char *value, Hashmap **shadow);
int sysctl_writef(const char *property, const char *format, ...) _printf_(2, 3);
static inline int sysctl_write(const char *property, const char *value) {
return sysctl_write_full(property, value, NULL);
}
int sysctl_read_ip_property(int af, const char *ifname, const char *property, char **ret);
int sysctl_read_ip_property_int(int af, const char *ifname, const char *property, int *ret);
int sysctl_read_ip_property_uint32(int af, const char *ifname, const char *property, uint32_t *ret);
int sysctl_write_ip_property(int af, const char *ifname, const char *property, const char *value, Hashmap **shadow);
int sysctl_write_ip_property_boolean(int af, const char *ifname, const char *property, bool value, Hashmap **shadow);
int sysctl_write_ip_neighbor_property(int af, const char *ifname, const char *property, const char *value, Hashmap **shadow);
int sysctl_write_ip_neighbor_property_uint32(int af, const char *ifname, const char *property, uint32_t value, Hashmap **shadow);
#define DEFINE_SYSCTL_WRITE_IP_PROPERTY(name, type, format) \
static inline int sysctl_write_ip_property_##name(int af, const char *ifname, const char *property, type value, Hashmap **shadow) { \
char buf[DECIMAL_STR_MAX(type)]; \
xsprintf(buf, format, value); \
return sysctl_write_ip_property(af, ifname, property, buf, shadow); \
}
DEFINE_SYSCTL_WRITE_IP_PROPERTY(int, int, "%i");
DEFINE_SYSCTL_WRITE_IP_PROPERTY(uint32, uint32_t, "%" PRIu32);