diff options
30 files changed, 488 insertions, 265 deletions
@@ -24,6 +24,15 @@ External: Features: +* sd_notify("SHUTDOWN=1") to fix a dbus activation race. + http://lists.freedesktop.org/archives/systemd-devel/2014-July/020983.html + +* merge ~/.local/share and ~/.local/lib into one similar /usr/lib and /usr/share.... + +* make "systemctl suspend" block until we are back from suspend + +* remove readahead in 217 + * journald: allows specification of UID range for splitting up journal files * systemd.show_status= should probably have a mode where only failed diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 290aa6efe5..024509968a 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -301,7 +301,18 @@ This option may be specified more than once.</para> </listitem> </varlistentry> -<!-- TODO: document NTP= option when it is actually used somewhere --> + <varlistentry> + <term><varname>Domains=</varname></term> + <listitem> + <para>The domains used for DNS resolution over this link.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><varname>NTP=</varname></term> + <listitem> + <para>An NTP server address. This option may be specified more than once.</para> + </listitem> + </varlistentry> <varlistentry> <term><varname>Bridge=</varname></term> <listitem> diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 42bf09f038..9248cb523b 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -199,7 +199,8 @@ static int whitelist_device(const char *path, const char *node, const char *acc) acc); r = cg_set_attribute("devices", path, "devices.allow", buf); - log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r)); + if (r < 0) + log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r)); return r; } @@ -270,7 +271,8 @@ static int whitelist_major(const char *path, const char *name, char type, const acc); r = cg_set_attribute("devices", path, "devices.allow", buf); - log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r)); + if (r < 0) + log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set devices.allow on %s: %s", path, strerror(-r)); } return 0; @@ -301,18 +303,21 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha state == MANAGER_STARTING && c->startup_cpu_shares != (unsigned long) -1 ? c->startup_cpu_shares : c->cpu_shares != (unsigned long) -1 ? c->cpu_shares : 1024); r = cg_set_attribute("cpu", path, "cpu.shares", buf); - log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.shares on %s: %s", path, strerror(-r)); + if (r < 0) + log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.shares on %s: %s", path, strerror(-r)); sprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC); r = cg_set_attribute("cpu", path, "cpu.cfs_period_us", buf); - log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_period_us on %s: %s", path, strerror(-r)); + if (r < 0) + log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_period_us on %s: %s", path, strerror(-r)); if (c->cpu_quota_per_sec_usec != USEC_INFINITY) { sprintf(buf, USEC_FMT "\n", c->cpu_quota_per_sec_usec * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC); r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", buf); } else r = cg_set_attribute("cpu", path, "cpu.cfs_quota_us", "-1"); - log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_quota_us on %s: %s", path, strerror(-r)); + if (r < 0) + log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set cpu.cfs_quota_us on %s: %s", path, strerror(-r)); } if (mask & CGROUP_BLKIO) { @@ -326,7 +331,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha sprintf(buf, "%lu\n", state == MANAGER_STARTING && c->startup_blockio_weight != (unsigned long) -1 ? c->startup_blockio_weight : c->blockio_weight != (unsigned long) -1 ? c->blockio_weight : 1000); r = cg_set_attribute("blkio", path, "blkio.weight", buf); - log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight on %s: %s", path, strerror(-r)); + if (r < 0) + log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight on %s: %s", path, strerror(-r)); /* FIXME: no way to reset this list */ LIST_FOREACH(device_weights, w, c->blockio_device_weights) { @@ -338,7 +344,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha sprintf(buf, "%u:%u %lu", major(dev), minor(dev), w->weight); r = cg_set_attribute("blkio", path, "blkio.weight_device", buf); - log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight_device on %s: %s", path, strerror(-r)); + if (r < 0) + log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set blkio.weight_device on %s: %s", path, strerror(-r)); } } @@ -355,7 +362,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), b->bandwidth); r = cg_set_attribute("blkio", path, a, buf); - log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set %s on %s: %s", a, path, strerror(-r)); + if (r < 0) + log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set %s on %s: %s", a, path, strerror(-r)); } } @@ -368,7 +376,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha } else r = cg_set_attribute("memory", path, "memory.limit_in_bytes", "-1"); - log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r)); + if (r < 0) + log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to set memory.limit_in_bytes on %s: %s", path, strerror(-r)); } if ((mask & CGROUP_DEVICE) && !is_root) { @@ -378,7 +387,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha r = cg_set_attribute("devices", path, "devices.deny", "a"); else r = cg_set_attribute("devices", path, "devices.allow", "a"); - log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to reset devices.list on %s: %s", path, strerror(-r)); + if (r < 0) + log_full(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, "Failed to reset devices.list on %s: %s", path, strerror(-r)); if (c->device_policy == CGROUP_CLOSED || (c->device_policy == CGROUP_AUTO && c->device_allow)) { diff --git a/src/core/main.c b/src/core/main.c index f33b78d375..792b316c61 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -228,31 +228,25 @@ static void install_crash_handler(void) { sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1); } -static int console_setup(bool do_reset) { - int tty_fd, r; - - /* If we are init, we connect stdin/stdout/stderr to /dev/null - * and make sure we don't have a controlling tty. */ - - release_terminal(); - - if (!do_reset) - return 0; +static int console_setup(void) { + _cleanup_close_ int tty_fd = -1; + int r; tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); if (tty_fd < 0) { log_error("Failed to open /dev/console: %s", strerror(-tty_fd)); - return -tty_fd; + return tty_fd; } - /* We don't want to force text mode. - * plymouth may be showing pictures already from initrd. */ + /* We don't want to force text mode. plymouth may be showing + * pictures already from initrd. */ r = reset_terminal_fd(tty_fd, false); - if (r < 0) + if (r < 0) { log_error("Failed to reset /dev/console: %s", strerror(-r)); + return r; + } - safe_close(tty_fd); - return r; + return 0; } static int set_default_unit(const char *u) { @@ -299,26 +293,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { if (in_initrd()) return set_default_unit(value); - } else if (streq(key, "systemd.log_target") && value) { - - if (log_set_target_from_string(value) < 0) - log_warning("Failed to parse log target %s. Ignoring.", value); - - } else if (streq(key, "systemd.log_level") && value) { - - if (log_set_max_level_from_string(value) < 0) - log_warning("Failed to parse log level %s. Ignoring.", value); - - } else if (streq(key, "systemd.log_color") && value) { - - if (log_show_color_from_string(value) < 0) - log_warning("Failed to parse log color setting %s. Ignoring.", value); - - } else if (streq(key, "systemd.log_location") && value) { - - if (log_show_location_from_string(value) < 0) - log_warning("Failed to parse log location setting %s. Ignoring.", value); - } else if (streq(key, "systemd.dump_core") && value) { r = parse_boolean(value); @@ -394,7 +368,8 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { } else if (streq(key, "debug") && !value) { - log_set_max_level(LOG_DEBUG); + /* Note that log_parse_environment() handles 'debug' + * too, and sets the log level to LOG_DEBUG. */ if (detect_container(NULL) > 0) log_set_target(LOG_TARGET_CONSOLE); @@ -969,37 +944,6 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } - if (detect_container(NULL) > 0) { - char **a; - - /* All /proc/cmdline arguments the kernel didn't - * understand it passed to us. We're not really - * interested in that usually since /proc/cmdline is - * more interesting and complete. With one exception: - * if we are run in a container /proc/cmdline is not - * relevant for the container, hence we rely on argv[] - * instead. */ - - for (a = argv; a < argv + argc; a++) { - _cleanup_free_ char *w; - char *value; - - w = strdup(*a); - if (!w) - return log_oom(); - - value = strchr(w, '='); - if (value) - *(value++) = 0; - - r = parse_proc_cmdline_item(w, value); - if (r < 0) { - log_error("Failed on cmdline argument %s: %s", *a, strerror(-r)); - return r; - } - } - } - return 0; } @@ -1461,6 +1405,8 @@ int main(int argc, char *argv[]) { if (parse_proc_cmdline(parse_proc_cmdline_item) < 0) goto finish; + /* Note that this also parses bits from the kernel command + * line, including "debug". */ log_parse_environment(); if (parse_argv(argc, argv) < 0) @@ -1537,8 +1483,16 @@ int main(int argc, char *argv[]) { /* Reset the console, but only if this is really init and we * are freshly booted */ - if (arg_running_as == SYSTEMD_SYSTEM && arg_action == ACTION_RUN) - console_setup(getpid() == 1 && !skip_setup); + if (arg_running_as == SYSTEMD_SYSTEM && arg_action == ACTION_RUN) { + + /* If we are init, we connect stdin/stdout/stderr to + * /dev/null and make sure we don't have a controlling + * tty. */ + release_terminal(); + + if (getpid() == 1 && !skip_setup) + console_setup(); + } /* Open the logging devices, if possible and necessary */ log_open(); diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index f8e1a811f8..e48736920f 100644 --- a/src/hostname/hostnamectl.c +++ b/src/hostname/hostnamectl.c @@ -68,6 +68,7 @@ typedef struct StatusInfo { char *icon_name; char *chassis; char *deployment; + char *location; char *kernel_name; char *kernel_release; char *os_pretty_name; @@ -92,12 +93,19 @@ static void print_status_info(StatusInfo *i) { !streq_ptr(i->hostname, i->static_hostname)) printf("Transient hostname: %s\n", i->hostname); - printf(" Icon name: %s\n" - " Chassis: %s\n" - " Deployment: %s\n", - strna(i->icon_name), - strna(i->chassis), - strna(i->deployment)); + if (!isempty(i->icon_name)) + printf(" Icon name: %s\n", + strna(i->icon_name)); + + if (!isempty(i->chassis)) + printf(" Chassis: %s\n", + strna(i->chassis)); + + if (!isempty(i->deployment)) + printf(" Deployment: %s\n", i->deployment); + + if (!isempty(i->location)) + printf(" Location: %s\n", i->location); r = sd_id128_get_machine(&mid); if (r >= 0) @@ -155,22 +163,23 @@ static int show_all_names(sd_bus *bus) { StatusInfo info = {}; static const struct bus_properties_map hostname_map[] = { - { "Hostname", "s", NULL, offsetof(StatusInfo, hostname) }, - { "StaticHostname", "s", NULL, offsetof(StatusInfo, static_hostname) }, - { "PrettyHostname", "s", NULL, offsetof(StatusInfo, pretty_hostname) }, - { "IconName", "s", NULL, offsetof(StatusInfo, icon_name) }, - { "Chassis", "s", NULL, offsetof(StatusInfo, chassis) }, - { "Deployment", "s", NULL, offsetof(StatusInfo, deployment) }, - { "KernelName", "s", NULL, offsetof(StatusInfo, kernel_name) }, - { "KernelRelease", "s", NULL, offsetof(StatusInfo, kernel_release) }, - { "OperatingSystemPrettyName", "s", NULL, offsetof(StatusInfo, os_pretty_name) }, - { "OperatingSystemCPEName", "s", NULL, offsetof(StatusInfo, os_cpe_name) }, + { "Hostname", "s", NULL, offsetof(StatusInfo, hostname) }, + { "StaticHostname", "s", NULL, offsetof(StatusInfo, static_hostname) }, + { "PrettyHostname", "s", NULL, offsetof(StatusInfo, pretty_hostname) }, + { "IconName", "s", NULL, offsetof(StatusInfo, icon_name) }, + { "Chassis", "s", NULL, offsetof(StatusInfo, chassis) }, + { "Deployment", "s", NULL, offsetof(StatusInfo, deployment) }, + { "Location", "s", NULL, offsetof(StatusInfo, location) }, + { "KernelName", "s", NULL, offsetof(StatusInfo, kernel_name) }, + { "KernelRelease", "s", NULL, offsetof(StatusInfo, kernel_release) }, + { "OperatingSystemPrettyName", "s", NULL, offsetof(StatusInfo, os_pretty_name) }, + { "OperatingSystemCPEName", "s", NULL, offsetof(StatusInfo, os_cpe_name) }, {} }; static const struct bus_properties_map manager_map[] = { - { "Virtualization", "s", NULL, offsetof(StatusInfo, virtualization) }, - { "Architecture", "s", NULL, offsetof(StatusInfo, architecture) }, + { "Virtualization", "s", NULL, offsetof(StatusInfo, virtualization) }, + { "Architecture", "s", NULL, offsetof(StatusInfo, architecture) }, {} }; @@ -199,6 +208,7 @@ fail: free(info.icon_name); free(info.chassis); free(info.deployment); + free(info.location); free(info.kernel_name); free(info.kernel_release); free(info.os_pretty_name); @@ -321,6 +331,13 @@ static int set_deployment(sd_bus *bus, char **args, unsigned n) { return set_simple_string(bus, "SetDeployment", args[1]); } +static int set_location(sd_bus *bus, char **args, unsigned n) { + assert(args); + assert(n == 2); + + return set_simple_string(bus, "SetLocation", args[1]); +} + static void help(void) { printf("%s [OPTIONS...] COMMAND ...\n\n" "Query or change system hostname.\n\n" @@ -338,6 +355,7 @@ static void help(void) { " set-icon-name NAME Set icon name for host\n" " set-chassis NAME Set chassis type for host\n" " set-deployment NAME Set deployment environment for host\n" + " set-location NAME Set location for host\n" , program_invocation_short_name); } @@ -429,11 +447,12 @@ static int hostnamectl_main(sd_bus *bus, int argc, char *argv[]) { const int argc; int (* const dispatch)(sd_bus *bus, char **args, unsigned n); } verbs[] = { - { "status", LESS, 1, show_status }, - { "set-hostname", EQUAL, 2, set_hostname }, - { "set-icon-name", EQUAL, 2, set_icon_name }, - { "set-chassis", EQUAL, 2, set_chassis }, - { "set-deployment", EQUAL, 2, set_deployment }, + { "status", LESS, 1, show_status }, + { "set-hostname", EQUAL, 2, set_hostname }, + { "set-icon-name", EQUAL, 2, set_icon_name }, + { "set-chassis", EQUAL, 2, set_chassis }, + { "set-deployment", EQUAL, 2, set_deployment }, + { "set-location", EQUAL, 2, set_location }, }; int left; diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index a6f440f4e1..c7f738a62c 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -23,6 +23,7 @@ #include <string.h> #include <unistd.h> #include <sys/utsname.h> +#include <sys/capability.h> #include "util.h" #include "strv.h" @@ -425,7 +426,7 @@ static int method_set_hostname(sd_bus *bus, sd_bus_message *m, void *userdata, s if (streq_ptr(name, c->data[PROP_HOSTNAME])) return sd_bus_reply_method_return(m, NULL); - r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.hostname1.set-hostname", interactive, error, method_set_hostname, c); + r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN, "org.freedesktop.hostname1.set-hostname", interactive, error, method_set_hostname, c); if (r < 0) return r; if (r == 0) @@ -467,7 +468,7 @@ static int method_set_static_hostname(sd_bus *bus, sd_bus_message *m, void *user if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME])) return sd_bus_reply_method_return(m, NULL); - r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.hostname1.set-static-hostname", interactive, error, method_set_static_hostname, c); + r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN, "org.freedesktop.hostname1.set-static-hostname", interactive, error, method_set_static_hostname, c); if (r < 0) return r; if (r == 0) @@ -532,9 +533,10 @@ static int set_machine_info(Context *c, sd_bus *bus, sd_bus_message *m, int prop * same time as the static one, use the same policy action for * both... */ - r = bus_verify_polkit_async(bus, &c->polkit_registry, m, prop == PROP_PRETTY_HOSTNAME ? - "org.freedesktop.hostname1.set-static-hostname" : - "org.freedesktop.hostname1.set-machine-info", interactive, error, cb, c); + r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN, + prop == PROP_PRETTY_HOSTNAME ? + "org.freedesktop.hostname1.set-static-hostname" : + "org.freedesktop.hostname1.set-machine-info", interactive, error, cb, c); if (r < 0) return r; if (r == 0) diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install index c17b8a98d5..6f032b5a4b 100644 --- a/src/kernel-install/90-loaderentry.install +++ b/src/kernel-install/90-loaderentry.install @@ -47,11 +47,10 @@ if [[ -f /etc/kernel/cmdline ]]; then fi if ! [[ ${BOOT_OPTIONS[*]} ]]; then - readarray -t line < /proc/cmdline - for i in ${line[*]}; do - if [[ "${i#initrd=*}" == "$i" ]]; then - BOOT_OPTIONS[${#BOOT_OPTIONS[@]}]="$i" - fi + read -ar line < /proc/cmdline + for i in "${line[@]}"; do + [[ "${i#initrd=*}" != "$i" ]] && continue + BOOT_OPTIONS[${#BOOT_OPTIONS[@]}]="$i" done fi diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c index c5b9cd4caa..f88836b884 100644 --- a/src/libsystemd/sd-bus/bus-convenience.c +++ b/src/libsystemd/sd-bus/bus-convenience.c @@ -472,3 +472,56 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b return bus_creds_extend_by_pid(c, mask, creds); } + +_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) { + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + uid_t our_uid; + int r; + + assert_return(call, -EINVAL); + assert_return(call->sealed, -EPERM); + assert_return(call->bus, -EINVAL); + assert_return(!bus_pid_changed(call->bus), -ECHILD); + + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + + /* We only trust the effective capability set if this is + * kdbus. On classic dbus1 we cannot retrieve the value + * without races. Since this function is supposed to be useful + * for authentication decision we hence avoid requesting and + * using that information. */ + if (call->bus->is_kernel && capability >= 0) { + r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_has_effective_cap(creds, capability); + if (r > 0) + return 1; + } else { + r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID, &creds); + if (r < 0) + return r; + } + + /* Now, check the UID, but only if the capability check wasn't + * sufficient */ + our_uid = getuid(); + if (our_uid != 0 || !call->bus->is_kernel || capability < 0) { + uid_t sender_uid; + + r = sd_bus_creds_get_uid(creds, &sender_uid); + if (r >= 0) { + /* Sender has same UID as us, then let's grant access */ + if (sender_uid == our_uid) + return 1; + + /* Sender is root, we are not root. */ + if (our_uid != 0 && sender_uid == 0) + return 1; + } + } + + return 0; +} diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c index dbb04e5ec6..78dab8048d 100644 --- a/src/libsystemd/sd-bus/bus-objects.c +++ b/src/libsystemd/sd-bus/bus-objects.c @@ -289,7 +289,6 @@ static int node_callbacks_run( static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) { _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; uint64_t cap; - uid_t uid; int r; assert(bus); @@ -304,17 +303,6 @@ static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, if (c->vtable->flags & SD_BUS_VTABLE_UNPRIVILEGED) return 0; - /* If we are not connected to kdbus we cannot retrieve the - * effective capability set without race. Since we need this - * for a security decision we cannot use racy data, hence - * don't request it. */ - if (bus->is_kernel) - r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds); - else - r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds); - if (r < 0) - return r; - /* Check have the caller has the requested capability * set. Note that the flags value contains the capability * number plus one, which we need to subtract here. We do this @@ -328,16 +316,11 @@ static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, else cap --; - r = sd_bus_creds_has_effective_cap(creds, cap); + r = sd_bus_query_sender_privilege(m, cap); + if (r < 0) + return r; if (r > 0) - return 1; - - /* Caller has same UID as us, then let's grant access */ - r = sd_bus_creds_get_uid(creds, &uid); - if (r >= 0) { - if (uid == getuid()) - return 1; - } + return 0; return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access to %s.%s() not permitted.", c->interface, c->member); } diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c index 37f5c4620c..65f1d17c9f 100644 --- a/src/libsystemd/sd-bus/bus-util.c +++ b/src/libsystemd/sd-bus/bus-util.c @@ -186,28 +186,22 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) { int bus_verify_polkit( sd_bus *bus, sd_bus_message *m, + int capability, const char *action, bool interactive, bool *_challenge, sd_bus_error *e) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; - uid_t uid; int r; assert(bus); assert(m); assert(action); - r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds); + r = sd_bus_query_sender_privilege(m, capability); if (r < 0) return r; - - r = sd_bus_creds_get_uid(creds, &uid); - if (r < 0) - return r; - - if (uid == 0) + if (r > 0) return 1; #ifdef ENABLE_POLKIT @@ -325,6 +319,7 @@ int bus_verify_polkit_async( sd_bus *bus, Hashmap **registry, sd_bus_message *m, + int capability, const char *action, bool interactive, sd_bus_error *error, @@ -336,8 +331,6 @@ int bus_verify_polkit_async( AsyncPolkitQuery *q; const char *sender; #endif - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; - uid_t uid; int r; assert(bus); @@ -383,15 +376,10 @@ int bus_verify_polkit_async( } #endif - r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds); + r = sd_bus_query_sender_privilege(m, capability); if (r < 0) return r; - - r = sd_bus_creds_get_uid(creds, &uid); - if (r < 0) - return r; - - if (uid == 0) + if (r > 0) return 1; #ifdef ENABLE_POLKIT diff --git a/src/libsystemd/sd-bus/bus-util.h b/src/libsystemd/sd-bus/bus-util.h index b3b52af24c..1ac46875b2 100644 --- a/src/libsystemd/sd-bus/bus-util.h +++ b/src/libsystemd/sd-bus/bus-util.h @@ -62,9 +62,9 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error); int bus_check_peercred(sd_bus *c); -int bus_verify_polkit(sd_bus *bus, sd_bus_message *m, const char *action, bool interactive, bool *_challenge, sd_bus_error *e); +int bus_verify_polkit(sd_bus *bus, sd_bus_message *m, int capability, const char *action, bool interactive, bool *_challenge, sd_bus_error *e); -int bus_verify_polkit_async(sd_bus *bus, Hashmap **registry, sd_bus_message *m, const char *action, bool interactive, sd_bus_error *error, sd_bus_message_handler_t callback, void *userdata); +int bus_verify_polkit_async(sd_bus *bus, Hashmap **registry, sd_bus_message *m, int capability, const char *action, bool interactive, sd_bus_error *error, sd_bus_message_handler_t callback, void *userdata); void bus_verify_polkit_async_registry_free(Hashmap *registry); int bus_open_system_systemd(sd_bus **_bus); diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index 4d8b7e7b2c..3a3f53576f 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -92,6 +92,10 @@ _public_ int sd_network_get_ntp(char ***ret) { return network_get_strv("NTP", ret); } +_public_ int sd_network_get_domains(char ***ret) { + return network_get_strv("DOMAINS", ret); +} + _public_ int sd_network_link_get_setup_state(int ifindex, char **state) { _cleanup_free_ char *s = NULL, *p = NULL; int r; @@ -210,6 +214,26 @@ _public_ int sd_network_link_get_domains(int ifindex, char ***ret) { return network_get_link_strv("DOMAINS", ifindex, ret); } +_public_ int sd_network_link_get_wildcard_domain(int ifindex) { + int r; + _cleanup_free_ char *p = NULL, *s = NULL; + + assert_return(ifindex > 0, -EINVAL); + + if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0) + return -ENOMEM; + + r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + if (isempty(s)) + return -ENODATA; + + return parse_boolean(s); +} + static inline int MONITOR_TO_FD(sd_network_monitor *m) { return (int) (unsigned long) m - 1; } diff --git a/src/locale/localed.c b/src/locale/localed.c index 4d7d02b9a3..5c0bc2c84e 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -23,6 +23,7 @@ #include <errno.h> #include <string.h> #include <unistd.h> +#include <sys/capability.h> #include "sd-bus.h" @@ -876,7 +877,7 @@ static int method_set_locale(sd_bus *bus, sd_bus_message *m, void *userdata, sd_ } if (modified) { - r = bus_verify_polkit_async(bus, &c->polkit_registry, m, + r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-locale", interactive, error, method_set_locale, c); if (r < 0) @@ -954,7 +955,7 @@ static int method_set_vc_keyboard(sd_bus *bus, sd_bus_message *m, void *userdata (keymap_toggle && (!filename_is_safe(keymap_toggle) || !string_is_safe(keymap_toggle)))) return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keymap data"); - r = bus_verify_polkit_async(bus, &c->polkit_registry, m, + r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-keyboard", interactive, error, method_set_vc_keyboard, c); if (r < 0) @@ -1026,7 +1027,7 @@ static int method_set_x11_keyboard(sd_bus *bus, sd_bus_message *m, void *userdat (options && !string_is_safe(options))) return sd_bus_error_set_errnof(error, -EINVAL, "Received invalid keyboard data"); - r = bus_verify_polkit_async(bus, &c->polkit_registry, m, + r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_ADMIN, "org.freedesktop.locale1.set-keyboard", interactive, error, method_set_x11_keyboard, c); if (r < 0) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 1a363c2c59..bcfcba2d07 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1032,6 +1032,7 @@ static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *us r = bus_verify_polkit_async(bus, &m->polkit_registry, message, + CAP_SYS_ADMIN, "org.freedesktop.login1.set-user-linger", interactive, error, @@ -1204,6 +1205,7 @@ static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *user r = bus_verify_polkit_async(bus, &m->polkit_registry, message, + CAP_SYS_ADMIN, "org.freedesktop.login1.attach-device", interactive, error, @@ -1235,6 +1237,7 @@ static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *user r = bus_verify_polkit_async(bus, &m->polkit_registry, message, + CAP_SYS_ADMIN, "org.freedesktop.login1.flush-devices", interactive, error, @@ -1532,7 +1535,7 @@ static int method_do_shutdown_or_sleep( blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL); if (multiple_sessions) { - r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, + r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, CAP_SYS_BOOT, action_multiple_sessions, interactive, error, method, m); if (r < 0) return r; @@ -1541,7 +1544,7 @@ static int method_do_shutdown_or_sleep( } if (blocked) { - r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, + r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, error, method, m); if (r < 0) return r; @@ -1550,7 +1553,7 @@ static int method_do_shutdown_or_sleep( } if (!multiple_sessions && !blocked) { - r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, + r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, CAP_SYS_BOOT, action, interactive, error, method, m); if (r < 0) return r; @@ -1688,7 +1691,7 @@ static int method_can_shutdown_or_sleep( blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL); if (multiple_sessions) { - r = bus_verify_polkit(m->bus, message, action_multiple_sessions, false, &challenge, error); + r = bus_verify_polkit(m->bus, message, CAP_SYS_BOOT, action_multiple_sessions, false, &challenge, error); if (r < 0) return r; @@ -1701,7 +1704,7 @@ static int method_can_shutdown_or_sleep( } if (blocked) { - r = bus_verify_polkit(m->bus, message, action_ignore_inhibit, false, &challenge, error); + r = bus_verify_polkit(m->bus, message, CAP_SYS_BOOT, action_ignore_inhibit, false, &challenge, error); if (r < 0) return r; @@ -1717,7 +1720,7 @@ static int method_can_shutdown_or_sleep( /* If neither inhibit nor multiple sessions * apply then just check the normal policy */ - r = bus_verify_polkit(m->bus, message, action, false, &challenge, error); + r = bus_verify_polkit(m->bus, message, CAP_SYS_BOOT, action, false, &challenge, error); if (r < 0) return r; @@ -1837,7 +1840,7 @@ static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, if (m->action_what & w) return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running"); - r = bus_verify_polkit_async(bus, &m->polkit_registry, message, + r = bus_verify_polkit_async(bus, &m->polkit_registry, message, CAP_SYS_BOOT, w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") : w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") : w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" : diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 33fe8bfc61..6253cbf582 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -366,6 +366,17 @@ static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) { sd_network_link_get_dns(ifindex, &dns); sd_network_link_get_ntp(ifindex, &ntp); sd_network_link_get_domains(ifindex, &domains); + r = sd_network_link_get_wildcard_domain(ifindex); + if (r > 0) { + char *wildcard; + + wildcard = strdup("*"); + if (!wildcard) + return log_oom(); + + if (strv_consume(&domains, wildcard) < 0) + return log_oom(); + } sprintf(devid, "n%i", ifindex); d = udev_device_new_from_device_id(udev, devid); @@ -416,7 +427,7 @@ static int link_status_one(sd_rtnl *rtnl, struct udev *udev, const char *name) { if (!strv_isempty(dns)) dump_list(" DNS: ", dns); if (!strv_isempty(domains)) - dump_list(" Domains: ", domains); + dump_list(" Domain: ", domains); if (!strv_isempty(ntp)) dump_list(" NTP: ", ntp); @@ -443,7 +454,7 @@ static int link_status(char **args, unsigned n) { if (n <= 1 && !arg_all) { _cleanup_free_ char *operational_state = NULL; - _cleanup_strv_free_ char **dns = NULL, **ntp = NULL; + _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL; _cleanup_free_ struct local_address *addresses = NULL; const char *on_color_operational, *off_color_operational; int i, c; @@ -469,6 +480,10 @@ static int link_status(char **args, unsigned n) { if (!strv_isempty(dns)) dump_list(" DNS: ", dns); + sd_network_get_domains(&domains); + if (!strv_isempty(domains)) + dump_list(" Domain: ", domains); + sd_network_get_dns(&ntp); if (!strv_isempty(ntp)) dump_list(" NTP: ", ntp); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 9eb2e89091..a37561a04a 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1722,9 +1722,14 @@ int link_save(Link *link) { if (link->network) { char **address; + char **domain; fputs("DNS=", f); + STRV_FOREACH(address, link->network->dns) + fprintf(f, "%s%s", *address, + (address + 1 ? " " : "")); + if (link->network->dhcp_dns && link->dhcp_lease) { const struct in_addr *addresses; @@ -1737,14 +1742,14 @@ int link_save(Link *link) { } } - STRV_FOREACH(address, link->network->dns) - fprintf(f, "%s%s", *address, - (address + 1 ? " " : "")); - fputs("\n", f); fprintf(f, "NTP="); + STRV_FOREACH(address, link->network->ntp) + fprintf(f, "%s%s", *address, + (address + 1 ? " " : "")); + if (link->network->dhcp_ntp && link->dhcp_lease) { const struct in_addr *addresses; @@ -1757,21 +1762,31 @@ int link_save(Link *link) { } } - STRV_FOREACH(address, link->network->ntp) - fprintf(f, "%s%s", *address, - (address + 1 ? " " : "")); - fputs("\n", f); + fprintf(f, "DOMAINS="); + + STRV_FOREACH(domain, link->network->domains) + fprintf(f, "%s%s", *domain, + (domain + 1 ? " " : "")); + if (link->network->dhcp_domains && link->dhcp_lease) { const char *domainname; r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); - if (r >= 0) - fprintf(f, "DOMAINS=%s\n", domainname); + if (r >= 0) { + fputs(domainname, f); + if (link->network->domains) + fputs(" ", f); + } } + fputs("\n", f); + + fprintf(f, "WILDCARD_DOMAIN=%s\n", + yes_no(link->network->wildcard_domain)); + fprintf(f, "LLMNR=%s\n", llmnr_support_to_string(link->network->llmnr)); } diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index e3d72edece..f2fe5d5443 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -450,8 +450,27 @@ static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) { return c; } +static void print_string_set(FILE *f, const char *field, Set *s) { + bool space = false; + Iterator i; + char *p; + + if (set_isempty(s)) + return; + + fputs(field, f); + + SET_FOREACH(p, s, i) { + if (space) + fputc(' ', f); + fputs(p, f); + space = true; + } + fputc('\n', f); +} + int manager_save(Manager *m) { - _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL; + _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *domains = NULL; Link *link; Iterator i; _cleanup_free_ char *temp_path = NULL; @@ -472,6 +491,10 @@ int manager_save(Manager *m) { if (!ntp) return -ENOMEM; + domains = set_new(string_hash_func, string_compare_func); + if (!domains) + return -ENOMEM; + HASHMAP_FOREACH(link, m->links, i) { if (link->flags & IFF_LOOPBACK) continue; @@ -491,6 +514,10 @@ int manager_save(Manager *m) { if (r < 0) return r; + r = set_put_strdupv(domains, link->network->domains); + if (r < 0) + return r; + if (!link->dhcp_lease) continue; @@ -503,7 +530,7 @@ int manager_save(Manager *m) { r = set_put_in_addrv(dns, addresses, r); if (r < 0) return r; - } else if (r != -ENOENT) + } else if (r < 0 && r != -ENOENT) return r; } @@ -515,6 +542,18 @@ int manager_save(Manager *m) { r = set_put_in_addrv(ntp, addresses, r); if (r < 0) return r; + } else if (r < 0 && r != -ENOENT) + return r; + } + + if (link->network->dhcp_domains) { + const char *domainname; + + r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); + if (r >= 0) { + r = set_put_strdup(domains, domainname); + if (r < 0) + return r; } else if (r != -ENOENT) return r; } @@ -533,33 +572,9 @@ int manager_save(Manager *m) { "# This is private data. Do not parse.\n" "OPER_STATE=%s\n", operstate_str); - if (!set_isempty(dns)) { - bool space = false; - char *p; - - fputs("DNS=", f); - SET_FOREACH(p, dns, i) { - if (space) - fputc(' ', f); - fputs(p, f); - space = true; - } - fputc('\n', f); - } - - if (!set_isempty(ntp)) { - bool space = false; - char *p; - - fputs("NTP=", f); - SET_FOREACH(p, ntp, i) { - if (space) - fputc(' ', f); - fputs(p, f); - space = true; - } - fputc('\n', f); - } + print_string_set(f, "DNS=", dns); + print_string_set(f, "NTP=", ntp); + print_string_set(f, "DOMAINS=", domains); r = fflush_and_check(f); if (r < 0) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 9cd7a4aa61..c5b9614a2b 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -37,6 +37,7 @@ Network.IPv4LL, config_parse_bool, 0, Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route) Network.Address, config_parse_address, 0, 0 Network.Gateway, config_parse_gateway, 0, 0 +Network.Domains, config_parse_domains, 0, offsetof(Network, domains) Network.DNS, config_parse_strv, 0, offsetof(Network, dns) Network.LLMNR, config_parse_llmnr, 0, offsetof(Network, llmnr) Network.NTP, config_parse_strv, 0, offsetof(Network, ntp) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index e13e4a0f62..803fcdd609 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -166,6 +166,7 @@ void network_free(Network *network) { strv_free(network->ntp); strv_free(network->dns); + strv_free(network->domains); netdev_unref(network->bridge); @@ -341,6 +342,47 @@ int config_parse_netdev(const char *unit, return 0; } +int config_parse_domains(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = userdata; + char ***domains = data; + char **domain; + int r; + + r = config_parse_strv(unit, filename, line, section, section_line, + lvalue, ltype, rvalue, domains, userdata); + if (r < 0) + return r; + + strv_uniq(*domains); + network->wildcard_domain = !!strv_find(*domains, "*"); + + STRV_FOREACH(domain, *domains) { + if (is_localhost(*domain)) + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain); + else if (!hostname_is_valid(*domain)) { + if (!streq(*domain, "*")) + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "domain name is not valid, ignoring assignment: %s", *domain); + } else + continue; + + strv_remove(*domains, *domain); + + /* We removed one entry, make sure we don't skip the next one */ + domain--; + } + + return 0; +} + int config_parse_tunnel(const char *unit, const char *filename, unsigned line, diff --git a/src/network/networkd.h b/src/network/networkd.h index 90e798dbf5..c8d89d212b 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -111,7 +111,8 @@ struct Network { Hashmap *addresses_by_section; Hashmap *routes_by_section; - char **dns, **ntp; + bool wildcard_domain; + char **domains, **dns, **ntp; LLMNRSupport llmnr; @@ -224,6 +225,17 @@ int config_parse_netdev(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_domains(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata); + int config_parse_tunnel(const char *unit, const char *filename, unsigned line, diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 85709a4af8..039a754ff0 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -366,7 +366,10 @@ int dns_scope_llmnr_membership(DnsScope *s, bool b) { int fd; assert(s); - assert(s->protocol == DNS_PROTOCOL_LLMNR); + + if (s->protocol != DNS_PROTOCOL_LLMNR) + return 0; + assert(s->link); if (s->family == AF_INET) { diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c index eb78587ae6..8b3a3ced4b 100644 --- a/src/resolve/resolved-dns-stream.c +++ b/src/resolve/resolved-dns-stream.c @@ -64,7 +64,7 @@ static int dns_stream_complete(DnsStream *s, int error) { static int dns_stream_identify(DnsStream *s) { union { struct cmsghdr header; /* For alignment */ - uint8_t buffer[CMSG_SPACE(MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo))) + uint8_t buffer[CMSG_SPACE(CONST_MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo))) + EXTRA_CMSG_SPACE /* kernel appears to require extra space */]; } control; struct msghdr mh = {}; diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index bfbdc7d55b..04ee204074 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -841,7 +841,7 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; union { struct cmsghdr header; /* For alignment */ - uint8_t buffer[CMSG_SPACE(MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo))) + uint8_t buffer[CMSG_SPACE(CONST_MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo))) + CMSG_SPACE(int) /* ttl/hoplimit */ + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */]; } control; diff --git a/src/shared/log.c b/src/shared/log.c index 2bac998bcd..b730ac921a 100644 --- a/src/shared/log.c +++ b/src/shared/log.c @@ -871,27 +871,47 @@ int log_set_max_level_from_string(const char *e) { return 0; } +static int parse_proc_cmdline_item(const char *key, const char *value) { + + /* + * The systemd.log_xyz= settings are parsed by all tools, and + * so is "debug". + * + * However, "quiet" is only parsed by PID 1! + */ + + if (streq(key, "debug") && !value) + log_set_max_level(LOG_DEBUG); + + else if (streq(key, "systemd.log_target") && value) { + + if (log_set_target_from_string(value) < 0) + log_warning("Failed to parse log target '%s'. Ignoring.", value); + + } else if (streq(key, "systemd.log_level") && value) { + + if (log_set_max_level_from_string(value) < 0) + log_warning("Failed to parse log level '%s'. Ignoring.", value); + + } else if (streq(key, "systemd.log_color") && value) { + + if (log_show_color_from_string(value) < 0) + log_warning("Failed to parse log color setting '%s'. Ignoring.", value); + + } else if (streq(key, "systemd.log_location") && value) { + + if (log_show_location_from_string(value) < 0) + log_warning("Failed to parse log location setting '%s'. Ignoring.", value); + } + + return 0; +} + void log_parse_environment(void) { _cleanup_free_ char *line = NULL; const char *e; - int r; - r = proc_cmdline(&line); - if (r < 0) - log_warning("Failed to read /proc/cmdline. Ignoring: %s", strerror(-r)); - else if (r > 0) { - const char *word, *state; - size_t l; - - FOREACH_WORD_QUOTED(word, l, line, state) { - if (l == 5 && startswith(word, "debug")) { - log_set_max_level(LOG_DEBUG); - break; - } - } - if (!isempty(state)) - log_warning("Trailing garbage and the end of kernel commandline, ignoring."); - } + parse_proc_cmdline(parse_proc_cmdline_item); e = secure_getenv("SYSTEMD_LOG_TARGET"); if (e && log_set_target_from_string(e) < 0) diff --git a/src/shared/macro.h b/src/shared/macro.h index 5619c32e45..179b24c983 100644 --- a/src/shared/macro.h +++ b/src/shared/macro.h @@ -133,46 +133,55 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { }) #undef MAX -#define MAX(a,b) \ - __extension__ ({ \ - typeof(a) _a = (a); \ - typeof(b) _b = (b); \ - _a > _b ? _a : _b; \ +#define MAX(a,b) \ + __extension__ ({ \ + const typeof(a) _a = (a); \ + const typeof(b) _b = (b); \ + _a > _b ? _a : _b; \ }) -#define MAX3(x,y,z) \ - __extension__ ({ \ - typeof(x) _c = MAX(x,y); \ - MAX(_c, z); \ +/* evaluates to (void) if _A or _B are not constant or of different types */ +#define CONST_MAX(_A, _B) \ + __extension__ (__builtin_choose_expr( \ + __builtin_constant_p(_A) && \ + __builtin_constant_p(_B) && \ + __builtin_types_compatible_p(typeof(_A), typeof(_B)), \ + ((_A) > (_B)) ? (_A) : (_B), \ + (void)0)) + +#define MAX3(x,y,z) \ + __extension__ ({ \ + const typeof(x) _c = MAX(x,y); \ + MAX(_c, z); \ }) #undef MIN -#define MIN(a,b) \ - __extension__ ({ \ - typeof(a) _a = (a); \ - typeof(b) _b = (b); \ - _a < _b ? _a : _b; \ +#define MIN(a,b) \ + __extension__ ({ \ + const typeof(a) _a = (a); \ + const typeof(b) _b = (b); \ + _a < _b ? _a : _b; \ }) -#define MIN3(x,y,z) \ - __extension__ ({ \ - typeof(x) _c = MIN(x,y); \ - MIN(_c, z); \ +#define MIN3(x,y,z) \ + __extension__ ({ \ + const typeof(x) _c = MIN(x,y); \ + MIN(_c, z); \ }) -#define LESS_BY(A,B) \ - __extension__ ({ \ - typeof(A) _A = (A); \ - typeof(B) _B = (B); \ - _A > _B ? _A - _B : 0; \ +#define LESS_BY(A,B) \ + __extension__ ({ \ + const typeof(A) _A = (A); \ + const typeof(B) _B = (B); \ + _A > _B ? _A - _B : 0; \ }) #ifndef CLAMP #define CLAMP(x, low, high) \ __extension__ ({ \ - typeof(x) _x = (x); \ - typeof(low) _low = (low); \ - typeof(high) _high = (high); \ + const typeof(x) _x = (x); \ + const typeof(low) _low = (low); \ + const typeof(high) _high = (high); \ ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \ }) #endif diff --git a/src/shared/util.c b/src/shared/util.c index 0db4bd90e8..18d40f398f 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -2084,12 +2084,14 @@ fail: } int release_terminal(void) { - int r = 0; - struct sigaction sa_old, sa_new = { + static const struct sigaction sa_new = { .sa_handler = SIG_IGN, .sa_flags = SA_RESTART, }; - _cleanup_close_ int fd; + + _cleanup_close_ int fd = -1; + struct sigaction sa_old; + int r = 0; fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC); if (fd < 0) @@ -6868,11 +6870,13 @@ char *tempfn_random(const char *p) { bool is_localhost(const char *hostname) { assert(hostname); - /* This tries to identify local hostnames described in RFC6761 - * plus the redhatism of .localdomain */ + /* This tries to identify local host and domain names + * described in RFC6761 plus the redhatism of .localdomain */ return streq(hostname, "localhost") || streq(hostname, "localhost.") || + streq(hostname, "localdomain.") || + streq(hostname, "localdomain") || endswith(hostname, ".localhost") || endswith(hostname, ".localhost.") || endswith(hostname, ".localdomain") || @@ -6929,4 +6933,4 @@ int is_symlink(const char *path) { return 1; return 0; -}
\ No newline at end of file +} diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 79566d2109..3eedb4450b 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -282,6 +282,7 @@ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **in int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_; int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds); +int sd_bus_query_sender_privilege(sd_bus_message *call, int capability); /* Credential handling */ diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h index db785077ff..b2086c7836 100644 --- a/src/systemd/sd-network.h +++ b/src/systemd/sd-network.h @@ -58,11 +58,14 @@ int sd_network_get_operational_state(char **state); /* Get DNS entries for all links. These are string representations of * IP addresses */ -int sd_network_get_dns(char ***addr); +int sd_network_get_dns(char ***dns); /* Get NTP entries for all links. These are domain names or string * reperesentations of IP addresses */ -int sd_network_get_ntp(char ***addr); +int sd_network_get_ntp(char ***ntp); + +/* Get the search/routing domains for all links. */ +int sd_network_get_domains(char ***domains); /* Get setup state from ifindex. * Possible states: @@ -107,6 +110,10 @@ int sd_network_link_get_llmnr(int ifindex, char **llmnr); /* Get the DNS domain names for a given link. */ int sd_network_link_get_domains(int ifindex, char ***domains); +/* Returns whether or not domains that don't match any link should be resolved + * on this link. 1 for yes, 0 for no and negative value for error */ +int sd_network_link_get_wildcard_domain(int ifindex); + /* Monitor object */ typedef struct sd_network_monitor sd_network_monitor; diff --git a/src/test/test-util.c b/src/test/test-util.c index 7d81b0b7be..a8fa48aed2 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -70,6 +70,28 @@ static void test_align_power2(void) { } } +static void test_max(void) { + static const struct { + int a; + int b[CONST_MAX(10, 100)]; + } val1 = { + .a = CONST_MAX(10, 100), + }; + int d = 0; + + assert_cc(sizeof(val1.b) == sizeof(int) * 100); + + /* CONST_MAX returns (void) instead of a value if the passed arguments + * are not of the same type or not constant expressions. */ + assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 10)), int)); + assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(d, 10)), void)); + assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 1U)), void)); + + assert_se(val1.a == 100); + assert_se(MAX(++d, 0) == 1); + assert_se(d == 1); +} + static void test_first_word(void) { assert_se(first_word("Hello", "")); assert_se(first_word("Hello", "Hello")); @@ -927,6 +949,7 @@ int main(int argc, char *argv[]) { test_streq_ptr(); test_align_power2(); + test_max(); test_first_word(); test_close_many(); test_parse_boolean(); diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 1efbf3386e..16036953fa 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -395,7 +395,7 @@ static int method_set_timezone(sd_bus *bus, sd_bus_message *m, void *userdata, s if (streq_ptr(z, c->zone)) return sd_bus_reply_method_return(m, NULL); - r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.timedate1.set-timezone", interactive, error, method_set_timezone, c); + r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-timezone", interactive, error, method_set_timezone, c); if (r < 0) return r; if (r == 0) @@ -456,7 +456,7 @@ static int method_set_local_rtc(sd_bus *bus, sd_bus_message *m, void *userdata, if (lrtc == c->local_rtc) return sd_bus_reply_method_return(m, NULL); - r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.timedate1.set-local-rtc", interactive, error, method_set_local_rtc, c); + r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-local-rtc", interactive, error, method_set_local_rtc, c); if (r < 0) return r; if (r == 0) @@ -561,7 +561,7 @@ static int method_set_time(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bu } else timespec_store(&ts, (usec_t) utc); - r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.timedate1.set-time", interactive, error, method_set_time, c); + r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-time", interactive, error, method_set_time, c); if (r < 0) return r; if (r == 0) @@ -601,7 +601,7 @@ static int method_set_ntp(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus if ((bool)ntp == c->use_ntp) return sd_bus_reply_method_return(m, NULL); - r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.timedate1.set-ntp", interactive, error, method_set_ntp, c); + r = bus_verify_polkit_async(bus, &c->polkit_registry, m, CAP_SYS_TIME, "org.freedesktop.timedate1.set-ntp", interactive, error, method_set_ntp, c); if (r < 0) return r; if (r == 0) |