From 780950a2ba584fae3381abeb3d1a5f42b8bedbcb Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 22 Jul 2015 11:16:44 +0200 Subject: Revert "build-sys: hide magic section variables from exported symbols" This reverts commit aac7c5ed8bc6ffaba417b9c0b87bcf342865431b. This visibility bug originated in ld.gold and has been fixed upstream: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5417c94d1a944d1a27f99240e5d62a6d7cd324f1 --- src/libsystemd/sd-bus/bus-error.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c index 64a5a972ae..dac157be16 100644 --- a/src/libsystemd/sd-bus/bus-error.c +++ b/src/libsystemd/sd-bus/bus-error.c @@ -70,11 +70,9 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = { SD_BUS_ERROR_MAP_END }; -/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section. - * Hide them; for currently unknown reasons they get exported to the shared libries - * even without being listed in the sym file. */ -extern const sd_bus_error_map __start_BUS_ERROR_MAP[] _hidden_; -extern const sd_bus_error_map __stop_BUS_ERROR_MAP[] _hidden_; +/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section */ +extern const sd_bus_error_map __start_BUS_ERROR_MAP[]; +extern const sd_bus_error_map __stop_BUS_ERROR_MAP[]; /* Additional maps registered with sd_bus_error_add_map() are in this * NULL terminated array */ -- cgit v1.2.3-54-g00ecf From afb14803b34a9f4abf5265365aebe9a3132344c2 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Wed, 9 Dec 2015 15:46:46 +0100 Subject: automount: implement transient automounts --- src/core/automount.c | 3 +++ src/core/dbus-automount.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ src/core/dbus-automount.h | 2 ++ 3 files changed, 59 insertions(+) diff --git a/src/core/automount.c b/src/core/automount.c index 85803a9c4a..10ea4ee17d 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -1105,6 +1105,9 @@ const UnitVTable automount_vtable = { .reset_failed = automount_reset_failed, .bus_vtable = bus_automount_vtable, + .bus_set_property = bus_automount_set_property, + + .can_transient = true, .shutdown = automount_shutdown, .supported = automount_supported, diff --git a/src/core/dbus-automount.c b/src/core/dbus-automount.c index b2806ad86f..26212b3a95 100644 --- a/src/core/dbus-automount.c +++ b/src/core/dbus-automount.c @@ -32,3 +32,57 @@ const sd_bus_vtable bus_automount_vtable[] = { SD_BUS_PROPERTY("TimeoutIdleUSec", "t", bus_property_get_usec, offsetof(Automount, timeout_idle_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_VTABLE_END }; + +static int bus_automount_set_transient_property( + Automount *a, + const char *name, + sd_bus_message *message, + UnitSetPropertiesMode mode, + sd_bus_error *error) { + + int r; + + assert(a); + assert(name); + assert(message); + + if (streq(name, "TimeoutIdleUSec")) { + usec_t timeout_idle_usec; + r = sd_bus_message_read(message, "t", &timeout_idle_usec); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) { + char time[FORMAT_TIMESPAN_MAX]; + + a->timeout_idle_usec = timeout_idle_usec; + unit_write_drop_in_format(UNIT(a), mode, name, "[Automount]\nTimeoutIdleSec=%s\n", + format_timespan(time, sizeof(time), timeout_idle_usec, USEC_PER_MSEC)); + } + } else + return 0; + + return 1; +} + +int bus_automount_set_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitSetPropertiesMode mode, + sd_bus_error *error) { + + Automount *a = AUTOMOUNT(u); + int r = 0; + + assert(a); + assert(name); + assert(message); + + if (u->transient && u->load_state == UNIT_STUB) + /* This is a transient unit, let's load a little more */ + + r = bus_automount_set_transient_property(a, name, message, mode, error); + + return r; +} diff --git a/src/core/dbus-automount.h b/src/core/dbus-automount.h index 7b51eb973a..f41adda2a6 100644 --- a/src/core/dbus-automount.h +++ b/src/core/dbus-automount.h @@ -21,3 +21,5 @@ extern const sd_bus_vtable bus_automount_vtable[]; + +int bus_automount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error); -- cgit v1.2.3-54-g00ecf From b294b79fb0f9749afa53624c8f06b145ea2c1525 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Wed, 9 Dec 2015 16:02:10 +0100 Subject: mount: use get_mount_parameters_fragment() consistently There are multiple different checks, that all mean the same thing: Is it a explicitly configured mount unit where actions need to be taken to mount it, or is is just mirroring 'mountinfo': 'from_fragment' to set if fragment_path is not NULL, and get_mount_parameters_fragment() just wraps that and returns fragment_path. Use get_mount_parameters_fragment() everywhere to be consistent. This is just a cleanup without functional change. --- src/core/mount.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/core/mount.c b/src/core/mount.c index 665a60bb55..7b20892b0d 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -482,6 +482,7 @@ static int mount_add_default_dependencies(Mount *m) { static int mount_verify(Mount *m) { _cleanup_free_ char *e = NULL; + MountParameters *p; int r; assert(m); @@ -506,7 +507,8 @@ static int mount_verify(Mount *m) { return -EINVAL; } - if (UNIT(m)->fragment_path && !m->parameters_fragment.what) { + p = get_mount_parameters_fragment(m); + if (p && !p->what) { log_unit_error(UNIT(m), "What= setting is missing. Refusing."); return -EBADMSG; } @@ -850,11 +852,6 @@ fail: mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES); } -static int mount_get_opts(Mount *m, char **ret) { - return fstab_filter_options(m->parameters_fragment.options, - "nofail\0" "noauto\0" "auto\0", NULL, NULL, ret); -} - static void mount_enter_mounting(Mount *m) { int r; MountParameters *p; @@ -877,19 +874,18 @@ static void mount_enter_mounting(Mount *m) { if (p && mount_is_bind(p)) (void) mkdir_p_label(p->what, m->directory_mode); - if (m->from_fragment) { + if (p) { _cleanup_free_ char *opts = NULL; - r = mount_get_opts(m, &opts); + r = fstab_filter_options(p->options, "nofail\0" "noauto\0" "auto\0", NULL, NULL, &opts); if (r < 0) goto fail; - r = exec_command_set(m->control_command, MOUNT_PATH, - m->parameters_fragment.what, m->where, NULL); + r = exec_command_set(m->control_command, MOUNT_PATH, p->what, m->where, NULL); if (r >= 0 && m->sloppy_options) r = exec_command_append(m->control_command, "-s", NULL); - if (r >= 0 && m->parameters_fragment.fstype) - r = exec_command_append(m->control_command, "-t", m->parameters_fragment.fstype, NULL); + if (r >= 0 && p->fstype) + r = exec_command_append(m->control_command, "-t", p->fstype, NULL); if (r >= 0 && !isempty(opts)) r = exec_command_append(m->control_command, "-o", opts, NULL); } else @@ -915,27 +911,29 @@ fail: static void mount_enter_remounting(Mount *m) { int r; + MountParameters *p; assert(m); m->control_command_id = MOUNT_EXEC_REMOUNT; m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT; - if (m->from_fragment) { + p = get_mount_parameters_fragment(m); + if (p) { const char *o; - if (m->parameters_fragment.options) - o = strjoina("remount,", m->parameters_fragment.options); + if (p->options) + o = strjoina("remount,", p->options); else o = "remount"; r = exec_command_set(m->control_command, MOUNT_PATH, - m->parameters_fragment.what, m->where, + p->what, m->where, "-o", o, NULL); if (r >= 0 && m->sloppy_options) r = exec_command_append(m->control_command, "-s", NULL); - if (r >= 0 && m->parameters_fragment.fstype) - r = exec_command_append(m->control_command, "-t", m->parameters_fragment.fstype, NULL); + if (r >= 0 && p->fstype) + r = exec_command_append(m->control_command, "-t", p->fstype, NULL); } else r = -ENOENT; -- cgit v1.2.3-54-g00ecf From 96f5957f1f0d98584bb463d73616a6755e02624b Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Wed, 9 Dec 2015 16:02:51 +0100 Subject: mount: write drop-in file when setting transient properties This fixes transient mount units in general. With this change, 'from_fragment' is for transient mount units. As a result, the normal logic for 'fragment' mount units vs. 'mountinfo' mount units works for transient mount units as well. --- src/core/dbus-mount.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c index 935db7c48b..b4bbee0648 100644 --- a/src/core/dbus-mount.c +++ b/src/core/dbus-mount.c @@ -157,6 +157,9 @@ static int bus_mount_set_transient_property( if (!p) return -ENOMEM; + unit_write_drop_in_format(UNIT(m), mode, name, "[Mount]\n%s=%s\n", + name, new_property); + free(*property); *property = p; } -- cgit v1.2.3-54-g00ecf From 3228995c534c4cae609e97502f7c7ca1d4a14840 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Thu, 23 Jun 2016 11:52:45 +0200 Subject: cgroup: detect cgroup namespaces - define CLONE_NEWCGROUP - add fun to detect whether cgroup namespaces are supported --- src/basic/cgroup-util.c | 14 ++++++++++++++ src/basic/cgroup-util.h | 2 ++ src/basic/missing.h | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 7cdc97ee3c..0561a07ed9 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -134,6 +134,20 @@ int cg_read_event(const char *controller, const char *path, const char *event, return -ENOENT; } +bool cg_ns_supported(void) { + static thread_local int enabled = -1; + + if (enabled >= 0) + return enabled; + + if (access("/proc/self/ns/cgroup", F_OK) == 0) + enabled = 1; + else + enabled = 0; + + return enabled; +} + int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) { _cleanup_free_ char *fs = NULL; int r; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 4bb5291296..5c1c474112 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -214,6 +214,8 @@ int cg_mask_supported(CGroupMask *ret); int cg_kernel_controllers(Set *controllers); +bool cg_ns_supported(void); + int cg_unified(void); void cg_unified_flush(void); diff --git a/src/basic/missing.h b/src/basic/missing.h index b1272f8799..f8e096605e 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -445,6 +445,10 @@ struct btrfs_ioctl_quota_ctl_args { #define CGROUP2_SUPER_MAGIC 0x63677270 #endif +#ifndef CLONE_NEWCGROUP +#define CLONE_NEWCGROUP 0x02000000 +#endif + #ifndef TMPFS_MAGIC #define TMPFS_MAGIC 0x01021994 #endif -- cgit v1.2.3-54-g00ecf From 0996ef00fb5c0770d49670f81a230fcc2552af89 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Thu, 23 Jun 2016 13:41:56 +0200 Subject: nspawn: handle cgroup namespaces (NOTE: Cgroup namespaces work with legacy and unified hierarchies: "This is completely backward compatible and will be completely invisible to any existing cgroup users (except for those running inside a cgroup namespace and looking at /proc/pid/cgroup of tasks outside their namespace.)" (https://lists.linuxfoundation.org/pipermail/containers/2016-January/036582.html) So there is no need to special case unified.) If cgroup namespaces are supported we skip mount_cgroups() in the outer_child(). Instead, we unshare(CLONE_NEWCGROUP) in the inner_child() and only then do we call mount_cgroups(). The clean way to handle cgroup namespaces would be to delegate mounting of cgroups completely to the init system in the container. However, this would likely break backward compatibility with the UNIFIED_CGROUP_HIERARCHY flag of systemd-nspawn. Also no cgroupfs would be mounted whenever the user simply requests a shell and no init is available to mount cgroups. Hence, we introduce mount_legacy_cgns_supported(). After calling unshare(CLONE_NEWCGROUP) it parses /proc/self/cgroup to find the mounted controllers and mounts them inside the new cgroup namespace. This should preserve backward compatibility with the UNIFIED_CGROUP_HIERARCHY flag and mount a cgroupfs when no init in the container is running. --- src/nspawn/nspawn-mount.c | 188 ++++++++++++++++++++++++++++++++++++++++++---- src/nspawn/nspawn.c | 41 +++++++--- 2 files changed, 201 insertions(+), 28 deletions(-) diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 8e2d2d543c..b76b09b9cb 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -23,6 +23,8 @@ #include "alloc-util.h" #include "cgroup-util.h" #include "escape.h" +#include "fd-util.h" +#include "fileio.h" #include "fs-util.h" #include "label.h" #include "mkdir.h" @@ -181,13 +183,15 @@ int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s) { static int tmpfs_patch_options( const char *options, - bool userns, uid_t uid_shift, uid_t uid_range, + bool userns, + uid_t uid_shift, uid_t uid_range, + bool patch_ids, const char *selinux_apifs_context, char **ret) { char *buf = NULL; - if (userns && uid_shift != 0) { + if ((userns && uid_shift != 0) || patch_ids) { assert(uid_shift != UID_INVALID); if (options) @@ -218,7 +222,13 @@ static int tmpfs_patch_options( } #endif + if (!buf && options) { + buf = strdup(options); + if (!buf) + return -ENOMEM; + } *ret = buf; + return !!buf; } @@ -271,7 +281,15 @@ int mount_sysfs(const char *dest) { return log_error_errno(errno, "Failed to remove %s: %m", full); x = prefix_roota(top, "/fs/kdbus"); - (void) mkdir(x, 0755); + (void) mkdir_p(x, 0755); + + /* Create mountpoint for cgroups. Otherwise we are not allowed since we + * remount /sys read-only. + */ + if (cg_ns_supported()) { + x = prefix_roota(top, "/fs/cgroup"); + (void) mkdir_p(x, 0755); + } if (mount(NULL, top, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL) < 0) return log_error_errno(errno, "Failed to make %s read-only: %m", top); @@ -348,7 +366,7 @@ int mount_all(const char *dest, o = mount_table[k].options; if (streq_ptr(mount_table[k].type, "tmpfs")) { - r = tmpfs_patch_options(o, use_userns, uid_shift, uid_range, selinux_apifs_context, &options); + r = tmpfs_patch_options(o, use_userns, uid_shift, uid_range, false, selinux_apifs_context, &options); if (r < 0) return log_oom(); if (r > 0) @@ -485,7 +503,7 @@ static int mount_tmpfs( if (r < 0 && r != -EEXIST) return log_error_errno(r, "Creating mount point for tmpfs %s failed: %m", where); - r = tmpfs_patch_options(m->options, userns, uid_shift, uid_range, selinux_apifs_context, &buf); + r = tmpfs_patch_options(m->options, userns, uid_shift, uid_range, false, selinux_apifs_context, &buf); if (r < 0) return log_oom(); options = r > 0 ? buf : m->options; @@ -600,6 +618,48 @@ int mount_custom( return 0; } +/* Retrieve existing subsystems. This function is called in a new cgroup + * namespace. + */ +static int get_controllers(Set *subsystems) { + _cleanup_fclose_ FILE *f = NULL; + char line[LINE_MAX]; + + assert(subsystems); + + f = fopen("/proc/self/cgroup", "re"); + if (!f) + return errno == ENOENT ? -ESRCH : -errno; + + FOREACH_LINE(line, f, return -errno) { + int r; + char *e, *l, *p; + + truncate_nl(line); + + l = strchr(line, ':'); + if (!l) + continue; + + l++; + e = strchr(l, ':'); + if (!e) + continue; + + *e = 0; + + if (streq(l, "") || streq(l, "name=systemd")) + continue; + + p = strdup(l); + r = set_consume(subsystems, p); + if (r < 0) + return r; + } + + return 0; +} + static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controller, const char *hierarchy, bool read_only) { char *to; int r; @@ -628,11 +688,107 @@ static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controlle return 1; } -static int mount_legacy_cgroups( - const char *dest, +/* Mount a legacy cgroup hierarchy when cgroup namespaces are supported. */ +static int mount_legacy_cgns_supported( bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { + _cleanup_set_free_free_ Set *controllers = NULL; + const char *cgroup_root = "/sys/fs/cgroup", *c; + int r; + (void) mkdir_p(cgroup_root, 0755); + + /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */ + r = path_is_mount_point(cgroup_root, AT_SYMLINK_FOLLOW); + if (r < 0) + return log_error_errno(r, "Failed to determine if /sys/fs/cgroup is already mounted: %m"); + if (r == 0) { + _cleanup_free_ char *options = NULL; + + /* When cgroup namespaces are enabled and user namespaces are + * used then the mount of the cgroupfs is done *inside* the new + * user namespace. We're root in the new user namespace and the + * kernel will happily translate our uid/gid to the correct + * uid/gid as seen from e.g. /proc/1/mountinfo. So we simply + * pass uid 0 and not uid_shift to tmpfs_patch_options(). + */ + r = tmpfs_patch_options("mode=755", userns, 0, uid_range, true, selinux_apifs_context, &options); + if (r < 0) + return log_oom(); + + if (mount("tmpfs", cgroup_root, "tmpfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options) < 0) + return log_error_errno(errno, "Failed to mount /sys/fs/cgroup: %m"); + } + + if (cg_unified() > 0) + goto skip_controllers; + + controllers = set_new(&string_hash_ops); + if (!controllers) + return log_oom(); + + r = get_controllers(controllers); + if (r < 0) + return log_error_errno(r, "Failed to determine cgroup controllers: %m"); + + for (;;) { + _cleanup_free_ const char *controller = NULL; + + controller = set_steal_first(controllers); + if (!controller) + break; + + r = mount_legacy_cgroup_hierarchy("", controller, controller, !userns); + if (r < 0) + return r; + + /* When multiple hierarchies are co-mounted, make their + * constituting individual hierarchies a symlink to the + * co-mount. + */ + c = controller; + for (;;) { + _cleanup_free_ char *target = NULL, *tok = NULL; + + r = extract_first_word(&c, &tok, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to extract co-mounted cgroup controller: %m"); + if (r == 0) + break; + + target = prefix_root("/sys/fs/cgroup", tok); + if (!target) + return log_oom(); + + if (streq(controller, tok)) + break; + + r = symlink_idempotent(controller, target); + if (r == -EINVAL) + return log_error_errno(r, "Invalid existing symlink for combined hierarchy: %m"); + if (r < 0) + return log_error_errno(r, "Failed to create symlink for combined hierarchy: %m"); + } + } + +skip_controllers: + r = mount_legacy_cgroup_hierarchy("", "none,name=systemd,xattr", "systemd", false); + if (r < 0) + return r; + + if (!userns) { + if (mount(NULL, cgroup_root, NULL, MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755") < 0) + return log_error_errno(errno, "Failed to remount %s read-only: %m", cgroup_root); + } + + return 0; +} + +/* Mount legacy cgroup hierarchy when cgroup namespaces are unsupported. */ +static int mount_legacy_cgns_unsupported( + const char *dest, + bool userns, uid_t uid_shift, uid_t uid_range, + const char *selinux_apifs_context) { _cleanup_set_free_free_ Set *controllers = NULL; const char *cgroup_root; int r; @@ -648,7 +804,7 @@ static int mount_legacy_cgroups( if (r == 0) { _cleanup_free_ char *options = NULL; - r = tmpfs_patch_options("mode=755", userns, uid_shift, uid_range, selinux_apifs_context, &options); + r = tmpfs_patch_options("mode=755", userns, uid_shift, uid_range, false, selinux_apifs_context, &options); if (r < 0) return log_oom(); @@ -707,10 +863,8 @@ static int mount_legacy_cgroups( return r; r = symlink_idempotent(combined, target); - if (r == -EINVAL) { - log_error("Invalid existing symlink for combined hierarchy"); - return r; - } + if (r == -EINVAL) + return log_error_errno(r, "Invalid existing symlink for combined hierarchy: %m"); if (r < 0) return log_error_errno(r, "Failed to create symlink for combined hierarchy: %m"); } @@ -765,8 +919,10 @@ int mount_cgroups( if (unified_requested) return mount_unified_cgroups(dest); - else - return mount_legacy_cgroups(dest, userns, uid_shift, uid_range, selinux_apifs_context); + else if (cg_ns_supported()) + return mount_legacy_cgns_supported(userns, uid_shift, uid_range, selinux_apifs_context); + + return mount_legacy_cgns_unsupported(dest, userns, uid_shift, uid_range, selinux_apifs_context); } int mount_systemd_cgroup_writable( @@ -834,7 +990,7 @@ int setup_volatile_state( return log_error_errno(errno, "Failed to create %s: %m", directory); options = "mode=755"; - r = tmpfs_patch_options(options, userns, uid_shift, uid_range, selinux_apifs_context, &buf); + r = tmpfs_patch_options(options, userns, uid_shift, uid_range, false, selinux_apifs_context, &buf); if (r < 0) return log_oom(); if (r > 0) @@ -870,7 +1026,7 @@ int setup_volatile( return log_error_errno(errno, "Failed to create temporary directory: %m"); options = "mode=755"; - r = tmpfs_patch_options(options, userns, uid_shift, uid_range, selinux_apifs_context, &buf); + r = tmpfs_patch_options(options, userns, uid_shift, uid_range, false, selinux_apifs_context, &buf); if (r < 0) return log_oom(); if (r > 0) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 73c56d7310..9e74a77758 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2594,9 +2594,24 @@ static int inner_child( return -ESRCH; } - r = mount_systemd_cgroup_writable("", arg_unified_cgroup_hierarchy); - if (r < 0) - return r; + if (cg_ns_supported()) { + r = unshare(CLONE_NEWCGROUP); + if (r < 0) + return log_error_errno(errno, "Failed to unshare cgroup namespace"); + r = mount_cgroups( + "", + arg_unified_cgroup_hierarchy, + arg_userns_mode != USER_NAMESPACE_NO, + arg_uid_shift, + arg_uid_range, + arg_selinux_apifs_context); + if (r < 0) + return r; + } else { + r = mount_systemd_cgroup_writable("", arg_unified_cgroup_hierarchy); + if (r < 0) + return r; + } r = reset_uid_gid(); if (r < 0) @@ -2978,15 +2993,17 @@ static int outer_child( if (r < 0) return r; - r = mount_cgroups( - directory, - arg_unified_cgroup_hierarchy, - arg_userns_mode != USER_NAMESPACE_NO, - arg_uid_shift, - arg_uid_range, - arg_selinux_apifs_context); - if (r < 0) - return r; + if (!cg_ns_supported()) { + r = mount_cgroups( + directory, + arg_unified_cgroup_hierarchy, + arg_userns_mode != USER_NAMESPACE_NO, + arg_uid_shift, + arg_uid_range, + arg_selinux_apifs_context); + if (r < 0) + return r; + } r = mount_move_root(directory); if (r < 0) -- cgit v1.2.3-54-g00ecf From b52a109ad38cd37b660ccd5394ff5c171a5e5355 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 18:19:29 +0200 Subject: gpt-generator: use /efi as mount point for the ESP if it exists Let's make the EFI generator a bit smarter: if /efi exists it is used as mount point for the ESP, otherwise /boot is used. This should increase compatibility with distros which use legacy boot loaders that insist on having /boot as something that isn't the ESP. --- man/systemd-gpt-auto-generator.xml | 23 +++++++++------- src/gpt-auto-generator/gpt-auto-generator.c | 41 ++++++++++++++++------------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/man/systemd-gpt-auto-generator.xml b/man/systemd-gpt-auto-generator.xml index e890c4dce2..d26206710f 100644 --- a/man/systemd-gpt-auto-generator.xml +++ b/man/systemd-gpt-auto-generator.xml @@ -137,6 +137,11 @@ Swap All swap partitions located on the disk the root partition is located on are enabled. + + c12a7328-f81f-11d2-ba4b-00a0c93ec93b + EFI System Partition (ESP) + The first ESP located on the disk the root partition is located on is mounted to /boot or /efi, see below. + @@ -150,16 +155,14 @@ /etc/crypttab with a different device mapper device name. - Mount and automount units for the EFI System Partition (ESP), - mounting it to /boot, are generated on EFI - systems where the boot loader communicates the used ESP to the operating - system. Since this generator creates an automount unit, the mount will - only be activated on-demand, when accessed. On systems where - /boot is an explicitly configured mount - (for example, listed in - fstab5) - or where the /boot mount point is non-empty, no - mount units are generated. + Mount and automount units for the EFI System Partition (ESP) are generated on EFI systems. The ESP is mounted + to /boot, unless a mount point directory /efi exists, in which case it is + mounted there. Since this generator creates an automount unit, the mount will only be activated on-demand, when + accessed. On systems where /boot (or /efi if it exists) is an explicitly + configured mount (for example, listed in fstab5) or where the + /boot (or /efi) mount point is non-empty, no mount units are + generated. When using this generator in conjunction with btrfs file systems, make sure to set the correct default subvolumes on them, diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index a4938a7c3a..dede86eabf 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -453,33 +453,37 @@ static int add_boot(const char *what) { _cleanup_blkid_free_probe_ blkid_probe b = NULL; const char *fstype = NULL, *uuid = NULL; sd_id128_t id, type_id; + const char *esp; int r; assert(what); if (!is_efi_boot()) { - log_debug("Not an EFI boot, ignoring /boot."); + log_debug("Not an EFI boot, ignoring the ESP."); return 0; } if (in_initrd()) { - log_debug("In initrd, ignoring /boot."); + log_debug("In initrd, ignoring the ESP."); return 0; } if (detect_container() > 0) { - log_debug("In a container, ignoring /boot."); + log_debug("In a container, ignoring the ESP."); return 0; } + /* If /efi exists we'll use that. Otherwise we'll use /boot, as that's usually the better choice */ + esp = access("/efi/", F_OK) >= 0 ? "/efi" : "/boot"; + /* We create an .automount which is not overridden by the .mount from the fstab generator. */ - if (fstab_is_mount_point("/boot")) { - log_debug("/boot specified in fstab, ignoring."); + if (fstab_is_mount_point(esp)) { + log_debug("%s specified in fstab, ignoring.", esp); return 0; } - if (path_is_busy("/boot")) { - log_debug("/boot already populated, ignoring."); + if (path_is_busy(esp)) { + log_debug("%s already populated, ignoring.", esp); return 0; } @@ -488,7 +492,6 @@ static int add_boot(const char *what) { log_debug("EFI loader partition unknown."); return 0; } - if (r < 0) { log_error_errno(r, "Failed to read ESP partition UUID: %m"); return r; @@ -514,35 +517,35 @@ static int add_boot(const char *what) { (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); if (!streq_ptr(fstype, "vfat")) { - log_debug("Partition for /boot is not a FAT filesystem, ignoring."); + log_debug("Partition for %s is not a FAT filesystem, ignoring.", esp); return 0; } errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid, NULL); if (r != 0) { - log_debug_errno(errno, "Partition for /boot does not have a UUID, ignoring."); + log_debug_errno(errno, "Partition for %s does not have a UUID, ignoring.", esp); return 0; } if (sd_id128_from_string(uuid, &type_id) < 0) { - log_debug("Partition for /boot does not have a valid UUID, ignoring."); + log_debug("Partition for %s does not have a valid UUID, ignoring.", esp); return 0; } if (!sd_id128_equal(type_id, id)) { - log_debug("Partition for /boot does not appear to be the partition we are booted from."); + log_debug("Partition for %s does not appear to be the partition we are booted from.", esp); return 0; } r = add_automount("boot", - what, - "/boot", - "vfat", - true, - "umask=0077", - "EFI System Partition Automount", - 120 * USEC_PER_SEC); + what, + esp, + "vfat", + true, + "umask=0077", + "EFI System Partition Automount", + 120 * USEC_PER_SEC); return r; } -- cgit v1.2.3-54-g00ecf From a6bc7db980532d294c29f1cd5654f03453519c92 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 18:36:04 +0200 Subject: nspawn: if an ESP is part of the disk image to operate on, mount it to /efi or /boot Matching the behaviour of gpt-auto-generator, if we find an ESP while dissecting a container image, mount it to /efi or /boot if those dirs exist and are empty. This should enable us to run "bootctl" inside a container and do the right thing. --- src/nspawn/nspawn.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index e4be0a2251..befe342b02 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1803,17 +1803,18 @@ static int dissect_image( char **root_device, bool *root_device_rw, char **home_device, bool *home_device_rw, char **srv_device, bool *srv_device_rw, + char **esp_device, bool *secondary) { #ifdef HAVE_BLKID - int home_nr = -1, srv_nr = -1; + int home_nr = -1, srv_nr = -1, esp_nr = -1; #ifdef GPT_ROOT_NATIVE int root_nr = -1; #endif #ifdef GPT_ROOT_SECONDARY int secondary_root_nr = -1; #endif - _cleanup_free_ char *home = NULL, *root = NULL, *secondary_root = NULL, *srv = NULL, *generic = NULL; + _cleanup_free_ char *home = NULL, *root = NULL, *secondary_root = NULL, *srv = NULL, *esp = NULL, *generic = NULL; _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; @@ -1831,6 +1832,7 @@ static int dissect_image( assert(root_device); assert(home_device); assert(srv_device); + assert(esp_device); assert(secondary); assert(arg_image); @@ -2044,6 +2046,16 @@ static int dissect_image( r = free_and_strdup(&srv, node); if (r < 0) return log_oom(); + } else if (sd_id128_equal(type_id, GPT_ESP)) { + + if (esp && nr >= esp_nr) + continue; + + esp_nr = nr; + + r = free_and_strdup(&esp, node); + if (r < 0) + return log_oom(); } #ifdef GPT_ROOT_NATIVE else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) { @@ -2161,6 +2173,11 @@ static int dissect_image( *srv_device_rw = srv_rw; } + if (esp) { + *esp_device = esp; + esp = NULL; + } + return 0; #else log_error("--image= is not supported, compiled without blkid support."); @@ -2289,7 +2306,8 @@ static int mount_devices( const char *where, const char *root_device, bool root_device_rw, const char *home_device, bool home_device_rw, - const char *srv_device, bool srv_device_rw) { + const char *srv_device, bool srv_device_rw, + const char *esp_device) { int r; assert(where); @@ -2312,6 +2330,27 @@ static int mount_devices( return log_error_errno(r, "Failed to mount server data directory: %m"); } + if (esp_device) { + const char *mp, *x; + + /* Mount the ESP to /efi if it exists and is empty. If it doesn't exist, use /boot instead. */ + + mp = "/efi"; + x = strjoina(arg_directory, mp); + r = dir_is_empty(x); + if (r == -ENOENT) { + mp = "/boot"; + x = strjoina(arg_directory, mp); + r = dir_is_empty(x); + } + + if (r > 0) { + r = mount_device(esp_device, arg_directory, mp, true); + if (r < 0) + return log_error_errno(r, "Failed to mount ESP: %m"); + } + } + return 0; } @@ -2785,6 +2824,7 @@ static int outer_child( const char *root_device, bool root_device_rw, const char *home_device, bool home_device_rw, const char *srv_device, bool srv_device_rw, + const char *esp_device, bool interactive, bool secondary, int pid_socket, @@ -2846,7 +2886,8 @@ static int outer_child( r = mount_devices(directory, root_device, root_device_rw, home_device, home_device_rw, - srv_device, srv_device_rw); + srv_device, srv_device_rw, + esp_device); if (r < 0) return r; @@ -3449,7 +3490,7 @@ static int load_settings(void) { int main(int argc, char *argv[]) { - _cleanup_free_ char *device_path = NULL, *root_device = NULL, *home_device = NULL, *srv_device = NULL, *console = NULL; + _cleanup_free_ char *device_path = NULL, *root_device = NULL, *home_device = NULL, *srv_device = NULL, *esp_device = NULL, *console = NULL; bool root_device_rw = true, home_device_rw = true, srv_device_rw = true; _cleanup_close_ int master = -1, image_fd = -1; _cleanup_fdset_free_ FDSet *fds = NULL; @@ -3631,6 +3672,7 @@ int main(int argc, char *argv[]) { &root_device, &root_device_rw, &home_device, &home_device_rw, &srv_device, &srv_device_rw, + &esp_device, &secondary); if (r < 0) goto finish; @@ -3805,6 +3847,7 @@ int main(int argc, char *argv[]) { root_device, root_device_rw, home_device, home_device_rw, srv_device, srv_device_rw, + esp_device, interactive, secondary, pid_socket_pair[1], -- cgit v1.2.3-54-g00ecf From 25579a43efcf5fdced4041427164e0852c035ab0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 18:39:54 +0200 Subject: bootctl: minor coding style improvements --- src/boot/bootctl.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 7cb2259717..6e0c961527 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -46,6 +46,9 @@ #include "string-util.h" #include "util.h" +static const char *arg_path = "/boot"; +static bool arg_touch_variables = true; + static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) { struct statfs sfs; struct stat st, st2; @@ -930,9 +933,6 @@ static int help(void) { return 0; } -static const char *arg_path = "/boot"; -static bool arg_touch_variables = true; - static int parse_argv(int argc, char *argv[]) { enum { ARG_PATH = 0x100, @@ -1036,12 +1036,10 @@ static int bootctl_main(int argc, char*argv[]) { return r; switch (arg_action) { + case ACTION_STATUS: { - _cleanup_free_ char *fw_type = NULL; - _cleanup_free_ char *fw_info = NULL; - _cleanup_free_ char *loader = NULL; - _cleanup_free_ char *loader_path = NULL; - sd_id128_t loader_part_uuid = {}; + _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL; + sd_id128_t loader_part_uuid = SD_ID128_NULL; if (is_efi_boot()) { read_loader_efi_var("LoaderFirmwareType", &fw_type); -- cgit v1.2.3-54-g00ecf From c18532e031d2923e095a189999c289be13aea7b8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 18:40:03 +0200 Subject: bootctl: fix error message check --- src/boot/bootctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 6e0c961527..f337eb6675 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -1049,7 +1049,7 @@ static int bootctl_main(int argc, char*argv[]) { if (loader_path) efi_tilt_backslashes(loader_path); r = efi_loader_get_device_part_uuid(&loader_part_uuid); - if (r < 0 && r == -ENOENT) + if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m"); printf("System:\n"); -- cgit v1.2.3-54-g00ecf From 2f2c539cd4af7ca526296adecff2a6f90d7d7b0c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 20:19:20 +0200 Subject: bootctl: rework to use common verbs parsing, and add searching of ESP path This rearranges bootctl a bit, so that it uses the usual verbs parsing routines, and automatically searches the ESP in /boot, /efi or /boot/efi, thus increasing compatibility with mainstream distros that insist on /boot/efi. This also adds minimal support for running bootctl in a container environment: when run inside a container verification of the ESP via raw block device access, trusting the container manager to mount the ESP correctly. Moreover, EFI variables are not accessed when running in the container. --- man/bootctl.xml | 6 +- src/boot/bootctl.c | 342 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 224 insertions(+), 124 deletions(-) diff --git a/man/bootctl.xml b/man/bootctl.xml index 6e835c037f..82c162ee70 100644 --- a/man/bootctl.xml +++ b/man/bootctl.xml @@ -101,8 +101,10 @@ - - Path to the EFI system partition. The default is /boot. + + Path to the EFI System Partition (ESP). If not specified, /efi, + /boot, and /boot/efi are checked in turn. It is recommended to mount + the ESP to /boot, if possible. diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index f337eb6675..8b2407f145 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -42,25 +42,52 @@ #include "fd-util.h" #include "fileio.h" #include "locale-util.h" +#include "parse-util.h" #include "rm-rf.h" #include "string-util.h" +#include "strv.h" +#include "umask-util.h" #include "util.h" +#include "verbs.h" +#include "virt.h" -static const char *arg_path = "/boot"; +static char *arg_path = NULL; static bool arg_touch_variables = true; -static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) { - struct statfs sfs; - struct stat st, st2; - _cleanup_free_ char *t = NULL; +static int verify_esp( + bool searching, + const char *p, + uint32_t *ret_part, + uint64_t *ret_pstart, + uint64_t *ret_psize, + sd_id128_t *ret_uuid) { + _cleanup_blkid_free_probe_ blkid_probe b = NULL; - int r; + _cleanup_free_ char *t = NULL; + uint64_t pstart = 0, psize = 0; + struct stat st, st2; const char *v, *t2; + struct statfs sfs; + sd_id128_t uuid = SD_ID128_NULL; + uint32_t part = 0; + int r; + + assert(p); + + if (statfs(p, &sfs) < 0) { + + /* If we are searching for the mount point, don't generate a log message if we can't find the path */ + if (errno == ENOENT && searching) + return -ENOENT; - if (statfs(p, &sfs) < 0) return log_error_errno(errno, "Failed to check file system type of \"%s\": %m", p); + } if (sfs.f_type != 0x4d44) { + + if (searching) + return -EADDRNOTAVAIL; + log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p); return -ENODEV; } @@ -83,6 +110,11 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t return -ENODEV; } + /* In a container we don't have access to block devices, skip this part of the verification, we trust the + * container manager set everything up correctly on its own. */ + if (detect_container() > 0) + goto finish; + r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev)); if (r < 0) return log_oom(); @@ -120,7 +152,6 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe file system type \"%s\": %m", p); } - if (!streq(v, "vfat")) { log_error("File system \"%s\" is not FAT.", p); return -ENODEV; @@ -132,7 +163,6 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition scheme \"%s\": %m", p); } - if (!streq(v, "gpt")) { log_error("File system \"%s\" is not on a GPT partition table.", p); return -ENODEV; @@ -144,7 +174,6 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition type UUID \"%s\": %m", p); } - if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) { log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p); return -ENODEV; @@ -156,8 +185,7 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition entry UUID \"%s\": %m", p); } - - r = sd_id128_from_string(v, uuid); + r = sd_id128_from_string(v, &uuid); if (r < 0) { log_error("Partition \"%s\" has invalid UUID \"%s\".", p, v); return -EIO; @@ -169,7 +197,9 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition number \"%s\": m", p); } - *part = strtoul(v, NULL, 10); + r = safe_atou32(v, &part); + if (r < 0) + return log_error_errno(r, "Failed to parse PART_ENTRY_NUMBER field."); errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL); @@ -177,7 +207,9 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition offset \"%s\": %m", p); } - *pstart = strtoul(v, NULL, 10); + r = safe_atou64(v, &pstart); + if (r < 0) + return log_error_errno(r, "Failed to parse PART_ENTRY_OFFSET field."); errno = 0; r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL); @@ -185,11 +217,50 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t r = errno ? -errno : -EIO; return log_error_errno(r, "Failed to probe partition size \"%s\": %m", p); } - *psize = strtoul(v, NULL, 10); + r = safe_atou64(v, &psize); + if (r < 0) + return log_error_errno(r, "Failed to parse PART_ENTRY_SIZE field."); + +finish: + if (ret_part) + *ret_part = part; + if (ret_pstart) + *ret_pstart = pstart; + if (ret_psize) + *ret_psize = psize; + if (ret_uuid) + *ret_uuid = uuid; return 0; } +static int find_esp(uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) { + const char *path; + int r; + + if (arg_path) + return verify_esp(false, arg_path, part, pstart, psize, uuid); + + FOREACH_STRING(path, "/efi", "/boot", "/boot/efi") { + + r = verify_esp(true, path, part, pstart, psize, uuid); + if (IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */ + continue; + if (r < 0) + return r; + + arg_path = strdup(path); + if (!arg_path) + return log_oom(); + + log_info("Using EFI System Parition at %s.", path); + return 0; + } + + log_error("Couldn't find EFI system partition. It is recommended to mount it to /boot. Alternatively, use --path= to specify path to mount point."); + return -ENOENT; +} + /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */ static int get_file_version(int fd, char **v) { struct stat st; @@ -914,7 +985,8 @@ static int install_loader_config(const char *esp_path) { return 0; } -static int help(void) { +static int help(int argc, char *argv[], void *userdata) { + printf("%s [COMMAND] [OPTIONS...]\n" "\n" "Install, update or remove the systemd-boot EFI boot manager.\n\n" @@ -948,7 +1020,7 @@ static int parse_argv(int argc, char *argv[]) { { NULL, 0, NULL, 0 } }; - int c; + int c, r; assert(argc >= 0); assert(argv); @@ -957,14 +1029,16 @@ static int parse_argv(int argc, char *argv[]) { switch (c) { case 'h': - help(); + help(0, NULL, NULL); return 0; case ARG_VERSION: return version(); case ARG_PATH: - arg_path = optarg; + r = free_and_strdup(&arg_path, optarg); + if (r < 0) + return log_oom(); break; case ARG_NO_VARIABLES: @@ -989,147 +1063,170 @@ static void read_loader_efi_var(const char *name, char **var) { log_warning_errno(r, "Failed to read EFI variable %s: %m", name); } -static int bootctl_main(int argc, char*argv[]) { - enum action { - ACTION_STATUS, - ACTION_INSTALL, - ACTION_UPDATE, - ACTION_REMOVE - } arg_action = ACTION_STATUS; - static const struct { - const char* verb; - enum action action; - } verbs[] = { - { "status", ACTION_STATUS }, - { "install", ACTION_INSTALL }, - { "update", ACTION_UPDATE }, - { "remove", ACTION_REMOVE }, - }; +static int must_be_root(void) { - sd_id128_t uuid = {}; - uint32_t part = 0; - uint64_t pstart = 0, psize = 0; - int r, q; + if (geteuid() == 0) + return 0; - if (argv[optind]) { - unsigned i; + log_error("Need to be root."); + return -EPERM; +} - for (i = 0; i < ELEMENTSOF(verbs); i++) { - if (!streq(argv[optind], verbs[i].verb)) - continue; - arg_action = verbs[i].action; - break; - } - if (i >= ELEMENTSOF(verbs)) { - log_error("Unknown operation \"%s\"", argv[optind]); - return -EINVAL; - } - } +static int verb_status(int argc, char *argv[], void *userdata) { - if (geteuid() != 0) - return log_error_errno(EPERM, "Need to be root."); + sd_id128_t uuid = SD_ID128_NULL; + int r; - r = verify_esp(arg_path, &part, &pstart, &psize, &uuid); - if (r == -ENODEV && !arg_path) - log_notice("You might want to use --path= to indicate the path to your ESP, in case it is not mounted on /boot."); + r = must_be_root(); if (r < 0) return r; - switch (arg_action) { + r = find_esp(NULL, NULL, NULL, &uuid); + if (r < 0) + return r; - case ACTION_STATUS: { + if (is_efi_boot()) { _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL; sd_id128_t loader_part_uuid = SD_ID128_NULL; - if (is_efi_boot()) { - read_loader_efi_var("LoaderFirmwareType", &fw_type); - read_loader_efi_var("LoaderFirmwareInfo", &fw_info); - read_loader_efi_var("LoaderInfo", &loader); - read_loader_efi_var("LoaderImageIdentifier", &loader_path); - if (loader_path) - efi_tilt_backslashes(loader_path); - r = efi_loader_get_device_part_uuid(&loader_part_uuid); - if (r < 0 && r != -ENOENT) - log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m"); - - printf("System:\n"); - printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info)); - - r = is_efi_secure_boot(); - if (r < 0) - log_warning_errno(r, "Failed to query secure boot status: %m"); - else - printf(" Secure Boot: %s\n", r ? "enabled" : "disabled"); + read_loader_efi_var("LoaderFirmwareType", &fw_type); + read_loader_efi_var("LoaderFirmwareInfo", &fw_info); + read_loader_efi_var("LoaderInfo", &loader); + read_loader_efi_var("LoaderImageIdentifier", &loader_path); - r = is_efi_secure_boot_setup_mode(); - if (r < 0) - log_warning_errno(r, "Failed to query secure boot mode: %m"); - else - printf(" Setup Mode: %s\n", r ? "setup" : "user"); - printf("\n"); - - printf("Loader:\n"); - printf(" Product: %s\n", strna(loader)); - if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL)) - printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", - SD_ID128_FORMAT_VAL(loader_part_uuid)); - else - printf(" Partition: n/a\n"); - printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path)); - printf("\n"); - } else - printf("System:\n Not booted with EFI\n"); - - r = status_binaries(arg_path, uuid); + if (loader_path) + efi_tilt_backslashes(loader_path); + + r = efi_loader_get_device_part_uuid(&loader_part_uuid); + if (r < 0 && r != -ENOENT) + log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m"); + + printf("System:\n"); + printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info)); + + r = is_efi_secure_boot(); if (r < 0) - return r; + log_warning_errno(r, "Failed to query secure boot status: %m"); + else + printf(" Secure Boot: %s\n", r ? "enabled" : "disabled"); - if (arg_touch_variables) - r = status_variables(); - break; - } + r = is_efi_secure_boot_setup_mode(); + if (r < 0) + log_warning_errno(r, "Failed to query secure boot mode: %m"); + else + printf(" Setup Mode: %s\n", r ? "setup" : "user"); + printf("\n"); + + printf("Loader:\n"); + printf(" Product: %s\n", strna(loader)); + if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL)) + printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + SD_ID128_FORMAT_VAL(loader_part_uuid)); + else + printf(" Partition: n/a\n"); + printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path)); + printf("\n"); + } else + printf("System:\n Not booted with EFI\n"); + + r = status_binaries(arg_path, uuid); + if (r < 0) + return r; + + if (arg_touch_variables) + r = status_variables(); + + return r; +} - case ACTION_INSTALL: - case ACTION_UPDATE: - umask(0002); +static int verb_install(int argc, char *argv[], void *userdata) { - r = install_binaries(arg_path, arg_action == ACTION_INSTALL); + sd_id128_t uuid = SD_ID128_NULL; + uint64_t pstart = 0, psize = 0; + uint32_t part = 0; + bool install; + int r; + + r = must_be_root(); + if (r < 0) + return r; + + r = find_esp(&part, &pstart, &psize, &uuid); + if (r < 0) + return r; + + install = streq(argv[0], "install"); + + RUN_WITH_UMASK(0002) { + r = install_binaries(arg_path, install); if (r < 0) return r; - if (arg_action == ACTION_INSTALL) { + if (install) { r = install_loader_config(arg_path); if (r < 0) return r; } + } + + if (arg_touch_variables) + r = install_variables(arg_path, + part, pstart, psize, uuid, + "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", + install); - if (arg_touch_variables) - r = install_variables(arg_path, - part, pstart, psize, uuid, - "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", - arg_action == ACTION_INSTALL); - break; + return r; +} - case ACTION_REMOVE: - r = remove_binaries(arg_path); +static int verb_remove(int argc, char *argv[], void *userdata) { + sd_id128_t uuid = SD_ID128_NULL; + int r; - if (arg_touch_variables) { - q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true); - if (q < 0 && r == 0) - r = q; - } - break; + r = must_be_root(); + if (r < 0) + return r; + + r = find_esp(NULL, NULL, NULL, &uuid); + if (r < 0) + return r; + + r = remove_binaries(arg_path); + + if (arg_touch_variables) { + int q; + + q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true); + if (q < 0 && r == 0) + r = q; } return r; } +static int bootctl_main(int argc, char *argv[]) { + + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, help }, + { "status", VERB_ANY, 1, VERB_DEFAULT, verb_status }, + { "install", VERB_ANY, 1, 0, verb_install }, + { "update", VERB_ANY, 1, 0, verb_install }, + { "remove", VERB_ANY, 1, 0, verb_remove }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + int main(int argc, char *argv[]) { int r; log_parse_environment(); log_open(); + /* If we run in a container, automatically turn of EFI file system access */ + if (detect_container() > 0) + arg_touch_variables = false; + r = parse_argv(argc, argv); if (r <= 0) goto finish; @@ -1137,5 +1234,6 @@ int main(int argc, char *argv[]) { r = bootctl_main(argc, argv); finish: + free(arg_path); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } -- cgit v1.2.3-54-g00ecf From 181ccb43ead439059d4302252870a77ff4441688 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 20:26:24 +0200 Subject: bootctl: make use of STRV_FOREACH() where we can --- src/boot/bootctl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 8b2407f145..d9c3897392 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -628,11 +628,11 @@ static const char *efi_subdirs[] = { }; static int create_dirs(const char *esp_path) { + const char **i; int r; - unsigned i; - for (i = 0; i < ELEMENTSOF(efi_subdirs); i++) { - r = mkdir_one(esp_path, efi_subdirs[i]); + STRV_FOREACH(i, efi_subdirs) { + r = mkdir_one(esp_path, *i); if (r < 0) return r; } @@ -836,7 +836,7 @@ static int install_variables(const char *esp_path, "Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?" : "Failed to determine current boot order: %m"); - if (first || r == false) { + if (first || r == 0) { r = efi_add_boot_option(slot, "Linux Boot Manager", part, pstart, psize, uuid, path); -- cgit v1.2.3-54-g00ecf From 617eec3452b6c906615babf61adf51275e04d41d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 20:29:21 +0200 Subject: man: use in bootctl man page where appropriate --- man/bootctl.xml | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/man/bootctl.xml b/man/bootctl.xml index 82c162ee70..3548ad12fb 100644 --- a/man/bootctl.xml +++ b/man/bootctl.xml @@ -71,19 +71,14 @@ currently installed versions of the boot loader binaries and all current EFI boot variables. - bootctl update updates all installed - versions of systemd-boot, if the current version is newer than the - version installed in the EFI system partition. This also includes - the EFI default/fallback loader at /EFI/BOOT/BOOT*.EFI. A - systemd-boot entry in the EFI boot variables is created if there - is no current entry. The created entry will be added to the end of - the boot order list. - - bootctl install installs systemd-boot into - the EFI system partition. A copy of systemd-boot will be stored as - the EFI default/fallback loader at /EFI/BOOT/BOOT*.EFI. A systemd-boot - entry in the EFI boot variables is created and added to the top - of the boot order list. + bootctl update updates all installed versions of systemd-boot, if the current version is + newer than the version installed in the EFI system partition. This also includes the EFI default/fallback loader at + /EFI/BOOT/BOOT*.EFI. A systemd-boot entry in the EFI boot variables is created if there is no + current entry. The created entry will be added to the end of the boot order list. + + bootctl install installs systemd-boot into the EFI system partition. A copy of + systemd-boot will be stored as the EFI default/fallback loader at /EFI/BOOT/BOOT*.EFI. A + systemd-boot entry in the EFI boot variables is created and added to the top of the boot order list. bootctl remove removes all installed versions of systemd-boot from the EFI system partition, and removes -- cgit v1.2.3-54-g00ecf From fdc1af0a8ac1801a32192d2ad5d7e1245cecc34b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 20:30:16 +0200 Subject: man: add missing whitespace to bootctl command lines --- man/bootctl.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/man/bootctl.xml b/man/bootctl.xml index 3548ad12fb..e2575a4751 100644 --- a/man/bootctl.xml +++ b/man/bootctl.xml @@ -47,16 +47,16 @@ - bootctl OPTIONSstatus + bootctl OPTIONS status - bootctl OPTIONSupdate + bootctl OPTIONS update - bootctl OPTIONSinstall + bootctl OPTIONS install - bootctl OPTIONSremove + bootctl OPTIONS remove -- cgit v1.2.3-54-g00ecf From 846b8fc30d52a63dd6a010e497aa80164fea31d8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 20:43:54 +0200 Subject: bootctl: move toupper() implementation to string-util.h We already have tolower() calls there, hence let's unify this at one place. Also, update the code to only use ASCII operations, so that we don't end up being locale dependant. --- src/basic/string-util.c | 19 +++++++++++++++++++ src/basic/string-util.h | 3 +++ src/boot/bootctl.c | 11 +---------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/basic/string-util.c b/src/basic/string-util.c index 293a15f9c0..e9856b90d3 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -323,6 +323,14 @@ char ascii_tolower(char x) { return x; } +char ascii_toupper(char x) { + + if (x >= 'a' && x <= 'z') + return x - 'a' + 'A'; + + return x; +} + char *ascii_strlower(char *t) { char *p; @@ -334,6 +342,17 @@ char *ascii_strlower(char *t) { return t; } +char *ascii_strupper(char *t) { + char *p; + + assert(t); + + for (p = t; *p; p++) + *p = ascii_toupper(*p); + + return t; +} + char *ascii_strlower_n(char *t, size_t n) { size_t i; diff --git a/src/basic/string-util.h b/src/basic/string-util.h index 1209e1e2e1..b75aba63c2 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -137,6 +137,9 @@ char ascii_tolower(char x); char *ascii_strlower(char *s); char *ascii_strlower_n(char *s, size_t n); +char ascii_toupper(char x); +char *ascii_strupper(char *s); + int ascii_strcasecmp_n(const char *a, const char *b, size_t n); int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m); diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index d9c3897392..5c3e7a04a0 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -597,15 +597,6 @@ error: return r; } -static char* strupper(char *s) { - char *p; - - for (p = s; *p; p++) - *p = toupper(*p); - - return s; -} - static int mkdir_one(const char *prefix, const char *suffix) { char *p; @@ -654,7 +645,7 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) { /* Create the EFI default boot loader name (specified for removable devices) */ v = strjoina(esp_path, "/EFI/BOOT/BOOT", name + strlen("systemd-boot")); - strupper(strrchr(v, '/') + 1); + ascii_strupper(strrchr(v, '/') + 1); k = copy_file(p, v, force); if (k < 0 && r == 0) -- cgit v1.2.3-54-g00ecf From 5fa6c13c7bd6df488c0585608688a5feb8a03d5d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 20:45:10 +0200 Subject: bootctl: use F_TYPE_EQUAL() to compare statfs' .f_type field After all, the field is kinda borked. --- src/boot/bootctl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 5c3e7a04a0..9a24ecd6b2 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,7 @@ #include "util.h" #include "verbs.h" #include "virt.h" +#include "stat-util.h" static char *arg_path = NULL; static bool arg_touch_variables = true; @@ -83,7 +85,7 @@ static int verify_esp( return log_error_errno(errno, "Failed to check file system type of \"%s\": %m", p); } - if (sfs.f_type != 0x4d44) { + if (!F_TYPE_EQUAL(sfs.f_type, MSDOS_SUPER_MAGIC)) { if (searching) return -EADDRNOTAVAIL; -- cgit v1.2.3-54-g00ecf From db6d9faeb0179b15cf29e87bd20d29d6210142ef Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 20:46:17 +0200 Subject: bootctl: clean up get_file_version() Make sure that we always initialize the return parameter on success, and that all errors result in an error message, not just some. --- src/boot/bootctl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 9a24ecd6b2..ff14cff166 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -275,14 +275,16 @@ static int get_file_version(int fd, char **v) { assert(v); if (fstat(fd, &st) < 0) - return -errno; + return log_error_errno(errno, "Failed to stat EFI binary: %m"); - if (st.st_size < 27) + if (st.st_size < 27) { + *v = NULL; return 0; + } buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (buf == MAP_FAILED) - return -errno; + return log_error_errno(errno, "Failed to memory map EFI binary: %m"); s = memmem(buf, st.st_size - 8, "#### LoaderInfo: ", 17); if (!s) @@ -304,7 +306,7 @@ static int get_file_version(int fd, char **v) { r = 1; finish: - munmap(buf, st.st_size); + (void) munmap(buf, st.st_size); *v = x; return r; } -- cgit v1.2.3-54-g00ecf From f939cff715775553bb1ec903454acf0d95bf5023 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 20:47:09 +0200 Subject: bootctl: various coding style updates --- src/boot/bootctl.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index ff14cff166..9cbea5041e 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -416,9 +416,10 @@ static int status_variables(void) { n_options = efi_get_boot_options(&options); if (n_options == -ENOENT) - return log_error_errno(ENOENT, "Failed to access EFI variables, efivarfs" + return log_error_errno(n_options, + "Failed to access EFI variables, efivarfs" " needs to be available at /sys/firmware/efi/efivars/."); - else if (n_options < 0) + if (n_options < 0) return log_error_errno(n_options, "Failed to read EFI boot entries: %m"); n_order = efi_get_boot_order(&order); @@ -438,11 +439,9 @@ static int status_variables(void) { for (j = 0; j < n_order; j++) if (options[i] == order[j]) - goto next; + continue; print_efi_option(options[i], false); - next: - continue; } return 0; @@ -820,8 +819,8 @@ static int install_variables(const char *esp_path, if (access(p, F_OK) < 0) { if (errno == ENOENT) return 0; - else - return log_error_errno(errno, "Cannot access \"%s\": %m", p); + + return log_error_errno(errno, "Cannot access \"%s\": %m", p); } r = find_slot(uuid, path, &slot); @@ -941,8 +940,8 @@ static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) { if (in_order) return remove_from_order(slot); - else - return 0; + + return 0; } static int install_loader_config(const char *esp_path) { -- cgit v1.2.3-54-g00ecf From d5ff6d6d341d56de725633a38e23778e58140b9e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 20:48:22 +0200 Subject: bootctl: modernize install_loader_config() let's the proper APIs to read the machine ID, and properly check for all errors. --- src/boot/bootctl.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 9cbea5041e..f0a88ab3ac 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -945,36 +945,28 @@ static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) { } static int install_loader_config(const char *esp_path) { - char *p; - char line[64]; - char *machine = NULL; - _cleanup_fclose_ FILE *f = NULL, *g = NULL; - f = fopen("/etc/machine-id", "re"); - if (!f) - return errno == ENOENT ? 0 : -errno; + _cleanup_fclose_ FILE *f = NULL; + char machine_string[SD_ID128_STRING_MAX]; + sd_id128_t machine_id; + const char *p; + int r; - if (fgets(line, sizeof(line), f) != NULL) { - char *s; + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return log_error_errno(r, "Failed to get machine did: %m"); - s = strchr(line, '\n'); - if (s) - s[0] = '\0'; - if (strlen(line) == 32) - machine = line; - } + p = strjoina(esp_path, "/loader/loader.conf"); + f = fopen(p, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to open loader.conf for writing: %m"); - if (!machine) - return -ESRCH; + fprintf(f, "#timeout 3\n"); + fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string)); - p = strjoina(esp_path, "/loader/loader.conf"); - g = fopen(p, "wxe"); - if (g) { - fprintf(g, "#timeout 3\n"); - fprintf(g, "default %s-*\n", machine); - if (ferror(g)) - return log_error_errno(EIO, "Failed to write \"%s\": %m", p); - } + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write \"%s\": %m", p); return 0; } -- cgit v1.2.3-54-g00ecf From 5b8411a2aa2d986a0c7e995c57d01ed6e56e74da Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 19 Jul 2016 21:08:57 +0200 Subject: kernel-install: when searching for location to place kernel consider /efi With this change kernel-install will now first look for an existing kernel installation in /efi, /boot and /boot/efi. If none is found, /efi is used if it is a mount point, otherwise /boot/efi if it is one. If nothing of that worked /boot is used without further checking. This means /boot should be the default unless something was installed before or something else was explicitly mounted. --- src/kernel-install/kernel-install | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install index 1159dc384d..c66bcfc092 100644 --- a/src/kernel-install/kernel-install +++ b/src/kernel-install/kernel-install @@ -86,10 +86,15 @@ if [[ ! $COMMAND ]] || [[ ! $KERNEL_VERSION ]]; then exit 1 fi -if [[ -d /boot/loader/entries ]] || [[ -d /boot/$MACHINE_ID ]]; then +if [[ -d /efi/loader/entries ]] || [[ -d /efi/$MACHINE_ID ]]; then + BOOT_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION" +elif [[ -d /boot/loader/entries ]] || [[ -d /boot/$MACHINE_ID ]]; then BOOT_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION" -elif [[ -d /boot/efi/loader/entries ]] || [[ -d /boot/efi/$MACHINE_ID ]] \ - || mountpoint -q /boot/efi; then +elif [[ -d /boot/efi/loader/entries ]] || [[ -d /boot/efi/$MACHINE_ID ]]; then + BOOT_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION" +elif mountpoint -q /efi; then + BOOT_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION" +elif mountpoint -q /boot/efi; then BOOT_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION" else BOOT_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION" -- cgit v1.2.3-54-g00ecf From 7ba25ab5616339a8340117b85cbecd061c52d8cc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 21 Jul 2016 11:30:02 +0200 Subject: gpt-generator: relax EFI check a bit Previously, we'd not mount the ESP except on EFI boots, and only when the ESP used for booting matches the ESP we found. With this change on non-EFI boots we'll mount a discovered ESP anyway, and on EFI boots we'll only mount it if it matches the ESP we booted from. --- src/gpt-auto-generator/gpt-auto-generator.c | 107 ++++++++++++++-------------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index dede86eabf..e4c913f2c4 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -450,19 +450,11 @@ static int add_automount( } static int add_boot(const char *what) { - _cleanup_blkid_free_probe_ blkid_probe b = NULL; - const char *fstype = NULL, *uuid = NULL; - sd_id128_t id, type_id; const char *esp; int r; assert(what); - if (!is_efi_boot()) { - log_debug("Not an EFI boot, ignoring the ESP."); - return 0; - } - if (in_initrd()) { log_debug("In initrd, ignoring the ESP."); return 0; @@ -487,58 +479,67 @@ static int add_boot(const char *what) { return 0; } - r = efi_loader_get_device_part_uuid(&id); - if (r == -ENOENT) { - log_debug("EFI loader partition unknown."); - return 0; - } - if (r < 0) { - log_error_errno(r, "Failed to read ESP partition UUID: %m"); - return r; - } + if (is_efi_boot()) { + _cleanup_blkid_free_probe_ blkid_probe b = NULL; + const char *fstype = NULL, *uuid_string = NULL; + sd_id128_t loader_uuid, part_uuid; - errno = 0; - b = blkid_new_probe_from_filename(what); - if (!b) { - if (errno == 0) - return log_oom(); - return log_error_errno(errno, "Failed to allocate prober: %m"); - } + /* If this is an EFI boot, be extra careful, and only mount the ESP if it was the ESP used for booting. */ - blkid_probe_enable_partitions(b, 1); - blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); + r = efi_loader_get_device_part_uuid(&loader_uuid); + if (r == -ENOENT) { + log_debug("EFI loader partition unknown."); + return 0; + } + if (r < 0) { + log_error_errno(r, "Failed to read ESP partition UUID: %m"); + return r; + } - errno = 0; - r = blkid_do_safeprobe(b); - if (r == -2 || r == 1) /* no result or uncertain */ - return 0; - else if (r != 0) - return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what); + errno = 0; + b = blkid_new_probe_from_filename(what); + if (!b) { + if (errno == 0) + return log_oom(); + return log_error_errno(errno, "Failed to allocate prober: %m"); + } - (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); - if (!streq_ptr(fstype, "vfat")) { - log_debug("Partition for %s is not a FAT filesystem, ignoring.", esp); - return 0; - } + blkid_probe_enable_partitions(b, 1); + blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); - errno = 0; - r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid, NULL); - if (r != 0) { - log_debug_errno(errno, "Partition for %s does not have a UUID, ignoring.", esp); - return 0; - } + errno = 0; + r = blkid_do_safeprobe(b); + if (r == -2 || r == 1) /* no result or uncertain */ + return 0; + else if (r != 0) + return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what); - if (sd_id128_from_string(uuid, &type_id) < 0) { - log_debug("Partition for %s does not have a valid UUID, ignoring.", esp); - return 0; - } + (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); + if (!streq_ptr(fstype, "vfat")) { + log_debug("Partition for %s is not a FAT filesystem, ignoring.", esp); + return 0; + } - if (!sd_id128_equal(type_id, id)) { - log_debug("Partition for %s does not appear to be the partition we are booted from.", esp); - return 0; - } + errno = 0; + r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid_string, NULL); + if (r != 0) { + log_debug_errno(errno, "Partition for %s does not have a UUID, ignoring.", esp); + return 0; + } - r = add_automount("boot", + if (sd_id128_from_string(uuid_string, &part_uuid) < 0) { + log_debug("Partition for %s does not have a valid UUID, ignoring.", esp); + return 0; + } + + if (!sd_id128_equal(part_uuid, loader_uuid)) { + log_debug("Partition for %s does not appear to be the partition we are booted from.", esp); + return 0; + } + } else + log_debug("Not an EFI boot, skipping ESP check."); + + return add_automount("boot", what, esp, "vfat", @@ -546,8 +547,6 @@ static int add_boot(const char *what) { "umask=0077", "EFI System Partition Automount", 120 * USEC_PER_SEC); - - return r; } #else static int add_boot(const char *what) { -- cgit v1.2.3-54-g00ecf From e4631b48e17e63a3859456df639482063a0276fd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 14 Jul 2016 12:23:39 +0200 Subject: sysusers: move various user credential validity checks to src/basic/ This way we can reuse them for validating User=/Group= settings in unit files (to be added in a later commit). Also, add some tests for them. --- src/basic/user-util.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ src/basic/user-util.h | 5 +++ src/sysusers/sysusers.c | 75 -------------------------------------- src/test/test-user-util.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+), 75 deletions(-) diff --git a/src/basic/user-util.c b/src/basic/user-util.c index e9d668ddfc..122d9a0c7c 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "missing.h" #include "alloc-util.h" @@ -39,6 +40,7 @@ #include "path-util.h" #include "string-util.h" #include "user-util.h" +#include "utf8.h" bool uid_is_valid(uid_t uid) { @@ -479,3 +481,94 @@ int take_etc_passwd_lock(const char *root) { return fd; } + +bool valid_user_group_name(const char *u) { + const char *i; + long sz; + + /* Checks if the specified name is a valid user/group name. */ + + if (isempty(u)) + return false; + + if (!(u[0] >= 'a' && u[0] <= 'z') && + !(u[0] >= 'A' && u[0] <= 'Z') && + u[0] != '_') + return false; + + for (i = u+1; *i; i++) { + if (!(*i >= 'a' && *i <= 'z') && + !(*i >= 'A' && *i <= 'Z') && + !(*i >= '0' && *i <= '9') && + *i != '_' && + *i != '-') + return false; + } + + sz = sysconf(_SC_LOGIN_NAME_MAX); + assert_se(sz > 0); + + if ((size_t) (i-u) > (size_t) sz) + return false; + + if ((size_t) (i-u) > UT_NAMESIZE - 1) + return false; + + return true; +} + +bool valid_user_group_name_or_id(const char *u) { + + /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the right + * range, and not the invalid user ids. */ + + if (isempty(u)) + return false; + + if (valid_user_group_name(u)) + return true; + + return parse_uid(u, NULL) >= 0; +} + +bool valid_gecos(const char *d) { + + if (!d) + return false; + + if (!utf8_is_valid(d)) + return false; + + if (string_has_cc(d, NULL)) + return false; + + /* Colons are used as field separators, and hence not OK */ + if (strchr(d, ':')) + return false; + + return true; +} + +bool valid_home(const char *p) { + + if (isempty(p)) + return false; + + if (!utf8_is_valid(p)) + return false; + + if (string_has_cc(p, NULL)) + return false; + + if (!path_is_absolute(p)) + return false; + + if (!path_is_safe(p)) + return false; + + /* Colons are used as field separators, and hence not OK */ + if (strchr(p, ':')) + return false; + + return true; +} diff --git a/src/basic/user-util.h b/src/basic/user-util.h index 8026eca3f4..36f71fb004 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -68,3 +68,8 @@ int take_etc_passwd_lock(const char *root); static inline bool userns_supported(void) { return access("/proc/self/uid_map", F_OK) >= 0; } + +bool valid_user_group_name(const char *u); +bool valid_user_group_name_or_id(const char *u); +bool valid_gecos(const char *d); +bool valid_home(const char *p); diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 787d68a009..5d72493725 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -1299,81 +1299,6 @@ static bool item_equal(Item *a, Item *b) { return true; } -static bool valid_user_group_name(const char *u) { - const char *i; - long sz; - - if (isempty(u)) - return false; - - if (!(u[0] >= 'a' && u[0] <= 'z') && - !(u[0] >= 'A' && u[0] <= 'Z') && - u[0] != '_') - return false; - - for (i = u+1; *i; i++) { - if (!(*i >= 'a' && *i <= 'z') && - !(*i >= 'A' && *i <= 'Z') && - !(*i >= '0' && *i <= '9') && - *i != '_' && - *i != '-') - return false; - } - - sz = sysconf(_SC_LOGIN_NAME_MAX); - assert_se(sz > 0); - - if ((size_t) (i-u) > (size_t) sz) - return false; - - if ((size_t) (i-u) > UT_NAMESIZE - 1) - return false; - - return true; -} - -static bool valid_gecos(const char *d) { - - if (!d) - return false; - - if (!utf8_is_valid(d)) - return false; - - if (string_has_cc(d, NULL)) - return false; - - /* Colons are used as field separators, and hence not OK */ - if (strchr(d, ':')) - return false; - - return true; -} - -static bool valid_home(const char *p) { - - if (isempty(p)) - return false; - - if (!utf8_is_valid(p)) - return false; - - if (string_has_cc(p, NULL)) - return false; - - if (!path_is_absolute(p)) - return false; - - if (!path_is_safe(p)) - return false; - - /* Colons are used as field separators, and hence not OK */ - if (strchr(p, ':')) - return false; - - return true; -} - static int parse_line(const char *fname, unsigned line, const char *buffer) { static const Specifier specifier_table[] = { diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c index 8d1ec19f17..2a344a9f93 100644 --- a/src/test/test-user-util.c +++ b/src/test/test-user-util.c @@ -61,6 +61,88 @@ static void test_uid_ptr(void) { assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000); } +static void test_valid_user_group_name(void) { + assert_se(!valid_user_group_name(NULL)); + assert_se(!valid_user_group_name("")); + assert_se(!valid_user_group_name("1")); + assert_se(!valid_user_group_name("65535")); + assert_se(!valid_user_group_name("-1")); + assert_se(!valid_user_group_name("-kkk")); + assert_se(!valid_user_group_name("rööt")); + assert_se(!valid_user_group_name(".")); + assert_se(!valid_user_group_name("eff.eff")); + assert_se(!valid_user_group_name("foo\nbar")); + assert_se(!valid_user_group_name("0123456789012345678901234567890123456789")); + assert_se(!valid_user_group_name_or_id("aaa:bbb")); + + assert_se(valid_user_group_name("root")); + assert_se(valid_user_group_name("lennart")); + assert_se(valid_user_group_name("LENNART")); + assert_se(valid_user_group_name("_kkk")); + assert_se(valid_user_group_name("kkk-")); + assert_se(valid_user_group_name("kk-k")); + + assert_se(valid_user_group_name("some5")); + assert_se(!valid_user_group_name("5some")); + assert_se(valid_user_group_name("INNER5NUMBER")); +} + +static void test_valid_user_group_name_or_id(void) { + assert_se(!valid_user_group_name_or_id(NULL)); + assert_se(!valid_user_group_name_or_id("")); + assert_se(valid_user_group_name_or_id("0")); + assert_se(valid_user_group_name_or_id("1")); + assert_se(valid_user_group_name_or_id("65534")); + assert_se(!valid_user_group_name_or_id("65535")); + assert_se(valid_user_group_name_or_id("65536")); + assert_se(!valid_user_group_name_or_id("-1")); + assert_se(!valid_user_group_name_or_id("-kkk")); + assert_se(!valid_user_group_name_or_id("rööt")); + assert_se(!valid_user_group_name_or_id(".")); + assert_se(!valid_user_group_name_or_id("eff.eff")); + assert_se(!valid_user_group_name_or_id("foo\nbar")); + assert_se(!valid_user_group_name_or_id("0123456789012345678901234567890123456789")); + assert_se(!valid_user_group_name_or_id("aaa:bbb")); + + assert_se(valid_user_group_name_or_id("root")); + assert_se(valid_user_group_name_or_id("lennart")); + assert_se(valid_user_group_name_or_id("LENNART")); + assert_se(valid_user_group_name_or_id("_kkk")); + assert_se(valid_user_group_name_or_id("kkk-")); + assert_se(valid_user_group_name_or_id("kk-k")); + + assert_se(valid_user_group_name_or_id("some5")); + assert_se(!valid_user_group_name_or_id("5some")); + assert_se(valid_user_group_name_or_id("INNER5NUMBER")); +} + +static void test_valid_gecos(void) { + + assert_se(!valid_gecos(NULL)); + assert_se(valid_gecos("")); + assert_se(valid_gecos("test")); + assert_se(valid_gecos("Ümläüt")); + assert_se(!valid_gecos("In\nvalid")); + assert_se(!valid_gecos("In:valid")); +} + +static void test_valid_home(void) { + + assert_se(!valid_home(NULL)); + assert_se(!valid_home("")); + assert_se(!valid_home(".")); + assert_se(!valid_home("/home/..")); + assert_se(!valid_home("/home/../")); + assert_se(!valid_home("/home\n/foo")); + assert_se(!valid_home("./piep")); + assert_se(!valid_home("piep")); + assert_se(!valid_home("/home/user:lennart")); + + assert_se(valid_home("/")); + assert_se(valid_home("/home")); + assert_se(valid_home("/home/foo")); +} + int main(int argc, char*argv[]) { test_uid_to_name_one(0, "root"); @@ -75,5 +157,10 @@ int main(int argc, char*argv[]) { test_parse_uid(); test_uid_ptr(); + test_valid_user_group_name(); + test_valid_user_group_name_or_id(); + test_valid_gecos(); + test_valid_home(); + return 0; } -- cgit v1.2.3-54-g00ecf From 66dccd8d85aac9f029c626aac8d2b7e58d239b47 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 14 Jul 2016 12:28:06 +0200 Subject: core: be stricter when parsing User=/Group= fields Let's verify the validity of the syntax of the user/group names set. --- src/core/load-fragment-gperf.gperf.m4 | 10 +-- src/core/load-fragment.c | 118 ++++++++++++++++++++++++++++++++++ src/core/load-fragment.h | 2 + 3 files changed, 125 insertions(+), 5 deletions(-) diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 6a5c16a000..7f7c2fe185 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -19,9 +19,9 @@ m4_dnl Define the context options only once m4_define(`EXEC_CONTEXT_CONFIG_ITEMS', `$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context) $1.RootDirectory, config_parse_unit_path_printf, 0, offsetof($1, exec_context.root_directory) -$1.User, config_parse_unit_string_printf, 0, offsetof($1, exec_context.user) -$1.Group, config_parse_unit_string_printf, 0, offsetof($1, exec_context.group) -$1.SupplementaryGroups, config_parse_strv, 0, offsetof($1, exec_context.supplementary_groups) +$1.User, config_parse_user_group, 0, offsetof($1, exec_context.user) +$1.Group, config_parse_user_group, 0, offsetof($1, exec_context.group) +$1.SupplementaryGroups, config_parse_user_group_strv, 0, offsetof($1, exec_context.supplementary_groups) $1.Nice, config_parse_exec_nice, 0, offsetof($1, exec_context) $1.OOMScoreAdjust, config_parse_exec_oom_score_adjust, 0, offsetof($1, exec_context) $1.IOSchedulingClass, config_parse_exec_io_class, 0, offsetof($1, exec_context) @@ -285,8 +285,8 @@ Socket.ExecStartPost, config_parse_exec, SOCKET_EXEC Socket.ExecStopPre, config_parse_exec, SOCKET_EXEC_STOP_PRE, offsetof(Socket, exec_command) Socket.ExecStopPost, config_parse_exec, SOCKET_EXEC_STOP_POST, offsetof(Socket, exec_command) Socket.TimeoutSec, config_parse_sec, 0, offsetof(Socket, timeout_usec) -Socket.SocketUser, config_parse_unit_string_printf, 0, offsetof(Socket, user) -Socket.SocketGroup, config_parse_unit_string_printf, 0, offsetof(Socket, group) +Socket.SocketUser, config_parse_user_group, 0, offsetof(Socket, user) +Socket.SocketGroup, config_parse_user_group, 0, offsetof(Socket, group) Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode) Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode) Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 782e420e4c..d8aaf4ef40 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -64,6 +64,7 @@ #include "unit-name.h" #include "unit-printf.h" #include "unit.h" +#include "user-util.h" #include "utf8.h" #include "web-util.h" @@ -1763,6 +1764,123 @@ int config_parse_sec_fix_0( return 0; } +int config_parse_user_group( + 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) { + + char **user = data, *n; + Unit *u = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + if (isempty(rvalue)) + n = NULL; + else { + _cleanup_free_ char *k = NULL; + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); + return 0; + } + + if (!valid_user_group_name_or_id(k)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID, ignoring: %s", k); + return 0; + } + + n = k; + k = NULL; + } + + free(*user); + *user = n; + + return 0; +} + +int config_parse_user_group_strv( + 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) { + + char ***users = data; + Unit *u = userdata; + const char *p; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + if (isempty(rvalue)) { + char **empty; + + empty = new0(char*, 1); + if (!empty) + return log_oom(); + + strv_free(*users); + *users = empty; + + return 0; + } + + p = rvalue; + for (;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&p, &word, WHITESPACE, 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + break; + } + + r = unit_full_printf(u, word, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word); + continue; + } + + if (!valid_user_group_name_or_id(k)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID, ignoring: %s", k); + continue; + } + + r = strv_push(users, k); + if (r < 0) + return log_oom(); + + k = NULL; + } + + return 0; +} + int config_parse_busname_service( const char *unit, const char *filename, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index b36a2e3a02..213bce55a7 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -111,6 +111,8 @@ int config_parse_exec_utmp_mode(const char *unit, const char *filename, unsigned int config_parse_working_directory(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_fdname(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_sec_fix_0(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_user_group(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_user_group_strv(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); /* gperf prototypes */ const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length); -- cgit v1.2.3-54-g00ecf From 29206d4619843252c2e04f20dc03c246547600a2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 14 Jul 2016 12:37:28 +0200 Subject: core: add a concept of "dynamic" user ids, that are allocated as long as a service is running This adds a new boolean setting DynamicUser= to service files. If set, a new user will be allocated dynamically when the unit is started, and released when it is stopped. The user ID is allocated from the range 61184..65519. The user will not be added to /etc/passwd (but an NSS module to be added later should make it show up in getent passwd). For now, care should be taken that the service writes no files to disk, since this might result in files owned by UIDs that might get assigned dynamically to a different service later on. Later patches will tighten sandboxing in order to ensure that this cannot happen, except for a few selected directories. A simple way to test this is: systemd-run -p DynamicUser=1 /bin/sleep 99999 --- Makefile.am | 2 + man/systemd.exec.xml | 36 +- src/basic/socket-util.c | 14 + src/basic/socket-util.h | 2 + src/core/dbus-execute.c | 6 +- src/core/dbus-manager.c | 60 ++- src/core/dynamic-user.c | 763 ++++++++++++++++++++++++++++++ src/core/dynamic-user.h | 66 +++ src/core/execute.c | 75 ++- src/core/execute.h | 6 + src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/manager.c | 18 +- src/core/manager.h | 3 + src/core/mount.c | 15 +- src/core/mount.h | 3 +- src/core/service.c | 16 +- src/core/service.h | 1 + src/core/socket.c | 15 +- src/core/socket.h | 2 + src/core/swap.c | 15 +- src/core/swap.h | 1 + src/core/unit.c | 63 +++ src/core/unit.h | 5 + src/libsystemd/sd-bus/bus-common-errors.c | 1 + src/libsystemd/sd-bus/bus-common-errors.h | 1 + src/shared/bus-unit-util.c | 11 +- 26 files changed, 1166 insertions(+), 35 deletions(-) create mode 100644 src/core/dynamic-user.c create mode 100644 src/core/dynamic-user.h diff --git a/Makefile.am b/Makefile.am index c9fb4917ad..3d5ce1e2c3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1197,6 +1197,8 @@ libcore_la_SOURCES = \ src/core/load-dropin.h \ src/core/execute.c \ src/core/execute.h \ + src/core/dynamic-user.c \ + src/core/dynamic-user.h \ src/core/kill.c \ src/core/kill.h \ src/core/dbus.c \ diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 49fea98a95..bfb4101d99 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -143,10 +143,38 @@ User= Group= - Sets the Unix user or group that the processes - are executed as, respectively. Takes a single user or group - name or ID as argument. If no group is set, the default group - of the user is chosen. These do not affect commands prefixed with !. + Set the UNIX user or group that the processes are executed as, respectively. Takes a single + user or group name, or numeric ID as argument. If no group is set, the default group of the user is used. This + setting does not affect commands whose command line is prefixed with !. + + + + DynamicUser= + + Takes a boolean parameter. If set, a UNIX user and group pair is allocated dynamically when the + unit is started, and released as soon as it is stopped. The user and group will not be added to + /etc/passwd or /etc/group, but are managed transiently during + runtime. The nss-systemd8 + glibc NSS module provides integration of these dynamic users/groups into the system's user and group + databases. The user and group name to use may be configured via User= and + Group= (see above). If these options are not used and dynamic user/group allocation is + enabled for a unit, the name of the dynamic user/group is implicitly derived from the unit name. If the unit + name without the type suffix qualifies as valid user name it is used directly, otherwise a name incorporating a + hash of it is used. If a statically allocated user or group of the configured name already exists, it is used + and no dynamic user/group is allocated. Dynamic users/groups are allocated from the UID/GID range + 61184…65519. It is recommended to avoid this range for regular system or login users. At any point in time + each UID/GID from this range is only assigned to zero or one dynamically allocated users/groups in + use. However, UID/GIDs are recycled after a unit is terminated. Care should be taken that any processes running + as part of a unit for which dynamic users/groups are enabled do not leave files or directories owned by these + users/groups around, as a different unit might get the same UID/GID assigned later on, and thus gain access to + these files or directories. If DynamicUser= is enabled, PrivateTmp= is + implied. This ensures that the lifetime of temporary files created by the executed processes is bound to the + runtime of the service, and hence the lifetime of the dynamic user/group. Since /tmp and + /var/tmp are usually the only world-writable directories on a system this ensures that a + unit making use of dynamic user/group allocation cannot leave files around after unit termination. Use + RuntimeDirectory= (see below) in order to assign a writable runtime directory to a service, + owned by the dynamic user/group and removed automatically when the unit is terminated. Defaults to + off. diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 385c3e4df3..6093e47172 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1046,3 +1046,17 @@ int flush_accept(int fd) { close(cfd); } } + +struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) { + struct cmsghdr *cmsg; + + assert(mh); + + CMSG_FOREACH(cmsg, mh) + if (cmsg->cmsg_level == level && + cmsg->cmsg_type == type && + (length == (socklen_t) -1 || length == cmsg->cmsg_len)) + return cmsg; + + return NULL; +} diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index e9230e4a9f..2536b085f9 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -142,6 +142,8 @@ int flush_accept(int fd); #define CMSG_FOREACH(cmsg, mh) \ for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) +struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length); + /* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */ #define SOCKADDR_UN_LEN(sa) \ ({ \ diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 307c3d8e7a..a6896c6e6c 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -693,6 +693,7 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), @@ -1061,7 +1062,8 @@ int bus_exec_context_set_transient_property( } else if (STR_IN_SET(name, "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "PrivateTmp", "PrivateDevices", "PrivateNetwork", - "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute", "RestrictRealtime")) { + "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute", + "RestrictRealtime", "DynamicUser")) { int b; r = sd_bus_message_read(message, "b", &b); @@ -1089,6 +1091,8 @@ int bus_exec_context_set_transient_property( c->memory_deny_write_execute = b; else if (streq(name, "RestrictRealtime")) c->restrict_realtime = b; + else if (streq(name, "DynamicUser")) + c->dynamic_user = b; unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, yes_no(b)); } diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index d05968bd65..ef05a75a8b 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -43,6 +43,7 @@ #include "string-util.h" #include "strv.h" #include "syslog-util.h" +#include "user-util.h" #include "virt.h" #include "watchdog.h" @@ -1511,8 +1512,8 @@ static int method_unset_and_set_environment(sd_bus_message *message, void *userd } static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_error *error) { - uint8_t code; Manager *m = userdata; + uint8_t code; int r; assert(message); @@ -1534,6 +1535,61 @@ static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_ return sd_bus_reply_method_return(message, NULL); } +static int method_lookup_dynamic_user_by_name(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + uid_t uid; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read_basic(message, 's', &name); + if (r < 0) + return r; + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance."); + if (!valid_user_group_name(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User name invalid: %s", name); + + r = dynamic_user_lookup_name(m, name, &uid); + if (r == -ESRCH) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER, "Dynamic user %s does not exist.", name); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "u", (uint32_t) uid); +} + +static int method_lookup_dynamic_user_by_uid(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *name = NULL; + Manager *m = userdata; + uid_t uid; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(uid) == sizeof(uint32_t)); + r = sd_bus_message_read_basic(message, 'u', &uid); + if (r < 0) + return r; + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance."); + if (!uid_is_valid(uid)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User ID invalid: " UID_FMT, uid); + + r = dynamic_user_lookup_uid(m, uid, &name); + if (r == -ESRCH) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER, "Dynamic user ID " UID_FMT " does not exist.", uid); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "s", name); +} + static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states, char **patterns) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; @@ -2199,6 +2255,8 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetExitCode", "y", NULL, method_set_exit_code, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("LookupDynamicUserByName", "s", "u", method_lookup_dynamic_user_by_name, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("LookupDynamicUserByUID", "u", "s", method_lookup_dynamic_user_by_uid, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("UnitNew", "so", 0), SD_BUS_SIGNAL("UnitRemoved", "so", 0), diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c new file mode 100644 index 0000000000..8035bee231 --- /dev/null +++ b/src/core/dynamic-user.c @@ -0,0 +1,763 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "dynamic-user.h" +#include "fd-util.h" +#include "fs-util.h" +#include "parse-util.h" +#include "random-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "user-util.h" +#include "fileio.h" + +/* Let's pick a UIDs within the 16bit range, so that we are compatible with containers using 16bit user namespacing. At + * least on Fedora normal users are allocated until UID 60000, hence do not allocate from below this. Also stay away + * from the upper end of the range as that is often used for overflow/nobody users. */ +#define UID_PICK_MIN ((uid_t) UINT32_C(0x0000EF00)) +#define UID_PICK_MAX ((uid_t) UINT32_C(0x0000FFEF)) + +/* Takes a value generated randomly or by hashing and turns it into a UID in the right range */ +#define UID_CLAMP_INTO_RANGE(rnd) (((uid_t) (rnd) % (UID_PICK_MAX - UID_PICK_MIN + 1)) + UID_PICK_MIN) + +static DynamicUser* dynamic_user_free(DynamicUser *d) { + if (!d) + return NULL; + + if (d->manager) + (void) hashmap_remove(d->manager->dynamic_users, d->name); + + safe_close_pair(d->storage_socket); + free(d); + + return NULL; +} + +static int dynamic_user_add(Manager *m, const char *name, int storage_socket[2], DynamicUser **ret) { + DynamicUser *d = NULL; + int r; + + assert(m); + assert(name); + assert(storage_socket); + + r = hashmap_ensure_allocated(&m->dynamic_users, &string_hash_ops); + if (r < 0) + return r; + + d = malloc0(offsetof(DynamicUser, name) + strlen(name) + 1); + if (!d) + return -ENOMEM; + + strcpy(d->name, name); + + d->storage_socket[0] = storage_socket[0]; + d->storage_socket[1] = storage_socket[1]; + + r = hashmap_put(m->dynamic_users, d->name, d); + if (r < 0) { + free(d); + return r; + } + + d->manager = m; + + if (ret) + *ret = d; + + return 0; +} + +int dynamic_user_acquire(Manager *m, const char *name, DynamicUser** ret) { + _cleanup_close_pair_ int storage_socket[2] = { -1, -1 }; + DynamicUser *d; + int r; + + assert(m); + assert(name); + + /* Return the DynamicUser structure for a specific user name. Note that this won't actually allocate a UID for + * it, but just prepare the data structure for it. The UID is allocated only on demand, when it's really + * needed, and in the child process we fork off, since allocation involves NSS checks which are not OK to do + * from PID 1. To allow the children and PID 1 share information about allocated UIDs we use an anonymous + * AF_UNIX/SOCK_DGRAM socket (called the "storage socket") that contains at most one datagram with the + * allocated UID number, plus an fd referencing the lock file for the UID + * (i.e. /run/systemd/dynamic-uid/$UID). Why involve the socket pair? So that PID 1 and all its children can + * share the same storage for the UID and lock fd, simply by inheriting the storage socket fds. The socket pair + * may exist in three different states: + * + * a) no datagram stored. This is the initial state. In this case the dynamic user was never realized. + * + * b) a datagram containing a UID stored, but no lock fd attached to it. In this case there was already a + * statically assigned UID by the same name, which we are reusing. + * + * c) a datagram containing a UID stored, and a lock fd is attached to it. In this case we allocated a dynamic + * UID and locked it in the file system, using the lock fd. + * + * As PID 1 and various children might access the socket pair simultaneously, and pop the datagram or push it + * back in any time, we also maintain a lock on the socket pair. Note one peculiarity regarding locking here: + * the UID lock on disk is protected via a BSD file lock (i.e. an fd-bound lock), so that the lock is kept in + * place as long as there's a reference to the fd open. The lock on the storage socket pair however is a POSIX + * file lock (i.e. a process-bound lock), as all users share the same fd of this (after all it is anonymous, + * nobody else could get any access to it except via our own fd) and we want to synchronize access between all + * processes that have access to it. */ + + d = hashmap_get(m->dynamic_users, name); + if (d) { + /* We already have a structure for the dynamic user, let's increase the ref count and reuse it */ + d->n_ref++; + *ret = d; + return 0; + } + + if (!valid_user_group_name_or_id(name)) + return -EINVAL; + + if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, storage_socket) < 0) + return -errno; + + r = dynamic_user_add(m, name, storage_socket, &d); + if (r < 0) + return r; + + storage_socket[0] = storage_socket[1] = -1; + + if (ret) { + d->n_ref++; + *ret = d; + } + + return 1; +} + +static int pick_uid(const char *name, uid_t *ret_uid) { + + static const uint8_t hash_key[] = { + 0x37, 0x53, 0x7e, 0x31, 0xcf, 0xce, 0x48, 0xf5, + 0x8a, 0xbb, 0x39, 0x57, 0x8d, 0xd9, 0xec, 0x59 + }; + + unsigned n_tries = 100; + uid_t candidate; + int r; + + /* A static user by this name does not exist yet. Let's find a free ID then, and use that. We start with a UID + * generated as hash from the user name. */ + candidate = UID_CLAMP_INTO_RANGE(siphash24(name, strlen(name), hash_key)); + + (void) mkdir("/run/systemd/dynamic-uid", 0755); + + for (;;) { + char lock_path[strlen("/run/systemd/dynamic-uid/") + DECIMAL_STR_MAX(uid_t) + 1]; + _cleanup_close_ int lock_fd = -1; + ssize_t l; + + if (--n_tries <= 0) /* Give up retrying eventually */ + return -EBUSY; + + if (candidate < UID_PICK_MIN || candidate > UID_PICK_MAX) + goto next; + + xsprintf(lock_path, "/run/systemd/dynamic-uid/" UID_FMT, candidate); + + for (;;) { + struct stat st; + + lock_fd = open(lock_path, O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY, 0600); + if (lock_fd < 0) + return -errno; + + r = flock(lock_fd, LOCK_EX|LOCK_NB); /* Try to get a BSD file lock on the UID lock file */ + if (r < 0) { + if (errno == EBUSY || errno == EAGAIN) + goto next; /* already in use */ + + return -errno; + } + + if (fstat(lock_fd, &st) < 0) + return -errno; + if (st.st_nlink > 0) + break; + + /* Oh, bummer, we got got the lock, but the file was unlinked between the time we opened it and + * got the lock. Close it, and try again. */ + lock_fd = safe_close(lock_fd); + } + + /* Some superficial check whether this UID/GID might already be taken by some static user */ + if (getpwuid(candidate) || getgrgid((gid_t) candidate)) { + (void) unlink(lock_path); + goto next; + } + + /* Let's store the user name in the lock file, so that we can use it for looking up the username for a UID */ + l = pwritev(lock_fd, + (struct iovec[2]) { + { .iov_base = (char*) name, .iov_len = strlen(name) }, + { .iov_base = (char[1]) { '\n' }, .iov_len = 1 } + }, 2, 0); + if (l < 0) { + (void) unlink(lock_path); + return -errno; + } + + (void) ftruncate(lock_fd, l); + + *ret_uid = candidate; + r = lock_fd; + lock_fd = -1; + + return r; + + next: + /* Pick another random UID, and see if that works for us. */ + random_bytes(&candidate, sizeof(candidate)); + candidate = UID_CLAMP_INTO_RANGE(candidate); + } +} + +static int dynamic_user_pop(DynamicUser *d, uid_t *ret_uid, int *ret_lock_fd) { + uid_t uid = UID_INVALID; + struct iovec iov = { + .iov_base = &uid, + .iov_len = sizeof(uid), + }; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int))]; + } control = {}; + struct msghdr mh = { + .msg_control = &control, + .msg_controllen = sizeof(control), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + struct cmsghdr *cmsg; + + ssize_t k; + int lock_fd = -1; + + assert(d); + assert(ret_uid); + assert(ret_lock_fd); + + /* Read the UID and lock fd that is stored in the storage AF_UNIX socket. This should be called with the lock + * on the socket taken. */ + + k = recvmsg(d->storage_socket[0], &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC); + if (k < 0) + return -errno; + + cmsg = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int))); + if (cmsg) + lock_fd = *(int*) CMSG_DATA(cmsg); + else + cmsg_close_all(&mh); /* just in case... */ + + *ret_uid = uid; + *ret_lock_fd = lock_fd; + + return 0; +} + +static int dynamic_user_push(DynamicUser *d, uid_t uid, int lock_fd) { + struct iovec iov = { + .iov_base = &uid, + .iov_len = sizeof(uid), + }; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int))]; + } control = {}; + struct msghdr mh = { + .msg_control = &control, + .msg_controllen = sizeof(control), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + ssize_t k; + + assert(d); + + /* Store the UID and lock_fd in the storage socket. This should be called with the socket pair lock taken. */ + + if (lock_fd >= 0) { + struct cmsghdr *cmsg; + + cmsg = CMSG_FIRSTHDR(&mh); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &lock_fd, sizeof(int)); + + mh.msg_controllen = CMSG_SPACE(sizeof(int)); + } else { + mh.msg_control = NULL; + mh.msg_controllen = 0; + } + + k = sendmsg(d->storage_socket[1], &mh, MSG_DONTWAIT|MSG_NOSIGNAL); + if (k < 0) + return -errno; + + return 0; +} + +static void unlink_uid_lock(int lock_fd, uid_t uid) { + char lock_path[strlen("/run/systemd/dynamic-uid/") + DECIMAL_STR_MAX(uid_t) + 1]; + + if (lock_fd < 0) + return; + + xsprintf(lock_path, "/run/systemd/dynamic-uid/" UID_FMT, uid); + (void) unlink_noerrno(lock_path); +} + +int dynamic_user_realize(DynamicUser *d, uid_t *ret) { + + _cleanup_close_ int etc_passwd_lock_fd = -1, uid_lock_fd = -1; + uid_t uid = UID_INVALID; + int r; + + assert(d); + + /* Acquire a UID for the user name. This will allocate a UID for the user name if the user doesn't exist + * yet. If it already exists its existing UID/GID will be reused. */ + + if (lockf(d->storage_socket[0], F_LOCK, 0) < 0) + return -errno; + + r = dynamic_user_pop(d, &uid, &uid_lock_fd); + if (r < 0) { + int new_uid_lock_fd; + uid_t new_uid; + + if (r != -EAGAIN) + goto finish; + + /* OK, nothing stored yet, let's try to find something useful. While we are working on this release the + * lock however, so that nobody else blocks on our NSS lookups. */ + (void) lockf(d->storage_socket[0], F_ULOCK, 0); + + /* Let's see if a proper, static user or group by this name exists. Try to take the lock on + * /etc/passwd, if that fails with EROFS then /etc is read-only. In that case it's fine if we don't + * take the lock, given that users can't be added there anyway in this case. */ + etc_passwd_lock_fd = take_etc_passwd_lock(NULL); + if (etc_passwd_lock_fd < 0 && etc_passwd_lock_fd != -EROFS) + return etc_passwd_lock_fd; + + /* First, let's parse this as numeric UID */ + r = parse_uid(d->name, &uid); + if (r < 0) { + struct passwd *p; + struct group *g; + + /* OK, this is not a numeric UID. Let's see if there's a user by this name */ + p = getpwnam(d->name); + if (p) + uid = p->pw_uid; + + /* Let's see if there's a group by this name */ + g = getgrnam(d->name); + if (g) { + /* If the UID/GID of the user/group of the same don't match, refuse operation */ + if (uid != UID_INVALID && uid != (uid_t) g->gr_gid) + return -EILSEQ; + + uid = (uid_t) g->gr_gid; + } + } + + if (uid == UID_INVALID) { + /* No static UID assigned yet, excellent. Let's pick a new dynamic one, and lock it. */ + + uid_lock_fd = pick_uid(d->name, &uid); + if (uid_lock_fd < 0) + return uid_lock_fd; + } + + /* So, we found a working UID/lock combination. Let's see if we actually still need it. */ + if (lockf(d->storage_socket[0], F_LOCK, 0) < 0) { + unlink_uid_lock(uid_lock_fd, uid); + return -errno; + } + + r = dynamic_user_pop(d, &new_uid, &new_uid_lock_fd); + if (r < 0) { + if (r != -EAGAIN) { + /* OK, something bad happened, let's get rid of the bits we acquired. */ + unlink_uid_lock(uid_lock_fd, uid); + goto finish; + } + + /* Great! Nothing is stored here, still. Store our newly acquired data. */ + } else { + /* Hmm, so as it appears there's now something stored in the storage socket. Throw away what we + * acquired, and use what's stored now. */ + + unlink_uid_lock(uid_lock_fd, uid); + safe_close(uid_lock_fd); + + uid = new_uid; + uid_lock_fd = new_uid_lock_fd; + } + } + + /* If the UID/GID was already allocated dynamically, push the data we popped out back in. If it was already + * allocated statically, push the UID back too, but do not push the lock fd in. If we allocated the UID + * dynamically right here, push that in along with the lock fd for it. */ + r = dynamic_user_push(d, uid, uid_lock_fd); + if (r < 0) + goto finish; + + *ret = uid; + r = 0; + +finish: + (void) lockf(d->storage_socket[0], F_ULOCK, 0); + return r; +} + +int dynamic_user_current(DynamicUser *d, uid_t *ret) { + _cleanup_close_ int lock_fd = -1; + uid_t uid; + int r; + + assert(d); + assert(ret); + + /* Get the currently assigned UID for the user, if there's any. This simply pops the data from the storage socket, and pushes it back in right-away. */ + + if (lockf(d->storage_socket[0], F_LOCK, 0) < 0) + return -errno; + + r = dynamic_user_pop(d, &uid, &lock_fd); + if (r < 0) + goto finish; + + r = dynamic_user_push(d, uid, lock_fd); + if (r < 0) + goto finish; + + *ret = uid; + r = 0; + +finish: + (void) lockf(d->storage_socket[0], F_ULOCK, 0); + return r; +} + +DynamicUser* dynamic_user_ref(DynamicUser *d) { + if (!d) + return NULL; + + assert(d->n_ref > 0); + d->n_ref++; + + return d; +} + +DynamicUser* dynamic_user_unref(DynamicUser *d) { + if (!d) + return NULL; + + /* Note that this doesn't actually release any resources itself. If a dynamic user should be fully destroyed + * and its UID released, use dynamic_user_destroy() instead. NB: the dynamic user table may contain entries + * with no references, which is commonly the case right before a daemon reload. */ + + assert(d->n_ref > 0); + d->n_ref--; + + return NULL; +} + +static int dynamic_user_close(DynamicUser *d) { + _cleanup_close_ int lock_fd = -1; + uid_t uid; + int r; + + /* Release the user ID, by releasing the lock on it, and emptying the storage socket. After this the user is + * unrealized again, much like it was after it the DynamicUser object was first allocated. */ + + if (lockf(d->storage_socket[0], F_LOCK, 0) < 0) + return -errno; + + r = dynamic_user_pop(d, &uid, &lock_fd); + if (r == -EAGAIN) { + /* User wasn't realized yet, nothing to do. */ + r = 0; + goto finish; + } + if (r < 0) + goto finish; + + /* This dynamic user was realized and dynamically allocated. In this case, let's remove the lock file. */ + unlink_uid_lock(lock_fd, uid); + r = 1; + +finish: + (void) lockf(d->storage_socket[0], F_ULOCK, 0); + return r; +} + +DynamicUser* dynamic_user_destroy(DynamicUser *d) { + if (!d) + return NULL; + + /* Drop a reference to a DynamicUser object, and destroy the user completely if this was the last + * reference. This is called whenever a service is shut down and wants its dynamic UID gone. Note that + * dynamic_user_unref() is what is called whenever a service is simply freed, for example during a reload + * cycle, where the dynamic users should not be destroyed, but our datastructures should. */ + + dynamic_user_unref(d); + + if (d->n_ref > 0) + return NULL; + + (void) dynamic_user_close(d); + return dynamic_user_free(d); +} + +int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds) { + DynamicUser *d; + Iterator i; + + assert(m); + assert(f); + assert(fds); + + /* Dump the dynamic user database into the manager serialization, to deal with daemon reloads. */ + + HASHMAP_FOREACH(d, m->dynamic_users, i) { + int copy0, copy1; + + copy0 = fdset_put_dup(fds, d->storage_socket[0]); + if (copy0 < 0) + return copy0; + + copy1 = fdset_put_dup(fds, d->storage_socket[1]); + if (copy1 < 0) + return copy1; + + fprintf(f, "dynamic-user=%s %i %i\n", d->name, copy0, copy1); + } + + return 0; +} + +void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds) { + _cleanup_free_ char *name = NULL, *s0 = NULL, *s1 = NULL; + int r, fd0, fd1; + + assert(m); + assert(value); + assert(fds); + + /* Parse the serialization again, after a daemon reload */ + + r = extract_many_words(&value, NULL, 0, &name, &s0, &s1, NULL); + if (r != 3 || !isempty(value)) { + log_debug("Unable to parse dynamic user line."); + return; + } + + if (safe_atoi(s0, &fd0) < 0 || !fdset_contains(fds, fd0)) { + log_debug("Unable to process dynamic user fd specification."); + return; + } + + if (safe_atoi(s1, &fd1) < 0 || !fdset_contains(fds, fd1)) { + log_debug("Unable to process dynamic user fd specification."); + return; + } + + r = dynamic_user_add(m, name, (int[]) { fd0, fd1 }, NULL); + if (r < 0) { + log_debug_errno(r, "Failed to add dynamic user: %m"); + return; + } + + (void) fdset_remove(fds, fd0); + (void) fdset_remove(fds, fd1); +} + +void dynamic_user_vacuum(Manager *m, bool close_user) { + DynamicUser *d; + Iterator i; + + assert(m); + + /* Empty the dynamic user database, optionally cleaning up orphaned dynamic users, i.e. destroy and free users + * to which no reference exist. This is called after a daemon reload finished, in order to destroy users which + * might not be referenced anymore. */ + + HASHMAP_FOREACH(d, m->dynamic_users, i) { + if (d->n_ref > 0) + continue; + + if (close_user) { + log_debug("Removing orphaned dynamic user %s", d->name); + (void) dynamic_user_close(d); + } + + dynamic_user_free(d); + } +} + +int dynamic_user_lookup_uid(Manager *m, uid_t uid, char **ret) { + char lock_path[strlen("/run/systemd/dynamic-uid/") + DECIMAL_STR_MAX(uid_t) + 1]; + _cleanup_free_ char *user = NULL; + uid_t check_uid; + int r; + + assert(m); + assert(ret); + + /* A friendly way to translate a dynamic user's UID into a his name. */ + + if (uid < UID_PICK_MIN) + return -ESRCH; + if (uid > UID_PICK_MAX) + return -ESRCH; + + xsprintf(lock_path, "/run/systemd/dynamic-uid/" UID_FMT, uid); + r = read_one_line_file(lock_path, &user); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + + /* The lock file might be stale, hence let's verify the data before we return it */ + r = dynamic_user_lookup_name(m, user, &check_uid); + if (r < 0) + return r; + if (check_uid != uid) /* lock file doesn't match our own idea */ + return -ESRCH; + + *ret = user; + user = NULL; + + return 0; +} + +int dynamic_user_lookup_name(Manager *m, const char *name, uid_t *ret) { + DynamicUser *d; + int r; + + assert(m); + assert(name); + assert(ret); + + /* A friendly call for translating a dynamic user's name into its UID */ + + d = hashmap_get(m->dynamic_users, name); + if (!d) + return -ESRCH; + + r = dynamic_user_current(d, ret); + if (r == -EAGAIN) /* not realized yet? */ + return -ESRCH; + + return r; +} + +int dynamic_creds_acquire(DynamicCreds *creds, Manager *m, const char *user, const char *group) { + bool acquired = false; + int r; + + assert(creds); + assert(m); + + /* A DynamicUser object encapsulates an allocation of both a UID and a GID for a specific name. However, some + * services use different user and groups. For cases like that there's DynamicCreds containing a pair of user + * and group. This call allocates a pair. */ + + if (!creds->user && user) { + r = dynamic_user_acquire(m, user, &creds->user); + if (r < 0) + return r; + + acquired = true; + } + + if (!creds->group) { + + if (creds->user && (!group || streq_ptr(user, group))) + creds->group = dynamic_user_ref(creds->user); + else { + r = dynamic_user_acquire(m, group, &creds->group); + if (r < 0) { + if (acquired) + creds->user = dynamic_user_unref(creds->user); + return r; + } + } + } + + return 0; +} + +int dynamic_creds_realize(DynamicCreds *creds, uid_t *uid, gid_t *gid) { + uid_t u = UID_INVALID; + gid_t g = GID_INVALID; + int r; + + assert(creds); + assert(uid); + assert(gid); + + /* Realize both the referenced user and group */ + + if (creds->user) { + r = dynamic_user_realize(creds->user, &u); + if (r < 0) + return r; + } + + if (creds->group && creds->group != creds->user) { + r = dynamic_user_realize(creds->group, &g); + if (r < 0) + return r; + } else + g = u; + + *uid = u; + *gid = g; + + return 0; +} + +void dynamic_creds_unref(DynamicCreds *creds) { + assert(creds); + + creds->user = dynamic_user_unref(creds->user); + creds->group = dynamic_user_unref(creds->group); +} + +void dynamic_creds_destroy(DynamicCreds *creds) { + assert(creds); + + creds->user = dynamic_user_destroy(creds->user); + creds->group = dynamic_user_destroy(creds->group); +} diff --git a/src/core/dynamic-user.h b/src/core/dynamic-user.h new file mode 100644 index 0000000000..0b8bce1a72 --- /dev/null +++ b/src/core/dynamic-user.h @@ -0,0 +1,66 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +typedef struct DynamicUser DynamicUser; + +typedef struct DynamicCreds { + /* A combination of a dynamic user and group */ + DynamicUser *user; + DynamicUser *group; +} DynamicCreds; + +#include "manager.h" + +/* Note that this object always allocates a pair of user and group under the same name, even if one of them isn't + * used. This means, if you want to allocate a group and user pair, and they might have two different names, then you + * need to allocated two of these objects. DynamicCreds below makes that easy. */ +struct DynamicUser { + int n_ref; + Manager *manager; + + /* An AF_UNIX socket pair that contains a datagram containing both the numeric ID assigned, as well as a lock + * file fd locking the user ID we picked. */ + int storage_socket[2]; + + char name[]; +}; + +int dynamic_user_acquire(Manager *m, const char *name, DynamicUser **ret); + +int dynamic_user_realize(DynamicUser *d, uid_t *ret); +int dynamic_user_current(DynamicUser *d, uid_t *ret); + +DynamicUser* dynamic_user_ref(DynamicUser *d); +DynamicUser* dynamic_user_unref(DynamicUser *d); +DynamicUser* dynamic_user_destroy(DynamicUser *d); + +int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds); +void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds); +void dynamic_user_vacuum(Manager *m, bool close_user); + +int dynamic_user_lookup_uid(Manager *m, uid_t uid, char **ret); +int dynamic_user_lookup_name(Manager *m, const char *name, uid_t *ret); + +int dynamic_creds_acquire(DynamicCreds *creds, Manager *m, const char *user, const char *group); +int dynamic_creds_realize(DynamicCreds *creds, uid_t *uid, gid_t *gid); + +void dynamic_creds_unref(DynamicCreds *creds); +void dynamic_creds_destroy(DynamicCreds *creds); diff --git a/src/core/execute.c b/src/core/execute.c index 7c178b97c3..c186f2a705 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1526,14 +1526,28 @@ static bool exec_needs_mount_namespace( return false; } +static void append_socket_pair(int *array, unsigned *n, int pair[2]) { + assert(array); + assert(n); + + if (!pair) + return; + + if (pair[0] >= 0) + array[(*n)++] = pair[0]; + if (pair[1] >= 0) + array[(*n)++] = pair[1]; +} + static int close_remaining_fds( const ExecParameters *params, ExecRuntime *runtime, + DynamicCreds *dcreds, int socket_fd, int *fds, unsigned n_fds) { unsigned n_dont_close = 0; - int dont_close[n_fds + 7]; + int dont_close[n_fds + 11]; assert(params); @@ -1551,11 +1565,14 @@ static int close_remaining_fds( n_dont_close += n_fds; } - if (runtime) { - if (runtime->netns_storage_socket[0] >= 0) - dont_close[n_dont_close++] = runtime->netns_storage_socket[0]; - if (runtime->netns_storage_socket[1] >= 0) - dont_close[n_dont_close++] = runtime->netns_storage_socket[1]; + if (runtime) + append_socket_pair(dont_close, &n_dont_close, runtime->netns_storage_socket); + + if (dcreds) { + if (dcreds->user) + append_socket_pair(dont_close, &n_dont_close, dcreds->user->storage_socket); + if (dcreds->group) + append_socket_pair(dont_close, &n_dont_close, dcreds->group->storage_socket); } return close_all_fds(dont_close, n_dont_close); @@ -1567,6 +1584,7 @@ static int exec_child( const ExecContext *context, const ExecParameters *params, ExecRuntime *runtime, + DynamicCreds *dcreds, char **argv, int socket_fd, int *fds, unsigned n_fds, @@ -1617,7 +1635,7 @@ static int exec_child( log_forget_fds(); - r = close_remaining_fds(params, runtime, socket_fd, fds, n_fds); + r = close_remaining_fds(params, runtime, dcreds, socket_fd, fds, n_fds); if (r < 0) { *exit_status = EXIT_FDS; return r; @@ -1650,25 +1668,42 @@ static int exec_child( } } - if (context->user) { - username = context->user; - r = get_user_creds(&username, &uid, &gid, &home, &shell); + if (context->dynamic_user && dcreds) { + + r = dynamic_creds_realize(dcreds, &uid, &gid); if (r < 0) { *exit_status = EXIT_USER; return r; } - } - if (context->group) { - const char *g = context->group; + if (uid == UID_INVALID || gid == GID_INVALID) { + *exit_status = EXIT_USER; + return -ESRCH; + } - r = get_group_creds(&g, &gid); - if (r < 0) { - *exit_status = EXIT_GROUP; - return r; + if (dcreds->user) + username = dcreds->user->name; + + } else { + if (context->user) { + username = context->user; + r = get_user_creds(&username, &uid, &gid, &home, &shell); + if (r < 0) { + *exit_status = EXIT_USER; + return r; + } } - } + if (context->group) { + const char *g = context->group; + + r = get_group_creds(&g, &gid); + if (r < 0) { + *exit_status = EXIT_GROUP; + return r; + } + } + } /* If a socket is connected to STDIN/STDOUT/STDERR, we * must sure to drop O_NONBLOCK */ @@ -2192,6 +2227,7 @@ int exec_spawn(Unit *unit, const ExecContext *context, const ExecParameters *params, ExecRuntime *runtime, + DynamicCreds *dcreds, pid_t *ret) { _cleanup_strv_free_ char **files_env = NULL; @@ -2250,6 +2286,7 @@ int exec_spawn(Unit *unit, context, params, runtime, + dcreds, argv, socket_fd, fds, n_fds, @@ -2723,6 +2760,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { if (c->group) fprintf(f, "%sGroup: %s\n", prefix, c->group); + fprintf(f, "%sDynamicUser: %s\n", prefix, yes_no(c->dynamic_user)); + if (strv_length(c->supplementary_groups) > 0) { fprintf(f, "%sSupplementaryGroups:", prefix); strv_fprintf(f, c->supplementary_groups); diff --git a/src/core/execute.h b/src/core/execute.h index 189c4d0999..48cc18fbb3 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -92,6 +92,8 @@ struct ExecRuntime { char *tmp_dir; char *var_tmp_dir; + /* An AF_UNIX socket pair, that contains a datagram containing a file descriptor referring to the network + * namespace. */ int netns_storage_socket[2]; }; @@ -174,6 +176,8 @@ struct ExecContext { bool no_new_privileges; + bool dynamic_user; + /* This is not exposed to the user but available * internally. We need it to make sure that whenever we spawn * /usr/bin/mount it is run in the same process group as us so @@ -235,12 +239,14 @@ struct ExecParameters { }; #include "unit.h" +#include "dynamic-user.h" int exec_spawn(Unit *unit, ExecCommand *command, const ExecContext *context, const ExecParameters *exec_params, ExecRuntime *runtime, + DynamicCreds *dynamic_creds, pid_t *ret); void exec_command_done(ExecCommand *c); diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 7f7c2fe185..c9cdbe8ba7 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -34,6 +34,7 @@ $1.UMask, config_parse_mode, 0, $1.Environment, config_parse_environ, 0, offsetof($1, exec_context.environment) $1.EnvironmentFile, config_parse_unit_env_file, 0, offsetof($1, exec_context.environment_files) $1.PassEnvironment, config_parse_pass_environ, 0, offsetof($1, exec_context.pass_environment) +$1.DynamicUser, config_parse_bool, 0, offsetof($1, exec_context.dynamic_user) $1.StandardInput, config_parse_input, 0, offsetof($1, exec_context.std_input) $1.StandardOutput, config_parse_output, 0, offsetof($1, exec_context.std_output) $1.StandardError, config_parse_output, 0, offsetof($1, exec_context.std_error) diff --git a/src/core/manager.c b/src/core/manager.c index a0181e2138..a4d027f0fc 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1004,6 +1004,9 @@ Manager* manager_free(Manager *m) { bus_done(m); + dynamic_user_vacuum(m, false); + hashmap_free(m->dynamic_users); + hashmap_free(m->units); hashmap_free(m->jobs); hashmap_free(m->watch_pids1); @@ -1227,6 +1230,9 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { /* Third, fire things up! */ manager_coldplug(m); + /* Release any dynamic users no longer referenced */ + dynamic_user_vacuum(m, true); + if (serialization) { assert(m->n_reloading > 0); m->n_reloading--; @@ -2403,6 +2409,10 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { bus_track_serialize(m->subscribed, f); + r = dynamic_user_serialize(m, f, fds); + if (r < 0) + return r; + fputc('\n', f); HASHMAP_FOREACH_KEY(u, t, m->units, i) { @@ -2579,7 +2589,9 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { m->kdbus_fd = fdset_remove(fds, fd); } - } else { + } else if (startswith(l, "dynamic-user=")) + dynamic_user_deserialize_one(m, l + 13, fds); + else { int k; k = bus_track_deserialize_item(&m->deserialized_subscribed, l); @@ -2660,6 +2672,7 @@ int manager_reload(Manager *m) { manager_clear_jobs_and_units(m); lookup_paths_flush_generator(&m->lookup_paths); lookup_paths_free(&m->lookup_paths); + dynamic_user_vacuum(m, false); q = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, 0, NULL); if (q < 0 && r >= 0) @@ -2696,6 +2709,9 @@ int manager_reload(Manager *m) { /* Third, fire things up! */ manager_coldplug(m); + /* Release any dynamic users no longer referenced */ + dynamic_user_vacuum(m, true); + /* Sync current state of bus names with our set of listening units */ if (m->api_bus) manager_sync_bus_names(m, m->api_bus); diff --git a/src/core/manager.h b/src/core/manager.h index 6ed15c1a41..c681d5dc46 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -298,6 +298,9 @@ struct Manager { /* Used for processing polkit authorization responses */ Hashmap *polkit_registry; + /* Dynamic users/groups, indexed by their name */ + Hashmap *dynamic_users; + /* When the user hits C-A-D more than 7 times per 2s, reboot immediately... */ RateLimit ctrl_alt_del_ratelimit; diff --git a/src/core/mount.c b/src/core/mount.c index fda4d65d6f..db5cafcb11 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -245,6 +245,8 @@ static void mount_done(Unit *u) { exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX); m->control_command = NULL; + dynamic_creds_unref(&m->dynamic_creds); + mount_unwatch_control_pid(m); m->timer_event_source = sd_event_source_unref(m->timer_event_source); @@ -648,6 +650,9 @@ static int mount_coldplug(Unit *u) { return r; } + if (!IN_SET(new_state, MOUNT_DEAD, MOUNT_FAILED)) + (void) unit_setup_dynamic_creds(u); + mount_set_state(m, new_state); return 0; } @@ -716,6 +721,10 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { if (r < 0) return r; + r = unit_setup_dynamic_creds(UNIT(m)); + if (r < 0) + return r; + r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec)); if (r < 0) return r; @@ -732,6 +741,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { &m->exec_context, &exec_params, m->exec_runtime, + &m->dynamic_creds, &pid); if (r < 0) return r; @@ -752,12 +762,14 @@ static void mount_enter_dead(Mount *m, MountResult f) { if (f != MOUNT_SUCCESS) m->result = f; + mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD); + exec_runtime_destroy(m->exec_runtime); m->exec_runtime = exec_runtime_unref(m->exec_runtime); exec_context_destroy_runtime_directory(&m->exec_context, manager_get_runtime_prefix(UNIT(m)->manager)); - mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD); + dynamic_creds_destroy(&m->dynamic_creds); } static void mount_enter_mounted(Mount *m, MountResult f) { @@ -1817,6 +1829,7 @@ const UnitVTable mount_vtable = { .cgroup_context_offset = offsetof(Mount, cgroup_context), .kill_context_offset = offsetof(Mount, kill_context), .exec_runtime_offset = offsetof(Mount, exec_runtime), + .dynamic_creds_offset = offsetof(Mount, dynamic_creds), .sections = "Unit\0" diff --git a/src/core/mount.h b/src/core/mount.h index da529c44f4..ac27b518cc 100644 --- a/src/core/mount.h +++ b/src/core/mount.h @@ -21,8 +21,8 @@ typedef struct Mount Mount; -#include "execute.h" #include "kill.h" +#include "dynamic-user.h" typedef enum MountExecCommand { MOUNT_EXEC_MOUNT, @@ -85,6 +85,7 @@ struct Mount { CGroupContext cgroup_context; ExecRuntime *exec_runtime; + DynamicCreds dynamic_creds; MountState state, deserialized_state; diff --git a/src/core/service.c b/src/core/service.c index afb198507b..4d59d78ecb 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -322,6 +322,8 @@ static void service_done(Unit *u) { s->control_command = NULL; s->main_command = NULL; + dynamic_creds_unref(&s->dynamic_creds); + exit_status_set_free(&s->restart_prevent_status); exit_status_set_free(&s->restart_force_status); exit_status_set_free(&s->success_status); @@ -1030,6 +1032,9 @@ static int service_coldplug(Unit *u) { if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) service_start_watchdog(s); + if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)) + (void) unit_setup_dynamic_creds(u); + service_set_state(s, s->deserialized_state); return 0; } @@ -1184,6 +1189,10 @@ static int service_spawn( if (r < 0) return r; + r = unit_setup_dynamic_creds(UNIT(s)); + if (r < 0) + return r; + if (pass_fds || s->exec_context.std_input == EXEC_INPUT_SOCKET || s->exec_context.std_output == EXEC_OUTPUT_SOCKET || @@ -1285,6 +1294,7 @@ static int service_spawn( &s->exec_context, &exec_params, s->exec_runtime, + &s->dynamic_creds, &pid); if (r < 0) return r; @@ -1418,9 +1428,12 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) exec_runtime_destroy(s->exec_runtime); s->exec_runtime = exec_runtime_unref(s->exec_runtime); - /* Also, remove the runtime directory in */ + /* Also, remove the runtime directory */ exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager)); + /* Release the user, and destroy it if we are the only remaining owner */ + dynamic_creds_destroy(&s->dynamic_creds); + /* Try to delete the pid file. At this point it will be * out-of-date, and some software might be confused by it, so * let's remove it. */ @@ -3323,6 +3336,7 @@ const UnitVTable service_vtable = { .cgroup_context_offset = offsetof(Service, cgroup_context), .kill_context_offset = offsetof(Service, kill_context), .exec_runtime_offset = offsetof(Service, exec_runtime), + .dynamic_creds_offset = offsetof(Service, dynamic_creds), .sections = "Unit\0" diff --git a/src/core/service.h b/src/core/service.h index cfef375b03..8e56e1acb9 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -148,6 +148,7 @@ struct Service { /* Runtime data of the execution context */ ExecRuntime *exec_runtime; + DynamicCreds dynamic_creds; pid_t main_pid, control_pid; int socket_fd; diff --git a/src/core/socket.c b/src/core/socket.c index e098055885..1ce41a1f07 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -150,6 +150,8 @@ static void socket_done(Unit *u) { exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); s->control_command = NULL; + dynamic_creds_unref(&s->dynamic_creds); + socket_unwatch_control_pid(s); unit_ref_unset(&s->service); @@ -1602,6 +1604,9 @@ static int socket_coldplug(Unit *u) { return r; } + if (!IN_SET(s->deserialized_state, SOCKET_DEAD, SOCKET_FAILED)) + (void) unit_setup_dynamic_creds(u); + socket_set_state(s, s->deserialized_state); return 0; } @@ -1633,6 +1638,10 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { if (r < 0) return r; + r = unit_setup_dynamic_creds(UNIT(s)); + if (r < 0) + return r; + r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); if (r < 0) return r; @@ -1654,6 +1663,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { &s->exec_context, &exec_params, s->exec_runtime, + &s->dynamic_creds, &pid); if (r < 0) return r; @@ -1757,12 +1767,14 @@ static void socket_enter_dead(Socket *s, SocketResult f) { if (f != SOCKET_SUCCESS) s->result = f; + socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD); + exec_runtime_destroy(s->exec_runtime); s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager)); - socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD); + dynamic_creds_destroy(&s->dynamic_creds); } static void socket_enter_signal(Socket *s, SocketState state, SocketResult f); @@ -2930,6 +2942,7 @@ const UnitVTable socket_vtable = { .cgroup_context_offset = offsetof(Socket, cgroup_context), .kill_context_offset = offsetof(Socket, kill_context), .exec_runtime_offset = offsetof(Socket, exec_runtime), + .dynamic_creds_offset = offsetof(Socket, dynamic_creds), .sections = "Unit\0" diff --git a/src/core/socket.h b/src/core/socket.h index 0f1ac69c6f..6c32d67bef 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -94,7 +94,9 @@ struct Socket { ExecContext exec_context; KillContext kill_context; CGroupContext cgroup_context; + ExecRuntime *exec_runtime; + DynamicCreds dynamic_creds; /* For Accept=no sockets refers to the one service we'll activate. For Accept=yes sockets is either NULL, or filled diff --git a/src/core/swap.c b/src/core/swap.c index a532b15be8..66a318d01f 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -153,6 +153,8 @@ static void swap_done(Unit *u) { exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX); s->control_command = NULL; + dynamic_creds_unref(&s->dynamic_creds); + swap_unwatch_control_pid(s); s->timer_event_source = sd_event_source_unref(s->timer_event_source); @@ -553,6 +555,9 @@ static int swap_coldplug(Unit *u) { return r; } + if (!IN_SET(new_state, SWAP_DEAD, SWAP_FAILED)) + (void) unit_setup_dynamic_creds(u); + swap_set_state(s, new_state); return 0; } @@ -628,6 +633,10 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { if (r < 0) goto fail; + r = unit_setup_dynamic_creds(UNIT(s)); + if (r < 0) + return r; + r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); if (r < 0) goto fail; @@ -644,6 +653,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { &s->exec_context, &exec_params, s->exec_runtime, + &s->dynamic_creds, &pid); if (r < 0) goto fail; @@ -668,12 +678,14 @@ static void swap_enter_dead(Swap *s, SwapResult f) { if (f != SWAP_SUCCESS) s->result = f; + swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD); + exec_runtime_destroy(s->exec_runtime); s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager)); - swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD); + dynamic_creds_destroy(&s->dynamic_creds); } static void swap_enter_active(Swap *s, SwapResult f) { @@ -1466,6 +1478,7 @@ const UnitVTable swap_vtable = { .cgroup_context_offset = offsetof(Swap, cgroup_context), .kill_context_offset = offsetof(Swap, kill_context), .exec_runtime_offset = offsetof(Swap, exec_runtime), + .dynamic_creds_offset = offsetof(Swap, dynamic_creds), .sections = "Unit\0" diff --git a/src/core/swap.h b/src/core/swap.h index fbf66debdc..b0ef50f1e8 100644 --- a/src/core/swap.h +++ b/src/core/swap.h @@ -82,6 +82,7 @@ struct Swap { CGroupContext cgroup_context; ExecRuntime *exec_runtime; + DynamicCreds dynamic_creds; SwapState state, deserialized_state; diff --git a/src/core/unit.c b/src/core/unit.c index 4934a0e56f..ff7c562fba 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3224,6 +3224,33 @@ void unit_ref_unset(UnitRef *ref) { ref->unit = NULL; } +static int user_from_unit_name(Unit *u, char **ret) { + + static const uint8_t hash_key[] = { + 0x58, 0x1a, 0xaf, 0xe6, 0x28, 0x58, 0x4e, 0x96, + 0xb4, 0x4e, 0xf5, 0x3b, 0x8c, 0x92, 0x07, 0xec + }; + + _cleanup_free_ char *n = NULL; + int r; + + r = unit_name_to_prefix(u->id, &n); + if (r < 0) + return r; + + if (valid_user_group_name(n)) { + *ret = n; + n = NULL; + return 0; + } + + /* If we can't use the unit name as a user name, then let's hash it and use that */ + if (asprintf(ret, "_du%016" PRIx64, siphash24(n, strlen(n), hash_key)) < 0) + return -ENOMEM; + + return 0; +} + int unit_patch_contexts(Unit *u) { CGroupContext *cc; ExecContext *ec; @@ -3268,6 +3295,22 @@ int unit_patch_contexts(Unit *u) { if (ec->private_devices) ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_MKNOD); + + if (ec->dynamic_user) { + if (!ec->user) { + r = user_from_unit_name(u, &ec->user); + if (r < 0) + return r; + } + + if (!ec->group) { + ec->group = strdup(ec->user); + if (!ec->group) + return -ENOMEM; + } + + ec->private_tmp = true; + } } cc = unit_get_cgroup_context(u); @@ -3776,6 +3819,26 @@ int unit_setup_exec_runtime(Unit *u) { return exec_runtime_make(rt, unit_get_exec_context(u), u->id); } +int unit_setup_dynamic_creds(Unit *u) { + ExecContext *ec; + DynamicCreds *dcreds; + size_t offset; + + assert(u); + + offset = UNIT_VTABLE(u)->dynamic_creds_offset; + assert(offset > 0); + dcreds = (DynamicCreds*) ((uint8_t*) u + offset); + + ec = unit_get_exec_context(u); + assert(ec); + + if (!ec->dynamic_user) + return 0; + + return dynamic_creds_acquire(dcreds, u->manager, ec->user, ec->group); +} + bool unit_type_supported(UnitType t) { if (_unlikely_(t < 0)) return false; diff --git a/src/core/unit.h b/src/core/unit.h index 1eabfa51e2..47eb8d50a6 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -291,6 +291,10 @@ struct UnitVTable { * that */ size_t exec_runtime_offset; + /* If greater than 0, the offset into the object where the pointer to DynamicCreds is found, if the unit type + * has that. */ + size_t dynamic_creds_offset; + /* The name of the configuration file section with the private settings of this unit */ const char *private_section; @@ -589,6 +593,7 @@ CGroupContext *unit_get_cgroup_context(Unit *u) _pure_; ExecRuntime *unit_get_exec_runtime(Unit *u) _pure_; int unit_setup_exec_runtime(Unit *u); +int unit_setup_dynamic_creds(Unit *u); int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data); int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) _printf_(4,5); diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index 02e3bf904c..32be3cdc38 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -44,6 +44,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION, EPERM), SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED), SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index c8f369cb78..befb6fbfe0 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -40,6 +40,7 @@ #define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation" #define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown" #define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning" +#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser" #define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine" #define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage" diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 94ffa8af87..5c50c0cd2e 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -179,11 +179,12 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "sv", sn, "t", l.rlim_cur); } else if (STR_IN_SET(field, - "CPUAccounting", "MemoryAccounting", "IOAccounting", "BlockIOAccounting", "TasksAccounting", - "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies", - "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit", - "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges", - "SyslogLevelPrefix", "Delegate", "RemainAfterElapse", "MemoryDenyWriteExecute")) { + "CPUAccounting", "MemoryAccounting", "IOAccounting", "BlockIOAccounting", "TasksAccounting", + "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies", + "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit", + "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges", + "SyslogLevelPrefix", "Delegate", "RemainAfterElapse", "MemoryDenyWriteExecute", + "RestrictRealtime", "DynamicUser")) { r = parse_boolean(eq); if (r < 0) -- cgit v1.2.3-54-g00ecf From 6f3e79859d91aecb3a75097b69fb9cba086b2cb1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 14 Jul 2016 19:17:18 +0200 Subject: core: enforce user/group name validity also when creating transient units --- src/core/dbus-execute.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index a6896c6e6c..9c50cd93e5 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -44,6 +44,7 @@ #endif #include "strv.h" #include "syslog-util.h" +#include "user-util.h" #include "utf8.h" BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput); @@ -841,6 +842,9 @@ int bus_exec_context_set_transient_property( if (r < 0) return r; + if (!isempty(uu) && !valid_user_group_name_or_id(uu)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user name: %s", uu); + if (mode != UNIT_CHECK) { if (isempty(uu)) @@ -860,6 +864,9 @@ int bus_exec_context_set_transient_property( if (r < 0) return r; + if (!isempty(gg) && !valid_user_group_name_or_id(gg)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group name: %s", gg); + if (mode != UNIT_CHECK) { if (isempty(gg)) -- cgit v1.2.3-54-g00ecf From 409093fe10685ed55915ef256f09cdf144b6528b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 14 Jul 2016 19:19:49 +0200 Subject: nss: add new "nss-systemd" NSS module for mapping dynamic users With this NSS module all dynamic service users will be resolvable via NSS like any real user. --- Makefile-man.am | 7 + Makefile.am | 21 +++ README | 21 ++- man/nss-myhostname.xml | 5 +- man/nss-mymachines.xml | 5 +- man/nss-resolve.xml | 7 +- man/nss-systemd.xml | 107 +++++++++++++ src/core/execute.c | 6 + src/nss-systemd/Makefile | 1 + src/nss-systemd/nss-systemd.c | 332 ++++++++++++++++++++++++++++++++++++++++ src/nss-systemd/nss-systemd.sym | 17 ++ 11 files changed, 515 insertions(+), 14 deletions(-) create mode 100644 man/nss-systemd.xml create mode 120000 src/nss-systemd/Makefile create mode 100644 src/nss-systemd/nss-systemd.c create mode 100644 src/nss-systemd/nss-systemd.sym diff --git a/Makefile-man.am b/Makefile-man.am index 8ab733360d..3ac1906a4a 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -23,6 +23,7 @@ MANPAGES += \ man/localtime.5 \ man/machine-id.5 \ man/machine-info.5 \ + man/nss-systemd.8 \ man/os-release.5 \ man/sd-bus-errors.3 \ man/sd-bus.3 \ @@ -255,6 +256,7 @@ MANPAGES_ALIAS += \ man/SD_WARNING.3 \ man/init.1 \ man/journald.conf.d.5 \ + man/libnss_systemd.so.2.8 \ man/poweroff.8 \ man/reboot.8 \ man/sd_bus_creds_get_audit_login_uid.3 \ @@ -587,6 +589,7 @@ man/SD_NOTICE.3: man/sd-daemon.3 man/SD_WARNING.3: man/sd-daemon.3 man/init.1: man/systemd.1 man/journald.conf.d.5: man/journald.conf.5 +man/libnss_systemd.so.2.8: man/nss-systemd.8 man/poweroff.8: man/halt.8 man/reboot.8: man/halt.8 man/sd_bus_creds_get_audit_login_uid.3: man/sd_bus_creds_get_pid.3 @@ -1071,6 +1074,9 @@ man/init.html: man/systemd.html man/journald.conf.d.html: man/journald.conf.html $(html-alias) +man/libnss_systemd.so.2.html: man/nss-systemd.html + $(html-alias) + man/poweroff.html: man/halt.html $(html-alias) @@ -2519,6 +2525,7 @@ EXTRA_DIST += \ man/nss-myhostname.xml \ man/nss-mymachines.xml \ man/nss-resolve.xml \ + man/nss-systemd.xml \ man/os-release.xml \ man/pam_systemd.xml \ man/resolved.conf.xml \ diff --git a/Makefile.am b/Makefile.am index 3d5ce1e2c3..a4241122d5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5001,6 +5001,27 @@ test_nss_LDADD = \ manual_tests += \ test-nss +# ------------------------------------------------------------------------------ +libnss_systemd_la_SOURCES = \ + src/nss-systemd/nss-systemd.sym \ + src/nss-systemd/nss-systemd.c + +libnss_systemd_la_LDFLAGS = \ + $(AM_LDFLAGS) \ + -module \ + -export-dynamic \ + -avoid-version \ + -shared \ + -shrext .so.2 \ + -Wl,--version-script=$(top_srcdir)/src/nss-systemd/nss-systemd.sym + +libnss_systemd_la_LIBADD = \ + libsystemd-internal.la \ + libbasic.la + +lib_LTLIBRARIES += \ + libnss_systemd.la + # ------------------------------------------------------------------------------ if HAVE_MYHOSTNAME libnss_myhostname_la_SOURCES = \ diff --git a/README b/README index ca8993cb12..19c15a70b0 100644 --- a/README +++ b/README @@ -201,7 +201,7 @@ USERS AND GROUPS: "systemd-coredump" system user and group to exist. NSS: - systemd ships with three NSS modules: + systemd ships with four glibc NSS modules: nss-myhostname resolves the local hostname to locally configured IP addresses, as well as "localhost" to @@ -210,15 +210,22 @@ NSS: nss-resolve enables DNS resolution via the systemd-resolved DNS/LLMNR caching stub resolver "systemd-resolved". - nss-mymachines enables resolution of all local containers - registered with machined to their respective IP addresses. + nss-mymachines enables resolution of all local containers registered + with machined to their respective IP addresses. It also maps UID/GIDs + ranges used by containers to useful names. - To make use of these NSS modules, please add them to the - "hosts: " line in /etc/nsswitch.conf. The "resolve" module - should replace the glibc "dns" module in this file. + nss-systemd enables resolution of all dynamically allocated service + users. (See the DynamicUser= setting in unit files.) - The three modules should be used in the following order: + To make use of these NSS modules, please add them to the "hosts:", + "passwd:" and "group:" lines in /etc/nsswitch.conf. The "resolve" + module should replace the glibc "dns" module in this file (and don't + worry, it chain-loads the "dns" module if it can't talk to resolved). + The four modules should be used in the following order: + + passwd: compat mymachines systemd + group: compat mymachines systemd hosts: files mymachines resolve myhostname SYSV INIT.D SCRIPTS: diff --git a/man/nss-myhostname.xml b/man/nss-myhostname.xml index a920ec334f..b1daaba02b 100644 --- a/man/nss-myhostname.xml +++ b/man/nss-myhostname.xml @@ -106,8 +106,8 @@ Here is an example /etc/nsswitch.conf file that enables nss-myhostname correctly: -passwd: compat mymachines -group: compat mymachines +passwd: compat mymachines systemd +group: compat mymachines systemd shadow: compat hosts: files mymachines resolve myhostname @@ -138,6 +138,7 @@ netgroup: nis See Also systemd1, + nss-systemd8, nss-resolve8, nss-mymachines8, nsswitch.conf5, diff --git a/man/nss-mymachines.xml b/man/nss-mymachines.xml index ec047449bf..a70119e256 100644 --- a/man/nss-mymachines.xml +++ b/man/nss-mymachines.xml @@ -82,8 +82,8 @@ Here is an example /etc/nsswitch.conf file that enables nss-mymachines correctly: - passwd: compat mymachines -group: compat mymachines + passwd: compat mymachines systemd +group: compat mymachines systemd shadow: compat hosts: files mymachines resolve myhostname @@ -103,6 +103,7 @@ netgroup: nis systemd1, systemd-machined.service8, + nss-systemd8, nss-resolve8, nss-myhostname8, nsswitch.conf5, diff --git a/man/nss-resolve.xml b/man/nss-resolve.xml index d9e56453e8..e6cc1d982a 100644 --- a/man/nss-resolve.xml +++ b/man/nss-resolve.xml @@ -81,8 +81,8 @@ Here is an example /etc/nsswitch.conf file that enables nss-resolve correctly: -passwd: compat mymachines -group: compat mymachines +passwd: compat mymachines systemd +group: compat mymachines systemd shadow: compat hosts: files mymachines resolve myhostname @@ -102,8 +102,9 @@ netgroup: nis systemd1, systemd-resolved8, - nss-mymachines8, + nss-systemd8, nss-myhostname8, + nss-mymachines8, nsswitch.conf5 diff --git a/man/nss-systemd.xml b/man/nss-systemd.xml new file mode 100644 index 0000000000..4228372e51 --- /dev/null +++ b/man/nss-systemd.xml @@ -0,0 +1,107 @@ + + + + + + + + + nss-systemd + systemd + + + + Developer + Lennart + Poettering + lennart@poettering.net + + + + + + nss-systemd + 8 + + + + nss-systemd + libnss_systemd.so.2 + Provide UNIX user and group name resolution for dynamic users and groups. + + + + libnss_systemd.so.2 + + + + Description + + nss-systemd is a plug-in module for the GNU Name Service Switch (NSS) functionality of the + GNU C Library (glibc), providing UNIX user and group name resolution for dynamic users and + groups allocated through the DynamicUser= option in systemd unit files. See + systemd.exec5 for details on + this option. + + To activate the NSS module, add systemd to the lines starting with + passwd: and group: in /etc/nsswitch.conf. + + It is recommended to place systemd after the files or + compat entry of the /etc/nsswitch.conf lines so that + /etc/passwd and /etc/group based mappings take precedence. + + + + Example + + Here is an example /etc/nsswitch.conf file that enables + nss-systemd correctly: + + passwd: compat mymachines systemd +group: compat mymachines systemd +shadow: compat + +hosts: files mymachines resolve myhostname +networks: files + +protocols: db files +services: db files +ethers: db files +rpc: db files + +netgroup: nis + + + + + See Also + + systemd1, + systemd.exec5, + nss-resolve8, + nss-myhostname8, + nss-mymachines8, + nsswitch.conf5, + getent1 + + + + diff --git a/src/core/execute.c b/src/core/execute.c index c186f2a705..26e9cd5339 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1670,6 +1670,12 @@ static int exec_child( if (context->dynamic_user && dcreds) { + /* Make sure we bypass our own NSS module for any NSS checks */ + if (putenv((char*) "SYSTEMD_NSS_DYNAMIC_BYPASS=1") != 0) { + *exit_status = EXIT_USER; + return -errno; + } + r = dynamic_creds_realize(dcreds, &uid, &gid); if (r < 0) { *exit_status = EXIT_USER; diff --git a/src/nss-systemd/Makefile b/src/nss-systemd/Makefile new file mode 120000 index 0000000000..d0b0e8e008 --- /dev/null +++ b/src/nss-systemd/Makefile @@ -0,0 +1 @@ +../Makefile \ No newline at end of file diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c new file mode 100644 index 0000000000..e7a4393bb0 --- /dev/null +++ b/src/nss-systemd/nss-systemd.c @@ -0,0 +1,332 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#include "sd-bus.h" + +#include "bus-common-errors.h" +#include "env-util.h" +#include "macro.h" +#include "nss-util.h" +#include "signal-util.h" +#include "user-util.h" +#include "util.h" + +NSS_GETPW_PROTOTYPES(systemd); +NSS_GETGR_PROTOTYPES(systemd); + +enum nss_status _nss_systemd_getpwnam_r( + const char *name, + struct passwd *pwd, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + uint32_t translated; + size_t l; + int r; + + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(pwd); + + /* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */ + if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) + goto not_found; + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByName", + &error, + &reply, + "s", + name); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + goto not_found; + + goto fail; + } + + r = sd_bus_message_read(reply, "u", &translated); + if (r < 0) + goto fail; + + l = strlen(name); + if (buflen < l+1) { + *errnop = ENOMEM; + return NSS_STATUS_TRYAGAIN; + } + + memcpy(buffer, name, l+1); + + pwd->pw_name = buffer; + pwd->pw_uid = (uid_t) translated; + pwd->pw_gid = (uid_t) translated; + pwd->pw_gecos = (char*) "Dynamic User"; + pwd->pw_passwd = (char*) "*"; /* locked */ + pwd->pw_dir = (char*) "/"; + pwd->pw_shell = (char*) "/sbin/nologin"; + + *errnop = 0; + return NSS_STATUS_SUCCESS; + +not_found: + *errnop = 0; + return NSS_STATUS_NOTFOUND; + +fail: + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} + +enum nss_status _nss_systemd_getpwuid_r( + uid_t uid, + struct passwd *pwd, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + const char *translated; + size_t l; + int r; + + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + if (!uid_is_valid(uid)) { + r = -EINVAL; + goto fail; + } + + if (uid <= SYSTEM_UID_MAX) + goto not_found; + + if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) + goto not_found; + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByUID", + &error, + &reply, + "u", + (uint32_t) uid); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + goto not_found; + + goto fail; + } + + r = sd_bus_message_read(reply, "s", &translated); + if (r < 0) + goto fail; + + l = strlen(translated) + 1; + if (buflen < l) { + *errnop = ENOMEM; + return NSS_STATUS_TRYAGAIN; + } + + memcpy(buffer, translated, l); + + pwd->pw_name = buffer; + pwd->pw_uid = uid; + pwd->pw_gid = uid; + pwd->pw_gecos = (char*) "Dynamic User"; + pwd->pw_passwd = (char*) "*"; /* locked */ + pwd->pw_dir = (char*) "/"; + pwd->pw_shell = (char*) "/sbin/nologin"; + + *errnop = 0; + return NSS_STATUS_SUCCESS; + +not_found: + *errnop = 0; + return NSS_STATUS_NOTFOUND; + +fail: + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} + +enum nss_status _nss_systemd_getgrnam_r( + const char *name, + struct group *gr, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + uint32_t translated; + size_t l; + int r; + + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(gr); + + if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) + goto not_found; + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByName", + &error, + &reply, + "s", + name); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + goto not_found; + + goto fail; + } + + r = sd_bus_message_read(reply, "u", &translated); + if (r < 0) + goto fail; + + l = sizeof(char*) + strlen(name) + 1; + if (buflen < l) { + *errnop = ENOMEM; + return NSS_STATUS_TRYAGAIN; + } + + memzero(buffer, sizeof(char*)); + strcpy(buffer + sizeof(char*), name); + + gr->gr_name = buffer + sizeof(char*); + gr->gr_gid = (gid_t) translated; + gr->gr_passwd = (char*) "*"; /* locked */ + gr->gr_mem = (char**) buffer; + + *errnop = 0; + return NSS_STATUS_SUCCESS; + +not_found: + *errnop = 0; + return NSS_STATUS_NOTFOUND; + +fail: + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} + +enum nss_status _nss_systemd_getgrgid_r( + gid_t gid, + struct group *gr, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + const char *translated; + size_t l; + int r; + + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + if (!gid_is_valid(gid)) { + r = -EINVAL; + goto fail; + } + + if (gid <= SYSTEM_GID_MAX) + goto not_found; + + if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) + goto not_found; + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByUID", + &error, + &reply, + "u", + (uint32_t) gid); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + goto not_found; + + goto fail; + } + + r = sd_bus_message_read(reply, "s", &translated); + if (r < 0) + goto fail; + + l = sizeof(char*) + strlen(translated) + 1; + if (buflen < l) { + *errnop = ENOMEM; + return NSS_STATUS_TRYAGAIN; + } + + memzero(buffer, sizeof(char*)); + strcpy(buffer + sizeof(char*), translated); + + gr->gr_name = buffer + sizeof(char*); + gr->gr_gid = gid; + gr->gr_passwd = (char*) "*"; /* locked */ + gr->gr_mem = (char**) buffer; + + *errnop = 0; + return NSS_STATUS_SUCCESS; + +not_found: + *errnop = 0; + return NSS_STATUS_NOTFOUND; + +fail: + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} diff --git a/src/nss-systemd/nss-systemd.sym b/src/nss-systemd/nss-systemd.sym new file mode 100644 index 0000000000..955078788a --- /dev/null +++ b/src/nss-systemd/nss-systemd.sym @@ -0,0 +1,17 @@ +/*** + This file is part of systemd. + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. +***/ + +{ +global: + _nss_systemd_getpwnam_r; + _nss_systemd_getpwuid_r; + _nss_systemd_getgrnam_r; + _nss_systemd_getgrgid_r; +local: *; +}; -- cgit v1.2.3-54-g00ecf From d82047bef5b8a35fb2d1d4685f241383df1a1d76 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 14 Jul 2016 12:26:07 +0200 Subject: update TODO --- TODO | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index ef25ef578e..bb36522bf9 100644 --- a/TODO +++ b/TODO @@ -33,6 +33,29 @@ Janitorial Clean-ups: Features: +* RemoveIPC= in unit files for removing POSIX/SysV IPC objects + +* Set SERVICE_RESULT= as env var while running ExecStop= + +* Introduce ProtectSystem=strict for making the entire OS hierarchy read-only + except for a select few + +* nspawn: start UID allocation loop from hash of container name + +* in the DynamicUser=1 nss module, also map "nobody" and "root" statically + +* pid1: log about all processes we kill with with SIGKILL or in abandoned scopes, as this should normally not happen + +* nspawn: support that /proc, /sys/, /dev are pre-mounted + +* nspawn: mount esp, so that bootctl can work + +* define gpt header bits to select volatility mode + +* nspawn: mount loopback filesystems with "discard" + +* Make TasksMax= take percentages, taken relative to the pids_max sysctl and pids.max cgroup limit + * ProtectKernelLogs= (drops CAP_SYSLOG, add seccomp for syslog() syscall, and DeviceAllow to /dev/kmsg) in service files * ProtectClock= (drops CAP_SYS_TIMES, adds seecomp filters for settimeofday, adjtimex), sets DeviceAllow o /dev/rtc @@ -46,7 +69,7 @@ Features: * PrivateUsers= which maps the all user ids except root and the one specified in User= to nobody -* Add AllocateUser= for allowing dynamic user ids per-service +* ProtectControlGroups= which mounts all of /sys/fs/cgroup read-only * Add DataDirectory=, CacheDirectory= and LogDirectory= to match RuntimeDirectory=, and create it as necessary when starting a service, owned by the right user. @@ -60,8 +83,6 @@ Features: * RestrictNamespaces= or so in services (taking away the ability to create namespaces, with setns, unshare, clone) -* nspawn: make /proc/sys/net writable? - * make sure the ratelimit object can deal with USEC_INFINITY as way to turn off things * journalctl: make sure -f ends when the container indicated by -M terminates -- cgit v1.2.3-54-g00ecf From c92fcc4f4375b0aebc5919311bbf703138b21918 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Mon, 25 Jul 2016 22:01:35 +0200 Subject: units: add graphical-session.target user unit (#3678) This unit acts as a dynamic "alias" target for any concrete graphical user session like gnome-session.target; these should declare "BindsTo=graphical-session.target" so that both targets stop and start at the same time. This allows services that run in a particular graphical user session (e. g. gnome-settings-daemon.service) to declare "PartOf=graphical-session.target" without having to know or get updated for all/new session types. This will ensure that stopping the graphical session will stop all services which are associated to it. --- Makefile.am | 3 ++- man/systemd.special.xml | 51 +++++++++++++++++++++++++++++++++++++ units/user/graphical-session.target | 13 ++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 units/user/graphical-session.target diff --git a/Makefile.am b/Makefile.am index 0c27f81986..c1e1c63634 100644 --- a/Makefile.am +++ b/Makefile.am @@ -573,7 +573,8 @@ endif dist_userunit_DATA = \ units/user/basic.target \ units/user/default.target \ - units/user/exit.target + units/user/exit.target \ + units/user/graphical-session.target nodist_userunit_DATA = \ units/user/systemd-exit.service diff --git a/man/systemd.special.xml b/man/systemd.special.xml index 18ad8f92e5..18142598cb 100644 --- a/man/systemd.special.xml +++ b/man/systemd.special.xml @@ -878,6 +878,57 @@ sound.target. + + Special Passive User Units + + + graphical-session.target + + This target is active whenever any graphical session is running. It + is used to stop user services which only apply to a graphical (X, + Wayland, etc.) session when the session is terminated. Such services + should have PartOf=graphical-session.target in their + [Unit] section. A target for a particular session + (e. g. gnome-session.target) starts and stops + graphical-session.target with + BindsTo=graphical-session.target. + + Which services are started by a session target is determined by the + Wants= and Requires= dependencies. + For services that can be enabled independently, symlinks in + .wants/ and .requires/ should be + used, see + systemd.unit5. + Those symlinks should either be shipped in packages, or should be added + dynamically after installation, for example using systemctl add-wants, see + systemctl1. + + + + Nautilus as part of a GNOME session + + gnome-session.target pulls in Nautilus as + top-level service: + + [Unit] +Description=User systemd services for GNOME graphical session +Wants=nautilus.service +BindsTo=graphical-session.target + + + nautilus.service gets stopped when the session stops: + + [Unit] +Description=Render the desktop icons with Nautilus +PartOf=graphical-session.target + +[Service] +... + + + + + Special Slice Units diff --git a/units/user/graphical-session.target b/units/user/graphical-session.target new file mode 100644 index 0000000000..00d16230b7 --- /dev/null +++ b/units/user/graphical-session.target @@ -0,0 +1,13 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Current graphical user session +Documentation=man:systemd.special(7) +Requires=basic.target +RefuseManualStart=yes +StopWhenUnneeded=yes -- cgit v1.2.3-54-g00ecf From 76153ad45f09b6ae45464f2e03d3afefbb4b2afe Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 26 Jul 2016 02:19:33 -0400 Subject: journald: deprecate SplitMode=login (#3805) In this mode, messages from processes which are not part of the session land in the main journal file, and only output of processes which are properly part of the session land in the user's journal. This is confusing, in particular because systemd-coredump runs outside of the login session. "Deprecate" SplitMode=login by removing it from documentation, to discourage people from using it. --- NEWS | 7 +++++++ man/journald.conf.xml | 26 +++++++++----------------- src/journal/journald-server.h | 2 +- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/NEWS b/NEWS index ca54685878..7ff4a44835 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,12 @@ systemd System and Service Manager +CHANGES WITH 232 in spe + + * Journald's SplitMode=login setting has been deprecated. It has been + removed from documentation, and it's use is discouraged. In a future + release it will be completely removed, and made equivalent to current + default of SplitMode=uid. + CHANGES WITH 231: * In service units the various ExecXYZ= settings have been extended diff --git a/man/journald.conf.xml b/man/journald.conf.xml index fef4fde898..a9562c121a 100644 --- a/man/journald.conf.xml +++ b/man/journald.conf.xml @@ -129,23 +129,15 @@ SplitMode= - Controls whether to split up journal files per user. Split-up journal files are primarily - useful for access control: on UNIX/Linux access control is managed per file, and the journal daemon will assign - users read access to their journal files. This setting takes one of uid, - login or none. If uid, all regular users will get each - their own journal files regardless of whether their processes possess login sessions or not, however system - users will log into the system journal. If login, actually logged-in users will get each - their own journal files, but users without login session and system users will log into the system - journal. Note that in this mode, user code running outside of any login session will log into the system log - instead of the split-out user logs. Most importantly, this means that information about core dumps of user - processes collected via the - systemd-coredump8 subsystem - will end up in the system logs instead of the user logs, and thus not be accessible to the owning users. If - none, journal files are not split up by user and all messages are instead stored in the - single system journal. In this mode unprivileged users generally do not have access to their own log data. Note - that splitting up journal files by user is only available for journals stored persistently. If journals are - stored on volatile storage (see above), only a single journal file for all user IDs is kept. Defaults to - uid. + Controls whether to split up journal files per user, either uid or + none. Split journal files are primarily useful for access control: on UNIX/Linux access + control is managed per file, and the journal daemon will assign users read access to their journal files. If + uid, all regular users will each get their own journal files, and system users will log to + the system journal. If none, journal files are not split up by user and all messages are + instead stored in the single system journal. In this mode unprivileged users generally do not have access to + their own log data. Note that splitting up journal files by user is only available for journals stored + persistently. If journals are stored on volatile storage (see Storage= above), only a single + journal file is used. Defaults to uid. diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index e025a4cf90..d2a32ab422 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -43,7 +43,7 @@ typedef enum Storage { typedef enum SplitMode { SPLIT_UID, - SPLIT_LOGIN, + SPLIT_LOGIN, /* deprecated */ SPLIT_NONE, _SPLIT_MAX, _SPLIT_INVALID = -1 -- cgit v1.2.3-54-g00ecf From 1d3c86c06fca8311923fcf81af0ab0bbb66e1edd Mon Sep 17 00:00:00 2001 From: Michal Sekletar Date: Tue, 26 Jul 2016 14:25:52 +0200 Subject: systemctl: allow disable on the unit file path, but warn about it (#3806) systemd now returns an error when it is asked to perform disable on the unit file path. In the past this was allowed, but systemd never really considered an actual content of the [Install] section of the unit file. Instead it performed disable on the unit name, i.e. purged all symlinks pointing to the given unit file (undo of implicit link action done by systemd when enable is called on the unit file path) and all symlinks that have the same basename as the given unit file. However, to notice that [Install] info of the file is not consulted one must create additional symlinks manually. I argue that in most cases users do not create such links. Let's be nice to our users and don't break existing scripts that expect disable to work with the unit file path. Fixes #3706. --- src/systemctl/systemctl.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 6a0ed79a53..91caae009e 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5670,6 +5670,29 @@ static int mangle_names(char **original_names, char ***mangled_names) { return 0; } +static int normalize_names(char **names, bool warn_if_path) { + char **u; + bool was_path = false; + + STRV_FOREACH(u, names) { + int r; + + if (!is_path(*u)) + continue; + + r = free_and_strdup(u, basename(*u)); + if (r < 0) + return log_error_errno(r, "Failed to normalize unit file path: %m"); + + was_path = true; + } + + if (warn_if_path && was_path) + log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name."); + + return 0; +} + static int unit_exists(const char *unit) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; @@ -5737,6 +5760,12 @@ static int enable_unit(int argc, char *argv[], void *userdata) { return daemon_reload(argc, argv, userdata); } + if (streq(verb, "disable")) { + r = normalize_names(names, true); + if (r < 0) + return r; + } + if (install_client_side()) { if (streq(verb, "enable")) { r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes); -- cgit v1.2.3-54-g00ecf From 5a8ff0e61dd8094b2b5d0b35df2ca13b489e0dfa Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 26 Jul 2016 16:49:15 +0200 Subject: nspawn: add SYSTEMD_NSPAWN_USE_CGNS env variable (#3809) SYSTEMD_NSPAWN_USE_CGNS allows to disable the use of cgroup namespaces. --- src/nspawn/nspawn-mount.c | 5 +++-- src/nspawn/nspawn-mount.h | 2 +- src/nspawn/nspawn.c | 17 +++++++++++++---- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index ac93357ef4..803caef3dd 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -916,11 +916,12 @@ int mount_cgroups( const char *dest, bool unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, - const char *selinux_apifs_context) { + const char *selinux_apifs_context, + bool use_cgns) { if (unified_requested) return mount_unified_cgroups(dest); - else if (cg_ns_supported()) + else if (use_cgns && cg_ns_supported()) return mount_legacy_cgns_supported(userns, uid_shift, uid_range, selinux_apifs_context); return mount_legacy_cgns_unsupported(dest, userns, uid_shift, uid_range, selinux_apifs_context); diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h index 0daf145412..0eff8e1006 100644 --- a/src/nspawn/nspawn-mount.h +++ b/src/nspawn/nspawn-mount.h @@ -58,7 +58,7 @@ int custom_mount_compare(const void *a, const void *b); int mount_all(const char *dest, bool use_userns, bool in_userns, bool use_netns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); int mount_sysfs(const char *dest); -int mount_cgroups(const char *dest, bool unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); +int mount_cgroups(const char *dest, bool unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool use_cgns); int mount_systemd_cgroup_writable(const char *dest, bool unified_requested); int mount_custom(const char *dest, CustomMount *mounts, unsigned n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index f8a43d89a2..6cc1b9177d 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -194,6 +194,7 @@ static int arg_settings_trusted = -1; static char **arg_parameters = NULL; static const char *arg_container_service_name = "systemd-nspawn"; static bool arg_notify_ready = false; +static bool arg_use_cgns = true; static void help(void) { printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n" @@ -1104,6 +1105,12 @@ static int parse_argv(int argc, char *argv[]) { if (e) arg_container_service_name = e; + r = getenv_bool("SYSTEMD_NSPAWN_USE_CGNS"); + if (r < 0) + arg_use_cgns = cg_ns_supported(); + else + arg_use_cgns = r; + return 1; } @@ -2628,7 +2635,7 @@ static int inner_child( return -ESRCH; } - if (cg_ns_supported()) { + if (arg_use_cgns && cg_ns_supported()) { r = unshare(CLONE_NEWCGROUP); if (r < 0) return log_error_errno(errno, "Failed to unshare cgroup namespace"); @@ -2638,7 +2645,8 @@ static int inner_child( arg_userns_mode != USER_NAMESPACE_NO, arg_uid_shift, arg_uid_range, - arg_selinux_apifs_context); + arg_selinux_apifs_context, + arg_use_cgns); if (r < 0) return r; } else { @@ -3029,14 +3037,15 @@ static int outer_child( if (r < 0) return r; - if (!cg_ns_supported()) { + if (!arg_use_cgns || !cg_ns_supported()) { r = mount_cgroups( directory, arg_unified_cgroup_hierarchy, arg_userns_mode != USER_NAMESPACE_NO, arg_uid_shift, arg_uid_range, - arg_selinux_apifs_context); + arg_selinux_apifs_context, + arg_use_cgns); if (r < 0) return r; } -- cgit v1.2.3-54-g00ecf From c2f2c51c53e91232e6f2aa686d734728ad703f9f Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Wed, 27 Jul 2016 00:57:01 +0200 Subject: vconsole: don't do GIO_SCRNMAP / GIO_UNISCRNMAP GIO_SCRNMAP / GIO_UNISCRNMAP are related to what setfont does with -m option - namely setting intermediate map from 8bit values into unicode values. This map is global, so single setfont invocation sets it for all applicable consoles. Furthermore calling GIO_SCRNMAP before GIO_UNISCRNMAP causes issues as the former corrupts values > 255 (UNI alone would be sufficient). The bug can be easily tested with the following conf: KEYMAP=pl FONT=LatArCyrHeb-16 FONT_MAP=8859-2 --- src/vconsole/vconsole-setup.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 1118118450..abf3871fd8 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -192,8 +192,6 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map, */ static void font_copy_to_all_vcs(int fd) { struct vt_stat vcs = {}; - unsigned char map8[E_TABSZ]; - unsigned short map16[E_TABSZ]; struct unimapdesc unimapd; _cleanup_free_ struct unipair* unipairs = NULL; int i, r; @@ -234,14 +232,6 @@ static void font_copy_to_all_vcs(int fd) { cfo.height = vcs.v_active-1; /* tty1 == index 0 */ (void) ioctl(vcfd, KDFONTOP, &cfo); - /* copy map of 8bit chars */ - if (ioctl(fd, GIO_SCRNMAP, map8) >= 0) - (void) ioctl(vcfd, PIO_SCRNMAP, map8); - - /* copy map of 8bit chars -> 16bit Unicode values */ - if (ioctl(fd, GIO_UNISCRNMAP, map16) >= 0) - (void) ioctl(vcfd, PIO_UNISCRNMAP, map16); - /* copy unicode translation table */ /* unimapd is a ushort count and a pointer to an array of struct unipair { ushort, ushort } */ -- cgit v1.2.3-54-g00ecf From 9fa71843bbb31c89f81976819eec009335b09f2d Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Wed, 27 Jul 2016 00:57:01 +0200 Subject: vconsole: copy font to 63 consoles instead of 15 We copy only to allocated consoles, so the cost of looping over all possible ones is minuscule. --- src/vconsole/vconsole-setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index abf3871fd8..df18c231e0 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -209,7 +209,7 @@ static void font_copy_to_all_vcs(int fd) { return; } - for (i = 1; i <= 15; i++) { + for (i = 1; i <= 63; i++) { char vcname[strlen("/dev/vcs") + DECIMAL_STR_MAX(int)]; _cleanup_close_ int vcfd = -1; struct console_font_op cfo = {}; -- cgit v1.2.3-54-g00ecf From 042d7f5065c9c19b3f96804f9403b14d910e46d1 Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Wed, 27 Jul 2016 00:57:01 +0200 Subject: vconsole: add two new toggle functions, remove old enable/disable ones Add toggle_utf8() and toggle_utf8_sysfs() and use them in place of old enable/disable functions. toggle_utf8() also adds iutf8 setting and is set up to be called per-console (in subsequent patches). Note, that old disable_utf8() didn't bother checking if it was ok to change the kbdmode. --- src/vconsole/vconsole-setup.c | 73 ++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 46 deletions(-) diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index df18c231e0..016cf004a0 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "alloc-util.h" @@ -50,56 +51,38 @@ static bool is_vconsole(int fd) { return ioctl(fd, TIOCLINUX, data) >= 0; } -static int disable_utf8(int fd) { - int r = 0, k; - - if (ioctl(fd, KDSKBMODE, K_XLATE) < 0) - r = -errno; - - k = loop_write(fd, "\033%@", 3, false); - if (k < 0) - r = k; - - k = write_string_file("/sys/module/vt/parameters/default_utf8", "0", 0); - if (k < 0) - r = k; +static int toggle_utf8(int fd, bool utf8) { + int r; + struct termios tc = {}; + r = ioctl(fd, KDSKBMODE, utf8 ? K_UNICODE : K_XLATE); if (r < 0) - log_warning_errno(r, "Failed to disable UTF-8: %m"); - - return r; -} + return log_warning_errno(errno, "Failed to %s UTF-8 kbdmode: %m", utf8 ? "enable" : "disable"); -static int enable_utf8(int fd) { - int r = 0, k; - long current = 0; - - if (ioctl(fd, KDGKBMODE, ¤t) < 0 || current == K_XLATE) { - /* - * Change the current keyboard to unicode, unless it - * is currently in raw or off mode anyway. We - * shouldn't interfere with X11's processing of the - * key events. - * - * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html - * - */ - - if (ioctl(fd, KDSKBMODE, K_UNICODE) < 0) - r = -errno; + r = loop_write(fd, utf8 ? "\033%G" : "\033%@", 3, false); + if (r < 0) + return log_warning_errno(r, "Failed to %s UTF-8 term processing: %m", utf8 ? "enable" : "disable"); + + r = tcgetattr(fd, &tc); + if (r >= 0) { + if (utf8) + tc.c_iflag |= IUTF8; + else + tc.c_iflag &= ~IUTF8; + r = tcsetattr(fd, TCSANOW, &tc); } + if (r < 0) + return log_warning_errno(errno, "Failed to %s iutf8 flag: %m", utf8 ? "enable" : "disable"); - k = loop_write(fd, "\033%G", 3, false); - if (k < 0) - r = k; + return 0; +} - k = write_string_file("/sys/module/vt/parameters/default_utf8", "1", 0); - if (k < 0) - r = k; +static int toggle_utf8_sysfs(bool utf8) { + int r; + r = write_string_file("/sys/module/vt/parameters/default_utf8", one_zero(utf8), 0); if (r < 0) - log_warning_errno(r, "Failed to enable UTF-8: %m"); - + log_warning_errno(r, "Failed to %s sysfs UTF-8 flag: %m", utf8 ? "enable" : "disable"); return r; } @@ -306,10 +289,8 @@ int main(int argc, char **argv) { log_warning_errno(r, "Failed to read /proc/cmdline: %m"); } - if (utf8) - (void) enable_utf8(fd); - else - (void) disable_utf8(fd); + toggle_utf8_sysfs(utf8); + toggle_utf8(fd, utf8); font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) > 0; keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) > 0; -- cgit v1.2.3-54-g00ecf From 03044059bfff8b79d47efc53e2468e122f502a72 Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Wed, 27 Jul 2016 00:57:01 +0200 Subject: vconsole: Add generic is_*() functions is_allocated() and is_allocated_byfd(): Checks if the console is allocated by its index (first function) or its open descriptor (second function). is_settable(): Checks if the console is in xlate or unicode mode, so we can adjust is safely without interfering with X. --- src/vconsole/vconsole-setup.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 016cf004a0..15e7ed39b4 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -51,6 +51,37 @@ static bool is_vconsole(int fd) { return ioctl(fd, TIOCLINUX, data) >= 0; } +static bool is_allocated(unsigned int idx) { + char vcname[strlen("/dev/vcs") + DECIMAL_STR_MAX(int)]; + + xsprintf(vcname, "/dev/vcs%i", idx); + return access(vcname, F_OK) == 0; +} + +static bool is_allocated_byfd(int fd) { + struct vt_stat vcs = {}; + + if (ioctl(fd, VT_GETSTATE, &vcs) < 0) { + log_warning_errno(errno, "VT_GETSTATE failed: %m"); + return false; + } + return is_allocated(vcs.v_active); +} + +static bool is_settable(int fd) { + int r, curr_mode; + + r = ioctl(fd, KDGKBMODE, &curr_mode); + /* + * Make sure we only adjust consoles in K_XLATE or K_UNICODE mode. + * Oterwise we would (likely) interfere with X11's processing of the + * key events. + * + * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html + */ + return r == 0 && IN_SET(curr_mode, K_XLATE, K_UNICODE); +} + static int toggle_utf8(int fd, bool utf8) { int r; struct termios tc = {}; @@ -262,6 +293,16 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } + if (!is_allocated_byfd(fd)) { + log_error("Virtual console %s is not allocated.", vc); + return EXIT_FAILURE; + } + + if (!is_settable(fd)) { + log_error("Virtual console %s is not in K_XLATE or K_UNICODE.", vc); + return EXIT_FAILURE; + } + utf8 = is_locale_utf8(); r = parse_env_file("/etc/vconsole.conf", NEWLINE, -- cgit v1.2.3-54-g00ecf From c9d2b3d0f00a00049aeb8a6dba78200e6df48244 Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Wed, 27 Jul 2016 00:57:01 +0200 Subject: vconsole: updates of keyboard/font loading functions Change return convention to -errno/==0 and use isempty() instead of just pointer tests. --- src/vconsole/vconsole-setup.c | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 15e7ed39b4..c98c699922 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -119,12 +119,12 @@ static int toggle_utf8_sysfs(bool utf8) { static int keyboard_load_and_wait(const char *vc, const char *map, const char *map_toggle, bool utf8) { const char *args[8]; - int i = 0, r; + int i = 0; pid_t pid; /* An empty map means kernel map */ if (isempty(map)) - return 1; + return 0; args[i++] = KBD_LOADKEYS; args[i++] = "-q"; @@ -149,34 +149,31 @@ static int keyboard_load_and_wait(const char *vc, const char *map, const char *m _exit(EXIT_FAILURE); } - r = wait_for_terminate_and_warn(KBD_LOADKEYS, pid, true); - if (r < 0) - return r; - - return r == 0; + return wait_for_terminate_and_warn(KBD_LOADKEYS, pid, true); } static int font_load_and_wait(const char *vc, const char *font, const char *map, const char *unimap) { const char *args[9]; - int i = 0, r; + int i = 0; pid_t pid; - /* An empty font means kernel font */ - if (isempty(font)) - return 1; + /* Any part can be set independently */ + if (isempty(font) && isempty(map) && isempty(unimap)) + return 0; args[i++] = KBD_SETFONT; args[i++] = "-C"; args[i++] = vc; - args[i++] = font; - if (map) { + if (!isempty(map)) { args[i++] = "-m"; args[i++] = map; } - if (unimap) { + if (!isempty(unimap)) { args[i++] = "-u"; args[i++] = unimap; } + if (!isempty(font)) + args[i++] = font; args[i++] = NULL; pid = fork(); @@ -191,11 +188,7 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map, _exit(EXIT_FAILURE); } - r = wait_for_terminate_and_warn(KBD_SETFONT, pid, true); - if (r < 0) - return r; - - return r == 0; + return wait_for_terminate_and_warn(KBD_SETFONT, pid, true); } /* @@ -333,8 +326,8 @@ int main(int argc, char **argv) { toggle_utf8_sysfs(utf8); toggle_utf8(fd, utf8); - font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) > 0; - keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) > 0; + font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) == 0; + keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) == 0; /* Only copy the font when we executed setfont successfully */ if (font_copy && font_ok) -- cgit v1.2.3-54-g00ecf From eb22d84b47f16bedb60824b441900715fd79841d Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Wed, 27 Jul 2016 00:57:01 +0200 Subject: vconsole: use KD_FONT_OP_GET/SET to handle copying We now use KD_FONT_OP_GET & KD_FONT_OP_SET instead of problematic KD_FONT_OP_COPY. --- src/vconsole/vconsole-setup.c | 93 ++++++++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index c98c699922..5da807bf17 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -196,11 +196,21 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map, * we update all possibly already allocated VTs with the configured * font. It also allows to restart systemd-vconsole-setup.service, * to apply a new font to all VTs. + * + * We also setup per-console utf8 related stuff: kbdmode, term + * processing, stty iutf8. */ -static void font_copy_to_all_vcs(int fd) { +static void setup_remaining_vcs(int fd, bool utf8) { + struct console_font_op cfo = { + .op = KD_FONT_OP_GET, .flags = 0, + .width = 32, .height = 32, + .charcount = 512, + }; struct vt_stat vcs = {}; + struct unimapinit adv = {}; struct unimapdesc unimapd; _cleanup_free_ struct unipair* unipairs = NULL; + _cleanup_free_ void *fontbuf = NULL; int i, r; unipairs = new(struct unipair, USHRT_MAX); @@ -209,46 +219,73 @@ static void font_copy_to_all_vcs(int fd) { return; } + fontbuf = malloc(cfo.width * cfo.height * cfo.charcount / 8); + if (!fontbuf) { + log_oom(); + return; + } + /* get active, and 16 bit mask of used VT numbers */ r = ioctl(fd, VT_GETSTATE, &vcs); if (r < 0) { - log_debug_errno(errno, "VT_GETSTATE failed, ignoring: %m"); + log_warning_errno(errno, "VT_GETSTATE failed, ignoring remaining consoles: %m"); return; } + /* get fonts from source console */ + cfo.data = fontbuf; + r = ioctl(fd, KDFONTOP, &cfo); + if (r < 0) + log_warning_errno(errno, "KD_FONT_OP_GET failed, fonts will not be copied: %m"); + else { + unimapd.entries = unipairs; + unimapd.entry_ct = USHRT_MAX; + r = ioctl(fd, GIO_UNIMAP, &unimapd); + if (r < 0) + log_warning_errno(errno, "GIO_UNIMAP failed, fonts will not be copied: %m"); + else + cfo.op = KD_FONT_OP_SET; + } + for (i = 1; i <= 63; i++) { - char vcname[strlen("/dev/vcs") + DECIMAL_STR_MAX(int)]; - _cleanup_close_ int vcfd = -1; - struct console_font_op cfo = {}; + char ttyname[strlen("/dev/tty") + DECIMAL_STR_MAX(int)]; + _cleanup_close_ int fd_d = -1; - if (i == vcs.v_active) + if (i == vcs.v_active || !is_allocated(i)) continue; - /* skip non-allocated ttys */ - xsprintf(vcname, "/dev/vcs%i", i); - if (access(vcname, F_OK) < 0) + /* try to open terminal */ + xsprintf(ttyname, "/dev/tty%i", i); + fd_d = open_terminal(ttyname, O_RDWR|O_CLOEXEC); + if (fd_d < 0) { + log_warning_errno(fd_d, "Unable to open tty%i, fonts will not be copied: %m", i); continue; + } - xsprintf(vcname, "/dev/tty%i", i); - vcfd = open_terminal(vcname, O_RDWR|O_CLOEXEC); - if (vcfd < 0) + if (!is_settable(fd_d)) continue; - /* copy font from active VT, where the font was uploaded to */ - cfo.op = KD_FONT_OP_COPY; - cfo.height = vcs.v_active-1; /* tty1 == index 0 */ - (void) ioctl(vcfd, KDFONTOP, &cfo); + toggle_utf8(fd_d, utf8); + + if (cfo.op != KD_FONT_OP_SET) + continue; + + r = ioctl(fd_d, KDFONTOP, &cfo); + if (r < 0) { + log_warning_errno(errno, "KD_FONT_OP_SET failed, fonts will not be copied to tty%i: %m", i); + continue; + } /* copy unicode translation table */ /* unimapd is a ushort count and a pointer to an array of struct unipair { ushort, ushort } */ - unimapd.entries = unipairs; - unimapd.entry_ct = USHRT_MAX; - if (ioctl(fd, GIO_UNIMAP, &unimapd) >= 0) { - struct unimapinit adv = { 0, 0, 0 }; - - (void) ioctl(vcfd, PIO_UNIMAPCLR, &adv); - (void) ioctl(vcfd, PIO_UNIMAP, &unimapd); + r = ioctl(fd_d, PIO_UNIMAPCLR, &adv); + if (r < 0) + log_warning_errno(errno, "PIO_UNIMAPCLR failed, unimaps might be incorrect for tty%i: %m", i); + else { + r = ioctl(fd_d, PIO_UNIMAP, &unimapd); + if (r < 0) + log_warning_errno(errno, "PIO_UNIMAP failed, unimaps might be incorrect for tty%i: %m", i); } } } @@ -325,13 +362,15 @@ int main(int argc, char **argv) { toggle_utf8_sysfs(utf8); toggle_utf8(fd, utf8); - font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) == 0; keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) == 0; - /* Only copy the font when we executed setfont successfully */ - if (font_copy && font_ok) - (void) font_copy_to_all_vcs(fd); + if (font_copy) { + if (font_ok) + setup_remaining_vcs(fd, utf8); + else + log_warning("Setting source virtual console failed, ignoring remaining ones."); + } return font_ok && keyboard_ok ? EXIT_SUCCESS : EXIT_FAILURE; } -- cgit v1.2.3-54-g00ecf From 8125e8d38e3aa099c7dce8b0161997b8842aebdc Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Wed, 27 Jul 2016 00:57:01 +0200 Subject: vconsole: Don't do static installation under sysinit.target Udev rules cover all the necessary initializations. As the service now is neither installed, nor installable - we can remove explicit dependencies and RemainAfterExit=yes option. --- Makefile.am | 3 --- units/systemd-vconsole-setup.service.in | 3 --- 2 files changed, 6 deletions(-) diff --git a/Makefile.am b/Makefile.am index c9fb4917ad..7535b505fb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4628,9 +4628,6 @@ nodist_udevrules_DATA += \ nodist_systemunit_DATA += \ units/systemd-vconsole-setup.service - -SYSINIT_TARGET_WANTS += \ - systemd-vconsole-setup.service endif EXTRA_DIST += \ diff --git a/units/systemd-vconsole-setup.service.in b/units/systemd-vconsole-setup.service.in index 6160361871..2bd1fd1a5d 100644 --- a/units/systemd-vconsole-setup.service.in +++ b/units/systemd-vconsole-setup.service.in @@ -9,11 +9,8 @@ Description=Setup Virtual Console Documentation=man:systemd-vconsole-setup.service(8) man:vconsole.conf(5) DefaultDependencies=no -Conflicts=shutdown.target -Before=sysinit.target shutdown.target ConditionPathExists=/dev/tty0 [Service] Type=oneshot -RemainAfterExit=yes ExecStart=@rootlibexecdir@/systemd-vconsole-setup -- cgit v1.2.3-54-g00ecf From af7a5213f13051b5c399787d8a88ab640382192c Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Wed, 27 Jul 2016 00:57:01 +0200 Subject: vconsole: add copyright line --- src/vconsole/vconsole-setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 5da807bf17..a8f4f05771 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -2,6 +2,7 @@ This file is part of systemd. Copyright 2010 Kay Sievers + Copyright 2016 Michal Soltys systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by -- cgit v1.2.3-54-g00ecf From 9e303250acafe284a3406b71dbe9a7620ee71fcc Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Wed, 27 Jul 2016 00:57:01 +0200 Subject: vconsole: correct kernel command line namespace --- src/vconsole/vconsole-setup.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index a8f4f05771..59e6c90c9a 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -351,8 +351,12 @@ int main(int argc, char **argv) { if (detect_container() <= 0) { r = parse_env_file("/proc/cmdline", WHITESPACE, "vconsole.keymap", &vc_keymap, - "vconsole.keymap.toggle", &vc_keymap_toggle, + "vconsole.keymap_toggle", &vc_keymap_toggle, "vconsole.font", &vc_font, + "vconsole.font_map", &vc_font_map, + "vconsole.font_unimap", &vc_font_unimap, + /* compatibility with obsolete multiple-dot scheme */ + "vconsole.keymap.toggle", &vc_keymap_toggle, "vconsole.font.map", &vc_font_map, "vconsole.font.unimap", &vc_font_unimap, NULL); -- cgit v1.2.3-54-g00ecf From 61eca97fceaa95f76732a47ae2a7eb98cc6995c5 Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Wed, 27 Jul 2016 00:57:01 +0200 Subject: vconsole: update man page - about namespace - about udev rules --- man/vconsole.conf.xml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/man/vconsole.conf.xml b/man/vconsole.conf.xml index 27196d44e9..7f6ae3452f 100644 --- a/man/vconsole.conf.xml +++ b/man/vconsole.conf.xml @@ -55,8 +55,11 @@ The /etc/vconsole.conf file configures the virtual console, i.e. keyboard mapping and console font. It is - applied at boot by - systemd-vconsole-setup.service8. + applied at boot by udev using 90-vconsole.rules file. + You can safely mask this file if you want to avoid this kind of initialization. + There is also systemd-vconsole-setup.service8 + provided that you can conveniently use at any time to [re]initialize consoles. + The basic file format of the vconsole.conf is a newline-separated list of @@ -68,10 +71,10 @@ Note that the kernel command line options vconsole.keymap=, - vconsole.keymap.toggle=, + vconsole.keymap_toggle=, vconsole.font=, - vconsole.font.map=, - vconsole.font.unimap= may be used + vconsole.font_map=, + vconsole.font_unimap= may be used to override the console settings at boot. Depending on the operating system other configuration files -- cgit v1.2.3-54-g00ecf From b6b609dbc202e5645fc58e87b8a7d46426ee4bb7 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Wed, 27 Jul 2016 05:32:37 +0200 Subject: string-util: rework memory_erase() to not use GCC optimize attribute (#3812) "#pragma GCC optimize" is merely a convenience to decorate multiple functions with attribute optimize. And the manual has this to say about this attribute: This attribute should be used for debugging purposes only. It is not suitable in production code. Some versions of GCC also seem to have a problem with this pragma in combination with LTO, resulting in ICEs. So use a different approach (indirect the memset call via a volatile function pointer) as implemented in openssl's crypto/mem_clr.c. Closes: #3811 --- src/basic/string-util.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/basic/string-util.c b/src/basic/string-util.c index e9856b90d3..5d4510e1b3 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "alloc-util.h" #include "gunicode.h" @@ -822,25 +823,20 @@ int free_and_strdup(char **p, const char *s) { return 1; } -#pragma GCC push_options -#pragma GCC optimize("O0") +/* + * Pointer to memset is volatile so that compiler must de-reference + * the pointer and can't assume that it points to any function in + * particular (such as memset, which it then might further "optimize") + * This approach is inspired by openssl's crypto/mem_clr.c. + */ +typedef void *(*memset_t)(void *,int,size_t); -void* memory_erase(void *p, size_t l) { - volatile uint8_t* x = (volatile uint8_t*) p; - - /* This basically does what memset() does, but hopefully isn't - * optimized away by the compiler. One of those days, when - * glibc learns memset_s() we should replace this call by - * memset_s(), but until then this has to do. */ - - for (; l > 0; l--) - *(x++) = 'x'; +static volatile memset_t memset_func = memset; - return p; +void* memory_erase(void *p, size_t l) { + return memset_func(p, 'x', l); } -#pragma GCC pop_options - char* string_erase(char *x) { if (!x) -- cgit v1.2.3-54-g00ecf From d5317f3544654d9a95bd589c75b94ea39facc3b5 Mon Sep 17 00:00:00 2001 From: Dennis Wassenberg Date: Tue, 26 Jul 2016 16:41:47 +0200 Subject: hwdb: add Lenovo T440p pointing stick speed fix Like many other recent thinkpads the factory default pointingstick sensitivity on these devices is quite low, making the pointingstick very slow in moving the cursor. This extends the existing hwdb rules for tweaking the sensitivity to also apply to the T440p models. --- hwdb/70-pointingstick.hwdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index ec166ead40..d69e234773 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -97,6 +97,8 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX230 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX230Tablet:* # Lenovo Thinkpad X240 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX240:* +# Lenovo Thinkpad T440p +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT440p:* # Lenovo Thinkpad T440s evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT440s:* # Lenovo Thinkpad T540p -- cgit v1.2.3-54-g00ecf From f8a0b229d2c5193a9a8538807338f8f7199debc2 Mon Sep 17 00:00:00 2001 From: Dennis Wassenberg Date: Tue, 26 Jul 2016 16:47:54 +0200 Subject: hwdb: add Lenovo L450 pointing stick speed fix Like many other recent thinkpads the factory default pointingstick sensitivity on these devices is quite low, making the pointingstick very slow in moving the cursor. This extends the existing hwdb rules for tweaking the sensitivity to also apply to the L450 models. --- hwdb/70-pointingstick.hwdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index d69e234773..f38ff3fae2 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -103,6 +103,8 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT440 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT440s:* # Lenovo Thinkpad T540p evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT540p:* +# Lenovo Thinkpad L450 +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadL450:* # Lenovo Thinkpad T550 / W550s evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT550:* # Lenovo Thinkpad X1 Carbon 3rd gen -- cgit v1.2.3-54-g00ecf From 9e67418c407bd6d75a7612b66ef7d945c15689a6 Mon Sep 17 00:00:00 2001 From: Dennis Wassenberg Date: Tue, 26 Jul 2016 16:50:07 +0200 Subject: hwdb: add Lenovo T450s pointing stick speed fix Like many other recent thinkpads the factory default pointingstick sensitivity on these devices is quite low, making the pointingstick very slow in moving the cursor. This extends the existing hwdb rules for tweaking the sensitivity to also apply to the T450s models. --- hwdb/70-pointingstick.hwdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index f38ff3fae2..92966bafb8 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -105,6 +105,8 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT440 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT540p:* # Lenovo Thinkpad L450 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadL450:* +# Lenovo Thinkpad T450s +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT450s:* # Lenovo Thinkpad T550 / W550s evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT550:* # Lenovo Thinkpad X1 Carbon 3rd gen -- cgit v1.2.3-54-g00ecf From 612ad804827545a5da0ec14558c6ddb5f816b228 Mon Sep 17 00:00:00 2001 From: Dennis Wassenberg Date: Wed, 27 Jul 2016 10:56:50 +0200 Subject: hwdb: add Lenovo X250 pointing stick speed fix Like many other recent thinkpads the factory default pointingstick sensitivity on these devices is quite low, making the pointingstick very slow in moving the cursor. This extends the existing hwdb rules for tweaking the sensitivity to also apply to the X250 models. --- hwdb/70-pointingstick.hwdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index 92966bafb8..ba1939c8e7 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -109,6 +109,8 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadL450 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT450s:* # Lenovo Thinkpad T550 / W550s evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT550:* +# Lenovo Thinkpad X250 +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX250:* # Lenovo Thinkpad X1 Carbon 3rd gen evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:* # Lenovo Thinkpad X1 Carbon 4th gen -- cgit v1.2.3-54-g00ecf From 95f6fc608d63aa0fbeb5d170dbe1066e5a70a1cb Mon Sep 17 00:00:00 2001 From: Dennis Wassenberg Date: Wed, 27 Jul 2016 10:59:38 +0200 Subject: hwdb: add Lenovo L460 pointing stick speed fix Like many other recent thinkpads the factory default pointingstick sensitivity on these devices is quite low, making the pointingstick very slow in moving the cursor. This extends the existing hwdb rules for tweaking the sensitivity to also apply to the L460 models. --- hwdb/70-pointingstick.hwdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index ba1939c8e7..cdda2e8837 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -111,6 +111,8 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT450 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT550:* # Lenovo Thinkpad X250 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX250:* +# Lenovo Thinkpad L460 +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadL460:* # Lenovo Thinkpad X1 Carbon 3rd gen evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:* # Lenovo Thinkpad X1 Carbon 4th gen -- cgit v1.2.3-54-g00ecf From ded495d94774dce142540ed2463142b2aed0592f Mon Sep 17 00:00:00 2001 From: Dennis Wassenberg Date: Wed, 27 Jul 2016 11:00:27 +0200 Subject: hwdb: add Lenovo T460s pointing stick speed fix Like many other recent thinkpads the factory default pointingstick sensitivity on these devices is quite low, making the pointingstick very slow in moving the cursor. This extends the existing hwdb rules for tweaking the sensitivity to also apply to the T460s models. --- hwdb/70-pointingstick.hwdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index cdda2e8837..31306ce77c 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -113,6 +113,8 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT550 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX250:* # Lenovo Thinkpad L460 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadL460:* +# Lenovo Thinkpad T460s +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT460s:* # Lenovo Thinkpad X1 Carbon 3rd gen evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:* # Lenovo Thinkpad X1 Carbon 4th gen -- cgit v1.2.3-54-g00ecf From 4499df99c1e3e376438287a20a64a5bc8b30a2d7 Mon Sep 17 00:00:00 2001 From: Dennis Wassenberg Date: Wed, 27 Jul 2016 11:00:56 +0200 Subject: hwdb: add Lenovo T560 pointing stick speed fix Like many other recent thinkpads the factory default pointingstick sensitivity on these devices is quite low, making the pointingstick very slow in moving the cursor. This extends the existing hwdb rules for tweaking the sensitivity to also apply to the T560 models. --- hwdb/70-pointingstick.hwdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index 31306ce77c..16695f2b2c 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -115,6 +115,8 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX250 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadL460:* # Lenovo Thinkpad T460s evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT460s:* +# Lenovo Thinkpad T560 +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT560:* # Lenovo Thinkpad X1 Carbon 3rd gen evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:* # Lenovo Thinkpad X1 Carbon 4th gen -- cgit v1.2.3-54-g00ecf From 57b8b16237187e64bcc99564af4d0133b7bed698 Mon Sep 17 00:00:00 2001 From: Dennis Wassenberg Date: Wed, 27 Jul 2016 11:01:27 +0200 Subject: hwdb: add Lenovo X260 pointing stick speed fix Like many other recent thinkpads the factory default pointingstick sensitivity on these devices is quite low, making the pointingstick very slow in moving the cursor. This extends the existing hwdb rules for tweaking the sensitivity to also apply to the X260 models. --- hwdb/70-pointingstick.hwdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index 16695f2b2c..8a74573904 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -117,6 +117,8 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadL460 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT460s:* # Lenovo Thinkpad T560 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT560:* +# Lenovo Thinkpad X260 +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX260:* # Lenovo Thinkpad X1 Carbon 3rd gen evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:* # Lenovo Thinkpad X1 Carbon 4th gen -- cgit v1.2.3-54-g00ecf From 689e4e6a94222b4d58a8b9cb3c51cc2f82268aa9 Mon Sep 17 00:00:00 2001 From: Christian Rebischke Date: Thu, 28 Jul 2016 04:40:20 +0200 Subject: systemctl: be sure to be quiet with 'systemctl is-enabled --quiet' (#3819) Fixes #3813. --- src/systemctl/systemctl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 91caae009e..782824ff38 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5566,10 +5566,12 @@ static int enable_sysv_units(const char *verb, char **args) { if (!found_sysv) continue; - if (found_native) - log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]); - else - log_info("%s is not a native service, redirecting to systemd-sysv-install.", name); + if (!arg_quiet) { + if (found_native) + log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]); + else + log_info("%s is not a native service, redirecting to systemd-sysv-install.", name); + } if (!isempty(arg_root)) argv[c++] = q = strappend("--root=", arg_root); -- cgit v1.2.3-54-g00ecf From 4e3382bdd70a54628ffe030c5d37e06713c329ab Mon Sep 17 00:00:00 2001 From: Davide Cavalca Date: Thu, 28 Jul 2016 20:42:45 -0700 Subject: build-sys: conditionally disable LTO if requested (#3823) This adds a --disable-lto option to ./configure, but does not change the default behavior. --- configure.ac | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index cf595e68c0..a86deca471 100644 --- a/configure.ac +++ b/configure.ac @@ -211,9 +211,12 @@ AS_CASE([$CC], [*clang*], -Wno-gnu-variable-sized-type-not-at-end \ ])]) +AC_ARG_ENABLE([lto], [AS_HELP_STRING([--disable-lto], [disable -flto])], + [], [enable_lto=yes]) AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*], - [CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\ - -flto])], + [AS_IF([test "x$enable_lto" = "xyes"], + [CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [-flto])], + [AC_MSG_RESULT([disabling -flto as requested])])], [AC_MSG_RESULT([skipping -flto, optimization not enabled])]) AC_SUBST([OUR_CFLAGS], "$with_cflags $sanitizer_cflags") -- cgit v1.2.3-54-g00ecf From e4d214efc20245c37d9b1e3a7e35c6a4443da131 Mon Sep 17 00:00:00 2001 From: Davide Cavalca Date: Wed, 27 Jul 2016 14:17:52 -0700 Subject: tests: skip udev-test if running inside a chroot --- test/udev-test.pl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/udev-test.pl b/test/udev-test.pl index da0a4e1f6b..35a2668fb3 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -1535,6 +1535,13 @@ if (!($<==0)) { exit($EXIT_TEST_SKIP); } +# skip the test when running in a chroot +system("systemd-detect-virt", "-r", "-q"); +if ($? >> 8 == 0) { + print "Running in a chroot, skipping the test.\n"; + exit($EXIT_TEST_SKIP); +} + # skip the test when running in a container system("systemd-detect-virt", "-c", "-q"); if ($? >> 8 == 0) { -- cgit v1.2.3-54-g00ecf From 40a23924efc64598d580b5fd92ef3937583d1fc9 Mon Sep 17 00:00:00 2001 From: Steve Muir Date: Wed, 27 Jul 2016 14:19:37 -0700 Subject: tests: don't test hostname if it looks like an id128 The condition tests for hostname will fail if hostname looks like an id128. The test function attempts to convert hostname to an id128, and if that succeeds compare it to the machine ID (presumably because the 'hostname' condition test is overloaded to also test machine ID). That will typically fail, and unfortunately the 'mock' utility generates a random hostname that happens to have the same format as an id128, thus causing a test failure. --- src/test/test-condition.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/test/test-condition.c b/src/test/test-condition.c index 987862f1c6..4ef61ebfa5 100644 --- a/src/test/test-condition.c +++ b/src/test/test-condition.c @@ -25,6 +25,7 @@ #include "audit-util.h" #include "condition.h" #include "hostname-util.h" +#include "id128-util.h" #include "ima-util.h" #include "log.h" #include "macro.h" @@ -142,9 +143,14 @@ static void test_condition_test_host(void) { hostname = gethostname_malloc(); assert_se(hostname); - condition = condition_new(CONDITION_HOST, hostname, false, false); - assert_se(condition_test(condition)); - condition_free(condition); + /* if hostname looks like an id128 then skip testing it */ + if (id128_is_valid(hostname)) { + log_notice("hostname is an id128, skipping test"); + } else { + condition = condition_new(CONDITION_HOST, hostname, false, false); + assert_se(condition_test(condition)); + condition_free(condition); + } } static void test_condition_test_architecture(void) { -- cgit v1.2.3-54-g00ecf From 76c19e9f6c8e8e5922e43716137d532c542e34c8 Mon Sep 17 00:00:00 2001 From: Davide Cavalca Date: Wed, 27 Jul 2016 14:22:26 -0700 Subject: tests: skip process 1 tests if systemd not is running No point running tests against process 1 if systemd is not running as that process. This is a rework of an unpublished patch by @9muir. --- src/test/test-process-util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c index 562ad4acb8..9ada46b1e9 100644 --- a/src/test/test-process-util.c +++ b/src/test/test-process-util.c @@ -40,6 +40,7 @@ #include "stdio-util.h" #include "string-util.h" #include "terminal-util.h" +#include "test-helper.h" #include "util.h" #include "virt.h" @@ -357,7 +358,7 @@ int main(int argc, char *argv[]) { (void) parse_pid(argv[1], &pid); test_get_process_comm(pid); } else { - test_get_process_comm(1); + TEST_REQ_RUNNING_SYSTEMD(test_get_process_comm(1)); test_get_process_comm(getpid()); } -- cgit v1.2.3-54-g00ecf From 4dd4cb8fe40baea007336a346ec2aa645890eec3 Mon Sep 17 00:00:00 2001 From: Steve Muir Date: Wed, 27 Jul 2016 14:23:44 -0700 Subject: tests: don't run private device tests if running in a container Private devices don't exist when running in a container, so skip the related tests. --- src/test/test-execute.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 77ef4e8b2a..baf5b96487 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -33,6 +33,7 @@ #include "test-helper.h" #include "unit.h" #include "util.h" +#include "virt.h" typedef void (*test_function_t)(Manager *m); @@ -111,6 +112,10 @@ static void test_exec_privatetmp(Manager *m) { } static void test_exec_privatedevices(Manager *m) { + if (detect_container() > 0) { + log_notice("testing in container, skipping private device tests"); + return; + } test(m, "exec-privatedevices-yes.service", 0, CLD_EXITED); test(m, "exec-privatedevices-no.service", 0, CLD_EXITED); } -- cgit v1.2.3-54-g00ecf From 65c1cdb282d33f72d2c247dfe13dd7c8baa8f302 Mon Sep 17 00:00:00 2001 From: Maxime de Roucy Date: Sun, 31 Jul 2016 14:38:56 +0200 Subject: documentation: add cgroup-v2.txt link add cgroup-v2.txt link in section "Unified and Legacy Control Group Hierarchies" of systemd.resource-control man. --- man/systemd.resource-control.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index bf44a68345..76f3370b53 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -99,9 +99,10 @@ Unified and Legacy Control Group Hierarchies - The unified control group hierarchy is the new version of kernel control group interface. Depending on the - resource type, there are differences in resource control capabilities. Also, because of interface changes, some - resource types have a separate set of options on the unified hierarchy. + The unified control group hierarchy is the new version of kernel control group interface, see cgroup-v2.txt. Depending on the resource type, + there are differences in resource control capabilities. Also, because of interface changes, some resource types + have separate set of options on the unified hierarchy. -- cgit v1.2.3-54-g00ecf From c23b2c70bf65d3fdf869c60eee4072b1d4e5905b Mon Sep 17 00:00:00 2001 From: Maxime de Roucy Date: Sun, 31 Jul 2016 14:43:23 +0200 Subject: documentation: cgroup-v1 and systemd user instance Explain in the systemd.resource-control man that systemd user instance can't use resource control on cgroup-v1. --- man/systemd.resource-control.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index 76f3370b53..cb8c896e5c 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -127,6 +127,13 @@ settings of a unit for a given resource type are for the other hierarchy type, the settings are translated and applied. If there are any valid settings for the hierarchy in use, all translations are disabled for the resource type. Mixing the two types of settings on a unit can lead to confusing results. + + Legacy control group hierarchy (see cgroups.txt), also called cgroup-v1, + doesn't allow safe delegation of controllers to unprivileged processes. If the system use legacy control group + hierarchy, resource control is disabled for systemd user instance, see + systemd1. + -- cgit v1.2.3-54-g00ecf From cb3e4417590196bd30e1b8097348dca6ba34bd15 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 31 Jul 2016 21:38:47 -0400 Subject: logind: 0% and 100% should be valid for UserTasksMax (#3836) config_parse_user_tasks_max() was incorrectly accepting percentage value between 1 and 99. Update it to accept 0% and 100%. This brings it in line with TasksMax handling in systemd. --- src/login/logind-user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 348e396292..63363035e7 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -893,7 +893,7 @@ int config_parse_user_tasks_max( /* First, try to parse as percentage */ r = parse_percent(rvalue); - if (r > 0 && r < 100) + if (r >= 0) k = system_tasks_max_scale(r, 100U); else { -- cgit v1.2.3-54-g00ecf From 6d1e2ddd59f929ce98e400cb14fba7a873e2b409 Mon Sep 17 00:00:00 2001 From: Mike Gilbert Date: Sun, 31 Jul 2016 21:50:50 -0400 Subject: test-path-util: check for /lt-test-path-util or /test-path-util (#3841) Depending on how binutils was configured and the --enable-fast-install configure option, the test binary might be called either name. Fixes: https://github.com/systemd/systemd/issues/3838 --- src/test/test-path-util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 6094d4c3e5..164a10d8a8 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -114,7 +114,8 @@ static void test_find_binary(const char *self) { assert_se(find_binary(self, &p) == 0); puts(p); - assert_se(endswith(p, "/lt-test-path-util")); + /* libtool might prefix the binary name with "lt-" */ + assert_se(endswith(p, "/lt-test-path-util") || endswith(p, "/test-path-util")); assert_se(path_is_absolute(p)); free(p); -- cgit v1.2.3-54-g00ecf From 2d37cd5356f666b399c5ae93ce77053f501d0e33 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 24 Jul 2016 14:12:58 -0400 Subject: Add enable_disable() helper In this patch "enabled" and "disabled" is used exclusively, but "enable" and "disable" forms are need for the following patch. --- src/basic/util.h | 4 ++++ src/boot/bootctl.c | 2 +- src/journal-remote/journal-remote.c | 2 +- src/network/networkd-link.c | 8 ++------ src/timedate/timedated.c | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/basic/util.h b/src/basic/util.h index 44497dcd78..bb2fc318ef 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -61,6 +61,10 @@ static inline const char* one_zero(bool b) { return b ? "1" : "0"; } +static inline const char* enable_disable(bool b) { + return b ? "enable" : "disable"; +} + void execute_directories(const char* const* directories, usec_t timeout, char *argv[]); bool plymouth_running(void); diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index ff8c7a38dd..a7cdf92ed2 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -1094,7 +1094,7 @@ static int verb_status(int argc, char *argv[], void *userdata) { if (r < 0) log_warning_errno(r, "Failed to query secure boot status: %m"); else - printf(" Secure Boot: %s\n", r ? "enabled" : "disabled"); + printf(" Secure Boot: %sd\n", enable_disable(r)); r = is_efi_secure_boot_setup_mode(); if (r < 0) diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index 35a1e55f9e..f1ef90ed7a 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -1564,7 +1564,7 @@ int main(int argc, char **argv) { if (r < 0) log_error_errno(r, "Failed to enable watchdog: %m"); else - log_debug("Watchdog is %s.", r > 0 ? "enabled" : "disabled"); + log_debug("Watchdog is %sd.", enable_disable(r > 0)); log_debug("%s running as pid "PID_FMT, program_invocation_short_name, getpid()); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 82f56158be..a0da697707 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -256,12 +256,8 @@ static int link_enable_ipv6(Link *link) { r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE); if (r < 0) log_link_warning_errno(link, r, "Cannot %s IPv6 for interface %s: %m", disabled ? "disable" : "enable", link->ifname); - else { - if (disabled) - log_link_info(link, "IPv6 disabled for interface: %m"); - else - log_link_info(link, "IPv6 enabled for interface: %m"); - } + else + log_link_info(link, "IPv6 %sd for interface: %m", enable_disable(!disabled)); return 0; } diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index ffec609c69..490929e93b 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -637,7 +637,7 @@ static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error return r; c->use_ntp = enabled; - log_info("Set NTP to %s", enabled ? "enabled" : "disabled"); + log_info("Set NTP to %sd", enable_disable(enabled)); (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", NULL); -- cgit v1.2.3-54-g00ecf From aaa709bbaa6b909278f3ec0679b49a484423d913 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 24 Jul 2016 14:14:20 -0400 Subject: vconsole-setup: add lots of debug messages For error messages, make them more meaningful by printing the tty name. Follow-up for #3742. --- src/vconsole/vconsole-setup.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 59e6c90c9a..c0d76f9685 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -83,17 +83,19 @@ static bool is_settable(int fd) { return r == 0 && IN_SET(curr_mode, K_XLATE, K_UNICODE); } -static int toggle_utf8(int fd, bool utf8) { +static int toggle_utf8(const char *name, int fd, bool utf8) { int r; struct termios tc = {}; + assert(name); + r = ioctl(fd, KDSKBMODE, utf8 ? K_UNICODE : K_XLATE); if (r < 0) - return log_warning_errno(errno, "Failed to %s UTF-8 kbdmode: %m", utf8 ? "enable" : "disable"); + return log_warning_errno(errno, "Failed to %s UTF-8 kbdmode on %s: %m", enable_disable(utf8), name); r = loop_write(fd, utf8 ? "\033%G" : "\033%@", 3, false); if (r < 0) - return log_warning_errno(r, "Failed to %s UTF-8 term processing: %m", utf8 ? "enable" : "disable"); + return log_warning_errno(r, "Failed to %s UTF-8 term processing on %s: %m", enable_disable(utf8), name); r = tcgetattr(fd, &tc); if (r >= 0) { @@ -104,8 +106,9 @@ static int toggle_utf8(int fd, bool utf8) { r = tcsetattr(fd, TCSANOW, &tc); } if (r < 0) - return log_warning_errno(errno, "Failed to %s iutf8 flag: %m", utf8 ? "enable" : "disable"); + return log_warning_errno(errno, "Failed to %s iutf8 flag on %s: %m", enable_disable(utf8), name); + log_debug("UTF-8 kbdmode %sd on %s", enable_disable(utf8), name); return 0; } @@ -114,8 +117,10 @@ static int toggle_utf8_sysfs(bool utf8) { r = write_string_file("/sys/module/vt/parameters/default_utf8", one_zero(utf8), 0); if (r < 0) - log_warning_errno(r, "Failed to %s sysfs UTF-8 flag: %m", utf8 ? "enable" : "disable"); - return r; + return log_warning_errno(r, "Failed to %s sysfs UTF-8 flag: %m", enable_disable(utf8)); + + log_debug("Sysfs UTF-8 flag %sd", enable_disable(utf8)); + return 0; } static int keyboard_load_and_wait(const char *vc, const char *map, const char *map_toggle, bool utf8) { @@ -266,7 +271,7 @@ static void setup_remaining_vcs(int fd, bool utf8) { if (!is_settable(fd_d)) continue; - toggle_utf8(fd_d, utf8); + toggle_utf8(ttyname, fd_d, utf8); if (cfo.op != KD_FONT_OP_SET) continue; @@ -281,13 +286,18 @@ static void setup_remaining_vcs(int fd, bool utf8) { /* unimapd is a ushort count and a pointer to an array of struct unipair { ushort, ushort } */ r = ioctl(fd_d, PIO_UNIMAPCLR, &adv); - if (r < 0) + if (r < 0) { log_warning_errno(errno, "PIO_UNIMAPCLR failed, unimaps might be incorrect for tty%i: %m", i); - else { - r = ioctl(fd_d, PIO_UNIMAP, &unimapd); - if (r < 0) - log_warning_errno(errno, "PIO_UNIMAP failed, unimaps might be incorrect for tty%i: %m", i); + continue; } + + r = ioctl(fd_d, PIO_UNIMAP, &unimapd); + if (r < 0) { + log_warning_errno(errno, "PIO_UNIMAP failed, unimaps might be incorrect for tty%i: %m", i); + continue; + } + + log_debug("Font and unimap successfully copied to %s", ttyname); } } @@ -366,7 +376,7 @@ int main(int argc, char **argv) { } toggle_utf8_sysfs(utf8); - toggle_utf8(fd, utf8); + toggle_utf8(vc, fd, utf8); font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) == 0; keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) == 0; @@ -374,7 +384,7 @@ int main(int argc, char **argv) { if (font_ok) setup_remaining_vcs(fd, utf8); else - log_warning("Setting source virtual console failed, ignoring remaining ones."); + log_warning("Setting source virtual console failed, ignoring remaining ones"); } return font_ok && keyboard_ok ? EXIT_SUCCESS : EXIT_FAILURE; -- cgit v1.2.3-54-g00ecf From 72ccee50d0d08e2339ec283d669eb9ed282aac29 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 29 Jul 2016 01:01:04 -0400 Subject: man: move description of kernel vconsole.conf overrides to vconsole.conf(5) They were outdated, and this way it's less likely that they'll get out of sync again. Anyway, it's easier for the reader to have the kernel and config file options next to one another. --- man/kernel-command-line.xml | 11 +++++----- man/systemd-vconsole-setup.service.xml | 36 +------------------------------- man/vconsole.conf.xml | 38 +++++++++++++++++++++++++++------- 3 files changed, 36 insertions(+), 49 deletions(-) diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml index 3ecc969c10..1fa31a14b7 100644 --- a/man/kernel-command-line.xml +++ b/man/kernel-command-line.xml @@ -224,15 +224,14 @@ vconsole.keymap= - vconsole.keymap.toggle= + vconsole.keymap_toggle= vconsole.font= - vconsole.font.map= - vconsole.font.unimap= + vconsole.font_map= + vconsole.font_unimap= - Parameters understood by the virtual console setup - logic. For details, see - systemd-vconsole-setup.service8. + Parameters understood by the virtual console setup logic. For details, see + vconsole.conf5. diff --git a/man/systemd-vconsole-setup.service.xml b/man/systemd-vconsole-setup.service.xml index ff079761c1..e048258621 100644 --- a/man/systemd-vconsole-setup.service.xml +++ b/man/systemd-vconsole-setup.service.xml @@ -63,41 +63,7 @@ See vconsole.conf5 - for information about the configuration files understood by this - service. - - - - - - Kernel Command Line - - A few configuration parameters from - vconsole.conf may be overridden on the kernel - command line: - - - - vconsole.keymap= - vconsole.keymap.toggle= - - Overrides the key mapping table for the - keyboard and the second toggle keymap. - - - - vconsole.font= - vconsole.font.map= - vconsole.font.unimap= - - Configures the console font, the console map, - and the unicode font map. - - - - See - vconsole.conf5 - for information about these settings. + for information about the configuration files and kernel command line options understood by this program. diff --git a/man/vconsole.conf.xml b/man/vconsole.conf.xml index 7f6ae3452f..fa30ca6569 100644 --- a/man/vconsole.conf.xml +++ b/man/vconsole.conf.xml @@ -57,8 +57,6 @@ the virtual console, i.e. keyboard mapping and console font. It is applied at boot by udev using 90-vconsole.rules file. You can safely mask this file if you want to avoid this kind of initialization. - There is also systemd-vconsole-setup.service8 - provided that you can conveniently use at any time to [re]initialize consoles. The basic file format of the @@ -93,12 +91,10 @@ KEYMAP= KEYMAP_TOGGLE= - Configures the key mapping table for the - keyboard. KEYMAP= defaults to - us if not set. The - KEYMAP_TOGGLE= can be used to configure a - second toggle keymap and is by default - unset. + Configures the key mapping table for the keyboard. + KEYMAP= defaults to us if not set. The + KEYMAP_TOGGLE= can be used to configure a second toggle keymap and is by + default unset. @@ -113,6 +109,32 @@ + + Kernel Command Line + + A few configuration parameters from vconsole.conf may be overridden + on the kernel command line: + + + + vconsole.keymap= + vconsole.keymap_toggle= + + Overrides KEYMAP= and KEYMAP_TOGGLE=. + + + + + vconsole.font= + vconsole.font_map= + vconsole.font_unimap= + + Overrides FONT=, FONT_MAP=, and + FONT_UNIMAP=. + + + + Example -- cgit v1.2.3-54-g00ecf From 494294d6f88612c20339cc34e4ef893a14565a0f Mon Sep 17 00:00:00 2001 From: 0xAX <0xAX@users.noreply.github.com> Date: Mon, 1 Aug 2016 13:38:25 +0300 Subject: main: get rid of ACTION_DONE (#3849) the ACTION_DONE was introduced in the 4288f61921 (dbus: automatically generate and install introspection files ) commit and was used in systemd --introspect command. Later 'introspect' command was removed in the ca2871d9b (bus: remove static introspection file export) commit and have no users anymore. So we can remove it. --- src/core/main.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index f2adca7d2b..74b8ea139f 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -92,8 +92,7 @@ static enum { ACTION_HELP, ACTION_VERSION, ACTION_TEST, - ACTION_DUMP_CONFIGURATION_ITEMS, - ACTION_DONE + ACTION_DUMP_CONFIGURATION_ITEMS } arg_action = ACTION_RUN; static char *arg_default_unit = NULL; static bool arg_system = false; @@ -1618,9 +1617,6 @@ int main(int argc, char *argv[]) { unit_dump_config_items(stdout); retval = EXIT_SUCCESS; goto finish; - } else if (arg_action == ACTION_DONE) { - retval = EXIT_SUCCESS; - goto finish; } if (!arg_system && -- cgit v1.2.3-54-g00ecf From aa0c34279ee40bce2f9681b496922dedbadfca19 Mon Sep 17 00:00:00 2001 From: Leonardo Brondani Schenkel Date: Mon, 1 Aug 2016 15:04:49 +0200 Subject: virt: detect bhyve (FreeBSD hypervisor) (#3840) The CPUID and DMI vendor strings do not seem to be documented. Values were found experimentally and by inspecting the source code. --- man/systemd-detect-virt.xml | 7 ++++++- src/basic/virt.c | 5 +++++ src/basic/virt.h | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml index 2b7f4e69ab..61a5f8937f 100644 --- a/man/systemd-detect-virt.xml +++ b/man/systemd-detect-virt.xml @@ -88,7 +88,7 @@ - VM + VM qemu QEMU software virtualization @@ -138,6 +138,11 @@ Parallels Desktop, Parallels Server + + bhyve + bhyve, FreeBSD hypervisor + + Container openvz diff --git a/src/basic/virt.c b/src/basic/virt.c index dace1f4328..10a2043746 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -49,6 +49,8 @@ static int detect_vm_cpuid(void) { { "VMwareVMware", VIRTUALIZATION_VMWARE }, /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */ { "Microsoft Hv", VIRTUALIZATION_MICROSOFT }, + /* https://wiki.freebsd.org/bhyve */ + { "bhyve bhyve ", VIRTUALIZATION_BHYVE }, }; uint32_t eax, ecx; @@ -178,6 +180,8 @@ static int detect_vm_dmi(void) { { "Xen", VIRTUALIZATION_XEN }, { "Bochs", VIRTUALIZATION_BOCHS }, { "Parallels", VIRTUALIZATION_PARALLELS }, + /* https://wiki.freebsd.org/bhyve */ + { "BHYVE", VIRTUALIZATION_BHYVE }, }; unsigned i; int r; @@ -502,6 +506,7 @@ static const char *const virtualization_table[_VIRTUALIZATION_MAX] = { [VIRTUALIZATION_MICROSOFT] = "microsoft", [VIRTUALIZATION_ZVM] = "zvm", [VIRTUALIZATION_PARALLELS] = "parallels", + [VIRTUALIZATION_BHYVE] = "bhyve", [VIRTUALIZATION_VM_OTHER] = "vm-other", [VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn", diff --git a/src/basic/virt.h b/src/basic/virt.h index a538f07f6b..bc5b3ae94d 100644 --- a/src/basic/virt.h +++ b/src/basic/virt.h @@ -37,6 +37,7 @@ enum { VIRTUALIZATION_MICROSOFT, VIRTUALIZATION_ZVM, VIRTUALIZATION_PARALLELS, + VIRTUALIZATION_BHYVE, VIRTUALIZATION_VM_OTHER, VIRTUALIZATION_VM_LAST = VIRTUALIZATION_VM_OTHER, -- cgit v1.2.3-54-g00ecf From a912ab0474e2fcdc346d0315a8493f0f3ac867aa Mon Sep 17 00:00:00 2001 From: 0xAX <0xAX@users.noreply.github.com> Date: Mon, 1 Aug 2016 18:39:27 +0300 Subject: machinectl: hide legend in a case when no data (#3839) For this moment machinectl prints legend and count of machines/images/etc. But in a case when we have no images,machines,etc., there is no sense to show legend: ~$ machinectl MACHINE CLASS SERVICE 0 machines listed. Let's print only 'No machines', 'No images', 'No transfers' in this case. --- src/machine/machinectl.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index ddec6cb4d6..c78ca7ad76 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -185,7 +185,7 @@ static int list_machines(int argc, char *argv[], void *userdata) { qsort_safe(machines, n_machines, sizeof(MachineInfo), compare_machine_info); - if (arg_legend) + if (arg_legend && n_machines > 0) printf("%-*s %-*s %-*s\n", (int) max_name, "MACHINE", (int) max_class, "CLASS", @@ -197,8 +197,10 @@ static int list_machines(int argc, char *argv[], void *userdata) { (int) max_class, machines[j].class, (int) max_service, machines[j].service); - if (arg_legend) + if (arg_legend && n_machines > 0) printf("\n%zu machines listed.\n", n_machines); + else + printf("No machines.\n"); return 0; } @@ -305,7 +307,7 @@ static int list_images(int argc, char *argv[], void *userdata) { qsort_safe(images, n_images, sizeof(ImageInfo), compare_image_info); - if (arg_legend) + if (arg_legend && n_images > 0) printf("%-*s %-*s %-3s %-*s %-*s %-*s\n", (int) max_name, "NAME", (int) max_type, "TYPE", @@ -326,8 +328,10 @@ static int list_images(int argc, char *argv[], void *userdata) { (int) max_mtime, strna(format_timestamp(mtime_buf, sizeof(mtime_buf), images[j].mtime))); } - if (arg_legend) + if (arg_legend && n_images > 0) printf("\n%zu images listed.\n", n_images); + else + printf("No images.\n"); return 0; } @@ -2314,7 +2318,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) { qsort_safe(transfers, n_transfers, sizeof(TransferInfo), compare_transfer_info); - if (arg_legend) + if (arg_legend && n_transfers > 0) printf("%-*s %-*s %-*s %-*s %-*s\n", (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), "ID", (int) 7, "PERCENT", @@ -2330,8 +2334,10 @@ static int list_transfers(int argc, char *argv[], void *userdata) { (int) max_local, transfers[j].local, (int) max_remote, transfers[j].remote); - if (arg_legend) + if (arg_legend && n_transfers > 0) printf("\n%zu transfers listed.\n", n_transfers); + else + printf("No transfers.\n"); return 0; } -- cgit v1.2.3-54-g00ecf From d7032b1fcd6e51b736698a8b264273c625084643 Mon Sep 17 00:00:00 2001 From: Jakub Filak Date: Tue, 26 Apr 2016 09:54:39 +0200 Subject: coredump: save /proc/[pid]/mountinfo The file contains information one can use to debug processes running within a container. --- src/coredump/coredump.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index dcc09fcc6d..953f04e205 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -933,11 +933,12 @@ static int process_kernel(int argc, char* argv[]) { /* The larger ones we allocate on the heap */ _cleanup_free_ char *core_owner_uid = NULL, *core_open_fds = NULL, *core_proc_status = NULL, - *core_proc_maps = NULL, *core_proc_limits = NULL, *core_proc_cgroup = NULL, *core_environ = NULL; + *core_proc_maps = NULL, *core_proc_limits = NULL, *core_proc_cgroup = NULL, *core_environ = NULL, + *core_proc_mountinfo = NULL; _cleanup_free_ char *exe = NULL, *comm = NULL; const char *context[_CONTEXT_MAX]; - struct iovec iovec[25]; + struct iovec iovec[26]; size_t n_iovec = 0; uid_t owner_uid; const char *p; @@ -1110,6 +1111,15 @@ static int process_kernel(int argc, char* argv[]) { IOVEC_SET_STRING(iovec[n_iovec++], core_proc_cgroup); } + p = procfs_file_alloca(pid, "mountinfo"); + if (read_full_file(p, &t, NULL) >=0) { + core_proc_mountinfo = strappend("COREDUMP_PROC_MOUNTINFO=", t); + free(t); + + if (core_proc_mountinfo) + IOVEC_SET_STRING(iovec[n_iovec++], core_proc_mountinfo); + } + if (get_process_cwd(pid, &t) >= 0) { core_cwd = strjoina("COREDUMP_CWD=", t); free(t); -- cgit v1.2.3-54-g00ecf From 7633f8ef371a0992374956437fb7bb8189156b10 Mon Sep 17 00:00:00 2001 From: tblume Date: Tue, 2 Aug 2016 14:55:25 +0200 Subject: systemd-ask-password: make sure directory watch is started before cryptsetup (#3850) The password directory watch should get ordered before cryptsetup to make sure that the password for unlocking the crypt device gets prompted. --- units/systemd-ask-password-console.path | 2 +- units/systemd-ask-password-wall.path | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/units/systemd-ask-password-console.path b/units/systemd-ask-password-console.path index 2949635fea..7899ae788f 100644 --- a/units/systemd-ask-password-console.path +++ b/units/systemd-ask-password-console.path @@ -11,7 +11,7 @@ Documentation=man:systemd-ask-password-console.service(8) DefaultDependencies=no Conflicts=shutdown.target After=plymouth-start.service -Before=paths.target shutdown.target +Before=paths.target shutdown.target cryptsetup.target ConditionPathExists=!/run/plymouth/pid [Path] diff --git a/units/systemd-ask-password-wall.path b/units/systemd-ask-password-wall.path index 95ec9bc8a0..a3ca617256 100644 --- a/units/systemd-ask-password-wall.path +++ b/units/systemd-ask-password-wall.path @@ -10,7 +10,7 @@ Description=Forward Password Requests to Wall Directory Watch Documentation=man:systemd-ask-password-console.service(8) DefaultDependencies=no Conflicts=shutdown.target -Before=paths.target shutdown.target +Before=paths.target shutdown.target cryptsetup.target [Path] DirectoryNotEmpty=/run/systemd/ask-password -- cgit v1.2.3-54-g00ecf From 98d2d46876c08d6f2ae63284ec5a28f90cbbb8ac Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Tue, 2 Aug 2016 14:56:45 +0200 Subject: units: add graphical-session-pre.target user unit (#3848) This complements graphical-session.target for services which set up the environment (e. g. dbus-update-activation-environment) and need to run before the actual graphical session. --- Makefile.am | 3 ++- man/systemd.special.xml | 13 +++++++++++++ units/user/graphical-session-pre.target | 14 ++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 units/user/graphical-session-pre.target diff --git a/Makefile.am b/Makefile.am index 7dd021b56a..763b16289d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -574,7 +574,8 @@ dist_userunit_DATA = \ units/user/basic.target \ units/user/default.target \ units/user/exit.target \ - units/user/graphical-session.target + units/user/graphical-session.target \ + units/user/graphical-session-pre.target nodist_userunit_DATA = \ units/user/systemd-exit.service diff --git a/man/systemd.special.xml b/man/systemd.special.xml index 18142598cb..d977298cd8 100644 --- a/man/systemd.special.xml +++ b/man/systemd.special.xml @@ -927,6 +927,19 @@ PartOf=graphical-session.target + + + graphical-session-pre.target + + This target contains services which set up the environment or + global configuration of a graphical session, such as SSH/GPG agents + (which need to export an environment variable into all desktop processes) + or migration of obsolete d-conf keys after an OS upgrade (which needs to + happen before starting any process that might use them). This target must + be started before starting a graphical session + like gnome-session.target. + + diff --git a/units/user/graphical-session-pre.target b/units/user/graphical-session-pre.target new file mode 100644 index 0000000000..86d15aff33 --- /dev/null +++ b/units/user/graphical-session-pre.target @@ -0,0 +1,14 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Session services which should run early before the graphical session is brought up +Documentation=man:systemd.special(7) +Requires=basic.target +Before=graphical-session.target +RefuseManualStart=yes +StopWhenUnneeded=yes -- cgit v1.2.3-54-g00ecf From 96694e998be1f631861c8c72de67c581a5306afa Mon Sep 17 00:00:00 2001 From: Ismo Puustinen Date: Tue, 2 Aug 2016 15:58:30 +0300 Subject: main: load Smack policy before IMA policy (#3859) IMA wiki says: "If the IMA policy contains LSM labels, then the LSM policy must be loaded prior to the IMA policy." Right now, in case of Smack, the IMA policy is loaded before the Smack policy. Move the order around to allow Smack labels to be used in IMA policy. --- src/core/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 74b8ea139f..c46d886653 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1414,12 +1414,12 @@ int main(int argc, char *argv[]) { if (mac_selinux_setup(&loaded_policy) < 0) { error_message = "Failed to load SELinux policy"; goto finish; - } else if (ima_setup() < 0) { - error_message = "Failed to load IMA policy"; - goto finish; } else if (mac_smack_setup(&loaded_policy) < 0) { error_message = "Failed to load SMACK policy"; goto finish; + } else if (ima_setup() < 0) { + error_message = "Failed to load IMA policy"; + goto finish; } dual_timestamp_get(&security_finish_timestamp); } -- cgit v1.2.3-54-g00ecf From 7ed03ce69ede34b03107702efd6efb100e9a23bc Mon Sep 17 00:00:00 2001 From: Jakub Filak Date: Wed, 27 Apr 2016 15:23:49 +0200 Subject: coredump: save process container parent cmdline Process container parent is the process used to start processes with a new user namespace - e.g systemd-nspawn, runc, lxc, etc. There is not standard way how to find such a process - or I do not know about it - hence I have decided to find the first process in the parent process hierarchy with a different mount namespace and different /proc/self/root's inode. I have decided for this criteria because in ABRT we take special care only if the crashed process runs different code than installed on the host. Other processes with namespaces different than PID 1's namespaces are just processes running code shipped by the OS vendor and bug reporting tools can get information about the provider of the code without the need to deal with changed root and so on. --- src/coredump/coredump.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 953f04e205..e3d17c864d 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -558,6 +558,89 @@ static int compose_open_fds(pid_t pid, char **open_fds) { return 0; } +static int get_process_ns(pid_t pid, const char *namespace, ino_t *ns) { + const char *p; + struct stat stbuf; + _cleanup_close_ int proc_ns_dir_fd; + + p = procfs_file_alloca(pid, "ns"); + + proc_ns_dir_fd = open(p, O_DIRECTORY | O_CLOEXEC | O_RDONLY); + if (proc_ns_dir_fd < 0) + return -errno; + + if (fstatat(proc_ns_dir_fd, namespace, &stbuf, /* flags */0) < 0) + return -errno; + + *ns = stbuf.st_ino; + return 0; +} + +static int get_mount_namespace_leader(pid_t pid, pid_t *container_pid) { + pid_t cpid = pid, ppid = 0; + ino_t proc_mntns; + int r = 0; + + r = get_process_ns(pid, "mnt", &proc_mntns); + if (r < 0) + return r; + + while (1) { + ino_t parent_mntns; + + r = get_process_ppid(cpid, &ppid); + if (r < 0) + return r; + + r = get_process_ns(ppid, "mnt", &parent_mntns); + if (r < 0) + return r; + + if (proc_mntns != parent_mntns) + break; + + if (ppid == 1) + return -ENOENT; + + cpid = ppid; + } + + *container_pid = ppid; + return 0; +} + +/* Returns 1 if the parent was found. + * Returns 0 if there is not a process we can call the pid's + * container parent (the pid's process isn't 'containerized'). + * Returns a negative number on errors. + */ +static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) { + int r = 0; + pid_t container_pid; + const char *proc_root_path; + struct stat root_stat, proc_root_stat; + + /* To compare inodes of / and /proc/[pid]/root */ + if (stat("/", &root_stat) < 0) + return -errno; + + proc_root_path = procfs_file_alloca(pid, "root"); + if (stat(proc_root_path, &proc_root_stat) < 0) + return -errno; + + /* The process uses system root. */ + if (proc_root_stat.st_ino == root_stat.st_ino) { + *cmdline = NULL; + return 0; + } + + r = get_mount_namespace_leader(pid, &container_pid); + if (r < 0) + return r; + + return get_process_cmdline(container_pid, 0, false, cmdline); +} + static int change_uid_gid(const char *context[]) { uid_t uid; gid_t gid; @@ -934,11 +1017,12 @@ static int process_kernel(int argc, char* argv[]) { _cleanup_free_ char *core_owner_uid = NULL, *core_open_fds = NULL, *core_proc_status = NULL, *core_proc_maps = NULL, *core_proc_limits = NULL, *core_proc_cgroup = NULL, *core_environ = NULL, - *core_proc_mountinfo = NULL; + *core_proc_mountinfo = NULL, *core_container_cmdline = NULL; _cleanup_free_ char *exe = NULL, *comm = NULL; const char *context[_CONTEXT_MAX]; - struct iovec iovec[26]; + bool proc_self_root_is_slash; + struct iovec iovec[27]; size_t n_iovec = 0; uid_t owner_uid; const char *p; @@ -1129,9 +1213,20 @@ static int process_kernel(int argc, char* argv[]) { if (get_process_root(pid, &t) >= 0) { core_root = strjoina("COREDUMP_ROOT=", t); - free(t); IOVEC_SET_STRING(iovec[n_iovec++], core_root); + + /* If the process' root is "/", then there is a chance it has + * mounted own root and hence being containerized. */ + proc_self_root_is_slash = strcmp(t, "/") == 0; + free(t); + if (proc_self_root_is_slash && get_process_container_parent_cmdline(pid, &t) > 0) { + core_container_cmdline = strappend("COREDUMP_CONTAINER_CMDLINE=", t); + free(t); + + if (core_container_cmdline) + IOVEC_SET_STRING(iovec[n_iovec++], core_container_cmdline); + } } if (get_process_environ(pid, &t) >= 0) { -- cgit v1.2.3-54-g00ecf From cce9c80af32ac7f84607123c81da8c2ee028e55e Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 2 Aug 2016 10:04:39 -0400 Subject: gitignore: libsystemd-journal.pc is no more (#3863) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …since 4de282cf9324ab. --- src/journal/.gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/src/journal/.gitignore b/src/journal/.gitignore index 04d5852547..b93a9462fa 100644 --- a/src/journal/.gitignore +++ b/src/journal/.gitignore @@ -1,4 +1,3 @@ /journald-gperf.c -/libsystemd-journal.pc /audit_type-list.txt /audit_type-*-name.* -- cgit v1.2.3-54-g00ecf From 125918635516491dc8ec1d803c38b9225b3599b9 Mon Sep 17 00:00:00 2001 From: Jan Synacek Date: Tue, 2 Aug 2016 16:22:56 +0200 Subject: test: fix test-execute personality tests on ppc64 and aarch64 (#3825) --- Makefile.am | 3 +++ src/test/test-execute.c | 10 ++++++++++ test/test-execute/exec-personality-aarch64.service | 7 +++++++ test/test-execute/exec-personality-ppc64.service | 7 +++++++ test/test-execute/exec-personality-ppc64le.service | 7 +++++++ 5 files changed, 34 insertions(+) create mode 100644 test/test-execute/exec-personality-aarch64.service create mode 100644 test/test-execute/exec-personality-ppc64.service create mode 100644 test/test-execute/exec-personality-ppc64le.service diff --git a/Makefile.am b/Makefile.am index 763b16289d..bf853c8f90 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1629,6 +1629,9 @@ EXTRA_DIST += \ test/test-execute/exec-personality-x86-64.service \ test/test-execute/exec-personality-x86.service \ test/test-execute/exec-personality-s390.service \ + test/test-execute/exec-personality-ppc64.service \ + test/test-execute/exec-personality-ppc64le.service \ + test/test-execute/exec-personality-aarch64.service \ test/test-execute/exec-privatedevices-no.service \ test/test-execute/exec-privatedevices-yes.service \ test/test-execute/exec-privatetmp-no.service \ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index baf5b96487..1d24115b5c 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -92,6 +92,16 @@ static void test_exec_personality(Manager *m) { #elif defined(__s390__) test(m, "exec-personality-s390.service", 0, CLD_EXITED); +#elif defined(__powerpc64__) +# if __BYTE_ORDER == __BIG_ENDIAN + test(m, "exec-personality-ppc64.service", 0, CLD_EXITED); +# else + test(m, "exec-personality-ppc64le.service", 0, CLD_EXITED); +# endif + +#elif defined(__aarch64__) + test(m, "exec-personality-aarch64.service", 0, CLD_EXITED); + #elif defined(__i386__) test(m, "exec-personality-x86.service", 0, CLD_EXITED); #endif diff --git a/test/test-execute/exec-personality-aarch64.service b/test/test-execute/exec-personality-aarch64.service new file mode 100644 index 0000000000..40b6d95e3a --- /dev/null +++ b/test/test-execute/exec-personality-aarch64.service @@ -0,0 +1,7 @@ +Unit] +Description=Test for Personality=aarch64 + +[Service] +ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "aarch64")' +Type=oneshot +Personality=aarch64 diff --git a/test/test-execute/exec-personality-ppc64.service b/test/test-execute/exec-personality-ppc64.service new file mode 100644 index 0000000000..ccc2c8d83d --- /dev/null +++ b/test/test-execute/exec-personality-ppc64.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Personality=ppc64 + +[Service] +ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "ppc64")' +Type=oneshot +Personality=ppc64 diff --git a/test/test-execute/exec-personality-ppc64le.service b/test/test-execute/exec-personality-ppc64le.service new file mode 100644 index 0000000000..2a7625087d --- /dev/null +++ b/test/test-execute/exec-personality-ppc64le.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Personality=ppc64le + +[Service] +ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "ppc64le")' +Type=oneshot +Personality=ppc64le -- cgit v1.2.3-54-g00ecf From 9d565427647a874b7eda64ef0cb41ea74a96659b Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Tue, 2 Aug 2016 23:18:23 +0530 Subject: socket: add support to control no. of connections from one source (#3607) Introduce MaxConnectionsPerSource= that is number of concurrent connections allowed per IP. RFE: 1939 --- man/systemd.socket.xml | 8 ++ src/core/dbus-socket.c | 1 + src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/service.c | 1 + src/core/service.h | 1 + src/core/socket.c | 185 ++++++++++++++++++++++++++++++++++ src/core/socket.h | 16 +++ 7 files changed, 213 insertions(+) diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 5bf54d8ef3..26e5d3ce7b 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -443,6 +443,14 @@ + MaxConnectionsPerSource= + The maximum number of connections for a service per source IP address. + This is is very similar to the MaxConnections= directive + above. Disabled by default. + + + + KeepAlive= Takes a boolean argument. If true, the TCP/IP stack will send a keep alive message after 2h (depending on diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 961340608d..9a071a1355 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -137,6 +137,7 @@ const sd_bus_vtable bus_socket_vtable[] = { SD_BUS_PROPERTY("Symlinks", "as", NULL, offsetof(Socket, symlinks), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Mark", "i", bus_property_get_int, offsetof(Socket, mark), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MaxConnections", "u", bus_property_get_unsigned, offsetof(Socket, max_connections), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MaxConnectionsPerSource", "u", bus_property_get_unsigned, offsetof(Socket, max_connections_per_source), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MessageQueueMaxMessages", "x", bus_property_get_long, offsetof(Socket, mq_maxmsg), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MessageQueueMessageSize", "x", bus_property_get_long, offsetof(Socket, mq_msgsize), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ReusePort", "b", bus_property_get_bool, offsetof(Socket, reuse_port), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index c9cdbe8ba7..396f847213 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -293,6 +293,7 @@ Socket.DirectoryMode, config_parse_mode, 0, Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept) Socket.Writable, config_parse_bool, 0, offsetof(Socket, writable) Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections) +Socket.MaxConnectionsPerSource, config_parse_unsigned, 0, offsetof(Socket, max_connections_per_source) Socket.KeepAlive, config_parse_bool, 0, offsetof(Socket, keep_alive) Socket.KeepAliveTimeSec, config_parse_sec, 0, offsetof(Socket, keep_alive_time) Socket.KeepAliveIntervalSec, config_parse_sec, 0, offsetof(Socket, keep_alive_interval) diff --git a/src/core/service.c b/src/core/service.c index 4d59d78ecb..eb125cb999 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -342,6 +342,7 @@ static void service_done(Unit *u) { s->bus_name_owner = mfree(s->bus_name_owner); service_close_socket_fd(s); + s->peer = socket_peer_unref(s->peer); unit_ref_unset(&s->accept_socket); diff --git a/src/core/service.h b/src/core/service.h index 8e56e1acb9..888007cc0b 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -152,6 +152,7 @@ struct Service { pid_t main_pid, control_pid; int socket_fd; + SocketPeer *peer; bool socket_fd_selinux_context_net; bool permissions_start_only; diff --git a/src/core/socket.c b/src/core/socket.c index 1ce41a1f07..ff55885fb3 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -57,6 +57,7 @@ #include "unit-printf.h" #include "unit.h" #include "user-util.h" +#include "in-addr-util.h" static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { [SOCKET_DEAD] = UNIT_INACTIVE, @@ -77,6 +78,9 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); +SocketPeer *socket_peer_new(void); +int socket_find_peer(Socket *s, int fd, SocketPeer **p); + static void socket_init(Unit *u) { Socket *s = SOCKET(u); @@ -141,11 +145,17 @@ void socket_free_ports(Socket *s) { static void socket_done(Unit *u) { Socket *s = SOCKET(u); + SocketPeer *p; assert(s); socket_free_ports(s); + while ((p = hashmap_steal_first(s->peers_by_address))) + p->socket = NULL; + + s->peers_by_address = hashmap_free(s->peers_by_address); + s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); s->control_command = NULL; @@ -468,6 +478,40 @@ static int socket_verify(Socket *s) { return 0; } +static void peer_address_hash_func(const void *p, struct siphash *state) { + const SocketPeer *s = p; + + assert(s); + + if (s->peer.sa.sa_family == AF_INET) + siphash24_compress(&s->peer.in.sin_addr, sizeof(s->peer.in.sin_addr), state); + else if (s->peer.sa.sa_family == AF_INET6) + siphash24_compress(&s->peer.in6.sin6_addr, sizeof(s->peer.in6.sin6_addr), state); +} + +static int peer_address_compare_func(const void *a, const void *b) { + const SocketPeer *x = a, *y = b; + + if (x->peer.sa.sa_family < y->peer.sa.sa_family) + return -1; + if (x->peer.sa.sa_family > y->peer.sa.sa_family) + return 1; + + switch(x->peer.sa.sa_family) { + case AF_INET: + return memcmp(&x->peer.in.sin_addr, &y->peer.in.sin_addr, sizeof(x->peer.in.sin_addr)); + case AF_INET6: + return memcmp(&x->peer.in6.sin6_addr, &y->peer.in6.sin6_addr, sizeof(x->peer.in6.sin6_addr)); + } + + return -1; +} + +const struct hash_ops peer_address_hash_ops = { + .hash = peer_address_hash_func, + .compare = peer_address_compare_func +}; + static int socket_load(Unit *u) { Socket *s = SOCKET(u); int r; @@ -475,6 +519,10 @@ static int socket_load(Unit *u) { assert(u); assert(u->load_state == UNIT_STUB); + r = hashmap_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops); + if (r < 0) + return r; + r = unit_load_fragment_and_dropin(u); if (r < 0) return r; @@ -2050,6 +2098,7 @@ static void socket_enter_running(Socket *s, int cfd) { socket_set_state(s, SOCKET_RUNNING); } else { _cleanup_free_ char *prefix = NULL, *instance = NULL, *name = NULL; + _cleanup_(socket_peer_unrefp) SocketPeer *p = NULL; Service *service; if (s->n_connections >= s->max_connections) { @@ -2058,6 +2107,21 @@ static void socket_enter_running(Socket *s, int cfd) { return; } + if (s->max_connections_per_source > 0) { + r = socket_find_peer(s, cfd, &p); + if (r < 0) { + safe_close(cfd); + return; + } + + if (p->n_ref > s->max_connections_per_source) { + log_unit_warning(UNIT(s), "Too many incoming connections (%u) from source, refusing connection attempt.", p->n_ref); + safe_close(cfd); + p = NULL; + return; + } + } + r = socket_instantiate_service(s); if (r < 0) goto fail; @@ -2099,6 +2163,11 @@ static void socket_enter_running(Socket *s, int cfd) { cfd = -1; /* We passed ownership of the fd to the service now. Forget it here. */ s->n_connections++; + if (s->max_connections_per_source > 0) { + service->peer = socket_peer_ref(p); + p = NULL; + } + r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, &error, NULL); if (r < 0) { /* We failed to activate the new service, but it still exists. Let's make sure the service @@ -2244,7 +2313,9 @@ static int socket_stop(Unit *u) { static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { Socket *s = SOCKET(u); + SocketPeer *k; SocketPort *p; + Iterator i; int r; assert(u); @@ -2295,6 +2366,16 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { } } + HASHMAP_FOREACH(k, s->peers_by_address, i) { + _cleanup_free_ char *t = NULL; + + r = sockaddr_pretty(&k->peer.sa, FAMILY_ADDRESS_SIZE(k->peer.sa.sa_family), true, true, &t); + if (r < 0) + return r; + + unit_serialize_item_format(u, f, "peer", "%u %s", k->n_ref, t); + } + return 0; } @@ -2458,6 +2539,33 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, } } + } else if (streq(key, "peer")) { + _cleanup_(socket_peer_unrefp) SocketPeer *p; + int n_ref, skip = 0; + SocketAddress a; + int r; + + if (sscanf(value, "%u %n", &n_ref, &skip) < 1 || n_ref < 1) + log_unit_debug(u, "Failed to parse socket peer value: %s", value); + else { + r = socket_address_parse(&a, value+skip); + if (r < 0) + return r; + + p = socket_peer_new(); + if (!p) + return log_oom(); + + p->n_ref = n_ref; + memcpy(&p->peer, &a.sockaddr, sizeof(a.sockaddr)); + p->socket = s; + + r = hashmap_put(s->peers_by_address, p, p); + if (r < 0) + return r; + + p = NULL; + } } else log_unit_debug(UNIT(s), "Unknown serialization key: %s", key); @@ -2554,6 +2662,83 @@ _pure_ static bool socket_check_gc(Unit *u) { return s->n_connections > 0; } +SocketPeer *socket_peer_new(void) { + SocketPeer *p; + + p = new0(SocketPeer, 1); + if (!p) + return NULL; + + p->n_ref = 1; + + return p; +} + +SocketPeer *socket_peer_ref(SocketPeer *p) { + if (!p) + return NULL; + + assert(p->n_ref > 0); + p->n_ref++; + + return p; +} + +SocketPeer *socket_peer_unref(SocketPeer *p) { + if (!p) + return NULL; + + assert(p->n_ref > 0); + + p->n_ref--; + + if (p->n_ref > 0) + return NULL; + + if (p->socket) + (void) hashmap_remove(p->socket->peers_by_address, p); + + free(p); + + return NULL; +} + +int socket_find_peer(Socket *s, int fd, SocketPeer **p) { + _cleanup_free_ SocketPeer *remote = NULL; + SocketPeer sa, *i; + socklen_t salen = sizeof(sa.peer); + int r; + + assert(fd >= 0); + assert(s); + + r = getpeername(fd, &sa.peer.sa, &salen); + if (r < 0) + return log_error_errno(errno, "getpeername failed: %m"); + + i = hashmap_get(s->peers_by_address, &sa); + if (i) { + *p = i; + return 1; + } + + remote = socket_peer_new(); + if (!remote) + return log_oom(); + + memcpy(&remote->peer, &sa.peer, sizeof(union sockaddr_union)); + remote->socket = s; + + r = hashmap_put(s->peers_by_address, remote, remote); + if (r < 0) + return r; + + *p = remote; + remote = NULL; + + return 0; +} + static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { SocketPort *p = userdata; int cfd = -1; diff --git a/src/core/socket.h b/src/core/socket.h index 6c32d67bef..2fe38ef2aa 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -20,6 +20,7 @@ ***/ typedef struct Socket Socket; +typedef struct SocketPeer SocketPeer; #include "mount.h" #include "service.h" @@ -79,9 +80,12 @@ struct Socket { LIST_HEAD(SocketPort, ports); + Hashmap *peers_by_address; + unsigned n_accepted; unsigned n_connections; unsigned max_connections; + unsigned max_connections_per_source; unsigned backlog; unsigned keep_alive_cnt; @@ -164,6 +168,18 @@ struct Socket { RateLimit trigger_limit; }; +struct SocketPeer { + unsigned n_ref; + + Socket *socket; + union sockaddr_union peer; +}; + +SocketPeer *socket_peer_ref(SocketPeer *p); +SocketPeer *socket_peer_unref(SocketPeer *p); + +DEFINE_TRIVIAL_CLEANUP_FUNC(SocketPeer*, socket_peer_unref); + /* Called from the service code when collecting fds */ int socket_collect_fds(Socket *s, int **fds); -- cgit v1.2.3-54-g00ecf From d5c3b228f007b3fbda00a8352ce9e90df8950910 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 3 Aug 2016 20:34:56 +1000 Subject: hwdb: add ID_INPUT_TRACKBALL as additional identifier (#3872) Whether a device is a trackball or not is a physical property so we should store this globally, in one place. The new property must be set in addition to ID_INPUT_MOUSE, otherwise existing clients won't detect the device. No actual code changes required, the default match rule is simply checking for "Trackball" in the name (in a few versions), other entries need to be added manually. --- hwdb/70-mouse.hwdb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb index a5b39dc41e..b68c01066e 100644 --- a/hwdb/70-mouse.hwdb +++ b/hwdb/70-mouse.hwdb @@ -44,10 +44,18 @@ # udevadm info /dev/input/eventXX. # # Allowed properties are: +# ID_INPUT_TRACKBALL # MOUSE_DPI # MOUSE_WHEEL_CLICK_ANGLE # ######################################### +# ID_INPUT_TRACKBALL # +######################################### +# +# Specified *in additition* to ID_INPUT_MOUSE if the device is a trackball. +# Removing ID_INPUT_MOUSE will break backwards compatibility. +# +######################################### # MOUSE_DPI # ######################################### # @@ -101,6 +109,14 @@ # Sort by brand, type (usb, bluetooth), DPI, frequency. # For mice with switchable resolution, sort by the starred entry. +########################################## +# Generic +########################################## +mouse:*:name:*Trackball*: +mouse:*:name:*trackball*: +mouse:*:name:*TrackBall*: + ID_INPUT_TRACKBALL=1 + ########################################## # Apple ########################################## @@ -231,6 +247,7 @@ mouse:usb:v04b3p310c:name:USB Optical Mouse: # Logitech M570 trackball mouse:usb:v046dp1028:name:Logitech M570: MOUSE_DPI=540@167 + ID_INPUT_TRACKBALL=1 # Logitech USB-PS/2 M-BZ96C mouse:usb:v046dpc045:name:Logitech USB-PS/2 Optical Mouse: -- cgit v1.2.3-54-g00ecf From e5bc3f4fdc2ac2f68b781adc958e9570e577538b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 3 Aug 2016 21:12:37 +1000 Subject: hwdb: compress the various Lenovo *40, *50 and *60 series (#3877) Each series has identical hardware, let's use a glob instead of listing them one by one. --- hwdb/70-pointingstick.hwdb | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index 8a74573904..ff52f11e45 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -95,30 +95,12 @@ evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6400*:pvr* evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX230:* # Lenovo Thinkpad X230 tablet evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX230Tablet:* -# Lenovo Thinkpad X240 -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX240:* -# Lenovo Thinkpad T440p -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT440p:* -# Lenovo Thinkpad T440s -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT440s:* -# Lenovo Thinkpad T540p -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT540p:* -# Lenovo Thinkpad L450 -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadL450:* -# Lenovo Thinkpad T450s -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT450s:* -# Lenovo Thinkpad T550 / W550s -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT550:* -# Lenovo Thinkpad X250 -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX250:* -# Lenovo Thinkpad L460 -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadL460:* -# Lenovo Thinkpad T460s -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT460s:* -# Lenovo Thinkpad T560 -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT560:* -# Lenovo Thinkpad X260 -evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX260:* +# Lenovo Thinkpad *40 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??40?:* +# Lenovo Thinkpad *50 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??50?:* +# Lenovo Thinkpad *60 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??60?:* # Lenovo Thinkpad X1 Carbon 3rd gen evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:* # Lenovo Thinkpad X1 Carbon 4th gen -- cgit v1.2.3-54-g00ecf From 3539724c26a1b2b00c4eb3c004b635a4b8647de6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2016 14:50:45 +0200 Subject: nspawn: try to bind mount resolved's resolv.conf snippet into the container This has the benefit that the container can follow the host's DNS server changes without us having to constantly update the container's resolv.conf settings. --- src/nspawn/nspawn.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 6cc1b9177d..05e1fc1ab7 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1254,24 +1254,39 @@ static int setup_resolv_conf(const char *dest) { /* Fix resolv.conf, if possible */ where = prefix_roota(dest, "/etc/resolv.conf"); + if (access("/usr/lib/systemd/resolv.conf", F_OK) >= 0) { + /* resolved is enabled on the host. In this, case bind mount its static resolv.conf file into the + * container, so that the container can use the host's resolver. Given that network namespacing is + * disabled it's only natural of the container also uses the host's resolver. It also has the big + * advantage that the container will be able to follow the host's DNS server configuration changes + * transparently. */ + + if (mount("/usr/lib/systemd/resolv.conf", where, NULL, MS_BIND, NULL) < 0) + log_warning_errno(errno, "Failed to mount /etc/resolv.conf in the container, ignoring: %m"); + else { + if (mount(NULL, where, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL) < 0) + return log_error_errno(errno, "Failed to remount /etc/resolv.conf read-only: %m"); + + return 0; + } + } + + /* If that didn't work, let's copy the file */ r = copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW, 0644, 0); if (r < 0) { - /* If the file already exists as symlink, let's - * suppress the warning, under the assumption that - * resolved or something similar runs inside and the - * symlink points there. + /* If the file already exists as symlink, let's suppress the warning, under the assumption that + * resolved or something similar runs inside and the symlink points there. * - * If the disk image is read-only, there's also no - * point in complaining. + * If the disk image is read-only, there's also no point in complaining. */ log_full_errno(IN_SET(r, -ELOOP, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, - "Failed to copy /etc/resolv.conf to %s: %m", where); + "Failed to copy /etc/resolv.conf to %s, ignoring: %m", where); return 0; } r = userns_lchown(where, 0, 0); if (r < 0) - log_warning_errno(r, "Failed to chown /etc/resolv.conf: %m"); + log_warning_errno(r, "Failed to chown /etc/resolv.conf, ignoring: %m"); return 0; } -- cgit v1.2.3-54-g00ecf From a6b5216c7cb3055cd234bacac3f785f86dbaf873 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2016 14:56:17 +0200 Subject: nspawn: deprecate --share-system support This removes the --share-system switch: from the documentation, the --help text as well as the command line parsing. It's an ugly option, given that it kinda contradicts the whole concept of PID namespaces that nspawn implements. Since it's barely ever used, let's just deprecate it and remove it from the options. It might be useful as a debugging option, hence the functionality is kept around for now, exposed via an undocumented $SYSTEMD_NSPAWN_SHARE_SYSTEM environment variable. --- man/systemd-nspawn.xml | 27 +++------------------------ src/nspawn/nspawn.c | 10 +++++++--- 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index 9b623c8353..97b348b565 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -274,8 +274,7 @@ signals. It is recommended to use this mode to invoke arbitrary commands in containers, unless they have been modified to run correctly as PID 1. Or in other words: this switch should be used for pretty much all commands, except when the command refers to an init or shell implementation, as these are generally capable of running - correctly as PID 1. This option may not be combined with or - . + correctly as PID 1. This option may not be combined with . @@ -285,8 +284,7 @@ Automatically search for an init binary and invoke it as PID 1, instead of a shell or a user supplied program. If this option is used, arguments specified on the command line are used as arguments for the - init binary. This option may not be combined with or - . + init binary. This option may not be combined with . The following table explains the different modes of invocation and relationship to (see above): @@ -846,23 +844,6 @@ parameter may be used more than once. - - - - Allows the container to share certain system - facilities with the host. More specifically, this turns off - PID namespacing, UTS namespacing and IPC namespacing, and thus - allows the guest to see and interact more easily with - processes outside of the container. Note that using this - option makes it impossible to start up a full Operating System - in the container, as an init system cannot operate in this - mode. It is only useful to run specific programs or - applications this way, without involving an init system in the - container. This option implies . - This option may not be combined with - . - - @@ -877,9 +858,7 @@ and shown by tools such as ps1. If the container does not run an init system, it is - recommended to set this option to no. Note - that implies - . + recommended to set this option to no. diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 05e1fc1ab7..b7c2fe9e55 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -269,7 +269,6 @@ static void help(void) { " --overlay-ro=PATH[:PATH...]:PATH\n" " Similar, but creates a read-only overlay mount\n" " -E --setenv=NAME=VALUE Pass an environment variable to PID 1\n" - " --share-system Share system namespaces with host\n" " --register=BOOLEAN Register container as machine\n" " --keep-unit Do not register a scope for the machine, reuse\n" " the service unit nspawn is running in\n" @@ -405,7 +404,7 @@ static int parse_argv(int argc, char *argv[]) { { "selinux-context", required_argument, NULL, 'Z' }, { "selinux-apifs-context", required_argument, NULL, 'L' }, { "quiet", no_argument, NULL, 'q' }, - { "share-system", no_argument, NULL, ARG_SHARE_SYSTEM }, + { "share-system", no_argument, NULL, ARG_SHARE_SYSTEM }, /* not documented */ { "register", required_argument, NULL, ARG_REGISTER }, { "keep-unit", no_argument, NULL, ARG_KEEP_UNIT }, { "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE }, @@ -814,6 +813,8 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_SHARE_SYSTEM: + /* We don't officially support this anymore, except for compat reasons. People should use the + * $SYSTEMD_NSPAWN_SHARE_SYSTEM environment variable instead. */ arg_share_system = true; break; @@ -1018,6 +1019,9 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } + if (getenv_bool("SYSTEMD_NSPAWN_SHARE_SYSTEM") > 0) + arg_share_system = true; + if (arg_share_system) arg_register = false; @@ -1025,7 +1029,7 @@ static int parse_argv(int argc, char *argv[]) { arg_userns_chown = true; if (arg_start_mode != START_PID1 && arg_share_system) { - log_error("--boot and --share-system may not be combined."); + log_error("--boot and SYSTEMD_NSPAWN_SHARE_SYSTEM=1 may not be combined."); return -EINVAL; } -- cgit v1.2.3-54-g00ecf From 43992e57e0bf479a583e90fa2e23f0f1aa2fc2fb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2016 15:12:42 +0200 Subject: core: drop spurious newline --- src/core/manager.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/manager.c b/src/core/manager.c index e41b65da50..c20e185d78 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -553,7 +553,6 @@ static int manager_default_environment(Manager *m) { return 0; } - int manager_new(UnitFileScope scope, bool test_run, Manager **_m) { Manager *m; int r; -- cgit v1.2.3-54-g00ecf From 6af760f3b263d3ddfa80a4168ad0a0c5e59bae1f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2016 15:25:55 +0200 Subject: core: inherit TERM from PID 1 for all services started on /dev/console This way, invoking nspawn from a shell in the best case inherits the TERM setting all the way down into the login shell spawned in the container. Fixes: #3697 --- src/basic/terminal-util.c | 2 +- src/core/execute.c | 60 +++++++++++++++++++++++++++++++++-------------- src/core/main.c | 2 +- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index df56d85317..f0a46c48cf 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -785,7 +785,7 @@ bool tty_is_vc_resolve(const char *tty) { } const char *default_term_for_tty(const char *tty) { - return tty && tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220"; + return tty && tty_is_vc_resolve(tty) ? "linux" : "vt220"; } int fd_columns(int fd) { diff --git a/src/core/execute.c b/src/core/execute.c index 26e9cd5339..0bf80fc437 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -219,12 +219,36 @@ static void exec_context_tty_reset(const ExecContext *context, const ExecParamet (void) vt_disallocate(path); } +static bool is_terminal_input(ExecInput i) { + return IN_SET(i, + EXEC_INPUT_TTY, + EXEC_INPUT_TTY_FORCE, + EXEC_INPUT_TTY_FAIL); +} + static bool is_terminal_output(ExecOutput o) { - return - o == EXEC_OUTPUT_TTY || - o == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || - o == EXEC_OUTPUT_KMSG_AND_CONSOLE || - o == EXEC_OUTPUT_JOURNAL_AND_CONSOLE; + return IN_SET(o, + EXEC_OUTPUT_TTY, + EXEC_OUTPUT_SYSLOG_AND_CONSOLE, + EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_JOURNAL_AND_CONSOLE); +} + +static bool exec_context_needs_term(const ExecContext *c) { + assert(c); + + /* Return true if the execution context suggests we should set $TERM to something useful. */ + + if (is_terminal_input(c->std_input)) + return true; + + if (is_terminal_output(c->std_output)) + return true; + + if (is_terminal_output(c->std_error)) + return true; + + return !!c->tty_path; } static int open_null_as(int flags, int nfd) { @@ -363,13 +387,6 @@ static int open_terminal_as(const char *path, mode_t mode, int nfd) { return r; } -static bool is_terminal_input(ExecInput i) { - return - i == EXEC_INPUT_TTY || - i == EXEC_INPUT_TTY_FORCE || - i == EXEC_INPUT_TTY_FAIL; -} - static int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) { if (is_terminal_input(std_input) && !apply_tty_stdin) @@ -1444,12 +1461,21 @@ static int build_environment( our_env[n_env++] = x; } - if (is_terminal_input(c->std_input) || - c->std_output == EXEC_OUTPUT_TTY || - c->std_error == EXEC_OUTPUT_TTY || - c->tty_path) { + if (exec_context_needs_term(c)) { + const char *tty_path, *term = NULL; + + tty_path = exec_context_tty_path(c); + + /* If we are forked off PID 1 and we are supposed to operate on /dev/console, then let's try to inherit + * the $TERM set for PID 1. This is useful for containers so that the $TERM the container manager + * passes to PID 1 ends up all the way in the console login shown. */ + + if (path_equal(tty_path, "/dev/console") && getppid() == 1) + term = getenv("TERM"); + if (!term) + term = default_term_for_tty(tty_path); - x = strdup(default_term_for_tty(exec_context_tty_path(c))); + x = strappend("TERM=", term); if (!x) return -ENOMEM; our_env[n_env++] = x; diff --git a/src/core/main.c b/src/core/main.c index c46d886653..094bbef964 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1318,7 +1318,7 @@ static int fixup_environment(void) { return r; if (r == 0) { - term = strdup(default_term_for_tty("/dev/console") + 5); + term = strdup(default_term_for_tty("/dev/console")); if (!term) return -ENOMEM; } -- cgit v1.2.3-54-g00ecf From 70493828032abc74e5134563a915c4a3ccdde7f2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2016 20:00:33 +0200 Subject: execute: don't set $SHELL and $HOME for services, if they don't contain interesting data --- src/core/execute.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/core/execute.c b/src/core/execute.c index 0bf80fc437..77a75245cb 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1724,6 +1724,17 @@ static int exec_child( *exit_status = EXIT_USER; return r; } + + /* Don't set $HOME or $SHELL if they are are not particularly enlightening anyway. */ + if (isempty(home) || path_equal(home, "/")) + home = NULL; + + if (isempty(shell) || PATH_IN_SET(shell, + "/bin/nologin", + "/sbin/nologin", + "/usr/bin/nologin", + "/usr/sbin/nologin")) + shell = NULL; } if (context->group) { -- cgit v1.2.3-54-g00ecf From f7b7b3df9e24713464d9089f62958c8c5c3aac49 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 3 Aug 2016 14:51:05 +0200 Subject: nspawn: if we can't mark the boot ID RO let's fail It's probably better to be safe here. --- src/nspawn/nspawn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index b7c2fe9e55..5c6605a08e 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1320,7 +1320,7 @@ static int setup_boot_id(const char *dest) { if (mount(from, to, NULL, MS_BIND, NULL) < 0) r = log_error_errno(errno, "Failed to bind mount boot id: %m"); else if (mount(NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL) < 0) - log_warning_errno(errno, "Failed to make boot id read-only, ignoring: %m"); + r = log_error_errno(errno, "Failed to make boot id read-only: %m"); (void) unlink(from); return r; -- cgit v1.2.3-54-g00ecf From 7f5da8bd4fb1ba49ba40195a74ca76bb5d4d1f81 Mon Sep 17 00:00:00 2001 From: Lukáš Nykrýn Date: Wed, 3 Aug 2016 17:08:37 +0200 Subject: systemctl: consider service running only when it is in active or reloading state (#3874) Otherwise for example services that are failing on start and have Restart=on-failure and bigger RestartSec systemctl status will return 0. Fixes: #3864 --- src/systemctl/systemctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 782824ff38..4fa7adfc41 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -4767,7 +4767,7 @@ static int show_one( else if (streq(verb, "status")) { print_status_info(bus, &info, ellipsized); - if (info.active_state && STR_IN_SET(info.active_state, "inactive", "failed")) + if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading")) r = EXIT_PROGRAM_NOT_RUNNING; else r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK; -- cgit v1.2.3-54-g00ecf From d251207d555a1a0d97924980e49b0ba563b9fc67 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 3 Aug 2016 18:44:51 +0200 Subject: core: add new PrivateUsers= option to service execution This setting adds minimal user namespacing support to a service. When set the invoked processes will run in their own user namespace. Only a trivial mapping will be set up: the root user/group is mapped to root, and the user/group of the service will be mapped to itself, everything else is mapped to nobody. If this setting is used the service runs with no capabilities on the host, but configurable capabilities within the service. This setting is particularly useful in conjunction with RootDirectory= as the need to synchronize /etc/passwd and /etc/group between the host and the service OS tree is reduced, as only three UID/GIDs need to match: root, nobody and the user of the service itself. But even outside the RootDirectory= case this setting is useful to substantially reduce the attack surface of a service. Example command to test this: systemd-run -p PrivateUsers=1 -p User=foobar -t /bin/sh This runs a shell as user "foobar". When typing "ps" only processes owned by "root", by "foobar", and by "nobody" should be visible. --- man/systemd.exec.xml | 65 ++++++++----- src/core/dbus-execute.c | 7 +- src/core/execute.c | 168 +++++++++++++++++++++++++++++++++- src/core/execute.h | 1 + src/core/load-fragment-gperf.gperf.m4 | 3 +- src/shared/bus-unit-util.c | 2 +- 6 files changed, 215 insertions(+), 31 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 58ba582911..2190da55d4 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -107,36 +107,29 @@ WorkingDirectory= - Takes a directory path relative to the service's root - directory specified by RootDirectory=, or the - special value ~. Sets the working directory - for executed processes. If set to ~, the - home directory of the user specified in - User= is used. If not set, defaults to the - root directory when systemd is running as a system instance - and the respective user's home directory if run as user. If - the setting is prefixed with the - - character, a missing working directory is not considered - fatal. If RootDirectory= is not set, then - WorkingDirectory= is relative to the root of - the system running the service manager. - Note that setting this parameter might result in - additional dependencies to be added to the unit (see - above). + Takes a directory path relative to the service's root directory specified by + RootDirectory=, or the special value ~. Sets the working directory for + executed processes. If set to ~, the home directory of the user specified in + User= is used. If not set, defaults to the root directory when systemd is running as a + system instance and the respective user's home directory if run as user. If the setting is prefixed with the + - character, a missing working directory is not considered fatal. If + RootDirectory= is not set, then WorkingDirectory= is relative to the root + of the system running the service manager. Note that setting this parameter might result in additional + dependencies to be added to the unit (see above). RootDirectory= - Takes a directory path relative to the host's root directory - (i.e. the root of the system running the service manager). Sets the - root directory for executed processes, with the chroot2 - system call. If this is used, it must be ensured that the - process binary and all its auxiliary files are available in - the chroot() jail. Note that setting this - parameter might result in additional dependencies to be added - to the unit (see above). + Takes a directory path relative to the host's root directory (i.e. the root of the system + running the service manager). Sets the root directory for executed processes, with the chroot2 system + call. If this is used, it must be ensured that the process binary and all its auxiliary files are available in + the chroot() jail. Note that setting this parameter might result in additional + dependencies to be added to the unit (see above). + + The PrivateUsers= setting is particularly useful in conjunction with + RootDirectory=. For details, see below. @@ -998,6 +991,28 @@ accessible). + + PrivateUsers= + + Takes a boolean argument. If true, sets up a new user namespace for the executed processes and + configures a minimal user and group mapping, that maps the root user and group as well as + the unit's own user and group to themselves and everything else to the nobody user and + group. This is useful to securely detach the user and group databases used by the unit from the rest of the + system, and thus to create an effective sandbox environment. All files, directories, processes, IPC objects and + other resources owned by users/groups not equalling root or the unit's own will stay visible + from within the unit but appear owned by the nobody user and group. If this mode is enabled, + all unit processes are run without privileges in the host user namespace (regardless if the unit's own + user/group is root or not). Specifically this means that the process will have zero process + capabilities on the host's user namespace, but full capabilities within the service's user namespace. Settings + such as CapabilityBoundingSet= will affect only the latter, and there's no way to acquire + additional capabilities in the host's user namespace. Defaults to off. + + This setting is particularly useful in conjunction with RootDirectory=, as the need to + synchronize the user and group databases in the root directory and on the host is reduced, as the only users + and groups who need to be matched are root, nobody and the unit's own + user and group. + + ProtectSystem= diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 9c50cd93e5..4b3bbfbc7d 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -705,8 +705,9 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST), @@ -1068,7 +1069,7 @@ int bus_exec_context_set_transient_property( } else if (STR_IN_SET(name, "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", - "PrivateTmp", "PrivateDevices", "PrivateNetwork", + "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute", "RestrictRealtime", "DynamicUser")) { int b; @@ -1090,6 +1091,8 @@ int bus_exec_context_set_transient_property( c->private_devices = b; else if (streq(name, "PrivateNetwork")) c->private_network = b; + else if (streq(name, "PrivateUsers")) + c->private_users = b; else if (streq(name, "NoNewPrivileges")) c->no_new_privileges = b; else if (streq(name, "SyslogLevelPrefix")) diff --git a/src/core/execute.c b/src/core/execute.c index 26e9cd5339..cec3b3cf40 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1526,6 +1527,159 @@ static bool exec_needs_mount_namespace( return false; } +static int setup_private_users(uid_t uid, gid_t gid) { + _cleanup_free_ char *uid_map = NULL, *gid_map = NULL; + _cleanup_close_pair_ int errno_pipe[2] = { -1, -1 }; + _cleanup_close_ int unshare_ready_fd = -1; + _cleanup_(sigkill_waitp) pid_t pid = 0; + uint64_t c = 1; + siginfo_t si; + ssize_t n; + int r; + + /* Set up a user namespace and map root to root, the selected UID/GID to itself, and everything else to + * nobody. In order to be able to write this mapping we need CAP_SETUID in the original user namespace, which + * we however lack after opening the user namespace. To work around this we fork() a temporary child process, + * which waits for the parent to create the new user namespace while staying in the original namespace. The + * child then writes the UID mapping, under full privileges. The parent waits for the child to finish and + * continues execution normally. */ + + if (uid != 0 && uid_is_valid(uid)) + asprintf(&uid_map, + "0 0 1\n" /* Map root → root */ + UID_FMT " " UID_FMT " 1\n", /* Map $UID → $UID */ + uid, uid); /* The case where the above is the same */ + else + uid_map = strdup("0 0 1\n"); + if (!uid_map) + return -ENOMEM; + + if (gid != 0 && gid_is_valid(gid)) + asprintf(&gid_map, + "0 0 1\n" /* Map root → root */ + GID_FMT " " GID_FMT " 1\n", /* Map $GID → $GID */ + gid, gid); + else + gid_map = strdup("0 0 1\n"); /* The case where the above is the same */ + if (!gid_map) + return -ENOMEM; + + /* Create a communication channel so that the parent can tell the child when it finished creating the user + * namespace. */ + unshare_ready_fd = eventfd(0, EFD_CLOEXEC); + if (unshare_ready_fd < 0) + return -errno; + + /* Create a communication channel so that the child can tell the parent a proper error code in case it + * failed. */ + if (pipe2(errno_pipe, O_CLOEXEC) < 0) + return -errno; + + pid = fork(); + if (pid < 0) + return -errno; + + if (pid == 0) { + _cleanup_close_ int fd = -1; + const char *a; + pid_t ppid; + + /* Child process, running in the original user namespace. Let's update the parent's UID/GID map from + * here, after the parent opened its own user namespace. */ + + ppid = getppid(); + errno_pipe[0] = safe_close(errno_pipe[0]); + + /* Wait until the parent unshared the user namespace */ + if (read(unshare_ready_fd, &c, sizeof(c)) < 0) { + r = -errno; + goto child_fail; + } + + /* Disable the setgroups() system call in the child user namespace, for good. */ + a = procfs_file_alloca(ppid, "setgroups"); + fd = open(a, O_WRONLY|O_CLOEXEC); + if (fd < 0) { + if (errno != ENOENT) { + r = -errno; + goto child_fail; + } + + /* If the file is missing the kernel is too old, let's continue anyway. */ + } else { + if (write(fd, "deny\n", 5) < 0) { + r = -errno; + goto child_fail; + } + + fd = safe_close(fd); + } + + /* First write the GID map */ + a = procfs_file_alloca(ppid, "gid_map"); + fd = open(a, O_WRONLY|O_CLOEXEC); + if (fd < 0) { + r = -errno; + goto child_fail; + } + if (write(fd, gid_map, strlen(gid_map)) < 0) { + r = -errno; + goto child_fail; + } + fd = safe_close(fd); + + /* The write the UID map */ + a = procfs_file_alloca(ppid, "uid_map"); + fd = open(a, O_WRONLY|O_CLOEXEC); + if (fd < 0) { + r = -errno; + goto child_fail; + } + if (write(fd, uid_map, strlen(uid_map)) < 0) { + r = -errno; + goto child_fail; + } + + _exit(EXIT_SUCCESS); + + child_fail: + (void) write(errno_pipe[1], &r, sizeof(r)); + _exit(EXIT_FAILURE); + } + + errno_pipe[1] = safe_close(errno_pipe[1]); + + if (unshare(CLONE_NEWUSER) < 0) + return -errno; + + /* Let the child know that the namespace is ready now */ + if (write(unshare_ready_fd, &c, sizeof(c)) < 0) + return -errno; + + /* Try to read an error code from the child */ + n = read(errno_pipe[0], &r, sizeof(r)); + if (n < 0) + return -errno; + if (n == sizeof(r)) { /* an error code was sent to us */ + if (r < 0) + return r; + return -EIO; + } + if (n != 0) /* on success we should have read 0 bytes */ + return -EIO; + + r = wait_for_terminate(pid, &si); + if (r < 0) + return r; + pid = 0; + + /* If something strange happened with the child, let's consider this fatal, too */ + if (si.si_code != CLD_EXITED || si.si_status != 0) + return -EIO; + + return 0; +} + static void append_socket_pair(int *array, unsigned *n, int pair[2]) { assert(array); assert(n); @@ -2037,6 +2191,14 @@ static int exec_child( } #endif + if (params->apply_permissions && context->private_users) { + r = setup_private_users(uid, gid); + if (r < 0) { + *exit_status = EXIT_USER; + return r; + } + } + /* We repeat the fd closing here, to make sure that * nothing is leaked from the PAM modules. Note that * we are more aggressive this time since socket_fd @@ -2598,8 +2760,9 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { "%sRootDirectory: %s\n" "%sNonBlocking: %s\n" "%sPrivateTmp: %s\n" - "%sPrivateNetwork: %s\n" "%sPrivateDevices: %s\n" + "%sPrivateNetwork: %s\n" + "%sPrivateUsers: %s\n" "%sProtectHome: %s\n" "%sProtectSystem: %s\n" "%sIgnoreSIGPIPE: %s\n" @@ -2610,8 +2773,9 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { prefix, c->root_directory ? c->root_directory : "/", prefix, yes_no(c->non_blocking), prefix, yes_no(c->private_tmp), - prefix, yes_no(c->private_network), prefix, yes_no(c->private_devices), + prefix, yes_no(c->private_network), + prefix, yes_no(c->private_users), prefix, protect_home_to_string(c->protect_home), prefix, protect_system_to_string(c->protect_system), prefix, yes_no(c->ignore_sigpipe), diff --git a/src/core/execute.h b/src/core/execute.h index 48cc18fbb3..5fac3e85e8 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -171,6 +171,7 @@ struct ExecContext { bool private_tmp; bool private_network; bool private_devices; + bool private_users; ProtectSystem protect_system; ProtectHome protect_home; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 396f847213..251155b428 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -88,8 +88,9 @@ $1.ReadWritePaths, config_parse_namespace_path_strv, 0, $1.ReadOnlyPaths, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_only_paths) $1.InaccessiblePaths, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_paths) $1.PrivateTmp, config_parse_bool, 0, offsetof($1, exec_context.private_tmp) -$1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network) $1.PrivateDevices, config_parse_bool, 0, offsetof($1, exec_context.private_devices) +$1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network) +$1.PrivateUsers, config_parse_bool, 0, offsetof($1, exec_context.private_users) $1.ProtectSystem, config_parse_protect_system, 0, offsetof($1, exec_context) $1.ProtectHome, config_parse_protect_home, 0, offsetof($1, exec_context) $1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context) diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 14bf8ad627..9d8061b539 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -202,7 +202,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen "CPUAccounting", "MemoryAccounting", "IOAccounting", "BlockIOAccounting", "TasksAccounting", "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies", "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit", - "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges", + "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges", "SyslogLevelPrefix", "Delegate", "RemainAfterElapse", "MemoryDenyWriteExecute", "RestrictRealtime", "DynamicUser")) { -- cgit v1.2.3-54-g00ecf From 8ce9b83a8f0316b42143ad01c10e4944acc85e87 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 3 Aug 2016 18:40:48 +0200 Subject: update TODO --- TODO | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index bb36522bf9..0199d9d509 100644 --- a/TODO +++ b/TODO @@ -66,11 +66,10 @@ Features: * ProtectKeyRing= to take keyring calls away -* PrivateUsers= which maps the all user ids except root and the one specified - in User= to nobody - * ProtectControlGroups= which mounts all of /sys/fs/cgroup read-only +* RemoveKeyRing= to remove all keyring entries of the specified user + * Add DataDirectory=, CacheDirectory= and LogDirectory= to match RuntimeDirectory=, and create it as necessary when starting a service, owned by the right user. @@ -90,6 +89,11 @@ Features: * expose the "privileged" flag of ExecCommand on the bus, and open it up to transient units +* in nss-systemd, if we run inside of RootDirectory= with PrivateUsers= set, + find a way to map the User=/Group= of the service to the right name. This way + a user/group for a service only has to exist on the host for the right + mapping to work. + * allow attaching additional journald log fields to cgroups * rework fopen_temporary() to make use of open_tmpfile_linkable() (problem: the -- cgit v1.2.3-54-g00ecf From 21b3a0fcd1fc4e4c668c4d34115e2e411dc0dceb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 4 Aug 2016 01:04:53 +0200 Subject: util-lib: make timestamp generation and parsing reversible (#3869) This patch improves parsing and generation of timestamps and calendar specifications in two ways: - The week day is now always printed in the abbreviated English form, instead of the locale's setting. This makes sure we can always parse the week day again, even if the locale is changed. Given that we don't follow locale settings for printing timestamps in any other way either (for example, we always use 24h syntax in order to make uniform parsing possible), it only makes sense to also stick to a generic, non-localized form for the timestamp, too. - When parsing a timestamp, the local timezone (in its DST or non-DST name) may be specified, in addition to "UTC". Other timezones are still not supported however (not because we wouldn't want to, but mostly because libc offers no nice API for that). In itself this brings no new features, however it ensures that any locally formatted timestamp's timezone is also parsable again. These two changes ensure that the output of format_timestamp() may always be passed to parse_timestamp() and results in the original input. The related flavours for usec/UTC also work accordingly. Calendar specifications are extended in a similar way. The man page is updated accordingly, in particular this removes the claim that timestamps systemd prints wouldn't be parsable by systemd. They are now. The man page previously showed invalid timestamps as examples. This has been removed, as the man page shouldn't be a unit test, where such negative examples would be useful. The man page also no longer mentions the names of internal functions, such as format_timestamp_us() or UNIX error codes such as EINVAL. --- man/systemd.time.xml | 150 +++++++++++++++++++++---------------------- src/basic/calendarspec.c | 43 ++++++++++++- src/basic/calendarspec.h | 1 + src/basic/time-util.c | 146 ++++++++++++++++++++++++++++++++++------- src/basic/time-util.h | 4 +- src/test/test-calendarspec.c | 23 +++++++ src/test/test-time.c | 44 +++++++++++++ 7 files changed, 307 insertions(+), 104 deletions(-) diff --git a/man/systemd.time.xml b/man/systemd.time.xml index aae3accb6c..47229b4a4e 100644 --- a/man/systemd.time.xml +++ b/man/systemd.time.xml @@ -57,14 +57,13 @@ Displaying Time Spans - Time spans refer to time durations. On display, systemd will - present time spans as a space-separated series of time values each - suffixed by a time unit. + Time spans refer to time durations. On display, systemd will present time spans as a space-separated series + of time values each suffixed by a time unit. Example: 2h 30min - All specified time values are meant to be added up. The - above hence refers to 150 minutes. + All specified time values are meant to be added up. The above hence refers to 150 minutes. Display is + locale-independent, only English names for the time units are used. @@ -83,13 +82,13 @@ days, day, d weeks, week, w months, month, M (defined as 30.44 days) - years, year, y (define as 365.25 days) + years, year, y (defined as 365.25 days) - If no time unit is specified, generally seconds are assumed, - but some exceptions exist and are marked as such. In a few cases - ns, nsec is accepted too, - where the granularity of the time span allows for this. + If no time unit is specified, generally seconds are assumed, but some exceptions exist and are marked as + such. In a few cases ns, nsec is accepted too, where the granularity of the + time span permits this. Parsing is generally locale-independent, non-English names for the time units are not + accepted. Examples for valid time span specifications: @@ -110,30 +109,29 @@ Fri 2012-11-23 23:02:15 CET - The weekday is printed according to the locale choice of the - user. + The weekday is printed in the abbreviated English language form. The formatting is locale-independent. + + In some cases timestamps are shown in the UTC timezone instead of the local timezone, which is indicated via + the UTC timezone specifier in the output. + + In some cases timestamps are shown with microsecond granularity. In this case the sub-second remainder is + separated by a full stop from the seconds component. Parsing Timestamps - When parsing, systemd will accept a similar syntax, but - expects no timezone specification, unless it is given as the - literal string "UTC". In this case, the time is considered in UTC, - otherwise in the local timezone. The weekday specification is - optional, but when the weekday is specified, it must either be in - the abbreviated (Wed) or non-abbreviated - (Wednesday) English language form (case does - not matter), and is not subject to the locale choice of the user. - Either the date, or the time part may be omitted, in which case - the current date or 00:00:00, respectively, is assumed. The seconds - component of the time may also be omitted, in which case ":00" is - assumed. Year numbers may be specified in full or may be - abbreviated (omitting the century). - - A timestamp is considered invalid if a weekday is specified - and the date does not actually match the specified day of the - week. + When parsing, systemd will accept a similar syntax, but expects no timezone specification, unless it is given + as the literal string UTC (for the UTC timezone) or is specified to be the locally configured + timezone. Other timezones than the local and UTC are not supported. The weekday specification is optional, but when + the weekday is specified, it must either be in the abbreviated (Wed) or non-abbreviated + (Wednesday) English language form (case does not matter), and is not subject to the locale + choice of the user. Either the date, or the time part may be omitted, in which case the current date or 00:00:00, + respectively, is assumed. The seconds component of the time may also be omitted, in which case ":00" is + assumed. Year numbers may be specified in full or may be abbreviated (omitting the century). + + A timestamp is considered invalid if a weekday is specified and the date does not match the specified day of + the week. When parsing, systemd will also accept a few special placeholders instead of timestamps: now may be @@ -167,8 +165,6 @@ 2012-11-23 → Fri 2012-11-23 00:00:00 12-11-23 → Fri 2012-11-23 00:00:00 11:12:13 → Fri 2012-11-23 11:12:13 - 11:12:13.9900009 → Fri 2012-11-23 11:12:13 - format_timestamp_us: Fri 2012-11-23 11:12:13.990000 11:12 → Fri 2012-11-23 11:12:00 now → Fri 2012-11-23 18:15:22 today → Fri 2012-11-23 00:00:00 @@ -176,28 +172,25 @@ yesterday → Fri 2012-11-22 00:00:00 tomorrow → Fri 2012-11-24 00:00:00 +3h30min → Fri 2012-11-23 21:45:22 - +3h30min UTC → -EINVAL -5s → Fri 2012-11-23 18:15:17 11min ago → Fri 2012-11-23 18:04:22 - 11min ago UTC → -EINVAL @1395716396 → Tue 2014-03-25 03:59:56 - Note that timestamps printed by systemd will not be parsed - correctly by systemd, as the timezone specification is not - accepted, and printing timestamps is subject to locale settings - for the weekday, while parsing only accepts English weekday - names. + Note that timestamps displayed by remote systems with a non-matching timezone are usually not parsable + locally, as the timezone component is not understood (unless it happens to be UTC). - In some cases, systemd will display a relative timestamp - (relative to the current time, or the time of invocation of the - command) instead or in addition to an absolute timestamp as - described above. A relative timestamp is formatted as - follows: + Timestamps may also be specified with microsecond granularity. The sub-second remainder is expected separated + by a full stop from the seconds component. Example: + + 2014-03-25 03:59:56.654563 + + In some cases, systemd will display a relative timestamp (relative to the current time, or the time of + invocation of the command) instead of or in addition to an absolute timestamp as described above. A relative + timestamp is formatted as follows: - 2 months 5 days ago + 2 months 5 days ago - Note that any relative timestamp will also parse correctly - where a timestamp is expected. (see above) + Note that a relative timestamp is also accepted where a timestamp is expected (see above). @@ -239,8 +232,9 @@ second component is not specified, :00 is assumed. - A timezone specification is not expected, unless it is given - as the literal string "UTC", similarly to timestamps. + A timezone specification is not expected, unless it is given as the literal string UTC, or + the local timezone, similar to the supported syntax of timestamps (see above). Non-local timezones except for UTC + are not supported. The special expressions minutely, @@ -263,38 +257,38 @@ Examples for valid timestamps and their normalized form: - Sat,Thu,Mon..Wed,Sat..Sun → Mon..Thu,Sat,Sun *-*-* 00:00:00 - Mon,Sun 12-*-* 2,1:23 → Mon,Sun 2012-*-* 01,02:23:00 - Wed *-1 → Wed *-*-01 00:00:00 + Sat,Thu,Mon..Wed,Sat..Sun → Mon..Thu,Sat,Sun *-*-* 00:00:00 + Mon,Sun 12-*-* 2,1:23 → Mon,Sun 2012-*-* 01,02:23:00 + Wed *-1 → Wed *-*-01 00:00:00 Wed..Wed,Wed *-1 → Wed *-*-01 00:00:00 - Wed, 17:48 → Wed *-*-* 17:48:00 + Wed, 17:48 → Wed *-*-* 17:48:00 Wed..Sat,Tue 12-10-15 1:2:3 → Tue..Sat 2012-10-15 01:02:03 - *-*-7 0:0:0 → *-*-07 00:00:00 - 10-15 → *-10-15 00:00:00 - monday *-12-* 17:00 → Mon *-12-* 17:00:00 - Mon,Fri *-*-3,1,2 *:30:45 → Mon,Fri *-*-01,02,03 *:30:45 - 12,14,13,12:20,10,30 → *-*-* 12,13,14:10,20,30:00 - 12..14:10,20,30 → *-*-* 12,13,14:10,20,30:00 - mon,fri *-1/2-1,3 *:30:45 → Mon,Fri *-01/2-01,03 *:30:45 - 03-05 08:05:40 → *-03-05 08:05:40 - 08:05:40 → *-*-* 08:05:40 - 05:40 → *-*-* 05:40:00 - Sat,Sun 12-05 08:05:40 → Sat,Sun *-12-05 08:05:40 - Sat,Sun 08:05:40 → Sat,Sun *-*-* 08:05:40 - 2003-03-05 05:40 → 2003-03-05 05:40:00 -05:40:23.4200004/3.1700005 → 05:40:23.420000/3.170001 - 2003-02..04-05 → 2003-02,03,04-05 00:00:00 - 2003-03-05 05:40 UTC → 2003-03-05 05:40:00 UTC - 2003-03-05 → 2003-03-05 00:00:00 - 03-05 → *-03-05 00:00:00 - hourly → *-*-* *:00:00 - daily → *-*-* 00:00:00 - daily UTC → *-*-* 00:00:00 UTC - monthly → *-*-01 00:00:00 - weekly → Mon *-*-* 00:00:00 - yearly → *-01-01 00:00:00 - annually → *-01-01 00:00:00 - *:2/3 → *-*-* *:02/3:00 + *-*-7 0:0:0 → *-*-07 00:00:00 + 10-15 → *-10-15 00:00:00 + monday *-12-* 17:00 → Mon *-12-* 17:00:00 + Mon,Fri *-*-3,1,2 *:30:45 → Mon,Fri *-*-01,02,03 *:30:45 + 12,14,13,12:20,10,30 → *-*-* 12,13,14:10,20,30:00 + 12..14:10,20,30 → *-*-* 12,13,14:10,20,30:00 + mon,fri *-1/2-1,3 *:30:45 → Mon,Fri *-01/2-01,03 *:30:45 + 03-05 08:05:40 → *-03-05 08:05:40 + 08:05:40 → *-*-* 08:05:40 + 05:40 → *-*-* 05:40:00 + Sat,Sun 12-05 08:05:40 → Sat,Sun *-12-05 08:05:40 + Sat,Sun 08:05:40 → Sat,Sun *-*-* 08:05:40 + 2003-03-05 05:40 → 2003-03-05 05:40:00 + 05:40:23.4200004/3.1700005 → 05:40:23.420000/3.170001 + 2003-02..04-05 → 2003-02,03,04-05 00:00:00 + 2003-03-05 05:40 UTC → 2003-03-05 05:40:00 UTC + 2003-03-05 → 2003-03-05 00:00:00 + 03-05 → *-03-05 00:00:00 + hourly → *-*-* *:00:00 + daily → *-*-* 00:00:00 + daily UTC → *-*-* 00:00:00 UTC + monthly → *-*-01 00:00:00 + weekly → Mon *-*-* 00:00:00 + yearly → *-01-01 00:00:00 + annually → *-01-01 00:00:00 + *:2/3 → *-*-* *:02/3:00 Calendar events are used by timer units, see systemd.timer5 diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c index e4cfab364e..fda293fcb9 100644 --- a/src/basic/calendarspec.c +++ b/src/basic/calendarspec.c @@ -302,6 +302,17 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) { if (c->utc) fputs(" UTC", f); + else if (IN_SET(c->dst, 0, 1)) { + + /* If daylight saving is explicitly on or off, let's show the used timezone. */ + + tzset(); + + if (!isempty(tzname[c->dst])) { + fputc(' ', f); + fputs(tzname[c->dst], f); + } + } r = fflush_and_check(f); if (r < 0) { @@ -747,9 +758,9 @@ fail: } int calendar_spec_from_string(const char *p, CalendarSpec **spec) { + const char *utc; CalendarSpec *c; int r; - const char *utc; assert(p); assert(spec); @@ -760,11 +771,39 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) { c = new0(CalendarSpec, 1); if (!c) return -ENOMEM; + c->dst = -1; utc = endswith_no_case(p, " UTC"); if (utc) { c->utc = true; p = strndupa(p, utc - p); + } else { + const char *e = NULL; + int j; + + tzset(); + + /* Check if the local timezone was specified? */ + for (j = 0; j <= 1; j++) { + if (isempty(tzname[j])) + continue; + + e = endswith_no_case(p, tzname[j]); + if(!e) + continue; + if (e == p) + continue; + if (e[-1] != ' ') + continue; + + break; + } + + /* Found one of the two timezones specified? */ + if (IN_SET(j, 0, 1)) { + p = strndupa(p, e - p - 1); + c->dst = j; + } } if (strcaseeq(p, "minutely")) { @@ -1017,7 +1056,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { for (;;) { /* Normalize the current date */ (void) mktime_or_timegm(&c, spec->utc); - c.tm_isdst = -1; + c.tm_isdst = spec->dst; c.tm_year += 1900; r = find_matching_component(spec->year, &c.tm_year); diff --git a/src/basic/calendarspec.h b/src/basic/calendarspec.h index f6472c1244..c6087228fd 100644 --- a/src/basic/calendarspec.h +++ b/src/basic/calendarspec.h @@ -37,6 +37,7 @@ typedef struct CalendarComponent { typedef struct CalendarSpec { int weekdays_bits; bool utc; + int dst; CalendarComponent *year; CalendarComponent *month; diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 24e681bf85..0ef1f6393e 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -254,32 +254,95 @@ struct timeval *timeval_store(struct timeval *tv, usec_t u) { return tv; } -static char *format_timestamp_internal(char *buf, size_t l, usec_t t, - bool utc, bool us) { +static char *format_timestamp_internal( + char *buf, + size_t l, + usec_t t, + bool utc, + bool us) { + + /* The weekdays in non-localized (English) form. We use this instead of the localized form, so that our + * generated timestamps may be parsed with parse_timestamp(), and always read the same. */ + static const char * const weekdays[] = { + [0] = "Sun", + [1] = "Mon", + [2] = "Tue", + [3] = "Wed", + [4] = "Thu", + [5] = "Fri", + [6] = "Sat", + }; + struct tm tm; time_t sec; - int k; + size_t n; assert(buf); - assert(l > 0); + if (l < + 3 + /* week day */ + 1 + 10 + /* space and date */ + 1 + 8 + /* space and time */ + (us ? 1 + 6 : 0) + /* "." and microsecond part */ + 1 + 1 + /* space and shortest possible zone */ + 1) + return NULL; /* Not enough space even for the shortest form. */ if (t <= 0 || t == USEC_INFINITY) + return NULL; /* Timestamp is unset */ + + sec = (time_t) (t / USEC_PER_SEC); /* Round down */ + if ((usec_t) sec != (t / USEC_PER_SEC)) + return NULL; /* overflow? */ + + if (!localtime_or_gmtime_r(&sec, &tm, utc)) return NULL; - sec = (time_t) (t / USEC_PER_SEC); - localtime_or_gmtime_r(&sec, &tm, utc); + /* Start with the week day */ + assert((size_t) tm.tm_wday < ELEMENTSOF(weekdays)); + memcpy(buf, weekdays[tm.tm_wday], 4); - if (us) - k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S", &tm); - else - k = strftime(buf, l, "%a %Y-%m-%d %H:%M:%S %Z", &tm); + /* Add the main components */ + if (strftime(buf + 3, l - 3, " %Y-%m-%d %H:%M:%S", &tm) <= 0) + return NULL; /* Doesn't fit */ - if (k <= 0) - return NULL; + /* Append the microseconds part, if that's requested */ if (us) { - snprintf(buf + strlen(buf), l - strlen(buf), ".%06llu", (unsigned long long) (t % USEC_PER_SEC)); - if (strftime(buf + strlen(buf), l - strlen(buf), " %Z", &tm) <= 0) - return NULL; + n = strlen(buf); + if (n + 8 > l) + return NULL; /* Microseconds part doesn't fit. */ + + sprintf(buf + n, ".%06llu", (unsigned long long) (t % USEC_PER_SEC)); + } + + /* Append the timezone */ + n = strlen(buf); + if (utc) { + /* If this is UTC then let's explicitly use the "UTC" string here, because gmtime_r() normally uses the + * obsolete "GMT" instead. */ + if (n + 5 > l) + return NULL; /* "UTC" doesn't fit. */ + + strcpy(buf + n, " UTC"); + + } else if (!isempty(tm.tm_zone)) { + size_t tn; + + /* An explicit timezone is specified, let's use it, if it fits */ + tn = strlen(tm.tm_zone); + if (n + 1 + tn + 1 > l) { + /* The full time zone does not fit in. Yuck. */ + + if (n + 1 + _POSIX_TZNAME_MAX + 1 > l) + return NULL; /* Not even enough space for the POSIX minimum (of 6)? In that case, complain that it doesn't fit */ + + /* So the time zone doesn't fit in fully, but the caller passed enough space for the POSIX + * minimum time zone length. In this case suppress the timezone entirely, in order not to dump + * an overly long, hard to read string on the user. This should be safe, because the user will + * assume the local timezone anyway if none is shown. And so does parse_timestamp(). */ + } else { + buf[n++] = ' '; + strcpy(buf + n, tm.tm_zone); + } } return buf; @@ -539,12 +602,11 @@ int parse_timestamp(const char *t, usec_t *usec) { { "Sat", 6 }, }; - const char *k; - const char *utc; + const char *k, *utc, *tzn = NULL; struct tm tm, copy; time_t x; usec_t x_usec, plus = 0, minus = 0, ret; - int r, weekday = -1; + int r, weekday = -1, dst = -1; unsigned i; /* @@ -609,15 +671,55 @@ int parse_timestamp(const char *t, usec_t *usec) { goto finish; } + /* See if the timestamp is suffixed with UTC */ utc = endswith_no_case(t, " UTC"); if (utc) t = strndupa(t, utc - t); + else { + const char *e = NULL; + int j; + + tzset(); + + /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only + * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because + * there are no nice APIs available to cover this. By accepting the local time zone strings, we make + * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't + * support arbitrary timezone specifications. */ + + for (j = 0; j <= 1; j++) { + + if (isempty(tzname[j])) + continue; + + e = endswith_no_case(t, tzname[j]); + if (!e) + continue; + if (e == t) + continue; + if (e[-1] != ' ') + continue; + + break; + } - x = ret / USEC_PER_SEC; + if (IN_SET(j, 0, 1)) { + /* Found one of the two timezones specified. */ + t = strndupa(t, e - t - 1); + dst = j; + tzn = tzname[j]; + } + } + + x = (time_t) (ret / USEC_PER_SEC); x_usec = 0; - assert_se(localtime_or_gmtime_r(&x, &tm, utc)); - tm.tm_isdst = -1; + if (!localtime_or_gmtime_r(&x, &tm, utc)) + return -EINVAL; + + tm.tm_isdst = dst; + if (tzn) + tm.tm_zone = tzn; if (streq(t, "today")) { tm.tm_sec = tm.tm_min = tm.tm_hour = 0; @@ -634,7 +736,6 @@ int parse_timestamp(const char *t, usec_t *usec) { goto from_tm; } - for (i = 0; i < ELEMENTSOF(day_nr); i++) { size_t skip; @@ -727,7 +828,6 @@ parse_usec: return -EINVAL; x_usec = add; - } from_tm: diff --git a/src/basic/time-util.h b/src/basic/time-util.h index 1b058f0e49..99be5ce6ee 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -68,7 +68,9 @@ typedef struct triple_timestamp { #define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC)) #define NSEC_PER_YEAR ((nsec_t) (31557600ULL*NSEC_PER_SEC)) -#define FORMAT_TIMESTAMP_MAX ((4*4+1)+11+9+4+1) /* weekdays can be unicode */ +/* We assume a maximum timezone length of 6. TZNAME_MAX is not defined on Linux, but glibc internally initializes this + * to 6. Let's rely on that. */ +#define FORMAT_TIMESTAMP_MAX (3+1+10+1+8+1+6+1+6+1) #define FORMAT_TIMESTAMP_WIDTH 28 /* when outputting, assume this width */ #define FORMAT_TIMESTAMP_RELATIVE_MAX 256 #define FORMAT_TIMESPAN_MAX 64 diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c index 4a2b93de59..57d9da4855 100644 --- a/src/test/test-calendarspec.c +++ b/src/test/test-calendarspec.c @@ -88,6 +88,27 @@ static void test_next(const char *input, const char *new_tz, usec_t after, usec_ tzset(); } +static void test_timestamp(void) { + char buf[FORMAT_TIMESTAMP_MAX]; + _cleanup_free_ char *t = NULL; + CalendarSpec *c; + usec_t x, y; + + /* Ensure that a timestamp is also a valid calendar specification. Convert forth and back */ + + x = now(CLOCK_REALTIME); + + assert_se(format_timestamp_us(buf, sizeof(buf), x)); + printf("%s\n", buf); + assert_se(calendar_spec_from_string(buf, &c) >= 0); + assert_se(calendar_spec_to_string(c, &t) >= 0); + calendar_spec_free(c); + printf("%s\n", t); + + assert_se(parse_timestamp(t, &y) >= 0); + assert_se(y == x); +} + int main(int argc, char* argv[]) { CalendarSpec *c; @@ -155,5 +176,7 @@ int main(int argc, char* argv[]) { assert_se(calendar_spec_from_string("00:00:00/0.00000001", &c) < 0); assert_se(calendar_spec_from_string("00:00:00.0..00.9", &c) < 0); + test_timestamp(); + return 0; } diff --git a/src/test/test-time.c b/src/test/test-time.c index ee7d55c5ab..7078a0374d 100644 --- a/src/test/test-time.c +++ b/src/test/test-time.c @@ -19,6 +19,7 @@ #include "strv.h" #include "time-util.h" +#include "random-util.h" static void test_parse_sec(void) { usec_t u; @@ -201,6 +202,48 @@ static void test_usec_sub(void) { assert_se(usec_sub(USEC_INFINITY, 5) == USEC_INFINITY); } +static void test_format_timestamp(void) { + unsigned i; + + for (i = 0; i < 100; i++) { + char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESPAN_MAX)]; + usec_t x, y; + + random_bytes(&x, sizeof(x)); + x = x % (2147483600 * USEC_PER_SEC) + 1; + + assert_se(format_timestamp(buf, sizeof(buf), x)); + log_info("%s", buf); + assert_se(parse_timestamp(buf, &y) >= 0); + assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC); + + assert_se(format_timestamp_utc(buf, sizeof(buf), x)); + log_info("%s", buf); + assert_se(parse_timestamp(buf, &y) >= 0); + assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC); + + assert_se(format_timestamp_us(buf, sizeof(buf), x)); + log_info("%s", buf); + assert_se(parse_timestamp(buf, &y) >= 0); + assert_se(x == y); + + assert_se(format_timestamp_us_utc(buf, sizeof(buf), x)); + log_info("%s", buf); + assert_se(parse_timestamp(buf, &y) >= 0); + assert_se(x == y); + + assert_se(format_timestamp_relative(buf, sizeof(buf), x)); + log_info("%s", buf); + assert_se(parse_timestamp(buf, &y) >= 0); + + /* The two calls above will run with a slightly different local time. Make sure we are in the same + * range however, but give enough leeway that this is unlikely to explode. And of course, + * format_timestamp_relative() scales the accuracy with the distance from the current time up to one + * month, cover for that too. */ + assert_se(y > x ? y - x : x - y <= USEC_PER_MONTH + USEC_PER_DAY); + } +} + int main(int argc, char *argv[]) { uintmax_t x; @@ -214,6 +257,7 @@ int main(int argc, char *argv[]) { test_get_timezones(); test_usec_add(); test_usec_sub(); + test_format_timestamp(); /* Ensure time_t is signed */ assert_cc((time_t) -1 < (time_t) 1); -- cgit v1.2.3-54-g00ecf From 29a753df7682424a0ea505698d548f85c514fad5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 4 Aug 2016 01:45:07 +0200 Subject: journalctl: add new output mode "short-full" (#3880) This new output mode formats all timestamps using the usual format_timestamp() call we use pretty much everywhere else. Timestamps formatted this way are some ways more useful than traditional syslog timestamps as they include weekday, month and timezone information, while not being much longer. They are also not locale-dependent. The primary advantage however is that they may be passed directly to journalctl's --since= and --until= switches as soon as #3869 is merged. While we are at it, let's also add "short-unix" to shell completion. --- man/journalctl.xml | 41 ++++---- shell-completion/bash/journalctl | 2 +- shell-completion/bash/systemctl.in | 2 +- shell-completion/zsh/_sd_outputmodes | 2 +- src/shared/logs-show.c | 183 +++++++++++++++++++++-------------- src/shared/output-mode.c | 1 + src/shared/output-mode.h | 1 + 7 files changed, 140 insertions(+), 92 deletions(-) diff --git a/man/journalctl.xml b/man/journalctl.xml index e77621d7b3..c448a29a51 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -248,6 +248,18 @@ + + + + + + is very similar, but shows timestamps in the format the and + options accept. Unlike the timestamp information shown in + output mode this mode includes weekday, year and timezone information in the + output, and is locale-independent. + + + @@ -572,24 +584,17 @@ - Start showing entries on or newer than the - specified date, or on or older than the specified date, - respectively. Date specifications should be of the format - 2012-10-30 18:17:16. If the time part is - omitted, 00:00:00 is assumed. If only the - seconds component is omitted, :00 is - assumed. If the date component is omitted, the current day is - assumed. Alternatively the strings - yesterday, today, - tomorrow are understood, which refer to - 00:00:00 of the day before the current day, the current day, - or the day after the current day, - respectively. now refers to the current - time. Finally, relative times may be specified, prefixed with - - or +, referring to - times before or after the current time, respectively. For complete - time and date specification, see - systemd.time7. + Start showing entries on or newer than the specified date, or on or older than the specified + date, respectively. Date specifications should be of the format 2012-10-30 18:17:16. If the + time part is omitted, 00:00:00 is assumed. If only the seconds component is omitted, + :00 is assumed. If the date component is omitted, the current day is assumed. Alternatively + the strings yesterday, today, tomorrow are understood, + which refer to 00:00:00 of the day before the current day, the current day, or the day after the current day, + respectively. now refers to the current time. Finally, relative times may be specified, + prefixed with - or +, referring to times before or after the current + time, respectively. For complete time and date specification, see + systemd.time7. Note that + prints timestamps that follow precisely this format. diff --git a/shell-completion/bash/journalctl b/shell-completion/bash/journalctl index 53bedcd92e..a999a10df1 100644 --- a/shell-completion/bash/journalctl +++ b/shell-completion/bash/journalctl @@ -65,7 +65,7 @@ _journalctl() { compopt -o filenames ;; --output|-o) - comps='short short-iso short-precise short-monotonic verbose export json json-pretty json-sse cat' + comps='short short-full short-iso short-precise short-monotonic short-unix verbose export json json-pretty json-sse cat' ;; --field|-F) comps=$(journalctl --fields | sort 2>/dev/null) diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in index 6f2b3f122c..2a45dcbba0 100644 --- a/shell-completion/bash/systemctl.in +++ b/shell-completion/bash/systemctl.in @@ -145,7 +145,7 @@ _systemctl () { comps='full enable-only disable-only' ;; --output|-o) - comps='short short-iso short-precise short-monotonic verbose export json + comps='short short-full short-iso short-precise short-monotonic short-unix verbose export json json-pretty json-sse cat' ;; --machine|-M) diff --git a/shell-completion/zsh/_sd_outputmodes b/shell-completion/zsh/_sd_outputmodes index 3836f79b73..52617c6b7a 100644 --- a/shell-completion/zsh/_sd_outputmodes +++ b/shell-completion/zsh/_sd_outputmodes @@ -1,5 +1,5 @@ #autoload local -a _output_opts -_output_opts=(short short-iso short-precise short-monotonic verbose export json json-pretty json-sse cat) +_output_opts=(short short-full short-iso short-precise short-monotonic short-unix verbose export json json-pretty json-sse cat) _describe -t output 'output mode' _output_opts || compadd "$@" diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index d04728f505..f9d9c4ed62 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -45,6 +45,7 @@ #include "parse-util.h" #include "process-util.h" #include "sparse-endian.h" +#include "stdio-util.h" #include "string-table.h" #include "string-util.h" #include "terminal-util.h" @@ -206,6 +207,108 @@ static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, Output return ellipsized; } +static int output_timestamp_monotonic(FILE *f, sd_journal *j, const char *monotonic) { + sd_id128_t boot_id; + uint64_t t; + int r; + + assert(f); + assert(j); + + r = -ENXIO; + if (monotonic) + r = safe_atou64(monotonic, &t); + if (r < 0) + r = sd_journal_get_monotonic_usec(j, &t, &boot_id); + if (r < 0) + return log_error_errno(r, "Failed to get monotonic timestamp: %m"); + + fprintf(f, "[%5llu.%06llu]", + (unsigned long long) (t / USEC_PER_SEC), + (unsigned long long) (t % USEC_PER_SEC)); + + return 1 + 5 + 1 + 6 + 1; +} + +static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, OutputFlags flags, const char *realtime) { + char buf[MAX(FORMAT_TIMESTAMP_MAX, 64)]; + struct tm *(*gettime_r)(const time_t *, struct tm *); + struct tm tm; + uint64_t x; + time_t t; + int r; + + assert(f); + assert(j); + + r = -ENXIO; + if (realtime) + r = safe_atou64(realtime, &x); + if (r < 0) + r = sd_journal_get_realtime_usec(j, &x); + if (r < 0) + return log_error_errno(r, "Failed to get realtime timestamp: %m"); + + if (mode == OUTPUT_SHORT_FULL) { + const char *k; + + if (flags & OUTPUT_UTC) + k = format_timestamp_utc(buf, sizeof(buf), x); + else + k = format_timestamp(buf, sizeof(buf), x); + if (!k) { + log_error("Failed to format timestamp."); + return -EINVAL; + } + + } else { + gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r; + t = (time_t) (x / USEC_PER_SEC); + + switch (mode) { + + case OUTPUT_SHORT_UNIX: + xsprintf(buf, "%10llu.%06llu", (unsigned long long) t, (unsigned long long) (x % USEC_PER_SEC)); + break; + + case OUTPUT_SHORT_ISO: + if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm)) <= 0) { + log_error("Failed for format ISO time"); + return -EINVAL; + } + break; + + case OUTPUT_SHORT: + case OUTPUT_SHORT_PRECISE: + + if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm)) <= 0) { + log_error("Failed to format syslog time"); + return -EINVAL; + } + + if (mode == OUTPUT_SHORT_PRECISE) { + size_t k; + + assert(sizeof(buf) > strlen(buf)); + k = sizeof(buf) - strlen(buf); + + r = snprintf(buf + strlen(buf), k, ".%06llu", (unsigned long long) (x % USEC_PER_SEC)); + if (r <= 0 || (size_t) r >= k) { /* too long? */ + log_error("Failed to format precise time"); + return -EINVAL; + } + } + break; + + default: + assert_not_reached("Unknown time format"); + } + } + + fputs(buf, f); + return (int) strlen(buf); +} + static int output_short( FILE *f, sd_journal *j, @@ -305,78 +408,15 @@ static int output_short( if (priority_len == 1 && *priority >= '0' && *priority <= '7') p = *priority - '0'; - if (mode == OUTPUT_SHORT_MONOTONIC) { - uint64_t t; - sd_id128_t boot_id; - - r = -ENOENT; - - if (monotonic) - r = safe_atou64(monotonic, &t); - - if (r < 0) - r = sd_journal_get_monotonic_usec(j, &t, &boot_id); - - if (r < 0) - return log_error_errno(r, "Failed to get monotonic timestamp: %m"); - - fprintf(f, "[%5llu.%06llu]", - (unsigned long long) (t / USEC_PER_SEC), - (unsigned long long) (t % USEC_PER_SEC)); - - n += 1 + 5 + 1 + 6 + 1; - - } else { - char buf[64]; - uint64_t x; - time_t t; - struct tm tm; - struct tm *(*gettime_r)(const time_t *, struct tm *); - - r = -ENOENT; - gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r; - - if (realtime) - r = safe_atou64(realtime, &x); - - if (r < 0) - r = sd_journal_get_realtime_usec(j, &x); - - if (r < 0) - return log_error_errno(r, "Failed to get realtime timestamp: %m"); - - t = (time_t) (x / USEC_PER_SEC); - - switch (mode) { - - case OUTPUT_SHORT_UNIX: - r = snprintf(buf, sizeof(buf), "%10llu.%06llu", (unsigned long long) t, (unsigned long long) (x % USEC_PER_SEC)); - break; - - case OUTPUT_SHORT_ISO: - r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm)); - break; - - case OUTPUT_SHORT_PRECISE: - r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm)); - if (r > 0) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ".%06llu", (unsigned long long) (x % USEC_PER_SEC)); - break; - - default: - r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm)); - } - - if (r <= 0) { - log_error("Failed to format time."); - return -EINVAL; - } - - fputs(buf, f); - n += strlen(buf); - } + if (mode == OUTPUT_SHORT_MONOTONIC) + r = output_timestamp_monotonic(f, j, monotonic); + else + r = output_timestamp_realtime(f, j, mode, flags, realtime); + if (r < 0) + return r; + n += r; - if (hostname && (flags & OUTPUT_NO_HOSTNAME)) { + if (flags & OUTPUT_NO_HOSTNAME) { /* Suppress display of the hostname if this is requested. */ hostname = NULL; hostname_len = 0; @@ -910,6 +950,7 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])( [OUTPUT_SHORT_PRECISE] = output_short, [OUTPUT_SHORT_MONOTONIC] = output_short, [OUTPUT_SHORT_UNIX] = output_short, + [OUTPUT_SHORT_FULL] = output_short, [OUTPUT_VERBOSE] = output_verbose, [OUTPUT_EXPORT] = output_export, [OUTPUT_JSON] = output_json, diff --git a/src/shared/output-mode.c b/src/shared/output-mode.c index bec53ee0ae..67d8208ad2 100644 --- a/src/shared/output-mode.c +++ b/src/shared/output-mode.c @@ -22,6 +22,7 @@ static const char *const output_mode_table[_OUTPUT_MODE_MAX] = { [OUTPUT_SHORT] = "short", + [OUTPUT_SHORT_FULL] = "short-full", [OUTPUT_SHORT_ISO] = "short-iso", [OUTPUT_SHORT_PRECISE] = "short-precise", [OUTPUT_SHORT_MONOTONIC] = "short-monotonic", diff --git a/src/shared/output-mode.h b/src/shared/output-mode.h index f37189e57f..ff29dafcb5 100644 --- a/src/shared/output-mode.h +++ b/src/shared/output-mode.h @@ -23,6 +23,7 @@ typedef enum OutputMode { OUTPUT_SHORT, + OUTPUT_SHORT_FULL, OUTPUT_SHORT_ISO, OUTPUT_SHORT_PRECISE, OUTPUT_SHORT_MONOTONIC, -- cgit v1.2.3-54-g00ecf From d26d41f36c598aeddcb25cca19ee3526f771c045 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 4 Aug 2016 09:57:36 +1000 Subject: hwdb: fix hwdb entry for numeric-only Lenovo *40, *50 and *60 series Commit e5bc3f4fdc matches on e.g. a T440s, but not a T440 (i.e. the one without a suffix). --- hwdb/70-pointingstick.hwdb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index ff52f11e45..c0ec8ffbe0 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -96,10 +96,13 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX230 # Lenovo Thinkpad X230 tablet evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX230Tablet:* # Lenovo Thinkpad *40 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??40:* evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??40?:* # Lenovo Thinkpad *50 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??50:* evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??50?:* # Lenovo Thinkpad *60 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??60:* evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??60?:* # Lenovo Thinkpad X1 Carbon 3rd gen evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:* -- cgit v1.2.3-54-g00ecf From 5124866d7355b685c08aef6abc618e03367e4b93 Mon Sep 17 00:00:00 2001 From: David Michael Date: Thu, 4 Aug 2016 04:09:54 -0700 Subject: util-lib: add parse_percent_unbounded() for percentages over 100% (#3886) This permits CPUQuota to accept greater values as documented. --- src/basic/parse-util.c | 11 +++++++++-- src/basic/parse-util.h | 1 + src/core/load-fragment.c | 2 +- src/shared/bus-unit-util.c | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c index 503a895731..11849ade0b 100644 --- a/src/basic/parse-util.c +++ b/src/basic/parse-util.c @@ -533,7 +533,7 @@ int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) { return 0; } -int parse_percent(const char *p) { +int parse_percent_unbounded(const char *p) { const char *pc, *n; unsigned v; int r; @@ -546,8 +546,15 @@ int parse_percent(const char *p) { r = safe_atou(n, &v); if (r < 0) return r; + + return (int) v; +} + +int parse_percent(const char *p) { + int v = parse_percent_unbounded(p); + if (v > 100) return -ERANGE; - return (int) v; + return v; } diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h index 73441bb6fd..f0fa5f9752 100644 --- a/src/basic/parse-util.h +++ b/src/basic/parse-util.h @@ -106,4 +106,5 @@ int safe_atod(const char *s, double *ret_d); int parse_fractional_part_u(const char **s, size_t digits, unsigned *res); +int parse_percent_unbounded(const char *p); int parse_percent(const char *p); diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index e8cb3a4249..d5f035b67f 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2903,7 +2903,7 @@ int config_parse_cpu_quota( return 0; } - r = parse_percent(rvalue); + r = parse_percent_unbounded(rvalue); if (r <= 0) { log_syntax(unit, LOG_ERR, filename, line, r, "CPU quota '%s' invalid. Ignoring.", rvalue); return 0; diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 14bf8ad627..589f9d46e9 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -84,7 +84,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen if (isempty(eq)) r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", USEC_INFINITY); else { - r = parse_percent(eq); + r = parse_percent_unbounded(eq); if (r <= 0) { log_error_errno(r, "CPU quota '%s' invalid.", eq); return -EINVAL; -- cgit v1.2.3-54-g00ecf From 584c6e70509ef0792a22d456e96718d3ea9cb30d Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 3 Aug 2016 19:52:28 -0400 Subject: journalctl,systemctl: add "short-full", "short-unix" mode to --help --- src/journal/journalctl.c | 6 +++--- src/systemctl/systemctl.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 53c6180864..6f841efb69 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -297,9 +297,9 @@ static void help(void) { " -n --lines[=INTEGER] Number of journal entries to show\n" " --no-tail Show all lines, even in follow mode\n" " -r --reverse Show the newest entries first\n" - " -o --output=STRING Change journal output mode (short, short-iso,\n" - " short-precise, short-monotonic, verbose,\n" - " export, json, json-pretty, json-sse, cat)\n" + " -o --output=STRING Change journal output mode (short, short-precise,\n" + " short-iso, short-full, short-monotonic, short-unix,\n" + " verbose, export, json, json-pretty, json-sse, cat)\n" " --utc Express time in Coordinated Universal Time (UTC)\n" " -x --catalog Add message explanations where available\n" " --no-full Ellipsize fields\n" diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 4fa7adfc41..b4ce6fba5a 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -6591,9 +6591,9 @@ static void systemctl_help(void) { " --preset-mode= Apply only enable, only disable, or all presets\n" " --root=PATH Enable unit files in the specified root directory\n" " -n --lines=INTEGER Number of journal entries to show\n" - " -o --output=STRING Change journal output mode (short, short-iso,\n" - " short-precise, short-monotonic, verbose,\n" - " export, json, json-pretty, json-sse, cat)\n" + " -o --output=STRING Change journal output mode (short, short-precise,\n" + " short-iso, short-full, short-monotonic, short-unix,\n" + " verbose, export, json, json-pretty, json-sse, cat)\n" " --firmware-setup Tell the firmware to show the setup menu on next boot\n" " --plain Print unit dependencies as a list instead of a tree\n\n" "Unit Commands:\n" -- cgit v1.2.3-54-g00ecf From 90b4a64d77ad9395d940b095a27cf9f1cb65e5cb Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 3 Aug 2016 20:05:37 -0400 Subject: nspawn,resolve: short --help output to fit within 80 columns make dist-check-help FTW! --- src/nspawn/nspawn.c | 18 ++++++++---------- src/resolve/resolve-tool.c | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 6cc1b9177d..3d131863f7 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -216,10 +216,10 @@ static void help(void) { " --uuid=UUID Set a specific machine UUID for the container\n" " -S --slice=SLICE Place the container in the specified slice\n" " --property=NAME=VALUE Set scope unit property\n" - " -U --private-users=pick Run within user namespace, pick UID/GID range automatically\n" + " -U --private-users=pick Run within user namespace, autoselect UID/GID range\n" " --private-users[=UIDBASE[:NUIDS]]\n" - " Run within user namespace, user configured UID/GID range\n" - " --private-user-chown Adjust OS tree file ownership for private UID/GID range\n" + " Similar, but with user configured UID/GID range\n" + " --private-user-chown Adjust OS tree ownership to private UID/GID range\n" " --private-network Disable network in container\n" " --network-interface=INTERFACE\n" " Assign an existing network interface to the\n" @@ -236,11 +236,10 @@ static void help(void) { " Add an additional virtual Ethernet link between\n" " host and container\n" " --network-bridge=INTERFACE\n" - " Add a virtual Ethernet connection between host\n" - " and container and add it to an existing bridge on\n" - " the host\n" - " --network-zone=NAME Add a virtual Ethernet connection to the container,\n" - " and add it to an automatically managed bridge interface\n" + " Add a virtual Ethernet connection to the container\n" + " and attach it to an existing bridge on the host\n" + " --network-zone=NAME Similar, but attach the new interface to an\n" + " an automatically managed bridge interface\n" " -p --port=[PROTOCOL:]HOSTPORT[:CONTAINERPORT]\n" " Expose a container IP port on the host\n" " -Z --selinux-context=SECLABEL\n" @@ -275,8 +274,7 @@ static void help(void) { " the service unit nspawn is running in\n" " --volatile[=MODE] Run the system in volatile mode\n" " --settings=BOOLEAN Load additional settings from .nspawn file\n" - " --notify-ready=BOOLEAN Receive notifications from the container's init process,\n" - " accepted values: yes and no\n" + " --notify-ready=BOOLEAN Receive notifications from the child init process\n" , program_invocation_short_name); } diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c index 6ae3750417..07e4cd7d1d 100644 --- a/src/resolve/resolve-tool.c +++ b/src/resolve/resolve-tool.c @@ -1542,7 +1542,7 @@ static void help(void) { "%1$s [OPTIONS...] --statistics\n" "%1$s [OPTIONS...] --reset-statistics\n" "\n" - "Resolve domain names, IPv4 and IPv6 addresses, DNS resource records, and services.\n\n" + "Resolve domain names, IPv4 and IPv6 addresses, DNS records, and services.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" -- cgit v1.2.3-54-g00ecf From e9fbae3f680ccd8dc3d6d4e7a3d0f7d5de1b28ad Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 3 Aug 2016 23:49:18 -0400 Subject: man: describe list-dependencies --all Meaning of --all was mentioned in list-dependencies description, but the this effect should also be mentioned in the description of the option itself. --- man/systemctl.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/man/systemctl.xml b/man/systemctl.xml index e7880d24f7..0ad0ad6d7e 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -156,6 +156,10 @@ To list all units installed in the file system, use the list-unit-files command instead. + + When listing units with list-dependencies, recursively show + dependencies of all dependent units (by default only dependencies of target units are + shown). -- cgit v1.2.3-54-g00ecf From 1898a1a5c37ba019c7a5a48505befd64f78071dc Mon Sep 17 00:00:00 2001 From: Jonathan Boulle Date: Thu, 4 Aug 2016 15:54:10 +0200 Subject: src/test: add tests for parse_percent_unbounded (#3889) --- src/test/test-parse-util.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c index 0a76308f72..097c464229 100644 --- a/src/test/test-parse-util.c +++ b/src/test/test-parse-util.c @@ -493,6 +493,11 @@ static void test_parse_percent(void) { assert_se(parse_percent("1%%") == -EINVAL); } +static void test_parse_percent_unbounded(void) { + assert_se(parse_percent_unbounded("101%") == 101); + assert_se(parse_percent_unbounded("400%") == 400); +} + int main(int argc, char *argv[]) { log_parse_environment(); log_open(); @@ -507,6 +512,7 @@ int main(int argc, char *argv[]) { test_safe_atoi16(); test_safe_atod(); test_parse_percent(); + test_parse_percent_unbounded(); return 0; } -- cgit v1.2.3-54-g00ecf From 3104883ddc2452ae210de3c70576c03023250a51 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Thu, 4 Aug 2016 19:26:39 +0530 Subject: networkd: remove route if carrier is lost (#3831) Fixes #3669. --- src/network/networkd-link.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index a0da697707..99784b0ebe 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2314,6 +2314,35 @@ static int link_drop_foreign_config(Link *link) { return 0; } +static int link_drop_config(Link *link) { + Address *address; + Route *route; + Iterator i; + int r; + + SET_FOREACH(address, link->addresses, i) { + /* we consider IPv6LL addresses to be managed by the kernel */ + if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1) + continue; + + r = address_remove(address, link, link_address_remove_handler); + if (r < 0) + return r; + } + + SET_FOREACH(route, link->routes, i) { + /* do not touch routes managed by the kernel */ + if (route->protocol == RTPROT_KERNEL) + continue; + + r = route_remove(route, link, link_route_remove_handler); + if (r < 0) + return r; + } + + return 0; +} + static int link_update_lldp(Link *link) { int r; @@ -2860,6 +2889,14 @@ static int link_carrier_lost(Link *link) { return r; } + r = link_drop_config(link); + if (r < 0) + return r; + + r = link_drop_foreign_config(link); + if (r < 0) + return r; + r = link_handle_bound_by_list(link); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 99d2baa2cab0706d89beff596f997d4e3a1c833f Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Thu, 4 Aug 2016 19:30:58 +0530 Subject: networkd: add support to configure NOARP/ARP for interface (#3854) https://lists.freedesktop.org/archives/systemd-devel/2016-August/037268.html --- man/systemd.network.xml | 11 ++++++ src/network/networkd-link.c | 63 ++++++++++++++++++++++++++++++++ src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 + 5 files changed, 77 insertions(+) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 4541a55490..c332cd7bdc 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -212,6 +212,17 @@ below 1280 (the minimum MTU for IPv6) it will automatically be increased to this value. + + ARP= + + A boolean. Enables or disables the ARP (low-level Address Resolution Protocol) + for this interface. Defaults to unset, which means that the kernel default will be used. + For example, disabling ARP is useful when creating multiple MACVLAN or VLAN virtual + interfaces atop a single lower-level physical interface, which will then only serve as a + link/"bridge" device aggregating traffic to the same physical link and not participate in + the network otherwise. + + diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 99784b0ebe..3e10ab1e04 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1314,6 +1314,65 @@ int link_set_mtu(Link *link, uint32_t mtu) { return 0; } +static int set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { + _cleanup_link_unref_ Link *link = userdata; + int r; + + assert(m); + assert(link); + assert(link->ifname); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_link_warning_errno(link, r, "Could not set link flags: %m"); + + return 1; +} + +static int link_set_flags(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + unsigned ifi_change = 0; + unsigned ifi_flags = 0; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + if (link->network->arp < 0) + return 0; + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + if (link->network->arp >= 0) { + ifi_change |= IFF_NOARP; + ifi_flags |= IFF_NOARP; + } + + r = sd_rtnl_message_link_set_flags(req, ifi_flags, ifi_change); + if (r < 0) + return log_link_error_errno(link, r, "Could not set link flags: %m"); + + r = sd_netlink_call_async(link->manager->rtnl, req, set_flags_handler, link, 0, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + static int link_set_bridge(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -2411,6 +2470,10 @@ static int link_configure(Link *link) { if (r < 0) return r; + r = link_set_flags(link); + if (r < 0) + return r; + if (link_ipv4ll_enabled(link)) { r = ipv4ll_configure(link); if (r < 0) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 5172a7b5e9..19adac66b8 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -28,6 +28,7 @@ Match.KernelCommandLine, config_parse_net_condition, Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch) Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac) Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu) +Link.ARP, config_parse_tristate, 0, offsetof(Network, arp) Network.Description, config_parse_string, 0, offsetof(Network, description) Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge) Network.Bond, config_parse_netdev, 0, offsetof(Network, bond) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 2b764d4f24..17bbe5de9f 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -134,6 +134,7 @@ static int network_load_one(Manager *manager, const char *filename) { network->ipv6_hop_limit = -1; network->duid.type = _DUID_TYPE_INVALID; network->proxy_arp = -1; + network->arp = -1; network->ipv6_accept_ra_use_dns = true; r = config_parse(NULL, filename, file, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 08ee939faa..7c0bdc1e4a 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -171,6 +171,7 @@ struct Network { struct ether_addr *mac; unsigned mtu; + int arp; uint32_t iaid; DUID duid; -- cgit v1.2.3-54-g00ecf From 992e8f224b91cacc3d6589bea7882c7ab9c0911b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 26 Jul 2016 17:23:28 +0200 Subject: util-lib: rework /tmp and /var/tmp handling code Beef up the existing var_tmp() call, rename it to var_tmp_dir() and add a matching tmp_dir() call (the former looks for the place for /var/tmp, the latter for /tmp). Both calls check $TMPDIR, $TEMP, $TMP, following the algorithm Python3 uses. All dirs are validated before use. secure_getenv() is used in order to limite exposure in suid binaries. This also ports a couple of users over to these new APIs. The var_tmp() return parameter is changed from an allocated buffer the caller will own to a const string either pointing into environ[], or into a static const buffer. Given that environ[] is mostly considered constant (and this is exposed in the very well-known getenv() call), this should be OK behaviour and allows us to avoid memory allocations in most cases. Note that $TMPDIR and friends override both /var/tmp and /tmp usage if set. --- src/basic/fileio.c | 17 ++++++-- src/basic/fs-util.c | 98 +++++++++++++++++++++++++++++++++++--------- src/basic/fs-util.h | 3 +- src/coredump/coredumpctl.c | 9 +++- src/journal/journal-verify.c | 4 +- src/machine/machined-dbus.c | 2 +- src/test/test-fs-util.c | 54 ++++++++++-------------- 7 files changed, 126 insertions(+), 61 deletions(-) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index f183de4999..6114bf3315 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -1161,8 +1161,8 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) { char *t, *x; uint64_t u; unsigned i; + int r; - assert(p); assert(ret); /* Turns this: @@ -1171,6 +1171,12 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) { * /foo/bar/waldo/.#3c2b6219aa75d7d0 */ + if (!p) { + r = tmp_dir(&p); + if (r < 0) + return r; + } + if (!extra) extra = ""; @@ -1257,10 +1263,13 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) int open_tmpfile_unlinkable(const char *directory, int flags) { char *p; - int fd; + int fd, r; - if (!directory) - directory = "/tmp"; + if (!directory) { + r = tmp_dir(&directory); + if (r < 0) + return r; + } /* Returns an unlinked temporary file that cannot be linked into the file system anymore */ diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index f0c6f3265e..ce87257bc1 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -496,34 +496,94 @@ int get_files_in_directory(const char *path, char ***list) { return n; } -int var_tmp(char **ret) { - const char *tmp_dir = NULL; - const char *env_tmp_dir = NULL; - char *c = NULL; - int r; +static int getenv_tmp_dir(const char **ret_path) { + const char *n; + int r, ret = 0; - assert(ret); + assert(ret_path); - env_tmp_dir = getenv("TMPDIR"); - if (env_tmp_dir != NULL) { - r = is_dir(env_tmp_dir, true); - if (r < 0 && r != -ENOENT) - return r; - if (r > 0) - tmp_dir = env_tmp_dir; + /* We use the same order of environment variables python uses in tempfile.gettempdir(): + * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */ + FOREACH_STRING(n, "TMPDIR", "TEMP", "TMP") { + const char *e; + + e = secure_getenv(n); + if (!e) + continue; + if (!path_is_absolute(e)) { + r = -ENOTDIR; + goto next; + } + if (!path_is_safe(e)) { + r = -EPERM; + goto next; + } + + r = is_dir(e, true); + if (r < 0) + goto next; + if (r == 0) { + r = -ENOTDIR; + goto next; + } + + *ret_path = e; + return 1; + + next: + /* Remember first error, to make this more debuggable */ + if (ret >= 0) + ret = r; } - if (!tmp_dir) - tmp_dir = "/var/tmp"; + if (ret < 0) + return ret; - c = strdup(tmp_dir); - if (!c) - return -ENOMEM; - *ret = c; + *ret_path = NULL; + return ret; +} +static int tmp_dir_internal(const char *def, const char **ret) { + const char *e; + int r, k; + + assert(def); + assert(ret); + + r = getenv_tmp_dir(&e); + if (r > 0) { + *ret = e; + return 0; + } + + k = is_dir(def, true); + if (k == 0) + k = -ENOTDIR; + if (k < 0) + return r < 0 ? r : k; + + *ret = def; return 0; } +int var_tmp_dir(const char **ret) { + + /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus + * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is + * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR, + * making it a variable that overrides all temporary file storage locations. */ + + return tmp_dir_internal("/var/tmp", ret); +} + +int tmp_dir(const char **ret) { + + /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually + * backed by an in-memory file system: /tmp. */ + + return tmp_dir_internal("/tmp", ret); +} + int inotify_add_watch_fd(int fd, int what, uint32_t mask) { char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; int r; diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 075e5942b1..2c3b9a1c74 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -61,7 +61,8 @@ int mkfifo_atomic(const char *path, mode_t mode); int get_files_in_directory(const char *path, char ***list); -int var_tmp(char **ret); +int tmp_dir(const char **ret); +int var_tmp_dir(const char **ret); #define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 27b1e0fb3f..bbf8793e57 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -30,6 +30,7 @@ #include "compress.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "journal-internal.h" #include "log.h" #include "macro.h" @@ -609,7 +610,13 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { char *temp = NULL; if (fd < 0) { - temp = strdup("/var/tmp/coredump-XXXXXX"); + const char *vt; + + r = var_tmp_dir(&vt); + if (r < 0) + return log_error_errno(r, "Failed to acquire temporary directory path: %m"); + + temp = strjoin(vt, "/coredump-XXXXXX", NULL); if (!temp) return log_oom(); diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index f61f158e8a..4105abfccc 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -826,7 +826,7 @@ int journal_file_verify( int data_fd = -1, entry_fd = -1, entry_array_fd = -1; unsigned i; bool found_last = false; - _cleanup_free_ char *tmp_dir = NULL; + const char *tmp_dir = NULL; #ifdef HAVE_GCRYPT uint64_t last_tag = 0; @@ -846,7 +846,7 @@ int journal_file_verify( } else if (f->seal) return -ENOKEY; - r = var_tmp(&tmp_dir); + r = var_tmp_dir(&tmp_dir); if (r < 0) { log_error_errno(r, "Failed to determine temporary directory: %m"); goto fail; diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 1923e8b971..5e2462cba2 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -954,7 +954,7 @@ static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_err /* Create a temporary file we can dump information about deleted images into. We use a temporary file for this * instead of a pipe or so, since this might grow quit large in theory and we don't want to process this * continuously */ - result_fd = open_tmpfile_unlinkable("/tmp/", O_RDWR|O_CLOEXEC); + result_fd = open_tmpfile_unlinkable(NULL, O_RDWR|O_CLOEXEC); if (result_fd < 0) return -errno; diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index e0c040f39b..93eec3ef9c 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -83,47 +83,35 @@ static void test_get_files_in_directory(void) { } static void test_var_tmp(void) { - char *tmp_dir = NULL; - char *tmpdir_backup = NULL; - const char *default_var_tmp = NULL; - const char *var_name; - bool do_overwrite = true; - - default_var_tmp = "/var/tmp"; - var_name = "TMPDIR"; - - if (getenv(var_name) != NULL) { - tmpdir_backup = strdup(getenv(var_name)); - assert_se(tmpdir_backup != NULL); - } - - unsetenv(var_name); + _cleanup_free_ char *tmpdir_backup = NULL; + const char *tmp_dir = NULL, *t; - var_tmp(&tmp_dir); - assert_se(!strcmp(tmp_dir, default_var_tmp)); - - free(tmp_dir); + t = getenv("TMPDIR"); + if (t) { + tmpdir_backup = strdup(t); + assert_se(tmpdir_backup); + } - setenv(var_name, "/tmp", do_overwrite); - assert_se(!strcmp(getenv(var_name), "/tmp")); + assert(unsetenv("TMPDIR") >= 0); - var_tmp(&tmp_dir); - assert_se(!strcmp(tmp_dir, "/tmp")); + assert_se(var_tmp_dir(&tmp_dir) >= 0); + assert_se(streq(tmp_dir, "/var/tmp")); - free(tmp_dir); + assert_se(setenv("TMPDIR", "/tmp", true) >= 0); + assert_se(streq(getenv("TMPDIR"), "/tmp")); - setenv(var_name, "/88_does_not_exist_88", do_overwrite); - assert_se(!strcmp(getenv(var_name), "/88_does_not_exist_88")); + assert_se(var_tmp_dir(&tmp_dir) >= 0); + assert_se(streq(tmp_dir, "/tmp")); - var_tmp(&tmp_dir); - assert_se(!strcmp(tmp_dir, default_var_tmp)); + assert_se(setenv("TMPDIR", "/88_does_not_exist_88", true) >= 0); + assert_se(streq(getenv("TMPDIR"), "/88_does_not_exist_88")); - free(tmp_dir); + assert_se(var_tmp_dir(&tmp_dir) >= 0); + assert_se(streq(tmp_dir, "/var/tmp")); - if (tmpdir_backup != NULL) { - setenv(var_name, tmpdir_backup, do_overwrite); - assert_se(!strcmp(getenv(var_name), tmpdir_backup)); - free(tmpdir_backup); + if (tmpdir_backup) { + assert_se(setenv("TMPDIR", tmpdir_backup, true) >= 0); + assert_se(streq(getenv("TMPDIR"), tmpdir_backup)); } } -- cgit v1.2.3-54-g00ecf From c39f1ce24ddb1aa683991c5099dcc2afbfcbc57c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 26 Jul 2016 17:40:35 +0200 Subject: core: turn various execution flags into a proper flags parameter The ExecParameters structure contains a number of bit-flags, that were so far exposed as bool:1, change this to a proper, single binary bit flag field. This makes things a bit more expressive, and is helpful as we add more flags, since these booleans are passed around in various callers, for example service_spawn(), whose signature can be made much shorter now. Not all bit booleans from ExecParameters are moved into the flags field for now, but this can be added later. --- src/core/execute.c | 21 ++++++++----- src/core/execute.h | 17 ++++++++--- src/core/mount.c | 12 +++----- src/core/service.c | 90 +++++++++++++++++++----------------------------------- src/core/socket.c | 12 +++----- src/core/swap.c | 12 +++----- 6 files changed, 72 insertions(+), 92 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 77a75245cb..bc0fd27402 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -427,7 +427,7 @@ static int setup_input( return STDIN_FILENO; } - i = fixup_input(context->std_input, socket_fd, params->apply_tty_stdin); + i = fixup_input(context->std_input, socket_fd, params->flags & EXEC_APPLY_TTY_STDIN); switch (i) { @@ -502,7 +502,7 @@ static int setup_output( return STDERR_FILENO; } - i = fixup_input(context->std_input, socket_fd, params->apply_tty_stdin); + i = fixup_input(context->std_input, socket_fd, params->flags & EXEC_APPLY_TTY_STDIN); o = fixup_output(context->std_output, socket_fd); if (fileno == STDERR_FILENO) { @@ -1675,7 +1675,7 @@ static int exec_child( exec_context_tty_reset(context, params); - if (params->confirm_spawn) { + if (params->flags & EXEC_CONFIRM_SPAWN) { char response; r = ask_for_confirmation(&response, argv); @@ -1940,7 +1940,7 @@ static int exec_child( umask(context->umask); - if (params->apply_permissions && !command->privileged) { + if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { r = enforce_groups(context, username, gid); if (r < 0) { *exit_status = EXIT_GROUP; @@ -2010,7 +2010,7 @@ static int exec_child( } r = setup_namespace( - params->apply_chroot ? context->root_directory : NULL, + (params->flags & EXEC_APPLY_CHROOT) ? context->root_directory : NULL, context->read_write_paths, context->read_only_paths, context->inaccessible_paths, @@ -2041,7 +2041,7 @@ static int exec_child( else wd = "/"; - if (params->apply_chroot) { + if (params->flags & EXEC_APPLY_CHROOT) { if (!needs_mount_namespace && context->root_directory) if (chroot(context->root_directory) < 0) { *exit_status = EXIT_CHROOT; @@ -2065,7 +2065,12 @@ static int exec_child( } #ifdef HAVE_SELINUX - if (params->apply_permissions && mac_selinux_use() && params->selinux_context_net && socket_fd >= 0 && !command->privileged) { + if ((params->flags & EXEC_APPLY_PERMISSIONS) && + mac_selinux_use() && + params->selinux_context_net && + socket_fd >= 0 && + !command->privileged) { + r = mac_selinux_get_child_mls_label(socket_fd, command->path, context->selinux_context, &mac_selinux_context_net); if (r < 0) { *exit_status = EXIT_SELINUX_CONTEXT; @@ -2090,7 +2095,7 @@ static int exec_child( return r; } - if (params->apply_permissions && !command->privileged) { + if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { bool use_address_families = context->address_families_whitelist || !set_isempty(context->address_families); diff --git a/src/core/execute.h b/src/core/execute.h index 48cc18fbb3..77418ea2ad 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -208,6 +208,17 @@ struct ExecContext { bool no_new_privileges_set:1; }; +typedef enum ExecFlags { + EXEC_CONFIRM_SPAWN = 1U << 0, + EXEC_APPLY_PERMISSIONS = 1U << 1, + EXEC_APPLY_CHROOT = 1U << 2, + EXEC_APPLY_TTY_STDIN = 1U << 3, + + /* The following are not usec by execute.c, but by consumers internally */ + EXEC_PASS_FDS = 1U << 4, + EXEC_IS_CONTROL = 1U << 5, +} ExecFlags; + struct ExecParameters { char **argv; char **environment; @@ -216,11 +227,7 @@ struct ExecParameters { char **fd_names; unsigned n_fds; - bool apply_permissions:1; - bool apply_chroot:1; - bool apply_tty_stdin:1; - - bool confirm_spawn:1; + ExecFlags flags; bool selinux_context_net:1; bool cgroup_delegate:1; diff --git a/src/core/mount.c b/src/core/mount.c index afb20af9e2..3f6ac7fcf9 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -701,12 +701,10 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { pid_t pid; int r; ExecParameters exec_params = { - .apply_permissions = true, - .apply_chroot = true, - .apply_tty_stdin = true, - .stdin_fd = -1, - .stdout_fd = -1, - .stderr_fd = -1, + .flags = EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + .stdin_fd = -1, + .stdout_fd = -1, + .stderr_fd = -1, }; assert(m); @@ -732,7 +730,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { return r; exec_params.environment = UNIT(m)->manager->environment; - exec_params.confirm_spawn = UNIT(m)->manager->confirm_spawn; + exec_params.flags |= UNIT(m)->manager->confirm_spawn ? EXEC_CONFIRM_SPAWN : 0; exec_params.cgroup_supported = UNIT(m)->manager->cgroup_supported; exec_params.cgroup_path = UNIT(m)->cgroup_path; exec_params.cgroup_delegate = m->cgroup_context.delegate; diff --git a/src/core/service.c b/src/core/service.c index eb125cb999..b4db7d17ed 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1152,11 +1152,7 @@ static int service_spawn( Service *s, ExecCommand *c, usec_t timeout, - bool pass_fds, - bool apply_permissions, - bool apply_chroot, - bool apply_tty_stdin, - bool is_control, + ExecFlags flags, pid_t *_pid) { _cleanup_strv_free_ char **argv = NULL, **final_env = NULL, **our_env = NULL, **fd_names = NULL; @@ -1166,12 +1162,10 @@ static int service_spawn( pid_t pid; ExecParameters exec_params = { - .apply_permissions = apply_permissions, - .apply_chroot = apply_chroot, - .apply_tty_stdin = apply_tty_stdin, - .stdin_fd = -1, - .stdout_fd = -1, - .stderr_fd = -1, + .flags = flags, + .stdin_fd = -1, + .stdout_fd = -1, + .stderr_fd = -1, }; int r; @@ -1194,7 +1188,7 @@ static int service_spawn( if (r < 0) return r; - if (pass_fds || + if ((flags & EXEC_PASS_FDS) || s->exec_context.std_input == EXEC_INPUT_SOCKET || s->exec_context.std_output == EXEC_OUTPUT_SOCKET || s->exec_context.std_error == EXEC_OUTPUT_SOCKET) { @@ -1218,7 +1212,7 @@ static int service_spawn( if (!our_env) return -ENOMEM; - if (is_control ? s->notify_access == NOTIFY_ALL : s->notify_access != NOTIFY_NONE) + if ((flags & EXEC_IS_CONTROL) ? s->notify_access == NOTIFY_ALL : s->notify_access != NOTIFY_NONE) if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", UNIT(s)->manager->notify_socket) < 0) return -ENOMEM; @@ -1226,7 +1220,7 @@ static int service_spawn( if (asprintf(our_env + n_env++, "MAINPID="PID_FMT, s->main_pid) < 0) return -ENOMEM; - if (!MANAGER_IS_SYSTEM(UNIT(s)->manager)) + if (MANAGER_IS_USER(UNIT(s)->manager)) if (asprintf(our_env + n_env++, "MANAGERPID="PID_FMT, getpid()) < 0) return -ENOMEM; @@ -1266,18 +1260,18 @@ static int service_spawn( if (!final_env) return -ENOMEM; - if (is_control && UNIT(s)->cgroup_path) { + if ((flags & EXEC_IS_CONTROL) && UNIT(s)->cgroup_path) { path = strjoina(UNIT(s)->cgroup_path, "/control"); (void) cg_create(SYSTEMD_CGROUP_CONTROLLER, path); } else path = UNIT(s)->cgroup_path; exec_params.argv = argv; + exec_params.environment = final_env; exec_params.fds = fds; exec_params.fd_names = fd_names; exec_params.n_fds = n_fds; - exec_params.environment = final_env; - exec_params.confirm_spawn = UNIT(s)->manager->confirm_spawn; + exec_params.flags |= UNIT(s)->manager->confirm_spawn ? EXEC_CONFIRM_SPAWN : 0; exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported; exec_params.cgroup_path = path; exec_params.cgroup_delegate = s->cgroup_context.delegate; @@ -1465,11 +1459,9 @@ static void service_enter_stop_post(Service *s, ServiceResult f) { r = service_spawn(s, s->control_command, s->timeout_stop_usec, - false, - !s->permissions_start_only, - !s->root_directory_start_only, - true, - true, + (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS) | + (s->root_directory_start_only ? 0 : EXEC_APPLY_CHROOT) | + EXEC_APPLY_TTY_STDIN | EXEC_IS_CONTROL, &s->control_pid); if (r < 0) goto fail; @@ -1580,11 +1572,9 @@ static void service_enter_stop(Service *s, ServiceResult f) { r = service_spawn(s, s->control_command, s->timeout_stop_usec, - false, - !s->permissions_start_only, - !s->root_directory_start_only, - false, - true, + (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS) | + (s->root_directory_start_only ? 0 : EXEC_APPLY_CHROOT) | + EXEC_IS_CONTROL, &s->control_pid); if (r < 0) goto fail; @@ -1661,11 +1651,9 @@ static void service_enter_start_post(Service *s) { r = service_spawn(s, s->control_command, s->timeout_start_usec, - false, - !s->permissions_start_only, - !s->root_directory_start_only, - false, - true, + (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS)| + (s->root_directory_start_only ? 0 : EXEC_APPLY_CHROOT)| + EXEC_IS_CONTROL, &s->control_pid); if (r < 0) goto fail; @@ -1735,11 +1723,7 @@ static void service_enter_start(Service *s) { r = service_spawn(s, c, timeout, - true, - true, - true, - true, - false, + EXEC_PASS_FDS|EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, &pid); if (r < 0) goto fail; @@ -1798,11 +1782,9 @@ static void service_enter_start_pre(Service *s) { r = service_spawn(s, s->control_command, s->timeout_start_usec, - false, - !s->permissions_start_only, - !s->root_directory_start_only, - true, - true, + (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS) | + (s->root_directory_start_only ? 0: EXEC_APPLY_CHROOT) | + EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN, &s->control_pid); if (r < 0) goto fail; @@ -1877,11 +1859,9 @@ static void service_enter_reload(Service *s) { r = service_spawn(s, s->control_command, s->timeout_start_usec, - false, - !s->permissions_start_only, - !s->root_directory_start_only, - false, - true, + (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS) | + (s->root_directory_start_only ? 0 : EXEC_APPLY_CHROOT) | + EXEC_IS_CONTROL, &s->control_pid); if (r < 0) goto fail; @@ -1919,12 +1899,10 @@ static void service_run_next_control(Service *s) { r = service_spawn(s, s->control_command, timeout, - false, - !s->permissions_start_only, - !s->root_directory_start_only, - s->control_command_id == SERVICE_EXEC_START_PRE || - s->control_command_id == SERVICE_EXEC_STOP_POST, - true, + (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS) | + (s->root_directory_start_only ? 0 : EXEC_APPLY_CHROOT) | + (IN_SET(s->control_command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_STOP_POST) ? EXEC_APPLY_TTY_STDIN : 0)| + EXEC_IS_CONTROL, &s->control_pid); if (r < 0) goto fail; @@ -1962,11 +1940,7 @@ static void service_run_next_main(Service *s) { r = service_spawn(s, s->main_command, s->timeout_start_usec, - true, - true, - true, - true, - false, + EXEC_PASS_FDS|EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, &pid); if (r < 0) goto fail; diff --git a/src/core/socket.c b/src/core/socket.c index ff55885fb3..82363e2157 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1664,12 +1664,10 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { pid_t pid; int r; ExecParameters exec_params = { - .apply_permissions = true, - .apply_chroot = true, - .apply_tty_stdin = true, - .stdin_fd = -1, - .stdout_fd = -1, - .stderr_fd = -1, + .flags = EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + .stdin_fd = -1, + .stdout_fd = -1, + .stderr_fd = -1, }; assert(s); @@ -1700,7 +1698,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { exec_params.argv = argv; exec_params.environment = UNIT(s)->manager->environment; - exec_params.confirm_spawn = UNIT(s)->manager->confirm_spawn; + exec_params.flags |= UNIT(s)->manager->confirm_spawn ? EXEC_CONFIRM_SPAWN : 0; exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported; exec_params.cgroup_path = UNIT(s)->cgroup_path; exec_params.cgroup_delegate = s->cgroup_context.delegate; diff --git a/src/core/swap.c b/src/core/swap.c index 66a318d01f..0ba4c4d881 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -611,12 +611,10 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { pid_t pid; int r; ExecParameters exec_params = { - .apply_permissions = true, - .apply_chroot = true, - .apply_tty_stdin = true, - .stdin_fd = -1, - .stdout_fd = -1, - .stderr_fd = -1, + .flags = EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + .stdin_fd = -1, + .stdout_fd = -1, + .stderr_fd = -1, }; assert(s); @@ -642,7 +640,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { goto fail; exec_params.environment = UNIT(s)->manager->environment; - exec_params.confirm_spawn = UNIT(s)->manager->confirm_spawn; + exec_params.flags |= UNIT(s)->manager->confirm_spawn ? EXEC_CONFIRM_SPAWN : 0; exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported; exec_params.cgroup_path = UNIT(s)->cgroup_path; exec_params.cgroup_delegate = s->cgroup_context.delegate; -- cgit v1.2.3-54-g00ecf From 9c1a61adba1ed61a405bc30675f08b8442eefd70 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 26 Jul 2016 17:53:07 +0200 Subject: core: move masking of chroot/permission masking into service_spawn() Let's fix up the flags fields in service_spawn() rather than its callers, in order to simplify things a bit. --- src/core/execute.h | 2 +- src/core/service.c | 34 +++++++++++++++------------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/core/execute.h b/src/core/execute.h index 77418ea2ad..8d659ca178 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -214,7 +214,7 @@ typedef enum ExecFlags { EXEC_APPLY_CHROOT = 1U << 2, EXEC_APPLY_TTY_STDIN = 1U << 3, - /* The following are not usec by execute.c, but by consumers internally */ + /* The following are not used by execute.c, but by consumers internally */ EXEC_PASS_FDS = 1U << 4, EXEC_IS_CONTROL = 1U << 5, } ExecFlags; diff --git a/src/core/service.c b/src/core/service.c index b4db7d17ed..32b8e7d2c5 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1174,6 +1174,14 @@ static int service_spawn( assert(c); assert(_pid); + if (flags & EXEC_IS_CONTROL) { + /* If this is a control process, mask the permissions/chroot application if this is requested. */ + if (s->permissions_start_only) + exec_params.flags &= ~EXEC_APPLY_PERMISSIONS; + if (s->root_directory_start_only) + exec_params.flags &= ~EXEC_APPLY_CHROOT; + } + (void) unit_realize_cgroup(UNIT(s)); if (s->reset_cpu_usage) { (void) unit_reset_cpu_usage(UNIT(s)); @@ -1459,9 +1467,7 @@ static void service_enter_stop_post(Service *s, ServiceResult f) { r = service_spawn(s, s->control_command, s->timeout_stop_usec, - (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS) | - (s->root_directory_start_only ? 0 : EXEC_APPLY_CHROOT) | - EXEC_APPLY_TTY_STDIN | EXEC_IS_CONTROL, + EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_IS_CONTROL, &s->control_pid); if (r < 0) goto fail; @@ -1572,9 +1578,7 @@ static void service_enter_stop(Service *s, ServiceResult f) { r = service_spawn(s, s->control_command, s->timeout_stop_usec, - (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS) | - (s->root_directory_start_only ? 0 : EXEC_APPLY_CHROOT) | - EXEC_IS_CONTROL, + EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL, &s->control_pid); if (r < 0) goto fail; @@ -1651,9 +1655,7 @@ static void service_enter_start_post(Service *s) { r = service_spawn(s, s->control_command, s->timeout_start_usec, - (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS)| - (s->root_directory_start_only ? 0 : EXEC_APPLY_CHROOT)| - EXEC_IS_CONTROL, + EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL, &s->control_pid); if (r < 0) goto fail; @@ -1782,9 +1784,7 @@ static void service_enter_start_pre(Service *s) { r = service_spawn(s, s->control_command, s->timeout_start_usec, - (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS) | - (s->root_directory_start_only ? 0: EXEC_APPLY_CHROOT) | - EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN, + EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN, &s->control_pid); if (r < 0) goto fail; @@ -1859,9 +1859,7 @@ static void service_enter_reload(Service *s) { r = service_spawn(s, s->control_command, s->timeout_start_usec, - (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS) | - (s->root_directory_start_only ? 0 : EXEC_APPLY_CHROOT) | - EXEC_IS_CONTROL, + EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL, &s->control_pid); if (r < 0) goto fail; @@ -1899,10 +1897,8 @@ static void service_run_next_control(Service *s) { r = service_spawn(s, s->control_command, timeout, - (s->permissions_start_only ? 0 : EXEC_APPLY_PERMISSIONS) | - (s->root_directory_start_only ? 0 : EXEC_APPLY_CHROOT) | - (IN_SET(s->control_command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_STOP_POST) ? EXEC_APPLY_TTY_STDIN : 0)| - EXEC_IS_CONTROL, + EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL| + (IN_SET(s->control_command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_STOP_POST) ? EXEC_APPLY_TTY_STDIN : 0), &s->control_pid); if (r < 0) goto fail; -- cgit v1.2.3-54-g00ecf From af9d16e10a23899b821af19e54e339486a86bd82 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2016 11:50:37 +0200 Subject: core: use the correct APIs to determine whether a dual timestamp is initialized --- src/core/execute.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index bc0fd27402..9028139723 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2969,12 +2969,12 @@ void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) { "%sPID: "PID_FMT"\n", prefix, s->pid); - if (s->start_timestamp.realtime > 0) + if (dual_timestamp_is_set(&s->start_timestamp)) fprintf(f, "%sStart Timestamp: %s\n", prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime)); - if (s->exit_timestamp.realtime > 0) + if (dual_timestamp_is_set(&s->exit_timestamp)) fprintf(f, "%sExit Timestamp: %s\n" "%sExit Code: %s\n" -- cgit v1.2.3-54-g00ecf From ffff9abe1d4dc61d6f9a47ce0f3f85a3854373cf Mon Sep 17 00:00:00 2001 From: Tobias Jungel Date: Thu, 4 Aug 2016 17:11:13 +0200 Subject: networkd: apply bridge vlan configuration correct bridge vlan configuration was applied even if it wasn't configured. fixes #3876 --- src/network/networkd-brvlan.c | 20 ++++++++++++++++++++ src/network/networkd-brvlan.h | 1 + src/network/networkd-link.c | 3 ++- src/network/networkd-network-gperf.gperf | 2 +- src/network/networkd-network.h | 1 + 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-brvlan.c b/src/network/networkd-brvlan.c index 8bc330ebae..18ecd86858 100644 --- a/src/network/networkd-brvlan.c +++ b/src/network/networkd-brvlan.c @@ -257,6 +257,24 @@ static int parse_vid_range(const char *rvalue, uint16_t *vid, uint16_t *vid_end) return r; } +int config_parse_brvlan_pvid(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; + int r; + uint16_t pvid; + r = parse_vlanid(rvalue, &pvid); + if (r < 0) + return r; + + network->pvid = pvid; + network->use_br_vlan = true; + + return 0; +} + int config_parse_brvlan_vlan(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, @@ -288,6 +306,7 @@ int config_parse_brvlan_vlan(const char *unit, const char *filename, for (; vid <= vid_end; vid++) set_bit(vid, network->br_vid_bitmap); } + network->use_br_vlan = true; return 0; } @@ -325,5 +344,6 @@ int config_parse_brvlan_untagged(const char *unit, const char *filename, set_bit(vid, network->br_untagged_bitmap); } } + network->use_br_vlan = true; return 0; } diff --git a/src/network/networkd-brvlan.h b/src/network/networkd-brvlan.h index 6aa6883bfc..b37633f94f 100644 --- a/src/network/networkd-brvlan.h +++ b/src/network/networkd-brvlan.h @@ -25,5 +25,6 @@ typedef struct Link Link; int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap); +int config_parse_brvlan_pvid(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_brvlan_vlan(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_brvlan_untagged(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); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 3e10ab1e04..e1d07eb4b0 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2060,7 +2060,8 @@ static int link_joined(Link *link) { log_link_error_errno(link, r, "Could not set bridge message: %m"); } - if (link->network->bridge || streq_ptr("bridge", link->kind)) { + if (link->network->use_br_vlan && + (link->network->bridge || streq_ptr("bridge", link->kind))) { r = link_set_bridge_vlan(link); if (r < 0) log_link_error_errno(link, r, "Could not set bridge vlan: %m"); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 19adac66b8..b96f0b7210 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -115,7 +115,7 @@ Bridge.AllowPortToBeRoot, config_parse_bool, Bridge.UnicastFlood, config_parse_bool, 0, offsetof(Network, unicast_flood) BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0 BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0 -BridgeVLAN.PVID, config_parse_vlanid, 0, offsetof(Network, pvid) +BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0 BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0 BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0 /* backwards compatibility: do not add new entries to this section */ diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 7c0bdc1e4a..5460eb4d1c 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -151,6 +151,7 @@ struct Network { bool unicast_flood; unsigned cost; + bool use_br_vlan; uint16_t pvid; uint32_t br_vid_bitmap[BRIDGE_VLAN_BITMAP_LEN]; uint32_t br_untagged_bitmap[BRIDGE_VLAN_BITMAP_LEN]; -- cgit v1.2.3-54-g00ecf From c2d11a630287631d3b401a5cf300ea3655e21fd1 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Thu, 4 Aug 2016 13:52:02 -0700 Subject: fileio: fix read_full_stream() bugs (#3887) read_full_stream() _always_ allocated twice the memory needed, due to only breaking the realloc() && fread() loop when fread() returned 0, requiring another iteration and exponentially enlarged buffer just to discover the EOF condition. This also caused file sizes >2MiB && <= 4MiB to erroneously be treated as E2BIG, due to the inappropriately doubled buffer size exceeding 4*1024*1024. Also made the 4*1024*1024 magic number a READ_FULL_BYTES_MAX constant. --- src/basic/fileio.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index f183de4999..c18ac39e03 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -47,6 +47,8 @@ #include "umask-util.h" #include "utf8.h" +#define READ_FULL_BYTES_MAX (4U*1024U*1024U) + int write_string_stream(FILE *f, const char *line, bool enforce_newline) { assert(f); @@ -230,7 +232,7 @@ int read_full_stream(FILE *f, char **contents, size_t *size) { if (S_ISREG(st.st_mode)) { /* Safety check */ - if (st.st_size > 4*1024*1024) + if (st.st_size > READ_FULL_BYTES_MAX) return -E2BIG; /* Start with the right file size, but be prepared for @@ -245,26 +247,31 @@ int read_full_stream(FILE *f, char **contents, size_t *size) { char *t; size_t k; - t = realloc(buf, n+1); + t = realloc(buf, n + 1); if (!t) return -ENOMEM; buf = t; k = fread(buf + l, 1, n - l, f); + if (k > 0) + l += k; - if (k <= 0) { - if (ferror(f)) - return -errno; + if (ferror(f)) + return -errno; + if (feof(f)) break; - } - l += k; - n *= 2; + /* We aren't expecting fread() to return a short read outside + * of (error && eof), assert buffer is full and enlarge buffer. + */ + assert(l == n); /* Safety check */ - if (n > 4*1024*1024) + if (n >= READ_FULL_BYTES_MAX) return -E2BIG; + + n = MAX(n * 2, READ_FULL_BYTES_MAX); } buf[l] = 0; -- cgit v1.2.3-54-g00ecf From 13811bf909d99b24411d3d5fbea790c9f81d08b7 Mon Sep 17 00:00:00 2001 From: 0xAX <0xAX@users.noreply.github.com> Date: Thu, 4 Aug 2016 23:52:24 +0300 Subject: main: use pager for --dump-configuration-items (#3894) --- src/core/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/main.c b/src/core/main.c index 094bbef964..02324d325e 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1614,6 +1614,7 @@ int main(int argc, char *argv[]) { retval = version(); goto finish; } else if (arg_action == ACTION_DUMP_CONFIGURATION_ITEMS) { + pager_open(arg_no_pager, false); unit_dump_config_items(stdout); retval = EXIT_SUCCESS; goto finish; -- cgit v1.2.3-54-g00ecf From 136dc4c4350dfcb1d61ceaac982d0d0a8e6e3863 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2016 11:51:11 +0200 Subject: core: set $SERVICE_RESULT, $EXIT_CODE and $EXIT_STATUS in ExecStop=/ExecStopPost= commands This should simplify monitoring tools for services, by passing the most basic information about service result/exit information via environment variables, thus making it unnecessary to retrieve them explicitly via the bus. --- man/systemd.exec.xml | 37 +++++++++++++++++++++++++++++++++++++ man/systemd.service.xml | 8 +++++++- src/core/execute.h | 1 + src/core/service.c | 27 +++++++++++++++++++++++---- 4 files changed, 68 insertions(+), 5 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 58ba582911..0fc658f180 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1602,6 +1602,43 @@ functions) if their standard output or standard error output is connected to the journal anyway, thus enabling delivery of structured metadata along with logged messages. + + + $SERVICE_RESULT + + Only defined for the service unit type, this environment variable is passed to all + ExecStop= and ExecStopPost= processes, and encodes the service + "result". Currently, the following values are defined: timeout (in case of an operation + timeout), exit-code (if a service process exited with a non-zero exit code; see + $EXIT_STATUS below for the actual exit status returned), signal (if a + service process was terminated abnormally by a signal; see $EXIT_STATUS below for the actual + signal used for the termination), core-dump (if a service process terminated abnormally and + dumped core), watchdog (if the watchdog keep-alive ping was enabled for the service but it + missed the deadline), or resources (a catch-all condition in case a system operation + failed). + + This environment variable is useful to monitor failure or successful termination of a service. Even + though this variable is available in both ExecStop= and ExecStopPost=, it + is usually a better choice to place monitoring tools in the latter, as the former is only invoked for services + that managed to start up correctly, and the latter covers both services that failed during their start-up and + those which failed during their runtime. + + + + $EXIT_CODE + $EXIT_STATUS + + Only defined for the service unit type, these environment variables are passed to all + ExecStop=, ExecStopPost= processes and contain exit status/code + information of the main process of the service. For the precise definition of the exit code and status, see + wait2. $EXIT_CODE + is one of exited, killed, + dumped. $EXIT_STATUS contains the numeric exit code formatted as string + if $EXIT_CODE is exited, and the signal name in all other cases. Note + that these environment variables are only set if the service manager succeeded to start and identify the main + process of the service. + + Additional variables may be configured by the following diff --git a/man/systemd.service.xml b/man/systemd.service.xml index 875d368fcf..e82edbe93e 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -429,7 +429,13 @@ service failed to start up correctly. Commands configured with this setting need to be able to operate even if the service failed starting up half-way and left incompletely initialized data around. As the service's processes have been terminated already when the commands specified with this setting are executed they should - not attempt to communicate with them. + not attempt to communicate with them. + + Note that all commands that are configured with this setting are invoked with the result code of the + service, as well as the main process' exit code and status, set in the $SERVICE_RESULT, + $EXIT_CODE and $EXIT_STATUS environment variables, see + systemd.exec5 for + details. diff --git a/src/core/execute.h b/src/core/execute.h index 8d659ca178..2b4238ed7e 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -217,6 +217,7 @@ typedef enum ExecFlags { /* The following are not used by execute.c, but by consumers internally */ EXEC_PASS_FDS = 1U << 4, EXEC_IS_CONTROL = 1U << 5, + EXEC_SETENV_RESULT = 1U << 6, } ExecFlags; struct ExecParameters { diff --git a/src/core/service.c b/src/core/service.c index 32b8e7d2c5..0cbea52276 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1216,7 +1216,7 @@ static int service_spawn( if (r < 0) return r; - our_env = new0(char*, 6); + our_env = new0(char*, 9); if (!our_env) return -ENOMEM; @@ -1264,6 +1264,24 @@ static int service_spawn( } } + if (flags & EXEC_SETENV_RESULT) { + if (asprintf(our_env + n_env++, "SERVICE_RESULT=%s", service_result_to_string(s->result)) < 0) + return -ENOMEM; + + if (s->main_exec_status.pid > 0 && + dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) { + if (asprintf(our_env + n_env++, "EXIT_CODE=%s", sigchld_code_to_string(s->main_exec_status.code)) < 0) + return -ENOMEM; + + if (s->main_exec_status.code == CLD_EXITED) + r = asprintf(our_env + n_env++, "EXIT_STATUS=%i", s->main_exec_status.status); + else + r = asprintf(our_env + n_env++, "EXIT_STATUS=%s", signal_to_string(s->main_exec_status.status)); + if (r < 0) + return -ENOMEM; + } + } + final_env = strv_env_merge(2, UNIT(s)->manager->environment, our_env, NULL); if (!final_env) return -ENOMEM; @@ -1467,7 +1485,7 @@ static void service_enter_stop_post(Service *s, ServiceResult f) { r = service_spawn(s, s->control_command, s->timeout_stop_usec, - EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_IS_CONTROL, + EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_IS_CONTROL|EXEC_SETENV_RESULT, &s->control_pid); if (r < 0) goto fail; @@ -1578,7 +1596,7 @@ static void service_enter_stop(Service *s, ServiceResult f) { r = service_spawn(s, s->control_command, s->timeout_stop_usec, - EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL, + EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_SETENV_RESULT, &s->control_pid); if (r < 0) goto fail; @@ -1898,7 +1916,8 @@ static void service_run_next_control(Service *s) { s->control_command, timeout, EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL| - (IN_SET(s->control_command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_STOP_POST) ? EXEC_APPLY_TTY_STDIN : 0), + (IN_SET(s->control_command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_STOP_POST) ? EXEC_APPLY_TTY_STDIN : 0)| + (IN_SET(s->control_command_id, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST) ? EXEC_SETENV_RESULT : 0), &s->control_pid); if (r < 0) goto fail; -- cgit v1.2.3-54-g00ecf From 2129011e92feee93383b450bb2d20008786b90a0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2016 13:14:01 +0200 Subject: nss-systemd: resolve root/nobody statically Let's extend nss-systemd to also synthesize user/group entries for the UIDs/GIDs 0 and 65534 which have special kernel meaning. Given that nss-systemd is listed in /etc/nsswitch.conf only very late any explicit listing in /etc/passwd or /etc/group takes precedence. This functionality is useful in minimal container-like setups that lack /etc/passwd files (or only have incompletely populated ones). --- configure.ac | 22 ++++++++- man/nss-systemd.xml | 4 ++ src/nss-systemd/nss-systemd.c | 101 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index a86deca471..4d1c96606f 100644 --- a/configure.ac +++ b/configure.ac @@ -556,12 +556,30 @@ AC_SUBST(CERTIFICATEROOT) AC_ARG_WITH([support-url], AS_HELP_STRING([--with-support-url=URL], - [Specify the supoport URL to show in catalog entries included in systemd]), + [Specify the support URL to show in catalog entries included in systemd]), [SUPPORT_URL="$withval"], [SUPPORT_URL=http://lists.freedesktop.org/mailman/listinfo/systemd-devel]) AC_SUBST(SUPPORT_URL) +AC_ARG_WITH([nobody-user], + AS_HELP_STRING([--with-nobody-user=NAME], + [Specify the name of the nobody user (the one with UID 65534)]), + [NOBODY_USER_NAME="$withval"], + [NOBODY_USER_NAME=nobody]) + +AC_SUBST(NOBODY_USER_NAME) +AC_DEFINE_UNQUOTED(NOBODY_USER_NAME, ["$NOBODY_USER_NAME"], [The name of the nobody user (the one with UID 65534)]) + +AC_ARG_WITH([nobody-group], + AS_HELP_STRING([--with-nobody-group=NAME], + [Specify the name of the nobody group (the one with GID 65534)]), + [NOBODY_GROUP_NAME="$withval"], + [NOBODY_GROUP_NAME=nobody]) + +AC_SUBST(NOBODY_GROUP_NAME) +AC_DEFINE_UNQUOTED(NOBODY_GROUP_NAME, ["$NOBODY_GROUP_NAME"], [The name of the nobody group (the one with GID 65534)]) + # ------------------------------------------------------------------------------ have_xz=no AC_ARG_ENABLE(xz, AS_HELP_STRING([--disable-xz], [Disable optional XZ support])) @@ -1677,6 +1695,8 @@ AC_MSG_RESULT([ Maximum System GID: ${SYSTEM_GID_MAX} Certificate root: ${CERTIFICATEROOT} Support URL: ${SUPPORT_URL} + Nobody User Name: ${NOBODY_USER_NAME} + Nobody Group Name: ${NOBODY_GROUP_NAME} CFLAGS: ${OUR_CFLAGS} ${CFLAGS} CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS} diff --git a/man/nss-systemd.xml b/man/nss-systemd.xml index 4228372e51..56d26e7d1f 100644 --- a/man/nss-systemd.xml +++ b/man/nss-systemd.xml @@ -61,6 +61,10 @@ systemd.exec5 for details on this option. + This module also ensures that the root and nobody users and groups (i.e. the users/groups with the UIDs/GIDs + 0 and 65534) remain resolvable at all times, even if they aren't listed in /etc/passwd or + /etc/group, or if these files are missing. + To activate the NSS module, add systemd to the lines starting with passwd: and group: in /etc/nsswitch.conf. diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index e7a4393bb0..7078c0c50c 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -26,9 +26,52 @@ #include "macro.h" #include "nss-util.h" #include "signal-util.h" +#include "string-util.h" #include "user-util.h" #include "util.h" +#ifndef NOBODY_USER_NAME +#define NOBODY_USER_NAME "nobody" +#endif + +#ifndef NOBODY_GROUP_NAME +#define NOBODY_GROUP_NAME "nobody" +#endif + +static const struct passwd root_passwd = { + .pw_name = (char*) "root", + .pw_passwd = (char*) "x", /* see shadow file */ + .pw_uid = 0, + .pw_gid = 0, + .pw_gecos = (char*) "Super User", + .pw_dir = (char*) "/root", + .pw_shell = (char*) "/bin/sh", +}; + +static const struct passwd nobody_passwd = { + .pw_name = (char*) NOBODY_USER_NAME, + .pw_passwd = (char*) "*", /* locked */ + .pw_uid = 65534, + .pw_gid = 65534, + .pw_gecos = (char*) "User Nobody", + .pw_dir = (char*) "/", + .pw_shell = (char*) "/sbin/nologin", +}; + +static const struct group root_group = { + .gr_name = (char*) "root", + .gr_gid = 0, + .gr_passwd = (char*) "x", /* see shadow file */ + .gr_mem = (char*[]) { NULL }, +}; + +static const struct group nobody_group = { + .gr_name = (char*) NOBODY_GROUP_NAME, + .gr_gid = 65534, + .gr_passwd = (char*) "*", /* locked */ + .gr_mem = (char*[]) { NULL }, +}; + NSS_GETPW_PROTOTYPES(systemd); NSS_GETGR_PROTOTYPES(systemd); @@ -50,6 +93,23 @@ enum nss_status _nss_systemd_getpwnam_r( assert(name); assert(pwd); + if (!valid_user_group_name(name)) { + r = -EINVAL; + goto fail; + } + + /* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */ + if (streq(name, root_passwd.pw_name)) { + *pwd = root_passwd; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + if (streq(name, nobody_passwd.pw_name)) { + *pwd = nobody_passwd; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + /* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */ if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) goto not_found; @@ -126,6 +186,18 @@ enum nss_status _nss_systemd_getpwuid_r( goto fail; } + /* Synthesize data for the root user and for nobody in case they are missing from /etc/passwd */ + if (uid == root_passwd.pw_uid) { + *pwd = root_passwd; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + if (uid == nobody_passwd.pw_uid) { + *pwd = nobody_passwd; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + if (uid <= SYSTEM_UID_MAX) goto not_found; @@ -202,6 +274,23 @@ enum nss_status _nss_systemd_getgrnam_r( assert(name); assert(gr); + if (!valid_user_group_name(name)) { + r = -EINVAL; + goto fail; + } + + /* Synthesize records for root and nobody, in case they are missing form /etc/group */ + if (streq(name, root_group.gr_name)) { + *gr = root_group; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + if (streq(name, nobody_group.gr_name)) { + *gr = nobody_group; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) goto not_found; @@ -275,6 +364,18 @@ enum nss_status _nss_systemd_getgrgid_r( goto fail; } + /* Synthesize records for root and nobody, in case they are missing from /etc/group */ + if (gid == root_group.gr_gid) { + *gr = root_group; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + if (gid == nobody_group.gr_gid) { + *gr = nobody_group; + *errnop = 0; + return NSS_STATUS_SUCCESS; + } + if (gid <= SYSTEM_GID_MAX) goto not_found; -- cgit v1.2.3-54-g00ecf From d47f681b285b1dfb7ce68200205bfe8b835657a2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 27 Jul 2016 13:30:58 +0200 Subject: update TODO --- TODO | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/TODO b/TODO index bb36522bf9..723292cde0 100644 --- a/TODO +++ b/TODO @@ -35,27 +35,17 @@ Features: * RemoveIPC= in unit files for removing POSIX/SysV IPC objects -* Set SERVICE_RESULT= as env var while running ExecStop= - * Introduce ProtectSystem=strict for making the entire OS hierarchy read-only except for a select few * nspawn: start UID allocation loop from hash of container name -* in the DynamicUser=1 nss module, also map "nobody" and "root" statically - -* pid1: log about all processes we kill with with SIGKILL or in abandoned scopes, as this should normally not happen - * nspawn: support that /proc, /sys/, /dev are pre-mounted -* nspawn: mount esp, so that bootctl can work - * define gpt header bits to select volatility mode * nspawn: mount loopback filesystems with "discard" -* Make TasksMax= take percentages, taken relative to the pids_max sysctl and pids.max cgroup limit - * ProtectKernelLogs= (drops CAP_SYSLOG, add seccomp for syslog() syscall, and DeviceAllow to /dev/kmsg) in service files * ProtectClock= (drops CAP_SYS_TIMES, adds seecomp filters for settimeofday, adjtimex), sets DeviceAllow o /dev/rtc -- cgit v1.2.3-54-g00ecf From a0fef983ab200db4e2b151beb06c9cf8fef6c5ab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 4 Aug 2016 21:14:27 +0200 Subject: core: remember first unit failure, not last unit failure Previously, the result value of a unit was overriden with each failure that took place, so that the result always reported the last failure that took place. With this commit this is changed, so that the first failure taking place is stored instead. This should normally not matter much as multiple failures are sufficiently uncommon. However, it improves one behaviour: if we send SIGABRT to a service due to a watchdog timeout, then this currently would be reported as "coredump" failure, rather than the "watchodg" failure it really is. Hence, in order to report information about the type of the failure, and not about the effect of it, let's change this from all unit type to store the first, not the last failure. This addresses the issue pointed out here: https://github.com/systemd/systemd/pull/3818#discussion_r73433520 --- src/core/automount.c | 2 +- src/core/busname.c | 6 +++--- src/core/mount.c | 8 ++++---- src/core/path.c | 2 +- src/core/scope.c | 4 ++-- src/core/service.c | 14 +++++++------- src/core/socket.c | 10 +++++----- src/core/swap.c | 8 ++++---- src/core/timer.c | 2 +- 9 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/core/automount.c b/src/core/automount.c index 20a73c76f9..00295cf769 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -301,7 +301,7 @@ static void automount_dump(Unit *u, FILE *f, const char *prefix) { static void automount_enter_dead(Automount *a, AutomountResult f) { assert(a); - if (f != AUTOMOUNT_SUCCESS) + if (a->result == AUTOMOUNT_SUCCESS) a->result = f; automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD); diff --git a/src/core/busname.c b/src/core/busname.c index 730be2ee14..7952cd31aa 100644 --- a/src/core/busname.c +++ b/src/core/busname.c @@ -442,7 +442,7 @@ fail: static void busname_enter_dead(BusName *n, BusNameResult f) { assert(n); - if (f != BUSNAME_SUCCESS) + if (n->result == BUSNAME_SUCCESS) n->result = f; busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD); @@ -454,7 +454,7 @@ static void busname_enter_signal(BusName *n, BusNameState state, BusNameResult f assert(n); - if (f != BUSNAME_SUCCESS) + if (n->result == BUSNAME_SUCCESS) n->result = f; kill_context_init(&kill_context); @@ -882,7 +882,7 @@ static void busname_sigchld_event(Unit *u, pid_t pid, int code, int status) { log_unit_full(u, f == BUSNAME_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0, "Control process exited, code=%s status=%i", sigchld_code_to_string(code), status); - if (f != BUSNAME_SUCCESS) + if (n->result == BUSNAME_SUCCESS) n->result = f; switch (n->state) { diff --git a/src/core/mount.c b/src/core/mount.c index 3f6ac7fcf9..f3ccf6d48a 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -759,7 +759,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { static void mount_enter_dead(Mount *m, MountResult f) { assert(m); - if (f != MOUNT_SUCCESS) + if (m->result == MOUNT_SUCCESS) m->result = f; mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD); @@ -775,7 +775,7 @@ static void mount_enter_dead(Mount *m, MountResult f) { static void mount_enter_mounted(Mount *m, MountResult f) { assert(m); - if (f != MOUNT_SUCCESS) + if (m->result == MOUNT_SUCCESS) m->result = f; mount_set_state(m, MOUNT_MOUNTED); @@ -786,7 +786,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) { assert(m); - if (f != MOUNT_SUCCESS) + if (m->result == MOUNT_SUCCESS) m->result = f; r = unit_kill_context( @@ -1158,7 +1158,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { else assert_not_reached("Unknown code"); - if (f != MOUNT_SUCCESS) + if (m->result == MOUNT_SUCCESS) m->result = f; if (m->control_command) { diff --git a/src/core/path.c b/src/core/path.c index 0dd0d375d8..10f9b06974 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -454,7 +454,7 @@ static int path_coldplug(Unit *u) { static void path_enter_dead(Path *p, PathResult f) { assert(p); - if (f != PATH_SUCCESS) + if (p->result == PATH_SUCCESS) p->result = f; path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD); diff --git a/src/core/scope.c b/src/core/scope.c index b45e238974..b278aed3d6 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -221,7 +221,7 @@ static void scope_dump(Unit *u, FILE *f, const char *prefix) { static void scope_enter_dead(Scope *s, ScopeResult f) { assert(s); - if (f != SCOPE_SUCCESS) + if (s->result == SCOPE_SUCCESS) s->result = f; scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD); @@ -233,7 +233,7 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) { assert(s); - if (f != SCOPE_SUCCESS) + if (s->result == SCOPE_SUCCESS) s->result = f; unit_watch_all_pids(UNIT(s)); diff --git a/src/core/service.c b/src/core/service.c index 0cbea52276..a6793b813b 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1423,7 +1423,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) int r; assert(s); - if (f != SERVICE_SUCCESS) + if (s->result == SERVICE_SUCCESS) s->result = f; service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD); @@ -1472,7 +1472,7 @@ static void service_enter_stop_post(Service *s, ServiceResult f) { int r; assert(s); - if (f != SERVICE_SUCCESS) + if (s->result == SERVICE_SUCCESS) s->result = f; service_unwatch_control_pid(s); @@ -1525,7 +1525,7 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f assert(s); - if (f != SERVICE_SUCCESS) + if (s->result == SERVICE_SUCCESS) s->result = f; unit_watch_all_pids(UNIT(s)); @@ -1583,7 +1583,7 @@ static void service_enter_stop(Service *s, ServiceResult f) { assert(s); - if (f != SERVICE_SUCCESS) + if (s->result == SERVICE_SUCCESS) s->result = f; service_unwatch_control_pid(s); @@ -1635,7 +1635,7 @@ static bool service_good(Service *s) { static void service_enter_running(Service *s, ServiceResult f) { assert(s); - if (f != SERVICE_SUCCESS) + if (s->result == SERVICE_SUCCESS) s->result = f; service_unwatch_control_pid(s); @@ -2609,7 +2609,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { "EXIT_STATUS=%i", status, NULL); - if (f != SERVICE_SUCCESS) + if (s->result == SERVICE_SUCCESS) s->result = f; if (s->main_command && @@ -2690,7 +2690,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { "Control process exited, code=%s status=%i", sigchld_code_to_string(code), status); - if (f != SERVICE_SUCCESS) + if (s->result == SERVICE_SUCCESS) s->result = f; /* Immediately get rid of the cgroup, so that the diff --git a/src/core/socket.c b/src/core/socket.c index 82363e2157..c919e89b7d 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1810,7 +1810,7 @@ fail: static void socket_enter_dead(Socket *s, SocketResult f) { assert(s); - if (f != SOCKET_SUCCESS) + if (s->result == SOCKET_SUCCESS) s->result = f; socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD); @@ -1829,7 +1829,7 @@ static void socket_enter_stop_post(Socket *s, SocketResult f) { int r; assert(s); - if (f != SOCKET_SUCCESS) + if (s->result == SOCKET_SUCCESS) s->result = f; socket_unwatch_control_pid(s); @@ -1857,7 +1857,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) { assert(s); - if (f != SOCKET_SUCCESS) + if (s->result == SOCKET_SUCCESS) s->result = f; r = unit_kill_context( @@ -1901,7 +1901,7 @@ static void socket_enter_stop_pre(Socket *s, SocketResult f) { int r; assert(s); - if (f != SOCKET_SUCCESS) + if (s->result == SOCKET_SUCCESS) s->result = f; socket_unwatch_control_pid(s); @@ -2822,7 +2822,7 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) { "Control process exited, code=%s status=%i", sigchld_code_to_string(code), status); - if (f != SOCKET_SUCCESS) + if (s->result == SOCKET_SUCCESS) s->result = f; if (s->control_command && diff --git a/src/core/swap.c b/src/core/swap.c index 0ba4c4d881..2c802da3b5 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -673,7 +673,7 @@ fail: static void swap_enter_dead(Swap *s, SwapResult f) { assert(s); - if (f != SWAP_SUCCESS) + if (s->result == SWAP_SUCCESS) s->result = f; swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD); @@ -689,7 +689,7 @@ static void swap_enter_dead(Swap *s, SwapResult f) { static void swap_enter_active(Swap *s, SwapResult f) { assert(s); - if (f != SWAP_SUCCESS) + if (s->result == SWAP_SUCCESS) s->result = f; swap_set_state(s, SWAP_ACTIVE); @@ -700,7 +700,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) { assert(s); - if (f != SWAP_SUCCESS) + if (s->result == SWAP_SUCCESS) s->result = f; r = unit_kill_context( @@ -997,7 +997,7 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) { else assert_not_reached("Unknown code"); - if (f != SWAP_SUCCESS) + if (s->result == SWAP_SUCCESS) s->result = f; if (s->control_command) { diff --git a/src/core/timer.c b/src/core/timer.c index 3206296f09..e2b43f02f8 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -291,7 +291,7 @@ static int timer_coldplug(Unit *u) { static void timer_enter_dead(Timer *t, TimerResult f) { assert(t); - if (f != TIMER_SUCCESS) + if (t->result == TIMER_SUCCESS) t->result = f; timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD); -- cgit v1.2.3-54-g00ecf From b08af3b12706f352f651e70e117f6d6dcf11a911 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 4 Aug 2016 22:11:29 +0200 Subject: core: only set the watchdog variables in ExecStart= lines --- src/core/execute.c | 2 +- src/core/execute.h | 1 + src/core/service.c | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 9028139723..7aafb1b058 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1425,7 +1425,7 @@ static int build_environment( our_env[n_env++] = x; } - if (p->watchdog_usec > 0) { + if ((p->flags & EXEC_SET_WATCHDOG) && p->watchdog_usec > 0) { if (asprintf(&x, "WATCHDOG_PID="PID_FMT, getpid()) < 0) return -ENOMEM; our_env[n_env++] = x; diff --git a/src/core/execute.h b/src/core/execute.h index 2b4238ed7e..2d05ca39aa 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -218,6 +218,7 @@ typedef enum ExecFlags { EXEC_PASS_FDS = 1U << 4, EXEC_IS_CONTROL = 1U << 5, EXEC_SETENV_RESULT = 1U << 6, + EXEC_SET_WATCHDOG = 1U << 7, } ExecFlags; struct ExecParameters { diff --git a/src/core/service.c b/src/core/service.c index a6793b813b..c21653f5fa 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1743,7 +1743,7 @@ static void service_enter_start(Service *s) { r = service_spawn(s, c, timeout, - EXEC_PASS_FDS|EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + EXEC_PASS_FDS|EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG, &pid); if (r < 0) goto fail; @@ -1955,7 +1955,7 @@ static void service_run_next_main(Service *s) { r = service_spawn(s, s->main_command, s->timeout_start_usec, - EXEC_PASS_FDS|EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + EXEC_PASS_FDS|EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG, &pid); if (r < 0) goto fail; -- cgit v1.2.3-54-g00ecf From 163f561e2a1d2ef8ef3a1efa2ea8f00d90cc1246 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 4 Aug 2016 20:36:10 -0400 Subject: basic/set: remove some spurious spaces --- src/basic/set.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/basic/set.h b/src/basic/set.h index 12f64a8c57..a5f8beb0c4 100644 --- a/src/basic/set.h +++ b/src/basic/set.h @@ -23,8 +23,8 @@ #include "hashmap.h" #include "macro.h" -Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); -#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS) +Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS) static inline Set *set_free(Set *s) { internal_hashmap_free(HASHMAP_BASE(s)); @@ -42,8 +42,8 @@ static inline Set *set_copy(Set *s) { return (Set*) internal_hashmap_copy(HASHMAP_BASE(s)); } -int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); -#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) +int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) int set_put(Set *s, const void *key); /* no set_update */ -- cgit v1.2.3-54-g00ecf From 9a73653c3ed819c28a293a5df2da8bdac84dfdb1 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 4 Aug 2016 20:55:45 -0400 Subject: systemd: convert peers_by_address to a set --- src/core/socket.c | 16 ++++++++-------- src/core/socket.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/core/socket.c b/src/core/socket.c index ff55885fb3..d3b9a75547 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -151,10 +151,10 @@ static void socket_done(Unit *u) { socket_free_ports(s); - while ((p = hashmap_steal_first(s->peers_by_address))) + while ((p = set_steal_first(s->peers_by_address))) p->socket = NULL; - s->peers_by_address = hashmap_free(s->peers_by_address); + s->peers_by_address = set_free(s->peers_by_address); s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); @@ -519,7 +519,7 @@ static int socket_load(Unit *u) { assert(u); assert(u->load_state == UNIT_STUB); - r = hashmap_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops); + r = set_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops); if (r < 0) return r; @@ -2366,7 +2366,7 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { } } - HASHMAP_FOREACH(k, s->peers_by_address, i) { + SET_FOREACH(k, s->peers_by_address, i) { _cleanup_free_ char *t = NULL; r = sockaddr_pretty(&k->peer.sa, FAMILY_ADDRESS_SIZE(k->peer.sa.sa_family), true, true, &t); @@ -2560,7 +2560,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, memcpy(&p->peer, &a.sockaddr, sizeof(a.sockaddr)); p->socket = s; - r = hashmap_put(s->peers_by_address, p, p); + r = set_put(s->peers_by_address, p); if (r < 0) return r; @@ -2696,7 +2696,7 @@ SocketPeer *socket_peer_unref(SocketPeer *p) { return NULL; if (p->socket) - (void) hashmap_remove(p->socket->peers_by_address, p); + set_remove(p->socket->peers_by_address, p); free(p); @@ -2716,7 +2716,7 @@ int socket_find_peer(Socket *s, int fd, SocketPeer **p) { if (r < 0) return log_error_errno(errno, "getpeername failed: %m"); - i = hashmap_get(s->peers_by_address, &sa); + i = set_get(s->peers_by_address, &sa); if (i) { *p = i; return 1; @@ -2729,7 +2729,7 @@ int socket_find_peer(Socket *s, int fd, SocketPeer **p) { memcpy(&remote->peer, &sa.peer, sizeof(union sockaddr_union)); remote->socket = s; - r = hashmap_put(s->peers_by_address, remote, remote); + r = set_put(s->peers_by_address, remote); if (r < 0) return r; diff --git a/src/core/socket.h b/src/core/socket.h index 2fe38ef2aa..edbe9df6b1 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -80,7 +80,7 @@ struct Socket { LIST_HEAD(SocketPort, ports); - Hashmap *peers_by_address; + Set *peers_by_address; unsigned n_accepted; unsigned n_connections; -- cgit v1.2.3-54-g00ecf From 2604646c05fcb8a10dadc302ea5a376a56faaa73 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Thu, 4 Aug 2016 21:05:34 -0700 Subject: journal-remote: remove unnecessary gnutls includes (#3895) journal-(gatewayd,remote).c don't actually utilize libgnutls even when HAVE_GNUTLS is defined. --- src/journal-remote/journal-gatewayd.c | 3 --- src/journal-remote/journal-remote.c | 4 ---- 2 files changed, 7 deletions(-) diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index 4ad9184993..a1627fab39 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -19,9 +19,6 @@ #include #include -#ifdef HAVE_GNUTLS -#include -#endif #include #include #include diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index f1ef90ed7a..80e2adb100 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -27,10 +27,6 @@ #include #include -#ifdef HAVE_GNUTLS -#include -#endif - #include "sd-daemon.h" #include "alloc-util.h" -- cgit v1.2.3-54-g00ecf From 82b103a7ce299effbb151a2cd7f0b3c7d29aefad Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Thu, 4 Aug 2016 21:09:23 -0700 Subject: fileio: fix MIN/MAX mixup (#3896) The intention is to clamp the value to READ_FULL_BYTES_MAX, which would be the minimum of the two. --- src/basic/fileio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index c18ac39e03..588eacd77c 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -271,7 +271,7 @@ int read_full_stream(FILE *f, char **contents, size_t *size) { if (n >= READ_FULL_BYTES_MAX) return -E2BIG; - n = MAX(n * 2, READ_FULL_BYTES_MAX); + n = MIN(n * 2, READ_FULL_BYTES_MAX); } buf[l] = 0; -- cgit v1.2.3-54-g00ecf From 1ed1f50f8277df07918e13cba3331a114eaa6fe3 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 5 Aug 2016 04:37:10 -0400 Subject: networkd: do not set NOARP unconditionally (#3891) Fixes #3890. --- src/network/networkd-link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index e1d07eb4b0..69ee7424ce 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1357,7 +1357,7 @@ static int link_set_flags(Link *link) { if (link->network->arp >= 0) { ifi_change |= IFF_NOARP; - ifi_flags |= IFF_NOARP; + ifi_flags |= link->network->arp ? 0 : IFF_NOARP; } r = sd_rtnl_message_link_set_flags(req, ifi_flags, ifi_change); -- cgit v1.2.3-54-g00ecf From 41bf0590cc89438f1d319465190b1c00809c78fe Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Aug 2016 11:17:08 +0200 Subject: util-lib: unify parsing of nice level values This adds parse_nice() that parses a nice level and ensures it is in the right range, via a new nice_is_valid() helper. It then ports over a number of users to this. No functional changes. --- src/basic/parse-util.c | 18 +++++++++++++++++- src/basic/parse-util.h | 2 ++ src/basic/process-util.h | 5 +++++ src/core/dbus-execute.c | 2 +- src/core/load-fragment.c | 32 ++++++++++++++++---------------- src/run/run.c | 8 +++----- src/shared/bus-unit-util.c | 12 +++++------- src/test/test-parse-util.c | 29 +++++++++++++++++++++++++++++ 8 files changed, 78 insertions(+), 30 deletions(-) diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c index 11849ade0b..c98815b9bc 100644 --- a/src/basic/parse-util.c +++ b/src/basic/parse-util.c @@ -29,6 +29,7 @@ #include "extract-word.h" #include "macro.h" #include "parse-util.h" +#include "process-util.h" #include "string-util.h" int parse_boolean(const char *v) { @@ -551,10 +552,25 @@ int parse_percent_unbounded(const char *p) { } int parse_percent(const char *p) { - int v = parse_percent_unbounded(p); + int v; + v = parse_percent_unbounded(p); if (v > 100) return -ERANGE; return v; } + +int parse_nice(const char *p, int *ret) { + int n, r; + + r = safe_atoi(p, &n); + if (r < 0) + return r; + + if (!nice_is_valid(n)) + return -ERANGE; + + *ret = n; + return 0; +} diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h index f0fa5f9752..461e1cd4d8 100644 --- a/src/basic/parse-util.h +++ b/src/basic/parse-util.h @@ -108,3 +108,5 @@ int parse_fractional_part_u(const char **s, size_t digits, unsigned *res); int parse_percent_unbounded(const char *p); int parse_percent(const char *p); + +int parse_nice(const char *p, int *ret); diff --git a/src/basic/process-util.h b/src/basic/process-util.h index 9f75088796..2568e3834f 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "formats-util.h" #include "macro.h" @@ -103,3 +104,7 @@ int sched_policy_from_string(const char *s); void valgrind_summary_hack(void); int pid_compare_func(const void *a, const void *b); + +static inline bool nice_is_valid(int n) { + return n >= PRIO_MIN && n < PRIO_MAX; +} diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 9c50cd93e5..346c8b973e 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -935,7 +935,7 @@ int bus_exec_context_set_transient_property( if (r < 0) return r; - if (n < PRIO_MIN || n >= PRIO_MAX) + if (!nice_is_valid(n)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range"); if (mode != UNIT_CHECK) { diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index d5f035b67f..420f368689 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -491,16 +491,17 @@ int config_parse_socket_bind(const char *unit, return 0; } -int config_parse_exec_nice(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_exec_nice( + 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) { ExecContext *c = data; int priority, r; @@ -510,14 +511,13 @@ int config_parse_exec_nice(const char *unit, assert(rvalue); assert(data); - r = safe_atoi(rvalue, &priority); + r = parse_nice(rvalue, &priority); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority, ignoring: %s", rvalue); - return 0; - } + if (r == -ERANGE) + log_syntax(unit, LOG_ERR, filename, line, r, "Nice priority out of range, ignoring: %s", rvalue); + else + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority, ignoring: %s", rvalue); - if (priority < PRIO_MIN || priority >= PRIO_MAX) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Nice priority out of range, ignoring: %s", rvalue); return 0; } diff --git a/src/run/run.c b/src/run/run.c index 58fa49a4d1..1917ffd857 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -257,11 +257,9 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_NICE: - r = safe_atoi(optarg, &arg_nice); - if (r < 0 || arg_nice < PRIO_MIN || arg_nice >= PRIO_MAX) { - log_error("Failed to parse nice value"); - return -EINVAL; - } + r = parse_nice(optarg, &arg_nice); + if (r < 0) + return log_error_errno(r, "Failed to parse nice value: %s", optarg); arg_nice_set = true; break; diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 589f9d46e9..c3a5233532 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -366,15 +366,13 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen } } else if (streq(field, "Nice")) { - int32_t i; + int n; - r = safe_atoi32(eq, &i); - if (r < 0) { - log_error("Failed to parse %s value %s.", field, eq); - return -EINVAL; - } + r = parse_nice(eq, &n); + if (r < 0) + return log_error_errno(r, "Failed to parse nice value: %s", eq); - r = sd_bus_message_append(m, "v", "i", i); + r = sd_bus_message_append(m, "v", "i", (int32_t) n); } else if (STR_IN_SET(field, "Environment", "PassEnvironment")) { const char *p; diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c index 097c464229..d08014100b 100644 --- a/src/test/test-parse-util.c +++ b/src/test/test-parse-util.c @@ -498,6 +498,34 @@ static void test_parse_percent_unbounded(void) { assert_se(parse_percent_unbounded("400%") == 400); } +static void test_parse_nice(void) { + int n; + + assert_se(parse_nice("0", &n) >= 0 && n == 0); + assert_se(parse_nice("+0", &n) >= 0 && n == 0); + assert_se(parse_nice("-1", &n) >= 0 && n == -1); + assert_se(parse_nice("-2", &n) >= 0 && n == -2); + assert_se(parse_nice("1", &n) >= 0 && n == 1); + assert_se(parse_nice("2", &n) >= 0 && n == 2); + assert_se(parse_nice("+1", &n) >= 0 && n == 1); + assert_se(parse_nice("+2", &n) >= 0 && n == 2); + assert_se(parse_nice("-20", &n) >= 0 && n == -20); + assert_se(parse_nice("19", &n) >= 0 && n == 19); + assert_se(parse_nice("+19", &n) >= 0 && n == 19); + + + assert_se(parse_nice("", &n) == -EINVAL); + assert_se(parse_nice("-", &n) == -EINVAL); + assert_se(parse_nice("+", &n) == -EINVAL); + assert_se(parse_nice("xx", &n) == -EINVAL); + assert_se(parse_nice("-50", &n) == -ERANGE); + assert_se(parse_nice("50", &n) == -ERANGE); + assert_se(parse_nice("+50", &n) == -ERANGE); + assert_se(parse_nice("-21", &n) == -ERANGE); + assert_se(parse_nice("20", &n) == -ERANGE); + assert_se(parse_nice("+20", &n) == -ERANGE); +} + int main(int argc, char *argv[]) { log_parse_environment(); log_open(); @@ -513,6 +541,7 @@ int main(int argc, char *argv[]) { test_safe_atod(); test_parse_percent(); test_parse_percent_unbounded(); + test_parse_nice(); return 0; } -- cgit v1.2.3-54-g00ecf From 166cf510c2ba5aed15dcb807ec263ea2201dcb28 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 4 Aug 2016 21:42:23 -0400 Subject: core/socket: rework SocketPeer refcounting Make functions and definitions that don't need to be shared local to socket.c. --- src/core/socket.c | 194 ++++++++++++++++++++++++++++-------------------------- src/core/socket.h | 7 -- 2 files changed, 100 insertions(+), 101 deletions(-) diff --git a/src/core/socket.c b/src/core/socket.c index d3b9a75547..972d494dbc 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -59,6 +59,13 @@ #include "user-util.h" #include "in-addr-util.h" +struct SocketPeer { + unsigned n_ref; + + Socket *socket; + union sockaddr_union peer; +}; + static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { [SOCKET_DEAD] = UNIT_INACTIVE, [SOCKET_START_PRE] = UNIT_ACTIVATING, @@ -78,9 +85,6 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); -SocketPeer *socket_peer_new(void); -int socket_find_peer(Socket *s, int fd, SocketPeer **p); - static void socket_init(Unit *u) { Socket *s = SOCKET(u); @@ -482,10 +486,11 @@ static void peer_address_hash_func(const void *p, struct siphash *state) { const SocketPeer *s = p; assert(s); + assert(IN_SET(s->peer.sa.sa_family, AF_INET, AF_INET6)); if (s->peer.sa.sa_family == AF_INET) siphash24_compress(&s->peer.in.sin_addr, sizeof(s->peer.in.sin_addr), state); - else if (s->peer.sa.sa_family == AF_INET6) + else siphash24_compress(&s->peer.in6.sin6_addr, sizeof(s->peer.in6.sin6_addr), state); } @@ -503,8 +508,7 @@ static int peer_address_compare_func(const void *a, const void *b) { case AF_INET6: return memcmp(&x->peer.in6.sin6_addr, &y->peer.in6.sin6_addr, sizeof(x->peer.in6.sin6_addr)); } - - return -1; + assert_not_reached("Black sheep in the family!"); } const struct hash_ops peer_address_hash_ops = { @@ -537,6 +541,87 @@ static int socket_load(Unit *u) { return socket_verify(s); } +static SocketPeer *socket_peer_new(void) { + SocketPeer *p; + + p = new0(SocketPeer, 1); + if (!p) + return NULL; + + p->n_ref = 1; + + return p; +} + +SocketPeer *socket_peer_ref(SocketPeer *p) { + if (!p) + return NULL; + + assert(p->n_ref > 0); + p->n_ref++; + + return p; +} + +SocketPeer *socket_peer_unref(SocketPeer *p) { + if (!p) + return NULL; + + assert(p->n_ref > 0); + + p->n_ref--; + + if (p->n_ref > 0) + return NULL; + + if (p->socket) + set_remove(p->socket->peers_by_address, p); + + return mfree(p); +} + +static int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) { + _cleanup_(socket_peer_unrefp) SocketPeer *remote = NULL; + SocketPeer sa = {}, *i; + socklen_t salen = sizeof(sa.peer); + int r; + + assert(fd >= 0); + assert(s); + + r = getpeername(fd, &sa.peer.sa, &salen); + if (r < 0) + return log_error_errno(errno, "getpeername failed: %m"); + + if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6)) { + *p = NULL; + return 0; + } + + i = set_get(s->peers_by_address, &sa); + if (i) { + *p = socket_peer_ref(i); + return 1; + } + + remote = socket_peer_new(); + if (!remote) + return log_oom(); + + remote->peer = sa.peer; + + r = set_put(s->peers_by_address, remote); + if (r < 0) + return r; + + remote->socket = s; + + *p = remote; + remote = NULL; + + return 1; +} + _const_ static const char* listen_lookup(int family, int type) { if (family == AF_NETLINK) @@ -2102,22 +2187,22 @@ static void socket_enter_running(Socket *s, int cfd) { Service *service; if (s->n_connections >= s->max_connections) { - log_unit_warning(UNIT(s), "Too many incoming connections (%u), refusing connection attempt.", s->n_connections); + log_unit_warning(UNIT(s), "Too many incoming connections (%u), refusing connection attempt.", + s->n_connections); safe_close(cfd); return; } if (s->max_connections_per_source > 0) { - r = socket_find_peer(s, cfd, &p); + r = socket_acquire_peer(s, cfd, &p); if (r < 0) { safe_close(cfd); return; - } - - if (p->n_ref > s->max_connections_per_source) { - log_unit_warning(UNIT(s), "Too many incoming connections (%u) from source, refusing connection attempt.", p->n_ref); + } else if (r > 0 && p->n_ref > s->max_connections_per_source) { + log_unit_warning(UNIT(s), + "Too many incoming connections (%u) from source, refusing connection attempt.", + p->n_ref); safe_close(cfd); - p = NULL; return; } } @@ -2163,10 +2248,8 @@ static void socket_enter_running(Socket *s, int cfd) { cfd = -1; /* We passed ownership of the fd to the service now. Forget it here. */ s->n_connections++; - if (s->max_connections_per_source > 0) { - service->peer = socket_peer_ref(p); - p = NULL; - } + service->peer = p; /* Pass ownership of the peer reference */ + p = NULL; r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, &error, NULL); if (r < 0) { @@ -2662,83 +2745,6 @@ _pure_ static bool socket_check_gc(Unit *u) { return s->n_connections > 0; } -SocketPeer *socket_peer_new(void) { - SocketPeer *p; - - p = new0(SocketPeer, 1); - if (!p) - return NULL; - - p->n_ref = 1; - - return p; -} - -SocketPeer *socket_peer_ref(SocketPeer *p) { - if (!p) - return NULL; - - assert(p->n_ref > 0); - p->n_ref++; - - return p; -} - -SocketPeer *socket_peer_unref(SocketPeer *p) { - if (!p) - return NULL; - - assert(p->n_ref > 0); - - p->n_ref--; - - if (p->n_ref > 0) - return NULL; - - if (p->socket) - set_remove(p->socket->peers_by_address, p); - - free(p); - - return NULL; -} - -int socket_find_peer(Socket *s, int fd, SocketPeer **p) { - _cleanup_free_ SocketPeer *remote = NULL; - SocketPeer sa, *i; - socklen_t salen = sizeof(sa.peer); - int r; - - assert(fd >= 0); - assert(s); - - r = getpeername(fd, &sa.peer.sa, &salen); - if (r < 0) - return log_error_errno(errno, "getpeername failed: %m"); - - i = set_get(s->peers_by_address, &sa); - if (i) { - *p = i; - return 1; - } - - remote = socket_peer_new(); - if (!remote) - return log_oom(); - - memcpy(&remote->peer, &sa.peer, sizeof(union sockaddr_union)); - remote->socket = s; - - r = set_put(s->peers_by_address, remote); - if (r < 0) - return r; - - *p = remote; - remote = NULL; - - return 0; -} - static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { SocketPort *p = userdata; int cfd = -1; diff --git a/src/core/socket.h b/src/core/socket.h index edbe9df6b1..6a78fd322d 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -168,13 +168,6 @@ struct Socket { RateLimit trigger_limit; }; -struct SocketPeer { - unsigned n_ref; - - Socket *socket; - union sockaddr_union peer; -}; - SocketPeer *socket_peer_ref(SocketPeer *p); SocketPeer *socket_peer_unref(SocketPeer *p); -- cgit v1.2.3-54-g00ecf From 9dfb64f87da718284f5c840ac6176dccbfd7dc3e Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 4 Aug 2016 23:26:31 -0400 Subject: core/service: serialize and deserialize accept_socket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes an issue during reexec — the count of connections would be lost: [zbyszek@fedora-rawhide ~]$ systemctl status testlimit.socket | grep Connected Accepted: 1; Connected: 1 [zbyszek@fedora-rawhide ~]$ sudo systemctl daemon-reexec [zbyszek@fedora-rawhide ~]$ systemctl status testlimit.socket | grep Connected Accepted: 1; Connected: 0 With the patch, Connected count is preserved. Also add "Accept Socket" to the dump output for services. --- src/core/service.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/core/service.c b/src/core/service.c index eb125cb999..1629e1ce44 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -761,6 +761,11 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) { prefix, s->bus_name, prefix, yes_no(s->bus_name_good)); + if (UNIT_ISSET(s->accept_socket)) + fprintf(f, + "%sAccept Socket: %s\n", + prefix, UNIT_DEREF(s->accept_socket)->id); + kill_context_dump(&s->kill_context, f, prefix); exec_context_dump(&s->exec_context, f, prefix); @@ -2130,6 +2135,12 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) { if (r < 0) return r; + if (UNIT_ISSET(s->accept_socket)) { + r = unit_serialize_item(u, f, "accept-socket", UNIT_DEREF(s->accept_socket)->id); + if (r < 0) + return r; + } + r = unit_serialize_item_fd(u, f, fds, "socket-fd", s->socket_fd); if (r < 0) return r; @@ -2260,6 +2271,17 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, s->control_command_id = id; s->control_command = s->exec_command[id]; } + } else if (streq(key, "accept-socket")) { + Unit *socket; + + r = manager_load_unit(u->manager, value, NULL, NULL, &socket); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to load accept-socket unit: %s", value); + else { + unit_ref_set(&s->accept_socket, socket); + SOCKET(socket)->n_connections++; + } + } else if (streq(key, "socket-fd")) { int fd; -- cgit v1.2.3-54-g00ecf From 3ebcd323bdeeb55bb963fe5e9d97a87f96fd8879 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 4 Aug 2016 23:42:27 -0400 Subject: systemd: do not serialize peer, bump count when deserializing socket instead --- src/core/service.c | 14 ++++++++++++++ src/core/socket.c | 42 +----------------------------------------- src/core/socket.h | 1 + 3 files changed, 16 insertions(+), 41 deletions(-) diff --git a/src/core/service.c b/src/core/service.c index 1629e1ce44..3c9455a5f8 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1041,6 +1041,20 @@ static int service_coldplug(Unit *u) { if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)) (void) unit_setup_dynamic_creds(u); + if (UNIT_ISSET(s->accept_socket)) { + Socket* socket = SOCKET(UNIT_DEREF(s->accept_socket)); + + if (socket->max_connections_per_source > 0) { + SocketPeer *peer; + + /* Make a best-effort attempt at bumping the connection count */ + if (socket_acquire_peer(socket, s->socket_fd, &peer) > 0) { + socket_peer_unref(s->peer); + s->peer = peer; + } + } + } + service_set_state(s, s->deserialized_state); return 0; } diff --git a/src/core/socket.c b/src/core/socket.c index 972d494dbc..0d77694251 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -580,7 +580,7 @@ SocketPeer *socket_peer_unref(SocketPeer *p) { return mfree(p); } -static int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) { +int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) { _cleanup_(socket_peer_unrefp) SocketPeer *remote = NULL; SocketPeer sa = {}, *i; socklen_t salen = sizeof(sa.peer); @@ -2396,9 +2396,7 @@ static int socket_stop(Unit *u) { static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { Socket *s = SOCKET(u); - SocketPeer *k; SocketPort *p; - Iterator i; int r; assert(u); @@ -2449,16 +2447,6 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { } } - SET_FOREACH(k, s->peers_by_address, i) { - _cleanup_free_ char *t = NULL; - - r = sockaddr_pretty(&k->peer.sa, FAMILY_ADDRESS_SIZE(k->peer.sa.sa_family), true, true, &t); - if (r < 0) - return r; - - unit_serialize_item_format(u, f, "peer", "%u %s", k->n_ref, t); - } - return 0; } @@ -2574,7 +2562,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse socket value: %s", value); else { - LIST_FOREACH(port, p, s->ports) if (socket_address_is(&p->address, value+skip, type)) break; @@ -2622,33 +2609,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, } } - } else if (streq(key, "peer")) { - _cleanup_(socket_peer_unrefp) SocketPeer *p; - int n_ref, skip = 0; - SocketAddress a; - int r; - - if (sscanf(value, "%u %n", &n_ref, &skip) < 1 || n_ref < 1) - log_unit_debug(u, "Failed to parse socket peer value: %s", value); - else { - r = socket_address_parse(&a, value+skip); - if (r < 0) - return r; - - p = socket_peer_new(); - if (!p) - return log_oom(); - - p->n_ref = n_ref; - memcpy(&p->peer, &a.sockaddr, sizeof(a.sockaddr)); - p->socket = s; - - r = set_put(s->peers_by_address, p); - if (r < 0) - return r; - - p = NULL; - } } else log_unit_debug(UNIT(s), "Unknown serialization key: %s", key); diff --git a/src/core/socket.h b/src/core/socket.h index 6a78fd322d..89f4664510 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -170,6 +170,7 @@ struct Socket { SocketPeer *socket_peer_ref(SocketPeer *p); SocketPeer *socket_peer_unref(SocketPeer *p); +int socket_acquire_peer(Socket *s, int fd, SocketPeer **p); DEFINE_TRIVIAL_CLEANUP_FUNC(SocketPeer*, socket_peer_unref); -- cgit v1.2.3-54-g00ecf From ea8f50f8085ce9385676385006030e8886cabaa6 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 4 Aug 2016 23:51:47 -0400 Subject: core/socket: include remote address in the message when dropping connection Without the address the message is not very useful. Aug 04 23:52:21 rawhide systemd[1]: testlimit.socket: Too many incoming connections (4) from source ::1, dropping connection. --- src/core/socket.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/core/socket.c b/src/core/socket.c index 0d77694251..b8a2f7fff8 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2187,7 +2187,7 @@ static void socket_enter_running(Socket *s, int cfd) { Service *service; if (s->n_connections >= s->max_connections) { - log_unit_warning(UNIT(s), "Too many incoming connections (%u), refusing connection attempt.", + log_unit_warning(UNIT(s), "Too many incoming connections (%u), dropping connection.", s->n_connections); safe_close(cfd); return; @@ -2199,9 +2199,13 @@ static void socket_enter_running(Socket *s, int cfd) { safe_close(cfd); return; } else if (r > 0 && p->n_ref > s->max_connections_per_source) { + _cleanup_free_ char *t = NULL; + + sockaddr_pretty(&p->peer.sa, FAMILY_ADDRESS_SIZE(p->peer.sa.sa_family), true, false, &t); + log_unit_warning(UNIT(s), - "Too many incoming connections (%u) from source, refusing connection attempt.", - p->n_ref); + "Too many incoming connections (%u) from source %s, dropping connection.", + p->n_ref, strnull(t)); safe_close(cfd); return; } -- cgit v1.2.3-54-g00ecf From 80a58668d989c2316bcf1079b3e98ae526e633fa Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 5 Aug 2016 08:24:00 -0400 Subject: socket: add helper function to remove code duplication --- src/core/socket.c | 82 ++++++++++++++++++++----------------------------------- 1 file changed, 29 insertions(+), 53 deletions(-) diff --git a/src/core/socket.c b/src/core/socket.c index b8a2f7fff8..7f3f154a16 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2454,6 +2454,11 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { return 0; } +static void socket_port_take_fd(SocketPort *p, FDSet *fds, int fd) { + safe_close(p->fd); + p->fd = fdset_remove(fds, fd); +} + static int socket_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Socket *s = SOCKET(u); @@ -2508,18 +2513,13 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse fifo value: %s", value); - else { - + else LIST_FOREACH(port, p, s->ports) if (p->type == SOCKET_FIFO && - path_equal_or_files_same(p->path, value+skip)) + path_equal_or_files_same(p->path, value+skip)) { + socket_port_take_fd(p, fds, fd); break; - - if (p) { - safe_close(p->fd); - p->fd = fdset_remove(fds, fd); - } - } + } } else if (streq(key, "special")) { int fd, skip = 0; @@ -2527,18 +2527,13 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse special value: %s", value); - else { - + else LIST_FOREACH(port, p, s->ports) if (p->type == SOCKET_SPECIAL && - path_equal_or_files_same(p->path, value+skip)) + path_equal_or_files_same(p->path, value+skip)) { + socket_port_take_fd(p, fds, fd); break; - - if (p) { - safe_close(p->fd); - p->fd = fdset_remove(fds, fd); - } - } + } } else if (streq(key, "mqueue")) { int fd, skip = 0; @@ -2546,18 +2541,13 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse mqueue value: %s", value); - else { - + else LIST_FOREACH(port, p, s->ports) if (p->type == SOCKET_MQUEUE && - streq(p->path, value+skip)) + streq(p->path, value+skip)) { + socket_port_take_fd(p, fds, fd); break; - - if (p) { - safe_close(p->fd); - p->fd = fdset_remove(fds, fd); - } - } + } } else if (streq(key, "socket")) { int fd, type, skip = 0; @@ -2565,16 +2555,12 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse socket value: %s", value); - else { + else LIST_FOREACH(port, p, s->ports) - if (socket_address_is(&p->address, value+skip, type)) + if (socket_address_is(&p->address, value+skip, type)) { + socket_port_take_fd(p, fds, fd); break; - - if (p) { - safe_close(p->fd); - p->fd = fdset_remove(fds, fd); - } - } + } } else if (streq(key, "netlink")) { int fd, skip = 0; @@ -2582,17 +2568,12 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse socket value: %s", value); - else { - + else LIST_FOREACH(port, p, s->ports) - if (socket_address_is_netlink(&p->address, value+skip)) + if (socket_address_is_netlink(&p->address, value+skip)) { + socket_port_take_fd(p, fds, fd); break; - - if (p) { - safe_close(p->fd); - p->fd = fdset_remove(fds, fd); - } - } + } } else if (streq(key, "ffs")) { int fd, skip = 0; @@ -2600,18 +2581,13 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) log_unit_debug(u, "Failed to parse ffs value: %s", value); - else { - + else LIST_FOREACH(port, p, s->ports) if (p->type == SOCKET_USB_FUNCTION && - path_equal_or_files_same(p->path, value+skip)) + path_equal_or_files_same(p->path, value+skip)) { + socket_port_take_fd(p, fds, fd); break; - - if (p) { - safe_close(p->fd); - p->fd = fdset_remove(fds, fd); - } - } + } } else log_unit_debug(UNIT(s), "Unknown serialization key: %s", key); -- cgit v1.2.3-54-g00ecf From b760a9af902c73ae76a05e17374e12e8e6c4e629 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Sat, 6 Aug 2016 05:14:57 +0530 Subject: networkd: add support to set STP (#3903) fixes #3881 --- man/systemd.netdev.xml | 9 ++++++++- src/network/networkd-netdev-bridge.c | 7 +++++++ src/network/networkd-netdev-bridge.h | 1 + src/network/networkd-netdev-gperf.gperf | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index a5c6f0fa40..e56708a648 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -343,8 +343,15 @@ + + STP= + + A boolean. This enables the bridge's Spanning Tree Protocol (STP). When unset, + the kernel's default setting applies. + + + - diff --git a/src/network/networkd-netdev-bridge.c b/src/network/networkd-netdev-bridge.c index a5085d2b19..12b0fe972f 100644 --- a/src/network/networkd-netdev-bridge.c +++ b/src/network/networkd-netdev-bridge.c @@ -108,6 +108,12 @@ static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_mess return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_FILTERING attribute: %m"); } + if (b->stp >= 0) { + r = sd_netlink_message_append_u32(req, IFLA_BR_STP_STATE, b->stp); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_STP_STATE attribute: %m"); + } + r = sd_netlink_message_close_container(req); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); @@ -135,6 +141,7 @@ static void bridge_init(NetDev *n) { b->mcast_querier = -1; b->mcast_snooping = -1; b->vlan_filtering = -1; + b->stp = -1; } const NetDevVTable bridge_vtable = { diff --git a/src/network/networkd-netdev-bridge.h b/src/network/networkd-netdev-bridge.h index a637aea0a3..4ce0fbb6f9 100644 --- a/src/network/networkd-netdev-bridge.h +++ b/src/network/networkd-netdev-bridge.h @@ -27,6 +27,7 @@ typedef struct Bridge { int mcast_querier; int mcast_snooping; int vlan_filtering; + int stp; usec_t forward_delay; usec_t hello_time; diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf index 9d69f61376..a1ca1a3d4e 100644 --- a/src/network/networkd-netdev-gperf.gperf +++ b/src/network/networkd-netdev-gperf.gperf @@ -106,4 +106,5 @@ Bridge.ForwardDelaySec, config_parse_sec, 0, Bridge.MulticastQuerier, config_parse_tristate, 0, offsetof(Bridge, mcast_querier) Bridge.MulticastSnooping, config_parse_tristate, 0, offsetof(Bridge, mcast_snooping) Bridge.VLANFiltering, config_parse_tristate, 0, offsetof(Bridge, vlan_filtering) +Bridge.STP, config_parse_tristate, 0, offsetof(Bridge, stp) VRF.TableId, config_parse_uint32, 0, offsetof(Vrf, table_id) -- cgit v1.2.3-54-g00ecf From d6d46cddee404cec266a63fe83b8224b8532e9eb Mon Sep 17 00:00:00 2001 From: Cristian Rodríguez Date: Thu, 4 Aug 2016 16:49:19 +0000 Subject: test: test-sigbus must be skipped when -fsanitize=address is used ASAN is unable to handle it. --- src/test/test-sigbus.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/test-sigbus.c b/src/test/test-sigbus.c index 17b81747be..02b8e24308 100644 --- a/src/test/test-sigbus.c +++ b/src/test/test-sigbus.c @@ -29,6 +29,9 @@ int main(int argc, char *argv[]) { void *addr = NULL; uint8_t *p; +#ifdef __SANITIZE_ADDRESS__ + return EXIT_TEST_SKIP; +#endif sigbus_install(); assert_se(sigbus_pop(&addr) == 0); -- cgit v1.2.3-54-g00ecf From ba8868f58a1030d8d71ecd0edb1c90fe23b914d8 Mon Sep 17 00:00:00 2001 From: Cristian Rodríguez Date: Fri, 5 Aug 2016 16:07:49 +0000 Subject: test: fix stack overflow reported by ASAN It was meant to write to q instead of t FAIL: test-id128 ================ ================================================================= ==125770==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd4615bd31 at pc 0x7a2f41b1bf33 bp 0x7ffd4615b750 sp 0x7ffd4615b748 WRITE of size 1 at 0x7ffd4615bd31 thread T0 #0 0x7a2f41b1bf32 in id128_to_uuid_string src/libsystemd/sd-id128/id128-util.c:42 #1 0x401f73 in main src/test/test-id128.c:147 #2 0x7a2f41336341 in __libc_start_main (/lib64/libc.so.6+0x20341) #3 0x401129 in _start (/home/crrodriguez/scm/systemd/.libs/test-id128+0x401129) Address 0x7ffd4615bd31 is located in stack of thread T0 at offset 1409 in frame #0 0x401205 in main src/test/test-id128.c:37 This frame has 23 object(s): [32, 40) 'b' [96, 112) 'id' [160, 176) 'id2' [224, 240) 'a' [288, 304) 'b' [352, 368) 'a' [416, 432) 'b' [480, 496) 'a' [544, 560) 'b' [608, 624) 'a' [672, 688) 'b' [736, 752) 'a' [800, 816) 'b' [864, 880) 'a' [928, 944) 'b' [992, 1008) 'a' [1056, 1072) 'b' [1120, 1136) 'a' [1184, 1200) 'b' [1248, 1264) 'a' [1312, 1328) 'b' [1376, 1409) 't' <== Memory access at offset 1409 overflows this variable [1472, 1509) 'q' HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext (longjmp and C++ exceptions *are* supported) SUMMARY: AddressSanitizer: stack-buffer-overflow src/libsystemd/sd-id128/id128-util.c:42 in id128_to_uuid_string Shadow bytes around the buggy address: 0x100028c23750: f2 f2 00 00 f4 f4 f2 f2 f2 f2 00 00 f4 f4 f2 f2 0x100028c23760: f2 f2 00 00 f4 f4 f2 f2 f2 f2 00 00 f4 f4 f2 f2 0x100028c23770: f2 f2 00 00 f4 f4 f2 f2 f2 f2 00 00 f4 f4 f2 f2 0x100028c23780: f2 f2 00 00 f4 f4 f2 f2 f2 f2 00 00 f4 f4 f2 f2 0x100028c23790: f2 f2 00 00 f4 f4 f2 f2 f2 f2 00 00 f4 f4 f2 f2 =>0x100028c237a0: f2 f2 00 00 00 00[01]f4 f4 f4 f2 f2 f2 f2 00 00 0x100028c237b0: 00 00 05 f4 f4 f4 00 00 00 00 00 00 00 00 00 00 0x100028c237c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100028c237d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100028c237e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100028c237f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==125770==ABORTING FAIL test-id128 (exit status: 1) --- src/test/test-id128.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/test-id128.c b/src/test/test-id128.c index f01fbdd6b2..1c8e5549da 100644 --- a/src/test/test-id128.c +++ b/src/test/test-id128.c @@ -144,7 +144,7 @@ int main(int argc, char *argv[]) { assert_se(ftruncate(fd, 0) >= 0); assert_se(sd_id128_randomize(&id) >= 0); - assert_se(write(fd, id128_to_uuid_string(id, t), 36) == 36); + assert_se(write(fd, id128_to_uuid_string(id, q), 36) == 36); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL); -- cgit v1.2.3-54-g00ecf From 7dbe0b72c5666a0e0a73cefac2b1c253bce5deef Mon Sep 17 00:00:00 2001 From: Cristian Rodríguez Date: Fri, 5 Aug 2016 16:10:41 +0000 Subject: buildsys,journal: allow -fsanitize=address without VALGRIND defined Fixed (master) versions of libtool pass -fsanitize=address correctly into CFLAGS and LDFLAGS allowing ASAN to be used without any special configure tricks..however ASAN triggers in lookup3.c for the same reasons valgrind does. take the alternative codepath if __SANITIZE_ADDRESS__ is defined as well. --- src/journal/lookup3.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/journal/lookup3.c b/src/journal/lookup3.c index 3d791234f4..d8f1a4977d 100644 --- a/src/journal/lookup3.c +++ b/src/journal/lookup3.c @@ -317,7 +317,7 @@ uint32_t jenkins_hashlittle( const void *key, size_t length, uint32_t initval) * still catch it and complain. The masking trick does make the hash * noticeably faster for short strings (like English words). */ -#ifndef VALGRIND +#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__) switch(length) { @@ -503,7 +503,7 @@ void jenkins_hashlittle2( * still catch it and complain. The masking trick does make the hash * noticeably faster for short strings (like English words). */ -#ifndef VALGRIND +#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__) switch(length) { @@ -681,7 +681,7 @@ uint32_t jenkins_hashbig( const void *key, size_t length, uint32_t initval) * still catch it and complain. The masking trick does make the hash * noticeably faster for short strings (like English words). */ -#ifndef VALGRIND +#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__) switch(length) { -- cgit v1.2.3-54-g00ecf From 1aa1e59c7f34acdbd1af7c18e1fc471e5b92ed85 Mon Sep 17 00:00:00 2001 From: Yi EungJun Date: Sun, 7 Aug 2016 02:00:31 +0900 Subject: journal-gatewayd: add --directory option (#3913) Serve journals in the specified directory instead of default journals. --- man/systemd-journal-gatewayd.service.xml | 10 ++++++++++ src/journal-remote/journal-gatewayd.c | 23 ++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/man/systemd-journal-gatewayd.service.xml b/man/systemd-journal-gatewayd.service.xml index 9ed85c3950..2cb114f6e3 100644 --- a/man/systemd-journal-gatewayd.service.xml +++ b/man/systemd-journal-gatewayd.service.xml @@ -100,6 +100,16 @@ with . + + + + + Takes a directory path as argument. If + specified, systemd-journal-gatewayd will serve the + specified journal directory DIR instead of + the default runtime and system journal paths. + + diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index a1627fab39..4d785c819f 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -45,6 +45,7 @@ static char *arg_key_pem = NULL; static char *arg_cert_pem = NULL; static char *arg_trust_pem = NULL; +static char *arg_directory = NULL; typedef struct RequestMeta { sd_journal *journal; @@ -115,7 +116,10 @@ static int open_journal(RequestMeta *m) { if (m->journal) return 0; - return sd_journal_open(&m->journal, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM); + if (arg_directory) + return sd_journal_open_directory(&m->journal, arg_directory, 0); + else + return sd_journal_open(&m->journal, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM); } static int request_meta_ensure_tmp(RequestMeta *m) { @@ -878,7 +882,8 @@ static void help(void) { " --version Show package version\n" " --cert=CERT.PEM Server certificate in PEM format\n" " --key=KEY.PEM Server key in PEM format\n" - " --trust=CERT.PEM Certificat authority certificate in PEM format\n", + " --trust=CERT.PEM Certificat authority certificate in PEM format\n" + " -D --directory=PATH Serve journal files in directory\n", program_invocation_short_name); } @@ -893,11 +898,12 @@ static int parse_argv(int argc, char *argv[]) { int r, c; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "key", required_argument, NULL, ARG_KEY }, - { "cert", required_argument, NULL, ARG_CERT }, - { "trust", required_argument, NULL, ARG_TRUST }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "key", required_argument, NULL, ARG_KEY }, + { "cert", required_argument, NULL, ARG_CERT }, + { "trust", required_argument, NULL, ARG_TRUST }, + { "directory", required_argument, NULL, 'D' }, {} }; @@ -951,6 +957,9 @@ static int parse_argv(int argc, char *argv[]) { #else log_error("Option --trust is not available."); #endif + case 'D': + arg_directory = optarg; + break; case '?': return -EINVAL; -- cgit v1.2.3-54-g00ecf From 3475fc5899db8c8c9198573912429b85213e4862 Mon Sep 17 00:00:00 2001 From: Yi EungJun Date: Sun, 7 Aug 2016 05:39:13 +0900 Subject: journal-gatewayd: fix segfault with certain request (#3893) When client requests to get logs with `follow` and `KEY=match` that doesn't match any log entry, journal-gatewayd segfaulted. Make request_reader_entries to return zero in such case to wait for matching entries. This fixes https://github.com/systemd/systemd/issues/3873. --- src/journal-remote/journal-gatewayd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index 4d785c819f..05c8698f78 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -240,6 +240,9 @@ static ssize_t request_reader_entries( m->size = (uint64_t) sz; } + if (m->tmp == NULL && m->follow) + return 0; + if (fseeko(m->tmp, pos, SEEK_SET) < 0) { log_error_errno(errno, "Failed to seek to position: %m"); return MHD_CONTENT_READER_END_WITH_ERROR; -- cgit v1.2.3-54-g00ecf From 0a07667d8dd7e931ab425b3beb4fef01d8238f3c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 6 Aug 2016 16:36:51 -0400 Subject: man: provide html links to a bunch of external man pages --- man/localectl.xml | 2 +- man/systemd-resolved.service.xml | 8 ++++---- man/systemd.exec.xml | 2 +- man/systemd.mount.xml | 2 +- man/systemd.offline-updates.xml | 2 +- man/tmpfiles.d.xml | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/man/localectl.xml b/man/localectl.xml index 8d2becb5d9..31238272f3 100644 --- a/man/localectl.xml +++ b/man/localectl.xml @@ -223,7 +223,7 @@ systemctl1, systemd-localed.service8, systemd-firstboot1, - mkinitrd8 + mkinitrd8 diff --git a/man/systemd-resolved.service.xml b/man/systemd-resolved.service.xml index aa1c2365e5..56f67960ce 100644 --- a/man/systemd-resolved.service.xml +++ b/man/systemd-resolved.service.xml @@ -68,12 +68,12 @@ link-local networking). The glibc - getaddrinfo3 API as defined + getaddrinfo3 API as defined by RFC3493 and its related resolver functions, - including gethostbyname3. This + including gethostbyname3. This API is widely supported, including beyond the Linux platform. In its current form it does not expose DNSSEC validation status information however, and is synchronous only. This API is backed by the glibc Name Service - Switch (nss5). Usage of the + Switch (nss5). Usage of the glibc NSS module nss-resolve8 is required in order to allow glibc's NSS resolver functions to resolve host names via systemd-resolved. @@ -164,7 +164,7 @@ <filename>/etc/resolv.conf</filename> Three modes of handling /etc/resolv.conf (see - resolv.conf5) are + resolv.conf5) are supported: diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 0fc658f180..f530acac8f 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1449,7 +1449,7 @@ Takes a boolean argument. If set, any attempts to enable realtime scheduling in a process of the unit are refused. This restricts access to realtime task scheduling policies such as SCHED_FIFO, SCHED_RR or SCHED_DEADLINE. See - sched7 for details about + sched7 for details about these scheduling policies. Realtime scheduling policies may be used to monopolize CPU time for longer periods of time, and may hence be used to lock up or otherwise trigger Denial-of-Service situations on the system. It is hence recommended to restrict access to realtime scheduling to the few programs that actually require diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml index 66cddd72e0..a38165f9b9 100644 --- a/man/systemd.mount.xml +++ b/man/systemd.mount.xml @@ -160,7 +160,7 @@ for details about the conversion. The NFS mount option for NFS background mounts - as documented in nfs5 + as documented in nfs5 is not supported in /etc/fstab entries. The systemd mount option provides similar functionality and should be used instead. diff --git a/man/systemd.offline-updates.xml b/man/systemd.offline-updates.xml index ae53b8552d..ba35a1786a 100644 --- a/man/systemd.offline-updates.xml +++ b/man/systemd.offline-updates.xml @@ -163,7 +163,7 @@ systemd1, systemd.generator7, systemd-update-generator8, - dnf.plugin.system-upgrade8 + dnf.plugin.system-upgrade8 diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml index 957475d2bd..75fb901102 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -626,7 +626,7 @@ Create directories with specific mode and ownership - screen1, + screen1, needs two directories created at boot with specific modes and ownership: # /usr/lib/tmpfiles.d/screen.conf @@ -652,7 +652,7 @@ t /run/cups - - - - security.SMACK64=printing user.attr-with-spaces="foo bar" Create a directory and prevent its contents from cleanup - abrt1, + abrt1, needs a directory created at boot with specific mode and ownership and its content should be preserved from the automatic cleanup applied to the contents of /var/tmp: -- cgit v1.2.3-54-g00ecf From 2ac5fe9525eaaff33549b15ac3d12982aedb3d71 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 6 Aug 2016 16:38:09 -0400 Subject: man: fix some internal man page references sd_journal-query_enumerate was an early draft, the name was changed to sd_j_enumerate_fields. --- man/networkd.conf.xml | 2 +- man/sd-journal.xml | 2 -- man/systemd.offline-updates.xml | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/man/networkd.conf.xml b/man/networkd.conf.xml index 4bfc4f773a..57e647a31b 100644 --- a/man/networkd.conf.xml +++ b/man/networkd.conf.xml @@ -120,7 +120,7 @@ The DUID value specified here overrides the DUID that systemd-networkd generates using the machine-id from the /etc/machine-id file. To configure DUID per-network, see - systemd.network 5. + systemd.network5. The configured DHCP DUID should conform to the specification in RFC 3315, RFC 6355. To configure IAID, see diff --git a/man/sd-journal.xml b/man/sd-journal.xml index 09747a480c..936a83acf7 100644 --- a/man/sd-journal.xml +++ b/man/sd-journal.xml @@ -77,7 +77,6 @@ sd_journal_get_realtime_usec3, sd_journal_add_match3, sd_journal_seek_head3, - sd_journal_query_enumerate3, sd_journal_enumerate_fields3, sd_journal_get_cursor3, sd_journal_get_cutoff_realtime_usec3, @@ -113,7 +112,6 @@ sd_journal_get_realtime_usec3, sd_journal_add_match3, sd_journal_seek_head3, - sd_journal_query_enumerate3, sd_journal_enumerate_fields3, sd_journal_get_cursor3, sd_journal_get_cutoff_realtime_usec3, diff --git a/man/systemd.offline-updates.xml b/man/systemd.offline-updates.xml index ba35a1786a..f404c8d72f 100644 --- a/man/systemd.offline-updates.xml +++ b/man/systemd.offline-updates.xml @@ -77,7 +77,7 @@ Very early in the new boot - systemd-update-generator8 + systemd-system-update-generator8 checks whether /system-update exists. If so, it (temporarily and for this boot only) redirects (i.e. symlinks) default.target to system-update.target, a special target that is pulls in the base system @@ -162,7 +162,7 @@ Implementing Offline System Updates, systemd1, systemd.generator7, - systemd-update-generator8, + systemd-system-update-generator8, dnf.plugin.system-upgrade8 -- cgit v1.2.3-54-g00ecf From e64e1bfd86534e542f7d5585459e78f88a6d9b27 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 7 Aug 2016 05:14:40 -0400 Subject: man: add a table of possible exit statuses (#3910) --- man/systemd.exec.xml | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 2495998295..6163709afd 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1651,9 +1651,68 @@ dumped. $EXIT_STATUS contains the numeric exit code formatted as string if $EXIT_CODE is exited, and the signal name in all other cases. Note that these environment variables are only set if the service manager succeeded to start and identify the main - process of the service. - + process of the service. + + + Summary of possible service result variable values + + + + + + + $SERVICE_RESULT + $EXIT_STATUS + $EXIT_CODE + + + + + + exit-code + exited + 0123255 + + + + signal + killed + HUPINTKILL + + + + core-dump + dumped + ABRTSEGVQUIT + + + watchdog + dumped + ABRT + + + killed + TERMKILL + + + exited + 0123255 + + + + resources + any of the above + any of the above + + + +
+ + + Additional variables may be configured by the following @@ -1689,4 +1748,5 @@ + -- cgit v1.2.3-54-g00ecf From 2ad6b61049e13b93b1b3a92b4802e82ab99c86af Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Sun, 7 Aug 2016 14:53:32 +0530 Subject: networkd: remove duplicate call to manager_dirty (#3917) since link_dirty itself calls manager_dirty no need to call it separately . --- src/network/networkd-network.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 17bbe5de9f..49faba5b12 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -395,10 +395,8 @@ int network_apply(Manager *manager, Network *network, Link *link) { if (!strv_isempty(network->dns) || !strv_isempty(network->ntp) || !strv_isempty(network->search_domains) || - !strv_isempty(network->route_domains)) { - manager_dirty(manager); + !strv_isempty(network->route_domains)) link_dirty(link); - } return 0; } -- cgit v1.2.3-54-g00ecf From 66ebf6c0a1005f90099e25ece5630551ad97a3c3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 7 Aug 2016 09:45:39 -0400 Subject: core: add cgroup CPU controller support on the unified hierarchy Unfortunately, due to the disagreements in the kernel development community, CPU controller cgroup v2 support has not been merged and enabling it requires applying two small out-of-tree kernel patches. The situation is explained in the following documentation. https://git.kernel.org/cgit/linux/kernel/git/tj/cgroup.git/tree/Documentation/cgroup-v2-cpu.txt?h=cgroup-v2-cpu While it isn't clear what will happen with CPU controller cgroup v2 support, there are critical features which are possible only on cgroup v2 such as buffered write control making cgroup v2 essential for a lot of workloads. This commit implements systemd CPU controller support on the unified hierarchy so that users who choose to deploy CPU controller cgroup v2 support can easily take advantage of it. On the unified hierarchy, "cpu.weight" knob replaces "cpu.shares" and "cpu.max" replaces "cpu.cfs_period_us" and "cpu.cfs_quota_us". [Startup]CPUWeight config options are added with the usual compat translation. CPU quota settings remain unchanged and apply to both legacy and unified hierarchies. v2: - Error in man page corrected. - CPU config application in cgroup_context_apply() refactored. - CPU accounting now works on unified hierarchy. --- man/systemd.resource-control.xml | 98 ++++++++++------ src/basic/cgroup-util.c | 47 +++++++- src/basic/cgroup-util.h | 1 + src/cgtop/cgtop.c | 50 +++++++-- src/core/cgroup.c | 203 +++++++++++++++++++++++++++------- src/core/cgroup.h | 5 +- src/core/dbus-cgroup.c | 46 ++++++++ src/core/load-fragment-gperf.gperf.m4 | 2 + src/core/load-fragment.c | 29 +++++ src/core/load-fragment.h | 1 + src/core/unit.c | 6 +- src/core/unit.h | 4 +- src/shared/bus-unit-util.c | 11 ++ 13 files changed, 413 insertions(+), 90 deletions(-) diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index 0e98ca78b8..84dbfa2ff3 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -106,13 +106,21 @@ + - + - IO prefixed settings are superset of and replace BlockIO - prefixed ones. On unified hierarchy, IO resource control also applies to buffered writes. + Due to the lack of consensus in the kernel community, the CPU controller support on the unified + cgroup hierarchy requires out-of-tree kernel patches. See cgroup-v2-cpu.txt. + + CPUWeight= and StartupCPUWeight= replace + CPUShares= and StartupCPUShares=, respectively. + + The cpuacct controller does not exist separately on the unified hierarchy. + @@ -120,6 +128,15 @@ and MemoryHigh= are effective only on unified hierarchy. + + + + + IO prefixed settings are superset of and replace BlockIO + prefixed ones. On unified hierarchy, IO resource control also applies to buffered writes. + + + @@ -159,31 +176,50 @@ + + CPUWeight=weight + StartupCPUWeight=weight + + + Assign the specified CPU time weight to the processes executed, if the unified control group hierarchy + is used on the system. These options take an integer value and control the cpu.weight + control group attribute. The allowed range is 1 to 10000. Defaults to 100. For details about this control + group attribute, see cgroup-v2.txt and sched-design-CFS.txt. + The available CPU time is split up among all units within one slice relative to their CPU time weight. + + While StartupCPUWeight= only applies to the startup phase of the system, + CPUWeight= applies to normal runtime of the system, and if the former is not set also to + the startup phase. Using StartupCPUWeight= allows prioritizing specific services at + boot-up differently than during normal runtime. + + Implies CPUAccounting=true. + + These settings are supported only if the unified control group hierarchy is used. + + + CPUShares=weight StartupCPUShares=weight - Assign the specified CPU time share weight to the - processes executed. These options take an integer value and - control the cpu.shares control group - attribute. The allowed range is 2 to 262144. Defaults to - 1024. For details about this control group attribute, see - Assign the specified CPU time share weight to the processes executed. These options take an integer + value and control the cpu.shares control group attribute. The allowed range is 2 to + 262144. Defaults to 1024. For details about this control group attribute, see sched-design-CFS.txt. - The available CPU time is split up among all units within - one slice relative to their CPU time share weight. + The available CPU time is split up among all units within one slice relative to their CPU time share + weight. - While StartupCPUShares= only - applies to the startup phase of the system, - CPUShares= applies to normal runtime of - the system, and if the former is not set also to the startup - phase. Using StartupCPUShares= allows - prioritizing specific services at boot-up differently than - during normal runtime. + While StartupCPUShares= only applies to the startup phase of the system, + CPUShares= applies to normal runtime of the system, and if the former is not set also to + the startup phase. Using StartupCPUShares= allows prioritizing specific services at + boot-up differently than during normal runtime. - These options imply - CPUAccounting=true. + Implies CPUAccounting=true. + + These settings are supported only if the legacy control group hierarchy is used. @@ -191,22 +227,20 @@ CPUQuota= - Assign the specified CPU time quota to the processes - executed. Takes a percentage value, suffixed with "%". The - percentage specifies how much CPU time the unit shall get at - maximum, relative to the total CPU time available on one - CPU. Use values > 100% for allotting CPU time on more than - one CPU. This controls the - cpu.cfs_quota_us control group - attribute. For details about this control group attribute, - see Assign the specified CPU time quota to the processes executed. Takes a percentage value, suffixed with + "%". The percentage specifies how much CPU time the unit shall get at maximum, relative to the total CPU time + available on one CPU. Use values > 100% for allotting CPU time on more than one CPU. This controls the + cpu.max attribute on the unified control group hierarchy and + cpu.cfs_quota_us on legacy. For details about these control group attributes, see cgroup-v2.txt and sched-design-CFS.txt. - Example: CPUQuota=20% ensures that - the executed processes will never get more than 20% CPU time - on one CPU. + Example: CPUQuota=20% ensures that the executed processes will never get more than + 20% CPU time on one CPU. Implies CPUAccounting=true. + + This setting is supported on both unified and legacy control group hierarchies. diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 302b958d0d..25ef8a5c76 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1905,6 +1905,49 @@ int cg_get_attribute(const char *controller, const char *path, const char *attri return read_one_line_file(p, ret); } +int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, const char **keys, char **values) { + _cleanup_free_ char *filename = NULL, *content = NULL; + char *line, *p; + int i, r; + + for (i = 0; keys[i]; i++) + values[i] = NULL; + + r = cg_get_path(controller, path, attribute, &filename); + if (r < 0) + return r; + + r = read_full_file(filename, &content, NULL); + if (r < 0) + return r; + + p = content; + while ((line = strsep(&p, "\n"))) { + char *key; + + key = strsep(&line, " "); + + for (i = 0; keys[i]; i++) { + if (streq(key, keys[i])) { + values[i] = strdup(line); + break; + } + } + } + + for (i = 0; keys[i]; i++) { + if (!values[i]) { + for (i = 0; keys[i]; i++) { + free(values[i]); + values[i] = NULL; + } + return -ENOENT; + } + } + + return 0; +} + int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path) { CGroupController c; int r, unified; @@ -2101,10 +2144,10 @@ int cg_mask_supported(CGroupMask *ret) { mask |= CGROUP_CONTROLLER_TO_MASK(v); } - /* Currently, we only support the memory, io and pids + /* Currently, we support the cpu, memory, io and pids * controller in the unified hierarchy, mask * everything else off. */ - mask &= CGROUP_MASK_MEMORY | CGROUP_MASK_IO | CGROUP_MASK_PIDS; + mask &= CGROUP_MASK_CPU | CGROUP_MASK_MEMORY | CGROUP_MASK_IO | CGROUP_MASK_PIDS; } else { CGroupController c; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index ec5c715987..a509a1775c 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -169,6 +169,7 @@ int cg_create_and_attach(const char *controller, const char *path, pid_t pid); int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value); int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret); +int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, const char **keys, char **values); int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index c67b328b38..6045ae0437 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -208,24 +208,47 @@ static int process( if (g->n_tasks > 0) g->n_tasks_valid = true; - } else if (streq(controller, "cpuacct") && cg_unified() <= 0) { + } else if (streq(controller, "cpu") || streq(controller, "cpuacct")) { _cleanup_free_ char *p = NULL, *v = NULL; uint64_t new_usage; nsec_t timestamp; - r = cg_get_path(controller, path, "cpuacct.usage", &p); - if (r < 0) - return r; + if (cg_unified() > 0) { + const char *keys[] = { "usage_usec", NULL }; + _cleanup_free_ char *val = NULL; - r = read_one_line_file(p, &v); - if (r == -ENOENT) - return 0; - if (r < 0) - return r; + if (!streq(controller, "cpu")) + return 0; - r = safe_atou64(v, &new_usage); - if (r < 0) - return r; + r = cg_get_keyed_attribute("cpu", path, "cpu.stat", keys, &val); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + r = safe_atou64(val, &new_usage); + if (r < 0) + return r; + + new_usage *= NSEC_PER_USEC; + } else { + if (!streq(controller, "cpuacct")) + return 0; + + r = cg_get_path(controller, path, "cpuacct.usage", &p); + if (r < 0) + return r; + + r = read_one_line_file(p, &v); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + r = safe_atou64(v, &new_usage); + if (r < 0) + return r; + } timestamp = now_nsec(CLOCK_MONOTONIC); @@ -447,6 +470,9 @@ static int refresh(const char *root, Hashmap *a, Hashmap *b, unsigned iteration) assert(a); r = refresh_one(SYSTEMD_CGROUP_CONTROLLER, root, a, b, iteration, 0, NULL); + if (r < 0) + return r; + r = refresh_one("cpu", root, a, b, iteration, 0, NULL); if (r < 0) return r; r = refresh_one("cpuacct", root, a, b, iteration, 0, NULL); diff --git a/src/core/cgroup.c b/src/core/cgroup.c index c19e43f571..910a64b4da 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -57,9 +57,12 @@ void cgroup_context_init(CGroupContext *c) { /* Initialize everything to the kernel defaults, assuming the * structure is preinitialized to 0 */ + c->cpu_weight = CGROUP_WEIGHT_INVALID; + c->startup_cpu_weight = CGROUP_WEIGHT_INVALID; + c->cpu_quota_per_sec_usec = USEC_INFINITY; + c->cpu_shares = CGROUP_CPU_SHARES_INVALID; c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID; - c->cpu_quota_per_sec_usec = USEC_INFINITY; c->memory_high = CGROUP_LIMIT_MAX; c->memory_max = CGROUP_LIMIT_MAX; @@ -158,6 +161,8 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { "%sBlockIOAccounting=%s\n" "%sMemoryAccounting=%s\n" "%sTasksAccounting=%s\n" + "%sCPUWeight=%" PRIu64 "\n" + "%sStartupCPUWeight=%" PRIu64 "\n" "%sCPUShares=%" PRIu64 "\n" "%sStartupCPUShares=%" PRIu64 "\n" "%sCPUQuotaPerSecSec=%s\n" @@ -177,6 +182,8 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { prefix, yes_no(c->blockio_accounting), prefix, yes_no(c->memory_accounting), prefix, yes_no(c->tasks_accounting), + prefix, c->cpu_weight, + prefix, c->startup_cpu_weight, prefix, c->cpu_shares, prefix, c->startup_cpu_shares, prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1), @@ -382,6 +389,95 @@ fail: return -errno; } +static bool cgroup_context_has_cpu_weight(CGroupContext *c) { + return c->cpu_weight != CGROUP_WEIGHT_INVALID || + c->startup_cpu_weight != CGROUP_WEIGHT_INVALID; +} + +static bool cgroup_context_has_cpu_shares(CGroupContext *c) { + return c->cpu_shares != CGROUP_CPU_SHARES_INVALID || + c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID; +} + +static uint64_t cgroup_context_cpu_weight(CGroupContext *c, ManagerState state) { + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + c->startup_cpu_weight != CGROUP_WEIGHT_INVALID) + return c->startup_cpu_weight; + else if (c->cpu_weight != CGROUP_WEIGHT_INVALID) + return c->cpu_weight; + else + return CGROUP_WEIGHT_DEFAULT; +} + +static uint64_t cgroup_context_cpu_shares(CGroupContext *c, ManagerState state) { + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID) + return c->startup_cpu_shares; + else if (c->cpu_shares != CGROUP_CPU_SHARES_INVALID) + return c->cpu_shares; + else + return CGROUP_CPU_SHARES_DEFAULT; +} + +static void cgroup_apply_unified_cpu_config(Unit *u, uint64_t weight, uint64_t quota) { + char buf[MAX(DECIMAL_STR_MAX(uint64_t) + 1, (DECIMAL_STR_MAX(usec_t) + 1) * 2)]; + int r; + + xsprintf(buf, "%" PRIu64 "\n", weight); + r = cg_set_attribute("cpu", u->cgroup_path, "cpu.weight", buf); + if (r < 0) + log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to set cpu.weight: %m"); + + if (quota != USEC_INFINITY) + xsprintf(buf, USEC_FMT " " USEC_FMT "\n", + quota * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC, CGROUP_CPU_QUOTA_PERIOD_USEC); + else + xsprintf(buf, "max " USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC); + + r = cg_set_attribute("cpu", u->cgroup_path, "cpu.max", buf); + + if (r < 0) + log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to set cpu.max: %m"); +} + +static void cgroup_apply_legacy_cpu_config(Unit *u, uint64_t shares, uint64_t quota) { + char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1]; + int r; + + xsprintf(buf, "%" PRIu64 "\n", shares); + r = cg_set_attribute("cpu", u->cgroup_path, "cpu.shares", buf); + if (r < 0) + log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to set cpu.shares: %m"); + + xsprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC); + r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_period_us", buf); + if (r < 0) + log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to set cpu.cfs_period_us: %m"); + + if (quota != USEC_INFINITY) { + xsprintf(buf, USEC_FMT "\n", quota * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC); + r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_quota_us", buf); + } else + r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_quota_us", "-1"); + if (r < 0) + log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to set cpu.cfs_quota_us: %m"); +} + +static uint64_t cgroup_cpu_shares_to_weight(uint64_t shares) { + return CLAMP(shares * CGROUP_WEIGHT_DEFAULT / CGROUP_CPU_SHARES_DEFAULT, + CGROUP_WEIGHT_MIN, CGROUP_WEIGHT_MAX); +} + +static uint64_t cgroup_cpu_weight_to_shares(uint64_t weight) { + return CLAMP(weight * CGROUP_CPU_SHARES_DEFAULT / CGROUP_WEIGHT_DEFAULT, + CGROUP_CPU_SHARES_MIN, CGROUP_CPU_SHARES_MAX); +} + static bool cgroup_context_has_io_config(CGroupContext *c) { return c->io_accounting || c->io_weight != CGROUP_WEIGHT_INVALID || @@ -566,30 +662,42 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { * and missing cgroups, i.e. EROFS and ENOENT. */ if ((mask & CGROUP_MASK_CPU) && !is_root) { - char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1]; + bool has_weight = cgroup_context_has_cpu_weight(c); + bool has_shares = cgroup_context_has_cpu_shares(c); - sprintf(buf, "%" PRIu64 "\n", - IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->startup_cpu_shares : - c->cpu_shares != CGROUP_CPU_SHARES_INVALID ? c->cpu_shares : CGROUP_CPU_SHARES_DEFAULT); - r = cg_set_attribute("cpu", path, "cpu.shares", buf); - if (r < 0) - log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, - "Failed to set cpu.shares: %m"); + if (cg_unified() > 0) { + uint64_t weight; - sprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC); - r = cg_set_attribute("cpu", path, "cpu.cfs_period_us", buf); - if (r < 0) - log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, - "Failed to set cpu.cfs_period_us: %m"); + if (has_weight) + weight = cgroup_context_cpu_weight(c, state); + else if (has_shares) { + uint64_t shares = cgroup_context_cpu_shares(c, state); - 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"); - if (r < 0) - log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, - "Failed to set cpu.cfs_quota_us: %m"); + weight = cgroup_cpu_shares_to_weight(shares); + + log_cgroup_compat(u, "Applying [Startup]CpuShares %" PRIu64 " as [Startup]CpuWeight %" PRIu64 " on %s", + shares, weight, path); + } else + weight = CGROUP_WEIGHT_DEFAULT; + + cgroup_apply_unified_cpu_config(u, weight, c->cpu_quota_per_sec_usec); + } else { + uint64_t shares; + + if (has_shares) + shares = cgroup_context_cpu_shares(c, state); + else if (has_weight) { + uint64_t weight = cgroup_context_cpu_weight(c, state); + + shares = cgroup_cpu_weight_to_shares(weight); + + log_cgroup_compat(u, "Applying [Startup]CpuWeight %" PRIu64 " as [Startup]CpuShares %" PRIu64 " on %s", + weight, shares, path); + } else + shares = CGROUP_CPU_SHARES_DEFAULT; + + cgroup_apply_legacy_cpu_config(u, shares, c->cpu_quota_per_sec_usec); + } } if (mask & CGROUP_MASK_IO) { @@ -864,8 +972,8 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) { /* Figure out which controllers we need */ if (c->cpu_accounting || - c->cpu_shares != CGROUP_CPU_SHARES_INVALID || - c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID || + cgroup_context_has_cpu_weight(c) || + cgroup_context_has_cpu_shares(c) || c->cpu_quota_per_sec_usec != USEC_INFINITY) mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU; @@ -1890,18 +1998,37 @@ static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) { if (!u->cgroup_path) return -ENODATA; - if ((u->cgroup_realized_mask & CGROUP_MASK_CPUACCT) == 0) - return -ENODATA; + if (cg_unified() > 0) { + const char *keys[] = { "usage_usec", NULL }; + _cleanup_free_ char *val = NULL; + uint64_t us; - r = cg_get_attribute("cpuacct", u->cgroup_path, "cpuacct.usage", &v); - if (r == -ENOENT) - return -ENODATA; - if (r < 0) - return r; + if ((u->cgroup_realized_mask & CGROUP_MASK_CPU) == 0) + return -ENODATA; - r = safe_atou64(v, &ns); - if (r < 0) - return r; + r = cg_get_keyed_attribute("cpu", u->cgroup_path, "cpu.stat", keys, &val); + if (r < 0) + return r; + + r = safe_atou64(val, &us); + if (r < 0) + return r; + + ns = us * NSEC_PER_USEC; + } else { + if ((u->cgroup_realized_mask & CGROUP_MASK_CPUACCT) == 0) + return -ENODATA; + + r = cg_get_attribute("cpuacct", u->cgroup_path, "cpuacct.usage", &v); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + + r = safe_atou64(v, &ns); + if (r < 0) + return r; + } *ret = ns; return 0; @@ -1915,8 +2042,8 @@ int unit_get_cpu_usage(Unit *u, nsec_t *ret) { if (r < 0) return r; - if (ns > u->cpuacct_usage_base) - ns -= u->cpuacct_usage_base; + if (ns > u->cpu_usage_base) + ns -= u->cpu_usage_base; else ns = 0; @@ -1932,11 +2059,11 @@ int unit_reset_cpu_usage(Unit *u) { r = unit_get_cpu_usage_raw(u, &ns); if (r < 0) { - u->cpuacct_usage_base = 0; + u->cpu_usage_base = 0; return r; } - u->cpuacct_usage_base = ns; + u->cpu_usage_base = ns; return 0; } diff --git a/src/core/cgroup.h b/src/core/cgroup.h index a57403e79f..2fe9cc4039 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -89,6 +89,10 @@ struct CGroupContext { bool tasks_accounting; /* For unified hierarchy */ + uint64_t cpu_weight; + uint64_t startup_cpu_weight; + usec_t cpu_quota_per_sec_usec; + uint64_t io_weight; uint64_t startup_io_weight; LIST_HEAD(CGroupIODeviceWeight, io_device_weights); @@ -101,7 +105,6 @@ struct CGroupContext { /* For legacy hierarchies */ uint64_t cpu_shares; uint64_t startup_cpu_shares; - usec_t cpu_quota_per_sec_usec; uint64_t blockio_weight; uint64_t startup_blockio_weight; diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 85b0c86a2f..2ca80d2996 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -210,6 +210,8 @@ const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0), SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0), + SD_BUS_PROPERTY("CPUWeight", "t", NULL, offsetof(CGroupContext, cpu_weight), 0), + SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL, offsetof(CGroupContext, startup_cpu_weight), 0), SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0), SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0), SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0), @@ -303,6 +305,50 @@ int bus_cgroup_set_property( return 1; + } else if (streq(name, "CPUWeight")) { + uint64_t weight; + + r = sd_bus_message_read(message, "t", &weight); + if (r < 0) + return r; + + if (!CGROUP_WEIGHT_IS_OK(weight)) + return sd_bus_error_set_errnof(error, EINVAL, "CPUWeight value out of range"); + + if (mode != UNIT_CHECK) { + c->cpu_weight = weight; + unit_invalidate_cgroup(u, CGROUP_MASK_CPU); + + if (weight == CGROUP_WEIGHT_INVALID) + unit_write_drop_in_private(u, mode, name, "CPUWeight="); + else + unit_write_drop_in_private_format(u, mode, name, "CPUWeight=%" PRIu64, weight); + } + + return 1; + + } else if (streq(name, "StartupCPUWeight")) { + uint64_t weight; + + r = sd_bus_message_read(message, "t", &weight); + if (r < 0) + return r; + + if (!CGROUP_WEIGHT_IS_OK(weight)) + return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUWeight value out of range"); + + if (mode != UNIT_CHECK) { + c->startup_cpu_weight = weight; + unit_invalidate_cgroup(u, CGROUP_MASK_CPU); + + if (weight == CGROUP_CPU_SHARES_INVALID) + unit_write_drop_in_private(u, mode, name, "StartupCPUWeight="); + else + unit_write_drop_in_private_format(u, mode, name, "StartupCPUWeight=%" PRIu64, weight); + } + + return 1; + } else if (streq(name, "CPUShares")) { uint64_t shares; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 396f847213..edcfa6fa1b 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -121,6 +121,8 @@ $1.KillSignal, config_parse_signal, 0, m4_define(`CGROUP_CONTEXT_CONFIG_ITEMS', `$1.Slice, config_parse_unit_slice, 0, 0 $1.CPUAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.cpu_accounting) +$1.CPUWeight, config_parse_cpu_weight, 0, offsetof($1, cgroup_context.cpu_weight) +$1.StartupCPUWeight, config_parse_cpu_weight, 0, offsetof($1, cgroup_context.startup_cpu_weight) $1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares) $1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares) $1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 420f368689..4ad6c4d79b 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2851,6 +2851,34 @@ int config_parse_unit_slice( DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy"); +int config_parse_cpu_weight( + 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) { + + uint64_t *weight = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = cg_weight_parse(rvalue, weight); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "CPU weight '%s' invalid. Ignoring.", rvalue); + return 0; + } + + return 0; +} + int config_parse_cpu_shares( const char *unit, const char *filename, @@ -4191,6 +4219,7 @@ void unit_dump_config_items(FILE *f) { { config_parse_address_families, "FAMILIES" }, #endif { config_parse_cpu_shares, "SHARES" }, + { config_parse_cpu_weight, "WEIGHT" }, { config_parse_memory_limit, "LIMIT" }, { config_parse_device_allow, "DEVICE" }, { config_parse_device_policy, "POLICY" }, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 213bce55a7..8b688740cf 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -81,6 +81,7 @@ int config_parse_syscall_errno(const char *unit, const char *filename, unsigned int config_parse_environ(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_pass_environ(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_unit_slice(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_cpu_weight(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_cpu_shares(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_memory_limit(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_tasks_max(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); diff --git a/src/core/unit.c b/src/core/unit.c index ff7c562fba..952604e0db 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2608,7 +2608,7 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { unit_serialize_item(u, f, "assert-result", yes_no(u->assert_result)); unit_serialize_item(u, f, "transient", yes_no(u->transient)); - unit_serialize_item_format(u, f, "cpuacct-usage-base", "%" PRIu64, u->cpuacct_usage_base); + unit_serialize_item_format(u, f, "cpu-usage-base", "%" PRIu64, u->cpu_usage_base); if (u->cgroup_path) unit_serialize_item(u, f, "cgroup", u->cgroup_path); @@ -2824,9 +2824,9 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { continue; - } else if (streq(l, "cpuacct-usage-base")) { + } else if (streq(l, "cpu-usage-base") || streq(l, "cpuacct-usage-base")) { - r = safe_atou64(v, &u->cpuacct_usage_base); + r = safe_atou64(v, &u->cpu_usage_base); if (r < 0) log_unit_debug(u, "Failed to parse CPU usage %s, ignoring.", v); diff --git a/src/core/unit.h b/src/core/unit.h index 47eb8d50a6..a6c69938dd 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -184,8 +184,8 @@ struct Unit { UnitFileState unit_file_state; int unit_file_preset; - /* Where the cpuacct.usage cgroup counter was at the time the unit was started */ - nsec_t cpuacct_usage_base; + /* Where the cpu.stat or cpuacct.usage was at the time the unit was started */ + nsec_t cpu_usage_base; /* Counterparts in the cgroup filesystem */ char *cgroup_path; diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index c3a5233532..bb98951a06 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -212,6 +212,17 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "v", "b", r); + } else if (STR_IN_SET(field, "CPUWeight", "StartupCPUWeight")) { + uint64_t u; + + r = cg_weight_parse(eq, &u); + if (r < 0) { + log_error("Failed to parse %s value %s.", field, eq); + return -EINVAL; + } + + r = sd_bus_message_append(m, "v", "t", u); + } else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) { uint64_t u; -- cgit v1.2.3-54-g00ecf From 3f193af8807be50913b87e1a5b88c494f8985667 Mon Sep 17 00:00:00 2001 From: romanstingler Date: Sun, 7 Aug 2016 17:45:44 +0200 Subject: hwdb: add multimedia keys for Medion Akoya series (#3918) --- hwdb/60-keyboard.hwdb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb index fd49b03493..1f96d9e3cc 100644 --- a/hwdb/60-keyboard.hwdb +++ b/hwdb/60-keyboard.hwdb @@ -797,6 +797,14 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMAXDATA:pnPro*7000*:pvr* # Medion ########################################################### +# Akoya +evdev:atkbd:dmi:bvn*:bvr*:svnMedion*:pnAkoya*:pvr* + KEYBOARD_KEY_a0=!mute + KEYBOARD_KEY_ae=!volumedown + KEYBOARD_KEY_b0=!volumeup + KEYBOARD_KEY_19=!p + KEYBOARD_KEY_df=sleep + # FID2060 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMEDION*:pn*FID2060*:pvr* KEYBOARD_KEY_6b=channeldown # Thottle Down -- cgit v1.2.3-54-g00ecf From 06a70b918d4d753769a727239f75af8896006467 Mon Sep 17 00:00:00 2001 From: Mantas Mikulėnas Date: Mon, 8 Aug 2016 11:07:38 +0300 Subject: Revert "logind: really handle *KeyIgnoreInhibited options in logind.conf" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 8121f4d209eca85dcb11830800483cdfafbef9b7. The special 'key handling' inhibitors should always work regardless of any *IgnoreInhibited settings – otherwise they're nearly useless. Reverts: #3470 Fixes: #3897 --- src/login/logind-action.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/login/logind-action.c b/src/login/logind-action.c index 8ef48dbaa1..a950409254 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -85,7 +85,7 @@ int manager_handle_action( } /* If the key handling is inhibited, don't do anything */ - if (!ignore_inhibited && inhibit_key > 0) { + if (inhibit_key > 0) { if (manager_is_inhibited(m, inhibit_key, INHIBIT_BLOCK, NULL, true, false, 0, NULL)) { log_debug("Refusing operation, %s is inhibited.", inhibit_what_to_string(inhibit_key)); return 0; -- cgit v1.2.3-54-g00ecf From 87da8a864fd2173e176eb8b2f09b27711f1d3b5e Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 8 Aug 2016 17:39:16 -0400 Subject: core: amend policy to open up dynamic user queries (#3920) --- src/core/org.freedesktop.systemd1.conf | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index 3c64f20872..14f6aec029 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -108,6 +108,14 @@ send_interface="org.freedesktop.systemd1.Manager" send_member="GetDefaultTarget"/> + + + + Date: Tue, 9 Aug 2016 08:58:19 +1000 Subject: hwdb: fix duplicate entry for Apple touchpads (#3921) Copy-paste error, correct IDs from the kernel's drivers/input/mouse/bcm5974.c Fixes: https://github.com/systemd/systemd/pull/3906/ --- hwdb/60-evdev.hwdb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb index d4cd61c24d..4d14a6a2f4 100644 --- a/hwdb/60-evdev.hwdb +++ b/hwdb/60-evdev.hwdb @@ -76,9 +76,9 @@ evdev:input:b0003v05ACp0254* EVDEV_ABS_36=::92 # MacbookPro10,1 (unibody, June 2012) -evdev:input:b0003v05ACp0259* -evdev:input:b0003v05ACp025A* -evdev:input:b0003v05ACp025B* +evdev:input:b0003v05ACp0262* +evdev:input:b0003v05ACp0263* +evdev:input:b0003v05ACp0264* # MacbookPro10,2 (unibody, October 2012) evdev:input:b0003v05ACp0259* evdev:input:b0003v05ACp025A* -- cgit v1.2.3-54-g00ecf From 5a507f8cce8b8557a916c68ec277851f311b035c Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Mon, 8 Aug 2016 21:35:07 -0700 Subject: journal-gatewayd: fix typo; s/Certificat/Certificate/ (#3931) --- src/journal-remote/journal-gatewayd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index 05c8698f78..c2b5a5f205 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -885,7 +885,7 @@ static void help(void) { " --version Show package version\n" " --cert=CERT.PEM Server certificate in PEM format\n" " --key=KEY.PEM Server key in PEM format\n" - " --trust=CERT.PEM Certificat authority certificate in PEM format\n" + " --trust=CERT.PEM Certificate authority certificate in PEM format\n" " -D --directory=PATH Serve journal files in directory\n", program_invocation_short_name); } -- cgit v1.2.3-54-g00ecf From 3d431503b3d2753dba8148896301228c3068e38c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 5 Aug 2016 10:52:21 -0400 Subject: hwdb: remove extra spaces --- hwdb/70-mouse.hwdb | 2 +- hwdb/70-pointingstick.hwdb | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb index b68c01066e..62bb77a0ef 100644 --- a/hwdb/70-mouse.hwdb +++ b/hwdb/70-mouse.hwdb @@ -297,7 +297,7 @@ mouse:usb:v046dpc049:name:Logitech USB Gaming Mouse: mouse:usb:v046dpc24e:name:Logitech G500s Laser Gaming Mouse: MOUSE_DPI=400@500 *800@500 2000@500 - # Logitech G9 +# Logitech G9 mouse:usb:v046dpc048:name:Logitech G9 Laser Mouse: MOUSE_DPI=400@1000 800@1000 *1600@1000 diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index c0ec8ffbe0..5e2ab393bd 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -77,15 +77,15 @@ # Latitude D620 evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeD620*:pvr* - POINTINGSTICK_CONST_ACCEL=0.5 + POINTINGSTICK_CONST_ACCEL=0.5 # Latitude E6320 evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320*:pvr* - POINTINGSTICK_CONST_ACCEL=2.0 + POINTINGSTICK_CONST_ACCEL=2.0 # Latitude E6400 evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6400*:pvr* - POINTINGSTICK_CONST_ACCEL=1.5 + POINTINGSTICK_CONST_ACCEL=1.5 ######################################### # Lenovo @@ -108,13 +108,13 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??60 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:* # Lenovo Thinkpad X1 Carbon 4th gen evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon4th:* - POINTINGSTICK_SENSITIVITY=200 - POINTINGSTICK_CONST_ACCEL=1.0 + POINTINGSTICK_SENSITIVITY=200 + POINTINGSTICK_CONST_ACCEL=1.0 # Lenovo Thinkpad X200s / X201s # Note these come with 2 revisions of keyboard, with the trackpoints having a # different sensitivity in the different revisions. 1.25 is a bit slow for the # least sensitive revision, but it is better to be a bit slow than too fast. evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX20?s:* - POINTINGSTICK_SENSITIVITY=200 - POINTINGSTICK_CONST_ACCEL=1.25 + POINTINGSTICK_SENSITIVITY=200 + POINTINGSTICK_CONST_ACCEL=1.25 -- cgit v1.2.3-54-g00ecf From 40e7518b03408f643e1cf41b0808e3bd9ba2c00b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 5 Aug 2016 13:33:22 -0400 Subject: hwdb: indent commented properties This way it's clear that the property block does not end at the comment. The python checker will complain if this is not the case. We had a few bugs before where two match blocks were merged by mistake, and this change should help avoid that. --- hwdb/60-keyboard.hwdb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb index 1f96d9e3cc..16f29b820a 100644 --- a/hwdb/60-keyboard.hwdb +++ b/hwdb/60-keyboard.hwdb @@ -482,8 +482,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnFalco:pvr* KEYBOARD_KEY_43=volumedown KEYBOARD_KEY_44=volumeup KEYBOARD_KEY_db=search # Same position as caps lock key on most keyboards -# KEYBOARD_KEY_3e=fullscreen, no defined key sym - + # KEYBOARD_KEY_3e=fullscreen, no defined key sym # HP EliteBook 725 G2 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPLicrice:pvr* -- cgit v1.2.3-54-g00ecf From 0c9836c0cf93235c324e59235d7b4fe40e7e0594 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 5 Aug 2016 10:53:06 -0400 Subject: tests: add python parser for hwdb grammar This works for hwdb/[67]0-*.hwdb. I also added code to parse hwdb/20-*, but those files are huge, and parsing them using this parser is annoyingly slow (about one minute for the biggest files). So I removed the support for hwdb/20-*, a much simpler hand-generated parser should suffice for those. Current output: hwdb/60-evdev.hwdb: 24 match groups, 35 matches, 88 properties, 0.19323015213012695s to parse Match 'evdev:input:b0003v05ACp0259*' is duplicated Match 'evdev:input:b0003v05ACp025A*' is duplicated Match 'evdev:input:b0003v05ACp025B*' is duplicated hwdb/60-keyboard.hwdb: 122 match groups, 188 matches, 638 properties, 1.0906572341918945s to parse Failed to parse: 'KEYBOARD_KEY_8F=switchvideomode' Failed to parse: 'KEYBOARD_KEY_C0183=media' Failed to parse: 'KEYBOARD_KEY_C0201=new' Failed to parse: 'KEYBOARD_KEY_C0289=reply' Failed to parse: 'KEYBOARD_KEY_C028B=forwardmail' Failed to parse: 'KEYBOARD_KEY_C028C=send' Failed to parse: 'KEYBOARD_KEY_C021A=undo' Failed to parse: 'KEYBOARD_KEY_C0279=redo' Failed to parse: 'KEYBOARD_KEY_C0208=print' Failed to parse: 'KEYBOARD_KEY_C0207=save' Failed to parse: 'KEYBOARD_KEY_C0194=file' Failed to parse: 'KEYBOARD_KEY_C01A7=documents' Failed to parse: 'KEYBOARD_KEY_C01B6=images' Failed to parse: 'KEYBOARD_KEY_C01B7=sound' Property KEYBOARD_KEY_c7 is duplicated Failed to parse: 'KEYBOARD_KEY_cF=end' hwdb/70-mouse.hwdb: 62 match groups, 93 matches, 68 properties, 0.34186625480651855s to parse Match 'mouse:usb:v046dpc51b:name:Logitech USB Receiver:' is duplicated hwdb/70-pointingstick.hwdb: 5 match groups, 14 matches, 7 properties, 0.06518816947937012s to parse hwdb/70-touchpad.hwdb: 3 match groups, 5 matches, 3 properties, 0.039690494537353516s to parse Subsequest commits will clean those issues up. --- hwdb/parse_hwdb.py | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 hwdb/parse_hwdb.py diff --git a/hwdb/parse_hwdb.py b/hwdb/parse_hwdb.py new file mode 100644 index 0000000000..773513eaf0 --- /dev/null +++ b/hwdb/parse_hwdb.py @@ -0,0 +1,177 @@ +# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ +# +# This file is part of systemd. +# +# Copyright 2016 Zbigniew Jędrzejewski-Szmek +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +import sys +import string +import functools + +try: + from pyparsing import (Word, White, Literal, ParserElement, Regex, + LineStart, LineEnd, + ZeroOrMore, OneOrMore, Combine, Or, Optional, Suppress, Group, + nums, alphanums, printables, + stringEnd, pythonStyleComment, + ParseBaseException) +except ImportError: + sys.exit('pyparsing is not available') + +try: + from evdev.ecodes import ecodes +except ImportError: + ecodes = None + print('WARNING: evdev is not available') + +EOL = LineEnd().suppress() +EMPTYLINE = LineStart() + LineEnd() +COMMENTLINE = pythonStyleComment + EOL +INTEGER = Word(nums) +REAL = Combine((INTEGER + Optional('.' + Optional(INTEGER))) ^ ('.' + INTEGER)) +UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_') + +TYPES = {'mouse': ('usb', 'bluetooth', 'ps2', '*'), + 'evdev': ('name', 'atkbd', 'input'), + 'touchpad': ('i8042', 'rmi', 'bluetooth', 'usb'), + 'keyboard': ('name', ), + } + +@functools.lru_cache() +def hwdb_grammar(): + ParserElement.setDefaultWhitespaceChars('') + + prefix = Or(category + ':' + Or(conn) + ':' + for category, conn in TYPES.items()) + matchline = Combine(prefix + Word(printables + ' ' + '®')) + EOL + propertyline = (White(' ', exact=1).suppress() + + Combine(UDEV_TAG - '=' - Word(alphanums + '_=:@*.! ') - Optional(pythonStyleComment)) + + EOL) + propertycomment = White(' ', exact=1) + pythonStyleComment + EOL + + group = (OneOrMore(matchline('MATCHES*') ^ COMMENTLINE.suppress()) - + OneOrMore(propertyline('PROPERTIES*') ^ propertycomment.suppress()) - + (EMPTYLINE ^ stringEnd()).suppress() ) + commentgroup = OneOrMore(COMMENTLINE).suppress() - EMPTYLINE.suppress() + + grammar = OneOrMore(group('GROUPS*') ^ commentgroup) + stringEnd() + + return grammar + +@functools.lru_cache() +def property_grammar(): + ParserElement.setDefaultWhitespaceChars(' ') + + setting = Optional('*')('DEFAULT') + INTEGER('DPI') + Suppress('@') + INTEGER('HZ') + props = (('MOUSE_DPI', Group(OneOrMore(setting('SETTINGS*')))), + ('MOUSE_WHEEL_CLICK_ANGLE', INTEGER), + ('ID_INPUT_TRACKBALL', Literal('1')), + ('POINTINGSTICK_SENSITIVITY', INTEGER), + ('POINTINGSTICK_CONST_ACCEL', REAL), + ('ID_INPUT_TOUCHPAD_INTEGRATION', Or(('internal', 'external'))), + ) + fixed_props = [Literal(name)('NAME') - Suppress('=') - val('VALUE') + for name, val in props] + kbd_props = [Regex(r'KEYBOARD_KEY_[0-9a-f]+')('NAME') + - Suppress('=') - + ('!' ^ (Optional('!') - Word(alphanums + '_')))('VALUE') + ] + abs_props = [Regex(r'EVDEV_ABS_[0-9a-f]{2}')('NAME') + - Suppress('=') - + Word(nums + ':')('VALUE') + ] + + grammar = Or(fixed_props + kbd_props + abs_props) + + return grammar + +ERROR = False +def error(fmt, *args, **kwargs): + global ERROR + ERROR = True + print(fmt.format(*args, **kwargs)) + +def convert_properties(group): + matches = [m[0] for m in group.MATCHES] + props = [p[0] for p in group.PROPERTIES] + return matches, props + +def parse(fname): + grammar = hwdb_grammar() + try: + parsed = grammar.parseFile(fname) + except ParseBaseException as e: + error('Cannot parse {}: {}', fname, e) + return [] + return [convert_properties(g) for g in parsed.GROUPS] + +def check_match_uniqueness(groups): + matches = sum((group[0] for group in groups), []) + matches.sort() + prev = None + for match in matches: + if match == prev: + error('Match {!r} is duplicated', match) + prev = match + +def check_one_default(prop, settings): + defaults = [s for s in settings if s.DEFAULT] + if len(defaults) > 1: + error('More than one star entry: {!r}', prop) + +def check_one_keycode(prop, value): + if value != '!' and ecodes is not None: + key = 'KEY_' + value.upper() + if key not in ecodes: + error('Keycode {} unknown', key) + +def check_properties(groups): + grammar = property_grammar() + for matches, props in groups: + prop_names = set() + for prop in props: + # print('--', prop) + prop = prop.partition('#')[0].rstrip() + try: + parsed = grammar.parseString(prop) + except ParseBaseException as e: + error('Failed to parse: {!r}', prop) + continue + # print('{!r}'.format(parsed)) + if parsed.NAME in prop_names: + error('Property {} is duplicated', parsed.NAME) + prop_names.add(parsed.NAME) + if parsed.NAME == 'MOUSE_DPI': + check_one_default(prop, parsed.VALUE.SETTINGS) + elif parsed.NAME.startswith('KEYBOARD_KEY_'): + check_one_keycode(prop, parsed.VALUE) + +def print_summary(fname, groups): + print('{}: {} match groups, {} matches, {} properties' + .format(fname, + len(groups), + sum(len(matches) for matches, props in groups), + sum(len(props) for matches, props in groups), + )) + +if __name__ == '__main__': + for fname in sys.argv[1:]: + groups = parse(fname) + print_summary(fname, groups) + check_match_uniqueness(groups) + check_properties(groups) + + sys.exit(ERROR) -- cgit v1.2.3-54-g00ecf From 704c3aa9e8b98956b3919ac4b2aa18d1cae1f2a4 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 4 Aug 2016 15:31:05 -0400 Subject: hwdb: remove duplicated matches for old Logitech unifying receiver Quoting https://github.com/systemd/systemd/pull/3906#discussion_r73828368: > According to > http://support.logitech.com/en_us/product/v220-cordless-optical-mouse-for-notebooks > it seems the mouse is using a pre-version of the small unifying receiver we > know now. If there are 2 mice with the same receiver, that means that the > values should both be dropped IMO. --- hwdb/70-mouse.hwdb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb index 62bb77a0ef..73df25def1 100644 --- a/hwdb/70-mouse.hwdb +++ b/hwdb/70-mouse.hwdb @@ -342,8 +342,6 @@ mouse:usb:v046dp402d:name:Logitech M560: mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:402d: MOUSE_DPI=1000@125 -# Logitech V220 Cordless Optical Mouse -mouse:usb:v046dpc51b:name:Logitech USB Receiver: # Logitech Performance MX mouse:usb:v046dp101a:name:Logitech Performance MX: # Logitech MX Master @@ -373,11 +371,6 @@ mouse:usb:v046dp4027:name:Logitech T620: mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4027: MOUSE_DPI=1200@250 -# Logitech LX8 Cordless Laser Mouse -mouse:usb:v046dpc51b:name:Logitech USB Receiver: - MOUSE_DPI=1300@125 - MOUSE_WHEEL_CLICK_ANGLE=15 - # Logitech ZoneTouch Mouse T400 mouse:usb:v046dp4026:name:Logitech T400: mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4026: -- cgit v1.2.3-54-g00ecf From 3ab779475759277e4a0f1289bc2a1d83ca1b5d39 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 5 Aug 2016 13:31:37 -0400 Subject: hwdb: use lowercase hex for key numbers It seems awkward to have both cases mixes. Note that the real parser accepts both cases, and this only standarizes the usage in the systemd database. --- hwdb/60-keyboard.hwdb | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb index 16f29b820a..cf340ee702 100644 --- a/hwdb/60-keyboard.hwdb +++ b/hwdb/60-keyboard.hwdb @@ -213,7 +213,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pn* KEYBOARD_KEY_8a=suspend # Fn+F1 hibernate KEYBOARD_KEY_8b=switchvideomode # Fn+F8 CRT/LCD (high keycode: "displaytoggle") KEYBOARD_KEY_8c=unknown # Fn+Right Auto Brightness - KEYBOARD_KEY_8F=switchvideomode # Fn+F7 aspect ratio + KEYBOARD_KEY_8f=switchvideomode # Fn+F7 aspect ratio KEYBOARD_KEY_90=previoussong # Front panel previous song KEYBOARD_KEY_91=prog1 # Wi-Fi Catcher (Dell-specific) KEYBOARD_KEY_92=media # MediaDirect button (house icon) @@ -693,7 +693,7 @@ evdev:input:b0003v046DpC308* KEYBOARD_KEY_90003=finance # Finance KEYBOARD_KEY_90004=prog1 # My Sites KEYBOARD_KEY_90005=prog2 # Community - KEYBOARD_KEY_C0183=media # Media + KEYBOARD_KEY_c0183=media # Media # Cordless Desktop S510 evdev:input:b0003v046DpC50C* @@ -762,18 +762,18 @@ evdev:input:b0003v046DpC309* KEYBOARD_KEY_90002=camera # webcam KEYBOARD_KEY_90003=prog1 # iTouch KEYBOARD_KEY_90004=shop # Shopping - KEYBOARD_KEY_C0201=new # New (F1) - KEYBOARD_KEY_C0289=reply # Reply mail (F2) - KEYBOARD_KEY_C028B=forwardmail # Forward mail (F3) - KEYBOARD_KEY_C028C=send # Send (F4) - KEYBOARD_KEY_C021A=undo # Undo (F5). - KEYBOARD_KEY_C0279=redo # Redo (F6). - KEYBOARD_KEY_C0208=print # Print (F7) - KEYBOARD_KEY_C0207=save # Save (F8) - KEYBOARD_KEY_C0194=file # My Computer (F9) - KEYBOARD_KEY_C01A7=documents # My Documents (F10) - KEYBOARD_KEY_C01B6=images # My Pictures (F11) ?? - KEYBOARD_KEY_C01B7=sound # My Music (F12) ?? + KEYBOARD_KEY_c0201=new # New (F1) + KEYBOARD_KEY_c0289=reply # Reply mail (F2) + KEYBOARD_KEY_c028b=forwardmail # Forward mail (F3) + KEYBOARD_KEY_c028c=send # Send (F4) + KEYBOARD_KEY_c021a=undo # Undo (F5). + KEYBOARD_KEY_c0279=redo # Redo (F6). + KEYBOARD_KEY_c0208=print # Print (F7) + KEYBOARD_KEY_c0207=save # Save (F8) + KEYBOARD_KEY_c0194=file # My Computer (F9) + KEYBOARD_KEY_c01a7=documents # My Documents (F10) + KEYBOARD_KEY_c01b6=images # My Pictures (F11) ?? + KEYBOARD_KEY_c01b7=sound # My Music (F12) ?? ########################################################### @@ -916,7 +916,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOLPC:pnXO:* KEYBOARD_KEY_c9=pageup KEYBOARD_KEY_d1=pagedown KEYBOARD_KEY_c7=home - KEYBOARD_KEY_cF=end + KEYBOARD_KEY_cf=end KEYBOARD_KEY_73=hp KEYBOARD_KEY_7e=hp KEYBOARD_KEY_db=leftmeta # left grab -- cgit v1.2.3-54-g00ecf From 2abd461344f3a4d37584795a2644c102c098edc8 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 5 Aug 2016 13:36:26 -0400 Subject: hwdb: comment out a duplicated key for the XO It's hard to say which one of the two mappings should stay. But the later one would win (when both very present), and nobody complained, so let's assume that that's the one. --- hwdb/60-keyboard.hwdb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb index cf340ee702..1176881650 100644 --- a/hwdb/60-keyboard.hwdb +++ b/hwdb/60-keyboard.hwdb @@ -896,7 +896,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOLPC:pnXO:* KEYBOARD_KEY_c2=f8 KEYBOARD_KEY_c3=f9 KEYBOARD_KEY_c4=f10 - KEYBOARD_KEY_c7=f11 + # KEYBOARD_KEY_c7=f11 # FIXME! KEYBOARD_KEY_d8=f12 KEYBOARD_KEY_f7=f13 KEYBOARD_KEY_f6=f14 -- cgit v1.2.3-54-g00ecf From c3f6a561e2fcda5b41569e7bf7785fad825d3a72 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 5 Aug 2016 15:07:41 -0400 Subject: build-sys: hook up the hwdb parser to check --- Makefile.am | 6 ++++-- hwdb/parse_hwdb.py | 14 ++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) mode change 100644 => 100755 hwdb/parse_hwdb.py diff --git a/Makefile.am b/Makefile.am index bf853c8f90..d4e3e9a013 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3872,7 +3872,8 @@ TESTS += \ if HAVE_PYTHON TESTS += \ - test/rule-syntax-check.py + test/rule-syntax-check.py \ + hwdb/parse_hwdb.py if HAVE_SYSV_COMPAT TESTS += \ @@ -3924,7 +3925,8 @@ EXTRA_DIST += \ test/udev-test.pl \ test/rule-syntax-check.py \ test/sysv-generator-test.py \ - test/mocks/fsck + test/mocks/fsck \ + hwdb/parse_hwdb.py # ------------------------------------------------------------------------------ ata_id_SOURCES = \ diff --git a/hwdb/parse_hwdb.py b/hwdb/parse_hwdb.py old mode 100644 new mode 100755 index 773513eaf0..99d034b4e0 --- a/hwdb/parse_hwdb.py +++ b/hwdb/parse_hwdb.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3 # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # # This file is part of systemd. @@ -17,9 +18,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . -import sys -import string import functools +import glob +import string +import sys +import os try: from pyparsing import (Word, White, Literal, ParserElement, Regex, @@ -29,7 +32,8 @@ try: stringEnd, pythonStyleComment, ParseBaseException) except ImportError: - sys.exit('pyparsing is not available') + print('pyparsing is not available') + sys.exit(77) try: from evdev.ecodes import ecodes @@ -168,7 +172,9 @@ def print_summary(fname, groups): )) if __name__ == '__main__': - for fname in sys.argv[1:]: + args = sys.argv[1:] or glob.glob(os.path.dirname(sys.argv[0]) + '/[67]0-*.hwdb') + + for fname in args: groups = parse(fname) print_summary(fname, groups) check_match_uniqueness(groups) -- cgit v1.2.3-54-g00ecf From ac741b47dc259c190f6897a8cf581f2c3b73e18e Mon Sep 17 00:00:00 2001 From: romanstingler Date: Tue, 9 Aug 2016 06:51:38 +0200 Subject: added Zelotes gaming mouse (#3925) --- hwdb/70-mouse.hwdb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb index b68c01066e..c569d66d47 100644 --- a/hwdb/70-mouse.hwdb +++ b/hwdb/70-mouse.hwdb @@ -500,3 +500,11 @@ mouse:usb:v1038p1369:name:SteelSeries Sensei Raw Gaming Mouse: # Trust illuminated mouse gxt 152 mouse:usb:v145fp01ac:name:HID-compliant Mouse Trust Gaming Mouse: MOUSE_DPI=*800@528 1200@537 1600@536 2400@521 + + ########################################## + # Zelotes + ########################################## + +# Zelotes 5500 DPI 7 Button USB Wired Gaming Mouse +mouse:usb:v1d57pad17:* + MOUSE_DPI=1000@500 1600@500 2400@500 3200@500 5500@500 *1000@1000 1600@1000 2400@1000 3200@1000 5500@1000 -- cgit v1.2.3-54-g00ecf From e73529f9dd878cc449f5271f749929ebd9e93d88 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Tue, 9 Aug 2016 15:49:32 +0300 Subject: sd-journal: watch logs below container's /{var,run}/log/journal (instead of the /) (#3934) Fixes #3927. --- src/journal/sd-journal.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 75a0ffb49b..2a3824d0e8 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -2290,6 +2290,8 @@ _public_ int sd_journal_get_fd(sd_journal *j) { * inotify */ if (j->no_new_files) r = add_current_paths(j); + else if (j->flags & SD_JOURNAL_OS_ROOT) + r = add_search_paths(j); else if (j->toplevel_fd >= 0) r = add_root_directory(j, NULL, false); else if (j->path) -- cgit v1.2.3-54-g00ecf From 1cd1dab98c574f92e1afca184a4c44327c764955 Mon Sep 17 00:00:00 2001 From: Rhys Date: Tue, 9 Aug 2016 23:33:46 +1000 Subject: install: follow config_path symlink (#3362) Under NixOS, the config_path /etc/systemd/system is a symlink to /etc/static/systemd/system. Commands such as `systemctl list-unit-files` and `systemctl is-enabled` did not work as the symlink was not followed. This does not affect how symlinks are treated within the config_path directory. --- src/shared/install.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/install.c b/src/shared/install.c index 7b49e1ece9..e740ef3910 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -777,7 +777,7 @@ static int find_symlinks( assert(config_path); assert(same_name_link); - fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); + fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC); if (fd < 0) { if (IN_SET(errno, ENOENT, ENOTDIR, EACCES)) return 0; -- cgit v1.2.3-54-g00ecf From 6998b54093831fac92e2b1e251659e64d56e1df6 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 11 Aug 2016 04:51:00 -0400 Subject: coredump: treat RLIMIT_CORE below page size as disabling coredumps (#3932) The kernel treats values below a certain threshold (minfmt->min_coredump which is initialized do ELF_EXEC_PAGESIZE, which varies between architectures, but is usually the same as PAGE_SIZE) as disabling coredumps [1]. Any core image below ELF_EXEC_PAGESIZE will yield an invalid backtrace anyway [2], so follow the kernel and not try to parse or store such images. [1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/coredump.c#n660 [2] systemd-coredump[16260]: Process 16258 (sleep) of user 1002 dumped core. Stack trace of thread 16258: #0 0x00007f1d8b3d3810 n/a (n/a) https://bugzilla.redhat.com/show_bug.cgi?id=1309172#c19 --- src/coredump/coredump.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index e3d17c864d..be724aed4e 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -327,9 +327,11 @@ static int save_external_coredump( r = safe_atou64(context[CONTEXT_RLIMIT], &rlimit); if (r < 0) return log_error_errno(r, "Failed to parse resource limit: %s", context[CONTEXT_RLIMIT]); - if (rlimit <= 0) { - /* Is coredumping disabled? Then don't bother saving/processing the coredump */ - log_info("Core Dumping has been disabled for process %s (%s).", context[CONTEXT_PID], context[CONTEXT_COMM]); + if (rlimit < page_size()) { + /* Is coredumping disabled? Then don't bother saving/processing the coredump. + * Anything below PAGE_SIZE cannot give a readable coredump (the kernel uses + * ELF_EXEC_PAGESIZE which is not easily accessible, but is usually the same as PAGE_SIZE. */ + log_info("Core dumping has been disabled for process %s (%s).", context[CONTEXT_PID], context[CONTEXT_COMM]); return -EBADSLT; } -- cgit v1.2.3-54-g00ecf From 29df65f913ec7d360637ef1703ec284bb1fa6821 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 11 Aug 2016 04:51:49 -0400 Subject: man: add "timeout" to status table (#3919) --- man/systemd.exec.xml | 16 ++++++++++++++++ man/systemd.service.xml | 19 +++++++------------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index f8b2aff81b..bf82326096 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1668,6 +1668,18 @@ + + timeout + killed + TERMKILL + + + + exited + 0123255 + + exit-code exited @@ -1707,6 +1719,10 @@ any of the above any of the above + + + Note: the process may be also terminated by a signal not sent by systemd. In particular the process may send an arbitrary signal to itself in a handler for any of the non-maskable signals. Nevertheless, in the timeout and watchdog rows above only the signals that systemd sends have been included. + diff --git a/man/systemd.service.xml b/man/systemd.service.xml index e82edbe93e..b58e887662 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -276,17 +276,12 @@ below (see section "Command Lines" below). - When Type= is not - , only one command may and must be - given. When Type=oneshot is used, zero or - more commands may be specified. This can be specified by - providing multiple command lines in the same directive, or - alternatively, this directive may be specified more than once - with the same effect. If the empty string is assigned to this - option, the list of commands to start is reset, prior - assignments of this option will have no effect. If no - ExecStart= is specified, then the service - must have RemainAfterExit=yes set. + Unless Type= is , exactly one command must be given. When + Type=oneshot is used, zero or more commands may be specified. Commands may be specified by + providing multiple command lines in the same directive, or alternatively, this directive may be specified more + than once with the same effect. If the empty string is assigned to this option, the list of commands to start + is reset, prior assignments of this option will have no effect. If no ExecStart= is + specified, then the service must have RemainAfterExit=yes set. For each of the specified commands, the first argument must be an absolute path to an executable. Optionally, if this file name is prefixed with @, the second token will be @@ -294,7 +289,7 @@ the absolute filename is prefixed with -, an exit code of the command normally considered a failure (i.e. non-zero exit status or abnormal exit due to signal) is ignored and considered success. If the absolute path is prefixed with + then it is executed with full - privileges. -, @, and + may be used together and they + privileges. @, -, and + may be used together and they can appear in any order. If more than one command is specified, the commands are -- cgit v1.2.3-54-g00ecf From 56ef545c24a4b83f6ad9f542a1159b2130a30f3e Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Thu, 11 Aug 2016 18:46:31 +0200 Subject: zsh: _filter_units_by_property: respect --user Use `$_sys_service_mgr` to handle `--user`, so that `systemctl --user stop` will correctly filter the active (user) units. Before this patch, only user units that also exist as system units and are stoppable there would be listed. --- shell-completion/zsh/_systemctl.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in index 44c31b7833..69f643303d 100644 --- a/shell-completion/zsh/_systemctl.in +++ b/shell-completion/zsh/_systemctl.in @@ -126,7 +126,7 @@ _filter_units_by_property() { local property=$1 value=$2 ; shift ; shift local -a units ; units=($*) local props - for props in ${(ps:\n\n:)"$(_call_program units "$service show --no-pager --property="Id,$property" -- ${units} 2>/dev/null")"}; do + for props in ${(ps:\n\n:)"$(_call_program units "$service $_sys_service_mgr show --no-pager --property="Id,$property" -- ${units} 2>/dev/null")"}; do props=(${(f)props}) if [[ "${props[2]}" = "$property=$value" ]]; then echo -E - " ${props[1]#Id=}" -- cgit v1.2.3-54-g00ecf From 21d84318c3a2dc54732513a80c983f560948c4d8 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Thu, 11 Aug 2016 18:52:13 +0200 Subject: zsh: _journalctl: handle --user in _journal_none This uses the same mechanism from _systemctl to inject `--user` into the `journalctrl -F _EXE` call to list executables. Before this patch the "commands" section would list executables from system units always. --- shell-completion/zsh/_journalctl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shell-completion/zsh/_journalctl b/shell-completion/zsh/_journalctl index 2bee23b6d3..2271f7fa9c 100644 --- a/shell-completion/zsh/_journalctl +++ b/shell-completion/zsh/_journalctl @@ -23,7 +23,7 @@ _list_fields() { _journal_none() { local -a _commands _files _jrnl_none # Setting use-cache will slow this down considerably - _commands=( ${"$(_call_program commands "$service" -F _EXE 2>/dev/null)"} ) + _commands=( ${"$(_call_program commands "$service $_sys_service_mgr -F _EXE" 2>/dev/null)"} ) _jrnl_none='yes' _alternative : \ 'files:/dev files:_files -W /dev -P /dev/' \ @@ -51,6 +51,8 @@ _journal_boots() { "bootid:boot ids:compadd -a _bootid" } +local -a _modes; _modes=("--user" "--system") +local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]:---system} _arguments -s \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ -- cgit v1.2.3-54-g00ecf From 1aaa68f535a4cb5908917031610bb7473baa30c7 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 11 Aug 2016 22:43:07 -0400 Subject: sd-journal: split out flags into separate defines for legibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … in preparation for future changes. --- src/journal/sd-journal.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 2a3824d0e8..a9e90c159a 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -1737,12 +1737,17 @@ fail: return NULL; } +#define OPEN_ALLOWED_FLAGS \ + (SD_JOURNAL_LOCAL_ONLY | \ + SD_JOURNAL_RUNTIME_ONLY | \ + SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER) + _public_ int sd_journal_open(sd_journal **ret, int flags) { sd_journal *j; int r; assert_return(ret, -EINVAL); - assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_RUNTIME_ONLY|SD_JOURNAL_SYSTEM|SD_JOURNAL_CURRENT_USER)) == 0, -EINVAL); + assert_return((flags & ~OPEN_ALLOWED_FLAGS) == 0, -EINVAL); j = journal_new(flags, NULL); if (!j) @@ -1761,6 +1766,9 @@ fail: return r; } +#define OPEN_CONTAINER_ALLOWED_FLAGS \ + (SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_SYSTEM) + _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) { _cleanup_free_ char *root = NULL, *class = NULL; sd_journal *j; @@ -1772,7 +1780,7 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in assert_return(machine, -EINVAL); assert_return(ret, -EINVAL); - assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM)) == 0, -EINVAL); + assert_return((flags & ~OPEN_CONTAINER_ALLOWED_FLAGS) == 0, -EINVAL); assert_return(machine_name_is_valid(machine), -EINVAL); p = strjoina("/run/systemd/machines/", machine); @@ -1806,13 +1814,16 @@ fail: return r; } +#define OPEN_DIRECTORY_ALLOWED_FLAGS \ + SD_JOURNAL_OS_ROOT + _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) { sd_journal *j; int r; assert_return(ret, -EINVAL); assert_return(path, -EINVAL); - assert_return((flags & ~SD_JOURNAL_OS_ROOT) == 0, -EINVAL); + assert_return((flags & ~OPEN_DIRECTORY_ALLOWED_FLAGS) == 0, -EINVAL); j = journal_new(flags, path); if (!j) @@ -1861,6 +1872,9 @@ fail: return r; } +#define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \ + SD_JOURNAL_OS_ROOT + _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) { sd_journal *j; struct stat st; @@ -1868,7 +1882,7 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) { assert_return(ret, -EINVAL); assert_return(fd >= 0, -EBADF); - assert_return((flags & ~SD_JOURNAL_OS_ROOT) == 0, -EINVAL); + assert_return((flags & ~OPEN_DIRECTORY_FD_ALLOWED_FLAGS) == 0, -EINVAL); if (fstat(fd, &st) < 0) return -errno; -- cgit v1.2.3-54-g00ecf From 10752e829b5751d332c0cfb95d69754bc4875ee9 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 11 Aug 2016 22:48:58 -0400 Subject: sd-journal: allow SYSTEM and CURRENT_USER flags with sd_j_open_directory[_fd] There is no reason not to. This makes journalctl -D ... --system work, useful for example when viewing files from a deactivated container. --- man/sd_journal_open.xml | 11 +++++++---- src/journal/sd-journal.c | 6 ++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/man/sd_journal_open.xml b/man/sd_journal_open.xml index 153af2387f..74e67023b5 100644 --- a/man/sd_journal_open.xml +++ b/man/sd_journal_open.xml @@ -129,10 +129,13 @@ sd_journal_open_directory() is similar to sd_journal_open() but takes an absolute directory path as argument. All journal files in this directory will be opened and interleaved - automatically. This call also takes a flags argument. The only flags parameter accepted by this call is - SD_JOURNAL_OS_ROOT. If specified, the journal files are searched below the usual - /var/log/journal and /run/log/journal relative to the specified path, - instead of directly beneath it. + automatically. This call also takes a flags argument. The flags parameters accepted by this call are + SD_JOURNAL_OS_ROOT, SD_JOURNAL_SYSTEM, and + SD_JOURNAL_CURRENT_USER. If SD_JOURNAL_OS_ROOT is specified, journal + files are searched for below the usual /var/log/journal and + /run/log/journal relative to the specified path, instead of directly beneath it. + The other two flags limit which files are opened, the same as for sd_journal_open(). + sd_journal_open_directory_fd() is similar to sd_journal_open_directory(), but takes a file descriptor referencing a directory in the file diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index a9e90c159a..082d2dd178 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -1815,7 +1815,8 @@ fail: } #define OPEN_DIRECTORY_ALLOWED_FLAGS \ - SD_JOURNAL_OS_ROOT + (SD_JOURNAL_OS_ROOT | \ + SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER ) _public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) { sd_journal *j; @@ -1873,7 +1874,8 @@ fail: } #define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \ - SD_JOURNAL_OS_ROOT + (SD_JOURNAL_OS_ROOT | \ + SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER ) _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) { sd_journal *j; -- cgit v1.2.3-54-g00ecf From 16fefe9080fafa9e8a96248519f0623f3c7dc5b5 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 12 Aug 2016 00:32:10 -0400 Subject: sd-journal: fix sd_journal_open_directory with SD_JOURNAL_OS_ROOT The directory argument that is given to sd_j_o_d was ignored when SD_JOURNAL_OS_ROOT was given, and directories relative to the root of the host file system were used. With that flag, sd_j_o_d should do the same as sd_j_open_container: use the path as "prefix", i.e. the directory relative to which everything happens. Instead of touching sd_j_o_d, journal_new is fixed to do what sd_j_o_c was doing, and treat the specified path as prefix when SD_JOURNAL_OS_ROOT is specified. --- src/journal/sd-journal.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 082d2dd178..98c8a47afe 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -1719,9 +1719,16 @@ static sd_journal *journal_new(int flags, const char *path) { j->data_threshold = DEFAULT_DATA_THRESHOLD; if (path) { - j->path = strdup(path); - if (!j->path) + char *t; + + t = strdup(path); + if (!t) goto fail; + + if (flags & SD_JOURNAL_OS_ROOT) + j->prefix = t; + else + j->path = t; } j->files = ordered_hashmap_new(&string_hash_ops); @@ -1795,13 +1802,10 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in if (!streq_ptr(class, "container")) return -EIO; - j = journal_new(flags, NULL); + j = journal_new(flags, root); if (!j) return -ENOMEM; - j->prefix = root; - root = NULL; - r = add_search_paths(j); if (r < 0) goto fail; -- cgit v1.2.3-54-g00ecf From 0a1750934f58d72682f5f8d441a249f5e6f22c24 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 12 Aug 2016 00:34:45 -0400 Subject: journalctl: allow --root argument for journal watching It is useful to look at a (possibly inactive) container or other os tree with --root=/path/to/container. This is similar to specifying --directory=/path/to/container/var/log/journal --directory=/path/to/container/run/systemd/journal (if using --directory multiple times was allowed), but doesn't require as much typing. --- man/journalctl.xml | 6 ++++-- src/journal/journalctl.c | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/man/journalctl.xml b/man/journalctl.xml index c448a29a51..63b4a267b8 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -659,10 +659,12 @@ Takes a directory path as an argument. If - specified, journalctl will operate on catalog file hierarchy + specified, journalctl will operate on journal directories and catalog file hierarchy underneath the specified directory instead of the root directory (e.g. will create - ROOT/var/lib/systemd/catalog/database). + ROOT/var/lib/systemd/catalog/database, + and journal files under ROOT/run/journal + or ROOT/var/log/journal will be displayed). diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 6f841efb69..381e219390 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -310,7 +310,7 @@ static void help(void) { " -m --merge Show entries from all available journals\n" " -D --directory=PATH Show journal files from directory\n" " --file=PATH Show journal file\n" - " --root=ROOT Operate on catalog files below a root directory\n" + " --root=ROOT Operate on files below a root directory\n" #ifdef HAVE_GCRYPT " --interval=TIME Time interval for changing the FSS sealing key\n" " --verify-key=KEY Specify FSS verification key\n" @@ -848,8 +848,8 @@ static int parse_argv(int argc, char *argv[]) { if (arg_follow && !arg_no_tail && !arg_since && arg_lines == ARG_LINES_DEFAULT) arg_lines = 10; - if (!!arg_directory + !!arg_file + !!arg_machine > 1) { - log_error("Please specify either -D/--directory= or --file= or -M/--machine=, not more than one."); + if (!!arg_directory + !!arg_file + !!arg_machine + !!arg_root > 1) { + log_error("Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root."); return -EINVAL; } @@ -1267,7 +1267,7 @@ static int add_boot(sd_journal *j) { * We can do this only when we logs are coming from the current machine, * so take the slow path if log location is specified. */ if (arg_boot_offset == 0 && sd_id128_is_null(arg_boot_id) && - !arg_directory && !arg_file) + !arg_directory && !arg_file && !arg_root) return add_match_this_boot(j, arg_machine); @@ -2161,6 +2161,8 @@ int main(int argc, char *argv[]) { if (arg_directory) r = sd_journal_open_directory(&j, arg_directory, arg_journal_type); + else if (arg_root) + r = sd_journal_open_directory(&j, arg_root, arg_journal_type | SD_JOURNAL_OS_ROOT); else if (arg_file_stdin) { int ifd = STDIN_FILENO; r = sd_journal_open_files_fd(&j, &ifd, 1, 0); -- cgit v1.2.3-54-g00ecf From d551b8fcf75c32e34115a7ca638686e80be57657 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 13 Aug 2016 16:41:22 +0200 Subject: zsh: _journalctl: improve support for handling mode args (#3952) This only completes fields from `journalctl --user` in _journal_fields when `--user` is used. It also changes $_sys_service_mgr to include both `--system` and `--user`, because `journalctl` behaves different from `systemctl` in this regard. No attempt is made to filter out invalid combinations, e.g. when using both `--directory` and `--system` (see https://github.com/systemd/systemd/issues/3949). --- shell-completion/zsh/_journalctl | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/shell-completion/zsh/_journalctl b/shell-completion/zsh/_journalctl index 2271f7fa9c..e6549e863f 100644 --- a/shell-completion/zsh/_journalctl +++ b/shell-completion/zsh/_journalctl @@ -33,7 +33,7 @@ _journal_none() { _journal_fields() { local -a _fields cmd - cmd=("journalctl" "-F ${@[-1]}" "2>/dev/null" ) + cmd=("journalctl $_sys_service_mgr" "-F ${@[-1]}" "2>/dev/null" ) _fields=$(_call_program fields $cmd[@]) _fields=${_fields//'\'/'\\'} _fields=${_fields//':'/'\:'} @@ -51,8 +51,22 @@ _journal_boots() { "bootid:boot ids:compadd -a _bootid" } -local -a _modes; _modes=("--user" "--system") -local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]:---system} +# Build arguments for "journalctl" to be used in completion. +# Use both --user and --system modes, they are not exclusive. +local -a _modes; _modes=(--user --system) +local -a _modes_with_arg; _modes_with_arg=(--directory -D --file -M --machine) +typeset -a _sys_service_mgr +local w i=0 n=$#words +while (( i++ < n )); do + w=$words[$i] + if (( $_modes[(I)$w] )); then + _sys_service_mgr+=($w) + else + if (( ${_modes_with_arg[(I)$w]} )); then + _sys_service_mgr+=($w ${words[((++i))]}) + fi + fi +done _arguments -s \ {-h,--help}'[Show this help]' \ '--version[Show package version]' \ -- cgit v1.2.3-54-g00ecf From e09d0d46c297068d9d742d8a00c2c52e2d95a0c1 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 13 Aug 2016 16:42:55 +0200 Subject: zsh: _systemctl: do not attempt to use "--system" by default (#3951) In 68c4f6d the following was added: local -a _modes; _modes=("--user" "--system") local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]:---system} With the following comment: > If neither are on the line, --system is set; for system services to be > completed. But it does not work as documented: % _modes=(--user --system) % words=() % echo ${${words:*_modes}[(R)(${(j.|.)_modes})]:---system} However, it should not use `--system` in that case anyway, so this patch removes the part that should cause a default to be used and adds some comments. --- shell-completion/zsh/_systemctl.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in index 69f643303d..b525286932 100644 --- a/shell-completion/zsh/_systemctl.in +++ b/shell-completion/zsh/_systemctl.in @@ -351,8 +351,10 @@ _job_modes() { _values -s , "${_modes[@]}" } +# Build arguments for "systemctl" to be used in completion. local -a _modes; _modes=("--user" "--system") -local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]:---system} +# Use the last mode (they are exclusive and the last one is used). +local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]} _arguments -s \ {-h,--help}'[Show help]' \ '--version[Show package version]' \ -- cgit v1.2.3-54-g00ecf From 2d891284c74d9246077aae192a22fd1df9e22aa8 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 13 Aug 2016 11:14:58 -0400 Subject: hwdb: normalize spacing in 60-keyboard.hwdb (#3954) --- hwdb/60-keyboard.hwdb | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb index 1176881650..25caa60626 100644 --- a/hwdb/60-keyboard.hwdb +++ b/hwdb/60-keyboard.hwdb @@ -758,22 +758,22 @@ evdev:input:b0003v046DpC52D* # Internet Navigator evdev:input:b0003v046DpC309* - KEYBOARD_KEY_90001=chat # Messenger/SMS - KEYBOARD_KEY_90002=camera # webcam - KEYBOARD_KEY_90003=prog1 # iTouch - KEYBOARD_KEY_90004=shop # Shopping - KEYBOARD_KEY_c0201=new # New (F1) - KEYBOARD_KEY_c0289=reply # Reply mail (F2) - KEYBOARD_KEY_c028b=forwardmail # Forward mail (F3) - KEYBOARD_KEY_c028c=send # Send (F4) - KEYBOARD_KEY_c021a=undo # Undo (F5). - KEYBOARD_KEY_c0279=redo # Redo (F6). - KEYBOARD_KEY_c0208=print # Print (F7) - KEYBOARD_KEY_c0207=save # Save (F8) - KEYBOARD_KEY_c0194=file # My Computer (F9) - KEYBOARD_KEY_c01a7=documents # My Documents (F10) - KEYBOARD_KEY_c01b6=images # My Pictures (F11) ?? - KEYBOARD_KEY_c01b7=sound # My Music (F12) ?? + KEYBOARD_KEY_90001=chat # Messenger/SMS + KEYBOARD_KEY_90002=camera # webcam + KEYBOARD_KEY_90003=prog1 # iTouch + KEYBOARD_KEY_90004=shop # Shopping + KEYBOARD_KEY_c0201=new # New (F1) + KEYBOARD_KEY_c0289=reply # Reply mail (F2) + KEYBOARD_KEY_c028b=forwardmail # Forward mail (F3) + KEYBOARD_KEY_c028c=send # Send (F4) + KEYBOARD_KEY_c021a=undo # Undo (F5) + KEYBOARD_KEY_c0279=redo # Redo (F6) + KEYBOARD_KEY_c0208=print # Print (F7) + KEYBOARD_KEY_c0207=save # Save (F8) + KEYBOARD_KEY_c0194=file # My Computer (F9) + KEYBOARD_KEY_c01a7=documents # My Documents (F10) + KEYBOARD_KEY_c01b6=images # My Pictures (F11) ?? + KEYBOARD_KEY_c01b7=sound # My Music (F12) ?? ########################################################### @@ -803,7 +803,7 @@ evdev:atkbd:dmi:bvn*:bvr*:svnMedion*:pnAkoya*:pvr* KEYBOARD_KEY_b0=!volumeup KEYBOARD_KEY_19=!p KEYBOARD_KEY_df=sleep - + # FID2060 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMEDION*:pn*FID2060*:pvr* KEYBOARD_KEY_6b=channeldown # Thottle Down -- cgit v1.2.3-54-g00ecf From 04d0f7e9f9e2d68502f322b8f494c652cbeb5146 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 13 Aug 2016 11:15:19 -0400 Subject: units: do not start load-random-seed in containers (#3941) Random numbers are provided by the host kernel, we don't need to do anything. https://bugzilla.redhat.com/show_bug.cgi?id=1329124 --- units/systemd-random-seed.service.in | 1 + 1 file changed, 1 insertion(+) diff --git a/units/systemd-random-seed.service.in b/units/systemd-random-seed.service.in index 115233268d..b244a8ce43 100644 --- a/units/systemd-random-seed.service.in +++ b/units/systemd-random-seed.service.in @@ -13,6 +13,7 @@ RequiresMountsFor=@RANDOM_SEED@ Conflicts=shutdown.target After=systemd-remount-fs.service Before=sysinit.target shutdown.target +ConditionVirtualization=!container [Service] Type=oneshot -- cgit v1.2.3-54-g00ecf From aa43d4bb8984255c5738b377df0a0d3735b0e199 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 14 Aug 2016 15:24:33 -0400 Subject: build-sys: clarify that --disable-efi is about sd-boot and bootctl If wasn't obvious what the effect of --disable-efi was without going through Makefile.am. Fixes #3959. --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 4d1c96606f..36061c0ba9 100644 --- a/configure.ac +++ b/configure.ac @@ -1220,9 +1220,9 @@ AM_CONDITIONAL(ENABLE_NETWORKD, [test "x$have_networkd" = "xyes"]) # ------------------------------------------------------------------------------ have_efi=no -AC_ARG_ENABLE(efi, AS_HELP_STRING([--disable-efi], [disable EFI support])) +AC_ARG_ENABLE(efi, AS_HELP_STRING([--disable-efi], [disable systemd-boot and bootctl (EFI support)])) if test "x$enable_efi" != "xno"; then - AC_DEFINE(ENABLE_EFI, 1, [Define if EFI support is to be enabled]) + AC_DEFINE(ENABLE_EFI, 1, [Define if systemd-boot and bootctl are to be enabled]) have_efi=yes fi AM_CONDITIONAL(ENABLE_EFI, [test "x$have_efi" = "xyes"]) -- cgit v1.2.3-54-g00ecf From 05b2a8fd7a0533758d2f532df798cabc3c442683 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 14 Aug 2016 16:27:59 -0400 Subject: man: explain that *KeyIgnoreInhibited only apply to a subset of locks Follow-up for #3924. --- man/logind.conf.xml | 42 ++++++++++++++++++++++++++---------------- man/systemd-inhibit.xml | 2 +- man/systemd-logind.service.xml | 2 +- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/man/logind.conf.xml b/man/logind.conf.xml index adba5a4131..5931832996 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -211,7 +211,7 @@ HandleLidSwitch= HandleLidSwitchDocked= - Controls whether logind shall handle the + Controls how logind shall handle the system power and sleep keys and the lid switch to trigger actions such as system power-off or suspend. Can be one of ignore, @@ -240,7 +240,16 @@ docking station, or if more than one display is connected, the action specified by HandleLidSwitchDocked= occurs; otherwise the HandleLidSwitch= - action occurs. + action occurs. + + A different application may disable logind's handling of system power and + sleep keys and the lid switch by taking a low-level inhibitor lock + ("handle-power-key", "handle-suspend-key", "handle-hibernate-key", + "handle-lid-switch"). This is most commonly used by graphical desktop environments + to take over suspend and hibernation handling, and to use their own configuration + mechanisms. If a low-level inhibitor lock is taken, logind will not take any + action when that key or switch is triggered and the Handle*= + settings are irrelevant. @@ -249,21 +258,22 @@ HibernateKeyIgnoreInhibited= LidSwitchIgnoreInhibited= - Controls whether actions triggered by the - power and sleep keys and the lid switch are subject to - inhibitor locks. These settings take boolean arguments. If - no, the inhibitor locks taken by - applications in order to block the requested operation are - respected. If yes, the requested operation - is executed in any case. + Controls whether actions that systemd-logind + takes when the power and sleep keys and the lid switch are triggered are subject + to high-level inhibitor locks ("shutdown", "sleep", "idle"). Low level inhibitor + locks ("handle-*-key"), are always honoured, irrespective of this setting. + + These settings take boolean arguments. If no, the + inhibitor locks taken by applications are respected. If yes, + "shutdown", "sleep", and "idle" inhibitor locks are ignored. PowerKeyIgnoreInhibited=, - SuspendKeyIgnoreInhibited= and - HibernateKeyIgnoreInhibited= default to - no. - LidSwitchIgnoreInhibited= defaults to - yes. This means that the lid switch does - not respect suspend blockers by default, but the power and - sleep keys do. + SuspendKeyIgnoreInhibited=, and + HibernateKeyIgnoreInhibited= default to no. + LidSwitchIgnoreInhibited= defaults to yes. + This means that when systemd-logind is handling events by + itself (no low level inhibitor locks are taken by another application), the lid + switch does not respect suspend blockers by default, but the power and sleep keys + do. diff --git a/man/systemd-inhibit.xml b/man/systemd-inhibit.xml index 9d85908f97..ce169960d8 100644 --- a/man/systemd-inhibit.xml +++ b/man/systemd-inhibit.xml @@ -61,7 +61,7 @@ Description systemd-inhibit may be used to execute a - program with a shutdown, sleep or idle inhibitor lock taken. The + program with a shutdown, sleep, or idle inhibitor lock taken. The lock will be acquired before the specified command line is executed and released afterwards. diff --git a/man/systemd-logind.service.xml b/man/systemd-logind.service.xml index 5733e42cd1..f0bdb1c756 100644 --- a/man/systemd-logind.service.xml +++ b/man/systemd-logind.service.xml @@ -84,7 +84,7 @@ management
- User sessions are registered in logind via the + User sessions are registered with logind via the pam_systemd8 PAM module. -- cgit v1.2.3-54-g00ecf From ca2f6384aa2076576b316c7253964be90b102d96 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 Aug 2016 18:13:36 -0400 Subject: core: rename cg_unified() to cg_all_unified() A following patch will update cgroup handling so that the systemd controller (/sys/fs/cgroup/systemd) can use the unified hierarchy even if the kernel resource controllers are on the legacy hierarchies. This would require distinguishing whether all controllers are on cgroup v2 or only the systemd controller is. In preparation, this patch renames cg_unified() to cg_all_unified(). This patch doesn't cause any functional changes. --- src/basic/cgroup-util.c | 30 +++++++++++++++--------------- src/basic/cgroup-util.h | 2 +- src/cgls/cgls.c | 2 +- src/cgtop/cgtop.c | 10 +++++----- src/core/cgroup.c | 16 ++++++++-------- src/core/manager.c | 2 +- src/core/scope.c | 2 +- src/core/service.c | 2 +- src/core/unit.c | 2 +- src/libsystemd/sd-bus/test-bus-creds.c | 2 +- src/nspawn/nspawn-cgroup.c | 4 ++-- src/nspawn/nspawn-mount.c | 4 ++-- src/nspawn/nspawn.c | 2 +- 13 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 25ef8a5c76..5473fec0dd 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -623,7 +623,7 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch if (!cg_controller_is_valid(controller)) return -EINVAL; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; @@ -651,7 +651,7 @@ static int controller_is_accessible(const char *controller) { if (!cg_controller_is_valid(controller)) return -EINVAL; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) { @@ -869,7 +869,7 @@ int cg_set_task_access( if (r < 0) return r; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified) @@ -893,7 +893,7 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) { assert(path); assert(pid >= 0); - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified == 0) { @@ -969,7 +969,7 @@ int cg_install_release_agent(const char *controller, const char *agent) { assert(agent); - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified) /* doesn't apply to unified hierarchy */ @@ -1020,7 +1020,7 @@ int cg_uninstall_release_agent(const char *controller) { _cleanup_free_ char *fs = NULL; int r, unified; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified) /* Doesn't apply to unified hierarchy */ @@ -1076,7 +1076,7 @@ int cg_is_empty_recursive(const char *controller, const char *path) { if (controller && (isempty(path) || path_equal(path, "/"))) return false; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; @@ -1962,7 +1962,7 @@ int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path return r; /* If we are in the unified hierarchy, we are done now */ - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) @@ -1992,7 +1992,7 @@ int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_m if (r < 0) return r; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) @@ -2044,7 +2044,7 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to return r; } - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) @@ -2077,7 +2077,7 @@ int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root) if (r < 0) return r; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) @@ -2103,7 +2103,7 @@ int cg_mask_supported(CGroupMask *ret) { * includes controllers we can make sense of and that are * actually accessible. */ - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (unified > 0) { @@ -2226,7 +2226,7 @@ int cg_kernel_controllers(Set *controllers) { static thread_local int unified_cache = -1; -int cg_unified(void) { +int cg_all_unified(void) { struct statfs fs; /* Checks if we support the unified hierarchy. Returns an @@ -2264,7 +2264,7 @@ int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p) { if (supported == 0) return 0; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return unified; if (!unified) /* on the legacy hiearchy there's no joining of controllers defined */ @@ -2303,7 +2303,7 @@ bool cg_is_unified_wanted(void) { /* If the hierarchy is already mounted, then follow whatever * was chosen for it. */ - unified = cg_unified(); + unified = cg_all_unified(); if (unified >= 0) return unified; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index a509a1775c..5fa856affc 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -225,7 +225,7 @@ int cg_kernel_controllers(Set *controllers); bool cg_ns_supported(void); -int cg_unified(void); +int cg_all_unified(void); void cg_unified_flush(void); bool cg_is_unified_wanted(void); diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index dcb5912b83..adf488e8e1 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -166,7 +166,7 @@ static int get_cgroup_root(char **ret) { static void show_cg_info(const char *controller, const char *path) { - if (cg_unified() <= 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER)) + if (cg_all_unified() <= 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER)) printf("Controller %s; ", controller); printf("Control group %s:\n", isempty(path) ? "/" : path); diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 6045ae0437..aba17c9829 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -213,7 +213,7 @@ static int process( uint64_t new_usage; nsec_t timestamp; - if (cg_unified() > 0) { + if (cg_all_unified() > 0) { const char *keys[] = { "usage_usec", NULL }; _cleanup_free_ char *val = NULL; @@ -273,7 +273,7 @@ static int process( } else if (streq(controller, "memory")) { _cleanup_free_ char *p = NULL, *v = NULL; - if (cg_unified() <= 0) + if (cg_all_unified() <= 0) r = cg_get_path(controller, path, "memory.usage_in_bytes", &p); else r = cg_get_path(controller, path, "memory.current", &p); @@ -293,11 +293,11 @@ static int process( if (g->memory > 0) g->memory_valid = true; - } else if ((streq(controller, "io") && cg_unified() > 0) || - (streq(controller, "blkio") && cg_unified() <= 0)) { + } else if ((streq(controller, "io") && cg_all_unified() > 0) || + (streq(controller, "blkio") && cg_all_unified() <= 0)) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; - bool unified = cg_unified() > 0; + bool unified = cg_all_unified() > 0; uint64_t wr = 0, rd = 0; nsec_t timestamp; diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 910a64b4da..7c6fc01c0e 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -665,7 +665,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { bool has_weight = cgroup_context_has_cpu_weight(c); bool has_shares = cgroup_context_has_cpu_shares(c); - if (cg_unified() > 0) { + if (cg_all_unified() > 0) { uint64_t weight; if (has_weight) @@ -846,7 +846,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { } if ((mask & CGROUP_MASK_MEMORY) && !is_root) { - if (cg_unified() > 0) { + if (cg_all_unified() > 0) { uint64_t max = c->memory_max; if (cgroup_context_has_unified_memory_config(c)) @@ -1019,7 +1019,7 @@ CGroupMask unit_get_own_mask(Unit *u) { e = unit_get_exec_context(u); if (!e || exec_context_maintains_privileges(e) || - cg_unified() > 0) + cg_all_unified() > 0) return _CGROUP_MASK_ALL; } @@ -1245,7 +1245,7 @@ int unit_watch_cgroup(Unit *u) { return 0; /* Only applies to the unified hierarchy */ - r = cg_unified(); + r = cg_all_unified(); if (r < 0) return log_unit_error_errno(u, r, "Failed detect whether the unified hierarchy is used: %m"); if (r == 0) @@ -1645,7 +1645,7 @@ int unit_watch_all_pids(Unit *u) { if (!u->cgroup_path) return -ENOENT; - if (cg_unified() > 0) /* On unified we can use proper notifications */ + if (cg_all_unified() > 0) /* On unified we can use proper notifications */ return 0; return unit_watch_pids_in_path(u, u->cgroup_path); @@ -1755,7 +1755,7 @@ int manager_setup_cgroup(Manager *m) { if (r < 0) return log_error_errno(r, "Cannot find cgroup mount point: %m"); - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m"); if (unified > 0) @@ -1953,7 +1953,7 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) { if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0) return -ENODATA; - if (cg_unified() <= 0) + if (cg_all_unified() <= 0) r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v); else r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v); @@ -1998,7 +1998,7 @@ static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) { if (!u->cgroup_path) return -ENODATA; - if (cg_unified() > 0) { + if (cg_all_unified() > 0) { const char *keys[] = { "usage_usec", NULL }; _cleanup_free_ char *val = NULL; uint64_t us; diff --git a/src/core/manager.c b/src/core/manager.c index c20e185d78..108591c464 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -766,7 +766,7 @@ static int manager_setup_cgroups_agent(Manager *m) { if (!MANAGER_IS_SYSTEM(m)) return 0; - if (cg_unified() > 0) /* We don't need this anymore on the unified hierarchy */ + if (cg_all_unified() > 0) /* We don't need this anymore on the unified hierarchy */ return 0; if (m->cgroups_agent_fd < 0) { diff --git a/src/core/scope.c b/src/core/scope.c index b278aed3d6..7c72bb7091 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -441,7 +441,7 @@ static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) { /* If the PID set is empty now, then let's finish this off (On unified we use proper notifications) */ - if (cg_unified() <= 0 && set_isempty(u->pids)) + if (cg_all_unified() <= 0 && set_isempty(u->pids)) scope_notify_cgroup_empty_event(u); } diff --git a/src/core/service.c b/src/core/service.c index 4a37702f52..29e53867bf 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2866,7 +2866,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { /* If the PID set is empty now, then let's finish this off (On unified we use proper notifications) */ - if (cg_unified() <= 0 && set_isempty(u->pids)) + if (cg_all_unified() <= 0 && set_isempty(u->pids)) service_notify_cgroup_empty_event(u); } diff --git a/src/core/unit.c b/src/core/unit.c index 952604e0db..b24c32569c 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3695,7 +3695,7 @@ int unit_kill_context( * there we get proper events. Hence rely on * them.*/ - if (cg_unified() > 0 || + if (cg_all_unified() > 0 || (detect_container() == 0 && !unit_cgroup_delegate(u))) wait_for_exit = true; diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c index e9ef483bdd..82237af115 100644 --- a/src/libsystemd/sd-bus/test-bus-creds.c +++ b/src/libsystemd/sd-bus/test-bus-creds.c @@ -27,7 +27,7 @@ int main(int argc, char *argv[]) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; int r; - if (cg_unified() == -ENOMEDIUM) { + if (cg_all_unified() == -ENOMEDIUM) { puts("Skipping test: /sys/fs/cgroup/ not available"); return EXIT_TEST_SKIP; } diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index b1580236c9..ea3cab513c 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -70,7 +70,7 @@ int sync_cgroup(pid_t pid, bool unified_requested) { const char *fn; int unified, r; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m"); @@ -132,7 +132,7 @@ int create_subcgroup(pid_t pid, bool unified_requested) { if (!unified_requested) return 0; - unified = cg_unified(); + unified = cg_all_unified(); if (unified < 0) return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m"); if (unified == 0) diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 803caef3dd..b5d83d481a 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -721,7 +721,7 @@ static int mount_legacy_cgns_supported( return log_error_errno(errno, "Failed to mount /sys/fs/cgroup: %m"); } - if (cg_unified() > 0) + if (cg_all_unified() > 0) goto skip_controllers; controllers = set_new(&string_hash_ops); @@ -813,7 +813,7 @@ static int mount_legacy_cgns_unsupported( return log_error_errno(errno, "Failed to mount /sys/fs/cgroup: %m"); } - if (cg_unified() > 0) + if (cg_all_unified() > 0) goto skip_controllers; controllers = set_new(&string_hash_ops); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index fcf14bba4c..429b6ddc4f 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -332,7 +332,7 @@ static int detect_unified_cgroup_hierarchy(void) { } /* Otherwise inherit the default from the host system */ - r = cg_unified(); + r = cg_all_unified(); if (r < 0) return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m"); -- cgit v1.2.3-54-g00ecf From 856e309d7b18cabe18c845bdf57e92958343a9ec Mon Sep 17 00:00:00 2001 From: Michael Chapman Date: Tue, 16 Aug 2016 19:07:42 +1000 Subject: networkd: avoid NULL pointer dereference in route_add If no result parameter is provided, do not attempt to write the found/newly-created route to it. This is presently not an issue as all callers currently provide a non-NULL result parameter, however we should do this for symmetry with address_add and future code robustness. --- src/network/networkd-route.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index cedaf47cf8..82f9047ff6 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -322,7 +322,8 @@ int route_add( } else return r; - *ret = route; + if (ret) + *ret = route; return 0; } -- cgit v1.2.3-54-g00ecf From ba89f80620d619867b4838973785d529c5a959f6 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Tue, 16 Aug 2016 18:42:41 +0200 Subject: zsh: _journalctl: do not complete exclusive modes (#3957) After `journalctl -D /var/log/journal` "--directory", "--file", "--machine" and "--root" should not be available for completion, because they are exclusive. But multiple `--file` arguments are allowed. --- shell-completion/zsh/_journalctl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shell-completion/zsh/_journalctl b/shell-completion/zsh/_journalctl index e6549e863f..610788dcce 100644 --- a/shell-completion/zsh/_journalctl +++ b/shell-completion/zsh/_journalctl @@ -96,10 +96,10 @@ _arguments -s \ {-F,--field=}'[List all values a certain field takes]:Fields:_list_fields' \ '--system[Show system and kernel messages]' \ '--user[Show messages from user services]' \ - {-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ - {-D+,--directory=}'[Show journal files from directory]:directories:_directories' \ - '--file=[Operate on specified journal files]:file:_files' \ - '--root=[Operate on catalog hierarchy under specified directory]:directories:_directories' \ + '(--directory -D -M --machine --root --file)'{-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ + '(--directory -D -M --machine --root --file)'{-D+,--directory=}'[Show journal files from directory]:directories:_directories' \ + '(--directory -D -M --machine --root --file)''--root=[Operate on catalog hierarchy under specified directory]:directories:_directories' \ + '(--directory -D -M --machine --root)--file=[Operate on specified journal files]:file:_files' \ '--new-id128[Generate a new 128 Bit ID]' \ '--header[Show journal header information]' \ '--disk-usage[Show total disk usage]' \ -- cgit v1.2.3-54-g00ecf From b2fe35fe58f5229c0a265c86877b5d08114a2867 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Tue, 16 Aug 2016 18:47:39 +0200 Subject: zsh: _journalctl: also handle --root arg and --key=value style (#3956) This will now also handle `journalctl --directory=/var/log/journal` properly. --- shell-completion/zsh/_journalctl | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/shell-completion/zsh/_journalctl b/shell-completion/zsh/_journalctl index 610788dcce..ef67fcf2a0 100644 --- a/shell-completion/zsh/_journalctl +++ b/shell-completion/zsh/_journalctl @@ -54,16 +54,25 @@ _journal_boots() { # Build arguments for "journalctl" to be used in completion. # Use both --user and --system modes, they are not exclusive. local -a _modes; _modes=(--user --system) -local -a _modes_with_arg; _modes_with_arg=(--directory -D --file -M --machine) +local -a _modes_with_arg; _modes_with_arg=(--directory -D --file -M --machine --root) typeset -a _sys_service_mgr -local w i=0 n=$#words +local w k v i=0 n=$#words while (( i++ < n )); do w=$words[$i] if (( $_modes[(I)$w] )); then _sys_service_mgr+=($w) else - if (( ${_modes_with_arg[(I)$w]} )); then - _sys_service_mgr+=($w ${words[((++i))]}) + # Handle options with arguments. "--key=value" and "--key value". + k=${w%%=*} + if (( ${_modes_with_arg[(I)$k]} )); then + v=${w#*=} + if [[ "$k" != "$w" ]]; then + # "--key=value" style. + _sys_service_mgr+=($w) + else + # "--key value" style. + _sys_service_mgr+=($w ${words[((++i))]}) + fi fi fi done -- cgit v1.2.3-54-g00ecf From a5110c90303cf455db5062faef34d5724d12e2e9 Mon Sep 17 00:00:00 2001 From: Michal Sekletar Date: Wed, 17 Aug 2016 14:10:28 +0200 Subject: rules: introduce disk/by-id (model_serial) symlinks for NVMe drives (#3974) $ ls -l /dev/disk/by-id/nvme* lrwxrwxrwx. 1 root root 13 Aug 17 04:25 /dev/disk/by-id/nvme-HUSPR3216AHP301_STM0001B6780 -> ../../nvme0n1 lrwxrwxrwx. 1 root root 15 Aug 17 04:25 /dev/disk/by-id/nvme-HUSPR3216AHP301_STM0001B6780-part1 -> ../../nvme0n1p1 https://github.com/systemd/systemd/issues/1453 https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=779ff75617099f4defe14e20443b95019a4c5ae8 --- rules/60-persistent-storage.rules | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules index d7bbbf9866..c13d05cdb1 100644 --- a/rules/60-persistent-storage.rules +++ b/rules/60-persistent-storage.rules @@ -19,6 +19,12 @@ ENV{DEVTYPE}=="partition", IMPORT{parent}="ID_*" KERNEL=="nvme*[0-9]n*[0-9]", ATTR{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}" KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}-part%n" +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}" +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{model}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$attr{model}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}" + +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}" +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{model}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$attr{model}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n" + # virtio-blk KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}" KERNEL=="vd*[0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}-part%n" -- cgit v1.2.3-54-g00ecf From 105bdb46b4ac7eb658a2f27727216591d0bfe267 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Wed, 17 Aug 2016 05:51:07 -0700 Subject: journal: ensure open journals from find_journal() (#3973) If journals get into a closed state like when rotate fails due to ENOSPC, when space is made available it currently goes unnoticed leaving the journals in a closed state indefinitely. By calling system_journal_open() on entry to find_journal() we ensure the journal has been opened/created if possible. Also moved system_journal_open() up to after open_journal(), before find_journal(). Fixes https://github.com/systemd/systemd/issues/3968 --- src/journal/journald-server.c | 164 ++++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 77 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 587c343b31..443b2a4cd7 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -267,6 +267,82 @@ static int open_journal( return r; } +static int system_journal_open(Server *s, bool flush_requested) { + const char *fn; + int r = 0; + + if (!s->system_journal && + (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) && + (flush_requested + || access("/run/systemd/journal/flushed", F_OK) >= 0)) { + + /* If in auto mode: first try to create the machine + * path, but not the prefix. + * + * If in persistent mode: create /var/log/journal and + * the machine path */ + + if (s->storage == STORAGE_PERSISTENT) + (void) mkdir_p("/var/log/journal/", 0755); + + fn = strjoina("/var/log/journal/", SERVER_MACHINE_ID(s)); + (void) mkdir(fn, 0755); + + fn = strjoina(fn, "/system.journal"); + r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &s->system_journal); + if (r >= 0) { + server_add_acls(s->system_journal, 0); + (void) determine_space_for(s, &s->system_metrics, "/var/log/journal/", "System journal", true, true, NULL, NULL); + } else if (r < 0) { + if (r != -ENOENT && r != -EROFS) + log_warning_errno(r, "Failed to open system journal: %m"); + + r = 0; + } + } + + if (!s->runtime_journal && + (s->storage != STORAGE_NONE)) { + + fn = strjoina("/run/log/journal/", SERVER_MACHINE_ID(s), "/system.journal"); + + if (s->system_journal) { + + /* Try to open the runtime journal, but only + * if it already exists, so that we can flush + * it into the system journal */ + + r = open_journal(s, false, fn, O_RDWR, false, &s->runtime_metrics, &s->runtime_journal); + if (r < 0) { + if (r != -ENOENT) + log_warning_errno(r, "Failed to open runtime journal: %m"); + + r = 0; + } + + } else { + + /* OK, we really need the runtime journal, so create + * it if necessary. */ + + (void) mkdir("/run/log", 0755); + (void) mkdir("/run/log/journal", 0755); + (void) mkdir_parents(fn, 0750); + + r = open_journal(s, true, fn, O_RDWR|O_CREAT, false, &s->runtime_metrics, &s->runtime_journal); + if (r < 0) + return log_error_errno(r, "Failed to open runtime journal: %m"); + } + + if (s->runtime_journal) { + server_add_acls(s->runtime_journal, 0); + (void) determine_space_for(s, &s->runtime_metrics, "/run/log/journal/", "Runtime journal", true, true, NULL, NULL); + } + } + + return r; +} + static JournalFile* find_journal(Server *s, uid_t uid) { _cleanup_free_ char *p = NULL; int r; @@ -275,6 +351,17 @@ static JournalFile* find_journal(Server *s, uid_t uid) { assert(s); + /* A rotate that fails to create the new journal (ENOSPC) leaves the + * rotated journal as NULL. Unless we revisit opening, even after + * space is made available we'll continue to return NULL indefinitely. + * + * system_journal_open() is a noop if the journals are already open, so + * we can just call it here to recover from failed rotates (or anything + * else that's left the journals as NULL). + * + * Fixes https://github.com/systemd/systemd/issues/3968 */ + (void) system_journal_open(s, false); + /* We split up user logs only on /var, not on /run. If the * runtime file is open, we write to it exclusively, in order * to guarantee proper order as soon as we flush /run to @@ -979,83 +1066,6 @@ finish: dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid); } - -static int system_journal_open(Server *s, bool flush_requested) { - const char *fn; - int r = 0; - - if (!s->system_journal && - (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) && - (flush_requested - || access("/run/systemd/journal/flushed", F_OK) >= 0)) { - - /* If in auto mode: first try to create the machine - * path, but not the prefix. - * - * If in persistent mode: create /var/log/journal and - * the machine path */ - - if (s->storage == STORAGE_PERSISTENT) - (void) mkdir_p("/var/log/journal/", 0755); - - fn = strjoina("/var/log/journal/", SERVER_MACHINE_ID(s)); - (void) mkdir(fn, 0755); - - fn = strjoina(fn, "/system.journal"); - r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &s->system_journal); - if (r >= 0) { - server_add_acls(s->system_journal, 0); - (void) determine_space_for(s, &s->system_metrics, "/var/log/journal/", "System journal", true, true, NULL, NULL); - } else if (r < 0) { - if (r != -ENOENT && r != -EROFS) - log_warning_errno(r, "Failed to open system journal: %m"); - - r = 0; - } - } - - if (!s->runtime_journal && - (s->storage != STORAGE_NONE)) { - - fn = strjoina("/run/log/journal/", SERVER_MACHINE_ID(s), "/system.journal"); - - if (s->system_journal) { - - /* Try to open the runtime journal, but only - * if it already exists, so that we can flush - * it into the system journal */ - - r = open_journal(s, false, fn, O_RDWR, false, &s->runtime_metrics, &s->runtime_journal); - if (r < 0) { - if (r != -ENOENT) - log_warning_errno(r, "Failed to open runtime journal: %m"); - - r = 0; - } - - } else { - - /* OK, we really need the runtime journal, so create - * it if necessary. */ - - (void) mkdir("/run/log", 0755); - (void) mkdir("/run/log/journal", 0755); - (void) mkdir_parents(fn, 0750); - - r = open_journal(s, true, fn, O_RDWR|O_CREAT, false, &s->runtime_metrics, &s->runtime_journal); - if (r < 0) - return log_error_errno(r, "Failed to open runtime journal: %m"); - } - - if (s->runtime_journal) { - server_add_acls(s->runtime_journal, 0); - (void) determine_space_for(s, &s->runtime_metrics, "/run/log/journal/", "Runtime journal", true, true, NULL, NULL); - } - } - - return r; -} - int server_flush_to_var(Server *s) { sd_id128_t machine; sd_journal *j = NULL; -- cgit v1.2.3-54-g00ecf From 7532e6d4f4e5c155c01cbd039c0ba077184b2097 Mon Sep 17 00:00:00 2001 From: Felipe Sateler Date: Wed, 17 Aug 2016 15:11:27 -0300 Subject: sysv-generator: better error reporting (#3977) Currently in the journal you get messages without context like: systemd-sysv-generator[$pid]: Failed to build name: Invalid argument When parsing the init script, show the file and line number where the error was found. At the same time, add more context information if available. Thus turning the message into something like: systemd-sysv-generator[$pid]: [/etc/init.d/root-system-proofd:13] Could not build name for facility $network,: Invalid argument --- src/sysv-generator/sysv-generator.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c index 3ed8f23ff9..39821687b9 100644 --- a/src/sysv-generator/sysv-generator.c +++ b/src/sysv-generator/sysv-generator.c @@ -247,7 +247,7 @@ static char *sysv_translate_name(const char *name) { return res; } -static int sysv_translate_facility(const char *name, const char *filename, char **ret) { +static int sysv_translate_facility(SysvStub *s, unsigned line, const char *name, char **ret) { /* We silently ignore the $ prefix here. According to the LSB * spec it simply indicates whether something is a @@ -266,15 +266,18 @@ static int sysv_translate_facility(const char *name, const char *filename, char "time", SPECIAL_TIME_SYNC_TARGET, }; + const char *filename; char *filename_no_sh, *e, *m; const char *n; unsigned i; int r; assert(name); - assert(filename); + assert(s); assert(ret); + filename = basename(s->path); + n = *name == '$' ? name + 1 : name; for (i = 0; i < ELEMENTSOF(table); i += 2) { @@ -299,7 +302,7 @@ static int sysv_translate_facility(const char *name, const char *filename, char if (*name == '$') { r = unit_name_build(n, NULL, ".target", ret); if (r < 0) - return log_error_errno(r, "Failed to build name: %m"); + return log_error_errno(r, "[%s:%u] Could not build name for facility %s: %m", s->path, line, name); return r; } @@ -337,11 +340,11 @@ static int handle_provides(SysvStub *s, unsigned line, const char *full_text, co r = extract_first_word(&text, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); if (r < 0) - return log_error_errno(r, "Failed to parse word from provides string: %m"); + return log_error_errno(r, "[%s:%u] Failed to parse word from provides string: %m", s->path, line); if (r == 0) break; - r = sysv_translate_facility(word, basename(s->path), &m); + r = sysv_translate_facility(s, line, word, &m); if (r <= 0) /* continue on error */ continue; @@ -403,11 +406,11 @@ static int handle_dependencies(SysvStub *s, unsigned line, const char *full_text r = extract_first_word(&text, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); if (r < 0) - return log_error_errno(r, "Failed to parse word from provides string: %m"); + return log_error_errno(r, "[%s:%u] Failed to parse word from provides string: %m", s->path, line); if (r == 0) break; - r = sysv_translate_facility(word, basename(s->path), &m); + r = sysv_translate_facility(s, line, word, &m); if (r <= 0) /* continue on error */ continue; -- cgit v1.2.3-54-g00ecf From 5da38d0768bf53f611ccdd47d7d941e1c560e44e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 15 Aug 2016 18:13:36 -0400 Subject: core: use the unified hierarchy for the systemd cgroup controller hierarchy Currently, systemd uses either the legacy hierarchies or the unified hierarchy. When the legacy hierarchies are used, systemd uses a named legacy hierarchy mounted on /sys/fs/cgroup/systemd without any kernel controllers for process management. Due to the shortcomings in the legacy hierarchy, this involves a lot of workarounds and complexities. Because the unified hierarchy can be mounted and used in parallel to legacy hierarchies, there's no reason for systemd to use a legacy hierarchy for management even if the kernel resource controllers need to be mounted on legacy hierarchies. It can simply mount the unified hierarchy under /sys/fs/cgroup/systemd and use it without affecting other legacy hierarchies. This disables a significant amount of fragile workaround logics and would allow using features which depend on the unified hierarchy membership such bpf cgroup v2 membership test. In time, this would also allow deleting the said complexities. This patch updates systemd so that it prefers the unified hierarchy for the systemd cgroup controller hierarchy when legacy hierarchies are used for kernel resource controllers. * cg_unified(@controller) is introduced which tests whether the specific controller in on unified hierarchy and used to choose the unified hierarchy code path for process and service management when available. Kernel controller specific operations remain gated by cg_all_unified(). * "systemd.legacy_systemd_cgroup_controller" kernel argument can be used to force the use of legacy hierarchy for systemd cgroup controller. * nspawn: By default nspawn uses the same hierarchies as the host. If UNIFIED_CGROUP_HIERARCHY is set to 1, unified hierarchy is used for all. If 0, legacy for all. * nspawn: arg_unified_cgroup_hierarchy is made an enum and now encodes one of three options - legacy, only systemd controller on unified, and unified. The value is passed into mount setup functions and controls cgroup configuration. * nspawn: Interpretation of SYSTEMD_CGROUP_CONTROLLER to the actual mount option is moved to mount_legacy_cgroup_hierarchy() so that it can take an appropriate action depending on the configuration of the host. v2: - CGroupUnified enum replaces open coded integer values to indicate the cgroup operation mode. - Various style updates. v3: Fixed a bug in detect_unified_cgroup_hierarchy() introduced during v2. v4: Restored legacy container on unified host support and fixed another bug in detect_unified_cgroup_hierarchy(). --- src/basic/cgroup-util.c | 113 ++++++++++++++++++++++++++++++++++++--------- src/basic/cgroup-util.h | 10 ++++ src/core/cgroup.c | 24 ++++++---- src/core/manager.c | 2 +- src/core/mount-setup.c | 6 ++- src/core/scope.c | 2 +- src/core/service.c | 2 +- src/core/unit.c | 2 +- src/nspawn/nspawn-cgroup.c | 13 +++--- src/nspawn/nspawn-cgroup.h | 6 ++- src/nspawn/nspawn-mount.c | 42 ++++++++++------- src/nspawn/nspawn-mount.h | 6 ++- src/nspawn/nspawn.c | 26 ++++++++--- 13 files changed, 181 insertions(+), 73 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 5473fec0dd..1ef1de0604 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -869,7 +869,7 @@ int cg_set_task_access( if (r < 0) return r; - unified = cg_all_unified(); + unified = cg_unified(controller); if (unified < 0) return unified; if (unified) @@ -893,18 +893,17 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) { assert(path); assert(pid >= 0); - unified = cg_all_unified(); + if (controller) { + if (!cg_controller_is_valid(controller)) + return -EINVAL; + } else + controller = SYSTEMD_CGROUP_CONTROLLER; + + unified = cg_unified(controller); if (unified < 0) return unified; - if (unified == 0) { - if (controller) { - if (!cg_controller_is_valid(controller)) - return -EINVAL; - } else - controller = SYSTEMD_CGROUP_CONTROLLER; - + if (unified == 0) cs = strlen(controller); - } fs = procfs_file_alloca(pid, "cgroup"); f = fopen(fs, "re"); @@ -969,7 +968,7 @@ int cg_install_release_agent(const char *controller, const char *agent) { assert(agent); - unified = cg_all_unified(); + unified = cg_unified(controller); if (unified < 0) return unified; if (unified) /* doesn't apply to unified hierarchy */ @@ -1020,7 +1019,7 @@ int cg_uninstall_release_agent(const char *controller) { _cleanup_free_ char *fs = NULL; int r, unified; - unified = cg_all_unified(); + unified = cg_unified(controller); if (unified < 0) return unified; if (unified) /* Doesn't apply to unified hierarchy */ @@ -1076,7 +1075,7 @@ int cg_is_empty_recursive(const char *controller, const char *path) { if (controller && (isempty(path) || path_equal(path, "/"))) return false; - unified = cg_all_unified(); + unified = cg_unified(controller); if (unified < 0) return unified; @@ -2224,9 +2223,10 @@ int cg_kernel_controllers(Set *controllers) { return 0; } -static thread_local int unified_cache = -1; +static thread_local CGroupUnified unified_cache = CGROUP_UNIFIED_UNKNOWN; + +static int cg_update_unified(void) { -int cg_all_unified(void) { struct statfs fs; /* Checks if we support the unified hierarchy. Returns an @@ -2234,24 +2234,47 @@ int cg_all_unified(void) { * have any other trouble determining if the unified hierarchy * is supported. */ - if (unified_cache >= 0) - return unified_cache; + if (unified_cache >= CGROUP_UNIFIED_NONE) + return 0; if (statfs("/sys/fs/cgroup/", &fs) < 0) return -errno; if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) - unified_cache = true; - else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC)) - unified_cache = false; - else + unified_cache = CGROUP_UNIFIED_ALL; + else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC)) { + if (statfs("/sys/fs/cgroup/systemd/", &fs) < 0) + return -errno; + + unified_cache = F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC) ? + CGROUP_UNIFIED_SYSTEMD : CGROUP_UNIFIED_NONE; + } else return -ENOMEDIUM; - return unified_cache; + return 0; +} + +int cg_unified(const char *controller) { + + int r; + + r = cg_update_unified(); + if (r < 0) + return r; + + if (streq_ptr(controller, SYSTEMD_CGROUP_CONTROLLER)) + return unified_cache >= CGROUP_UNIFIED_SYSTEMD; + else + return unified_cache >= CGROUP_UNIFIED_ALL; +} + +int cg_all_unified(void) { + + return cg_unified(NULL); } void cg_unified_flush(void) { - unified_cache = -1; + unified_cache = CGROUP_UNIFIED_UNKNOWN; } int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p) { @@ -2333,6 +2356,50 @@ bool cg_is_legacy_wanted(void) { return !cg_is_unified_wanted(); } +bool cg_is_unified_systemd_controller_wanted(void) { + static thread_local int wanted = -1; + int r, unified; + + /* If the unified hierarchy is requested in full, no need to + * bother with this. */ + if (cg_is_unified_wanted()) + return 0; + + /* If the hierarchy is already mounted, then follow whatever + * was chosen for it. */ + unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER); + if (unified >= 0) + return unified; + + /* Otherwise, let's see what the kernel command line has to + * say. Since checking that is expensive, let's cache the + * result. */ + if (wanted >= 0) + return wanted; + + r = get_proc_cmdline_key("systemd.legacy_systemd_cgroup_controller", NULL); + if (r > 0) { + wanted = false; + } else { + _cleanup_free_ char *value = NULL; + + r = get_proc_cmdline_key("systemd.legacy_systemd_cgroup_controller=", &value); + if (r < 0) + return true; + + if (r == 0) + wanted = true; + else + wanted = parse_boolean(value) <= 0; + } + + return wanted; +} + +bool cg_is_legacy_systemd_controller_wanted(void) { + return cg_is_legacy_wanted() && !cg_is_unified_systemd_controller_wanted(); +} + int cg_weight_parse(const char *s, uint64_t *ret) { uint64_t u; int r; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 5fa856affc..5d9bee50f5 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -112,6 +112,13 @@ static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) { (x >= CGROUP_BLKIO_WEIGHT_MIN && x <= CGROUP_BLKIO_WEIGHT_MAX); } +typedef enum CGroupUnified { + CGROUP_UNIFIED_UNKNOWN = -1, + CGROUP_UNIFIED_NONE = 0, /* Both systemd and controllers on legacy */ + CGROUP_UNIFIED_SYSTEMD = 1, /* Only systemd on unified */ + CGROUP_UNIFIED_ALL = 2, /* Both systemd and controllers on unified */ +} CGroupUnified; + /* * General rules: * @@ -226,10 +233,13 @@ int cg_kernel_controllers(Set *controllers); bool cg_ns_supported(void); int cg_all_unified(void); +int cg_unified(const char *controller); void cg_unified_flush(void); bool cg_is_unified_wanted(void); bool cg_is_legacy_wanted(void); +bool cg_is_unified_systemd_controller_wanted(void); +bool cg_is_legacy_systemd_controller_wanted(void); const char* cgroup_controller_to_string(CGroupController c) _const_; CGroupController cgroup_controller_from_string(const char *s) _pure_; diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 7c6fc01c0e..4b73a9ac13 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -1245,7 +1245,7 @@ int unit_watch_cgroup(Unit *u) { return 0; /* Only applies to the unified hierarchy */ - r = cg_all_unified(); + r = cg_unified(SYSTEMD_CGROUP_CONTROLLER); if (r < 0) return log_unit_error_errno(u, r, "Failed detect whether the unified hierarchy is used: %m"); if (r == 0) @@ -1645,7 +1645,7 @@ int unit_watch_all_pids(Unit *u) { if (!u->cgroup_path) return -ENOENT; - if (cg_all_unified() > 0) /* On unified we can use proper notifications */ + if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) > 0) /* On unified we can use proper notifications */ return 0; return unit_watch_pids_in_path(u, u->cgroup_path); @@ -1718,7 +1718,7 @@ static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents, int manager_setup_cgroup(Manager *m) { _cleanup_free_ char *path = NULL; CGroupController c; - int r, unified; + int r, all_unified, systemd_unified; char *e; assert(m); @@ -1755,11 +1755,17 @@ int manager_setup_cgroup(Manager *m) { if (r < 0) return log_error_errno(r, "Cannot find cgroup mount point: %m"); - unified = cg_all_unified(); - if (unified < 0) - return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m"); - if (unified > 0) + all_unified = cg_all_unified(); + systemd_unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER); + + if (all_unified < 0 || systemd_unified < 0) + return log_error_errno(all_unified < 0 ? all_unified : systemd_unified, + "Couldn't determine if we are running in the unified hierarchy: %m"); + + if (all_unified > 0) log_debug("Unified cgroup hierarchy is located at %s.", path); + else if (systemd_unified > 0) + log_debug("Unified cgroup hierarchy is located at %s. Controllers are on legacy hierarchies.", path); else log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path); @@ -1767,7 +1773,7 @@ int manager_setup_cgroup(Manager *m) { const char *scope_path; /* 3. Install agent */ - if (unified) { + if (systemd_unified) { /* In the unified hierarchy we can get * cgroup empty notifications via inotify. */ @@ -1827,7 +1833,7 @@ int manager_setup_cgroup(Manager *m) { return log_error_errno(errno, "Failed to open pin file: %m"); /* 6. Always enable hierarchical support if it exists... */ - if (!unified) + if (!all_unified) (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1"); } diff --git a/src/core/manager.c b/src/core/manager.c index 108591c464..5c58e64a1b 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -766,7 +766,7 @@ static int manager_setup_cgroups_agent(Manager *m) { if (!MANAGER_IS_SYSTEM(m)) return 0; - if (cg_all_unified() > 0) /* We don't need this anymore on the unified hierarchy */ + if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) > 0) /* We don't need this anymore on the unified hierarchy */ return 0; if (m->cgroups_agent_fd < 0) { diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c index 5d8ab0ec70..ca63a93e8b 100644 --- a/src/core/mount-setup.c +++ b/src/core/mount-setup.c @@ -99,10 +99,12 @@ static const MountPoint mount_table[] = { cg_is_unified_wanted, MNT_FATAL|MNT_IN_CONTAINER }, { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER }, + { "cgroup", "/sys/fs/cgroup/systemd", "cgroup2", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + cg_is_unified_systemd_controller_wanted, MNT_IN_CONTAINER }, { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd,xattr", MS_NOSUID|MS_NOEXEC|MS_NODEV, - cg_is_legacy_wanted, MNT_IN_CONTAINER }, + cg_is_legacy_systemd_controller_wanted, MNT_IN_CONTAINER }, { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV, - cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER }, + cg_is_legacy_systemd_controller_wanted, MNT_FATAL|MNT_IN_CONTAINER }, { "pstore", "/sys/fs/pstore", "pstore", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL, MNT_NONE }, #ifdef ENABLE_EFI diff --git a/src/core/scope.c b/src/core/scope.c index 7c72bb7091..65fa65493b 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -441,7 +441,7 @@ static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) { /* If the PID set is empty now, then let's finish this off (On unified we use proper notifications) */ - if (cg_all_unified() <= 0 && set_isempty(u->pids)) + if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) <= 0 && set_isempty(u->pids)) scope_notify_cgroup_empty_event(u); } diff --git a/src/core/service.c b/src/core/service.c index 29e53867bf..ef5f506fa1 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2866,7 +2866,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { /* If the PID set is empty now, then let's finish this off (On unified we use proper notifications) */ - if (cg_all_unified() <= 0 && set_isempty(u->pids)) + if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) <= 0 && set_isempty(u->pids)) service_notify_cgroup_empty_event(u); } diff --git a/src/core/unit.c b/src/core/unit.c index b24c32569c..d690cf89de 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3695,7 +3695,7 @@ int unit_kill_context( * there we get proper events. Hence rely on * them.*/ - if (cg_all_unified() > 0 || + if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) > 0 || (detect_container() == 0 && !unit_cgroup_delegate(u))) wait_for_exit = true; diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index ea3cab513c..aa0da04955 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -20,7 +20,6 @@ #include #include "alloc-util.h" -#include "cgroup-util.h" #include "fd-util.h" #include "fileio.h" #include "mkdir.h" @@ -63,18 +62,18 @@ int chown_cgroup(pid_t pid, uid_t uid_shift) { return 0; } -int sync_cgroup(pid_t pid, bool unified_requested) { +int sync_cgroup(pid_t pid, CGroupUnified unified_requested) { _cleanup_free_ char *cgroup = NULL; char tree[] = "/tmp/unifiedXXXXXX", pid_string[DECIMAL_STR_MAX(pid) + 1]; bool undo_mount = false; const char *fn; int unified, r; - unified = cg_all_unified(); + unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER); if (unified < 0) return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m"); - if ((unified > 0) == unified_requested) + if ((unified > 0) == (unified_requested >= CGROUP_UNIFIED_SYSTEMD)) return 0; /* When the host uses the legacy cgroup setup, but the @@ -117,7 +116,7 @@ finish: return r; } -int create_subcgroup(pid_t pid, bool unified_requested) { +int create_subcgroup(pid_t pid, CGroupUnified unified_requested) { _cleanup_free_ char *cgroup = NULL; const char *child; int unified, r; @@ -129,10 +128,10 @@ int create_subcgroup(pid_t pid, bool unified_requested) { * did not create a scope unit for the container move us and * the container into two separate subcgroups. */ - if (!unified_requested) + if (unified_requested == CGROUP_UNIFIED_NONE) return 0; - unified = cg_all_unified(); + unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER); if (unified < 0) return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m"); if (unified == 0) diff --git a/src/nspawn/nspawn-cgroup.h b/src/nspawn/nspawn-cgroup.h index 1ff35a299a..dc33da8abe 100644 --- a/src/nspawn/nspawn-cgroup.h +++ b/src/nspawn/nspawn-cgroup.h @@ -22,6 +22,8 @@ #include #include +#include "cgroup-util.h" + int chown_cgroup(pid_t pid, uid_t uid_shift); -int sync_cgroup(pid_t pid, bool unified_requested); -int create_subcgroup(pid_t pid, bool unified_requested); +int sync_cgroup(pid_t pid, CGroupUnified unified_requested); +int create_subcgroup(pid_t pid, CGroupUnified unified_requested); diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index b5d83d481a..295b75341f 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -21,7 +21,6 @@ #include #include "alloc-util.h" -#include "cgroup-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" @@ -661,7 +660,8 @@ static int get_controllers(Set *subsystems) { return 0; } -static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controller, const char *hierarchy, bool read_only) { +static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controller, const char *hierarchy, + CGroupUnified unified_requested, bool read_only) { char *to; int r; @@ -677,7 +677,15 @@ static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controlle /* The superblock mount options of the mount point need to be * identical to the hosts', and hence writable... */ - if (mount("cgroup", to, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, controller) < 0) + if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { + if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) + r = mount("cgroup", to, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); + else + r = mount("cgroup", to, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr"); + } else + r = mount("cgroup", to, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, controller); + + if (r < 0) return log_error_errno(errno, "Failed to mount to %s: %m", to); /* ... hence let's only make the bind mount read-only, not the @@ -691,8 +699,8 @@ static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controlle /* Mount a legacy cgroup hierarchy when cgroup namespaces are supported. */ static int mount_legacy_cgns_supported( - bool userns, uid_t uid_shift, uid_t uid_range, - const char *selinux_apifs_context) { + CGroupUnified unified_requested, bool userns, uid_t uid_shift, + uid_t uid_range, const char *selinux_apifs_context) { _cleanup_set_free_free_ Set *controllers = NULL; const char *cgroup_root = "/sys/fs/cgroup", *c; int r; @@ -739,7 +747,7 @@ static int mount_legacy_cgns_supported( if (!controller) break; - r = mount_legacy_cgroup_hierarchy("", controller, controller, !userns); + r = mount_legacy_cgroup_hierarchy("", controller, controller, unified_requested, !userns); if (r < 0) return r; @@ -773,7 +781,7 @@ static int mount_legacy_cgns_supported( } skip_controllers: - r = mount_legacy_cgroup_hierarchy("", "none,name=systemd,xattr", "systemd", false); + r = mount_legacy_cgroup_hierarchy("", SYSTEMD_CGROUP_CONTROLLER, "systemd", unified_requested, false); if (r < 0) return r; @@ -788,7 +796,7 @@ skip_controllers: /* Mount legacy cgroup hierarchy when cgroup namespaces are unsupported. */ static int mount_legacy_cgns_unsupported( const char *dest, - bool userns, uid_t uid_shift, uid_t uid_range, + CGroupUnified unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { _cleanup_set_free_free_ Set *controllers = NULL; const char *cgroup_root; @@ -839,7 +847,7 @@ static int mount_legacy_cgns_unsupported( if (r == -EINVAL) { /* Not a symbolic link, but directly a single cgroup hierarchy */ - r = mount_legacy_cgroup_hierarchy(dest, controller, controller, true); + r = mount_legacy_cgroup_hierarchy(dest, controller, controller, unified_requested, true); if (r < 0) return r; @@ -859,7 +867,7 @@ static int mount_legacy_cgns_unsupported( continue; } - r = mount_legacy_cgroup_hierarchy(dest, combined, combined, true); + r = mount_legacy_cgroup_hierarchy(dest, combined, combined, unified_requested, true); if (r < 0) return r; @@ -872,7 +880,7 @@ static int mount_legacy_cgns_unsupported( } skip_controllers: - r = mount_legacy_cgroup_hierarchy(dest, "none,name=systemd,xattr", "systemd", false); + r = mount_legacy_cgroup_hierarchy(dest, SYSTEMD_CGROUP_CONTROLLER, "systemd", unified_requested, false); if (r < 0) return r; @@ -914,22 +922,22 @@ static int mount_unified_cgroups(const char *dest) { int mount_cgroups( const char *dest, - bool unified_requested, + CGroupUnified unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool use_cgns) { - if (unified_requested) + if (unified_requested >= CGROUP_UNIFIED_ALL) return mount_unified_cgroups(dest); else if (use_cgns && cg_ns_supported()) - return mount_legacy_cgns_supported(userns, uid_shift, uid_range, selinux_apifs_context); + return mount_legacy_cgns_supported(unified_requested, userns, uid_shift, uid_range, selinux_apifs_context); - return mount_legacy_cgns_unsupported(dest, userns, uid_shift, uid_range, selinux_apifs_context); + return mount_legacy_cgns_unsupported(dest, unified_requested, userns, uid_shift, uid_range, selinux_apifs_context); } int mount_systemd_cgroup_writable( const char *dest, - bool unified_requested) { + CGroupUnified unified_requested) { _cleanup_free_ char *own_cgroup_path = NULL; const char *systemd_root, *systemd_own; @@ -945,7 +953,7 @@ int mount_systemd_cgroup_writable( if (path_equal(own_cgroup_path, "/")) return 0; - if (unified_requested) { + if (unified_requested >= CGROUP_UNIFIED_ALL) { systemd_own = strjoina(dest, "/sys/fs/cgroup", own_cgroup_path); systemd_root = prefix_roota(dest, "/sys/fs/cgroup"); } else { diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h index 0eff8e1006..7307a838a5 100644 --- a/src/nspawn/nspawn-mount.h +++ b/src/nspawn/nspawn-mount.h @@ -21,6 +21,8 @@ #include +#include "cgroup-util.h" + typedef enum VolatileMode { VOLATILE_NO, VOLATILE_YES, @@ -58,8 +60,8 @@ int custom_mount_compare(const void *a, const void *b); int mount_all(const char *dest, bool use_userns, bool in_userns, bool use_netns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); int mount_sysfs(const char *dest); -int mount_cgroups(const char *dest, bool unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool use_cgns); -int mount_systemd_cgroup_writable(const char *dest, bool unified_requested); +int mount_cgroups(const char *dest, CGroupUnified unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool use_cgns); +int mount_systemd_cgroup_writable(const char *dest, CGroupUnified unified_requested); int mount_custom(const char *dest, CustomMount *mounts, unsigned n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 429b6ddc4f..24d243109a 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -188,7 +188,7 @@ static UserNamespaceMode arg_userns_mode = USER_NAMESPACE_NO; static uid_t arg_uid_shift = UID_INVALID, arg_uid_range = 0x10000U; static bool arg_userns_chown = false; static int arg_kill_signal = 0; -static bool arg_unified_cgroup_hierarchy = false; +static CGroupUnified arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_UNKNOWN; static SettingsMask arg_settings_mask = 0; static int arg_settings_trusted = -1; static char **arg_parameters = NULL; @@ -318,7 +318,14 @@ static int custom_mounts_prepare(void) { static int detect_unified_cgroup_hierarchy(void) { const char *e; - int r; + int r, all_unified, systemd_unified; + + all_unified = cg_all_unified(); + systemd_unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER); + + if (all_unified < 0 || systemd_unified < 0) + return log_error_errno(all_unified < 0 ? all_unified : systemd_unified, + "Failed to determine whether the unified cgroups hierarchy is used: %m"); /* Allow the user to control whether the unified hierarchy is used */ e = getenv("UNIFIED_CGROUP_HIERARCHY"); @@ -326,17 +333,22 @@ static int detect_unified_cgroup_hierarchy(void) { r = parse_boolean(e); if (r < 0) return log_error_errno(r, "Failed to parse $UNIFIED_CGROUP_HIERARCHY."); + if (r > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL; + else + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; - arg_unified_cgroup_hierarchy = r; return 0; } /* Otherwise inherit the default from the host system */ - r = cg_all_unified(); - if (r < 0) - return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m"); + if (all_unified > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL; + else if (systemd_unified > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_SYSTEMD; + else + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; - arg_unified_cgroup_hierarchy = r; return 0; } -- cgit v1.2.3-54-g00ecf From 3bdccf69ca626d6c2f6653044f1f68d9c9da0e42 Mon Sep 17 00:00:00 2001 From: Michael Chapman Date: Thu, 18 Aug 2016 17:46:21 +1000 Subject: networkd: do not touch link_messages when expiring routes link_messages is used during link configuration to advance the link state machine through SETTING_ADDRESSES -> SETTING_ROUTES -> CONFIGURED. If a route expires in the middle of this, it is possible for link_messages to hit zero inside route_expire_callback, rather than in route_handler or address_handler where it would trigger the next step in configuration. Should this happen, the link will not complete configuration, and it may not have its static routes configured. Since route_expire_callback does not need to do anything once the expired route has been removed from the kernel, it is safe to simply not account for the netlink request. --- src/network/networkd-route.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 82f9047ff6..5335df53c7 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -441,20 +441,14 @@ static int route_expire_callback(sd_netlink *rtnl, sd_netlink_message *m, void * assert(m); assert(link); assert(link->ifname); - assert(link->link_messages > 0); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; - link->link_messages--; - r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EEXIST) log_link_warning_errno(link, r, "could not remove route: %m"); - if (link->link_messages == 0) - log_link_debug(link, "route removed"); - return 1; } @@ -467,11 +461,8 @@ int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { r = route_remove(route, route->link, route_expire_callback); if (r < 0) log_warning_errno(r, "Could not remove route: %m"); - else { - /* route may not be exist in kernel. If we fail still remove it */ - route->link->link_messages++; + else route_free(route); - } return 1; } -- cgit v1.2.3-54-g00ecf From a0d95bbc38e60b1ac0b6b57d7a0ac3246d1576be Mon Sep 17 00:00:00 2001 From: Michael Chapman Date: Thu, 18 Aug 2016 17:54:12 +1000 Subject: networkd: use RT_TABLE_MAIN by default The default route table used by sd-netlink (and iproute2) is RT_TABLE_MAIN, not RT_TABLE_DEFAULT. Ensure networkd has the same idea. --- src/network/networkd-route.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 5335df53c7..b197a5da6b 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -41,7 +41,7 @@ int route_new(Route **ret) { route->family = AF_UNSPEC; route->scope = RT_SCOPE_UNIVERSE; route->protocol = RTPROT_UNSPEC; - route->table = RT_TABLE_DEFAULT; + route->table = RT_TABLE_MAIN; route->lifetime = USEC_INFINITY; *ret = route; @@ -549,14 +549,12 @@ int route_configure( if (r < 0) return log_error_errno(r, "Could not set flags: %m"); - if (route->table != RT_TABLE_DEFAULT) { - + if (route->table != RT_TABLE_MAIN) { if (route->table < 256) { r = sd_rtnl_message_route_set_table(req, route->table); if (r < 0) return log_error_errno(r, "Could not set route table: %m"); } else { - r = sd_rtnl_message_route_set_table(req, RT_TABLE_UNSPEC); if (r < 0) return log_error_errno(r, "Could not set route table: %m"); -- cgit v1.2.3-54-g00ecf From 8673cf13c08998b50818346b703ad91fe5facfdf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Aug 2016 18:32:42 +0200 Subject: bus-util: unify loop around bus_append_unit_property_assignment() This is done exactly the same way a couple of times at various places, let's unify this into one version. --- src/nspawn/nspawn-register.c | 9 +++------ src/run/run.c | 9 +++------ src/shared/bus-unit-util.c | 15 +++++++++++++++ src/shared/bus-unit-util.h | 1 + src/systemctl/systemctl.c | 9 +++------ 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/nspawn/nspawn-register.c b/src/nspawn/nspawn-register.c index e5b76a0c5d..06c56d9ec8 100644 --- a/src/nspawn/nspawn-register.c +++ b/src/nspawn/nspawn-register.c @@ -68,7 +68,6 @@ int register_machine( local_ifindex > 0 ? 1 : 0, local_ifindex); } else { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; - char **i; unsigned j; r = sd_bus_message_new_method_call( @@ -157,11 +156,9 @@ int register_machine( return bus_log_create_error(r); } - STRV_FOREACH(i, properties) { - r = bus_append_unit_property_assignment(m, *i); - if (r < 0) - return r; - } + r = bus_append_unit_property_assignment_many(m, properties); + if (r < 0) + return r; r = sd_bus_message_close_container(m); if (r < 0) diff --git a/src/run/run.c b/src/run/run.c index 1917ffd857..f4a90fce71 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -410,18 +410,15 @@ static int parse_argv(int argc, char *argv[]) { } static int transient_unit_set_properties(sd_bus_message *m, char **properties) { - char **i; int r; r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description); if (r < 0) return r; - STRV_FOREACH(i, properties) { - r = bus_append_unit_property_assignment(m, *i); - if (r < 0) - return r; - } + r = bus_append_unit_property_assignment_many(m, properties); + if (r < 0) + return r; return 0; } diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index f9e12e0578..28bfa8b522 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -568,6 +568,21 @@ finish: return 0; } +int bus_append_unit_property_assignment_many(sd_bus_message *m, char **l) { + char **i; + int r; + + assert(m); + + STRV_FOREACH(i, l) { + r = bus_append_unit_property_assignment(m, *i); + if (r < 0) + return r; + } + + return 0; +} + typedef struct BusWaitForJobs { sd_bus *bus; Set *jobs; diff --git a/src/shared/bus-unit-util.h b/src/shared/bus-unit-util.h index c0c172f336..d102ea180e 100644 --- a/src/shared/bus-unit-util.h +++ b/src/shared/bus-unit-util.h @@ -41,6 +41,7 @@ typedef struct UnitInfo { int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u); int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment); +int bus_append_unit_property_assignment_many(sd_bus_message *m, char **l); typedef struct BusWaitForJobs BusWaitForJobs; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index b4ce6fba5a..4444e3064d 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5093,7 +5093,6 @@ static int set_property(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *n = NULL; sd_bus *bus; - char **i; int r; r = acquire_bus(BUS_MANAGER, &bus); @@ -5124,11 +5123,9 @@ static int set_property(int argc, char *argv[], void *userdata) { if (r < 0) return bus_log_create_error(r); - STRV_FOREACH(i, strv_skip(argv, 2)) { - r = bus_append_unit_property_assignment(m, *i); - if (r < 0) - return r; - } + r = bus_append_unit_property_assignment_many(m, strv_skip(argv, 2)); + if (r < 0) + return r; r = sd_bus_message_close_container(m); if (r < 0) -- cgit v1.2.3-54-g00ecf From ad2c17019a2a25ace8d604b069124b361874139a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 6 Aug 2016 00:30:12 +0200 Subject: run: various minor improvements Let's improve the --help text a bit, and other changes. --- man/systemd-run.xml | 2 +- src/run/run.c | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/man/systemd-run.xml b/man/systemd-run.xml index 9c1a29218e..1a30c0706b 100644 --- a/man/systemd-run.xml +++ b/man/systemd-run.xml @@ -45,7 +45,7 @@ systemd-run - Run programs in transient scope or service or timer units + Run programs in transient scope units, service units, or timer-scheduled service units diff --git a/src/run/run.c b/src/run/run.c index f4a90fce71..0797547684 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -83,9 +83,7 @@ static void polkit_agent_open_if_enabled(void) { static void help(void) { printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n" - "Run the specified command in a transient scope or service or timer\n" - "unit. If a timer option is specified and the unit specified with\n" - "the --unit option exists, the command can be omitted.\n\n" + "Run the specified command in a transient scope or service.\n\n" " -h --help Show this help\n" " --version Show package version\n" " --no-ask-password Do not prompt for password\n" @@ -94,7 +92,7 @@ static void help(void) { " -M --machine=CONTAINER Operate on local container\n" " --scope Run this as scope rather than service\n" " --unit=UNIT Run under the specified unit name\n" - " -p --property=NAME=VALUE Set unit property\n" + " -p --property=NAME=VALUE Set service or scope unit property\n" " --description=TEXT Description for unit\n" " --slice=SLICE Run in the specified slice\n" " --no-block Do not wait until operation finished\n" @@ -107,15 +105,15 @@ static void help(void) { " -E --setenv=NAME=VALUE Set environment\n" " -t --pty Run service on pseudo tty\n" " -q --quiet Suppress information messages during runtime\n\n" - "Timer options:\n\n" + "Timer options:\n" " --on-active=SECONDS Run after SECONDS delay\n" " --on-boot=SECONDS Run SECONDS after machine was booted up\n" " --on-startup=SECONDS Run SECONDS after systemd activation\n" " --on-unit-active=SECONDS Run SECONDS after the last activation\n" " --on-unit-inactive=SECONDS Run SECONDS after the last deactivation\n" " --on-calendar=SPEC Realtime timer\n" - " --timer-property=NAME=VALUE Set timer unit property\n", - program_invocation_short_name); + " --timer-property=NAME=VALUE Set timer unit property\n" + , program_invocation_short_name); } static bool with_timer(void) { @@ -178,7 +176,7 @@ static int parse_argv(int argc, char *argv[]) { { "on-calendar", required_argument, NULL, ARG_ON_CALENDAR }, { "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY }, { "no-block", no_argument, NULL, ARG_NO_BLOCK }, - { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, {}, }; @@ -195,13 +193,13 @@ static int parse_argv(int argc, char *argv[]) { help(); return 0; + case ARG_VERSION: + return version(); + case ARG_NO_ASK_PASSWORD: arg_ask_password = false; break; - case ARG_VERSION: - return version(); - case ARG_USER: arg_user = true; break; @@ -1141,7 +1139,7 @@ static int start_transient_timer( if (r < 0) return bus_log_create_error(r); - if (argv[0]) { + if (!strv_isempty(argv)) { r = sd_bus_message_open_container(m, 'r', "sa(sv)"); if (r < 0) return bus_log_create_error(r); -- cgit v1.2.3-54-g00ecf From 450442cf93375af58161c1a9b973e3dfba60cba0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 6 Aug 2016 00:32:46 +0200 Subject: add a new tool for creating transient mount and automount units MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds "systemd-mount" which is for transient mount and automount units what "systemd-run" is for transient service, scope and timer units. The tool allows establishing mounts and automounts during runtime. It is very similar to the usual /bin/mount commands, but can pull in additional dependenices on access (for example, it pulls in fsck automatically), an take benefit of the automount logic. This tool is particularly useful for mount removable file systems (such as USB sticks), as the automount logic (together with automatic unmount-on-idle), as well as automatic fsck on first access ensure that the removable file system has a high chance to remain in a fully clean state even when it is unplugged abruptly, and returns to a clean state on the next re-plug. This is a follow-up for #2471, as it adds a simple client-side for the transient automount logic added in that PR. In later work it might make sense to invoke this tool automatically from udev rules in order to implement a simpler and safer version of removable media management á la udisks. --- .gitignore | 1 + Makefile-man.am | 2 + Makefile.am | 8 + man/standard-options.xml | 6 + man/systemd-mount.xml | 295 ++++++++++++ man/systemd-run.xml | 1 + src/basic/mount-util.c | 1 - src/mount/Makefile | 1 + src/mount/mount-tool.c | 1112 ++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 1426 insertions(+), 1 deletion(-) create mode 100644 man/systemd-mount.xml create mode 120000 src/mount/Makefile create mode 100644 src/mount/mount-tool.c diff --git a/.gitignore b/.gitignore index f7db68b4a6..6caa8218bd 100644 --- a/.gitignore +++ b/.gitignore @@ -89,6 +89,7 @@ /systemd-machine-id-setup /systemd-machined /systemd-modules-load +/systemd-mount /systemd-networkd /systemd-networkd-wait-online /systemd-notify diff --git a/Makefile-man.am b/Makefile-man.am index 3ac1906a4a..bf8de1e58f 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -121,6 +121,7 @@ MANPAGES += \ man/systemd-journald.service.8 \ man/systemd-machine-id-commit.service.8 \ man/systemd-machine-id-setup.1 \ + man/systemd-mount.1 \ man/systemd-notify.1 \ man/systemd-nspawn.1 \ man/systemd-path.1 \ @@ -2651,6 +2652,7 @@ EXTRA_DIST += \ man/systemd-machine-id-setup.xml \ man/systemd-machined.service.xml \ man/systemd-modules-load.service.xml \ + man/systemd-mount.xml \ man/systemd-networkd-wait-online.service.xml \ man/systemd-networkd.service.xml \ man/systemd-notify.xml \ diff --git a/Makefile.am b/Makefile.am index d4e3e9a013..336f12880c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -384,6 +384,7 @@ bin_PROGRAMS = \ systemd-delta \ systemd-analyze \ systemd-run \ + systemd-mount \ systemd-stdio-bridge \ systemd-path @@ -3132,6 +3133,13 @@ systemd_run_SOURCES = \ systemd_run_LDADD = \ libsystemd-shared.la +# ------------------------------------------------------------------------------ +systemd_mount_SOURCES = \ + src/mount/mount-tool.c + +systemd_mount_LDADD = \ + libsystemd-shared.la + # ------------------------------------------------------------------------------ systemd_stdio_bridge_SOURCES = \ src/stdio-bridge/stdio-bridge.c diff --git a/man/standard-options.xml b/man/standard-options.xml index f214463392..f718451a1b 100644 --- a/man/standard-options.xml +++ b/man/standard-options.xml @@ -28,6 +28,12 @@ + + + + Do not query the user for authentication for privileged operations. + + diff --git a/man/systemd-mount.xml b/man/systemd-mount.xml new file mode 100644 index 0000000000..e6c07863c0 --- /dev/null +++ b/man/systemd-mount.xml @@ -0,0 +1,295 @@ + + + + + + + + + systemd-mount + systemd + + + + Developer + Lennart + Poettering + lennart@poettering.net + + + + + + systemd-mount + 1 + + + + systemd-mount + Establish a mount or auto-mount point transiently + + + + + systemd-mount + OPTIONS + WHAT + WHERE + + + systemd-mount + OPTIONS + + + + + + Description + + systemd-mount may be used to create and start a transient .mount or + .automount unit of the file system WHAT on the mount point + WHERE. + + In many ways, systemd-mount is similar to the lower-level + mount8 command, however instead + of executing the mount operation directly and immediately, systemd-mount schedules it through + the service manager job queue, so that it may pull in further dependencies (such as parent mounts, or a file system + checker to execute a priori), and may make use of the auto-mounting logic. + + The command takes either one or two arguments. If only one argument is specified it should refer to a block + device containing a file system (e.g. /dev/sdb1), which is then probed for a label and other + metadata, and is mounted to a directory whose name is generated from the label. In this mode the block device must + exist at the time of invocation of the command, so that it may be probed. If the device is found to be a removable + block device (e.g. a USB stick) an automount point instead of a regular mount point is created (i.e. the + option is implied, see below). + + If two arguments are specified the first indicates the mount source (the WHAT) and + the second indicates the path to mount it on (the WHERE). In this mode no probing of the + source is attempted, and a backing device node doesn't have to exist yet. However, if this mode is combined with + , device node probing for additional metadata is enabled, and – much like in the + single-argument case discussed above – the specified device has to exist at the time of invocation of the + command. + + Use the command to show a terse table of all local, known block devices with file + systems that may be mounted with this command. + + + + Options + + The following options are understood: + + + + + + + + Do not synchronously wait for the requested operation to finish. If this is not specified, the job will + be verified, enqueued and systemd-mount will wait until the mount or automount unit's + start-up is completed. By passing this argument, it is only verified and enqueued. + + + + + + + + + + + Suppresses additional informational output while running. + + + + + + Enable probing of the mount source. This switch is implied if a single argument is specified on + the command line. If passed, additional metadata is read from the device to enhance the unit to create. For + example, a descriptive string for the transient units is generated from the file system label and device + model. Moreover if a removable block device (e.g. USB stick) is detected an automount unit instead of a regular + mount unit is created, with a short idle time-out, in order to ensure the file-system is placed in a clean + state quickly after each access. + + + + + + + Specifies the file system type to mount (e.g. vfat, ext4, + …). If omitted (or set to auto) the file system is determined automatically. + + + + + + + Additional mount options for the mount point. + + + + + + Takes a boolean argument, defaults to on. Controls whether to run a file system check + immediately before the mount operation. In the automount case (see below) the + check will be run the moment the first access to the device is made, which might slightly delay the + access. + + + + + + Provide a description for the mount or automount unit. See Description= in + systemd.unit5. + + + + + + + + Sets a unit property for the mount unit that is created. This takes an assignment in the same + format as systemctl1's + set-property command. + + + + + + + Takes a boolean argument. Controls whether to create an automount point or a regular mount + point. If true an automount point is created that is backed by the actual file system at the time of first + access. If false a plain mount point is created that is backed by the actual file system immediately. Automount + points have the benefit that the file system stays unmounted and hence in clean state until it is first + accessed. In automount mode the switch (see below) may be used to ensure + the mount point is unmounted automatically after the last access and an idle period passed. + + If this switch is not specified it defaults to false. If not specified and is + used (or only a single argument passed, which implies , see above), and the file + system block device is detected to be removable, it is set to true, in order to increase the chance that the + file system is in a fully clean state if the device is unplugged abruptly. + + + + + + Equivalent to . + + + + + + Takes a time value that controls the idle timeout in automount mode. If set to + infinity (the default) no automatic unmounts are done. Otherwise the file system backing the + automount point is detached after the last access and the idle timeout passed. See + systemd.time7 for details on + the time syntax supported. This option has no effect if only a regular mount is established, and automounting + is not used. + + Note that if is used (or only a single argument passed, which implies + , see above), and the file system block device is detected to be removable, + is implied. + + + + + + Similar to , but applies additional properties to the automount + unit created, instead of the mount unit. + + + + + + Takes a boolean argument, defaults to off. This option only has an effect in automount mode, + and controls whether the automount unit shall be bound to the backing device's lifetime. If enabled, the + automount point will be removed automatically when the backing device vanishes. If disabled the automount point + stays around, and subsequent accesses will block until backing device is replugged. This option has no effect + in case of non-device mounts, such as network or virtual file system mounts. + + Note that if is used (or only a single argument passed, which implies + , see above), and the file system block device is detected to be removable, this + option is implied. + + + + + + Instead of establishing a mount or automount point, print a terse list of block devices + containing file systems that may be mounted with systemd-mount, along with useful metadata + such as labels, etc. + + + + + + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure + code otherwise. + + + + The udev Database + + If is used, systemd-mount honours a couple of additional udev + properties of block devices: + + + + SYSTEMD_MOUNT_OPTIONS= + + The mount options to use, if is not used. + + + + SYSTEMD_MOUNT_WHERE= + + The file system path to place the mount point at, instead of the automatically generated + one. + + + + + + See Also + + systemd1, + mount8, + systemctl1, + systemd.unit5, + systemd.mount5, + systemd.automount5, + systemd-run1 + + + + diff --git a/man/systemd-run.xml b/man/systemd-run.xml index 1a30c0706b..56d585cdf9 100644 --- a/man/systemd-run.xml +++ b/man/systemd-run.xml @@ -452,6 +452,7 @@ There is a screen on: systemd.exec5, systemd.resource-control5, systemd.timer5, + systemd-mount1, machinectl1 diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c index 28dc778969..bfa04394fe 100644 --- a/src/basic/mount-util.c +++ b/src/basic/mount-util.c @@ -75,7 +75,6 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id return safe_atoi(p, mnt_id); } - int fd_is_mount_point(int fd, const char *filename, int flags) { union file_handle_union h = FILE_HANDLE_INIT, h_parent = FILE_HANDLE_INIT; int mount_id = -1, mount_id_parent = -1; diff --git a/src/mount/Makefile b/src/mount/Makefile new file mode 120000 index 0000000000..d0b0e8e008 --- /dev/null +++ b/src/mount/Makefile @@ -0,0 +1 @@ +../Makefile \ No newline at end of file diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c new file mode 100644 index 0000000000..9076ba3b0b --- /dev/null +++ b/src/mount/mount-tool.c @@ -0,0 +1,1112 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#include "libudev.h" +#include "sd-bus.h" + +#include "bus-error.h" +#include "bus-unit-util.h" +#include "bus-util.h" +#include "escape.h" +#include "fstab-util.h" +#include "pager.h" +#include "parse-util.h" +#include "path-util.h" +#include "spawn-polkit-agent.h" +#include "strv.h" +#include "udev-util.h" +#include "unit-name.h" +#include "terminal-util.h" + +enum { + ACTION_DEFAULT, + ACTION_MOUNT, + ACTION_AUTOMOUNT, + ACTION_LIST, +} arg_action = ACTION_DEFAULT; + +static bool arg_no_block = false; +static bool arg_no_pager = false; +static bool arg_ask_password = true; +static bool arg_quiet = false; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static bool arg_user = false; +static const char *arg_host = NULL; +static bool arg_discover = false; +static char *arg_mount_what = NULL; +static char *arg_mount_where = NULL; +static char *arg_mount_type = NULL; +static char *arg_mount_options = NULL; +static char *arg_description = NULL; +static char **arg_property = NULL; +static usec_t arg_timeout_idle = USEC_INFINITY; +static bool arg_timeout_idle_set = false; +static char **arg_automount_property = NULL; +static int arg_bind_device = -1; +static bool arg_fsck = true; + +static void polkit_agent_open_if_enabled(void) { + + /* Open the polkit agent as a child process if necessary */ + if (!arg_ask_password) + return; + + if (arg_transport != BUS_TRANSPORT_LOCAL) + return; + + polkit_agent_open(); +} + +static void help(void) { + printf("%s [OPTIONS...] WHAT [WHERE]\n\n" + "Establish a mount or auto-mount point transiently.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-block Do not wait until operation finished\n" + " --no-pager Do not pipe output into a pager\n" + " --no-ask-password Do not prompt for password\n" + " -q --quiet Suppress information messages during runtime\n" + " --user Run as user unit\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on local container\n" + " --discover Discover mount device metadata\n" + " -t --type=TYPE File system type\n" + " -o --options=OPTIONS Mount options\n" + " --fsck=no Don't run file system check before mount\n" + " --description=TEXT Description for unit\n" + " -p --property=NAME=VALUE Set mount unit property\n" + " -A --automount=BOOL Create an auto-mount point\n" + " --timeout-idle-sec=SEC Specify automount idle timeout\n" + " --automount-property=NAME=VALUE\n" + " Set automount unit property\n" + " --bind-device Bind automount unit to device\n" + " --list List mountable block devices\n" + , program_invocation_short_name); +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_NO_BLOCK, + ARG_NO_PAGER, + ARG_NO_ASK_PASSWORD, + ARG_USER, + ARG_SYSTEM, + ARG_DISCOVER, + ARG_MOUNT_TYPE, + ARG_MOUNT_OPTIONS, + ARG_FSCK, + ARG_DESCRIPTION, + ARG_TIMEOUT_IDLE, + ARG_AUTOMOUNT, + ARG_AUTOMOUNT_PROPERTY, + ARG_BIND_DEVICE, + ARG_LIST, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-block", no_argument, NULL, ARG_NO_BLOCK }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "quiet", no_argument, NULL, 'q' }, + { "user", no_argument, NULL, ARG_USER }, + { "system", no_argument, NULL, ARG_SYSTEM }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "discover", no_argument, NULL, ARG_DISCOVER }, + { "type", required_argument, NULL, 't' }, + { "options", required_argument, NULL, 'o' }, + { "description", required_argument, NULL, ARG_DESCRIPTION }, + { "property", required_argument, NULL, 'p' }, + { "automount", required_argument, NULL, ARG_AUTOMOUNT }, + { "timeout-idle-sec", required_argument, NULL, ARG_TIMEOUT_IDLE }, + { "automount-property", required_argument, NULL, ARG_AUTOMOUNT_PROPERTY }, + { "bind-device", no_argument, NULL, ARG_BIND_DEVICE }, + { "list", no_argument, NULL, ARG_LIST }, + {}, + }; + + int r, c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hqH:M:t:o:p:A", options, NULL)) >= 0) + + switch (c) { + + case 'h': + help(); + return 0; + + case ARG_VERSION: + return version(); + + case ARG_NO_BLOCK: + arg_no_block = true; + break; + + case ARG_NO_PAGER: + arg_no_pager = true; + break; + + case ARG_NO_ASK_PASSWORD: + arg_ask_password = false; + break; + + case 'q': + arg_quiet = true; + break; + + case ARG_USER: + arg_user = true; + break; + + case ARG_SYSTEM: + arg_user = false; + break; + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case ARG_DISCOVER: + arg_discover = true; + break; + + case 't': + if (free_and_strdup(&arg_mount_type, optarg) < 0) + return log_oom(); + break; + + case 'o': + if (free_and_strdup(&arg_mount_options, optarg) < 0) + return log_oom(); + break; + + case ARG_FSCK: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --fsck= argument: %s", optarg); + + arg_fsck = r; + break; + + case ARG_DESCRIPTION: + if (free_and_strdup(&arg_description, optarg) < 0) + return log_oom(); + break; + + case 'p': + if (strv_extend(&arg_property, optarg) < 0) + return log_oom(); + + break; + + case 'A': + arg_action = ACTION_AUTOMOUNT; + break; + + case ARG_AUTOMOUNT: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "--automount= expects a valid boolean parameter: %s", optarg); + + arg_action = r ? ACTION_AUTOMOUNT : ACTION_MOUNT; + break; + + case ARG_TIMEOUT_IDLE: + r = parse_sec(optarg, &arg_timeout_idle); + if (r < 0) + return log_error_errno(r, "Failed to parse timeout: %s", optarg); + + break; + + case ARG_AUTOMOUNT_PROPERTY: + if (strv_extend(&arg_automount_property, optarg) < 0) + return log_oom(); + + break; + + case ARG_BIND_DEVICE: + arg_bind_device = true; + break; + + case ARG_LIST: + arg_action = ACTION_LIST; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_user && arg_transport != BUS_TRANSPORT_LOCAL) { + log_error("Execution in user context is not supported on non-local systems."); + return -EINVAL; + } + + if (arg_action == ACTION_LIST) { + if (optind < argc) { + log_error("Too many arguments."); + return -EINVAL; + } + + if (arg_transport != BUS_TRANSPORT_LOCAL) { + log_error("Listing devices only supported locally."); + return -EOPNOTSUPP; + } + } else { + if (optind >= argc) { + log_error("At least one argument required."); + return -EINVAL; + } + + if (argc > optind+2) { + log_error("At most two arguments required."); + return -EINVAL; + } + + arg_mount_what = fstab_node_to_udev_node(argv[optind]); + if (!arg_mount_what) + return log_oom(); + + if (argc > optind+1) { + r = path_make_absolute_cwd(argv[optind+1], &arg_mount_where); + if (r < 0) + return log_error_errno(r, "Failed to make path absolute: %m"); + } else + arg_discover = true; + + if (arg_discover && arg_transport != BUS_TRANSPORT_LOCAL) { + log_error("Automatic mount location discovery is only supported locally."); + return -EOPNOTSUPP; + } + } + + return 1; +} + +static int transient_unit_set_properties(sd_bus_message *m, char **properties) { + int r; + + r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description); + if (r < 0) + return r; + + if (arg_bind_device && is_device_path(arg_mount_what)) { + _cleanup_free_ char *device_unit = NULL; + + r = unit_name_from_path(arg_mount_what, ".device", &device_unit); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "(sv)(sv)", + "After", "as", 1, device_unit, + "BindsTo", "as", 1, device_unit); + if (r < 0) + return r; + } + + r = bus_append_unit_property_assignment_many(m, properties); + if (r < 0) + return r; + + return 0; +} + +static int transient_mount_set_properties(sd_bus_message *m) { + int r; + + assert(m); + + r = transient_unit_set_properties(m, arg_property); + if (r < 0) + return r; + + if (arg_mount_what) { + r = sd_bus_message_append(m, "(sv)", "What", "s", arg_mount_what); + if (r < 0) + return r; + } + + if (arg_mount_type) { + r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_mount_type); + if (r < 0) + return r; + } + + if (arg_mount_options) { + r = sd_bus_message_append(m, "(sv)", "Options", "s", arg_mount_options); + if (r < 0) + return r; + } + + if (arg_fsck) { + _cleanup_free_ char *fsck = NULL; + + r = unit_name_from_path_instance("systemd-fsck", arg_mount_what, ".service", &fsck); + if (r < 0) + return r; + + r = sd_bus_message_append(m, + "(sv)(sv)", + "Requires", "as", 1, fsck, + "After", "as", 1, fsck); + if (r < 0) + return r; + } + + return 0; +} + +static int transient_automount_set_properties(sd_bus_message *m) { + int r; + + assert(m); + + r = transient_unit_set_properties(m, arg_automount_property); + if (r < 0) + return r; + + if (arg_timeout_idle != USEC_INFINITY) { + r = sd_bus_message_append(m, "(sv)", "TimeoutIdleUSec", "t", arg_timeout_idle); + if (r < 0) + return r; + } + + return 0; +} + +static int start_transient_mount( + sd_bus *bus, + char **argv) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + _cleanup_free_ char *mount_unit = NULL; + int r; + + if (!arg_no_block) { + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_error_errno(r, "Could not watch jobs: %m"); + } + + r = unit_name_from_path(arg_mount_where, ".mount", &mount_unit); + if (r < 0) + return log_error_errno(r, "Failed to make mount unit name: %m"); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); + if (r < 0) + return bus_log_create_error(r); + + /* Name and mode */ + r = sd_bus_message_append(m, "ss", mount_unit, "fail"); + if (r < 0) + return bus_log_create_error(r); + + /* Properties */ + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = transient_mount_set_properties(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + /* Auxiliary units */ + r = sd_bus_message_append(m, "a(sa(sv))", 0); + if (r < 0) + return bus_log_create_error(r); + + polkit_agent_open_if_enabled(); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to start transient mount unit: %s", bus_error_message(&error, r)); + + if (w) { + const char *object; + + r = sd_bus_message_read(reply, "o", &object); + if (r < 0) + return bus_log_parse_error(r); + + r = bus_wait_for_jobs_one(w, object, arg_quiet); + if (r < 0) + return r; + } + + if (!arg_quiet) + log_info("Started unit %s%s%s for mount point: %s%s%s", + ansi_highlight(), mount_unit, ansi_normal(), + ansi_highlight(), arg_mount_where, ansi_normal()); + + return 0; +} + +static int start_transient_automount( + sd_bus *bus, + char **argv) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + _cleanup_free_ char *automount_unit = NULL, *mount_unit = NULL; + int r; + + if (!arg_no_block) { + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_error_errno(r, "Could not watch jobs: %m"); + } + + r = unit_name_from_path(arg_mount_where, ".automount", &automount_unit); + if (r < 0) + return log_error_errno(r, "Failed to make automount unit name: %m"); + + r = unit_name_from_path(arg_mount_where, ".mount", &mount_unit); + if (r < 0) + return log_error_errno(r, "Failed to make mount unit name: %m"); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); + if (r < 0) + return bus_log_create_error(r); + + /* Name and mode */ + r = sd_bus_message_append(m, "ss", automount_unit, "fail"); + if (r < 0) + return bus_log_create_error(r); + + /* Properties */ + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = transient_automount_set_properties(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + /* Auxiliary units */ + r = sd_bus_message_open_container(m, 'a', "(sa(sv))"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'r', "sa(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", mount_unit); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = transient_mount_set_properties(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + polkit_agent_open_if_enabled(); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to start transient automount unit: %s", bus_error_message(&error, r)); + + if (w) { + const char *object; + + r = sd_bus_message_read(reply, "o", &object); + if (r < 0) + return bus_log_parse_error(r); + + r = bus_wait_for_jobs_one(w, object, arg_quiet); + if (r < 0) + return r; + } + + if (!arg_quiet) + log_info("Started unit %s%s%s for mount point: %s%s%s", + ansi_highlight(), automount_unit, ansi_normal(), + ansi_highlight(), arg_mount_where, ansi_normal()); + + return 0; +} + +static int acquire_mount_type(struct udev_device *d) { + const char *v; + + assert(d); + + if (arg_mount_type) + return 0; + + v = udev_device_get_property_value(d, "ID_FS_TYPE"); + if (isempty(v)) + return 0; + + arg_mount_type = strdup(v); + if (!arg_mount_type) + return log_oom(); + + log_debug("Discovered type=%s", arg_mount_type); + return 1; +} + +static int acquire_mount_options(struct udev_device *d) { + const char *v; + + if (arg_mount_options) + return 0; + + v = udev_device_get_property_value(d, "SYSTEMD_MOUNT_OPTIONS"); + if (isempty(v)) + return 0; + + arg_mount_options = strdup(v); + if (!arg_mount_options) + return log_oom(); + + log_debug("Discovered options=%s", arg_mount_options); + return 1; +} + +static const char *get_model(struct udev_device *d) { + const char *model; + + assert(d); + + model = udev_device_get_property_value(d, "ID_MODEL_FROM_DATABASE"); + if (model) + return model; + + return udev_device_get_property_value(d, "ID_MODEL"); +} + +static const char* get_label(struct udev_device *d) { + const char *label; + + assert(d); + + label = udev_device_get_property_value(d, "ID_FS_LABEL"); + if (label) + return label; + + return udev_device_get_property_value(d, "ID_PART_ENTRY_NAME"); +} + +static int acquire_mount_where(struct udev_device *d) { + const char *v; + + if (arg_mount_where) + return 0; + + v = udev_device_get_property_value(d, "SYSTEMD_MOUNT_WHERE"); + if (isempty(v)) { + _cleanup_free_ char *escaped = NULL; + const char *name; + + name = get_label(d); + if (!name) + name = get_model(d); + if (!name) { + const char *dn; + + dn = udev_device_get_devnode(d); + if (!dn) + return 0; + + name = basename(dn); + } + + escaped = xescape(name, "\\"); + if (!filename_is_valid(escaped)) + return 0; + + arg_mount_where = strjoin("/run/media/system/", escaped, NULL); + } else + arg_mount_where = strdup(v); + + if (!arg_mount_where) + return log_oom(); + + log_debug("Discovered where=%s", arg_mount_where); + return 1; +} + +static int acquire_description(struct udev_device *d) { + const char *model, *label; + + if (arg_description) + return 0; + + model = get_model(d); + + label = get_label(d); + if (!label) + label = udev_device_get_property_value(d, "ID_PART_ENTRY_NUMBER"); + + if (model && label) + arg_description = strjoin(model, " ", label, NULL); + else if (label) + arg_description = strdup(label); + else if (model) + arg_description = strdup(model); + else + return NULL; + + if (!arg_description) + return log_oom(); + + log_debug("Discovered description=%s", arg_description); + return 1; +} + +static int acquire_removable(struct udev_device *d) { + const char *v; + + /* Shortcut this if there's no reason to check it */ + if (arg_action != ACTION_DEFAULT && arg_timeout_idle_set && arg_bind_device >= 0) + return 0; + + for (;;) { + v = udev_device_get_sysattr_value(d, "removable"); + if (v) + break; + + d = udev_device_get_parent(d); + if (!d) + return 0; + + if (!streq_ptr(udev_device_get_subsystem(d), "block")) + return 0; + } + + if (parse_boolean(v) <= 0) + return 0; + + log_debug("Discovered removable device."); + + if (arg_action == ACTION_DEFAULT) { + log_debug("Automatically turning on automount."); + arg_action = ACTION_AUTOMOUNT; + } + + if (!arg_timeout_idle_set) { + log_debug("Setting idle timeout to 1s."); + arg_timeout_idle = USEC_PER_SEC; + } + + if (arg_bind_device < 0) { + log_debug("Binding automount unit to device."); + arg_bind_device = true; + } + + return 1; +} + +static int discover_device(void) { + _cleanup_udev_device_unref_ struct udev_device *d = NULL; + _cleanup_udev_unref_ struct udev *udev = NULL; + struct stat st; + const char *v; + int r; + + if (!arg_discover) + return 0; + + if (!is_device_path(arg_mount_what)) { + log_error("Discovery only supported for block devices, don't know what to do."); + return -EINVAL; + } + + if (stat(arg_mount_what, &st) < 0) + return log_error_errno(errno, "Can't stat %s: %m", arg_mount_what); + + if (!S_ISBLK(st.st_mode)) { + log_error("Path %s is not a block device, don't know what to do.", arg_mount_what); + return -ENOTBLK; + } + + udev = udev_new(); + if (!udev) + return log_oom(); + + d = udev_device_new_from_devnum(udev, 'b', st.st_rdev); + if (!d) + return log_oom(); + + v = udev_device_get_property_value(d, "ID_FS_USAGE"); + if (!streq_ptr(v, "filesystem")) { + log_error("%s does not contain a file system.", arg_mount_what); + return -EINVAL; + } + + r = acquire_mount_type(d); + if (r < 0) + return r; + + r = acquire_mount_options(d); + if (r < 0) + return r; + + r = acquire_mount_where(d); + if (r < 0) + return r; + + r = acquire_description(d); + if (r < 0) + return r; + + r = acquire_removable(d); + if (r < 0) + return r; + + return 0; +} + +enum { + COLUMN_NODE, + COLUMN_PATH, + COLUMN_MODEL, + COLUMN_WWN, + COLUMN_FSTYPE, + COLUMN_LABEL, + COLUMN_UUID, + _COLUMN_MAX, +}; + +struct item { + char* columns[_COLUMN_MAX]; +}; + +static int compare_item(const void *a, const void *b) { + const struct item *x = a, *y = b; + + if (x->columns[COLUMN_NODE] == y->columns[COLUMN_NODE]) + return 0; + if (!x->columns[COLUMN_NODE]) + return 1; + if (!y->columns[COLUMN_NODE]) + return -1; + + return path_compare(x->columns[COLUMN_NODE], y->columns[COLUMN_NODE]); +} + +static int list_devices(void) { + + static const char * const titles[_COLUMN_MAX] = { + [COLUMN_NODE] = "NODE", + [COLUMN_PATH] = "PATH", + [COLUMN_MODEL] = "MODEL", + [COLUMN_WWN] = "WWN", + [COLUMN_FSTYPE] = "TYPE", + [COLUMN_LABEL] = "LABEL", + [COLUMN_UUID] = "UUID" + }; + + _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; + _cleanup_udev_unref_ struct udev *udev = NULL; + struct udev_list_entry *item = NULL, *first = NULL; + size_t n_allocated = 0, n = 0, i; + size_t column_width[_COLUMN_MAX]; + struct item *items = NULL; + unsigned c; + int r; + + for (c = 0; c < _COLUMN_MAX; c++) + column_width[c] = strlen(titles[c]); + + udev = udev_new(); + if (!udev) + return log_oom(); + + e = udev_enumerate_new(udev); + if (!e) + return log_oom(); + + r = udev_enumerate_add_match_subsystem(e, "block"); + if (r < 0) + return log_error_errno(r, "Failed to add block match: %m"); + + r = udev_enumerate_add_match_property(e, "ID_FS_USAGE", "filesystem"); + if (r < 0) + return log_error_errno(r, "Failed to add property match: %m"); + + r = udev_enumerate_scan_devices(e); + if (r < 0) + return log_error_errno(r, "Failed to scan devices: %m"); + + first = udev_enumerate_get_list_entry(e); + udev_list_entry_foreach(item, first) { + _cleanup_udev_device_unref_ struct udev_device *d; + struct item *j; + + d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); + if (!d) { + r = log_oom(); + goto finish; + } + + if (!GREEDY_REALLOC0(items, n_allocated, n+1)) { + r = log_oom(); + goto finish; + } + + j = items + n++; + + for (c = 0; c < _COLUMN_MAX; c++) { + const char *x; + size_t k; + + switch (c) { + + case COLUMN_NODE: + x = udev_device_get_devnode(d); + break; + + case COLUMN_PATH: + x = udev_device_get_property_value(d, "ID_PATH"); + break; + + case COLUMN_MODEL: + x = get_model(d); + break; + + case COLUMN_WWN: + x = udev_device_get_property_value(d, "ID_WWN"); + break; + + case COLUMN_FSTYPE: + x = udev_device_get_property_value(d, "ID_FS_TYPE"); + break; + + case COLUMN_LABEL: + x = get_label(d); + break; + + case COLUMN_UUID: + x = udev_device_get_property_value(d, "ID_FS_UUID"); + break; + } + + if (isempty(x)) + continue; + + j->columns[c] = strdup(x); + if (!j->columns[c]) { + r = log_oom(); + goto finish; + } + + k = strlen(x); + if (k > column_width[c]) + column_width[c] = k; + } + } + + if (n == 0) { + log_info("No devices found."); + goto finish; + } + + qsort_safe(items, n, sizeof(struct item), compare_item); + + pager_open(arg_no_pager, false); + + fputs(ansi_underline(), stdout); + for (c = 0; c < _COLUMN_MAX; c++) { + if (c > 0) + fputc(' ', stdout); + + printf("%-*s", (int) column_width[c], titles[c]); + } + fputs(ansi_normal(), stdout); + fputc('\n', stdout); + + for (i = 0; i < n; i++) { + for (c = 0; c < _COLUMN_MAX; c++) { + if (c > 0) + fputc(' ', stdout); + + printf("%-*s", (int) column_width[c], strna(items[i].columns[c])); + } + fputc('\n', stdout); + } + + r = 0; + +finish: + for (i = 0; i < n; i++) + for (c = 0; c < _COLUMN_MAX; c++) + free(items[i].columns[c]); + + free(items); + return r; +} + +int main(int argc, char* argv[]) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + + if (arg_action == ACTION_LIST) { + r = list_devices(); + goto finish; + } + + r = discover_device(); + if (r < 0) + goto finish; + if (!arg_mount_where) { + log_error("Can't figure out where to mount %s.", arg_mount_what); + r = -EINVAL; + goto finish; + } + + path_kill_slashes(arg_mount_where); + + if (path_equal(arg_mount_where, "/")) { + log_error("Refusing to operate on root directory."); + r = -EINVAL; + goto finish; + } + + if (!path_is_safe(arg_mount_where)) { + log_error("Path is contains unsafe components."); + r = -EINVAL; + goto finish; + } + + if (streq_ptr(arg_mount_type, "auto")) + arg_mount_type = mfree(arg_mount_type); + if (streq_ptr(arg_mount_options, "defaults")) + arg_mount_options = mfree(arg_mount_options); + + if (!is_device_path(arg_mount_what)) + arg_fsck = false; + + if (arg_fsck && arg_mount_type && arg_transport == BUS_TRANSPORT_LOCAL) { + r = fsck_exists(arg_mount_type); + if (r < 0) + log_warning_errno(r, "Couldn't determine whether fsck for %s exists, proceeding anyway.", arg_mount_type); + else if (r == 0) { + log_debug("Disabling file system check as fsck for %s doesn't exist.", arg_mount_type); + arg_fsck = false; /* fsck doesn't exist, let's not attempt it */ + } + } + + r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus); + if (r < 0) { + log_error_errno(r, "Failed to create bus connection: %m"); + goto finish; + } + + switch (arg_action) { + + case ACTION_MOUNT: + case ACTION_DEFAULT: + r = start_transient_mount(bus, argv + optind); + break; + + case ACTION_AUTOMOUNT: + r = start_transient_automount(bus, argv + optind); + break; + + default: + assert_not_reached("Unexpected action."); + } + +finish: + bus = sd_bus_flush_close_unref(bus); + + pager_close(); + + free(arg_mount_what); + free(arg_mount_where); + free(arg_mount_type); + free(arg_mount_options); + free(arg_description); + strv_free(arg_property); + strv_free(arg_automount_property); + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} -- cgit v1.2.3-54-g00ecf From b4c990e91b33ec0130c428a1960a60fcaa6785bc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 28 Jul 2016 09:50:28 +0200 Subject: unit: remove orphaned cgroup_netclass_id field --- src/core/unit.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/unit.h b/src/core/unit.h index a6c69938dd..513ea1614c 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -195,8 +195,6 @@ struct Unit { CGroupMask cgroup_members_mask; int cgroup_inotify_wd; - uint32_t cgroup_netclass_id; - /* How to start OnFailure units */ JobMode on_failure_job_mode; -- cgit v1.2.3-54-g00ecf From 91f2048c4166a5669f8013ddd5f4150443518434 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 28 Jul 2016 09:51:25 +0200 Subject: clean-ipc: don't filter out '.' and '..' twice --- src/shared/clean-ipc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c index a3ac7aeb82..44b7e08ce8 100644 --- a/src/shared/clean-ipc.c +++ b/src/shared/clean-ipc.c @@ -207,7 +207,7 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid) { assert(dir); - FOREACH_DIRENT(de, dir, goto fail) { + FOREACH_DIRENT_ALL(de, dir, goto fail) { struct stat st; if (STR_IN_SET(de->d_name, "..", ".")) @@ -295,7 +295,7 @@ static int clean_posix_mq(uid_t uid) { return log_warning_errno(errno, "Failed to open /dev/mqueue: %m"); } - FOREACH_DIRENT(de, dir, goto fail) { + FOREACH_DIRENT_ALL(de, dir, goto fail) { struct stat st; char fn[1+strlen(de->d_name)+1]; -- cgit v1.2.3-54-g00ecf From 3db99289c153b0a648c035d63c8b523f6d8f8e96 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 28 Jul 2016 09:51:47 +0200 Subject: clean-ipc: shorten code a bit --- src/shared/clean-ipc.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c index 44b7e08ce8..95686348c1 100644 --- a/src/shared/clean-ipc.c +++ b/src/shared/clean-ipc.c @@ -217,8 +217,7 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid) { if (errno == ENOENT) continue; - log_warning_errno(errno, "Failed to stat() POSIX shared memory segment %s: %m", de->d_name); - ret = -errno; + ret = log_warning_errno(errno, "Failed to stat() POSIX shared memory segment %s: %m", de->d_name); continue; } @@ -230,10 +229,8 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid) { kid = xopendirat(dirfd(dir), de->d_name, O_NOFOLLOW|O_NOATIME); if (!kid) { - if (errno != ENOENT) { - log_warning_errno(errno, "Failed to enter shared memory directory %s: %m", de->d_name); - ret = -errno; - } + if (errno != ENOENT) + ret = log_warning_errno(errno, "Failed to enter shared memory directory %s: %m", de->d_name); } else { r = clean_posix_shm_internal(kid, uid); if (r < 0) @@ -245,8 +242,7 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid) { if (errno == ENOENT) continue; - log_warning_errno(errno, "Failed to remove POSIX shared memory directory %s: %m", de->d_name); - ret = -errno; + ret = log_warning_errno(errno, "Failed to remove POSIX shared memory directory %s: %m", de->d_name); } } else { @@ -255,8 +251,7 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid) { if (errno == ENOENT) continue; - log_warning_errno(errno, "Failed to remove POSIX shared memory segment %s: %m", de->d_name); - ret = -errno; + ret = log_warning_errno(errno, "Failed to remove POSIX shared memory segment %s: %m", de->d_name); } } } @@ -264,8 +259,7 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid) { return ret; fail: - log_warning_errno(errno, "Failed to read /dev/shm: %m"); - return -errno; + return log_warning_errno(errno, "Failed to read /dev/shm: %m"); } static int clean_posix_shm(uid_t uid) { -- cgit v1.2.3-54-g00ecf From 92b25bcabb75846928f5ea1417808dab981d5e25 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 29 Jul 2016 16:22:30 +0200 Subject: core: make use of uid_is_valid() when checking for UID validity --- src/core/execute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/execute.c b/src/core/execute.c index 6019df7ea6..18bb421cab 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1862,7 +1862,7 @@ static int exec_child( return r; } - if (uid == UID_INVALID || gid == GID_INVALID) { + if (!uid_is_valid(uid) || !gid_is_valid(gid)) { *exit_status = EXIT_USER; return -ESRCH; } -- cgit v1.2.3-54-g00ecf From 51d73fd96a55810ca40324eec098e66c6657699b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 1 Aug 2016 17:40:37 +0200 Subject: core: move obsolete properties to the end of vtables This makes it easier to discern the relevant and obsolete parts of the vtables, and in particular helps when comparing introspection data with the actual vtable definitions. --- src/core/dbus-service.c | 11 ++++++----- src/core/dbus-unit.c | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index fab3677a01..5eac876a6e 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -50,11 +50,6 @@ const sd_bus_vtable bus_service_vtable[] = { SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0), - /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */ - SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("FailureAction", "s", property_get_failure_action, offsetof(Service, failure_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST), @@ -77,6 +72,12 @@ const sd_bus_vtable bus_service_vtable[] = { BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + + /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */ + SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_VTABLE_END }; diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index b55d2cf735..89e56a2e51 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -660,10 +660,6 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_JOINS_NAMESPACE_OF]), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("RequiresMountsFor", "as", NULL, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST), @@ -705,7 +701,6 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* obsolete alias name */ SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), @@ -721,6 +716,12 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED), + /* Obsolete properties or obsolete alias names */ + SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_VTABLE_END }; -- cgit v1.2.3-54-g00ecf From 00d9ef8560c252d8504be99cb38d1a54d35a9144 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 1 Aug 2016 19:24:40 +0200 Subject: core: add RemoveIPC= setting This adds the boolean RemoveIPC= setting to service, socket, mount and swap units (i.e. all unit types that may invoke processes). if turned on, and the unit's user/group is not root, all IPC objects of the user/group are removed when the service is shut down. The life-cycle of the IPC objects is hence bound to the unit life-cycle. This is particularly relevant for units with dynamic users, as it is essential that no objects owned by the dynamic users survive the service exiting. In fact, this patch adds code to imply RemoveIPC= if DynamicUser= is set. In order to communicate the UID/GID of an executed process back to PID 1 this adds a new "user lookup" socket pair, that is inherited into the forked processes, and closed before the exec(). This is needed since we cannot do NSS from PID 1 due to deadlock risks, However need to know the used UID/GID in order to clean up IPC owned by it if the unit shuts down. --- man/systemd.exec.xml | 60 ++++--- src/core/dbus-execute.c | 5 +- src/core/dbus-mount.c | 2 + src/core/dbus-service.c | 3 + src/core/dbus-socket.c | 2 + src/core/dbus-swap.c | 2 + src/core/execute.c | 46 ++++- src/core/execute.h | 1 + src/core/manager.c | 411 ++++++++++++++++++++++++++++++++++++++++++++- src/core/manager.h | 23 ++- src/core/mount.c | 2 + src/core/service.c | 3 + src/core/socket.c | 2 + src/core/swap.c | 2 + src/core/unit.c | 174 ++++++++++++++++++- src/core/unit.h | 18 +- src/login/logind-user.c | 11 +- src/shared/bus-unit-util.c | 2 +- src/shared/clean-ipc.c | 66 +++++--- src/shared/clean-ipc.h | 4 +- src/test/test-ipcrm.c | 2 +- 21 files changed, 777 insertions(+), 64 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index bf82326096..bcedebd5bb 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -160,14 +160,14 @@ use. However, UID/GIDs are recycled after a unit is terminated. Care should be taken that any processes running as part of a unit for which dynamic users/groups are enabled do not leave files or directories owned by these users/groups around, as a different unit might get the same UID/GID assigned later on, and thus gain access to - these files or directories. If DynamicUser= is enabled, PrivateTmp= is - implied. This ensures that the lifetime of temporary files created by the executed processes is bound to the - runtime of the service, and hence the lifetime of the dynamic user/group. Since /tmp and - /var/tmp are usually the only world-writable directories on a system this ensures that a - unit making use of dynamic user/group allocation cannot leave files around after unit termination. Use - RuntimeDirectory= (see below) in order to assign a writable runtime directory to a service, - owned by the dynamic user/group and removed automatically when the unit is terminated. Defaults to - off. + these files or directories. If DynamicUser= is enabled, RemoveIPC= and + PrivateTmp= are implied. This ensures that the lifetime of IPC objects and temporary files + created by the executed processes is bound to the runtime of the service, and hence the lifetime of the dynamic + user/group. Since /tmp and /var/tmp are usually the only + world-writable directories on a system this ensures that a unit making use of dynamic user/group allocation + cannot leave files around after unit termination. Use RuntimeDirectory= (see below) in order + to assign a writable runtime directory to a service, owned by the dynamic user/group and removed automatically + when the unit is terminated. Defaults to off. @@ -185,6 +185,18 @@ user. This does not affect commands prefixed with +. + + RemoveIPC= + + Takes a boolean parameter. If set, all System V and POSIX IPC objects owned by the user and + group the processes of this unit are run as are removed when the unit is stopped. This setting only has an + effect if at least one of User=, Group= and + DynamicUser= are used. It has no effect on IPC objects owned by the root user. Specifically, + this removes System V semaphores, as well as System V and POSIX shared memory segments and message queues. If + multiple units use the same user or group the IPC objects are removed when the last of these units is + stopped. This setting is implied if DynamicUser= is set. + + Nice= @@ -920,27 +932,19 @@ PrivateTmp= - Takes a boolean argument. If true, sets up a - new file system namespace for the executed processes and - mounts private /tmp and - /var/tmp directories inside it that is - not shared by processes outside of the namespace. This is - useful to secure access to temporary files of the process, but - makes sharing between processes via /tmp - or /var/tmp impossible. If this is - enabled, all temporary files created by a service in these - directories will be removed after the service is stopped. - Defaults to false. It is possible to run two or more units - within the same private /tmp and - /var/tmp namespace by using the + Takes a boolean argument. If true, sets up a new file system namespace for the executed + processes and mounts private /tmp and /var/tmp directories inside it + that is not shared by processes outside of the namespace. This is useful to secure access to temporary files of + the process, but makes sharing between processes via /tmp or /var/tmp + impossible. If this is enabled, all temporary files created by a service in these directories will be removed + after the service is stopped. Defaults to false. It is possible to run two or more units within the same + private /tmp and /var/tmp namespace by using the JoinsNamespaceOf= directive, see - systemd.unit5 - for details. Note that using this setting will disconnect - propagation of mounts from the service to the host - (propagation in the opposite direction continues to work). - This means that this setting may not be used for services - which shall be able to install mount points in the main mount - namespace. + systemd.unit5 for + details. Note that using this setting will disconnect propagation of mounts from the service to the host + (propagation in the opposite direction continues to work). This means that this setting may not be used for + services which shall be able to install mount points in the main mount namespace. This setting is implied if + DynamicUser= is set. diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index e35d3ccd2e..7e33a2d201 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -695,6 +695,7 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), @@ -1071,7 +1072,7 @@ int bus_exec_context_set_transient_property( "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute", - "RestrictRealtime", "DynamicUser")) { + "RestrictRealtime", "DynamicUser", "RemoveIPC")) { int b; r = sd_bus_message_read(message, "b", &b); @@ -1103,6 +1104,8 @@ int bus_exec_context_set_transient_property( c->restrict_realtime = b; else if (streq(name, "DynamicUser")) c->dynamic_user = b; + else if (streq(name, "RemoveIPC")) + c->remove_ipc = b; unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, yes_no(b)); } diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c index b4bbee0648..3c6bda4073 100644 --- a/src/core/dbus-mount.c +++ b/src/core/dbus-mount.c @@ -117,6 +117,8 @@ const sd_bus_vtable bus_mount_vtable[] = { SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Mount, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SloppyOptions", "b", bus_property_get_bool, offsetof(Mount, sloppy_options), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_EXEC_COMMAND_VTABLE("ExecMount", offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_VTABLE("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_VTABLE("ExecRemount", offsetof(Mount, exec_command[MOUNT_EXEC_REMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index 5eac876a6e..3c55e0f7fe 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -65,6 +65,9 @@ const sd_bus_vtable bus_service_vtable[] = { SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL, offsetof(Service, usb_function_descriptors), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL, offsetof(Service, usb_function_strings), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 9a071a1355..21adb64e15 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -152,6 +152,8 @@ const sd_bus_vtable bus_socket_vtable[] = { SD_BUS_PROPERTY("SocketProtocol", "i", bus_property_get_int, offsetof(Socket, socket_protocol), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TriggerLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Socket, trigger_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TriggerLimitBurst", "u", bus_property_get_unsigned, offsetof(Socket, trigger_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c index 292f8738c6..85a2c26b98 100644 --- a/src/core/dbus-swap.c +++ b/src/core/dbus-swap.c @@ -84,6 +84,8 @@ const sd_bus_vtable bus_swap_vtable[] = { SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Swap, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Swap, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Swap, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_EXEC_COMMAND_VTABLE("ExecActivate", offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), BUS_EXEC_COMMAND_VTABLE("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_VTABLE_END diff --git a/src/core/execute.c b/src/core/execute.c index 18bb421cab..4c786a2e33 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1723,11 +1723,12 @@ static int close_remaining_fds( const ExecParameters *params, ExecRuntime *runtime, DynamicCreds *dcreds, + int user_lookup_fd, int socket_fd, int *fds, unsigned n_fds) { unsigned n_dont_close = 0; - int dont_close[n_fds + 11]; + int dont_close[n_fds + 12]; assert(params); @@ -1755,9 +1756,40 @@ static int close_remaining_fds( append_socket_pair(dont_close, &n_dont_close, dcreds->group->storage_socket); } + if (user_lookup_fd >= 0) + dont_close[n_dont_close++] = user_lookup_fd; + return close_all_fds(dont_close, n_dont_close); } +static int send_user_lookup( + Unit *unit, + int user_lookup_fd, + uid_t uid, + gid_t gid) { + + assert(unit); + + /* Send the resolved UID/GID to PID 1 after we learnt it. We send a single datagram, containing the UID/GID + * data as well as the unit name. Note that we suppress sending this if no user/group to resolve was + * specified. */ + + if (user_lookup_fd < 0) + return 0; + + if (!uid_is_valid(uid) && !gid_is_valid(gid)) + return 0; + + if (writev(user_lookup_fd, + (struct iovec[]) { + { .iov_base = &uid, .iov_len = sizeof(uid) }, + { .iov_base = &gid, .iov_len = sizeof(gid) }, + { .iov_base = unit->id, .iov_len = strlen(unit->id) }}, 3) < 0) + return -errno; + + return 0; +} + static int exec_child( Unit *unit, ExecCommand *command, @@ -1769,6 +1801,7 @@ static int exec_child( int socket_fd, int *fds, unsigned n_fds, char **files_env, + int user_lookup_fd, int *exit_status) { _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **final_argv = NULL; @@ -1815,7 +1848,7 @@ static int exec_child( log_forget_fds(); - r = close_remaining_fds(params, runtime, dcreds, socket_fd, fds, n_fds); + r = close_remaining_fds(params, runtime, dcreds, user_lookup_fd, socket_fd, fds, n_fds); if (r < 0) { *exit_status = EXIT_FDS; return r; @@ -1902,6 +1935,14 @@ static int exec_child( } } + r = send_user_lookup(unit, user_lookup_fd, uid, gid); + if (r < 0) { + *exit_status = EXIT_USER; + return r; + } + + user_lookup_fd = safe_close(user_lookup_fd); + /* If a socket is connected to STDIN/STDOUT/STDERR, we * must sure to drop O_NONBLOCK */ if (socket_fd >= 0) @@ -2501,6 +2542,7 @@ int exec_spawn(Unit *unit, socket_fd, fds, n_fds, files_env, + unit->manager->user_lookup_fds[1], &exit_status); if (r < 0) { log_open(); diff --git a/src/core/execute.h b/src/core/execute.h index 106154f81a..6082c42aba 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -178,6 +178,7 @@ struct ExecContext { bool no_new_privileges; bool dynamic_user; + bool remove_ipc; /* This is not exposed to the user but available * internally. We need it to make sure that whenever we spawn diff --git a/src/core/manager.c b/src/core/manager.c index c20e185d78..6f2477eef4 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -45,6 +45,7 @@ #include "bus-error.h" #include "bus-kernel.h" #include "bus-util.h" +#include "clean-ipc.h" #include "dbus-job.h" #include "dbus-manager.h" #include "dbus-unit.h" @@ -81,6 +82,7 @@ #include "transaction.h" #include "umask-util.h" #include "unit-name.h" +#include "user-util.h" #include "util.h" #include "virt.h" #include "watchdog.h" @@ -98,6 +100,7 @@ static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, ui static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); +static int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata); static int manager_dispatch_run_queue(sd_event_source *source, void *userdata); static int manager_run_generators(Manager *m); @@ -590,6 +593,8 @@ int manager_new(UnitFileScope scope, bool test_run, Manager **_m) { m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->cgroup_inotify_fd = m->ask_password_inotify_fd = -1; + m->user_lookup_fds[0] = m->user_lookup_fds[1] = -1; + m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */ m->have_ask_password = -EINVAL; /* we don't know */ @@ -812,6 +817,59 @@ static int manager_setup_cgroups_agent(Manager *m) { return 0; } +static int manager_setup_user_lookup_fd(Manager *m) { + int r; + + assert(m); + + /* Set up the socket pair used for passing UID/GID resolution results from forked off processes to PID + * 1. Background: we can't do name lookups (NSS) from PID 1, since it might involve IPC and thus activation, + * and we might hence deadlock on ourselves. Hence we do all user/group lookups asynchronously from the forked + * off processes right before executing the binaries to start. In order to be able to clean up any IPC objects + * created by a unit (see RemoveIPC=) we need to know in PID 1 the used UID/GID of the executed processes, + * hence we establish this communication channel so that forked off processes can pass their UID/GID + * information back to PID 1. The forked off processes send their resolved UID/GID to PID 1 in a simple + * datagram, along with their unit name, so that we can share one communication socket pair among all units for + * this purpose. + * + * You might wonder why we need a communication channel for this that is independent of the usual notification + * socket scheme (i.e. $NOTIFY_SOCKET). The primary difference is about trust: data sent via the $NOTIFY_SOCKET + * channel is only accepted if it originates from the right unit and if reception was enabled for it. The user + * lookup socket OTOH is only accessible by PID 1 and its children until they exec(), and always available. + * + * Note that this function is called under two circumstances: when we first initialize (in which case we + * allocate both the socket pair and the event source to listen on it), and when we deserialize after a reload + * (in which case the socket pair already exists but we still need to allocate the event source for it). */ + + if (m->user_lookup_fds[0] < 0) { + + /* Free all secondary fields */ + safe_close_pair(m->user_lookup_fds); + m->user_lookup_event_source = sd_event_source_unref(m->user_lookup_event_source); + + if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, m->user_lookup_fds) < 0) + return log_error_errno(errno, "Failed to allocate user lookup socket: %m"); + + (void) fd_inc_rcvbuf(m->user_lookup_fds[0], NOTIFY_RCVBUF_SIZE); + } + + if (!m->user_lookup_event_source) { + r = sd_event_add_io(m->event, &m->user_lookup_event_source, m->user_lookup_fds[0], EPOLLIN, manager_dispatch_user_lookup_fd, m); + if (r < 0) + return log_error_errno(errno, "Failed to allocate user lookup event source: %m"); + + /* Process even earlier than the notify event source, so that we always know first about valid UID/GID + * resolutions */ + r = sd_event_source_set_priority(m->user_lookup_event_source, SD_EVENT_PRIORITY_NORMAL-8); + if (r < 0) + return log_error_errno(errno, "Failed to set priority ot user lookup event source: %m"); + + (void) sd_event_source_set_description(m->user_lookup_event_source, "user-lookup"); + } + + return 0; +} + static int manager_connect_bus(Manager *m, bool reexecuting) { bool try_bus_connect; @@ -853,8 +911,7 @@ enum { _GC_OFFSET_MAX }; -static void unit_gc_mark_good(Unit *u, unsigned gc_marker) -{ +static void unit_gc_mark_good(Unit *u, unsigned gc_marker) { Iterator i; Unit *other; @@ -1021,12 +1078,14 @@ Manager* manager_free(Manager *m) { sd_event_source_unref(m->time_change_event_source); sd_event_source_unref(m->jobs_in_progress_event_source); sd_event_source_unref(m->run_queue_event_source); + sd_event_source_unref(m->user_lookup_event_source); safe_close(m->signal_fd); safe_close(m->notify_fd); safe_close(m->cgroups_agent_fd); safe_close(m->time_change_fd); safe_close(m->kdbus_fd); + safe_close_pair(m->user_lookup_fds); manager_close_ask_password(m); @@ -1052,6 +1111,9 @@ Manager* manager_free(Manager *m) { assert(hashmap_isempty(m->units_requiring_mounts_for)); hashmap_free(m->units_requiring_mounts_for); + hashmap_free(m->uid_refs); + hashmap_free(m->gid_refs); + free(m); return NULL; } @@ -1221,6 +1283,10 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { if (q < 0 && r == 0) r = q; + q = manager_setup_user_lookup_fd(m); + if (q < 0 && r == 0) + r = q; + /* We might have deserialized the kdbus control fd, but if we * didn't, then let's create the bus now. */ manager_connect_bus(m, !!serialization); @@ -1232,6 +1298,10 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { /* Release any dynamic users no longer referenced */ dynamic_user_vacuum(m, true); + /* Release any references to UIDs/GIDs no longer referenced, and destroy any IPC owned by them */ + manager_vacuum_uid_refs(m); + manager_vacuum_gid_refs(m); + if (serialization) { assert(m->n_reloading > 0); m->n_reloading--; @@ -2396,6 +2466,20 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { fprintf(f, "cgroups-agent-fd=%i\n", copy); } + if (m->user_lookup_fds[0] >= 0) { + int copy0, copy1; + + copy0 = fdset_put_dup(fds, m->user_lookup_fds[0]); + if (copy0 < 0) + return copy0; + + copy1 = fdset_put_dup(fds, m->user_lookup_fds[1]); + if (copy1 < 0) + return copy1; + + fprintf(f, "user-lookup=%i %i\n", copy0, copy1); + } + if (m->kdbus_fd >= 0) { int copy; @@ -2412,6 +2496,9 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { if (r < 0) return r; + manager_serialize_uid_refs(m, f); + manager_serialize_gid_refs(m, f); + fputc('\n', f); HASHMAP_FOREACH_KEY(u, t, m->units, i) { @@ -2578,6 +2665,18 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { m->cgroups_agent_fd = fdset_remove(fds, fd); } + } else if (startswith(l, "user-lookup=")) { + int fd0, fd1; + + if (sscanf(l + 12, "%i %i", &fd0, &fd1) != 2 || fd0 < 0 || fd1 < 0 || fd0 == fd1 || !fdset_contains(fds, fd0) || !fdset_contains(fds, fd1)) + log_debug("Failed to parse user lookup fd: %s", l + 12); + else { + m->user_lookup_event_source = sd_event_source_unref(m->user_lookup_event_source); + safe_close_pair(m->user_lookup_fds); + m->user_lookup_fds[0] = fdset_remove(fds, fd0); + m->user_lookup_fds[1] = fdset_remove(fds, fd1); + } + } else if (startswith(l, "kdbus-fd=")) { int fd; @@ -2590,6 +2689,10 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { } else if (startswith(l, "dynamic-user=")) dynamic_user_deserialize_one(m, l + 13, fds); + else if (startswith(l, "destroy-ipc-uid=")) + manager_deserialize_uid_refs_one(m, l + 16); + else if (startswith(l, "destroy-ipc-gid=")) + manager_deserialize_gid_refs_one(m, l + 16); else { int k; @@ -2672,6 +2775,8 @@ int manager_reload(Manager *m) { lookup_paths_flush_generator(&m->lookup_paths); lookup_paths_free(&m->lookup_paths); dynamic_user_vacuum(m, false); + m->uid_refs = hashmap_free(m->uid_refs); + m->gid_refs = hashmap_free(m->gid_refs); q = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, 0, NULL); if (q < 0 && r >= 0) @@ -2705,12 +2810,20 @@ int manager_reload(Manager *m) { if (q < 0 && r >= 0) r = q; + q = manager_setup_user_lookup_fd(m); + if (q < 0 && r >= 0) + r = q; + /* Third, fire things up! */ manager_coldplug(m); /* Release any dynamic users no longer referenced */ dynamic_user_vacuum(m, true); + /* Release any references to UIDs/GIDs no longer referenced, and destroy any IPC owned by them */ + manager_vacuum_uid_refs(m); + manager_vacuum_gid_refs(m); + /* Sync current state of bus names with our set of listening units */ if (m->api_bus) manager_sync_bus_names(m, m->api_bus); @@ -3144,6 +3257,300 @@ ManagerState manager_state(Manager *m) { return MANAGER_RUNNING; } +#define DESTROY_IPC_FLAG (UINT32_C(1) << 31) + +static void manager_unref_uid_internal( + Manager *m, + Hashmap **uid_refs, + uid_t uid, + bool destroy_now, + int (*_clean_ipc)(uid_t uid)) { + + uint32_t c, n; + + assert(m); + assert(uid_refs); + assert(uid_is_valid(uid)); + assert(_clean_ipc); + + /* A generic implementation, covering both manager_unref_uid() and manager_unref_gid(), under the assumption + * that uid_t and gid_t are actually defined the same way, with the same validity rules. + * + * We store a hashmap where the UID/GID is they key and the value is a 32bit reference counter, whose highest + * bit is used as flag for marking UIDs/GIDs whose IPC objects to remove when the last reference to the UID/GID + * is dropped. The flag is set to on, once at least one reference from a unit where RemoveIPC= is set is added + * on a UID/GID. It is reset when the UID's/GID's reference counter drops to 0 again. */ + + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + assert_cc(UID_INVALID == (uid_t) GID_INVALID); + + if (uid == 0) /* We don't keep track of root, and will never destroy it */ + return; + + c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid))); + + n = c & ~DESTROY_IPC_FLAG; + assert(n > 0); + n--; + + if (destroy_now && n == 0) { + hashmap_remove(*uid_refs, UID_TO_PTR(uid)); + + if (c & DESTROY_IPC_FLAG) { + log_debug("%s " UID_FMT " is no longer referenced, cleaning up its IPC.", + _clean_ipc == clean_ipc_by_uid ? "UID" : "GID", + uid); + (void) _clean_ipc(uid); + } + } else { + c = n | (c & DESTROY_IPC_FLAG); + assert_se(hashmap_update(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c)) >= 0); + } +} + +void manager_unref_uid(Manager *m, uid_t uid, bool destroy_now) { + manager_unref_uid_internal(m, &m->uid_refs, uid, destroy_now, clean_ipc_by_uid); +} + +void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now) { + manager_unref_uid_internal(m, &m->gid_refs, (uid_t) gid, destroy_now, clean_ipc_by_gid); +} + +static int manager_ref_uid_internal( + Manager *m, + Hashmap **uid_refs, + uid_t uid, + bool clean_ipc) { + + uint32_t c, n; + int r; + + assert(m); + assert(uid_refs); + assert(uid_is_valid(uid)); + + /* A generic implementation, covering both manager_ref_uid() and manager_ref_gid(), under the assumption + * that uid_t and gid_t are actually defined the same way, with the same validity rules. */ + + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + assert_cc(UID_INVALID == (uid_t) GID_INVALID); + + if (uid == 0) /* We don't keep track of root, and will never destroy it */ + return 0; + + r = hashmap_ensure_allocated(uid_refs, &trivial_hash_ops); + if (r < 0) + return r; + + c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid))); + + n = c & ~DESTROY_IPC_FLAG; + n++; + + if (n & DESTROY_IPC_FLAG) /* check for overflow */ + return -EOVERFLOW; + + c = n | (c & DESTROY_IPC_FLAG) | (clean_ipc ? DESTROY_IPC_FLAG : 0); + + return hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c)); +} + +int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc) { + return manager_ref_uid_internal(m, &m->uid_refs, uid, clean_ipc); +} + +int manager_ref_gid(Manager *m, gid_t gid, bool clean_ipc) { + return manager_ref_uid_internal(m, &m->gid_refs, (uid_t) gid, clean_ipc); +} + +static void manager_vacuum_uid_refs_internal( + Manager *m, + Hashmap **uid_refs, + int (*_clean_ipc)(uid_t uid)) { + + Iterator i; + void *p, *k; + + assert(m); + assert(uid_refs); + assert(_clean_ipc); + + HASHMAP_FOREACH_KEY(p, k, *uid_refs, i) { + uint32_t c, n; + uid_t uid; + + uid = PTR_TO_UID(k); + c = PTR_TO_UINT32(p); + + n = c & ~DESTROY_IPC_FLAG; + if (n > 0) + continue; + + if (c & DESTROY_IPC_FLAG) { + log_debug("Found unreferenced %s " UID_FMT " after reload/reexec. Cleaning up.", + _clean_ipc == clean_ipc_by_uid ? "UID" : "GID", + uid); + (void) _clean_ipc(uid); + } + + assert_se(hashmap_remove(*uid_refs, k) == p); + } +} + +void manager_vacuum_uid_refs(Manager *m) { + manager_vacuum_uid_refs_internal(m, &m->uid_refs, clean_ipc_by_uid); +} + +void manager_vacuum_gid_refs(Manager *m) { + manager_vacuum_uid_refs_internal(m, &m->gid_refs, clean_ipc_by_gid); +} + +static void manager_serialize_uid_refs_internal( + Manager *m, + FILE *f, + Hashmap **uid_refs, + const char *field_name) { + + Iterator i; + void *p, *k; + + assert(m); + assert(f); + assert(uid_refs); + assert(field_name); + + /* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as the actual counter + * of it is better rebuild after a reload/reexec. */ + + HASHMAP_FOREACH_KEY(p, k, *uid_refs, i) { + uint32_t c; + uid_t uid; + + uid = PTR_TO_UID(k); + c = PTR_TO_UINT32(p); + + if (!(c & DESTROY_IPC_FLAG)) + continue; + + fprintf(f, "%s=" UID_FMT "\n", field_name, uid); + } +} + +void manager_serialize_uid_refs(Manager *m, FILE *f) { + manager_serialize_uid_refs_internal(m, f, &m->uid_refs, "destroy-ipc-uid"); +} + +void manager_serialize_gid_refs(Manager *m, FILE *f) { + manager_serialize_uid_refs_internal(m, f, &m->gid_refs, "destroy-ipc-gid"); +} + +static void manager_deserialize_uid_refs_one_internal( + Manager *m, + Hashmap** uid_refs, + const char *value) { + + uid_t uid; + uint32_t c; + int r; + + assert(m); + assert(uid_refs); + assert(value); + + r = parse_uid(value, &uid); + if (r < 0 || uid == 0) { + log_debug("Unable to parse UID reference serialization"); + return; + } + + r = hashmap_ensure_allocated(uid_refs, &trivial_hash_ops); + if (r < 0) { + log_oom(); + return; + } + + c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid))); + if (c & DESTROY_IPC_FLAG) + return; + + c |= DESTROY_IPC_FLAG; + + r = hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c)); + if (r < 0) { + log_debug("Failed to add UID reference entry"); + return; + } +} + +void manager_deserialize_uid_refs_one(Manager *m, const char *value) { + manager_deserialize_uid_refs_one_internal(m, &m->uid_refs, value); +} + +void manager_deserialize_gid_refs_one(Manager *m, const char *value) { + manager_deserialize_uid_refs_one_internal(m, &m->gid_refs, value); +} + +int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + struct buffer { + uid_t uid; + gid_t gid; + char unit_name[UNIT_NAME_MAX+1]; + } _packed_ buffer; + + Manager *m = userdata; + ssize_t l; + size_t n; + Unit *u; + + assert_se(source); + assert_se(m); + + /* Invoked whenever a child process succeeded resolving its user/group to use and sent us the resulting UID/GID + * in a datagram. We parse the datagram here and pass it off to the unit, so that it can add a reference to the + * UID/GID so that it can destroy the UID/GID's IPC objects when the reference counter drops to 0. */ + + l = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT); + if (l < 0) { + if (errno == EINTR || errno == EAGAIN) + return 0; + + return log_error_errno(errno, "Failed to read from user lookup fd: %m"); + } + + if ((size_t) l <= offsetof(struct buffer, unit_name)) { + log_warning("Received too short user lookup message, ignoring."); + return 0; + } + + if ((size_t) l > offsetof(struct buffer, unit_name) + UNIT_NAME_MAX) { + log_warning("Received too long user lookup message, ignoring."); + return 0; + } + + if (!uid_is_valid(buffer.uid) && !gid_is_valid(buffer.gid)) { + log_warning("Got user lookup message with invalid UID/GID pair, ignoring."); + return 0; + } + + n = (size_t) l - offsetof(struct buffer, unit_name); + if (memchr(buffer.unit_name, 0, n)) { + log_warning("Received lookup message with embedded NUL character, ignoring."); + return 0; + } + + buffer.unit_name[n] = 0; + u = manager_get_unit(m, buffer.unit_name); + if (!u) { + log_debug("Got user lookup message but unit doesn't exist, ignoring."); + return 0; + } + + log_unit_debug(u, "User lookup succeeded: uid=" UID_FMT " gid=" GID_FMT, buffer.uid, buffer.gid); + + unit_notify_user_lookup(u, buffer.uid, buffer.gid); + return 0; +} + static const char *const manager_state_table[_MANAGER_STATE_MAX] = { [MANAGER_INITIALIZING] = "initializing", [MANAGER_STARTING] = "starting", diff --git a/src/core/manager.h b/src/core/manager.h index c681d5dc46..b9f2e4b5a1 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -143,6 +143,9 @@ struct Manager { sd_event_source *jobs_in_progress_event_source; + int user_lookup_fds[2]; + sd_event_source *user_lookup_event_source; + UnitFileScope unit_file_scope; LookupPaths lookup_paths; Set *unit_path_cache; @@ -234,7 +237,6 @@ struct Manager { bool dispatching_dbus_queue:1; bool taint_usr:1; - bool test_run:1; /* If non-zero, exit with the following value when the systemd @@ -301,6 +303,10 @@ struct Manager { /* Dynamic users/groups, indexed by their name */ Hashmap *dynamic_users; + /* Keep track of all UIDs and GIDs any of our services currently use. This is useful for the RemoveIPC= logic. */ + Hashmap *uid_refs; + Hashmap *gid_refs; + /* When the user hits C-A-D more than 7 times per 2s, reboot immediately... */ RateLimit ctrl_alt_del_ratelimit; @@ -378,5 +384,20 @@ ManagerState manager_state(Manager *m); int manager_update_failed_units(Manager *m, Unit *u, bool failed); +void manager_unref_uid(Manager *m, uid_t uid, bool destroy_now); +int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc); + +void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now); +int manager_ref_gid(Manager *m, gid_t gid, bool destroy_now); + +void manager_vacuum_uid_refs(Manager *m); +void manager_vacuum_gid_refs(Manager *m); + +void manager_serialize_uid_refs(Manager *m, FILE *f); +void manager_deserialize_uid_refs_one(Manager *m, const char *value); + +void manager_serialize_gid_refs(Manager *m, FILE *f); +void manager_deserialize_gid_refs_one(Manager *m, const char *value); + const char *manager_state_to_string(ManagerState m) _const_; ManagerState manager_state_from_string(const char *s) _pure_; diff --git a/src/core/mount.c b/src/core/mount.c index f3ccf6d48a..f2ac8d171f 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -769,6 +769,8 @@ static void mount_enter_dead(Mount *m, MountResult f) { exec_context_destroy_runtime_directory(&m->exec_context, manager_get_runtime_prefix(UNIT(m)->manager)); + unit_unref_uid_gid(UNIT(m), true); + dynamic_creds_destroy(&m->dynamic_creds); } diff --git a/src/core/service.c b/src/core/service.c index 4a37702f52..1951ba9222 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1471,6 +1471,9 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) /* Also, remove the runtime directory */ exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager)); + /* Get rid of the IPC bits of the user */ + unit_unref_uid_gid(UNIT(s), true); + /* Release the user, and destroy it if we are the only remaining owner */ dynamic_creds_destroy(&s->dynamic_creds); diff --git a/src/core/socket.c b/src/core/socket.c index 50872e8366..70d55dd9ed 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1905,6 +1905,8 @@ static void socket_enter_dead(Socket *s, SocketResult f) { exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager)); + unit_unref_uid_gid(UNIT(s), true); + dynamic_creds_destroy(&s->dynamic_creds); } diff --git a/src/core/swap.c b/src/core/swap.c index 2c802da3b5..fb222b6858 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -683,6 +683,8 @@ static void swap_enter_dead(Swap *s, SwapResult f) { exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager)); + unit_unref_uid_gid(UNIT(s), true); + dynamic_creds_destroy(&s->dynamic_creds); } diff --git a/src/core/unit.c b/src/core/unit.c index 952604e0db..4b8d81c3f1 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -100,7 +100,8 @@ Unit *unit_new(Manager *m, size_t size) { u->on_failure_job_mode = JOB_REPLACE; u->cgroup_inotify_wd = -1; u->job_timeout = USEC_INFINITY; - u->sigchldgen = 0; + u->ref_uid = UID_INVALID; + u->ref_gid = GID_INVALID; RATELIMIT_INIT(u->start_limit, m->default_start_limit_interval, m->default_start_limit_burst); RATELIMIT_INIT(u->auto_stop_ratelimit, 10 * USEC_PER_SEC, 16); @@ -550,6 +551,8 @@ void unit_free(Unit *u) { unit_release_cgroup(u); + unit_unref_uid_gid(u, false); + (void) manager_update_failed_units(u->manager, u, false); set_remove(u->manager->startup_units, u); @@ -2614,6 +2617,11 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { unit_serialize_item(u, f, "cgroup", u->cgroup_path); unit_serialize_item(u, f, "cgroup-realized", yes_no(u->cgroup_realized)); + if (uid_is_valid(u->ref_uid)) + unit_serialize_item_format(u, f, "ref-uid", UID_FMT, u->ref_uid); + if (gid_is_valid(u->ref_gid)) + unit_serialize_item_format(u, f, "ref-gid", GID_FMT, u->ref_gid); + if (serialize_jobs) { if (u->job) { fprintf(f, "job\n"); @@ -2851,6 +2859,28 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { u->cgroup_realized = b; continue; + + } else if (streq(l, "ref-uid")) { + uid_t uid; + + r = parse_uid(v, &uid); + if (r < 0) + log_unit_debug(u, "Failed to parse referenced UID %s, ignoring.", v); + else + unit_ref_uid_gid(u, uid, GID_INVALID); + + continue; + + } else if (streq(l, "ref-gid")) { + gid_t gid; + + r = parse_gid(v, &gid); + if (r < 0) + log_unit_debug(u, "Failed to parse referenced GID %s, ignoring.", v); + else + unit_ref_uid_gid(u, UID_INVALID, gid); + + continue; } if (unit_can_serialize(u)) { @@ -3310,6 +3340,7 @@ int unit_patch_contexts(Unit *u) { } ec->private_tmp = true; + ec->remove_ipc = true; } } @@ -3932,3 +3963,144 @@ pid_t unit_main_pid(Unit *u) { return 0; } + +static void unit_unref_uid_internal( + Unit *u, + uid_t *ref_uid, + bool destroy_now, + void (*_manager_unref_uid)(Manager *m, uid_t uid, bool destroy_now)) { + + assert(u); + assert(ref_uid); + assert(_manager_unref_uid); + + /* Generic implementation of both unit_unref_uid() and unit_unref_gid(), under the assumption that uid_t and + * gid_t are actually the same time, with the same validity rules. + * + * Drops a reference to UID/GID from a unit. */ + + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + assert_cc(UID_INVALID == (uid_t) GID_INVALID); + + if (!uid_is_valid(*ref_uid)) + return; + + _manager_unref_uid(u->manager, *ref_uid, destroy_now); + *ref_uid = UID_INVALID; +} + +void unit_unref_uid(Unit *u, bool destroy_now) { + unit_unref_uid_internal(u, &u->ref_uid, destroy_now, manager_unref_uid); +} + +void unit_unref_gid(Unit *u, bool destroy_now) { + unit_unref_uid_internal(u, (uid_t*) &u->ref_gid, destroy_now, manager_unref_gid); +} + +static int unit_ref_uid_internal( + Unit *u, + uid_t *ref_uid, + uid_t uid, + bool clean_ipc, + int (*_manager_ref_uid)(Manager *m, uid_t uid, bool clean_ipc)) { + + int r; + + assert(u); + assert(ref_uid); + assert(uid_is_valid(uid)); + assert(_manager_ref_uid); + + /* Generic implementation of both unit_ref_uid() and unit_ref_guid(), under the assumption that uid_t and gid_t + * are actually the same type, and have the same validity rules. + * + * Adds a reference on a specific UID/GID to this unit. Each unit referencing the same UID/GID maintains a + * reference so that we can destroy the UID/GID's IPC resources as soon as this is requested and the counter + * drops to zero. */ + + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + assert_cc(UID_INVALID == (uid_t) GID_INVALID); + + if (*ref_uid == uid) + return 0; + + if (uid_is_valid(*ref_uid)) /* Already set? */ + return -EBUSY; + + r = _manager_ref_uid(u->manager, uid, clean_ipc); + if (r < 0) + return r; + + *ref_uid = uid; + return 1; +} + +int unit_ref_uid(Unit *u, uid_t uid, bool clean_ipc) { + return unit_ref_uid_internal(u, &u->ref_uid, uid, clean_ipc, manager_ref_uid); +} + +int unit_ref_gid(Unit *u, gid_t gid, bool clean_ipc) { + return unit_ref_uid_internal(u, (uid_t*) &u->ref_gid, (uid_t) gid, clean_ipc, manager_ref_gid); +} + +static int unit_ref_uid_gid_internal(Unit *u, uid_t uid, gid_t gid, bool clean_ipc) { + int r = 0, q = 0; + + assert(u); + + /* Reference both a UID and a GID in one go. Either references both, or neither. */ + + if (uid_is_valid(uid)) { + r = unit_ref_uid(u, uid, clean_ipc); + if (r < 0) + return r; + } + + if (gid_is_valid(gid)) { + q = unit_ref_gid(u, gid, clean_ipc); + if (q < 0) { + if (r > 0) + unit_unref_uid(u, false); + + return q; + } + } + + return r > 0 || q > 0; +} + +int unit_ref_uid_gid(Unit *u, uid_t uid, gid_t gid) { + ExecContext *c; + int r; + + assert(u); + + c = unit_get_exec_context(u); + + r = unit_ref_uid_gid_internal(u, uid, gid, c ? c->remove_ipc : false); + if (r < 0) + return log_unit_warning_errno(u, r, "Couldn't add UID/GID reference to unit, proceeding without: %m"); + + return r; +} + +void unit_unref_uid_gid(Unit *u, bool destroy_now) { + assert(u); + + unit_unref_uid(u, destroy_now); + unit_unref_gid(u, destroy_now); +} + +void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid) { + int r; + + assert(u); + + /* This is invoked whenever one of the forked off processes let's us know the UID/GID its user name/group names + * resolved to. We keep track of which UID/GID is currently assigned in order to be able to destroy its IPC + * objects when no service references the UID/GID anymore. */ + + r = unit_ref_uid_gid(u, uid, gid); + if (r > 0) + bus_unit_send_change_signal(u); +} diff --git a/src/core/unit.h b/src/core/unit.h index 513ea1614c..53875653d7 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -180,6 +180,10 @@ struct Unit { /* Make sure we never enter endless loops with the check unneeded logic, or the BindsTo= logic */ RateLimit auto_stop_ratelimit; + /* Reference to a specific UID/GID */ + uid_t ref_uid; + gid_t ref_gid; + /* Cached unit file state and preset */ UnitFileState unit_file_state; int unit_file_preset; @@ -371,8 +375,7 @@ struct UnitVTable { /* Called whenever a process of this unit sends us a message */ void (*notify_message)(Unit *u, pid_t pid, char **tags, FDSet *fds); - /* Called whenever a name this Unit registered for comes or - * goes away. */ + /* Called whenever a name this Unit registered for comes or goes away. */ void (*bus_name_owner_change)(Unit *u, const char *name, const char *old_owner, const char *new_owner); /* Called for each property that is being set */ @@ -621,6 +624,17 @@ int unit_fail_if_symlink(Unit *u, const char* where); int unit_start_limit_test(Unit *u); +void unit_unref_uid(Unit *u, bool destroy_now); +int unit_ref_uid(Unit *u, uid_t uid, bool clean_ipc); + +void unit_unref_gid(Unit *u, bool destroy_now); +int unit_ref_gid(Unit *u, gid_t gid, bool clean_ipc); + +int unit_ref_uid_gid(Unit *u, uid_t uid, gid_t gid); +void unit_unref_uid_gid(Unit *u, bool destroy_now); + +void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid); + /* Macros which append UNIT= or USER_UNIT= to the message */ #define log_unit_full(unit, level, error, ...) \ diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 63363035e7..11951aca5b 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -612,9 +612,14 @@ int user_finalize(User *u) { if (k < 0) r = k; - /* Clean SysV + POSIX IPC objects */ - if (u->manager->remove_ipc) { - k = clean_ipc(u->uid); + /* Clean SysV + POSIX IPC objects, but only if this is not a system user. Background: in many setups cronjobs + * are run in full PAM and thus logind sessions, even if the code run doesn't belong to actual users but to + * system components. Since enable RemoveIPC= globally for all users, we need to be a bit careful with such + * cases, as we shouldn't accidentally remove a system service's IPC objects while it is running, just because + * a cronjob running as the same user just finished. Hence: exclude system users generally from IPC clean-up, + * and do it only for normal users. */ + if (u->manager->remove_ipc && u->uid > SYSTEM_UID_MAX) { + k = clean_ipc_by_uid(u->uid); if (k < 0) r = k; } diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index f9e12e0578..ab30afb527 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -204,7 +204,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges", "SyslogLevelPrefix", "Delegate", "RemainAfterElapse", "MemoryDenyWriteExecute", - "RestrictRealtime", "DynamicUser")) { + "RestrictRealtime", "DynamicUser", "RemoveIPC")) { r = parse_boolean(eq); if (r < 0) diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c index 95686348c1..64f9b94641 100644 --- a/src/shared/clean-ipc.c +++ b/src/shared/clean-ipc.c @@ -41,8 +41,20 @@ #include "macro.h" #include "string-util.h" #include "strv.h" +#include "user-util.h" -static int clean_sysvipc_shm(uid_t delete_uid) { +static bool match_uid_gid(uid_t subject_uid, gid_t subject_gid, uid_t delete_uid, gid_t delete_gid) { + + if (uid_is_valid(delete_uid) && subject_uid == delete_uid) + return true; + + if (gid_is_valid(delete_gid) && subject_gid == delete_gid) + return true; + + return false; +} + +static int clean_sysvipc_shm(uid_t delete_uid, gid_t delete_gid) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; bool first = true; @@ -77,7 +89,7 @@ static int clean_sysvipc_shm(uid_t delete_uid) { if (n_attached > 0) continue; - if (uid != delete_uid) + if (!match_uid_gid(uid, gid, delete_uid, delete_gid)) continue; if (shmctl(shmid, IPC_RMID, NULL) < 0) { @@ -98,7 +110,7 @@ fail: return log_warning_errno(errno, "Failed to read /proc/sysvipc/shm: %m"); } -static int clean_sysvipc_sem(uid_t delete_uid) { +static int clean_sysvipc_sem(uid_t delete_uid, gid_t delete_gid) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; bool first = true; @@ -128,7 +140,7 @@ static int clean_sysvipc_sem(uid_t delete_uid) { &semid, &uid, &gid, &cuid, &cgid) != 5) continue; - if (uid != delete_uid) + if (!match_uid_gid(uid, gid, delete_uid, delete_gid)) continue; if (semctl(semid, 0, IPC_RMID) < 0) { @@ -149,7 +161,7 @@ fail: return log_warning_errno(errno, "Failed to read /proc/sysvipc/sem: %m"); } -static int clean_sysvipc_msg(uid_t delete_uid) { +static int clean_sysvipc_msg(uid_t delete_uid, gid_t delete_gid) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; bool first = true; @@ -180,7 +192,7 @@ static int clean_sysvipc_msg(uid_t delete_uid) { &msgid, &cpid, &lpid, &uid, &gid, &cuid, &cgid) != 7) continue; - if (uid != delete_uid) + if (!match_uid_gid(uid, gid, delete_uid, delete_gid)) continue; if (msgctl(msgid, IPC_RMID, NULL) < 0) { @@ -201,7 +213,7 @@ fail: return log_warning_errno(errno, "Failed to read /proc/sysvipc/msg: %m"); } -static int clean_posix_shm_internal(DIR *dir, uid_t uid) { +static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid) { struct dirent *de; int ret = 0, r; @@ -221,7 +233,7 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid) { continue; } - if (st.st_uid != uid) + if (!match_uid_gid(st.st_uid, st.st_gid, uid, gid)) continue; if (S_ISDIR(st.st_mode)) { @@ -232,7 +244,7 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid) { if (errno != ENOENT) ret = log_warning_errno(errno, "Failed to enter shared memory directory %s: %m", de->d_name); } else { - r = clean_posix_shm_internal(kid, uid); + r = clean_posix_shm_internal(kid, uid, gid); if (r < 0) ret = r; } @@ -262,7 +274,7 @@ fail: return log_warning_errno(errno, "Failed to read /dev/shm: %m"); } -static int clean_posix_shm(uid_t uid) { +static int clean_posix_shm(uid_t uid, gid_t gid) { _cleanup_closedir_ DIR *dir = NULL; dir = opendir("/dev/shm"); @@ -273,10 +285,10 @@ static int clean_posix_shm(uid_t uid) { return log_warning_errno(errno, "Failed to open /dev/shm: %m"); } - return clean_posix_shm_internal(dir, uid); + return clean_posix_shm_internal(dir, uid, gid); } -static int clean_posix_mq(uid_t uid) { +static int clean_posix_mq(uid_t uid, gid_t gid) { _cleanup_closedir_ DIR *dir = NULL; struct dirent *de; int ret = 0; @@ -306,7 +318,7 @@ static int clean_posix_mq(uid_t uid) { continue; } - if (st.st_uid != uid) + if (!match_uid_gid(st.st_uid, st.st_gid, uid, gid)) continue; fn[0] = '/'; @@ -328,32 +340,44 @@ fail: return log_warning_errno(errno, "Failed to read /dev/mqueue: %m"); } -int clean_ipc(uid_t uid) { +int clean_ipc(uid_t uid, gid_t gid) { int ret = 0, r; - /* Refuse to clean IPC of the root and system users */ - if (uid <= SYSTEM_UID_MAX) + /* Anything to do? */ + if (!uid_is_valid(uid) && !gid_is_valid(gid)) return 0; - r = clean_sysvipc_shm(uid); + /* Refuse to clean IPC of the root user */ + if (uid == 0 && gid == 0) + return 0; + + r = clean_sysvipc_shm(uid, gid); if (r < 0) ret = r; - r = clean_sysvipc_sem(uid); + r = clean_sysvipc_sem(uid, gid); if (r < 0) ret = r; - r = clean_sysvipc_msg(uid); + r = clean_sysvipc_msg(uid, gid); if (r < 0) ret = r; - r = clean_posix_shm(uid); + r = clean_posix_shm(uid, gid); if (r < 0) ret = r; - r = clean_posix_mq(uid); + r = clean_posix_mq(uid, gid); if (r < 0) ret = r; return ret; } + +int clean_ipc_by_uid(uid_t uid) { + return clean_ipc(uid, GID_INVALID); +} + +int clean_ipc_by_gid(gid_t gid) { + return clean_ipc(UID_INVALID, gid); +} diff --git a/src/shared/clean-ipc.h b/src/shared/clean-ipc.h index 44a83afcf7..6ca57f44fd 100644 --- a/src/shared/clean-ipc.h +++ b/src/shared/clean-ipc.h @@ -21,4 +21,6 @@ #include -int clean_ipc(uid_t uid); +int clean_ipc(uid_t uid, gid_t gid); +int clean_ipc_by_uid(uid_t uid); +int clean_ipc_by_gid(gid_t gid); diff --git a/src/test/test-ipcrm.c b/src/test/test-ipcrm.c index c5bcaf47bb..551eba7215 100644 --- a/src/test/test-ipcrm.c +++ b/src/test/test-ipcrm.c @@ -32,5 +32,5 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } - return clean_ipc(uid) < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + return clean_ipc_by_uid(uid) < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } -- cgit v1.2.3-54-g00ecf From 8a384842b25fc910859f3aa7121aa61f7f4e3906 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 2 Aug 2016 11:14:56 +0200 Subject: clean-ipc: debug log about all remove IPC objects --- src/shared/clean-ipc.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c index 64f9b94641..d5db604f03 100644 --- a/src/shared/clean-ipc.c +++ b/src/shared/clean-ipc.c @@ -101,7 +101,8 @@ static int clean_sysvipc_shm(uid_t delete_uid, gid_t delete_gid) { ret = log_warning_errno(errno, "Failed to remove SysV shared memory segment %i: %m", shmid); - } + } else + log_debug("Removed SysV shared memory segment %i.", shmid); } return ret; @@ -152,7 +153,8 @@ static int clean_sysvipc_sem(uid_t delete_uid, gid_t delete_gid) { ret = log_warning_errno(errno, "Failed to remove SysV semaphores object %i: %m", semid); - } + } else + log_debug("Removed SysV semaphore %i.", semid); } return ret; @@ -204,7 +206,8 @@ static int clean_sysvipc_msg(uid_t delete_uid, gid_t delete_gid) { ret = log_warning_errno(errno, "Failed to remove SysV message queue %i: %m", msgid); - } + } else + log_debug("Removed SysV message queue %i.", msgid); } return ret; @@ -255,7 +258,8 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid) { continue; ret = log_warning_errno(errno, "Failed to remove POSIX shared memory directory %s: %m", de->d_name); - } + } else + log_debug("Removed POSIX shared memory directory %s", de->d_name); } else { if (unlinkat(dirfd(dir), de->d_name, 0) < 0) { @@ -264,7 +268,8 @@ static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid) { continue; ret = log_warning_errno(errno, "Failed to remove POSIX shared memory segment %s: %m", de->d_name); - } + } else + log_debug("Removed POSIX shared memory segment %s", de->d_name); } } @@ -331,7 +336,8 @@ static int clean_posix_mq(uid_t uid, gid_t gid) { ret = log_warning_errno(errno, "Failed to unlink POSIX message queue %s: %m", fn); - } + } else + log_debug("Removed POSIX message queue %s", fn); } return ret; -- cgit v1.2.3-54-g00ecf From fd63e712b2025d235ce4bfbb512fada10e2690b5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 2 Aug 2016 12:28:51 +0200 Subject: core: bypass dynamic user lookups from dbus-daemon dbus-daemon does NSS name look-ups in order to enforce its bus policy. This might dead-lock if an NSS module use wants to use D-Bus for the look-up itself, like our nss-systemd does. Let's work around this by bypassing bus communication in the NSS module if we run inside of dbus-daemon. To make this work we keep a bit of extra state in /run/systemd/dynamic-uid/ so that we don't have to consult the bus, but can still resolve the names. Note that the normal codepath continues to be via the bus, so that resolving works from all mount namespaces and is subject to authentication, as before. This is a bit dirty, but not too dirty, as dbus daemon is kinda special anyway for PID 1. --- src/core/dynamic-user.c | 51 +++++++- src/core/execute.c | 15 ++- src/nss-systemd/nss-systemd.c | 262 ++++++++++++++++++++++++++++-------------- 3 files changed, 235 insertions(+), 93 deletions(-) diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c index 8035bee231..185d0e5f00 100644 --- a/src/core/dynamic-user.c +++ b/src/core/dynamic-user.c @@ -150,6 +150,42 @@ int dynamic_user_acquire(Manager *m, const char *name, DynamicUser** ret) { return 1; } +static int make_uid_symlinks(uid_t uid, const char *name, bool b) { + + char path1[strlen("/run/systemd/dynamic-uid/direct:") + DECIMAL_STR_MAX(uid_t) + 1]; + const char *path2; + int r = 0; + + /* Add direct additional symlinks for direct lookups of dynamic UIDs and their names by userspace code. The + * only reason we have this is because dbus-daemon cannot use D-Bus for resolving users and groups (since it + * would be its own client then). We hence keep these world-readable symlinks in place, so that the + * unprivileged dbus user can read the mappings when it needs them via these symlinks instead of having to go + * via the bus. Ideally, we'd use the lock files we keep for this anyway, but we can't since we use BSD locks + * on them and as those may be taken by any user with read access we can't make them world-readable. */ + + xsprintf(path1, "/run/systemd/dynamic-uid/direct:" UID_FMT, uid); + if (unlink(path1) < 0) { + if (errno != ENOENT) + r = -errno; + } + if (b) { + if (symlink(name, path1) < 0) + r = -errno; + } + + path2 = strjoina("/run/systemd/dynamic-uid/direct:", name); + if (unlink(path2) < 0) { + if (errno != ENOENT) + r = -errno; + } + if (b) { + if (symlink(path1 + strlen("/run/systemd/dynamic-uid/direct:"), path2) < 0) + r = -errno; + } + + return r; +} + static int pick_uid(const char *name, uid_t *ret_uid) { static const uint8_t hash_key[] = { @@ -223,6 +259,7 @@ static int pick_uid(const char *name, uid_t *ret_uid) { } (void) ftruncate(lock_fd, l); + (void) make_uid_symlinks(candidate, name, true); /* also add direct lookup symlinks */ *ret_uid = candidate; r = lock_fd; @@ -324,14 +361,16 @@ static int dynamic_user_push(DynamicUser *d, uid_t uid, int lock_fd) { return 0; } -static void unlink_uid_lock(int lock_fd, uid_t uid) { +static void unlink_uid_lock(int lock_fd, uid_t uid, const char *name) { char lock_path[strlen("/run/systemd/dynamic-uid/") + DECIMAL_STR_MAX(uid_t) + 1]; if (lock_fd < 0) return; xsprintf(lock_path, "/run/systemd/dynamic-uid/" UID_FMT, uid); - (void) unlink_noerrno(lock_path); + (void) unlink(lock_path); + + (void) make_uid_symlinks(uid, name, false); /* remove direct lookup symlinks */ } int dynamic_user_realize(DynamicUser *d, uid_t *ret) { @@ -399,7 +438,7 @@ int dynamic_user_realize(DynamicUser *d, uid_t *ret) { /* So, we found a working UID/lock combination. Let's see if we actually still need it. */ if (lockf(d->storage_socket[0], F_LOCK, 0) < 0) { - unlink_uid_lock(uid_lock_fd, uid); + unlink_uid_lock(uid_lock_fd, uid, d->name); return -errno; } @@ -407,7 +446,7 @@ int dynamic_user_realize(DynamicUser *d, uid_t *ret) { if (r < 0) { if (r != -EAGAIN) { /* OK, something bad happened, let's get rid of the bits we acquired. */ - unlink_uid_lock(uid_lock_fd, uid); + unlink_uid_lock(uid_lock_fd, uid, d->name); goto finish; } @@ -416,7 +455,7 @@ int dynamic_user_realize(DynamicUser *d, uid_t *ret) { /* Hmm, so as it appears there's now something stored in the storage socket. Throw away what we * acquired, and use what's stored now. */ - unlink_uid_lock(uid_lock_fd, uid); + unlink_uid_lock(uid_lock_fd, uid, d->name); safe_close(uid_lock_fd); uid = new_uid; @@ -513,7 +552,7 @@ static int dynamic_user_close(DynamicUser *d) { goto finish; /* This dynamic user was realized and dynamically allocated. In this case, let's remove the lock file. */ - unlink_uid_lock(lock_fd, uid); + unlink_uid_lock(lock_fd, uid, d->name); r = 1; finish: diff --git a/src/core/execute.c b/src/core/execute.c index 4c786a2e33..0af8eb5a02 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -91,6 +91,7 @@ #include "selinux-util.h" #include "signal-util.h" #include "smack-util.h" +#include "special.h" #include "string-table.h" #include "string-util.h" #include "strv.h" @@ -1384,6 +1385,7 @@ static void do_idle_pipe_dance(int idle_pipe[4]) { } static int build_environment( + Unit *u, const ExecContext *c, const ExecParameters *p, unsigned n_fds, @@ -1401,7 +1403,7 @@ static int build_environment( assert(c); assert(ret); - our_env = new0(char*, 12); + our_env = new0(char*, 13); if (!our_env) return -ENOMEM; @@ -1436,6 +1438,16 @@ static int build_environment( our_env[n_env++] = x; } + /* If this is D-Bus, tell the nss-systemd module, since it relies on being able to use D-Bus look up dynamic + * users via PID 1, possibly dead-locking the dbus daemon. This way it will not use D-Bus to resolve names, but + * check the database directly. */ + if (unit_has_name(u, SPECIAL_DBUS_SERVICE)) { + x = strdup("SYSTEMD_NSS_BYPASS_BUS=1"); + if (!x) + return -ENOMEM; + our_env[n_env++] = x; + } + if (home) { x = strappend("HOME=", home); if (!x) @@ -2100,6 +2112,7 @@ static int exec_child( } r = build_environment( + unit, context, params, n_fds, diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index 7078c0c50c..17d04e958d 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -21,11 +21,14 @@ #include "sd-bus.h" +#include "alloc-util.h" #include "bus-common-errors.h" #include "env-util.h" +#include "fs-util.h" #include "macro.h" #include "nss-util.h" #include "signal-util.h" +#include "stdio-util.h" #include "string-util.h" #include "user-util.h" #include "util.h" @@ -75,15 +78,50 @@ static const struct group nobody_group = { NSS_GETPW_PROTOTYPES(systemd); NSS_GETGR_PROTOTYPES(systemd); +static int direct_lookup_name(const char *name, uid_t *ret) { + _cleanup_free_ char *s = NULL; + const char *path; + int r; + + assert(name); + + /* Normally, we go via the bus to resolve names. That has the benefit that it is available from any mount + * namespace and subject to proper authentication. However, there's one problem: if our module is called from + * dbus-daemon itself we really can't use D-Bus to communicate. In this case, resort to a client-side hack, + * and look for the dynamic names directly. This is pretty ugly, but breaks the cyclic dependency. */ + + path = strjoina("/run/systemd/dynamic-uid/direct:", name); + r = readlink_malloc(path, &s); + if (r < 0) + return r; + + return parse_uid(s, ret); +} + +static int direct_lookup_uid(uid_t uid, char **ret) { + char path[strlen("/run/systemd/dynamic-uid/direct:") + DECIMAL_STR_MAX(uid_t) + 1], *s; + int r; + + xsprintf(path, "/run/systemd/dynamic-uid/direct:" UID_FMT, uid); + + r = readlink_malloc(path, &s); + if (r < 0) + return r; + if (!valid_user_group_name(s)) { /* extra safety check */ + free(s); + return -EINVAL; + } + + *ret = s; + return 0; +} + enum nss_status _nss_systemd_getpwnam_r( const char *name, struct passwd *pwd, char *buffer, size_t buflen, int *errnop) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; uint32_t translated; size_t l; int r; @@ -114,30 +152,45 @@ enum nss_status _nss_systemd_getpwnam_r( if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) goto not_found; - r = sd_bus_open_system(&bus); - if (r < 0) - goto fail; + if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) { - r = sd_bus_call_method(bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "LookupDynamicUserByName", - &error, - &reply, - "s", - name); - if (r < 0) { - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + /* Access the dynamic UID allocation directly if we are called from dbus-daemon, see above. */ + r = direct_lookup_name(name, (uid_t*) &translated); + if (r == -ENOENT) goto not_found; - - goto fail; + if (r < 0) + goto fail; + + } else { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByName", + &error, + &reply, + "s", + name); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + goto not_found; + + goto fail; + } + + r = sd_bus_message_read(reply, "u", &translated); + if (r < 0) + goto fail; } - r = sd_bus_message_read(reply, "u", &translated); - if (r < 0) - goto fail; - l = strlen(name); if (buflen < l+1) { *errnop = ENOMEM; @@ -175,6 +228,7 @@ enum nss_status _nss_systemd_getpwuid_r( _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *direct = NULL; const char *translated; size_t l; int r; @@ -204,30 +258,42 @@ enum nss_status _nss_systemd_getpwuid_r( if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) goto not_found; - r = sd_bus_open_system(&bus); - if (r < 0) - goto fail; + if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) { - r = sd_bus_call_method(bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "LookupDynamicUserByUID", - &error, - &reply, - "u", - (uint32_t) uid); - if (r < 0) { - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + r = direct_lookup_uid(uid, &direct); + if (r == -ENOENT) goto not_found; - - goto fail; + if (r < 0) + goto fail; + + translated = direct; + + } else { + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByUID", + &error, + &reply, + "u", + (uint32_t) uid); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + goto not_found; + + goto fail; + } + + r = sd_bus_message_read(reply, "s", &translated); + if (r < 0) + goto fail; } - r = sd_bus_message_read(reply, "s", &translated); - if (r < 0) - goto fail; - l = strlen(translated) + 1; if (buflen < l) { *errnop = ENOMEM; @@ -262,9 +328,6 @@ enum nss_status _nss_systemd_getgrnam_r( char *buffer, size_t buflen, int *errnop) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; uint32_t translated; size_t l; int r; @@ -294,30 +357,45 @@ enum nss_status _nss_systemd_getgrnam_r( if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) goto not_found; - r = sd_bus_open_system(&bus); - if (r < 0) - goto fail; + if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) { - r = sd_bus_call_method(bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "LookupDynamicUserByName", - &error, - &reply, - "s", - name); - if (r < 0) { - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + /* Access the dynamic GID allocation directly if we are called from dbus-daemon, see above. */ + r = direct_lookup_name(name, (uid_t*) &translated); + if (r == -ENOENT) goto not_found; - - goto fail; + if (r < 0) + goto fail; + } else { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByName", + &error, + &reply, + "s", + name); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + goto not_found; + + goto fail; + } + + r = sd_bus_message_read(reply, "u", &translated); + if (r < 0) + goto fail; } - r = sd_bus_message_read(reply, "u", &translated); - if (r < 0) - goto fail; - l = sizeof(char*) + strlen(name) + 1; if (buflen < l) { *errnop = ENOMEM; @@ -353,6 +431,7 @@ enum nss_status _nss_systemd_getgrgid_r( _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *direct = NULL; const char *translated; size_t l; int r; @@ -382,30 +461,41 @@ enum nss_status _nss_systemd_getgrgid_r( if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) goto not_found; - r = sd_bus_open_system(&bus); - if (r < 0) - goto fail; + if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) { - r = sd_bus_call_method(bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "LookupDynamicUserByUID", - &error, - &reply, - "u", - (uint32_t) gid); - if (r < 0) { - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + r = direct_lookup_uid(gid, &direct); + if (r == -ENOENT) goto not_found; - - goto fail; + if (r < 0) + goto fail; + + translated = direct; + } else { + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByUID", + &error, + &reply, + "u", + (uint32_t) gid); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + goto not_found; + + goto fail; + } + + r = sd_bus_message_read(reply, "s", &translated); + if (r < 0) + goto fail; } - r = sd_bus_message_read(reply, "s", &translated); - if (r < 0) - goto fail; - l = sizeof(char*) + strlen(translated) + 1; if (buflen < l) { *errnop = ENOMEM; -- cgit v1.2.3-54-g00ecf From 6e32c03ed87e5dfd3857013e909e48b5e61564c1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 00:35:05 +0200 Subject: nss-mymachines: avoid connecting to dbus from inside dbus-daemon Inspired from the new logic in nss-systemd let's make sure we don't end up deadlocking in nss-mymachines either in case dbus-daemon tries to a look up a name and we want to connect to the bus. This case is much simpler though, as there's no point in resolving virtual machine UIDs by dbus-daemon as those should never be able to connect to the host's busses. --- src/nss-mymachines/nss-mymachines.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c index 8d57b26cbc..895f61c462 100644 --- a/src/nss-mymachines/nss-mymachines.c +++ b/src/nss-mymachines/nss-mymachines.c @@ -25,6 +25,7 @@ #include "alloc-util.h" #include "bus-common-errors.h" +#include "env-util.h" #include "hostname-util.h" #include "in-addr-util.h" #include "macro.h" @@ -434,6 +435,12 @@ enum nss_status _nss_mymachines_getpwnam_r( if (!machine_name_is_valid(machine)) goto not_found; + if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) + /* Make sure we can't deadlock if we are invoked by dbus-daemon. This way, it won't be able to resolve + * these UIDs, but that should be unproblematic as containers should never be able to connect to a bus + * running on the host. */ + goto not_found; + r = sd_bus_open_system(&bus); if (r < 0) goto fail; @@ -514,6 +521,9 @@ enum nss_status _nss_mymachines_getpwuid_r( if (uid < HOST_UID_LIMIT) goto not_found; + if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) + goto not_found; + r = sd_bus_open_system(&bus); if (r < 0) goto fail; @@ -605,6 +615,9 @@ enum nss_status _nss_mymachines_getgrnam_r( if (!machine_name_is_valid(machine)) goto not_found; + if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) + goto not_found; + r = sd_bus_open_system(&bus); if (r < 0) goto fail; @@ -682,6 +695,9 @@ enum nss_status _nss_mymachines_getgrgid_r( if (gid < HOST_GID_LIMIT) goto not_found; + if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) + goto not_found; + r = sd_bus_open_system(&bus); if (r < 0) goto fail; -- cgit v1.2.3-54-g00ecf From 2ae0858e6c12018def32921e5d732395c74c4379 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 03:16:16 +0200 Subject: hostnamectl: rework pretty hostname validation (#3985) Rework 17eb9a9ddba3f03fcba33445c1c1eedeb948da04 a bit. Let's make sure we don't clobber the input parameter args[1], following our coding style to not clobber parameters unless explicitly indicated. (in particular, as we don't want to have our changes appear in the command line shown in "ps"...) No functional change. --- src/basic/hostname-util.c | 1 - src/hostname/hostnamectl.c | 36 +++++++++++++++++++----------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c index 13c3bb6446..e44a357287 100644 --- a/src/basic/hostname-util.c +++ b/src/basic/hostname-util.c @@ -163,7 +163,6 @@ char* hostname_cleanup(char *s) { *(d++) = *p; dot = false; } - } if (dot && d > s) diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index c16a324232..4795324667 100644 --- a/src/hostname/hostnamectl.c +++ b/src/hostname/hostnamectl.c @@ -251,7 +251,7 @@ static int set_simple_string(sd_bus *bus, const char *method, const char *value) static int set_hostname(sd_bus *bus, char **args, unsigned n) { _cleanup_free_ char *h = NULL; - char *hostname = args[1]; + const char *hostname = args[1]; int r; assert(args); @@ -263,27 +263,29 @@ static int set_hostname(sd_bus *bus, char **args, unsigned n) { if (arg_pretty) { const char *p; - /* If the passed hostname is already valid, then - * assume the user doesn't know anything about pretty - * hostnames, so let's unset the pretty hostname, and - * just set the passed hostname as static/dynamic + /* If the passed hostname is already valid, then assume the user doesn't know anything about pretty + * hostnames, so let's unset the pretty hostname, and just set the passed hostname as static/dynamic * hostname. */ - - if (arg_static && hostname_is_valid(hostname, true)) { - p = ""; - /* maybe get rid of trailing dot */ - hostname = hostname_cleanup(hostname); - } else { - p = h = strdup(hostname); - if (!p) - return log_oom(); - - hostname_cleanup(hostname); - } + if (arg_static && hostname_is_valid(hostname, true)) + p = ""; /* No pretty hostname (as it is redundant), just a static one */ + else + p = hostname; /* Use the passed name as pretty hostname */ r = set_simple_string(bus, "SetPrettyHostname", p); if (r < 0) return r; + + /* Now that we set the pretty hostname, let's clean up the parameter and use that as static + * hostname. If the hostname was already valid as static hostname, this will only chop off the trailing + * dot if there is one. If it was not valid, then it will be made fully valid by truncating, dropping + * multiple dots, and and dropping weird chars. Note that we clean the name up only if we also are + * supposed to set the pretty name. If the pretty name is not being set we assume the user knows what + * he does and pass the name as-is. */ + h = strdup(hostname); + if (!h) + return log_oom(); + + hostname = hostname_cleanup(h); /* Use the cleaned up name as static hostname */ } if (arg_static) { -- cgit v1.2.3-54-g00ecf From bbb040884dc88bcf27f7f08f0d10cb72e0e7fb4d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 15 Aug 2016 13:22:12 +1000 Subject: libudev: fix typo in comment --- src/libudev/libudev-device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c index 995bf56586..c5f36725dc 100644 --- a/src/libudev/libudev-device.c +++ b/src/libudev/libudev-device.c @@ -495,7 +495,7 @@ _public_ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struc return NULL; } - /* then walk the chain of udev_device parents until the correspanding + /* then walk the chain of udev_device parents until the corresponding one is found */ while ((udev_device = udev_device_get_parent(udev_device))) { if (udev_device->device == parent) -- cgit v1.2.3-54-g00ecf From 5fc9e4abb41e7f58f6c308f54881c596713fba75 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 16 Aug 2016 15:23:42 +1000 Subject: hwdb: add a udev property for a wheel click angle on horiz wheels The Logitech MX Master has a horizontal scroll wheel with a different click angle than the vertical one. Add a new property for this case, we can't add values to the normal one without risking upsetting existing parsers. Fixes #3947 --- hwdb/70-mouse.hwdb | 14 ++++++++++++++ hwdb/parse_hwdb.py | 1 + 2 files changed, 15 insertions(+) diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb index d8215a6179..70a7fb98d1 100644 --- a/hwdb/70-mouse.hwdb +++ b/hwdb/70-mouse.hwdb @@ -47,6 +47,7 @@ # ID_INPUT_TRACKBALL # MOUSE_DPI # MOUSE_WHEEL_CLICK_ANGLE +# MOUSE_WHEEL_CLICK_ANGLE_HORIZ # ######################################### # ID_INPUT_TRACKBALL # @@ -104,6 +105,14 @@ # # Most mice have a 15 degree click stop (24 clicks per full rotation). # +######################################### +# MOUSE_WHEEL_CLICK_ANGLE_HORIZ # +######################################### +# +# Identical to MOUSE_WHEEL_CLICK_ANGLE but for the horizontal scroll wheel. +# This property may only be specified if the angle for the horizontal +# scroll wheel differs from the vertical wheel. If so, *both* click angles +# must be specified. # # Sort by brand, type (usb, bluetooth), DPI, frequency. @@ -344,9 +353,14 @@ mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:402d: # Logitech Performance MX mouse:usb:v046dp101a:name:Logitech Performance MX: + MOUSE_DPI=1000@166 + # Logitech MX Master +# Horiz wheel has 14 stops, angle is rounded up mouse:usb:v046dp4041:name:Logitech MX Master: MOUSE_DPI=1000@166 + MOUSE_WHEEL_CLICK_ANGLE=15 + MOUSE_WHEEL_CLICK_ANGLE_HORIZ=26 # Logitech MK260 Wireless Combo Receiver aka M-R0011 mouse:usb:v046dpc52e:name:Logitech USB Receiver: diff --git a/hwdb/parse_hwdb.py b/hwdb/parse_hwdb.py index 99d034b4e0..fc23a5d025 100755 --- a/hwdb/parse_hwdb.py +++ b/hwdb/parse_hwdb.py @@ -82,6 +82,7 @@ def property_grammar(): setting = Optional('*')('DEFAULT') + INTEGER('DPI') + Suppress('@') + INTEGER('HZ') props = (('MOUSE_DPI', Group(OneOrMore(setting('SETTINGS*')))), ('MOUSE_WHEEL_CLICK_ANGLE', INTEGER), + ('MOUSE_WHEEL_CLICK_ANGLE_HORIZ', INTEGER), ('ID_INPUT_TRACKBALL', Literal('1')), ('POINTINGSTICK_SENSITIVITY', INTEGER), ('POINTINGSTICK_CONST_ACCEL', REAL), -- cgit v1.2.3-54-g00ecf From 206fc4b284afe68b1a0b7d776212ee81c12abf64 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 17 Aug 2016 12:06:07 -0400 Subject: systemd: warn when setrlimit fails This should make it easier to figure things out. --- src/core/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/main.c b/src/core/main.c index 02324d325e..3f4fa74fed 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1505,7 +1505,8 @@ int main(int argc, char *argv[]) { if (getpid() == 1) { /* Don't limit the core dump size, so that coredump handlers such as systemd-coredump (which honour the limit) * will process core dumps for system services by default. */ - (void) setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY)); + if (setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0) + log_warning_errno(errno, "Failed to set RLIMIT_CORE: %m"); /* But at the same time, turn off the core_pattern logic by default, so that no coredumps are stored * until the systemd-coredump tool is enabled via sysctl. */ -- cgit v1.2.3-54-g00ecf From bd64d82c1c0e3fe2a5f9b3dd9132d62834f50b2d Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 18 Aug 2016 21:39:39 -0400 Subject: Revert "pid1: reconnect to the console before being re-executed" This reverts commit affd7ed1a923b0df8479cff1bd9eafb625fdaa66. > So it looks like make_console_stdio() has bad side effect. More specifically it > does a TIOCSCTTY ioctl (via acquire_terminal()) which sees to disturb the > process which was using/owning the console. Fixes #3842. https://bugs.debian.org/834367 https://bugzilla.redhat.com/show_bug.cgi?id=1367766 --- src/core/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 3f4fa74fed..fd72c900e7 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -2014,9 +2014,6 @@ finish: log_error_errno(r, "Failed to switch root, trying to continue: %m"); } - /* Reopen the console */ - (void) make_console_stdio(); - args_size = MAX(6, argc+1); args = newa(const char*, args_size); @@ -2064,6 +2061,9 @@ finish: arg_serialization = safe_fclose(arg_serialization); fds = fdset_free(fds); + /* Reopen the console */ + (void) make_console_stdio(); + for (j = 1, i = 1; j < (unsigned) argc; j++) args[i++] = argv[j]; args[i++] = NULL; -- cgit v1.2.3-54-g00ecf From f50582649f8eee73f59aff95fadd9a963ed4ffea Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 18 Aug 2016 22:57:53 -0400 Subject: logind: update empty and "infinity" handling for [User]TasksMax (#3835) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The parsing functions for [User]TasksMax were inconsistent. Empty string and "infinity" were interpreted as no limit for TasksMax but not accepted for UserTasksMax. Update them so that they're consistent with other knobs. * Empty string indicates the default value. * "infinity" indicates no limit. While at it, replace opencoded (uint64_t) -1 with CGROUP_LIMIT_MAX in TasksMax handling. v2: Update empty string to indicate the default value as suggested by Zbigniew Jędrzejewski-Szmek. v3: Fixed empty UserTasksMax handling. --- man/logind.conf.xml | 5 +++-- src/basic/cgroup-util.h | 4 ++++ src/core/cgroup.c | 2 +- src/core/load-fragment.c | 20 +++++++++++++------- src/core/main.c | 2 +- src/login/logind-user.c | 13 ++++++++++++- src/login/logind.c | 3 ++- 7 files changed, 36 insertions(+), 13 deletions(-) diff --git a/man/logind.conf.xml b/man/logind.conf.xml index adba5a4131..cbee83357b 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -318,8 +318,9 @@ Sets the maximum number of OS tasks each user may run concurrently. This controls the TasksMax= setting of the per-user slice unit, see systemd.resource-control5 - for details. Defaults to 33%, which equals 10813 with the kernel's defaults on the host, but might be smaller - in OS containers. + for details. If assigned the special value infinity, no tasks limit is applied. + Defaults to 33%, which equals 10813 with the kernel's defaults on the host, but might be smaller in + OS containers. diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index a509a1775c..f1617a16be 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -112,6 +112,10 @@ static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) { (x >= CGROUP_BLKIO_WEIGHT_MIN && x <= CGROUP_BLKIO_WEIGHT_MAX); } +/* Default resource limits */ +#define DEFAULT_TASKS_MAX_PERCENTAGE 15U /* 15% of PIDs, 4915 on default settings */ +#define DEFAULT_USER_TASKS_MAX_PERCENTAGE 33U /* 33% of PIDs, 10813 on default settings */ + /* * General rules: * diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 910a64b4da..ca3c3366f3 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -952,7 +952,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { if ((mask & CGROUP_MASK_PIDS) && !is_root) { - if (c->tasks_max != (uint64_t) -1) { + if (c->tasks_max != CGROUP_LIMIT_MAX) { char buf[DECIMAL_STR_MAX(uint64_t) + 2]; sprintf(buf, "%" PRIu64 "\n", c->tasks_max); diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 4ad6c4d79b..d5185cf6a0 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2999,30 +2999,36 @@ int config_parse_tasks_max( void *data, void *userdata) { - uint64_t *tasks_max = data, u; + uint64_t *tasks_max = data, v; + Unit *u = userdata; int r; - if (isempty(rvalue) || streq(rvalue, "infinity")) { - *tasks_max = (uint64_t) -1; + if (isempty(rvalue)) { + *tasks_max = u->manager->default_tasks_max; + return 0; + } + + if (streq(rvalue, "infinity")) { + *tasks_max = CGROUP_LIMIT_MAX; return 0; } r = parse_percent(rvalue); if (r < 0) { - r = safe_atou64(rvalue, &u); + r = safe_atou64(rvalue, &v); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Maximum tasks value '%s' invalid. Ignoring.", rvalue); return 0; } } else - u = system_tasks_max_scale(r, 100U); + v = system_tasks_max_scale(r, 100U); - if (u <= 0 || u >= UINT64_MAX) { + if (v <= 0 || v >= UINT64_MAX) { log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range. Ignoring.", rvalue); return 0; } - *tasks_max = u; + *tasks_max = v; return 0; } diff --git a/src/core/main.c b/src/core/main.c index 02324d325e..c7c6df3447 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1559,7 +1559,7 @@ int main(int argc, char *argv[]) { (void) reset_all_signal_handlers(); (void) ignore_signals(SIGNALS_IGNORE, -1); - arg_default_tasks_max = system_tasks_max_scale(15U, 100U); /* 15% the system PIDs equals 4915 by default. */ + arg_default_tasks_max = system_tasks_max_scale(DEFAULT_TASKS_MAX_PERCENTAGE, 100U); if (parse_config_file() < 0) { error_message = "Failed to parse config file"; diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 11951aca5b..e0e73b034d 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -26,6 +26,7 @@ #include "bus-common-errors.h" #include "bus-error.h" #include "bus-util.h" +#include "cgroup-util.h" #include "clean-ipc.h" #include "conf-parser.h" #include "escape.h" @@ -896,7 +897,17 @@ int config_parse_user_tasks_max( assert(rvalue); assert(data); - /* First, try to parse as percentage */ + if (isempty(rvalue)) { + *m = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); + return 0; + } + + if (streq(rvalue, "infinity")) { + *m = CGROUP_LIMIT_MAX; + return 0; + } + + /* Try to parse as percentage */ r = parse_percent(rvalue); if (r >= 0) k = system_tasks_max_scale(r, 100U); diff --git a/src/login/logind.c b/src/login/logind.c index 5ce36d28c7..bbbf4aef57 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -38,6 +38,7 @@ #include "signal-util.h" #include "strv.h" #include "udev-util.h" +#include "cgroup-util.h" static void manager_free(Manager *m); @@ -62,7 +63,7 @@ static void manager_reset_config(Manager *m) { m->idle_action = HANDLE_IGNORE; m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */ - m->user_tasks_max = system_tasks_max_scale(33U, 100U); /* 33% */ + m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */ m->sessions_max = 8192; m->inhibitors_max = 8192; -- cgit v1.2.3-54-g00ecf From 986a34a6834795f1a2d25bcffbe67debf9bbd6b2 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 18 Aug 2016 23:09:29 -0400 Subject: core/dynamic-users: warn when creation of symlinks for dynamic users fails Also return the first error, since it's most likely to be interesting. If unlink fails, symlink will usually return EEXIST. --- src/core/dynamic-user.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c index 185d0e5f00..53c1699b92 100644 --- a/src/core/dynamic-user.c +++ b/src/core/dynamic-user.c @@ -154,7 +154,7 @@ static int make_uid_symlinks(uid_t uid, const char *name, bool b) { char path1[strlen("/run/systemd/dynamic-uid/direct:") + DECIMAL_STR_MAX(uid_t) + 1]; const char *path2; - int r = 0; + int r = 0, k; /* Add direct additional symlinks for direct lookups of dynamic UIDs and their names by userspace code. The * only reason we have this is because dbus-daemon cannot use D-Bus for resolving users and groups (since it @@ -164,23 +164,26 @@ static int make_uid_symlinks(uid_t uid, const char *name, bool b) { * on them and as those may be taken by any user with read access we can't make them world-readable. */ xsprintf(path1, "/run/systemd/dynamic-uid/direct:" UID_FMT, uid); - if (unlink(path1) < 0) { - if (errno != ENOENT) - r = -errno; - } - if (b) { - if (symlink(name, path1) < 0) - r = -errno; + if (unlink(path1) < 0 && errno != ENOENT) + r = -errno; + + if (b && symlink(name, path1) < 0) { + k = log_warning_errno(errno, "Failed to symlink \"%s\": %m", path1); + if (r == 0) + r = k; } path2 = strjoina("/run/systemd/dynamic-uid/direct:", name); - if (unlink(path2) < 0) { - if (errno != ENOENT) - r = -errno; + if (unlink(path2) < 0 && errno != ENOENT) { + k = -errno; + if (r == 0) + r = k; } - if (b) { - if (symlink(path1 + strlen("/run/systemd/dynamic-uid/direct:"), path2) < 0) - r = -errno; + + if (b && symlink(path1 + strlen("/run/systemd/dynamic-uid/direct:"), path2) < 0) { + k = log_warning_errno(errno, "Failed to symlink \"%s\": %m", path2); + if (r == 0) + r = k; } return r; -- cgit v1.2.3-54-g00ecf From 61755fdae08fffd72229feb52af74a85a9e0c8f7 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 18 Aug 2016 23:19:10 -0400 Subject: journald: do not create split journals for dynamic users Dynamic users should be treated like system users, and their logs should end up in the main system journal. --- src/basic/user-util.h | 16 ++++++++++++++-- src/core/dynamic-user.c | 17 ++++------------- src/journal/journald-server.c | 2 +- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/basic/user-util.h b/src/basic/user-util.h index 36f71fb004..f569363811 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -20,6 +20,7 @@ ***/ #include +#include #include #include @@ -57,8 +58,19 @@ int take_etc_passwd_lock(const char *root); #define UID_INVALID ((uid_t) -1) #define GID_INVALID ((gid_t) -1) -/* The following macros add 1 when converting things, since UID 0 is a - * valid UID, while the pointer NULL is special */ +/* Let's pick a UIDs within the 16bit range, so that we are compatible with containers using 16bit + * user namespacing. At least on Fedora normal users are allocated until UID 60000, hence do not + * allocate from below this. Also stay away from the upper end of the range as that is often used + * for overflow/nobody users. */ +#define DYNAMIC_UID_MIN ((uid_t) UINT32_C(0x0000EF00)) +#define DYNAMIC_UID_MAX ((uid_t) UINT32_C(0x0000FFEF)) + +static inline bool uid_is_dynamic(uid_t uid) { + return DYNAMIC_UID_MIN <= uid && uid <= DYNAMIC_UID_MAX; +} + +/* The following macros add 1 when converting things, since UID 0 is a valid UID, while the pointer + * NULL is special */ #define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1)) #define UID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1)) diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c index 53c1699b92..310aaa94e1 100644 --- a/src/core/dynamic-user.c +++ b/src/core/dynamic-user.c @@ -31,14 +31,8 @@ #include "user-util.h" #include "fileio.h" -/* Let's pick a UIDs within the 16bit range, so that we are compatible with containers using 16bit user namespacing. At - * least on Fedora normal users are allocated until UID 60000, hence do not allocate from below this. Also stay away - * from the upper end of the range as that is often used for overflow/nobody users. */ -#define UID_PICK_MIN ((uid_t) UINT32_C(0x0000EF00)) -#define UID_PICK_MAX ((uid_t) UINT32_C(0x0000FFEF)) - /* Takes a value generated randomly or by hashing and turns it into a UID in the right range */ -#define UID_CLAMP_INTO_RANGE(rnd) (((uid_t) (rnd) % (UID_PICK_MAX - UID_PICK_MIN + 1)) + UID_PICK_MIN) +#define UID_CLAMP_INTO_RANGE(rnd) (((uid_t) (rnd) % (DYNAMIC_UID_MAX - DYNAMIC_UID_MIN + 1)) + DYNAMIC_UID_MIN) static DynamicUser* dynamic_user_free(DynamicUser *d) { if (!d) @@ -214,7 +208,7 @@ static int pick_uid(const char *name, uid_t *ret_uid) { if (--n_tries <= 0) /* Give up retrying eventually */ return -EBUSY; - if (candidate < UID_PICK_MIN || candidate > UID_PICK_MAX) + if (!uid_is_dynamic(candidate)) goto next; xsprintf(lock_path, "/run/systemd/dynamic-uid/" UID_FMT, candidate); @@ -676,11 +670,8 @@ int dynamic_user_lookup_uid(Manager *m, uid_t uid, char **ret) { assert(m); assert(ret); - /* A friendly way to translate a dynamic user's UID into a his name. */ - - if (uid < UID_PICK_MIN) - return -ESRCH; - if (uid > UID_PICK_MAX) + /* A friendly way to translate a dynamic user's UID into a name. */ + if (!uid_is_dynamic(uid)) return -ESRCH; xsprintf(lock_path, "/run/systemd/dynamic-uid/" UID_FMT, uid); diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 443b2a4cd7..2a043a95b1 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -370,7 +370,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) { if (s->runtime_journal) return s->runtime_journal; - if (uid <= SYSTEM_UID_MAX) + if (uid <= SYSTEM_UID_MAX || uid_is_dynamic(uid)) return s->system_journal; r = sd_id128_get_machine(&machine); -- cgit v1.2.3-54-g00ecf From 8249c5722d373121950cc667747f0ca56cc21bbb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 19 Aug 2016 18:25:53 +1000 Subject: hwdb: add resolution for the Dell Precision 5510 (#3989) https://bugs.freedesktop.org/show_bug.cgi?id=97347 --- hwdb/60-evdev.hwdb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb index 4d14a6a2f4..e738ff7be5 100644 --- a/hwdb/60-evdev.hwdb +++ b/hwdb/60-evdev.hwdb @@ -134,6 +134,13 @@ evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLati EVDEV_ABS_35=76:1815:22 EVDEV_ABS_36=131:1330:30 +# Dell Precision 5510 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnPrecision5510* + EVDEV_ABS_00=::42 + EVDEV_ABS_01=::43 + EVDEV_ABS_35=::42 + EVDEV_ABS_36=::43 + # Dell Precision M4700 evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:*svnDellInc.:pnPrecisionM4700* EVDEV_ABS_00=0:1960:24 -- cgit v1.2.3-54-g00ecf From 2c85bbaa53da1c7c3becbcb969b9aa388498d388 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 11:01:21 +0200 Subject: tests: add test from #3979 Let's add one more test that came up during the discussion of an issue. The selected name with 69 chars is above the Linux hostname limit of 64. --- src/test/test-hostname-util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/test-hostname-util.c b/src/test/test-hostname-util.c index 17fde9f27e..1c3d13ed1d 100644 --- a/src/test/test-hostname-util.c +++ b/src/test/test-hostname-util.c @@ -42,6 +42,7 @@ static void test_hostname_is_valid(void) { assert_se(!hostname_is_valid("foo..bar", false)); assert_se(!hostname_is_valid("foo.bar..", false)); assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", false)); + assert_se(!hostname_is_valid("au-xph5-rvgrdsb5hcxc-47et3a5vvkrc-server-wyoz4elpdpe3.openstack.local", false)); assert_se(hostname_is_valid("foobar", true)); assert_se(hostname_is_valid("foobar.com", true)); -- cgit v1.2.3-54-g00ecf From 7c9f396b8aa9346642d5bb163d305ce7127b1685 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 11:02:24 +0200 Subject: man: document that static/transient hostnames may be 64 chars at max --- man/hostnamectl.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/man/hostnamectl.xml b/man/hostnamectl.xml index 60004e9d04..589a252ea8 100644 --- a/man/hostnamectl.xml +++ b/man/hostnamectl.xml @@ -71,10 +71,9 @@ set, and is valid (something other than localhost), then the transient hostname is not used. - Note that the pretty hostname has little restrictions on the - characters used, while the static and transient hostnames are - limited to the usually accepted characters of Internet domain - names. + Note that the pretty hostname has little restrictions on the characters and length used, while the static and + transient hostnames are limited to the usually accepted characters of Internet domain names, and 64 characters at + maximum (the latter being a Linux limitation). The static hostname is stored in /etc/hostname, see -- cgit v1.2.3-54-g00ecf From 0cce63da781878f8e66c15c4b32a61b8d61d03d1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 11:02:55 +0200 Subject: man: don't claim we replace spaces by dashes when cleaning up hostnames Let's make sure the man page actually documents what is implemented, i.e. "Lennart's PC" turns into "LennartsPC" when we clean up the name. --- man/hostnamectl.xml | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/man/hostnamectl.xml b/man/hostnamectl.xml index 589a252ea8..a7f89b918d 100644 --- a/man/hostnamectl.xml +++ b/man/hostnamectl.xml @@ -138,22 +138,14 @@ set-hostname NAME - Set the system hostname to - NAME. By default, this will alter - the pretty, the static, and the transient hostname alike; - however, if one or more of , - , are - used, only the selected hostnames are changed. If the pretty - hostname is being set, and static or transient are being set - as well, the specified hostname will be simplified in regards - to the character set used before the latter are updated. This - is done by replacing spaces with - and - removing special characters. This ensures that the pretty and - the static hostname are always closely related while still - following the validity rules of the specific name. This - simplification of the hostname string is not done if only the - transient and/or static host names are set, and the pretty - host name is left untouched. + Set the system hostname to NAME. By default, this will alter the + pretty, the static, and the transient hostname alike; however, if one or more of , + , are used, only the selected hostnames are changed. If + the pretty hostname is being set, and static or transient are being set as well, the specified hostname will be + simplified in regards to the character set used before the latter are updated. This is done by removing special + characters and spaces. This ensures that the pretty and the static hostname are always closely related while + still following the validity rules of the specific name. This simplification of the hostname string is not done + if only the transient and/or static host names are set, and the pretty host name is left untouched. Pass the empty string as the hostname to reset the selected hostnames to their default -- cgit v1.2.3-54-g00ecf From 986cf85d9481866662ac8a3e1b11ff2b02e3b013 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 11:04:13 +0200 Subject: man: minor wording fixes --- man/hostnamectl.xml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/man/hostnamectl.xml b/man/hostnamectl.xml index a7f89b918d..9e1b593e6d 100644 --- a/man/hostnamectl.xml +++ b/man/hostnamectl.xml @@ -106,15 +106,11 @@ - If status is used (or no - explicit command is given) and one of those fields is given, - hostnamectl will print out just this - selected hostname. - - If used with set-hostname, only the - selected hostname(s) will be updated. When more than one of - those options is used, all the specified hostnames will be - updated. + If status is invoked (or no explicit command is given) and one of these + switches is specified, hostnamectl will print out just this selected hostname. + + If used with set-hostname, only the selected hostname(s) will be updated. When more + than one of these switches are specified, all the specified hostnames will be updated. -- cgit v1.2.3-54-g00ecf From a6a8e60bd318c588f09aa89385f40ca926913574 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 15:31:36 +0200 Subject: hwdb: let's no abbreivate HORIZONTAL as HORIZ (#3994) I think I am developing OCD... Let's fix this before this actually gets used in the wild. A follow-up for #3986 (5fc9e4abb41e7f58f6c308f54881c596713fba75). --- hwdb/70-mouse.hwdb | 6 +++--- hwdb/parse_hwdb.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb index 70a7fb98d1..56e36af0e5 100644 --- a/hwdb/70-mouse.hwdb +++ b/hwdb/70-mouse.hwdb @@ -47,7 +47,7 @@ # ID_INPUT_TRACKBALL # MOUSE_DPI # MOUSE_WHEEL_CLICK_ANGLE -# MOUSE_WHEEL_CLICK_ANGLE_HORIZ +# MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL # ######################################### # ID_INPUT_TRACKBALL # @@ -106,7 +106,7 @@ # Most mice have a 15 degree click stop (24 clicks per full rotation). # ######################################### -# MOUSE_WHEEL_CLICK_ANGLE_HORIZ # +# MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL # ######################################### # # Identical to MOUSE_WHEEL_CLICK_ANGLE but for the horizontal scroll wheel. @@ -360,7 +360,7 @@ mouse:usb:v046dp101a:name:Logitech Performance MX: mouse:usb:v046dp4041:name:Logitech MX Master: MOUSE_DPI=1000@166 MOUSE_WHEEL_CLICK_ANGLE=15 - MOUSE_WHEEL_CLICK_ANGLE_HORIZ=26 + MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26 # Logitech MK260 Wireless Combo Receiver aka M-R0011 mouse:usb:v046dpc52e:name:Logitech USB Receiver: diff --git a/hwdb/parse_hwdb.py b/hwdb/parse_hwdb.py index fc23a5d025..f55562250d 100755 --- a/hwdb/parse_hwdb.py +++ b/hwdb/parse_hwdb.py @@ -82,7 +82,7 @@ def property_grammar(): setting = Optional('*')('DEFAULT') + INTEGER('DPI') + Suppress('@') + INTEGER('HZ') props = (('MOUSE_DPI', Group(OneOrMore(setting('SETTINGS*')))), ('MOUSE_WHEEL_CLICK_ANGLE', INTEGER), - ('MOUSE_WHEEL_CLICK_ANGLE_HORIZ', INTEGER), + ('MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL', INTEGER), ('ID_INPUT_TRACKBALL', Literal('1')), ('POINTINGSTICK_SENSITIVITY', INTEGER), ('POINTINGSTICK_CONST_ACCEL', REAL), -- cgit v1.2.3-54-g00ecf From 32d9493e593fed7fe5b4dd1e92fe4fd419042fe5 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 11 Aug 2016 21:53:32 -0400 Subject: systemctl: fix preset-all with missing /etc/systemd/system If the directory is missing, we can assume that those pesky symlinks are gone too. --- src/shared/install.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/install.c b/src/shared/install.c index e740ef3910..ccb1a70096 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -620,7 +620,7 @@ static int remove_marked_symlinks( fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); if (fd < 0) - return -errno; + return errno == ENOENT ? 0 : -errno; do { int q, cfd; -- cgit v1.2.3-54-g00ecf From ff56349d5a83f2202ed331f232f5d73467db482c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 12 Aug 2016 23:50:58 -0400 Subject: shared/install: remove unused paramater and add more comments --- src/shared/install.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/shared/install.c b/src/shared/install.c index ccb1a70096..0cf6a29403 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -903,6 +903,10 @@ static int install_info_may_process( return 0; } +/** + * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process + * hashmap, or retrieves the existing one if already present. + */ static int install_info_add( InstallContext *c, const char *name, @@ -1334,9 +1338,8 @@ static int install_info_follow( } /** - * Search for the unit file. If the unit name is a symlink, - * follow the symlink to the target, maybe more than once. - * Propagate the instance name if present. + * Search for the unit file. If the unit name is a symlink, follow the symlink to the + * target, maybe more than once. Propagate the instance name if present. */ static int install_info_traverse( UnitFileScope scope, @@ -1421,6 +1424,10 @@ static int install_info_traverse( return 0; } +/** + * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/") + * or the name (otherwise). root_dir is prepended to the path. + */ static int install_info_add_auto( InstallContext *c, const LookupPaths *paths, @@ -2685,7 +2692,6 @@ static int preset_prepare_one( InstallContext *plus, InstallContext *minus, LookupPaths *paths, - UnitFilePresetMode mode, const char *name, Presets presets, UnitFileChange **changes, @@ -2748,7 +2754,7 @@ int unit_file_preset( return r; STRV_FOREACH(i, files) { - r = preset_prepare_one(scope, &plus, &minus, &paths, mode, *i, presets, changes, n_changes); + r = preset_prepare_one(scope, &plus, &minus, &paths, *i, presets, changes, n_changes); if (r < 0) return r; } @@ -2809,7 +2815,7 @@ int unit_file_preset_all( continue; /* we don't pass changes[] in, because we want to handle errors on our own */ - r = preset_prepare_one(scope, &plus, &minus, &paths, mode, de->d_name, presets, NULL, 0); + r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, presets, NULL, 0); if (r == -ERFKILL) r = unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, de->d_name, NULL); -- cgit v1.2.3-54-g00ecf From 11e11fd57a837ea1cb142009c3048882392f3ed3 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 13 Aug 2016 01:20:29 -0400 Subject: shared/install: ignore unit symlinks when doing preset-all Before, when interating over unit files during preset-all, behaviour was the following: - if we hit the real unit name first, presets were queried for that name, and that unit was enabled or disabled accordingly, - if we hit an alias first (one of the symlinks chaining to the real unit), we checked the presets using the symlink name, and then proceeded to enable or disable the real unit. E.g. for systemd-networkd.service we have the alias dbus-org.freedesktop.network1.service (/usr/lib/systemd/system/dbus-org.freedesktop.network1.service), but the preset is only for the systemd-networkd.service name. The service would be enabled or disabled pseudorandomly depending on the order of iteration. For "preset", behaviour was analogous: preset on the alias name disabled the service (following the default disable policy), preset on the "real" name applied the presets. With the patch, for "preset" and "preset-all" we silently skip symlinks. This gives mostly the right behaviour, with the limitation that presets on aliases are ignored. I think that presets on aliases are not that common (at least my preset files on Fedora don't exhibit any such usage), and should not be necessary, since whoever installs the preset can just refer to the real unit file. It would be possible to overcome this limitation by gathering a list of names of a unit first, and then checking whether *any* of the names matches the presets list. That would require a significant redesign of the code, and be a lot slower (since we would have to fully read all unit directories to preset one unit) to so I'm not doing that for now. With this patch, two properties are satisfied: - preset-all and preset are idempotent, and the second and subsequent invocations do not produce any changes, - preset-all and preset for a specific name produce the same state for that unit. Fixes #3616. --- src/shared/install.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/shared/install.c b/src/shared/install.c index 0cf6a29403..8e40c171da 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1974,7 +1974,6 @@ int unit_file_revert( unsigned *n_changes) { _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; - /* _cleanup_(install_context_done) InstallContext c = {}; */ _cleanup_lookup_paths_free_ LookupPaths paths = {}; _cleanup_strv_free_ char **todo = NULL; size_t n_todo = 0, n_allocated = 0; @@ -2697,13 +2696,21 @@ static int preset_prepare_one( UnitFileChange **changes, unsigned *n_changes) { + _cleanup_(install_context_done) InstallContext tmp = {}; UnitFileInstallInfo *i; int r; - if (install_info_find(plus, name) || - install_info_find(minus, name)) + if (install_info_find(plus, name) || install_info_find(minus, name)) return 0; + r = install_info_discover(scope, &tmp, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); + if (r < 0) + return r; + if (!streq(name, i->name)) { + log_debug("Skipping %s because is an alias for %s", name, i->name); + return 0; + } + r = query_presets(name, presets); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From d923e42eed9a29137821760dafecb13798264c07 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 13 Aug 2016 09:38:12 -0400 Subject: man: describe what symlinks to unit do, and specify that presets must use real names The man pages didn't ever mention that symlinks to units can be created, and what exactly this means. Fix that omission, and disallow presets on alias names. --- man/systemctl.xml | 3 ++- man/systemd.preset.xml | 4 ++++ man/systemd.unit.xml | 36 +++++++++++++++++++++++------------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index 0ad0ad6d7e..78607c9ba3 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1092,7 +1092,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service enabled and disabled, or only enabled, or only disabled. If the unit carries no install information, it will be silently ignored - by this command. + by this command. NAME must be the real unit name, + any alias names are ignored silently. For more information on the preset policy format, see systemd.preset5. diff --git a/man/systemd.preset.xml b/man/systemd.preset.xml index b7164014f0..d09167baaf 100644 --- a/man/systemd.preset.xml +++ b/man/systemd.preset.xml @@ -98,6 +98,10 @@ Empty lines and lines whose first non-whitespace character is # or ; are ignored. + Presets must refer to the "real" unit file, and not to any aliases. See + systemd.unit5 + for a description of unit aliasing. + Two different directives are understood: enable may be used to enable units by default, disable to disable units by default. diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 85a7b12d76..f818e772a9 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -144,21 +144,31 @@ and are equivalent. - Time span values encoded in unit files can be written in - various formats. A stand-alone number specifies a time in seconds. - If suffixed with a time unit, the unit is honored. A concatenation - of multiple values with units is supported, in which case the - values are added up. Example: "50" refers to 50 seconds; "2min - 200ms" refers to 2 minutes plus 200 milliseconds, i.e. 120200ms. - The following time units are understood: s, min, h, d, w, ms, us. - For details see + Time span values encoded in unit files can be written in various formats. A stand-alone number specifies a + time in seconds. If suffixed with a time unit, the unit is honored. A concatenation of multiple values with units + is supported, in which case the values are added up. Example: 50 refers to 50 seconds; + 2min 200ms refers to 2 minutes and 200 milliseconds, i.e. 120200 ms. The following time units + are understood: s, min, h, d, + w, ms, us. For details see systemd.time7. - Empty lines and lines starting with # or ; are - ignored. This may be used for commenting. Lines ending - in a backslash are concatenated with the following - line while reading and the backslash is replaced by a - space character. This may be used to wrap long lines. + Empty lines and lines starting with # or ; are ignored. This may be + used for commenting. Lines ending in a backslash are concatenated with the following line while reading and the + backslash is replaced by a space character. This may be used to wrap long lines. + + Units can be aliased (have an alternative name), by creating a symlink from the new name to the existing name + in one of the unit search paths. For example, systemd-networkd.service has the alias + dbus-org.freedesktop.network1.service, created during installation as the symlink + /usr/lib/systemd/system/dbus-org.freedesktop.network1.service. In addition, unit files may + specify aliases through the Alias= directive in the [Install] section; those aliases are only + effective when the unit is enabled. When the unit is enabled, symlinks will be created for those names, and removed + when the unit is disabled. For example, reboot.target specifies + Alias=ctrl-alt-del.target, so when enabled it will be invoked whenever CTRL+ALT+DEL is + pressed. Alias names may be used in commands like enable, disable, + start, stop, status, …, and in unit dependency directives + Wants=, Requires=, Before=, After=, …, + with the limitation that aliases specified through Alias= are only effective when the unit is + enabled. Aliases cannot be used with the preset command. Along with a unit file foo.service, the directory foo.service.wants/ may exist. All -- cgit v1.2.3-54-g00ecf From 60bec8e4031367869520280350fa1523625d682b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 13 Aug 2016 01:21:57 -0400 Subject: shared/install: move root skipping into create_symlink() No functional change intended. --- src/shared/install.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/shared/install.c b/src/shared/install.c index 8e40c171da..ad2e619237 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -394,6 +394,7 @@ void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *chang } static int create_symlink( + const LookupPaths *paths, const char *old_path, const char *new_path, bool force, @@ -401,11 +402,16 @@ static int create_symlink( unsigned *n_changes) { _cleanup_free_ char *dest = NULL; + const char *rp; int r; assert(old_path); assert(new_path); + rp = skip_root(paths, old_path); + if (rp) + old_path = rp; + /* Actually create a symlink, and remember that we did. Is * smart enough to check if there's already a valid symlink in * place. @@ -1486,7 +1492,6 @@ static int install_info_symlink_alias( STRV_FOREACH(s, i->aliases) { _cleanup_free_ char *alias_path = NULL, *dst = NULL; - const char *rp; q = install_full_printf(i, *s, &dst); if (q < 0) @@ -1496,9 +1501,7 @@ static int install_info_symlink_alias( if (!alias_path) return -ENOMEM; - rp = skip_root(paths, i->path); - - q = create_symlink(rp ?: i->path, alias_path, force, changes, n_changes); + q = create_symlink(paths, i->path, alias_path, force, changes, n_changes); if (r == 0) r = q; } @@ -1542,7 +1545,6 @@ static int install_info_symlink_wants( STRV_FOREACH(s, list) { _cleanup_free_ char *path = NULL, *dst = NULL; - const char *rp; q = install_full_printf(i, *s, &dst); if (q < 0) @@ -1557,9 +1559,7 @@ static int install_info_symlink_wants( if (!path) return -ENOMEM; - rp = skip_root(paths, i->path); - - q = create_symlink(rp ?: i->path, path, true, changes, n_changes); + q = create_symlink(paths, i->path, path, true, changes, n_changes); if (r == 0) r = q; } @@ -1576,7 +1576,6 @@ static int install_info_symlink_link( unsigned *n_changes) { _cleanup_free_ char *path = NULL; - const char *rp; int r; assert(i); @@ -1594,9 +1593,7 @@ static int install_info_symlink_link( if (!path) return -ENOMEM; - rp = skip_root(paths, i->path); - - return create_symlink(rp ?: i->path, path, force, changes, n_changes); + return create_symlink(paths, i->path, path, force, changes, n_changes); } static int install_info_apply( @@ -1772,7 +1769,7 @@ int unit_file_mask( if (!path) return -ENOMEM; - q = create_symlink("/dev/null", path, force, changes, n_changes); + q = create_symlink(&paths, "/dev/null", path, force, changes, n_changes); if (q < 0 && r >= 0) r = q; } @@ -1932,14 +1929,12 @@ int unit_file_link( r = 0; STRV_FOREACH(i, todo) { _cleanup_free_ char *new_path = NULL; - const char *old_path; - old_path = skip_root(&paths, *i); new_path = path_make_absolute(basename(*i), config_path); if (!new_path) return -ENOMEM; - q = create_symlink(old_path ?: *i, new_path, force, changes, n_changes); + q = create_symlink(&paths, *i, new_path, force, changes, n_changes); if (q < 0 && r >= 0) r = q; } @@ -2318,7 +2313,7 @@ int unit_file_set_default( _cleanup_lookup_paths_free_ LookupPaths paths = {}; _cleanup_(install_context_done) InstallContext c = {}; UnitFileInstallInfo *i; - const char *new_path, *old_path; + const char *new_path; int r; assert(scope >= 0); @@ -2341,10 +2336,8 @@ int unit_file_set_default( if (r < 0) return r; - old_path = skip_root(&paths, i->path); new_path = strjoina(paths.persistent_config, "/" SPECIAL_DEFAULT_TARGET); - - return create_symlink(old_path ?: i->path, new_path, force, changes, n_changes); + return create_symlink(&paths, i->path, new_path, force, changes, n_changes); } int unit_file_get_default( -- cgit v1.2.3-54-g00ecf From 25ea92778d5f4339e07c152a99d16223f43ad681 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 13 Aug 2016 01:27:21 -0400 Subject: shared/install: when creating symlinks, keep existing relative symlinks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running preset-all on a system installed from rpms or even created using make install would remove and recreate a lot of symlinks, changing relative to absolute symlinks. In general relative symlinks are nicer, so there is no reason to change them, and those spurious changes were obscuring more interesting stuff. $ make install DESTDIR=/var/tmp/inst1 $ systemctl preset-all --root=/var/tmp/inst1 (before) Removed /var/tmp/inst1/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service. Created symlink /var/tmp/inst1/etc/systemd/system/ctrl-alt-del.target → /usr/lib/systemd/system/exit.target. Removed /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/remote-fs.target. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/remote-fs.target → /usr/lib/systemd/system/remote-fs.target. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/machines.target → /usr/lib/systemd/system/machines.target. Created symlink /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-journal-remote.socket → /usr/lib/systemd/system/systemd-journal-remote.socket. Removed /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-networkd.socket. Created symlink /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-networkd.socket → /usr/lib/systemd/system/systemd-networkd.socket. Removed /var/tmp/inst1/etc/systemd/system/getty.target.wants/getty@tty1.service. Created symlink /var/tmp/inst1/etc/systemd/system/getty.target.wants/getty@tty1.service → /usr/lib/systemd/system/getty@.service. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-journal-upload.service → /usr/lib/systemd/system/systemd-journal-upload.service. Removed /var/tmp/inst1/etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service. Created symlink /var/tmp/inst1/etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service → /usr/lib/systemd/system/systemd-timesyncd.service. Removed /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-resolved.service. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-resolved.service → /usr/lib/systemd/system/systemd-resolved.service. Removed /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-networkd.service. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-networkd.service → /usr/lib/systemd/system/systemd-networkd.service. (after) Removed /var/tmp/inst1/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service. Created symlink /var/tmp/inst1/etc/systemd/system/ctrl-alt-del.target → /usr/lib/systemd/system/exit.target. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/machines.target → /usr/lib/systemd/system/machines.target. Created symlink /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-journal-remote.socket → /usr/lib/systemd/system/systemd-journal-remote.socket. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-journal-upload.service → /usr/lib/systemd/system/systemd-journal-upload.service. --- src/shared/install.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/shared/install.c b/src/shared/install.c index ad2e619237..6c7eb9b2ef 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -393,6 +393,21 @@ void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *chang log_error_errno(r, "Failed to %s: %m.", verb); } +/** + * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem. + * wc should be the full path in the host file system. + */ +static bool chroot_symlinks_same(const char *root, const char *wd, const char *a, const char *b) { + assert(path_is_absolute(wd)); + + /* This will give incorrect results if the paths are relative and go outside + * of the chroot. False negatives are possible. */ + + a = strjoina(path_is_absolute(a) ? root : wd, "/", a); + b = strjoina(path_is_absolute(b) ? root : wd, "/", b); + return path_equal_or_files_same(a, b); +} + static int create_symlink( const LookupPaths *paths, const char *old_path, @@ -401,7 +416,7 @@ static int create_symlink( UnitFileChange **changes, unsigned *n_changes) { - _cleanup_free_ char *dest = NULL; + _cleanup_free_ char *dest = NULL, *dirname = NULL; const char *rp; int r; @@ -442,7 +457,11 @@ static int create_symlink( return r; } - if (path_equal(dest, old_path)) + dirname = dirname_malloc(new_path); + if (!dirname) + return -ENOMEM; + + if (chroot_symlinks_same(paths->root_dir, dirname, dest, old_path)) return 1; if (!force) { -- cgit v1.2.3-54-g00ecf From 58a6dd15582c038a25bd7059435833943e2e4617 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 13 Aug 2016 01:52:12 -0400 Subject: units: enable systemd-networkd-wait-online.service, disable all journal-remote stuff The preset for systemd-networkd-wait-online.service should match whatever we do for systemd-networkd.service. s-n-wait-online.service is only pulled in when some other unit pulls in network-online.target, otherwise it's not used. But if something pulls in network-online.target, they should expect s-n-wait-online.service to be active iff systemd-networkd.service is active. OTOH, the journal-remote and journal-upload services should be disabled by default, since they don't do anything without additional configuration. --- system-preset/90-systemd.preset | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system-preset/90-systemd.preset b/system-preset/90-systemd.preset index ee1b864bcf..09f920a5f7 100644 --- a/system-preset/90-systemd.preset +++ b/system-preset/90-systemd.preset @@ -15,6 +15,7 @@ enable getty@.service enable systemd-timesyncd.service enable systemd-networkd.service enable systemd-resolved.service +enable systemd-networkd-wait-online.service disable console-getty.service disable console-shell.service @@ -29,4 +30,5 @@ disable rescue.target disable syslog.socket disable systemd-journal-gatewayd.* -disable systemd-networkd-wait-online.service +disable systemd-journal-remote.* +disable systemd-journal-upload.* -- cgit v1.2.3-54-g00ecf From 0064dcc0fc1c6519d54c5a104990c1db94f19ddf Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 13 Aug 2016 01:55:16 -0400 Subject: units: synchronize Makefile and presets settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable reboot.target and disable exit.target: the first is used on normal machines, the second only in containers, and the more general one should be enabled by default. Also fix the Makefile to match what preset-all does. With this and the previous commits, doing "make instal DESTDIR=…" followed by "systemctl preset-all --root=…" doesn't result in any changes. --- Makefile.am | 4 ++++ system-preset/90-systemd.preset | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index d4e3e9a013..bc615bdc3b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -634,6 +634,10 @@ EXTRA_DIST += \ units/rc-local.service.in \ units/halt-local.service.in +GENERAL_ALIASES += \ + $(systemunitdir)/reboot.target $(pkgsysconfdir)/system/ctrl-alt-del.target \ + $(systemunitdir)/machines.target $(pkgsysconfdir)/system/multi-user.target.wants/machines.target + # automake is broken and can't handle files with a dash in front # http://debbugs.gnu.org/cgi/bugreport.cgi?bug=14728#8 units-install-hook: diff --git a/system-preset/90-systemd.preset b/system-preset/90-systemd.preset index 09f920a5f7..0f494b7552 100644 --- a/system-preset/90-systemd.preset +++ b/system-preset/90-systemd.preset @@ -24,8 +24,9 @@ disable debug-shell.service disable halt.target disable kexec.target disable poweroff.target -disable reboot.target +enable reboot.target disable rescue.target +disable exit.target disable syslog.socket -- cgit v1.2.3-54-g00ecf From de78fa9ba0be55b01066ca5a716c6673d76b817b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 13 Aug 2016 10:09:11 -0400 Subject: units: install user units as real files, not symlinks to ../system/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was causing preset-all --global to create symlinks: $ systemctl preset-all --global --root=/var/tmp/inst1 Created symlink /var/tmp/inst1/etc/systemd/user/shutdown.target → /usr/lib/systemd/user/../system/shutdown.target. Created symlink /var/tmp/inst1/etc/systemd/user/sockets.target → /usr/lib/systemd/user/../system/sockets.target. Created symlink /var/tmp/inst1/etc/systemd/user/timers.target → /usr/lib/systemd/user/../system/timers.target. Created symlink /var/tmp/inst1/etc/systemd/user/paths.target → /usr/lib/systemd/user/../system/paths.target. Created symlink /var/tmp/inst1/etc/systemd/user/bluetooth.target → /usr/lib/systemd/user/../system/bluetooth.target. Created symlink /var/tmp/inst1/etc/systemd/user/printer.target → /usr/lib/systemd/user/../system/printer.target. Created symlink /var/tmp/inst1/etc/systemd/user/sound.target → /usr/lib/systemd/user/../system/sound.target. Created symlink /var/tmp/inst1/etc/systemd/user/smartcard.target → /usr/lib/systemd/user/../system/smartcard.target. Created symlink /var/tmp/inst1/etc/systemd/user/busnames.target → /usr/lib/systemd/user/../system/busnames.target. It is better to create units in a state that completely matches the presets, i.e. preset-all should do nothing when invoked immediately after installation. I'm sure it was confusing to users too, suggesting that system and user units may somehow alias each other. --- Makefile.am | 24 ++++++++++-------------- units/user/bluetooth.target | 1 + units/user/busnames.target | 1 + units/user/paths.target | 1 + units/user/printer.target | 1 + units/user/shutdown.target | 1 + units/user/smartcard.target | 1 + units/user/sockets.target | 1 + units/user/sound.target | 1 + units/user/timers.target | 1 + 10 files changed, 19 insertions(+), 14 deletions(-) create mode 120000 units/user/bluetooth.target create mode 120000 units/user/busnames.target create mode 120000 units/user/paths.target create mode 120000 units/user/printer.target create mode 120000 units/user/shutdown.target create mode 120000 units/user/smartcard.target create mode 120000 units/user/sockets.target create mode 120000 units/user/sound.target create mode 120000 units/user/timers.target diff --git a/Makefile.am b/Makefile.am index bc615bdc3b..a1bb21e4fc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -575,7 +575,16 @@ dist_userunit_DATA = \ units/user/default.target \ units/user/exit.target \ units/user/graphical-session.target \ - units/user/graphical-session-pre.target + units/user/graphical-session-pre.target \ + units/user/bluetooth.target \ + units/user/busnames.target \ + units/user/paths.target \ + units/user/printer.target \ + units/user/shutdown.target \ + units/user/smartcard.target \ + units/user/sockets.target \ + units/user/sound.target \ + units/user/timers.target nodist_userunit_DATA = \ units/user/systemd-exit.service @@ -6296,19 +6305,6 @@ SYSTEM_UNIT_ALIASES += \ reboot.target ctrl-alt-del.target \ getty@.service autovt@.service -USER_UNIT_ALIASES += \ - $(systemunitdir)/shutdown.target shutdown.target \ - $(systemunitdir)/sockets.target sockets.target \ - $(systemunitdir)/timers.target timers.target \ - $(systemunitdir)/paths.target paths.target \ - $(systemunitdir)/bluetooth.target bluetooth.target \ - $(systemunitdir)/printer.target printer.target \ - $(systemunitdir)/sound.target sound.target \ - $(systemunitdir)/smartcard.target smartcard.target - -USER_UNIT_ALIASES += \ - $(systemunitdir)/busnames.target busnames.target - GENERAL_ALIASES += \ $(systemunitdir)/remote-fs.target $(pkgsysconfdir)/system/multi-user.target.wants/remote-fs.target \ $(systemunitdir)/getty@.service $(pkgsysconfdir)/system/getty.target.wants/getty@tty1.service \ diff --git a/units/user/bluetooth.target b/units/user/bluetooth.target new file mode 120000 index 0000000000..72e74be0a1 --- /dev/null +++ b/units/user/bluetooth.target @@ -0,0 +1 @@ +../bluetooth.target \ No newline at end of file diff --git a/units/user/busnames.target b/units/user/busnames.target new file mode 120000 index 0000000000..04f4ba1345 --- /dev/null +++ b/units/user/busnames.target @@ -0,0 +1 @@ +../busnames.target \ No newline at end of file diff --git a/units/user/paths.target b/units/user/paths.target new file mode 120000 index 0000000000..33545d24f3 --- /dev/null +++ b/units/user/paths.target @@ -0,0 +1 @@ +../paths.target \ No newline at end of file diff --git a/units/user/printer.target b/units/user/printer.target new file mode 120000 index 0000000000..8b8d5511cd --- /dev/null +++ b/units/user/printer.target @@ -0,0 +1 @@ +../printer.target \ No newline at end of file diff --git a/units/user/shutdown.target b/units/user/shutdown.target new file mode 120000 index 0000000000..a9de83782f --- /dev/null +++ b/units/user/shutdown.target @@ -0,0 +1 @@ +../shutdown.target \ No newline at end of file diff --git a/units/user/smartcard.target b/units/user/smartcard.target new file mode 120000 index 0000000000..f7a23b6b6d --- /dev/null +++ b/units/user/smartcard.target @@ -0,0 +1 @@ +../smartcard.target \ No newline at end of file diff --git a/units/user/sockets.target b/units/user/sockets.target new file mode 120000 index 0000000000..a9e4b97184 --- /dev/null +++ b/units/user/sockets.target @@ -0,0 +1 @@ +../sockets.target \ No newline at end of file diff --git a/units/user/sound.target b/units/user/sound.target new file mode 120000 index 0000000000..17c8e9d6e1 --- /dev/null +++ b/units/user/sound.target @@ -0,0 +1 @@ +../sound.target \ No newline at end of file diff --git a/units/user/timers.target b/units/user/timers.target new file mode 120000 index 0000000000..f98b68a84d --- /dev/null +++ b/units/user/timers.target @@ -0,0 +1 @@ +../timers.target \ No newline at end of file -- cgit v1.2.3-54-g00ecf From f16517151310b88591f3501a59e23ae2a79e7f02 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 17 Aug 2016 22:15:54 -0400 Subject: shared/install: properly report masked units listed in Also= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A masked unit is listed in Also=: $ systemctl cat test1 test2 →# /etc/systemd/system/test1.service [Unit] Description=test service 1 [Service] Type=oneshot ExecStart=/usr/bin/true [Install] WantedBy=multi-user.target Also=test2.service Alias=alias1.service →# /dev/null $ systemctl --root=/ enable test1 (before) Created symlink /etc/systemd/system/alias1.service → /etc/systemd/system/test1.service. Created symlink /etc/systemd/system/multi-user.target.wants/test1.service → /etc/systemd/system/test1.service. The unit files have no installation config (WantedBy, RequiredBy, Also, Alias settings in the [Install] section, and DefaultInstance for template units). This means they are not meant to be enabled using systemctl. Possible reasons for having this kind of units are: 1) A unit may be statically enabled by being symlinked from another unit's .wants/ or .requires/ directory. 2) A unit's purpose may be to act as a helper for some other unit which has a requirement dependency on it. 3) A unit may be started when needed via activation (socket, path, timer, D-Bus, udev, scripted systemctl call, ...). 4) In case of template units, the unit is meant to be enabled with some instance name specified. (after) Created symlink /etc/systemd/system/alias1.service → /etc/systemd/system/test1.service. Created symlink /etc/systemd/system/multi-user.target.wants/test1.service → /etc/systemd/system/test1.service. Unit /etc/systemd/system/test2.service is masked, ignoring. --- src/shared/install.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/shared/install.c b/src/shared/install.c index 6c7eb9b2ef..6a16f8985b 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1686,6 +1686,17 @@ static int install_context_apply( if (r < 0) return r; + /* We can attempt to process a masked unit when a different unit + * that we were processing specifies it in DefaultInstance= or Also=. */ + if (i->type == UNIT_FILE_TYPE_MASKED) { + unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path, NULL); + if (r >= 0) + /* Assume that some *could* have been enabled here, avoid + * "empty [Install] section" warning. */ + r += 1; + continue; + } + if (i->type != UNIT_FILE_TYPE_REGULAR) continue; -- cgit v1.2.3-54-g00ecf From 4d548a7d86cc50a6c09c16bda8e03c38d6bc84b9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 16:00:51 +0200 Subject: test: always check whether condition allocation worked Our tests should test for OOM too explicitly, hence fix the test accordingly --- src/test/test-condition.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/src/test/test-condition.c b/src/test/test-condition.c index 66003aa6bd..6f7d71ef9a 100644 --- a/src/test/test-condition.c +++ b/src/test/test-condition.c @@ -37,66 +37,82 @@ static void test_condition_test_path(void) { Condition *condition; condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false); + assert_se(condition); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true); + assert_se(condition); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false); + assert_se(condition); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false); + assert_se(condition); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false); + assert_se(condition); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_READ_WRITE, "/tmp", false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK, "/dev/stdout", false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); } @@ -105,38 +121,44 @@ static void test_condition_test_ac_power(void) { Condition *condition; condition = condition_new(CONDITION_AC_POWER, "true", false, false); + assert_se(condition); assert_se(condition_test(condition) == on_ac_power()); condition_free(condition); condition = condition_new(CONDITION_AC_POWER, "false", false, false); + assert_se(condition); assert_se(condition_test(condition) != on_ac_power()); condition_free(condition); condition = condition_new(CONDITION_AC_POWER, "false", false, true); + assert_se(condition); assert_se(condition_test(condition) == on_ac_power()); condition_free(condition); } static void test_condition_test_host(void) { + _cleanup_free_ char *hostname = NULL; + char sid[SD_ID128_STRING_MAX]; Condition *condition; sd_id128_t id; int r; - char sid[SD_ID128_STRING_MAX]; - _cleanup_free_ char *hostname = NULL; r = sd_id128_get_machine(&id); assert_se(r >= 0); assert_se(sd_id128_to_string(id, sid)); condition = condition_new(CONDITION_HOST, sid, false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false); + assert_se(condition); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_HOST, sid, false, true); + assert_se(condition); assert_se(!condition_test(condition)); condition_free(condition); @@ -148,6 +170,7 @@ static void test_condition_test_host(void) { log_notice("hostname is an id128, skipping test"); else { condition = condition_new(CONDITION_HOST, hostname, false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); } @@ -165,14 +188,17 @@ static void test_condition_test_architecture(void) { assert_se(sa); condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false); + assert_se(condition); assert_se(condition_test(condition) > 0); condition_free(condition); condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false); + assert_se(condition); assert_se(condition_test(condition) == 0); condition_free(condition); condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true); + assert_se(condition); assert_se(condition_test(condition) == 0); condition_free(condition); } @@ -181,10 +207,12 @@ static void test_condition_test_kernel_command_line(void) { Condition *condition; condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false); + assert_se(condition); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false); + assert_se(condition); assert_se(!condition_test(condition)); condition_free(condition); } @@ -193,10 +221,12 @@ static void test_condition_test_null(void) { Condition *condition; condition = condition_new(CONDITION_NULL, NULL, false, false); + assert_se(condition); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_NULL, NULL, false, true); + assert_se(condition); assert_se(!condition_test(condition)); condition_free(condition); } @@ -205,31 +235,36 @@ static void test_condition_test_security(void) { Condition *condition; condition = condition_new(CONDITION_SECURITY, "garbage oifdsjfoidsjoj", false, false); + assert_se(condition); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "selinux", false, true); + assert_se(condition); assert_se(condition_test(condition) != mac_selinux_have()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "ima", false, false); + assert_se(condition); assert_se(condition_test(condition) == use_ima()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "apparmor", false, false); + assert_se(condition); assert_se(condition_test(condition) == mac_apparmor_use()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "smack", false, false); + assert_se(condition); assert_se(condition_test(condition) == mac_smack_use()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "audit", false, false); + assert_se(condition); assert_se(condition_test(condition) == use_audit()); condition_free(condition); } - int main(int argc, char *argv[]) { log_parse_environment(); log_open(); -- cgit v1.2.3-54-g00ecf From d3fc8bf43f983e9da4ea1a5bb338f49dc5c755ba Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 16:01:17 +0200 Subject: tests: let's stick to 8ch indenting, in perl code too --- test/udev-test.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/udev-test.pl b/test/udev-test.pl index 129af854f1..9723386b23 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -37,7 +37,7 @@ my $EXIT_TEST_SKIP = 77; my $rules_10k_tags = ""; for (my $i = 1; $i <= 10000; ++$i) { - $rules_10k_tags .= 'KERNEL=="sda", TAG+="test' . $i . "\"\n"; + $rules_10k_tags .= 'KERNEL=="sda", TAG+="test' . $i . "\"\n"; } my @tests = ( @@ -1596,6 +1596,6 @@ system("umount", "$udev_tmpfs"); rmdir($udev_tmpfs); if ($error > 0) { - exit(1); + exit(1); } exit(0); -- cgit v1.2.3-54-g00ecf From 158fbf7661912adf0f42c93155499119811dde82 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 18 Aug 2016 22:03:56 -0400 Subject: systemd: ignore lack of tty when checking whether colors should be enabled When started by the kernel, we are connected to the console, and we'll set TERM properly to some value in fixup_environment(). We'll then enable or disable colors based on the value of $SYSTEMD_COLORS and $TERM. When reexecuting, TERM should be already set, so we can use this value. Effectively, behaviour is the same as before affd7ed1a was reverted, but instead of reopening the console before configuring color output, we just ignore what stdout is connected to and decide based on the variables only. --- src/basic/terminal-util.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index f0a46c48cf..19d289275e 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1191,12 +1191,9 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) { return receive_one_fd(pair[0], 0); } -bool terminal_is_dumb(void) { +static bool getenv_terminal_is_dumb(void) { const char *e; - if (!on_tty()) - return true; - e = getenv("TERM"); if (!e) return true; @@ -1204,6 +1201,13 @@ bool terminal_is_dumb(void) { return streq(e, "dumb"); } +bool terminal_is_dumb(void) { + if (!on_tty()) + return true; + + return getenv_terminal_is_dumb(); +} + bool colors_enabled(void) { static int enabled = -1; @@ -1213,6 +1217,9 @@ bool colors_enabled(void) { colors = getenv("SYSTEMD_COLORS"); if (colors) enabled = parse_boolean(colors) != 0; + else if (getpid() == 1) + /* PID1 outputs to the console without holding it open all the time */ + enabled = !getenv_terminal_is_dumb(); else enabled = !terminal_is_dumb(); } -- cgit v1.2.3-54-g00ecf From acf553b04d40ccde8098a2bcdebf8245b212d289 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 19 Aug 2016 10:26:27 -0400 Subject: terminal-util: use getenv_bool for $SYSTEMD_COLORS This changes the semantics a bit: before, SYSTEMD_COLORS= would be treated as "yes", same as SYSTEMD_COLORS=xxx and SYSTEMD_COLORS=1, and only SYSTEMD_COLORS=0 would be treated as "no". Now, only valid booleans are treated as "yes". This actually matches how $SYSTEMD_COLORS was announced in NEWS. --- man/systemd.xml | 10 ++++++---- src/basic/terminal-util.c | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/man/systemd.xml b/man/systemd.xml index 65f55199e2..e30333e209 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -837,8 +837,10 @@ $SYSTEMD_COLORS - Controls whether colorized output should be generated. - + The value must be a boolean. Controls whether colorized output should be + generated. This can be specified to override the decision that systemd + makes based on $TERM and what the console is connected to. + @@ -849,7 +851,7 @@ Set by systemd for supervised processes during socket-based activation. See sd_listen_fds3 - for more information. + for more information. @@ -858,7 +860,7 @@ Set by systemd for supervised processes for status and start-up completion notification. See sd_notify3 - for more information. + for more information. diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 19d289275e..bfa936bd4e 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -39,6 +39,7 @@ #include #include "alloc-util.h" +#include "env-util.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" @@ -1212,11 +1213,11 @@ bool colors_enabled(void) { static int enabled = -1; if (_unlikely_(enabled < 0)) { - const char *colors; + int val; - colors = getenv("SYSTEMD_COLORS"); - if (colors) - enabled = parse_boolean(colors) != 0; + val = getenv_bool("SYSTEMD_COLORS"); + if (val >= 0) + enabled = val; else if (getpid() == 1) /* PID1 outputs to the console without holding it open all the time */ enabled = !getenv_terminal_is_dumb(); -- cgit v1.2.3-54-g00ecf From fb1bad9d51644f9db75f0aff7afc45610662756d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 18:16:28 +0200 Subject: man: document that "systemctl switch-root" tries hard to pass state across (#3995) As suggested: https://github.com/systemd/systemd/pull/3958#issuecomment-240410958 Let's document that we try hard to pass system state from the initrd to the host, and even compare the systemd binary paths. --- man/systemctl.xml | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index 0ad0ad6d7e..9762fd0450 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1680,20 +1680,15 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service switch-root ROOT INIT - Switches to a different root directory and executes a - new system manager process below it. This is intended for - usage in initial RAM disks ("initrd"), and will transition - from the initrd's system manager process (a.k.a. "init" - process) to the main system manager process. This call takes two - arguments: the directory that is to become the new root directory, and - the path to the new system manager binary below it to - execute as PID 1. If the latter is omitted or the empty - string, a systemd binary will automatically be searched for - and used as init. If the system manager path is omitted or - equal to the empty string, the state of the initrd's system - manager process is passed to the main system manager, which - allows later introspection of the state of the services - involved in the initrd boot. + Switches to a different root directory and executes a new system manager process below it. This is + intended for usage in initial RAM disks ("initrd"), and will transition from the initrd's system manager + process (a.k.a. "init" process) to the main system manager process which is loaded from the actual host + volume. This call takes two arguments: the directory that is to become the new root directory, and the path + to the new system manager binary below it to execute as PID 1. If the latter is omitted or the empty + string, a systemd binary will automatically be searched for and used as init. If the system manager path is + omitted, equal to the empty string or identical to the path to the systemd binary, the state of the + initrd's system manager process is passed to the main system manager, which allows later introspection of + the state of the services involved in the initrd boot phase. -- cgit v1.2.3-54-g00ecf From e6c9fa74a5b1dc1c29797cab43a078b512438885 Mon Sep 17 00:00:00 2001 From: 0xAX <0xAX@users.noreply.github.com> Date: Sat, 20 Aug 2016 01:51:54 +0300 Subject: terminal-util: remove unnecessary check of result of isatty() (#4000) After the call of the isatty() we check its result twice in the open_terminal(). There are no sense to check result of isatty() that it is less than zero and return -errno, because as described in documentation: isatty() returns 1 if fd is an open file descriptor referring to a terminal; otherwise 0 is returned, and errno is set to indicate the error. So it can't be less than zero. --- src/basic/terminal-util.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index bfa936bd4e..eafdea9eb3 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -346,12 +346,7 @@ int open_terminal(const char *name, int mode) { } r = isatty(fd); - if (r < 0) { - safe_close(fd); - return -errno; - } - - if (!r) { + if (r == 0) { safe_close(fd); return -ENOTTY; } -- cgit v1.2.3-54-g00ecf From 169d7fb684b39d9132de80f88c53760647f2e042 Mon Sep 17 00:00:00 2001 From: Clinton Roy Date: Sat, 20 Aug 2016 08:59:02 +1000 Subject: systemctl: kill all units specified on the command line, not just the first one. --- src/systemctl/systemctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 4444e3064d..4b87bdceb2 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3384,9 +3384,9 @@ static int kill_unit(int argc, char *argv[], void *userdata) { "KillUnit", &error, NULL, - "ssi", *names, kill_who ? kill_who : arg_kill_who, arg_signal); + "ssi", *name, kill_who ? kill_who : arg_kill_who, arg_signal); if (q < 0) { - log_error_errno(q, "Failed to kill unit %s: %s", *names, bus_error_message(&error, q)); + log_error_errno(q, "Failed to kill unit %s: %s", *name, bus_error_message(&error, q)); if (r == 0) r = q; } -- cgit v1.2.3-54-g00ecf From e3fc2b025e6277c913e34bbee7c60d2561adcc48 Mon Sep 17 00:00:00 2001 From: Seraphime Date: Sun, 21 Aug 2016 05:39:07 +0200 Subject: machinectl: print OS release in `machinectl list` (#3975) --- src/machine/machinectl.c | 129 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 89 insertions(+), 40 deletions(-) diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index c78ca7ad76..4acce4bea7 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -109,6 +109,7 @@ typedef struct MachineInfo { const char *name; const char *class; const char *service; + char *os; } MachineInfo; static int compare_machine_info(const void *a, const void *b) { @@ -117,12 +118,66 @@ static int compare_machine_info(const void *a, const void *b) { return strcmp(x->name, y->name); } +static void clean_machine_info(MachineInfo *machines, size_t n_machines) { + size_t i; + + if (!machines || n_machines == 0) + return; + + for (i = 0; i < n_machines; i++) + free(machines[i].os); + free(machines); +} + +static int get_os_name(sd_bus *bus, const char *name, char **out) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *k, *v, *os; + char *str; + int r; + + assert(bus); + assert(name); + assert(out); + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetMachineOSRelease", + NULL, &reply, "s", name); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(reply, 'a', "{ss}"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) { + if (streq(k, "PRETTY_NAME")) + os = v; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + str = strdup(os); + if (!str) + return log_oom(); + *out = str; + + return 0; +} + static int list_machines(int argc, char *argv[], void *userdata) { - size_t max_name = strlen("MACHINE"), max_class = strlen("CLASS"), max_service = strlen("SERVICE"); + size_t max_name = strlen("MACHINE"), max_class = strlen("CLASS"), + max_service = strlen("SERVICE"), max_os = strlen("OS"); _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_free_ MachineInfo *machines = NULL; + MachineInfo *machines = NULL; const char *name, *class, *service, *object; size_t n_machines = 0, n_allocated = 0, j; sd_bus *bus = userdata; @@ -148,15 +203,21 @@ static int list_machines(int argc, char *argv[], void *userdata) { r = sd_bus_message_enter_container(reply, 'a', "(ssso)"); if (r < 0) return bus_log_parse_error(r); - while ((r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, &object)) > 0) { size_t l; if (name[0] == '.' && !arg_all) continue; - if (!GREEDY_REALLOC(machines, n_allocated, n_machines + 1)) - return log_oom(); + if (!GREEDY_REALLOC(machines, n_allocated, n_machines + 1)) { + r = log_oom(); + goto out; + } + + machines[n_machines].os = NULL; + r = get_os_name(bus, name, &machines[n_machines].os); + if (r < 0) + goto out; machines[n_machines].name = name; machines[n_machines].class = class; @@ -174,35 +235,47 @@ static int list_machines(int argc, char *argv[], void *userdata) { if (l > max_service) max_service = l; + l = machines[n_machines].os ? strlen(machines[n_machines].os) : 0; + if (l > max_os) + max_os = l; + n_machines++; } - if (r < 0) - return bus_log_parse_error(r); + if (r < 0) { + r = bus_log_parse_error(r); + goto out; + } r = sd_bus_message_exit_container(reply); - if (r < 0) - return bus_log_parse_error(r); + if (r < 0) { + r = bus_log_parse_error(r); + goto out; + } qsort_safe(machines, n_machines, sizeof(MachineInfo), compare_machine_info); if (arg_legend && n_machines > 0) - printf("%-*s %-*s %-*s\n", + printf("%-*s %-*s %-*s %-*s\n", (int) max_name, "MACHINE", (int) max_class, "CLASS", - (int) max_service, "SERVICE"); + (int) max_service, "SERVICE", + (int) max_os, "OS"); for (j = 0; j < n_machines; j++) - printf("%-*s %-*s %-*s\n", + printf("%-*s %-*s %-*s %-*s\n", (int) max_name, machines[j].name, (int) max_class, machines[j].class, - (int) max_service, machines[j].service); + (int) max_service, machines[j].service, + (int) max_os, machines[j].os ? machines[j].os : ""); if (arg_legend && n_machines > 0) printf("\n%zu machines listed.\n", n_machines); else printf("No machines.\n"); - return 0; +out: + clean_machine_info(machines, n_machines); + return r; } typedef struct ImageInfo { @@ -456,41 +529,17 @@ static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *p } static int print_os_release(sd_bus *bus, const char *name, const char *prefix) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - const char *k, *v, *pretty = NULL; + _cleanup_free_ char *pretty = NULL; int r; assert(bus); assert(name); assert(prefix); - r = sd_bus_call_method(bus, - "org.freedesktop.machine1", - "/org/freedesktop/machine1", - "org.freedesktop.machine1.Manager", - "GetMachineOSRelease", - NULL, - &reply, - "s", name); + r = get_os_name(bus, name, &pretty); if (r < 0) return r; - r = sd_bus_message_enter_container(reply, 'a', "{ss}"); - if (r < 0) - return bus_log_parse_error(r); - - while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) { - if (streq(k, "PRETTY_NAME")) - pretty = v; - - } - if (r < 0) - return bus_log_parse_error(r); - - r = sd_bus_message_exit_container(reply); - if (r < 0) - return bus_log_parse_error(r); - if (pretty) printf("%s%s\n", prefix, pretty); -- cgit v1.2.3-54-g00ecf From 47d2d30d83eb7494593181915967be38451d72f1 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 21 Aug 2016 09:06:28 -0400 Subject: networkd: limit the number of routes to the kernel limit (#4007) Fixes #3922. --- src/network/networkd-route.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index b197a5da6b..6f60ee5e31 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -26,10 +26,37 @@ #include "parse-util.h" #include "set.h" #include "string-util.h" +#include "sysctl-util.h" #include "util.h" -#define ROUTES_PER_LINK_MAX 2048U -#define STATIC_ROUTES_PER_NETWORK_MAX 1024U +#define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U + +static unsigned routes_max(void) { + static thread_local unsigned cached = 0; + + _cleanup_free_ char *s4 = NULL, *s6 = NULL; + unsigned val4 = ROUTES_DEFAULT_MAX_PER_FAMILY, val6 = ROUTES_DEFAULT_MAX_PER_FAMILY; + + if (cached > 0) + return cached; + + if (sysctl_read("net/ipv4/route/max_size", &s4) >= 0) { + truncate_nl(s4); + if (safe_atou(s4, &val4) >= 0 && + val4 == 2147483647U) + /* This is the default "no limit" value in the kernel */ + val4 = ROUTES_DEFAULT_MAX_PER_FAMILY; + } + + if (sysctl_read("net/ipv6/route/max_size", &s6) >= 0) { + truncate_nl(s6); + (void) safe_atou(s6, &val6); + } + + cached = MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val4) + + MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val6); + return cached; +} int route_new(Route **ret) { _cleanup_route_free_ Route *route = NULL; @@ -67,7 +94,7 @@ int route_new_static(Network *network, unsigned section, Route **ret) { } } - if (network->n_static_routes >= STATIC_ROUTES_PER_NETWORK_MAX) + if (network->n_static_routes >= routes_max()) return -E2BIG; r = route_new(&route); @@ -484,7 +511,7 @@ int route_configure( assert(route->family == AF_INET || route->family == AF_INET6); if (route_get(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL) <= 0 && - set_size(link->routes) >= ROUTES_PER_LINK_MAX) + set_size(link->routes) >= routes_max()) return -E2BIG; r = sd_rtnl_message_new_route(link->manager->rtnl, &req, -- cgit v1.2.3-54-g00ecf From 047d91f9c8cf1bcf5a30f428668babd619533944 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 21 Aug 2016 09:10:51 -0400 Subject: shared/install: do not enable masked instances (#4005) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When told to enable a template unit, and the DefaultInstance specified in that unit was masked, we would do this. Such a unit cannot be started or loaded, so reporting successful enabling is misleading and unexpected. $ systemctl mask getty@tty1 Created symlink /etc/systemd/system/getty@tty1.service → /dev/null. $ systemctl --root=/ enable getty@tty1 (unchanged) Failed to enable unit, unit /etc/systemd/system/getty@tty1.service is masked. $ systemctl --root=/ enable getty@ (before) Created symlink /etc/systemd/system/getty.target.wants/getty@tty1.service → /usr/lib/systemd/system/getty@.service. (now) Failed to enable unit, unit /etc/systemd/system/getty@tty1.service is masked. The same error is emitted for enable and preset. And an error is emmited, not a warning, so the failure to enable DefaultInstance is treated the same as if the instance was specified on the command line. I think that this makes most sense, for most template units. Fixes #2513. --- src/shared/install.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/shared/install.c b/src/shared/install.c index 6a16f8985b..6b82ad05a7 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -912,8 +912,8 @@ static int install_info_may_process( assert(i); assert(paths); - /* Checks whether the loaded unit file is one we should process, or is masked, transient or generated and thus - * not subject to enable/disable operations. */ + /* Checks whether the loaded unit file is one we should process, or is masked, + * transient or generated and thus not subject to enable/disable operations. */ if (i->type == UNIT_FILE_TYPE_MASKED) { unit_file_changes_add(changes, n_changes, -ERFKILL, i->path, NULL); @@ -1134,7 +1134,6 @@ static int unit_file_load( struct stat st; int r; - assert(c); assert(info); assert(path); @@ -1163,6 +1162,9 @@ static int unit_file_load( return 0; } + /* c is only needed if we actually load the file */ + assert(c); + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); if (fd < 0) return -errno; @@ -1275,7 +1277,6 @@ static int unit_file_search( char **p; int r; - assert(c); assert(info); assert(paths); @@ -1546,7 +1547,14 @@ static int install_info_symlink_wants( assert(paths); assert(config_path); + if (strv_isempty(list)) + return 0; + if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) { + UnitFileInstallInfo instance = { + .type = _UNIT_FILE_TYPE_INVALID, + }; + _cleanup_free_ char *path = NULL; /* Don't install any symlink if there's no default * instance configured */ @@ -1558,6 +1566,19 @@ static int install_info_symlink_wants( if (r < 0) return r; + instance.name = buf; + r = unit_file_search(NULL, &instance, paths, SEARCH_FOLLOW_CONFIG_SYMLINKS); + if (r < 0) + return r; + + path = instance.path; + instance.path = NULL; + + if (instance.type == UNIT_FILE_TYPE_MASKED) { + unit_file_changes_add(changes, n_changes, -ERFKILL, path, NULL); + return -ERFKILL; + } + n = buf; } else n = i->name; @@ -1687,12 +1708,12 @@ static int install_context_apply( return r; /* We can attempt to process a masked unit when a different unit - * that we were processing specifies it in DefaultInstance= or Also=. */ + * that we were processing specifies it in Also=. */ if (i->type == UNIT_FILE_TYPE_MASKED) { unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path, NULL); if (r >= 0) - /* Assume that some *could* have been enabled here, avoid - * "empty [Install] section" warning. */ + /* Assume that something *could* have been enabled here, + * avoid "empty [Install] section" warning. */ r += 1; continue; } -- cgit v1.2.3-54-g00ecf From b68d26b8cd5b5175e84a6b7a464a96dca6d40f66 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 21 Aug 2016 13:15:26 -0400 Subject: networkd: fix typo (#4013) --- src/network/networkd-link.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 69ee7424ce..71484e3288 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2805,17 +2805,17 @@ network_file_fail: if (dhcp4_address) { r = in_addr_from_string(AF_INET, dhcp4_address, &address); if (r < 0) { - log_link_debug_errno(link, r, "Falied to parse DHCPv4 address %s: %m", dhcp4_address); + log_link_debug_errno(link, r, "Failed to parse DHCPv4 address %s: %m", dhcp4_address); goto dhcp4_address_fail; } r = sd_dhcp_client_new(&link->dhcp_client); if (r < 0) - return log_link_error_errno(link, r, "Falied to create DHCPv4 client: %m"); + return log_link_error_errno(link, r, "Failed to create DHCPv4 client: %m"); r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in); if (r < 0) - return log_link_error_errno(link, r, "Falied to set initial DHCPv4 address %s: %m", dhcp4_address); + return log_link_error_errno(link, r, "Failed to set initial DHCPv4 address %s: %m", dhcp4_address); } dhcp4_address_fail: @@ -2823,17 +2823,17 @@ dhcp4_address_fail: if (ipv4ll_address) { r = in_addr_from_string(AF_INET, ipv4ll_address, &address); if (r < 0) { - log_link_debug_errno(link, r, "Falied to parse IPv4LL address %s: %m", ipv4ll_address); + log_link_debug_errno(link, r, "Failed to parse IPv4LL address %s: %m", ipv4ll_address); goto ipv4ll_address_fail; } r = sd_ipv4ll_new(&link->ipv4ll); if (r < 0) - return log_link_error_errno(link, r, "Falied to create IPv4LL client: %m"); + return log_link_error_errno(link, r, "Failed to create IPv4LL client: %m"); r = sd_ipv4ll_set_address(link->ipv4ll, &address.in); if (r < 0) - return log_link_error_errno(link, r, "Falied to set initial IPv4LL address %s: %m", ipv4ll_address); + return log_link_error_errno(link, r, "Failed to set initial IPv4LL address %s: %m", ipv4ll_address); } ipv4ll_address_fail: -- cgit v1.2.3-54-g00ecf From df35bfaa25f8bda7953d922c73c5fd0242089fe6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 22 Aug 2016 09:31:25 +1000 Subject: hwdb: provide axis ranges for the Dell XPS M1530 (#4016) https://bugs.freedesktop.org/show_bug.cgi?id=97433 --- hwdb/60-evdev.hwdb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb index e738ff7be5..1606c66bbe 100644 --- a/hwdb/60-evdev.hwdb +++ b/hwdb/60-evdev.hwdb @@ -155,6 +155,11 @@ evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnXPS159550* EVDEV_ABS_35=::41 EVDEV_ABS_36=::43 +# Dell XPS M1530 +evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:bvn*:bvr*:bd*:svnDellInc.:pnXPSM1530* + EVDEV_ABS_00=85:947:15 + EVDEV_ABS_01=154:726:18 + ######################################### # Google ######################################### -- cgit v1.2.3-54-g00ecf From 05b4d3b55c0a60aa17817d51129f2bc83914c1f4 Mon Sep 17 00:00:00 2001 From: 0xAX <0xAX@users.noreply.github.com> Date: Mon, 22 Aug 2016 09:14:23 +0300 Subject: mount-tool: return 0 instead of NULL in the acquire_description() (#4009) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to prevent: src/mount/mount-tool.c: In function ‘acquire_description’: src/mount/mount-tool.c:728:24: warning: return makes integer from pointer without a cast [-Wint-conversion] return NULL; ^~~~ warning. Additionally we don't set Description property in a case when arg_description is NULL. --- src/mount/mount-tool.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index 9076ba3b0b..80bba086e4 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -319,9 +319,11 @@ static int parse_argv(int argc, char *argv[]) { static int transient_unit_set_properties(sd_bus_message *m, char **properties) { int r; - r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description); - if (r < 0) - return r; + if (!isempty(arg_description)) { + r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description); + if (r < 0) + return r; + } if (arg_bind_device && is_device_path(arg_mount_what)) { _cleanup_free_ char *device_unit = NULL; @@ -725,7 +727,7 @@ static int acquire_description(struct udev_device *d) { else if (model) arg_description = strdup(model); else - return NULL; + return 0; if (!arg_description) return log_oom(); -- cgit v1.2.3-54-g00ecf From 4a4485ae69bddf6cc01d4c50f3f53535c2d8fea4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Aug 2016 17:53:25 +0200 Subject: seccomp: make sure getrlimit() is among the default permitted syscalls A lot of basic code wants to know the stack size, and it is safe if they do, hence let's permit getrlimit() (but not setrlimit()) by default. See: #3970 --- src/shared/seccomp-util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 8656d112b8..b549426e2b 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -127,6 +127,7 @@ const SystemCallFilterSet syscall_filter_sets[] = { "execve\0" "exit\0" "exit_group\0" + "getrlimit\0" /* make sure processes can query stack size and such */ "rt_sigreturn\0" "sigreturn\0" }, { -- cgit v1.2.3-54-g00ecf From 512e3bbce6925f9951fcd1c397d4e1b6ab37d37a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Aug 2016 14:57:29 +0200 Subject: man: don't claim arguments where const that actually are not --- man/sd_bus_creds_new_from_pid.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/sd_bus_creds_new_from_pid.xml b/man/sd_bus_creds_new_from_pid.xml index 082f7b67db..b4d7d61d0f 100644 --- a/man/sd_bus_creds_new_from_pid.xml +++ b/man/sd_bus_creds_new_from_pid.xml @@ -66,12 +66,12 @@ uint64_t sd_bus_creds_get_mask - const sd_bus_creds *c + sd_bus_creds *c uint64_t sd_bus_creds_get_augmented_mask - const sd_bus_creds *c + sd_bus_creds *c -- cgit v1.2.3-54-g00ecf From ae1a2efa8b72c30b46528fa6469ce6686527dec7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Aug 2016 14:58:09 +0200 Subject: sd-bus: add a "recursive" mode to sd_bus_track This adds an optional "recursive" counting mode to sd_bus_track. If enabled adding the same name multiple times to an sd_bus_track object is counted individually, so that it also has to be removed the same number of times before it is gone again from the tracking object. This functionality is useful for implementing local ref counted objects that peers make take references on. --- src/libsystemd/libsystemd.sym | 8 ++ src/libsystemd/sd-bus/bus-track.c | 188 +++++++++++++++++++++++++++++++------- src/systemd/sd-bus.h | 8 +- 3 files changed, 172 insertions(+), 32 deletions(-) diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 542254295c..ae60e346eb 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -500,3 +500,11 @@ LIBSYSTEMD_231 { global: sd_event_get_iteration; } LIBSYSTEMD_230; + +LIBSYSTEMD_232 { +global: + sd_bus_track_set_recursive; + sd_bus_track_get_recursive; + sd_bus_track_count_name; + sd_bus_track_count_sender; +} LIBSYSTEMD_231; diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 1f436fe560..6ece2244c2 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -24,6 +24,12 @@ #include "bus-track.h" #include "bus-util.h" +struct track_item { + unsigned n_ref; + char *name; + sd_bus_slot *slot; +}; + struct sd_bus_track { unsigned n_ref; sd_bus *bus; @@ -32,8 +38,9 @@ struct sd_bus_track { Hashmap *names; LIST_FIELDS(sd_bus_track, queue); Iterator iterator; - bool in_queue; - bool modified; + bool in_queue:1; + bool modified:1; + bool recursive:1; }; #define MATCH_PREFIX \ @@ -56,6 +63,20 @@ struct sd_bus_track { _x; \ }) +static struct track_item* track_item_free(struct track_item *i) { + + if (!i) + return NULL; + + sd_bus_slot_unref(i->slot); + free(i->name); + free(i); + + return NULL; +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free); + static void bus_track_add_to_queue(sd_bus_track *track) { assert(track); @@ -79,6 +100,25 @@ static void bus_track_remove_from_queue(sd_bus_track *track) { track->in_queue = false; } +static int bus_track_remove_name_fully(sd_bus_track *track, const char *name) { + struct track_item *i; + + assert(track); + assert(name); + + i = hashmap_remove(track->names, name); + if (!i) + return 0; + + track_item_free(i); + + if (hashmap_isempty(track->names)) + bus_track_add_to_queue(track); + + track->modified = true; + return 1; +} + _public_ int sd_bus_track_new( sd_bus *bus, sd_bus_track **track, @@ -121,7 +161,7 @@ _public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) { } _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { - const char *n; + struct track_item *i; if (!track) return NULL; @@ -133,8 +173,8 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { return NULL; } - while ((n = hashmap_first_key(track->names))) - sd_bus_track_remove_name(track, n); + while ((i = hashmap_steal_first(track->names))) + track_item_free(i); bus_track_remove_from_queue(track); hashmap_free(track->names); @@ -156,49 +196,64 @@ static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus if (r < 0) return 0; - sd_bus_track_remove_name(track, name); + bus_track_remove_name_fully(track, name); return 0; } _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { - _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; - _cleanup_free_ char *n = NULL; + _cleanup_(track_item_freep) struct track_item *n = NULL; + struct track_item *i; const char *match; int r; assert_return(track, -EINVAL); assert_return(service_name_is_valid(name), -EINVAL); + i = hashmap_get(track->names, name); + if (i) { + if (track->recursive) { + unsigned k = track->n_ref + 1; + + if (k < track->n_ref) /* Check for overflow */ + return -EOVERFLOW; + + track->n_ref = k; + } + + bus_track_remove_from_queue(track); + return 0; + } + r = hashmap_ensure_allocated(&track->names, &string_hash_ops); if (r < 0) return r; - n = strdup(name); + n = new0(struct track_item, 1); if (!n) return -ENOMEM; + n->name = strdup(name); + if (!n->name) + return -ENOMEM; /* First, subscribe to this name */ - match = MATCH_FOR_NAME(n); - r = sd_bus_add_match(track->bus, &slot, match, on_name_owner_changed, track); + match = MATCH_FOR_NAME(name); + r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track); if (r < 0) return r; - r = hashmap_put(track->names, n, slot); - if (r == -EEXIST) - return 0; + r = hashmap_put(track->names, n->name, n); if (r < 0) return r; - /* Second, check if it is currently existing, or maybe - * doesn't, or maybe disappeared already. */ - r = sd_bus_get_name_creds(track->bus, n, 0, NULL); + /* Second, check if it is currently existing, or maybe doesn't, or maybe disappeared already. */ + r = sd_bus_get_name_creds(track->bus, name, 0, NULL); if (r < 0) { - hashmap_remove(track->names, n); + hashmap_remove(track->names, name); return r; } + n->n_ref = 1; n = NULL; - slot = NULL; bus_track_remove_from_queue(track); track->modified = true; @@ -207,37 +262,48 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { } _public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) { - _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; - _cleanup_free_ char *n = NULL; + struct track_item *i; assert_return(name, -EINVAL); - if (!track) + if (!track) /* Treat a NULL track object as an empty track object */ return 0; - slot = hashmap_remove2(track->names, (char*) name, (void**) &n); - if (!slot) - return 0; + if (!track->recursive) + return bus_track_remove_name_fully(track, name); - if (hashmap_isempty(track->names)) - bus_track_add_to_queue(track); + i = hashmap_get(track->names, name); + if (!i) + return -EUNATCH; + if (i->n_ref <= 0) + return -EUNATCH; - track->modified = true; + i->n_ref--; + + if (i->n_ref <= 0) + return bus_track_remove_name_fully(track, name); return 1; } _public_ unsigned sd_bus_track_count(sd_bus_track *track) { - if (!track) + + if (!track) /* Let's consider a NULL object equivalent to an empty object */ return 0; + /* This signature really should have returned an int, so that we can propagate errors. But well, ... Also, note + * that this returns the number of names being watched, and multiple references to the same name are not + * counted. */ + return hashmap_size(track->names); } _public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) { - assert_return(track, NULL); assert_return(name, NULL); + if (!track) /* Let's consider a NULL object equivalent to an empty object */ + return NULL; + return hashmap_get(track->names, (void*) name) ? name : NULL; } @@ -273,6 +339,9 @@ _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) { assert_return(track, -EINVAL); assert_return(m, -EINVAL); + if (sd_bus_message_get_bus(m) != track->bus) + return -EINVAL; + sender = sd_bus_message_get_sender(m); if (!sender) return -EINVAL; @@ -283,9 +352,14 @@ _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) { _public_ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m) { const char *sender; - assert_return(track, -EINVAL); assert_return(m, -EINVAL); + if (!track) /* Treat a NULL track object as an empty track object */ + return 0; + + if (sd_bus_message_get_bus(m) != track->bus) + return -EINVAL; + sender = sd_bus_message_get_sender(m); if (!sender) return -EINVAL; @@ -335,3 +409,55 @@ _public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) { return ret; } + +_public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) { + assert_return(track, -EINVAL); + + if (track->recursive == !!b) + return 0; + + if (!hashmap_isempty(track->names)) + return -EBUSY; + + track->recursive = b; + return 0; +} + +_public_ int sd_bus_track_get_recursive(sd_bus_track *track) { + assert_return(track, -EINVAL); + + return track->recursive; +} + +_public_ int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m) { + const char *sender; + + assert_return(m, -EINVAL); + + if (!track) /* Let's consider a NULL object equivalent to an empty object */ + return 0; + + if (sd_bus_message_get_bus(m) != track->bus) + return -EINVAL; + + sender = sd_bus_message_get_sender(m); + if (!sender) + return -EINVAL; + + return sd_bus_track_count_name(track, sender); +} + +_public_ int sd_bus_track_count_name(sd_bus_track *track, const char *name) { + struct track_item *i; + + assert_return(service_name_is_valid(name), -EINVAL); + + if (!track) /* Let's consider a NULL object equivalent to an empty object */ + return 0; + + i = hashmap_get(track->names, name); + if (!i) + return 0; + + return i->n_ref; +} diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 295989cd69..0305c56a8c 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -438,8 +438,14 @@ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m); int sd_bus_track_add_name(sd_bus_track *track, const char *name); int sd_bus_track_remove_name(sd_bus_track *track, const char *name); +int sd_bus_track_set_recursive(sd_bus_track *track, int b); +int sd_bus_track_get_recursive(sd_bus_track *track); + unsigned sd_bus_track_count(sd_bus_track *track); -const char* sd_bus_track_contains(sd_bus_track *track, const char *names); +int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m); +int sd_bus_track_count_name(sd_bus_track *track, const char *name); + +const char* sd_bus_track_contains(sd_bus_track *track, const char *name); const char* sd_bus_track_first(sd_bus_track *track); const char* sd_bus_track_next(sd_bus_track *track); -- cgit v1.2.3-54-g00ecf From ecddb2b586d1b69e5538fb85262d2b9e6d253ac0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Aug 2016 14:59:59 +0200 Subject: man: document sd_bus_track objects And while ware at it, also drop some references to kdbus, and stop claiming sd-bus wasn't stable yet. Also order man page references in the main sd-bus man page alphabetically. --- Makefile-man.am | 89 ++++++++++++++ man/sd-bus.xml | 51 ++++---- man/sd_bus_track_add_name.xml | 261 +++++++++++++++++++++++++++++++++++++++++ man/sd_bus_track_new.xml | 263 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 634 insertions(+), 30 deletions(-) create mode 100644 man/sd_bus_track_add_name.xml create mode 100644 man/sd_bus_track_new.xml diff --git a/Makefile-man.am b/Makefile-man.am index bf8de1e58f..ef5077cc5a 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -52,6 +52,8 @@ MANPAGES += \ man/sd_bus_path_encode.3 \ man/sd_bus_process.3 \ man/sd_bus_request_name.3 \ + man/sd_bus_track_add_name.3 \ + man/sd_bus_track_new.3 \ man/sd_event_add_child.3 \ man/sd_event_add_defer.3 \ man/sd_event_add_io.3 \ @@ -332,6 +334,23 @@ MANPAGES_ALIAS += \ man/sd_bus_path_encode_many.3 \ man/sd_bus_ref.3 \ man/sd_bus_release_name.3 \ + man/sd_bus_track_add_sender.3 \ + man/sd_bus_track_contains.3 \ + man/sd_bus_track_count.3 \ + man/sd_bus_track_count_name.3 \ + man/sd_bus_track_count_sender.3 \ + man/sd_bus_track_first.3 \ + man/sd_bus_track_get_bus.3 \ + man/sd_bus_track_get_recursive.3 \ + man/sd_bus_track_get_userdata.3 \ + man/sd_bus_track_next.3 \ + man/sd_bus_track_ref.3 \ + man/sd_bus_track_remove_name.3 \ + man/sd_bus_track_remove_sender.3 \ + man/sd_bus_track_set_recursive.3 \ + man/sd_bus_track_set_userdata.3 \ + man/sd_bus_track_unref.3 \ + man/sd_bus_track_unrefp.3 \ man/sd_bus_unref.3 \ man/sd_bus_unrefp.3 \ man/sd_event.3 \ @@ -665,6 +684,23 @@ man/sd_bus_path_decode_many.3: man/sd_bus_path_encode.3 man/sd_bus_path_encode_many.3: man/sd_bus_path_encode.3 man/sd_bus_ref.3: man/sd_bus_new.3 man/sd_bus_release_name.3: man/sd_bus_request_name.3 +man/sd_bus_track_add_sender.3: man/sd_bus_track_add_name.3 +man/sd_bus_track_contains.3: man/sd_bus_track_add_name.3 +man/sd_bus_track_count.3: man/sd_bus_track_add_name.3 +man/sd_bus_track_count_name.3: man/sd_bus_track_add_name.3 +man/sd_bus_track_count_sender.3: man/sd_bus_track_add_name.3 +man/sd_bus_track_first.3: man/sd_bus_track_add_name.3 +man/sd_bus_track_get_bus.3: man/sd_bus_track_new.3 +man/sd_bus_track_get_recursive.3: man/sd_bus_track_new.3 +man/sd_bus_track_get_userdata.3: man/sd_bus_track_new.3 +man/sd_bus_track_next.3: man/sd_bus_track_add_name.3 +man/sd_bus_track_ref.3: man/sd_bus_track_new.3 +man/sd_bus_track_remove_name.3: man/sd_bus_track_add_name.3 +man/sd_bus_track_remove_sender.3: man/sd_bus_track_add_name.3 +man/sd_bus_track_set_recursive.3: man/sd_bus_track_new.3 +man/sd_bus_track_set_userdata.3: man/sd_bus_track_new.3 +man/sd_bus_track_unref.3: man/sd_bus_track_new.3 +man/sd_bus_track_unrefp.3: man/sd_bus_track_new.3 man/sd_bus_unref.3: man/sd_bus_new.3 man/sd_bus_unrefp.3: man/sd_bus_new.3 man/sd_event.3: man/sd_event_new.3 @@ -1300,6 +1336,57 @@ man/sd_bus_ref.html: man/sd_bus_new.html man/sd_bus_release_name.html: man/sd_bus_request_name.html $(html-alias) +man/sd_bus_track_add_sender.html: man/sd_bus_track_add_name.html + $(html-alias) + +man/sd_bus_track_contains.html: man/sd_bus_track_add_name.html + $(html-alias) + +man/sd_bus_track_count.html: man/sd_bus_track_add_name.html + $(html-alias) + +man/sd_bus_track_count_name.html: man/sd_bus_track_add_name.html + $(html-alias) + +man/sd_bus_track_count_sender.html: man/sd_bus_track_add_name.html + $(html-alias) + +man/sd_bus_track_first.html: man/sd_bus_track_add_name.html + $(html-alias) + +man/sd_bus_track_get_bus.html: man/sd_bus_track_new.html + $(html-alias) + +man/sd_bus_track_get_recursive.html: man/sd_bus_track_new.html + $(html-alias) + +man/sd_bus_track_get_userdata.html: man/sd_bus_track_new.html + $(html-alias) + +man/sd_bus_track_next.html: man/sd_bus_track_add_name.html + $(html-alias) + +man/sd_bus_track_ref.html: man/sd_bus_track_new.html + $(html-alias) + +man/sd_bus_track_remove_name.html: man/sd_bus_track_add_name.html + $(html-alias) + +man/sd_bus_track_remove_sender.html: man/sd_bus_track_add_name.html + $(html-alias) + +man/sd_bus_track_set_recursive.html: man/sd_bus_track_new.html + $(html-alias) + +man/sd_bus_track_set_userdata.html: man/sd_bus_track_new.html + $(html-alias) + +man/sd_bus_track_unref.html: man/sd_bus_track_new.html + $(html-alias) + +man/sd_bus_track_unrefp.html: man/sd_bus_track_new.html + $(html-alias) + man/sd_bus_unref.html: man/sd_bus_new.html $(html-alias) @@ -2559,6 +2646,8 @@ EXTRA_DIST += \ man/sd_bus_path_encode.xml \ man/sd_bus_process.xml \ man/sd_bus_request_name.xml \ + man/sd_bus_track_add_name.xml \ + man/sd_bus_track_new.xml \ man/sd_event_add_child.xml \ man/sd_event_add_defer.xml \ man/sd_event_add_io.xml \ diff --git a/man/sd-bus.xml b/man/sd-bus.xml index 336dd33ea0..66b1c96c15 100644 --- a/man/sd-bus.xml +++ b/man/sd-bus.xml @@ -44,7 +44,7 @@ sd-bus - A lightweight D-Bus and kdbus client library + A lightweight D-Bus IPC client library @@ -61,49 +61,40 @@ Description - sd-bus.h provides an implementation - of a D-Bus client. It can interoperate both with the traditional - dbus-daemon1, - and with kdbus. See + sd-bus.h provides an implementation of a D-Bus IPC client. See - for more information about the big picture. + for more information about D-Bus IPC. - - Interfaces described here have not been declared stable yet, - and are not accessible from libsystemd.so. - This documentation is provided in hope it might be useful for - developers, without any guarantees of availability or stability. - - - See + sd-bus-errors3, + sd_bus_creds_get_pid3, + sd_bus_creds_new_from_pid3, sd_bus_default3, - sd_bus_new3, - sd_bus_request_name3, - sd_bus_start3, + sd_bus_error3, + sd_bus_error_add_map3, + sd_bus_get_name_creds3, + sd_bus_get_owner_creds3, sd_bus_message_append3, - sd_bus_message_append_basic3, sd_bus_message_append_array3, + sd_bus_message_append_basic3, sd_bus_message_append_string_memfd3, sd_bus_message_append_strv3, sd_bus_message_can_send3, sd_bus_message_get_cookie3, sd_bus_message_get_monotonic_usec3, + sd_bus_negotiate_fds3, + sd_bus_new3, + sd_bus_path_encode3, + sd_bus_request_name3, sd_bus_send3, sd_bus_set_address3, + sd_bus_set_allow_interactive_authorization3 sd_bus_set_description3, sd_bus_set_prepare3, - sd_bus_creds_get_pid3, - sd_bus_creds_new_from_pid3, - sd_bus_get_name_creds3, - sd_bus_get_owner_creds3, - sd_bus_negotiate_fds3, - sd_bus_path_encode3, - sd-bus-errors3, - sd_bus_error3, - sd_bus_error_add_map3, - sd_bus_set_allow_interactive_authorization3 + sd_bus_start3, + sd_bus_track_add_name3, + sd_bus_track_new3, for more information about the functions available. @@ -114,9 +105,9 @@ systemd1, sd-event3, + busctl1, dbus-daemon1, - dbus-send1, - gdbus + dbus-send1 diff --git a/man/sd_bus_track_add_name.xml b/man/sd_bus_track_add_name.xml new file mode 100644 index 0000000000..6a5e344cb1 --- /dev/null +++ b/man/sd_bus_track_add_name.xml @@ -0,0 +1,261 @@ + + + + + + + + + sd_bus_track_add_name + systemd + + + + Developer + Lennart + Poettering + lennart@poettering.net + + + + + + sd_bus_track_add_name + 3 + + + + sd_bus_track_add_name + sd_bus_track_add_sender + sd_bus_track_remove_name + sd_bus_track_remove_sender + sd_bus_track_count + sd_bus_track_count_sender + sd_bus_track_count_name + sd_bus_track_contains + sd_bus_track_first + sd_bus_track_next + + Add, remove and retrieve bus peers tracked in a bus peer tracking object + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_track_add_name + sd_bus_track* t + const char* name + + + + int sd_bus_track_add_sender + sd_bus_track* t + sd_bus_message* message + + + + int sd_bus_track_remove_name + sd_bus_track* t + const char* name + + + + int sd_bus_track_remove_sender + sd_bus_track* t + sd_bus_message* message + + + + unsigned sd_bus_track_count + sd_bus_track* t + + + + int sd_bus_track_count_name + sd_bus_track* t + const char* name + + + + int sd_bus_track_count_sender + sd_bus_track* t + sd_bus_message* message + + + + int sd_bus_track_contains + sd_bus_track* t + const char* name + + + + const char* sd_bus_track_first + sd_bus_track* t + + + + const char* sd_bus_track_next + sd_bus_track* t + + + + + + + Description + + sd_bus_track_add_name() adds a peer to track to a bus peer tracking object. The first + argument should refer to a bus peer tracking object created with + sd_bus_track_new3, the second + name should refer to a D-Bus peer name to track, either in unique or well-known service format. If the name is not + tracked yet it will be added to the list of names to track. If it already is being tracked and non-recursive mode + is enabled, no operation is executed by this call. If recursive mode is enabled a per-name counter is increased by + one each time this call is invoked, and sd_bus_track_remove_name() has to be called as many + times as sd_bus_track_add_name() was invoked before in order to stop tracking of the name. Use + sd_bus_track_set_recursive3 to + switch from the default non-recursive mode to recursive mode, or back. Note that the specified name is tracked as + it is, well-known names are not resolved to unique names by this call. Note that multiple bus peer tracking objects + may track the same name. + + sd_bus_track_remove_name() undoes the effect of + sd_bus_track_add_name() and removes a bus peer name from the list of peers to watch. Depending + on whether non-recursive or recursive mode is enabled for the bus peer tracking object this call will either remove + the name fully from the tracking object, or will simply decrement the per-name counter by one, removing the name + only when the counter reaches zero (see above). Note that a bus peer disconnecting from the bus will implicitly + remove its names fully from the bus peer tracking object, regardless of the current per-name counter. + + sd_bus_track_add_sender() and sd_bus_track_remove_sender() are + similar to sd_bus_track_add_name() and sd_bus_track_remove_name() but + take a bus message as argument. The sender of this bus message is determined and added to/removed from the bus peer + tracking object. As messages always originate from unique names, and never from well-known names this means that + this call will effectively only add unique names to the bus peer tracking object. + + sd_bus_track_count() returns the number of names currently being tracked by the + specified bus peer tracking object. Note that this function always returns the actual number of names tracked, and + hence if sd_bus_track_add_name() has been invoked multiple times for the same name it is only + counted as one, regardless if recursive mode is used or not. + + sd_bus_track_count_name() returns the current per-name counter for the specified + name. If non-recursive mode is used this returns either 1 or 0, depending on whether the specified name has been + added to the tracking object before, or not. If recursive mode has been enabled, values larger than 1 may be + returned too, in case sd_bus_track_add_name() has been called multiple times for the same + name. + + sd_bus_track_count_sender() is similar to + sd_bus_track_count_name(), but takes a bus message object and returns the per-name counter + matching the sender of the message. + + sd_bus_track_contains() may be used to determine whether the specified name has been + added at least once to the specified bus peer tracking object. + + sd_bus_track_first() and sd_bus_track_next() may be used to + enumerate all names currently being tracked by the passed bus peer tracking + object. sd_bus_track_first() returns the first entry in the object, and resets an internally + maintained read index. Each subsequent invocation of sd_bus_track_next() returns the next name + contained in the bus object. If the end is reached NULL is returned. If no names have been + added to the object yet sd_bus_track_first() will return NULL + immediately. The order in which names are returned is undefined; in particular which name is considered the first + returned is not defined. If recursive mode is enabled and the same name has been added multiple times to the bus + peer tracking object it is only returned once by this enumeration. If new names are added to or existing names + removed from the bus peer tracking object while it is being enumerated the enumeration ends on the next invocation + of sd_bus_track_next() as NULL is returned. + + + + Return Value + + On success, sd_bus_track_add_name() and sd_bus_track_add_sender() + return 0 if the specified name has already been added to the bus peer tracking object before and positive if it + hasn't. On failure, they return a negative errno-style error code. + + sd_bus_track_remove_name() and sd_bus_track_remove_sender() return + positive if the specified name was previously tracked by the bus peer tracking object and has now been removed. In + non-recursive mode, 0 is returned if the specified name was not being tracked yet. In recursive mode + -EUNATCH is returned in this case. On failure, they return a negative errno-style error + code. + + sd_bus_track_count() returns the number of names currently being tracked, or 0 on + failure. + + sd_bus_track_count_name() and sd_bus_track_count_sender() return + the current per-name counter for the specified name or the sender of the specified message. Zero is returned for + names that are not being tracked yet, a positive value for names added at least once. Larger values than 1 are only + returned in recursive mode. On failure, a negative errno-style error code is returned. + + sd_bus_track_contains() returns the passed name if it exists in the bus peer tracking + object. On failure, and if the name has not been added yet NULL is returned. + + sd_bus_track_first() and sd_bus_track_next() return the first/next + name contained in the bus peer tracking object, and NULL if the end of the enumeration is + reached and on error. + + + + Errors + + Returned errors may indicate the following problems: + + + + + -EUNATCH + + sd_bus_track_remove_name() or + sd_bus_track_remove_sender() have been invoked for a name not previously added to the bus + peer object. + + + + -EINVAL + + Specified parameter is invalid. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + Notes + + sd_bus_track_add_name() and the other calls described here are available as a shared library, + which can be compiled and linked to with the libsystemd pkg-config1 file. + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_track_new3 + + + + diff --git a/man/sd_bus_track_new.xml b/man/sd_bus_track_new.xml new file mode 100644 index 0000000000..60e2e77f75 --- /dev/null +++ b/man/sd_bus_track_new.xml @@ -0,0 +1,263 @@ + + + + + + + + + sd_bus_track_new + systemd + + + + Developer + Lennart + Poettering + lennart@poettering.net + + + + + + sd_bus_track_new + 3 + + + + sd_bus_track_new + sd_bus_track_ref + sd_bus_track_unref + sd_bus_track_unrefp + sd_bus_track_set_recursive + sd_bus_track_get_recursive + sd_bus_track_get_bus + sd_bus_track_get_userdata + sd_bus_track_set_userdata + + Track bus peers + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_track_new + sd_bus* bus + sd_bus_track** ret + sd_bus_track_handler_t handler + void* userdata + + + + sd_bus_track *sd_bus_track_ref + sd_bus_track *t + + + + sd_bus_track *sd_bus_track_unref + sd_bus_track *t + + + + void sd_bus_track_unrefp + sd_bus_track **t + + + + int sd_bus_track_get_recursive + sd_bus_track *t + + + + int sd_bus_track_set_recursive + sd_bus_track *t + int b + + + + sd_bus* sd_bus_track_get_bus + sd_bus_track *t + + + + void* sd_bus_track_get_userdata + sd_bus_track *t + + + + void* sd_bus_track_set_userdata + sd_bus_track *t + void *userdata + + + + + + + Description + + sd_bus_track_new() creates a new bus peer tracking object. The object is allocated for + the specified bus, and returned in the *ret parameter. After use, the object should be freed + again by dropping the acquired reference with sd_bus_track_unref() (see below). A bus peer + tracking object may be used to keep track of peers on a specific IPC bus, for cases where peers are making use of + one or more local objects, in order to control the lifecycle of the local objects and ensure they stay around as + long as the peers needing them are around, and unreferenced (and possibly destroyed) as soon as all relevant peers + have vanished. Each bus peer tracking object may be used to track zero, one or more peers add a time. References to + specific bus peers are added via + sd_bus_track_add_name3 or + sd_bus_track_add_sender(). They may be dropped again via + sd_bus_track_remove_name() and + sd_bus_track_remove_sender(). Alternatively, references on peers are removed automatically + when they disconnect from the bus. If non-NULL the handler may specify a function that is + invoked whenever the last reference is dropped, regardless whether the reference is dropped explicitly via + sd_bus_track_remove_name() or implicitly because the peer disconnected from the bus. The final + argument userdata may be used to attach a generic user data pointer to the object. This + pointer is passed to the handler callback when it is invoked. + + sd_bus_track_ref() creates a new reference to a bus peer tracking object. This object + will not be destroyed until sd_bus_track_unref() has been called as many times plus once + more. Once the reference count has dropped to zero, the specified object cannot be used anymore, further calls to + sd_bus_track_ref() or sd_bus_track_unref() on the same object are + illegal. + + sd_bus_track_unref() destroys a reference to a bus peer tracking object. + + sd_bus_track_unrefp() is similar to sd_bus_track_unref() but takes + a pointer to a pointer to an sd_bus_track object. This call is useful in conjunction with GCC's and + LLVM's Clean-up Variable + Attribute. Note that this function is defined as inline function. + + sd_bus_track_ref(), sd_bus_track_unref() and + sd_bus_track_unrefp() execute no operation if the passed in bus peer tracking object is + NULL. + + Bus peer tracking objects may exist in two modes: by default they operate in non-recursive mode, but may + optionally be switched into recursive mode. If operating in the default non-recursive mode a peer is either tracked + or not tracked. In this mode invoking sd_bus_track_add_name() multiple times in a row for the + same peer is fully equivalent to calling it just once, as the call adds the peer to the set of tracked peers if + necessary, and executes no operation if the peer is already being tracked. A single invocation of + sd_bus_track_remove_name() removes the reference on the peer again, regardless how many times + sd_bus_track_add_name() was called before. If operating in recursive mode, the number of times + sd_bus_track_add_name() is invoked for the same peer name is counted and + sd_bus_track_remove_name() must be called the same number of times before the peer is not + tracked anymore, with the exception when the tracked peer vanishes from the bus, in which case the count is + irrelevant and the tracking of the specific peer is immediately + removed. sd_bus_track_get_recursive() may be used to determine whether the bus peer tracking + object is operating in recursive mode. sd_bus_track_set_recursive() may be used to enable or + disable recursive mode. By default a bus peer tracking object operates in non-recursive mode, and + sd_bus_track_get_recursive() for a newly allocated object hence returns a value equal to + zero. Use sd_bus_track_set_recursive() to enable recursive mode, right after allocation. It + takes a boolean argument to enable or disable recursive mode. Note that tracking objects for which + sd_bus_track_add_name() was already invoked at least once (and which hence track already one + or more peers) may not be switched from recursive to non-recursive mode anymore. + + sd_bus_track_get_bus() returns the bus object the bus peer tracking object belongs + to. It returns the bus object initially passed to sd_bus_track_new() when the object was + allocated. + + sd_bus_track_get_userdata() returns the generic user data pointer set on the bus peer + tracking object at the time of creation using sd_bus_track_new() or at a later time, using + sd_bus_track_set_userdata(). + + + + Return Value + + On success, sd_bus_track_new() and sd_bus_track_set_recursive() + return 0 or a positive integer. On failure, they return a negative errno-style error code. + + sd_bus_track_ref() always returns the argument. + + sd_bus_track_unref() always returns NULL. + + sd_bus_track_get_recursive() returns 0 if non-recursive mode is selected (default), and + greater than 0 if recursive mode is selected. On failure a negative errno-style error code is returned. + + sd_bus_track_get_bus() returns the bus object associated to the bus peer tracking + object. + + sd_bus_track_get_userdata() returns the generic user data pointer associated with the + bus peer tracking object. sd_bus_track_set_userdata() returns the previous user data pointer + set. + + + + + Reference ownership + + The sd_bus_track_new() function creates a new object and the caller owns the sole + reference. When not needed anymore, this reference should be destroyed with + sd_bus_track_unref(). + + + + + Errors + + Returned errors may indicate the following problems: + + + + + -EBUSY + + Bus peers have already been added to the bus peer tracking object and + sd_bus_track_set_recursive() was called to change tracking mode. + + + + -EINVAL + + Specified parameter is invalid + (NULL in case of output + parameters). + + + + -ENOMEM + + Memory allocation failed. + + + + + + + Notes + + sd_bus_track_new() and the other calls described here are available as a shared library, + which can be compiled and linked to with the libsystemd pkg-config1 file. + + + + See Also + + + systemd1, + sd-bus3 + sd_bus_track_add_name3 + + + + -- cgit v1.2.3-54-g00ecf From 05a98afd3e0513de50c5949b7fa50ff0989d68bc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Aug 2016 18:12:01 +0200 Subject: core: add Ref()/Unref() bus calls for units This adds two (privileged) bus calls Ref() and Unref() to the Unit interface. The two calls may be used by clients to pin a unit into memory, so that various runtime properties aren't flushed out by the automatic GC. This is necessary to permit clients to race-freely acquire runtime results (such as process exit status/code or accumulated CPU time) on successful service termination. Ref() and Unref() are fully recursive, hence act like the usual reference counting concept in C. Taking a reference is a privileged operation, as this allows pinning units into memory which consumes resources. Transient units may also gain a reference at the time of creation, via the new AddRef property (that is only defined for transient units at the time of creation). --- man/systemctl.xml | 12 +-- src/core/dbus-manager.c | 57 +++++++++++ src/core/dbus-unit.c | 155 +++++++++++++++++++++++++++++- src/core/dbus-unit.h | 8 +- src/core/dbus.c | 71 +++++++------- src/core/dbus.h | 5 +- src/core/job.c | 17 ++-- src/core/job.h | 4 +- src/core/manager.c | 27 +++--- src/core/org.freedesktop.systemd1.conf | 8 ++ src/core/unit.c | 52 +++++++--- src/core/unit.h | 7 ++ src/libsystemd/sd-bus/bus-common-errors.c | 1 + src/libsystemd/sd-bus/bus-common-errors.h | 1 + 14 files changed, 341 insertions(+), 84 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index fde4f4f3bb..7e0ac9613a 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -642,13 +642,13 @@ list-units PATTERN... - List units that systemd has loaded. This includes units that - are either referenced directly or through a dependency, or units that were active in the - past and have failed. By default only units which are active, have pending jobs, or have + List units that systemd has loaded. This includes units that are either referenced + directly or through a dependency, units that are pinned by applications programmatically, or units that + were active in the past and have failed. By default only units which are active, have pending jobs, or have failed are shown; this can be changed with option . If one or more - PATTERNs are specified, only units matching one of them are - shown. The units that are shown are additionally filtered by - and if those options are specified. + PATTERNs are specified, only units matching one of them are shown. The units + that are shown are additionally filtered by and if those + options are specified. This is the default command. diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index ef05a75a8b..ea7ced2fd0 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -643,6 +643,54 @@ static int method_set_unit_properties(sd_bus_message *message, void *userdata, s return bus_unit_method_set_properties(message, u, error); } +static int method_ref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_load_unit(m, name, NULL, error, &u); + if (r < 0) + return r; + + r = bus_unit_check_load_state(u, error); + if (r < 0) + return r; + + return bus_unit_method_ref(message, u, error); +} + +static int method_unref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_load_unit(m, name, NULL, error, &u); + if (r < 0) + return r; + + r = bus_unit_check_load_state(u, error); + if (r < 0) + return r; + + return bus_unit_method_unref(message, u, error); +} + static int reply_unit_info(sd_bus_message *reply, Unit *u) { _cleanup_free_ char *unit_path = NULL, *job_path = NULL; Unit *following; @@ -781,6 +829,13 @@ static int transient_unit_from_message( if (r < 0) return r; + /* If the client asked for it, automatically add a reference to this unit. */ + if (u->bus_track_add) { + r = bus_unit_track_add_sender(u, message); + if (r < 0) + return log_error_errno(r, "Failed to watch sender: %m"); + } + /* Now load the missing bits of the unit we just created */ unit_add_to_load_queue(u); manager_dispatch_load_queue(m); @@ -2211,6 +2266,8 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RefUnit", "s", NULL, method_ref_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnrefUnit", "s", NULL, method_unref_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetUnitProcesses", "s", "a(sus)", method_get_unit_processes, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 89e56a2e51..1b86bdde43 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -418,6 +418,7 @@ static int bus_verify_manage_units_async_full( const char *verb, int capability, const char *polkit_message, + bool interactive, sd_bus_message *call, sd_bus_error *error) { @@ -433,7 +434,15 @@ static int bus_verify_manage_units_async_full( details[7] = GETTEXT_PACKAGE; } - return bus_verify_polkit_async(call, capability, "org.freedesktop.systemd1.manage-units", details, false, UID_INVALID, &u->manager->polkit_registry, error); + return bus_verify_polkit_async( + call, + capability, + "org.freedesktop.systemd1.manage-units", + details, + interactive, + UID_INVALID, + &u->manager->polkit_registry, + error); } int bus_unit_method_start_generic( @@ -486,6 +495,7 @@ int bus_unit_method_start_generic( verb, CAP_SYS_ADMIN, job_type < _JOB_TYPE_MAX ? polkit_message_for_job[job_type] : NULL, + true, message, error); if (r < 0) @@ -558,6 +568,7 @@ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error * "kill", CAP_KILL, N_("Authentication is required to kill '$(unit)'."), + true, message, error); if (r < 0) @@ -588,6 +599,7 @@ int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus "reset-failed", CAP_SYS_ADMIN, N_("Authentication is required to reset the \"failed\" state of '$(unit)'."), + true, message, error); if (r < 0) @@ -620,6 +632,7 @@ int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_b "set-property", CAP_SYS_ADMIN, N_("Authentication is required to set properties on '$(unit)'."), + true, message, error); if (r < 0) @@ -634,6 +647,53 @@ int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_b return sd_bus_reply_method_return(message, NULL); } +int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = mac_selinux_unit_access_check(u, message, "start", error); + if (r < 0) + return r; + + r = bus_verify_manage_units_async_full( + u, + "ref", + CAP_SYS_ADMIN, + NULL, + false, + message, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = bus_unit_track_add_sender(u, message); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = bus_unit_track_remove_sender(u, message); + if (r == -EUNATCH) + return sd_bus_error_setf(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet."); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_VTABLE_START(0), @@ -715,6 +775,8 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Ref", NULL, NULL, bus_unit_method_ref, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Unref", NULL, NULL, bus_unit_method_unref, SD_BUS_VTABLE_UNPRIVILEGED), /* Obsolete properties or obsolete alias names */ SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN), @@ -1318,6 +1380,29 @@ static int bus_unit_set_transient_property( return r; return 1; + + } else if (streq(name, "AddRef")) { + + int b; + + /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method + * on the Unit interface, and it's probably not a good idea to expose a property and a method on the + * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for + * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference + * dependency type, hence let's not confuse things with that. + * + * Note that we don't acually add the reference to the bus track. We do that only after the setup of + * the transient unit is complete, so that setting this property multiple times in the same transient + * unit creation call doesn't count as individual references. */ + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) + u->bus_track_add = b; + + return 1; } return 0; @@ -1422,3 +1507,71 @@ int bus_unit_check_load_state(Unit *u, sd_bus_error *error) { return sd_bus_error_set_errnof(error, u->load_error, "Unit %s is not loaded properly: %m.", u->id); } + +static int bus_track_handler(sd_bus_track *t, void *userdata) { + Unit *u = userdata; + + assert(t); + assert(u); + + u->bus_track = sd_bus_track_unref(u->bus_track); /* make sure we aren't called again */ + + unit_add_to_gc_queue(u); + return 0; +} + +static int allocate_bus_track(Unit *u) { + int r; + + assert(u); + + if (u->bus_track) + return 0; + + r = sd_bus_track_new(u->manager->api_bus, &u->bus_track, bus_track_handler, u); + if (r < 0) + return r; + + r = sd_bus_track_set_recursive(u->bus_track, true); + if (r < 0) { + u->bus_track = sd_bus_track_unref(u->bus_track); + return r; + } + + return 0; +} + +int bus_unit_track_add_name(Unit *u, const char *name) { + int r; + + assert(u); + + r = allocate_bus_track(u); + if (r < 0) + return r; + + return sd_bus_track_add_name(u->bus_track, name); +} + +int bus_unit_track_add_sender(Unit *u, sd_bus_message *m) { + int r; + + assert(u); + + r = allocate_bus_track(u); + if (r < 0) + return r; + + return sd_bus_track_add_sender(u->bus_track, m); +} + +int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m) { + assert(u); + + /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet, return an + * error */ + if (!u->bus_track) + return -EUNATCH; + + return sd_bus_track_remove_sender(u->bus_track, m); +} diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h index 4db88dbebc..b280de7a1d 100644 --- a/src/core/dbus-unit.h +++ b/src/core/dbus-unit.h @@ -33,9 +33,15 @@ int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error); -int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error); int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error); int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error); int bus_unit_check_load_state(Unit *u, sd_bus_error *error); + +int bus_unit_track_add_name(Unit *u, const char *name); +int bus_unit_track_add_sender(Unit *u, sd_bus_message *m); +int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m); diff --git a/src/core/dbus.c b/src/core/dbus.c index 3422a02d68..1e41a42aa6 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -1168,60 +1168,57 @@ int bus_foreach_bus( return ret; } -void bus_track_serialize(sd_bus_track *t, FILE *f) { +void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) { const char *n; assert(f); + assert(prefix); - for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) - fprintf(f, "subscribed=%s\n", n); -} - -int bus_track_deserialize_item(char ***l, const char *line) { - const char *e; - int r; - - assert(l); - assert(line); - - e = startswith(line, "subscribed="); - if (!e) - return 0; + for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) { + int c, j; - r = strv_extend(l, e); - if (r < 0) - return r; + c = sd_bus_track_count_name(t, n); - return 1; + for (j = 0; j < c; j++) { + fputs(prefix, f); + fputc('=', f); + fputs(n, f); + fputc('\n', f); + } + } } -int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) { +int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) { + char **i; int r = 0; assert(m); assert(t); - assert(l); - - if (!strv_isempty(*l) && m->api_bus) { - char **i; - if (!*t) { - r = sd_bus_track_new(m->api_bus, t, NULL, NULL); - if (r < 0) - return r; - } + if (strv_isempty(l)) + return 0; - r = 0; - STRV_FOREACH(i, *l) { - int k; + if (!m->api_bus) + return 0; - k = sd_bus_track_add_name(*t, *i); - if (k < 0) - r = k; - } + if (!*t) { + r = sd_bus_track_new(m->api_bus, t, NULL, NULL); + if (r < 0) + return r; } - *l = strv_free(*l); + r = sd_bus_track_set_recursive(*t, recursive); + if (r < 0) + return r; + + r = 0; + STRV_FOREACH(i, l) { + int k; + + k = sd_bus_track_add_name(*t, *i); + if (k < 0) + r = k; + } return r; } diff --git a/src/core/dbus.h b/src/core/dbus.h index 6baaffbd75..a092ed9d76 100644 --- a/src/core/dbus.h +++ b/src/core/dbus.h @@ -28,9 +28,8 @@ void bus_done(Manager *m); int bus_fdset_add_all(Manager *m, FDSet *fds); -void bus_track_serialize(sd_bus_track *t, FILE *f); -int bus_track_deserialize_item(char ***l, const char *line); -int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l); +void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix); +int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l); int manager_sync_bus_names(Manager *m, sd_bus *bus); diff --git a/src/core/job.c b/src/core/job.c index 7557874d4d..7faf2ef686 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -997,7 +997,10 @@ char *job_dbus_path(Job *j) { return p; } -int job_serialize(Job *j, FILE *f, FDSet *fds) { +int job_serialize(Job *j, FILE *f) { + assert(j); + assert(f); + fprintf(f, "job-id=%u\n", j->id); fprintf(f, "job-type=%s\n", job_type_to_string(j->type)); fprintf(f, "job-state=%s\n", job_state_to_string(j->state)); @@ -1008,15 +1011,16 @@ int job_serialize(Job *j, FILE *f, FDSet *fds) { if (j->begin_usec > 0) fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec); - bus_track_serialize(j->clients, f); + bus_track_serialize(j->clients, f, "subscribed"); /* End marker */ fputc('\n', f); return 0; } -int job_deserialize(Job *j, FILE *f, FDSet *fds) { +int job_deserialize(Job *j, FILE *f) { assert(j); + assert(f); for (;;) { char line[LINE_MAX], *l, *v; @@ -1106,7 +1110,7 @@ int job_deserialize(Job *j, FILE *f, FDSet *fds) { } else if (streq(l, "subscribed")) { if (strv_extend(&j->deserialized_clients, v) < 0) - return log_oom(); + log_oom(); } } } @@ -1118,9 +1122,8 @@ int job_coldplug(Job *j) { /* After deserialization is complete and the bus connection * set up again, let's start watching our subscribers again */ - r = bus_track_coldplug(j->manager, &j->clients, &j->deserialized_clients); - if (r < 0) - return r; + (void) bus_track_coldplug(j->manager, &j->clients, false, j->deserialized_clients); + j->deserialized_clients = strv_free(j->deserialized_clients); if (j->state == JOB_WAITING) job_add_to_run_queue(j); diff --git a/src/core/job.h b/src/core/job.h index d359e8bb3e..85368f0d30 100644 --- a/src/core/job.h +++ b/src/core/job.h @@ -177,8 +177,8 @@ Job* job_install(Job *j); int job_install_deserialized(Job *j); void job_uninstall(Job *j); void job_dump(Job *j, FILE*f, const char *prefix); -int job_serialize(Job *j, FILE *f, FDSet *fds); -int job_deserialize(Job *j, FILE *f, FDSet *fds); +int job_serialize(Job *j, FILE *f); +int job_deserialize(Job *j, FILE *f); int job_coldplug(Job *j); JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts); diff --git a/src/core/manager.c b/src/core/manager.c index 7576d038a2..b58f68fa7a 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1287,10 +1287,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { if (q < 0 && r == 0) r = q; - /* We might have deserialized the kdbus control fd, but if we - * didn't, then let's create the bus now. */ - manager_connect_bus(m, !!serialization); - bus_track_coldplug(m, &m->subscribed, &m->deserialized_subscribed); + /* We might have deserialized the kdbus control fd, but if we didn't, then let's create the bus now. */ + (void) manager_connect_bus(m, !!serialization); + + (void) bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed); + m->deserialized_subscribed = strv_free(m->deserialized_subscribed); /* Third, fire things up! */ manager_coldplug(m); @@ -2490,7 +2491,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { fprintf(f, "kdbus-fd=%i\n", copy); } - bus_track_serialize(m->subscribed, f); + bus_track_serialize(m->subscribed, f, "subscribed"); r = dynamic_user_serialize(m, f, fds); if (r < 0) @@ -2693,15 +2694,13 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { manager_deserialize_uid_refs_one(m, l + 16); else if (startswith(l, "destroy-ipc-gid=")) manager_deserialize_gid_refs_one(m, l + 16); - else { - int k; - - k = bus_track_deserialize_item(&m->deserialized_subscribed, l); - if (k < 0) - log_debug_errno(k, "Failed to deserialize bus tracker object: %m"); - else if (k == 0) - log_debug("Unknown serialization item '%s'", l); - } + else if (startswith(l, "subscribed=")) { + + if (strv_extend(&m->deserialized_subscribed, l+11) < 0) + log_oom(); + + } else + log_debug("Unknown serialization item '%s'", l); } for (;;) { diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index 14f6aec029..647e5f736c 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -182,6 +182,14 @@ send_interface="org.freedesktop.systemd1.Manager" send_member="Reexecute"/> + + + + diff --git a/src/core/unit.c b/src/core/unit.c index c58c501bc3..6d92eb0c30 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -329,6 +329,9 @@ bool unit_check_gc(Unit *u) { if (u->refs) return true; + if (sd_bus_track_count(u->bus_track) > 0) + return true; + if (UNIT_VTABLE(u)->check_gc) if (UNIT_VTABLE(u)->check_gc(u)) return true; @@ -509,6 +512,9 @@ void unit_free(Unit *u) { sd_bus_slot_unref(u->match_bus_slot); + sd_bus_track_unref(u->bus_track); + u->deserialized_refs = strv_free(u->deserialized_refs); + unit_free_requires_mounts_for(u); SET_FOREACH(t, u->names, i) @@ -897,6 +903,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { Unit *following; _cleanup_set_free_ Set *following_set = NULL; int r; + const char *n; assert(u); assert(u->type >= 0); @@ -1038,6 +1045,8 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { else if (u->load_state == UNIT_ERROR) fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error)); + for (n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track)) + fprintf(f, "%s\tBus Ref: %s\n", prefix, n); if (u->job) job_dump(u->job, f, prefix2); @@ -2622,15 +2631,17 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { if (gid_is_valid(u->ref_gid)) unit_serialize_item_format(u, f, "ref-gid", GID_FMT, u->ref_gid); + bus_track_serialize(u->bus_track, f, "ref"); + if (serialize_jobs) { if (u->job) { fprintf(f, "job\n"); - job_serialize(u->job, f, fds); + job_serialize(u->job, f); } if (u->nop_job) { fprintf(f, "job\n"); - job_serialize(u->nop_job, f, fds); + job_serialize(u->nop_job, f); } } @@ -2760,7 +2771,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { if (!j) return log_oom(); - r = job_deserialize(j, f, fds); + r = job_deserialize(j, f); if (r < 0) { job_free(j); return r; @@ -2880,6 +2891,12 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { else unit_ref_uid_gid(u, UID_INVALID, gid); + } else if (streq(l, "ref")) { + + r = strv_extend(&u->deserialized_refs, v); + if (r < 0) + log_oom(); + continue; } @@ -2955,7 +2972,8 @@ int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep } int unit_coldplug(Unit *u) { - int r = 0, q = 0; + int r = 0, q; + char **i; assert(u); @@ -2966,18 +2984,26 @@ int unit_coldplug(Unit *u) { u->coldplugged = true; - if (UNIT_VTABLE(u)->coldplug) - r = UNIT_VTABLE(u)->coldplug(u); + STRV_FOREACH(i, u->deserialized_refs) { + q = bus_unit_track_add_name(u, *i); + if (q < 0 && r >= 0) + r = q; + } + u->deserialized_refs = strv_free(u->deserialized_refs); - if (u->job) - q = job_coldplug(u->job); + if (UNIT_VTABLE(u)->coldplug) { + q = UNIT_VTABLE(u)->coldplug(u); + if (q < 0 && r >= 0) + r = q; + } - if (r < 0) - return r; - if (q < 0) - return q; + if (u->job) { + q = job_coldplug(u->job); + if (q < 0 && r >= 0) + r = q; + } - return 0; + return r; } static bool fragment_mtime_newer(const char *path, usec_t mtime) { diff --git a/src/core/unit.h b/src/core/unit.h index 53875653d7..e5a2a77b7b 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -108,6 +108,10 @@ struct Unit { /* The slot used for watching NameOwnerChanged signals */ sd_bus_slot *match_bus_slot; + /* References to this unit from clients */ + sd_bus_track *bus_track; + char **deserialized_refs; + /* Job timeout and action to take */ usec_t job_timeout; FailureAction job_timeout_action; @@ -247,6 +251,9 @@ struct Unit { /* Did we already invoke unit_coldplug() for this unit? */ bool coldplugged:1; + + /* For transient units: whether to add a bus track reference after creating the unit */ + bool bus_track_add:1; }; struct UnitStatusMessageFormats { diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index 32be3cdc38..a69193aa32 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -45,6 +45,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED), SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH), + SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index befb6fbfe0..5df21c8926 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -41,6 +41,7 @@ #define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown" #define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning" #define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser" +#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced" #define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine" #define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage" -- cgit v1.2.3-54-g00ecf From bdf97b8ad84a66e0687222ac139603468162d785 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Aug 2016 19:00:12 +0200 Subject: bus-util: support mapping signed integers with bus_map_properties() Let's make sure we can read the exit code/status properties exposed by PID 1 properly. Let's reuse the existing code for unsigned fields, as we just use it to copy words around, and don't calculate it. --- src/shared/bus-util.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 52410999cf..b7dda3ee4d 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1059,29 +1059,27 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ break; } + case SD_BUS_TYPE_INT32: case SD_BUS_TYPE_UINT32: { - uint32_t u; - uint32_t *p = userdata; + uint32_t u, *p = userdata; r = sd_bus_message_read_basic(m, type, &u); if (r < 0) break; *p = u; - break; } + case SD_BUS_TYPE_INT64: case SD_BUS_TYPE_UINT64: { - uint64_t t; - uint64_t *p = userdata; + uint64_t t, *p = userdata; r = sd_bus_message_read_basic(m, type, &t); if (r < 0) break; *p = t; - break; } -- cgit v1.2.3-54-g00ecf From 0b83b8a4dcd429e6d14f2251fffdc7eae215c1f5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Aug 2016 19:03:44 +0200 Subject: bus-util: treat an empty string as a NULL Instead of ignoring empty strings retrieved via the bus, treat them as NULL, as it's customary in systemd. --- src/shared/bus-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index b7dda3ee4d..af676db3ea 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1025,7 +1025,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ break; if (isempty(s)) - break; + s = NULL; r = free_and_strdup(p, s); break; -- cgit v1.2.3-54-g00ecf From 8b3b6f588cd9aecbfb17664a5961f789b5a11386 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Aug 2016 19:04:35 +0200 Subject: bus-util: make sure map_basic() returns EOPNOTSUPP if called for an unknown type Make sure we return proper errors for types not understood yet. --- src/shared/bus-util.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index af676db3ea..fd42605b3e 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1016,19 +1016,19 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ return r; switch (type) { + case SD_BUS_TYPE_STRING: { - const char *s; char **p = userdata; + const char *s; r = sd_bus_message_read_basic(m, type, &s); if (r < 0) - break; + return r; if (isempty(s)) s = NULL; - r = free_and_strdup(p, s); - break; + return free_and_strdup(p, s); } case SD_BUS_TYPE_ARRAY: { @@ -1037,13 +1037,12 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ r = bus_message_read_strv_extend(m, &l); if (r < 0) - break; + return r; strv_free(*p); *p = l; l = NULL; - - break; + return 0; } case SD_BUS_TYPE_BOOLEAN: { @@ -1052,11 +1051,10 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ r = sd_bus_message_read_basic(m, type, &b); if (r < 0) - break; + return r; *p = b; - - break; + return 0; } case SD_BUS_TYPE_INT32: @@ -1065,10 +1063,10 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ r = sd_bus_message_read_basic(m, type, &u); if (r < 0) - break; + return r; *p = u; - break; + return 0; } case SD_BUS_TYPE_INT64: @@ -1077,30 +1075,24 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ r = sd_bus_message_read_basic(m, type, &t); if (r < 0) - break; + return r; *p = t; - break; + return 0; } case SD_BUS_TYPE_DOUBLE: { - double d; - double *p = userdata; + double d, *p = userdata; r = sd_bus_message_read_basic(m, type, &d); if (r < 0) - break; + return r; *p = d; + return 0; + }} - break; - } - - default: - break; - } - - return r; + return -EOPNOTSUPP; } int bus_message_map_all_properties( -- cgit v1.2.3-54-g00ecf From fe700f46ec5490efcb8da49e644bb4d781f896f2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Aug 2016 20:58:10 +0200 Subject: core: cache last CPU usage counter, before destorying a cgroup It is useful for clients to be able to read the last CPU usage counter value of a unit even if the unit is already terminated. Hence, before destroying a cgroup's cgroup cache the last CPU usage counter and return it if the cgroup is gone. --- src/core/cgroup.c | 23 ++++++++++++++++++++++- src/core/unit.c | 16 ++++++++++++++-- src/core/unit.h | 1 + 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 086cd7a789..20f9f9fc7e 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -1524,6 +1524,8 @@ void unit_prune_cgroup(Unit *u) { if (!u->cgroup_path) return; + (void) unit_get_cpu_usage(u, NULL); /* Cache the last CPU usage value before we destroy the cgroup */ + is_root_slice = unit_has_name(u, SPECIAL_ROOT_SLICE); r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !is_root_slice); @@ -2044,7 +2046,21 @@ int unit_get_cpu_usage(Unit *u, nsec_t *ret) { nsec_t ns; int r; + assert(u); + + /* Retrieve the current CPU usage counter. This will subtract the CPU counter taken when the unit was + * started. If the cgroup has been removed already, returns the last cached value. To cache the value, simply + * call this function with a NULL return value. */ + r = unit_get_cpu_usage_raw(u, &ns); + if (r == -ENODATA && u->cpu_usage_last != NSEC_INFINITY) { + /* If we can't get the CPU usage anymore (because the cgroup was already removed, for example), use our + * cached value. */ + + if (ret) + *ret = u->cpu_usage_last; + return 0; + } if (r < 0) return r; @@ -2053,7 +2069,10 @@ int unit_get_cpu_usage(Unit *u, nsec_t *ret) { else ns = 0; - *ret = ns; + u->cpu_usage_last = ns; + if (ret) + *ret = ns; + return 0; } @@ -2063,6 +2082,8 @@ int unit_reset_cpu_usage(Unit *u) { assert(u); + u->cpu_usage_last = NSEC_INFINITY; + r = unit_get_cpu_usage_raw(u, &ns); if (r < 0) { u->cpu_usage_base = 0; diff --git a/src/core/unit.c b/src/core/unit.c index 6d92eb0c30..03ee6424fa 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -102,6 +102,7 @@ Unit *unit_new(Manager *m, size_t size) { u->job_timeout = USEC_INFINITY; u->ref_uid = UID_INVALID; u->ref_gid = GID_INVALID; + u->cpu_usage_last = NSEC_INFINITY; RATELIMIT_INIT(u->start_limit, m->default_start_limit_interval, m->default_start_limit_burst); RATELIMIT_INIT(u->auto_stop_ratelimit, 10 * USEC_PER_SEC, 16); @@ -2620,7 +2621,10 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { unit_serialize_item(u, f, "assert-result", yes_no(u->assert_result)); unit_serialize_item(u, f, "transient", yes_no(u->transient)); + unit_serialize_item_format(u, f, "cpu-usage-base", "%" PRIu64, u->cpu_usage_base); + if (u->cpu_usage_last != NSEC_INFINITY) + unit_serialize_item_format(u, f, "cpu-usage-last", "%" PRIu64, u->cpu_usage_last); if (u->cgroup_path) unit_serialize_item(u, f, "cgroup", u->cgroup_path); @@ -2843,11 +2847,19 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { continue; - } else if (streq(l, "cpu-usage-base") || streq(l, "cpuacct-usage-base")) { + } else if (STR_IN_SET(l, "cpu-usage-base", "cpuacct-usage-base")) { r = safe_atou64(v, &u->cpu_usage_base); if (r < 0) - log_unit_debug(u, "Failed to parse CPU usage %s, ignoring.", v); + log_unit_debug(u, "Failed to parse CPU usage base %s, ignoring.", v); + + continue; + + } else if (streq(l, "cpu-usage-last")) { + + r = safe_atou64(v, &u->cpu_usage_last); + if (r < 0) + log_unit_debug(u, "Failed to read CPU usage last %s, ignoring.", v); continue; diff --git a/src/core/unit.h b/src/core/unit.h index e5a2a77b7b..31f0fef87b 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -194,6 +194,7 @@ struct Unit { /* Where the cpu.stat or cpuacct.usage was at the time the unit was started */ nsec_t cpu_usage_base; + nsec_t cpu_usage_last; /* the most recently read value */ /* Counterparts in the cgroup filesystem */ char *cgroup_path; -- cgit v1.2.3-54-g00ecf From 2a453c2ee3090e1942bfd962262f3eff0adbfa97 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Aug 2016 14:24:17 +0200 Subject: run: optionally, wait for the service to finish and show its result --- src/run/run.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++------ src/shared/ptyfwd.c | 102 +++++++++++++++-------- src/shared/ptyfwd.h | 8 +- 3 files changed, 283 insertions(+), 58 deletions(-) diff --git a/src/run/run.c b/src/run/run.c index 0797547684..8db9f07158 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -33,6 +33,7 @@ #include "formats-util.h" #include "parse-util.h" #include "path-util.h" +#include "process-util.h" #include "ptyfwd.h" #include "signal-util.h" #include "spawn-polkit-agent.h" @@ -45,6 +46,7 @@ static bool arg_ask_password = true; static bool arg_scope = false; static bool arg_remain_after_exit = false; static bool arg_no_block = false; +static bool arg_wait = false; static const char *arg_unit = NULL; static const char *arg_description = NULL; static const char *arg_slice = NULL; @@ -97,6 +99,7 @@ static void help(void) { " --slice=SLICE Run in the specified slice\n" " --no-block Do not wait until operation finished\n" " -r --remain-after-exit Leave service around until explicitly stopped\n" + " --wait Wait until service stopped again\n" " --send-sighup Send SIGHUP when terminating\n" " --service-type=TYPE Service type\n" " --uid=USER Run as system user\n" @@ -144,6 +147,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_TIMER_PROPERTY, ARG_NO_BLOCK, ARG_NO_ASK_PASSWORD, + ARG_WAIT, }; static const struct option options[] = { @@ -160,6 +164,7 @@ static int parse_argv(int argc, char *argv[]) { { "host", required_argument, NULL, 'H' }, { "machine", required_argument, NULL, 'M' }, { "service-type", required_argument, NULL, ARG_SERVICE_TYPE }, + { "wait", no_argument, NULL, ARG_WAIT }, { "uid", required_argument, NULL, ARG_EXEC_USER }, { "gid", required_argument, NULL, ARG_EXEC_GROUP }, { "nice", required_argument, NULL, ARG_NICE }, @@ -357,6 +362,10 @@ static int parse_argv(int argc, char *argv[]) { arg_no_block = true; break; + case ARG_WAIT: + arg_wait = true; + break; + case '?': return -EINVAL; @@ -404,6 +413,23 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } + if (arg_wait) { + if (arg_no_block) { + log_error("--wait may not be combined with --no-block."); + return -EINVAL; + } + + if (with_timer()) { + log_error("--wait may not be combined with timer operations."); + return -EINVAL; + } + + if (arg_scope) { + log_error("--wait may not be combined with --scope."); + return -EINVAL; + } + } + return 1; } @@ -466,6 +492,12 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons if (r < 0) return r; + if (arg_wait) { + r = sd_bus_message_append(m, "(sv)", "AddRef", "b", 1); + if (r < 0) + return r; + } + if (arg_remain_after_exit) { r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit); if (r < 0) @@ -723,9 +755,97 @@ static int make_unit_name(sd_bus *bus, UnitType t, char **ret) { return 0; } +typedef struct RunContext { + sd_bus *bus; + sd_event *event; + PTYForward *forward; + sd_bus_slot *match; + + /* The exit data of the unit */ + char *active_state; + uint64_t inactive_exit_usec; + uint64_t inactive_enter_usec; + char *result; + uint64_t cpu_usage_nsec; + uint32_t exit_code; + uint32_t exit_status; +} RunContext; + +static void run_context_free(RunContext *c) { + assert(c); + + c->forward = pty_forward_free(c->forward); + c->match = sd_bus_slot_unref(c->match); + c->bus = sd_bus_unref(c->bus); + c->event = sd_event_unref(c->event); + + free(c->active_state); + free(c->result); +} + +static void run_context_check_done(RunContext *c) { + bool done = true; + + assert(c); + + if (c->match) + done = done && (c->active_state && STR_IN_SET(c->active_state, "inactive", "failed")); + + if (c->forward) + done = done && pty_forward_is_done(c->forward); + + if (done) + sd_event_exit(c->event, EXIT_SUCCESS); +} + +static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + + static const struct bus_properties_map map[] = { + { "ActiveState", "s", NULL, offsetof(RunContext, active_state) }, + { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_exit_usec) }, + { "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_enter_usec) }, + { "Result", "s", NULL, offsetof(RunContext, result) }, + { "ExecMainCode", "i", NULL, offsetof(RunContext, exit_code) }, + { "ExecMainStatus", "i", NULL, offsetof(RunContext, exit_status) }, + { "CPUUsageNSec", "t", NULL, offsetof(RunContext, cpu_usage_nsec) }, + {} + }; + + RunContext *c = userdata; + int r; + + r = bus_map_all_properties(c->bus, + "org.freedesktop.systemd1", + sd_bus_message_get_path(m), + map, + c); + if (r < 0) { + sd_event_exit(c->event, EXIT_FAILURE); + return log_error_errno(r, "Failed to query unit state: %m"); + } + + run_context_check_done(c); + return 0; +} + +static int pty_forward_handler(PTYForward *f, int rcode, void *userdata) { + RunContext *c = userdata; + + assert(f); + + if (rcode < 0) { + sd_event_exit(c->event, EXIT_FAILURE); + return log_error_errno(rcode, "Error on PTY forwarding logic: %m"); + } + + run_context_check_done(c); + return 0; +} + static int start_transient_service( sd_bus *bus, - char **argv) { + char **argv, + int *retval) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; @@ -736,6 +856,7 @@ static int start_transient_service( assert(bus); assert(argv); + assert(retval); if (arg_pty) { @@ -859,40 +980,95 @@ static int start_transient_service( return r; } - if (master >= 0) { - _cleanup_(pty_forward_freep) PTYForward *forward = NULL; - _cleanup_(sd_event_unrefp) sd_event *event = NULL; - char last_char = 0; + if (!arg_quiet) + log_info("Running as unit: %s", service); + + if (arg_wait || master >= 0) { + _cleanup_(run_context_free) RunContext c = {}; - r = sd_event_default(&event); + c.bus = sd_bus_ref(bus); + + r = sd_event_default(&c.event); if (r < 0) return log_error_errno(r, "Failed to get event loop: %m"); - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0); + if (master >= 0) { + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0); + (void) sd_event_add_signal(c.event, NULL, SIGINT, NULL, NULL); + (void) sd_event_add_signal(c.event, NULL, SIGTERM, NULL, NULL); + + if (!arg_quiet) + log_info("Press ^] three times within 1s to disconnect TTY."); - (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); - (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); + r = pty_forward_new(c.event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &c.forward); + if (r < 0) + return log_error_errno(r, "Failed to create PTY forwarder: %m"); + + pty_forward_set_handler(c.forward, pty_forward_handler, &c); + } - if (!arg_quiet) - log_info("Running as unit: %s\nPress ^] three times within 1s to disconnect TTY.", service); + if (arg_wait) { + _cleanup_free_ char *path = NULL; + const char *mt; - r = pty_forward_new(event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &forward); - if (r < 0) - return log_error_errno(r, "Failed to create PTY forwarder: %m"); + path = unit_dbus_path_from_name(service); + if (!path) + return log_oom(); + + mt = strjoina("type='signal'," + "sender='org.freedesktop.systemd1'," + "path='", path, "'," + "interface='org.freedesktop.DBus.Properties'," + "member='PropertiesChanged'"); + r = sd_bus_add_match(bus, &c.match, mt, on_properties_changed, &c); + if (r < 0) + return log_error_errno(r, "Failed to add properties changed signal."); - r = sd_event_loop(event); + r = sd_bus_attach_event(bus, c.event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop."); + } + + r = sd_event_loop(c.event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); - pty_forward_get_last_char(forward, &last_char); + if (c.forward) { + char last_char = 0; - forward = pty_forward_free(forward); + r = pty_forward_get_last_char(c.forward, &last_char); + if (r >= 0 && !arg_quiet && last_char != '\n') + fputc('\n', stdout); + } - if (!arg_quiet && last_char != '\n') - fputc('\n', stdout); + if (!arg_quiet) { + if (!isempty(c.result)) + log_info("Finished with result: %s", strna(c.result)); - } else if (!arg_quiet) - log_info("Running as unit: %s", service); + if (c.exit_code == CLD_EXITED) + log_info("Main processes terminated with: code=%s/status=%i", sigchld_code_to_string(c.exit_code), c.exit_status); + else if (c.exit_code > 0) + log_info("Main processes terminated with: code=%s/status=%s", sigchld_code_to_string(c.exit_code), signal_to_string(c.exit_status)); + + if (c.inactive_enter_usec > 0 && c.inactive_enter_usec != USEC_INFINITY && + c.inactive_exit_usec > 0 && c.inactive_exit_usec != USEC_INFINITY && + c.inactive_enter_usec > c.inactive_exit_usec) { + char ts[FORMAT_TIMESPAN_MAX]; + log_info("Service runtime: %s", format_timespan(ts, sizeof(ts), c.inactive_enter_usec - c.inactive_exit_usec, USEC_PER_MSEC)); + } + + if (c.cpu_usage_nsec > 0 && c.cpu_usage_nsec != NSEC_INFINITY) { + char ts[FORMAT_TIMESPAN_MAX]; + log_info("CPU time consumed: %s", format_timespan(ts, sizeof(ts), (c.cpu_usage_nsec + NSEC_PER_USEC - 1) / NSEC_PER_USEC, USEC_PER_MSEC)); + } + } + + /* Try to propagate the service's return value */ + if (c.result && STR_IN_SET(c.result, "success", "exit-code") && c.exit_code == CLD_EXITED) + *retval = c.exit_status; + else + *retval = EXIT_FAILURE; + } return 0; } @@ -1195,7 +1371,7 @@ static int start_transient_timer( int main(int argc, char* argv[]) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *description = NULL, *command = NULL; - int r; + int r, retval = EXIT_SUCCESS; log_parse_environment(); log_open(); @@ -1232,7 +1408,12 @@ int main(int argc, char* argv[]) { arg_description = description; } - r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus); + /* If --wait is used connect via the bus, unconditionally, as ref/unref is not supported via the limited direct + * connection */ + if (arg_wait) + r = bus_connect_transport(arg_transport, arg_host, arg_user, &bus); + else + r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; @@ -1243,12 +1424,12 @@ int main(int argc, char* argv[]) { else if (with_timer()) r = start_transient_timer(bus, argv + optind); else - r = start_transient_service(bus, argv + optind); + r = start_transient_service(bus, argv + optind, &retval); finish: strv_free(arg_environment); strv_free(arg_property); strv_free(arg_timer_property); - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + return r < 0 ? EXIT_FAILURE : retval; } diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 02c03b98d8..24055e772b 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -68,6 +68,8 @@ struct PTYForward { bool read_from_master:1; + bool done:1; + bool last_char_set:1; char last_char; @@ -76,10 +78,54 @@ struct PTYForward { usec_t escape_timestamp; unsigned escape_counter; + + PTYForwardHandler handler; + void *userdata; }; #define ESCAPE_USEC (1*USEC_PER_SEC) +static void pty_forward_disconnect(PTYForward *f) { + + if (f) { + f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); + f->stdout_event_source = sd_event_source_unref(f->stdout_event_source); + + f->master_event_source = sd_event_source_unref(f->master_event_source); + f->sigwinch_event_source = sd_event_source_unref(f->sigwinch_event_source); + f->event = sd_event_unref(f->event); + + if (f->saved_stdout) + tcsetattr(STDOUT_FILENO, TCSANOW, &f->saved_stdout_attr); + if (f->saved_stdin) + tcsetattr(STDIN_FILENO, TCSANOW, &f->saved_stdin_attr); + + f->saved_stdout = f->saved_stdin = false; + } + + /* STDIN/STDOUT should not be nonblocking normally, so let's unconditionally reset it */ + fd_nonblock(STDIN_FILENO, false); + fd_nonblock(STDOUT_FILENO, false); +} + +static int pty_forward_done(PTYForward *f, int rcode) { + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + assert(f); + + if (f->done) + return 0; + + e = sd_event_ref(f->event); + + f->done = true; + pty_forward_disconnect(f); + + if (f->handler) + return f->handler(f, rcode, f->userdata); + else + return sd_event_exit(e, rcode < 0 ? EXIT_FAILURE : rcode); +} + static bool look_for_escape(PTYForward *f, const char *buffer, size_t n) { const char *p; @@ -147,7 +193,7 @@ static int shovel(PTYForward *f) { f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); } else { log_error_errno(errno, "read(): %m"); - return sd_event_exit(f->event, EXIT_FAILURE); + return pty_forward_done(f, -errno); } } else if (k == 0) { /* EOF on stdin */ @@ -156,12 +202,10 @@ static int shovel(PTYForward *f) { f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); } else { - /* Check if ^] has been - * pressed three times within - * one second. If we get this - * we quite immediately. */ + /* Check if ^] has been pressed three times within one second. If we get this we quite + * immediately. */ if (look_for_escape(f, f->in_buffer + f->in_buffer_full, k)) - return sd_event_exit(f->event, EXIT_FAILURE); + return pty_forward_done(f, -ECANCELED); f->in_buffer_full += (size_t) k; } @@ -181,7 +225,7 @@ static int shovel(PTYForward *f) { f->master_event_source = sd_event_source_unref(f->master_event_source); } else { log_error_errno(errno, "write(): %m"); - return sd_event_exit(f->event, EXIT_FAILURE); + return pty_forward_done(f, -errno); } } else { assert(f->in_buffer_full >= (size_t) k); @@ -211,7 +255,7 @@ static int shovel(PTYForward *f) { f->master_event_source = sd_event_source_unref(f->master_event_source); } else { log_error_errno(errno, "read(): %m"); - return sd_event_exit(f->event, EXIT_FAILURE); + return pty_forward_done(f, -errno); } } else { f->read_from_master = true; @@ -232,7 +276,7 @@ static int shovel(PTYForward *f) { f->stdout_event_source = sd_event_source_unref(f->stdout_event_source); } else { log_error_errno(errno, "write(): %m"); - return sd_event_exit(f->event, EXIT_FAILURE); + return pty_forward_done(f, -errno); } } else { @@ -255,7 +299,7 @@ static int shovel(PTYForward *f) { if ((f->out_buffer_full <= 0 || f->stdout_hangup) && (f->in_buffer_full <= 0 || f->master_hangup)) - return sd_event_exit(f->event, EXIT_SUCCESS); + return pty_forward_done(f, 0); } return 0; @@ -418,27 +462,8 @@ int pty_forward_new( } PTYForward *pty_forward_free(PTYForward *f) { - - if (f) { - sd_event_source_unref(f->stdin_event_source); - sd_event_source_unref(f->stdout_event_source); - sd_event_source_unref(f->master_event_source); - sd_event_source_unref(f->sigwinch_event_source); - sd_event_unref(f->event); - - if (f->saved_stdout) - tcsetattr(STDOUT_FILENO, TCSANOW, &f->saved_stdout_attr); - if (f->saved_stdin) - tcsetattr(STDIN_FILENO, TCSANOW, &f->saved_stdin_attr); - - free(f); - } - - /* STDIN/STDOUT should not be nonblocking normally, so let's - * unconditionally reset it */ - fd_nonblock(STDIN_FILENO, false); - fd_nonblock(STDOUT_FILENO, false); - + pty_forward_disconnect(f); + free(f); return NULL; } @@ -477,8 +502,21 @@ int pty_forward_set_ignore_vhangup(PTYForward *f, bool b) { return 0; } -int pty_forward_get_ignore_vhangup(PTYForward *f) { +bool pty_forward_get_ignore_vhangup(PTYForward *f) { assert(f); return !!(f->flags & PTY_FORWARD_IGNORE_VHANGUP); } + +bool pty_forward_is_done(PTYForward *f) { + assert(f); + + return f->done; +} + +void pty_forward_set_handler(PTYForward *f, PTYForwardHandler cb, void *userdata) { + assert(f); + + f->handler = cb; + f->userdata = userdata; +} diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h index a046eb4e5e..bd5d5fec0d 100644 --- a/src/shared/ptyfwd.h +++ b/src/shared/ptyfwd.h @@ -37,12 +37,18 @@ typedef enum PTYForwardFlags { PTY_FORWARD_IGNORE_INITIAL_VHANGUP = 4, } PTYForwardFlags; +typedef int (*PTYForwardHandler)(PTYForward *f, int rcode, void*userdata); + int pty_forward_new(sd_event *event, int master, PTYForwardFlags flags, PTYForward **f); PTYForward *pty_forward_free(PTYForward *f); int pty_forward_get_last_char(PTYForward *f, char *ch); int pty_forward_set_ignore_vhangup(PTYForward *f, bool ignore_vhangup); -int pty_forward_get_ignore_vhangup(PTYForward *f); +bool pty_forward_get_ignore_vhangup(PTYForward *f); + +bool pty_forward_is_done(PTYForward *f); + +void pty_forward_set_handler(PTYForward *f, PTYForwardHandler handler, void *userdata); DEFINE_TRIVIAL_CLEANUP_FUNC(PTYForward*, pty_forward_free); -- cgit v1.2.3-54-g00ecf From 014c4c98ba85544d75a8447eb7b78c1953d9e3b7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Aug 2016 21:53:38 +0200 Subject: man: document the new --wait switch of systemd-run Also, make major improvements to the an page in general. --- man/systemd-run.xml | 165 ++++++++++++++++++++++------------------------------ 1 file changed, 71 insertions(+), 94 deletions(-) diff --git a/man/systemd-run.xml b/man/systemd-run.xml index 56d585cdf9..15f9119e54 100644 --- a/man/systemd-run.xml +++ b/man/systemd-run.xml @@ -68,42 +68,30 @@ Description - systemd-run may be used to create and - start a transient .service or - .scope unit and run the specified - COMMAND in it. It may also be used to - create and start transient .timer - units. - - If a command is run as transient service unit, it will be - started and managed by the service manager like any other service, - and thus shows up in the output of systemctl - list-units like any other unit. It will run in a clean - and detached execution environment, with the service manager as - its parent process. In this mode, systemd-run - will start the service asynchronously in the background and return - after the command has begun execution. - - If a command is run as transient scope unit, it will be - started by systemd-run itself as parent process - and will thus inherit the execution environment of the - caller. However, the processes of the command are managed by the - service manager similar to normal services, and will show up in - the output of systemctl list-units. Execution - in this case is synchronous, and will return only when the command - finishes. This mode is enabled via the - switch (see below). - - If a command is run with timer options such as - (see below), a transient timer - unit is created alongside the service unit for the specified - command. Only the transient timer unit is started immediately, the - transient service unit will be started when the transient timer - elapses. If the is specified, the - COMMAND may be omitted. In this case, - systemd-run only creates a - .timer unit that invokes the specified unit - when elapsing. + systemd-run may be used to create and start a transient .service or + .scope unit and run the specified COMMAND in it. It may also be + used to create and start a transient .timer unit, that activates a + .service unit when elapsing. + + If a command is run as transient service unit, it will be started and managed by the service manager like any + other service, and thus shows up in the output of systemctl list-units like any other unit. It + will run in a clean and detached execution environment, with the service manager as its parent process. In this + mode, systemd-run will start the service asynchronously in the background and return after the + command has begun execution (unless or are specified, see + below). + + If a command is run as transient scope unit, it will be executed by systemd-run itself as + parent process and will thus inherit the execution environment of the caller. However, the processes of the command + are managed by the service manager similar to normal services, and will show up in the output of systemctl + list-units. Execution in this case is synchronous, and will return only when the command finishes. This + mode is enabled via the switch (see below). + + If a command is run with timer options such as (see below), a transient timer + unit is created alongside the service unit for the specified command. Only the transient timer unit is started + immediately, the transient service unit will be started when the timer elapses. If the + option is specified, the COMMAND may be omitted. In this case, + systemd-run creates only a .timer unit that invokes the specified unit when + elapsing. @@ -123,8 +111,8 @@ - Create a transient .scope unit instead of - the default transient .service unit. + Create a transient .scope unit instead of the default transient + .service unit (see above). @@ -140,9 +128,8 @@ - Sets a unit property for the scope or service - unit that is created. This takes an assignment in the same - format as + Sets a property on the scope or service unit that is created. This option takes an assignment + in the same format as systemctl1's set-property command. @@ -151,9 +138,8 @@ - Provide a description for the service or scope - unit. If not specified, the command itself will be used as a - description. See Description= in + Provide a description for the service, scope or timer unit. If not specified, the command + itself will be used as a description. See Description= in systemd.unit5. @@ -161,19 +147,16 @@ - Make the new .service or - .scope unit part of the specified slice, - instead of the system.slice. + Make the new .service or .scope unit part of the + specified slice, instead of system.slice. - After the service or scope process has - terminated, keep the service around until it is explicitly - stopped. This is useful to collect runtime information about - the service after it finished running. Also see + After the service process has terminated, keep the service around until it is explicitly + stopped. This is useful to collect runtime information about the service after it finished running. Also see RemainAfterExit= in systemd.service5. @@ -183,10 +166,8 @@ - When terminating the scope or service unit, - send a SIGHUP immediately after SIGTERM. This is useful to - indicate to shells and shell-like processes that the - connection has been severed. Also see + When terminating the scope or service unit, send a SIGHUP immediately after SIGTERM. This is + useful to indicate to shells and shell-like processes that the connection has been severed. Also see SendSIGHUP= in systemd.kill5. @@ -209,9 +190,8 @@ - Runs the service process under the UNIX user - and group. Also see User= and - Group= in + Runs the service process under the specified UNIX user and group. Also see + User= and Group= in systemd.exec5. @@ -239,11 +219,9 @@ - When invoking a command, the service connects - its standard input and output to the invoking tty via a - pseudo TTY device. This allows invoking binaries as services - that expect interactive user input, such as interactive - command shells. + When invoking the command, the transient service connects its standard input and output to the + terminal systemd-run is invoked on, via a pseudo TTY device. This allows running binaries + that expect interactive user input as services, such as interactive command shells. @@ -263,44 +241,32 @@ - Defines monotonic timers relative to different - starting points. Also see OnActiveSec=, - OnBootSec=, - OnStartupSec=, - OnUnitActiveSec= and - OnUnitInactiveSec= in - systemd.timer5. This - options have no effect in conjunction with - . + Defines a monotonic timer relative to different starting points for starting the specified + command. See OnActiveSec=, OnBootSec=, OnStartupSec=, + OnUnitActiveSec= and OnUnitInactiveSec= in + systemd.timer5 for + details. These options may not be combined with . - Defines realtime (i.e. wallclock) timers with - calendar event expressions. Also see - OnCalendar= in - systemd.timer5. This - option has no effect in conjunction with - . + Defines a calendar timer for starting the specified command. See OnCalendar= + in systemd.timer5. This + option may not be combined with . - Sets a timer unit property for the timer unit - that is created. It is similar with - but only for created timer - unit. This option only has effect in conjunction with - , , - , - , - , - . This takes an assignment in - the same format as - systemctl1's + Sets a property on the timer unit that is created. This option is similar to + but applies to the transient timer unit rather than the transient service unit + created. This option only has an effect in conjunction with , + , , , + or . This option takes an assignment in the + same format as systemctl1's set-property command. @@ -308,14 +274,25 @@ - Do not synchronously wait for the requested operation - to finish. If this is not specified, the job will be - verified, enqueued and systemd-run will - wait until the unit's start-up is completed. By passing this - argument, it is only verified and enqueued. + Do not synchronously wait for the unit start operation to finish. If this option is not specified, the + start request for the transient unit will be verified, enqueued and systemd-run will wait + until the unit's start-up is completed. By passing this argument, it is only verified and enqueued. This + option may not be combined with . + + + + Synchronously wait for the transient service to terminate. If this option is specified, the + start request for the transient unit is verified, enqueued, and waited for. Subsequently the invoked unit is + monitored, and it is waited until it is deactivated again (most likely because the specified command + completed). On exit, terse information about the unit's runtime is shown, including total runtime (as well as + CPU usage, if was set) and the exit code and status of the main + process. This output may be suppressed with . This option may not be combined with + , or the various timer options. + + -- cgit v1.2.3-54-g00ecf From 390bc2b149a09661c81df404692b191e20dac7a0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Aug 2016 19:30:06 +0200 Subject: core: let's use set_contains() where appropriate --- src/core/unit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/unit.c b/src/core/unit.c index 03ee6424fa..de22f657c6 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -114,7 +114,7 @@ bool unit_has_name(Unit *u, const char *name) { assert(u); assert(name); - return !!set_get(u->names, (char*) name); + return set_contains(u->names, (char*) name); } static void unit_init(Unit *u) { -- cgit v1.2.3-54-g00ecf From 217fcc7eb3b558e65538cbb42f47b2cb89f2850a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 14:45:34 +0200 Subject: sd-bus: split out handling of reply callbacks on close into its own function When a bus connection is closed we dispatch all reply callbacks. Do so in a new function if its own. No behaviour changes. --- src/libsystemd/sd-bus/sd-bus.c | 92 +++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index ed5f94e136..95c37d8b19 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -2640,63 +2640,71 @@ null_message: return r; } -static int process_closing(sd_bus *bus, sd_bus_message **ret) { +static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; - struct reply_callback *c; + sd_bus_slot *slot; int r; assert(bus); - assert(bus->state == BUS_CLOSING); + assert(c); - c = ordered_hashmap_first(bus->reply_callbacks); - if (c) { - _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; - sd_bus_slot *slot; + r = bus_message_new_synthetic_error( + bus, + c->cookie, + &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"), + &m); + if (r < 0) + return r; - /* First, fail all outstanding method calls */ - r = bus_message_new_synthetic_error( - bus, - c->cookie, - &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"), - &m); - if (r < 0) - return r; + r = bus_seal_synthetic_message(bus, m); + if (r < 0) + return r; - r = bus_seal_synthetic_message(bus, m); - if (r < 0) - return r; + if (c->timeout != 0) { + prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); + c->timeout = 0; + } - if (c->timeout != 0) { - prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); - c->timeout = 0; - } + ordered_hashmap_remove(bus->reply_callbacks, &c->cookie); + c->cookie = 0; + + slot = container_of(c, sd_bus_slot, reply_callback); - ordered_hashmap_remove(bus->reply_callbacks, &c->cookie); - c->cookie = 0; + bus->iteration_counter++; - slot = container_of(c, sd_bus_slot, reply_callback); + bus->current_message = m; + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_handler = c->callback; + bus->current_userdata = slot->userdata; + r = c->callback(m, slot->userdata, &error_buffer); + bus->current_userdata = NULL; + bus->current_handler = NULL; + bus->current_slot = NULL; + bus->current_message = NULL; - bus->iteration_counter++; + if (slot->floating) { + bus_slot_disconnect(slot); + sd_bus_slot_unref(slot); + } - bus->current_message = m; - bus->current_slot = sd_bus_slot_ref(slot); - bus->current_handler = c->callback; - bus->current_userdata = slot->userdata; - r = c->callback(m, slot->userdata, &error_buffer); - bus->current_userdata = NULL; - bus->current_handler = NULL; - bus->current_slot = NULL; - bus->current_message = NULL; + sd_bus_slot_unref(slot); - if (slot->floating) { - bus_slot_disconnect(slot); - sd_bus_slot_unref(slot); - } + return bus_maybe_reply_error(m, r, &error_buffer); +} - sd_bus_slot_unref(slot); +static int process_closing(sd_bus *bus, sd_bus_message **ret) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + struct reply_callback *c; + int r; - return bus_maybe_reply_error(m, r, &error_buffer); - } + assert(bus); + assert(bus->state == BUS_CLOSING); + + /* First, fail all outstanding method calls */ + c = ordered_hashmap_first(bus->reply_callbacks); + if (c) + return process_closing_reply_callback(bus, c); /* Then, synthesize a Disconnected message */ r = sd_bus_message_new_signal( -- cgit v1.2.3-54-g00ecf From 8b6e65ac32627e371ee61f7d086ed33bc47e4b4c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 16:09:15 +0200 Subject: sd-bus: ensure we don't dispatch track objects while we are adding names to them In order to add a name to a bus tracking object we need to do some bus operations: we need to check if the name already exists and add match for it. Both are synchronous bus calls. While processing those we need to make sure that the tracking object is not dispatched yet, as it might still be empty, but is not going to be empty for very long. hence, block dispatching by removing the object from the dispatch queue while adding it, and readding it on error. --- src/libsystemd/sd-bus/bus-track.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 6ece2244c2..90e0c7ae01 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -32,6 +32,7 @@ struct track_item { struct sd_bus_track { unsigned n_ref; + unsigned n_adding; /* are we in the process of adding a new name? */ sd_bus *bus; sd_bus_track_handler_t handler; void *userdata; @@ -80,9 +81,23 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free); static void bus_track_add_to_queue(sd_bus_track *track) { assert(track); + /* Adds the bus track object to the queue of objects we should dispatch next, subject to a number of + * conditions. */ + + /* Already in the queue? */ if (track->in_queue) return; + /* if we are currently in the process of adding a new name, then let's not enqueue this just yet, let's wait + * until the addition is complete. */ + if (track->n_adding > 0) + return; + + /* still referenced? */ + if (hashmap_size(track->names) > 0) + return; + + /* Nothing to call? */ if (!track->handler) return; @@ -112,8 +127,7 @@ static int bus_track_remove_name_fully(sd_bus_track *track, const char *name) { track_item_free(i); - if (hashmap_isempty(track->names)) - bus_track_add_to_queue(track); + bus_track_add_to_queue(track); track->modified = true; return 1; @@ -237,18 +251,30 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { /* First, subscribe to this name */ match = MATCH_FOR_NAME(name); + + bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */ + + track->n_adding++; /* make sure we aren't dispatched while we synchronously add this match */ r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track); - if (r < 0) + track->n_adding--; + if (r < 0) { + bus_track_add_to_queue(track); return r; + } r = hashmap_put(track->names, n->name, n); - if (r < 0) + if (r < 0) { + bus_track_add_to_queue(track); return r; + } /* Second, check if it is currently existing, or maybe doesn't, or maybe disappeared already. */ + track->n_adding++; /* again, make sure this isn't dispatch while we are working in it */ r = sd_bus_get_name_creds(track->bus, name, 0, NULL); + track->n_adding--; if (r < 0) { hashmap_remove(track->names, name); + bus_track_add_to_queue(track); return r; } -- cgit v1.2.3-54-g00ecf From 232f367766b35fa248476d0ded49781a06a80ae1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 16:11:54 +0200 Subject: sd-bus: when the server-side disconnects, make sure to dispatch all tracking objects immediately If the server side kicks us from the bus, from our view no names are on the bus anymore, hence let's make sure to dispatch all tracking objects immediately. --- src/libsystemd/sd-bus/bus-internal.h | 1 + src/libsystemd/sd-bus/bus-track.c | 44 ++++++++++++++++++++++++++++++++++-- src/libsystemd/sd-bus/bus-track.h | 1 + src/libsystemd/sd-bus/sd-bus.c | 7 ++++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 216d9f62bc..13357075bf 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -320,6 +320,7 @@ struct sd_bus { sd_bus_track *track_queue; LIST_HEAD(sd_bus_slot, slots); + LIST_HEAD(sd_bus_track, tracks); }; #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 90e0c7ae01..00e93a215f 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -39,9 +39,12 @@ struct sd_bus_track { Hashmap *names; LIST_FIELDS(sd_bus_track, queue); Iterator iterator; - bool in_queue:1; + bool in_list:1; /* In bus->tracks? */ + bool in_queue:1; /* In bus->track_queue? */ bool modified:1; bool recursive:1; + + LIST_FIELDS(sd_bus_track, tracks); }; #define MATCH_PREFIX \ @@ -101,6 +104,10 @@ static void bus_track_add_to_queue(sd_bus_track *track) { if (!track->handler) return; + /* Already closed? */ + if (!track->in_list) + return; + LIST_PREPEND(queue, track->bus->track_queue, track); track->in_queue = true; } @@ -156,6 +163,9 @@ _public_ int sd_bus_track_new( t->userdata = userdata; t->bus = sd_bus_ref(bus); + LIST_PREPEND(tracks, bus->tracks, t); + t->in_list = true; + bus_track_add_to_queue(t); *track = t; @@ -190,6 +200,9 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { while ((i = hashmap_steal_first(track->names))) track_item_free(i); + if (track->in_list) + LIST_REMOVE(tracks, track->bus->tracks, track); + bus_track_remove_from_queue(track); hashmap_free(track->names); sd_bus_unref(track->bus); @@ -403,7 +416,6 @@ void bus_track_dispatch(sd_bus_track *track) { int r; assert(track); - assert(track->in_queue); assert(track->handler); bus_track_remove_from_queue(track); @@ -419,6 +431,34 @@ void bus_track_dispatch(sd_bus_track *track) { sd_bus_track_unref(track); } +void bus_track_close(sd_bus_track *track) { + struct track_item *i; + + assert(track); + + /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it + * immediately, as we are closing now, but first flush out all names. */ + + if (!track->in_list) + return; /* We already closed this one, don't close it again. */ + + /* Remember that this one is closed now */ + LIST_REMOVE(tracks, track->bus->tracks, track); + track->in_list = false; + + /* If there's no name in this one anyway, we don't have to dispatch */ + if (hashmap_isempty(track->names)) + return; + + /* Let's flush out all names */ + while ((i = hashmap_steal_first(track->names))) + track_item_free(i); + + /* Invoke handler */ + if (track->handler) + bus_track_dispatch(track); +} + _public_ void *sd_bus_track_get_userdata(sd_bus_track *track) { assert_return(track, NULL); diff --git a/src/libsystemd/sd-bus/bus-track.h b/src/libsystemd/sd-bus/bus-track.h index 7d93a727d6..26bd05f5c7 100644 --- a/src/libsystemd/sd-bus/bus-track.h +++ b/src/libsystemd/sd-bus/bus-track.h @@ -20,3 +20,4 @@ ***/ void bus_track_dispatch(sd_bus_track *track); +void bus_track_close(sd_bus_track *track); diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 95c37d8b19..6ee5f82e12 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -107,6 +107,7 @@ static void bus_free(sd_bus *b) { assert(b); assert(!b->track_queue); + assert(!b->tracks); b->state = BUS_CLOSED; @@ -2706,6 +2707,12 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) { if (c) return process_closing_reply_callback(bus, c); + /* Then, fake-drop all remaining bus tracking references */ + if (bus->tracks) { + bus_track_close(bus->tracks); + return 1; + } + /* Then, synthesize a Disconnected message */ r = sd_bus_message_new_signal( bus, -- cgit v1.2.3-54-g00ecf From 70cb8b7b16d2f1c63b21d90a493d895018fe8f67 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 16:13:19 +0200 Subject: sd-bus: add a small test case for sd_bus_track This tests in particular that disconnecting results in the tracking object's handlers to be called. --- .gitignore | 1 + Makefile.am | 11 ++++ src/libsystemd/sd-bus/test-bus-track.c | 113 +++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 src/libsystemd/sd-bus/test-bus-track.c diff --git a/.gitignore b/.gitignore index 6caa8218bd..565a3a3839 100644 --- a/.gitignore +++ b/.gitignore @@ -152,6 +152,7 @@ /test-bus-policy /test-bus-server /test-bus-signature +/test-bus-track /test-bus-zero-copy /test-calendarspec /test-cap-list diff --git a/Makefile.am b/Makefile.am index 431975de8b..3a617560e0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3323,6 +3323,7 @@ tests += \ test-bus-error \ test-bus-creds \ test-bus-gvariant \ + test-bus-track \ test-event \ test-netlink \ test-local-addresses \ @@ -3366,6 +3367,16 @@ test_bus_cleanup_CFLAGS = \ test_bus_cleanup_LDADD = \ libsystemd-shared.la +test_bus_track_SOURCES = \ + src/libsystemd/sd-bus/test-bus-track.c + +test_bus_track_CFLAGS = \ + $(AM_CFLAGS) \ + $(SECCOMP_CFLAGS) + +test_bus_track_LDADD = \ + libsystemd-shared.la + test_bus_server_SOURCES = \ src/libsystemd/sd-bus/test-bus-server.c diff --git a/src/libsystemd/sd-bus/test-bus-track.c b/src/libsystemd/sd-bus/test-bus-track.c new file mode 100644 index 0000000000..4beb61f05a --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-track.c @@ -0,0 +1,113 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#include "macro.h" + +static bool track_cb_called_x = false; +static bool track_cb_called_y = false; + +static int track_cb_x(sd_bus_track *t, void *userdata) { + + log_error("TRACK CB X"); + + assert_se(!track_cb_called_x); + track_cb_called_x = true; + + /* This means b's name disappeared. Let's now disconnect, to make sure the track handling on disconnect works + * as it should. */ + + assert_se(shutdown(sd_bus_get_fd(sd_bus_track_get_bus(t)), SHUT_RDWR) >= 0); + return 1; +} + +static int track_cb_y(sd_bus_track *t, void *userdata) { + int r; + + log_error("TRACK CB Y"); + + assert_se(!track_cb_called_y); + track_cb_called_y = true; + + /* We got disconnected, let's close everything */ + + r = sd_event_exit(sd_bus_get_event(sd_bus_track_get_bus(t)), EXIT_SUCCESS); + assert_se(r >= 0); + + return 0; +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(sd_bus_track_unrefp) sd_bus_track *x = NULL, *y = NULL; + _cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL; + const char *unique; + int r; + + r = sd_event_default(&event); + assert_se(r >= 0); + + r = sd_bus_open_system(&a); + if (IN_SET(r, -ECONNREFUSED, -ENOENT)) { + log_info("Failed to connect to bus, skipping tests."); + return EXIT_TEST_SKIP; + } + assert_se(r >= 0); + + r = sd_bus_attach_event(a, event, SD_EVENT_PRIORITY_NORMAL); + assert_se(r >= 0); + + r = sd_bus_open_system(&b); + assert_se(r >= 0); + + r = sd_bus_attach_event(b, event, SD_EVENT_PRIORITY_NORMAL); + assert_se(r >= 0); + + /* Watch b's name from a */ + r = sd_bus_track_new(a, &x, track_cb_x, NULL); + assert_se(r >= 0); + + r = sd_bus_get_unique_name(b, &unique); + assert_se(r >= 0); + + r = sd_bus_track_add_name(x, unique); + assert_se(r >= 0); + + /* Watch's a's own name from a */ + r = sd_bus_track_new(a, &y, track_cb_y, NULL); + assert_se(r >= 0); + + r = sd_bus_get_unique_name(a, &unique); + assert_se(r >= 0); + + r = sd_bus_track_add_name(y, unique); + assert_se(r >= 0); + + /* Now make b's name disappear */ + sd_bus_close(b); + + r = sd_event_loop(event); + assert_se(r >= 0); + + assert_se(track_cb_called_x); + assert_se(track_cb_called_y); + + return 0; +} -- cgit v1.2.3-54-g00ecf From 2c5f295823028bd4cf8250d1e4e56a8712f78cc8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 Aug 2016 14:48:14 +0200 Subject: update TODO --- TODO | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 33afe39783..0ce9a1fd30 100644 --- a/TODO +++ b/TODO @@ -33,7 +33,13 @@ Janitorial Clean-ups: Features: -* RemoveIPC= in unit files for removing POSIX/SysV IPC objects +* introduce an "invocation ID" for units, that is randomly generated, and + identifies each runtime-cycle of a unit. It should be set freshly each time + we traverse inactive → activating/active, and should be the primary key to + map offline data (stored in the journal) with online bus objects. Let's pass + this as $SYSTEMD_INVOCATION_ID to services, as well as set this as xattr on + the cgroup of a services. The former is accessible without privileges, the + latter ensures the ID cannot be faked. * Introduce ProtectSystem=strict for making the entire OS hierarchy read-only except for a select few @@ -58,6 +64,8 @@ Features: * ProtectControlGroups= which mounts all of /sys/fs/cgroup read-only +* ProtectKernelTunables= which mounts /sys and /proc/sys read-only + * RemoveKeyRing= to remove all keyring entries of the specified user * Add DataDirectory=, CacheDirectory= and LogDirectory= to match @@ -76,6 +84,9 @@ Features: * journalctl: make sure -f ends when the container indicated by -M terminates +* mount: automatically search for "main" partition of an image has multiple + partitions + * expose the "privileged" flag of ExecCommand on the bus, and open it up to transient units @@ -86,6 +97,12 @@ Features: * allow attaching additional journald log fields to cgroups +* add bus API for creating unit files in /etc, reusing the code for transient units + +* add bus API to remove unit files from /etc + +* add bus API to retrieve current unit file contents (i.e. implement "systemctl cat" on the bus only) + * rework fopen_temporary() to make use of open_tmpfile_linkable() (problem: the kernel doesn't support linkat() that replaces existing files, currently) @@ -112,8 +129,6 @@ Features: * add systemctl stop --job-mode=triggering that follows TRIGGERED_BY deps and adds them to the same transaction -* Maybe add a way how users can "pin" units into memory, so that they are not subject to automatic GC? - * PID1: find a way how we can reload unit file configuration for specific units only, without reloading the whole of systemd -- cgit v1.2.3-54-g00ecf From fbb4603d487d329bdd7aff744ff9ba7a7c2a2965 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 17:19:12 +0200 Subject: sd-bus: optionally, exit process or event loop on disconnect Old libdbus has a feature that the process is terminated whenever the the bus connection receives a disconnect. This is pretty useful on desktop apps (where a disconnect indicates session termination), as well as on command line apps (where we really shouldn't stay hanging in most cases if dbus daemon goes down). Add a similar feature to sd-bus, but make it opt-in rather than opt-out, like it is on libdbus. Also, if the bus is attached to an event loop just exit the event loop rather than the the whole process. --- src/libsystemd/libsystemd.sym | 2 ++ src/libsystemd/sd-bus/bus-internal.h | 3 +++ src/libsystemd/sd-bus/sd-bus.c | 47 ++++++++++++++++++++++++++++++++++++ src/systemd/sd-bus.h | 2 ++ 4 files changed, 54 insertions(+) diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index ae60e346eb..70ea347361 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -507,4 +507,6 @@ global: sd_bus_track_get_recursive; sd_bus_track_count_name; sd_bus_track_count_sender; + sd_bus_set_exit_on_disconnect; + sd_bus_get_exit_on_disconnect; } LIBSYSTEMD_231; diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 13357075bf..2608f5469c 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -209,6 +209,9 @@ struct sd_bus { bool is_system:1; bool is_user:1; bool allow_interactive_authorization:1; + bool exit_on_disconnect:1; + bool exited:1; + bool exit_triggered:1; int use_memfd; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 6ee5f82e12..d746348544 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -2641,6 +2641,31 @@ null_message: return r; } +static int bus_exit_now(sd_bus *bus) { + assert(bus); + + /* Exit due to close, if this is requested. If this is bus object is attached to an event source, invokes + * sd_event_exit(), otherwise invokes libc exit(). */ + + if (bus->exited) /* did we already exit? */ + return 0; + if (!bus->exit_triggered) /* was the exit condition triggered? */ + return 0; + if (!bus->exit_on_disconnect) /* Shall we actually exit on disconnection? */ + return 0; + + bus->exited = true; /* never exit more than once */ + + log_debug("Bus connection disconnected, exiting."); + + if (bus->event) + return sd_event_exit(bus->event, EXIT_FAILURE); + else + exit(EXIT_FAILURE); + + assert_not_reached("exit() didn't exit?"); +} + static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c) { _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; @@ -2742,6 +2767,10 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) { if (r != 0) goto finish; + /* Nothing else to do, exit now, if the condition holds */ + bus->exit_triggered = true; + (void) bus_exit_now(bus); + if (ret) { *ret = m; m = NULL; @@ -3804,3 +3833,21 @@ _public_ void sd_bus_default_flush_close(void) { flush_close(default_user_bus); flush_close(default_system_bus); } + +_public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + + /* Turns on exit-on-disconnect, and triggers it immediately if the bus connection was already + * disconnected. Note that this is triggered exclusively on disconnections triggered by the server side, never + * from the client side. */ + bus->exit_on_disconnect = b; + + /* If the exit condition was triggered already, exit immediately. */ + return bus_exit_now(bus); +} + +_public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) { + assert_return(bus, -EINVAL); + + return bus->exit_on_disconnect; +} diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 0305c56a8c..c47459c9ad 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -147,6 +147,8 @@ int sd_bus_can_send(sd_bus *bus, char type); int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *creds_mask); int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b); int sd_bus_get_allow_interactive_authorization(sd_bus *bus); +int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b); +int sd_bus_get_exit_on_disconnect(sd_bus *bus); int sd_bus_start(sd_bus *ret); -- cgit v1.2.3-54-g00ecf From 383034987de71927683dd34896ca7f3c9c259f7c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 17:21:27 +0200 Subject: bus-util: turn on exit-on-disconnect for all command line tools bus_connect_transport() is exclusively used from our command line tools, hence let's set exit-on-disconnect for all of them, making behaviour a bit nicer in case dbus-daemon goes down. --- src/shared/bus-util.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index fd42605b3e..e2a216a5cc 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1230,12 +1230,13 @@ int bus_map_all_properties( return bus_message_map_all_properties(m, map, userdata); } -int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) { +int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) { + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; int r; assert(transport >= 0); assert(transport < _BUS_TRANSPORT_MAX); - assert(bus); + assert(ret); assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL); assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP); @@ -1244,25 +1245,34 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s case BUS_TRANSPORT_LOCAL: if (user) - r = sd_bus_default_user(bus); + r = sd_bus_default_user(&bus); else - r = sd_bus_default_system(bus); + r = sd_bus_default_system(&bus); break; case BUS_TRANSPORT_REMOTE: - r = sd_bus_open_system_remote(bus, host); + r = sd_bus_open_system_remote(&bus, host); break; case BUS_TRANSPORT_MACHINE: - r = sd_bus_open_system_machine(bus, host); + r = sd_bus_open_system_machine(&bus, host); break; default: assert_not_reached("Hmm, unknown transport type."); } + if (r < 0) + return r; - return r; + r = sd_bus_set_exit_on_disconnect(bus, true); + if (r < 0) + return r; + + *ret = bus; + bus = NULL; + + return 0; } int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) { -- cgit v1.2.3-54-g00ecf From 83f12b27d14853e7c89a326f7cd31a6c739d378e Mon Sep 17 00:00:00 2001 From: Felipe Sateler Date: Mon, 22 Aug 2016 16:40:58 -0300 Subject: core: do not fail at step SECCOMP if there is no kernel support (#4004) Fixes #3882 --- src/core/execute.c | 38 ++++++++++++++++++++++++++++++-------- src/core/main.c | 6 ++++++ src/shared/seccomp-util.c | 10 ++++++++++ src/shared/seccomp-util.h | 2 ++ src/test/test-execute.c | 11 ++++++++++- 5 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 0af8eb5a02..55f15d7e49 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1074,7 +1074,17 @@ static void rename_process_from_path(const char *path) { #ifdef HAVE_SECCOMP -static int apply_seccomp(const ExecContext *c) { +static bool skip_seccomp_unavailable(const Unit* u, const char* msg) { + if (!is_seccomp_available()) { + log_open(); + log_unit_debug(u, "SECCOMP not detected in the kernel, skipping %s", msg); + log_close(); + return true; + } + return false; +} + +static int apply_seccomp(const Unit* u, const ExecContext *c) { uint32_t negative_action, action; scmp_filter_ctx *seccomp; Iterator i; @@ -1083,6 +1093,9 @@ static int apply_seccomp(const ExecContext *c) { assert(c); + if (skip_seccomp_unavailable(u, "syscall filtering")) + return 0; + negative_action = c->syscall_errno == 0 ? SCMP_ACT_KILL : SCMP_ACT_ERRNO(c->syscall_errno); seccomp = seccomp_init(c->syscall_whitelist ? negative_action : SCMP_ACT_ALLOW); @@ -1123,13 +1136,16 @@ finish: return r; } -static int apply_address_families(const ExecContext *c) { +static int apply_address_families(const Unit* u, const ExecContext *c) { scmp_filter_ctx *seccomp; Iterator i; int r; assert(c); + if (skip_seccomp_unavailable(u, "RestrictAddressFamilies=")) + return 0; + seccomp = seccomp_init(SCMP_ACT_ALLOW); if (!seccomp) return -ENOMEM; @@ -1244,12 +1260,15 @@ finish: return r; } -static int apply_memory_deny_write_execute(const ExecContext *c) { +static int apply_memory_deny_write_execute(const Unit* u, const ExecContext *c) { scmp_filter_ctx *seccomp; int r; assert(c); + if (skip_seccomp_unavailable(u, "MemoryDenyWriteExecute=")) + return 0; + seccomp = seccomp_init(SCMP_ACT_ALLOW); if (!seccomp) return -ENOMEM; @@ -1283,7 +1302,7 @@ finish: return r; } -static int apply_restrict_realtime(const ExecContext *c) { +static int apply_restrict_realtime(const Unit* u, const ExecContext *c) { static const int permitted_policies[] = { SCHED_OTHER, SCHED_BATCH, @@ -1296,6 +1315,9 @@ static int apply_restrict_realtime(const ExecContext *c) { assert(c); + if (skip_seccomp_unavailable(u, "RestrictRealtime=")) + return 0; + seccomp = seccomp_init(SCMP_ACT_ALLOW); if (!seccomp) return -ENOMEM; @@ -2403,7 +2425,7 @@ static int exec_child( #ifdef HAVE_SECCOMP if (use_address_families) { - r = apply_address_families(context); + r = apply_address_families(unit, context); if (r < 0) { *exit_status = EXIT_ADDRESS_FAMILIES; return r; @@ -2411,7 +2433,7 @@ static int exec_child( } if (context->memory_deny_write_execute) { - r = apply_memory_deny_write_execute(context); + r = apply_memory_deny_write_execute(unit, context); if (r < 0) { *exit_status = EXIT_SECCOMP; return r; @@ -2419,7 +2441,7 @@ static int exec_child( } if (context->restrict_realtime) { - r = apply_restrict_realtime(context); + r = apply_restrict_realtime(unit, context); if (r < 0) { *exit_status = EXIT_SECCOMP; return r; @@ -2427,7 +2449,7 @@ static int exec_child( } if (use_syscall_filter) { - r = apply_seccomp(context); + r = apply_seccomp(unit, context); if (r < 0) { *exit_status = EXIT_SECCOMP; return r; diff --git a/src/core/main.c b/src/core/main.c index 125cfb28f0..7d8322ebd8 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -72,6 +72,9 @@ #include "process-util.h" #include "raw-clone.h" #include "rlimit-util.h" +#ifdef HAVE_SECCOMP +#include "seccomp-util.h" +#endif #include "selinux-setup.h" #include "selinux-util.h" #include "signal-util.h" @@ -1186,6 +1189,9 @@ static int enforce_syscall_archs(Set *archs) { void *id; int r; + if (!is_seccomp_available()) + return 0; + seccomp = seccomp_init(SCMP_ACT_ALLOW); if (!seccomp) return log_oom(); diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 8656d112b8..4667f508c7 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -21,6 +21,8 @@ #include #include +#include "alloc-util.h" +#include "fileio.h" #include "macro.h" #include "seccomp-util.h" #include "string-util.h" @@ -89,6 +91,14 @@ int seccomp_add_secondary_archs(scmp_filter_ctx *c) { } +bool is_seccomp_available(void) { + _cleanup_free_ char* field = NULL; + static int cached_enabled = -1; + if (cached_enabled < 0) + cached_enabled = get_proc_field("/proc/self/status", "Seccomp", "\n", &field) == 0; + return cached_enabled; +} + const SystemCallFilterSet syscall_filter_sets[] = { { /* Clock */ diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h index be33eecb85..cca7c17912 100644 --- a/src/shared/seccomp-util.h +++ b/src/shared/seccomp-util.h @@ -27,6 +27,8 @@ int seccomp_arch_from_string(const char *n, uint32_t *ret); int seccomp_add_secondary_archs(scmp_filter_ctx *c); +bool is_seccomp_available(void); + typedef struct SystemCallFilterSet { const char *set_name; const char *value; diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 1d24115b5c..05ec1d2eb1 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -30,6 +30,9 @@ #include "mkdir.h" #include "path-util.h" #include "rm-rf.h" +#ifdef HAVE_SECCOMP +#include "seccomp-util.h" +#endif #include "test-helper.h" #include "unit.h" #include "util.h" @@ -132,21 +135,27 @@ static void test_exec_privatedevices(Manager *m) { static void test_exec_systemcallfilter(Manager *m) { #ifdef HAVE_SECCOMP + if (!is_seccomp_available()) + return; test(m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED); test(m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED); test(m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED); test(m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED); + #endif } static void test_exec_systemcallerrornumber(Manager *m) { #ifdef HAVE_SECCOMP - test(m, "exec-systemcallerrornumber.service", 1, CLD_EXITED); + if (is_seccomp_available()) + test(m, "exec-systemcallerrornumber.service", 1, CLD_EXITED); #endif } static void test_exec_systemcall_system_mode_with_user(Manager *m) { #ifdef HAVE_SECCOMP + if (!is_seccomp_available()) + return; if (getpwnam("nobody")) test(m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED); else if (getpwnam("nfsnobody")) -- cgit v1.2.3-54-g00ecf From 8dec4a9d2d8301102e12f8cf1d9a646e685fb1ea Mon Sep 17 00:00:00 2001 From: Felipe Sateler Date: Tue, 23 Aug 2016 06:29:30 -0300 Subject: core,network: Use const qualifiers for block-local variables in macro functions (#4019) Prevents discard-qualifiers warnings when the passed variable was const --- src/core/selinux-access.h | 2 +- src/core/unit.h | 2 +- src/network/networkd-link.h | 2 +- src/network/networkd-netdev.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/selinux-access.h b/src/core/selinux-access.h index 8f1f058a32..f46370d020 100644 --- a/src/core/selinux-access.h +++ b/src/core/selinux-access.h @@ -33,7 +33,7 @@ int mac_selinux_generic_access_check(sd_bus_message *message, const char *path, #define mac_selinux_unit_access_check(unit, message, permission, error) \ ({ \ - Unit *_unit = (unit); \ + const Unit *_unit = (unit); \ mac_selinux_generic_access_check((message), _unit->source_path ?: _unit->fragment_path, (permission), (error)); \ }) diff --git a/src/core/unit.h b/src/core/unit.h index 53875653d7..f7a65782f1 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -639,7 +639,7 @@ void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid); #define log_unit_full(unit, level, error, ...) \ ({ \ - Unit *_u = (unit); \ + const Unit *_u = (unit); \ _u ? log_object_internal(level, error, __FILE__, __LINE__, __func__, _u->manager->unit_log_field, _u->id, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 2809b1fe0b..05b2a2b323 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -186,7 +186,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); #define log_link_full(link, level, error, ...) \ ({ \ - Link *_l = (link); \ + const Link *_l = (link); \ _l ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) \ diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h index b92a973b85..09863e72b4 100644 --- a/src/network/networkd-netdev.h +++ b/src/network/networkd-netdev.h @@ -180,7 +180,7 @@ const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsign #define log_netdev_full(netdev, level, error, ...) \ ({ \ - NetDev *_n = (netdev); \ + const NetDev *_n = (netdev); \ _n ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _n->ifname, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) -- cgit v1.2.3-54-g00ecf From 3e3ddccf08c0a74177914dfc2c0d5196d7c6d67a Mon Sep 17 00:00:00 2001 From: Balázs Úr Date: Tue, 23 Aug 2016 20:08:35 +0200 Subject: Updated Hungarian translation (#4026) --- po/hu.po | 110 +++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 61 insertions(+), 49 deletions(-) diff --git a/po/hu.po b/po/hu.po index 88fecbc506..b92921707f 100644 --- a/po/hu.po +++ b/po/hu.po @@ -3,20 +3,21 @@ # This file is distributed under the same license as the systemd package. # # Gabor Kelemen , 2015, 2016. +# Balázs Úr , 2016. msgid "" msgstr "" "Project-Id-Version: systemd master\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-01-02 13:41+0100\n" -"PO-Revision-Date: 2016-01-02 13:45+0100\n" -"Last-Translator: Gabor Kelemen \n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2016-04-24 12:53+0000\n" +"PO-Revision-Date: 2016-08-23 18:03+0100\n" +"Last-Translator: Balázs Úr \n" "Language-Team: Hungarian \n" "Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Lokalize 1.5\n" +"X-Generator: Lokalize 2.0\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" @@ -241,50 +242,60 @@ msgstr "" "kezelésének meggátlásához." #: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in user to run programs" +msgstr "Programfuttatás engedélyezése be nem jelentkezett felhasználó számára" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Határozott kérés szükséges a programfuttatáshoz be nem jelentkezett " +"felhasználóként." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow non-logged-in users to run programs" msgstr "Programfuttatás engedélyezése be nem jelentkezett felhasználók számára" -#: ../src/login/org.freedesktop.login1.policy.in.h:20 +#: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" "Hitelesítés szükséges a programfuttatáshoz be nem jelentkezett " "felhasználóként." -#: ../src/login/org.freedesktop.login1.policy.in.h:21 +#: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Allow attaching devices to seats" msgstr "Eszközök csatolásának engedélyezése munkaállomásokhoz" -#: ../src/login/org.freedesktop.login1.policy.in.h:22 +#: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "Authentication is required for attaching a device to a seat." msgstr "" "Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy " "munkaállomáshoz" -#: ../src/login/org.freedesktop.login1.policy.in.h:23 +#: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Flush device to seat attachments" msgstr "Eszközök és munkaállomások csatolásainak törlése" -#: ../src/login/org.freedesktop.login1.policy.in.h:24 +#: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Hitelesítés szükséges az eszközök munkaállomásokhoz csatolásainak " "alaphelyzetbe állításához." -#: ../src/login/org.freedesktop.login1.policy.in.h:25 +#: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system" msgstr "A rendszer kikapcsolása" -#: ../src/login/org.freedesktop.login1.policy.in.h:26 +#: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "Authentication is required for powering off the system." msgstr "Hitelesítés szükséges a rendszer kikapcsolásához." -#: ../src/login/org.freedesktop.login1.policy.in.h:27 +#: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while other users are logged in" msgstr "" "A rendszer kikapcsolása miközben be vannak jelentkezve más felhasználók" -#: ../src/login/org.freedesktop.login1.policy.in.h:28 +#: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while other users are " "logged in." @@ -292,12 +303,12 @@ msgstr "" "Hitelesítés szükséges a rendszer kikapcsolásához miközben be vannak " "jelentkezve más felhasználók." -#: ../src/login/org.freedesktop.login1.policy.in.h:29 +#: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Power off the system while an application asked to inhibit it" msgstr "" "A rendszer kikapcsolása miközben egy alkalmazás ennek meggátlását kérte" -#: ../src/login/org.freedesktop.login1.policy.in.h:30 +#: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." @@ -305,19 +316,19 @@ msgstr "" "Hitelesítés szükséges a rendszer kikapcsolásához miközben egy alkalmazás " "ennek meggátlását kérte." -#: ../src/login/org.freedesktop.login1.policy.in.h:31 +#: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system" msgstr "A rendszer újraindítása" -#: ../src/login/org.freedesktop.login1.policy.in.h:32 +#: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "Authentication is required for rebooting the system." msgstr "Hitelesítés szükséges a rendszer újraindításához." -#: ../src/login/org.freedesktop.login1.policy.in.h:33 +#: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while other users are logged in" msgstr "A rendszer újraindítása mialatt be vannak jelentkezve más felhasználók" -#: ../src/login/org.freedesktop.login1.policy.in.h:34 +#: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." @@ -325,12 +336,12 @@ msgstr "" "Hitelesítés szükséges a rendszer újraindításához miközben be vannak " "jelentkezve más felhasználók." -#: ../src/login/org.freedesktop.login1.policy.in.h:35 +#: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Reboot the system while an application asked to inhibit it" msgstr "" "A rendszer újraindítása miközben egy alkalmazás ennek meggátlását kérte" -#: ../src/login/org.freedesktop.login1.policy.in.h:36 +#: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." @@ -338,20 +349,20 @@ msgstr "" "Hitelesítés szükséges a rendszer újraindításához miközben egy alkalmazás " "ennek meggátlását kérte." -#: ../src/login/org.freedesktop.login1.policy.in.h:37 +#: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system" msgstr "A rendszer felfüggesztése" -#: ../src/login/org.freedesktop.login1.policy.in.h:38 +#: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "Authentication is required for suspending the system." msgstr "Hitelesítés szükséges a rendszer felfüggesztéséhez." -#: ../src/login/org.freedesktop.login1.policy.in.h:39 +#: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while other users are logged in" msgstr "" "A rendszer felfüggesztése mialatt be vannak jelentkezve más felhasználók" -#: ../src/login/org.freedesktop.login1.policy.in.h:40 +#: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while other users are " "logged in." @@ -359,12 +370,12 @@ msgstr "" "Hitelesítés szükséges a rendszer felfüggesztéséhez miközben be vannak " "jelentkezve más felhasználók." -#: ../src/login/org.freedesktop.login1.policy.in.h:41 +#: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Suspend the system while an application asked to inhibit it" msgstr "" "A rendszer felfüggesztése miközben egy alkalmazás ennek meggátlását kérte" -#: ../src/login/org.freedesktop.login1.policy.in.h:42 +#: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." @@ -372,19 +383,19 @@ msgstr "" "Hitelesítés szükséges a rendszer felfüggesztéséhez miközben egy alkalmazás " "ennek meggátlását kérte." -#: ../src/login/org.freedesktop.login1.policy.in.h:43 +#: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system" msgstr "A rendszer hibernálása" -#: ../src/login/org.freedesktop.login1.policy.in.h:44 +#: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "Authentication is required for hibernating the system." msgstr "Hitelesítés szükséges a rendszer hibernálásához." -#: ../src/login/org.freedesktop.login1.policy.in.h:45 +#: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while other users are logged in" msgstr "A rendszer hibernálása mialatt be vannak jelentkezve más felhasználók" -#: ../src/login/org.freedesktop.login1.policy.in.h:46 +#: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." @@ -392,11 +403,11 @@ msgstr "" "Hitelesítés szükséges a rendszer hibernálásához miközben be vannak " "jelentkezve más felhasználók." -#: ../src/login/org.freedesktop.login1.policy.in.h:47 +#: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Hibernate the system while an application asked to inhibit it" msgstr "A rendszer hibernálása miközben egy alkalmazás ennek meggátlását kérte" -#: ../src/login/org.freedesktop.login1.policy.in.h:48 +#: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" "Authentication is required for hibernating the system while an application " "asked to inhibit it." @@ -404,31 +415,31 @@ msgstr "" "Hitelesítés szükséges a rendszer hibernálásához miközben egy alkalmazás " "ennek meggátlását kérte." -#: ../src/login/org.freedesktop.login1.policy.in.h:49 +#: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Manage active sessions, users and seats" msgstr "Aktív munkamenetek, felhasználók és munkaállomások kezelése" -#: ../src/login/org.freedesktop.login1.policy.in.h:50 +#: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Hitelesítés szükséges az aktív munkamenetek, felhasználók és munkaállomások " "kezeléséhez." -#: ../src/login/org.freedesktop.login1.policy.in.h:51 +#: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Lock or unlock active sessions" msgstr "Aktív munkamenetek zárolása vagy feloldása" -#: ../src/login/org.freedesktop.login1.policy.in.h:52 +#: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "Authentication is required to lock or unlock active sessions." msgstr "" "Hitelesítés szükséges az aktív munkamenetek zárolásához vagy feloldásához." -#: ../src/login/org.freedesktop.login1.policy.in.h:53 +#: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Allow indication to the firmware to boot to setup interface" msgstr "A firmware-nek jelezhető, hogy a beállítófelületet bootolja" -#: ../src/login/org.freedesktop.login1.policy.in.h:54 +#: ../src/login/org.freedesktop.login1.policy.in.h:56 msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." @@ -436,11 +447,11 @@ msgstr "" "Hitelesítés szükséges a firmware-nek jelzéshez, hogy a beállítófelületet " "bootolja" -#: ../src/login/org.freedesktop.login1.policy.in.h:55 +#: ../src/login/org.freedesktop.login1.policy.in.h:57 msgid "Set a wall message" msgstr "Falüzenet beállítása" -#: ../src/login/org.freedesktop.login1.policy.in.h:56 +#: ../src/login/org.freedesktop.login1.policy.in.h:58 msgid "Authentication is required to set a wall message" msgstr "Hitelesítés szükséges a falüzenet beállításához" @@ -552,33 +563,34 @@ msgid "" "shall be enabled." msgstr "Hitelesítés szükséges a hálózati időszinkronizáció engedélyezéséhez." -#: ../src/core/dbus-unit.c:449 +#: ../src/core/dbus-unit.c:450 msgid "Authentication is required to start '$(unit)'." msgstr "Hitelesítés szükséges a következő elindításához: „$(unit)”." -#: ../src/core/dbus-unit.c:450 +#: ../src/core/dbus-unit.c:451 msgid "Authentication is required to stop '$(unit)'." msgstr "Hitelesítés szükséges a következő leállításához: „$(unit)”." -#: ../src/core/dbus-unit.c:451 +#: ../src/core/dbus-unit.c:452 msgid "Authentication is required to reload '$(unit)'." msgstr "Hitelesítés szükséges a következő újratöltéséhez: „$(unit)”." -#: ../src/core/dbus-unit.c:452 ../src/core/dbus-unit.c:453 +#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 msgid "Authentication is required to restart '$(unit)'." msgstr "Hitelesítés szükséges a következő újraindításához: „$(unit)”." -#: ../src/core/dbus-unit.c:556 +#: ../src/core/dbus-unit.c:560 msgid "Authentication is required to kill '$(unit)'." msgstr "Hitelesítés szükséges a következő kilövéséhez: „$(unit)”." -#: ../src/core/dbus-unit.c:586 +#: ../src/core/dbus-unit.c:590 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "Hitelesítés szükséges a következő „sikertelen” állapotának törléséhez: " "„$(unit)”." -#: ../src/core/dbus-unit.c:618 +#: ../src/core/dbus-unit.c:622 msgid "Authentication is required to set properties on '$(unit)'." msgstr "" "Hitelesítés szükséges a következő tulajdonságainak beállításához: „$(unit)”." + -- cgit v1.2.3-54-g00ecf From 769c29d5d12532e81c983d9946961ce084609571 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 24 Aug 2016 20:11:48 +1000 Subject: hwdb: add axis ranges for the MacBook 4,1 (#4030) https://bugzilla.redhat.com/show_bug.cgi?id=1357990 --- hwdb/60-evdev.hwdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb index 1606c66bbe..a5eba52224 100644 --- a/hwdb/60-evdev.hwdb +++ b/hwdb/60-evdev.hwdb @@ -45,6 +45,8 @@ # Macbook2,1 (late 2006), single-button touchpad evdev:input:b0003v05ACp021B* +# Macbook4,1 +evdev:input:b0003v05ACp0229* EVDEV_ABS_00=256:1471:12 EVDEV_ABS_01=256:831:12 -- cgit v1.2.3-54-g00ecf From 3dea75dead5d3b229c9780de63479ea0aa655ba5 Mon Sep 17 00:00:00 2001 From: Nick Owens Date: Wed, 24 Aug 2016 03:12:18 -0700 Subject: run: respect quiet when starting timer (#4029) --- src/run/run.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/run/run.c b/src/run/run.c index 0797547684..e8586ef61a 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -1185,9 +1185,11 @@ static int start_transient_timer( if (r < 0) return r; - log_info("Running timer as unit: %s", timer); - if (argv[0]) - log_info("Will run service as unit: %s", service); + if (!arg_quiet) { + log_info("Running timer as unit: %s", timer); + if (argv[0]) + log_info("Will run service as unit: %s", service); + } return 0; } -- cgit v1.2.3-54-g00ecf From b74d0fdf79db9b16b217832a052dbdd0e2f48b3d Mon Sep 17 00:00:00 2001 From: Stefan Date: Wed, 24 Aug 2016 20:49:53 +0200 Subject: docs: add --with-support-url= to distribution porting guide. (#4035) --- DISTRO_PORTING | 1 + 1 file changed, 1 insertion(+) diff --git a/DISTRO_PORTING b/DISTRO_PORTING index 07aea865be..a397d700c6 100644 --- a/DISTRO_PORTING +++ b/DISTRO_PORTING @@ -15,6 +15,7 @@ HOWTO: --with-kbd-setfont= --with-tty-gid= --with-ntp-servers= + --with-support-url= 2) Try it out. Play around (as an ordinary user) with '/usr/lib/systemd/systemd --test --system' for a test run -- cgit v1.2.3-54-g00ecf From 1ef72b55ba6d38f879d7ac9f0237cf8a2b53f0e6 Mon Sep 17 00:00:00 2001 From: Michal Sekletar Date: Thu, 25 Aug 2016 08:18:42 +0200 Subject: udev: inform systemd how many workers we can potentially spawn (#4036) --- src/udev/udevd.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/udev/udevd.c b/src/udev/udevd.c index a893a2b3d9..19f1c29198 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -776,9 +776,9 @@ static void manager_reload(Manager *manager) { manager->rules = udev_rules_unref(manager->rules); udev_builtin_exit(manager->udev); - sd_notify(false, - "READY=1\n" - "STATUS=Processing..."); + sd_notifyf(false, + "READY=1\n" + "STATUS=Processing with %u children at max", arg_children_max); } static void event_queue_start(Manager *manager) { @@ -1000,6 +1000,10 @@ static int on_ctrl_msg(sd_event_source *s, int fd, uint32_t revents, void *userd if (i >= 0) { log_debug("udevd message (SET_MAX_CHILDREN) received, children_max=%i", i); arg_children_max = i; + + (void) sd_notifyf(false, + "READY=1\n" + "STATUS=Processing with %u children at max", arg_children_max); } if (udev_ctrl_get_ping(ctrl_msg) > 0) @@ -1627,9 +1631,9 @@ static int run(int fd_ctrl, int fd_uevent, const char *cgroup) { if (r < 0) log_error_errno(r, "failed to apply permissions on static device nodes: %m"); - (void) sd_notify(false, - "READY=1\n" - "STATUS=Processing..."); + (void) sd_notifyf(false, + "READY=1\n" + "STATUS=Processing with %u children at max", arg_children_max); r = sd_event_loop(manager->event); if (r < 0) { -- cgit v1.2.3-54-g00ecf From c436d553973b43ec5e8cf2eab84dd3e9e334295f Mon Sep 17 00:00:00 2001 From: Mantas Mikulėnas Date: Wed, 24 Aug 2016 18:26:48 +0300 Subject: networkd: do not drop config for unmanaged interfaces Flushing foreign configuration for unmanaged interfaces is outright evil, especially when it's a regular occurence with Wi-Fi. Fixes: 3104883ddc24 "networkd: remove route if carrier is lost" Ref: #3831 --- src/network/networkd-link.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 71484e3288..aab40a0eb1 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2957,9 +2957,11 @@ static int link_carrier_lost(Link *link) { if (r < 0) return r; - r = link_drop_foreign_config(link); - if (r < 0) - return r; + if (link->state != LINK_STATE_UNMANAGED) { + r = link_drop_foreign_config(link); + if (r < 0) + return r; + } r = link_handle_bound_by_list(link); if (r < 0) -- cgit v1.2.3-54-g00ecf From 929eeb5498e8ae87e05ae683c6d3014d4b59056d Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Thu, 25 Aug 2016 08:37:57 -0700 Subject: journal: implicitly flush to var on recovery (#4028) When the system journal becomes re-opened post-flush with the runtime journal open, it implies we've recovered from something like an ENOSPC situation where the system journal rotate had failed, leaving the system journal closed, causing the runtime journal to be opened post-flush. For the duration of the unavailable system journal, we log to the runtime journal. But when the system journal gets opened (space made available, for example), we need to close the runtime journal before new journal writes will go to the system journal. Calling server_flush_to_var() after opening the system journal with a runtime journal present, post-flush, achieves this while preserving the runtime journal's contents in the system journal. The combination of the present flushed flag file and the runtime journal being open is a state where we should be logging to the system journal, so it's appropriate to resume doing so once we've successfully opened the system journal. --- src/journal/journald-server.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 2a043a95b1..ca47d64fe0 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -268,13 +268,14 @@ static int open_journal( } static int system_journal_open(Server *s, bool flush_requested) { + bool flushed = false; const char *fn; int r = 0; if (!s->system_journal && (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) && (flush_requested - || access("/run/systemd/journal/flushed", F_OK) >= 0)) { + || (flushed = (access("/run/systemd/journal/flushed", F_OK) >= 0)))) { /* If in auto mode: first try to create the machine * path, but not the prefix. @@ -299,6 +300,16 @@ static int system_journal_open(Server *s, bool flush_requested) { r = 0; } + + /* If the runtime journal is open, and we're post-flush, we're + * recovering from a failed system journal rotate (ENOSPC) + * for which the runtime journal was reopened. + * + * Perform an implicit flush to var, leaving the runtime + * journal closed, now that the system journal is back. + */ + if (s->runtime_journal && flushed) + (void) server_flush_to_var(s); } if (!s->runtime_journal && @@ -1294,7 +1305,7 @@ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo * log_info("Received request to flush runtime journal from PID " PID_FMT, si->ssi_pid); - server_flush_to_var(s); + (void) server_flush_to_var(s); server_sync(s); server_vacuum(s, false, false); -- cgit v1.2.3-54-g00ecf From 51bce29f8eee1cdc0eb25c8fe87e69e24b5fbd98 Mon Sep 17 00:00:00 2001 From: Michal Sekletar Date: Fri, 26 Aug 2016 00:07:58 +0200 Subject: units: remove udev control socket when systemd stops the socket unit (#4039) Mere presence of the socket in the filesystem makes udev_queue_get_udev_is_active() return that udev is running. Note that, udev on exit doesn't unlink control socket nor does systemd. Thus socket stays around even when both daemon and socket are stopped. This causes problems for cryptsetup because when it detects running udev it launches synchronous operations that *really* require udev. This in turn may cause blocking and subsequent timeout in systemd-cryptsetup on reboot while machine is in a state that udev and its control socket units are stopped, e.g. emergency mode. Fixes #2477 --- units/systemd-udevd-control.socket | 1 + 1 file changed, 1 insertion(+) diff --git a/units/systemd-udevd-control.socket b/units/systemd-udevd-control.socket index 8330a1c035..46f704ed79 100644 --- a/units/systemd-udevd-control.socket +++ b/units/systemd-udevd-control.socket @@ -17,3 +17,4 @@ Service=systemd-udevd.service ListenSequentialPacket=/run/udev/control SocketMode=0600 PassCredentials=yes +RemoveOnStop=yes -- cgit v1.2.3-54-g00ecf From 0c582db0c6ec3330953270cf0324038cb6615617 Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Thu, 25 Aug 2016 22:08:26 +0000 Subject: nspawn: split down SYSTEMD_NSPAWN_SHARE_SYSTEM (#4023) This commit follows further on the deprecation path for --share-system, by splitting and gating each share-able namespace behind its own environment flag. --- src/nspawn/nspawn.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 24d243109a..6d0420965a 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -169,7 +169,6 @@ static CustomMount *arg_custom_mounts = NULL; static unsigned arg_n_custom_mounts = 0; static char **arg_setenv = NULL; static bool arg_quiet = false; -static bool arg_share_system = false; static bool arg_register = true; static bool arg_keep_unit = false; static char **arg_network_interfaces = NULL; @@ -195,6 +194,7 @@ static char **arg_parameters = NULL; static const char *arg_container_service_name = "systemd-nspawn"; static bool arg_notify_ready = false; static bool arg_use_cgns = true; +static unsigned long arg_clone_ns_flags = CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS; static void help(void) { printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n" @@ -352,6 +352,17 @@ static int detect_unified_cgroup_hierarchy(void) { return 0; } +static void parse_share_ns_env(const char *name, unsigned long ns_flag) { + int r; + + r = getenv_bool(name); + if (r == -ENXIO) + return; + if (r < 0) + log_warning_errno(r, "Failed to parse %s from environment, defaulting to false.", name); + arg_clone_ns_flags = (arg_clone_ns_flags & ~ns_flag) | (r > 0 ? 0 : ns_flag); +} + static int parse_argv(int argc, char *argv[]) { enum { @@ -824,8 +835,8 @@ static int parse_argv(int argc, char *argv[]) { case ARG_SHARE_SYSTEM: /* We don't officially support this anymore, except for compat reasons. People should use the - * $SYSTEMD_NSPAWN_SHARE_SYSTEM environment variable instead. */ - arg_share_system = true; + * $SYSTEMD_NSPAWN_SHARE_* environment variables instead. */ + arg_clone_ns_flags = 0; break; case ARG_REGISTER: @@ -1029,20 +1040,22 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } - if (getenv_bool("SYSTEMD_NSPAWN_SHARE_SYSTEM") > 0) - arg_share_system = true; + parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_NS_IPC", CLONE_NEWIPC); + parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_NS_PID", CLONE_NEWPID); + parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_NS_UTS", CLONE_NEWUTS); + parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_SYSTEM", CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS); - if (arg_share_system) + if (arg_clone_ns_flags != (CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS)) { arg_register = false; + if (arg_start_mode != START_PID1) { + log_error("--boot cannot be used without namespacing."); + return -EINVAL; + } + } if (arg_userns_mode == USER_NAMESPACE_PICK) arg_userns_chown = true; - if (arg_start_mode != START_PID1 && arg_share_system) { - log_error("--boot and SYSTEMD_NSPAWN_SHARE_SYSTEM=1 may not be combined."); - return -EINVAL; - } - if (arg_keep_unit && cg_pid_get_owner_uid(0, NULL) >= 0) { log_error("--keep-unit may not be used when invoked from a user session."); return -EINVAL; @@ -1310,9 +1323,6 @@ static int setup_boot_id(const char *dest) { const char *from, *to; int r; - if (arg_share_system) - return 0; - /* Generate a new randomized boot ID, so that each boot-up of * the container gets a new one */ @@ -1530,7 +1540,7 @@ static int on_address_change(sd_netlink *rtnl, sd_netlink_message *m, void *user static int setup_hostname(void) { - if (arg_share_system) + if ((arg_clone_ns_flags & CLONE_NEWUTS) == 0) return 0; if (sethostname_idempotent(arg_machine) < 0) @@ -1681,7 +1691,7 @@ static int reset_audit_loginuid(void) { _cleanup_free_ char *p = NULL; int r; - if (arg_share_system) + if ((arg_clone_ns_flags & CLONE_NEWPID) == 0) return 0; r = read_one_line_file("/proc/self/loginuid", &p); @@ -3088,7 +3098,7 @@ static int outer_child( return fd; pid = raw_clone(SIGCHLD|CLONE_NEWNS| - (arg_share_system ? 0 : CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS) | + arg_clone_ns_flags | (arg_private_network ? CLONE_NEWNET : 0) | (arg_userns_mode != USER_NAMESPACE_NO ? CLONE_NEWUSER : 0)); if (pid < 0) -- cgit v1.2.3-54-g00ecf From 23cabb68acac12f4e17332f6b5696c8f7ac52d62 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Fri, 26 Aug 2016 18:49:56 +0300 Subject: tests: mount proc before `exec valgrind` (#4044) Fixes: $ sudo make run QEMU_BIN=/usr/bin/qemu-system-x86_64 KERNEL_APPEND=systemd.unit=multi-user.target SKIP_INITRD=yes TEST RUN: Basic systemd setup + /usr/bin/qemu-system-x86_64 -smp 1 -net none -m 512M -nographic -kernel /boot/vmlinuz-4.6.7-200.fc23.x86_64 -drive format=raw,cache=unsafe,file=/var/tmp/systemd-test.izx99J/rootdisk.img -append 'root=/dev/sda1 raid=noautodetect loglevel=2 init=/usr/lib/systemd/systemd-under-valgrind rw console=ttyS0 selinux=0 systemd.unified_cgroup_hierarchy=no systemd.unit=multi-user.target ' valgrind: warning (non-fatal): readlink("/proc/self/exe") failed. valgrind: continuing, however --trace-children=yes will not work. --1:0: aspacem Valgrind: FATAL: can't open /proc/self/maps --1:0: aspacem Exiting now. [ 3.152367] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100 [ 3.152367] [ 3.152367] CPU: 0 PID: 1 Comm: memcheck-amd64- Not tainted 4.6.7-200.fc23.x86_64 #1 [ 3.152367] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.8.2-20150714_191134- 04/01/2014 [ 3.152367] 0000000000000086 0000000047ca1666 ffff88001ea43e00 ffffffff813d954e [ 3.152367] ffffffff81a205a0 ffff88001ea43e98 ffff88001ea43e88 ffffffff811b5557 [ 3.152367] ffffffff00000010 ffff88001ea43e98 ffff88001ea43e30 0000000047ca1666 [ 3.152367] Call Trace: [ 3.152367] [] dump_stack+0x63/0x85 [ 3.152367] [] panic+0xde/0x220 [ 3.152367] [] do_exit+0xb43/0xb50 [ 3.152367] [] do_group_exit+0x47/0xb0 [ 3.152367] [] SyS_exit_group+0x14/0x20 [ 3.152367] [] entry_SYSCALL_64_fastpath+0x1a/0xa4 [ 3.152367] Kernel Offset: disabled [ 3.152367] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100 [ 3.152367] QEMU: Terminated --- test/test-functions | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test-functions b/test/test-functions index 567a000b8d..2a21a64c5c 100644 --- a/test/test-functions +++ b/test/test-functions @@ -225,6 +225,7 @@ create_valgrind_wrapper() { cat >$_valgrind_wrapper < Date: Fri, 26 Aug 2016 08:51:13 -0700 Subject: journal: add/use flushed_flag_is_set() helper (#4041) Minor cleanup suggested by Lennart. --- src/journal/journald-server.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index ca47d64fe0..3507910919 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -267,6 +267,10 @@ static int open_journal( return r; } +static bool flushed_flag_is_set(void) { + return (access("/run/systemd/journal/flushed", F_OK) >= 0); +} + static int system_journal_open(Server *s, bool flush_requested) { bool flushed = false; const char *fn; @@ -274,8 +278,7 @@ static int system_journal_open(Server *s, bool flush_requested) { if (!s->system_journal && (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) && - (flush_requested - || (flushed = (access("/run/systemd/journal/flushed", F_OK) >= 0)))) { + (flush_requested || (flushed = flushed_flag_is_set()))) { /* If in auto mode: first try to create the machine * path, but not the prefix. -- cgit v1.2.3-54-g00ecf From e520950a03419957875034bc27795b0b81d8e793 Mon Sep 17 00:00:00 2001 From: brulon Date: Fri, 26 Aug 2016 11:57:22 -0400 Subject: mount: add new LazyUnmount= setting for mount units, mapping to umount(8)'s "-l" switch (#3827) --- man/systemd.mount.xml | 13 +++++++++++++ src/core/dbus-mount.c | 1 + src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/mount.c | 8 ++++++-- src/core/mount.h | 2 ++ 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml index a38165f9b9..fa17f22dc3 100644 --- a/man/systemd.mount.xml +++ b/man/systemd.mount.xml @@ -351,6 +351,19 @@ off. + + LazyUnmount= + + Takes a boolean argument. If true, detach the + filesystem from the filesystem hierarchy at time of the unmount + operation, and clean up all references to the filesystem as + soon as they are not busy anymore. + This corresponds with + umount8's + -l switch. Defaults to + off. + + DirectoryMode= Directories of mount points (and any parent diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c index 3c6bda4073..4421f26bc1 100644 --- a/src/core/dbus-mount.c +++ b/src/core/dbus-mount.c @@ -116,6 +116,7 @@ const sd_bus_vtable bus_mount_vtable[] = { SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Mount, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Mount, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SloppyOptions", "b", bus_property_get_bool, offsetof(Mount, sloppy_options), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LazyUnmount", "b", bus_property_get_bool, offsetof(Mount, lazy_unmount), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 05fe0df7e3..420d32dbd7 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -355,6 +355,7 @@ Mount.Type, config_parse_string, 0, Mount.TimeoutSec, config_parse_sec, 0, offsetof(Mount, timeout_usec) Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode) Mount.SloppyOptions, config_parse_bool, 0, offsetof(Mount, sloppy_options) +Mount.LazyUnmount, config_parse_bool, 0, offsetof(Mount, lazy_unmount) EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl CGROUP_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl diff --git a/src/core/mount.c b/src/core/mount.c index f2ac8d171f..2c2a54edbb 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -677,7 +677,8 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { "%sOptions: %s\n" "%sFrom /proc/self/mountinfo: %s\n" "%sFrom fragment: %s\n" - "%sDirectoryMode: %04o\n", + "%sDirectoryMode: %04o\n" + "%sLazyUnmount: %s\n", prefix, mount_state_to_string(m->state), prefix, mount_result_to_string(m->result), prefix, m->where, @@ -686,7 +687,8 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { prefix, p ? strna(p->options) : "n/a", prefix, yes_no(m->from_proc_self_mountinfo), prefix, yes_no(m->from_fragment), - prefix, m->directory_mode); + prefix, m->directory_mode, + prefix, yes_no(m->lazy_unmount)); if (m->control_pid > 0) fprintf(f, @@ -846,6 +848,8 @@ static void mount_enter_unmounting(Mount *m) { m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT; r = exec_command_set(m->control_command, UMOUNT_PATH, m->where, NULL); + if (r >= 0 && m->lazy_unmount) + r = exec_command_append(m->control_command, "-l", NULL); if (r < 0) goto fail; diff --git a/src/core/mount.h b/src/core/mount.h index ac27b518cc..c4a2bff100 100644 --- a/src/core/mount.h +++ b/src/core/mount.h @@ -71,6 +71,8 @@ struct Mount { bool sloppy_options; + bool lazy_unmount; + MountResult result; MountResult reload_result; -- cgit v1.2.3-54-g00ecf From 2507992f6bec6ccb4d96abd1f55ba278a38b1723 Mon Sep 17 00:00:00 2001 From: Douglas Christman Date: Fri, 26 Aug 2016 12:13:16 -0400 Subject: load-fragment: Resolve specifiers in OnCalendar and On*Sec Resolves #3534 --- src/core/load-fragment.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index d5185cf6a0..d3fc3e36d9 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -1338,10 +1338,13 @@ int config_parse_timer(const char *unit, void *userdata) { Timer *t = data; - usec_t u = 0; + usec_t usec = 0; TimerValue *v; TimerBase b; CalendarSpec *c = NULL; + Unit *u = userdata; + _cleanup_free_ char *k = NULL; + int r; assert(filename); assert(lvalue); @@ -1360,14 +1363,20 @@ int config_parse_timer(const char *unit, return 0; } + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); + return 0; + } + if (b == TIMER_CALENDAR) { - if (calendar_spec_from_string(rvalue, &c) < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse calendar specification, ignoring: %s", rvalue); + if (calendar_spec_from_string(k, &c) < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse calendar specification, ignoring: %s", k); return 0; } } else { - if (parse_sec(rvalue, &u) < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer value, ignoring: %s", rvalue); + if (parse_sec(k, &usec) < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer value, ignoring: %s", k); return 0; } } @@ -1379,7 +1388,7 @@ int config_parse_timer(const char *unit, } v->base = b; - v->value = u; + v->value = usec; v->calendar_spec = c; LIST_PREPEND(value, t->values, v); -- cgit v1.2.3-54-g00ecf From 67684ba66517fec7ae7558edf7fd28f3aa9776f6 Mon Sep 17 00:00:00 2001 From: Erik Karlsson Date: Wed, 24 Aug 2016 20:18:22 +0200 Subject: hwdb: add axis range corrections for Lenovo Ideapad 500S-13ISK --- hwdb/60-evdev.hwdb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb index a5eba52224..4bed8d026d 100644 --- a/hwdb/60-evdev.hwdb +++ b/hwdb/60-evdev.hwdb @@ -240,6 +240,13 @@ evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapadY700-14ISK* EVDEV_ABS_35=::27 EVDEV_ABS_36=::29 +# Lenovo Ideapad 500S-13ISK +evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapad500S-13ISK* + EVDEV_ABS_00=125:3955:37 + EVDEV_ABS_01=104:1959:27 + EVDEV_ABS_35=125:3954:37 + EVDEV_ABS_36=104:1959:27 + ######################################### # Samsung ######################################### -- cgit v1.2.3-54-g00ecf From 4f8d40a9dc3d2dc754a30bc9455817ee6a857c62 Mon Sep 17 00:00:00 2001 From: Barron Rulon Date: Sat, 27 Aug 2016 10:27:49 -0400 Subject: mount: add new ForceUnmount= setting for mount units, mapping to umount(8)'s "-f" switch --- man/systemd.mount.xml | 11 +++++++++++ src/core/dbus-mount.c | 1 + src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/mount.c | 8 ++++++-- src/core/mount.h | 1 + 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml index fa17f22dc3..dd08feb5ad 100644 --- a/man/systemd.mount.xml +++ b/man/systemd.mount.xml @@ -364,6 +364,17 @@ off. + + ForceUnmount= + + Takes a boolean argument. If true, force an + unmount (in case of an unreachable NFS system). + This corresponds with + umount8's + -f switch. Defaults to + off. + + DirectoryMode= Directories of mount points (and any parent diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c index 4421f26bc1..76a7a7ce97 100644 --- a/src/core/dbus-mount.c +++ b/src/core/dbus-mount.c @@ -117,6 +117,7 @@ const sd_bus_vtable bus_mount_vtable[] = { SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Mount, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SloppyOptions", "b", bus_property_get_bool, offsetof(Mount, sloppy_options), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LazyUnmount", "b", bus_property_get_bool, offsetof(Mount, lazy_unmount), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ForceUnmount", "b", bus_property_get_bool, offsetof(Mount, force_unmount), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 420d32dbd7..057b92bfa3 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -356,6 +356,7 @@ Mount.TimeoutSec, config_parse_sec, 0, Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode) Mount.SloppyOptions, config_parse_bool, 0, offsetof(Mount, sloppy_options) Mount.LazyUnmount, config_parse_bool, 0, offsetof(Mount, lazy_unmount) +Mount.ForceUnmount, config_parse_bool, 0, offsetof(Mount, force_unmount) EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl CGROUP_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl diff --git a/src/core/mount.c b/src/core/mount.c index 2c2a54edbb..6c794d4073 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -678,7 +678,8 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { "%sFrom /proc/self/mountinfo: %s\n" "%sFrom fragment: %s\n" "%sDirectoryMode: %04o\n" - "%sLazyUnmount: %s\n", + "%sLazyUnmount: %s\n" + "%sForceUnmount: %s\n", prefix, mount_state_to_string(m->state), prefix, mount_result_to_string(m->result), prefix, m->where, @@ -688,7 +689,8 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { prefix, yes_no(m->from_proc_self_mountinfo), prefix, yes_no(m->from_fragment), prefix, m->directory_mode, - prefix, yes_no(m->lazy_unmount)); + prefix, yes_no(m->lazy_unmount), + prefix, yes_no(m->force_unmount)); if (m->control_pid > 0) fprintf(f, @@ -850,6 +852,8 @@ static void mount_enter_unmounting(Mount *m) { r = exec_command_set(m->control_command, UMOUNT_PATH, m->where, NULL); if (r >= 0 && m->lazy_unmount) r = exec_command_append(m->control_command, "-l", NULL); + if (r >= 0 && m->force_unmount) + r = exec_command_append(m->control_command, "-f", NULL); if (r < 0) goto fail; diff --git a/src/core/mount.h b/src/core/mount.h index c4a2bff100..9f7326ba6a 100644 --- a/src/core/mount.h +++ b/src/core/mount.h @@ -72,6 +72,7 @@ struct Mount { bool sloppy_options; bool lazy_unmount; + bool force_unmount; MountResult result; MountResult reload_result; -- cgit v1.2.3-54-g00ecf From 49915de2451a2ddbd2449a825c682b9731432895 Mon Sep 17 00:00:00 2001 From: Barron Rulon Date: Sat, 27 Aug 2016 10:42:05 -0400 Subject: mount: add SloppyOptions= to mount_dump() --- src/core/mount.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/mount.c b/src/core/mount.c index 6c794d4073..04025b83b9 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -678,6 +678,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { "%sFrom /proc/self/mountinfo: %s\n" "%sFrom fragment: %s\n" "%sDirectoryMode: %04o\n" + "%sSloppyOptions: %s\n" "%sLazyUnmount: %s\n" "%sForceUnmount: %s\n", prefix, mount_state_to_string(m->state), @@ -689,6 +690,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { prefix, yes_no(m->from_proc_self_mountinfo), prefix, yes_no(m->from_fragment), prefix, m->directory_mode, + prefix, yes_no(m->sloppy_options), prefix, yes_no(m->lazy_unmount), prefix, yes_no(m->force_unmount)); -- cgit v1.2.3-54-g00ecf From d9e76d1433891b39b4ac88a8cc54194d1f3209c4 Mon Sep 17 00:00:00 2001 From: Mantas Mikulėnas Date: Fri, 19 Aug 2016 21:33:28 +0300 Subject: hwdb: 60-keyboard: remove line causing a syntax error --- hwdb/60-keyboard.hwdb | 1 - 1 file changed, 1 deletion(-) diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb index 25caa60626..f7d5ac58d4 100644 --- a/hwdb/60-keyboard.hwdb +++ b/hwdb/60-keyboard.hwdb @@ -896,7 +896,6 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOLPC:pnXO:* KEYBOARD_KEY_c2=f8 KEYBOARD_KEY_c3=f9 KEYBOARD_KEY_c4=f10 - # KEYBOARD_KEY_c7=f11 # FIXME! KEYBOARD_KEY_d8=f12 KEYBOARD_KEY_f7=f13 KEYBOARD_KEY_f6=f14 -- cgit v1.2.3-54-g00ecf From 871583be952ccf7d19c0c3e489d94a4330a77a7c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 29 Aug 2016 11:02:36 +0900 Subject: man: systemd.mount: DefaultTimeoutStart -> DefaultTimeoutStartSec --- man/systemd.mount.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml index fa17f22dc3..bfdb3ce315 100644 --- a/man/systemd.mount.xml +++ b/man/systemd.mount.xml @@ -386,7 +386,7 @@ Takes a unit-less value in seconds, or a time span value such as "5min 20s". Pass 0 to disable the timeout logic. The default value is set from the manager configuration file's - DefaultTimeoutStart= + DefaultTimeoutStartSec= variable. -- cgit v1.2.3-54-g00ecf From de87760fde427c97763c87c8e88516ba2e4db8cc Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 29 Aug 2016 15:59:18 +0900 Subject: man: systemd-journal-remote: do not use ulink tags for example addresses Applying ulink tags to example addresses adds meaningless references in NOTES section of the man page. --- man/systemd-journal-remote.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/systemd-journal-remote.xml b/man/systemd-journal-remote.xml index 3899f175d4..f208f8deb4 100644 --- a/man/systemd-journal-remote.xml +++ b/man/systemd-journal-remote.xml @@ -121,8 +121,8 @@ ADDRESS. This URL should refer to the root of a remote systemd-journal-gatewayd8 - instance (e.g. http://some.host:19531/ or - https://some.host:19531/). + instance, e.g. http://some.host:19531/ or + https://some.host:19531/. -- cgit v1.2.3-54-g00ecf From 4a6d35237f96d07f3a783c874933f87bf14f93e0 Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Sun, 28 Aug 2016 16:26:04 +0200 Subject: importd/export-raw: needs missing.h for O_TMPFILE O_TMPFILE may be missing from the system headers, so use our fallback definition. --- Changes v1 -> v2: - move include with local includes --- src/import/export-raw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/import/export-raw.c b/src/import/export-raw.c index db06e11b87..6136b677dd 100644 --- a/src/import/export-raw.c +++ b/src/import/export-raw.c @@ -34,6 +34,7 @@ #include "fd-util.h" #include "fileio.h" #include "import-common.h" +#include "missing.h" #include "ratelimit.h" #include "string-util.h" #include "util.h" -- cgit v1.2.3-54-g00ecf From daad709a7c13c0fac73e407528f96cc876c09629 Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Sun, 28 Aug 2016 17:26:42 +0200 Subject: missing.h: add missing definitions for __O_TMPFILE Currently, a missing __O_TMPFILE was only defined for i386 and x86_64, leaving any other architectures with an "old" toolchain fail miserably at build time: src/import/export-raw.c: In function 'reflink_snapshot': src/import/export-raw.c:271:26: error: 'O_TMPFILE' undeclared (first use in this function) new_fd = open(d, O_TMPFILE|O_CLOEXEC|O_NOCTTY|O_RDWR, 0600); ^ __O_TMPFILE (and O_TMPFILE) are available since glibc 2.19. However, a lot of existing toolchains are still using glibc-2.18, and some even before that, and it is not really possible to update those toolchains. Instead of defining it only for i386 and x86_64, define __O_TMPFILE with the specific values for those archs where it is different from the generic value. Use the values as found in the Linux kernel (v4.8-rc3, current as of time of commit). --- Note: tested on ARM (build+run), with glibc-2.18 and linux headers 3.12. Untested on other archs, though (I have no board to test this). Changes v1 -> v2: - add a comment specifying some are hexa, others are octal. --- src/basic/missing.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/basic/missing.h b/src/basic/missing.h index f8e096605e..13ff51cd35 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -537,12 +537,21 @@ struct btrfs_ioctl_quota_ctl_args { # define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f) #endif -#if defined(__i386__) || defined(__x86_64__) - -/* The precise definition of __O_TMPFILE is arch specific, so let's - * just define this on x86 where we know the value. */ +/* The precise definition of __O_TMPFILE is arch specific; use the + * values defined by the kernel (note: some are hexa, some are octal, + * duplicated as-is from the kernel definitions): + * - alpha, parisc, sparc: each has a specific value; + * - others: they use the "generic" value. + */ #ifndef __O_TMPFILE +#if defined(__alpha__) +#define __O_TMPFILE 0100000000 +#elif defined(__parisc__) || defined(__hppa__) +#define __O_TMPFILE 0400000000 +#elif defined(__sparc__) || defined(__sparc64__) +#define __O_TMPFILE 0x2000000 +#else #define __O_TMPFILE 020000000 #endif -- cgit v1.2.3-54-g00ecf From 1d9ed171788821c21ca900a921833a8e41bf22f3 Mon Sep 17 00:00:00 2001 From: "Yann E. MORIN" Date: Mon, 29 Aug 2016 12:34:50 +0200 Subject: basic/fileio: we always have O_TMPFILE now fileio makes use of O_TMPFILE when it is available. We now always have O_TMPFILE, defined in missing.h if missing from the toolchain headers. Have fileio include missing.h and drop the guards around the use of O_TMPFILE. --- src/basic/fileio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index d642f3daea..a5920e7d36 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -37,6 +37,7 @@ #include "hexdecoct.h" #include "log.h" #include "macro.h" +#include "missing.h" #include "parse-util.h" #include "path-util.h" #include "random-util.h" @@ -1280,12 +1281,10 @@ int open_tmpfile_unlinkable(const char *directory, int flags) { /* Returns an unlinked temporary file that cannot be linked into the file system anymore */ -#ifdef O_TMPFILE /* Try O_TMPFILE first, if it is supported */ fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR); if (fd >= 0) return fd; -#endif /* Fall back to unguessable name + unlinking */ p = strjoina(directory, "/systemd-tmp-XXXXXX"); @@ -1313,7 +1312,6 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) { * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */ -#ifdef O_TMPFILE { _cleanup_free_ char *dn = NULL; @@ -1329,7 +1327,6 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) { log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn); } -#endif r = tempfn_random(target, NULL, &tmp); if (r < 0) -- cgit v1.2.3-54-g00ecf From 96e131ea091f748780776b81b7163f8084ed8244 Mon Sep 17 00:00:00 2001 From: WaLyong Cho Date: Mon, 4 Jul 2016 07:03:54 +0000 Subject: core: introduce MemorySwapMax= Similar to MemoryMax=, MemorySwapMax= limits swap usage. This controls controls "memory.swap.max" attribute in unified cgroup. --- man/systemd.resource-control.xml | 18 ++++++++++++++++++ src/core/cgroup.c | 12 +++++++++--- src/core/cgroup.h | 1 + src/core/dbus-cgroup.c | 5 ++++- src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/load-fragment.c | 6 +++++- src/systemctl/systemctl.c | 11 ++++++++++- 7 files changed, 48 insertions(+), 6 deletions(-) diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index 84dbfa2ff3..c11f420fe5 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -325,6 +325,24 @@ + + MemorySwapMax=bytes + + + Specify the absolute limit on swap usage of the executed processes in this unit. + + Takes a swap size in bytes. If the value is suffixed with K, M, G or T, the specified swap size is + parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. If assigned the + special value infinity, no swap limit is applied. This controls the + memory.swap.max control group attribute. For details about this control group attribute, + see cgroup-v2.txt. + + Implies MemoryAccounting=true. + + This setting is supported only if the unified control group hierarchy is used. + + + MemoryLimit=bytes diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 20f9f9fc7e..7873f88785 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -66,6 +66,7 @@ void cgroup_context_init(CGroupContext *c) { c->memory_high = CGROUP_LIMIT_MAX; c->memory_max = CGROUP_LIMIT_MAX; + c->memory_swap_max = CGROUP_LIMIT_MAX; c->memory_limit = CGROUP_LIMIT_MAX; @@ -173,6 +174,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { "%sMemoryLow=%" PRIu64 "\n" "%sMemoryHigh=%" PRIu64 "\n" "%sMemoryMax=%" PRIu64 "\n" + "%sMemorySwapMax=%" PRIu64 "\n" "%sMemoryLimit=%" PRIu64 "\n" "%sTasksMax=%" PRIu64 "\n" "%sDevicePolicy=%s\n" @@ -194,6 +196,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { prefix, c->memory_low, prefix, c->memory_high, prefix, c->memory_max, + prefix, c->memory_swap_max, prefix, c->memory_limit, prefix, c->tasks_max, prefix, cgroup_device_policy_to_string(c->device_policy), @@ -617,7 +620,7 @@ static unsigned cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, u } static bool cgroup_context_has_unified_memory_config(CGroupContext *c) { - return c->memory_low > 0 || c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX; + return c->memory_low > 0 || c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX || c->memory_swap_max != CGROUP_LIMIT_MAX; } static void cgroup_apply_unified_memory_limit(Unit *u, const char *file, uint64_t v) { @@ -848,10 +851,12 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { if ((mask & CGROUP_MASK_MEMORY) && !is_root) { if (cg_all_unified() > 0) { uint64_t max = c->memory_max; + uint64_t swap_max = c->memory_swap_max; - if (cgroup_context_has_unified_memory_config(c)) + if (cgroup_context_has_unified_memory_config(c)) { max = c->memory_max; - else { + swap_max = c->memory_swap_max; + } else { max = c->memory_limit; if (max != CGROUP_LIMIT_MAX) @@ -861,6 +866,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { cgroup_apply_unified_memory_limit(u, "memory.low", c->memory_low); cgroup_apply_unified_memory_limit(u, "memory.high", c->memory_high); cgroup_apply_unified_memory_limit(u, "memory.max", max); + cgroup_apply_unified_memory_limit(u, "memory.swap.max", swap_max); } else { char buf[DECIMAL_STR_MAX(uint64_t) + 1]; uint64_t val = c->memory_limit; diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 2fe9cc4039..4cd168f63e 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -101,6 +101,7 @@ struct CGroupContext { uint64_t memory_low; uint64_t memory_high; uint64_t memory_max; + uint64_t memory_swap_max; /* For legacy hierarchies */ uint64_t cpu_shares; diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 2ca80d2996..c4067a95bf 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -233,6 +233,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0), SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0), SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0), + SD_BUS_PROPERTY("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_max), 0), SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0), SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0), SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0), @@ -875,7 +876,7 @@ int bus_cgroup_set_property( return 1; - } else if (STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax")) { + } else if (STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax")) { uint64_t v; r = sd_bus_message_read(message, "t", &v); @@ -889,6 +890,8 @@ int bus_cgroup_set_property( c->memory_low = v; else if (streq(name, "MemoryHigh")) c->memory_high = v; + else if (streq(name, "MemorySwapMax")) + c->memory_swap_max = v; else c->memory_max = v; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 420d32dbd7..0741aca616 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -131,6 +131,7 @@ $1.MemoryAccounting, config_parse_bool, 0, $1.MemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context) $1.MemoryHigh, config_parse_memory_limit, 0, offsetof($1, cgroup_context) $1.MemoryMax, config_parse_memory_limit, 0, offsetof($1, cgroup_context) +$1.MemorySwapMax, config_parse_memory_limit, 0, offsetof($1, cgroup_context) $1.MemoryLimit, config_parse_memory_limit, 0, offsetof($1, cgroup_context) $1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context) $1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index d5185cf6a0..65ca9d8a33 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2981,8 +2981,12 @@ int config_parse_memory_limit( c->memory_high = bytes; else if (streq(lvalue, "MemoryMax")) c->memory_max = bytes; - else + else if (streq(lvalue, "MemorySwapMax")) + c->memory_swap_max = bytes; + else if (streq(lvalue, "MemoryLimit")) c->memory_limit = bytes; + else + return -EINVAL; return 0; } diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 4b87bdceb2..682805045d 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3571,6 +3571,7 @@ typedef struct UnitStatusInfo { uint64_t memory_low; uint64_t memory_high; uint64_t memory_max; + uint64_t memory_swap_max; uint64_t memory_limit; uint64_t cpu_usage_nsec; uint64_t tasks_current; @@ -3883,7 +3884,8 @@ static void print_status_info( printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current)); - if (i->memory_low > 0 || i->memory_high != CGROUP_LIMIT_MAX || i->memory_max != CGROUP_LIMIT_MAX || + if (i->memory_low > 0 || i->memory_high != CGROUP_LIMIT_MAX || + i->memory_max != CGROUP_LIMIT_MAX || i->memory_swap_max != CGROUP_LIMIT_MAX || i->memory_limit != CGROUP_LIMIT_MAX) { const char *prefix = ""; @@ -3900,6 +3902,10 @@ static void print_status_info( printf("%smax: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_max)); prefix = " "; } + if (i->memory_swap_max != CGROUP_LIMIT_MAX) { + printf("%sswap max: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_swap_max)); + prefix = " "; + } if (i->memory_limit != CGROUP_LIMIT_MAX) { printf("%slimit: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_limit)); prefix = " "; @@ -4140,6 +4146,8 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo * i->memory_high = u; else if (streq(name, "MemoryMax")) i->memory_max = u; + else if (streq(name, "MemorySwapMax")) + i->memory_swap_max = u; else if (streq(name, "MemoryLimit")) i->memory_limit = u; else if (streq(name, "TasksCurrent")) @@ -4655,6 +4663,7 @@ static int show_one( .memory_current = (uint64_t) -1, .memory_high = CGROUP_LIMIT_MAX, .memory_max = CGROUP_LIMIT_MAX, + .memory_swap_max = CGROUP_LIMIT_MAX, .memory_limit = (uint64_t) -1, .cpu_usage_nsec = (uint64_t) -1, .tasks_current = (uint64_t) -1, -- cgit v1.2.3-54-g00ecf From 67852d08e6a35d34b428e8be64efdb3f003f4697 Mon Sep 17 00:00:00 2001 From: Lukas Nykryn Date: Tue, 30 Aug 2016 15:04:07 +0200 Subject: install: fix disable when /etc/systemd/system is a symlink --- src/shared/install.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/install.c b/src/shared/install.c index 6b82ad05a7..11770d887f 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -643,7 +643,7 @@ static int remove_marked_symlinks( if (set_size(remove_symlinks_to) <= 0) return 0; - fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); + fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC); if (fd < 0) return errno == ENOENT ? 0 : -errno; -- cgit v1.2.3-54-g00ecf From a908cf0a126a332a209670ad5c769efa231fd002 Mon Sep 17 00:00:00 2001 From: Mantas Mikulėnas Date: Tue, 30 Aug 2016 17:50:19 +0300 Subject: bootctl: properly skip duplicate entries (#4048) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'continue' is a fancy no-op here – it only skips through the inner loop, not the outer one, so entries already in BootOrder get printed twice. This partially reverts f939cff71577 "bootctl: various coding style updates". --- src/boot/bootctl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index a7cdf92ed2..ee6d7eb864 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -439,9 +439,12 @@ static int status_variables(void) { for (j = 0; j < n_order; j++) if (options[i] == order[j]) - continue; + goto next_option; print_efi_option(options[i], false); + + next_option: + continue; } return 0; -- cgit v1.2.3-54-g00ecf From 50725d10e3417fd357abe1df2f177b8458027ac7 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Tue, 30 Aug 2016 20:22:04 +0530 Subject: link : add support to configure Offload features (#4017) This patch supports these features to be on or off Generic Segmentation Offload TCP Segmentation Offload UDP Segmentation Offload fixes #432 --- man/systemd.link.xml | 24 ++++++++ src/udev/net/ethtool-util.c | 111 +++++++++++++++++++++++++++++++++++ src/udev/net/ethtool-util.h | 9 +++ src/udev/net/link-config-gperf.gperf | 41 +++++++------ src/udev/net/link-config.c | 6 ++ src/udev/net/link-config.h | 1 + 6 files changed, 173 insertions(+), 19 deletions(-) diff --git a/man/systemd.link.xml b/man/systemd.link.xml index d5b4d1038d..313e4a4aa3 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -387,6 +387,30 @@ + + TCPSegmentationOffload= + + The TCP Segmentation Offload (TSO) when true enables + TCP segmentation offload. Takes a boolean value. + Defaults to "unset". + + + + GenericSegmentationOffload= + + The Generic Segmentation Offload (GSO) when true enables + generic segmentation offload. Takes a boolean value. + Defaults to "unset". + + + + UDPSegmentationOffload= + + The UDP Segmentation Offload (USO) when true enables + UDP segmentation offload. Takes a boolean value. + Defaults to "unset". + + diff --git a/src/udev/net/ethtool-util.c b/src/udev/net/ethtool-util.c index c00ff79123..5143eb5a9d 100644 --- a/src/udev/net/ethtool-util.c +++ b/src/udev/net/ethtool-util.c @@ -46,6 +46,12 @@ static const char* const wol_table[_WOL_MAX] = { DEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan); DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting"); +static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = { + [NET_DEV_FEAT_GSO] = "tx-generic-segmentation", + [NET_DEV_FEAT_TSO] = "tx-tcp-segmentation", + [NET_DEV_FEAT_UFO] = "tx-udp-fragmentation", +}; + int ethtool_connect(int *ret) { int fd; @@ -206,3 +212,108 @@ int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol) { return 0; } + +static int ethtool_get_stringset(int *fd, struct ifreq *ifr, int stringset_id, struct ethtool_gstrings **gstrings) { + _cleanup_free_ struct ethtool_gstrings *strings = NULL; + struct ethtool_sset_info info = { + .cmd = ETHTOOL_GSSET_INFO, + .reserved = 0, + .sset_mask = 1ULL << stringset_id, + }; + unsigned len; + int r; + + ifr->ifr_data = (void *) &info; + + r = ioctl(*fd, SIOCETHTOOL, ifr); + if (r < 0) + return -errno; + + if (!info.sset_mask) + return -EINVAL; + + len = info.data[0]; + + strings = malloc0(sizeof(struct ethtool_gstrings) + len * ETH_GSTRING_LEN); + if (!strings) + return -ENOMEM; + + strings->cmd = ETHTOOL_GSTRINGS; + strings->string_set = stringset_id; + strings->len = len; + + ifr->ifr_data = (void *) strings; + + r = ioctl(*fd, SIOCETHTOOL, ifr); + if (r < 0) + return -errno; + + *gstrings = strings; + strings = NULL; + + return 0; +} + +static int find_feature_index(struct ethtool_gstrings *strings, const char *feature) { + unsigned i; + + for (i = 0; i < strings->len; i++) { + if (streq((char *) &strings->data[i * ETH_GSTRING_LEN], feature)) + return i; + } + + return -1; +} + +int ethtool_set_features(int *fd, const char *ifname, NetDevFeature *features) { + _cleanup_free_ struct ethtool_gstrings *strings = NULL; + struct ethtool_sfeatures *sfeatures; + int block, bit, i, r; + struct ifreq ifr; + + if (*fd < 0) { + r = ethtool_connect(fd); + if (r < 0) + return log_warning_errno(r, "link_config: could not connect to ethtool: %m"); + } + + strscpy(ifr.ifr_name, IFNAMSIZ, ifname); + + r = ethtool_get_stringset(fd, &ifr, ETH_SS_FEATURES, &strings); + if (r < 0) + return log_warning_errno(r, "link_config: could not get ethtool features for %s", ifname); + + sfeatures = alloca0(sizeof(struct ethtool_gstrings) + DIV_ROUND_UP(strings->len, 32U) * sizeof(sfeatures->features[0])); + sfeatures->cmd = ETHTOOL_SFEATURES; + sfeatures->size = DIV_ROUND_UP(strings->len, 32U); + + for (i = 0; i < _NET_DEV_FEAT_MAX; i++) { + + if (features[i] != -1) { + + r = find_feature_index(strings, netdev_feature_table[i]); + if (r < 0) { + log_warning_errno(r, "link_config: could not find feature: %s", netdev_feature_table[i]); + continue; + } + + block = r / 32; + bit = r % 32; + + sfeatures->features[block].valid |= 1 << bit; + + if (features[i]) + sfeatures->features[block].requested |= 1 << bit; + else + sfeatures->features[block].requested &= ~(1 << bit); + } + } + + ifr.ifr_data = (void *) sfeatures; + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return log_warning_errno(r, "link_config: could not set ethtool features for %s", ifname); + + return 0; +} diff --git a/src/udev/net/ethtool-util.h b/src/udev/net/ethtool-util.h index 7716516e76..2b5b9fbd1a 100644 --- a/src/udev/net/ethtool-util.h +++ b/src/udev/net/ethtool-util.h @@ -38,11 +38,20 @@ typedef enum WakeOnLan { _WOL_INVALID = -1 } WakeOnLan; +typedef enum NetDevFeature { + NET_DEV_FEAT_GSO, + NET_DEV_FEAT_TSO, + NET_DEV_FEAT_UFO, + _NET_DEV_FEAT_MAX, + _NET_DEV_FEAT_INVALID = -1 +} NetDevFeature; + int ethtool_connect(int *ret); int ethtool_get_driver(int *fd, const char *ifname, char **ret); int ethtool_set_speed(int *fd, const char *ifname, unsigned int speed, Duplex duplex); int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol); +int ethtool_set_features(int *fd, const char *ifname, NetDevFeature *features); const char *duplex_to_string(Duplex d) _const_; Duplex duplex_from_string(const char *d) _pure_; diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf index b25e4b3344..5c57a0cb94 100644 --- a/src/udev/net/link-config-gperf.gperf +++ b/src/udev/net/link-config-gperf.gperf @@ -16,22 +16,25 @@ struct ConfigPerfItem; %struct-type %includes %% -Match.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, match_mac) -Match.OriginalName, config_parse_ifnames, 0, offsetof(link_config, match_name) -Match.Path, config_parse_strv, 0, offsetof(link_config, match_path) -Match.Driver, config_parse_strv, 0, offsetof(link_config, match_driver) -Match.Type, config_parse_strv, 0, offsetof(link_config, match_type) -Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, match_host) -Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, match_virt) -Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, match_kernel) -Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(link_config, match_arch) -Link.Description, config_parse_string, 0, offsetof(link_config, description) -Link.MACAddressPolicy, config_parse_mac_policy, 0, offsetof(link_config, mac_policy) -Link.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, mac) -Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy) -Link.Name, config_parse_ifname, 0, offsetof(link_config, name) -Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias) -Link.MTUBytes, config_parse_iec_size, 0, offsetof(link_config, mtu) -Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed) -Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex) -Link.WakeOnLan, config_parse_wol, 0, offsetof(link_config, wol) +Match.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, match_mac) +Match.OriginalName, config_parse_ifnames, 0, offsetof(link_config, match_name) +Match.Path, config_parse_strv, 0, offsetof(link_config, match_path) +Match.Driver, config_parse_strv, 0, offsetof(link_config, match_driver) +Match.Type, config_parse_strv, 0, offsetof(link_config, match_type) +Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, match_host) +Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, match_virt) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, match_kernel) +Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(link_config, match_arch) +Link.Description, config_parse_string, 0, offsetof(link_config, description) +Link.MACAddressPolicy, config_parse_mac_policy, 0, offsetof(link_config, mac_policy) +Link.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, mac) +Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy) +Link.Name, config_parse_ifname, 0, offsetof(link_config, name) +Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias) +Link.MTUBytes, config_parse_iec_size, 0, offsetof(link_config, mtu) +Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed) +Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex) +Link.WakeOnLan, config_parse_wol, 0, offsetof(link_config, wol) +Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GSO]) +Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO]) +Link.UDPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_UFO]) diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index c66504102f..eedd94e777 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -168,6 +168,8 @@ static int load_link(link_config_ctx *ctx, const char *filename) { link->wol = _WOL_INVALID; link->duplex = _DUP_INVALID; + memset(&link->features, -1, _NET_DEV_FEAT_MAX); + r = config_parse(NULL, filename, file, "Match\0Link\0Ethernet\0", config_item_perf_lookup, link_config_gperf_lookup, @@ -397,6 +399,10 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m", old_name, wol_to_string(config->wol)); + r = ethtool_set_features(&ctx->ethtool_fd, old_name, config->features); + if (r < 0) + log_warning_errno(r, "Could not set offload features of %s: %m", old_name); + ifindex = udev_device_get_ifindex(device); if (ifindex <= 0) { log_warning("Could not find ifindex"); diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h index 9df5529d05..91cc0357c4 100644 --- a/src/udev/net/link-config.h +++ b/src/udev/net/link-config.h @@ -70,6 +70,7 @@ struct link_config { size_t speed; Duplex duplex; WakeOnLan wol; + NetDevFeature features[_NET_DEV_FEAT_MAX]; LIST_FIELDS(link_config, links); }; -- cgit v1.2.3-54-g00ecf From f7ea90fbba95618e75371e98cf513957ff433de7 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Wed, 31 Aug 2016 12:47:02 +0530 Subject: link : add support to configure LRO and GRO Offload features The patch supports to configure GenericReceiveOffload LargeReceiveOffload --- man/systemd.link.xml | 16 ++++++++++++++++ src/udev/net/ethtool-util.c | 2 ++ src/udev/net/ethtool-util.h | 2 ++ src/udev/net/link-config-gperf.gperf | 2 ++ 4 files changed, 22 insertions(+) diff --git a/man/systemd.link.xml b/man/systemd.link.xml index 313e4a4aa3..10fddeced0 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -411,6 +411,22 @@ Defaults to "unset". + + GenericReceiveOffload= + + The Generic Receive Offload (GRO) when true enables + generic receive offload. Takes a boolean value. + Defaults to "unset". + + + + LargeReceiveOffload= + + The Large Receive Offload (LRO) when true enables + large receive offload. Takes a boolean value. + Defaults to "unset". + + diff --git a/src/udev/net/ethtool-util.c b/src/udev/net/ethtool-util.c index 5143eb5a9d..19c69a98b1 100644 --- a/src/udev/net/ethtool-util.c +++ b/src/udev/net/ethtool-util.c @@ -48,6 +48,8 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse Wake static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = { [NET_DEV_FEAT_GSO] = "tx-generic-segmentation", + [NET_DEV_FEAT_GRO] = "rx-gro", + [NET_DEV_FEAT_LRO] = "rx-lro", [NET_DEV_FEAT_TSO] = "tx-tcp-segmentation", [NET_DEV_FEAT_UFO] = "tx-udp-fragmentation", }; diff --git a/src/udev/net/ethtool-util.h b/src/udev/net/ethtool-util.h index 2b5b9fbd1a..0744164653 100644 --- a/src/udev/net/ethtool-util.h +++ b/src/udev/net/ethtool-util.h @@ -40,6 +40,8 @@ typedef enum WakeOnLan { typedef enum NetDevFeature { NET_DEV_FEAT_GSO, + NET_DEV_FEAT_GRO, + NET_DEV_FEAT_LRO, NET_DEV_FEAT_TSO, NET_DEV_FEAT_UFO, _NET_DEV_FEAT_MAX, diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf index 5c57a0cb94..f8b85cbd13 100644 --- a/src/udev/net/link-config-gperf.gperf +++ b/src/udev/net/link-config-gperf.gperf @@ -38,3 +38,5 @@ Link.WakeOnLan, config_parse_wol, 0, Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GSO]) Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO]) Link.UDPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_UFO]) +Link.GenericReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GRO]) +Link.LargeReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_LRO]) -- cgit v1.2.3-54-g00ecf From c7440e7401461a4bc668f5dae5b1861ed26b85dd Mon Sep 17 00:00:00 2001 From: Tobias Jungel Date: Wed, 31 Aug 2016 20:06:23 +0200 Subject: networkd: add options to bridge (#4051) This patch allows to configure AgeingTimeSec, Priority and DefaultPVID for bridge interfaces. --- man/systemd.netdev.xml | 20 ++++++++++++++++++++ src/network/networkd-netdev-bridge.c | 18 ++++++++++++++++++ src/network/networkd-netdev-bridge.h | 3 +++ src/network/networkd-netdev-gperf.gperf | 3 +++ src/shared/conf-parser.c | 1 + src/shared/conf-parser.h | 1 + 6 files changed, 46 insertions(+) diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index e56708a648..1f9f071b94 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -314,6 +314,26 @@ of the Listening and Learning states before the Forwarding state is entered. + + AgeingTimeSec= + + This specifies the number of seconds a MAC Address will be kept in + the forwaring database after having a packet received from this MAC Address. + + + + Priority= + + The priority of the bridge. An integer between 0 and 65535. A lower value + means higher priority. The bridge having the lowest priority will be elected as root bridge. + + + + DefaultPVID= + + This specifies the default port VLAN ID of a newly attached bridge port. + + MulticastQuerier= diff --git a/src/network/networkd-netdev-bridge.c b/src/network/networkd-netdev-bridge.c index 12b0fe972f..bdbea7d770 100644 --- a/src/network/networkd-netdev-bridge.c +++ b/src/network/networkd-netdev-bridge.c @@ -90,6 +90,24 @@ static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_mess return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MAX_AGE attribute: %m"); } + if (b->ageing_time > 0) { + r = sd_netlink_message_append_u32(req, IFLA_BR_AGEING_TIME, usec_to_jiffies(b->ageing_time)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_AGEING_TIME attribute: %m"); + } + + if (b->priority > 0) { + r = sd_netlink_message_append_u16(req, IFLA_BR_PRIORITY, b->priority); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_PRIORITY attribute: %m"); + } + + if (b->default_pvid > 0) { + r = sd_netlink_message_append_u16(req, IFLA_BR_VLAN_DEFAULT_PVID, b->default_pvid); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_DEFAULT_PVID attribute: %m"); + } + if (b->mcast_querier >= 0) { r = sd_netlink_message_append_u8(req, IFLA_BR_MCAST_QUERIER, b->mcast_querier); if (r < 0) diff --git a/src/network/networkd-netdev-bridge.h b/src/network/networkd-netdev-bridge.h index 4ce0fbb6f9..53f72f1ea5 100644 --- a/src/network/networkd-netdev-bridge.h +++ b/src/network/networkd-netdev-bridge.h @@ -28,10 +28,13 @@ typedef struct Bridge { int mcast_snooping; int vlan_filtering; int stp; + uint16_t priority; + uint16_t default_pvid; usec_t forward_delay; usec_t hello_time; usec_t max_age; + usec_t ageing_time; } Bridge; DEFINE_NETDEV_CAST(BRIDGE, Bridge); diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf index a1ca1a3d4e..6dbb627f15 100644 --- a/src/network/networkd-netdev-gperf.gperf +++ b/src/network/networkd-netdev-gperf.gperf @@ -102,7 +102,10 @@ Bond.ARPIntervalSec, config_parse_sec, 0, Bond.LearnPacketIntervalSec, config_parse_sec, 0, offsetof(Bond, lp_interval) Bridge.HelloTimeSec, config_parse_sec, 0, offsetof(Bridge, hello_time) Bridge.MaxAgeSec, config_parse_sec, 0, offsetof(Bridge, max_age) +Bridge.AgeingTimeSec, config_parse_sec, 0, offsetof(Bridge, ageing_time) Bridge.ForwardDelaySec, config_parse_sec, 0, offsetof(Bridge, forward_delay) +Bridge.Priority, config_parse_uint16, 0, offsetof(Bridge, priority) +Bridge.DefaultPVID, config_parse_vlanid, 0, offsetof(Bridge, default_pvid) Bridge.MulticastQuerier, config_parse_tristate, 0, offsetof(Bridge, mcast_querier) Bridge.MulticastSnooping, config_parse_tristate, 0, offsetof(Bridge, mcast_snooping) Bridge.VLANFiltering, config_parse_tristate, 0, offsetof(Bridge, vlan_filtering) diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 7cf222e4d2..f31d219418 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -460,6 +460,7 @@ int config_parse_many(const char *conf_file, DEFINE_PARSER(int, int, safe_atoi); DEFINE_PARSER(long, long, safe_atoli); +DEFINE_PARSER(uint16, uint16_t, safe_atou16); DEFINE_PARSER(uint32, uint32_t, safe_atou32); DEFINE_PARSER(uint64, uint64_t, safe_atou64); DEFINE_PARSER(unsigned, unsigned, safe_atou); diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index f6964e3fd4..3298dc0cea 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -107,6 +107,7 @@ int config_parse_many(const char *conf_file, /* possibly NULL */ int config_parse_int(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_unsigned(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_long(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_uint16(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_uint32(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_uint64(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_double(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); -- cgit v1.2.3-54-g00ecf From 07b0b339d6a818fd7aa71beecba8ffbd36d59a8f Mon Sep 17 00:00:00 2001 From: Seraphime Kirkovski Date: Wed, 31 Aug 2016 21:06:57 +0300 Subject: machinectl: split OS field in two; print ip addresses (#4058) This splits the OS field in two : one for the distribution name and one for the the version id. Dashes are written for missing fields. This also prints ip addresses of known machines. The `--max-addresses` option specifies how much ip addresses we want to see. The default is 1. When more than one address is written for a machine, a `,` follows it. If there are more ips than `--max-addresses`, `...` follows the last address. --- TODO | 2 - man/machinectl.xml | 14 +++++ src/basic/string-util.h | 4 ++ src/machine/machinectl.c | 152 ++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 141 insertions(+), 31 deletions(-) diff --git a/TODO b/TODO index 0ce9a1fd30..88bf48d0d9 100644 --- a/TODO +++ b/TODO @@ -642,8 +642,6 @@ Features: is used * machined: - - "machinectl list" should probably show columns for OS version and IP - addresses - add an API so that libvirt-lxc can inform us about network interfaces being removed or added to an existing machine - "machinectl migrate" or similar to copy a container from or to a diff --git a/man/machinectl.xml b/man/machinectl.xml index 597a5cc583..7056fd4204 100644 --- a/man/machinectl.xml +++ b/man/machinectl.xml @@ -285,6 +285,20 @@ name passed. + + + + When used with the + command, limits the number of ip addresses output for every machine. + Defaults to 1. All addresses can be requested with all + as argument to . If the argument to + is less than the actual number + of addresses,...follows the last address. + If multiple addresses are to be written for a given machine, every + address except the first one is on a new line and is followed by + , if another address will be output afterwards. + + diff --git a/src/basic/string-util.h b/src/basic/string-util.h index b75aba63c2..d029d538bd 100644 --- a/src/basic/string-util.h +++ b/src/basic/string-util.h @@ -70,6 +70,10 @@ static inline const char *empty_to_null(const char *p) { return isempty(p) ? NULL : p; } +static inline const char *strdash_if_empty(const char *str) { + return isempty(str) ? "-" : str; +} + static inline char *startswith(const char *s, const char *prefix) { size_t l; diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 4acce4bea7..74e1a349bc 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -60,6 +60,9 @@ #include "util.h" #include "verbs.h" #include "web-util.h" +#include "stdio-util.h" + +#define ALL_IP_ADDRESSES -1 static char **arg_property = NULL; static bool arg_all = false; @@ -82,6 +85,9 @@ static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE; static const char* arg_format = NULL; static const char *arg_uid = NULL; static char **arg_setenv = NULL; +static int arg_addrs = 1; + +static int print_addresses(sd_bus *bus, const char *name, int, const char *pr1, const char *pr2, int n_addr); static void polkit_agent_open_if_enabled(void) { @@ -110,6 +116,7 @@ typedef struct MachineInfo { const char *class; const char *service; char *os; + char *version_id; } MachineInfo; static int compare_machine_info(const void *a, const void *b) { @@ -124,20 +131,27 @@ static void clean_machine_info(MachineInfo *machines, size_t n_machines) { if (!machines || n_machines == 0) return; - for (i = 0; i < n_machines; i++) + for (i = 0; i < n_machines; i++) { free(machines[i].os); + free(machines[i].version_id); + } free(machines); } -static int get_os_name(sd_bus *bus, const char *name, char **out) { +static int get_os_release_property(sd_bus *bus, const char *name, const char *query, ...) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - const char *k, *v, *os; - char *str; + const char *k, *v, *iter, **query_res = NULL; + size_t count = 0, awaited_args = 0; + va_list ap; int r; assert(bus); assert(name); - assert(out); + assert(query); + + NULSTR_FOREACH(iter, query) + awaited_args++; + query_res = newa0(const char *, awaited_args); r = sd_bus_call_method(bus, "org.freedesktop.machine1", @@ -153,8 +167,14 @@ static int get_os_name(sd_bus *bus, const char *name, char **out) { return bus_log_parse_error(r); while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) { - if (streq(k, "PRETTY_NAME")) - os = v; + count = 0; + NULSTR_FOREACH(iter, query) { + if (streq(k, iter)) { + query_res[count] = v; + break; + } + count++; + } } if (r < 0) return bus_log_parse_error(r); @@ -163,10 +183,22 @@ static int get_os_name(sd_bus *bus, const char *name, char **out) { if (r < 0) return bus_log_parse_error(r); - str = strdup(os); - if (!str) - return log_oom(); - *out = str; + va_start(ap, query); + for (count = 0; count < awaited_args; count++) { + char *val, **out; + + out = va_arg(ap, char **); + assert(out); + if (query_res[count]) { + val = strdup(query_res[count]); + if (!val) { + va_end(ap); + return log_oom(); + } + *out = val; + } + } + va_end(ap); return 0; } @@ -174,9 +206,10 @@ static int get_os_name(sd_bus *bus, const char *name, char **out) { static int list_machines(int argc, char *argv[], void *userdata) { size_t max_name = strlen("MACHINE"), max_class = strlen("CLASS"), - max_service = strlen("SERVICE"), max_os = strlen("OS"); + max_service = strlen("SERVICE"), max_os = strlen("OS"), max_version_id = strlen("VERSION"); _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *prefix = NULL; MachineInfo *machines = NULL; const char *name, *class, *service, *object; size_t n_machines = 0, n_allocated = 0, j; @@ -215,7 +248,11 @@ static int list_machines(int argc, char *argv[], void *userdata) { } machines[n_machines].os = NULL; - r = get_os_name(bus, name, &machines[n_machines].os); + machines[n_machines].version_id = NULL; + r = get_os_release_property(bus, name, + "ID\0" "VERSION_ID\0", + &machines[n_machines].os, + &machines[n_machines].version_id); if (r < 0) goto out; @@ -235,10 +272,14 @@ static int list_machines(int argc, char *argv[], void *userdata) { if (l > max_service) max_service = l; - l = machines[n_machines].os ? strlen(machines[n_machines].os) : 0; + l = machines[n_machines].os ? strlen(machines[n_machines].os) : 1; if (l > max_os) max_os = l; + l = machines[n_machines].version_id ? strlen(machines[n_machines].version_id) : 1; + if (l > max_version_id) + max_version_id = l; + n_machines++; } if (r < 0) { @@ -254,19 +295,40 @@ static int list_machines(int argc, char *argv[], void *userdata) { qsort_safe(machines, n_machines, sizeof(MachineInfo), compare_machine_info); + /* Allocate for prefix max characters for all fields + spaces between them + strlen(",\n") */ + r = asprintf(&prefix, "%-*s", + (int) (max_name + + max_class + + max_service + + max_os + + max_version_id + 5 + strlen(",\n")), + ",\n"); + if (r < 0) { + r = log_oom(); + goto out; + } + if (arg_legend && n_machines > 0) - printf("%-*s %-*s %-*s %-*s\n", + printf("%-*s %-*s %-*s %-*s %-*s %s\n", (int) max_name, "MACHINE", (int) max_class, "CLASS", (int) max_service, "SERVICE", - (int) max_os, "OS"); + (int) max_os, "OS", + (int) max_version_id, "VERSION", + "ADDRESSES"); - for (j = 0; j < n_machines; j++) - printf("%-*s %-*s %-*s %-*s\n", + for (j = 0; j < n_machines; j++) { + printf("%-*s %-*s %-*s %-*s %-*s ", (int) max_name, machines[j].name, (int) max_class, machines[j].class, - (int) max_service, machines[j].service, - (int) max_os, machines[j].os ? machines[j].os : ""); + (int) max_service, strdash_if_empty(machines[j].service), + (int) max_os, strdash_if_empty(machines[j].os), + (int) max_version_id, strdash_if_empty(machines[j].version_id)); + + r = print_addresses(bus, machines[j].name, 0, "", prefix, arg_addrs); + if (r == -ENOSYS) + printf("-\n"); + } if (arg_legend && n_machines > 0) printf("\n%zu machines listed.\n", n_machines); @@ -467,8 +529,10 @@ static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) { return 0; } -static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2) { +static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2, int n_addr) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *addresses = NULL; + bool truncate = false; int r; assert(bus); @@ -487,6 +551,11 @@ static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *p if (r < 0) return r; + addresses = strdup(prefix); + if (!addresses) + return log_oom(); + prefix = ""; + r = sd_bus_message_enter_container(reply, 'a', "(iay)"); if (r < 0) return bus_log_parse_error(r); @@ -495,7 +564,7 @@ static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *p int family; const void *a; size_t sz; - char buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)]; + char buf_ifi[DECIMAL_STR_MAX(int) + 2], buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)]; r = sd_bus_message_read(reply, "i", &family); if (r < 0) @@ -505,11 +574,16 @@ static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *p if (r < 0) return bus_log_parse_error(r); - fputs(prefix, stdout); - fputs(inet_ntop(family, a, buffer, sizeof(buffer)), stdout); - if (family == AF_INET6 && ifi > 0) - printf("%%%i", ifi); - fputc('\n', stdout); + if (n_addr != 0) { + if (family == AF_INET6 && ifi > 0) + xsprintf(buf_ifi, "%%%i", ifi); + else + strcpy(buf_ifi, ""); + + if(!strextend(&addresses, prefix, inet_ntop(family, a, buffer, sizeof(buffer)), buf_ifi, NULL)) + return log_oom(); + } else + truncate = true; r = sd_bus_message_exit_container(reply); if (r < 0) @@ -517,6 +591,9 @@ static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *p if (prefix != prefix2) prefix = prefix2; + + if (n_addr > 0) + n_addr -= 1; } if (r < 0) return bus_log_parse_error(r); @@ -525,6 +602,7 @@ static int print_addresses(sd_bus *bus, const char *name, int ifi, const char *p if (r < 0) return bus_log_parse_error(r); + fprintf(stdout, "%s%s\n", addresses, truncate ? "..." : ""); return 0; } @@ -536,7 +614,7 @@ static int print_os_release(sd_bus *bus, const char *name, const char *prefix) { assert(name); assert(prefix); - r = get_os_name(bus, name, &pretty); + r = get_os_release_property(bus, name, "PRETTY_NAME\0", &pretty, NULL); if (r < 0) return r; @@ -644,7 +722,8 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) { print_addresses(bus, i->name, ifi, "\t Address: ", - "\t "); + "\n\t ", + ALL_IP_ADDRESSES); print_os_release(bus, i->name, "\t OS: "); @@ -2546,6 +2625,7 @@ static int help(int argc, char *argv[], void *userdata) { " --read-only Create read-only bind mount\n" " --mkdir Create directory before bind mounting, if missing\n" " -n --lines=INTEGER Number of journal entries to show\n" + " --max-addresses=INTEGER Number of internet addresses to show at most\n" " -o --output=STRING Change journal output mode (short,\n" " short-monotonic, verbose, export, json,\n" " json-pretty, json-sse, cat)\n" @@ -2610,6 +2690,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_FORCE, ARG_FORMAT, ARG_UID, + ARG_NUMBER_IPS, }; static const struct option options[] = { @@ -2636,6 +2717,7 @@ static int parse_argv(int argc, char *argv[]) { { "format", required_argument, NULL, ARG_FORMAT }, { "uid", required_argument, NULL, ARG_UID }, { "setenv", required_argument, NULL, 'E' }, + { "max-addresses", required_argument, NULL, ARG_NUMBER_IPS }, {} }; @@ -2826,6 +2908,18 @@ static int parse_argv(int argc, char *argv[]) { return log_oom(); break; + case ARG_NUMBER_IPS: + if (streq(optarg, "all")) + arg_addrs = ALL_IP_ADDRESSES; + else if (safe_atoi(optarg, &arg_addrs) < 0) { + log_error("Invalid number of IPs"); + return -EINVAL; + } else if (arg_addrs < 0) { + log_error("Number of IPs cannot be negative"); + return -EINVAL; + } + break; + case '?': return -EINVAL; -- cgit v1.2.3-54-g00ecf From 5ddda46f18384d51c74df6daca58a8bc87b46ad1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 31 Aug 2016 20:09:31 +0200 Subject: sd-bus: bump message queue size Let's bump it further, as this the current limit turns out to be problematic IRL. Let's bump it to more than twice what we know of is needed. Fixes: #4068 --- src/libsystemd/sd-bus/bus-internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 2608f5469c..bb0414c4d6 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -328,8 +328,8 @@ struct sd_bus { #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) -#define BUS_WQUEUE_MAX 1024 -#define BUS_RQUEUE_MAX 64*1024 +#define BUS_WQUEUE_MAX (192*1024) +#define BUS_RQUEUE_MAX (192*1024) #define BUS_MESSAGE_SIZE_MAX (64*1024*1024) #define BUS_AUTH_SIZE_MAX (64*1024) -- cgit v1.2.3-54-g00ecf From f07529fe7d17d1405e36993506cd46d70fb9ce46 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 31 Aug 2016 20:12:11 +0200 Subject: resolved: include d.f.ip6.arpa in default NTA list Fixes: #4049 --- src/resolve/resolved-dns-trust-anchor.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c index 77370e7dd5..9917b9e984 100644 --- a/src/resolve/resolved-dns-trust-anchor.c +++ b/src/resolve/resolved-dns-trust-anchor.c @@ -127,6 +127,9 @@ static int dns_trust_anchor_add_builtin_negative(DnsTrustAnchor *d) { "31.172.in-addr.arpa\0" "168.192.in-addr.arpa\0" + /* The same, but for IPv6. */ + "d.f.ip6.arpa\0" + /* RFC 6762 reserves the .local domain for Multicast * DNS, it hence cannot appear in the root zone. (Note * that we by default do not route .local traffic to -- cgit v1.2.3-54-g00ecf From 219bfe3872465c6587b57ffdda25a36ccc6ee85f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 31 Aug 2016 20:23:19 +0200 Subject: hostnamed: prefer more precise DMI info over ACPI OSPM info (also: add comments about the used numbers) Fixes: #3930 --- src/hostname/hostnamed.c | 89 +++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 47 deletions(-) diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index fe8bb62752..080a2cd138 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -148,56 +148,61 @@ static bool valid_deployment(const char *deployment) { } static const char* fallback_chassis(void) { - int r; char *type; unsigned t; - int v; + int v, r; v = detect_virtualization(); - if (VIRTUALIZATION_IS_VM(v)) return "vm"; if (VIRTUALIZATION_IS_CONTAINER(v)) return "container"; - r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type); + r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type); if (r < 0) - goto try_dmi; + goto try_acpi; r = safe_atou(type, &t); free(type); if (r < 0) - goto try_dmi; + goto try_acpi; - /* We only list the really obvious cases here as the ACPI data - * is not really super reliable. - * - * See the ACPI 5.0 Spec Section 5.2.9.1 for details: - * - * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf + /* We only list the really obvious cases here. The DMI data is unreliable enough, so let's not do any + additional guesswork on top of that. + + See the SMBIOS Specification 3.0 section 7.4.1 for details about the values listed here: + + https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf */ - switch(t) { + switch (t) { - case 1: - case 3: - case 6: + case 0x3: /* Desktop */ + case 0x4: /* Low Profile Desktop */ + case 0x6: /* Mini Tower */ + case 0x7: /* Tower */ return "desktop"; - case 2: + case 0x8: /* Portable */ + case 0x9: /* Laptop */ + case 0xA: /* Notebook */ + case 0xE: /* Sub Notebook */ return "laptop"; - case 4: - case 5: - case 7: + case 0xB: /* Hand Held */ + return "handset"; + + case 0x11: /* Main Server Chassis */ + case 0x1C: /* Blade */ + case 0x1D: /* Blade Enclosure */ return "server"; - case 8: + case 0x1E: /* Tablet */ return "tablet"; } -try_dmi: - r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type); +try_acpi: + r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type); if (r < 0) return NULL; @@ -206,39 +211,29 @@ try_dmi: if (r < 0) return NULL; - /* We only list the really obvious cases here. The DMI data is - unreliable enough, so let's not do any additional guesswork - on top of that. - - See the SMBIOS Specification 3.0 section 7.4.1 for - details about the values listed here: - - https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf + /* We only list the really obvious cases here as the ACPI data is not really super reliable. + * + * See the ACPI 5.0 Spec Section 5.2.9.1 for details: + * + * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf */ - switch (t) { + switch(t) { - case 0x3: - case 0x4: - case 0x6: - case 0x7: + case 1: /* Desktop */ + case 3: /* Workstation */ + case 6: /* Appliance PC */ return "desktop"; - case 0x8: - case 0x9: - case 0xA: - case 0xE: + case 2: /* Mobile */ return "laptop"; - case 0xB: - return "handset"; - - case 0x11: - case 0x1C: - case 0x1D: + case 4: /* Enterprise Server */ + case 5: /* SOHO Server */ + case 7: /* Performance Server */ return "server"; - case 0x1E: + case 8: /* Tablet */ return "tablet"; } -- cgit v1.2.3-54-g00ecf From 082d0c5ced26ff7efda97de3e1ade5c85f595765 Mon Sep 17 00:00:00 2001 From: David Michael Date: Wed, 31 Aug 2016 11:57:52 -0700 Subject: resolved: remove unused prototype --- src/resolve/resolved-conf.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h index e1fd2cceec..1d2492212c 100644 --- a/src/resolve/resolved-conf.h +++ b/src/resolve/resolved-conf.h @@ -33,4 +33,3 @@ const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, unsigned len int config_parse_dns_servers(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_search_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_dnssec(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); -- cgit v1.2.3-54-g00ecf From 07f264e40a36552a11559ff3fd5e07dbdbfad444 Mon Sep 17 00:00:00 2001 From: David Michael Date: Wed, 31 Aug 2016 15:33:21 -0700 Subject: resolved: directly include some required headers instead of inheriting --- src/resolve/resolved-conf.h | 1 + src/resolve/resolved-dns-scope.h | 3 +++ src/resolve/resolved-dns-stream.h | 1 + src/resolve/resolved-dns-transaction.h | 2 ++ src/resolve/resolved-link.h | 1 + 5 files changed, 8 insertions(+) diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h index 1d2492212c..64a185c69f 100644 --- a/src/resolve/resolved-conf.h +++ b/src/resolve/resolved-conf.h @@ -20,6 +20,7 @@ ***/ #include "resolved-manager.h" +#include "resolved-dns-server.h" int manager_parse_config_file(Manager *m); diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h index 538bc61f81..01a83a76b2 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -26,7 +26,10 @@ typedef struct DnsScope DnsScope; #include "resolved-dns-cache.h" #include "resolved-dns-dnssec.h" #include "resolved-dns-packet.h" +#include "resolved-dns-query.h" +#include "resolved-dns-search-domain.h" #include "resolved-dns-server.h" +#include "resolved-dns-stream.h" #include "resolved-dns-zone.h" #include "resolved-link.h" diff --git a/src/resolve/resolved-dns-stream.h b/src/resolve/resolved-dns-stream.h index e6569678fa..4cdb4f6806 100644 --- a/src/resolve/resolved-dns-stream.h +++ b/src/resolve/resolved-dns-stream.h @@ -25,6 +25,7 @@ typedef struct DnsStream DnsStream; #include "resolved-dns-packet.h" #include "resolved-dns-transaction.h" +#include "resolved-manager.h" /* Streams are used by three subsystems: * diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h index 96b066845d..5a1df70422 100644 --- a/src/resolve/resolved-dns-transaction.h +++ b/src/resolve/resolved-dns-transaction.h @@ -59,6 +59,8 @@ enum DnsTransactionSource { #include "resolved-dns-packet.h" #include "resolved-dns-question.h" #include "resolved-dns-scope.h" +#include "resolved-dns-server.h" +#include "resolved-dns-stream.h" struct DnsTransaction { DnsScope *scope; diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h index 6a2343f9f7..c9b2a58c34 100644 --- a/src/resolve/resolved-link.h +++ b/src/resolve/resolved-link.h @@ -29,6 +29,7 @@ typedef struct Link Link; typedef struct LinkAddress LinkAddress; #include "resolved-dns-rr.h" +#include "resolved-dns-scope.h" #include "resolved-dns-search-domain.h" #include "resolved-dns-server.h" #include "resolved-manager.h" -- cgit v1.2.3-54-g00ecf From 4ad6f2133a7cb89071c31aef96ad1f1b778b9441 Mon Sep 17 00:00:00 2001 From: Noeljunior Date: Thu, 1 Sep 2016 03:02:10 +0100 Subject: hwdb: add axis corrections for the Lenovo Yoga 500-14ISK touchpad --- hwdb/60-evdev.hwdb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb index 4bed8d026d..4e61117cb5 100644 --- a/hwdb/60-evdev.hwdb +++ b/hwdb/60-evdev.hwdb @@ -247,6 +247,13 @@ evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapad500S-13ISK* EVDEV_ABS_35=125:3954:37 EVDEV_ABS_36=104:1959:27 +# Lenovo Yoga 500-14ISK +evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoYoga500-14ISK* + EVDEV_ABS_00=124:3955:36 + EVDEV_ABS_01=103:1959:26 + EVDEV_ABS_35=124:3955:36 + EVDEV_ABS_36=103:1959:26 + ######################################### # Samsung ######################################### -- cgit v1.2.3-54-g00ecf From 3ba320560a86fdd9a7c840205f96ff68ff159e31 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 1 Sep 2016 16:29:13 +1000 Subject: hwdb: add axis range corrections for Lenovo L430 (#4074) https://bugs.freedesktop.org/show_bug.cgi?id=96220 --- hwdb/60-evdev.hwdb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb index 4bed8d026d..2b151564e4 100644 --- a/hwdb/60-evdev.hwdb +++ b/hwdb/60-evdev.hwdb @@ -195,6 +195,13 @@ evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:pn*ThinkPadEdgeE530* EVDEV_ABS_35=1241:5703:49 EVDEV_ABS_36=1105:4820:68 +# Lenovo L430 +evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnLENOVO*:pvrThinkPadL430* + EVDEV_ABS_00=19:2197:29 + EVDEV_ABS_01=12:1151:25 + EVDEV_ABS_35=19:2197:29 + EVDEV_ABS_36=12:1151:25 + # Lenovo P50 evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*P50* EVDEV_ABS_00=::44 -- cgit v1.2.3-54-g00ecf From a6405ca288ed3458589c82b6c6ddf87e8c054858 Mon Sep 17 00:00:00 2001 From: Cireo Date: Thu, 1 Sep 2016 02:04:36 -0700 Subject: systemctl: usable status command for special units (#4072) Prior to this commit, users could be given an unusable command to run if they attempted to stop or start special services. For example: $ systemctl stop -- -.mount Failed to stop -.mount: Operation refused, unit -.mount may be \ requested by dependency only. See system logs and 'systemctl status -.mount' for details. $ systemctl status -.mount systemctl: invalid option -- '.' This adds a '--' to the example command in these situations. --- src/systemctl/systemctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 682805045d..5912441168 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -2720,9 +2720,10 @@ static int start_unit_one( if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) && !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED)) - log_error("See %s logs and 'systemctl%s status %s' for details.", + log_error("See %s logs and 'systemctl%s status%s %s' for details.", arg_scope == UNIT_FILE_SYSTEM ? "system" : "user", arg_scope == UNIT_FILE_SYSTEM ? "" : " --user", + name[0] == '-' ? " --" : "", name); return r; -- cgit v1.2.3-54-g00ecf From 0cea2697edd26113d5328d235572e4b0c77b8779 Mon Sep 17 00:00:00 2001 From: Marcos Mello Date: Fri, 2 Sep 2016 07:18:11 -0300 Subject: shell-completion: add systemd-resolve --status (#4085) From be371fe. --- shell-completion/bash/systemd-resolve | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell-completion/bash/systemd-resolve b/shell-completion/bash/systemd-resolve index 0c501c9405..f59482fe23 100644 --- a/shell-completion/bash/systemd-resolve +++ b/shell-completion/bash/systemd-resolve @@ -36,8 +36,8 @@ _systemd-resolve() { local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local -A OPTS=( [STANDALONE]='-h --help --version -4 -6 - --service --openpgp --tlsa --statistics --reset-statistics - --service-address=no --service-txt=no + --service --openpgp --tlsa --status --statistics + --reset-statistics --service-address=no --service-txt=no --cname=no --search=no --legend=no' [ARG]='-i --interface -p --protocol -t --type -c --class' ) -- cgit v1.2.3-54-g00ecf From a9dee27f0d1bcbb7a8b52bfee45bc6d8ba901d17 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Fri, 2 Sep 2016 16:06:58 +0530 Subject: fix #4080 ethtool_sset_info adding some extra space to it. also fix valgrind warning ``` Unloaded link configuration context. ==31690== ==31690== HEAP SUMMARY: ==31690== in use at exit: 8,192 bytes in 2 blocks ==31690== total heap usage: 431 allocs, 429 frees, 321,164 bytes allocated ==31690== ==31690== 4,096 bytes in 1 blocks are still reachable in loss record 1 of 2 ==31690== at 0x4C2BBAD: malloc (vg_replace_malloc.c:299) ==31690== by 0x166B32: mempool_alloc_tile (mempool.c:62) ==31690== by 0x166BBC: mempool_alloc0_tile (mempool.c:81) ==31690== by 0x15B8FC: hashmap_base_new (hashmap.c:732) ==31690== by 0x15B9F7: internal_hashmap_new (hashmap.c:766) ==31690== by 0x151291: conf_files_list_strv_internal (conf-files.c:103) ==31690== by 0x1514BA: conf_files_list_strv (conf-files.c:135) ==31690== by 0x13A1CF: link_config_load (link-config.c:227) ==31690== by 0x135B68: builtin_net_setup_link_init (udev-builtin-net_setup_link.c:77) ==31690== by 0x1306B3: udev_builtin_init (udev-builtin.c:57) ==31690== by 0x11E984: adm_builtin (udevadm-test-builtin.c:72) ==31690== by 0x117B4D: run_command (udevadm.c:75) ``` Fixes #4080 --- src/udev/net/ethtool-util.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/udev/net/ethtool-util.c b/src/udev/net/ethtool-util.c index 19c69a98b1..b1aa0223fd 100644 --- a/src/udev/net/ethtool-util.c +++ b/src/udev/net/ethtool-util.c @@ -217,24 +217,28 @@ int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol) { static int ethtool_get_stringset(int *fd, struct ifreq *ifr, int stringset_id, struct ethtool_gstrings **gstrings) { _cleanup_free_ struct ethtool_gstrings *strings = NULL; - struct ethtool_sset_info info = { - .cmd = ETHTOOL_GSSET_INFO, - .reserved = 0, - .sset_mask = 1ULL << stringset_id, + struct { + struct ethtool_sset_info info; + uint32_t space; + } buffer = { + .info = { + .cmd = ETHTOOL_GSSET_INFO, + .sset_mask = UINT64_C(1) << stringset_id, + }, }; unsigned len; int r; - ifr->ifr_data = (void *) &info; + ifr->ifr_data = (void *) &buffer.info; r = ioctl(*fd, SIOCETHTOOL, ifr); if (r < 0) return -errno; - if (!info.sset_mask) + if (!buffer.info.sset_mask) return -EINVAL; - len = info.data[0]; + len = buffer.info.data[0]; strings = malloc0(sizeof(struct ethtool_gstrings) + len * ETH_GSTRING_LEN); if (!strings) @@ -271,7 +275,7 @@ int ethtool_set_features(int *fd, const char *ifname, NetDevFeature *features) { _cleanup_free_ struct ethtool_gstrings *strings = NULL; struct ethtool_sfeatures *sfeatures; int block, bit, i, r; - struct ifreq ifr; + struct ifreq ifr = {}; if (*fd < 0) { r = ethtool_connect(fd); -- cgit v1.2.3-54-g00ecf From d347d9029c7ec6b30eaaab93649105d935061b55 Mon Sep 17 00:00:00 2001 From: Felipe Sateler Date: Wed, 31 Aug 2016 10:00:35 -0300 Subject: seccomp: also detect if seccomp filtering is enabled In https://github.com/systemd/systemd/pull/4004 , a runtime detection method for seccomp was added. However, it does not detect the case where CONFIG_SECCOMP=y but CONFIG_SECCOMP_FILTER=n. This is possible if the architecture does not support filtering yet. Add a check for that case too. While at it, change get_proc_field usage to use PR_GET_SECCOMP prctl, as that should save a few system calls and (unnecessary) allocations. Previously, reading of /proc/self/stat was done as recommended by prctl(2) as safer. However, given that we need to do the prctl call anyway, lets skip opening, reading and parsing the file. Code for checking inspired by https://outflux.net/teach-seccomp/autodetect.html --- src/core/execute.c | 2 +- src/shared/seccomp-util.c | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 55f15d7e49..2026137721 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1077,7 +1077,7 @@ static void rename_process_from_path(const char *path) { static bool skip_seccomp_unavailable(const Unit* u, const char* msg) { if (!is_seccomp_available()) { log_open(); - log_unit_debug(u, "SECCOMP not detected in the kernel, skipping %s", msg); + log_unit_debug(u, "SECCOMP features not detected in the kernel, skipping %s", msg); log_close(); return true; } diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 6c489284d1..2f42381fc1 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -20,9 +20,9 @@ #include #include #include +#include +#include -#include "alloc-util.h" -#include "fileio.h" #include "macro.h" #include "seccomp-util.h" #include "string-util.h" @@ -91,11 +91,22 @@ int seccomp_add_secondary_archs(scmp_filter_ctx *c) { } +static bool is_basic_seccomp_available(void) { + int r; + r = prctl(PR_GET_SECCOMP, 0, 0, 0, 0); + return r >= 0; +} + +static bool is_seccomp_filter_available(void) { + int r; + r = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, 0, 0); + return r < 0 && errno == EFAULT; +} + bool is_seccomp_available(void) { - _cleanup_free_ char* field = NULL; static int cached_enabled = -1; if (cached_enabled < 0) - cached_enabled = get_proc_field("/proc/self/status", "Seccomp", "\n", &field) == 0; + cached_enabled = is_basic_seccomp_available() && is_seccomp_filter_available(); return cached_enabled; } -- cgit v1.2.3-54-g00ecf From 1cec406d62f00a7642c94834010a60548ae99d96 Mon Sep 17 00:00:00 2001 From: Felipe Sateler Date: Tue, 6 Sep 2016 20:25:22 -0300 Subject: nspawn: detect SECCOMP availability, skip audit filter if unavailable Fail hard if SECCOMP was detected but could not be installed --- src/nspawn/nspawn-seccomp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c index 3ab7160ebe..44a0b397ab 100644 --- a/src/nspawn/nspawn-seccomp.c +++ b/src/nspawn/nspawn-seccomp.c @@ -130,6 +130,11 @@ int setup_seccomp(uint64_t cap_list_retain) { scmp_filter_ctx seccomp; int r; + if (!is_seccomp_available()) { + log_debug("SECCOMP features not detected in the kernel, disabling SECCOMP audit filter"); + return 0; + } + seccomp = seccomp_init(SCMP_ACT_ALLOW); if (!seccomp) return log_oom(); @@ -173,11 +178,6 @@ int setup_seccomp(uint64_t cap_list_retain) { } r = seccomp_load(seccomp); - if (r == -EINVAL) { - log_debug_errno(r, "Kernel is probably not configured with CONFIG_SECCOMP. Disabling seccomp audit filter: %m"); - r = 0; - goto finish; - } if (r < 0) { log_error_errno(r, "Failed to install seccomp audit filter: %m"); goto finish; -- cgit v1.2.3-54-g00ecf From fd74fa791f95433ac52520764b67e6fb4bda2c0e Mon Sep 17 00:00:00 2001 From: Felipe Sateler Date: Mon, 5 Sep 2016 19:16:13 -0300 Subject: README: document that CONFIG_SECCOMP_FILTER is required for SECCOMP support --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index 19c15a70b0..fb6fd6381b 100644 --- a/README +++ b/README @@ -79,6 +79,7 @@ REQUIREMENTS: CONFIG_TMPFS_XATTR CONFIG_{TMPFS,EXT4,XFS,BTRFS_FS,...}_POSIX_ACL CONFIG_SECCOMP + CONFIG_SECCOMP_FILTER (required for seccomp support) CONFIG_CHECKPOINT_RESTORE (for the kcmp() syscall) Required for CPUShares= in resource control unit settings -- cgit v1.2.3-54-g00ecf From de737be0a8c90a7a1f113e0c63f995937da32f4e Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Thu, 8 Sep 2016 10:18:16 +0200 Subject: man: add missing tag (#4109) --- man/sd_is_fifo.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/man/sd_is_fifo.xml b/man/sd_is_fifo.xml index 627cb87aaf..7ff02cbfec 100644 --- a/man/sd_is_fifo.xml +++ b/man/sd_is_fifo.xml @@ -117,10 +117,10 @@ whether the specified file descriptor refers to a socket. If the family parameter is not AF_UNSPEC, it is checked whether the socket - is of the specified family (AF_UNIX, AF_INET, - ...). If the type parameter is not 0, it is - checked whether the socket is of the specified type - (SOCK_STREAM, + is of the specified family (AF_UNIX, + AF_INET, ...). If the type + parameter is not 0, it is checked whether the socket is of the + specified type (SOCK_STREAM, SOCK_DGRAM, ...). If the listening parameter is positive, it is checked whether the socket is in accepting mode, i.e. -- cgit v1.2.3-54-g00ecf From f2dbd059a6b325f058c1eff65f2441a0f9f90eb1 Mon Sep 17 00:00:00 2001 From: Kyle Russell Date: Thu, 8 Sep 2016 22:34:43 -0400 Subject: service: Continue shutdown on socket activated unit on termination (#4108) ENOTCONN may be a legitimate return code if the endpoint disappeared, but the service should still attempt to shutdown cleanly. --- src/core/service.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/core/service.c b/src/core/service.c index 969c62bd83..57f8d90ee5 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1256,10 +1256,17 @@ static int service_spawn( socklen_t salen = sizeof(sa); r = getpeername(s->socket_fd, &sa.sa, &salen); - if (r < 0) - return -errno; + if (r < 0) { + r = -errno; + + /* ENOTCONN is legitimate if the endpoint disappeared on shutdown. + * This connection is over, but the socket unit lives on. */ + if (r != -ENOTCONN || + (c != s->exec_command[SERVICE_EXEC_STOP] && c != s->exec_command[SERVICE_EXEC_STOP_POST])) + return r; + } - if (IN_SET(sa.sa.sa_family, AF_INET, AF_INET6)) { + if (r == 0 && IN_SET(sa.sa.sa_family, AF_INET, AF_INET6)) { _cleanup_free_ char *addr = NULL; char *t; int port; -- cgit v1.2.3-54-g00ecf From b1bdb6496c07fc4fcf3f0feae69b5ef89ae557d9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 9 Sep 2016 16:20:05 +0900 Subject: bash-completion: systemctl: do not pass masked or not-found units to filter Also, add new function __filter_units_by_properties() for filtering units by multiple properties, and make __get_startable_units() use it. fixes #4114 --- shell-completion/bash/systemctl.in | 43 ++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in index 2a45dcbba0..e62cfa57a9 100644 --- a/shell-completion/bash/systemctl.in +++ b/shell-completion/bash/systemctl.in @@ -51,6 +51,37 @@ __filter_units_by_property () { done } +__filter_units_by_properties () { + local mode=$1 properties=$2 values=$3 ; shift 3 + local units=("$@") + local props + IFS=$'\n' read -rd '' -a props < \ + <(__systemctl $mode show --property "$properties" -- "${units[@]}") + IFS=$',' read -r -a properties < <(echo $properties) + IFS=$',' read -r -a values < <(echo $values) + local conditions=() + for ((i=0; i < ${#properties[*]}; i++)); do + for ((j=0; j < ${#properties[*]}; j++)); do + if [[ ${props[i]%%=*} == ${properties[j]} ]]; then + conditions+=( "${properties[j]}=${values[j]}" ) + fi + done + done + local flag + for ((i=0; i < ${#units[*]}; i++)); do + flag=1 + for ((j=0; j < ${#conditions[*]}; j++)); do + if [[ "${props[ i * ${#conditions[*]} + j]}" != "${conditions[j]}" ]]; then + flag= + break + fi + done + if [[ -n $flag ]]; then + echo " ${units[i]}" + fi + done +} + __get_all_units () { { __systemctl $1 list-unit-files; __systemctl $1 list-units --all; } \ | { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; }; } __get_template_names () { __systemctl $1 list-unit-files \ @@ -60,12 +91,12 @@ __get_active_units () { __systemctl $1 list-units \ | { while read -r a b; do echo " $a"; done; }; } __get_startable_units () { # find startable inactive units - __filter_units_by_property $mode ActiveState inactive $( - __filter_units_by_property $mode CanStart yes $( - __systemctl $mode list-unit-files --state enabled,disabled,static | \ - { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; } - __systemctl $mode list-units --state inactive,failed | \ - { while read -r a b; do echo " $a"; done; } )) + __filter_units_by_properties $mode ActiveState,CanStart inactive,yes $( + { __systemctl $mode list-unit-files --state enabled,enabled-runtime,linked,linked-runtime,static,indirect,disabled,generated,transient | \ + { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; } + __systemctl $mode list-units --state inactive,failed | \ + { while read -r a b c; do [[ $b == "loaded" ]] && echo " $a"; done; } + } | sort -u ) } __get_restartable_units () { # filter out masked and not-found -- cgit v1.2.3-54-g00ecf From 2acaa3789a417290154ca9e18354e7a930b37dfb Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 9 Sep 2016 15:03:11 +0100 Subject: build-sys: drop last reference to --have-kdbus --- configure.ac | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.ac b/configure.ac index 36061c0ba9..4181483798 100644 --- a/configure.ac +++ b/configure.ac @@ -1656,7 +1656,6 @@ AC_MSG_RESULT([ nss-myhostname: ${have_myhostname} hwdb: ${enable_hwdb} tpm: ${have_tpm} - kdbus: ${have_kdbus} Python: ${have_python} man pages: ${have_manpages} test coverage: ${have_coverage} -- cgit v1.2.3-54-g00ecf From ba612f4204230a9a63e18c42e20b47ed09da675e Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 9 Sep 2016 15:06:06 +0100 Subject: man: drop kdbus descriptions from sd_b_negotiate_fds(3) --- man/sd_bus_negotiate_fds.xml | 46 +++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/man/sd_bus_negotiate_fds.xml b/man/sd_bus_negotiate_fds.xml index a538b13cf0..1501e1427d 100644 --- a/man/sd_bus_negotiate_fds.xml +++ b/man/sd_bus_negotiate_fds.xml @@ -99,41 +99,27 @@ setting as negotiated by the program ultimately activated. By default, file descriptor passing is enabled for both. - sd_bus_negotiate_timestamps() controls - whether implicit sender timestamps shall be attached automatically - to all incoming messages. Takes a bus object and a boolean, which, - when true, enables timestamping, and, when false, disables it. - Use + sd_bus_negotiate_timestamp() controls whether implicit sender + timestamps shall be attached automatically to all incoming messages. Takes a bus object and a + boolean, which, when true, enables timestamping, and, when false, disables it. Use sd_bus_message_get_monotonic_usec3, sd_bus_message_get_realtime_usec3, sd_bus_message_get_seqnum3 - to query the timestamps of incoming messages. If negotiation is - disabled or not supported, these calls will fail with - -ENODATA. Note that not all transports - support timestamping of messages. Specifically, timestamping is - only available on the kdbus transport, but not on dbus1. The - timestamping is applied by the kernel and cannot be manipulated by - userspace. By default, message timestamping is not negotiated for + to query the timestamps of incoming messages. If negotiation is disabled or not supported, these + calls will fail with -ENODATA. Note that currently no transports support + timestamping of messages. By default, message timestamping is not negotiated for connections. - sd_bus_negotiate_creds() controls - whether and which implicit sender credentials shall be attached - automatically to all incoming messages. Takes a bus object and a - boolean indicating whether to enable or disable the credential - parts encoded in the bit mask value argument. Note that not all - transports support attaching sender credentials to messages, or do - not support all types of sender credential parameters, or might - suppress them under certain circumstances for individual - messages. Specifically, implicit sender credentials on messages - are only fully supported on kdbus transports, and dbus1 only - supports SD_BUS_CREDS_UNIQUE_NAME. The sender - credentials are attached by the kernel and cannot be manipulated - by userspace, and are thus suitable for authorization - decisions. By default, only - SD_BUS_CREDS_WELL_KNOWN_NAMES and - SD_BUS_CREDS_UNIQUE_NAME are enabled. In - fact, these two credential fields are always sent along and cannot - be turned off. + sd_bus_negotiate_creds() controls whether and which implicit sender + credentials shall be attached automatically to all incoming messages. Takes a bus object and a + boolean indicating whether to enable or disable the credential parts encoded in the bit mask + value argument. Note that not all transports support attaching sender credentials to messages, + or do not support all types of sender credential parameters, or might suppress them under + certain circumstances for individual messages. Specifically, dbus1 only supports + SD_BUS_CREDS_UNIQUE_NAME. The sender credentials are suitable for + authorization decisions. By default, only SD_BUS_CREDS_WELL_KNOWN_NAMES and + SD_BUS_CREDS_UNIQUE_NAME are enabled. In fact, these two credential fields + are always sent along and cannot be turned off. The sd_bus_negotiate_fds() function may be called only before the connection has been started with -- cgit v1.2.3-54-g00ecf From 232f6754f60ae803c992ca156cbc25fa80a5b9db Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 9 Sep 2016 15:16:26 +0100 Subject: pid1: drop kdbus_fd and all associated logic --- src/core/dbus.c | 4 ---- src/core/manager.c | 33 +++++---------------------------- src/core/manager.h | 3 --- 3 files changed, 5 insertions(+), 35 deletions(-) diff --git a/src/core/dbus.c b/src/core/dbus.c index 1e41a42aa6..070974fe66 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -964,10 +964,6 @@ static int bus_init_private(Manager *m) { if (m->private_listen_fd >= 0) return 0; - /* We don't need the private socket if we have kdbus */ - if (m->kdbus_fd >= 0) - return 0; - if (MANAGER_IS_SYSTEM(m)) { /* We want the private bus only when running as init */ diff --git a/src/core/manager.c b/src/core/manager.c index b58f68fa7a..fa8deb9b1b 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -590,7 +590,7 @@ int manager_new(UnitFileScope scope, bool test_run, Manager **_m) { m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1; m->pin_cgroupfs_fd = m->notify_fd = m->cgroups_agent_fd = m->signal_fd = m->time_change_fd = - m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->cgroup_inotify_fd = + m->dev_autofs_fd = m->private_listen_fd = m->cgroup_inotify_fd = m->ask_password_inotify_fd = -1; m->user_lookup_fds[0] = m->user_lookup_fds[1] = -1; @@ -661,9 +661,8 @@ int manager_new(UnitFileScope scope, bool test_run, Manager **_m) { goto fail; } - /* Note that we set up neither kdbus, nor the notify fd - * here. We do that after deserialization, since they might - * have gotten serialized across the reexec. */ + /* Note that we do not set up the notify fd here. We do that after deserialization, + * since they might have gotten serialized across the reexec. */ m->taint_usr = dir_is_empty("/usr") > 0; @@ -879,7 +878,6 @@ static int manager_connect_bus(Manager *m, bool reexecuting) { return 0; try_bus_connect = - m->kdbus_fd >= 0 || reexecuting || (MANAGER_IS_USER(m) && getenv("DBUS_SESSION_BUS_ADDRESS")); @@ -1084,7 +1082,6 @@ Manager* manager_free(Manager *m) { safe_close(m->notify_fd); safe_close(m->cgroups_agent_fd); safe_close(m->time_change_fd); - safe_close(m->kdbus_fd); safe_close_pair(m->user_lookup_fds); manager_close_ask_password(m); @@ -1287,7 +1284,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { if (q < 0 && r == 0) r = q; - /* We might have deserialized the kdbus control fd, but if we didn't, then let's create the bus now. */ + /* Let's connect to the bus now. */ (void) manager_connect_bus(m, !!serialization); (void) bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed); @@ -2481,16 +2478,6 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { fprintf(f, "user-lookup=%i %i\n", copy0, copy1); } - if (m->kdbus_fd >= 0) { - int copy; - - copy = fdset_put_dup(fds, m->kdbus_fd); - if (copy < 0) - return copy; - - fprintf(f, "kdbus-fd=%i\n", copy); - } - bus_track_serialize(m->subscribed, f, "subscribed"); r = dynamic_user_serialize(m, f, fds); @@ -2678,16 +2665,6 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { m->user_lookup_fds[1] = fdset_remove(fds, fd1); } - } else if (startswith(l, "kdbus-fd=")) { - int fd; - - if (safe_atoi(l + 9, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) - log_debug("Failed to parse kdbus fd: %s", l + 9); - else { - safe_close(m->kdbus_fd); - m->kdbus_fd = fdset_remove(fds, fd); - } - } else if (startswith(l, "dynamic-user=")) dynamic_user_deserialize_one(m, l + 13, fds); else if (startswith(l, "destroy-ipc-uid=")) @@ -2699,7 +2676,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { if (strv_extend(&m->deserialized_subscribed, l+11) < 0) log_oom(); - } else + } else if (!startswith(l, "kdbus-fd=")) /* ignore this one */ log_debug("Unknown serialization item '%s'", l); } diff --git a/src/core/manager.h b/src/core/manager.h index b9f2e4b5a1..a592f1cb94 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -294,9 +294,6 @@ struct Manager { * value where Unit objects are contained. */ Hashmap *units_requiring_mounts_for; - /* Reference to the kdbus bus control fd */ - int kdbus_fd; - /* Used for processing polkit authorization responses */ Hashmap *polkit_registry; -- cgit v1.2.3-54-g00ecf From 0dd99f86addd1f81e24e89807b6bc4aab57d5793 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Fri, 9 Sep 2016 17:05:06 +0200 Subject: unit: sent change signal before removing the unit if necessary (#4106) If the unit is in the dbus queue when it is removed then the last change signal is never sent. Fix this by checking the dbus queue and explicitly send the change signal before sending the remove signal. --- src/core/dbus-unit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 1b86bdde43..5020dfba4b 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -1167,7 +1167,7 @@ void bus_unit_send_removed_signal(Unit *u) { int r; assert(u); - if (!u->sent_dbus_new_signal) + if (!u->sent_dbus_new_signal || u->in_dbus_queue) bus_unit_send_change_signal(u); if (!u->id) -- cgit v1.2.3-54-g00ecf From f35c467db30481be231fca0056b132b2214f2d42 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Fri, 9 Sep 2016 17:11:54 +0200 Subject: shared: recognize DNS names with more than one trailing dot as invalid (#4111) One trailing dot is valid, but more than one isn't. This also fixes glibc's posix/tst-getaddrinfo5 test. Fixes #3978. --- src/shared/dns-domain.c | 4 ++++ src/test/test-dns-domain.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index 835557c6b2..892f0aadf5 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -131,6 +131,10 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) { if (r == 0 && *n) return -EINVAL; + /* More than one trailing dot? */ + if (*n == '.') + return -EINVAL; + if (sz >= 1 && d) *d = 0; diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c index a9d09f59bc..e2f097c95e 100644 --- a/src/test/test-dns-domain.c +++ b/src/test/test-dns-domain.c @@ -48,6 +48,7 @@ static void test_dns_label_unescape(void) { test_dns_label_unescape_one("..", "", 20, -EINVAL); test_dns_label_unescape_one(".foobar", "", 20, -EINVAL); test_dns_label_unescape_one("foobar.", "foobar", 20, 6); + test_dns_label_unescape_one("foobar..", "foobar", 20, -EINVAL); } static void test_dns_name_to_wire_format_one(const char *what, const char *expect, size_t buffer_sz, int ret) { @@ -359,6 +360,7 @@ static void test_dns_name_is_valid_one(const char *s, int ret) { static void test_dns_name_is_valid(void) { test_dns_name_is_valid_one("foo", 1); test_dns_name_is_valid_one("foo.", 1); + test_dns_name_is_valid_one("foo..", 0); test_dns_name_is_valid_one("Foo", 1); test_dns_name_is_valid_one("foo.bar", 1); test_dns_name_is_valid_one("foo.bar.baz", 1); @@ -366,6 +368,7 @@ static void test_dns_name_is_valid(void) { test_dns_name_is_valid_one("foo..bar", 0); test_dns_name_is_valid_one(".foo.bar", 0); test_dns_name_is_valid_one("foo.bar.", 1); + test_dns_name_is_valid_one("foo.bar..", 0); test_dns_name_is_valid_one("\\zbar", 0); test_dns_name_is_valid_one("ä", 1); test_dns_name_is_valid_one("\n", 0); -- cgit v1.2.3-54-g00ecf From 7dd736abecd8048843d117de56c65bbf489a6f4f Mon Sep 17 00:00:00 2001 From: Kyle Russell Date: Sat, 10 Sep 2016 01:55:36 -0400 Subject: service: fixup ExecStop for socket-activated shutdown (#4120) Previous fix didn't consider handling multiple ExecStop commands. --- src/core/service.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/service.c b/src/core/service.c index 57f8d90ee5..99a70395fc 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1261,8 +1261,7 @@ static int service_spawn( /* ENOTCONN is legitimate if the endpoint disappeared on shutdown. * This connection is over, but the socket unit lives on. */ - if (r != -ENOTCONN || - (c != s->exec_command[SERVICE_EXEC_STOP] && c != s->exec_command[SERVICE_EXEC_STOP_POST])) + if (r != -ENOTCONN || !IN_SET(s->control_command_id, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST)) return r; } -- cgit v1.2.3-54-g00ecf From 4245eb507295522699215e35418c4c2716d6687c Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Sat, 10 Sep 2016 09:38:04 +0200 Subject: test-fs-util: also empty TEMP and TMP env vars (#4121) A follow-up for #3818 (992e8f2). --- src/test/test-fs-util.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 93eec3ef9c..b3c4a2a2eb 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -83,7 +83,7 @@ static void test_get_files_in_directory(void) { } static void test_var_tmp(void) { - _cleanup_free_ char *tmpdir_backup = NULL; + _cleanup_free_ char *tmpdir_backup = NULL, *temp_backup = NULL, *tmp_backup = NULL; const char *tmp_dir = NULL, *t; t = getenv("TMPDIR"); @@ -92,7 +92,21 @@ static void test_var_tmp(void) { assert_se(tmpdir_backup); } + t = getenv("TEMP"); + if (t) { + temp_backup = strdup(t); + assert_se(temp_backup); + } + + t = getenv("TMP"); + if (t) { + tmp_backup = strdup(t); + assert_se(tmp_backup); + } + assert(unsetenv("TMPDIR") >= 0); + assert(unsetenv("TEMP") >= 0); + assert(unsetenv("TMP") >= 0); assert_se(var_tmp_dir(&tmp_dir) >= 0); assert_se(streq(tmp_dir, "/var/tmp")); @@ -113,6 +127,16 @@ static void test_var_tmp(void) { assert_se(setenv("TMPDIR", tmpdir_backup, true) >= 0); assert_se(streq(getenv("TMPDIR"), tmpdir_backup)); } + + if (temp_backup) { + assert_se(setenv("TEMP", temp_backup, true) >= 0); + assert_se(streq(getenv("TEMP"), temp_backup)); + } + + if (tmp_backup) { + assert_se(setenv("TMP", tmp_backup, true) >= 0); + assert_se(streq(getenv("TMP"), tmp_backup)); + } } int main(int argc, char *argv[]) { -- cgit v1.2.3-54-g00ecf From ae9efab711e7478b4f035edd00824d518bcf0d3c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 10 Sep 2016 12:07:51 +0100 Subject: shared/install: fix set-default with empty root (#4118) https://bugzilla.redhat.com/show_bug.cgi?id=1374371 When root was empty or equal to "/", chroot_symlinks_same was called with root==NULL, and strjoina returned "", so the code thought both paths are equal even if they were not. Fix that by always providing a non-null first argument to strjoina. --- src/shared/install.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shared/install.c b/src/shared/install.c index 11770d887f..5f12fb447f 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -403,6 +403,9 @@ static bool chroot_symlinks_same(const char *root, const char *wd, const char *a /* This will give incorrect results if the paths are relative and go outside * of the chroot. False negatives are possible. */ + if (!root) + root = "/"; + a = strjoina(path_is_absolute(a) ? root : wd, "/", a); b = strjoina(path_is_absolute(b) ? root : wd, "/", b); return path_equal_or_files_same(a, b); -- cgit v1.2.3-54-g00ecf From f5b15d1b94717c65ea134cb56462d734a4c37a49 Mon Sep 17 00:00:00 2001 From: dwassenberg Date: Mon, 12 Sep 2016 14:29:55 +0200 Subject: hwdb: add Lenovo X1 Tablet pointing stick speed fix (#4128) Like many other recent thinkpads the factory default pointingstick sensitivity on these devices is quite low, making the pointingstick very slow in moving the cursor. This extends the existing hwdb rules for tweaking the sensitivity to also apply to the X1 Tablet models. Signed-off-by: Dennis Wassenberg --- hwdb/70-pointingstick.hwdb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index 5e2ab393bd..2b30896dff 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -108,6 +108,8 @@ evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??60 evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:* # Lenovo Thinkpad X1 Carbon 4th gen evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon4th:* +# Lenovo Thinkpad X1 Tablet +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Tablet:* POINTINGSTICK_SENSITIVITY=200 POINTINGSTICK_CONST_ACCEL=1.0 -- cgit v1.2.3-54-g00ecf From acb986015d9def3dd65a99ea4f0f893af44c6fc3 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 13 Sep 2016 07:18:13 +0100 Subject: Relicense hwdb/parse_hwdb.py as MIT (#4129) This parser will also be used in libinput, which uses the MIT license, so relicense this file to the more permissive license to make bidirectional code flow easier. parse_hwdb.py is only useful during building of the project, and is not part of the installation, so effectively both licenses are very similar. In particular, the licensing of binary packages produced by systemd is not influenced in any way, because the MIT licensed part is not installed. --- hwdb/parse_hwdb.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/hwdb/parse_hwdb.py b/hwdb/parse_hwdb.py index f55562250d..e163edbc51 100755 --- a/hwdb/parse_hwdb.py +++ b/hwdb/parse_hwdb.py @@ -1,22 +1,30 @@ #!/usr/bin/python3 -# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ +# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */ # -# This file is part of systemd. +# This file is part of systemd. It is distrubuted under the MIT license, see +# below. # -# Copyright 2016 Zbigniew Jędrzejewski-Szmek +# Copyright 2016 Zbigniew Jędrzejewski-Szmek # -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. +# The MIT License (MIT) # -# systemd is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -# You should have received a copy of the GNU Lesser General Public License -# along with systemd; If not, see . +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. import functools import glob -- cgit v1.2.3-54-g00ecf From 646853bdd8b1337204643aa014ff3f1f49d91a4f Mon Sep 17 00:00:00 2001 From: Topi Miettinen Date: Tue, 13 Sep 2016 06:20:38 +0000 Subject: fileio: simplify mkostemp_safe() (#4090) According to its manual page, flags given to mkostemp(3) shouldn't include O_RDWR, O_CREAT or O_EXCL flags as these are always included. Beyond those, the only flag that all callers (except a few tests where it probably doesn't matter) use is O_CLOEXEC, so set that unconditionally. --- src/basic/fileio.c | 8 ++++---- src/basic/fileio.h | 2 +- src/coredump/coredumpctl.c | 2 +- src/journal/journalctl.c | 2 +- src/journal/test-catalog.c | 4 ++-- src/journal/test-compress.c | 4 ++-- src/journal/test-mmap-cache.c | 6 +++--- src/shared/ask-password-api.c | 2 +- src/test/test-acl-util.c | 2 +- src/test/test-async.c | 2 +- src/test/test-clock.c | 2 +- src/test/test-copy.c | 12 ++++++------ src/test/test-fd-util.c | 8 ++++---- src/test/test-fdset.c | 16 ++++++++-------- src/test/test-fileio.c | 24 ++++++++++++------------ src/test/test-fs-util.c | 2 +- src/test/test-glob-util.c | 2 +- src/test/test-hostname-util.c | 2 +- src/test/test-stat-util.c | 4 ++-- src/test/test-terminal-util.c | 2 +- src/test/test-tmpfiles.c | 2 +- src/test/test-unit-file.c | 10 +++++----- 22 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index a5920e7d36..1cfb7a98f5 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -1043,7 +1043,7 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) { if (r < 0) return r; - fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC); + fd = mkostemp_safe(t); if (fd < 0) { free(t); return -errno; @@ -1076,7 +1076,7 @@ int fflush_and_check(FILE *f) { } /* This is much like mkostemp() but is subject to umask(). */ -int mkostemp_safe(char *pattern, int flags) { +int mkostemp_safe(char *pattern) { _cleanup_umask_ mode_t u = 0; int fd; @@ -1084,7 +1084,7 @@ int mkostemp_safe(char *pattern, int flags) { u = umask(077); - fd = mkostemp(pattern, flags); + fd = mkostemp(pattern, O_CLOEXEC); if (fd < 0) return -errno; @@ -1289,7 +1289,7 @@ int open_tmpfile_unlinkable(const char *directory, int flags) { /* Fall back to unguessable name + unlinking */ p = strjoina(directory, "/systemd-tmp-XXXXXX"); - fd = mkostemp_safe(p, flags); + fd = mkostemp_safe(p); if (fd < 0) return fd; diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 9ac497d9eb..b58c83e64a 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -71,7 +71,7 @@ int search_and_fopen_nulstr(const char *path, const char *mode, const char *root int fflush_and_check(FILE *f); int fopen_temporary(const char *path, FILE **_f, char **_temp_path); -int mkostemp_safe(char *pattern, int flags); +int mkostemp_safe(char *pattern); int tempfn_xxxxxx(const char *p, const char *extra, char **ret); int tempfn_random(const char *p, const char *extra, char **ret); diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index bbf8793e57..8ba7c08eed 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -620,7 +620,7 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { if (!temp) return log_oom(); - fdt = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC); + fdt = mkostemp_safe(temp); if (fdt < 0) return log_error_errno(fdt, "Failed to create temporary file: %m"); log_debug("Created temporary file %s", temp); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 381e219390..31074eb5f8 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -1632,7 +1632,7 @@ static int setup_keys(void) { n /= arg_interval; safe_close(fd); - fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC); + fd = mkostemp_safe(k); if (fd < 0) { r = log_error_errno(fd, "Failed to open %s: %m", k); goto finish; diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c index 898c876450..b7d9e7bffa 100644 --- a/src/journal/test-catalog.c +++ b/src/journal/test-catalog.c @@ -55,7 +55,7 @@ static Hashmap * test_import(const char* contents, ssize_t size, int code) { assert_se(h = hashmap_new(&catalog_hash_ops)); - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, contents, size) == size); @@ -182,7 +182,7 @@ static void test_catalog_update(void) { static char name[] = "/tmp/test-catalog.XXXXXX"; int r; - r = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + r = mkostemp_safe(name); assert_se(r >= 0); database = name; diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c index 68c9a4d76c..00e5222a1c 100644 --- a/src/journal/test-compress.c +++ b/src/journal/test-compress.c @@ -167,7 +167,7 @@ static void test_compress_stream(int compression, log_debug("/* test compression */"); - assert_se((dst = mkostemp_safe(pattern, O_RDWR|O_CLOEXEC)) >= 0); + assert_se((dst = mkostemp_safe(pattern)) >= 0); assert_se(compress(src, dst, -1) == 0); @@ -178,7 +178,7 @@ static void test_compress_stream(int compression, log_debug("/* test decompression */"); - assert_se((dst2 = mkostemp_safe(pattern2, O_RDWR|O_CLOEXEC)) >= 0); + assert_se((dst2 = mkostemp_safe(pattern2)) >= 0); assert_se(stat(srcfile, &st) == 0); diff --git a/src/journal/test-mmap-cache.c b/src/journal/test-mmap-cache.c index 009aabf55e..0ad49aeb5f 100644 --- a/src/journal/test-mmap-cache.c +++ b/src/journal/test-mmap-cache.c @@ -36,15 +36,15 @@ int main(int argc, char *argv[]) { assert_se(m = mmap_cache_new()); - x = mkostemp_safe(px, O_RDWR|O_CLOEXEC); + x = mkostemp_safe(px); assert_se(x >= 0); unlink(px); - y = mkostemp_safe(py, O_RDWR|O_CLOEXEC); + y = mkostemp_safe(py); assert_se(y >= 0); unlink(py); - z = mkostemp_safe(pz, O_RDWR|O_CLOEXEC); + z = mkostemp_safe(pz); assert_se(z >= 0); unlink(pz); diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 65151b19a6..2597cfc648 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -484,7 +484,7 @@ int ask_password_agent( (void) mkdir_p_label("/run/systemd/ask-password", 0755); - fd = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC); + fd = mkostemp_safe(temp); if (fd < 0) { r = fd; goto finish; diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c index 430dda8e78..5b572bb0bf 100644 --- a/src/test/test-acl-util.c +++ b/src/test/test-acl-util.c @@ -35,7 +35,7 @@ static void test_add_acls_for_user(void) { uid_t uid; int r; - fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(fn); assert_se(fd >= 0); /* Use the mode that user journal files use */ diff --git a/src/test/test-async.c b/src/test/test-async.c index ada6d67c42..4ebc27f0bd 100644 --- a/src/test/test-async.c +++ b/src/test/test-async.c @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) { int fd; char name[] = "/tmp/test-asynchronous_close.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); asynchronous_close(fd); diff --git a/src/test/test-clock.c b/src/test/test-clock.c index 84f775e5bc..7d97328416 100644 --- a/src/test/test-clock.c +++ b/src/test/test-clock.c @@ -55,7 +55,7 @@ static void test_clock_is_localtime(void) { /* without an adjtime file we default to UTC */ assert_se(clock_is_localtime("/nonexisting/adjtime") == 0); - fd = mkostemp_safe(adjtime, O_WRONLY|O_CLOEXEC); + fd = mkostemp_safe(adjtime); assert_se(fd >= 0); log_info("adjtime test file: %s", adjtime); f = fdopen(fd, "w"); diff --git a/src/test/test-copy.c b/src/test/test-copy.c index 68154fc4e8..ed1ea51dbd 100644 --- a/src/test/test-copy.c +++ b/src/test/test-copy.c @@ -42,11 +42,11 @@ static void test_copy_file(void) { log_info("%s", __func__); - fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(fn); assert_se(fd >= 0); close(fd); - fd = mkostemp_safe(fn_copy, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(fn_copy); assert_se(fd >= 0); close(fd); @@ -71,9 +71,9 @@ static void test_copy_file_fd(void) { log_info("%s", __func__); - in_fd = mkostemp_safe(in_fn, O_RDWR); + in_fd = mkostemp_safe(in_fn); assert_se(in_fd >= 0); - out_fd = mkostemp_safe(out_fn, O_RDWR); + out_fd = mkostemp_safe(out_fn); assert_se(out_fd >= 0); assert_se(write_string_file(in_fn, text, WRITE_STRING_FILE_CREATE) == 0); @@ -207,10 +207,10 @@ static void test_copy_bytes_regular_file(const char *src, bool try_reflink, uint fd = open(src, O_RDONLY | O_CLOEXEC | O_NOCTTY); assert_se(fd >= 0); - fd2 = mkostemp_safe(fn2, O_RDWR); + fd2 = mkostemp_safe(fn2); assert_se(fd2 >= 0); - fd3 = mkostemp_safe(fn3, O_WRONLY); + fd3 = mkostemp_safe(fn3); assert_se(fd3 >= 0); r = copy_bytes(fd, fd2, max_bytes, try_reflink); diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c index 421d3bdeb3..f555bb976c 100644 --- a/src/test/test-fd-util.c +++ b/src/test/test-fd-util.c @@ -31,9 +31,9 @@ static void test_close_many(void) { char name1[] = "/tmp/test-close-many.XXXXXX"; char name2[] = "/tmp/test-close-many.XXXXXX"; - fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC); - fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC); - fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC); + fds[0] = mkostemp_safe(name0); + fds[1] = mkostemp_safe(name1); + fds[2] = mkostemp_safe(name2); close_many(fds, 2); @@ -52,7 +52,7 @@ static void test_close_nointr(void) { char name[] = "/tmp/test-test-close_nointr.XXXXXX"; int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(close_nointr(fd) >= 0); assert_se(close_nointr(fd) < 0); diff --git a/src/test/test-fdset.c b/src/test/test-fdset.c index 282aab1246..adbf99a7ec 100644 --- a/src/test/test-fdset.c +++ b/src/test/test-fdset.c @@ -31,7 +31,7 @@ static void test_fdset_new_fill(void) { _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_new_fill.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(fdset_new_fill(&fdset) >= 0); assert_se(fdset_contains(fdset, fd)); @@ -45,7 +45,7 @@ static void test_fdset_put_dup(void) { _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_put_dup.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -64,7 +64,7 @@ static void test_fdset_cloexec(void) { int flags = -1; char name[] = "/tmp/test-fdset_cloexec.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -91,7 +91,7 @@ static void test_fdset_close_others(void) { int flags = -1; char name[] = "/tmp/test-fdset_close_others.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -113,7 +113,7 @@ static void test_fdset_remove(void) { FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_remove.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -136,7 +136,7 @@ static void test_fdset_iterate(void) { int c = 0; int a; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -161,7 +161,7 @@ static void test_fdset_isempty(void) { _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_isempty.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -179,7 +179,7 @@ static void test_fdset_steal_first(void) { _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_steal_first.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index 79609765e0..92663ef66f 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -45,11 +45,11 @@ static void test_parse_env_file(void) { char **i; unsigned k; - fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(p); assert_se(fd >= 0); close(fd); - fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(t); assert_se(fd >= 0); f = fdopen(fd, "w"); @@ -158,11 +158,11 @@ static void test_parse_multiline_env_file(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL; char **i; - fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(p); assert_se(fd >= 0); close(fd); - fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(t); assert_se(fd >= 0); f = fdopen(fd, "w"); @@ -211,7 +211,7 @@ static void test_executable_is_script(void) { FILE *f; char *command; - fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(t); assert_se(fd >= 0); f = fdopen(fd, "w"); @@ -300,7 +300,7 @@ static void test_write_string_stream(void) { int fd; char buf[64]; - fd = mkostemp_safe(fn, O_RDWR); + fd = mkostemp_safe(fn); assert_se(fd >= 0); f = fdopen(fd, "r"); @@ -334,7 +334,7 @@ static void test_write_string_file(void) { char buf[64] = {}; _cleanup_close_ int fd; - fd = mkostemp_safe(fn, O_RDWR); + fd = mkostemp_safe(fn); assert_se(fd >= 0); assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0); @@ -350,7 +350,7 @@ static void test_write_string_file_no_create(void) { _cleanup_close_ int fd; char buf[64] = {0}; - fd = mkostemp_safe(fn, O_RDWR); + fd = mkostemp_safe(fn); assert_se(fd >= 0); assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0); @@ -390,7 +390,7 @@ static void test_load_env_file_pairs(void) { _cleanup_strv_free_ char **l = NULL; char **k, **v; - fd = mkostemp_safe(fn, O_RDWR); + fd = mkostemp_safe(fn); assert_se(fd >= 0); r = write_string_file(fn, @@ -433,7 +433,7 @@ static void test_search_and_fopen(void) { int r; FILE *f; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); close(fd); @@ -469,7 +469,7 @@ static void test_search_and_fopen_nulstr(void) { int r; FILE *f; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); close(fd); @@ -504,7 +504,7 @@ static void test_writing_tmpfile(void) { IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n"); IOVEC_SET_STRING(iov[2], ""); - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); printf("tmpfile: %s", name); r = writev(fd, iov, 3); diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index b3c4a2a2eb..b35a2ea2c8 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -34,7 +34,7 @@ static void test_unlink_noerrno(void) { char name[] = "/tmp/test-close_nointr.XXXXXX"; int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(close_nointr(fd) >= 0); diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c index 227d4290f0..9eea3eb608 100644 --- a/src/test/test-glob-util.c +++ b/src/test/test-glob-util.c @@ -30,7 +30,7 @@ static void test_glob_exists(void) { int fd = -1; int r; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); close(fd); diff --git a/src/test/test-hostname-util.c b/src/test/test-hostname-util.c index 1c3d13ed1d..d2c3ea5e0d 100644 --- a/src/test/test-hostname-util.c +++ b/src/test/test-hostname-util.c @@ -104,7 +104,7 @@ static void test_read_hostname_config(void) { char *hostname; int fd; - fd = mkostemp_safe(path, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(path); assert(fd > 0); close(fd); diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c index a10227f823..6c34250a01 100644 --- a/src/test/test-stat-util.c +++ b/src/test/test-stat-util.c @@ -31,7 +31,7 @@ static void test_files_same(void) { char name[] = "/tmp/test-files_same.XXXXXX"; char name_alias[] = "/tmp/test-files_same.alias"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(symlink(name, name_alias) >= 0); @@ -47,7 +47,7 @@ static void test_is_symlink(void) { char name_link[] = "/tmp/test-is_symlink.link"; _cleanup_close_ int fd = -1; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(symlink(name, name_link) >= 0); diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c index 84b448a095..373a1b70ba 100644 --- a/src/test/test-terminal-util.c +++ b/src/test/test-terminal-util.c @@ -50,7 +50,7 @@ static void test_read_one_char(void) { char name[] = "/tmp/test-read_one_char.XXXXXX"; int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); file = fdopen(fd, "r+"); assert_se(file); diff --git a/src/test/test-tmpfiles.c b/src/test/test-tmpfiles.c index b34ebeefb2..f35e6793b7 100644 --- a/src/test/test-tmpfiles.c +++ b/src/test/test-tmpfiles.c @@ -51,7 +51,7 @@ int main(int argc, char** argv) { log_debug("link1: %s", ans); assert_se(endswith(ans, " (deleted)")); - fd2 = mkostemp_safe(pattern, O_RDWR|O_CLOEXEC); + fd2 = mkostemp_safe(pattern); assert_se(fd >= 0); assert_se(unlink(pattern) == 0); diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index ade0ff2a63..193de26173 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -485,7 +485,7 @@ static void test_load_env_file_1(void) { char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1)); @@ -508,7 +508,7 @@ static void test_load_env_file_2(void) { char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2)); @@ -526,7 +526,7 @@ static void test_load_env_file_3(void) { char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3)); @@ -542,7 +542,7 @@ static void test_load_env_file_4(void) { _cleanup_close_ int fd; int r; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4)); @@ -562,7 +562,7 @@ static void test_load_env_file_5(void) { char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5)); -- cgit v1.2.3-54-g00ecf From e788ef482f951ee07ba029e8a80e3bff026a70c9 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 12 Sep 2016 18:46:19 +0100 Subject: man: "disabled on" does not sound right --- man/dnssec-trust-anchors.d.xml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/man/dnssec-trust-anchors.d.xml b/man/dnssec-trust-anchors.d.xml index 4bdc167f79..9a28862ceb 100644 --- a/man/dnssec-trust-anchors.d.xml +++ b/man/dnssec-trust-anchors.d.xml @@ -160,14 +160,12 @@ Negative Trust Anchors - Negative trust anchors define domains where DNSSEC - validation shall be turned off. Negative trust anchor files are - found at the same location as positive trust anchor files, and - follow the same overriding rules. They are text files with the - .negative suffix. Empty lines and lines whose - first character is ; are ignored. Each line - specifies one domain name where DNSSEC validation shall be - disabled on. + Negative trust anchors define domains where DNSSEC validation shall be turned + off. Negative trust anchor files are found at the same location as positive trust anchor files, + and follow the same overriding rules. They are text files with the + .negative suffix. Empty lines and lines whose first character is + ; are ignored. Each line specifies one domain name which is the root of a DNS + subtree where validation shall be disabled. Negative trust anchors are useful to support private DNS subtrees that are not referenced from the Internet DNS hierarchy, -- cgit v1.2.3-54-g00ecf From 303a2ebcb600e475fd8b87caef81cf3790f0fa81 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 12 Sep 2016 19:03:35 +0100 Subject: udev: use get_proc_cmdline_key instead of FOREACH_WORD_QUOTED --- src/udev/net/link-config.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index eedd94e777..ece9248c2a 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -191,20 +191,12 @@ static int load_link(link_config_ctx *ctx, const char *filename) { } static bool enable_name_policy(void) { - _cleanup_free_ char *line = NULL; - const char *word, *state; + _cleanup_free_ char *value = NULL; int r; - size_t l; - r = proc_cmdline(&line); - if (r < 0) { - log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m"); - return true; - } - - FOREACH_WORD_QUOTED(word, l, line, state) - if (strneq(word, "net.ifnames=0", l)) - return false; + r = get_proc_cmdline_key("net.ifnames=", &value); + if (r > 0 && streq(value, "0")) + return false; return true; } -- cgit v1.2.3-54-g00ecf From 1b4cd64683ba057cb3d4c5cd311b1c25e6d8d614 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 12 Sep 2016 19:24:45 +0100 Subject: journal-remote: implement %m support in mhd_respondf errno value is not protected (it is undefined after this function returns). Various mhd_* functions are not documented to protect errno, so this could not guaranteed anyway. --- src/hostname/hostnamed.c | 8 ++++---- src/journal-remote/journal-gatewayd.c | 18 +++++++++--------- src/journal-remote/journal-remote.c | 17 ++++++++--------- src/journal-remote/microhttpd-util.c | 4 ++++ src/journal-remote/microhttpd-util.h | 3 ++- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 080a2cd138..197f905b7d 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -451,7 +451,7 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error * r = context_update_kernel_hostname(c); if (r < 0) { log_error_errno(r, "Failed to set host name: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m"); } log_info("Changed host name to '%s'", strna(c->data[PROP_HOSTNAME])); @@ -512,13 +512,13 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_ r = context_update_kernel_hostname(c); if (r < 0) { log_error_errno(r, "Failed to set host name: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m"); } r = context_write_data_static_hostname(c); if (r < 0) { log_error_errno(r, "Failed to write static host name: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %m"); } log_info("Changed static host name to '%s'", strna(c->data[PROP_STATIC_HOSTNAME])); @@ -593,7 +593,7 @@ static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_mess r = context_write_data_machine_info(c); if (r < 0) { log_error_errno(r, "Failed to write machine info: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %m"); } log_info("Changed %s to '%s'", diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index c2b5a5f205..05e9b7253a 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -475,7 +475,7 @@ static int request_handler_entries( r = open_journal(m); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m\n"); if (request_parse_accept(m, connection) < 0) return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n"); @@ -633,7 +633,7 @@ static int request_handler_fields( r = open_journal(m); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m\n"); if (request_parse_accept(m, connection) < 0) return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n"); @@ -699,10 +699,10 @@ static int request_handler_file( fd = open(path, O_RDONLY|O_CLOEXEC); if (fd < 0) - return mhd_respondf(connection, MHD_HTTP_NOT_FOUND, "Failed to open file %s: %m\n", path); + return mhd_respondf(connection, errno, MHD_HTTP_NOT_FOUND, "Failed to open file %s: %m\n", path); if (fstat(fd, &st) < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m\n"); + return mhd_respondf(connection, errno, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m\n"); response = MHD_create_response_from_fd_at_offset64(st.st_size, fd, 0); if (!response) @@ -766,15 +766,15 @@ static int request_handler_machine( r = open_journal(m); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m\n"); r = sd_id128_get_machine(&mid); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine machine ID: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine machine ID: %m\n"); r = sd_id128_get_boot(&bid); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine boot ID: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine boot ID: %m\n"); hostname = gethostname_malloc(); if (!hostname) @@ -782,11 +782,11 @@ static int request_handler_machine( r = sd_journal_get_usage(m->journal, &usage); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n"); r = sd_journal_get_cutoff_realtime_usec(m->journal, &cutoff_from, &cutoff_to); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n"); if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL) == -ENOENT) (void) parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL); diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index 80e2adb100..a3884f574a 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -524,13 +524,12 @@ static int process_http_upload( log_warning("Failed to process data for connection %p", connection); if (r == -E2BIG) return mhd_respondf(connection, - MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, - "Entry is too large, maximum is %u bytes.\n", - DATA_SIZE_MAX); + r, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, + "Entry is too large, maximum is " STRINGIFY(DATA_SIZE_MAX) " bytes.\n"); else return mhd_respondf(connection, - MHD_HTTP_UNPROCESSABLE_ENTITY, - "Processing failed: %s.", strerror(-r)); + r, MHD_HTTP_UNPROCESSABLE_ENTITY, + "Processing failed: %m."); } } @@ -541,8 +540,9 @@ static int process_http_upload( remaining = source_non_empty(source); if (remaining > 0) { - log_warning("Premature EOFbyte. %zu bytes lost.", remaining); - return mhd_respondf(connection, MHD_HTTP_EXPECTATION_FAILED, + log_warning("Premature EOF byte. %zu bytes lost.", remaining); + return mhd_respondf(connection, + 0, MHD_HTTP_EXPECTATION_FAILED, "Premature EOF. %zu bytes of trailing data not processed.", remaining); } @@ -623,8 +623,7 @@ static int request_handler( if (r == -ENOMEM) return respond_oom(connection); else if (r < 0) - return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, - strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "%m"); hostname = NULL; return MHD_YES; diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c index 2f16b02e9a..67d97e24ff 100644 --- a/src/journal-remote/microhttpd-util.c +++ b/src/journal-remote/microhttpd-util.c @@ -82,6 +82,7 @@ int mhd_respond_oom(struct MHD_Connection *connection) { } int mhd_respondf(struct MHD_Connection *connection, + int error, enum MHD_RequestTerminationCode code, const char *format, ...) { @@ -92,6 +93,9 @@ int mhd_respondf(struct MHD_Connection *connection, assert(connection); assert(format); + if (error < 0) + error = -error; + errno = -error; va_start(ap, format); r = vasprintf(&m, format, ap); va_end(ap); diff --git a/src/journal-remote/microhttpd-util.h b/src/journal-remote/microhttpd-util.h index ea160f212b..af26ab69fe 100644 --- a/src/journal-remote/microhttpd-util.h +++ b/src/journal-remote/microhttpd-util.h @@ -39,8 +39,9 @@ void microhttpd_logger(void *arg, const char *fmt, va_list ap) _printf_(2, 0); #define respond_oom(connection) log_oom(), mhd_respond_oom(connection) int mhd_respondf(struct MHD_Connection *connection, + int error, unsigned code, - const char *format, ...) _printf_(3,4); + const char *format, ...) _printf_(4,5); int mhd_respond(struct MHD_Connection *connection, unsigned code, -- cgit v1.2.3-54-g00ecf From f5e757f1ce84c1d6ae932cf2b604238fb4cedc00 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 12 Sep 2016 19:33:37 +0100 Subject: microhttpd-util: add the trailing newline automatically It's prone to error and annoying to have to add it manually. It was missing from a few places. --- src/journal-remote/journal-gatewayd.c | 37 +++++++++++++++++------------------ src/journal-remote/journal-remote.c | 17 +++++++--------- src/journal-remote/microhttpd-util.c | 16 ++++++++++----- 3 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index 05e9b7253a..54f42b8bf3 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -475,20 +475,20 @@ static int request_handler_entries( r = open_journal(m); if (r < 0) - return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m\n"); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m"); if (request_parse_accept(m, connection) < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header."); if (request_parse_range(m, connection) < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Range header.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Range header."); if (request_parse_arguments(m, connection) < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse URL arguments.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse URL arguments."); if (m->discrete) { if (!m->cursor) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Discrete seeks require a cursor specification.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Discrete seeks require a cursor specification."); m->n_entries = 1; m->n_entries_set = true; @@ -501,7 +501,7 @@ static int request_handler_entries( else if (m->n_skip < 0) r = sd_journal_seek_tail(m->journal); if (r < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to seek in journal.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to seek in journal."); response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_entries, m, NULL); if (!response) @@ -633,14 +633,14 @@ static int request_handler_fields( r = open_journal(m); if (r < 0) - return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m\n"); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m"); if (request_parse_accept(m, connection) < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header."); r = sd_journal_query_unique(m->journal, field); if (r < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to query unique fields.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to query unique fields."); response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_fields, m, NULL); if (!response) @@ -699,10 +699,10 @@ static int request_handler_file( fd = open(path, O_RDONLY|O_CLOEXEC); if (fd < 0) - return mhd_respondf(connection, errno, MHD_HTTP_NOT_FOUND, "Failed to open file %s: %m\n", path); + return mhd_respondf(connection, errno, MHD_HTTP_NOT_FOUND, "Failed to open file %s: %m", path); if (fstat(fd, &st) < 0) - return mhd_respondf(connection, errno, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m\n"); + return mhd_respondf(connection, errno, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m"); response = MHD_create_response_from_fd_at_offset64(st.st_size, fd, 0); if (!response) @@ -766,15 +766,15 @@ static int request_handler_machine( r = open_journal(m); if (r < 0) - return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m\n"); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m"); r = sd_id128_get_machine(&mid); if (r < 0) - return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine machine ID: %m\n"); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine machine ID: %m"); r = sd_id128_get_boot(&bid); if (r < 0) - return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine boot ID: %m\n"); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine boot ID: %m"); hostname = gethostname_malloc(); if (!hostname) @@ -782,11 +782,11 @@ static int request_handler_machine( r = sd_journal_get_usage(m->journal, &usage); if (r < 0) - return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n"); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s"); r = sd_journal_get_cutoff_realtime_usec(m->journal, &cutoff_from, &cutoff_to); if (r < 0) - return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n"); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s"); if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL) == -ENOENT) (void) parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL); @@ -844,8 +844,7 @@ static int request_handler( assert(method); if (!streq(method, "GET")) - return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, - "Unsupported method.\n"); + return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, "Unsupported method."); if (!*connection_cls) { @@ -875,7 +874,7 @@ static int request_handler( if (streq(url, "/machine")) return request_handler_machine(connection, *connection_cls); - return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found.\n"); + return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found."); } static void help(void) { diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index a3884f574a..aebc4cafb4 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -525,7 +525,7 @@ static int process_http_upload( if (r == -E2BIG) return mhd_respondf(connection, r, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, - "Entry is too large, maximum is " STRINGIFY(DATA_SIZE_MAX) " bytes.\n"); + "Entry is too large, maximum is " STRINGIFY(DATA_SIZE_MAX) " bytes."); else return mhd_respondf(connection, r, MHD_HTTP_UNPROCESSABLE_ENTITY, @@ -547,7 +547,7 @@ static int process_http_upload( remaining); } - return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK.\n"); + return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK."); }; static int request_handler( @@ -577,19 +577,16 @@ static int request_handler( *connection_cls); if (!streq(method, "POST")) - return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, - "Unsupported method.\n"); + return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, "Unsupported method."); if (!streq(url, "/upload")) - return mhd_respond(connection, MHD_HTTP_NOT_FOUND, - "Not found.\n"); + return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found."); header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Type"); if (!header || !streq(header, "application/vnd.fdo.journal")) return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE, - "Content-Type: application/vnd.fdo.journal" - " is required.\n"); + "Content-Type: application/vnd.fdo.journal is required."); { const union MHD_ConnectionInfo *ci; @@ -599,7 +596,7 @@ static int request_handler( if (!ci) { log_error("MHD_get_connection_info failed: cannot get remote fd"); return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, - "Cannot check remote address"); + "Cannot check remote address."); } fd = ci->connect_fd; @@ -614,7 +611,7 @@ static int request_handler( r = getpeername_pretty(fd, false, &hostname); if (r < 0) return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, - "Cannot check remote hostname"); + "Cannot check remote hostname."); } assert(hostname); diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c index 67d97e24ff..cae10203c6 100644 --- a/src/journal-remote/microhttpd-util.c +++ b/src/journal-remote/microhttpd-util.c @@ -48,7 +48,7 @@ void microhttpd_logger(void *arg, const char *fmt, va_list ap) { static int mhd_respond_internal(struct MHD_Connection *connection, enum MHD_RequestTerminationCode code, - char *buffer, + const char *buffer, size_t size, enum MHD_ResponseMemoryMode mode) { struct MHD_Response *response; @@ -56,7 +56,7 @@ static int mhd_respond_internal(struct MHD_Connection *connection, assert(connection); - response = MHD_create_response_from_buffer(size, buffer, mode); + response = MHD_create_response_from_buffer(size, (char*) buffer, mode); if (!response) return MHD_NO; @@ -72,13 +72,17 @@ int mhd_respond(struct MHD_Connection *connection, enum MHD_RequestTerminationCode code, const char *message) { + const char *fmt; + + fmt = strjoina(message, "\n"); + return mhd_respond_internal(connection, code, - (char*) message, strlen(message), + fmt, strlen(message) + 1, MHD_RESPMEM_PERSISTENT); } int mhd_respond_oom(struct MHD_Connection *connection) { - return mhd_respond(connection, MHD_HTTP_SERVICE_UNAVAILABLE, "Out of memory.\n"); + return mhd_respond(connection, MHD_HTTP_SERVICE_UNAVAILABLE, "Out of memory."); } int mhd_respondf(struct MHD_Connection *connection, @@ -86,6 +90,7 @@ int mhd_respondf(struct MHD_Connection *connection, enum MHD_RequestTerminationCode code, const char *format, ...) { + const char *fmt; char *m; int r; va_list ap; @@ -96,8 +101,9 @@ int mhd_respondf(struct MHD_Connection *connection, if (error < 0) error = -error; errno = -error; + fmt = strjoina(format, "\n"); va_start(ap, format); - r = vasprintf(&m, format, ap); + r = vasprintf(&m, fmt, ap); va_end(ap); if (r < 0) -- cgit v1.2.3-54-g00ecf From 581fc868bed69d8d693c034cca3685b19eacc2fa Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 12 Sep 2016 19:41:33 +0100 Subject: journal-verify: get rid of strerror --- src/journal/journal-verify.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 4105abfccc..9e4d8a28a5 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -118,6 +118,11 @@ static void flush_progress(void) { log_error(OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \ } while (0) +#define error_errno(_offset, error, _fmt, ...) do { \ + flush_progress(); \ + log_error_errno(error, OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \ + } while (0) + static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o) { uint64_t i; @@ -168,8 +173,8 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o le64toh(o->object.size) - offsetof(Object, data.payload), &b, &alloc, &b_size, 0); if (r < 0) { - error(offset, "%s decompression failed: %s", - object_compressed_to_string(compression), strerror(-r)); + error_errno(offset, r, "%s decompression failed: %m", + object_compressed_to_string(compression)); return r; } @@ -912,7 +917,7 @@ int journal_file_verify( r = journal_file_object_verify(f, p, o); if (r < 0) { - error(p, "Invalid object contents: %s", strerror(-r)); + error_errno(p, r, "Invalid object contents: %m"); goto fail; } -- cgit v1.2.3-54-g00ecf From 048c386eee9135d2fae9f4120103cea46dad4e2e Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 12 Sep 2016 19:54:35 +0100 Subject: tree-wide: use %m in calls to sd_bus_error_set_errnof sd_bus_error_set_errnof supports %m, so there's no need to call strerror manually. --- src/locale/localed.c | 6 +++--- src/machine/machined-dbus.c | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/locale/localed.c b/src/locale/localed.c index 298f176e40..1cb049e74a 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -334,7 +334,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er r = locale_write_data(c, &settings); if (r < 0) { log_error_errno(r, "Failed to set locale: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set locale: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set locale: %m"); } locale_update_system_manager(c, sd_bus_message_get_bus(m)); @@ -403,7 +403,7 @@ static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_erro r = vconsole_write_data(c); if (r < 0) { log_error_errno(r, "Failed to set virtual console keymap: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set virtual console keymap: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set virtual console keymap: %m"); } log_info("Changed virtual console keymap to '%s' toggle '%s'", @@ -592,7 +592,7 @@ static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_err r = x11_write_data(c); if (r < 0) { log_error_errno(r, "Failed to set X11 keyboard layout: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set X11 keyboard layout: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set X11 keyboard layout: %m"); } log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'", diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 5e2462cba2..e40f40a263 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -444,7 +444,9 @@ static int method_register_machine_internal(sd_bus_message *message, bool read_n r = cg_pid_get_unit(m->leader, &m->unit); if (r < 0) { - r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r)); + r = sd_bus_error_set_errnof(error, r, + "Failed to determine unit of process "PID_FMT" : %m", + m->leader); goto fail; } -- cgit v1.2.3-54-g00ecf From 9eec7d12eda398fbc4a1db880bd4a13bc1c58db4 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 12 Sep 2016 19:55:34 +0100 Subject: tests: get rid of strerror --- src/journal/test-journal-interleaving.c | 7 +++---- src/libsystemd/sd-bus/test-bus-chat.c | 2 +- src/test/test-engine.c | 2 +- src/test/test-execute.c | 2 +- src/test/test-path.c | 2 +- src/test/test-sched-prio.c | 2 +- src/test/test-unit-file.c | 8 ++++---- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c index 5e063f4d04..35cae23bf8 100644 --- a/src/journal/test-journal-interleaving.c +++ b/src/journal/test-journal-interleaving.c @@ -36,10 +36,9 @@ static bool arg_keep = false; -noreturn static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) { - log_internal(LOG_CRIT, 0, file, line, func, - "'%s' failed at %s:%u (%s): %s.", - text, file, line, func, strerror(eno)); +noreturn static void log_assert_errno(const char *text, int error, const char *file, int line, const char *func) { + log_internal(LOG_CRIT, error, file, line, func, + "'%s' failed at %s:%u (%s): %m", text, file, line, func); abort(); } diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c index 048c0d19e2..fc60830059 100644 --- a/src/libsystemd/sd-bus/test-bus-chat.c +++ b/src/libsystemd/sd-bus/test-bus-chat.c @@ -351,7 +351,7 @@ finish: static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { bool *x = userdata; - log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m))); + log_error_errno(sd_bus_message_get_errno(m), "Quit callback: %m"); *x = 1; return 1; diff --git a/src/test/test-engine.c b/src/test/test-engine.c index 23da10fa1a..a651f6b683 100644 --- a/src/test/test-engine.c +++ b/src/test/test-engine.c @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) { assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 05ec1d2eb1..1db7f78041 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -324,7 +324,7 @@ static int run_tests(UnitFileScope scope, test_function_t *tests) { r = manager_new(scope, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %n"); return EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-path.c b/src/test/test-path.c index 62181e22a0..4d3f0e9948 100644 --- a/src/test/test-path.c +++ b/src/test/test-path.c @@ -47,7 +47,7 @@ static int setup_test(Manager **m) { r = manager_new(UNIT_FILE_USER, true, &tmp); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return -EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c index c068f5c39e..7b37910c33 100644 --- a/src/test/test-sched-prio.c +++ b/src/test/test-sched-prio.c @@ -40,7 +40,7 @@ int main(int argc, char *argv[]) { assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index ade0ff2a63..a5009f98ef 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -56,12 +56,12 @@ static int test_unit_file_get_set(void) { r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL); if (r == -EPERM || r == -EACCES) { - printf("Skipping test: unit_file_get_list: %s", strerror(-r)); + log_notice_errno(r, "Skipping test: unit_file_get_list: %m"); return EXIT_TEST_SKIP; } - log_full(r == 0 ? LOG_INFO : LOG_ERR, - "unit_file_get_list: %s", strerror(-r)); + log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r, + "unit_file_get_list: %m"); if (r < 0) return EXIT_FAILURE; @@ -117,7 +117,7 @@ static void test_config_parse_exec(void) { r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return; } -- cgit v1.2.3-54-g00ecf From 432b5c8a4df006d29531f73b2d980d5908f4e0c5 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 12 Sep 2016 19:56:50 +0100 Subject: TODO: remove strerror entry I believe the remaining call sites are legitimate uses which cannot be easily replaced with %m. --- TODO | 2 -- 1 file changed, 2 deletions(-) diff --git a/TODO b/TODO index 88bf48d0d9..ba65f7f40f 100644 --- a/TODO +++ b/TODO @@ -27,8 +27,6 @@ Janitorial Clean-ups: * replace manual readdir() loops with FOREACH_DIRENT or FOREACH_DIRENT_ALL -* Get rid of the last strerror() invocations in favour of %m and strerror_r() - * Rearrange tests so that the various test-xyz.c match a specific src/basic/xyz.c again Features: -- cgit v1.2.3-54-g00ecf From 481a2b02a3e7881b0c62ff6bca9f17d2d6fabc9f Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 12 Sep 2016 20:09:36 +0100 Subject: Always use unicode ellipsis when ellipsizing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were already unconditionally using the unicode character when the input string was not pure ASCII, leading to different behaviour in depending on the input string. systemd[1]: Starting printit.service. python3[19962]: foooooooooooooooooooooooooooooooooooo…oooo python3[19964]: fooąęoooooooooooooooooooooooooooooooo…oooo python3[19966]: fooąęoooooooooooooooooooooooooooooooo…ąęąę python3[19968]: fooąęoooooooooooooooooąęąęąęąęąęąęąęą…ąęąę systemd[1]: Started printit.service. --- TODO | 2 -- src/basic/string-util.c | 12 ++++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/TODO b/TODO index ba65f7f40f..13d0e47d97 100644 --- a/TODO +++ b/TODO @@ -112,8 +112,6 @@ Features: * journald: sigbus API via a signal-handler safe function that people may call from the SIGBUS handler -* when using UTF8, ellipsize with "…" rather than "...", so that we can show more contents before truncating - * move specifier expansion from service_spawn() into load-fragment.c * optionally, also require WATCHDOG=1 notifications during service start-up and shutdown diff --git a/src/basic/string-util.c b/src/basic/string-util.c index 5d4510e1b3..dc7de5dab8 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -443,7 +443,7 @@ static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_le if (old_length <= 3 || old_length <= new_length) return strndup(s, old_length); - r = new0(char, new_length+1); + r = new0(char, new_length+3); if (!r) return NULL; @@ -453,12 +453,12 @@ static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_le x = new_length - 3; memcpy(r, s, x); - r[x] = '.'; - r[x+1] = '.'; - r[x+2] = '.'; + r[x] = 0xe2; /* tri-dot ellipsis: … */ + r[x+1] = 0x80; + r[x+2] = 0xa6; memcpy(r + x + 3, - s + old_length - (new_length - x - 3), - new_length - x - 3); + s + old_length - (new_length - x - 1), + new_length - x - 1); return r; } -- cgit v1.2.3-54-g00ecf From e031c227cbbe7243212ecb38a6db105a93655eae Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 12 Sep 2016 20:20:33 +0100 Subject: TODO: remove duplicated item --- TODO | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/TODO b/TODO index 13d0e47d97..a833a3158d 100644 --- a/TODO +++ b/TODO @@ -23,7 +23,8 @@ External: Janitorial Clean-ups: -* code cleanup: retire FOREACH_WORD_QUOTED, port to extract_first_word() loops instead +* code cleanup: retire FOREACH_WORD_QUOTED, port to extract_first_word() loops instead. + For example, most conf parsing callbacks should use it. * replace manual readdir() loops with FOREACH_DIRENT or FOREACH_DIRENT_ALL @@ -196,7 +197,7 @@ Features: * synchronize console access with BSD locks: http://lists.freedesktop.org/archives/systemd-devel/2014-October/024582.html -* as soon as we have kdbus, and sender timestamps, revisit coalescing multiple parallel daemon reloads: +* as soon as we have sender timestamps, revisit coalescing multiple parallel daemon reloads: http://lists.freedesktop.org/archives/systemd-devel/2014-December/025862.html * in systemctl list-unit-files: show the install value the presets would suggest for a service in a third column @@ -236,10 +237,6 @@ Features: * timesyncd: add ugly bus calls to set NTP servers per-interface, for usage by NM -* extract_many_words() should probably be used by a lot of code that - currently uses FOREACH_WORD and friends. For example, most conf - parsing callbacks should use it. - * merge ~/.local/share and ~/.local/lib into one similar /usr/lib and /usr/share.... * systemd.show_status= should probably have a mode where only failed -- cgit v1.2.3-54-g00ecf From 4ffe24797cc881f1dc95f39badf6facd8061117e Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 14 Sep 2016 01:40:02 -0400 Subject: NEWS: add a bunch of stuff for the 232 release (#4132) This does not include the description of the mixed v1/v2 mode, but everything important apart from that should be covered. --- NEWS | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/NEWS b/NEWS index 7ff4a44835..178ccf9b04 100644 --- a/NEWS +++ b/NEWS @@ -2,11 +2,141 @@ systemd System and Service Manager CHANGES WITH 232 in spe + * The new RemoveIPC= option can be used to remove IPC objects owned by + the user or group of a service when that service exits. + + * Support for dynamically creating users for the lifetime of a service + has been added. If DynamicUser=yes is specified, user and group IDs + will be allocated from the range 61184..65519 for the lifetime of the + service. They can be resolved using the new nss-systemd.so NSS + module. The module must be enabled in /etc/nsswitch.conf. Services + started in this way have PrivateTmp= and RemoveIPC= enabled, so that + any resources allocated by the service will be cleaned up when the + service exits. + + The nss-systemd module also always resolves root and nobody, making + it possible to have no /etc/passwd or /etc/group files in minimal + container systems. + + * Services may be started with their own user namespace using the new + PrivateUsers= option. Only root, nobody, and the uid/gid under which + the service is running are mapped. All other users are mapped to + nobody. + + * Support for the cgroup namespace has been added to systemd-nspawn. If + supported by kernel, the container system started by systemd-nspawn + will have its own view of the cgroup hierarchy. This new behaviour + can be disabled using $SYSTEMD_NSPAWN_USE_CGNS environment variable. + + * The new MemorySwapMax= option can be used to limit the maximum swap + usage under the unified cgroup hierarchy. + + * Support for the CPU controller in the unified cgroup hierarchy has + been added, via the CPUWeight=, CPUStartupWeight=, CPUAccounting= + options. This controller requires out-of-tree patches for the kernel + and the support is provisional. + + * .automount units may now be transient. + + * systemd-mount is a new tool which wraps mount(8) to pull in + additional dependencies through transient .mount and .automount + units. For example, this automatically runs fsck on the block device + before mounting, and allows the automount logic to be used. + + * LazyUnmount=yes option for mount units has been added to expose the + umount --lazy option. Similarly, ForceUnmount=yes exposes the --force + option. + + * /efi will be used as the mount point of the EFI boot partition, if + the directory is present, and the mount point was not configured + through other means (e.g. fstab). If /efi directory does not exist, + /boot will be used as before. This makes it easier to automatically + mount the EFI partition on systems where /boot is used for something + else. + + * disk/by-id symlinks are now created for NVMe drives. + + * Two new user session targets have been added to support running + graphical sessions under the systemd --user instance: + graphical-session.target and graphical-session-pre.target. See + systemd.special(7) for a description of how those targets should be + used. + + * The vconsole initialization code has been significantly reworked to + use KD_FONT_OP_GET/SET ioctls insteads of KD_FONT_OP_COPY and better + support unicode keymaps. Font and keymap configuration will now be + copied to all allocated virtual consoles. + + * FreeBSD's bhyve virtiualization is now detected. + + * Information recored in the journal for core dumps now includes the + contents of /proc/mountinfo and the command line of the process at + the top of the process hierarchy (which is usually the init process + of the container). + + * systemd-journal-gatewayd learned the --directory option to serve + files from the specified location. + + * journalctl --root=… can be used to peruse the journal in the + /var/log/ directories inside of a container tree. This is similar to + the existing --machine= option, but does not require the container to + be active. + + * The hardware database has been extended to support + ID_INPUT_TRACKBALL, used in addition to ID_INPUT_MOUSE to identify + trackball devices. + + MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL hwdb property has been added to + specify the click rate for mice which include a horizontal wheel with + a click rate that is different than the one for the vertical wheel. + + * systemd-run gained a new --wait option that makes service execution + synchronous. + + * A new journal output mode "short-full" has been added which uses + timestamps with abbreviated English day names and adds a timezone + suffix. Those timestamps include more information and can be parsed + by journalctl. + + * /etc/resolv.conf will be bind-mounted into containers started by + systemd-nspawn, if possible, so any changes to resolv.conf contents + are automatically propagated to the container. + + * The number of instances for socket-activated services originating + from a single IP can be limited with MaxConnectionsPerSource=, + extending the existing setting of MaxConnections. + + * UDP Segmentation Offload, TCP Segmentation Offload, Generic + Segmentation Offload, Generic Receive Offload, Large Receive Offload + can be enabled and disabled using the new UDPSegmentationOffload=, + TCPSegmentationOffload=, GenericSegmentationOffload=, + GenericReceiveOffload=, LargeReceiveOffload= options in the + [Link] section of .link files. + + Spanning Tree Protocol enablement, Priority, Aging Time, and the + Default Port VLAN ID can be configured for bridge devices using the + new STP=, Priority=, AgeingTimeSec=, and DefaultPVID= settings in the + [Bridge] section of .netdev files. + + Address Resolution Protocol can be disabled on links managed by + systemd-networkd using the ARP=no setting in the [Link] section of + .network files. + + * $SERVICE_RESULT, $EXIT_CODE, $EXIT_STATUS are set for ExecStop= and + ExecStopPost= commands. + * Journald's SplitMode=login setting has been deprecated. It has been removed from documentation, and it's use is discouraged. In a future release it will be completely removed, and made equivalent to current default of SplitMode=uid. + * The --share-system systemd-nspawn option has been replaced with an + (undocumented) variable $SYSTEMD_NSPAWN_SHARE_SYSTEM, but the use of + this functionality is discouraged. In addition the variables + $SYSTEMD_NSPAWN_SHARE_NS_IPC, $SYSTEMD_NSPAWN_SHARE_NS_PID, + $SYSTEMD_NSPAWN_SHARE_NS_UTS may be used to control the unsharing of + individual namespaces. + CHANGES WITH 231: * In service units the various ExecXYZ= settings have been extended @@ -223,6 +353,9 @@ CHANGES WITH 231: local changes made to systemd in a pristine, defined environment. See HACKING for details. + * configure learned the --with-support-url= option to specify the + distribution's bugtracker. + Contributions from: Alban Crequy, Alessandro Puccetti, Alessio Igor Bogani, Alexander Kuleshov, Alexander Kurtz, Alex Gaynor, Andika Triwidada, Andreas Pokorny, Andreas Rammhold, Andrew Jeddeloh, Ansgar -- cgit v1.2.3-54-g00ecf From 34210af7c63640fca1fd4a09fc23b01a8cd70bf3 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 14 Sep 2016 01:57:43 -0400 Subject: kernel-install: Add KERNEL_INSTALL_NOOP (#4103) Will be used by rpm-ostree (and likely lorax) to suppress RPM->kernel->%posttrans->dracut runs, and basically everything else this script is doing. I'll also likely change the `kernel.spec` to respect this as well. --- src/kernel-install/kernel-install | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install index c66bcfc092..f37c023c6a 100644 --- a/src/kernel-install/kernel-install +++ b/src/kernel-install/kernel-install @@ -61,6 +61,13 @@ for i in "$@"; do fi done +# KERNEL_INSTALL_NOOP may be used by programs like lorax and rpm-ostree which +# want to install a kernel (indirectly via RPM), but control generation of the +# initramfs. In general, OSTree takes over kernel management too. +if test -n "${KERNEL_INSTALL_NOOP:-}"; then + exit 0 +fi + if [[ "${0##*/}" == 'installkernel' ]]; then COMMAND='add' else -- cgit v1.2.3-54-g00ecf From c07c80bc969fdb745593a86c8a34758722eeb29a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 14 Sep 2016 15:22:45 +0900 Subject: bash-completion: systemctl: use local variables --- shell-completion/bash/systemctl.in | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in index e62cfa57a9..dcf71a1f51 100644 --- a/shell-completion/bash/systemctl.in +++ b/shell-completion/bash/systemctl.in @@ -41,7 +41,7 @@ __contains_word () { __filter_units_by_property () { local mode=$1 property=$2 value=$3 ; shift 3 local units=("$@") - local props + local props i IFS=$'\n' read -rd '' -a props < \ <(__systemctl $mode show --property "$property" -- "${units[@]}") for ((i=0; $i < ${#units[*]}; i++)); do @@ -54,12 +54,11 @@ __filter_units_by_property () { __filter_units_by_properties () { local mode=$1 properties=$2 values=$3 ; shift 3 local units=("$@") - local props + local props i j conditions=() IFS=$'\n' read -rd '' -a props < \ <(__systemctl $mode show --property "$properties" -- "${units[@]}") IFS=$',' read -r -a properties < <(echo $properties) IFS=$',' read -r -a values < <(echo $values) - local conditions=() for ((i=0; i < ${#properties[*]}; i++)); do for ((j=0; j < ${#properties[*]}; j++)); do if [[ ${props[i]%%=*} == ${properties[j]} ]]; then @@ -67,16 +66,13 @@ __filter_units_by_properties () { fi done done - local flag for ((i=0; i < ${#units[*]}; i++)); do - flag=1 for ((j=0; j < ${#conditions[*]}; j++)); do if [[ "${props[ i * ${#conditions[*]} + j]}" != "${conditions[j]}" ]]; then - flag= break fi done - if [[ -n $flag ]]; then + if (( j == ${#conditions[*]} )); then echo " ${units[i]}" fi done -- cgit v1.2.3-54-g00ecf From 92c918b06d970cd4ce2e7e529e6093ffc46a9cfa Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Wed, 14 Sep 2016 21:45:16 +0530 Subject: networkd: add support to configure virtual CAN device (#4139) 1. add support for kind vcan 2. fixup indention netlink-types.c, networkd-netdev.c --- Makefile.am | 2 + man/systemd.netdev.xml | 6 ++- src/libsystemd/sd-netlink/netlink-types.c | 74 +++++++++++++++---------------- src/libsystemd/sd-netlink/netlink-types.h | 1 + src/network/networkd-link.c | 38 ++++++++++++++++ src/network/networkd-netdev-vcan.c | 25 +++++++++++ src/network/networkd-netdev-vcan.h | 34 ++++++++++++++ src/network/networkd-netdev.c | 4 +- src/network/networkd-netdev.h | 1 + src/network/networkd-network.c | 1 + src/network/networkd.h | 1 + 11 files changed, 147 insertions(+), 40 deletions(-) create mode 100644 src/network/networkd-netdev-vcan.c create mode 100644 src/network/networkd-netdev-vcan.h diff --git a/Makefile.am b/Makefile.am index 3a617560e0..946af196f3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5650,6 +5650,8 @@ libnetworkd_core_la_SOURCES = \ src/network/networkd-netdev-bond.c \ src/network/networkd-netdev-bridge.h \ src/network/networkd-netdev-bridge.c \ + src/network/networkd-netdev-vcan.h \ + src/network/networkd-netdev-vcan.c \ src/network/networkd-link-bus.c \ src/network/networkd-ipv4ll.c \ src/network/networkd-dhcp4.c \ diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 1f9f071b94..78f0e25a6f 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -163,7 +163,11 @@ A virtual extensible LAN (vxlan), for connecting Cloud computing deployments. vrf - A Virtual Routing and Forwarding (VRF) interface to create separate routing and forwarding domains. + A Virtual Routing and Forwarding (VRF) interface to create separate routing and forwarding domains. + + vcan + The virtual CAN driver (vcan). Similar to the network loopback devices, + vcan offers a virtual local CAN interface. diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c index 566a050432..1c10dd55a7 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -303,49 +304,48 @@ static const char* const nl_union_link_info_data_table[] = { [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = "vti6", [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl", [NL_UNION_LINK_INFO_DATA_VRF] = "vrf", + [NL_UNION_LINK_INFO_DATA_VCAN] = "vcan", }; DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData); static const NLTypeSystem rtnl_link_info_data_type_systems[] = { - [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types), - .types = rtnl_link_info_data_bond_types }, - [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types), - .types = rtnl_link_info_data_bridge_types }, - [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types), - .types = rtnl_link_info_data_vlan_types }, - [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types), - .types = rtnl_link_info_data_veth_types }, - [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), - .types = rtnl_link_info_data_macvlan_types }, - [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), - .types = rtnl_link_info_data_macvlan_types }, - [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types), - .types = rtnl_link_info_data_ipvlan_types }, - [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types), - .types = rtnl_link_info_data_vxlan_types }, - [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), - .types = rtnl_link_info_data_iptun_types }, - [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types), + .types = rtnl_link_info_data_bond_types }, + [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types), + .types = rtnl_link_info_data_bridge_types }, + [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types), + .types = rtnl_link_info_data_vlan_types }, + [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types), + .types = rtnl_link_info_data_veth_types }, + [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), + .types = rtnl_link_info_data_macvlan_types }, + [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), + .types = rtnl_link_info_data_macvlan_types }, + [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types), + .types = rtnl_link_info_data_ipvlan_types }, + [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types), + .types = rtnl_link_info_data_vxlan_types }, + [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), + .types = rtnl_link_info_data_iptun_types }, + [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), + .types = rtnl_link_info_data_ipgre_types }, [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), - .types = rtnl_link_info_data_iptun_types }, - [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), - .types = rtnl_link_info_data_ipvti_types }, - [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), - .types = rtnl_link_info_data_ipvti_types }, - [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types), - .types = rtnl_link_info_data_ip6tnl_types }, - - [NL_UNION_LINK_INFO_DATA_VRF] = { .count = ELEMENTSOF(rtnl_link_info_data_vrf_types), - .types = rtnl_link_info_data_vrf_types }, - + .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), + .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), + .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), + .types = rtnl_link_info_data_iptun_types }, + [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), + .types = rtnl_link_info_data_ipvti_types }, + [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), + .types = rtnl_link_info_data_ipvti_types }, + [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types), + .types = rtnl_link_info_data_ip6tnl_types }, + [NL_UNION_LINK_INFO_DATA_VRF] = { .count = ELEMENTSOF(rtnl_link_info_data_vrf_types), + .types = rtnl_link_info_data_vrf_types }, }; static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = { diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h index 7c0e598b26..42e96173de 100644 --- a/src/libsystemd/sd-netlink/netlink-types.h +++ b/src/libsystemd/sd-netlink/netlink-types.h @@ -87,6 +87,7 @@ typedef enum NLUnionLinkInfoData { NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL, NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL, NL_UNION_LINK_INFO_DATA_VRF, + NL_UNION_LINK_INFO_DATA_VCAN, _NL_UNION_LINK_INFO_DATA_MAX, _NL_UNION_LINK_INFO_DATA_INVALID = -1 } NLUnionLinkInfoData; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index aab40a0eb1..1687d9bf31 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1787,6 +1787,31 @@ static int link_down(Link *link) { return 0; } +static int link_up_can(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + + log_link_debug(link, "Bringing CAN link up"); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP); + if (r < 0) + return log_link_error_errno(link, r, "Could not set link flags: %m"); + + r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + static int link_handle_bound_to_list(Link *link) { Link *l; Iterator i; @@ -2431,6 +2456,19 @@ static int link_configure(Link *link) { assert(link->network); assert(link->state == LINK_STATE_PENDING); + if (streq_ptr(link->kind, "vcan")) { + + if (!(link->flags & IFF_UP)) { + r = link_up_can(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + } + + return 0; + } + /* Drop foreign config, but ignore loopback or critical devices. * We do not want to remove loopback address or addresses used for root NFS. */ if (!(link->flags & IFF_LOOPBACK) && !(link->network->dhcp_critical)) { diff --git a/src/network/networkd-netdev-vcan.c b/src/network/networkd-netdev-vcan.c new file mode 100644 index 0000000000..bfce6e1962 --- /dev/null +++ b/src/network/networkd-netdev-vcan.c @@ -0,0 +1,25 @@ +/*** + This file is part of systemd. + + Copyright 2016 Susant Sahani + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "networkd-netdev-vcan.h" + +const NetDevVTable vcan_vtable = { + .object_size = sizeof(VCan), + .create_type = NETDEV_CREATE_INDEPENDENT, +}; diff --git a/src/network/networkd-netdev-vcan.h b/src/network/networkd-netdev-vcan.h new file mode 100644 index 0000000000..6ba47fd70e --- /dev/null +++ b/src/network/networkd-netdev-vcan.h @@ -0,0 +1,34 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2016 Susant Sahani + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +typedef struct VCan VCan; + +#include + +#include "networkd-netdev.h" + +struct VCan { + NetDev meta; +}; + +DEFINE_NETDEV_CAST(VCAN, VCan); + +extern const NetDevVTable vcan_vtable; diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index e7edc366af..583389c8dd 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -56,7 +56,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { [NETDEV_KIND_TAP] = &tap_vtable, [NETDEV_KIND_IP6TNL] = &ip6tnl_vtable, [NETDEV_KIND_VRF] = &vrf_vtable, - + [NETDEV_KIND_VCAN] = &vcan_vtable, }; static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { @@ -81,7 +81,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { [NETDEV_KIND_TAP] = "tap", [NETDEV_KIND_IP6TNL] = "ip6tnl", [NETDEV_KIND_VRF] = "vrf", - + [NETDEV_KIND_VCAN] = "vcan", }; DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind); diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h index 09863e72b4..31b55e2791 100644 --- a/src/network/networkd-netdev.h +++ b/src/network/networkd-netdev.h @@ -56,6 +56,7 @@ typedef enum NetDevKind { NETDEV_KIND_TUN, NETDEV_KIND_TAP, NETDEV_KIND_VRF, + NETDEV_KIND_VCAN, _NETDEV_KIND_MAX, _NETDEV_KIND_INVALID = -1 } NetDevKind; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 49faba5b12..9865c8a5c0 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -479,6 +479,7 @@ int config_parse_netdev(const char *unit, case NETDEV_KIND_MACVTAP: case NETDEV_KIND_IPVLAN: case NETDEV_KIND_VXLAN: + case NETDEV_KIND_VCAN: r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Can not add VLAN '%s' to network: %m", rvalue); diff --git a/src/network/networkd.h b/src/network/networkd.h index c4bd712147..cb1b73145e 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -43,6 +43,7 @@ #include "networkd-netdev-vlan.h" #include "networkd-netdev-vrf.h" #include "networkd-netdev-vxlan.h" +#include "networkd-netdev-vcan.h" #include "networkd-network.h" #include "networkd-util.h" -- cgit v1.2.3-54-g00ecf From bf6585ce64f7eb826704c3d9fdb8ad2a820af794 Mon Sep 17 00:00:00 2001 From: Davide Cavalca Date: Wed, 14 Sep 2016 10:15:21 -0700 Subject: gitignore: ignore image.raw from mkosi (#4141) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 565a3a3839..c925f19f41 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ /exported /exported-* /hostnamectl +/image.raw /install-tree /journalctl /libtool -- cgit v1.2.3-54-g00ecf From c0f9116d6cd795edd9d4df8d27a87a7232d3e675 Mon Sep 17 00:00:00 2001 From: Davide Cavalca Date: Wed, 14 Sep 2016 13:38:53 -0700 Subject: shell-completion: add --wait to systemd-run completions (#4140) --- shell-completion/bash/systemd-run | 3 ++- shell-completion/zsh/_systemd-run | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/shell-completion/bash/systemd-run b/shell-completion/bash/systemd-run index 022331e6a9..4116ba7eca 100644 --- a/shell-completion/bash/systemd-run +++ b/shell-completion/bash/systemd-run @@ -36,7 +36,8 @@ _systemd_run() { -r --remain-after-exit --send-sighup -H --host -M --machine --service-type --on-active --on-boot --on-startup --on-unit-active --on-unit-inactive --on-calendar --timer-property -t --pty -q --quiet --no-block - --uid --gid --nice --setenv -p --property --no-ask-password' + --uid --gid --nice --setenv -p --property --no-ask-password + --wait' local mode=--system local i diff --git a/shell-completion/zsh/_systemd-run b/shell-completion/zsh/_systemd-run index 6362b97766..da9f73a6d0 100644 --- a/shell-completion/zsh/_systemd-run +++ b/shell-completion/zsh/_systemd-run @@ -57,4 +57,5 @@ _arguments \ '--on-unit-inactive=[Run after SEC seconds from the last deactivation]:SEC' \ '--on-calendar=[Realtime timer]:SPEC' \ '--timer-property=[Set timer unit property]:NAME=VALUE' \ + '--wait=[Wait until service stopped again]' \ '*::command:_command' -- cgit v1.2.3-54-g00ecf From 3a730176b36bc1191c54b149a8147bbf6ec8e482 Mon Sep 17 00:00:00 2001 From: Ivan Shapovalov Date: Thu, 15 Sep 2016 05:19:31 +0300 Subject: time-util: export timespec_load_nsec() --- src/basic/time-util.c | 4 +--- src/basic/time-util.h | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 0ef1f6393e..fedff1362c 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -40,8 +40,6 @@ #include "strv.h" #include "time-util.h" -static nsec_t timespec_load_nsec(const struct timespec *ts); - static clockid_t map_clock_id(clockid_t c) { /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will @@ -198,7 +196,7 @@ usec_t timespec_load(const struct timespec *ts) { (usec_t) ts->tv_nsec / NSEC_PER_USEC; } -static nsec_t timespec_load_nsec(const struct timespec *ts) { +nsec_t timespec_load_nsec(const struct timespec *ts) { assert(ts); if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1) diff --git a/src/basic/time-util.h b/src/basic/time-util.h index 99be5ce6ee..558b0b5b7f 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -111,6 +111,7 @@ static inline bool triple_timestamp_is_set(triple_timestamp *ts) { usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock); usec_t timespec_load(const struct timespec *ts) _pure_; +nsec_t timespec_load_nsec(const struct timespec *ts) _pure_; struct timespec *timespec_store(struct timespec *ts, usec_t u); usec_t timeval_load(const struct timeval *tv) _pure_; -- cgit v1.2.3-54-g00ecf From fb8b0869a7bc30e23be175cf978df23192d59118 Mon Sep 17 00:00:00 2001 From: Ivan Shapovalov Date: Tue, 13 Sep 2016 03:04:35 +0300 Subject: update-done, condition: write the timestamp to the file as well and use it to prevent false-positives This fixes https://bugs.freedesktop.org/show_bug.cgi?id=90192 and #4130 for real. Also, remove timestamp check in update-done.c altogether since the whole operation is idempotent. --- src/shared/condition.c | 42 ++++++++++++++++++++++-- src/update-done/update-done.c | 76 +++++++++++++++++++------------------------ 2 files changed, 73 insertions(+), 45 deletions(-) diff --git a/src/shared/condition.c b/src/shared/condition.c index 6bb42c0692..f13fa6a9fd 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -37,6 +37,7 @@ #include "condition.h" #include "extract-word.h" #include "fd-util.h" +#include "fileio.h" #include "glob-util.h" #include "hostname-util.h" #include "ima-util.h" @@ -309,8 +310,45 @@ static int condition_test_needs_update(Condition *c) { if (lstat("/usr/", &usr) < 0) return true; - return usr.st_mtim.tv_sec > other.st_mtim.tv_sec || - (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec); + /* + * First, compare seconds as they are always accurate... + */ + if (usr.st_mtim.tv_sec != other.st_mtim.tv_sec) + return usr.st_mtim.tv_sec > other.st_mtim.tv_sec; + + /* + * ...then compare nanoseconds. + * + * A false positive is only possible when /usr's nanoseconds > 0 + * (otherwise /usr cannot be strictly newer than the target file) + * AND the target file's nanoseconds == 0 + * (otherwise the filesystem supports nsec timestamps, see stat(2)). + */ + if (usr.st_mtim.tv_nsec > 0 && other.st_mtim.tv_nsec == 0) { + _cleanup_free_ char *timestamp_str = NULL; + uint64_t timestamp; + int r; + + r = parse_env_file(p, NULL, "TimestampNSec", ×tamp_str, NULL); + if (r < 0) { + log_error_errno(-r, "Failed to parse timestamp file '%s', using mtime: %m", p); + return true; + } else if (r == 0) { + log_debug("No data in timestamp file '%s', using mtime", p); + return true; + } + + r = safe_atou64(timestamp_str, ×tamp); + if (r < 0) { + log_error_errno(-r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", + timestamp_str, p); + return true; + } + + other.st_mtim.tv_nsec = timestamp % NSEC_PER_SEC; + } + + return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec; } static int condition_test_first_boot(Condition *c) { diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c index da306a4444..5cc5abfddf 100644 --- a/src/update-done/update-done.c +++ b/src/update-done/update-done.c @@ -23,67 +23,57 @@ #include "util.h" #define MESSAGE \ - "This file was created by systemd-update-done. Its only \n" \ - "purpose is to hold a timestamp of the time this directory\n" \ - "was updated. See systemd-update-done.service(8).\n" + "# This file was created by systemd-update-done. Its only \n" \ + "# purpose is to hold a timestamp of the time this directory\n" \ + "# was updated. See systemd-update-done.service(8).\n" static int apply_timestamp(const char *path, struct timespec *ts) { struct timespec twice[2] = { *ts, *ts }; - struct stat st; + int fd = -1; + _cleanup_fclose_ FILE *f = NULL; + int r; assert(path); assert(ts); - if (stat(path, &st) >= 0) { - /* Is the timestamp file already newer than the OS? If - * so, there's nothing to do. We ignore the nanosecond - * component of the timestamp, since some file systems - * do not support any better accuracy than 1s and we - * have no way to identify the accuracy - * available. Most notably ext4 on small disks (where - * 128 byte inodes are used) does not support better - * accuracy than 1s. */ - if (st.st_mtim.tv_sec > ts->tv_sec) - return 0; - - /* It is older? Then let's update it */ - if (utimensat(AT_FDCWD, path, twice, AT_SYMLINK_NOFOLLOW) < 0) { - - if (errno == EROFS) - return log_debug("Can't update timestamp file %s, file system is read-only.", path); + /* + * We store the timestamp both as mtime of the file and in the file itself, + * to support filesystems which cannot store nanosecond-precision timestamps. + * Hence, don't bother updating the file, let's just rewrite it. + */ - return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); - } + r = mac_selinux_create_file_prepare(path, S_IFREG); + if (r < 0) + return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); - } else if (errno == ENOENT) { - _cleanup_close_ int fd = -1; - int r; + fd = open(path, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); + mac_selinux_create_file_clear(); - /* The timestamp file doesn't exist yet? Then let's create it. */ + if (fd < 0) { + if (errno == EROFS) + return log_debug("Can't create timestamp file %s, file system is read-only.", path); - r = mac_selinux_create_file_prepare(path, S_IFREG); - if (r < 0) - return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); - - fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); - mac_selinux_create_file_clear(); + return log_error_errno(errno, "Failed to create/open timestamp file %s: %m", path); + } - if (fd < 0) { - if (errno == EROFS) - return log_debug("Can't create timestamp file %s, file system is read-only.", path); + f = fdopen(fd, "w"); + if (!f) { + safe_close(fd); + return log_error_errno(errno, "Failed to fdopen() timestamp file %s: %m", path); + } - return log_error_errno(errno, "Failed to create timestamp file %s: %m", path); - } + (void) fprintf(f, + "%s" + "TimestampNSec=" NSEC_FMT "\n", + MESSAGE, timespec_load_nsec(ts)); - (void) loop_write(fd, MESSAGE, strlen(MESSAGE), false); + fflush(f); - if (futimens(fd, twice) < 0) - return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); - } else - log_error_errno(errno, "Failed to stat() timestamp file %s: %m", path); + if (futimens(fd, twice) < 0) + return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); return 0; } -- cgit v1.2.3-54-g00ecf From 1bc7460bf2044c71278d3bc67ee4f41d574a6298 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Thu, 15 Sep 2016 10:18:22 +0530 Subject: TODO: update networkd TODO --- TODO | 2 -- 1 file changed, 2 deletions(-) diff --git a/TODO b/TODO index a833a3158d..e7391f0bfe 100644 --- a/TODO +++ b/TODO @@ -801,7 +801,6 @@ Features: - add reduced [Link] support to .network files - add Scope= parsing option for [Network] - properly handle routerless dhcp leases - - add more attribute support for SIT tunnel - work with non-Ethernet devices - add support for more bond options - dhcp: do we allow configuring dhcp routes on interfaces that are not the one we got the dhcp info from? @@ -818,7 +817,6 @@ Features: support Name=foo*|bar*|baz ? - duplicate address check for static IPs (like ARPCHECK in network-scripts) - allow DUID/IAID to be customized, see issue #394. - - support configuration option for TSO (tcp segmentation offload) - whenever uplink info changes, make DHCP server send out FORCERENEW * networkd-wait-online: -- cgit v1.2.3-54-g00ecf From 9b53e129874dc784376ae09774898fd08adda507 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Thu, 15 Sep 2016 10:18:59 +0530 Subject: networkd: netdev fixup copy paste error --- src/network/networkd-netdev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index 583389c8dd..897de9bde5 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -34,7 +34,6 @@ #include "string-util.h" const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { - [NETDEV_KIND_BRIDGE] = &bridge_vtable, [NETDEV_KIND_BOND] = &bond_vtable, [NETDEV_KIND_VLAN] = &vlan_vtable, @@ -516,7 +515,7 @@ static int netdev_create(NetDev *netdev, Link *link, r = sd_netlink_message_close_container(m); if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); + return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); r = sd_netlink_message_close_container(m); if (r < 0) -- cgit v1.2.3-54-g00ecf From a4820c463acd3777268bf6eb25284f7dab898187 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Thu, 15 Sep 2016 10:19:26 +0530 Subject: networkd: network fix log message --- src/network/networkd-network.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 9865c8a5c0..91e51e9124 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -482,7 +482,7 @@ int config_parse_netdev(const char *unit, case NETDEV_KIND_VCAN: r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Can not add VLAN '%s' to network: %m", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r, "Can not add NetDev '%s' to network: %m", rvalue); return 0; } -- cgit v1.2.3-54-g00ecf From bbe7cdeb8fa6e880a1296e170648e468036e843b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 15 Sep 2016 16:16:05 +1000 Subject: hwdb: add Lenovo *40 series resolution fixes (#4149) --- hwdb/60-evdev.hwdb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb index 8651946db7..0b692a1b5d 100644 --- a/hwdb/60-evdev.hwdb +++ b/hwdb/60-evdev.hwdb @@ -209,6 +209,14 @@ evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*P50* EVDEV_ABS_35=::44 EVDEV_ABS_36=::67 +# Lenovo *40 series +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPad??40:* +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPad??40?:* + EVDEV_ABS_00=::41 + EVDEV_ABS_01=::37 + EVDEV_ABS_35=::41 + EVDEV_ABS_36=::37 + # Lenovo T460 evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T460* EVDEV_ABS_00=1266:5677:44 -- cgit v1.2.3-54-g00ecf From d903a89246f40b6527e2358498657a9a3c625237 Mon Sep 17 00:00:00 2001 From: kristbaum Date: Thu, 15 Sep 2016 09:11:33 +0200 Subject: Update systemctl.xml (#4151) --- man/systemctl.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index 7e0ac9613a..781de0912a 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1073,8 +1073,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service Reenable one or more units, as specified on the command line. This is a combination of disable and enable and is useful to reset the symlinks a unit file is - enabled with to the defaults configured in its [Install] section. This commands expects - a unit uname only, it does not accept paths to unit files. + enabled with to the defaults configured in its [Install] section. This command expects + a unit name only, it does not accept paths to unit files. -- cgit v1.2.3-54-g00ecf From 2179fd109d08c1d0dfcbc83bade2c9cda3d9f13c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 15 Sep 2016 08:21:42 -0400 Subject: test-execute: fix %n typo (#4153) --- src/test/test-execute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 1db7f78041..25489cefbc 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -324,7 +324,7 @@ static int run_tests(UnitFileScope scope, test_function_t *tests) { r = manager_new(scope, true, &m); if (MANAGER_SKIP_TEST(r)) { - log_notice_errno(r, "Skipping test: manager_new: %n"); + log_notice_errno(r, "Skipping test: manager_new: %m"); return EXIT_TEST_SKIP; } assert_se(r >= 0); -- cgit v1.2.3-54-g00ecf From 390e02073514cc6972aa8bc5f10d974c226ecbcb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 15 Sep 2016 22:09:35 +0200 Subject: hwdb: Update database of Bluetooth company identifiers --- hwdb/20-bluetooth-vendor-product.hwdb | 202 +++++++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 2 deletions(-) diff --git a/hwdb/20-bluetooth-vendor-product.hwdb b/hwdb/20-bluetooth-vendor-product.hwdb index 5089ab4e04..ab6e321ff6 100644 --- a/hwdb/20-bluetooth-vendor-product.hwdb +++ b/hwdb/20-bluetooth-vendor-product.hwdb @@ -424,7 +424,7 @@ bluetooth:v008A* ID_VENDOR_FROM_DATABASE=Jawbone bluetooth:v008B* - ID_VENDOR_FROM_DATABASE=Topcorn Positioning Systems, LLC + ID_VENDOR_FROM_DATABASE=Topcon Positioning Systems, LLC bluetooth:v008C* ID_VENDOR_FROM_DATABASE=Gimbal Inc. (formerly Qualcomm Labs, Inc. and Qualcomm Retail Solutions, Inc.) @@ -1231,7 +1231,7 @@ bluetooth:v0197* ID_VENDOR_FROM_DATABASE=WiSilica Inc bluetooth:v0198* - ID_VENDOR_FROM_DATABASE=Vengit Limited + ID_VENDOR_FROM_DATABASE=VENGIT Korlátolt Felelősségű Társaság bluetooth:v0199* ID_VENDOR_FROM_DATABASE=SALTO SYSTEMS S.L. @@ -2828,3 +2828,201 @@ bluetooth:v03AB* bluetooth:v03AC* ID_VENDOR_FROM_DATABASE=Smablo LTD + +bluetooth:v03AD* + ID_VENDOR_FROM_DATABASE=XiQ + +bluetooth:v03AE* + ID_VENDOR_FROM_DATABASE=Allswell Inc. + +bluetooth:v03AF* + ID_VENDOR_FROM_DATABASE=Comm-N-Sense Corp DBA Verigo + +bluetooth:v03B0* + ID_VENDOR_FROM_DATABASE=VIBRADORM GmbH + +bluetooth:v03B1* + ID_VENDOR_FROM_DATABASE=Otodata Wireless Network Inc. + +bluetooth:v03B2* + ID_VENDOR_FROM_DATABASE=Propagation Systems Limited + +bluetooth:v03B3* + ID_VENDOR_FROM_DATABASE=Midwest Instruments & Controls + +bluetooth:v03B4* + ID_VENDOR_FROM_DATABASE=Alpha Nodus, inc. + +bluetooth:v03B5* + ID_VENDOR_FROM_DATABASE=petPOMM, Inc + +bluetooth:v03B6* + ID_VENDOR_FROM_DATABASE=Mattel + +bluetooth:v03B7* + ID_VENDOR_FROM_DATABASE=Airbly Inc. + +bluetooth:v03B8* + ID_VENDOR_FROM_DATABASE=A-Safe Limited + +bluetooth:v03B9* + ID_VENDOR_FROM_DATABASE=FREDERIQUE CONSTANT SA + +bluetooth:v03BA* + ID_VENDOR_FROM_DATABASE=Maxscend Microelectronics Company Limited + +bluetooth:v03BB* + ID_VENDOR_FROM_DATABASE=Abbott Diabetes Care + +bluetooth:v03BC* + ID_VENDOR_FROM_DATABASE=ASB Bank Ltd + +bluetooth:v03BD* + ID_VENDOR_FROM_DATABASE=amadas + +bluetooth:v03BE* + ID_VENDOR_FROM_DATABASE=Applied Science, Inc. + +bluetooth:v03BF* + ID_VENDOR_FROM_DATABASE=iLumi Solutions Inc. + +bluetooth:v03C0* + ID_VENDOR_FROM_DATABASE=Arch Systems Inc. + +bluetooth:v03C1* + ID_VENDOR_FROM_DATABASE=Ember Technologies, Inc. + +bluetooth:v03C2* + ID_VENDOR_FROM_DATABASE=Snapchat Inc + +bluetooth:v03C3* + ID_VENDOR_FROM_DATABASE=Casambi Technologies Oy + +bluetooth:v03C4* + ID_VENDOR_FROM_DATABASE=Pico Technology Inc. + +bluetooth:v03C5* + ID_VENDOR_FROM_DATABASE=St. Jude Medical, Inc. + +bluetooth:v03C6* + ID_VENDOR_FROM_DATABASE=Intricon + +bluetooth:v03C7* + ID_VENDOR_FROM_DATABASE=Structural Health Systems, Inc. + +bluetooth:v03C8* + ID_VENDOR_FROM_DATABASE=Avvel International + +bluetooth:v03C9* + ID_VENDOR_FROM_DATABASE=Gallagher Group + +bluetooth:v03CA* + ID_VENDOR_FROM_DATABASE=In2things Automation Pvt. Ltd. + +bluetooth:v03CB* + ID_VENDOR_FROM_DATABASE=SYSDEV Srl + +bluetooth:v03CC* + ID_VENDOR_FROM_DATABASE=Vonkil Technologies Ltd + +bluetooth:v03CD* + ID_VENDOR_FROM_DATABASE=Wynd Technologies, Inc. + +bluetooth:v03CE* + ID_VENDOR_FROM_DATABASE=CONTRINEX S.A. + +bluetooth:v03CF* + ID_VENDOR_FROM_DATABASE=MIRA, Inc. + +bluetooth:v03D0* + ID_VENDOR_FROM_DATABASE=Watteam Ltd + +bluetooth:v03D1* + ID_VENDOR_FROM_DATABASE=Density Inc. + +bluetooth:v03D2* + ID_VENDOR_FROM_DATABASE=IOT Pot India Private Limited + +bluetooth:v03D3* + ID_VENDOR_FROM_DATABASE=Sigma Connectivity AB + +bluetooth:v03D4* + ID_VENDOR_FROM_DATABASE=PEG PEREGO SPA + +bluetooth:v03D5* + ID_VENDOR_FROM_DATABASE=Wyzelink Systems Inc. + +bluetooth:v03D6* + ID_VENDOR_FROM_DATABASE=Yota Devices LTD + +bluetooth:v03D7* + ID_VENDOR_FROM_DATABASE=FINSECUR + +bluetooth:v03D8* + ID_VENDOR_FROM_DATABASE=Zen-Me Labs Ltd + +bluetooth:v03D9* + ID_VENDOR_FROM_DATABASE=3IWare Co., Ltd. + +bluetooth:v03DA* + ID_VENDOR_FROM_DATABASE=EnOcean GmbH + +bluetooth:v03DB* + ID_VENDOR_FROM_DATABASE=Instabeat, Inc + +bluetooth:v03DC* + ID_VENDOR_FROM_DATABASE=Nima Labs + +bluetooth:v03DD* + ID_VENDOR_FROM_DATABASE=Andreas Stihl AG & Co. KG + +bluetooth:v03DE* + ID_VENDOR_FROM_DATABASE=Nathan Rhoades LLC + +bluetooth:v03DF* + ID_VENDOR_FROM_DATABASE=Grob Technologies, LLC + +bluetooth:v03E0* + ID_VENDOR_FROM_DATABASE=Actions (Zhuhai) Technology Co., Limited + +bluetooth:v03E1* + ID_VENDOR_FROM_DATABASE=SPD Development Company Ltd + +bluetooth:v03E2* + ID_VENDOR_FROM_DATABASE=Sensoan Oy + +bluetooth:v03E3* + ID_VENDOR_FROM_DATABASE=Qualcomm Life Inc + +bluetooth:v03E4* + ID_VENDOR_FROM_DATABASE=Chip-ing AG + +bluetooth:v03E5* + ID_VENDOR_FROM_DATABASE=ffly4u + +bluetooth:v03E6* + ID_VENDOR_FROM_DATABASE=IoT Instruments Oy + +bluetooth:v03E7* + ID_VENDOR_FROM_DATABASE=TRUE Fitness Technology + +bluetooth:v03E8* + ID_VENDOR_FROM_DATABASE=Reiner Kartengeraete GmbH & Co. KG. + +bluetooth:v03E9* + ID_VENDOR_FROM_DATABASE=SHENZHEN LEMONJOY TECHNOLOGY CO., LTD. + +bluetooth:v03EA* + ID_VENDOR_FROM_DATABASE=Hello Inc. + +bluetooth:v03EB* + ID_VENDOR_FROM_DATABASE=Evollve Inc. + +bluetooth:v03EC* + ID_VENDOR_FROM_DATABASE=Jigowatts Inc. + +bluetooth:v03ED* + ID_VENDOR_FROM_DATABASE=BASIC MICRO.COM,INC. + +bluetooth:v03EE* + ID_VENDOR_FROM_DATABASE=CUBE TECHNOLOGIES -- cgit v1.2.3-54-g00ecf From 7dabbb55a8744a43ec869839ef371b184c8d2ffe Mon Sep 17 00:00:00 2001 From: Tomáš Janoušek Date: Fri, 16 Sep 2016 01:26:31 +0200 Subject: logind: fix /run/user/$UID creation in apparmor-confined containers (#4154) When a docker container is confined with AppArmor [1] and happens to run on top of a kernel that supports mount mediation [2], e.g. any Ubuntu kernel, mount(2) returns EACCES instead of EPERM. This then leads to: systemd-logind[33]: Failed to mount per-user tmpfs directory /run/user/1000: Permission denied login[42]: pam_systemd(login:session): Failed to create session: Access denied and user sessions don't start. This also applies to selinux that too returns EACCES on mount denial. [1] https://github.com/docker/docker/blob/master/docs/security/apparmor.md#understand-the-policies [2] http://bazaar.launchpad.net/~apparmor-dev/apparmor/master/view/head:/kernel-patches/4.7/0025-UBUNTU-SAUCE-apparmor-Add-the-ability-to-mediate-mou.patch --- src/login/logind-user.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/login/logind-user.c b/src/login/logind-user.c index e0e73b034d..2dc5fa7665 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -354,14 +354,12 @@ static int user_mkdir_runtime_path(User *u) { r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t); if (r < 0) { - if (errno != EPERM) { + if (errno != EPERM && errno != EACCES) { r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", u->runtime_path); goto fail; } - /* Lacking permissions, maybe - * CAP_SYS_ADMIN-less container? In this case, - * just use a normal directory. */ + log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s, assuming containerized execution, ignoring: %m", u->runtime_path); r = chmod_and_chown(u->runtime_path, 0700, u->uid, u->gid); if (r < 0) { -- cgit v1.2.3-54-g00ecf From 734530b7b5c9db8f19d6b83262dcd7a2447bdbb8 Mon Sep 17 00:00:00 2001 From: Stefan Date: Fri, 16 Sep 2016 04:55:22 +0200 Subject: man: update url to openpgpkey rfc (#4156) --- man/systemd-resolve.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemd-resolve.xml b/man/systemd-resolve.xml index ca26bb4d49..24f499c282 100644 --- a/man/systemd-resolve.xml +++ b/man/systemd-resolve.xml @@ -135,7 +135,7 @@ TXT). The switch may be used to query PGP keys stored as - OPENPGPKEY resource records. + OPENPGPKEY resource records. When this option is specified one or more e-mail address must be specified. The switch maybe be used to query TLS public -- cgit v1.2.3-54-g00ecf From 96ee6ce3c9bee14e4543a482ee9815e775340bf6 Mon Sep 17 00:00:00 2001 From: Stefan Schweter Date: Fri, 16 Sep 2016 14:22:12 +0200 Subject: man: Update example for downloading a Fedora image (#4166) --- man/systemd-nspawn.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index 97b348b565..bf3860604c 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -1007,8 +1007,8 @@ Download a Fedora image and start a shell in it - # machinectl pull-raw --verify=no http://ftp.halifax.rwth-aachen.de/fedora/linux/releases/21/Cloud/Images/x86_64/Fedora-Cloud-Base-20141203-21.x86_64.raw.xz -# systemd-nspawn -M Fedora-Cloud-Base-20141203-21 + # machinectl pull-raw --verify=no http://ftp.halifax.rwth-aachen.de/fedora/linux/releases/24/CloudImages/x86_64/images/Fedora-Cloud-Base-24-1.2.x86_64.raw.xz +# systemd-nspawn -M Fedora-Cloud-Base-24-1.2.x86_64.raw This downloads an image using machinectl1 -- cgit v1.2.3-54-g00ecf From 9ea78383e8279ef41d96928d812ad8d4570d5147 Mon Sep 17 00:00:00 2001 From: hi117 Date: Fri, 16 Sep 2016 10:14:55 -0400 Subject: Updated formatting for printing the key for FSS (#4165) The key used to be jammed next to the local file path. Based on the format string on line 1675, I determined that the order of arguments was written incorrectly, and updated the function based on that assumption. Before: ``` Please write down the following secret verification key. It should be stored at a safe location and should not be saved locally on disk. /var/log/journal/9b47c1a5b339412887a197b7654673a7/fss8f66d6-f0a998-f782d0-1fe522/18fdb8-35a4e900 The sealing key is automatically changed every 15min. ``` After: ``` Please write down the following secret verification key. It should be stored at a safe location and should not be saved locally on disk. d53ed4-cc43d6-284e10-8f0324/18fdb8-35a4e900 The sealing key is automatically changed every 15min. ``` --- src/journal/journalctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 31074eb5f8..4350925fb0 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -1684,9 +1684,9 @@ static int setup_keys(void) { "at a safe location and should not be saved locally on disk.\n" "\n\t%s", ansi_highlight(), ansi_normal(), + p, ansi_highlight(), ansi_normal(), - ansi_highlight_red(), - p); + ansi_highlight_red()); fflush(stderr); } for (i = 0; i < seed_size; i++) { -- cgit v1.2.3-54-g00ecf From 38d78d1ee9f967aecda14a1c80cd664a66b976c7 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 14 Sep 2016 06:52:40 -0400 Subject: networkd-test: add a helper function to always clean up temporary config files --- test/networkd-test.py | 54 +++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/test/networkd-test.py b/test/networkd-test.py index bfa1bf3580..57f4c04295 100755 --- a/test/networkd-test.py +++ b/test/networkd-test.py @@ -54,7 +54,6 @@ class ClientTestBase: self.workdir_obj = tempfile.TemporaryDirectory() self.workdir = self.workdir_obj.name self.config = '/run/systemd/network/test_eth42.network' - os.makedirs(os.path.dirname(self.config), exist_ok=True) # avoid "Failed to open /dev/tty" errors in containers os.environ['SYSTEMD_LOG_TARGET'] = 'journal' @@ -77,10 +76,14 @@ class ClientTestBase: def tearDown(self): self.shutdown_iface() - if os.path.exists(self.config): - os.unlink(self.config) subprocess.call(['systemctl', 'stop', 'systemd-networkd']) + def writeConfig(self, fname, contents): + os.makedirs(os.path.dirname(fname), exist_ok=True) + with open(fname, 'w') as f: + f.write(contents) + self.addCleanup(os.remove, fname) + def show_journal(self, unit): '''Show journal of given unit since start of the test''' @@ -107,8 +110,8 @@ class ClientTestBase: def do_test(self, coldplug=True, ipv6=False, extra_opts='', online_timeout=10, dhcp_mode='yes'): subprocess.check_call(['systemctl', 'start', 'systemd-resolved']) - with open(self.config, 'w') as f: - f.write('''[Match] + self.writeConfig(self.config, '''\ +[Match] Name=%s [Network] DHCP=%s @@ -225,20 +228,18 @@ DHCP=%s self.do_test(coldplug=False, ipv6=True) def test_route_only_dns(self): - with open('/run/systemd/network/myvpn.netdev', 'w') as f: - f.write('''[NetDev] + self.writeConfig('/run/systemd/network/myvpn.netdev', '''\ +[NetDev] Name=dummy0 Kind=dummy MACAddress=12:34:56:78:9a:bc''') - with open('/run/systemd/network/myvpn.network', 'w') as f: - f.write('''[Match] + self.writeConfig('/run/systemd/network/myvpn.network', '''\ +[Match] Name=dummy0 [Network] Address=192.168.42.100 DNS=192.168.42.1 Domains= ~company''') - self.addCleanup(os.remove, '/run/systemd/network/myvpn.netdev') - self.addCleanup(os.remove, '/run/systemd/network/myvpn.network') self.do_test(coldplug=True, ipv6=False, extra_opts='IPv6AcceptRouterAdvertisements=False') @@ -320,7 +321,8 @@ class NetworkdClientTest(ClientTestBase, unittest.TestCase): (fd, script) = tempfile.mkstemp(prefix='networkd-router.sh') self.addCleanup(os.remove, script) with os.fdopen(fd, 'w+') as f: - f.write('''#!/bin/sh -eu + f.write('''\ +#!/bin/sh -eu mkdir -p /run/systemd/network mkdir -p /run/systemd/netif mount -t tmpfs none /run/systemd/network @@ -398,20 +400,18 @@ exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ { s/^.*=// # we don't use this interface for this test self.if_router = None - with open('/run/systemd/network/test.netdev', 'w') as f: - f.write('''[NetDev] + self.writeConfig('/run/systemd/network/test.netdev', '''\ +[NetDev] Name=dummy0 Kind=dummy MACAddress=12:34:56:78:9a:bc''') - with open('/run/systemd/network/test.network', 'w') as f: - f.write('''[Match] + self.writeConfig('/run/systemd/network/test.network', '''\ +[Match] Name=dummy0 [Network] Address=192.168.42.100 DNS=192.168.42.1 Domains= one two three four five six seven eight nine ten''') - self.addCleanup(os.remove, '/run/systemd/network/test.netdev') - self.addCleanup(os.remove, '/run/systemd/network/test.network') subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) @@ -432,23 +432,18 @@ Domains= one two three four five six seven eight nine ten''') name_prefix = 'a' * 60 - with open('/run/systemd/network/test.netdev', 'w') as f: - f.write('''[NetDev] + self.writeConfig('/run/systemd/network/test.netdev', '''\ +[NetDev] Name=dummy0 Kind=dummy MACAddress=12:34:56:78:9a:bc''') - with open('/run/systemd/network/test.network', 'w') as f: - f.write('''[Match] + self.writeConfig('/run/systemd/network/test.network', '''\ +[Match] Name=dummy0 [Network] Address=192.168.42.100 DNS=192.168.42.1 -Domains=''') - for i in range(5): - f.write('%s%i ' % (name_prefix, i)) - - self.addCleanup(os.remove, '/run/systemd/network/test.netdev') - self.addCleanup(os.remove, '/run/systemd/network/test.network') +Domains={p}0 {p}1 {p}2 {p}3 {p}4'''.format(p=name_prefix)) subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) @@ -458,10 +453,9 @@ Domains=''') if ' one' in contents: break time.sleep(0.1) - self.assertRegex(contents, 'search .*%(p)s0 %(p)s1 %(p)s2' % {'p': name_prefix}) + self.assertRegex(contents, 'search .*{p}0 {p}1 {p}2'.format(p=name_prefix)) self.assertIn('# Total length of all search domains is too long, remaining ones ignored.', contents) - if __name__ == '__main__': unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) -- cgit v1.2.3-54-g00ecf From 047a0dacde06740050858d72c385cc07a4091feb Mon Sep 17 00:00:00 2001 From: Jean-Sébastien Bour Date: Sat, 9 Jul 2016 16:55:26 +0200 Subject: networkd: support drop-in directories for .network files Fixes #3655. [zj: Fix the tests.] --- src/network/networkd-network.c | 18 ++++++++++++++++-- test/networkd-test.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 49faba5b12..0b36f13be8 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -40,6 +40,10 @@ static int network_load_one(Manager *manager, const char *filename) { _cleanup_network_free_ Network *network = NULL; _cleanup_fclose_ FILE *file = NULL; char *d; + const char *dropin_dirname; + _cleanup_strv_free_ char **dropin_dirs = NULL; + _cleanup_free_ char *dropin_dirs_nulstr = NULL; + size_t dropin_dirs_nulstr_size; Route *route; Address *address; int r; @@ -137,7 +141,17 @@ static int network_load_one(Manager *manager, const char *filename) { network->arp = -1; network->ipv6_accept_ra_use_dns = true; - r = config_parse(NULL, filename, file, + dropin_dirname = strjoina("/", network->name, ".network.d"); + + r = strv_extend_strv_concat(&dropin_dirs, (char**) network_dirs, dropin_dirname); + if (r < 0) + return r; + + r = strv_make_nulstr(dropin_dirs, &dropin_dirs_nulstr, &dropin_dirs_nulstr_size); + if (r < 0) + return r; + + r = config_parse_many(filename, dropin_dirs_nulstr, "Match\0" "Link\0" "Network\0" @@ -151,7 +165,7 @@ static int network_load_one(Manager *manager, const char *filename) { "BridgeFDB\0" "BridgeVLAN\0", config_item_perf_lookup, network_network_gperf_lookup, - false, false, true, network); + false, network); if (r < 0) return r; diff --git a/test/networkd-test.py b/test/networkd-test.py index 57f4c04295..baa1dc2a47 100755 --- a/test/networkd-test.py +++ b/test/networkd-test.py @@ -456,6 +456,36 @@ Domains={p}0 {p}1 {p}2 {p}3 {p}4'''.format(p=name_prefix)) self.assertRegex(contents, 'search .*{p}0 {p}1 {p}2'.format(p=name_prefix)) self.assertIn('# Total length of all search domains is too long, remaining ones ignored.', contents) + def test_dropin(self): + # we don't use this interface for this test + self.if_router = None + + self.writeConfig('/run/systemd/network/test.netdev', '''\ +[NetDev] +Name=dummy0 +Kind=dummy +MACAddress=12:34:56:78:9a:bc''') + self.writeConfig('/run/systemd/network/test.network', '''\ +[Match] +Name=dummy0 +[Network] +Address=192.168.42.100 +DNS=192.168.42.1''') + self.writeConfig('/run/systemd/network/test.network.d/dns.conf', '''\ +[Network] +DNS=127.0.0.1''') + + subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) + + for timeout in range(50): + with open(RESOLV_CONF) as f: + contents = f.read() + if ' 127.0.0.1' in contents: + break + time.sleep(0.1) + self.assertIn('nameserver 192.168.42.1\n', contents) + self.assertIn('nameserver 127.0.0.1\n', contents) + if __name__ == '__main__': unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) -- cgit v1.2.3-54-g00ecf From 43688c49d1fdb585196d94e2e30bb29755fa591b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 10 Sep 2016 11:02:40 +0100 Subject: tree-wide: rename config_parse_many to …_nulstr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for adding a version which takes a strv. --- src/basic/def.h | 2 +- src/core/main.c | 2 +- src/coredump/coredump.c | 2 +- src/journal-remote/journal-remote.c | 2 +- src/journal-remote/journal-upload.c | 2 +- src/journal/journald-server.c | 2 +- src/login/logind.c | 2 +- src/network/networkd-conf.c | 2 +- src/network/networkd-network.c | 2 +- src/resolve/resolved-conf.c | 2 +- src/shared/conf-parser.c | 16 +++++++++------- src/shared/conf-parser.h | 38 +++++++++++++++++++------------------ src/shared/sleep-config.c | 2 +- src/timesync/timesyncd-conf.c | 2 +- 14 files changed, 41 insertions(+), 37 deletions(-) diff --git a/src/basic/def.h b/src/basic/def.h index 1a7a0f4928..2266eff650 100644 --- a/src/basic/def.h +++ b/src/basic/def.h @@ -79,7 +79,7 @@ #endif /* Return a nulstr for a standard cascade of configuration paths, - * suitable to pass to conf_files_list_nulstr() or config_parse_many() + * suitable to pass to conf_files_list_nulstr() or config_parse_many_nulstr() * to implement drop-in directories for extending configuration * files. */ #define CONF_PATHS_NULSTR(n) \ diff --git a/src/core/main.c b/src/core/main.c index 7d8322ebd8..803307c9d5 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -715,7 +715,7 @@ static int parse_config_file(void) { CONF_PATHS_NULSTR("systemd/system.conf.d") : CONF_PATHS_NULSTR("systemd/user.conf.d"); - config_parse_many(fn, conf_dirs_nulstr, "Manager\0", config_item_table_lookup, items, false, NULL); + config_parse_many_nulstr(fn, conf_dirs_nulstr, "Manager\0", config_item_table_lookup, items, false, NULL); /* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we used USEC_INFINITY * like everywhere else. */ diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index be724aed4e..9dea10b3e1 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -128,7 +128,7 @@ static int parse_config(void) { {} }; - return config_parse_many(PKGSYSCONFDIR "/coredump.conf", + return config_parse_many_nulstr(PKGSYSCONFDIR "/coredump.conf", CONF_PATHS_NULSTR("systemd/coredump.conf.d"), "Coredump\0", config_item_table_lookup, items, diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index 80e2adb100..220c71754a 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -1198,7 +1198,7 @@ static int parse_config(void) { { "Remote", "TrustedCertificateFile", config_parse_path, 0, &arg_trust }, {}}; - return config_parse_many(PKGSYSCONFDIR "/journal-remote.conf", + return config_parse_many_nulstr(PKGSYSCONFDIR "/journal-remote.conf", CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"), "Remote\0", config_item_table_lookup, items, false, NULL); diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index 4647cfdeb3..c0f967ab94 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -542,7 +542,7 @@ static int parse_config(void) { { "Upload", "TrustedCertificateFile", config_parse_path, 0, &arg_trust }, {}}; - return config_parse_many(PKGSYSCONFDIR "/journal-upload.conf", + return config_parse_many_nulstr(PKGSYSCONFDIR "/journal-upload.conf", CONF_PATHS_NULSTR("systemd/journal-upload.conf.d"), "Upload\0", config_item_table_lookup, items, false, NULL); diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 3507910919..cc352dbae2 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -1474,7 +1474,7 @@ static int server_parse_proc_cmdline(Server *s) { static int server_parse_config_file(Server *s) { assert(s); - return config_parse_many(PKGSYSCONFDIR "/journald.conf", + return config_parse_many_nulstr(PKGSYSCONFDIR "/journald.conf", CONF_PATHS_NULSTR("systemd/journald.conf.d"), "Journal\0", config_item_perf_lookup, journald_gperf_lookup, diff --git a/src/login/logind.c b/src/login/logind.c index bbbf4aef57..a9a06f5e28 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -1002,7 +1002,7 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us static int manager_parse_config_file(Manager *m) { assert(m); - return config_parse_many(PKGSYSCONFDIR "/logind.conf", + return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf", CONF_PATHS_NULSTR("systemd/logind.conf.d"), "Login\0", config_item_perf_lookup, logind_gperf_lookup, diff --git a/src/network/networkd-conf.c b/src/network/networkd-conf.c index c03e2b2ebf..49bb8c18f6 100644 --- a/src/network/networkd-conf.c +++ b/src/network/networkd-conf.c @@ -29,7 +29,7 @@ int manager_parse_config_file(Manager *m) { assert(m); - return config_parse_many(PKGSYSCONFDIR "/networkd.conf", + return config_parse_many_nulstr(PKGSYSCONFDIR "/networkd.conf", CONF_PATHS_NULSTR("systemd/networkd.conf.d"), "DHCP\0", config_item_perf_lookup, networkd_gperf_lookup, diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 0b36f13be8..1ce23b1ddb 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -151,7 +151,7 @@ static int network_load_one(Manager *manager, const char *filename) { if (r < 0) return r; - r = config_parse_many(filename, dropin_dirs_nulstr, + r = config_parse_many_nulstr(filename, dropin_dirs_nulstr, "Match\0" "Link\0" "Network\0" diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index dd233e7c4a..83f7596ac8 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -221,7 +221,7 @@ int manager_parse_config_file(Manager *m) { assert(m); - r = config_parse_many(PKGSYSCONFDIR "/resolved.conf", + r = config_parse_many_nulstr(PKGSYSCONFDIR "/resolved.conf", CONF_PATHS_NULSTR("systemd/resolved.conf.d"), "Resolve\0", config_item_perf_lookup, resolved_gperf_lookup, diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index f31d219418..f3351c6bb2 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -397,13 +397,15 @@ int config_parse(const char *unit, } /* Parse each config file in the specified directories. */ -int config_parse_many(const char *conf_file, - const char *conf_file_dirs, - const char *sections, - ConfigItemLookup lookup, - const void *table, - bool relaxed, - void *userdata) { +int config_parse_many_nulstr( + const char *conf_file, + const char *conf_file_dirs, + const char *sections, + ConfigItemLookup lookup, + const void *table, + bool relaxed, + void *userdata) { + _cleanup_strv_free_ char **files = NULL; char **fn; int r; diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 3298dc0cea..e0b8d83dab 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -84,24 +84,26 @@ int config_item_table_lookup(const void *table, const char *section, const char * ConfigPerfItem tables */ int config_item_perf_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata); -int config_parse(const char *unit, - const char *filename, - FILE *f, - const char *sections, /* nulstr */ - ConfigItemLookup lookup, - const void *table, - bool relaxed, - bool allow_include, - bool warn, - void *userdata); - -int config_parse_many(const char *conf_file, /* possibly NULL */ - const char *conf_file_dirs, /* nulstr */ - const char *sections, /* nulstr */ - ConfigItemLookup lookup, - const void *table, - bool relaxed, - void *userdata); +int config_parse( + const char *unit, + const char *filename, + FILE *f, + const char *sections, /* nulstr */ + ConfigItemLookup lookup, + const void *table, + bool relaxed, + bool allow_include, + bool warn, + void *userdata); + +int config_parse_many_nulstr( + const char *conf_file, /* possibly NULL */ + const char *conf_file_dirs, /* nulstr */ + const char *sections, /* nulstr */ + ConfigItemLookup lookup, + const void *table, + bool relaxed, + void *userdata); /* Generic parsers */ int config_parse_int(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); diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index f00624d0f2..ed31a80c8d 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -58,7 +58,7 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states) { {} }; - config_parse_many(PKGSYSCONFDIR "/sleep.conf", + config_parse_many_nulstr(PKGSYSCONFDIR "/sleep.conf", CONF_PATHS_NULSTR("systemd/sleep.conf.d"), "Sleep\0", config_item_table_lookup, items, false, NULL); diff --git a/src/timesync/timesyncd-conf.c b/src/timesync/timesyncd-conf.c index 20c64a3354..bf25b112e1 100644 --- a/src/timesync/timesyncd-conf.c +++ b/src/timesync/timesyncd-conf.c @@ -98,7 +98,7 @@ int config_parse_servers( int manager_parse_config_file(Manager *m) { assert(m); - return config_parse_many(PKGSYSCONFDIR "/timesyncd.conf", + return config_parse_many_nulstr(PKGSYSCONFDIR "/timesyncd.conf", CONF_PATHS_NULSTR("systemd/timesyncd.conf.d"), "Time\0", config_item_perf_lookup, timesyncd_gperf_lookup, -- cgit v1.2.3-54-g00ecf From 23bb31aa0a3ef7509dc5200518517d1297530534 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 10 Sep 2016 12:19:41 +0100 Subject: shared/conf-parser: add config_parse_many which takes strv with dirs This way we don't have to create a nulstr just to unpack it in a moment. --- src/network/networkd-network.c | 45 ++++++++++++------------------- src/shared/conf-parser.c | 60 ++++++++++++++++++++++++++++++++++++------ src/shared/conf-parser.h | 10 +++++++ 3 files changed, 79 insertions(+), 36 deletions(-) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 1ce23b1ddb..58e19e542a 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -41,9 +41,6 @@ static int network_load_one(Manager *manager, const char *filename) { _cleanup_fclose_ FILE *file = NULL; char *d; const char *dropin_dirname; - _cleanup_strv_free_ char **dropin_dirs = NULL; - _cleanup_free_ char *dropin_dirs_nulstr = NULL; - size_t dropin_dirs_nulstr_size; Route *route; Address *address; int r; @@ -141,31 +138,23 @@ static int network_load_one(Manager *manager, const char *filename) { network->arp = -1; network->ipv6_accept_ra_use_dns = true; - dropin_dirname = strjoina("/", network->name, ".network.d"); - - r = strv_extend_strv_concat(&dropin_dirs, (char**) network_dirs, dropin_dirname); - if (r < 0) - return r; - - r = strv_make_nulstr(dropin_dirs, &dropin_dirs_nulstr, &dropin_dirs_nulstr_size); - if (r < 0) - return r; - - r = config_parse_many_nulstr(filename, dropin_dirs_nulstr, - "Match\0" - "Link\0" - "Network\0" - "Address\0" - "Route\0" - "DHCP\0" - "DHCPv4\0" /* compat */ - "DHCPServer\0" - "IPv6AcceptRA\0" - "Bridge\0" - "BridgeFDB\0" - "BridgeVLAN\0", - config_item_perf_lookup, network_network_gperf_lookup, - false, network); + dropin_dirname = strjoina(network->name, ".network.d"); + + r = config_parse_many(filename, network_dirs, dropin_dirname, + "Match\0" + "Link\0" + "Network\0" + "Address\0" + "Route\0" + "DHCP\0" + "DHCPv4\0" /* compat */ + "DHCPServer\0" + "IPv6AcceptRA\0" + "Bridge\0" + "BridgeFDB\0" + "BridgeVLAN\0", + config_item_perf_lookup, network_network_gperf_lookup, + false, network); if (r < 0) return r; diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index f3351c6bb2..2ec0155b71 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -396,24 +396,18 @@ int config_parse(const char *unit, return 0; } -/* Parse each config file in the specified directories. */ -int config_parse_many_nulstr( +static int config_parse_many_files( const char *conf_file, - const char *conf_file_dirs, + char **files, const char *sections, ConfigItemLookup lookup, const void *table, bool relaxed, void *userdata) { - _cleanup_strv_free_ char **files = NULL; char **fn; int r; - r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); - if (r < 0) - return r; - if (conf_file) { r = config_parse(NULL, conf_file, NULL, sections, lookup, table, relaxed, false, true, userdata); if (r < 0) @@ -429,6 +423,56 @@ int config_parse_many_nulstr( return 0; } +/* Parse each config file in the directories specified as nulstr. */ +int config_parse_many_nulstr( + const char *conf_file, + const char *conf_file_dirs, + const char *sections, + ConfigItemLookup lookup, + const void *table, + bool relaxed, + void *userdata) { + + _cleanup_strv_free_ char **files = NULL; + int r; + + r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); + if (r < 0) + return r; + + return config_parse_many_files(conf_file, files, + sections, lookup, table, relaxed, userdata); +} + +/* Parse each config file in the directories specified as strv. */ +int config_parse_many( + const char *conf_file, + const char* const* conf_file_dirs, + const char *dropin_dirname, + const char *sections, + ConfigItemLookup lookup, + const void *table, + bool relaxed, + void *userdata) { + + _cleanup_strv_free_ char **dropin_dirs = NULL; + _cleanup_strv_free_ char **files = NULL; + const char *suffix; + int r; + + suffix = strjoina("/", dropin_dirname); + r = strv_extend_strv_concat(&dropin_dirs, (char**) conf_file_dirs, suffix); + if (r < 0) + return r; + + r = conf_files_list_strv(&files, ".conf", NULL, (const char* const*) dropin_dirs); + if (r < 0) + return r; + + return config_parse_many_files(conf_file, files, + sections, lookup, table, relaxed, userdata); +} + #define DEFINE_PARSER(type, vartype, conv_func) \ int config_parse_##type( \ const char *unit, \ diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index e0b8d83dab..26ff3df16f 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -105,6 +105,16 @@ int config_parse_many_nulstr( bool relaxed, void *userdata); +int config_parse_many( + const char *conf_file, /* possibly NULL */ + const char* const* conf_file_dirs, + const char *dropin_dirname, + const char *sections, /* nulstr */ + ConfigItemLookup lookup, + const void *table, + bool relaxed, + void *userdata); + /* Generic parsers */ int config_parse_int(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_unsigned(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); -- cgit v1.2.3-54-g00ecf From 2cc34d5b91684256530242b94bf6ea1f27ffa7a9 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 10 Sep 2016 14:32:19 +0100 Subject: networkd: support drop-in dirs for .network files --- src/network/networkd-netdev.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index e7edc366af..9cf678a3ef 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -577,6 +577,7 @@ static int netdev_load_one(Manager *manager, const char *filename) { _cleanup_netdev_unref_ NetDev *netdev = NULL; _cleanup_free_ NetDev *netdev_raw = NULL; _cleanup_fclose_ FILE *file = NULL; + const char *dropin_dirname; int r; assert(manager); @@ -600,11 +601,12 @@ static int netdev_load_one(Manager *manager, const char *filename) { return log_oom(); netdev_raw->kind = _NETDEV_KIND_INVALID; + dropin_dirname = strjoina(basename(filename), ".d"); - r = config_parse(NULL, filename, file, - "Match\0NetDev\0", - config_item_perf_lookup, network_netdev_gperf_lookup, - true, false, true, netdev_raw); + r = config_parse_many(filename, network_dirs, dropin_dirname, + "Match\0NetDev\0", + config_item_perf_lookup, network_netdev_gperf_lookup, + true, netdev_raw); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From bac150e9d192af1096482e19a2c9564fb633ce9c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 10 Sep 2016 14:34:07 +0100 Subject: man: mention that netdev,network files support dropins Also update the description of drop-ins in systemd.unit(5) to say that .d directories, not .conf files, are in /etc/system/system, /run/systemd/system, etc. --- man/systemd.netdev.xml | 53 ++++++++++++---------- man/systemd.network.xml | 59 ++++++++++++++---------- man/systemd.unit.xml | 118 ++++++++++++++++++++++++------------------------ 3 files changed, 123 insertions(+), 107 deletions(-) diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 1f9f071b94..585b924e3d 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -58,31 +58,38 @@ systemd-networkd8. - Virtual Network Device files must have the extension - .netdev; other extensions are ignored. - Virtual network devices are created as soon as networkd is - started. If a netdev with the specified name already exists, - networkd will use that as-is rather than create its own. Note that - the settings of the pre-existing netdev will not be changed by + The main Virtual Network Device file must have the extension .netdev; + other extensions are ignored. Virtual network devices are created as soon as networkd is + started. If a netdev with the specified name already exists, networkd will use that as-is rather + than create its own. Note that the settings of the pre-existing netdev will not be changed by networkd. - The .netdev files are read from the - files located in the system network directory - /usr/lib/systemd/network, the volatile - runtime network directory - /run/systemd/network and the local - administration network directory - /etc/systemd/network. All configuration files - are collectively sorted and processed in lexical order, regardless - of the directories in which they live. However, files with - identical filenames replace each other. Files in - /etc have the highest priority, files in - /run take precedence over files with the same - name in /usr/lib. This can be used to - override a system-supplied configuration file with a local file if - needed. As a special case, an empty file (file size 0) or symlink - with the same name pointing to /dev/null - disables the configuration file entirely (it is "masked"). + The .netdev files are read from the files located in the system + network directory /usr/lib/systemd/network, the volatile runtime network + directory /run/systemd/network and the local administration network + directory /etc/systemd/network. All configuration files are collectively + sorted and processed in lexical order, regardless of the directories in which they live. + However, files with identical filenames replace each other. Files in /etc + have the highest priority, files in /run take precedence over files with + the same name in /usr/lib. This can be used to override a system-supplied + configuration file with a local file if needed. As a special case, an empty file (file size 0) + or symlink with the same name pointing to /dev/null disables the + configuration file entirely (it is "masked"). + + Along with the netdev file foo.netdev, a "drop-in" directory + foo.netdev.d/ may exist. All files with the suffix .conf + from this directory will be parsed after the file itself is parsed. This is useful to alter or + add configuration settings, without having to modify the main configuration file. Each drop-in + file must have appropriate section headers. + + In addition to /etc/systemd/network, drop-in .d + directories can be placed in /usr/lib/systemd/network or + /run/systemd/network directories. Drop-in files in + /etc take precedence over those in /run which in turn + take precedence over those in /usr/lib. Drop-in files under any of these + directories take precedence over the main netdev file wherever located. (Of course, since + /run is temporary and /usr/lib is for vendors, it is + unlikely drop-ins should be used in either of those places.) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index c332cd7bdc..eb7d441842 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -58,31 +58,40 @@ systemd-networkd8. - Network files must have the extension - .network; other extensions are ignored. - Networks are applied to links whenever the links appear. - - The .network files are read from the - files located in the system network directory - /usr/lib/systemd/network, the volatile - runtime network directory - /run/systemd/network and the local - administration network directory - /etc/systemd/network. All configuration files - are collectively sorted and processed in lexical order, regardless - of the directories in which they live. However, files with - identical filenames replace each other. Files in - /etc have the highest priority, files in - /run take precedence over files with the same - name in /usr/lib. This can be used to - override a system-supplied configuration file with a local file if - needed. As a special case, an empty file (file size 0) or symlink - with the same name pointing to /dev/null - disables the configuration file entirely (it is "masked"). - - Note that an interface without any static IPv6 addresses configured, and neither DHCPv6 nor IPv6LL enabled, - shall be considered to have no IPv6 support. IPv6 will be automatically disabled for that interface by writing "1" - to /proc/sys/net/ipv6/conf/ifname/disable_ipv6. + The main network file must have the extension .network; other + extensions are ignored. Networks are applied to links whenever the links appear. + + The .network files are read from the files located in the system + network directory /usr/lib/systemd/network, the volatile runtime network + directory /run/systemd/network and the local administration network + directory /etc/systemd/network. All configuration files are collectively + sorted and processed in lexical order, regardless of the directories in which they live. + However, files with identical filenames replace each other. Files in /etc + have the highest priority, files in /run take precedence over files with + the same name in /usr/lib. This can be used to override a system-supplied + configuration file with a local file if needed. As a special case, an empty file (file size 0) + or symlink with the same name pointing to /dev/null disables the + configuration file entirely (it is "masked"). + + Along with the network file foo.network, a "drop-in" directory + foo.network.d/ may exist. All files with the suffix + .conf from this directory will be parsed after the file itself is + parsed. This is useful to alter or add configuration settings, without having to modify the main + configuration file. Each drop-in file must have appropriate section headers. + + In addition to /etc/systemd/network, drop-in .d + directories can be placed in /usr/lib/systemd/network or + /run/systemd/network directories. Drop-in files in + /etc take precedence over those in /run which in turn + take precedence over those in /usr/lib. Drop-in files under any of these + directories take precedence over the main netdev file wherever located. (Of course, since + /run is temporary and /usr/lib is for vendors, it is + unlikely drop-ins should be used in either of those places.) + + Note that an interface without any static IPv6 addresses configured, and neither DHCPv6 + nor IPv6LL enabled, shall be considered to have no IPv6 support. IPv6 will be automatically + disabled for that interface by writing "1" to + /proc/sys/net/ipv6/conf/ifname/disable_ipv6. diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index f818e772a9..9778283fec 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -144,71 +144,71 @@ and are equivalent. - Time span values encoded in unit files can be written in various formats. A stand-alone number specifies a - time in seconds. If suffixed with a time unit, the unit is honored. A concatenation of multiple values with units - is supported, in which case the values are added up. Example: 50 refers to 50 seconds; - 2min 200ms refers to 2 minutes and 200 milliseconds, i.e. 120200 ms. The following time units - are understood: s, min, h, d, + Time span values encoded in unit files can be written in various formats. A stand-alone + number specifies a time in seconds. If suffixed with a time unit, the unit is honored. A + concatenation of multiple values with units is supported, in which case the values are added + up. Example: 50 refers to 50 seconds; 2min 200ms refers to + 2 minutes and 200 milliseconds, i.e. 120200 ms. The following time units are understood: + s, min, h, d, w, ms, us. For details see systemd.time7. - Empty lines and lines starting with # or ; are ignored. This may be - used for commenting. Lines ending in a backslash are concatenated with the following line while reading and the - backslash is replaced by a space character. This may be used to wrap long lines. - - Units can be aliased (have an alternative name), by creating a symlink from the new name to the existing name - in one of the unit search paths. For example, systemd-networkd.service has the alias - dbus-org.freedesktop.network1.service, created during installation as the symlink - /usr/lib/systemd/system/dbus-org.freedesktop.network1.service. In addition, unit files may - specify aliases through the Alias= directive in the [Install] section; those aliases are only - effective when the unit is enabled. When the unit is enabled, symlinks will be created for those names, and removed - when the unit is disabled. For example, reboot.target specifies - Alias=ctrl-alt-del.target, so when enabled it will be invoked whenever CTRL+ALT+DEL is - pressed. Alias names may be used in commands like enable, disable, - start, stop, status, …, and in unit dependency directives - Wants=, Requires=, Before=, After=, …, - with the limitation that aliases specified through Alias= are only effective when the unit is - enabled. Aliases cannot be used with the preset command. - - Along with a unit file foo.service, the - directory foo.service.wants/ may exist. All - unit files symlinked from such a directory are implicitly added as - dependencies of type Wants= to the unit. This - is useful to hook units into the start-up of other units, without - having to modify their unit files. For details about the semantics - of Wants=, see below. The preferred way to - create symlinks in the .wants/ directory of a - unit file is with the enable command of the + Empty lines and lines starting with # or ; are + ignored. This may be used for commenting. Lines ending in a backslash are concatenated with the + following line while reading and the backslash is replaced by a space character. This may be + used to wrap long lines. + + Units can be aliased (have an alternative name), by creating a symlink from the new name + to the existing name in one of the unit search paths. For example, + systemd-networkd.service has the alias + dbus-org.freedesktop.network1.service, created during installation as the + symlink /usr/lib/systemd/system/dbus-org.freedesktop.network1.service. In + addition, unit files may specify aliases through the Alias= directive in the + [Install] section; those aliases are only effective when the unit is enabled. When the unit is + enabled, symlinks will be created for those names, and removed when the unit is disabled. For + example, reboot.target specifies + Alias=ctrl-alt-del.target, so when enabled it will be invoked whenever + CTRL+ALT+DEL is pressed. Alias names may be used in commands like enable, + disable, start, stop, + status, …, and in unit dependency directives Wants=, + Requires=, Before=, After=, …, with the + limitation that aliases specified through Alias= are only effective when the + unit is enabled. Aliases cannot be used with the preset command. + + Along with a unit file foo.service, the directory + foo.service.wants/ may exist. All unit files symlinked from such a + directory are implicitly added as dependencies of type Wants= to the unit. + This is useful to hook units into the start-up of other units, without having to modify their + unit files. For details about the semantics of Wants=, see below. The + preferred way to create symlinks in the .wants/ directory of a unit file is + with the enable command of the systemctl1 - tool which reads information from the [Install] section of unit - files (see below). A similar functionality exists for - Requires= type dependencies as well, the - directory suffix is .requires/ in this - case. + tool which reads information from the [Install] section of unit files (see below). A similar + functionality exists for Requires= type dependencies as well, the directory + suffix is .requires/ in this case. Along with a unit file foo.service, a "drop-in" directory - foo.service.d/ may exist. All files with the suffix .conf from this - directory will be parsed after the file itself is parsed. This is useful to alter or add configuration settings for - a unit, without having to modify unit files. Each drop-in file must have appropriate section headers. Note that for - instantiated units, this logic will first look for the instance .d/ subdirectory and read its - .conf files, followed by the template .d/ subdirectory and the - .conf files there. Also note that settings from the [Install] section are not - honoured in drop-in unit files, and have no effect. - - In addition to /etc/systemd/system, - the drop-in .conf files for system services - can be placed in /usr/lib/systemd/system or - /run/systemd/system directories. Drop-in - files in /etc take precedence over those in - /run which in turn take precedence over - those in /usr/lib. Drop-in files under any of - these directories take precedence over unit files wherever located. - (Of course, since /run is temporary and - /usr/lib is for vendors, it is unlikely - drop-ins should be used in either of those places.) - + foo.service.d/ may exist. All files with the suffix + .conf from this directory will be parsed after the file itself is + parsed. This is useful to alter or add configuration settings for a unit, without having to + modify unit files. Each drop-in file must have appropriate section headers. Note that for + instantiated units, this logic will first look for the instance .d/ + subdirectory and read its .conf files, followed by the template + .d/ subdirectory and the .conf files there. Also note that + settings from the [Install] section are not honoured in drop-in unit files, + and have no effect. + + In addition to /etc/systemd/system, the drop-in .d + directories for system services can be placed in /usr/lib/systemd/system or + /run/systemd/system directories. Drop-in files in /etc + take precedence over those in /run which in turn take precedence over those + in /usr/lib. Drop-in files under any of these directories take precedence + over unit files wherever located. (Of course, since /run is temporary and + /usr/lib is for vendors, it is unlikely drop-ins should be used in either + of those places.) + + Some unit names reflect paths existing in the file system namespace. Example: a device unit -- cgit v1.2.3-54-g00ecf From 881e6b5edfd6ff82e0683678f19c887cbacab344 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 10 Sep 2016 17:44:50 +0100 Subject: networkd: change message about missing Kind If Kind is not specied, the message about "Invalid Kind" was misleading. If Kind was specified in an invalid way, we get a message in the parsing phase anyway. Reword the message to cover both cases better. --- src/network/networkd-netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index 9cf678a3ef..ece4ea2e64 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -622,7 +622,7 @@ static int netdev_load_one(Manager *manager, const char *filename) { return 0; if (netdev_raw->kind == _NETDEV_KIND_INVALID) { - log_warning("NetDev with invalid Kind configured in %s. Ignoring", filename); + log_warning("NetDev has no Kind configured in %s. Ignoring", filename); return 0; } -- cgit v1.2.3-54-g00ecf From 0b493a02631d08bd2f48db8bc618dcd1fe3bdcb3 Mon Sep 17 00:00:00 2001 From: Michael Pope Date: Sat, 17 Sep 2016 00:59:28 -0700 Subject: nspawn: clarify log warning for /etc/localtime not being a symbolic link (#4163) --- src/nspawn/nspawn.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 6d0420965a..6f4a33cd96 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1219,7 +1219,13 @@ static int setup_timezone(const char *dest) { /* Fix the timezone, if possible */ r = readlink_malloc("/etc/localtime", &p); if (r < 0) { - log_warning("/etc/localtime is not a symlink, not updating container timezone."); + log_warning("host's /etc/localtime is not a symlink, not updating container timezone."); + /* to handle warning, delete /etc/localtime and replace it + * it /w a symbolic link to a time zone data file. + * + * Example: + * ln -s /etc/localtime /usr/share/zoneinfo/UTC + */ return 0; } -- cgit v1.2.3-54-g00ecf From 7ce9cc154576e342015eab8c1500790a9ededc01 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Sat, 17 Sep 2016 16:39:00 +0200 Subject: Revert "kernel-install: Add KERNEL_INSTALL_NOOP (#4103)" Further discussion showed that this better gets addressed at the packaging level. This reverts commit 34210af7c63640fca1fd4a09fc23b01a8cd70bf3. --- src/kernel-install/kernel-install | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install index f37c023c6a..c66bcfc092 100644 --- a/src/kernel-install/kernel-install +++ b/src/kernel-install/kernel-install @@ -61,13 +61,6 @@ for i in "$@"; do fi done -# KERNEL_INSTALL_NOOP may be used by programs like lorax and rpm-ostree which -# want to install a kernel (indirectly via RPM), but control generation of the -# initramfs. In general, OSTree takes over kernel management too. -if test -n "${KERNEL_INSTALL_NOOP:-}"; then - exit 0 -fi - if [[ "${0##*/}" == 'installkernel' ]]; then COMMAND='add' else -- cgit v1.2.3-54-g00ecf From dd8352659c9428b196706d04399eec106a8917ed Mon Sep 17 00:00:00 2001 From: Felix Zhang Date: Sun, 18 Sep 2016 17:14:50 +0800 Subject: journal: fix typo in comment (#4176) --- src/journal/journald-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index cc352dbae2..a762558e3d 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -1587,7 +1587,7 @@ static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents, assert(s->notify_fd == fd); /* The $NOTIFY_SOCKET is writable again, now send exactly one - * message on it. Either it's the wtachdog event, the initial + * message on it. Either it's the watchdog event, the initial * READY=1 event or an stdout stream event. If there's nothing * to write anymore, turn our event source off. The next time * there's something to send it will be turned on again. */ -- cgit v1.2.3-54-g00ecf From f594276b8659a04a8cb18ea3fef3ddb1ed10524a Mon Sep 17 00:00:00 2001 From: Jason Kölker Date: Mon, 19 Sep 2016 02:26:12 +0000 Subject: networkd: Allow specifying RouteTable for DHCP --- man/systemd.network.xml | 9 +++++++++ src/network/networkd-dhcp4.c | 3 +++ src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 31 +++++++++++++++++++++++++++++++ src/network/networkd-network.h | 2 ++ 5 files changed, 46 insertions(+) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index eb7d441842..961ff64ff0 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -917,6 +917,15 @@ DHCP server. + + + RouteTable=num + + The table identifier for dhcp routes (a number between 1 and 4294967295, or 0 to unset). + The table can be retrieved using ip route show table num. + + + diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 12fb8e3fce..76d3d132ea 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -95,6 +95,7 @@ static int link_set_dhcp_routes(Link *link) { route_gw->scope = RT_SCOPE_LINK; route_gw->protocol = RTPROT_DHCP; route_gw->priority = link->network->dhcp_route_metric; + route_gw->table = link->network->dhcp_route_table; r = route_configure(route_gw, link, dhcp4_route_handler); if (r < 0) @@ -106,6 +107,7 @@ static int link_set_dhcp_routes(Link *link) { route->gw.in = gateway; route->prefsrc.in = address; route->priority = link->network->dhcp_route_metric; + route->table = link->network->dhcp_route_table; r = route_configure(route, link, dhcp4_route_handler); if (r < 0) { @@ -136,6 +138,7 @@ static int link_set_dhcp_routes(Link *link) { assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0); assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0); route->priority = link->network->dhcp_route_metric; + route->table = link->network->dhcp_route_table; r = route_configure(route, link, dhcp4_route_handler); if (r < 0) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index b96f0b7210..65ea20c4ca 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -92,6 +92,7 @@ DHCP.VendorClassIdentifier, config_parse_string, DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid.type) DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid) DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) +DHCP.RouteTable, config_parse_dhcp_route_table, 0, offsetof(Network, dhcp_route_table) DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) DHCP.IAID, config_parse_iaid, 0, offsetof(Network, iaid) IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 313abca762..c7dc785b24 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -111,6 +111,7 @@ static int network_load_one(Manager *manager, const char *filename) { network->dhcp_send_hostname = true; network->dhcp_route_metric = DHCP_ROUTE_METRIC; network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID; + network->dhcp_route_table = RT_TABLE_MAIN; network->dhcp_server_emit_dns = true; network->dhcp_server_emit_ntp = true; @@ -1033,6 +1034,36 @@ int config_parse_dnssec_negative_trust_anchors( return 0; } +int config_parse_dhcp_route_table(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) { + uint32_t rt; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou32(rvalue, &rt); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Unable to read RouteTable, ignoring assignment: %s", rvalue); + return 0; + } + + *((uint32_t *)data) = rt; + + return 0; +} + DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting"); static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = { diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 5460eb4d1c..a34dbf5c7b 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -123,6 +123,7 @@ struct Network { bool dhcp_use_routes; bool dhcp_use_timezone; unsigned dhcp_route_metric; + uint32_t dhcp_route_table; /* DHCP Server Support */ bool dhcp_server; @@ -228,6 +229,7 @@ int config_parse_dhcp_server_ntp(const char *unit, const char *filename, unsigne int config_parse_dnssec_negative_trust_anchors(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_dhcp_use_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_lldp_mode(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_dhcp_route_table(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); /* Legacy IPv4LL support */ int config_parse_ipv4ll(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); -- cgit v1.2.3-54-g00ecf From 2ba31d29a5ee8d72802d31cca711175c1fcdd7aa Mon Sep 17 00:00:00 2001 From: Jason Kölker Date: Mon, 19 Sep 2016 02:59:11 +0000 Subject: networkd: Allow specifying RouteTable for RAs --- man/systemd.network.xml | 9 +++++++++ src/network/networkd-ndisc.c | 6 +++--- src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 1 + src/network/networkd-network.h | 1 + 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 961ff64ff0..2e4d927470 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -966,6 +966,15 @@ project='man-pages'>resolv.conf5. + + + RouteTable=num + + The table identifier for dhcp routes (a number between 1 and 4294967295, or 0 to unset). + The table can be retrieved using ip route show table num. + + + diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index d9c18b32a5..c2b7970623 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -94,7 +94,7 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { } route->family = AF_INET6; - route->table = RT_TABLE_MAIN; + route->table = link->network->ipv6_accept_ra_route_table; route->protocol = RTPROT_RA; route->pref = preference; route->gw.in6 = gateway; @@ -214,7 +214,7 @@ static void ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) } route->family = AF_INET6; - route->table = RT_TABLE_MAIN; + route->table = link->network->ipv6_accept_ra_route_table; route->protocol = RTPROT_RA; route->flags = RTM_F_PREFIX; route->dst_prefixlen = prefixlen; @@ -285,7 +285,7 @@ static void ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { } route->family = AF_INET6; - route->table = RT_TABLE_MAIN; + route->table = link->network->ipv6_accept_ra_route_table; route->protocol = RTPROT_RA; route->pref = preference; route->gw.in6 = gateway; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 65ea20c4ca..62779c7c48 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -97,6 +97,7 @@ DHCP.UseTimezone, config_parse_bool, DHCP.IAID, config_parse_iaid, 0, offsetof(Network, iaid) IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns) IPv6AcceptRA.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains) +IPv6AcceptRA.RouteTable, config_parse_dhcp_route_table, 0, offsetof(Network, ipv6_accept_ra_route_table) DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec) DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec) DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index c7dc785b24..584cb96979 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -138,6 +138,7 @@ static int network_load_one(Manager *manager, const char *filename) { network->proxy_arp = -1; network->arp = -1; network->ipv6_accept_ra_use_dns = true; + network->ipv6_accept_ra_route_table = RT_TABLE_MAIN; dropin_dirname = strjoina(network->name, ".network.d"); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index a34dbf5c7b..ef4b499ab9 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -167,6 +167,7 @@ struct Network { bool ipv6_accept_ra_use_dns; DHCPUseDomains ipv6_accept_ra_use_domains; + uint32_t ipv6_accept_ra_route_table; union in_addr_union ipv6_token; IPv6PrivacyExtensions ipv6_privacy_extensions; -- cgit v1.2.3-54-g00ecf From 21dc02277d6f0844c1f7ab7ccb543b69848fff32 Mon Sep 17 00:00:00 2001 From: Michael Pope Date: Mon, 19 Sep 2016 22:30:48 -0700 Subject: nspawn: fix comment typo in setup_timezone example (#4183) --- src/nspawn/nspawn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 6f4a33cd96..632c12898f 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1224,7 +1224,7 @@ static int setup_timezone(const char *dest) { * it /w a symbolic link to a time zone data file. * * Example: - * ln -s /etc/localtime /usr/share/zoneinfo/UTC + * ln -s /usr/share/zoneinfo/UTC /etc/localtime */ return 0; } -- cgit v1.2.3-54-g00ecf From af0a10bfa1a4f73195575681c215ff43183ae4b4 Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Tue, 20 Sep 2016 21:24:45 +0200 Subject: nss: install nss modules to ${rootlibdir} NSS modules (libnss_*.so.*) need to be installed into ${rootlibdir} (typically /lib) in order to be used. Previously, the modules were installed into ${libdir}, thus usually ending up in /usr/lib, even on systems where split usr is enabled, or ${libdir} is passed explicitly. Signed-off-by: Maciek Borzecki --- Makefile.am | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 946af196f3..ed14610893 100644 --- a/Makefile.am +++ b/Makefile.am @@ -157,6 +157,7 @@ nodist_zshcompletion_DATA = $(nodist_zshcompletion_data) endif udevlibexec_PROGRAMS = gperf_gperf_sources = +rootlib_LTLIBRARIES = in_files = $(filter %.in,$(EXTRA_DIST)) in_in_files = $(filter %.in.in, $(in_files)) @@ -5056,7 +5057,7 @@ libnss_systemd_la_LIBADD = \ libsystemd-internal.la \ libbasic.la -lib_LTLIBRARIES += \ +rootlib_LTLIBRARIES += \ libnss_systemd.la # ------------------------------------------------------------------------------ @@ -5078,7 +5079,7 @@ libnss_myhostname_la_LIBADD = \ libsystemd-internal.la \ libbasic.la -lib_LTLIBRARIES += \ +rootlib_LTLIBRARIES += \ libnss_myhostname.la endif @@ -5177,7 +5178,7 @@ libnss_mymachines_la_LIBADD = \ libsystemd-internal.la \ libbasic.la -lib_LTLIBRARIES += \ +rootlib_LTLIBRARIES += \ libnss_mymachines.la endif @@ -5476,7 +5477,7 @@ libnss_resolve_la_LIBADD = \ libbasic.la \ -ldl -lib_LTLIBRARIES += \ +rootlib_LTLIBRARIES += \ libnss_resolve.la systemd_resolve_SOURCES = \ -- cgit v1.2.3-54-g00ecf From 86c2fc21f98e5a1a3deb7759f493e24f73e49b85 Mon Sep 17 00:00:00 2001 From: Daniel Maixner Date: Wed, 21 Sep 2016 14:42:35 +0200 Subject: l10n: add Czech Translation (#4195) --- po/LINGUAS | 1 + po/cs.po | 585 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 586 insertions(+) create mode 100644 po/cs.po diff --git a/po/LINGUAS b/po/LINGUAS index 2f1ba199ac..287d42b047 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -1,6 +1,7 @@ be be@latin bg +cs da de el diff --git a/po/cs.po b/po/cs.po new file mode 100644 index 0000000000..c15c4bea89 --- /dev/null +++ b/po/cs.po @@ -0,0 +1,585 @@ +# translation of cs.po to Czech +# Daniel Maixner 2016 +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-04-23 14:24+0200\n" +"PO-Revision-Date: 2016-09-20 15:00+0200\n" +"Last-Translator: Daniel Maixner \n" +"Language: cs_CZ\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 1.8.8\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Odeslat heslo zpět do systému" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Autentizace je vyžadována pro odeslání zadaného hesla do systému" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Správa systémových služeb nebo dalších jednotek (units)" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Autentizace je vyžadována pro správu systémových služeb nebo dalších " +"jednotek (units)" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Správa systémové služby nebo souborů jednotky (unit files)" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Autentizace je vyžadována pro správu systémové služby nebo souborů jednotky " +"(unit files)" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Nastavení nebo zrušení proměnné správce systému a služeb " + + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Autentizace je vyžadována pro nastavení nebo rušení proměnných správce " +"systému a služeb " + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Znovu načti stav systemd" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "Autentizace je vyžadována pro znovu načtení stavu systemd" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Nastavení názvu stroje (host name)" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "" +"Autentizace je vyžadována pro nastavení lokálního názvu stroje (local host " +"name)" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Nastavení statického názvu stoje" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Autentizace je požadována pro nastavení staticky konfigurovaný název " +"lokálního stroje, stejně tak pro změnu uživatelsky přívětivého jména" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Nastavení informací o stroji" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "Autentizace je vyžadována pro nastavení informací o stroji" + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "Import obrazu virtuální stroje nebo kontejneru" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Autentizace je vyžadována pro Import oprazu virtuální stroje nebo kontejneru" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "Export obrazu virtuální stroje nebo kontejneru" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Autentizace je vyžadována pro export obrazu virtuální stroje nebo kontejneru" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "Stáhnout obraz virtuální stroje nebo kontejneru" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Autentizace je vyžadována pro stažení obrazu virtuální stroje nebo kontejneru" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Nastavení lokalizace systému" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "Autentizace je vyžadována pro nastavení lokalizace systému" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Nastavení systémové konfigurace klávesnice" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Autentizace je vyžadována pro nastavení systémové konfigurace klávesnice" + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Povolit aplikacím zakázat vypnutí systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Autentizace je vyžadována pro povolení aplikacím zakázat vypnutí systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Povolit aplikacím odložit vypnutí systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Autentizace je vyžadována pro povolení aplikacím zdržet vypnutí systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Povolit aplikacím zakázat uspání systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Autentizace je vyžadována pro povolení aplikacím zakázat uspání systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Povolit aplikacím odložit uspání systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Autentizace je vyžadována pro povolení aplikacím odložit uspání systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Povolit aplikacím zakázat automatické vypnutí systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Autentizace je vyžadována pro povolení aplikacím zakázat automatické " +"vypnutí systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Povolit aplikacím zakázat chovaní systému na stisknutí vypínacího tlačítka" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na " +"stisknutí vypínacího tlačítka" + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Povolit aplikacím zakázat chovaní systému na stisknutí tlačítka spánku" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na " +"stisknutí uspávacího tlačítka" + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Povolit aplikacím zakázat chovaní systému na stisknutí tlačítka hibernace" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na " +"stisknutí tlačítka hibernace" + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "Povolit aplikacím zakázat chovaní systému na zavření víka" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na " +"zavření víka" + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in user to run programs" +msgstr "Povolit nepřehlášeným uživatelům spouštět programy" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Speciální požadavek je třeba ke spuštění programů jako nepřihlášený uživatel" + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow non-logged-in users to run programs" +msgstr "Povolit nepřehlášeným uživatelům spouštět programy" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Autentizace je vyžadována ke spuštění programů jako nepřihlášený uživatel" + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Allow attaching devices to seats" +msgstr "Povolit připojování zařízení ke stanovišti" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "Authentication is required for attaching a device to a seat." +msgstr "Autentizace je vyžadována pro připojování zařízení ke stanovišti" + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Flush device to seat attachments" +msgstr "Odstranění přiřazení stanoviště - zařízení" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Autentizace je vyžadována pro reset způsobu jak jsou zařízení přiřazována ke " +"stanovištím" + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system" +msgstr "Vypnutí systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "Authentication is required for powering off the system." +msgstr "Autentizace je vyžadována pro vypnutí systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while other users are logged in" +msgstr "Vypnout systém, když jsou jiní uživatelé přihlášení" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Autentizace je vyžadována pro vypnutí systém, když jsou jiní uživatelé " +"přihlášení" + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Vypnout systém, když aplikace požádala o jeho zakázání" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Autentizace je vyžadována pro vypnutí systému, když aplikace požádala o jeho " +"zakázání" + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system" +msgstr "Restartovat systém" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "Authentication is required for rebooting the system." +msgstr "Autentizace je vyžadována pro restartovaní systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while other users are logged in" +msgstr "Restartovat systém, když jsou jiný uživatelé přihlášení" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Autentizace je požadována pro restart systému, když jsou jiní uživatelé " +"přihlášení" + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Restartovat systém, když aplikace požádala o jeho zakázání" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Autentizace je vyžadována pro restart systému, když aplikace požádala o jeho " +"zakázání" + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system" +msgstr "Uspání systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "Authentication is required for suspending the system." +msgstr "Autentizace je vyžadována pro uspání systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while other users are logged in" +msgstr "Uspat systém, když jsou jiní uživatelé přihlášení" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Autentizace je vyžadována pro uspání systému, když jsou jiní uživatelé " +"přihlášení" + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Uspat systém, když aplikace požádala o jeho zakázání" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Autentizace je vyžadována pro uspání systému, když aplikace požádala o jeho " +"zakázání" + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system" +msgstr "Hibernace systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "Authentication is required for hibernating the system." +msgstr "Autentizace je potřeba k hibernaci systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while other users are logged in" +msgstr "Hibernovat systém, když jsou přihlášeni jiní uživatelé" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Autentizace je vyžadována pro hibernaci systému, když jsou přihlášeni jiní " +"uživatelé" + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Hibernace systému, když aplikace pořádala o její zakázání" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Autentizace je vyžadována pro hibernaci systému, když aplikace požádala o " +"její zakázání" + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Manage active sessions, users and seats" +msgstr "Správa aktivních sezení, uživatelů a stanovišť" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Autentizace je vyžadována pro správu aktivních sezení, uživatelů a stanovišť" + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Lock or unlock active sessions" +msgstr "Zamčení nebo odemčení aktivních sezení" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "Autentizace je vyžadována pro zamčení nebo odemčení aktivních sezení" + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "Povolit indikaci firmwaru bootovat instalační prostředí" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Autentizace je vyžadována k povolení indikace firmwaru bootovat instalační " +"prostředí" + +#: ../src/login/org.freedesktop.login1.policy.in.h:57 +msgid "Set a wall message" +msgstr "Nastavit Wall zprávu" + +#: ../src/login/org.freedesktop.login1.policy.in.h:58 +msgid "Authentication is required to set a wall message" +msgstr "Autentizace je vyžadována k nastavení Wall zprávy" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Přihlásit se do lokálního kontejneru" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "Autentizace je vyžadována pro přihlášení do lokálního kontejneru" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Přihlásit se na lokální stroj" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "Autentizace je vyžadována pro přihlášení k lokálnímu stroji" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Získání shell z lokálního kontejneru" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "Autentizace je vyžadována pro získání shellu z lokálního kontejneru" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Získání shell z lokálního stroje" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "Autentizace je vyžadována pro získání shellu z lokálního stroje" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Získání Pseudo TTY v lokálním kontejneru" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "Autentizace je vyžadována pro získání pseudo TTY v lokálním kontejneru" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Získání pseudo TTY na lokální stroji" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "Autentizace je vyžadována prozískání pseuto TTY na lokálním stroji" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Spravovat lokální virtuální stroje a kontejery" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Autentizace je vyžadována pro správu lokálních virtuálních mašin a kontejerů" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Spravovat lokální obrazy virtuálních mašin a kontejnerů" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Autentizace je požadována ke správě obrazů virtuálních mašin a kontejnerů" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Nastavit systémový čas" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Autentizace je požadována pro nastavení systémového času" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Nastavit systémovou časovou zónu" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "Autentizace je požadována pro nastavení systémové časové zóny" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Nastavit RTC na lokální časovou zónu nebo UTC" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Autentizace je vyžadována pro kontrolu jestli RTC ukládá lokální časovou " +"zónu nebo UTC čas" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Vypnout nebo zapnout synchronizaci s časem ze sítě " + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "Autentizace je požadována pro kontrolu synchronizace času ze sítě" + +#: ../src/core/dbus-unit.c:450 +msgid "Authentication is required to start '$(unit)'." +msgstr "Autentizace je vyžadována pro spuštění „$(unit)”." + +#: ../src/core/dbus-unit.c:451 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Autentizace je vyžadována pro vypnutí „$(unit)”" + +#: ../src/core/dbus-unit.c:452 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Autentizace je vyžadována pro znovu načtení „$(unit)”" + +#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Autentizace je vyžadována pro restart „$(unit)”" + +#: ../src/core/dbus-unit.c:560 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Autentizace je vyžadována pro ukončení „$(unit)”" + +#: ../src/core/dbus-unit.c:590 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Autentizace je vyžadována pro resetování chybného („failed”) stavu " +"„$(unit)”." + +#: ../src/core/dbus-unit.c:622 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Autentizace je vyžadována pro nastavení vlastností na „$(unit)”." + + -- cgit v1.2.3-54-g00ecf From 8bf9763656c9209f74cda460225da5a9939494cc Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 21 Sep 2016 14:56:04 +0200 Subject: sd-hwdb: fix child/value offset calculation It is not legal to use hard-coded types to calculate offsets. We must always use the offsets of the hwdb header to calculate those. Otherwise, we will break horribly if run on hwdb files written by other implementations or written with future extensions. Signed-off-by: David Herrmann --- src/libsystemd/sd-hwdb/sd-hwdb.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c index 062fa97b17..fb9522959f 100644 --- a/src/libsystemd/sd-hwdb/sd-hwdb.c +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -97,15 +97,20 @@ static void linebuf_rem_char(struct linebuf *buf) { linebuf_rem(buf, 1); } -static const struct trie_child_entry_f *trie_node_children(sd_hwdb *hwdb, const struct trie_node_f *node) { - return (const struct trie_child_entry_f *)((const char *)node + le64toh(hwdb->head->node_size)); +static const struct trie_child_entry_f *trie_node_child(sd_hwdb *hwdb, const struct trie_node_f *node, size_t idx) { + const char *base = (const char *)node; + + base += le64toh(hwdb->head->node_size); + base += idx * le64toh(hwdb->head->child_entry_size); + return (const struct trie_child_entry_f *)base; } -static const struct trie_value_entry_f *trie_node_values(sd_hwdb *hwdb, const struct trie_node_f *node) { +static const struct trie_value_entry_f *trie_node_value(sd_hwdb *hwdb, const struct trie_node_f *node, size_t idx) { const char *base = (const char *)node; base += le64toh(hwdb->head->node_size); base += node->children_count * le64toh(hwdb->head->child_entry_size); + base += idx * le64toh(hwdb->head->value_entry_size); return (const struct trie_value_entry_f *)base; } @@ -129,7 +134,7 @@ static const struct trie_node_f *node_lookup_f(sd_hwdb *hwdb, const struct trie_ struct trie_child_entry_f search; search.c = c; - child = bsearch(&search, trie_node_children(hwdb, node), node->children_count, + child = bsearch(&search, (const char *)node + le64toh(hwdb->head->node_size), node->children_count, le64toh(hwdb->head->child_entry_size), trie_children_cmp_f); if (child) return trie_node_from_off(hwdb, child->child_off); @@ -177,7 +182,7 @@ static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t linebuf_add(buf, prefix + p, len); for (i = 0; i < node->children_count; i++) { - const struct trie_child_entry_f *child = &trie_node_children(hwdb, node)[i]; + const struct trie_child_entry_f *child = trie_node_child(hwdb, node, i); linebuf_add_char(buf, child->c); err = trie_fnmatch_f(hwdb, trie_node_from_off(hwdb, child->child_off), 0, buf, search); @@ -188,8 +193,8 @@ static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t if (le64toh(node->values_count) && fnmatch(linebuf_get(buf), search, 0) == 0) for (i = 0; i < le64toh(node->values_count); i++) { - err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[i].key_off), - trie_string(hwdb, trie_node_values(hwdb, node)[i].value_off)); + err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_value(hwdb, node, i)->key_off), + trie_string(hwdb, trie_node_value(hwdb, node, i)->value_off)); if (err < 0) return err; } @@ -254,8 +259,8 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) { size_t n; for (n = 0; n < le64toh(node->values_count); n++) { - err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[n].key_off), - trie_string(hwdb, trie_node_values(hwdb, node)[n].value_off)); + err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_value(hwdb, node, n)->key_off), + trie_string(hwdb, trie_node_value(hwdb, node, n)->value_off)); if (err < 0) return err; } -- cgit v1.2.3-54-g00ecf From 698c5a176ead078e7c86c541be714ccb464dae95 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 21 Sep 2016 14:22:49 +0200 Subject: hwdb: store file-name and file-number with properties Extend the hwdb to store the source file-name and file-number for each property. We simply extend the stored value struct with the new information. It is fully backwards compatible and old readers will continue to work. The libudev/sd-hwdb reader is updated in a followup. Signed-off-by: David Herrmann --- src/hwdb/hwdb.c | 56 +++++++++++++++++++++++++--------- src/libsystemd/sd-hwdb/hwdb-internal.h | 8 +++++ 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c index e12cd93d1c..be4ef5f9e9 100644 --- a/src/hwdb/hwdb.c +++ b/src/hwdb/hwdb.c @@ -85,6 +85,8 @@ struct trie_child_entry { struct trie_value_entry { size_t key_off; size_t value_off; + size_t filename_off; + size_t line_number; }; static int trie_children_cmp(const void *v1, const void *v2) { @@ -157,14 +159,19 @@ static int trie_values_cmp(const void *v1, const void *v2, void *arg) { } static int trie_node_add_value(struct trie *trie, struct trie_node *node, - const char *key, const char *value) { - ssize_t k, v; + const char *key, const char *value, + const char *filename, size_t line_number) { + ssize_t k, v, fn; struct trie_value_entry *val; + int r; k = strbuf_add_string(trie->strings, key, strlen(key)); if (k < 0) return k; v = strbuf_add_string(trie->strings, value, strlen(value)); + if (v < 0) + return v; + fn = strbuf_add_string(trie->strings, filename, strlen(filename)); if (v < 0) return v; @@ -176,8 +183,20 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node, val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie); if (val) { + /* + * At this point we have 2 identical properties on the same match-string. We + * strictly order them by filename+line-number, since we know the dynamic + * runtime lookup does the same for multiple matching nodes. + */ + r = strcmp(filename, trie->strings->buf + val->filename_off); + if (r < 0 || + (r == 0 && line_number < val->line_number)) + return 0; + /* replace existing earlier key with new value */ val->value_off = v; + val->filename_off = fn; + val->line_number = line_number; return 0; } } @@ -190,13 +209,16 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node, node->values = val; node->values[node->values_count].key_off = k; node->values[node->values_count].value_off = v; + node->values[node->values_count].filename_off = fn; + node->values[node->values_count].line_number = line_number; node->values_count++; qsort_r(node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie); return 0; } static int trie_insert(struct trie *trie, struct trie_node *node, const char *search, - const char *key, const char *value) { + const char *key, const char *value, + const char *filename, uint64_t line_number) { size_t i = 0; int err = 0; @@ -250,7 +272,7 @@ static int trie_insert(struct trie *trie, struct trie_node *node, const char *se c = search[i]; if (c == '\0') - return trie_node_add_value(trie, node, key, value); + return trie_node_add_value(trie, node, key, value, filename, line_number); child = node_lookup(node, c); if (!child) { @@ -274,7 +296,7 @@ static int trie_insert(struct trie *trie, struct trie_node *node, const char *se return err; } - return trie_node_add_value(trie, child, key, value); + return trie_node_add_value(trie, child, key, value, filename, line_number); } node = child; @@ -303,7 +325,7 @@ static void trie_store_nodes_size(struct trie_f *trie, struct trie_node *node) { for (i = 0; i < node->children_count; i++) trie->strings_off += sizeof(struct trie_child_entry_f); for (i = 0; i < node->values_count; i++) - trie->strings_off += sizeof(struct trie_value_entry_f); + trie->strings_off += sizeof(struct trie_value_entry2_f); } static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node) { @@ -349,12 +371,14 @@ static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node) { /* append values array */ for (i = 0; i < node->values_count; i++) { - struct trie_value_entry_f v = { + struct trie_value_entry2_f v = { .key_off = htole64(trie->strings_off + node->values[i].key_off), .value_off = htole64(trie->strings_off + node->values[i].value_off), + .filename_off = htole64(trie->strings_off + node->values[i].filename_off), + .line_number = htole64(node->values[i].line_number), }; - fwrite(&v, sizeof(struct trie_value_entry_f), 1, trie->f); + fwrite(&v, sizeof(struct trie_value_entry2_f), 1, trie->f); trie->values_count++; } @@ -375,7 +399,7 @@ static int trie_store(struct trie *trie, const char *filename) { .header_size = htole64(sizeof(struct trie_header_f)), .node_size = htole64(sizeof(struct trie_node_f)), .child_entry_size = htole64(sizeof(struct trie_child_entry_f)), - .value_entry_size = htole64(sizeof(struct trie_value_entry_f)), + .value_entry_size = htole64(sizeof(struct trie_value_entry2_f)), }; int err; @@ -431,14 +455,15 @@ static int trie_store(struct trie *trie, const char *filename) { log_debug("child pointers: %8"PRIu64" bytes (%8"PRIu64")", t.children_count * sizeof(struct trie_child_entry_f), t.children_count); log_debug("value pointers: %8"PRIu64" bytes (%8"PRIu64")", - t.values_count * sizeof(struct trie_value_entry_f), t.values_count); + t.values_count * sizeof(struct trie_value_entry2_f), t.values_count); log_debug("string store: %8zu bytes", trie->strings->len); log_debug("strings start: %8"PRIu64, t.strings_off); return 0; } -static int insert_data(struct trie *trie, char **match_list, char *line, const char *filename) { +static int insert_data(struct trie *trie, char **match_list, char *line, + const char *filename, size_t line_number) { char *value, **entry; value = strchr(line, '='); @@ -460,7 +485,7 @@ static int insert_data(struct trie *trie, char **match_list, char *line, const c } STRV_FOREACH(entry, match_list) - trie_insert(trie, trie->root, *entry, line, value); + trie_insert(trie, trie->root, *entry, line, value, filename, line_number); return 0; } @@ -474,6 +499,7 @@ static int import_file(struct trie *trie, const char *filename) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; _cleanup_strv_free_ char **match_list = NULL; + size_t line_number = 0; char *match = NULL; int r; @@ -485,6 +511,8 @@ static int import_file(struct trie *trie, const char *filename) { size_t len; char *pos; + ++line_number; + /* comment line */ if (line[0] == '#') continue; @@ -546,7 +574,7 @@ static int import_file(struct trie *trie, const char *filename) { /* first data */ state = HW_DATA; - insert_data(trie, match_list, line, filename); + insert_data(trie, match_list, line, filename, line_number); break; case HW_DATA: @@ -564,7 +592,7 @@ static int import_file(struct trie *trie, const char *filename) { break; } - insert_data(trie, match_list, line, filename); + insert_data(trie, match_list, line, filename, line_number); break; }; } diff --git a/src/libsystemd/sd-hwdb/hwdb-internal.h b/src/libsystemd/sd-hwdb/hwdb-internal.h index 8ffb5e5c74..4fff94ec76 100644 --- a/src/libsystemd/sd-hwdb/hwdb-internal.h +++ b/src/libsystemd/sd-hwdb/hwdb-internal.h @@ -70,3 +70,11 @@ struct trie_value_entry_f { le64_t key_off; le64_t value_off; } _packed_; + +/* v2 extends v1 with filename and line-number */ +struct trie_value_entry2_f { + le64_t key_off; + le64_t value_off; + le64_t filename_off; + le64_t line_number; +} _packed_; -- cgit v1.2.3-54-g00ecf From 3a04b789c6f17dff2000a3cdbeaaf86baa604524 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 21 Sep 2016 15:16:00 +0200 Subject: sd-hwdb: order properties by origin If we find duplicates in a property-lookup, make sure to order them by their origin. That is, matches defined "later" take precedence over earlier matches. The "later"-order is defined by file-name + line-number combination. That is, if a match is defined below another one in the same hwdb file, it takes precedence, same as if it is defined in a file ordered after another one. Signed-off-by: David Herrmann --- src/libsystemd/sd-hwdb/sd-hwdb.c | 43 ++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c index fb9522959f..488e101ea8 100644 --- a/src/libsystemd/sd-hwdb/sd-hwdb.c +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -141,12 +141,13 @@ static const struct trie_node_f *node_lookup_f(sd_hwdb *hwdb, const struct trie_ return NULL; } -static int hwdb_add_property(sd_hwdb *hwdb, const char *key, const char *value) { +static int hwdb_add_property(sd_hwdb *hwdb, const struct trie_value_entry_f *entry) { + const char *key; int r; assert(hwdb); - assert(key); - assert(value); + + key = trie_string(hwdb, entry->key_off); /* * Silently ignore all properties which do not start with a @@ -157,11 +158,25 @@ static int hwdb_add_property(sd_hwdb *hwdb, const char *key, const char *value) key++; + if (le64toh(hwdb->head->value_entry_size) >= sizeof(struct trie_value_entry2_f)) { + const struct trie_value_entry2_f *old, *entry2; + + entry2 = (const struct trie_value_entry2_f *)entry; + old = ordered_hashmap_get(hwdb->properties, key); + if (old) { + /* on duplicates, we order by filename and line-number */ + r = strcmp(trie_string(hwdb, entry2->filename_off), trie_string(hwdb, old->filename_off)); + if (r < 0 || + (r == 0 && entry2->line_number < old->line_number)) + return 0; + } + } + r = ordered_hashmap_ensure_allocated(&hwdb->properties, &string_hash_ops); if (r < 0) return r; - r = ordered_hashmap_replace(hwdb->properties, key, (char*)value); + r = ordered_hashmap_replace(hwdb->properties, key, (void *)entry); if (r < 0) return r; @@ -193,8 +208,7 @@ static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t if (le64toh(node->values_count) && fnmatch(linebuf_get(buf), search, 0) == 0) for (i = 0; i < le64toh(node->values_count); i++) { - err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_value(hwdb, node, i)->key_off), - trie_string(hwdb, trie_node_value(hwdb, node, i)->value_off)); + err = hwdb_add_property(hwdb, trie_node_value(hwdb, node, i)); if (err < 0) return err; } @@ -259,8 +273,7 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) { size_t n; for (n = 0; n < le64toh(node->values_count); n++) { - err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_value(hwdb, node, n)->key_off), - trie_string(hwdb, trie_node_value(hwdb, node, n)->value_off)); + err = hwdb_add_property(hwdb, trie_node_value(hwdb, node, n)); if (err < 0) return err; } @@ -415,7 +428,7 @@ static int properties_prepare(sd_hwdb *hwdb, const char *modalias) { } _public_ int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, const char **_value) { - const char *value; + const struct trie_value_entry_f *entry; int r; assert_return(hwdb, -EINVAL); @@ -427,11 +440,11 @@ _public_ int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, c if (r < 0) return r; - value = ordered_hashmap_get(hwdb->properties, key); - if (!value) + entry = ordered_hashmap_get(hwdb->properties, key); + if (!entry) return -ENOENT; - *_value = value; + *_value = trie_string(hwdb, entry->value_off); return 0; } @@ -454,8 +467,8 @@ _public_ int sd_hwdb_seek(sd_hwdb *hwdb, const char *modalias) { } _public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value) { + const struct trie_value_entry_f *entry; const void *k; - void *v; assert_return(hwdb, -EINVAL); assert_return(key, -EINVAL); @@ -464,12 +477,12 @@ _public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **val if (hwdb->properties_modified) return -EAGAIN; - ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, &v, &k); + ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, (void **)&entry, &k); if (!k) return 0; *key = k; - *value = v; + *value = trie_string(hwdb, entry->value_off); return 1; } -- cgit v1.2.3-54-g00ecf From fbdec7923f3f1762516889341a250f43652d67ba Mon Sep 17 00:00:00 2001 From: Wilhelm Schuster Date: Thu, 22 Sep 2016 21:49:22 +0200 Subject: machine: Disable more output when quiet flag is set (#4196) --- src/machine/machinectl.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 74e1a349bc..d2ca2ef342 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -1326,10 +1326,12 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0); - if (streq(name, ".host")) - log_info("Connected to the local host. Press ^] three times within 1s to exit session."); - else - log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", name); + if (!arg_quiet) { + if (streq(name, ".host")) + log_info("Connected to the local host. Press ^] three times within 1s to exit session."); + else + log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", name); + } sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); @@ -1353,12 +1355,14 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT if (last_char != '\n') fputc('\n', stdout); - if (machine_died) - log_info("Machine %s terminated.", name); - else if (streq(name, ".host")) - log_info("Connection to the local host terminated."); - else - log_info("Connection to machine %s terminated.", name); + if (!arg_quiet) { + if (machine_died) + log_info("Machine %s terminated.", name); + else if (streq(name, ".host")) + log_info("Connection to the local host terminated."); + else + log_info("Connection to machine %s terminated.", name); + } sd_event_get_exit_code(event, &ret); return ret; -- cgit v1.2.3-54-g00ecf From a4d373452dc71d8a4e03608e7b64de0923042df8 Mon Sep 17 00:00:00 2001 From: AsciiWolf Date: Fri, 23 Sep 2016 07:11:26 +0200 Subject: l10n: update Czech translation (#4203) --- po/cs.po | 211 +++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 104 insertions(+), 107 deletions(-) diff --git a/po/cs.po b/po/cs.po index c15c4bea89..d5f1dcafeb 100644 --- a/po/cs.po +++ b/po/cs.po @@ -1,19 +1,22 @@ -# translation of cs.po to Czech -# Daniel Maixner 2016 +# Czech translation for systemd. +# Copyright (C) 2016 systemd's author and translators. +# This file is distributed under the same license as the systemd package. +# Daniel Maixner , 2016 +# Daniel Rusek , 2016 +# msgid "" msgstr "" -"Project-Id-Version: systemd\n" +"Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-04-23 14:24+0200\n" -"PO-Revision-Date: 2016-09-20 15:00+0200\n" -"Last-Translator: Daniel Maixner \n" -"Language: cs_CZ\n" +"PO-Revision-Date: 2016-09-22 16:00+0200\n" +"Last-Translator: Daniel Rusek \n" +"Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" -"X-Generator: Poedit 1.8.8\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" @@ -23,32 +26,30 @@ msgstr "Odeslat heslo zpět do systému" msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" -"Autentizace je vyžadována pro odeslání zadaného hesla do systému" +"Autentizace je vyžadována pro odeslání zadaného hesla do systému." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 msgid "Manage system services or other units" -msgstr "Správa systémových služeb nebo dalších jednotek (units)" +msgstr "Správa systémových služeb nebo dalších jednotek" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 msgid "Authentication is required to manage system services or other units." msgstr "" "Autentizace je vyžadována pro správu systémových služeb nebo dalších " -"jednotek (units)" +"jednotek." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 msgid "Manage system service or unit files" -msgstr "Správa systémové služby nebo souborů jednotky (unit files)" +msgstr "Správa systémové služby nebo souborů jednotky" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 msgid "Authentication is required to manage system service or unit files." -msgstr "" -"Autentizace je vyžadována pro správu systémové služby nebo souborů jednotky " -"(unit files)" +msgstr "Autentizace je vyžadována pro správu systémové služby nebo souborů jednotky." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "" -"Nastavení nebo zrušení proměnné správce systému a služeb " +"Nastavení nebo rušení proměnných správce systému a služeb" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 @@ -57,25 +58,23 @@ msgid "" "environment variables." msgstr "" "Autentizace je vyžadována pro nastavení nebo rušení proměnných správce " -"systému a služeb " +"systému a služeb." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" -msgstr "Znovu načti stav systemd" +msgstr "Znovu načíst stav systemd" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 msgid "Authentication is required to reload the systemd state." -msgstr "Autentizace je vyžadována pro znovu načtení stavu systemd" +msgstr "Autentizace je vyžadována pro znovu načtení stavu systemd." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 msgid "Set host name" -msgstr "Nastavení názvu stroje (host name)" +msgstr "Nastavení názvu stroje" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." -msgstr "" -"Autentizace je vyžadována pro nastavení lokálního názvu stroje (local host " -"name)" +msgstr "Autentizace je vyžadována pro nastavení lokálního názvu stroje." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" @@ -86,8 +85,8 @@ msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" -"Autentizace je požadována pro nastavení staticky konfigurovaný název " -"lokálního stroje, stejně tak pro změnu uživatelsky přívětivého jména" +"Autentizace je vyžadována pro nastavení staticky konfigurovaného názvu " +"lokálního stroje, stejně tak pro změnu uživatelsky přívětivého jména." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" @@ -95,7 +94,7 @@ msgstr "Nastavení informací o stroji" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." -msgstr "Autentizace je vyžadována pro nastavení informací o stroji" +msgstr "Autentizace je vyžadována pro nastavení informací o stroji." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" @@ -104,25 +103,25 @@ msgstr "Import obrazu virtuální stroje nebo kontejneru" #: ../src/import/org.freedesktop.import1.policy.in.h:2 msgid "Authentication is required to import a VM or container image" msgstr "" -"Autentizace je vyžadována pro Import oprazu virtuální stroje nebo kontejneru" +"Autentizace je vyžadována pro import obrazu virtuálního stroje nebo kontejneru" #: ../src/import/org.freedesktop.import1.policy.in.h:3 msgid "Export a VM or container image" -msgstr "Export obrazu virtuální stroje nebo kontejneru" +msgstr "Export obrazu virtuálního stroje nebo kontejneru" #: ../src/import/org.freedesktop.import1.policy.in.h:4 msgid "Authentication is required to export a VM or container image" msgstr "" -"Autentizace je vyžadována pro export obrazu virtuální stroje nebo kontejneru" +"Autentizace je vyžadována pro export obrazu virtuálního stroje nebo kontejneru" #: ../src/import/org.freedesktop.import1.policy.in.h:5 msgid "Download a VM or container image" -msgstr "Stáhnout obraz virtuální stroje nebo kontejneru" +msgstr "Stáhnout obraz virtuálního stroje nebo kontejneru" #: ../src/import/org.freedesktop.import1.policy.in.h:6 msgid "Authentication is required to download a VM or container image" msgstr "" -"Autentizace je vyžadována pro stažení obrazu virtuální stroje nebo kontejneru" +"Autentizace je vyžadována pro stažení obrazu virtuálního stroje nebo kontejneru" #: ../src/locale/org.freedesktop.locale1.policy.in.h:1 msgid "Set system locale" @@ -130,7 +129,7 @@ msgstr "Nastavení lokalizace systému" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." -msgstr "Autentizace je vyžadována pro nastavení lokalizace systému" +msgstr "Autentizace je vyžadována pro nastavení lokalizace systému." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" @@ -139,7 +138,7 @@ msgstr "Nastavení systémové konfigurace klávesnice" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." msgstr "" -"Autentizace je vyžadována pro nastavení systémové konfigurace klávesnice" +"Autentizace je vyžadována pro nastavení systémové konfigurace klávesnice." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" @@ -149,7 +148,7 @@ msgstr "Povolit aplikacím zakázat vypnutí systému" msgid "" "Authentication is required for an application to inhibit system shutdown." msgstr "" -"Autentizace je vyžadována pro povolení aplikacím zakázat vypnutí systému" +"Autentizace je vyžadována pro povolení aplikacím zakázat vypnutí systému." #: ../src/login/org.freedesktop.login1.policy.in.h:3 msgid "Allow applications to delay system shutdown" @@ -158,7 +157,7 @@ msgstr "Povolit aplikacím odložit vypnutí systému" #: ../src/login/org.freedesktop.login1.policy.in.h:4 msgid "Authentication is required for an application to delay system shutdown." msgstr "" -"Autentizace je vyžadována pro povolení aplikacím zdržet vypnutí systému" +"Autentizace je vyžadována pro povolení aplikacím odložit vypnutí systému." #: ../src/login/org.freedesktop.login1.policy.in.h:5 msgid "Allow applications to inhibit system sleep" @@ -167,7 +166,7 @@ msgstr "Povolit aplikacím zakázat uspání systému" #: ../src/login/org.freedesktop.login1.policy.in.h:6 msgid "Authentication is required for an application to inhibit system sleep." msgstr "" -"Autentizace je vyžadována pro povolení aplikacím zakázat uspání systému" +"Autentizace je vyžadována pro povolení aplikacím zakázat uspání systému." #: ../src/login/org.freedesktop.login1.policy.in.h:7 msgid "Allow applications to delay system sleep" @@ -176,7 +175,7 @@ msgstr "Povolit aplikacím odložit uspání systému" #: ../src/login/org.freedesktop.login1.policy.in.h:8 msgid "Authentication is required for an application to delay system sleep." msgstr "" -"Autentizace je vyžadována pro povolení aplikacím odložit uspání systému" +"Autentizace je vyžadována pro povolení aplikacím odložit uspání systému." #: ../src/login/org.freedesktop.login1.policy.in.h:9 msgid "Allow applications to inhibit automatic system suspend" @@ -188,7 +187,7 @@ msgid "" "suspend." msgstr "" "Autentizace je vyžadována pro povolení aplikacím zakázat automatické " -"vypnutí systému" +"vypnutí systému." #: ../src/login/org.freedesktop.login1.policy.in.h:11 msgid "Allow applications to inhibit system handling of the power key" @@ -201,12 +200,12 @@ msgid "" "the power key." msgstr "" "Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na " -"stisknutí vypínacího tlačítka" +"stisknutí vypínacího tlačítka." #: ../src/login/org.freedesktop.login1.policy.in.h:13 msgid "Allow applications to inhibit system handling of the suspend key" msgstr "" -"Povolit aplikacím zakázat chovaní systému na stisknutí tlačítka spánku" +"Povolit aplikacím zakázat chovaní systému na stisknutí uspávacího tlačítka" #: ../src/login/org.freedesktop.login1.policy.in.h:14 msgid "" @@ -214,7 +213,7 @@ msgid "" "the suspend key." msgstr "" "Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na " -"stisknutí uspávacího tlačítka" +"stisknutí uspávacího tlačítka." #: ../src/login/org.freedesktop.login1.policy.in.h:15 msgid "Allow applications to inhibit system handling of the hibernate key" @@ -227,7 +226,7 @@ msgid "" "the hibernate key." msgstr "" "Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na " -"stisknutí tlačítka hibernace" +"stisknutí tlačítka hibernace." #: ../src/login/org.freedesktop.login1.policy.in.h:17 msgid "Allow applications to inhibit system handling of the lid switch" @@ -239,25 +238,25 @@ msgid "" "the lid switch." msgstr "" "Autentizace je vyžadována pro povolení aplikacím zakázat chovaní systému na " -"zavření víka" +"zavření víka." #: ../src/login/org.freedesktop.login1.policy.in.h:19 msgid "Allow non-logged-in user to run programs" -msgstr "Povolit nepřehlášeným uživatelům spouštět programy" +msgstr "Povolit nepřihlášenému uživateli spouštět programy" #: ../src/login/org.freedesktop.login1.policy.in.h:20 msgid "Explicit request is required to run programs as a non-logged-in user." msgstr "" -"Speciální požadavek je třeba ke spuštění programů jako nepřihlášený uživatel" +"Speciální požadavek je třeba ke spuštění programů jako nepřihlášený uživatel." #: ../src/login/org.freedesktop.login1.policy.in.h:21 msgid "Allow non-logged-in users to run programs" -msgstr "Povolit nepřehlášeným uživatelům spouštět programy" +msgstr "Povolit nepřihlášeným uživatelům spouštět programy" #: ../src/login/org.freedesktop.login1.policy.in.h:22 msgid "Authentication is required to run programs as a non-logged-in user." msgstr "" -"Autentizace je vyžadována ke spuštění programů jako nepřihlášený uživatel" +"Autentizace je vyžadována ke spuštění programů jako nepřihlášený uživatel." #: ../src/login/org.freedesktop.login1.policy.in.h:23 msgid "Allow attaching devices to seats" @@ -265,18 +264,18 @@ msgstr "Povolit připojování zařízení ke stanovišti" #: ../src/login/org.freedesktop.login1.policy.in.h:24 msgid "Authentication is required for attaching a device to a seat." -msgstr "Autentizace je vyžadována pro připojování zařízení ke stanovišti" +msgstr "Autentizace je vyžadována pro připojování zařízení ke stanovišti." #: ../src/login/org.freedesktop.login1.policy.in.h:25 msgid "Flush device to seat attachments" -msgstr "Odstranění přiřazení stanoviště - zařízení" +msgstr "Odstranění přiřazení zařízení ke stanovištím" #: ../src/login/org.freedesktop.login1.policy.in.h:26 msgid "" "Authentication is required for resetting how devices are attached to seats." msgstr "" "Autentizace je vyžadována pro reset způsobu jak jsou zařízení přiřazována ke " -"stanovištím" +"stanovištím." #: ../src/login/org.freedesktop.login1.policy.in.h:27 msgid "Power off the system" @@ -284,31 +283,31 @@ msgstr "Vypnutí systému" #: ../src/login/org.freedesktop.login1.policy.in.h:28 msgid "Authentication is required for powering off the system." -msgstr "Autentizace je vyžadována pro vypnutí systému" +msgstr "Autentizace je vyžadována pro vypnutí systému." #: ../src/login/org.freedesktop.login1.policy.in.h:29 msgid "Power off the system while other users are logged in" -msgstr "Vypnout systém, když jsou jiní uživatelé přihlášení" +msgstr "Vypnout systém, i když jsou přihlášeni další uživatelé" #: ../src/login/org.freedesktop.login1.policy.in.h:30 msgid "" "Authentication is required for powering off the system while other users are " "logged in." msgstr "" -"Autentizace je vyžadována pro vypnutí systém, když jsou jiní uživatelé " -"přihlášení" +"Autentizace je vyžadována pro vypnutí systému, když jsou přihlášeni " +"další uživatelé." #: ../src/login/org.freedesktop.login1.policy.in.h:31 msgid "Power off the system while an application asked to inhibit it" -msgstr "Vypnout systém, když aplikace požádala o jeho zakázání" +msgstr "Vypnout systém, i když aplikace požádala o zákaz vypnutí" #: ../src/login/org.freedesktop.login1.policy.in.h:32 msgid "" "Authentication is required for powering off the system while an application " "asked to inhibit it." msgstr "" -"Autentizace je vyžadována pro vypnutí systému, když aplikace požádala o jeho " -"zakázání" +"Autentizace je vyžadována pro vypnutí systému, když aplikace požádala o " +"zákaz vypnutí." #: ../src/login/org.freedesktop.login1.policy.in.h:33 msgid "Reboot the system" @@ -316,31 +315,31 @@ msgstr "Restartovat systém" #: ../src/login/org.freedesktop.login1.policy.in.h:34 msgid "Authentication is required for rebooting the system." -msgstr "Autentizace je vyžadována pro restartovaní systému" +msgstr "Autentizace je vyžadována pro restartovaní systému." #: ../src/login/org.freedesktop.login1.policy.in.h:35 msgid "Reboot the system while other users are logged in" -msgstr "Restartovat systém, když jsou jiný uživatelé přihlášení" +msgstr "Restartovat systém, i když jsou přihlášeni další uživatelé" #: ../src/login/org.freedesktop.login1.policy.in.h:36 msgid "" "Authentication is required for rebooting the system while other users are " "logged in." msgstr "" -"Autentizace je požadována pro restart systému, když jsou jiní uživatelé " -"přihlášení" +"Autentizace je vyžadována pro restart systému, když jsou přihlášeni " +"další uživatelé." #: ../src/login/org.freedesktop.login1.policy.in.h:37 msgid "Reboot the system while an application asked to inhibit it" -msgstr "Restartovat systém, když aplikace požádala o jeho zakázání" +msgstr "Restartovat systém, i když aplikace požádala o zákaz restartu" #: ../src/login/org.freedesktop.login1.policy.in.h:38 msgid "" "Authentication is required for rebooting the system while an application " "asked to inhibit it." msgstr "" -"Autentizace je vyžadována pro restart systému, když aplikace požádala o jeho " -"zakázání" +"Autentizace je vyžadována pro restart systému, když aplikace požádala o " +"zákaz restartu." #: ../src/login/org.freedesktop.login1.policy.in.h:39 msgid "Suspend the system" @@ -348,31 +347,31 @@ msgstr "Uspání systému" #: ../src/login/org.freedesktop.login1.policy.in.h:40 msgid "Authentication is required for suspending the system." -msgstr "Autentizace je vyžadována pro uspání systému" +msgstr "Autentizace je vyžadována pro uspání systému." #: ../src/login/org.freedesktop.login1.policy.in.h:41 msgid "Suspend the system while other users are logged in" -msgstr "Uspat systém, když jsou jiní uživatelé přihlášení" +msgstr "Uspat systém, i když jsou přihlášeni další uživatelé" #: ../src/login/org.freedesktop.login1.policy.in.h:42 msgid "" "Authentication is required for suspending the system while other users are " "logged in." msgstr "" -"Autentizace je vyžadována pro uspání systému, když jsou jiní uživatelé " -"přihlášení" +"Autentizace je vyžadována pro uspání systému, když jsou přihlášeni " +"další uživatelé." #: ../src/login/org.freedesktop.login1.policy.in.h:43 msgid "Suspend the system while an application asked to inhibit it" -msgstr "Uspat systém, když aplikace požádala o jeho zakázání" +msgstr "Uspat systém, i když aplikace požádala o zákaz uspání" #: ../src/login/org.freedesktop.login1.policy.in.h:44 msgid "" "Authentication is required for suspending the system while an application " "asked to inhibit it." msgstr "" -"Autentizace je vyžadována pro uspání systému, když aplikace požádala o jeho " -"zakázání" +"Autentizace je vyžadována pro uspání systému, když aplikace požádala o " +"zákaz uspání." #: ../src/login/org.freedesktop.login1.policy.in.h:45 msgid "Hibernate the system" @@ -380,23 +379,23 @@ msgstr "Hibernace systému" #: ../src/login/org.freedesktop.login1.policy.in.h:46 msgid "Authentication is required for hibernating the system." -msgstr "Autentizace je potřeba k hibernaci systému" +msgstr "Autentizace je vyžadována k hibernaci systému." #: ../src/login/org.freedesktop.login1.policy.in.h:47 msgid "Hibernate the system while other users are logged in" -msgstr "Hibernovat systém, když jsou přihlášeni jiní uživatelé" +msgstr "Hibernovat systém, i když jsou přihlášeni další uživatelé" #: ../src/login/org.freedesktop.login1.policy.in.h:48 msgid "" "Authentication is required for hibernating the system while other users are " "logged in." msgstr "" -"Autentizace je vyžadována pro hibernaci systému, když jsou přihlášeni jiní " -"uživatelé" +"Autentizace je vyžadována pro hibernaci systému, když jsou přihlášeni " +"další uživatelé." #: ../src/login/org.freedesktop.login1.policy.in.h:49 msgid "Hibernate the system while an application asked to inhibit it" -msgstr "Hibernace systému, když aplikace pořádala o její zakázání" +msgstr "Hibernace systému, i když aplikace požádala o zákaz hibernace" #: ../src/login/org.freedesktop.login1.policy.in.h:50 msgid "" @@ -404,7 +403,7 @@ msgid "" "asked to inhibit it." msgstr "" "Autentizace je vyžadována pro hibernaci systému, když aplikace požádala o " -"její zakázání" +"zákaz hibernace." #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Manage active sessions, users and seats" @@ -414,7 +413,7 @@ msgstr "Správa aktivních sezení, uživatelů a stanovišť" msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" -"Autentizace je vyžadována pro správu aktivních sezení, uživatelů a stanovišť" +"Autentizace je vyžadována pro správu aktivních sezení, uživatelů a stanovišť." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Lock or unlock active sessions" @@ -422,7 +421,7 @@ msgstr "Zamčení nebo odemčení aktivních sezení" #: ../src/login/org.freedesktop.login1.policy.in.h:54 msgid "Authentication is required to lock or unlock active sessions." -msgstr "Autentizace je vyžadována pro zamčení nebo odemčení aktivních sezení" +msgstr "Autentizace je vyžadována pro zamčení nebo odemčení aktivních sezení." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Allow indication to the firmware to boot to setup interface" @@ -434,15 +433,15 @@ msgid "" "interface." msgstr "" "Autentizace je vyžadována k povolení indikace firmwaru bootovat instalační " -"prostředí" +"prostředí." #: ../src/login/org.freedesktop.login1.policy.in.h:57 msgid "Set a wall message" -msgstr "Nastavit Wall zprávu" +msgstr "Nastavit zprávu všem uživatelům" #: ../src/login/org.freedesktop.login1.policy.in.h:58 msgid "Authentication is required to set a wall message" -msgstr "Autentizace je vyžadována k nastavení Wall zprávy" +msgstr "Autentizace je vyžadována k nastavení zprávy všem uživatelům" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" @@ -450,7 +449,7 @@ msgstr "Přihlásit se do lokálního kontejneru" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." -msgstr "Autentizace je vyžadována pro přihlášení do lokálního kontejneru" +msgstr "Autentizace je vyžadována pro přihlášení do lokálního kontejneru." #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 msgid "Log into the local host" @@ -458,23 +457,23 @@ msgstr "Přihlásit se na lokální stroj" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 msgid "Authentication is required to log into the local host." -msgstr "Autentizace je vyžadována pro přihlášení k lokálnímu stroji" +msgstr "Autentizace je vyžadována pro přihlášení k lokálnímu stroji." #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" -msgstr "Získání shell z lokálního kontejneru" +msgstr "Získání shellu v lokálním kontejneru" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." -msgstr "Autentizace je vyžadována pro získání shellu z lokálního kontejneru" +msgstr "Autentizace je vyžadována pro získání shellu v lokálním kontejneru." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" -msgstr "Získání shell z lokálního stroje" +msgstr "Získání shellu na lokálním stroji" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 msgid "Authentication is required to acquire a shell on the local host." -msgstr "Autentizace je vyžadována pro získání shellu z lokálního stroje" +msgstr "Autentizace je vyžadována pro získání shellu na lokálním stroji." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" @@ -483,36 +482,36 @@ msgstr "Získání Pseudo TTY v lokálním kontejneru" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." -msgstr "Autentizace je vyžadována pro získání pseudo TTY v lokálním kontejneru" +msgstr "Autentizace je vyžadována pro získání pseudo TTY v lokálním kontejneru." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" -msgstr "Získání pseudo TTY na lokální stroji" +msgstr "Získání pseudo TTY na lokálním stroji" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 msgid "Authentication is required to acquire a pseudo TTY on the local host." -msgstr "Autentizace je vyžadována prozískání pseuto TTY na lokálním stroji" +msgstr "Autentizace je vyžadována pro získání pseudo TTY na lokálním stroji." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" -msgstr "Spravovat lokální virtuální stroje a kontejery" +msgstr "Spravovat lokální virtuální stroje a kontejnery" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" -"Autentizace je vyžadována pro správu lokálních virtuálních mašin a kontejerů" +"Autentizace je vyžadována pro správu lokálních virtuálních strojů a kontejnerů." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" -msgstr "Spravovat lokální obrazy virtuálních mašin a kontejnerů" +msgstr "Spravovat lokální obrazy virtuálních strojů a kontejnerů" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" "Authentication is required to manage local virtual machine and container " "images." msgstr "" -"Autentizace je požadována ke správě obrazů virtuálních mašin a kontejnerů" +"Autentizace je vyžadována ke správě obrazů virtuálních strojů a kontejnerů." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" @@ -520,7 +519,7 @@ msgstr "Nastavit systémový čas" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." -msgstr "Autentizace je požadována pro nastavení systémového času" +msgstr "Autentizace je vyžadována pro nastavení systémového času." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" @@ -528,7 +527,7 @@ msgstr "Nastavit systémovou časovou zónu" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." -msgstr "Autentizace je požadována pro nastavení systémové časové zóny" +msgstr "Autentizace je vyžadována pro nastavení systémové časové zóny." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" @@ -540,46 +539,44 @@ msgid "" "UTC time." msgstr "" "Autentizace je vyžadována pro kontrolu jestli RTC ukládá lokální časovou " -"zónu nebo UTC čas" +"zónu nebo UTC čas." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 msgid "Turn network time synchronization on or off" -msgstr "Vypnout nebo zapnout synchronizaci s časem ze sítě " +msgstr "Zapnout nebo vypnout synchronizaci s časem ze sítě" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 msgid "" "Authentication is required to control whether network time synchronization " "shall be enabled." -msgstr "Autentizace je požadována pro kontrolu synchronizace času ze sítě" +msgstr "Autentizace je vyžadována pro kontrolu synchronizace času ze sítě." #: ../src/core/dbus-unit.c:450 msgid "Authentication is required to start '$(unit)'." -msgstr "Autentizace je vyžadována pro spuštění „$(unit)”." +msgstr "Autentizace je vyžadována pro spuštění „$(unit)”." #: ../src/core/dbus-unit.c:451 msgid "Authentication is required to stop '$(unit)'." -msgstr "Autentizace je vyžadována pro vypnutí „$(unit)”" +msgstr "Autentizace je vyžadována pro vypnutí „$(unit)”." #: ../src/core/dbus-unit.c:452 msgid "Authentication is required to reload '$(unit)'." -msgstr "Autentizace je vyžadována pro znovu načtení „$(unit)”" +msgstr "Autentizace je vyžadována pro znovu načtení „$(unit)”." #: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 msgid "Authentication is required to restart '$(unit)'." -msgstr "Autentizace je vyžadována pro restart „$(unit)”" +msgstr "Autentizace je vyžadována pro restart „$(unit)”." #: ../src/core/dbus-unit.c:560 msgid "Authentication is required to kill '$(unit)'." -msgstr "Autentizace je vyžadována pro ukončení „$(unit)”" +msgstr "Autentizace je vyžadována pro ukončení „$(unit)”." #: ../src/core/dbus-unit.c:590 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" -"Autentizace je vyžadována pro resetování chybného („failed”) stavu " +"Autentizace je vyžadována pro resetování chybného stavu " "„$(unit)”." #: ../src/core/dbus-unit.c:622 msgid "Authentication is required to set properties on '$(unit)'." msgstr "Autentizace je vyžadována pro nastavení vlastností na „$(unit)”." - - -- cgit v1.2.3-54-g00ecf From 43cd8794839548a6f332875e8bee8bed2652bf2c Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Fri, 23 Sep 2016 12:12:13 +0200 Subject: journal: warn when we fail to append a tag to a journal We shouldn't silently fail when appending the tag to a journal file since FSS protection will simply be disabled in this case. --- src/journal/journal-file.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 7504326bff..f6f58a1ae3 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -333,8 +333,13 @@ JournalFile* journal_file_close(JournalFile *f) { #ifdef HAVE_GCRYPT /* Write the final tag */ - if (f->seal && f->writable) - journal_file_append_tag(f); + if (f->seal && f->writable) { + int r; + + r = journal_file_append_tag(f); + if (r < 0) + log_error_errno(r, "Failed to append tag when closing journal: %m"); + } #endif if (f->post_change_timer) { -- cgit v1.2.3-54-g00ecf From 33685a5a3a98c6ded64d0cc25e37d0180ceb0a6a Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Fri, 23 Sep 2016 13:33:01 +0200 Subject: journal: fix HMAC calculation when appending a data object Since commit 5996c7c295e073ce21d41305169132c8aa993ad0 (v190 !), the calculation of the HMAC is broken because the hash for a data object including a field is done in the wrong order: the field object is hashed before the data object is. However during verification, the hash is done in the opposite order as objects are scanned sequentially. --- src/journal/journal-file.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index f6f58a1ae3..349ef74e81 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -1374,6 +1374,12 @@ static int journal_file_append_data( if (r < 0) return r; +#ifdef HAVE_GCRYPT + r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p); + if (r < 0) + return r; +#endif + /* The linking might have altered the window, so let's * refresh our pointer */ r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); @@ -1398,12 +1404,6 @@ static int journal_file_append_data( fo->field.head_data_offset = le64toh(p); } -#ifdef HAVE_GCRYPT - r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p); - if (r < 0) - return r; -#endif - if (ret) *ret = o; -- cgit v1.2.3-54-g00ecf From 48a8d337a62cfa444769dfb8b1a7857fd8fb50e6 Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Sat, 24 Sep 2016 12:30:42 +0000 Subject: nspawn: decouple --boot from CLONE_NEWIPC (#4180) This commit is a minor tweak after the split of `--share-system`, decoupling the `--boot` option from IPC namespacing. Historically there has been a single `--share-system` option for sharing IPC/PID/UTS with the host, which was incompatible with boot/pid1 mode. After the split, it is now possible to express the requirements with better granularity. For reference, this is a followup to #4023 which contains references to previous discussions. I realized too late that CLONE_NEWIPC is not strictly needed for boot mode. --- src/nspawn/nspawn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 632c12898f..0d61d34ebf 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1045,7 +1045,8 @@ static int parse_argv(int argc, char *argv[]) { parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_NS_UTS", CLONE_NEWUTS); parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_SYSTEM", CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS); - if (arg_clone_ns_flags != (CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS)) { + if (!(arg_clone_ns_flags & CLONE_NEWPID) || + !(arg_clone_ns_flags & CLONE_NEWUTS)) { arg_register = false; if (arg_start_mode != START_PID1) { log_error("--boot cannot be used without namespacing."); -- cgit v1.2.3-54-g00ecf From 886cf982d3018f7451f0548dadbc05bd2d583bb6 Mon Sep 17 00:00:00 2001 From: HATAYAMA Daisuke Date: Sat, 24 Sep 2016 21:56:07 +0900 Subject: sysctl: configure kernel parameters in the order they occur in each sysctl configuration files (#4205) Currently, systemd-sysctl command configures kernel parameters in each sysctl configuration files in random order due to characteristics of iterator of Hashmap. However, kernel parameters need to be configured in the order they occur in each sysctl configuration files. - For example, consider fs.suid_coredump and kernel.core_pattern. If fs.suid_coredump=2 is configured before kernel.core_pattern= whose default value is "core", then kernel outputs the following message: Unsafe core_pattern used with suid_dumpable=2. Pipe handler or fully qualified core dump path required. Note that the security issue mentioned in this message has already been fixed on recent kernels, so this is just a warning message on such kernels. But it's still confusing to users that this message is output on some boot and not output on another boot. - I don't know but there could be other kernel parameters that are significant in the order they are configured. - The legacy sysctl command configures kernel parameters in the order they occur in each sysctl configuration files. Although I didn't find any official specification explaining this behavior of sysctl command, I don't think there is any meaningful reason to change this behavior, in particular, to the random one. This commit does the change by simply using OrderedHashmap instead of Hashmap. --- src/sysctl/sysctl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index ce7c26e7d3..fbc1e0eb1a 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -41,12 +41,12 @@ static char **arg_prefixes = NULL; static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysctl.d"); -static int apply_all(Hashmap *sysctl_options) { +static int apply_all(OrderedHashmap *sysctl_options) { char *property, *value; Iterator i; int r = 0; - HASHMAP_FOREACH_KEY(value, property, sysctl_options, i) { + ORDERED_HASHMAP_FOREACH_KEY(value, property, sysctl_options, i) { int k; k = sysctl_write(property, value); @@ -62,7 +62,7 @@ static int apply_all(Hashmap *sysctl_options) { return r; } -static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_enoent) { +static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ignore_enoent) { _cleanup_fclose_ FILE *f = NULL; int r; @@ -125,13 +125,13 @@ static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_eno } found: - existing = hashmap_get2(sysctl_options, p, &v); + existing = ordered_hashmap_get2(sysctl_options, p, &v); if (existing) { if (streq(value, existing)) continue; log_debug("Overwriting earlier assignment of %s in file '%s'.", p, path); - free(hashmap_remove(sysctl_options, p)); + free(ordered_hashmap_remove(sysctl_options, p)); free(v); } @@ -145,7 +145,7 @@ found: return log_oom(); } - k = hashmap_put(sysctl_options, property, new_value); + k = ordered_hashmap_put(sysctl_options, property, new_value); if (k < 0) { log_error_errno(k, "Failed to add sysctl variable %s to hashmap: %m", property); free(property); @@ -230,7 +230,7 @@ static int parse_argv(int argc, char *argv[]) { int main(int argc, char *argv[]) { int r = 0, k; - Hashmap *sysctl_options; + OrderedHashmap *sysctl_options; r = parse_argv(argc, argv); if (r <= 0) @@ -242,7 +242,7 @@ int main(int argc, char *argv[]) { umask(0022); - sysctl_options = hashmap_new(&string_hash_ops); + sysctl_options = ordered_hashmap_new(&string_hash_ops); if (!sysctl_options) { r = log_oom(); goto finish; @@ -280,7 +280,7 @@ int main(int argc, char *argv[]) { r = k; finish: - hashmap_free_free_free(sysctl_options); + ordered_hashmap_free_free_free(sysctl_options); strv_free(arg_prefixes); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -- cgit v1.2.3-54-g00ecf From eb93312810937b63bef884479ffb304452ce5385 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 24 Sep 2016 09:03:54 -0400 Subject: kernel-install: allow plugins to terminate the procedure (#4174) Replaces #4103. --- man/kernel-install.xml | 5 ++++- src/kernel-install/kernel-install | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/man/kernel-install.xml b/man/kernel-install.xml index d7e27de758..4a8a46cef4 100644 --- a/man/kernel-install.xml +++ b/man/kernel-install.xml @@ -72,9 +72,12 @@ in /usr/lib/kernel/install.d/. This can be used to override a system-supplied executables with a local file if needed; a symbolic link in /etc/kernel/install.d/ with the same name as an executable in /usr/lib/kernel/install.d/, - pointing to /dev/null, disables the executable entirely. Executables must have the + pointing to /dev/null, disables the executable entirely. Executables must have the extension .install; other extensions are ignored. + An executable should return 0 on success. It may also + return 77 to cause the whole operation to terminate + (executables later in lexical order will be skipped). diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install index c66bcfc092..0c0ee718ac 100644 --- a/src/kernel-install/kernel-install +++ b/src/kernel-install/kernel-install @@ -19,6 +19,8 @@ # You should have received a copy of the GNU Lesser General Public License # along with systemd; If not, see . +SKIP_REMAINING=77 + usage() { echo "Usage:" @@ -123,7 +125,11 @@ case $COMMAND in for f in "${PLUGINS[@]}"; do if [[ -x $f ]]; then "$f" add "$KERNEL_VERSION" "$BOOT_DIR_ABS" "$KERNEL_IMAGE" - ((ret+=$?)) + x=$? + if [[ $x == $SKIP_REMAINING ]]; then + return 0 + fi + ((ret+=$x)) fi done ;; @@ -132,7 +138,11 @@ case $COMMAND in for f in "${PLUGINS[@]}"; do if [[ -x $f ]]; then "$f" remove "$KERNEL_VERSION" "$BOOT_DIR_ABS" - ((ret+=$?)) + x=$? + if [[ $x == $SKIP_REMAINING ]]; then + return 0 + fi + ((ret+=$x)) fi done -- cgit v1.2.3-54-g00ecf From 082210c7a837063fd8b520b18c221b42059d7eff Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sat, 24 Sep 2016 14:17:30 +0200 Subject: build-sys: get rid of move-to-rootlibdir Replace move-to-rootlibdir calls in post-install hooks with explicitly used ${rootlibdir} where needed. Signed-off-by: Maciek Borzecki --- Makefile.am | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/Makefile.am b/Makefile.am index ed14610893..e823a5c515 100644 --- a/Makefile.am +++ b/Makefile.am @@ -251,16 +251,6 @@ AM_CFLAGS = $(OUR_CFLAGS) AM_LDFLAGS = $(OUR_LDFLAGS) # ------------------------------------------------------------------------------ -define move-to-rootlibdir - if test "$(libdir)" != "$(rootlibdir)"; then \ - $(MKDIR_P) $(DESTDIR)$(rootlibdir) && \ - so_img_name=$$(readlink $(DESTDIR)$(libdir)/$$libname) && \ - rm -f $(DESTDIR)$(libdir)/$$libname && \ - $(LN_S) --relative -f $(DESTDIR)$(rootlibdir)/$$so_img_name $(DESTDIR)$(libdir)/$$libname && \ - mv $(DESTDIR)$(libdir)/$$libname.* $(DESTDIR)$(rootlibdir); \ - fi -endef - INSTALL_DIRS = SHUTDOWN_TARGET_WANTS = @@ -3284,15 +3274,6 @@ libsystemd_la_LIBADD = \ libbasic.la \ libsystemd-journal-internal.la -libsystemd-install-hook: - libname=libsystemd.so && $(move-to-rootlibdir) - -libsystemd-uninstall-hook: - rm -f $(DESTDIR)$(rootlibdir)/libsystemd.so* - -INSTALL_EXEC_HOOKS += libsystemd-install-hook -UNINSTALL_EXEC_HOOKS += libsystemd-uninstall-hook - pkgconfiglib_DATA += \ src/libsystemd/libsystemd.pc @@ -3305,7 +3286,7 @@ pkginclude_HEADERS += \ src/systemd/sd-id128.h \ src/systemd/sd-daemon.h -lib_LTLIBRARIES += \ +rootlib_LTLIBRARIES += \ libsystemd.la tests += \ @@ -3637,7 +3618,7 @@ tests += \ include_HEADERS += \ src/libudev/libudev.h -lib_LTLIBRARIES += \ +rootlib_LTLIBRARIES += \ libudev.la libudev_la_SOURCES =\ @@ -3669,16 +3650,6 @@ pkgconfiglib_DATA += \ EXTRA_DIST += \ src/libudev/libudev.pc.in -# move lib from $(libdir) to $(rootlibdir) and update devel link, if needed -libudev-install-hook: - libname=libudev.so && $(move-to-rootlibdir) - -libudev-uninstall-hook: - rm -f $(DESTDIR)$(rootlibdir)/libudev.so* - -INSTALL_EXEC_HOOKS += libudev-install-hook -UNINSTALL_EXEC_HOOKS += libudev-uninstall-hook - # ------------------------------------------------------------------------------ noinst_LTLIBRARIES += \ libudev-internal.la -- cgit v1.2.3-54-g00ecf From f258e948434183a2f0a38b429bb9a2054d61d954 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Sat, 24 Sep 2016 16:07:45 +0200 Subject: networkd: do not drop config for pending interfaces (#4187) While an interface is still being processed by udev, it is in state "pending", instead of "unmanaged". We must not flush device configuration then. Further fixes commit 3104883ddc24 after commit c436d55397. Fixes #4186 --- src/network/networkd-link.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 1687d9bf31..9cd4aa2c39 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2995,7 +2995,8 @@ static int link_carrier_lost(Link *link) { if (r < 0) return r; - if (link->state != LINK_STATE_UNMANAGED) { + if (!IN_SET(link->state, LINK_STATE_UNMANAGED, LINK_STATE_PENDING)) { + log_link_debug(link, "State is %s, dropping config", link_state_to_string(link->state)); r = link_drop_foreign_config(link); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 72240b52f1d66b3d255ede56e6f70a155f1acae1 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 24 Sep 2016 19:17:31 -0400 Subject: systemctl: use STR_IN_SET --- src/systemctl/systemctl.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 5912441168..dc8f61b049 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3121,7 +3121,7 @@ static int logind_check_inhibitors(enum action a) { if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user")) continue; - if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty"))) + if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "tty")) continue; sd_session_get_tty(*s, &tty); @@ -4583,7 +4583,8 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return 0; - } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "IODeviceWeight") || streq(name, "BlockIODeviceWeight"))) { + } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && + STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) { const char *path; uint64_t weight; @@ -4602,8 +4603,9 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte return 0; - } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (cgroup_io_limit_type_from_string(name) >= 0 || - streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) { + } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && + (cgroup_io_limit_type_from_string(name) >= 0 || + STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) { const char *path; uint64_t bandwidth; -- cgit v1.2.3-54-g00ecf From c7bf9d5183deef8c8c01c86de2bc1bcbca7d3bff Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 24 Sep 2016 20:13:28 -0400 Subject: basic/strv: add STRPTR_IN_SET Also some trivial tests for STR_IN_SET and STRPTR_IN_SET. --- src/basic/strv.h | 5 +++++ src/test/test-strv.c | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/basic/strv.h b/src/basic/strv.h index 683ce83a2a..fec2597db0 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -141,6 +141,11 @@ void strv_print(char **l); }) #define STR_IN_SET(x, ...) strv_contains(STRV_MAKE(__VA_ARGS__), x) +#define STRPTR_IN_SET(x, ...) \ + ({ \ + const char* _x = (x); \ + _x && strv_contains(STRV_MAKE(__VA_ARGS__), _x); \ + }) #define FOREACH_STRING(x, ...) \ for (char **_l = ({ \ diff --git a/src/test/test-strv.c b/src/test/test-strv.c index 841a36782f..ce20f2dd5b 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -54,6 +54,25 @@ static void test_specifier_printf(void) { puts(w); } +static void test_str_in_set(void) { + assert_se(STR_IN_SET("x", "x", "y", "z")); + assert_se(!STR_IN_SET("X", "x", "y", "z")); + assert_se(!STR_IN_SET("", "x", "y", "z")); + assert_se(STR_IN_SET("x", "w", "x")); +} + +static void test_strptr_in_set(void) { + assert_se(STRPTR_IN_SET("x", "x", "y", "z")); + assert_se(!STRPTR_IN_SET("X", "x", "y", "z")); + assert_se(!STRPTR_IN_SET("", "x", "y", "z")); + assert_se(STRPTR_IN_SET("x", "w", "x")); + + assert_se(!STRPTR_IN_SET(NULL, "x", "y", "z")); + assert_se(!STRPTR_IN_SET(NULL, "")); + /* strv cannot contain a null, hence the result below */ + assert_se(!STRPTR_IN_SET(NULL, NULL)); +} + static const char* const input_table_multiple[] = { "one", "two", @@ -703,6 +722,8 @@ static void test_strv_fnmatch(void) { int main(int argc, char *argv[]) { test_specifier_printf(); + test_str_in_set(); + test_strptr_in_set(); test_strv_foreach(); test_strv_foreach_backwards(); test_strv_foreach_pair(); -- cgit v1.2.3-54-g00ecf From 1cf03a4f8e5de53ca1ecc8a6dc64cb32ab8de536 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 24 Sep 2016 20:18:02 -0400 Subject: systemctl,networkctl,busctl,backlight: use STRPTR_IN_SET --- src/backlight/backlight.c | 2 +- src/libsystemd/sd-bus/busctl.c | 3 +-- src/network/networkctl.c | 2 +- src/systemctl/systemctl.c | 12 +++++------- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c index 45be135a23..7c59f60d5f 100644 --- a/src/backlight/backlight.c +++ b/src/backlight/backlight.c @@ -167,7 +167,7 @@ static bool validate_device(struct udev *udev, struct udev_device *device) { continue; v = udev_device_get_sysattr_value(other, "type"); - if (!streq_ptr(v, "platform") && !streq_ptr(v, "firmware")) + if (!STRPTR_IN_SET(v, "platform", "firmware")) continue; /* OK, so there's another backlight device, and it's a diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c index eb042e9c81..2c3f591053 100644 --- a/src/libsystemd/sd-bus/busctl.c +++ b/src/libsystemd/sd-bus/busctl.c @@ -2003,8 +2003,7 @@ int main(int argc, char *argv[]) { goto finish; } - if (streq_ptr(argv[optind], "monitor") || - streq_ptr(argv[optind], "capture")) { + if (STRPTR_IN_SET(argv[optind], "monitor", "capture")) { r = sd_bus_set_monitor(bus, true); if (r < 0) { diff --git a/src/network/networkctl.c b/src/network/networkctl.c index d2df9b7560..6f7f41bf7d 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -122,7 +122,7 @@ static void setup_state_to_color(const char *state, const char **on, const char } else if (streq_ptr(state, "configuring")) { *on = ansi_highlight_yellow(); *off = ansi_normal(); - } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) { + } else if (STRPTR_IN_SET(state, "failed", "linger")) { *on = ansi_highlight_red(); *off = ansi_normal(); } else diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index dc8f61b049..02224896ff 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3622,7 +3622,7 @@ static void print_status_info( if (streq_ptr(i->active_state, "failed")) { active_on = ansi_highlight_red(); active_off = ansi_normal(); - } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) { + } else if (STRPTR_IN_SET(i->active_state, "active", "reloading")) { active_on = ansi_highlight_green(); active_off = ansi_normal(); } else @@ -3703,12 +3703,10 @@ static void print_status_info( if (!isempty(i->result) && !streq(i->result, "success")) printf(" (Result: %s)", i->result); - timestamp = (streq_ptr(i->active_state, "active") || - streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp : - (streq_ptr(i->active_state, "inactive") || - streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp : - streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp : - i->active_exit_timestamp; + timestamp = STRPTR_IN_SET(i->active_state, "active", "reloading") ? i->active_enter_timestamp : + STRPTR_IN_SET(i->active_state, "inactive", "failed") ? i->inactive_enter_timestamp : + STRPTR_IN_SET(i->active_state, "activating") ? i->inactive_exit_timestamp : + i->active_exit_timestamp; s1 = format_timestamp_relative(since1, sizeof(since1), timestamp); s2 = format_timestamp(since2, sizeof(since2), timestamp); -- cgit v1.2.3-54-g00ecf From bd5b9f0a12dd9c1947b11534e99c395ddf44caa9 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 24 Sep 2016 20:58:04 -0400 Subject: systemctl: suppress errors with "show" for nonexistent units and properties Show is documented to be program-parseable, and printing the warning about about a non-existent unit, while useful for humans, broke a lot of scripts. Restore previous behaviour of returning success and printing empty or useless stuff for units which do not exist, and printing empty values for properties which do not exists. With SYSTEMD_LOG_LEVEL=debug, hints are printed, but the return value is still 0. This undoes parts of e33a06a and 3dced37b7 and fixes #3856. We might consider adding an explicit switch to fail on missing units/properties (e.g. --ensure-exists or similar), and make -P foobar equivalent to --ensure-exists --property=foobar. --- src/systemctl/systemctl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 02224896ff..5337561664 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -4695,12 +4695,14 @@ static int show_one( return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r)); if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) { - log_error("Unit %s could not be found.", unit); + log_full(streq(verb, "status") ? LOG_ERR : LOG_DEBUG, + "Unit %s could not be found.", unit); if (streq(verb, "status")) return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN; - return -ENOENT; + if (!streq(verb, "show")) + return -ENOENT; } r = sd_bus_message_rewind(reply, true); @@ -4765,10 +4767,11 @@ static int show_one( r = 0; if (show_properties) { char **pp; + int not_found_level = streq(verb, "show") ? LOG_DEBUG : LOG_WARNING; STRV_FOREACH(pp, arg_properties) if (!set_contains(found_properties, *pp)) { - log_warning("Property %s does not exist.", *pp); + log_full(not_found_level, "Property %s does not exist.", *pp); r = -ENXIO; } -- cgit v1.2.3-54-g00ecf From e4662e553ccc7abccb80bf74eb79544c2e26dabe Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 24 Sep 2016 21:46:48 -0400 Subject: journal-remote: fix error format string Bug introduced in 1b4cd64683. --- src/journal-remote/journal-gatewayd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index 54f42b8bf3..7325adee8f 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -782,11 +782,11 @@ static int request_handler_machine( r = sd_journal_get_usage(m->journal, &usage); if (r < 0) - return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s"); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %m"); r = sd_journal_get_cutoff_realtime_usec(m->journal, &cutoff_from, &cutoff_to); if (r < 0) - return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s"); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %m"); if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL) == -ENOENT) (void) parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL); -- cgit v1.2.3-54-g00ecf From 72246c2a654ead7f7ee6e7799161e2e46dc0b84b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 19:01:14 +0200 Subject: core: enforce seccomp for secondary archs too, for all rules Let's make sure that all our rules apply to all archs the local kernel supports. --- src/core/execute.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/core/execute.c b/src/core/execute.c index 2026137721..ee734e8445 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1273,6 +1273,10 @@ static int apply_memory_deny_write_execute(const Unit* u, const ExecContext *c) if (!seccomp) return -ENOMEM; + r = seccomp_add_secondary_archs(seccomp); + if (r < 0) + goto finish; + r = seccomp_rule_add( seccomp, SCMP_ACT_ERRNO(EPERM), @@ -1322,6 +1326,10 @@ static int apply_restrict_realtime(const Unit* u, const ExecContext *c) { if (!seccomp) return -ENOMEM; + r = seccomp_add_secondary_archs(seccomp); + if (r < 0) + goto finish; + /* Determine the highest policy constant we want to allow */ for (i = 0; i < ELEMENTSOF(permitted_policies); i++) if (permitted_policies[i] > max_policy) -- cgit v1.2.3-54-g00ecf From 59eeb84ba65483c5543d1bc840c2ac75642ef638 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Aug 2016 18:43:59 +0200 Subject: core: add two new service settings ProtectKernelTunables= and ProtectControlGroups= If enabled, these will block write access to /sys, /proc/sys and /proc/sys/fs/cgroup. --- man/systemd.exec.xml | 20 +++++++ src/core/dbus-execute.c | 9 ++- src/core/execute.c | 100 ++++++++++++++++++++++++++++++---- src/core/execute.h | 2 + src/core/load-fragment-gperf.gperf.m4 | 2 + src/core/namespace.c | 36 ++++++++++-- src/core/namespace.h | 2 + src/shared/bus-unit-util.c | 2 +- src/test/test-ns.c | 2 + 9 files changed, 159 insertions(+), 16 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index bcedebd5bb..07128b489e 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1059,6 +1059,26 @@ Defaults to off. + + ProtectKernelTunables= + + Takes a boolean argument. If true, kernel variables accessible through + /proc/sys and /sys will be made read-only to all processes of the + unit. Usually, tunable kernel variables should only be written at boot-time, with the + sysctl.d5 mechanism. Almost + no services need to write to these at runtime; it is hence recommended to turn this on for most + services. Defaults to off. + + + + ProtectControlGroups= + + Takes a boolean argument. If true, the Linux Control Groups ("cgroups") hierarchies accessible + through /sys/fs/cgroup will be made read-only to all processes of the unit. Except for + container managers no services should require write access to the control groups hierarchies; it is hence + recommended to turn this on for most services. Defaults to off. + + MountFlags= diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 7e33a2d201..eec4500c8c 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -707,6 +707,8 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_tunables), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST), @@ -1072,7 +1074,8 @@ int bus_exec_context_set_transient_property( "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute", - "RestrictRealtime", "DynamicUser", "RemoveIPC")) { + "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables", + "ProtectControlGroups")) { int b; r = sd_bus_message_read(message, "b", &b); @@ -1106,6 +1109,10 @@ int bus_exec_context_set_transient_property( c->dynamic_user = b; else if (streq(name, "RemoveIPC")) c->remove_ipc = b; + else if (streq(name, "ProtectKernelTunables")) + c->protect_kernel_tunables = b; + else if (streq(name, "ProtectControlGroups")) + c->protect_control_groups = b; unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, yes_no(b)); } diff --git a/src/core/execute.c b/src/core/execute.c index ee734e8445..609b69a859 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1383,6 +1383,45 @@ finish: return r; } +static int apply_protect_sysctl(Unit *u, const ExecContext *c) { + scmp_filter_ctx *seccomp; + int r; + + assert(c); + + /* Turn off the legacy sysctl() system call. Many distributions turn this off while building the kernel, but + * let's protect even those systems where this is left on in the kernel. */ + + if (skip_seccomp_unavailable(u, "ProtectKernelTunables=")) + return 0; + + seccomp = seccomp_init(SCMP_ACT_ALLOW); + if (!seccomp) + return -ENOMEM; + + r = seccomp_add_secondary_archs(seccomp); + if (r < 0) + goto finish; + + r = seccomp_rule_add( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(_sysctl), + 0); + if (r < 0) + goto finish; + + r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); + if (r < 0) + goto finish; + + r = seccomp_load(seccomp); + +finish: + seccomp_release(seccomp); + return r; +} + #endif static void do_idle_pipe_dance(int idle_pipe[4]) { @@ -1589,7 +1628,9 @@ static bool exec_needs_mount_namespace( if (context->private_devices || context->protect_system != PROTECT_SYSTEM_NO || - context->protect_home != PROTECT_HOME_NO) + context->protect_home != PROTECT_HOME_NO || + context->protect_kernel_tunables || + context->protect_control_groups) return true; return false; @@ -1804,6 +1845,37 @@ static int close_remaining_fds( return close_all_fds(dont_close, n_dont_close); } +static bool context_has_address_families(const ExecContext *c) { + assert(c); + + return c->address_families_whitelist || + !set_isempty(c->address_families); +} + +static bool context_has_syscall_filters(const ExecContext *c) { + assert(c); + + return c->syscall_whitelist || + !set_isempty(c->syscall_filter) || + !set_isempty(c->syscall_archs); +} + +static bool context_has_no_new_privileges(const ExecContext *c) { + assert(c); + + if (c->no_new_privileges) + return true; + + if (have_effective_cap(CAP_SYS_ADMIN)) /* if we are privileged, we don't need NNP */ + return false; + + return context_has_address_families(c) || /* we need NNP if we have any form of seccomp and are unprivileged */ + c->memory_deny_write_execute || + c->restrict_realtime || + c->protect_kernel_tunables || + context_has_syscall_filters(c); +} + static int send_user_lookup( Unit *unit, int user_lookup_fd, @@ -2255,6 +2327,8 @@ static int exec_child( tmp, var, context->private_devices, + context->protect_kernel_tunables, + context->protect_control_groups, context->protect_home, context->protect_system, context->mount_flags); @@ -2343,11 +2417,6 @@ static int exec_child( if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { - bool use_address_families = context->address_families_whitelist || - !set_isempty(context->address_families); - bool use_syscall_filter = context->syscall_whitelist || - !set_isempty(context->syscall_filter) || - !set_isempty(context->syscall_archs); int secure_bits = context->secure_bits; for (i = 0; i < _RLIMIT_MAX; i++) { @@ -2424,15 +2493,14 @@ static int exec_child( return -errno; } - if (context->no_new_privileges || - (!have_effective_cap(CAP_SYS_ADMIN) && (use_address_families || context->memory_deny_write_execute || context->restrict_realtime || use_syscall_filter))) + if (context_has_no_new_privileges(context)) if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { *exit_status = EXIT_NO_NEW_PRIVILEGES; return -errno; } #ifdef HAVE_SECCOMP - if (use_address_families) { + if (context_has_address_families(context)) { r = apply_address_families(unit, context); if (r < 0) { *exit_status = EXIT_ADDRESS_FAMILIES; @@ -2456,7 +2524,15 @@ static int exec_child( } } - if (use_syscall_filter) { + if (context->protect_kernel_tunables) { + r = apply_protect_sysctl(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return r; + } + } + + if (context_has_syscall_filters(context)) { r = apply_seccomp(unit, context); if (r < 0) { *exit_status = EXIT_SECCOMP; @@ -2888,6 +2964,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { "%sNonBlocking: %s\n" "%sPrivateTmp: %s\n" "%sPrivateDevices: %s\n" + "%sProtectKernelTunables: %s\n" + "%sProtectControlGroups: %s\n" "%sPrivateNetwork: %s\n" "%sPrivateUsers: %s\n" "%sProtectHome: %s\n" @@ -2901,6 +2979,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { prefix, yes_no(c->non_blocking), prefix, yes_no(c->private_tmp), prefix, yes_no(c->private_devices), + prefix, yes_no(c->protect_kernel_tunables), + prefix, yes_no(c->protect_control_groups), prefix, yes_no(c->private_network), prefix, yes_no(c->private_users), prefix, protect_home_to_string(c->protect_home), diff --git a/src/core/execute.h b/src/core/execute.h index 6082c42aba..449180c903 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -174,6 +174,8 @@ struct ExecContext { bool private_users; ProtectSystem protect_system; ProtectHome protect_home; + bool protect_kernel_tunables; + bool protect_control_groups; bool no_new_privileges; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 2e6c965aec..c49c1d6732 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -89,6 +89,8 @@ $1.ReadOnlyPaths, config_parse_namespace_path_strv, 0, $1.InaccessiblePaths, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_paths) $1.PrivateTmp, config_parse_bool, 0, offsetof($1, exec_context.private_tmp) $1.PrivateDevices, config_parse_bool, 0, offsetof($1, exec_context.private_devices) +$1.ProtectKernelTunables, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_tunables) +$1.ProtectControlGroups, config_parse_bool, 0, offsetof($1, exec_context.protect_control_groups) $1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network) $1.PrivateUsers, config_parse_bool, 0, offsetof($1, exec_context.private_users) $1.ProtectSystem, config_parse_protect_system, 0, offsetof($1, exec_context) diff --git a/src/core/namespace.c b/src/core/namespace.c index 52a2505d94..f2768aeb28 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -53,7 +53,7 @@ typedef enum MountMode { PRIVATE_TMP, PRIVATE_VAR_TMP, PRIVATE_DEV, - READWRITE + READWRITE, } MountMode; typedef struct BindMount { @@ -366,6 +366,8 @@ int setup_namespace( const char* tmp_dir, const char* var_tmp_dir, bool private_dev, + bool protect_sysctl, + bool protect_cgroups, ProtectHome protect_home, ProtectSystem protect_system, unsigned long mount_flags) { @@ -385,6 +387,8 @@ int setup_namespace( strv_length(read_only_paths) + strv_length(inaccessible_paths) + private_dev + + (protect_sysctl ? 3 : 0) + + (protect_cgroups != protect_sysctl) + (protect_home != PROTECT_HOME_NO ? 3 : 0) + (protect_system != PROTECT_SYSTEM_NO ? 2 : 0) + (protect_system == PROTECT_SYSTEM_FULL ? 1 : 0); @@ -421,6 +425,27 @@ int setup_namespace( m++; } + if (protect_sysctl) { + m->path = prefix_roota(root_directory, "/proc/sys"); + m->mode = READONLY; + m++; + + m->path = prefix_roota(root_directory, "/proc/sysrq-trigger"); + m->mode = READONLY; + m->ignore = true; /* Not always compiled into the kernel */ + m++; + + m->path = prefix_roota(root_directory, "/sys"); + m->mode = READONLY; + m++; + } + + if (protect_cgroups != protect_sysctl) { + m->path = prefix_roota(root_directory, "/sys/fs/cgroup"); + m->mode = protect_cgroups ? READONLY : READWRITE; + m++; + } + if (protect_home != PROTECT_HOME_NO) { const char *home_dir, *run_user_dir, *root_dir; @@ -505,9 +530,12 @@ int setup_namespace( fail: if (n > 0) { - for (m = mounts; m < mounts + n; ++m) - if (m->done) - (void) umount2(m->path, MNT_DETACH); + for (m = mounts; m < mounts + n; ++m) { + if (!m->done) + continue; + + (void) umount2(m->path, MNT_DETACH); + } } return r; diff --git a/src/core/namespace.h b/src/core/namespace.h index 1aedf5f208..3845336287 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -46,6 +46,8 @@ int setup_namespace(const char *chroot, const char *tmp_dir, const char *var_tmp_dir, bool private_dev, + bool protect_sysctl, + bool protect_cgroups, ProtectHome protect_home, ProtectSystem protect_system, unsigned long mount_flags); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index feb4a06737..c6bd2f145c 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -204,7 +204,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges", "SyslogLevelPrefix", "Delegate", "RemainAfterElapse", "MemoryDenyWriteExecute", - "RestrictRealtime", "DynamicUser", "RemoveIPC")) { + "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables", "ProtectControlGroups")) { r = parse_boolean(eq); if (r < 0) diff --git a/src/test/test-ns.c b/src/test/test-ns.c index 9248f2987c..05f243c75c 100644 --- a/src/test/test-ns.c +++ b/src/test/test-ns.c @@ -69,6 +69,8 @@ int main(int argc, char *argv[]) { tmp_dir, var_tmp_dir, true, + true, + true, PROTECT_HOME_NO, PROTECT_SYSTEM_NO, 0); -- cgit v1.2.3-54-g00ecf From fe3c2583bee339b6744872dc1897e6486d5bd7e0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Aug 2016 23:17:42 +0200 Subject: namespace: make sure InaccessibleDirectories= masks all mounts further down If a dir is marked to be inaccessible then everything below it should be masked by it. --- src/core/namespace.c | 44 ++++++++++++++++++++++++++++++++++++++++---- src/test/test-ns.c | 4 +++- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index f2768aeb28..102fe576f3 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -116,16 +116,47 @@ static void drop_duplicates(BindMount *m, unsigned *n) { assert(m); assert(n); + /* Drops duplicate entries. Expects that the array is properly ordered already. */ + for (f = m, t = m, previous = NULL; f < m+*n; f++) { - /* The first one wins */ - if (previous && path_equal(f->path, previous->path)) + /* The first one wins (which is the one with the more restrictive mode), see mount_path_compare() + * above. */ + if (previous && path_equal(f->path, previous->path)) { + log_debug("%s is duplicate.", f->path); continue; + } *t = *f; - previous = t; + t++; + } + + *n = t - m; +} + +static void drop_inaccessible(BindMount *m, unsigned *n) { + BindMount *f, *t; + const char *clear = NULL; + + assert(m); + assert(n); + + /* Drops all entries obstructed by another entry further up the tree. Expects that the array is properly + * ordered already. */ + + for (f = m, t = m; f < m+*n; f++) { + + /* If we found a path set for INACCESSIBLE earlier, and this entry has it as prefix we should drop + * it, as inaccessible paths really should drop the entire subtree. */ + if (clear && path_startswith(f->path, clear)) { + log_debug("%s is masked by %s.", f->path, clear); + continue; + } + clear = f->mode == INACCESSIBLE ? f->path : NULL; + + *t = *f; t++; } @@ -282,6 +313,8 @@ static int apply_mount( assert(m); + log_debug("Applying namespace mount on %s", m->path); + switch (m->mode) { case INACCESSIBLE: @@ -289,7 +322,7 @@ static int apply_mount( /* First, get rid of everything that is below if there * is anything... Then, overmount it with an * inaccessible path. */ - umount_recursive(m->path, 0); + (void) umount_recursive(m->path, 0); if (lstat(m->path, &target) < 0) { if (m->ignore && errno == ENOENT) @@ -303,6 +336,7 @@ static int apply_mount( return -ELOOP; } break; + case READONLY: case READWRITE: /* Nothing to mount here, we just later toggle the @@ -480,7 +514,9 @@ int setup_namespace( assert(mounts + n == m); qsort(mounts, n, sizeof(BindMount), mount_path_compare); + drop_duplicates(mounts, &n); + drop_inaccessible(mounts, &n); } if (n > 0 || root_directory) { diff --git a/src/test/test-ns.c b/src/test/test-ns.c index 05f243c75c..03a24620af 100644 --- a/src/test/test-ns.c +++ b/src/test/test-ns.c @@ -26,6 +26,7 @@ int main(int argc, char *argv[]) { const char * const writable[] = { "/home", + "/home/lennart/projects/foobar", /* this should be masked automatically */ NULL }; @@ -42,11 +43,12 @@ int main(int argc, char *argv[]) { }; char *root_directory; char *projects_directory; - int r; char tmp_dir[] = "/tmp/systemd-private-XXXXXX", var_tmp_dir[] = "/var/tmp/systemd-private-XXXXXX"; + log_set_max_level(LOG_DEBUG); + assert_se(mkdtemp(tmp_dir)); assert_se(mkdtemp(var_tmp_dir)); -- cgit v1.2.3-54-g00ecf From 07689d5d2c07ee434437de5e39bf0abaa772818b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Aug 2016 10:12:57 +0200 Subject: execute: split out creation of runtime dirs into its own functions --- src/core/execute.c | 57 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 609b69a859..3877293b4f 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1789,6 +1789,37 @@ static int setup_private_users(uid_t uid, gid_t gid) { return 0; } +static int setup_runtime_directory( + const ExecContext *context, + const ExecParameters *params, + uid_t uid, + gid_t gid) { + + char **rt; + int r; + + assert(context); + assert(params); + + STRV_FOREACH(rt, context->runtime_directory) { + _cleanup_free_ char *p; + + p = strjoin(params->runtime_prefix, "/", *rt, NULL); + if (!p) + return -ENOMEM; + + r = mkdir_p_label(p, context->runtime_directory_mode); + if (r < 0) + return r; + + r = chmod_and_chown(p, context->runtime_directory_mode, uid, gid); + if (r < 0) + return r; + } + + return 0; +} + static void append_socket_pair(int *array, unsigned *n, int pair[2]) { assert(array); assert(n); @@ -2188,28 +2219,10 @@ static int exec_child( } if (!strv_isempty(context->runtime_directory) && params->runtime_prefix) { - char **rt; - - STRV_FOREACH(rt, context->runtime_directory) { - _cleanup_free_ char *p; - - p = strjoin(params->runtime_prefix, "/", *rt, NULL); - if (!p) { - *exit_status = EXIT_RUNTIME_DIRECTORY; - return -ENOMEM; - } - - r = mkdir_p_label(p, context->runtime_directory_mode); - if (r < 0) { - *exit_status = EXIT_RUNTIME_DIRECTORY; - return r; - } - - r = chmod_and_chown(p, context->runtime_directory_mode, uid, gid); - if (r < 0) { - *exit_status = EXIT_RUNTIME_DIRECTORY; - return r; - } + r = setup_runtime_directory(context, params, uid, gid); + if (r < 0) { + *exit_status = EXIT_RUNTIME_DIRECTORY; + return r; } } -- cgit v1.2.3-54-g00ecf From be39ccf3a0d4d15324af1de4d8552a1d65f40808 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Aug 2016 10:24:10 +0200 Subject: execute: move suppression of HOME=/ and SHELL=/bin/nologin into user-util.c This adds a new call get_user_creds_clean(), which is just like get_user_creds() but returns NULL in the home/shell parameters if they contain no useful information. This code previously lived in execute.c, but by generalizing this we can reuse it in run.c. --- src/basic/user-util.c | 32 +++++++++++++++++++++++++++++++- src/basic/user-util.h | 1 + src/core/execute.c | 14 +++----------- src/run/run.c | 18 +++++++++++------- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 122d9a0c7c..0522bce1d1 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -31,14 +31,15 @@ #include #include -#include "missing.h" #include "alloc-util.h" #include "fd-util.h" #include "formats-util.h" #include "macro.h" +#include "missing.h" #include "parse-util.h" #include "path-util.h" #include "string-util.h" +#include "strv.h" #include "user-util.h" #include "utf8.h" @@ -175,6 +176,35 @@ int get_user_creds( return 0; } +int get_user_creds_clean( + const char **username, + uid_t *uid, gid_t *gid, + const char **home, + const char **shell) { + + int r; + + /* Like get_user_creds(), but resets home/shell to NULL if they don't contain anything relevant. */ + + r = get_user_creds(username, uid, gid, home, shell); + if (r < 0) + return r; + + if (shell && + (isempty(*shell) || PATH_IN_SET(*shell, + "/bin/nologin", + "/sbin/nologin", + "/usr/bin/nologin", + "/usr/sbin/nologin"))) + *shell = NULL; + + if (home && + (isempty(*home) || path_equal(*home, "/"))) + *home = NULL; + + return 0; +} + int get_group_creds(const char **groupname, gid_t *gid) { struct group *g; gid_t id; diff --git a/src/basic/user-util.h b/src/basic/user-util.h index f569363811..6c61f63cae 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -40,6 +40,7 @@ char* getlogname_malloc(void); char* getusername_malloc(void); int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell); +int get_user_creds_clean(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell); int get_group_creds(const char **groupname, gid_t *gid); char* uid_to_name(uid_t uid); diff --git a/src/core/execute.c b/src/core/execute.c index 3877293b4f..c7a3ea39e7 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2051,22 +2051,14 @@ static int exec_child( } else { if (context->user) { username = context->user; - r = get_user_creds(&username, &uid, &gid, &home, &shell); + r = get_user_creds_clean(&username, &uid, &gid, &home, &shell); if (r < 0) { *exit_status = EXIT_USER; return r; } - /* Don't set $HOME or $SHELL if they are are not particularly enlightening anyway. */ - if (isempty(home) || path_equal(home, "/")) - home = NULL; - - if (isempty(shell) || PATH_IN_SET(shell, - "/bin/nologin", - "/sbin/nologin", - "/usr/bin/nologin", - "/usr/sbin/nologin")) - shell = NULL; + /* Note that we don't set $HOME or $SHELL if they are are not particularly enlightening anyway + * (i.e. are "/" or "/bin/nologin"). */ } if (context->group) { diff --git a/src/run/run.c b/src/run/run.c index 2dd229868c..81b53fdfab 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -1168,17 +1168,21 @@ static int start_transient_scope( uid_t uid; gid_t gid; - r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell); + r = get_user_creds_clean(&arg_exec_user, &uid, &gid, &home, &shell); if (r < 0) return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user); - r = strv_extendf(&user_env, "HOME=%s", home); - if (r < 0) - return log_oom(); + if (home) { + r = strv_extendf(&user_env, "HOME=%s", home); + if (r < 0) + return log_oom(); + } - r = strv_extendf(&user_env, "SHELL=%s", shell); - if (r < 0) - return log_oom(); + if (shell) { + r = strv_extendf(&user_env, "SHELL=%s", shell); + if (r < 0) + return log_oom(); + } r = strv_extendf(&user_env, "USER=%s", arg_exec_user); if (r < 0) -- cgit v1.2.3-54-g00ecf From 3fbe8dbe41ad662d7cae0525f6fd62a66d2c5ec5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Aug 2016 10:42:38 +0200 Subject: execute: if RuntimeDirectory= is set, it should be writable Implicitly make all dirs set with RuntimeDirectory= writable, as the concept otherwise makes no sense. --- src/core/execute.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index c7a3ea39e7..20e74ec8a6 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1820,6 +1820,44 @@ static int setup_runtime_directory( return 0; } +static int compile_read_write_paths( + const ExecContext *context, + const ExecParameters *params, + char ***ret) { + + _cleanup_strv_free_ char **l = NULL; + char **rt; + + /* Compile the list of writable paths. This is the combination of the explicitly configured paths, plus all + * runtime directories. */ + + if (strv_isempty(context->read_write_paths) && + strv_isempty(context->runtime_directory)) { + *ret = NULL; /* NOP if neither is set */ + return 0; + } + + l = strv_copy(context->read_write_paths); + if (!l) + return -ENOMEM; + + STRV_FOREACH(rt, context->runtime_directory) { + char *s; + + s = strjoin(params->runtime_prefix, "/", *rt, NULL); + if (!s) + return -ENOMEM; + + if (strv_consume(&l, s) < 0) + return -ENOMEM; + } + + *ret = l; + l = NULL; + + return 0; +} + static void append_socket_pair(int *array, unsigned *n, int pair[2]) { assert(array); assert(n); @@ -2307,8 +2345,8 @@ static int exec_child( } needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime); - if (needs_mount_namespace) { + _cleanup_free_ char **rw = NULL; char *tmp = NULL, *var = NULL; /* The runtime struct only contains the parent @@ -2324,9 +2362,15 @@ static int exec_child( var = strjoina(runtime->var_tmp_dir, "/tmp"); } + r = compile_read_write_paths(context, params, &rw); + if (r < 0) { + *exit_status = EXIT_NAMESPACE; + return r; + } + r = setup_namespace( (params->flags & EXEC_APPLY_CHROOT) ? context->root_directory : NULL, - context->read_write_paths, + rw, context->read_only_paths, context->inaccessible_paths, tmp, -- cgit v1.2.3-54-g00ecf From 6ee1a919cf9013a695da2a01ae67327b996a6ef6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Aug 2016 10:44:09 +0200 Subject: namespace: simplify mount_path_compare() a bit --- src/core/namespace.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index 102fe576f3..74201caa10 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -93,21 +93,19 @@ static int mount_path_compare(const void *a, const void *b) { const BindMount *p = a, *q = b; int d; + /* If the paths are not equal, then order prefixes first */ d = path_compare(p->path, q->path); + if (d != 0) + return d; - if (d == 0) { - /* If the paths are equal, check the mode */ - if (p->mode < q->mode) - return -1; - - if (p->mode > q->mode) - return 1; + /* If the paths are equal, check the mode */ + if (p->mode < q->mode) + return -1; - return 0; - } + if (p->mode > q->mode) + return 1; - /* If the paths are not equal, then order prefixes first */ - return d; + return 0; } static void drop_duplicates(BindMount *m, unsigned *n) { -- cgit v1.2.3-54-g00ecf From 7648a565d14dfb5516d93bacf0d87de2de5b5d91 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Aug 2016 11:29:32 +0200 Subject: namespace: when enforcing fs namespace restrictions suppress redundant mounts If /foo is marked to be read-only, and /foo/bar too, then the latter may be suppressed as it has no effect. --- src/core/namespace.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/core/namespace.c b/src/core/namespace.c index 74201caa10..72f850b2f2 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -161,6 +161,44 @@ static void drop_inaccessible(BindMount *m, unsigned *n) { *n = t - m; } +static void drop_nop(BindMount *m, unsigned *n) { + BindMount *f, *t; + + assert(m); + assert(n); + + /* Drops all entries which have an immediate parent that has the same type, as they are redundant. Assumes the + * list is ordered by prefixes. */ + + for (f = m, t = m; f < m+*n; f++) { + + /* Only suppress such subtrees for READONLY and READWRITE entries */ + if (IN_SET(f->mode, READONLY, READWRITE)) { + BindMount *p; + bool found = false; + + /* Now let's find the first parent of the entry we are looking at. */ + for (p = t-1; p >= m; p--) { + if (path_startswith(f->path, p->path)) { + found = true; + break; + } + } + + /* We found it, let's see if it's the same mode, if so, we can drop this entry */ + if (found && p->mode == f->mode) { + log_debug("%s is redundant by %s", f->path, p->path); + continue; + } + } + + *t = *f; + t++; + } + + *n = t - m; +} + static int mount_dev(BindMount *m) { static const char devnodes[] = "/dev/null\0" @@ -515,6 +553,7 @@ int setup_namespace( drop_duplicates(mounts, &n); drop_inaccessible(mounts, &n); + drop_nop(mounts, &n); } if (n > 0 || root_directory) { -- cgit v1.2.3-54-g00ecf From 6b7c9f8bce4679c89f3b89cacfd4932c0aeadad4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 25 Sep 2016 10:40:51 +0200 Subject: namespace: rework how ReadWritePaths= is applied Previously, if ReadWritePaths= was nested inside a ReadOnlyPaths= specification, then we'd first recursively apply the ReadOnlyPaths= paths, and make everything below read-only, only in order to then flip the read-only bit again for the subdirs listed in ReadWritePaths= below it. This is not only ugly (as for the dirs in question we first turn on the RO bit, only to turn it off again immediately after), but also problematic in containers, where a container manager might have marked a set of dirs read-only and this code will undo this is ReadWritePaths= is set for any. With this patch behaviour in this regard is altered: ReadOnlyPaths= will not be applied to the children listed in ReadWritePaths= in the first place, so that we do not need to turn off the RO bit for those after all. This means that ReadWritePaths=/ReadOnlyPaths= may only be used to turn on the RO bit, but never to turn it off again. Or to say this differently: if some dirs are marked read-only via some external tool, then ReadWritePaths= will not undo it. This is not only the safer option, but also more in-line with what the man page currently claims: "Entries (files or directories) listed in ReadWritePaths= are accessible from within the namespace with the same access rights as from outside." To implement this change bind_remount_recursive() gained a new "blacklist" string list parameter, which when passed may contain subdirs that shall be excluded from the read-only mounting. A number of functions are updated to add more debug logging to make this more digestable. --- src/basic/mount-util.c | 71 ++++++++++++++++++++++++++++++++--------------- src/basic/mount-util.h | 2 +- src/core/namespace.c | 66 ++++++++++++++++++++++++++++--------------- src/nspawn/nspawn-mount.c | 6 ++-- src/nspawn/nspawn.c | 2 +- 5 files changed, 96 insertions(+), 51 deletions(-) diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c index bfa04394fe..b9affb4e70 100644 --- a/src/basic/mount-util.c +++ b/src/basic/mount-util.c @@ -36,6 +36,7 @@ #include "set.h" #include "stdio-util.h" #include "string-util.h" +#include "strv.h" static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) { char path[strlen("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)]; @@ -287,10 +288,12 @@ int umount_recursive(const char *prefix, int flags) { continue; if (umount2(p, flags) < 0) { - r = -errno; + r = log_debug_errno(errno, "Failed to umount %s: %m", p); continue; } + log_debug("Successfully unmounted %s", p); + again = true; n++; @@ -311,24 +314,21 @@ static int get_mount_flags(const char *path, unsigned long *flags) { return 0; } -int bind_remount_recursive(const char *prefix, bool ro) { +int bind_remount_recursive(const char *prefix, bool ro, char **blacklist) { _cleanup_set_free_free_ Set *done = NULL; _cleanup_free_ char *cleaned = NULL; int r; - /* Recursively remount a directory (and all its submounts) - * read-only or read-write. If the directory is already - * mounted, we reuse the mount and simply mark it - * MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write - * operation). If it isn't we first make it one. Afterwards we - * apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to all - * submounts we can access, too. When mounts are stacked on - * the same mount point we only care for each individual - * "top-level" mount on each point, as we cannot - * influence/access the underlying mounts anyway. We do not - * have any effect on future submounts that might get - * propagated, they migt be writable. This includes future - * submounts that have been triggered via autofs. */ + /* Recursively remount a directory (and all its submounts) read-only or read-write. If the directory is already + * mounted, we reuse the mount and simply mark it MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write + * operation). If it isn't we first make it one. Afterwards we apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to + * all submounts we can access, too. When mounts are stacked on the same mount point we only care for each + * individual "top-level" mount on each point, as we cannot influence/access the underlying mounts anyway. We + * do not have any effect on future submounts that might get propagated, they migt be writable. This includes + * future submounts that have been triggered via autofs. + * + * If the "blacklist" parameter is specified it may contain a list of subtrees to exclude from the + * remount operation. Note that we'll ignore the blacklist for the top-level path. */ cleaned = strdup(prefix); if (!cleaned) @@ -385,6 +385,33 @@ int bind_remount_recursive(const char *prefix, bool ro) { if (r < 0) return r; + if (!path_startswith(p, cleaned)) + continue; + + /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount we shall + * operate on. */ + if (!path_equal(cleaned, p)) { + bool blacklisted = false; + char **i; + + STRV_FOREACH(i, blacklist) { + + if (path_equal(*i, cleaned)) + continue; + + if (!path_startswith(*i, cleaned)) + continue; + + if (path_startswith(p, *i)) { + blacklisted = true; + log_debug("Not remounting %s, because blacklisted by %s, called for %s", p, *i, cleaned); + break; + } + } + if (blacklisted) + continue; + } + /* Let's ignore autofs mounts. If they aren't * triggered yet, we want to avoid triggering * them, as we don't make any guarantees for @@ -396,12 +423,9 @@ int bind_remount_recursive(const char *prefix, bool ro) { continue; } - if (path_startswith(p, cleaned) && - !set_contains(done, p)) { - + if (!set_contains(done, p)) { r = set_consume(todo, p); p = NULL; - if (r == -EEXIST) continue; if (r < 0) @@ -418,8 +442,7 @@ int bind_remount_recursive(const char *prefix, bool ro) { if (!set_contains(done, cleaned) && !set_contains(todo, cleaned)) { - /* The prefix directory itself is not yet a - * mount, make it one. */ + /* The prefix directory itself is not yet a mount, make it one. */ if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0) return -errno; @@ -430,6 +453,8 @@ int bind_remount_recursive(const char *prefix, bool ro) { if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) return -errno; + log_debug("Made top-level directory %s a mount point.", prefix); + x = strdup(cleaned); if (!x) return -ENOMEM; @@ -447,8 +472,7 @@ int bind_remount_recursive(const char *prefix, bool ro) { if (r < 0) return r; - /* Deal with mount points that are obstructed by a - * later mount */ + /* Deal with mount points that are obstructed by a later mount */ r = path_is_mount_point(x, 0); if (r == -ENOENT || r == 0) continue; @@ -463,6 +487,7 @@ int bind_remount_recursive(const char *prefix, bool ro) { if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) return -errno; + log_debug("Remounted %s read-only.", x); } } } diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h index f46989ebb3..74730de663 100644 --- a/src/basic/mount-util.h +++ b/src/basic/mount-util.h @@ -35,7 +35,7 @@ int path_is_mount_point(const char *path, int flags); int repeat_unmount(const char *path, int flags); int umount_recursive(const char *target, int flags); -int bind_remount_recursive(const char *prefix, bool ro); +int bind_remount_recursive(const char *prefix, bool ro, char **blacklist); int mount_move_root(const char *path); diff --git a/src/core/namespace.c b/src/core/namespace.c index 72f850b2f2..b0dab9459e 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -375,9 +375,19 @@ static int apply_mount( case READONLY: case READWRITE: - /* Nothing to mount here, we just later toggle the - * MS_RDONLY bit for the mount point */ - return 0; + + r = path_is_mount_point(m->path, 0); + if (r < 0) { + if (m->ignore && errno == ENOENT) + return 0; + return log_debug_errno(r, "Failed to determine whether %s is already a mount point: %m", m->path); + } + if (r > 0) /* Nothing to do here, it is already a mount. We just later toggle the MS_RDONLY bit for the mount point if needed. */ + return 0; + + /* This isn't a mount point yet, let's make it one. */ + what = m->path; + break; case PRIVATE_TMP: what = tmp_dir; @@ -396,31 +406,33 @@ static int apply_mount( assert(what); - r = mount(what, m->path, NULL, MS_BIND|MS_REC, NULL); - if (r >= 0) { - log_debug("Successfully mounted %s to %s", what, m->path); - return r; - } else { + if (mount(what, m->path, NULL, MS_BIND|MS_REC, NULL) < 0) { if (m->ignore && errno == ENOENT) return 0; + return log_debug_errno(errno, "Failed to mount %s to %s: %m", what, m->path); } + + log_debug("Successfully mounted %s to %s", what, m->path); + return 0; } -static int make_read_only(BindMount *m) { - int r; +static int make_read_only(BindMount *m, char **blacklist) { + int r = 0; assert(m); if (IN_SET(m->mode, INACCESSIBLE, READONLY)) - r = bind_remount_recursive(m->path, true); - else if (IN_SET(m->mode, READWRITE, PRIVATE_TMP, PRIVATE_VAR_TMP, PRIVATE_DEV)) { - r = bind_remount_recursive(m->path, false); - if (r == 0 && m->mode == PRIVATE_DEV) /* can be readonly but the submounts can't*/ - if (mount(NULL, m->path, NULL, MS_REMOUNT|DEV_MOUNT_OPTIONS|MS_RDONLY, NULL) < 0) - r = -errno; + r = bind_remount_recursive(m->path, true, blacklist); + else if (m->mode == PRIVATE_DEV) { /* Can be readonly but the submounts can't*/ + if (mount(NULL, m->path, NULL, MS_REMOUNT|DEV_MOUNT_OPTIONS|MS_RDONLY, NULL) < 0) + r = -errno; } else - r = 0; + return 0; + + /* Not that we only turn on the MS_RDONLY flag here, we never turn it off. Something that was marked read-only + * already stays this way. This improves compatibility with container managers, where we won't attempt to undo + * read-only mounts already applied. */ if (m->ignore && r == -ENOENT) return 0; @@ -570,14 +582,25 @@ int setup_namespace( } if (n > 0) { + char **blacklist; + unsigned j; + + /* First round, add in all special mounts we need */ for (m = mounts; m < mounts + n; ++m) { r = apply_mount(m, tmp_dir, var_tmp_dir); if (r < 0) goto fail; } + /* Create a blacklist we can pass to bind_mount_recursive() */ + blacklist = newa(char*, n+1); + for (j = 0; j < n; j++) + blacklist[j] = (char*) mounts[j].path; + blacklist[j] = NULL; + + /* Second round, flip the ro bits if necessary. */ for (m = mounts; m < mounts + n; ++m) { - r = make_read_only(m); + r = make_read_only(m, blacklist); if (r < 0) goto fail; } @@ -586,9 +609,7 @@ int setup_namespace( if (root_directory) { /* MS_MOVE does not work on MS_SHARED so the remount MS_SHARED will be done later */ r = mount_move_root(root_directory); - - /* at this point, we cannot rollback */ - if (r < 0) + if (r < 0) /* at this point, we cannot rollback */ return r; } @@ -596,8 +617,7 @@ int setup_namespace( * reestablish propagation from our side to the host, since * what's disconnected is disconnected. */ if (mount(NULL, "/", NULL, mount_flags | MS_REC, NULL) < 0) - /* at this point, we cannot rollback */ - return -errno; + return -errno; /* at this point, we cannot rollback */ return 0; diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 295b75341f..8457357003 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -476,7 +476,7 @@ static int mount_bind(const char *dest, CustomMount *m) { return log_error_errno(errno, "mount(%s) failed: %m", where); if (m->read_only) { - r = bind_remount_recursive(where, true); + r = bind_remount_recursive(where, true, NULL); if (r < 0) return log_error_errno(r, "Read-only bind mount failed: %m"); } @@ -990,7 +990,7 @@ int setup_volatile_state( /* --volatile=state means we simply overmount /var with a tmpfs, and the rest read-only. */ - r = bind_remount_recursive(directory, true); + r = bind_remount_recursive(directory, true, NULL); if (r < 0) return log_error_errno(r, "Failed to remount %s read-only: %m", directory); @@ -1065,7 +1065,7 @@ int setup_volatile( bind_mounted = true; - r = bind_remount_recursive(t, true); + r = bind_remount_recursive(t, true, NULL); if (r < 0) { log_error_errno(r, "Failed to remount %s read-only: %m", t); goto fail; diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 0d61d34ebf..1f3e1f2dac 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3019,7 +3019,7 @@ static int outer_child( return r; if (arg_read_only) { - r = bind_remount_recursive(directory, true); + r = bind_remount_recursive(directory, true, NULL); if (r < 0) return log_error_errno(r, "Failed to make tree read-only: %m"); } -- cgit v1.2.3-54-g00ecf From 160cfdbed3eb23b6bc3c17613685b756f23be4a1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Aug 2016 15:51:37 +0200 Subject: namespace: add some debug logging when enforcing InaccessiblePaths= --- src/core/namespace.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index b0dab9459e..e08d7459c5 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -345,7 +345,6 @@ static int apply_mount( const char *what; int r; - struct stat target; assert(m); @@ -353,7 +352,8 @@ static int apply_mount( switch (m->mode) { - case INACCESSIBLE: + case INACCESSIBLE: { + struct stat target; /* First, get rid of everything that is below if there * is anything... Then, overmount it with an @@ -363,7 +363,7 @@ static int apply_mount( if (lstat(m->path, &target) < 0) { if (m->ignore && errno == ENOENT) return 0; - return -errno; + return log_debug_errno(errno, "Failed to lstat() %s to determine what to mount over it: %m", m->path); } what = mode_to_inaccessible_node(target.st_mode); @@ -372,6 +372,7 @@ static int apply_mount( return -ELOOP; } break; + } case READONLY: case READWRITE: -- cgit v1.2.3-54-g00ecf From 3f815163ff8fdcdbd329680580df36f94e15325d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Aug 2016 15:57:21 +0200 Subject: core: introduce ProtectSystem=strict Let's tighten our sandbox a bit more: with this change ProtectSystem= gains a new setting "strict". If set, the entire directory tree of the system is mounted read-only, but the API file systems /proc, /dev, /sys are excluded (they may be managed with PrivateDevices= and ProtectKernelTunables=). Also, /home and /root are excluded as those are left for ProtectHome= to manage. In this mode, all "real" file systems (i.e. non-API file systems) are mounted read-only, and specific directories may only be excluded via ReadWriteDirectories=, thus implementing an effective whitelist instead of blacklist of writable directories. While we are at, also add /efi to the list of paths always affected by ProtectSystem=. This is a follow-up for b52a109ad38cd37b660ccd5394ff5c171a5e5355 which added /efi as alternative for /boot. Our namespacing logic should respect that too. --- man/systemd.exec.xml | 33 ++++++++++++++++--------------- src/core/namespace.c | 56 +++++++++++++++++++++++++++++++++++++++++++--------- src/core/namespace.h | 1 + 3 files changed, 65 insertions(+), 25 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 07128b489e..1b672fe0c9 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1020,22 +1020,23 @@ ProtectSystem= - Takes a boolean argument or - full. If true, mounts the - /usr and /boot - directories read-only for processes invoked by this unit. If - set to full, the /etc - directory is mounted read-only, too. This setting ensures that - any modification of the vendor-supplied operating system (and - optionally its configuration) is prohibited for the service. - It is recommended to enable this setting for all long-running - services, unless they are involved with system updates or need - to modify the operating system in other ways. Note however - that processes retaining the CAP_SYS_ADMIN capability can undo - the effect of this setting. This setting is hence particularly - useful for daemons which have this capability removed, for - example with CapabilityBoundingSet=. - Defaults to off. + Takes a boolean argument or the special values full or + strict. If true, mounts the /usr and /boot + directories read-only for processes invoked by this unit. If set to full, the + /etc directory is mounted read-only, too. If set to strict the entire + file system hierarchy is mounted read-only, except for the API file system subtrees /dev, + /proc and /sys (protect these directories using + PrivateDevices=, ProtectKernelTunables=, + ProtectControlGroups=). This setting ensures that any modification of the vendor-supplied + operating system (and optionally its configuration, and local mounts) is prohibited for the service. It is + recommended to enable this setting for all long-running services, unless they are involved with system updates + or need to modify the operating system in other ways. If this option is used, + ReadWritePaths= may be used to exclude specific directories from being made read-only. Note + that processes retaining the CAP_SYS_ADMIN capability (and with no system call filter that + prohibits mount-related system calls applied) can undo the effect of this setting. This setting is hence + particularly useful for daemons which have this either the @mount set filtered using + SystemCallFilter=, or have the CAP_SYS_ADMIN capability removed, for + example with CapabilityBoundingSet=. Defaults to off. diff --git a/src/core/namespace.c b/src/core/namespace.c index e08d7459c5..498cd139bf 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -472,9 +472,11 @@ int setup_namespace( private_dev + (protect_sysctl ? 3 : 0) + (protect_cgroups != protect_sysctl) + - (protect_home != PROTECT_HOME_NO ? 3 : 0) + - (protect_system != PROTECT_SYSTEM_NO ? 2 : 0) + - (protect_system == PROTECT_SYSTEM_FULL ? 1 : 0); + (protect_home != PROTECT_HOME_NO || protect_system == PROTECT_SYSTEM_STRICT ? 3 : 0) + + (protect_system == PROTECT_SYSTEM_STRICT ? + (2 + !private_dev + !protect_sysctl) : + ((protect_system != PROTECT_SYSTEM_NO ? 3 : 0) + + (protect_system == PROTECT_SYSTEM_FULL ? 1 : 0))); if (n > 0) { m = mounts = (BindMount *) alloca0(n * sizeof(BindMount)); @@ -529,9 +531,13 @@ int setup_namespace( m++; } - if (protect_home != PROTECT_HOME_NO) { + if (protect_home != PROTECT_HOME_NO || protect_system == PROTECT_SYSTEM_STRICT) { const char *home_dir, *run_user_dir, *root_dir; + /* If protection of $HOME and $XDG_RUNTIME_DIR is requested, then go for it. If we are in + * strict system protection mode, then also add entries for these directories, but mark them + * writable. This is because we want ProtectHome= and ProtectSystem= to be fully orthogonal. */ + home_dir = prefix_roota(root_directory, "/home"); home_dir = strjoina("-", home_dir); run_user_dir = prefix_roota(root_directory, "/run/user"); @@ -540,22 +546,53 @@ int setup_namespace( root_dir = strjoina("-", root_dir); r = append_mounts(&m, STRV_MAKE(home_dir, run_user_dir, root_dir), - protect_home == PROTECT_HOME_READ_ONLY ? READONLY : INACCESSIBLE); + protect_home == PROTECT_HOME_READ_ONLY ? READONLY : + protect_home == PROTECT_HOME_YES ? INACCESSIBLE : READWRITE); if (r < 0) return r; } - if (protect_system != PROTECT_SYSTEM_NO) { - const char *usr_dir, *boot_dir, *etc_dir; + if (protect_system == PROTECT_SYSTEM_STRICT) { + /* In strict mode, we mount everything read-only, except for /proc, /dev, /sys which are the + * kernel API VFS, which are left writable, but PrivateDevices= + ProtectKernelTunables= + * protect those, and these options should be fully orthogonal. (And of course /home and + * friends are also left writable, as ProtectHome= shall manage those, orthogonally, see + * above). */ + + m->path = prefix_roota(root_directory, "/"); + m->mode = READONLY; + m++; + + m->path = prefix_roota(root_directory, "/proc"); + m->mode = READWRITE; + m++; + + if (!private_dev) { + m->path = prefix_roota(root_directory, "/dev"); + m->mode = READWRITE; + m++; + } + if (!protect_sysctl) { + m->path = prefix_roota(root_directory, "/sys"); + m->mode = READWRITE; + m++; + } + + } else if (protect_system != PROTECT_SYSTEM_NO) { + const char *usr_dir, *boot_dir, *efi_dir, *etc_dir; + + /* In any other mode we simply mark the relevant three directories ready-only. */ usr_dir = prefix_roota(root_directory, "/usr"); boot_dir = prefix_roota(root_directory, "/boot"); boot_dir = strjoina("-", boot_dir); + efi_dir = prefix_roota(root_directory, "/efi"); + efi_dir = strjoina("-", efi_dir); etc_dir = prefix_roota(root_directory, "/etc"); r = append_mounts(&m, protect_system == PROTECT_SYSTEM_FULL - ? STRV_MAKE(usr_dir, boot_dir, etc_dir) - : STRV_MAKE(usr_dir, boot_dir), READONLY); + ? STRV_MAKE(usr_dir, boot_dir, efi_dir, etc_dir) + : STRV_MAKE(usr_dir, boot_dir, efi_dir), READONLY); if (r < 0) return r; } @@ -780,6 +817,7 @@ static const char *const protect_system_table[_PROTECT_SYSTEM_MAX] = { [PROTECT_SYSTEM_NO] = "no", [PROTECT_SYSTEM_YES] = "yes", [PROTECT_SYSTEM_FULL] = "full", + [PROTECT_SYSTEM_STRICT] = "strict", }; DEFINE_STRING_TABLE_LOOKUP(protect_system, ProtectSystem); diff --git a/src/core/namespace.h b/src/core/namespace.h index 3845336287..6505bcc499 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -35,6 +35,7 @@ typedef enum ProtectSystem { PROTECT_SYSTEM_NO, PROTECT_SYSTEM_YES, PROTECT_SYSTEM_FULL, + PROTECT_SYSTEM_STRICT, _PROTECT_SYSTEM_MAX, _PROTECT_SYSTEM_INVALID = -1 } ProtectSystem; -- cgit v1.2.3-54-g00ecf From 63bb64a056113d4be5fefb16604accf08c8c204a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Aug 2016 16:12:46 +0200 Subject: core: imply ProtectHome=read-only and ProtectSystem=strict if DynamicUser=1 Let's make sure that services that use DynamicUser=1 cannot leave files in the file system should the system accidentally have a world-writable directory somewhere. This effectively ensures that directories need to be whitelisted rather than blacklisted for access when DynamicUser=1 is set. --- man/systemd.exec.xml | 12 ++++++++---- src/core/unit.c | 6 ++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 1b672fe0c9..e4d9c0ef1b 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -160,14 +160,18 @@ use. However, UID/GIDs are recycled after a unit is terminated. Care should be taken that any processes running as part of a unit for which dynamic users/groups are enabled do not leave files or directories owned by these users/groups around, as a different unit might get the same UID/GID assigned later on, and thus gain access to - these files or directories. If DynamicUser= is enabled, RemoveIPC= and + these files or directories. If DynamicUser= is enabled, RemoveIPC=, PrivateTmp= are implied. This ensures that the lifetime of IPC objects and temporary files created by the executed processes is bound to the runtime of the service, and hence the lifetime of the dynamic user/group. Since /tmp and /var/tmp are usually the only world-writable directories on a system this ensures that a unit making use of dynamic user/group allocation - cannot leave files around after unit termination. Use RuntimeDirectory= (see below) in order - to assign a writable runtime directory to a service, owned by the dynamic user/group and removed automatically - when the unit is terminated. Defaults to off. + cannot leave files around after unit termination. Moreover ProtectSystem=strict and + ProtectHome=read-only are implied, thus prohibiting the service to write to arbitrary file + system locations. In order to allow the service to write to certain directories, they have to be whitelisted + using ReadWritePaths=, but care must be taken so that that UID/GID recycling doesn't + create security issues involving files created by the service. Use RuntimeDirectory= (see + below) in order to assign a writable runtime directory to a service, owned by the dynamic user/group and + removed automatically when the unit is terminated. Defaults to off. diff --git a/src/core/unit.c b/src/core/unit.c index de22f657c6..5d284a359d 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3377,8 +3377,14 @@ int unit_patch_contexts(Unit *u) { return -ENOMEM; } + /* If the dynamic user option is on, let's make sure that the unit can't leave its UID/GID + * around in the file system or on IPC objects. Hence enforce a strict sandbox. */ + ec->private_tmp = true; ec->remove_ipc = true; + ec->protect_system = PROTECT_SYSTEM_STRICT; + if (ec->protect_home == PROTECT_HOME_NO) + ec->protect_home = PROTECT_HOME_READ_ONLY; } } -- cgit v1.2.3-54-g00ecf From 920a7899ded2711e5ff4fe367a60a4fefca6767f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Aug 2016 16:25:49 +0200 Subject: nspawn: let's mount /proc/sysrq-trigger read-only by default LXC does this, and we should probably too. Better safe than sorry. --- src/nspawn/nspawn-mount.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 8457357003..25d38aa742 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -314,19 +314,21 @@ int mount_all(const char *dest, } MountPoint; static const MountPoint mount_table[] = { - { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true, false }, - { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true, false }, /* Bind mount first ...*/ - { "/proc/sys/net", "/proc/sys/net", NULL, NULL, MS_BIND, true, true, true }, /* (except for this) */ - { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true, true, false }, /* ... then, make it r/o */ - { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false, true }, - { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false, false }, - { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false, false }, - { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false }, - { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false }, - { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false, false }, + { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true, false }, + { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true, false }, /* Bind mount first ...*/ + { "/proc/sys/net", "/proc/sys/net", NULL, NULL, MS_BIND, true, true, true }, /* (except for this) */ + { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true, true, false }, /* ... then, make it r/o */ + { "/proc/sysrq-trigger", "/proc/sysrq-trigger", NULL, NULL, MS_BIND, false, true, false }, /* Bind mount first ...*/ + { NULL, "/proc/sysrq-trigger", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, true, false }, /* ... then, make it r/o */ + { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false, true }, + { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false, false }, + { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false, false }, + { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false }, + { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false }, + { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false, false }, #ifdef HAVE_SELINUX - { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false, false }, /* Bind mount first */ - { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, false, false }, /* Then, make it r/o */ + { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false, false }, /* Bind mount first */ + { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, false, false }, /* Then, make it r/o */ #endif }; @@ -356,7 +358,7 @@ int mount_all(const char *dest, continue; r = mkdir_p(where, 0755); - if (r < 0) { + if (r < 0 && r != -EEXIST) { if (mount_table[k].fatal) return log_error_errno(r, "Failed to create directory %s: %m", where); -- cgit v1.2.3-54-g00ecf From 096424d1230e0a0339735c51b43949809e972430 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Aug 2016 17:29:12 +0200 Subject: execute: drop group priviliges only after setting up namespace If PrivateDevices=yes is set, the namespace code creates device nodes in /dev that should be owned by the host's root, hence let's make sure we set up the namespace before dropping group privileges. --- src/core/execute.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 20e74ec8a6..ae251b2a4c 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2291,14 +2291,9 @@ static int exec_child( } accum_env = strv_env_clean(accum_env); - umask(context->umask); + (void) umask(context->umask); if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { - r = enforce_groups(context, username, gid); - if (r < 0) { - *exit_status = EXIT_GROUP; - return r; - } #ifdef HAVE_SMACK if (context->smack_process_label) { r = mac_smack_apply_pid(0, context->smack_process_label); @@ -2395,6 +2390,14 @@ static int exec_child( } } + if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { + r = enforce_groups(context, username, gid); + if (r < 0) { + *exit_status = EXIT_GROUP; + return r; + } + } + if (context->working_directory_home) wd = home; else if (context->working_directory) -- cgit v1.2.3-54-g00ecf From 1e4e94c8819e2fe3a7217690c0590dba8ab0be9e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 25 Aug 2016 17:30:47 +0200 Subject: namespace: invoke unshare() only after checking all parameters Let's create the new namespace only after we validated and processed all parameters, right before we start with actually mounting things. This way, the window where we can roll back is larger (not that it matters IRL...) --- src/core/namespace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index 498cd139bf..356d3c8121 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -462,9 +462,6 @@ int setup_namespace( if (mount_flags == 0) mount_flags = MS_SHARED; - if (unshare(CLONE_NEWNS) < 0) - return -errno; - n = !!tmp_dir + !!var_tmp_dir + strv_length(read_write_paths) + strv_length(read_only_paths) + @@ -606,6 +603,9 @@ int setup_namespace( drop_nop(mounts, &n); } + if (unshare(CLONE_NEWNS) < 0) + return -errno; + if (n > 0 || root_directory) { /* Remount / as SLAVE so that nothing now mounted in the namespace shows up in the parent */ -- cgit v1.2.3-54-g00ecf From d944dc9553009822deaddec76814f5642a6a8176 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 24 Sep 2016 12:41:30 +0200 Subject: namespace: chase symlinks for mounts to set up in userspace This adds logic to chase symlinks for all mount points that shall be created in a namespace environment in userspace, instead of leaving this to the kernel. This has the advantage that we can correctly handle absolute symlinks that shall be taken relative to a specific root directory. Moreover, we can properly handle mounts created on symlinked files or directories as we can merge their mounts as necessary. (This also drops the "done" flag in the namespace logic, which was never actually working, but was supposed to permit a partial rollback of the namespace logic, which however is only mildly useful as it wasn't clear in which case it would or would not be able to roll back.) Fixes: #3867 --- src/basic/fs-util.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++ src/basic/fs-util.h | 2 + src/core/namespace.c | 118 +++++++++++++++++++----------- src/test/test-fs-util.c | 96 ++++++++++++++++++++++++- src/test/test-ns.c | 10 ++- 5 files changed, 367 insertions(+), 46 deletions(-) diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index ce87257bc1..86d9ad7e36 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -597,3 +597,190 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) { return r; } + +int chase_symlinks(const char *path, const char *_root, char **ret) { + _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL; + _cleanup_close_ int fd = -1; + unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */ + char *todo; + int r; + + assert(path); + + /* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following + * symlinks relative to a root directory, instead of the root of the host. + * + * Note that "root" matters only if we encounter an absolute symlink, it's unused otherwise. Most importantly + * this means the path parameter passed in is not prefixed by it. + * + * Algorithmically this operates on two path buffers: "done" are the components of the path we already + * processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we still need to + * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning + * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no + * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races + * at a minimum. */ + + r = path_make_absolute_cwd(path, &buffer); + if (r < 0) + return r; + + if (_root) { + r = path_make_absolute_cwd(_root, &root); + if (r < 0) + return r; + } + + fd = open("/", O_CLOEXEC|O_NOFOLLOW|O_PATH); + if (fd < 0) + return -errno; + + todo = buffer; + for (;;) { + _cleanup_free_ char *first = NULL; + _cleanup_close_ int child = -1; + struct stat st; + size_t n, m; + + /* Determine length of first component in the path */ + n = strspn(todo, "/"); /* The slashes */ + m = n + strcspn(todo + n, "/"); /* The entire length of the component */ + + /* Extract the first component. */ + first = strndup(todo, m); + if (!first) + return -ENOMEM; + + todo += m; + + /* Just a single slash? Then we reached the end. */ + if (isempty(first) || path_equal(first, "/")) + break; + + /* Just a dot? Then let's eat this up. */ + if (path_equal(first, "/.")) + continue; + + /* Two dots? Then chop off the last bit of what we already found out. */ + if (path_equal(first, "/..")) { + _cleanup_free_ char *parent = NULL; + int fd_parent = -1; + + if (isempty(done) || path_equal(done, "/")) + return -EINVAL; + + parent = dirname_malloc(done); + if (!parent) + return -ENOMEM; + + /* Don't allow this to leave the root dir */ + if (root && + path_startswith(done, root) && + !path_startswith(parent, root)) + return -EINVAL; + + free(done); + done = parent; + parent = NULL; + + fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH); + if (fd_parent < 0) + return -errno; + + safe_close(fd); + fd = fd_parent; + + continue; + } + + /* Otherwise let's see what this is. */ + child = openat(fd, first + n, O_CLOEXEC|O_NOFOLLOW|O_PATH); + if (child < 0) + return -errno; + + if (fstat(child, &st) < 0) + return -errno; + + if (S_ISLNK(st.st_mode)) { + _cleanup_free_ char *destination = NULL; + + /* This is a symlink, in this case read the destination. But let's make sure we don't follow + * symlinks without bounds. */ + if (--max_follow <= 0) + return -ELOOP; + + r = readlinkat_malloc(fd, first + n, &destination); + if (r < 0) + return r; + if (isempty(destination)) + return -EINVAL; + + if (path_is_absolute(destination)) { + + /* An absolute destination. Start the loop from the beginning, but use the root + * directory as base. */ + + safe_close(fd); + fd = open(root ?: "/", O_CLOEXEC|O_NOFOLLOW|O_PATH); + if (fd < 0) + return -errno; + + free(buffer); + buffer = destination; + destination = NULL; + + todo = buffer; + free(done); + + /* Note that we do not revalidate the root, we take it as is. */ + if (isempty(root)) + done = NULL; + else { + done = strdup(root); + if (!done) + return -ENOMEM; + } + + } else { + char *joined; + + /* A relative destination. If so, this is what we'll prefix what's left to do with what + * we just read, and start the loop again, but remain in the current directory. */ + + joined = strjoin("/", destination, todo, NULL); + if (!joined) + return -ENOMEM; + + free(buffer); + todo = buffer = joined; + } + + continue; + } + + /* If this is not a symlink, then let's just add the name we read to what we already verified. */ + if (!done) { + done = first; + first = NULL; + } else { + if (!strextend(&done, first, NULL)) + return -ENOMEM; + } + + /* And iterate again, but go one directory further down. */ + safe_close(fd); + fd = child; + child = -1; + } + + if (!done) { + /* Special case, turn the empty string into "/", to indicate the root directory. */ + done = strdup("/"); + if (!done) + return -ENOMEM; + } + + *ret = done; + done = NULL; + + return 0; +} diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 2c3b9a1c74..31df47cf1e 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -77,3 +77,5 @@ union inotify_event_buffer { }; int inotify_add_watch_fd(int fd, int what, uint32_t mask); + +int chase_symlinks(const char *path, const char *_root, char **ret); diff --git a/src/core/namespace.c b/src/core/namespace.c index 356d3c8121..d3ab2e8e3e 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -29,6 +29,7 @@ #include "alloc-util.h" #include "dev-setup.h" #include "fd-util.h" +#include "fs-util.h" #include "loopback-setup.h" #include "missing.h" #include "mkdir.h" @@ -57,9 +58,9 @@ typedef enum MountMode { } MountMode; typedef struct BindMount { - const char *path; + const char *path; /* stack memory, doesn't need to be freed explicitly */ + char *chased; /* malloc()ed memory, needs to be freed */ MountMode mode; - bool done; bool ignore; } BindMount; @@ -71,7 +72,6 @@ static int append_mounts(BindMount **p, char **strv, MountMode mode) { STRV_FOREACH(i, strv) { (*p)->ignore = false; - (*p)->done = false; if ((mode == INACCESSIBLE || mode == READONLY || mode == READWRITE) && (*i)[0] == '-') { (*p)->ignore = true; @@ -360,11 +360,8 @@ static int apply_mount( * inaccessible path. */ (void) umount_recursive(m->path, 0); - if (lstat(m->path, &target) < 0) { - if (m->ignore && errno == ENOENT) - return 0; + if (lstat(m->path, &target) < 0) return log_debug_errno(errno, "Failed to lstat() %s to determine what to mount over it: %m", m->path); - } what = mode_to_inaccessible_node(target.st_mode); if (!what) { @@ -378,11 +375,8 @@ static int apply_mount( case READWRITE: r = path_is_mount_point(m->path, 0); - if (r < 0) { - if (m->ignore && errno == ENOENT) - return 0; + if (r < 0) return log_debug_errno(r, "Failed to determine whether %s is already a mount point: %m", m->path); - } if (r > 0) /* Nothing to do here, it is already a mount. We just later toggle the MS_RDONLY bit for the mount point if needed. */ return 0; @@ -407,12 +401,8 @@ static int apply_mount( assert(what); - if (mount(what, m->path, NULL, MS_BIND|MS_REC, NULL) < 0) { - if (m->ignore && errno == ENOENT) - return 0; - + if (mount(what, m->path, NULL, MS_BIND|MS_REC, NULL) < 0) return log_debug_errno(errno, "Failed to mount %s to %s: %m", what, m->path); - } log_debug("Successfully mounted %s to %s", what, m->path); return 0; @@ -435,12 +425,43 @@ static int make_read_only(BindMount *m, char **blacklist) { * already stays this way. This improves compatibility with container managers, where we won't attempt to undo * read-only mounts already applied. */ - if (m->ignore && r == -ENOENT) - return 0; - return r; } +static int chase_all_symlinks(const char *root_directory, BindMount *m, unsigned *n) { + BindMount *f, *t; + int r; + + assert(m); + assert(n); + + /* Since mount() will always follow symlinks and we need to take the different root directory into account we + * chase the symlinks on our own first. This call wil do so for all entries and remove all entries where we + * can't resolve the path, and which have been marked for such removal. */ + + for (f = m, t = m; f < m+*n; f++) { + + r = chase_symlinks(f->path, root_directory, &f->chased); + if (r == -ENOENT && f->ignore) /* Doesn't exist? Then remove it! */ + continue; + if (r < 0) + return log_debug_errno(r, "Failed to chase symlinks for %s: %m", f->path); + + if (path_equal(f->path, f->chased)) + f->chased = mfree(f->chased); + else { + log_debug("Chased %s → %s", f->path, f->chased); + f->path = f->chased; + } + + *t = *f; + t++; + } + + *n = t - m; + return 0; +} + int setup_namespace( const char* root_directory, char** read_write_paths, @@ -456,6 +477,7 @@ int setup_namespace( unsigned long mount_flags) { BindMount *m, *mounts = NULL; + bool make_slave = false; unsigned n; int r = 0; @@ -475,6 +497,9 @@ int setup_namespace( ((protect_system != PROTECT_SYSTEM_NO ? 3 : 0) + (protect_system == PROTECT_SYSTEM_FULL ? 1 : 0))); + if (root_directory || n > 0) + make_slave = true; + if (n > 0) { m = mounts = (BindMount *) alloca0(n * sizeof(BindMount)); r = append_mounts(&m, read_write_paths, READWRITE); @@ -596,6 +621,13 @@ int setup_namespace( assert(mounts + n == m); + /* Resolve symlinks manually first, as mount() will always follow them relative to the host's + * root. Moreover we want to suppress duplicates based on the resolved paths. This of course is a bit + * racy. */ + r = chase_all_symlinks(root_directory, mounts, &n); + if (r < 0) + goto finish; + qsort(mounts, n, sizeof(BindMount), mount_path_compare); drop_duplicates(mounts, &n); @@ -603,20 +635,26 @@ int setup_namespace( drop_nop(mounts, &n); } - if (unshare(CLONE_NEWNS) < 0) - return -errno; + if (unshare(CLONE_NEWNS) < 0) { + r = -errno; + goto finish; + } - if (n > 0 || root_directory) { + if (make_slave) { /* Remount / as SLAVE so that nothing now mounted in the namespace shows up in the parent */ - if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) - return -errno; + if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) { + r = -errno; + goto finish; + } } if (root_directory) { /* Turn directory into bind mount */ - if (mount(root_directory, root_directory, NULL, MS_BIND|MS_REC, NULL) < 0) - return -errno; + if (mount(root_directory, root_directory, NULL, MS_BIND|MS_REC, NULL) < 0) { + r = -errno; + goto finish; + } } if (n > 0) { @@ -627,7 +665,7 @@ int setup_namespace( for (m = mounts; m < mounts + n; ++m) { r = apply_mount(m, tmp_dir, var_tmp_dir); if (r < 0) - goto fail; + goto finish; } /* Create a blacklist we can pass to bind_mount_recursive() */ @@ -640,34 +678,30 @@ int setup_namespace( for (m = mounts; m < mounts + n; ++m) { r = make_read_only(m, blacklist); if (r < 0) - goto fail; + goto finish; } } if (root_directory) { /* MS_MOVE does not work on MS_SHARED so the remount MS_SHARED will be done later */ r = mount_move_root(root_directory); - if (r < 0) /* at this point, we cannot rollback */ - return r; + if (r < 0) + goto finish; } /* Remount / as the desired mode. Not that this will not * reestablish propagation from our side to the host, since * what's disconnected is disconnected. */ - if (mount(NULL, "/", NULL, mount_flags | MS_REC, NULL) < 0) - return -errno; /* at this point, we cannot rollback */ + if (mount(NULL, "/", NULL, mount_flags | MS_REC, NULL) < 0) { + r = -errno; + goto finish; + } - return 0; + r = 0; -fail: - if (n > 0) { - for (m = mounts; m < mounts + n; ++m) { - if (!m->done) - continue; - - (void) umount2(m->path, MNT_DETACH); - } - } +finish: + for (m = mounts; m < mounts + n; m++) + free(m->chased); return r; } diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index b35a2ea2c8..53a3cdc663 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -20,16 +20,109 @@ #include #include "alloc-util.h" -#include "fileio.h" #include "fd-util.h" +#include "fileio.h" #include "fs-util.h" #include "macro.h" #include "mkdir.h" +#include "path-util.h" #include "rm-rf.h" #include "string-util.h" #include "strv.h" #include "util.h" +static void test_chase_symlinks(void) { + _cleanup_free_ char *result = NULL; + char temp[] = "/tmp/test-chase.XXXXXX"; + const char *top, *p, *q; + int r; + + assert_se(mkdtemp(temp)); + + top = strjoina(temp, "/top"); + assert_se(mkdir(top, 0700) >= 0); + + p = strjoina(top, "/dot"); + assert_se(symlink(".", p) >= 0); + + p = strjoina(top, "/dotdot"); + assert_se(symlink("..", p) >= 0); + + p = strjoina(top, "/dotdota"); + assert_se(symlink("../a", p) >= 0); + + p = strjoina(temp, "/a"); + assert_se(symlink("b", p) >= 0); + + p = strjoina(temp, "/b"); + assert_se(symlink("/usr", p) >= 0); + + p = strjoina(temp, "/start"); + assert_se(symlink("top/dot/dotdota", p) >= 0); + + r = chase_symlinks(p, NULL, &result); + assert_se(r >= 0); + assert_se(path_equal(result, "/usr")); + + result = mfree(result); + r = chase_symlinks(p, temp, &result); + assert_se(r == -ENOENT); + + q = strjoina(temp, "/usr"); + assert_se(mkdir(q, 0700) >= 0); + + r = chase_symlinks(p, temp, &result); + assert_se(r >= 0); + assert_se(path_equal(result, q)); + + p = strjoina(temp, "/slash"); + assert_se(symlink("/", p) >= 0); + + result = mfree(result); + r = chase_symlinks(p, NULL, &result); + assert_se(r >= 0); + assert_se(path_equal(result, "/")); + + result = mfree(result); + r = chase_symlinks(p, temp, &result); + assert_se(r >= 0); + assert_se(path_equal(result, temp)); + + p = strjoina(temp, "/slashslash"); + assert_se(symlink("///usr///", p) >= 0); + + result = mfree(result); + r = chase_symlinks(p, NULL, &result); + assert_se(r >= 0); + assert_se(path_equal(result, "/usr")); + + result = mfree(result); + r = chase_symlinks(p, temp, &result); + assert_se(r >= 0); + assert_se(path_equal(result, q)); + + result = mfree(result); + r = chase_symlinks("/etc/./.././", NULL, &result); + assert_se(r >= 0); + assert_se(path_equal(result, "/")); + + result = mfree(result); + r = chase_symlinks("/etc/./.././", "/etc", &result); + assert_se(r == -EINVAL); + + result = mfree(result); + r = chase_symlinks("/etc/machine-id/foo", NULL, &result); + assert_se(r == -ENOTDIR); + + result = mfree(result); + p = strjoina(temp, "/recursive-symlink"); + assert_se(symlink("recursive-symlink", p) >= 0); + r = chase_symlinks(p, NULL, &result); + assert_se(r == -ELOOP); + + assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); +} + static void test_unlink_noerrno(void) { char name[] = "/tmp/test-close_nointr.XXXXXX"; int fd; @@ -144,6 +237,7 @@ int main(int argc, char *argv[]) { test_readlink_and_make_absolute(); test_get_files_in_directory(); test_var_tmp(); + test_chase_symlinks(); return 0; } diff --git a/src/test/test-ns.c b/src/test/test-ns.c index 03a24620af..c4d4da6d05 100644 --- a/src/test/test-ns.c +++ b/src/test/test-ns.c @@ -26,14 +26,18 @@ int main(int argc, char *argv[]) { const char * const writable[] = { "/home", - "/home/lennart/projects/foobar", /* this should be masked automatically */ + "-/home/lennart/projects/foobar", /* this should be masked automatically */ NULL }; const char * const readonly[] = { - "/", - "/usr", + /* "/", */ + /* "/usr", */ "/boot", + "/lib", + "/usr/lib", + "-/lib64", + "-/usr/lib64", NULL }; -- cgit v1.2.3-54-g00ecf From 8f1ad200f010dc2106f7e3ff5879f0330ee36996 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 11:27:38 +0200 Subject: namespace: don't make the root directory of a namespace a mount if it already is one Let's not stack mounts needlessly. --- src/core/namespace.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index d3ab2e8e3e..a7451ffbdc 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -650,10 +650,15 @@ int setup_namespace( } if (root_directory) { - /* Turn directory into bind mount */ - if (mount(root_directory, root_directory, NULL, MS_BIND|MS_REC, NULL) < 0) { - r = -errno; + /* Turn directory into bind mount, if it isn't one yet */ + r = path_is_mount_point(root_directory, AT_SYMLINK_FOLLOW); + if (r < 0) goto finish; + if (r == 0) { + if (mount(root_directory, root_directory, NULL, MS_BIND|MS_REC, NULL) < 0) { + r = -errno; + goto finish; + } } } -- cgit v1.2.3-54-g00ecf From b2656f1b1ca94fc8b6a0eb44986df78d23ff7950 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 12:22:23 +0200 Subject: man: in user-facing documentaiton don't reference C function names Let's drop the reference to the cap_from_name() function in the documentation for the capabilities setting, as it is hardly helpful. Our readers are not necessarily C hackers knowing the semantics of cap_from_name(). Moreover, the strings we accept are just the plain capability names as listed in capabilities(7) hence there's really no point in confusing the user with anything else. --- man/systemd.exec.xml | 64 +++++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index e4d9c0ef1b..67182f17dc 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -821,49 +821,37 @@ Controls which capabilities to include in the capability bounding set for the executed process. See capabilities7 for - details. Takes a whitespace-separated list of capability names as read by cap_from_name3, - e.g. CAP_SYS_ADMIN, CAP_DAC_OVERRIDE, - CAP_SYS_PTRACE. Capabilities listed will be included in the bounding set, all others are - removed. If the list of capabilities is prefixed with ~, all but the listed capabilities - will be included, the effect of the assignment inverted. Note that this option also affects the respective - capabilities in the effective, permitted and inheritable capability sets. If this option is not used, the - capability bounding set is not modified on process execution, hence no limits on the capabilities of the - process are enforced. This option may appear more than once, in which case the bounding sets are merged. If the - empty string is assigned to this option, the bounding set is reset to the empty capability set, and all prior - settings have no effect. If set to ~ (without any further argument), the bounding set is - reset to the full set of available capabilities, also undoing any previous settings. This does not affect - commands prefixed with +. + details. Takes a whitespace-separated list of capability names, e.g. CAP_SYS_ADMIN, + CAP_DAC_OVERRIDE, CAP_SYS_PTRACE. Capabilities listed will be + included in the bounding set, all others are removed. If the list of capabilities is prefixed with + ~, all but the listed capabilities will be included, the effect of the assignment + inverted. Note that this option also affects the respective capabilities in the effective, permitted and + inheritable capability sets. If this option is not used, the capability bounding set is not modified on process + execution, hence no limits on the capabilities of the process are enforced. This option may appear more than + once, in which case the bounding sets are merged. If the empty string is assigned to this option, the bounding + set is reset to the empty capability set, and all prior settings have no effect. If set to + ~ (without any further argument), the bounding set is reset to the full set of available + capabilities, also undoing any previous settings. This does not affect commands prefixed with + +. AmbientCapabilities= - Controls which capabilities to include in the - ambient capability set for the executed process. Takes a - whitespace-separated list of capability names as read by - cap_from_name3, - e.g. CAP_SYS_ADMIN, - CAP_DAC_OVERRIDE, - CAP_SYS_PTRACE. This option may appear more than - once in which case the ambient capability sets are merged. - If the list of capabilities is prefixed with ~, all - but the listed capabilities will be included, the effect of the - assignment inverted. If the empty string is - assigned to this option, the ambient capability set is reset to - the empty capability set, and all prior settings have no effect. - If set to ~ (without any further argument), the - ambient capability set is reset to the full set of available - capabilities, also undoing any previous settings. Note that adding - capabilities to ambient capability set adds them to the process's - inherited capability set. - - Ambient capability sets are useful if you want to execute a process - as a non-privileged user but still want to give it some capabilities. - Note that in this case option keep-caps is - automatically added to SecureBits= to retain the - capabilities over the user change. AmbientCapabilities= does not affect - commands prefixed with +. + Controls which capabilities to include in the ambient capability set for the executed + process. Takes a whitespace-separated list of capability names, e.g. CAP_SYS_ADMIN, + CAP_DAC_OVERRIDE, CAP_SYS_PTRACE. This option may appear more than + once in which case the ambient capability sets are merged. If the list of capabilities is prefixed with + ~, all but the listed capabilities will be included, the effect of the assignment + inverted. If the empty string is assigned to this option, the ambient capability set is reset to the empty + capability set, and all prior settings have no effect. If set to ~ (without any further + argument), the ambient capability set is reset to the full set of available capabilities, also undoing any + previous settings. Note that adding capabilities to ambient capability set adds them to the process's inherited + capability set. Ambient capability sets are useful if you want to execute a process as a + non-privileged user but still want to give it some capabilities. Note that in this case option + keep-caps is automatically added to SecureBits= to retain the + capabilities over the user change. AmbientCapabilities= does not affect commands prefixed + with +. -- cgit v1.2.3-54-g00ecf From effbd6d2eadb61bd236d118afc7901940c4c6b37 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 12:24:37 +0200 Subject: man: rework documentation for ReadOnlyPaths= and related settings This reworks the documentation for ReadOnlyPaths=, ReadWritePaths=, InaccessiblePaths=. It no longer claims that we'd follow symlinks relative to the host file system. (Which wasn't true actually, as we didn't follow symlinks at all in the most recent releases, and we know do follow them, but relative to RootDirectory=). This also replaces all references to the fact that all fs namespacing options can be undone with enough privileges and disable propagation by a single one in the documentation of ReadOnlyPaths= and friends, and then directs the read to this in all other places. Moreover a hint is added to the documentation of SystemCallFilter=, suggesting usage of ~@mount in case any of the fs namespacing related options are used. --- man/systemd.exec.xml | 214 ++++++++++++++++++++++----------------------------- 1 file changed, 92 insertions(+), 122 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 67182f17dc..84f81fe38e 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -877,48 +877,34 @@ ReadOnlyPaths= InaccessiblePaths= - Sets up a new file system namespace for - executed processes. These options may be used to limit access - a process might have to the main file system hierarchy. Each - setting takes a space-separated list of paths relative to - the host's root directory (i.e. the system running the service manager). - Note that if entries contain symlinks, they are resolved from the host's root directory as well. - Entries (files or directories) listed in - ReadWritePaths= are accessible from - within the namespace with the same access rights as from - outside. Entries listed in - ReadOnlyPaths= are accessible for - reading only, writing will be refused even if the usual file - access controls would permit this. Entries listed in - InaccessiblePaths= will be made - inaccessible for processes inside the namespace, and may not - countain any other mountpoints, including those specified by - ReadWritePaths= or - ReadOnlyPaths=. - Note that restricting access with these options does not extend - to submounts of a directory that are created later on. - Non-directory paths can be specified as well. These - options may be specified more than once, in which case all - paths listed will have limited access from within the - namespace. If the empty string is assigned to this option, the - specific list is reset, and all prior assignments have no - effect. - Paths in - ReadOnlyPaths= - and - InaccessiblePaths= - may be prefixed with - -, in which case - they will be ignored when they do not - exist. Note that using this - setting will disconnect propagation of - mounts from the service to the host - (propagation in the opposite direction - continues to work). This means that - this setting may not be used for - services which shall be able to - install mount points in the main mount - namespace. + Sets up a new file system namespace for executed processes. These options may be used to limit + access a process might have to the file system hierarchy. Each setting takes a space-separated list of paths + relative to the host's root directory (i.e. the system running the service manager). Note that if paths + contain symlinks, they are resolved relative to the root directory set with + RootDirectory=. + + Paths listed in ReadWritePaths= are accessible from within the namespace with the same + access modes as from outside of it. Paths listed in ReadOnlyPaths= are accessible for + reading only, writing will be refused even if the usual file access controls would permit this. Nest + ReadWritePaths= inside of ReadOnlyPaths= in order to provide writable + subdirectories within read-only directories. Use ReadWritePaths= in order to whitelist + specific paths for write access if ProtectSystem=strict is used. Paths listed in + InaccessiblePaths= will be made inaccessible for processes inside the namespace (along with + everything below them in the file system hierarchy). + + Note that restricting access with these options does not extend to submounts of a directory that are + created later on. Non-directory paths may be specified as well. These options may be specified more than once, + in which case all paths listed will have limited access from within the namespace. If the empty string is + assigned to this option, the specific list is reset, and all prior assignments have no effect. + + Paths in ReadOnlyPaths= and InaccessiblePaths= may be prefixed with + -, in which case they will be ignored when they do not exist. Note that using this setting + will disconnect propagation of mounts from the service to the host (propagation in the opposite direction + continues to work). This means that this setting may not be used for services which shall be able to install + mount points in the main mount namespace. Note that the effect of these settings may be undone by privileged + processes. In order to set up an effective sandboxed environment for a unit it is thus recommended to combine + these settings with either CapabilityBoundingSet=~CAP_SYS_ADMIN or + SystemCallFilter=~@mount. @@ -933,37 +919,30 @@ private /tmp and /var/tmp namespace by using the JoinsNamespaceOf= directive, see systemd.unit5 for - details. Note that using this setting will disconnect propagation of mounts from the service to the host - (propagation in the opposite direction continues to work). This means that this setting may not be used for - services which shall be able to install mount points in the main mount namespace. This setting is implied if - DynamicUser= is set. + details. This setting is implied if DynamicUser= is set. For this setting the same + restrictions regarding mount propagation and privileges apply as for ReadOnlyPaths= and + related calls, see above. + PrivateDevices= - Takes a boolean argument. If true, sets up a - new /dev namespace for the executed processes and only adds - API pseudo devices such as /dev/null, - /dev/zero or - /dev/random (as well as the pseudo TTY - subsystem) to it, but no physical devices such as - /dev/sda. This is useful to securely turn - off physical device access by the executed process. Defaults - to false. Enabling this option will also remove - CAP_MKNOD from the capability bounding - set for the unit (see above), and set - DevicePolicy=closed (see + Takes a boolean argument. If true, sets up a new /dev namespace for the executed processes and + only adds API pseudo devices such as /dev/null, /dev/zero or + /dev/random (as well as the pseudo TTY subsystem) to it, but no physical devices such as + /dev/sda. This is useful to securely turn off physical device access by the executed + process. Defaults to false. Enabling this option will also remove CAP_MKNOD from the + capability bounding set for the unit (see above), and set DevicePolicy=closed (see systemd.resource-control5 - for details). Note that using this setting will disconnect - propagation of mounts from the service to the host - (propagation in the opposite direction continues to work). - This means that this setting may not be used for services - which shall be able to install mount points in the main mount - namespace. The /dev namespace will be mounted read-only and 'noexec'. - The latter may break old programs which try to set up executable - memory by using mmap2 - of /dev/zero instead of using MAP_ANON. + for details). Note that using this setting will disconnect propagation of mounts from the service to the host + (propagation in the opposite direction continues to work). This means that this setting may not be used for + services which shall be able to install mount points in the main mount namespace. The /dev namespace will be + mounted read-only and 'noexec'. The latter may break old programs which try to set up executable memory by + using mmap2 of + /dev/zero instead of using MAP_ANON. This setting is implied if + DynamicUser= is set. For this setting the same restrictions regarding mount propagation and + privileges apply as for ReadOnlyPaths= and related calls, see above. @@ -1023,33 +1002,23 @@ operating system (and optionally its configuration, and local mounts) is prohibited for the service. It is recommended to enable this setting for all long-running services, unless they are involved with system updates or need to modify the operating system in other ways. If this option is used, - ReadWritePaths= may be used to exclude specific directories from being made read-only. Note - that processes retaining the CAP_SYS_ADMIN capability (and with no system call filter that - prohibits mount-related system calls applied) can undo the effect of this setting. This setting is hence - particularly useful for daemons which have this either the @mount set filtered using - SystemCallFilter=, or have the CAP_SYS_ADMIN capability removed, for - example with CapabilityBoundingSet=. Defaults to off. + ReadWritePaths= may be used to exclude specific directories from being made read-only. This + setting is implied if DynamicUser= is set. For this setting the same restrictions regarding + mount propagation and privileges apply as for ReadOnlyPaths= and related calls, see + above. Defaults to off. ProtectHome= - Takes a boolean argument or - read-only. If true, the directories - /home, /root and - /run/user - are made inaccessible and empty for processes invoked by this - unit. If set to read-only, the three - directories are made read-only instead. It is recommended to - enable this setting for all long-running services (in - particular network-facing ones), to ensure they cannot get - access to private user data, unless the services actually - require access to the user's private data. Note however that - processes retaining the CAP_SYS_ADMIN capability can undo the - effect of this setting. This setting is hence particularly - useful for daemons which have this capability removed, for - example with CapabilityBoundingSet=. - Defaults to off. + Takes a boolean argument or read-only. If true, the directories + /home, /root and /run/user are made inaccessible + and empty for processes invoked by this unit. If set to read-only, the three directories are + made read-only instead. It is recommended to enable this setting for all long-running services (in particular + network-facing ones), to ensure they cannot get access to private user data, unless the services actually + require access to the user's private data. This setting is implied if DynamicUser= is + set. For this setting the same restrictions regarding mount propagation and privileges apply as for + ReadOnlyPaths= and related calls, see above. @@ -1059,48 +1028,41 @@ /proc/sys and /sys will be made read-only to all processes of the unit. Usually, tunable kernel variables should only be written at boot-time, with the sysctl.d5 mechanism. Almost - no services need to write to these at runtime; it is hence recommended to turn this on for most - services. Defaults to off. + no services need to write to these at runtime; it is hence recommended to turn this on for most services. For + this setting the same restrictions regarding mount propagation and privileges apply as for + ReadOnlyPaths= and related calls, see above. Defaults to off. ProtectControlGroups= - Takes a boolean argument. If true, the Linux Control Groups ("cgroups") hierarchies accessible - through /sys/fs/cgroup will be made read-only to all processes of the unit. Except for - container managers no services should require write access to the control groups hierarchies; it is hence - recommended to turn this on for most services. Defaults to off. + Takes a boolean argument. If true, the Linux Control Groups (cgroups7) hierarchies + accessible through /sys/fs/cgroup will be made read-only to all processes of the + unit. Except for container managers no services should require write access to the control groups hierarchies; + it is hence recommended to turn this on for most services. For this setting the same restrictions regarding + mount propagation and privileges apply as for ReadOnlyPaths= and related calls, see + above. Defaults to off. MountFlags= - Takes a mount propagation flag: - , or - , which control whether mounts in the - file system namespace set up for this unit's processes will - receive or propagate mounts or unmounts. See - mount2 - for details. Defaults to . Use - to ensure that mounts and unmounts are - propagated from the host to the container and vice versa. Use - to run processes so that none of their - mounts and unmounts will propagate to the host. Use - to also ensure that no mounts and - unmounts from the host will propagate into the unit processes' - namespace. Note that means that file - systems mounted on the host might stay mounted continuously in - the unit's namespace, and thus keep the device busy. Note that - the file system namespace related options - (PrivateTmp=, - PrivateDevices=, - ProtectSystem=, - ProtectHome=, - ReadOnlyPaths=, - InaccessiblePaths= and - ReadWritePaths=) require that mount - and unmount propagation from the unit's file system namespace - is disabled, and hence downgrade to + Takes a mount propagation flag: , or + , which control whether mounts in the file system namespace set up for this unit's + processes will receive or propagate mounts or unmounts. See mount2 for + details. Defaults to . Use to ensure that mounts and unmounts + are propagated from the host to the container and vice versa. Use to run processes so + that none of their mounts and unmounts will propagate to the host. Use to also ensure + that no mounts and unmounts from the host will propagate into the unit processes' namespace. Note that + means that file systems mounted on the host might stay mounted continuously in the + unit's namespace, and thus keep the device busy. Note that the file system namespace related options + (PrivateTmp=, PrivateDevices=, ProtectSystem=, + ProtectHome=, ProtectKernelTunables=, + ProtectControlGroups=, ReadOnlyPaths=, + InaccessiblePaths=, ReadWritePaths=) require that mount and unmount + propagation from the unit's file system namespace is disabled, and hence downgrade to . @@ -1335,7 +1297,15 @@ Note, that as new system calls are added to the kernel, additional system calls might be added to the groups - above, so the contents of the sets may change between systemd versions. + above, so the contents of the sets may change between systemd versions. + + It is recommended to combine the file system namespacing related options with + SystemCallFilter=~@mount, in order to prohibit the unit's processes to undo the + mappings. Specifically these are the options PrivateTmp=, + PrivateDevices=, ProtectSystem=, ProtectHome=, + ProtectKernelTunables=, ProtectControlGroups=, + ReadOnlyPaths=, InaccessiblePaths= and + ReadWritePaths=. -- cgit v1.2.3-54-g00ecf From 81c8aceed4a0cabd605788e46a266cc4cefdc16a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 12:29:28 +0200 Subject: man: the exit code/signal is stored in $EXIT_CODE, not $EXIT_STATUS --- man/systemd.exec.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 84f81fe38e..6811e7cc53 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1612,8 +1612,8 @@ ExecStop= and ExecStopPost= processes, and encodes the service "result". Currently, the following values are defined: timeout (in case of an operation timeout), exit-code (if a service process exited with a non-zero exit code; see - $EXIT_STATUS below for the actual exit status returned), signal (if a - service process was terminated abnormally by a signal; see $EXIT_STATUS below for the actual + $EXIT_CODE below for the actual exit code returned), signal (if a + service process was terminated abnormally by a signal; see $EXIT_CODE below for the actual signal used for the termination), core-dump (if a service process terminated abnormally and dumped core), watchdog (if the watchdog keep-alive ping was enabled for the service but it missed the deadline), or resources (a catch-all condition in case a system operation -- cgit v1.2.3-54-g00ecf From 6757c06a1a8dd3755338ca76e598e0d81dc164f2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 12:29:52 +0200 Subject: man: shorten the exit status table a bit Let's merge a couple of columns, to make the table a bit shorter. This effectively just drops whitespace, not contents, but makes the currently humungous table much much more compact. --- man/systemd.exec.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 6811e7cc53..403aa471c8 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1658,32 +1658,32 @@ timeout killed - TERMKILL + TERM, KILL exited - 0123255 + 0, 1, 2, 3, …, 255 exit-code exited - 0123255 + 0, 1, 2, 3, …, 255 signal killed - HUPINTKILL + HUP, INT, KILL, … core-dump dumped - ABRTSEGVQUIT + ABRT, SEGV, QUIT, … @@ -1693,12 +1693,12 @@ killed - TERMKILL + TERM, KILL exited - 0123255 + 0, 1, 2, 3, …, 255 -- cgit v1.2.3-54-g00ecf From f6eb19a474fdee780d5f2a4b62b5a55e6cbef4de Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 12:45:10 +0200 Subject: units: permit importd to mount stuff Fixes #3996 --- units/systemd-importd.service.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/units/systemd-importd.service.in b/units/systemd-importd.service.in index 0f5489e7e3..332ee910d1 100644 --- a/units/systemd-importd.service.in +++ b/units/systemd-importd.service.in @@ -18,4 +18,4 @@ NoNewPrivileges=yes WatchdogSec=3min KillMode=mixed MemoryDenyWriteExecute=yes -SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io +SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io -- cgit v1.2.3-54-g00ecf From 0c28d51ac84973904e5f780b024adf8108e69fa1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 13:23:27 +0200 Subject: units: further lock down our long-running services Let's make this an excercise in dogfooding: let's turn on more security features for all our long-running services. Specifically: - Turn on RestrictRealtime=yes for all of them - Turn on ProtectKernelTunables=yes and ProtectControlGroups=yes for most of them - Turn on RestrictAddressFamilies= for all of them, but different sets of address families for each Also, always order settings in the unit files, that the various sandboxing features are close together. Add a couple of missing, older settings for a numbre of unit files. Note that this change turns off AF_INET/AF_INET6 from udevd, thus effectively turning of networking from udev rule commands. Since this might break stuff (that is already broken I'd argue) this is documented in NEWS. --- units/systemd-hostnamed.service.in | 6 +++++- units/systemd-importd.service.in | 6 ++++-- units/systemd-journal-gatewayd.service.in | 5 +++++ units/systemd-journal-remote.service.in | 13 +++++++++---- units/systemd-journal-upload.service.in | 12 +++++++++--- units/systemd-journald.service.in | 4 +++- units/systemd-localed.service.in | 6 +++++- units/systemd-logind.service.in | 4 +++- units/systemd-machined.service.in | 4 +++- units/systemd-networkd.service.m4.in | 5 ++++- units/systemd-resolved.service.m4.in | 8 +++++++- units/systemd-timedated.service.in | 6 +++++- units/systemd-timesyncd.service.in | 6 +++++- units/systemd-udevd.service.in | 5 ++++- 14 files changed, 71 insertions(+), 19 deletions(-) diff --git a/units/systemd-hostnamed.service.in b/units/systemd-hostnamed.service.in index 0b03a589ea..edc5a1722a 100644 --- a/units/systemd-hostnamed.service.in +++ b/units/systemd-hostnamed.service.in @@ -13,12 +13,16 @@ Documentation=http://www.freedesktop.org/wiki/Software/systemd/hostnamed [Service] ExecStart=@rootlibexecdir@/systemd-hostnamed BusName=org.freedesktop.hostname1 -CapabilityBoundingSet=CAP_SYS_ADMIN WatchdogSec=3min +CapabilityBoundingSet=CAP_SYS_ADMIN PrivateTmp=yes PrivateDevices=yes PrivateNetwork=yes ProtectSystem=yes ProtectHome=yes +ProtectControlGroups=yes +ProtectKernelTunables=yes MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io diff --git a/units/systemd-importd.service.in b/units/systemd-importd.service.in index 332ee910d1..ac27c2bcba 100644 --- a/units/systemd-importd.service.in +++ b/units/systemd-importd.service.in @@ -13,9 +13,11 @@ Documentation=http://www.freedesktop.org/wiki/Software/systemd/importd [Service] ExecStart=@rootlibexecdir@/systemd-importd BusName=org.freedesktop.import1 -CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD CAP_SETFCAP CAP_SYS_ADMIN CAP_SETPCAP CAP_DAC_OVERRIDE -NoNewPrivileges=yes WatchdogSec=3min KillMode=mixed +CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD CAP_SETFCAP CAP_SYS_ADMIN CAP_SETPCAP CAP_DAC_OVERRIDE +NoNewPrivileges=yes MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io diff --git a/units/systemd-journal-gatewayd.service.in b/units/systemd-journal-gatewayd.service.in index f4f845841d..efefaa4244 100644 --- a/units/systemd-journal-gatewayd.service.in +++ b/units/systemd-journal-gatewayd.service.in @@ -20,6 +20,11 @@ PrivateDevices=yes PrivateNetwork=yes ProtectSystem=full ProtectHome=yes +ProtectControlGroups=yes +ProtectKernelTunables=yes +MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 # If there are many split upjournal files we need a lot of fds to # access them all and combine diff --git a/units/systemd-journal-remote.service.in b/units/systemd-journal-remote.service.in index fdf3da4b64..753dd6c158 100644 --- a/units/systemd-journal-remote.service.in +++ b/units/systemd-journal-remote.service.in @@ -11,15 +11,20 @@ Documentation=man:systemd-journal-remote(8) man:journal-remote.conf(5) Requires=systemd-journal-remote.socket [Service] -ExecStart=@rootlibexecdir@/systemd-journal-remote \ - --listen-https=-3 \ - --output=/var/log/journal/remote/ +ExecStart=@rootlibexecdir@/systemd-journal-remote --listen-https=-3 --output=/var/log/journal/remote/ User=systemd-journal-remote Group=systemd-journal-remote +WatchdogSec=3min PrivateTmp=yes PrivateDevices=yes PrivateNetwork=yes -WatchdogSec=3min +ProtectSystem=full +ProtectHome=yes +ProtectControlGroups=yes +ProtectKernelTunables=yes +MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 [Install] Also=systemd-journal-remote.socket diff --git a/units/systemd-journal-upload.service.in b/units/systemd-journal-upload.service.in index 1f488ff425..c709543af5 100644 --- a/units/systemd-journal-upload.service.in +++ b/units/systemd-journal-upload.service.in @@ -11,13 +11,19 @@ Documentation=man:systemd-journal-upload(8) After=network.target [Service] -ExecStart=@rootlibexecdir@/systemd-journal-upload \ - --save-state +ExecStart=@rootlibexecdir@/systemd-journal-upload --save-state User=systemd-journal-upload SupplementaryGroups=systemd-journal +WatchdogSec=3min PrivateTmp=yes PrivateDevices=yes -WatchdogSec=3min +ProtectSystem=full +ProtectHome=yes +ProtectControlGroups=yes +ProtectKernelTunables=yes +MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 # If there are many split up journal files we need a lot of fds to # access them all and combine diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in index 08ace8ae44..712ce55483 100644 --- a/units/systemd-journald.service.in +++ b/units/systemd-journald.service.in @@ -21,10 +21,12 @@ Restart=always RestartSec=0 NotifyAccess=all StandardOutput=null -CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE WatchdogSec=3min FileDescriptorStoreMax=1024 +CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_NETLINK SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io # Increase the default a bit in order to allow many simultaneous diff --git a/units/systemd-localed.service.in b/units/systemd-localed.service.in index 1f3151c2b5..df829e1164 100644 --- a/units/systemd-localed.service.in +++ b/units/systemd-localed.service.in @@ -13,12 +13,16 @@ Documentation=http://www.freedesktop.org/wiki/Software/systemd/localed [Service] ExecStart=@rootlibexecdir@/systemd-localed BusName=org.freedesktop.locale1 -CapabilityBoundingSet= WatchdogSec=3min +CapabilityBoundingSet= PrivateTmp=yes PrivateDevices=yes PrivateNetwork=yes ProtectSystem=yes ProtectHome=yes +ProtectControlGroups=yes +ProtectKernelTunables=yes MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in index bee08d011f..0b6de35733 100644 --- a/units/systemd-logind.service.in +++ b/units/systemd-logind.service.in @@ -23,9 +23,11 @@ ExecStart=@rootlibexecdir@/systemd-logind Restart=always RestartSec=0 BusName=org.freedesktop.login1 -CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG WatchdogSec=3min +CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io # Increase the default a bit in order to allow many simultaneous diff --git a/units/systemd-machined.service.in b/units/systemd-machined.service.in index dcf9f347b7..911ead79ee 100644 --- a/units/systemd-machined.service.in +++ b/units/systemd-machined.service.in @@ -15,9 +15,11 @@ After=machine.slice [Service] ExecStart=@rootlibexecdir@/systemd-machined BusName=org.freedesktop.machine1 -CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD WatchdogSec=3min +CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io # Note that machined cannot be placed in a mount namespace, since it diff --git a/units/systemd-networkd.service.m4.in b/units/systemd-networkd.service.m4.in index 38d967d2d1..a968d8bd45 100644 --- a/units/systemd-networkd.service.m4.in +++ b/units/systemd-networkd.service.m4.in @@ -27,11 +27,14 @@ Type=notify Restart=on-failure RestartSec=0 ExecStart=@rootlibexecdir@/systemd-networkd +WatchdogSec=3min CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER ProtectSystem=full ProtectHome=yes -WatchdogSec=3min +ProtectControlGroups=yes MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 AF_PACKET SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io [Install] diff --git a/units/systemd-resolved.service.m4.in b/units/systemd-resolved.service.m4.in index 15ab56a066..0f0440ddaf 100644 --- a/units/systemd-resolved.service.m4.in +++ b/units/systemd-resolved.service.m4.in @@ -23,11 +23,17 @@ Type=notify Restart=always RestartSec=0 ExecStart=@rootlibexecdir@/systemd-resolved +WatchdogSec=3min CapabilityBoundingSet=CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_NET_RAW CAP_NET_BIND_SERVICE +PrivateTmp=yes +PrivateDevices=yes ProtectSystem=full ProtectHome=yes -WatchdogSec=3min +ProtectControlGroups=yes +ProtectKernelTunables=yes MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io [Install] diff --git a/units/systemd-timedated.service.in b/units/systemd-timedated.service.in index bc1795d747..e8c4d5ed4b 100644 --- a/units/systemd-timedated.service.in +++ b/units/systemd-timedated.service.in @@ -13,10 +13,14 @@ Documentation=http://www.freedesktop.org/wiki/Software/systemd/timedated [Service] ExecStart=@rootlibexecdir@/systemd-timedated BusName=org.freedesktop.timedate1 -CapabilityBoundingSet=CAP_SYS_TIME WatchdogSec=3min +CapabilityBoundingSet=CAP_SYS_TIME PrivateTmp=yes ProtectSystem=yes ProtectHome=yes +ProtectControlGroups=yes +ProtectKernelTunables=yes MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX SystemCallFilter=~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io diff --git a/units/systemd-timesyncd.service.in b/units/systemd-timesyncd.service.in index df1e339196..9a6c6ea60d 100644 --- a/units/systemd-timesyncd.service.in +++ b/units/systemd-timesyncd.service.in @@ -22,13 +22,17 @@ Type=notify Restart=always RestartSec=0 ExecStart=@rootlibexecdir@/systemd-timesyncd +WatchdogSec=3min CapabilityBoundingSet=CAP_SYS_TIME CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER PrivateTmp=yes PrivateDevices=yes ProtectSystem=full ProtectHome=yes -WatchdogSec=3min +ProtectControlGroups=yes +ProtectKernelTunables=yes MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 SystemCallFilter=~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io [Install] diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in index 67e4c5fcd7..cb2d8ba775 100644 --- a/units/systemd-udevd.service.in +++ b/units/systemd-udevd.service.in @@ -21,7 +21,10 @@ Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket Restart=always RestartSec=0 ExecStart=@rootlibexecdir@/systemd-udevd -MountFlags=slave KillMode=mixed WatchdogSec=3min TasksMax=infinity +MountFlags=slave +MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_NETLINK -- cgit v1.2.3-54-g00ecf From 1ecdba149bab8346b611e2ccacfe66e58a7b863c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Sep 2016 21:29:06 +0200 Subject: NEWS: update news about systemd-udevd.service --- NEWS | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/NEWS b/NEWS index 178ccf9b04..5f3f76df4f 100644 --- a/NEWS +++ b/NEWS @@ -137,6 +137,20 @@ CHANGES WITH 232 in spe $SYSTEMD_NSPAWN_SHARE_NS_UTS may be used to control the unsharing of individual namespaces. + * systemd-udevd.service is now run in a Seccomp-based sandbox that + prohibits access to AF_INET and AF_INET6 sockets and thus access to + the network. This might break code that runs from udev rules that + tries to talk to the network. Doing that is generally a bad idea and + unsafe due to a variety of reasons. It's also racy as device + management would race against network configuration. It is + recommended to rework such rules to use the SYSTEMD_WANTS property on + the relevant devices to pull in a proper systemd service (which can + be sandboxed differently and ordered correctly after the network + having come up). If that's not possible consider reverting this + sandboxing feature locally by removing the RestrictAddressFamilies= + setting from the systemd-udevd.service unit file, or adding AF_INET + and AF_INET6 to it. + CHANGES WITH 231: * In service units the various ExecXYZ= settings have been extended -- cgit v1.2.3-54-g00ecf From ba128bb809cc59ca60db65f0c09bd7f48876fa83 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 16:39:04 +0200 Subject: execute: filter low-level I/O syscalls if PrivateDevices= is set If device access is restricted via PrivateDevices=, let's also block the various low-level I/O syscalls at the same time, so that we know that the minimal set of devices in our virtualized /dev are really everything the unit can access. --- src/core/execute.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/core/execute.c b/src/core/execute.c index ae251b2a4c..a20e9ea829 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1422,12 +1422,67 @@ finish: return r; } +static int apply_private_devices(Unit *u, const ExecContext *c) { + + static const int device_syscalls[] = { + SCMP_SYS(ioperm), + SCMP_SYS(iopl), + SCMP_SYS(pciconfig_iobase), + SCMP_SYS(pciconfig_read), + SCMP_SYS(pciconfig_write), +#ifdef __NR_s390_pci_mmio_read + SCMP_SYS(s390_pci_mmio_read), +#endif +#ifdef __NR_s390_pci_mmio_write + SCMP_SYS(s390_pci_mmio_write), +#endif + }; + + scmp_filter_ctx *seccomp; + unsigned i; + int r; + + assert(c); + + /* If PrivateDevices= is set, also turn off iopl and friends. */ + + if (skip_seccomp_unavailable(u, "PrivateDevices=")) + return 0; + + seccomp = seccomp_init(SCMP_ACT_ALLOW); + if (!seccomp) + return -ENOMEM; + + r = seccomp_add_secondary_archs(seccomp); + if (r < 0) + goto finish; + + for (i = 0; i < ELEMENTSOF(device_syscalls); i++) { + r = seccomp_rule_add( + seccomp, + SCMP_ACT_ERRNO(EPERM), + device_syscalls[i], + 0); + if (r < 0) + goto finish; + } + + r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); + if (r < 0) + goto finish; + + r = seccomp_load(seccomp); + +finish: + seccomp_release(seccomp); + return r; +} + #endif static void do_idle_pipe_dance(int idle_pipe[4]) { assert(idle_pipe); - idle_pipe[1] = safe_close(idle_pipe[1]); idle_pipe[2] = safe_close(idle_pipe[2]); @@ -2584,6 +2639,14 @@ static int exec_child( } } + if (context->private_devices) { + r = apply_private_devices(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return r; + } + } + if (context_has_syscall_filters(context)) { r = apply_seccomp(unit, context); if (r < 0) { -- cgit v1.2.3-54-g00ecf From 0439746492e5839cfa1cdd76b9d23711eb1f451b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 24 Aug 2016 20:53:56 +0200 Subject: Update TODO --- TODO | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/TODO b/TODO index e7391f0bfe..a47f4c488b 100644 --- a/TODO +++ b/TODO @@ -32,6 +32,8 @@ Janitorial Clean-ups: Features: +* switch to ProtectSystem=strict for all our long-running services where that's possible + * introduce an "invocation ID" for units, that is randomly generated, and identifies each runtime-cycle of a unit. It should be set freshly each time we traverse inactive → activating/active, and should be the primary key to @@ -40,8 +42,9 @@ Features: the cgroup of a services. The former is accessible without privileges, the latter ensures the ID cannot be faked. -* Introduce ProtectSystem=strict for making the entire OS hierarchy read-only - except for a select few +* If RootDirectory= is used, mount /proc, /sys, /dev into it, if not mounted yet + +* Permit masking specific netlink APIs with RestrictAddressFamily= * nspawn: start UID allocation loop from hash of container name @@ -55,15 +58,13 @@ Features: * ProtectClock= (drops CAP_SYS_TIMES, adds seecomp filters for settimeofday, adjtimex), sets DeviceAllow o /dev/rtc -* ProtectMount= (drop mount/umount/pivot_root from seccomp, disallow fuse via DeviceAllow, imply Mountflags=slave) - -* ProtectDevices= should also take iopl/ioperm/pciaccess away +* ProtectKernelModules= (drops CAP_SYS_MODULE and filters the kmod syscalls) -* ProtectKeyRing= to take keyring calls away +* ProtectTracing= (drops CAP_SYS_PTRACE, blocks ptrace syscall, makes /sys/kernel/tracing go away) -* ProtectControlGroups= which mounts all of /sys/fs/cgroup read-only +* ProtectMount= (drop mount/umount/pivot_root from seccomp, disallow fuse via DeviceAllow, imply Mountflags=slave) -* ProtectKernelTunables= which mounts /sys and /proc/sys read-only +* ProtectKeyRing= to take keyring calls away * RemoveKeyRing= to remove all keyring entries of the specified user @@ -72,9 +73,6 @@ Features: * Add BindDirectory= for allowing arbitrary, private bind mounts for services -* Beef up RootDirectory= to use namespacing/bind mounts as soon as fs - namespaces are enabled by the service - * Add RootImage= for mounting a disk image or file as root directory * RestrictNamespaces= or so in services (taking away the ability to create namespaces, with setns, unshare, clone) @@ -180,7 +178,7 @@ Features: * implement a per-service firewall based on net_cls * Port various tools to make use of verbs.[ch], where applicable: busctl, - bootctl, coredumpctl, hostnamectl, localectl, systemd-analyze, timedatectl + coredumpctl, hostnamectl, localectl, systemd-analyze, timedatectl * hostnamectl: show root image uuid @@ -293,9 +291,6 @@ Features: * MessageQueueMessageSize= (and suchlike) should use parse_iec_size(). -* "busctl status" works only as root on dbus1, since we cannot read - /proc/$PID/exe - * implement Distribute= in socket units to allow running multiple service instances processing the listening socket, and open this up for ReusePort= @@ -306,8 +301,6 @@ Features: and passes this back to PID1 via SCM_RIGHTS. This also could be used to allow Chown/chgrp on sockets without requiring NSS in PID 1. -* New service property: maximum CPU runtime for a service - * introduce bus call FreezeUnit(s, b), as well as "systemctl freeze $UNIT" and "systemctl thaw $UNIT" as wrappers around this. The calls should SIGSTOP all unit processes in a loop until all processes of @@ -344,12 +337,10 @@ Features: error. Currently, we just ignore it and read the unit from the search path anyway. -* refuse boot if /etc/os-release is missing or /etc/machine-id cannot be set up +* refuse boot if /usr/lib/os-release is missing or /etc/machine-id cannot be set up * btrfs raid assembly: some .device jobs stay stuck in the queue -* make sure gdm does not use multi-user-x but the new default X configuration file, and then remove multi-user-x from systemd - * man: the documentation of Restart= currently is very misleading and suggests the tools from ExecStartPre= might get restarted. * load .d/*.conf dropins for device units @@ -606,9 +597,6 @@ Features: * currently x-systemd.timeout is lost in the initrd, since crypttab is copied into dracut, but fstab is not * nspawn: - - to allow "linking" of nspawn containers, extend --network-bridge= so - that it can dynamically create bridge interfaces that are refcounted - by the containers on them. For each group of containers to link together - nspawn -x should support ephemeral instances of gpt images - emulate /dev/kmsg using CUSE and turn off the syslog syscall with seccomp. That should provide us with a useful log buffer that @@ -617,8 +605,6 @@ Features: - as soon as networkd has a bus interface, hook up --network-interface=, --network-bridge= with networkd, to trigger netdev creation should an interface be missing - - don't copy /etc/resolv.conf from host into container unless we are in - shared-network mode - a nice way to boot up without machine id set, so that it is set at boot automatically for supporting --ephemeral. Maybe hash the host machine id together with the machine name to generate the machine id for the container @@ -684,7 +670,6 @@ Features: * coredump: - save coredump in Windows/Mozilla minidump format - - move PID 1 segfaults to /var/lib/systemd/coredump? * support crash reporting operation modes (https://live.gnome.org/GnomeOS/Design/Whiteboards/ProblemReporting) @@ -751,7 +736,6 @@ Features: - GC unreferenced jobs (such as .device jobs) - move PAM code into its own binary - when we automatically restart a service, ensure we restart its rdeps, too. - - for services: do not set $HOME in services unless requested - hide PAM options in fragment parser when compile time disabled - Support --test based on current system state - If we show an error about a unit (such as not showing up) and it has no Description string, then show a description string generated form the reverse of unit_name_mangle(). -- cgit v1.2.3-54-g00ecf From 54500613a46023fe991f424e21ed15948b9a74f5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 17:25:08 +0200 Subject: main: minor simplification --- src/core/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 803307c9d5..be0cb0b6d1 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -996,10 +996,8 @@ static int parse_argv(int argc, char *argv[]) { case ARG_MACHINE_ID: r = set_machine_id(optarg); - if (r < 0) { - log_error("MachineID '%s' is not valid.", optarg); - return r; - } + if (r < 0) + return log_error_errno(r, "MachineID '%s' is not valid.", optarg); break; case 'h': -- cgit v1.2.3-54-g00ecf From cd2902c9546eabfffcf5d6de4d0bd4dfe6a4d427 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 17:25:40 +0200 Subject: namespace: drop all mounts outside of the new root directory There's no point in mounting these, if they are outside of the root directory we'll move to. --- src/core/namespace.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/core/namespace.c b/src/core/namespace.c index a7451ffbdc..c9b2154985 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -199,6 +199,31 @@ static void drop_nop(BindMount *m, unsigned *n) { *n = t - m; } +static void drop_outside_root(const char *root_directory, BindMount *m, unsigned *n) { + BindMount *f, *t; + + assert(m); + assert(n); + + if (!root_directory) + return; + + /* Drops all mounts that are outside of the root directory. */ + + for (f = m, t = m; f < m+*n; f++) { + + if (!path_startswith(f->path, root_directory)) { + log_debug("%s is outside of root directory.", f->path); + continue; + } + + *t = *f; + t++; + } + + *n = t - m; +} + static int mount_dev(BindMount *m) { static const char devnodes[] = "/dev/null\0" @@ -631,6 +656,7 @@ int setup_namespace( qsort(mounts, n, sizeof(BindMount), mount_path_compare); drop_duplicates(mounts, &n); + drop_outside_root(root_directory, mounts, &n); drop_inaccessible(mounts, &n); drop_nop(mounts, &n); } -- cgit v1.2.3-54-g00ecf From cefc33aee299fa214f093d3d1b4c171ac3b30dde Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 17:40:42 +0200 Subject: execute: move SMACK setup code into its own function While we are at it, move PAM code #ifdeffery into setup_pam() to simplify the main execution logic a bit. --- src/core/execute.c | 74 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index a20e9ea829..0488ba2ca9 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -837,6 +837,8 @@ static int null_conv( return PAM_CONV_ERR; } +#endif + static int setup_pam( const char *name, const char *user, @@ -845,6 +847,8 @@ static int setup_pam( char ***env, int fds[], unsigned n_fds) { +#ifdef HAVE_PAM + static const struct pam_conv conv = { .conv = null_conv, .appdata_ptr = NULL @@ -1038,8 +1042,10 @@ fail: closelog(); return r; -} +#else + return 0; #endif +} static void rename_process_from_path(const char *path) { char process_name[11]; @@ -1875,6 +1881,42 @@ static int setup_runtime_directory( return 0; } +static int setup_smack( + const ExecContext *context, + const ExecCommand *command) { + +#ifdef HAVE_SMACK + int r; + + assert(context); + assert(command); + + if (!mac_smack_use()) + return 0; + + if (context->smack_process_label) { + r = mac_smack_apply_pid(0, context->smack_process_label); + if (r < 0) + return r; + } +#ifdef SMACK_DEFAULT_PROCESS_LABEL + else { + _cleanup_free_ char *exec_label = NULL; + + r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label); + if (r < 0 && r != -ENODATA && r != -EOPNOTSUPP) + return r; + + r = mac_smack_apply_pid(0, exec_label ? : SMACK_DEFAULT_PROCESS_LABEL); + if (r < 0) + return r; + } +#endif +#endif + + return 0; +} + static int compile_read_write_paths( const ExecContext *context, const ExecParameters *params, @@ -2349,33 +2391,12 @@ static int exec_child( (void) umask(context->umask); if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { -#ifdef HAVE_SMACK - if (context->smack_process_label) { - r = mac_smack_apply_pid(0, context->smack_process_label); - if (r < 0) { - *exit_status = EXIT_SMACK_PROCESS_LABEL; - return r; - } + r = setup_smack(context, command); + if (r < 0) { + *exit_status = EXIT_SMACK_PROCESS_LABEL; + return r; } -#ifdef SMACK_DEFAULT_PROCESS_LABEL - else { - _cleanup_free_ char *exec_label = NULL; - r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label); - if (r < 0 && r != -ENODATA && r != -EOPNOTSUPP) { - *exit_status = EXIT_SMACK_PROCESS_LABEL; - return r; - } - - r = mac_smack_apply_pid(0, exec_label ? : SMACK_DEFAULT_PROCESS_LABEL); - if (r < 0) { - *exit_status = EXIT_SMACK_PROCESS_LABEL; - return r; - } - } -#endif -#endif -#ifdef HAVE_PAM if (context->pam_name && username) { r = setup_pam(context->pam_name, username, uid, context->tty_path, &accum_env, fds, n_fds); if (r < 0) { @@ -2383,7 +2404,6 @@ static int exec_child( return r; } } -#endif } if (context->private_network && runtime && runtime->netns_storage_socket[0] >= 0) { -- cgit v1.2.3-54-g00ecf From 9c94d52e0919e4d7999e49b9ba2654a9e2ca4543 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 25 Sep 2016 11:03:21 +0200 Subject: core:namespace: minor improvements to append_mounts() --- src/core/namespace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index c9b2154985..8de774e6f6 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -70,12 +70,11 @@ static int append_mounts(BindMount **p, char **strv, MountMode mode) { assert(p); STRV_FOREACH(i, strv) { + bool ignore = false; - (*p)->ignore = false; - - if ((mode == INACCESSIBLE || mode == READONLY || mode == READWRITE) && (*i)[0] == '-') { - (*p)->ignore = true; + if (IN_SET(mode, INACCESSIBLE, READONLY, READWRITE) && startswith(*i, "-")) { (*i)++; + ignore = true; } if (!path_is_absolute(*i)) @@ -83,6 +82,7 @@ static int append_mounts(BindMount **p, char **strv, MountMode mode) { (*p)->path = *i; (*p)->mode = mode; + (*p)->ignore = ignore; (*p)++; } -- cgit v1.2.3-54-g00ecf From 11a30cec2a9b6168b024c06720ad238dd1390794 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 25 Sep 2016 11:16:44 +0200 Subject: core:namespace: put paths protected by ProtectKernelTunables= in Instead of having all these paths everywhere, put the ones that are protected by ProtectKernelTunables= into their own table. This way it is easy to add paths and track which ones are protected. --- src/core/namespace.c | 54 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index 8de774e6f6..13f6aeba51 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -61,9 +61,23 @@ typedef struct BindMount { const char *path; /* stack memory, doesn't need to be freed explicitly */ char *chased; /* malloc()ed memory, needs to be freed */ MountMode mode; - bool ignore; + bool ignore; /* Ignore if path does not exist */ } BindMount; +typedef struct TargetMount { + const char *path; + MountMode mode; + bool ignore; /* Ignore if path does not exist */ +} TargetMount; + +/* ProtectKernelTunables= option and the related filesystem APIs */ +static const TargetMount protect_kernel_tunables_table[] = { + { "/proc/sys", READONLY, false }, + { "/proc/sysrq-trigger", READONLY, true }, + { "/sys", READONLY, false }, + { "/sys/fs/cgroup", READWRITE, false }, /* READONLY is set by ProtectControlGroups= option */ +}; + static int append_mounts(BindMount **p, char **strv, MountMode mode) { char **i; @@ -89,6 +103,20 @@ static int append_mounts(BindMount **p, char **strv, MountMode mode) { return 0; } +static void append_protect_kernel_tunables(BindMount **p, const char *root_directory) { + unsigned int i; + + assert(p); + + for (i = 0; i < ELEMENTSOF(protect_kernel_tunables_table); i++) { + const TargetMount *t = &protect_kernel_tunables_table[i]; + (*p)->path = prefix_roota(root_directory, t->path); + (*p)->mode = t->mode; + (*p)->ignore = t->ignore; + (*p)++; + } +} + static int mount_path_compare(const void *a, const void *b) { const BindMount *p = a, *q = b; int d; @@ -514,8 +542,8 @@ int setup_namespace( strv_length(read_only_paths) + strv_length(inaccessible_paths) + private_dev + - (protect_sysctl ? 3 : 0) + - (protect_cgroups != protect_sysctl) + + (protect_sysctl ? ELEMENTSOF(protect_kernel_tunables_table) : 0) + + (protect_cgroups ? 1 : 0) + (protect_home != PROTECT_HOME_NO || protect_system == PROTECT_SYSTEM_STRICT ? 3 : 0) + (protect_system == PROTECT_SYSTEM_STRICT ? (2 + !private_dev + !protect_sysctl) : @@ -557,24 +585,12 @@ int setup_namespace( m++; } - if (protect_sysctl) { - m->path = prefix_roota(root_directory, "/proc/sys"); - m->mode = READONLY; - m++; - - m->path = prefix_roota(root_directory, "/proc/sysrq-trigger"); - m->mode = READONLY; - m->ignore = true; /* Not always compiled into the kernel */ - m++; + if (protect_sysctl) + append_protect_kernel_tunables(&m, root_directory); - m->path = prefix_roota(root_directory, "/sys"); - m->mode = READONLY; - m++; - } - - if (protect_cgroups != protect_sysctl) { + if (protect_cgroups) { m->path = prefix_roota(root_directory, "/sys/fs/cgroup"); - m->mode = protect_cgroups ? READONLY : READWRITE; + m->mode = READONLY; m++; } -- cgit v1.2.3-54-g00ecf From 2652c6c10394623b2c3e2ed5d4616c85918d140c Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 25 Sep 2016 11:25:00 +0200 Subject: core:namespace: simplify mount calculation Move out mount calculation on its own function. Actually the logic is smart enough to later drop nop and duplicates mounts, this change improves code readability. --- src/core/namespace.c | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) --- src/core/namespace.c | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index 13f6aeba51..8aa8b83c88 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -515,6 +515,32 @@ static int chase_all_symlinks(const char *root_directory, BindMount *m, unsigned return 0; } +static unsigned namespace_calculate_mounts( + char** read_write_paths, + char** read_only_paths, + char** inaccessible_paths, + const char* tmp_dir, + const char* var_tmp_dir, + bool private_dev, + bool protect_sysctl, + bool protect_cgroups, + ProtectHome protect_home, + ProtectSystem protect_system) { + + return !!tmp_dir + !!var_tmp_dir + + strv_length(read_write_paths) + + strv_length(read_only_paths) + + strv_length(inaccessible_paths) + + private_dev + + (protect_sysctl ? ELEMENTSOF(protect_kernel_tunables_table) : 0) + + (protect_cgroups ? 1 : 0) + + (protect_home != PROTECT_HOME_NO || protect_system == PROTECT_SYSTEM_STRICT ? 3 : 0) + + (protect_system == PROTECT_SYSTEM_STRICT ? + (2 + !private_dev + !protect_sysctl) : + ((protect_system != PROTECT_SYSTEM_NO ? 3 : 0) + + (protect_system == PROTECT_SYSTEM_FULL ? 1 : 0))); +} + int setup_namespace( const char* root_directory, char** read_write_paths, @@ -537,19 +563,15 @@ int setup_namespace( if (mount_flags == 0) mount_flags = MS_SHARED; - n = !!tmp_dir + !!var_tmp_dir + - strv_length(read_write_paths) + - strv_length(read_only_paths) + - strv_length(inaccessible_paths) + - private_dev + - (protect_sysctl ? ELEMENTSOF(protect_kernel_tunables_table) : 0) + - (protect_cgroups ? 1 : 0) + - (protect_home != PROTECT_HOME_NO || protect_system == PROTECT_SYSTEM_STRICT ? 3 : 0) + - (protect_system == PROTECT_SYSTEM_STRICT ? - (2 + !private_dev + !protect_sysctl) : - ((protect_system != PROTECT_SYSTEM_NO ? 3 : 0) + - (protect_system == PROTECT_SYSTEM_FULL ? 1 : 0))); + n = namespace_calculate_mounts(read_write_paths, + read_only_paths, + inaccessible_paths, + tmp_dir, var_tmp_dir, + private_dev, protect_sysctl, + protect_cgroups, protect_home, + protect_system); + /* Set mount slave mode */ if (root_directory || n > 0) make_slave = true; -- cgit v1.2.3-54-g00ecf From e778185bb55320e8242b57c19079377fe33e01bc Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Mon, 19 Sep 2016 21:46:17 +0200 Subject: doc: documentation fixes for ReadWritePaths= and ProtectKernelTunables= Documentation fixes for ReadWritePaths= and ProtectKernelTunables= as reported by Evgeny Vereshchagin. --- man/systemd.exec.xml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 403aa471c8..79ceee3ec0 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -897,14 +897,14 @@ in which case all paths listed will have limited access from within the namespace. If the empty string is assigned to this option, the specific list is reset, and all prior assignments have no effect. - Paths in ReadOnlyPaths= and InaccessiblePaths= may be prefixed with - -, in which case they will be ignored when they do not exist. Note that using this setting - will disconnect propagation of mounts from the service to the host (propagation in the opposite direction - continues to work). This means that this setting may not be used for services which shall be able to install - mount points in the main mount namespace. Note that the effect of these settings may be undone by privileged - processes. In order to set up an effective sandboxed environment for a unit it is thus recommended to combine - these settings with either CapabilityBoundingSet=~CAP_SYS_ADMIN or - SystemCallFilter=~@mount. + Paths in ReadWritePaths=, ReadOnlyPaths= and + InaccessiblePaths= may be prefixed with -, in which case they will be ignored + when they do not exist. Note that using this setting will disconnect propagation of mounts from the service to + the host (propagation in the opposite direction continues to work). This means that this setting may not be used + for services which shall be able to install mount points in the main mount namespace. Note that the effect of + these settings may be undone by privileged processes. In order to set up an effective sandboxed environment for + a unit it is thus recommended to combine these settings with either + CapabilityBoundingSet=~CAP_SYS_ADMIN or SystemCallFilter=~@mount. @@ -1025,11 +1025,11 @@ ProtectKernelTunables= Takes a boolean argument. If true, kernel variables accessible through - /proc/sys and /sys will be made read-only to all processes of the - unit. Usually, tunable kernel variables should only be written at boot-time, with the - sysctl.d5 mechanism. Almost - no services need to write to these at runtime; it is hence recommended to turn this on for most services. For - this setting the same restrictions regarding mount propagation and privileges apply as for + /proc/sys, /sys and /proc/sysrq-trigger will be + made read-only to all processes of the unit. Usually, tunable kernel variables should only be written at + boot-time, with the sysctl.d5 + mechanism. Almost no services need to write to these at runtime; it is hence recommended to turn this on for + most services. For this setting the same restrictions regarding mount propagation and privileges apply as for ReadOnlyPaths= and related calls, see above. Defaults to off. -- cgit v1.2.3-54-g00ecf From 9221aec8d09f3b55a08fcbe8012e48129474ab54 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Mon, 19 Sep 2016 21:46:17 +0200 Subject: doc: explicitly document that /dev/mem and /dev/port are blocked by PrivateDevices=true --- man/systemd.exec.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 79ceee3ec0..a3a431c82b 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -931,9 +931,10 @@ Takes a boolean argument. If true, sets up a new /dev namespace for the executed processes and only adds API pseudo devices such as /dev/null, /dev/zero or /dev/random (as well as the pseudo TTY subsystem) to it, but no physical devices such as - /dev/sda. This is useful to securely turn off physical device access by the executed - process. Defaults to false. Enabling this option will also remove CAP_MKNOD from the - capability bounding set for the unit (see above), and set DevicePolicy=closed (see + /dev/sda, system memory /dev/mem, system ports + /dev/port and others. This is useful to securely turn off physical device access by the + executed process. Defaults to false. Enabling this option will also remove CAP_MKNOD from + the capability bounding set for the unit (see above), and set DevicePolicy=closed (see systemd.resource-control5 for details). Note that using this setting will disconnect propagation of mounts from the service to the host (propagation in the opposite direction continues to work). This means that this setting may not be used for -- cgit v1.2.3-54-g00ecf From 49accde7bd915944d99c947dca0cf26ae0f24165 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 25 Sep 2016 11:30:11 +0200 Subject: core:sandbox: add more /proc/* entries to ProtectKernelTunables= Make ALSA entries, latency interface, mtrr, apm/acpi, suspend interface, filesystems configuration and IRQ tuning readonly. Most of these interfaces now days should be in /sys but they are still available through /proc, so just protect them. This patch does not touch /proc/net/... --- man/systemd.exec.xml | 6 ++++-- src/core/namespace.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index a3a431c82b..f19e7f6ee9 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1026,8 +1026,10 @@ ProtectKernelTunables= Takes a boolean argument. If true, kernel variables accessible through - /proc/sys, /sys and /proc/sysrq-trigger will be - made read-only to all processes of the unit. Usually, tunable kernel variables should only be written at + /proc/sys, /sys, /proc/sysrq-trigger, + /proc/latency_stats, /proc/acpi, + /proc/timer_stats, /proc/fs and /proc/irq will + be made read-only to all processes of the unit. Usually, tunable kernel variables should only be written at boot-time, with the sysctl.d5 mechanism. Almost no services need to write to these at runtime; it is hence recommended to turn this on for most services. For this setting the same restrictions regarding mount propagation and privileges apply as for diff --git a/src/core/namespace.c b/src/core/namespace.c index 8aa8b83c88..3234fab4bc 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -74,7 +74,18 @@ typedef struct TargetMount { static const TargetMount protect_kernel_tunables_table[] = { { "/proc/sys", READONLY, false }, { "/proc/sysrq-trigger", READONLY, true }, + { "/proc/latency_stats", READONLY, true }, + { "/proc/mtrr", READONLY, true }, + { "/proc/apm", READONLY, true }, + { "/proc/acpi", READONLY, true }, + { "/proc/timer_stats", READONLY, true }, + { "/proc/asound", READONLY, true }, + { "/proc/bus", READONLY, true }, + { "/proc/fs", READONLY, true }, + { "/proc/irq", READONLY, true }, { "/sys", READONLY, false }, + { "/sys/kernel/debug", READONLY, true }, + { "/sys/kernel/tracing", READONLY, true }, { "/sys/fs/cgroup", READWRITE, false }, /* READONLY is set by ProtectControlGroups= option */ }; -- cgit v1.2.3-54-g00ecf From f471b2afa11c97e48a4b6756f7254f88cc436960 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 25 Sep 2016 12:21:25 +0200 Subject: core: simplify ProtectSystem= implementation ProtectSystem= with all its different modes and other options like PrivateDevices= + ProtectKernelTunables= + ProtectHome= are orthogonal, however currently it's a bit hard to parse that from the implementation view. Simplify it by giving each mode its own table with all paths and references to other Protect options. With this change some entries are duplicated, but we do not care since duplicate mounts are first sorted by the most restrictive mode then cleaned. --- src/core/namespace.c | 171 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 113 insertions(+), 58 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index 3234fab4bc..985e343096 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -70,6 +70,14 @@ typedef struct TargetMount { bool ignore; /* Ignore if path does not exist */ } TargetMount; +/* + * The following Protect tables are to protect paths and mark some of them + * READONLY, in case a path is covered by an option from another table, then + * it is marked READWRITE in the current one, and the more restrictive mode is + * applied from that other table. This way all options can be combined in a + * safe and comprehensible way for users. + */ + /* ProtectKernelTunables= option and the related filesystem APIs */ static const TargetMount protect_kernel_tunables_table[] = { { "/proc/sys", READONLY, false }, @@ -89,6 +97,45 @@ static const TargetMount protect_kernel_tunables_table[] = { { "/sys/fs/cgroup", READWRITE, false }, /* READONLY is set by ProtectControlGroups= option */ }; +/* ProtectSystem=yes table */ +static const TargetMount protect_system_yes_table[] = { + { "/usr", READONLY, false }, + { "/boot", READONLY, true }, + { "/efi", READONLY, true }, +}; + +/* ProtectSystem=full includes ProtectSystem=yes */ +static const TargetMount protect_system_full_table[] = { + { "/usr", READONLY, false }, + { "/boot", READONLY, true }, + { "/efi", READONLY, true }, + { "/etc", READONLY, false }, +}; + +/* + * ProtectSystem=strict table. In this strict mode, we mount everything + * read-only, except for /proc, /dev, /sys which are the kernel API VFS, + * which are left writable, but PrivateDevices= + ProtectKernelTunables= + * protect those, and these options should be fully orthogonal. + * (And of course /home and friends are also left writable, as ProtectHome= + * shall manage those, orthogonally). + */ +static const TargetMount protect_system_strict_table[] = { + { "/", READONLY, false }, + { "/proc", READWRITE, false }, /* ProtectKernelTunables= */ + { "/sys", READWRITE, false }, /* ProtectKernelTunables= */ + { "/dev", READWRITE, false }, /* PrivateDevices= */ + { "/home", READWRITE, true }, /* ProtectHome= */ + { "/run/user", READWRITE, true }, /* ProtectHome= */ + { "/root", READWRITE, true }, /* ProtectHome= */ +}; + +static void set_bind_mount(BindMount **p, const char *path, MountMode mode, bool ignore) { + (*p)->path = path; + (*p)->mode = mode; + (*p)->ignore = ignore; +} + static int append_mounts(BindMount **p, char **strv, MountMode mode) { char **i; @@ -105,27 +152,71 @@ static int append_mounts(BindMount **p, char **strv, MountMode mode) { if (!path_is_absolute(*i)) return -EINVAL; - (*p)->path = *i; - (*p)->mode = mode; - (*p)->ignore = ignore; + set_bind_mount(p, *i, mode, ignore); (*p)++; } return 0; } -static void append_protect_kernel_tunables(BindMount **p, const char *root_directory) { - unsigned int i; +static int append_target_mounts(BindMount **p, const char *root_directory, const TargetMount *mounts, const size_t size) { + unsigned i; assert(p); + assert(mounts); - for (i = 0; i < ELEMENTSOF(protect_kernel_tunables_table); i++) { - const TargetMount *t = &protect_kernel_tunables_table[i]; - (*p)->path = prefix_roota(root_directory, t->path); - (*p)->mode = t->mode; - (*p)->ignore = t->ignore; + for (i = 0; i < size; i++) { + /* + * Here we assume that the ignore field is set during + * declaration we do not support "-" at the beginning. + */ + const TargetMount *m = &mounts[i]; + const char *path = prefix_roota(root_directory, m->path); + + if (!path_is_absolute(path)) + return -EINVAL; + + set_bind_mount(p, path, m->mode, m->ignore); (*p)++; } + + return 0; +} + +static int append_protect_kernel_tunables(BindMount **p, const char *root_directory) { + assert(p); + + return append_target_mounts(p, root_directory, protect_kernel_tunables_table, + ELEMENTSOF(protect_kernel_tunables_table)); +} + +static int append_protect_system(BindMount **p, const char *root_directory, ProtectSystem protect_system) { + int r = 0; + + assert(p); + + if (protect_system == PROTECT_SYSTEM_NO) + return 0; + + switch (protect_system) { + case PROTECT_SYSTEM_STRICT: + r = append_target_mounts(p, root_directory, protect_system_strict_table, + ELEMENTSOF(protect_system_strict_table)); + break; + case PROTECT_SYSTEM_YES: + r = append_target_mounts(p, root_directory, protect_system_yes_table, + ELEMENTSOF(protect_system_yes_table)); + break; + case PROTECT_SYSTEM_FULL: + r = append_target_mounts(p, root_directory, protect_system_full_table, + ELEMENTSOF(protect_system_full_table)); + break; + default: + r = -EINVAL; + break; + } + + return r; } static int mount_path_compare(const void *a, const void *b) { @@ -538,6 +629,14 @@ static unsigned namespace_calculate_mounts( ProtectHome protect_home, ProtectSystem protect_system) { + unsigned protect_system_cnt = + (protect_system == PROTECT_SYSTEM_STRICT ? + ELEMENTSOF(protect_system_strict_table) : + ((protect_system == PROTECT_SYSTEM_FULL) ? + ELEMENTSOF(protect_system_full_table) : + ((protect_system == PROTECT_SYSTEM_YES) ? + ELEMENTSOF(protect_system_yes_table) : 0))); + return !!tmp_dir + !!var_tmp_dir + strv_length(read_write_paths) + strv_length(read_only_paths) + @@ -546,10 +645,7 @@ static unsigned namespace_calculate_mounts( (protect_sysctl ? ELEMENTSOF(protect_kernel_tunables_table) : 0) + (protect_cgroups ? 1 : 0) + (protect_home != PROTECT_HOME_NO || protect_system == PROTECT_SYSTEM_STRICT ? 3 : 0) + - (protect_system == PROTECT_SYSTEM_STRICT ? - (2 + !private_dev + !protect_sysctl) : - ((protect_system != PROTECT_SYSTEM_NO ? 3 : 0) + - (protect_system == PROTECT_SYSTEM_FULL ? 1 : 0))); + protect_system_cnt; } int setup_namespace( @@ -648,50 +744,9 @@ int setup_namespace( return r; } - if (protect_system == PROTECT_SYSTEM_STRICT) { - /* In strict mode, we mount everything read-only, except for /proc, /dev, /sys which are the - * kernel API VFS, which are left writable, but PrivateDevices= + ProtectKernelTunables= - * protect those, and these options should be fully orthogonal. (And of course /home and - * friends are also left writable, as ProtectHome= shall manage those, orthogonally, see - * above). */ - - m->path = prefix_roota(root_directory, "/"); - m->mode = READONLY; - m++; - - m->path = prefix_roota(root_directory, "/proc"); - m->mode = READWRITE; - m++; - - if (!private_dev) { - m->path = prefix_roota(root_directory, "/dev"); - m->mode = READWRITE; - m++; - } - if (!protect_sysctl) { - m->path = prefix_roota(root_directory, "/sys"); - m->mode = READWRITE; - m++; - } - - } else if (protect_system != PROTECT_SYSTEM_NO) { - const char *usr_dir, *boot_dir, *efi_dir, *etc_dir; - - /* In any other mode we simply mark the relevant three directories ready-only. */ - - usr_dir = prefix_roota(root_directory, "/usr"); - boot_dir = prefix_roota(root_directory, "/boot"); - boot_dir = strjoina("-", boot_dir); - efi_dir = prefix_roota(root_directory, "/efi"); - efi_dir = strjoina("-", efi_dir); - etc_dir = prefix_roota(root_directory, "/etc"); - - r = append_mounts(&m, protect_system == PROTECT_SYSTEM_FULL - ? STRV_MAKE(usr_dir, boot_dir, efi_dir, etc_dir) - : STRV_MAKE(usr_dir, boot_dir, efi_dir), READONLY); - if (r < 0) - return r; - } + r = append_protect_system(&m, root_directory, protect_system); + if (r < 0) + return r; assert(mounts + n == m); -- cgit v1.2.3-54-g00ecf From b6c432ca7ed930c7e9078ac2266ae439aa242632 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 25 Sep 2016 12:41:16 +0200 Subject: core:namespace: simplify ProtectHome= implementation As with previous patch simplify ProtectHome and don't care about duplicates, they will be sorted by most restrictive mode and cleaned. --- src/core/namespace.c | 75 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index 985e343096..43a2f4ba6e 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -97,6 +97,23 @@ static const TargetMount protect_kernel_tunables_table[] = { { "/sys/fs/cgroup", READWRITE, false }, /* READONLY is set by ProtectControlGroups= option */ }; +/* + * ProtectHome=read-only table, protect $HOME and $XDG_RUNTIME_DIR and rest of + * system should be protected by ProtectSystem= + */ +static const TargetMount protect_home_read_only_table[] = { + { "/home", READONLY, true }, + { "/run/user", READONLY, true }, + { "/root", READONLY, true }, +}; + +/* ProtectHome=yes table */ +static const TargetMount protect_home_yes_table[] = { + { "/home", INACCESSIBLE, true }, + { "/run/user", INACCESSIBLE, true }, + { "/root", INACCESSIBLE, true }, +}; + /* ProtectSystem=yes table */ static const TargetMount protect_system_yes_table[] = { { "/usr", READONLY, false }, @@ -190,6 +207,31 @@ static int append_protect_kernel_tunables(BindMount **p, const char *root_direct ELEMENTSOF(protect_kernel_tunables_table)); } +static int append_protect_home(BindMount **p, const char *root_directory, ProtectHome protect_home) { + int r = 0; + + assert(p); + + if (protect_home == PROTECT_HOME_NO) + return 0; + + switch (protect_home) { + case PROTECT_HOME_READ_ONLY: + r = append_target_mounts(p, root_directory, protect_home_read_only_table, + ELEMENTSOF(protect_home_read_only_table)); + break; + case PROTECT_HOME_YES: + r = append_target_mounts(p, root_directory, protect_home_yes_table, + ELEMENTSOF(protect_home_yes_table)); + break; + default: + r = -EINVAL; + break; + } + + return r; +} + static int append_protect_system(BindMount **p, const char *root_directory, ProtectSystem protect_system) { int r = 0; @@ -629,6 +671,7 @@ static unsigned namespace_calculate_mounts( ProtectHome protect_home, ProtectSystem protect_system) { + unsigned protect_home_cnt; unsigned protect_system_cnt = (protect_system == PROTECT_SYSTEM_STRICT ? ELEMENTSOF(protect_system_strict_table) : @@ -637,6 +680,12 @@ static unsigned namespace_calculate_mounts( ((protect_system == PROTECT_SYSTEM_YES) ? ELEMENTSOF(protect_system_yes_table) : 0))); + protect_home_cnt = + (protect_home == PROTECT_HOME_YES ? + ELEMENTSOF(protect_home_yes_table) : + ((protect_home == PROTECT_HOME_READ_ONLY) ? + ELEMENTSOF(protect_home_read_only_table) : 0)); + return !!tmp_dir + !!var_tmp_dir + strv_length(read_write_paths) + strv_length(read_only_paths) + @@ -644,8 +693,7 @@ static unsigned namespace_calculate_mounts( private_dev + (protect_sysctl ? ELEMENTSOF(protect_kernel_tunables_table) : 0) + (protect_cgroups ? 1 : 0) + - (protect_home != PROTECT_HOME_NO || protect_system == PROTECT_SYSTEM_STRICT ? 3 : 0) + - protect_system_cnt; + protect_home_cnt + protect_system_cnt; } int setup_namespace( @@ -723,26 +771,9 @@ int setup_namespace( m++; } - if (protect_home != PROTECT_HOME_NO || protect_system == PROTECT_SYSTEM_STRICT) { - const char *home_dir, *run_user_dir, *root_dir; - - /* If protection of $HOME and $XDG_RUNTIME_DIR is requested, then go for it. If we are in - * strict system protection mode, then also add entries for these directories, but mark them - * writable. This is because we want ProtectHome= and ProtectSystem= to be fully orthogonal. */ - - home_dir = prefix_roota(root_directory, "/home"); - home_dir = strjoina("-", home_dir); - run_user_dir = prefix_roota(root_directory, "/run/user"); - run_user_dir = strjoina("-", run_user_dir); - root_dir = prefix_roota(root_directory, "/root"); - root_dir = strjoina("-", root_dir); - - r = append_mounts(&m, STRV_MAKE(home_dir, run_user_dir, root_dir), - protect_home == PROTECT_HOME_READ_ONLY ? READONLY : - protect_home == PROTECT_HOME_YES ? INACCESSIBLE : READWRITE); - if (r < 0) - return r; - } + r = append_protect_home(&m, root_directory, protect_home); + if (r < 0) + return r; r = append_protect_system(&m, root_directory, protect_system); if (r < 0) -- cgit v1.2.3-54-g00ecf From 8f81a5f61bcf745bae3acad599d7a9da686643e3 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 25 Sep 2016 12:52:27 +0200 Subject: core: Use @raw-io syscall group to filter I/O syscalls when PrivateDevices= is set Instead of having a local syscall list, use the @raw-io group which contains the same set of syscalls to filter. --- man/systemd.exec.xml | 6 ++++-- src/core/execute.c | 55 +++++++++++++++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index f19e7f6ee9..f70e5c36d4 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -933,8 +933,10 @@ /dev/random (as well as the pseudo TTY subsystem) to it, but no physical devices such as /dev/sda, system memory /dev/mem, system ports /dev/port and others. This is useful to securely turn off physical device access by the - executed process. Defaults to false. Enabling this option will also remove CAP_MKNOD from - the capability bounding set for the unit (see above), and set DevicePolicy=closed (see + executed process. Defaults to false. Enabling this option will install a system call filter to block low-level + I/O system calls that are grouped in the @raw-io set, will also remove + CAP_MKNOD from the capability bounding set for the unit (see above), and set + DevicePolicy=closed (see systemd.resource-control5 for details). Note that using this setting will disconnect propagation of mounts from the service to the host (propagation in the opposite direction continues to work). This means that this setting may not be used for diff --git a/src/core/execute.c b/src/core/execute.c index 0488ba2ca9..3da7ef3be6 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1429,28 +1429,15 @@ finish: } static int apply_private_devices(Unit *u, const ExecContext *c) { - - static const int device_syscalls[] = { - SCMP_SYS(ioperm), - SCMP_SYS(iopl), - SCMP_SYS(pciconfig_iobase), - SCMP_SYS(pciconfig_read), - SCMP_SYS(pciconfig_write), -#ifdef __NR_s390_pci_mmio_read - SCMP_SYS(s390_pci_mmio_read), -#endif -#ifdef __NR_s390_pci_mmio_write - SCMP_SYS(s390_pci_mmio_write), -#endif - }; - + const SystemCallFilterSet *set; scmp_filter_ctx *seccomp; - unsigned i; + const char *sys; + bool syscalls_found = false; int r; assert(c); - /* If PrivateDevices= is set, also turn off iopl and friends. */ + /* If PrivateDevices= is set, also turn off iopl and all @raw-io syscalls. */ if (skip_seccomp_unavailable(u, "PrivateDevices=")) return 0; @@ -1463,12 +1450,40 @@ static int apply_private_devices(Unit *u, const ExecContext *c) { if (r < 0) goto finish; - for (i = 0; i < ELEMENTSOF(device_syscalls); i++) { + for (set = syscall_filter_sets; set->set_name; set++) + if (streq(set->set_name, "@raw-io")) { + syscalls_found = true; + break; + } + + /* We should never fail here */ + if (!syscalls_found) { + r = -EOPNOTSUPP; + goto finish; + } + + NULSTR_FOREACH(sys, set->value) { + int id; + bool add = true; + +#ifndef __NR_s390_pci_mmio_read + if (streq(sys, "s390_pci_mmio_read")) + add = false; +#endif +#ifndef __NR_s390_pci_mmio_write + if (streq(sys, "s390_pci_mmio_write")) + add = false; +#endif + + if (!add) + continue; + + id = seccomp_syscall_resolve_name(sys); + r = seccomp_rule_add( seccomp, SCMP_ACT_ERRNO(EPERM), - device_syscalls[i], - 0); + id, 0); if (r < 0) goto finish; } -- cgit v1.2.3-54-g00ecf From 615a1f4b26f3c7d10ad9ea638341a6920a6bc435 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 25 Sep 2016 13:04:30 +0200 Subject: test: add CAP_MKNOD tests for PrivateDevices= --- Makefile.am | 2 ++ src/test/test-execute.c | 10 ++++++++++ .../exec-privatedevices-no-capability-mknod.service | 7 +++++++ .../exec-privatedevices-yes-capability-mknod.service | 7 +++++++ 4 files changed, 26 insertions(+) create mode 100644 test/test-execute/exec-privatedevices-no-capability-mknod.service create mode 100644 test/test-execute/exec-privatedevices-yes-capability-mknod.service diff --git a/Makefile.am b/Makefile.am index e823a5c515..66dbbeca0e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1639,6 +1639,8 @@ EXTRA_DIST += \ test/test-execute/exec-personality-aarch64.service \ test/test-execute/exec-privatedevices-no.service \ test/test-execute/exec-privatedevices-yes.service \ + test/test-execute/exec-privatedevices-no-capability-mknod.service \ + test/test-execute/exec-privatedevices-yes-capability-mknod.service \ test/test-execute/exec-privatetmp-no.service \ test/test-execute/exec-privatetmp-yes.service \ test/test-execute/exec-spec-interpolation.service \ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 25489cefbc..2bc1854485 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -133,6 +133,15 @@ static void test_exec_privatedevices(Manager *m) { test(m, "exec-privatedevices-no.service", 0, CLD_EXITED); } +static void test_exec_privatedevices_capabilities(Manager *m) { + if (detect_container() > 0) { + log_notice("testing in container, skipping private device tests"); + return; + } + test(m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED); + test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED); +} + static void test_exec_systemcallfilter(Manager *m) { #ifdef HAVE_SECCOMP if (!is_seccomp_available()) @@ -345,6 +354,7 @@ int main(int argc, char *argv[]) { test_exec_ignoresigpipe, test_exec_privatetmp, test_exec_privatedevices, + test_exec_privatedevices_capabilities, test_exec_privatenetwork, test_exec_systemcallfilter, test_exec_systemcallerrornumber, diff --git a/test/test-execute/exec-privatedevices-no-capability-mknod.service b/test/test-execute/exec-privatedevices-no-capability-mknod.service new file mode 100644 index 0000000000..6d39469da8 --- /dev/null +++ b/test/test-execute/exec-privatedevices-no-capability-mknod.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test CAP_MKNOD capability for PrivateDevices=no + +[Service] +PrivateDevices=no +ExecStart=/bin/sh -x -c 'capsh --print | grep cap_mknod' +Type=oneshot diff --git a/test/test-execute/exec-privatedevices-yes-capability-mknod.service b/test/test-execute/exec-privatedevices-yes-capability-mknod.service new file mode 100644 index 0000000000..fb1fc2875a --- /dev/null +++ b/test/test-execute/exec-privatedevices-yes-capability-mknod.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test CAP_MKNOD capability for PrivateDevices=yes + +[Service] +PrivateDevices=yes +ExecStart=/bin/sh -x -c '! capsh --print | grep cap_mknod' +Type=oneshot -- cgit v1.2.3-54-g00ecf From d23a0044a3ba9ebff5e4e304152fd24ecf113524 Mon Sep 17 00:00:00 2001 From: Torstein Husebø Date: Mon, 26 Sep 2016 11:32:47 +0200 Subject: treewide: fix typos (#4217) --- man/systemd.netdev.xml | 2 +- src/nspawn/nspawn.c | 2 +- src/vconsole/vconsole-setup.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index c8b5a057f8..68ebd5c9f4 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -329,7 +329,7 @@ AgeingTimeSec= This specifies the number of seconds a MAC Address will be kept in - the forwaring database after having a packet received from this MAC Address. + the forwarding database after having a packet received from this MAC Address. diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 0d61d34ebf..5e0207adf0 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1222,7 +1222,7 @@ static int setup_timezone(const char *dest) { if (r < 0) { log_warning("host's /etc/localtime is not a symlink, not updating container timezone."); /* to handle warning, delete /etc/localtime and replace it - * it /w a symbolic link to a time zone data file. + * with a symbolic link to a time zone data file. * * Example: * ln -s /usr/share/zoneinfo/UTC /etc/localtime diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index c0d76f9685..ac4ceb1486 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -75,7 +75,7 @@ static bool is_settable(int fd) { r = ioctl(fd, KDGKBMODE, &curr_mode); /* * Make sure we only adjust consoles in K_XLATE or K_UNICODE mode. - * Oterwise we would (likely) interfere with X11's processing of the + * Otherwise we would (likely) interfere with X11's processing of the * key events. * * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html -- cgit v1.2.3-54-g00ecf From a5ca3649d34c5649ca04fc81000a80e476a81a64 Mon Sep 17 00:00:00 2001 From: Matej Habrnal Date: Mon, 26 Sep 2016 17:28:58 +0200 Subject: coredump: initialize coredump_size in submit_coredump() (#4219) If ulimit is smaller than page_size(), function save_external_coredump() returns -EBADSLT and this causes skipping whole core dumping part in submit_coredump(). Initializing coredump_size to UINT64_MAX prevents evaluating a condition with uninitialized varialbe which leads to calling allocate_journal_field() with coredump_fd = -1 which causes aborting. Signed-off-by: Matej Habrnal --- src/coredump/coredump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 9dea10b3e1..7cc3f3fca2 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -678,7 +678,7 @@ static int submit_coredump( _cleanup_close_ int coredump_fd = -1, coredump_node_fd = -1; _cleanup_free_ char *core_message = NULL, *filename = NULL, *coredump_data = NULL; - uint64_t coredump_size; + uint64_t coredump_size = UINT64_MAX; int r; assert(context); -- cgit v1.2.3-54-g00ecf From eeb084806be1cc7f579d61634fe7b9b3dd5b3df9 Mon Sep 17 00:00:00 2001 From: HATAYAMA Daisuke Date: Tue, 27 Sep 2016 00:36:20 +0900 Subject: journald,ratelimit: fix wrong calculation of burst_modulate() (#4218) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes wrong calculation of burst_modulate(), which now calculates the values smaller than really expected ones if available disk space is strictly more than 1MB. In particular, if available disk space is strictly more than 1MB and strictly less than 16MB, the resulted value becomes smaller than its original one. >>> (math.log2(1*1024**2)-16) / 4 1.0 >>> (math.log2(16*1024**2)-16) / 4 2.0 >>> (math.log2(256*1024**2)-16) / 4 3.0 → This matches the comment in the function. --- src/journal/journald-rate-limit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c index fce799a6ce..d30bf92cec 100644 --- a/src/journal/journald-rate-limit.c +++ b/src/journal/journald-rate-limit.c @@ -190,7 +190,7 @@ static unsigned burst_modulate(unsigned burst, uint64_t available) { if (k <= 20) return burst; - burst = (burst * (k-20)) / 4; + burst = (burst * (k-16)) / 4; /* * Example: -- cgit v1.2.3-54-g00ecf From bc3bb330b8543a31d4a1f488cb782b6ff3519d6a Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 26 Sep 2016 11:45:31 -0400 Subject: machinectl: prefer user@ to --uid=user for shell (#4006) It seems to me that the explicit positional argument should have higher priority than "an option". --- man/machinectl.xml | 11 +++++----- src/machine/machinectl.c | 57 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/man/machinectl.xml b/man/machinectl.xml index 7056fd4204..eaa247714b 100644 --- a/man/machinectl.xml +++ b/man/machinectl.xml @@ -186,12 +186,11 @@ - When used with the shell - command, chooses the user ID to open the interactive shell - session as. If this switch is not specified, defaults to - root. Note that this switch is not - supported for the login command (see - below). + When used with the shell command, chooses the user ID to + open the interactive shell session as. If the argument to the shell + command also specifies an user name, this option is ignored. If the name is not specified + in either way, root will be used by default. Note that this switch is + not supported for the login command (see below). diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index d2ca2ef342..e9de31e184 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -1368,6 +1368,41 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT return ret; } +static int parse_machine_uid(const char *spec, const char **machine, char **uid) { + /* + * Whatever is specified in the spec takes priority over global arguments. + */ + char *_uid = NULL; + const char *_machine = NULL; + + if (spec) { + const char *at; + + at = strchr(spec, '@'); + if (at) { + if (at == spec) + /* Do the same as ssh and refuse "@host". */ + return -EINVAL; + + _machine = at + 1; + _uid = strndup(spec, at - spec); + if (!_uid) + return -ENOMEM; + } else + _machine = spec; + }; + + if (arg_uid && !_uid) { + _uid = strdup(arg_uid); + if (!_uid) + return -ENOMEM; + } + + *uid = _uid; + *machine = isempty(_machine) ? ".host" : _machine; + return 0; +} + static int login_machine(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; @@ -1443,7 +1478,8 @@ static int shell_machine(int argc, char *argv[], void *userdata) { _cleanup_(sd_event_unrefp) sd_event *event = NULL; int master = -1, r; sd_bus *bus = userdata; - const char *pty, *match, *machine, *path, *uid = NULL; + const char *pty, *match, *machine, *path; + _cleanup_free_ char *uid = NULL; assert(bus); @@ -1474,22 +1510,9 @@ static int shell_machine(int argc, char *argv[], void *userdata) { if (r < 0) return log_error_errno(r, "Failed to attach bus to event loop: %m"); - machine = argc < 2 || isempty(argv[1]) ? NULL : argv[1]; - - if (arg_uid) - uid = arg_uid; - else if (machine) { - const char *at; - - at = strchr(machine, '@'); - if (at) { - uid = strndupa(machine, at - machine); - machine = at + 1; - } - } - - if (isempty(machine)) - machine = ".host"; + r = parse_machine_uid(argc >= 2 ? argv[1] : NULL, &machine, &uid); + if (r < 0) + return log_error_errno(r, "Failed to parse machine specification: %m"); match = strjoina("type='signal'," "sender='org.freedesktop.machine1'," -- cgit v1.2.3-54-g00ecf From 00bb64ecfa87c3da13764578e0e65e9b4e72bbf8 Mon Sep 17 00:00:00 2001 From: Paweł Szewczyk Date: Mon, 26 Sep 2016 18:45:47 +0200 Subject: core: Fix USB functionfs activation and clarify its documentation (#4188) There was no certainty about how the path in service file should look like for usb functionfs activation. Because of this it was treated differently in different places, which made this feature unusable. This patch fixes the path to be the *mount directory* of functionfs, not ep0 file path and clarifies in the documentation that ListenUSBFunction should be the location of functionfs mount point, not ep0 file itself. --- man/systemd.socket.xml | 6 +++--- src/core/socket.c | 9 ++------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 26e5d3ce7b..5b6045f69b 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -294,10 +294,10 @@ ListenUSBFunction= Specifies a USB - FunctionFS endpoint location to listen on, for + FunctionFS endpoints location to listen on, for implementation of USB gadget functions. This expects an - absolute file system path as the argument. Behavior otherwise - is very similar to the ListenFIFO= + absolute file system path of functionfs mount point as the argument. + Behavior otherwise is very similar to the ListenFIFO= directive above. Use this to open the FunctionFS endpoint ep0. When using this option, the activated service has to have the diff --git a/src/core/socket.c b/src/core/socket.c index 70d55dd9ed..b9032fa5c9 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1334,14 +1334,9 @@ static int usbffs_select_ep(const struct dirent *d) { static int usbffs_dispatch_eps(SocketPort *p) { _cleanup_free_ struct dirent **ent = NULL; - _cleanup_free_ char *path = NULL; int r, i, n, k; - path = dirname_malloc(p->path); - if (!path) - return -ENOMEM; - - r = scandir(path, &ent, usbffs_select_ep, alphasort); + r = scandir(p->path, &ent, usbffs_select_ep, alphasort); if (r < 0) return -errno; @@ -1356,7 +1351,7 @@ static int usbffs_dispatch_eps(SocketPort *p) { for (i = 0; i < n; ++i) { _cleanup_free_ char *ep = NULL; - ep = path_make_absolute(ent[i]->d_name, path); + ep = path_make_absolute(ent[i]->d_name, p->path); if (!ep) return -ENOMEM; -- cgit v1.2.3-54-g00ecf From b4c6f71b827d41a4af8007b735edf21ef7609f99 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Mon, 26 Sep 2016 13:01:07 -0600 Subject: udev/path_id: introduce support for NVMe devices (#4169) This appends the nvme name and namespace identifier attribute the the PCI path for by-path links. Symlinks like the following are now present: lrwxrwxrwx. 1 root root 13 Sep 16 12:12 pci-0000:01:00.0-nvme-1 -> ../../nvme0n1 lrwxrwxrwx. 1 root root 15 Sep 16 12:12 pci-0000:01:00.0-nvme-1-part1 -> ../../nvme0n1p1 Cc: Michal Sekletar Signed-off-by: Keith Busch --- src/udev/udev-builtin-path_id.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c index 6e9adc6e96..1825ee75a7 100644 --- a/src/udev/udev-builtin-path_id.c +++ b/src/udev/udev-builtin-path_id.c @@ -693,6 +693,15 @@ static int builtin_path_id(struct udev_device *dev, int argc, char *argv[], bool parent = skip_subsystem(parent, "iucv"); supported_transport = true; supported_parent = true; + } else if (streq(subsys, "nvme")) { + const char *nsid = udev_device_get_sysattr_value(dev, "nsid"); + + if (nsid) { + path_prepend(&path, "nvme-%s", nsid); + parent = skip_subsystem(parent, "nvme"); + supported_parent = true; + supported_transport = true; + } } if (parent) -- cgit v1.2.3-54-g00ecf From 9aa8fa701b79b74d118df8dbda0940f74aa8735b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 26 Sep 2016 22:22:28 +0200 Subject: test-bus-creds: are more debugging info This test sometimes fails in semaphore, but not when run interactively, so it's hard to debug. --- src/libsystemd/sd-bus/test-bus-creds.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c index 82237af115..6fdcfa4128 100644 --- a/src/libsystemd/sd-bus/test-bus-creds.c +++ b/src/libsystemd/sd-bus/test-bus-creds.c @@ -27,12 +27,17 @@ int main(int argc, char *argv[]) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; int r; + log_set_max_level(LOG_DEBUG); + log_parse_environment(); + log_open(); + if (cg_all_unified() == -ENOMEDIUM) { - puts("Skipping test: /sys/fs/cgroup/ not available"); + log_info("Skipping test: /sys/fs/cgroup/ not available"); return EXIT_TEST_SKIP; } r = sd_bus_creds_new_from_pid(&creds, 0, _SD_BUS_CREDS_ALL); + log_full_errno(r < 0 ? LOG_ERR : LOG_DEBUG, r, "sd_bus_creds_new_from_pid: %m"); assert_se(r >= 0); bus_creds_dump(creds, NULL, true); -- cgit v1.2.3-54-g00ecf From f78b36f016b5f3e6ce1dfbdfcb78ba227ff8ccac Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 25 Sep 2016 19:24:25 +0200 Subject: test: add tests for simple ReadOnlyPaths= case --- Makefile.am | 1 + src/test/test-execute.c | 5 +++++ test/test-execute/exec-readonlypaths.service | 7 +++++++ 3 files changed, 13 insertions(+) create mode 100644 test/test-execute/exec-readonlypaths.service diff --git a/Makefile.am b/Makefile.am index 66dbbeca0e..0417a0511f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1643,6 +1643,7 @@ EXTRA_DIST += \ test/test-execute/exec-privatedevices-yes-capability-mknod.service \ test/test-execute/exec-privatetmp-no.service \ test/test-execute/exec-privatetmp-yes.service \ + test/test-execute/exec-readonlypaths.service \ test/test-execute/exec-spec-interpolation.service \ test/test-execute/exec-systemcallerrornumber.service \ test/test-execute/exec-systemcallfilter-failing2.service \ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 2bc1854485..aa8544e21a 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -142,6 +142,10 @@ static void test_exec_privatedevices_capabilities(Manager *m) { test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED); } +static void test_exec_readonlypaths(Manager *m) { + test(m, "exec-readonlypaths.service", 0, CLD_EXITED); +} + static void test_exec_systemcallfilter(Manager *m) { #ifdef HAVE_SECCOMP if (!is_seccomp_available()) @@ -355,6 +359,7 @@ int main(int argc, char *argv[]) { test_exec_privatetmp, test_exec_privatedevices, test_exec_privatedevices_capabilities, + test_exec_readonlypaths, test_exec_privatenetwork, test_exec_systemcallfilter, test_exec_systemcallerrornumber, diff --git a/test/test-execute/exec-readonlypaths.service b/test/test-execute/exec-readonlypaths.service new file mode 100644 index 0000000000..6866fdc700 --- /dev/null +++ b/test/test-execute/exec-readonlypaths.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for ReadOnlyPaths= + +[Service] +ReadOnlyPaths=/etc -/i-dont-exist /usr +ExecStart=/bin/sh -x -c 'test ! -w /etc && test ! -w /usr && test ! -e /i-dont-exist && test -w /var' +Type=oneshot -- cgit v1.2.3-54-g00ecf From cdfbd1fb26eb75fe6beca47dce7e5e348b077d97 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 25 Sep 2016 19:50:25 +0200 Subject: test: make sure that {readonly|inaccessible|readwrite}paths disconnect mount propagation Better safe. --- Makefile.am | 3 +++ src/test/test-execute.c | 11 +++++++++++ .../exec-inaccessiblepaths-mount-propagation.service | 7 +++++++ .../test-execute/exec-readonlypaths-mount-propagation.service | 7 +++++++ .../exec-readwritepaths-mount-propagation.service | 7 +++++++ 5 files changed, 35 insertions(+) create mode 100644 test/test-execute/exec-inaccessiblepaths-mount-propagation.service create mode 100644 test/test-execute/exec-readonlypaths-mount-propagation.service create mode 100644 test/test-execute/exec-readwritepaths-mount-propagation.service diff --git a/Makefile.am b/Makefile.am index 0417a0511f..9185bae7b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1644,6 +1644,9 @@ EXTRA_DIST += \ test/test-execute/exec-privatetmp-no.service \ test/test-execute/exec-privatetmp-yes.service \ test/test-execute/exec-readonlypaths.service \ + test/test-execute/exec-readonlypaths-mount-propagation.service \ + test/test-execute/exec-readwritepaths-mount-propagation.service \ + test/test-execute/exec-inaccessiblepaths-mount-propagation.service \ test/test-execute/exec-spec-interpolation.service \ test/test-execute/exec-systemcallerrornumber.service \ test/test-execute/exec-systemcallfilter-failing2.service \ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index aa8544e21a..8b4ff22495 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -144,6 +144,15 @@ static void test_exec_privatedevices_capabilities(Manager *m) { static void test_exec_readonlypaths(Manager *m) { test(m, "exec-readonlypaths.service", 0, CLD_EXITED); + test(m, "exec-readonlypaths-mount-propagation.service", 0, CLD_EXITED); +} + +static void test_exec_readwritepaths(Manager *m) { + test(m, "exec-readwritepaths-mount-propagation.service", 0, CLD_EXITED); +} + +static void test_exec_inaccessiblepaths(Manager *m) { + test(m, "exec-inaccessiblepaths-mount-propagation.service", 0, CLD_EXITED); } static void test_exec_systemcallfilter(Manager *m) { @@ -360,6 +369,8 @@ int main(int argc, char *argv[]) { test_exec_privatedevices, test_exec_privatedevices_capabilities, test_exec_readonlypaths, + test_exec_readwritepaths, + test_exec_inaccessiblepaths, test_exec_privatenetwork, test_exec_systemcallfilter, test_exec_systemcallerrornumber, diff --git a/test/test-execute/exec-inaccessiblepaths-mount-propagation.service b/test/test-execute/exec-inaccessiblepaths-mount-propagation.service new file mode 100644 index 0000000000..23c6ff3f93 --- /dev/null +++ b/test/test-execute/exec-inaccessiblepaths-mount-propagation.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test to make sure that InaccessiblePaths= disconnect mount propagation + +[Service] +InaccessiblePaths=-/i-dont-exist +ExecStart=/bin/sh -x -c 'mkdir -p /TEST; mount -t tmpfs tmpfs /TEST; grep TEST /proc/self/mountinfo && ! grep TEST /proc/$${PPID}/mountinfo && ! grep TEST /proc/1/mountinfo' +Type=oneshot diff --git a/test/test-execute/exec-readonlypaths-mount-propagation.service b/test/test-execute/exec-readonlypaths-mount-propagation.service new file mode 100644 index 0000000000..237cbb2efb --- /dev/null +++ b/test/test-execute/exec-readonlypaths-mount-propagation.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test to make sure that passing ReadOnlyPaths= disconnect mount propagation + +[Service] +ReadOnlyPaths=-/i-dont-exist +ExecStart=/bin/sh -x -c 'mkdir -p /TEST; mount -t tmpfs tmpfs /TEST; grep TEST /proc/self/mountinfo && ! grep TEST /proc/$${PPID}/mountinfo && ! grep TEST /proc/1/mountinfo' +Type=oneshot diff --git a/test/test-execute/exec-readwritepaths-mount-propagation.service b/test/test-execute/exec-readwritepaths-mount-propagation.service new file mode 100644 index 0000000000..466ce6c747 --- /dev/null +++ b/test/test-execute/exec-readwritepaths-mount-propagation.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test to make sure that passing ReadWritePaths= disconnect mount propagation + +[Service] +ReadWritePaths=-/i-dont-exist +ExecStart=/bin/sh -x -c 'mkdir -p /TEST; mount -t tmpfs tmpfs /TEST; grep TEST /proc/self/mountinfo && ! grep TEST /proc/$${PPID}/mountinfo && ! grep TEST /proc/1/mountinfo' +Type=oneshot -- cgit v1.2.3-54-g00ecf From 629abfc23f4e8d61ec0e952182e8200656b2bbe1 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Tue, 27 Sep 2016 19:25:13 +0530 Subject: basic: fix for IPv6 status (#4224) Even if ``` cat /proc/sys/net/ipv6/conf/all/disable_ipv6 1 ``` is disabled cat /proc/net/sockstat6 ``` TCP6: inuse 2 UDP6: inuse 1 UDPLITE6: inuse 0 RAW6: inuse 0 FRAG6: inuse 0 memory 0 ``` Looking for /proc/net/if_inet6 is the right choice. --- src/basic/socket-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 6093e47172..5c829e0e7e 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -441,7 +441,7 @@ const char* socket_address_get_path(const SocketAddress *a) { } bool socket_ipv6_is_supported(void) { - if (access("/proc/net/sockstat6", F_OK) != 0) + if (access("/proc/net/if_inet6", F_OK) != 0) return false; return true; -- cgit v1.2.3-54-g00ecf From 95cbb83c2061237bfd3760c470f6c91cf3ec069b Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Tue, 27 Sep 2016 22:35:48 -0700 Subject: journal: add stdout_stream_scan() comment (#4102) When s->length is zero this function doesn't do anything, note that in a comment. --- src/journal/journald-stream.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c index 4ad16ee41c..bc092f3c12 100644 --- a/src/journal/journald-stream.c +++ b/src/journal/journald-stream.c @@ -393,6 +393,9 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) { p = s->buffer; remaining = s->length; + + /* XXX: This function does nothing if (s->length == 0) */ + for (;;) { char *end; size_t skip; -- cgit v1.2.3-54-g00ecf From 831d3dc8d7ab2719c90485274b537f4a7882fe66 Mon Sep 17 00:00:00 2001 From: Alfie John <33c6c91f3bb4a391082e8a29642cafaf@alfie.wtf> Date: Wed, 28 Sep 2016 09:10:26 +0000 Subject: man: remove duplicate "the" for systemctl --plain (#4230) --- man/systemctl.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index 781de0912a..0bf9e1fd3f 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -613,7 +613,7 @@ When used with list-dependencies, - list-units or list-machines, the + list-units or list-machines, the output is printed as a list instead of a tree, and the bullet circles are omitted. -- cgit v1.2.3-54-g00ecf From fc6cec86136976488e64b8faec2bad6810acfb68 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 26 Sep 2016 23:40:20 +0200 Subject: coredump: remove Storage=both option Back when external storage was initially added in 34c10968cb, this mode of storage was added. This could have made some sense back when XZ compression was used, and an uncompressed core on disk could be used as short-lived cache file which does require costly decompression. But now fast LZ4 compression is used (by default) both internally and externally, so we have duplicated storage, using the same compression and same default maximum core size in both cases, but with different expiration lifetimes. Even the uncompressed-external, compressed-internal mode is not very useful: for small files, decompression with LZ4 is fast enough not to matter, and for large files, decompression is still relatively fast, but the disk-usage penalty is very big. An additional problem with the two modes of storage is that it complicates the code and makes it much harder to return a useful error message to the user if we cannot find the core file, since if we cannot find the file we have to check the internal storage first. This patch drops "both" storage mode. Effectively this means that if somebody configured coredump this way, they will get a warning about an unsupported value for Storage, and the default of "external" will be used. I'm pretty sure that this mode is very rarely used anyway. --- man/coredump.conf.xml | 17 +++--- src/coredump/coredump.c | 6 +- src/coredump/coredumpctl.c | 146 +++++++++++++++++++++------------------------ 3 files changed, 78 insertions(+), 91 deletions(-) diff --git a/man/coredump.conf.xml b/man/coredump.conf.xml index 4f95680a3a..77b4dac51c 100644 --- a/man/coredump.conf.xml +++ b/man/coredump.conf.xml @@ -83,16 +83,13 @@ Storage= - Controls where to store cores. One of - none, external, - journal, and both. When - none, the core dumps will be logged but not - stored permanently. When external (the - default), cores will be stored in /var/lib/systemd/coredump. - When journal, cores will be stored in - the journal and rotated following normal journal - rotation patterns. When both, cores - will be stored in both locations. + Controls where to store cores. One of none, + external, and journal. When + none, the core dumps will be logged (included the traceback if + possible), but not stored permanently. When external (the + default), cores will be stored in /var/lib/systemd/coredump/. + When journal, cores will be stored in the journal and rotated + following normal journal rotation patterns. When cores are stored in the journal, they might be compressed following journal compression settings, see diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 7cc3f3fca2..608b290dd4 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -93,7 +93,6 @@ typedef enum CoredumpStorage { COREDUMP_STORAGE_NONE, COREDUMP_STORAGE_EXTERNAL, COREDUMP_STORAGE_JOURNAL, - COREDUMP_STORAGE_BOTH, _COREDUMP_STORAGE_MAX, _COREDUMP_STORAGE_INVALID = -1 } CoredumpStorage; @@ -102,7 +101,6 @@ static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = { [COREDUMP_STORAGE_NONE] = "none", [COREDUMP_STORAGE_EXTERNAL] = "external", [COREDUMP_STORAGE_JOURNAL] = "journal", - [COREDUMP_STORAGE_BOTH] = "both", }; DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_storage, CoredumpStorage); @@ -247,7 +245,7 @@ static int maybe_remove_external_coredump(const char *filename, uint64_t size) { /* Returns 1 if might remove, 0 if will not remove, < 0 on error. */ - if (IN_SET(arg_storage, COREDUMP_STORAGE_EXTERNAL, COREDUMP_STORAGE_BOTH) && + if (arg_storage == COREDUMP_STORAGE_EXTERNAL && size <= arg_external_size_max) return 0; @@ -740,7 +738,7 @@ log: IOVEC_SET_STRING(iovec[n_iovec++], core_message); /* Optionally store the entire coredump in the journal */ - if (IN_SET(arg_storage, COREDUMP_STORAGE_JOURNAL, COREDUMP_STORAGE_BOTH) && + if (arg_storage == COREDUMP_STORAGE_JOURNAL && coredump_size <= arg_journal_size_max) { size_t sz = 0; diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 8ba7c08eed..67bf502e73 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -580,23 +580,21 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { _cleanup_free_ char *filename = NULL; size_t len; int r; + _cleanup_close_ int fdt = -1; + char *temp = NULL; assert((fd >= 0) != !!path); assert(!!path == !!unlink_temp); - /* Prefer uncompressed file to journal (probably cached) to - * compressed file (probably uncached). */ + /* Look for a coredump on disk first. */ r = sd_journal_get_data(j, "COREDUMP_FILENAME", (const void**) &data, &len); if (r < 0 && r != -ENOENT) - log_warning_errno(r, "Failed to retrieve COREDUMP_FILENAME: %m"); + return log_error_errno(r, "Failed to retrieve COREDUMP_FILENAME: %m"); else if (r == 0) retrieve(data, len, "COREDUMP_FILENAME", &filename); - if (filename && access(filename, R_OK) < 0) { - log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, - "File %s is not readable: %m", filename); - filename = mfree(filename); - } + if (filename && access(filename, R_OK) < 0) + return log_error_errno(errno, "File \"%s\" is not readable: %m", filename); if (filename && !endswith(filename, ".xz") && !endswith(filename, ".lz4")) { if (path) { @@ -605,92 +603,86 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { } return 0; - } else { - _cleanup_close_ int fdt = -1; - char *temp = NULL; + } - if (fd < 0) { - const char *vt; + if (fd < 0) { + const char *vt; - r = var_tmp_dir(&vt); - if (r < 0) - return log_error_errno(r, "Failed to acquire temporary directory path: %m"); + /* Create a temporary file to write the uncompressed core to. */ - temp = strjoin(vt, "/coredump-XXXXXX", NULL); - if (!temp) - return log_oom(); + r = var_tmp_dir(&vt); + if (r < 0) + return log_error_errno(r, "Failed to acquire temporary directory path: %m"); - fdt = mkostemp_safe(temp); - if (fdt < 0) - return log_error_errno(fdt, "Failed to create temporary file: %m"); - log_debug("Created temporary file %s", temp); + temp = strjoin(vt, "/coredump-XXXXXX", NULL); + if (!temp) + return log_oom(); - fd = fdt; - } + fdt = mkostemp_safe(temp); + if (fdt < 0) + return log_error_errno(fdt, "Failed to create temporary file: %m"); + log_debug("Created temporary file %s", temp); - r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len); - if (r == 0) { - ssize_t sz; - - assert(len >= 9); - data += 9; - len -= 9; - - sz = write(fdt, data, len); - if (sz < 0) { - r = log_error_errno(errno, - "Failed to write temporary file: %m"); - goto error; - } - if (sz != (ssize_t) len) { - log_error("Short write to temporary file."); - r = -EIO; - goto error; - } - } else if (filename) { + fd = fdt; + } + + if (filename) { #if defined(HAVE_XZ) || defined(HAVE_LZ4) - _cleanup_close_ int fdf; - - fdf = open(filename, O_RDONLY | O_CLOEXEC); - if (fdf < 0) { - r = log_error_errno(errno, - "Failed to open %s: %m", - filename); - goto error; - } + _cleanup_close_ int fdf; - r = decompress_stream(filename, fdf, fd, -1); - if (r < 0) { - log_error_errno(r, "Failed to decompress %s: %m", filename); - goto error; - } -#else - log_error("Cannot decompress file. Compiled without compression support."); - r = -EOPNOTSUPP; + fdf = open(filename, O_RDONLY | O_CLOEXEC); + if (fdf < 0) { + r = log_error_errno(errno, "Failed to open %s: %m", filename); goto error; -#endif - } else { - if (r == -ENOENT) - log_error("Cannot retrieve coredump from journal or disk."); - else - log_error_errno(r, "Failed to retrieve COREDUMP field: %m"); + } + + r = decompress_stream(filename, fdf, fd, -1); + if (r < 0) { + log_error_errno(r, "Failed to decompress %s: %m", filename); goto error; } +#else + log_error("Cannot decompress file. Compiled without compression support."); + r = -EOPNOTSUPP; + goto error; +#endif + } else { + ssize_t sz; - if (temp) { - *path = temp; - *unlink_temp = true; + r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len); + if (r < 0) + return log_error_errno(r, + r == -ENOENT ? "Core file was not saved for this entry." : + "Failed to retrieve COREDUMP field: %m"); + + assert(len >= 9); + data += 9; + len -= 9; + + sz = write(fdt, data, len); + if (sz < 0) { + r = log_error_errno(errno, "Failed to write temporary file: %m"); + goto error; } + if (sz != (ssize_t) len) { + log_error("Short write to temporary file."); + r = -EIO; + goto error; + } + } - return 0; + if (temp) { + *path = temp; + *unlink_temp = true; + } + return 0; error: - if (temp) { - unlink(temp); - log_debug("Removed temporary file %s", temp); - } - return r; + if (temp) { + unlink(temp); + log_debug("Removed temporary file %s", temp); } + return r; } static int dump_core(sd_journal* j) { -- cgit v1.2.3-54-g00ecf From 954d3a51afc0ee23e84b1aa9c4a9073901cfb766 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 27 Sep 2016 00:10:04 +0200 Subject: coredumpctl: fix handling of files written to fd Added in 9fe13294a9 (by me :[```), and later obfuscated in d0c8806d4ab, if an uncompressed external file or an internally stored coredump was supposed to be written to a file descriptor, nothing would be written. --- src/coredump/coredumpctl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 67bf502e73..05a097076b 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -593,16 +593,16 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { else if (r == 0) retrieve(data, len, "COREDUMP_FILENAME", &filename); - if (filename && access(filename, R_OK) < 0) - return log_error_errno(errno, "File \"%s\" is not readable: %m", filename); + if (filename) { + if (access(filename, R_OK) < 0) + return log_error_errno(errno, "File \"%s\" is not readable: %m", filename); - if (filename && !endswith(filename, ".xz") && !endswith(filename, ".lz4")) { - if (path) { + if (path && !endswith(filename, ".xz") && !endswith(filename, ".lz4")) { *path = filename; filename = NULL; - } - return 0; + return 0; + } } if (fd < 0) { @@ -659,13 +659,13 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { data += 9; len -= 9; - sz = write(fdt, data, len); + sz = write(fd, data, len); if (sz < 0) { - r = log_error_errno(errno, "Failed to write temporary file: %m"); + r = log_error_errno(errno, "Failed to write output: %m"); goto error; } if (sz != (ssize_t) len) { - log_error("Short write to temporary file."); + log_error("Short write to output."); r = -EIO; goto error; } -- cgit v1.2.3-54-g00ecf From cfeead6c77792a8cec83e4d5673698aef3e4d817 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 27 Sep 2016 00:40:55 +0200 Subject: coredumpctl: fix spurious "more than one entry matches" warning sd_journal_previous() returns 0 if it didn't do any move, so the warning was stupidly always printed. --- src/coredump/coredumpctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 05a097076b..45ce31e9bb 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -706,7 +706,7 @@ static int dump_core(sd_journal* j) { return log_error_errno(r, "Coredump retrieval failed: %m"); r = sd_journal_previous(j); - if (r >= 0) + if (r > 0) log_warning("More than one entry matches, ignoring rest."); return 0; -- cgit v1.2.3-54-g00ecf From 554ed50f90a4cea4ed536b1bea598af045953c67 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 27 Sep 2016 01:18:48 +0200 Subject: coredumpctl: report user unit properly --- src/coredump/coredumpctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 45ce31e9bb..0640816989 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -477,7 +477,7 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { if (unit) fprintf(file, " Unit: %s\n", unit); if (user_unit) - fprintf(file, " User Unit: %s\n", unit); + fprintf(file, " User Unit: %s\n", user_unit); if (slice) fprintf(file, " Slice: %s\n", slice); if (session) -- cgit v1.2.3-54-g00ecf From 47f50642075a7a215c9f7b600599cbfee81a2913 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 27 Sep 2016 01:19:01 +0200 Subject: coredumpctl: report corefile presence properly In 'list', show present also for coredumps stored in the journal. In 'status', replace "File" with "Storage" line that is always present. Possible values: Storage: none Storage: journal Storage: /path/to/file (inacessible) Storage: /path/to/file Previously the File field be only present if the file was accessible, so users had to manually extract the file name precisely in the cases where it was needed, i.e. when coredumpctl couldn't access the file. It's much more friendly to always show something. This output is designed for human consumption, so it's better to be a bit verbose. The call to sd_j_set_data_threshold is moved, so that status is always printed with the default of 64k, list uses 4k, and coredump retrieval is done with the limit unset. This should make checking for the presence of the COREDUMP field not too costly. --- src/coredump/coredumpctl.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 0640816989..15ffd56fd1 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -304,7 +304,7 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { _cleanup_free_ char *pid = NULL, *uid = NULL, *gid = NULL, *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL, - *filename = NULL; + *filename = NULL, *coredump = NULL; const void *d; size_t l; usec_t t; @@ -324,6 +324,7 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { retrieve(d, l, "COREDUMP_COMM", &comm); retrieve(d, l, "COREDUMP_CMDLINE", &cmdline); retrieve(d, l, "COREDUMP_FILENAME", &filename); + retrieve(d, l, "COREDUMP", &coredump); } if (!pid && !uid && !gid && !sgnl && !exe && !comm && !cmdline && !filename) { @@ -336,7 +337,7 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { return log_error_errno(r, "Failed to get realtime timestamp: %m"); format_timestamp(buf, sizeof(buf), t); - present = filename && access(filename, F_OK) == 0; + present = (filename && access(filename, F_OK) == 0) || coredump; if (!had_legend && !arg_no_legend) fprintf(file, "%-*s %*s %*s %*s %*s %*s %s\n", @@ -367,7 +368,8 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { *unit = NULL, *user_unit = NULL, *session = NULL, *boot_id = NULL, *machine_id = NULL, *hostname = NULL, *slice = NULL, *cgroup = NULL, *owner_uid = NULL, - *message = NULL, *timestamp = NULL, *filename = NULL; + *message = NULL, *timestamp = NULL, *filename = NULL, + *coredump = NULL; const void *d; size_t l; int r; @@ -391,6 +393,7 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { retrieve(d, l, "COREDUMP_CGROUP", &cgroup); retrieve(d, l, "COREDUMP_TIMESTAMP", ×tamp); retrieve(d, l, "COREDUMP_FILENAME", &filename); + retrieve(d, l, "COREDUMP", &coredump); retrieve(d, l, "_BOOT_ID", &boot_id); retrieve(d, l, "_MACHINE_ID", &machine_id); retrieve(d, l, "_HOSTNAME", &hostname); @@ -505,8 +508,13 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { if (hostname) fprintf(file, " Hostname: %s\n", hostname); - if (filename && access(filename, F_OK) == 0) - fprintf(file, " Coredump: %s\n", filename); + if (filename) + fprintf(file, " Storage: %s%s\n", filename, + access(filename, F_OK) < 0 ? " (inaccessible)" : ""); + else if (coredump) + fprintf(file, " Storage: journal\n"); + else + fprintf(file, " Storage: none\n"); if (message) { _cleanup_free_ char *m = NULL; @@ -586,6 +594,9 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { assert((fd >= 0) != !!path); assert(!!path == !!unlink_temp); + /* We want full data, nothing truncated. */ + sd_journal_set_data_threshold(j, 0); + /* Look for a coredump on disk first. */ r = sd_journal_get_data(j, "COREDUMP_FILENAME", (const void**) &data, &len); if (r < 0 && r != -ENOENT) @@ -828,9 +839,6 @@ int main(int argc, char *argv[]) { } } - /* We want full data, nothing truncated. */ - sd_journal_set_data_threshold(j, 0); - SET_FOREACH(match, matches, it) { r = sd_journal_add_match(j, match, strlen(match)); if (r != 0) { -- cgit v1.2.3-54-g00ecf From 04de587942054c414beda54af303880851b0fa4c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 27 Sep 2016 01:41:38 +0200 Subject: coredumpctl: rework presence reporting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The column for "present" was easy to miss, especially if somebody had no coredumps present at all, in which case the column of spaces of width one wasn't visually distinguished from the neighbouring columns. Replace this with an explicit text, one of: "missing", "journal", "present", "error". $ coredumpctl TIME PID UID GID SIG COREFILE EXE Mon 2016-09-26 22:46:31 CEST 8623 0 0 11 missing /usr/bin/bash Mon 2016-09-26 22:46:35 CEST 8639 1001 1001 11 missing /usr/bin/bash Tue 2016-09-27 01:10:46 CEST 16110 1001 1001 11 journal /usr/bin/bash Tue 2016-09-27 01:13:20 CEST 16290 1001 1001 11 journal /usr/bin/bash Tue 2016-09-27 01:33:48 CEST 17867 1001 1001 11 present /usr/bin/bash Tue 2016-09-27 01:37:55 CEST 18549 0 0 11 error /usr/bin/bash Also, use access(…, R_OK), so that we can report a present but inaccessible file different than a missing one. --- src/coredump/coredumpctl.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 15ffd56fd1..57d18006a4 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -310,7 +310,7 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { usec_t t; char buf[FORMAT_TIMESTAMP_MAX]; int r; - bool present; + const char *present; assert(file); assert(j); @@ -337,7 +337,6 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { return log_error_errno(r, "Failed to get realtime timestamp: %m"); format_timestamp(buf, sizeof(buf), t); - present = (filename && access(filename, F_OK) == 0) || coredump; if (!had_legend && !arg_no_legend) fprintf(file, "%-*s %*s %*s %*s %*s %*s %s\n", @@ -346,16 +345,28 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { 5, "UID", 5, "GID", 3, "SIG", - 1, "PRESENT", + 8, "COREFILE", "EXE"); - fprintf(file, "%-*s %*s %*s %*s %*s %*s %s\n", + if (filename) + if (access(filename, R_OK) == 0) + present = "present"; + else if (errno == ENOENT) + present = "missing"; + else + present = "error"; + else if (coredump) + present = "journal"; + else + present = "none"; + + fprintf(file, "%-*s %*s %*s %*s %*s %-*s %s\n", FORMAT_TIMESTAMP_WIDTH, buf, 6, strna(pid), 5, strna(uid), 5, strna(gid), 3, strna(sgnl), - 1, present ? "*" : "", + 8, present, strna(exe ?: (comm ?: cmdline))); return 0; @@ -510,7 +521,7 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { if (filename) fprintf(file, " Storage: %s%s\n", filename, - access(filename, F_OK) < 0 ? " (inaccessible)" : ""); + access(filename, R_OK) < 0 ? " (inaccessible)" : ""); else if (coredump) fprintf(file, " Storage: journal\n"); else -- cgit v1.2.3-54-g00ecf From 062b99e8be63ba49b80d988da9b00a1d39255496 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 27 Sep 2016 10:52:10 +0200 Subject: coredumpctl: tighten print_field() code Propagate errors properly, so that if we hit oom or an error in the journal, the whole command will fail. This is important when using the output in scripts. Support the output of multiple values for the same field with -F. The journal supports that, and our official commands should too, as far as it makes sense. -F can be used to print user-defined fields (e.g. somebody could use a TAG field with multiple occurences), so we should support that too. That seems better than silently printing the last value found as was done before. We would iterate trying to match the same field with all possible field names. Once we find something, cut the loop short, since we know that nothing else can match. --- src/coredump/coredumpctl.c | 109 +++++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 43 deletions(-) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 57d18006a4..a408adf169 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -280,11 +280,10 @@ static int retrieve(const void *data, free(*var); *var = v; - return 0; + return 1; } -static void print_field(FILE* file, sd_journal *j) { - _cleanup_free_ char *value = NULL; +static int print_field(FILE* file, sd_journal *j) { const void *d; size_t l; @@ -293,13 +292,34 @@ static void print_field(FILE* file, sd_journal *j) { assert(arg_field); - SD_JOURNAL_FOREACH_DATA(j, d, l) - retrieve(d, l, arg_field, &value); + /* A (user-specified) field may appear more than once for a given entry. + * We will print all of the occurences. + * This is different below for fields that systemd-coredump uses, + * because they cannot meaningfully appear more than once. + */ + SD_JOURNAL_FOREACH_DATA(j, d, l) { + _cleanup_free_ char *value = NULL; + int r; + + r = retrieve(d, l, arg_field, &value); + if (r < 0) + return r; + if (r > 0) + fprintf(file, "%s\n", value); + } - if (value) - fprintf(file, "%s\n", value); + return 0; } +#define RETRIEVE(d, l, name, arg) \ + { \ + int _r = retrieve(d, l, name, &arg); \ + if (_r < 0) \ + return _r; \ + if (_r > 0) \ + continue; \ + } + static int print_list(FILE* file, sd_journal *j, int had_legend) { _cleanup_free_ char *pid = NULL, *uid = NULL, *gid = NULL, @@ -316,15 +336,15 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) { assert(j); SD_JOURNAL_FOREACH_DATA(j, d, l) { - retrieve(d, l, "COREDUMP_PID", &pid); - retrieve(d, l, "COREDUMP_UID", &uid); - retrieve(d, l, "COREDUMP_GID", &gid); - retrieve(d, l, "COREDUMP_SIGNAL", &sgnl); - retrieve(d, l, "COREDUMP_EXE", &exe); - retrieve(d, l, "COREDUMP_COMM", &comm); - retrieve(d, l, "COREDUMP_CMDLINE", &cmdline); - retrieve(d, l, "COREDUMP_FILENAME", &filename); - retrieve(d, l, "COREDUMP", &coredump); + RETRIEVE(d, l, "COREDUMP_PID", pid); + RETRIEVE(d, l, "COREDUMP_UID", uid); + RETRIEVE(d, l, "COREDUMP_GID", gid); + RETRIEVE(d, l, "COREDUMP_SIGNAL", sgnl); + RETRIEVE(d, l, "COREDUMP_EXE", exe); + RETRIEVE(d, l, "COREDUMP_COMM", comm); + RETRIEVE(d, l, "COREDUMP_CMDLINE", cmdline); + RETRIEVE(d, l, "COREDUMP_FILENAME", filename); + RETRIEVE(d, l, "COREDUMP", coredump); } if (!pid && !uid && !gid && !sgnl && !exe && !comm && !cmdline && !filename) { @@ -389,26 +409,26 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) { assert(j); SD_JOURNAL_FOREACH_DATA(j, d, l) { - retrieve(d, l, "COREDUMP_PID", &pid); - retrieve(d, l, "COREDUMP_UID", &uid); - retrieve(d, l, "COREDUMP_GID", &gid); - retrieve(d, l, "COREDUMP_SIGNAL", &sgnl); - retrieve(d, l, "COREDUMP_EXE", &exe); - retrieve(d, l, "COREDUMP_COMM", &comm); - retrieve(d, l, "COREDUMP_CMDLINE", &cmdline); - retrieve(d, l, "COREDUMP_UNIT", &unit); - retrieve(d, l, "COREDUMP_USER_UNIT", &user_unit); - retrieve(d, l, "COREDUMP_SESSION", &session); - retrieve(d, l, "COREDUMP_OWNER_UID", &owner_uid); - retrieve(d, l, "COREDUMP_SLICE", &slice); - retrieve(d, l, "COREDUMP_CGROUP", &cgroup); - retrieve(d, l, "COREDUMP_TIMESTAMP", ×tamp); - retrieve(d, l, "COREDUMP_FILENAME", &filename); - retrieve(d, l, "COREDUMP", &coredump); - retrieve(d, l, "_BOOT_ID", &boot_id); - retrieve(d, l, "_MACHINE_ID", &machine_id); - retrieve(d, l, "_HOSTNAME", &hostname); - retrieve(d, l, "MESSAGE", &message); + RETRIEVE(d, l, "COREDUMP_PID", pid); + RETRIEVE(d, l, "COREDUMP_UID", uid); + RETRIEVE(d, l, "COREDUMP_GID", gid); + RETRIEVE(d, l, "COREDUMP_SIGNAL", sgnl); + RETRIEVE(d, l, "COREDUMP_EXE", exe); + RETRIEVE(d, l, "COREDUMP_COMM", comm); + RETRIEVE(d, l, "COREDUMP_CMDLINE", cmdline); + RETRIEVE(d, l, "COREDUMP_UNIT", unit); + RETRIEVE(d, l, "COREDUMP_USER_UNIT", user_unit); + RETRIEVE(d, l, "COREDUMP_SESSION", session); + RETRIEVE(d, l, "COREDUMP_OWNER_UID", owner_uid); + RETRIEVE(d, l, "COREDUMP_SLICE", slice); + RETRIEVE(d, l, "COREDUMP_CGROUP", cgroup); + RETRIEVE(d, l, "COREDUMP_TIMESTAMP", timestamp); + RETRIEVE(d, l, "COREDUMP_FILENAME", filename); + RETRIEVE(d, l, "COREDUMP", coredump); + RETRIEVE(d, l, "_BOOT_ID", boot_id); + RETRIEVE(d, l, "_MACHINE_ID", machine_id); + RETRIEVE(d, l, "_HOSTNAME", hostname); + RETRIEVE(d, l, "MESSAGE", message); } if (need_space) @@ -553,15 +573,15 @@ static int focus(sd_journal *j) { return r; } -static void print_entry(sd_journal *j, unsigned n_found) { +static int print_entry(sd_journal *j, unsigned n_found) { assert(j); if (arg_action == ACTION_INFO) - print_info(stdout, j, n_found); + return print_info(stdout, j, n_found); else if (arg_field) - print_field(stdout, j); + return print_field(stdout, j); else - print_list(stdout, j, n_found); + return print_list(stdout, j, n_found); } static int dump_list(sd_journal *j) { @@ -580,10 +600,13 @@ static int dump_list(sd_journal *j) { if (r < 0) return r; - print_entry(j, 0); + return print_entry(j, 0); } else { - SD_JOURNAL_FOREACH(j) - print_entry(j, n_found++); + SD_JOURNAL_FOREACH(j) { + r = print_entry(j, n_found++); + if (r < 0) + return r; + } if (!arg_field && n_found <= 0) { log_notice("No coredumps found."); -- cgit v1.2.3-54-g00ecf From bb7c5bad4a088a18d102c448caaa72e36bfdb84d Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 27 Sep 2016 00:32:42 +0200 Subject: coredumpctl: delay the "on tty" refusal until as late as possible For the user, if the core file is missing or inaccessible, it is more interesting that the fact that they forgot to pipe to a file. So delay the failure from the check until after we have verified that the file or the COREDUMP field are present. Partially fixes #4161. Also, error reporting on failure was duplicated. save_core() now always prints an error message (because it knows the paths involved, so can the most useful message), and the callers don't have to. --- src/coredump/coredumpctl.c | 66 ++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index a408adf169..0e5351e621 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -617,26 +617,34 @@ static int dump_list(sd_journal *j) { return 0; } -static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { +static int save_core(sd_journal *j, FILE *file, char **path, bool *unlink_temp) { const char *data; _cleanup_free_ char *filename = NULL; size_t len; - int r; + int r, fd; _cleanup_close_ int fdt = -1; char *temp = NULL; - assert((fd >= 0) != !!path); - assert(!!path == !!unlink_temp); - - /* We want full data, nothing truncated. */ - sd_journal_set_data_threshold(j, 0); + assert(!(file && path)); /* At most one can be specified */ + assert(!!path == !!unlink_temp); /* Those must be specified together */ /* Look for a coredump on disk first. */ r = sd_journal_get_data(j, "COREDUMP_FILENAME", (const void**) &data, &len); - if (r < 0 && r != -ENOENT) - return log_error_errno(r, "Failed to retrieve COREDUMP_FILENAME: %m"); - else if (r == 0) + if (r == 0) retrieve(data, len, "COREDUMP_FILENAME", &filename); + else { + if (r != -ENOENT) + return log_error_errno(r, "Failed to retrieve COREDUMP_FILENAME field: %m"); + /* Check that we can have a COREDUMP field. We still haven't set a high + * data threshold, so we'll get a few kilobytes at most. + */ + + r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len); + if (r == -ENOENT) + return log_error_errno(r, "Coredump entry has no core attached (neither internally in the journal nor externally on disk)."); + if (r < 0) + return log_error_errno(r, "Failed to retrieve COREDUMP field: %m"); + } if (filename) { if (access(filename, R_OK) < 0) @@ -650,7 +658,7 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { } } - if (fd < 0) { + if (path) { const char *vt; /* Create a temporary file to write the uncompressed core to. */ @@ -669,6 +677,22 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { log_debug("Created temporary file %s", temp); fd = fdt; + } else { + /* If neither path or file are specified, we will write to stdout. Let's now check + * if stdout is connected to a tty. We checked that the file exists, or that the + * core might be stored in the journal. In this second case, if we found the entry, + * in all likelyhood we will be able to access the COREDUMP= field. In either case, + * we stop before doing any "real" work, i.e. before starting decompression or + * reading from the file or creating temporary files. + */ + if (!file) { + if (on_tty()) + return log_error_errno(ENOTTY, "Refusing to dump core to tty" + " (use shell redirection or specify --output)."); + file = stdout; + } + + fd = fileno(file); } if (filename) { @@ -694,11 +718,12 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { } else { ssize_t sz; + /* We want full data, nothing truncated. */ + sd_journal_set_data_threshold(j, 0); + r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len); if (r < 0) - return log_error_errno(r, - r == -ENOENT ? "Core file was not saved for this entry." : - "Failed to retrieve COREDUMP field: %m"); + return log_error_errno(r, "Failed to retrieve COREDUMP field: %m"); assert(len >= 9); data += 9; @@ -741,14 +766,9 @@ static int dump_core(sd_journal* j) { print_info(arg_output ? stdout : stderr, j, false); - if (on_tty() && !arg_output) { - log_error("Refusing to dump core to tty."); - return -ENOTTY; - } - - r = save_core(j, arg_output ? fileno(arg_output) : STDOUT_FILENO, NULL, NULL); + r = save_core(j, arg_output, NULL, NULL); if (r < 0) - return log_error_errno(r, "Coredump retrieval failed: %m"); + return r; r = sd_journal_previous(j); if (r > 0) @@ -797,9 +817,9 @@ static int run_gdb(sd_journal *j) { return -ENOENT; } - r = save_core(j, -1, &path, &unlink_path); + r = save_core(j, NULL, &path, &unlink_path); if (r < 0) - return log_error_errno(r, "Failed to retrieve core: %m"); + return r; pid = fork(); if (pid < 0) { -- cgit v1.2.3-54-g00ecf From 6e9ef6038f3971ae42657b98d952ed4c1318b4d7 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 27 Sep 2016 11:32:36 +0200 Subject: coredump: log if the core is too large to store or generate backtrace Another fix for #4161. --- src/coredump/coredump.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index 608b290dd4..ecb38bdd8c 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -370,8 +370,7 @@ static int save_external_coredump( #if defined(HAVE_XZ) || defined(HAVE_LZ4) /* If we will remove the coredump anyway, do not compress. */ - if (maybe_remove_external_coredump(NULL, st.st_size) == 0 - && arg_compress) { + if (arg_compress && !maybe_remove_external_coredump(NULL, st.st_size)) { _cleanup_free_ char *fn_compressed = NULL, *tmp_compressed = NULL; _cleanup_close_ int fd_compressed = -1; @@ -703,7 +702,9 @@ static int submit_coredump( coredump_filename = strjoina("COREDUMP_FILENAME=", filename); IOVEC_SET_STRING(iovec[n_iovec++], coredump_filename); - } + } else if (arg_storage == COREDUMP_STORAGE_EXTERNAL) + log_info("The core will not be stored: size %zu is greater than %zu (the configured maximum)", + coredump_size, arg_external_size_max); /* Vacuum again, but exclude the coredump we just created */ (void) coredump_vacuum(coredump_node_fd >= 0 ? coredump_node_fd : coredump_fd, arg_keep_free, arg_max_use); @@ -728,7 +729,9 @@ static int submit_coredump( log_warning("Failed to generate stack trace: %s", dwfl_errmsg(dwfl_errno())); else log_warning_errno(r, "Failed to generate stack trace: %m"); - } + } else + log_debug("Not generating stack trace: core size %zu is greater than %zu (the configured maximum)", + coredump_size, arg_process_size_max); if (!core_message) #endif @@ -738,18 +741,22 @@ log: IOVEC_SET_STRING(iovec[n_iovec++], core_message); /* Optionally store the entire coredump in the journal */ - if (arg_storage == COREDUMP_STORAGE_JOURNAL && - coredump_size <= arg_journal_size_max) { - size_t sz = 0; - - /* Store the coredump itself in the journal */ - - r = allocate_journal_field(coredump_fd, (size_t) coredump_size, &coredump_data, &sz); - if (r >= 0) { - iovec[n_iovec].iov_base = coredump_data; - iovec[n_iovec].iov_len = sz; - n_iovec++; - } + if (arg_storage == COREDUMP_STORAGE_JOURNAL) { + if (coredump_size <= arg_journal_size_max) { + size_t sz = 0; + + /* Store the coredump itself in the journal */ + + r = allocate_journal_field(coredump_fd, (size_t) coredump_size, &coredump_data, &sz); + if (r >= 0) { + iovec[n_iovec].iov_base = coredump_data; + iovec[n_iovec].iov_len = sz; + n_iovec++; + } else + log_warning_errno(r, "Failed to attach the core to the journal entry: %m"); + } else + log_info("The core will not be stored: size %zu is greater than %zu (the configured maximum)", + coredump_size, arg_journal_size_max); } assert(n_iovec <= n_iovec_allocated); -- cgit v1.2.3-54-g00ecf From 73a99163a721d9e96bf7006ecbfb1aefce228c99 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 27 Sep 2016 12:40:54 +0200 Subject: coredump,catalog: give better notice when a core file is truncated coredump had code to check if copy_bytes() hit the max_bytes limit, and refuse further processing in that case. But in 84ee0960443, the return convention for copy_bytes() was changed from -EFBIG to 1 for the case when the limit is hit, so the condition check in coredump couldn't ever trigger. But it seems that *do* want to process such truncated cores [1]. So change the code to detect truncation properly, but instead of returning an error, give a nice log entry. [1] https://github.com/systemd/systemd/issues/3883#issuecomment-239106337 Should fix (or at least alleviate) #3883. --- TODO | 1 + catalog/systemd.catalog.in | 11 +++++++++++ src/coredump/coredump.c | 31 ++++++++++++++++++------------- src/systemd/sd-messages.h | 1 + 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/TODO b/TODO index a47f4c488b..64d530b7d7 100644 --- a/TODO +++ b/TODO @@ -670,6 +670,7 @@ Features: * coredump: - save coredump in Windows/Mozilla minidump format + - when truncating coredumps, also log the full size that the process had, and make a metadata field so we can report truncated coredumps * support crash reporting operation modes (https://live.gnome.org/GnomeOS/Design/Whiteboards/ProblemReporting) diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in index 8de8597fe9..2c72d31290 100644 --- a/catalog/systemd.catalog.in +++ b/catalog/systemd.catalog.in @@ -88,6 +88,17 @@ Process @COREDUMP_PID@ (@COREDUMP_COMM@) crashed and dumped core. This usually indicates a programming error in the crashing program and should be reported to its vendor as a bug. +-- 5aadd8e954dc4b1a8c954d63fd9e1137 +Subject: Core file was truncated to @SIZE_LIMIT@ bytes. +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:coredump.conf(5) + +The process had more memory mapped than the configured maximum for processing +and storage by systemd-coredump(8). Only the first @SIZE_LIMIT@ bytes were +saved. This core might still be usable, but various tools like gdb(1) will warn +about the file being truncated. + -- fc2e22bc6ee647b6b90729ab34a250b1 de Subject: Speicherabbild für Prozess @COREDUMP_PID@ (@COREDUMP_COMM) generiert Defined-By: systemd diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index ecb38bdd8c..db60d0af7a 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -28,9 +28,10 @@ #include #endif +#include "sd-daemon.h" #include "sd-journal.h" #include "sd-login.h" -#include "sd-daemon.h" +#include "sd-messages.h" #include "acl-util.h" #include "alloc-util.h" @@ -133,6 +134,10 @@ static int parse_config(void) { false, NULL); } +static inline uint64_t storage_size_max(void) { + return arg_storage == COREDUMP_STORAGE_EXTERNAL ? arg_external_size_max : arg_journal_size_max; +} + static int fix_acl(int fd, uid_t uid) { #ifdef HAVE_ACL @@ -329,12 +334,13 @@ static int save_external_coredump( /* Is coredumping disabled? Then don't bother saving/processing the coredump. * Anything below PAGE_SIZE cannot give a readable coredump (the kernel uses * ELF_EXEC_PAGESIZE which is not easily accessible, but is usually the same as PAGE_SIZE. */ - log_info("Core dumping has been disabled for process %s (%s).", context[CONTEXT_PID], context[CONTEXT_COMM]); + log_info("Resource limits disable core dumping for process %s (%s).", + context[CONTEXT_PID], context[CONTEXT_COMM]); return -EBADSLT; } /* Never store more than the process configured, or than we actually shall keep or process */ - max_size = MIN(rlimit, MAX(arg_process_size_max, arg_external_size_max)); + max_size = MIN(rlimit, MAX(arg_process_size_max, storage_size_max())); r = make_filename(context, &fn); if (r < 0) @@ -347,19 +353,18 @@ static int save_external_coredump( return log_error_errno(fd, "Failed to create temporary file for coredump %s: %m", fn); r = copy_bytes(input_fd, fd, max_size, false); - if (r == -EFBIG) { - log_error("Coredump of %s (%s) is larger than configured processing limit, refusing.", context[CONTEXT_PID], context[CONTEXT_COMM]); - goto fail; - } else if (IN_SET(r, -EDQUOT, -ENOSPC)) { - log_error("Not enough disk space for coredump of %s (%s), refusing.", context[CONTEXT_PID], context[CONTEXT_COMM]); - goto fail; - } else if (r < 0) { - log_error_errno(r, "Failed to dump coredump to file: %m"); + if (r < 0) { + log_error_errno(r, "Cannot store coredump of %s (%s): %m", context[CONTEXT_PID], context[CONTEXT_COMM]); goto fail; - } + } else if (r == 1) + log_struct(LOG_INFO, + LOG_MESSAGE("Core file was truncated to %zu bytes.", max_size), + "SIZE_LIMIT=%zu", max_size, + LOG_MESSAGE_ID(SD_MESSAGE_TRUNCATED_CORE), + NULL); if (fstat(fd, &st) < 0) { - log_error_errno(errno, "Failed to fstat coredump %s: %m", coredump_tmpfile_name(tmp)); + log_error_errno(errno, "Failed to fstat core file %s: %m", coredump_tmpfile_name(tmp)); goto fail; } diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h index 3c44d63021..79246ae060 100644 --- a/src/systemd/sd-messages.h +++ b/src/systemd/sd-messages.h @@ -40,6 +40,7 @@ _SD_BEGIN_DECLARATIONS; #define SD_MESSAGE_JOURNAL_USAGE SD_ID128_MAKE(ec,38,7f,57,7b,84,4b,8f,a9,48,f3,3c,ad,9a,75,e6) #define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) +#define SD_MESSAGE_TRUNCATED_CORE SD_ID128_MAKE(5a,ad,d8,e9,54,dc,4b,1a,8c,95,4d,63,fd,9e,11,37) #define SD_MESSAGE_SESSION_START SD_ID128_MAKE(8d,45,62,0c,1a,43,48,db,b1,74,10,da,57,c6,0c,66) #define SD_MESSAGE_SESSION_STOP SD_ID128_MAKE(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a) -- cgit v1.2.3-54-g00ecf From 531ac2b2349da02acc9c382849758e07eb92b020 Mon Sep 17 00:00:00 2001 From: Jorge Niedbalski Date: Wed, 28 Sep 2016 18:25:50 -0300 Subject: If the notification message length is 0, ignore the message (#4237) Fixes #4234. Signed-off-by: Jorge Niedbalski --- src/core/manager.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/manager.c b/src/core/manager.c index fa8deb9b1b..43e231c328 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1721,6 +1721,10 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t return -errno; } + if (n == 0) { + log_debug("Got zero-length notification message. Ignoring."); + return 0; + } CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { -- cgit v1.2.3-54-g00ecf From 9987750e7a4c62e0eb8473603150596ba7c3a015 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Thu, 29 Sep 2016 19:44:34 +0200 Subject: pid1: don't return any error in manager_dispatch_notify_fd() (#4240) If manager_dispatch_notify_fd() fails and returns an error then the handling of service notifications will be disabled entirely leading to a compromised system. For example pid1 won't be able to receive the WATCHDOG messages anymore and will kill all services supposed to send such messages. --- src/core/manager.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 43e231c328..5704005a0c 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1716,10 +1716,14 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); if (n < 0) { - if (errno == EAGAIN || errno == EINTR) - return 0; + if (!IN_SET(errno, EAGAIN, EINTR)) + log_error("Failed to receive notification message: %m"); - return -errno; + /* It's not an option to return an error here since it + * would disable the notification handler entirely. Services + * wouldn't be able to send the WATCHDOG message for + * example... */ + return 0; } if (n == 0) { log_debug("Got zero-length notification message. Ignoring."); @@ -1746,7 +1750,8 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r = fdset_new_array(&fds, fd_array, n_fds); if (r < 0) { close_many(fd_array, n_fds); - return log_oom(); + log_oom(); + return 0; } } -- cgit v1.2.3-54-g00ecf From 8523bf7dd514a3a2c6114b7b8fb8f308b4f09fc4 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 29 Sep 2016 16:06:02 +0200 Subject: pid1: process zero-length notification messages again This undoes 531ac2b234. I acked that patch without looking at the code carefully enough. There are two problems: - we want to process the fds anyway - in principle empty notification messages are valid, and we should process them as usual, including logging using log_unit_debug(). --- src/core/manager.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 5704005a0c..1ea6539ebc 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1657,13 +1657,12 @@ static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, ui return 0; } -static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, const char *buf, size_t n, FDSet *fds) { +static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, const char *buf, FDSet *fds) { _cleanup_strv_free_ char **tags = NULL; assert(m); assert(u); assert(buf); - assert(n > 0); tags = strv_split(buf, "\n\r"); if (!tags) { @@ -1725,10 +1724,6 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t * example... */ return 0; } - if (n == 0) { - log_debug("Got zero-length notification message. Ignoring."); - return 0; - } CMSG_FOREACH(cmsg, &msghdr) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { @@ -1765,25 +1760,27 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t return 0; } + /* The message should be a string. Here we make sure it's NUL-terminated, + * but only the part until first NUL will be used anyway. */ buf[n] = 0; /* Notify every unit that might be interested, but try * to avoid notifying the same one multiple times. */ u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid); if (u1) { - manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds); + manager_invoke_notify_message(m, u1, ucred->pid, buf, fds); found = true; } u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid)); if (u2 && u2 != u1) { - manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds); + manager_invoke_notify_message(m, u2, ucred->pid, buf, fds); found = true; } u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(ucred->pid)); if (u3 && u3 != u2 && u3 != u1) { - manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds); + manager_invoke_notify_message(m, u3, ucred->pid, buf, fds); found = true; } -- cgit v1.2.3-54-g00ecf From a86b76753d7868c2d05f046f601bc7dc89fc2203 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 29 Sep 2016 16:07:41 +0200 Subject: pid1: more informative error message for ignored notifications It's probably easier to diagnose a bad notification message if the contents are printed. But still, do anything only if debugging is on. --- src/core/manager.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 1ea6539ebc..0f95bf49fb 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1672,8 +1672,14 @@ static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, const if (UNIT_VTABLE(u)->notify_message) UNIT_VTABLE(u)->notify_message(u, pid, tags, fds); - else - log_unit_debug(u, "Got notification message for unit. Ignoring."); + else if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) { + _cleanup_free_ char *x = NULL, *y = NULL; + + x = cescape(buf); + if (x) + y = ellipsize(x, 20, 90); + log_unit_debug(u, "Got notification message \"%s\", ignoring.", strnull(y)); + } } static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { -- cgit v1.2.3-54-g00ecf From b9fe94cad99968a58e169592d999306fd059eb14 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Fri, 30 Sep 2016 09:30:08 +0200 Subject: resolved: don't query domain-limited DNS servers for other domains (#3621) DNS servers which have route-only domains should only be used for the specified domains. Routing queries about other domains there is a privacy violation, prone to fail (as that DNS server was not meant to be used for other domains), and puts unnecessary load onto that server. Introduce a new helper function dns_server_limited_domains() that checks if the DNS server should only be used for some selected domains, i. e. has some route-only domains without "~.". Use that when determining whether to query it in the scope, and when writing resolv.conf. Extend the test_route_only_dns() case to ensure that the DNS server limited to ~company does not appear in resolv.conf. Add test_route_only_dns_all_domains() to ensure that a server that also has ~. does appear in resolv.conf as global name server. These reproduce #3420. Add a new test_resolved_domain_restricted_dns() test case that verifies that domain-limited DNS servers are only being used for those domains. This reproduces #3421. Clarify what a "routing domain" is in the manpage. Fixes #3420 Fixes #3421 --- man/systemd.network.xml | 4 +- src/resolve/resolved-dns-scope.c | 8 +++ src/resolve/resolved-dns-server.c | 21 +++++++ src/resolve/resolved-dns-server.h | 2 + src/resolve/resolved-resolv-conf.c | 10 ++++ test/networkd-test.py | 110 ++++++++++++++++++++++++++++++++++++- 6 files changed, 152 insertions(+), 3 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 9c1b10fc5c..08dd157e31 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -475,8 +475,8 @@ The specified domains are also used for routing of DNS queries: look-ups for host names ending in the domains specified here are preferably routed to the DNS servers configured for this interface. If a domain - name is prefixed with ~, the domain name becomes a pure "routing" domain, is used for - DNS query routing purposes only and is not used in the described domain search logic. By specifying a + name is prefixed with ~, the domain name becomes a pure "routing" domain, the DNS server + is used for the given domain names only and is not used in the described domain search logic. By specifying a routing domain of ~. (the tilde indicating definition of a routing domain, the dot referring to the DNS root domain which is the implied suffix of all valid DNS names) it is possible to route all DNS traffic preferably to the DNS server specified for this interface. The route domain logic is diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index ed0c6aa105..03811ac8e7 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -407,6 +407,7 @@ int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *add DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) { DnsSearchDomain *d; + DnsServer *dns_server; assert(s); assert(domain); @@ -447,6 +448,13 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co if (dns_name_endswith(domain, d->name) > 0) return DNS_SCOPE_YES; + /* If the DNS server has route-only domains, don't send other requests + * to it. This would be a privacy violation, will most probably fail + * anyway, and adds unnecessary load. */ + dns_server = dns_scope_get_dns_server(s); + if (dns_server && dns_server_limited_domains(dns_server)) + return DNS_SCOPE_NO; + switch (s->protocol) { case DNS_PROTOCOL_DNS: diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 9b7b471600..97cc8c0e09 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -576,6 +576,27 @@ void dns_server_warn_downgrade(DnsServer *server) { server->warned_downgrade = true; } +bool dns_server_limited_domains(DnsServer *server) +{ + DnsSearchDomain *domain; + bool domain_restricted = false; + + /* Check if the server has route-only domains without ~., i. e. whether + * it should only be used for particular domains */ + if (!server->link) + return false; + + LIST_FOREACH(domains, domain, server->link->search_domains) + if (domain->route_only) { + domain_restricted = true; + /* ~. means "any domain", thus it is a global server */ + if (streq(DNS_SEARCH_DOMAIN_NAME(domain), ".")) + return false; + } + + return domain_restricted; +} + static void dns_server_hash_func(const void *p, struct siphash *state) { const DnsServer *s = p; diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h index c1732faffd..83e288a202 100644 --- a/src/resolve/resolved-dns-server.h +++ b/src/resolve/resolved-dns-server.h @@ -128,6 +128,8 @@ bool dns_server_dnssec_supported(DnsServer *server); void dns_server_warn_downgrade(DnsServer *server); +bool dns_server_limited_domains(DnsServer *server); + DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr, int ifindex); void dns_server_unlink_all(DnsServer *first); diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index 31b25ca50f..801014caf5 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -154,6 +154,16 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) { return; } + /* Check if the DNS server is limited to particular domains; + * resolv.conf does not have a syntax to express that, so it must not + * appear as a global name server to avoid routing unrelated domains to + * it (which is a privacy violation, will most probably fail anyway, + * and adds unnecessary load) */ + if (dns_server_limited_domains(s)) { + log_debug("DNS server %s has route-only domains, not using as global name server", dns_server_string(s)); + return; + } + if (*count == MAXNS) fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f); (*count)++; diff --git a/test/networkd-test.py b/test/networkd-test.py index baa1dc2a47..3091722fc1 100755 --- a/test/networkd-test.py +++ b/test/networkd-test.py @@ -250,6 +250,38 @@ Domains= ~company''') self.assertNotRegex(contents, 'search.*company') # our global server should appear self.assertIn('nameserver 192.168.5.1\n', contents) + # should not have domain-restricted server as global server + self.assertNotIn('nameserver 192.168.42.1\n', contents) + + def test_route_only_dns_all_domains(self): + with open('/run/systemd/network/myvpn.netdev', 'w') as f: + f.write('''[NetDev] +Name=dummy0 +Kind=dummy +MACAddress=12:34:56:78:9a:bc''') + with open('/run/systemd/network/myvpn.network', 'w') as f: + f.write('''[Match] +Name=dummy0 +[Network] +Address=192.168.42.100 +DNS=192.168.42.1 +Domains= ~company ~.''') + self.addCleanup(os.remove, '/run/systemd/network/myvpn.netdev') + self.addCleanup(os.remove, '/run/systemd/network/myvpn.network') + + self.do_test(coldplug=True, ipv6=False, + extra_opts='IPv6AcceptRouterAdvertisements=False') + + with open(RESOLV_CONF) as f: + contents = f.read() + + # ~company is not a search domain, only a routing domain + self.assertNotRegex(contents, 'search.*company') + + # our global server should appear + self.assertIn('nameserver 192.168.5.1\n', contents) + # should have company server as global server due to ~. + self.assertIn('nameserver 192.168.42.1\n', contents) @unittest.skipUnless(have_dnsmasq, 'dnsmasq not installed') @@ -260,7 +292,7 @@ class DnsmasqClientTest(ClientTestBase, unittest.TestCase): super().setUp() self.dnsmasq = None - def create_iface(self, ipv6=False): + def create_iface(self, ipv6=False, dnsmasq_opts=None): '''Create test interface with DHCP server behind it''' # add veth pair @@ -281,6 +313,8 @@ class DnsmasqClientTest(ClientTestBase, unittest.TestCase): extra_opts = ['--enable-ra', '--dhcp-range=2600::10,2600::20'] else: extra_opts = [] + if dnsmasq_opts: + extra_opts += dnsmasq_opts self.dnsmasq = subprocess.Popen( ['dnsmasq', '--keep-in-foreground', '--log-queries', '--log-facility=' + self.dnsmasq_log, '--conf-file=/dev/null', @@ -305,6 +339,80 @@ class DnsmasqClientTest(ClientTestBase, unittest.TestCase): with open(self.dnsmasq_log) as f: sys.stdout.write('\n\n---- dnsmasq log ----\n%s\n------\n\n' % f.read()) + def test_resolved_domain_restricted_dns(self): + '''resolved: domain-restricted DNS servers''' + + # create interface for generic connections; this will map all DNS names + # to 192.168.42.1 + self.create_iface(dnsmasq_opts=['--address=/#/192.168.42.1']) + self.writeConfig('/run/systemd/network/general.network', '''\ +[Match] +Name=%s +[Network] +DHCP=ipv4 +IPv6AcceptRA=False''' % self.iface) + + # create second device/dnsmasq for a .company/.lab VPN interface + # static IPs for simplicity + subprocess.check_call(['ip', 'link', 'add', 'name', 'testvpnclient', 'type', + 'veth', 'peer', 'name', 'testvpnrouter']) + self.addCleanup(subprocess.call, ['ip', 'link', 'del', 'dev', 'testvpnrouter']) + subprocess.check_call(['ip', 'a', 'flush', 'dev', 'testvpnrouter']) + subprocess.check_call(['ip', 'a', 'add', '10.241.3.1/24', 'dev', 'testvpnrouter']) + subprocess.check_call(['ip', 'link', 'set', 'testvpnrouter', 'up']) + + vpn_dnsmasq_log = os.path.join(self.workdir, 'dnsmasq-vpn.log') + vpn_dnsmasq = subprocess.Popen( + ['dnsmasq', '--keep-in-foreground', '--log-queries', + '--log-facility=' + vpn_dnsmasq_log, '--conf-file=/dev/null', + '--dhcp-leasefile=/dev/null', '--bind-interfaces', + '--interface=testvpnrouter', '--except-interface=lo', + '--address=/math.lab/10.241.3.3', '--address=/cantina.company/10.241.4.4']) + self.addCleanup(vpn_dnsmasq.wait) + self.addCleanup(vpn_dnsmasq.kill) + + self.writeConfig('/run/systemd/network/vpn.network', '''\ +[Match] +Name=testvpnclient +[Network] +IPv6AcceptRA=False +Address=10.241.3.2/24 +DNS=10.241.3.1 +Domains= ~company ~lab''') + + subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) + subprocess.check_call([self.networkd_wait_online, '--interface', self.iface, + '--interface=testvpnclient', '--timeout=20']) + + # ensure we start fresh with every test + subprocess.check_call(['systemctl', 'restart', 'systemd-resolved']) + + # test vpnclient specific domains; these should *not* be answered by + # the general DNS + out = subprocess.check_output(['systemd-resolve', 'math.lab']) + self.assertIn(b'math.lab: 10.241.3.3', out) + out = subprocess.check_output(['systemd-resolve', 'kettle.cantina.company']) + self.assertIn(b'kettle.cantina.company: 10.241.4.4', out) + + # test general domains + out = subprocess.check_output(['systemd-resolve', 'megasearch.net']) + self.assertIn(b'megasearch.net: 192.168.42.1', out) + + with open(self.dnsmasq_log) as f: + general_log = f.read() + with open(vpn_dnsmasq_log) as f: + vpn_log = f.read() + + # VPN domains should only be sent to VPN DNS + self.assertRegex(vpn_log, 'query.*math.lab') + self.assertRegex(vpn_log, 'query.*cantina.company') + self.assertNotIn('lab', general_log) + self.assertNotIn('company', general_log) + + # general domains should not be sent to the VPN DNS + self.assertRegex(general_log, 'query.*megasearch.net') + self.assertNotIn('megasearch.net', vpn_log) + class NetworkdClientTest(ClientTestBase, unittest.TestCase): '''Test networkd client against networkd server''' -- cgit v1.2.3-54-g00ecf From 82936769a81cf923c9e98fa350138eb6618bd1eb Mon Sep 17 00:00:00 2001 From: Elias Probst Date: Fri, 30 Sep 2016 13:25:25 +0200 Subject: networkd: fix "parametres" typo (#4244) --- src/network/networkd-netdev-bridge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/networkd-netdev-bridge.c b/src/network/networkd-netdev-bridge.c index bdbea7d770..002ad94210 100644 --- a/src/network/networkd-netdev-bridge.c +++ b/src/network/networkd-netdev-bridge.c @@ -39,7 +39,7 @@ static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, vo return 1; } - log_netdev_debug(netdev, "Bridge parametres set success"); + log_netdev_debug(netdev, "Bridge parameters set success"); return 1; } -- cgit v1.2.3-54-g00ecf From c4bee3c40e13b27f1a33f67a9c5692d042b463d7 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 30 Sep 2016 13:34:10 +0200 Subject: core: get rid of unneeded state variable No functional change. --- src/core/manager.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 0f95bf49fb..26a3152484 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1705,7 +1705,6 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t struct cmsghdr *cmsg; struct ucred *ucred = NULL; - bool found = false; Unit *u1, *u2, *u3; int r, *fd_array = NULL; unsigned n_fds = 0; @@ -1773,24 +1772,18 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t /* Notify every unit that might be interested, but try * to avoid notifying the same one multiple times. */ u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid); - if (u1) { + if (u1) manager_invoke_notify_message(m, u1, ucred->pid, buf, fds); - found = true; - } u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid)); - if (u2 && u2 != u1) { + if (u2 && u2 != u1) manager_invoke_notify_message(m, u2, ucred->pid, buf, fds); - found = true; - } u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(ucred->pid)); - if (u3 && u3 != u2 && u3 != u1) { + if (u3 && u3 != u2 && u3 != u1) manager_invoke_notify_message(m, u3, ucred->pid, buf, fds); - found = true; - } - if (!found) + if (!u1 && !u2 && !u3) log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid); if (fdset_size(fds) > 0) -- cgit v1.2.3-54-g00ecf From 5fd2c135f1fd6b5147de54531940f398c6213b0c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 30 Sep 2016 13:35:07 +0200 Subject: core: update warning message "closing all" might suggest that _all_ fds received with the notification message will be closed. Reword the message to clarify that only the "unused" ones will be closed. --- src/core/manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/manager.c b/src/core/manager.c index 26a3152484..e63b31bdf3 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1787,7 +1787,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid); if (fdset_size(fds) > 0) - log_warning("Got auxiliary fds with notification message, closing all."); + log_warning("Got extra auxiliary fds with notification message, closing them."); return 0; } -- cgit v1.2.3-54-g00ecf From 46c7a7ac874fd97e28d8d7e0be15f2bf15b2a430 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Fri, 16 Sep 2016 10:57:06 +0200 Subject: nss-resolve: simplify error handling Handle general errors from the resolved call in _nss_resolve_gethostbyaddr2_r() the same say as in the other variants: Just "goto fail" as that does exactly the same. --- src/nss-resolve/nss-resolve.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c index 5ce10f1cbd..5db83e5d0e 100644 --- a/src/nss-resolve/nss-resolve.c +++ b/src/nss-resolve/nss-resolve.c @@ -558,9 +558,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r( goto fallback; - *errnop = -r; - *h_errnop = NO_RECOVERY; - return NSS_STATUS_UNAVAIL; + goto fail; } r = sd_bus_message_enter_container(reply, 'a', "(is)"); -- cgit v1.2.3-54-g00ecf From 4484e1792b64b01614f04b7bde97bf019f601bf9 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Sat, 1 Oct 2016 16:54:45 +0200 Subject: man: drop myhostname from recommended nsswitch host configuration resolve includes myhostname functionality, so there is no need to add it again. --- man/nss-resolve.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/nss-resolve.xml b/man/nss-resolve.xml index e6cc1d982a..33f1f28a8c 100644 --- a/man/nss-resolve.xml +++ b/man/nss-resolve.xml @@ -85,7 +85,7 @@ group: compat mymachines systemd shadow: compat -hosts: files mymachines resolve myhostname +hosts: files mymachines resolve networks: files protocols: db files -- cgit v1.2.3-54-g00ecf From d7247512a904f1dd74125859d8da66166c2a6933 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Fri, 16 Sep 2016 08:27:39 +0200 Subject: nss-resolve: return NOTFOUND instead of UNAVAIL on resolution errors It needs to be possible to tell apart "the nss-resolve module does not exist" (which can happen when running foreign-architecture programs) from "the queried DNS name failed DNSSEC validation" or other errors. So return NOTFOUND for these cases too, and only keep UNAVAIL for the cases where we cannot handle the given address family. This makes it possible to configure a fallback to "dns" without breaking DNSSEC, with "resolve [!UNAVAIL=return] dns". Add this to the manpage. This does not change behaviour if resolved is not running, as that already falls back to the "dns" glibc module. Fixes #4157 --- man/nss-resolve.xml | 4 +++- src/nss-resolve/nss-resolve.c | 9 ++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/man/nss-resolve.xml b/man/nss-resolve.xml index 33f1f28a8c..d66e8ba521 100644 --- a/man/nss-resolve.xml +++ b/man/nss-resolve.xml @@ -85,7 +85,7 @@ group: compat mymachines systemd shadow: compat -hosts: files mymachines resolve +hosts: files mymachines resolve [!UNAVAIL=return] dns networks: files protocols: db files @@ -95,6 +95,8 @@ rpc: db files netgroup: nis + This keeps the dns module as a fallback for cases where the nss-resolve + module is not installed. diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c index 5db83e5d0e..eea91e3e88 100644 --- a/src/nss-resolve/nss-resolve.c +++ b/src/nss-resolve/nss-resolve.c @@ -279,9 +279,12 @@ fallback: } fail: + /* When we arrive here, resolved runs and has answered (fallback to + * "dns" is handled earlier). So we have a definitive "no" answer and + * should not fall back to subsequent NSS modules via "UNAVAIL". */ *errnop = -r; *h_errnop = NO_RECOVERY; - return NSS_STATUS_UNAVAIL; + return NSS_STATUS_NOTFOUND; } enum nss_status _nss_resolve_gethostbyname3_r( @@ -476,7 +479,7 @@ fallback: fail: *errnop = -r; *h_errnop = NO_RECOVERY; - return NSS_STATUS_UNAVAIL; + return NSS_STATUS_NOTFOUND; } enum nss_status _nss_resolve_gethostbyaddr2_r( @@ -666,7 +669,7 @@ fallback: fail: *errnop = -r; *h_errnop = NO_RECOVERY; - return NSS_STATUS_UNAVAIL; + return NSS_STATUS_NOTFOUND; } NSS_GETHOSTBYNAME_FALLBACKS(resolve); -- cgit v1.2.3-54-g00ecf From c49b50113e1af56149e3dfbd96215c29b06eb4e8 Mon Sep 17 00:00:00 2001 From: Stefan Schweter Date: Sat, 1 Oct 2016 17:11:38 +0200 Subject: man: update mx record example (#4257) --- man/systemd-resolve.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemd-resolve.xml b/man/systemd-resolve.xml index 24f499c282..2bc917ac26 100644 --- a/man/systemd-resolve.xml +++ b/man/systemd-resolve.xml @@ -339,7 +339,7 @@ www.0pointer.net: 2a01:238:43ed:c300:10c3:bcf3:3266:da74 - Retrieve the MX record of the <literal>0pointer.net</literal> domain + Retrieve the MX record of the <literal>yahoo.com</literal> domain $ systemd-resolve -t MX yahoo.com --legend=no yahoo.com. IN MX 1 mta7.am0.yahoodns.net -- cgit v1.2.3-54-g00ecf From 93a0884126146361ca078ec627da2cf766205a1c Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Mon, 5 Sep 2016 13:14:36 +0200 Subject: systemctl: Add --wait option to wait until started units terminate again Fixes #3830 --- man/systemctl.xml | 15 +++- src/systemctl/systemctl.c | 168 ++++++++++++++++++++++++++++++++++++++++- test/TEST-03-JOBS/test-jobs.sh | 28 +++++++ 3 files changed, 207 insertions(+), 4 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index 0bf9e1fd3f..e738b5aecd 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -363,7 +363,20 @@ to finish. If this is not specified, the job will be verified, enqueued and systemctl will wait until the unit's start-up is completed. By passing this - argument, it is only verified and enqueued. + argument, it is only verified and enqueued. This option may not be + combined with . + + + + + + + + Synchronously wait for started units to terminate again. + This option may not be combined with . + Note that this will wait forever if any given unit never terminates + (by itself or by getting stopped explicitly); particularly services + which use RemainAfterExit=yes. diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 5337561664..bb6002e8ef 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -118,6 +118,7 @@ static enum dependency { } arg_dependency = DEPENDENCY_FORWARD; static const char *arg_job_mode = "replace"; static UnitFileScope arg_scope = UNIT_FILE_SYSTEM; +static bool arg_wait = false; static bool arg_no_block = false; static bool arg_no_legend = false; static bool arg_no_pager = false; @@ -2679,13 +2680,86 @@ static const char *method_to_verb(const char *method) { return "n/a"; } +typedef struct { + sd_bus_slot *match; + sd_event *event; + Set *unit_paths; + bool any_failed; +} WaitContext; + +static void wait_context_free(WaitContext *c) { + c->match = sd_bus_slot_unref(c->match); + c->event = sd_event_unref(c->event); + c->unit_paths = set_free(c->unit_paths); +} + +static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + WaitContext *c = userdata; + const char *path; + int r; + + path = sd_bus_message_get_path(m); + if (!set_contains(c->unit_paths, path)) + return 0; + + /* Check if ActiveState changed to inactive/failed */ + /* (s interface, a{sv} changed_properties, as invalidated_properties) */ + r = sd_bus_message_skip(m, "s"); + if (r < 0) + return bus_log_parse_error(r); + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { + const char *s; + bool is_failed; + + r = sd_bus_message_read(m, "s", &s); + if (r < 0) + return bus_log_parse_error(r); + if (streq(s, "ActiveState")) { + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "s"); + if (r < 0) + return bus_log_parse_error(r); + r = sd_bus_message_read(m, "s", &s); + if (r < 0) + return bus_log_parse_error(r); + is_failed = streq(s, "failed"); + if (streq(s, "inactive") || is_failed) { + log_debug("%s became %s, dropping from --wait tracking", path, s); + set_remove(c->unit_paths, path); + c->any_failed |= is_failed; + } else + log_debug("ActiveState on %s changed to %s", path, s); + break; /* no need to dissect the rest of the message */ + } else { + /* other property */ + r = sd_bus_message_skip(m, "v"); + if (r < 0) + return bus_log_parse_error(r); + } + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + } + if (r < 0) + return bus_log_parse_error(r); + + if (set_isempty(c->unit_paths)) + sd_event_exit(c->event, EXIT_SUCCESS); + + return 0; +} + static int start_unit_one( sd_bus *bus, const char *method, const char *name, const char *mode, sd_bus_error *error, - BusWaitForJobs *w) { + BusWaitForJobs *w, + WaitContext *wait_context) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *path; @@ -2696,6 +2770,40 @@ static int start_unit_one( assert(mode); assert(error); + if (wait_context) { + _cleanup_free_ char *unit_path = NULL; + const char* mt; + + log_debug("Watching for property changes of %s", name); + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "RefUnit", + error, + NULL, + "s", name); + if (r < 0) + return log_error_errno(r, "Failed to RefUnit %s: %s", name, bus_error_message(error, r)); + + unit_path = unit_dbus_path_from_name(name); + if (!unit_path) + return log_oom(); + + r = set_put_strdup(wait_context->unit_paths, unit_path); + if (r < 0) + return log_error_errno(r, "Failed to add unit path %s to set: %m", unit_path); + + mt = strjoina("type='signal'," + "interface='org.freedesktop.DBus.Properties'," + "path='", unit_path, "'," + "member='PropertiesChanged'"); + r = sd_bus_add_match(bus, &wait_context->match, mt, on_properties_changed, wait_context); + if (r < 0) + return log_error_errno(r, "Failed to add match for PropertiesChanged signal: %m"); + } + log_debug("Calling manager for %s on %s, %s", method, name, mode); r = sd_bus_call_method( @@ -2841,10 +2949,18 @@ static int start_unit(int argc, char *argv[], void *userdata) { const char *method, *mode, *one_name, *suffix = NULL; _cleanup_strv_free_ char **names = NULL; sd_bus *bus; + _cleanup_(wait_context_free) WaitContext wait_context = {}; char **name; int r = 0; - r = acquire_bus(BUS_MANAGER, &bus); + if (arg_wait && !strstr(argv[0], "start")) { + log_error("--wait may only be used with a command that starts units."); + return -EINVAL; + } + + /* we cannot do sender tracking on the private bus, so we need the full + * one for RefUnit to implement --wait */ + r = acquire_bus(arg_wait ? BUS_FULL : BUS_MANAGER, &bus); if (r < 0) return r; @@ -2888,11 +3004,36 @@ static int start_unit(int argc, char *argv[], void *userdata) { return log_error_errno(r, "Could not watch jobs: %m"); } + if (arg_wait) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + wait_context.unit_paths = set_new(&string_hash_ops); + if (!wait_context.unit_paths) + return log_oom(); + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Subscribe", + &error, + NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to enable subscription: %s", bus_error_message(&error, r)); + r = sd_event_default(&wait_context.event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + r = sd_bus_attach_event(bus, wait_context.event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + } + STRV_FOREACH(name, names) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int q; - q = start_unit_one(bus, method, *name, mode, &error, w); + q = start_unit_one(bus, method, *name, mode, &error, w, arg_wait ? &wait_context : NULL); if (r >= 0 && q < 0) r = translate_bus_error_to_exit_status(q, &error); } @@ -2924,6 +3065,15 @@ static int start_unit(int argc, char *argv[], void *userdata) { check_triggering_units(bus, *name); } + if (r >= 0 && arg_wait) { + int q; + q = sd_event_loop(wait_context.event); + if (q < 0) + return log_error_errno(q, "Failed to run event loop: %m"); + if (wait_context.any_failed) + r = EXIT_FAILURE; + } + return r; } @@ -6587,6 +6737,7 @@ static void systemctl_help(void) { " -s --signal=SIGNAL Which signal to send\n" " --now Start or stop unit in addition to enabling or disabling it\n" " -q --quiet Suppress output\n" + " --wait For (re)start, wait until service stopped again\n" " --no-block Do not wait until operation finished\n" " --no-wall Don't send wall message before halt/power-off/reboot\n" " --no-reload Don't reload daemon after en-/dis-abling unit files\n" @@ -6857,6 +7008,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_FIRMWARE_SETUP, ARG_NOW, ARG_MESSAGE, + ARG_WAIT, }; static const struct option options[] = { @@ -6880,6 +7032,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "user", no_argument, NULL, ARG_USER }, { "system", no_argument, NULL, ARG_SYSTEM }, { "global", no_argument, NULL, ARG_GLOBAL }, + { "wait", no_argument, NULL, ARG_WAIT }, { "no-block", no_argument, NULL, ARG_NO_BLOCK }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, @@ -7060,6 +7213,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { arg_scope = UNIT_FILE_GLOBAL; break; + case ARG_WAIT: + arg_wait = true; + break; + case ARG_NO_BLOCK: arg_no_block = true; break; @@ -7235,6 +7392,11 @@ static int systemctl_parse_argv(int argc, char *argv[]) { return -EINVAL; } + if (arg_wait && arg_no_block) { + log_error("--wait may not be combined with --no-block."); + return -EINVAL; + } + return 1; } diff --git a/test/TEST-03-JOBS/test-jobs.sh b/test/TEST-03-JOBS/test-jobs.sh index 0c7d4439a2..fa6cf4181a 100755 --- a/test/TEST-03-JOBS/test-jobs.sh +++ b/test/TEST-03-JOBS/test-jobs.sh @@ -49,4 +49,32 @@ systemctl stop --job-mode=replace-irreversibly unstoppable.service || exit 1 # Shutdown of the container/VM will hang if not. systemctl start unstoppable.service || exit 1 +# Test waiting for a started unit(s) to terminate again +cat < /run/systemd/system/wait2.service +[Unit] +Description=Wait for 2 seconds +[Service] +ExecStart=/bin/sh -ec 'sleep 2' +EOF +cat < /run/systemd/system/wait5fail.service +[Unit] +Description=Wait for 5 seconds and fail +[Service] +ExecStart=/bin/sh -ec 'sleep 5; false' +EOF + +# wait2 succeeds +START_SEC=$(date -u '+%s') +systemctl start --wait wait2.service || exit 1 +END_SEC=$(date -u '+%s') +ELAPSED=$(($END_SEC-$START_SEC)) +[[ "$ELAPSED" -ge 2 ]] && [[ "$ELAPSED" -le 3 ]] || exit 1 + +# wait5fail fails, so systemctl should fail +START_SEC=$(date -u '+%s') +! systemctl start --wait wait2.service wait5fail.service || exit 1 +END_SEC=$(date -u '+%s') +ELAPSED=$(($END_SEC-$START_SEC)) +[[ "$ELAPSED" -ge 5 ]] && [[ "$ELAPSED" -le 7 ]] || exit 1 + touch /testok -- cgit v1.2.3-54-g00ecf From dd5e7000cb54f94fdf4756a28144ab32d6e214c8 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 25 Sep 2016 08:34:30 -0400 Subject: core: complain if Before= dep on .device is declared [Unit] Before=foobar.device [Service] ExecStart=/bin/true Type=oneshot $ systemd-analyze verify before-device.service before-device.service: Dependency Before=foobar.device ignored (.device units cannot be delayed) --- TODO | 2 -- src/core/unit.c | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/TODO b/TODO index 64d530b7d7..ff9e9be9fb 100644 --- a/TODO +++ b/TODO @@ -139,8 +139,6 @@ Features: * PID 1 should send out sd_notify("WATCHDOG=1") messages (for usage in the --user mode, and when run via nspawn) -* consider throwing a warning if a service declares it wants to be "Before=" a .device unit. - * there's probably something wrong with having user mounts below /sys, as we have for debugfs. for exmaple, src/core/mount.c handles mounts prefixed with /sys generally special. diff --git a/src/core/unit.c b/src/core/unit.c index 5d284a359d..693f75c928 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2225,6 +2225,11 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen return 0; } + if (d == UNIT_BEFORE && other->type == UNIT_DEVICE) { + log_unit_warning(u, "Dependency Before=%s ignored (.device units cannot be delayed)", other->id); + return 0; + } + r = set_ensure_allocated(&u->dependencies[d], NULL); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From d941ea22e39673414eac941226e41a1d12a41e46 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 25 Sep 2016 09:55:26 -0400 Subject: analyze-verify: honour $SYSTEMD_UNIT_PATH, allow system paths to be ignored SYSTEMD_UNIT_PATH=foobar: systemd-analyze verify barbar/unit.service will load units from barbar/, foobar/, /etc/systemd/system/, etc. SYSTEMD_UNIT_PATH= systemd-analyze verify barbar/unit.service will load units only from barbar/, which is useful e.g. when testing systemd's own units on a system with an older version of systemd installed. --- man/systemd-analyze.xml | 17 +++++++++-------- src/analyze/analyze-verify.c | 17 ++++++++++++++--- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index bc37765dff..8fa7cd3329 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -181,14 +181,15 @@ , described in systemd1). - systemd-analyze verify will load unit - files and print warnings if any errors are detected. Files - specified on the command line will be loaded, but also any other - units referenced by them. This command works by prepending the - directories for all command line arguments at the beginning of the - unit load path, which means that all units files found in those - directories will be used in preference to the unit files found in - the standard locations, even if not listed explicitly. + systemd-analyze verify will load unit files and print + warnings if any errors are detected. Files specified on the command line will be + loaded, but also any other units referenced by them. The full unit search path is + formed by combining the directories for all command line arguments, and the usual unit + load paths (variable $SYSTEMD_UNIT_PATH is supported, and may be + used to replace or augment the compiled in set of unit load paths; see + systemd.unit5). + All units files present in the directories containing the command line arguments will + be used in preference to the other paths. If no command is passed, systemd-analyze time is implied. diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c index 5fd3ee49eb..0ce0276d92 100644 --- a/src/analyze/analyze-verify.c +++ b/src/analyze/analyze-verify.c @@ -71,6 +71,7 @@ static int prepare_filename(const char *filename, char **ret) { } static int generate_path(char **var, char **filenames) { + const char *old; char **filename; _cleanup_strv_free_ char **ans = NULL; @@ -90,9 +91,19 @@ static int generate_path(char **var, char **filenames) { assert_se(strv_uniq(ans)); - r = strv_extend(&ans, ""); - if (r < 0) - return r; + /* First, prepend our directories. Second, if some path was specified, use that, and + * otherwise use the defaults. Any duplicates will be filtered out in path-lookup.c. + * Treat explicit empty path to mean that nothing should be appended. + */ + old = getenv("SYSTEMD_UNIT_PATH"); + if (!streq_ptr(old, "")) { + if (!old) + old = ":"; + + r = strv_extend(&ans, old); + if (r < 0) + return r; + } *var = strv_join(ans, ":"); if (!*var) -- cgit v1.2.3-54-g00ecf From a63ee40751ee3cae053470f4e0fb0016fbc40f25 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 25 Sep 2016 09:58:29 -0400 Subject: core: do not try to create /run/systemd/transient in test mode This prevented systemd-analyze from unprivileged operation on older systemd installations, which should be possible. Also, we shouldn't touch the file system in test mode even if we can. --- src/core/manager.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index e63b31bdf3..dd0d1fa984 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1236,9 +1236,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { return r; /* Make sure the transient directory always exists, so that it remains in the search path */ - r = mkdir_p_label(m->lookup_paths.transient, 0755); - if (r < 0) - return r; + if (!m->test_run) { + r = mkdir_p_label(m->lookup_paths.transient, 0755); + if (r < 0) + return r; + } dual_timestamp_get(&m->generators_start_timestamp); r = manager_run_generators(m); -- cgit v1.2.3-54-g00ecf From ba9fa3bc4868048e6884af9fe496a8d8a324b7e5 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 2 Oct 2016 13:24:54 +0200 Subject: man: fix indentation in table -ies must be a single line of text. Otherwise docbook does strange things to the indentation. --- man/systemd.netdev.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 68ebd5c9f4..e4527f2837 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -173,8 +173,7 @@ A Virtual Routing and Forwarding (VRF) interface to create separate routing and forwarding domains. vcan - The virtual CAN driver (vcan). Similar to the network loopback devices, - vcan offers a virtual local CAN interface. + The virtual CAN driver (vcan). Similar to the network loopback devices, vcan offers a virtual local CAN interface. -- cgit v1.2.3-54-g00ecf From 2df225294fa620ba7654589eedf9d8dde368e0d0 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 2 Oct 2016 14:32:44 +0200 Subject: man: rework the explanation of Domains= Put more emphasis on the routing part. This is the more interesting thing, and also more complicated and novel. Explain "search domains" as the special case. Also explain the effect of ~. in more detail. --- man/systemd.network.xml | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 08dd157e31..0af927db19 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -467,24 +467,31 @@ Domains= - The domains used for DNS host name resolution on this link. Takes a list of DNS domain names which - are used as search suffixes for extending single-label host names (host names containing no dots) to become - fully qualified domain names (FQDNs). If a single-label host name is resolved on this interface, each of - the specified search domains are appended to it in turn, converting it into a fully qualified domain name, - until one of them may be successfully resolved. - - The specified domains are also used for routing of DNS queries: look-ups for host names ending in the - domains specified here are preferably routed to the DNS servers configured for this interface. If a domain - name is prefixed with ~, the domain name becomes a pure "routing" domain, the DNS server - is used for the given domain names only and is not used in the described domain search logic. By specifying a - routing domain of ~. (the tilde indicating definition of a routing domain, the dot - referring to the DNS root domain which is the implied suffix of all valid DNS names) it is possible to - route all DNS traffic preferably to the DNS server specified for this interface. The route domain logic is - particularly useful on multi-homed hosts with DNS servers serving particular private DNS zones on each - interface. + A list of domains which should be resolved using the DNS servers on this link. Each item in the list + should be a domain name, optionally prefixed with a tilde (~). The domains with the + prefix are called "routing-only domains". The domains without the prefix are called "search domains" and + are first used as search suffixes for extending single-label host names (host names containing no dots) to + become fully qualified domain names (FQDNs). If a single-label host name is resolved on this interface, + each of the specified search domains are appended to it in turn, converting it into a fully qualified + domain name, until one of them may be successfully resolved. + + Both "search" and "routing-only" domains are used for routing of DNS queries: look-ups for host names + ending in those domains (hence also single label names, if any "search domains" are listed), are routed to + the DNS servers configured for this interface. The domain routing logic is particularly useful on + multi-homed hosts with DNS servers serving particular private DNS zones on each interface. + + The "routing-only" domain ~. (the tilde indicating definition of a routing domain, + the dot referring to the DNS root domain which is the implied suffix of all valid DNS names) has special + effect. It causes all DNS traffic which does not match another configured domain routing entry to be routed + to DNS servers specified for this interface. This setting is useful to prefer a certain set of DNS servers + if a link on which they are connected is available. This setting is read by - systemd-resolved.service8. + systemd-resolved.service8. + "Search domains" correspond to the domain and search entries in + resolv.conf5. + Domain name routing has no equivalent in the traditional glibc API, which has no concept of domain + name servers limited to a specific link. -- cgit v1.2.3-54-g00ecf From 4a77c53d64b91f8e622df7c7dec1579278f1e1ce Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 2 Oct 2016 14:51:49 +0200 Subject: NEWS: add another batch of entries --- NEWS | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- TODO | 1 + 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/NEWS b/NEWS index 5f3f76df4f..4a6a07ae18 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,36 @@ CHANGES WITH 232 in spe * The new RemoveIPC= option can be used to remove IPC objects owned by the user or group of a service when that service exits. + * ProtectSystem= option gained a new value "strict", which causes the + whole file system tree with the exception of /dev, /proc, and /sys, + to be remounted read-only for a service. + + The new ProtectedKernelTunables= options can be used to disable + modification of configuration files in /sys and /proc by a service. + Various directories and files are remounted read-only, so access is + restricted even if the file permissions would allow it. + + The new ProtectControlGroups= option can be used to disable write + access by a service to /sys/fs/cgroup. + + * Various systemd services have been hardened with + ProtectKernelTunables=yes, ProtectControlGroups=yes, + RestrictAddressFamilies=. + + In particular, systemd-udevd.service is now run in a Seccomp-based + sandbox that prohibits access to AF_INET and AF_INET6 sockets and + thus access to the network. This might break code that runs from udev + rules that tries to talk to the network. Doing that is generally a + bad idea and unsafe due to a variety of reasons. It's also racy as + device management would race against network configuration. It is + recommended to rework such rules to use the SYSTEMD_WANTS property on + the relevant devices to pull in a proper systemd service (which can + be sandboxed differently and ordered correctly after the network + having come up). If that's not possible consider reverting this + sandboxing feature locally by removing the RestrictAddressFamilies= + setting from the systemd-udevd.service unit file, or adding AF_INET + and AF_INET6 to it. + * Support for dynamically creating users for the lifetime of a service has been added. If DynamicUser=yes is specified, user and group IDs will be allocated from the range 61184..65519 for the lifetime of the @@ -12,7 +42,9 @@ CHANGES WITH 232 in spe module. The module must be enabled in /etc/nsswitch.conf. Services started in this way have PrivateTmp= and RemoveIPC= enabled, so that any resources allocated by the service will be cleaned up when the - service exits. + service exits. They also have ProtectHome=read-only and + ProtectSystem=strict enabled, so they are not able to make any + permanent modifications to the system. The nss-systemd module also always resolves root and nobody, making it possible to have no /etc/passwd or /etc/group files in minimal @@ -54,7 +86,7 @@ CHANGES WITH 232 in spe mount the EFI partition on systems where /boot is used for something else. - * disk/by-id symlinks are now created for NVMe drives. + * disk/by-id and disk/by-path symlinks are now created for NVMe drives. * Two new user session targets have been added to support running graphical sessions under the systemd --user instance: @@ -93,6 +125,9 @@ CHANGES WITH 232 in spe * systemd-run gained a new --wait option that makes service execution synchronous. + systemctl gained a new --wait option that causes the start command to + wait until the units being started have terminated again. + * A new journal output mode "short-full" has been added which uses timestamps with abbreviated English day names and adds a timezone suffix. Those timestamps include more information and can be parsed @@ -106,6 +141,12 @@ CHANGES WITH 232 in spe from a single IP can be limited with MaxConnectionsPerSource=, extending the existing setting of MaxConnections. + * systemd-networkd gained support for vcan ("Virtual CAN") interface + configuration. + + * .netdev and .network configuration can now be extended through + drop-ins. + * UDP Segmentation Offload, TCP Segmentation Offload, Generic Segmentation Offload, Generic Receive Offload, Large Receive Offload can be enabled and disabled using the new UDPSegmentationOffload=, @@ -118,6 +159,10 @@ CHANGES WITH 232 in spe new STP=, Priority=, AgeingTimeSec=, and DefaultPVID= settings in the [Bridge] section of .netdev files. + The route table to which routes received over DHCP or RA should be + added can be configured with the new RouteTable= option in the [DHCP] + and [IPv6AcceptRA] sections of .network files. + Address Resolution Protocol can be disabled on links managed by systemd-networkd using the ARP=no setting in the [Link] section of .network files. @@ -125,11 +170,24 @@ CHANGES WITH 232 in spe * $SERVICE_RESULT, $EXIT_CODE, $EXIT_STATUS are set for ExecStop= and ExecStopPost= commands. + * systemd-sysctl will now configure kernel parameters in the order + they occur in the configuration files. This mathes what sysctl + has been traditionally doing. + + * kernel-install "plugins" that are executed to perform various + tasks after a new kernel is added and before an old one is removed + can now return a special value to terminate the procedure and + prevent any later plugins from running. + * Journald's SplitMode=login setting has been deprecated. It has been removed from documentation, and it's use is discouraged. In a future release it will be completely removed, and made equivalent to current default of SplitMode=uid. + * Storage=both option setting in /etc/systemd/coredump.conf has been + removed. With fast LZ4 compression storing the core dump twice is not + useful. + * The --share-system systemd-nspawn option has been replaced with an (undocumented) variable $SYSTEMD_NSPAWN_SHARE_SYSTEM, but the use of this functionality is discouraged. In addition the variables @@ -137,20 +195,6 @@ CHANGES WITH 232 in spe $SYSTEMD_NSPAWN_SHARE_NS_UTS may be used to control the unsharing of individual namespaces. - * systemd-udevd.service is now run in a Seccomp-based sandbox that - prohibits access to AF_INET and AF_INET6 sockets and thus access to - the network. This might break code that runs from udev rules that - tries to talk to the network. Doing that is generally a bad idea and - unsafe due to a variety of reasons. It's also racy as device - management would race against network configuration. It is - recommended to rework such rules to use the SYSTEMD_WANTS property on - the relevant devices to pull in a proper systemd service (which can - be sandboxed differently and ordered correctly after the network - having come up). If that's not possible consider reverting this - sandboxing feature locally by removing the RestrictAddressFamilies= - setting from the systemd-udevd.service unit file, or adding AF_INET - and AF_INET6 to it. - CHANGES WITH 231: * In service units the various ExecXYZ= settings have been extended diff --git a/TODO b/TODO index ff9e9be9fb..f215a4944b 100644 --- a/TODO +++ b/TODO @@ -821,6 +821,7 @@ Features: or interface down - some servers don't do rapid commit without a filled in IA_NA, verify this behavior + - RouteTable= ? External: -- cgit v1.2.3-54-g00ecf From 1ef11fb628ed4e23bca5a2be1734e03f89bb678a Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 2 Oct 2016 14:52:52 +0200 Subject: build-sys: use non-breaking spaces in contributor list I think it's easier to read peoples' names with this change. --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 9185bae7b7..f7ae9ff7aa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6556,7 +6556,7 @@ print-%: @echo $($*) git-contrib: - @git shortlog -s `git describe --abbrev=0`.. | cut -c8- | awk '{ print $$0 "," }' | sort -u + @git shortlog -s `git describe --abbrev=0`.. | cut -c8- | sed 's/ / /g' | awk '{ print $$0 "," }' | sort -u EXTRA_DIST += \ tools/gdb-sd_dump_hashmaps.py -- cgit v1.2.3-54-g00ecf From 19caffac75a2590a0c5ebc2a0214960f8188aec7 Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Sat, 1 Oct 2016 10:58:56 +0200 Subject: nspawn: set shared propagation mode for the container --- src/nspawn/nspawn.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index c2733a19f8..a5d5180727 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1755,6 +1755,11 @@ static int setup_propagate(const char *root) { if (mount(NULL, q, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) return log_error_errno(errno, "Failed to make propagation mount read-only"); + /* machined will MS_MOVE into that directory, and that's only + * supported for non-shared mounts. */ + if (mount(NULL, q, NULL, MS_SLAVE, NULL) < 0) + return log_error_errno(errno, "Failed to make propagation mount slave"); + return 0; } @@ -2990,6 +2995,15 @@ static int outer_child( if (mount(directory, directory, NULL, MS_BIND|MS_REC, NULL) < 0) return log_error_errno(errno, "Failed to make bind mount: %m"); + /* Mark everything as shared so our mounts get propagated down. This is + * required to make new bind mounts available in systemd services + * inside the containter that create a new mount namespace. + * See https://github.com/systemd/systemd/issues/3860 + * Further submounts (such as /dev) done after this will inherit the + * shared propagation mode.*/ + if (mount(NULL, directory, NULL, MS_SHARED|MS_REC, NULL) < 0) + return log_error_errno(errno, "MS_SHARED|MS_REC failed: %m"); + r = recursive_chown(directory, arg_uid_shift, arg_uid_range); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From cfaf4b75e0398d33b4c39683d0c9065e135c6ac1 Mon Sep 17 00:00:00 2001 From: Stefan Schweter Date: Mon, 3 Oct 2016 17:09:54 +0200 Subject: man: remove consecutive duplicate words (#4268) This PR removes consecutive duplicate words from the man pages of: * `resolved.conf.xml` * `systemd.exec.xml` * `systemd.socket.xml` --- man/resolved.conf.xml | 2 +- man/systemd.exec.xml | 2 +- man/systemd.socket.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml index 7556c6ff31..a7710dcb44 100644 --- a/man/resolved.conf.xml +++ b/man/resolved.conf.xml @@ -206,7 +206,7 @@ Cache= Takes a boolean argument. If "yes" (the default), resolving a domain name which already got queried earlier will return the previous result as long as it is still valid, and thus does not result in a new - network request. Be aware that that turning off caching comes at a performance penalty, which is particularly + network request. Be aware that turning off caching comes at a performance penalty, which is particularly high when DNSSEC is used. Note that caching is turned off implicitly if the configured DNS server is on a host-local IP address diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index f70e5c36d4..2054267b90 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -168,7 +168,7 @@ cannot leave files around after unit termination. Moreover ProtectSystem=strict and ProtectHome=read-only are implied, thus prohibiting the service to write to arbitrary file system locations. In order to allow the service to write to certain directories, they have to be whitelisted - using ReadWritePaths=, but care must be taken so that that UID/GID recycling doesn't + using ReadWritePaths=, but care must be taken so that UID/GID recycling doesn't create security issues involving files created by the service. Use RuntimeDirectory= (see below) in order to assign a writable runtime directory to a service, owned by the dynamic user/group and removed automatically when the unit is terminated. Defaults to off. diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 5b6045f69b..d759e17289 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -445,7 +445,7 @@ MaxConnectionsPerSource= The maximum number of connections for a service per source IP address. - This is is very similar to the MaxConnections= directive + This is very similar to the MaxConnections= directive above. Disabled by default. -- cgit v1.2.3-54-g00ecf From 05ecf467eed50ed57c9a12750768b68e092d9be4 Mon Sep 17 00:00:00 2001 From: Elias Probst Date: Tue, 4 Oct 2016 14:37:28 +0200 Subject: Typo (`virtiualization` → `virtualization`) (#4281) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 5f3f76df4f..2f9ceff1a9 100644 --- a/NEWS +++ b/NEWS @@ -67,7 +67,7 @@ CHANGES WITH 232 in spe support unicode keymaps. Font and keymap configuration will now be copied to all allocated virtual consoles. - * FreeBSD's bhyve virtiualization is now detected. + * FreeBSD's bhyve virtualization is now detected. * Information recored in the journal for core dumps now includes the contents of /proc/mountinfo and the command line of the process at -- cgit v1.2.3-54-g00ecf From 20b8e666d3770fb003a3833260eba54b6349aeea Mon Sep 17 00:00:00 2001 From: andhe Date: Tue, 4 Oct 2016 15:36:03 +0200 Subject: po: updated Swedish translation (#4241) * po: updated Swedish translation * po: swedish: fix login vs write logs to confusion Since previous commit (updated messages) there's now a mix of different translation meanings for the same thing. While both translations are technically correct I think the meaning of the original messages are probably "to login" rather than "to write log messages to". This commit switches all translations to the "login" meaning. --- po/sv.po | 94 ++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 44 insertions(+), 50 deletions(-) diff --git a/po/sv.po b/po/sv.po index 2830741309..6ecf5479a4 100644 --- a/po/sv.po +++ b/po/sv.po @@ -3,20 +3,22 @@ # This file is distributed under the same license as the systemd package. # Josef Andersson , 2015. # Sebastian Rasmussen , 2015. +# Andreas Henriksson , 2016. +# msgid "" msgstr "" "Project-Id-Version: systemd master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-11-22 16:37+0100\n" -"PO-Revision-Date: 2015-03-14 11:09+0100\n" -"Last-Translator: Sebastian Rasmussen \n" +"PO-Revision-Date: 2016-09-29 11:58+0200\n" +"Last-Translator: Andreas Henriksson \n" "Language-Team: Swedish\n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.6.10\n" +"X-Generator: Gtranslator 2.91.7\n" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" @@ -72,7 +74,7 @@ msgstr "Ange värdnamn" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 msgid "Authentication is required to set the local host name." -msgstr "Autentisering krävs för att ange lokalt värdnamn." +msgstr "Autentisering krävs för att ställa in lokalt värdnamn." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 msgid "Set static host name" @@ -83,16 +85,16 @@ msgid "" "Authentication is required to set the statically configured local host name, " "as well as the pretty host name." msgstr "" -"Autentisering krävs för att ange det statiskt konfigurerade lokala " +"Autentisering krävs för att ställa in det statiskt konfigurerade lokala " "värdnamnet såväl som det stiliga värdnamnet." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" -msgstr "Ange datorinformation" +msgstr "Ställa in datorinformation" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." -msgstr "Autentisering krävs för att ange lokal datorinformation." +msgstr "Autentisering krävs för att ställa in lokal datorinformation." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" @@ -124,7 +126,7 @@ msgstr "Ange systemlokal" #: ../src/locale/org.freedesktop.locale1.policy.in.h:2 msgid "Authentication is required to set the system locale." -msgstr "Autentisering krävs för att ange systemlokal." +msgstr "Autentisering krävs för att ställa in systemlokal." #: ../src/locale/org.freedesktop.locale1.policy.in.h:3 msgid "Set system keyboard settings" @@ -132,7 +134,7 @@ msgstr "Ange systeminställningar för tangentbord" #: ../src/locale/org.freedesktop.locale1.policy.in.h:4 msgid "Authentication is required to set the system keyboard settings." -msgstr "Autentisering krävs för att ange systeminställningar för tangentbord." +msgstr "Autentisering krävs för att ställa in systeminställningar för tangentbord." #: ../src/login/org.freedesktop.login1.policy.in.h:1 msgid "Allow applications to inhibit system shutdown" @@ -410,79 +412,76 @@ msgstr "Autentisering krävs för att låsa eller låsa upp aktiva sessioner." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Allow indication to the firmware to boot to setup interface" msgstr "" +"Tillåt indikering till firmware att starta upp i inställningsgränssnitt" #: ../src/login/org.freedesktop.login1.policy.in.h:54 -#, fuzzy msgid "" "Authentication is required to indicate to the firmware to boot to setup " "interface." -msgstr "Autentisering krävs för att ange lokalt värdnamn." +msgstr "" +"Autentisering krävs för att indikera till firmware att starta upp till " +"inställningsgränssnitt." #: ../src/login/org.freedesktop.login1.policy.in.h:55 msgid "Set a wall message" -msgstr "" +msgstr "Ange ett väggmeddelande" #: ../src/login/org.freedesktop.login1.policy.in.h:56 -#, fuzzy msgid "Authentication is required to set a wall message" -msgstr "Autentisering krävs för att ange lokalt värdnamn." +msgstr "Autentisering krävs för att ställa in ett väggmeddelande" #: ../src/machine/org.freedesktop.machine1.policy.in.h:1 msgid "Log into a local container" -msgstr "Logga till en lokal behållare" +msgstr "Logga in i en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:2 msgid "Authentication is required to log into a local container." -msgstr "Autentisering krävs för att logga till en lokal behållare" +msgstr "Autentisering krävs för att logga in i en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -#, fuzzy msgid "Log into the local host" -msgstr "Logga till en lokal behållare" +msgstr "Logga in på en lokal värd" #: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -#, fuzzy msgid "Authentication is required to log into the local host." -msgstr "Autentisering krävs för att logga till en lokal behållare" +msgstr "Autentisering krävs för att logga in på den lokala värden" #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -#, fuzzy msgid "Acquire a shell in a local container" -msgstr "Logga till en lokal behållare" +msgstr "Förvärva en kommandotolk i en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -#, fuzzy msgid "Authentication is required to acquire a shell in a local container." -msgstr "Autentisering krävs för att logga till en lokal behållare" +msgstr "" +"Autentisering krävs för att förvärva en kommandotolk i en lokal behållare." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" -msgstr "" +msgstr "Förvärva en kommandotolk på den lokala värden" #: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -#, fuzzy msgid "Authentication is required to acquire a shell on the local host." -msgstr "Autentisering krävs för att ange lokalt värdnamn." +msgstr "" +"Autentisering krävs för att förvärva en kommandotolk på den lokala värden." #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -#, fuzzy msgid "Acquire a pseudo TTY in a local container" -msgstr "Logga till en lokal behållare" +msgstr "Förvärva en pseudo TTY i en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -#, fuzzy msgid "" "Authentication is required to acquire a pseudo TTY in a local container." -msgstr "Autentisering krävs för att logga till en lokal behållare" +msgstr "" +"Autentisering krävs för att förvärva en pseudo TTY i en lokal behållare" #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" -msgstr "" +msgstr "Förvärva en pseudo TTY på den lokala värden" #: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -#, fuzzy msgid "Authentication is required to acquire a pseudo TTY on the local host." -msgstr "Autentisering krävs för att ange lokalt värdnamn." +msgstr "" +"Autentisering krävs för att förvärva en pseudo TTY på den lokala värden." #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" @@ -512,7 +511,7 @@ msgstr "Ange systemtid" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 msgid "Authentication is required to set the system time." -msgstr "Autentisering krävs för ange systemtiden." +msgstr "Autentisering krävs för ställa in systemtiden." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 msgid "Set system timezone" @@ -520,7 +519,7 @@ msgstr "Ange systemets tidszon" #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 msgid "Authentication is required to set the system timezone." -msgstr "Autentisering krävs för att ange systemets tidszon." +msgstr "Autentisering krävs för att ställa in systemets tidszon." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 msgid "Set RTC to local timezone or UTC" @@ -549,39 +548,34 @@ msgstr "" "nätverkstid ska vara aktiverat." #: ../src/core/dbus-unit.c:428 -#, fuzzy msgid "Authentication is required to start '$(unit)'." -msgstr "Autentisering krävs för ange systemtiden." +msgstr "Autentisering krävs för att starta \"$(unit)\"." #: ../src/core/dbus-unit.c:429 -#, fuzzy msgid "Authentication is required to stop '$(unit)'." -msgstr "Autentisering krävs för ange systemtiden." +msgstr "Autentisering krävs för att stoppa \"$(unit)\"." #: ../src/core/dbus-unit.c:430 -#, fuzzy msgid "Authentication is required to reload '$(unit)'." -msgstr "Autentisering krävs för att läsa om tillståndet för systemd." +msgstr "Autentisering krävs för att läsa om tillståndet för \"$(unit)\"." #: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 -#, fuzzy msgid "Authentication is required to restart '$(unit)'." -msgstr "Autentisering krävs för ange systemtiden." +msgstr "Autentisering krävs för att starta om \"$(unit)\"." #: ../src/core/dbus-unit.c:535 -#, fuzzy msgid "Authentication is required to kill '$(unit)'." -msgstr "Autentisering krävs för att logga till en lokal behållare" +msgstr "Autentisering krävs för att döda \"$(unit)\"." #: ../src/core/dbus-unit.c:565 -#, fuzzy msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." -msgstr "Autentisering krävs för att ange lokalt värdnamn." +msgstr "" +"Autentisering krävs för att återställa det \"fallerade\" tillståndet för " +"\"$(unit)\"." #: ../src/core/dbus-unit.c:597 -#, fuzzy msgid "Authentication is required to set properties on '$(unit)'." -msgstr "Autentisering krävs för ange systemtiden." +msgstr "Autentisering krävs för att ställa in egenskaper på \"$(unit)\"." #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" #~ msgstr "Tryck Ctrl+C för att avbryta alla pågående filsystemskontroller." -- cgit v1.2.3-54-g00ecf From 1f4f4cf76c7482a3d64086f0c0d1e2e649183a29 Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Tue, 4 Oct 2016 15:53:16 +0200 Subject: Typo (`mathes` → `matches`) (#4283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 2b7b1738f3..531e7c2155 100644 --- a/NEWS +++ b/NEWS @@ -171,7 +171,7 @@ CHANGES WITH 232 in spe ExecStopPost= commands. * systemd-sysctl will now configure kernel parameters in the order - they occur in the configuration files. This mathes what sysctl + they occur in the configuration files. This matches what sysctl has been traditionally doing. * kernel-install "plugins" that are executed to perform various -- cgit v1.2.3-54-g00ecf From c080fbce9ca4ac21d8dbb1c2d0e8c9205edfdbfb Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Tue, 4 Oct 2016 16:13:27 +0200 Subject: automount: make sure the expire event is restarted after a daemon-reload (#4265) If the corresponding mount unit is deserialized after the automount unit then the expire event is set up in automount_trigger_notify(). However, if the mount unit is deserialized first then the automount unit is still in state AUTOMOUNT_DEAD and automount_trigger_notify() aborts without setting up the expire event. Explicitly call automount_start_expire() during coldplug to make sure that the expire event is set up as necessary. Fixes #4249. --- src/core/automount.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/automount.c b/src/core/automount.c index 00295cf769..bdc0e06965 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -271,6 +271,11 @@ static int automount_coldplug(Unit *u) { return r; (void) sd_event_source_set_description(a->pipe_event_source, "automount-io"); + if (a->deserialized_state == AUTOMOUNT_RUNNING) { + r = automount_start_expire(a); + if (r < 0) + log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m"); + } } automount_set_state(a, a->deserialized_state); -- cgit v1.2.3-54-g00ecf From 5076f4219ee3f25a39e3520943270c2c915b03d1 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Tue, 4 Oct 2016 16:15:37 +0200 Subject: list: LIST_INSERT_BEFORE: update head if necessary (#4261) If the new item is inserted before the first item in the list, then the head must be updated as well. Add a test to the list unit test to check for this. --- src/basic/list.h | 2 ++ src/test/test-list.c | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/basic/list.h b/src/basic/list.h index 5962aa4211..c3771a177f 100644 --- a/src/basic/list.h +++ b/src/basic/list.h @@ -142,6 +142,8 @@ } else { \ if ((_b->name##_prev = _a->name##_prev)) \ _b->name##_prev->name##_next = _b; \ + else \ + *_head = _b; \ _b->name##_next = _a; \ _a->name##_prev = _b; \ } \ diff --git a/src/test/test-list.c b/src/test/test-list.c index 160064d06a..0ccd745cc9 100644 --- a/src/test/test-list.c +++ b/src/test/test-list.c @@ -132,6 +132,29 @@ int main(int argc, const char *argv[]) { assert_se(items[1].item_prev == &items[3]); assert_se(items[3].item_prev == NULL); + LIST_INSERT_BEFORE(item, head, &items[3], &items[0]); + assert_se(items[2].item_next == NULL); + assert_se(items[1].item_next == &items[2]); + assert_se(items[3].item_next == &items[1]); + assert_se(items[0].item_next == &items[3]); + + assert_se(items[2].item_prev == &items[1]); + assert_se(items[1].item_prev == &items[3]); + assert_se(items[3].item_prev == &items[0]); + assert_se(items[0].item_prev == NULL); + assert_se(head == &items[0]); + + LIST_REMOVE(item, head, &items[0]); + assert_se(LIST_JUST_US(item, &items[0])); + + assert_se(items[2].item_next == NULL); + assert_se(items[1].item_next == &items[2]); + assert_se(items[3].item_next == &items[1]); + + assert_se(items[2].item_prev == &items[1]); + assert_se(items[1].item_prev == &items[3]); + assert_se(items[3].item_prev == NULL); + LIST_INSERT_BEFORE(item, head, NULL, &items[0]); assert_se(items[0].item_next == NULL); assert_se(items[2].item_next == &items[0]); -- cgit v1.2.3-54-g00ecf From 629ff674ac48653703440ab16998adb03391f986 Mon Sep 17 00:00:00 2001 From: Stefan Schweter Date: Sun, 2 Oct 2016 19:37:21 +0200 Subject: tree-wide: remove consecutive duplicate words in comments --- src/basic/escape.c | 2 +- src/basic/util.c | 2 +- src/core/dynamic-user.c | 2 +- src/core/execute.c | 2 +- src/hostname/hostnamectl.c | 2 +- src/login/logind-session.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/basic/escape.c b/src/basic/escape.c index 01daf11ce7..4a1ec4505e 100644 --- a/src/basic/escape.c +++ b/src/basic/escape.c @@ -333,7 +333,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi assert(remaining > 0); if (*f != '\\') { - /* A literal literal, copy verbatim */ + /* A literal, copy verbatim */ *(t++) = *f; continue; } diff --git a/src/basic/util.c b/src/basic/util.c index 9d66d28eb7..ec7939dc83 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -467,7 +467,7 @@ bool in_initrd(void) { * 2. the root file system must be a memory file system * * The second check is extra paranoia, since misdetecting an - * initrd can have bad bad consequences due the initrd + * initrd can have bad consequences due the initrd * emptying when transititioning to the main systemd. */ diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c index 310aaa94e1..1043da3eb7 100644 --- a/src/core/dynamic-user.c +++ b/src/core/dynamic-user.c @@ -233,7 +233,7 @@ static int pick_uid(const char *name, uid_t *ret_uid) { if (st.st_nlink > 0) break; - /* Oh, bummer, we got got the lock, but the file was unlinked between the time we opened it and + /* Oh, bummer, we got the lock, but the file was unlinked between the time we opened it and * got the lock. Close it, and try again. */ lock_fd = safe_close(lock_fd); } diff --git a/src/core/execute.c b/src/core/execute.c index 3da7ef3be6..82d8c978c1 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2207,7 +2207,7 @@ static int exec_child( return r; } - /* Note that we don't set $HOME or $SHELL if they are are not particularly enlightening anyway + /* Note that we don't set $HOME or $SHELL if they are not particularly enlightening anyway * (i.e. are "/" or "/bin/nologin"). */ } diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index 4795324667..07c57fb567 100644 --- a/src/hostname/hostnamectl.c +++ b/src/hostname/hostnamectl.c @@ -278,7 +278,7 @@ static int set_hostname(sd_bus *bus, char **args, unsigned n) { /* Now that we set the pretty hostname, let's clean up the parameter and use that as static * hostname. If the hostname was already valid as static hostname, this will only chop off the trailing * dot if there is one. If it was not valid, then it will be made fully valid by truncating, dropping - * multiple dots, and and dropping weird chars. Note that we clean the name up only if we also are + * multiple dots, and dropping weird chars. Note that we clean the name up only if we also are * supposed to set the pretty name. If the pretty name is not being set we assume the user knows what * he does and pass the name as-is. */ h = strdup(hostname); diff --git a/src/login/logind-session.c b/src/login/logind-session.c index b6da237397..ba1bcc2630 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -611,7 +611,7 @@ static int session_stop_scope(Session *s, bool force) { return 0; /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything - * that is left in in the scope is "left-over". Informing systemd about this has the benefit that it will log + * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log * when killing any processes left after this point. */ r = manager_abandon_scope(s->manager, s->scope, &error); if (r < 0) -- cgit v1.2.3-54-g00ecf From d4c08299f2e2a97f23f619cd564e5ac8f1505e0e Mon Sep 17 00:00:00 2001 From: "Thomas H. P. Andersen" Date: Tue, 4 Oct 2016 20:41:46 +0200 Subject: NEWS: typo fixes (#4285) --- NEWS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 531e7c2155..511c260c37 100644 --- a/NEWS +++ b/NEWS @@ -95,13 +95,13 @@ CHANGES WITH 232 in spe used. * The vconsole initialization code has been significantly reworked to - use KD_FONT_OP_GET/SET ioctls insteads of KD_FONT_OP_COPY and better + use KD_FONT_OP_GET/SET ioctls instead of KD_FONT_OP_COPY and better support unicode keymaps. Font and keymap configuration will now be copied to all allocated virtual consoles. * FreeBSD's bhyve virtualization is now detected. - * Information recored in the journal for core dumps now includes the + * Information recorded in the journal for core dumps now includes the contents of /proc/mountinfo and the command line of the process at the top of the process hierarchy (which is usually the init process of the container). @@ -180,7 +180,7 @@ CHANGES WITH 232 in spe prevent any later plugins from running. * Journald's SplitMode=login setting has been deprecated. It has been - removed from documentation, and it's use is discouraged. In a future + removed from documentation, and its use is discouraged. In a future release it will be completely removed, and made equivalent to current default of SplitMode=uid. -- cgit v1.2.3-54-g00ecf From 41eb436265684080c601bff392ba6da1789639a2 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Wed, 5 Oct 2016 06:57:02 +0200 Subject: nspawn: add log message to let users know that nspawn needs an empty /dev directory (#4226) Fixes https://github.com/systemd/systemd/issues/3695 At the same time it adds a protection against userns chown of inodes of a shared mount point. --- src/nspawn/nspawn.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index a5d5180727..9a8274c8de 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1395,6 +1395,12 @@ static int copy_devnodes(const char *dest) { } else { if (mknod(to, st.st_mode, st.st_rdev) < 0) { + /* + * This is some sort of protection too against + * recursive userns chown on shared /dev/ + */ + if (errno == EEXIST) + log_notice("%s/dev/ should be an empty directory", dest); if (errno != EPERM) return log_error_errno(errno, "mknod(%s) failed: %m", to); -- cgit v1.2.3-54-g00ecf From 6abfd30372f9440c3dc3cf2fcf6d3eee85037ccb Mon Sep 17 00:00:00 2001 From: hbrueckner Date: Wed, 5 Oct 2016 13:58:55 +0200 Subject: seccomp: add support for the s390 architecture (#4287) Add seccomp support for the s390 architecture (31-bit and 64-bit) to systemd. This requires libseccomp >= 2.3.1. --- README | 2 +- configure.ac | 2 +- man/systemd.exec.xml | 3 ++- src/shared/seccomp-util.c | 22 ++++++++++++++++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/README b/README index fb6fd6381b..d610baaf76 100644 --- a/README +++ b/README @@ -120,7 +120,7 @@ REQUIREMENTS: libcap libmount >= 2.27.1 (from util-linux) (util-linux *must* be built with --enable-libmount-force-mountinfo) - libseccomp >= 1.0.0 (optional) + libseccomp >= 2.3.1 (optional) libblkid >= 2.24 (from util-linux) (optional) libkmod >= 15 (optional) PAM >= 1.1.2 (optional) diff --git a/configure.ac b/configure.ac index 4181483798..ccd212ef13 100644 --- a/configure.ac +++ b/configure.ac @@ -459,7 +459,7 @@ AM_CONDITIONAL(HAVE_LIBMOUNT, [test "$have_libmount" = "yes"]) have_seccomp=no AC_ARG_ENABLE(seccomp, AS_HELP_STRING([--disable-seccomp], [Disable optional SECCOMP support])) if test "x$enable_seccomp" != "xno"; then - PKG_CHECK_MODULES(SECCOMP, [libseccomp >= 1.0.0], + PKG_CHECK_MODULES(SECCOMP, [libseccomp >= 2.3.1], [AC_DEFINE(HAVE_SECCOMP, 1, [Define if seccomp is available]) have_seccomp=yes M4_DEFINES="$M4_DEFINES -DHAVE_SECCOMP"], diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 2054267b90..5e6787338d 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1334,7 +1334,8 @@ identifiers to include in the system call filter. The known architecture identifiers are x86, x86-64, x32, - arm as well as the special identifier + arm, s390, + s390x as well as the special identifier native. Only system calls of the specified architectures will be permitted to processes of this unit. This is an effective way to disable compatibility with diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 2f42381fc1..8116c7671f 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -39,6 +39,10 @@ const char* seccomp_arch_to_string(uint32_t c) { return "x32"; if (c == SCMP_ARCH_ARM) return "arm"; + if (c == SCMP_ARCH_S390) + return "s390"; + if (c == SCMP_ARCH_S390X) + return "s390x"; return NULL; } @@ -59,6 +63,10 @@ int seccomp_arch_from_string(const char *n, uint32_t *ret) { *ret = SCMP_ARCH_X32; else if (streq(n, "arm")) *ret = SCMP_ARCH_ARM; + else if (streq(n, "s390")) + *ret = SCMP_ARCH_S390; + else if (streq(n, "s390x")) + *ret = SCMP_ARCH_S390X; else return -EINVAL; @@ -85,6 +93,20 @@ int seccomp_add_secondary_archs(scmp_filter_ctx *c) { if (r < 0 && r != -EEXIST) return r; +#elif defined(__s390__) || defined(__s390x__) + int r; + + /* Add in all possible secondary archs we are aware of that + * this kernel might support. */ + + r = seccomp_arch_add(c, SCMP_ARCH_S390); + if (r < 0 && r != -EEXIST) + return r; + + r = seccomp_arch_add(c, SCMP_ARCH_S390X); + if (r < 0 && r != -EEXIST) + return r; + #endif return 0; -- cgit v1.2.3-54-g00ecf From 110b7e909aa36d7e83ece76e18a99aa89de00c28 Mon Sep 17 00:00:00 2001 From: Zeal Jagannatha Date: Wed, 5 Oct 2016 14:00:06 +0200 Subject: Added ArchLinux config for mkosi (#4274) --- mkosi.arch | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 mkosi.arch diff --git a/mkosi.arch b/mkosi.arch new file mode 100644 index 0000000000..4c44f288ae --- /dev/null +++ b/mkosi.arch @@ -0,0 +1,67 @@ +# This file is part of systemd. +# +# Copyright 2016 Zeal Jagannatha +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +# Simply invoke "mkosi" in the project directory to build an OS image. + +[Distribution] +Distribution=arch + +[Output] +Format=raw_btrfs +Bootable=yes + +[Partitions] +RootSize=2G + +[Packages] +Cache=/var/cache/pacman/pkg/ +BuildPackages= + acl + autoconf + automake + bzip2 + cryptsetup + curl + dbus + docbook-xsl + elfutils + gcc + git + gnu-efi-libs + gnutls + gperf + intltool + iptables + kmod + libcap + libgcrypt + libidn + libmicrohttpd + libseccomp + libtool + libutil-linux + libxkbcommon + libxslt + lz4 + make + pam + pkgconfig + python + python-lxml + qrencode + xz -- cgit v1.2.3-54-g00ecf From f6bb7ac5c6a200eb444f7f7ad043c01b2afa7d4c Mon Sep 17 00:00:00 2001 From: Tobias Jungel Date: Wed, 5 Oct 2016 17:06:40 +0200 Subject: networkd: use BridgeFDB as well on bridge ports (#4253) [BridgeFDB] did not apply to bridge ports so far. This patch adds the proper handling. In case of a bridge interface the correct flag NTF_MASTER is now set in the netlink call. FDB MAC addresses are now applied in link_enter_set_addresses to make sure the link is setup. --- src/network/networkd-fdb.c | 12 ++++++++++-- src/network/networkd-link.c | 37 ++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index be8aebee2d..ed5a47589e 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -107,20 +107,28 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; sd_netlink *rtnl; int r; + uint8_t flags; + Bridge *bridge; assert(link); + assert(link->network); assert(link->manager); assert(fdb_entry); rtnl = link->manager->rtnl; + bridge = BRIDGE(link->network->bridge); /* create new RTM message */ r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE); if (r < 0) return rtnl_log_create_error(r); - /* only NTF_SELF flag supported. */ - r = sd_rtnl_message_neigh_set_flags(req, NTF_SELF); + if (bridge) + flags = NTF_MASTER; + else + flags = NTF_SELF; + + r = sd_rtnl_message_neigh_set_flags(req, flags); if (r < 0) return rtnl_log_create_error(r); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 9cd4aa2c39..25f46c093e 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -942,6 +942,20 @@ static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { return sd_dhcp_server_set_ntp(s, addresses, n_addresses); } +static int link_set_bridge_fdb(Link *link) { + FdbEntry *fdb_entry; + int r = 0; + + LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) { + r = fdb_entry_configure(link, fdb_entry); + if (r < 0) { + return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m"); + } + } + + return r; +} + static int link_enter_set_addresses(Link *link) { Address *ad; int r; @@ -950,6 +964,10 @@ static int link_enter_set_addresses(Link *link) { assert(link->network); assert(link->state != _LINK_STATE_INVALID); + r = link_set_bridge_fdb(link); + if (r < 0) + return r; + link_set_state(link, LINK_STATE_SETTING_ADDRESSES); LIST_FOREACH(addresses, ad, link->network->static_addresses) { @@ -1119,21 +1137,6 @@ static int link_set_bridge_vlan(Link *link) { return r; } -static int link_set_bridge_fdb(Link *link) { - FdbEntry *fdb_entry; - int r = 0; - - LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) { - r = fdb_entry_configure(link, fdb_entry); - if (r < 0) { - log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m"); - break; - } - } - - return r; -} - static int link_set_proxy_arp(Link *link) { const char *p = NULL; int r; @@ -2477,10 +2480,6 @@ static int link_configure(Link *link) { return r; } - r = link_set_bridge_fdb(link); - if (r < 0) - return r; - r = link_set_proxy_arp(link); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 77531863ca50fb5c0dfb952dbda50250bbe3e5d1 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Tue, 4 Oct 2016 10:51:25 +0200 Subject: Fix typo --- src/core/umount.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/umount.c b/src/core/umount.c index c21a2be54e..1e5459ed80 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -375,7 +375,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e /* If we are in a container, don't attempt to read-only mount anything as that brings no real benefits, but might confuse the host, as we remount - the superblock here, not the bind mound. */ + the superblock here, not the bind mount. */ if (detect_container() <= 0) { _cleanup_free_ char *options = NULL; /* MS_REMOUNT requires that the data parameter -- cgit v1.2.3-54-g00ecf From 100a5f579db3fd9aa4418225f0928b99ecee3807 Mon Sep 17 00:00:00 2001 From: Piotr Drąg Date: Wed, 5 Oct 2016 22:59:37 +0200 Subject: catalog,po: update Polish translation (#4290) --- catalog/systemd.pl.catalog.in | 73 +++++++++++++++++++++++++------------------ po/pl.po | 58 +++++++++++++++++----------------- 2 files changed, 72 insertions(+), 59 deletions(-) diff --git a/catalog/systemd.pl.catalog.in b/catalog/systemd.pl.catalog.in index 33c2122974..5eead5c92c 100644 --- a/catalog/systemd.pl.catalog.in +++ b/catalog/systemd.pl.catalog.in @@ -1,7 +1,7 @@ # This file is part of systemd. # # Copyright 2012 Lennart Poettering -# Copyright 2014, 2015, 2016 Piotr Drąg +# Copyright 2014-2016 Piotr Drąg # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by @@ -29,15 +29,15 @@ Subject: Uruchomiono dziennik Defined-By: systemd Support: %SUPPORT_URL% -Systemowy proces dziennika został uruchomiony, otworzył pliki dziennika do -zapisu i jest gotowy do przetwarzania żądań. +Systemowy proces dziennika został uruchomiony, otworzył pliki dziennika +do zapisu i jest gotowy do przetwarzania żądań. -- d93fb3c9c24d451a97cea615ce59c00b Subject: Zatrzymano dziennik Defined-By: systemd Support: %SUPPORT_URL% -Systemowy proces dziennika został wyłączony i zamknął wszystkie obecnie +Systemowy proces dziennika został wyłączony i zamknął wszystkie obecnie aktywne pliki dziennika. -- ec387f577b844b8fa948f33cad9a75e6 @@ -48,28 +48,28 @@ Support: %SUPPORT_URL% @JOURNAL_NAME@ (@JOURNAL_PATH@) obecnie używa @CURRENT_USE_PRETTY@. Maksymalnie może używać @MAX_USE_PRETTY@. Zostawianie co najmniej @DISK_KEEP_FREE_PRETTY@ wolnego (z obecnie dostępnego @DISK_AVAILABLE_PRETTY@ miejsca na dysku). -Wymuszone ograniczenie użycia wynosi więc @LIMIT_PRETTY@, z czego @AVAILABLE_PRETTY@ jest nadal dostępne. +Wymuszone ograniczenie użycia wynosi więc @LIMIT_PRETTY@, z czego @AVAILABLE_PRETTY@ jest nadal dostępne. Ograniczenia kontrolujące ilość miejsca na dysku używanego przez dziennik można konfigurować za pomocą ustawień SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= -w pliku /etc/systemd/journald.conf. Strona journald.conf(5) zawiera więcej +w pliku /etc/systemd/journald.conf. Strona journald.conf(5) zawiera więcej informacji. -- a596d6fe7bfa4994828e72309e95d61e -Subject: Ograniczono komunikaty z usługi +Subject: Ograniczono komunikaty z usługi Defined-By: systemd Support: %SUPPORT_URL% Documentation: man:journald.conf(5) -Usługa zapisała za dużo komunikatów w określonym czasie. Komunikaty z usługi -zostały pominięte. +Usługa zapisała za dużo komunikatów w określonym czasie. +Komunikaty z usługi zostały pominięte. -Proszę zauważyć, że tylko komunikaty z danej usługi zostały pominięte. Nie ma -to wpływu na komunikaty innych usług. +Proszę zauważyć, że tylko komunikaty z danej usługi zostały pominięte. +Nie ma to wpływu na komunikaty innych usług. Ograniczenia kontrolujące pomijanie komunikatów mogą być konfigurowane -za pomocą opcji RateLimitIntervalSec= i RateLimitBurst= w pliku +za pomocą opcji RateLimitIntervalSec= i RateLimitBurst= w pliku /etc/systemd/journald.conf. Strona journald.conf(5) zawiera więcej informacji. -- e9bf28e6e834481bb6f48f548ad13606 @@ -86,18 +86,29 @@ Defined-By: systemd Support: %SUPPORT_URL% Documentation: man:core(5) -Proces @COREDUMP_PID@ (@COREDUMP_COMM@) uległ awarii i zrzucił plik core. +Proces @COREDUMP_PID@ (@COREDUMP_COMM@) uległ awarii i zrzucił plik core. -Zwykle wskazuje to na błąd programistyczny w danym programie i powinno zostać +Zwykle wskazuje to na błąd programistyczny w danym programie i powinno zostać zgłoszone jego producentowi jako błąd. +-- 5aadd8e954dc4b1a8c954d63fd9e1137 +Subject: Plik core został skrócony do @SIZE_LIMIT@ B. +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:coredump.conf(5) + +Proces miał więcej zmapowanej pamięci niż maksimum dla przetwarzania i miejsca +skonfigurowane przez systemd-coredump(8). Tylko pierwsze @SIZE_LIMIT@ B +zostało zapisanych. Ten plik core może nadal być używalny, ale narzędzia typu +gdb(1) będą ostrzegały o skróceniu pliku. + -- 8d45620c1a4348dbb17410da57c60c66 Subject: Utworzono nową sesję @SESSION_ID@ dla użytkownika @USER_ID@ Defined-By: systemd Support: %SUPPORT_URL% Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat -Nowa sesja o identyfikatorze @SESSION_ID@ została utworzona dla użytkownika +Nowa sesja o identyfikatorze @SESSION_ID@ została utworzona dla użytkownika @USER_ID@. Proces prowadzący sesji: @LEADER@. @@ -108,7 +119,7 @@ Defined-By: systemd Support: %SUPPORT_URL% Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat -Sesja o identyfikatorze @SESSION_ID@ została zakończona. +Sesja o identyfikatorze @SESSION_ID@ została zakończona. -- fcbefc5da23d428093f97c82a9290f7b Subject: Dostępne jest nowe stanowisko @SEAT_ID@ @@ -116,7 +127,7 @@ Defined-By: systemd Support: %SUPPORT_URL% Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat -Nowe stanowisko @SEAT_ID@ zostało skonfigurowane i jest teraz dostępne. +Nowe stanowisko @SEAT_ID@ zostało skonfigurowane i jest teraz dostępne. -- e7852bfe46784ed0accde04bc864c2d5 Subject: Usunięto stanowisko @SEAT_ID@ @@ -124,7 +135,7 @@ Defined-By: systemd Support: %SUPPORT_URL% Documentation: http://www.freedesktop.org/wiki/Software/systemd/multiseat -Stanowisko @SEAT_ID@ zostało usunięte i nie jest już dostępne. +Stanowisko @SEAT_ID@ zostało usunięte i nie jest już dostępne. -- c7a787079b354eaaa9e77b371893cd27 Subject: Zmiana czasu @@ -175,8 +186,8 @@ Subject: Zainicjowano wyłączenie systemu Defined-By: systemd Support: %SUPPORT_URL% -Zainicjowano wyłączenie systemd. Wyłączenie zostało rozpoczęte i wszystkie -usługi systemowe zostały zakończone, a wszystkie systemy plików odmontowane. +Zainicjowano wyłączenie systemd. Wyłączenie zostało rozpoczęte i wszystkie +usługi systemowe zostały zakończone, a wszystkie systemy plików odmontowane. -- 7d4958e842da4a758f6c1cdc7b36dcc5 Subject: Rozpoczęto uruchamianie jednostki @UNIT@ @@ -238,7 +249,7 @@ Subject: Nie można wykonać procesu @EXECUTABLE@ Defined-By: systemd Support: %SUPPORT_URL% -Proces @EXECUTABLE@ nie mógł zostać wykonany i się nie powiódł. +Proces @EXECUTABLE@ nie mógł zostać wykonany i się nie powiódł. Numer błędu zwrócony przez ten proces: @ERRNO@. @@ -249,25 +260,25 @@ Support: %SUPPORT_URL% Jeden lub więcej komunikatów nie może zostać przekazanych do usługi syslog uruchomionej obok journald. Zwykle oznacza to, że implementacja syslog nie -jest w stanie nadążyć za prędkością kolejki komunikatów. +jest w stanie nadążyć za prędkością kolejki komunikatów. -- 1dee0369c7fc4736b7099b38ecb46ee7 Subject: Punkt montowania nie jest pusty Defined-By: systemd Support: %SUPPORT_URL% -Katalog @WHERE@ został podany jako punkt montowania (drugie pole w pliku -/etc/fstab lub pole Where= w pliku jednostki systemd) i nie jest pusty. Nie -wpływa to na montowanie, ale wcześniej istniejące pliki w tym katalogu stają +Katalog @WHERE@ został podany jako punkt montowania (drugie pole w pliku +/etc/fstab lub pole Where= w pliku jednostki systemd) i nie jest pusty. Nie +wpływa to na montowanie, ale wcześniej istniejące pliki w tym katalogu stają się niedostępne. Aby zobaczyć te pliki, proszę ręcznie zamontować system -plików w innym położeniu. +plików w innym położeniu. -- 24d8d4452573402496068381a6312df2 Subject: Uruchomiono maszynę wirtualną lub kontener Defined-By: systemd Support: %SUPPORT_URL% -Maszyna wirtualna @NAME@ (PID prowadzący @LEADER@) została uruchomiona i jest +Maszyna wirtualna @NAME@ (PID prowadzący @LEADER@) została uruchomiona i jest gotowa do użycia. -- 58432bd3bace477cb514b56381b8a758 @@ -284,15 +295,15 @@ Support: %SUPPORT_URL% Documentation: man:systemd-resolved.service(8) resolved.conf(5) Usługa resolver (systemd-resolved.service) wykryła, że skonfigurowany serwer -DNS nie obsługuje DNSSEC, w wyniku czego walidacja DNSSEC została wyłączona. +DNS nie obsługuje DNSSEC, w wyniku czego walidacja DNSSEC została wyłączona. To zdarzenie będzie miało miejsce, jeśli skonfigurowano DNSSEC=allow-downgrade -w pliku resolved.conf, a skonfigurowany serwer DNS jest niezgodny z DNSSEC. +w pliku resolved.conf, a skonfigurowany serwer DNS jest niezgodny z DNSSEC. Proszę zauważyć, że używanie tego trybu umożliwia ataki wyłączające DNSSEC, ponieważ atakujący będzie mógł wyłączyć walidację DNSSEC na komputerze przez -umieszczenie odpowiednich odpowiedzi DNS w kanale komunikacji. +umieszczenie odpowiednich odpowiedzi DNS w kanale komunikacji. -To zdarzenie może wskazywać, że serwer DNS jest faktycznie niezgodny z DNSSEC, +To zdarzenie może wskazywać, że serwer DNS jest faktycznie niezgodny z DNSSEC, albo że atakującemu udało się upozorować atak tego typu. -- 1675d7f172174098b1108bf8c7dc8f5d diff --git a/po/pl.po b/po/pl.po index 92e9a209cc..c289a2cd4c 100644 --- a/po/pl.po +++ b/po/pl.po @@ -1,13 +1,15 @@ -# translation of pl.po to Polish -# Piotr Drąg , 2011, 2013, 2014, 2015, 2016. +# Polish translation for systemd. +# Copyright © 2011-2016 the systemd authors. +# This file is distributed under the same license as the systemd package. +# Piotr Drąg , 2011, 2013-2016. # Zbigniew Jędrzejewski-Szmek , 2011. # msgid "" msgstr "" "Project-Id-Version: systemd\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-04-23 14:24+0200\n" -"PO-Revision-Date: 2016-04-23 14:25+0200\n" +"POT-Creation-Date: 2016-10-05 19:01+0200\n" +"PO-Revision-Date: 2016-10-05 19:02+0200\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish \n" "Language: pl\n" @@ -19,13 +21,13 @@ msgstr "" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 msgid "Send passphrase back to system" -msgstr "Wysłanie hasła z powrotem do systemu" +msgstr "Wysłanie hasła z powrotem do systemu" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 msgid "" "Authentication is required to send the entered passphrase back to the system." msgstr "" -"Wymagane jest uwierzytelnienie, aby wysłać podane hasło z powrotem do " +"Wymagane jest uwierzytelnienie, aby wysłać podane hasło z powrotem do " "systemu." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 @@ -51,7 +53,7 @@ msgstr "" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 msgid "Set or unset system and service manager environment variables" msgstr "" -"Ustawienie lub usunięcie zmiennych środowiskowych menedżera systemu i usług" +"Ustawienie lub usunięcie zmiennych środowiskowych menedżera systemu i usług" #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 msgid "" @@ -59,7 +61,7 @@ msgid "" "environment variables." msgstr "" "Wymagane jest uwierzytelnienie, aby ustawić lub usunąć zmienne środowiskowe " -"menedżera systemu i usług." +"menedżera systemu i usług." #: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 msgid "Reload the systemd state" @@ -87,16 +89,16 @@ msgid "" "as well as the pretty host name." msgstr "" "Wymagane jest uwierzytelnienie, aby ustawić statycznie skonfigurowaną nazwę " -"lokalnego komputera, a także jego ładną nazwę." +"lokalnego komputera, a także jego ładną nazwę." #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 msgid "Set machine information" -msgstr "Ustawienie informacji o komputerze" +msgstr "Ustawienie informacji o komputerze" #: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 msgid "Authentication is required to set local machine information." msgstr "" -"Wymagane jest uwierzytelnienie, aby ustawić informacje o lokalnym komputerze." +"Wymagane jest uwierzytelnienie, aby ustawić informacje o lokalnym komputerze." #: ../src/import/org.freedesktop.import1.policy.in.h:1 msgid "Import a VM or container image" @@ -410,14 +412,14 @@ msgstr "" #: ../src/login/org.freedesktop.login1.policy.in.h:51 msgid "Manage active sessions, users and seats" -msgstr "Zarządzanie aktywnymi sesjami, użytkownikami i stanowiskami" +msgstr "Zarządzanie aktywnymi sesjami, użytkownikami i stanowiskami" #: ../src/login/org.freedesktop.login1.policy.in.h:52 msgid "" "Authentication is required for managing active sessions, users and seats." msgstr "" "Wymagane jest uwierzytelnienie, aby zarządzać aktywnymi sesjami, " -"użytkownikami i stanowiskami." +"użytkownikami i stanowiskami." #: ../src/login/org.freedesktop.login1.policy.in.h:53 msgid "Lock or unlock active sessions" @@ -468,12 +470,12 @@ msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:5 msgid "Acquire a shell in a local container" -msgstr "Uzyskanie powłoki w lokalnym kontenerze" +msgstr "Uzyskanie powłoki w lokalnym kontenerze" #: ../src/machine/org.freedesktop.machine1.policy.in.h:6 msgid "Authentication is required to acquire a shell in a local container." msgstr "" -"Wymagane jest uwierzytelnienie, aby uzyskać powłokę w lokalnym kontenerze." +"Wymagane jest uwierzytelnienie, aby uzyskać powłokę w lokalnym kontenerze." #: ../src/machine/org.freedesktop.machine1.policy.in.h:7 msgid "Acquire a shell on the local host" @@ -486,13 +488,13 @@ msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:9 msgid "Acquire a pseudo TTY in a local container" -msgstr "Uzyskanie pseudo-TTY w lokalnym kontenerze" +msgstr "Uzyskanie pseudo-TTY w lokalnym kontenerze" #: ../src/machine/org.freedesktop.machine1.policy.in.h:10 msgid "" "Authentication is required to acquire a pseudo TTY in a local container." msgstr "" -"Wymagane jest uwierzytelnienie, aby uzyskać pseudo-TTY w lokalnym kontenerze." +"Wymagane jest uwierzytelnienie, aby uzyskać pseudo-TTY w lokalnym kontenerze." #: ../src/machine/org.freedesktop.machine1.policy.in.h:11 msgid "Acquire a pseudo TTY on the local host" @@ -506,18 +508,18 @@ msgstr "" #: ../src/machine/org.freedesktop.machine1.policy.in.h:13 msgid "Manage local virtual machines and containers" -msgstr "Zarządzanie lokalnymi maszynami wirtualnymi i kontenerami" +msgstr "Zarządzanie lokalnymi maszynami wirtualnymi i kontenerami" #: ../src/machine/org.freedesktop.machine1.policy.in.h:14 msgid "" "Authentication is required to manage local virtual machines and containers." msgstr "" "Wymagane jest uwierzytelnienie, aby zarządzać lokalnymi maszynami " -"wirtualnymi i kontenerami." +"wirtualnymi i kontenerami." #: ../src/machine/org.freedesktop.machine1.policy.in.h:15 msgid "Manage local virtual machine and container images" -msgstr "Zarządzanie lokalnymi obrazami maszyn wirtualnych i kontenerów" +msgstr "Zarządzanie lokalnymi obrazami maszyn wirtualnych i kontenerów" #: ../src/machine/org.freedesktop.machine1.policy.in.h:16 msgid "" @@ -525,7 +527,7 @@ msgid "" "images." msgstr "" "Wymagane jest uwierzytelnienie, aby zarządzać lokalnymi obrazami maszyn " -"wirtualnych i kontenerów." +"wirtualnych i kontenerów." #: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 msgid "Set system time" @@ -567,36 +569,36 @@ msgstr "" "Wymagane jest uwierzytelnienie, aby kontrolować, czy włączyć synchronizację " "czasu przez sieć." -#: ../src/core/dbus-unit.c:450 +#: ../src/core/dbus-unit.c:459 msgid "Authentication is required to start '$(unit)'." msgstr "Wymagane jest uwierzytelnienie, aby uruchomić jednostkę „$(unit)”." -#: ../src/core/dbus-unit.c:451 +#: ../src/core/dbus-unit.c:460 msgid "Authentication is required to stop '$(unit)'." msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać jednostkę „$(unit)”." -#: ../src/core/dbus-unit.c:452 +#: ../src/core/dbus-unit.c:461 msgid "Authentication is required to reload '$(unit)'." msgstr "" "Wymagane jest uwierzytelnienie, aby ponownie wczytać jednostkę „$(unit)”." -#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 +#: ../src/core/dbus-unit.c:462 ../src/core/dbus-unit.c:463 msgid "Authentication is required to restart '$(unit)'." msgstr "" "Wymagane jest uwierzytelnienie, aby ponownie uruchomić jednostkę „$(unit)”." -#: ../src/core/dbus-unit.c:560 +#: ../src/core/dbus-unit.c:570 msgid "Authentication is required to kill '$(unit)'." msgstr "" "Wymagane jest uwierzytelnienie, aby wymusić wyłączenie jednostki „$(unit)”." -#: ../src/core/dbus-unit.c:590 +#: ../src/core/dbus-unit.c:601 msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." msgstr "" "Wymagane jest uwierzytelnienie, aby przywrócić stan „failed” (niepowodzenia) " "jednostki „$(unit)”." -#: ../src/core/dbus-unit.c:622 +#: ../src/core/dbus-unit.c:634 msgid "Authentication is required to set properties on '$(unit)'." msgstr "" "Wymagane jest uwierzytelnienie, aby ustawić właściwości jednostki „$(unit)”." -- cgit v1.2.3-54-g00ecf From d2665e0866772663ad7c774c05bf2e0dc8ddcb04 Mon Sep 17 00:00:00 2001 From: Yuki Inoguchi Date: Thu, 6 Oct 2016 18:44:51 +0900 Subject: journald, ratelimit: fix inaccurate message suppression in journal_rate_limit_test() (#4291) Currently, the ratelimit does not handle the number of suppressed messages accurately. Even though the number of messages reaches the limit, it still allows to add one extra messages to journal. This patch fixes the problem. --- src/journal/journald-rate-limit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c index d30bf92cec..f48639cf58 100644 --- a/src/journal/journald-rate-limit.c +++ b/src/journal/journald-rate-limit.c @@ -261,7 +261,7 @@ int journal_rate_limit_test(JournalRateLimit *r, const char *id, int priority, u return 1 + s; } - if (p->num <= burst) { + if (p->num < burst) { p->num++; return 1; } -- cgit v1.2.3-54-g00ecf From 197e2809320357772c0d2def0b53474a4b1f07fd Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Thu, 6 Oct 2016 15:15:07 +0530 Subject: networkd: fix coding style (#4294) --- src/network/networkd-link.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 25f46c093e..d9e060b6cf 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -944,16 +944,15 @@ static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { static int link_set_bridge_fdb(Link *link) { FdbEntry *fdb_entry; - int r = 0; + int r; LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) { r = fdb_entry_configure(link, fdb_entry); - if (r < 0) { + if (r < 0) return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m"); - } } - return r; + return 0; } static int link_enter_set_addresses(Link *link) { -- cgit v1.2.3-54-g00ecf From f006b30bd5a24cb4420e0d439ebb5805b2b4c84d Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 28 Sep 2016 18:26:25 +0200 Subject: audit: disable if cannot create NETLINK_AUDIT socket --- src/basic/audit-util.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/basic/audit-util.c b/src/basic/audit-util.c index 5741fecdd6..d1c9695973 100644 --- a/src/basic/audit-util.c +++ b/src/basic/audit-util.c @@ -92,8 +92,11 @@ bool use_audit(void) { int fd; fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT); - if (fd < 0) - cached_use = errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT; + if (fd < 0) { + cached_use = !IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT, EPERM); + if (errno == EPERM) + log_debug_errno(errno, "Audit access prohibited, won't talk to audit"); + } else { cached_use = true; safe_close(fd); -- cgit v1.2.3-54-g00ecf From 36d854780c01d589e5da1fc6e94f46aa41f7016f Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 28 Sep 2016 18:37:39 +0200 Subject: core: do not fail in a container if we can't use setgroups It might be blocked through /proc/PID/setgroups --- src/basic/capability-util.c | 3 ++- src/basic/user-util.c | 27 ++++++++++++++++++++++++++- src/basic/user-util.h | 2 ++ src/core/execute.c | 2 +- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c index d4c5bd6937..f8db6e0212 100644 --- a/src/basic/capability-util.c +++ b/src/basic/capability-util.c @@ -31,6 +31,7 @@ #include "log.h" #include "macro.h" #include "parse-util.h" +#include "user-util.h" #include "util.h" int have_effective_cap(int value) { @@ -295,7 +296,7 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) { if (setresgid(gid, gid, gid) < 0) return log_error_errno(errno, "Failed to change group ID: %m"); - if (setgroups(0, NULL) < 0) + if (maybe_setgroups(0, NULL) < 0) return log_error_errno(errno, "Failed to drop auxiliary groups list: %m"); /* Ensure we keep the permitted caps across the setresuid() */ diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 0522bce1d1..16496fccfa 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -33,6 +33,7 @@ #include "alloc-util.h" #include "fd-util.h" +#include "fileio.h" #include "formats-util.h" #include "macro.h" #include "missing.h" @@ -460,7 +461,7 @@ int get_shell(char **_s) { int reset_uid_gid(void) { - if (setgroups(0, NULL) < 0) + if (maybe_setgroups(0, NULL) < 0) return -errno; if (setresgid(0, 0, 0) < 0) @@ -602,3 +603,27 @@ bool valid_home(const char *p) { return true; } + +int maybe_setgroups(size_t size, const gid_t *list) { + static int cached_can_setgroups = -1; + /* check if setgroups is allowed before we try to drop all the auxiliary groups */ + if (size == 0) { + if (cached_can_setgroups < 0) { + _cleanup_free_ char *setgroups_content = NULL; + int r = read_one_line_file("/proc/self/setgroups", &setgroups_content); + if (r < 0 && errno != ENOENT) + return r; + if (r < 0) { + /* old kernels don't have /proc/self/setgroups, so assume we can use setgroups */ + cached_can_setgroups = true; + } else { + cached_can_setgroups = streq(setgroups_content, "allow"); + if (!cached_can_setgroups) + log_debug("skip setgroups, /proc/self/setgroups is set to 'deny'"); + } + } + if (!cached_can_setgroups) + return 0; + } + return setgroups(size, list); +} diff --git a/src/basic/user-util.h b/src/basic/user-util.h index 6c61f63cae..dfea561bde 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -86,3 +86,5 @@ bool valid_user_group_name(const char *u); bool valid_user_group_name_or_id(const char *u); bool valid_gecos(const char *d); bool valid_home(const char *p); + +int maybe_setgroups(size_t size, const gid_t *list); diff --git a/src/core/execute.c b/src/core/execute.c index 82d8c978c1..019ff8490b 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -781,7 +781,7 @@ static int enforce_groups(const ExecContext *context, const char *username, gid_ k++; } - if (setgroups(k, gids) < 0) { + if (maybe_setgroups(k, gids) < 0) { free(gids); return -errno; } -- cgit v1.2.3-54-g00ecf From 94f42fe3a68129fc5d30fc0ee2094c3052ea782b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 6 Oct 2016 22:40:53 +0900 Subject: units: systemd-udevd: add AF_INET and AF_INET6 to RestrictAddressFamilies= (#4296) The udev builtin command `net_setup_link` requires AF_INET and AF_INET6. Fixes #4293. --- NEWS | 14 -------------- units/systemd-udevd.service.in | 2 +- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/NEWS b/NEWS index 511c260c37..4924d7c4b6 100644 --- a/NEWS +++ b/NEWS @@ -21,20 +21,6 @@ CHANGES WITH 232 in spe ProtectKernelTunables=yes, ProtectControlGroups=yes, RestrictAddressFamilies=. - In particular, systemd-udevd.service is now run in a Seccomp-based - sandbox that prohibits access to AF_INET and AF_INET6 sockets and - thus access to the network. This might break code that runs from udev - rules that tries to talk to the network. Doing that is generally a - bad idea and unsafe due to a variety of reasons. It's also racy as - device management would race against network configuration. It is - recommended to rework such rules to use the SYSTEMD_WANTS property on - the relevant devices to pull in a proper systemd service (which can - be sandboxed differently and ordered correctly after the network - having come up). If that's not possible consider reverting this - sandboxing feature locally by removing the RestrictAddressFamilies= - setting from the systemd-udevd.service unit file, or adding AF_INET - and AF_INET6 to it. - * Support for dynamically creating users for the lifetime of a service has been added. If DynamicUser=yes is specified, user and group IDs will be allocated from the range 61184..65519 for the lifetime of the diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in index cb2d8ba775..46d637883b 100644 --- a/units/systemd-udevd.service.in +++ b/units/systemd-udevd.service.in @@ -27,4 +27,4 @@ TasksMax=infinity MountFlags=slave MemoryDenyWriteExecute=yes RestrictRealtime=yes -RestrictAddressFamilies=AF_UNIX AF_NETLINK +RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 -- cgit v1.2.3-54-g00ecf From d21494ea25a5f36af998191a7d86adc2fe511638 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Oct 2016 11:54:03 +0200 Subject: update TODO --- TODO | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TODO b/TODO index f215a4944b..9ca2736b2a 100644 --- a/TODO +++ b/TODO @@ -32,6 +32,10 @@ Janitorial Clean-ups: Features: +* in networkd, when matching device types, fix up DEVTYPE rubbish the kernel passes to us + +* enable LockMLOCK to take a percentage value relative to physical memory + * switch to ProtectSystem=strict for all our long-running services where that's possible * introduce an "invocation ID" for units, that is randomly generated, and -- cgit v1.2.3-54-g00ecf From fef05f7ae969a64e9c2b916bceaad0638987a706 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 4 Oct 2016 11:00:02 -0400 Subject: mkosi: create .mkosi directory Since it looks like we'll wind up with a bunch of mkosi files for different distros, it's probably better to keep them in a subdirectory. --- .mkosi/mkosi.arch | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ .mkosi/mkosi.fedora | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mkosi.arch | 67 ------------------------------------------------ mkosi.default | 73 +---------------------------------------------------- 4 files changed, 140 insertions(+), 139 deletions(-) create mode 100644 .mkosi/mkosi.arch create mode 100644 .mkosi/mkosi.fedora delete mode 100644 mkosi.arch mode change 100644 => 120000 mkosi.default diff --git a/.mkosi/mkosi.arch b/.mkosi/mkosi.arch new file mode 100644 index 0000000000..4c44f288ae --- /dev/null +++ b/.mkosi/mkosi.arch @@ -0,0 +1,67 @@ +# This file is part of systemd. +# +# Copyright 2016 Zeal Jagannatha +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +# Simply invoke "mkosi" in the project directory to build an OS image. + +[Distribution] +Distribution=arch + +[Output] +Format=raw_btrfs +Bootable=yes + +[Partitions] +RootSize=2G + +[Packages] +Cache=/var/cache/pacman/pkg/ +BuildPackages= + acl + autoconf + automake + bzip2 + cryptsetup + curl + dbus + docbook-xsl + elfutils + gcc + git + gnu-efi-libs + gnutls + gperf + intltool + iptables + kmod + libcap + libgcrypt + libidn + libmicrohttpd + libseccomp + libtool + libutil-linux + libxkbcommon + libxslt + lz4 + make + pam + pkgconfig + python + python-lxml + qrencode + xz diff --git a/.mkosi/mkosi.fedora b/.mkosi/mkosi.fedora new file mode 100644 index 0000000000..1c161df836 --- /dev/null +++ b/.mkosi/mkosi.fedora @@ -0,0 +1,72 @@ +# This file is part of systemd. +# +# Copyright 2016 Lennart Poettering +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +# Simply invoke "mkosi" in the project directory to build an OS image. + +[Distribution] +Distribution=fedora +Release=24 + +[Output] +Format=raw_btrfs +Bootable=yes + +[Partitions] +RootSize=2G + +[Packages] +Cache=/var/tmp/dnf-cache +BuildPackages= + audit-libs-devel + autoconf + automake + bzip2-devel + cryptsetup-devel + dbus-devel + docbook-style-xsl + elfutils-devel + gcc + git + gnu-efi + gnu-efi-devel + gnutls-devel + gperf + intltool + iptables-devel + kmod-devel + libacl-devel + libblkid-devel + libcap-devel + libcurl-devel + libgcrypt-devel + libidn-devel + libmicrohttpd-devel + libmount-devel + libseccomp-devel + libselinux-devel + libtool + libxkbcommon-devel + libxslt + lz4-devel + make + pam-devel + pkgconfig + python3-devel + python3-lxml + qrencode-devel + xz-devel diff --git a/mkosi.arch b/mkosi.arch deleted file mode 100644 index 4c44f288ae..0000000000 --- a/mkosi.arch +++ /dev/null @@ -1,67 +0,0 @@ -# This file is part of systemd. -# -# Copyright 2016 Zeal Jagannatha -# -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# systemd is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with systemd; If not, see . - -# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). -# Simply invoke "mkosi" in the project directory to build an OS image. - -[Distribution] -Distribution=arch - -[Output] -Format=raw_btrfs -Bootable=yes - -[Partitions] -RootSize=2G - -[Packages] -Cache=/var/cache/pacman/pkg/ -BuildPackages= - acl - autoconf - automake - bzip2 - cryptsetup - curl - dbus - docbook-xsl - elfutils - gcc - git - gnu-efi-libs - gnutls - gperf - intltool - iptables - kmod - libcap - libgcrypt - libidn - libmicrohttpd - libseccomp - libtool - libutil-linux - libxkbcommon - libxslt - lz4 - make - pam - pkgconfig - python - python-lxml - qrencode - xz diff --git a/mkosi.default b/mkosi.default deleted file mode 100644 index 1c161df836..0000000000 --- a/mkosi.default +++ /dev/null @@ -1,72 +0,0 @@ -# This file is part of systemd. -# -# Copyright 2016 Lennart Poettering -# -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# systemd is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with systemd; If not, see . - -# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). -# Simply invoke "mkosi" in the project directory to build an OS image. - -[Distribution] -Distribution=fedora -Release=24 - -[Output] -Format=raw_btrfs -Bootable=yes - -[Partitions] -RootSize=2G - -[Packages] -Cache=/var/tmp/dnf-cache -BuildPackages= - audit-libs-devel - autoconf - automake - bzip2-devel - cryptsetup-devel - dbus-devel - docbook-style-xsl - elfutils-devel - gcc - git - gnu-efi - gnu-efi-devel - gnutls-devel - gperf - intltool - iptables-devel - kmod-devel - libacl-devel - libblkid-devel - libcap-devel - libcurl-devel - libgcrypt-devel - libidn-devel - libmicrohttpd-devel - libmount-devel - libseccomp-devel - libselinux-devel - libtool - libxkbcommon-devel - libxslt - lz4-devel - make - pam-devel - pkgconfig - python3-devel - python3-lxml - qrencode-devel - xz-devel diff --git a/mkosi.default b/mkosi.default new file mode 120000 index 0000000000..2718c9e2a0 --- /dev/null +++ b/mkosi.default @@ -0,0 +1 @@ +.mkosi/mkosi.fedora \ No newline at end of file -- cgit v1.2.3-54-g00ecf From be9bc687d8de5450c0f72f2671710085457bda39 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 4 Oct 2016 11:02:22 -0400 Subject: mkosi: disable our own cache No point in spamming the fs. --- .mkosi/mkosi.fedora | 1 - 1 file changed, 1 deletion(-) diff --git a/.mkosi/mkosi.fedora b/.mkosi/mkosi.fedora index 1c161df836..b10e11718b 100644 --- a/.mkosi/mkosi.fedora +++ b/.mkosi/mkosi.fedora @@ -30,7 +30,6 @@ Bootable=yes RootSize=2G [Packages] -Cache=/var/tmp/dnf-cache BuildPackages= audit-libs-devel autoconf -- cgit v1.2.3-54-g00ecf From a10744be42c9f6de1af2c9eb8aac7f74344a5dad Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 6 Oct 2016 11:52:36 -0400 Subject: mkosi: drop git clean This is required after systemd/mkosi#25. --- mkosi.build | 1 - 1 file changed, 1 deletion(-) diff --git a/mkosi.build b/mkosi.build index 09d835d45b..94a6667e42 100755 --- a/mkosi.build +++ b/mkosi.build @@ -20,7 +20,6 @@ # This is a build script for OS image generation using mkosi (https://github.com/systemd/mkosi). # Simply invoke "mkosi" in the project directory to build an OS image. -git clean -dfqx ./autogen.sh c make -j `nproc` make install -- cgit v1.2.3-54-g00ecf From cd35d461bec09d098103b778eb7b228ec846d470 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 6 Oct 2016 11:53:07 -0400 Subject: mkosi: install Fedora 25 No need to look back at the past. Fedora 25 is here (almost). --- .mkosi/mkosi.fedora | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mkosi/mkosi.fedora b/.mkosi/mkosi.fedora index b10e11718b..0af20c924a 100644 --- a/.mkosi/mkosi.fedora +++ b/.mkosi/mkosi.fedora @@ -20,7 +20,7 @@ [Distribution] Distribution=fedora -Release=24 +Release=25 [Output] Format=raw_btrfs -- cgit v1.2.3-54-g00ecf From 429b43502675550ed61d3f62a4ffd295ab10732d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Oct 2016 15:48:15 +0200 Subject: sd-device/networkd: unify code to get a socket for issuing netdev ioctls on As suggested here: https://github.com/systemd/systemd/pull/4296#issuecomment-251911349 Let's try AF_INET first as socket, but let's fall back to AF_NETLINK, so that we can use a protocol-independent socket here if possible. This has the benefit that our code will still work even if AF_INET/AF_INET6 is made unavailable (for exmple via seccomp), at least on current kernels. --- src/basic/socket-util.c | 17 +++++++++++++++++ src/basic/socket-util.h | 2 ++ src/libsystemd/sd-device/sd-device.c | 5 +++-- src/udev/net/ethtool-util.c | 6 +++--- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 5c829e0e7e..1662c04705 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1060,3 +1060,20 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng return NULL; } + +int socket_ioctl_fd(void) { + int fd; + + /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for + * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not + * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more + * generic AF_NETLINK. */ + + fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) + fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_GENERIC); + if (fd < 0) + return -errno; + + return fd; +} diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 2536b085f9..2ef572badb 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -154,3 +154,5 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \ strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \ }) + +int socket_ioctl_fd(void); diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 0c4ad966bd..411453e08d 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -36,6 +36,7 @@ #include "parse-util.h" #include "path-util.h" #include "set.h" +#include "socket-util.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" @@ -629,9 +630,9 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) { if (r < 0) return r; - sk = socket(PF_INET, SOCK_DGRAM, 0); + sk = socket_ioctl_fd(); if (sk < 0) - return -errno; + return sk; r = ioctl(sk, SIOCGIFNAME, &ifr); if (r < 0) diff --git a/src/udev/net/ethtool-util.c b/src/udev/net/ethtool-util.c index b1aa0223fd..708a665576 100644 --- a/src/udev/net/ethtool-util.c +++ b/src/udev/net/ethtool-util.c @@ -25,6 +25,7 @@ #include "conf-parser.h" #include "ethtool-util.h" #include "log.h" +#include "socket-util.h" #include "string-table.h" #include "strxcpyx.h" #include "util.h" @@ -59,10 +60,9 @@ int ethtool_connect(int *ret) { assert_return(ret, -EINVAL); - fd = socket(PF_INET, SOCK_DGRAM, 0); + fd = socket_ioctl_fd(); if (fd < 0) - return -errno; - + return fd; *ret = fd; return 0; -- cgit v1.2.3-54-g00ecf From 19526c66795d7f7d2e956f10422dc76a7429901c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Oct 2016 15:50:30 +0200 Subject: sd-bus: add a few missing entries to the error translation tables These were forgotten, let's add some useful mappings for all errors we define. --- src/libsystemd/sd-bus/bus-common-errors.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index a69193aa32..de7b65ca14 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -52,6 +52,8 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS, EEXIST), SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING, ENOSYS), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER_MAPPING, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_GROUP_MAPPING, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SESSION, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_NO_SESSION_FOR_PID, ENXIO), @@ -64,6 +66,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_NOT_TAKEN, EINVAL), SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS, EINPROGRESS), SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP), + SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY), SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY), -- cgit v1.2.3-54-g00ecf From 6f21e066f6c8c5bedafedddc4b350c58102506c6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Oct 2016 16:01:05 +0200 Subject: resolved: properly handle BADCOOKIE DNS error Add this new error code (documented in RFC7873) to our list of known errors. --- src/resolve/resolved-dns-packet.c | 1 + src/resolve/resolved-dns-packet.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index a8ad8fe342..5304c6e6e6 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -2289,6 +2289,7 @@ static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = { [DNS_RCODE_BADNAME] = "BADNAME", [DNS_RCODE_BADALG] = "BADALG", [DNS_RCODE_BADTRUNC] = "BADTRUNC", + [DNS_RCODE_BADCOOKIE] = "BADCOOKIE", }; DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int); diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index 7b7d4e14c9..054dc88a85 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -263,6 +263,7 @@ enum { DNS_RCODE_BADNAME = 20, DNS_RCODE_BADALG = 21, DNS_RCODE_BADTRUNC = 22, + DNS_RCODE_BADCOOKIE = 23, _DNS_RCODE_MAX_DEFINED, _DNS_RCODE_MAX = 4095 /* 4 bit rcode in the header plus 8 bit rcode in OPT, makes 12 bit */ }; -- cgit v1.2.3-54-g00ecf From 729c6467df4887e55b57b4efe9541bff0d31016b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Oct 2016 16:01:44 +0200 Subject: sd-bus: add DNS errors to the errno translation table We generate these, hence we should also add errno translations for them. --- src/libsystemd/sd-bus/bus-common-errors.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index de7b65ca14..9cc28ed564 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -85,6 +85,25 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY), SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "FORMERR", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "SERVFAIL", EHOSTDOWN), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXDOMAIN", ENXIO), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTIMP", ENOSYS), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "REFUSED", EACCES), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YXDOMAIN", EEXIST), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YRRSET", EEXIST), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXRRSET", ENOENT), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTAUTH", EACCES), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTZONE", EREMOTE), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADVERS", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADKEY", EKEYREJECTED), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTIME", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADMODE", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADNAME", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADALG", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTRUNC", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADCOOKIE", EBADR), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO), SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY), -- cgit v1.2.3-54-g00ecf From 2d6fce8d7c397fe915230b728cb92aa749245e43 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Oct 2016 16:03:01 +0200 Subject: core: leave PAM stub process around with GIDs updated In the process execution code of PID 1, before 096424d1230e0a0339735c51b43949809e972430 the GID settings where changed before invoking PAM, and the UID settings after. After the change both changes are made after the PAM session hooks are run. When invoking PAM we fork once, and leave a stub process around which will invoke the PAM session end hooks when the session goes away. This code previously was dropping the remaining privs (which were precisely the UID). Fix this code to do this correctly again, by really dropping them else (i.e. the GID as well). While we are at it, also fix error logging of this code. Fixes: #4238 --- src/core/execute.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 019ff8490b..e4a23ac169 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -843,6 +843,7 @@ static int setup_pam( const char *name, const char *user, uid_t uid, + gid_t gid, const char *tty, char ***env, int fds[], unsigned n_fds) { @@ -948,8 +949,13 @@ static int setup_pam( * and this will make PR_SET_PDEATHSIG work in most cases. * If this fails, ignore the error - but expect sd-pam threads * to fail to exit normally */ + + if (maybe_setgroups(0, NULL) < 0) + log_warning_errno(errno, "Failed to setgroups() in sd-pam: %m"); + if (setresgid(gid, gid, gid) < 0) + log_warning_errno(errno, "Failed to setresgid() in sd-pam: %m"); if (setresuid(uid, uid, uid) < 0) - log_error_errno(r, "Error: Failed to setresuid() in sd-pam: %m"); + log_warning_errno(errno, "Failed to setresuid() in sd-pam: %m"); (void) ignore_signals(SIGPIPE, -1); @@ -2413,7 +2419,7 @@ static int exec_child( } if (context->pam_name && username) { - r = setup_pam(context->pam_name, username, uid, context->tty_path, &accum_env, fds, n_fds); + r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds); if (r < 0) { *exit_status = EXIT_PAM; return r; -- cgit v1.2.3-54-g00ecf From 7429b2eb8308f3a2bf8c28d555fcdf5e961e65f0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Oct 2016 17:44:51 +0200 Subject: tree-wide: drop some misleading compiler warnings gcc at some optimization levels thinks thes variables were used without initialization. it's wrong, but let's make the message go anyway. --- src/nspawn/nspawn.c | 2 +- src/resolve/resolved-dns-packet.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 9a8274c8de..a08377b3a3 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3830,7 +3830,7 @@ int main(int argc, char *argv[]) { _cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(pty_forward_freep) PTYForward *forward = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - ContainerStatus container_status; + ContainerStatus container_status = 0; char last_char = 0; int ifi = 0; ssize_t l; diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c index 5304c6e6e6..337a8c473f 100644 --- a/src/resolve/resolved-dns-packet.c +++ b/src/resolve/resolved-dns-packet.c @@ -2143,7 +2143,7 @@ int dns_packet_extract(DnsPacket *p) { for (i = 0; i < n; i++) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; - bool cache_flush; + bool cache_flush = false; r = dns_packet_read_rr(p, &rr, &cache_flush, NULL); if (r < 0) -- cgit v1.2.3-54-g00ecf From 97f0e76f18d322d29bcfbc4ab6bb9cd67a1cdd54 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 6 Oct 2016 17:54:12 +0200 Subject: user-util: rework maybe_setgroups() a bit Let's drop the caching of the setgroups /proc field for now. While there's a strict regime in place when it changes states, let's better not cache it since we cannot really be sure we follow that regime correctly. More importantly however, this is not in performance sensitive code, and there's no indication the cache is really beneficial, hence let's drop the caching and make things a bit simpler. Also, while we are at it, rework the error handling a bit, and always return negative errno-style error codes, following our usual coding style. This has the benefit that we can sensible hanld read_one_line_file() errors, without having to updat errno explicitly. --- src/basic/capability-util.c | 5 +++-- src/basic/user-util.c | 49 ++++++++++++++++++++++++++------------------- src/core/execute.c | 10 +++++---- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c index f8db6e0212..c3de20a0e8 100644 --- a/src/basic/capability-util.c +++ b/src/basic/capability-util.c @@ -296,8 +296,9 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) { if (setresgid(gid, gid, gid) < 0) return log_error_errno(errno, "Failed to change group ID: %m"); - if (maybe_setgroups(0, NULL) < 0) - return log_error_errno(errno, "Failed to drop auxiliary groups list: %m"); + r = maybe_setgroups(0, NULL); + if (r < 0) + return log_error_errno(r, "Failed to drop auxiliary groups list: %m"); /* Ensure we keep the permitted caps across the setresuid() */ if (prctl(PR_SET_KEEPCAPS, 1) < 0) diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 16496fccfa..de6c93056e 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -460,9 +460,11 @@ int get_shell(char **_s) { } int reset_uid_gid(void) { + int r; - if (maybe_setgroups(0, NULL) < 0) - return -errno; + r = maybe_setgroups(0, NULL); + if (r < 0) + return r; if (setresgid(0, 0, 0) < 0) return -errno; @@ -605,25 +607,30 @@ bool valid_home(const char *p) { } int maybe_setgroups(size_t size, const gid_t *list) { - static int cached_can_setgroups = -1; - /* check if setgroups is allowed before we try to drop all the auxiliary groups */ - if (size == 0) { - if (cached_can_setgroups < 0) { - _cleanup_free_ char *setgroups_content = NULL; - int r = read_one_line_file("/proc/self/setgroups", &setgroups_content); - if (r < 0 && errno != ENOENT) - return r; - if (r < 0) { - /* old kernels don't have /proc/self/setgroups, so assume we can use setgroups */ - cached_can_setgroups = true; - } else { - cached_can_setgroups = streq(setgroups_content, "allow"); - if (!cached_can_setgroups) - log_debug("skip setgroups, /proc/self/setgroups is set to 'deny'"); - } - } - if (!cached_can_setgroups) + int r; + + /* Check if setgroups is allowed before we try to drop all the auxiliary groups */ + if (size == 0) { /* Dropping all aux groups? */ + _cleanup_free_ char *setgroups_content = NULL; + bool can_setgroups; + + r = read_one_line_file("/proc/self/setgroups", &setgroups_content); + if (r == -ENOENT) + /* Old kernels don't have /proc/self/setgroups, so assume we can use setgroups */ + can_setgroups = true; + else if (r < 0) + return r; + else + can_setgroups = streq(setgroups_content, "allow"); + + if (!can_setgroups) { + log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'"); return 0; + } } - return setgroups(size, list); + + if (setgroups(size, list) < 0) + return -errno; + + return 0; } diff --git a/src/core/execute.c b/src/core/execute.c index e4a23ac169..d5c4e60796 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -781,9 +781,10 @@ static int enforce_groups(const ExecContext *context, const char *username, gid_ k++; } - if (maybe_setgroups(k, gids) < 0) { + r = maybe_setgroups(k, gids); + if (r < 0) { free(gids); - return -errno; + return r; } free(gids); @@ -950,8 +951,9 @@ static int setup_pam( * If this fails, ignore the error - but expect sd-pam threads * to fail to exit normally */ - if (maybe_setgroups(0, NULL) < 0) - log_warning_errno(errno, "Failed to setgroups() in sd-pam: %m"); + r = maybe_setgroups(0, NULL); + if (r < 0) + log_warning_errno(r, "Failed to setgroups() in sd-pam: %m"); if (setresgid(gid, gid, gid) < 0) log_warning_errno(errno, "Failed to setresgid() in sd-pam: %m"); if (setresuid(uid, uid, uid) < 0) -- cgit v1.2.3-54-g00ecf From 24dd31c19ede505143833346ff850af942694aa6 Mon Sep 17 00:00:00 2001 From: Lukáš Nykrýn Date: Fri, 7 Oct 2016 03:08:21 +0200 Subject: core: add possibility to set action for ctrl-alt-del burst (#4105) For some certification, it should not be possible to reboot the machine through ctrl-alt-delete. Currently we suggest our customers to mask the ctrl-alt-delete target, but that is obviously not enough. Patching the keymaps to disable that is really not a way to go for them, because the settings need to be easily checked by some SCAP tools. --- man/systemd-system.conf.xml | 11 ++++++++++ src/core/main.c | 5 +++++ src/core/manager.c | 51 +++++++++++++++++++++++++++++++++------------ src/core/manager.h | 14 ++++++++++++- src/core/system.conf | 1 + 5 files changed, 68 insertions(+), 14 deletions(-) diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index 1bb40fd234..a268397d09 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -105,6 +105,17 @@ arguments. + + CtrlAltDelBurstAction= + + Defines what action will be performed + if user presses Ctr-Alt-Delete more than 7 times in 2s. + Can be set to reboot-force, poweroff-force + or disabled with ignore. Defaults to + reboot-force. + + + CPUAffinity= diff --git a/src/core/main.c b/src/core/main.c index be0cb0b6d1..6fe440277e 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -131,6 +131,7 @@ static bool arg_default_memory_accounting = false; static bool arg_default_tasks_accounting = true; static uint64_t arg_default_tasks_max = UINT64_MAX; static sd_id128_t arg_machine_id = {}; +static CADBurstAction arg_cad_burst_action = CAD_BURST_ACTION_REBOOT; noreturn static void freeze_or_reboot(void) { @@ -648,6 +649,8 @@ static int config_parse_join_controllers(const char *unit, return 0; } +static DEFINE_CONFIG_PARSE_ENUM(config_parse_cad_burst_action, cad_burst_action, CADBurstAction, "Failed to parse service restart specifier"); + static int parse_config_file(void) { const ConfigTableItem items[] = { @@ -702,6 +705,7 @@ static int parse_config_file(void) { { "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting }, { "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting }, { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max }, + { "Manager", "CtrlAltDelBurstAction", config_parse_cad_burst_action, 0, &arg_cad_burst_action}, {} }; @@ -1794,6 +1798,7 @@ int main(int argc, char *argv[]) { m->initrd_timestamp = initrd_timestamp; m->security_start_timestamp = security_start_timestamp; m->security_finish_timestamp = security_finish_timestamp; + m->cad_burst_action = arg_cad_burst_action; manager_set_defaults(m); manager_set_show_status(m, arg_show_status); diff --git a/src/core/manager.c b/src/core/manager.c index dd0d1fa984..5253cb3712 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1894,6 +1894,35 @@ static int manager_start_target(Manager *m, const char *name, JobMode mode) { return r; } +static void manager_handle_ctrl_alt_del(Manager *m) { + /* If the user presses C-A-D more than + * 7 times within 2s, we reboot/shutdown immediately, + * unless it was disabled in system.conf */ + + if (ratelimit_test(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == CAD_BURST_ACTION_IGNORE) + manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY); + else { + switch (m->cad_burst_action) { + + case CAD_BURST_ACTION_REBOOT: + m->exit_code = MANAGER_REBOOT; + break; + + case CAD_BURST_ACTION_POWEROFF: + m->exit_code = MANAGER_POWEROFF; + break; + + default: + assert_not_reached("Unknown action."); + } + + log_notice("Ctrl-Alt-Del was pressed more than 7 times within 2s, performing immediate %s.", + cad_burst_action_to_string(m->cad_burst_action)); + status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, performing immediate %s.", + cad_burst_action_to_string(m->cad_burst_action)); + } +} + static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; ssize_t n; @@ -1945,19 +1974,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t case SIGINT: if (MANAGER_IS_SYSTEM(m)) { - - /* If the user presses C-A-D more than - * 7 times within 2s, we reboot - * immediately. */ - - if (ratelimit_test(&m->ctrl_alt_del_ratelimit)) - manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY); - else { - log_notice("Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately."); - status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, rebooting immediately."); - m->exit_code = MANAGER_REBOOT; - } - + manager_handle_ctrl_alt_del(m); break; } @@ -3544,3 +3561,11 @@ static const char *const manager_state_table[_MANAGER_STATE_MAX] = { }; DEFINE_STRING_TABLE_LOOKUP(manager_state, ManagerState); + +static const char *const cad_burst_action_table[_CAD_BURST_ACTION_MAX] = { + [CAD_BURST_ACTION_IGNORE] = "ignore", + [CAD_BURST_ACTION_REBOOT] = "reboot-force", + [CAD_BURST_ACTION_POWEROFF] = "poweroff-force", +}; + +DEFINE_STRING_TABLE_LOOKUP(cad_burst_action, CADBurstAction); diff --git a/src/core/manager.h b/src/core/manager.h index a592f1cb94..495440b446 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -62,6 +62,14 @@ typedef enum ManagerExitCode { _MANAGER_EXIT_CODE_INVALID = -1 } ManagerExitCode; +typedef enum CADBurstAction { + CAD_BURST_ACTION_IGNORE, + CAD_BURST_ACTION_REBOOT, + CAD_BURST_ACTION_POWEROFF, + _CAD_BURST_ACTION_MAX, + _CAD_BURST_ACTION_INVALID = -1 +} CADBurstAction; + typedef enum StatusType { STATUS_TYPE_EPHEMERAL, STATUS_TYPE_NORMAL, @@ -304,8 +312,9 @@ struct Manager { Hashmap *uid_refs; Hashmap *gid_refs; - /* When the user hits C-A-D more than 7 times per 2s, reboot immediately... */ + /* When the user hits C-A-D more than 7 times per 2s, do something immediately... */ RateLimit ctrl_alt_del_ratelimit; + CADBurstAction cad_burst_action; const char *unit_log_field; const char *unit_log_format_string; @@ -398,3 +407,6 @@ void manager_deserialize_gid_refs_one(Manager *m, const char *value); const char *manager_state_to_string(ManagerState m) _const_; ManagerState manager_state_from_string(const char *s) _pure_; + +const char *cad_burst_action_to_string(CADBurstAction a) _const_; +CADBurstAction cad_burst_action_from_string(const char *s) _pure_; diff --git a/src/core/system.conf b/src/core/system.conf index c6bb050aac..746572b7ff 100644 --- a/src/core/system.conf +++ b/src/core/system.conf @@ -21,6 +21,7 @@ #CrashChangeVT=no #CrashShell=no #CrashReboot=no +#CtrlAltDelBurstAction=reboot-force #CPUAffinity=1 2 #JoinControllers=cpu,cpuacct net_cls,net_prio #RuntimeWatchdogSec=0 -- cgit v1.2.3-54-g00ecf From c55ae51e77e1fc56fde7bc3466dd2021ff3856cb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Oct 2016 12:08:51 +0200 Subject: manager: don't ever busy loop when we get a notification message we can't process If the kernel doesn't permit us to dequeue/process an incoming notification datagram message it's still better to stop processing the notification messages altogether than to enter a busy loop where we keep getting notified but can't do a thing about it. With this change, manager_dispatch_notify_fd() behaviour is changed like this: - if an error indicating a spurious wake-up is seen on recvmsg(), ignore it (EAGAIN/EINTR) - if any other error is seen on recvmsg() propagate it, thus disabling processing of further wakeups - if any error is seen on later code in the function, warn about it but do not propagate it, as in this cas we're not going to busy loop as the offending message is already dequeued. --- src/core/manager.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 5253cb3712..ab65d630a1 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1722,14 +1722,13 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); if (n < 0) { - if (!IN_SET(errno, EAGAIN, EINTR)) - log_error("Failed to receive notification message: %m"); + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; /* Spurious wakeup, try again */ - /* It's not an option to return an error here since it - * would disable the notification handler entirely. Services - * wouldn't be able to send the WATCHDOG message for - * example... */ - return 0; + /* If this is any other, real error, then let's stop processing this socket. This of course means we + * won't take notification messages anymore, but that's still better than busy looping around this: + * being woken up over and over again but being unable to actually read the message off the socket. */ + return log_error_errno(errno, "Failed to receive notification message: %m"); } CMSG_FOREACH(cmsg, &msghdr) { -- cgit v1.2.3-54-g00ecf From 045a3d5989f7565dc496013a9e96d95d86a12cc8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Oct 2016 12:12:10 +0200 Subject: manager: be stricter with incomining notifications, warn properly about too large ones Let's make the kernel let us know the full, original datagram size of the incoming message. If it's larger than the buffer space provided by us, drop the whole message with a warning. Before this change the kernel would truncate the message for us to the buffer space provided, and we'd not complain about this, and simply process the incomplete message as far as it made sense. --- src/core/manager.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index ab65d630a1..66b8904e4e 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1720,7 +1720,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t return 0; } - n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC); if (n < 0) { if (IN_SET(errno, EAGAIN, EINTR)) return 0; /* Spurious wakeup, try again */ @@ -1761,7 +1761,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t return 0; } - if ((size_t) n >= sizeof(buf)) { + if ((size_t) n >= sizeof(buf) || (msghdr.msg_flags & MSG_TRUNC)) { log_warning("Received notify message exceeded maximum size. Ignoring."); return 0; } -- cgit v1.2.3-54-g00ecf From 875ca88da576b4f7c412f6a5e1fc642ba3bd288a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Oct 2016 12:14:33 +0200 Subject: manager: tighten incoming notification message checks Let's not accept datagrams with embedded NUL bytes. Previously we'd simply ignore everything after the first NUL byte. But given that sending us that is pretty ugly let's instead complain and refuse. With this change we'll only accept messages that have exactly zero or one NUL bytes at the very end of the datagram. --- src/core/manager.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 66b8904e4e..34db276a7d 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1766,8 +1766,14 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t return 0; } - /* The message should be a string. Here we make sure it's NUL-terminated, - * but only the part until first NUL will be used anyway. */ + /* As extra safety check, let's make sure the string we get doesn't contain embedded NUL bytes. We permit one + * trailing NUL byte in the message, but don't expect it. */ + if (n > 1 && memchr(buf, 0, n-1)) { + log_warning("Received notify message with embedded NUL bytes. Ignoring."); + return 0; + } + + /* Make sure it's NUL-terminated. */ buf[n] = 0; /* Notify every unit that might be interested, but try -- cgit v1.2.3-54-g00ecf From 171b53380085b1288b03b19a2b978f36a5c003d0 Mon Sep 17 00:00:00 2001 From: rwmjones Date: Fri, 7 Oct 2016 13:56:27 +0100 Subject: architecture: Add support for the RISC-V architecture. (#4305) RISC-V is an open source ISA in development since 2010 at UCB. For more information, see https://riscv.org/ I am adding RISC-V support to Fedora: https://fedoraproject.org/wiki/Architectures/RISC-V There are three major variants of the architecture (32-, 64- and 128-bit). The 128-bit variant is a paper exercise, but the other two really exist in silicon. RISC-V is always little endian. On Linux, the default kernel uname(2) can return "riscv" for all variants. However a patch was added recently which makes the kernel return one of "riscv32" or "riscv64" (or in future "riscv128"). So systemd should be prepared to handle any of "riscv", "riscv32" or "riscv64" (in future, "riscv128" but that is not included in the current patch). If the kernel returns "riscv" then you need to use the pointer size in order to know the real variant. The Fedora/RISC-V kernel only ever returns "riscv64" since we're only doing Fedora for 64 bit at the moment, and we've patched the kernel so it doesn't return "riscv". As well as the major bitsize variants, there are also architecture extensions. However I'm trying to ensure that uname(2) does *not* return any other information about those in utsname.machine, so that we don't end up with "riscv64abcde" nonsense. Instead those extensions will be exposed in /proc/cpuinfo similar to how flags work in x86. --- src/basic/architecture.c | 10 ++++++++++ src/basic/architecture.h | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/basic/architecture.c b/src/basic/architecture.c index b1c8e91f50..b74dc0db78 100644 --- a/src/basic/architecture.c +++ b/src/basic/architecture.c @@ -123,6 +123,14 @@ int uname_architecture(void) { { "crisv32", ARCHITECTURE_CRIS }, #elif defined(__nios2__) { "nios2", ARCHITECTURE_NIOS2 }, +#elif defined(__riscv__) + { "riscv32", ARCHITECTURE_RISCV32 }, + { "riscv64", ARCHITECTURE_RISCV64 }, +# if __SIZEOF_POINTER__ == 4 + { "riscv", ARCHITECTURE_RISCV32 }, +# elif __SIZEOF_POINTER__ == 8 + { "riscv", ARCHITECTURE_RISCV64 }, +# endif #else #error "Please register your architecture here!" #endif @@ -174,6 +182,8 @@ static const char *const architecture_table[_ARCHITECTURE_MAX] = { [ARCHITECTURE_TILEGX] = "tilegx", [ARCHITECTURE_CRIS] = "cris", [ARCHITECTURE_NIOS2] = "nios2", + [ARCHITECTURE_RISCV32] = "riscv32", + [ARCHITECTURE_RISCV64] = "riscv64", }; DEFINE_STRING_TABLE_LOOKUP(architecture, int); diff --git a/src/basic/architecture.h b/src/basic/architecture.h index b3e4d85906..5a77c31932 100644 --- a/src/basic/architecture.h +++ b/src/basic/architecture.h @@ -58,6 +58,8 @@ enum { ARCHITECTURE_TILEGX, ARCHITECTURE_CRIS, ARCHITECTURE_NIOS2, + ARCHITECTURE_RISCV32, + ARCHITECTURE_RISCV64, _ARCHITECTURE_MAX, _ARCHITECTURE_INVALID = -1 }; @@ -191,6 +193,16 @@ int uname_architecture(void); #elif defined(__nios2__) # define native_architecture() ARCHITECTURE_NIOS2 # define LIB_ARCH_TUPLE "nios2-linux-gnu" +#elif defined(__riscv__) +# if __SIZEOF_POINTER__ == 4 +# define native_architecture() ARCHITECTURE_RISCV32 +# define LIB_ARCH_TUPLE "riscv32-linux-gnu" +# elif __SIZEOF_POINTER__ == 8 +# define native_architecture() ARCHITECTURE_RISCV64 +# define LIB_ARCH_TUPLE "riscv64-linux-gnu" +# else +# error "Unrecognized riscv architecture variant" +# endif #else # error "Please register your architecture here!" #endif -- cgit v1.2.3-54-g00ecf From 16441027352ba442c6664c03af852606035c4a45 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Fri, 7 Oct 2016 19:16:18 +0530 Subject: networkd: remote checksum offload for vxlan (#4110) This patch adds support to remote checksum checksum offload to VXLAN. This patch adds RemoteCheckSumTx and RemoteCheckSumRx vxlan configuration to enable remote checksum offload for transmit and receive on the VXLAN tunnel. --- man/systemd.netdev.xml | 12 ++++++++++++ src/network/networkd-netdev-gperf.gperf | 2 ++ src/network/networkd-netdev-vxlan.c | 8 ++++++++ src/network/networkd-netdev-vxlan.h | 2 ++ 4 files changed, 24 insertions(+) diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index e4527f2837..e378e61dd1 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -554,6 +554,18 @@ A boolean. When true, receiving zero checksums in VXLAN/IPv6 is turned on. + + RemoteCheckSumTx= + + A boolean. When true, remote transmit checksum offload of VXLAN is turned on. + + + + RemoteCheckSumRx= + + A boolean. When true, remote receive checksum offload in VXLAN is turned on. + + GroupPolicyExtension= diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf index 6dbb627f15..6b7ab7ab87 100644 --- a/src/network/networkd-netdev-gperf.gperf +++ b/src/network/networkd-netdev-gperf.gperf @@ -65,6 +65,8 @@ VXLAN.RouteShortCircuit, config_parse_bool, 0, VXLAN.UDPCheckSum, config_parse_bool, 0, offsetof(VxLan, udpcsum) VXLAN.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx) VXLAN.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx) +VXLAN.RemoteCheckSumTx, config_parse_bool, 0, offsetof(VxLan, remote_csum_tx) +VXLAN.RemoteCheckSumRx, config_parse_bool, 0, offsetof(VxLan, remote_csum_rx) VXLAN.FDBAgeingSec, config_parse_sec, 0, offsetof(VxLan, fdb_ageing) VXLAN.GroupPolicyExtension, config_parse_bool, 0, offsetof(VxLan, group_policy) VXLAN.MaximumFDBEntries, config_parse_unsigned, 0, offsetof(VxLan, max_fdb) diff --git a/src/network/networkd-netdev-vxlan.c b/src/network/networkd-netdev-vxlan.c index 724f9861be..706e52b698 100644 --- a/src/network/networkd-netdev-vxlan.c +++ b/src/network/networkd-netdev-vxlan.c @@ -112,6 +112,14 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %m"); + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_REMCSUM_TX, v->remote_csum_tx); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_REMCSUM_TX attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_REMCSUM_RX, v->remote_csum_rx); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_REMCSUM_RX attribute: %m"); + r = sd_netlink_message_append_u16(m, IFLA_VXLAN_PORT, htobe16(v->dest_port)); if (r < 0) return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT attribute: %m"); diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h index 4614c66fd1..3906820afb 100644 --- a/src/network/networkd-netdev-vxlan.h +++ b/src/network/networkd-netdev-vxlan.h @@ -50,6 +50,8 @@ struct VxLan { bool udpcsum; bool udp6zerocsumtx; bool udp6zerocsumrx; + bool remote_csum_tx; + bool remote_csum_rx; bool group_policy; struct ifla_vxlan_port_range port_range; -- cgit v1.2.3-54-g00ecf From 8f4d6401351b1114117a1517283f00c7f349c9ff Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 7 Oct 2016 09:39:42 -0400 Subject: core: only warn on short reads on signal fd --- src/core/manager.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 34db276a7d..c1dce62a18 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1946,14 +1946,17 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t for (;;) { n = read(m->signal_fd, &sfsi, sizeof(sfsi)); if (n != sizeof(sfsi)) { + if (n >= 0) { + log_warning("Truncated read from signal fd (%zu bytes)!", n); + return 0; + } - if (n >= 0) - return -EIO; - - if (errno == EINTR || errno == EAGAIN) + if (IN_SET(errno, EINTR, EAGAIN)) break; - return -errno; + /* We return an error here, which will kill this handler, + * to avoid a busy loop on read error. */ + return log_error_errno(errno, "Reading from signal fd failed: %m"); } log_received_signal(sfsi.ssi_signo == SIGCHLD || -- cgit v1.2.3-54-g00ecf From 4a39c774196f1a694477432f845e8bd62efee245 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 19:18:15 +0200 Subject: strv: fix STRV_FOREACH_BACKWARDS() to be a single statement only Let's make sure people invoking STRV_FOREACH_BACKWARDS() as a single statement of an if statement don't fall into a trap, and find the tail for the list via strv_length(). --- src/basic/strv.h | 11 +++++++---- src/test/test-strv.c | 9 +++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/basic/strv.h b/src/basic/strv.h index fec2597db0..385ad17779 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -96,10 +96,13 @@ bool strv_overlap(char **a, char **b) _pure_; #define STRV_FOREACH(s, l) \ for ((s) = (l); (s) && *(s); (s)++) -#define STRV_FOREACH_BACKWARDS(s, l) \ - STRV_FOREACH(s, l) \ - ; \ - for ((s)--; (l) && ((s) >= (l)); (s)--) +#define STRV_FOREACH_BACKWARDS(s, l) \ + for (s = ({ \ + char **_l = l; \ + _l ? _l + strv_length(_l) - 1U : NULL; \ + }); \ + (l) && ((s) >= (l)); \ + (s)--) #define STRV_FOREACH_PAIR(x, y, l) \ for ((x) = (l), (y) = (x+1); (x) && *(x) && *(y); (x) += 2, (y) = (x + 1)) diff --git a/src/test/test-strv.c b/src/test/test-strv.c index ce20f2dd5b..88da69e2d7 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -453,9 +453,14 @@ static void test_strv_foreach_backwards(void) { assert_se(a); - STRV_FOREACH_BACKWARDS(check, a) { + STRV_FOREACH_BACKWARDS(check, a) assert_se(streq_ptr(*check, input_table_multiple[i--])); - } + + STRV_FOREACH_BACKWARDS(check, (char**) NULL) + assert_not_reached("Let's see that we check empty strv right, too."); + + STRV_FOREACH_BACKWARDS(check, (char**) { NULL }) + assert_not_reached("Let's see that we check empty strv right, too."); } static void test_strv_foreach_pair(void) { -- cgit v1.2.3-54-g00ecf From 766c94ad6b6d6101520a02aa2906ca7a446f4863 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 26 Aug 2016 19:20:02 +0200 Subject: bus-util: generalize helper for ID128 prpoerties This way, we can make use of this in other code, too. --- src/machine/machine-dbus.c | 20 +------------------- src/shared/bus-util.c | 17 +++++++++++++++++ src/shared/bus-util.h | 1 + 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index ba7ac04b56..5ca18ff87e 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -51,24 +51,6 @@ #include "terminal-util.h" #include "user-util.h" -static int property_get_id( - sd_bus *bus, - const char *path, - const char *interface, - const char *property, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error) { - - Machine *m = userdata; - - assert(bus); - assert(reply); - assert(m); - - return sd_bus_message_append_array(reply, 'y', &m->id, 16); -} - static int property_get_state( sd_bus *bus, const char *path, @@ -1311,7 +1293,7 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda const sd_bus_vtable machine_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Id", "ay", property_get_id, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Id", "ay", bus_property_get_id128, offsetof(Machine, id), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Unit", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index e2a216a5cc..64fcf9295f 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1324,6 +1324,23 @@ int bus_property_get_bool( return sd_bus_message_append_basic(reply, 'b', &b); } +int bus_property_get_id128( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + sd_id128_t *id = userdata; + + if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */ + return sd_bus_message_append(reply, "ay", 0); + else + return sd_bus_message_append_array(reply, 'b', id->bytes, 16); +} + #if __SIZEOF_SIZE_T__ != 8 int bus_property_get_size( sd_bus *bus, diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index db6b1acba2..934e0b5b77 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -79,6 +79,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all); int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); +int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); #define bus_property_get_usec ((sd_bus_property_get_t) NULL) #define bus_property_set_usec ((sd_bus_property_set_t) NULL) -- cgit v1.2.3-54-g00ecf From d473176a74891256b95a4a5c89f1c0b9e1440945 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Aug 2016 21:00:52 +0200 Subject: journal: complete slice info in journal metadata We are already attaching the system slice information to log messages, now add theuser slice info too, as well as the object slice info. --- src/journal/journald-server.c | 20 +++++++++++++++++++- src/journal/journald-server.h | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index a762558e3d..79a93df26a 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -713,7 +713,7 @@ static void dispatch_message_real( assert(s); assert(iovec); assert(n > 0); - assert(n + N_IOVEC_META_FIELDS + (object_pid ? N_IOVEC_OBJECT_FIELDS : 0) <= m); + assert(n + N_IOVEC_META_FIELDS + (object_pid > 0 ? N_IOVEC_OBJECT_FIELDS : 0) <= m); if (ucred) { realuid = ucred->uid; @@ -814,6 +814,12 @@ static void dispatch_message_real( IOVEC_SET_STRING(iovec[n++], x); } + if (cg_path_get_user_slice(c, &t) >= 0) { + x = strjoina("_SYSTEMD_USER_SLICE=", t); + free(t); + IOVEC_SET_STRING(iovec[n++], x); + } + free(c); } else if (unit_id) { x = strjoina("_SYSTEMD_UNIT=", unit_id); @@ -919,6 +925,18 @@ static void dispatch_message_real( IOVEC_SET_STRING(iovec[n++], x); } + if (cg_path_get_slice(c, &t) >= 0) { + x = strjoina("OBJECT_SYSTEMD_SLICE=", t); + free(t); + IOVEC_SET_STRING(iovec[n++], x); + } + + if (cg_path_get_user_slice(c, &t) >= 0) { + x = strjoina("OBJECT_SYSTEMD_USER_SLICE=", t); + free(t); + IOVEC_SET_STRING(iovec[n++], x); + } + free(c); } } diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index d2a32ab422..784d24833d 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -153,10 +153,10 @@ struct Server { #define SERVER_MACHINE_ID(s) ((s)->machine_id_field + strlen("_MACHINE_ID=")) -#define N_IOVEC_META_FIELDS 20 +#define N_IOVEC_META_FIELDS 21 #define N_IOVEC_KERNEL_FIELDS 64 #define N_IOVEC_UDEV_FIELDS 32 -#define N_IOVEC_OBJECT_FIELDS 12 +#define N_IOVEC_OBJECT_FIELDS 14 #define N_IOVEC_PAYLOAD_FIELDS 15 void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority, pid_t object_pid); -- cgit v1.2.3-54-g00ecf From 398a50cdd198d2573566f44c39c335fb8a3749bf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Aug 2016 21:01:58 +0200 Subject: journal: fix format string used for usec_t --- src/journal/journald-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 79a93df26a..015b74b203 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -943,7 +943,7 @@ static void dispatch_message_real( assert(n <= m); if (tv) { - sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu", (unsigned long long) timeval_load(tv)); + sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=" USEC_FMT, timeval_load(tv)); IOVEC_SET_STRING(iovec[n++], source_time); } -- cgit v1.2.3-54-g00ecf From 0474ef7b3ed81f0e568b88d0d84d3ab6446561d0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Aug 2016 21:02:36 +0200 Subject: log: minor fixes Most important is a fix to negate the error number if necessary, before we first access it. --- src/basic/log.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/basic/log.c b/src/basic/log.c index 49b4598b7c..6a8dad311d 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -133,7 +133,7 @@ static int create_log_socket(int type) { if (fd < 0) return -errno; - fd_inc_sndbuf(fd, SNDBUF_SIZE); + (void) fd_inc_sndbuf(fd, SNDBUF_SIZE); /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever in the @@ -343,7 +343,7 @@ static int write_to_console( return 0; if (log_target == LOG_TARGET_CONSOLE_PREFIXED) { - sprintf(prefix, "<%i>", level); + xsprintf(prefix, "<%i>", level); IOVEC_SET_STRING(iovec[n++], prefix); } @@ -563,6 +563,9 @@ static int log_dispatch( assert(buffer); + if (error < 0) + error = -error; + if (log_target == LOG_TARGET_NULL) return -error; @@ -570,9 +573,6 @@ static int log_dispatch( if ((level & LOG_FACMASK) == 0) level = log_facility | LOG_PRI(level); - if (error < 0) - error = -error; - do { char *e; int k = 0; -- cgit v1.2.3-54-g00ecf From e5d855d364a2a474cb42da618d2e4372619ac61d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Aug 2016 21:49:26 +0200 Subject: util: use SPECIAL_ROOT_SLICE macro where appropriate --- src/basic/cgroup-util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 9b44c5a7a5..7675ab0299 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1666,7 +1666,7 @@ int cg_path_get_slice(const char *p, char **slice) { if (!e) { char *s; - s = strdup("-.slice"); + s = strdup(SPECIAL_ROOT_SLICE); if (!s) return -ENOMEM; @@ -1821,7 +1821,7 @@ int cg_slice_to_path(const char *unit, char **ret) { assert(unit); assert(ret); - if (streq(unit, "-.slice")) { + if (streq(unit, SPECIAL_ROOT_SLICE)) { char *x; x = strdup(""); -- cgit v1.2.3-54-g00ecf From 4b58153dd22172d817055d2a09a0cdf3f4bd9db3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 30 Aug 2016 23:18:46 +0200 Subject: core: add "invocation ID" concept to service manager This adds a new invocation ID concept to the service manager. The invocation ID identifies each runtime cycle of a unit uniquely. A new randomized 128bit ID is generated each time a unit moves from and inactive to an activating or active state. The primary usecase for this concept is to connect the runtime data PID 1 maintains about a service with the offline data the journal stores about it. Previously we'd use the unit name plus start/stop times, which however is highly racy since the journal will generally process log data after the service already ended. The "invocation ID" kinda matches the "boot ID" concept of the Linux kernel, except that it applies to an individual unit instead of the whole system. The invocation ID is passed to the activated processes as environment variable. It is additionally stored as extended attribute on the cgroup of the unit. The latter is used by journald to automatically retrieve it for each log logged message and attach it to the log entry. The environment variable is very easily accessible, even for unprivileged services. OTOH the extended attribute is only accessible to privileged processes (this is because cgroupfs only supports the "trusted." xattr namespace, not "user."). The environment variable may be altered by services, the extended attribute may not be, hence is the better choice for the journal. Note that reading the invocation ID off the extended attribute from journald is racy, similar to the way reading the unit name for a logging process is. This patch adds APIs to read the invocation ID to sd-id128: sd_id128_get_invocation() may be used in a similar fashion to sd_id128_get_boot(). PID1's own logging is updated to always include the invocation ID when it logs information about a unit. A new bus call GetUnitByInvocationID() is added that allows retrieving a bus path to a unit by its invocation ID. The bus path is built using the invocation ID, thus providing a path for referring to a unit that is valid only for the current runtime cycleof it. Outlook for the future: should the kernel eventually allow passing of cgroup information along AF_UNIX/SOCK_DGRAM messages via a unique cgroup id, then we can alter the invocation ID to be generated as hash from that rather than entirely randomly. This way we can derive the invocation race-freely from the messages. --- Makefile-man.am | 5 ++ man/sd_id128_get_machine.xml | 34 +++++++----- man/systemd.exec.xml | 10 ++++ src/basic/cgroup-util.c | 38 +++++++++++++ src/basic/cgroup-util.h | 3 ++ src/basic/log.c | 45 +++++++++------- src/basic/log.h | 10 ++-- src/core/automount.c | 4 ++ src/core/busname.c | 4 ++ src/core/cgroup.c | 21 ++++++++ src/core/dbus-manager.c | 59 +++++++++++++++++++++ src/core/dbus-unit.c | 1 + src/core/device.c | 4 ++ src/core/execute.c | 10 +++- src/core/manager.c | 24 ++++++++- src/core/manager.h | 4 ++ src/core/mount.c | 11 ++-- src/core/org.freedesktop.systemd1.conf | 4 ++ src/core/path.c | 4 ++ src/core/scope.c | 4 ++ src/core/service.c | 4 ++ src/core/slice.c | 5 ++ src/core/socket.c | 5 +- src/core/swap.c | 5 ++ src/core/target.c | 5 ++ src/core/timer.c | 6 ++- src/core/unit.c | 88 ++++++++++++++++++++++++++++++- src/core/unit.h | 10 +++- src/journal/journald-server.c | 60 ++++++++++++++++++--- src/journal/journald-server.h | 2 +- src/libsystemd/libsystemd.sym | 1 + src/libsystemd/sd-bus/bus-common-errors.c | 1 + src/libsystemd/sd-bus/bus-common-errors.h | 1 + src/libsystemd/sd-id128/id128-util.c | 13 +++++ src/libsystemd/sd-id128/id128-util.h | 6 +++ src/libsystemd/sd-id128/sd-id128.c | 22 ++++++++ src/network/networkd-link.h | 2 +- src/network/networkd-netdev.h | 2 +- src/shared/bus-util.c | 2 +- src/systemd/sd-id128.h | 2 +- 40 files changed, 486 insertions(+), 55 deletions(-) diff --git a/Makefile-man.am b/Makefile-man.am index ef5077cc5a..5760878fe3 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -395,6 +395,7 @@ MANPAGES_ALIAS += \ man/sd_id128_equal.3 \ man/sd_id128_from_string.3 \ man/sd_id128_get_boot.3 \ + man/sd_id128_get_invocation.3 \ man/sd_id128_t.3 \ man/sd_is_mq.3 \ man/sd_is_socket.3 \ @@ -745,6 +746,7 @@ man/sd_event_unrefp.3: man/sd_event_new.3 man/sd_id128_equal.3: man/sd-id128.3 man/sd_id128_from_string.3: man/sd_id128_to_string.3 man/sd_id128_get_boot.3: man/sd_id128_get_machine.3 +man/sd_id128_get_invocation.3: man/sd_id128_get_machine.3 man/sd_id128_t.3: man/sd-id128.3 man/sd_is_mq.3: man/sd_is_fifo.3 man/sd_is_socket.3: man/sd_is_fifo.3 @@ -1519,6 +1521,9 @@ man/sd_id128_from_string.html: man/sd_id128_to_string.html man/sd_id128_get_boot.html: man/sd_id128_get_machine.html $(html-alias) +man/sd_id128_get_invocation.html: man/sd_id128_get_machine.html + $(html-alias) + man/sd_id128_t.html: man/sd-id128.html $(html-alias) diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml index 2ad1f8f728..9a86c24aed 100644 --- a/man/sd_id128_get_machine.xml +++ b/man/sd_id128_get_machine.xml @@ -45,6 +45,7 @@ sd_id128_get_machine sd_id128_get_boot + sd_id128_get_invocation Retrieve 128-bit IDs @@ -62,6 +63,11 @@ sd_id128_t *ret + + int sd_id128_get_invocation + sd_id128_t *ret + + @@ -83,11 +89,15 @@ for more information. This function also internally caches the returned ID to make this call a cheap operation. - Note that sd_id128_get_boot() always - returns a UUID v4 compatible ID. - sd_id128_get_machine() will also return a - UUID v4-compatible ID on new installations but might not on older. - It is possible to convert the machine ID into a UUID v4-compatible + sd_id128_get_invocation() returns the invocation ID of the currently executed + service. In its current implementation, this reads and parses the $INVOCATION_ID environment + variable that the service manager sets when activating a service, see + systemd.exec5 for details. The + ID is cached internally. In future a different mechanism to determine the invocation ID may be added. + + Note that sd_id128_get_boot() and sd_id128_get_invocation() always + return UUID v4 compatible IDs. sd_id128_get_machine() will also return a UUID v4-compatible + ID on new installations but might not on older. It is possible to convert the machine ID into a UUID v4-compatible one. For more information, see machine-id5. @@ -107,11 +117,10 @@ Notes - The sd_id128_get_machine() and - sd_id128_get_boot() interfaces are available - as a shared library, which can be compiled and linked to with the - libsystemd pkg-config1 - file. + The sd_id128_get_machine(), sd_id128_get_boot() and + sd_id128_get_invocation() interfaces are available as a shared library, which can be compiled + and linked to with the libsystemd pkg-config1 file. @@ -121,8 +130,9 @@ systemd1, sd-id1283, machine-id5, - random4, - sd_id128_randomize3 + systemd.exec5, + sd_id128_randomize3, + random4 diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 5e6787338d..c73ccaa493 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1513,6 +1513,16 @@ + + $INVOCATION_ID + + Contains a randomized, unique 128bit ID identifying each runtime cycle of the unit, formatted + as 32 character hexadecimal string. A new ID is assigned each time the unit changes from an inactive state into + an activating or active state, and may be used to identify this specific runtime cycle, in particular in data + stored offline, such as the journal. The same ID is passed to all processes run as part of the + unit. + + $XDG_RUNTIME_DIR diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 7675ab0299..37e6928a46 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "alloc-util.h" @@ -883,6 +884,43 @@ int cg_set_task_access( return 0; } +int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags) { + _cleanup_free_ char *fs = NULL; + int r; + + assert(path); + assert(name); + assert(value || size <= 0); + + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) + return r; + + if (setxattr(fs, name, value, size, flags) < 0) + return -errno; + + return 0; +} + +int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size) { + _cleanup_free_ char *fs = NULL; + ssize_t n; + int r; + + assert(path); + assert(name); + + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) + return r; + + n = getxattr(fs, name, value, size); + if (n < 0) + return -errno; + + return (int) n; +} + int cg_pid_get_path(const char *controller, pid_t pid, char **path) { _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX]; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 1a61c7ad22..7529c9719e 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -185,6 +185,9 @@ int cg_get_keyed_attribute(const char *controller, const char *path, const char int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); +int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags); +int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size); + int cg_install_release_agent(const char *controller, const char *agent); int cg_uninstall_release_agent(const char *controller); diff --git a/src/basic/log.c b/src/basic/log.c index 6a8dad311d..bd6c96c4f8 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -330,8 +330,6 @@ static int write_to_console( const char *file, int line, const char *func, - const char *object_field, - const char *object, const char *buffer) { char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2]; @@ -390,8 +388,6 @@ static int write_to_syslog( const char *file, int line, const char *func, - const char *object_field, - const char *object, const char *buffer) { char header_priority[2 + DECIMAL_STR_MAX(int) + 1], @@ -453,8 +449,6 @@ static int write_to_kmsg( const char *file, int line, const char *func, - const char *object_field, - const char *object, const char *buffer) { char header_priority[2 + DECIMAL_STR_MAX(int) + 1], @@ -485,7 +479,8 @@ static int log_do_header( int level, int error, const char *file, int line, const char *func, - const char *object_field, const char *object) { + const char *object_field, const char *object, + const char *extra_field, const char *extra) { snprintf(header, size, "PRIORITY=%i\n" @@ -495,6 +490,7 @@ static int log_do_header( "%s%s%s" "%s%.*i%s" "%s%s%s" + "%s%s%s" "SYSLOG_IDENTIFIER=%s\n", LOG_PRI(level), LOG_FAC(level), @@ -513,6 +509,9 @@ static int log_do_header( isempty(object) ? "" : object_field, isempty(object) ? "" : object, isempty(object) ? "" : "\n", + isempty(extra) ? "" : extra_field, + isempty(extra) ? "" : extra, + isempty(extra) ? "" : "\n", program_invocation_short_name); return 0; @@ -526,6 +525,8 @@ static int write_to_journal( const char *func, const char *object_field, const char *object, + const char *extra_field, + const char *extra, const char *buffer) { char header[LINE_MAX]; @@ -535,7 +536,7 @@ static int write_to_journal( if (journal_fd < 0) return 0; - log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object); + log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra); IOVEC_SET_STRING(iovec[0], header); IOVEC_SET_STRING(iovec[1], "MESSAGE="); @@ -559,6 +560,8 @@ static int log_dispatch( const char *func, const char *object_field, const char *object, + const char *extra, + const char *extra_field, char *buffer) { assert(buffer); @@ -589,7 +592,7 @@ static int log_dispatch( log_target == LOG_TARGET_JOURNAL_OR_KMSG || log_target == LOG_TARGET_JOURNAL) { - k = write_to_journal(level, error, file, line, func, object_field, object, buffer); + k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer); if (k < 0) { if (k != -EAGAIN) log_close_journal(); @@ -600,7 +603,7 @@ static int log_dispatch( if (log_target == LOG_TARGET_SYSLOG_OR_KMSG || log_target == LOG_TARGET_SYSLOG) { - k = write_to_syslog(level, error, file, line, func, object_field, object, buffer); + k = write_to_syslog(level, error, file, line, func, buffer); if (k < 0) { if (k != -EAGAIN) log_close_syslog(); @@ -615,7 +618,7 @@ static int log_dispatch( log_target == LOG_TARGET_JOURNAL_OR_KMSG || log_target == LOG_TARGET_KMSG)) { - k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer); + k = write_to_kmsg(level, error, file, line, func, buffer); if (k < 0) { log_close_kmsg(); log_open_console(); @@ -623,7 +626,7 @@ static int log_dispatch( } if (k <= 0) - (void) write_to_console(level, error, file, line, func, object_field, object, buffer); + (void) write_to_console(level, error, file, line, func, buffer); buffer = e; } while (buffer); @@ -649,7 +652,7 @@ int log_dump_internal( if (_likely_(LOG_PRI(level) > log_max_level)) return -error; - return log_dispatch(level, error, file, line, func, NULL, NULL, buffer); + return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer); } int log_internalv( @@ -676,7 +679,7 @@ int log_internalv( vsnprintf(buffer, sizeof(buffer), format, ap); - return log_dispatch(level, error, file, line, func, NULL, NULL, buffer); + return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer); } int log_internal( @@ -705,6 +708,8 @@ int log_object_internalv( const char *func, const char *object_field, const char *object, + const char *extra_field, + const char *extra, const char *format, va_list ap) { @@ -738,7 +743,7 @@ int log_object_internalv( vsnprintf(b, l, format, ap); - return log_dispatch(level, error, file, line, func, object_field, object, buffer); + return log_dispatch(level, error, file, line, func, object_field, object, extra_field, extra, buffer); } int log_object_internal( @@ -749,13 +754,15 @@ int log_object_internal( const char *func, const char *object_field, const char *object, + const char *extra_field, + const char *extra, const char *format, ...) { va_list ap; int r; va_start(ap, format); - r = log_object_internalv(level, error, file, line, func, object_field, object, format, ap); + r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap); va_end(ap); return r; @@ -780,7 +787,7 @@ static void log_assert( log_abort_msg = buffer; - log_dispatch(level, 0, file, line, func, NULL, NULL, buffer); + log_dispatch(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer); } noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) { @@ -888,7 +895,7 @@ int log_struct_internal( bool fallback = false; /* If the journal is available do structured logging */ - log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL); + log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL); IOVEC_SET_STRING(iovec[n++], header); va_start(ap, format); @@ -935,7 +942,7 @@ int log_struct_internal( if (!found) return -error; - return log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8); + return log_dispatch(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8); } int log_set_target_from_string(const char *e) { diff --git a/src/basic/log.h b/src/basic/log.h index b6356228d9..2afee20bb5 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -100,18 +100,22 @@ int log_object_internal( const char *func, const char *object_field, const char *object, - const char *format, ...) _printf_(8,9); + const char *extra_field, + const char *extra, + const char *format, ...) _printf_(10,11); int log_object_internalv( int level, int error, - const char*file, + const char *file, int line, const char *func, const char *object_field, const char *object, + const char *extra_field, + const char *extra, const char *format, - va_list ap) _printf_(8,0); + va_list ap) _printf_(9,0); int log_struct_internal( int level, diff --git a/src/core/automount.c b/src/core/automount.c index bdc0e06965..7d7a0a6e46 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -800,6 +800,10 @@ static int automount_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + a->result = AUTOMOUNT_SUCCESS; automount_enter_waiting(a); return 1; diff --git a/src/core/busname.c b/src/core/busname.c index 7952cd31aa..63c7dde0bd 100644 --- a/src/core/busname.c +++ b/src/core/busname.c @@ -639,6 +639,10 @@ static int busname_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + n->result = BUSNAME_SUCCESS; busname_enter_making(n); diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 7873f88785..20bdbc39d0 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -1361,6 +1361,26 @@ int unit_attach_pids_to_cgroup(Unit *u) { return 0; } +static void cgroup_xattr_apply(Unit *u) { + char ids[SD_ID128_STRING_MAX]; + int r; + + assert(u); + + if (!MANAGER_IS_SYSTEM(u->manager)) + return; + + if (sd_id128_is_null(u->invocation_id)) + return; + + r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, + "trusted.invocation_id", + sd_id128_to_string(u->invocation_id, ids), 32, + 0); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to set invocation ID on control group %s, ignoring: %m", u->cgroup_path); +} + static bool unit_has_mask_realized(Unit *u, CGroupMask target_mask, CGroupMask enable_mask) { assert(u); @@ -1404,6 +1424,7 @@ static int unit_realize_cgroup_now(Unit *u, ManagerState state) { /* Finally, apply the necessary attributes. */ cgroup_context_apply(u, target_mask, state); + cgroup_xattr_apply(u); return 0; } diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index ea7ced2fd0..12eb55cb7f 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -464,6 +464,64 @@ static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bu return sd_bus_reply_method_return(message, "o", path); } +static int method_get_unit_by_invocation_id(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *path = NULL; + Manager *m = userdata; + sd_id128_t id; + const void *a; + Unit *u; + size_t sz; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = sd_bus_message_read_array(message, 'y', &a, &sz); + if (r < 0) + return r; + if (sz == 0) + id = SD_ID128_NULL; + else if (sz == 16) + memcpy(&id, a, sz); + else + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid invocation ID"); + + if (sd_id128_is_null(id)) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + pid_t pid; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + + u = manager_get_unit_by_pid(m, pid); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client " PID_FMT " not member of any unit.", pid); + } else { + u = hashmap_get(m->units_by_invocation_id, &id); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.", SD_ID128_FORMAT_VAL(id)); + } + + r = mac_selinux_unit_access_check(u, message, "status", error); + if (r < 0) + return r; + + /* So here's a special trick: the bus path we return actually references the unit by its invocation ID instead + * of the unit name. This means it stays valid only as long as the invocation ID stays the same. */ + path = unit_dbus_path_invocation_id(u); + if (!path) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", path); +} + static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *path = NULL; Manager *m = userdata; @@ -2254,6 +2312,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitByInvocationID", "ay", "o", method_get_unit_by_invocation_id, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 5020dfba4b..245912fc0f 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -764,6 +764,7 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0), SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/device.c b/src/core/device.c index 16e56efcc3..8a3e888e5e 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -464,6 +464,10 @@ static void device_update_found_one(Device *d, bool add, DeviceFound found, bool if (!now) return; + /* Didn't exist before, but does now? if so, generate a new invocation ID for it */ + if (previous == DEVICE_NOT_FOUND && d->found != DEVICE_NOT_FOUND) + (void) unit_acquire_invocation_id(UNIT(d)); + if (d->found & DEVICE_FOUND_UDEV) /* When the device is known to udev we consider it * plugged. */ diff --git a/src/core/execute.c b/src/core/execute.c index d5c4e60796..7079aeed6e 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1553,10 +1553,11 @@ static int build_environment( unsigned n_env = 0; char *x; + assert(u); assert(c); assert(ret); - our_env = new0(char*, 13); + our_env = new0(char*, 14); if (!our_env) return -ENOMEM; @@ -1627,6 +1628,13 @@ static int build_environment( our_env[n_env++] = x; } + if (!sd_id128_is_null(u->invocation_id)) { + if (asprintf(&x, "INVOCATION_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id)) < 0) + return -ENOMEM; + + our_env[n_env++] = x; + } + if (exec_context_needs_term(c)) { const char *tty_path, *term = NULL; diff --git a/src/core/manager.c b/src/core/manager.c index c1dce62a18..3569249788 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -522,6 +522,7 @@ static void manager_clean_environment(Manager *m) { "LISTEN_FDNAMES", "WATCHDOG_PID", "WATCHDOG_USEC", + "INVOCATION_ID", NULL); } @@ -582,9 +583,15 @@ int manager_new(UnitFileScope scope, bool test_run, Manager **_m) { if (MANAGER_IS_SYSTEM(m)) { m->unit_log_field = "UNIT="; m->unit_log_format_string = "UNIT=%s"; + + m->invocation_log_field = "INVOCATION_ID="; + m->invocation_log_format_string = "INVOCATION_ID=" SD_ID128_FORMAT_STR; } else { m->unit_log_field = "USER_UNIT="; m->unit_log_format_string = "USER_UNIT=%s"; + + m->invocation_log_field = "USER_INVOCATION_ID="; + m->invocation_log_format_string = "USER_INVOCATION_ID=" SD_ID128_FORMAT_STR; } m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1; @@ -1062,6 +1069,7 @@ Manager* manager_free(Manager *m) { hashmap_free(m->dynamic_users); hashmap_free(m->units); + hashmap_free(m->units_by_invocation_id); hashmap_free(m->jobs); hashmap_free(m->watch_pids1); hashmap_free(m->watch_pids2); @@ -2268,6 +2276,7 @@ int manager_loop(Manager *m) { int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u) { _cleanup_free_ char *n = NULL; + sd_id128_t invocation_id; Unit *u; int r; @@ -2279,12 +2288,25 @@ int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, if (r < 0) return r; + /* Permit addressing units by invocation ID: if the passed bus path is suffixed by a 128bit ID then we use it + * as invocation ID. */ + r = sd_id128_from_string(n, &invocation_id); + if (r >= 0) { + u = hashmap_get(m->units_by_invocation_id, &invocation_id); + if (u) { + *_u = u; + return 0; + } + + return sd_bus_error_setf(e, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.", SD_ID128_FORMAT_VAL(invocation_id)); + } + + /* If this didn't work, we use the suffix as unit name. */ r = manager_load_unit(m, n, NULL, e, &u); if (r < 0) return r; *_u = u; - return 0; } diff --git a/src/core/manager.h b/src/core/manager.h index 495440b446..29fe14e10b 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -89,6 +89,7 @@ struct Manager { /* Active jobs and units */ Hashmap *units; /* name string => Unit object n:1 */ + Hashmap *units_by_invocation_id; Hashmap *jobs; /* job id => Job object 1:1 */ /* To make it easy to iterate through the units of a specific @@ -319,6 +320,9 @@ struct Manager { const char *unit_log_field; const char *unit_log_format_string; + const char *invocation_log_field; + const char *invocation_log_format_string; + int first_boot; /* tri-state */ }; diff --git a/src/core/mount.c b/src/core/mount.c index 04025b83b9..436c0e1029 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1005,6 +1005,10 @@ static int mount_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + m->result = MOUNT_SUCCESS; m->reload_result = MOUNT_SUCCESS; m->reset_cpu_usage = true; @@ -1742,9 +1746,10 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, case MOUNT_DEAD: case MOUNT_FAILED: - /* This has just been mounted by - * somebody else, follow the state - * change. */ + + /* This has just been mounted by somebody else, follow the state change, but let's + * generate a new invocation ID for this implicitly and automatically. */ + (void) unit_acquire_invocation_id(UNIT(mount)); mount_enter_mounted(mount, MOUNT_SUCCESS); break; diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index 647e5f736c..6caa15b0b8 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -52,6 +52,10 @@ send_interface="org.freedesktop.systemd1.Manager" send_member="GetUnitByPID"/> + + diff --git a/src/core/path.c b/src/core/path.c index 10f9b06974..83f794be89 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -577,6 +577,10 @@ static int path_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + path_mkdir(p); p->result = PATH_SUCCESS; diff --git a/src/core/scope.c b/src/core/scope.c index 65fa65493b..e7583f6d89 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -298,6 +298,10 @@ static int scope_start(Unit *u) { if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) return -ENOENT; + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + (void) unit_realize_cgroup(u); (void) unit_reset_cpu_usage(u); diff --git a/src/core/service.c b/src/core/service.c index 99a70395fc..8ce25c494c 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2033,6 +2033,10 @@ static int service_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + s->result = SERVICE_SUCCESS; s->reload_result = SERVICE_SUCCESS; s->main_pid_known = false; diff --git a/src/core/slice.c b/src/core/slice.c index c7700b8857..03fe797f27 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -187,10 +187,15 @@ static void slice_dump(Unit *u, FILE *f, const char *prefix) { static int slice_start(Unit *u) { Slice *t = SLICE(u); + int r; assert(t); assert(t->state == SLICE_DEAD); + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + (void) unit_realize_cgroup(u); (void) unit_reset_cpu_usage(u); diff --git a/src/core/socket.c b/src/core/socket.c index b9032fa5c9..ae8a1f751f 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2354,11 +2354,14 @@ static int socket_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + s->result = SOCKET_SUCCESS; s->reset_cpu_usage = true; socket_enter_start_pre(s); - return 1; } diff --git a/src/core/swap.c b/src/core/swap.c index fb222b6858..0333eaefb8 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -861,6 +861,10 @@ static int swap_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + s->result = SWAP_SUCCESS; s->reset_cpu_usage = true; @@ -1189,6 +1193,7 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v case SWAP_DEAD: case SWAP_FAILED: + (void) unit_acquire_invocation_id(UNIT(swap)); swap_enter_active(swap, SWAP_SUCCESS); break; diff --git a/src/core/target.c b/src/core/target.c index 61a91aad07..765c1f3fa4 100644 --- a/src/core/target.c +++ b/src/core/target.c @@ -124,10 +124,15 @@ static void target_dump(Unit *u, FILE *f, const char *prefix) { static int target_start(Unit *u) { Target *t = TARGET(u); + int r; assert(t); assert(t->state == TARGET_DEAD); + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + target_set_state(t, TARGET_ACTIVE); return 1; } diff --git a/src/core/timer.c b/src/core/timer.c index e2b43f02f8..9538059c13 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -616,6 +616,10 @@ static int timer_start(Unit *u) { return r; } + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + t->last_trigger = DUAL_TIMESTAMP_NULL; /* Reenable all timers that depend on unit activation time */ @@ -632,7 +636,7 @@ static int timer_start(Unit *u) { /* The timer has never run before, * make sure a stamp file exists. */ - touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID); + (void) touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID); } t->result = TIMER_SUCCESS; diff --git a/src/core/unit.c b/src/core/unit.c index 693f75c928..690f7f7dd9 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -37,6 +37,7 @@ #include "execute.h" #include "fileio-label.h" #include "formats-util.h" +#include "id128-util.h" #include "load-dropin.h" #include "load-fragment.h" #include "log.h" @@ -521,6 +522,9 @@ void unit_free(Unit *u) { SET_FOREACH(t, u->names, i) hashmap_remove_value(u->manager->units, t, u); + if (!sd_id128_is_null(u->invocation_id)) + hashmap_remove_value(u->manager->units_by_invocation_id, &u->invocation_id, u); + if (u->job) { Job *j = u->job; job_uninstall(j); @@ -953,6 +957,10 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { SET_FOREACH(t, u->names, i) fprintf(f, "%s\tName: %s\n", prefix, t); + if (!sd_id128_is_null(u->invocation_id)) + fprintf(f, "%s\tInvocation ID: " SD_ID128_FORMAT_STR "\n", + prefix, SD_ID128_FORMAT_VAL(u->invocation_id)); + STRV_FOREACH(j, u->documentation) fprintf(f, "%s\tDocumentation: %s\n", prefix, *j); @@ -1054,7 +1062,6 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { if (u->nop_job) job_dump(u->nop_job, f, prefix2); - } /* Common implementation for multiple backends */ @@ -2392,6 +2399,15 @@ char *unit_dbus_path(Unit *u) { return unit_dbus_path_from_name(u->id); } +char *unit_dbus_path_invocation_id(Unit *u) { + assert(u); + + if (sd_id128_is_null(u->invocation_id)) + return NULL; + + return unit_dbus_path_from_name(u->invocation_id_string); +} + int unit_set_slice(Unit *u, Unit *slice) { assert(u); assert(slice); @@ -2640,6 +2656,9 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { if (gid_is_valid(u->ref_gid)) unit_serialize_item_format(u, f, "ref-gid", GID_FMT, u->ref_gid); + if (!sd_id128_is_null(u->invocation_id)) + unit_serialize_item_format(u, f, "invocation-id", SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id)); + bus_track_serialize(u->bus_track, f, "ref"); if (serialize_jobs) { @@ -2914,6 +2933,19 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { if (r < 0) log_oom(); + continue; + } else if (streq(l, "invocation-id")) { + sd_id128_t id; + + r = sd_id128_from_string(v, &id); + if (r < 0) + log_unit_debug(u, "Failed to parse invocation id %s, ignoring.", v); + else { + r = unit_set_invocation_id(u, id); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to set invocation ID for unit: %m"); + } + continue; } @@ -4153,3 +4185,57 @@ void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid) { if (r > 0) bus_unit_send_change_signal(u); } + +int unit_set_invocation_id(Unit *u, sd_id128_t id) { + int r; + + assert(u); + + /* Set the invocation ID for this unit. If we cannot, this will not roll back, but reset the whole thing. */ + + if (sd_id128_equal(u->invocation_id, id)) + return 0; + + if (!sd_id128_is_null(u->invocation_id)) + (void) hashmap_remove_value(u->manager->units_by_invocation_id, &u->invocation_id, u); + + if (sd_id128_is_null(id)) { + r = 0; + goto reset; + } + + r = hashmap_ensure_allocated(&u->manager->units_by_invocation_id, &id128_hash_ops); + if (r < 0) + goto reset; + + u->invocation_id = id; + sd_id128_to_string(id, u->invocation_id_string); + + r = hashmap_put(u->manager->units_by_invocation_id, &u->invocation_id, u); + if (r < 0) + goto reset; + + return 0; + +reset: + u->invocation_id = SD_ID128_NULL; + u->invocation_id_string[0] = 0; + return r; +} + +int unit_acquire_invocation_id(Unit *u) { + sd_id128_t id; + int r; + + assert(u); + + r = sd_id128_randomize(&id); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to generate invocation ID for unit: %m"); + + r = unit_set_invocation_id(u, id); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to set invocation ID for unit: %m"); + + return 0; +} diff --git a/src/core/unit.h b/src/core/unit.h index 3584c16d8c..a8dd3e602c 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -207,6 +207,10 @@ struct Unit { /* How to start OnFailure units */ JobMode on_failure_job_mode; + /* The current invocation ID */ + sd_id128_t invocation_id; + char invocation_id_string[SD_ID128_STRING_MAX]; /* useful when logging */ + /* Garbage collect us we nobody wants or requires us anymore */ bool stop_when_unneeded; @@ -546,6 +550,7 @@ bool unit_job_is_applicable(Unit *u, JobType j); int set_unit_path(const char *p); char *unit_dbus_path(Unit *u); +char *unit_dbus_path_invocation_id(Unit *u); int unit_load_related_unit(Unit *u, const char *type, Unit **_found); @@ -643,12 +648,15 @@ void unit_unref_uid_gid(Unit *u, bool destroy_now); void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid); +int unit_set_invocation_id(Unit *u, sd_id128_t id); +int unit_acquire_invocation_id(Unit *u); + /* Macros which append UNIT= or USER_UNIT= to the message */ #define log_unit_full(unit, level, error, ...) \ ({ \ const Unit *_u = (unit); \ - _u ? log_object_internal(level, error, __FILE__, __LINE__, __func__, _u->manager->unit_log_field, _u->id, ##__VA_ARGS__) : \ + _u ? log_object_internal(level, error, __FILE__, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 015b74b203..f01cf1d937 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -44,6 +44,7 @@ #include "fs-util.h" #include "hashmap.h" #include "hostname-util.h" +#include "id128-util.h" #include "io-util.h" #include "journal-authenticate.h" #include "journal-file.h" @@ -56,6 +57,7 @@ #include "journald-server.h" #include "journald-stream.h" #include "journald-syslog.h" +#include "log.h" #include "missing.h" #include "mkdir.h" #include "parse-util.h" @@ -69,7 +71,6 @@ #include "string-table.h" #include "string-util.h" #include "user-util.h" -#include "log.h" #define USER_JOURNALS_MAX 1024 @@ -675,6 +676,44 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned server_schedule_sync(s, priority); } +static int get_invocation_id(const char *cgroup_root, const char *slice, const char *unit, char **ret) { + _cleanup_free_ char *escaped = NULL, *slice_path = NULL, *p = NULL; + char *copy, ids[SD_ID128_STRING_MAX]; + int r; + + /* Read the invocation ID of a unit off a unit. It's stored in the "trusted.invocation_id" extended attribute + * on the cgroup path. */ + + r = cg_slice_to_path(slice, &slice_path); + if (r < 0) + return r; + + escaped = cg_escape(unit); + if (!escaped) + return -ENOMEM; + + p = strjoin(cgroup_root, "/", slice_path, "/", escaped, NULL); + if (!p) + return -ENOMEM; + + r = cg_get_xattr(SYSTEMD_CGROUP_CONTROLLER, p, "trusted.invocation_id", ids, 32); + if (r < 0) + return r; + if (r != 32) + return -EINVAL; + ids[32] = 0; + + if (!id128_is_valid(ids)) + return -EINVAL; + + copy = strdup(ids); + if (!copy) + return -ENOMEM; + + *ret = copy; + return 0; +} + static void dispatch_message_real( Server *s, struct iovec *iovec, unsigned n, unsigned m, @@ -771,6 +810,7 @@ static void dispatch_message_real( r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &c); if (r >= 0) { + _cleanup_free_ char *raw_unit = NULL, *raw_slice = NULL; char *session = NULL; x = strjoina("_SYSTEMD_CGROUP=", c); @@ -790,9 +830,8 @@ static void dispatch_message_real( IOVEC_SET_STRING(iovec[n++], owner_uid); } - if (cg_path_get_unit(c, &t) >= 0) { - x = strjoina("_SYSTEMD_UNIT=", t); - free(t); + if (cg_path_get_unit(c, &raw_unit) >= 0) { + x = strjoina("_SYSTEMD_UNIT=", raw_unit); IOVEC_SET_STRING(iovec[n++], x); } else if (unit_id && !session) { x = strjoina("_SYSTEMD_UNIT=", unit_id); @@ -808,9 +847,8 @@ static void dispatch_message_real( IOVEC_SET_STRING(iovec[n++], x); } - if (cg_path_get_slice(c, &t) >= 0) { - x = strjoina("_SYSTEMD_SLICE=", t); - free(t); + if (cg_path_get_slice(c, &raw_slice) >= 0) { + x = strjoina("_SYSTEMD_SLICE=", raw_slice); IOVEC_SET_STRING(iovec[n++], x); } @@ -820,6 +858,14 @@ static void dispatch_message_real( IOVEC_SET_STRING(iovec[n++], x); } + if (raw_slice && raw_unit) { + if (get_invocation_id(s->cgroup_root, raw_slice, raw_unit, &t) >= 0) { + x = strjoina("_SYSTEMD_INVOCATION_ID=", t); + free(t); + IOVEC_SET_STRING(iovec[n++], x); + } + } + free(c); } else if (unit_id) { x = strjoina("_SYSTEMD_UNIT=", unit_id); diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 784d24833d..dfb5724794 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -153,7 +153,7 @@ struct Server { #define SERVER_MACHINE_ID(s) ((s)->machine_id_field + strlen("_MACHINE_ID=")) -#define N_IOVEC_META_FIELDS 21 +#define N_IOVEC_META_FIELDS 22 #define N_IOVEC_KERNEL_FIELDS 64 #define N_IOVEC_UDEV_FIELDS 32 #define N_IOVEC_OBJECT_FIELDS 14 diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 70ea347361..d48ef6bbe2 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -509,4 +509,5 @@ global: sd_bus_track_count_sender; sd_bus_set_exit_on_disconnect; sd_bus_get_exit_on_disconnect; + sd_id128_get_invocation; } LIBSYSTEMD_231; diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index 9cc28ed564..d2a826bf6e 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -27,6 +27,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_UNIT, ENOENT), SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_PID, ESRCH), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, ENOENT), SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS, EEXIST), SD_BUS_ERROR_MAP(BUS_ERROR_LOAD_FAILED, EIO), SD_BUS_ERROR_MAP(BUS_ERROR_JOB_FAILED, EREMOTEIO), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index 5df21c8926..525b79fa77 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -23,6 +23,7 @@ #define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit" #define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID" +#define BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID "org.freedesktop.systemd1.NoUnitForInvocationID" #define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists" #define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed" #define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed" diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c index c3f527d657..337eae24b4 100644 --- a/src/libsystemd/sd-id128/id128-util.c +++ b/src/libsystemd/sd-id128/id128-util.c @@ -192,3 +192,16 @@ int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) { return id128_write_fd(fd, f, id, do_sync); } + +void id128_hash_func(const void *p, struct siphash *state) { + siphash24_compress(p, 16, state); +} + +int id128_compare_func(const void *a, const void *b) { + return memcmp(a, b, 16); +} + +const struct hash_ops id128_hash_ops = { + .hash = id128_hash_func, + .compare = id128_compare_func, +}; diff --git a/src/libsystemd/sd-id128/id128-util.h b/src/libsystemd/sd-id128/id128-util.h index 3ba59acbca..6b3855acbb 100644 --- a/src/libsystemd/sd-id128/id128-util.h +++ b/src/libsystemd/sd-id128/id128-util.h @@ -22,6 +22,8 @@ #include #include "sd-id128.h" + +#include "hash-funcs.h" #include "macro.h" char *id128_to_uuid_string(sd_id128_t id, char s[37]); @@ -43,3 +45,7 @@ int id128_read(const char *p, Id128Format f, sd_id128_t *ret); int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync); int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync); + +void id128_hash_func(const void *p, struct siphash *state); +int id128_compare_func(const void *a, const void *b) _pure_; +extern const struct hash_ops id128_hash_ops; diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c index 9f47d04e61..d4450c70a0 100644 --- a/src/libsystemd/sd-id128/sd-id128.c +++ b/src/libsystemd/sd-id128/sd-id128.c @@ -129,6 +129,28 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) { return 0; } +_public_ int sd_id128_get_invocation(sd_id128_t *ret) { + static thread_local sd_id128_t saved_invocation_id = {}; + int r; + + assert_return(ret, -EINVAL); + + if (sd_id128_is_null(saved_invocation_id)) { + const char *e; + + e = secure_getenv("INVOCATION_ID"); + if (!e) + return -ENXIO; + + r = sd_id128_from_string(e, &saved_invocation_id); + if (r < 0) + return r; + } + + *ret = saved_invocation_id; + return 0; +} + static sd_id128_t make_v4_uuid(sd_id128_t id) { /* Stolen from generate_random_uuid() of drivers/char/random.c * in the kernel sources */ diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 05b2a2b323..77f72d070e 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -187,7 +187,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); #define log_link_full(link, level, error, ...) \ ({ \ const Link *_l = (link); \ - _l ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, ##__VA_ARGS__) : \ + _l ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) \ diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h index 31b55e2791..70ff947b99 100644 --- a/src/network/networkd-netdev.h +++ b/src/network/networkd-netdev.h @@ -182,7 +182,7 @@ const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsign #define log_netdev_full(netdev, level, error, ...) \ ({ \ const NetDev *_n = (netdev); \ - _n ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _n->ifname, ##__VA_ARGS__) : \ + _n ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _n->ifname, NULL, NULL, ##__VA_ARGS__) : \ log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ }) diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 64fcf9295f..bb90c89cc2 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1338,7 +1338,7 @@ int bus_property_get_id128( if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */ return sd_bus_message_append(reply, "ay", 0); else - return sd_bus_message_append_array(reply, 'b', id->bytes, 16); + return sd_bus_message_append_array(reply, 'y', id->bytes, 16); } #if __SIZEOF_SIZE_T__ != 8 diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h index 4dff0b9b81..ee011b1861 100644 --- a/src/systemd/sd-id128.h +++ b/src/systemd/sd-id128.h @@ -45,8 +45,8 @@ int sd_id128_from_string(const char *s, sd_id128_t *ret); int sd_id128_randomize(sd_id128_t *ret); int sd_id128_get_machine(sd_id128_t *ret); - int sd_id128_get_boot(sd_id128_t *ret); +int sd_id128_get_invocation(sd_id128_t *ret); #define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \ ((const sd_id128_t) { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \ -- cgit v1.2.3-54-g00ecf From 3dbea941d2ee2700eb5e42c8b8352c841e9e0d96 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 31 Aug 2016 12:23:27 +0200 Subject: man: update sd-id128(3) a bit Let's add documentation about SD_ID128_NULL and sd_id128_is_null(). Let's also indent our examples by 8chs, as is generally our coding style. --- Makefile-man.am | 10 ++++++++++ man/sd-id128.xml | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/Makefile-man.am b/Makefile-man.am index 5760878fe3..a900b8d25a 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -239,6 +239,7 @@ MANPAGES_ALIAS += \ man/SD_ID128_FORMAT_STR.3 \ man/SD_ID128_FORMAT_VAL.3 \ man/SD_ID128_MAKE.3 \ + man/SD_ID128_NULL.3 \ man/SD_INFO.3 \ man/SD_JOURNAL_APPEND.3 \ man/SD_JOURNAL_CURRENT_USER.3 \ @@ -396,6 +397,7 @@ MANPAGES_ALIAS += \ man/sd_id128_from_string.3 \ man/sd_id128_get_boot.3 \ man/sd_id128_get_invocation.3 \ + man/sd_id128_is_null.3 \ man/sd_id128_t.3 \ man/sd_is_mq.3 \ man/sd_is_socket.3 \ @@ -590,6 +592,7 @@ man/SD_ID128_CONST_STR.3: man/sd-id128.3 man/SD_ID128_FORMAT_STR.3: man/sd-id128.3 man/SD_ID128_FORMAT_VAL.3: man/sd-id128.3 man/SD_ID128_MAKE.3: man/sd-id128.3 +man/SD_ID128_NULL.3: man/sd-id128.3 man/SD_INFO.3: man/sd-daemon.3 man/SD_JOURNAL_APPEND.3: man/sd_journal_get_fd.3 man/SD_JOURNAL_CURRENT_USER.3: man/sd_journal_open.3 @@ -747,6 +750,7 @@ man/sd_id128_equal.3: man/sd-id128.3 man/sd_id128_from_string.3: man/sd_id128_to_string.3 man/sd_id128_get_boot.3: man/sd_id128_get_machine.3 man/sd_id128_get_invocation.3: man/sd_id128_get_machine.3 +man/sd_id128_is_null.3: man/sd-id128.3 man/sd_id128_t.3: man/sd-id128.3 man/sd_is_mq.3: man/sd_is_fifo.3 man/sd_is_socket.3: man/sd_is_fifo.3 @@ -1053,6 +1057,9 @@ man/SD_ID128_FORMAT_VAL.html: man/sd-id128.html man/SD_ID128_MAKE.html: man/sd-id128.html $(html-alias) +man/SD_ID128_NULL.html: man/sd-id128.html + $(html-alias) + man/SD_INFO.html: man/sd-daemon.html $(html-alias) @@ -1524,6 +1531,9 @@ man/sd_id128_get_boot.html: man/sd_id128_get_machine.html man/sd_id128_get_invocation.html: man/sd_id128_get_machine.html $(html-alias) +man/sd_id128_is_null.html: man/sd-id128.html + $(html-alias) + man/sd_id128_t.html: man/sd-id128.html $(html-alias) diff --git a/man/sd-id128.xml b/man/sd-id128.xml index ea7972055d..5f24feff8e 100644 --- a/man/sd-id128.xml +++ b/man/sd-id128.xml @@ -47,10 +47,12 @@ sd-id128 sd_id128_t SD_ID128_MAKE + SD_ID128_NULL SD_ID128_CONST_STR SD_ID128_FORMAT_STR SD_ID128_FORMAT_VAL sd_id128_equal + sd_id128_is_null APIs for processing 128-bit IDs @@ -88,8 +90,8 @@ union type: typedef union sd_id128 { - uint8_t bytes[16]; - uint64_t qwords[2]; + uint8_t bytes[16]; + uint64_t qwords[2]; } sd_id128_t; This union type allows accessing the 128-bit ID as 16 @@ -108,37 +110,46 @@ #define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) + SD_ID128_NULL may be used to refer to the 128bit ID consisting of only NUL + bytes. + SD_ID128_CONST_STR() may be used to convert constant 128-bit IDs into constant strings for output. The following example code will output the string "fc2e22bc6ee647b6b90729ab34a250b1": int main(int argc, char *argv[]) { - puts(SD_ID128_CONST_STR(SD_MESSAGE_COREDUMP)); + puts(SD_ID128_CONST_STR(SD_MESSAGE_COREDUMP)); } - SD_ID128_FORMAT_STR and + SD_ID128_FORMAT_STR() and SD_ID128_FORMAT_VAL() may be used to format a 128-bit ID in a printf3 format string, as shown in the following example: int main(int argc, char *argv[]) { - sd_id128_t id; - id = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07); - printf("The ID encoded in this C file is " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(id)); - return 0; + sd_id128_t id; + id = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07); + printf("The ID encoded in this C file is " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(id)); + return 0; } Use sd_id128_equal() to compare two 128-bit IDs: int main(int argc, char *argv[]) { - sd_id128_t a, b, c; - a = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07); - b = SD_ID128_MAKE(f2,28,88,9c,5f,09,44,15,9d,d7,04,77,58,cb,e7,3e); - c = a; - assert(sd_id128_equal(a, c)); - assert(!sd_id128_equal(a, b)); - return 0; + sd_id128_t a, b, c; + a = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07); + b = SD_ID128_MAKE(f2,28,88,9c,5f,09,44,15,9d,d7,04,77,58,cb,e7,3e); + c = a; + assert(sd_id128_equal(a, c)); + assert(!sd_id128_equal(a, b)); + return 0; +} + + Use sd_id128_is_null() to check if an 128bit ID consists of only NUL bytes: + + int main(int argc, char *argv[]) { + assert(sd_id128_is_null(SD_ID128_NULL)); } Note that new, randomized IDs may be generated with -- cgit v1.2.3-54-g00ecf From a46eac1bbddcdd15e741fc6c8389078db1067f81 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Oct 2016 20:32:23 +0200 Subject: update TODO --- TODO | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/TODO b/TODO index 9ca2736b2a..9b949e93f7 100644 --- a/TODO +++ b/TODO @@ -72,6 +72,12 @@ Features: * RemoveKeyRing= to remove all keyring entries of the specified user +* ProtectReboot= that masks reboot() and kexec_load() syscalls, prohibits kill + on PID 1 with the relevant signals, and makes relevant files in /sys and + /proc (such as the sysrq stuff) unavailable + +* DeviceAllow= should also generate seccomp filters for mknod() + * Add DataDirectory=, CacheDirectory= and LogDirectory= to match RuntimeDirectory=, and create it as necessary when starting a service, owned by the right user. -- cgit v1.2.3-54-g00ecf From 1ae43295751fc235e7f93719a635a5b06f3ac09b Mon Sep 17 00:00:00 2001 From: David Michael Date: Wed, 31 Aug 2016 15:34:29 -0700 Subject: resolved: add an option to control the DNS stub listener --- man/resolved.conf.xml | 12 ++++++++++++ src/resolve/resolved-conf.c | 11 +++++++++++ src/resolve/resolved-conf.h | 15 +++++++++++++++ src/resolve/resolved-dns-stub.c | 24 ++++++++++++++---------- src/resolve/resolved-gperf.gperf | 13 +++++++------ src/resolve/resolved-manager.c | 1 + src/resolve/resolved-manager.h | 2 ++ src/resolve/resolved.conf.in | 1 + 8 files changed, 63 insertions(+), 16 deletions(-) diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml index 7556c6ff31..44df8ffa80 100644 --- a/man/resolved.conf.xml +++ b/man/resolved.conf.xml @@ -213,6 +213,18 @@ (such as 127.0.0.1 or ::1), in order to avoid duplicate local caching. + + DNSStubListener= + Takes a boolean argument or one of udp and tcp. If + udp (the default), a DNS stub resolver will listen for UDP requests on address 127.0.0.53 + port 53. If tcp, the stub will listen for TCP requests on the same address and port. If + yes, the stub listens for both UDP and TCP requests. If no, the stub + listener is disabled. + + Note that the DNS stub listener is turned off implicitly when its listening address and port are already + in use. + + diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index dd233e7c4a..246327daa2 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -23,8 +23,19 @@ #include "extract-word.h" #include "parse-util.h" #include "resolved-conf.h" +#include "string-table.h" #include "string-util.h" +DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode, "Failed to parse DNS stub listener mode setting"); + +static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MAX] = { + [DNS_STUB_LISTENER_NO] = "no", + [DNS_STUB_LISTENER_UDP] = "udp", + [DNS_STUB_LISTENER_TCP] = "tcp", + [DNS_STUB_LISTENER_YES] = "yes", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_stub_listener_mode, DnsStubListenerMode, DNS_STUB_LISTENER_YES); + int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) { union in_addr_union address; int family, r, ifindex = 0; diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h index 64a185c69f..fc425a36b2 100644 --- a/src/resolve/resolved-conf.h +++ b/src/resolve/resolved-conf.h @@ -19,6 +19,17 @@ along with systemd; If not, see . ***/ +typedef enum DnsStubListenerMode DnsStubListenerMode; + +enum DnsStubListenerMode { + DNS_STUB_LISTENER_NO, + DNS_STUB_LISTENER_UDP, + DNS_STUB_LISTENER_TCP, + DNS_STUB_LISTENER_YES, + _DNS_STUB_LISTENER_MODE_MAX, + _DNS_STUB_LISTENER_MODE_INVALID = -1 +}; + #include "resolved-manager.h" #include "resolved-dns-server.h" @@ -34,3 +45,7 @@ const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, unsigned len int config_parse_dns_servers(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_search_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_dns_stub_listener_mode(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); + +const char* dns_stub_listener_mode_to_string(DnsStubListenerMode p) _const_; +DnsStubListenerMode dns_stub_listener_mode_from_string(const char *s) _pure_; diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index d263cedcd9..53772535c6 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -540,17 +540,21 @@ int manager_dns_stub_start(Manager *m) { assert(m); - r = manager_dns_stub_udp_fd(m); - if (r == -EADDRINUSE) - goto eaddrinuse; - if (r < 0) - return r; + if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_UDP)) { + r = manager_dns_stub_udp_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + } - r = manager_dns_stub_tcp_fd(m); - if (r == -EADDRINUSE) - goto eaddrinuse; - if (r < 0) - return r; + if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_TCP)) { + r = manager_dns_stub_tcp_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + } return 0; diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf index 2fd56bce26..446f85cdf4 100644 --- a/src/resolve/resolved-gperf.gperf +++ b/src/resolve/resolved-gperf.gperf @@ -14,9 +14,10 @@ struct ConfigPerfItem; %struct-type %includes %% -Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0 -Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0 -Resolve.Domains, config_parse_search_domains, 0, 0 -Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support) -Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode) -Resolve.Cache, config_parse_bool, 0, offsetof(Manager, enable_cache) +Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0 +Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0 +Resolve.Domains, config_parse_search_domains, 0, 0 +Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support) +Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode) +Resolve.Cache, config_parse_bool, 0, offsetof(Manager, enable_cache) +Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0, offsetof(Manager, dns_stub_listener_mode) diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 92ade820ac..40f08e8044 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -501,6 +501,7 @@ int manager_new(Manager **ret) { m->mdns_support = RESOLVE_SUPPORT_NO; m->dnssec_mode = DEFAULT_DNSSEC_MODE; m->enable_cache = true; + m->dns_stub_listener_mode = DNS_STUB_LISTENER_UDP; m->read_resolv_conf = true; m->need_builtin_fallbacks = true; m->etc_hosts_last = m->etc_hosts_mtime = USEC_INFINITY; diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index deebd8e484..6b2208ed94 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -30,6 +30,7 @@ typedef struct Manager Manager; +#include "resolved-conf.h" #include "resolved-dns-query.h" #include "resolved-dns-search-domain.h" #include "resolved-dns-server.h" @@ -47,6 +48,7 @@ struct Manager { ResolveSupport mdns_support; DnssecMode dnssec_mode; bool enable_cache; + DnsStubListenerMode dns_stub_listener_mode; /* Network */ Hashmap *links; diff --git a/src/resolve/resolved.conf.in b/src/resolve/resolved.conf.in index 3bd8389c88..60afa151e3 100644 --- a/src/resolve/resolved.conf.in +++ b/src/resolve/resolved.conf.in @@ -18,3 +18,4 @@ #LLMNR=yes #DNSSEC=@DEFAULT_DNSSEC_MODE@ #Cache=yes +#DNSStubListener=udp -- cgit v1.2.3-54-g00ecf From e63be0847c39bfdca45c25c505922814374581a7 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Sat, 8 Oct 2016 16:35:41 +0530 Subject: networkd: address add support to configure flags (#4201) This patch enables to configure IFA_F_HOMEADDRESS IFA_F_NODAD IFA_F_MANAGETEMPADDR IFA_F_NOPREFIXROUTE IFA_F_MCAUTOJOIN --- man/systemd.network.xml | 51 +++++++++++++++++++++++++++ src/basic/missing.h | 4 +++ src/network/networkd-address.c | 59 ++++++++++++++++++++++++++++++++ src/network/networkd-address.h | 6 ++++ src/network/networkd-network-gperf.gperf | 5 +++ 5 files changed, 125 insertions(+) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 0af927db19..2fb4907634 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -695,6 +695,57 @@ which is then configured to use them explicitly. + + HomeAddress= + + Takes a boolean argument. Designates this address the "home address" as defined in + RFC 6275. + Supported only on IPv6. Defaults to false. + + + + DuplicateAddressDetection= + + Takes a boolean argument. Do not perform Duplicate Address Detection + RFC 4862 when adding this address. + Supported only on IPv6. Defaults to false. + + + + ManageTemporaryAddress= + + Takes a boolean argument. If true the kernel manage temporary addresses created + from this one as template on behalf of Privacy Extensions + RFC 3041. For this to become + active, the use_tempaddr sysctl setting has to be set to a value greater than zero. + The given address needs to have a prefix length of 64. This flag allows to use privacy + extensions in a manually configured network, just like if stateless auto-configuration + was active. Defaults to false. + + + + PrefixRoute= + + Takes a boolean argument. When adding or modifying an IPv6 address, the userspace + application needs a way to suppress adding a prefix route. This is for example relevant + together with IFA_F_MANAGERTEMPADDR, where userspace creates autoconf generated addresses, + but depending on on-link, no route for the prefix should be added. Defaults to false. + + + + AutoJoin= + + Takes a boolean argument. Joining multicast group on ethernet level via + ip maddr command would not work if we have an Ethernet switch that does + IGMP snooping since the switch would not replicate multicast packets on ports that did not + have IGMP reports for the multicast addresses. Linux vxlan interfaces created via + ip link add vxlan or networkd's netdev kind vxlan have the group option + that enables then to do the required join. By extending ip address command with option + autojoin we can get similar functionality for openvswitch (OVS) vxlan + interfaces as well as other tunneling mechanisms that need to receive multicast traffic. + Defaults to no. + + diff --git a/src/basic/missing.h b/src/basic/missing.h index 13ff51cd35..4a78269e33 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -1052,6 +1052,10 @@ typedef int32_t key_serial_t; #define ETHERTYPE_LLDP 0x88cc #endif +#ifndef IFA_F_MCAUTOJOIN +#define IFA_F_MCAUTOJOIN 0x400 +#endif + #endif #include "missing_syscall.h" diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 5498e352d8..ed52d5e42d 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -571,6 +571,21 @@ int address_configure( address->flags |= IFA_F_PERMANENT; + if (address->home_address) + address->flags |= IFA_F_HOMEADDRESS; + + if (address->duplicate_address_detection) + address->flags |= IFA_F_NODAD; + + if (address->manage_temporary_address) + address->flags |= IFA_F_MANAGETEMPADDR; + + if (address->prefix_route) + address->flags |= IFA_F_NOPREFIXROUTE; + + if (address->autojoin) + address->flags |= IFA_F_MCAUTOJOIN; + r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff)); if (r < 0) return log_error_errno(r, "Could not set flags: %m"); @@ -856,6 +871,50 @@ int config_parse_lifetime(const char *unit, return 0; } +int config_parse_address_flags(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; + _cleanup_address_free_ Address *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_new_static(network, section_line, &n); + if (r < 0) + return r; + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address flag, ignoring: %s", rvalue); + return 0; + } + + if (streq(lvalue, "HomeAddress")) + n->home_address = r; + else if (streq(lvalue, "DuplicateAddressDetection")) + n->duplicate_address_detection = r; + else if (streq(lvalue, "ManageTemporaryAddress")) + n->manage_temporary_address = r; + else if (streq(lvalue, "PrefixRoute")) + n->prefix_route = r; + else if (streq(lvalue, "AutoJoin")) + n->autojoin = r; + + return 0; +} + bool address_is_ready(const Address *a) { assert(a); diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 03c4bea7c6..bc3b4fc7f3 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -53,6 +53,11 @@ struct Address { union in_addr_union in_addr_peer; bool ip_masquerade_done:1; + bool duplicate_address_detection; + bool manage_temporary_address; + bool home_address; + bool prefix_route; + bool autojoin; LIST_FIELDS(Address, addresses); }; @@ -77,3 +82,4 @@ int config_parse_address(const char *unit, const char *filename, unsigned line, int config_parse_broadcast(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_label(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_lifetime(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_address_flags(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); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 62779c7c48..5587961b9f 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -70,6 +70,11 @@ Address.Peer, config_parse_address, Address.Broadcast, config_parse_broadcast, 0, 0 Address.Label, config_parse_label, 0, 0 Address.PreferredLifetime, config_parse_lifetime, 0, 0 +Address.HomeAddress, config_parse_address_flags, 0, 0 +Address.DuplicateAddressDetection, config_parse_address_flags, 0, 0 +Address.ManageTemporaryAddress, config_parse_address_flags, 0, 0 +Address.PrefixRoute, config_parse_address_flags, 0, 0 +Address.AutoJoin, config_parse_address_flags, 0, 0 Route.Gateway, config_parse_gateway, 0, 0 Route.Destination, config_parse_destination, 0, 0 Route.Source, config_parse_destination, 0, 0 -- cgit v1.2.3-54-g00ecf From a60f4d0b4403ae398594f9426832e7a4ed9ca686 Mon Sep 17 00:00:00 2001 From: Stefan Schweter Date: Sat, 8 Oct 2016 13:59:34 +0200 Subject: systemd-resolve: use sha256 for local-part of openpgp key (#4193) --- src/resolve/resolve-tool.c | 40 ++++++++++++++++++++++++++++++---------- src/shared/gcrypt-util.h | 8 ++++++++ 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c index 07e4cd7d1d..8aa79049b6 100644 --- a/src/resolve/resolve-tool.c +++ b/src/resolve/resolve-tool.c @@ -395,7 +395,7 @@ static int output_rr_packet(const void *d, size_t l, int ifindex) { return 0; } -static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type) { +static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type, bool warn_missing) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char ifname[IF_NAMESIZE] = ""; @@ -430,7 +430,8 @@ static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_ r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) { - log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r)); + if (warn_missing || r != -ENXIO) + log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r)); return r; } @@ -488,7 +489,8 @@ static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_ return bus_log_parse_error(r); if (n == 0) { - log_error("%s: no records found", name); + if (warn_missing) + log_error("%s: no records found", name); return -ESRCH; } @@ -618,7 +620,7 @@ static int resolve_rfc4501(sd_bus *bus, const char *name) { if (type == 0) type = arg_type ?: DNS_TYPE_A; - return resolve_record(bus, n, class, type); + return resolve_record(bus, n, class, type, true); invalid: log_error("Invalid DNS URI: %s", name); @@ -840,16 +842,34 @@ static int resolve_openpgp(sd_bus *bus, const char *address) { } domain++; - r = string_hashsum_sha224(address, domain - 1 - address, &hashed); + r = string_hashsum_sha256(address, domain - 1 - address, &hashed); if (r < 0) return log_error_errno(r, "Hashing failed: %m"); + strshorten(hashed, 56); + full = strjoina(hashed, "._openpgpkey.", domain); log_debug("Looking up \"%s\".", full); - return resolve_record(bus, full, - arg_class ?: DNS_CLASS_IN, - arg_type ?: DNS_TYPE_OPENPGPKEY); + r = resolve_record(bus, full, + arg_class ?: DNS_CLASS_IN, + arg_type ?: DNS_TYPE_OPENPGPKEY, false); + + if (IN_SET(r, -ENXIO, -ESRCH)) { /* NXDOMAIN or NODATA? */ + hashed = NULL; + r = string_hashsum_sha224(address, domain - 1 - address, &hashed); + if (r < 0) + return log_error_errno(r, "Hashing failed: %m"); + + full = strjoina(hashed, "._openpgpkey.", domain); + log_debug("Looking up \"%s\".", full); + + return resolve_record(bus, full, + arg_class ?: DNS_CLASS_IN, + arg_type ?: DNS_TYPE_OPENPGPKEY, true); + } + + return r; } static int resolve_tlsa(sd_bus *bus, const char *address) { @@ -881,7 +901,7 @@ static int resolve_tlsa(sd_bus *bus, const char *address) { return resolve_record(bus, full, arg_class ?: DNS_CLASS_IN, - arg_type ?: DNS_TYPE_TLSA); + arg_type ?: DNS_TYPE_TLSA, true); } static int show_statistics(sd_bus *bus) { @@ -1877,7 +1897,7 @@ int main(int argc, char **argv) { while (argv[optind]) { int k; - k = resolve_record(bus, argv[optind], arg_class, arg_type); + k = resolve_record(bus, argv[optind], arg_class, arg_type, true); if (r == 0) r = k; diff --git a/src/shared/gcrypt-util.h b/src/shared/gcrypt-util.h index cf33b3c59c..1da12a32be 100644 --- a/src/shared/gcrypt-util.h +++ b/src/shared/gcrypt-util.h @@ -37,3 +37,11 @@ static inline int string_hashsum_sha224(const char *s, size_t len, char **out) { return -EOPNOTSUPP; #endif } + +static inline int string_hashsum_sha256(const char *s, size_t len, char **out) { +#ifdef HAVE_GCRYPT + return string_hashsum(s, len, GCRY_MD_SHA256, out); +#else + return -EOPNOTSUPP; +#endif +} -- cgit v1.2.3-54-g00ecf From 5a46d55fc8f3dc4a86f3994f96369d169c0b96bb Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 2 Oct 2016 15:51:27 +0200 Subject: path-util: add a function to peek into a container and guess systemd version This is a bit crude and only works for new systemd versions which have libsystemd-shared. --- src/basic/path-util.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ src/basic/path-util.h | 2 ++ src/test/test-path-util.c | 19 +++++++++++++ 3 files changed, 89 insertions(+) diff --git a/src/basic/path-util.c b/src/basic/path-util.c index b2fa81a294..c32e961af4 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -34,9 +34,11 @@ #include "alloc-util.h" #include "extract-word.h" #include "fs-util.h" +#include "glob-util.h" #include "log.h" #include "macro.h" #include "missing.h" +#include "parse-util.h" #include "path-util.h" #include "stat-util.h" #include "string-util.h" @@ -814,3 +816,69 @@ bool is_device_path(const char *path) { path_startswith(path, "/dev/") || path_startswith(path, "/sys/"); } + +int systemd_installation_has_version(const char *root, unsigned minimal_version) { + const char *pattern; + int r; + + /* Try to guess if systemd installation is later than the specified version. This + * is hacky and likely to yield false negatives, particularly if the installation + * is non-standard. False positives should be relatively rare. + */ + + NULSTR_FOREACH(pattern, + /* /lib works for systems without usr-merge, and for systems with a sane + * usr-merge, where /lib is a symlink to /usr/lib. /usr/lib is necessary + * for Gentoo which does a merge without making /lib a symlink. + */ + "lib/systemd/libsystemd-shared-*.so\0" + "usr/lib/systemd/libsystemd-shared-*.so\0") { + + _cleanup_strv_free_ char **names = NULL; + _cleanup_free_ char *path = NULL; + char *c, **name; + + path = prefix_root(root, pattern); + if (!path) + return -ENOMEM; + + r = glob_extend(&names, path); + if (r == -ENOENT) + continue; + if (r < 0) + return r; + + assert_se((c = endswith(path, "*.so"))); + *c = '\0'; /* truncate the glob part */ + + STRV_FOREACH(name, names) { + /* This is most likely to run only once, hence let's not optimize anything. */ + char *t, *t2; + unsigned version; + + t = startswith(*name, path); + if (!t) + continue; + + t2 = endswith(t, ".so"); + if (!t2) + continue; + + t2[0] = '\0'; /* truncate the suffix */ + + r = safe_atou(t, &version); + if (r < 0) { + log_debug_errno(r, "Found libsystemd shared at \"%s.so\", but failed to parse version: %m", *name); + continue; + } + + log_debug("Found libsystemd shared at \"%s.so\", version %u (%s).", + *name, version, + version >= minimal_version ? "OK" : "too old"); + if (version >= minimal_version) + return true; + } + } + + return false; +} diff --git a/src/basic/path-util.h b/src/basic/path-util.h index a27c13fcc3..78472f0961 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -125,3 +125,5 @@ char *file_in_same_dir(const char *path, const char *filename); bool hidden_or_backup_file(const char *filename) _pure_; bool is_device_path(const char *path); + +int systemd_installation_has_version(const char *root, unsigned minimal_version); diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 164a10d8a8..0b10d8e25e 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -511,7 +511,24 @@ static void test_hidden_or_backup_file(void) { assert_se(!hidden_or_backup_file("test.dpkg-old.foo")); } +static void test_systemd_installation_has_version(const char *path) { + int r; + const unsigned versions[] = {0, 231, atoi(PACKAGE_VERSION), 999}; + unsigned i; + + for (i = 0; i < ELEMENTSOF(versions); i++) { + r = systemd_installation_has_version(path, versions[i]); + assert_se(r >= 0); + log_info("%s has systemd >= %u: %s", + path ?: "Current installation", versions[i], yes_no(r)); + } +} + int main(int argc, char **argv) { + log_set_max_level(LOG_DEBUG); + log_parse_environment(); + log_open(); + test_path(); test_find_binary(argv[0]); test_prefixes(); @@ -526,5 +543,7 @@ int main(int argc, char **argv) { test_filename_is_valid(); test_hidden_or_backup_file(); + test_systemd_installation_has_version(argv[1]); /* NULL is OK */ + return 0; } -- cgit v1.2.3-54-g00ecf From 98afd6af3a2022bd03543a6dea79120f689967b0 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 2 Oct 2016 20:07:22 +0200 Subject: nspawn: check env var first, detect second If we are going to use the env var to override the detection result anyway, there is not point in doing the detection, especially that it can fail. --- src/nspawn/nspawn.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index a08377b3a3..4ce0e2e0c1 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -320,13 +320,6 @@ static int detect_unified_cgroup_hierarchy(void) { const char *e; int r, all_unified, systemd_unified; - all_unified = cg_all_unified(); - systemd_unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER); - - if (all_unified < 0 || systemd_unified < 0) - return log_error_errno(all_unified < 0 ? all_unified : systemd_unified, - "Failed to determine whether the unified cgroups hierarchy is used: %m"); - /* Allow the user to control whether the unified hierarchy is used */ e = getenv("UNIFIED_CGROUP_HIERARCHY"); if (e) { @@ -341,6 +334,13 @@ static int detect_unified_cgroup_hierarchy(void) { return 0; } + all_unified = cg_all_unified(); + systemd_unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER); + + if (all_unified < 0 || systemd_unified < 0) + return log_error_errno(all_unified < 0 ? all_unified : systemd_unified, + "Failed to determine whether the unified cgroups hierarchy is used: %m"); + /* Otherwise inherit the default from the host system */ if (all_unified > 0) arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL; -- cgit v1.2.3-54-g00ecf From b006762524c76e8a3ef8d965bb2bf42c894196e4 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 2 Oct 2016 21:32:38 +0200 Subject: nspawn: move the main loop body out to a new function The new function has 416 lines by itself! "return log_error_errno" is used to nicely reduce the volume of error handling code. A few minor issues are fixed on the way: - positive value was used as error value (EIO), causing systemd-nspawn to return success, even though it shouldn't. - In two places random values were used as error status, when the actual value was in an unusual place (etc_password_lock, notify_socket). Those are the only functional changes. There is another potential issue, which is marked with a comment, and left unresolved: the container can also return 133 by itself, causing a spurious reboot. --- src/nspawn/nspawn.c | 890 +++++++++++++++++++++++++--------------------------- 1 file changed, 430 insertions(+), 460 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 4ce0e2e0c1..d688d2eb64 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3575,18 +3575,433 @@ static int load_settings(void) { return 0; } +static int run(int master, + const char* console, + const char *root_device, bool root_device_rw, + const char *home_device, bool home_device_rw, + const char *srv_device, bool srv_device_rw, + const char *esp_device, + bool interactive, + bool secondary, + FDSet *fds, + char veth_name[IFNAMSIZ], bool *veth_created, + union in_addr_union *exposed, + pid_t *pid, int *ret) { + + static const struct sigaction sa = { + .sa_handler = nop_signal_handler, + .sa_flags = SA_NOCLDSTOP, + }; + + _cleanup_release_lock_file_ LockFile uid_shift_lock = LOCK_FILE_INIT; + _cleanup_close_ int etc_passwd_lock = -1; + _cleanup_close_pair_ int + kmsg_socket_pair[2] = { -1, -1 }, + rtnl_socket_pair[2] = { -1, -1 }, + pid_socket_pair[2] = { -1, -1 }, + uuid_socket_pair[2] = { -1, -1 }, + notify_socket_pair[2] = { -1, -1 }, + uid_shift_socket_pair[2] = { -1, -1 }; + _cleanup_close_ int notify_socket= -1; + _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(pty_forward_freep) PTYForward *forward = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + ContainerStatus container_status = 0; + char last_char = 0; + int ifi = 0, r; + ssize_t l; + sigset_t mask_chld; + + assert_se(sigemptyset(&mask_chld) == 0); + assert_se(sigaddset(&mask_chld, SIGCHLD) == 0); + + if (arg_userns_mode == USER_NAMESPACE_PICK) { + /* When we shall pick the UID/GID range, let's first lock /etc/passwd, so that we can safely + * check with getpwuid() if the specific user already exists. Note that /etc might be + * read-only, in which case this will fail with EROFS. But that's really OK, as in that case we + * can be reasonably sure that no users are going to be added. Note that getpwuid() checks are + * really just an extra safety net. We kinda assume that the UID range we allocate from is + * really ours. */ + + etc_passwd_lock = take_etc_passwd_lock(NULL); + if (etc_passwd_lock < 0 && etc_passwd_lock != -EROFS) + return log_error_errno(etc_passwd_lock, "Failed to take /etc/passwd lock: %m"); + } + + r = barrier_create(&barrier); + if (r < 0) + return log_error_errno(r, "Cannot initialize IPC barrier: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) + return log_error_errno(errno, "Failed to create kmsg socket pair: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, rtnl_socket_pair) < 0) + return log_error_errno(errno, "Failed to create rtnl socket pair: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pid_socket_pair) < 0) + return log_error_errno(errno, "Failed to create pid socket pair: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, uuid_socket_pair) < 0) + return log_error_errno(errno, "Failed to create id socket pair: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, notify_socket_pair) < 0) + return log_error_errno(errno, "Failed to create notify socket pair: %m"); + + if (arg_userns_mode != USER_NAMESPACE_NO) + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, uid_shift_socket_pair) < 0) + return log_error_errno(errno, "Failed to create uid shift socket pair: %m"); + + /* Child can be killed before execv(), so handle SIGCHLD in order to interrupt + * parent's blocking calls and give it a chance to call wait() and terminate. */ + r = sigprocmask(SIG_UNBLOCK, &mask_chld, NULL); + if (r < 0) + return log_error_errno(errno, "Failed to change the signal mask: %m"); + + r = sigaction(SIGCHLD, &sa, NULL); + if (r < 0) + return log_error_errno(errno, "Failed to install SIGCHLD handler: %m"); + + *pid = raw_clone(SIGCHLD|CLONE_NEWNS); + if (*pid < 0) + return log_error_errno(errno, "clone() failed%s: %m", + errno == EINVAL ? + ", do you have namespace support enabled in your kernel? (You need UTS, IPC, PID and NET namespacing built in)" : ""); + + if (*pid == 0) { + /* The outer child only has a file system namespace. */ + barrier_set_role(&barrier, BARRIER_CHILD); + + master = safe_close(master); + + kmsg_socket_pair[0] = safe_close(kmsg_socket_pair[0]); + rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]); + pid_socket_pair[0] = safe_close(pid_socket_pair[0]); + uuid_socket_pair[0] = safe_close(uuid_socket_pair[0]); + notify_socket_pair[0] = safe_close(notify_socket_pair[0]); + uid_shift_socket_pair[0] = safe_close(uid_shift_socket_pair[0]); + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + + r = outer_child(&barrier, + arg_directory, + console, + root_device, root_device_rw, + home_device, home_device_rw, + srv_device, srv_device_rw, + esp_device, + interactive, + secondary, + pid_socket_pair[1], + uuid_socket_pair[1], + notify_socket_pair[1], + kmsg_socket_pair[1], + rtnl_socket_pair[1], + uid_shift_socket_pair[1], + fds); + if (r < 0) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + barrier_set_role(&barrier, BARRIER_PARENT); + + fds = fdset_free(fds); + + kmsg_socket_pair[1] = safe_close(kmsg_socket_pair[1]); + rtnl_socket_pair[1] = safe_close(rtnl_socket_pair[1]); + pid_socket_pair[1] = safe_close(pid_socket_pair[1]); + uuid_socket_pair[1] = safe_close(uuid_socket_pair[1]); + notify_socket_pair[1] = safe_close(notify_socket_pair[1]); + uid_shift_socket_pair[1] = safe_close(uid_shift_socket_pair[1]); + + if (arg_userns_mode != USER_NAMESPACE_NO) { + /* The child just let us know the UID shift it might have read from the image. */ + l = recv(uid_shift_socket_pair[0], &arg_uid_shift, sizeof arg_uid_shift, 0); + if (l < 0) + return log_error_errno(errno, "Failed to read UID shift: %m"); + + if (l != sizeof arg_uid_shift) { + log_error("Short read while reading UID shift."); + return -EIO; + } + + if (arg_userns_mode == USER_NAMESPACE_PICK) { + /* If we are supposed to pick the UID shift, let's try to use the shift read from the + * image, but if that's already in use, pick a new one, and report back to the child, + * which one we now picked. */ + + r = uid_shift_pick(&arg_uid_shift, &uid_shift_lock); + if (r < 0) + return log_error_errno(r, "Failed to pick suitable UID/GID range: %m"); + + l = send(uid_shift_socket_pair[0], &arg_uid_shift, sizeof arg_uid_shift, MSG_NOSIGNAL); + if (l < 0) + return log_error_errno(errno, "Failed to send UID shift: %m"); + if (l != sizeof arg_uid_shift) { + log_error("Short write while writing UID shift."); + return -EIO; + } + } + } + + /* Wait for the outer child. */ + r = wait_for_terminate_and_warn("namespace helper", *pid, NULL); + if (r != 0) + return r < 0 ? r : -EIO; + + /* And now retrieve the PID of the inner child. */ + l = recv(pid_socket_pair[0], pid, sizeof *pid, 0); + if (l < 0) + return log_error_errno(errno, "Failed to read inner child PID: %m"); + if (l != sizeof *pid) { + log_error("Short read while reading inner child PID."); + return -EIO; + } + + /* We also retrieve container UUID in case it was generated by outer child */ + l = recv(uuid_socket_pair[0], &arg_uuid, sizeof arg_uuid, 0); + if (l < 0) + return log_error_errno(errno, "Failed to read container machine ID: %m"); + if (l != sizeof(arg_uuid)) { + log_error("Short read while reading container machined ID."); + return -EIO; + } + + /* We also retrieve the socket used for notifications generated by outer child */ + notify_socket = receive_one_fd(notify_socket_pair[0], 0); + if (notify_socket < 0) + return log_error_errno(notify_socket, + "Failed to receive notification socket from the outer child: %m"); + + log_debug("Init process invoked as PID "PID_FMT, *pid); + + if (arg_userns_mode != USER_NAMESPACE_NO) { + if (!barrier_place_and_sync(&barrier)) { /* #1 */ + log_error("Child died too early."); + return -ESRCH; + } + + r = setup_uid_map(*pid); + if (r < 0) + return r; + + (void) barrier_place(&barrier); /* #2 */ + } + + if (arg_private_network) { + + r = move_network_interfaces(*pid, arg_network_interfaces); + if (r < 0) + return r; + + if (arg_network_veth) { + r = setup_veth(arg_machine, *pid, veth_name, + arg_network_bridge || arg_network_zone); + if (r < 0) + return r; + else if (r > 0) + ifi = r; + + if (arg_network_bridge) { + /* Add the interface to a bridge */ + r = setup_bridge(veth_name, arg_network_bridge, false); + if (r < 0) + return r; + if (r > 0) + ifi = r; + } else if (arg_network_zone) { + /* Add the interface to a bridge, possibly creating it */ + r = setup_bridge(veth_name, arg_network_zone, true); + if (r < 0) + return r; + if (r > 0) + ifi = r; + } + } + + r = setup_veth_extra(arg_machine, *pid, arg_network_veth_extra); + if (r < 0) + return r; + + /* We created the primary and extra veth links now; let's remember this, so that we know to + remove them later on. Note that we don't bother with removing veth links that were created + here when their setup failed half-way, because in that case the kernel should be able to + remove them on its own, since they cannot be referenced by anything yet. */ + *veth_created = true; + + r = setup_macvlan(arg_machine, *pid, arg_network_macvlan); + if (r < 0) + return r; + + r = setup_ipvlan(arg_machine, *pid, arg_network_ipvlan); + if (r < 0) + return r; + } + + if (arg_register) { + r = register_machine( + arg_machine, + *pid, + arg_directory, + arg_uuid, + ifi, + arg_slice, + arg_custom_mounts, arg_n_custom_mounts, + arg_kill_signal, + arg_property, + arg_keep_unit, + arg_container_service_name); + if (r < 0) + return r; + } + + r = sync_cgroup(*pid, arg_unified_cgroup_hierarchy); + if (r < 0) + return r; + + if (arg_keep_unit) { + r = create_subcgroup(*pid, arg_unified_cgroup_hierarchy); + if (r < 0) + return r; + } + + r = chown_cgroup(*pid, arg_uid_shift); + if (r < 0) + return r; + + /* Notify the child that the parent is ready with all + * its setup (including cgroup-ification), and that + * the child can now hand over control to the code to + * run inside the container. */ + (void) barrier_place(&barrier); /* #3 */ + + /* Block SIGCHLD here, before notifying child. + * process_pty() will handle it with the other signals. */ + assert_se(sigprocmask(SIG_BLOCK, &mask_chld, NULL) >= 0); + + /* Reset signal to default */ + r = default_signals(SIGCHLD, -1); + if (r < 0) + return log_error_errno(r, "Failed to reset SIGCHLD: %m"); + + r = sd_event_new(&event); + if (r < 0) + return log_error_errno(r, "Failed to get default event source: %m"); + + r = setup_sd_notify_parent(event, notify_socket, PID_TO_PTR(*pid)); + if (r < 0) + return r; + + /* Let the child know that we are ready and wait that the child is completely ready now. */ + if (!barrier_place_and_sync(&barrier)) { /* #4 */ + log_error("Child died too early."); + return -ESRCH; + } + + /* At this point we have made use of the UID we picked, and thus nss-mymachines + * will make them appear in getpwuid(), thus we can release the /etc/passwd lock. */ + etc_passwd_lock = safe_close(etc_passwd_lock); + + sd_notifyf(false, + "STATUS=Container running.\n" + "X_NSPAWN_LEADER_PID=" PID_FMT, *pid); + if (!arg_notify_ready) + sd_notify(false, "READY=1\n"); + + if (arg_kill_signal > 0) { + /* Try to kill the init system on SIGINT or SIGTERM */ + sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, PID_TO_PTR(*pid)); + sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, PID_TO_PTR(*pid)); + } else { + /* Immediately exit */ + sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); + sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); + } + + /* simply exit on sigchld */ + sd_event_add_signal(event, NULL, SIGCHLD, NULL, NULL); + + if (arg_expose_ports) { + r = expose_port_watch_rtnl(event, rtnl_socket_pair[0], on_address_change, exposed, &rtnl); + if (r < 0) + return r; + + (void) expose_port_execute(rtnl, arg_expose_ports, exposed); + } + + rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]); + + r = pty_forward_new(event, master, + PTY_FORWARD_IGNORE_VHANGUP | (interactive ? 0 : PTY_FORWARD_READ_ONLY), + &forward); + if (r < 0) + return log_error_errno(r, "Failed to create PTY forwarder: %m"); + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + pty_forward_get_last_char(forward, &last_char); + + forward = pty_forward_free(forward); + + if (!arg_quiet && last_char != '\n') + putc('\n', stdout); + + /* Kill if it is not dead yet anyway */ + if (arg_register && !arg_keep_unit) + terminate_machine(*pid); + + /* Normally redundant, but better safe than sorry */ + kill(*pid, SIGKILL); + + r = wait_for_container(*pid, &container_status); + *pid = 0; + + if (r < 0) + /* We failed to wait for the container, or the container exited abnormally. */ + return r; + if (r > 0 || container_status == CONTAINER_TERMINATED) { + /* r > 0 → The container exited with a non-zero status, + * otherwise → The container exited with zero status and reboot was not requested. */ + *ret = r; + // XXX: if the container returned 133, we will reboot! + return 0; /* finito */ + } + + /* CONTAINER_REBOOTED, loop again */ + + if (arg_keep_unit) { + /* Special handling if we are running as a service: instead of simply + * restarting the machine we want to restart the entire service, so let's + * inform systemd about this with the special exit code 133. The service + * file uses RestartForceExitStatus=133 so that this results in a full + * nspawn restart. This is necessary since we might have cgroup parameters + * set we want to have flushed out. */ + *ret = 0; + return 133; + } + + expose_port_flush(arg_expose_ports, exposed); + + (void) remove_veth_links(veth_name, arg_network_veth_extra); + *veth_created = false; + return 1; /* loop again */ +} + int main(int argc, char *argv[]) { _cleanup_free_ char *device_path = NULL, *root_device = NULL, *home_device = NULL, *srv_device = NULL, *esp_device = NULL, *console = NULL; bool root_device_rw = true, home_device_rw = true, srv_device_rw = true; _cleanup_close_ int master = -1, image_fd = -1; _cleanup_fdset_free_ FDSet *fds = NULL; - int r, n_fd_passed, loop_nr = -1; + int r, n_fd_passed, loop_nr = -1, ret = EXIT_FAILURE; char veth_name[IFNAMSIZ] = ""; bool secondary = false, remove_subvol = false; - sigset_t mask_chld; pid_t pid = 0; - int ret = EXIT_SUCCESS; union in_addr_union exposed = {}; _cleanup_release_lock_file_ LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT; bool interactive, veth_created = false; @@ -3802,470 +4217,25 @@ int main(int argc, char *argv[]) { assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1) >= 0); - assert_se(sigemptyset(&mask_chld) == 0); - assert_se(sigaddset(&mask_chld, SIGCHLD) == 0); - if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) { r = log_error_errno(errno, "Failed to become subreaper: %m"); goto finish; } for (;;) { - static const struct sigaction sa = { - .sa_handler = nop_signal_handler, - .sa_flags = SA_NOCLDSTOP, - }; - - _cleanup_release_lock_file_ LockFile uid_shift_lock = LOCK_FILE_INIT; - _cleanup_close_ int etc_passwd_lock = -1; - _cleanup_close_pair_ int - kmsg_socket_pair[2] = { -1, -1 }, - rtnl_socket_pair[2] = { -1, -1 }, - pid_socket_pair[2] = { -1, -1 }, - uuid_socket_pair[2] = { -1, -1 }, - notify_socket_pair[2] = { -1, -1 }, - uid_shift_socket_pair[2] = { -1, -1 }; - _cleanup_close_ int notify_socket= -1; - _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL; - _cleanup_(sd_event_unrefp) sd_event *event = NULL; - _cleanup_(pty_forward_freep) PTYForward *forward = NULL; - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - ContainerStatus container_status = 0; - char last_char = 0; - int ifi = 0; - ssize_t l; - - if (arg_userns_mode == USER_NAMESPACE_PICK) { - /* When we shall pick the UID/GID range, let's first lock /etc/passwd, so that we can safely - * check with getpwuid() if the specific user already exists. Note that /etc might be - * read-only, in which case this will fail with EROFS. But that's really OK, as in that case we - * can be reasonably sure that no users are going to be added. Note that getpwuid() checks are - * really just an extra safety net. We kinda assume that the UID range we allocate from is - * really ours. */ - - etc_passwd_lock = take_etc_passwd_lock(NULL); - if (etc_passwd_lock < 0 && etc_passwd_lock != -EROFS) { - log_error_errno(r, "Failed to take /etc/passwd lock: %m"); - goto finish; - } - } - - r = barrier_create(&barrier); - if (r < 0) { - log_error_errno(r, "Cannot initialize IPC barrier: %m"); - goto finish; - } - - if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) { - r = log_error_errno(errno, "Failed to create kmsg socket pair: %m"); - goto finish; - } - - if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, rtnl_socket_pair) < 0) { - r = log_error_errno(errno, "Failed to create rtnl socket pair: %m"); - goto finish; - } - - if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pid_socket_pair) < 0) { - r = log_error_errno(errno, "Failed to create pid socket pair: %m"); - goto finish; - } - - if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, uuid_socket_pair) < 0) { - r = log_error_errno(errno, "Failed to create id socket pair: %m"); - goto finish; - } - - if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, notify_socket_pair) < 0) { - r = log_error_errno(errno, "Failed to create notify socket pair: %m"); - goto finish; - } - - if (arg_userns_mode != USER_NAMESPACE_NO) - if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, uid_shift_socket_pair) < 0) { - r = log_error_errno(errno, "Failed to create uid shift socket pair: %m"); - goto finish; - } - - /* Child can be killed before execv(), so handle SIGCHLD - * in order to interrupt parent's blocking calls and - * give it a chance to call wait() and terminate. */ - r = sigprocmask(SIG_UNBLOCK, &mask_chld, NULL); - if (r < 0) { - r = log_error_errno(errno, "Failed to change the signal mask: %m"); - goto finish; - } - - r = sigaction(SIGCHLD, &sa, NULL); - if (r < 0) { - r = log_error_errno(errno, "Failed to install SIGCHLD handler: %m"); - goto finish; - } - - pid = raw_clone(SIGCHLD|CLONE_NEWNS); - if (pid < 0) { - if (errno == EINVAL) - r = log_error_errno(errno, "clone() failed, do you have namespace support enabled in your kernel? (You need UTS, IPC, PID and NET namespacing built in): %m"); - else - r = log_error_errno(errno, "clone() failed: %m"); - - goto finish; - } - - if (pid == 0) { - /* The outer child only has a file system namespace. */ - barrier_set_role(&barrier, BARRIER_CHILD); - - master = safe_close(master); - - kmsg_socket_pair[0] = safe_close(kmsg_socket_pair[0]); - rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]); - pid_socket_pair[0] = safe_close(pid_socket_pair[0]); - uuid_socket_pair[0] = safe_close(uuid_socket_pair[0]); - notify_socket_pair[0] = safe_close(notify_socket_pair[0]); - uid_shift_socket_pair[0] = safe_close(uid_shift_socket_pair[0]); - - (void) reset_all_signal_handlers(); - (void) reset_signal_mask(); - - r = outer_child(&barrier, - arg_directory, - console, - root_device, root_device_rw, - home_device, home_device_rw, - srv_device, srv_device_rw, - esp_device, - interactive, - secondary, - pid_socket_pair[1], - uuid_socket_pair[1], - notify_socket_pair[1], - kmsg_socket_pair[1], - rtnl_socket_pair[1], - uid_shift_socket_pair[1], - fds); - if (r < 0) - _exit(EXIT_FAILURE); - - _exit(EXIT_SUCCESS); - } - - barrier_set_role(&barrier, BARRIER_PARENT); - - fds = fdset_free(fds); - - kmsg_socket_pair[1] = safe_close(kmsg_socket_pair[1]); - rtnl_socket_pair[1] = safe_close(rtnl_socket_pair[1]); - pid_socket_pair[1] = safe_close(pid_socket_pair[1]); - uuid_socket_pair[1] = safe_close(uuid_socket_pair[1]); - notify_socket_pair[1] = safe_close(notify_socket_pair[1]); - uid_shift_socket_pair[1] = safe_close(uid_shift_socket_pair[1]); - - if (arg_userns_mode != USER_NAMESPACE_NO) { - /* The child just let us know the UID shift it might have read from the image. */ - l = recv(uid_shift_socket_pair[0], &arg_uid_shift, sizeof(arg_uid_shift), 0); - if (l < 0) { - r = log_error_errno(errno, "Failed to read UID shift: %m"); - goto finish; - } - if (l != sizeof(arg_uid_shift)) { - log_error("Short read while reading UID shift."); - r = EIO; - goto finish; - } - - if (arg_userns_mode == USER_NAMESPACE_PICK) { - /* If we are supposed to pick the UID shift, let's try to use the shift read from the - * image, but if that's already in use, pick a new one, and report back to the child, - * which one we now picked. */ - - r = uid_shift_pick(&arg_uid_shift, &uid_shift_lock); - if (r < 0) { - log_error_errno(r, "Failed to pick suitable UID/GID range: %m"); - goto finish; - } - - l = send(uid_shift_socket_pair[0], &arg_uid_shift, sizeof(arg_uid_shift), MSG_NOSIGNAL); - if (l < 0) { - r = log_error_errno(errno, "Failed to send UID shift: %m"); - goto finish; - } - if (l != sizeof(arg_uid_shift)) { - log_error("Short write while writing UID shift."); - r = -EIO; - goto finish; - } - } - } - - /* Wait for the outer child. */ - r = wait_for_terminate_and_warn("namespace helper", pid, NULL); - if (r < 0) - goto finish; - if (r != 0) { - r = -EIO; - goto finish; - } - pid = 0; - - /* And now retrieve the PID of the inner child. */ - l = recv(pid_socket_pair[0], &pid, sizeof(pid), 0); - if (l < 0) { - r = log_error_errno(errno, "Failed to read inner child PID: %m"); - goto finish; - } - if (l != sizeof(pid)) { - log_error("Short read while reading inner child PID."); - r = EIO; - goto finish; - } - - /* We also retrieve container UUID in case it was generated by outer child */ - l = recv(uuid_socket_pair[0], &arg_uuid, sizeof(arg_uuid), 0); - if (l < 0) { - r = log_error_errno(errno, "Failed to read container machine ID: %m"); - goto finish; - } - if (l != sizeof(arg_uuid)) { - log_error("Short read while reading container machined ID."); - r = EIO; - goto finish; - } - - /* We also retrieve the socket used for notifications generated by outer child */ - notify_socket = receive_one_fd(notify_socket_pair[0], 0); - if (notify_socket < 0) { - r = log_error_errno(errno, "Failed to receive notification socket from the outer child: %m"); - goto finish; - } - - log_debug("Init process invoked as PID " PID_FMT, pid); - - if (arg_userns_mode != USER_NAMESPACE_NO) { - if (!barrier_place_and_sync(&barrier)) { /* #1 */ - log_error("Child died too early."); - r = -ESRCH; - goto finish; - } - - r = setup_uid_map(pid); - if (r < 0) - goto finish; - - (void) barrier_place(&barrier); /* #2 */ - } - - if (arg_private_network) { - - r = move_network_interfaces(pid, arg_network_interfaces); - if (r < 0) - goto finish; - - if (arg_network_veth) { - r = setup_veth(arg_machine, pid, veth_name, - arg_network_bridge || arg_network_zone); - if (r < 0) - goto finish; - else if (r > 0) - ifi = r; - - if (arg_network_bridge) { - /* Add the interface to a bridge */ - r = setup_bridge(veth_name, arg_network_bridge, false); - if (r < 0) - goto finish; - if (r > 0) - ifi = r; - } else if (arg_network_zone) { - /* Add the interface to a bridge, possibly creating it */ - r = setup_bridge(veth_name, arg_network_zone, true); - if (r < 0) - goto finish; - if (r > 0) - ifi = r; - } - } - - r = setup_veth_extra(arg_machine, pid, arg_network_veth_extra); - if (r < 0) - goto finish; - - /* We created the primary and extra veth links now; let's remember this, so that we know to - remove them later on. Note that we don't bother with removing veth links that were created - here when their setup failed half-way, because in that case the kernel should be able to - remove them on its own, since they cannot be referenced by anything yet. */ - veth_created = true; - - r = setup_macvlan(arg_machine, pid, arg_network_macvlan); - if (r < 0) - goto finish; - - r = setup_ipvlan(arg_machine, pid, arg_network_ipvlan); - if (r < 0) - goto finish; - } - - if (arg_register) { - r = register_machine( - arg_machine, - pid, - arg_directory, - arg_uuid, - ifi, - arg_slice, - arg_custom_mounts, arg_n_custom_mounts, - arg_kill_signal, - arg_property, - arg_keep_unit, - arg_container_service_name); - if (r < 0) - goto finish; - } - - r = sync_cgroup(pid, arg_unified_cgroup_hierarchy); - if (r < 0) - goto finish; - - if (arg_keep_unit) { - r = create_subcgroup(pid, arg_unified_cgroup_hierarchy); - if (r < 0) - goto finish; - } - - r = chown_cgroup(pid, arg_uid_shift); - if (r < 0) - goto finish; - - /* Notify the child that the parent is ready with all - * its setup (including cgroup-ification), and that - * the child can now hand over control to the code to - * run inside the container. */ - (void) barrier_place(&barrier); /* #3 */ - - /* Block SIGCHLD here, before notifying child. - * process_pty() will handle it with the other signals. */ - assert_se(sigprocmask(SIG_BLOCK, &mask_chld, NULL) >= 0); - - /* Reset signal to default */ - r = default_signals(SIGCHLD, -1); - if (r < 0) { - log_error_errno(r, "Failed to reset SIGCHLD: %m"); - goto finish; - } - - r = sd_event_new(&event); - if (r < 0) { - log_error_errno(r, "Failed to get default event source: %m"); - goto finish; - } - - r = setup_sd_notify_parent(event, notify_socket, PID_TO_PTR(pid)); - if (r < 0) - goto finish; - - /* Let the child know that we are ready and wait that the child is completely ready now. */ - if (!barrier_place_and_sync(&barrier)) { /* #4 */ - log_error("Child died too early."); - r = -ESRCH; - goto finish; - } - - /* At this point we have made use of the UID we picked, and thus nss-mymachines will make them appear - * in getpwuid(), thus we can release the /etc/passwd lock. */ - etc_passwd_lock = safe_close(etc_passwd_lock); - - sd_notifyf(false, - "STATUS=Container running.\n" - "X_NSPAWN_LEADER_PID=" PID_FMT, pid); - if (!arg_notify_ready) - sd_notify(false, "READY=1\n"); - - if (arg_kill_signal > 0) { - /* Try to kill the init system on SIGINT or SIGTERM */ - sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, PID_TO_PTR(pid)); - sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, PID_TO_PTR(pid)); - } else { - /* Immediately exit */ - sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); - sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); - } - - /* simply exit on sigchld */ - sd_event_add_signal(event, NULL, SIGCHLD, NULL, NULL); - - if (arg_expose_ports) { - r = expose_port_watch_rtnl(event, rtnl_socket_pair[0], on_address_change, &exposed, &rtnl); - if (r < 0) - goto finish; - - (void) expose_port_execute(rtnl, arg_expose_ports, &exposed); - } - - rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]); - - r = pty_forward_new(event, master, PTY_FORWARD_IGNORE_VHANGUP | (interactive ? 0 : PTY_FORWARD_READ_ONLY), &forward); - if (r < 0) { - log_error_errno(r, "Failed to create PTY forwarder: %m"); - goto finish; - } - - r = sd_event_loop(event); - if (r < 0) { - log_error_errno(r, "Failed to run event loop: %m"); - goto finish; - } - - pty_forward_get_last_char(forward, &last_char); - - forward = pty_forward_free(forward); - - if (!arg_quiet && last_char != '\n') - putc('\n', stdout); - - /* Kill if it is not dead yet anyway */ - if (arg_register && !arg_keep_unit) - terminate_machine(pid); - - /* Normally redundant, but better safe than sorry */ - kill(pid, SIGKILL); - - r = wait_for_container(pid, &container_status); - pid = 0; - - if (r < 0) - /* We failed to wait for the container, or the - * container exited abnormally */ - goto finish; - else if (r > 0 || container_status == CONTAINER_TERMINATED) { - /* The container exited with a non-zero - * status, or with zero status and no reboot - * was requested. */ - ret = r; - break; - } - - /* CONTAINER_REBOOTED, loop again */ - - if (arg_keep_unit) { - /* Special handling if we are running as a - * service: instead of simply restarting the - * machine we want to restart the entire - * service, so let's inform systemd about this - * with the special exit code 133. The service - * file uses RestartForceExitStatus=133 so - * that this results in a full nspawn - * restart. This is necessary since we might - * have cgroup parameters set we want to have - * flushed out. */ - ret = 133; - r = 0; + r = run(master, + console, + root_device, root_device_rw, + home_device, home_device_rw, + srv_device, srv_device_rw, + esp_device, + interactive, secondary, + fds, + veth_name, &veth_created, + &exposed, + &pid, &ret); + if (r <= 0) break; - } - - expose_port_flush(arg_expose_ports, &exposed); - - (void) remove_veth_links(veth_name, arg_network_veth_extra); - veth_created = false; } finish: -- cgit v1.2.3-54-g00ecf From 27e29a1e4390415e2d5b709f3d8c2d9481b50987 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 7 Oct 2016 10:31:47 -0400 Subject: nspawn: fix spurious reboot if container process returns 133 --- src/nspawn/nspawn.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index d688d2eb64..12d6eab8be 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3965,10 +3965,14 @@ static int run(int master, /* We failed to wait for the container, or the container exited abnormally. */ return r; if (r > 0 || container_status == CONTAINER_TERMINATED) { - /* r > 0 → The container exited with a non-zero status, - * otherwise → The container exited with zero status and reboot was not requested. */ + /* r > 0 → The container exited with a non-zero status. + * As a special case, we need to replace 133 with a different value, + * because 133 is special-cased in the service file to reboot the container. + * otherwise → The container exited with zero status and a reboot was not requested. + */ + if (r == 133) + r = EXIT_FAILURE; /* replace 133 with the general failure code */ *ret = r; - // XXX: if the container returned 133, we will reboot! return 0; /* finito */ } -- cgit v1.2.3-54-g00ecf From 0fd9563fdeff88458f1a533ac50445abc89e56d8 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 8 Oct 2016 02:18:26 -0400 Subject: nspawn: use mixed cgroup hierarchy only when container has new systemd systemd-soon-to-be-released-232 is able to deal with the mixed hierarchy. So make an educated guess, and use the mixed hierarchy in that case. Tested by running the host with mixed hierarchy (i.e. simply using a recent kernel with systemd from git), and booting first a container with older systemd, and then one with a newer systemd. Fixes #4008. --- src/nspawn/nspawn.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 12d6eab8be..a775d1ac4f 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -316,7 +316,7 @@ static int custom_mounts_prepare(void) { return 0; } -static int detect_unified_cgroup_hierarchy(void) { +static int detect_unified_cgroup_hierarchy(const char *directory) { const char *e; int r, all_unified, systemd_unified; @@ -344,9 +344,16 @@ static int detect_unified_cgroup_hierarchy(void) { /* Otherwise inherit the default from the host system */ if (all_unified > 0) arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL; - else if (systemd_unified > 0) - arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_SYSTEMD; - else + else if (systemd_unified > 0) { + /* mixed cgroup hierarchy support was added in 232 */ + r = systemd_installation_has_version(directory, 232); + if (r < 0) + return log_error_errno(r, "Failed to determine systemd version in container: %m"); + if (r > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_SYSTEMD; + else + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; + } else arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; return 0; @@ -1125,10 +1132,6 @@ static int parse_argv(int argc, char *argv[]) { arg_caps_retain = (arg_caps_retain | plus | (arg_private_network ? 1ULL << CAP_NET_ADMIN : 0)) & ~minus; - r = detect_unified_cgroup_hierarchy(); - if (r < 0) - return r; - e = getenv("SYSTEMD_NSPAWN_CONTAINER_SERVICE"); if (e) arg_container_service_name = e; @@ -2970,6 +2973,10 @@ static int outer_child( if (r < 0) return r; + r = detect_unified_cgroup_hierarchy(directory); + if (r < 0) + return r; + if (arg_userns_mode != USER_NAMESPACE_NO) { /* Let the parent know which UID shift we read from the image */ l = send(uid_shift_socket, &arg_uid_shift, sizeof(arg_uid_shift), MSG_NOSIGNAL); -- cgit v1.2.3-54-g00ecf From 084f5805572c2c4797b87e402c31d82fc9c0623d Mon Sep 17 00:00:00 2001 From: 0xAX <0xAX@users.noreply.github.com> Date: Sun, 9 Oct 2016 00:49:33 +0300 Subject: machinectl: enable pager on help (#4313) as its output is fairly long. --- src/machine/machinectl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index e9de31e184..7b9be3b425 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -2629,6 +2629,7 @@ static int clean_images(int argc, char *argv[], void *userdata) { } static int help(int argc, char *argv[], void *userdata) { + pager_open(arg_no_pager, false); printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Send control commands to or query the virtual machine and container\n" -- cgit v1.2.3-54-g00ecf From a8725a06e6c5073325f2f6a7d6ef115c11d30a51 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 8 Oct 2016 19:03:53 -0400 Subject: nspawn: also fall back to legacy cgroup hierarchy for old containers Current systemd version detection routine cannot detect systemd 230, only systmed >= 231. This means that we'll still use the legacy hierarchy in some cases where we wouldn't have too. If somebody figures out a nice way to detect systemd 230 this can be later improved. --- src/nspawn/nspawn.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index a775d1ac4f..dbf94b48c3 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -342,10 +342,18 @@ static int detect_unified_cgroup_hierarchy(const char *directory) { "Failed to determine whether the unified cgroups hierarchy is used: %m"); /* Otherwise inherit the default from the host system */ - if (all_unified > 0) - arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL; - else if (systemd_unified > 0) { - /* mixed cgroup hierarchy support was added in 232 */ + if (all_unified > 0) { + /* Unified cgroup hierarchy support was added in 230. Unfortunately the detection + * routine only detects 231, so we'll have a false negative here for 230. */ + r = systemd_installation_has_version(directory, 230); + if (r < 0) + return log_error_errno(r, "Failed to determine systemd version in container: %m"); + if (r > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL; + else + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; + } else if (systemd_unified > 0) { + /* Mixed cgroup hierarchy support was added in 232 */ r = systemd_installation_has_version(directory, 232); if (r < 0) return log_error_errno(r, "Failed to determine systemd version in container: %m"); -- cgit v1.2.3-54-g00ecf From 27eb8e90285f5af26c95ce1566c37d4b0efcdeb3 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 9 Oct 2016 11:18:22 -0400 Subject: nspawn: reindent table --- src/nspawn/nspawn.c | 92 ++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index a08377b3a3..c3698b1a40 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -400,52 +400,52 @@ static int parse_argv(int argc, char *argv[]) { }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "directory", required_argument, NULL, 'D' }, - { "template", required_argument, NULL, ARG_TEMPLATE }, - { "ephemeral", no_argument, NULL, 'x' }, - { "user", required_argument, NULL, 'u' }, - { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK }, - { "as-pid2", no_argument, NULL, 'a' }, - { "boot", no_argument, NULL, 'b' }, - { "uuid", required_argument, NULL, ARG_UUID }, - { "read-only", no_argument, NULL, ARG_READ_ONLY }, - { "capability", required_argument, NULL, ARG_CAPABILITY }, - { "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY }, - { "link-journal", required_argument, NULL, ARG_LINK_JOURNAL }, - { "bind", required_argument, NULL, ARG_BIND }, - { "bind-ro", required_argument, NULL, ARG_BIND_RO }, - { "tmpfs", required_argument, NULL, ARG_TMPFS }, - { "overlay", required_argument, NULL, ARG_OVERLAY }, - { "overlay-ro", required_argument, NULL, ARG_OVERLAY_RO }, - { "machine", required_argument, NULL, 'M' }, - { "slice", required_argument, NULL, 'S' }, - { "setenv", required_argument, NULL, 'E' }, - { "selinux-context", required_argument, NULL, 'Z' }, - { "selinux-apifs-context", required_argument, NULL, 'L' }, - { "quiet", no_argument, NULL, 'q' }, - { "share-system", no_argument, NULL, ARG_SHARE_SYSTEM }, /* not documented */ - { "register", required_argument, NULL, ARG_REGISTER }, - { "keep-unit", no_argument, NULL, ARG_KEEP_UNIT }, - { "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE }, - { "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN }, - { "network-ipvlan", required_argument, NULL, ARG_NETWORK_IPVLAN }, - { "network-veth", no_argument, NULL, 'n' }, - { "network-veth-extra", required_argument, NULL, ARG_NETWORK_VETH_EXTRA}, - { "network-bridge", required_argument, NULL, ARG_NETWORK_BRIDGE }, - { "network-zone", required_argument, NULL, ARG_NETWORK_ZONE }, - { "personality", required_argument, NULL, ARG_PERSONALITY }, - { "image", required_argument, NULL, 'i' }, - { "volatile", optional_argument, NULL, ARG_VOLATILE }, - { "port", required_argument, NULL, 'p' }, - { "property", required_argument, NULL, ARG_PROPERTY }, - { "private-users", optional_argument, NULL, ARG_PRIVATE_USERS }, - { "private-users-chown", optional_argument, NULL, ARG_PRIVATE_USERS_CHOWN}, - { "kill-signal", required_argument, NULL, ARG_KILL_SIGNAL }, - { "settings", required_argument, NULL, ARG_SETTINGS }, - { "chdir", required_argument, NULL, ARG_CHDIR }, - { "notify-ready", required_argument, NULL, ARG_NOTIFY_READY }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "directory", required_argument, NULL, 'D' }, + { "template", required_argument, NULL, ARG_TEMPLATE }, + { "ephemeral", no_argument, NULL, 'x' }, + { "user", required_argument, NULL, 'u' }, + { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK }, + { "as-pid2", no_argument, NULL, 'a' }, + { "boot", no_argument, NULL, 'b' }, + { "uuid", required_argument, NULL, ARG_UUID }, + { "read-only", no_argument, NULL, ARG_READ_ONLY }, + { "capability", required_argument, NULL, ARG_CAPABILITY }, + { "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY }, + { "link-journal", required_argument, NULL, ARG_LINK_JOURNAL }, + { "bind", required_argument, NULL, ARG_BIND }, + { "bind-ro", required_argument, NULL, ARG_BIND_RO }, + { "tmpfs", required_argument, NULL, ARG_TMPFS }, + { "overlay", required_argument, NULL, ARG_OVERLAY }, + { "overlay-ro", required_argument, NULL, ARG_OVERLAY_RO }, + { "machine", required_argument, NULL, 'M' }, + { "slice", required_argument, NULL, 'S' }, + { "setenv", required_argument, NULL, 'E' }, + { "selinux-context", required_argument, NULL, 'Z' }, + { "selinux-apifs-context", required_argument, NULL, 'L' }, + { "quiet", no_argument, NULL, 'q' }, + { "share-system", no_argument, NULL, ARG_SHARE_SYSTEM }, /* not documented */ + { "register", required_argument, NULL, ARG_REGISTER }, + { "keep-unit", no_argument, NULL, ARG_KEEP_UNIT }, + { "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE }, + { "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN }, + { "network-ipvlan", required_argument, NULL, ARG_NETWORK_IPVLAN }, + { "network-veth", no_argument, NULL, 'n' }, + { "network-veth-extra", required_argument, NULL, ARG_NETWORK_VETH_EXTRA }, + { "network-bridge", required_argument, NULL, ARG_NETWORK_BRIDGE }, + { "network-zone", required_argument, NULL, ARG_NETWORK_ZONE }, + { "personality", required_argument, NULL, ARG_PERSONALITY }, + { "image", required_argument, NULL, 'i' }, + { "volatile", optional_argument, NULL, ARG_VOLATILE }, + { "port", required_argument, NULL, 'p' }, + { "property", required_argument, NULL, ARG_PROPERTY }, + { "private-users", optional_argument, NULL, ARG_PRIVATE_USERS }, + { "private-users-chown", optional_argument, NULL, ARG_PRIVATE_USERS_CHOWN }, + { "kill-signal", required_argument, NULL, ARG_KILL_SIGNAL }, + { "settings", required_argument, NULL, ARG_SETTINGS }, + { "chdir", required_argument, NULL, ARG_CHDIR }, + { "notify-ready", required_argument, NULL, ARG_NOTIFY_READY }, {} }; -- cgit v1.2.3-54-g00ecf From bfd292ec35c7b768f9fb5cff4d921f3133e62b19 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 9 Oct 2016 11:44:03 -0400 Subject: nspawn: fix parsing of numeric arguments for --private-users The documentation says lists "yes", "no", "pick", and numeric arguments. But parse_boolean was attempted first, so various numeric arguments were misinterpreted. In particular, this fixes --private-users=0 to mean the same thing as --private-users=0:65536. While at it, use strndupa to avoid some error handling. Also give a better error for an empty UID range. I think it's likely that people will use --private-users=0:0 thinking that the argument means UID:GID. --- src/nspawn/nspawn.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index c3698b1a40..d29866c3fe 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -900,13 +900,12 @@ static int parse_argv(int argc, char *argv[]) { case ARG_PRIVATE_USERS: - r = optarg ? parse_boolean(optarg) : 1; - if (r == 0) { + if (streq_ptr(optarg, "no")) { /* no: User namespacing off */ arg_userns_mode = USER_NAMESPACE_NO; arg_uid_shift = UID_INVALID; arg_uid_range = UINT32_C(0x10000); - } else if (r > 0) { + } else if (!optarg || streq(optarg, "yes")) { /* yes: User namespacing on, UID range is read from root dir */ arg_userns_mode = USER_NAMESPACE_FIXED; arg_uid_shift = UID_INVALID; @@ -917,23 +916,20 @@ static int parse_argv(int argc, char *argv[]) { arg_uid_shift = UID_INVALID; arg_uid_range = UINT32_C(0x10000); } else { - _cleanup_free_ char *buffer = NULL; const char *range, *shift; /* anything else: User namespacing on, UID range is explicitly configured */ range = strchr(optarg, ':'); if (range) { - buffer = strndup(optarg, range - optarg); - if (!buffer) - return log_oom(); - shift = buffer; + shift = strndupa(optarg, range - optarg); range++; - if (safe_atou32(range, &arg_uid_range) < 0 || arg_uid_range <= 0) { - log_error("Failed to parse UID range: %s", range); - return -EINVAL; - } + r = safe_atou32(range, &arg_uid_range); + if (r < 0) + return log_error_errno(r, "Failed to parse UID range '%s': %m", range); + if (arg_uid_range == 0) + return log_error_errno(EINVAL, "UID range cannot be 0."); } else shift = optarg; -- cgit v1.2.3-54-g00ecf From 6265bde205663644249b7c86286f49618031e382 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 9 Oct 2016 11:48:01 -0400 Subject: man: describe how to reverse systemd-nspawn -U Now that systemd-nspawn@.service includes -U, more users might be interested in this tidbit ;) --- man/systemd-nspawn.xml | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index bf3860604c..4439d554a7 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -453,17 +453,6 @@ except in the file ownership of the files and directories of the container. - - - - If the kernel supports the user namespaces feature, equivalent to - , otherwise equivalent to - . - - Note that is the default if the systemd-nspawn@.service template unit - file is used. - - @@ -476,6 +465,23 @@ user namespacing is not used. + + + + If the kernel supports the user namespaces feature, equivalent to + , otherwise equivalent to + . + + Note that is the default if the + systemd-nspawn@.service template unit file is used. + + Note: it is possible to undo the effect of (or + ) on the file system by redoing the operation with the first UID of 0: + + systemd-nspawn … --private-users=0 --private-users-chown + + + -- cgit v1.2.3-54-g00ecf From 59991e3fe3a71d6b6c743d4a38a2acd887ee7590 Mon Sep 17 00:00:00 2001 From: Lans Zhang Date: Mon, 10 Oct 2016 06:59:54 +0800 Subject: sd-boot: trigger to record further logs to tcg 2.0 final event log area (#4302) According to TCG EFI Protocol Specification for TPM 2.0 family, all events generated after the invocation of EFI_TCG2_GET_EVENT_LOG shall be stored in an instance of an EFI_CONFIGURATION_TABLE aka EFI TCG 2.0 final events table. Hence, it is necessary to trigger the internal switch through calling get_event_log() in order to allow to retrieve the logs from OS runtime. msekletar: > I've looked at EDK2 and indeed log entry is added to FinalEventsTable only after > EFI_TCG2_PROTOCOL.GetEventLog was called[1][2]. Also, same patch was currently > merged to shim by Peter Jones [3]. [1] https://github.com/tianocore/edk2/blob/master/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c#L698 [2] https://github.com/tianocore/edk2/blob/master/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c#L824 [3] rhinstaller/shim#64 --- src/boot/efi/measure.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c index 7c016387c1..4ac11a9bb0 100644 --- a/src/boot/efi/measure.c +++ b/src/boot/efi/measure.c @@ -209,12 +209,35 @@ static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 p return EFI_SUCCESS; } +/* + * According to TCG EFI Protocol Specification for TPM 2.0 family, + * all events generated after the invocation of EFI_TCG2_GET_EVENT_LOG + * shall be stored in an instance of an EFI_CONFIGURATION_TABLE aka + * EFI TCG 2.0 final events table. Hence, it is necessary to trigger the + * internal switch through calling get_event_log() in order to allow + * to retrieve the logs from OS runtime. + */ +static EFI_STATUS trigger_tcg2_final_events_table(const EFI_TCG2 *tcg) +{ + return uefi_call_wrapper(tcg->GetEventLog, 5, tcg, + EFI_TCG2_EVENT_LOG_FORMAT_TCG_2, NULL, + NULL, NULL); +} static EFI_STATUS tpm2_measure_to_pcr_and_event_log(const EFI_TCG2 *tcg, UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINT64 buffer_size, const CHAR16 *description) { EFI_STATUS status; EFI_TCG2_EVENT *tcg_event; UINTN desc_len; + static BOOLEAN triggered = FALSE; + + if (triggered == FALSE) { + status = trigger_tcg2_final_events_table(tcg); + if (EFI_ERROR(status)) + return status; + + triggered = TRUE; + } desc_len = StrLen(description) * sizeof(CHAR16); -- cgit v1.2.3-54-g00ecf From 424e490b94fca44d180122b3f2ded22bfc6d31ea Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 9 Oct 2016 14:19:06 -0400 Subject: resolved: simplify error handling in manager_dns_stub_{udp,tcp}_fd() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure an error is always printed… When systemd-resolved is started in a user namespace without private network, it would fail on setsockopt, but the error wouldn't be particularly informative: "Failed to start manager: permission denied." --- src/resolve/resolved-dns-stub.c | 152 ++++++++++++++-------------------------- src/resolve/resolved-dns-stub.h | 3 - 2 files changed, 54 insertions(+), 101 deletions(-) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 53772535c6..2430949525 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -25,6 +25,9 @@ * IP and UDP header sizes */ #define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U) +static int manager_dns_stub_udp_fd(Manager *m); +static int manager_dns_stub_tcp_fd(Manager *m); + static int dns_stub_make_reply_packet( uint16_t id, int rcode, @@ -354,66 +357,48 @@ static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void return 0; } -int manager_dns_stub_udp_fd(Manager *m) { +static int manager_dns_stub_udp_fd(Manager *m) { static const int one = 1; - union sockaddr_union sa = { .in.sin_family = AF_INET, .in.sin_port = htobe16(53), .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB), }; - + _cleanup_close_ int fd = -1; int r; if (m->dns_stub_udp_fd >= 0) return m->dns_stub_udp_fd; - m->dns_stub_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); - if (m->dns_stub_udp_fd < 0) + fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) return -errno; - r = setsockopt(m->dns_stub_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) < 0) + return -errno; - r = setsockopt(m->dns_stub_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof one) < 0) + return -errno; - r = setsockopt(m->dns_stub_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof one) < 0) + return -errno; /* Make sure no traffic from outside the local host can leak to onto this socket */ - r = setsockopt(m->dns_stub_udp_fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3) < 0) + return -errno; - r = bind(m->dns_stub_udp_fd, &sa.sa, sizeof(sa.in)); - if (r < 0) { - r = -errno; - goto fail; - } + if (bind(fd, &sa.sa, sizeof(sa.in)) < 0) + return -errno; - r = sd_event_add_io(m->event, &m->dns_stub_udp_event_source, m->dns_stub_udp_fd, EPOLLIN, on_dns_stub_packet, m); + r = sd_event_add_io(m->event, &m->dns_stub_udp_event_source, fd, EPOLLIN, on_dns_stub_packet, m); if (r < 0) - goto fail; + return r; (void) sd_event_source_set_description(m->dns_stub_udp_event_source, "dns-stub-udp"); + m->dns_stub_udp_fd = fd; + fd = -1; return m->dns_stub_udp_fd; - -fail: - m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd); - return r; } static int on_dns_stub_stream_packet(DnsStream *s) { @@ -461,106 +446,77 @@ static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void return 0; } -int manager_dns_stub_tcp_fd(Manager *m) { +static int manager_dns_stub_tcp_fd(Manager *m) { static const int one = 1; - union sockaddr_union sa = { .in.sin_family = AF_INET, .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB), .in.sin_port = htobe16(53), }; - + _cleanup_close_ int fd = -1; int r; if (m->dns_stub_tcp_fd >= 0) return m->dns_stub_tcp_fd; - m->dns_stub_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); - if (m->dns_stub_tcp_fd < 0) + fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) return -errno; - r = setsockopt(m->dns_stub_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof one) < 0) + return -errno; - r = setsockopt(m->dns_stub_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) < 0) + return -errno; - r = setsockopt(m->dns_stub_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof one) < 0) + return -errno; - r = setsockopt(m->dns_stub_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one)); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof one) < 0) + return -errno; /* Make sure no traffic from outside the local host can leak to onto this socket */ - r = setsockopt(m->dns_stub_tcp_fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3); - if (r < 0) { - r = -errno; - goto fail; - } + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, "lo", 3) < 0) + return -errno; - r = bind(m->dns_stub_tcp_fd, &sa.sa, sizeof(sa.in)); - if (r < 0) { - r = -errno; - goto fail; - } + if (bind(fd, &sa.sa, sizeof(sa.in)) < 0) + return -errno; - r = listen(m->dns_stub_tcp_fd, SOMAXCONN); - if (r < 0) { - r = -errno; - goto fail; - } + if (listen(fd, SOMAXCONN) < 0) + return -errno; - r = sd_event_add_io(m->event, &m->dns_stub_tcp_event_source, m->dns_stub_tcp_fd, EPOLLIN, on_dns_stub_stream, m); + r = sd_event_add_io(m->event, &m->dns_stub_tcp_event_source, fd, EPOLLIN, on_dns_stub_stream, m); if (r < 0) - goto fail; + return r; (void) sd_event_source_set_description(m->dns_stub_tcp_event_source, "dns-stub-tcp"); + m->dns_stub_tcp_fd = fd; + fd = -1; return m->dns_stub_tcp_fd; - -fail: - m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd); - return r; } int manager_dns_stub_start(Manager *m) { + const char *t = "UDP"; int r; assert(m); - if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_UDP)) { + if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_UDP)) r = manager_dns_stub_udp_fd(m); - if (r == -EADDRINUSE) - goto eaddrinuse; - if (r < 0) - return r; - } - if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_TCP)) { + if (r >= 0 && + IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_TCP)) { + t = "TCP"; r = manager_dns_stub_tcp_fd(m); - if (r == -EADDRINUSE) - goto eaddrinuse; - if (r < 0) - return r; } - return 0; - -eaddrinuse: - log_warning("Another process is already listening on 127.0.0.53:53. Turning off local DNS stub support."); - manager_dns_stub_stop(m); + if (r == -EADDRINUSE) { + log_warning("Another process is already listening on %s socket 127.0.0.53:53.\n" + "Turning off local DNS stub support.", t); + manager_dns_stub_stop(m); + } else if (r < 0) + return log_error_errno(r, "Failed to listen on %s socket 127.0.0.53:53: %m", t); return 0; } diff --git a/src/resolve/resolved-dns-stub.h b/src/resolve/resolved-dns-stub.h index fce4d25ede..12b86f6753 100644 --- a/src/resolve/resolved-dns-stub.h +++ b/src/resolve/resolved-dns-stub.h @@ -24,8 +24,5 @@ /* 127.0.0.53 in native endian */ #define INADDR_DNS_STUB ((in_addr_t) 0x7f000035U) -int manager_dns_stub_udp_fd(Manager *m); -int manager_dns_stub_tcp_fd(Manager *m); - void manager_dns_stub_stop(Manager *m); int manager_dns_stub_start(Manager *m); -- cgit v1.2.3-54-g00ecf From 0f4db364c940d4ad672f9a62d3077aeef89d8629 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 9 Oct 2016 15:04:59 -0400 Subject: resolved: also disable stub listener on EPERM When running in a user namespace without private networking, resolved would fail to start. There isn't much difference between EADDRINUSE and EPERM, so treat them the same, except for the warning message text. --- src/resolve/resolved-dns-stub.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 2430949525..b1c570cee6 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -511,9 +511,15 @@ int manager_dns_stub_start(Manager *m) { r = manager_dns_stub_tcp_fd(m); } - if (r == -EADDRINUSE) { - log_warning("Another process is already listening on %s socket 127.0.0.53:53.\n" - "Turning off local DNS stub support.", t); + if (IN_SET(r, -EADDRINUSE, -EPERM)) { + if (r == -EADDRINUSE) + log_warning_errno(r, + "Another process is already listening on %s socket 127.0.0.53:53.\n" + "Turning off local DNS stub support.", t); + else + log_warning_errno(r, + "Failed to listen on %s socket 127.0.0.53:53: %m.\n" + "Turning off local DNS stub support.", t); manager_dns_stub_stop(m); } else if (r < 0) return log_error_errno(r, "Failed to listen on %s socket 127.0.0.53:53: %m", t); -- cgit v1.2.3-54-g00ecf From 9fc932bff1e2058885fc458412b3c94d586cb586 Mon Sep 17 00:00:00 2001 From: 0xAX <0xAX@users.noreply.github.com> Date: Mon, 10 Oct 2016 05:55:24 +0300 Subject: tree-wide: print warning in a failure case of make_null_stdio() (#4320) The make_null_stdio() may fail. Let's check its result and print warning message instead of keeping silence. --- src/core/main.c | 3 ++- src/udev/udevd.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 6fe440277e..e88362b7fe 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1532,7 +1532,8 @@ int main(int argc, char *argv[]) { * need to do that for user instances since they never log * into the console. */ log_show_color(colors_enabled()); - make_null_stdio(); + if (make_null_stdio() < 0) + log_warning_errno(errno, "Failed to redirect standard streams to /dev/null: %m"); } /* Initialize default unit */ diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 19f1c29198..6000d9c7ec 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -1739,7 +1739,9 @@ int main(int argc, char *argv[]) { /* connect /dev/null to stdin, stdout, stderr */ if (log_get_max_level() < LOG_DEBUG) - (void) make_null_stdio(); + if (make_null_stdio() < 0) + log_warning_errno(errno, "Failed to redirect standard streams to /dev/null: %m"); + pid = fork(); switch (pid) { -- cgit v1.2.3-54-g00ecf From 10c961b9c9625d4e0408b5f21e2ba815148ccf63 Mon Sep 17 00:00:00 2001 From: 0xAX <0xAX@users.noreply.github.com> Date: Mon, 10 Oct 2016 05:57:03 +0300 Subject: main: initialize default unit little later (#4321) systemd fills arg_default_unit during startup with default.target value. But arg_default_unit may be overwritten in parse_argv() or parse_proc_cmdline_item(). Let's check value of arg_default_unit after calls of parse_argv() and parse_proc_cmdline_item() and fill it with default.target if it wasn't filled before. In this way we will not spend unnecessary time to for filling arg_default_unit with default.target. --- src/core/main.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index e88362b7fe..0fad393323 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1536,14 +1536,6 @@ int main(int argc, char *argv[]) { log_warning_errno(errno, "Failed to redirect standard streams to /dev/null: %m"); } - /* Initialize default unit */ - r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET); - if (r < 0) { - log_emergency_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET); - error_message = "Failed to set default unit"; - goto finish; - } - r = initialize_join_controllers(); if (r < 0) { error_message = "Failed to initialize cgroup controllers"; @@ -1591,6 +1583,16 @@ int main(int argc, char *argv[]) { goto finish; } + /* Initialize default unit */ + if (!arg_default_unit) { + r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET); + if (r < 0) { + log_emergency_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET); + error_message = "Failed to set default unit"; + goto finish; + } + } + if (arg_action == ACTION_TEST && geteuid() == 0) { log_error("Don't run test mode as root."); -- cgit v1.2.3-54-g00ecf From 84a69ca9ba49a516c741582c4b2f69b0feb0f020 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Mon, 10 Oct 2016 12:06:26 +0200 Subject: unit: drop console-shell.service (#4298) (#4325) console-shell.service was supposed to be useful for normal clean boots (i.e. multi-user.target or so), as a replacement for logind/getty@.service for simpler use cases. But due to the lack of documentation and sanity check one can easily be confused and enable this service in // with getty@.service. In this case we end up with both services sharing the same tty which ends up in strange results. Even worse, console-shell.service might be failing while getty@.service tries to acquire the terminal which ends up in the system to poweroff since console-shell.service uses: "ExecStopPost=-/usr/bin/systemctl poweroff". Another issue: this service doesn't work well if plymouth is also used since it lets the splash screen program run and mess the tty (at least a "plymouth quit" is missing). So let's kill it for now. --- Makefile.am | 2 -- system-preset/90-systemd.preset | 1 - units/.gitignore | 2 -- units/console-shell.service.m4.in | 31 ------------------------------- 4 files changed, 36 deletions(-) delete mode 100644 units/console-shell.service.m4.in diff --git a/Makefile.am b/Makefile.am index f7ae9ff7aa..b09b0cf167 100644 --- a/Makefile.am +++ b/Makefile.am @@ -524,7 +524,6 @@ dist_systemunit_DATA_busnames += \ nodist_systemunit_DATA = \ units/getty@.service \ units/serial-getty@.service \ - units/console-shell.service \ units/console-getty.service \ units/container-getty@.service \ units/systemd-initctl.service \ @@ -587,7 +586,6 @@ dist_systempreset_DATA = \ EXTRA_DIST += \ units/getty@.service.m4 \ units/serial-getty@.service.m4 \ - units/console-shell.service.m4.in \ units/console-getty.service.m4.in \ units/container-getty@.service.m4.in \ units/rescue.service.in \ diff --git a/system-preset/90-systemd.preset b/system-preset/90-systemd.preset index 0f494b7552..6b5349dc8d 100644 --- a/system-preset/90-systemd.preset +++ b/system-preset/90-systemd.preset @@ -18,7 +18,6 @@ enable systemd-resolved.service enable systemd-networkd-wait-online.service disable console-getty.service -disable console-shell.service disable debug-shell.service disable halt.target diff --git a/units/.gitignore b/units/.gitignore index 47e99154ee..8f4949258e 100644 --- a/units/.gitignore +++ b/units/.gitignore @@ -1,8 +1,6 @@ /user@.service.m4 /console-getty.service /console-getty.service.m4 -/console-shell.service -/console-shell.service.m4 /container-getty@.service /container-getty@.service.m4 /debug-shell.service diff --git a/units/console-shell.service.m4.in b/units/console-shell.service.m4.in deleted file mode 100644 index a345ec25d4..0000000000 --- a/units/console-shell.service.m4.in +++ /dev/null @@ -1,31 +0,0 @@ -# This file is part of systemd. -# -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. - -[Unit] -Description=Console Shell -Documentation=man:sulogin(8) -After=systemd-user-sessions.service plymouth-quit-wait.service -m4_ifdef(`HAVE_SYSV_COMPAT', -After=rc-local.service -)m4_dnl -Before=getty.target - -[Service] -Environment=HOME=/root -WorkingDirectory=-/root -ExecStart=-@SULOGIN@ -ExecStopPost=-@SYSTEMCTL@ poweroff -Type=idle -StandardInput=tty-force -StandardOutput=inherit -StandardError=inherit -KillMode=process -IgnoreSIGPIPE=no -SendSIGHUP=yes - -[Install] -WantedBy=getty.target -- cgit v1.2.3-54-g00ecf From baed1fedba161d7db89636a417751891831c432a Mon Sep 17 00:00:00 2001 From: Felipe Sateler Date: Mon, 10 Oct 2016 10:40:05 -0300 Subject: login: drop fedora-specific PAM config, add note to DISTRO_PORTING (#4314) It is impossible to ship a fully generic PAM configuration upstream. Therefore, ship a minimal configuration with the systemd --user requirements, and add a note to DISTRO_PORTING documenting this. Fixes #4284 --- DISTRO_PORTING | 7 +++++++ src/login/systemd-user.m4 | 4 +--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/DISTRO_PORTING b/DISTRO_PORTING index a397d700c6..9f61bd6de6 100644 --- a/DISTRO_PORTING +++ b/DISTRO_PORTING @@ -41,6 +41,13 @@ NTP POOL: NTP servers, then you will get served wrong time, and will rely on services that might not be supported for long. +PAM: + The default PAM config shipped by systemd is really bare bones. + It does not include many modules your distro might want to enable + to provide a more seamless experience. For example, limits set in + /etc/security/limits.conf will not be read unless you load pam_limits. + Make sure you add modules your distro expects from user services. + CONTRIBUTING UPSTREAM: We generally do no longer accept distribution-specific diff --git a/src/login/systemd-user.m4 b/src/login/systemd-user.m4 index f188a8e548..fe38b24fef 100644 --- a/src/login/systemd-user.m4 +++ b/src/login/systemd-user.m4 @@ -2,11 +2,9 @@ # # Used by systemd --user instances. -account include system-auth - m4_ifdef(`HAVE_SELINUX', session required pam_selinux.so close session required pam_selinux.so nottys open )m4_dnl session required pam_loginuid.so -session include system-auth +session optional pam_systemd.so -- cgit v1.2.3-54-g00ecf From 6c2058b35e7678bc0319f374a75a52affeb4a9e9 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 10 Oct 2016 10:04:31 -0400 Subject: Revert "nspawn: fix parsing of numeric arguments for --private-users" This reverts commit bfd292ec35c7b768f9fb5cff4d921f3133e62b19. --- src/nspawn/nspawn.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index d29866c3fe..c3698b1a40 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -900,12 +900,13 @@ static int parse_argv(int argc, char *argv[]) { case ARG_PRIVATE_USERS: - if (streq_ptr(optarg, "no")) { + r = optarg ? parse_boolean(optarg) : 1; + if (r == 0) { /* no: User namespacing off */ arg_userns_mode = USER_NAMESPACE_NO; arg_uid_shift = UID_INVALID; arg_uid_range = UINT32_C(0x10000); - } else if (!optarg || streq(optarg, "yes")) { + } else if (r > 0) { /* yes: User namespacing on, UID range is read from root dir */ arg_userns_mode = USER_NAMESPACE_FIXED; arg_uid_shift = UID_INVALID; @@ -916,20 +917,23 @@ static int parse_argv(int argc, char *argv[]) { arg_uid_shift = UID_INVALID; arg_uid_range = UINT32_C(0x10000); } else { + _cleanup_free_ char *buffer = NULL; const char *range, *shift; /* anything else: User namespacing on, UID range is explicitly configured */ range = strchr(optarg, ':'); if (range) { - shift = strndupa(optarg, range - optarg); + buffer = strndup(optarg, range - optarg); + if (!buffer) + return log_oom(); + shift = buffer; range++; - r = safe_atou32(range, &arg_uid_range); - if (r < 0) - return log_error_errno(r, "Failed to parse UID range '%s': %m", range); - if (arg_uid_range == 0) - return log_error_errno(EINVAL, "UID range cannot be 0."); + if (safe_atou32(range, &arg_uid_range) < 0 || arg_uid_range <= 0) { + log_error("Failed to parse UID range: %s", range); + return -EINVAL; + } } else shift = optarg; -- cgit v1.2.3-54-g00ecf From ae209204d80043f75d71b38a4e98e676887155d8 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 10 Oct 2016 11:12:57 -0400 Subject: nspawn,man: fix parsing of numeric args for --private-users, accept any boolean This is like the previous reverted commit, but any boolean is still accepted, not just "yes" and "no". Man page is adjusted to match the code. --- man/systemd-nspawn.xml | 59 +++++++++++++++++++++++++------------------------- src/nspawn/nspawn.c | 15 +++++++++---- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index 4439d554a7..5ac54df81a 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -405,35 +405,36 @@ purposes (usually in the range beyond the host's UID/GID 65536). The parameter may be specified as follows: - The value no turns off user namespacing. This is the default. - - The value yes (or the omission of a parameter) turns on user - namespacing. The UID/GID range to use is determined automatically from the file ownership of the root - directory of the container's directory tree. To use this option, make sure to prepare the directory tree in - advance, and ensure that all files and directories in it are owned by UIDs/GIDs in the range you'd like to - use. Also, make sure that used file ACLs exclusively reference UIDs/GIDs in the appropriate range. If this - mode is used the number of UIDs/GIDs assigned to the container for use is 65536, and the UID/GID of the - root directory must be a multiple of 65536. - - The value "pick" turns on user namespacing. In this case the UID/GID range is automatically - chosen. As first step, the file owner of the root directory of the container's directory tree is read, and it - is checked that it is currently not used by the system otherwise (in particular, that no other container is - using it). If this check is successful, the UID/GID range determined this way is used, similar to the - behaviour if "yes" is specified. If the check is not successful (and thus the UID/GID range indicated in the - root directory's file owner is already used elsewhere) a new – currently unused – UID/GID range of 65536 - UIDs/GIDs is randomly chosen between the host UID/GIDs of 524288 and 1878982656, always starting at a - multiple of 65536. This setting implies (see below), which has the - effect that the files and directories in the container's directory tree will be owned by the appropriate - users of the range picked. Using this option makes user namespace behaviour fully automatic. Note that the - first invocation of a previously unused container image might result in picking a new UID/GID range for it, - and thus in the (possibly expensive) file ownership adjustment operation. However, subsequent invocations of - the container will be cheap (unless of course the picked UID/GID range is assigned to a different use by - then). - - Finally if one or two colon-separated numeric parameters are specified, user namespacing is - turned on, too. The first parameter specifies the first host UID/GID to assign to the container, the second - parameter specifies the number of host UIDs/GIDs to assign to the container. If the second parameter is - omitted, 65536 UIDs/GIDs are assigned. + If one or two colon-separated numers are specified, user namespacing is turned on. The first + parameter specifies the first host UID/GID to assign to the container, the second parameter specifies the + number of host UIDs/GIDs to assign to the container. If the second parameter is omitted, 65536 UIDs/GIDs are + assigned. + + If the parameter is omitted, or true, user namespacing is turned on. The UID/GID range to + use is determined automatically from the file ownership of the root directory of the container's directory + tree. To use this option, make sure to prepare the directory tree in advance, and ensure that all files and + directories in it are owned by UIDs/GIDs in the range you'd like to use. Also, make sure that used file ACLs + exclusively reference UIDs/GIDs in the appropriate range. If this mode is used the number of UIDs/GIDs + assigned to the container for use is 65536, and the UID/GID of the root directory must be a multiple of + 65536. + + If the parameter is false, user namespacing is turned off. This is the default. + + + The special value pick turns on user namespacing. In this case the UID/GID + range is automatically chosen. As first step, the file owner of the root directory of the container's + directory tree is read, and it is checked that it is currently not used by the system otherwise (in + particular, that no other container is using it). If this check is successful, the UID/GID range determined + this way is used, similar to the behaviour if "yes" is specified. If the check is not successful (and thus + the UID/GID range indicated in the root directory's file owner is already used elsewhere) a new – currently + unused – UID/GID range of 65536 UIDs/GIDs is randomly chosen between the host UID/GIDs of 524288 and + 1878982656, always starting at a multiple of 65536. This setting implies + (see below), which has the effect that the files and directories in + the container's directory tree will be owned by the appropriate users of the range picked. Using this option + makes user namespace behaviour fully automatic. Note that the first invocation of a previously unused + container image might result in picking a new UID/GID range for it, and thus in the (possibly expensive) file + ownership adjustment operation. However, subsequent invocations of the container will be cheap (unless of + course the picked UID/GID range is assigned to a different use by then). It is recommended to assign at least 65536 UIDs/GIDs to each container, so that the usable UID/GID range in the diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index c3698b1a40..869b20e180 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -898,15 +898,21 @@ static int parse_argv(int argc, char *argv[]) { break; - case ARG_PRIVATE_USERS: + case ARG_PRIVATE_USERS: { + int boolean = -1; - r = optarg ? parse_boolean(optarg) : 1; - if (r == 0) { + if (!optarg) + boolean = true; + else if (!in_charset(optarg, DIGITS)) + /* do *not* parse numbers as booleans */ + boolean = parse_boolean(optarg); + + if (boolean == false) { /* no: User namespacing off */ arg_userns_mode = USER_NAMESPACE_NO; arg_uid_shift = UID_INVALID; arg_uid_range = UINT32_C(0x10000); - } else if (r > 0) { + } else if (boolean == true) { /* yes: User namespacing on, UID range is read from root dir */ arg_userns_mode = USER_NAMESPACE_FIXED; arg_uid_shift = UID_INVALID; @@ -947,6 +953,7 @@ static int parse_argv(int argc, char *argv[]) { arg_settings_mask |= SETTING_USERNS; break; + } case 'U': if (userns_supported()) { -- cgit v1.2.3-54-g00ecf From be7157316ce44bdff9d89c138c6b98ae0e96b9e3 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 10 Oct 2016 11:22:45 -0400 Subject: nspawn: better error messages for parsing errors In particular, the check for arg_uid_range <= 0 is moved to the end, so that "foobar:0" gives "Failed to parse UID", and not "UID range cannot be 0.". --- src/nspawn/nspawn.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 869b20e180..aec86df4b6 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -936,21 +936,24 @@ static int parse_argv(int argc, char *argv[]) { shift = buffer; range++; - if (safe_atou32(range, &arg_uid_range) < 0 || arg_uid_range <= 0) { - log_error("Failed to parse UID range: %s", range); - return -EINVAL; - } + r = safe_atou32(range, &arg_uid_range); + if (r < 0) + return log_error_errno(r, "Failed to parse UID range \"%s\": %m", range); } else shift = optarg; - if (parse_uid(shift, &arg_uid_shift) < 0) { - log_error("Failed to parse UID: %s", optarg); - return -EINVAL; - } + r = parse_uid(shift, &arg_uid_shift); + if (r < 0) + return log_error_errno(r, "Failed to parse UID \"%s\": %m", optarg); arg_userns_mode = USER_NAMESPACE_FIXED; } + if (arg_uid_range <= 0) { + log_error("UID range cannot be 0."); + return -EINVAL; + } + arg_settings_mask |= SETTING_USERNS; break; } -- cgit v1.2.3-54-g00ecf From c76cf844d6e59ca5ac5eb3e6c60b3e501815c5b8 Mon Sep 17 00:00:00 2001 From: 0xAX <0xAX@users.noreply.github.com> Date: Mon, 10 Oct 2016 20:51:33 +0300 Subject: tree-wide: pass return value of make_null_stdio() to warning instead of errno (#4328) as @poettering suggested in the #4320 --- src/core/main.c | 5 +++-- src/udev/udevd.c | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 0fad393323..30d9c43fbb 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1532,8 +1532,9 @@ int main(int argc, char *argv[]) { * need to do that for user instances since they never log * into the console. */ log_show_color(colors_enabled()); - if (make_null_stdio() < 0) - log_warning_errno(errno, "Failed to redirect standard streams to /dev/null: %m"); + r = make_null_stdio(); + if (r < 0) + log_warning_errno(r, "Failed to redirect standard streams to /dev/null: %m"); } r = initialize_join_controllers(); diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 6000d9c7ec..535d317c27 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -1738,9 +1738,12 @@ int main(int argc, char *argv[]) { log_info("starting version " VERSION); /* connect /dev/null to stdin, stdout, stderr */ - if (log_get_max_level() < LOG_DEBUG) - if (make_null_stdio() < 0) - log_warning_errno(errno, "Failed to redirect standard streams to /dev/null: %m"); + if (log_get_max_level() < LOG_DEBUG) { + r = make_null_stdio(); + if (r < 0) + log_warning_errno(r, "Failed to redirect standard streams to /dev/null: %m"); + } + pid = fork(); -- cgit v1.2.3-54-g00ecf From 53c06862c12918ec717ea70918039765212eee95 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Mon, 10 Oct 2016 23:22:12 +0530 Subject: networkd: rename Rename CheckSum → Checksum (#4312) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- man/systemd.netdev.xml | 8 ++++---- src/network/networkd-netdev-gperf.gperf | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index e378e61dd1..ffb66e735b 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -537,7 +537,7 @@ - UDPCheckSum= + UDPChecksum= A boolean. When true, transmitting UDP checksums when doing VXLAN/IPv4 is turned on. @@ -549,19 +549,19 @@ - UDP6ZeroCheckSumRx= + UDP6ZeroChecksumRx= A boolean. When true, receiving zero checksums in VXLAN/IPv6 is turned on. - RemoteCheckSumTx= + RemoteChecksumTx= A boolean. When true, remote transmit checksum offload of VXLAN is turned on. - RemoteCheckSumRx= + RemoteChecksumRx= A boolean. When true, remote receive checksum offload in VXLAN is turned on. diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf index 6b7ab7ab87..323eaa8032 100644 --- a/src/network/networkd-netdev-gperf.gperf +++ b/src/network/networkd-netdev-gperf.gperf @@ -63,10 +63,13 @@ VXLAN.L2MissNotification, config_parse_bool, 0, VXLAN.L3MissNotification, config_parse_bool, 0, offsetof(VxLan, l3miss) VXLAN.RouteShortCircuit, config_parse_bool, 0, offsetof(VxLan, route_short_circuit) VXLAN.UDPCheckSum, config_parse_bool, 0, offsetof(VxLan, udpcsum) +VXLAN.UDPChecksum, config_parse_bool, 0, offsetof(VxLan, udpcsum) VXLAN.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx) +VXLAN.UDP6ZeroChecksumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx) VXLAN.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx) -VXLAN.RemoteCheckSumTx, config_parse_bool, 0, offsetof(VxLan, remote_csum_tx) -VXLAN.RemoteCheckSumRx, config_parse_bool, 0, offsetof(VxLan, remote_csum_rx) +VXLAN.UDP6ZeroChecksumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx) +VXLAN.RemoteChecksumTx, config_parse_bool, 0, offsetof(VxLan, remote_csum_tx) +VXLAN.RemoteChecksumRx, config_parse_bool, 0, offsetof(VxLan, remote_csum_rx) VXLAN.FDBAgeingSec, config_parse_sec, 0, offsetof(VxLan, fdb_ageing) VXLAN.GroupPolicyExtension, config_parse_bool, 0, offsetof(VxLan, group_policy) VXLAN.MaximumFDBEntries, config_parse_unsigned, 0, offsetof(VxLan, max_fdb) -- cgit v1.2.3-54-g00ecf From 642d6665f431c246e466703cdd4f32814603b579 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Oct 2016 19:53:37 +0200 Subject: update TODO --- TODO | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO b/TODO index 9ca2736b2a..752253f826 100644 --- a/TODO +++ b/TODO @@ -32,6 +32,8 @@ Janitorial Clean-ups: Features: +* on cgroupsv2 add DelegateControllers=, to pick the precise cgroup controllers to delegate + * in networkd, when matching device types, fix up DEVTYPE rubbish the kernel passes to us * enable LockMLOCK to take a percentage value relative to physical memory -- cgit v1.2.3-54-g00ecf From 65e3fd83c98a44111c1b05a6e0d492dcab58853b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Oct 2016 20:08:41 +0200 Subject: exit-status: remove ExitStatus typedef Do not make up our own type for ExitStatus, but use the type used by POSIX for this, which is "int". In particular as we never used that type outside of the definition of exit_status_to_string() where we internally cast the paramter to (int) every single time we used it. Hence, let's simplify things, drop the type and use the kernel type directly. --- src/basic/exit-status.c | 9 ++++----- src/basic/exit-status.h | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c index d488cfc59f..d2a8d3b418 100644 --- a/src/basic/exit-status.c +++ b/src/basic/exit-status.c @@ -24,12 +24,12 @@ #include "macro.h" #include "set.h" -const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) { +const char* exit_status_to_string(int status, ExitStatusLevel level) { /* We cast to int here, so that -Wenum doesn't complain that * EXIT_SUCCESS/EXIT_FAILURE aren't in the enum */ - switch ((int) status) { + switch (status) { case EXIT_SUCCESS: return "SUCCESS"; @@ -39,7 +39,7 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) { } if (IN_SET(level, EXIT_STATUS_SYSTEMD, EXIT_STATUS_LSB)) { - switch ((int) status) { + switch (status) { case EXIT_CHDIR: return "CHDIR"; @@ -152,7 +152,7 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) { } if (level == EXIT_STATUS_LSB) { - switch ((int) status) { + switch (status) { case EXIT_INVALIDARGUMENT: return "INVALIDARGUMENT"; @@ -177,7 +177,6 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) { return NULL; } - bool is_clean_exit(int code, int status, ExitStatusSet *success_status) { if (code == CLD_EXITED) diff --git a/src/basic/exit-status.h b/src/basic/exit-status.h index 2309f68815..46cc905865 100644 --- a/src/basic/exit-status.h +++ b/src/basic/exit-status.h @@ -31,7 +31,7 @@ * https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html */ -typedef enum ExitStatus { +enum { /* EXIT_SUCCESS defined by libc */ /* EXIT_FAILURE defined by libc */ EXIT_INVALIDARGUMENT = 2, @@ -82,7 +82,7 @@ typedef enum ExitStatus { EXIT_MAKE_STARTER, EXIT_CHOWN, EXIT_SMACK_PROCESS_LABEL, -} ExitStatus; +}; typedef enum ExitStatusLevel { EXIT_STATUS_MINIMAL, /* only cover libc EXIT_STATUS/EXIT_FAILURE */ @@ -96,7 +96,7 @@ typedef struct ExitStatusSet { Set *signal; } ExitStatusSet; -const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) _const_; +const char* exit_status_to_string(int status, ExitStatusLevel level) _const_; bool is_clean_exit(int code, int status, ExitStatusSet *success_status); bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status); -- cgit v1.2.3-54-g00ecf From 56ecbcc04868e749ae320b7ed9c3fd90aff2951f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Oct 2016 20:11:21 +0200 Subject: exit-status: reorder the exit status switch table Let's make sure it's in the same order as the actual enum defining the exit statuses. --- src/basic/exit-status.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c index d2a8d3b418..81c2c6675c 100644 --- a/src/basic/exit-status.c +++ b/src/basic/exit-status.c @@ -140,12 +140,12 @@ const char* exit_status_to_string(int status, ExitStatusLevel level) { case EXIT_RUNTIME_DIRECTORY: return "RUNTIME_DIRECTORY"; - case EXIT_CHOWN: - return "CHOWN"; - case EXIT_MAKE_STARTER: return "MAKE_STARTER"; + case EXIT_CHOWN: + return "CHOWN"; + case EXIT_SMACK_PROCESS_LABEL: return "SMACK_PROCESS_LABEL"; } -- cgit v1.2.3-54-g00ecf From 3b8769bda8c79283ea89686a16e6cff2e9a6f495 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Oct 2016 20:11:49 +0200 Subject: install: let's always refer to the actual setting in errors --- src/shared/install.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/install.c b/src/shared/install.c index 5f12fb447f..60a6d1312d 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1020,7 +1020,7 @@ static int config_parse_alias( type = unit_name_to_type(name); if (!unit_type_may_alias(type)) return log_syntax(unit, LOG_WARNING, filename, line, 0, - "Aliases are not allowed for %s units, ignoring.", + "Alias= is not allowed for %s units, ignoring.", unit_type_to_string(type)); return config_parse_strv(unit, filename, line, section, section_line, @@ -1098,7 +1098,7 @@ static int config_parse_default_instance( return 0; if (!unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) return log_syntax(unit, LOG_WARNING, filename, line, 0, - "DefaultInstance only makes sense for template units, ignoring."); + "DefaultInstance= only makes sense for template units, ignoring."); r = install_full_printf(i, rvalue, &printed); if (r < 0) -- cgit v1.2.3-54-g00ecf From 800d3f3478b3dfd546344a4b8f5cc09860bd7da5 Mon Sep 17 00:00:00 2001 From: Dan Dedrick Date: Wed, 4 May 2016 17:06:45 -0400 Subject: journal-remote: make the child pipe non-blocking We are going to add this child as a source to our event loop so we don't want to block when reading data from it as this will prevent us from processing other events. Specifically this will block the signalfds which means if we are waiting for data from curl we won't handle SIGTERM or SIGINT until we happen to get more data. --- src/journal-remote/journal-remote.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index a9009cfefe..d86c3681b1 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -127,6 +127,10 @@ static int spawn_child(const char* child, char** argv) { if (r < 0) log_warning_errno(errno, "Failed to close write end of pipe: %m"); + r = fd_nonblock(fd[0], true); + if (r < 0) + log_warning_errno(errno, "Failed to set child pipe to non-blocking: %m"); + return fd[0]; } -- cgit v1.2.3-54-g00ecf From 6f157e4e4f37a12235ee619970e3776f1fdd1849 Mon Sep 17 00:00:00 2001 From: Dan Dedrick Date: Fri, 6 May 2016 15:14:14 -0400 Subject: journal-remote: fix up misleading man page The --no-seal and --no-compress options were dropped and replaced with boolean functionality. This syncs the man page with the code. --- man/systemd-journal-remote.xml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/man/systemd-journal-remote.xml b/man/systemd-journal-remote.xml index f208f8deb4..ee2d5c2486 100644 --- a/man/systemd-journal-remote.xml +++ b/man/systemd-journal-remote.xml @@ -250,20 +250,19 @@ - - + [BOOL] - Compress or not, respectively, the data in the - journal using XZ. + If this is set to yes then compress + the data in the journal using XZ. The default is yes. + - - + [BOOL] - Periodically sign or not, respectively, the - data in the journal using Forward Secure Sealing. - + If this is set to yes then + periodically sign the data in the journal using Forward Secure Sealing. + The default is no. -- cgit v1.2.3-54-g00ecf From 41e2036eb83204df95a1c3e829bcfd78ee17aaa3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Oct 2016 21:48:08 +0200 Subject: exit-status: kill is_clean_exit_lsb(), move logic to sysv-generator Let's get rid of is_clean_exit_lsb(), let's move the logic for the special handling of the two LSB exit codes into the sysv-generator by writing out appropriate SuccessExitStatus= lines if the LSB header exists. This is not only semantically more correct, bug also fixes a bug as the code in service.c that chose between is_clean_exit_lsb() and is_clean_exit() based this check on whether a native unit files was available for the unit. However, that check was bogus since a long time, since the SysV generator was introduced and native SysV script support was removed from PID 1, as in that case a unit file always existed. --- src/basic/exit-status.c | 10 ---------- src/basic/exit-status.h | 1 - src/core/service.c | 3 +-- src/systemctl/systemctl.c | 2 +- src/sysv-generator/sysv-generator.c | 8 ++++++++ 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c index 81c2c6675c..96d4619da6 100644 --- a/src/basic/exit-status.c +++ b/src/basic/exit-status.c @@ -194,16 +194,6 @@ bool is_clean_exit(int code, int status, ExitStatusSet *success_status) { return false; } -bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status) { - - if (is_clean_exit(code, status, success_status)) - return true; - - return - code == CLD_EXITED && - IN_SET(status, EXIT_NOTINSTALLED, EXIT_NOTCONFIGURED); -} - void exit_status_set_free(ExitStatusSet *x) { assert(x); diff --git a/src/basic/exit-status.h b/src/basic/exit-status.h index 46cc905865..b3baa50cf4 100644 --- a/src/basic/exit-status.h +++ b/src/basic/exit-status.h @@ -99,7 +99,6 @@ typedef struct ExitStatusSet { const char* exit_status_to_string(int status, ExitStatusLevel level) _const_; bool is_clean_exit(int code, int status, ExitStatusSet *success_status); -bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status); void exit_status_set_free(ExitStatusSet *x); bool exit_status_set_is_empty(ExitStatusSet *x); diff --git a/src/core/service.c b/src/core/service.c index 99a70395fc..fc1d353356 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2600,8 +2600,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { assert(s); assert(pid >= 0); - if (UNIT(s)->fragment_path ? is_clean_exit(code, status, &s->success_status) : - is_clean_exit_lsb(code, status, &s->success_status)) + if (is_clean_exit(code, status, &s->success_status)) f = SERVICE_SUCCESS; else if (code == CLD_EXITED) f = SERVICE_FAILURE_EXIT_CODE; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index bb6002e8ef..9c6a475a39 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3936,7 +3936,7 @@ static void print_status_info( argv = strv_join(p->argv, " "); printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv)); - good = is_clean_exit_lsb(p->code, p->status, NULL); + good = is_clean_exit(p->code, p->status, NULL); if (!good) { on = ansi_highlight_red(); off = ansi_normal(); diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c index 39821687b9..c2c80175a2 100644 --- a/src/sysv-generator/sysv-generator.c +++ b/src/sysv-generator/sysv-generator.c @@ -25,6 +25,7 @@ #include "alloc-util.h" #include "dirent-util.h" +#include "exit-status.h" #include "fd-util.h" #include "fileio.h" #include "hashmap.h" @@ -199,6 +200,13 @@ static int generate_unit_file(SysvStub *s) { if (s->pid_file) fprintf(f, "PIDFile=%s\n", s->pid_file); + /* Consider two special LSB exit codes a clean exit */ + if (s->has_lsb) + fprintf(f, + "SuccessExitStatus=%i %i\n", + EXIT_NOTINSTALLED, + EXIT_NOTCONFIGURED); + fprintf(f, "ExecStart=%s start\n" "ExecStop=%s stop\n", -- cgit v1.2.3-54-g00ecf From f6dd106c73abb33af5eb0aaeffcddd11724515e6 Mon Sep 17 00:00:00 2001 From: 0xAX <0xAX@users.noreply.github.com> Date: Mon, 10 Oct 2016 23:11:36 +0300 Subject: main: use strdup instead of free_and_strdup to initialize default unit (#4335) Previously we've used free_and_strdup() to fill arg_default_unit with unit name, If we didn't pass default unit name through a kernel command line or command line arguments. But we can use just strdup() instead of free_and_strdup() for this, because we will start fill arg_default_unit only if it wasn't set before. --- src/core/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 30d9c43fbb..9985510161 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1586,9 +1586,9 @@ int main(int argc, char *argv[]) { /* Initialize default unit */ if (!arg_default_unit) { - r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET); - if (r < 0) { - log_emergency_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET); + arg_default_unit = strdup(SPECIAL_DEFAULT_TARGET); + if (!arg_default_unit) { + r = log_oom(); error_message = "Failed to set default unit"; goto finish; } -- cgit v1.2.3-54-g00ecf From 38107f5a4ad5ab148054910040d5d548a4c7a805 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Oct 2016 21:56:36 +0200 Subject: core: lower exit status "level" at one place When we print information about PID 1's crashdump subprocess failing. In this case we *know* that we do not generate LSB exit codes, as it's basically PID 1 itself that exited there. --- src/core/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/main.c b/src/core/main.c index 30d9c43fbb..0908993c4a 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -203,7 +203,7 @@ noreturn static void crash(int sig) { pid, sigchld_code_to_string(status.si_code), status.si_status, strna(status.si_code == CLD_EXITED - ? exit_status_to_string(status.si_status, EXIT_STATUS_FULL) + ? exit_status_to_string(status.si_status, EXIT_STATUS_MINIMAL) : signal_to_string(status.si_status))); else log_emergency("Caught <%s>, dumped core as pid "PID_FMT".", signal_to_string(sig), pid); -- cgit v1.2.3-54-g00ecf From 1f0958f640b87175cd547c1e69084cfe54a22e9d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Oct 2016 22:07:30 +0200 Subject: core: when determining whether a process exit status is clean, consider whether it is a command or a daemon SIGTERM should be considered a clean exit code for daemons (i.e. long-running processes, as a daemon without SIGTERM handler may be shut down without issues via SIGTERM still) while it should not be considered a clean exit code for commands (i.e. short-running processes). Let's add two different clean checking modes for this, and use the right one at the appropriate places. Fixes: #4275 --- src/basic/exit-status.c | 8 ++++---- src/basic/exit-status.h | 7 ++++++- src/core/busname.c | 2 +- src/core/mount.c | 2 +- src/core/service.c | 2 +- src/core/socket.c | 2 +- src/core/swap.c | 2 +- src/remount-fs/remount-fs.c | 2 +- src/systemctl/systemctl.c | 2 +- src/tty-ask-password-agent/tty-ask-password-agent.c | 2 +- 10 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c index 96d4619da6..59557f8afe 100644 --- a/src/basic/exit-status.c +++ b/src/basic/exit-status.c @@ -177,17 +177,17 @@ const char* exit_status_to_string(int status, ExitStatusLevel level) { return NULL; } -bool is_clean_exit(int code, int status, ExitStatusSet *success_status) { +bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status) { if (code == CLD_EXITED) return status == 0 || (success_status && set_contains(success_status->status, INT_TO_PTR(status))); - /* If a daemon does not implement handlers for some of the - * signals that's not considered an unclean shutdown */ + /* If a daemon does not implement handlers for some of the signals that's not considered an unclean shutdown */ if (code == CLD_KILLED) - return IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE) || + return + (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) || (success_status && set_contains(success_status->signal, INT_TO_PTR(status))); diff --git a/src/basic/exit-status.h b/src/basic/exit-status.h index b3baa50cf4..0cfdfd7891 100644 --- a/src/basic/exit-status.h +++ b/src/basic/exit-status.h @@ -98,7 +98,12 @@ typedef struct ExitStatusSet { const char* exit_status_to_string(int status, ExitStatusLevel level) _const_; -bool is_clean_exit(int code, int status, ExitStatusSet *success_status); +typedef enum ExitClean { + EXIT_CLEAN_DAEMON, + EXIT_CLEAN_COMMAND, +} ExitClean; + +bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status); void exit_status_set_free(ExitStatusSet *x); bool exit_status_set_is_empty(ExitStatusSet *x); diff --git a/src/core/busname.c b/src/core/busname.c index 7952cd31aa..a69e3831f6 100644 --- a/src/core/busname.c +++ b/src/core/busname.c @@ -868,7 +868,7 @@ static void busname_sigchld_event(Unit *u, pid_t pid, int code, int status) { n->control_pid = 0; - if (is_clean_exit(code, status, NULL)) + if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL)) f = BUSNAME_SUCCESS; else if (code == CLD_EXITED) f = BUSNAME_FAILURE_EXIT_CODE; diff --git a/src/core/mount.c b/src/core/mount.c index 04025b83b9..ed542776ac 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1159,7 +1159,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { m->control_pid = 0; - if (is_clean_exit(code, status, NULL)) + if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL)) f = MOUNT_SUCCESS; else if (code == CLD_EXITED) f = MOUNT_FAILURE_EXIT_CODE; diff --git a/src/core/service.c b/src/core/service.c index fc1d353356..98edc437a2 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2600,7 +2600,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { assert(s); assert(pid >= 0); - if (is_clean_exit(code, status, &s->success_status)) + if (is_clean_exit(code, status, s->type == SERVICE_ONESHOT ? EXIT_CLEAN_COMMAND : EXIT_CLEAN_DAEMON, &s->success_status)) f = SERVICE_SUCCESS; else if (code == CLD_EXITED) f = SERVICE_FAILURE_EXIT_CODE; diff --git a/src/core/socket.c b/src/core/socket.c index b9032fa5c9..1b4a1b3dc3 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2743,7 +2743,7 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) { s->control_pid = 0; - if (is_clean_exit(code, status, NULL)) + if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL)) f = SOCKET_SUCCESS; else if (code == CLD_EXITED) f = SOCKET_FAILURE_EXIT_CODE; diff --git a/src/core/swap.c b/src/core/swap.c index fb222b6858..fee9e7b0e6 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -988,7 +988,7 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) { s->control_pid = 0; - if (is_clean_exit(code, status, NULL)) + if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL)) f = SWAP_SUCCESS; else if (code == CLD_EXITED) f = SWAP_FAILURE_EXIT_CODE; diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c index 6468d1eecd..c3bdcaf1da 100644 --- a/src/remount-fs/remount-fs.c +++ b/src/remount-fs/remount-fs.c @@ -137,7 +137,7 @@ int main(int argc, char *argv[]) { s = hashmap_remove(pids, PID_TO_PTR(si.si_pid)); if (s) { - if (!is_clean_exit(si.si_code, si.si_status, NULL)) { + if (!is_clean_exit(si.si_code, si.si_status, EXIT_CLEAN_COMMAND, NULL)) { if (si.si_code == CLD_EXITED) log_error(MOUNT_PATH " for %s exited with exit status %i.", s, si.si_status); else diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 9c6a475a39..18a8a4f248 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3936,7 +3936,7 @@ static void print_status_info( argv = strv_join(p->argv, " "); printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv)); - good = is_clean_exit(p->code, p->status, NULL); + good = is_clean_exit(p->code, p->status, EXIT_CLEAN_DAEMON, NULL); if (!good) { on = ansi_highlight_red(); off = ansi_normal(); diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 8851af449d..b45490be1a 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -827,7 +827,7 @@ static int ask_on_consoles(int argc, char *argv[]) { break; } - if (!is_clean_exit(status.si_code, status.si_status, NULL)) + if (!is_clean_exit(status.si_code, status.si_status, EXIT_CLEAN_DAEMON, NULL)) log_error("Password agent failed with: %d", status.si_status); terminate_agents(pids); -- cgit v1.2.3-54-g00ecf From f2aed3070d2c3bc6f380b711b1bdcebbda1bd1e8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Oct 2016 22:28:38 +0200 Subject: core: make use of IN_SET() in various places in mount.c --- src/core/mount.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/core/mount.c b/src/core/mount.c index ed542776ac..26c33b94ea 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -830,7 +830,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) { fail: log_unit_warning_errno(UNIT(m), r, "Failed to kill processes: %m"); - if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL) + if (IN_SET(state, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL)) mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES); else mount_enter_dead(m, MOUNT_FAILURE_RESOURCES); @@ -986,18 +986,19 @@ static int mount_start(Unit *u) { /* We cannot fulfill this request right now, try again later * please! */ - if (m->state == MOUNT_UNMOUNTING || - m->state == MOUNT_UNMOUNTING_SIGTERM || - m->state == MOUNT_UNMOUNTING_SIGKILL || - m->state == MOUNT_MOUNTING_SIGTERM || - m->state == MOUNT_MOUNTING_SIGKILL) + if (IN_SET(m->state, + MOUNT_UNMOUNTING, + MOUNT_UNMOUNTING_SIGTERM, + MOUNT_UNMOUNTING_SIGKILL, + MOUNT_MOUNTING_SIGTERM, + MOUNT_MOUNTING_SIGKILL)) return -EAGAIN; /* Already on it! */ if (m->state == MOUNT_MOUNTING) return 0; - assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED); + assert(IN_SET(m->state, MOUNT_DEAD, MOUNT_FAILED)); r = unit_start_limit_test(u); if (r < 0) { @@ -1019,19 +1020,21 @@ static int mount_stop(Unit *u) { assert(m); /* Already on it */ - if (m->state == MOUNT_UNMOUNTING || - m->state == MOUNT_UNMOUNTING_SIGKILL || - m->state == MOUNT_UNMOUNTING_SIGTERM || - m->state == MOUNT_MOUNTING_SIGTERM || - m->state == MOUNT_MOUNTING_SIGKILL) + if (IN_SET(m->state, + MOUNT_UNMOUNTING, + MOUNT_UNMOUNTING_SIGKILL, + MOUNT_UNMOUNTING_SIGTERM, + MOUNT_MOUNTING_SIGTERM, + MOUNT_MOUNTING_SIGKILL)) return 0; - assert(m->state == MOUNT_MOUNTING || - m->state == MOUNT_MOUNTING_DONE || - m->state == MOUNT_MOUNTED || - m->state == MOUNT_REMOUNTING || - m->state == MOUNT_REMOUNTING_SIGTERM || - m->state == MOUNT_REMOUNTING_SIGKILL); + assert(IN_SET(m->state, + MOUNT_MOUNTING, + MOUNT_MOUNTING_DONE, + MOUNT_MOUNTED, + MOUNT_REMOUNTING, + MOUNT_REMOUNTING_SIGTERM, + MOUNT_REMOUNTING_SIGKILL)); mount_enter_unmounting(m); return 1; -- cgit v1.2.3-54-g00ecf From 052364d41f432c5a2357122a41d5f60cabb63a5e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 10 Oct 2016 22:28:55 +0200 Subject: core: simplify if branches a bit We do the same thing in two branches, let's merge them. Let's also add an explanatory comment, while we are at it. --- src/core/mount.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/mount.c b/src/core/mount.c index 26c33b94ea..f5e67b1d78 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1200,9 +1200,10 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { case MOUNT_MOUNTING_SIGKILL: case MOUNT_MOUNTING_SIGTERM: - if (f == MOUNT_SUCCESS) - mount_enter_mounted(m, f); - else if (m->from_proc_self_mountinfo) + if (f == MOUNT_SUCCESS || m->from_proc_self_mountinfo) + /* If /bin/mount returned success, or if we see the mount point in /proc/self/mountinfo we are + * happy. If we see the first condition first, we should see the the second condition + * immediately after – or /bin/mount lies to us and is broken. */ mount_enter_mounted(m, f); else mount_enter_dead(m, f); -- cgit v1.2.3-54-g00ecf From 01b0669e9ac772d8eeed447ee469b7d4131c3ced Mon Sep 17 00:00:00 2001 From: "Thomas H. P. Andersen" Date: Tue, 11 Oct 2016 02:12:40 +0200 Subject: resolved: initialize variable (#4338) r was not initialized and would be used if "tcp" was the only option used for the stub. We should initialize it to 0 to indicate that no error happened in the udp case. --- src/resolve/resolved-dns-stub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index b1c570cee6..e76de6c06a 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -498,7 +498,7 @@ static int manager_dns_stub_tcp_fd(Manager *m) { int manager_dns_stub_start(Manager *m) { const char *t = "UDP"; - int r; + int r = 0; assert(m); -- cgit v1.2.3-54-g00ecf From 19f0cf65c945884d19c91667a683dac084f0a944 Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Tue, 11 Oct 2016 02:27:09 +0200 Subject: man: update unit type count (#4339) It seems that this count was not updated when snapshot units were removed in #1841. --- man/systemd.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemd.xml b/man/systemd.xml index e30333e209..7f24a874ed 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -272,7 +272,7 @@ Concepts systemd provides a dependency system between various - entities called "units" of 12 different types. Units encapsulate + entities called "units" of 11 different types. Units encapsulate various objects that are relevant for system boot-up and maintenance. The majority of units are configured in unit configuration files, whose syntax and basic set of options is -- cgit v1.2.3-54-g00ecf From 1f1a5e8b403332eb0788ace2fa44f07c588a2464 Mon Sep 17 00:00:00 2001 From: Stefan Schweter Date: Tue, 11 Oct 2016 09:08:04 +0200 Subject: udevadm: use parse_sec instead of atoi for timeout option (#4331) log_error method is used instead of fprintf --- src/udev/udevadm-control.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/udev/udevadm-control.c b/src/udev/udevadm-control.c index 989decbe95..6f8e96a123 100644 --- a/src/udev/udevadm-control.c +++ b/src/udev/udevadm-control.c @@ -20,6 +20,7 @@ #include #include +#include "time-util.h" #include "udev-util.h" #include "udev.h" @@ -60,7 +61,7 @@ static int adm_control(struct udev *udev, int argc, char *argv[]) { }; if (getuid() != 0) { - fprintf(stderr, "root privileges required\n"); + log_error("root privileges required"); return 1; } @@ -81,7 +82,7 @@ static int adm_control(struct udev *udev, int argc, char *argv[]) { i = util_log_priority(optarg); if (i < 0) { - fprintf(stderr, "invalid number '%s'\n", optarg); + log_error("invalid number '%s'", optarg); return rc; } if (udev_ctrl_send_set_log_level(uctrl, util_log_priority(optarg), timeout) < 0) @@ -110,7 +111,7 @@ static int adm_control(struct udev *udev, int argc, char *argv[]) { break; case 'p': if (strchr(optarg, '=') == NULL) { - fprintf(stderr, "expect = instead of '%s'\n", optarg); + log_error("expect = instead of '%s'", optarg); return rc; } if (udev_ctrl_send_set_env(uctrl, optarg, timeout) < 0) @@ -124,7 +125,7 @@ static int adm_control(struct udev *udev, int argc, char *argv[]) { i = strtoul(optarg, &endp, 0); if (endp[0] != '\0' || i < 1) { - fprintf(stderr, "invalid number '%s'\n", optarg); + log_error("invalid number '%s'", optarg); return rc; } if (udev_ctrl_send_set_children_max(uctrl, i, timeout) < 0) @@ -134,13 +135,21 @@ static int adm_control(struct udev *udev, int argc, char *argv[]) { break; } case 't': { + usec_t s; int seconds; + int r; - seconds = atoi(optarg); - if (seconds >= 0) + r = parse_sec(optarg, &s); + if (r < 0) + return log_error_errno(r, "Failed to parse timeout value '%s'.", optarg); + + if (((s + USEC_PER_SEC - 1) / USEC_PER_SEC) > INT_MAX) + log_error("Timeout value is out of range."); + else { + seconds = s != USEC_INFINITY ? (int) ((s + USEC_PER_SEC - 1) / USEC_PER_SEC) : INT_MAX; timeout = seconds; - else - fprintf(stderr, "invalid timeout value\n"); + rc = 0; + } break; } case 'h': @@ -150,9 +159,9 @@ static int adm_control(struct udev *udev, int argc, char *argv[]) { } if (optind < argc) - fprintf(stderr, "Extraneous argument: %s\n", argv[optind]); + log_error("Extraneous argument: %s", argv[optind]); else if (optind == 1) - fprintf(stderr, "Option missing\n"); + log_error("Option missing"); return rc; } -- cgit v1.2.3-54-g00ecf From a8cb1dc3e0fa81affd01c8ed3df35e4c4520a24e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 11 Oct 2016 21:36:14 +0900 Subject: units: add Wants=initrd-cleanup.service to initrd-switch-root.target (#4345) `systemctl isolate initrd-switch-root.target` called by initrd-cleanup.service kills initrd-cleanup.service itself. Then, initrd-cleanup.service failed and system goes to emergency shell. To prevent this problem, this commit adds `Wants=initrd-cleanup.service` to initrd-switch-root.target. fixes: #4343. --- units/initrd-switch-root.target | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/units/initrd-switch-root.target b/units/initrd-switch-root.target index f34768790b..934d82f667 100644 --- a/units/initrd-switch-root.target +++ b/units/initrd-switch-root.target @@ -12,5 +12,5 @@ DefaultDependencies=no Requires=initrd-switch-root.service Before=initrd-switch-root.service AllowIsolate=yes -Wants=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target systemd-journald.service +Wants=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target systemd-journald.service initrd-cleanup.service After=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target emergency.service emergency.target -- cgit v1.2.3-54-g00ecf From 6e16066e8ecd92e69b8f1e4bad728ee5b4cb7d34 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Oct 2016 17:45:49 +0200 Subject: man: expand the documentation of $SYSTEMD_PAGER and related environment variables Document the default pagers used, as well as $SYSTEMD_LESSCHARSET. Fixes: #4143 --- man/less-variables.xml | 53 ++++++++++++++++++++++++++++---------------------- man/systemctl.xml | 1 + 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/man/less-variables.xml b/man/less-variables.xml index 0fb4d7fbcf..1f34cbc1bf 100644 --- a/man/less-variables.xml +++ b/man/less-variables.xml @@ -3,27 +3,34 @@ "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> - Environment - - - - $SYSTEMD_PAGER - - Pager to use when - is not given; - overrides $PAGER. Setting - this to an empty string or the value - cat is equivalent to passing - . - - - - $SYSTEMD_LESS - - Override the default - options passed to - less - (FRSXMK). - - + Environment + + + + $SYSTEMD_PAGER + + Pager to use when is not given; overrides + $PAGER. If neither $SYSTEMD_PAGER nor $PAGER are set, a + set of well-known pager implementations are tried in turn, including + less1 and + more1, until one is found. If + no pager implementation is discovered no pager is invoked. Setting this environment variable to an empty string + or the value cat is equivalent to passing . + + + + $SYSTEMD_LESS + + Override the options passed to less (by default + FRSXMK). + + + + $SYSTEMD_LESSCHARSET + + Override the charset passed to less (by default utf-8, if + the invoking terminal is determined to be UTF-8 compatible). + + + diff --git a/man/systemctl.xml b/man/systemctl.xml index e738b5aecd..cd1f3f976f 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1817,6 +1817,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service + -- cgit v1.2.3-54-g00ecf From 57c9e047819c839b6a208e99bf4d9f09d8c83c1e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Oct 2016 17:46:59 +0200 Subject: pager: tiny beautification --- src/shared/pager.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shared/pager.c b/src/shared/pager.c index a2524d4420..09672a4abf 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -36,6 +36,7 @@ #include "process-util.h" #include "signal-util.h" #include "string-util.h" +#include "strv.h" #include "terminal-util.h" static pid_t pager_pid = 0; @@ -71,7 +72,7 @@ int pager_open(bool no_pager, bool jump_to_end) { pager = getenv("PAGER"); /* If the pager is explicitly turned off, honour it */ - if (pager && (pager[0] == 0 || streq(pager, "cat"))) + if (pager && STR_IN_SET(pager, "", "cat")) return 0; /* Determine and cache number of columns before we spawn the -- cgit v1.2.3-54-g00ecf From 2cdbbc9a341eba4655ca03d13844fdc77753ce53 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Oct 2016 17:55:04 +0200 Subject: man: avoid using the term "loaded" for units currently in memory, since we also have a unit state of that name Fixes: #3971 --- man/systemctl.xml | 34 +++++++++++++++------------------- src/systemctl/systemctl.c | 14 ++++++++------ 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index cd1f3f976f..3b883ea754 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -655,10 +655,10 @@ list-units PATTERN... - List units that systemd has loaded. This includes units that are either referenced - directly or through a dependency, units that are pinned by applications programmatically, or units that - were active in the past and have failed. By default only units which are active, have pending jobs, or have - failed are shown; this can be changed with option . If one or more + List units that systemd currently has in memory. This includes units that are + either referenced directly or through a dependency, units that are pinned by applications programmatically, + or units that were active in the past and have failed. By default only units which are active, have pending + jobs, or have failed are shown; this can be changed with option . If one or more PATTERNs are specified, only units matching one of them are shown. The units that are shown are additionally filtered by and if those options are specified. @@ -671,9 +671,8 @@ list-sockets PATTERN... - List socket units ordered by listening address. - If one or more PATTERNs are - specified, only socket units matching one of them are + List socket units currently in memory, ordered by listening address. If one or more + PATTERNs are specified, only socket units matching one of them are shown. Produces output similar to LISTEN UNIT ACTIVATES @@ -687,8 +686,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service is not suitable for programmatic consumption. - See also the options , - , and . + Also see , , and . @@ -696,13 +694,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service list-timers PATTERN... - List timer units ordered by the time they elapse - next. If one or more PATTERNs - are specified, only units matching one of them are shown. + List timer units currently in memory, ordered by the time they elapse next. If one or more + PATTERNs are specified, only units matching one of them are shown. - See also the options and - . + Also see and . @@ -713,8 +709,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service Start (activate) one or more units specified on the command line. - Note that glob patterns operate on the set of primary names of currently loaded units. Units which - are not active and are not in a failed state usually are not loaded, and will not be matched by any + Note that glob patterns operate on the set of primary names of units currently in memory. Units which + are not active and are not in a failed state usually are not in memory, and will not be matched by any pattern. In addition, in case of instantiated units, systemd is often unaware of the instance name until the instance has been started. Therefore, using glob patterns with start has limited usefulness. Also, secondary alias names of units are not considered. @@ -1759,7 +1755,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service are equivalent to: # systemctl status dev-sda.device # systemctl status home.mount - In the second case, shell-style globs will be matched against the primary names of all currently loaded units; + In the second case, shell-style globs will be matched against the primary names of all units currently in memory; literal unit names, with or without a suffix, will be treated as in the first case. This means that literal unit names always refer to exactly one unit, but globs may match zero units and this is not considered an error. @@ -1771,11 +1767,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service [] may be used. See glob7 for more details. The patterns are matched against the primary names of - currently loaded units, and patterns which do not match anything + units currently in memory, and patterns which do not match anything are silently skipped. For example: # systemctl stop sshd@*.service will stop all sshd@.service instances. Note that alias names of units, and units that aren't - loaded are not considered for glob expansion. + in memory are not considered for glob expansion. For unit file commands, the specified NAME should be the name of the unit file diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 18a8a4f248..7ed60dbe87 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -6721,9 +6721,9 @@ static void systemctl_help(void) { " -t --type=TYPE List units of a particular type\n" " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n" " -p --property=NAME Show only properties by this name\n" - " -a --all Show all loaded units/properties, including dead/empty\n" - " ones. To list all units installed on the system, use\n" - " the 'list-unit-files' command instead.\n" + " -a --all Show all properties/all units currently in memory,\n" + " including dead/empty ones. To list all units installed on\n" + " the system, use the 'list-unit-files' command instead.\n" " -l --full Don't ellipsize unit names on output\n" " -r --recursive Show unit list of host and local containers\n" " --reverse Show reverse dependencies with 'list-dependencies'\n" @@ -6758,9 +6758,11 @@ static void systemctl_help(void) { " --firmware-setup Tell the firmware to show the setup menu on next boot\n" " --plain Print unit dependencies as a list instead of a tree\n\n" "Unit Commands:\n" - " list-units [PATTERN...] List loaded units\n" - " list-sockets [PATTERN...] List loaded sockets ordered by address\n" - " list-timers [PATTERN...] List loaded timers ordered by next elapse\n" + " list-units [PATTERN...] List units currently in memory\n" + " list-sockets [PATTERN...] List socket units currently in memory, ordered\n" + " by address\n" + " list-timers [PATTERN...] List timer units currently in memory, ordered\n" + " by next elapse\n" " start NAME... Start (activate) one or more units\n" " stop NAME... Stop (deactivate) one or more units\n" " reload NAME... Reload one or more units\n" -- cgit v1.2.3-54-g00ecf From 6dcda09cbfb698c6b50fcab2ef52a540766f25bf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Oct 2016 18:01:54 +0200 Subject: man: document that Type=idle is subject to a 5s time-out Fixes: #4116 --- man/systemd.service.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/man/systemd.service.xml b/man/systemd.service.xml index b58e887662..8203f2d52e 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -209,11 +209,11 @@ if used in combination with PrivateNetwork=. - Behavior of is very similar to - ; however, actual execution of the - service binary is delayed until all jobs are dispatched. This - may be used to avoid interleaving of output of shell services - with the status output on the console. + Behavior of is very similar to ; however, actual execution + of the service binary is delayed until all active jobs are dispatched. This may be used to avoid interleaving + of output of shell services with the status output on the console. Note that this type is useful only to + improve console output, it is not useful as a general unit ordering tool, and the effect of this service type + is subject to a 5s time-out, after which the service binary is invoked anyway. -- cgit v1.2.3-54-g00ecf From f4c9356d133a7453dc9ed4e499a3edeb62c90fa9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Oct 2016 18:42:22 +0200 Subject: man: beef up documentation on per-unit resource limits a bit Let's clarify that for user services some OS-defined limits bound the settings in the unit files. Fixes: #4232 --- man/systemd.exec.xml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 5e6787338d..4d5e5b1f32 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -703,8 +703,19 @@ MemoryLimit= is a more powerful (and working) replacement for LimitRSS=. + For system units these resource limits may be chosen freely. For user units however (i.e. units run by a + per-user instance of + systemd1), these limits are + bound by (possibly more restrictive) per-user limits enforced by the OS. + + Resource limits not configured explicitly for a unit default to the value configured in the various + DefaultLimitCPU=, DefaultLimitFSIZE=, … options available in + systemd-system.conf5, and – + if not configured there – the kernel or per-user defaults, as defined by the OS (the latter only for user + services, see above). + - Limit directives and their equivalent with ulimit + Resource limit directives, their equivalent <command>ulimit</command> shell commands and the unit used @@ -713,7 +724,7 @@ Directive - ulimit equivalent + ulimit equivalent Unit -- cgit v1.2.3-54-g00ecf From f68c9dd5c6d0862cbcc89d5339715128a3b5d4a9 Mon Sep 17 00:00:00 2001 From: "Thomas H. P. Andersen" Date: Tue, 11 Oct 2016 19:51:03 +0200 Subject: resolve: remove unsed counter (#4349) It was introduced but never used in 45ec7efb. --- src/resolve/resolve-tool.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/resolve/resolve-tool.c b/src/resolve/resolve-tool.c index 8aa79049b6..9d4d04220c 100644 --- a/src/resolve/resolve-tool.c +++ b/src/resolve/resolve-tool.c @@ -780,7 +780,6 @@ static int resolve_service(sd_bus *bus, const char *name, const char *type, cons if (r < 0) return bus_log_parse_error(r); - c = 0; while ((r = sd_bus_message_read_array(reply, 'y', (const void**) &p, &sz)) > 0) { _cleanup_free_ char *escaped = NULL; @@ -789,7 +788,6 @@ static int resolve_service(sd_bus *bus, const char *name, const char *type, cons return log_oom(); printf("%*s%s\n", (int) indent, "", escaped); - c++; } if (r < 0) return bus_log_parse_error(r); -- cgit v1.2.3-54-g00ecf From e0d2adfde677d91b57dd63f6a3f00f4b86be9a64 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Oct 2016 20:07:22 +0200 Subject: core: chown() any TTY used for stdin, not just when StandardInput=tty is used (#4347) If stdin is supplied as an fd for transient units (using the StandardInputFileDescriptor pseudo-property for transient units), then we should also fix up the TTY ownership, not just when we opened the TTY ourselves. This simply drops the explicit is_terminal_input()-based check. Note that chown_terminal() internally does a much more appropriate isatty()-based check anyway, hence we can drop this without replacement. Fixes: #4260 --- src/core/execute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/execute.c b/src/core/execute.c index 7079aeed6e..0c983f4953 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2350,7 +2350,7 @@ static int exec_child( USER_PROCESS, username ? "root" : context->user); - if (context->user && is_terminal_input(context->std_input)) { + if (context->user) { r = chown_terminal(STDIN_FILENO, uid); if (r < 0) { *exit_status = EXIT_STDIN; -- cgit v1.2.3-54-g00ecf From ada5412039b7c3e24654bc33550471e0a0869631 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 10 Oct 2016 16:12:50 -0400 Subject: nspawn: simplify arg_us_cgns passing We would check the condition cg_ns_supported() twice. No functional change. --- src/nspawn/nspawn-mount.c | 2 +- src/nspawn/nspawn.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 25d38aa742..0be06c8c09 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -931,7 +931,7 @@ int mount_cgroups( if (unified_requested >= CGROUP_UNIFIED_ALL) return mount_unified_cgroups(dest); - else if (use_cgns && cg_ns_supported()) + else if (use_cgns) return mount_legacy_cgns_supported(unified_requested, userns, uid_shift, uid_range, selinux_apifs_context); return mount_legacy_cgns_unsupported(dest, unified_requested, userns, uid_shift, uid_range, selinux_apifs_context); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index a173d171e1..d62b8c6b82 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2724,7 +2724,7 @@ static int inner_child( arg_uid_shift, arg_uid_range, arg_selinux_apifs_context, - arg_use_cgns); + true); if (r < 0) return r; } else { @@ -3136,7 +3136,7 @@ static int outer_child( arg_uid_shift, arg_uid_range, arg_selinux_apifs_context, - arg_use_cgns); + false); if (r < 0) return r; } -- cgit v1.2.3-54-g00ecf From add554f4e16f3ece6bca1448a5ef4f859984fd8d Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 11 Oct 2016 14:41:30 -0400 Subject: nspawn: small cleanups in get_controllers() - check for oom after strdup - no need to truncate the line since we're only extracting one field anyway - use STR_IN_SET --- src/nspawn/nspawn-mount.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 0be06c8c09..02dc94cfe1 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -637,8 +637,6 @@ static int get_controllers(Set *subsystems) { int r; char *e, *l, *p; - truncate_nl(line); - l = strchr(line, ':'); if (!l) continue; @@ -650,10 +648,13 @@ static int get_controllers(Set *subsystems) { *e = 0; - if (streq(l, "") || streq(l, "name=systemd")) + if (STR_IN_SET(l, "", "name=systemd")) continue; p = strdup(l); + if (!p) + return -ENOMEM; + r = set_consume(subsystems, p); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 60e76d4897d48d2187f8bf129147aaf4eb81a59f Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 10 Oct 2016 15:55:20 -0400 Subject: nspawn,mount-util: add [u]mount_verbose and use it in nspawn This makes it easier to debug failed nspawn invocations: Mounting sysfs on /var/lib/machines/fedora-rawhide/sys (MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV "")... Mounting tmpfs on /var/lib/machines/fedora-rawhide/dev (MS_NOSUID|MS_STRICTATIME "mode=755,uid=1450901504,gid=1450901504")... Mounting tmpfs on /var/lib/machines/fedora-rawhide/dev/shm (MS_NOSUID|MS_NODEV|MS_STRICTATIME "mode=1777,uid=1450901504,gid=1450901504")... Mounting tmpfs on /var/lib/machines/fedora-rawhide/run (MS_NOSUID|MS_NODEV|MS_STRICTATIME "mode=755,uid=1450901504,gid=1450901504")... Bind-mounting /sys/fs/selinux on /var/lib/machines/fedora-rawhide/sys/fs/selinux (MS_BIND "")... Remounting /var/lib/machines/fedora-rawhide/sys/fs/selinux (MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_BIND|MS_REMOUNT "")... Mounting proc on /proc (MS_NOSUID|MS_NOEXEC|MS_NODEV "")... Bind-mounting /proc/sys on /proc/sys (MS_BIND "")... Remounting /proc/sys (MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_BIND|MS_REMOUNT "")... Bind-mounting /proc/sysrq-trigger on /proc/sysrq-trigger (MS_BIND "")... Remounting /proc/sysrq-trigger (MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_BIND|MS_REMOUNT "")... Mounting tmpfs on /tmp (MS_STRICTATIME "mode=1777,uid=0,gid=0")... Mounting tmpfs on /sys/fs/cgroup (MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME "mode=755,uid=0,gid=0")... Mounting cgroup on /sys/fs/cgroup/systemd (MS_NOSUID|MS_NOEXEC|MS_NODEV "none,name=systemd,xattr")... Failed to mount cgroup on /sys/fs/cgroup/systemd (MS_NOSUID|MS_NOEXEC|MS_NODEV "none,name=systemd,xattr"): No such file or directory --- src/basic/mount-util.c | 105 +++++++++++++++++++++++++++++ src/basic/mount-util.h | 9 +++ src/nspawn/nspawn-cgroup.c | 13 ++-- src/nspawn/nspawn-mount.c | 162 ++++++++++++++++++++++----------------------- src/nspawn/nspawn.c | 78 +++++++++++----------- 5 files changed, 236 insertions(+), 131 deletions(-) diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c index b9affb4e70..0ef00676ef 100644 --- a/src/basic/mount-util.c +++ b/src/basic/mount-util.c @@ -581,3 +581,108 @@ const char* mode_to_inaccessible_node(mode_t mode) { } return NULL; } + +#define FLAG(name) (flags & name ? STRINGIFY(name) "|" : "") +static char* mount_flags_to_string(long unsigned flags) { + char *x; + _cleanup_free_ char *y = NULL; + long unsigned overflow; + + overflow = flags & ~(MS_RDONLY | + MS_NOSUID | + MS_NODEV | + MS_NOEXEC | + MS_SYNCHRONOUS | + MS_REMOUNT | + MS_MANDLOCK | + MS_DIRSYNC | + MS_NOATIME | + MS_NODIRATIME | + MS_BIND | + MS_MOVE | + MS_REC | + MS_SILENT | + MS_POSIXACL | + MS_UNBINDABLE | + MS_PRIVATE | + MS_SLAVE | + MS_SHARED | + MS_RELATIME | + MS_KERNMOUNT | + MS_I_VERSION | + MS_STRICTATIME | + MS_LAZYTIME); + + if (flags == 0 || overflow != 0) + if (asprintf(&y, "%lx", overflow) < 0) + return NULL; + + x = strjoin(FLAG(MS_RDONLY), + FLAG(MS_NOSUID), + FLAG(MS_NODEV), + FLAG(MS_NOEXEC), + FLAG(MS_SYNCHRONOUS), + FLAG(MS_REMOUNT), + FLAG(MS_MANDLOCK), + FLAG(MS_DIRSYNC), + FLAG(MS_NOATIME), + FLAG(MS_NODIRATIME), + FLAG(MS_BIND), + FLAG(MS_MOVE), + FLAG(MS_REC), + FLAG(MS_SILENT), + FLAG(MS_POSIXACL), + FLAG(MS_UNBINDABLE), + FLAG(MS_PRIVATE), + FLAG(MS_SLAVE), + FLAG(MS_SHARED), + FLAG(MS_RELATIME), + FLAG(MS_KERNMOUNT), + FLAG(MS_I_VERSION), + FLAG(MS_STRICTATIME), + FLAG(MS_LAZYTIME), + y, NULL); + if (!x) + return NULL; + if (!y) + x[strlen(x) - 1] = '\0'; /* truncate the last | */ + return x; +} + +int mount_verbose( + int error_log_level, + const char *what, + const char *where, + const char *type, + unsigned long flags, + const char *options) { + + _cleanup_free_ char *fl = NULL; + + fl = mount_flags_to_string(flags); + + if ((flags & MS_REMOUNT) && !what && !type) + log_debug("Remounting %s (%s \"%s\")...", + where, strnull(fl), strempty(options)); + else if (!what && !type) + log_debug("Mounting %s (%s \"%s\")...", + where, strnull(fl), strempty(options)); + else if ((flags & MS_BIND) && !type) + log_debug("Bind-mounting %s on %s (%s \"%s\")...", + what, where, strnull(fl), strempty(options)); + else + log_debug("Mounting %s on %s (%s \"%s\")...", + strna(type), where, strnull(fl), strempty(options)); + if (mount(what, where, type, flags, options) < 0) + return log_full_errno(error_log_level, errno, + "Failed to mount %s on %s (%s \"%s\"): %m", + strna(type), where, strnull(fl), strempty(options)); + return 0; +} + +int umount_verbose(const char *what) { + log_debug("Umounting %s...", what); + if (umount(what) < 0) + return log_error_errno(errno, "Failed to unmount %s: %m", what); + return 0; +} diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h index 74730de663..4f305df19f 100644 --- a/src/basic/mount-util.h +++ b/src/basic/mount-util.h @@ -52,3 +52,12 @@ union file_handle_union { const char* mode_to_inaccessible_node(mode_t mode); #define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ } + +int mount_verbose( + int error_log_level, + const char *what, + const char *where, + const char *type, + unsigned long flags, + const char *options); +int umount_verbose(const char *where); diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index aa0da04955..6793df1286 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -23,6 +23,7 @@ #include "fd-util.h" #include "fileio.h" #include "mkdir.h" +#include "mount-util.h" #include "nspawn-cgroup.h" #include "string-util.h" #include "strv.h" @@ -90,13 +91,13 @@ int sync_cgroup(pid_t pid, CGroupUnified unified_requested) { return log_error_errno(errno, "Failed to generate temporary mount point for unified hierarchy: %m"); if (unified) - r = mount("cgroup", tree, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr"); + r = mount_verbose(LOG_ERR, "cgroup", tree, "cgroup", + MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr"); else - r = mount("cgroup", tree, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); - if (r < 0) { - r = log_error_errno(errno, "Failed to mount unified hierarchy: %m"); + r = mount_verbose(LOG_ERR, "cgroup", tree, "cgroup2", + MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); + if (r < 0) goto finish; - } undo_mount = true; @@ -110,7 +111,7 @@ int sync_cgroup(pid_t pid, CGroupUnified unified_requested) { finish: if (undo_mount) - (void) umount(tree); + (void) umount_verbose(tree); (void) rmdir(tree); return r; diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 02dc94cfe1..da5bc68a89 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -250,8 +250,10 @@ int mount_sysfs(const char *dest) { (void) mkdir(full, 0755); - if (mount("sysfs", full, "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0) - return log_error_errno(errno, "Failed to mount sysfs to %s: %m", full); + r = mount_verbose(LOG_ERR, "sysfs", full, "sysfs", + MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); + if (r < 0) + return r; FOREACH_STRING(x, "block", "bus", "class", "dev", "devices", "kernel") { _cleanup_free_ char *from = NULL, *to = NULL; @@ -266,15 +268,19 @@ int mount_sysfs(const char *dest) { (void) mkdir(to, 0755); - if (mount(from, to, NULL, MS_BIND, NULL) < 0) - return log_error_errno(errno, "Failed to mount /sys/%s into place: %m", x); + r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL); + if (r < 0) + return r; - if (mount(NULL, to, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL) < 0) - return log_error_errno(errno, "Failed to mount /sys/%s read-only: %m", x); + r = mount_verbose(LOG_ERR, NULL, to, NULL, + MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL); + if (r < 0) + return r; } - if (umount(full) < 0) - return log_error_errno(errno, "Failed to unmount %s: %m", full); + r = umount_verbose(full); + if (r < 0) + return r; if (rmdir(full) < 0) return log_error_errno(errno, "Failed to remove %s: %m", full); @@ -290,10 +296,8 @@ int mount_sysfs(const char *dest) { (void) mkdir_p(x, 0755); } - if (mount(NULL, top, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL) < 0) - return log_error_errno(errno, "Failed to make %s read-only: %m", top); - - return 0; + return mount_verbose(LOG_ERR, NULL, top, NULL, + MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL); } int mount_all(const char *dest, @@ -375,17 +379,14 @@ int mount_all(const char *dest, o = options; } - if (mount(mount_table[k].what, - where, - mount_table[k].type, - mount_table[k].flags, - o) < 0) { - - if (mount_table[k].fatal) - return log_error_errno(errno, "mount(%s) failed: %m", where); - - log_warning_errno(errno, "mount(%s) failed, ignoring: %m", where); - } + r = mount_verbose(mount_table[k].fatal ? LOG_ERR : LOG_WARNING, + mount_table[k].what, + where, + mount_table[k].type, + mount_table[k].flags, + o); + if (r < 0 && mount_table[k].fatal) + return r; } return 0; @@ -470,12 +471,12 @@ static int mount_bind(const char *dest, CustomMount *m) { if (r < 0) return log_error_errno(r, "Failed to create mount point %s: %m", where); - } else { + } else return log_error_errno(errno, "Failed to stat %s: %m", where); - } - if (mount(m->source, where, NULL, mount_flags, mount_opts) < 0) - return log_error_errno(errno, "mount(%s) failed: %m", where); + r = mount_verbose(LOG_ERR, m->source, where, NULL, mount_flags, mount_opts); + if (r < 0) + return r; if (m->read_only) { r = bind_remount_recursive(where, true, NULL); @@ -510,10 +511,7 @@ static int mount_tmpfs( return log_oom(); options = r > 0 ? buf : m->options; - if (mount("tmpfs", where, "tmpfs", MS_NODEV|MS_STRICTATIME, options) < 0) - return log_error_errno(errno, "tmpfs mount to %s failed: %m", where); - - return 0; + return mount_verbose(LOG_ERR, "tmpfs", where, "tmpfs", MS_NODEV|MS_STRICTATIME, options); } static char *joined_and_escaped_lower_dirs(char * const *lower) { @@ -575,10 +573,7 @@ static int mount_overlay(const char *dest, CustomMount *m) { options = strjoina("lowerdir=", lower, ",upperdir=", escaped_source, ",workdir=", escaped_work_dir); } - if (mount("overlay", where, "overlay", m->read_only ? MS_RDONLY : 0, options) < 0) - return log_error_errno(errno, "overlay mount to %s failed: %m", where); - - return 0; + return mount_verbose(LOG_ERR, "overlay", where, "overlay", m->read_only ? MS_RDONLY : 0, options); } int mount_custom( @@ -665,7 +660,7 @@ static int get_controllers(Set *subsystems) { static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controller, const char *hierarchy, CGroupUnified unified_requested, bool read_only) { - char *to; + const char *to, *fstype, *opts; int r; to = strjoina(strempty(dest), "/sys/fs/cgroup/", hierarchy); @@ -681,22 +676,30 @@ static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controlle /* The superblock mount options of the mount point need to be * identical to the hosts', and hence writable... */ if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { - if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) - r = mount("cgroup", to, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); - else - r = mount("cgroup", to, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr"); - } else - r = mount("cgroup", to, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, controller); + if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) { + fstype = "cgroup2"; + opts = NULL; + } else { + fstype = "cgroup"; + opts = "none,name=systemd,xattr"; + } + } else { + fstype = "cgroup"; + opts = controller; + } + r = mount_verbose(LOG_ERR, "cgroup", to, fstype, MS_NOSUID|MS_NOEXEC|MS_NODEV, opts); if (r < 0) - return log_error_errno(errno, "Failed to mount to %s: %m", to); + return r; - /* ... hence let's only make the bind mount read-only, not the - * superblock. */ + /* ... hence let's only make the bind mount read-only, not the superblock. */ if (read_only) { - if (mount(NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL) < 0) - return log_error_errno(errno, "Failed to remount %s read-only: %m", to); + r = mount_verbose(LOG_ERR, NULL, to, NULL, + MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL); + if (r < 0) + return r; } + return 1; } @@ -728,8 +731,10 @@ static int mount_legacy_cgns_supported( if (r < 0) return log_oom(); - if (mount("tmpfs", cgroup_root, "tmpfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options) < 0) - return log_error_errno(errno, "Failed to mount /sys/fs/cgroup: %m"); + r = mount_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs", + MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options); + if (r < 0) + return r; } if (cg_all_unified() > 0) @@ -788,10 +793,9 @@ skip_controllers: if (r < 0) return r; - if (!userns) { - if (mount(NULL, cgroup_root, NULL, MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755") < 0) - return log_error_errno(errno, "Failed to remount %s read-only: %m", cgroup_root); - } + if (!userns) + return mount_verbose(LOG_ERR, NULL, cgroup_root, NULL, + MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); return 0; } @@ -820,8 +824,10 @@ static int mount_legacy_cgns_unsupported( if (r < 0) return log_oom(); - if (mount("tmpfs", cgroup_root, "tmpfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options) < 0) - return log_error_errno(errno, "Failed to mount /sys/fs/cgroup: %m"); + r = mount_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs", + MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options); + if (r < 0) + return r; } if (cg_all_unified() > 0) @@ -887,10 +893,8 @@ skip_controllers: if (r < 0) return r; - if (mount(NULL, cgroup_root, NULL, MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755") < 0) - return log_error_errno(errno, "Failed to remount %s read-only: %m", cgroup_root); - - return 0; + return mount_verbose(LOG_ERR, NULL, cgroup_root, NULL, + MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); } static int mount_unified_cgroups(const char *dest) { @@ -917,10 +921,7 @@ static int mount_unified_cgroups(const char *dest) { return -EINVAL; } - if (mount("cgroup", p, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0) - return log_error_errno(errno, "Failed to mount unified cgroup hierarchy to %s: %m", p); - - return 0; + return mount_verbose(LOG_ERR, "cgroup", p, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); } int mount_cgroups( @@ -965,14 +966,13 @@ int mount_systemd_cgroup_writable( } /* Make our own cgroup a (writable) bind mount */ - if (mount(systemd_own, systemd_own, NULL, MS_BIND, NULL) < 0) - return log_error_errno(errno, "Failed to turn %s into a bind mount: %m", own_cgroup_path); + r = mount_verbose(LOG_ERR, systemd_own, systemd_own, NULL, MS_BIND, NULL); + if (r < 0) + return r; /* And then remount the systemd cgroup root read-only */ - if (mount(NULL, systemd_root, NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL) < 0) - return log_error_errno(errno, "Failed to mount cgroup root read-only: %m"); - - return 0; + return mount_verbose(LOG_ERR, NULL, systemd_root, NULL, + MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL); } int setup_volatile_state( @@ -1009,10 +1009,7 @@ int setup_volatile_state( if (r > 0) options = buf; - if (mount("tmpfs", p, "tmpfs", MS_STRICTATIME, options) < 0) - return log_error_errno(errno, "Failed to mount tmpfs to /var: %m"); - - return 0; + return mount_verbose(LOG_ERR, "tmpfs", p, "tmpfs", MS_STRICTATIME, options); } int setup_volatile( @@ -1045,10 +1042,9 @@ int setup_volatile( if (r > 0) options = buf; - if (mount("tmpfs", template, "tmpfs", MS_STRICTATIME, options) < 0) { - r = log_error_errno(errno, "Failed to mount tmpfs for root directory: %m"); + r = mount_verbose(LOG_ERR, "tmpfs", template, "tmpfs", MS_STRICTATIME, options); + if (r < 0) goto fail; - } tmpfs_mounted = true; @@ -1061,10 +1057,9 @@ int setup_volatile( goto fail; } - if (mount(f, t, NULL, MS_BIND|MS_REC, NULL) < 0) { - r = log_error_errno(errno, "Failed to create /usr bind mount: %m"); + r = mount_verbose(LOG_ERR, f, t, NULL, MS_BIND|MS_REC, NULL); + if (r < 0) goto fail; - } bind_mounted = true; @@ -1074,10 +1069,9 @@ int setup_volatile( goto fail; } - if (mount(template, directory, NULL, MS_MOVE, NULL) < 0) { - r = log_error_errno(errno, "Failed to move root mount: %m"); + r = mount_verbose(LOG_ERR, template, directory, NULL, MS_MOVE, NULL); + if (r < 0) goto fail; - } (void) rmdir(template); @@ -1085,10 +1079,10 @@ int setup_volatile( fail: if (bind_mounted) - (void) umount(t); + (void) umount_verbose(t); if (tmpfs_mounted) - (void) umount(template); + (void) umount_verbose(template); (void) rmdir(template); return r; } diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index d62b8c6b82..d95204f71e 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1316,14 +1316,10 @@ static int setup_resolv_conf(const char *dest) { * advantage that the container will be able to follow the host's DNS server configuration changes * transparently. */ - if (mount("/usr/lib/systemd/resolv.conf", where, NULL, MS_BIND, NULL) < 0) - log_warning_errno(errno, "Failed to mount /etc/resolv.conf in the container, ignoring: %m"); - else { - if (mount(NULL, where, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL) < 0) - return log_error_errno(errno, "Failed to remount /etc/resolv.conf read-only: %m"); - - return 0; - } + r = mount_verbose(LOG_WARNING, "/usr/lib/systemd/resolv.conf", where, NULL, MS_BIND, NULL); + if (r >= 0) + return mount_verbose(LOG_ERR, NULL, where, NULL, + MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); } /* If that didn't work, let's copy the file */ @@ -1365,10 +1361,10 @@ static int setup_boot_id(const char *dest) { if (r < 0) return log_error_errno(r, "Failed to write boot id: %m"); - if (mount(from, to, NULL, MS_BIND, NULL) < 0) - r = log_error_errno(errno, "Failed to bind mount boot id: %m"); - else if (mount(NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL) < 0) - r = log_error_errno(errno, "Failed to make boot id read-only: %m"); + r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL); + if (r >= 0) + r = mount_verbose(LOG_ERR, NULL, to, NULL, + MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); (void) unlink(from); return r; @@ -1430,8 +1426,9 @@ static int copy_devnodes(const char *dest) { r = touch(to); if (r < 0) return log_error_errno(r, "touch (%s) failed: %m", to); - if (mount(from, to, NULL, MS_BIND, NULL) < 0) - return log_error_errno(errno, "Both mknod and bind mount (%s) failed: %m", to); + r = mount_verbose(LOG_DEBUG, from, to, NULL, MS_BIND, NULL); + if (r < 0) + return log_error_errno(r, "Both mknod and bind mount (%s) failed: %m", to); } r = userns_lchown(to, 0, 0); @@ -1467,8 +1464,9 @@ static int setup_pts(const char *dest) { p = prefix_roota(dest, "/dev/pts"); if (mkdir(p, 0755) < 0) return log_error_errno(errno, "Failed to create /dev/pts: %m"); - if (mount("devpts", p, "devpts", MS_NOSUID|MS_NOEXEC, options) < 0) - return log_error_errno(errno, "Failed to mount /dev/pts: %m"); + r = mount_verbose(LOG_ERR, "devpts", p, "devpts", MS_NOSUID|MS_NOEXEC, options); + if (r < 0) + return r; r = userns_lchown(p, 0, 0); if (r < 0) return log_error_errno(r, "Failed to chown /dev/pts: %m"); @@ -1513,10 +1511,7 @@ static int setup_dev_console(const char *dest, const char *console) { if (r < 0) return log_error_errno(r, "touch() for /dev/console failed: %m"); - if (mount(console, to, NULL, MS_BIND, NULL) < 0) - return log_error_errno(errno, "Bind mount for /dev/console failed: %m"); - - return 0; + return mount_verbose(LOG_ERR, console, to, NULL, MS_BIND, NULL); } static int setup_kmsg(const char *dest, int kmsg_socket) { @@ -1540,8 +1535,9 @@ static int setup_kmsg(const char *dest, int kmsg_socket) { if (mkfifo(from, 0600) < 0) return log_error_errno(errno, "mkfifo() for /run/kmsg failed: %m"); - if (mount(from, to, NULL, MS_BIND, NULL) < 0) - return log_error_errno(errno, "Bind mount for /proc/kmsg failed: %m"); + r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL); + if (r < 0) + return r; fd = open(from, O_RDWR|O_NDELAY|O_CLOEXEC); if (fd < 0) @@ -1711,7 +1707,8 @@ static int setup_journal(const char *directory) { if (r < 0) return log_error_errno(r, "Failed to create %s: %m", q); - if (mount(p, q, NULL, MS_BIND, NULL) < 0) + r = mount_verbose(LOG_DEBUG, p, q, NULL, MS_BIND, NULL); + if (r < 0) return log_error_errno(errno, "Failed to bind mount journal from host into guest: %m"); return 0; @@ -1776,18 +1773,17 @@ static int setup_propagate(const char *root) { return log_error_errno(r, "Failed to create /run/systemd/nspawn/incoming: %m"); q = prefix_roota(root, "/run/systemd/nspawn/incoming"); - if (mount(p, q, NULL, MS_BIND, NULL) < 0) - return log_error_errno(errno, "Failed to install propagation bind mount."); + r = mount_verbose(LOG_ERR, p, q, NULL, MS_BIND, NULL); + if (r < 0) + return r; - if (mount(NULL, q, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) - return log_error_errno(errno, "Failed to make propagation mount read-only"); + r = mount_verbose(LOG_ERR, NULL, q, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL); + if (r < 0) + return r; /* machined will MS_MOVE into that directory, and that's only * supported for non-shared mounts. */ - if (mount(NULL, q, NULL, MS_SLAVE, NULL) < 0) - return log_error_errno(errno, "Failed to make propagation mount slave"); - - return 0; + return mount_verbose(LOG_ERR, NULL, q, NULL, MS_SLAVE, NULL); } static int setup_image(char **device_path, int *loop_nr) { @@ -2313,10 +2309,7 @@ static int mount_device(const char *what, const char *where, const char *directo return -EOPNOTSUPP; } - if (mount(what, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), NULL) < 0) - return log_error_errno(errno, "Failed to mount %s: %m", what); - - return 0; + return mount_verbose(LOG_ERR, what, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), NULL); #else log_error("--image= is not supported, compiled without blkid support."); return -EOPNOTSUPP; @@ -2976,8 +2969,9 @@ static int outer_child( /* Mark everything as slave, so that we still * receive mounts from the real root, but don't * propagate mounts to the real root. */ - if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) - return log_error_errno(errno, "MS_SLAVE|MS_REC failed: %m"); + r = mount_verbose(LOG_ERR, NULL, "/", NULL, MS_SLAVE|MS_REC, NULL); + if (r < 0) + return r; r = mount_devices(directory, root_device, root_device_rw, @@ -3023,8 +3017,9 @@ static int outer_child( } /* Turn directory into bind mount */ - if (mount(directory, directory, NULL, MS_BIND|MS_REC, NULL) < 0) - return log_error_errno(errno, "Failed to make bind mount: %m"); + r = mount_verbose(LOG_ERR, directory, directory, NULL, MS_BIND|MS_REC, NULL); + if (r < 0) + return r; /* Mark everything as shared so our mounts get propagated down. This is * required to make new bind mounts available in systemd services @@ -3032,8 +3027,9 @@ static int outer_child( * See https://github.com/systemd/systemd/issues/3860 * Further submounts (such as /dev) done after this will inherit the * shared propagation mode.*/ - if (mount(NULL, directory, NULL, MS_SHARED|MS_REC, NULL) < 0) - return log_error_errno(errno, "MS_SHARED|MS_REC failed: %m"); + r = mount_verbose(LOG_ERR, NULL, directory, NULL, MS_SHARED|MS_REC, NULL); + if (r < 0) + return r; r = recursive_chown(directory, arg_uid_shift, arg_uid_range); if (r < 0) -- cgit v1.2.3-54-g00ecf From 8492849ee567c4657d6ac6587ed9536857624b4c Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Wed, 12 Oct 2016 00:18:27 +0300 Subject: nspawn: let's mount(/tmp) inside the user namespace (#4340) Fixes: host# systemd-nspawn -D ... -U -b systemd.unit=multi-user.target ... $ grep /tmp /proc/self/mountinfo 154 145 0:41 / /tmp rw - tmpfs tmpfs rw,seclabel,uid=1036124160,gid=1036124160 $ umount /tmp umount: /root/tmp: not mounted $ systemctl poweroff ... [FAILED] Failed unmounting Temporary Directory. --- src/nspawn/nspawn-mount.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 25d38aa742..895fc6134c 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -325,7 +325,7 @@ int mount_all(const char *dest, { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false, false }, { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false }, { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false, false }, - { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, false, false }, + { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_STRICTATIME, true, true, false }, #ifdef HAVE_SELINUX { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, false, false, false }, /* Bind mount first */ { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, false, false }, /* Then, make it r/o */ @@ -368,7 +368,10 @@ int mount_all(const char *dest, o = mount_table[k].options; if (streq_ptr(mount_table[k].type, "tmpfs")) { - r = tmpfs_patch_options(o, use_userns, uid_shift, uid_range, false, selinux_apifs_context, &options); + if (in_userns) + r = tmpfs_patch_options(o, use_userns, 0, uid_range, true, selinux_apifs_context, &options); + else + r = tmpfs_patch_options(o, use_userns, uid_shift, uid_range, false, selinux_apifs_context, &options); if (r < 0) return log_oom(); if (r > 0) -- cgit v1.2.3-54-g00ecf From 7ef7147041573e355cb52b381bec3843e7d6d24b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 11 Oct 2016 17:24:03 -0400 Subject: missing: add a bunch of mount flags --- src/basic/missing.h | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/basic/missing.h b/src/basic/missing.h index 4a78269e33..4c013be608 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -473,24 +473,44 @@ struct btrfs_ioctl_quota_ctl_args { #define MS_MOVE 8192 #endif +#ifndef MS_REC +#define MS_REC 16384 +#endif + #ifndef MS_PRIVATE -#define MS_PRIVATE (1 << 18) +#define MS_PRIVATE (1<<18) #endif -#ifndef SCM_SECURITY -#define SCM_SECURITY 0x03 +#ifndef MS_REC +#define MS_REC (1<<19) +#endif + +#ifndef MS_SHARED +#define MS_SHARED (1<<20) +#endif + +#ifndef MS_RELATIME +#define MS_RELATIME (1<<21) +#endif + +#ifndef MS_KERNMOUNT +#define MS_KERNMOUNT (1<<22) +#endif + +#ifndef MS_I_VERSION +#define MS_I_VERSION (1<<23) #endif #ifndef MS_STRICTATIME -#define MS_STRICTATIME (1<<24) +#define MS_STRICTATIME (1<<24) #endif -#ifndef MS_REC -#define MS_REC 16384 +#ifndef MS_LAZYTIME +#define MS_LAZYTIME (1<<25) #endif -#ifndef MS_SHARED -#define MS_SHARED (1<<20) +#ifndef SCM_SECURITY +#define SCM_SECURITY 0x03 #endif #ifndef PR_SET_NO_NEW_PRIVS -- cgit v1.2.3-54-g00ecf From 74e7579c17e08ee548a81dfca3d98251d3d3948c Mon Sep 17 00:00:00 2001 From: 0xAX <0xAX@users.noreply.github.com> Date: Wed, 12 Oct 2016 00:30:04 +0300 Subject: core/main: get rid from excess check of ACTION_TEST (#4350) If `--test` command line option was passed, the systemd set skip_setup to true during bootup. But after this we check again that arg_action is test or help and opens pager depends on result. We should skip setup in a case when `--test` is passed, but it is also safe to set skip_setup in a case of `--help`. So let's remove first check and move skip_setup = true to the second check. --- src/core/main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 4b82a57b3c..61f3828a36 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1614,11 +1614,10 @@ int main(int argc, char *argv[]) { goto finish; } - if (arg_action == ACTION_TEST) - skip_setup = true; - - if (arg_action == ACTION_TEST || arg_action == ACTION_HELP) + if (arg_action == ACTION_TEST || arg_action == ACTION_HELP) { pager_open(arg_no_pager, false); + skip_setup = true; + } if (arg_action == ACTION_HELP) { retval = help(); -- cgit v1.2.3-54-g00ecf From 9f1008d5131806a390d697f2e1e994ea1e9bf83d Mon Sep 17 00:00:00 2001 From: Andrew Jeddeloh Date: Tue, 11 Oct 2016 21:28:22 -0400 Subject: networkd: add dbus interface for lease raw options (#3528) Add a dbus object to represent dhcp leases and their raw options (i.e. options 224-254). --- src/network/networkd-link-bus.c | 131 ++++++++++++++++++++++++++++++++++++++++ src/network/networkd-link.h | 5 ++ src/network/networkd-manager.c | 8 +++ 3 files changed, 144 insertions(+) diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c index 532557ed6c..10ec08351a 100644 --- a/src/network/networkd-link-bus.c +++ b/src/network/networkd-link-bus.c @@ -23,6 +23,7 @@ #include "networkd.h" #include "parse-util.h" #include "strv.h" +#include "dhcp-lease-internal.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState); @@ -36,6 +37,50 @@ const sd_bus_vtable link_vtable[] = { SD_BUS_VTABLE_END }; +static int get_private_options(sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + sd_dhcp_lease *lease = userdata; + struct sd_dhcp_raw_option *option = NULL; + int r; + + assert(bus); + assert(reply); + assert(lease); + + r = sd_bus_message_open_container(reply, SD_BUS_TYPE_ARRAY, "{yay}"); + if (r < 0) + return r; + + LIST_FOREACH(options, option, lease->private_options) { + r = sd_bus_message_open_container(reply, SD_BUS_TYPE_DICT_ENTRY, "yay"); + if (r < 0) + return r; + r = sd_bus_message_append(reply, "y", option->tag); + if (r < 0) + return r; + r = sd_bus_message_append_array(reply, 'y', option->data, option->length); + if (r < 0) + return r; + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + } + return sd_bus_message_close_container(reply); +} + +const sd_bus_vtable lease_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("PrivateOptions", "a{yay}", get_private_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + + SD_BUS_VTABLE_END +}; + static char *link_bus_path(Link *link) { _cleanup_free_ char *ifindex = NULL; char *p; @@ -54,6 +99,24 @@ static char *link_bus_path(Link *link) { return p; } +static char *lease_bus_path(Link *link) { + _cleanup_free_ char *p = NULL; + char *ret = NULL; + int r; + + assert(link); + + p = link_bus_path(link); + if (!p) + return NULL; + + r = sd_bus_path_encode(p, "lease", &ret); + if (r < 0) + return NULL; + + return ret; +} + int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; Manager *m = userdata; @@ -87,6 +150,42 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char *** return 1; } +int lease_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + unsigned c = 0; + Link *link; + Iterator i; + + assert(bus); + assert(path); + assert(m); + assert(nodes); + + l = new0(char*, hashmap_size(m->links) + 1); + if (!l) + return -ENOMEM; + + HASHMAP_FOREACH(link, m->links, i) { + char *p; + + if (!link->dhcp_lease) + continue; + + p = lease_bus_path(link); + if (!p) + return -ENOMEM; + + l[c++] = p; + } + + l[c] = NULL; + *nodes = l; + l = NULL; + + return 1; +} + int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { _cleanup_free_ char *identifier = NULL; Manager *m = userdata; @@ -116,6 +215,38 @@ int link_object_find(sd_bus *bus, const char *path, const char *interface, void return 1; } +int lease_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + _cleanup_free_ char *identifier = NULL; + Manager *m = userdata; + Link *link; + int ifindex, r; + + assert(bus); + assert(path); + assert(interface); + assert(m); + assert(found); + + r = sd_bus_path_decode_many(path, "/org/freedesktop/network1/link/%/lease", &identifier); + if (r <= 0) + return 0; + + r = parse_ifindex(identifier, &ifindex); + if (r < 0) + return 0; + + r = link_get(m, ifindex, &link); + if (r < 0) + return 0; + + if (!link->dhcp_lease) + return 0; + + *found = link->dhcp_lease; + + return 1; +} + int link_send_changed(Link *link, const char *property, ...) { _cleanup_free_ char *p = NULL; char **l; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 77f72d070e..1178999bb4 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -179,6 +179,11 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char *** int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); int link_send_changed(Link *link, const char *property, ...) _sentinel_; +extern const sd_bus_vtable lease_vtable[]; + +int lease_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); +int lease_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); + DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); #define _cleanup_link_unref_ _cleanup_(link_unrefp) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 9174dcc7f4..0ad34e0cc2 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -176,6 +176,14 @@ int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to add link enumerator: %m"); + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link.Lease", lease_vtable, lease_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to add lease object vtable: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", lease_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to add lease enumerator: %m"); + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/network", "org.freedesktop.network1.Network", network_vtable, network_object_find, m); if (r < 0) return log_error_errno(r, "Failed to add network object vtable: %m"); -- cgit v1.2.3-54-g00ecf From 3ccb886283a1a98b549f44b6d33edeecc3768f1f Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 12 Oct 2016 05:12:11 -0400 Subject: Allow block and char classes in DeviceAllow bus properties (#4353) Allowed paths are unified betwen the configuration file parses and the bus property checker. The biggest change is that the bus code now allows "block-" and "char-" classes. In addition, path_startswith("/dev") was used in the bus code, and startswith("/dev") was used in the config file code. It seems reasonable to use path_startswith() which allows a slightly broader class of strings. Fixes #3935. --- src/basic/path-util.c | 11 ++++++++--- src/basic/path-util.h | 1 + src/core/load-fragment.c | 4 +--- src/shared/bus-unit-util.c | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/basic/path-util.c b/src/basic/path-util.c index c32e961af4..a76963aa9f 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -812,9 +812,14 @@ bool is_device_path(const char *path) { /* Returns true on paths that refer to a device, either in * sysfs or in /dev */ - return - path_startswith(path, "/dev/") || - path_startswith(path, "/sys/"); + return path_startswith(path, "/dev/") || + path_startswith(path, "/sys/"); +} + +bool is_deviceallow_pattern(const char *path) { + return path_startswith(path, "/dev/") || + startswith(path, "block-") || + startswith(path, "char-"); } int systemd_installation_has_version(const char *root, unsigned minimal_version) { diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 78472f0961..66545f52d9 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -125,5 +125,6 @@ char *file_in_same_dir(const char *path, const char *filename); bool hidden_or_backup_file(const char *filename) _pure_; bool is_device_path(const char *path); +bool is_deviceallow_pattern(const char *path); int systemd_installation_has_version(const char *root, unsigned minimal_version); diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 8f067b5586..06c156a623 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -3084,9 +3084,7 @@ int config_parse_device_allow( if (!path) return log_oom(); - if (!startswith(path, "/dev/") && - !startswith(path, "block-") && - !startswith(path, "char-")) { + if (!is_deviceallow_pattern(path)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path); return 0; } diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index c6bd2f145c..a550a370b5 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -303,7 +303,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen rwm = ""; } - if (!path_startswith(path, "/dev")) { + if (!is_deviceallow_pattern(path)) { log_error("%s is not a device file in /dev.", path); return -EINVAL; } -- cgit v1.2.3-54-g00ecf From 3f2a3726d02e269a37f1f2c2e429212988fd4cbf Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 12 Oct 2016 18:13:13 +0900 Subject: units: journal-upload Wants= and After=network-online.target (#4354) To upload journal entries to a remote server, it is required that the network is online. --- units/systemd-journal-upload.service.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/units/systemd-journal-upload.service.in b/units/systemd-journal-upload.service.in index c709543af5..d8fd243620 100644 --- a/units/systemd-journal-upload.service.in +++ b/units/systemd-journal-upload.service.in @@ -8,7 +8,8 @@ [Unit] Description=Journal Remote Upload Service Documentation=man:systemd-journal-upload(8) -After=network.target +Wants=network-online.target +After=network-online.target [Service] ExecStart=@rootlibexecdir@/systemd-journal-upload --save-state -- cgit v1.2.3-54-g00ecf From 502d704e5ed2d288069471f4e3611115cde107d6 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Wed, 12 Oct 2016 13:31:21 +0200 Subject: core:sandbox: Add ProtectKernelModules= option This is useful to turn off explicit module load and unload operations on modular kernels. This option removes CAP_SYS_MODULE from the capability bounding set for the unit, and installs a system call filter to block module system calls. This option will not prevent the kernel from loading modules using the module auto-load feature which is a system wide operation. --- man/systemd.exec.xml | 17 ++++++++++++ src/core/dbus-execute.c | 5 +++- src/core/execute.c | 52 +++++++++++++++++++++++++++++++++++ src/core/execute.h | 1 + src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/unit.c | 3 ++ src/shared/bus-unit-util.c | 3 +- 7 files changed, 80 insertions(+), 2 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 986985ad35..3bea4976b3 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1404,6 +1404,23 @@ logging. This does not affect commands prefixed with +. + + ProtectKernelModules= + + Takes a boolean argument. If true, explicit module loading will + be denied. This allows to turn off module load and unload operations on modular + kernels. It is recomended to turn this on for most services that do not need special + file systems or extra kernel modules to work. Default to off. Enabling this option + removes CAP_SYS_MODULE from the capability bounding set for + the unit, and installs a system call filter to block module system calls. + Note that limited automatic module loading due to user configuration or kernel + mapping tables might still happen as side effect of requested user operations, + both privileged and unprivileged. To disable module auto-load feature please see + sysctl.d5 + kernel.modules_disabled mechanism and + /proc/sys/kernel/modules_disabled documentation. + + Personality= diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index eec4500c8c..b8720d7d3d 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -708,6 +708,7 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_tunables), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_modules), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST), @@ -1075,7 +1076,7 @@ int bus_exec_context_set_transient_property( "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute", "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables", - "ProtectControlGroups")) { + "ProtectKernelModules", "ProtectControlGroups")) { int b; r = sd_bus_message_read(message, "b", &b); @@ -1111,6 +1112,8 @@ int bus_exec_context_set_transient_property( c->remove_ipc = b; else if (streq(name, "ProtectKernelTunables")) c->protect_kernel_tunables = b; + else if (streq(name, "ProtectKernelModules")) + c->protect_kernel_modules = b; else if (streq(name, "ProtectControlGroups")) c->protect_control_groups = b; diff --git a/src/core/execute.c b/src/core/execute.c index 0c983f4953..7a278b7d31 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1436,6 +1436,50 @@ finish: return r; } +static int apply_protect_kernel_modules(Unit *u, const ExecContext *c) { + static const int module_syscalls[] = { + SCMP_SYS(delete_module), + SCMP_SYS(finit_module), + SCMP_SYS(init_module), + }; + + scmp_filter_ctx *seccomp; + unsigned i; + int r; + + assert(c); + + /* Turn of module syscalls on ProtectKernelModules=yes */ + + if (skip_seccomp_unavailable(u, "ProtectKernelModules=")) + return 0; + + seccomp = seccomp_init(SCMP_ACT_ALLOW); + if (!seccomp) + return -ENOMEM; + + r = seccomp_add_secondary_archs(seccomp); + if (r < 0) + goto finish; + + for (i = 0; i < ELEMENTSOF(module_syscalls); i++) { + r = seccomp_rule_add(seccomp, SCMP_ACT_ERRNO(EPERM), + module_syscalls[i], 0); + if (r < 0) + goto finish; + } + + r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); + if (r < 0) + goto finish; + + r = seccomp_load(seccomp); + +finish: + seccomp_release(seccomp); + return r; +} + static int apply_private_devices(Unit *u, const ExecContext *c) { const SystemCallFilterSet *set; scmp_filter_ctx *seccomp; @@ -2690,6 +2734,14 @@ static int exec_child( } } + if (context->protect_kernel_modules) { + r = apply_protect_kernel_modules(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return r; + } + } + if (context->private_devices) { r = apply_private_devices(unit, context); if (r < 0) { diff --git a/src/core/execute.h b/src/core/execute.h index 449180c903..1de439c3ad 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -175,6 +175,7 @@ struct ExecContext { ProtectSystem protect_system; ProtectHome protect_home; bool protect_kernel_tunables; + bool protect_kernel_modules; bool protect_control_groups; bool no_new_privileges; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index c49c1d6732..a700d853cc 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -90,6 +90,7 @@ $1.InaccessiblePaths, config_parse_namespace_path_strv, 0, $1.PrivateTmp, config_parse_bool, 0, offsetof($1, exec_context.private_tmp) $1.PrivateDevices, config_parse_bool, 0, offsetof($1, exec_context.private_devices) $1.ProtectKernelTunables, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_tunables) +$1.ProtectKernelModules, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_modules) $1.ProtectControlGroups, config_parse_bool, 0, offsetof($1, exec_context.protect_control_groups) $1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network) $1.PrivateUsers, config_parse_bool, 0, offsetof($1, exec_context.private_users) diff --git a/src/core/unit.c b/src/core/unit.c index 690f7f7dd9..71f95c0b96 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3401,6 +3401,9 @@ int unit_patch_contexts(Unit *u) { if (ec->private_devices) ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_MKNOD); + if (ec->protect_kernel_modules) + ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYS_MODULE); + if (ec->dynamic_user) { if (!ec->user) { r = user_from_unit_name(u, &ec->user); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index a550a370b5..f639e0e832 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -204,7 +204,8 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges", "SyslogLevelPrefix", "Delegate", "RemainAfterElapse", "MemoryDenyWriteExecute", - "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables", "ProtectControlGroups")) { + "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables", + "ProtectKernelModules", "ProtectControlGroups")) { r = parse_boolean(eq); if (r < 0) -- cgit v1.2.3-54-g00ecf From 3ae33295f00be5e2836f009bf1991b0caddf80b7 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Fri, 7 Oct 2016 19:17:34 +0200 Subject: test: add capability tests for ProtectKernelModules= This just adds capabilities test. --- Makefile.am | 2 ++ src/test/test-execute.c | 11 +++++++++++ .../exec-protectkernelmodules-no-capabilities.service | 7 +++++++ .../exec-protectkernelmodules-yes-capabilities.service | 7 +++++++ 4 files changed, 27 insertions(+) create mode 100644 test/test-execute/exec-protectkernelmodules-no-capabilities.service create mode 100644 test/test-execute/exec-protectkernelmodules-yes-capabilities.service diff --git a/Makefile.am b/Makefile.am index b09b0cf167..1ea25bb688 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1639,6 +1639,8 @@ EXTRA_DIST += \ test/test-execute/exec-privatedevices-yes.service \ test/test-execute/exec-privatedevices-no-capability-mknod.service \ test/test-execute/exec-privatedevices-yes-capability-mknod.service \ + test/test-execute/exec-protectkernelmodules-no-capabilities.service \ + test/test-execute/exec-protectkernelmodules-yes-capabilities.service \ test/test-execute/exec-privatetmp-no.service \ test/test-execute/exec-privatetmp-yes.service \ test/test-execute/exec-readonlypaths.service \ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 8b4ff22495..f7d38fb0f3 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -142,6 +142,16 @@ static void test_exec_privatedevices_capabilities(Manager *m) { test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED); } +static void test_exec_protectkernelmodules_capabilities(Manager *m) { + if (detect_container() > 0) { + log_notice("testing in container, skipping protectkernelmodules tests"); + return; + } + + test(m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED); + test(m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED); +} + static void test_exec_readonlypaths(Manager *m) { test(m, "exec-readonlypaths.service", 0, CLD_EXITED); test(m, "exec-readonlypaths-mount-propagation.service", 0, CLD_EXITED); @@ -368,6 +378,7 @@ int main(int argc, char *argv[]) { test_exec_privatetmp, test_exec_privatedevices, test_exec_privatedevices_capabilities, + test_exec_protectkernelmodules_capabilities, test_exec_readonlypaths, test_exec_readwritepaths, test_exec_inaccessiblepaths, diff --git a/test/test-execute/exec-protectkernelmodules-no-capabilities.service b/test/test-execute/exec-protectkernelmodules-no-capabilities.service new file mode 100644 index 0000000000..b2f2cd6b8a --- /dev/null +++ b/test/test-execute/exec-protectkernelmodules-no-capabilities.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test CAP_SYS_MODULE ProtectKernelModules=no + +[Service] +ProtectKernelModules=no +ExecStart=/bin/sh -x -c 'capsh --print | grep cap_sys_module' +Type=oneshot diff --git a/test/test-execute/exec-protectkernelmodules-yes-capabilities.service b/test/test-execute/exec-protectkernelmodules-yes-capabilities.service new file mode 100644 index 0000000000..84bf39be56 --- /dev/null +++ b/test/test-execute/exec-protectkernelmodules-yes-capabilities.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test CAP_SYS_MODULE for ProtectKernelModules=yes + +[Service] +ProtectKernelModules=yes +ExecStart=/bin/sh -x -c '! capsh --print | grep cap_sys_module' +Type=oneshot -- cgit v1.2.3-54-g00ecf From 2cd0a735470894bd2d25147442285744764633a1 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Fri, 7 Oct 2016 20:38:05 +0200 Subject: core:sandbox: remove CAP_SYS_RAWIO on PrivateDevices=yes The rawio system calls were filtered, but CAP_SYS_RAWIO allows to access raw data through /proc, ioctl and some other exotic system calls... --- man/systemd.exec.xml | 4 ++-- src/core/unit.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 3bea4976b3..c46c0f6dd8 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -946,8 +946,8 @@ /dev/port and others. This is useful to securely turn off physical device access by the executed process. Defaults to false. Enabling this option will install a system call filter to block low-level I/O system calls that are grouped in the @raw-io set, will also remove - CAP_MKNOD from the capability bounding set for the unit (see above), and set - DevicePolicy=closed (see + CAP_MKNOD and CAP_SYS_RAWIO from the capability bounding set for + the unit (see above), and set DevicePolicy=closed (see systemd.resource-control5 for details). Note that using this setting will disconnect propagation of mounts from the service to the host (propagation in the opposite direction continues to work). This means that this setting may not be used for diff --git a/src/core/unit.c b/src/core/unit.c index 71f95c0b96..67668bdc48 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3399,7 +3399,7 @@ int unit_patch_contexts(Unit *u) { ec->no_new_privileges = true; if (ec->private_devices) - ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_MKNOD); + ec->capability_bounding_set &= ~((UINT64_C(1) << CAP_MKNOD) | (UINT64_C(1) << CAP_SYS_RAWIO)); if (ec->protect_kernel_modules) ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYS_MODULE); -- cgit v1.2.3-54-g00ecf From 625d8769fa6394a302b024eaee45043e6eb0c87a Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Fri, 7 Oct 2016 20:41:38 +0200 Subject: test: add test to make sure that CAP_SYS_RAWIO was removed on PrivateDevices=yes --- src/test/test-execute.c | 2 ++ .../exec-privatedevices-no-capability-sys-rawio.service | 7 +++++++ .../exec-privatedevices-yes-capability-sys-rawio.service | 7 +++++++ 3 files changed, 16 insertions(+) create mode 100644 test/test-execute/exec-privatedevices-no-capability-sys-rawio.service create mode 100644 test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service diff --git a/src/test/test-execute.c b/src/test/test-execute.c index f7d38fb0f3..1eade98ed3 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -140,6 +140,8 @@ static void test_exec_privatedevices_capabilities(Manager *m) { } test(m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED); test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED); + test(m, "exec-privatedevices-yes-capability-sys-rawio.service", 0, CLD_EXITED); + test(m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED); } static void test_exec_protectkernelmodules_capabilities(Manager *m) { diff --git a/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service b/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service new file mode 100644 index 0000000000..e7f529c44c --- /dev/null +++ b/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test CAP_SYS_RAWIO capability for PrivateDevices=no + +[Service] +PrivateDevices=no +ExecStart=/bin/sh -x -c 'capsh --print | grep cap_sys_rawio' +Type=oneshot diff --git a/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service b/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service new file mode 100644 index 0000000000..cebc493a7a --- /dev/null +++ b/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test CAP_SYS_RAWIO capability for PrivateDevices=yes + +[Service] +PrivateDevices=yes +ExecStart=/bin/sh -x -c '! capsh --print | grep cap_sys_rawio' +Type=oneshot -- cgit v1.2.3-54-g00ecf From ac246d9868bd476297e2702e0a7ef52294f9cfa8 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sat, 8 Oct 2016 17:48:35 +0200 Subject: doc: minor hint about InaccessiblePaths= in regard of ProtectKernelTunables= --- man/systemd.exec.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index c46c0f6dd8..4a68695348 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1046,7 +1046,10 @@ boot-time, with the sysctl.d5 mechanism. Almost no services need to write to these at runtime; it is hence recommended to turn this on for most services. For this setting the same restrictions regarding mount propagation and privileges apply as for - ReadOnlyPaths= and related calls, see above. Defaults to off. + ReadOnlyPaths= and related calls, see above. Defaults to off. + Note that this option does not prevent kernel tuning through IPC interfaces and exeternal programs. However + InaccessiblePaths= can be used to make some IPC file system objects + inaccessible. -- cgit v1.2.3-54-g00ecf From c575770b75b6cd15684fbacd249147bf5fd6ead7 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Wed, 12 Oct 2016 14:11:16 +0200 Subject: core:sandbox: lets make /lib/modules/ inaccessible on ProtectKernelModules= Lets go further and make /lib/modules/ inaccessible for services that do not have business with modules, this is a minor improvment but it may help on setups with custom modules and they are limited... in regard of kernel auto-load feature. This change introduce NameSpaceInfo struct which we may embed later inside ExecContext but for now lets just reduce the argument number to setup_namespace() and merge ProtectKernelModules feature. --- man/systemd.exec.xml | 5 ++++- src/core/execute.c | 11 ++++++++--- src/core/namespace.c | 54 +++++++++++++++++++++++++++++++++++----------------- src/core/namespace.h | 14 +++++++++++--- src/test/test-ns.c | 12 +++++++++--- 5 files changed, 69 insertions(+), 27 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 4a68695348..249fcb0363 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1415,7 +1415,10 @@ kernels. It is recomended to turn this on for most services that do not need special file systems or extra kernel modules to work. Default to off. Enabling this option removes CAP_SYS_MODULE from the capability bounding set for - the unit, and installs a system call filter to block module system calls. + the unit, and installs a system call filter to block module system calls, + also /usr/lib/modules is made inaccessible. For this + setting the same restrictions regarding mount propagation and privileges + apply as for ReadOnlyPaths= and related calls, see above. Note that limited automatic module loading due to user configuration or kernel mapping tables might still happen as side effect of requested user operations, both privileged and unprivileged. To disable module auto-load feature please see diff --git a/src/core/execute.c b/src/core/execute.c index 7a278b7d31..dc078d96f0 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1766,6 +1766,7 @@ static bool exec_needs_mount_namespace( context->protect_system != PROTECT_SYSTEM_NO || context->protect_home != PROTECT_HOME_NO || context->protect_kernel_tunables || + context->protect_kernel_modules || context->protect_control_groups) return true; @@ -2493,6 +2494,12 @@ static int exec_child( if (needs_mount_namespace) { _cleanup_free_ char **rw = NULL; char *tmp = NULL, *var = NULL; + NameSpaceInfo ns_info = { + .private_dev = context->private_devices, + .protect_control_groups = context->protect_control_groups, + .protect_kernel_tunables = context->protect_kernel_tunables, + .protect_kernel_modules = context->protect_kernel_modules, + }; /* The runtime struct only contains the parent * of the private /tmp, which is @@ -2515,14 +2522,12 @@ static int exec_child( r = setup_namespace( (params->flags & EXEC_APPLY_CHROOT) ? context->root_directory : NULL, + &ns_info, rw, context->read_only_paths, context->inaccessible_paths, tmp, var, - context->private_devices, - context->protect_kernel_tunables, - context->protect_control_groups, context->protect_home, context->protect_system, context->mount_flags); diff --git a/src/core/namespace.c b/src/core/namespace.c index 43a2f4ba6e..1195e9a854 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -97,6 +97,14 @@ static const TargetMount protect_kernel_tunables_table[] = { { "/sys/fs/cgroup", READWRITE, false }, /* READONLY is set by ProtectControlGroups= option */ }; +/* ProtectKernelModules= option */ +static const TargetMount protect_kernel_modules_table[] = { +#ifdef HAVE_SPLIT_USR + { "/lib/modules", INACCESSIBLE, true }, +#endif + { "/usr/lib/modules", INACCESSIBLE, true }, +}; + /* * ProtectHome=read-only table, protect $HOME and $XDG_RUNTIME_DIR and rest of * system should be protected by ProtectSystem= @@ -207,6 +215,13 @@ static int append_protect_kernel_tunables(BindMount **p, const char *root_direct ELEMENTSOF(protect_kernel_tunables_table)); } +static int append_protect_kernel_modules(BindMount **p, const char *root_directory) { + assert(p); + + return append_target_mounts(p, root_directory, protect_kernel_modules_table, + ELEMENTSOF(protect_kernel_modules_table)); +} + static int append_protect_home(BindMount **p, const char *root_directory, ProtectHome protect_home) { int r = 0; @@ -660,14 +675,12 @@ static int chase_all_symlinks(const char *root_directory, BindMount *m, unsigned } static unsigned namespace_calculate_mounts( + const NameSpaceInfo *ns_info, char** read_write_paths, char** read_only_paths, char** inaccessible_paths, const char* tmp_dir, const char* var_tmp_dir, - bool private_dev, - bool protect_sysctl, - bool protect_cgroups, ProtectHome protect_home, ProtectSystem protect_system) { @@ -690,22 +703,21 @@ static unsigned namespace_calculate_mounts( strv_length(read_write_paths) + strv_length(read_only_paths) + strv_length(inaccessible_paths) + - private_dev + - (protect_sysctl ? ELEMENTSOF(protect_kernel_tunables_table) : 0) + - (protect_cgroups ? 1 : 0) + + ns_info->private_dev + + (ns_info->protect_kernel_tunables ? ELEMENTSOF(protect_kernel_tunables_table) : 0) + + (ns_info->protect_control_groups ? 1 : 0) + + (ns_info->protect_kernel_modules ? ELEMENTSOF(protect_kernel_modules_table) : 0) + protect_home_cnt + protect_system_cnt; } int setup_namespace( const char* root_directory, + const NameSpaceInfo *ns_info, char** read_write_paths, char** read_only_paths, char** inaccessible_paths, const char* tmp_dir, const char* var_tmp_dir, - bool private_dev, - bool protect_sysctl, - bool protect_cgroups, ProtectHome protect_home, ProtectSystem protect_system, unsigned long mount_flags) { @@ -718,13 +730,12 @@ int setup_namespace( if (mount_flags == 0) mount_flags = MS_SHARED; - n = namespace_calculate_mounts(read_write_paths, + n = namespace_calculate_mounts(ns_info, + read_write_paths, read_only_paths, inaccessible_paths, tmp_dir, var_tmp_dir, - private_dev, protect_sysctl, - protect_cgroups, protect_home, - protect_system); + protect_home, protect_system); /* Set mount slave mode */ if (root_directory || n > 0) @@ -756,16 +767,25 @@ int setup_namespace( m++; } - if (private_dev) { + if (ns_info->private_dev) { m->path = prefix_roota(root_directory, "/dev"); m->mode = PRIVATE_DEV; m++; } - if (protect_sysctl) - append_protect_kernel_tunables(&m, root_directory); + if (ns_info->protect_kernel_tunables) { + r = append_protect_kernel_tunables(&m, root_directory); + if (r < 0) + return r; + } + + if (ns_info->protect_kernel_modules) { + r = append_protect_kernel_modules(&m, root_directory); + if (r < 0) + return r; + } - if (protect_cgroups) { + if (ns_info->protect_control_groups) { m->path = prefix_roota(root_directory, "/sys/fs/cgroup"); m->mode = READONLY; m++; diff --git a/src/core/namespace.h b/src/core/namespace.h index 6505bcc499..6310638e9a 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -4,6 +4,7 @@ This file is part of systemd. Copyright 2010 Lennart Poettering + Copyright 2016 Djalal Harouni systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -19,6 +20,8 @@ along with systemd; If not, see . ***/ +typedef struct NameSpaceInfo NameSpaceInfo; + #include #include "macro.h" @@ -40,15 +43,20 @@ typedef enum ProtectSystem { _PROTECT_SYSTEM_INVALID = -1 } ProtectSystem; +struct NameSpaceInfo { + bool private_dev:1; + bool protect_control_groups:1; + bool protect_kernel_tunables:1; + bool protect_kernel_modules:1; +}; + int setup_namespace(const char *chroot, + const NameSpaceInfo *ns_info, char **read_write_paths, char **read_only_paths, char **inaccessible_paths, const char *tmp_dir, const char *var_tmp_dir, - bool private_dev, - bool protect_sysctl, - bool protect_cgroups, ProtectHome protect_home, ProtectSystem protect_system, unsigned long mount_flags); diff --git a/src/test/test-ns.c b/src/test/test-ns.c index c4d4da6d05..da7a8b0565 100644 --- a/src/test/test-ns.c +++ b/src/test/test-ns.c @@ -45,6 +45,14 @@ int main(int argc, char *argv[]) { "/home/lennart/projects", NULL }; + + static const NameSpaceInfo ns_info = { + .private_dev = true, + .protect_control_groups = true, + .protect_kernel_tunables = true, + .protect_kernel_modules = true, + }; + char *root_directory; char *projects_directory; int r; @@ -69,14 +77,12 @@ int main(int argc, char *argv[]) { log_info("Not chrooted"); r = setup_namespace(root_directory, + &ns_info, (char **) writable, (char **) readonly, (char **) inaccessible, tmp_dir, var_tmp_dir, - true, - true, - true, PROTECT_HOME_NO, PROTECT_SYSTEM_NO, 0); -- cgit v1.2.3-54-g00ecf From 4084e8fc8947566092fd4ee5a07405570fdbf84d Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 9 Oct 2016 12:28:25 +0200 Subject: core: check protect_kernel_modules and private_devices in order to setup NNP --- src/core/execute.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/execute.c b/src/core/execute.c index dc078d96f0..71439bc3c2 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2115,6 +2115,8 @@ static bool context_has_no_new_privileges(const ExecContext *c) { c->memory_deny_write_execute || c->restrict_realtime || c->protect_kernel_tunables || + c->protect_kernel_modules || + c->private_devices || context_has_syscall_filters(c); } -- cgit v1.2.3-54-g00ecf From e66a2f658b182b1fe8e4bc46b384b9967abd2bf2 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 9 Oct 2016 12:31:51 +0200 Subject: core: make sure to dump ProtectKernelModules= value --- src/core/execute.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/execute.c b/src/core/execute.c index 71439bc3c2..869522704a 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -3190,6 +3190,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { "%sPrivateTmp: %s\n" "%sPrivateDevices: %s\n" "%sProtectKernelTunables: %s\n" + "%sProtectKernelModules: %s\n" "%sProtectControlGroups: %s\n" "%sPrivateNetwork: %s\n" "%sPrivateUsers: %s\n" @@ -3205,6 +3206,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { prefix, yes_no(c->private_tmp), prefix, yes_no(c->private_devices), prefix, yes_no(c->protect_kernel_tunables), + prefix, yes_no(c->protect_kernel_modules), prefix, yes_no(c->protect_control_groups), prefix, yes_no(c->private_network), prefix, yes_no(c->private_users), -- cgit v1.2.3-54-g00ecf From 4982dbcc300d4599aa6ac143e922d6fbee31a860 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 9 Oct 2016 12:38:45 +0200 Subject: test: add test to make sure that ProtectKernelModules=yes disconnect mount propagation --- Makefile.am | 1 + src/test/test-execute.c | 5 +++-- .../exec-protectkernelmodules-yes-mount-propagation.service | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service diff --git a/Makefile.am b/Makefile.am index 1ea25bb688..4a69236090 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1641,6 +1641,7 @@ EXTRA_DIST += \ test/test-execute/exec-privatedevices-yes-capability-mknod.service \ test/test-execute/exec-protectkernelmodules-no-capabilities.service \ test/test-execute/exec-protectkernelmodules-yes-capabilities.service \ + test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service \ test/test-execute/exec-privatetmp-no.service \ test/test-execute/exec-privatetmp-yes.service \ test/test-execute/exec-readonlypaths.service \ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 1eade98ed3..e8ff02adaf 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -144,7 +144,7 @@ static void test_exec_privatedevices_capabilities(Manager *m) { test(m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED); } -static void test_exec_protectkernelmodules_capabilities(Manager *m) { +static void test_exec_protectkernelmodules(Manager *m) { if (detect_container() > 0) { log_notice("testing in container, skipping protectkernelmodules tests"); return; @@ -152,6 +152,7 @@ static void test_exec_protectkernelmodules_capabilities(Manager *m) { test(m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED); test(m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED); + test(m, "exec-protectkernelmodules-yes-mount-propagation.service", 0, CLD_EXITED); } static void test_exec_readonlypaths(Manager *m) { @@ -380,7 +381,7 @@ int main(int argc, char *argv[]) { test_exec_privatetmp, test_exec_privatedevices, test_exec_privatedevices_capabilities, - test_exec_protectkernelmodules_capabilities, + test_exec_protectkernelmodules, test_exec_readonlypaths, test_exec_readwritepaths, test_exec_inaccessiblepaths, diff --git a/test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service b/test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service new file mode 100644 index 0000000000..e438783df3 --- /dev/null +++ b/test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test to make sure that passing ProtectKernelModules=yes disconnect mount propagation + +[Service] +ProtectKernelModules=yes +ExecStart=/bin/sh -x -c 'mkdir -p /TEST; mount -t tmpfs tmpfs /TEST; grep TEST /proc/self/mountinfo && ! grep TEST /proc/$${PPID}/mountinfo && ! grep TEST /proc/1/mountinfo' +Type=oneshot -- cgit v1.2.3-54-g00ecf From 63b0a24b5639d4eade5e85641dfd660fbc974322 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 12 Oct 2016 14:41:56 +0100 Subject: hwdb: Treat Latitude 2110 brightness keys like on Inspiron 1520 (#4355) Like the Inspiron 1520, the Dell Latitude 2110 emits brightness-control key events both through atkbd and acpi-video. This suppresses them on the atkbd side. --- hwdb/60-keyboard.hwdb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb index f7d5ac58d4..9c87aecd30 100644 --- a/hwdb/60-keyboard.hwdb +++ b/hwdb/60-keyboard.hwdb @@ -238,8 +238,9 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1110:pvr* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1210:pvr* KEYBOARD_KEY_84=wlan -# Dell Inspiron 1520 +# Dell Inspiron 1520 and Latitude 2110 evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1520:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*2110:pvr* KEYBOARD_KEY_85=unknown # Brightness Down, also emitted by acpi-video, ignore KEYBOARD_KEY_86=unknown # Brightness Up, also emitted by acpi-video, ignore -- cgit v1.2.3-54-g00ecf From 95cbf84564d30a771f51f76e03ce1edf4349fd20 Mon Sep 17 00:00:00 2001 From: Felipe Sateler Date: Wed, 12 Oct 2016 11:20:46 -0300 Subject: systemd-user: add pam_unix account module Otherwise systemd-user@ fails because systemd validates the account Fixes: #4342 --- src/login/systemd-user.m4 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/login/systemd-user.m4 b/src/login/systemd-user.m4 index fe38b24fef..e33963b125 100644 --- a/src/login/systemd-user.m4 +++ b/src/login/systemd-user.m4 @@ -2,6 +2,8 @@ # # Used by systemd --user instances. +account required pam_unix.so + m4_ifdef(`HAVE_SELINUX', session required pam_selinux.so close session required pam_selinux.so nottys open -- cgit v1.2.3-54-g00ecf From ec02a6c90a5d8b234db534ce3f8f1901f8532057 Mon Sep 17 00:00:00 2001 From: hese10 Date: Wed, 12 Oct 2016 19:40:28 +0300 Subject: Avoid forever loop for journalctl --list-boots command (#4278) When date is changed in system to future and normal user logs to new journal file, and then date is changed back to present time, the "journalctl --list-boot" command goes to forever loop. This commit tries to fix this problem by checking first the boot id list if the found boot id was already in that list. If it is found, then stopping the boot id find loop. --- src/journal/journalctl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 4350925fb0..13e3b44f06 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -1112,7 +1112,7 @@ static int get_boots( bool skip_once; int r, count = 0; - BootId *head = NULL, *tail = NULL; + BootId *head = NULL, *tail = NULL, *id; const bool advance_older = boot_id && offset <= 0; sd_id128_t previous_boot_id; @@ -1203,6 +1203,13 @@ static int get_boots( break; } } else { + LIST_FOREACH(boot_list, id, head) { + if (sd_id128_equal(id->id, current->id)) { + /* boot id already stored, something wrong with the journal files */ + /* exiting as otherwise this problem would cause forever loop */ + goto finish; + } + } LIST_INSERT_AFTER(boot_list, head, tail, current); tail = current; current = NULL; -- cgit v1.2.3-54-g00ecf From 651742d8ecd62d718080329fbba805bf364e6c25 Mon Sep 17 00:00:00 2001 From: Felipe Sateler Date: Wed, 12 Oct 2016 11:56:27 -0300 Subject: build-sys: Allow disabling installation of pam config snippet --- DISTRO_PORTING | 3 +++ Makefile.am | 2 ++ configure.ac | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/DISTRO_PORTING b/DISTRO_PORTING index 9f61bd6de6..51a244389d 100644 --- a/DISTRO_PORTING +++ b/DISTRO_PORTING @@ -48,6 +48,9 @@ PAM: /etc/security/limits.conf will not be read unless you load pam_limits. Make sure you add modules your distro expects from user services. + Pass --with-pamconfdir=no to ./configure to avoid installing this file + and instead install your own. + CONTRIBUTING UPSTREAM: We generally do no longer accept distribution-specific diff --git a/Makefile.am b/Makefile.am index b09b0cf167..e740512f98 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5902,8 +5902,10 @@ pam_systemd_la_LIBADD = \ pamlib_LTLIBRARIES = \ pam_systemd.la +if ENABLE_PAM_CONFIG dist_pamconf_DATA = \ src/login/systemd-user +endif EXTRA_DIST += \ src/login/systemd-user.m4 diff --git a/configure.ac b/configure.ac index ccd212ef13..0e87adc38f 100644 --- a/configure.ac +++ b/configure.ac @@ -1507,9 +1507,10 @@ AC_ARG_WITH([pamlibdir], AX_NORMALIZE_PATH([with_pamlibdir]) AC_ARG_WITH([pamconfdir], - AS_HELP_STRING([--with-pamconfdir=DIR], [Directory for PAM configuration]), + AS_HELP_STRING([--with-pamconfdir=DIR], [Directory for PAM configuration (pass no to disable installing)]), [], [with_pamconfdir=${sysconfdir}/pam.d]) +AM_CONDITIONAL(ENABLE_PAM_CONFIG, [test "$with_pamconfdir" != "no"]) AX_NORMALIZE_PATH([with_pamconfdir]) AC_ARG_ENABLE([split-usr], -- cgit v1.2.3-54-g00ecf From 202fd896e516bbd7379bf2e2bcc224d3ec2356cd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Oct 2016 19:12:41 +0200 Subject: journal: when we encounter a broken journal file, add some debug logging Let's make it easier to figure out when we see an invalid journal file, why we consider it invalid, and add some minimal debug logging for it. This log output is normally not seen (after all, this all is library code), unless debug logging is exlicitly turned on. --- src/journal/journal-file.c | 24 ++++++++++++++++++------ src/journal/journalctl.c | 4 +++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 349ef74e81..953f4e5ce6 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -747,12 +747,16 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset assert(ret); /* Objects may only be located at multiple of 64 bit */ - if (!VALID64(offset)) + if (!VALID64(offset)) { + log_debug("Attempt to move to object at non-64bit boundary: %" PRIu64, offset); return -EBADMSG; + } /* Object may not be located in the file header */ - if (offset < le64toh(f->header->header_size)) + if (offset < le64toh(f->header->header_size)) { + log_debug("Attempt to move to object located in file header: %" PRIu64, offset); return -EBADMSG; + } r = journal_file_move_to(f, type, false, offset, sizeof(ObjectHeader), &t); if (r < 0) @@ -761,17 +765,25 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset o = (Object*) t; s = le64toh(o->object.size); - if (s < sizeof(ObjectHeader)) + if (s < sizeof(ObjectHeader)) { + log_debug("Attempt to move to overly short object: %" PRIu64, offset); return -EBADMSG; + } - if (o->object.type <= OBJECT_UNUSED) + if (o->object.type <= OBJECT_UNUSED) { + log_debug("Attempt to move to object with invalid type: %" PRIu64, offset); return -EBADMSG; + } - if (s < minimum_header_size(o)) + if (s < minimum_header_size(o)) { + log_debug("Attempt to move to truncated object: %" PRIu64, offset); return -EBADMSG; + } - if (type > OBJECT_UNUSED && o->object.type != type) + if (type > OBJECT_UNUSED && o->object.type != type) { + log_debug("Attempt to move to object of unexpected type: %" PRIu64, offset); return -EBADMSG; + } if (s > sizeof(ObjectHeader)) { r = journal_file_move_to(f, type, false, offset, s, &t); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 13e3b44f06..f753435888 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -1091,8 +1091,10 @@ static int discover_next_boot(sd_journal *j, r = sd_journal_previous(j); if (r < 0) return r; - else if (r == 0) + else if (r == 0) { + log_debug("Whoopsie! We found a boot ID but can't read its last entry."); return -ENODATA; /* This shouldn't happen. We just came from this very boot ID. */ + } r = sd_journal_get_realtime_usec(j, &next_boot->last); if (r < 0) -- cgit v1.2.3-54-g00ecf From aa598ba5b63b70273d6295fce3cb8c304716a205 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 11:54:36 +0200 Subject: journal: split out array index inc/dec code into a new call bump_array_index() This allows us to share a bit more code between journal_file_next_entry() and journal_file_next_entry_for_data(). --- src/journal/journal-file.c | 48 ++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 953f4e5ce6..8e47ebb944 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -2484,6 +2484,25 @@ int journal_file_compare_locations(JournalFile *af, JournalFile *bf) { return 0; } +static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) { + + /* Increase or decrease the specified index, in the right direction. */ + + if (direction == DIRECTION_DOWN) { + if (*i >= n - 1) + return 0; + + (*i) ++; + } else { + if (*i <= 0) + return 0; + + (*i) --; + } + + return 1; +} + int journal_file_next_entry( JournalFile *f, uint64_t p, @@ -2514,17 +2533,9 @@ int journal_file_next_entry( if (r <= 0) return r; - if (direction == DIRECTION_DOWN) { - if (i >= n - 1) - return 0; - - i++; - } else { - if (i <= 0) - return 0; - - i--; - } + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; } /* And jump to it */ @@ -2594,18 +2605,9 @@ int journal_file_next_entry_for_data( if (r <= 0) return r; - if (direction == DIRECTION_DOWN) { - if (i >= n - 1) - return 0; - - i++; - } else { - if (i <= 0) - return 0; - - i--; - } - + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; } return generic_array_get_plus_one(f, -- cgit v1.2.3-54-g00ecf From b6da4ed0450ced53a911d974c8b1da6ad9ff212a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 12:12:05 +0200 Subject: journal: split out check for properly ordered arrays into its own function This adds a new call check_properly_ordered(), which we can reuse later, and makes the code a bit more readable. --- src/journal/journal-file.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 8e47ebb944..52562cd0b8 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -2503,6 +2503,18 @@ static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) { return 1; } +static bool check_properly_ordered(uint64_t new_offset, uint64_t old_offset, direction_t direction) { + + /* Consider it an error if any of the two offsets is uninitialized */ + if (old_offset == 0 || new_offset == 0) + return false; + + /* If we go down, the new offset must be larger than the old one. */ + return direction == DIRECTION_DOWN ? + new_offset > old_offset : + new_offset < old_offset; +} + int journal_file_next_entry( JournalFile *f, uint64_t p, @@ -2552,9 +2564,9 @@ int journal_file_next_entry( if (r <= 0) return r; - if (p > 0 && - (direction == DIRECTION_DOWN ? ofs <= p : ofs >= p)) { - log_debug("%s: entry array corrupted at entry %" PRIu64, f->path, i); + /* Ensure our array is properly ordered. */ + if (p > 0 && !check_properly_ordered(ofs, p, direction)) { + log_debug("%s: entry array not properly ordered at entry %" PRIu64, f->path, i); return -EBADMSG; } -- cgit v1.2.3-54-g00ecf From ded5034e7a3e7b3330bbe4f5dd13ca994785d6cb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 12:12:58 +0200 Subject: journal: also check that our entry arrays are properly ordered Let's and extra check, reusing check_properly_ordered() also for journal_file_next_entry_for_data(). --- src/journal/journal-file.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 52562cd0b8..f59858277e 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -2583,7 +2583,7 @@ int journal_file_next_entry_for_data( direction_t direction, Object **ret, uint64_t *offset) { - uint64_t n, i; + uint64_t i, n, ofs; int r; Object *d; @@ -2622,11 +2622,24 @@ int journal_file_next_entry_for_data( return r; } - return generic_array_get_plus_one(f, - le64toh(d->data.entry_offset), - le64toh(d->data.entry_array_offset), - i, - ret, offset); + r = generic_array_get_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + i, + ret, &ofs); + if (r <= 0) + return r; + + /* Ensure our array is properly ordered. */ + if (p > 0 && check_properly_ordered(ofs, p, direction)) { + log_debug("%s data entry array not properly ordered at entry %" PRIu64, f->path, i); + return -EBADMSG; + } + + if (offset) + *offset = ofs; + + return 1; } int journal_file_move_to_entry_by_offset_for_data( -- cgit v1.2.3-54-g00ecf From 1c69f0966a86e3c9ae0120e6222709414b68e186 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 12:22:57 +0200 Subject: journal: add an explicit check for uninitialized objects Let's make dissecting of borked journal files more expressive: if we encounter an object whose first 8 bytes are all zeroes, then let's assume the object was simply never initialized, and say so. Previously, this would be detected as "overly short object", which is true too in a away, but it's a lot more helpful printing different debug options for the case where the size is not initialized at all and where the size is initialized to some bogus value. No function behaviour change, only a different log messages for both cases. --- src/journal/journal-file.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index f59858277e..3f1afdaf1f 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -765,6 +765,10 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset o = (Object*) t; s = le64toh(o->object.size); + if (s == 0) { + log_debug("Attempt to move to uninitialized object: %" PRIu64, offset); + return -EBADMSG; + } if (s < sizeof(ObjectHeader)) { log_debug("Attempt to move to overly short object: %" PRIu64, offset); return -EBADMSG; -- cgit v1.2.3-54-g00ecf From 989793d341e730f452175fa18cf0f7ef4529d62c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 12:36:01 +0200 Subject: journal: when iterating through entry arrays and we hit an invalid one keep going When iterating through partially synced journal files we need to be prepared for hitting with invalid entries (specifically: non-initialized). Instead of generated an error and giving up, let's simply try to preceed with the next one that is valid (and debug log about this). This reworks the logic introduced with caeab8f626e709569cc492b75eb7e119076059e7 to iteration in both directions, and tries to look for valid entries located after the invalid one. It also extends the behaviour to both iterating through the global entry array and per-data object entry arrays. Fixes: #4088 --- src/journal/journal-file.c | 54 ++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 3f1afdaf1f..e26c8223d8 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -2555,18 +2555,24 @@ int journal_file_next_entry( } /* And jump to it */ - r = generic_array_get(f, - le64toh(f->header->entry_array_offset), - i, - ret, &ofs); - if (r == -EBADMSG && direction == DIRECTION_DOWN) { - /* Special case: when we iterate throught the journal file linearly, and hit an entry we can't read, - * consider this the end of the journal file. */ - log_debug_errno(r, "Encountered entry we can't read while iterating through journal file. Considering this the end of the file."); - return 0; + for (;;) { + r = generic_array_get(f, + le64toh(f->header->entry_array_offset), + i, + ret, &ofs); + if (r > 0) + break; + if (r != -EBADMSG) + return r; + + /* OK, so this entry is borked. Most likely some entry didn't get synced to disk properly, let's see if + * the next one might work for us instead. */ + log_debug_errno(r, "Entry item %" PRIu64 " is bad, skipping over it.", i); + + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; } - if (r <= 0) - return r; /* Ensure our array is properly ordered. */ if (p > 0 && !check_properly_ordered(ofs, p, direction)) { @@ -2588,8 +2594,8 @@ int journal_file_next_entry_for_data( Object **ret, uint64_t *offset) { uint64_t i, n, ofs; - int r; Object *d; + int r; assert(f); assert(p > 0 || !o); @@ -2626,13 +2632,23 @@ int journal_file_next_entry_for_data( return r; } - r = generic_array_get_plus_one(f, - le64toh(d->data.entry_offset), - le64toh(d->data.entry_array_offset), - i, - ret, &ofs); - if (r <= 0) - return r; + for (;;) { + r = generic_array_get_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + i, + ret, &ofs); + if (r > 0) + break; + if (r != -EBADMSG) + return r; + + log_debug_errno(r, "Data entry item %" PRIu64 " is bad, skipping over it.", i); + + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; + } /* Ensure our array is properly ordered. */ if (p > 0 && check_properly_ordered(ofs, p, direction)) { -- cgit v1.2.3-54-g00ecf From 0f972d66d439789afacbbcfba9a786965dd9e4b3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 18:46:07 +0200 Subject: journald: use the event loop dispatch timestamp for journal entries Let's use the earliest linearized event timestamp for journal entries we have: the event dispatch timestamp from the event loop, instead of requerying the timestamp at the time of writing. This makes the time a bit more accurate, allows us to query the kernel time one time less per event loop, and also makes sure we always use the same timestamp for both attempts to write an entry to a journal file. --- src/journal/journald-server.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index f01cf1d937..7227c80c86 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -627,14 +627,21 @@ static bool shall_try_append_again(JournalFile *f, int r) { } static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) { - JournalFile *f; + struct dual_timestamp ts; bool vacuumed = false; + JournalFile *f; int r; assert(s); assert(iovec); assert(n > 0); + /* Get the closest, linearized time we have for this log event from the event loop. (Note that we do not use + * the source time, and not even the time the event was originally seen, but instead simply the time we started + * processing it, as we want strictly linear ordering in what we write out.) */ + assert_se(sd_event_now(s->event, CLOCK_REALTIME, &ts.realtime) >= 0); + assert_se(sd_event_now(s->event, CLOCK_MONOTONIC, &ts.monotonic) >= 0); + f = find_journal(s, uid); if (!f) return; @@ -650,7 +657,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned return; } - r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL); + r = journal_file_append_entry(f, &ts, iovec, n, &s->seqnum, NULL, NULL); if (r >= 0) { server_schedule_sync(s, priority); return; @@ -669,7 +676,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned return; log_debug("Retrying write."); - r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL); + r = journal_file_append_entry(f, &ts, iovec, n, &s->seqnum, NULL, NULL); if (r < 0) log_error_errno(r, "Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n)); else -- cgit v1.2.3-54-g00ecf From 7c07001711ee1f0aa7a3db7b63b354a4800cadcc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 18:49:51 +0200 Subject: journald: automatically rotate journal files when the clock jumps backwards As soon as we notice that the clock jumps backwards, rotate journal files. This is beneficial, as this makes sure that the entries in journal files remain strictly ordered internally, and thus the bisection algorithm applied on it is not confused. This should help avoiding borked wallclock-based bisection on journal files as witnessed in #4278. --- src/journal/journald-server.c | 29 +++++++++++++++++++++++------ src/journal/journald-server.h | 2 ++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 7227c80c86..28aea35d18 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -627,8 +627,8 @@ static bool shall_try_append_again(JournalFile *f, int r) { } static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) { + bool vacuumed = false, rotate = false; struct dual_timestamp ts; - bool vacuumed = false; JournalFile *f; int r; @@ -642,12 +642,27 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned assert_se(sd_event_now(s->event, CLOCK_REALTIME, &ts.realtime) >= 0); assert_se(sd_event_now(s->event, CLOCK_MONOTONIC, &ts.monotonic) >= 0); - f = find_journal(s, uid); - if (!f) - return; + if (ts.realtime < s->last_realtime_clock) { + /* When the time jumps backwards, let's immediately rotate. Of course, this should not happen during + * regular operation. However, when it does happen, then we should make sure that we start fresh files + * to ensure that the entries in the journal files are strictly ordered by time, in order to ensure + * bisection works correctly. */ - if (journal_file_rotate_suggested(f, s->max_file_usec)) { - log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path); + log_debug("Time jumped backwards, rotating."); + rotate = true; + } else { + + f = find_journal(s, uid); + if (!f) + return; + + if (journal_file_rotate_suggested(f, s->max_file_usec)) { + log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path); + rotate = true; + } + } + + if (rotate) { server_rotate(s); server_vacuum(s, false, false); vacuumed = true; @@ -657,6 +672,8 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned return; } + s->last_realtime_clock = ts.realtime; + r = journal_file_append_entry(f, &ts, iovec, n, &s->seqnum, NULL, NULL); if (r >= 0) { server_schedule_sync(s, priority); diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index dfb5724794..cc68a0a690 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -149,6 +149,8 @@ struct Server { char *cgroup_root; usec_t watchdog_usec; + + usec_t last_realtime_clock; }; #define SERVER_MACHINE_ID(s) ((s)->machine_id_field + strlen("_MACHINE_ID=")) -- cgit v1.2.3-54-g00ecf From ae739cc1edc7cfa9d1afb4b7087c434aadf61a7a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 18:53:35 +0200 Subject: journal: refuse opening journal files from the future for writing Never permit that we write to journal files that have newer timestamps than our local wallclock has. If we'd accept that, then the entries in the file might end up not being ordered strictly. Let's refuse this with ETXTBSY, and then immediately rotate to use a new file, so that each file remains strictly ordered also be wallclock internally. --- src/journal/journal-file.c | 13 +++++++++++-- src/journal/journald-server.c | 12 ++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index e26c8223d8..49199b269f 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -568,8 +568,8 @@ static int journal_file_verify_header(JournalFile *f) { return -ENODATA; if (f->writable) { - uint8_t state; sd_id128_t machine_id; + uint8_t state; int r; r = sd_id128_get_machine(&machine_id); @@ -590,6 +590,14 @@ static int journal_file_verify_header(JournalFile *f) { log_debug("Journal file %s has unknown state %i.", f->path, state); return -EBUSY; } + + /* Don't permit appending to files from the future. Because otherwise the realtime timestamps wouldn't + * be strictly ordered in the entries in the file anymore, and we can't have that since it breaks + * bisection. */ + if (le64toh(f->header->tail_entry_realtime) > now(CLOCK_REALTIME)) { + log_debug("Journal file %s is from the future, refusing to append new data to it that'd be older.", f->path); + return -ETXTBSY; + } } f->compress_xz = JOURNAL_HEADER_COMPRESSED_XZ(f->header); @@ -3330,7 +3338,8 @@ int journal_file_open_reliably( -EBUSY, /* unclean shutdown */ -ESHUTDOWN, /* already archived */ -EIO, /* IO error, including SIGBUS on mmap */ - -EIDRM /* File has been deleted */)) + -EIDRM, /* File has been deleted */ + -ETXTBSY)) /* File is from the future */ return r; if ((flags & O_ACCMODE) == O_RDONLY) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 28aea35d18..3224bdbf5f 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -595,32 +595,44 @@ static void server_cache_hostname(Server *s) { static bool shall_try_append_again(JournalFile *f, int r) { switch(r) { + case -E2BIG: /* Hit configured limit */ case -EFBIG: /* Hit fs limit */ case -EDQUOT: /* Quota limit hit */ case -ENOSPC: /* Disk full */ log_debug("%s: Allocation limit reached, rotating.", f->path); return true; + case -EIO: /* I/O error of some kind (mmap) */ log_warning("%s: IO error, rotating.", f->path); return true; + case -EHOSTDOWN: /* Other machine */ log_info("%s: Journal file from other machine, rotating.", f->path); return true; + case -EBUSY: /* Unclean shutdown */ log_info("%s: Unclean shutdown, rotating.", f->path); return true; + case -EPROTONOSUPPORT: /* Unsupported feature */ log_info("%s: Unsupported feature, rotating.", f->path); return true; + case -EBADMSG: /* Corrupted */ case -ENODATA: /* Truncated */ case -ESHUTDOWN: /* Already archived */ log_warning("%s: Journal file corrupted, rotating.", f->path); return true; + case -EIDRM: /* Journal file has been deleted */ log_warning("%s: Journal file has been deleted, rotating.", f->path); return true; + + case -ETXTBSY: /* Journal file is from the future */ + log_warning("%s: Journal file is from the future, rotateing.", f->path); + return true; + default: return false; } -- cgit v1.2.3-54-g00ecf From 8da830bca9f3b3fb34b1538dba70455749238fe0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 20:20:53 +0200 Subject: journalctl: don't claim the journal was stored on disk Let's just say that the journal takes up space in the file system, not on disk, as tmpfs is definitely a file system, but not a disk. Fixes: #4059 --- src/journal/journalctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index f753435888..7f997487b4 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -2266,7 +2266,7 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - printf("Archived and active journals take up %s on disk.\n", + printf("Archived and active journals take up %s in the file system.\n", format_bytes(sbytes, sizeof(sbytes), bytes)); goto finish; } -- cgit v1.2.3-54-g00ecf From 3cc44bf91babddb667c877706e29c927c27ebb62 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 20:23:43 +0200 Subject: journalctl: say in which directory we vacuum stuff Fixes: #4060 --- src/journal/journal-vacuum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c index f09dc66e03..12ce2fd56c 100644 --- a/src/journal/journal-vacuum.c +++ b/src/journal/journal-vacuum.c @@ -343,7 +343,7 @@ finish: free(list[i].filename); free(list); - log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals on disk.", format_bytes(sbytes, sizeof(sbytes), freed)); + log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals from %s.", format_bytes(sbytes, sizeof(sbytes), freed), directory); return r; } -- cgit v1.2.3-54-g00ecf From da597d2b5279f1a09943182075e430cf9a88a226 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Oct 2016 20:33:33 +0200 Subject: update TODO --- TODO | 9 --------- 1 file changed, 9 deletions(-) diff --git a/TODO b/TODO index b4443ce585..1f1c2739c5 100644 --- a/TODO +++ b/TODO @@ -40,14 +40,6 @@ Features: * switch to ProtectSystem=strict for all our long-running services where that's possible -* introduce an "invocation ID" for units, that is randomly generated, and - identifies each runtime-cycle of a unit. It should be set freshly each time - we traverse inactive → activating/active, and should be the primary key to - map offline data (stored in the journal) with online bus objects. Let's pass - this as $SYSTEMD_INVOCATION_ID to services, as well as set this as xattr on - the cgroup of a services. The former is accessible without privileges, the - latter ensures the ID cannot be faked. - * If RootDirectory= is used, mount /proc, /sys, /dev into it, if not mounted yet * Permit masking specific netlink APIs with RestrictAddressFamily= @@ -498,7 +490,6 @@ Features: message that works, but alraedy after a short tiemout - check if we can make journalctl by default use --follow mode inside of less if called without args? - maybe add API to send pairs of iovecs via sd_journal_send - - journal: when writing journal auto-rotate if time jumps backwards - journal: add a setgid "systemd-journal" utility to invoke from libsystemd-journal, which passes fds via STDOUT and does PK access - journactl: support negative filtering, i.e. FOOBAR!="waldo", and !FOOBAR for events without FOOBAR. -- cgit v1.2.3-54-g00ecf From e7f1334f07e361290f3c682565963f8c0166f132 Mon Sep 17 00:00:00 2001 From: Stefan Schweter Date: Wed, 12 Oct 2016 22:48:41 +0200 Subject: basic: use for() loop instead of while() --- src/basic/gunicode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/gunicode.c b/src/basic/gunicode.c index 542110503f..e6ac0545a4 100644 --- a/src/basic/gunicode.c +++ b/src/basic/gunicode.c @@ -26,7 +26,7 @@ char * utf8_prev_char (const char *p) { - while (1) + for (;;) { p--; if ((*p & 0xc0) != 0x80) -- cgit v1.2.3-54-g00ecf From aa7530d6817b0712c0795bbcdeffd4001ec19467 Mon Sep 17 00:00:00 2001 From: Stefan Schweter Date: Wed, 12 Oct 2016 22:49:01 +0200 Subject: coredump: use for() loop instead of while() --- src/coredump/coredump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index db60d0af7a..a982c204be 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -589,7 +589,7 @@ static int get_mount_namespace_leader(pid_t pid, pid_t *container_pid) { if (r < 0) return r; - while (1) { + for (;;) { ino_t parent_mntns; r = get_process_ppid(cpid, &ppid); -- cgit v1.2.3-54-g00ecf From 2dd678171ee38cc48880a5437eeac7732426ad7d Mon Sep 17 00:00:00 2001 From: Thomas Hindoe Paaboel Andersen Date: Wed, 12 Oct 2016 23:02:44 +0200 Subject: man: typo fixes A mix of fixes for typos and UK english --- man/logind.conf.xml | 2 +- man/sd-event.xml | 2 +- man/sd_event_source_set_priority.xml | 2 +- man/systemctl.xml | 4 ++-- man/systemd-coredump.xml | 2 +- man/systemd-mount.xml | 2 +- man/systemd-nspawn.xml | 10 +++++----- man/systemd-run.xml | 2 +- man/systemd-system.conf.xml | 2 +- man/systemd.exec.xml | 4 ++-- man/systemd.link.xml | 2 +- man/systemd.socket.xml | 2 +- man/systemd.unit.xml | 2 +- 13 files changed, 19 insertions(+), 19 deletions(-) diff --git a/man/logind.conf.xml b/man/logind.conf.xml index 9b0e181849..994e0e1140 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml @@ -261,7 +261,7 @@ Controls whether actions that systemd-logind takes when the power and sleep keys and the lid switch are triggered are subject to high-level inhibitor locks ("shutdown", "sleep", "idle"). Low level inhibitor - locks ("handle-*-key"), are always honoured, irrespective of this setting. + locks ("handle-*-key"), are always honored, irrespective of this setting. These settings take boolean arguments. If no, the inhibitor locks taken by applications are respected. If yes, diff --git a/man/sd-event.xml b/man/sd-event.xml index fc615f0906..24a69bb645 100644 --- a/man/sd-event.xml +++ b/man/sd-event.xml @@ -97,7 +97,7 @@ iteration a single event source is dispatched. Each time an event source is dispatched the kernel is polled for new events, before the next event source is dispatched. The event loop is designed to - honour priorities and provide fairness within each priority. It is + honor priorities and provide fairness within each priority. It is not designed to provide optimal throughput, as this contradicts these goals due the limitations of the underlying epoll7 diff --git a/man/sd_event_source_set_priority.xml b/man/sd_event_source_set_priority.xml index 8c9b39fe5e..6e7032fc80 100644 --- a/man/sd_event_source_set_priority.xml +++ b/man/sd_event_source_set_priority.xml @@ -115,7 +115,7 @@ reliable. However, it is guaranteed that if events are seen on multiple same-priority event sources at the same time, each one is not dispatched again until all others have been dispatched - once. This behaviour guarantees that within each priority + once. This behavior guarantees that within each priority particular event sources do not starve or dominate the event loop. diff --git a/man/systemctl.xml b/man/systemctl.xml index 3b883ea754..b51badf7fe 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -306,7 +306,7 @@ ignore-requirements is similar to ignore-dependencies, but only causes the requirement dependencies to be ignored, the ordering - dependencies will still be honoured. + dependencies will still be honored. @@ -1006,7 +1006,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service desired, combine this command with the switch, or invoke start with appropriate arguments later. Note that in case of unit instance enablement (i.e. enablement of units of the form foo@bar.service), symlinks named the same as instances are created in the - unit configuration diectory, however they point to the single template unit file they are instantiated + unit configuration directory, however they point to the single template unit file they are instantiated from. This command expects either valid unit names (in which case various unit file directories are diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml index a28dc62e5a..4a1bc8b296 100644 --- a/man/systemd-coredump.xml +++ b/man/systemd-coredump.xml @@ -107,7 +107,7 @@ systemd-sysctl8. - The behaviour of systemd-coredump itself is configured through the configuration file + The behavior of systemd-coredump itself is configured through the configuration file /etc/systemd/coredump.conf and corresponding snippets /etc/systemd/coredump.conf.d/*.conf, see coredump.conf5. A new diff --git a/man/systemd-mount.xml b/man/systemd-mount.xml index e6c07863c0..06b7c85bd8 100644 --- a/man/systemd-mount.xml +++ b/man/systemd-mount.xml @@ -260,7 +260,7 @@ The udev Database - If is used, systemd-mount honours a couple of additional udev + If is used, systemd-mount honors a couple of additional udev properties of block devices: diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index 5ac54df81a..f153034296 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -405,7 +405,7 @@ purposes (usually in the range beyond the host's UID/GID 65536). The parameter may be specified as follows: - If one or two colon-separated numers are specified, user namespacing is turned on. The first + If one or two colon-separated numbers are specified, user namespacing is turned on. The first parameter specifies the first host UID/GID to assign to the container, the second parameter specifies the number of host UIDs/GIDs to assign to the container. If the second parameter is omitted, 65536 UIDs/GIDs are assigned. @@ -425,13 +425,13 @@ range is automatically chosen. As first step, the file owner of the root directory of the container's directory tree is read, and it is checked that it is currently not used by the system otherwise (in particular, that no other container is using it). If this check is successful, the UID/GID range determined - this way is used, similar to the behaviour if "yes" is specified. If the check is not successful (and thus + this way is used, similar to the behavior if "yes" is specified. If the check is not successful (and thus the UID/GID range indicated in the root directory's file owner is already used elsewhere) a new – currently unused – UID/GID range of 65536 UIDs/GIDs is randomly chosen between the host UID/GIDs of 524288 and 1878982656, always starting at a multiple of 65536. This setting implies (see below), which has the effect that the files and directories in the container's directory tree will be owned by the appropriate users of the range picked. Using this option - makes user namespace behaviour fully automatic. Note that the first invocation of a previously unused + makes user namespace behavior fully automatic. Note that the first invocation of a previously unused container image might result in picking a new UID/GID range for it, and thus in the (possibly expensive) file ownership adjustment operation. However, subsequent invocations of the container will be cheap (unless of course the picked UID/GID range is assigned to a different use by then). @@ -440,7 +440,7 @@ It is recommended to assign at least 65536 UIDs/GIDs to each container, so that the usable UID/GID range in the container covers 16 bit. For best security, do not assign overlapping UID/GID ranges to multiple containers. It is hence a good idea to use the upper 16 bit of the host 32-bit UIDs/GIDs as container identifier, while the lower 16 - bit encode the container UID/GID used. This is in fact the behaviour enforced by the + bit encode the container UID/GID used. This is in fact the behavior enforced by the option. When user namespaces are used, the GID range assigned to each container is always chosen identical to the @@ -722,7 +722,7 @@ and the subdirectory is symlinked into the host at the same location. try-host and try-guest do the same but do not fail if - the host does not have persistent journalling enabled. If + the host does not have persistent journaling enabled. If auto (the default), and the right subdirectory of /var/log/journal exists, it will be bind mounted into the container. If the diff --git a/man/systemd-run.xml b/man/systemd-run.xml index 15f9119e54..2ad8cb0835 100644 --- a/man/systemd-run.xml +++ b/man/systemd-run.xml @@ -402,7 +402,7 @@ There is a screen on: when the user first logs in, and stays around as long as at least one login session is open. After the user logs out of the last session, user@.service and all services underneath it - are terminated. This behaviour is the default, when "lingering" is + are terminated. This behavior is the default, when "lingering" is not enabled for that user. Enabling lingering means that user@.service is started automatically during boot, even if the user is not logged in, and that the service is diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index a268397d09..1d995f143e 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -109,7 +109,7 @@ CtrlAltDelBurstAction= Defines what action will be performed - if user presses Ctr-Alt-Delete more than 7 times in 2s. + if user presses Ctrl-Alt-Delete more than 7 times in 2s. Can be set to reboot-force, poweroff-force or disabled with ignore. Defaults to reboot-force. diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 986985ad35..c088042a51 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -988,7 +988,7 @@ the unit's own user and group to themselves and everything else to the nobody user and group. This is useful to securely detach the user and group databases used by the unit from the rest of the system, and thus to create an effective sandbox environment. All files, directories, processes, IPC objects and - other resources owned by users/groups not equalling root or the unit's own will stay visible + other resources owned by users/groups not equaling root or the unit's own will stay visible from within the unit but appear owned by the nobody user and group. If this mode is enabled, all unit processes are run without privileges in the host user namespace (regardless if the unit's own user/group is root or not). Specifically this means that the process will have zero process @@ -1560,7 +1560,7 @@ $MAINPID - The PID of the units main process if it is + The PID of the unit's main process if it is known. This is only set for control processes as invoked by ExecReload= and similar. diff --git a/man/systemd.link.xml b/man/systemd.link.xml index 10fddeced0..8edbe758d9 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -107,7 +107,7 @@ A whitespace-separated list of shell-style globs matching the device name, as exposed by the udev property - "INTERFACE". This can not be used to match on names that have + "INTERFACE". This cannot be used to match on names that have already been changed from userspace. Caution is advised when matching on kernel-assigned names, as they are known to be unstable between reboots. diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index d759e17289..0ce1203cfb 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -535,7 +535,7 @@ and the kernel will ignore initial ACK packets without any data. The argument specifies the approximate amount of time the kernel should wait for incoming data before falling back - to the normal behavior of honouring empty ACK packets. This + to the normal behavior of honoring empty ACK packets. This option is beneficial for protocols where the client sends the data first (e.g. HTTP, in contrast to SMTP), because the server process will not be woken up unnecessarily before it diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 9778283fec..79bdb2cd38 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -195,7 +195,7 @@ instantiated units, this logic will first look for the instance .d/ subdirectory and read its .conf files, followed by the template .d/ subdirectory and the .conf files there. Also note that - settings from the [Install] section are not honoured in drop-in unit files, + settings from the [Install] section are not honored in drop-in unit files, and have no effect. In addition to /etc/systemd/system, the drop-in .d -- cgit v1.2.3-54-g00ecf From f0bef277a44e9285bc2da9dc39e830ab56238094 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Thu, 13 Oct 2016 16:50:46 +0300 Subject: nspawn: cleanup and chown the synced cgroup hierarchy (#4223) Fixes: #4181 --- src/basic/cgroup-util.c | 14 ++++++++++++ src/basic/cgroup-util.h | 4 ++++ src/basic/rm-rf.c | 14 ++++++++---- src/nspawn/nspawn-cgroup.c | 53 ++++++++++++++++++++++++++++++++------------- src/nspawn/nspawn-cgroup.h | 2 +- src/nspawn/nspawn.c | 2 +- src/test/test-cgroup-util.c | 25 +++++++++++++++++++++ 7 files changed, 93 insertions(+), 21 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 37e6928a46..cede835920 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -2514,6 +2514,20 @@ int cg_blkio_weight_parse(const char *s, uint64_t *ret) { return 0; } +bool is_cgroup_fs(const struct statfs *s) { + return is_fs_type(s, CGROUP_SUPER_MAGIC) || + is_fs_type(s, CGROUP2_SUPER_MAGIC); +} + +bool fd_is_cgroup_fs(int fd) { + struct statfs s; + + if (fstatfs(fd, &s) < 0) + return -errno; + + return is_cgroup_fs(&s); +} + static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = { [CGROUP_CONTROLLER_CPU] = "cpu", [CGROUP_CONTROLLER_CPUACCT] = "cpuacct", diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 7529c9719e..0aa27c4cd7 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "def.h" @@ -254,3 +255,6 @@ CGroupController cgroup_controller_from_string(const char *s) _pure_; int cg_weight_parse(const char *s, uint64_t *ret); int cg_cpu_shares_parse(const char *s, uint64_t *ret); int cg_blkio_weight_parse(const char *s, uint64_t *ret); + +bool is_cgroup_fs(const struct statfs *s); +bool fd_is_cgroup_fs(int fd); diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c index 43816fd1bb..baa70c2c8d 100644 --- a/src/basic/rm-rf.c +++ b/src/basic/rm-rf.c @@ -27,6 +27,7 @@ #include #include "btrfs-util.h" +#include "cgroup-util.h" #include "fd-util.h" #include "log.h" #include "macro.h" @@ -36,9 +37,14 @@ #include "stat-util.h" #include "string-util.h" +static bool is_physical_fs(const struct statfs *sfs) { + return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs); +} + int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { _cleanup_closedir_ DIR *d = NULL; int ret = 0, r; + struct statfs sfs; assert(fd >= 0); @@ -47,13 +53,13 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { if (!(flags & REMOVE_PHYSICAL)) { - r = fd_is_temporary_fs(fd); + r = fstatfs(fd, &sfs); if (r < 0) { safe_close(fd); - return r; + return -errno; } - if (!r) { + if (is_physical_fs(&sfs)) { /* We refuse to clean physical file systems * with this call, unless explicitly * requested. This is extra paranoia just to @@ -210,7 +216,7 @@ int rm_rf(const char *path, RemoveFlags flags) { if (statfs(path, &s) < 0) return -errno; - if (!is_temporary_fs(&s)) { + if (is_physical_fs(&s)) { log_error("Attempted to remove disk file system, and we can't allow that."); return -EPERM; } diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index 6793df1286..fd0578b85c 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -25,27 +25,18 @@ #include "mkdir.h" #include "mount-util.h" #include "nspawn-cgroup.h" +#include "rm-rf.h" #include "string-util.h" #include "strv.h" #include "util.h" -int chown_cgroup(pid_t pid, uid_t uid_shift) { - _cleanup_free_ char *path = NULL, *fs = NULL; +static int chown_cgroup_path(const char *path, uid_t uid_shift) { _cleanup_close_ int fd = -1; const char *fn; - int r; - r = cg_pid_get_path(NULL, pid, &path); - if (r < 0) - return log_error_errno(r, "Failed to get container cgroup path: %m"); - - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs); - if (r < 0) - return log_error_errno(r, "Failed to get file system path for container cgroup: %m"); - - fd = open(fs, O_RDONLY|O_CLOEXEC|O_DIRECTORY); + fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY); if (fd < 0) - return log_error_errno(errno, "Failed to open %s: %m", fs); + return -errno; FOREACH_STRING(fn, ".", @@ -63,7 +54,27 @@ int chown_cgroup(pid_t pid, uid_t uid_shift) { return 0; } -int sync_cgroup(pid_t pid, CGroupUnified unified_requested) { +int chown_cgroup(pid_t pid, uid_t uid_shift) { + _cleanup_free_ char *path = NULL, *fs = NULL; + _cleanup_close_ int fd = -1; + int r; + + r = cg_pid_get_path(NULL, pid, &path); + if (r < 0) + return log_error_errno(r, "Failed to get container cgroup path: %m"); + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs); + if (r < 0) + return log_error_errno(r, "Failed to get file system path for container cgroup: %m"); + + r = chown_cgroup_path(fs, uid_shift); + if (r < 0) + return log_error_errno(r, "Failed to chown() cgroup %s: %m", fs); + + return 0; +} + +int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t arg_uid_shift) { _cleanup_free_ char *cgroup = NULL; char tree[] = "/tmp/unifiedXXXXXX", pid_string[DECIMAL_STR_MAX(pid) + 1]; bool undo_mount = false; @@ -101,14 +112,26 @@ int sync_cgroup(pid_t pid, CGroupUnified unified_requested) { undo_mount = true; + /* If nspawn dies abruptly the cgroup hierarchy created below + * its unit isn't cleaned up. So, let's remove it + * https://github.com/systemd/systemd/pull/4223#issuecomment-252519810 */ + fn = strjoina(tree, cgroup); + (void) rm_rf(fn, REMOVE_ROOT|REMOVE_ONLY_DIRECTORIES); + fn = strjoina(tree, cgroup, "/cgroup.procs"); (void) mkdir_parents(fn, 0755); sprintf(pid_string, PID_FMT, pid); r = write_string_file(fn, pid_string, 0); - if (r < 0) + if (r < 0) { log_error_errno(r, "Failed to move process: %m"); + goto finish; + } + fn = strjoina(tree, cgroup); + r = chown_cgroup_path(fn, arg_uid_shift); + if (r < 0) + log_error_errno(r, "Failed to chown() cgroup %s: %m", fn); finish: if (undo_mount) (void) umount_verbose(tree); diff --git a/src/nspawn/nspawn-cgroup.h b/src/nspawn/nspawn-cgroup.h index dc33da8abe..fa4321ab43 100644 --- a/src/nspawn/nspawn-cgroup.h +++ b/src/nspawn/nspawn-cgroup.h @@ -25,5 +25,5 @@ #include "cgroup-util.h" int chown_cgroup(pid_t pid, uid_t uid_shift); -int sync_cgroup(pid_t pid, CGroupUnified unified_requested); +int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift); int create_subcgroup(pid_t pid, CGroupUnified unified_requested); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index d95204f71e..14af51fc0e 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3879,7 +3879,7 @@ static int run(int master, return r; } - r = sync_cgroup(*pid, arg_unified_cgroup_hierarchy); + r = sync_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift); if (r < 0) return r; diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index 43f8906172..c24c784e9b 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -24,6 +24,7 @@ #include "formats-util.h" #include "parse-util.h" #include "process-util.h" +#include "stat-util.h" #include "string-util.h" #include "test-helper.h" #include "user-util.h" @@ -309,6 +310,28 @@ static void test_mask_supported(void) { printf("'%s' is supported: %s\n", cgroup_controller_to_string(c), yes_no(m & CGROUP_CONTROLLER_TO_MASK(c))); } +static void test_is_cgroup_fs(void) { + struct statfs sfs; + assert_se(statfs("/sys/fs/cgroup", &sfs) == 0); + if (is_temporary_fs(&sfs)) + assert_se(statfs("/sys/fs/cgroup/systemd", &sfs) == 0); + assert_se(is_cgroup_fs(&sfs)); +} + +static void test_fd_is_cgroup_fs(void) { + int fd; + + fd = open("/sys/fs/cgroup", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); + assert_se(fd >= 0); + if (fd_is_temporary_fs(fd)) { + fd = safe_close(fd); + fd = open("/sys/fs/cgroup/systemd", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); + assert_se(fd >= 0); + } + assert_se(fd_is_cgroup_fs(fd)); + fd = safe_close(fd); +} + int main(void) { test_path_decode_unit(); test_path_get_unit(); @@ -324,6 +347,8 @@ int main(void) { test_slice_to_path(); test_shift_path(); TEST_REQ_RUNNING_SYSTEMD(test_mask_supported()); + TEST_REQ_RUNNING_SYSTEMD(test_is_cgroup_fs()); + TEST_REQ_RUNNING_SYSTEMD(test_fd_is_cgroup_fs()); return 0; } -- cgit v1.2.3-54-g00ecf From 5c4624e082c0c153df63c0d11e31a85c73f770b7 Mon Sep 17 00:00:00 2001 From: "Thomas H. P. Andersen" Date: Thu, 13 Oct 2016 23:30:28 +0200 Subject: nspawn: remove unused variable (#4369) --- src/nspawn/nspawn-cgroup.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index fd0578b85c..5274767b96 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -56,7 +56,6 @@ static int chown_cgroup_path(const char *path, uid_t uid_shift) { int chown_cgroup(pid_t pid, uid_t uid_shift) { _cleanup_free_ char *path = NULL, *fs = NULL; - _cleanup_close_ int fd = -1; int r; r = cg_pid_get_path(NULL, pid, &path); -- cgit v1.2.3-54-g00ecf From 7d862ab8c25d5c20eae6ed28c10c00c525c64a1f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 14 Oct 2016 21:07:16 -0400 Subject: core: make settings for unified cgroup hierarchy supersede the ones for legacy hierarchy (#4269) There are overlapping control group resource settings for the unified and legacy hierarchies. To help transition, the settings are translated back and forth. When both versions of a given setting are present, the one matching the cgroup hierarchy type in use is used. Unfortunately, this is more confusing to use and document than necessary because there is no clear static precedence. Update the translation logic so that the settings for the unified hierarchy are always preferred. systemd.resource-control man page is updated to reflect the change and reorganized so that the deprecated settings are at the end in its own section. --- man/systemd.resource-control.xml | 325 ++++++++++++++++++++------------------- src/core/cgroup.c | 60 ++++---- 2 files changed, 195 insertions(+), 190 deletions(-) diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index c11f420fe5..10aefbe0c5 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -140,10 +140,10 @@ - To ease the transition, there is best-effort translation between the two versions of settings. If all - settings of a unit for a given resource type are for the other hierarchy type, the settings are translated and - applied. If there are any valid settings for the hierarchy in use, all translations are disabled for the resource - type. Mixing the two types of settings on a unit can lead to confusing results. + To ease the transition, there is best-effort translation between the two versions of settings. For each + controller, if any of the settings for the unified hierarchy are present, all settings for the legacy hierarchy are + ignored. If the resulting settings are for the other type of hierarchy, the configurations are translated before + application. Legacy control group hierarchy (see cgroups.txt), also called cgroup-v1, @@ -196,30 +196,7 @@ Implies CPUAccounting=true. - These settings are supported only if the unified control group hierarchy is used. - - - - - CPUShares=weight - StartupCPUShares=weight - - - Assign the specified CPU time share weight to the processes executed. These options take an integer - value and control the cpu.shares control group attribute. The allowed range is 2 to - 262144. Defaults to 1024. For details about this control group attribute, see sched-design-CFS.txt. - The available CPU time is split up among all units within one slice relative to their CPU time share - weight. - - While StartupCPUShares= only applies to the startup phase of the system, - CPUShares= applies to normal runtime of the system, and if the former is not set also to - the startup phase. Using StartupCPUShares= allows prioritizing specific services at - boot-up differently than during normal runtime. - - Implies CPUAccounting=true. - - These settings are supported only if the legacy control group hierarchy is used. + These settings replace CPUShares= and StartupCPUShares=. @@ -239,8 +216,6 @@ 20% CPU time on one CPU. Implies CPUAccounting=true. - - This setting is supported on both unified and legacy control group hierarchies. @@ -276,7 +251,8 @@ Implies MemoryAccounting=true. - This setting is supported only if the unified control group hierarchy is used. + This setting is supported only if the unified control group hierarchy is used and disables + MemoryLimit=. @@ -298,7 +274,8 @@ Implies MemoryAccounting=true. - This setting is supported only if the unified control group hierarchy is used. + This setting is supported only if the unified control group hierarchy is used and disables + MemoryLimit=. @@ -320,8 +297,7 @@ Implies MemoryAccounting=true. - This setting is supported only if the unified control group hierarchy is used. Use - MemoryLimit= on systems using the legacy control group hierarchy. + This setting replaces MemoryLimit=. @@ -339,28 +315,8 @@ Implies MemoryAccounting=true. - This setting is supported only if the unified control group hierarchy is used. - - - - - MemoryLimit=bytes - - - Specify the limit on maximum memory usage of the executed processes. The limit specifies how much - process and kernel memory can be used by tasks in this unit. Takes a memory size in bytes. If the value is - suffixed with K, M, G or T, the specified memory size is parsed as Kilobytes, Megabytes, Gigabytes, or - Terabytes (with the base 1024), respectively. Alternatively, a percentage value may be specified, which is - taken relative to the installed physical memory on the system. If assigned the special value - infinity, no memory limit is applied. This controls the - memory.limit_in_bytes control group attribute. For details about this control group - attribute, see memory.txt. - - Implies MemoryAccounting=true. - - This setting is supported only if the legacy control group hierarchy is used. Use - MemoryMax= on systems using the unified control group hierarchy. + This setting is supported only if the unified control group hierarchy is used and disables + MemoryLimit=. @@ -412,8 +368,8 @@ in systemd-system.conf5. - This setting is supported only if the unified control group hierarchy is used. Use - BlockIOAccounting= on systems using the legacy control group hierarchy. + This setting replaces BlockIOAccounting= and disables settings prefixed with + BlockIO or StartupBlockIO. @@ -438,9 +394,8 @@ Implies IOAccounting=true. - This setting is supported only if the unified control group hierarchy is used. Use - BlockIOWeight= and StartupBlockIOWeight= on systems using the legacy - control group hierarchy. + These settings replace BlockIOWeight= and StartupBlockIOWeight= + and disable settings prefixed with BlockIO or StartupBlockIO. @@ -459,8 +414,8 @@ Implies IOAccounting=true. - This setting is supported only if the unified control group hierarchy is used. Use - BlockIODeviceWeight= on systems using the legacy control group hierarchy. + This setting replaces BlockIODeviceWeight= and disables settings prefixed with + BlockIO or StartupBlockIO. @@ -484,8 +439,9 @@ Implies IOAccounting=true. - This setting is supported only if the unified control group hierarchy is used. Use - BlockIOAccounting= on systems using the legacy control group hierarchy. + These settings replace BlockIOReadBandwidth= and + BlockIOWriteBandwidth= and disable settings prefixed with BlockIO or + StartupBlockIO. @@ -509,100 +465,8 @@ Implies IOAccounting=true. - This setting is supported only if the unified control group hierarchy is used. - - - - - BlockIOAccounting= - - - Turn on Block I/O accounting for this unit, if the legacy control group hierarchy is used on the - system. Takes a boolean argument. Note that turning on block I/O accounting for one unit will also implicitly - turn it on for all units contained in the same slice and all for its parent slices and the units contained - therein. The system default for this setting may be controlled with - DefaultBlockIOAccounting= in - systemd-system.conf5. - - This setting is supported only if the legacy control group hierarchy is used. Use - IOAccounting= on systems using the unified control group hierarchy. - - - - - BlockIOWeight=weight - StartupBlockIOWeight=weight - - Set the default overall block I/O weight for the executed processes, if the legacy control - group hierarchy is used on the system. Takes a single weight value (between 10 and 1000) to set the default - block I/O weight. This controls the blkio.weight control group attribute, which defaults to - 500. For details about this control group attribute, see blkio-controller.txt. - The available I/O bandwidth is split up among all units within one slice relative to their block I/O - weight. - - While StartupBlockIOWeight= only - applies to the startup phase of the system, - BlockIOWeight= applies to the later runtime - of the system, and if the former is not set also to the - startup phase. This allows prioritizing specific services at - boot-up differently than during runtime. - - Implies - BlockIOAccounting=true. - - This setting is supported only if the legacy control group hierarchy is used. Use - IOWeight= and StartupIOWeight= on systems using the unified control group - hierarchy. - - - - - - BlockIODeviceWeight=device weight - - - Set the per-device overall block I/O weight for the executed processes, if the legacy control group - hierarchy is used on the system. Takes a space-separated pair of a file path and a weight value to specify - the device specific weight value, between 10 and 1000. (Example: "/dev/sda 500"). The file path may be - specified as path to a block device node or as any other file, in which case the backing block device of the - file system of the file is determined. This controls the blkio.weight_device control group - attribute, which defaults to 1000. Use this option multiple times to set weights for multiple devices. For - details about this control group attribute, see blkio-controller.txt. - - Implies - BlockIOAccounting=true. - - This setting is supported only if the legacy control group hierarchy is used. Use - IODeviceWeight= on systems using the unified control group hierarchy. - - - - - BlockIOReadBandwidth=device bytes - BlockIOWriteBandwidth=device bytes - - - Set the per-device overall block I/O bandwidth limit for the executed processes, if the legacy control - group hierarchy is used on the system. Takes a space-separated pair of a file path and a bandwidth value (in - bytes per second) to specify the device specific bandwidth. The file path may be a path to a block device - node, or as any other file in which case the backing block device of the file system of the file is used. If - the bandwidth is suffixed with K, M, G, or T, the specified bandwidth is parsed as Kilobytes, Megabytes, - Gigabytes, or Terabytes, respectively, to the base of 1000. (Example: - "/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0 5M"). This controls the - blkio.throttle.read_bps_device and blkio.throttle.write_bps_device - control group attributes. Use this option multiple times to set bandwidth limits for multiple devices. For - details about these control group attributes, see blkio-controller.txt. - - - Implies - BlockIOAccounting=true. - - This setting is supported only if the legacy control group hierarchy is used. Use - IOReadBandwidthMax= and IOWriteBandwidthMax= on systems using the - unified control group hierarchy. + These settings are supported only if the unified control group hierarchy is used and disable settings + prefixed with BlockIO or StartupBlockIO. @@ -733,6 +597,149 @@ + + Deprecated Options + + The following options are deprecated. Use the indicated superseding options instead: + + + + + CPUShares=weight + StartupCPUShares=weight + + + Assign the specified CPU time share weight to the processes executed. These options take an integer + value and control the cpu.shares control group attribute. The allowed range is 2 to + 262144. Defaults to 1024. For details about this control group attribute, see sched-design-CFS.txt. + The available CPU time is split up among all units within one slice relative to their CPU time share + weight. + + While StartupCPUShares= only applies to the startup phase of the system, + CPUShares= applies to normal runtime of the system, and if the former is not set also to + the startup phase. Using StartupCPUShares= allows prioritizing specific services at + boot-up differently than during normal runtime. + + Implies CPUAccounting=true. + + These settings are deprecated. Use CPUWeight= and + StartupCPUWeight= instead. + + + + + MemoryLimit=bytes + + + Specify the limit on maximum memory usage of the executed processes. The limit specifies how much + process and kernel memory can be used by tasks in this unit. Takes a memory size in bytes. If the value is + suffixed with K, M, G or T, the specified memory size is parsed as Kilobytes, Megabytes, Gigabytes, or + Terabytes (with the base 1024), respectively. Alternatively, a percentage value may be specified, which is + taken relative to the installed physical memory on the system. If assigned the special value + infinity, no memory limit is applied. This controls the + memory.limit_in_bytes control group attribute. For details about this control group + attribute, see memory.txt. + + Implies MemoryAccounting=true. + + This setting is deprecated. Use MemoryMax= instead. + + + + + BlockIOAccounting= + + + Turn on Block I/O accounting for this unit, if the legacy control group hierarchy is used on the + system. Takes a boolean argument. Note that turning on block I/O accounting for one unit will also implicitly + turn it on for all units contained in the same slice and all for its parent slices and the units contained + therein. The system default for this setting may be controlled with + DefaultBlockIOAccounting= in + systemd-system.conf5. + + This setting is deprecated. Use IOAccounting= instead. + + + + + BlockIOWeight=weight + StartupBlockIOWeight=weight + + Set the default overall block I/O weight for the executed processes, if the legacy control + group hierarchy is used on the system. Takes a single weight value (between 10 and 1000) to set the default + block I/O weight. This controls the blkio.weight control group attribute, which defaults to + 500. For details about this control group attribute, see blkio-controller.txt. + The available I/O bandwidth is split up among all units within one slice relative to their block I/O + weight. + + While StartupBlockIOWeight= only + applies to the startup phase of the system, + BlockIOWeight= applies to the later runtime + of the system, and if the former is not set also to the + startup phase. This allows prioritizing specific services at + boot-up differently than during runtime. + + Implies + BlockIOAccounting=true. + + These settings are deprecated. Use IOWeight= and StartupIOWeight= + instead. + + + + + + BlockIODeviceWeight=device weight + + + Set the per-device overall block I/O weight for the executed processes, if the legacy control group + hierarchy is used on the system. Takes a space-separated pair of a file path and a weight value to specify + the device specific weight value, between 10 and 1000. (Example: "/dev/sda 500"). The file path may be + specified as path to a block device node or as any other file, in which case the backing block device of the + file system of the file is determined. This controls the blkio.weight_device control group + attribute, which defaults to 1000. Use this option multiple times to set weights for multiple devices. For + details about this control group attribute, see blkio-controller.txt. + + Implies + BlockIOAccounting=true. + + This setting is deprecated. Use IODeviceWeight= instead. + + + + + BlockIOReadBandwidth=device bytes + BlockIOWriteBandwidth=device bytes + + + Set the per-device overall block I/O bandwidth limit for the executed processes, if the legacy control + group hierarchy is used on the system. Takes a space-separated pair of a file path and a bandwidth value (in + bytes per second) to specify the device specific bandwidth. The file path may be a path to a block device + node, or as any other file in which case the backing block device of the file system of the file is used. If + the bandwidth is suffixed with K, M, G, or T, the specified bandwidth is parsed as Kilobytes, Megabytes, + Gigabytes, or Terabytes, respectively, to the base of 1000. (Example: + "/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0 5M"). This controls the + blkio.throttle.read_bps_device and blkio.throttle.write_bps_device + control group attributes. Use this option multiple times to set bandwidth limits for multiple devices. For + details about these control group attributes, see blkio-controller.txt. + + + Implies + BlockIOAccounting=true. + + These settings are deprecated. Use IOReadBandwidthMax= and + IOWriteBandwidthMax= instead. + + + + + + See Also diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 20bdbc39d0..23a92f9651 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -687,16 +687,16 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { } else { uint64_t shares; - if (has_shares) - shares = cgroup_context_cpu_shares(c, state); - else if (has_weight) { + if (has_weight) { uint64_t weight = cgroup_context_cpu_weight(c, state); shares = cgroup_cpu_weight_to_shares(weight); log_cgroup_compat(u, "Applying [Startup]CpuWeight %" PRIu64 " as [Startup]CpuShares %" PRIu64 " on %s", weight, shares, path); - } else + } else if (has_shares) + shares = cgroup_context_cpu_shares(c, state); + else shares = CGROUP_CPU_SHARES_DEFAULT; cgroup_apply_legacy_cpu_config(u, shares, c->cpu_quota_per_sec_usec); @@ -788,16 +788,16 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { char buf[DECIMAL_STR_MAX(uint64_t)+1]; uint64_t weight; - if (has_blockio) - weight = cgroup_context_blkio_weight(c, state); - else if (has_io) { + if (has_io) { uint64_t io_weight = cgroup_context_io_weight(c, state); weight = cgroup_weight_io_to_blkio(cgroup_context_io_weight(c, state)); log_cgroup_compat(u, "Applying [Startup]IOWeight %" PRIu64 " as [Startup]BlockIOWeight %" PRIu64, io_weight, weight); - } else + } else if (has_blockio) + weight = cgroup_context_blkio_weight(c, state); + else weight = CGROUP_BLKIO_WEIGHT_DEFAULT; xsprintf(buf, "%" PRIu64 "\n", weight); @@ -806,13 +806,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to set blkio.weight: %m"); - if (has_blockio) { - CGroupBlockIODeviceWeight *w; - - /* FIXME: no way to reset this list */ - LIST_FOREACH(device_weights, w, c->blockio_device_weights) - cgroup_apply_blkio_device_weight(u, w->path, w->weight); - } else if (has_io) { + if (has_io) { CGroupIODeviceWeight *w; /* FIXME: no way to reset this list */ @@ -824,18 +818,17 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { cgroup_apply_blkio_device_weight(u, w->path, weight); } + } else if (has_blockio) { + CGroupBlockIODeviceWeight *w; + + /* FIXME: no way to reset this list */ + LIST_FOREACH(device_weights, w, c->blockio_device_weights) + cgroup_apply_blkio_device_weight(u, w->path, w->weight); } } /* Apply limits and free ones without config. */ - if (has_blockio) { - CGroupBlockIODeviceBandwidth *b, *next; - - LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths) { - if (!cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps)) - cgroup_context_free_blockio_device_bandwidth(c, b); - } - } else if (has_io) { + if (has_io) { CGroupIODeviceLimit *l, *next; LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) { @@ -845,13 +838,19 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { if (!cgroup_apply_blkio_device_limit(u, l->path, l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX])) cgroup_context_free_io_device_limit(c, l); } + } else if (has_blockio) { + CGroupBlockIODeviceBandwidth *b, *next; + + LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths) + if (!cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps)) + cgroup_context_free_blockio_device_bandwidth(c, b); } } if ((mask & CGROUP_MASK_MEMORY) && !is_root) { if (cg_all_unified() > 0) { - uint64_t max = c->memory_max; - uint64_t swap_max = c->memory_swap_max; + uint64_t max; + uint64_t swap_max = CGROUP_LIMIT_MAX; if (cgroup_context_has_unified_memory_config(c)) { max = c->memory_max; @@ -869,14 +868,13 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) { cgroup_apply_unified_memory_limit(u, "memory.swap.max", swap_max); } else { char buf[DECIMAL_STR_MAX(uint64_t) + 1]; - uint64_t val = c->memory_limit; + uint64_t val; - if (val == CGROUP_LIMIT_MAX) { + if (cgroup_context_has_unified_memory_config(c)) { val = c->memory_max; - - if (val != CGROUP_LIMIT_MAX) - log_cgroup_compat(u, "Applying MemoryMax %" PRIi64 " as MemoryLimit", c->memory_max); - } + log_cgroup_compat(u, "Applying MemoryMax %" PRIi64 " as MemoryLimit", val); + } else + val = c->memory_limit; if (val == CGROUP_LIMIT_MAX) strncpy(buf, "-1\n", sizeof(buf)); -- cgit v1.2.3-54-g00ecf From 579a2ab3d65a2908afef5578af26793e80898d55 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Sat, 15 Oct 2016 12:11:03 -0400 Subject: hwdb: Add sensitivity for Dell Latitude E7470 pointingstick --- hwdb/70-pointingstick.hwdb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index 2b30896dff..e18ef28290 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -87,6 +87,10 @@ evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320*:pvr* evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6400*:pvr* POINTINGSTICK_CONST_ACCEL=1.5 +# Latitude E7470 +evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470*:pvr* + POINTINGSTICK_CONST_ACCEL=0.6 + ######################################### # Lenovo ######################################### -- cgit v1.2.3-54-g00ecf From 08a28eeca70eeefb55af61191b63e4c938daca73 Mon Sep 17 00:00:00 2001 From: Lukáš Nykrýn Date: Sat, 15 Oct 2016 19:54:58 +0200 Subject: virt: add possibility to skip the check for chroot (#4374) https://bugzilla.redhat.com/show_bug.cgi?id=1379852 --- src/basic/virt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/basic/virt.c b/src/basic/virt.c index 10a2043746..41012d52a0 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -33,6 +33,7 @@ #include "string-table.h" #include "string-util.h" #include "virt.h" +#include "env-util.h" static int detect_vm_cpuid(void) { @@ -487,6 +488,9 @@ int detect_virtualization(void) { int running_in_chroot(void) { int ret; + if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0) + return 0; + ret = files_same("/proc/1/root", "/"); if (ret < 0) return ret; -- cgit v1.2.3-54-g00ecf From 74b47bbd5d4770c68e0eb448cc157414288ce60d Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 15 Oct 2016 14:17:05 -0400 Subject: man: add crosslink between systemd.resource-control(5) and systemd.exec(5) Fixes #4379. --- man/systemd.exec.xml | 5 +++++ man/systemd.resource-control.xml | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 71dc86ec2f..6228b786f7 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -74,6 +74,11 @@ execution specific configuration options are configured in the [Service], [Socket], [Mount], or [Swap] sections, depending on the unit type. + + In addition, options which control resources through cgroups + are listed in + systemd.resource-control5. + Those options complement options listed here. diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index 10aefbe0c5..a97bcca9df 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -83,6 +83,11 @@ [Slice], [Scope], [Service], [Socket], [Mount], or [Swap] sections, depending on the unit type. + In addition, options which control resources available to programs + executed by systemd are listed in + systemd.exec5. + Those options complement options listed here. + See the New Control Group Interfaces for an introduction on how to make @@ -751,6 +756,7 @@ systemd.socket5, systemd.mount5, systemd.swap5, + systemd.exec5, systemd.directives7, systemd.special7, The documentation for control groups and specific controllers in the Linux kernel: -- cgit v1.2.3-54-g00ecf From a8d46a1663c80e96508ed9bbd7c3acd55c5b4252 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 15 Oct 2016 15:24:55 -0400 Subject: man: add notes about thread safety of sd_journal_* functions Fixes #4056. --- man/sd-journal.xml | 15 +++++++++++++++ man/sd_journal_add_match.xml | 3 +++ man/sd_journal_enumerate_fields.xml | 3 +++ man/sd_journal_get_catalog.xml | 4 ++++ man/sd_journal_get_cursor.xml | 3 +++ man/sd_journal_get_cutoff_realtime_usec.xml | 3 +++ man/sd_journal_get_usage.xml | 3 +++ man/sd_journal_has_runtime_files.xml | 12 ++++++++++++ man/sd_journal_next.xml | 3 +++ man/sd_journal_open.xml | 3 +++ man/sd_journal_print.xml | 7 ++++--- man/sd_journal_query_unique.xml | 3 +++ man/sd_journal_seek_head.xml | 3 +++ man/sd_journal_stream_fd.xml | 4 ++++ 14 files changed, 66 insertions(+), 3 deletions(-) diff --git a/man/sd-journal.xml b/man/sd-journal.xml index 936a83acf7..0f4b3e8eea 100644 --- a/man/sd-journal.xml +++ b/man/sd-journal.xml @@ -98,6 +98,21 @@ tool. + + Thread safety + + Functions that operate on the sd_journal object are thread + agnostic — given sd_journal pointer may only be used from one thread at + a time, but multiple threads may use multiple such objects safely. Other functions — + those that are used to send entries to the journal, like + sd_journal_print3 + and similar, or those that are used to retrieve global information like + sd_journal_stream_fd3 + and + sd_journal_get_catalog_for_message_id3 + — are thread-safe and may be called from multiple threads in parallel. + + diff --git a/man/sd_journal_add_match.xml b/man/sd_journal_add_match.xml index 98415d53fd..7c64329aed 100644 --- a/man/sd_journal_add_match.xml +++ b/man/sd_journal_add_match.xml @@ -168,6 +168,9 @@ Notes + All functions listed here are thread-agnostic and only a single thread may operate + on a given sd_journal object. + The sd_journal_add_match(), sd_journal_add_disjunction(), sd_journal_add_conjunction() and diff --git a/man/sd_journal_enumerate_fields.xml b/man/sd_journal_enumerate_fields.xml index fa5884106b..bc2c21ed4b 100644 --- a/man/sd_journal_enumerate_fields.xml +++ b/man/sd_journal_enumerate_fields.xml @@ -110,6 +110,9 @@ Notes + All functions listed here are thread-agnostic and only a single thread may operate + on a given sd_journal object. + The sd_journal_enumerate_fields() and sd_journal_restart_fields() interfaces are available as a shared library, which can be compiled and linked to with the libsystemd  Notes + Function sd_journal_get_catalog() is thread-agnostic and only a + single thread may operate on a given sd_journal object. Function + sd_journal_get_catalog_for_message_id() is thread-safe. + The sd_journal_get_catalog() and sd_journal_get_catalog_for_message_id() interfaces are available as a shared library, which can be diff --git a/man/sd_journal_get_cursor.xml b/man/sd_journal_get_cursor.xml index a400d8b1b5..b7aa05f8b2 100644 --- a/man/sd_journal_get_cursor.xml +++ b/man/sd_journal_get_cursor.xml @@ -122,6 +122,9 @@ Notes + All functions listed here are thread-agnostic and only a single thread may operate + on a given sd_journal object. + The sd_journal_get_cursor() and sd_journal_test_cursor() interfaces are available as a shared library, which can be compiled and linked to diff --git a/man/sd_journal_get_cutoff_realtime_usec.xml b/man/sd_journal_get_cutoff_realtime_usec.xml index 23e7cc65e8..0950e11b44 100644 --- a/man/sd_journal_get_cutoff_realtime_usec.xml +++ b/man/sd_journal_get_cutoff_realtime_usec.xml @@ -120,6 +120,9 @@ Notes + All functions listed here are thread-agnostic and only a single thread may operate + on a given sd_journal object. + The sd_journal_get_cutoff_realtime_usec() and sd_journal_get_cutoff_monotonic_usec() diff --git a/man/sd_journal_get_usage.xml b/man/sd_journal_get_usage.xml index 72c804d834..06b0ff534d 100644 --- a/man/sd_journal_get_usage.xml +++ b/man/sd_journal_get_usage.xml @@ -80,6 +80,9 @@ Notes + All functions listed here are thread-agnostic and only a single thread may operate + on a given sd_journal object. + The sd_journal_get_usage() interface is available as a shared library, which can be compiled and linked to with the diff --git a/man/sd_journal_has_runtime_files.xml b/man/sd_journal_has_runtime_files.xml index 237e649206..3f6d56ca77 100644 --- a/man/sd_journal_has_runtime_files.xml +++ b/man/sd_journal_has_runtime_files.xml @@ -85,6 +85,18 @@ + + Notes + + All functions listed here are thread-agnostic and only a single thread may operate + on a given sd_journal object. + + Functions listed here are available as a shared library, which can be compiled and linked + to with the libsystemd pkg-config1 + file. + + See Also diff --git a/man/sd_journal_next.xml b/man/sd_journal_next.xml index 115fe26661..7c385de260 100644 --- a/man/sd_journal_next.xml +++ b/man/sd_journal_next.xml @@ -146,6 +146,9 @@ Notes + All functions listed here are thread-agnostic and only a single thread may operate + on a given sd_journal object. + The sd_journal_next(), sd_journal_previous(), sd_journal_next_skip() and diff --git a/man/sd_journal_open.xml b/man/sd_journal_open.xml index 74e67023b5..25b3048f2e 100644 --- a/man/sd_journal_open.xml +++ b/man/sd_journal_open.xml @@ -208,6 +208,9 @@ Notes + All functions listed here are thread-agnostic and only a single thread may operate + on a given sd_journal object. + The sd_journal_open(), sd_journal_open_directory() and sd_journal_close() interfaces are available diff --git a/man/sd_journal_print.xml b/man/sd_journal_print.xml index 76542527fc..2d8dd635aa 100644 --- a/man/sd_journal_print.xml +++ b/man/sd_journal_print.xml @@ -201,9 +201,10 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid( - Async signal safety - sd_journal_sendv() is "async signal - safe" in the meaning of + Thread safety + All functions listed here are thread-safe and may be called in parallel from multiple threads. + + sd_journal_sendv() is "async signal safe" in the meaning of signal7. diff --git a/man/sd_journal_query_unique.xml b/man/sd_journal_query_unique.xml index dbff55c105..d7a41a039c 100644 --- a/man/sd_journal_query_unique.xml +++ b/man/sd_journal_query_unique.xml @@ -150,6 +150,9 @@ Notes + All functions listed here are thread-agnostic and only a single thread may operate + on a given sd_journal object. + The sd_journal_query_unique(), sd_journal_enumerate_unique() and sd_journal_restart_unique() interfaces are diff --git a/man/sd_journal_seek_head.xml b/man/sd_journal_seek_head.xml index d74c2d5bbc..985073496c 100644 --- a/man/sd_journal_seek_head.xml +++ b/man/sd_journal_seek_head.xml @@ -144,6 +144,9 @@ Notes + All functions listed here are thread-agnostic and only a single thread may operate + on a given sd_journal object. + The sd_journal_seek_head(), sd_journal_seek_tail(), sd_journal_seek_monotonic_usec(), diff --git a/man/sd_journal_stream_fd.xml b/man/sd_journal_stream_fd.xml index 2ea7731b48..226298ae1b 100644 --- a/man/sd_journal_stream_fd.xml +++ b/man/sd_journal_stream_fd.xml @@ -104,6 +104,10 @@ Notes + Function sd_journal_stream_fd() is thread-safe and may be be called + from multiple threads. All calls will return the same file descriptor, although temporarily + multiple file descriptors may be open. + The sd_journal_stream_fd() interface is available as a shared library, which can be compiled and linked to with the -- cgit v1.2.3-54-g00ecf From 50e666288beb8c2e5959895cef01aa4efc31f14d Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 15 Oct 2016 16:12:46 -0400 Subject: man: add journal-upload.conf(5) Fixes #3370. --- Makefile-man.am | 7 +++ man/journal-remote.conf.xml | 13 +++-- man/journal-upload.conf.xml | 113 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 man/journal-upload.conf.xml diff --git a/Makefile-man.am b/Makefile-man.am index a900b8d25a..013e0d7967 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -2272,19 +2272,25 @@ endif if HAVE_MICROHTTPD MANPAGES += \ man/journal-remote.conf.5 \ + man/journal-upload.conf.5 \ man/systemd-journal-gatewayd.service.8 \ man/systemd-journal-remote.8 \ man/systemd-journal-upload.8 MANPAGES_ALIAS += \ man/journal-remote.conf.d.5 \ + man/journal-upload.conf.d.5 \ man/systemd-journal-gatewayd.8 \ man/systemd-journal-gatewayd.socket.8 man/journal-remote.conf.d.5: man/journal-remote.conf.5 +man/journal-upload.conf.d.5: man/journal-upload.conf.5 man/systemd-journal-gatewayd.8: man/systemd-journal-gatewayd.service.8 man/systemd-journal-gatewayd.socket.8: man/systemd-journal-gatewayd.service.8 man/journal-remote.conf.d.html: man/journal-remote.conf.html $(html-alias) +man/journal-upload.conf.d.html: man/journal-upload.conf.html + $(html-alias) + man/systemd-journal-gatewayd.html: man/systemd-journal-gatewayd.service.html $(html-alias) @@ -2607,6 +2613,7 @@ EXTRA_DIST += \ man/hostnamectl.xml \ man/hwdb.xml \ man/journal-remote.conf.xml \ + man/journal-upload.conf.xml \ man/journalctl.xml \ man/journald.conf.xml \ man/kernel-command-line.xml \ diff --git a/man/journal-remote.conf.xml b/man/journal-remote.conf.xml index 2d345963d9..f7ac8c46e0 100644 --- a/man/journal-remote.conf.xml +++ b/man/journal-remote.conf.xml @@ -45,22 +45,21 @@ journal-remote.conf journal-remote.conf.d - Journal remote service configuration files + Configuration files for the service accepting remote journal uploads /etc/systemd/journal-remote.conf - /etc/systemd/journald.conf.d/*.conf - /run/systemd/journald.conf.d/*.conf - /usr/lib/systemd/journald.conf.d/*.conf + /etc/systemd/journal-remote.conf.d/*.conf + /run/systemd/journal-remote.conf.d/*.conf + /usr/lib/systemd/journal-remote.conf.d/*.conf Description - These files configure various parameters of the systemd-remote-journal - application, - systemd-journal-remote8. + These files configure various parameters of + systemd-journal-remote.service8. diff --git a/man/journal-upload.conf.xml b/man/journal-upload.conf.xml new file mode 100644 index 0000000000..e3be62dfd1 --- /dev/null +++ b/man/journal-upload.conf.xml @@ -0,0 +1,113 @@ + + + + + + + + journal-upload.conf + systemd + + + + Monkey with a keyboard + Zbigniew + Jędrzejewski-Szmek + zbyszek@in.waw.pl + + + + + + journal-upload.conf + 5 + + + + journal-upload.conf + journal-upload.conf.d + Configuration files for the journal upload service + + + + /etc/systemd/journal-upload.conf + /etc/systemd/journal-upload.conf.d/*.conf + /run/systemd/journal-upload.conf.d/*.conf + /usr/lib/systemd/journal-upload.conf.d/*.conf + + + + Description + + These files configure various parameters of + systemd-journal-upload.service8. + + + + + + Options + + All options are configured in the [Upload] section: + + + + URL= + + The URL to upload the journal entries to. See the description + of --url= option in + systemd-journal-upload8 + for the description of possible values. + + + + ServerKeyFile= + + SSL key in PEM format. + + + + ServerCertificateFile= + + SSL CA certificate in PEM format. + + + + TrustedCertificateFile= + + SSL CA certificate. + + + + + + + + See Also + + systemd-journal-upload8, + systemd1, + systemd-journald.service8 + + + + -- cgit v1.2.3-54-g00ecf From d0d5f0f778e6d95f2237b3bfcff9a2634c0557ab Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 15 Oct 2016 16:46:13 -0400 Subject: man: drop discouragment of runtime and vendor drop-ins In certain situations drop-ins in /usr/lib/ are useful, for example when one package wants to modify the behaviour of another package, or the vendor wants to tweak some upstream unit without patching. Drop-ins in /run are useful for testing, and may also be created by systemd itself. Follow-up for the discussion in #2103. --- man/systemd.unit.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 79bdb2cd38..a4f5711d7a 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -203,9 +203,7 @@ /run/systemd/system directories. Drop-in files in /etc take precedence over those in /run which in turn take precedence over those in /usr/lib. Drop-in files under any of these directories take precedence - over unit files wherever located. (Of course, since /run is temporary and - /usr/lib is for vendors, it is unlikely drop-ins should be used in either - of those places.) + over unit files wherever located. -- cgit v1.2.3-54-g00ecf From 6d6e4ddd3de8c82091e18811f5845bee9bdede8b Mon Sep 17 00:00:00 2001 From: Martin Ejdestig Date: Sun, 16 Oct 2016 16:25:34 +0200 Subject: man: document sd_event_get_tid() return value (#4385) --- man/sd_event_new.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/man/sd_event_new.xml b/man/sd_event_new.xml index 2c23b00a8c..c0a5e98177 100644 --- a/man/sd_event_new.xml +++ b/man/sd_event_new.xml @@ -183,8 +183,9 @@ Return Value - On success, sd_event_new() and - sd_event_default() return 0 or a positive + On success, sd_event_new(), + sd_event_default() and + sd_event_get_tid() return 0 or a positive integer. On failure, they return a negative errno-style error code. sd_event_ref() always returns a pointer to the event loop object passed -- cgit v1.2.3-54-g00ecf From e8f215d34c3fabb4a9a909491800866d73f5da37 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 14:19:06 -0400 Subject: loginctl: drop casts in printf --- src/login/loginctl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 0fc33cf541..b6fbe843b6 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -118,7 +118,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) { printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT"); while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) { - printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat); + printf("%10s %10"PRIu32" %-16s %-16s\n", id, uid, user, seat); k++; } if (r < 0) @@ -165,7 +165,7 @@ static int list_users(int argc, char *argv[], void *userdata) { printf("%10s %-16s\n", "UID", "USER"); while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) { - printf("%10u %-16s\n", (unsigned) uid, user); + printf("%10"PRIu32" %-16s\n", uid, user); k++; } if (r < 0) @@ -462,9 +462,9 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li printf("%s - ", strna(i.id)); if (i.name) - printf("%s (%u)\n", i.name, (unsigned) i.uid); + printf("%s (%"PRIu32")\n", i.name, i.uid); else - printf("%u\n", (unsigned) i.uid); + printf("%"PRIu32"\n", i.uid); s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime); s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime); @@ -477,7 +477,7 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li if (i.leader > 0) { _cleanup_free_ char *t = NULL; - printf("\t Leader: %u", (unsigned) i.leader); + printf("\t Leader: %"PRIu32, i.leader); get_process_comm(i.leader, &t); if (t) @@ -589,9 +589,9 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) *new_line = true; if (i.name) - printf("%s (%u)\n", i.name, (unsigned) i.uid); + printf("%s (%"PRIu32")\n", i.name, i.uid); else - printf("%u\n", (unsigned) i.uid); + printf("%"PRIu32"\n", i.uid); s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime); s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime); -- cgit v1.2.3-54-g00ecf From 5611ddebe4dd800410f0c413ee034735e1d9993c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 15:13:03 -0400 Subject: loginctl: report tty in session listings Without the tty it's really hard to tell which session is which. New output: $ ./loginctl SESSION UID USER SEAT TTY 13 1002 zbyszek seat0 tty3 c1 42 gdm seat0 /dev/tty1 11 1002 zbyszek seat0 tty4 3 1002 zbyszek seat0 /dev/tty2 17 1002 zbyszek seat0 tty5 18 1002 zbyszek seat0 tty6 6 sessions listed. --- src/login/loginctl.c | 78 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/src/login/loginctl.c b/src/login/loginctl.c index b6fbe843b6..4c618ed19e 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -83,6 +83,34 @@ static OutputFlags get_output_flags(void) { colors_enabled() * OUTPUT_COLOR; } +static int get_session_path(sd_bus *bus, const char *session_id, sd_bus_error *error, char **path) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + char *ans; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "GetSession", + error, &reply, + "s", session_id); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "o", &ans); + if (r < 0) + return r; + + ans = strdup(ans); + if (!ans) + return -ENOMEM; + + *path = ans; + return 0; +} + static int list_sessions(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; @@ -115,10 +143,38 @@ static int list_sessions(int argc, char *argv[], void *userdata) { return bus_log_parse_error(r); if (arg_legend) - printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT"); + printf("%10s %10s %-16s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT", "TTY"); while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) { - printf("%10s %10"PRIu32" %-16s %-16s\n", id, uid, user, seat); + _cleanup_(sd_bus_error_free) sd_bus_error error2 = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply2 = NULL; + _cleanup_free_ char *path = NULL; + const char *tty = NULL; + + r = get_session_path(bus, id, &error2, &path); + if (r < 0) + log_warning("Failed to get session path: %s", bus_error_message(&error, r)); + else { + r = sd_bus_get_property( + bus, + "org.freedesktop.login1", + path, + "org.freedesktop.login1.Session", + "TTY", + &error2, + &reply2, + "s"); + if (r < 0) + log_warning("Failed to get TTY for session %s: %s", + id, bus_error_message(&error2, r)); + else { + r = sd_bus_message_read(reply2, "s", &tty); + if (r < 0) + return bus_log_parse_error(r); + } + } + + printf("%10s %10"PRIu32" %-16s %-16s %-16s\n", id, uid, user, seat, strna(tty)); k++; } if (r < 0) @@ -887,26 +943,14 @@ static int show_session(int argc, char *argv[], void *userdata) { for (i = 1; i < argc; i++) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL; - const char *path = NULL; + _cleanup_free_ char *path = NULL; - r = sd_bus_call_method( - bus, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "GetSession", - &error, &reply, - "s", argv[i]); + r = get_session_path(bus, argv[1], &error, &path); if (r < 0) { - log_error("Failed to get session: %s", bus_error_message(&error, r)); + log_error("Failed to get session path: %s", bus_error_message(&error, r)); return r; } - r = sd_bus_message_read(reply, "o", &path); - if (r < 0) - return bus_log_parse_error(r); - if (properties) r = show_properties(bus, path, &new_line); else -- cgit v1.2.3-54-g00ecf From d7604756ca5888350d5ed4ab6867baa967b24299 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 17:59:37 -0400 Subject: shared/install: use _cleanup_free_ Also rewrap some comments so that they don't have a very long line and a very short line. --- src/shared/install.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/shared/install.c b/src/shared/install.c index 60a6d1312d..c1ef62b337 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -214,8 +214,8 @@ static int path_is_config(const LookupPaths *p, const char *path) { assert(p); assert(path); - /* Note that we do *not* have generic checks for /etc or /run in place, since with them we couldn't discern - * configuration from transient or generated units */ + /* Note that we do *not* have generic checks for /etc or /run in place, since with + * them we couldn't discern configuration from transient or generated units */ parent = dirname_malloc(path); if (!parent) @@ -232,8 +232,8 @@ static int path_is_runtime(const LookupPaths *p, const char *path) { assert(p); assert(path); - /* Everything in /run is considered runtime. On top of that we also add explicit checks for the various runtime - * directories, as safety net. */ + /* Everything in /run is considered runtime. On top of that we also add + * explicit checks for the various runtime directories, as safety net. */ rpath = skip_root(p, path); if (rpath && path_startswith(rpath, "/run")) @@ -1084,7 +1084,7 @@ static int config_parse_default_instance( UnitFileInstallInfo *i = data; const char *name; - char *printed; + _cleanup_free_ char *printed = NULL; int r; assert(filename); @@ -1104,13 +1104,12 @@ static int config_parse_default_instance( if (r < 0) return r; - if (!unit_instance_is_valid(printed)) { - free(printed); + if (!unit_instance_is_valid(printed)) return -EINVAL; - } free(i->default_instance); i->default_instance = printed; + printed = NULL; return 0; } -- cgit v1.2.3-54-g00ecf From 6b430fdb7c0c2c52ea69a7d56f23d739218b13d0 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 18:28:30 -0400 Subject: tree-wide: use mfree more --- coccinelle/mfree_return.cocci | 6 ++++++ src/basic/bitmap.c | 6 ++---- src/basic/env-util.c | 3 +-- src/basic/prioq.c | 4 +--- src/basic/replace-var.c | 3 +-- src/basic/strbuf.c | 3 +-- src/basic/string-util.c | 6 ++---- src/basic/strv.c | 9 +++------ src/core/dynamic-user.c | 4 +--- src/core/execute.c | 4 +--- src/core/manager.c | 3 +-- src/core/transaction.c | 6 ++---- src/core/unit.c | 6 ++---- src/cryptsetup/cryptsetup-generator.c | 9 +++------ src/import/curl-util.c | 4 +--- src/import/export-raw.c | 4 +--- src/import/export-tar.c | 4 +--- src/import/import-raw.c | 4 +--- src/import/import-tar.c | 4 +--- src/import/importd.c | 6 ++---- src/import/pull-job.c | 4 +--- src/import/pull-raw.c | 4 +--- src/import/pull-tar.c | 4 +--- src/journal-remote/journal-remote-write.c | 10 +++------- src/journal/journal-file.c | 3 +-- src/journal/mmap-cache.c | 6 ++---- src/journal/sd-journal.c | 9 +++------ src/libsystemd-network/ndisc-router.c | 3 +-- src/libsystemd-network/sd-dhcp-client.c | 4 +--- src/libsystemd-network/sd-dhcp-lease.c | 4 +--- src/libsystemd-network/sd-dhcp-server.c | 4 +--- src/libsystemd-network/sd-dhcp6-client.c | 4 +--- src/libsystemd-network/sd-dhcp6-lease.c | 4 +--- src/libsystemd-network/sd-ipv4acd.c | 4 +--- src/libsystemd-network/sd-ipv4ll.c | 4 +--- src/libsystemd-network/sd-lldp.c | 4 +--- src/libsystemd-network/sd-ndisc.c | 4 +--- src/libsystemd/sd-bus/bus-slot.c | 4 +--- src/libsystemd/sd-bus/bus-track.c | 8 ++------ src/libudev/libudev-list.c | 14 ++++++-------- src/libudev/libudev-monitor.c | 3 +-- src/login/logind-button.c | 9 +++------ src/login/logind-device.c | 9 +++------ src/login/logind-inhibit.c | 9 +++------ src/login/logind-seat.c | 9 +++------ src/login/logind-session.c | 12 ++++-------- src/machine/machine.c | 4 +--- src/machine/operation.c | 3 +-- src/network/networkd-wait-online-link.c | 3 +-- src/nspawn/nspawn-settings.c | 4 +--- src/resolve/resolved-dns-query.c | 8 ++------ src/resolve/resolved-dns-rr.c | 10 +++------- src/resolve/resolved-dns-scope.c | 4 +--- src/resolve/resolved-dns-search-domain.c | 4 +--- src/resolve/resolved-dns-server.c | 3 +-- src/resolve/resolved-dns-stream.c | 4 +--- src/resolve/resolved-dns-transaction.c | 3 +-- src/resolve/resolved-link.c | 6 ++---- src/resolve/resolved-manager.c | 4 +--- src/shared/machine-image.c | 3 +-- src/shared/ptyfwd.c | 3 +-- src/timesync/timesyncd-server.c | 7 ++----- src/udev/udev-ctrl.c | 3 +-- src/udev/udev-rules.c | 3 +-- 64 files changed, 105 insertions(+), 228 deletions(-) create mode 100644 coccinelle/mfree_return.cocci diff --git a/coccinelle/mfree_return.cocci b/coccinelle/mfree_return.cocci new file mode 100644 index 0000000000..8119fe07f2 --- /dev/null +++ b/coccinelle/mfree_return.cocci @@ -0,0 +1,6 @@ +@@ +expression p; +@@ +- free(p); +- return NULL; ++ return mfree(p); diff --git a/src/basic/bitmap.c b/src/basic/bitmap.c index f4b12fc261..f6212e6151 100644 --- a/src/basic/bitmap.c +++ b/src/basic/bitmap.c @@ -58,10 +58,8 @@ Bitmap *bitmap_copy(Bitmap *b) { return NULL; ret->bitmaps = newdup(uint64_t, b->bitmaps, b->n_bitmaps); - if (!ret->bitmaps) { - free(ret); - return NULL; - } + if (!ret->bitmaps) + return mfree(ret); ret->n_bitmaps = ret->bitmaps_allocated = b->n_bitmaps; return ret; diff --git a/src/basic/env-util.c b/src/basic/env-util.c index 7f5fddb700..b74290d6fd 100644 --- a/src/basic/env-util.c +++ b/src/basic/env-util.c @@ -544,8 +544,7 @@ char *replace_env(const char *format, char **env) { return k; fail: - free(r); - return NULL; + return mfree(r); } char **replace_env_argv(char **argv, char **env) { diff --git a/src/basic/prioq.c b/src/basic/prioq.c index d2ec516d29..4570b8e4ba 100644 --- a/src/basic/prioq.c +++ b/src/basic/prioq.c @@ -62,9 +62,7 @@ Prioq* prioq_free(Prioq *q) { return NULL; free(q->items); - free(q); - - return NULL; + return mfree(q); } int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func) { diff --git a/src/basic/replace-var.c b/src/basic/replace-var.c index 6a204b9ec3..0d21423a9c 100644 --- a/src/basic/replace-var.c +++ b/src/basic/replace-var.c @@ -107,6 +107,5 @@ char *replace_var(const char *text, char *(*lookup)(const char *variable, void*u return r; oom: - free(r); - return NULL; + return mfree(r); } diff --git a/src/basic/strbuf.c b/src/basic/strbuf.c index 4bef87d3c2..00aaf9e621 100644 --- a/src/basic/strbuf.c +++ b/src/basic/strbuf.c @@ -62,8 +62,7 @@ struct strbuf *strbuf_new(void) { err: free(str->buf); free(str->root); - free(str); - return NULL; + return mfree(str); } static void strbuf_node_cleanup(struct strbuf_node *node) { diff --git a/src/basic/string-util.c b/src/basic/string-util.c index dc7de5dab8..6b06e643c9 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -610,8 +610,7 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin return r; oom: - free(r); - return NULL; + return mfree(r); } char *strip_tab_ansi(char **ibuf, size_t *_isz) { @@ -682,8 +681,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) { if (ferror(f)) { fclose(f); - free(obuf); - return NULL; + return mfree(obuf); } fclose(f); diff --git a/src/basic/strv.c b/src/basic/strv.c index 34e464d253..0eec868eed 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -87,8 +87,7 @@ void strv_clear(char **l) { char **strv_free(char **l) { strv_clear(l); - free(l); - return NULL; + return mfree(l); } char **strv_free_erase(char **l) { @@ -426,8 +425,7 @@ char *strv_join_quoted(char **l) { return buf; oom: - free(buf); - return NULL; + return mfree(buf); } int strv_push(char ***l, char *value) { @@ -869,8 +867,7 @@ char ***strv_free_free(char ***l) { for (i = l; *i; i++) strv_free(*i); - free(l); - return NULL; + return mfree(l); } char **strv_skip(char **l, size_t n) { diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c index 1043da3eb7..e1846e1adb 100644 --- a/src/core/dynamic-user.c +++ b/src/core/dynamic-user.c @@ -42,9 +42,7 @@ static DynamicUser* dynamic_user_free(DynamicUser *d) { (void) hashmap_remove(d->manager->dynamic_users, d->name); safe_close_pair(d->storage_socket); - free(d); - - return NULL; + return mfree(d); } static int dynamic_user_add(Manager *m, const char *name, int storage_socket[2], DynamicUser **ret) { diff --git a/src/core/execute.c b/src/core/execute.c index 869522704a..59c2bd0dd2 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -3740,9 +3740,7 @@ ExecRuntime *exec_runtime_unref(ExecRuntime *r) { free(r->tmp_dir); free(r->var_tmp_dir); safe_close_pair(r->netns_storage_socket); - free(r); - - return NULL; + return mfree(r); } int exec_runtime_serialize(Unit *u, ExecRuntime *rt, FILE *f, FDSet *fds) { diff --git a/src/core/manager.c b/src/core/manager.c index 3569249788..50aae0d1ba 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1119,8 +1119,7 @@ Manager* manager_free(Manager *m) { hashmap_free(m->uid_refs); hashmap_free(m->gid_refs); - free(m); - return NULL; + return mfree(m); } void manager_enumerate(Manager *m) { diff --git a/src/core/transaction.c b/src/core/transaction.c index 8370b864fb..e22e3b30c2 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -1085,10 +1085,8 @@ Transaction *transaction_new(bool irreversible) { return NULL; tr->jobs = hashmap_new(NULL); - if (!tr->jobs) { - free(tr); - return NULL; - } + if (!tr->jobs) + return mfree(tr); tr->irreversible = irreversible; diff --git a/src/core/unit.c b/src/core/unit.c index 67668bdc48..a6b8ecdcb7 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -88,10 +88,8 @@ Unit *unit_new(Manager *m, size_t size) { return NULL; u->names = set_new(&string_hash_ops); - if (!u->names) { - free(u); - return NULL; - } + if (!u->names) + return mfree(u); u->manager = m; u->type = _UNIT_TYPE_INVALID; diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 8ac5ab730a..de0a3b6f9c 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -264,16 +264,13 @@ static crypto_device *get_crypto_device(const char *uuid) { d->keyfile = d->options = d->name = NULL; d->uuid = strdup(uuid); - if (!d->uuid) { - free(d); - return NULL; - } + if (!d->uuid) + return mfree(d); r = hashmap_put(arg_disks, d->uuid, d); if (r < 0) { free(d->uuid); - free(d); - return NULL; + return mfree(d); } } diff --git a/src/import/curl-util.c b/src/import/curl-util.c index 6990c47f48..734e1560e6 100644 --- a/src/import/curl-util.c +++ b/src/import/curl-util.c @@ -235,9 +235,7 @@ CurlGlue *curl_glue_unref(CurlGlue *g) { sd_event_source_unref(g->timer); sd_event_unref(g->event); - free(g); - - return NULL; + return mfree(g); } int curl_glue_new(CurlGlue **glue, sd_event *event) { diff --git a/src/import/export-raw.c b/src/import/export-raw.c index 6136b677dd..a3dbce1954 100644 --- a/src/import/export-raw.c +++ b/src/import/export-raw.c @@ -87,9 +87,7 @@ RawExport *raw_export_unref(RawExport *e) { free(e->buffer); free(e->path); - free(e); - - return NULL; + return mfree(e); } int raw_export_new( diff --git a/src/import/export-tar.c b/src/import/export-tar.c index d79c27f2d0..3bb6027431 100644 --- a/src/import/export-tar.c +++ b/src/import/export-tar.c @@ -91,9 +91,7 @@ TarExport *tar_export_unref(TarExport *e) { free(e->buffer); free(e->path); - free(e); - - return NULL; + return mfree(e); } int tar_export_new( diff --git a/src/import/import-raw.c b/src/import/import-raw.c index fd6b9f7703..29f3f896e5 100644 --- a/src/import/import-raw.c +++ b/src/import/import-raw.c @@ -100,9 +100,7 @@ RawImport* raw_import_unref(RawImport *i) { free(i->final_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int raw_import_new( diff --git a/src/import/import-tar.c b/src/import/import-tar.c index 8b81324fde..22f9b8c5ea 100644 --- a/src/import/import-tar.c +++ b/src/import/import-tar.c @@ -107,9 +107,7 @@ TarImport* tar_import_unref(TarImport *i) { free(i->final_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int tar_import_new( diff --git a/src/import/importd.c b/src/import/importd.c index 28b4302cb3..9d31a956a5 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -141,8 +141,7 @@ static Transfer *transfer_unref(Transfer *t) { safe_close(t->stdin_fd); safe_close(t->stdout_fd); - free(t); - return NULL; + return mfree(t); } DEFINE_TRIVIAL_CLEANUP_FUNC(Transfer*, transfer_unref); @@ -548,8 +547,7 @@ static Manager *manager_unref(Manager *m) { m->bus = sd_bus_flush_close_unref(m->bus); sd_event_unref(m->event); - free(m); - return NULL; + return mfree(m); } DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref); diff --git a/src/import/pull-job.c b/src/import/pull-job.c index 6bcf35ef4e..e550df2c57 100644 --- a/src/import/pull-job.c +++ b/src/import/pull-job.c @@ -50,9 +50,7 @@ PullJob* pull_job_unref(PullJob *j) { free(j->payload); free(j->checksum); - free(j); - - return NULL; + return mfree(j); } static void pull_job_finish(PullJob *j, int ret) { diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c index 8993402821..0cf410a5d9 100644 --- a/src/import/pull-raw.c +++ b/src/import/pull-raw.c @@ -110,9 +110,7 @@ RawPull* raw_pull_unref(RawPull *i) { free(i->settings_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int raw_pull_new( diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c index 8c61c46f73..68e2397b02 100644 --- a/src/import/pull-tar.c +++ b/src/import/pull-tar.c @@ -114,9 +114,7 @@ TarPull* tar_pull_unref(TarPull *i) { free(i->settings_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int tar_pull_new( diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c index 7bba52566e..8729372aa3 100644 --- a/src/journal-remote/journal-remote-write.c +++ b/src/journal-remote/journal-remote-write.c @@ -75,10 +75,8 @@ Writer* writer_new(RemoteServer *server) { memset(&w->metrics, 0xFF, sizeof(w->metrics)); w->mmap = mmap_cache_new(); - if (!w->mmap) { - free(w); - return NULL; - } + if (!w->mmap) + return mfree(w); w->n_ref = 1; w->server = server; @@ -103,9 +101,7 @@ Writer* writer_free(Writer *w) { if (w->mmap) mmap_cache_unref(w->mmap); - free(w); - - return NULL; + return mfree(w); } Writer* writer_unref(Writer *w) { diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 49199b269f..d3e0214731 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -394,8 +394,7 @@ JournalFile* journal_file_close(JournalFile *f) { gcry_md_close(f->hmac); #endif - free(f); - return NULL; + return mfree(f); } void journal_file_close_set(Set *s) { diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c index 293d27053a..d91247b524 100644 --- a/src/journal/mmap-cache.c +++ b/src/journal/mmap-cache.c @@ -325,10 +325,8 @@ static FileDescriptor* fd_add(MMapCache *m, int fd) { f->fd = fd; r = hashmap_put(m->fds, FD_TO_PTR(fd), f); - if (r < 0) { - free(f); - return NULL; - } + if (r < 0) + return mfree(f); return f; } diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 98c8a47afe..f2f8546086 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -387,7 +387,7 @@ _public_ int sd_journal_add_disjunction(sd_journal *j) { } static char *match_make_string(Match *m) { - char *p, *r; + char *p = NULL, *r; Match *i; bool enclose = false; @@ -397,15 +397,12 @@ static char *match_make_string(Match *m) { if (m->type == MATCH_DISCRETE) return strndup(m->data, m->size); - p = NULL; LIST_FOREACH(matches, i, m->matches) { char *t, *k; t = match_make_string(i); - if (!t) { - free(p); - return NULL; - } + if (!t) + return mfree(p); if (p) { k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL); diff --git a/src/libsystemd-network/ndisc-router.c b/src/libsystemd-network/ndisc-router.c index d9950b638c..41ff2b353a 100644 --- a/src/libsystemd-network/ndisc-router.c +++ b/src/libsystemd-network/ndisc-router.c @@ -49,8 +49,7 @@ _public_ sd_ndisc_router* sd_ndisc_router_unref(sd_ndisc_router *rt) { if (rt->n_ref > 0) return NULL; - free(rt); - return NULL; + return mfree(rt); } sd_ndisc_router *ndisc_router_new(size_t raw_size) { diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 179e5950bd..5ccb23922c 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -1873,9 +1873,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) { free(client->req_opts); free(client->hostname); free(client->vendor_class_identifier); - free(client); - - return NULL; + return mfree(client); } int sd_dhcp_client_new(sd_dhcp_client **ret) { diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index ef50ed17a1..8387b185c0 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -282,9 +282,7 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) { free(lease->static_route); free(lease->client_id); free(lease->vendor_specific); - free(lease); - - return NULL; + return mfree(lease); } static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) { diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 11ee2e252e..f16314a37f 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -178,9 +178,7 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) { hashmap_free(server->leases_by_client_id); free(server->bound_leases); - free(server); - - return NULL; + return mfree(server); } int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) { diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 463fde401c..e81215f7d7 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -1300,9 +1300,7 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) { sd_dhcp6_client_detach_event(client); free(client->req_opts); - free(client); - - return NULL; + return mfree(client); } int sd_dhcp6_client_new(sd_dhcp6_client **ret) { diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index 5c10a6326a..ab59977a3f 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -389,9 +389,7 @@ sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) { free(lease->ntp); lease->ntp_fqdn = strv_free(lease->ntp_fqdn); - free(lease); - - return NULL; + return mfree(lease); } int dhcp6_lease_new(sd_dhcp6_lease **ret) { diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c index 662885840f..4dd343c101 100644 --- a/src/libsystemd-network/sd-ipv4acd.c +++ b/src/libsystemd-network/sd-ipv4acd.c @@ -135,9 +135,7 @@ sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd) { ipv4acd_reset(acd); sd_ipv4acd_detach_event(acd); - free(acd); - - return NULL; + return mfree(acd); } int sd_ipv4acd_new(sd_ipv4acd **ret) { diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c index 5603a533a5..13209261f9 100644 --- a/src/libsystemd-network/sd-ipv4ll.c +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -90,9 +90,7 @@ sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) { return NULL; sd_ipv4acd_unref(ll->acd); - free(ll); - - return NULL; + return mfree(ll); } int sd_ipv4ll_new(sd_ipv4ll **ret) { diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c index 0bd1e66aa0..0702241506 100644 --- a/src/libsystemd-network/sd-lldp.c +++ b/src/libsystemd-network/sd-lldp.c @@ -374,9 +374,7 @@ _public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) { hashmap_free(lldp->neighbor_by_id); prioq_free(lldp->neighbor_by_expiry); - free(lldp); - - return NULL; + return mfree(lldp); } _public_ int sd_lldp_new(sd_lldp **ret) { diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c index 07b0d7f704..1d3be9b862 100644 --- a/src/libsystemd-network/sd-ndisc.c +++ b/src/libsystemd-network/sd-ndisc.c @@ -148,9 +148,7 @@ _public_ sd_ndisc *sd_ndisc_unref(sd_ndisc *nd) { ndisc_reset(nd); sd_ndisc_detach_event(nd); - free(nd); - - return NULL; + return mfree(nd); } _public_ int sd_ndisc_new(sd_ndisc **ret) { diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c index 8e9074c7df..33590c31ac 100644 --- a/src/libsystemd/sd-bus/bus-slot.c +++ b/src/libsystemd/sd-bus/bus-slot.c @@ -212,9 +212,7 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) { bus_slot_disconnect(slot); free(slot->description); - free(slot); - - return NULL; + return mfree(slot); } _public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) { diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 00e93a215f..4acaf24793 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -74,9 +74,7 @@ static struct track_item* track_item_free(struct track_item *i) { sd_bus_slot_unref(i->slot); free(i->name); - free(i); - - return NULL; + return mfree(i); } DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free); @@ -206,9 +204,7 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { bus_track_remove_from_queue(track); hashmap_free(track->names); sd_bus_unref(track->bus); - free(track); - - return NULL; + return mfree(track); } static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c index da496ed456..0d51322a15 100644 --- a/src/libudev/libudev-list.c +++ b/src/libudev/libudev-list.c @@ -166,17 +166,16 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char * entry = new0(struct udev_list_entry, 1); if (entry == NULL) return NULL; + entry->name = strdup(name); - if (entry->name == NULL) { - free(entry); - return NULL; - } + if (entry->name == NULL) + return mfree(entry); + if (value != NULL) { entry->value = strdup(value); if (entry->value == NULL) { free(entry->name); - free(entry); - return NULL; + return mfree(entry); } } @@ -193,8 +192,7 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char * if (entries == NULL) { free(entry->name); free(entry->value); - free(entry); - return NULL; + return mfree(entry); } list->entries = entries; list->entries_max += add; diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c index 1f9d16c450..a1f2b33ad5 100644 --- a/src/libudev/libudev-monitor.c +++ b/src/libudev/libudev-monitor.c @@ -207,8 +207,7 @@ struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const c udev_monitor->sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); if (udev_monitor->sock < 0) { log_debug_errno(errno, "error getting socket: %m"); - free(udev_monitor); - return NULL; + return mfree(udev_monitor); } } else { udev_monitor->bound = true; diff --git a/src/login/logind-button.c b/src/login/logind-button.c index baa6b7113c..90fb93bbaf 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -43,15 +43,12 @@ Button* button_new(Manager *m, const char *name) { return NULL; b->name = strdup(name); - if (!b->name) { - free(b); - return NULL; - } + if (!b->name) + return mfree(b); if (hashmap_put(m->buttons, b->name, b) < 0) { free(b->name); - free(b); - return NULL; + return mfree(b); } b->manager = m; diff --git a/src/login/logind-device.c b/src/login/logind-device.c index eb5edd1cd5..6537fa04bf 100644 --- a/src/login/logind-device.c +++ b/src/login/logind-device.c @@ -34,15 +34,12 @@ Device* device_new(Manager *m, const char *sysfs, bool master) { return NULL; d->sysfs = strdup(sysfs); - if (!d->sysfs) { - free(d); - return NULL; - } + if (!d->sysfs) + return mfree(d); if (hashmap_put(m->devices, d->sysfs, d) < 0) { free(d->sysfs); - free(d); - return NULL; + return mfree(d); } d->manager = m; diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index 6c78e0dddc..c93b24009b 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -45,17 +45,14 @@ Inhibitor* inhibitor_new(Manager *m, const char* id) { return NULL; i->state_file = strappend("/run/systemd/inhibit/", id); - if (!i->state_file) { - free(i); - return NULL; - } + if (!i->state_file) + return mfree(i); i->id = basename(i->state_file); if (hashmap_put(m->inhibitors, i->id, i) < 0) { free(i->state_file); - free(i); - return NULL; + return mfree(i); } i->manager = m; diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index b5192320e4..ecc7bd2e5b 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -48,18 +48,15 @@ Seat *seat_new(Manager *m, const char *id) { return NULL; s->state_file = strappend("/run/systemd/seats/", id); - if (!s->state_file) { - free(s); - return NULL; - } + if (!s->state_file) + return mfree(s); s->id = basename(s->state_file); s->manager = m; if (hashmap_put(m->seats, s->id, s) < 0) { free(s->state_file); - free(s); - return NULL; + return mfree(s); } return s; diff --git a/src/login/logind-session.c b/src/login/logind-session.c index ba1bcc2630..cbf035f706 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -62,16 +62,13 @@ Session* session_new(Manager *m, const char *id) { return NULL; s->state_file = strappend("/run/systemd/sessions/", id); - if (!s->state_file) { - free(s); - return NULL; - } + if (!s->state_file) + return mfree(s); s->devices = hashmap_new(&devt_hash_ops); if (!s->devices) { free(s->state_file); - free(s); - return NULL; + return mfree(s); } s->id = basename(s->state_file); @@ -79,8 +76,7 @@ Session* session_new(Manager *m, const char *id) { if (hashmap_put(m->sessions, s->id, s) < 0) { hashmap_free(s->devices); free(s->state_file); - free(s); - return NULL; + return mfree(s); } s->manager = m; diff --git a/src/machine/machine.c b/src/machine/machine.c index dd046d6563..a02b9d7575 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -80,9 +80,7 @@ Machine* machine_new(Manager *manager, MachineClass class, const char *name) { fail: free(m->state_file); free(m->name); - free(m); - - return NULL; + return mfree(m); } void machine_free(Machine *m) { diff --git a/src/machine/operation.c b/src/machine/operation.c index 2bf93cb493..c966d0d21c 100644 --- a/src/machine/operation.c +++ b/src/machine/operation.c @@ -147,6 +147,5 @@ Operation *operation_free(Operation *o) { if (o->machine) LIST_REMOVE(operations_by_machine, o->machine->operations, o); - free(o); - return NULL; + return mfree(o); } diff --git a/src/network/networkd-wait-online-link.c b/src/network/networkd-wait-online-link.c index 5727422e3d..e63ba07e90 100644 --- a/src/network/networkd-wait-online-link.c +++ b/src/network/networkd-wait-online-link.c @@ -77,8 +77,7 @@ Link *link_free(Link *l) { } free(l->ifname); - free(l); - return NULL; + return mfree(l); } int link_update_rtnl(Link *l, sd_netlink_message *m) { diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c index 5f1522cfb6..09c8f070ba 100644 --- a/src/nspawn/nspawn-settings.c +++ b/src/nspawn/nspawn-settings.c @@ -101,9 +101,7 @@ Settings* settings_free(Settings *s) { expose_port_free_all(s->expose_ports); custom_mount_free_all(s->custom_mounts, s->n_custom_mounts); - free(s); - - return NULL; + return mfree(s); } bool settings_private_network(Settings *s) { diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index 53be18efc6..e03db4d003 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -83,9 +83,7 @@ DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) { if (c->scope) LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c); - free(c); - - return NULL; + return mfree(c); } static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) { @@ -421,9 +419,7 @@ DnsQuery *dns_query_free(DnsQuery *q) { q->manager->n_dns_queries--; } - free(q); - - return NULL; + return mfree(q); } int dns_query_new( diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index 5687588a7d..87e4abec6e 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -73,10 +73,8 @@ DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const D return dns_resource_key_ref((DnsResourceKey*) key); k = dns_resource_key_new_consume(key->class, key->type, destination); - if (!k) { - free(destination); - return NULL; - } + if (!k) + return mfree(destination); return k; } @@ -513,9 +511,7 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) { } free(rr->to_string); - free(rr); - - return NULL; + return mfree(rr); } int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) { diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 03811ac8e7..8dbc7f623b 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -128,9 +128,7 @@ DnsScope* dns_scope_free(DnsScope *s) { dns_zone_flush(&s->zone); LIST_REMOVE(scopes, s->manager->dns_scopes, s); - free(s); - - return NULL; + return mfree(s); } DnsServer *dns_scope_get_dns_server(DnsScope *s) { diff --git a/src/resolve/resolved-dns-search-domain.c b/src/resolve/resolved-dns-search-domain.c index 732471027b..1386e6a17b 100644 --- a/src/resolve/resolved-dns-search-domain.c +++ b/src/resolve/resolved-dns-search-domain.c @@ -104,9 +104,7 @@ DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d) { return NULL; free(d->name); - free(d); - - return NULL; + return mfree(d); } void dns_search_domain_unlink(DnsSearchDomain *d) { diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 97cc8c0e09..7282848e35 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -139,8 +139,7 @@ DnsServer* dns_server_unref(DnsServer *s) { return NULL; free(s->server_string); - free(s); - return NULL; + return mfree(s); } void dns_server_unlink(DnsServer *s) { diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c index dd0e0b90e3..878bae47dc 100644 --- a/src/resolve/resolved-dns-stream.c +++ b/src/resolve/resolved-dns-stream.c @@ -343,9 +343,7 @@ DnsStream *dns_stream_unref(DnsStream *s) { dns_packet_unref(s->write_packet); dns_packet_unref(s->read_packet); - free(s); - - return NULL; + return mfree(s); } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_unref); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index d455b6b1fa..2fce44ec8b 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -134,8 +134,7 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) { dns_answer_unref(t->validated_keys); dns_resource_key_unref(t->key); - free(t); - return NULL; + return mfree(t); } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free); diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index ea4a007139..13e1f91192 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -101,8 +101,7 @@ Link *link_free(Link *l) { free(l->state_file); - free(l); - return NULL; + return mfree(l); } void link_allocate_scopes(Link *l) { @@ -698,8 +697,7 @@ LinkAddress *link_address_free(LinkAddress *a) { dns_resource_record_unref(a->llmnr_address_rr); dns_resource_record_unref(a->llmnr_ptr_rr); - free(a); - return NULL; + return mfree(a); } void link_address_add_rrs(LinkAddress *a, bool force_remove) { diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 40f08e8044..0954641c20 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -630,9 +630,7 @@ Manager *manager_free(Manager *m) { dns_trust_anchor_flush(&m->trust_anchor); manager_etc_hosts_flush(m); - free(m); - - return NULL; + return mfree(m); } int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index 529d89ee2a..060f8d50c7 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -62,8 +62,7 @@ Image *image_unref(Image *i) { free(i->name); free(i->path); - free(i); - return NULL; + return mfree(i); } static char **image_settings_path(Image *image) { diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 24055e772b..293c6673fc 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -463,8 +463,7 @@ int pty_forward_new( PTYForward *pty_forward_free(PTYForward *f) { pty_forward_disconnect(f); - free(f); - return NULL; + return mfree(f); } int pty_forward_get_last_char(PTYForward *f, char *ch) { diff --git a/src/timesync/timesyncd-server.c b/src/timesync/timesyncd-server.c index 6bda86fe6e..57a7bf2c25 100644 --- a/src/timesync/timesyncd-server.c +++ b/src/timesync/timesyncd-server.c @@ -61,8 +61,7 @@ ServerAddress* server_address_free(ServerAddress *a) { manager_set_server_address(a->name->manager, NULL); } - free(a); - return NULL; + return mfree(a); } int server_name_new( @@ -137,9 +136,7 @@ ServerName *server_name_free(ServerName *n) { log_debug("Removed server %s.", n->string); free(n->string); - free(n); - - return NULL; + return mfree(n); } void server_name_flush_addresses(ServerName *n) { diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index f68a09d7a8..7717ac7924 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -211,8 +211,7 @@ struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) { err: if (conn->sock >= 0) close(conn->sock); - free(conn); - return NULL; + return mfree(conn); } struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn) { diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 26fa52cf6c..7619c8371b 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -1583,8 +1583,7 @@ struct udev_rules *udev_rules_unref(struct udev_rules *rules) { strbuf_cleanup(rules->strbuf); free(rules->uids); free(rules->gids); - free(rules); - return NULL; + return mfree(rules); } bool udev_rules_check_timestamp(struct udev_rules *rules) { -- cgit v1.2.3-54-g00ecf From 3b319885c4febb5f7ea9b5ab31c3395548ed6886 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 19:23:35 -0400 Subject: tree-wide: introduce free_and_replace helper It's a common pattern, so add a helper for it. A macro is necessary because a function that takes a pointer to a pointer would be type specific, similarly to cleanup functions. Seems better to use a macro. --- coccinelle/free_and_replace.cocci | 15 +++++++++++++++ src/basic/alloc-util.h | 8 ++++++++ src/basic/fs-util.c | 8 ++------ src/basic/path-util.c | 4 +--- src/core/load-fragment.c | 10 ++-------- src/core/mount.c | 14 +++----------- src/core/service.c | 4 +--- src/journal-remote/journal-upload.c | 4 +--- src/shared/install.c | 10 ++-------- 9 files changed, 35 insertions(+), 42 deletions(-) create mode 100644 coccinelle/free_and_replace.cocci diff --git a/coccinelle/free_and_replace.cocci b/coccinelle/free_and_replace.cocci new file mode 100644 index 0000000000..9dcdbf4d42 --- /dev/null +++ b/coccinelle/free_and_replace.cocci @@ -0,0 +1,15 @@ +@@ +expression p, q; +@@ +- free(p); +- p = q; +- q = NULL; +- return 0; ++ return free_and_replace(p, q); +@@ +expression p, q; +@@ +- free(p); +- p = q; +- q = NULL; ++ free_and_replace(p, q); diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h index ceeee519b7..a44dd473c1 100644 --- a/src/basic/alloc-util.h +++ b/src/basic/alloc-util.h @@ -43,6 +43,14 @@ static inline void *mfree(void *memory) { return NULL; } +#define free_and_replace(a, b) \ + ({ \ + free(a); \ + (a) = (b); \ + (b) = NULL; \ + 0; \ + }) + void* memdup(const void *p, size_t l) _alloc_(2); static inline void freep(void *p) { diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 86d9ad7e36..48952a1c26 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -678,9 +678,7 @@ int chase_symlinks(const char *path, const char *_root, char **ret) { !path_startswith(parent, root)) return -EINVAL; - free(done); - done = parent; - parent = NULL; + free_and_replace(done, parent); fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH); if (fd_parent < 0) @@ -724,9 +722,7 @@ int chase_symlinks(const char *path, const char *_root, char **ret) { if (fd < 0) return -errno; - free(buffer); - buffer = destination; - destination = NULL; + free_and_replace(buffer, destination); todo = buffer; free(done); diff --git a/src/basic/path-util.c b/src/basic/path-util.c index a76963aa9f..0f5b20cf05 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -288,9 +288,7 @@ char **path_strv_resolve(char **l, const char *prefix) { } else { /* canonicalized path goes outside of * prefix, keep the original path instead */ - free(u); - u = orig; - orig = NULL; + free_and_replace(u, orig); } } else free(t); diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 06c156a623..8cc7a8e765 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -1591,11 +1591,7 @@ int config_parse_fdname( return 0; } - free(s->fdname); - s->fdname = p; - p = NULL; - - return 0; + return free_and_replace(s->fdname, p); } int config_parse_service_sockets( @@ -2052,9 +2048,7 @@ int config_parse_working_directory( return 0; } - free(c->working_directory); - c->working_directory = k; - k = NULL; + free_and_replace(c->working_directory, k); c->working_directory_home = false; } diff --git a/src/core/mount.c b/src/core/mount.c index 15619dffe3..da480001e1 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1484,17 +1484,9 @@ static int mount_setup_unit( MOUNT(u)->from_proc_self_mountinfo = true; - free(p->what); - p->what = w; - w = NULL; - - free(p->options); - p->options = o; - o = NULL; - - free(p->fstype); - p->fstype = f; - f = NULL; + free_and_replace(p->what, w); + free_and_replace(p->options, o); + free_and_replace(p->fstype, f); if (load_extras) { r = mount_add_extras(MOUNT(u)); diff --git a/src/core/service.c b/src/core/service.c index 63045ede55..c949de9cbe 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -3088,9 +3088,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds) if (!streq_ptr(s->status_text, t)) { - free(s->status_text); - s->status_text = t; - t = NULL; + free_and_replace(s->status_text, t); notify_dbus = true; } diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index c0f967ab94..61190ff83c 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -527,9 +527,7 @@ static int perform_upload(Uploader *u) { log_debug("Upload finished successfully with code %ld: %s", status, strna(u->answer)); - free(u->last_cursor); - u->last_cursor = u->current_cursor; - u->current_cursor = NULL; + free_and_replace(u->last_cursor, u->current_cursor); return update_cursor_state(u); } diff --git a/src/shared/install.c b/src/shared/install.c index c1ef62b337..f70b3e3dd5 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1107,11 +1107,7 @@ static int config_parse_default_instance( if (!unit_instance_is_valid(printed)) return -EINVAL; - free(i->default_instance); - i->default_instance = printed; - printed = NULL; - - return 0; + return free_and_replace(i->default_instance, printed); } static int unit_file_load( @@ -1357,9 +1353,7 @@ static int install_info_follow( if (!streq(basename(i->symlink_target), i->name)) return -EXDEV; - free(i->path); - i->path = i->symlink_target; - i->symlink_target = NULL; + free_and_replace(i->path, i->symlink_target); i->type = _UNIT_FILE_TYPE_INVALID; return unit_file_load_or_readlink(c, i, i->path, root_dir, flags); -- cgit v1.2.3-54-g00ecf From 250517d2d3716cf0b8b7f66d0b16f5f5617a7611 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 17 Oct 2016 00:08:43 -0400 Subject: test-calendarspec: test that hourly timers are incremented properly Apparently this works just fine, so the issue in #4031 is elsewhere. --- src/test/test-calendarspec.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c index 57d9da4855..752ad0aca8 100644 --- a/src/test/test-calendarspec.c +++ b/src/test/test-calendarspec.c @@ -73,7 +73,7 @@ static void test_next(const char *input, const char *new_tz, usec_t after, usec_ u = after; r = calendar_spec_next_usec(c, after, &u); - printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof(buf), u)); + printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u)); if (expect != (usec_t)-1) assert_se(r >= 0 && u == expect); else @@ -109,6 +109,28 @@ static void test_timestamp(void) { assert_se(y == x); } +static void test_hourly_bug_4031(void) { + CalendarSpec *c; + usec_t n, u, w; + char buf[FORMAT_TIMESTAMP_MAX], zaf[FORMAT_TIMESTAMP_MAX]; + int r; + + assert_se(calendar_spec_from_string("hourly", &c) >= 0); + n = now(CLOCK_REALTIME); + assert_se((r = calendar_spec_next_usec(c, n, &u)) >= 0); + + printf("Now: %s (%"PRIu64")\n", format_timestamp_us(buf, sizeof buf, n), n); + printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u), u); + + assert_se((r = calendar_spec_next_usec(c, u, &w)) >= 0); + printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(zaf, sizeof zaf, w), w); + + assert_se(n < u); + assert_se(u <= n + USEC_PER_HOUR); + assert_se(u < w); + assert_se(w <= u + USEC_PER_HOUR); +} + int main(int argc, char* argv[]) { CalendarSpec *c; @@ -177,6 +199,7 @@ int main(int argc, char* argv[]) { assert_se(calendar_spec_from_string("00:00:00.0..00.9", &c) < 0); test_timestamp(); + test_hourly_bug_4031(); return 0; } -- cgit v1.2.3-54-g00ecf From ba25d39e449347952522162c3fa110b04308e28c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 17 Oct 2016 01:15:03 -0400 Subject: pid1: do not use mtime==0 as sign of masking (#4388) It is allowed for unit files to have an mtime==0, so instead of assuming that any file that had mtime==0 was masked, use the load_state to filter masked units. Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1384150. --- src/core/unit.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/core/unit.c b/src/core/unit.c index a6b8ecdcb7..b24ca5aed8 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -3053,7 +3053,7 @@ int unit_coldplug(Unit *u) { return r; } -static bool fragment_mtime_newer(const char *path, usec_t mtime) { +static bool fragment_mtime_newer(const char *path, usec_t mtime, bool path_masked) { struct stat st; if (!path) @@ -3063,12 +3063,12 @@ static bool fragment_mtime_newer(const char *path, usec_t mtime) { /* What, cannot access this anymore? */ return true; - if (mtime > 0) + if (path_masked) + /* For masked files check if they are still so */ + return !null_or_empty(&st); + else /* For non-empty files check the mtime */ return timespec_load(&st.st_mtim) > mtime; - else if (!null_or_empty(&st)) - /* For masked files check if they are still so */ - return true; return false; } @@ -3079,18 +3079,22 @@ bool unit_need_daemon_reload(Unit *u) { assert(u); - if (fragment_mtime_newer(u->fragment_path, u->fragment_mtime)) + /* For unit files, we allow masking… */ + if (fragment_mtime_newer(u->fragment_path, u->fragment_mtime, + u->load_state == UNIT_MASKED)) return true; - if (fragment_mtime_newer(u->source_path, u->source_mtime)) + /* Source paths should not be masked… */ + if (fragment_mtime_newer(u->source_path, u->source_mtime, false)) return true; (void) unit_find_dropin_paths(u, &t); if (!strv_equal(u->dropin_paths, t)) return true; + /* … any drop-ins that are masked are simply omitted from the list. */ STRV_FOREACH(path, u->dropin_paths) - if (fragment_mtime_newer(*path, u->dropin_mtime)) + if (fragment_mtime_newer(*path, u->dropin_mtime, false)) return true; return false; -- cgit v1.2.3-54-g00ecf From 6e2c9ce1b6940c93d1bfdb26d75dec5a2885664b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 17 Oct 2016 02:05:30 -0400 Subject: core/timer: reset next_elapse_*time when timer is not waiting When the unit that is triggered by a timer is started and running, we transition to "running" state, and the timer will not elapse again until the unit has finished running. In this state "systemctl list-timers" would display the previously calculated next elapse time, which would now of course be in the past, leading to nonsensical values. Simply set the next elapse to infinity, which causes list-timers to show n/a. We cannot specify when the next elapse will happen, possibly never. Fixes #4031. --- src/core/timer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/timer.c b/src/core/timer.c index 9538059c13..2469a517ea 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -261,6 +261,8 @@ static void timer_set_state(Timer *t, TimerState state) { if (state != TIMER_WAITING) { t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source); t->realtime_event_source = sd_event_source_unref(t->realtime_event_source); + t->next_elapse_monotonic_or_boottime = USEC_INFINITY; + t->next_elapse_realtime = USEC_INFINITY; } if (state != old_state) -- cgit v1.2.3-54-g00ecf From 9b914a9d6b8279eecbf2c30f97e7aa6b21f03f5d Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 19:44:40 -0400 Subject: man: mention that systemctl --root=/ operates on the fs directly --- man/systemctl.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index b51badf7fe..75885bcf02 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -544,8 +544,10 @@ When used with enable/disable/is-enabled - (and related commands), use an alternate root path when - looking for unit files. + (and related commands), use the specified root path when looking for unit + files. If this option is present, systemctl will operate on + the file system directly, instead of communicating with the systemd + daemon to carry out changes. -- cgit v1.2.3-54-g00ecf From 010454b459ef59bab2f9ddd994e4f50491ced371 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 21:20:08 -0400 Subject: shared/install: do not break loop when we enounter a dangling symlink We should ignore that unit, but otherwise continue. --- src/shared/install.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/install.c b/src/shared/install.c index 60a6d1312d..bcb169e7df 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1767,7 +1767,7 @@ static int install_context_mark_for_removal( r = install_info_traverse(scope, c, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL); if (r == -ENOLINK) - return 0; + continue; else if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 6c9414a700a040be1d3160bd2336baac58a1da3e Mon Sep 17 00:00:00 2001 From: llua Date: Mon, 17 Oct 2016 08:35:26 -0400 Subject: zsh-completion: fix for #4318 (#4394) Escape unit names for the eval call in _call_program The value of the Id property is transformed back into a unit name usable by systemctl. system-systemd\x5cx2dcryptsetup.slice -> system-systemd\x2dcryptsetup.slice Also filter units by property via parameter expansion, not a for loop --- shell-completion/zsh/_systemctl.in | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in index b525286932..03a1c930b0 100644 --- a/shell-completion/zsh/_systemctl.in +++ b/shell-completion/zsh/_systemctl.in @@ -123,15 +123,11 @@ _systemctl_really_all_units() } _filter_units_by_property() { - local property=$1 value=$2 ; shift ; shift - local -a units ; units=($*) - local props - for props in ${(ps:\n\n:)"$(_call_program units "$service $_sys_service_mgr show --no-pager --property="Id,$property" -- ${units} 2>/dev/null")"}; do - props=(${(f)props}) - if [[ "${props[2]}" = "$property=$value" ]]; then - echo -E - " ${props[1]#Id=}" - fi - done + local property=$1 value=$2; shift 2 + local -a units; units=("${(q-)@}") + local -A props + props=(${(f)"$(_call_program units "$service $_sys_service_mgr show --no-pager --property=\"Id,$property\" -- ${units} 2>/dev/null")"}) + echo -E - "${(@g:o:)${(k@)props[(Re)$property=$value]}#Id=}" } _systemctl_get_template_names() { echo -E - ${^${(M)${(f)"$(__systemctl list-unit-files)"}##*@.[^[:space:]]##}%%@.*}\@ } -- cgit v1.2.3-54-g00ecf From c7458f93991105e9890b0ec8dfc849b019b5df5f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 17 Oct 2016 15:50:26 +0200 Subject: man: avoid abbreviated "cgroups" terminology (#4396) Let's avoid the overly abbreviated "cgroups" terminology. Let's instead write: "Linux Control Groups (cgroups)" is the long form wherever the term is introduced in prose. Use "control groups" in the short form wherever the term is used within brief explanations. Follow-up to: #4381 --- man/sd_bus_creds_get_pid.xml | 2 +- man/systemd.exec.xml | 3 +-- man/systemd.resource-control.xml | 12 +++++------- man/systemd.unit.xml | 2 +- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/man/sd_bus_creds_get_pid.xml b/man/sd_bus_creds_get_pid.xml index 4c05835568..9e68d5e8c7 100644 --- a/man/sd_bus_creds_get_pid.xml +++ b/man/sd_bus_creds_get_pid.xml @@ -366,7 +366,7 @@ -ENXIO is returned. sd_bus_creds_get_cgroup() will retrieve - the cgroup path. See cgroups.txt. diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 6228b786f7..a5a453031f 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -75,8 +75,7 @@ [Service], [Socket], [Mount], or [Swap] sections, depending on the unit type. - In addition, options which control resources through cgroups - are listed in + In addition, options which control resources through Linux Control Groups (cgroups) are listed in systemd.resource-control5. Those options complement options listed here. diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index a97bcca9df..02878b28a0 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -60,12 +60,10 @@ Description - Unit configuration files for services, slices, scopes, - sockets, mount points, and swap devices share a subset of - configuration options for resource control of spawned - processes. Internally, this relies on the Control Groups - kernel concept for organizing processes in a hierarchical tree of - named groups for the purpose of resource management. + Unit configuration files for services, slices, scopes, sockets, mount points, and swap devices share a subset + of configuration options for resource control of spawned processes. Internally, this relies on the Linux Control + Groups (cgroups) kernel concept for organizing processes in a hierarchical tree of named groups for the purpose of + resource management. This man page lists the configuration options shared by those six unit types. See @@ -116,7 +114,7 @@ Due to the lack of consensus in the kernel community, the CPU controller support on the unified - cgroup hierarchy requires out-of-tree kernel patches. See cgroup-v2-cpu.txt. CPUWeight= and StartupCPUWeight= replace diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index a4f5711d7a..04efee2891 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -1252,7 +1252,7 @@ %r Control group path of the slice the unit is placed in - This usually maps to the parent cgroup path of %c. + This usually maps to the parent control group path of %c. %R -- cgit v1.2.3-54-g00ecf From 16484a8a1506abcac057825dc5d28c52949023cc Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 17 Oct 2016 11:37:41 -0400 Subject: systemctl: use underlines to seperate unit types in listing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (printf("%.*s", -1, "…") is the same as not specifying the precision at all.) v2: also underline highlighted (failing) units Fixes #4137. --- src/basic/terminal-util.h | 20 ++++++++++++++ src/systemctl/systemctl.c | 69 ++++++++++++++++++++++++++++------------------- 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index 169ab772ff..6b47c17278 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -36,6 +36,10 @@ #define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m" #define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m" #define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m" +#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m" +#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m" +#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;33m" +#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m" #define ANSI_NORMAL "\x1B[0m" #define ANSI_ERASE_TO_END_OF_LINE "\x1B[K" @@ -111,6 +115,22 @@ static inline const char *ansi_highlight_blue(void) { return colors_enabled() ? ANSI_HIGHLIGHT_BLUE : ""; } +static inline const char *ansi_highlight_red_underline(void) { + return colors_enabled() ? ANSI_HIGHLIGHT_RED_UNDERLINE : ""; +} + +static inline const char *ansi_highlight_green_underline(void) { + return colors_enabled() ? ANSI_HIGHLIGHT_GREEN_UNDERLINE : ""; +} + +static inline const char *ansi_highlight_yellow_underline(void) { + return colors_enabled() ? ANSI_HIGHLIGHT_YELLOW_UNDERLINE : ""; +} + +static inline const char *ansi_highlight_blue_underline(void) { + return colors_enabled() ? ANSI_HIGHLIGHT_BLUE_UNDERLINE : ""; +} + static inline const char *ansi_normal(void) { return colors_enabled() ? ANSI_NORMAL : ""; } diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 7ed60dbe87..8b08b1762f 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -362,22 +362,24 @@ static int compare_unit_info(const void *a, const void *b) { return strcasecmp(u->id, v->id); } +static const char* unit_type_suffix(const char *name) { + const char *dot; + + dot = strrchr(name, '.'); + if (!dot) + return ""; + + return dot + 1; +} + static bool output_show_unit(const UnitInfo *u, char **patterns) { assert(u); if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE)) return false; - if (arg_types) { - const char *dot; - - dot = strrchr(u->id, '.'); - if (!dot) - return false; - - if (!strv_find(arg_types, dot+1)) - return false; - } + if (arg_types && !strv_find(arg_types, unit_type_suffix(u->id))) + return false; if (arg_all) return true; @@ -403,10 +405,10 @@ static bool output_show_unit(const UnitInfo *u, char **patterns) { } static int output_units_list(const UnitInfo *unit_infos, unsigned c) { - unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len; + unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len; const UnitInfo *u; unsigned n_shown = 0; - int job_count = 0; + int job_count = 0, desc_len; max_id_len = strlen("UNIT"); load_len = strlen("LOAD"); @@ -464,18 +466,20 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { for (u = unit_infos; u < unit_infos + c; u++) { _cleanup_free_ char *e = NULL, *j = NULL; + const char *on_underline = "", *off_underline = ""; const char *on_loaded = "", *off_loaded = ""; const char *on_active = "", *off_active = ""; const char *on_circle = "", *off_circle = ""; const char *id; - bool circle = false; + bool circle = false, underline = false; if (!n_shown && !arg_no_legend) { if (circle_len > 0) fputs(" ", stdout); - printf("%-*s %-*s %-*s %-*s ", + printf("%s%-*s %-*s %-*s %-*s ", + ansi_underline(), id_len, "UNIT", load_len, "LOAD", active_len, "ACTIVE", @@ -484,23 +488,33 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { if (job_count) printf("%-*s ", job_len, "JOB"); - if (!arg_full && arg_no_pager) - printf("%.*s\n", desc_len, "DESCRIPTION"); - else - printf("%s\n", "DESCRIPTION"); + printf("%.*s%s\n", + !arg_full && arg_no_pager ? desc_len : -1, + "DESCRIPTION", + ansi_normal()); } n_shown++; + if (u + 1 < unit_infos + c && + !streq(unit_type_suffix(u->id), unit_type_suffix((u + 1)->id))) { + on_underline = ansi_underline(); + off_underline = ansi_normal(); + underline = true; + } + if (STR_IN_SET(u->load_state, "error", "not-found", "masked") && !arg_plain) { - on_loaded = ansi_highlight_red(); on_circle = ansi_highlight_yellow(); - off_loaded = off_circle = ansi_normal(); + off_circle = ansi_normal(); circle = true; + on_loaded = underline ? ansi_highlight_red_underline() : ansi_highlight_red(); + off_loaded = on_underline; } else if (streq(u->active_state, "failed") && !arg_plain) { - on_circle = on_active = ansi_highlight_red(); - off_circle = off_active = ansi_normal(); + on_circle = ansi_highlight_red(); + off_circle = ansi_normal(); circle = true; + on_active = underline ? ansi_highlight_red_underline() : ansi_highlight_red(); + off_active = on_underline; } if (u->machine) { @@ -523,17 +537,18 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { if (circle_len > 0) printf("%s%s%s ", on_circle, circle ? special_glyph(BLACK_CIRCLE) : " ", off_circle); - printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s", + printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s", + on_underline, on_active, id_len, id, off_active, on_loaded, load_len, u->load_state, off_loaded, on_active, active_len, u->active_state, sub_len, u->sub_state, off_active, job_count ? job_len + 1 : 0, u->job_id ? u->job_type : ""); - if (desc_len > 0) - printf("%.*s\n", desc_len, u->description); - else - printf("%s\n", u->description); + printf("%.*s%s\n", + desc_len > 0 ? desc_len : -1, + u->description, + off_underline); } if (!arg_no_legend) { -- cgit v1.2.3-54-g00ecf From 6ae3e62a5415ec367528456e230e75800045d276 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 17 Oct 2016 11:37:55 -0400 Subject: systemctl: ditto for list-unit-files --- src/systemctl/systemctl.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 8b08b1762f..129706d15f 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -1410,35 +1410,46 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) { id_cols = max_id_len; if (!arg_no_legend && c > 0) - printf("%-*s %-*s\n", + printf("%s%-*s %-*s%s\n", + ansi_underline(), id_cols, "UNIT FILE", - state_cols, "STATE"); + state_cols, "STATE", + ansi_normal()); for (u = units; u < units + c; u++) { _cleanup_free_ char *e = NULL; - const char *on, *off; + const char *on, *off, *on_underline = "", *off_underline = ""; const char *id; + bool underline = false; + + if (u + 1 < units + c && + !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path))) { + on_underline = ansi_underline(); + off_underline = ansi_normal(); + underline = true; + } if (IN_SET(u->state, UNIT_FILE_MASKED, UNIT_FILE_MASKED_RUNTIME, UNIT_FILE_DISABLED, - UNIT_FILE_BAD)) { - on = ansi_highlight_red(); - off = ansi_normal(); - } else if (u->state == UNIT_FILE_ENABLED) { - on = ansi_highlight_green(); - off = ansi_normal(); - } else - on = off = ""; + UNIT_FILE_BAD)) + on = underline ? ansi_highlight_red_underline() : ansi_highlight_red(); + else if (u->state == UNIT_FILE_ENABLED) + on = underline ? ansi_highlight_green_underline() : ansi_highlight_green(); + else + on = on_underline; + off = off_underline; id = basename(u->path); e = arg_full ? NULL : ellipsize(id, id_cols, 33); - printf("%-*s %s%-*s%s\n", + printf("%s%-*s %s%-*s%s%s\n", + on_underline, id_cols, e ? e : id, - on, state_cols, unit_file_state_to_string(u->state), off); + on, state_cols, unit_file_state_to_string(u->state), off, + off_underline); } if (!arg_no_legend) -- cgit v1.2.3-54-g00ecf From 5c98198f67199802a760851d969fc6a9cf8eae9b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 17 Oct 2016 11:48:12 -0400 Subject: terminal-util: helper macro for highlighting functions --- src/basic/terminal-util.h | 65 +++++++++++++---------------------------------- 1 file changed, 18 insertions(+), 47 deletions(-) diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index 6b47c17278..b862bfaf05 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -87,53 +87,24 @@ bool on_tty(void); bool terminal_is_dumb(void); bool colors_enabled(void); -static inline const char *ansi_underline(void) { - return colors_enabled() ? ANSI_UNDERLINE : ""; -} - -static inline const char *ansi_highlight(void) { - return colors_enabled() ? ANSI_HIGHLIGHT : ""; -} - -static inline const char *ansi_highlight_underline(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_UNDERLINE : ""; -} - -static inline const char *ansi_highlight_red(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_RED : ""; -} - -static inline const char *ansi_highlight_green(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_GREEN : ""; -} - -static inline const char *ansi_highlight_yellow(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_YELLOW : ""; -} - -static inline const char *ansi_highlight_blue(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_BLUE : ""; -} - -static inline const char *ansi_highlight_red_underline(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_RED_UNDERLINE : ""; -} - -static inline const char *ansi_highlight_green_underline(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_GREEN_UNDERLINE : ""; -} - -static inline const char *ansi_highlight_yellow_underline(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_YELLOW_UNDERLINE : ""; -} - -static inline const char *ansi_highlight_blue_underline(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_BLUE_UNDERLINE : ""; -} - -static inline const char *ansi_normal(void) { - return colors_enabled() ? ANSI_NORMAL : ""; -} +#define DEFINE_ANSI_FUNC(name, NAME) \ + static inline const char *ansi_##name(void) { \ + return colors_enabled() ? ANSI_##NAME : ""; \ + } \ + struct __useless_struct_to_allow_trailing_semicolon__ + +DEFINE_ANSI_FUNC(underline, UNDERLINE); +DEFINE_ANSI_FUNC(highlight, HIGHLIGHT); +DEFINE_ANSI_FUNC(highlight_underline, HIGHLIGHT_UNDERLINE); +DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED); +DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN); +DEFINE_ANSI_FUNC(highlight_yellow, HIGHLIGHT_YELLOW); +DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE); +DEFINE_ANSI_FUNC(highlight_red_underline, HIGHLIGHT_RED_UNDERLINE); +DEFINE_ANSI_FUNC(highlight_green_underline, HIGHLIGHT_GREEN_UNDERLINE); +DEFINE_ANSI_FUNC(highlight_yellow_underline, HIGHLIGHT_YELLOW_UNDERLINE); +DEFINE_ANSI_FUNC(highlight_blue_underline, HIGHLIGHT_BLUE_UNDERLINE); +DEFINE_ANSI_FUNC(normal, NORMAL); int get_ctty_devnr(pid_t pid, dev_t *d); int get_ctty(pid_t, dev_t *_devnr, char **r); -- cgit v1.2.3-54-g00ecf From caf15ff01e7ebd83b09e7ad6e0446b24d0041beb Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 17 Oct 2016 12:22:44 -0400 Subject: man: add a note that NULL "s" arg for sd_bus_message_append --- man/sd_bus_message_append.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/man/sd_bus_message_append.xml b/man/sd_bus_message_append.xml index 77fce02eae..c222d0fd0e 100644 --- a/man/sd_bus_message_append.xml +++ b/man/sd_bus_message_append.xml @@ -169,6 +169,11 @@
+ For types "s" and "g" (unicode string or signature), the pointer may be + NULL, which is equivalent to an empty string. See + sd_bus_message_append_basic3 + for the precise interpretation of those and other types. + -- cgit v1.2.3-54-g00ecf From c7934185fec8e7746f0660df71b3c03d48a0b132 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Fri, 14 Oct 2016 18:42:46 +0000 Subject: tests: add smoke test for systemd-nspawn Basically, this test runs: ``` systemd-nspawn --register=no -D "$_root" -b systemd-nspawn --register=no -D "$_root" --private-network -b systemd-nspawn --register=no -D "$_root" -U -b systemd-nspawn --register=no -D "$_root" --private-network -U -b ``` and exports the `UNIFIED_CGROUP_HIERARCHY=[yes|no]`, `SYSTEMD_NSPAWN_USE_CGNS=[yes|no]` Inspired by * systemd#3589 (comment) * systemd#4372 (comment) * systemd#4223 (comment) * systemd#1555 and so on :-) --- Makefile.am | 4 + test/TEST-13-NSPAWN-SMOKE/Makefile | 11 ++ test/TEST-13-NSPAWN-SMOKE/create-busybox-container | 53 ++++++++ test/TEST-13-NSPAWN-SMOKE/has-overflow.c | 143 +++++++++++++++++++++ test/TEST-13-NSPAWN-SMOKE/test.sh | 138 ++++++++++++++++++++ 5 files changed, 349 insertions(+) create mode 100644 test/TEST-13-NSPAWN-SMOKE/Makefile create mode 100755 test/TEST-13-NSPAWN-SMOKE/create-busybox-container create mode 100644 test/TEST-13-NSPAWN-SMOKE/has-overflow.c create mode 100755 test/TEST-13-NSPAWN-SMOKE/test.sh diff --git a/Makefile.am b/Makefile.am index a0c17db179..00124a29f8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6030,6 +6030,10 @@ EXTRA_DIST += \ test/TEST-11-ISSUE-3166/test.sh \ test/TEST-12-ISSUE-3171/Makefile \ test/TEST-12-ISSUE-3171/test.sh \ + test/TEST-13-NSPAWN-SMOKE/Makefile \ + test/TEST-13-NSPAWN-SMOKE/has-overflow.c \ + test/TEST-13-NSPAWN-SMOKE/create-busybox-container \ + test/TEST-13-NSPAWN-SMOKE/test.sh \ test/test-functions EXTRA_DIST += \ diff --git a/test/TEST-13-NSPAWN-SMOKE/Makefile b/test/TEST-13-NSPAWN-SMOKE/Makefile new file mode 100644 index 0000000000..2ca5b12cf3 --- /dev/null +++ b/test/TEST-13-NSPAWN-SMOKE/Makefile @@ -0,0 +1,11 @@ +all: has-overflow + @make -s --no-print-directory -C ../.. all + @basedir=../.. TEST_BASE_DIR=../ ./test.sh --all +setup: has-overflow + @make --no-print-directory -C ../.. all + @basedir=../.. TEST_BASE_DIR=../ ./test.sh --setup +clean: + @basedir=../.. TEST_BASE_DIR=../ ./test.sh --clean + @rm -f has-overflow +run: + @basedir=../.. TEST_BASE_DIR=../ ./test.sh --run diff --git a/test/TEST-13-NSPAWN-SMOKE/create-busybox-container b/test/TEST-13-NSPAWN-SMOKE/create-busybox-container new file mode 100755 index 0000000000..868dfd852a --- /dev/null +++ b/test/TEST-13-NSPAWN-SMOKE/create-busybox-container @@ -0,0 +1,53 @@ +#!/bin/bash + +set -e +set -u +set -o pipefail + +root="${1:?Usage $0 container-root}" +mkdir -p "$root" +mkdir "$root/bin" +cp $(type -P busybox) "$root/bin" + +mkdir -p "$root/usr/lib" +touch "$root/usr/lib/os-release" + +ln -s busybox "$root/bin/sh" +ln -s busybox "$root/bin/cat" +ln -s busybox "$root/bin/tr" +ln -s busybox "$root/bin/ps" +ln -s busybox "$root/bin/ip" + +mkdir -p "$root/sbin" +cat <<'EOF' >"$root/sbin/init" +#!/bin/sh + +printf "ps aufx:\n" +ps aufx + +printf "/proc/1/cmdline:\n" +printf "%s\n\n" "$(tr '\0' ' ' +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) + +struct child_args { + int pipe_fd[2]; /* Pipe used to synchronize parent and child */ +}; + +static void usage(char *pname) { + fprintf(stderr, "Options can be:\n"); + fprintf(stderr, "\t-M uid_map Specify UID map for user namespace\n"); + fprintf(stderr, "\t-G gid_map Specify GID map for user namespace\n"); + + exit(EXIT_FAILURE); +} + +static void update_map(char *mapping, char *map_file) { + int fd, j; + size_t map_len; + + map_len = strlen(mapping); + + fd = open(map_file, O_RDWR); + if (fd == -1) { + fprintf(stderr, "ERROR: open %s: %s\n", map_file, strerror(errno)); + exit(EXIT_FAILURE); + } + + if (write(fd, mapping, map_len) != map_len) { + fprintf(stderr, "ERROR: write %s: %s\n", map_file, strerror(errno)); + exit(EXIT_FAILURE); + } + + close(fd); +} + +static void proc_setgroups_write(pid_t child_pid, char *str) { + char setgroups_path[PATH_MAX]; + int fd; + + snprintf(setgroups_path, PATH_MAX, "/proc/%ld/setgroups", (long) child_pid); + + fd = open(setgroups_path, O_RDWR); + if (fd == -1) { + if (errno != ENOENT) + fprintf(stderr, "ERROR: open %s: %s\n", setgroups_path, strerror(errno)); + return; + } + + if (write(fd, str, strlen(str)) == -1) + fprintf(stderr, "ERROR: write %s: %s\n", setgroups_path, strerror(errno)); + + close(fd); +} + +static int child_func(void *arg) { + struct child_args *args = (struct child_args *) arg; + char ch; + + close(args->pipe_fd[1]); + if (read(args->pipe_fd[0], &ch, 1) != 0) { + fprintf(stderr, "Failure in child: read from pipe returned != 0\n"); + exit(EXIT_FAILURE); + } + + mount("tmpfs", "/tmp", "tmpfs", MS_MGC_VAL, "mode=777,uid=0,gid=0"); + if (mkdir("/tmp/hey", 0777) < 0) + exit(EXIT_FAILURE); + + exit(EXIT_SUCCESS); +} + +#define STACK_SIZE (1024 * 1024) + +static char child_stack[STACK_SIZE]; + +int main(int argc, char *argv[]) { + int flags, opt; + pid_t child_pid; + struct child_args args; + char *uid_map, *gid_map; + const int MAP_BUF_SIZE = 100; + char map_buf[MAP_BUF_SIZE]; + char map_path[PATH_MAX]; + int status; + + flags = 0; + gid_map = NULL; + uid_map = NULL; + while ((opt = getopt(argc, argv, "+M:G:")) != -1) { + switch (opt) { + case 'M': + uid_map = optarg; + break; + case 'G': + gid_map = optarg; + break; + default: + usage(argv[0]); + } + } + + if (!uid_map || !gid_map) + usage(argv[0]); + + flags |= CLONE_NEWNS; + flags |= CLONE_NEWUSER; + + if (pipe(args.pipe_fd) == -1) + errExit("pipe"); + + child_pid = clone(child_func, child_stack + STACK_SIZE, flags | SIGCHLD, &args); + if (child_pid == -1) + errExit("clone"); + + snprintf(map_path, PATH_MAX, "/proc/%ld/uid_map", (long) child_pid); + update_map(uid_map, map_path); + + proc_setgroups_write(child_pid, "allow"); + snprintf(map_path, PATH_MAX, "/proc/%ld/gid_map", (long) child_pid); + update_map(gid_map, map_path); + + close(args.pipe_fd[1]); + + if (waitpid(child_pid, &status, 0) == -1) + errExit("waitpid"); + + exit(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS ? EXIT_FAILURE : EXIT_SUCCESS); +} diff --git a/test/TEST-13-NSPAWN-SMOKE/test.sh b/test/TEST-13-NSPAWN-SMOKE/test.sh new file mode 100755 index 0000000000..dfc437c0ee --- /dev/null +++ b/test/TEST-13-NSPAWN-SMOKE/test.sh @@ -0,0 +1,138 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh +TEST_DESCRIPTION="systemd-nspawn smoke test" +SKIP_INITRD=yes +. $TEST_BASE_DIR/test-functions + +check_result_qemu() { + ret=1 + mkdir -p $TESTDIR/root + mount ${LOOPDEV}p1 $TESTDIR/root + [[ -e $TESTDIR/root/testok ]] && ret=0 + [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR + cp -a $TESTDIR/root/var/log/journal $TESTDIR + umount $TESTDIR/root + [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed + ls -l $TESTDIR/journal/*/*.journal + test -s $TESTDIR/failed && ret=$(($ret+1)) + return $ret +} + +test_run() { + if run_qemu; then + check_result_qemu || return 1 + else + dwarn "can't run QEMU, skipping" + fi + return 0 +} + +test_setup() { + create_empty_image + mkdir -p $TESTDIR/root + mount ${LOOPDEV}p1 $TESTDIR/root + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + dracut_install busybox chmod rmdir + dracut_install ./has-overflow + + cp create-busybox-container $initdir/ + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <$initdir/test-nspawn.sh <<'EOF' +#!/bin/bash +set -x +set -e +set -u +set -o pipefail + +export SYSTEMD_LOG_LEVEL=debug + +# check cgroup-v2 +is_v2_supported=no +mkdir -p /tmp/cgroup2 +if mount -t cgroup2 cgroup2 /tmp/cgroup2; then + is_v2_supported=yes + umount /tmp/cgroup2 +fi +rmdir /tmp/cgroup2 + +# check cgroup namespaces +is_cgns_supported=no +if [[ -f /proc/1/ns/cgroup ]]; then + is_cgns_supported=yes +fi + +function run { + if [[ "$1" = "yes" && "$is_v2_supported" = "no" ]]; then + printf "Unified cgroup hierarchy is not supported. Skipping.\n" >&2 + return 0 + fi + if [[ "$2" = "yes" && "$is_cgns_supported" = "no" ]]; then + printf "Cgroup namespaces are not supported. Skipping.\n" >&2 + return 0 + fi + + local _root="/var/lib/machines/unified-$1-cgns-$2" + /create-busybox-container "$_root" + UNIFIED_CGROUP_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" systemd-nspawn --register=no -D "$_root" -b + UNIFIED_CGROUP_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" systemd-nspawn --register=no -D "$_root" --private-network -b + + if ! UNIFIED_CGROUP_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" systemd-nspawn --register=no -D "$_root" -U -b; then + if [[ "$1" = "no" && "$2" = "yes" ]] && /has-overflow -M '0 1073283072 65536' -G '0 1073283072 65536'; then + printf "Failure expected, ignoring (see https://github.com/systemd/systemd/issues/4352)\n" >&2 + else + return 1 + fi + fi + + if ! UNIFIED_CGROUP_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" systemd-nspawn --register=no -D "$_root" --private-network -U -b; then + if [[ "$1" = "no" && "$2" = "yes" ]] && /has-overflow -M '0 1073283072 65536' -G '0 1073283072 65536'; then + printf "Failure expected, ignoring (see https://github.com/systemd/systemd/issues/4352)\n" >&2 + else + return 1 + fi + fi + + return 0 +} + +run no no +run yes no +run no yes +run yes yes + +touch /testok +EOF + + chmod 0755 $initdir/test-nspawn.sh + setup_testsuite + ) || return 1 + + ddebug "umount $TESTDIR/root" + umount $TESTDIR/root +} + +test_cleanup() { + umount $TESTDIR/root 2>/dev/null + [[ $LOOPDEV ]] && losetup -d $LOOPDEV + return 0 +} + +do_test "$@" -- cgit v1.2.3-54-g00ecf From a2fc3d87fb681c53a001bcc42470b647b25e3821 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 15 Oct 2016 20:51:19 -0400 Subject: README: list dependencies for testing Fixes #4365. --- README | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README b/README index d610baaf76..9f5bc93827 100644 --- a/README +++ b/README @@ -169,6 +169,13 @@ REQUIREMENTS: under all circumstances. In fact, systemd-hostnamed will warn if nss-myhostname is not installed. + Additional packages are necessary to run some tests: + - busybox (used by test/TEST-13-NSPAWN-SMOKE) + - nc (used by test/TEST-12-ISSUE-3171) + - python3-pyparsing + - python3-evdev (used by hwdb parsing tests) + - strace (used by test/test-functions) + USERS AND GROUPS: Default udev rules use the following standard system group names, which need to be resolvable by getgrnam() at any time, -- cgit v1.2.3-54-g00ecf From 52c239d770d3ef955220c5ae72b852360da67c8b Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Tue, 18 Oct 2016 00:05:49 +0000 Subject: core/exec: add a named-descriptor option ("fd") for streams (#4179) This commit adds a `fd` option to `StandardInput=`, `StandardOutput=` and `StandardError=` properties in order to connect standard streams to externally named descriptors provided by some socket units. This option looks for a file descriptor named as the corresponding stream. Custom names can be specified, separated by a colon. If multiple name-matches exist, the first matching fd will be used. --- man/systemd.exec.xml | 46 +++++++++++++-- src/core/dbus-execute.c | 86 +++++++++++++++++++++++++++- src/core/execute.c | 86 +++++++++++++++++++++++++--- src/core/execute.h | 5 ++ src/core/load-fragment-gperf.gperf.m4 | 6 +- src/core/load-fragment.c | 104 ++++++++++++++++++++++++++++++++-- src/core/load-fragment.h | 2 + src/core/unit.c | 20 +++---- 8 files changed, 322 insertions(+), 33 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index a5a453031f..7453aa7bee 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -409,8 +409,9 @@ , , , - or - . + , + or + . If is selected, standard input will be connected to /dev/null, i.e. all @@ -448,6 +449,20 @@ inetd8 daemon. + The option connects + the input stream to a single file descriptor provided by a socket unit. + A custom named file descriptor can be specified as part of this option, + after a : (e.g. fd:foobar). + If no name is specified, stdin is assumed + (i.e. fd is equivalent to fd:stdin). + At least one socket unit defining such name must be explicitly provided via the + Sockets= option, and file descriptor name may differ + from the name of its containing socket unit. + If multiple matches are found, the first one will be used. + See FileDescriptorName= in + systemd.socket5 + for more details about named descriptors and ordering. + This setting defaults to . @@ -464,8 +479,9 @@ , , , - or - . + , + or + . duplicates the file descriptor of standard input for standard output. @@ -514,6 +530,20 @@ similar to the same option of StandardInput=. + The option connects + the output stream to a single file descriptor provided by a socket unit. + A custom named file descriptor can be specified as part of this option, + after a : (e.g. fd:foobar). + If no name is specified, stdout is assumed + (i.e. fd is equivalent to fd:stdout). + At least one socket unit defining such name must be explicitly provided via the + Sockets= option, and file descriptor name may differ + from the name of its containing socket unit. + If multiple matches are found, the first one will be used. + See FileDescriptorName= in + systemd.socket5 + for more details about named descriptors and ordering. + If the standard output (or error output, see below) of a unit is connected to the journal, syslog or the kernel log buffer, the unit will implicitly gain a dependency of type After= on systemd-journald.socket (also see the automatic dependencies section above). @@ -531,9 +561,13 @@ Controls where file descriptor 2 (STDERR) of the executed processes is connected to. The available options are identical to those of StandardOutput=, - with one exception: if set to the + with some exceptions: if set to the file descriptor used for standard output is duplicated for - standard error. This setting defaults to the value set with + standard error, while operates on the error + stream and will look by default for a descriptor named + stderr. + + This setting defaults to the value set with in systemd-system.conf5, which defaults to . Note that setting diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index b8720d7d3d..1a7f770db1 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -627,6 +627,53 @@ static int property_get_syslog_facility( return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority)); } +static int property_get_input_fdname( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + const char *name; + + assert(bus); + assert(c); + assert(property); + assert(reply); + + name = exec_context_fdname(c, STDIN_FILENO); + + return sd_bus_message_append(reply, "s", name); +} + +static int property_get_output_fdname( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + const char *name = NULL; + + assert(bus); + assert(c); + assert(property); + assert(reply); + + if (c->std_output == EXEC_OUTPUT_NAMED_FD && streq(property, "StandardOutputFileDescriptorName")) + name = exec_context_fdname(c, STDOUT_FILENO); + else if (c->std_error == EXEC_OUTPUT_NAMED_FD && streq(property, "StandardErrorFileDescriptorName")) + name = exec_context_fdname(c, STDERR_FILENO); + + return sd_bus_message_append(reply, "s", name); +} + const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST), @@ -677,8 +724,11 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_input_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_output_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_output_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST), @@ -1030,7 +1080,6 @@ int bus_exec_context_set_transient_property( return 1; - } else if (streq(name, "StandardOutput")) { const char *s; ExecOutput p; @@ -1071,6 +1120,41 @@ int bus_exec_context_set_transient_property( return 1; + } else if (STR_IN_SET(name, + "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) { + const char *s; + + r = sd_bus_message_read(message, "s", &s); + if (r < 0) + return r; + + if (!fdname_is_valid(s)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name"); + + if (mode != UNIT_CHECK) { + if (streq(name, "StandardInputFileDescriptorName")) { + c->std_input = EXEC_INPUT_NAMED_FD; + r = free_and_strdup(&c->stdio_fdname[STDIN_FILENO], s); + if (r < 0) + return r; + unit_write_drop_in_private_format(u, mode, name, "StandardInput=fd:%s", s); + } else if (streq(name, "StandardOutputFileDescriptorName")) { + c->std_output = EXEC_OUTPUT_NAMED_FD; + r = free_and_strdup(&c->stdio_fdname[STDOUT_FILENO], s); + if (r < 0) + return r; + unit_write_drop_in_private_format(u, mode, name, "StandardOutput=fd:%s", s); + } else if (streq(name, "StandardErrorFileDescriptorName")) { + c->std_error = EXEC_OUTPUT_NAMED_FD; + r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], s); + if (r < 0) + return r; + unit_write_drop_in_private_format(u, mode, name, "StandardError=fd:%s", s); + } + } + + return 1; + } else if (STR_IN_SET(name, "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", diff --git a/src/core/execute.c b/src/core/execute.c index 59c2bd0dd2..1b7b4a928d 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -411,7 +411,8 @@ static int fixup_output(ExecOutput std_output, int socket_fd) { static int setup_input( const ExecContext *context, const ExecParameters *params, - int socket_fd) { + int socket_fd, + int named_iofds[3]) { ExecInput i; @@ -461,6 +462,10 @@ static int setup_input( case EXEC_INPUT_SOCKET: return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO; + case EXEC_INPUT_NAMED_FD: + (void) fd_nonblock(named_iofds[STDIN_FILENO], false); + return dup2(named_iofds[STDIN_FILENO], STDIN_FILENO) < 0 ? -errno : STDIN_FILENO; + default: assert_not_reached("Unknown input type"); } @@ -472,6 +477,7 @@ static int setup_output( const ExecParameters *params, int fileno, int socket_fd, + int named_iofds[3], const char *ident, uid_t uid, gid_t gid, @@ -523,7 +529,7 @@ static int setup_output( return fileno; /* Duplicate from stdout if possible */ - if (e == o || e == EXEC_OUTPUT_INHERIT) + if ((e == o && e != EXEC_OUTPUT_NAMED_FD) || e == EXEC_OUTPUT_INHERIT) return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno; o = e; @@ -585,6 +591,10 @@ static int setup_output( assert(socket_fd >= 0); return dup2(socket_fd, fileno) < 0 ? -errno : fileno; + case EXEC_OUTPUT_NAMED_FD: + (void) fd_nonblock(named_iofds[fileno], false); + return dup2(named_iofds[fileno], fileno) < 0 ? -errno : fileno; + default: assert_not_reached("Unknown error type"); } @@ -2157,6 +2167,7 @@ static int exec_child( DynamicCreds *dcreds, char **argv, int socket_fd, + int named_iofds[3], int *fds, unsigned n_fds, char **files_env, int user_lookup_fd, @@ -2298,19 +2309,19 @@ static int exec_child( if (socket_fd >= 0) (void) fd_nonblock(socket_fd, false); - r = setup_input(context, params, socket_fd); + r = setup_input(context, params, socket_fd, named_iofds); if (r < 0) { *exit_status = EXIT_STDIN; return r; } - r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino); + r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino); if (r < 0) { *exit_status = EXIT_STDOUT; return r; } - r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino); + r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino); if (r < 0) { *exit_status = EXIT_STDERR; return r; @@ -2829,6 +2840,7 @@ int exec_spawn(Unit *unit, int *fds = NULL; unsigned n_fds = 0; _cleanup_free_ char *line = NULL; int socket_fd, r; + int named_iofds[3] = { -1, -1, -1 }; char **argv; pid_t pid; @@ -2855,6 +2867,10 @@ int exec_spawn(Unit *unit, n_fds = params->n_fds; } + r = exec_context_named_iofds(unit, context, params, named_iofds); + if (r < 0) + return log_unit_error_errno(unit, r, "Failed to load a named file descriptor: %m"); + r = exec_context_load_environment(unit, context, &files_env); if (r < 0) return log_unit_error_errno(unit, r, "Failed to load environment files: %m"); @@ -2884,6 +2900,7 @@ int exec_spawn(Unit *unit, dcreds, argv, socket_fd, + named_iofds, fds, n_fds, files_env, unit->manager->user_lookup_fds[1], @@ -2946,6 +2963,9 @@ void exec_context_done(ExecContext *c) { for (l = 0; l < ELEMENTSOF(c->rlimit); l++) c->rlimit[l] = mfree(c->rlimit[l]); + for (l = 0; l < 3; l++) + c->stdio_fdname[l] = mfree(c->stdio_fdname[l]); + c->working_directory = mfree(c->working_directory); c->root_directory = mfree(c->root_directory); c->tty_path = mfree(c->tty_path); @@ -3044,6 +3064,56 @@ static void invalid_env(const char *p, void *userdata) { log_unit_error(info->unit, "Ignoring invalid environment assignment '%s': %s", p, info->path); } +const char* exec_context_fdname(const ExecContext *c, int fd_index) { + assert(c); + + switch (fd_index) { + case STDIN_FILENO: + if (c->std_input != EXEC_INPUT_NAMED_FD) + return NULL; + return c->stdio_fdname[STDIN_FILENO] ?: "stdin"; + case STDOUT_FILENO: + if (c->std_output != EXEC_OUTPUT_NAMED_FD) + return NULL; + return c->stdio_fdname[STDOUT_FILENO] ?: "stdout"; + case STDERR_FILENO: + if (c->std_error != EXEC_OUTPUT_NAMED_FD) + return NULL; + return c->stdio_fdname[STDERR_FILENO] ?: "stderr"; + default: + return NULL; + } +} + +int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParameters *p, int named_iofds[3]) { + unsigned i, targets; + const char *stdio_fdname[3]; + + assert(c); + assert(p); + + targets = (c->std_input == EXEC_INPUT_NAMED_FD) + + (c->std_output == EXEC_OUTPUT_NAMED_FD) + + (c->std_error == EXEC_OUTPUT_NAMED_FD); + + for (i = 0; i < 3; i++) + stdio_fdname[i] = exec_context_fdname(c, i); + + for (i = 0; i < p->n_fds && targets > 0; i++) + if (named_iofds[STDIN_FILENO] < 0 && c->std_input == EXEC_INPUT_NAMED_FD && stdio_fdname[STDIN_FILENO] && streq(p->fd_names[i], stdio_fdname[STDIN_FILENO])) { + named_iofds[STDIN_FILENO] = p->fds[i]; + targets--; + } else if (named_iofds[STDOUT_FILENO] < 0 && c->std_output == EXEC_OUTPUT_NAMED_FD && stdio_fdname[STDOUT_FILENO] && streq(p->fd_names[i], stdio_fdname[STDOUT_FILENO])) { + named_iofds[STDOUT_FILENO] = p->fds[i]; + targets--; + } else if (named_iofds[STDERR_FILENO] < 0 && c->std_error == EXEC_OUTPUT_NAMED_FD && stdio_fdname[STDERR_FILENO] && streq(p->fd_names[i], stdio_fdname[STDERR_FILENO])) { + named_iofds[STDERR_FILENO] = p->fds[i]; + targets--; + } + + return (targets == 0 ? 0 : -ENOENT); +} + int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) { char **i, **r = NULL; @@ -3896,7 +3966,8 @@ static const char* const exec_input_table[_EXEC_INPUT_MAX] = { [EXEC_INPUT_TTY] = "tty", [EXEC_INPUT_TTY_FORCE] = "tty-force", [EXEC_INPUT_TTY_FAIL] = "tty-fail", - [EXEC_INPUT_SOCKET] = "socket" + [EXEC_INPUT_SOCKET] = "socket", + [EXEC_INPUT_NAMED_FD] = "fd", }; DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput); @@ -3911,7 +3982,8 @@ static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = { [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console", [EXEC_OUTPUT_JOURNAL] = "journal", [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console", - [EXEC_OUTPUT_SOCKET] = "socket" + [EXEC_OUTPUT_SOCKET] = "socket", + [EXEC_OUTPUT_NAMED_FD] = "fd", }; DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput); diff --git a/src/core/execute.h b/src/core/execute.h index 1de439c3ad..c7d0f7761e 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -50,6 +50,7 @@ typedef enum ExecInput { EXEC_INPUT_TTY_FORCE, EXEC_INPUT_TTY_FAIL, EXEC_INPUT_SOCKET, + EXEC_INPUT_NAMED_FD, _EXEC_INPUT_MAX, _EXEC_INPUT_INVALID = -1 } ExecInput; @@ -65,6 +66,7 @@ typedef enum ExecOutput { EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE, EXEC_OUTPUT_SOCKET, + EXEC_OUTPUT_NAMED_FD, _EXEC_OUTPUT_MAX, _EXEC_OUTPUT_INVALID = -1 } ExecOutput; @@ -120,6 +122,7 @@ struct ExecContext { ExecInput std_input; ExecOutput std_output; ExecOutput std_error; + char *stdio_fdname[3]; nsec_t timer_slack_nsec; @@ -284,6 +287,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix); int exec_context_destroy_runtime_directory(ExecContext *c, const char *runtime_root); int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l); +int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParameters *p, int named_iofds[3]); +const char* exec_context_fdname(const ExecContext *c, int fd_index); bool exec_context_may_touch_console(ExecContext *c); bool exec_context_maintains_privileges(ExecContext *c); diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index a700d853cc..08c88b6b53 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -35,9 +35,9 @@ $1.Environment, config_parse_environ, 0, $1.EnvironmentFile, config_parse_unit_env_file, 0, offsetof($1, exec_context.environment_files) $1.PassEnvironment, config_parse_pass_environ, 0, offsetof($1, exec_context.pass_environment) $1.DynamicUser, config_parse_bool, 0, offsetof($1, exec_context.dynamic_user) -$1.StandardInput, config_parse_input, 0, offsetof($1, exec_context.std_input) -$1.StandardOutput, config_parse_output, 0, offsetof($1, exec_context.std_output) -$1.StandardError, config_parse_output, 0, offsetof($1, exec_context.std_error) +$1.StandardInput, config_parse_exec_input, 0, offsetof($1, exec_context) +$1.StandardOutput, config_parse_exec_output, 0, offsetof($1, exec_context) +$1.StandardError, config_parse_exec_output, 0, offsetof($1, exec_context) $1.TTYPath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.tty_path) $1.TTYReset, config_parse_bool, 0, offsetof($1, exec_context.tty_reset) $1.TTYVHangup, config_parse_bool, 0, offsetof($1, exec_context.tty_vhangup) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 8cc7a8e765..a69f60097d 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -776,8 +776,104 @@ int config_parse_socket_bindtodevice( return 0; } -DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier"); -DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input literal specifier"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output literal specifier"); + +int config_parse_exec_input(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) { + ExecContext *c = data; + const char *name; + int r; + + assert(data); + assert(filename); + assert(line); + assert(rvalue); + + name = startswith(rvalue, "fd:"); + if (name) { + /* Strip prefix and validate fd name */ + if (!fdname_is_valid(name)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name, ignoring: %s", name); + return 0; + } + c->std_input = EXEC_INPUT_NAMED_FD; + r = free_and_strdup(&c->stdio_fdname[STDIN_FILENO], name); + if (r < 0) + log_oom(); + return r; + } else { + ExecInput ei = exec_input_from_string(rvalue); + if (ei == _EXEC_INPUT_INVALID) + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse input specifier, ignoring: %s", rvalue); + else + c->std_input = ei; + return 0; + } +} + +int config_parse_exec_output(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) { + ExecContext *c = data; + ExecOutput eo; + const char *name; + int r; + + assert(data); + assert(filename); + assert(line); + assert(lvalue); + assert(rvalue); + + name = startswith(rvalue, "fd:"); + if (name) { + /* Strip prefix and validate fd name */ + if (!fdname_is_valid(name)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name, ignoring: %s", name); + return 0; + } + eo = EXEC_OUTPUT_NAMED_FD; + } else { + eo = exec_output_from_string(rvalue); + if (eo == _EXEC_OUTPUT_INVALID) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output specifier, ignoring: %s", rvalue); + return 0; + } + } + + if (streq(lvalue, "StandardOutput")) { + c->std_output = eo; + r = free_and_strdup(&c->stdio_fdname[STDOUT_FILENO], name); + if (r < 0) + log_oom(); + return r; + } else if (streq(lvalue, "StandardError")) { + c->std_error = eo; + r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], name); + if (r < 0) + log_oom(); + return r; + } else { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output property, ignoring: %s", lvalue); + return 0; + } +} int config_parse_exec_io_class(const char *unit, const char *filename, @@ -4183,8 +4279,8 @@ void unit_dump_config_items(FILE *f) { { config_parse_exec_cpu_affinity, "CPUAFFINITY" }, { config_parse_mode, "MODE" }, { config_parse_unit_env_file, "FILE" }, - { config_parse_output, "OUTPUT" }, - { config_parse_input, "INPUT" }, + { config_parse_exec_output, "OUTPUT" }, + { config_parse_exec_input, "INPUT" }, { config_parse_log_facility, "FACILITY" }, { config_parse_log_level, "LEVEL" }, { config_parse_exec_secure_bits, "SECUREBITS" }, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 8b688740cf..6d1fe55bcd 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -45,7 +45,9 @@ int config_parse_service_timeout(const char *unit, const char *filename, unsigne int config_parse_service_type(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_service_restart(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_socket_bindtodevice(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_exec_output(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_output(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_exec_input(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_input(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_exec_io_class(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_exec_io_priority(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); diff --git a/src/core/unit.c b/src/core/unit.c index b24ca5aed8..2fa397bd41 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -858,18 +858,14 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) { return r; } - if (c->std_output != EXEC_OUTPUT_KMSG && - c->std_output != EXEC_OUTPUT_SYSLOG && - c->std_output != EXEC_OUTPUT_JOURNAL && - c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE && - c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE && - c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE && - c->std_error != EXEC_OUTPUT_KMSG && - c->std_error != EXEC_OUTPUT_SYSLOG && - c->std_error != EXEC_OUTPUT_JOURNAL && - c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE && - c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE && - c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE) + if (!IN_SET(c->std_output, + EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE, + EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE) && + !IN_SET(c->std_error, + EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE, + EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE)) return 0; /* If syslog or kernel logging is requested, make sure our own -- cgit v1.2.3-54-g00ecf From 59f62519f17d7f2da81a9abcc4002497d97c7fa8 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Tue, 18 Oct 2016 08:49:08 +0530 Subject: networkd: use proper cast to access VTI6 (#4399) Fixes #4371. --- src/network/networkd-netdev-tunnel.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c index 77a4734df8..9138ee4511 100644 --- a/src/network/networkd-netdev-tunnel.c +++ b/src/network/networkd-netdev-tunnel.c @@ -201,12 +201,18 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl } static int netdev_vti_fill_message_key(NetDev *netdev, Link *link, sd_netlink_message *m) { - Tunnel *t = VTI(netdev); uint32_t ikey, okey; + Tunnel *t; int r; assert(link); assert(m); + + if (netdev->kind == NETDEV_KIND_VTI) + t = VTI(netdev); + else + t = VTI6(netdev); + assert(t); if (t->key != 0) -- cgit v1.2.3-54-g00ecf From 19539807b597274275271c82113e8eb2850bb19f Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 20:56:31 -0400 Subject: shared/install: in install_context_mark_for_removal ignore not found units With the following test case: [Install] WantedBy= default.target Also=foobar-unknown.service disabling would fail with: $ ./systemctl --root=/ disable testing.service Cannot find unit foobar-unknown.service. # this is level debug Failed to disable: No such file or directory. # this is the error After the change we proceed: $ ./systemctl --root=/ disable testing.service Cannot find unit foobar-unknown.service. Removed /etc/systemd/system/default.target.wants/testing.service. This does not affect specifying a missing unit directly: $ ./systemctl --root=/ disable nosuch.service Failed to disable: No such file or directory. --- src/shared/install.c | 33 ++++++++++++++++++++++----------- src/shared/install.h | 4 ++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/shared/install.c b/src/shared/install.c index bcb169e7df..9e26284ade 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -934,11 +934,14 @@ static int install_info_may_process( /** * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process * hashmap, or retrieves the existing one if already present. + * + * Returns negative on error, 0 if the unit was already known, 1 otherwise. */ static int install_info_add( InstallContext *c, const char *name, const char *path, + bool auxiliary, UnitFileInstallInfo **ret) { UnitFileInstallInfo *i = NULL; @@ -955,6 +958,8 @@ static int install_info_add( i = install_info_find(c, name); if (i) { + i->auxiliary = i->auxiliary && auxiliary; + if (ret) *ret = i; return 0; @@ -968,6 +973,7 @@ static int install_info_add( if (!i) return -ENOMEM; i->type = _UNIT_FILE_TYPE_INVALID; + i->auxiliary = auxiliary; i->name = strdup(name); if (!i->name) { @@ -990,7 +996,7 @@ static int install_info_add( if (ret) *ret = i; - return 0; + return 1; fail: install_info_free(i); @@ -1039,7 +1045,7 @@ static int config_parse_also( void *data, void *userdata) { - UnitFileInstallInfo *i = userdata; + UnitFileInstallInfo *info = userdata, *alsoinfo = NULL; InstallContext *c = data; int r; @@ -1056,11 +1062,11 @@ static int config_parse_also( if (r == 0) break; - r = install_info_add(c, word, NULL, NULL); + r = install_info_add(c, word, NULL, true, &alsoinfo); if (r < 0) return r; - r = strv_push(&i->also, word); + r = strv_push(&info->also, word); if (r < 0) return r; @@ -1432,7 +1438,7 @@ static int install_info_traverse( bn = buffer; } - r = install_info_add(c, bn, NULL, &i); + r = install_info_add(c, bn, NULL, false, &i); if (r < 0) return r; @@ -1471,9 +1477,9 @@ static int install_info_add_auto( pp = prefix_roota(paths->root_dir, name_or_path); - return install_info_add(c, NULL, pp, ret); + return install_info_add(c, NULL, pp, false, ret); } else - return install_info_add(c, name_or_path, NULL, ret); + return install_info_add(c, name_or_path, NULL, false, ret); } static int install_info_discover( @@ -1766,10 +1772,15 @@ static int install_context_mark_for_removal( return r; r = install_info_traverse(scope, c, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL); - if (r == -ENOLINK) + if (r == -ENOLINK) { + log_debug_errno(r, "Name %s leads to a dangling symlink, ignoring.", i->name); continue; - else if (r < 0) - return r; + } else if (r == -ENOENT && i->auxiliary) { + /* some unit specified in Also= or similar is missing */ + log_debug_errno(r, "Auxiliary unit %s not found, ignoring.", i->name); + continue; + } else if (r < 0) + return log_debug_errno(r, "Failed to find unit %s: %m", i->name); if (i->type != UNIT_FILE_TYPE_REGULAR) { log_debug("Unit %s has type %s, ignoring.", @@ -2316,7 +2327,7 @@ int unit_file_disable( if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) return -EINVAL; - r = install_info_add(&c, *i, NULL, NULL); + r = install_info_add(&c, *i, NULL, false, NULL); if (r < 0) return r; } diff --git a/src/shared/install.h b/src/shared/install.h index c6aa4f6ef1..b1f220693b 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -119,10 +119,10 @@ struct UnitFileInstallInfo { char **also; char *default_instance; + char *symlink_target; UnitFileType type; - - char *symlink_target; + bool auxiliary; }; static inline bool UNIT_FILE_INSTALL_INFO_HAS_RULES(UnitFileInstallInfo *i) { -- cgit v1.2.3-54-g00ecf From db093eed04cf88aa75c58cb7a69d55d669af0e34 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 21:27:57 -0400 Subject: shared/install: provide more info if install_info_traverse_fails Test case: [Install] WantedBy= default.target Also=foobar-unknown.service Before: $ systemctl --root=/ enable testing2@instance.service Failed to enable: No such file or directory. After $ ./systemctl --root=/ enable testing2@instance.service Failed to enable unit, file foobar-unknown.service: No such file or directory. --- src/shared/install.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/shared/install.c b/src/shared/install.c index 9e26284ade..32f7edc8cc 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1713,8 +1713,10 @@ static int install_context_apply( return q; r = install_info_traverse(scope, c, paths, i, flags, NULL); - if (r < 0) + if (r < 0) { + unit_file_changes_add(changes, n_changes, r, i->name, NULL); return r; + } /* We can attempt to process a masked unit when a different unit * that we were processing specifies it in Also=. */ -- cgit v1.2.3-54-g00ecf From a6612e658c19717a51366fa2e4925e557d95a427 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 21:40:41 -0400 Subject: shared/install: resolve specifiers in Also= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test case: [Install] WantedBy= default.target Also=getty@%p.service $ ./systemctl --root=/ enable testing@instance.service Created symlink /etc/systemd/system/default.target.wants/testing@instance.service → /etc/systemd/system/testing@.service. Created symlink /etc/systemd/system/getty.target.wants/getty@testing.service → /usr/lib/systemd/system/getty@.service. $ ./systemctl --root=/ disable testing@instance.service Removed /etc/systemd/system/getty.target.wants/getty@testing.service. Removed /etc/systemd/system/default.target.wants/testing@instance.service. Fixes part of #4210. Resolving specifiers in DefaultInstance seems to work too: [Install] WantedBy= default.target DefaultInstance=%u $ systemctl --root=/ enable testing3@instance.service Created symlink /etc/systemd/system/default.target.wants/testing3@instance.service → /etc/systemd/system/testing3@.service. $ systemctl --root=/ enable testing3@.service Created symlink /etc/systemd/system/default.target.wants/testing3@zbyszek.service → /etc/systemd/system/testing3@.service. --- src/shared/install.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/shared/install.c b/src/shared/install.c index 32f7edc8cc..ff1ecbe7ff 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1054,7 +1054,7 @@ static int config_parse_also( assert(rvalue); for (;;) { - _cleanup_free_ char *word = NULL; + _cleanup_free_ char *word = NULL, *printed = NULL; r = extract_first_word(&rvalue, &word, NULL, 0); if (r < 0) @@ -1062,15 +1062,22 @@ static int config_parse_also( if (r == 0) break; - r = install_info_add(c, word, NULL, true, &alsoinfo); + r = install_full_printf(info, word, &printed); if (r < 0) return r; - r = strv_push(&info->also, word); + if (!unit_name_is_valid(printed, UNIT_NAME_ANY)) + return -EINVAL; + + r = install_info_add(c, printed, NULL, true, &alsoinfo); + if (r < 0) + return r; + + r = strv_push(&info->also, printed); if (r < 0) return r; - word = NULL; + printed = NULL; } return 0; -- cgit v1.2.3-54-g00ecf From 59108fbecb831664cb968ad04acb77c55a756eb1 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 16 Oct 2016 22:57:38 -0400 Subject: shared/install: report invalid unit files slightly better When a unit file is invalid, we'd return an error without any details: $ systemctl --root=/ enable testing@instance.service Failed to enable: Invalid argument. Fix things to at least print the offending file name: $ systemctl enable testing@instance.service Failed to enable unit: File testing@instance.service: Invalid argument $ systemctl --root=/ enable testing@instance.service Failed to enable unit, file testing@instance.service: Invalid argument. A real fix would be to pass back a proper error message from conf-parser. But this would require major surgery, since conf-parser functions now simply print log errors, but we would need to return them over the bus. So let's just print the file name, to indicate where the error is. (Incomplete) fix for #4210. --- src/shared/install.c | 42 +++++++++++++++++++++++++++--------------- src/test/test-install-root.c | 4 +++- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/shared/install.c b/src/shared/install.c index ff1ecbe7ff..f44f80560a 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1205,7 +1205,7 @@ static int unit_file_load( config_item_table_lookup, items, true, true, false, info); if (r < 0) - return r; + return log_debug_errno(r, "Failed to parse %s: %m", info->name); info->type = UNIT_FILE_TYPE_REGULAR; @@ -1495,7 +1495,9 @@ static int install_info_discover( const LookupPaths *paths, const char *name, SearchFlags flags, - UnitFileInstallInfo **ret) { + UnitFileInstallInfo **ret, + UnitFileChange **changes, + unsigned *n_changes) { UnitFileInstallInfo *i; int r; @@ -1505,10 +1507,12 @@ static int install_info_discover( assert(name); r = install_info_add_auto(c, paths, name, &i); - if (r < 0) - return r; + if (r >= 0) + r = install_info_traverse(scope, c, paths, i, flags, ret); - return install_info_traverse(scope, c, paths, i, flags, ret); + if (r < 0) + unit_file_changes_add(changes, n_changes, r, name, NULL); + return r; } static int install_info_symlink_alias( @@ -2225,7 +2229,8 @@ int unit_file_add_dependency( config_path = runtime ? paths.runtime_config : paths.persistent_config; - r = install_info_discover(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, &target_info); + r = install_info_discover(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, + &target_info, changes, n_changes); if (r < 0) return r; r = install_info_may_process(target_info, &paths, changes, n_changes); @@ -2237,7 +2242,8 @@ int unit_file_add_dependency( STRV_FOREACH(f, files) { char ***l; - r = install_info_discover(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); + r = install_info_discover(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, changes, n_changes); if (r < 0) return r; r = install_info_may_process(i, &paths, changes, n_changes); @@ -2290,7 +2296,8 @@ int unit_file_enable( config_path = runtime ? paths.runtime_config : paths.persistent_config; STRV_FOREACH(f, files) { - r = install_info_discover(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); + r = install_info_discover(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, changes, n_changes); if (r < 0) return r; r = install_info_may_process(i, &paths, changes, n_changes); @@ -2403,7 +2410,7 @@ int unit_file_set_default( if (r < 0) return r; - r = install_info_discover(scope, &c, &paths, name, 0, &i); + r = install_info_discover(scope, &c, &paths, name, 0, &i, changes, n_changes); if (r < 0) return r; r = install_info_may_process(i, &paths, changes, n_changes); @@ -2433,7 +2440,8 @@ int unit_file_get_default( if (r < 0) return r; - r = install_info_discover(scope, &c, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); + r = install_info_discover(scope, &c, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, NULL, NULL); if (r < 0) return r; r = install_info_may_process(i, &paths, NULL, 0); @@ -2465,7 +2473,8 @@ static int unit_file_lookup_state( if (!unit_name_is_valid(name, UNIT_NAME_ANY)) return -EINVAL; - r = install_info_discover(scope, &c, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); + r = install_info_discover(scope, &c, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, NULL, NULL); if (r < 0) return r; @@ -2552,7 +2561,7 @@ int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char * if (!unit_name_is_valid(name, UNIT_NAME_ANY)) return -EINVAL; - r = install_info_discover(scope, &c, paths, name, 0, NULL); + r = install_info_discover(scope, &c, paths, name, 0, NULL, NULL, NULL); if (r == -ENOENT) return 0; if (r < 0) @@ -2770,7 +2779,8 @@ static int preset_prepare_one( if (install_info_find(plus, name) || install_info_find(minus, name)) return 0; - r = install_info_discover(scope, &tmp, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); + r = install_info_discover(scope, &tmp, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, changes, n_changes); if (r < 0) return r; if (!streq(name, i->name)) { @@ -2783,7 +2793,8 @@ static int preset_prepare_one( return r; if (r > 0) { - r = install_info_discover(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); + r = install_info_discover(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, changes, n_changes); if (r < 0) return r; @@ -2791,7 +2802,8 @@ static int preset_prepare_one( if (r < 0) return r; } else - r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i); + r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, changes, n_changes); return r; } diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c index db1c928660..1686054d2a 100644 --- a/src/test/test-install-root.c +++ b/src/test/test-install-root.c @@ -326,7 +326,9 @@ static void test_default(const char *root) { assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT); assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "idontexist.target", false, &changes, &n_changes) == -ENOENT); - assert_se(n_changes == 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == -ENOENT); + assert_se(streq_ptr(changes[0].path, "idontexist.target")); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; -- cgit v1.2.3-54-g00ecf From e0ed6db9cdde5ee64fb91f131beb0aa1690bc59a Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Mon, 3 Oct 2016 18:12:41 +0200 Subject: journal: introduce determine_path_usage() This commit simply extracts from determine_space_for() the code which determines the FS usage where the passed path lives (statvfs(3)) and put it into a function of its own so it can be reused by others paths later. No functional changes. --- src/journal/journald-server.c | 76 ++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 381182fa2c..6639230366 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -86,6 +86,47 @@ /* The period to insert between posting changes for coalescing */ #define POST_CHANGE_TIMER_INTERVAL_USEC (250*USEC_PER_MSEC) +static int determine_path_usage(Server *s, const char *path, uint64_t *ret_used, uint64_t *ret_free) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + struct statvfs ss; + const char *p; + + assert(ret_used); + assert(ret_free); + + p = strjoina(path, SERVER_MACHINE_ID(s)); + d = opendir(p); + if (!d) + return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, + errno, "Failed to open %s: %m", p); + + if (fstatvfs(dirfd(d), &ss) < 0) + return log_error_errno(errno, "Failed to fstatvfs(%s): %m", p); + + *ret_free = ss.f_bsize * ss.f_bavail; + *ret_used = 0; + FOREACH_DIRENT_ALL(de, d, break) { + struct stat st; + + if (!endswith(de->d_name, ".journal") && + !endswith(de->d_name, ".journal~")) + continue; + + if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { + log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", p, de->d_name); + continue; + } + + if (!S_ISREG(st.st_mode)) + continue; + + *ret_used += (uint64_t) st.st_blocks * 512UL; + } + + return 0; +} + static int determine_space_for( Server *s, JournalMetrics *metrics, @@ -96,12 +137,10 @@ static int determine_space_for( uint64_t *available, uint64_t *limit) { - uint64_t sum = 0, ss_avail, avail; + uint64_t sum, avail, ss_avail; _cleanup_closedir_ DIR *d = NULL; - struct dirent *de; - struct statvfs ss; - const char *p; usec_t ts; + int r; assert(s); assert(metrics); @@ -120,31 +159,9 @@ static int determine_space_for( return 0; } - p = strjoina(path, SERVER_MACHINE_ID(s)); - d = opendir(p); - if (!d) - return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open %s: %m", p); - - if (fstatvfs(dirfd(d), &ss) < 0) - return log_error_errno(errno, "Failed to fstatvfs(%s): %m", p); - - FOREACH_DIRENT_ALL(de, d, break) { - struct stat st; - - if (!endswith(de->d_name, ".journal") && - !endswith(de->d_name, ".journal~")) - continue; - - if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { - log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", p, de->d_name); - continue; - } - - if (!S_ISREG(st.st_mode)) - continue; - - sum += (uint64_t) st.st_blocks * 512UL; - } + r = determine_path_usage(s, path, &sum, &ss_avail); + if (r < 0) + return r; /* If requested, then let's bump the min_use limit to the * current usage on disk. We do this when starting up and @@ -156,7 +173,6 @@ static int determine_space_for( if (patch_min_use) metrics->min_use = MAX(metrics->min_use, sum); - ss_avail = ss.f_bsize * ss.f_bavail; avail = LESS_BY(ss_avail, metrics->keep_free); s->cached_space_limit = MIN(MAX(sum + avail, metrics->min_use), metrics->max_use); -- cgit v1.2.3-54-g00ecf From 266a470005c65851bb5cf6ab6fc1bb0828456ae2 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Tue, 4 Oct 2016 17:13:21 +0200 Subject: journal: introduce JournalStorage and JournalStorageSpace structures This structure keeps track of specificities for a given journal type (persistent or volatile) such as metrics, name, etc... The cached space values are now moved in this structure so that each journal has its own set of cached values. Previously only one set existed and we didn't know if the cached values were for the runtime journal or the persistent one. When doing: determine_space_for(s, runtime_metrics, ...); determine_space_for(s, system_metrics, ...); the second call returned the cached values for the runtime metrics. --- src/journal/journald-gperf.gperf | 16 ++--- src/journal/journald-server.c | 131 ++++++++++++++++++--------------------- src/journal/journald-server.h | 22 +++++-- 3 files changed, 84 insertions(+), 85 deletions(-) diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf index 7fecd7a964..654fd76a4b 100644 --- a/src/journal/journald-gperf.gperf +++ b/src/journal/journald-gperf.gperf @@ -23,14 +23,14 @@ Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_in Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Server, rate_limit_interval) Journal.RateLimitIntervalSec,config_parse_sec, 0, offsetof(Server, rate_limit_interval) Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(Server, rate_limit_burst) -Journal.SystemMaxUse, config_parse_iec_uint64, 0, offsetof(Server, system_metrics.max_use) -Journal.SystemMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, system_metrics.max_size) -Journal.SystemKeepFree, config_parse_iec_uint64, 0, offsetof(Server, system_metrics.keep_free) -Journal.SystemMaxFiles, config_parse_uint64, 0, offsetof(Server, system_metrics.n_max_files) -Journal.RuntimeMaxUse, config_parse_iec_uint64, 0, offsetof(Server, runtime_metrics.max_use) -Journal.RuntimeMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, runtime_metrics.max_size) -Journal.RuntimeKeepFree, config_parse_iec_uint64, 0, offsetof(Server, runtime_metrics.keep_free) -Journal.RuntimeMaxFiles, config_parse_uint64, 0, offsetof(Server, runtime_metrics.n_max_files) +Journal.SystemMaxUse, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.max_use) +Journal.SystemMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.max_size) +Journal.SystemKeepFree, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.keep_free) +Journal.SystemMaxFiles, config_parse_uint64, 0, offsetof(Server, system_storage.metrics.n_max_files) +Journal.RuntimeMaxUse, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.max_use) +Journal.RuntimeMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.max_size) +Journal.RuntimeKeepFree, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.keep_free) +Journal.RuntimeMaxFiles, config_parse_uint64, 0, offsetof(Server, runtime_storage.metrics.n_max_files) Journal.MaxRetentionSec, config_parse_sec, 0, offsetof(Server, max_retention_usec) Journal.MaxFileSec, config_parse_sec, 0, offsetof(Server, max_file_usec) Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Server, forward_to_syslog) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 6639230366..db228d447c 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -90,19 +90,17 @@ static int determine_path_usage(Server *s, const char *path, uint64_t *ret_used, _cleanup_closedir_ DIR *d = NULL; struct dirent *de; struct statvfs ss; - const char *p; assert(ret_used); assert(ret_free); - p = strjoina(path, SERVER_MACHINE_ID(s)); - d = opendir(p); + d = opendir(path); if (!d) return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, - errno, "Failed to open %s: %m", p); + errno, "Failed to open %s: %m", path); if (fstatvfs(dirfd(d), &ss) < 0) - return log_error_errno(errno, "Failed to fstatvfs(%s): %m", p); + return log_error_errno(errno, "Failed to fstatvfs(%s): %m", path); *ret_free = ss.f_bsize * ss.f_bavail; *ret_used = 0; @@ -114,7 +112,7 @@ static int determine_path_usage(Server *s, const char *path, uint64_t *ret_used, continue; if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { - log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", p, de->d_name); + log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", path, de->d_name); continue; } @@ -129,9 +127,7 @@ static int determine_path_usage(Server *s, const char *path, uint64_t *ret_used, static int determine_space_for( Server *s, - JournalMetrics *metrics, - const char *path, - const char *name, + JournalStorage *storage, bool verbose, bool patch_min_use, uint64_t *available, @@ -139,22 +135,25 @@ static int determine_space_for( uint64_t sum, avail, ss_avail; _cleanup_closedir_ DIR *d = NULL; + JournalMetrics *metrics; + const char *path, *name; usec_t ts; int r; assert(s); - assert(metrics); - assert(path); - assert(name); + + name = storage->name; + path = storage->path; + metrics = &storage->metrics; ts = now(CLOCK_MONOTONIC); - if (!verbose && s->cached_space_timestamp + RECHECK_SPACE_USEC > ts) { + if (!verbose && storage->space.timestamp + RECHECK_SPACE_USEC > ts) { if (available) - *available = s->cached_space_available; + *available = storage->space.available; if (limit) - *limit = s->cached_space_limit; + *limit = storage->space.limit; return 0; } @@ -175,9 +174,9 @@ static int determine_space_for( avail = LESS_BY(ss_avail, metrics->keep_free); - s->cached_space_limit = MIN(MAX(sum + avail, metrics->min_use), metrics->max_use); - s->cached_space_available = LESS_BY(s->cached_space_limit, sum); - s->cached_space_timestamp = ts; + storage->space.limit = MIN(MAX(sum + avail, metrics->min_use), metrics->max_use); + storage->space.available = LESS_BY(storage->space.limit, sum); + storage->space.timestamp = ts; if (verbose) { char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX], @@ -186,8 +185,8 @@ static int determine_space_for( format_bytes(fb2, sizeof(fb2), metrics->max_use); format_bytes(fb3, sizeof(fb3), metrics->keep_free); format_bytes(fb4, sizeof(fb4), ss_avail); - format_bytes(fb5, sizeof(fb5), s->cached_space_limit); - format_bytes(fb6, sizeof(fb6), s->cached_space_available); + format_bytes(fb5, sizeof(fb5), storage->space.limit); + format_bytes(fb6, sizeof(fb6), storage->space.available); server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE, LOG_MESSAGE("%s (%s) is %s, max %s, %s free.", @@ -202,38 +201,28 @@ static int determine_space_for( "DISK_KEEP_FREE_PRETTY=%s", fb3, "DISK_AVAILABLE=%"PRIu64, ss_avail, "DISK_AVAILABLE_PRETTY=%s", fb4, - "LIMIT=%"PRIu64, s->cached_space_limit, + "LIMIT=%"PRIu64, storage->space.limit, "LIMIT_PRETTY=%s", fb5, - "AVAILABLE=%"PRIu64, s->cached_space_available, + "AVAILABLE=%"PRIu64, storage->space.available, "AVAILABLE_PRETTY=%s", fb6, NULL); } if (available) - *available = s->cached_space_available; + *available = storage->space.available; if (limit) - *limit = s->cached_space_limit; + *limit = storage->space.limit; return 1; } static int determine_space(Server *s, bool verbose, bool patch_min_use, uint64_t *available, uint64_t *limit) { - JournalMetrics *metrics; - const char *path, *name; + JournalStorage *js; assert(s); - if (s->system_journal) { - path = "/var/log/journal/"; - metrics = &s->system_metrics; - name = "System journal"; - } else { - path = "/run/log/journal/"; - metrics = &s->runtime_metrics; - name = "Runtime journal"; - } - - return determine_space_for(s, metrics, path, name, verbose, patch_min_use, available, limit); + js = s->system_journal ? &s->system_storage : &s->runtime_storage; + return determine_space_for(s, js, verbose, patch_min_use, available, limit); } static void server_add_acls(JournalFile *f, uid_t uid) { @@ -306,14 +295,13 @@ static int system_journal_open(Server *s, bool flush_requested) { if (s->storage == STORAGE_PERSISTENT) (void) mkdir_p("/var/log/journal/", 0755); - fn = strjoina("/var/log/journal/", SERVER_MACHINE_ID(s)); - (void) mkdir(fn, 0755); + (void) mkdir(s->system_storage.path, 0755); - fn = strjoina(fn, "/system.journal"); - r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &s->system_journal); + fn = strjoina(s->system_storage.path, "/system.journal"); + r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_storage.metrics, &s->system_journal); if (r >= 0) { server_add_acls(s->system_journal, 0); - (void) determine_space_for(s, &s->system_metrics, "/var/log/journal/", "System journal", true, true, NULL, NULL); + (void) determine_space_for(s, &s->system_storage, true, true, NULL, NULL); } else if (r < 0) { if (r != -ENOENT && r != -EROFS) log_warning_errno(r, "Failed to open system journal: %m"); @@ -335,7 +323,7 @@ static int system_journal_open(Server *s, bool flush_requested) { if (!s->runtime_journal && (s->storage != STORAGE_NONE)) { - fn = strjoina("/run/log/journal/", SERVER_MACHINE_ID(s), "/system.journal"); + fn = strjoina(s->runtime_storage.path, "/system.journal"); if (s->system_journal) { @@ -343,7 +331,7 @@ static int system_journal_open(Server *s, bool flush_requested) { * if it already exists, so that we can flush * it into the system journal */ - r = open_journal(s, false, fn, O_RDWR, false, &s->runtime_metrics, &s->runtime_journal); + r = open_journal(s, false, fn, O_RDWR, false, &s->runtime_storage.metrics, &s->runtime_journal); if (r < 0) { if (r != -ENOENT) log_warning_errno(r, "Failed to open runtime journal: %m"); @@ -360,14 +348,14 @@ static int system_journal_open(Server *s, bool flush_requested) { (void) mkdir("/run/log/journal", 0755); (void) mkdir_parents(fn, 0750); - r = open_journal(s, true, fn, O_RDWR|O_CREAT, false, &s->runtime_metrics, &s->runtime_journal); + r = open_journal(s, true, fn, O_RDWR|O_CREAT, false, &s->runtime_storage.metrics, &s->runtime_journal); if (r < 0) return log_error_errno(r, "Failed to open runtime journal: %m"); } if (s->runtime_journal) { server_add_acls(s->runtime_journal, 0); - (void) determine_space_for(s, &s->runtime_metrics, "/run/log/journal/", "Runtime journal", true, true, NULL, NULL); + (void) determine_space_for(s, &s->runtime_storage, true, true, NULL, NULL); } } @@ -423,7 +411,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) { (void) journal_file_close(f); } - r = open_journal(s, true, p, O_RDWR|O_CREAT, s->seal, &s->system_metrics, &f); + r = open_journal(s, true, p, O_RDWR|O_CREAT, s->seal, &s->system_storage.metrics, &f); if (r < 0) return s->system_journal; @@ -519,33 +507,28 @@ void server_sync(Server *s) { static void do_vacuum( Server *s, - JournalFile *f, - JournalMetrics *metrics, - const char *path, - const char *name, + JournalStorage *storage, bool verbose, bool patch_min_use) { - const char *p; + JournalMetrics *metrics; uint64_t limit; int r; assert(s); - assert(metrics); - assert(path); - assert(name); - - if (!f) - return; - - p = strjoina(path, SERVER_MACHINE_ID(s)); + assert(storage); + metrics = &storage->metrics; limit = metrics->max_use; - (void) determine_space_for(s, metrics, path, name, verbose, patch_min_use, NULL, &limit); + (void) determine_space_for(s, storage, verbose, patch_min_use, NULL, &limit); - r = journal_directory_vacuum(p, limit, metrics->n_max_files, s->max_retention_usec, &s->oldest_file_usec, verbose); + r = journal_directory_vacuum(storage->path, limit, metrics->n_max_files, s->max_retention_usec, &s->oldest_file_usec, verbose); if (r < 0 && r != -ENOENT) - log_warning_errno(r, "Failed to vacuum %s, ignoring: %m", p); + log_warning_errno(r, "Failed to vacuum %s, ignoring: %m", storage->path); + + storage->space.limit = 0; + storage->space.available = 0; + storage->space.timestamp = 0; } int server_vacuum(Server *s, bool verbose, bool patch_min_use) { @@ -555,12 +538,10 @@ int server_vacuum(Server *s, bool verbose, bool patch_min_use) { s->oldest_file_usec = 0; - do_vacuum(s, s->system_journal, &s->system_metrics, "/var/log/journal/", "System journal", verbose, patch_min_use); - do_vacuum(s, s->runtime_journal, &s->runtime_metrics, "/run/log/journal/", "Runtime journal", verbose, patch_min_use); - - s->cached_space_limit = 0; - s->cached_space_available = 0; - s->cached_space_timestamp = 0; + if (s->system_journal) + do_vacuum(s, &s->system_storage, verbose, patch_min_use); + if (s->runtime_journal) + do_vacuum(s, &s->runtime_storage, verbose, patch_min_use); return 0; } @@ -1888,8 +1869,8 @@ int server_init(Server *s) { s->max_level_console = LOG_INFO; s->max_level_wall = LOG_EMERG; - journal_reset_metrics(&s->system_metrics); - journal_reset_metrics(&s->runtime_metrics); + journal_reset_metrics(&s->system_storage.metrics); + journal_reset_metrics(&s->runtime_storage.metrics); server_parse_config_file(s); server_parse_proc_cmdline(s); @@ -2042,6 +2023,14 @@ int server_init(Server *s) { server_cache_boot_id(s); server_cache_machine_id(s); + s->runtime_storage.name = "Runtime journal"; + s->system_storage.name = "System journal"; + + s->runtime_storage.path = strjoin("/run/log/journal/", SERVER_MACHINE_ID(s), NULL); + s->system_storage.path = strjoin("/var/log/journal/", SERVER_MACHINE_ID(s), NULL); + if (!s->runtime_storage.path || !s->system_storage.path) + return -ENOMEM; + (void) server_connect_notify(s); return system_journal_open(s, false); diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index cc68a0a690..9cf4fad722 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -49,6 +49,20 @@ typedef enum SplitMode { _SPLIT_INVALID = -1 } SplitMode; +typedef struct JournalStorageSpace { + uint64_t available; + uint64_t limit; + usec_t timestamp; +} JournalStorageSpace; + +typedef struct JournalStorage { + const char *name; + const char *path; + + JournalMetrics metrics; + JournalStorageSpace space; +} JournalStorage; + struct Server { int syslog_fd; int native_fd; @@ -89,8 +103,8 @@ struct Server { usec_t rate_limit_interval; unsigned rate_limit_burst; - JournalMetrics runtime_metrics; - JournalMetrics system_metrics; + JournalStorage runtime_storage; + JournalStorage system_storage; bool compress; bool seal; @@ -103,10 +117,6 @@ struct Server { unsigned n_forward_syslog_missed; usec_t last_warn_forward_syslog_missed; - uint64_t cached_space_available; - uint64_t cached_space_limit; - usec_t cached_space_timestamp; - uint64_t var_available_timestamp; usec_t max_retention_usec; -- cgit v1.2.3-54-g00ecf From cba5629e870bdab445a3b2ad42b140667c22eac1 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Tue, 11 Oct 2016 16:46:16 +0200 Subject: journal: introduce server_space_usage_message() This commit simply extracts from determine_space_for() the code which emits the storage usage message and put it into a function of its own so it can be reused by others paths later. No functional changes. --- src/journal/journald-server.c | 78 +++++++++++++++++++++++++------------------ src/journal/journald-server.h | 1 + 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index db228d447c..2a966eb481 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -136,14 +136,11 @@ static int determine_space_for( uint64_t sum, avail, ss_avail; _cleanup_closedir_ DIR *d = NULL; JournalMetrics *metrics; - const char *path, *name; usec_t ts; int r; assert(s); - name = storage->name; - path = storage->path; metrics = &storage->metrics; ts = now(CLOCK_MONOTONIC); @@ -158,7 +155,7 @@ static int determine_space_for( return 0; } - r = determine_path_usage(s, path, &sum, &ss_avail); + r = determine_path_usage(s, storage->path, &sum, &ss_avail); if (r < 0) return r; @@ -178,35 +175,8 @@ static int determine_space_for( storage->space.available = LESS_BY(storage->space.limit, sum); storage->space.timestamp = ts; - if (verbose) { - char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX], - fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX]; - format_bytes(fb1, sizeof(fb1), sum); - format_bytes(fb2, sizeof(fb2), metrics->max_use); - format_bytes(fb3, sizeof(fb3), metrics->keep_free); - format_bytes(fb4, sizeof(fb4), ss_avail); - format_bytes(fb5, sizeof(fb5), storage->space.limit); - format_bytes(fb6, sizeof(fb6), storage->space.available); - - server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE, - LOG_MESSAGE("%s (%s) is %s, max %s, %s free.", - name, path, fb1, fb5, fb6), - "JOURNAL_NAME=%s", name, - "JOURNAL_PATH=%s", path, - "CURRENT_USE=%"PRIu64, sum, - "CURRENT_USE_PRETTY=%s", fb1, - "MAX_USE=%"PRIu64, metrics->max_use, - "MAX_USE_PRETTY=%s", fb2, - "DISK_KEEP_FREE=%"PRIu64, metrics->keep_free, - "DISK_KEEP_FREE_PRETTY=%s", fb3, - "DISK_AVAILABLE=%"PRIu64, ss_avail, - "DISK_AVAILABLE_PRETTY=%s", fb4, - "LIMIT=%"PRIu64, storage->space.limit, - "LIMIT_PRETTY=%s", fb5, - "AVAILABLE=%"PRIu64, storage->space.available, - "AVAILABLE_PRETTY=%s", fb6, - NULL); - } + if (verbose) + server_space_usage_message(s, storage); if (available) *available = storage->space.available; @@ -225,6 +195,48 @@ static int determine_space(Server *s, bool verbose, bool patch_min_use, uint64_t return determine_space_for(s, js, verbose, patch_min_use, available, limit); } +void server_space_usage_message(Server *s, JournalStorage *storage) { + char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX], + fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX]; + JournalMetrics *metrics; + uint64_t used, avail; + + assert(s); + + if (!storage) + storage = s->system_journal ? &s->system_storage : &s->runtime_storage; + + if (determine_path_usage(s, storage->path, &used, &avail) < 0) + return; + + metrics = &storage->metrics; + format_bytes(fb1, sizeof(fb1), used); + format_bytes(fb2, sizeof(fb2), metrics->max_use); + format_bytes(fb3, sizeof(fb3), metrics->keep_free); + format_bytes(fb4, sizeof(fb4), avail); + format_bytes(fb5, sizeof(fb5), storage->space.limit); + format_bytes(fb6, sizeof(fb6), storage->space.available); + + server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE, + LOG_MESSAGE("%s (%s) is %s, max %s, %s free.", + storage->name, storage->path, fb1, fb5, fb6), + "JOURNAL_NAME=%s", storage->name, + "JOURNAL_PATH=%s", storage->path, + "CURRENT_USE=%"PRIu64, used, + "CURRENT_USE_PRETTY=%s", fb1, + "MAX_USE=%"PRIu64, metrics->max_use, + "MAX_USE_PRETTY=%s", fb2, + "DISK_KEEP_FREE=%"PRIu64, metrics->keep_free, + "DISK_KEEP_FREE_PRETTY=%s", fb3, + "DISK_AVAILABLE=%"PRIu64, avail, + "DISK_AVAILABLE_PRETTY=%s", fb4, + "LIMIT=%"PRIu64, storage->space.limit, + "LIMIT_PRETTY=%s", fb5, + "AVAILABLE=%"PRIu64, storage->space.available, + "AVAILABLE_PRETTY=%s", fb6, + NULL); +} + static void server_add_acls(JournalFile *f, uid_t uid) { #ifdef HAVE_ACL int r; diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 9cf4fad722..18fb21b3aa 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -196,3 +196,4 @@ int server_schedule_sync(Server *s, int priority); int server_flush_to_var(Server *s); void server_maybe_append_tags(Server *s); int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata); +void server_space_usage_message(Server *s, JournalStorage *storage); -- cgit v1.2.3-54-g00ecf From 18e758bf25d49ec7af589df9a2a4e6c905281a4e Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Tue, 11 Oct 2016 16:51:37 +0200 Subject: journal: don't emit space usage message when opening the journal (#4190) This patch makes system_journal_open() stop emitting the space usage message. The caller is now free to emit this message when appropriate. When restarting the journal, we can now emit the message *after* flushing the journal (if required) so that all flushed log entries are written in the persistent journal *before* the status message. This is required since the status message is always younger than the flushed entries. Fixes #4190. --- src/journal/journald-server.c | 22 +++++++++++----------- src/journal/journald.c | 5 +++++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 2a966eb481..a3af00100e 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -128,7 +128,6 @@ static int determine_path_usage(Server *s, const char *path, uint64_t *ret_used, static int determine_space_for( Server *s, JournalStorage *storage, - bool verbose, bool patch_min_use, uint64_t *available, uint64_t *limit) { @@ -145,7 +144,7 @@ static int determine_space_for( ts = now(CLOCK_MONOTONIC); - if (!verbose && storage->space.timestamp + RECHECK_SPACE_USEC > ts) { + if (storage->space.timestamp + RECHECK_SPACE_USEC > ts) { if (available) *available = storage->space.available; @@ -175,9 +174,6 @@ static int determine_space_for( storage->space.available = LESS_BY(storage->space.limit, sum); storage->space.timestamp = ts; - if (verbose) - server_space_usage_message(s, storage); - if (available) *available = storage->space.available; if (limit) @@ -186,13 +182,13 @@ static int determine_space_for( return 1; } -static int determine_space(Server *s, bool verbose, bool patch_min_use, uint64_t *available, uint64_t *limit) { +static int determine_space(Server *s, bool patch_min_use, uint64_t *available, uint64_t *limit) { JournalStorage *js; assert(s); js = s->system_journal ? &s->system_storage : &s->runtime_storage; - return determine_space_for(s, js, verbose, patch_min_use, available, limit); + return determine_space_for(s, js, patch_min_use, available, limit); } void server_space_usage_message(Server *s, JournalStorage *storage) { @@ -313,7 +309,7 @@ static int system_journal_open(Server *s, bool flush_requested) { r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_storage.metrics, &s->system_journal); if (r >= 0) { server_add_acls(s->system_journal, 0); - (void) determine_space_for(s, &s->system_storage, true, true, NULL, NULL); + (void) determine_space_for(s, &s->system_storage, true, NULL, NULL); } else if (r < 0) { if (r != -ENOENT && r != -EROFS) log_warning_errno(r, "Failed to open system journal: %m"); @@ -367,7 +363,7 @@ static int system_journal_open(Server *s, bool flush_requested) { if (s->runtime_journal) { server_add_acls(s->runtime_journal, 0); - (void) determine_space_for(s, &s->runtime_storage, true, true, NULL, NULL); + (void) determine_space_for(s, &s->runtime_storage, true, NULL, NULL); } } @@ -532,7 +528,10 @@ static void do_vacuum( metrics = &storage->metrics; limit = metrics->max_use; - (void) determine_space_for(s, storage, verbose, patch_min_use, NULL, &limit); + (void) determine_space_for(s, storage, patch_min_use, NULL, &limit); + + if (verbose) + server_space_usage_message(s, storage); r = journal_directory_vacuum(storage->path, limit, metrics->n_max_files, s->max_retention_usec, &s->oldest_file_usec, verbose); if (r < 0 && r != -ENOENT) @@ -1174,7 +1173,7 @@ void server_dispatch_message( } } - (void) determine_space(s, false, false, &available, NULL); + (void) determine_space(s, false, &available, NULL); rl = journal_rate_limit_test(s->rate_limit, path, priority & LOG_PRIMASK, available); if (rl == 0) return; @@ -1425,6 +1424,7 @@ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo * if (r < 0) log_warning_errno(r, "Failed to touch /run/systemd/journal/flushed, ignoring: %m"); + server_space_usage_message(s, NULL); return 0; } diff --git a/src/journal/journald.c b/src/journal/journald.c index 272acb71c4..13061f6469 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -60,6 +60,11 @@ int main(int argc, char *argv[]) { LOG_MESSAGE("Journal started"), NULL); + /* Make sure to send the usage message *after* flushing the + * journal so entries from the runtime journals are ordered + * before this message. See #4190 for some details. */ + server_space_usage_message(&server, NULL); + for (;;) { usec_t t = USEC_INFINITY, n; -- cgit v1.2.3-54-g00ecf From 23aba343498f3cbe0bdce6c841a0c34339d1be90 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Wed, 12 Oct 2016 08:58:04 +0200 Subject: journal: cache used vfs stats as well The set of storage space values we cache are calculated according to a couple of filesystem statistics (free blocks, block size). This patch caches the vfs stats we're interested in so these values are available later and coherent with the rest of the space cached values. --- src/journal/journald-server.c | 44 ++++++++++++++++++++++++------------------- src/journal/journald-server.h | 6 +++++- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index a3af00100e..5f77bd296d 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -132,32 +132,39 @@ static int determine_space_for( uint64_t *available, uint64_t *limit) { - uint64_t sum, avail, ss_avail; _cleanup_closedir_ DIR *d = NULL; + JournalStorageSpace *space; JournalMetrics *metrics; + uint64_t vfs_used, vfs_avail, avail; usec_t ts; int r; assert(s); metrics = &storage->metrics; + space = &storage->space; ts = now(CLOCK_MONOTONIC); - if (storage->space.timestamp + RECHECK_SPACE_USEC > ts) { + if (space->timestamp + RECHECK_SPACE_USEC > ts) { if (available) - *available = storage->space.available; + *available = space->available; if (limit) - *limit = storage->space.limit; + *limit = space->limit; return 0; } - r = determine_path_usage(s, storage->path, &sum, &ss_avail); + r = determine_path_usage(s, storage->path, &vfs_used, &vfs_avail); if (r < 0) return r; + space->vfs_used = vfs_used; + space->vfs_available = vfs_avail; + + avail = LESS_BY(vfs_avail, metrics->keep_free); + /* If requested, then let's bump the min_use limit to the * current usage on disk. We do this when starting up and * first opening the journal files. This way sudden spikes in @@ -166,18 +173,16 @@ static int determine_space_for( * journald will make it reset this value. */ if (patch_min_use) - metrics->min_use = MAX(metrics->min_use, sum); - - avail = LESS_BY(ss_avail, metrics->keep_free); + metrics->min_use = MAX(metrics->min_use, vfs_used); - storage->space.limit = MIN(MAX(sum + avail, metrics->min_use), metrics->max_use); - storage->space.available = LESS_BY(storage->space.limit, sum); - storage->space.timestamp = ts; + space->limit = MIN(MAX(vfs_used + avail, metrics->min_use), metrics->max_use); + space->available = LESS_BY(space->limit, vfs_used); + space->timestamp = ts; if (available) - *available = storage->space.available; + *available = space->available; if (limit) - *limit = storage->space.limit; + *limit = space->limit; return 1; } @@ -195,21 +200,20 @@ void server_space_usage_message(Server *s, JournalStorage *storage) { char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX], fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX]; JournalMetrics *metrics; - uint64_t used, avail; assert(s); if (!storage) storage = s->system_journal ? &s->system_storage : &s->runtime_storage; - if (determine_path_usage(s, storage->path, &used, &avail) < 0) + if (determine_space_for(s, storage, false, NULL, NULL) < 0) return; metrics = &storage->metrics; - format_bytes(fb1, sizeof(fb1), used); + format_bytes(fb1, sizeof(fb1), storage->space.vfs_used); format_bytes(fb2, sizeof(fb2), metrics->max_use); format_bytes(fb3, sizeof(fb3), metrics->keep_free); - format_bytes(fb4, sizeof(fb4), avail); + format_bytes(fb4, sizeof(fb4), storage->space.vfs_available); format_bytes(fb5, sizeof(fb5), storage->space.limit); format_bytes(fb6, sizeof(fb6), storage->space.available); @@ -218,13 +222,13 @@ void server_space_usage_message(Server *s, JournalStorage *storage) { storage->name, storage->path, fb1, fb5, fb6), "JOURNAL_NAME=%s", storage->name, "JOURNAL_PATH=%s", storage->path, - "CURRENT_USE=%"PRIu64, used, + "CURRENT_USE=%"PRIu64, storage->space.vfs_used, "CURRENT_USE_PRETTY=%s", fb1, "MAX_USE=%"PRIu64, metrics->max_use, "MAX_USE_PRETTY=%s", fb2, "DISK_KEEP_FREE=%"PRIu64, metrics->keep_free, "DISK_KEEP_FREE_PRETTY=%s", fb3, - "DISK_AVAILABLE=%"PRIu64, avail, + "DISK_AVAILABLE=%"PRIu64, storage->space.vfs_available, "DISK_AVAILABLE_PRETTY=%s", fb4, "LIMIT=%"PRIu64, storage->space.limit, "LIMIT_PRETTY=%s", fb5, @@ -540,6 +544,8 @@ static void do_vacuum( storage->space.limit = 0; storage->space.available = 0; storage->space.timestamp = 0; + storage->space.vfs_used = 0; + storage->space.vfs_available = 0; } int server_vacuum(Server *s, bool verbose, bool patch_min_use) { diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 18fb21b3aa..1ce52cdadd 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -50,9 +50,13 @@ typedef enum SplitMode { } SplitMode; typedef struct JournalStorageSpace { + usec_t timestamp; + uint64_t available; uint64_t limit; - usec_t timestamp; + + uint64_t vfs_used; /* space used by journal files */ + uint64_t vfs_available; } JournalStorageSpace; typedef struct JournalStorage { -- cgit v1.2.3-54-g00ecf From a0edc477bd80208596badb9bc147a0d0eb06fbf6 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Wed, 12 Oct 2016 09:05:55 +0200 Subject: journal: introduce cache_space_invalidate() Introduce a dedicated helper in order to reset the storage space cache. --- src/journal/journald-server.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 5f77bd296d..4839c58918 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -125,6 +125,10 @@ static int determine_path_usage(Server *s, const char *path, uint64_t *ret_used, return 0; } +static void cache_space_invalidate(JournalStorageSpace *space) { + memset(space, 0, sizeof(*space)); +} + static int determine_space_for( Server *s, JournalStorage *storage, @@ -541,11 +545,7 @@ static void do_vacuum( if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to vacuum %s, ignoring: %m", storage->path); - storage->space.limit = 0; - storage->space.available = 0; - storage->space.timestamp = 0; - storage->space.vfs_used = 0; - storage->space.vfs_available = 0; + cache_space_invalidate(&storage->space); } int server_vacuum(Server *s, bool verbose, bool patch_min_use) { -- cgit v1.2.3-54-g00ecf From 3a19f2150da1baae5af65f85864ff8df403a1aea Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Wed, 12 Oct 2016 09:58:10 +0200 Subject: journal: introduce patch_min_use() helper Updating min_use is rather an unusual operation that is limited when we first open the journal files, therefore extracts it from determine_space_for() and create a function of its own and call this new function when needed. determine_space_for() is now dealing with storage space (cached) values only. There should be no functional changes. --- src/journal/journald-server.c | 67 +++++++++++++++++++++++-------------------- src/journal/journald-server.h | 2 +- src/journal/journald.c | 4 +-- 3 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 4839c58918..0edd99ef62 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -132,7 +132,6 @@ static void cache_space_invalidate(JournalStorageSpace *space) { static int determine_space_for( Server *s, JournalStorage *storage, - bool patch_min_use, uint64_t *available, uint64_t *limit) { @@ -169,16 +168,6 @@ static int determine_space_for( avail = LESS_BY(vfs_avail, metrics->keep_free); - /* If requested, then let's bump the min_use limit to the - * current usage on disk. We do this when starting up and - * first opening the journal files. This way sudden spikes in - * disk usage will not cause journald to vacuum files without - * bounds. Note that this means that only a restart of - * journald will make it reset this value. */ - - if (patch_min_use) - metrics->min_use = MAX(metrics->min_use, vfs_used); - space->limit = MIN(MAX(vfs_used + avail, metrics->min_use), metrics->max_use); space->available = LESS_BY(space->limit, vfs_used); space->timestamp = ts; @@ -191,13 +180,26 @@ static int determine_space_for( return 1; } -static int determine_space(Server *s, bool patch_min_use, uint64_t *available, uint64_t *limit) { +static void patch_min_use(JournalStorage *storage) { + assert(storage); + + /* Let's bump the min_use limit to the current usage on disk. We do + * this when starting up and first opening the journal files. This way + * sudden spikes in disk usage will not cause journald to vacuum files + * without bounds. Note that this means that only a restart of journald + * will make it reset this value. */ + + storage->metrics.min_use = MAX(storage->metrics.min_use, storage->space.vfs_used); +} + + +static int determine_space(Server *s, uint64_t *available, uint64_t *limit) { JournalStorage *js; assert(s); js = s->system_journal ? &s->system_storage : &s->runtime_storage; - return determine_space_for(s, js, patch_min_use, available, limit); + return determine_space_for(s, js, available, limit); } void server_space_usage_message(Server *s, JournalStorage *storage) { @@ -210,7 +212,7 @@ void server_space_usage_message(Server *s, JournalStorage *storage) { if (!storage) storage = s->system_journal ? &s->system_storage : &s->runtime_storage; - if (determine_space_for(s, storage, false, NULL, NULL) < 0) + if (determine_space_for(s, storage, NULL, NULL) < 0) return; metrics = &storage->metrics; @@ -317,7 +319,8 @@ static int system_journal_open(Server *s, bool flush_requested) { r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_storage.metrics, &s->system_journal); if (r >= 0) { server_add_acls(s->system_journal, 0); - (void) determine_space_for(s, &s->system_storage, true, NULL, NULL); + (void) determine_space_for(s, &s->system_storage, NULL, NULL); + patch_min_use(&s->system_storage); } else if (r < 0) { if (r != -ENOENT && r != -EROFS) log_warning_errno(r, "Failed to open system journal: %m"); @@ -371,7 +374,8 @@ static int system_journal_open(Server *s, bool flush_requested) { if (s->runtime_journal) { server_add_acls(s->runtime_journal, 0); - (void) determine_space_for(s, &s->runtime_storage, true, NULL, NULL); + (void) determine_space_for(s, &s->runtime_storage, NULL, NULL); + patch_min_use(&s->runtime_storage); } } @@ -521,11 +525,7 @@ void server_sync(Server *s) { s->sync_scheduled = false; } -static void do_vacuum( - Server *s, - JournalStorage *storage, - bool verbose, - bool patch_min_use) { +static void do_vacuum(Server *s, JournalStorage *storage, bool verbose) { JournalMetrics *metrics; uint64_t limit; @@ -536,7 +536,7 @@ static void do_vacuum( metrics = &storage->metrics; limit = metrics->max_use; - (void) determine_space_for(s, storage, patch_min_use, NULL, &limit); + (void) determine_space_for(s, storage, NULL, &limit); if (verbose) server_space_usage_message(s, storage); @@ -548,7 +548,7 @@ static void do_vacuum( cache_space_invalidate(&storage->space); } -int server_vacuum(Server *s, bool verbose, bool patch_min_use) { +int server_vacuum(Server *s, bool verbose) { assert(s); log_debug("Vacuuming..."); @@ -556,9 +556,9 @@ int server_vacuum(Server *s, bool verbose, bool patch_min_use) { s->oldest_file_usec = 0; if (s->system_journal) - do_vacuum(s, &s->system_storage, verbose, patch_min_use); + do_vacuum(s, &s->system_storage, verbose); if (s->runtime_journal) - do_vacuum(s, &s->runtime_storage, verbose, patch_min_use); + do_vacuum(s, &s->runtime_storage, verbose); return 0; } @@ -690,7 +690,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned if (rotate) { server_rotate(s); - server_vacuum(s, false, false); + server_vacuum(s, false); vacuumed = true; f = find_journal(s, uid); @@ -712,7 +712,7 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned } server_rotate(s); - server_vacuum(s, false, false); + server_vacuum(s, false); f = find_journal(s, uid); if (!f) @@ -1179,7 +1179,7 @@ void server_dispatch_message( } } - (void) determine_space(s, false, &available, NULL); + (void) determine_space(s, &available, NULL); rl = journal_rate_limit_test(s->rate_limit, path, priority & LOG_PRIMASK, available); if (rl == 0) return; @@ -1255,7 +1255,7 @@ int server_flush_to_var(Server *s) { } server_rotate(s); - server_vacuum(s, false, false); + server_vacuum(s, false); if (!s->system_journal) { log_notice("Didn't flush runtime journal since rotation of system journal wasn't successful."); @@ -1424,7 +1424,7 @@ static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo * (void) server_flush_to_var(s); server_sync(s); - server_vacuum(s, false, false); + server_vacuum(s, false); r = touch("/run/systemd/journal/flushed"); if (r < 0) @@ -1442,7 +1442,12 @@ static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo * log_info("Received request to rotate journal from PID " PID_FMT, si->ssi_pid); server_rotate(s); - server_vacuum(s, true, true); + server_vacuum(s, true); + + if (s->system_journal) + patch_min_use(&s->system_storage); + if (s->runtime_journal) + patch_min_use(&s->runtime_storage); /* Let clients know when the most recent rotation happened. */ r = write_timestamp_file_atomic("/run/systemd/journal/rotated", now(CLOCK_MONOTONIC)); diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 1ce52cdadd..99d91496be 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -194,7 +194,7 @@ SplitMode split_mode_from_string(const char *s) _pure_; int server_init(Server *s); void server_done(Server *s); void server_sync(Server *s); -int server_vacuum(Server *s, bool verbose, bool patch_min_use); +int server_vacuum(Server *s, bool verbose); void server_rotate(Server *s); int server_schedule_sync(Server *s, int priority); int server_flush_to_var(Server *s); diff --git a/src/journal/journald.c b/src/journal/journald.c index 13061f6469..7f47ca22dd 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -51,7 +51,7 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - server_vacuum(&server, false, false); + server_vacuum(&server, false); server_flush_to_var(&server); server_flush_dev_kmsg(&server); @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) { if (server.oldest_file_usec + server.max_retention_usec < n) { log_info("Retention time reached."); server_rotate(&server); - server_vacuum(&server, false, false); + server_vacuum(&server, false); continue; } -- cgit v1.2.3-54-g00ecf From 57f443a6d981d78c14b413ae2dde26a04eddde40 Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Wed, 12 Oct 2016 10:09:45 +0200 Subject: journal: rename determine_space_for() into cache_space_refresh() Now that determine_space_for() only deals with storage space (cached) values, rename it so it reflects the fact that only the cached storage space values are updated. --- src/journal/journald-server.c | 48 +++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 0edd99ef62..5ea65e2deb 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -129,11 +129,7 @@ static void cache_space_invalidate(JournalStorageSpace *space) { memset(space, 0, sizeof(*space)); } -static int determine_space_for( - Server *s, - JournalStorage *storage, - uint64_t *available, - uint64_t *limit) { +static int cache_space_refresh(Server *s, JournalStorage *storage) { _cleanup_closedir_ DIR *d = NULL; JournalStorageSpace *space; @@ -149,15 +145,8 @@ static int determine_space_for( ts = now(CLOCK_MONOTONIC); - if (space->timestamp + RECHECK_SPACE_USEC > ts) { - - if (available) - *available = space->available; - if (limit) - *limit = space->limit; - + if (space->timestamp + RECHECK_SPACE_USEC > ts) return 0; - } r = determine_path_usage(s, storage->path, &vfs_used, &vfs_avail); if (r < 0) @@ -171,12 +160,6 @@ static int determine_space_for( space->limit = MIN(MAX(vfs_used + avail, metrics->min_use), metrics->max_use); space->available = LESS_BY(space->limit, vfs_used); space->timestamp = ts; - - if (available) - *available = space->available; - if (limit) - *limit = space->limit; - return 1; } @@ -195,11 +178,20 @@ static void patch_min_use(JournalStorage *storage) { static int determine_space(Server *s, uint64_t *available, uint64_t *limit) { JournalStorage *js; + int r; assert(s); js = s->system_journal ? &s->system_storage : &s->runtime_storage; - return determine_space_for(s, js, available, limit); + + r = cache_space_refresh(s, js); + if (r >= 0) { + if (available) + *available = js->space.available; + if (limit) + *limit = js->space.limit; + } + return r; } void server_space_usage_message(Server *s, JournalStorage *storage) { @@ -212,7 +204,7 @@ void server_space_usage_message(Server *s, JournalStorage *storage) { if (!storage) storage = s->system_journal ? &s->system_storage : &s->runtime_storage; - if (determine_space_for(s, storage, NULL, NULL) < 0) + if (cache_space_refresh(s, storage) < 0) return; metrics = &storage->metrics; @@ -319,7 +311,7 @@ static int system_journal_open(Server *s, bool flush_requested) { r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_storage.metrics, &s->system_journal); if (r >= 0) { server_add_acls(s->system_journal, 0); - (void) determine_space_for(s, &s->system_storage, NULL, NULL); + (void) cache_space_refresh(s, &s->system_storage); patch_min_use(&s->system_storage); } else if (r < 0) { if (r != -ENOENT && r != -EROFS) @@ -374,7 +366,7 @@ static int system_journal_open(Server *s, bool flush_requested) { if (s->runtime_journal) { server_add_acls(s->runtime_journal, 0); - (void) determine_space_for(s, &s->runtime_storage, NULL, NULL); + (void) cache_space_refresh(s, &s->runtime_storage); patch_min_use(&s->runtime_storage); } } @@ -527,21 +519,19 @@ void server_sync(Server *s) { static void do_vacuum(Server *s, JournalStorage *storage, bool verbose) { - JournalMetrics *metrics; - uint64_t limit; int r; assert(s); assert(storage); - metrics = &storage->metrics; - limit = metrics->max_use; - (void) determine_space_for(s, storage, NULL, &limit); + (void) cache_space_refresh(s, storage); if (verbose) server_space_usage_message(s, storage); - r = journal_directory_vacuum(storage->path, limit, metrics->n_max_files, s->max_retention_usec, &s->oldest_file_usec, verbose); + r = journal_directory_vacuum(storage->path, storage->space.limit, + storage->metrics.n_max_files, s->max_retention_usec, + &s->oldest_file_usec, verbose); if (r < 0 && r != -ENOENT) log_warning_errno(r, "Failed to vacuum %s, ignoring: %m", storage->path); -- cgit v1.2.3-54-g00ecf From 9ee051b9c7623e148bf0d768cc2677aecf283fc8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 19 Oct 2016 20:50:47 +0900 Subject: boot: fix `bootctl install` segfault (#4404) --- src/boot/bootctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index ee6d7eb864..13cf7e94f0 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -621,7 +621,8 @@ static const char *efi_subdirs[] = { "EFI/systemd", "EFI/BOOT", "loader", - "loader/entries" + "loader/entries", + NULL }; static int create_dirs(const char *esp_path) { -- cgit v1.2.3-54-g00ecf From 88a00ac517f282a0efa61c629031cacb38437855 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Wed, 19 Oct 2016 22:15:20 +0300 Subject: bootctl: don't try to remove esp_path (#4407) This is a follow-up for 9ee051b9c7623 --- src/boot/bootctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 13cf7e94f0..dc11b0d9db 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -918,7 +918,7 @@ static int remove_binaries(const char *esp_path) { if (q < 0 && r == 0) r = q; - for (i = ELEMENTSOF(efi_subdirs); i > 0; i--) { + for (i = ELEMENTSOF(efi_subdirs)-1; i > 0; i--) { q = rmdir_one(esp_path, efi_subdirs[i-1]); if (q < 0 && r == 0) r = q; -- cgit v1.2.3-54-g00ecf From 4cf13011fe564229a145d5a82c64216ef88d4f57 Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Wed, 19 Oct 2016 23:21:26 +0200 Subject: man: document dependencies implied by Sockets= (#4412) Fixes #4410. Also includes two minor improvements to the previous sentence. --- man/systemd.service.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/man/systemd.service.xml b/man/systemd.service.xml index 8203f2d52e..90b1312603 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -96,9 +96,12 @@ After= on dbus.socket. - Socket activated service are automatically ordered after - their activated .socket units via an - automatic After= dependency. + Socket activated services are automatically ordered after + their activating .socket units via an + automatic After= dependency. + Services also pull in all .socket units + listed in Sockets= via automatic + Wants= and After= dependencies. Unless DefaultDependencies= in the [Unit] is set to , service units will implicitly have dependencies of type Requires= and -- cgit v1.2.3-54-g00ecf From 5368222db6093195dbbd5fc7418508b154b1b769 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Oct 2016 01:48:35 +0200 Subject: core: let's upgrade the log level for service processes dying of signal (#4415) As suggested in https://github.com/systemd/systemd/pull/4367#issuecomment-253670328 --- src/core/service.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/core/service.c b/src/core/service.c index c949de9cbe..f9127d7509 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2646,7 +2646,14 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { f = SERVICE_SUCCESS; } - log_struct(f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE, + /* When this is a successful exit, let's log about the exit code on DEBUG level. If this is a failure + * and the process exited on its own via exit(), then let's make this a NOTICE, under the assumption + * that the service already logged the reason at a higher log level on its own. However, if the service + * died due to a signal, then it most likely didn't say anything about any reason, hence let's raise + * our log level to WARNING then. */ + + log_struct(f == SERVICE_SUCCESS ? LOG_DEBUG : + (code == CLD_EXITED ? LOG_NOTICE : LOG_WARNING), LOG_UNIT_ID(u), LOG_UNIT_MESSAGE(u, "Main process exited, code=%s, status=%i/%s", sigchld_code_to_string(code), status, -- cgit v1.2.3-54-g00ecf From 3ce40911bdfee404ff816471c77a6afd7d8b2271 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 18 Oct 2016 13:38:41 -0400 Subject: pid1: downgrade some rlimit warnings Since we ignore the result anyway, downgrade errors to warning. log_oom() will still emit an error, but that's mostly theoretical, so it is not worth complicating the code to avoid the small inconsistency --- src/core/main.c | 6 +++--- src/core/manager.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 61f3828a36..cf3c640a73 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1124,7 +1124,7 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) { * later when transitioning from the initrd to the main * systemd or suchlike. */ if (getrlimit(RLIMIT_NOFILE, saved_rlimit) < 0) - return log_error_errno(errno, "Reading RLIMIT_NOFILE failed: %m"); + return log_warning_errno(errno, "Reading RLIMIT_NOFILE failed, ignoring: %m"); /* Make sure forked processes get the default kernel setting */ if (!arg_default_rlimit[RLIMIT_NOFILE]) { @@ -1141,7 +1141,7 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) { nl.rlim_cur = nl.rlim_max = 64*1024; r = setrlimit_closest(RLIMIT_NOFILE, &nl); if (r < 0) - return log_error_errno(r, "Setting RLIMIT_NOFILE failed: %m"); + return log_warning_errno(r, "Setting RLIMIT_NOFILE failed, ignoring: %m"); return 0; } @@ -1775,7 +1775,7 @@ int main(int argc, char *argv[]) { log_warning_errno(errno, "Failed to make us a subreaper: %m"); if (arg_system) { - bump_rlimit_nofile(&saved_rlimit_nofile); + (void) bump_rlimit_nofile(&saved_rlimit_nofile); if (empty_etc) { r = unit_file_preset_all(UNIT_FILE_SYSTEM, false, NULL, UNIT_FILE_PRESET_ENABLE_ONLY, false, NULL, 0); diff --git a/src/core/manager.c b/src/core/manager.c index 50aae0d1ba..65f163de31 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -3098,7 +3098,7 @@ int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) { m->rlimit[i] = newdup(struct rlimit, default_rlimit[i], 1); if (!m->rlimit[i]) - return -ENOMEM; + return log_oom(); } return 0; -- cgit v1.2.3-54-g00ecf From a5e739a570081231eccb5a01a2b891f8bbaa86ba Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 19 Oct 2016 22:49:22 -0400 Subject: build-sys: allow autogen.sh to take configure params It is sometimes nice to run autogen with some configure parameters. For example: ./autogen.sh c --disable-manpages So pass any extra args after the [cgals] verb to the configure command. Also, check that the verb is correct (empty or one of the known letters) before doing any non-trivial work. --- autogen.sh | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/autogen.sh b/autogen.sh index 4ec1b2be79..82ebb57db1 100755 --- a/autogen.sh +++ b/autogen.sh @@ -17,6 +17,16 @@ set -e +verb="$1" + +if [[ -n "$verb" ]]; then + if [[ "$verb" != [cgals] ]]; then + echo "Unexpected argument: $verb" >&2 + exit 1 + fi + shift +fi + oldpwd=$(pwd) topdir=$(dirname $0) cd $topdir @@ -52,21 +62,22 @@ args="$args \ " fi +args="$args $@" cd $oldpwd -if [ "x$1" = "xc" ]; then +if [ "$verb" = "c" ]; then $topdir/configure CFLAGS='-g -O0 -ftrapv' $args make clean -elif [ "x$1" = "xg" ]; then +elif [ "$verb" = "g" ]; then $topdir/configure CFLAGS='-g -Og -ftrapv' $args make clean -elif [ "x$1" = "xa" ]; then +elif [ "$verb" = "a" ]; then $topdir/configure CFLAGS='-g -O0 -Wsuggest-attribute=pure -Wsuggest-attribute=const -ftrapv' $args make clean -elif [ "x$1" = "xl" ]; then +elif [ "$verb" = "l" ]; then $topdir/configure CC=clang CFLAGS='-g -O0 -ftrapv' $args make clean -elif [ "x$1" = "xs" ]; then +elif [ "$verb" = "s" ]; then scan-build $topdir/configure CFLAGS='-std=gnu99 -g -O0 -ftrapv' $args scan-build make else -- cgit v1.2.3-54-g00ecf From fe9d97c673e6e2c0c39147582547a89e217bfcdb Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 19 Oct 2016 22:57:02 -0400 Subject: build-sys: show configure and make commands And also hide make clean output which is very verbose and not particularly interesting. --- autogen.sh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/autogen.sh b/autogen.sh index 82ebb57db1..fa8d2916ad 100755 --- a/autogen.sh +++ b/autogen.sh @@ -66,18 +66,23 @@ args="$args $@" cd $oldpwd if [ "$verb" = "c" ]; then + set -x $topdir/configure CFLAGS='-g -O0 -ftrapv' $args - make clean + make clean >/dev/null elif [ "$verb" = "g" ]; then + set -x $topdir/configure CFLAGS='-g -Og -ftrapv' $args - make clean + make clean >/dev/null elif [ "$verb" = "a" ]; then + set -x $topdir/configure CFLAGS='-g -O0 -Wsuggest-attribute=pure -Wsuggest-attribute=const -ftrapv' $args - make clean + make clean >/dev/null elif [ "$verb" = "l" ]; then + set -x $topdir/configure CC=clang CFLAGS='-g -O0 -ftrapv' $args - make clean + make clean >/dev/null elif [ "$verb" = "s" ]; then + set -x scan-build $topdir/configure CFLAGS='-std=gnu99 -g -O0 -ftrapv' $args scan-build make else -- cgit v1.2.3-54-g00ecf From 697f4942160908a5bb227f7833c5666262ae4565 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 20 Oct 2016 10:24:18 +0200 Subject: hwdb: Update database of Bluetooth company identifiers --- hwdb/20-bluetooth-vendor-product.hwdb | 93 +++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/hwdb/20-bluetooth-vendor-product.hwdb b/hwdb/20-bluetooth-vendor-product.hwdb index ab6e321ff6..9cba3bfc05 100644 --- a/hwdb/20-bluetooth-vendor-product.hwdb +++ b/hwdb/20-bluetooth-vendor-product.hwdb @@ -3026,3 +3026,96 @@ bluetooth:v03ED* bluetooth:v03EE* ID_VENDOR_FROM_DATABASE=CUBE TECHNOLOGIES + +bluetooth:v03EF* + ID_VENDOR_FROM_DATABASE=foolography GmbH + +bluetooth:v03F0* + ID_VENDOR_FROM_DATABASE=CLINK + +bluetooth:v03F1* + ID_VENDOR_FROM_DATABASE=Hestan Smart Cooking Inc. + +bluetooth:v03F2* + ID_VENDOR_FROM_DATABASE=WindowMaster A/S + +bluetooth:v03F3* + ID_VENDOR_FROM_DATABASE=Flowscape AB + +bluetooth:v03F4* + ID_VENDOR_FROM_DATABASE=PAL Technologies Ltd + +bluetooth:v03F5* + ID_VENDOR_FROM_DATABASE=WHERE, Inc. + +bluetooth:v03F6* + ID_VENDOR_FROM_DATABASE=Iton Technology Corp. + +bluetooth:v03F7* + ID_VENDOR_FROM_DATABASE=Owl Labs Inc. + +bluetooth:v03F8* + ID_VENDOR_FROM_DATABASE=Rockford Corp. + +bluetooth:v03F9* + ID_VENDOR_FROM_DATABASE=Becon Technologies Co.,Ltd. + +bluetooth:v03FA* + ID_VENDOR_FROM_DATABASE=Vyassoft Technologies Inc + +bluetooth:v03FB* + ID_VENDOR_FROM_DATABASE=Nox Medical + +bluetooth:v03FC* + ID_VENDOR_FROM_DATABASE=Kimberly-Clark + +bluetooth:v03FD* + ID_VENDOR_FROM_DATABASE=Trimble Navigation Ltd. + +bluetooth:v03FE* + ID_VENDOR_FROM_DATABASE=Littelfuse + +bluetooth:v03FF* + ID_VENDOR_FROM_DATABASE=Withings + +bluetooth:v0400* + ID_VENDOR_FROM_DATABASE=i-developer IT Beratung UG + +bluetooth:v0401* + ID_VENDOR_FROM_DATABASE=リレーションズ株式会社 + +bluetooth:v0402* + ID_VENDOR_FROM_DATABASE=Sears Holdings Corporation + +bluetooth:v0403* + ID_VENDOR_FROM_DATABASE=Gantner Electronic GmbH + +bluetooth:v0404* + ID_VENDOR_FROM_DATABASE=Authomate Inc + +bluetooth:v0405* + ID_VENDOR_FROM_DATABASE=Vertex International, Inc. + +bluetooth:v0406* + ID_VENDOR_FROM_DATABASE=Airtago + +bluetooth:v0407* + ID_VENDOR_FROM_DATABASE=Swiss Audio SA + +bluetooth:v0408* + ID_VENDOR_FROM_DATABASE=ToGetHome Inc. + +bluetooth:v0409* + ID_VENDOR_FROM_DATABASE=AXIS + +bluetooth:v040A* + ID_VENDOR_FROM_DATABASE=Openmatics + +bluetooth:v040B* + ID_VENDOR_FROM_DATABASE=Jana Care Inc. + +bluetooth:v040C* + ID_VENDOR_FROM_DATABASE=Senix Corporation + +bluetooth:v040D* + ID_VENDOR_FROM_DATABASE=NorthStar Battery Company, LLC -- cgit v1.2.3-54-g00ecf From e9c880dd2c841b4c61c6e8c194001767feed0aab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 18 Oct 2016 16:18:08 +0200 Subject: man: one more cgroup wording fix --- man/machinectl.xml | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/man/machinectl.xml b/man/machinectl.xml index eaa247714b..0d57c01765 100644 --- a/man/machinectl.xml +++ b/man/machinectl.xml @@ -343,18 +343,13 @@ show [NAME...] - Show properties of one or more registered - virtual machines or containers or the manager itself. If no - argument is specified, properties of the manager will be - shown. If a NAME is specified, properties of this virtual - machine or container are shown. By default, empty properties - are suppressed. Use to show those too. - To select specific properties to show, use - . This command is intended to be - used whenever computer-parsable output is required, and does - not print the cgroup tree or journal entries. Use - status if you are looking for formatted - human-readable output. + Show properties of one or more registered virtual machines or containers or the manager + itself. If no argument is specified, properties of the manager will be shown. If a NAME is specified, + properties of this virtual machine or container are shown. By default, empty properties are suppressed. Use + to show those too. To select specific properties to show, use + . This command is intended to be used whenever computer-parsable output is + required, and does not print the control group tree or journal entries. Use status if you + are looking for formatted human-readable output. -- cgit v1.2.3-54-g00ecf From 8ae2c6300feffc598f1b13b9268e7312c647d19e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Oct 2016 23:30:50 +0200 Subject: journald,core: add short comments we we keep reopening /dev/console all the time Just to make sure the next one reading this isn't surprised that the fd isn't kept open. SAK and stuff... Fix suggested: https://github.com/systemd/systemd/pull/4366#issuecomment-253659162 --- src/core/show-status.c | 5 +++++ src/journal/journald-console.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/core/show-status.c b/src/core/show-status.c index 59ebdc7219..65f9cb888a 100644 --- a/src/core/show-status.c +++ b/src/core/show-status.c @@ -61,6 +61,11 @@ int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char if (vasprintf(&s, format, ap) < 0) return log_oom(); + /* Before you ask: yes, on purpose we open/close the console for each status line we write individually. This + * is a good strategy to avoid PID 1 getting killed by the kernel's SAK concept (it doesn't fix this entirely, + * but minimizes the time window the kernel might end up killing PID 1 due to SAK). It also makes things easier + * for us so that we don't have to recover from hangups and suchlike triggered on the console. */ + fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) return fd; diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c index fcc9f25814..3a9fba42a3 100644 --- a/src/journal/journald-console.c +++ b/src/journal/journald-console.c @@ -102,6 +102,11 @@ void server_forward_console( tty = s->tty_path ? s->tty_path : "/dev/console"; + /* Before you ask: yes, on purpose we open/close the console for each log line we write individually. This is a + * good strategy to avoid journald getting killed by the kernel's SAK concept (it doesn't fix this entirely, + * but minimizes the time window the kernel might end up killing journald due to SAK). It also makes things + * easier for us so that we don't have to recover from hangups and suchlike triggered on the console. */ + fd = open_terminal(tty, O_WRONLY|O_NOCTTY|O_CLOEXEC); if (fd < 0) { log_debug_errno(fd, "Failed to open %s for logging: %m", tty); -- cgit v1.2.3-54-g00ecf From 47da760efddc1fae8dac460430efd0ae7090c6c4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Oct 2016 23:40:31 +0200 Subject: man: document default for User= Replaces: #4375 --- man/systemd.exec.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 7453aa7bee..dbe4594730 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -141,8 +141,13 @@ Group= Set the UNIX user or group that the processes are executed as, respectively. Takes a single - user or group name, or numeric ID as argument. If no group is set, the default group of the user is used. This - setting does not affect commands whose command line is prefixed with +. + user or group name, or numeric ID as argument. For system services (services run by the system service manager, + i.e. managed by PID 1) and for user services of the root user (services managed by root's instance of + systemd --user), the default is root, but User= may be + used to specify a different user. For user services of any other user, switching user identity is not + permitted, hence the only valid setting is the same user the user's service manager is running as. If no group + is set, the default group of the user is used. This setting does not affect commands whose command line is + prefixed with +. -- cgit v1.2.3-54-g00ecf From 6e3136b209679d88c4347ce2f6d5e22c031e4d3e Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 20 Oct 2016 00:27:46 -0400 Subject: shared/install: fix DefaultInstance expansion in %i MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should substitute DefaultInstance if the instance is not specified. Test case: [Install] DefaultInstance=bond1 WantedBy= foobar-i-%i.device $ systemctl --root=/ enable testing4@.service Created symlink /etc/systemd/system/foobar-i-bond1.device.wants/testing4@bond1.service → /etc/systemd/system/testing4@.service. (before, the symlink would be created as /etc/systemd/system/foobar-i-.device.wants/testing4@bond1.service) Fixes #4411. --- src/shared/install-printf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c index 88143361da..9fc915d62e 100644 --- a/src/shared/install-printf.c +++ b/src/shared/install-printf.c @@ -27,6 +27,7 @@ #include "install.h" #include "macro.h" #include "specifier.h" +#include "string-util.h" #include "unit-name.h" #include "user-util.h" @@ -47,7 +48,7 @@ static int specifier_prefix(char specifier, void *data, void *userdata, char **r } static int specifier_instance(char specifier, void *data, void *userdata, char **ret) { - UnitFileInstallInfo *i = userdata; + const UnitFileInstallInfo *i = userdata; char *instance; int r; @@ -57,8 +58,8 @@ static int specifier_instance(char specifier, void *data, void *userdata, char * if (r < 0) return r; - if (!instance) { - instance = strdup(""); + if (isempty(instance)) { + instance = strdup(i->default_instance ?: ""); if (!instance) return -ENOMEM; } -- cgit v1.2.3-54-g00ecf From cfd559c9a8bc398ce03d604957fa31fbbcaef2ef Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 20 Oct 2016 00:27:46 -0400 Subject: shared/install: fix DefaultInstance expansion in %n, %N MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should substitute DefaultInstance if the instance is not specified. Test case: [Install] DefaultInstance=bond1 WantedBy= foobar-n-%n.device WantedBy= foobar-N-%N.device $ systemctl --root=/ enable testing4@.service Created symlink /etc/systemd/system/foobar-n-testing4@bond1.service.device.wants/testing4@bond1.service → /etc/systemd/system/testing4@.service. Created symlink /etc/systemd/system/foobar-N-testing4@bond1.device.wants/testing4@bond1.service → /etc/systemd/system/testing4@.service. (before, the symlink would be created with empty %n, %N parts). --- src/shared/install-printf.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c index 9fc915d62e..267762d84f 100644 --- a/src/shared/install-printf.c +++ b/src/shared/install-printf.c @@ -32,15 +32,49 @@ #include "user-util.h" static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) { - UnitFileInstallInfo *i = userdata; + const UnitFileInstallInfo *i = userdata; + _cleanup_free_ char *prefix = NULL; + int r; + + assert(i); + + r = unit_name_to_prefix_and_instance(i->name, &prefix); + if (r < 0) + return r; + + if (endswith(prefix, "@") && i->default_instance) { + char *ans; + + ans = strjoin(prefix, i->default_instance, NULL); + if (!ans) + return -ENOMEM; + *ret = ans; + } else { + *ret = prefix; + prefix = NULL; + } + + return 0; +} + +static int specifier_name(char specifier, void *data, void *userdata, char **ret) { + const UnitFileInstallInfo *i = userdata; + char *ans; assert(i); - return unit_name_to_prefix_and_instance(i->name, ret); + if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE) && i->default_instance) + return unit_name_replace_instance(i->name, i->default_instance, ret); + + ans = strdup(i->name); + if (!ans) + return -ENOMEM; + *ret = ans; + return 0; } static int specifier_prefix(char specifier, void *data, void *userdata, char **ret) { - UnitFileInstallInfo *i = userdata; + const UnitFileInstallInfo *i = userdata; assert(i); @@ -111,7 +145,7 @@ int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret) */ const Specifier table[] = { - { 'n', specifier_string, i->name }, + { 'n', specifier_name, NULL }, { 'N', specifier_prefix_and_instance, NULL }, { 'p', specifier_prefix, NULL }, { 'i', specifier_instance, NULL }, -- cgit v1.2.3-54-g00ecf From 6309e51ea32d64524431ee65c49eecd44390da8f Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 20 Oct 2016 00:27:46 -0400 Subject: shared/install: fix %u expansion when running under sudo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test case: [Install] DefaultInstance=bond1 WantedBy= foobar-U-%U.device WantedBy= foobar-u-%u.device $ sudo systemctl --root=/ enable testing4@.service (before) Created symlink /etc/systemd/system/foobar-U-0.device.wants/testing4@bond1.service → /etc/systemd/system/testing4@.service. Created symlink /etc/systemd/system/foobar-u-zbyszek.device.wants/testing4@bond1.service → /etc/systemd/system/testing4@.service. (after) Created symlink /etc/systemd/system/foobar-U-0.device.wants/testing4@bond1.service → /etc/systemd/system/testing4@.service. Created symlink /etc/systemd/system/foobar-u-root.device.wants/testing4@bond1.service → /etc/systemd/system/testing4@.service. It doesn't make much sense to use a different user for %U and %u. --- src/shared/install-printf.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c index 267762d84f..cbdf66827f 100644 --- a/src/shared/install-printf.c +++ b/src/shared/install-printf.c @@ -108,9 +108,13 @@ static int specifier_user_name(char specifier, void *data, void *userdata, char /* If we are UID 0 (root), this will not result in NSS, * otherwise it might. This is good, as we want to be able to * run this in PID 1, where our user ID is 0, but where NSS - * lookups are not allowed. */ + * lookups are not allowed. - t = getusername_malloc(); + * We don't user getusername_malloc() here, because we don't want to look + * at $USER, to remain consistent with specifer_user_id() below. + */ + + t = uid_to_name(getuid()); if (!t) return -ENOMEM; -- cgit v1.2.3-54-g00ecf From a5d5c0d2df73fdb31effe1e0f4949508f340bf59 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Thu, 20 Oct 2016 18:44:30 +0300 Subject: tests: fix memleak in test-calendarspec (#4424) Fixes: ``` ==10750== ==10750== HEAP SUMMARY: ==10750== in use at exit: 96 bytes in 3 blocks ==10750== total heap usage: 1,711 allocs, 1,708 frees, 854,545 bytes allocated ==10750== ==10750== 96 (64 direct, 32 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 3 ==10750== at 0x4C2DA60: calloc (vg_replace_malloc.c:711) ==10750== by 0x4EB3BDA: calendar_spec_from_string (calendarspec.c:771) ==10750== by 0x109675: test_hourly_bug_4031 (test-calendarspec.c:118) ==10750== by 0x10A00E: main (test-calendarspec.c:202) ==10750== ==10750== LEAK SUMMARY: ==10750== definitely lost: 64 bytes in 1 blocks ==10750== indirectly lost: 32 bytes in 2 blocks ==10750== possibly lost: 0 bytes in 0 blocks ==10750== still reachable: 0 bytes in 0 blocks ==10750== suppressed: 0 bytes in 0 blocks ==10750== ==10750== For counts of detected and suppressed errors, rerun with: -v ==10750== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) ``` --- src/test/test-calendarspec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c index 752ad0aca8..59217b131c 100644 --- a/src/test/test-calendarspec.c +++ b/src/test/test-calendarspec.c @@ -129,6 +129,8 @@ static void test_hourly_bug_4031(void) { assert_se(u <= n + USEC_PER_HOUR); assert_se(u < w); assert_se(w <= u + USEC_PER_HOUR); + + calendar_spec_free(c); } int main(int argc, char* argv[]) { -- cgit v1.2.3-54-g00ecf From 2fa4f10835b9d994f152b8097537e3f2cdc6f6e7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Oct 2016 17:45:27 +0200 Subject: units: extend stop timeout for user@.service to 120s (#4426) By default all user and all system services get stop timeouts for 90s. This is problematic as the user manager of course is run as system service. Thus, if the default time-out is hit for any user service, then it will also be hit for user@.service as a whole, thus making the whole concept useless for user services. This patch extends the stop timeout to 120s for user@.service hence, so that that the user service manager has ample time to process user services timing out. (The other option would have been to shorten the default user service timeout, but I think a user service should get the same timeout by default as a system service) Fixes: #4206 --- units/user@.service.m4.in | 1 + 1 file changed, 1 insertion(+) diff --git a/units/user@.service.m4.in b/units/user@.service.m4.in index 66aba4f985..1beb901db8 100644 --- a/units/user@.service.m4.in +++ b/units/user@.service.m4.in @@ -18,3 +18,4 @@ Slice=user-%i.slice KillMode=mixed Delegate=yes TasksMax=infinity +TimeoutStopSec=120s -- cgit v1.2.3-54-g00ecf From 411e869f497c7c7bd0688f1e3500f9043bc56e48 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Oct 2016 19:36:28 +0200 Subject: sysctl: run sysctl service if /proc/sys/net is writable (#4425) This simply changes this line: ConditionPathIsReadWrite=/proc/sys/ to this: ConditionPathIsReadWrite=/proc/sys/net/ The background for this is that the latter is namespaced through network namespacing usually and hence frequently set as writable in containers, even though the former is kept read-only. If /proc/sys is read-only but /proc/sys/net is writable we should run the sysctl service, as useful settings may be made in this case. Fixes: #4370 --- units/systemd-sysctl.service.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/units/systemd-sysctl.service.in b/units/systemd-sysctl.service.in index d784c6426d..980f611df2 100644 --- a/units/systemd-sysctl.service.in +++ b/units/systemd-sysctl.service.in @@ -12,7 +12,7 @@ DefaultDependencies=no Conflicts=shutdown.target After=systemd-modules-load.service Before=sysinit.target shutdown.target -ConditionPathIsReadWrite=/proc/sys/ +ConditionPathIsReadWrite=/proc/sys/net/ [Service] Type=oneshot -- cgit v1.2.3-54-g00ecf From b5bdbcd5ba2c0279ada3fce31ff9f631361831c5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Oct 2016 19:19:34 +0200 Subject: update TODO --- TODO | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TODO b/TODO index 1f1c2739c5..7e21c3e8d5 100644 --- a/TODO +++ b/TODO @@ -32,6 +32,10 @@ Janitorial Clean-ups: Features: +* add a percentage syntax for TimeoutStopSec=, e.g. TimeoutStopSec=150%, and + then use that for the setting used in user@.service. It should be understood + relative to the configured default value. + * on cgroupsv2 add DelegateControllers=, to pick the precise cgroup controllers to delegate * in networkd, when matching device types, fix up DEVTYPE rubbish the kernel passes to us -- cgit v1.2.3-54-g00ecf From 84a4e6608dbda38c724ab196a226db209a50b224 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Oct 2016 19:19:46 +0200 Subject: logind: don't hit assert when we try to free NULL manager object Fixes: #4431 --- src/login/logind.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/login/logind.c b/src/login/logind.c index a9a06f5e28..a9841a3832 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -126,7 +126,8 @@ static void manager_free(Manager *m) { Inhibitor *i; Button *b; - assert(m); + if (!m) + return; while ((session = hashmap_first(m->sessions))) session_free(session); -- cgit v1.2.3-54-g00ecf From dfc7f59430fb5adb280c0ef42df3c8cd23fefc13 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Oct 2016 19:20:22 +0200 Subject: update-utmp: let's use STR_IN_SET() where it is pretty --- src/update-utmp/update-utmp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c index 8ae4a8a833..a8efe8e91f 100644 --- a/src/update-utmp/update-utmp.c +++ b/src/update-utmp/update-utmp.c @@ -34,6 +34,7 @@ #include "log.h" #include "macro.h" #include "special.h" +#include "strv.h" #include "unit-name.h" #include "util.h" #include "utmp-wtmp.h" @@ -107,7 +108,7 @@ static int get_current_runlevel(Context *c) { if (r < 0) return log_warning_errno(r, "Failed to get state: %s", bus_error_message(&error, r)); - if (streq(state, "active") || streq(state, "reloading")) + if (STR_IN_SET(state, "active", "reloading")) return table[i].runlevel; } -- cgit v1.2.3-54-g00ecf From d9b8ea5448ba1e61d681a206d770a4eac39b9936 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Thu, 20 Oct 2016 21:23:32 +0300 Subject: sysusers: fix memleak (#4430) Fixes: ``` ==28075== 64 bytes in 1 blocks are definitely lost in loss record 2 of 3 ==28075== at 0x4C2BAEE: malloc (vg_replace_malloc.c:298) ==28075== by 0x4C2DCA1: realloc (vg_replace_malloc.c:785) ==28075== by 0x4ED40A2: greedy_realloc (alloc-util.c:57) ==28075== by 0x4E90F87: extract_first_word (extract-word.c:78) ==28075== by 0x4E91813: extract_many_words (extract-word.c:270) ==28075== by 0x10FE93: parse_line (sysusers.c:1325) ==28075== by 0x11198B: read_config_file (sysusers.c:1640) ==28075== by 0x111EB8: main (sysusers.c:1773) ==28075== ``` --- src/sysusers/sysusers.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 5d72493725..655f41c610 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -1189,6 +1189,7 @@ static void item_free(Item *i) { free(i->uid_path); free(i->gid_path); free(i->description); + free(i->home); free(i); } -- cgit v1.2.3-54-g00ecf From 24597ee0e626b61f134e09b4e871449ef86b1343 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 20 Oct 2016 23:03:26 -0400 Subject: nspawn, NEWS: add missing "s" in --private-users-chown (#4438) --- NEWS | 14 +++++++------- src/nspawn/nspawn.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index 4924d7c4b6..5467166567 100644 --- a/NEWS +++ b/NEWS @@ -569,13 +569,13 @@ CHANGES WITH 230: of the owners and the ACLs of all files and directories in a container tree to match the UID/GID user namespacing range selected for the container invocation. This mode is enabled via the new - --private-user-chown switch. It also gained support for automatically - choosing a free, previously unused UID/GID range when starting a - container, via the new --private-users=pick setting (which implies - --private-user-chown). Together, these options for the first time - make user namespacing for nspawn containers fully automatic and thus - deployable. The systemd-nspawn@.service template unit file has been - changed to use this functionality by default. + --private-users-chown switch. It also gained support for + automatically choosing a free, previously unused UID/GID range when + starting a container, via the new --private-users=pick setting (which + implies --private-users-chown). Together, these options for the first + time make user namespacing for nspawn containers fully automatic and + thus deployable. The systemd-nspawn@.service template unit file has + been changed to use this functionality by default. * systemd-nspawn gained a new --network-zone= switch, that allows creating ad-hoc virtual Ethernet links between multiple containers, diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 14af51fc0e..2cbe563953 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -219,7 +219,7 @@ static void help(void) { " -U --private-users=pick Run within user namespace, autoselect UID/GID range\n" " --private-users[=UIDBASE[:NUIDS]]\n" " Similar, but with user configured UID/GID range\n" - " --private-user-chown Adjust OS tree ownership to private UID/GID range\n" + " --private-users-chown Adjust OS tree ownership to private UID/GID range\n" " --private-network Disable network in container\n" " --network-interface=INTERFACE\n" " Assign an existing network interface to the\n" -- cgit v1.2.3-54-g00ecf From 75e2089581100ba0ae76d9e5f5dd82ae1cbc6c14 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 21 Oct 2016 02:17:16 -0400 Subject: Revert "add networkd dbus lease info" (#4435) --- src/network/networkd-link-bus.c | 131 ---------------------------------------- src/network/networkd-link.h | 5 -- src/network/networkd-manager.c | 8 --- 3 files changed, 144 deletions(-) diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c index 10ec08351a..532557ed6c 100644 --- a/src/network/networkd-link-bus.c +++ b/src/network/networkd-link-bus.c @@ -23,7 +23,6 @@ #include "networkd.h" #include "parse-util.h" #include "strv.h" -#include "dhcp-lease-internal.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState); @@ -37,50 +36,6 @@ const sd_bus_vtable link_vtable[] = { SD_BUS_VTABLE_END }; -static int get_private_options(sd_bus *bus, - const char *path, - const char *interface, - const char *property, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error) { - sd_dhcp_lease *lease = userdata; - struct sd_dhcp_raw_option *option = NULL; - int r; - - assert(bus); - assert(reply); - assert(lease); - - r = sd_bus_message_open_container(reply, SD_BUS_TYPE_ARRAY, "{yay}"); - if (r < 0) - return r; - - LIST_FOREACH(options, option, lease->private_options) { - r = sd_bus_message_open_container(reply, SD_BUS_TYPE_DICT_ENTRY, "yay"); - if (r < 0) - return r; - r = sd_bus_message_append(reply, "y", option->tag); - if (r < 0) - return r; - r = sd_bus_message_append_array(reply, 'y', option->data, option->length); - if (r < 0) - return r; - r = sd_bus_message_close_container(reply); - if (r < 0) - return r; - } - return sd_bus_message_close_container(reply); -} - -const sd_bus_vtable lease_vtable[] = { - SD_BUS_VTABLE_START(0), - - SD_BUS_PROPERTY("PrivateOptions", "a{yay}", get_private_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - - SD_BUS_VTABLE_END -}; - static char *link_bus_path(Link *link) { _cleanup_free_ char *ifindex = NULL; char *p; @@ -99,24 +54,6 @@ static char *link_bus_path(Link *link) { return p; } -static char *lease_bus_path(Link *link) { - _cleanup_free_ char *p = NULL; - char *ret = NULL; - int r; - - assert(link); - - p = link_bus_path(link); - if (!p) - return NULL; - - r = sd_bus_path_encode(p, "lease", &ret); - if (r < 0) - return NULL; - - return ret; -} - int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; Manager *m = userdata; @@ -150,42 +87,6 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char *** return 1; } -int lease_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - unsigned c = 0; - Link *link; - Iterator i; - - assert(bus); - assert(path); - assert(m); - assert(nodes); - - l = new0(char*, hashmap_size(m->links) + 1); - if (!l) - return -ENOMEM; - - HASHMAP_FOREACH(link, m->links, i) { - char *p; - - if (!link->dhcp_lease) - continue; - - p = lease_bus_path(link); - if (!p) - return -ENOMEM; - - l[c++] = p; - } - - l[c] = NULL; - *nodes = l; - l = NULL; - - return 1; -} - int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { _cleanup_free_ char *identifier = NULL; Manager *m = userdata; @@ -215,38 +116,6 @@ int link_object_find(sd_bus *bus, const char *path, const char *interface, void return 1; } -int lease_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { - _cleanup_free_ char *identifier = NULL; - Manager *m = userdata; - Link *link; - int ifindex, r; - - assert(bus); - assert(path); - assert(interface); - assert(m); - assert(found); - - r = sd_bus_path_decode_many(path, "/org/freedesktop/network1/link/%/lease", &identifier); - if (r <= 0) - return 0; - - r = parse_ifindex(identifier, &ifindex); - if (r < 0) - return 0; - - r = link_get(m, ifindex, &link); - if (r < 0) - return 0; - - if (!link->dhcp_lease) - return 0; - - *found = link->dhcp_lease; - - return 1; -} - int link_send_changed(Link *link, const char *property, ...) { _cleanup_free_ char *p = NULL; char **l; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 1178999bb4..77f72d070e 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -179,11 +179,6 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char *** int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); int link_send_changed(Link *link, const char *property, ...) _sentinel_; -extern const sd_bus_vtable lease_vtable[]; - -int lease_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); -int lease_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); - DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); #define _cleanup_link_unref_ _cleanup_(link_unrefp) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 0ad34e0cc2..9174dcc7f4 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -176,14 +176,6 @@ int manager_connect_bus(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to add link enumerator: %m"); - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link.Lease", lease_vtable, lease_object_find, m); - if (r < 0) - return log_error_errno(r, "Failed to add lease object vtable: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", lease_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to add lease enumerator: %m"); - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/network", "org.freedesktop.network1.Network", network_vtable, network_object_find, m); if (r < 0) return log_error_errno(r, "Failed to add network object vtable: %m"); -- cgit v1.2.3-54-g00ecf From 47fffb3530af3e3ad4048570611685635fde062e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Oct 2016 12:27:46 +0200 Subject: core: if the start command vanishes during runtime don't hit an assert This can happen when the configuration is changed and reloaded while we are executing a service. Let's not hit an assert in this case. Fixes: #4444 --- src/core/service.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/core/service.c b/src/core/service.c index f9127d7509..53c26984ca 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1756,7 +1756,15 @@ static void service_enter_start(Service *s) { } if (!c) { - assert(s->type == SERVICE_ONESHOT); + if (s->type != SERVICE_ONESHOT) { + /* There's no command line configured for the main command? Hmm, that is strange. This can only + * happen if the configuration changes at runtime. In this case, let's enter a failure + * state. */ + log_unit_error(UNIT(s), "There's no 'start' task anymore we could start: %m"); + r = -ENXIO; + goto fail; + } + service_enter_start_post(s); return; } -- cgit v1.2.3-54-g00ecf From 0a12bb1eaa097dc83018aa034faef113a91e6014 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Fri, 21 Oct 2016 13:30:45 +0300 Subject: sysusers: fix memleak (#4443) Fixes: Oct 20 09:10:49 systemd-sysusers[144]: Direct leak of 20 byte(s) in 1 object(s) allocated from: Oct 20 09:10:49 systemd-sysusers[144]: #0 0x7f3565a13e60 in malloc (/lib64/libasan.so.3+0xc6e60) Oct 20 09:10:49 systemd-sysusers[144]: #1 0x7f3565526bd0 in malloc_multiply src/basic/alloc-util.h:70 Oct 20 09:10:49 systemd-sysusers[144]: #2 0x7f356552cb55 in tempfn_xxxxxx src/basic/fileio.c:1116 Oct 20 09:10:49 systemd-sysusers[144]: #3 0x7f356552c4f0 in fopen_temporary src/basic/fileio.c:1042 Oct 20 09:10:49 systemd-sysusers[144]: #4 0x7f356555e00e in fopen_temporary_label src/basic/fileio-label.c:63 Oct 20 09:10:49 systemd-sysusers[144]: #5 0x56197c4a1766 in make_backup src/sysusers/sysusers.c:209 Oct 20 09:10:49 systemd-sysusers[144]: #6 0x56197c4a6335 in write_files src/sysusers/sysusers.c:710 Oct 20 09:10:49 systemd-sysusers[144]: #7 0x56197c4ae571 in main src/sysusers/sysusers.c:1817 Oct 20 09:10:49 systemd-sysusers[144]: #8 0x7f3564dee730 in __libc_start_main (/lib64/libc.so.6+0x20730) --- src/sysusers/sysusers.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 655f41c610..0684f58fcd 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -190,7 +190,8 @@ static int load_group_database(void) { static int make_backup(const char *target, const char *x) { _cleanup_close_ int src = -1; _cleanup_fclose_ FILE *dst = NULL; - char *backup, *temp; + _cleanup_free_ char *temp = NULL; + char *backup; struct timespec ts[2]; struct stat st; int r; -- cgit v1.2.3-54-g00ecf From 9107a337771a95c4ac7d4b1279f5a9ba73f6c893 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 21 Oct 2016 20:31:32 +1000 Subject: hwdb: add MOUSE_WHEEL_CLICK_COUNT for non-integer click angles (#4440) MOUSE_WHEEL_CLICK_ANGLE has been an integer, and at least libinput (probably the only user) parses it as strict integer. For backwards compatibility, we cannot change it to a decimal number now. Add a new property to list the number of clicks for a full 360 degree rotation, to be specified in addition to the old click angle property. Clients can prefer the new one where available and calculate the decimal value to whatever precision they want. --- hwdb/70-mouse.hwdb | 22 ++++++++++++++++++++++ hwdb/parse_hwdb.py | 2 ++ 2 files changed, 24 insertions(+) diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb index 56e36af0e5..bf3d134c46 100644 --- a/hwdb/70-mouse.hwdb +++ b/hwdb/70-mouse.hwdb @@ -48,6 +48,8 @@ # MOUSE_DPI # MOUSE_WHEEL_CLICK_ANGLE # MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL +# MOUSE_WHEEL_CLICK_COUNT +# MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL # ######################################### # ID_INPUT_TRACKBALL # @@ -104,6 +106,9 @@ # MOUSE_WHEEL_CLICK_ANGLE= # # Most mice have a 15 degree click stop (24 clicks per full rotation). +# For backwards-compatibility, the click angle must be an integer. +# Where a device has non-integer click angles, the MOUSE_WHEEL_CLICK_COUNT +# property should also be specified. # ######################################### # MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL # @@ -113,6 +118,21 @@ # This property may only be specified if the angle for the horizontal # scroll wheel differs from the vertical wheel. If so, *both* click angles # must be specified. +# +######################################### +# MOUSE_WHEEL_CLICK_COUNT # +# MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL # +######################################### +# +# The number of clicks the wheel sends per 360 degree rotation. This +# property should only be used where the click angle is not an integer. +# For backwards compatibility it must be specified in addition to +# MOUSE_WHEEL_CLICK_ANGLE. +# Clients should prefer MOUSE_WHEEL_CLICK_COUNT where available, it is more +# precise than MOUSE_WHEEL_CLICK_ANGLE. +# +# MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL works the same way but also follows the +# rules of MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL. # # Sort by brand, type (usb, bluetooth), DPI, frequency. @@ -361,6 +381,8 @@ mouse:usb:v046dp4041:name:Logitech MX Master: MOUSE_DPI=1000@166 MOUSE_WHEEL_CLICK_ANGLE=15 MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26 + MOUSE_WHEEL_CLICK_COUNT=24 + MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL=14 # Logitech MK260 Wireless Combo Receiver aka M-R0011 mouse:usb:v046dpc52e:name:Logitech USB Receiver: diff --git a/hwdb/parse_hwdb.py b/hwdb/parse_hwdb.py index e163edbc51..2540c8c2f6 100755 --- a/hwdb/parse_hwdb.py +++ b/hwdb/parse_hwdb.py @@ -91,6 +91,8 @@ def property_grammar(): props = (('MOUSE_DPI', Group(OneOrMore(setting('SETTINGS*')))), ('MOUSE_WHEEL_CLICK_ANGLE', INTEGER), ('MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL', INTEGER), + ('MOUSE_WHEEL_CLICK_COUNT', INTEGER), + ('MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL', INTEGER), ('ID_INPUT_TRACKBALL', Literal('1')), ('POINTINGSTICK_SENSITIVITY', INTEGER), ('POINTINGSTICK_CONST_ACCEL', REAL), -- cgit v1.2.3-54-g00ecf From 6fa441140ee6faf131c97b1aa002e060b81aaaff Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Fri, 21 Oct 2016 13:25:23 +0200 Subject: NEWS: update NEWS about ProtectKernelModules= option (#4445) --- NEWS | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 5467166567..6378e596f6 100644 --- a/NEWS +++ b/NEWS @@ -5,16 +5,19 @@ CHANGES WITH 232 in spe * The new RemoveIPC= option can be used to remove IPC objects owned by the user or group of a service when that service exits. + * The new ProtectKernelModules= option can be used to disable explicit + load and unload operations of kernel modules by a service. + * ProtectSystem= option gained a new value "strict", which causes the whole file system tree with the exception of /dev, /proc, and /sys, to be remounted read-only for a service. - The new ProtectedKernelTunables= options can be used to disable + * The new ProtectedKernelTunables= option can be used to disable modification of configuration files in /sys and /proc by a service. Various directories and files are remounted read-only, so access is restricted even if the file permissions would allow it. - The new ProtectControlGroups= option can be used to disable write + * The new ProtectControlGroups= option can be used to disable write access by a service to /sys/fs/cgroup. * Various systemd services have been hardened with -- cgit v1.2.3-54-g00ecf From 87a47f99bc8e576a63581ad2593c62eb10a53814 Mon Sep 17 00:00:00 2001 From: Lukas Nykryn Date: Thu, 20 Oct 2016 15:27:37 +0200 Subject: failure-action: generalize failure action to emergency action --- Makefile.am | 4 +- src/core/dbus-service.c | 6 +- src/core/dbus-unit.c | 6 +- src/core/emergency-action.c | 128 ++++++++++++++++++++++++++++++++++ src/core/emergency-action.h | 41 +++++++++++ src/core/failure-action.c | 127 --------------------------------- src/core/failure-action.h | 41 ----------- src/core/job.c | 2 +- src/core/load-fragment-gperf.gperf.m4 | 8 +-- src/core/load-fragment.c | 4 +- src/core/load-fragment.h | 2 +- src/core/service.c | 2 +- src/core/service.h | 2 +- src/core/unit.c | 6 +- src/core/unit.h | 6 +- src/test/test-tables.c | 2 +- 16 files changed, 194 insertions(+), 193 deletions(-) create mode 100644 src/core/emergency-action.c create mode 100644 src/core/emergency-action.h delete mode 100644 src/core/failure-action.c delete mode 100644 src/core/failure-action.h diff --git a/Makefile.am b/Makefile.am index 00124a29f8..07acce347e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1275,8 +1275,8 @@ libcore_la_SOURCES = \ src/core/audit-fd.h \ src/core/show-status.c \ src/core/show-status.h \ - src/core/failure-action.c \ - src/core/failure-action.h + src/core/emergency-action.c \ + src/core/emergency-action.h nodist_libcore_la_SOURCES = \ src/core/load-fragment-gperf.c \ diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index 3c55e0f7fe..61b83d2d62 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -36,7 +36,7 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess); -static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_failure_action, failure_action, FailureAction); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction); const sd_bus_vtable bus_service_vtable[] = { SD_BUS_VTABLE_START(0), @@ -50,7 +50,7 @@ const sd_bus_vtable bus_service_vtable[] = { SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0), - SD_BUS_PROPERTY("FailureAction", "s", property_get_failure_action, offsetof(Service, failure_action), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Service, emergency_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST), @@ -79,7 +79,7 @@ const sd_bus_vtable bus_service_vtable[] = { /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */ SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), - SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_VTABLE_END }; diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 245912fc0f..8f34fa1a52 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -37,7 +37,7 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode); -static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_failure_action, failure_action, FailureAction); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction); static int property_get_names( sd_bus *bus, @@ -750,7 +750,7 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_failure_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), @@ -762,7 +762,7 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0), diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c new file mode 100644 index 0000000000..90232bc57a --- /dev/null +++ b/src/core/emergency-action.c @@ -0,0 +1,128 @@ +/*** + This file is part of systemd. + + Copyright 2014 Lennart Poettering + Copyright 2012 Michael Olbrich + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include + +#include "bus-error.h" +#include "bus-util.h" +#include "emergency-action.h" +#include "special.h" +#include "string-table.h" +#include "terminal-util.h" + +static void log_and_status(Manager *m, const char *message, const char *reason) { + log_warning("%s: %s", message, reason); + manager_status_printf(m, STATUS_TYPE_EMERGENCY, + ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, + "%s: %s", message, reason); +} + +int emergency_action( + Manager *m, + EmergencyAction action, + const char *reboot_arg, + const char *reason) { + + assert(m); + assert(action >= 0); + assert(action < _EMERGENCY_ACTION_MAX); + + if (action == EMERGENCY_ACTION_NONE) + return -ECANCELED; + + if (!MANAGER_IS_SYSTEM(m)) { + /* Downgrade all options to simply exiting if we run + * in user mode */ + + log_warning("Exiting: %s", reason); + m->exit_code = MANAGER_EXIT; + return -ECANCELED; + } + + switch (action) { + + case EMERGENCY_ACTION_REBOOT: + log_and_status(m, "Rebooting", reason); + + (void) update_reboot_parameter_and_warn(reboot_arg); + (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); + + break; + + case EMERGENCY_ACTION_REBOOT_FORCE: + log_and_status(m, "Forcibly rebooting", reason); + + (void) update_reboot_parameter_and_warn(reboot_arg); + m->exit_code = MANAGER_REBOOT; + + break; + + case EMERGENCY_ACTION_REBOOT_IMMEDIATE: + log_and_status(m, "Rebooting immediately", reason); + + sync(); + + if (!isempty(reboot_arg)) { + log_info("Rebooting with argument '%s'.", reboot_arg); + syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, reboot_arg); + log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m"); + } + + log_info("Rebooting."); + reboot(RB_AUTOBOOT); + break; + + case EMERGENCY_ACTION_POWEROFF: + log_and_status(m, "Powering off", reason); + (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); + break; + + case EMERGENCY_ACTION_POWEROFF_FORCE: + log_and_status(m, "Forcibly powering off", reason); + m->exit_code = MANAGER_POWEROFF; + break; + + case EMERGENCY_ACTION_POWEROFF_IMMEDIATE: + log_and_status(m, "Powering off immediately", reason); + + sync(); + + log_info("Powering off."); + reboot(RB_POWER_OFF); + break; + + default: + assert_not_reached("Unknown emergency action"); + } + + return -ECANCELED; +} + +static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = { + [EMERGENCY_ACTION_NONE] = "none", + [EMERGENCY_ACTION_REBOOT] = "reboot", + [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force", + [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate", + [EMERGENCY_ACTION_POWEROFF] = "poweroff", + [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force", + [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate" +}; +DEFINE_STRING_TABLE_LOOKUP(emergency_action, EmergencyAction); diff --git a/src/core/emergency-action.h b/src/core/emergency-action.h new file mode 100644 index 0000000000..8804b59752 --- /dev/null +++ b/src/core/emergency-action.h @@ -0,0 +1,41 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2014 Lennart Poettering + Copyright 2012 Michael Olbrich + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +typedef enum EmergencyAction { + EMERGENCY_ACTION_NONE, + EMERGENCY_ACTION_REBOOT, + EMERGENCY_ACTION_REBOOT_FORCE, + EMERGENCY_ACTION_REBOOT_IMMEDIATE, + EMERGENCY_ACTION_POWEROFF, + EMERGENCY_ACTION_POWEROFF_FORCE, + EMERGENCY_ACTION_POWEROFF_IMMEDIATE, + _EMERGENCY_ACTION_MAX, + _EMERGENCY_ACTION_INVALID = -1 +} EmergencyAction; + +#include "macro.h" +#include "manager.h" + +int emergency_action(Manager *m, EmergencyAction action, const char *reboot_arg, const char *reason); + +const char* emergency_action_to_string(EmergencyAction i) _const_; +EmergencyAction emergency_action_from_string(const char *s) _pure_; diff --git a/src/core/failure-action.c b/src/core/failure-action.c deleted file mode 100644 index ddae46190f..0000000000 --- a/src/core/failure-action.c +++ /dev/null @@ -1,127 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - Copyright 2012 Michael Olbrich - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -#include -#include - -#include "bus-error.h" -#include "bus-util.h" -#include "failure-action.h" -#include "special.h" -#include "string-table.h" -#include "terminal-util.h" - -static void log_and_status(Manager *m, const char *message) { - log_warning("%s", message); - manager_status_printf(m, STATUS_TYPE_EMERGENCY, - ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, - "%s", message); -} - -int failure_action( - Manager *m, - FailureAction action, - const char *reboot_arg) { - - assert(m); - assert(action >= 0); - assert(action < _FAILURE_ACTION_MAX); - - if (action == FAILURE_ACTION_NONE) - return -ECANCELED; - - if (!MANAGER_IS_SYSTEM(m)) { - /* Downgrade all options to simply exiting if we run - * in user mode */ - - log_warning("Exiting as result of failure."); - m->exit_code = MANAGER_EXIT; - return -ECANCELED; - } - - switch (action) { - - case FAILURE_ACTION_REBOOT: - log_and_status(m, "Rebooting as result of failure."); - - (void) update_reboot_parameter_and_warn(reboot_arg); - (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); - - break; - - case FAILURE_ACTION_REBOOT_FORCE: - log_and_status(m, "Forcibly rebooting as result of failure."); - - (void) update_reboot_parameter_and_warn(reboot_arg); - m->exit_code = MANAGER_REBOOT; - - break; - - case FAILURE_ACTION_REBOOT_IMMEDIATE: - log_and_status(m, "Rebooting immediately as result of failure."); - - sync(); - - if (!isempty(reboot_arg)) { - log_info("Rebooting with argument '%s'.", reboot_arg); - syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, reboot_arg); - log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m"); - } - - log_info("Rebooting."); - reboot(RB_AUTOBOOT); - break; - - case FAILURE_ACTION_POWEROFF: - log_and_status(m, "Powering off as result of failure."); - (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL); - break; - - case FAILURE_ACTION_POWEROFF_FORCE: - log_and_status(m, "Forcibly powering off as result of failure."); - m->exit_code = MANAGER_POWEROFF; - break; - - case FAILURE_ACTION_POWEROFF_IMMEDIATE: - log_and_status(m, "Powering off immediately as result of failure."); - - sync(); - - log_info("Powering off."); - reboot(RB_POWER_OFF); - break; - - default: - assert_not_reached("Unknown failure action"); - } - - return -ECANCELED; -} - -static const char* const failure_action_table[_FAILURE_ACTION_MAX] = { - [FAILURE_ACTION_NONE] = "none", - [FAILURE_ACTION_REBOOT] = "reboot", - [FAILURE_ACTION_REBOOT_FORCE] = "reboot-force", - [FAILURE_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate", - [FAILURE_ACTION_POWEROFF] = "poweroff", - [FAILURE_ACTION_POWEROFF_FORCE] = "poweroff-force", - [FAILURE_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate" -}; -DEFINE_STRING_TABLE_LOOKUP(failure_action, FailureAction); diff --git a/src/core/failure-action.h b/src/core/failure-action.h deleted file mode 100644 index 1adac4ad5c..0000000000 --- a/src/core/failure-action.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - Copyright 2012 Michael Olbrich - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ - -typedef enum FailureAction { - FAILURE_ACTION_NONE, - FAILURE_ACTION_REBOOT, - FAILURE_ACTION_REBOOT_FORCE, - FAILURE_ACTION_REBOOT_IMMEDIATE, - FAILURE_ACTION_POWEROFF, - FAILURE_ACTION_POWEROFF_FORCE, - FAILURE_ACTION_POWEROFF_IMMEDIATE, - _FAILURE_ACTION_MAX, - _FAILURE_ACTION_INVALID = -1 -} FailureAction; - -#include "macro.h" -#include "manager.h" - -int failure_action(Manager *m, FailureAction action, const char *reboot_arg); - -const char* failure_action_to_string(FailureAction i) _const_; -FailureAction failure_action_from_string(const char *s) _pure_; diff --git a/src/core/job.c b/src/core/job.c index 7faf2ef686..3ecc8a1a73 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -927,7 +927,7 @@ static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *user u = j->unit; job_finish_and_invalidate(j, JOB_TIMEOUT, true, false); - failure_action(u->manager, u->job_timeout_action, u->job_timeout_reboot_arg); + emergency_action(u->manager, u->job_timeout_action, u->job_timeout_reboot_arg, "job timed out"); return 0; } diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 08c88b6b53..af2f9d960b 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -188,13 +188,13 @@ Unit.OnFailureIsolate, config_parse_job_mode_isolate, 0, Unit.IgnoreOnIsolate, config_parse_bool, 0, offsetof(Unit, ignore_on_isolate) Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0 Unit.JobTimeoutSec, config_parse_sec_fix_0, 0, offsetof(Unit, job_timeout) -Unit.JobTimeoutAction, config_parse_failure_action, 0, offsetof(Unit, job_timeout_action) +Unit.JobTimeoutAction, config_parse_emergency_action, 0, offsetof(Unit, job_timeout_action) Unit.JobTimeoutRebootArgument, config_parse_string, 0, offsetof(Unit, job_timeout_reboot_arg) Unit.StartLimitIntervalSec, config_parse_sec, 0, offsetof(Unit, start_limit.interval) m4_dnl The following is a legacy alias name for compatibility Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval) Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst) -Unit.StartLimitAction, config_parse_failure_action, 0, offsetof(Unit, start_limit_action) +Unit.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action) Unit.RebootArgument, config_parse_string, 0, offsetof(Unit, reboot_arg) Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions) Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions) @@ -251,9 +251,9 @@ Service.WatchdogSec, config_parse_sec, 0, m4_dnl The following three only exist for compatibility, they moved into Unit, see above Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval) Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst) -Service.StartLimitAction, config_parse_failure_action, 0, offsetof(Unit, start_limit_action) +Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action) Service.RebootArgument, config_parse_string, 0, offsetof(Unit, reboot_arg) -Service.FailureAction, config_parse_failure_action, 0, offsetof(Service, failure_action) +Service.FailureAction, config_parse_emergency_action, 0, offsetof(Service, emergency_action) Service.Type, config_parse_service_type, 0, offsetof(Service, type) Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart) Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index a69f60097d..6f68e23340 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2523,7 +2523,7 @@ int config_parse_unit_condition_null( } DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier"); -DEFINE_CONFIG_PARSE_ENUM(config_parse_failure_action, failure_action, FailureAction, "Failed to parse failure action specifier"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_emergency_action, emergency_action, EmergencyAction, "Failed to parse failure action specifier"); int config_parse_unit_requires_mounts_for( const char *unit, @@ -4315,7 +4315,7 @@ void unit_dump_config_items(FILE *f) { { config_parse_unit_slice, "SLICE" }, { config_parse_documentation, "URL" }, { config_parse_service_timeout, "SECONDS" }, - { config_parse_failure_action, "ACTION" }, + { config_parse_emergency_action, "ACTION" }, { config_parse_set_status, "STATUS" }, { config_parse_service_sockets, "SOCKETS" }, { config_parse_environ, "ENVIRON" }, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 6d1fe55bcd..c05f205c37 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -75,7 +75,7 @@ int config_parse_unit_condition_string(const char *unit, const char *filename, u int config_parse_unit_condition_null(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_kill_mode(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_notify_access(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_failure_action(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_emergency_action(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_unit_requires_mounts_for(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_syscall_filter(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_syscall_archs(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); diff --git a/src/core/service.c b/src/core/service.c index f9127d7509..5b92c901e3 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1455,7 +1455,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) if (s->result != SERVICE_SUCCESS) { log_unit_warning(UNIT(s), "Failed with result '%s'.", service_result_to_string(s->result)); - failure_action(UNIT(s)->manager, s->failure_action, UNIT(s)->reboot_arg); + emergency_action(UNIT(s)->manager, s->emergency_action, UNIT(s)->reboot_arg, "service failed"); } if (allow_restart && service_shall_restart(s)) { diff --git a/src/core/service.h b/src/core/service.h index 888007cc0b..2869144fcb 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -178,7 +178,7 @@ struct Service { char *status_text; int status_errno; - FailureAction failure_action; + EmergencyAction emergency_action; UnitRef accept_socket; diff --git a/src/core/unit.c b/src/core/unit.c index 2fa397bd41..cabb1050a8 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -982,8 +982,8 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { if (u->job_timeout != USEC_INFINITY) fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0)); - if (u->job_timeout_action != FAILURE_ACTION_NONE) - fprintf(f, "%s\tJob Timeout Action: %s\n", prefix, failure_action_to_string(u->job_timeout_action)); + if (u->job_timeout_action != EMERGENCY_ACTION_NONE) + fprintf(f, "%s\tJob Timeout Action: %s\n", prefix, emergency_action_to_string(u->job_timeout_action)); if (u->job_timeout_reboot_arg) fprintf(f, "%s\tJob Timeout Reboot Argument: %s\n", prefix, u->job_timeout_reboot_arg); @@ -1490,7 +1490,7 @@ int unit_start_limit_test(Unit *u) { log_unit_warning(u, "Start request repeated too quickly."); u->start_limit_hit = true; - return failure_action(u->manager, u->start_limit_action, u->reboot_arg); + return emergency_action(u->manager, u->start_limit_action, u->reboot_arg, "unit failed"); } /* Errors: diff --git a/src/core/unit.h b/src/core/unit.h index a8dd3e602c..adcdee6db6 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -29,7 +29,7 @@ typedef struct UnitRef UnitRef; typedef struct UnitStatusMessageFormats UnitStatusMessageFormats; #include "condition.h" -#include "failure-action.h" +#include "emergency-action.h" #include "install.h" #include "list.h" #include "unit-name.h" @@ -114,7 +114,7 @@ struct Unit { /* Job timeout and action to take */ usec_t job_timeout; - FailureAction job_timeout_action; + EmergencyAction job_timeout_action; char *job_timeout_reboot_arg; /* References to this */ @@ -178,7 +178,7 @@ struct Unit { /* Put a ratelimit on unit starting */ RateLimit start_limit; - FailureAction start_limit_action; + EmergencyAction start_limit_action; char *reboot_arg; /* Make sure we never enter endless loops with the check unneeded logic, or the BindsTo= logic */ diff --git a/src/test/test-tables.c b/src/test/test-tables.c index 0be74921fc..8d4622694e 100644 --- a/src/test/test-tables.c +++ b/src/test/test-tables.c @@ -63,7 +63,7 @@ int main(int argc, char **argv) { test_table(device_state, DEVICE_STATE); test_table(exec_input, EXEC_INPUT); test_table(exec_output, EXEC_OUTPUT); - test_table(failure_action, FAILURE_ACTION); + test_table(emergency_action, EMERGENCY_ACTION); test_table(job_mode, JOB_MODE); test_table(job_result, JOB_RESULT); test_table(job_state, JOB_STATE); -- cgit v1.2.3-54-g00ecf From ae8c7939df962cbf660b2b9517fe46be272f58b9 Mon Sep 17 00:00:00 2001 From: Lukas Nykryn Date: Tue, 18 Oct 2016 12:16:32 +0200 Subject: core: use emergency_action for ctr+alt+del burst Fixes #4306 --- man/systemd-system.conf.xml | 5 +++-- src/core/main.c | 7 +++---- src/core/manager.c | 33 ++++----------------------------- src/core/manager.h | 13 +------------ 4 files changed, 11 insertions(+), 47 deletions(-) diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index 1d995f143e..80cad7f09c 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -110,8 +110,9 @@ Defines what action will be performed if user presses Ctrl-Alt-Delete more than 7 times in 2s. - Can be set to reboot-force, poweroff-force - or disabled with ignore. Defaults to + Can be set to reboot-force, poweroff-force, + reboot-immediate, poweroff-immediate + or disabled with none. Defaults to reboot-force. diff --git a/src/core/main.c b/src/core/main.c index cf3c640a73..b635a633a7 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -89,6 +89,7 @@ #include "user-util.h" #include "virt.h" #include "watchdog.h" +#include "emergency-action.h" static enum { ACTION_RUN, @@ -131,7 +132,7 @@ static bool arg_default_memory_accounting = false; static bool arg_default_tasks_accounting = true; static uint64_t arg_default_tasks_max = UINT64_MAX; static sd_id128_t arg_machine_id = {}; -static CADBurstAction arg_cad_burst_action = CAD_BURST_ACTION_REBOOT; +static EmergencyAction arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE; noreturn static void freeze_or_reboot(void) { @@ -649,8 +650,6 @@ static int config_parse_join_controllers(const char *unit, return 0; } -static DEFINE_CONFIG_PARSE_ENUM(config_parse_cad_burst_action, cad_burst_action, CADBurstAction, "Failed to parse service restart specifier"); - static int parse_config_file(void) { const ConfigTableItem items[] = { @@ -705,7 +704,7 @@ static int parse_config_file(void) { { "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting }, { "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting }, { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max }, - { "Manager", "CtrlAltDelBurstAction", config_parse_cad_burst_action, 0, &arg_cad_burst_action}, + { "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, 0, &arg_cad_burst_action }, {} }; diff --git a/src/core/manager.c b/src/core/manager.c index 65f163de31..ffccfdcd5e 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1911,28 +1911,11 @@ static void manager_handle_ctrl_alt_del(Manager *m) { * 7 times within 2s, we reboot/shutdown immediately, * unless it was disabled in system.conf */ - if (ratelimit_test(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == CAD_BURST_ACTION_IGNORE) + if (ratelimit_test(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE) manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY); - else { - switch (m->cad_burst_action) { - - case CAD_BURST_ACTION_REBOOT: - m->exit_code = MANAGER_REBOOT; - break; - - case CAD_BURST_ACTION_POWEROFF: - m->exit_code = MANAGER_POWEROFF; - break; - - default: - assert_not_reached("Unknown action."); - } - - log_notice("Ctrl-Alt-Del was pressed more than 7 times within 2s, performing immediate %s.", - cad_burst_action_to_string(m->cad_burst_action)); - status_printf(NULL, true, false, "Ctrl-Alt-Del was pressed more than 7 times within 2s, performing immediate %s.", - cad_burst_action_to_string(m->cad_burst_action)); - } + else + emergency_action(m, m->cad_burst_action, NULL, + "Ctrl-Alt-Del was pressed more than 7 times within 2s"); } static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { @@ -3590,11 +3573,3 @@ static const char *const manager_state_table[_MANAGER_STATE_MAX] = { }; DEFINE_STRING_TABLE_LOOKUP(manager_state, ManagerState); - -static const char *const cad_burst_action_table[_CAD_BURST_ACTION_MAX] = { - [CAD_BURST_ACTION_IGNORE] = "ignore", - [CAD_BURST_ACTION_REBOOT] = "reboot-force", - [CAD_BURST_ACTION_POWEROFF] = "poweroff-force", -}; - -DEFINE_STRING_TABLE_LOOKUP(cad_burst_action, CADBurstAction); diff --git a/src/core/manager.h b/src/core/manager.h index 29fe14e10b..35172fdba9 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -62,14 +62,6 @@ typedef enum ManagerExitCode { _MANAGER_EXIT_CODE_INVALID = -1 } ManagerExitCode; -typedef enum CADBurstAction { - CAD_BURST_ACTION_IGNORE, - CAD_BURST_ACTION_REBOOT, - CAD_BURST_ACTION_POWEROFF, - _CAD_BURST_ACTION_MAX, - _CAD_BURST_ACTION_INVALID = -1 -} CADBurstAction; - typedef enum StatusType { STATUS_TYPE_EPHEMERAL, STATUS_TYPE_NORMAL, @@ -315,7 +307,7 @@ struct Manager { /* When the user hits C-A-D more than 7 times per 2s, do something immediately... */ RateLimit ctrl_alt_del_ratelimit; - CADBurstAction cad_burst_action; + EmergencyAction cad_burst_action; const char *unit_log_field; const char *unit_log_format_string; @@ -411,6 +403,3 @@ void manager_deserialize_gid_refs_one(Manager *m, const char *value); const char *manager_state_to_string(ManagerState m) _const_; ManagerState manager_state_from_string(const char *s) _pure_; - -const char *cad_burst_action_to_string(CADBurstAction a) _const_; -CADBurstAction cad_burst_action_from_string(const char *s) _pure_; -- cgit v1.2.3-54-g00ecf From 6b169c13ecf645a0a341f49b9dc2afb312a74206 Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Fri, 21 Oct 2016 16:11:39 +0200 Subject: vconsole: skip unnecessary udev call for dummy device In particular, the font copying has no chance of succeeding as the required functionality is not implemented, see: drivers/video/console/dummycon.c --- src/vconsole/90-vconsole.rules.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vconsole/90-vconsole.rules.in b/src/vconsole/90-vconsole.rules.in index 35b9ad5151..84b4d575bd 100644 --- a/src/vconsole/90-vconsole.rules.in +++ b/src/vconsole/90-vconsole.rules.in @@ -7,4 +7,4 @@ # Each vtcon keeps its own state of fonts. # -ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon*", RUN+="@rootlibexecdir@/systemd-vconsole-setup" +ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon*", ATTR{name}!="*dummy device", RUN+="@rootlibexecdir@/systemd-vconsole-setup" -- cgit v1.2.3-54-g00ecf From e49e2c25f3cdb315b931cfc29557b6de7bf9fb99 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sat, 22 Oct 2016 00:43:36 +0200 Subject: NEWS: option is ProtectKernelTunables not ProtectedKernelTunables (#4451) --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 6378e596f6..24d6ae1bd2 100644 --- a/NEWS +++ b/NEWS @@ -12,7 +12,7 @@ CHANGES WITH 232 in spe whole file system tree with the exception of /dev, /proc, and /sys, to be remounted read-only for a service. - * The new ProtectedKernelTunables= option can be used to disable + * The new ProtectKernelTunables= option can be used to disable modification of configuration files in /sys and /proc by a service. Various directories and files are remounted read-only, so access is restricted even if the file permissions would allow it. -- cgit v1.2.3-54-g00ecf From 863a5610c7336829d76252375dbe361fd6813a7c Mon Sep 17 00:00:00 2001 From: Umut Tezduyar Lindskog Date: Sat, 22 Oct 2016 01:40:55 +0200 Subject: journald: systemd.journald.max_level_* kernel command line options (#4427) The log forward levels can be configured through kernel command line. --- man/journald.conf.xml | 9 ++++++++- src/journal/journald-server.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/man/journald.conf.xml b/man/journald.conf.xml index a9562c121a..df2e2246a1 100644 --- a/man/journald.conf.xml +++ b/man/journald.conf.xml @@ -348,7 +348,14 @@ notice for MaxLevelKMsg=, info for MaxLevelConsole=, and emerg for - MaxLevelWall=. + MaxLevelWall=. These settings may be + overridden at boot time with the kernel command line options + systemd.journald.max_level_store=, + systemd.journald.max_level_syslog=, + systemd.journald.max_level_kmsg=, + systemd.journald.max_level_console=, + systemd.journald.max_level_wall=. + diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 5ea65e2deb..92c623d9e9 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -71,6 +71,7 @@ #include "string-table.h" #include "string-util.h" #include "user-util.h" +#include "syslog-util.h" #define USER_JOURNALS_MAX 1024 @@ -1573,6 +1574,36 @@ static int server_parse_proc_cmdline(Server *s) { log_warning("Failed to parse forward to wall switch %s. Ignoring.", word + 33); else s->forward_to_wall = r; + } else if (startswith(word, "systemd.journald.max_level_console=")) { + r = log_level_from_string(word + 35); + if (r < 0) + log_warning("Failed to parse max level console value %s. Ignoring.", word + 35); + else + s->max_level_console = r; + } else if (startswith(word, "systemd.journald.max_level_store=")) { + r = log_level_from_string(word + 33); + if (r < 0) + log_warning("Failed to parse max level store value %s. Ignoring.", word + 33); + else + s->max_level_store = r; + } else if (startswith(word, "systemd.journald.max_level_syslog=")) { + r = log_level_from_string(word + 34); + if (r < 0) + log_warning("Failed to parse max level syslog value %s. Ignoring.", word + 34); + else + s->max_level_syslog = r; + } else if (startswith(word, "systemd.journald.max_level_kmsg=")) { + r = log_level_from_string(word + 32); + if (r < 0) + log_warning("Failed to parse max level kmsg value %s. Ignoring.", word + 32); + else + s->max_level_kmsg = r; + } else if (startswith(word, "systemd.journald.max_level_wall=")) { + r = log_level_from_string(word + 32); + if (r < 0) + log_warning("Failed to parse max level wall value %s. Ignoring.", word + 32); + else + s->max_level_wall = r; } else if (startswith(word, "systemd.journald")) log_warning("Invalid systemd.journald parameter. Ignoring."); } -- cgit v1.2.3-54-g00ecf From ce830873f0a76b635305926a947a34ddc294355a Mon Sep 17 00:00:00 2001 From: Jakub Wilk Date: Sat, 22 Oct 2016 13:18:17 +0200 Subject: NEWS: fix typos --- NEWS | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index 24d6ae1bd2..87cc4f48c0 100644 --- a/NEWS +++ b/NEWS @@ -360,7 +360,7 @@ CHANGES WITH 231: file. It can be used in lieu of %systemd_requires in packages which don't use any systemd functionality and are intended to be installed in minimal containers without systemd present. This macro provides - ordering dependecies to ensure that if the package is installed in + ordering dependencies to ensure that if the package is installed in the same rpm transaction as systemd, systemd will be installed before the scriptlets for the package are executed, allowing unit presets to be handled. @@ -395,7 +395,7 @@ CHANGES WITH 231: "mkosi" is invoked in the build tree a new raw OS image is generated incorporating the systemd sources currently being worked on and a clean, fresh distribution installation. The generated OS image may be - booted up with "systemd-nspawn -b -i", qemu-kvm or on any physcial + booted up with "systemd-nspawn -b -i", qemu-kvm or on any physical UEFI PC. This functionality is particularly useful to easily test local changes made to systemd in a pristine, defined environment. See HACKING for details. @@ -1058,7 +1058,7 @@ CHANGES WITH 228: --user instance of systemd these specifiers where correctly resolved, but hardly made any sense, since the user instance lacks privileges to do user switches anyway, and User= is - hence useless. Morever, even in the --user instance of + hence useless. Moreover, even in the --user instance of systemd behaviour was awkward as it would only take settings from User= assignment placed before the specifier into account. In order to unify and simplify the logic around @@ -1194,7 +1194,7 @@ CHANGES WITH 227: * The RuntimeDirectory= setting now understands unit specifiers like %i or %f. - * A new (still internal) libary API sd-ipv4acd has been added, + * A new (still internal) library API sd-ipv4acd has been added, that implements address conflict detection for IPv4. It's based on code from sd-ipv4ll, and will be useful for detecting DHCP address conflicts. @@ -1763,7 +1763,7 @@ CHANGES WITH 220: * systemd-nspawn gained a new --property= setting to set unit properties for the container scope. This is useful for - setting resource parameters (e.g "CPUShares=500") on + setting resource parameters (e.g. "CPUShares=500") on containers started from the command line. * systemd-nspawn gained a new --private-users= switch to make @@ -3109,7 +3109,7 @@ CHANGES WITH 214: time, the extended attribute calls have moved to glibc, and libattr is thus unnecessary. - * Virtualization detection works without priviliges now. This + * Virtualization detection works without privileges now. This means the systemd-detect-virt binary no longer requires CAP_SYS_PTRACE file capabilities, and our daemons can run with fewer privileges. @@ -3833,7 +3833,7 @@ CHANGES WITH 209: /usr/lib/net/links/99-default.link. Old 80-net-name-slot.rules udev configuration file has been removed, so local configuration overriding this file should - be adapated to override 99-default.link instead. + be adapted to override 99-default.link instead. * When the User= switch is used in a unit file, also initialize $SHELL= based on the user database entry. @@ -4476,7 +4476,7 @@ CHANGES WITH 206: * logind's device ACLs may now be applied to these "dead" devices nodes too, thus finally allowing managed access to - devices such as /dev/snd/sequencer whithout loading the + devices such as /dev/snd/sequencer without loading the backing module right-away. * A new RPM macro has been added that may be used to apply @@ -4967,7 +4967,7 @@ CHANGES WITH 199: processes executed in parallel based on the number of available CPUs instead of the amount of available RAM. This is supposed to provide a more reliable default and limit a too aggressive - paralellism for setups with 1000s of devices connected. + parallelism for setups with 1000s of devices connected. Contributions from: Auke Kok, Colin Walters, Cristian Rodríguez, Daniel Buch, Dave Reisner, Frederic Crozat, Hannes @@ -5305,7 +5305,7 @@ CHANGES WITH 197: presenting log data. * systemctl will no longer show control group information for - a unit if a the control group is empty anyway. + a unit if the control group is empty anyway. * logind can now automatically suspend/hibernate/shutdown the system on idle. @@ -6096,7 +6096,7 @@ CHANGES WITH 186: * The SysV search path is no longer exported on the D-Bus Manager object. - * The Names= option is been removed from unit file parsing. + * The Names= option has been removed from unit file parsing. * There's a new man page bootup(7) detailing the boot process. @@ -6241,7 +6241,7 @@ CHANGES WITH 183: about this in more detail. * var-run.mount and var-lock.mount are no longer provided - (which prevously bind mounted these directories to their new + (which previously bind mounted these directories to their new places). Distributions which have not converted these directories to symlinks should consider stealing these files from git history and add them downstream. @@ -6382,7 +6382,7 @@ CHANGES WITH 44: * Many bugfixes for the journal, including endianness fixes and ensuring that disk space enforcement works - * sd-login.h is C++ comptaible again + * sd-login.h is C++ compatible again * Extend the /etc/os-release format on request of the Debian folks @@ -6610,7 +6610,7 @@ CHANGES WITH 38: * New man pages for all APIs from libsystemd-login. - * The build tree got reorganized and a the build system is a + * The build tree got reorganized and the build system is a lot more modular allowing embedded setups to specifically select the components of systemd they are interested in. -- cgit v1.2.3-54-g00ecf From b5331acc961c1461b1e811a346308f580c3c0771 Mon Sep 17 00:00:00 2001 From: Thomas Hindoe Paaboel Andersen Date: Sat, 22 Oct 2016 14:01:20 +0200 Subject: journal: remove unused variable --- src/journal/journald-server.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 92c623d9e9..44962bc5d6 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -131,8 +131,6 @@ static void cache_space_invalidate(JournalStorageSpace *space) { } static int cache_space_refresh(Server *s, JournalStorage *storage) { - - _cleanup_closedir_ DIR *d = NULL; JournalStorageSpace *space; JournalMetrics *metrics; uint64_t vfs_used, vfs_avail, avail; -- cgit v1.2.3-54-g00ecf From a0282d9fa365186fe1f428bacf8f52d7b10115e1 Mon Sep 17 00:00:00 2001 From: Dongsu Park Date: Sat, 22 Oct 2016 17:29:33 +0200 Subject: catalog: fix typo and make a clear sentence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix typo: s/ournald.conf/journald.conf/ Change also "시스템의 다음 위치에" to "시스템을 별도 위치에" to make a clear sentence. --- catalog/systemd.ko.catalog.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/catalog/systemd.ko.catalog.in b/catalog/systemd.ko.catalog.in index 8a053254ee..4786ee2fac 100644 --- a/catalog/systemd.ko.catalog.in +++ b/catalog/systemd.ko.catalog.in @@ -56,7 +56,7 @@ Documentation: man:journald.conf(5) 메시지 거절 제어 제한 값은 /etc/systemd/journald.conf 의 RateLimitIntervalSec= 변수와 RateLimitBurst= 변수로 설정합니다. -자세한 내용은 ournald.conf(5)를 살펴보십시오. +자세한 내용은 journald.conf(5)를 살펴보십시오. -- e9bf28e6e834481bb6f48f548ad13606 Subject: 저널 메시지 놓침 @@ -246,7 +246,7 @@ Support: %SUPPORT_URL% 두번째 필드 또는 systemd 유닛 파일의 Where= 필드) 비어있지 않습니다. 마운트 과정에 방해가 되진 않지만 이전에 이 디렉터리에 존재하는 파일에 접근할 수 없게 됩니다. 중복으로 마운트한 파일을 보려면, 근본 파일 -시스템의 다음 위치에 직접 마운트하십시오. +시스템을 별도 위치에 직접 마운트하십시오. -- 24d8d4452573402496068381a6312df2 Subject: 가상 머신 또는 컨테이너 시작 -- cgit v1.2.3-54-g00ecf From 4cfa6da41f351564d09ed69d9a442cb827a2f859 Mon Sep 17 00:00:00 2001 From: Dongsu Park Date: Sat, 22 Oct 2016 17:29:38 +0200 Subject: catalog: add more Korean translations Add more Korean translations of journal and DNSSEC log messages. --- catalog/systemd.ko.catalog.in | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/catalog/systemd.ko.catalog.in b/catalog/systemd.ko.catalog.in index 4786ee2fac..0249cba747 100644 --- a/catalog/systemd.ko.catalog.in +++ b/catalog/systemd.ko.catalog.in @@ -25,6 +25,7 @@ # # Translator : # Seong-ho Cho , 2015. +# Dongsu Park , 2016. -- f77379a8490b408bbe5f6940505a777b Subject: 저널 시작 @@ -42,6 +43,24 @@ Support: %SUPPORT_URL% 시스템 저널 프로세스를 껐고 현재 활성화 중인 저널 파일을 모두 닫았습니다. +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: 저널이 디스크 공간을 점유중 +Defined-By: systemd +Support: %SUPPORT_URL% + +저널 @JOURNAL_NAME@ (@JOURNAL_PATH@)이 현재 @CURRENT_USE_PRETTY@ +만큼의 용량을 사용하고 있습니다. 최대 허용 용량은 +@MAX_USE_PRETTY@입니다. 최소한 @DISK_KEEP_FREE_PRETTY@의 빈공간을 +남겨둡니다. (현재 디스크 전체 용량은 @DISK_AVAILABLE_PRETTY@) +따라서 실제 사용 최대 한도는 @LIMIT_PRETTY@으로 설정되며, +@AVAILABLE_PRETTY@ 만큼의 용량이 계속 비어있습니다. + +저널이 차지하는 디스크 공간을 제어하기 위해서는 +/etc/systemd/journald.conf 의 SystemMaxUse=, SystemKeepFree=, +SystemMaxFileSize=, RuntimeMaxUse=, RuntimeKeepFree=, +RuntimeMaxFileSize= 변수를 설정합니다. 자세한 내용은 +journald.conf(5)을 살펴보십시오. + -- a596d6fe7bfa4994828e72309e95d61e Subject: 서비스의 메시지를 거절함 Defined-By: systemd @@ -262,3 +281,41 @@ Defined-By: systemd Support: %SUPPORT_URL% @LEADER@ 프로세스 ID로 동작하는 @NAME@ 가상 머신을 껐습니다. + +-- 36db2dfa5a9045e1bd4af5f93e1cf057 +Subject: 서버 미지원으로 인하여 DNSSEC 모드 종료 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) resolved.conf(5) + +해당 DNS 서버가 DNSSEC을 지원하지 않는다는 것을 리졸버 서비스 +(systemd-resolved.service)가 인식했습니다. 따라서 DNSSEC 검증 기능도 +꺼집니다. + +이 이벤트는 resolved.conf 파일에 DNSSEC=allow-downgrade가 설정되었고, 해당 +DNS 서버가 DNSSEC과 비호환일 경우에만 발생합니다. 이 모드를 켤 경우에는 +DNSSEC 다운그레이드 공격을 허용할수 있다는 점에 주의하세요. 이는 공격자 +역시 다운그레이드가 발생한 통신 채널에 DNS 응답 메시지를 끼워넣는 방식으로 +DNSSEC 검증 기능을 꺼버릴수 있기 때문입니다. + +이 이벤트가 의미하는 것은, DNS 서버가 실제로 DNSSEC과 비호환이거나, 또는 +공격자가 위와 같은 다운그레이드 공격을 수행하는데 성공했다는 뜻입니다. + +-- 1675d7f172174098b1108bf8c7dc8f5d +Subject: DNSSEC 검증 실패 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +DNS 요청 또는 리소스 레코드가 DNSSEC 검증에 실패했습니다. 이것은 보통 +해당 통신 채널이 조작되었다는 뜻입니다. + +-- 4d4408cfd0d144859184d1e65d7c8a65 +Subject: DNSSEC 신뢰성 시작점 취소 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +DNSSEC 신뢰성 시작점이 취소되었습니다. 새로운 신뢰성 시작점이 설정되거나, +또는 업데이트된 DNSSEC 신뢰성 시작점을 제공하기 위해서 운영체제를 업데이트 +해야 합니다. -- cgit v1.2.3-54-g00ecf From 96287a491676763849ab73bda6c4486d7f775323 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 22 Oct 2016 14:24:52 -0400 Subject: tree-wide: allow state to be passed through to parse_proc_cmdline_item No functional change. --- src/basic/log.c | 4 ++-- src/basic/proc-cmdline.c | 4 ++-- src/basic/proc-cmdline.h | 2 +- src/core/main.c | 4 ++-- src/cryptsetup/cryptsetup-generator.c | 4 ++-- src/debug-generator/debug-generator.c | 4 ++-- src/fsck/fsck.c | 4 ++-- src/fstab-generator/fstab-generator.c | 4 ++-- src/gpt-auto-generator/gpt-auto-generator.c | 4 ++-- src/hibernate-resume/hibernate-resume-generator.c | 4 ++-- src/modules-load/modules-load.c | 4 ++-- src/quotacheck/quotacheck.c | 4 ++-- src/test/test-proc-cmdline.c | 7 +++++-- src/udev/udevd.c | 4 ++-- 14 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/basic/log.c b/src/basic/log.c index bd6c96c4f8..40f342ca72 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -967,7 +967,7 @@ int log_set_max_level_from_string(const char *e) { return 0; } -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { /* * The systemd.log_xyz= settings are parsed by all tools, and @@ -1012,7 +1012,7 @@ void log_parse_environment(void) { /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is user stuff. */ - (void) parse_proc_cmdline(parse_proc_cmdline_item); + (void) parse_proc_cmdline(parse_proc_cmdline_item, NULL); e = secure_getenv("SYSTEMD_LOG_TARGET"); if (e && log_set_target_from_string(e) < 0) diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c index 0430beadaa..951db34d1a 100644 --- a/src/basic/proc-cmdline.c +++ b/src/basic/proc-cmdline.c @@ -42,7 +42,7 @@ int proc_cmdline(char **ret) { return read_one_line_file("/proc/cmdline", ret); } -int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) { +int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, void *data), void *data) { _cleanup_free_ char *line = NULL; const char *p; int r; @@ -73,7 +73,7 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) { if (value) *(value++) = 0; - r = parse_item(word, value); + r = parse_item(word, value, data); if (r < 0) return r; } diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h index 452642a2f5..a8832d8419 100644 --- a/src/basic/proc-cmdline.h +++ b/src/basic/proc-cmdline.h @@ -20,7 +20,7 @@ ***/ int proc_cmdline(char **ret); -int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value)); +int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value, void *data), void *data); int get_proc_cmdline_key(const char *parameter, char **value); int shall_restore_state(void); diff --git a/src/core/main.c b/src/core/main.c index cf3c640a73..bf9bba28d6 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -307,7 +307,7 @@ static int set_machine_id(const char *m) { return 0; } -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; @@ -1570,7 +1570,7 @@ int main(int argc, char *argv[]) { } if (arg_system) { - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); } diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index de0a3b6f9c..7193d93070 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -277,7 +277,7 @@ static crypto_device *get_crypto_device(const char *uuid) { return d; } -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; crypto_device *d; _cleanup_free_ char *uuid = NULL, *uuid_value = NULL; @@ -478,7 +478,7 @@ int main(int argc, char *argv[]) { if (!arg_disks) goto cleanup; - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); if (r < 0) { log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); r = EXIT_FAILURE; diff --git a/src/debug-generator/debug-generator.c b/src/debug-generator/debug-generator.c index 7e80af78e7..0b0de1b461 100644 --- a/src/debug-generator/debug-generator.c +++ b/src/debug-generator/debug-generator.c @@ -33,7 +33,7 @@ static char **arg_mask = NULL; static char **arg_wants = NULL; static bool arg_debug_shell = false; -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; assert(key); @@ -178,7 +178,7 @@ int main(int argc, char *argv[]) { goto finish; } - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index d32e1d923e..957e0ccef8 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -94,7 +94,7 @@ static void start_target(const char *target, const char *mode) { log_error("Failed to start unit: %s", bus_error_message(&error, r)); } -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; assert(key); @@ -293,7 +293,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 33af553d0d..b608eff630 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -590,7 +590,7 @@ static int add_sysroot_usr_mount(void) { "/proc/cmdline"); } -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; /* root=, usr=, usrfstype= and roofstype= may occur more than once, the last @@ -674,7 +674,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index 6cc1aad705..a25b3413ae 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -907,7 +907,7 @@ fallback: return 1; } -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; assert(key); @@ -1018,7 +1018,7 @@ int main(int argc, char *argv[]) { return EXIT_SUCCESS; } - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/hibernate-resume/hibernate-resume-generator.c b/src/hibernate-resume/hibernate-resume-generator.c index d7ee80d58f..8be461aafa 100644 --- a/src/hibernate-resume/hibernate-resume-generator.c +++ b/src/hibernate-resume/hibernate-resume-generator.c @@ -33,7 +33,7 @@ static const char *arg_dest = "/tmp"; static char *arg_resume_dev = NULL; -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { if (streq(key, "resume") && value) { free(arg_resume_dev); @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) { if (!in_initrd()) return EXIT_SUCCESS; - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index f75015d8c3..bd07bad446 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -59,7 +59,7 @@ static int add_modules(const char *p) { return 0; } -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; if (STR_IN_SET(key, "modules-load", "rd.modules-load") && value) { @@ -226,7 +226,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c index 6d8c05f046..a87b0866cd 100644 --- a/src/quotacheck/quotacheck.c +++ b/src/quotacheck/quotacheck.c @@ -32,7 +32,7 @@ static bool arg_skip = false; static bool arg_force = false; -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { if (streq(key, "quotacheck.mode") && value) { @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c index 80ad5ed98b..e4207935c4 100644 --- a/src/test/test-proc-cmdline.c +++ b/src/test/test-proc-cmdline.c @@ -25,15 +25,18 @@ #include "string-util.h" #include "util.h" -static int parse_item(const char *key, const char *value) { +static int obj; + +static int parse_item(const char *key, const char *value, void *data) { assert_se(key); + assert_se(data == &obj); log_info("kernel cmdline option <%s> = <%s>", key, strna(value)); return 0; } static void test_parse_proc_cmdline(void) { - assert_se(parse_proc_cmdline(parse_item) >= 0); + assert_se(parse_proc_cmdline(parse_item, &obj) >= 0); } static void test_runlevel_to_target(void) { diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 535d317c27..601ab69f1b 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -1362,7 +1362,7 @@ static int listen_fds(int *rctrl, int *rnetlink) { * udev.exec-delay= delay execution of every executed program * udev.event-timeout= seconds to wait before terminating an event */ -static int parse_proc_cmdline_item(const char *key, const char *value) { +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { const char *full_key = key; int r; @@ -1665,7 +1665,7 @@ int main(int argc, char *argv[]) { if (r <= 0) goto exit; - r = parse_proc_cmdline(parse_proc_cmdline_item); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); if (r < 0) log_warning_errno(r, "failed to parse kernel command line, ignoring: %m"); -- cgit v1.2.3-54-g00ecf From 5707ecf300a96376449d2d7670a61e64bb53a236 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 22 Oct 2016 14:25:30 -0400 Subject: journald: convert journald to use parse_proc_cmdline This makes journald use the common option parsing functionality. One behavioural change is implemented: "systemd.journald.forward_to_syslog" is now equivalent to "systemd.journald.forward_to_syslog=1". I think it's nicer to use this way. --- man/journald.conf.xml | 31 +++++----- src/journal/journald-server.c | 135 ++++++++++++++++++------------------------ 2 files changed, 74 insertions(+), 92 deletions(-) diff --git a/man/journald.conf.xml b/man/journald.conf.xml index df2e2246a1..9daa964803 100644 --- a/man/journald.conf.xml +++ b/man/journald.conf.xml @@ -301,22 +301,21 @@ ForwardToConsole= ForwardToWall= - Control whether log messages received by the - journal daemon shall be forwarded to a traditional syslog - daemon, to the kernel log buffer (kmsg), to the system - console, or sent as wall messages to all logged-in users. - These options take boolean arguments. If forwarding to syslog - is enabled but nothing reads messages from the socket, - forwarding to syslog has no effect. By default, only - forwarding to wall is enabled. These settings may be - overridden at boot time with the kernel command line options - systemd.journald.forward_to_syslog=, - systemd.journald.forward_to_kmsg=, - systemd.journald.forward_to_console=, and - systemd.journald.forward_to_wall=. When - forwarding to the console, the TTY to log to can be changed - with TTYPath=, described - below. + Control whether log messages received by the journal daemon shall + be forwarded to a traditional syslog daemon, to the kernel log buffer (kmsg), to + the system console, or sent as wall messages to all logged-in users. These + options take boolean arguments. If forwarding to syslog is enabled but nothing + reads messages from the socket, forwarding to syslog has no effect. By default, + only forwarding to wall is enabled. These settings may be overridden at boot time + with the kernel command line options + systemd.journald.forward_to_syslog, + systemd.journald.forward_to_kmsg, + systemd.journald.forward_to_console, and + systemd.journald.forward_to_wall. If the option name is + specified without = and the following argument, true is + assumed. Otherwise, the argument is parsed as a boolean. When forwarding to the + console, the TTY to log to can be changed with TTYPath=, + described below. diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 92c623d9e9..e7dcbba04f 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -1528,85 +1528,68 @@ static int setup_signals(Server *s) { return 0; } -static int server_parse_proc_cmdline(Server *s) { - _cleanup_free_ char *line = NULL; - const char *p; +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + Server *s = data; int r; - r = proc_cmdline(&line); - if (r < 0) { - log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m"); - return 0; - } - - p = line; - for (;;) { - _cleanup_free_ char *word = NULL; + assert(s); - r = extract_first_word(&p, &word, NULL, 0); + if (streq(key, "systemd.journald.forward_to_syslog")) { + r = value ? parse_boolean(value) : true; if (r < 0) - return log_error_errno(r, "Failed to parse journald syntax \"%s\": %m", line); - - if (r == 0) - break; - - if (startswith(word, "systemd.journald.forward_to_syslog=")) { - r = parse_boolean(word + 35); - if (r < 0) - log_warning("Failed to parse forward to syslog switch %s. Ignoring.", word + 35); - else - s->forward_to_syslog = r; - } else if (startswith(word, "systemd.journald.forward_to_kmsg=")) { - r = parse_boolean(word + 33); - if (r < 0) - log_warning("Failed to parse forward to kmsg switch %s. Ignoring.", word + 33); - else - s->forward_to_kmsg = r; - } else if (startswith(word, "systemd.journald.forward_to_console=")) { - r = parse_boolean(word + 36); - if (r < 0) - log_warning("Failed to parse forward to console switch %s. Ignoring.", word + 36); - else - s->forward_to_console = r; - } else if (startswith(word, "systemd.journald.forward_to_wall=")) { - r = parse_boolean(word + 33); - if (r < 0) - log_warning("Failed to parse forward to wall switch %s. Ignoring.", word + 33); - else - s->forward_to_wall = r; - } else if (startswith(word, "systemd.journald.max_level_console=")) { - r = log_level_from_string(word + 35); - if (r < 0) - log_warning("Failed to parse max level console value %s. Ignoring.", word + 35); - else - s->max_level_console = r; - } else if (startswith(word, "systemd.journald.max_level_store=")) { - r = log_level_from_string(word + 33); - if (r < 0) - log_warning("Failed to parse max level store value %s. Ignoring.", word + 33); - else - s->max_level_store = r; - } else if (startswith(word, "systemd.journald.max_level_syslog=")) { - r = log_level_from_string(word + 34); - if (r < 0) - log_warning("Failed to parse max level syslog value %s. Ignoring.", word + 34); - else - s->max_level_syslog = r; - } else if (startswith(word, "systemd.journald.max_level_kmsg=")) { - r = log_level_from_string(word + 32); - if (r < 0) - log_warning("Failed to parse max level kmsg value %s. Ignoring.", word + 32); - else - s->max_level_kmsg = r; - } else if (startswith(word, "systemd.journald.max_level_wall=")) { - r = log_level_from_string(word + 32); - if (r < 0) - log_warning("Failed to parse max level wall value %s. Ignoring.", word + 32); - else - s->max_level_wall = r; - } else if (startswith(word, "systemd.journald")) - log_warning("Invalid systemd.journald parameter. Ignoring."); - } + log_warning("Failed to parse forward to syslog switch \"%s\". Ignoring.", value); + else + s->forward_to_syslog = r; + } else if (streq(key, "systemd.journald.forward_to_kmsg")) { + r = value ? parse_boolean(value) : true; + if (r < 0) + log_warning("Failed to parse forward to kmsg switch \"%s\". Ignoring.", value); + else + s->forward_to_kmsg = r; + } else if (streq(key, "systemd.journald.forward_to_console")) { + r = value ? parse_boolean(value) : true; + if (r < 0) + log_warning("Failed to parse forward to console switch \"%s\". Ignoring.", value); + else + s->forward_to_console = r; + } else if (streq(key, "systemd.journald.forward_to_wall")) { + r = value ? parse_boolean(value) : true; + if (r < 0) + log_warning("Failed to parse forward to wall switch \"%s\". Ignoring.", value); + else + s->forward_to_wall = r; + } else if (streq(key, "systemd.journald.max_level_console") && value) { + r = log_level_from_string(value); + if (r < 0) + log_warning("Failed to parse max level console value \"%s\". Ignoring.", value); + else + s->max_level_console = r; + } else if (streq(key, "systemd.journald.max_level_store") && value) { + r = log_level_from_string(value); + if (r < 0) + log_warning("Failed to parse max level store value \"%s\". Ignoring.", value); + else + s->max_level_store = r; + } else if (streq(key, "systemd.journald.max_level_syslog") && value) { + r = log_level_from_string(value); + if (r < 0) + log_warning("Failed to parse max level syslog value \"%s\". Ignoring.", value); + else + s->max_level_syslog = r; + } else if (streq(key, "systemd.journald.max_level_kmsg") && value) { + r = log_level_from_string(value); + if (r < 0) + log_warning("Failed to parse max level kmsg value \"%s\". Ignoring.", value); + else + s->max_level_kmsg = r; + } else if (streq(key, "systemd.journald.max_level_wall") && value) { + r = log_level_from_string(value); + if (r < 0) + log_warning("Failed to parse max level wall value \"%s\". Ignoring.", value); + else + s->max_level_wall = r; + } else if (startswith(key, "systemd.journald")) + log_warning("Unknown journald kernel command line option \"%s\". Ignoring.", key); /* do not warn about state here, since probably systemd already did */ return 0; @@ -1917,7 +1900,7 @@ int server_init(Server *s) { journal_reset_metrics(&s->runtime_storage.metrics); server_parse_config_file(s); - server_parse_proc_cmdline(s); + parse_proc_cmdline(parse_proc_cmdline_item, s); if (!!s->rate_limit_interval ^ !!s->rate_limit_burst) { log_debug("Setting both rate limit interval and burst from "USEC_FMT",%u to 0,0", -- cgit v1.2.3-54-g00ecf From 92e724670f700d100b8cc8cbaea776b053be31ed Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 22 Oct 2016 14:38:49 -0400 Subject: udev: change kernel commandline option parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - do not crash if an option without value is specified on the kernel command line, e.g. "udev.log-priority" :P - simplify the code a bit - warn about unknown "udev.*" options — this should make it easier to spot typos and reduce user confusion --- src/udev/udevd.c | 47 +++++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 601ab69f1b..05cd5079c1 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -1363,8 +1363,7 @@ static int listen_fds(int *rctrl, int *rnetlink) { * udev.event-timeout= seconds to wait before terminating an event */ static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { - const char *full_key = key; - int r; + int r = 0; assert(key); @@ -1374,37 +1373,25 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (startswith(key, "rd.")) key += strlen("rd."); - if (startswith(key, "udev.")) - key += strlen("udev."); - else - return 0; - - if (streq(key, "log-priority")) { - int prio; - - prio = util_log_priority(value); - if (prio < 0) - goto invalid; - log_set_max_level(prio); - } else if (streq(key, "children-max")) { + if (streq(key, "udev.log-priority") && value) { + r = util_log_priority(value); + if (r >= 0) + log_set_max_level(r); + } else if (streq(key, "udev.event-timeout") && value) { + r = safe_atou64(value, &arg_event_timeout_usec); + if (r >= 0) { + arg_event_timeout_usec *= USEC_PER_SEC; + arg_event_timeout_warn_usec = (arg_event_timeout_usec / 3) ? : 1; + } + } else if (streq(key, "udev.children-max") && value) r = safe_atou(value, &arg_children_max); - if (r < 0) - goto invalid; - } else if (streq(key, "exec-delay")) { + else if (streq(key, "udev.exec-delay") && value) r = safe_atoi(value, &arg_exec_delay); - if (r < 0) - goto invalid; - } else if (streq(key, "event-timeout")) { - r = safe_atou64(value, &arg_event_timeout_usec); - if (r < 0) - goto invalid; - arg_event_timeout_usec *= USEC_PER_SEC; - arg_event_timeout_warn_usec = (arg_event_timeout_usec / 3) ? : 1; - } + else if (startswith(key, "udev.")) + log_warning("Unknown udev kernel command line option \"%s\"", key); - return 0; -invalid: - log_warning("invalid %s ignored: %s", full_key, value); + if (r < 0) + log_warning_errno(r, "Failed to parse \"%s=%s\", ignoring: %m", key, value); return 0; } -- cgit v1.2.3-54-g00ecf From d7f69e16f1a5b84e9acf1771a9b53da3787ae79d Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 22 Oct 2016 15:31:14 -0400 Subject: tree-wide: make parse_proc_cmdline() strip "rd." prefix automatically This stripping is contolled by a new boolean parameter. When the parameter is true, it means that the caller does not care about the distinction between initrd and real root, and wants to act on both rd-dot-prefixed and unprefixed parameters in the initramfs, and only on the unprefixed parameters in real root. If the parameter is false, behaviour is the same as before. Changes by caller: log.c (systemd.log_*): changed to accept rd-dot-prefix params pid1: no change, custom logic cryptsetup-generator: no change, still accepts rd-dot-prefix params debug-generator: no change, does not accept rd-dot-prefix params fsck: changed to accept rd-dot-prefix params fstab-generator: no change, custom logic gpt-auto-generator: no change, custom logic hibernate-resume-generator: no change, does not accept rd-dot-prefix params journald: changed to accept rd-dot-prefix params modules-load: no change, still accepts rd-dot-prefix params quote-check: no change, does not accept rd-dot-prefix params udevd: no change, still accepts rd-dot-prefix params I added support for "rd." params in the three cases where I think it's useful: logging, fsck options, journald forwarding options. --- src/basic/log.c | 2 +- src/basic/proc-cmdline.c | 11 +++++++---- src/basic/proc-cmdline.h | 4 +++- src/core/main.c | 2 +- src/cryptsetup/cryptsetup-generator.c | 14 +++++++------- src/debug-generator/debug-generator.c | 2 +- src/fsck/fsck.c | 2 +- src/fstab-generator/fstab-generator.c | 2 +- src/gpt-auto-generator/gpt-auto-generator.c | 2 +- src/hibernate-resume/hibernate-resume-generator.c | 2 +- src/journal/journald-server.c | 2 +- src/modules-load/modules-load.c | 4 ++-- src/quotacheck/quotacheck.c | 2 +- src/test/test-proc-cmdline.c | 2 +- src/udev/udevd.c | 5 +---- 15 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/basic/log.c b/src/basic/log.c index 40f342ca72..2ff70be255 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -1012,7 +1012,7 @@ void log_parse_environment(void) { /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is user stuff. */ - (void) parse_proc_cmdline(parse_proc_cmdline_item, NULL); + (void) parse_proc_cmdline(parse_proc_cmdline_item, NULL, true); e = secure_getenv("SYSTEMD_LOG_TARGET"); if (e && log_set_target_from_string(e) < 0) diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c index 951db34d1a..8297a222b7 100644 --- a/src/basic/proc-cmdline.c +++ b/src/basic/proc-cmdline.c @@ -42,7 +42,9 @@ int proc_cmdline(char **ret) { return read_one_line_file("/proc/cmdline", ret); } -int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, void *data), void *data) { +int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, void *data), + void *data, + bool strip_prefix) { _cleanup_free_ char *line = NULL; const char *p; int r; @@ -56,7 +58,7 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, voi p = line; for (;;) { _cleanup_free_ char *word = NULL; - char *value = NULL; + char *value = NULL, *unprefixed; r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX); if (r < 0) @@ -66,14 +68,15 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, voi /* Filter out arguments that are intended only for the * initrd */ - if (!in_initrd() && startswith(word, "rd.")) + unprefixed = startswith(word, "rd."); + if (unprefixed && !in_initrd()) continue; value = strchr(word, '='); if (value) *(value++) = 0; - r = parse_item(word, value, data); + r = parse_item(strip_prefix && unprefixed ? unprefixed : word, value, data); if (r < 0) return r; } diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h index a8832d8419..6d6ee95c11 100644 --- a/src/basic/proc-cmdline.h +++ b/src/basic/proc-cmdline.h @@ -20,7 +20,9 @@ ***/ int proc_cmdline(char **ret); -int parse_proc_cmdline(int (*parse_word)(const char *key, const char *value, void *data), void *data); +int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value, void *data), + void *data, + bool strip_prefix); int get_proc_cmdline_key(const char *parameter, char **value); int shall_restore_state(void); diff --git a/src/core/main.c b/src/core/main.c index bf9bba28d6..ffc7725f16 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1570,7 +1570,7 @@ int main(int argc, char *argv[]) { } if (arg_system) { - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); } diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 7193d93070..e2dc4327fe 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -282,7 +282,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat crypto_device *d; _cleanup_free_ char *uuid = NULL, *uuid_value = NULL; - if (STR_IN_SET(key, "luks", "rd.luks") && value) { + if (streq(key, "luks") && value) { r = parse_boolean(value); if (r < 0) @@ -290,7 +290,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat else arg_enabled = r; - } else if (STR_IN_SET(key, "luks.crypttab", "rd.luks.crypttab") && value) { + } else if (streq(key, "luks.crypttab") && value) { r = parse_boolean(value); if (r < 0) @@ -298,7 +298,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat else arg_read_crypttab = r; - } else if (STR_IN_SET(key, "luks.uuid", "rd.luks.uuid") && value) { + } else if (streq(key, "luks.uuid") && value) { d = get_crypto_device(startswith(value, "luks-") ? value+5 : value); if (!d) @@ -306,7 +306,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat d->create = arg_whitelist = true; - } else if (STR_IN_SET(key, "luks.options", "rd.luks.options") && value) { + } else if (streq(key, "luks.options") && value) { r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); if (r == 2) { @@ -320,7 +320,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat } else if (free_and_strdup(&arg_default_options, value) < 0) return log_oom(); - } else if (STR_IN_SET(key, "luks.key", "rd.luks.key") && value) { + } else if (streq(key, "luks.key") && value) { r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); if (r == 2) { @@ -334,7 +334,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat } else if (free_and_strdup(&arg_default_keyfile, value) < 0) return log_oom(); - } else if (STR_IN_SET(key, "luks.name", "rd.luks.name") && value) { + } else if (streq(key, "luks.name") && value) { r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); if (r == 2) { @@ -478,7 +478,7 @@ int main(int argc, char *argv[]) { if (!arg_disks) goto cleanup; - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true); if (r < 0) { log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); r = EXIT_FAILURE; diff --git a/src/debug-generator/debug-generator.c b/src/debug-generator/debug-generator.c index 0b0de1b461..7f11ec724d 100644 --- a/src/debug-generator/debug-generator.c +++ b/src/debug-generator/debug-generator.c @@ -178,7 +178,7 @@ int main(int argc, char *argv[]) { goto finish; } - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 957e0ccef8..be25c6a2b2 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -293,7 +293,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index b608eff630..e77bd71a52 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -674,7 +674,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index a25b3413ae..a098b27a8e 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -1018,7 +1018,7 @@ int main(int argc, char *argv[]) { return EXIT_SUCCESS; } - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/hibernate-resume/hibernate-resume-generator.c b/src/hibernate-resume/hibernate-resume-generator.c index 8be461aafa..17e670604e 100644 --- a/src/hibernate-resume/hibernate-resume-generator.c +++ b/src/hibernate-resume/hibernate-resume-generator.c @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) { if (!in_initrd()) return EXIT_SUCCESS; - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index e7dcbba04f..76c9baf6db 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -1900,7 +1900,7 @@ int server_init(Server *s) { journal_reset_metrics(&s->runtime_storage.metrics); server_parse_config_file(s); - parse_proc_cmdline(parse_proc_cmdline_item, s); + parse_proc_cmdline(parse_proc_cmdline_item, s, true); if (!!s->rate_limit_interval ^ !!s->rate_limit_burst) { log_debug("Setting both rate limit interval and burst from "USEC_FMT",%u to 0,0", diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index bd07bad446..0901fea8dc 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -62,7 +62,7 @@ static int add_modules(const char *p) { static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; - if (STR_IN_SET(key, "modules-load", "rd.modules-load") && value) { + if (streq(key, "modules-load") && value) { r = add_modules(value); if (r < 0) return r; @@ -226,7 +226,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c index a87b0866cd..2714cde5c7 100644 --- a/src/quotacheck/quotacheck.c +++ b/src/quotacheck/quotacheck.c @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c index e4207935c4..4101678f19 100644 --- a/src/test/test-proc-cmdline.c +++ b/src/test/test-proc-cmdline.c @@ -36,7 +36,7 @@ static int parse_item(const char *key, const char *value, void *data) { } static void test_parse_proc_cmdline(void) { - assert_se(parse_proc_cmdline(parse_item, &obj) >= 0); + assert_se(parse_proc_cmdline(parse_item, &obj, true) >= 0); } static void test_runlevel_to_target(void) { diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 05cd5079c1..badbab6205 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -1370,9 +1370,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (!value) return 0; - if (startswith(key, "rd.")) - key += strlen("rd."); - if (streq(key, "udev.log-priority") && value) { r = util_log_priority(value); if (r >= 0) @@ -1652,7 +1649,7 @@ int main(int argc, char *argv[]) { if (r <= 0) goto exit; - r = parse_proc_cmdline(parse_proc_cmdline_item, NULL); + r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, true); if (r < 0) log_warning_errno(r, "failed to parse kernel command line, ignoring: %m"); -- cgit v1.2.3-54-g00ecf From 9b232d3241fcfbf60affab69fa51213e36133db5 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 22 Oct 2016 23:28:46 -0400 Subject: core: do not set no_new_privileges flag in config_parse_syscall_filter If SyscallFilter was set, and subsequently cleared, the no_new_privileges flag was not reset properly. We don't need to set this flag here, it will be set automatically in unit_patch_contexts() if syscall_filter is set. --- src/core/load-fragment.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index a69f60097d..9881baf192 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2736,11 +2736,6 @@ int config_parse_syscall_filter( if (!isempty(state)) log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); - /* Turn on NNP, but only if it wasn't configured explicitly - * before, and only if we are in user mode. */ - if (!c->no_new_privileges_set && MANAGER_IS_USER(u->manager)) - c->no_new_privileges = true; - return 0; } @@ -3829,7 +3824,7 @@ int config_parse_no_new_privileges( return 0; } - c->no_new_privileges = !!k; + c->no_new_privileges = k; c->no_new_privileges_set = true; return 0; -- cgit v1.2.3-54-g00ecf From 4d885bd326d958827d926512ecc5e0d21f6ad76b Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Sun, 23 Oct 2016 23:24:14 +0200 Subject: core: first lookup and cache creds then apply them after namespace setup This fixes: https://github.com/systemd/systemd/issues/4357 Let's lookup and cache creds then apply them. We also switch from getgroups() to getgrouplist(). --- src/core/execute.c | 213 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 144 insertions(+), 69 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 1b7b4a928d..874f035b2e 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -730,74 +730,146 @@ static int ask_for_confirmation(char *response, char **argv) { return r; } -static int enforce_groups(const ExecContext *context, const char *username, gid_t gid) { - bool keep_groups = false; +static int get_fixed_user(const ExecContext *c, const char **user, + uid_t *uid, gid_t *gid, + const char **home, const char **shell) { int r; + const char *name; - assert(context); + assert(c); - /* Lookup and set GID and supplementary group list. Here too - * we avoid NSS lookups for gid=0. */ + if (!c->user) + return 0; - if (context->group || username) { - /* First step, initialize groups from /etc/groups */ - if (username && gid != 0) { - if (initgroups(username, gid) < 0) - return -errno; + /* Note that we don't set $HOME or $SHELL if they are not particularly enlightening anyway + * (i.e. are "/" or "/bin/nologin"). */ - keep_groups = true; - } + name = c->user; + r = get_user_creds_clean(&name, uid, gid, home, shell); + if (r < 0) + return r; - /* Second step, set our gids */ - if (setresgid(gid, gid, gid) < 0) + *user = name; + return 0; +} + +static int get_fixed_group(const ExecContext *c, const char **group, gid_t *gid) { + int r; + const char *name; + + assert(c); + + if (!c->group) + return 0; + + name = c->group; + r = get_group_creds(&name, gid); + if (r < 0) + return r; + + *group = name; + return 0; +} + +static int get_fixed_supplementary_groups(const ExecContext *c, + const char *user, + const char *group, + gid_t gid, + gid_t **supplementary_gids, int *ngids) { + char **i; + int r, k = 0; + int ngroups_max; + bool keep_groups = false; + gid_t *groups = NULL; + _cleanup_free_ gid_t *l_gids = NULL; + + assert(c); + + if (!c->supplementary_groups) + return 0; + + /* + * If user is given, then lookup GID and supplementary group list. + * We avoid NSS lookups for gid=0. + */ + if (user && gid_is_valid(gid) && gid != 0) { + /* First step, initialize groups from /etc/groups */ + if (initgroups(user, gid) < 0) return -errno; + + keep_groups = true; } - if (context->supplementary_groups) { - int ngroups_max, k; - gid_t *gids; - char **i; + assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0); - /* Final step, initialize any manually set supplementary groups */ - assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0); + l_gids = new(gid_t, ngroups_max); + if (!l_gids) + return -ENOMEM; - if (!(gids = new(gid_t, ngroups_max))) - return -ENOMEM; + if (keep_groups) { + /* + * Lookup the list of groups that the user belongs to, we + * avoid NSS lookups here too for gid=0. + */ + k = ngroups_max; + if (getgrouplist(user, gid, l_gids, &k) < 0) + return -EINVAL; + } else + k = 0; - if (keep_groups) { - k = getgroups(ngroups_max, gids); - if (k < 0) { - free(gids); - return -errno; - } - } else - k = 0; + STRV_FOREACH(i, c->supplementary_groups) { + const char *g; - STRV_FOREACH(i, context->supplementary_groups) { - const char *g; + if (k >= ngroups_max) + return -E2BIG; - if (k >= ngroups_max) { - free(gids); - return -E2BIG; - } + g = *i; + r = get_group_creds(&g, l_gids+k); + if (r < 0) + return r; - g = *i; - r = get_group_creds(&g, gids+k); - if (r < 0) { - free(gids); - return r; - } + k++; + } - k++; - } + /* + * Sets ngids to zero to drop all supplementary groups, happens + * when we are under root and SupplementaryGroups= is empty. + */ + if (k == 0) { + *ngids = 0; + return 0; + } - r = maybe_setgroups(k, gids); - if (r < 0) { - free(gids); + /* Otherwise get the final list of supplementary groups */ + groups = memdup(l_gids, sizeof(gid_t) * k); + if (!groups) + return -ENOMEM; + + *supplementary_gids = groups; + *ngids = k; + + groups = NULL; + + return 0; +} + +static int enforce_groups(const ExecContext *context, gid_t gid, + gid_t *supplementary_gids, int ngids) { + int r; + + assert(context); + + /* Handle SupplementaryGroups= even if it is empty */ + if (context->supplementary_groups) { + r = maybe_setgroups(ngids, supplementary_gids); + if (r < 0) return r; - } + } - free(gids); + if (gid_is_valid(gid)) { + /* Then set our gids */ + if (setresgid(gid, gid, gid) < 0) + return -errno; } return 0; @@ -806,6 +878,9 @@ static int enforce_groups(const ExecContext *context, const char *username, gid_ static int enforce_user(const ExecContext *context, uid_t uid) { assert(context); + if (!uid_is_valid(uid)) + return 0; + /* Sets (but doesn't look up) the uid and make sure we keep the * capabilities while doing so. */ @@ -2175,13 +2250,15 @@ static int exec_child( _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **final_argv = NULL; _cleanup_free_ char *mac_selinux_context_net = NULL; - const char *username = NULL, *home = NULL, *shell = NULL, *wd; + _cleanup_free_ gid_t *supplementary_gids = NULL; + const char *username = NULL, *groupname = NULL; + const char *home = NULL, *shell = NULL, *wd; dev_t journal_stream_dev = 0; ino_t journal_stream_ino = 0; bool needs_mount_namespace; uid_t uid = UID_INVALID; gid_t gid = GID_INVALID; - int i, r; + int i, r, ngids = 0; assert(unit); assert(command); @@ -2273,26 +2350,23 @@ static int exec_child( username = dcreds->user->name; } else { - if (context->user) { - username = context->user; - r = get_user_creds_clean(&username, &uid, &gid, &home, &shell); - if (r < 0) { - *exit_status = EXIT_USER; - return r; - } - - /* Note that we don't set $HOME or $SHELL if they are not particularly enlightening anyway - * (i.e. are "/" or "/bin/nologin"). */ + r = get_fixed_user(context, &username, &uid, &gid, &home, &shell); + if (r < 0) { + *exit_status = EXIT_USER; + return r; } - if (context->group) { - const char *g = context->group; + r = get_fixed_group(context, &groupname, &gid); + if (r < 0) { + *exit_status = EXIT_GROUP; + return r; + } - r = get_group_creds(&g, &gid); - if (r < 0) { - *exit_status = EXIT_GROUP; - return r; - } + r = get_fixed_supplementary_groups(context, username, groupname, + gid, &supplementary_gids, &ngids); + if (r < 0) { + *exit_status = EXIT_GROUP; + return r; } } @@ -2558,8 +2632,9 @@ static int exec_child( } } + /* Drop group as early as possbile */ if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { - r = enforce_groups(context, username, gid); + r = enforce_groups(context, gid, supplementary_gids, ngids); if (r < 0) { *exit_status = EXIT_GROUP; return r; -- cgit v1.2.3-54-g00ecf From 86b838eaa36814f1a9c02f3289328cd0ec42d1ff Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Fri, 14 Oct 2016 10:32:27 +0200 Subject: test: Add simple test for supplementary groups --- Makefile.am | 1 + src/test/test-execute.c | 5 +++++ test/test-execute/exec-supplementarygroups.service | 7 +++++++ 3 files changed, 13 insertions(+) create mode 100644 test/test-execute/exec-supplementarygroups.service diff --git a/Makefile.am b/Makefile.am index 07acce347e..0debd38964 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1627,6 +1627,7 @@ EXTRA_DIST += \ test/test-execute/exec-passenvironment.service \ test/test-execute/exec-group.service \ test/test-execute/exec-group-nfsnobody.service \ + test/test-execute/exec-supplementarygroups.service \ test/test-execute/exec-ignoresigpipe-no.service \ test/test-execute/exec-ignoresigpipe-yes.service \ test/test-execute/exec-personality-x86-64.service \ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index e8ff02adaf..cda035c6e7 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -218,6 +218,10 @@ static void test_exec_group(Manager *m) { log_error_errno(errno, "Skipping test_exec_group, could not find nobody/nfsnobody group: %m"); } +static void test_exec_supplementary_groups(Manager *m) { + test(m, "exec-supplementarygroups.service", 0, CLD_EXITED); +} + static void test_exec_environment(Manager *m) { test(m, "exec-environment.service", 0, CLD_EXITED); test(m, "exec-environment-multiple.service", 0, CLD_EXITED); @@ -390,6 +394,7 @@ int main(int argc, char *argv[]) { test_exec_systemcallerrornumber, test_exec_user, test_exec_group, + test_exec_supplementary_groups, test_exec_environment, test_exec_environmentfile, test_exec_passenvironment, diff --git a/test/test-execute/exec-supplementarygroups.service b/test/test-execute/exec-supplementarygroups.service new file mode 100644 index 0000000000..43a9a981f2 --- /dev/null +++ b/test/test-execute/exec-supplementarygroups.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Supplementary Group + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -G)" = "0 1"' +Type=oneshot +SupplementaryGroups=1 -- cgit v1.2.3-54-g00ecf From bf9ace96fc764fb6c795790a5febade4689f9aba Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Mon, 17 Oct 2016 10:06:18 +0200 Subject: test: add more tests for SupplementaryGroups= --- Makefile.am | 2 ++ src/test/test-execute.c | 2 ++ .../exec-supplementarygroups-single-group-user.service | 9 +++++++++ test/test-execute/exec-supplementarygroups-single-group.service | 8 ++++++++ 4 files changed, 21 insertions(+) create mode 100644 test/test-execute/exec-supplementarygroups-single-group-user.service create mode 100644 test/test-execute/exec-supplementarygroups-single-group.service diff --git a/Makefile.am b/Makefile.am index 0debd38964..c49edef7b2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1628,6 +1628,8 @@ EXTRA_DIST += \ test/test-execute/exec-group.service \ test/test-execute/exec-group-nfsnobody.service \ test/test-execute/exec-supplementarygroups.service \ + test/test-execute/exec-supplementarygroups-single-group.service \ + test/test-execute/exec-supplementarygroups-single-group-user.service \ test/test-execute/exec-ignoresigpipe-no.service \ test/test-execute/exec-ignoresigpipe-yes.service \ test/test-execute/exec-personality-x86-64.service \ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index cda035c6e7..1254ef8a05 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -220,6 +220,8 @@ static void test_exec_group(Manager *m) { static void test_exec_supplementary_groups(Manager *m) { test(m, "exec-supplementarygroups.service", 0, CLD_EXITED); + test(m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED); + test(m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED); } static void test_exec_environment(Manager *m) { diff --git a/test/test-execute/exec-supplementarygroups-single-group-user.service b/test/test-execute/exec-supplementarygroups-single-group-user.service new file mode 100644 index 0000000000..ed6276d303 --- /dev/null +++ b/test/test-execute/exec-supplementarygroups-single-group-user.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for Supplementary Group with only one group and uid 1 + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -G)" = "1" && test "$$(id -g)" = "1" && test "$$(id -u)" = "1"' +Type=oneshot +User=1 +Group=1 +SupplementaryGroups=1 diff --git a/test/test-execute/exec-supplementarygroups-single-group.service b/test/test-execute/exec-supplementarygroups-single-group.service new file mode 100644 index 0000000000..ee502b3d37 --- /dev/null +++ b/test/test-execute/exec-supplementarygroups-single-group.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for Supplementary Group with only one group + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -G)" = "1" && test "$$(id -g)" = "1" && test "$$(id -u)" = "0"' +Type=oneshot +Group=1 +SupplementaryGroups=1 -- cgit v1.2.3-54-g00ecf From 8b6903ad4d0dc94cd0098f453a4ea8ab24a4a3f7 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Fri, 21 Oct 2016 22:22:56 +0200 Subject: core: lets move the setup of working directory before group enforce This is minor but lets try to split and move bit by bit cgroups and portable environment setup before applying the security context. --- src/core/execute.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 874f035b2e..a9b2b8f299 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2632,6 +2632,13 @@ static int exec_child( } } + if (context->working_directory_home) + wd = home; + else if (context->working_directory) + wd = context->working_directory; + else + wd = "/"; + /* Drop group as early as possbile */ if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { r = enforce_groups(context, gid, supplementary_gids, ngids); @@ -2641,13 +2648,6 @@ static int exec_child( } } - if (context->working_directory_home) - wd = home; - else if (context->working_directory) - wd = context->working_directory; - else - wd = "/"; - if (params->flags & EXEC_APPLY_CHROOT) { if (!needs_mount_namespace && context->root_directory) if (chroot(context->root_directory) < 0) { -- cgit v1.2.3-54-g00ecf From 548bd57376f7eb82cc792f0476688ccc9843962a Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Thu, 20 Oct 2016 09:01:45 +0000 Subject: basic: fallback to the fstat if we don't have access to the /proc/self/fdinfo https://github.com/systemd/systemd/pull/4372#discussion_r83354107: I get `open("/proc/self/fdinfo/13", O_RDONLY|O_CLOEXEC) = -1 EACCES (Permission denied)` 327 mkdir("/proc", 0755 327 <... mkdir resumed> ) = -1 EEXIST (File exists) 327 stat("/proc", 327 <... stat resumed> {st_dev=makedev(8, 1), st_ino=28585, st_mode=S_IFDIR|0755, st_nlink=2, st_uid=0, st_gid=0, st_blksize=1024, st_blocks=4, st_size=1024, st_atime=2016/10/14-02:55:32, st_mtime=2016/ 327 mount("proc", "/proc", "proc", MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL 327 <... mount resumed> ) = 0 327 lstat("/proc", 327 <... lstat resumed> {st_dev=makedev(0, 34), st_ino=1, st_mode=S_IFDIR|0555, st_nlink=75, st_uid=65534, st_gid=65534, st_blksize=1024, st_blocks=0, st_size=0, st_atime=2016/10/14-03:13:35.971031263, 327 lstat("/proc/sys", {st_dev=makedev(0, 34), st_ino=4026531855, st_mode=S_IFDIR|0555, st_nlink=1, st_uid=65534, st_gid=65534, st_blksize=1024, st_blocks=0, st_size=0, st_atime=2016/10/14-03:13:39.1630 327 openat(AT_FDCWD, "/proc", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_PATH) = 11 327 name_to_handle_at(11, "sys", {handle_bytes=128}, 0x7ffe3a238604, AT_SYMLINK_FOLLOW) = -1 EOPNOTSUPP (Operation not supported) 327 name_to_handle_at(11, "", {handle_bytes=128}, 0x7ffe3a238608, AT_EMPTY_PATH) = -1 EOPNOTSUPP (Operation not supported) 327 openat(11, "sys", O_RDONLY|O_CLOEXEC|O_PATH) = 13 327 open("/proc/self/fdinfo/13", O_RDONLY|O_CLOEXEC) = -1 EACCES (Permission denied) 327 close(13 327 <... close resumed> ) = 0 327 close(11 327 <... close resumed> ) = 0 -bash-4.3# ls -ld /proc/ dr-xr-xr-x 76 65534 65534 0 Oct 14 02:57 /proc/ -bash-4.3# ls -ld /proc/1 dr-xr-xr-x 9 root root 0 Oct 14 02:57 /proc/1 -bash-4.3# ls -ld /proc/1/fdinfo dr-x------ 2 65534 65534 0 Oct 14 03:00 /proc/1/fdinfo --- src/basic/mount-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c index 0ef00676ef..2985cc475a 100644 --- a/src/basic/mount-util.c +++ b/src/basic/mount-util.c @@ -162,7 +162,7 @@ int fd_is_mount_point(int fd, const char *filename, int flags) { fallback_fdinfo: r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id); - if (r == -EOPNOTSUPP) + if (IN_SET(r, -EOPNOTSUPP, -EACCES)) goto fallback_fstat; if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 63eae72312b6b8df4c7186233994a65d747229a7 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Thu, 20 Oct 2016 09:03:40 +0000 Subject: nspawn: really lchown(uid/gid) https://github.com/systemd/systemd/pull/4372#issuecomment-253723849: * `mount_all (outer_child)` creates `container_dir/sys/fs/selinux` * `mount_all (outer_child)` doesn't patch `container_dir/sys/fs` and so on. * `mount_sysfs (inner_child)` tries to create `/sys/fs/cgroup` * This fails 370 stat("/sys/fs", {st_dev=makedev(0, 28), st_ino=13880, st_mode=S_IFDIR|0755, st_nlink=3, st_uid=65534, st_gid=65534, st_blksize=4096, st_blocks=0, st_size=60, st_atime=2016/10/14-05:16:43.398665943, st_mtime=2016/10/14-05:16:43.399665943, st_ctime=2016/10/14-05:16:43.399665943}) = 0 370 mkdir("/sys/fs/cgroup", 0755) = -1 EACCES (Permission denied) * `mount_syfs (inner_child)` ignores that error and mount(NULL, "/sys", NULL, MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_REMOUNT|MS_BIND, NULL) = 0 * `mount_cgroups` finally fails --- src/nspawn/nspawn-mount.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 44dc9bfcf4..115de64cf9 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -300,6 +300,59 @@ int mount_sysfs(const char *dest) { MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL); } +static int mkdir_userns(const char *path, mode_t mode, bool in_userns, uid_t uid_shift) { + int r; + + assert(path); + + r = mkdir(path, mode); + if (r < 0 && errno != EEXIST) + return -errno; + + if (!in_userns) { + r = lchown(path, uid_shift, uid_shift); + if (r < 0) + return -errno; + } + + return 0; +} + +static int mkdir_userns_p(const char *prefix, const char *path, mode_t mode, bool in_userns, uid_t uid_shift) { + const char *p, *e; + int r; + + assert(path); + + if (prefix && !path_startswith(path, prefix)) + return -ENOTDIR; + + /* create every parent directory in the path, except the last component */ + p = path + strspn(path, "/"); + for (;;) { + char t[strlen(path) + 1]; + + e = p + strcspn(p, "/"); + p = e + strspn(e, "/"); + + /* Is this the last component? If so, then we're done */ + if (*p == 0) + break; + + memcpy(t, path, e - path); + t[e-path] = 0; + + if (prefix && path_startswith(prefix, t)) + continue; + + r = mkdir_userns(t, mode, in_userns, uid_shift); + if (r < 0) + return r; + } + + return mkdir_userns(path, mode, in_userns, uid_shift); +} + int mount_all(const char *dest, bool use_userns, bool in_userns, bool use_netns, @@ -361,7 +414,7 @@ int mount_all(const char *dest, if (mount_table[k].what && r > 0) continue; - r = mkdir_p(where, 0755); + r = mkdir_userns_p(dest, where, 0755, in_userns, uid_shift); if (r < 0 && r != -EEXIST) { if (mount_table[k].fatal) return log_error_errno(r, "Failed to create directory %s: %m", where); -- cgit v1.2.3-54-g00ecf From 6d66bd3b2a7ebe99aa7fcd06df9bc05b178a142a Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Thu, 20 Oct 2016 09:05:46 +0000 Subject: nspawn: become a new root early https://github.com/torvalds/linux/commit/036d523641c66bef713042894a17f4335f199e49 > vfs: Don't create inodes with a uid or gid unknown to the vfs It is expected that filesystems can not represent uids and gids from outside of their user namespace. Keep things simple by not even trying to create filesystem nodes with non-sense uids and gids. So, we actually should `reset_uid_gid` early to prevent https://github.com/systemd/systemd/pull/4223#issuecomment-252522955 $ sudo UNIFIED_CGROUP_HIERARCHY=no LD_LIBRARY_PATH=.libs .libs/systemd-nspawn -D /var/lib/machines/fedora-rawhide -U -b systemd.unit=multi-user.target Spawning container fedora-rawhide on /var/lib/machines/fedora-rawhide. Press ^] three times within 1s to kill container. Child died too early. Selected user namespace base 1073283072 and range 65536. Failed to mount to /sys/fs/cgroup/systemd: No such file or directory Details: https://github.com/systemd/systemd/pull/4223#issuecomment-253046519 Fixes: #4352 --- src/nspawn/nspawn.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 2cbe563953..295293858e 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2684,6 +2684,10 @@ static int inner_child( } } + r = reset_uid_gid(); + if (r < 0) + return log_error_errno(r, "Couldn't become new root: %m"); + r = mount_all(NULL, arg_userns_mode != USER_NAMESPACE_NO, true, @@ -2726,10 +2730,6 @@ static int inner_child( return r; } - r = reset_uid_gid(); - if (r < 0) - return log_error_errno(r, "Couldn't become new root: %m"); - r = setup_boot_id(NULL); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 844da987ef8b8c98f837d3328eeb3ed481f43835 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Thu, 20 Oct 2016 09:16:23 +0000 Subject: tests/TEST-13-NSPAWN-SMOKE: remove an expected failure check https://github.com/systemd/systemd/issues/4352 has been fixed So, we don't need this workaround anymore --- Makefile.am | 1 - test/TEST-13-NSPAWN-SMOKE/Makefile | 4 +- test/TEST-13-NSPAWN-SMOKE/has-overflow.c | 143 ------------------------------- test/TEST-13-NSPAWN-SMOKE/test.sh | 19 +--- 4 files changed, 4 insertions(+), 163 deletions(-) delete mode 100644 test/TEST-13-NSPAWN-SMOKE/has-overflow.c diff --git a/Makefile.am b/Makefile.am index 00124a29f8..b68f380e49 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6031,7 +6031,6 @@ EXTRA_DIST += \ test/TEST-12-ISSUE-3171/Makefile \ test/TEST-12-ISSUE-3171/test.sh \ test/TEST-13-NSPAWN-SMOKE/Makefile \ - test/TEST-13-NSPAWN-SMOKE/has-overflow.c \ test/TEST-13-NSPAWN-SMOKE/create-busybox-container \ test/TEST-13-NSPAWN-SMOKE/test.sh \ test/test-functions diff --git a/test/TEST-13-NSPAWN-SMOKE/Makefile b/test/TEST-13-NSPAWN-SMOKE/Makefile index 2ca5b12cf3..ff1470f852 100644 --- a/test/TEST-13-NSPAWN-SMOKE/Makefile +++ b/test/TEST-13-NSPAWN-SMOKE/Makefile @@ -1,7 +1,7 @@ -all: has-overflow +all: @make -s --no-print-directory -C ../.. all @basedir=../.. TEST_BASE_DIR=../ ./test.sh --all -setup: has-overflow +setup: @make --no-print-directory -C ../.. all @basedir=../.. TEST_BASE_DIR=../ ./test.sh --setup clean: diff --git a/test/TEST-13-NSPAWN-SMOKE/has-overflow.c b/test/TEST-13-NSPAWN-SMOKE/has-overflow.c deleted file mode 100644 index 1b3331fad7..0000000000 --- a/test/TEST-13-NSPAWN-SMOKE/has-overflow.c +++ /dev/null @@ -1,143 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) - -struct child_args { - int pipe_fd[2]; /* Pipe used to synchronize parent and child */ -}; - -static void usage(char *pname) { - fprintf(stderr, "Options can be:\n"); - fprintf(stderr, "\t-M uid_map Specify UID map for user namespace\n"); - fprintf(stderr, "\t-G gid_map Specify GID map for user namespace\n"); - - exit(EXIT_FAILURE); -} - -static void update_map(char *mapping, char *map_file) { - int fd, j; - size_t map_len; - - map_len = strlen(mapping); - - fd = open(map_file, O_RDWR); - if (fd == -1) { - fprintf(stderr, "ERROR: open %s: %s\n", map_file, strerror(errno)); - exit(EXIT_FAILURE); - } - - if (write(fd, mapping, map_len) != map_len) { - fprintf(stderr, "ERROR: write %s: %s\n", map_file, strerror(errno)); - exit(EXIT_FAILURE); - } - - close(fd); -} - -static void proc_setgroups_write(pid_t child_pid, char *str) { - char setgroups_path[PATH_MAX]; - int fd; - - snprintf(setgroups_path, PATH_MAX, "/proc/%ld/setgroups", (long) child_pid); - - fd = open(setgroups_path, O_RDWR); - if (fd == -1) { - if (errno != ENOENT) - fprintf(stderr, "ERROR: open %s: %s\n", setgroups_path, strerror(errno)); - return; - } - - if (write(fd, str, strlen(str)) == -1) - fprintf(stderr, "ERROR: write %s: %s\n", setgroups_path, strerror(errno)); - - close(fd); -} - -static int child_func(void *arg) { - struct child_args *args = (struct child_args *) arg; - char ch; - - close(args->pipe_fd[1]); - if (read(args->pipe_fd[0], &ch, 1) != 0) { - fprintf(stderr, "Failure in child: read from pipe returned != 0\n"); - exit(EXIT_FAILURE); - } - - mount("tmpfs", "/tmp", "tmpfs", MS_MGC_VAL, "mode=777,uid=0,gid=0"); - if (mkdir("/tmp/hey", 0777) < 0) - exit(EXIT_FAILURE); - - exit(EXIT_SUCCESS); -} - -#define STACK_SIZE (1024 * 1024) - -static char child_stack[STACK_SIZE]; - -int main(int argc, char *argv[]) { - int flags, opt; - pid_t child_pid; - struct child_args args; - char *uid_map, *gid_map; - const int MAP_BUF_SIZE = 100; - char map_buf[MAP_BUF_SIZE]; - char map_path[PATH_MAX]; - int status; - - flags = 0; - gid_map = NULL; - uid_map = NULL; - while ((opt = getopt(argc, argv, "+M:G:")) != -1) { - switch (opt) { - case 'M': - uid_map = optarg; - break; - case 'G': - gid_map = optarg; - break; - default: - usage(argv[0]); - } - } - - if (!uid_map || !gid_map) - usage(argv[0]); - - flags |= CLONE_NEWNS; - flags |= CLONE_NEWUSER; - - if (pipe(args.pipe_fd) == -1) - errExit("pipe"); - - child_pid = clone(child_func, child_stack + STACK_SIZE, flags | SIGCHLD, &args); - if (child_pid == -1) - errExit("clone"); - - snprintf(map_path, PATH_MAX, "/proc/%ld/uid_map", (long) child_pid); - update_map(uid_map, map_path); - - proc_setgroups_write(child_pid, "allow"); - snprintf(map_path, PATH_MAX, "/proc/%ld/gid_map", (long) child_pid); - update_map(gid_map, map_path); - - close(args.pipe_fd[1]); - - if (waitpid(child_pid, &status, 0) == -1) - errExit("waitpid"); - - exit(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS ? EXIT_FAILURE : EXIT_SUCCESS); -} diff --git a/test/TEST-13-NSPAWN-SMOKE/test.sh b/test/TEST-13-NSPAWN-SMOKE/test.sh index dfc437c0ee..e6977a7f1c 100755 --- a/test/TEST-13-NSPAWN-SMOKE/test.sh +++ b/test/TEST-13-NSPAWN-SMOKE/test.sh @@ -40,7 +40,6 @@ test_setup() { setup_basic_environment dracut_install busybox chmod rmdir - dracut_install ./has-overflow cp create-busybox-container $initdir/ @@ -93,22 +92,8 @@ function run { /create-busybox-container "$_root" UNIFIED_CGROUP_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" systemd-nspawn --register=no -D "$_root" -b UNIFIED_CGROUP_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" systemd-nspawn --register=no -D "$_root" --private-network -b - - if ! UNIFIED_CGROUP_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" systemd-nspawn --register=no -D "$_root" -U -b; then - if [[ "$1" = "no" && "$2" = "yes" ]] && /has-overflow -M '0 1073283072 65536' -G '0 1073283072 65536'; then - printf "Failure expected, ignoring (see https://github.com/systemd/systemd/issues/4352)\n" >&2 - else - return 1 - fi - fi - - if ! UNIFIED_CGROUP_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" systemd-nspawn --register=no -D "$_root" --private-network -U -b; then - if [[ "$1" = "no" && "$2" = "yes" ]] && /has-overflow -M '0 1073283072 65536' -G '0 1073283072 65536'; then - printf "Failure expected, ignoring (see https://github.com/systemd/systemd/issues/4352)\n" >&2 - else - return 1 - fi - fi + UNIFIED_CGROUP_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" systemd-nspawn --register=no -D "$_root" -U -b + UNIFIED_CGROUP_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" systemd-nspawn --register=no -D "$_root" --private-network -U -b return 0 } -- cgit v1.2.3-54-g00ecf From b3796dd8349af4235143889e44522a730c1635c0 Mon Sep 17 00:00:00 2001 From: Jan Synacek Date: Thu, 20 Oct 2016 14:48:33 +0200 Subject: install: introduce UnitFileFlags Introduce a new enum to get rid of some boolean arguments of unit_file_* functions. It unifies the code, makes it a bit cleaner and extensible. --- src/core/dbus-manager.c | 37 +++++++++++++++++++------- src/core/main.c | 2 +- src/shared/install.c | 61 +++++++++++++++++++------------------------ src/shared/install.h | 33 ++++++++++++----------- src/systemctl/systemctl.c | 28 +++++++++++++------- src/test/test-install-root.c | 62 ++++++++++++++++++++++---------------------- src/test/test-install.c | 38 +++++++++++++-------------- 7 files changed, 139 insertions(+), 122 deletions(-) diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 12eb55cb7f..ecad71a5aa 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -47,6 +47,11 @@ #include "virt.h" #include "watchdog.h" +static UnitFileFlags unit_file_bools_to_flags(bool runtime, bool force) { + return (runtime ? UNIT_FILE_RUNTIME : 0) | + (force ? UNIT_FILE_FORCE : 0); +} + static int property_get_version( sd_bus *bus, const char *path, @@ -1948,13 +1953,14 @@ static int install_error( static int method_enable_unit_files_generic( sd_bus_message *message, Manager *m, - int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes), + int (*call)(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes), bool carries_install_info, sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; UnitFileChange *changes = NULL; unsigned n_changes = 0; + UnitFileFlags flags; int runtime, force, r; assert(message); @@ -1968,13 +1974,15 @@ static int method_enable_unit_files_generic( if (r < 0) return r; + flags = unit_file_bools_to_flags(runtime, force); + r = bus_verify_manage_unit_files_async(m, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - r = call(m->unit_file_scope, runtime, NULL, l, force, &changes, &n_changes); + r = call(m->unit_file_scope, flags, NULL, l, &changes, &n_changes); if (r < 0) return install_error(error, r, changes, n_changes); @@ -1993,8 +2001,8 @@ static int method_link_unit_files(sd_bus_message *message, void *userdata, sd_bu return method_enable_unit_files_generic(message, userdata, unit_file_link, false, error); } -static int unit_file_preset_without_mode(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) { - return unit_file_preset(scope, runtime, root_dir, files, UNIT_FILE_PRESET_FULL, force, changes, n_changes); +static int unit_file_preset_without_mode(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes) { + return unit_file_preset(scope, flags, root_dir, files, UNIT_FILE_PRESET_FULL, changes, n_changes); } static int method_preset_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { @@ -2013,6 +2021,7 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use Manager *m = userdata; UnitFilePresetMode mm; int runtime, force, r; + UnitFileFlags flags; const char *mode; assert(message); @@ -2026,6 +2035,8 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use if (r < 0) return r; + flags = unit_file_bools_to_flags(runtime, force); + if (isempty(mode)) mm = UNIT_FILE_PRESET_FULL; else { @@ -2040,7 +2051,7 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - r = unit_file_preset(m->unit_file_scope, runtime, NULL, l, mm, force, &changes, &n_changes); + r = unit_file_preset(m->unit_file_scope, flags, NULL, l, mm, &changes, &n_changes); if (r < 0) return install_error(error, r, changes, n_changes); @@ -2050,7 +2061,7 @@ static int method_preset_unit_files_with_mode(sd_bus_message *message, void *use static int method_disable_unit_files_generic( sd_bus_message *message, Manager *m, - int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes), + int (*call)(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes), sd_bus_error *error) { _cleanup_strv_free_ char **l = NULL; @@ -2075,7 +2086,7 @@ static int method_disable_unit_files_generic( if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - r = call(m->unit_file_scope, runtime, NULL, l, &changes, &n_changes); + r = call(m->unit_file_scope, runtime ? UNIT_FILE_RUNTIME : 0, NULL, l, &changes, &n_changes); if (r < 0) return install_error(error, r, changes, n_changes); @@ -2141,7 +2152,7 @@ static int method_set_default_target(sd_bus_message *message, void *userdata, sd if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - r = unit_file_set_default(m->unit_file_scope, NULL, name, force, &changes, &n_changes); + r = unit_file_set_default(m->unit_file_scope, force ? UNIT_FILE_FORCE : 0, NULL, name, &changes, &n_changes); if (r < 0) return install_error(error, r, changes, n_changes); @@ -2154,6 +2165,7 @@ static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, Manager *m = userdata; UnitFilePresetMode mm; const char *mode; + UnitFileFlags flags; int force, runtime, r; assert(message); @@ -2167,6 +2179,8 @@ static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, if (r < 0) return r; + flags = unit_file_bools_to_flags(runtime, force); + if (isempty(mode)) mm = UNIT_FILE_PRESET_FULL; else { @@ -2181,7 +2195,7 @@ static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - r = unit_file_preset_all(m->unit_file_scope, runtime, NULL, mm, force, &changes, &n_changes); + r = unit_file_preset_all(m->unit_file_scope, flags, NULL, mm, &changes, &n_changes); if (r < 0) return install_error(error, r, changes, n_changes); @@ -2196,6 +2210,7 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd int runtime, force, r; char *target, *type; UnitDependency dep; + UnitFileFlags flags; assert(message); assert(m); @@ -2214,11 +2229,13 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd if (r < 0) return r; + flags = unit_file_bools_to_flags(runtime, force); + dep = unit_dependency_from_string(type); if (dep < 0) return -EINVAL; - r = unit_file_add_dependency(m->unit_file_scope, runtime, NULL, l, target, dep, force, &changes, &n_changes); + r = unit_file_add_dependency(m->unit_file_scope, flags, NULL, l, target, dep, &changes, &n_changes); if (r < 0) return install_error(error, r, changes, n_changes); diff --git a/src/core/main.c b/src/core/main.c index b635a633a7..498e289a83 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1777,7 +1777,7 @@ int main(int argc, char *argv[]) { (void) bump_rlimit_nofile(&saved_rlimit_nofile); if (empty_etc) { - r = unit_file_preset_all(UNIT_FILE_SYSTEM, false, NULL, UNIT_FILE_PRESET_ENABLE_ONLY, false, NULL, 0); + r = unit_file_preset_all(UNIT_FILE_SYSTEM, 0, NULL, UNIT_FILE_PRESET_ENABLE_ONLY, NULL, 0); if (r < 0) log_full_errno(r == -EEXIST ? LOG_NOTICE : LOG_WARNING, r, "Failed to populate /etc with preset unit settings, ignoring: %m"); else diff --git a/src/shared/install.c b/src/shared/install.c index d33a658d0a..caca23435a 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1805,10 +1805,9 @@ static int install_context_mark_for_removal( int unit_file_mask( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, - bool force, UnitFileChange **changes, unsigned *n_changes) { @@ -1824,7 +1823,7 @@ int unit_file_mask( if (r < 0) return r; - config_path = runtime ? paths.runtime_config : paths.persistent_config; + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; STRV_FOREACH(i, files) { _cleanup_free_ char *path = NULL; @@ -1840,7 +1839,7 @@ int unit_file_mask( if (!path) return -ENOMEM; - q = create_symlink(&paths, "/dev/null", path, force, changes, n_changes); + q = create_symlink(&paths, "/dev/null", path, !!(flags & UNIT_FILE_FORCE), changes, n_changes); if (q < 0 && r >= 0) r = q; } @@ -1850,7 +1849,7 @@ int unit_file_mask( int unit_file_unmask( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, @@ -1871,7 +1870,7 @@ int unit_file_unmask( if (r < 0) return r; - config_path = runtime ? paths.runtime_config : paths.persistent_config; + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; STRV_FOREACH(i, files) { _cleanup_free_ char *path = NULL; @@ -1935,10 +1934,9 @@ int unit_file_unmask( int unit_file_link( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, - bool force, UnitFileChange **changes, unsigned *n_changes) { @@ -1956,7 +1954,7 @@ int unit_file_link( if (r < 0) return r; - config_path = runtime ? paths.runtime_config : paths.persistent_config; + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; STRV_FOREACH(i, files) { _cleanup_free_ char *full = NULL; @@ -2005,7 +2003,7 @@ int unit_file_link( if (!new_path) return -ENOMEM; - q = create_symlink(&paths, *i, new_path, force, changes, n_changes); + q = create_symlink(&paths, *i, new_path, !!(flags & UNIT_FILE_FORCE), changes, n_changes); if (q < 0 && r >= 0) r = q; } @@ -2190,12 +2188,11 @@ int unit_file_revert( int unit_file_add_dependency( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, const char *target, UnitDependency dep, - bool force, UnitFileChange **changes, unsigned *n_changes) { @@ -2220,7 +2217,7 @@ int unit_file_add_dependency( if (r < 0) return r; - config_path = runtime ? paths.runtime_config : paths.persistent_config; + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; r = install_info_discover(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, &target_info, changes, n_changes); @@ -2260,15 +2257,14 @@ int unit_file_add_dependency( return -ENOMEM; } - return install_context_apply(scope, &c, &paths, config_path, force, SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes); + return install_context_apply(scope, &c, &paths, config_path, !!(flags & UNIT_FILE_FORCE), SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes); } int unit_file_enable( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, - bool force, UnitFileChange **changes, unsigned *n_changes) { @@ -2286,7 +2282,7 @@ int unit_file_enable( if (r < 0) return r; - config_path = runtime ? paths.runtime_config : paths.persistent_config; + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; STRV_FOREACH(f, files) { r = install_info_discover(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, @@ -2305,12 +2301,12 @@ int unit_file_enable( is useful to determine whether the passed files had any installation data at all. */ - return install_context_apply(scope, &c, &paths, config_path, force, SEARCH_LOAD, changes, n_changes); + return install_context_apply(scope, &c, &paths, config_path, !!(flags & UNIT_FILE_FORCE), SEARCH_LOAD, changes, n_changes); } int unit_file_disable( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, @@ -2330,7 +2326,7 @@ int unit_file_disable( if (r < 0) return r; - config_path = runtime ? paths.runtime_config : paths.persistent_config; + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; STRV_FOREACH(i, files) { if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) @@ -2350,10 +2346,9 @@ int unit_file_disable( int unit_file_reenable( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, - bool force, UnitFileChange **changes, unsigned *n_changes) { @@ -2368,19 +2363,19 @@ int unit_file_reenable( n[i] = basename(files[i]); n[i] = NULL; - r = unit_file_disable(scope, runtime, root_dir, n, changes, n_changes); + r = unit_file_disable(scope, flags, root_dir, n, changes, n_changes); if (r < 0) return r; /* But the enable command with the full name */ - return unit_file_enable(scope, runtime, root_dir, files, force, changes, n_changes); + return unit_file_enable(scope, flags, root_dir, files, changes, n_changes); } int unit_file_set_default( UnitFileScope scope, + UnitFileFlags flags, const char *root_dir, const char *name, - bool force, UnitFileChange **changes, unsigned *n_changes) { @@ -2411,7 +2406,7 @@ int unit_file_set_default( return r; new_path = strjoina(paths.persistent_config, "/" SPECIAL_DEFAULT_TARGET); - return create_symlink(&paths, i->path, new_path, force, changes, n_changes); + return create_symlink(&paths, i->path, new_path, !!(flags & UNIT_FILE_FORCE), changes, n_changes); } int unit_file_get_default( @@ -2803,11 +2798,10 @@ static int preset_prepare_one( int unit_file_preset( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, UnitFilePresetMode mode, - bool force, UnitFileChange **changes, unsigned *n_changes) { @@ -2826,7 +2820,7 @@ int unit_file_preset( if (r < 0) return r; - config_path = runtime ? paths.runtime_config : paths.persistent_config; + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; r = read_presets(scope, root_dir, &presets); if (r < 0) @@ -2838,15 +2832,14 @@ int unit_file_preset( return r; } - return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, force, changes, n_changes); + return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes); } int unit_file_preset_all( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, UnitFilePresetMode mode, - bool force, UnitFileChange **changes, unsigned *n_changes) { @@ -2865,7 +2858,7 @@ int unit_file_preset_all( if (r < 0) return r; - config_path = runtime ? paths.runtime_config : paths.persistent_config; + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; r = read_presets(scope, root_dir, &presets); if (r < 0) @@ -2906,7 +2899,7 @@ int unit_file_preset_all( } } - return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, force, changes, n_changes); + return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes); } static void unit_file_list_free_one(UnitFileList *f) { diff --git a/src/shared/install.h b/src/shared/install.h index b1f220693b..561b521bbc 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -23,6 +23,7 @@ typedef enum UnitFileScope UnitFileScope; typedef enum UnitFileState UnitFileState; typedef enum UnitFilePresetMode UnitFilePresetMode; typedef enum UnitFileChangeType UnitFileChangeType; +typedef enum UnitFileFlags UnitFileFlags; typedef enum UnitFileType UnitFileType; typedef struct UnitFileChange UnitFileChange; typedef struct UnitFileList UnitFileList; @@ -78,6 +79,11 @@ enum UnitFileChangeType { _UNIT_FILE_CHANGE_INVALID = INT_MIN }; +enum UnitFileFlags { + UNIT_FILE_RUNTIME = 1, + UNIT_FILE_FORCE = 1 << 1, +}; + /* type can either one of the UnitFileChangeTypes listed above, or a negative error. * If source is specified, it should be the contents of the path symlink. * In case of an error, source should be the existing symlink contents or NULL @@ -144,65 +150,59 @@ bool unit_type_may_template(UnitType type) _const_; int unit_file_enable( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, - bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_disable( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes); int unit_file_reenable( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, - bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_preset( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, UnitFilePresetMode mode, - bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_preset_all( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, UnitFilePresetMode mode, - bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_mask( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, - bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_unmask( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes); int unit_file_link( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, - bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_revert( @@ -213,9 +213,9 @@ int unit_file_revert( unsigned *n_changes); int unit_file_set_default( UnitFileScope scope, + UnitFileFlags flags, const char *root_dir, const char *file, - bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_get_default( @@ -224,12 +224,11 @@ int unit_file_get_default( char **name); int unit_file_add_dependency( UnitFileScope scope, - bool runtime, + UnitFileFlags flags, const char *root_dir, char **files, const char *target, UnitDependency dep, - bool force, UnitFileChange **changes, unsigned *n_changes); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 129706d15f..c9ca3db3f1 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -189,6 +189,11 @@ typedef enum BusFocus { static sd_bus *busses[_BUS_FOCUS_MAX] = {}; +static UnitFileFlags args_to_flags(void) { + return (arg_runtime ? UNIT_FILE_RUNTIME : 0) | + (arg_force ? UNIT_FILE_FORCE : 0); +} + static int acquire_bus(BusFocus focus, sd_bus **ret) { int r; @@ -2137,7 +2142,7 @@ static int set_default(int argc, char *argv[], void *userdata) { return log_error_errno(r, "Failed to mangle unit name: %m"); if (install_client_side()) { - r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes); + r = unit_file_set_default(arg_scope, UNIT_FILE_FORCE, arg_root, unit, &changes, &n_changes); unit_file_dump_changes(r, "set default", changes, n_changes, arg_quiet); if (r > 0) @@ -5955,22 +5960,25 @@ static int enable_unit(int argc, char *argv[], void *userdata) { } if (install_client_side()) { + UnitFileFlags flags; + + flags = args_to_flags(); if (streq(verb, "enable")) { - r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes); + r = unit_file_enable(arg_scope, flags, arg_root, names, &changes, &n_changes); carries_install_info = r; } else if (streq(verb, "disable")) - r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes); + r = unit_file_disable(arg_scope, flags, arg_root, names, &changes, &n_changes); else if (streq(verb, "reenable")) { - r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes); + r = unit_file_reenable(arg_scope, flags, arg_root, names, &changes, &n_changes); carries_install_info = r; } else if (streq(verb, "link")) - r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes); + r = unit_file_link(arg_scope, flags, arg_root, names, &changes, &n_changes); else if (streq(verb, "preset")) { - r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes); + r = unit_file_preset(arg_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes); } else if (streq(verb, "mask")) - r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes); + r = unit_file_mask(arg_scope, flags, arg_root, names, &changes, &n_changes); else if (streq(verb, "unmask")) - r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes); + r = unit_file_unmask(arg_scope, flags, arg_root, names, &changes, &n_changes); else if (streq(verb, "revert")) r = unit_file_revert(arg_scope, arg_root, names, &changes, &n_changes); else @@ -6152,7 +6160,7 @@ static int add_dependency(int argc, char *argv[], void *userdata) { assert_not_reached("Unknown verb"); if (install_client_side()) { - r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes); + r = unit_file_add_dependency(arg_scope, args_to_flags(), arg_root, names, target, dep, &changes, &n_changes); unit_file_dump_changes(r, "add dependency on", changes, n_changes, arg_quiet); if (r > 0) @@ -6214,7 +6222,7 @@ static int preset_all(int argc, char *argv[], void *userdata) { int r; if (install_client_side()) { - r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes); + r = unit_file_preset_all(arg_scope, args_to_flags(), arg_root, arg_preset_mode, &changes, &n_changes); unit_file_dump_changes(r, "preset", changes, n_changes, arg_quiet); if (r > 0) diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c index 1686054d2a..a98de76b43 100644 --- a/src/test/test-install-root.c +++ b/src/test/test-install-root.c @@ -64,7 +64,7 @@ static void test_basic_mask_and_enable(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) >= 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED); - assert_se(unit_file_mask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_mask(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/dev/null")); @@ -80,11 +80,11 @@ static void test_basic_mask_and_enable(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_MASKED); /* Enabling a masked unit should fail! */ - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == -ERFKILL); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) == -ERFKILL); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; - assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); + assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service"); @@ -92,7 +92,7 @@ static void test_basic_mask_and_enable(const char *root) { unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) == 1); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) == 1); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service")); @@ -107,12 +107,12 @@ static void test_basic_mask_and_enable(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED); /* Enabling it again should succeed but be a NOP */ - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 0); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; - assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service"); @@ -126,13 +126,13 @@ static void test_basic_mask_and_enable(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED); /* Disabling a disabled unit must suceed but be a NOP */ - assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 0); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; /* Let's enable this indirectly via a symlink */ - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("d.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("d.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service")); @@ -148,7 +148,7 @@ static void test_basic_mask_and_enable(const char *root) { /* Let's try to reenable */ - assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("b.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("b.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 2); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service"); @@ -217,7 +217,7 @@ static void test_linked_units(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", &state) >= 0 && state == UNIT_FILE_LINKED); /* First, let's link the unit into the search path */ - assert_se(unit_file_link(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_link(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("/opt/linked.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/opt/linked.service")); @@ -229,7 +229,7 @@ static void test_linked_units(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_LINKED); /* Let's unlink it from the search path again */ - assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0); + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service"); @@ -240,7 +240,7 @@ static void test_linked_units(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT); /* Now, let's not just link it, but also enable it */ - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("/opt/linked.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("/opt/linked.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 2); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service"); q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service"); @@ -262,7 +262,7 @@ static void test_linked_units(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED); /* And let's unlink it again */ - assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0); + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 2); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service"); q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service"); @@ -282,7 +282,7 @@ static void test_linked_units(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT); - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked2.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked2.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 2); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked2.service"); q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked2.service"); @@ -301,7 +301,7 @@ static void test_linked_units(const char *root) { unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("linked3.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked3.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(startswith(changes[0].path, root)); @@ -325,7 +325,7 @@ static void test_default(const char *root) { assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT); - assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "idontexist.target", false, &changes, &n_changes) == -ENOENT); + assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, 0, root, "idontexist.target", &changes, &n_changes) == -ENOENT); assert_se(n_changes == 1); assert_se(changes[0].type == -ENOENT); assert_se(streq_ptr(changes[0].path, "idontexist.target")); @@ -334,7 +334,7 @@ static void test_default(const char *root) { assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT); - assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, root, "test-default.target", false, &changes, &n_changes) >= 0); + assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, 0, root, "test-default.target", &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target")); @@ -364,7 +364,7 @@ static void test_add_dependency(const char *root) { p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-service.service"); assert_se(symlink("real-add-dependency-test-service.service", p) >= 0); - assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS, false, &changes, &n_changes) >= 0); + assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS, &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/real-add-dependency-test-service.service")); @@ -401,7 +401,7 @@ static void test_template_enable(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service")); @@ -417,7 +417,7 @@ static void test_template_enable(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); - assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0); + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); assert_se(streq(changes[0].path, p)); @@ -431,7 +431,7 @@ static void test_template_enable(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@foo.service"); @@ -446,7 +446,7 @@ static void test_template_enable(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED); - assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0); + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); assert_se(streq(changes[0].path, p)); @@ -462,7 +462,7 @@ static void test_template_enable(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED); - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("template-symlink@quux.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template-symlink@quux.service"), &changes, &n_changes) >= 0); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service")); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@quux.service"); @@ -507,7 +507,7 @@ static void test_indirect(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); - assert_se(unit_file_enable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), false, &changes, &n_changes) >= 0); + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/indirectb.service")); @@ -520,7 +520,7 @@ static void test_indirect(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); - assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0); + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service"); @@ -560,7 +560,7 @@ static void test_preset_and_list(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); - assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0); + assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/preset-yes.service")); @@ -572,7 +572,7 @@ static void test_preset_and_list(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); - assert_se(unit_file_disable(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0); + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_UNLINK); p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service"); @@ -583,7 +583,7 @@ static void test_preset_and_list(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); - assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0); + assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); assert_se(n_changes == 0); unit_file_changes_free(changes, n_changes); changes = NULL; n_changes = 0; @@ -591,7 +591,7 @@ static void test_preset_and_list(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); - assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, false, root, UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0); + assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, 0, root, UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); assert_se(n_changes > 0); @@ -716,7 +716,7 @@ static void test_preset_order(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED); - assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("prefix-1.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0); + assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("prefix-1.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); assert_se(n_changes == 1); assert_se(changes[0].type == UNIT_FILE_SYMLINK); assert_se(streq(changes[0].source, "/usr/lib/systemd/system/prefix-1.service")); @@ -728,7 +728,7 @@ static void test_preset_order(const char *root) { assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED); - assert_se(unit_file_preset(UNIT_FILE_SYSTEM, false, root, STRV_MAKE("prefix-2.service"), UNIT_FILE_PRESET_FULL, false, &changes, &n_changes) >= 0); + assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("prefix-2.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); assert_se(n_changes == 0); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED); diff --git a/src/test/test-install.c b/src/test/test-install.c index 0ac85f040a..fb36aa83ca 100644 --- a/src/test/test-install.c +++ b/src/test/test-install.c @@ -70,12 +70,12 @@ int main(int argc, char* argv[]) { log_info("/*** enable **/"); - r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes); + r = unit_file_enable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); log_info("/*** enable2 **/"); - r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes); + r = unit_file_enable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -89,7 +89,7 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -103,10 +103,10 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes); + r = unit_file_mask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); log_info("/*** mask2 ***/"); - r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes); + r = unit_file_mask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -120,10 +120,10 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); + r = unit_file_unmask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); log_info("/*** unmask2 ***/"); - r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); + r = unit_file_unmask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -137,7 +137,7 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_mask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, false, &changes, &n_changes); + r = unit_file_mask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -151,10 +151,10 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); log_info("/*** disable2 ***/"); - r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -168,7 +168,7 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_unmask(UNIT_FILE_SYSTEM, false, NULL, (char**) files, &changes, &n_changes); + r = unit_file_unmask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -182,7 +182,7 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_enable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes); + r = unit_file_enable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -196,7 +196,7 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -209,7 +209,7 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_link(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes); + r = unit_file_link(UNIT_FILE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -223,7 +223,7 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -236,7 +236,7 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_link(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes); + r = unit_file_link(UNIT_FILE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -250,7 +250,7 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_reenable(UNIT_FILE_SYSTEM, false, NULL, (char**) files2, false, &changes, &n_changes); + r = unit_file_reenable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -264,7 +264,7 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_disable(UNIT_FILE_SYSTEM, false, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); @@ -276,7 +276,7 @@ int main(int argc, char* argv[]) { changes = NULL; n_changes = 0; - r = unit_file_preset(UNIT_FILE_SYSTEM, false, NULL, (char**) files, UNIT_FILE_PRESET_FULL, false, &changes, &n_changes); + r = unit_file_preset(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, UNIT_FILE_PRESET_FULL, &changes, &n_changes); assert_se(r >= 0); dump_changes(changes, n_changes); -- cgit v1.2.3-54-g00ecf From 3b3557c410c7910fae0990599dcb82711cf5fbb7 Mon Sep 17 00:00:00 2001 From: Jan Synacek Date: Thu, 20 Oct 2016 15:20:11 +0200 Subject: shared, systemctl: teach is-enabled to show installation targets It may be desired by users to know what targets a particular service is installed into. Improve user friendliness by teaching the is-enabled command to show such information when used with --full. This patch makes use of the newly added UnitFileFlags and adds UNIT_FILE_DRY_RUN flag into it. Since the API had already been modified, it's now easy to add the new dry-run feature for other commands as well. As a next step, --dry-run could be added to systemctl, which in turn might pave the way for a long requested dry-run feature when running systemctl start. --- man/systemctl.xml | 3 ++ src/core/dbus-manager.c | 44 ++++++++++++++++++++ src/core/org.freedesktop.systemd1.conf | 4 ++ src/shared/install.c | 38 +++++++++-------- src/shared/install.h | 1 + src/systemctl/systemctl.c | 74 ++++++++++++++++++++++++++++++++-- 6 files changed, 145 insertions(+), 19 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index 75885bcf02..a4d4c53725 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -233,6 +233,8 @@ of status, list-units, list-jobs, and list-timers. + Also, show installation targets in the output of + is-enabled. @@ -1136,6 +1138,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service exit code of 0 if at least one is enabled, non-zero otherwise. Prints the current enable status (see table). To suppress this output, use . + To show installation targets, use . diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index ecad71a5aa..d7d3d3c8ce 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -2242,6 +2242,49 @@ static int method_add_dependency_unit_files(sd_bus_message *message, void *userd return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes); } +static int method_get_unit_file_links(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + UnitFileChange *changes = NULL; + unsigned n_changes = 0, i; + UnitFileFlags flags; + const char *name; + char **p; + int runtime, r; + + r = sd_bus_message_read(message, "sb", &name, &runtime); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, SD_BUS_TYPE_ARRAY, "s"); + if (r < 0) + return r; + + p = STRV_MAKE(name); + flags = UNIT_FILE_DRY_RUN | + (runtime ? UNIT_FILE_RUNTIME : 0); + + r = unit_file_disable(UNIT_FILE_SYSTEM, flags, NULL, p, &changes, &n_changes); + if (r < 0) + return log_error_errno(r, "Failed to get file links for %s: %m", name); + + for (i = 0; i < n_changes; i++) + if (changes[i].type == UNIT_FILE_UNLINK) { + r = sd_bus_message_append(reply, "s", changes[i].path); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_VTABLE_START(0), @@ -2387,6 +2430,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitFileLinks", "sb", "as", method_get_unit_file_links, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetExitCode", "y", NULL, method_set_exit_code, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LookupDynamicUserByName", "s", "u", method_lookup_dynamic_user_by_name, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LookupDynamicUserByUID", "u", "s", method_lookup_dynamic_user_by_uid, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index 6caa15b0b8..a61677e645 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -92,6 +92,10 @@ send_interface="org.freedesktop.systemd1.Manager" send_member="GetUnitProcesses"/> + + diff --git a/src/shared/install.c b/src/shared/install.c index caca23435a..96fba6e25b 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -518,6 +518,7 @@ static int remove_marked_symlinks_fd( const char *path, const char *config_path, const LookupPaths *lp, + bool dry_run, bool *restart, UnitFileChange **changes, unsigned *n_changes) { @@ -566,7 +567,7 @@ static int remove_marked_symlinks_fd( } /* This will close nfd, regardless whether it succeeds or not */ - q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, lp, restart, changes, n_changes); + q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, lp, dry_run, restart, changes, n_changes); if (q < 0 && r == 0) r = q; @@ -603,14 +604,16 @@ static int remove_marked_symlinks_fd( if (!found) continue; - if (unlinkat(fd, de->d_name, 0) < 0 && errno != ENOENT) { - if (r == 0) - r = -errno; - unit_file_changes_add(changes, n_changes, -errno, p, NULL); - continue; - } + if (!dry_run) { + if (unlinkat(fd, de->d_name, 0) < 0 && errno != ENOENT) { + if (r == 0) + r = -errno; + unit_file_changes_add(changes, n_changes, -errno, p, NULL); + continue; + } - (void) rmdir_parents(p, config_path); + (void) rmdir_parents(p, config_path); + } unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL); @@ -621,7 +624,7 @@ static int remove_marked_symlinks_fd( q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: p); if (q < 0) return q; - if (q > 0) + if (q > 0 && !dry_run) *restart = true; } } @@ -633,6 +636,7 @@ static int remove_marked_symlinks( Set *remove_symlinks_to, const char *config_path, const LookupPaths *lp, + bool dry_run, UnitFileChange **changes, unsigned *n_changes) { @@ -659,7 +663,7 @@ static int remove_marked_symlinks( return -errno; /* This takes possession of cfd and closes it */ - q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, lp, &restart, changes, n_changes); + q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, lp, dry_run, &restart, changes, n_changes); if (r == 0) r = q; } while (restart); @@ -1861,6 +1865,7 @@ int unit_file_unmask( size_t n_todo = 0, n_allocated = 0; const char *config_path; char **i; + bool dry_run; int r, q; assert(scope >= 0); @@ -1871,6 +1876,7 @@ int unit_file_unmask( return r; config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + dry_run = !!(flags & UNIT_FILE_DRY_RUN); STRV_FOREACH(i, files) { _cleanup_free_ char *path = NULL; @@ -1907,7 +1913,7 @@ int unit_file_unmask( if (!path) return -ENOMEM; - if (unlink(path) < 0) { + if (!dry_run && unlink(path) < 0) { if (errno != ENOENT) { if (r >= 0) r = -errno; @@ -1925,7 +1931,7 @@ int unit_file_unmask( return q; } - q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, changes, n_changes); + q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes); if (r >= 0) r = q; @@ -2175,11 +2181,11 @@ int unit_file_revert( return q; } - q = remove_marked_symlinks(remove_symlinks_to, paths.runtime_config, &paths, changes, n_changes); + q = remove_marked_symlinks(remove_symlinks_to, paths.runtime_config, &paths, false, changes, n_changes); if (r >= 0) r = q; - q = remove_marked_symlinks(remove_symlinks_to, paths.persistent_config, &paths, changes, n_changes); + q = remove_marked_symlinks(remove_symlinks_to, paths.persistent_config, &paths, false, changes, n_changes); if (r >= 0) r = q; @@ -2341,7 +2347,7 @@ int unit_file_disable( if (r < 0) return r; - return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, changes, n_changes); + return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, !!(flags & UNIT_FILE_DRY_RUN), changes, n_changes); } int unit_file_reenable( @@ -2730,7 +2736,7 @@ static int execute_preset( if (r < 0) return r; - r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, changes, n_changes); + r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes); } else r = 0; diff --git a/src/shared/install.h b/src/shared/install.h index 561b521bbc..7a5859e729 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -82,6 +82,7 @@ enum UnitFileChangeType { enum UnitFileFlags { UNIT_FILE_RUNTIME = 1, UNIT_FILE_FORCE = 1 << 1, + UNIT_FILE_DRY_RUN = 1 << 2, }; /* type can either one of the UnitFileChangeTypes listed above, or a negative error. diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index c9ca3db3f1..2e3b59af3e 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -6271,6 +6271,63 @@ finish: return r; } +static int show_installation_targets_client_side(const char *name) { + UnitFileChange *changes = NULL; + unsigned n_changes = 0, i; + UnitFileFlags flags; + char **p; + int r; + + p = STRV_MAKE(name); + flags = UNIT_FILE_DRY_RUN | + (arg_runtime ? UNIT_FILE_RUNTIME : 0); + + r = unit_file_disable(UNIT_FILE_SYSTEM, flags, NULL, p, &changes, &n_changes); + if (r < 0) + return log_error_errno(r, "Failed to get file links for %s: %m", name); + + for (i = 0; i < n_changes; i++) + if (changes[i].type == UNIT_FILE_UNLINK) + printf(" %s\n", changes[i].path); + + return 0; +} + +static int show_installation_targets(sd_bus *bus, const char *name) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *link; + int r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetUnitFileLinks", + &error, + &reply, + "sb", name, arg_runtime); + if (r < 0) + return log_error_errno(r, "Failed to get unit file links for %s: %s", name, bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "s", &link)) > 0) + printf(" %s\n", link); + + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return 0; +} + static int unit_is_enabled(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; @@ -6289,7 +6346,6 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) { enabled = r > 0; if (install_client_side()) { - STRV_FOREACH(name, names) { UnitFileState state; @@ -6305,8 +6361,14 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) { UNIT_FILE_GENERATED)) enabled = true; - if (!arg_quiet) + if (!arg_quiet) { puts(unit_file_state_to_string(state)); + if (arg_full) { + r = show_installation_targets_client_side(*name); + if (r < 0) + return r; + } + } } r = 0; @@ -6341,8 +6403,14 @@ static int unit_is_enabled(int argc, char *argv[], void *userdata) { if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect", "generated")) enabled = true; - if (!arg_quiet) + if (!arg_quiet) { puts(s); + if (arg_full) { + r = show_installation_targets(bus, *name); + if (r < 0) + return r; + } + } } } -- cgit v1.2.3-54-g00ecf From 50ca7a35a1c4b7550bc7f219d1c54052a2662445 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Mon, 24 Oct 2016 12:38:53 +0200 Subject: test: lets add more tests to cover SupplementaryGroups= cases. --- Makefile.am | 3 +++ src/test/test-execute.c | 3 +++ ...supplementarygroups-multiple-groups-default-group-user.service | 7 +++++++ .../exec-supplementarygroups-multiple-groups-withgid.service | 8 ++++++++ .../exec-supplementarygroups-multiple-groups-withuid.service | 8 ++++++++ 5 files changed, 29 insertions(+) create mode 100644 test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service create mode 100644 test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service create mode 100644 test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service diff --git a/Makefile.am b/Makefile.am index 04e1b71e9e..18a5f4a82a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1630,6 +1630,9 @@ EXTRA_DIST += \ test/test-execute/exec-supplementarygroups.service \ test/test-execute/exec-supplementarygroups-single-group.service \ test/test-execute/exec-supplementarygroups-single-group-user.service \ + test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service \ + test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service \ + test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service \ test/test-execute/exec-ignoresigpipe-no.service \ test/test-execute/exec-ignoresigpipe-yes.service \ test/test-execute/exec-personality-x86-64.service \ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 1254ef8a05..404421a2b8 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -222,6 +222,9 @@ static void test_exec_supplementary_groups(Manager *m) { test(m, "exec-supplementarygroups.service", 0, CLD_EXITED); test(m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED); test(m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED); + test(m, "exec-supplementarygroups-multiple-groups-default-group-user.service", 0, CLD_EXITED); + test(m, "exec-supplementarygroups-multiple-groups-withgid.service", 0, CLD_EXITED); + test(m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED); } static void test_exec_environment(Manager *m) { diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service b/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service new file mode 100644 index 0000000000..a49c9d26a1 --- /dev/null +++ b/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Supplementary Group with multiple groups without Group and User + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -G)" = "0 1 2 3" && test "$$(id -g)" = "0" && test "$$(id -u)" = "0"' +Type=oneshot +SupplementaryGroups=1 2 3 diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service b/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service new file mode 100644 index 0000000000..5c62c1d639 --- /dev/null +++ b/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for Supplementary Group with multiple groups and Group=1 + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -G)" = "1 2 3" && test "$$(id -g)" = "1" && test "$$(id -u)" = "0"' +Type=oneshot +Group=1 +SupplementaryGroups=1 2 3 diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service b/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service new file mode 100644 index 0000000000..00523e383b --- /dev/null +++ b/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for Supplementary Group with multiple groups and Uid=1 + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -G)" = "1 2 3" && test "$$(id -g)" = "1" && test "$$(id -u)" = "1"' +Type=oneshot +User=1 +SupplementaryGroups=1 2 3 -- cgit v1.2.3-54-g00ecf From 366ddd252ed25397ead209228b48c5eef93ced2e Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Mon, 24 Oct 2016 13:13:06 +0200 Subject: core: do not assert when sysconf(_SC_NGROUPS_MAX) fails (#4466) Remove the assert and check the return code of sysconf(_SC_NGROUPS_MAX). _SC_NGROUPS_MAX maps to NGROUPS_MAX which is defined in to 65536 these days. The value is a sysctl read-only /proc/sys/kernel/ngroups_max and the kernel assumes that it is always positive otherwise things may break. Follow this and support only positive values for all other case return either -errno or -EOPNOTSUPP. Now if there are systems that want to re-write NGROUPS_MAX then they should not pass SupplementaryGroups= in units even if it is empty, in this case nothing fails and we just ignore supplementary groups. However if SupplementaryGroups= is passed even if it is empty we have to assume that there will be groups manipulation from our side or the kernel and since the kernel always assumes that NGROUPS_MAX is positive, then follow that and support only positive values. --- src/core/execute.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index a9b2b8f299..53356c3c06 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -788,6 +788,19 @@ static int get_fixed_supplementary_groups(const ExecContext *c, if (!c->supplementary_groups) return 0; + /* + * If SupplementaryGroups= was passed then NGROUPS_MAX has to + * be positive, otherwise fail. + */ + errno = 0; + ngroups_max = (int) sysconf(_SC_NGROUPS_MAX); + if (ngroups_max <= 0) { + if (errno > 0) + return -errno; + else + return -EOPNOTSUPP; /* For all other values */ + } + /* * If user is given, then lookup GID and supplementary group list. * We avoid NSS lookups for gid=0. @@ -800,8 +813,6 @@ static int get_fixed_supplementary_groups(const ExecContext *c, keep_groups = true; } - assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0); - l_gids = new(gid_t, ngroups_max); if (!l_gids) return -ENOMEM; -- cgit v1.2.3-54-g00ecf From 6d7c761572a1a7630512c31ad8277728a7eadcb4 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Mon, 24 Oct 2016 14:44:01 +0300 Subject: networkd-ndisc: Don't add NDisc route for local address (#4467) When systemd-networkd is run on the same IPv6 enabled interface where radvd is announcing prefixes, a route is being set up pointing to the interface address. As this will fail with an invalid argument error, the link is marked as failed and the following message like the following will appear in in the logs: systemd-networkd[21459]: eth1: Could not set NDisc route or address: Invalid argument systemd-networkd[21459]: eth1: Failed Should the interface be required by systemd-networkd-wait-online, network-online.target will wait until its timeout hits thereby significantly delaying system startup. The fix is to check whether the gateway address obtained from NDisc messages is equal to any of the interface addresses on the same link and not set the NDisc route in that case. --- src/network/networkd-ndisc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index c2b7970623..b282634e4b 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -57,6 +57,8 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { unsigned preference; usec_t time_now; int r; + Address *address; + Iterator i; assert(link); assert(rt); @@ -75,6 +77,32 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { return; } + SET_FOREACH(address, link->addresses, i) { + if (!memcmp(&gateway, &address->in_addr.in6, + sizeof(address->in_addr.in6))) { + char buffer[INET6_ADDRSTRLEN]; + + log_link_debug(link, "No NDisc route added, gateway %s matches local address", + inet_ntop(AF_INET6, + &address->in_addr.in6, + buffer, sizeof(buffer))); + return; + } + } + + SET_FOREACH(address, link->addresses_foreign, i) { + if (!memcmp(&gateway, &address->in_addr.in6, + sizeof(address->in_addr.in6))) { + char buffer[INET6_ADDRSTRLEN]; + + log_link_debug(link, "No NDisc route added, gateway %s matches local address", + inet_ntop(AF_INET6, + &address->in_addr.in6, + buffer, sizeof(buffer))); + return; + } + } + r = sd_ndisc_router_get_preference(rt, &preference); if (r < 0) { log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m"); -- cgit v1.2.3-54-g00ecf From ec2ebfd524447caf14e63b49b3f63117b93c7c78 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Oct 2016 18:26:30 +0200 Subject: update-done: minor clean-ups This is a follow-up for fb8b0869a7bc30e23be175cf978df23192d59118, and makes a couple of minor clean-up changes: - The field name in the timestamp file is changed from "TimestampNSec=" to "TIMESTAMP_NSEC=". This is done simply to reflect the fact that we parse the file with the env var file parser, and hence the contents should better follow the usual capitalization of env vars, i.e. be all uppercase. - Needless negation of the errno parameter log_error_errno() and friends has been removed. - Instead of manually calculating the nsec remainder of the timestamp, use timespec_store(). - We now check whether we were able to write the timestamp file in full with fflush_and_check() the way we usually do it. --- src/shared/condition.c | 9 ++++----- src/update-done/update-done.c | 15 +++++++++------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/shared/condition.c b/src/shared/condition.c index f13fa6a9fd..69b4837e1f 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -329,9 +329,9 @@ static int condition_test_needs_update(Condition *c) { uint64_t timestamp; int r; - r = parse_env_file(p, NULL, "TimestampNSec", ×tamp_str, NULL); + r = parse_env_file(p, NULL, "TIMESTAMP_NSEC", ×tamp_str, NULL); if (r < 0) { - log_error_errno(-r, "Failed to parse timestamp file '%s', using mtime: %m", p); + log_error_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p); return true; } else if (r == 0) { log_debug("No data in timestamp file '%s', using mtime", p); @@ -340,12 +340,11 @@ static int condition_test_needs_update(Condition *c) { r = safe_atou64(timestamp_str, ×tamp); if (r < 0) { - log_error_errno(-r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", - timestamp_str, p); + log_error_errno(r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", timestamp_str, p); return true; } - other.st_mtim.tv_nsec = timestamp % NSEC_PER_SEC; + timespec_store(&other.st_mtim, timestamp); } return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec; diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c index 5cc5abfddf..48c2a3fff4 100644 --- a/src/update-done/update-done.c +++ b/src/update-done/update-done.c @@ -18,6 +18,7 @@ ***/ #include "fd-util.h" +#include "fileio.h" #include "io-util.h" #include "selinux-util.h" #include "util.h" @@ -32,8 +33,8 @@ static int apply_timestamp(const char *path, struct timespec *ts) { *ts, *ts }; - int fd = -1; _cleanup_fclose_ FILE *f = NULL; + int fd = -1; int r; assert(path); @@ -59,18 +60,20 @@ static int apply_timestamp(const char *path, struct timespec *ts) { return log_error_errno(errno, "Failed to create/open timestamp file %s: %m", path); } - f = fdopen(fd, "w"); + f = fdopen(fd, "we"); if (!f) { safe_close(fd); return log_error_errno(errno, "Failed to fdopen() timestamp file %s: %m", path); } (void) fprintf(f, - "%s" - "TimestampNSec=" NSEC_FMT "\n", - MESSAGE, timespec_load_nsec(ts)); + MESSAGE + "TIMESTAMP_NSEC=" NSEC_FMT "\n", + timespec_load_nsec(ts)); - fflush(f); + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write timestamp file: %m"); if (futimens(fd, twice) < 0) return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); -- cgit v1.2.3-54-g00ecf From f673b62df67dfa67ddfa4f5a72d78ea3c002278f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Oct 2016 20:03:51 +0200 Subject: core: simplify skip_seccomp_unavailable() a bit Let's prefer early-exit over deep-indented if blocks. Not behavioural change. --- src/core/execute.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 53356c3c06..b69297241b 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1185,13 +1185,14 @@ static void rename_process_from_path(const char *path) { #ifdef HAVE_SECCOMP static bool skip_seccomp_unavailable(const Unit* u, const char* msg) { - if (!is_seccomp_available()) { - log_open(); - log_unit_debug(u, "SECCOMP features not detected in the kernel, skipping %s", msg); - log_close(); - return true; - } - return false; + + if (is_seccomp_available()) + return false; + + log_open(); + log_unit_debug(u, "SECCOMP features not detected in the kernel, skipping %s", msg); + log_close(); + return true; } static int apply_seccomp(const Unit* u, const ExecContext *c) { -- cgit v1.2.3-54-g00ecf From e0f3720e399573134657458f4c8bd20c68fc092a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Oct 2016 20:05:49 +0200 Subject: core: move misplaced comment to the right place --- src/core/execute.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index b69297241b..e63a12f934 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1891,9 +1891,9 @@ static int setup_private_users(uid_t uid, gid_t gid) { asprintf(&uid_map, "0 0 1\n" /* Map root → root */ UID_FMT " " UID_FMT " 1\n", /* Map $UID → $UID */ - uid, uid); /* The case where the above is the same */ + uid, uid); else - uid_map = strdup("0 0 1\n"); + uid_map = strdup("0 0 1\n"); /* The case where the above is the same */ if (!uid_map) return -ENOMEM; -- cgit v1.2.3-54-g00ecf From 8130926d32d76193e98ba783ba932816f276bfad Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Oct 2016 21:50:05 +0200 Subject: core: rework syscall filter set handling A variety of fixes: - rename the SystemCallFilterSet structure to SyscallFilterSet. So far the main instance of it (the syscall_filter_sets[] array) used to abbreviate "SystemCall" as "Syscall". Let's stick to one of the two syntaxes, and not mix and match too wildly. Let's pick the shorter name in this case, as it is sufficiently well established to not confuse hackers reading this. - Export explicit indexes into the syscall_filter_sets[] array via an enum. This way, code that wants to make use of a specific filter set, can index it directly via the enum, instead of having to search for it. This makes apply_private_devices() in particular a lot simpler. - Provide two new helper calls in seccomp-util.c: syscall_filter_set_find() to find a set by its name, seccomp_add_syscall_filter_set() to add a set to a seccomp object. - Update SystemCallFilter= parser to use extract_first_word(). Let's work on deprecating FOREACH_WORD_QUOTED(). - Simplify apply_private_devices() using this functionality --- src/core/execute.c | 41 +-------------- src/core/load-fragment.c | 54 ++++++++++--------- src/shared/seccomp-util.c | 128 ++++++++++++++++++++++++++++++++++------------ src/shared/seccomp-util.h | 32 ++++++++++-- 4 files changed, 155 insertions(+), 100 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index e63a12f934..18bb67cda9 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1578,10 +1578,7 @@ finish: } static int apply_private_devices(Unit *u, const ExecContext *c) { - const SystemCallFilterSet *set; scmp_filter_ctx *seccomp; - const char *sys; - bool syscalls_found = false; int r; assert(c); @@ -1599,43 +1596,9 @@ static int apply_private_devices(Unit *u, const ExecContext *c) { if (r < 0) goto finish; - for (set = syscall_filter_sets; set->set_name; set++) - if (streq(set->set_name, "@raw-io")) { - syscalls_found = true; - break; - } - - /* We should never fail here */ - if (!syscalls_found) { - r = -EOPNOTSUPP; + r = seccomp_add_syscall_filter_set(seccomp, syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO, SCMP_ACT_ERRNO(EPERM)); + if (r < 0) goto finish; - } - - NULSTR_FOREACH(sys, set->value) { - int id; - bool add = true; - -#ifndef __NR_s390_pci_mmio_read - if (streq(sys, "s390_pci_mmio_read")) - add = false; -#endif -#ifndef __NR_s390_pci_mmio_write - if (streq(sys, "s390_pci_mmio_write")) - add = false; -#endif - - if (!add) - continue; - - id = seccomp_syscall_resolve_name(sys); - - r = seccomp_rule_add( - seccomp, - SCMP_ACT_ERRNO(EPERM), - id, 0); - if (r < 0) - goto finish; - } r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); if (r < 0) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 6f68e23340..118b39c1cf 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -2618,6 +2618,7 @@ int config_parse_documentation(const char *unit, } #ifdef HAVE_SECCOMP + static int syscall_filter_parse_one( const char *unit, const char *filename, @@ -2628,27 +2629,29 @@ static int syscall_filter_parse_one( bool warn) { int r; - if (*t == '@') { - const SystemCallFilterSet *set; + if (t[0] == '@') { + const SyscallFilterSet *set; + const char *i; - for (set = syscall_filter_sets; set->set_name; set++) - if (streq(set->set_name, t)) { - const char *sys; + set = syscall_filter_set_find(t); + if (!set) { + if (warn) + log_syntax(unit, LOG_WARNING, filename, line, 0, "Don't know system call group, ignoring: %s", t); + return 0; + } - NULSTR_FOREACH(sys, set->value) { - r = syscall_filter_parse_one(unit, filename, line, c, invert, sys, false); - if (r < 0) - return r; - } - break; - } + NULSTR_FOREACH(i, set->value) { + r = syscall_filter_parse_one(unit, filename, line, c, invert, i, false); + if (r < 0) + return r; + } } else { int id; id = seccomp_syscall_resolve_name(t); if (id == __NR_SCMP_ERROR) { if (warn) - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse system call, ignoring: %s", t); + log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse system call, ignoring: %s", t); return 0; } @@ -2662,8 +2665,9 @@ static int syscall_filter_parse_one( if (r < 0) return log_oom(); } else - set_remove(c->syscall_filter, INT_TO_PTR(id + 1)); + (void) set_remove(c->syscall_filter, INT_TO_PTR(id + 1)); } + return 0; } @@ -2682,8 +2686,7 @@ int config_parse_syscall_filter( ExecContext *c = data; Unit *u = userdata; bool invert = false; - const char *word, *state; - size_t l; + const char *p; int r; assert(filename); @@ -2722,19 +2725,24 @@ int config_parse_syscall_filter( } } - FOREACH_WORD_QUOTED(word, l, rvalue, state) { - _cleanup_free_ char *t = NULL; + p = rvalue; + for (;;) { + _cleanup_free_ char *word = NULL; - t = strndup(word, l); - if (!t) + r = extract_first_word(&p, &word, NULL, 0); + if (r == 0) + break; + if (r == -ENOMEM) return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + break; + } - r = syscall_filter_parse_one(unit, filename, line, c, invert, t, true); + r = syscall_filter_parse_one(unit, filename, line, c, invert, word, true); if (r < 0) return r; } - if (!isempty(state)) - log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); /* Turn on NNP, but only if it wasn't configured explicitly * before, and only if we are in user mode. */ diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 8116c7671f..1d51f3fd1f 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -26,6 +26,7 @@ #include "macro.h" #include "seccomp-util.h" #include "string-util.h" +#include "util.h" const char* seccomp_arch_to_string(uint32_t c) { @@ -132,28 +133,30 @@ bool is_seccomp_available(void) { return cached_enabled; } -const SystemCallFilterSet syscall_filter_sets[] = { - { +const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { + [SYSCALL_FILTER_SET_CLOCK] = { /* Clock */ - .set_name = "@clock", + .name = "@clock", .value = "adjtimex\0" "clock_adjtime\0" "clock_settime\0" "settimeofday\0" "stime\0" - }, { + }, + [SYSCALL_FILTER_SET_CPU_EMULATION] = { /* CPU emulation calls */ - .set_name = "@cpu-emulation", + .name = "@cpu-emulation", .value = "modify_ldt\0" "subpage_prot\0" "switch_endian\0" "vm86\0" "vm86old\0" - }, { + }, + [SYSCALL_FILTER_SET_DEBUG] = { /* Debugging/Performance Monitoring/Tracing */ - .set_name = "@debug", + .name = "@debug", .value = "lookup_dcookie\0" "perf_event_open\0" @@ -161,11 +164,14 @@ const SystemCallFilterSet syscall_filter_sets[] = { "process_vm_writev\0" "ptrace\0" "rtas\0" +#ifdef __NR_s390_runtime_instr "s390_runtime_instr\0" +#endif "sys_debug_setcontext\0" - }, { + }, + [SYSCALL_FILTER_SET_DEFAULT] = { /* Default list */ - .set_name = "@default", + .name = "@default", .value = "execve\0" "exit\0" @@ -173,9 +179,10 @@ const SystemCallFilterSet syscall_filter_sets[] = { "getrlimit\0" /* make sure processes can query stack size and such */ "rt_sigreturn\0" "sigreturn\0" - }, { + }, + [SYSCALL_FILTER_SET_IO_EVENT] = { /* Event loop use */ - .set_name = "@io-event", + .name = "@io-event", .value = "_newselect\0" "epoll_create1\0" @@ -191,9 +198,10 @@ const SystemCallFilterSet syscall_filter_sets[] = { "ppoll\0" "pselect6\0" "select\0" - }, { + }, + [SYSCALL_FILTER_SET_IPC] = { /* Message queues, SYSV IPC or other IPC: unusual */ - .set_name = "@ipc", + .name = "@ipc", .value = "ipc\0" "mq_getsetattr\0" "mq_notify\0" @@ -215,23 +223,26 @@ const SystemCallFilterSet syscall_filter_sets[] = { "shmctl\0" "shmdt\0" "shmget\0" - }, { + }, + [SYSCALL_FILTER_SET_KEYRING] = { /* Keyring */ - .set_name = "@keyring", + .name = "@keyring", .value = "add_key\0" "keyctl\0" "request_key\0" - }, { + }, + [SYSCALL_FILTER_SET_MODULE] = { /* Kernel module control */ - .set_name = "@module", + .name = "@module", .value = "delete_module\0" "finit_module\0" "init_module\0" - }, { + }, + [SYSCALL_FILTER_SET_MOUNT] = { /* Mounting */ - .set_name = "@mount", + .name = "@mount", .value = "chroot\0" "mount\0" @@ -239,9 +250,10 @@ const SystemCallFilterSet syscall_filter_sets[] = { "pivot_root\0" "umount2\0" "umount\0" - }, { + }, + [SYSCALL_FILTER_SET_NETWORK_IO] = { /* Network or Unix socket IO, should not be needed if not network facing */ - .set_name = "@network-io", + .name = "@network-io", .value = "accept4\0" "accept\0" @@ -264,9 +276,10 @@ const SystemCallFilterSet syscall_filter_sets[] = { "socket\0" "socketcall\0" "socketpair\0" - }, { + }, + [SYSCALL_FILTER_SET_OBSOLETE] = { /* Unusual, obsolete or unimplemented, some unknown even to libseccomp */ - .set_name = "@obsolete", + .name = "@obsolete", .value = "_sysctl\0" "afs_syscall\0" @@ -292,9 +305,10 @@ const SystemCallFilterSet syscall_filter_sets[] = { "uselib\0" "ustat\0" "vserver\0" - }, { + }, + [SYSCALL_FILTER_SET_PRIVILEGED] = { /* Nice grab-bag of all system calls which need superuser capabilities */ - .set_name = "@privileged", + .name = "@privileged", .value = "@clock\0" "@module\0" @@ -333,9 +347,10 @@ const SystemCallFilterSet syscall_filter_sets[] = { "swapon\0" "sysctl\0" "vhangup\0" - }, { + }, + [SYSCALL_FILTER_SET_PROCESS] = { /* Process control, execution, namespaces */ - .set_name = "@process", + .name = "@process", .value = "arch_prctl\0" "clone\0" @@ -349,19 +364,66 @@ const SystemCallFilterSet syscall_filter_sets[] = { "tkill\0" "unshare\0" "vfork\0" - }, { + }, + [SYSCALL_FILTER_SET_RAW_IO] = { /* Raw I/O ports */ - .set_name = "@raw-io", + .name = "@raw-io", .value = "ioperm\0" "iopl\0" "pciconfig_iobase\0" "pciconfig_read\0" "pciconfig_write\0" +#ifdef __NR_s390_pci_mmio_read "s390_pci_mmio_read\0" +#endif +#ifdef __NR_s390_pci_mmio_write "s390_pci_mmio_write\0" - }, { - .set_name = NULL, - .value = NULL - } +#endif + }, }; + +const SyscallFilterSet *syscall_filter_set_find(const char *name) { + unsigned i; + + if (isempty(name) || name[0] != '@') + return NULL; + + for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) + if (streq(syscall_filter_sets[i].name, name)) + return syscall_filter_sets + i; + + return NULL; +} + +int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action) { + const char *sys; + int r; + + assert(seccomp); + assert(set); + + NULSTR_FOREACH(sys, set->value) { + int id; + + if (sys[0] == '@') { + const SyscallFilterSet *other; + + other = syscall_filter_set_find(sys); + if (!other) + return -EINVAL; + + r = seccomp_add_syscall_filter_set(seccomp, other, action); + } else { + id = seccomp_syscall_resolve_name(sys); + if (id == __NR_SCMP_ERROR) + return -EINVAL; + + r = seccomp_rule_add(seccomp, action, id, 0); + } + if (r < 0) + return r; + } + + return 0; +} diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h index cca7c17912..34fd49c122 100644 --- a/src/shared/seccomp-util.h +++ b/src/shared/seccomp-util.h @@ -29,9 +29,31 @@ int seccomp_add_secondary_archs(scmp_filter_ctx *c); bool is_seccomp_available(void); -typedef struct SystemCallFilterSet { - const char *set_name; +typedef struct SyscallFilterSet { + const char *name; const char *value; -} SystemCallFilterSet; - -extern const SystemCallFilterSet syscall_filter_sets[]; +} SyscallFilterSet; + +enum { + SYSCALL_FILTER_SET_CLOCK, + SYSCALL_FILTER_SET_CPU_EMULATION, + SYSCALL_FILTER_SET_DEBUG, + SYSCALL_FILTER_SET_DEFAULT, + SYSCALL_FILTER_SET_IO_EVENT, + SYSCALL_FILTER_SET_IPC, + SYSCALL_FILTER_SET_KEYRING, + SYSCALL_FILTER_SET_MODULE, + SYSCALL_FILTER_SET_MOUNT, + SYSCALL_FILTER_SET_NETWORK_IO, + SYSCALL_FILTER_SET_OBSOLETE, + SYSCALL_FILTER_SET_PRIVILEGED, + SYSCALL_FILTER_SET_PROCESS, + SYSCALL_FILTER_SET_RAW_IO, + _SYSCALL_FILTER_SET_MAX +}; + +extern const SyscallFilterSet syscall_filter_sets[]; + +const SyscallFilterSet *syscall_filter_set_find(const char *name); + +int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action); -- cgit v1.2.3-54-g00ecf From 25a8d8a0cb297f75b6b9fd3cc15747ba7f56031e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Oct 2016 20:12:33 +0200 Subject: core: rework apply_protect_kernel_modules() to use seccomp_add_syscall_filter_set() Let's simplify this call, by making use of the new infrastructure. This is actually more in line with Djalal's original patch but instead of search the filter set in the array by its name we can now use the set index and jump directly to it. --- src/core/execute.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 18bb67cda9..f435a079c7 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1534,19 +1534,14 @@ finish: } static int apply_protect_kernel_modules(Unit *u, const ExecContext *c) { - static const int module_syscalls[] = { - SCMP_SYS(delete_module), - SCMP_SYS(finit_module), - SCMP_SYS(init_module), - }; scmp_filter_ctx *seccomp; - unsigned i; + const char *sys; int r; assert(c); - /* Turn of module syscalls on ProtectKernelModules=yes */ + /* Turn off module syscalls on ProtectKernelModules=yes */ if (skip_seccomp_unavailable(u, "ProtectKernelModules=")) return 0; @@ -1559,12 +1554,9 @@ static int apply_protect_kernel_modules(Unit *u, const ExecContext *c) { if (r < 0) goto finish; - for (i = 0; i < ELEMENTSOF(module_syscalls); i++) { - r = seccomp_rule_add(seccomp, SCMP_ACT_ERRNO(EPERM), - module_syscalls[i], 0); - if (r < 0) - goto finish; - } + r = seccomp_add_syscall_filter_set(seccomp, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM)); + if (r < 0) + goto finish; r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); if (r < 0) -- cgit v1.2.3-54-g00ecf From 8d7b0c8fd780e88ab5a6d1d79e09e27247245bee Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Oct 2016 20:28:05 +0200 Subject: seccomp: add new seccomp_init_conservative() helper This adds a new seccomp_init_conservative() helper call that is mostly just a wrapper around seccomp_init(), but turns off NNP and adds in all secondary archs, for best compatibility with everything else. Pretty much all of our code used the very same constructs for these three steps, hence unifying this in one small function makes things a lot shorter. This also changes incorrect usage of the "scmp_filter_ctx" type at various places. libseccomp defines it as typedef to "void*", i.e. it is a pointer type (pretty poor choice already!) that casts implicitly to and from all other pointer types (even poorer choice: you defined a confusing type now, and don't even gain any bit of type safety through it...). A lot of the code assumed the type would refer to a structure, and hence aded additional "*" here and there. Remove that. --- src/core/execute.c | 88 ++++++++++----------------------------------- src/nspawn/nspawn-seccomp.c | 18 ++-------- src/shared/seccomp-util.c | 30 ++++++++++++++-- src/shared/seccomp-util.h | 4 ++- 4 files changed, 53 insertions(+), 87 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index f435a079c7..668504c5cf 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1197,7 +1197,7 @@ static bool skip_seccomp_unavailable(const Unit* u, const char* msg) { static int apply_seccomp(const Unit* u, const ExecContext *c) { uint32_t negative_action, action; - scmp_filter_ctx *seccomp; + scmp_filter_ctx seccomp; Iterator i; void *id; int r; @@ -1248,7 +1248,7 @@ finish: } static int apply_address_families(const Unit* u, const ExecContext *c) { - scmp_filter_ctx *seccomp; + scmp_filter_ctx seccomp; Iterator i; int r; @@ -1257,13 +1257,9 @@ static int apply_address_families(const Unit* u, const ExecContext *c) { if (skip_seccomp_unavailable(u, "RestrictAddressFamilies=")) return 0; - seccomp = seccomp_init(SCMP_ACT_ALLOW); - if (!seccomp) - return -ENOMEM; - - r = seccomp_add_secondary_archs(seccomp); + r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW); if (r < 0) - goto finish; + return r; if (c->address_families_whitelist) { int af, first = 0, last = 0; @@ -1360,10 +1356,6 @@ static int apply_address_families(const Unit* u, const ExecContext *c) { } } - r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); - if (r < 0) - goto finish; - r = seccomp_load(seccomp); finish: @@ -1372,7 +1364,7 @@ finish: } static int apply_memory_deny_write_execute(const Unit* u, const ExecContext *c) { - scmp_filter_ctx *seccomp; + scmp_filter_ctx seccomp; int r; assert(c); @@ -1380,13 +1372,9 @@ static int apply_memory_deny_write_execute(const Unit* u, const ExecContext *c) if (skip_seccomp_unavailable(u, "MemoryDenyWriteExecute=")) return 0; - seccomp = seccomp_init(SCMP_ACT_ALLOW); - if (!seccomp) - return -ENOMEM; - - r = seccomp_add_secondary_archs(seccomp); + r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW); if (r < 0) - goto finish; + return r; r = seccomp_rule_add( seccomp, @@ -1406,10 +1394,6 @@ static int apply_memory_deny_write_execute(const Unit* u, const ExecContext *c) if (r < 0) goto finish; - r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); - if (r < 0) - goto finish; - r = seccomp_load(seccomp); finish: @@ -1424,7 +1408,7 @@ static int apply_restrict_realtime(const Unit* u, const ExecContext *c) { SCHED_IDLE, }; - scmp_filter_ctx *seccomp; + scmp_filter_ctx seccomp; unsigned i; int r, p, max_policy = 0; @@ -1433,13 +1417,9 @@ static int apply_restrict_realtime(const Unit* u, const ExecContext *c) { if (skip_seccomp_unavailable(u, "RestrictRealtime=")) return 0; - seccomp = seccomp_init(SCMP_ACT_ALLOW); - if (!seccomp) - return -ENOMEM; - - r = seccomp_add_secondary_archs(seccomp); + r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW); if (r < 0) - goto finish; + return r; /* Determine the highest policy constant we want to allow */ for (i = 0; i < ELEMENTSOF(permitted_policies); i++) @@ -1483,10 +1463,6 @@ static int apply_restrict_realtime(const Unit* u, const ExecContext *c) { if (r < 0) goto finish; - r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); - if (r < 0) - goto finish; - r = seccomp_load(seccomp); finish: @@ -1495,7 +1471,7 @@ finish: } static int apply_protect_sysctl(Unit *u, const ExecContext *c) { - scmp_filter_ctx *seccomp; + scmp_filter_ctx seccomp; int r; assert(c); @@ -1506,13 +1482,9 @@ static int apply_protect_sysctl(Unit *u, const ExecContext *c) { if (skip_seccomp_unavailable(u, "ProtectKernelTunables=")) return 0; - seccomp = seccomp_init(SCMP_ACT_ALLOW); - if (!seccomp) - return -ENOMEM; - - r = seccomp_add_secondary_archs(seccomp); + r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW); if (r < 0) - goto finish; + return r; r = seccomp_rule_add( seccomp, @@ -1522,10 +1494,6 @@ static int apply_protect_sysctl(Unit *u, const ExecContext *c) { if (r < 0) goto finish; - r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); - if (r < 0) - goto finish; - r = seccomp_load(seccomp); finish: @@ -1534,9 +1502,7 @@ finish: } static int apply_protect_kernel_modules(Unit *u, const ExecContext *c) { - - scmp_filter_ctx *seccomp; - const char *sys; + scmp_filter_ctx seccomp; int r; assert(c); @@ -1546,22 +1512,14 @@ static int apply_protect_kernel_modules(Unit *u, const ExecContext *c) { if (skip_seccomp_unavailable(u, "ProtectKernelModules=")) return 0; - seccomp = seccomp_init(SCMP_ACT_ALLOW); - if (!seccomp) - return -ENOMEM; - - r = seccomp_add_secondary_archs(seccomp); + r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW); if (r < 0) - goto finish; + return r; r = seccomp_add_syscall_filter_set(seccomp, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM)); if (r < 0) goto finish; - r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); - if (r < 0) - goto finish; - r = seccomp_load(seccomp); finish: @@ -1570,7 +1528,7 @@ finish: } static int apply_private_devices(Unit *u, const ExecContext *c) { - scmp_filter_ctx *seccomp; + scmp_filter_ctx seccomp; int r; assert(c); @@ -1580,22 +1538,14 @@ static int apply_private_devices(Unit *u, const ExecContext *c) { if (skip_seccomp_unavailable(u, "PrivateDevices=")) return 0; - seccomp = seccomp_init(SCMP_ACT_ALLOW); - if (!seccomp) - return -ENOMEM; - - r = seccomp_add_secondary_archs(seccomp); + r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW); if (r < 0) - goto finish; + return r; r = seccomp_add_syscall_filter_set(seccomp, syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO, SCMP_ACT_ERRNO(EPERM)); if (r < 0) goto finish; - r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); - if (r < 0) - goto finish; - r = seccomp_load(seccomp); finish: diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c index 44a0b397ab..03a397d30c 100644 --- a/src/nspawn/nspawn-seccomp.c +++ b/src/nspawn/nspawn-seccomp.c @@ -135,15 +135,9 @@ int setup_seccomp(uint64_t cap_list_retain) { return 0; } - seccomp = seccomp_init(SCMP_ACT_ALLOW); - if (!seccomp) - return log_oom(); - - r = seccomp_add_secondary_archs(seccomp); - if (r < 0) { - log_error_errno(r, "Failed to add secondary archs to seccomp filter: %m"); - goto finish; - } + r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW); + if (r < 0) + return log_error_errno(r, "Failed to allocate seccomp object: %m"); r = seccomp_add_default_syscall_filter(seccomp, cap_list_retain); if (r < 0) @@ -171,12 +165,6 @@ int setup_seccomp(uint64_t cap_list_retain) { goto finish; } - r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); - if (r < 0) { - log_error_errno(r, "Failed to unset NO_NEW_PRIVS: %m"); - goto finish; - } - r = seccomp_load(seccomp); if (r < 0) { log_error_errno(r, "Failed to install seccomp audit filter: %m"); diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 1d51f3fd1f..0b9fa47c44 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -74,7 +74,34 @@ int seccomp_arch_from_string(const char *n, uint32_t *ret) { return 0; } -int seccomp_add_secondary_archs(scmp_filter_ctx *c) { +int seccomp_init_conservative(scmp_filter_ctx *ret, uint32_t default_action) { + scmp_filter_ctx seccomp; + int r; + + /* Much like seccomp_init(), but tries to be a bit more conservative in its defaults: all secondary archs are + * added by default, and NNP is turned off. */ + + seccomp = seccomp_init(default_action); + if (!seccomp) + return -ENOMEM; + + r = seccomp_add_secondary_archs(seccomp); + if (r < 0) + goto finish; + + r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); + if (r < 0) + goto finish; + + *ret = seccomp; + return 0; + +finish: + seccomp_release(seccomp); + return r; +} + +int seccomp_add_secondary_archs(scmp_filter_ctx c) { #if defined(__i386__) || defined(__x86_64__) int r; @@ -111,7 +138,6 @@ int seccomp_add_secondary_archs(scmp_filter_ctx *c) { #endif return 0; - } static bool is_basic_seccomp_available(void) { diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h index 34fd49c122..2de429a772 100644 --- a/src/shared/seccomp-util.h +++ b/src/shared/seccomp-util.h @@ -25,7 +25,9 @@ const char* seccomp_arch_to_string(uint32_t c); int seccomp_arch_from_string(const char *n, uint32_t *ret); -int seccomp_add_secondary_archs(scmp_filter_ctx *c); +int seccomp_init_conservative(scmp_filter_ctx *ret, uint32_t default_action); + +int seccomp_add_secondary_archs(scmp_filter_ctx c); bool is_seccomp_available(void); -- cgit v1.2.3-54-g00ecf From 60f547cf684d27e8c0e7ff44663650e90f9e0bcf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Oct 2016 21:15:43 +0200 Subject: seccomp: two fixes for the syscall set tables "oldumount()" is not a syscall, but simply a wrapper for it, the actual syscall nr is called "umount" (and the nr of umount() is called umount2 internally). "sysctl()" is not a syscall, but "_syscall()" is. Fix this in the table. Without these changes libseccomp cannot actually translate the tables in full. This wasn't noticed before as the code was written defensively for this case. --- src/shared/seccomp-util.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 0b9fa47c44..f1e9de05b2 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -272,7 +272,6 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { .value = "chroot\0" "mount\0" - "oldumount\0" "pivot_root\0" "umount2\0" "umount\0" @@ -371,7 +370,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "setuid\0" "swapoff\0" "swapon\0" - "sysctl\0" + "_sysctl\0" "vhangup\0" }, [SYSCALL_FILTER_SET_PROCESS] = { -- cgit v1.2.3-54-g00ecf From a3be2849b2570482757f83181b999febbfc7bbef Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Oct 2016 21:18:46 +0200 Subject: seccomp: add new helper call seccomp_load_filter_set() This allows us to unify most of the code in apply_protect_kernel_modules() and apply_private_devices(). --- src/core/execute.c | 34 ++-------------------------------- src/shared/seccomp-util.c | 24 ++++++++++++++++++++++++ src/shared/seccomp-util.h | 2 ++ 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 668504c5cf..5e7d7c25d7 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1502,9 +1502,6 @@ finish: } static int apply_protect_kernel_modules(Unit *u, const ExecContext *c) { - scmp_filter_ctx seccomp; - int r; - assert(c); /* Turn off module syscalls on ProtectKernelModules=yes */ @@ -1512,25 +1509,10 @@ static int apply_protect_kernel_modules(Unit *u, const ExecContext *c) { if (skip_seccomp_unavailable(u, "ProtectKernelModules=")) return 0; - r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW); - if (r < 0) - return r; - - r = seccomp_add_syscall_filter_set(seccomp, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM)); - if (r < 0) - goto finish; - - r = seccomp_load(seccomp); - -finish: - seccomp_release(seccomp); - return r; + return seccomp_load_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM)); } static int apply_private_devices(Unit *u, const ExecContext *c) { - scmp_filter_ctx seccomp; - int r; - assert(c); /* If PrivateDevices= is set, also turn off iopl and all @raw-io syscalls. */ @@ -1538,19 +1520,7 @@ static int apply_private_devices(Unit *u, const ExecContext *c) { if (skip_seccomp_unavailable(u, "PrivateDevices=")) return 0; - r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW); - if (r < 0) - return r; - - r = seccomp_add_syscall_filter_set(seccomp, syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO, SCMP_ACT_ERRNO(EPERM)); - if (r < 0) - goto finish; - - r = seccomp_load(seccomp); - -finish: - seccomp_release(seccomp); - return r; + return seccomp_load_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO, SCMP_ACT_ERRNO(EPERM)); } #endif diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index f1e9de05b2..6252cd16a6 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -452,3 +452,27 @@ int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterS return 0; } + +int seccomp_load_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action) { + scmp_filter_ctx seccomp; + int r; + + assert(set); + + /* The one-stop solution: allocate a seccomp object, add a filter to it, and apply it */ + + r = seccomp_init_conservative(&seccomp, default_action); + if (r < 0) + return r; + + r = seccomp_add_syscall_filter_set(seccomp, set, action); + if (r < 0) + goto finish; + + r = seccomp_load(seccomp); + +finish: + seccomp_release(seccomp); + return r; + +} diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h index 2de429a772..667687b14f 100644 --- a/src/shared/seccomp-util.h +++ b/src/shared/seccomp-util.h @@ -59,3 +59,5 @@ extern const SyscallFilterSet syscall_filter_sets[]; const SyscallFilterSet *syscall_filter_set_find(const char *name); int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action); + +int seccomp_load_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action); -- cgit v1.2.3-54-g00ecf From f6281133def1da2d7ac875b8cf5af5c32bc63fd8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Oct 2016 21:48:10 +0200 Subject: seccomp: add test-seccomp test tool This validates the system call set table and many of our seccomp-util.c APIs. --- Makefile.am | 11 +++++ src/shared/seccomp-util.h | 1 + src/test/test-seccomp.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 src/test/test-seccomp.c diff --git a/Makefile.am b/Makefile.am index 18a5f4a82a..8ef3b42c41 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1570,6 +1570,11 @@ tests += \ test-acl-util endif +if HAVE_SECCOMP +tests += \ + test-seccomp +endif + EXTRA_DIST += \ test/a.service \ test/basic.target \ @@ -2038,6 +2043,12 @@ test_acl_util_SOURCES = \ test_acl_util_LDADD = \ libsystemd-shared.la +test_seccomp_SOURCES = \ + src/test/test-seccomp.c + +test_seccomp_LDADD = \ + libsystemd-shared.la + test_namespace_LDADD = \ libcore.la diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h index 667687b14f..8050fc6fbf 100644 --- a/src/shared/seccomp-util.h +++ b/src/shared/seccomp-util.h @@ -20,6 +20,7 @@ ***/ #include +#include #include const char* seccomp_arch_to_string(uint32_t c); diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c new file mode 100644 index 0000000000..0060ecdf02 --- /dev/null +++ b/src/test/test-seccomp.c @@ -0,0 +1,103 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "fd-util.h" +#include "macro.h" +#include "process-util.h" +#include "seccomp-util.h" + +static void test_seccomp_arch_to_string(void) { + uint32_t a, b; + const char *name; + + a = seccomp_arch_native(); + assert_se(a > 0); + name = seccomp_arch_to_string(a); + assert_se(name); + assert_se(seccomp_arch_from_string(name, &b) >= 0); + assert_se(a == b); +} + +static void test_syscall_filter_set_find(void) { + assert_se(!syscall_filter_set_find(NULL)); + assert_se(!syscall_filter_set_find("")); + assert_se(!syscall_filter_set_find("quux")); + assert_se(!syscall_filter_set_find("@quux")); + + assert_se(syscall_filter_set_find("@clock") == syscall_filter_sets + SYSCALL_FILTER_SET_CLOCK); + assert_se(syscall_filter_set_find("@default") == syscall_filter_sets + SYSCALL_FILTER_SET_DEFAULT); + assert_se(syscall_filter_set_find("@raw-io") == syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO); +} + +static void test_filter_sets(void) { + unsigned i; + int r; + + if (!is_seccomp_available()) + return; + + if (geteuid() != 0) + return; + + for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { + pid_t pid; + + log_info("Testing %s", syscall_filter_sets[i].name); + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { /* Child? */ + int fd; + + if (i == SYSCALL_FILTER_SET_DEFAULT) /* if we look at the default set, whitelist instead of blacklist */ + r = seccomp_load_filter_set(SCMP_ACT_ERRNO(EPERM), syscall_filter_sets + i, SCMP_ACT_ALLOW); + else + r = seccomp_load_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EPERM)); + if (r < 0) + _exit(EXIT_FAILURE); + + /* Test the sycall filter with one random system call */ + fd = eventfd(0, EFD_NONBLOCK|EFD_CLOEXEC); + if (IN_SET(i, SYSCALL_FILTER_SET_IO_EVENT, SYSCALL_FILTER_SET_DEFAULT)) + assert_se(fd < 0 && errno == EPERM); + else { + assert_se(fd >= 0); + safe_close(fd); + } + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_warn(syscall_filter_sets[i].name, pid, true) == EXIT_SUCCESS); + } +} + +int main(int argc, char *argv[]) { + + test_seccomp_arch_to_string(); + test_syscall_filter_set_find(); + test_filter_sets(); + + return 0; +} -- cgit v1.2.3-54-g00ecf From 171ae2cd86390c17d51121f9dff607911b888c5a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Oct 2016 20:15:18 +0200 Subject: Various additions to NEWS --- NEWS | 99 +++++++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 27 deletions(-) diff --git a/NEWS b/NEWS index 87cc4f48c0..2a1edbe766 100644 --- a/NEWS +++ b/NEWS @@ -35,14 +35,14 @@ CHANGES WITH 232 in spe ProtectSystem=strict enabled, so they are not able to make any permanent modifications to the system. - The nss-systemd module also always resolves root and nobody, making + * The nss-systemd module also always resolves root and nobody, making it possible to have no /etc/passwd or /etc/group files in minimal - container systems. + container or chroot environments. * Services may be started with their own user namespace using the new - PrivateUsers= option. Only root, nobody, and the uid/gid under which - the service is running are mapped. All other users are mapped to - nobody. + boolean PrivateUsers= option. Only root, nobody, and the uid/gid + under which the service is running are mapped. All other users are + mapped to nobody. * Support for the cgroup namespace has been added to systemd-nspawn. If supported by kernel, the container system started by systemd-nspawn @@ -57,12 +57,22 @@ CHANGES WITH 232 in spe options. This controller requires out-of-tree patches for the kernel and the support is provisional. - * .automount units may now be transient. - - * systemd-mount is a new tool which wraps mount(8) to pull in - additional dependencies through transient .mount and .automount - units. For example, this automatically runs fsck on the block device - before mounting, and allows the automount logic to be used. + * Mount and automount units may now be created transiently + (i.e. dynamically at runtime via the bus API, instead of requiring + unit files in the file system). + + * systemd-mount is a new tool which may mount file systems – much like + mount(8), optionally pulling in additional dependencies through + transient .mount and .automount units. For example, this tool + automatically runs fsck on a backing block device before mounting, + and allows the automount logic to be used dynamically from the + command line for establishing mount points. This tool is particularly + useful when dealing with removable media, as it will ensure fsck is + run – if necessary – before the first access and that the file system + is quickly unmounted after each access by utilizing the automount + logic. This maximizes the chance that the file system on the + removable media stays in a clean state, and if it isn't in a clean + state is fixed automatically. * LazyUnmount=yes option for mount units has been added to expose the umount --lazy option. Similarly, ForceUnmount=yes exposes the --force @@ -75,6 +85,12 @@ CHANGES WITH 232 in spe mount the EFI partition on systems where /boot is used for something else. + * When operating on GPT disk images for containers, systemd-nspawn will + now mount the ESP to /boot or /efi according to the same rules as PID + 1 running on a host. This allows tools like "bootctl" to operate + correctly within such containers, in order to make container images + bootable on physical systems. + * disk/by-id and disk/by-path symlinks are now created for NVMe drives. * Two new user session targets have been added to support running @@ -95,7 +111,7 @@ CHANGES WITH 232 in spe the top of the process hierarchy (which is usually the init process of the container). - * systemd-journal-gatewayd learned the --directory option to serve + * systemd-journal-gatewayd learned the --directory= option to serve files from the specified location. * journalctl --root=… can be used to peruse the journal in the @@ -112,23 +128,26 @@ CHANGES WITH 232 in spe a click rate that is different than the one for the vertical wheel. * systemd-run gained a new --wait option that makes service execution - synchronous. + synchronous. (Specifically, the command will not return until the + specified service binary exited.) - systemctl gained a new --wait option that causes the start command to + * systemctl gained a new --wait option that causes the start command to wait until the units being started have terminated again. - * A new journal output mode "short-full" has been added which uses + * A new journal output mode "short-full" has been added which displays timestamps with abbreviated English day names and adds a timezone - suffix. Those timestamps include more information and can be parsed - by journalctl. + suffix. Those timestamps include more information than the default + "short" output mode, and can be passed directly to journalctl's + --since= and --until= options. * /etc/resolv.conf will be bind-mounted into containers started by systemd-nspawn, if possible, so any changes to resolv.conf contents are automatically propagated to the container. * The number of instances for socket-activated services originating - from a single IP can be limited with MaxConnectionsPerSource=, - extending the existing setting of MaxConnections. + from a single IP address can be limited with + MaxConnectionsPerSource=, extending the existing setting of + MaxConnections=. * systemd-networkd gained support for vcan ("Virtual CAN") interface configuration. @@ -143,21 +162,23 @@ CHANGES WITH 232 in spe GenericReceiveOffload=, LargeReceiveOffload= options in the [Link] section of .link files. - Spanning Tree Protocol enablement, Priority, Aging Time, and the - Default Port VLAN ID can be configured for bridge devices using the - new STP=, Priority=, AgeingTimeSec=, and DefaultPVID= settings in the - [Bridge] section of .netdev files. + * The Spanning Tree Protocol, Priority, Aging Time, and the Default + Port VLAN ID can be configured for bridge devices using the new STP=, + Priority=, AgeingTimeSec=, and DefaultPVID= settings in the [Bridge] + section of .netdev files. - The route table to which routes received over DHCP or RA should be + * The route table to which routes received over DHCP or RA should be added can be configured with the new RouteTable= option in the [DHCP] and [IPv6AcceptRA] sections of .network files. - Address Resolution Protocol can be disabled on links managed by + * The Address Resolution Protocol can be disabled on links managed by systemd-networkd using the ARP=no setting in the [Link] section of .network files. - * $SERVICE_RESULT, $EXIT_CODE, $EXIT_STATUS are set for ExecStop= and - ExecStopPost= commands. + * New environment variables $SERVICE_RESULT, $EXIT_CODE and + $EXIT_STATUS are set for ExecStop= and ExecStopPost= commands, and + encode information about the result and exit codes of the current + service runtime cycle. * systemd-sysctl will now configure kernel parameters in the order they occur in the configuration files. This matches what sysctl @@ -184,6 +205,30 @@ CHANGES WITH 232 in spe $SYSTEMD_NSPAWN_SHARE_NS_UTS may be used to control the unsharing of individual namespaces. + * "machinectl list" now shows the IP address of running containers in + the output, as well as OS release information. + + * "loginctl list" now shows the TTY of each session in the output. + + * sd-bus gained new API calls sd_bus_track_set_recursive(), + sd_bus_track_get_recursive(), sd_bus_track_count_name(), + sd_bus_track_count_sender(). They permit usage of sd_bus_track peer + tracking objects in a "recursive" mode, where a single client can be + counted multiple times, if it takes multiple references. + + * sd-bus gained new API calls sd_bus_set_exit_on_disconnect() and + sd_bus_get_exit_on_disconnect(). They may be used to to make a + process using sd-bus automatically exit if the bus connection is + severed. + + * Bus clients of the service manager may now "pin" loaded units into + memory, by taking an explicit reference on them. This is useful to + ensure the client can retrieve runtime data about the service even + after the service completed execution. Taking such a reference is + available only for privileged clients and should be helpful to watch + running services in a race-free manner, and in particular collect + information about exit statuses and results. + CHANGES WITH 231: * In service units the various ExecXYZ= settings have been extended -- cgit v1.2.3-54-g00ecf From 413b05ccac40a9d53d278a3a17061286ea44e26d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Oct 2016 18:49:27 +0200 Subject: resolved: properly check for the root domain Fix-up for #4164 --- src/resolve/resolved-dns-server.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 7282848e35..22c64e8491 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -575,8 +575,7 @@ void dns_server_warn_downgrade(DnsServer *server) { server->warned_downgrade = true; } -bool dns_server_limited_domains(DnsServer *server) -{ +bool dns_server_limited_domains(DnsServer *server) { DnsSearchDomain *domain; bool domain_restricted = false; @@ -589,7 +588,7 @@ bool dns_server_limited_domains(DnsServer *server) if (domain->route_only) { domain_restricted = true; /* ~. means "any domain", thus it is a global server */ - if (streq(DNS_SEARCH_DOMAIN_NAME(domain), ".")) + if (dns_name_is_root(DNS_SEARCH_DOMAIN_NAME(domain))) return false; } -- cgit v1.2.3-54-g00ecf From 344874fcd0a3fc1f9bc6cdf34ecaf537c10a3ad3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Oct 2016 18:50:43 +0200 Subject: nss-resolve: be a bit more careful with returning NSS_STATUS_NOTFOUND Let's tighten the cases when our module returns NSS_STATUS_NOTFOUND. Let's do so only if we actually managed to talk to resolved. In all other cases stick to NSS_STATUS_UNAVAIL as before, as it clearly indicates that our module or the system is borked, and the "dns" fallback should really take place. In particular this fixes the 2nd-level fallback from our own dlopen() based fallback handling. In this case we really should return UNAVAIL so that the caller can apply its own fallback still. Fix-up for d7247512a904f1dd74125859d8da66166c2a6933. Note that our own dlopen() based fallback is pretty much redundant now if nsswitch.conf is configured like this: hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname In a future release we should probably drop our internal fallback then, in favour of this nsswitch.conf-based one. --- src/nss-resolve/nss-resolve.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c index eea91e3e88..d46a3afe91 100644 --- a/src/nss-resolve/nss-resolve.c +++ b/src/nss-resolve/nss-resolve.c @@ -121,6 +121,7 @@ enum nss_status _nss_resolve_gethostbyname4_r( _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + enum nss_status ret = NSS_STATUS_UNAVAIL; const char *canonical = NULL; size_t l, ms, idx; char *r_name; @@ -167,6 +168,10 @@ enum nss_status _nss_resolve_gethostbyname4_r( if (bus_error_shall_fallback(&error)) goto fallback; + /* Treat all other error conditions as NOTFOUND, and fail. This includes DNSSEC errors and + suchlike. (We don't use UNAVAIL in this case so that the nsswitch.conf configuration can distuingish + such executed but negative replies from complete failure to talk to resolved. */ + ret = NSS_STATUS_NOTFOUND; goto fail; } @@ -279,12 +284,9 @@ fallback: } fail: - /* When we arrive here, resolved runs and has answered (fallback to - * "dns" is handled earlier). So we have a definitive "no" answer and - * should not fall back to subsequent NSS modules via "UNAVAIL". */ *errnop = -r; *h_errnop = NO_RECOVERY; - return NSS_STATUS_NOTFOUND; + return ret; } enum nss_status _nss_resolve_gethostbyname3_r( @@ -300,6 +302,7 @@ enum nss_status _nss_resolve_gethostbyname3_r( _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *r_name, *r_aliases, *r_addr, *r_addr_list; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + enum nss_status ret = NSS_STATUS_UNAVAIL; size_t l, idx, ms, alen; const char *canonical; int c, r, i = 0; @@ -353,6 +356,7 @@ enum nss_status _nss_resolve_gethostbyname3_r( if (bus_error_shall_fallback(&error)) goto fallback; + ret = NSS_STATUS_NOTFOUND; goto fail; } @@ -479,7 +483,7 @@ fallback: fail: *errnop = -r; *h_errnop = NO_RECOVERY; - return NSS_STATUS_NOTFOUND; + return ret; } enum nss_status _nss_resolve_gethostbyaddr2_r( @@ -494,6 +498,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r( _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; char *r_name, *r_aliases, *r_addr, *r_addr_list; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + enum nss_status ret = NSS_STATUS_UNAVAIL; unsigned c = 0, i = 0; size_t ms = 0, idx; const char *n; @@ -560,7 +565,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r( if (bus_error_shall_fallback(&error)) goto fallback; - + ret = NSS_STATUS_NOTFOUND; goto fail; } @@ -669,7 +674,7 @@ fallback: fail: *errnop = -r; *h_errnop = NO_RECOVERY; - return NSS_STATUS_NOTFOUND; + return ret; } NSS_GETHOSTBYNAME_FALLBACKS(resolve); -- cgit v1.2.3-54-g00ecf From 75555c2824fde73bde83f78d160a4f50482bc160 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Oct 2016 18:58:03 +0200 Subject: man: sync up the suggested nsswitch.conf configuration for our four NSS modules This unifies the suggested nsswitch.conf configuration for our four NSS modules to this: hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname Note that this restores "myhostname" to the suggested configuration of nss-resolve for the time being, undoing 4484e1792b64b01614f04b7bde97bf019f601bf9. "myhostname" should probably be dropped eventually, but when we do this we should do it in full, and not only drop it from the suggested nsswitch.conf for one of the modules, but also drop it in source and stop referring to it altogether. Note that nss-resolve doesn't replace nss-myhostname in full: the former only works if D-Bus/resolved is available for resolving the local hostname, the latter works in all cases even if D-Bus or resolved are not in operation, hence there's some value in keeping the line as it is right now. Note that neither dns nor myhostname are considered at all with the above configuration unless the resolve module actually returns UNAVAIL. Thus, even though handling of local hostname resolving is implemented twice this way it is only executed once for each lookup. --- man/nss-myhostname.xml | 2 +- man/nss-mymachines.xml | 2 +- man/nss-resolve.xml | 2 +- man/nss-systemd.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/man/nss-myhostname.xml b/man/nss-myhostname.xml index b1daaba02b..c25476ecc8 100644 --- a/man/nss-myhostname.xml +++ b/man/nss-myhostname.xml @@ -110,7 +110,7 @@ group: compat mymachines systemd shadow: compat -hosts: files mymachines resolve myhostname +hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname networks: files protocols: db files diff --git a/man/nss-mymachines.xml b/man/nss-mymachines.xml index a70119e256..00bcc53ec0 100644 --- a/man/nss-mymachines.xml +++ b/man/nss-mymachines.xml @@ -86,7 +86,7 @@ group: compat mymachines systemd shadow: compat -hosts: files mymachines resolve myhostname +hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname networks: files protocols: db files diff --git a/man/nss-resolve.xml b/man/nss-resolve.xml index d66e8ba521..9f24f65019 100644 --- a/man/nss-resolve.xml +++ b/man/nss-resolve.xml @@ -85,7 +85,7 @@ group: compat mymachines systemd shadow: compat -hosts: files mymachines resolve [!UNAVAIL=return] dns +hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname networks: files protocols: db files diff --git a/man/nss-systemd.xml b/man/nss-systemd.xml index 56d26e7d1f..71aed4df83 100644 --- a/man/nss-systemd.xml +++ b/man/nss-systemd.xml @@ -83,7 +83,7 @@ group: compat mymachines systemd shadow: compat -hosts: files mymachines resolve myhostname +hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname networks: files protocols: db files -- cgit v1.2.3-54-g00ecf From 8e4e851f1ddc98daf69b68998afc5a096ea17893 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Oct 2016 20:37:54 +0200 Subject: core: move initialization of -.slice and init.scope into the unit_load() callbacks Previously, we'd synthesize the root slice unit and the init scope unit in the enumerator callbacks for the unit type. This is problematic if either of them is already referenced from a unit that is loaded as result of another unit type's enumerator logic. Let's clean this up and simply create the two objects from the enumerator callbacks, if they are not around yet. Do the actual filling in of the settings from the unit_load() callbacks, to match how other units are loaded. Fixes: #4322 --- src/core/scope.c | 44 ++++++++++++++++++++++++++++++++------------ src/core/slice.c | 38 ++++++++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/core/scope.c b/src/core/scope.c index e7583f6d89..af0c43c7da 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -147,6 +147,34 @@ static int scope_verify(Scope *s) { return 0; } +static int scope_load_init_scope(Unit *u) { + assert(u); + + if (!unit_has_name(u, SPECIAL_INIT_SCOPE)) + return 0; + + u->transient = true; + u->no_gc = true; + + /* init.scope is a bit special, as it has to stick around forever. Because of its special semantics we + * synthesize it here, instead of relying on the unit file on disk. */ + + u->default_dependencies = false; + u->ignore_on_isolate = true; + u->refuse_manual_start = true; + u->refuse_manual_stop = true; + + SCOPE(u)->kill_context.kill_signal = SIGRTMIN+14; + + /* Prettify things, if we can. */ + if (!u->description) + u->description = strdup("System and Service Manager"); + if (!u->documentation) + (void) strv_extend(&u->documentation, "man:systemd(1)"); + + return 1; +} + static int scope_load(Unit *u) { Scope *s = SCOPE(u); int r; @@ -158,6 +186,9 @@ static int scope_load(Unit *u) { /* Refuse to load non-transient scope units, but allow them while reloading. */ return -ENOENT; + r = scope_load_init_scope(u); + if (r < 0) + return r; r = unit_load_fragment_and_dropin_optional(u); if (r < 0) return r; @@ -543,25 +574,14 @@ static void scope_enumerate(Manager *m) { r = unit_add_name(u, SPECIAL_INIT_SCOPE); if (r < 0) { unit_free(u); - log_error_errno(r, "Failed to add init.scope name"); + log_error_errno(r, "Failed to add the " SPECIAL_INIT_SCOPE " name: %m"); return; } } u->transient = true; - u->default_dependencies = false; u->no_gc = true; - u->ignore_on_isolate = true; - u->refuse_manual_start = true; - u->refuse_manual_stop = true; SCOPE(u)->deserialized_state = SCOPE_RUNNING; - SCOPE(u)->kill_context.kill_signal = SIGRTMIN+14; - - /* Prettify things, if we can. */ - if (!u->description) - u->description = strdup("System and Service Manager"); - if (!u->documentation) - (void) strv_extend(&u->documentation, "man:systemd(1)"); unit_add_to_load_queue(u); unit_add_to_dbus_queue(u); diff --git a/src/core/slice.c b/src/core/slice.c index 03fe797f27..0fef29661f 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -130,6 +130,30 @@ static int slice_verify(Slice *s) { return 0; } +static int slice_load_root_slice(Unit *u) { + assert(u); + + if (!unit_has_name(u, SPECIAL_ROOT_SLICE)) + return 0; + + u->no_gc = true; + + /* The root slice is a bit special. For example it is always running and cannot be terminated. Because of its + * special semantics we synthesize it here, instead of relying on the unit file on disk. */ + + u->default_dependencies = false; + u->ignore_on_isolate = true; + u->refuse_manual_start = true; + u->refuse_manual_stop = true; + + if (!u->description) + u->description = strdup("Root Slice"); + if (!u->documentation) + u->documentation = strv_new("man:systemd.special(7)", NULL); + + return 1; +} + static int slice_load(Unit *u) { Slice *s = SLICE(u); int r; @@ -137,6 +161,9 @@ static int slice_load(Unit *u) { assert(s); assert(u->load_state == UNIT_STUB); + r = slice_load_root_slice(u); + if (r < 0) + return r; r = unit_load_fragment_and_dropin_optional(u); if (r < 0) return r; @@ -283,23 +310,14 @@ static void slice_enumerate(Manager *m) { r = unit_add_name(u, SPECIAL_ROOT_SLICE); if (r < 0) { unit_free(u); - log_error_errno(r, "Failed to add -.slice name"); + log_error_errno(r, "Failed to add the "SPECIAL_ROOT_SLICE " name: %m"); return; } } - u->default_dependencies = false; u->no_gc = true; - u->ignore_on_isolate = true; - u->refuse_manual_start = true; - u->refuse_manual_stop = true; SLICE(u)->deserialized_state = SLICE_ACTIVE; - if (!u->description) - u->description = strdup("Root Slice"); - if (!u->documentation) - (void) strv_extend(&u->documentation, "man:systemd.special(7)"); - unit_add_to_load_queue(u); unit_add_to_dbus_queue(u); } -- cgit v1.2.3-54-g00ecf From 828d92acbc8e6f536419cfaee10d6b5c7b0d7f82 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Oct 2016 20:49:48 +0200 Subject: core: drop -.slice from shipped units Since this unit is synthesized anyway there's no point in actually shipping it on disk. This also has the benefit that "cd /usr/lib/systemd/system ; ls *" won't be confused by the leading dash of the file name anymore. --- Makefile.am | 12 ------------ units/x-.slice | 12 ------------ 2 files changed, 24 deletions(-) delete mode 100644 units/x-.slice diff --git a/Makefile.am b/Makefile.am index 18a5f4a82a..bad6a2d18a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -493,7 +493,6 @@ dist_systemunit_DATA = \ units/swap.target \ units/slices.target \ units/system.slice \ - units/x-.slice \ units/systemd-initctl.socket \ units/syslog.socket \ units/dev-hugepages.mount \ @@ -637,17 +636,6 @@ GENERAL_ALIASES += \ $(systemunitdir)/reboot.target $(pkgsysconfdir)/system/ctrl-alt-del.target \ $(systemunitdir)/machines.target $(pkgsysconfdir)/system/multi-user.target.wants/machines.target -# automake is broken and can't handle files with a dash in front -# http://debbugs.gnu.org/cgi/bugreport.cgi?bug=14728#8 -units-install-hook: - mv $(DESTDIR)$(systemunitdir)/x-.slice $(DESTDIR)/$(systemunitdir)/-.slice - -units-uninstall-hook: - rm -f $(DESTDIR)/$(systemunitdir)/-.slice - -INSTALL_DATA_HOOKS += units-install-hook -UNINSTALL_DATA_HOOKS += units-uninstall-hook - dist_doc_DATA = \ README \ NEWS \ diff --git a/units/x-.slice b/units/x-.slice deleted file mode 100644 index ac82c35874..0000000000 --- a/units/x-.slice +++ /dev/null @@ -1,12 +0,0 @@ -# This file is part of systemd. -# -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. - -[Unit] -Description=Root Slice -Documentation=man:systemd.special(7) -DefaultDependencies=no -Before=slices.target -- cgit v1.2.3-54-g00ecf From e59ace18a5982b1b6bb3de244abdb924f1abbf70 Mon Sep 17 00:00:00 2001 From: Benjamin Richter Date: Mon, 24 Oct 2016 21:24:47 +0200 Subject: networkd: fix mixup of bond options (#4470) --- src/network/networkd-netdev-bond.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c index 7913b0088e..46d1669337 100644 --- a/src/network/networkd-netdev-bond.c +++ b/src/network/networkd-netdev-bond.c @@ -268,13 +268,13 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin if (b->arp_all_targets != _NETDEV_BOND_ARP_ALL_TARGETS_INVALID) { r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->arp_all_targets); if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_VALIDATE attribute: %m"); + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m"); } if (b->primary_reselect != _NETDEV_BOND_PRIMARY_RESELECT_INVALID) { - r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->primary_reselect); + r = sd_netlink_message_append_u8(m, IFLA_BOND_PRIMARY_RESELECT, b->primary_reselect); if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m"); + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_PRIMARY_RESELECT attribute: %m"); } if (b->resend_igmp <= RESEND_IGMP_MAX) { -- cgit v1.2.3-54-g00ecf From f2e5f466cbd8e0a93325e4ea8c2c38db3bbd1bc8 Mon Sep 17 00:00:00 2001 From: Martin Ejdestig Date: Tue, 25 Oct 2016 00:30:26 +0200 Subject: man: Fix event source priority enum names in synopsis (#4478) --- man/sd_event_source_set_priority.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/man/sd_event_source_set_priority.xml b/man/sd_event_source_set_priority.xml index 6e7032fc80..b6bab6d316 100644 --- a/man/sd_event_source_set_priority.xml +++ b/man/sd_event_source_set_priority.xml @@ -57,9 +57,9 @@ #include <systemd/sd-event.h> enum { - SD_EVENT_SOURCE_IMPORTANT = -100, - SD_EVENT_SOURCE_NORMAL = 0, - SD_EVENT_SOURCE_IDLE = 100, + SD_EVENT_PRIORITY_IMPORTANT = -100, + SD_EVENT_PRIORITY_NORMAL = 0, + SD_EVENT_PRIORITY_IDLE = 100, }; -- cgit v1.2.3-54-g00ecf From 74388c2d11acd9b638e33e09c7a99a9bc2c6292b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 22 Oct 2016 23:41:45 -0400 Subject: man: document the default value of NoNewPrivileges= Fixes #4329. --- man/systemd.exec.xml | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index dbe4594730..6a26f3c133 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1234,13 +1234,22 @@ NoNewPrivileges= - Takes a boolean argument. If true, ensures - that the service process and all its children can never gain - new privileges. This option is more powerful than the - respective secure bits flags (see above), as it also prohibits - UID changes of any kind. This is the simplest, most effective - way to ensure that a process and its children can never - elevate privileges again. + Takes a boolean argument. If true, ensures that the service + process and all its children can never gain new privileges. This option is more + powerful than the respective secure bits flags (see above), as it also prohibits + UID changes of any kind. This is the simplest and most effective way to ensure that + a process and its children can never elevate privileges again. Defaults to false, + but in the user manager instance certain settings force + NoNewPrivileges=yes, ignoring the value of this setting. + Those is the case when SystemCallFilter=, + SystemCallArchitectures=, + RestrictAddressFamilies=, + PrivateDevices=, + ProtectKernelTunables=, + ProtectKernelModules=, + MemoryDenyWriteExecute=, or + RestrictRealtime= are specified. + -- cgit v1.2.3-54-g00ecf From 4c37970d77e2b251eaa0546838a98e5bdff28c87 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Oct 2016 20:06:03 +0200 Subject: update NEWS file a bit more --- NEWS | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 2a1edbe766..8d8c1033d3 100644 --- a/NEWS +++ b/NEWS @@ -6,7 +6,8 @@ CHANGES WITH 232 in spe the user or group of a service when that service exits. * The new ProtectKernelModules= option can be used to disable explicit - load and unload operations of kernel modules by a service. + load and unload operations of kernel modules by a service. In + addition access to /usr/lib/modules is removed if this option is set. * ProtectSystem= option gained a new value "strict", which causes the whole file system tree with the exception of /dev, /proc, and /sys, @@ -229,6 +230,87 @@ CHANGES WITH 232 in spe running services in a race-free manner, and in particular collect information about exit statuses and results. + * The nss-resolve module has been changed to strictly return UNAVAIL + when communication via D-Bus with resolved failed, and NOTFOUND when + a lookup completed but was negative. This means it is now possible to + neatly configure fallbacks using nsswitch.conf result checking + expressions. Taking benefit of this, the new recommended + configuration line for the "hosts" entry in /etc/nsswitch.conf is: + + hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname + + * A new setting CtrlAltDelBurstAction= has been added to + /etc/systemd/system.conf which may be used to configure the precise + behaviour if the user on the console presses Ctrl-Alt-Del more often + than 7 times in 2s. Previously this would unconditionally result in + an expedited, immediate reboot. With this new setting the precise + operation may be configured in more detail, and also turned off + entirely. + + * In .netdev files two new settings RemoteChecksumTx= and + RemoteChecksumRx= are now understood that permit configuring the + remote checksumming logic for VXLAN networks. + + * The service manager learnt a new "invocation ID" concept for invoked + services. Each runtime cycle of a service will get a new invocation + ID (a 128bit random UUID) assigned that identifies the current + run of the service uniquely and globally. A new invocation ID + is generated each time a service starts up. The journal will store + the invocation ID of a service along with any logged messages, thus + making the invocation ID useful for matching the online runtime of a + service with the offline log data it generated in a safe way without + relying on synchronized timestamps. In many ways this new service + invocation ID concept is similar to the kernel's boot ID concept that + uniquely and globally identifies the runtime of each boot. The + invocation ID of a service is passed to the service itself via an + environment variable ($INVOCATION_ID). A new bus call + GetUnitByInvocationID() has been added that is similar to GetUnit() + but instead of retrieving the bus path for a unit by its name + retrieves it by its invocation ID. The returned path is valid only as + long as the passed invocation ID is current. + + * systemd-resolved gained a new "DNSStubListener" setting in + resolved.conf. It either takes a boolean value or the special values + "udp" and "tcp", and configures whether to enable the stub DNS + listener on 127.0.0.53:53. + + * IP addresses configured via networkd may now carry additional + configuration settings supported by the kernel. New options include: + HomeAddress=, DuplicateAddressDetection=, ManageTemporaryAddress=, + PrefixRoute=, AutoJoin=. + + * The PAM configuration fragment file for "user@.service" shipped with + systemd (i.e. the --user instance of systemd) has been stripped to + the minimum necessary to make the system boot. Previously, it + contained Fedora-specific stanzas that did not apply to other + distributions. It is expected that downstream distributions add + additional configuration lines, matching their needs to this file, + using it only as rough template of what systemd itself needs. Note + that this reduced fragment does not even include an invocation of + pam_limits which most distributions probably want to add, even though + systemd itself does not need it. (There's also the new build time + option --with-pamconfdir=no to disable installation of the PAM + fragment entirely.) + + * If PrivateDevices=yes is set for a service the CAP_SYS_RAWIO + capability is now also dropped from its set (in addition to + CAP_SYS_MKNOD as before). + + * In service unit files it is now possible to connect a specific named + file descriptor with stdin/stdout/stdout of an executed service. The + name may be specified in matching .socket units using the + FileDescriptorName= setting. + + * A number of journal settings may now be configured on the kernel + command line. Specifically, the following options are now understood: + systemd.journald.max_level_console=, + systemd.journald.max_level_store=, + systemd.journald.max_level_syslog=, systemd.journald.max_level_kmsg=, + systemd.journald.max_level_wall=. + + * "systemctl is-enabled --full" will now show by which symlinks a unit + file is enabled in the unit dependency tree. + CHANGES WITH 231: * In service units the various ExecXYZ= settings have been extended @@ -2106,7 +2188,7 @@ CHANGES WITH 219: files. * systemd now provides a way to store file descriptors - per-service in PID 1.This is useful for daemons to ensure + per-service in PID 1. This is useful for daemons to ensure that fds they require are not lost during a daemon restart. The fds are passed to the daemon on the next invocation in the same way socket activation fds are -- cgit v1.2.3-54-g00ecf From 6fa4160def76686c4aba4af28d3208648cad8051 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Oct 2016 20:06:22 +0200 Subject: systemctl: fix two minor memory leaks in --wait handling (Also, let's not use the binary |= operator on "bool" variables). Fix-up for 93a0884126146361ca078ec627da2cf766205a1c. --- src/systemctl/systemctl.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 2e3b59af3e..35d5c11cc7 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -2721,7 +2721,7 @@ typedef struct { static void wait_context_free(WaitContext *c) { c->match = sd_bus_slot_unref(c->match); c->event = sd_event_unref(c->event); - c->unit_paths = set_free(c->unit_paths); + c->unit_paths = set_free_free(c->unit_paths); } static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) { @@ -2738,31 +2738,37 @@ static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error r = sd_bus_message_skip(m, "s"); if (r < 0) return bus_log_parse_error(r); + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { const char *s; - bool is_failed; r = sd_bus_message_read(m, "s", &s); if (r < 0) return bus_log_parse_error(r); + if (streq(s, "ActiveState")) { + bool is_failed; + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "s"); if (r < 0) return bus_log_parse_error(r); + r = sd_bus_message_read(m, "s", &s); if (r < 0) return bus_log_parse_error(r); + is_failed = streq(s, "failed"); if (streq(s, "inactive") || is_failed) { log_debug("%s became %s, dropping from --wait tracking", path, s); - set_remove(c->unit_paths, path); - c->any_failed |= is_failed; + free(set_remove(c->unit_paths, path)); + c->any_failed = c->any_failed || is_failed; } else log_debug("ActiveState on %s changed to %s", path, s); + break; /* no need to dissect the rest of the message */ } else { /* other property */ -- cgit v1.2.3-54-g00ecf From 6086d2daf370426259299e6ff9316ae51238969a Mon Sep 17 00:00:00 2001 From: Dongsu Park Date: Tue, 25 Oct 2016 14:51:01 +0200 Subject: test: skip exec tests when inaccessible dir is unavailable In case of running test-execute on systems with systemd < v232, several tests like privatedevices or protectkernelmodules fail because /run/systemd/inaccessible/ doesn't exist. In these cases, we should skip tests to avoid unnecessary errors. See also https://github.com/systemd/systemd/pull/4243#issuecomment-253665566 --- src/test/test-execute.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 404421a2b8..c369098500 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -70,6 +70,24 @@ static void check(Manager *m, Unit *unit, int status_expected, int code_expected assert_se(service->main_exec_status.code == code_expected); } +static bool is_inaccessible_available(void) { + char *p; + + FOREACH_STRING(p, + "/run/systemd/inaccessible/reg", + "/run/systemd/inaccessible/dir", + "/run/systemd/inaccessible/chr", + "/run/systemd/inaccessible/blk", + "/run/systemd/inaccessible/fifo", + "/run/systemd/inaccessible/sock" + ) { + if (access(p, F_OK) < 0) + return false; + } + + return true; +} + static void test(Manager *m, const char *unit_name, int status_expected, int code_expected) { Unit *unit; @@ -129,6 +147,11 @@ static void test_exec_privatedevices(Manager *m) { log_notice("testing in container, skipping private device tests"); return; } + if (!is_inaccessible_available()) { + log_notice("testing without inaccessible, skipping private device tests"); + return; + } + test(m, "exec-privatedevices-yes.service", 0, CLD_EXITED); test(m, "exec-privatedevices-no.service", 0, CLD_EXITED); } @@ -138,6 +161,11 @@ static void test_exec_privatedevices_capabilities(Manager *m) { log_notice("testing in container, skipping private device tests"); return; } + if (!is_inaccessible_available()) { + log_notice("testing without inaccessible, skipping private device tests"); + return; + } + test(m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED); test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED); test(m, "exec-privatedevices-yes-capability-sys-rawio.service", 0, CLD_EXITED); @@ -149,6 +177,10 @@ static void test_exec_protectkernelmodules(Manager *m) { log_notice("testing in container, skipping protectkernelmodules tests"); return; } + if (!is_inaccessible_available()) { + log_notice("testing without inaccessible, skipping protectkernelmodules tests"); + return; + } test(m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED); test(m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED); -- cgit v1.2.3-54-g00ecf From 2b7466a22b897c7c30550f3572fbdd7bc77554ec Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Wed, 26 Oct 2016 02:39:48 +0300 Subject: build-sys/autogen: don't use bashisms (#4489) Fixes: $ ls -l /bin/sh lrwxrwxrwx 1 root root 4 Feb 17 2016 /bin/sh -> dash $ ./autogen.sh c ./autogen.sh: 22: ./autogen.sh: [[: not found ... checking whether make supports nested variables... (cached) yes checking build system type... Invalid configuration `c': machine `c' not recognized configure: error: /bin/bash build-aux/config.sub c failed this is a follow-up for a5e739a570081231 --- autogen.sh | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/autogen.sh b/autogen.sh index fa8d2916ad..1897e23b53 100755 --- a/autogen.sh +++ b/autogen.sh @@ -19,13 +19,11 @@ set -e verb="$1" -if [[ -n "$verb" ]]; then - if [[ "$verb" != [cgals] ]]; then - echo "Unexpected argument: $verb" >&2 - exit 1 - fi - shift -fi +case "$verb" in +"") ;; +[cgals]) shift ;; +*) echo "Unexpected argument: $verb" >&2; exit 1 ;; +esac oldpwd=$(pwd) topdir=$(dirname $0) -- cgit v1.2.3-54-g00ecf From d4a48671bc453ead3cff911a0dfcc16ce5538072 Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Wed, 26 Oct 2016 02:40:21 +0200 Subject: man: document that systemctl cat shows file content (#4488) ... and that that content might be outdated. --- man/systemctl.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index a4d4c53725..225eb06d8b 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -894,7 +894,11 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service Show backing files of one or more units. Prints the "fragment" and "drop-ins" (source files) of units. Each file is preceded by a comment which includes the file - name. + name. Note that this shows the contents of the backing files + on disk, which may not match the system manager's + understanding of these units if any unit files were + updated on disk and the daemon-reload + command wasn't issued since. -- cgit v1.2.3-54-g00ecf From 5297577f2748cef98486161b86d9c37312d4470b Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Wed, 12 Oct 2016 18:20:50 +0200 Subject: vconsole: setup_remaining_vcs() - more sanity checks Check if values filled up by KD_FONT_OP_GET ioctl make sense - dummy driver for example doesn't implement required functionality at all. --- src/vconsole/vconsole-setup.c | 59 +++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index ac4ceb1486..185b041a1c 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -208,9 +208,9 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map, */ static void setup_remaining_vcs(int fd, bool utf8) { struct console_font_op cfo = { - .op = KD_FONT_OP_GET, .flags = 0, - .width = 32, .height = 32, - .charcount = 512, + .op = KD_FONT_OP_GET, + .width = UINT_MAX, .height = UINT_MAX, + .charcount = UINT_MAX, }; struct vt_stat vcs = {}; struct unimapinit adv = {}; @@ -225,12 +225,6 @@ static void setup_remaining_vcs(int fd, bool utf8) { return; } - fontbuf = malloc(cfo.width * cfo.height * cfo.charcount / 8); - if (!fontbuf) { - log_oom(); - return; - } - /* get active, and 16 bit mask of used VT numbers */ r = ioctl(fd, VT_GETSTATE, &vcs); if (r < 0) { @@ -238,19 +232,46 @@ static void setup_remaining_vcs(int fd, bool utf8) { return; } - /* get fonts from source console */ - cfo.data = fontbuf; + /* get metadata of the current font (width, height, count) */ r = ioctl(fd, KDFONTOP, &cfo); if (r < 0) - log_warning_errno(errno, "KD_FONT_OP_GET failed, fonts will not be copied: %m"); + log_warning_errno(errno, "KD_FONT_OP_GET failed while trying to get the font metadata: %m"); else { - unimapd.entries = unipairs; - unimapd.entry_ct = USHRT_MAX; - r = ioctl(fd, GIO_UNIMAP, &unimapd); - if (r < 0) - log_warning_errno(errno, "GIO_UNIMAP failed, fonts will not be copied: %m"); - else - cfo.op = KD_FONT_OP_SET; + /* sanitize parameters first */ + if (cfo.width > 32 || cfo.height > 32 || cfo.charcount > 512) + log_warning("Invalid font metadata - width: %u (max 32), height: %u (max 32), count: %u (max 512)", + cfo.width, cfo.height, cfo.charcount); + else { + /* + * Console fonts supported by the kernel are limited in size to 32 x 32 and maximum 512 + * characters. Thus with 1 bit per pixel it requires up to 65536 bytes. The height always + * requries 32 per glyph, regardless of the actual height - see the comment above #define + * max_font_size 65536 in drivers/tty/vt/vt.c for more details. + */ + fontbuf = malloc((cfo.width + 7) / 8 * 32 * cfo.charcount); + if (!fontbuf) { + log_oom(); + return; + } + /* get fonts from source console */ + cfo.data = fontbuf; + r = ioctl(fd, KDFONTOP, &cfo); + if (r < 0) + log_warning_errno(errno, "KD_FONT_OP_GET failed while trying to read the font data: %m"); + else { + unimapd.entries = unipairs; + unimapd.entry_ct = USHRT_MAX; + r = ioctl(fd, GIO_UNIMAP, &unimapd); + if (r < 0) + log_warning_errno(errno, "GIO_UNIMAP failed while trying to read unicode mappings: %m"); + else + cfo.op = KD_FONT_OP_SET; + } + } + } + + if (cfo.op != KD_FONT_OP_SET) { + log_warning("Fonts will not be copied to remaining consoles"); } for (i = 1; i <= 63; i++) { -- cgit v1.2.3-54-g00ecf From d2ffa389b8112282be1633bb4638f6f47e159299 Mon Sep 17 00:00:00 2001 From: Topi Miettinen Date: Wed, 26 Oct 2016 18:52:53 +0300 Subject: seccomp: also block shmat(..., SHM_EXEC) for MemoryDenyWriteExecute shmat(..., SHM_EXEC) can be used to create writable and executable memory, so let's block it when MemoryDenyWriteExecute is set. --- man/systemd.exec.xml | 11 +++++++---- src/core/execute.c | 11 +++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index dbe4594730..f9a15d8db0 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1516,12 +1516,15 @@ MemoryDenyWriteExecute= Takes a boolean argument. If set, attempts to create memory mappings that are writable and - executable at the same time, or to change existing memory mappings to become executable are prohibited. + executable at the same time, or to change existing memory mappings to become executable, or mapping shared memory + segments as executable are prohibited. Specifically, a system call filter is added that rejects mmap2 - system calls with both PROT_EXEC and PROT_WRITE set - and mprotect2 - system calls with PROT_EXEC set. Note that this option is incompatible with programs + system calls with both PROT_EXEC and PROT_WRITE set, + mprotect2 + system calls with PROT_EXEC set and + shmat2 + system calls with SHM_EXEC set. Note that this option is incompatible with programs that generate program code dynamically at runtime, such as JIT execution engines, or programs compiled making use of the code "trampoline" feature of various C compilers. This option improves service security, as it makes harder for software exploits to change running code dynamically. diff --git a/src/core/execute.c b/src/core/execute.c index 5e7d7c25d7..7b42ac7bdc 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -29,8 +29,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -1394,6 +1396,15 @@ static int apply_memory_deny_write_execute(const Unit* u, const ExecContext *c) if (r < 0) goto finish; + r = seccomp_rule_add( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(shmat), + 1, + SCMP_A2(SCMP_CMP_MASKED_EQ, SHM_EXEC, SHM_EXEC)); + if (r < 0) + goto finish; + r = seccomp_load(seccomp); finish: -- cgit v1.2.3-54-g00ecf From 808b95ef82a0715af7bde08a0050e2477bfc6f0f Mon Sep 17 00:00:00 2001 From: Michal Soltys Date: Thu, 27 Oct 2016 01:21:02 +0200 Subject: vconsole: manual update (#4021) To more correctly reflect current behaviour as well as to provide a few more details. --- man/systemd-vconsole-setup.service.xml | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/man/systemd-vconsole-setup.service.xml b/man/systemd-vconsole-setup.service.xml index e048258621..f2da2a7b77 100644 --- a/man/systemd-vconsole-setup.service.xml +++ b/man/systemd-vconsole-setup.service.xml @@ -43,23 +43,35 @@ systemd-vconsole-setup.service systemd-vconsole-setup - Configure the virtual console at boot + Configure the virtual consoles systemd-vconsole-setup.service - /usr/lib/systemd/systemd-vconsole-setup + + /usr/lib/systemd/systemd-vconsole-setup + TTY + Description - systemd-vconsole-setup.service is an - early boot service that configures the virtual console font and - console keymap. Internally it calls - loadkeys1 - and - setfont8. + systemd-vconsole-setup is a helper used to prepare either all virtual consoles, or — if + the optional TTY parameter is provided — a specific one. When the system is booting up + it's called by udev during vtconsole subsystem initialization. + Systemd also calls it internally as needed via + systemd-vconsole-setup.service. The helper calls + loadkeys1 and + setfont8 + internally. + + + + You may want to use this helper whenever you change vconsole.conf to + refresh the settings on your consoles — either through the systemctl restart / + systemctl start command or directly through the executable. + See vconsole.conf5 -- cgit v1.2.3-54-g00ecf From 532538244028ca90e9a7c59ec9627a3ff17a7da8 Mon Sep 17 00:00:00 2001 From: Susant Sahani Date: Thu, 27 Oct 2016 05:01:04 +0530 Subject: networkd : verify dns ip address when parsing configuration (#4492) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Invalid IP addresses would be passed through as-is: $ networkctl status wlp3s0: ● 2: wlp3s0 Link File: /usr/lib/systemd/network/99-default.link Network File: /etc/systemd/network/wlp3s0.network Type: wlan State: routable (configured) Path: pci-0000:03:00.0 Driver: iwlwifi Vendor: Intel Corporation Model: Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 AGN) HW Address: XXXXXXXXXX (Intel Corporate) Address: 192.168.2.103 XXXXXXXXXXX Gateway: 192.168.2.1 (Arcadyan Technology Corporation) DNS: 127.0.0.5553 Instead verify that DNS= has a valid list of addresses when parsing configuration. Fixes #4462. --- src/network/networkd-network-gperf.gperf | 2 +- src/network/networkd-network.c | 50 ++++++++++++++++++++++++++++++++ src/network/networkd-network.h | 1 + 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 5587961b9f..bcf8186c33 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -49,7 +49,7 @@ Network.EmitLLDP, config_parse_lldp_emit, Network.Address, config_parse_address, 0, 0 Network.Gateway, config_parse_gateway, 0, 0 Network.Domains, config_parse_domains, 0, 0 -Network.DNS, config_parse_strv, 0, offsetof(Network, dns) +Network.DNS, config_parse_dns, 0, 0 Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr) Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns) Network.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Network, dnssec_mode) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 584cb96979..042232fcac 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -979,6 +979,56 @@ int config_parse_dhcp_server_ntp( } } +int config_parse_dns( + 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 *n = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL; + union in_addr_union a; + int family; + + r = extract_first_word(&rvalue, &w, WHITESPACE, EXTRACT_QUOTES|EXTRACT_RETAIN_ESCAPE); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + break; + } + + r = in_addr_from_string_auto(w, &family, &a); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse dns server address, ignoring: %s", w); + continue; + } + + r = strv_consume(&n->dns, w); + if (r < 0) + return log_oom(); + + w = NULL; + } + + return 0; +} + int config_parse_dnssec_negative_trust_anchors( const char *unit, const char *filename, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index ef4b499ab9..42fc82d392 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -220,6 +220,7 @@ int config_parse_netdev(const char *unit, const char *filename, unsigned line, c 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, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_dhcp(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_dns(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_dhcp_client_identifier(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_ipv6token(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_ipv6_privacy_extensions(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); -- cgit v1.2.3-54-g00ecf From 6328c51a5d123c80ad846855665af671cde4cfa1 Mon Sep 17 00:00:00 2001 From: "Thomas H. P. Andersen" Date: Thu, 27 Oct 2016 01:40:25 +0200 Subject: gitignore: add test-seccomp (#4498) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c925f19f41..f8336063b7 100644 --- a/.gitignore +++ b/.gitignore @@ -261,6 +261,7 @@ /test-ring /test-rlimit-util /test-sched-prio +/test-seccomp /test-selinux /test-set /test-sizeof -- cgit v1.2.3-54-g00ecf From 299a34c11a4241f8c5832ccd5a7bc13263f8488b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 20 Oct 2016 23:41:21 -0400 Subject: detect-virt: add --private-users switch to check if a userns is active Various things don't work when we're running in a user namespace, but it's pretty hard to reliably detect if that is true. A function is added which looks at /proc/self/uid_map and returns false if the default "0 0 UINT32_MAX" is found, and true if it finds anything else. This misses the case where an 1:1 mapping with the full range was used, but I don't know how to distinguish this case. 'systemd-detect-virt --private-users' is very similar to 'systemd-detect-virt --chroot', but we check for a user namespace instead. --- man/systemd-detect-virt.xml | 16 ++++++++-- man/systemd.unit.xml | 3 +- src/basic/virt.c | 70 +++++++++++++++++++++++++++++++++++++++++++ src/basic/virt.h | 1 + src/detect-virt/detect-virt.c | 31 ++++++++++++++----- 5 files changed, 111 insertions(+), 10 deletions(-) diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml index 61a5f8937f..996c2fa256 100644 --- a/man/systemd-detect-virt.xml +++ b/man/systemd-detect-virt.xml @@ -50,7 +50,8 @@ - systemd-detect-virt OPTIONS + systemd-detect-virt + OPTIONS @@ -217,6 +218,16 @@ environment or not. + + + + Detect whether invoked in a user namespace. In this mode, no + output is written, but the return value indicates whether the process was invoked + inside of a user namespace or not. See + user_namespaces7 + for more information. + + @@ -243,7 +254,8 @@ systemd1, systemd-nspawn1, - chroot2 + chroot2, + namespaces7 diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 04efee2891..40c4cfd854 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -908,7 +908,8 @@ systemd-nspawn, docker, rkt to test - against a specific implementation. See + against a specific implementation, or + private-users to check whether we are running in a user namespace. See systemd-detect-virt1 for a full list of known virtualization technologies and their identifiers. If multiple virtualization technologies are diff --git a/src/basic/virt.c b/src/basic/virt.c index 41012d52a0..69b0f96183 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -485,6 +485,76 @@ int detect_virtualization(void) { return r; } +static int userns_has_mapping(const char *name) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *buf = NULL; + size_t n_allocated = 0; + ssize_t n; + uint32_t a, b, c; + int r; + + f = fopen(name, "re"); + if (!f) { + log_debug_errno(errno, "Failed to open %s: %m", name); + return errno == -ENOENT ? false : -errno; + } + + n = getline(&buf, &n_allocated, f); + if (n < 0) { + if (feof(f)) { + log_debug("%s is empty, we're in an uninitialized user namespace", name); + return true; + } + + return log_debug_errno(errno, "Failed to read %s: %m", name); + } + + r = sscanf(buf, "%"PRIu32" %"PRIu32" %"PRIu32, &a, &b, &c); + if (r < 3) + return log_debug_errno(errno, "Failed to parse %s: %m", name); + + if (a == 0 && b == 0 && c == UINT32_MAX) { + /* The kernel calls mappings_overlap() and does not allow overlaps */ + log_debug("%s has a full 1:1 mapping", name); + return false; + } + + /* Anything else implies that we are in a user namespace */ + log_debug("Mapping found in %s, we're in a user namespace", name); + return true; +} + +int running_in_userns(void) { + _cleanup_free_ char *line = NULL; + int r; + + r = userns_has_mapping("/proc/self/uid_map"); + if (r != 0) + return r; + + r = userns_has_mapping("/proc/self/gid_map"); + if (r != 0) + return r; + + /* "setgroups" file was added in kernel v3.18-rc6-15-g9cc46516dd. It is also + * possible to compile a kernel without CONFIG_USER_NS, in which case "setgroups" + * also does not exist. We cannot distinguish those two cases, so assume that + * we're running on a stripped-down recent kernel, rather than on an old one, + * and if the file is not found, return false. + */ + r = read_one_line_file("/proc/self/setgroups", &line); + if (r < 0) { + log_debug_errno(r, "/proc/self/setgroups: %m"); + return r == -ENOENT ? false : r; + } + + truncate_nl(line); + r = streq(line, "deny"); + /* See user_namespaces(7) for a description of this "setgroups" contents. */ + log_debug("/proc/self/setgroups contains \"%s\", %s user namespace", line, r ? "in" : "not in"); + return r; +} + int running_in_chroot(void) { int ret; diff --git a/src/basic/virt.h b/src/basic/virt.h index bc5b3ae94d..7d15169112 100644 --- a/src/basic/virt.h +++ b/src/basic/virt.h @@ -67,6 +67,7 @@ int detect_vm(void); int detect_container(void); int detect_virtualization(void); +int running_in_userns(void); int running_in_chroot(void); const char *virtualization_to_string(int v) _const_; diff --git a/src/detect-virt/detect-virt.c b/src/detect-virt/detect-virt.c index 5d51589a31..4b8956f0ad 100644 --- a/src/detect-virt/detect-virt.c +++ b/src/detect-virt/detect-virt.c @@ -31,6 +31,7 @@ static enum { ONLY_VM, ONLY_CONTAINER, ONLY_CHROOT, + ONLY_PRIVATE_USERS, } arg_mode = ANY_VIRTUALIZATION; static void help(void) { @@ -41,6 +42,7 @@ static void help(void) { " -c --container Only detect whether we are run in a container\n" " -v --vm Only detect whether we are run in a VM\n" " -r --chroot Detect whether we are run in a chroot() environment\n" + " --private-users Only detect whether we are running in a user namespace\n" " -q --quiet Don't output anything, just set return value\n" , program_invocation_short_name); } @@ -48,16 +50,18 @@ static void help(void) { static int parse_argv(int argc, char *argv[]) { enum { - ARG_VERSION = 0x100 + ARG_VERSION = 0x100, + ARG_PRIVATE_USERS, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "container", no_argument, NULL, 'c' }, - { "vm", no_argument, NULL, 'v' }, - { "chroot", no_argument, NULL, 'r' }, - { "quiet", no_argument, NULL, 'q' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "container", no_argument, NULL, 'c' }, + { "vm", no_argument, NULL, 'v' }, + { "chroot", no_argument, NULL, 'r' }, + { "private-users", no_argument, NULL, ARG_PRIVATE_USERS }, + { "quiet", no_argument, NULL, 'q' }, {} }; @@ -85,6 +89,10 @@ static int parse_argv(int argc, char *argv[]) { arg_mode = ONLY_CONTAINER; break; + case ARG_PRIVATE_USERS: + arg_mode = ONLY_PRIVATE_USERS; + break; + case 'v': arg_mode = ONLY_VM; break; @@ -151,6 +159,15 @@ int main(int argc, char *argv[]) { return r ? EXIT_SUCCESS : EXIT_FAILURE; + case ONLY_PRIVATE_USERS: + r = running_in_userns(); + if (r < 0) { + log_error_errno(r, "Failed to check for user namespace: %m"); + return EXIT_FAILURE; + } + + return r ? EXIT_SUCCESS : EXIT_FAILURE; + case ANY_VIRTUALIZATION: default: r = detect_virtualization(); -- cgit v1.2.3-54-g00ecf From 239a5707e1bd7740b075e78a4837a77f1129cdaa Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 21 Oct 2016 22:56:58 -0400 Subject: shared/condition: add ConditionVirtualization=[!]private-users This can be useful to silence warnings about units which fail in userns container. --- src/shared/condition.c | 3 +++ src/test/test-condition.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/shared/condition.c b/src/shared/condition.c index f13fa6a9fd..376606e004 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -146,6 +146,9 @@ static int condition_test_virtualization(Condition *c) { assert(c->parameter); assert(c->type == CONDITION_VIRTUALIZATION); + if (streq(c->parameter, "private-users")) + return running_in_userns(); + v = detect_virtualization(); if (v < 0) return v; diff --git a/src/test/test-condition.c b/src/test/test-condition.c index 6f7d71ef9a..dd985f5863 100644 --- a/src/test/test-condition.c +++ b/src/test/test-condition.c @@ -31,6 +31,8 @@ #include "macro.h" #include "selinux-util.h" #include "smack-util.h" +#include "strv.h" +#include "virt.h" #include "util.h" static void test_condition_test_path(void) { @@ -265,7 +267,64 @@ static void test_condition_test_security(void) { condition_free(condition); } +static void test_condition_test_virtualization(void) { + Condition *condition; + const char *virt; + int r; + + condition = condition_new(CONDITION_VIRTUALIZATION, "garbage oifdsjfoidsjoj", false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionVirtualization=garbage → %i", r); + assert_se(r == 0); + condition_free(condition); + + condition = condition_new(CONDITION_VIRTUALIZATION, "container", false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionVirtualization=container → %i", r); + assert_se(r == !!detect_container()); + condition_free(condition); + + condition = condition_new(CONDITION_VIRTUALIZATION, "vm", false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionVirtualization=vm → %i", r); + assert_se(r == (detect_vm() && !detect_container())); + condition_free(condition); + + condition = condition_new(CONDITION_VIRTUALIZATION, "private-users", false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionVirtualization=private-users → %i", r); + assert_se(r == !!running_in_userns()); + condition_free(condition); + + NULSTR_FOREACH(virt, + "kvm\0" + "qemu\0" + "bochs\0" + "xen\0" + "uml\0" + "vmware\0" + "oracle\0" + "microsoft\0" + "zvm\0" + "parallels\0" + "bhyve\0" + "vm_other\0") { + + condition = condition_new(CONDITION_VIRTUALIZATION, virt, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionVirtualization=%s → %i", virt, r); + assert_se(r >= 0); + condition_free(condition); + } +} + int main(int argc, char *argv[]) { + log_set_max_level(LOG_DEBUG); log_parse_environment(); log_open(); @@ -276,6 +335,7 @@ int main(int argc, char *argv[]) { test_condition_test_kernel_command_line(); test_condition_test_null(); test_condition_test_security(); + test_condition_test_virtualization(); return 0; } -- cgit v1.2.3-54-g00ecf From d09f968657f379025c30c02cff7047b642b0866a Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 24 Oct 2016 19:17:50 -0400 Subject: test-tables: test ConditionVirtualization --- src/test/test-tables.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/test-tables.c b/src/test/test-tables.c index 0be74921fc..f954179b04 100644 --- a/src/test/test-tables.c +++ b/src/test/test-tables.c @@ -48,6 +48,7 @@ #include "unit-name.h" #include "unit.h" #include "util.h" +#include "virt.h" int main(int argc, char **argv) { test_table(architecture, ARCHITECTURE); @@ -114,6 +115,7 @@ int main(int argc, char **argv) { test_table(unit_load_state, UNIT_LOAD_STATE); test_table(unit_type, UNIT_TYPE); test_table(locale_variable, VARIABLE_LC); + test_table(virtualization, VIRTUALIZATION); test_table_sparse(object_compressed, OBJECT_COMPRESSED); -- cgit v1.2.3-54-g00ecf From 0809d7740c5cf988e049781b4b80e14a3bbefb70 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 24 Oct 2016 22:53:07 -0400 Subject: condition: simplify condition_test_virtualization Rewrite the function to be slightly simpler. In particular, if a specific match is found (like ConditionVirtualization=yes), simply return an answer immediately, instead of relying that "yes" will not be matched by any of the virtualization names below. No functional change. --- src/shared/condition.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/shared/condition.c b/src/shared/condition.c index 376606e004..17b80d9e0c 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -155,19 +155,15 @@ static int condition_test_virtualization(Condition *c) { /* First, compare with yes/no */ b = parse_boolean(c->parameter); - - if (v > 0 && b > 0) - return true; - - if (v == 0 && b == 0) - return true; + if (b >= 0) + return b == !!v; /* Then, compare categorization */ - if (VIRTUALIZATION_IS_VM(v) && streq(c->parameter, "vm")) - return true; + if (streq(c->parameter, "vm")) + return VIRTUALIZATION_IS_VM(v); - if (VIRTUALIZATION_IS_CONTAINER(v) && streq(c->parameter, "container")) - return true; + if (streq(c->parameter, "container")) + return VIRTUALIZATION_IS_CONTAINER(v); /* Finally compare id */ return v != VIRTUALIZATION_NONE && streq(c->parameter, virtualization_to_string(v)); -- cgit v1.2.3-54-g00ecf From 4bb30aeaf8e756b20d66e13af2eac0c5a30b01fa Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 21 Oct 2016 23:00:38 -0400 Subject: units: disable /dev/hugepages in private user namespaces The mount fails, even though CAP_SYS_ADMIN is granted. --- units/dev-hugepages.mount | 1 + 1 file changed, 1 insertion(+) diff --git a/units/dev-hugepages.mount b/units/dev-hugepages.mount index 882adb4545..489cc777e4 100644 --- a/units/dev-hugepages.mount +++ b/units/dev-hugepages.mount @@ -13,6 +13,7 @@ DefaultDependencies=no Before=sysinit.target ConditionPathExists=/sys/kernel/mm/hugepages ConditionCapability=CAP_SYS_ADMIN +ConditionVirtualization=!private-users [Mount] What=hugetlbfs -- cgit v1.2.3-54-g00ecf From 342d3ac165680197efe7973efbe08f7eb12b6b11 Mon Sep 17 00:00:00 2001 From: "Thomas H. P. Andersen" Date: Thu, 27 Oct 2016 03:22:26 +0200 Subject: hwdb: fix error check of wrong variable (#4499) We updated 'fn' but checked 'v' instead. From 698c5a17 Spotted with PVS --- src/hwdb/hwdb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c index be4ef5f9e9..ab1feb435b 100644 --- a/src/hwdb/hwdb.c +++ b/src/hwdb/hwdb.c @@ -172,8 +172,8 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node, if (v < 0) return v; fn = strbuf_add_string(trie->strings, filename, strlen(filename)); - if (v < 0) - return v; + if (fn < 0) + return fn; if (node->values_count) { struct trie_value_entry search = { -- cgit v1.2.3-54-g00ecf From 93c6bb51b6a3c80577fd823d0108c1dfcf01a0ce Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Thu, 27 Oct 2016 09:20:18 +0200 Subject: core: move the code that setups namespaces on its own function --- src/core/execute.c | 101 ++++++++++++++++++++++++++++------------------------- 1 file changed, 54 insertions(+), 47 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 5e7d7c25d7..2908ba8fa3 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2003,6 +2003,59 @@ static int compile_read_write_paths( return 0; } +static int apply_mount_namespace(Unit *u, const ExecContext *context, + const ExecParameters *params, + ExecRuntime *runtime) { + int r; + _cleanup_free_ char **rw = NULL; + char *tmp = NULL, *var = NULL; + const char *root_dir = NULL; + NameSpaceInfo ns_info = { + .private_dev = context->private_devices, + .protect_control_groups = context->protect_control_groups, + .protect_kernel_tunables = context->protect_kernel_tunables, + .protect_kernel_modules = context->protect_kernel_modules, + }; + + /* The runtime struct only contains the parent of the private /tmp, + * which is non-accessible to world users. Inside of it there's a /tmp + * that is sticky, and that's the one we want to use here. */ + + if (context->private_tmp && runtime) { + if (runtime->tmp_dir) + tmp = strjoina(runtime->tmp_dir, "/tmp"); + if (runtime->var_tmp_dir) + var = strjoina(runtime->var_tmp_dir, "/tmp"); + } + + r = compile_read_write_paths(context, params, &rw); + if (r < 0) + return r; + + if (params->flags & EXEC_APPLY_CHROOT) + root_dir = context->root_directory; + + r = setup_namespace(root_dir, &ns_info, rw, + context->read_only_paths, + context->inaccessible_paths, + tmp, + var, + context->protect_home, + context->protect_system, + context->mount_flags); + + /* If we couldn't set up the namespace this is probably due to a + * missing capability. In this case, silently proceeed. */ + if (IN_SET(r, -EPERM, -EACCES)) { + log_open(); + log_unit_debug_errno(u, r, "Failed to set up namespace, assuming containerized execution, ignoring: %m"); + log_close(); + r = 0; + } + + return r; +} + static void append_socket_pair(int *array, unsigned *n, int pair[2]) { assert(array); assert(n); @@ -2466,57 +2519,11 @@ static int exec_child( needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime); if (needs_mount_namespace) { - _cleanup_free_ char **rw = NULL; - char *tmp = NULL, *var = NULL; - NameSpaceInfo ns_info = { - .private_dev = context->private_devices, - .protect_control_groups = context->protect_control_groups, - .protect_kernel_tunables = context->protect_kernel_tunables, - .protect_kernel_modules = context->protect_kernel_modules, - }; - - /* The runtime struct only contains the parent - * of the private /tmp, which is - * non-accessible to world users. Inside of it - * there's a /tmp that is sticky, and that's - * the one we want to use here. */ - - if (context->private_tmp && runtime) { - if (runtime->tmp_dir) - tmp = strjoina(runtime->tmp_dir, "/tmp"); - if (runtime->var_tmp_dir) - var = strjoina(runtime->var_tmp_dir, "/tmp"); - } - - r = compile_read_write_paths(context, params, &rw); + r = apply_mount_namespace(unit, context, params, runtime); if (r < 0) { *exit_status = EXIT_NAMESPACE; return r; } - - r = setup_namespace( - (params->flags & EXEC_APPLY_CHROOT) ? context->root_directory : NULL, - &ns_info, - rw, - context->read_only_paths, - context->inaccessible_paths, - tmp, - var, - context->protect_home, - context->protect_system, - context->mount_flags); - - /* If we couldn't set up the namespace this is - * probably due to a missing capability. In this case, - * silently proceeed. */ - if (r == -EPERM || r == -EACCES) { - log_open(); - log_unit_debug_errno(unit, r, "Failed to set up namespace, assuming containerized execution, ignoring: %m"); - log_close(); - } else if (r < 0) { - *exit_status = EXIT_NAMESPACE; - return r; - } } if (context->working_directory_home) -- cgit v1.2.3-54-g00ecf From e7f1e7c6e2f91f3cad5eadfcc6ab9673caedb838 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Thu, 27 Oct 2016 09:21:44 +0200 Subject: core: move apply working directory code into its own apply_working_directory() --- src/core/execute.c | 52 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 2908ba8fa3..642add0360 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2056,6 +2056,33 @@ static int apply_mount_namespace(Unit *u, const ExecContext *context, return r; } +static int apply_working_directory(const ExecContext *context, + const ExecParameters *params, + const char *working_directory, + const bool needs_mount_ns) { + + if (params->flags & EXEC_APPLY_CHROOT) { + if (!needs_mount_ns && context->root_directory) + if (chroot(context->root_directory) < 0) + return -errno; + + if (chdir(working_directory) < 0 && + !context->working_directory_missing_ok) + return -errno; + + } else { + const char *d; + + d = strjoina(strempty(context->root_directory), "/", + strempty(working_directory)); + if (chdir(d) < 0 && + !context->working_directory_missing_ok) + return -errno; + } + + return 0; +} + static void append_socket_pair(int *array, unsigned *n, int pair[2]) { assert(array); assert(n); @@ -2542,27 +2569,10 @@ static int exec_child( } } - if (params->flags & EXEC_APPLY_CHROOT) { - if (!needs_mount_namespace && context->root_directory) - if (chroot(context->root_directory) < 0) { - *exit_status = EXIT_CHROOT; - return -errno; - } - - if (chdir(wd) < 0 && - !context->working_directory_missing_ok) { - *exit_status = EXIT_CHDIR; - return -errno; - } - } else { - const char *d; - - d = strjoina(strempty(context->root_directory), "/", strempty(wd)); - if (chdir(d) < 0 && - !context->working_directory_missing_ok) { - *exit_status = EXIT_CHDIR; - return -errno; - } + r = apply_working_directory(context, params, wd, needs_mount_namespace); + if (r < 0) { + *exit_status = EXIT_CHROOT; + return r; } #ifdef HAVE_SELINUX -- cgit v1.2.3-54-g00ecf From 2b3c1b9e9d7a09b1f974f8d702da8ebaeff036f6 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Thu, 27 Oct 2016 09:28:54 +0200 Subject: core: get the working directory value inside apply_working_directory() Improve apply_working_directory() and lets get the current working directory inside of it. --- src/core/execute.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 642add0360..0b6fcc9ac7 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2017,6 +2017,8 @@ static int apply_mount_namespace(Unit *u, const ExecContext *context, .protect_kernel_modules = context->protect_kernel_modules, }; + assert(context); + /* The runtime struct only contains the parent of the private /tmp, * which is non-accessible to world users. Inside of it there's a /tmp * that is sticky, and that's the one we want to use here. */ @@ -2058,27 +2060,31 @@ static int apply_mount_namespace(Unit *u, const ExecContext *context, static int apply_working_directory(const ExecContext *context, const ExecParameters *params, - const char *working_directory, + const char *home, const bool needs_mount_ns) { + const char *d; + const char *wd; + + assert(context); + + if (context->working_directory_home) + wd = home; + else if (context->working_directory) + wd = context->working_directory; + else + wd = "/"; if (params->flags & EXEC_APPLY_CHROOT) { if (!needs_mount_ns && context->root_directory) if (chroot(context->root_directory) < 0) return -errno; - if (chdir(working_directory) < 0 && - !context->working_directory_missing_ok) - return -errno; - - } else { - const char *d; + d = wd; + } else + d = strjoina(strempty(context->root_directory), "/", strempty(wd)); - d = strjoina(strempty(context->root_directory), "/", - strempty(working_directory)); - if (chdir(d) < 0 && - !context->working_directory_missing_ok) - return -errno; - } + if (chdir(d) < 0 && !context->working_directory_missing_ok) + return -errno; return 0; } @@ -2219,7 +2225,7 @@ static int exec_child( _cleanup_free_ char *mac_selinux_context_net = NULL; _cleanup_free_ gid_t *supplementary_gids = NULL; const char *username = NULL, *groupname = NULL; - const char *home = NULL, *shell = NULL, *wd; + const char *home = NULL, *shell = NULL; dev_t journal_stream_dev = 0; ino_t journal_stream_ino = 0; bool needs_mount_namespace; @@ -2553,13 +2559,6 @@ static int exec_child( } } - if (context->working_directory_home) - wd = home; - else if (context->working_directory) - wd = context->working_directory; - else - wd = "/"; - /* Drop group as early as possbile */ if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { r = enforce_groups(context, gid, supplementary_gids, ngids); @@ -2569,7 +2568,7 @@ static int exec_child( } } - r = apply_working_directory(context, params, wd, needs_mount_namespace); + r = apply_working_directory(context, params, home, needs_mount_namespace); if (r < 0) { *exit_status = EXIT_CHROOT; return r; -- cgit v1.2.3-54-g00ecf From 50b3dfb9d64872025450aa63765206720be471d6 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Tue, 25 Oct 2016 16:24:35 +0200 Subject: core: lets apply working directory just after mount namespaces This makes applying groups after applying the working directory, this may allow some flexibility but at same it is not a big deal since we don't execute or do anything between applying working directory and droping groups. --- src/core/execute.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 0b6fcc9ac7..a9e39f6fd7 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2559,6 +2559,13 @@ static int exec_child( } } + /* Apply just after mount namespace setup */ + r = apply_working_directory(context, params, home, needs_mount_namespace); + if (r < 0) { + *exit_status = EXIT_CHROOT; + return r; + } + /* Drop group as early as possbile */ if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { r = enforce_groups(context, gid, supplementary_gids, ngids); @@ -2568,12 +2575,6 @@ static int exec_child( } } - r = apply_working_directory(context, params, home, needs_mount_namespace); - if (r < 0) { - *exit_status = EXIT_CHROOT; - return r; - } - #ifdef HAVE_SELINUX if ((params->flags & EXEC_APPLY_PERMISSIONS) && mac_selinux_use() && -- cgit v1.2.3-54-g00ecf From 59e856c7d33e8260d0ac3a8e21318d6f0768d75b Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Thu, 27 Oct 2016 09:39:20 +0200 Subject: core: make unit argument const for apply seccomp functions --- src/core/execute.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index a9e39f6fd7..7f343c4902 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1470,7 +1470,7 @@ finish: return r; } -static int apply_protect_sysctl(Unit *u, const ExecContext *c) { +static int apply_protect_sysctl(const Unit *u, const ExecContext *c) { scmp_filter_ctx seccomp; int r; @@ -1501,7 +1501,7 @@ finish: return r; } -static int apply_protect_kernel_modules(Unit *u, const ExecContext *c) { +static int apply_protect_kernel_modules(const Unit *u, const ExecContext *c) { assert(c); /* Turn off module syscalls on ProtectKernelModules=yes */ @@ -1512,7 +1512,7 @@ static int apply_protect_kernel_modules(Unit *u, const ExecContext *c) { return seccomp_load_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM)); } -static int apply_private_devices(Unit *u, const ExecContext *c) { +static int apply_private_devices(const Unit *u, const ExecContext *c) { assert(c); /* If PrivateDevices= is set, also turn off iopl and all @raw-io syscalls. */ -- cgit v1.2.3-54-g00ecf From e100155dccaf90521f3e4da5af06736685e9e935 Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Thu, 27 Oct 2016 15:28:10 +0200 Subject: systemctl: warn when cat shows changed unit files (#4493) Suggested by @keszybz in #4488. --- src/systemctl/systemctl.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 35d5c11cc7..d311bbec1a 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5272,6 +5272,20 @@ static int cat(int argc, char *argv[], void *userdata) { else puts(""); + if (need_daemon_reload(bus, *name)) + fprintf(stderr, + "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n" + "%s# This output shows the current version of the unit's original fragment and drop-in files.\n" + "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n" + "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n", + ansi_highlight_red(), + *name, + ansi_highlight_red(), + ansi_highlight_red(), + ansi_highlight_red(), + arg_scope == UNIT_FILE_SYSTEM ? "" : " --user", + ansi_normal()); + if (fragment_path) { r = cat_file(fragment_path, false); if (r < 0) -- cgit v1.2.3-54-g00ecf From 4f985bd80278972912b80df1390f84d7a89f8d51 Mon Sep 17 00:00:00 2001 From: Michal Sekletar Date: Fri, 28 Oct 2016 12:09:14 +0200 Subject: udev: allow substitutions for SECLABEL key (#4505) --- man/udev.xml | 4 ++-- src/udev/udev-rules.c | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/man/udev.xml b/man/udev.xml index dd5563605c..3359fb0865 100644 --- a/man/udev.xml +++ b/man/udev.xml @@ -577,8 +577,8 @@ The NAME, SYMLINK, PROGRAM, OWNER, - GROUP, MODE, and - RUN fields support simple string substitutions. + GROUP, MODE, SECLABEL, + and RUN fields support simple string substitutions. The RUN substitutions are performed after all rules have been processed, right before the program is executed, allowing for the use of device properties set by earlier matching rules. For all other diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 7619c8371b..f6c416bf70 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -2218,10 +2218,16 @@ void udev_rules_apply_to_event(struct udev_rules *rules, rule->rule.filename_line); break; case TK_A_SECLABEL: { + char label_str[UTIL_LINE_SIZE] = {}; const char *name, *label; name = rules_str(rules, cur->key.attr_off); - label = rules_str(rules, cur->key.value_off); + udev_event_apply_format(event, rules_str(rules, cur->key.value_off), label_str, sizeof(label_str)); + if (label_str[0] != '\0') + label = label_str; + else + label = rules_str(rules, cur->key.value_off); + if (cur->key.op == OP_ASSIGN || cur->key.op == OP_ASSIGN_FINAL) udev_list_cleanup(&event->seclabel_list); udev_list_entry_add(&event->seclabel_list, name, label); -- cgit v1.2.3-54-g00ecf From e50e60b4744e48ee83e09c6ad62a6ee52836f4c8 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 28 Oct 2016 19:03:01 +0200 Subject: .gitignore: ignore precompiled GCC headers (#4516) Not sure since when this is the default behavior, but my local tree is full of such files. Let's ignore them for clarity. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f8336063b7..21fcf9841c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.a *.cache +*.gch *.la *.lo *.log -- cgit v1.2.3-54-g00ecf From 9021ff17e2a6e08e0675bc69c8b18e2ddb63de4a Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 22 Oct 2016 18:53:24 -0400 Subject: pid1: only log about added fd if it was really added If it was a duplicate, log nothing. --- src/core/service.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/service.c b/src/core/service.c index ee4f4983fc..c699a31941 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -368,6 +368,8 @@ static int service_add_fd_store(Service *s, int fd, const char *name) { ServiceFDStore *fs; int r; + /* fd is always consumed if we return >= 0 */ + assert(s); assert(fd >= 0); @@ -379,9 +381,8 @@ static int service_add_fd_store(Service *s, int fd, const char *name) { if (r < 0) return r; if (r > 0) { - /* Already included */ safe_close(fd); - return 1; + return 0; /* fd already included */ } } @@ -409,7 +410,7 @@ static int service_add_fd_store(Service *s, int fd, const char *name) { LIST_PREPEND(fd_store, s->fd_store, fs); s->n_fd_store++; - return 1; + return 1; /* fd newly stored */ } static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) { @@ -430,10 +431,9 @@ static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) { r = service_add_fd_store(s, fd, name); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Couldn't add fd to fd store: %m"); - if (r > 0) { + if (r > 0) log_unit_debug(UNIT(s), "Added fd to fd store."); - fd = -1; - } + fd = -1; } if (fdset_size(fds) > 0) @@ -2336,7 +2336,7 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, r = service_add_fd_store(s, fd, t); if (r < 0) log_unit_error_errno(u, r, "Failed to add fd to store: %m"); - else if (r > 0) + else fdset_remove(fds, fd); } -- cgit v1.2.3-54-g00ecf From 16f70d6362536c7432f0fd0af0155a5cd95c4a76 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 22 Oct 2016 20:01:37 -0400 Subject: pid1: nicely log when doing operation on stored fds Should help with debugging #4408. --- src/core/service.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/service.c b/src/core/service.c index c699a31941..0775bd6a9f 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -360,6 +360,10 @@ static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *us assert(fs); /* If we get either EPOLLHUP or EPOLLERR, it's time to remove this entry from the fd store */ + log_unit_debug(UNIT(fs->service), + "Received %s on stored fd %d (%s), closing.", + revents & EPOLLERR ? "EPOLLERR" : "EPOLLHUP", + fs->fd, strna(fs->fdname)); service_fd_store_unlink(fs); return 0; } @@ -432,7 +436,7 @@ static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) { if (r < 0) return log_unit_error_errno(UNIT(s), r, "Couldn't add fd to fd store: %m"); if (r > 0) - log_unit_debug(UNIT(s), "Added fd to fd store."); + log_unit_debug(UNIT(s), "Added fd %u (%s) to fd store.", fd, strna(name)); fd = -1; } @@ -1225,6 +1229,7 @@ static int service_spawn( return r; n_fds = r; + log_unit_debug(UNIT(s), "Passing %i fds to service", n_fds); } r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), timeout)); -- cgit v1.2.3-54-g00ecf From 99bdcdc7fc32def6cd6eab69c3869661b4b1888b Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 22 Oct 2016 20:32:59 -0400 Subject: man: add a note that FDSTORE=1 requires epoll-compatible fds Let's say that this was not obvious from our man page. --- man/sd_notify.xml | 41 +++++++++++++++++++---------------------- man/systemd.service.xml | 4 ++-- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/man/sd_notify.xml b/man/sd_notify.xml index 025fbec6c1..94542b80b8 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -205,28 +205,25 @@ FDSTORE=1 - Stores additional file descriptors in the - service manager. File descriptors sent this way will be - maintained per-service by the service manager and be passed - again using the usual file descriptor passing logic on the - next invocation of the service (see - sd_listen_fds3). - This is useful for implementing service restart schemes where - services serialize their state to /run, - push their file descriptors to the system manager, and are - then restarted, retrieving their state again via socket - passing and /run. Note that the service - manager will accept messages for a service only if - FileDescriptorStoreMax= is set to non-zero - for it (defaults to zero). See - systemd.service5 - for details. Multiple arrays of file descriptors may be sent - in separate messages, in which case the arrays are combined. - Note that the service manager removes duplicate file - descriptors before passing them to the service. Use - sd_pid_notify_with_fds() to send messages - with FDSTORE=1, see - below. + Stores additional file descriptors in the service manager. File + descriptors sent this way will be maintained per-service by the service manager + and will be passed again using the usual file descriptor passing logic on the next + invocation of the service, see + sd_listen_fds3. + This is useful for implementing service restart schemes where services serialize + their state to /run, push their file descriptors to the + system manager, and are then restarted, retrieving their state again via socket + passing and /run. Note that the service manager will accept + messages for a service only if FileDescriptorStoreMax= is set + to non-zero for it (defaults to zero, see + systemd.service5). + File descriptors must be pollable, see + epoll_ctl2. + Multiple arrays of file descriptors may be sent in separate messages, in which + case the arrays are combined. Note that the service manager removes duplicate + file descriptors before passing them to the service. Use + sd_pid_notify_with_fds() to send messages with + FDSTORE=1, see below. diff --git a/man/systemd.service.xml b/man/systemd.service.xml index 90b1312603..5c65957bda 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -852,13 +852,13 @@ serialized to /run and the file descriptors passed to the service manager, to allow restarts without losing state. Defaults to 0, i.e. no file descriptors - may be stored in the service manager by default. All file + may be stored in the service manager. All file descriptors passed to the service manager from a specific service are passed back to the service's main process on the next service restart. Any file descriptors passed to the service manager are automatically closed when POLLHUP or POLLERR is seen on them, or when the service is fully stopped - and no job queued or being executed for it. + and no job is queued or being executed for it. -- cgit v1.2.3-54-g00ecf From c7a7f78bb03d12ff0b1201739c712062ef437ea8 Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Sun, 30 Oct 2016 02:42:22 +0200 Subject: man: improve systemd-escape --path description The option does more than the documentation gave it credit for. --- man/systemd-escape.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/man/systemd-escape.xml b/man/systemd-escape.xml index dbb3869a24..acf8e0a02e 100644 --- a/man/systemd-escape.xml +++ b/man/systemd-escape.xml @@ -108,9 +108,10 @@ When escaping or unescaping a string, assume - it refers to a file system path. This enables special - processing of the initial / of the - path. + it refers to a file system path. This eliminates leading, + trailing or duplicate / characters + and rejects . and .. + path components. -- cgit v1.2.3-54-g00ecf From 918737f36524eee99588e46b9092c4a8f4242338 Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Sun, 30 Oct 2016 02:43:17 +0200 Subject: man: add missing period --- man/systemd-escape.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemd-escape.xml b/man/systemd-escape.xml index acf8e0a02e..7afac42613 100644 --- a/man/systemd-escape.xml +++ b/man/systemd-escape.xml @@ -97,7 +97,7 @@ Inserts the escaped strings in a unit name template. Takes a unit name template such as - foobar@.service May not be used in + foobar@.service. May not be used in conjunction with , or . -- cgit v1.2.3-54-g00ecf From 8bb36a1122b9e45a794188c10ca68e6dc33a271c Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Sun, 30 Oct 2016 02:44:07 +0200 Subject: man: make systemd-escape examples more consistent The first example wasn't phrased with "To ..." as the other three are, and the last example was lacking the colon. --- man/systemd-escape.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/systemd-escape.xml b/man/systemd-escape.xml index 7afac42613..5e95e22536 100644 --- a/man/systemd-escape.xml +++ b/man/systemd-escape.xml @@ -144,7 +144,7 @@ Examples - Escape a single string: + To escape a single string: $ systemd-escape 'Hallöchen, Meister' Hall\xc3\xb6chen\x2c\x20Meister @@ -156,7 +156,7 @@ Hallöchen, Meister $ systemd-escape -p --suffix=mount "/tmp//waldi/foobar/" tmp-waldi-foobar.mount - To generate instance names of three strings + To generate instance names of three strings: $ systemd-escape --template=systemd-nspawn@.service 'My Container 1' 'containerb' 'container/III' systemd-nspawn@My\x20Container\x201.service systemd-nspawn@containerb.service systemd-nspawn@container-III.service -- cgit v1.2.3-54-g00ecf From 0470289b6e93be7a65b1b3b2a2cc829bd20e08c8 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sun, 30 Oct 2016 10:21:29 -0400 Subject: tests: clarify test_path_startswith return value (#4508) A pendant for #4481. --- src/basic/path-util.c | 10 ++++++++++ src/test/test-path-util.c | 41 +++++++++++++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 0f5b20cf05..fd38f51c4c 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -354,6 +354,16 @@ char* path_startswith(const char *path, const char *prefix) { assert(path); assert(prefix); + /* Returns a pointer to the start of the first component after the parts matched by + * the prefix, iff + * - both paths are absolute or both paths are relative, + * and + * - each component in prefix in turn matches a component in path at the same position. + * An empty string will be returned when the prefix and path are equivalent. + * + * Returns NULL otherwise. + */ + if ((path[0] == '/') != (prefix[0] == '/')) return NULL; diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 0b10d8e25e..a6a09a0031 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -263,16 +263,37 @@ static void test_strv_resolve(void) { } static void test_path_startswith(void) { - assert_se(path_startswith("/foo/bar/barfoo/", "/foo")); - assert_se(path_startswith("/foo/bar/barfoo/", "/foo/")); - assert_se(path_startswith("/foo/bar/barfoo/", "/")); - assert_se(path_startswith("/foo/bar/barfoo/", "////")); - assert_se(path_startswith("/foo/bar/barfoo/", "/foo//bar/////barfoo///")); - assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo////")); - assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar///barfoo/")); - assert_se(path_startswith("/foo/bar/barfoo/", "/foo////bar/barfoo/")); - assert_se(path_startswith("/foo/bar/barfoo/", "////foo/bar/barfoo/")); - assert_se(path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo")); + const char *p; + + p = path_startswith("/foo/bar/barfoo/", "/foo"); + assert_se(streq_ptr(p, "bar/barfoo/")); + + p = path_startswith("/foo/bar/barfoo/", "/foo/"); + assert_se(streq_ptr(p, "bar/barfoo/")); + + p = path_startswith("/foo/bar/barfoo/", "/"); + assert_se(streq_ptr(p, "foo/bar/barfoo/")); + + p = path_startswith("/foo/bar/barfoo/", "////"); + assert_se(streq_ptr(p, "foo/bar/barfoo/")); + + p = path_startswith("/foo/bar/barfoo/", "/foo//bar/////barfoo///"); + assert_se(streq_ptr(p, "")); + + p = path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo////"); + assert_se(streq_ptr(p, "")); + + p = path_startswith("/foo/bar/barfoo/", "/foo/bar///barfoo/"); + assert_se(streq_ptr(p, "")); + + p = path_startswith("/foo/bar/barfoo/", "/foo////bar/barfoo/"); + assert_se(streq_ptr(p, "")); + + p = path_startswith("/foo/bar/barfoo/", "////foo/bar/barfoo/"); + assert_se(streq_ptr(p, "")); + + p = path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo"); + assert_se(streq_ptr(p, "")); assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa/")); assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa")); -- cgit v1.2.3-54-g00ecf From 52028838a1bc5f55f623f5f0344ee685d87d1fd0 Mon Sep 17 00:00:00 2001 From: George Hilliard Date: Sun, 30 Oct 2016 09:25:31 -0500 Subject: Implement VeraCrypt volume handling in crypttab (#4501) This introduces a new option, `tcrypt-veracrypt`, that sets the corresponding VeraCrypt flag in the flags passed to cryptsetup. --- man/crypttab.xml | 11 +++++++++++ src/cryptsetup/cryptsetup.c | 14 ++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/man/crypttab.xml b/man/crypttab.xml index 4b8d4aa3d6..17976f3704 100644 --- a/man/crypttab.xml +++ b/man/crypttab.xml @@ -326,6 +326,17 @@ option implies . + + + + Check for a VeraCrypt volume. VeraCrypt is a fork of + TrueCrypt that is mostly compatible, but uses different, stronger key + derivation algorithms that cannot be detected without this flag. + Enabling this option could substantially slow down unlocking, because + VeraCrypt's key derivation takes much longer than TrueCrypt's. This + option implies . + + diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 9927621ea0..ff5a3f36fb 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -52,6 +52,7 @@ static bool arg_verify = false; static bool arg_discards = false; static bool arg_tcrypt_hidden = false; static bool arg_tcrypt_system = false; +static bool arg_tcrypt_veracrypt = false; static char **arg_tcrypt_keyfiles = NULL; static uint64_t arg_offset = 0; static uint64_t arg_skip = 0; @@ -179,6 +180,14 @@ static int parse_one_option(const char *option) { } else if (streq(option, "tcrypt-system")) { arg_type = CRYPT_TCRYPT; arg_tcrypt_system = true; + } else if (streq(option, "tcrypt-veracrypt")) { +#ifdef CRYPT_TCRYPT_VERA_MODES + arg_type = CRYPT_TCRYPT; + arg_tcrypt_veracrypt = true; +#else + log_error("This version of cryptsetup does not support tcrypt-veracrypt; refusing."); + return -EINVAL; +#endif } else if (STR_IN_SET(option, "plain", "swap", "tmp")) arg_type = CRYPT_PLAIN; else if (startswith(option, "timeout=")) { @@ -441,6 +450,11 @@ static int attach_tcrypt( if (arg_tcrypt_system) params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER; +#ifdef CRYPT_TCRYPT_VERA_MODES + if (arg_tcrypt_veracrypt) + params.flags |= CRYPT_TCRYPT_VERA_MODES; +#endif + if (key_file) { r = read_one_line_file(key_file, &passphrase); if (r < 0) { -- cgit v1.2.3-54-g00ecf From b17649ee5e9d620b752d17f783ea380b5111d060 Mon Sep 17 00:00:00 2001 From: Jakub Wilk Date: Mon, 31 Oct 2016 13:08:08 +0100 Subject: man: fix typos (#4527) --- man/machinectl.xml | 2 +- man/sd_journal_stream_fd.xml | 2 +- man/systemctl.xml | 2 +- man/systemd-machine-id-setup.xml | 4 ++-- man/systemd-socket-activate.xml | 2 +- man/systemd-system.conf.xml | 2 +- man/systemd.exec.xml | 4 ++-- man/systemd.offline-updates.xml | 2 +- man/systemd.target.xml | 2 +- man/tmpfiles.d.xml | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/man/machinectl.xml b/man/machinectl.xml index 0d57c01765..5a6ec294d2 100644 --- a/man/machinectl.xml +++ b/man/machinectl.xml @@ -188,7 +188,7 @@ When used with the shell command, chooses the user ID to open the interactive shell session as. If the argument to the shell - command also specifies an user name, this option is ignored. If the name is not specified + command also specifies a user name, this option is ignored. If the name is not specified in either way, root will be used by default. Note that this switch is not supported for the login command (see below). diff --git a/man/sd_journal_stream_fd.xml b/man/sd_journal_stream_fd.xml index 226298ae1b..db88eba1bc 100644 --- a/man/sd_journal_stream_fd.xml +++ b/man/sd_journal_stream_fd.xml @@ -104,7 +104,7 @@ Notes - Function sd_journal_stream_fd() is thread-safe and may be be called + Function sd_journal_stream_fd() is thread-safe and may be called from multiple threads. All calls will return the same file descriptor, although temporarily multiple file descriptors may be open. diff --git a/man/systemctl.xml b/man/systemctl.xml index 225eb06d8b..ae3296d132 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1265,7 +1265,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service foo.service.d/ with all their contained files are removed, both below the persistent and runtime configuration directories (i.e. below /etc/systemd/system and /run/systemd/system); if the unit file has a vendor-supplied version (i.e. a unit file - located below /usr) any matching peristent or runtime unit file that overrides it is + located below /usr) any matching persistent or runtime unit file that overrides it is removed, too. Note that if a unit file has no vendor-supplied version (i.e. is only defined below /etc/systemd/system or /run/systemd/system, but not in a unit file stored below /usr), then it is not removed. Also, if a unit is masked, it is diff --git a/man/systemd-machine-id-setup.xml b/man/systemd-machine-id-setup.xml index 749987a937..944e899bd4 100644 --- a/man/systemd-machine-id-setup.xml +++ b/man/systemd-machine-id-setup.xml @@ -82,7 +82,7 @@ /etc/machine-id. If run inside a KVM virtual machine and a UUID - is was configured (via the + is configured (via the option), this UUID is used to initialize the machine ID. The caller must ensure that the UUID passed is sufficiently unique and is different for every booted instance of the @@ -154,7 +154,7 @@ - Print the machine ID generated or commited after the operation is complete. + Print the machine ID generated or committed after the operation is complete. diff --git a/man/systemd-socket-activate.xml b/man/systemd-socket-activate.xml index 2cf3a7d377..1c0619a840 100644 --- a/man/systemd-socket-activate.xml +++ b/man/systemd-socket-activate.xml @@ -142,7 +142,7 @@ FileDescriptorName= in socket unit files, and enables use of sd_listen_fds_with_names3. Multiple entries may be specifies using separate options or by separating names with colons - (:) in one option. In case more names are given than descriptors, superfluous ones willl be + (:) in one option. In case more names are given than descriptors, superfluous ones will be ignored. In case less names are given than descriptors, the remaining file descriptors will be unnamed. diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index 80cad7f09c..e4e81f7f2e 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -330,7 +330,7 @@ TasksAccounting=. See systemd.resource-control5 for details on the per-unit - settings. DefaulTasksAccounting= defaults + settings. DefaultTasksAccounting= defaults to on, the other three settings to off. diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 54ec7e29ca..d3a19c505d 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1090,7 +1090,7 @@ mechanism. Almost no services need to write to these at runtime; it is hence recommended to turn this on for most services. For this setting the same restrictions regarding mount propagation and privileges apply as for ReadOnlyPaths= and related calls, see above. Defaults to off. - Note that this option does not prevent kernel tuning through IPC interfaces and exeternal programs. However + Note that this option does not prevent kernel tuning through IPC interfaces and external programs. However InaccessiblePaths= can be used to make some IPC file system objects inaccessible. @@ -1464,7 +1464,7 @@ Takes a boolean argument. If true, explicit module loading will be denied. This allows to turn off module load and unload operations on modular - kernels. It is recomended to turn this on for most services that do not need special + kernels. It is recommended to turn this on for most services that do not need special file systems or extra kernel modules to work. Default to off. Enabling this option removes CAP_SYS_MODULE from the capability bounding set for the unit, and installs a system call filter to block module system calls, diff --git a/man/systemd.offline-updates.xml b/man/systemd.offline-updates.xml index f404c8d72f..07a5225512 100644 --- a/man/systemd.offline-updates.xml +++ b/man/systemd.offline-updates.xml @@ -143,7 +143,7 @@ FailureAction= makes sure that the specified unit is activated if your script exits uncleanly (by non-zero error code, or signal/coredump). If your script succeeds you should trigger the reboot in your own code, for example by invoking logind's - Reboot() call or calling systemct reboot. See + Reboot() call or calling systemctl reboot. See logind dbus API for details. diff --git a/man/systemd.target.xml b/man/systemd.target.xml index 2e35e54fc4..b3cccd4e52 100644 --- a/man/systemd.target.xml +++ b/man/systemd.target.xml @@ -83,7 +83,7 @@ Automatic Dependencies Unless DefaultDependencies= is set to - in either of releated units or an explicit ordering + in either of related units or an explicit ordering dependency is already defined, target units will implicitly complement all configured dependencies of type Wants= or Requires= with dependencies of type diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml index 75fb901102..e040a1636d 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -644,7 +644,7 @@ d /run/uscreens 0755 root screen 10d12h t /run/cups - - - - security.SMACK64=printing user.attr-with-spaces="foo bar" - The direcory will be owned by root and have default mode. It's contents are + The directory will be owned by root and have default mode. Its contents are not subject to time based cleanup, but will be obliterated when systemd-tmpfiles --remove runs. -- cgit v1.2.3-54-g00ecf From 3e2161153ca455ed66f5e5039b386a3a5627b709 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Mon, 31 Oct 2016 13:16:44 -0400 Subject: test-compression: allow the file to compress to be specified I'm seeing strange decompression errors with lz4, which might be content-dependent. Extend test-compression to allow testing specific content. (Edit: PEBKAC: lzcat and lz4cat are not the same beast. Nevertheless, the test might still be useful in the future.) --- src/journal/test-compress.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c index 00e5222a1c..72cadf1771 100644 --- a/src/journal/test-compress.c +++ b/src/journal/test-compress.c @@ -247,6 +247,9 @@ int main(int argc, char *argv[]) { "text\0foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF" "foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF"; + /* The file to test compression on can be specified as the first argument */ + const char *srcfile = argc > 1 ? argv[1] : argv[0]; + char data[512] = "random\0"; char huge[4096*1024]; @@ -275,7 +278,7 @@ int main(int argc, char *argv[]) { huge, sizeof(huge), true); test_compress_stream(OBJECT_COMPRESSED_XZ, "xzcat", - compress_stream_xz, decompress_stream_xz, argv[0]); + compress_stream_xz, decompress_stream_xz, srcfile); #else log_info("/* XZ test skipped */"); #endif @@ -297,7 +300,7 @@ int main(int argc, char *argv[]) { huge, sizeof(huge), true); test_compress_stream(OBJECT_COMPRESSED_LZ4, "lz4cat", - compress_stream_lz4, decompress_stream_lz4, argv[0]); + compress_stream_lz4, decompress_stream_lz4, srcfile); test_lz4_decompress_partial(); #else -- cgit v1.2.3-54-g00ecf From 67ae43665e7e03becba197e98df5b3ce40269567 Mon Sep 17 00:00:00 2001 From: "Brian J. Murrell" Date: Mon, 31 Oct 2016 23:48:00 -0400 Subject: Recognise Lustre as a remote file system (#4530) Lustre is also a remote file system that wants the network to be up before it is mounted. --- src/basic/mount-util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c index 2985cc475a..c8f8022578 100644 --- a/src/basic/mount-util.c +++ b/src/basic/mount-util.c @@ -525,6 +525,7 @@ bool fstype_is_network(const char *fstype) { "glusterfs\0" "pvfs2\0" /* OrangeFS */ "ocfs2\0" + "lustre\0" ; const char *x; -- cgit v1.2.3-54-g00ecf From aa34055ffbc0d862333c47023b56ee55d813c2a6 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Tue, 1 Nov 2016 11:33:18 -0400 Subject: seccomp: allow specifying arm64, mips, ppc (#4491) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "Secondary arch" table for mips is entirely speculative… --- man/systemd.exec.xml | 41 +++++++-------- src/shared/seccomp-util.c | 129 +++++++++++++++++++++++++++++++++------------- src/test/test-seccomp.c | 33 ++++++++++++ 3 files changed, 145 insertions(+), 58 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index d3a19c505d..11029ca186 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1396,28 +1396,25 @@ SystemCallArchitectures= - Takes a space-separated list of architecture - identifiers to include in the system call filter. The known - architecture identifiers are x86, - x86-64, x32, - arm, s390, - s390x as well as the special identifier - native. Only system calls of the - specified architectures will be permitted to processes of this - unit. This is an effective way to disable compatibility with - non-native architectures for processes, for example to - prohibit execution of 32-bit x86 binaries on 64-bit x86-64 - systems. The special native identifier - implicitly maps to the native architecture of the system (or - more strictly: to the architecture the system manager is - compiled for). If running in user mode, or in system mode, - but without the CAP_SYS_ADMIN - capability (e.g. setting User=nobody), - NoNewPrivileges=yes is implied. Note - that setting this option to a non-empty list implies that - native is included too. By default, this - option is set to the empty list, i.e. no architecture system - call filtering is applied. + Takes a space-separated list of architecture identifiers to + include in the system call filter. The known architecture identifiers are the same + as for ConditionArchitecture= described in + systemd.unit5, + as well as x32, mips64-n32, + mips64-le-n32, and the special identifier + native. Only system calls of the specified architectures will + be permitted to processes of this unit. This is an effective way to disable + compatibility with non-native architectures for processes, for example to prohibit + execution of 32-bit x86 binaries on 64-bit x86-64 systems. The special + native identifier implicitly maps to the native architecture + of the system (or more strictly: to the architecture the system manager is + compiled for). If running in user mode, or in system mode, but without the + CAP_SYS_ADMIN capability (e.g. setting + User=nobody), NoNewPrivileges=yes is + implied. Note that setting this option to a non-empty list implies that + native is included too. By default, this option is set to the + empty list, i.e. no architecture system call filtering is applied. + diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 6252cd16a6..1cbbb9d757 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -29,23 +29,49 @@ #include "util.h" const char* seccomp_arch_to_string(uint32_t c) { + /* Maintain order used in . + * + * Names used here should be the same as those used for ConditionArchitecture=, + * except for "subarchitectures" like x32. */ - if (c == SCMP_ARCH_NATIVE) + switch(c) { + case SCMP_ARCH_NATIVE: return "native"; - if (c == SCMP_ARCH_X86) + case SCMP_ARCH_X86: return "x86"; - if (c == SCMP_ARCH_X86_64) + case SCMP_ARCH_X86_64: return "x86-64"; - if (c == SCMP_ARCH_X32) + case SCMP_ARCH_X32: return "x32"; - if (c == SCMP_ARCH_ARM) + case SCMP_ARCH_ARM: return "arm"; - if (c == SCMP_ARCH_S390) + case SCMP_ARCH_AARCH64: + return "arm64"; + case SCMP_ARCH_MIPS: + return "mips"; + case SCMP_ARCH_MIPS64: + return "mips64"; + case SCMP_ARCH_MIPS64N32: + return "mips64-n32"; + case SCMP_ARCH_MIPSEL: + return "mips-le"; + case SCMP_ARCH_MIPSEL64: + return "mips64-le"; + case SCMP_ARCH_MIPSEL64N32: + return "mips64-le-n32"; + case SCMP_ARCH_PPC: + return "ppc"; + case SCMP_ARCH_PPC64: + return "ppc64"; + case SCMP_ARCH_PPC64LE: + return "ppc64-le"; + case SCMP_ARCH_S390: return "s390"; - if (c == SCMP_ARCH_S390X) + case SCMP_ARCH_S390X: return "s390x"; - - return NULL; + default: + return NULL; + } } int seccomp_arch_from_string(const char *n, uint32_t *ret) { @@ -64,6 +90,26 @@ int seccomp_arch_from_string(const char *n, uint32_t *ret) { *ret = SCMP_ARCH_X32; else if (streq(n, "arm")) *ret = SCMP_ARCH_ARM; + else if (streq(n, "arm64")) + *ret = SCMP_ARCH_AARCH64; + else if (streq(n, "mips")) + *ret = SCMP_ARCH_MIPS; + else if (streq(n, "mips64")) + *ret = SCMP_ARCH_MIPS64; + else if (streq(n, "mips64-n32")) + *ret = SCMP_ARCH_MIPS64N32; + else if (streq(n, "mips-le")) + *ret = SCMP_ARCH_MIPSEL; + else if (streq(n, "mips64-le")) + *ret = SCMP_ARCH_MIPSEL64; + else if (streq(n, "mips64-le-n32")) + *ret = SCMP_ARCH_MIPSEL64N32; + else if (streq(n, "ppc")) + *ret = SCMP_ARCH_PPC; + else if (streq(n, "ppc64")) + *ret = SCMP_ARCH_PPC64; + else if (streq(n, "ppc64-le")) + *ret = SCMP_ARCH_PPC64LE; else if (streq(n, "s390")) *ret = SCMP_ARCH_S390; else if (streq(n, "s390x")) @@ -101,41 +147,52 @@ finish: return r; } -int seccomp_add_secondary_archs(scmp_filter_ctx c) { - -#if defined(__i386__) || defined(__x86_64__) - int r; +int seccomp_add_secondary_archs(scmp_filter_ctx ctx) { /* Add in all possible secondary archs we are aware of that * this kernel might support. */ - r = seccomp_arch_add(c, SCMP_ARCH_X86); - if (r < 0 && r != -EEXIST) - return r; - - r = seccomp_arch_add(c, SCMP_ARCH_X86_64); - if (r < 0 && r != -EEXIST) - return r; - - r = seccomp_arch_add(c, SCMP_ARCH_X32); - if (r < 0 && r != -EEXIST) - return r; + static const int seccomp_arches[] = { +#if defined(__i386__) || defined(__x86_64__) + SCMP_ARCH_X86, + SCMP_ARCH_X86_64, + SCMP_ARCH_X32, + +#elif defined(__arm__) || defined(__aarch64__) + SCMP_ARCH_ARM, + SCMP_ARCH_AARCH64, + +#elif defined(__arm__) || defined(__aarch64__) + SCMP_ARCH_ARM, + SCMP_ARCH_AARCH64, + +#elif defined(__mips__) || defined(__mips64__) + SCMP_ARCH_MIPS, + SCMP_ARCH_MIPS64, + SCMP_ARCH_MIPS64N32, + SCMP_ARCH_MIPSEL, + SCMP_ARCH_MIPSEL64, + SCMP_ARCH_MIPSEL64N32, + +#elif defined(__powerpc__) || defined(__powerpc64__) + SCMP_ARCH_PPC, + SCMP_ARCH_PPC64, + SCMP_ARCH_PPC64LE, #elif defined(__s390__) || defined(__s390x__) - int r; - - /* Add in all possible secondary archs we are aware of that - * this kernel might support. */ - - r = seccomp_arch_add(c, SCMP_ARCH_S390); - if (r < 0 && r != -EEXIST) - return r; + SCMP_ARCH_S390, + SCMP_ARCH_S390X, +#endif + }; - r = seccomp_arch_add(c, SCMP_ARCH_S390X); - if (r < 0 && r != -EEXIST) - return r; + unsigned i; + int r; -#endif + for (i = 0; i < ELEMENTSOF(seccomp_arches); i++) { + r = seccomp_arch_add(ctx, seccomp_arches[i]); + if (r < 0 && r != -EEXIST) + return r; + } return 0; } diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c index 0060ecdf02..43d1567288 100644 --- a/src/test/test-seccomp.c +++ b/src/test/test-seccomp.c @@ -25,6 +25,8 @@ #include "macro.h" #include "process-util.h" #include "seccomp-util.h" +#include "string-util.h" +#include "util.h" static void test_seccomp_arch_to_string(void) { uint32_t a, b; @@ -38,6 +40,36 @@ static void test_seccomp_arch_to_string(void) { assert_se(a == b); } +static void test_architecture_table(void) { + const char *n, *n2; + + NULSTR_FOREACH(n, + "native\0" + "x86\0" + "x86-64\0" + "x32\0" + "arm\0" + "arm64\0" + "mips\0" + "mips64\0" + "mips64-n32\0" + "mips-le\0" + "mips64-le\0" + "mips64-le-n32\0" + "ppc\0" + "ppc64\0" + "ppc64-le\0" + "s390\0" + "s390x\0") { + uint32_t c; + + assert_se(seccomp_arch_from_string(n, &c) >= 0); + n2 = seccomp_arch_to_string(c); + log_info("seccomp-arch: %s → 0x%"PRIx32" → %s", n, c, n2); + assert_se(streq_ptr(n, n2)); + } +} + static void test_syscall_filter_set_find(void) { assert_se(!syscall_filter_set_find(NULL)); assert_se(!syscall_filter_set_find("")); @@ -96,6 +128,7 @@ static void test_filter_sets(void) { int main(int argc, char *argv[]) { test_seccomp_arch_to_string(); + test_architecture_table(); test_syscall_filter_set_find(); test_filter_sets(); -- cgit v1.2.3-54-g00ecf From f0bfbfac43b7faa68ef1bb2ad659c191b9ec85d2 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 22 Oct 2016 22:16:02 -0400 Subject: core: when restarting services, don't close fds We would close all the stored fds in service_release_resources(), which of course broke the whole concept of storing fds over service restart. Fixes #4408. --- src/core/service.c | 22 +++++++++++++++------- src/core/unit.c | 6 ++++-- src/core/unit.h | 2 +- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/core/service.c b/src/core/service.c index 0775bd6a9f..00ce500fd3 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -289,7 +289,17 @@ static void service_fd_store_unlink(ServiceFDStore *fs) { free(fs); } -static void service_release_resources(Unit *u) { +static void service_release_fd_store(Service *s) { + assert(s); + + log_unit_debug(UNIT(s), "Releasing all stored fds"); + while (s->fd_store) + service_fd_store_unlink(s->fd_store); + + assert(s->n_fd_store == 0); +} + +static void service_release_resources(Unit *u, bool inactive) { Service *s = SERVICE(u); assert(s); @@ -297,16 +307,14 @@ static void service_release_resources(Unit *u) { if (!s->fd_store && s->stdin_fd < 0 && s->stdout_fd < 0 && s->stderr_fd < 0) return; - log_unit_debug(u, "Releasing all resources."); + log_unit_debug(u, "Releasing resources."); s->stdin_fd = safe_close(s->stdin_fd); s->stdout_fd = safe_close(s->stdout_fd); s->stderr_fd = safe_close(s->stderr_fd); - while (s->fd_store) - service_fd_store_unlink(s->fd_store); - - assert(s->n_fd_store == 0); + if (inactive) + service_release_fd_store(s); } static void service_done(Unit *u) { @@ -350,7 +358,7 @@ static void service_done(Unit *u) { s->timer_event_source = sd_event_source_unref(s->timer_event_source); - service_release_resources(u); + service_release_resources(u, true); } static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) { diff --git a/src/core/unit.c b/src/core/unit.c index cabb1050a8..8e6cef103b 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -302,6 +302,7 @@ int unit_set_description(Unit *u, const char *description) { bool unit_check_gc(Unit *u) { UnitActiveState state; + bool inactive; assert(u); if (u->job) @@ -311,16 +312,17 @@ bool unit_check_gc(Unit *u) { return true; state = unit_active_state(u); + inactive = state == UNIT_INACTIVE; /* If the unit is inactive and failed and no job is queued for * it, then release its runtime resources */ if (UNIT_IS_INACTIVE_OR_FAILED(state) && UNIT_VTABLE(u)->release_resources) - UNIT_VTABLE(u)->release_resources(u); + UNIT_VTABLE(u)->release_resources(u, inactive); /* But we keep the unit object around for longer when it is * referenced or configured to not be gc'ed */ - if (state != UNIT_INACTIVE) + if (!inactive) return true; if (u->no_gc) diff --git a/src/core/unit.h b/src/core/unit.h index adcdee6db6..e01ec7a775 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -372,7 +372,7 @@ struct UnitVTable { /* When the unit is not running and no job for it queued we * shall release its runtime resources */ - void (*release_resources)(Unit *u); + void (*release_resources)(Unit *u, bool inactive); /* Invoked on every child that died */ void (*sigchld_event)(Unit *u, pid_t pid, int code, int status); -- cgit v1.2.3-54-g00ecf From bff653e3970bb79832568ae86b095ee530b62302 Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Thu, 20 Oct 2016 13:18:12 +0000 Subject: tests: add test that journald keeps fds over termination by signal This test fails before previous commit, and passes with it. --- test/TEST-04-JOURNAL/test-journal.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh index 6646eccfa7..493ff00ce0 100755 --- a/test/TEST-04-JOURNAL/test-journal.sh +++ b/test/TEST-04-JOURNAL/test-journal.sh @@ -59,4 +59,12 @@ sleep 3 systemctl stop forever-print-hola [[ ! -f "/i-lose-my-logs" ]] +# https://github.com/systemd/systemd/issues/4408 +rm -f /i-lose-my-logs +systemctl start forever-print-hola +sleep 3 +systemctl kill --signal=SIGKILL systemd-journald +sleep 3 +[[ ! -f "/i-lose-my-logs" ]] + touch /testok -- cgit v1.2.3-54-g00ecf From 4887b656c22af059d4e833de7b56544f24951184 Mon Sep 17 00:00:00 2001 From: Jiří Pírko Date: Wed, 2 Nov 2016 03:46:01 +0100 Subject: udev: net_id: add support for phys_port_name attribute (#4506) Switch drivers uses phys_port_name attribute to pass front panel port name to user. Use it to generate netdev names. Signed-off-by: Jiri Pirko --- src/udev/udev-builtin-net_id.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c index a7be2a4eed..0eb2500dd2 100644 --- a/src/udev/udev-builtin-net_id.c +++ b/src/udev/udev-builtin-net_id.c @@ -35,10 +35,12 @@ * Type of names: * b — BCMA bus core number * c — CCW bus group name, without leading zeros [s390] - * o[d] — on-board device index number - * s[f][d] — hotplug slot index number + * o[n|d] + * — on-board device index number + * s[f][n|d] + * — hotplug slot index number * x — MAC address - * [P]ps[f][d] + * [P]ps[f][n|d] * — PCI geographical location * [P]ps[f][u][..][c][i] * — USB port number chain @@ -137,7 +139,7 @@ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) { unsigned dev_port = 0; size_t l; char *s; - const char *attr; + const char *attr, *port_name; int idx; /* ACPI _DSM — device specific method for naming a PCI or PCI Express device */ @@ -164,10 +166,15 @@ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) { if (attr) dev_port = strtol(attr, NULL, 10); + /* kernel provided front panel port name for multiple port PCI device */ + port_name = udev_device_get_sysattr_value(dev, "phys_port_name"); + s = names->pci_onboard; l = sizeof(names->pci_onboard); l = strpcpyf(&s, l, "o%d", idx); - if (dev_port > 0) + if (port_name) + l = strpcpyf(&s, l, "n%s", port_name); + else if (dev_port > 0) l = strpcpyf(&s, l, "d%d", dev_port); if (l == 0) names->pci_onboard[0] = '\0'; @@ -202,7 +209,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { unsigned domain, bus, slot, func, dev_port = 0; size_t l; char *s; - const char *attr; + const char *attr, *port_name; struct udev_device *pci = NULL; char slots[256], str[256]; _cleanup_closedir_ DIR *dir = NULL; @@ -217,6 +224,9 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { if (attr) dev_port = strtol(attr, NULL, 10); + /* kernel provided front panel port name for multiple port PCI device */ + port_name = udev_device_get_sysattr_value(dev, "phys_port_name"); + /* compose a name based on the raw kernel's PCI bus, slot numbers */ s = names->pci_path; l = sizeof(names->pci_path); @@ -225,7 +235,9 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { l = strpcpyf(&s, l, "p%us%u", bus, slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = strpcpyf(&s, l, "f%u", func); - if (dev_port > 0) + if (port_name) + l = strpcpyf(&s, l, "n%s", port_name); + else if (dev_port > 0) l = strpcpyf(&s, l, "d%u", dev_port); if (l == 0) names->pci_path[0] = '\0'; @@ -275,7 +287,9 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { l = strpcpyf(&s, l, "s%d", hotplug_slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = strpcpyf(&s, l, "f%d", func); - if (dev_port > 0) + if (port_name) + l = strpcpyf(&s, l, "n%s", port_name); + else if (dev_port > 0) l = strpcpyf(&s, l, "d%d", dev_port); if (l == 0) names->pci_slot[0] = '\0'; -- cgit v1.2.3-54-g00ecf From 67234d218b11ce66d44f2479f4df8fdbd07d9e5b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 12:43:53 +0200 Subject: update TODO --- TODO | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TODO b/TODO index 7e21c3e8d5..c8266a549d 100644 --- a/TODO +++ b/TODO @@ -32,6 +32,11 @@ Janitorial Clean-ups: Features: +* drop nss-myhostname in favour of nss-resolve? + +* drop internal dlopen() based nss-dns fallback in nss-resolve, and rely on the + external nsswitch.conf based one + * add a percentage syntax for TimeoutStopSec=, e.g. TimeoutStopSec=150%, and then use that for the setting used in user@.service. It should be understood relative to the configured default value. -- cgit v1.2.3-54-g00ecf From c79aff9a82abf361aea47b5c745ed9729c5f0212 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 15:38:36 +0200 Subject: seccomp: add clock query and sleeping syscalls to "@default" group Timing and sleep are so basic operations, it makes very little sense to ever block them, hence don't. --- man/systemd.exec.xml | 38 ++++++++++++++------------------------ src/shared/seccomp-util.c | 9 ++++++++- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 11029ca186..e7d8bb23a4 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1255,30 +1255,20 @@ SystemCallFilter= - Takes a space-separated list of system call - names. If this setting is used, all system calls executed by - the unit processes except for the listed ones will result in - immediate process termination with the - SIGSYS signal (whitelisting). If the - first character of the list is ~, the - effect is inverted: only the listed system calls will result - in immediate process termination (blacklisting). If running in - user mode, or in system mode, but without the - CAP_SYS_ADMIN capability (e.g. setting - User=nobody), - NoNewPrivileges=yes is implied. This - feature makes use of the Secure Computing Mode 2 interfaces of - the kernel ('seccomp filtering') and is useful for enforcing a - minimal sandboxing environment. Note that the - execve, - rt_sigreturn, - sigreturn, - exit_group, exit - system calls are implicitly whitelisted and do not need to be - listed explicitly. This option may be specified more than once, - in which case the filter masks are merged. If the empty string - is assigned, the filter is reset, all prior assignments will - have no effect. This does not affect commands prefixed with +. + Takes a space-separated list of system call names. If this setting is used, all system calls + executed by the unit processes except for the listed ones will result in immediate process termination with the + SIGSYS signal (whitelisting). If the first character of the list is ~, + the effect is inverted: only the listed system calls will result in immediate process termination + (blacklisting). If running in user mode, or in system mode, but without the CAP_SYS_ADMIN + capability (e.g. setting User=nobody), NoNewPrivileges=yes is + implied. This feature makes use of the Secure Computing Mode 2 interfaces of the kernel ('seccomp filtering') + and is useful for enforcing a minimal sandboxing environment. Note that the execve, + exit, exit_group, getrlimit, + rt_sigreturn, sigreturn system calls and the system calls for + querying time and sleeping are implicitly whitelisted and do not need to be listed explicitly. This option may + be specified more than once, in which case the filter masks are merged. If the empty string is assigned, the + filter is reset, all prior assignments will have no effect. This does not affect commands prefixed with + +. If you specify both types of this option (i.e. whitelisting and blacklisting), the first encountered will diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 1cbbb9d757..ad5782fb29 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -253,15 +253,22 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "sys_debug_setcontext\0" }, [SYSCALL_FILTER_SET_DEFAULT] = { - /* Default list */ + /* Default list: the most basic of operations */ .name = "@default", .value = + "clock_getres\0" + "clock_gettime\0" + "clock_nanosleep\0" "execve\0" "exit\0" "exit_group\0" "getrlimit\0" /* make sure processes can query stack size and such */ + "gettimeofday\0" + "nanosleep\0" + "pause\0" "rt_sigreturn\0" "sigreturn\0" + "time\0" }, [SYSCALL_FILTER_SET_IO_EVENT] = { /* Event loop use */ -- cgit v1.2.3-54-g00ecf From a8c157ff3081ee963adb0d046015abf9a271fa67 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 15:42:10 +0200 Subject: seccomp: drop execve() from @process list The system call is already part in @default hence implicitly allowed anyway. Also, if it is actually blocked then systemd couldn't execute the service in question anymore, since the application of seccomp is immediately followed by it. --- man/systemd.exec.xml | 2 +- src/shared/seccomp-util.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index e7d8bb23a4..d45e5362dc 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1347,7 +1347,7 @@ @process - Process control, execution, namespaces (execve2, kill2, namespaces7, … + Process control, execution, namespaces (clone2, kill2, namespaces7, … @raw-io diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index ad5782fb29..70723e9e4e 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -443,7 +443,6 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { .value = "arch_prctl\0" "clone\0" - "execve\0" "execveat\0" "fork\0" "kill\0" -- cgit v1.2.3-54-g00ecf From cd5bfd7e60c08cfad41bcf881f550c424b2f3e44 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 15:43:31 +0200 Subject: seccomp: include pipes and memfd in @ipc These system calls clearly fall in the @ipc category, hence should be listed there, simply to avoid confusion and surprise by the user. --- man/systemd.exec.xml | 2 +- src/shared/seccomp-util.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index d45e5362dc..466511aaf3 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1319,7 +1319,7 @@ @ipc - SysV IPC, POSIX Message Queues or other IPC (mq_overview7, svipc7) + Pipes, SysV IPC, POSIX Message Queues and other IPC (mq_overview7, svipc7) @keyring diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 70723e9e4e..e0a61aa358 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -290,9 +290,10 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "select\0" }, [SYSCALL_FILTER_SET_IPC] = { - /* Message queues, SYSV IPC or other IPC: unusual */ + /* Message queues, SYSV IPC or other IPC */ .name = "@ipc", .value = "ipc\0" + "memfd_create\0" "mq_getsetattr\0" "mq_notify\0" "mq_open\0" @@ -303,6 +304,8 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "msgget\0" "msgrcv\0" "msgsnd\0" + "pipe2\0" + "pipe\0" "process_vm_readv\0" "process_vm_writev\0" "semctl\0" -- cgit v1.2.3-54-g00ecf From aa6b9cec8813c2135049cecc2247a202ff6e311d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 15:44:54 +0200 Subject: man: two minor fixes --- man/systemd.exec.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 466511aaf3..3b80bcccd0 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1351,13 +1351,13 @@ @raw-io - Raw I/O port access (ioperm2, iopl2, pciconfig_read(), … + Raw I/O port access (ioperm2, iopl2, pciconfig_read(), …)
- Note, that as new system calls are added to the kernel, additional system calls might be added to the groups + Note that as new system calls are added to the kernel, additional system calls might be added to the groups above, so the contents of the sets may change between systemd versions. It is recommended to combine the file system namespacing related options with -- cgit v1.2.3-54-g00ecf From 133ddbbeae74fc06173633605b3e612e934bc2dd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 2 Nov 2016 08:46:18 -0600 Subject: seccomp: add two new syscall groups @resources contains various syscalls that alter resource limits and memory and scheduling parameters of processes. As such they are good candidates to block for most services. @basic-io contains a number of basic syscalls for I/O, similar to the list seccomp v1 permitted but slightly more complete. It should be useful for building basic whitelisting for minimal sandboxes --- man/systemd.exec.xml | 8 ++++++++ src/shared/seccomp-util.c | 34 ++++++++++++++++++++++++++++++++++ src/shared/seccomp-util.h | 2 ++ 3 files changed, 44 insertions(+) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 3b80bcccd0..7daa3ae78e 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1301,6 +1301,10 @@ + + @basic-io + System calls for basic I/O: reading, writing, seeking, file descriptor duplication and closing (read2, write2, and related calls) + @clock System calls for changing the system clock (adjtimex2, settimeofday2, and related calls) @@ -1353,6 +1357,10 @@ @raw-io Raw I/O port access (ioperm2, iopl2, pciconfig_read(), …) + + @resources + System calls for changing resource limits, memory and scheduling parameters (setrlimit2, setpriority2, …) + diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index e0a61aa358..c9b24f1065 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -217,6 +217,24 @@ bool is_seccomp_available(void) { } const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { + [SYSCALL_FILTER_SET_BASIC_IO] = { + /* Basic IO */ + .name = "@basic-io", + .value = + "close\0" + "dup2\0" + "dup3\0" + "dup\0" + "lseek\0" + "pread64\0" + "preadv\0" + "pwrite64\0" + "pwritev\0" + "read\0" + "readv\0" + "write\0" + "writev\0" + }, [SYSCALL_FILTER_SET_CLOCK] = { /* Clock */ .name = "@clock", @@ -472,6 +490,22 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "s390_pci_mmio_write\0" #endif }, + [SYSCALL_FILTER_SET_RESOURCES] = { + /* Alter resource settings */ + .name = "@resources", + .value = + "sched_setparam\0" + "sched_setscheduler\0" + "sched_setaffinity\0" + "setpriority\0" + "setrlimit\0" + "set_mempolicy\0" + "migrate_pages\0" + "move_pages\0" + "mbind\0" + "sched_setattr\0" + "prlimit64\0" + }, }; const SyscallFilterSet *syscall_filter_set_find(const char *name) { diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h index 8050fc6fbf..8e209efef2 100644 --- a/src/shared/seccomp-util.h +++ b/src/shared/seccomp-util.h @@ -38,6 +38,7 @@ typedef struct SyscallFilterSet { } SyscallFilterSet; enum { + SYSCALL_FILTER_SET_BASIC_IO, SYSCALL_FILTER_SET_CLOCK, SYSCALL_FILTER_SET_CPU_EMULATION, SYSCALL_FILTER_SET_DEBUG, @@ -52,6 +53,7 @@ enum { SYSCALL_FILTER_SET_PRIVILEGED, SYSCALL_FILTER_SET_PROCESS, SYSCALL_FILTER_SET_RAW_IO, + SYSCALL_FILTER_SET_RESOURCES, _SYSCALL_FILTER_SET_MAX }; -- cgit v1.2.3-54-g00ecf From 5cd9cd3537d1afca85877103615e61e6c03e7079 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 15:52:54 +0200 Subject: execute: apply seccomp filters after changing selinux/aa/smack contexts Seccomp is generally an unprivileged operation, changing security contexts is most likely associated with some form of policy. Moreover, while seccomp may influence our own flow of code quite a bit (much more than the security context change) make sure to apply the seccomp filters immediately before executing the binary to invoke. This also moves enforcement of NNP after the security context change, so that NNP cannot affect it anymore. (However, the security policy now has to permit the NNP change). This change has a good chance of breaking current SELinux/AA/SMACK setups, because the policy might not expect this change of behaviour. However, it's technically the better choice I think and should hence be applied. Fixes: #3993 --- src/core/execute.c | 70 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index ae9df41b99..c73e2e7220 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -2538,12 +2538,6 @@ static int exec_child( (void) umask(context->umask); if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { - r = setup_smack(context, command); - if (r < 0) { - *exit_status = EXIT_SMACK_PROCESS_LABEL; - return r; - } - if (context->pam_name && username) { r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds); if (r < 0) { @@ -2693,6 +2687,41 @@ static int exec_child( } } + /* Apply the MAC contexts late, but before seccomp syscall filtering, as those should really be last to + * influence our own codepaths as little as possible. Moreover, applying MAC contexts usually requires + * syscalls that are subject to seccomp filtering, hence should probably be applied before the syscalls + * are restricted. */ + +#ifdef HAVE_SELINUX + if (mac_selinux_use()) { + char *exec_context = mac_selinux_context_net ?: context->selinux_context; + + if (exec_context) { + r = setexeccon(exec_context); + if (r < 0) { + *exit_status = EXIT_SELINUX_CONTEXT; + return r; + } + } + } +#endif + + r = setup_smack(context, command); + if (r < 0) { + *exit_status = EXIT_SMACK_PROCESS_LABEL; + return r; + } + +#ifdef HAVE_APPARMOR + if (context->apparmor_profile && mac_apparmor_use()) { + r = aa_change_onexec(context->apparmor_profile); + if (r < 0 && !context->apparmor_profile_ignore) { + *exit_status = EXIT_APPARMOR_PROFILE; + return -errno; + } + } +#endif + /* PR_GET_SECUREBITS is not privileged, while * PR_SET_SECUREBITS is. So to suppress * potential EPERMs we'll try not to call @@ -2758,6 +2787,8 @@ static int exec_child( } } + /* This really should remain the last step before the execve(), to make sure our own code is unaffected + * by the filter as little as possible. */ if (context_has_syscall_filters(context)) { r = apply_seccomp(unit, context); if (r < 0) { @@ -2766,30 +2797,6 @@ static int exec_child( } } #endif - -#ifdef HAVE_SELINUX - if (mac_selinux_use()) { - char *exec_context = mac_selinux_context_net ?: context->selinux_context; - - if (exec_context) { - r = setexeccon(exec_context); - if (r < 0) { - *exit_status = EXIT_SELINUX_CONTEXT; - return r; - } - } - } -#endif - -#ifdef HAVE_APPARMOR - if (context->apparmor_profile && mac_apparmor_use()) { - r = aa_change_onexec(context->apparmor_profile); - if (r < 0 && !context->apparmor_profile_ignore) { - *exit_status = EXIT_APPARMOR_PROFILE; - return -errno; - } - } -#endif } final_argv = replace_env_argv(argv, accum_env); @@ -3611,7 +3618,8 @@ char *exec_command_line(char **argv) { STRV_FOREACH(a, argv) k += strlen(*a)+3; - if (!(n = new(char, k))) + n = new(char, k); + if (!n) return NULL; p = n; -- cgit v1.2.3-54-g00ecf From 2ca8dc15f9cc050a8845b0a55f8226a7024ca623 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 16:08:38 +0200 Subject: man: document that too strict system call filters may affect the service manager If execve() or socket() is filtered the service manager might get into trouble executing the service binary, or handling any failures when this fails. Mention this in the documentation. The other option would be to implicitly whitelist all system calls that are required for these codepaths. However, that appears less than desirable as this would mean socket() and many related calls have to be whitelisted unconditionally. As writing system call filters requires a certain level of expertise anyway it sounds like the better option to simply document these issues and suggest that the user disables system call filters in the service temporarily in order to debug any such failures. See: #3993. --- man/systemd.exec.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 7daa3ae78e..3c350df11f 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -1270,6 +1270,14 @@ filter is reset, all prior assignments will have no effect. This does not affect commands prefixed with +. + Note that strict system call filters may impact execution and error handling code paths of the service + invocation. Specifically, access to the execve system call is required for the execution + of the service binary — if it is blocked service invocation will necessarily fail. Also, if execution of the + service binary fails for some reason (for example: missing service executable), the error handling logic might + require access to an additional set of system calls in order to process and log this failure correctly. It + might be necessary to temporarily disable system call filters in order to simplify debugging of such + failures. + If you specify both types of this option (i.e. whitelisting and blacklisting), the first encountered will take precedence and will dictate the default action -- cgit v1.2.3-54-g00ecf From 999a6c5d9c8bc9536f98ce26dde1de5adaabe29b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 1 Nov 2016 20:30:11 -0600 Subject: tests: make sure tests pass when invoked in "sudo" This is a follow-up for 6309e51ea32d64524431ee65c49eecd44390da8f and makes sure we compare test results with the right user identifier. --- src/test/test-unit-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index 7ef087a2e3..12f48bf435 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -589,7 +589,7 @@ static void test_install_printf(void) { assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid); assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid); assert_se((host = gethostname_malloc())); - assert_se((user = getusername_malloc())); + assert_se((user = uid_to_name(getuid()))); assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0); #define expect(src, pattern, result) \ -- cgit v1.2.3-54-g00ecf From bbeea271172a4664ce9a4a41a7fa3b1ca18dbedd Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Wed, 2 Nov 2016 17:51:35 +0100 Subject: core: initialize groups list before checking SupplementaryGroups= of a unit (#4533) Always initialize the supplementary groups of caller before checking the unit SupplementaryGroups= option. Fixes https://github.com/systemd/systemd/issues/4531 --- src/core/execute.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index ae9df41b99..a1bd0c1238 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -787,6 +787,20 @@ static int get_fixed_supplementary_groups(const ExecContext *c, assert(c); + /* + * If user is given, then lookup GID and supplementary groups list. + * We avoid NSS lookups for gid=0. Also we have to initialize groups + * as early as possible so we keep the list of supplementary groups + * of the caller. + */ + if (user && gid_is_valid(gid) && gid != 0) { + /* First step, initialize groups from /etc/groups */ + if (initgroups(user, gid) < 0) + return -errno; + + keep_groups = true; + } + if (!c->supplementary_groups) return 0; @@ -803,18 +817,6 @@ static int get_fixed_supplementary_groups(const ExecContext *c, return -EOPNOTSUPP; /* For all other values */ } - /* - * If user is given, then lookup GID and supplementary group list. - * We avoid NSS lookups for gid=0. - */ - if (user && gid_is_valid(gid) && gid != 0) { - /* First step, initialize groups from /etc/groups */ - if (initgroups(user, gid) < 0) - return -errno; - - keep_groups = true; - } - l_gids = new(gid_t, ngroups_max); if (!l_gids) return -ENOMEM; @@ -2577,7 +2579,7 @@ static int exec_child( return r; } - /* Drop group as early as possbile */ + /* Drop groups as early as possbile */ if ((params->flags & EXEC_APPLY_PERMISSIONS) && !command->privileged) { r = enforce_groups(context, gid, supplementary_gids, ngids); if (r < 0) { -- cgit v1.2.3-54-g00ecf From f5869324e303a136d7ca802769e8966e8eb26d56 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Oct 2016 21:41:54 +0200 Subject: core: rework the "no_gc" unit flag to become a more generic "perpetual" flag So far "no_gc" was set on -.slice and init.scope, to units that are always running, cannot be stopped and never exist in an "inactive" state. Since these units are the only users of this flag, let's remodel it and rename it "perpetual" and let's derive more funcitonality off it. Specifically, refuse enqueing stop jobs for these units, and report that they are "unstoppable" in the CanStop bus property. --- src/core/dbus-unit.c | 6 ++---- src/core/scope.c | 6 ++---- src/core/slice.c | 10 ++++------ src/core/unit.c | 27 ++++++++++++++++++++++++--- src/core/unit.h | 6 ++++-- 5 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 8f34fa1a52..69e249c844 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -263,10 +263,7 @@ static int property_get_can_stop( assert(reply); assert(u); - /* On the lower levels we assume that every unit we can start - * we can also stop */ - - return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_stop); + return sd_bus_message_append(reply, "b", unit_can_stop(u) && !u->refuse_manual_stop); } static int property_get_can_reload( @@ -760,6 +757,7 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0), SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/core/scope.c b/src/core/scope.c index af0c43c7da..77f3fdc2aa 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -154,15 +154,13 @@ static int scope_load_init_scope(Unit *u) { return 0; u->transient = true; - u->no_gc = true; + u->perpetual = true; /* init.scope is a bit special, as it has to stick around forever. Because of its special semantics we * synthesize it here, instead of relying on the unit file on disk. */ u->default_dependencies = false; u->ignore_on_isolate = true; - u->refuse_manual_start = true; - u->refuse_manual_stop = true; SCOPE(u)->kill_context.kill_signal = SIGRTMIN+14; @@ -580,7 +578,7 @@ static void scope_enumerate(Manager *m) { } u->transient = true; - u->no_gc = true; + u->perpetual = true; SCOPE(u)->deserialized_state = SCOPE_RUNNING; unit_add_to_load_queue(u); diff --git a/src/core/slice.c b/src/core/slice.c index 0fef29661f..c505fa1916 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -136,15 +136,13 @@ static int slice_load_root_slice(Unit *u) { if (!unit_has_name(u, SPECIAL_ROOT_SLICE)) return 0; - u->no_gc = true; + u->perpetual = true; /* The root slice is a bit special. For example it is always running and cannot be terminated. Because of its * special semantics we synthesize it here, instead of relying on the unit file on disk. */ u->default_dependencies = false; u->ignore_on_isolate = true; - u->refuse_manual_start = true; - u->refuse_manual_stop = true; if (!u->description) u->description = strdup("Root Slice"); @@ -302,7 +300,7 @@ static void slice_enumerate(Manager *m) { u = manager_get_unit(m, SPECIAL_ROOT_SLICE); if (!u) { u = unit_new(m, sizeof(Slice)); - if (!u) { + if (!u) { log_oom(); return; } @@ -310,12 +308,12 @@ static void slice_enumerate(Manager *m) { r = unit_add_name(u, SPECIAL_ROOT_SLICE); if (r < 0) { unit_free(u); - log_error_errno(r, "Failed to add the "SPECIAL_ROOT_SLICE " name: %m"); + log_error_errno(r, "Failed to add the " SPECIAL_ROOT_SLICE " name: %m"); return; } } - u->no_gc = true; + u->perpetual = true; SLICE(u)->deserialized_state = SLICE_ACTIVE; unit_add_to_load_queue(u); diff --git a/src/core/unit.c b/src/core/unit.c index cabb1050a8..8d74b44f73 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -323,7 +323,7 @@ bool unit_check_gc(Unit *u) { if (state != UNIT_INACTIVE) return true; - if (u->no_gc) + if (u->perpetual) return true; if (u->refs) @@ -924,6 +924,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { "%s\tGC Check Good: %s\n" "%s\tNeed Daemon Reload: %s\n" "%s\tTransient: %s\n" + "%s\tPerpetual: %s\n" "%s\tSlice: %s\n" "%s\tCGroup: %s\n" "%s\tCGroup realized: %s\n" @@ -942,6 +943,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { prefix, yes_no(unit_check_gc(u)), prefix, yes_no(unit_need_daemon_reload(u)), prefix, yes_no(u->transient), + prefix, yes_no(u->perpetual), prefix, strna(unit_slice_name(u)), prefix, strna(u->cgroup_path), prefix, yes_no(u->cgroup_realized), @@ -1616,6 +1618,18 @@ int unit_stop(Unit *u) { return UNIT_VTABLE(u)->stop(u); } +bool unit_can_stop(Unit *u) { + assert(u); + + if (!unit_supported(u)) + return false; + + if (u->perpetual) + return false; + + return !!UNIT_VTABLE(u)->stop; +} + /* Errors: * -EBADR: This unit type does not support reloading. * -ENOEXEC: Unit is not started. @@ -2150,13 +2164,20 @@ bool unit_job_is_applicable(Unit *u, JobType j) { case JOB_VERIFY_ACTIVE: case JOB_START: - case JOB_STOP: case JOB_NOP: + /* Note that we don't check unit_can_start() here. That's because .device units and suchlike are not + * startable by us but may appear due to external events, and it thus makes sense to permit enqueing + * jobs for it. */ return true; + case JOB_STOP: + /* Similar as above. However, perpetual units can never be stopped (neither explicitly nor due to + * external events), hence it makes no sense to permit enqueing such a request either. */ + return !u->perpetual; + case JOB_RESTART: case JOB_TRY_RESTART: - return unit_can_start(u); + return unit_can_stop(u) && unit_can_start(u); case JOB_RELOAD: case JOB_TRY_RELOAD: diff --git a/src/core/unit.h b/src/core/unit.h index adcdee6db6..e524553ed3 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -236,6 +236,9 @@ struct Unit { /* Is this a transient unit? */ bool transient; + /* Is this a unit that is always running and cannot be stopped? */ + bool perpetual; + bool in_load_queue:1; bool in_dbus_queue:1; bool in_cleanup_queue:1; @@ -244,8 +247,6 @@ struct Unit { bool sent_dbus_new_signal:1; - bool no_gc:1; - bool in_audit:1; bool cgroup_realized:1; @@ -524,6 +525,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix); bool unit_can_reload(Unit *u) _pure_; bool unit_can_start(Unit *u) _pure_; +bool unit_can_stop(Unit *u) _pure_; bool unit_can_isolate(Unit *u) _pure_; int unit_start(Unit *u); -- cgit v1.2.3-54-g00ecf From 11222d0fe0b5abb0cef65359b979e0c7f50129f3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 00:04:55 +0200 Subject: core: make the root mount perpetual too Now that have a proper concept of "perpetual" units, let's make the root mount one too, since it also cannot go away. --- src/basic/special.h | 3 ++ src/core/mount.c | 81 +++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/basic/special.h b/src/basic/special.h index 084d3dfa23..5276bcf598 100644 --- a/src/basic/special.h +++ b/src/basic/special.h @@ -117,3 +117,6 @@ /* The scope unit systemd itself lives in. */ #define SPECIAL_INIT_SCOPE "init.scope" + +/* The root directory. */ +#define SPECIAL_ROOT_MOUNT "-.mount" diff --git a/src/core/mount.c b/src/core/mount.c index da480001e1..03e5ea1376 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -159,17 +159,6 @@ static void mount_init(Unit *u) { m->timeout_usec = u->manager->default_timeout_start_usec; m->directory_mode = 0755; - if (unit_has_name(u, "-.mount")) { - /* Don't allow start/stop for root directory */ - u->refuse_manual_start = true; - u->refuse_manual_stop = true; - } else { - /* The stdio/kmsg bridge socket is on /, in order to avoid a - * dep loop, don't use kmsg logging for -.mount */ - m->exec_context.std_output = u->manager->default_std_output; - m->exec_context.std_error = u->manager->default_std_error; - } - /* We need to make sure that /usr/bin/mount is always called * in the same process group as us, so that the autofs kernel * side doesn't send us another mount request while we are @@ -577,6 +566,25 @@ static int mount_add_extras(Mount *m) { return 0; } +static int mount_load_root_mount(Unit *u) { + assert(u); + + if (!unit_has_name(u, SPECIAL_ROOT_MOUNT)) + return 0; + + u->perpetual = true; + u->default_dependencies = false; + + /* The stdio/kmsg bridge socket is on /, in order to avoid a dep loop, don't use kmsg logging for -.mount */ + MOUNT(u)->exec_context.std_output = EXEC_OUTPUT_NULL; + MOUNT(u)->exec_context.std_input = EXEC_INPUT_NULL; + + if (!u->description) + u->description = strdup("Root Mount"); + + return 1; +} + static int mount_load(Unit *u) { Mount *m = MOUNT(u); int r; @@ -584,11 +592,14 @@ static int mount_load(Unit *u) { assert(u); assert(u->load_state == UNIT_STUB); - if (m->from_proc_self_mountinfo) + r = mount_load_root_mount(u); + if (r < 0) + return r; + + if (m->from_proc_self_mountinfo || u->perpetual) r = unit_load_fragment_and_dropin_optional(u); else r = unit_load_fragment_and_dropin(u); - if (r < 0) return r; @@ -1592,11 +1603,51 @@ static int mount_get_timeout(Unit *u, usec_t *timeout) { return 1; } +static void synthesize_root_mount(Manager *m) { + Unit *u; + int r; + + assert(m); + + /* Whatever happens, we know for sure that the root directory is around, and cannot go away. Let's + * unconditionally synthesize it here and mark it as perpetual. */ + + u = manager_get_unit(m, SPECIAL_ROOT_MOUNT); + if (!u) { + u = unit_new(m, sizeof(Mount)); + if (!u) { + log_oom(); + return; + } + + r = unit_add_name(u, SPECIAL_ROOT_MOUNT); + if (r < 0) { + unit_free(u); + log_error_errno(r, "Failed to add the " SPECIAL_ROOT_MOUNT " name: %m"); + return; + } + } + + u->perpetual = true; + MOUNT(u)->deserialized_state = MOUNT_MOUNTED; + + unit_add_to_load_queue(u); + unit_add_to_dbus_queue(u); +} + +static bool mount_is_mounted(Mount *m) { + assert(m); + + return UNIT(m)->perpetual || m->is_mounted; +} + static void mount_enumerate(Manager *m) { int r; assert(m); + synthesize_root_mount(m); + mnt_init_debug(0); if (!m->mount_monitor) { @@ -1703,7 +1754,7 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) { Mount *mount = MOUNT(u); - if (!mount->is_mounted) { + if (!mount_is_mounted(mount)) { /* A mount point is not around right now. It * might be gone, or might never have @@ -1764,7 +1815,7 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, } } - if (mount->is_mounted && + if (mount_is_mounted(mount) && mount->from_proc_self_mountinfo && mount->parameters_proc_self_mountinfo.what) { -- cgit v1.2.3-54-g00ecf From a581e45ae8f9bb5c6693c23c78bc070aa15d0c8a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 00:29:05 +0200 Subject: unit: unify some code with new unit_new_for_name() call --- src/core/device.c | 6 +----- src/core/mount.c | 17 +++-------------- src/core/scope.c | 11 ++--------- src/core/slice.c | 11 ++--------- src/core/swap.c | 6 +----- src/core/unit.c | 18 ++++++++++++++++++ src/core/unit.h | 1 + 7 files changed, 28 insertions(+), 42 deletions(-) diff --git a/src/core/device.c b/src/core/device.c index 8a3e888e5e..bd87a447cd 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -331,11 +331,7 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa if (!u) { delete = true; - u = unit_new(m, sizeof(Device)); - if (!u) - return log_oom(); - - r = unit_add_name(u, e); + r = unit_new_for_name(m, sizeof(Device), e, &u); if (r < 0) goto fail; diff --git a/src/core/mount.c b/src/core/mount.c index 03e5ea1376..0641621d8f 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1404,11 +1404,7 @@ static int mount_setup_unit( if (!u) { delete = true; - u = unit_new(m, sizeof(Mount)); - if (!u) - return log_oom(); - - r = unit_add_name(u, e); + r = unit_new_for_name(m, sizeof(Mount), e, &u); if (r < 0) goto fail; @@ -1614,16 +1610,9 @@ static void synthesize_root_mount(Manager *m) { u = manager_get_unit(m, SPECIAL_ROOT_MOUNT); if (!u) { - u = unit_new(m, sizeof(Mount)); - if (!u) { - log_oom(); - return; - } - - r = unit_add_name(u, SPECIAL_ROOT_MOUNT); + r = unit_new_for_name(m, sizeof(Mount), SPECIAL_ROOT_MOUNT, &u); if (r < 0) { - unit_free(u); - log_error_errno(r, "Failed to add the " SPECIAL_ROOT_MOUNT " name: %m"); + log_error_errno(r, "Failed to allocate the special " SPECIAL_ROOT_MOUNT " unit: %m"); return; } } diff --git a/src/core/scope.c b/src/core/scope.c index 77f3fdc2aa..d6e1f8e392 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -563,16 +563,9 @@ static void scope_enumerate(Manager *m) { u = manager_get_unit(m, SPECIAL_INIT_SCOPE); if (!u) { - u = unit_new(m, sizeof(Scope)); - if (!u) { - log_oom(); - return; - } - - r = unit_add_name(u, SPECIAL_INIT_SCOPE); + r = unit_new_for_name(m, sizeof(Scope), SPECIAL_INIT_SCOPE, &u); if (r < 0) { - unit_free(u); - log_error_errno(r, "Failed to add the " SPECIAL_INIT_SCOPE " name: %m"); + log_error_errno(r, "Failed to allocate the special " SPECIAL_INIT_SCOPE " unit: %m"); return; } } diff --git a/src/core/slice.c b/src/core/slice.c index c505fa1916..ed5d3fd701 100644 --- a/src/core/slice.c +++ b/src/core/slice.c @@ -299,16 +299,9 @@ static void slice_enumerate(Manager *m) { u = manager_get_unit(m, SPECIAL_ROOT_SLICE); if (!u) { - u = unit_new(m, sizeof(Slice)); - if (!u) { - log_oom(); - return; - } - - r = unit_add_name(u, SPECIAL_ROOT_SLICE); + r = unit_new_for_name(m, sizeof(Slice), SPECIAL_ROOT_SLICE, &u); if (r < 0) { - unit_free(u); - log_error_errno(r, "Failed to add the " SPECIAL_ROOT_SLICE " name: %m"); + log_error_errno(r, "Failed to allocate the special " SPECIAL_ROOT_SLICE " unit: %m"); return; } } diff --git a/src/core/swap.c b/src/core/swap.c index b592abb9fb..2228a254bb 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -381,11 +381,7 @@ static int swap_setup_unit( if (!u) { delete = true; - u = unit_new(m, sizeof(Swap)); - if (!u) - return log_oom(); - - r = unit_add_name(u, e); + r = unit_new_for_name(m, sizeof(Swap), e, &u); if (r < 0) goto fail; diff --git a/src/core/unit.c b/src/core/unit.c index 8d74b44f73..068d319206 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -109,6 +109,24 @@ Unit *unit_new(Manager *m, size_t size) { return u; } +int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret) { + Unit *u; + int r; + + u = unit_new(m, size); + if (!u) + return -ENOMEM; + + r = unit_add_name(u, name); + if (r < 0) { + unit_free(u); + return r; + } + + *ret = u; + return r; +} + bool unit_has_name(Unit *u, const char *name) { assert(u); assert(name); diff --git a/src/core/unit.h b/src/core/unit.h index e524553ed3..899cd62c92 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -481,6 +481,7 @@ DEFINE_CAST(SCOPE, Scope); Unit *unit_new(Manager *m, size_t size); void unit_free(Unit *u); +int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret); int unit_add_name(Unit *u, const char *name); int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_reference); -- cgit v1.2.3-54-g00ecf From 39540de8abe24886693ca29a9caeea85c88089aa Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 09:22:22 +0200 Subject: sysctl: do not fail systemd-sysctl.service if /proc/sys is mounted read-only Let's make missing write access to /proc/sys non-fatal to the sysctl service. This is a follow-up to 411e869f497c7c7bd0688f1e3500f9043bc56e48 which altered the condition for running the sysctl service to check for /proc/sys/net being writable, accepting that /proc/sys might be read-only. In order to ensure the boot-up stays clean in containers lower the log level for the EROFS errors generated due to this. --- src/sysctl/sysctl.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index fbc1e0eb1a..1363a93830 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -51,11 +51,18 @@ static int apply_all(OrderedHashmap *sysctl_options) { k = sysctl_write(property, value); if (k < 0) { - log_full_errno(k == -ENOENT ? LOG_INFO : LOG_WARNING, k, - "Couldn't write '%s' to '%s', ignoring: %m", value, property); - - if (r == 0 && k != -ENOENT) - r = k; + /* If the sysctl is not available in the kernel or we are running with reduced privileges and + * cannot write it, then log about the issue at LOG_NOTICE level, and proceed without + * failing. (EROFS is treated as a permission problem here, since that's how container managers + * usually protected their sysctls.) In all other cases log an error and make the tool fail. */ + + if (IN_SET(k, -EPERM, -EACCES, -EROFS, -ENOENT)) + log_notice_errno(k, "Couldn't write '%s' to '%s', ignoring: %m", value, property); + else { + log_error_errno(k, "Couldn't write '%s' to '%s': %m", value, property); + if (r == 0) + r = k; + } } } -- cgit v1.2.3-54-g00ecf From 9c37b41c6166ca511b317255cfad271c906e597a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 09:25:21 +0200 Subject: sysctl: split out condition check into its own function This way, we can get rid of a label/goto. --- src/sysctl/sysctl.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index 1363a93830..a2a7a10f69 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -69,6 +69,25 @@ static int apply_all(OrderedHashmap *sysctl_options) { return r; } +static bool test_prefix(const char *p) { + char **i; + + if (strv_isempty(arg_prefixes)) + return true; + + STRV_FOREACH(i, arg_prefixes) { + const char *t; + + t = path_startswith(*i, "/proc/sys/"); + if (!t) + t = *i; + if (path_startswith(p, t)) + return true; + } + + return false; +} + static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ignore_enoent) { _cleanup_fclose_ FILE *f = NULL; int r; @@ -118,20 +137,9 @@ static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ign p = sysctl_normalize(strstrip(p)); value = strstrip(value); - if (!strv_isempty(arg_prefixes)) { - char **i, *t; - STRV_FOREACH(i, arg_prefixes) { - t = path_startswith(*i, "/proc/sys/"); - if (t == NULL) - t = *i; - if (path_startswith(p, t)) - goto found; - } - /* not found */ + if (!test_prefix(p)) continue; - } -found: existing = ordered_hashmap_get2(sysctl_options, p, &v); if (existing) { if (streq(value, existing)) -- cgit v1.2.3-54-g00ecf From 98bf5011fe670ea18b7b35d6c8ca3e84d4efbccf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 09:26:10 +0200 Subject: sysctl: when failing to process a config line, show line nr --- src/sysctl/sysctl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index a2a7a10f69..7117955568 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -90,6 +90,7 @@ static bool test_prefix(const char *p) { static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ignore_enoent) { _cleanup_fclose_ FILE *f = NULL; + unsigned c = 0; int r; assert(path); @@ -115,6 +116,8 @@ static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ign return log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path); } + c++; + p = strstrip(l); if (!*p) continue; @@ -124,7 +127,7 @@ static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ign value = strchr(p, '='); if (!value) { - log_error("Line is not an assignment in file '%s': %s", path, value); + log_error("Line is not an assignment at '%s:%u': %s", path, c, value); if (r == 0) r = -EINVAL; @@ -145,7 +148,7 @@ static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ign if (streq(value, existing)) continue; - log_debug("Overwriting earlier assignment of %s in file '%s'.", p, path); + log_debug("Overwriting earlier assignment of %s at '%s:%u'.", p, path, c); free(ordered_hashmap_remove(sysctl_options, p)); free(v); } -- cgit v1.2.3-54-g00ecf From 4f14f2bb6f7402302fd4fcad6754e5ee218f4487 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 09:26:31 +0200 Subject: sysctl: no need to check for eof twice Let's only check for eof once after the fgets(). There's no point in checking EOF before the first read, and twice in each loop. --- src/sysctl/sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index 7117955568..cce91b3d67 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -104,7 +104,7 @@ static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ign } log_debug("Parsing %s", path); - while (!feof(f)) { + for (;;) { char l[LINE_MAX], *p, *value, *new_value, *property, *existing; void *v; int k; -- cgit v1.2.3-54-g00ecf From e5105081152c3eb4558d9e5d9c8aaa33f9d802ff Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 09:27:39 +0200 Subject: sysctl: minor simplification Let's place only one ternary operator. --- src/sysctl/sysctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index cce91b3d67..b3587e249d 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -247,12 +247,12 @@ static int parse_argv(int argc, char *argv[]) { } int main(int argc, char *argv[]) { + OrderedHashmap *sysctl_options = NULL; int r = 0, k; - OrderedHashmap *sysctl_options; r = parse_argv(argc, argv); if (r <= 0) - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + goto finish; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); -- cgit v1.2.3-54-g00ecf From 835a19e02fa96a5f13700d0ce9f4b1813d0c1ad6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 10:00:06 +0200 Subject: systemctl: properly turn off color after active column If we turn on red color for the active column and it is not combined with underlining, then we need to turn it off explicitly afterwards. Do that. --- src/systemctl/systemctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index d311bbec1a..558186bd8a 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -513,13 +513,13 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { off_circle = ansi_normal(); circle = true; on_loaded = underline ? ansi_highlight_red_underline() : ansi_highlight_red(); - off_loaded = on_underline; + off_loaded = underline ? on_underline : ansi_normal(); } else if (streq(u->active_state, "failed") && !arg_plain) { on_circle = ansi_highlight_red(); off_circle = ansi_normal(); circle = true; on_active = underline ? ansi_highlight_red_underline() : ansi_highlight_red(); - off_active = on_underline; + off_active = underline ? on_underline : ansi_normal(); } if (u->machine) { -- cgit v1.2.3-54-g00ecf From b5d7f1bbfa09f2713d72f76f89d2f830e382382b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 11:06:47 +0200 Subject: systemctl: tweak the "systemctl list-units" output a bit Make the underlining between the header and the body and between the units of different types span the whole width of the table. Let's never make the table wider than necessary (which is relevant due the above). When space is limited and we can't show the full ID or description string prefer showing the full ID over the full description. The ID is after all something people might want to copy/paste, while the description is mostly just helpful decoration. --- src/systemctl/systemctl.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 558186bd8a..fb5a539bc6 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -410,23 +410,24 @@ static bool output_show_unit(const UnitInfo *u, char **patterns) { } static int output_units_list(const UnitInfo *unit_infos, unsigned c) { - unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len; + unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len, max_desc_len; const UnitInfo *u; unsigned n_shown = 0; - int job_count = 0, desc_len; + int job_count = 0; max_id_len = strlen("UNIT"); load_len = strlen("LOAD"); active_len = strlen("ACTIVE"); sub_len = strlen("SUB"); job_len = strlen("JOB"); - desc_len = 0; + max_desc_len = strlen("DESCRIPTION"); for (u = unit_infos; u < unit_infos + c; u++) { max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0)); load_len = MAX(load_len, strlen(u->load_state)); active_len = MAX(active_len, strlen(u->active_state)); sub_len = MAX(sub_len, strlen(u->sub_state)); + max_desc_len = MAX(max_desc_len, strlen(u->description)); if (u->job_id != 0) { job_len = MAX(job_len, strlen(u->job_type)); @@ -442,7 +443,7 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { if (!arg_full && original_stdout_is_tty) { unsigned basic_len; - id_len = MIN(max_id_len, 25u); + id_len = MIN(max_id_len, 25u); /* as much as it needs, but at most 25 for now */ basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len; if (job_count) @@ -455,19 +456,21 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { /* Either UNIT already got 25, or is fully satisfied. * Grant up to 25 to DESC now. */ incr = MIN(extra_len, 25u); - desc_len += incr; + desc_len = incr; extra_len -= incr; - /* split the remaining space between UNIT and DESC, - * but do not give UNIT more than it needs. */ + /* Of the remainder give as much as the ID needs to the ID, and give the rest to the + * description but not more than it needs. */ if (extra_len > 0) { - incr = MIN(extra_len / 2, max_id_len - id_len); + incr = MIN(max_id_len - id_len, extra_len); id_len += incr; - desc_len += extra_len - incr; + desc_len += MIN(extra_len - incr, max_desc_len - desc_len); } } - } else + } else { id_len = max_id_len; + desc_len = max_desc_len; + } for (u = unit_infos; u < unit_infos + c; u++) { _cleanup_free_ char *e = NULL, *j = NULL; @@ -493,8 +496,9 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { if (job_count) printf("%-*s ", job_len, "JOB"); - printf("%.*s%s\n", - !arg_full && arg_no_pager ? desc_len : -1, + printf("%-*.*s%s\n", + desc_len, + !arg_full && arg_no_pager ? (int) desc_len : -1, "DESCRIPTION", ansi_normal()); } @@ -550,8 +554,9 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { sub_len, u->sub_state, off_active, job_count ? job_len + 1 : 0, u->job_id ? u->job_type : ""); - printf("%.*s%s\n", - desc_len > 0 ? desc_len : -1, + printf("%-*.*s%s\n", + desc_len, + !arg_full && arg_no_pager ? (int) desc_len : -1, u->description, off_underline); } -- cgit v1.2.3-54-g00ecf From 2bce2acce869686d4417fa679eb794b5dc873110 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 11:39:09 +0200 Subject: nspawn: if we set up a loopback device, try to mount it with "discard" Let's make sure that our loopback files remain sparse, hence let's set "discard" as mount option on file systems that support it if the backing device is a loopback. --- src/nspawn/nspawn.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 295293858e..c56af6e6f4 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2260,7 +2260,7 @@ static int dissect_image( static int mount_device(const char *what, const char *where, const char *directory, bool rw) { #ifdef HAVE_BLKID _cleanup_blkid_free_probe_ blkid_probe b = NULL; - const char *fstype, *p; + const char *fstype, *p, *options; int r; assert(what); @@ -2309,7 +2309,17 @@ static int mount_device(const char *what, const char *where, const char *directo return -EOPNOTSUPP; } - return mount_verbose(LOG_ERR, what, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), NULL); + /* If this is a loopback device then let's mount the image with discard, so that the underlying file remains + * sparse when possible. */ + if (STR_IN_SET(fstype, "btrfs", "ext4", "vfat", "xfs")) { + const char *l; + + l = path_startswith(what, "/dev"); + if (l && startswith(l, "loop")) + options = "discard"; + } + + return mount_verbose(LOG_ERR, what, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options); #else log_error("--image= is not supported, compiled without blkid support."); return -EOPNOTSUPP; -- cgit v1.2.3-54-g00ecf From 02affb4e6a16fbec9d6d28265c220ca95479bbd0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 12:08:24 +0200 Subject: netword: minor memory leak fix --- src/network/networkd-ndisc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index b282634e4b..6ce6bfa787 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -680,13 +680,13 @@ void ndisc_vacuum(Link *link) { SET_FOREACH(r, link->ndisc_rdnss, i) if (r->valid_until < time_now) { - (void) set_remove(link->ndisc_rdnss, r); + free(set_remove(link->ndisc_rdnss, r)); link_dirty(link); } SET_FOREACH(d, link->ndisc_dnssl, i) if (d->valid_until < time_now) { - (void) set_remove(link->ndisc_dnssl, d); + free(set_remove(link->ndisc_dnssl, d)); link_dirty(link); } } -- cgit v1.2.3-54-g00ecf From c69305ff4fe5a182cd58b66077f3db7bc7c222e1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 25 Oct 2016 12:08:43 +0200 Subject: networkd: flush DNSSL/RDNSS lists when we lose carrier Fixes: #3870 --- src/network/networkd-link.c | 7 ++++--- src/network/networkd-ndisc.c | 9 +++++++++ src/network/networkd-ndisc.h | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index d9e060b6cf..aefe7335b9 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -514,13 +514,12 @@ static void link_free(Link *link) { sd_lldp_unref(link->lldp); free(link->lldp_file); + ndisc_flush(link); + sd_ipv4ll_unref(link->ipv4ll); sd_dhcp6_client_unref(link->dhcp6_client); sd_ndisc_unref(link->ndisc); - set_free_free(link->ndisc_rdnss); - set_free_free(link->ndisc_dnssl); - if (link->manager) hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)); @@ -2427,6 +2426,8 @@ static int link_drop_config(Link *link) { return r; } + ndisc_flush(link); + return 0; } diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 6ce6bfa787..4853791aa5 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -690,3 +690,12 @@ void ndisc_vacuum(Link *link) { link_dirty(link); } } + +void ndisc_flush(Link *link) { + assert(link); + + /* Removes all RDNSS and DNSSL entries, without exception */ + + link->ndisc_rdnss = set_free_free(link->ndisc_rdnss); + link->ndisc_dnssl = set_free_free(link->ndisc_dnssl); +} diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h index 2002f55107..127126190e 100644 --- a/src/network/networkd-ndisc.h +++ b/src/network/networkd-ndisc.h @@ -37,3 +37,4 @@ static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) { int ndisc_configure(Link *link); void ndisc_vacuum(Link *link); +void ndisc_flush(Link *link); -- cgit v1.2.3-54-g00ecf From 1201cae704c6674fde2c23fdd7feab8493a20159 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 2 Nov 2016 11:38:12 -0600 Subject: core: change mount_synthesize_root() return to int Let's propagate the error here, instead of eating it up early. In a later change we should probably also change mount_enumerate() to propagate errors up, but that would mean we'd have to change the unit vtable, and thus change all unit types, hence is quite an invasive change. --- src/core/mount.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/core/mount.c b/src/core/mount.c index 0641621d8f..d749e49df5 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1599,7 +1599,7 @@ static int mount_get_timeout(Unit *u, usec_t *timeout) { return 1; } -static void synthesize_root_mount(Manager *m) { +static int synthesize_root_mount(Manager *m) { Unit *u; int r; @@ -1611,10 +1611,8 @@ static void synthesize_root_mount(Manager *m) { u = manager_get_unit(m, SPECIAL_ROOT_MOUNT); if (!u) { r = unit_new_for_name(m, sizeof(Mount), SPECIAL_ROOT_MOUNT, &u); - if (r < 0) { - log_error_errno(r, "Failed to allocate the special " SPECIAL_ROOT_MOUNT " unit: %m"); - return; - } + if (r < 0) + return log_error_errno(r, "Failed to allocate the special " SPECIAL_ROOT_MOUNT " unit: %m"); } u->perpetual = true; @@ -1622,6 +1620,8 @@ static void synthesize_root_mount(Manager *m) { unit_add_to_load_queue(u); unit_add_to_dbus_queue(u); + + return 0; } static bool mount_is_mounted(Mount *m) { @@ -1635,7 +1635,9 @@ static void mount_enumerate(Manager *m) { assert(m); - synthesize_root_mount(m); + r = synthesize_root_mount(m); + if (r < 0) + goto fail; mnt_init_debug(0); -- cgit v1.2.3-54-g00ecf From b09246352f751c95ab06f598b639f6f6ca0e67b1 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 2 Nov 2016 15:00:54 -0400 Subject: pid1: fix fd memleak when we hit FileDescriptorStoreMax limit Since service_add_fd_store() already does the check, remove the redundant check from service_add_fd_store_set(). Also, print a warning when repopulating FDStore after daemon-reexec and we hit the limit. This is a user visible issue, so we should not discard fds silently. (Note that service_deserialize_item is impacted by the return value from service_add_fd_store(), but we rely on the general error message, so the caller does not need to be modified, and does not show up in the diff.) --- src/core/service.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/core/service.c b/src/core/service.c index 00ce500fd3..a7274a758f 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -386,7 +386,9 @@ static int service_add_fd_store(Service *s, int fd, const char *name) { assert(fd >= 0); if (s->n_fd_store >= s->n_fd_store_max) - return 0; + return -EXFULL; /* Our store is full. + * Use this errno rather than E[NM]FILE to distinguish from + * the case where systemd itself hits the file limit. */ LIST_FOREACH(fd_store, fs, s->fd_store) { r = same_fd(fs->fd, fd); @@ -430,10 +432,7 @@ static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) { assert(s); - if (fdset_size(fds) <= 0) - return 0; - - while (s->n_fd_store < s->n_fd_store_max) { + while (fdset_size(fds) > 0) { _cleanup_close_ int fd = -1; fd = fdset_steal_first(fds); @@ -441,16 +440,17 @@ static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) { break; r = service_add_fd_store(s, fd, name); + if (r == -EXFULL) + return log_unit_warning_errno(UNIT(s), r, + "Cannot store more fds than FileDescriptorStoreMax=%u, closing remaining.", + s->n_fd_store_max); if (r < 0) - return log_unit_error_errno(UNIT(s), r, "Couldn't add fd to fd store: %m"); + return log_unit_error_errno(UNIT(s), r, "Failed to add fd to store: %m"); if (r > 0) log_unit_debug(UNIT(s), "Added fd %u (%s) to fd store.", fd, strna(name)); fd = -1; } - if (fdset_size(fds) > 0) - log_unit_warning(UNIT(s), "Tried to store more fds than FileDescriptorStoreMax=%u allows, closing remaining.", s->n_fd_store_max); - return 0; } -- cgit v1.2.3-54-g00ecf From 07393b6ea9377f01a63e97d5cdd899ae0cc59530 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 2 Nov 2016 15:52:57 -0600 Subject: NEWS: add contributor list to news file Unfortunately, github drops the original commiter when a PR is "squashed" (even if it is only a single commit) and replaces it with some rubbish github-specific user id. Thus, to make the contributors list somewhat useful, update the .mailmap file and undo all the weirdness github applied there. --- .mailmap | 15 +++++++++++++++ NEWS | 29 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/.mailmap b/.mailmap index d56fb67845..d007ba741e 100644 --- a/.mailmap +++ b/.mailmap @@ -74,3 +74,18 @@ Thomas H. P. Andersen Michael Olbrich Douglas Christman Alexander Kuleshov <0xAX@users.noreply.github.com> +Andreas Henriksson +Daniel Rusek +Dennis Wassenberg +Reid Price +Stefan Schweter +Seraphime Kirkovski +Bart Rulon +Richard W.M. Jones +Roman Stingler +Michael Hoy +Tiago Levit +Eric Cook +Lukáš Nykrýn +Heikki Kemppainen +Hendrik Brueckner diff --git a/NEWS b/NEWS index 8d8c1033d3..9f0079d522 100644 --- a/NEWS +++ b/NEWS @@ -311,6 +311,35 @@ CHANGES WITH 232 in spe * "systemctl is-enabled --full" will now show by which symlinks a unit file is enabled in the unit dependency tree. + Contributions from: Alban Crequy, Alexander Kuleshov, Alfie John, + Andreas Henriksson, Andrew Jeddeloh, Balázs Úr, Bart Rulon, Benjamin + Richter, Ben Gamari, Ben Harris, Brian J. Murrell, Christian Brauner, + Christian Rebischke, Clinton Roy, Colin Walters, Cristian Rodríguez, + Daniel Hahler, Daniel Mack, Daniel Maixner, Daniel Rusek, Dan Dedrick, + Davide Cavalca, David Herrmann, David Michael, Dennis Wassenberg, + Djalal Harouni, Dongsu Park, Douglas Christman, Elias Probst, Eric + Cook, Erik Karlsson, Evgeny Vereshchagin, Felipe Sateler, Felix Zhang, + Franck Bui, George Hilliard, Giuseppe Scrivano, HATAYAMA Daisuke, + Heikki Kemppainen, Hendrik Brueckner, hi117, Ismo Puustinen, Ivan + Shapovalov, Jakub Filak, Jakub Wilk, Jan Synacek, Jason Kölker, + Jean-Sébastien Bour, Jiří Pírko, Jonathan Boulle, Jorge Niedbalski, + Keith Busch, kristbaum, Kyle Russell, Lans Zhang, Lennart Poettering, + Leonardo Brondani Schenkel, Lucas Werkmeister, Luca Bruno, Lukáš + Nykrýn, Maciek Borzecki, Mantas Mikulėnas, Marc-Antoine Perennou, + Marcel Holtmann, Marcos Mello, Martin Ejdestig, Martin Pitt, Matej + Habrnal, Maxime de Roucy, Michael Biebl, Michael Chapman, Michael Hoy, + Michael Olbrich, Michael Pope, Michal Sekletar, Michal Soltys, Mike + Gilbert, Nick Owens, Patrik Flykt, Paweł Szewczyk, Peter Hutterer, + Piotr Drąg, Reid Price, Richard W.M. Jones, Roman Stingler, Ronny + Chevalier, Seraphime Kirkovski, Stefan Schweter, Steve Muir, Susant + Sahani, Tejun Heo, Thomas Blume, Thomas H. P. Andersen, Tiago Levit, + Tobias Jungel, Tomáš Janoušek, Topi Miettinen, Torstein Husebø, Umut + Tezduyar Lindskog, Vito Caputo, WaLyong Cho, Wilhelm Schuster, Yann + E. MORIN, Yi EungJun, Yuki Inoguchi, Yu Watanabe, Zbigniew + Jędrzejewski-Szmek, Zeal Jagannatha + + — Santa Fe, 2016-11-XX + CHANGES WITH 231: * In service units the various ExecXYZ= settings have been extended -- cgit v1.2.3-54-g00ecf From b4eed568b913079f5a97c744ecc2c4f9c3d0403a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 2 Nov 2016 16:02:12 -0600 Subject: add two additional entries to NEWS --- NEWS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/NEWS b/NEWS index 9f0079d522..f0ad917464 100644 --- a/NEWS +++ b/NEWS @@ -311,6 +311,15 @@ CHANGES WITH 232 in spe * "systemctl is-enabled --full" will now show by which symlinks a unit file is enabled in the unit dependency tree. + * Support for VeraCrypt encrypted partitions has been added to the + "cryptsetup" logic and /etc/crypttab. + + * systemd-detect-virt gained support for a new --private-users switch + that checks whether the invoking processes are running inside a user + namespace. Similar, a new special value "private-users" for the + existing ConditionVirtualization= setting has been added, permitting + skipping of specific units in user namespace environments. + Contributions from: Alban Crequy, Alexander Kuleshov, Alfie John, Andreas Henriksson, Andrew Jeddeloh, Balázs Úr, Bart Rulon, Benjamin Richter, Ben Gamari, Ben Harris, Brian J. Murrell, Christian Brauner, -- cgit v1.2.3-54-g00ecf From 515958c9eb538607a260aac4a4d0145583e1a2e5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 2 Nov 2016 16:04:40 -0600 Subject: build-sys: bump package and library version in preparation for v232 --- Makefile.am | 4 ++-- configure.ac | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index a707d4a899..34c2f60330 100644 --- a/Makefile.am +++ b/Makefile.am @@ -42,9 +42,9 @@ LIBUDEV_CURRENT=7 LIBUDEV_REVISION=5 LIBUDEV_AGE=6 -LIBSYSTEMD_CURRENT=16 +LIBSYSTEMD_CURRENT=17 LIBSYSTEMD_REVISION=0 -LIBSYSTEMD_AGE=16 +LIBSYSTEMD_AGE=17 # Dirs of external packages dbuspolicydir=@dbuspolicydir@ diff --git a/configure.ac b/configure.ac index 0e87adc38f..0b10fc7de7 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ([2.64]) AC_INIT([systemd], - [231], + [232], [http://github.com/systemd/systemd/issues], [systemd], [http://www.freedesktop.org/wiki/Software/systemd]) -- cgit v1.2.3-54-g00ecf From 5b9635d16656090afa6c3aef52be469ff39fe247 Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Wed, 2 Nov 2016 23:12:03 +0100 Subject: systemctl: fix incorrect "need reload" on cat (#4535) Reported by @evverx in #4493. --- src/systemctl/systemctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index d311bbec1a..b6d66aa363 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -5272,7 +5272,7 @@ static int cat(int argc, char *argv[], void *userdata) { else puts(""); - if (need_daemon_reload(bus, *name)) + if (need_daemon_reload(bus, *name) > 0) /* ignore errors (<0), this is informational output */ fprintf(stderr, "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n" "%s# This output shows the current version of the unit's original fragment and drop-in files.\n" -- cgit v1.2.3-54-g00ecf From 0cc6064c3c2ea8e61298ff3b4a49ad63461db9ea Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Thu, 3 Nov 2016 01:10:29 +0100 Subject: man: fix two typos (is → are) (#4544) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- man/systemctl.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index ae3296d132..dfa00e0c03 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -877,8 +877,8 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service Show properties of one or more units, jobs, or the manager itself. If no argument is specified, properties of the manager will be shown. If a unit name is specified, - properties of the unit is shown, and if a job ID is - specified, properties of the job is shown. By default, empty + properties of the unit are shown, and if a job ID is + specified, properties of the job are shown. By default, empty properties are suppressed. Use to show those too. To select specific properties to show, use . This command is intended to be -- cgit v1.2.3-54-g00ecf From 07ecca0dc9d2d8f3b3abd73ab32f254f339fd903 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 2 Nov 2016 12:02:53 -0600 Subject: core: don't hit an assert when printing status messages about units with overly long description strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This essentially reverts one part of d054f0a4d451120c26494263fc4dc175bfd405b1. (We might also choose to use proper ellipsation here, but I wasn't sure the memory allocation this requires wouöld be a good idea here...) Fixes: #4534 --- src/core/job.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/job.c b/src/core/job.c index 3ecc8a1a73..d8b170b983 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -767,8 +767,9 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { if (!format) return; + /* The description might be longer than the buffer, but that's OK, we'll just truncate it here */ DISABLE_WARNING_FORMAT_NONLITERAL; - xsprintf(buf, format, unit_description(u)); + snprintf(buf, sizeof(buf), format, unit_description(u)); REENABLE_WARNING; switch (t) { -- cgit v1.2.3-54-g00ecf From ac334b2cfbf5e57b5b6510e2f57c5f550bc57cca Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 2 Nov 2016 12:05:22 -0600 Subject: core: make a constant table actually constant --- src/core/job.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/job.c b/src/core/job.c index d8b170b983..ac6910a906 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -690,16 +690,16 @@ _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobR } static void job_print_status_message(Unit *u, JobType t, JobResult result) { - static struct { + static const struct { const char *color, *word; } const statuses[_JOB_RESULT_MAX] = { - [JOB_DONE] = {ANSI_GREEN, " OK "}, - [JOB_TIMEOUT] = {ANSI_HIGHLIGHT_RED, " TIME "}, - [JOB_FAILED] = {ANSI_HIGHLIGHT_RED, "FAILED"}, - [JOB_DEPENDENCY] = {ANSI_HIGHLIGHT_YELLOW, "DEPEND"}, - [JOB_SKIPPED] = {ANSI_HIGHLIGHT, " INFO "}, - [JOB_ASSERT] = {ANSI_HIGHLIGHT_YELLOW, "ASSERT"}, - [JOB_UNSUPPORTED] = {ANSI_HIGHLIGHT_YELLOW, "UNSUPP"}, + [JOB_DONE] = { ANSI_GREEN, " OK " }, + [JOB_TIMEOUT] = { ANSI_HIGHLIGHT_RED, " TIME " }, + [JOB_FAILED] = { ANSI_HIGHLIGHT_RED, "FAILED" }, + [JOB_DEPENDENCY] = { ANSI_HIGHLIGHT_YELLOW, "DEPEND" }, + [JOB_SKIPPED] = { ANSI_HIGHLIGHT, " INFO " }, + [JOB_ASSERT] = { ANSI_HIGHLIGHT_YELLOW, "ASSERT" }, + [JOB_UNSUPPORTED] = { ANSI_HIGHLIGHT_YELLOW, "UNSUPP" }, }; const char *format; -- cgit v1.2.3-54-g00ecf From e68eedbbdc98fa13449756b7fee3bed689d76493 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 2 Nov 2016 22:02:46 -0400 Subject: Revert some uses of xsprintf This reverts some changes introduced in d054f0a4d4. xsprintf should be used in cases where we calculated the right buffer size by hand (using DECIMAL_STRING_MAX and such), and never in cases where we are printing externally specified strings of arbitrary length. Fixes #4534. --- src/basic/log.c | 2 +- src/core/unit.c | 2 +- src/udev/collect/collect.c | 6 +++--- src/udev/udev-builtin-net_id.c | 11 ++++++----- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/basic/log.c b/src/basic/log.c index 2ff70be255..4919d175da 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -782,7 +782,7 @@ static void log_assert( return; DISABLE_WARNING_FORMAT_NONLITERAL; - xsprintf(buffer, format, text, file, line, func); + snprintf(buffer, sizeof buffer, format, text, file, line, func); REENABLE_WARNING; log_abort_msg = buffer; diff --git a/src/core/unit.c b/src/core/unit.c index 463e6d6a62..e664e23892 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1472,7 +1472,7 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { format = unit_get_status_message_format(u, t); DISABLE_WARNING_FORMAT_NONLITERAL; - xsprintf(buf, format, unit_description(u)); + snprintf(buf, sizeof buf, format, unit_description(u)); REENABLE_WARNING; mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING : diff --git a/src/udev/collect/collect.c b/src/udev/collect/collect.c index 349585b634..0e973cd521 100644 --- a/src/udev/collect/collect.c +++ b/src/udev/collect/collect.c @@ -85,16 +85,16 @@ static void usage(void) */ static int prepare(char *dir, char *filename) { - char buf[512]; + char buf[PATH_MAX]; int r, fd; r = mkdir(dir, 0700); if (r < 0 && errno != EEXIST) return -errno; - xsprintf(buf, "%s/%s", dir, filename); + snprintf(buf, sizeof buf, "%s/%s", dir, filename); - fd = open(buf,O_RDWR|O_CREAT|O_CLOEXEC, S_IRUSR|S_IWUSR); + fd = open(buf, O_RDWR|O_CREAT|O_CLOEXEC, S_IRUSR|S_IWUSR); if (fd < 0) fprintf(stderr, "Cannot open %s: %m\n", buf); diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c index 0eb2500dd2..fe9d6f4482 100644 --- a/src/udev/udev-builtin-net_id.c +++ b/src/udev/udev-builtin-net_id.c @@ -211,7 +211,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { char *s; const char *attr, *port_name; struct udev_device *pci = NULL; - char slots[256], str[256]; + char slots[PATH_MAX]; _cleanup_closedir_ DIR *dir = NULL; struct dirent *dent; int hotplug_slot = 0, err = 0; @@ -248,7 +248,8 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { err = -ENOENT; goto out; } - xsprintf(slots, "%s/slots", udev_device_get_syspath(pci)); + + snprintf(slots, sizeof slots, "%s/slots", udev_device_get_syspath(pci)); dir = opendir(slots); if (!dir) { err = -errno; @@ -257,8 +258,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { int i; - char *rest; - char *address; + char *rest, *address, str[PATH_MAX]; if (dent->d_name[0] == '.') continue; @@ -267,7 +267,8 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { continue; if (i < 1) continue; - xsprintf(str, "%s/%s/address", slots, dent->d_name); + + snprintf(str, sizeof str, "%s/%s/address", slots, dent->d_name); if (read_one_line_file(str, &address) >= 0) { /* match slot address with device by stripping the function */ if (strneq(address, udev_device_get_sysname(names->pcidev), strlen(address))) -- cgit v1.2.3-54-g00ecf From 75ead2b753cb9586f3f208326446081baab70da1 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 2 Nov 2016 22:03:27 -0400 Subject: sd-bus: use PRIu64 instead of casting --- src/libsystemd/sd-bus/bus-kernel.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index 59398b841d..ad468572f3 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -848,8 +848,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { if (k->src_id == KDBUS_SRC_ID_KERNEL) bus_message_set_sender_driver(bus, m); else { - xsprintf(m->sender_buffer, ":1.%llu", - (unsigned long long)k->src_id); + xsprintf(m->sender_buffer, ":1.%"PRIu64, k->src_id); m->sender = m->creds.unique_name = m->sender_buffer; } @@ -860,8 +859,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { else if (k->dst_id == KDBUS_DST_ID_NAME) m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */ else { - xsprintf(m->destination_buffer, ":1.%llu", - (unsigned long long)k->dst_id); + xsprintf(m->destination_buffer, ":1.%"PRIu64, k->dst_id); m->destination = m->destination_buffer; } -- cgit v1.2.3-54-g00ecf From a6eccc3647c167ba13ac23885a8ea787f44d97e5 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 2 Nov 2016 22:05:06 -0400 Subject: Do not raise in switch root if paths are too long If we encounter the (unlikely) situation where the combined path to the new root and a path to a mount to be moved together exceed maximum path length, we shouldn't crash, but fail this path instead. --- src/shared/switch-root.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c index 47d3a5a1fa..4eff4f692e 100644 --- a/src/shared/switch-root.c +++ b/src/shared/switch-root.c @@ -75,17 +75,29 @@ int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot, NULSTR_FOREACH(i, move_mounts) { char new_mount[PATH_MAX]; struct stat sb; + size_t n; - xsprintf(new_mount, "%s%s", new_root, i); + n = snprintf(new_mount, sizeof new_mount, "%s%s", new_root, i); + if (n >= sizeof new_mount) { + bool move = mountflags & MS_MOVE; + + log_warning("New path is too long, %s: %s%s", + move ? "forcing unmount instead" : "ignoring", + new_root, i); + + if (move) + if (umount2(i, MNT_FORCE) < 0) + log_warning_errno(errno, "Failed to unmount %s: %m", i); + continue; + } mkdir_p_label(new_mount, 0755); - if ((stat(new_mount, &sb) < 0) || + if (stat(new_mount, &sb) < 0 || sb.st_dev != new_root_stat.st_dev) { /* Mount point seems to be mounted already or - * stat failed. Unmount the old mount - * point. */ + * stat failed. Unmount the old mount point. */ if (umount2(i, MNT_DETACH) < 0) log_warning_errno(errno, "Failed to unmount %s: %m", i); continue; @@ -97,10 +109,9 @@ int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot, if (umount2(i, MNT_FORCE) < 0) log_warning_errno(errno, "Failed to unmount %s: %m", i); - } - if (mountflags & MS_BIND) - log_error_errno(errno, "Failed to bind mount %s to %s: %m", i, new_mount); + } else if (mountflags & MS_BIND) + log_error_errno(errno, "Failed to bind mount %s to %s: %m", i, new_mount); } } -- cgit v1.2.3-54-g00ecf From e02c6135602bef7de81d7736d5c0959d45d5085c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 2 Nov 2016 22:05:48 -0400 Subject: udev/udev-watch: calculate the real buffer sizes needed --- src/udev/udev-node.c | 4 ++-- src/udev/udev-watch.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c index 5d2997fd8f..43004bc0bc 100644 --- a/src/udev/udev-node.c +++ b/src/udev/udev-node.c @@ -337,7 +337,7 @@ out: void udev_node_add(struct udev_device *dev, bool apply, mode_t mode, uid_t uid, gid_t gid, struct udev_list *seclabel_list) { - char filename[UTIL_PATH_SIZE]; + char filename[sizeof("/dev/block/:") + 2*DECIMAL_STR_MAX(unsigned)]; struct udev_list_entry *list_entry; log_debug("handling device node '%s', devnum=%s, mode=%#o, uid="UID_FMT", gid="GID_FMT, @@ -360,7 +360,7 @@ void udev_node_add(struct udev_device *dev, bool apply, void udev_node_remove(struct udev_device *dev) { struct udev_list_entry *list_entry; - char filename[UTIL_PATH_SIZE]; + char filename[sizeof("/dev/block/:") + 2*DECIMAL_STR_MAX(unsigned)]; /* remove/update symlinks, remove symlinks from name index */ udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c index 9ce5e975de..bc9096ed0c 100644 --- a/src/udev/udev-watch.c +++ b/src/udev/udev-watch.c @@ -89,7 +89,7 @@ unlink: } void udev_watch_begin(struct udev *udev, struct udev_device *dev) { - char filename[UTIL_PATH_SIZE]; + char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)]; int wd; int r; @@ -116,7 +116,7 @@ void udev_watch_begin(struct udev *udev, struct udev_device *dev) { void udev_watch_end(struct udev *udev, struct udev_device *dev) { int wd; - char filename[UTIL_PATH_SIZE]; + char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)]; if (inotify_fd < 0) return; @@ -135,7 +135,7 @@ void udev_watch_end(struct udev *udev, struct udev_device *dev) { } struct udev_device *udev_watch_lookup(struct udev *udev, int wd) { - char filename[UTIL_PATH_SIZE]; + char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)]; char device[UTIL_NAME_SIZE]; ssize_t len; -- cgit v1.2.3-54-g00ecf From 1258f088981ac62efd846de91922eef033302e76 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 2 Nov 2016 22:48:08 -0400 Subject: parse_hwdb: add import fallback for python2 --- hwdb/parse_hwdb.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hwdb/parse_hwdb.py b/hwdb/parse_hwdb.py index 2540c8c2f6..5d4c5ea64d 100755 --- a/hwdb/parse_hwdb.py +++ b/hwdb/parse_hwdb.py @@ -49,6 +49,12 @@ except ImportError: ecodes = None print('WARNING: evdev is not available') +try: + from functools import lru_cache +except ImportError: + # don't do caching on old python + lru_cache = lambda: (lambda f: f) + EOL = LineEnd().suppress() EMPTYLINE = LineStart() + LineEnd() COMMENTLINE = pythonStyleComment + EOL @@ -62,7 +68,7 @@ TYPES = {'mouse': ('usb', 'bluetooth', 'ps2', '*'), 'keyboard': ('name', ), } -@functools.lru_cache() +@lru_cache() def hwdb_grammar(): ParserElement.setDefaultWhitespaceChars('') @@ -83,7 +89,7 @@ def hwdb_grammar(): return grammar -@functools.lru_cache() +@lru_cache() def property_grammar(): ParserElement.setDefaultWhitespaceChars(' ') -- cgit v1.2.3-54-g00ecf From cdc5d5c55e58ff9eeb6b2258c9fc3a416ee8b53f Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Wed, 2 Nov 2016 22:42:40 +0100 Subject: core: intialize user aux groups and SupplementaryGroups= when DynamicUser= is set Make sure that when DynamicUser= is set that we intialize the user supplementary groups and that we also support SupplementaryGroups= Fixes: https://github.com/systemd/systemd/issues/4539 Thanks Evgeny Vereshchagin (@evverx) --- src/core/execute.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/core/execute.c b/src/core/execute.c index 3f053602b5..f13ca30395 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -773,11 +773,9 @@ static int get_fixed_group(const ExecContext *c, const char **group, gid_t *gid) return 0; } -static int get_fixed_supplementary_groups(const ExecContext *c, - const char *user, - const char *group, - gid_t gid, - gid_t **supplementary_gids, int *ngids) { +static int get_supplementary_groups(const ExecContext *c, const char *user, + const char *group, gid_t gid, + gid_t **supplementary_gids, int *ngids) { char **i; int r, k = 0; int ngroups_max; @@ -790,8 +788,8 @@ static int get_fixed_supplementary_groups(const ExecContext *c, /* * If user is given, then lookup GID and supplementary groups list. * We avoid NSS lookups for gid=0. Also we have to initialize groups - * as early as possible so we keep the list of supplementary groups - * of the caller. + * here and as early as possible so we keep the list of supplementary + * groups of the caller. */ if (user && gid_is_valid(gid) && gid != 0) { /* First step, initialize groups from /etc/groups */ @@ -2347,13 +2345,14 @@ static int exec_child( *exit_status = EXIT_GROUP; return r; } + } - r = get_fixed_supplementary_groups(context, username, groupname, - gid, &supplementary_gids, &ngids); - if (r < 0) { - *exit_status = EXIT_GROUP; - return r; - } + /* Initialize user supplementary groups and get SupplementaryGroups= ones */ + r = get_supplementary_groups(context, username, groupname, gid, + &supplementary_gids, &ngids); + if (r < 0) { + *exit_status = EXIT_GROUP; + return r; } r = send_user_lookup(unit, user_lookup_fd, uid, gid); -- cgit v1.2.3-54-g00ecf From 2b9ac11ed96f2823972a77fc7cb0c32981218429 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Wed, 2 Nov 2016 22:59:41 +0100 Subject: test: test DynamicUser= with a fixed user --- Makefile.am | 2 ++ src/test/test-execute.c | 6 ++++++ .../exec-dynamicuser-fixeduser-one-supplementarygroup.service | 9 +++++++++ test/test-execute/exec-dynamicuser-fixeduser.service | 8 ++++++++ 4 files changed, 25 insertions(+) create mode 100644 test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service create mode 100644 test/test-execute/exec-dynamicuser-fixeduser.service diff --git a/Makefile.am b/Makefile.am index 34c2f60330..3226ea4549 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1626,6 +1626,8 @@ EXTRA_DIST += \ test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service \ test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service \ test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service \ + test/test-execute/exec-dynamicuser-fixeduser.service \ + test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service \ test/test-execute/exec-ignoresigpipe-no.service \ test/test-execute/exec-ignoresigpipe-yes.service \ test/test-execute/exec-personality-x86-64.service \ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index c369098500..aa5a9f1695 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -259,6 +259,11 @@ static void test_exec_supplementary_groups(Manager *m) { test(m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED); } +static void test_exec_dynamic_user(Manager *m) { + test(m, "exec-dynamicuser-fixeduser.service", 0, CLD_EXITED); + test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", 0, CLD_EXITED); +} + static void test_exec_environment(Manager *m) { test(m, "exec-environment.service", 0, CLD_EXITED); test(m, "exec-environment-multiple.service", 0, CLD_EXITED); @@ -432,6 +437,7 @@ int main(int argc, char *argv[]) { test_exec_user, test_exec_group, test_exec_supplementary_groups, + test_exec_dynamic_user, test_exec_environment, test_exec_environmentfile, test_exec_passenvironment, diff --git a/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service b/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service new file mode 100644 index 0000000000..de1a6e7303 --- /dev/null +++ b/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test DynamicUser with User= and SupplementaryGroups= + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -G)" = "1" && test "$$(id -g)" = "1" && test "$$(id -u)" = "1"' +Type=oneshot +User=1 +DynamicUser=yes +SupplementaryGroups=1 diff --git a/test/test-execute/exec-dynamicuser-fixeduser.service b/test/test-execute/exec-dynamicuser-fixeduser.service new file mode 100644 index 0000000000..1d84af02ed --- /dev/null +++ b/test/test-execute/exec-dynamicuser-fixeduser.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test DynamicUser with User= + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -G)" = "1" && test "$$(id -g)" = "1" && test "$$(id -u)" = "1"' +Type=oneshot +User=1 +DynamicUser=yes -- cgit v1.2.3-54-g00ecf From 5c67067f0e521aba061904c7bb3aa092281ef9c4 Mon Sep 17 00:00:00 2001 From: Djalal Harouni Date: Wed, 2 Nov 2016 23:02:28 +0100 Subject: test: test DynamicUser= with SupplementaryGroups= --- Makefile.am | 1 + src/test/test-execute.c | 1 + test/test-execute/exec-dynamicuser-supplementarygroups.service | 8 ++++++++ 3 files changed, 10 insertions(+) create mode 100644 test/test-execute/exec-dynamicuser-supplementarygroups.service diff --git a/Makefile.am b/Makefile.am index 3226ea4549..f7652c2346 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1628,6 +1628,7 @@ EXTRA_DIST += \ test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service \ test/test-execute/exec-dynamicuser-fixeduser.service \ test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service \ + test/test-execute/exec-dynamicuser-supplementarygroups.service \ test/test-execute/exec-ignoresigpipe-no.service \ test/test-execute/exec-ignoresigpipe-yes.service \ test/test-execute/exec-personality-x86-64.service \ diff --git a/src/test/test-execute.c b/src/test/test-execute.c index aa5a9f1695..6029853e3e 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -262,6 +262,7 @@ static void test_exec_supplementary_groups(Manager *m) { static void test_exec_dynamic_user(Manager *m) { test(m, "exec-dynamicuser-fixeduser.service", 0, CLD_EXITED); test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", 0, CLD_EXITED); + test(m, "exec-dynamicuser-supplementarygroups.service", 0, CLD_EXITED); } static void test_exec_environment(Manager *m) { diff --git a/test/test-execute/exec-dynamicuser-supplementarygroups.service b/test/test-execute/exec-dynamicuser-supplementarygroups.service new file mode 100644 index 0000000000..a47b7fab78 --- /dev/null +++ b/test/test-execute/exec-dynamicuser-supplementarygroups.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test DynamicUser with SupplementaryGroups= + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -G | cut -d " " --complement -f 1)" = "1 2 3"' +Type=oneshot +DynamicUser=yes +SupplementaryGroups=1 2 3 -- cgit v1.2.3-54-g00ecf From 54b24597b84d5f96441825b9dc11334492a5d143 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Nov 2016 08:56:26 -0600 Subject: final NEWS update for 232 (#4558) let's get this out today! --- NEWS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index f0ad917464..b10a6f538f 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ systemd System and Service Manager -CHANGES WITH 232 in spe +CHANGES WITH 232: * The new RemoveIPC= option can be used to remove IPC objects owned by the user or group of a service when that service exits. @@ -347,7 +347,7 @@ CHANGES WITH 232 in spe E. MORIN, Yi EungJun, Yuki Inoguchi, Yu Watanabe, Zbigniew Jędrzejewski-Szmek, Zeal Jagannatha - — Santa Fe, 2016-11-XX + — Santa Fe, 2016-11-03 CHANGES WITH 231: -- cgit v1.2.3-54-g00ecf From c14eff367ca39b16830f76cdc90dcb70de174667 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Nov 2016 11:16:01 -0600 Subject: hwdb update for 232 (#4557) --- hwdb/20-OUI.hwdb | 21057 ++++++++++++++++++++++------------------ hwdb/20-acpi-vendor.hwdb | 24 + hwdb/20-pci-vendor-model.hwdb | 1391 ++- hwdb/20-usb-vendor-model.hwdb | 1149 ++- 4 files changed, 14008 insertions(+), 9613 deletions(-) diff --git a/hwdb/20-OUI.hwdb b/hwdb/20-OUI.hwdb index dd63627328..6bce57305d 100644 --- a/hwdb/20-OUI.hwdb +++ b/hwdb/20-OUI.hwdb @@ -998,6 +998,108 @@ OUI:70B3D51C8* OUI:70B3D5142* ID_OUI_FROM_DATABASE=DAVE SRL +OUI:70B3D5666* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D56A8* + ID_OUI_FROM_DATABASE=Vitsch Electronics + +OUI:70B3D5EBD* + ID_OUI_FROM_DATABASE=midBit Technologies, LLC + +OUI:70B3D5A8E* + ID_OUI_FROM_DATABASE=OMESH CITY GROUP + +OUI:70B3D5779* + ID_OUI_FROM_DATABASE=DR.BRIDGE AQUATECH + +OUI:70B3D5F5C* + ID_OUI_FROM_DATABASE=Nable Communications, Inc. + +OUI:70B3D5550* + ID_OUI_FROM_DATABASE=Merten GmbH&CoKG + +OUI:70B3D51BB* + ID_OUI_FROM_DATABASE=EFENTO T P SZYDŁOWSKI K ZARĘBA SPÓŁKA JAWNA + +OUI:70B3D5498* + ID_OUI_FROM_DATABASE=XGEM SAS + +OUI:70B3D5AAA* + ID_OUI_FROM_DATABASE=Xemex NV + +OUI:70B3D5197* + ID_OUI_FROM_DATABASE=Lattech Systems Pty Ltd + +OUI:70B3D5593* + ID_OUI_FROM_DATABASE=Asis Pro + +OUI:70B3D522F* + ID_OUI_FROM_DATABASE=Instec, Inc. + +OUI:70B3D5DD8* + ID_OUI_FROM_DATABASE=EMSCAN Corp. + +OUI:70B3D5ACD* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5BCC* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D55D6* + ID_OUI_FROM_DATABASE=BMT Messtechnik Gmbh + +OUI:70B3D53BE* + ID_OUI_FROM_DATABASE=MyDefence Communication ApS + +OUI:70B3D5289* + ID_OUI_FROM_DATABASE=Shenzhen Rongda Computer Co.,Ltd + +OUI:70B3D5C3E* + ID_OUI_FROM_DATABASE=DOSADORES ALLTRONIC + +OUI:70B3D59FB* + ID_OUI_FROM_DATABASE=Unicom Global, Inc. + +OUI:70B3D524D* + ID_OUI_FROM_DATABASE=INFO CREATIVE (HK) LTD + +OUI:70B3D5A36* + ID_OUI_FROM_DATABASE=Beijing DamingWuzhou Science&Technology Co., Ltd. + +OUI:70B3D59F8* + ID_OUI_FROM_DATABASE=Asymmetric Technologies + +OUI:70B3D5A85* + ID_OUI_FROM_DATABASE=exceet electronics GesmbH + +OUI:70B3D5AC5* + ID_OUI_FROM_DATABASE=ATOM GIKEN Co.,Ltd. + +OUI:70B3D5F07* + ID_OUI_FROM_DATABASE=DUVAL MESSIEN + +OUI:70B3D5939* + ID_OUI_FROM_DATABASE=Invertek Drives Ltd + +OUI:70B3D56D0* + ID_OUI_FROM_DATABASE=Code Blue Corporation + +OUI:70B3D52C3* + ID_OUI_FROM_DATABASE=Proterra + +OUI:70B3D5816* + ID_OUI_FROM_DATABASE=Smith Meter, Inc. + +OUI:70B3D5693* + ID_OUI_FROM_DATABASE=Altron, a.s. + +OUI:70B3D55D3* + ID_OUI_FROM_DATABASE=Supracon AG + +OUI:70B3D52AD* + ID_OUI_FROM_DATABASE=Opgal Optronic Industries + OUI:70B3D5D60* ID_OUI_FROM_DATABASE=Flintab AB @@ -1040,9 +1142,6 @@ OUI:70B3D5AE0* OUI:70B3D52B3* ID_OUI_FROM_DATABASE=HAS co.,ltd. -OUI:70B3D511D* - ID_OUI_FROM_DATABASE=Texka Labs - OUI:70B3D5D5A* ID_OUI_FROM_DATABASE=WyreStorm Technologies Ltd @@ -1817,6 +1916,66 @@ OUI:70B3D513E* OUI:70B3D50BA* ID_OUI_FROM_DATABASE=Ayre Acoustics, Inc. +OUI:70B3D510C* + ID_OUI_FROM_DATABASE=Vocality International Ltd + +OUI:70B3D5B7D* + ID_OUI_FROM_DATABASE=LOGIX ITS Inc + +OUI:70B3D5307* + ID_OUI_FROM_DATABASE=Energi innovation Aps + +OUI:70B3D59FA* + ID_OUI_FROM_DATABASE=Ideas srl + +OUI:70B3D5649* + ID_OUI_FROM_DATABASE=swissled technologies AG + +OUI:70B3D5C0E* + ID_OUI_FROM_DATABASE=SYSDEV Srl + +OUI:70B3D54C7* + ID_OUI_FROM_DATABASE=SOLVERIS sp. z o.o. + +OUI:70B3D57A4* + ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC + +OUI:70B3D5C86* + ID_OUI_FROM_DATABASE=Woodam Co., Ltd. + +OUI:70B3D5BE8* + ID_OUI_FROM_DATABASE=AndFun Co.,Ltd. + +OUI:70B3D527A* + ID_OUI_FROM_DATABASE=TD ECOPHISIKA + +OUI:70B3D554F* + ID_OUI_FROM_DATABASE=Assembly Contracts Limited + +OUI:70B3D5C0A* + ID_OUI_FROM_DATABASE=Infosocket Co., Ltd. + +OUI:70B3D5D95* + ID_OUI_FROM_DATABASE=SANO SERVICE Co.,Ltd + +OUI:70B3D52AC* + ID_OUI_FROM_DATABASE=New Imaging Technologies + +OUI:70B3D50D3* + ID_OUI_FROM_DATABASE=TSAT AS + +OUI:70B3D5A89* + ID_OUI_FROM_DATABASE=GBS COMMUNICATIONS, LLC + +OUI:70B3D57E1* + ID_OUI_FROM_DATABASE=Applied Materials + +OUI:70B3D554C* + ID_OUI_FROM_DATABASE=Husty M.Styczen J.Hupert Sp.J. + +OUI:70B3D5041* + ID_OUI_FROM_DATABASE=FIBERNET LTD + OUI:70B3D5AAE* ID_OUI_FROM_DATABASE=Nuviz Oy @@ -1907,29 +2066,92 @@ OUI:70B3D5238* OUI:70B3D59B6* ID_OUI_FROM_DATABASE=Intercomp S.p.A. -OUI:70B3D510C* - ID_OUI_FROM_DATABASE=Vocality International Ltd +OUI:70B3D5E8F* + ID_OUI_FROM_DATABASE=DISMUNTEL, S.A. -OUI:70B3D5B7D* - ID_OUI_FROM_DATABASE=LOGIX ITS Inc +OUI:70B3D57B0* + ID_OUI_FROM_DATABASE=Medisafe International -OUI:70B3D5307* - ID_OUI_FROM_DATABASE=Energi innovation Aps +OUI:70B3D509F* + ID_OUI_FROM_DATABASE=COMTECH Kft. -OUI:70B3D59FA* - ID_OUI_FROM_DATABASE=Ideas srl +OUI:70B3D5009* + ID_OUI_FROM_DATABASE=HolidayCoro -OUI:70B3D5649* - ID_OUI_FROM_DATABASE=swissled technologies AG +OUI:70B3D5AB0* + ID_OUI_FROM_DATABASE=OSR R&D ISRAEL LTD -OUI:70B3D5C0E* - ID_OUI_FROM_DATABASE=SYSDEV Srl +OUI:70B3D5317* + ID_OUI_FROM_DATABASE=Iotopia Solutions -OUI:70B3D54C7* - ID_OUI_FROM_DATABASE=SOLVERIS sp. z o.o. +OUI:70B3D5D32* + ID_OUI_FROM_DATABASE=Euklis by GSG International -OUI:70B3D57A4* - ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC +OUI:70B3D56B0* + ID_OUI_FROM_DATABASE=PTYPE Co., LTD. + +OUI:70B3D51E9* + ID_OUI_FROM_DATABASE=comtime GmbH + +OUI:70B3D586C* + ID_OUI_FROM_DATABASE=eeas gmbh + +OUI:70B3D5B0C* + ID_OUI_FROM_DATABASE=Vigilate srl + +OUI:70B3D5B37* + ID_OUI_FROM_DATABASE=CODEC Co., Ltd. + +OUI:70B3D5597* + ID_OUI_FROM_DATABASE=VAPE RAIL INTERNATIONAL + +OUI:70B3D5850* + ID_OUI_FROM_DATABASE=REO AG + +OUI:70B3D537A* + ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC + +OUI:70B3D5C3D* + ID_OUI_FROM_DATABASE=CISTECH Solutions + +OUI:70B3D5F8B* + ID_OUI_FROM_DATABASE=IOOOTA Srl + +OUI:70B3D52EC* + ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. + +OUI:70B3D599E* + ID_OUI_FROM_DATABASE=Trinity College Dublin + +OUI:70B3D5462* + ID_OUI_FROM_DATABASE=EarTex + +OUI:70B3D54CE* + ID_OUI_FROM_DATABASE=Agilack + +OUI:70B3D5F17* + ID_OUI_FROM_DATABASE=VITEC + +OUI:70B3D511D* + ID_OUI_FROM_DATABASE=Dakton Microlabs LLC + +OUI:70B3D5924* + ID_OUI_FROM_DATABASE=Meridian Technologies Inc + +OUI:70B3D503D* + ID_OUI_FROM_DATABASE=QUERCUS TECHNOLOGIES, S.L. + +OUI:70B3D5B97* + ID_OUI_FROM_DATABASE=Canam Technology, Inc. + +OUI:70B3D5352* + ID_OUI_FROM_DATABASE=Globalcom Engineering SPA + +OUI:70B3D57F4* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D5122* + ID_OUI_FROM_DATABASE=Henri Systems Holland bv OUI:70B3D5494* ID_OUI_FROM_DATABASE=Schildknecht AG @@ -2816,12 +3038,12 @@ OUI:70B3D58B3* OUI:70B3D5599* ID_OUI_FROM_DATABASE=LECO Corporation -OUI:70B3D5896* - ID_OUI_FROM_DATABASE=Shanghai Longpal Communication Equipment Co., Ltd. - OUI:70B3D5692* ID_OUI_FROM_DATABASE=HOSIN INDUSTRIAL LIMITED +OUI:70B3D5896* + ID_OUI_FROM_DATABASE=Shanghai Longpal Communication Equipment Co., Ltd. + OUI:70B3D5AE7* ID_OUI_FROM_DATABASE=E-T-A Elektrotechnische Apparate GmbH @@ -2834,15 +3056,15 @@ OUI:70B3D5E0F* OUI:70B3D512F* ID_OUI_FROM_DATABASE=DSP4YOU LTd +OUI:70B3D571B* + ID_OUI_FROM_DATABASE=elsys + OUI:70B3D59B1* ID_OUI_FROM_DATABASE=Aplex Technology Inc. OUI:70B3D5CA4* ID_OUI_FROM_DATABASE=Netemera Sp. z o.o. -OUI:70B3D571B* - ID_OUI_FROM_DATABASE=elsys - OUI:70B3D548F* ID_OUI_FROM_DATABASE=Seiwa Giken @@ -2858,6 +3080,144 @@ OUI:70B3D5D2F* OUI:70B3D536A* ID_OUI_FROM_DATABASE=Becton Dickinson +OUI:70B3D5C80* + ID_OUI_FROM_DATABASE=Link Care Services + +OUI:70B3D5607* + ID_OUI_FROM_DATABASE=ATEME + +OUI:70B3D5A33* + ID_OUI_FROM_DATABASE=TIAMA + +OUI:70B3D5A19* + ID_OUI_FROM_DATABASE=Qualitronix Madrass Pvt Ltd + +OUI:70B3D5F81* + ID_OUI_FROM_DATABASE=Littlemore Scientific + +OUI:70B3D5B3F* + ID_OUI_FROM_DATABASE=Orbit International + +OUI:70B3D528D* + ID_OUI_FROM_DATABASE=Technica Engineering GmbH + +OUI:70B3D5B62* + ID_OUI_FROM_DATABASE=Sakura Seiki Co.,Ltd. + +OUI:70B3D5CCF* + ID_OUI_FROM_DATABASE=Netberg + +OUI:70B3D5131* + ID_OUI_FROM_DATABASE=Inova Design Solutions Ltd + +OUI:70B3D5987* + ID_OUI_FROM_DATABASE=AXIS CORPORATION + +OUI:70B3D52BA* + ID_OUI_FROM_DATABASE=Active Brains + +OUI:70B3D50CE* + ID_OUI_FROM_DATABASE=Innominds Software Inc + +OUI:70B3D5644* + ID_OUI_FROM_DATABASE=ATX Networks Corp + +OUI:70B3D5376* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D552C* + ID_OUI_FROM_DATABASE=Centuryarks Ltd., + +OUI:70B3D5BC2* + ID_OUI_FROM_DATABASE=DWEWOONG ELECTRIC Co., Ltd. + +OUI:70B3D5DFC* + ID_OUI_FROM_DATABASE=ELECTRONIC SYSTEMS DESIGN SPRL + +OUI:70B3D57E5* + ID_OUI_FROM_DATABASE=Megaflex Oy + +OUI:70B3D5503* + ID_OUI_FROM_DATABASE=Itest communication Tech Co., LTD + +OUI:70B3D548A* + ID_OUI_FROM_DATABASE=George Wilson Industries Ltd + +OUI:70B3D50E5* + ID_OUI_FROM_DATABASE=Delta Solutions LLC + +OUI:70B3D581E* + ID_OUI_FROM_DATABASE=Novathings + +OUI:70B3D504B* + ID_OUI_FROM_DATABASE=Dream I System Co., Ltd + +OUI:70B3D549A* + ID_OUI_FROM_DATABASE=HAXE SYSTEME + +OUI:70B3D563C* + ID_OUI_FROM_DATABASE=Pivothead + +OUI:70B3D5ADB* + ID_OUI_FROM_DATABASE=RF Code + +OUI:70B3D5B53* + ID_OUI_FROM_DATABASE=Revolution Retail Systems, LLC + +OUI:70B3D5C7E* + ID_OUI_FROM_DATABASE=BirdDog Australia + +OUI:70B3D5F03* + ID_OUI_FROM_DATABASE=GMI Ltd + +OUI:70B3D58C2* + ID_OUI_FROM_DATABASE=F-domain corporation + +OUI:70B3D56CF* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D572C* + ID_OUI_FROM_DATABASE=NuRi&G Engineering co,.Ltd. + +OUI:70B3D5735* + ID_OUI_FROM_DATABASE=Swiss Audio + +OUI:70B3D5260* + ID_OUI_FROM_DATABASE=ModuSystems, Inc + +OUI:70B3D54EF* + ID_OUI_FROM_DATABASE=CMI, Inc. + +OUI:70B3D5C12* + ID_OUI_FROM_DATABASE=Beijing Wisetone Information Technology Co.,Ltd. + +OUI:70B3D5930* + ID_OUI_FROM_DATABASE=The Institute of Mine Seismology + +OUI:70B3D5188* + ID_OUI_FROM_DATABASE=Birket Engineering + +OUI:70B3D55E2* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D525A* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D516F* + ID_OUI_FROM_DATABASE=NimbeLink Corp + +OUI:70B3D59C0* + ID_OUI_FROM_DATABASE=Schneider Displaytechnik GmbH + +OUI:70B3D5149* + ID_OUI_FROM_DATABASE=eleven-x + +OUI:70B3D5E98* + ID_OUI_FROM_DATABASE=JSC Kaluga Astral + +OUI:70B3D5443* + ID_OUI_FROM_DATABASE=Slot3 GmbH + OUI:70B3D566B* ID_OUI_FROM_DATABASE=Innitive B.V. @@ -3626,6 +3986,117 @@ OUI:70B3D5A96* OUI:70B3D5367* ID_OUI_FROM_DATABASE=Living Water +OUI:70B3D58DB* + ID_OUI_FROM_DATABASE=Kratos Analytical Ltd + +OUI:70B3D5A4F* + ID_OUI_FROM_DATABASE=Weltek Technologies Co. Ltd. + +OUI:70B3D51A3* + ID_OUI_FROM_DATABASE=Telairity Semiconductor + +OUI:70B3D5650* + ID_OUI_FROM_DATABASE=GIFAS-ELECTRIC GmbH + +OUI:70B3D5C63* + ID_OUI_FROM_DATABASE=Xentech Solutions Limited + +OUI:70B3D5106* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D56C5* + ID_OUI_FROM_DATABASE=CJSC «Russian telecom equipment company» (CJSC RTEC) + +OUI:70B3D5FE9* + ID_OUI_FROM_DATABASE=Camsat Przemysław Gralak + +OUI:70B3D54C5* + ID_OUI_FROM_DATABASE=Moving iMage Technologies LLC + +OUI:70B3D591A* + ID_OUI_FROM_DATABASE=Fujian Landfone Information Technology Co.,Ltd + +OUI:70B3D59EC* + ID_OUI_FROM_DATABASE=eSoftThings + +OUI:70B3D5761* + ID_OUI_FROM_DATABASE=Critical Link LLC + +OUI:70B3D5C22* + ID_OUI_FROM_DATABASE=Skyriver Communications Inc. + +OUI:70B3D53BB* + ID_OUI_FROM_DATABASE=A-M Systems + +OUI:70B3D5B44* + ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD. + +OUI:70B3D5584* + ID_OUI_FROM_DATABASE=Sertone, a division of Opti-Knights Ltd + +OUI:70B3D53EF* + ID_OUI_FROM_DATABASE=Vtron Pty Ltd + +OUI:70B3D57C2* + ID_OUI_FROM_DATABASE=Morgan Schaffer Inc. + +OUI:70B3D5697* + ID_OUI_FROM_DATABASE=Alazar Technologies Inc. + +OUI:70B3D561A* + ID_OUI_FROM_DATABASE=Rocket Lab Ltd. + +OUI:70B3D5855* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5F8D* + ID_OUI_FROM_DATABASE=Flextronics Canafa Design Services + +OUI:70B3D59AE* + ID_OUI_FROM_DATABASE=Volansys technologies pvt ltd + +OUI:70B3D542C* + ID_OUI_FROM_DATABASE=D.Marchiori Srl + +OUI:70B3D5CE5* + ID_OUI_FROM_DATABASE=GridBridge Inc + +OUI:70B3D51EF* + ID_OUI_FROM_DATABASE=ADTEK + +OUI:70B3D5EDB* + ID_OUI_FROM_DATABASE=Netfort Solutions + +OUI:70B3D5CD9* + ID_OUI_FROM_DATABASE=Peter Huber Kaeltemaschinenbau GmbH + +OUI:70B3D51D7* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5976* + ID_OUI_FROM_DATABASE=Atonarp Micro-Systems India Pvt. Ltd. + +OUI:70B3D50DA* + ID_OUI_FROM_DATABASE=Aquavision Distribution Ltd + +OUI:70B3D5989* + ID_OUI_FROM_DATABASE=DCNS + +OUI:70B3D5833* + ID_OUI_FROM_DATABASE=Alpiq InTec Management AG + +OUI:70B3D53E8* + ID_OUI_FROM_DATABASE=COSMOS web Co., Ltd. + +OUI:70B3D597F* + ID_OUI_FROM_DATABASE=BISTOS.,Co.,Ltd + +OUI:70B3D5C5D* + ID_OUI_FROM_DATABASE=FOSHAN SHILANTIAN NETWORK S.T. CO., LTD. + +OUI:70B3D573B* + ID_OUI_FROM_DATABASE=S-I-C + OUI:70B3D5114* ID_OUI_FROM_DATABASE=Project H Pty Ltd @@ -3683,83 +4154,104 @@ OUI:70B3D5C4F* OUI:70B3D5BD9* ID_OUI_FROM_DATABASE=SolwayTech -OUI:70B3D58DB* - ID_OUI_FROM_DATABASE=Kratos Analytical Ltd +OUI:70B3D5F35* + ID_OUI_FROM_DATABASE=carbonTRACK -OUI:70B3D5A4F* - ID_OUI_FROM_DATABASE=Weltek Technologies Co. Ltd. +OUI:70B3D529F* + ID_OUI_FROM_DATABASE=Code Hardware SA -OUI:70B3D51A3* - ID_OUI_FROM_DATABASE=Telairity Semiconductor +OUI:70B3D5F76* + ID_OUI_FROM_DATABASE=Thermo Fisher Scientific -OUI:70B3D5650* - ID_OUI_FROM_DATABASE=GIFAS-ELECTRIC GmbH +OUI:70B3D52B9* + ID_OUI_FROM_DATABASE=BELECTRIC GmbH -OUI:70B3D5C63* - ID_OUI_FROM_DATABASE=Xentech Solutions Limited +OUI:70B3D59AD* + ID_OUI_FROM_DATABASE=Fortuna Impex Pvt ltd -OUI:70B3D5106* - ID_OUI_FROM_DATABASE=Aplex Technology Inc. +OUI:70B3D5594* + ID_OUI_FROM_DATABASE=ATE Systems Inc -OUI:70B3D56C5* - ID_OUI_FROM_DATABASE=CJSC «Russian telecom equipment company» (CJSC RTEC) +OUI:70B3D58CB* + ID_OUI_FROM_DATABASE=WELT Corporation -OUI:70B3D5FE9* - ID_OUI_FROM_DATABASE=Camsat Przemysław Gralak +OUI:70B3D5405* + ID_OUI_FROM_DATABASE=MG s.r.l. -OUI:70B3D54C5* - ID_OUI_FROM_DATABASE=Moving iMage Technologies LLC +OUI:70B3D587E* + ID_OUI_FROM_DATABASE=Septentrio NV -OUI:70B3D591A* - ID_OUI_FROM_DATABASE=Fujian Landfone Information Technology Co.,Ltd +OUI:70B3D5ECB* + ID_OUI_FROM_DATABASE=Re spa - Controlli Industriali - IT01782300154 -OUI:70B3D59EC* - ID_OUI_FROM_DATABASE=eSoftThings +OUI:70B3D55F4* + ID_OUI_FROM_DATABASE=FDSTiming -OUI:70B3D5761* - ID_OUI_FROM_DATABASE=Critical Link LLC +OUI:70B3D5D75* + ID_OUI_FROM_DATABASE=Hyundai MNSOFT -OUI:70B3D5C22* - ID_OUI_FROM_DATABASE=Skyriver Communications Inc. +OUI:70B3D5D9A* + ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd -OUI:70B3D53BB* - ID_OUI_FROM_DATABASE=A-M Systems +OUI:70B3D59C7* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd -OUI:70B3D5B44* - ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD. +OUI:70B3D532A* + ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd -OUI:70B3D5584* - ID_OUI_FROM_DATABASE=Sertone, a division of Opti-Knights Ltd +OUI:70B3D560E* + ID_OUI_FROM_DATABASE=HDANYWHERE -OUI:70B3D53EF* - ID_OUI_FROM_DATABASE=Vtron Pty Ltd +OUI:70B3D5EBB* + ID_OUI_FROM_DATABASE=Beijing Wing ICT Technology Co., Ltd. -OUI:70B3D57C2* - ID_OUI_FROM_DATABASE=Morgan Schaffer Inc. +OUI:70B3D5B09* + ID_OUI_FROM_DATABASE=FIRST LIGHT IMAGING -OUI:70B3D5697* - ID_OUI_FROM_DATABASE=Alazar Technologies Inc. +OUI:70B3D518C* + ID_OUI_FROM_DATABASE=CMC Industrial Electronics Ltd -OUI:70B3D561A* - ID_OUI_FROM_DATABASE=Rocket Lab Ltd. +OUI:70B3D5AFF* + ID_OUI_FROM_DATABASE=digital-spice -OUI:70B3D5855* - ID_OUI_FROM_DATABASE=CRDE +OUI:70B3D5563* + ID_OUI_FROM_DATABASE=Zhejiang Hao Teng Electronic Technology Co., Ltd. -OUI:70B3D5F8D* - ID_OUI_FROM_DATABASE=Flextronics Canafa Design Services +OUI:70B3D5C06* + ID_OUI_FROM_DATABASE=XotonicsMED GmbH -OUI:70B3D59AE* - ID_OUI_FROM_DATABASE=Volansys technologies pvt ltd +OUI:70B3D52DB* + ID_OUI_FROM_DATABASE=ProtoPixel SL -OUI:70B3D542C* - ID_OUI_FROM_DATABASE=D.Marchiori Srl +OUI:70B3D5A58* + ID_OUI_FROM_DATABASE=MCQ TECH GmbH -OUI:70B3D5CE5* - ID_OUI_FROM_DATABASE=GridBridge Inc +OUI:70B3D5934* + ID_OUI_FROM_DATABASE=RBS Netkom GmbH -OUI:70B3D51EF* - ID_OUI_FROM_DATABASE=ADTEK +OUI:70B3D513D* + ID_OUI_FROM_DATABASE=Elsist Srl + +OUI:70B3D53B7* + ID_OUI_FROM_DATABASE=Paul Scherrer Institut (PSI) + +OUI:70B3D594D* + ID_OUI_FROM_DATABASE=SEASON DESIGN TECHNOLOGY + +OUI:70B3D5A4C* + ID_OUI_FROM_DATABASE=Alere Technologies AS + +OUI:70B3D590B* + ID_OUI_FROM_DATABASE=Matrix Switch Corporation + +OUI:70B3D5C4B* + ID_OUI_FROM_DATABASE=ANKER-EAST + +OUI:70B3D5542* + ID_OUI_FROM_DATABASE=RTDS Technologies Inc. + +OUI:70B3D568E* + ID_OUI_FROM_DATABASE=CEA Technologies Pty Ltd OUI:70B3D58AB* ID_OUI_FROM_DATABASE=EMAC, Inc. @@ -4028,9 +4520,6 @@ OUI:70B3D5EFB* OUI:70B3D5A81* ID_OUI_FROM_DATABASE=Sienda New Media Technologies GmbH -OUI:70B3D5A1B* - ID_OUI_FROM_DATABASE=Potter Electric Signal Co. - OUI:70B3D5EAC* ID_OUI_FROM_DATABASE=Kentech Instruments Limited @@ -4067,9 +4556,6 @@ OUI:70B3D5DCF* OUI:70B3D5A25* ID_OUI_FROM_DATABASE=PulseTor LLC -OUI:70B3D5D3B* - ID_OUI_FROM_DATABASE=NimbeLink Corp - OUI:70B3D5882* ID_OUI_FROM_DATABASE=SIMON TECH, S.L. @@ -4523,6 +5009,90 @@ OUI:70B3D594F* OUI:70B3D5DFF* ID_OUI_FROM_DATABASE=Spanawave Corporation +OUI:70B3D57B6* + ID_OUI_FROM_DATABASE=Amada Miyachi America Inc. + +OUI:70B3D555A* + ID_OUI_FROM_DATABASE=Sontay Ltd. + +OUI:70B3D511C* + ID_OUI_FROM_DATABASE=Samriddi Automations Pvt. Ltd. + +OUI:70B3D5CB2* + ID_OUI_FROM_DATABASE=SECLAB + +OUI:70B3D5A91* + ID_OUI_FROM_DATABASE=IDEAL INDUSTRIES Ltd t/a Casella + +OUI:70B3D5AE5* + ID_OUI_FROM_DATABASE=BeatCraft, Inc. + +OUI:70B3D51DD* + ID_OUI_FROM_DATABASE=RF CREATIONS LTD + +OUI:70B3D51DA* + ID_OUI_FROM_DATABASE=Promess Inc. + +OUI:70B3D555B* + ID_OUI_FROM_DATABASE=Procon Electronics Pty Ltd + +OUI:70B3D50AE* + ID_OUI_FROM_DATABASE=Norsat International Inc. + +OUI:70B3D5461* + ID_OUI_FROM_DATABASE=TESEC Corporation + +OUI:70B3D57FB* + ID_OUI_FROM_DATABASE=db Broadcast Products Ltd + +OUI:70B3D56FF* + ID_OUI_FROM_DATABASE=AKEO PLUS + +OUI:70B3D5CD2* + ID_OUI_FROM_DATABASE=HBH Microwave GmbH + +OUI:70B3D5B23* + ID_OUI_FROM_DATABASE=Supervision Test et Pilotage + +OUI:70B3D5178* + ID_OUI_FROM_DATABASE=Gamber Johnson-LLC + +OUI:70B3D5A5C* + ID_OUI_FROM_DATABASE=Molekule + +OUI:70B3D5012* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D5FEC* + ID_OUI_FROM_DATABASE=Finder SpA + +OUI:70B3D519E* + ID_OUI_FROM_DATABASE=J-Factor Embedded Technologies + +OUI:70B3D5A20* + ID_OUI_FROM_DATABASE=Design For Life Systems + +OUI:70B3D590A* + ID_OUI_FROM_DATABASE=Hangzhou SunTown Intelligent Science & Technology Co.,Ltd. + +OUI:70B3D51DB* + ID_OUI_FROM_DATABASE=Hudson Robotics + +OUI:70B3D55CC* + ID_OUI_FROM_DATABASE=Akse srl + +OUI:70B3D5973* + ID_OUI_FROM_DATABASE=Autonomic Controls, Inc. + +OUI:70B3D5083* + ID_OUI_FROM_DATABASE=ZAO ZEO + +OUI:70B3D542A* + ID_OUI_FROM_DATABASE=Critical Link LLC + +OUI:70B3D5C0F* + ID_OUI_FROM_DATABASE=Honeywell Safety Products USA, Inc + OUI:70B3D565C* ID_OUI_FROM_DATABASE=Aplex Technology Inc. @@ -4580,9 +5150,6 @@ OUI:70B3D5A4A* OUI:70B3D585B* ID_OUI_FROM_DATABASE=TSUBAKIMOTO CHAIN CO. -OUI:70B3D56FF* - ID_OUI_FROM_DATABASE=AKEO PLUS - OUI:70B3D589B* ID_OUI_FROM_DATABASE=ControlWorks, Inc. @@ -4592,62 +5159,104 @@ OUI:70B3D568F* OUI:70B3D55AB* ID_OUI_FROM_DATABASE=Sea Air and Land Communications Ltd -OUI:70B3D5CD2* - ID_OUI_FROM_DATABASE=HBH Microwave GmbH +OUI:70B3D5CED* + ID_OUI_FROM_DATABASE=Advanced Products Corporation Pte Ltd -OUI:70B3D5B23* - ID_OUI_FROM_DATABASE=Supervision Test et Pilotage +OUI:70B3D5DB0* + ID_OUI_FROM_DATABASE=Arnouse Digital Devices Corp -OUI:70B3D5178* - ID_OUI_FROM_DATABASE=Gamber Johnson-LLC +OUI:70B3D5CCD* + ID_OUI_FROM_DATABASE=Suzhou PowerCore Technology Co.,Ltd. -OUI:70B3D57B6* - ID_OUI_FROM_DATABASE=Amada Miyachi America Inc. +OUI:70B3D5163* + ID_OUI_FROM_DATABASE=BHARAT HEAVY ELECTRICALS LIMITED -OUI:70B3D555A* - ID_OUI_FROM_DATABASE=Sontay Ltd. +OUI:70B3D5227* + ID_OUI_FROM_DATABASE=Montalvo -OUI:70B3D5CB2* - ID_OUI_FROM_DATABASE=SECLAB +OUI:70B3D5910* + ID_OUI_FROM_DATABASE=Eginity, Inc. -OUI:70B3D511C* - ID_OUI_FROM_DATABASE=Samriddi Automations Pvt. Ltd. +OUI:70B3D57D1* + ID_OUI_FROM_DATABASE=Schneider Electric Motion USA -OUI:70B3D5AE5* - ID_OUI_FROM_DATABASE=BeatCraft, Inc. +OUI:70B3D570F* + ID_OUI_FROM_DATABASE=Alion Science & Technology -OUI:70B3D5A91* - ID_OUI_FROM_DATABASE=IDEAL INDUSTRIES Ltd t/a Casella +OUI:70B3D5A1B* + ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC -OUI:70B3D51DD* - ID_OUI_FROM_DATABASE=RF CREATIONS LTD +OUI:70B3D5947* + ID_OUI_FROM_DATABASE=Checkbill Co,Ltd. -OUI:70B3D50AE* - ID_OUI_FROM_DATABASE=Norsat International Inc. +OUI:70B3D5B77* + ID_OUI_FROM_DATABASE=Motec Pty Ltd -OUI:70B3D51DA* - ID_OUI_FROM_DATABASE=Promess Inc. +OUI:70B3D5D9D* + ID_OUI_FROM_DATABASE=Electroimpact, Inc. -OUI:70B3D555B* - ID_OUI_FROM_DATABASE=Procon Electronics Pty Ltd +OUI:70B3D5C6F* + ID_OUI_FROM_DATABASE=nyantec UG (haftungsbeschränkt) -OUI:70B3D5461* - ID_OUI_FROM_DATABASE=TESEC Corporation +OUI:70B3D5475* + ID_OUI_FROM_DATABASE=EWATTCH -OUI:70B3D57FB* - ID_OUI_FROM_DATABASE=db Broadcast Products Ltd +OUI:70B3D5F30* + ID_OUI_FROM_DATABASE=ADE Technology Inc. -OUI:70B3D5CED* - ID_OUI_FROM_DATABASE=Advanced Products Corporation Pte Ltd +OUI:70B3D5F95* + ID_OUI_FROM_DATABASE=Get SAT -OUI:70B3D5DB0* - ID_OUI_FROM_DATABASE=Arnouse Digital Devices Corp +OUI:70B3D5457* + ID_OUI_FROM_DATABASE=Vivaldi Clima Srl -OUI:70B3D5CCD* - ID_OUI_FROM_DATABASE=Suzhou PowerCore Technology Co.,Ltd. +OUI:70B3D5CD5* + ID_OUI_FROM_DATABASE=Apantac LLC -OUI:70B3D5163* - ID_OUI_FROM_DATABASE=BHARAT HEAVY ELECTRICALS LIMITED +OUI:70B3D511F* + ID_OUI_FROM_DATABASE=Geppetto Electronics + +OUI:70B3D5136* + ID_OUI_FROM_DATABASE=Miguel Corporate Services Pte Ltd + +OUI:70B3D5E1A* + ID_OUI_FROM_DATABASE=BIZERBA LUCEO + +OUI:70B3D55D5* + ID_OUI_FROM_DATABASE=CT Company + +OUI:70B3D5A1F* + ID_OUI_FROM_DATABASE=GlobalTest LLC + +OUI:70B3D58CA* + ID_OUI_FROM_DATABASE=Allied Data Systems + +OUI:70B3D5785* + ID_OUI_FROM_DATABASE=Density Inc. + +OUI:70B3D56B1* + ID_OUI_FROM_DATABASE=TTC TELEKOMUNIKACE, s.r.o. + +OUI:70B3D5BD5* + ID_OUI_FROM_DATABASE=Synics AG + +OUI:70B3D55C1* + ID_OUI_FROM_DATABASE=Shanghai JaWay Information Technology Co., Ltd. + +OUI:70B3D5BE9* + ID_OUI_FROM_DATABASE=Telecast Inc. + +OUI:70B3D5C62* + ID_OUI_FROM_DATABASE=WIZNOVA + +OUI:70B3D5D3B* + ID_OUI_FROM_DATABASE=NimbeLink Corp + +OUI:70B3D5FF4* + ID_OUI_FROM_DATABASE=Serveron Corporation + +OUI:70B3D5760* + ID_OUI_FROM_DATABASE=QUALITTEQ LLC OUI:1C8776D* ID_OUI_FROM_DATABASE=Qivivo @@ -5027,9 +5636,6 @@ OUI:BC34007* OUI:B01F81D* ID_OUI_FROM_DATABASE=TAIWAN Anjie Electronics Co.,Ltd. -OUI:7419F87* - ID_OUI_FROM_DATABASE=Broadanet S.T.M - OUI:A43BFA7* ID_OUI_FROM_DATABASE=Deatronic srl @@ -5204,9 +5810,6 @@ OUI:D07650F* OUI:E81863F* ID_OUI_FROM_DATABASE=Private -OUI:3C39E7F* - ID_OUI_FROM_DATABASE=Private - OUI:F80278F* ID_OUI_FROM_DATABASE=Private @@ -5300,9 +5903,117 @@ OUI:4CE1737* OUI:4CE1739* ID_OUI_FROM_DATABASE=Shenzhen Evolution Dynamics Co., Ltd. +OUI:1CC0E11* + ID_OUI_FROM_DATABASE=Hangzhou Kaierda Electric Welding Machine Co.,Ltd + +OUI:1CC0E15* + ID_OUI_FROM_DATABASE=Kids Wireless Inc + OUI:1CC0E13* ID_OUI_FROM_DATABASE=HANGZHOU SOFTEL OPTIC CO., LTD +OUI:1CC0E1E* + ID_OUI_FROM_DATABASE=Yun Yang Fire Safety Equipment Co.,Ltd. + +OUI:1CC0E1A* + ID_OUI_FROM_DATABASE=SECHERON SA + +OUI:1CC0E17* + ID_OUI_FROM_DATABASE=SHENZHEN KINSTONE D&T DEVELOP CO.,LTD + +OUI:4865EE0* + ID_OUI_FROM_DATABASE=DefPower Ltd + +OUI:4865EEC* + ID_OUI_FROM_DATABASE=DNV GL + +OUI:3C39E7F* + ID_OUI_FROM_DATABASE=Private + +OUI:4865EE4* + ID_OUI_FROM_DATABASE=Mission Microwave Technologies, Inc + +OUI:244E7B2* + ID_OUI_FROM_DATABASE=RCC TIME CO .,LIMITED + +OUI:244E7B1* + ID_OUI_FROM_DATABASE=sonoscape + +OUI:244E7B7* + ID_OUI_FROM_DATABASE=Nanjing Wanlida Technology Co., Ltd. + +OUI:244E7B3* + ID_OUI_FROM_DATABASE=Shenzhen Ruixunyun Technology Co.,Ltd. + +OUI:244E7BB* + ID_OUI_FROM_DATABASE=Mighty Audio, Inc. + +OUI:7CCBE28* + ID_OUI_FROM_DATABASE=Polarteknik Oy + +OUI:7CCBE24* + ID_OUI_FROM_DATABASE=Ningbo bird sales co.,LTD + +OUI:7CCBE2D* + ID_OUI_FROM_DATABASE=optilink networks pvt ltd + +OUI:7419F87* + ID_OUI_FROM_DATABASE=Heptagon Systems PTY. LTD. + +OUI:500B91B* + ID_OUI_FROM_DATABASE=thumbzup UK Limited + +OUI:500B91C* + ID_OUI_FROM_DATABASE=Diamond Traffic Products, Inc + +OUI:500B915* + ID_OUI_FROM_DATABASE=jiangsu zhongling high-tech CO.,LTD. + +OUI:500B914* + ID_OUI_FROM_DATABASE=Sinope technologies Inc + +OUI:1CC0E14* + ID_OUI_FROM_DATABASE=Videri Inc. + +OUI:A4580F3* + ID_OUI_FROM_DATABASE=Engineered SA + +OUI:A4580FD* + ID_OUI_FROM_DATABASE=EYE IO, LLC + +OUI:40ED981* + ID_OUI_FROM_DATABASE=GuangZhou FiiO Electronics Technology Co.,Ltd + +OUI:40ED985* + ID_OUI_FROM_DATABASE=Cape + +OUI:34049E3* + ID_OUI_FROM_DATABASE=Nanjing Mythware Information Technology Co., Ltd. + +OUI:34049EA* + ID_OUI_FROM_DATABASE=i3 International Inc. + +OUI:50A4D06* + ID_OUI_FROM_DATABASE=PointGrab + +OUI:34049EE* + ID_OUI_FROM_DATABASE=ND SatCom GmbH + +OUI:50A4D05* + ID_OUI_FROM_DATABASE=TREXOM S.r.l. + +OUI:50A4D01* + ID_OUI_FROM_DATABASE=Beijing ANTVR Technology Co., LTD + +OUI:50A4D0A* + ID_OUI_FROM_DATABASE=Changsha SinoCare, Inc + +OUI:8CC8F4C* + ID_OUI_FROM_DATABASE=Shenzhen KSTAR Science and Technology Co., Ltd + +OUI:40F385D* + ID_OUI_FROM_DATABASE=Digital Bros S.p.A. + OUI:1C8776C* ID_OUI_FROM_DATABASE=Strone Technology @@ -5852,6 +6563,78 @@ OUI:8C192D3* OUI:8C192D1* ID_OUI_FROM_DATABASE=Shenzhen Huanuo Internet Technology Co.,Ltd +OUI:F0ACD72* + ID_OUI_FROM_DATABASE=QUANTUM POWER SYSTEMS + +OUI:F0ACD71* + ID_OUI_FROM_DATABASE=Intenta GmbH + +OUI:58E8769* + ID_OUI_FROM_DATABASE=TEM Mobile Limited + +OUI:58E8765* + ID_OUI_FROM_DATABASE=Broad Air Technology Co., LTD. + +OUI:C0D3913* + ID_OUI_FROM_DATABASE=IXON B.V. + +OUI:C0D3916* + ID_OUI_FROM_DATABASE=Ernitec + +OUI:C0D3912* + ID_OUI_FROM_DATABASE=Hofon Automation Co.,Ltd + +OUI:C0D391B* + ID_OUI_FROM_DATABASE=Private + +OUI:84E0F40* + ID_OUI_FROM_DATABASE=ShenZhen Panrich Technology Limited + +OUI:70F8E79* + ID_OUI_FROM_DATABASE=Kontech Electronics Co., Ltd + +OUI:70F8E70* + ID_OUI_FROM_DATABASE=SHENZHEN Xin JiuNing Electronics Co Ltd + +OUI:70F8E74* + ID_OUI_FROM_DATABASE=CLIP Inc. + +OUI:4CE173D* + ID_OUI_FROM_DATABASE=KTC(K-TEL) + +OUI:4865EE3* + ID_OUI_FROM_DATABASE=Data Technology Inc. + +OUI:4865EE1* + ID_OUI_FROM_DATABASE=Gopod Group Limited + +OUI:7CCBE26* + ID_OUI_FROM_DATABASE=SY Electronics Limited + +OUI:7CCBE2B* + ID_OUI_FROM_DATABASE=Easy Broadband Technology Co., Ltd. + +OUI:500B917* + ID_OUI_FROM_DATABASE=Shenzhen Xinfa Electronic Co.,ltd + +OUI:500B919* + ID_OUI_FROM_DATABASE=Machfu, Inc. + +OUI:500B913* + ID_OUI_FROM_DATABASE=EWIN TECHNOLOGY LIMITED + +OUI:A4580F5* + ID_OUI_FROM_DATABASE=CoAsia Microelectronics Corp. + +OUI:A4580FA* + ID_OUI_FROM_DATABASE=GUANGZHOU OPTICAL BRIDGE COMMUNICATION EQUIPMENT CO.,LTD. + +OUI:A4580FE* + ID_OUI_FROM_DATABASE=Finetree Communications Inc + +OUI:40ED980* + ID_OUI_FROM_DATABASE=Tsinghua Tongfang Co., LTD + OUI:D02212F* ID_OUI_FROM_DATABASE=Private @@ -5897,15 +6680,6 @@ OUI:84E0F49* OUI:84E0F4A* ID_OUI_FROM_DATABASE=iSolution Technologies Co.,Ltd. -OUI:70F8E74* - ID_OUI_FROM_DATABASE=CLIP Inc. - -OUI:70F8E70* - ID_OUI_FROM_DATABASE=SHENZHEN Xin JiuNing Electronics Co Ltd - -OUI:70F8E79* - ID_OUI_FROM_DATABASE=Kontech Electronics Co., Ltd - OUI:F81D78C* ID_OUI_FROM_DATABASE=SHENZHUOYUE TECHNOLOGY.,LTD @@ -5936,56 +6710,80 @@ OUI:383A21E* OUI:AC64DD4* ID_OUI_FROM_DATABASE=8Cups +OUI:AC64DD5* + ID_OUI_FROM_DATABASE=SHANGHAI ZTE TECHNOLOGIES CO.,LTD + +OUI:AC64DD8* + ID_OUI_FROM_DATABASE=PFDC ELANCYL + OUI:AC64DDC* ID_OUI_FROM_DATABASE=Beijing Hamigua Technology Co., Ltd. +OUI:AC64DDE* + ID_OUI_FROM_DATABASE=DIGIBIRD TECHNOLOGY CO., LTD. + OUI:4CE1730* ID_OUI_FROM_DATABASE=Beijing Sutongwang E-Business Co., Ltd -OUI:F0ACD72* - ID_OUI_FROM_DATABASE=QUANTUM POWER SYSTEMS +OUI:4CE173E* + ID_OUI_FROM_DATABASE=Plus One Japan Limited -OUI:F0ACD71* - ID_OUI_FROM_DATABASE=Intenta GmbH +OUI:1CC0E12* + ID_OUI_FROM_DATABASE=Abbott Medical Optics Inc. -OUI:58E8769* - ID_OUI_FROM_DATABASE=TEM Mobile Limited +OUI:4CE1736* + ID_OUI_FROM_DATABASE=DAIKOKU DENKI CO.,LTD. -OUI:58E8765* - ID_OUI_FROM_DATABASE=Broad Air Technology Co., LTD. +OUI:4865EE6* + ID_OUI_FROM_DATABASE=shenzhen sunflower technologies CO., LIMITED -OUI:C0D3913* - ID_OUI_FROM_DATABASE=IXON B.V. +OUI:4865EE9* + ID_OUI_FROM_DATABASE=VideoStitch, Inc -OUI:C0D3916* - ID_OUI_FROM_DATABASE=Ernitec +OUI:244E7B9* + ID_OUI_FROM_DATABASE=UniMAT Automation Technology Co., Ltd. -OUI:C0D3912* - ID_OUI_FROM_DATABASE=Hofon Automation Co.,Ltd +OUI:4865EE5* + ID_OUI_FROM_DATABASE=Swistec Systems AG -OUI:C0D391B* - ID_OUI_FROM_DATABASE=Private +OUI:244E7BA* + ID_OUI_FROM_DATABASE=Shenzhen AWT science & technology limited -OUI:84E0F40* - ID_OUI_FROM_DATABASE=ShenZhen Panrich Technology Limited +OUI:500B911* + ID_OUI_FROM_DATABASE=SPD Development Company Ltd -OUI:AC64DD5* - ID_OUI_FROM_DATABASE=SHANGHAI ZTE TECHNOLOGIES CO.,LTD +OUI:A4580F0* + ID_OUI_FROM_DATABASE=INNOPRO -OUI:AC64DD8* - ID_OUI_FROM_DATABASE=PFDC ELANCYL +OUI:A4580F4* + ID_OUI_FROM_DATABASE=Shenzhen City billion Leiden science and Technology Co., Ltd. -OUI:AC64DDE* - ID_OUI_FROM_DATABASE=DIGIBIRD TECHNOLOGY CO., LTD. +OUI:40ED98B* + ID_OUI_FROM_DATABASE=Siebert Industrieelektronik GmbH -OUI:4CE1736* - ID_OUI_FROM_DATABASE=CHINA CNR CORPORATION LIMITED DALIAN ELECTRIC TRACTION R&D CENTER +OUI:40ED98A* + ID_OUI_FROM_DATABASE=Integrated Design Ltd -OUI:4CE173D* - ID_OUI_FROM_DATABASE=KTC(K-TEL) +OUI:34049ED* + ID_OUI_FROM_DATABASE=uikismart -OUI:4CE173E* - ID_OUI_FROM_DATABASE=Plus One Japan Limited +OUI:50A4D03* + ID_OUI_FROM_DATABASE=Guangzhou Hysoon Electronic Co., Ltd. + +OUI:50A4D07* + ID_OUI_FROM_DATABASE=Shanghai Pujiang Smart Card Systems Co., Ltd. + +OUI:8CC8F49* + ID_OUI_FROM_DATABASE=Swift Navigation Inc + +OUI:8CC8F41* + ID_OUI_FROM_DATABASE=Lanhomex Technology(Shen Zhen)Co.,Ltd. + +OUI:8CC8F4A* + ID_OUI_FROM_DATABASE=Trilux Group Management GmbH + +OUI:40F3856* + ID_OUI_FROM_DATABASE=Lennox International Incorporated OUI:1C87765* ID_OUI_FROM_DATABASE=Zhuhai MYZR Technology Co.,Ltd @@ -6716,6 +7514,72 @@ OUI:4CE1733* OUI:4CE173C* ID_OUI_FROM_DATABASE=REMONDE NETWORK +OUI:1CC0E1B* + ID_OUI_FROM_DATABASE=Exigent Sensors + +OUI:1CC0E10* + ID_OUI_FROM_DATABASE=Shenzhen Highsharp Electronics Ltd. + +OUI:4865EE7* + ID_OUI_FROM_DATABASE=Venture Research Inc. + +OUI:4865EEB* + ID_OUI_FROM_DATABASE=EnBW Energie Baden-Württemberg AG + +OUI:244E7B0* + ID_OUI_FROM_DATABASE=Tekelek Europe Ltd + +OUI:500B912* + ID_OUI_FROM_DATABASE=annapurnalabs + +OUI:500B91A* + ID_OUI_FROM_DATABASE=New Audio LLC + +OUI:A4580F7* + ID_OUI_FROM_DATABASE=Changsha Tai Hui Network Technology Co.,Ltd + +OUI:A4580FB* + ID_OUI_FROM_DATABASE=ABB AB PGHV + +OUI:A4580F1* + ID_OUI_FROM_DATABASE=Stone Lock Global, Inc. + +OUI:40ED983* + ID_OUI_FROM_DATABASE=Knox Company + +OUI:40ED989* + ID_OUI_FROM_DATABASE=TeraTron GmbH + +OUI:40ED982* + ID_OUI_FROM_DATABASE=A-IOX INC. + +OUI:34049E4* + ID_OUI_FROM_DATABASE=Harbin Yantuo Science and Technology Development Co., Ltd + +OUI:34049E0* + ID_OUI_FROM_DATABASE=GoChip Inc. + +OUI:34049E2* + ID_OUI_FROM_DATABASE=EFD Induction + +OUI:34049E9* + ID_OUI_FROM_DATABASE=Private + +OUI:50A4D08* + ID_OUI_FROM_DATABASE=XinLian'AnBao(Beijing)Technology Co.,LTD. + +OUI:8CC8F40* + ID_OUI_FROM_DATABASE=Guardtec,Inc + +OUI:8CC8F46* + ID_OUI_FROM_DATABASE=SHENZHEN D-light Technolgy Limited + +OUI:8CC8F48* + ID_OUI_FROM_DATABASE=Strongbyte Solutions Limited + +OUI:8CC8F4E* + ID_OUI_FROM_DATABASE=Evaporcool Solutions + OUI:1C8776B* ID_OUI_FROM_DATABASE=Hekatron Vertriebs GmbH @@ -7322,6 +8186,93 @@ OUI:7C477CA* OUI:1C87760* ID_OUI_FROM_DATABASE=Dspread Technology (Beijing) Inc. +OUI:F0ACD70* + ID_OUI_FROM_DATABASE=Guilin glsun Science and Tech Co.,LTD + +OUI:F0ACD7E* + ID_OUI_FROM_DATABASE=Fiziico Co., Ltd. + +OUI:58E8760* + ID_OUI_FROM_DATABASE=Private + +OUI:58E8761* + ID_OUI_FROM_DATABASE=Beijing Perabytes IS Technology Co., Ltd + +OUI:C0D3914* + ID_OUI_FROM_DATABASE=Vernier Software & Technology + +OUI:C0D3919* + ID_OUI_FROM_DATABASE=xxter bv + +OUI:C0D391E* + ID_OUI_FROM_DATABASE=SAMSARA NETWORKS INC + +OUI:84E0F4D* + ID_OUI_FROM_DATABASE=Logos01 Srl + +OUI:70F8E7E* + ID_OUI_FROM_DATABASE=CUAV + +OUI:70F8E73* + ID_OUI_FROM_DATABASE=Dr. Simon Consulting GmbH + +OUI:F81D783* + ID_OUI_FROM_DATABASE=SHANGHAI SUN TELECOMMUNICATION CO., LTD. + +OUI:383A210* + ID_OUI_FROM_DATABASE=R3C Information(Shenzhen) Co.,Ltd. + +OUI:383A213* + ID_OUI_FROM_DATABASE=Shanghai Greatwall Safety System Co.,Ltd + +OUI:AC64DD7* + ID_OUI_FROM_DATABASE=Wittmann Kunststoffgeräte GmbH + +OUI:4CE1734* + ID_OUI_FROM_DATABASE=Huizhou Dehong Technology Co., Ltd. + +OUI:4CE173A* + ID_OUI_FROM_DATABASE=jvi + +OUI:1CC0E19* + ID_OUI_FROM_DATABASE=Ospicon Company Limited + +OUI:4865EE2* + ID_OUI_FROM_DATABASE=CaptionCall + +OUI:4865EEE* + ID_OUI_FROM_DATABASE=CNU + +OUI:4865EED* + ID_OUI_FROM_DATABASE=Winn Technology Co.,Ltd + +OUI:244E7BC* + ID_OUI_FROM_DATABASE=CHUNGHSIN TECHNOLOGY GROUP CO.,LTD + +OUI:7CCBE29* + ID_OUI_FROM_DATABASE=Hangzhou Haohaokaiche Technology Co.,Ltd. + +OUI:7CCBE2C* + ID_OUI_FROM_DATABASE=mirakonta s.l. + +OUI:7CCBE23* + ID_OUI_FROM_DATABASE=Astrum Technologies CC + +OUI:244E7BD* + ID_OUI_FROM_DATABASE=Private + +OUI:500B91D* + ID_OUI_FROM_DATABASE=Shenzhen Lucky Sonics Co .,Ltd + +OUI:7CCBE2E* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:A4580F2* + ID_OUI_FROM_DATABASE=BLOKS. GmbH + +OUI:40ED986* + ID_OUI_FROM_DATABASE=Shanghai Broadwan Communications Co.,Ltd + OUI:8C192D5* ID_OUI_FROM_DATABASE=ELCO(TIANJIN)ELECTRONICS CO.,LTD. @@ -7382,74 +8333,92 @@ OUI:84E0F43* OUI:1C88798* ID_OUI_FROM_DATABASE=Toshiba Toko Meter Systems Co., LTD. -OUI:383A210* - ID_OUI_FROM_DATABASE=R3C Information(Shenzhen) Co.,Ltd. +OUI:70F8E7C* + ID_OUI_FROM_DATABASE=Fixstars Corporation -OUI:4CE1734* - ID_OUI_FROM_DATABASE=Huizhou Dehong Technology Co., Ltd. +OUI:F81D78D* + ID_OUI_FROM_DATABASE=Tofino -OUI:4CE173A* - ID_OUI_FROM_DATABASE=jvi +OUI:F81D787* + ID_OUI_FROM_DATABASE=WUHAN GUIDE INFRARED CO.,LTD -OUI:F0ACD70* - ID_OUI_FROM_DATABASE=Guilin glsun Science and Tech Co.,LTD +OUI:F81D789* + ID_OUI_FROM_DATABASE=Ophrys Systèmes -OUI:F0ACD7E* - ID_OUI_FROM_DATABASE=Fiziico Co., Ltd. +OUI:383A21D* + ID_OUI_FROM_DATABASE=Colooc AB -OUI:58E8760* - ID_OUI_FROM_DATABASE=Private +OUI:AC64DD9* + ID_OUI_FROM_DATABASE=Micro Connect Pty Ltd -OUI:58E8761* - ID_OUI_FROM_DATABASE=Beijing Perabytes IS Technology Co., Ltd +OUI:AC64DD3* + ID_OUI_FROM_DATABASE=infypower Co., Ltd -OUI:C0D3914* - ID_OUI_FROM_DATABASE=Vernier Software & Technology +OUI:4865EE8* + ID_OUI_FROM_DATABASE=SmartDisplayer Technology Co., Ltd. -OUI:C0D3919* - ID_OUI_FROM_DATABASE=xxter bv +OUI:244E7B4* + ID_OUI_FROM_DATABASE=Leshi Internet Information & Technology (Beijing) Corp. -OUI:C0D391E* - ID_OUI_FROM_DATABASE=SAMSARA NETWORKS INC +OUI:244E7B6* + ID_OUI_FROM_DATABASE=Owasys Advanced Wireless Devices -OUI:84E0F4D* - ID_OUI_FROM_DATABASE=Logos01 Srl +OUI:244E7BE* + ID_OUI_FROM_DATABASE=WithWin Technology ShenZhen CO.,LTD -OUI:70F8E7E* - ID_OUI_FROM_DATABASE=CUAV +OUI:244E7B5* + ID_OUI_FROM_DATABASE=Jiangsu Xuanbo Electronic Technologies Co.,Ltd -OUI:70F8E73* - ID_OUI_FROM_DATABASE=Dr. Simon Consulting GmbH +OUI:7CCBE25* + ID_OUI_FROM_DATABASE=DTECH Labs, Inc. -OUI:70F8E7C* - ID_OUI_FROM_DATABASE=Fixstars Corporation +OUI:7CCBE27* + ID_OUI_FROM_DATABASE=Hangzhou Kaicom Communication Co.,Ltd -OUI:F81D783* - ID_OUI_FROM_DATABASE=SHANGHAI SUN TELECOMMUNICATION CO., LTD. +OUI:A4580F8* + ID_OUI_FROM_DATABASE=AIR LIQUIDE MEDICAL SYSTEMS -OUI:F81D78D* - ID_OUI_FROM_DATABASE=Tofino +OUI:40ED98C* + ID_OUI_FROM_DATABASE=BloomSky,Inc. -OUI:F81D787* - ID_OUI_FROM_DATABASE=WUHAN GUIDE INFRARED CO.,LTD +OUI:40ED98E* + ID_OUI_FROM_DATABASE=BORDA TECHNOLOGY -OUI:F81D789* - ID_OUI_FROM_DATABASE=Ophrys Systèmes +OUI:34049E6* + ID_OUI_FROM_DATABASE=Life Interface Co., Ltd. -OUI:383A21D* - ID_OUI_FROM_DATABASE=Colooc AB +OUI:34049E1* + ID_OUI_FROM_DATABASE=Connected IO Inc. -OUI:383A213* - ID_OUI_FROM_DATABASE=Shanghai Greatwall Safety System Co.,Ltd +OUI:34049EB* + ID_OUI_FROM_DATABASE=Eginity, Inc. -OUI:AC64DD7* - ID_OUI_FROM_DATABASE=Wittmann Kunststoffgeräte GmbH +OUI:34049E5* + ID_OUI_FROM_DATABASE=Seeiner Technology Co.,LTD -OUI:AC64DD9* - ID_OUI_FROM_DATABASE=Micro Connect Pty Ltd +OUI:34049EC* + ID_OUI_FROM_DATABASE=Private -OUI:AC64DD3* - ID_OUI_FROM_DATABASE=infypower Co., Ltd +OUI:50A4D09* + ID_OUI_FROM_DATABASE=OEM PRODUCTION INC. + +OUI:50A4D00* + ID_OUI_FROM_DATABASE=TRAXENS + +OUI:50A4D02* + ID_OUI_FROM_DATABASE=Seneco A/S + +OUI:8CC8F42* + ID_OUI_FROM_DATABASE=Dark Horse Connect LLC + +OUI:8CC8F4B* + ID_OUI_FROM_DATABASE=PTYPE Co., LTD. + +OUI:8CC8F45* + ID_OUI_FROM_DATABASE=Beijing KXWELL Technology CO., LTD + +OUI:8CC8F43* + ID_OUI_FROM_DATABASE=TOHO DENKI IND.CO.,LTD OUI:1C87740* ID_OUI_FROM_DATABASE=Philips Personal Health Solutions @@ -7763,9 +8732,6 @@ OUI:D022128* OUI:100723B* ID_OUI_FROM_DATABASE=Fujian Quanzhou Dong Ang Electronics Co., Ltd. -OUI:100723C* - ID_OUI_FROM_DATABASE=SHENZHEN XINFA ELECTRONIC CO.,LTD - OUI:1007235* ID_OUI_FROM_DATABASE=BEIJING SOOALL INFORMATION TECHNOLOGY CO.,LTD @@ -7946,6 +8912,78 @@ OUI:6891D0E* OUI:D0D94FC* ID_OUI_FROM_DATABASE=ARROWAVE TECHNOLOGIES LIMITED +OUI:F0ACD7A* + ID_OUI_FROM_DATABASE=Groupeer Technologies + +OUI:F0ACD74* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:58E876B* + ID_OUI_FROM_DATABASE=annapurnalabs + +OUI:58E876A* + ID_OUI_FROM_DATABASE=SHENZHEN DIGISSIN TECHNOLOGY + +OUI:58E8762* + ID_OUI_FROM_DATABASE=Coala Life AB + +OUI:C0D3917* + ID_OUI_FROM_DATABASE=ALNETz Co.,LTD + +OUI:C0D3918* + ID_OUI_FROM_DATABASE=XENA SECURITY LIMITED + +OUI:C0D391C* + ID_OUI_FROM_DATABASE=Zhinengguo technology company limited + +OUI:84E0F42* + ID_OUI_FROM_DATABASE=Hangzhou Uni-Ubi Co.,Ltd. + +OUI:84E0F46* + ID_OUI_FROM_DATABASE=Liaoning IK'SONYA Science and Technology Co., Ltd. + +OUI:383A216* + ID_OUI_FROM_DATABASE=Shenzhen Smart-core Technology co., Ltd. + +OUI:4CE1735* + ID_OUI_FROM_DATABASE=NewVastek + +OUI:AC64DD6* + ID_OUI_FROM_DATABASE=Kpnetworks Ltd. + +OUI:1CC0E18* + ID_OUI_FROM_DATABASE=LX Corporation Pty Ltd + +OUI:4865EEA* + ID_OUI_FROM_DATABASE=Shenzhen Inpor cloud Computing Co., Ltd. + +OUI:244E7B8* + ID_OUI_FROM_DATABASE=Cyber1st + +OUI:7CCBE2A* + ID_OUI_FROM_DATABASE=Shanghai Institute of Applied Physics, Chinese Academy of Sciences + +OUI:7CCBE21* + ID_OUI_FROM_DATABASE=CeoTronics AG + +OUI:A44F29F* + ID_OUI_FROM_DATABASE=Private + +OUI:A4580F9* + ID_OUI_FROM_DATABASE=Ksenia Security srl + +OUI:A4580FC* + ID_OUI_FROM_DATABASE=Homebeaver + +OUI:A4580F6* + ID_OUI_FROM_DATABASE=Astro, Inc + +OUI:40ED984* + ID_OUI_FROM_DATABASE=Kendrion Kuhnke Automation GmbH + +OUI:40ED987* + ID_OUI_FROM_DATABASE=Vaisala Oyj + OUI:2836387* ID_OUI_FROM_DATABASE=Innovative Technology Ltd @@ -7958,9 +8996,6 @@ OUI:B437D1F* OUI:0CEFAFF* ID_OUI_FROM_DATABASE=Private -OUI:A44F29F* - ID_OUI_FROM_DATABASE=Private - OUI:78C2C0F* ID_OUI_FROM_DATABASE=Private @@ -8018,44 +9053,74 @@ OUI:4CE1732* OUI:4CE1738* ID_OUI_FROM_DATABASE=Nanjing Tongke Technology Development Co., LTD -OUI:F0ACD7A* - ID_OUI_FROM_DATABASE=Groupeer Technologies +OUI:1CC0E1D* + ID_OUI_FROM_DATABASE=NewLand (NZ) Communication Tech Limited -OUI:F0ACD74* - ID_OUI_FROM_DATABASE=Sercomm Corporation. +OUI:1CC0E16* + ID_OUI_FROM_DATABASE=Monument Labs, Inc. -OUI:58E876B* - ID_OUI_FROM_DATABASE=annapurnalabs +OUI:1CC0E1C* + ID_OUI_FROM_DATABASE=Nitto Seiko -OUI:58E876A* - ID_OUI_FROM_DATABASE=SHENZHEN DIGISSIN TECHNOLOGY +OUI:100723C* + ID_OUI_FROM_DATABASE=Shenzhen Xinfa Electronic Co.,ltd -OUI:58E8762* - ID_OUI_FROM_DATABASE=Coala Life AB +OUI:7CCBE20* + ID_OUI_FROM_DATABASE=Heyuan Yongyida Technology Holdings Co.,Ltd. -OUI:C0D3917* - ID_OUI_FROM_DATABASE=ALNETz Co.,LTD +OUI:7CCBE22* + ID_OUI_FROM_DATABASE=1000eyes GmbH -OUI:C0D3918* - ID_OUI_FROM_DATABASE=XENA SECURITY LIMITED +OUI:500B918* + ID_OUI_FROM_DATABASE=Panasonic Enterprise Solutions Company -OUI:C0D391C* - ID_OUI_FROM_DATABASE=Zhinengguo technology company limited +OUI:500B910* + ID_OUI_FROM_DATABASE=Igor, Inc. -OUI:84E0F42* - ID_OUI_FROM_DATABASE=Hangzhou Uni-Ubi Co.,Ltd. +OUI:500B916* + ID_OUI_FROM_DATABASE=Security Alarms & Co. S.A. -OUI:84E0F46* - ID_OUI_FROM_DATABASE=Liaoning IK'SONYA Science and Technology Co., Ltd. +OUI:500B91E* + ID_OUI_FROM_DATABASE=Shenzhen zhong ju Fiber optical Co.Ltd -OUI:383A216* - ID_OUI_FROM_DATABASE=Shenzhen Smart-core Technology co., Ltd. +OUI:40ED98D* + ID_OUI_FROM_DATABASE=Hangzhou GANX Technology Co.,Ltd. -OUI:4CE1735* - ID_OUI_FROM_DATABASE=NewVastek +OUI:40ED988* + ID_OUI_FROM_DATABASE=GUANGZHOU AURIC INTELLIGENT TECHNOLOGY CO.,LTD. -OUI:AC64DD6* - ID_OUI_FROM_DATABASE=Kpnetworks Ltd. +OUI:34049E8* + ID_OUI_FROM_DATABASE=Eclipse Information Technologies + +OUI:34049E7* + ID_OUI_FROM_DATABASE=Pebble Technology + +OUI:50A4D04* + ID_OUI_FROM_DATABASE=Raven Industries Inc. + +OUI:50A4D0D* + ID_OUI_FROM_DATABASE=Axel Technology + +OUI:50A4D0C* + ID_OUI_FROM_DATABASE=Beijing YangLian Networks Technology co., LTD + +OUI:50A4D0E* + ID_OUI_FROM_DATABASE=Sagetech Corporation + +OUI:50A4D0B* + ID_OUI_FROM_DATABASE=ZHENG DIAN ELECTRONICS LIMITED + +OUI:8CC8F4D* + ID_OUI_FROM_DATABASE=Beijing Xinxunxintong Eletronics Co.,Ltd + +OUI:8CC8F47* + ID_OUI_FROM_DATABASE=Private + +OUI:8CC8F44* + ID_OUI_FROM_DATABASE=ITECH Electronic Co.,ltd. + +OUI:40F3852* + ID_OUI_FROM_DATABASE=Beijing Zongheng Electro-Mechanical Technology Development Co. OUI:E043DB* ID_OUI_FROM_DATABASE=Shenzhen ViewAt Technology Co.,Ltd. @@ -8129,12 +9194,6 @@ OUI:BCEC23* OUI:8CE748* ID_OUI_FROM_DATABASE=Private -OUI:F09CE9* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. - -OUI:C413E2* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. - OUI:AC06C7* ID_OUI_FROM_DATABASE=ServerNet S.r.l. @@ -8513,24 +9572,6 @@ OUI:283152* OUI:DCD2FC* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:F8A45F* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:8CBEBE* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:640980* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:98FAE3* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:185936* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:9C99A0* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - OUI:0003DD* ID_OUI_FROM_DATABASE=Comark Interactive Solutions @@ -9278,9 +10319,6 @@ OUI:E8162B* OUI:709F2D* ID_OUI_FROM_DATABASE=zte corporation -OUI:5C6B4F* - ID_OUI_FROM_DATABASE=Private - OUI:ECE2FD* ID_OUI_FROM_DATABASE=SKG Electric Group(Thailand) Co., Ltd. @@ -9557,9 +10595,6 @@ OUI:BC9CC5* OUI:505065* ID_OUI_FROM_DATABASE=TAKT Corporation -OUI:D00AAB* - ID_OUI_FROM_DATABASE=Yokogawa Digital Computer Corporation - OUI:A4A4D3* ID_OUI_FROM_DATABASE=Bluebank Communication Technology Co.Ltd @@ -9656,9 +10691,6 @@ OUI:FC4AE9* OUI:34E42A* ID_OUI_FROM_DATABASE=Automatic Bar Controls Inc. -OUI:B87CF2* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. - OUI:20A787* ID_OUI_FROM_DATABASE=Bointec Taiwan Corporation Limited @@ -9854,9 +10886,6 @@ OUI:80BAE6* OUI:3C18A0* ID_OUI_FROM_DATABASE=Luxshare Precision Industry Co.,Ltd. -OUI:4CB81C* - ID_OUI_FROM_DATABASE=SAM Electronics GmbH - OUI:041A04* ID_OUI_FROM_DATABASE=WaveIP @@ -11015,9 +12044,6 @@ OUI:D01AA7* OUI:B08E1A* ID_OUI_FROM_DATABASE=URadio Systems Co., Ltd -OUI:40605A* - ID_OUI_FROM_DATABASE=Hawkeye Tech Co. Ltd - OUI:E05DA6* ID_OUI_FROM_DATABASE=Detlef Fink Elektronik & Softwareentwicklung @@ -11036,9 +12062,6 @@ OUI:608C2B* OUI:EC1120* ID_OUI_FROM_DATABASE=FloDesign Wind Turbine Corporation -OUI:D0F73B* - ID_OUI_FROM_DATABASE=Helmut Mauell GmbH - OUI:C495A2* ID_OUI_FROM_DATABASE=SHENZHEN WEIJIU INDUSTRY AND TRADE DEVELOPMENT CO., LTD @@ -11297,9 +12320,6 @@ OUI:8C8A6E* OUI:E0ED1A* ID_OUI_FROM_DATABASE=vastriver Technology Co., Ltd -OUI:C83B45* - ID_OUI_FROM_DATABASE=JRI-Maxant - OUI:685E6B* ID_OUI_FROM_DATABASE=PowerRay Co., Ltd. @@ -11384,9 +12404,6 @@ OUI:C436DA* OUI:00FC70* ID_OUI_FROM_DATABASE=Intrepid Control Systems, Inc. -OUI:A4EE57* - ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION - OUI:D0AFB6* ID_OUI_FROM_DATABASE=Linktop Technology Co., LTD @@ -11801,15 +12818,9 @@ OUI:60893C* OUI:5C17D3* ID_OUI_FROM_DATABASE=LGE -OUI:347877* - ID_OUI_FROM_DATABASE=O-NET Communications(Shenzhen) Limited - OUI:70A191* ID_OUI_FROM_DATABASE=Trendsetter Medical, LLC -OUI:A49B13* - ID_OUI_FROM_DATABASE=Burroughs Payment Systems, Inc. - OUI:58BC27* ID_OUI_FROM_DATABASE=Cisco Systems, Inc @@ -12137,9 +13148,6 @@ OUI:448E81* OUI:2046F9* ID_OUI_FROM_DATABASE=Advanced Network Devices (dba:AND) -OUI:681FD8* - ID_OUI_FROM_DATABASE=Advanced Telemetry - OUI:0C8230* ID_OUI_FROM_DATABASE=SHENZHEN MAGNUS TECHNOLOGIES CO.,LTD @@ -15512,9 +16520,6 @@ OUI:000E5D* OUI:000E5E* ID_OUI_FROM_DATABASE=Raisecom Technology -OUI:000E58* - ID_OUI_FROM_DATABASE=Sonos, Inc. - OUI:000BE2* ID_OUI_FROM_DATABASE=Lumenera Corporation @@ -17234,9 +18239,6 @@ OUI:000189* OUI:00308B* ID_OUI_FROM_DATABASE=Brix Networks -OUI:00014F* - ID_OUI_FROM_DATABASE=ADTRAN INC - OUI:00015A* ID_OUI_FROM_DATABASE=Digital Video Broadcasting @@ -18104,9 +19106,6 @@ OUI:006010* OUI:006044* ID_OUI_FROM_DATABASE=LITTON/POLY-SCIENTIFIC -OUI:00609B* - ID_OUI_FROM_DATABASE=ASTRO-MED, INC. - OUI:0060BE* ID_OUI_FROM_DATABASE=WEBTRONICS @@ -19463,9 +20462,6 @@ OUI:806C1B* OUI:A470D6* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:3407FB* - ID_OUI_FROM_DATABASE=Ericsson AB - OUI:001B21* ID_OUI_FROM_DATABASE=Intel Corporate @@ -20426,15 +21422,6 @@ OUI:BC307D* OUI:5410EC* ID_OUI_FROM_DATABASE=Microchip Technology Inc. -OUI:00262D* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation - -OUI:5CFF35* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation - -OUI:000AE4* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation - OUI:309BAD* ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. @@ -20705,9 +21692,6 @@ OUI:001A8F* OUI:E89309* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00D0B2* - ID_OUI_FROM_DATABASE=19514 - OUI:001988* ID_OUI_FROM_DATABASE=Wi2Wi, Inc @@ -21233,9 +22217,6 @@ OUI:E0686D* OUI:A45385* ID_OUI_FROM_DATABASE=Weifang GoerTek Electronics Co., Ltd. -OUI:000678* - ID_OUI_FROM_DATABASE=D&M Holdings Inc. - OUI:98B039* ID_OUI_FROM_DATABASE=Nokia @@ -21428,6 +22409,300 @@ OUI:50584F* OUI:00A2EE* ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:98E476* + ID_OUI_FROM_DATABASE=Zentan + +OUI:18F76B* + ID_OUI_FROM_DATABASE=Zhejiang Winsight Technology CO.,LTD + +OUI:00609B* + ID_OUI_FROM_DATABASE=AstroNova, Inc + +OUI:B87CF2* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. + +OUI:C413E2* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. + +OUI:F09CE9* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. + +OUI:48D343* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:CCC5EF* + ID_OUI_FROM_DATABASE=Co-Comm Servicios Telecomunicaciones S.L. + +OUI:5C6B4F* + ID_OUI_FROM_DATABASE=Hello Inc. + +OUI:C09C04* + ID_OUI_FROM_DATABASE=Shaanxi GuoLian Digital TV Technology Co.,Ltd. + +OUI:D0F73B* + ID_OUI_FROM_DATABASE=Helmut Mauell GmbH Werk Weida + +OUI:D00AAB* + ID_OUI_FROM_DATABASE=Yokogawa Digital Computer Corporation + +OUI:AC233F* + ID_OUI_FROM_DATABASE=Shenzhen Minew Technologies Co., Ltd. + +OUI:000E58* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:2C598A* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:E0508B* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:2C6FC9* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:9C99A0* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:185936* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:98FAE3* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:640980* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:8CBEBE* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:F8A45F* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:508A0F* + ID_OUI_FROM_DATABASE=SHENZHEN FISE TECHNOLOGY HOLDING CO.,LTD. + +OUI:E4B005* + ID_OUI_FROM_DATABASE=Beijing IQIYI Science & Technology Co., Ltd. + +OUI:C83B45* + ID_OUI_FROM_DATABASE=JRI + +OUI:1CEEC9* + ID_OUI_FROM_DATABASE=Elo touch solutions + +OUI:4CB81C* + ID_OUI_FROM_DATABASE=SAM Electronics GmbH + +OUI:F83F51* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6C5C14* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:2CDCAD* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:704D7B* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:7CF95C* + ID_OUI_FROM_DATABASE=U.I. Lapp GmbH + +OUI:743A65* + ID_OUI_FROM_DATABASE=NEC Corporation + +OUI:C80CC8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0425C5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A4EE57* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:480033* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:14B31F* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:BC8385* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:A03D6F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:40605A* + ID_OUI_FROM_DATABASE=Hawkeye Tech Co. Ltd + +OUI:5419C8* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:C0210D* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:000678* + ID_OUI_FROM_DATABASE=D&M Holdings Inc. + +OUI:886B44* + ID_OUI_FROM_DATABASE=Sunnovo International Limited + +OUI:A408F5* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:54FA96* + ID_OUI_FROM_DATABASE=Nokia + +OUI:1840A4* + ID_OUI_FROM_DATABASE=Shenzhen Trylong Smart Science and Technology Co., Ltd. + +OUI:9C50EE* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:1077B0* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:F015B9* + ID_OUI_FROM_DATABASE=PlayFusion Limited + +OUI:70700D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E02202* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:24A7DC* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:2CD02D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3478D7* + ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co.,Ltd. + +OUI:1CEFCE* + ID_OUI_FROM_DATABASE=bebro electronic GmbH + +OUI:CCB8A8* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:5CFF35* + ID_OUI_FROM_DATABASE=Wistron Corporation + +OUI:78F29E* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:00D0B2* + ID_OUI_FROM_DATABASE=Xiotech Corporation + +OUI:000AE4* + ID_OUI_FROM_DATABASE=Wistron Corporation + +OUI:00262D* + ID_OUI_FROM_DATABASE=Wistron Corporation + +OUI:908674* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:F49651* + ID_OUI_FROM_DATABASE=NAKAYO Inc + +OUI:681FD8* + ID_OUI_FROM_DATABASE=Siemens Industry, Inc. + +OUI:C43018* + ID_OUI_FROM_DATABASE=MCS Logic Inc. + +OUI:FCB58A* + ID_OUI_FROM_DATABASE=Wapice Ltd. + +OUI:DCEFCA* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:E865D4* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:285261* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:286F7F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:089E08* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:00014F* + ID_OUI_FROM_DATABASE=Adtran Inc + +OUI:D8E0E1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:045D4B* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:A80CCA* + ID_OUI_FROM_DATABASE=Shenzhen Sundray Technologies Company Limited + +OUI:94652D* + ID_OUI_FROM_DATABASE=OnePlus Technology (Shenzhen) Co., Ltd + +OUI:F8A34F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:845A81* + ID_OUI_FROM_DATABASE=ffly4u + +OUI:347877* + ID_OUI_FROM_DATABASE=O-Net Communications (Shenzhen) Limited + +OUI:F483E1* + ID_OUI_FROM_DATABASE=Shanghai Clouder Semiconductor Co.,Ltd + +OUI:08CCA7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7868F7* + ID_OUI_FROM_DATABASE=YSTen Technology Co.,Ltd + +OUI:704F57* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:3407FB* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:6CB4A7* + ID_OUI_FROM_DATABASE=Landauer, Inc. + +OUI:1C398A* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:F8A5C5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A49B13* + ID_OUI_FROM_DATABASE=Digital Check + +OUI:542F8A* + ID_OUI_FROM_DATABASE=TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO + +OUI:6049C1* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:DCC64B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:043389* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A0A33B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:6854C1* + ID_OUI_FROM_DATABASE=ColorTokens, Inc. + +OUI:887873* + ID_OUI_FROM_DATABASE=Intel Corporate + OUI:0C6F9C* ID_OUI_FROM_DATABASE=Shaw Communications Inc. @@ -21524,9 +22799,6 @@ OUI:FC7516* OUI:7C18CD* ID_OUI_FROM_DATABASE=E-TRON Co.,Ltd. -OUI:C8665D* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. - OUI:3897D6* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited @@ -21539,12 +22811,6 @@ OUI:E498D6* OUI:606944* ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:001977* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. - -OUI:4018B1* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. - OUI:8896B6* ID_OUI_FROM_DATABASE=Global Fire Equipment S.A. @@ -21863,18 +23129,6 @@ OUI:B4475E* OUI:90FB5B* ID_OUI_FROM_DATABASE=Avaya Inc -OUI:14F65A* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:0C1DAF* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:28E31F* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:F0B429* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - OUI:00906F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc @@ -22313,9 +23567,6 @@ OUI:D8D1CB* OUI:4C8ECC* ID_OUI_FROM_DATABASE=SILKAN SA -OUI:3CEF8C* - ID_OUI_FROM_DATABASE=ZHEJIANG DAHUA TECHNOLOGY CO.,LTD. - OUI:98F428* ID_OUI_FROM_DATABASE=zte corporation @@ -22418,9 +23669,6 @@ OUI:68F956* OUI:58B633* ID_OUI_FROM_DATABASE=Ruckus Wireless -OUI:AC60B6* - ID_OUI_FROM_DATABASE=Ericsson AB - OUI:F4E926* ID_OUI_FROM_DATABASE=Tianjin Zanpu Technology Inc. @@ -22727,9 +23975,6 @@ OUI:7C7A53* OUI:4886E8* ID_OUI_FROM_DATABASE=Microsoft Corporation -OUI:78FC14* - ID_OUI_FROM_DATABASE=B Communications Pty Ltd - OUI:88E161* ID_OUI_FROM_DATABASE=Art Beijing Science and Technology Development Co., Ltd. @@ -22787,9 +24032,6 @@ OUI:908C09* OUI:1C7E51* ID_OUI_FROM_DATABASE=3bumen.com -OUI:60C798* - ID_OUI_FROM_DATABASE=Verifone, Inc. - OUI:380E7B* ID_OUI_FROM_DATABASE=V.P.S. Thai Co., Ltd @@ -23111,9 +24353,6 @@ OUI:64E892* OUI:086DF2* ID_OUI_FROM_DATABASE=Shenzhen MIMOWAVE Technology Co.,Ltd -OUI:64EB8C* - ID_OUI_FROM_DATABASE=Seiko Epson Corporation - OUI:48D0CF* ID_OUI_FROM_DATABASE=Universal Electronics, Inc. @@ -23153,15 +24392,9 @@ OUI:04DB8A* OUI:083F76* ID_OUI_FROM_DATABASE=Intellian Technologies, Inc. -OUI:0CC47A* - ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. - OUI:D0634D* ID_OUI_FROM_DATABASE=Meiko Maschinenbau GmbH & Co. KG -OUI:88C626* - ID_OUI_FROM_DATABASE=Logitech - Ultimate Ears - OUI:889CA6* ID_OUI_FROM_DATABASE=BTB Korea INC @@ -23393,9 +24626,6 @@ OUI:988E4A* OUI:1C4158* ID_OUI_FROM_DATABASE=Gemalto M2M GmbH -OUI:ACD657* - ID_OUI_FROM_DATABASE=Shaanxi Guolian Digital TV Technology Co., Ltd. - OUI:541B5D* ID_OUI_FROM_DATABASE=Techno-Innov @@ -23609,9 +24839,6 @@ OUI:0868D0* OUI:103DEA* ID_OUI_FROM_DATABASE=HFC Technology (Beijing) Ltd. Co. -OUI:E8E875* - ID_OUI_FROM_DATABASE=iS5 Communications Inc. - OUI:2C7B5A* ID_OUI_FROM_DATABASE=Milper Ltd @@ -24605,9 +25832,6 @@ OUI:E878A1* OUI:3057AC* ID_OUI_FROM_DATABASE=IRLAB LTD. -OUI:9002A9* - ID_OUI_FROM_DATABASE=ZHEJIANG DAHUA TECHNOLOGY CO.,LTD - OUI:28AF0A* ID_OUI_FROM_DATABASE=Sirius XM Radio Inc @@ -26042,9 +27266,6 @@ OUI:0026B5* OUI:0026AF* ID_OUI_FROM_DATABASE=Duelco A/S -OUI:0026AB* - ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION - OUI:0026A5* ID_OUI_FROM_DATABASE=MICROROBOT.CO.,LTD @@ -26189,9 +27410,6 @@ OUI:002451* OUI:00244C* ID_OUI_FROM_DATABASE=Solartron Metrology Ltd -OUI:002445* - ID_OUI_FROM_DATABASE=CommScope Canada Inc. - OUI:00243F* ID_OUI_FROM_DATABASE=Storwize, Inc. @@ -26387,9 +27605,6 @@ OUI:00235D* OUI:002356* ID_OUI_FROM_DATABASE=Packet Forensics LLC -OUI:00234A* - ID_OUI_FROM_DATABASE=Private - OUI:002313* ID_OUI_FROM_DATABASE=Qool Technologies Ltd. @@ -27866,9 +29081,6 @@ OUI:00160A* OUI:001603* ID_OUI_FROM_DATABASE=COOLKSKY Co., LTD -OUI:0015FC* - ID_OUI_FROM_DATABASE=Littelfuse Startco - OUI:0015F7* ID_OUI_FROM_DATABASE=Wintecronics Ltd. @@ -28412,9 +29624,6 @@ OUI:00118B* OUI:001196* ID_OUI_FROM_DATABASE=Actuality Systems, Inc. -OUI:00117E* - ID_OUI_FROM_DATABASE=Progeny, A division of Midmark Corp - OUI:001179* ID_OUI_FROM_DATABASE=Singular Technology Co. Ltd. @@ -28757,9 +29966,6 @@ OUI:000EE9* OUI:000EF0* ID_OUI_FROM_DATABASE=Festo AG & Co. KG -OUI:000F4F* - ID_OUI_FROM_DATABASE=Cadmus Technology Ltd - OUI:000F35* ID_OUI_FROM_DATABASE=Cisco Systems, Inc @@ -30170,9 +31376,6 @@ OUI:00042F* OUI:000429* ID_OUI_FROM_DATABASE=Pixord Corporation -OUI:000422* - ID_OUI_FROM_DATABASE=Gordon Kapes, Inc. - OUI:00041C* ID_OUI_FROM_DATABASE=ipDialog, Inc. @@ -30371,9 +31574,6 @@ OUI:000311* OUI:00030A* ID_OUI_FROM_DATABASE=Argus Technologies -OUI:000302* - ID_OUI_FROM_DATABASE=Charles Industries, Ltd. - OUI:000305* ID_OUI_FROM_DATABASE=MSC Vertriebs GmbH @@ -31712,9 +32912,6 @@ OUI:00E085* OUI:00E05A* ID_OUI_FROM_DATABASE=GALEA NETWORK SECURITY -OUI:00E022* - ID_OUI_FROM_DATABASE=Analog Devices Inc. - OUI:00E0E7* ID_OUI_FROM_DATABASE=RAYTHEON E-SYSTEMS, INC. @@ -32855,12 +34052,6 @@ OUI:E09861* OUI:F4F1E1* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:74C99A* - ID_OUI_FROM_DATABASE=Ericsson AB - -OUI:3C197D* - ID_OUI_FROM_DATABASE=Ericsson AB - OUI:60BEB5* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company @@ -33836,9 +35027,6 @@ OUI:FCF528* OUI:588BF3* ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation -OUI:EC43F6* - ID_OUI_FROM_DATABASE=5420 - OUI:D8B02E* ID_OUI_FROM_DATABASE=Guangzhou Zonerich Business Machine Co., LTD. @@ -33863,785 +35051,332 @@ OUI:C4BB4C* OUI:8C04FF* ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:104FA8* - ID_OUI_FROM_DATABASE=Sony Corporation +OUI:001972* + ID_OUI_FROM_DATABASE=Plexus (Xiamen) Co.,ltd. -OUI:6C25B9* - ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. +OUI:6488FF* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. -OUI:486B2C* - ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. +OUI:005979* + ID_OUI_FROM_DATABASE=Networked Energy Services -OUI:00001F* - ID_OUI_FROM_DATABASE=Telco Systems, Inc. +OUI:000997* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:0016D3* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation +OUI:000E62* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:001F16* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation +OUI:000EC0* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:BC307E* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation +OUI:000FCD* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:00C0AB* - ID_OUI_FROM_DATABASE=Telco Systems, Inc. +OUI:0004DC* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:0010CA* - ID_OUI_FROM_DATABASE=Telco Systems, Inc. +OUI:02E6D3* + ID_OUI_FROM_DATABASE=NIXDORF COMPUTER CORP. -OUI:0C2576* - ID_OUI_FROM_DATABASE=LONGCHEER TELECOMMUNICATION LIMITED +OUI:0016B9* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP -OUI:0007A6* - ID_OUI_FROM_DATABASE=Leviton Manufacturing Co., Inc. +OUI:0024A8* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP -OUI:208756* - ID_OUI_FROM_DATABASE=SIEMENS AG +OUI:CC3ADF* + ID_OUI_FROM_DATABASE=Private -OUI:B08900* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:141F78* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:640DCE* - ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +OUI:006F64* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00A085* - ID_OUI_FROM_DATABASE=Private +OUI:DC6672* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:ACDE48* - ID_OUI_FROM_DATABASE=Private +OUI:0025C3* + ID_OUI_FROM_DATABASE=21168 -OUI:6063F9* - ID_OUI_FROM_DATABASE=Ciholas, Inc. +OUI:001365* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:F0421C* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:001ECA* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:C0E42D* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:001D42* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:18D6C7* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:001CEB* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:B8BB23* - ID_OUI_FROM_DATABASE=Guangdong Nufront CSC Co., Ltd +OUI:002363* + ID_OUI_FROM_DATABASE=Zhuhai Raysharp Technology Co.,Ltd -OUI:EC26FB* - ID_OUI_FROM_DATABASE=TECC CO.,LTD. +OUI:D03742* + ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd -OUI:10683F* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) +OUI:001CFD* + ID_OUI_FROM_DATABASE=Universal Electronics, Inc. -OUI:A039F7* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) +OUI:080051* + ID_OUI_FROM_DATABASE=ExperData -OUI:64BC0C* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) +OUI:0080C7* + ID_OUI_FROM_DATABASE=XIRCOM -OUI:0090CC* - ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. +OUI:049FCA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:E09DB8* - ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. +OUI:C81FBE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:64899A* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) +OUI:203DB2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:58A2B5* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) +OUI:48D539* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:74A722* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) +OUI:10E68F* + ID_OUI_FROM_DATABASE=KWANGSUNG ELECTRONICS KOREA CO.,LTD. -OUI:001F6B* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) +OUI:1899F5* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. -OUI:903AE6* - ID_OUI_FROM_DATABASE=PARROT SA +OUI:E41D2D* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. -OUI:00E00F* - ID_OUI_FROM_DATABASE=Shanghai Baud Data Communication Co.,Ltd. +OUI:B80018* + ID_OUI_FROM_DATABASE=Htel -OUI:3C404F* - ID_OUI_FROM_DATABASE=GUANGDONG PISEN ELECTRONICS CO.,LTD +OUI:0081C4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00233E* - ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD +OUI:E8FD90* + ID_OUI_FROM_DATABASE=Turbostor -OUI:6CBEE9* - ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD +OUI:0017EA* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:0080F7* - ID_OUI_FROM_DATABASE=Zenith Electronics Corporation +OUI:0017E3* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:00C095* - ID_OUI_FROM_DATABASE=ZNYX Networks, Inc. +OUI:001834* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:60EB69* - ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. +OUI:00182F* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:C80AA9* - ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. +OUI:78DEE4* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:00238B* - ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. +OUI:B8FFFE* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:0007BA* - ID_OUI_FROM_DATABASE=UTStarcom Inc +OUI:E0D7BA* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:4439C4* - ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. +OUI:405FC2* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:70F395* - ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. +OUI:8030DC* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:001E37* - ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. +OUI:CC78AB* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:002713* - ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. +OUI:A4D578* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:002186* - ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. +OUI:544A16* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:8CFDF0* - ID_OUI_FROM_DATABASE=Qualcomm Inc. +OUI:D8DDFD* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:000031* - ID_OUI_FROM_DATABASE=QPSX COMMUNICATIONS, LTD. +OUI:20CD39* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:000E7B* - ID_OUI_FROM_DATABASE=Toshiba +OUI:987BF3* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:B86B23* - ID_OUI_FROM_DATABASE=Toshiba +OUI:247189* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:000C29* - ID_OUI_FROM_DATABASE=VMware, Inc. +OUI:EC1127* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:005056* - ID_OUI_FROM_DATABASE=VMware, Inc. +OUI:F0C77F* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:001C4D* - ID_OUI_FROM_DATABASE=Aplix IP Holdings Corporation +OUI:F45EAB* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:D0052A* - ID_OUI_FROM_DATABASE=Arcadyan Corporation +OUI:001783* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:F485C6* - ID_OUI_FROM_DATABASE=FDT Technologies +OUI:A81B6A* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:BC60A7* - ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. +OUI:9884E3* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:08D833* - ID_OUI_FROM_DATABASE=Shenzhen RF Technology Co., Ltd +OUI:38D269* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:94D469* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:C8FD19* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:385610* - ID_OUI_FROM_DATABASE=CANDY HOUSE, Inc. +OUI:508CB1* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:20F543* - ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD +OUI:04BBF9* + ID_OUI_FROM_DATABASE=Pavilion Data Systems Inc -OUI:685388* - ID_OUI_FROM_DATABASE=P&S Technology +OUI:B0F893* + ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd. -OUI:54A619* - ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd +OUI:00C017* + ID_OUI_FROM_DATABASE=NetScout Systems, Inc. -OUI:1880F5* - ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd +OUI:D49B5C* + ID_OUI_FROM_DATABASE=Chongqing Miedu Technology Co., Ltd. -OUI:24DBED* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:EC8CA2* + ID_OUI_FROM_DATABASE=Ruckus Wireless -OUI:AC3613* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:C411E0* + ID_OUI_FROM_DATABASE=Bull Group Co., Ltd -OUI:1449E0* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) +OUI:90842B* + ID_OUI_FROM_DATABASE=LEGO System A/S -OUI:C0BDD1* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) +OUI:84C7EA* + ID_OUI_FROM_DATABASE=Sony Mobile Communications AB -OUI:E8508B* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) +OUI:8C6102* + ID_OUI_FROM_DATABASE=Beijing Baofengmojing Technologies Co., Ltd -OUI:F025B7* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) +OUI:1005B1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:C8BA94* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) +OUI:10868C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:EC1F72* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) +OUI:1C1B68* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:9852B1* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:44E137* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:1489FD* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:E83381* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:CCFE3C* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:8461A0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:789ED0* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:0CF893* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:E440E2* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:14ABF0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:1CAF05* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:ACB313* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:E492FB* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:0026D9* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:247F20* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:28C87A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:0073E0* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:54E2E0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:BC4486* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:A055DE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:380B40* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:A0C562* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:8C0D76* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:FC6FB7* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:005A13* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:001A1B* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:002490* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:00149A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:0023D7* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:001371* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:FCA13E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:001DBE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:A00798* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:001E5A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:945103* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:001D6B* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:C819F7* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:001CC1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:2C4401* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:001C11* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:08C6B3* - ID_OUI_FROM_DATABASE=QTECH LLC +OUI:001F7E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:64DAA0* - ID_OUI_FROM_DATABASE=Robert Bosch Smart Home GmbH +OUI:002495* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:14B837* - ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd +OUI:2C9E5F* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:8056F2* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:C8AA21* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:70188B* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:341FE4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:3C77E6* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:400D10* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:0C84DC* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:001596* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:844BF5* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:0015A2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:E006E6* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:001311* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:60F494* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:0015CE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:A41731* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:002040* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:C0143D* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:0011AE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:642737* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:000F9F* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:60D819* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:306023* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:6474F6* - ID_OUI_FROM_DATABASE=Shooter Detection Systems +OUI:001DD6* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:604BAA* - ID_OUI_FROM_DATABASE=Private +OUI:001DD1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:CC7314* - ID_OUI_FROM_DATABASE=HONG KONG WHEATEK TECHNOLOGY LIMITED - -OUI:C0CB38* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. - -OUI:98E7F4* - ID_OUI_FROM_DATABASE=Hewlett Packard - -OUI:D42C44* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc - -OUI:D842E2* - ID_OUI_FROM_DATABASE=Canary Connect, Inc. - -OUI:500959* - ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. - -OUI:143365* - ID_OUI_FROM_DATABASE=TEM Mobile Limited - -OUI:205D47* - ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. - -OUI:C0F945* - ID_OUI_FROM_DATABASE=Toshiba Toko Meter Systems Co., LTD. - -OUI:ACAB2E* - ID_OUI_FROM_DATABASE=Beijing LasNubes Technology Co., Ltd. - -OUI:10E878* - ID_OUI_FROM_DATABASE=Nokia - -OUI:48F7F1* - ID_OUI_FROM_DATABASE=Nokia - -OUI:4CC94F* - ID_OUI_FROM_DATABASE=Nokia - -OUI:1CEA1B* - ID_OUI_FROM_DATABASE=Nokia - -OUI:B4F81E* - ID_OUI_FROM_DATABASE=Kinova - -OUI:A46011* - ID_OUI_FROM_DATABASE=VeriFone Inc. - -OUI:28CA09* - ID_OUI_FROM_DATABASE=ThyssenKrupp Elevators (Shanghai) Co.,Ltd - -OUI:E0B94D* - ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD - -OUI:D8380D* - ID_OUI_FROM_DATABASE=SHENZHEN IP-COM Network Co.,Ltd - -OUI:A4C64F* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:C83DD4* - ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. - -OUI:487B6B* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:3087D9* - ID_OUI_FROM_DATABASE=Ruckus Wireless - -OUI:A8E705* - ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD - -OUI:9C62AB* - ID_OUI_FROM_DATABASE=Sumavision Technologies Co.,Ltd - -OUI:487A55* - ID_OUI_FROM_DATABASE=ALE International - -OUI:000435* - ID_OUI_FROM_DATABASE=InfiNet LLC - -OUI:BC39D9* - ID_OUI_FROM_DATABASE=Z-TEC - -OUI:88E87F* - ID_OUI_FROM_DATABASE=Apple, Inc. - -OUI:B853AC* - ID_OUI_FROM_DATABASE=Apple, Inc. - -OUI:B04BBF* - ID_OUI_FROM_DATABASE=PT HAN SUNG ELECTORONICS INDONESIA - -OUI:0060D6* - ID_OUI_FROM_DATABASE=NovAtel Inc. - -OUI:2C3361* - ID_OUI_FROM_DATABASE=Apple, Inc. - -OUI:78B84B* - ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD - -OUI:40F420* - ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD - -OUI:9C6121* - ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD - -OUI:8C8ABB* - ID_OUI_FROM_DATABASE=Beijing Orient View Technology Co., Ltd. - -OUI:88366C* - ID_OUI_FROM_DATABASE=EFM Networks - -OUI:F074E4* - ID_OUI_FROM_DATABASE=Thundercomm Technology Co., Ltd - -OUI:A0722C* - ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. - -OUI:FCECDA* - ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. - -OUI:E07C13* - ID_OUI_FROM_DATABASE=zte corporation - -OUI:58696C* - ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD. - -OUI:001972* - ID_OUI_FROM_DATABASE=Plexus (Xiamen) Co.,ltd. - -OUI:6488FF* - ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. - -OUI:005979* - ID_OUI_FROM_DATABASE=Networked Energy Services - -OUI:000997* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:000E62* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:000EC0* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:000FCD* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:0004DC* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:02E6D3* - ID_OUI_FROM_DATABASE=NIXDORF COMPUTER CORP. - -OUI:0016B9* - ID_OUI_FROM_DATABASE=ProCurve Networking by HP - -OUI:0024A8* - ID_OUI_FROM_DATABASE=ProCurve Networking by HP - -OUI:CC3ADF* - ID_OUI_FROM_DATABASE=Private - -OUI:141F78* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:006F64* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:DC6672* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:0025C3* - ID_OUI_FROM_DATABASE=21168 - -OUI:001365* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:001ECA* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:001D42* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:001CEB* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:002363* - ID_OUI_FROM_DATABASE=Zhuhai Raysharp Technology Co.,Ltd - -OUI:D03742* - ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd - -OUI:001CFD* - ID_OUI_FROM_DATABASE=Universal Electronics, Inc. - -OUI:080051* - ID_OUI_FROM_DATABASE=ExperData - -OUI:0080C7* - ID_OUI_FROM_DATABASE=XIRCOM - -OUI:049FCA* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:C81FBE* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:203DB2* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:48D539* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:10E68F* - ID_OUI_FROM_DATABASE=KWANGSUNG ELECTRONICS KOREA CO.,LTD. - -OUI:1899F5* - ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. - -OUI:E41D2D* - ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. - -OUI:B80018* - ID_OUI_FROM_DATABASE=Htel - -OUI:0081C4* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc - -OUI:E8FD90* - ID_OUI_FROM_DATABASE=Turbostor - -OUI:0017EA* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:0017E3* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:001834* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:00182F* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:78DEE4* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:B8FFFE* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:E0D7BA* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:405FC2* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:8030DC* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:CC78AB* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:A4D578* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:544A16* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:D8DDFD* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:20CD39* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:987BF3* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:247189* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:EC1127* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:F0C77F* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:F45EAB* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:001783* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:A81B6A* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:9884E3* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:38D269* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:C8FD19* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:508CB1* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:04BBF9* - ID_OUI_FROM_DATABASE=Pavilion Data Systems Inc - -OUI:B0F893* - ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd. - -OUI:00C017* - ID_OUI_FROM_DATABASE=NetScout Systems, Inc. - -OUI:D49B5C* - ID_OUI_FROM_DATABASE=Chongqing Miedu Technology Co., Ltd. - -OUI:EC8CA2* - ID_OUI_FROM_DATABASE=Ruckus Wireless - -OUI:C411E0* - ID_OUI_FROM_DATABASE=Bull Group Co., Ltd - -OUI:90842B* - ID_OUI_FROM_DATABASE=LEGO System A/S - -OUI:84C7EA* - ID_OUI_FROM_DATABASE=Sony Mobile Communications AB - -OUI:8C6102* - ID_OUI_FROM_DATABASE=Beijing Baofengmojing Technologies Co., Ltd - -OUI:1005B1* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:10868C* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:1C1B68* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:44E137* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:E83381* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:8461A0* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:0CF893* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:14ABF0* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:ACB313* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:0026D9* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:28C87A* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:54E2E0* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:A055DE* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:A0C562* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:FC6FB7* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001A1B* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:00149A* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001371* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001DBE* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001E5A* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001D6B* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001CC1* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001C11* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001F7E* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:002495* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:2C9E5F* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:C8AA21* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:341FE4* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:400D10* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001596* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:0015A2* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001311* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:0015CE* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:002040* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:0011AE* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:000F9F* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:306023* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001DD6* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:001DD1* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - -OUI:601971* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:601971* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0000CA* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. @@ -34694,9 +35429,6 @@ OUI:F0038C* OUI:B45D50* ID_OUI_FROM_DATABASE=Aruba Networks -OUI:742344* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - OUI:001E7D* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd @@ -34832,1312 +35564,2080 @@ OUI:8CEA1B* OUI:001650* ID_OUI_FROM_DATABASE=Kratos EPD -OUI:58E16C* - ID_OUI_FROM_DATABASE=Ying Hua Information Technology (Shanghai)Co., LTD - -OUI:5846E1* - ID_OUI_FROM_DATABASE=Baxter International Inc +OUI:9CFBD5* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. -OUI:00D0BD* - ID_OUI_FROM_DATABASE=Lattice Semiconductor Corp. (LPA) +OUI:583112* + ID_OUI_FROM_DATABASE=DRUST -OUI:F08261* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:7C2634* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:D084B0* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:58696C* + ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD -OUI:00FEC8* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:A0B8F8* + ID_OUI_FROM_DATABASE=Amgen U.S.A. Inc. -OUI:0030C5* - ID_OUI_FROM_DATABASE=CADENCE DESIGN SYSTEMS, INC. +OUI:14A51A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:EC2280* - ID_OUI_FROM_DATABASE=D-Link International +OUI:C816A5* + ID_OUI_FROM_DATABASE=Masimo Corporation -OUI:047863* - ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd. +OUI:9002A9* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. -OUI:24BA13* - ID_OUI_FROM_DATABASE=RISO KAGAKU CORPORATION +OUI:ACD657* + ID_OUI_FROM_DATABASE=Shaanxi GuoLian Digital TV Technology Co.,Ltd. -OUI:24DA11* - ID_OUI_FROM_DATABASE=NO NDA Inc +OUI:E80945* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. -OUI:70CA4D* - ID_OUI_FROM_DATABASE=Shenzhen lnovance Technology Co.,Ltd. +OUI:98FD74* + ID_OUI_FROM_DATABASE=ACT.CO.LTD -OUI:DCC0EB* - ID_OUI_FROM_DATABASE=ASSA ABLOY CÔTE PICARDE +OUI:60C798* + ID_OUI_FROM_DATABASE=Verifone -OUI:001735* - ID_OUI_FROM_DATABASE=Intel Wireless Network Group +OUI:A46011* + ID_OUI_FROM_DATABASE=Verifone -OUI:9CDFB1* - ID_OUI_FROM_DATABASE=Shenzhen Crave Communication Co., LTD +OUI:2C2131* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:5CF938* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:0CC47A* + ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. -OUI:3871DE* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:60427F* + ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD -OUI:BC5436* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:F8461C* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. -OUI:0CC731* - ID_OUI_FROM_DATABASE=Currant, Inc. +OUI:40B93C* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise -OUI:00142F* - ID_OUI_FROM_DATABASE=Savvius +OUI:4C7487* + ID_OUI_FROM_DATABASE=Leader Phone Communication Technology Co., Ltd. -OUI:2CDDA3* - ID_OUI_FROM_DATABASE=Point Grey Research Inc. +OUI:F48C50* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:24FD5B* - ID_OUI_FROM_DATABASE=SmartThings, Inc. - -OUI:2876CD* - ID_OUI_FROM_DATABASE=Funshion Online Technologies Co.,Ltd - -OUI:F4F5D8* - ID_OUI_FROM_DATABASE=Google, Inc. - -OUI:F4F5E8* - ID_OUI_FROM_DATABASE=Google, Inc. - -OUI:F88FCA* - ID_OUI_FROM_DATABASE=Google, Inc. +OUI:E8E875* + ID_OUI_FROM_DATABASE=iS5 Communications Inc. -OUI:BCD1D3* - ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. +OUI:000422* + ID_OUI_FROM_DATABASE=Studio Technologies, Inc -OUI:BC4434* - ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. +OUI:ACC662* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. -OUI:0041D2* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:B8ECA3* + ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation -OUI:4CFB45* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:F01DBC* + ID_OUI_FROM_DATABASE=Microsoft Corporation -OUI:A4BA76* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:404D7F* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:78E3B5* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:7C04D0* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:984BE1* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:BC9FEF* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:68B599* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:8866A5* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:0C47C9* - ID_OUI_FROM_DATABASE=Amazon Technologies Inc. +OUI:ACDCE5* + ID_OUI_FROM_DATABASE=Procter & Gamble Company -OUI:14D64D* - ID_OUI_FROM_DATABASE=D-Link International +OUI:784F43* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:C8BE19* - ID_OUI_FROM_DATABASE=D-Link International +OUI:98D293* + ID_OUI_FROM_DATABASE=Google, Inc. -OUI:BCF685* - ID_OUI_FROM_DATABASE=D-Link International +OUI:5CCCA0* + ID_OUI_FROM_DATABASE=Gridwiz Inc. -OUI:CCB255* - ID_OUI_FROM_DATABASE=D-Link International +OUI:104FA8* + ID_OUI_FROM_DATABASE=Sony Corporation -OUI:84C9B2* - ID_OUI_FROM_DATABASE=D-Link International +OUI:6C25B9* + ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. -OUI:DCD321* - ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. +OUI:486B2C* + ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. -OUI:CC4EEC* - ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. +OUI:00001F* + ID_OUI_FROM_DATABASE=Telco Systems, Inc. -OUI:DC330D* - ID_OUI_FROM_DATABASE=Qingdao Haier Telecom Co.,Ltd +OUI:BC307E* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation -OUI:0080E1* - ID_OUI_FROM_DATABASE=STMicroelectronics SRL +OUI:00C0AB* + ID_OUI_FROM_DATABASE=Telco Systems, Inc. -OUI:58DC6D* - ID_OUI_FROM_DATABASE=Exceptional Innovation, Inc. +OUI:0010CA* + ID_OUI_FROM_DATABASE=Telco Systems, Inc. -OUI:00092D* - ID_OUI_FROM_DATABASE=HTC Corporation +OUI:0C2576* + ID_OUI_FROM_DATABASE=LONGCHEER TELECOMMUNICATION LIMITED -OUI:F8DB7F* - ID_OUI_FROM_DATABASE=HTC Corporation +OUI:0007A6* + ID_OUI_FROM_DATABASE=Leviton Manufacturing Co., Inc. -OUI:E899C4* - ID_OUI_FROM_DATABASE=HTC Corporation +OUI:208756* + ID_OUI_FROM_DATABASE=SIEMENS AG -OUI:7CB15D* +OUI:B08900* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:18686A* - ID_OUI_FROM_DATABASE=zte corporation - -OUI:0C0535* - ID_OUI_FROM_DATABASE=Juniper Systems - -OUI:8CF228* +OUI:640DCE* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. -OUI:08EA44* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. +OUI:00A085* + ID_OUI_FROM_DATABASE=Private -OUI:78F882* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) +OUI:ACDE48* + ID_OUI_FROM_DATABASE=Private -OUI:8851FB* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:6063F9* + ID_OUI_FROM_DATABASE=Ciholas, Inc. -OUI:AC162D* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:F0421C* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:A0B3CC* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:C0E42D* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:E4115B* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:18D6C7* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:C8CBB8* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:B8BB23* + ID_OUI_FROM_DATABASE=Guangdong Nufront CSC Co., Ltd -OUI:9457A5* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:EC26FB* + ID_OUI_FROM_DATABASE=TECC CO.,LTD. -OUI:0001E7* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:10683F* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:080009* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:A039F7* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:0080A0* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:64BC0C* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:D48564* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:0090CC* + ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. -OUI:3C4A92* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:E09DB8* + ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. -OUI:780AC7* - ID_OUI_FROM_DATABASE=Baofeng TV Co., Ltd. +OUI:64899A* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:001D73* - ID_OUI_FROM_DATABASE=BUFFALO.INC +OUI:58A2B5* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:001601* - ID_OUI_FROM_DATABASE=BUFFALO.INC +OUI:74A722* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:106F3F* - ID_OUI_FROM_DATABASE=BUFFALO.INC +OUI:001F6B* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:8857EE* - ID_OUI_FROM_DATABASE=BUFFALO.INC +OUI:903AE6* + ID_OUI_FROM_DATABASE=PARROT SA -OUI:009C02* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:00E00F* + ID_OUI_FROM_DATABASE=Shanghai Baud Data Communication Co.,Ltd. -OUI:78E7D1* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:3C404F* + ID_OUI_FROM_DATABASE=GUANGDONG PISEN ELECTRONICS CO.,LTD -OUI:001B78* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:00233E* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD -OUI:001E0B* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:6CBEE9* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD -OUI:2C6E85* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:0080F7* + ID_OUI_FROM_DATABASE=Zenith Electronics Corporation -OUI:00D0B7* - ID_OUI_FROM_DATABASE=Intel Corporation +OUI:00C095* + ID_OUI_FROM_DATABASE=ZNYX Networks, Inc. -OUI:0002B3* - ID_OUI_FROM_DATABASE=Intel Corporation +OUI:60EB69* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. -OUI:001111* - ID_OUI_FROM_DATABASE=Intel Corporation +OUI:C80AA9* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. -OUI:001320* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:00238B* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. -OUI:0012F0* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:0007BA* + ID_OUI_FROM_DATABASE=UTStarcom Inc -OUI:9049FA* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:4439C4* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. -OUI:C8348E* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:70F395* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. -OUI:00508B* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:001E37* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. -OUI:784859* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:002713* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. -OUI:1458D0* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:002186* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. -OUI:5065F3* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:8CFDF0* + ID_OUI_FROM_DATABASE=Qualcomm Inc. -OUI:A0481C* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:000031* + ID_OUI_FROM_DATABASE=QPSX COMMUNICATIONS, LTD. -OUI:A01D48* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:000E7B* + ID_OUI_FROM_DATABASE=Toshiba -OUI:94B2CC* - ID_OUI_FROM_DATABASE=PIONEER CORPORATION +OUI:B86B23* + ID_OUI_FROM_DATABASE=Toshiba -OUI:887F03* - ID_OUI_FROM_DATABASE=Comper Technology Investment Limited +OUI:000C29* + ID_OUI_FROM_DATABASE=VMware, Inc. -OUI:E06066* - ID_OUI_FROM_DATABASE=Sercomm Corporation +OUI:005056* + ID_OUI_FROM_DATABASE=VMware, Inc. -OUI:0019E0* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:001C4D* + ID_OUI_FROM_DATABASE=Aplix IP Holdings Corporation -OUI:0023CD* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:D0052A* + ID_OUI_FROM_DATABASE=Arcadyan Corporation -OUI:002719* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:F485C6* + ID_OUI_FROM_DATABASE=FDT Technologies -OUI:40169F* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:BC60A7* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. -OUI:940C6D* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:08D833* + ID_OUI_FROM_DATABASE=Shenzhen RF Technology Co., Ltd -OUI:74EA3A* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:94D469* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:90F652* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:385610* + ID_OUI_FROM_DATABASE=CANDY HOUSE, Inc. -OUI:10FEED* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:20F543* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD -OUI:C46E1F* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:685388* + ID_OUI_FROM_DATABASE=P&S Technology -OUI:50FA84* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:54A619* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd -OUI:F483CD* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:1880F5* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd -OUI:882593* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:24DBED* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:808917* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:AC3613* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:5C899A* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:1449E0* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) -OUI:A81B5A* - ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +OUI:C0BDD1* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) -OUI:E422A5* - ID_OUI_FROM_DATABASE=PLANTRONICS, INC. +OUI:E8508B* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) -OUI:1C994C* - ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. +OUI:F025B7* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) -OUI:F02765* - ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. +OUI:C8BA94* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) -OUI:D4970B* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd +OUI:EC1F72* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) -OUI:F48B32* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd +OUI:9852B1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:20A783* - ID_OUI_FROM_DATABASE=miControl GmbH +OUI:1489FD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:005053* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:CCFE3C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00500F* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:789ED0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:048A15* - ID_OUI_FROM_DATABASE=Avaya Inc +OUI:E440E2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:44322A* - ID_OUI_FROM_DATABASE=Avaya Inc +OUI:1CAF05* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:FC8399* - ID_OUI_FROM_DATABASE=Avaya Inc +OUI:E492FB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00040D* - ID_OUI_FROM_DATABASE=Avaya Inc +OUI:247F20* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:D842AC* - ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd. +OUI:0073E0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:34CDBE* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:BC4486* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:D46AA8* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:380B40* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:5439DF* +OUI:8C0D76* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:4846FB* +OUI:005A13* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:200BC7* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:002490* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:104780* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:0023D7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:88308A* - ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. +OUI:FCA13E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:44A7CF* - ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. +OUI:A00798* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:0013E0* - ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. +OUI:945103* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:748EF8* - ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. +OUI:C819F7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00E052* - ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. +OUI:2C4401* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:000480* - ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. +OUI:08C6B3* + ID_OUI_FROM_DATABASE=QTECH LLC -OUI:000088* - ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. +OUI:64DAA0* + ID_OUI_FROM_DATABASE=Robert Bosch Smart Home GmbH -OUI:344B50* - ID_OUI_FROM_DATABASE=zte corporation +OUI:14B837* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd -OUI:FCC897* - ID_OUI_FROM_DATABASE=zte corporation +OUI:8056F2* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:9CD24B* - ID_OUI_FROM_DATABASE=zte corporation +OUI:70188B* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:C864C7* - ID_OUI_FROM_DATABASE=zte corporation +OUI:3C77E6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:D0154A* - ID_OUI_FROM_DATABASE=zte corporation +OUI:0C84DC* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:88E3AB* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:844BF5* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:00664B* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:E006E6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:68A0F6* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:60F494* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:5CF96A* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:A41731* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:B43052* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:C0143D* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:88CEFA* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:642737* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:582AF7* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:60D819* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:F48E92* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:6474F6* + ID_OUI_FROM_DATABASE=Shooter Detection Systems -OUI:40CBA8* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:604BAA* + ID_OUI_FROM_DATABASE=Private -OUI:087A4C* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:CC7314* + ID_OUI_FROM_DATABASE=HONG KONG WHEATEK TECHNOLOGY LIMITED -OUI:D46E5C* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:C0CB38* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:2469A5* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:98E7F4* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:C8D15E* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:D42C44* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:F83DFF* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:D842E2* + ID_OUI_FROM_DATABASE=Canary Connect, Inc. -OUI:308730* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:500959* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:002568* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:143365* + ID_OUI_FROM_DATABASE=TEM Mobile Limited -OUI:D47856* - ID_OUI_FROM_DATABASE=Avaya Inc +OUI:205D47* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. -OUI:C057BC* - ID_OUI_FROM_DATABASE=Avaya Inc +OUI:C0F945* + ID_OUI_FROM_DATABASE=Toshiba Toko Meter Systems Co., LTD. -OUI:38BB3C* - ID_OUI_FROM_DATABASE=Avaya Inc +OUI:ACAB2E* + ID_OUI_FROM_DATABASE=Beijing LasNubes Technology Co., Ltd. -OUI:E45D52* - ID_OUI_FROM_DATABASE=Avaya Inc +OUI:10E878* + ID_OUI_FROM_DATABASE=Nokia -OUI:A4251B* - ID_OUI_FROM_DATABASE=Avaya Inc +OUI:48F7F1* + ID_OUI_FROM_DATABASE=Nokia -OUI:6CA849* - ID_OUI_FROM_DATABASE=Avaya Inc +OUI:4CC94F* + ID_OUI_FROM_DATABASE=Nokia -OUI:30D17E* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:1CEA1B* + ID_OUI_FROM_DATABASE=Nokia -OUI:9C28EF* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:B4F81E* + ID_OUI_FROM_DATABASE=Kinova -OUI:7C6097* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:28CA09* + ID_OUI_FROM_DATABASE=ThyssenKrupp Elevators (Shanghai) Co.,Ltd -OUI:60DE44* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:E0B94D* + ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD -OUI:3400A3* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:D8380D* + ID_OUI_FROM_DATABASE=SHENZHEN IP-COM Network Co.,Ltd -OUI:643E8C* +OUI:A4C64F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:00C610* - ID_OUI_FROM_DATABASE=Apple, Inc. - -OUI:70DEE2* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:C83DD4* + ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. -OUI:182032* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:487B6B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:6CC26B* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:3087D9* + ID_OUI_FROM_DATABASE=Ruckus Wireless -OUI:1040F3* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:A8E705* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD -OUI:FC253F* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:9C62AB* + ID_OUI_FROM_DATABASE=Sumavision Technologies Co.,Ltd -OUI:183451* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:487A55* + ID_OUI_FROM_DATABASE=ALE International -OUI:C0847A* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:000435* + ID_OUI_FROM_DATABASE=InfiNet LLC -OUI:64200C* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:BC39D9* + ID_OUI_FROM_DATABASE=Z-TEC -OUI:74E1B6* +OUI:88E87F* ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:0C771A* +OUI:B853AC* ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:00F4B9* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:B04BBF* + ID_OUI_FROM_DATABASE=PT HAN SUNG ELECTORONICS INDONESIA -OUI:C8334B* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:0060D6* + ID_OUI_FROM_DATABASE=NovAtel Inc. -OUI:B8F6B1* +OUI:2C3361* ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:C09F42* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:78B84B* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD -OUI:189EFC* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:40F420* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD -OUI:6C3E6D* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:9C6121* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD -OUI:0016FE* - ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. +OUI:8C8ABB* + ID_OUI_FROM_DATABASE=Beijing Orient View Technology Co., Ltd. -OUI:0498F3* - ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. +OUI:88366C* + ID_OUI_FROM_DATABASE=EFM Networks -OUI:38C096* - ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. +OUI:F074E4* + ID_OUI_FROM_DATABASE=Thundercomm Technology Co., Ltd -OUI:E0750A* - ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. +OUI:A0722C* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. -OUI:B05947* - ID_OUI_FROM_DATABASE=Shenzhen Qihu Intelligent Technology Company Limited +OUI:FCECDA* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. -OUI:00E04F* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:E07C13* + ID_OUI_FROM_DATABASE=zte corporation -OUI:001011* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:58E16C* + ID_OUI_FROM_DATABASE=Ying Hua Information Technology (Shanghai)Co., LTD -OUI:0010F6* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:24C1BD* + ID_OUI_FROM_DATABASE=CRRC DALIAN R&D CO.,LTD. -OUI:80E01D* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:A81E84* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. -OUI:80E86F* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:C82158* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:E4AA5D* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:2420C7* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:000389* - ID_OUI_FROM_DATABASE=PLANTRONICS, INC. +OUI:703D15* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited -OUI:0CE0E4* - ID_OUI_FROM_DATABASE=PLANTRONICS, INC. +OUI:4018B1* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. -OUI:B0AA77* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001977* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. -OUI:78BAF9* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:C8665D* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. -OUI:0016B6* - ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC +OUI:3CEF8C* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. -OUI:0018F8* - ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC +OUI:A0CC2B* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. -OUI:00252E* - ID_OUI_FROM_DATABASE=Cisco SPVTG +OUI:00234A* + ID_OUI_FROM_DATABASE=Private -OUI:A4A24A* - ID_OUI_FROM_DATABASE=Cisco SPVTG +OUI:88C626* + ID_OUI_FROM_DATABASE=Logitech, Inc -OUI:602AD0* - ID_OUI_FROM_DATABASE=Cisco SPVTG +OUI:B85001* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc. -OUI:001BFB* - ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. +OUI:28E31F* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:00E08F* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0C1DAF* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:203A07* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:14F65A* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:34A84E* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:742344* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:E4D3F1* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:F0B429* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:1CE6C7* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:94E979* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation -OUI:E02F6D* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:AC1F6B* + ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. -OUI:8478AC* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:80D4A5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:4403A7* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:38BC01* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:6886A7* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:04B0E7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:B4E9B0* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:446A2E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:000832* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0026AB* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation -OUI:B0FAEB* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:64EB8C* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation -OUI:500604* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:A06FAA* + ID_OUI_FROM_DATABASE=LG Innotek -OUI:70105C* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0015FC* + ID_OUI_FROM_DATABASE=Littelfuse Startco -OUI:7CFADF* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:504B5B* + ID_OUI_FROM_DATABASE=CONTROLtronic GmbH -OUI:101C0C* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:A0E0AF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001124* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:603E7B* + ID_OUI_FROM_DATABASE=Gafachi, Inc. -OUI:001D4F* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:98F199* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. -OUI:001E52* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:78FC14* + ID_OUI_FROM_DATABASE=Family Zone Cyber Safety Ltd -OUI:001F5B* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:1062EB* + ID_OUI_FROM_DATABASE=D-Link International -OUI:001FF3* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:1C48CE* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD -OUI:0021E9* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:E0A700* + ID_OUI_FROM_DATABASE=Verkada Inc -OUI:00236C* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:901711* + ID_OUI_FROM_DATABASE=Hagenuk Marinekommunikation GmbH -OUI:002500* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:D825B0* + ID_OUI_FROM_DATABASE=Rockeetech Systems Co.,Ltd. -OUI:60FB42* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:74614B* + ID_OUI_FROM_DATABASE=Chongqing Huijiatong Information Technology Co., Ltd. -OUI:14DAE9* - ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. +OUI:C0D9F7* + ID_OUI_FROM_DATABASE=ShanDong Domor Intelligent S&T CO.,Ltd -OUI:3C08F6* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:94FB29* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc. -OUI:D072DC* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:64DBA0* + ID_OUI_FROM_DATABASE=Select Comfort -OUI:28C7CE* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:5800E3* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation -OUI:6CFA89* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:64777D* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc -OUI:58F39C* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0495E6* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch -OUI:346288* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0016D3* + ID_OUI_FROM_DATABASE=Wistron Corporation -OUI:881DFC* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001F16* + ID_OUI_FROM_DATABASE=Wistron Corporation -OUI:F81EDF* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:4C4E03* + ID_OUI_FROM_DATABASE=TCT mobile ltd -OUI:90840D* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:50E666* + ID_OUI_FROM_DATABASE=Shenzhen Techtion Electronics Co., Ltd. -OUI:D8A25E* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:6831FE* + ID_OUI_FROM_DATABASE=Teladin Co.,Ltd. -OUI:C8BCC8* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:EC43F6* + ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation -OUI:28E7CF* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:D4B169* + ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited -OUI:D89E3F* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:0C3CCD* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. -OUI:040CCE* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:B04089* + ID_OUI_FROM_DATABASE=Senient Systems LTD -OUI:A4D1D2* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:682737* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:406C8F* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:002445* + ID_OUI_FROM_DATABASE=Adtran Inc -OUI:C067AF* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:689FF0* + ID_OUI_FROM_DATABASE=zte corporation -OUI:64E950* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:7CC6C4* + ID_OUI_FROM_DATABASE=Kolff Computer Supplies b.v. -OUI:189C5D* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:14B7F8* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:000EA6* - ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. +OUI:F06E32* + ID_OUI_FROM_DATABASE=MICROTEL INNOVATION S.R.L. -OUI:0013D4* - ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. +OUI:00E022* + ID_OUI_FROM_DATABASE=Analog Devices, Inc. -OUI:002618* - ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. +OUI:7C67A2* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:00248C* - ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. +OUI:000302* + ID_OUI_FROM_DATABASE=Charles Industries, Ltd. -OUI:0050A2* +OUI:0896AD* ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0050F0* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:8CF5A3* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) -OUI:00905F* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:B8EAAA* + ID_OUI_FROM_DATABASE=ICG NETWORKS CO.,ltd -OUI:00902B* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:B8F883* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:00100B* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:DCFE18* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:00100D* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:AC60B6* + ID_OUI_FROM_DATABASE=Ericsson AB -OUI:001014* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:3C197D* + ID_OUI_FROM_DATABASE=Ericsson AB -OUI:649ABE* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:74C99A* + ID_OUI_FROM_DATABASE=Ericsson AB -OUI:94E96A* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:000F4F* + ID_OUI_FROM_DATABASE=PCS Systemtechnik GmbH -OUI:AC293A* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:7C5A1C* + ID_OUI_FROM_DATABASE=Sophos Ltd -OUI:10417F* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:00E400* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. -OUI:7014A6* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:00117E* + ID_OUI_FROM_DATABASE=Midmark Corp -OUI:A8667F* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:703ACB* + ID_OUI_FROM_DATABASE=Google, Inc. -OUI:D02598* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:105AF7* + ID_OUI_FROM_DATABASE=ADB Italia -OUI:CC29F5* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:2C55D3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:6C709F* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:F44C7F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:0C3E9F* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:143004* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:34E2FD* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:D481D7* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:609217* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:5846E1* + ID_OUI_FROM_DATABASE=Baxter International Inc -OUI:8863DF* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:00D0BD* + ID_OUI_FROM_DATABASE=Lattice Semiconductor Corp. (LPA) -OUI:80E650* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:F08261* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:006171* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:D084B0* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:90FD61* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:00FEC8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:5C97F3* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:0030C5* + ID_OUI_FROM_DATABASE=CADENCE DESIGN SYSTEMS, INC. -OUI:6C4008* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:EC2280* + ID_OUI_FROM_DATABASE=D-Link International -OUI:24A074* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:047863* + ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd. -OUI:F02475* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:24BA13* + ID_OUI_FROM_DATABASE=RISO KAGAKU CORPORATION -OUI:20A2E4* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:24DA11* + ID_OUI_FROM_DATABASE=NO NDA Inc -OUI:5CF5DA* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:70CA4D* + ID_OUI_FROM_DATABASE=Shenzhen lnovance Technology Co.,Ltd. -OUI:D4B8FF* - ID_OUI_FROM_DATABASE=Home Control Singapore Pte Ltd +OUI:DCC0EB* + ID_OUI_FROM_DATABASE=ASSA ABLOY CÔTE PICARDE -OUI:28E14C* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:001735* + ID_OUI_FROM_DATABASE=Intel Wireless Network Group -OUI:54E43A* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:9CDFB1* + ID_OUI_FROM_DATABASE=Shenzhen Crave Communication Co., LTD -OUI:C8E0EB* +OUI:5CF938* ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:A88808* +OUI:3871DE* ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:907240* +OUI:BC5436* ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:0C4DE9* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:0CC731* + ID_OUI_FROM_DATABASE=Currant, Inc. -OUI:D89695* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:00142F* + ID_OUI_FROM_DATABASE=Savvius -OUI:0C3021* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:2CDDA3* + ID_OUI_FROM_DATABASE=Point Grey Research Inc. -OUI:F0F61C* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:24FD5B* + ID_OUI_FROM_DATABASE=SmartThings, Inc. -OUI:B03495* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:2876CD* + ID_OUI_FROM_DATABASE=Funshion Online Technologies Co.,Ltd -OUI:848E0C* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:F4F5D8* + ID_OUI_FROM_DATABASE=Google, Inc. -OUI:8C2DAA* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:F4F5E8* + ID_OUI_FROM_DATABASE=Google, Inc. -OUI:444C0C* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:F88FCA* + ID_OUI_FROM_DATABASE=Google, Inc. -OUI:84FCFE* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:BCD1D3* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. -OUI:E48B7F* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:BC4434* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. -OUI:5C969D* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:0041D2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:A8FAD8* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:4CFB45* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:949426* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:A4BA76* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:E0F5C6* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:78E3B5* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:AC6462* - ID_OUI_FROM_DATABASE=zte corporation +OUI:984BE1* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:C08488* - ID_OUI_FROM_DATABASE=Finis Inc +OUI:68B599* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:68E8EB* - ID_OUI_FROM_DATABASE=Linktel Technologies Co.,Ltd +OUI:0C47C9* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. -OUI:20C3A4* - ID_OUI_FROM_DATABASE=RetailNext +OUI:14D64D* + ID_OUI_FROM_DATABASE=D-Link International -OUI:780541* - ID_OUI_FROM_DATABASE=Queclink Wireless Solutions Co., Ltd +OUI:C8BE19* + ID_OUI_FROM_DATABASE=D-Link International -OUI:C02DEE* - ID_OUI_FROM_DATABASE=Cuff +OUI:BCF685* + ID_OUI_FROM_DATABASE=D-Link International -OUI:54A3FA* - ID_OUI_FROM_DATABASE=BQT Solutions (Australia)Pty Ltd +OUI:CCB255* + ID_OUI_FROM_DATABASE=D-Link International -OUI:9023EC* - ID_OUI_FROM_DATABASE=Availink, Inc. +OUI:84C9B2* + ID_OUI_FROM_DATABASE=D-Link International -OUI:7467F7* - ID_OUI_FROM_DATABASE=Zebra Technologoes +OUI:DCD321* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. -OUI:3891D5* - ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited +OUI:CC4EEC* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. -OUI:90DFFB* - ID_OUI_FROM_DATABASE=HOMERIDER SYSTEMS +OUI:DC330D* + ID_OUI_FROM_DATABASE=Qingdao Haier Telecom Co.,Ltd -OUI:3C831E* - ID_OUI_FROM_DATABASE=CKD Corporation +OUI:0080E1* + ID_OUI_FROM_DATABASE=STMicroelectronics SRL -OUI:381C23* - ID_OUI_FROM_DATABASE=Hilan Technology CO.,LTD +OUI:58DC6D* + ID_OUI_FROM_DATABASE=Exceptional Innovation, Inc. -OUI:E03676* +OUI:00092D* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:F8DB7F* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:E899C4* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:7CB15D* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:3CB72B* - ID_OUI_FROM_DATABASE=PLUMgrid Inc +OUI:18686A* + ID_OUI_FROM_DATABASE=zte corporation -OUI:243184* - ID_OUI_FROM_DATABASE=SHARP Corporation +OUI:0C0535* + ID_OUI_FROM_DATABASE=Juniper Systems -OUI:24DA9B* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:8CF228* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. -OUI:3052CB* - ID_OUI_FROM_DATABASE=Liteon Technology Corporation +OUI:78F882* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:B8B2EB* - ID_OUI_FROM_DATABASE=Googol Technology (HK) Limited +OUI:8851FB* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:C40049* - ID_OUI_FROM_DATABASE=Kamama +OUI:AC162D* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:50A9DE* - ID_OUI_FROM_DATABASE=Smartcom - Bulgaria AD +OUI:A0B3CC* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:8809AF* - ID_OUI_FROM_DATABASE=Masimo Corp. +OUI:E4115B* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:E8DED6* - ID_OUI_FROM_DATABASE=Intrising Networks, Inc. +OUI:C8CBB8* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:B844D9* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:9457A5* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:DC2B2A* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:0001E7* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:8C10D4* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:080009* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:089B4B* - ID_OUI_FROM_DATABASE=iKuai Networks +OUI:0080A0* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:3C7873* - ID_OUI_FROM_DATABASE=Airsonics +OUI:D48564* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:BC5FF6* - ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +OUI:3C4A92* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:C8F9C8* - ID_OUI_FROM_DATABASE=NewSharp Technology(SuZhou)Co,Ltd +OUI:780AC7* + ID_OUI_FROM_DATABASE=Baofeng TV Co., Ltd. -OUI:3C5CC3* - ID_OUI_FROM_DATABASE=Shenzhen First Blue Chip Technology Ltd +OUI:001D73* + ID_OUI_FROM_DATABASE=BUFFALO.INC -OUI:A8741D* - ID_OUI_FROM_DATABASE=PHOENIX CONTACT Electronics GmbH +OUI:001601* + ID_OUI_FROM_DATABASE=BUFFALO.INC -OUI:A4C138* - ID_OUI_FROM_DATABASE=Telink Semiconductor (Taipei) Co. Ltd. +OUI:106F3F* + ID_OUI_FROM_DATABASE=BUFFALO.INC -OUI:D8EFCD* - ID_OUI_FROM_DATABASE=Nokia +OUI:8857EE* + ID_OUI_FROM_DATABASE=BUFFALO.INC -OUI:EC0133* - ID_OUI_FROM_DATABASE=TRINUS SYSTEMS INC. +OUI:009C02* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:1C56FE* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:78E7D1* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:7CA23E* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:001B78* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:501AA5* - ID_OUI_FROM_DATABASE=GN Netcom A/S +OUI:001E0B* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:F09A51* - ID_OUI_FROM_DATABASE=Shanghai Viroyal Electronic Technology Company Limited +OUI:2C6E85* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:9870E8* - ID_OUI_FROM_DATABASE=INNATECH SDN BHD +OUI:00D0B7* + ID_OUI_FROM_DATABASE=Intel Corporation -OUI:50DF95* - ID_OUI_FROM_DATABASE=Lytx +OUI:0002B3* + ID_OUI_FROM_DATABASE=Intel Corporation -OUI:584925* - ID_OUI_FROM_DATABASE=E3 Enterprise +OUI:001111* + ID_OUI_FROM_DATABASE=Intel Corporation -OUI:94F278* - ID_OUI_FROM_DATABASE=Elma Electronic +OUI:001320* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:E8BDD1* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:0012F0* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:3481F4* - ID_OUI_FROM_DATABASE=SST Taiwan Ltd. +OUI:9049FA* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:F4B8A7* - ID_OUI_FROM_DATABASE=zte corporation +OUI:C8348E* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:58F102* - ID_OUI_FROM_DATABASE=BLU Products Inc. +OUI:00508B* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:B869C2* - ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd. +OUI:784859* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:2CC548* - ID_OUI_FROM_DATABASE=IAdea Corporation +OUI:1458D0* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:307CB2* - ID_OUI_FROM_DATABASE=ANOV FRANCE +OUI:5065F3* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:90D8F3* - ID_OUI_FROM_DATABASE=zte corporation +OUI:A0481C* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:444CA8* - ID_OUI_FROM_DATABASE=Arista Networks +OUI:A01D48* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:FCE33C* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:94B2CC* + ID_OUI_FROM_DATABASE=PIONEER CORPORATION -OUI:BC6A2F* - ID_OUI_FROM_DATABASE=Henge Docks LLC +OUI:887F03* + ID_OUI_FROM_DATABASE=Comper Technology Investment Limited -OUI:E4907E* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:E06066* + ID_OUI_FROM_DATABASE=Sercomm Corporation -OUI:48066A* - ID_OUI_FROM_DATABASE=Tempered Networks, Inc. +OUI:0019E0* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:1CF03E* - ID_OUI_FROM_DATABASE=Wearhaus Inc. +OUI:0023CD* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:DCDB70* - ID_OUI_FROM_DATABASE=Tonfunk Systementwicklung und Service GmbH +OUI:002719* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:C47D46* - ID_OUI_FROM_DATABASE=FUJITSU LIMITED +OUI:40169F* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:68EDA4* - ID_OUI_FROM_DATABASE=Shenzhen Seavo Technology Co.,Ltd +OUI:940C6D* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:B899B0* - ID_OUI_FROM_DATABASE=Cohere Technologies +OUI:74EA3A* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:2CC5D3* - ID_OUI_FROM_DATABASE=Ruckus Wireless +OUI:90F652* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:80C5E6* - ID_OUI_FROM_DATABASE=Microsoft Corporation +OUI:10FEED* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:D85DEF* - ID_OUI_FROM_DATABASE=Busch-Jaeger Elektro GmbH +OUI:C46E1F* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:10DF8B* - ID_OUI_FROM_DATABASE=Shenzhen CareDear Communication Technology Co.,Ltd +OUI:50FA84* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:00A784* - ID_OUI_FROM_DATABASE=ITX security +OUI:F483CD* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:800184* - ID_OUI_FROM_DATABASE=HTC Corporation +OUI:882593* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:38FACA* - ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd +OUI:808917* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:44C69B* - ID_OUI_FROM_DATABASE=Wuhan Feng Tian Information Network CO.,LTD +OUI:5C899A* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:C02567* - ID_OUI_FROM_DATABASE=Nexxt Solutions +OUI:A81B5A* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD -OUI:B46D35* - ID_OUI_FROM_DATABASE=Dalian Seasky Automation Co;Ltd +OUI:E422A5* + ID_OUI_FROM_DATABASE=PLANTRONICS, INC. -OUI:B89ACD* - ID_OUI_FROM_DATABASE=ELITE OPTOELECTRONIC(ASIA)CO.,LTD +OUI:1C994C* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. -OUI:241C04* - ID_OUI_FROM_DATABASE=SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD. +OUI:F02765* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. -OUI:F8CFC5* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:20A783* + ID_OUI_FROM_DATABASE=miControl GmbH -OUI:BCF811* - ID_OUI_FROM_DATABASE=Xiamen DNAKE Technology Co.,Ltd +OUI:005053* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:A8827F* - ID_OUI_FROM_DATABASE=CIBN Oriental Network(Beijing) CO.,Ltd +OUI:00500F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:609C9F* - ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. +OUI:048A15* + ID_OUI_FROM_DATABASE=Avaya Inc -OUI:900A39* - ID_OUI_FROM_DATABASE=Wiio, Inc. +OUI:44322A* + ID_OUI_FROM_DATABASE=Avaya Inc -OUI:C4693E* - ID_OUI_FROM_DATABASE=Turbulence Design Inc. +OUI:FC8399* + ID_OUI_FROM_DATABASE=Avaya Inc -OUI:1C8341* - ID_OUI_FROM_DATABASE=Hefei Bitland Information Technology Co.Ltd +OUI:00040D* + ID_OUI_FROM_DATABASE=Avaya Inc -OUI:4011DC* - ID_OUI_FROM_DATABASE=Sonance +OUI:D842AC* + ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd. -OUI:249EAB* +OUI:34CDBE* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:DC56E6* - ID_OUI_FROM_DATABASE=Shenzhen Bococom Technology Co.,LTD +OUI:D46AA8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:5CA178* - ID_OUI_FROM_DATABASE=TableTop Media (dba Ziosk) +OUI:5439DF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:702A7D* - ID_OUI_FROM_DATABASE=EpSpot AB +OUI:4846FB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:B8B3DC* - ID_OUI_FROM_DATABASE=DEREK (SHAOGUAN) LIMITED +OUI:200BC7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:6C1E70* - ID_OUI_FROM_DATABASE=Guangzhou YBDS IT Co.,Ltd +OUI:104780* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:C8E130* - ID_OUI_FROM_DATABASE=Milkyway Group Ltd +OUI:88308A* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. -OUI:8833BE* - ID_OUI_FROM_DATABASE=Ivenix, Inc. +OUI:44A7CF* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. -OUI:34CC28* - ID_OUI_FROM_DATABASE=Nexpring Co. LTD., +OUI:0013E0* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. -OUI:144146* - ID_OUI_FROM_DATABASE=Honeywell (China) Co., LTD +OUI:748EF8* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. -OUI:F41563* - ID_OUI_FROM_DATABASE=F5 Networks, Inc. +OUI:00E052* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. -OUI:C4EA1D* - ID_OUI_FROM_DATABASE=Technicolor +OUI:000480* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. -OUI:20E407* - ID_OUI_FROM_DATABASE=Spark srl +OUI:000088* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. -OUI:887384* - ID_OUI_FROM_DATABASE=Toshiba +OUI:344B50* + ID_OUI_FROM_DATABASE=zte corporation -OUI:584704* - ID_OUI_FROM_DATABASE=Shenzhen Webridge Technology Co.,Ltd +OUI:FCC897* + ID_OUI_FROM_DATABASE=zte corporation -OUI:749CE3* - ID_OUI_FROM_DATABASE=Art2Wave Canada Inc. +OUI:9CD24B* + ID_OUI_FROM_DATABASE=zte corporation -OUI:B856BD* - ID_OUI_FROM_DATABASE=ITT LLC +OUI:C864C7* + ID_OUI_FROM_DATABASE=zte corporation -OUI:107873* - ID_OUI_FROM_DATABASE=Shenzhen Jinkeyi Communication Co., Ltd. +OUI:D0154A* + ID_OUI_FROM_DATABASE=zte corporation -OUI:D45556* - ID_OUI_FROM_DATABASE=Fiber Mountain Inc. +OUI:88E3AB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:F01E34* - ID_OUI_FROM_DATABASE=ORICO Technologies Co., Ltd +OUI:00664B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:74A063* +OUI:68A0F6* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:A89008* - ID_OUI_FROM_DATABASE=Beijing Yuecheng Technology Co. Ltd. +OUI:5CF96A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:183864* - ID_OUI_FROM_DATABASE=CAP-TECH INTERNATIONAL CO., LTD. +OUI:B43052* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:08D34B* - ID_OUI_FROM_DATABASE=Techman Electronics (Changshu) Co., Ltd. +OUI:88CEFA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:C808E9* - ID_OUI_FROM_DATABASE=LG Electronics +OUI:582AF7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:78ACBF* - ID_OUI_FROM_DATABASE=Igneous Systems +OUI:F48E92* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:206274* - ID_OUI_FROM_DATABASE=Microsoft Corporation +OUI:40CBA8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:5CCCFF* - ID_OUI_FROM_DATABASE=Techroutes Network Pvt Ltd +OUI:087A4C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:844BB7* - ID_OUI_FROM_DATABASE=Beijing Sankuai Online Technology Co.,Ltd +OUI:D46E5C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:148F21* - ID_OUI_FROM_DATABASE=Garmin International +OUI:2469A5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:3C6A9D* - ID_OUI_FROM_DATABASE=Dexatek Technology LTD. +OUI:C8D15E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:14893E* - ID_OUI_FROM_DATABASE=VIXTEL TECHNOLOGIES LIMTED +OUI:F83DFF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:60F189* - ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. +OUI:308730* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:74A34A* - ID_OUI_FROM_DATABASE=ZIMI CORPORATION +OUI:002568* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:98F5A9* - ID_OUI_FROM_DATABASE=OHSUNG ELECTRONICS CO.,LTD. +OUI:D47856* + ID_OUI_FROM_DATABASE=Avaya Inc -OUI:D89341* - ID_OUI_FROM_DATABASE=General Electric Global Research +OUI:C057BC* + ID_OUI_FROM_DATABASE=Avaya Inc -OUI:F4645D* - ID_OUI_FROM_DATABASE=Toshiba +OUI:38BB3C* + ID_OUI_FROM_DATABASE=Avaya Inc -OUI:30D587* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:E45D52* + ID_OUI_FROM_DATABASE=Avaya Inc -OUI:1436C6* - ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. +OUI:A4251B* + ID_OUI_FROM_DATABASE=Avaya Inc -OUI:04C09C* - ID_OUI_FROM_DATABASE=Tellabs Inc. +OUI:6CA849* + ID_OUI_FROM_DATABASE=Avaya Inc -OUI:844464* - ID_OUI_FROM_DATABASE=ServerU Inc +OUI:30D17E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:589B0B* - ID_OUI_FROM_DATABASE=Shineway Technologies, Inc. +OUI:9C28EF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:A48CDB* - ID_OUI_FROM_DATABASE=Lenovo +OUI:7C6097* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:4062B6* - ID_OUI_FROM_DATABASE=Tele system communication +OUI:60DE44* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:3C2C94* - ID_OUI_FROM_DATABASE=杭州德澜科技有限公司(HangZhou Delan Technology Co.,Ltd) +OUI:3400A3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:78312B* - ID_OUI_FROM_DATABASE=zte corporation +OUI:643E8C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:C035C5* - ID_OUI_FROM_DATABASE=Prosoft Systems LTD +OUI:00C610* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:F8B2F3* - ID_OUI_FROM_DATABASE=GUANGZHOU BOSMA TECHNOLOGY CO.,LTD +OUI:70DEE2* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:1C7D22* - ID_OUI_FROM_DATABASE=Fuji Xerox Co., Ltd. +OUI:182032* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:7C11CD* - ID_OUI_FROM_DATABASE=QianTang Technology +OUI:6CC26B* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:0492EE* - ID_OUI_FROM_DATABASE=iway AG +OUI:1040F3* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:F02A23* - ID_OUI_FROM_DATABASE=Creative Next Design +OUI:FC253F* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:8C9109* - ID_OUI_FROM_DATABASE=Toyoshima Electric Technoeogy(Suzhou) Co.,Ltd. +OUI:183451* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:307350* +OUI:C0847A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:64200C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:74E1B6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0C771A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00F4B9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C8334B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B8F6B1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C09F42* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:189EFC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C3E6D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0016FE* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. + +OUI:0498F3* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. + +OUI:38C096* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. + +OUI:E0750A* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. + +OUI:B05947* + ID_OUI_FROM_DATABASE=Shenzhen Qihu Intelligent Technology Company Limited + +OUI:00E04F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001011* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0010F6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:80E01D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:80E86F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E4AA5D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000389* + ID_OUI_FROM_DATABASE=PLANTRONICS, INC. + +OUI:0CE0E4* + ID_OUI_FROM_DATABASE=PLANTRONICS, INC. + +OUI:B0AA77* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:78BAF9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0016B6* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:0018F8* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:00252E* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:A4A24A* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:602AD0* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:001BFB* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. + +OUI:00E08F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:203A07* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:34A84E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E4D3F1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:1CE6C7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E02F6D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:8478AC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:4403A7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6886A7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B4E9B0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000832* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B0FAEB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:500604* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70105C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7CFADF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:101C0C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001124* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001D4F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001E52* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001F5B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001FF3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0021E9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00236C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:002500* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60FB42* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:14DAE9* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:3C08F6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D072DC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:28C7CE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6CFA89* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:58F39C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:346288* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:881DFC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F81EDF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90840D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D8A25E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C8BCC8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28E7CF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D89E3F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:040CCE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A4D1D2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:406C8F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C067AF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:64E950* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:189C5D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000EA6* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:0013D4* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:002618* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:00248C* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:0050A2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0050F0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00905F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00902B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00100B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00100D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001014* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:649ABE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:94E96A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:AC293A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:10417F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7014A6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A8667F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D02598* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CC29F5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C709F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0C3E9F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:34E2FD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:609217* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8863DF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:80E650* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:006171* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90FD61* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5C97F3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C4008* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:24A074* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F02475* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:20A2E4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5CF5DA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D4B8FF* + ID_OUI_FROM_DATABASE=Home Control Singapore Pte Ltd + +OUI:28E14C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:54E43A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C8E0EB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A88808* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:907240* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0C4DE9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D89695* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0C3021* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0F61C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B03495* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:848E0C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C2DAA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:444C0C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:84FCFE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E48B7F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5C969D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A8FAD8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:949426* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E0F5C6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:AC6462* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:C08488* + ID_OUI_FROM_DATABASE=Finis Inc + +OUI:68E8EB* + ID_OUI_FROM_DATABASE=Linktel Technologies Co.,Ltd + +OUI:20C3A4* + ID_OUI_FROM_DATABASE=RetailNext + +OUI:780541* + ID_OUI_FROM_DATABASE=Queclink Wireless Solutions Co., Ltd + +OUI:C02DEE* + ID_OUI_FROM_DATABASE=Cuff + +OUI:54A3FA* + ID_OUI_FROM_DATABASE=BQT Solutions (Australia)Pty Ltd + +OUI:9023EC* + ID_OUI_FROM_DATABASE=Availink, Inc. + +OUI:7467F7* + ID_OUI_FROM_DATABASE=Zebra Technologoes + +OUI:3891D5* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:90DFFB* + ID_OUI_FROM_DATABASE=HOMERIDER SYSTEMS + +OUI:3C831E* + ID_OUI_FROM_DATABASE=CKD Corporation + +OUI:381C23* + ID_OUI_FROM_DATABASE=Hilan Technology CO.,LTD + +OUI:E03676* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3CB72B* + ID_OUI_FROM_DATABASE=PLUMgrid Inc + +OUI:243184* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:24DA9B* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:3052CB* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:B8B2EB* + ID_OUI_FROM_DATABASE=Googol Technology (HK) Limited + +OUI:C40049* + ID_OUI_FROM_DATABASE=Kamama + +OUI:50A9DE* + ID_OUI_FROM_DATABASE=Smartcom - Bulgaria AD + +OUI:E8DED6* + ID_OUI_FROM_DATABASE=Intrising Networks, Inc. + +OUI:B844D9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DC2B2A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C10D4* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:089B4B* + ID_OUI_FROM_DATABASE=iKuai Networks + +OUI:3C7873* + ID_OUI_FROM_DATABASE=Airsonics + +OUI:BC5FF6* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:C8F9C8* + ID_OUI_FROM_DATABASE=NewSharp Technology(SuZhou)Co,Ltd + +OUI:3C5CC3* + ID_OUI_FROM_DATABASE=Shenzhen First Blue Chip Technology Ltd + +OUI:A8741D* + ID_OUI_FROM_DATABASE=PHOENIX CONTACT Electronics GmbH + +OUI:A4C138* + ID_OUI_FROM_DATABASE=Telink Semiconductor (Taipei) Co. Ltd. + +OUI:D8EFCD* + ID_OUI_FROM_DATABASE=Nokia + +OUI:EC0133* + ID_OUI_FROM_DATABASE=TRINUS SYSTEMS INC. + +OUI:1C56FE* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:7CA23E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:501AA5* + ID_OUI_FROM_DATABASE=GN Netcom A/S + +OUI:F09A51* + ID_OUI_FROM_DATABASE=Shanghai Viroyal Electronic Technology Company Limited + +OUI:9870E8* + ID_OUI_FROM_DATABASE=INNATECH SDN BHD + +OUI:50DF95* + ID_OUI_FROM_DATABASE=Lytx + +OUI:584925* + ID_OUI_FROM_DATABASE=E3 Enterprise + +OUI:94F278* + ID_OUI_FROM_DATABASE=Elma Electronic + +OUI:E8BDD1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3481F4* + ID_OUI_FROM_DATABASE=SST Taiwan Ltd. + +OUI:F4B8A7* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:58F102* + ID_OUI_FROM_DATABASE=BLU Products Inc. + +OUI:B869C2* + ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd. + +OUI:2CC548* + ID_OUI_FROM_DATABASE=IAdea Corporation + +OUI:307CB2* + ID_OUI_FROM_DATABASE=ANOV FRANCE + +OUI:90D8F3* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:444CA8* + ID_OUI_FROM_DATABASE=Arista Networks + +OUI:FCE33C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:BC6A2F* + ID_OUI_FROM_DATABASE=Henge Docks LLC + +OUI:E4907E* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:48066A* + ID_OUI_FROM_DATABASE=Tempered Networks, Inc. + +OUI:1CF03E* + ID_OUI_FROM_DATABASE=Wearhaus Inc. + +OUI:DCDB70* + ID_OUI_FROM_DATABASE=Tonfunk Systementwicklung und Service GmbH + +OUI:C47D46* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:68EDA4* + ID_OUI_FROM_DATABASE=Shenzhen Seavo Technology Co.,Ltd + +OUI:B899B0* + ID_OUI_FROM_DATABASE=Cohere Technologies + +OUI:2CC5D3* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:80C5E6* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:D85DEF* + ID_OUI_FROM_DATABASE=Busch-Jaeger Elektro GmbH + +OUI:10DF8B* + ID_OUI_FROM_DATABASE=Shenzhen CareDear Communication Technology Co.,Ltd + +OUI:00A784* + ID_OUI_FROM_DATABASE=ITX security + +OUI:800184* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:38FACA* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:44C69B* + ID_OUI_FROM_DATABASE=Wuhan Feng Tian Information Network CO.,LTD + +OUI:C02567* + ID_OUI_FROM_DATABASE=Nexxt Solutions + +OUI:B46D35* + ID_OUI_FROM_DATABASE=Dalian Seasky Automation Co;Ltd + +OUI:B89ACD* + ID_OUI_FROM_DATABASE=ELITE OPTOELECTRONIC(ASIA)CO.,LTD + +OUI:241C04* + ID_OUI_FROM_DATABASE=SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD. + +OUI:F8CFC5* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:BCF811* + ID_OUI_FROM_DATABASE=Xiamen DNAKE Technology Co.,Ltd + +OUI:A8827F* + ID_OUI_FROM_DATABASE=CIBN Oriental Network(Beijing) CO.,Ltd + +OUI:609C9F* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:900A39* + ID_OUI_FROM_DATABASE=Wiio, Inc. + +OUI:C4693E* + ID_OUI_FROM_DATABASE=Turbulence Design Inc. + +OUI:1C8341* + ID_OUI_FROM_DATABASE=Hefei Bitland Information Technology Co.Ltd + +OUI:4011DC* + ID_OUI_FROM_DATABASE=Sonance + +OUI:249EAB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:DC56E6* + ID_OUI_FROM_DATABASE=Shenzhen Bococom Technology Co.,LTD + +OUI:5CA178* + ID_OUI_FROM_DATABASE=TableTop Media (dba Ziosk) + +OUI:702A7D* + ID_OUI_FROM_DATABASE=EpSpot AB + +OUI:B8B3DC* + ID_OUI_FROM_DATABASE=DEREK (SHAOGUAN) LIMITED + +OUI:6C1E70* + ID_OUI_FROM_DATABASE=Guangzhou YBDS IT Co.,Ltd + +OUI:C8E130* + ID_OUI_FROM_DATABASE=Milkyway Group Ltd + +OUI:8833BE* + ID_OUI_FROM_DATABASE=Ivenix, Inc. + +OUI:34CC28* + ID_OUI_FROM_DATABASE=Nexpring Co. LTD., + +OUI:144146* + ID_OUI_FROM_DATABASE=Honeywell (China) Co., LTD + +OUI:F41563* + ID_OUI_FROM_DATABASE=F5 Networks, Inc. + +OUI:C4EA1D* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:20E407* + ID_OUI_FROM_DATABASE=Spark srl + +OUI:887384* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:584704* + ID_OUI_FROM_DATABASE=Shenzhen Webridge Technology Co.,Ltd + +OUI:B856BD* + ID_OUI_FROM_DATABASE=ITT LLC + +OUI:107873* + ID_OUI_FROM_DATABASE=Shenzhen Jinkeyi Communication Co., Ltd. + +OUI:D45556* + ID_OUI_FROM_DATABASE=Fiber Mountain Inc. + +OUI:F01E34* + ID_OUI_FROM_DATABASE=ORICO Technologies Co., Ltd + +OUI:74A063* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A89008* + ID_OUI_FROM_DATABASE=Beijing Yuecheng Technology Co. Ltd. + +OUI:183864* + ID_OUI_FROM_DATABASE=CAP-TECH INTERNATIONAL CO., LTD. + +OUI:08D34B* + ID_OUI_FROM_DATABASE=Techman Electronics (Changshu) Co., Ltd. + +OUI:C808E9* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:78ACBF* + ID_OUI_FROM_DATABASE=Igneous Systems + +OUI:206274* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:5CCCFF* + ID_OUI_FROM_DATABASE=Techroutes Network Pvt Ltd + +OUI:844BB7* + ID_OUI_FROM_DATABASE=Beijing Sankuai Online Technology Co.,Ltd + +OUI:148F21* + ID_OUI_FROM_DATABASE=Garmin International + +OUI:3C6A9D* + ID_OUI_FROM_DATABASE=Dexatek Technology LTD. + +OUI:14893E* + ID_OUI_FROM_DATABASE=VIXTEL TECHNOLOGIES LIMTED + +OUI:60F189* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:74A34A* + ID_OUI_FROM_DATABASE=ZIMI CORPORATION + +OUI:98F5A9* + ID_OUI_FROM_DATABASE=OHSUNG ELECTRONICS CO.,LTD. + +OUI:D89341* + ID_OUI_FROM_DATABASE=General Electric Global Research + +OUI:F4645D* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:30D587* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:1436C6* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:04C09C* + ID_OUI_FROM_DATABASE=Tellabs Inc. + +OUI:844464* + ID_OUI_FROM_DATABASE=ServerU Inc + +OUI:589B0B* + ID_OUI_FROM_DATABASE=Shineway Technologies, Inc. + +OUI:A48CDB* + ID_OUI_FROM_DATABASE=Lenovo + +OUI:4062B6* + ID_OUI_FROM_DATABASE=Tele system communication + +OUI:3C2C94* + ID_OUI_FROM_DATABASE=杭州德澜科技有限公司(HangZhou Delan Technology Co.,Ltd) + +OUI:78312B* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:C035C5* + ID_OUI_FROM_DATABASE=Prosoft Systems LTD + +OUI:F8B2F3* + ID_OUI_FROM_DATABASE=GUANGZHOU BOSMA TECHNOLOGY CO.,LTD + +OUI:1C7D22* + ID_OUI_FROM_DATABASE=Fuji Xerox Co., Ltd. + +OUI:7C11CD* + ID_OUI_FROM_DATABASE=QianTang Technology + +OUI:0492EE* + ID_OUI_FROM_DATABASE=iway AG + +OUI:F02A23* + ID_OUI_FROM_DATABASE=Creative Next Design + +OUI:8C9109* + ID_OUI_FROM_DATABASE=Toyoshima Electric Technoeogy(Suzhou) Co.,Ltd. + +OUI:307350* ID_OUI_FROM_DATABASE=Inpeco SA OUI:E8CC18* @@ -36299,9 +37799,6 @@ OUI:2497ED* OUI:104E07* ID_OUI_FROM_DATABASE=Shanghai Genvision Industries Co.,Ltd -OUI:4C11BF* - ID_OUI_FROM_DATABASE=ZHEJIANG DAHUA TECHNOLOGY CO.,LTD. - OUI:FCD5D9* ID_OUI_FROM_DATABASE=Shenzhen SDMC Technology Co., Ltd. @@ -36437,9 +37934,6 @@ OUI:7CD30A* OUI:3481C4* ID_OUI_FROM_DATABASE=AVM GmbH -OUI:885BDD* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. - OUI:085700* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. @@ -36596,9 +38090,6 @@ OUI:4CE1BB* OUI:8CDE99* ID_OUI_FROM_DATABASE=Comlab Inc. -OUI:2C9AA4* - ID_OUI_FROM_DATABASE=NGI SpA - OUI:B46698* ID_OUI_FROM_DATABASE=Zealabs srl @@ -37259,9 +38750,6 @@ OUI:E0D9A2* OUI:F0F669* ID_OUI_FROM_DATABASE=Motion Analysis Corporation -OUI:F0219D* - ID_OUI_FROM_DATABASE=Cal-Comp Electronics & Communications Company Ltd. - OUI:F8D7BF* ID_OUI_FROM_DATABASE=REV Ritter GmbH @@ -37973,9 +39461,6 @@ OUI:B4C799* OUI:70B921* ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD -OUI:948FEE* - ID_OUI_FROM_DATABASE=Hughes Telematics, Inc. - OUI:E8C320* ID_OUI_FROM_DATABASE=Austco Communication Systems Pty Ltd @@ -38891,9 +40376,6 @@ OUI:B40832* OUI:002720* ID_OUI_FROM_DATABASE=NEW-SOL COM -OUI:00271C* - ID_OUI_FROM_DATABASE=MERCURY CORPORATION - OUI:002712* ID_OUI_FROM_DATABASE=MaxVision LLC @@ -39248,9 +40730,6 @@ OUI:002410* OUI:002409* ID_OUI_FROM_DATABASE=The Toro Company -OUI:0023F7* - ID_OUI_FROM_DATABASE=Private - OUI:0023FD* ID_OUI_FROM_DATABASE=AFT Atlas Fahrzeugtechnik GmbH @@ -39317,9 +40796,6 @@ OUI:002485* OUI:002480* ID_OUI_FROM_DATABASE=Meteocontrol GmbH -OUI:002448* - ID_OUI_FROM_DATABASE=SpiderCloud Wireless, Inc - OUI:00244A* ID_OUI_FROM_DATABASE=Voyant International @@ -39707,9 +41183,6 @@ OUI:002189* OUI:002184* ID_OUI_FROM_DATABASE=POWERSOFT SRL -OUI:002183* - ID_OUI_FROM_DATABASE=VATECH HYDRO - OUI:00217D* ID_OUI_FROM_DATABASE=PYXIS S.R.L. @@ -40700,9 +42173,6 @@ OUI:0017A5* OUI:0017A0* ID_OUI_FROM_DATABASE=RoboTech srl -OUI:00179B* - ID_OUI_FROM_DATABASE=Chant Sincere CO., LTD. - OUI:00170F* ID_OUI_FROM_DATABASE=Cisco Systems, Inc @@ -42086,9 +43556,6 @@ OUI:000D32* OUI:000D31* ID_OUI_FROM_DATABASE=Compellent Technologies, Inc. -OUI:000D2C* - ID_OUI_FROM_DATABASE=Patapsco Designs Ltd - OUI:000D25* ID_OUI_FROM_DATABASE=SANDEN CORPORATION @@ -42383,9 +43850,6 @@ OUI:000B9E* OUI:000B27* ID_OUI_FROM_DATABASE=Scion Corporation -OUI:000B2E* - ID_OUI_FROM_DATABASE=Cal-Comp Electronics (Thailand) Public Company Limited Taipe - OUI:000B1B* ID_OUI_FROM_DATABASE=Systronix, Inc. @@ -42875,9 +44339,6 @@ OUI:00071B* OUI:000722* ID_OUI_FROM_DATABASE=The Nielsen Company -OUI:00071C* - ID_OUI_FROM_DATABASE=AT&T Fixed Wireless Services - OUI:00070A* ID_OUI_FROM_DATABASE=Unicom Automation Co., Ltd. @@ -44192,9 +45653,6 @@ OUI:0050A5* OUI:005000* ID_OUI_FROM_DATABASE=NEXO COMMUNICATIONS, INC. -OUI:00D071* - ID_OUI_FROM_DATABASE=ECHELON CORP. - OUI:00D066* ID_OUI_FROM_DATABASE=WINTRISS ENGINEERING CORP. @@ -44606,9 +46064,6 @@ OUI:00E060* OUI:00E0A2* ID_OUI_FROM_DATABASE=MICROSLATE INC. -OUI:00E06C* - ID_OUI_FROM_DATABASE=Ultra Electronics Limited (AEP Networks) - OUI:00E0CE* ID_OUI_FROM_DATABASE=ARN @@ -44642,9 +46097,6 @@ OUI:006002* OUI:006061* ID_OUI_FROM_DATABASE=WHISTLE COMMUNICATIONS CORP. -OUI:0060BD* - ID_OUI_FROM_DATABASE=HUBBELL-PULSECOM - OUI:00E0A1* ID_OUI_FROM_DATABASE=HIMA PAUL HILDEBRANDT GmbH Co. KG @@ -45602,9 +47054,6 @@ OUI:0000E7* OUI:0000F3* ID_OUI_FROM_DATABASE=GANDALF DATA LIMITED -OUI:000064* - ID_OUI_FROM_DATABASE=Yokogawa Electric Corporation - OUI:00002C* ID_OUI_FROM_DATABASE=AUTOTOTE LIMITED @@ -45668,9 +47117,6 @@ OUI:0000DC* OUI:000024* ID_OUI_FROM_DATABASE=CONNECT AS -OUI:000048* - ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION - OUI:008030* ID_OUI_FROM_DATABASE=NEXUS ELECTRONICS @@ -45749,9 +47195,6 @@ OUI:080039* OUI:080030* ID_OUI_FROM_DATABASE=NETWORK RESEARCH CORPORATION -OUI:080027* - ID_OUI_FROM_DATABASE=Cadmus Computer Systems - OUI:00009B* ID_OUI_FROM_DATABASE=INFORMATION INTERNATIONAL, INC @@ -45923,12 +47366,6 @@ OUI:9068C3* OUI:408805* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:A4A1C2* - ID_OUI_FROM_DATABASE=Ericsson AB - -OUI:348446* - ID_OUI_FROM_DATABASE=Ericsson AB - OUI:AC2B6E* ID_OUI_FROM_DATABASE=Intel Corporate @@ -46676,9 +48113,6 @@ OUI:54511B* OUI:68536C* ID_OUI_FROM_DATABASE=SPnS Co.,Ltd -OUI:64CC2E* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - OUI:005BA1* ID_OUI_FROM_DATABASE=shanghai huayuan chuangxin software CO., LTD. @@ -47048,9 +48482,6 @@ OUI:40F413* OUI:2C094D* ID_OUI_FROM_DATABASE=Raptor Engineering, LLC -OUI:B0E235* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - OUI:88797E* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company @@ -47324,9 +48755,6 @@ OUI:7C0623* OUI:002555* ID_OUI_FROM_DATABASE=Visonic Technologies 1993 Ltd. -OUI:009058* - ID_OUI_FROM_DATABASE=Ultra Electronics Limited (AEP Networks) - OUI:48FD8E* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD @@ -47444,6 +48872,27 @@ OUI:981E0F* OUI:548CA0* ID_OUI_FROM_DATABASE=Liteon Technology Corporation +OUI:001AAD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00195E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001404* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001BDD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0023A2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001E8D* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0003E0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + OUI:707E43* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. @@ -47453,9 +48902,6 @@ OUI:1C1448* OUI:A47AA4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:001AAD* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. - OUI:E83EFC* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. @@ -47465,25 +48911,25 @@ OUI:E8892C* OUI:001DD3* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:3CDFA9* +OUI:0015D1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:8C09F4* +OUI:203D66* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:083E0C* +OUI:6455B1* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:D404CD* +OUI:C005C2* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:203D66* +OUI:3CDFA9* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:6455B1* +OUI:8C09F4* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:C005C2* +OUI:083E0C* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:001225* @@ -47492,10 +48938,10 @@ OUI:001225* OUI:00128A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:0003E0* +OUI:D404CD* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:0015D1* +OUI:002493* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:E46449* @@ -47519,10 +48965,10 @@ OUI:94E8C5* OUI:F8A097* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:BC644B* +OUI:00230B* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:347A60* +OUI:001B52* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:0023ED* @@ -47546,38 +48992,62 @@ OUI:3C754A* OUI:40FC89* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:002493* +OUI:BC644B* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:00195E* +OUI:347A60* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:001404* +OUI:84E058* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:001BDD* +OUI:003676* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:0023A2* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:001CA8* + ID_OUI_FROM_DATABASE=AirTies Wireless Networks -OUI:001E8D* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:0017D5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00230B* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:001247* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:001B52* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:E4121D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:84E058* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:684898* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:003676* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:F409D8* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) -OUI:001CA8* - ID_OUI_FROM_DATABASE=AirTies Wireless Networks +OUI:B479A7* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:002339* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D487D8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:184617* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5001BB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:380A94* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D857EF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:1C66AA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:58C38B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:001EE2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd @@ -47603,36 +49073,6 @@ OUI:00265D* OUI:D4E8B2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:0017D5* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:001247* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:78521A* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:E4121D* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:684898* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:F409D8* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) - -OUI:B479A7* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) - -OUI:18D276* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:1C66AA* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:58C38B* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - OUI:0808C2* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd @@ -47645,24 +49085,6 @@ OUI:D890E8* OUI:34AA8B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:002339* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:D487D8* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:184617* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:5001BB* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:380A94* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:D857EF* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - OUI:24C696* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd @@ -47678,14 +49100,11 @@ OUI:343111* OUI:34BE00* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:50CCF8* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. - -OUI:980C82* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. +OUI:78521A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:002119* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. +OUI:18D276* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD OUI:7825AD* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd @@ -47705,26 +49124,35 @@ OUI:00166C* OUI:E47CF9* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:002454* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:90187C* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. -OUI:5C0A5B* +OUI:FC1F19* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. -OUI:90187C* +OUI:50CCF8* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. -OUI:FC1F19* +OUI:980C82* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:002119* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. +OUI:002454* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + OUI:20D5BF* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:30CDA7* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00749C* - ID_OUI_FROM_DATABASE=RUIJIE NETWORKS CO., LTD. +OUI:5C0A5B* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:543530* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. OUI:300ED5* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. @@ -47744,84 +49172,81 @@ OUI:001DD9* OUI:001FE2* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:48E244* +OUI:002269* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:30F772* +OUI:40490F* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:90489A* +OUI:28565A* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:543530* +OUI:001F3A* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:C03896* +OUI:506313* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:2C337A* +OUI:78E400* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:ACD1B8* +OUI:8C7CB5* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:9439E5* +OUI:EC55F9* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:506313* +OUI:C03896* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:78E400* +OUI:2C337A* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:40490F* +OUI:ACD1B8* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:28565A* +OUI:48E244* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:001F3A* +OUI:30F772* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:002269* +OUI:90489A* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:5C8613* - ID_OUI_FROM_DATABASE=Beijing Zhoenet Technology Co., Ltd - -OUI:8C7CB5* +OUI:9439E5* ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:EC55F9* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:5C8613* + ID_OUI_FROM_DATABASE=Beijing Zhoenet Technology Co., Ltd OUI:C8B21E* ID_OUI_FROM_DATABASE=CHIPSEA TECHNOLOGIES (SHENZHEN) CORP. +OUI:503F98* + ID_OUI_FROM_DATABASE=CMITECH + OUI:B072BF* ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. OUI:600B03* ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited -OUI:503F98* - ID_OUI_FROM_DATABASE=CMITECH - OUI:C09F05* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD OUI:AC63BE* ID_OUI_FROM_DATABASE=Amazon Technologies Inc. -OUI:38521A* - ID_OUI_FROM_DATABASE=Nokia - OUI:A41437* ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. OUI:884CCF* ID_OUI_FROM_DATABASE=Pulzze Systems, Inc +OUI:38521A* + ID_OUI_FROM_DATABASE=Nokia + OUI:84DBFC* ID_OUI_FROM_DATABASE=Nokia @@ -47831,24 +49256,24 @@ OUI:143E60* OUI:D4E33F* ID_OUI_FROM_DATABASE=Nokia -OUI:00233A* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:C87E75* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - OUI:5454CF* ID_OUI_FROM_DATABASE=PROBEDIGITAL CO.,LTD OUI:F0D5BF* ID_OUI_FROM_DATABASE=Intel Corporate -OUI:748A69* - ID_OUI_FROM_DATABASE=Korea Image Technology Co., Ltd +OUI:C87E75* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00233A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:1C9D3E* ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. +OUI:748A69* + ID_OUI_FROM_DATABASE=Korea Image Technology Co., Ltd + OUI:30B64F* ID_OUI_FROM_DATABASE=Juniper Networks @@ -47861,14 +49286,14 @@ OUI:008731* OUI:B4EFFA* ID_OUI_FROM_DATABASE=Lemobile Information Technology (Beijing) Co., Ltd. -OUI:0005EE* - ID_OUI_FROM_DATABASE=Vanderbilt International (SWE) AB - OUI:9495A0* ID_OUI_FROM_DATABASE=Google, Inc. -OUI:CCFD17* - ID_OUI_FROM_DATABASE=TCT mobile ltd +OUI:0005EE* + ID_OUI_FROM_DATABASE=Vanderbilt International (SWE) AB + +OUI:38D547* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. OUI:4CF95D* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD @@ -47879,14 +49304,8 @@ OUI:8421F1* OUI:707990* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:38D547* - ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. - -OUI:248894* - ID_OUI_FROM_DATABASE=shenzhen lensun Communication Technology LTD - -OUI:60A4D0* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:CCFD17* + ID_OUI_FROM_DATABASE=TCT mobile ltd OUI:3C8BCD* ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd @@ -47894,8 +49313,11 @@ OUI:3C8BCD* OUI:E43ED7* ID_OUI_FROM_DATABASE=Arcadyan Corporation -OUI:38A4ED* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd +OUI:248894* + ID_OUI_FROM_DATABASE=shenzhen lensun Communication Technology LTD + +OUI:60A4D0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:00B0CE* ID_OUI_FROM_DATABASE=Viveris Technologies @@ -47921,33 +49343,33 @@ OUI:9840BB* OUI:CC2D83* ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD -OUI:4C3275* - ID_OUI_FROM_DATABASE=Apple, Inc. - OUI:E04FBD* ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD -OUI:ACE77B* - ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD - OUI:00B0E1* ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:4C3275* + ID_OUI_FROM_DATABASE=Apple, Inc. + OUI:0006F4* ID_OUI_FROM_DATABASE=Prime Electronics & Satellitics Inc. +OUI:ACE77B* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + OUI:24A43C* ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. -OUI:28EE52* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. - OUI:D4E90B* ID_OUI_FROM_DATABASE=CVT CO.,LTD OUI:788A20* ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. +OUI:28EE52* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + OUI:905C44* ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. @@ -47972,12 +49394,12 @@ OUI:B83A9D* OUI:00BBC1* ID_OUI_FROM_DATABASE=CANON INC. -OUI:2CC260* - ID_OUI_FROM_DATABASE=Oracle Corporation - OUI:1C14B3* ID_OUI_FROM_DATABASE=Airwire Technologies +OUI:2CC260* + ID_OUI_FROM_DATABASE=Oracle Corporation + OUI:407183* ID_OUI_FROM_DATABASE=Juniper Networks @@ -47987,6 +49409,330 @@ OUI:0059DC* OUI:14612F* ID_OUI_FROM_DATABASE=Avaya Inc +OUI:ACF85C* + ID_OUI_FROM_DATABASE=Private + +OUI:00749C* + ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD + +OUI:00271C* + ID_OUI_FROM_DATABASE=MERCURY CORPORATION + +OUI:E0D9E3* + ID_OUI_FROM_DATABASE=Eltex Enterprise Ltd. + +OUI:5098F3* + ID_OUI_FROM_DATABASE=Rheem Australia Pty Ltd + +OUI:701CE7* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:CC9470* + ID_OUI_FROM_DATABASE=Kinestral Technologies, Inc. + +OUI:446AB7* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:F0219D* + ID_OUI_FROM_DATABASE=Cal-Comp Electronics & Communications Company Ltd. + +OUI:000B2E* + ID_OUI_FROM_DATABASE=Cal-Comp Electronics & Communications Company Ltd. + +OUI:885BDD* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. + +OUI:08EA44* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. + +OUI:506B8D* + ID_OUI_FROM_DATABASE=Nutanix + +OUI:0038DF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C9924* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:006BF1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CC81DA* + ID_OUI_FROM_DATABASE=SHANGHAI PHICOMM COMMUNICATION CO.,LTD + +OUI:20D25F* + ID_OUI_FROM_DATABASE=SmartCap Technologies + +OUI:3CFA43* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:145F94* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4C11BF* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:EC0D9A* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:000064* + ID_OUI_FROM_DATABASE=Yokogawa Digital Computer Corporation + +OUI:0023F7* + ID_OUI_FROM_DATABASE=Private + +OUI:90D7BE* + ID_OUI_FROM_DATABASE=Wavelab Global Inc. + +OUI:686975* + ID_OUI_FROM_DATABASE=Angler Labs Inc + +OUI:002448* + ID_OUI_FROM_DATABASE=SpiderCloud Wireless, Inc + +OUI:7C03C9* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:64DB43* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + +OUI:D058A8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D071C4* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:48F07B* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO.,LTD. + +OUI:3C80AA* + ID_OUI_FROM_DATABASE=Ransnet Singapore Pte Ltd + +OUI:7CEBAE* + ID_OUI_FROM_DATABASE=Ridgeline Instruments + +OUI:E89EB4* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:D4970B* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:64CC2E* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:B0E235* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:38A4ED* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:F48B32* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:0060BD* + ID_OUI_FROM_DATABASE=Enginuity Communications + +OUI:AC83F3* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:707C69* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:18DBF2* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:000048* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:C0BFC0* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A08CF8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:54B56C* + ID_OUI_FROM_DATABASE=Xi'an NovaStar Tech Co., Ltd + +OUI:FC3CE9* + ID_OUI_FROM_DATABASE=Tsingtong Technologies Co, Ltd. + +OUI:04B648* + ID_OUI_FROM_DATABASE=ZENNER + +OUI:FC10C6* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:344CC8* + ID_OUI_FROM_DATABASE=Echodyne Corp + +OUI:948FEE* + ID_OUI_FROM_DATABASE=Verizon Telematics + +OUI:5C4A1F* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:0C8DDB* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:B0F963* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:E4E4AB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:58404E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DC0C5C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:2C200B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:98B6E9* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:8809AF* + ID_OUI_FROM_DATABASE=Masimo Corporation + +OUI:00E06C* + ID_OUI_FROM_DATABASE=Ultra Electronics Command & Control Systems + +OUI:009058* + ID_OUI_FROM_DATABASE=Ultra Electronics Command & Control Systems + +OUI:F8983A* + ID_OUI_FROM_DATABASE=Leeman International (HongKong) Limited + +OUI:4CECEF* + ID_OUI_FROM_DATABASE=Soraa, Inc. + +OUI:702D84* + ID_OUI_FROM_DATABASE=i4C Innovations + +OUI:CC9F7A* + ID_OUI_FROM_DATABASE=Chiun Mai Communication Systems, Inc + +OUI:446246* + ID_OUI_FROM_DATABASE=Comat AG + +OUI:C8AA55* + ID_OUI_FROM_DATABASE=Hunan Comtom Electronic Incorporated Co.,Ltd + +OUI:142FFD* + ID_OUI_FROM_DATABASE=LT SECURITY INC + +OUI:000D2C* + ID_OUI_FROM_DATABASE=Net2Edge Limited + +OUI:ECE154* + ID_OUI_FROM_DATABASE=Beijing Unisound Information Technology Co.,Ltd. + +OUI:60C658* + ID_OUI_FROM_DATABASE=PHYTRONIX Co.,Ltd. + +OUI:38454C* + ID_OUI_FROM_DATABASE=Light Labs, Inc. + +OUI:C894BB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D0FF98* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5004B8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:10B1F8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:14ABC5* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A462DF* + ID_OUI_FROM_DATABASE=DS Global. Co., LTD + +OUI:50D213* + ID_OUI_FROM_DATABASE=CviLux Corporation + +OUI:44D437* + ID_OUI_FROM_DATABASE=Inteno Broadband Technology AB + +OUI:78AF58* + ID_OUI_FROM_DATABASE=GIMASI SA + +OUI:00071C* + ID_OUI_FROM_DATABASE=AT&T + +OUI:2C9AA4* + ID_OUI_FROM_DATABASE=Eolo SpA + +OUI:002183* + ID_OUI_FROM_DATABASE=ANDRITZ HYDRO GmbH + +OUI:8404D2* + ID_OUI_FROM_DATABASE=Kirale Technologies SL + +OUI:083E5D* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:749CE3* + ID_OUI_FROM_DATABASE=KodaCloud Canada, Inc + +OUI:CC2D21* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:8C78D7* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:3CBD3E* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd. + +OUI:2C4D54* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:349672* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:00179B* + ID_OUI_FROM_DATABASE=CHANT SINCERE CO.,LTD + +OUI:080027* + ID_OUI_FROM_DATABASE=PCS Systemtechnik GmbH + +OUI:348446* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:A4A1C2* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:B0F1EC* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:B0C46C* + ID_OUI_FROM_DATABASE=Senseit + +OUI:105611* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:148951* + ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd + +OUI:F87588* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:BC3F8F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E4A749* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:04DEF2* + ID_OUI_FROM_DATABASE=Shenzhen ECOM Technology Co. Ltd + +OUI:00D071* + ID_OUI_FROM_DATABASE=ECHELON CORP. + OUI:D86CE9* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS @@ -48080,12 +49826,6 @@ OUI:C056E3* OUI:C8E7D8* ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. -OUI:E01C41* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. - -OUI:D854A2* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. - OUI:9CEFD5* ID_OUI_FROM_DATABASE=Panda Wireless, Inc. @@ -48140,9 +49880,6 @@ OUI:C44044* OUI:3898D8* ID_OUI_FROM_DATABASE=MERITECH CO.,LTD -OUI:C8675E* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. - OUI:000CF1* ID_OUI_FROM_DATABASE=Intel Corporation @@ -48293,9 +50030,6 @@ OUI:ACE87B* OUI:688F84* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:ACF7F3* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - OUI:889471* ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. @@ -48494,18 +50228,6 @@ OUI:DCCEC1* OUI:84B261* ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:009EC8* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:7C1DD9* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:A086C6* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:584498* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - OUI:70E422* ID_OUI_FROM_DATABASE=Cisco Systems, Inc @@ -49235,9 +50957,6 @@ OUI:ACC73F* OUI:18BDAD* ID_OUI_FROM_DATABASE=L-TECH CORPORATION -OUI:44D244* - ID_OUI_FROM_DATABASE=Seiko Epson Corporation - OUI:10C07C* ID_OUI_FROM_DATABASE=Blu-ray Disc Association @@ -51428,9047 +53147,9590 @@ OUI:C0626B* OUI:74D0DC* ID_OUI_FROM_DATABASE=ERICSSON AB -OUI:B4B88D* - ID_OUI_FROM_DATABASE=Thuh Company +OUI:B4B88D* + ID_OUI_FROM_DATABASE=Thuh Company + +OUI:60F59C* + ID_OUI_FROM_DATABASE=CRU-Dataport + +OUI:C4108A* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:4C73A5* + ID_OUI_FROM_DATABASE=KOVE + +OUI:F86971* + ID_OUI_FROM_DATABASE=Seibu Electric Co., + +OUI:44AA27* + ID_OUI_FROM_DATABASE=udworks Co., Ltd. + +OUI:6CAD3F* + ID_OUI_FROM_DATABASE=Hubbell Building Automation, Inc. + +OUI:8427CE* + ID_OUI_FROM_DATABASE=Corporation of the Presiding Bishop of The Church of Jesus Christ of Latter-day Saints + +OUI:D428B2* + ID_OUI_FROM_DATABASE=ioBridge, Inc. + +OUI:90B8D0* + ID_OUI_FROM_DATABASE=Joyent, Inc. + +OUI:909060* + ID_OUI_FROM_DATABASE=RSI VIDEO TECHNOLOGIES + +OUI:281471* + ID_OUI_FROM_DATABASE=Lantis co., LTD. + +OUI:1407E0* + ID_OUI_FROM_DATABASE=Abrantix AG + +OUI:DCCF94* + ID_OUI_FROM_DATABASE=Beijing Rongcheng Hutong Technology Co., Ltd. + +OUI:18E288* + ID_OUI_FROM_DATABASE=STT Condigi + +OUI:68876B* + ID_OUI_FROM_DATABASE=INQ Mobile Limited + +OUI:9866EA* + ID_OUI_FROM_DATABASE=Industrial Control Communications, Inc. + +OUI:F4A52A* + ID_OUI_FROM_DATABASE=Hawa Technologies Inc + +OUI:90CF15* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:B8D49D* + ID_OUI_FROM_DATABASE=M Seven System Ltd. + +OUI:B0A10A* + ID_OUI_FROM_DATABASE=Pivotal Systems Corporation + +OUI:48F47D* + ID_OUI_FROM_DATABASE=TechVision Holding Internation Limited + +OUI:6C391D* + ID_OUI_FROM_DATABASE=Beijing ZhongHuaHun Network Information center + +OUI:64D241* + ID_OUI_FROM_DATABASE=Keith & Koep GmbH + +OUI:101212* + ID_OUI_FROM_DATABASE=Vivo International Corporation Pty Ltd + +OUI:5087B8* + ID_OUI_FROM_DATABASE=Nuvyyo Inc + +OUI:E41289* + ID_OUI_FROM_DATABASE=topsystem Systemhaus GmbH + +OUI:A4134E* + ID_OUI_FROM_DATABASE=Luxul + +OUI:B09928* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:8C11CB* + ID_OUI_FROM_DATABASE=ABUS Security-Center GmbH & Co. KG + +OUI:806459* + ID_OUI_FROM_DATABASE=Nimbus Inc. + +OUI:A45A1C* + ID_OUI_FROM_DATABASE=smart-electronic GmbH + +OUI:8C89A5* + ID_OUI_FROM_DATABASE=Micro-Star INT'L CO., LTD + +OUI:3C672C* + ID_OUI_FROM_DATABASE=Sciovid Inc. + +OUI:18D071* + ID_OUI_FROM_DATABASE=DASAN CO., LTD. + +OUI:38D135* + ID_OUI_FROM_DATABASE=EasyIO Corporation Sdn. Bhd. + +OUI:184E94* + ID_OUI_FROM_DATABASE=MESSOA TECHNOLOGIES INC. + +OUI:94D93C* + ID_OUI_FROM_DATABASE=ENELPS + +OUI:DC9B1E* + ID_OUI_FROM_DATABASE=Intercom, Inc. + +OUI:5C7757* + ID_OUI_FROM_DATABASE=Haivision Network Video + +OUI:E8B4AE* + ID_OUI_FROM_DATABASE=Shenzhen C&D Electronics Co.,Ltd + +OUI:C45600* + ID_OUI_FROM_DATABASE=Galleon Embedded Computing + +OUI:E42FF6* + ID_OUI_FROM_DATABASE=Unicore communication Inc. + +OUI:B8F4D0* + ID_OUI_FROM_DATABASE=Herrmann Ultraschalltechnik GmbH & Co. Kg + +OUI:B4F323* + ID_OUI_FROM_DATABASE=PETATEL INC. + +OUI:C81E8E* + ID_OUI_FROM_DATABASE=ADV Security (S) Pte Ltd + +OUI:ACCABA* + ID_OUI_FROM_DATABASE=Midokura Co., Ltd. + +OUI:9C417C* + ID_OUI_FROM_DATABASE=Hame Technology Co., Limited + +OUI:10768A* + ID_OUI_FROM_DATABASE=EoCell + +OUI:044665* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:D0131E* + ID_OUI_FROM_DATABASE=Sunrex Technology Corp + +OUI:380197* + ID_OUI_FROM_DATABASE=TSST Global,Inc + +OUI:B40142* + ID_OUI_FROM_DATABASE=GCI Science & Technology Co.,LTD + +OUI:846EB1* + ID_OUI_FROM_DATABASE=Park Assist LLC + +OUI:6C504D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C0C1C0* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:1CBD0E* + ID_OUI_FROM_DATABASE=Amplified Engineering Pty Ltd + +OUI:F0A764* + ID_OUI_FROM_DATABASE=GST Co., Ltd. + +OUI:A0F217* + ID_OUI_FROM_DATABASE=GE Medical System(China) Co., Ltd. + +OUI:643409* + ID_OUI_FROM_DATABASE=BITwave Pte Ltd + +OUI:20D5AB* + ID_OUI_FROM_DATABASE=Korea Infocom Co.,Ltd. + +OUI:F05849* + ID_OUI_FROM_DATABASE=CareView Communications + +OUI:BC15A6* + ID_OUI_FROM_DATABASE=Taiwan Jantek Electronics,Ltd. + +OUI:241A8C* + ID_OUI_FROM_DATABASE=Squarehead Technology AS + +OUI:1083D2* + ID_OUI_FROM_DATABASE=Microseven Systems, LLC + +OUI:F05D89* + ID_OUI_FROM_DATABASE=Dycon Limited + +OUI:AC02CF* + ID_OUI_FROM_DATABASE=RW Tecnologia Industria e Comercio Ltda + +OUI:9067B5* + ID_OUI_FROM_DATABASE=Alcatel-Lucent + +OUI:40987B* + ID_OUI_FROM_DATABASE=Aisino Corporation + +OUI:6C2E33* + ID_OUI_FROM_DATABASE=Accelink Technologies Co.,Ltd. + +OUI:4CEDDE* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:E8E08F* + ID_OUI_FROM_DATABASE=GRAVOTECH MARKING SAS + +OUI:78B6C1* + ID_OUI_FROM_DATABASE=AOBO Telecom Co.,Ltd + +OUI:B8BA68* + ID_OUI_FROM_DATABASE=Xi'an Jizhong Digital Communication Co.,Ltd + +OUI:BC38D2* + ID_OUI_FROM_DATABASE=Pandachip Limited + +OUI:14EE9D* + ID_OUI_FROM_DATABASE=AirNav Systems LLC + +OUI:48174C* + ID_OUI_FROM_DATABASE=MicroPower technologies + +OUI:F81037* + ID_OUI_FROM_DATABASE=Atopia Systems, LP + +OUI:64F987* + ID_OUI_FROM_DATABASE=Avvasi Inc. + +OUI:3C7437* + ID_OUI_FROM_DATABASE=RIM + +OUI:04209A* + ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company + +OUI:64DC01* + ID_OUI_FROM_DATABASE=Static Systems Group PLC + +OUI:1CF5E7* + ID_OUI_FROM_DATABASE=Turtle Industry Co., Ltd. + +OUI:9C4A7B* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:2C8065* + ID_OUI_FROM_DATABASE=HARTING Inc. of North America + +OUI:F8F014* + ID_OUI_FROM_DATABASE=RackWare Inc. + +OUI:E41C4B* + ID_OUI_FROM_DATABASE=V2 TECHNOLOGY, INC. + +OUI:E0143E* + ID_OUI_FROM_DATABASE=Modoosis Inc. + +OUI:5C6984* + ID_OUI_FROM_DATABASE=NUVICO + +OUI:204AAA* + ID_OUI_FROM_DATABASE=Hanscan Spain S.A. + +OUI:F02572* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:8091C0* + ID_OUI_FROM_DATABASE=AgileMesh, Inc. + +OUI:0CF0B4* + ID_OUI_FROM_DATABASE=Globalsat International Technology Ltd + +OUI:BCC61A* + ID_OUI_FROM_DATABASE=SPECTRA EMBEDDED SYSTEMS + +OUI:48DF1C* + ID_OUI_FROM_DATABASE=Wuhan NEC Fibre Optic Communications industry Co. Ltd + +OUI:D0D3FC* + ID_OUI_FROM_DATABASE=Mios, Ltd. + +OUI:989449* + ID_OUI_FROM_DATABASE=Skyworth Wireless Technology Ltd. + +OUI:C8DF7C* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:F8C678* + ID_OUI_FROM_DATABASE=Carefusion + +OUI:FC3598* + ID_OUI_FROM_DATABASE=Favite Inc. + +OUI:A0AAFD* + ID_OUI_FROM_DATABASE=EraThink Technologies Corp. + +OUI:801F02* + ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. + +OUI:E03E7D* + ID_OUI_FROM_DATABASE=data-complex GmbH + +OUI:A4E32E* + ID_OUI_FROM_DATABASE=Silicon & Software Systems Ltd. + +OUI:1C19DE* + ID_OUI_FROM_DATABASE=eyevis GmbH + +OUI:DC07C1* + ID_OUI_FROM_DATABASE=HangZhou QiYang Technology Co.,Ltd. + +OUI:D8FE8F* + ID_OUI_FROM_DATABASE=IDFone Co., Ltd. + +OUI:0006F6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:ACAB8D* + ID_OUI_FROM_DATABASE=Lyngso Marine A/S + +OUI:181456* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:E8995A* + ID_OUI_FROM_DATABASE=PiiGAB, Processinformation i Goteborg AB + +OUI:D4E32C* + ID_OUI_FROM_DATABASE=S. Siedle & Sohne + +OUI:68DCE8* + ID_OUI_FROM_DATABASE=PacketStorm Communications + +OUI:78223D* + ID_OUI_FROM_DATABASE=Affirmed Networks + +OUI:60C980* + ID_OUI_FROM_DATABASE=Trymus + +OUI:94CDAC* + ID_OUI_FROM_DATABASE=Creowave Oy + +OUI:F4DCDA* + ID_OUI_FROM_DATABASE=Zhuhai Jiahe Communication Technology Co., limited + +OUI:100D32* + ID_OUI_FROM_DATABASE=Embedian, Inc. + +OUI:D82986* + ID_OUI_FROM_DATABASE=Best Wish Technology LTD + +OUI:C03B8F* + ID_OUI_FROM_DATABASE=Minicom Digital Signage + +OUI:A4218A* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:6C0460* + ID_OUI_FROM_DATABASE=RBH Access Technologies Inc. + +OUI:5C864A* + ID_OUI_FROM_DATABASE=Secret Labs LLC + +OUI:B8BA72* + ID_OUI_FROM_DATABASE=Cynove + +OUI:C00D7E* + ID_OUI_FROM_DATABASE=Additech, Inc. + +OUI:68784C* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:6C626D* + ID_OUI_FROM_DATABASE=Micro-Star INT'L CO., LTD + +OUI:8841C1* + ID_OUI_FROM_DATABASE=ORBISAT DA AMAZONIA IND E AEROL SA + +OUI:18B209* + ID_OUI_FROM_DATABASE=Torrey Pines Logic, Inc + +OUI:3018CF* + ID_OUI_FROM_DATABASE=DEOS control systems GmbH + +OUI:4CF737* + ID_OUI_FROM_DATABASE=SamJi Electronics Co., Ltd + +OUI:40406B* + ID_OUI_FROM_DATABASE=Icomera + +OUI:1880CE* + ID_OUI_FROM_DATABASE=Barberry Solutions Ltd + +OUI:CC43E3* + ID_OUI_FROM_DATABASE=Trump s.a. + +OUI:6C22AB* + ID_OUI_FROM_DATABASE=Ainsworth Game Technology + +OUI:3C106F* + ID_OUI_FROM_DATABASE=ALBAHITH TECHNOLOGIES + +OUI:7CE044* + ID_OUI_FROM_DATABASE=NEON Inc + +OUI:64D02D* + ID_OUI_FROM_DATABASE=Next Generation Integration (NGI) + +OUI:A04041* + ID_OUI_FROM_DATABASE=SAMWONFA Co.,Ltd. + +OUI:788C54* + ID_OUI_FROM_DATABASE=Eltek Technologies LTD + +OUI:9411DA* + ID_OUI_FROM_DATABASE=ITF Fröschl GmbH + +OUI:10E8EE* + ID_OUI_FROM_DATABASE=PhaseSpace + +OUI:A47C1F* + ID_OUI_FROM_DATABASE=Cobham plc + +OUI:8C1F94* + ID_OUI_FROM_DATABASE=RF Surgical System Inc. + +OUI:74A4A7* + ID_OUI_FROM_DATABASE=QRS Music Technologies, Inc. + +OUI:8039E5* + ID_OUI_FROM_DATABASE=PATLITE CORPORATION + +OUI:BCFFAC* + ID_OUI_FROM_DATABASE=TOPCON CORPORATION + +OUI:602A54* + ID_OUI_FROM_DATABASE=CardioTek B.V. + +OUI:1C3DE7* + ID_OUI_FROM_DATABASE=Sigma Koki Co.,Ltd. + +OUI:482CEA* + ID_OUI_FROM_DATABASE=Motorola Inc Business Light Radios + +OUI:70E139* + ID_OUI_FROM_DATABASE=3view Ltd + +OUI:AC6123* + ID_OUI_FROM_DATABASE=Drivven, Inc. + +OUI:3C04BF* + ID_OUI_FROM_DATABASE=PRAVIS SYSTEMS Co.Ltd., + +OUI:443D21* + ID_OUI_FROM_DATABASE=Nuvolt + +OUI:749050* + ID_OUI_FROM_DATABASE=Renesas Electronics Corporation + +OUI:7CBB6F* + ID_OUI_FROM_DATABASE=Cosco Electronics Co., Ltd. + +OUI:D466A8* + ID_OUI_FROM_DATABASE=Riedo Networks GmbH + +OUI:98E165* + ID_OUI_FROM_DATABASE=Accutome + +OUI:EC66D1* + ID_OUI_FROM_DATABASE=B&W Group LTD + +OUI:385FC3* + ID_OUI_FROM_DATABASE=Yu Jeong System, Co.Ltd + +OUI:94857A* + ID_OUI_FROM_DATABASE=Evantage Industries Corp + +OUI:4451DB* + ID_OUI_FROM_DATABASE=Raytheon BBN Technologies + +OUI:64995D* + ID_OUI_FROM_DATABASE=LGE + +OUI:585076* + ID_OUI_FROM_DATABASE=Linear Equipamentos Eletronicos SA + +OUI:4083DE* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc + +OUI:8897DF* + ID_OUI_FROM_DATABASE=Entrypass Corporation Sdn. Bhd. + +OUI:0C15C5* + ID_OUI_FROM_DATABASE=SDTEC Co., Ltd. + +OUI:9803A0* + ID_OUI_FROM_DATABASE=ABB n.v. Power Quality Products -OUI:60F59C* - ID_OUI_FROM_DATABASE=CRU-Dataport +OUI:DCFAD5* + ID_OUI_FROM_DATABASE=STRONG Ges.m.b.H. -OUI:C4108A* +OUI:D84606* + ID_OUI_FROM_DATABASE=Silicon Valley Global Marketing + +OUI:689234* ID_OUI_FROM_DATABASE=Ruckus Wireless -OUI:4C73A5* - ID_OUI_FROM_DATABASE=KOVE +OUI:D0E347* + ID_OUI_FROM_DATABASE=Yoga -OUI:F86971* - ID_OUI_FROM_DATABASE=Seibu Electric Co., +OUI:84A991* + ID_OUI_FROM_DATABASE=Cyber Trans Japan Co.,Ltd. -OUI:44AA27* - ID_OUI_FROM_DATABASE=udworks Co., Ltd. +OUI:D81C14* + ID_OUI_FROM_DATABASE=Compacta International, Ltd. -OUI:6CAD3F* - ID_OUI_FROM_DATABASE=Hubbell Building Automation, Inc. +OUI:9088A2* + ID_OUI_FROM_DATABASE=IONICS TECHNOLOGY ME LTDA -OUI:8427CE* - ID_OUI_FROM_DATABASE=Corporation of the Presiding Bishop of The Church of Jesus Christ of Latter-day Saints +OUI:B0B8D5* + ID_OUI_FROM_DATABASE=Nanjing Nengrui Auto Equipment CO.,Ltd -OUI:D428B2* - ID_OUI_FROM_DATABASE=ioBridge, Inc. +OUI:8497B8* + ID_OUI_FROM_DATABASE=Memjet Inc. -OUI:90B8D0* - ID_OUI_FROM_DATABASE=Joyent, Inc. +OUI:A8556A* + ID_OUI_FROM_DATABASE=Pocketnet Technology Inc. -OUI:909060* - ID_OUI_FROM_DATABASE=RSI VIDEO TECHNOLOGIES +OUI:B081D8* + ID_OUI_FROM_DATABASE=I-sys Corp -OUI:281471* - ID_OUI_FROM_DATABASE=Lantis co., LTD. +OUI:206AFF* + ID_OUI_FROM_DATABASE=Atlas Elektronik UK Limited -OUI:1407E0* - ID_OUI_FROM_DATABASE=Abrantix AG +OUI:EC542E* + ID_OUI_FROM_DATABASE=Shanghai XiMei Electronic Technology Co. Ltd -OUI:DCCF94* - ID_OUI_FROM_DATABASE=Beijing Rongcheng Hutong Technology Co., Ltd. +OUI:B88E3A* + ID_OUI_FROM_DATABASE=Infinite Technologies JLT -OUI:18E288* - ID_OUI_FROM_DATABASE=STT Condigi +OUI:74BE08* + ID_OUI_FROM_DATABASE=ATEK Products, LLC -OUI:68876B* - ID_OUI_FROM_DATABASE=INQ Mobile Limited +OUI:E0EE1B* + ID_OUI_FROM_DATABASE=Panasonic Automotive Systems Company of America -OUI:9866EA* - ID_OUI_FROM_DATABASE=Industrial Control Communications, Inc. +OUI:E80C38* + ID_OUI_FROM_DATABASE=DAEYOUNG INFORMATION SYSTEM CO., LTD -OUI:F4A52A* - ID_OUI_FROM_DATABASE=Hawa Technologies Inc +OUI:68597F* + ID_OUI_FROM_DATABASE=Alcatel Lucent -OUI:90CF15* - ID_OUI_FROM_DATABASE=Nokia Corporation +OUI:2C3068* + ID_OUI_FROM_DATABASE=Pantech Co.,Ltd -OUI:B8D49D* - ID_OUI_FROM_DATABASE=M Seven System Ltd. +OUI:5C4058* + ID_OUI_FROM_DATABASE=Jefferson Audio Video Systems, Inc. -OUI:B0A10A* - ID_OUI_FROM_DATABASE=Pivotal Systems Corporation +OUI:64317E* + ID_OUI_FROM_DATABASE=Dexin Corporation -OUI:48F47D* - ID_OUI_FROM_DATABASE=TechVision Holding Internation Limited +OUI:AC9B84* + ID_OUI_FROM_DATABASE=Smak Tecnologia e Automacao -OUI:6C391D* - ID_OUI_FROM_DATABASE=Beijing ZhongHuaHun Network Information center +OUI:4C022E* + ID_OUI_FROM_DATABASE=CMR KOREA CO., LTD -OUI:64D241* - ID_OUI_FROM_DATABASE=Keith & Koep GmbH +OUI:24A42C* + ID_OUI_FROM_DATABASE=KOUKAAM a.s. -OUI:101212* - ID_OUI_FROM_DATABASE=Vivo International Corporation Pty Ltd +OUI:34F39B* + ID_OUI_FROM_DATABASE=WizLAN Ltd. -OUI:5087B8* - ID_OUI_FROM_DATABASE=Nuvyyo Inc +OUI:74B9EB* + ID_OUI_FROM_DATABASE=JinQianMao Technology Co.,Ltd. -OUI:E41289* - ID_OUI_FROM_DATABASE=topsystem Systemhaus GmbH +OUI:244597* + ID_OUI_FROM_DATABASE=GEMUE Gebr. Mueller Apparatebau -OUI:A4134E* - ID_OUI_FROM_DATABASE=Luxul +OUI:30694B* + ID_OUI_FROM_DATABASE=RIM -OUI:B09928* - ID_OUI_FROM_DATABASE=FUJITSU LIMITED +OUI:AC5135* + ID_OUI_FROM_DATABASE=MPI TECH -OUI:8C11CB* - ID_OUI_FROM_DATABASE=ABUS Security-Center GmbH & Co. KG +OUI:E4EC10* + ID_OUI_FROM_DATABASE=Nokia Corporation -OUI:806459* - ID_OUI_FROM_DATABASE=Nimbus Inc. +OUI:00D38D* + ID_OUI_FROM_DATABASE=Hotel Technology Next Generation -OUI:A45A1C* - ID_OUI_FROM_DATABASE=smart-electronic GmbH +OUI:3C6278* + ID_OUI_FROM_DATABASE=SHENZHEN JETNET TECHNOLOGY CO.,LTD. -OUI:8C89A5* - ID_OUI_FROM_DATABASE=Micro-Star INT'L CO., LTD +OUI:8081A5* + ID_OUI_FROM_DATABASE=TONGQING COMMUNICATION EQUIPMENT (SHENZHEN) Co.,Ltd -OUI:3C672C* - ID_OUI_FROM_DATABASE=Sciovid Inc. +OUI:EC8EAD* + ID_OUI_FROM_DATABASE=DLX -OUI:18D071* - ID_OUI_FROM_DATABASE=DASAN CO., LTD. +OUI:ECDE3D* + ID_OUI_FROM_DATABASE=Lamprey Networks, Inc. -OUI:38D135* - ID_OUI_FROM_DATABASE=EasyIO Corporation Sdn. Bhd. +OUI:04FE7F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:184E94* - ID_OUI_FROM_DATABASE=MESSOA TECHNOLOGIES INC. +OUI:E8056D* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:94D93C* - ID_OUI_FROM_DATABASE=ENELPS +OUI:00D11C* + ID_OUI_FROM_DATABASE=ACETEL -OUI:DC9B1E* - ID_OUI_FROM_DATABASE=Intercom, Inc. +OUI:1056CA* + ID_OUI_FROM_DATABASE=Peplink International Ltd. -OUI:5C7757* - ID_OUI_FROM_DATABASE=Haivision Network Video +OUI:44A689* + ID_OUI_FROM_DATABASE=PROMAX ELECTRONICA SA -OUI:E8B4AE* - ID_OUI_FROM_DATABASE=Shenzhen C&D Electronics Co.,Ltd +OUI:10CCDB* + ID_OUI_FROM_DATABASE=AXIMUM PRODUITS ELECTRONIQUES -OUI:C45600* - ID_OUI_FROM_DATABASE=Galleon Embedded Computing +OUI:6C92BF* + ID_OUI_FROM_DATABASE=Inspur Electronic Information Industry Co.,Ltd. -OUI:E42FF6* - ID_OUI_FROM_DATABASE=Unicore communication Inc. +OUI:E01CEE* + ID_OUI_FROM_DATABASE=Bravo Tech, Inc. -OUI:B8F4D0* - ID_OUI_FROM_DATABASE=Herrmann Ultraschalltechnik GmbH & Co. Kg +OUI:3C1915* + ID_OUI_FROM_DATABASE=GFI Chrono Time -OUI:B4F323* - ID_OUI_FROM_DATABASE=PETATEL INC. +OUI:EC5C69* + ID_OUI_FROM_DATABASE=MITSUBISHI HEAVY INDUSTRIES MECHATRONICS SYSTEMS,LTD. -OUI:C81E8E* - ID_OUI_FROM_DATABASE=ADV Security (S) Pte Ltd +OUI:04E548* + ID_OUI_FROM_DATABASE=Cohda Wireless Pty Ltd -OUI:ACCABA* - ID_OUI_FROM_DATABASE=Midokura Co., Ltd. +OUI:0C1DC2* + ID_OUI_FROM_DATABASE=SeAH Networks -OUI:9C417C* - ID_OUI_FROM_DATABASE=Hame Technology Co., Limited +OUI:28CD4C* + ID_OUI_FROM_DATABASE=Individual Computers GmbH -OUI:10768A* - ID_OUI_FROM_DATABASE=EoCell +OUI:8C53F7* + ID_OUI_FROM_DATABASE=A&D ENGINEERING CO., LTD. -OUI:044665* - ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. +OUI:781185* + ID_OUI_FROM_DATABASE=NBS Payment Solutions Inc. -OUI:D0131E* - ID_OUI_FROM_DATABASE=Sunrex Technology Corp +OUI:2893FE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:380197* - ID_OUI_FROM_DATABASE=TSST Global,Inc +OUI:10B7F6* + ID_OUI_FROM_DATABASE=Plastoform Industries Ltd. -OUI:B40142* - ID_OUI_FROM_DATABASE=GCI Science & Technology Co.,LTD +OUI:2059A0* + ID_OUI_FROM_DATABASE=Paragon Technologies Inc. -OUI:846EB1* - ID_OUI_FROM_DATABASE=Park Assist LLC +OUI:487119* + ID_OUI_FROM_DATABASE=SGB GROUP LTD. -OUI:6C504D* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:E0ABFE* + ID_OUI_FROM_DATABASE=Orb Networks, Inc. -OUI:C0C1C0* +OUI:CCEA1C* + ID_OUI_FROM_DATABASE=DCONWORKS Co., Ltd + +OUI:ACE348* + ID_OUI_FROM_DATABASE=MadgeTech, Inc + +OUI:687F74* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC -OUI:1CBD0E* - ID_OUI_FROM_DATABASE=Amplified Engineering Pty Ltd +OUI:CCB888* + ID_OUI_FROM_DATABASE=AnB Securite s.a. -OUI:F0A764* - ID_OUI_FROM_DATABASE=GST Co., Ltd. +OUI:CC2218* + ID_OUI_FROM_DATABASE=InnoDigital Co., Ltd. -OUI:A0F217* - ID_OUI_FROM_DATABASE=GE Medical System(China) Co., Ltd. +OUI:B86491* + ID_OUI_FROM_DATABASE=CK Telecom Ltd -OUI:643409* - ID_OUI_FROM_DATABASE=BITwave Pte Ltd +OUI:80C862* + ID_OUI_FROM_DATABASE=Openpeak, Inc -OUI:20D5AB* - ID_OUI_FROM_DATABASE=Korea Infocom Co.,Ltd. +OUI:E43593* + ID_OUI_FROM_DATABASE=Hangzhou GoTo technology Co.Ltd -OUI:F05849* - ID_OUI_FROM_DATABASE=CareView Communications +OUI:E0BC43* + ID_OUI_FROM_DATABASE=C2 Microsystems, Inc. -OUI:BC15A6* - ID_OUI_FROM_DATABASE=Taiwan Jantek Electronics,Ltd. +OUI:7884EE* + ID_OUI_FROM_DATABASE=INDRA ESPACIO S.A. -OUI:241A8C* - ID_OUI_FROM_DATABASE=Squarehead Technology AS +OUI:2C3F3E* + ID_OUI_FROM_DATABASE=Alge-Timing GmbH -OUI:1083D2* - ID_OUI_FROM_DATABASE=Microseven Systems, LLC +OUI:C0CFA3* + ID_OUI_FROM_DATABASE=Creative Electronics & Software, Inc. -OUI:F05D89* - ID_OUI_FROM_DATABASE=Dycon Limited +OUI:D4823E* + ID_OUI_FROM_DATABASE=Argosy Technologies, Ltd. -OUI:AC02CF* - ID_OUI_FROM_DATABASE=RW Tecnologia Industria e Comercio Ltda +OUI:844823* + ID_OUI_FROM_DATABASE=WOXTER TECHNOLOGY Co. Ltd -OUI:9067B5* - ID_OUI_FROM_DATABASE=Alcatel-Lucent +OUI:D0F0DB* + ID_OUI_FROM_DATABASE=Ericsson -OUI:40987B* - ID_OUI_FROM_DATABASE=Aisino Corporation +OUI:7C1476* + ID_OUI_FROM_DATABASE=Damall Technologies SAS -OUI:6C2E33* - ID_OUI_FROM_DATABASE=Accelink Technologies Co.,Ltd. +OUI:D05875* + ID_OUI_FROM_DATABASE=Active Control Technology Inc. -OUI:4CEDDE* - ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP +OUI:D81BFE* + ID_OUI_FROM_DATABASE=TWINLINX CORPORATION -OUI:E8E08F* - ID_OUI_FROM_DATABASE=GRAVOTECH MARKING SAS +OUI:D46CBF* + ID_OUI_FROM_DATABASE=Goodrich ISR -OUI:78B6C1* - ID_OUI_FROM_DATABASE=AOBO Telecom Co.,Ltd +OUI:5C57C8* + ID_OUI_FROM_DATABASE=Nokia Corporation -OUI:B8BA68* - ID_OUI_FROM_DATABASE=Xi'an Jizhong Digital Communication Co.,Ltd +OUI:4CC602* + ID_OUI_FROM_DATABASE=Radios, Inc. -OUI:BC38D2* - ID_OUI_FROM_DATABASE=Pandachip Limited +OUI:3C05AB* + ID_OUI_FROM_DATABASE=Product Creation Studio -OUI:14EE9D* - ID_OUI_FROM_DATABASE=AirNav Systems LLC +OUI:3C39C3* + ID_OUI_FROM_DATABASE=JW Electronics Co., Ltd. -OUI:48174C* - ID_OUI_FROM_DATABASE=MicroPower technologies +OUI:547FEE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:F81037* - ID_OUI_FROM_DATABASE=Atopia Systems, LP +OUI:A4C2AB* + ID_OUI_FROM_DATABASE=Hangzhou LEAD-IT Information & Technology Co.,Ltd -OUI:64F987* - ID_OUI_FROM_DATABASE=Avvasi Inc. +OUI:48AA5D* + ID_OUI_FROM_DATABASE=Store Electronic Systems -OUI:3C7437* - ID_OUI_FROM_DATABASE=RIM +OUI:1062C9* + ID_OUI_FROM_DATABASE=Adatis GmbH & Co. KG -OUI:04209A* - ID_OUI_FROM_DATABASE=Panasonic AVC Networks Company +OUI:D8AE90* + ID_OUI_FROM_DATABASE=Itibia Technologies -OUI:64DC01* - ID_OUI_FROM_DATABASE=Static Systems Group PLC +OUI:904716* + ID_OUI_FROM_DATABASE=RORZE CORPORATION -OUI:1CF5E7* - ID_OUI_FROM_DATABASE=Turtle Industry Co., Ltd. +OUI:28E794* + ID_OUI_FROM_DATABASE=Microtime Computer Inc. -OUI:9C4A7B* - ID_OUI_FROM_DATABASE=Nokia Corporation +OUI:8894F9* + ID_OUI_FROM_DATABASE=Gemicom Technology, Inc. -OUI:2C8065* - ID_OUI_FROM_DATABASE=HARTING Inc. of North America +OUI:0CA42A* + ID_OUI_FROM_DATABASE=OB Telecom Electronic Technology Co., Ltd -OUI:F8F014* - ID_OUI_FROM_DATABASE=RackWare Inc. +OUI:5850E6* + ID_OUI_FROM_DATABASE=Best Buy Corporation -OUI:E41C4B* - ID_OUI_FROM_DATABASE=V2 TECHNOLOGY, INC. +OUI:AC9A96* + ID_OUI_FROM_DATABASE=Lantiq Deutschland GmbH -OUI:E0143E* - ID_OUI_FROM_DATABASE=Modoosis Inc. +OUI:E86CDA* + ID_OUI_FROM_DATABASE=Supercomputers and Neurocomputers Research Center -OUI:5C6984* - ID_OUI_FROM_DATABASE=NUVICO +OUI:24B6B8* + ID_OUI_FROM_DATABASE=FRIEM SPA -OUI:204AAA* - ID_OUI_FROM_DATABASE=Hanscan Spain S.A. +OUI:F86ECF* + ID_OUI_FROM_DATABASE=Arcx Inc -OUI:F02572* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:8C8401* + ID_OUI_FROM_DATABASE=Private -OUI:8091C0* - ID_OUI_FROM_DATABASE=AgileMesh, Inc. +OUI:6C7039* + ID_OUI_FROM_DATABASE=Novar GmbH -OUI:0CF0B4* - ID_OUI_FROM_DATABASE=Globalsat International Technology Ltd +OUI:A4561B* + ID_OUI_FROM_DATABASE=MCOT Corporation -OUI:BCC61A* - ID_OUI_FROM_DATABASE=SPECTRA EMBEDDED SYSTEMS +OUI:80EE73* + ID_OUI_FROM_DATABASE=Shuttle Inc. -OUI:48DF1C* - ID_OUI_FROM_DATABASE=Wuhan NEC Fibre Optic Communications industry Co. Ltd +OUI:10C73F* + ID_OUI_FROM_DATABASE=Midas Klark Teknik Ltd -OUI:D0D3FC* - ID_OUI_FROM_DATABASE=Mios, Ltd. +OUI:408A9A* + ID_OUI_FROM_DATABASE=TITENG CO., Ltd. -OUI:989449* - ID_OUI_FROM_DATABASE=Skyworth Wireless Technology Ltd. +OUI:702B1D* + ID_OUI_FROM_DATABASE=E-Domus International Limited -OUI:C8DF7C* - ID_OUI_FROM_DATABASE=Nokia Corporation +OUI:F077D0* + ID_OUI_FROM_DATABASE=Xcellen -OUI:F8C678* - ID_OUI_FROM_DATABASE=Carefusion +OUI:785C72* + ID_OUI_FROM_DATABASE=Hioso Technology Co., Ltd. -OUI:FC3598* - ID_OUI_FROM_DATABASE=Favite Inc. +OUI:94236E* + ID_OUI_FROM_DATABASE=Shenzhen Junlan Electronic Ltd -OUI:A0AAFD* - ID_OUI_FROM_DATABASE=EraThink Technologies Corp. +OUI:88BA7F* + ID_OUI_FROM_DATABASE=Qfiednet Co., Ltd. -OUI:801F02* - ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. +OUI:E02636* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:E03E7D* - ID_OUI_FROM_DATABASE=data-complex GmbH +OUI:4456B7* + ID_OUI_FROM_DATABASE=Spawn Labs, Inc -OUI:A4E32E* - ID_OUI_FROM_DATABASE=Silicon & Software Systems Ltd. +OUI:A09805* + ID_OUI_FROM_DATABASE=OpenVox Communication Co Ltd -OUI:1C19DE* - ID_OUI_FROM_DATABASE=eyevis GmbH +OUI:00271D* + ID_OUI_FROM_DATABASE=Comba Telecom Systems (China) Ltd. -OUI:DC07C1* - ID_OUI_FROM_DATABASE=HangZhou QiYang Technology Co.,Ltd. +OUI:002721* + ID_OUI_FROM_DATABASE=Shenzhen Baoan Fenda Industrial Co., Ltd -OUI:D8FE8F* - ID_OUI_FROM_DATABASE=IDFone Co., Ltd. +OUI:A09A5A* + ID_OUI_FROM_DATABASE=Time Domain -OUI:0006F6* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:64A837* + ID_OUI_FROM_DATABASE=Juni Korea Co., Ltd -OUI:ACAB8D* - ID_OUI_FROM_DATABASE=Lyngso Marine A/S +OUI:B4B5AF* + ID_OUI_FROM_DATABASE=Minsung Electronics -OUI:181456* - ID_OUI_FROM_DATABASE=Nokia Corporation +OUI:044FAA* + ID_OUI_FROM_DATABASE=Ruckus Wireless -OUI:E8995A* - ID_OUI_FROM_DATABASE=PiiGAB, Processinformation i Goteborg AB +OUI:44568D* + ID_OUI_FROM_DATABASE=PNC Technologies Co., Ltd. -OUI:D4E32C* - ID_OUI_FROM_DATABASE=S. Siedle & Sohne +OUI:ACD180* + ID_OUI_FROM_DATABASE=Crexendo Business Solutions, Inc. -OUI:68DCE8* - ID_OUI_FROM_DATABASE=PacketStorm Communications +OUI:AC8317* + ID_OUI_FROM_DATABASE=Shenzhen Furtunetel Communication Co., Ltd -OUI:78223D* - ID_OUI_FROM_DATABASE=Affirmed Networks +OUI:E80B13* + ID_OUI_FROM_DATABASE=Akib Systems Taiwan, INC -OUI:60C980* - ID_OUI_FROM_DATABASE=Trymus +OUI:44C9A2* + ID_OUI_FROM_DATABASE=Greenwald Industries -OUI:94CDAC* - ID_OUI_FROM_DATABASE=Creowave Oy +OUI:646E6C* + ID_OUI_FROM_DATABASE=Radio Datacom LLC -OUI:F4DCDA* - ID_OUI_FROM_DATABASE=Zhuhai Jiahe Communication Technology Co., limited +OUI:E4751E* + ID_OUI_FROM_DATABASE=Getinge Sterilization AB -OUI:100D32* - ID_OUI_FROM_DATABASE=Embedian, Inc. +OUI:F8811A* + ID_OUI_FROM_DATABASE=OVERKIZ -OUI:D82986* - ID_OUI_FROM_DATABASE=Best Wish Technology LTD +OUI:042BBB* + ID_OUI_FROM_DATABASE=PicoCELA, Inc. -OUI:C03B8F* - ID_OUI_FROM_DATABASE=Minicom Digital Signage +OUI:FC0877* + ID_OUI_FROM_DATABASE=Prentke Romich Company -OUI:A4218A* - ID_OUI_FROM_DATABASE=Nortel Networks +OUI:ECD00E* + ID_OUI_FROM_DATABASE=MiraeRecognition Co., Ltd. -OUI:6C0460* - ID_OUI_FROM_DATABASE=RBH Access Technologies Inc. +OUI:747E1A* + ID_OUI_FROM_DATABASE=Red Embedded Design Limited -OUI:5C864A* - ID_OUI_FROM_DATABASE=Secret Labs LLC +OUI:C47D4F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:B8BA72* - ID_OUI_FROM_DATABASE=Cynove +OUI:4C9EE4* + ID_OUI_FROM_DATABASE=Hanyang Navicom Co.,Ltd. -OUI:C00D7E* - ID_OUI_FROM_DATABASE=Additech, Inc. +OUI:3CDF1E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:68784C* - ID_OUI_FROM_DATABASE=Nortel Networks +OUI:BCB181* + ID_OUI_FROM_DATABASE=SHARP CORPORATION + +OUI:78B81A* + ID_OUI_FROM_DATABASE=INTER SALES A/S -OUI:6C626D* - ID_OUI_FROM_DATABASE=Micro-Star INT'L CO., LTD +OUI:78192E* + ID_OUI_FROM_DATABASE=NASCENT Technology -OUI:8841C1* - ID_OUI_FROM_DATABASE=ORBISAT DA AMAZONIA IND E AEROL SA +OUI:2C0623* + ID_OUI_FROM_DATABASE=Win Leader Inc. -OUI:18B209* - ID_OUI_FROM_DATABASE=Torrey Pines Logic, Inc +OUI:C82E94* + ID_OUI_FROM_DATABASE=Halfa Enterprise Co., Ltd. -OUI:3018CF* - ID_OUI_FROM_DATABASE=DEOS control systems GmbH +OUI:0C2755* + ID_OUI_FROM_DATABASE=Valuable Techologies Limited -OUI:4CF737* - ID_OUI_FROM_DATABASE=SamJi Electronics Co., Ltd +OUI:C038F9* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S -OUI:40406B* - ID_OUI_FROM_DATABASE=Icomera +OUI:F46349* + ID_OUI_FROM_DATABASE=Diffon Corporation -OUI:1880CE* - ID_OUI_FROM_DATABASE=Barberry Solutions Ltd +OUI:5C8778* + ID_OUI_FROM_DATABASE=Cybertelbridge co.,ltd -OUI:CC43E3* - ID_OUI_FROM_DATABASE=Trump s.a. +OUI:9C5E73* + ID_OUI_FROM_DATABASE=Calibre UK LTD -OUI:6C22AB* - ID_OUI_FROM_DATABASE=Ainsworth Game Technology +OUI:F06281* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP -OUI:3C106F* - ID_OUI_FROM_DATABASE=ALBAHITH TECHNOLOGIES +OUI:003A9B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:7CE044* - ID_OUI_FROM_DATABASE=NEON Inc +OUI:2C9127* + ID_OUI_FROM_DATABASE=Eintechno Corporation -OUI:64D02D* - ID_OUI_FROM_DATABASE=Next Generation Integration (NGI) +OUI:C09C92* + ID_OUI_FROM_DATABASE=COBY -OUI:A04041* - ID_OUI_FROM_DATABASE=SAMWONFA Co.,Ltd. +OUI:849000* + ID_OUI_FROM_DATABASE=Arnold & Richter Cine Technik -OUI:788C54* - ID_OUI_FROM_DATABASE=Eltek Technologies LTD +OUI:C87248* + ID_OUI_FROM_DATABASE=Aplicom Oy -OUI:9411DA* - ID_OUI_FROM_DATABASE=ITF Fröschl GmbH +OUI:74D850* + ID_OUI_FROM_DATABASE=Evrisko Systems -OUI:10E8EE* - ID_OUI_FROM_DATABASE=PhaseSpace +OUI:6CAC60* + ID_OUI_FROM_DATABASE=Venetex Corp -OUI:A47C1F* - ID_OUI_FROM_DATABASE=Cobham plc +OUI:DC0265* + ID_OUI_FROM_DATABASE=Meditech Kft -OUI:8C1F94* - ID_OUI_FROM_DATABASE=RF Surgical System Inc. +OUI:986DC8* + ID_OUI_FROM_DATABASE=TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORPORATION -OUI:74A4A7* - ID_OUI_FROM_DATABASE=QRS Music Technologies, Inc. +OUI:68A1B7* + ID_OUI_FROM_DATABASE=Honghao Mingchuan Technology (Beijing) CO.,Ltd. -OUI:8039E5* - ID_OUI_FROM_DATABASE=PATLITE CORPORATION +OUI:7CCFCF* + ID_OUI_FROM_DATABASE=Shanghai SEARI Intelligent System Co., Ltd -OUI:BCFFAC* - ID_OUI_FROM_DATABASE=TOPCON CORPORATION +OUI:EC3091* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:602A54* - ID_OUI_FROM_DATABASE=CardioTek B.V. +OUI:3032D4* + ID_OUI_FROM_DATABASE=Hanilstm Co., Ltd. -OUI:1C3DE7* - ID_OUI_FROM_DATABASE=Sigma Koki Co.,Ltd. +OUI:0026EE* + ID_OUI_FROM_DATABASE=TKM GmbH -OUI:482CEA* - ID_OUI_FROM_DATABASE=Motorola Inc Business Light Radios +OUI:0026E7* + ID_OUI_FROM_DATABASE=Shanghai ONLAN Communication Tech. Co., Ltd. -OUI:70E139* - ID_OUI_FROM_DATABASE=3view Ltd +OUI:0026E1* + ID_OUI_FROM_DATABASE=Stanford University, OpenFlow Group -OUI:AC6123* - ID_OUI_FROM_DATABASE=Drivven, Inc. +OUI:0026DB* + ID_OUI_FROM_DATABASE=Ionics EMS Inc. -OUI:3C04BF* - ID_OUI_FROM_DATABASE=PRAVIS SYSTEMS Co.Ltd., +OUI:0026CE* + ID_OUI_FROM_DATABASE=Kozumi USA Corp. -OUI:443D21* - ID_OUI_FROM_DATABASE=Nuvolt +OUI:0026D5* + ID_OUI_FROM_DATABASE=Ory Solucoes em Comercio de Informatica Ltda. -OUI:749050* - ID_OUI_FROM_DATABASE=Renesas Electronics Corporation +OUI:0026C8* + ID_OUI_FROM_DATABASE=System Sensor -OUI:7CBB6F* - ID_OUI_FROM_DATABASE=Cosco Electronics Co., Ltd. +OUI:002711* + ID_OUI_FROM_DATABASE=LanPro Inc -OUI:D466A8* - ID_OUI_FROM_DATABASE=Riedo Networks GmbH +OUI:00270D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:98E165* - ID_OUI_FROM_DATABASE=Accutome +OUI:002707* + ID_OUI_FROM_DATABASE=Lift Complex DS, JSC -OUI:EC66D1* - ID_OUI_FROM_DATABASE=B&W Group LTD +OUI:002700* + ID_OUI_FROM_DATABASE=Shenzhen Siglent Technology Co., Ltd. -OUI:385FC3* - ID_OUI_FROM_DATABASE=Yu Jeong System, Co.Ltd +OUI:0026FA* + ID_OUI_FROM_DATABASE=BandRich Inc. -OUI:94857A* - ID_OUI_FROM_DATABASE=Evantage Industries Corp +OUI:0026F4* + ID_OUI_FROM_DATABASE=Nesslab -OUI:4451DB* - ID_OUI_FROM_DATABASE=Raytheon BBN Technologies +OUI:0025D7* + ID_OUI_FROM_DATABASE=CEDO -OUI:64995D* - ID_OUI_FROM_DATABASE=LGE +OUI:0025D2* + ID_OUI_FROM_DATABASE=InpegVision Co., Ltd -OUI:585076* - ID_OUI_FROM_DATABASE=Linear Equipamentos Eletronicos SA +OUI:0025D1* + ID_OUI_FROM_DATABASE=Eastern Asia Technology Limited -OUI:4083DE* - ID_OUI_FROM_DATABASE=Zebra Technologies Inc +OUI:0025CB* + ID_OUI_FROM_DATABASE=Reiner SCT -OUI:8897DF* - ID_OUI_FROM_DATABASE=Entrypass Corporation Sdn. Bhd. +OUI:0025C4* + ID_OUI_FROM_DATABASE=Ruckus Wireless -OUI:0C15C5* - ID_OUI_FROM_DATABASE=SDTEC Co., Ltd. +OUI:0025BF* + ID_OUI_FROM_DATABASE=Wireless Cables Inc. -OUI:9803A0* - ID_OUI_FROM_DATABASE=ABB n.v. Power Quality Products +OUI:0025B1* + ID_OUI_FROM_DATABASE=Maya-Creation Corporation -OUI:DCFAD5* - ID_OUI_FROM_DATABASE=STRONG Ges.m.b.H. +OUI:0025B8* + ID_OUI_FROM_DATABASE=Agile Communications, Inc. -OUI:D84606* - ID_OUI_FROM_DATABASE=Silicon Valley Global Marketing +OUI:0025B2* + ID_OUI_FROM_DATABASE=MBDA Deutschland GmbH -OUI:689234* - ID_OUI_FROM_DATABASE=Ruckus Wireless +OUI:0025AC* + ID_OUI_FROM_DATABASE=I-Tech corporation -OUI:D0E347* - ID_OUI_FROM_DATABASE=Yoga +OUI:0026C2* + ID_OUI_FROM_DATABASE=SCDI Co. LTD -OUI:84A991* - ID_OUI_FROM_DATABASE=Cyber Trans Japan Co.,Ltd. +OUI:0026BC* + ID_OUI_FROM_DATABASE=General Jack Technology Ltd. -OUI:D81C14* - ID_OUI_FROM_DATABASE=Compacta International, Ltd. +OUI:0026B4* + ID_OUI_FROM_DATABASE=Ford Motor Company -OUI:9088A2* - ID_OUI_FROM_DATABASE=IONICS TECHNOLOGY ME LTDA +OUI:0026AE* + ID_OUI_FROM_DATABASE=Wireless Measurement Ltd -OUI:B0B8D5* - ID_OUI_FROM_DATABASE=Nanjing Nengrui Auto Equipment CO.,Ltd +OUI:0026AA* + ID_OUI_FROM_DATABASE=Kenmec Mechanical Engineering Co., Ltd. -OUI:8497B8* - ID_OUI_FROM_DATABASE=Memjet Inc. +OUI:0026A4* + ID_OUI_FROM_DATABASE=Novus Produtos Eletronicos Ltda -OUI:A8556A* - ID_OUI_FROM_DATABASE=Pocketnet Technology Inc. +OUI:002698* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:B081D8* - ID_OUI_FROM_DATABASE=I-sys Corp +OUI:00269D* + ID_OUI_FROM_DATABASE=M2Mnet Co., Ltd. -OUI:206AFF* - ID_OUI_FROM_DATABASE=Atlas Elektronik UK Limited +OUI:00268B* + ID_OUI_FROM_DATABASE=Guangzhou Escene Computer Technology Limited -OUI:EC542E* - ID_OUI_FROM_DATABASE=Shanghai XiMei Electronic Technology Co. Ltd +OUI:002685* + ID_OUI_FROM_DATABASE=Digital Innovation -OUI:B88E3A* - ID_OUI_FROM_DATABASE=Infinite Technologies JLT +OUI:002678* + ID_OUI_FROM_DATABASE=Logic Instrument SA -OUI:74BE08* - ID_OUI_FROM_DATABASE=ATEK Products, LLC +OUI:002672* + ID_OUI_FROM_DATABASE=AAMP of America -OUI:E0EE1B* - ID_OUI_FROM_DATABASE=Panasonic Automotive Systems Company of America +OUI:00266B* + ID_OUI_FROM_DATABASE=SHINE UNION ENTERPRISE LIMITED -OUI:E80C38* - ID_OUI_FROM_DATABASE=DAEYOUNG INFORMATION SYSTEM CO., LTD +OUI:002666* + ID_OUI_FROM_DATABASE=EFM Networks -OUI:68597F* - ID_OUI_FROM_DATABASE=Alcatel Lucent +OUI:002665* + ID_OUI_FROM_DATABASE=ProtectedLogic Corporation -OUI:2C3068* - ID_OUI_FROM_DATABASE=Pantech Co.,Ltd +OUI:002651* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:5C4058* - ID_OUI_FROM_DATABASE=Jefferson Audio Video Systems, Inc. +OUI:002652* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:64317E* - ID_OUI_FROM_DATABASE=Dexin Corporation +OUI:002646* + ID_OUI_FROM_DATABASE=SHENYANG TONGFANG MULTIMEDIA TECHNOLOGY COMPANY LIMITED -OUI:AC9B84* - ID_OUI_FROM_DATABASE=Smak Tecnologia e Automacao +OUI:002640* + ID_OUI_FROM_DATABASE=Baustem Broadband Technologies, Ltd. -OUI:4C022E* - ID_OUI_FROM_DATABASE=CMR KOREA CO., LTD +OUI:00263A* + ID_OUI_FROM_DATABASE=Digitec Systems -OUI:24A42C* - ID_OUI_FROM_DATABASE=KOUKAAM a.s. +OUI:002634* + ID_OUI_FROM_DATABASE=Infineta Systems, Inc -OUI:34F39B* - ID_OUI_FROM_DATABASE=WizLAN Ltd. +OUI:002633* + ID_OUI_FROM_DATABASE=MIR - Medical International Research -OUI:74B9EB* - ID_OUI_FROM_DATABASE=JinQianMao Technology Co.,Ltd. +OUI:00262E* + ID_OUI_FROM_DATABASE=Chengdu Jiuzhou Electronic Technology Inc -OUI:244597* - ID_OUI_FROM_DATABASE=GEMUE Gebr. Mueller Apparatebau +OUI:002627* + ID_OUI_FROM_DATABASE=Truesell -OUI:30694B* - ID_OUI_FROM_DATABASE=RIM +OUI:002621* + ID_OUI_FROM_DATABASE=InteliCloud Technology Inc. -OUI:AC5135* - ID_OUI_FROM_DATABASE=MPI TECH +OUI:00261B* + ID_OUI_FROM_DATABASE=LAUREL BANK MACHINES CO., LTD. -OUI:E4EC10* - ID_OUI_FROM_DATABASE=Nokia Corporation +OUI:002614* + ID_OUI_FROM_DATABASE=KTNF -OUI:00D38D* - ID_OUI_FROM_DATABASE=Hotel Technology Next Generation +OUI:00260E* + ID_OUI_FROM_DATABASE=Ablaze Systems, LLC -OUI:3C6278* - ID_OUI_FROM_DATABASE=SHENZHEN JETNET TECHNOLOGY CO.,LTD. +OUI:002602* + ID_OUI_FROM_DATABASE=SMART Temps LLC -OUI:8081A5* - ID_OUI_FROM_DATABASE=TONGQING COMMUNICATION EQUIPMENT (SHENZHEN) Co.,Ltd +OUI:002601* + ID_OUI_FROM_DATABASE=Cutera Inc -OUI:EC8EAD* - ID_OUI_FROM_DATABASE=DLX +OUI:0025F7* + ID_OUI_FROM_DATABASE=Ansaldo STS USA -OUI:ECDE3D* - ID_OUI_FROM_DATABASE=Lamprey Networks, Inc. +OUI:0025FC* + ID_OUI_FROM_DATABASE=ENDA ENDUSTRIYEL ELEKTRONIK LTD. STI. -OUI:04FE7F* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0025ED* + ID_OUI_FROM_DATABASE=NuVo Technologies LLC -OUI:E8056D* - ID_OUI_FROM_DATABASE=Nortel Networks +OUI:0025EE* + ID_OUI_FROM_DATABASE=Avtex Ltd -OUI:00D11C* - ID_OUI_FROM_DATABASE=ACETEL +OUI:0025E8* + ID_OUI_FROM_DATABASE=Idaho Technology -OUI:1056CA* - ID_OUI_FROM_DATABASE=Peplink International Ltd. +OUI:0025E3* + ID_OUI_FROM_DATABASE=Hanshinit Inc. -OUI:44A689* - ID_OUI_FROM_DATABASE=PROMAX ELECTRONICA SA +OUI:0025DE* + ID_OUI_FROM_DATABASE=Probits Co., LTD. -OUI:10CCDB* - ID_OUI_FROM_DATABASE=AXIMUM PRODUITS ELECTRONIQUES +OUI:002579* + ID_OUI_FROM_DATABASE=J & F Labs -OUI:6C92BF* - ID_OUI_FROM_DATABASE=Inspur Electronic Information Industry Co.,Ltd. +OUI:00257E* + ID_OUI_FROM_DATABASE=NEW POS Technology Limited -OUI:E01CEE* - ID_OUI_FROM_DATABASE=Bravo Tech, Inc. +OUI:002572* + ID_OUI_FROM_DATABASE=Nemo-Q International AB -OUI:3C1915* - ID_OUI_FROM_DATABASE=GFI Chrono Time +OUI:00256B* + ID_OUI_FROM_DATABASE=ATENIX E.E. s.r.l. -OUI:EC5C69* - ID_OUI_FROM_DATABASE=MITSUBISHI HEAVY INDUSTRIES MECHATRONICS SYSTEMS,LTD. +OUI:00256C* + ID_OUI_FROM_DATABASE=Azimut Production Association JSC -OUI:04E548* - ID_OUI_FROM_DATABASE=Cohda Wireless Pty Ltd +OUI:00255F* + ID_OUI_FROM_DATABASE=SenTec AG -OUI:0C1DC2* - ID_OUI_FROM_DATABASE=SeAH Networks +OUI:00255A* + ID_OUI_FROM_DATABASE=Tantalus Systems Corp. -OUI:28CD4C* - ID_OUI_FROM_DATABASE=Individual Computers GmbH +OUI:002559* + ID_OUI_FROM_DATABASE=Syphan Technologies Ltd -OUI:8C53F7* - ID_OUI_FROM_DATABASE=A&D ENGINEERING CO., LTD. +OUI:0025A5* + ID_OUI_FROM_DATABASE=Walnut Media Network -OUI:781185* - ID_OUI_FROM_DATABASE=NBS Payment Solutions Inc. +OUI:00259F* + ID_OUI_FROM_DATABASE=TechnoDigital Technologies GmbH -OUI:2893FE* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:002599* + ID_OUI_FROM_DATABASE=Hedon e.d. B.V. -OUI:10B7F6* - ID_OUI_FROM_DATABASE=Plastoform Industries Ltd. +OUI:002592* + ID_OUI_FROM_DATABASE=Guangzhou Shirui Electronic Co., Ltd -OUI:2059A0* - ID_OUI_FROM_DATABASE=Paragon Technologies Inc. +OUI:00258D* + ID_OUI_FROM_DATABASE=Haier -OUI:487119* - ID_OUI_FROM_DATABASE=SGB GROUP LTD. +OUI:002588* + ID_OUI_FROM_DATABASE=Genie Industries, Inc. -OUI:E0ABFE* - ID_OUI_FROM_DATABASE=Orb Networks, Inc. +OUI:002583* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:CCEA1C* - ID_OUI_FROM_DATABASE=DCONWORKS Co., Ltd +OUI:00254C* + ID_OUI_FROM_DATABASE=Videon Central, Inc. -OUI:ACE348* - ID_OUI_FROM_DATABASE=MadgeTech, Inc +OUI:002536* + ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd. -OUI:687F74* - ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC +OUI:00253D* + ID_OUI_FROM_DATABASE=DRS Consolidated Controls -OUI:CCB888* - ID_OUI_FROM_DATABASE=AnB Securite s.a. +OUI:002540* + ID_OUI_FROM_DATABASE=Quasar Technologies, Inc. -OUI:CC2218* - ID_OUI_FROM_DATABASE=InnoDigital Co., Ltd. +OUI:002533* + ID_OUI_FROM_DATABASE=WITTENSTEIN AG -OUI:B86491* - ID_OUI_FROM_DATABASE=CK Telecom Ltd +OUI:00252C* + ID_OUI_FROM_DATABASE=Entourage Systems, Inc. -OUI:80C862* - ID_OUI_FROM_DATABASE=Openpeak, Inc +OUI:002502* + ID_OUI_FROM_DATABASE=NaturalPoint -OUI:E43593* - ID_OUI_FROM_DATABASE=Hangzhou GoTo technology Co.Ltd +OUI:0024FB* + ID_OUI_FROM_DATABASE=Private -OUI:E0BC43* - ID_OUI_FROM_DATABASE=C2 Microsystems, Inc. +OUI:0024F6* + ID_OUI_FROM_DATABASE=MIYOSHI ELECTRONICS CORPORATION -OUI:7884EE* - ID_OUI_FROM_DATABASE=INDRA ESPACIO S.A. +OUI:0024EA* + ID_OUI_FROM_DATABASE=iris-GmbH infrared & intelligent sensors -OUI:2C3F3E* - ID_OUI_FROM_DATABASE=Alge-Timing GmbH +OUI:0024E3* + ID_OUI_FROM_DATABASE=CAO Group -OUI:C0CFA3* - ID_OUI_FROM_DATABASE=Creative Electronics & Software, Inc. +OUI:002527* + ID_OUI_FROM_DATABASE=Bitrode Corp. -OUI:D4823E* - ID_OUI_FROM_DATABASE=Argosy Technologies, Ltd. +OUI:002524* + ID_OUI_FROM_DATABASE=Lightcomm Technology Co., Ltd -OUI:844823* - ID_OUI_FROM_DATABASE=WOXTER TECHNOLOGY Co. Ltd +OUI:00251F* + ID_OUI_FROM_DATABASE=ZYNUS VISION INC. -OUI:D0F0DB* - ID_OUI_FROM_DATABASE=Ericsson +OUI:00251A* + ID_OUI_FROM_DATABASE=Psiber Data Systems Inc. -OUI:7C1476* - ID_OUI_FROM_DATABASE=Damall Technologies SAS +OUI:002515* + ID_OUI_FROM_DATABASE=SFR -OUI:D05875* - ID_OUI_FROM_DATABASE=Active Control Technology Inc. +OUI:00250E* + ID_OUI_FROM_DATABASE=gt german telematics gmbh -OUI:D81BFE* - ID_OUI_FROM_DATABASE=TWINLINX CORPORATION +OUI:002507* + ID_OUI_FROM_DATABASE=ASTAK Inc. -OUI:D46CBF* - ID_OUI_FROM_DATABASE=Goodrich ISR +OUI:002509* + ID_OUI_FROM_DATABASE=SHARETRONIC Group LTD -OUI:5C57C8* - ID_OUI_FROM_DATABASE=Nokia Corporation +OUI:002437* + ID_OUI_FROM_DATABASE=Motorola - BSG -OUI:4CC602* - ID_OUI_FROM_DATABASE=Radios, Inc. +OUI:00243C* + ID_OUI_FROM_DATABASE=S.A.A.A. -OUI:3C05AB* - ID_OUI_FROM_DATABASE=Product Creation Studio +OUI:002430* + ID_OUI_FROM_DATABASE=Ruby Tech Corp. -OUI:3C39C3* - ID_OUI_FROM_DATABASE=JW Electronics Co., Ltd. +OUI:0023FB* + ID_OUI_FROM_DATABASE=IP Datatel, LLC. -OUI:547FEE* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0023F3* + ID_OUI_FROM_DATABASE=Glocom, Inc. -OUI:A4C2AB* - ID_OUI_FROM_DATABASE=Hangzhou LEAD-IT Information & Technology Co.,Ltd +OUI:0023EF* + ID_OUI_FROM_DATABASE=Zuend Systemtechnik AG -OUI:48AA5D* - ID_OUI_FROM_DATABASE=Store Electronic Systems +OUI:0023E9* + ID_OUI_FROM_DATABASE=F5 Networks, Inc. -OUI:1062C9* - ID_OUI_FROM_DATABASE=Adatis GmbH & Co. KG +OUI:0023E3* + ID_OUI_FROM_DATABASE=Microtronic AG -OUI:D8AE90* - ID_OUI_FROM_DATABASE=Itibia Technologies +OUI:0023E2* + ID_OUI_FROM_DATABASE=SEA Signalisation -OUI:904716* - ID_OUI_FROM_DATABASE=RORZE CORPORATION +OUI:0023DD* + ID_OUI_FROM_DATABASE=ELGIN S.A. -OUI:28E794* - ID_OUI_FROM_DATABASE=Microtime Computer Inc. +OUI:0023D0* + ID_OUI_FROM_DATABASE=Uniloc USA Inc. -OUI:8894F9* - ID_OUI_FROM_DATABASE=Gemicom Technology, Inc. +OUI:0023CA* + ID_OUI_FROM_DATABASE=Behind The Set, LLC -OUI:0CA42A* - ID_OUI_FROM_DATABASE=OB Telecom Electronic Technology Co., Ltd +OUI:0024B0* + ID_OUI_FROM_DATABASE=ESAB AB -OUI:5850E6* - ID_OUI_FROM_DATABASE=Best Buy Corporation +OUI:0024A9* + ID_OUI_FROM_DATABASE=Ag Leader Technology -OUI:AC9A96* - ID_OUI_FROM_DATABASE=Lantiq Deutschland GmbH +OUI:0024A2* + ID_OUI_FROM_DATABASE=Hong Kong Middleware Technology Limited -OUI:E86CDA* - ID_OUI_FROM_DATABASE=Supercomputers and Neurocomputers Research Center +OUI:0024A4* + ID_OUI_FROM_DATABASE=Siklu Communication -OUI:24B6B8* - ID_OUI_FROM_DATABASE=FRIEM SPA +OUI:00249D* + ID_OUI_FROM_DATABASE=NES Technology Inc. -OUI:F86ECF* - ID_OUI_FROM_DATABASE=Arcx Inc +OUI:00248A* + ID_OUI_FROM_DATABASE=Kaga Electronics Co., Ltd. -OUI:8C8401* - ID_OUI_FROM_DATABASE=Private +OUI:00248F* + ID_OUI_FROM_DATABASE=DO-MONIX -OUI:6C7039* - ID_OUI_FROM_DATABASE=Novar GmbH +OUI:002496* + ID_OUI_FROM_DATABASE=Ginzinger electronic systems -OUI:A4561B* - ID_OUI_FROM_DATABASE=MCOT Corporation +OUI:002477* + ID_OUI_FROM_DATABASE=Tibbo Technology -OUI:80EE73* - ID_OUI_FROM_DATABASE=Shuttle Inc. +OUI:002470* + ID_OUI_FROM_DATABASE=AUROTECH ultrasound AS. -OUI:10C73F* - ID_OUI_FROM_DATABASE=Midas Klark Teknik Ltd +OUI:002472* + ID_OUI_FROM_DATABASE=ReDriven Power Inc. -OUI:408A9A* - ID_OUI_FROM_DATABASE=TITENG CO., Ltd. +OUI:00246B* + ID_OUI_FROM_DATABASE=Covia, Inc. -OUI:702B1D* - ID_OUI_FROM_DATABASE=E-Domus International Limited +OUI:002464* + ID_OUI_FROM_DATABASE=Bridge Technologies Co AS -OUI:F077D0* - ID_OUI_FROM_DATABASE=Xcellen +OUI:00245F* + ID_OUI_FROM_DATABASE=Vine Telecom CO.,Ltd. -OUI:785C72* - ID_OUI_FROM_DATABASE=Hioso Technology Co., Ltd. +OUI:002420* + ID_OUI_FROM_DATABASE=NetUP Inc. -OUI:94236E* - ID_OUI_FROM_DATABASE=Shenzhen Junlan Electronic Ltd +OUI:002426* + ID_OUI_FROM_DATABASE=NOHMI BOSAI LTD. -OUI:88BA7F* - ID_OUI_FROM_DATABASE=Qfiednet Co., Ltd. +OUI:00241A* + ID_OUI_FROM_DATABASE=Red Beetle Inc. -OUI:E02636* - ID_OUI_FROM_DATABASE=Nortel Networks +OUI:002413* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:4456B7* - ID_OUI_FROM_DATABASE=Spawn Labs, Inc +OUI:00240D* + ID_OUI_FROM_DATABASE=OnePath Networks LTD. -OUI:A09805* - ID_OUI_FROM_DATABASE=OpenVox Communication Co Ltd +OUI:00240E* + ID_OUI_FROM_DATABASE=Inventec Besta Co., Ltd. -OUI:00271D* - ID_OUI_FROM_DATABASE=Comba Telecom Systems (China) Ltd. +OUI:002407* + ID_OUI_FROM_DATABASE=TELEM SAS -OUI:002721* - ID_OUI_FROM_DATABASE=Shenzhen Baoan Fenda Industrial Co., Ltd +OUI:002400* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:A09A5A* - ID_OUI_FROM_DATABASE=Time Domain +OUI:0024D0* + ID_OUI_FROM_DATABASE=Shenzhen SOGOOD Industry CO.,LTD. -OUI:64A837* - ID_OUI_FROM_DATABASE=Juni Korea Co., Ltd +OUI:0024D5* + ID_OUI_FROM_DATABASE=Winward Industrial Limited -OUI:B4B5AF* - ID_OUI_FROM_DATABASE=Minsung Electronics +OUI:0024C9* + ID_OUI_FROM_DATABASE=Broadband Solutions Group -OUI:044FAA* - ID_OUI_FROM_DATABASE=Ruckus Wireless +OUI:0024C4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:44568D* - ID_OUI_FROM_DATABASE=PNC Technologies Co., Ltd. +OUI:0024BF* + ID_OUI_FROM_DATABASE=CIAT -OUI:ACD180* - ID_OUI_FROM_DATABASE=Crexendo Business Solutions, Inc. +OUI:0024B5* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:AC8317* - ID_OUI_FROM_DATABASE=Shenzhen Furtunetel Communication Co., Ltd +OUI:00245A* + ID_OUI_FROM_DATABASE=Nanjing Panda Electronics Company Limited -OUI:E80B13* - ID_OUI_FROM_DATABASE=Akib Systems Taiwan, INC +OUI:002453* + ID_OUI_FROM_DATABASE=Initra d.o.o. -OUI:44C9A2* - ID_OUI_FROM_DATABASE=Greenwald Industries +OUI:00244D* + ID_OUI_FROM_DATABASE=Hokkaido Electronics Corporation -OUI:646E6C* - ID_OUI_FROM_DATABASE=Radio Datacom LLC +OUI:002452* + ID_OUI_FROM_DATABASE=Silicon Software GmbH -OUI:E4751E* - ID_OUI_FROM_DATABASE=Getinge Sterilization AB +OUI:002446* + ID_OUI_FROM_DATABASE=MMB Research Inc. -OUI:F8811A* - ID_OUI_FROM_DATABASE=OVERKIZ +OUI:002441* + ID_OUI_FROM_DATABASE=Wanzl Metallwarenfabrik GmbH -OUI:042BBB* - ID_OUI_FROM_DATABASE=PicoCELA, Inc. +OUI:002368* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc -OUI:FC0877* - ID_OUI_FROM_DATABASE=Prentke Romich Company +OUI:00236F* + ID_OUI_FROM_DATABASE=DAQ System -OUI:ECD00E* - ID_OUI_FROM_DATABASE=MiraeRecognition Co., Ltd. +OUI:002362* + ID_OUI_FROM_DATABASE=Goldline Controls -OUI:747E1A* - ID_OUI_FROM_DATABASE=Red Embedded Design Limited +OUI:002361* + ID_OUI_FROM_DATABASE=Unigen Corporation -OUI:C47D4F* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00235C* + ID_OUI_FROM_DATABASE=Aprius, Inc. -OUI:4C9EE4* - ID_OUI_FROM_DATABASE=Hanyang Navicom Co.,Ltd. +OUI:002355* + ID_OUI_FROM_DATABASE=Kinco Automation(Shanghai) Ltd. -OUI:3CDF1E* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00234F* + ID_OUI_FROM_DATABASE=Luminous Power Technologies Pvt. Ltd. -OUI:BCB181* - ID_OUI_FROM_DATABASE=SHARP CORPORATION +OUI:002350* + ID_OUI_FROM_DATABASE=LynTec -OUI:78B81A* - ID_OUI_FROM_DATABASE=INTER SALES A/S +OUI:002349* + ID_OUI_FROM_DATABASE=Helmholtz Centre Berlin for Material and Energy -OUI:78192E* - ID_OUI_FROM_DATABASE=NASCENT Technology +OUI:002244* + ID_OUI_FROM_DATABASE=Chengdu Linkon Communications Device Co., Ltd -OUI:2C0623* - ID_OUI_FROM_DATABASE=Win Leader Inc. +OUI:00224F* + ID_OUI_FROM_DATABASE=Byzoro Networks Ltd. -OUI:C82E94* - ID_OUI_FROM_DATABASE=Halfa Enterprise Co., Ltd. +OUI:002248* + ID_OUI_FROM_DATABASE=Microsoft Corporation -OUI:0C2755* - ID_OUI_FROM_DATABASE=Valuable Techologies Limited +OUI:00223E* + ID_OUI_FROM_DATABASE=IRTrans GmbH -OUI:C038F9* - ID_OUI_FROM_DATABASE=Nokia Danmark A/S +OUI:002239* + ID_OUI_FROM_DATABASE=Indiana Life Sciences Incorporated -OUI:F46349* - ID_OUI_FROM_DATABASE=Diffon Corporation +OUI:002232* + ID_OUI_FROM_DATABASE=Design Design Technology Ltd -OUI:5C8778* - ID_OUI_FROM_DATABASE=Cybertelbridge co.,ltd +OUI:00222C* + ID_OUI_FROM_DATABASE=Ceton Corp -OUI:9C5E73* - ID_OUI_FROM_DATABASE=Calibre UK LTD +OUI:00230E* + ID_OUI_FROM_DATABASE=Gorba AG -OUI:F06281* - ID_OUI_FROM_DATABASE=ProCurve Networking by HP +OUI:002307* + ID_OUI_FROM_DATABASE=FUTURE INNOVATION TECH CO.,LTD -OUI:003A9B* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:002302* + ID_OUI_FROM_DATABASE=Cobalt Digital, Inc. -OUI:2C9127* - ID_OUI_FROM_DATABASE=Eintechno Corporation +OUI:0022EB* + ID_OUI_FROM_DATABASE=Data Respons A/S -OUI:C09C92* - ID_OUI_FROM_DATABASE=COBY +OUI:0022EC* + ID_OUI_FROM_DATABASE=IDEALBT TECHNOLOGY CORPORATION -OUI:849000* - ID_OUI_FROM_DATABASE=Arnold & Richter Cine Technik +OUI:0022F1* + ID_OUI_FROM_DATABASE=Private -OUI:C87248* - ID_OUI_FROM_DATABASE=Aplicom Oy +OUI:00239E* + ID_OUI_FROM_DATABASE=Jiangsu Lemote Technology Corporation Limited -OUI:74D850* - ID_OUI_FROM_DATABASE=Evrisko Systems +OUI:002398* + ID_OUI_FROM_DATABASE=Vutlan sro -OUI:6CAC60* - ID_OUI_FROM_DATABASE=Venetex Corp +OUI:002384* + ID_OUI_FROM_DATABASE=GGH Engineering s.r.l. -OUI:DC0265* - ID_OUI_FROM_DATABASE=Meditech Kft +OUI:002342* + ID_OUI_FROM_DATABASE=Coffee Equipment Company -OUI:986DC8* - ID_OUI_FROM_DATABASE=TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORPORATION +OUI:002336* + ID_OUI_FROM_DATABASE=METEL s.r.o. -OUI:68A1B7* - ID_OUI_FROM_DATABASE=Honghao Mingchuan Technology (Beijing) CO.,Ltd. +OUI:00233D* + ID_OUI_FROM_DATABASE=Novero holding B.V. -OUI:7CCFCF* - ID_OUI_FROM_DATABASE=Shanghai SEARI Intelligent System Co., Ltd +OUI:002330* + ID_OUI_FROM_DATABASE=DIZIPIA, INC. -OUI:EC3091* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00232C* + ID_OUI_FROM_DATABASE=Senticare -OUI:3032D4* - ID_OUI_FROM_DATABASE=Hanilstm Co., Ltd. +OUI:002320* + ID_OUI_FROM_DATABASE=Nicira Networks -OUI:0026EE* - ID_OUI_FROM_DATABASE=TKM GmbH +OUI:00231D* + ID_OUI_FROM_DATABASE=Deltacom Electronics Ltd -OUI:0026E7* - ID_OUI_FROM_DATABASE=Shanghai ONLAN Communication Tech. Co., Ltd. +OUI:00231E* + ID_OUI_FROM_DATABASE=Cezzer Multimedia Technologies -OUI:0026E1* - ID_OUI_FROM_DATABASE=Stanford University, OpenFlow Group +OUI:0022B8* + ID_OUI_FROM_DATABASE=Norcott -OUI:0026DB* - ID_OUI_FROM_DATABASE=Ionics EMS Inc. +OUI:0022B7* + ID_OUI_FROM_DATABASE=GSS Grundig SAT-Systems GmbH -OUI:0026CE* - ID_OUI_FROM_DATABASE=Kozumi USA Corp. +OUI:0022B2* + ID_OUI_FROM_DATABASE=4RF Communications Ltd -OUI:0026D5* - ID_OUI_FROM_DATABASE=Ory Solucoes em Comercio de Informatica Ltda. +OUI:0022AB* + ID_OUI_FROM_DATABASE=Shenzhen Turbosight Technology Ltd -OUI:0026C8* - ID_OUI_FROM_DATABASE=System Sensor +OUI:0022A6* + ID_OUI_FROM_DATABASE=Sony Computer Entertainment America -OUI:002711* - ID_OUI_FROM_DATABASE=LanPro Inc +OUI:00229F* + ID_OUI_FROM_DATABASE=Sensys Traffic AB -OUI:00270D* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0022E5* + ID_OUI_FROM_DATABASE=Fisher-Rosemount Systems Inc. -OUI:002707* - ID_OUI_FROM_DATABASE=Lift Complex DS, JSC +OUI:0022DE* + ID_OUI_FROM_DATABASE=OPPO Digital, Inc. -OUI:002700* - ID_OUI_FROM_DATABASE=Shenzhen Siglent Technology Co., Ltd. +OUI:0022D9* + ID_OUI_FROM_DATABASE=Fortex Industrial Ltd. -OUI:0026FA* - ID_OUI_FROM_DATABASE=BandRich Inc. +OUI:0022D2* + ID_OUI_FROM_DATABASE=All Earth Comércio de Eletrônicos LTDA. -OUI:0026F4* - ID_OUI_FROM_DATABASE=Nesslab +OUI:0022CC* + ID_OUI_FROM_DATABASE=SciLog, Inc. -OUI:0025D7* - ID_OUI_FROM_DATABASE=CEDO +OUI:0022C8* + ID_OUI_FROM_DATABASE=Applied Instruments B.V. -OUI:0025D2* - ID_OUI_FROM_DATABASE=InpegVision Co., Ltd +OUI:0022BE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0025D1* - ID_OUI_FROM_DATABASE=Eastern Asia Technology Limited +OUI:00228C* + ID_OUI_FROM_DATABASE=Photon Europe GmbH -OUI:0025CB* - ID_OUI_FROM_DATABASE=Reiner SCT +OUI:002286* + ID_OUI_FROM_DATABASE=ASTRON -OUI:0025C4* - ID_OUI_FROM_DATABASE=Ruckus Wireless +OUI:002285* + ID_OUI_FROM_DATABASE=NOMUS COMM SYSTEMS -OUI:0025BF* - ID_OUI_FROM_DATABASE=Wireless Cables Inc. +OUI:002280* + ID_OUI_FROM_DATABASE=A2B Electronics AB -OUI:0025B1* - ID_OUI_FROM_DATABASE=Maya-Creation Corporation +OUI:002276* + ID_OUI_FROM_DATABASE=Triple EYE B.V. -OUI:0025B8* - ID_OUI_FROM_DATABASE=Agile Communications, Inc. +OUI:00227B* + ID_OUI_FROM_DATABASE=Apogee Labs, Inc. -OUI:0025B2* - ID_OUI_FROM_DATABASE=MBDA Deutschland GmbH +OUI:002262* + ID_OUI_FROM_DATABASE=BEP Marine -OUI:0025AC* - ID_OUI_FROM_DATABASE=I-Tech corporation +OUI:00226C* + ID_OUI_FROM_DATABASE=LinkSprite Technologies, Inc. -OUI:0026C2* - ID_OUI_FROM_DATABASE=SCDI Co. LTD +OUI:00225E* + ID_OUI_FROM_DATABASE=Uwin Technologies Co.,LTD -OUI:0026BC* - ID_OUI_FROM_DATABASE=General Jack Technology Ltd. +OUI:002258* + ID_OUI_FROM_DATABASE=Taiyo Yuden Co., Ltd. -OUI:0026B4* - ID_OUI_FROM_DATABASE=Ford Motor Company +OUI:0023C3* + ID_OUI_FROM_DATABASE=LogMeIn, Inc. -OUI:0026AE* - ID_OUI_FROM_DATABASE=Wireless Measurement Ltd +OUI:0023BD* + ID_OUI_FROM_DATABASE=Digital Ally, Inc. -OUI:0026AA* - ID_OUI_FROM_DATABASE=Kenmec Mechanical Engineering Co., Ltd. +OUI:0023B7* + ID_OUI_FROM_DATABASE=Q-Light Co., Ltd. -OUI:0026A4* - ID_OUI_FROM_DATABASE=Novus Produtos Eletronicos Ltda +OUI:0023B1* + ID_OUI_FROM_DATABASE=Longcheer Technology (Singapore) Pte Ltd -OUI:002698* +OUI:0023B0* + ID_OUI_FROM_DATABASE=COMXION Technology Inc. + +OUI:0023AB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00269D* - ID_OUI_FROM_DATABASE=M2Mnet Co., Ltd. +OUI:0023A4* + ID_OUI_FROM_DATABASE=New Concepts Development Corp. -OUI:00268B* - ID_OUI_FROM_DATABASE=Guangzhou Escene Computer Technology Limited +OUI:001FC0* + ID_OUI_FROM_DATABASE=Control Express Finland Oy -OUI:002685* - ID_OUI_FROM_DATABASE=Digital Innovation +OUI:001FBB* + ID_OUI_FROM_DATABASE=Xenatech Co.,LTD -OUI:002678* - ID_OUI_FROM_DATABASE=Logic Instrument SA +OUI:001FB4* + ID_OUI_FROM_DATABASE=SmartShare Systems -OUI:002672* - ID_OUI_FROM_DATABASE=AAMP of America +OUI:001FAD* + ID_OUI_FROM_DATABASE=Brown Innovations, Inc -OUI:00266B* - ID_OUI_FROM_DATABASE=SHINE UNION ENTERPRISE LIMITED +OUI:001FAF* + ID_OUI_FROM_DATABASE=NextIO, Inc. -OUI:002666* - ID_OUI_FROM_DATABASE=EFM Networks +OUI:001FAE* + ID_OUI_FROM_DATABASE=Blick South Africa (Pty) Ltd -OUI:002665* - ID_OUI_FROM_DATABASE=ProtectedLogic Corporation +OUI:001FA8* + ID_OUI_FROM_DATABASE=Smart Energy Instruments Inc. -OUI:002651* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001FA3* + ID_OUI_FROM_DATABASE=T&W Electronics(Shenzhen)Co.,Ltd. -OUI:002652* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:002142* + ID_OUI_FROM_DATABASE=Advanced Control Systems doo -OUI:002646* - ID_OUI_FROM_DATABASE=SHENYANG TONGFANG MULTIMEDIA TECHNOLOGY COMPANY LIMITED +OUI:002140* + ID_OUI_FROM_DATABASE=EN Technologies Inc. -OUI:002640* - ID_OUI_FROM_DATABASE=Baustem Broadband Technologies, Ltd. +OUI:002138* + ID_OUI_FROM_DATABASE=Cepheid -OUI:00263A* - ID_OUI_FROM_DATABASE=Digitec Systems +OUI:00212E* + ID_OUI_FROM_DATABASE=dresden-elektronik -OUI:002634* - ID_OUI_FROM_DATABASE=Infineta Systems, Inc +OUI:002128* + ID_OUI_FROM_DATABASE=Oracle Corporation -OUI:002633* - ID_OUI_FROM_DATABASE=MIR - Medical International Research +OUI:002122* + ID_OUI_FROM_DATABASE=Chip-pro Ltd. -OUI:00262E* - ID_OUI_FROM_DATABASE=Chengdu Jiuzhou Electronic Technology Inc +OUI:00211B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:002627* - ID_OUI_FROM_DATABASE=Truesell +OUI:002115* + ID_OUI_FROM_DATABASE=PHYWE Systeme GmbH & Co. KG -OUI:002621* - ID_OUI_FROM_DATABASE=InteliCloud Technology Inc. +OUI:002116* + ID_OUI_FROM_DATABASE=Transcon Electronic Systems, spol. s r. o. -OUI:00261B* - ID_OUI_FROM_DATABASE=LAUREL BANK MACHINES CO., LTD. +OUI:00210F* + ID_OUI_FROM_DATABASE=Cernium Corp -OUI:002614* - ID_OUI_FROM_DATABASE=KTNF +OUI:00210B* + ID_OUI_FROM_DATABASE=GEMINI TRAZE RFID PVT. LTD. -OUI:00260E* - ID_OUI_FROM_DATABASE=Ablaze Systems, LLC +OUI:00210C* + ID_OUI_FROM_DATABASE=Cymtec Systems, Inc. -OUI:002602* - ID_OUI_FROM_DATABASE=SMART Temps LLC +OUI:001FFC* + ID_OUI_FROM_DATABASE=Riccius+Sohn GmbH -OUI:002601* - ID_OUI_FROM_DATABASE=Cutera Inc +OUI:001FF7* + ID_OUI_FROM_DATABASE=Nakajima All Precision Co., Ltd. -OUI:0025F7* - ID_OUI_FROM_DATABASE=Ansaldo STS USA +OUI:00216E* + ID_OUI_FROM_DATABASE=Function ATI (Huizhou) Telecommunications Co., Ltd. -OUI:0025FC* - ID_OUI_FROM_DATABASE=ENDA ENDUSTRIYEL ELEKTRONIK LTD. STI. +OUI:002168* + ID_OUI_FROM_DATABASE=iVeia, LLC -OUI:0025ED* - ID_OUI_FROM_DATABASE=NuVo Technologies LLC +OUI:002161* + ID_OUI_FROM_DATABASE=Yournet Inc. -OUI:0025EE* - ID_OUI_FROM_DATABASE=Avtex Ltd +OUI:002155* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0025E8* - ID_OUI_FROM_DATABASE=Idaho Technology +OUI:00214E* + ID_OUI_FROM_DATABASE=GS Yuasa Power Supply Ltd. -OUI:0025E3* - ID_OUI_FROM_DATABASE=Hanshinit Inc. +OUI:002149* + ID_OUI_FROM_DATABASE=China Daheng Group ,Inc. -OUI:0025DE* - ID_OUI_FROM_DATABASE=Probits Co., LTD. +OUI:001FF0* + ID_OUI_FROM_DATABASE=Audio Partnership -OUI:002579* - ID_OUI_FROM_DATABASE=J & F Labs +OUI:001FE9* + ID_OUI_FROM_DATABASE=Printrex, Inc. -OUI:00257E* - ID_OUI_FROM_DATABASE=NEW POS Technology Limited +OUI:001FEB* + ID_OUI_FROM_DATABASE=Trio Datacom Pty Ltd -OUI:002572* - ID_OUI_FROM_DATABASE=Nemo-Q International AB +OUI:001FEA* + ID_OUI_FROM_DATABASE=Applied Media Technologies Corporation -OUI:00256B* - ID_OUI_FROM_DATABASE=ATENIX E.E. s.r.l. +OUI:001FDD* + ID_OUI_FROM_DATABASE=GDI LLC -OUI:00256C* - ID_OUI_FROM_DATABASE=Azimut Production Association JSC +OUI:001FD8* + ID_OUI_FROM_DATABASE=A-TRUST COMPUTER CORPORATION -OUI:00255F* - ID_OUI_FROM_DATABASE=SenTec AG +OUI:001FD3* + ID_OUI_FROM_DATABASE=RIVA Networks Inc. -OUI:00255A* - ID_OUI_FROM_DATABASE=Tantalus Systems Corp. +OUI:001FCE* + ID_OUI_FROM_DATABASE=QTECH LLC -OUI:002559* - ID_OUI_FROM_DATABASE=Syphan Technologies Ltd +OUI:00219D* + ID_OUI_FROM_DATABASE=Adesys BV -OUI:0025A5* - ID_OUI_FROM_DATABASE=Walnut Media Network +OUI:0021A1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00259F* - ID_OUI_FROM_DATABASE=TechnoDigital Technologies GmbH +OUI:002198* + ID_OUI_FROM_DATABASE=Thai Radio Co, LTD -OUI:002599* - ID_OUI_FROM_DATABASE=Hedon e.d. B.V. +OUI:002193* + ID_OUI_FROM_DATABASE=Videofon MV -OUI:002592* - ID_OUI_FROM_DATABASE=Guangzhou Shirui Electronic Co., Ltd +OUI:00218D* + ID_OUI_FROM_DATABASE=AP Router Ind. Eletronica LTDA -OUI:00258D* - ID_OUI_FROM_DATABASE=Haier +OUI:00218E* + ID_OUI_FROM_DATABASE=MEKICS CO., LTD. -OUI:002588* - ID_OUI_FROM_DATABASE=Genie Industries, Inc. +OUI:002187* + ID_OUI_FROM_DATABASE=Imacs GmbH -OUI:002583* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:002181* + ID_OUI_FROM_DATABASE=Si2 Microsystems Limited -OUI:00254C* - ID_OUI_FROM_DATABASE=Videon Central, Inc. +OUI:00217B* + ID_OUI_FROM_DATABASE=Bastec AB -OUI:002536* - ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd. +OUI:002174* + ID_OUI_FROM_DATABASE=AvaLAN Wireless -OUI:00253D* - ID_OUI_FROM_DATABASE=DRS Consolidated Controls +OUI:0021F8* + ID_OUI_FROM_DATABASE=Enseo, Inc. -OUI:002540* - ID_OUI_FROM_DATABASE=Quasar Technologies, Inc. +OUI:0021F3* + ID_OUI_FROM_DATABASE=Si14 SpA -OUI:002533* - ID_OUI_FROM_DATABASE=WITTENSTEIN AG +OUI:0021EC* + ID_OUI_FROM_DATABASE=Solutronic GmbH -OUI:00252C* - ID_OUI_FROM_DATABASE=Entourage Systems, Inc. +OUI:0021E6* + ID_OUI_FROM_DATABASE=Starlight Video Limited -OUI:002502* - ID_OUI_FROM_DATABASE=NaturalPoint +OUI:0021E0* + ID_OUI_FROM_DATABASE=CommAgility Ltd -OUI:0024FB* - ID_OUI_FROM_DATABASE=Private +OUI:0021D3* + ID_OUI_FROM_DATABASE=BOCOM SECURITY(ASIA PACIFIC) LIMITED -OUI:0024F6* - ID_OUI_FROM_DATABASE=MIYOSHI ELECTRONICS CORPORATION +OUI:0021D4* + ID_OUI_FROM_DATABASE=Vollmer Werke GmbH -OUI:0024EA* - ID_OUI_FROM_DATABASE=iris-GmbH infrared & intelligent sensors +OUI:0021D9* + ID_OUI_FROM_DATABASE=SEKONIC CORPORATION -OUI:0024E3* - ID_OUI_FROM_DATABASE=CAO Group +OUI:0021CD* + ID_OUI_FROM_DATABASE=LiveTV -OUI:002527* - ID_OUI_FROM_DATABASE=Bitrode Corp. +OUI:0021C7* + ID_OUI_FROM_DATABASE=Russound -OUI:002524* - ID_OUI_FROM_DATABASE=Lightcomm Technology Co., Ltd +OUI:0021C6* + ID_OUI_FROM_DATABASE=CSJ Global, Inc. -OUI:00251F* - ID_OUI_FROM_DATABASE=ZYNUS VISION INC. +OUI:0021C1* + ID_OUI_FROM_DATABASE=ABB Oy / Medium Voltage Products -OUI:00251A* - ID_OUI_FROM_DATABASE=Psiber Data Systems Inc. +OUI:0021B4* + ID_OUI_FROM_DATABASE=APRO MEDIA CO., LTD -OUI:002515* - ID_OUI_FROM_DATABASE=SFR +OUI:0021AE* + ID_OUI_FROM_DATABASE=ALCATEL-LUCENT FRANCE - WTD -OUI:00250E* - ID_OUI_FROM_DATABASE=gt german telematics gmbh +OUI:0021A2* + ID_OUI_FROM_DATABASE=EKE-Electronics Ltd. -OUI:002507* - ID_OUI_FROM_DATABASE=ASTAK Inc. +OUI:0021A7* + ID_OUI_FROM_DATABASE=Hantle System Co., Ltd. -OUI:002509* - ID_OUI_FROM_DATABASE=SHARETRONIC Group LTD +OUI:00221F* + ID_OUI_FROM_DATABASE=eSang Technologies Co., Ltd. -OUI:002437* - ID_OUI_FROM_DATABASE=Motorola - BSG +OUI:002226* + ID_OUI_FROM_DATABASE=Avaak, Inc. -OUI:00243C* - ID_OUI_FROM_DATABASE=S.A.A.A. +OUI:00221A* + ID_OUI_FROM_DATABASE=Audio Precision -OUI:002430* - ID_OUI_FROM_DATABASE=Ruby Tech Corp. +OUI:002213* + ID_OUI_FROM_DATABASE=PCI CORPORATION -OUI:0023FB* - ID_OUI_FROM_DATABASE=IP Datatel, LLC. +OUI:00220D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0023F3* - ID_OUI_FROM_DATABASE=Glocom, Inc. +OUI:00220C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0023EF* - ID_OUI_FROM_DATABASE=Zuend Systemtechnik AG +OUI:002202* + ID_OUI_FROM_DATABASE=Excito Elektronik i Skåne AB -OUI:0023E9* - ID_OUI_FROM_DATABASE=F5 Networks, Inc. +OUI:0021F9* + ID_OUI_FROM_DATABASE=WIRECOM Technologies -OUI:0023E3* - ID_OUI_FROM_DATABASE=Microtronic AG +OUI:001F40* + ID_OUI_FROM_DATABASE=Speakercraft Inc. -OUI:0023E2* - ID_OUI_FROM_DATABASE=SEA Signalisation +OUI:001F38* + ID_OUI_FROM_DATABASE=POSITRON -OUI:0023DD* - ID_OUI_FROM_DATABASE=ELGIN S.A. +OUI:001F3D* + ID_OUI_FROM_DATABASE=Qbit GmbH -OUI:0023D0* - ID_OUI_FROM_DATABASE=Uniloc USA Inc. +OUI:001F37* + ID_OUI_FROM_DATABASE=Genesis I&C -OUI:0023CA* - ID_OUI_FROM_DATABASE=Behind The Set, LLC +OUI:001F2A* + ID_OUI_FROM_DATABASE=ACCM -OUI:0024B0* - ID_OUI_FROM_DATABASE=ESAB AB +OUI:001F31* + ID_OUI_FROM_DATABASE=Radiocomp -OUI:0024A9* - ID_OUI_FROM_DATABASE=Ag Leader Technology +OUI:001F25* + ID_OUI_FROM_DATABASE=MBS GmbH -OUI:0024A2* - ID_OUI_FROM_DATABASE=Hong Kong Middleware Technology Limited +OUI:001F1E* + ID_OUI_FROM_DATABASE=Astec Technology Co., Ltd -OUI:0024A4* - ID_OUI_FROM_DATABASE=Siklu Communication +OUI:001F17* + ID_OUI_FROM_DATABASE=IDX Company, Ltd. -OUI:00249D* - ID_OUI_FROM_DATABASE=NES Technology Inc. +OUI:001F18* + ID_OUI_FROM_DATABASE=Hakusan.Mfg.Co,.Ltd -OUI:00248A* - ID_OUI_FROM_DATABASE=Kaga Electronics Co., Ltd. +OUI:001E61* + ID_OUI_FROM_DATABASE=ITEC GmbH -OUI:00248F* - ID_OUI_FROM_DATABASE=DO-MONIX +OUI:001E5C* + ID_OUI_FROM_DATABASE=RB GeneralEkonomik -OUI:002496* - ID_OUI_FROM_DATABASE=Ginzinger electronic systems +OUI:001E5B* + ID_OUI_FROM_DATABASE=Unitron Company, Inc. -OUI:002477* - ID_OUI_FROM_DATABASE=Tibbo Technology +OUI:001E55* + ID_OUI_FROM_DATABASE=COWON SYSTEMS,Inc. -OUI:002470* - ID_OUI_FROM_DATABASE=AUROTECH ultrasound AS. +OUI:001E4E* + ID_OUI_FROM_DATABASE=DAKO EDV-Ingenieur- und Systemhaus GmbH -OUI:002472* - ID_OUI_FROM_DATABASE=ReDriven Power Inc. +OUI:001E49* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00246B* - ID_OUI_FROM_DATABASE=Covia, Inc. +OUI:001E44* + ID_OUI_FROM_DATABASE=SANTEC -OUI:002464* - ID_OUI_FROM_DATABASE=Bridge Technologies Co AS +OUI:001E3F* + ID_OUI_FROM_DATABASE=TrellisWare Technologies, Inc. -OUI:00245F* - ID_OUI_FROM_DATABASE=Vine Telecom CO.,Ltd. +OUI:001E38* + ID_OUI_FROM_DATABASE=Bluecard Software Technology Co., Ltd. -OUI:002420* - ID_OUI_FROM_DATABASE=NetUP Inc. +OUI:001E31* + ID_OUI_FROM_DATABASE=INFOMARK CO.,LTD. -OUI:002426* - ID_OUI_FROM_DATABASE=NOHMI BOSAI LTD. +OUI:001E32* + ID_OUI_FROM_DATABASE=Zensys -OUI:00241A* - ID_OUI_FROM_DATABASE=Red Beetle Inc. +OUI:001E2C* + ID_OUI_FROM_DATABASE=CyVerse Corporation -OUI:002413* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001E20* + ID_OUI_FROM_DATABASE=Intertain Inc. -OUI:00240D* - ID_OUI_FROM_DATABASE=OnePath Networks LTD. +OUI:001E19* + ID_OUI_FROM_DATABASE=GTRI -OUI:00240E* - ID_OUI_FROM_DATABASE=Inventec Besta Co., Ltd. +OUI:001E0F* + ID_OUI_FROM_DATABASE=Briot International -OUI:002407* - ID_OUI_FROM_DATABASE=TELEM SAS +OUI:001EE4* + ID_OUI_FROM_DATABASE=ACS Solutions France -OUI:002400* - ID_OUI_FROM_DATABASE=Nortel Networks +OUI:001EEB* + ID_OUI_FROM_DATABASE=Talk-A-Phone Co. -OUI:0024D0* - ID_OUI_FROM_DATABASE=Shenzhen SOGOOD Industry CO.,LTD. +OUI:001EDF* + ID_OUI_FROM_DATABASE=Master Industrialization Center Kista -OUI:0024D5* - ID_OUI_FROM_DATABASE=Winward Industrial Limited +OUI:001EDA* + ID_OUI_FROM_DATABASE=Wesemann Elektrotechniek B.V. -OUI:0024C9* - ID_OUI_FROM_DATABASE=Broadband Solutions Group +OUI:001ED5* + ID_OUI_FROM_DATABASE=Tekon-Automatics -OUI:0024C4* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001ECE* + ID_OUI_FROM_DATABASE=BISA Technologies (Hong Kong) Limited -OUI:0024BF* - ID_OUI_FROM_DATABASE=CIAT +OUI:001EC8* + ID_OUI_FROM_DATABASE=Rapid Mobile (Pty) Ltd -OUI:0024B5* - ID_OUI_FROM_DATABASE=Nortel Networks +OUI:001EBB* + ID_OUI_FROM_DATABASE=BLUELIGHT TECHNOLOGY INC. -OUI:00245A* - ID_OUI_FROM_DATABASE=Nanjing Panda Electronics Company Limited +OUI:001EB6* + ID_OUI_FROM_DATABASE=TAG Heuer SA -OUI:002453* - ID_OUI_FROM_DATABASE=Initra d.o.o. +OUI:001EB5* + ID_OUI_FROM_DATABASE=Ever Sparkle Technologies Ltd -OUI:00244D* - ID_OUI_FROM_DATABASE=Hokkaido Electronics Corporation +OUI:001EAF* + ID_OUI_FROM_DATABASE=Ophir Optronics Ltd -OUI:002452* - ID_OUI_FROM_DATABASE=Silicon Software GmbH +OUI:001EAA* + ID_OUI_FROM_DATABASE=E-Senza Technologies GmbH -OUI:002446* - ID_OUI_FROM_DATABASE=MMB Research Inc. +OUI:001E9D* + ID_OUI_FROM_DATABASE=Recall Technologies, Inc. -OUI:002441* - ID_OUI_FROM_DATABASE=Wanzl Metallwarenfabrik GmbH +OUI:001E98* + ID_OUI_FROM_DATABASE=GreenLine Communications -OUI:002368* - ID_OUI_FROM_DATABASE=Zebra Technologies Inc +OUI:001E97* + ID_OUI_FROM_DATABASE=Medium Link System Technology CO., LTD, -OUI:00236F* - ID_OUI_FROM_DATABASE=DAQ System +OUI:001E91* + ID_OUI_FROM_DATABASE=KIMIN Electronic Co., Ltd. -OUI:002362* - ID_OUI_FROM_DATABASE=Goldline Controls +OUI:001E8A* + ID_OUI_FROM_DATABASE=eCopy, Inc -OUI:002361* - ID_OUI_FROM_DATABASE=Unigen Corporation +OUI:001E85* + ID_OUI_FROM_DATABASE=Lagotek Corporation -OUI:00235C* - ID_OUI_FROM_DATABASE=Aprius, Inc. +OUI:001E78* + ID_OUI_FROM_DATABASE=Owitek Technology Ltd., -OUI:002355* - ID_OUI_FROM_DATABASE=Kinco Automation(Shanghai) Ltd. +OUI:001E6D* + ID_OUI_FROM_DATABASE=IT R&D Center -OUI:00234F* - ID_OUI_FROM_DATABASE=Luminous Power Technologies Pvt. Ltd. +OUI:001E6E* + ID_OUI_FROM_DATABASE=Shenzhen First Mile Communications Ltd -OUI:002350* - ID_OUI_FROM_DATABASE=LynTec +OUI:001F71* + ID_OUI_FROM_DATABASE=xG Technology, Inc. -OUI:002349* - ID_OUI_FROM_DATABASE=Helmholtz Centre Berlin for Material and Energy +OUI:001F72* + ID_OUI_FROM_DATABASE=QingDao Hiphone Technology Co,.Ltd -OUI:002244* - ID_OUI_FROM_DATABASE=Chengdu Linkon Communications Device Co., Ltd +OUI:001F76* + ID_OUI_FROM_DATABASE=AirLogic Systems Inc. -OUI:00224F* - ID_OUI_FROM_DATABASE=Byzoro Networks Ltd. +OUI:001F6C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:002248* - ID_OUI_FROM_DATABASE=Microsoft Corporation +OUI:001F60* + ID_OUI_FROM_DATABASE=COMPASS SYSTEMS CORP. -OUI:00223E* - ID_OUI_FROM_DATABASE=IRTrans GmbH +OUI:001F65* + ID_OUI_FROM_DATABASE=KOREA ELECTRIC TERMINAL CO., LTD. -OUI:002239* - ID_OUI_FROM_DATABASE=Indiana Life Sciences Incorporated +OUI:001F5F* + ID_OUI_FROM_DATABASE=Blatand GmbH -OUI:002232* - ID_OUI_FROM_DATABASE=Design Design Technology Ltd +OUI:001F59* + ID_OUI_FROM_DATABASE=Kronback Tracers -OUI:00222C* - ID_OUI_FROM_DATABASE=Ceton Corp +OUI:001F4D* + ID_OUI_FROM_DATABASE=Segnetics LLC -OUI:00230E* - ID_OUI_FROM_DATABASE=Gorba AG +OUI:001F52* + ID_OUI_FROM_DATABASE=UVT Unternehmensberatung fur Verkehr und Technik GmbH -OUI:002307* - ID_OUI_FROM_DATABASE=FUTURE INNOVATION TECH CO.,LTD +OUI:001F03* + ID_OUI_FROM_DATABASE=NUM AG -OUI:002302* - ID_OUI_FROM_DATABASE=Cobalt Digital, Inc. +OUI:001EFE* + ID_OUI_FROM_DATABASE=LEVEL s.r.o. -OUI:0022EB* - ID_OUI_FROM_DATABASE=Data Respons A/S +OUI:001F04* + ID_OUI_FROM_DATABASE=Granch Ltd. -OUI:0022EC* - ID_OUI_FROM_DATABASE=IDEALBT TECHNOLOGY CORPORATION +OUI:001EF2* + ID_OUI_FROM_DATABASE=Micro Motion Inc -OUI:0022F1* - ID_OUI_FROM_DATABASE=Private +OUI:001EF7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00239E* - ID_OUI_FROM_DATABASE=Jiangsu Lemote Technology Corporation Limited +OUI:001EF1* + ID_OUI_FROM_DATABASE=Servimat -OUI:002398* - ID_OUI_FROM_DATABASE=Vutlan sro +OUI:001F9E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00238A* - ID_OUI_FROM_DATABASE=Ciena Corporation +OUI:001F92* + ID_OUI_FROM_DATABASE=VideoIQ, Inc. -OUI:002384* - ID_OUI_FROM_DATABASE=GGH Engineering s.r.l. +OUI:001F97* + ID_OUI_FROM_DATABASE=BERTANA srl -OUI:002342* - ID_OUI_FROM_DATABASE=Coffee Equipment Company +OUI:001F8B* + ID_OUI_FROM_DATABASE=Cache IQ -OUI:002336* - ID_OUI_FROM_DATABASE=METEL s.r.o. +OUI:001F84* + ID_OUI_FROM_DATABASE=Gigle Semiconductor -OUI:00233D* - ID_OUI_FROM_DATABASE=Novero holding B.V. +OUI:001F7F* + ID_OUI_FROM_DATABASE=Phabrix Limited -OUI:002330* - ID_OUI_FROM_DATABASE=DIZIPIA, INC. +OUI:001CFF* + ID_OUI_FROM_DATABASE=Napera Networks Inc -OUI:00232C* - ID_OUI_FROM_DATABASE=Senticare +OUI:001CF8* + ID_OUI_FROM_DATABASE=Parade Technologies, Ltd. -OUI:002320* - ID_OUI_FROM_DATABASE=Nicira Networks +OUI:001CF1* + ID_OUI_FROM_DATABASE=SUPoX Technology Co. , LTD. -OUI:00231D* - ID_OUI_FROM_DATABASE=Deltacom Electronics Ltd +OUI:001CF2* + ID_OUI_FROM_DATABASE=Tenlon Technology Co.,Ltd. -OUI:00231E* - ID_OUI_FROM_DATABASE=Cezzer Multimedia Technologies +OUI:001CEC* + ID_OUI_FROM_DATABASE=Mobilesoft (Aust.) Pty Ltd -OUI:0022B8* - ID_OUI_FROM_DATABASE=Norcott +OUI:001CE7* + ID_OUI_FROM_DATABASE=Rocon PLC Research Centre -OUI:0022B7* - ID_OUI_FROM_DATABASE=GSS Grundig SAT-Systems GmbH +OUI:001CE2* + ID_OUI_FROM_DATABASE=Attero Tech, LLC. -OUI:0022B2* - ID_OUI_FROM_DATABASE=4RF Communications Ltd +OUI:001CDB* + ID_OUI_FROM_DATABASE=CARPOINT CO.,LTD -OUI:0022AB* - ID_OUI_FROM_DATABASE=Shenzhen Turbosight Technology Ltd +OUI:001CD5* + ID_OUI_FROM_DATABASE=ZeeVee, Inc. -OUI:0022A6* - ID_OUI_FROM_DATABASE=Sony Computer Entertainment America +OUI:001CCF* + ID_OUI_FROM_DATABASE=LIMETEK -OUI:00229F* - ID_OUI_FROM_DATABASE=Sensys Traffic AB +OUI:001E08* + ID_OUI_FROM_DATABASE=Centec Networks Inc -OUI:0022E5* - ID_OUI_FROM_DATABASE=Fisher-Rosemount Systems Inc. +OUI:001E03* + ID_OUI_FROM_DATABASE=LiComm Co., Ltd. -OUI:0022DE* - ID_OUI_FROM_DATABASE=OPPO Digital, Inc. +OUI:001DFC* + ID_OUI_FROM_DATABASE=KSIC -OUI:0022D9* - ID_OUI_FROM_DATABASE=Fortex Industrial Ltd. +OUI:001DF5* + ID_OUI_FROM_DATABASE=Sunshine Co,LTD -OUI:0022D2* - ID_OUI_FROM_DATABASE=All Earth Comércio de Eletrônicos LTDA. +OUI:001DF0* + ID_OUI_FROM_DATABASE=Vidient Systems, Inc. -OUI:0022CC* - ID_OUI_FROM_DATABASE=SciLog, Inc. +OUI:001DDC* + ID_OUI_FROM_DATABASE=HangZhou DeChangLong Tech&Info Co.,Ltd -OUI:0022C8* - ID_OUI_FROM_DATABASE=Applied Instruments B.V. +OUI:001DE4* + ID_OUI_FROM_DATABASE=Visioneered Image Systems -OUI:0022BE* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001DE2* + ID_OUI_FROM_DATABASE=Radionor Communications -OUI:00228C* - ID_OUI_FROM_DATABASE=Photon Europe GmbH +OUI:001CC8* + ID_OUI_FROM_DATABASE=INDUSTRONIC Industrie-Electronic GmbH & Co. KG -OUI:002286* - ID_OUI_FROM_DATABASE=ASTRON +OUI:001CBC* + ID_OUI_FROM_DATABASE=CastGrabber, LLC -OUI:002285* - ID_OUI_FROM_DATABASE=NOMUS COMM SYSTEMS +OUI:001CB2* + ID_OUI_FROM_DATABASE=BPT SPA -OUI:002280* - ID_OUI_FROM_DATABASE=A2B Electronics AB +OUI:001CA6* + ID_OUI_FROM_DATABASE=Win4NET -OUI:002276* - ID_OUI_FROM_DATABASE=Triple EYE B.V. +OUI:001CAB* + ID_OUI_FROM_DATABASE=Meyer Sound Laboratories, Inc. -OUI:00227B* - ID_OUI_FROM_DATABASE=Apogee Labs, Inc. +OUI:001CAC* + ID_OUI_FROM_DATABASE=Qniq Technology Corp. -OUI:002262* - ID_OUI_FROM_DATABASE=BEP Marine +OUI:001CA1* + ID_OUI_FROM_DATABASE=AKAMAI TECHNOLOGIES, INC. -OUI:00226C* - ID_OUI_FROM_DATABASE=LinkSprite Technologies, Inc. +OUI:001C95* + ID_OUI_FROM_DATABASE=Opticomm Corporation -OUI:00225E* - ID_OUI_FROM_DATABASE=Uwin Technologies Co.,LTD +OUI:001C90* + ID_OUI_FROM_DATABASE=Empacket Corporation -OUI:002258* - ID_OUI_FROM_DATABASE=Taiyo Yuden Co., Ltd. +OUI:001C8F* + ID_OUI_FROM_DATABASE=Advanced Electronic Design, Inc. -OUI:0023C3* - ID_OUI_FROM_DATABASE=LogMeIn, Inc. +OUI:001C89* + ID_OUI_FROM_DATABASE=Force Communications, Inc. -OUI:0023BD* - ID_OUI_FROM_DATABASE=Digital Ally, Inc. +OUI:001C7F* + ID_OUI_FROM_DATABASE=Check Point Software Technologies -OUI:0023B7* - ID_OUI_FROM_DATABASE=Q-Light Co., Ltd. +OUI:001C75* + ID_OUI_FROM_DATABASE=Segnet Ltd. -OUI:0023B1* - ID_OUI_FROM_DATABASE=Longcheer Technology (Singapore) Pte Ltd +OUI:001C6E* + ID_OUI_FROM_DATABASE=Newbury Networks, Inc. -OUI:0023B0* - ID_OUI_FROM_DATABASE=COMXION Technology Inc. +OUI:001C69* + ID_OUI_FROM_DATABASE=Packet Vision Ltd -OUI:0023AB* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001DA5* + ID_OUI_FROM_DATABASE=WB Electronics -OUI:0023A4* - ID_OUI_FROM_DATABASE=New Concepts Development Corp. +OUI:001DA6* + ID_OUI_FROM_DATABASE=Media Numerics Limited -OUI:001FC0* - ID_OUI_FROM_DATABASE=Control Express Finland Oy +OUI:001DA0* + ID_OUI_FROM_DATABASE=Heng Yu Electronic Manufacturing Company Limited -OUI:001FBB* - ID_OUI_FROM_DATABASE=Xenatech Co.,LTD +OUI:001D99* + ID_OUI_FROM_DATABASE=Cyan Optic, Inc. -OUI:001FB4* - ID_OUI_FROM_DATABASE=SmartShare Systems +OUI:001D94* + ID_OUI_FROM_DATABASE=Climax Technology Co., Ltd -OUI:001FAD* - ID_OUI_FROM_DATABASE=Brown Innovations, Inc +OUI:001D93* + ID_OUI_FROM_DATABASE=Modacom -OUI:001FAF* - ID_OUI_FROM_DATABASE=NextIO, Inc. +OUI:001D8D* + ID_OUI_FROM_DATABASE=Raytek GmbH -OUI:001FAE* - ID_OUI_FROM_DATABASE=Blick South Africa (Pty) Ltd +OUI:001D86* + ID_OUI_FROM_DATABASE=Shinwa Industries(China) Ltd. -OUI:001FA8* - ID_OUI_FROM_DATABASE=Smart Energy Instruments Inc. +OUI:001DC9* + ID_OUI_FROM_DATABASE=GainSpan Corp. -OUI:001FA3* - ID_OUI_FROM_DATABASE=T&W Electronics(Shenzhen)Co.,Ltd. +OUI:001DC2* + ID_OUI_FROM_DATABASE=XORTEC OY -OUI:002142* - ID_OUI_FROM_DATABASE=Advanced Control Systems doo +OUI:001DBD* + ID_OUI_FROM_DATABASE=Versamed Inc. -OUI:002140* - ID_OUI_FROM_DATABASE=EN Technologies Inc. +OUI:001DB6* + ID_OUI_FROM_DATABASE=BestComm Networks, Inc. -OUI:002138* - ID_OUI_FROM_DATABASE=Cepheid +OUI:001DB0* + ID_OUI_FROM_DATABASE=FuJian HengTong Information Technology Co.,Ltd -OUI:00212E* - ID_OUI_FROM_DATABASE=dresden-elektronik +OUI:001DAC* + ID_OUI_FROM_DATABASE=Gigamon Systems LLC -OUI:002128* - ID_OUI_FROM_DATABASE=Oracle Corporation +OUI:001D81* + ID_OUI_FROM_DATABASE=GUANGZHOU GATEWAY ELECTRONICS CO., LTD -OUI:002122* - ID_OUI_FROM_DATABASE=Chip-pro Ltd. +OUI:001D69* + ID_OUI_FROM_DATABASE=Knorr-Bremse IT-Services GmbH -OUI:00211B* +OUI:001D70* ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:002115* - ID_OUI_FROM_DATABASE=PHYWE Systeme GmbH & Co. KG - -OUI:002116* - ID_OUI_FROM_DATABASE=Transcon Electronic Systems, spol. s r. o. +OUI:001D77* + ID_OUI_FROM_DATABASE=NSGate -OUI:00210F* - ID_OUI_FROM_DATABASE=Cernium Corp +OUI:001D7C* + ID_OUI_FROM_DATABASE=ABE Elettronica S.p.A. -OUI:00210B* - ID_OUI_FROM_DATABASE=GEMINI TRAZE RFID PVT. LTD. +OUI:001D64* + ID_OUI_FROM_DATABASE=Adam Communications Systems Int Ltd -OUI:00210C* - ID_OUI_FROM_DATABASE=Cymtec Systems, Inc. +OUI:001D5D* + ID_OUI_FROM_DATABASE=Control Dynamics Pty. Ltd. -OUI:001FFC* - ID_OUI_FROM_DATABASE=Riccius+Sohn GmbH +OUI:001D2E* + ID_OUI_FROM_DATABASE=Ruckus Wireless -OUI:001FF7* - ID_OUI_FROM_DATABASE=Nakajima All Precision Co., Ltd. +OUI:001D21* + ID_OUI_FROM_DATABASE=Alcad SL -OUI:00216E* - ID_OUI_FROM_DATABASE=Function ATI (Huizhou) Telecommunications Co., Ltd. +OUI:001D1C* + ID_OUI_FROM_DATABASE=Gennet s.a. -OUI:002168* - ID_OUI_FROM_DATABASE=iVeia, LLC +OUI:001D17* + ID_OUI_FROM_DATABASE=Digital Sky Corporation -OUI:002161* - ID_OUI_FROM_DATABASE=Yournet Inc. +OUI:001D12* + ID_OUI_FROM_DATABASE=ROHM CO., LTD. -OUI:002155* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001D11* + ID_OUI_FROM_DATABASE=Analogue & Micro Ltd -OUI:00214E* - ID_OUI_FROM_DATABASE=GS Yuasa Power Supply Ltd. +OUI:001D0B* + ID_OUI_FROM_DATABASE=Power Standards Lab -OUI:002149* - ID_OUI_FROM_DATABASE=China Daheng Group ,Inc. +OUI:001D04* + ID_OUI_FROM_DATABASE=Zipit Wireless, Inc. -OUI:001FF0* - ID_OUI_FROM_DATABASE=Audio Partnership +OUI:001D58* + ID_OUI_FROM_DATABASE=CQ Inc -OUI:001FE9* - ID_OUI_FROM_DATABASE=Printrex, Inc. +OUI:001D57* + ID_OUI_FROM_DATABASE=CAETEC Messtechnik -OUI:001FEB* - ID_OUI_FROM_DATABASE=Trio Datacom Pty Ltd +OUI:001D51* + ID_OUI_FROM_DATABASE=Babcock & Wilcox Power Generation Group, Inc -OUI:001FEA* - ID_OUI_FROM_DATABASE=Applied Media Technologies Corporation +OUI:001D47* + ID_OUI_FROM_DATABASE=Covote GmbH & Co KG -OUI:001FDD* - ID_OUI_FROM_DATABASE=GDI LLC +OUI:001D40* + ID_OUI_FROM_DATABASE=Intel – GE Care Innovations LLC -OUI:001FD8* - ID_OUI_FROM_DATABASE=A-TRUST COMPUTER CORPORATION +OUI:001D34* + ID_OUI_FROM_DATABASE=SYRIS Technology Corp -OUI:001FD3* - ID_OUI_FROM_DATABASE=RIVA Networks Inc. +OUI:001D2D* + ID_OUI_FROM_DATABASE=Pylone, Inc. -OUI:001FCE* - ID_OUI_FROM_DATABASE=QTECH LLC +OUI:001B2A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00219D* - ID_OUI_FROM_DATABASE=Adesys BV +OUI:001B1D* + ID_OUI_FROM_DATABASE=Phoenix International Co., Ltd -OUI:0021A1* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001B22* + ID_OUI_FROM_DATABASE=Palit Microsystems ( H.K.) Ltd. -OUI:002198* - ID_OUI_FROM_DATABASE=Thai Radio Co, LTD +OUI:001B1B* + ID_OUI_FROM_DATABASE=Siemens AG, -OUI:002193* - ID_OUI_FROM_DATABASE=Videofon MV +OUI:001B16* + ID_OUI_FROM_DATABASE=Celtro Ltd. -OUI:00218D* - ID_OUI_FROM_DATABASE=AP Router Ind. Eletronica LTDA +OUI:001B0A* + ID_OUI_FROM_DATABASE=Intelligent Distributed Controls Ltd -OUI:00218E* - ID_OUI_FROM_DATABASE=MEKICS CO., LTD. +OUI:001B0F* + ID_OUI_FROM_DATABASE=Petratec -OUI:002187* - ID_OUI_FROM_DATABASE=Imacs GmbH +OUI:001AFE* + ID_OUI_FROM_DATABASE=SOFACREAL -OUI:002181* - ID_OUI_FROM_DATABASE=Si2 Microsystems Limited +OUI:001B03* + ID_OUI_FROM_DATABASE=Action Technology (SZ) Co., Ltd -OUI:00217B* - ID_OUI_FROM_DATABASE=Bastec AB +OUI:001B68* + ID_OUI_FROM_DATABASE=Modnnet Co., Ltd -OUI:002174* - ID_OUI_FROM_DATABASE=AvaLAN Wireless +OUI:001B62* + ID_OUI_FROM_DATABASE=JHT Optoelectronics Co.,Ltd. -OUI:0021F8* - ID_OUI_FROM_DATABASE=Enseo, Inc. +OUI:001B61* + ID_OUI_FROM_DATABASE=Digital Acoustics, LLC -OUI:0021F3* - ID_OUI_FROM_DATABASE=Si14 SpA +OUI:001B5C* + ID_OUI_FROM_DATABASE=Azuretec Co., Ltd. -OUI:0021EC* - ID_OUI_FROM_DATABASE=Solutronic GmbH +OUI:001B55* + ID_OUI_FROM_DATABASE=Hurco Automation Ltd. -OUI:0021E6* - ID_OUI_FROM_DATABASE=Starlight Video Limited +OUI:001B50* + ID_OUI_FROM_DATABASE=Nizhny Novgorod Factory named after M.Frunze, FSUE (NZiF) -OUI:0021E0* - ID_OUI_FROM_DATABASE=CommAgility Ltd +OUI:001B44* + ID_OUI_FROM_DATABASE=SanDisk Corporation -OUI:0021D3* - ID_OUI_FROM_DATABASE=BOCOM SECURITY(ASIA PACIFIC) LIMITED +OUI:001B49* + ID_OUI_FROM_DATABASE=Roberts Radio limited -OUI:0021D4* - ID_OUI_FROM_DATABASE=Vollmer Werke GmbH +OUI:001B42* + ID_OUI_FROM_DATABASE=Wise & Blue -OUI:0021D9* - ID_OUI_FROM_DATABASE=SEKONIC CORPORATION +OUI:001B3D* + ID_OUI_FROM_DATABASE=EuroTel Spa -OUI:0021CD* - ID_OUI_FROM_DATABASE=LiveTV +OUI:001B36* + ID_OUI_FROM_DATABASE=Tsubata Engineering Co.,Ltd. (Head Office) -OUI:0021C7* - ID_OUI_FROM_DATABASE=Russound +OUI:001B31* + ID_OUI_FROM_DATABASE=Neural Image. Co. Ltd. -OUI:0021C6* - ID_OUI_FROM_DATABASE=CSJ Global, Inc. +OUI:001C56* + ID_OUI_FROM_DATABASE=Pado Systems, Inc. -OUI:0021C1* - ID_OUI_FROM_DATABASE=ABB Oy / Medium Voltage Products +OUI:001C5B* + ID_OUI_FROM_DATABASE=Chubb Electronic Security Systems Ltd -OUI:0021B4* - ID_OUI_FROM_DATABASE=APRO MEDIA CO., LTD +OUI:001C5D* + ID_OUI_FROM_DATABASE=Leica Microsystems -OUI:0021AE* - ID_OUI_FROM_DATABASE=ALCATEL-LUCENT FRANCE - WTD +OUI:001C5C* + ID_OUI_FROM_DATABASE=Integrated Medical Systems, Inc. -OUI:0021A2* - ID_OUI_FROM_DATABASE=EKE-Electronics Ltd. +OUI:001C51* + ID_OUI_FROM_DATABASE=Celeno Communications -OUI:0021A7* - ID_OUI_FROM_DATABASE=Hantle System Co., Ltd. +OUI:001C52* + ID_OUI_FROM_DATABASE=VISIONEE SRL -OUI:00221F* - ID_OUI_FROM_DATABASE=eSang Technologies Co., Ltd. +OUI:001C45* + ID_OUI_FROM_DATABASE=Chenbro Micom Co., Ltd. -OUI:002226* - ID_OUI_FROM_DATABASE=Avaak, Inc. +OUI:001C4C* + ID_OUI_FROM_DATABASE=Petrotest Instruments -OUI:00221A* - ID_OUI_FROM_DATABASE=Audio Precision +OUI:001C39* + ID_OUI_FROM_DATABASE=S Netsystems Inc. -OUI:002213* - ID_OUI_FROM_DATABASE=PCI CORPORATION +OUI:001C40* + ID_OUI_FROM_DATABASE=VDG-Security bv -OUI:00220D* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001C32* + ID_OUI_FROM_DATABASE=Telian Corporation -OUI:00220C* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001AC7* + ID_OUI_FROM_DATABASE=UNIPOINT -OUI:002207* - ID_OUI_FROM_DATABASE=Inteno Broadband Technology AB +OUI:001AC2* + ID_OUI_FROM_DATABASE=YEC Co.,Ltd. -OUI:002202* - ID_OUI_FROM_DATABASE=Excito Elektronik i Skåne AB +OUI:001AB8* + ID_OUI_FROM_DATABASE=Anseri Corporation -OUI:0021F9* - ID_OUI_FROM_DATABASE=WIRECOM Technologies +OUI:001ABD* + ID_OUI_FROM_DATABASE=Impatica Inc. -OUI:001F40* - ID_OUI_FROM_DATABASE=Speakercraft Inc. +OUI:001AB1* + ID_OUI_FROM_DATABASE=Asia Pacific Satellite Industries Co., Ltd. -OUI:001F38* - ID_OUI_FROM_DATABASE=POSITRON +OUI:001B8C* + ID_OUI_FROM_DATABASE=JMicron Technology Corp. -OUI:001F3D* - ID_OUI_FROM_DATABASE=Qbit GmbH +OUI:001B91* + ID_OUI_FROM_DATABASE=EFKON AG -OUI:001F37* - ID_OUI_FROM_DATABASE=Genesis I&C +OUI:001B87* + ID_OUI_FROM_DATABASE=Deepsound Tech. Co., Ltd -OUI:001F2A* - ID_OUI_FROM_DATABASE=ACCM +OUI:001B82* + ID_OUI_FROM_DATABASE=Taiwan Semiconductor Co., Ltd. -OUI:001F31* - ID_OUI_FROM_DATABASE=Radiocomp +OUI:001B7B* + ID_OUI_FROM_DATABASE=The Tintometer Ltd -OUI:001F25* - ID_OUI_FROM_DATABASE=MBS GmbH +OUI:001B74* + ID_OUI_FROM_DATABASE=MiraLink Corporation -OUI:001F1E* - ID_OUI_FROM_DATABASE=Astec Technology Co., Ltd +OUI:001B6F* + ID_OUI_FROM_DATABASE=Teletrak Ltd -OUI:001F17* - ID_OUI_FROM_DATABASE=IDX Company, Ltd. +OUI:001AFC* + ID_OUI_FROM_DATABASE=ModusLink Corporation -OUI:001F18* - ID_OUI_FROM_DATABASE=Hakusan.Mfg.Co,.Ltd +OUI:001AF2* + ID_OUI_FROM_DATABASE=Dynavisions Schweiz AG -OUI:001E61* - ID_OUI_FROM_DATABASE=ITEC GmbH +OUI:001AF7* + ID_OUI_FROM_DATABASE=dataschalt e+a GmbH -OUI:001E5C* - ID_OUI_FROM_DATABASE=RB GeneralEkonomik +OUI:001AED* + ID_OUI_FROM_DATABASE=INCOTEC GmbH -OUI:001E5B* - ID_OUI_FROM_DATABASE=Unitron Company, Inc. +OUI:001ADF* + ID_OUI_FROM_DATABASE=Interactivetv Pty Limited -OUI:001E55* - ID_OUI_FROM_DATABASE=COWON SYSTEMS,Inc. +OUI:001AE1* + ID_OUI_FROM_DATABASE=EDGE ACCESS INC -OUI:001E4E* - ID_OUI_FROM_DATABASE=DAKO EDV-Ingenieur- und Systemhaus GmbH +OUI:001AE6* + ID_OUI_FROM_DATABASE=Atlanta Advanced Communications Holdings Limited -OUI:001E49* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001AD3* + ID_OUI_FROM_DATABASE=Vamp Ltd. -OUI:001E44* - ID_OUI_FROM_DATABASE=SANTEC +OUI:001ADA* + ID_OUI_FROM_DATABASE=Biz-2-Me Inc. -OUI:001E3F* - ID_OUI_FROM_DATABASE=TrellisWare Technologies, Inc. +OUI:001ACE* + ID_OUI_FROM_DATABASE=YUPITERU CORPORATION -OUI:001E38* - ID_OUI_FROM_DATABASE=Bluecard Software Technology Co., Ltd. +OUI:001BC8* + ID_OUI_FROM_DATABASE=MIURA CO.,LTD -OUI:001E31* - ID_OUI_FROM_DATABASE=INFOMARK CO.,LTD. +OUI:001BC1* + ID_OUI_FROM_DATABASE=HOLUX Technology, Inc. -OUI:001E32* - ID_OUI_FROM_DATABASE=Zensys +OUI:001BB7* + ID_OUI_FROM_DATABASE=Alta Heights Technology Corp. -OUI:001E2C* - ID_OUI_FROM_DATABASE=CyVerse Corporation +OUI:001BAB* + ID_OUI_FROM_DATABASE=Telchemy, Incorporated -OUI:001E20* - ID_OUI_FROM_DATABASE=Intertain Inc. +OUI:001BB0* + ID_OUI_FROM_DATABASE=BHARAT ELECTRONICS -OUI:001E19* - ID_OUI_FROM_DATABASE=GTRI +OUI:001BA4* + ID_OUI_FROM_DATABASE=S.A.E Afikim -OUI:001E0F* - ID_OUI_FROM_DATABASE=Briot International +OUI:001B9F* + ID_OUI_FROM_DATABASE=Calyptech Pty Ltd -OUI:001EE4* - ID_OUI_FROM_DATABASE=ACS Solutions France +OUI:001B9D* + ID_OUI_FROM_DATABASE=Novus Security Sp. z o.o. -OUI:001EEB* - ID_OUI_FROM_DATABASE=Talk-A-Phone Co. +OUI:001BF6* + ID_OUI_FROM_DATABASE=CONWISE Technology Corporation Ltd. -OUI:001EDF* - ID_OUI_FROM_DATABASE=Master Industrialization Center Kista +OUI:001BF1* + ID_OUI_FROM_DATABASE=Nanjing SilverNet Software Co., Ltd. -OUI:001EDA* - ID_OUI_FROM_DATABASE=Wesemann Elektrotechniek B.V. +OUI:001BEC* + ID_OUI_FROM_DATABASE=Netio Technologies Co., Ltd -OUI:001ED5* - ID_OUI_FROM_DATABASE=Tekon-Automatics +OUI:001BE7* + ID_OUI_FROM_DATABASE=Postek Electronics Co., Ltd. -OUI:001ECE* - ID_OUI_FROM_DATABASE=BISA Technologies (Hong Kong) Limited +OUI:001BE0* + ID_OUI_FROM_DATABASE=TELENOT ELECTRONIC GmbH -OUI:001EC8* - ID_OUI_FROM_DATABASE=Rapid Mobile (Pty) Ltd +OUI:001BD9* + ID_OUI_FROM_DATABASE=Edgewater Computer Systems -OUI:001EBB* - ID_OUI_FROM_DATABASE=BLUELIGHT TECHNOLOGY INC. +OUI:001BDB* + ID_OUI_FROM_DATABASE=Valeo VECS -OUI:001EB6* - ID_OUI_FROM_DATABASE=TAG Heuer SA +OUI:001BD4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001EB5* - ID_OUI_FROM_DATABASE=Ever Sparkle Technologies Ltd +OUI:001BCD* + ID_OUI_FROM_DATABASE=DAVISCOMMS (S) PTE LTD -OUI:001EAF* - ID_OUI_FROM_DATABASE=Ophir Optronics Ltd +OUI:001C2D* + ID_OUI_FROM_DATABASE=FlexRadio Systems -OUI:001EAA* - ID_OUI_FROM_DATABASE=E-Senza Technologies GmbH +OUI:001C1C* + ID_OUI_FROM_DATABASE=Center Communication Systems GmbH -OUI:001E9D* - ID_OUI_FROM_DATABASE=Recall Technologies, Inc. +OUI:001C21* + ID_OUI_FROM_DATABASE=Nucsafe Inc. -OUI:001E98* - ID_OUI_FROM_DATABASE=GreenLine Communications +OUI:001C20* + ID_OUI_FROM_DATABASE=CLB Benelux -OUI:001E97* - ID_OUI_FROM_DATABASE=Medium Link System Technology CO., LTD, +OUI:001C15* + ID_OUI_FROM_DATABASE=iPhotonix LLC -OUI:001E91* - ID_OUI_FROM_DATABASE=KIMIN Electronic Co., Ltd. +OUI:001C16* + ID_OUI_FROM_DATABASE=ThyssenKrupp Elevator -OUI:001E8A* - ID_OUI_FROM_DATABASE=eCopy, Inc +OUI:001C10* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC -OUI:001E85* - ID_OUI_FROM_DATABASE=Lagotek Corporation +OUI:001C09* + ID_OUI_FROM_DATABASE=SAE Electronic Co.,Ltd. -OUI:001E78* - ID_OUI_FROM_DATABASE=Owitek Technology Ltd., +OUI:001C04* + ID_OUI_FROM_DATABASE=Airgain, Inc. -OUI:001E6D* - ID_OUI_FROM_DATABASE=IT R&D Center +OUI:001BFD* + ID_OUI_FROM_DATABASE=Dignsys Inc. -OUI:001E6E* - ID_OUI_FROM_DATABASE=Shenzhen First Mile Communications Ltd +OUI:00192B* + ID_OUI_FROM_DATABASE=Aclara RF Systems Inc. -OUI:001F71* - ID_OUI_FROM_DATABASE=xG Technology, Inc. +OUI:001930* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001F72* - ID_OUI_FROM_DATABASE=QingDao Hiphone Technology Co,.Ltd +OUI:00191F* + ID_OUI_FROM_DATABASE=Microlink communications Inc. -OUI:001F76* - ID_OUI_FROM_DATABASE=AirLogic Systems Inc. +OUI:001924* + ID_OUI_FROM_DATABASE=LBNL Engineering -OUI:001F6C* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001911* + ID_OUI_FROM_DATABASE=Just In Mobile Information Technologies (Shanghai) Co., Ltd. -OUI:001F60* - ID_OUI_FROM_DATABASE=COMPASS SYSTEMS CORP. +OUI:001918* + ID_OUI_FROM_DATABASE=Interactive Wear AG -OUI:001F65* - ID_OUI_FROM_DATABASE=KOREA ELECTRIC TERMINAL CO., LTD. +OUI:00190C* + ID_OUI_FROM_DATABASE=Encore Electronics, Inc. -OUI:001F5F* - ID_OUI_FROM_DATABASE=Blatand GmbH +OUI:001900* + ID_OUI_FROM_DATABASE=Intelliverese - DBA Voicecom -OUI:001F59* - ID_OUI_FROM_DATABASE=Kronback Tracers +OUI:001905* + ID_OUI_FROM_DATABASE=SCHRACK Seconet AG -OUI:001F4D* - ID_OUI_FROM_DATABASE=Segnetics LLC +OUI:0018F4* + ID_OUI_FROM_DATABASE=EO TECHNICS Co., Ltd. -OUI:001F52* - ID_OUI_FROM_DATABASE=UVT Unternehmensberatung fur Verkehr und Technik GmbH +OUI:0018F6* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium -OUI:001F03* - ID_OUI_FROM_DATABASE=NUM AG +OUI:0018FB* + ID_OUI_FROM_DATABASE=Compro Technology -OUI:001EFE* - ID_OUI_FROM_DATABASE=LEVEL s.r.o. +OUI:0019EE* + ID_OUI_FROM_DATABASE=CARLO GAVAZZI CONTROLS SPA-Controls Division -OUI:001F04* - ID_OUI_FROM_DATABASE=Granch Ltd. +OUI:0019F0* + ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD -OUI:001EF2* - ID_OUI_FROM_DATABASE=Micro Motion Inc +OUI:0019F5* + ID_OUI_FROM_DATABASE=Imagination Technologies Ltd -OUI:001EF7* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0019E9* + ID_OUI_FROM_DATABASE=S-Information Technolgy, Co., Ltd. -OUI:001EF1* - ID_OUI_FROM_DATABASE=Servimat +OUI:0019DB* + ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. -OUI:001F9E* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0019DD* + ID_OUI_FROM_DATABASE=FEI-Zyfer, Inc. -OUI:001F92* - ID_OUI_FROM_DATABASE=VideoIQ, Inc. +OUI:0019CA* + ID_OUI_FROM_DATABASE=Broadata Communications, Inc -OUI:001F97* - ID_OUI_FROM_DATABASE=BERTANA srl +OUI:0019CF* + ID_OUI_FROM_DATABASE=SALICRU, S.A. -OUI:001F8B* - ID_OUI_FROM_DATABASE=Cache IQ +OUI:0019D6* + ID_OUI_FROM_DATABASE=LS Cable and System Ltd. -OUI:001F84* - ID_OUI_FROM_DATABASE=Gigle Semiconductor +OUI:0019B4* + ID_OUI_FROM_DATABASE=Intellio Ltd -OUI:001F7F* - ID_OUI_FROM_DATABASE=Phabrix Limited +OUI:001A6E* + ID_OUI_FROM_DATABASE=Impro Technologies -OUI:001CFF* - ID_OUI_FROM_DATABASE=Napera Networks Inc +OUI:001A67* + ID_OUI_FROM_DATABASE=Infinite QL Sdn Bhd -OUI:001CF8* - ID_OUI_FROM_DATABASE=Parade Technologies, Ltd. +OUI:001A69* + ID_OUI_FROM_DATABASE=Wuhan Yangtze Optical Technology CO.,Ltd. -OUI:001CF1* - ID_OUI_FROM_DATABASE=SUPoX Technology Co. , LTD. +OUI:001A62* + ID_OUI_FROM_DATABASE=Data Robotics, Incorporated -OUI:001CF2* - ID_OUI_FROM_DATABASE=Tenlon Technology Co.,Ltd. +OUI:001A58* + ID_OUI_FROM_DATABASE=CCV Deutschland GmbH - Celectronic eHealth Div. -OUI:001CEC* - ID_OUI_FROM_DATABASE=Mobilesoft (Aust.) Pty Ltd +OUI:001A5D* + ID_OUI_FROM_DATABASE=Mobinnova Corp. -OUI:001CE7* - ID_OUI_FROM_DATABASE=Rocon PLC Research Centre +OUI:001A4C* + ID_OUI_FROM_DATABASE=Crossbow Technology, Inc -OUI:001CE2* - ID_OUI_FROM_DATABASE=Attero Tech, LLC. +OUI:001A51* + ID_OUI_FROM_DATABASE=Alfred Mann Foundation -OUI:001CDB* - ID_OUI_FROM_DATABASE=CARPOINT CO.,LTD +OUI:001AAA* + ID_OUI_FROM_DATABASE=Analogic Corp. -OUI:001CD5* - ID_OUI_FROM_DATABASE=ZeeVee, Inc. +OUI:001AA1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001CCF* - ID_OUI_FROM_DATABASE=LIMETEK +OUI:001A9C* + ID_OUI_FROM_DATABASE=RightHand Technologies, Inc. -OUI:001E08* - ID_OUI_FROM_DATABASE=Centec Networks Inc +OUI:001A8B* + ID_OUI_FROM_DATABASE=CHUNIL ELECTRIC IND., CO. -OUI:001E03* - ID_OUI_FROM_DATABASE=LiComm Co., Ltd. +OUI:001A95* + ID_OUI_FROM_DATABASE=Hisense Mobile Communications Technoligy Co.,Ltd. -OUI:001DFC* - ID_OUI_FROM_DATABASE=KSIC +OUI:001A84* + ID_OUI_FROM_DATABASE=V One Multimedia Pte Ltd -OUI:001DF5* - ID_OUI_FROM_DATABASE=Sunshine Co,LTD +OUI:0019A1* + ID_OUI_FROM_DATABASE=LG INFORMATION & COMM. -OUI:001DF0* - ID_OUI_FROM_DATABASE=Vidient Systems, Inc. +OUI:0019AD* + ID_OUI_FROM_DATABASE=BOBST SA -OUI:001DDC* - ID_OUI_FROM_DATABASE=HangZhou DeChangLong Tech&Info Co.,Ltd +OUI:0019B2* + ID_OUI_FROM_DATABASE=XYnetsoft Co.,Ltd -OUI:001DE4* - ID_OUI_FROM_DATABASE=Visioneered Image Systems +OUI:00199A* + ID_OUI_FROM_DATABASE=EDO-EVI -OUI:001DE2* - ID_OUI_FROM_DATABASE=Radionor Communications +OUI:00199F* + ID_OUI_FROM_DATABASE=DKT A/S -OUI:001CC8* - ID_OUI_FROM_DATABASE=INDUSTRONIC Industrie-Electronic GmbH & Co. KG +OUI:001995* + ID_OUI_FROM_DATABASE=Jurong Hi-Tech (Suzhou)Co.ltd -OUI:001CBC* - ID_OUI_FROM_DATABASE=CastGrabber, LLC +OUI:001990* + ID_OUI_FROM_DATABASE=ELM DATA Co., Ltd. -OUI:001CB2* - ID_OUI_FROM_DATABASE=BPT SPA +OUI:001989* + ID_OUI_FROM_DATABASE=Sonitrol Corporation -OUI:001CA6* - ID_OUI_FROM_DATABASE=Win4NET +OUI:001A3E* + ID_OUI_FROM_DATABASE=Faster Technology LLC -OUI:001CAB* - ID_OUI_FROM_DATABASE=Meyer Sound Laboratories, Inc. +OUI:001A40* + ID_OUI_FROM_DATABASE=A-FOUR TECH CO., LTD. -OUI:001CAC* - ID_OUI_FROM_DATABASE=Qniq Technology Corp. +OUI:001A2D* + ID_OUI_FROM_DATABASE=The Navvo Group -OUI:001CA1* - ID_OUI_FROM_DATABASE=AKAMAI TECHNOLOGIES, INC. +OUI:001A32* + ID_OUI_FROM_DATABASE=ACTIVA MULTIMEDIA -OUI:001C95* - ID_OUI_FROM_DATABASE=Opticomm Corporation +OUI:001A28* + ID_OUI_FROM_DATABASE=ASWT Co., LTD. Taiwan Branch H.K. -OUI:001C90* - ID_OUI_FROM_DATABASE=Empacket Corporation +OUI:001A1C* + ID_OUI_FROM_DATABASE=GT&T Engineering Pte Ltd -OUI:001C8F* - ID_OUI_FROM_DATABASE=Advanced Electronic Design, Inc. +OUI:001A23* + ID_OUI_FROM_DATABASE=Ice Qube, Inc -OUI:001C89* - ID_OUI_FROM_DATABASE=Force Communications, Inc. +OUI:001A15* + ID_OUI_FROM_DATABASE=gemalto e-Payment -OUI:001C7F* - ID_OUI_FROM_DATABASE=Check Point Software Technologies +OUI:001A10* + ID_OUI_FROM_DATABASE=LUCENT TRANS ELECTRONICS CO.,LTD -OUI:001C75* - ID_OUI_FROM_DATABASE=Segnet Ltd. +OUI:001A09* + ID_OUI_FROM_DATABASE=Wayfarer Transit Systems Ltd -OUI:001C6E* - ID_OUI_FROM_DATABASE=Newbury Networks, Inc. +OUI:001A02* + ID_OUI_FROM_DATABASE=SECURE CARE PRODUCTS, INC -OUI:001C69* - ID_OUI_FROM_DATABASE=Packet Vision Ltd +OUI:001A04* + ID_OUI_FROM_DATABASE=Interay Solutions BV -OUI:001DA5* - ID_OUI_FROM_DATABASE=WB Electronics +OUI:001984* + ID_OUI_FROM_DATABASE=ESTIC Corporation -OUI:001DA6* - ID_OUI_FROM_DATABASE=Media Numerics Limited +OUI:001976* + ID_OUI_FROM_DATABASE=Xipher Technologies, LLC -OUI:001DA0* - ID_OUI_FROM_DATABASE=Heng Yu Electronic Manufacturing Company Limited +OUI:001978* + ID_OUI_FROM_DATABASE=Datum Systems, Inc. -OUI:001D99* - ID_OUI_FROM_DATABASE=Cyan Optic, Inc. +OUI:00196A* + ID_OUI_FROM_DATABASE=MikroM GmbH -OUI:001D94* - ID_OUI_FROM_DATABASE=Climax Technology Co., Ltd +OUI:001971* + ID_OUI_FROM_DATABASE=Guangzhou Unicomp Technology Co.,Ltd -OUI:001D93* - ID_OUI_FROM_DATABASE=Modacom +OUI:001965* + ID_OUI_FROM_DATABASE=YuHua TelTech (ShangHai) Co., Ltd. -OUI:001D8D* - ID_OUI_FROM_DATABASE=Raytek GmbH +OUI:001960* + ID_OUI_FROM_DATABASE=DoCoMo Systems, Inc. -OUI:001D86* - ID_OUI_FROM_DATABASE=Shinwa Industries(China) Ltd. +OUI:001954* + ID_OUI_FROM_DATABASE=Leaf Corporation. -OUI:001DC9* - ID_OUI_FROM_DATABASE=GainSpan Corp. +OUI:001959* + ID_OUI_FROM_DATABASE=Staccato Communications Inc. -OUI:001DC2* - ID_OUI_FROM_DATABASE=XORTEC OY +OUI:00194D* + ID_OUI_FROM_DATABASE=Avago Technologies Sdn Bhd -OUI:001DBD* - ID_OUI_FROM_DATABASE=Versamed Inc. +OUI:001948* + ID_OUI_FROM_DATABASE=AireSpider Networks -OUI:001DB6* - ID_OUI_FROM_DATABASE=BestComm Networks, Inc. +OUI:001941* + ID_OUI_FROM_DATABASE=Pitney Bowes, Inc -OUI:001DB0* - ID_OUI_FROM_DATABASE=FuJian HengTong Information Technology Co.,Ltd +OUI:001935* + ID_OUI_FROM_DATABASE=DUERR DENTAL AG -OUI:001DAC* - ID_OUI_FROM_DATABASE=Gigamon Systems LLC +OUI:00193A* + ID_OUI_FROM_DATABASE=OESOLUTIONS -OUI:001D81* - ID_OUI_FROM_DATABASE=GUANGZHOU GATEWAY ELECTRONICS CO., LTD +OUI:00193C* + ID_OUI_FROM_DATABASE=HighPoint Technologies Incorporated -OUI:001D69* - ID_OUI_FROM_DATABASE=Knorr-Bremse IT-Services GmbH +OUI:001773* + ID_OUI_FROM_DATABASE=Laketune Technologies Co. Ltd -OUI:001D70* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001778* + ID_OUI_FROM_DATABASE=Central Music Co. -OUI:001D77* - ID_OUI_FROM_DATABASE=NSGate +OUI:00177A* + ID_OUI_FROM_DATABASE=ASSA ABLOY AB -OUI:001D7C* - ID_OUI_FROM_DATABASE=ABE Elettronica S.p.A. +OUI:00176F* + ID_OUI_FROM_DATABASE=PAX Computer Technology(Shenzhen) Ltd. -OUI:001D64* - ID_OUI_FROM_DATABASE=Adam Communications Systems Int Ltd +OUI:00176A* + ID_OUI_FROM_DATABASE=Avago Technologies -OUI:001D5D* - ID_OUI_FROM_DATABASE=Control Dynamics Pty. Ltd. +OUI:001763* + ID_OUI_FROM_DATABASE=Essentia S.p.A. -OUI:001D2E* - ID_OUI_FROM_DATABASE=Ruckus Wireless +OUI:00175E* + ID_OUI_FROM_DATABASE=Zed-3 -OUI:001D21* - ID_OUI_FROM_DATABASE=Alcad SL +OUI:001750* + ID_OUI_FROM_DATABASE=GSI Group, MicroE Systems -OUI:001D1C* - ID_OUI_FROM_DATABASE=Gennet s.a. +OUI:001752* + ID_OUI_FROM_DATABASE=DAGS, Inc -OUI:001D17* - ID_OUI_FROM_DATABASE=Digital Sky Corporation +OUI:001757* + ID_OUI_FROM_DATABASE=RIX TECHNOLOGY LIMITED -OUI:001D12* - ID_OUI_FROM_DATABASE=ROHM CO., LTD. +OUI:00183D* + ID_OUI_FROM_DATABASE=Vertex Link Corporation -OUI:001D11* - ID_OUI_FROM_DATABASE=Analogue & Micro Ltd +OUI:001844* + ID_OUI_FROM_DATABASE=Heads Up Technologies, Inc. -OUI:001D0B* - ID_OUI_FROM_DATABASE=Power Standards Lab +OUI:001838* + ID_OUI_FROM_DATABASE=PanAccess Communications,Inc. -OUI:001D04* - ID_OUI_FROM_DATABASE=Zipit Wireless, Inc. +OUI:001827* + ID_OUI_FROM_DATABASE=NEC UNIFIED SOLUTIONS NEDERLAND B.V. -OUI:001D58* - ID_OUI_FROM_DATABASE=CQ Inc +OUI:00182C* + ID_OUI_FROM_DATABASE=Ascend Networks, Inc. -OUI:001D57* - ID_OUI_FROM_DATABASE=CAETEC Messtechnik +OUI:00181B* + ID_OUI_FROM_DATABASE=TaiJin Metal Co., Ltd. -OUI:001D51* - ID_OUI_FROM_DATABASE=Babcock & Wilcox Power Generation Group, Inc +OUI:001814* + ID_OUI_FROM_DATABASE=Mitutoyo Corporation -OUI:001D47* - ID_OUI_FROM_DATABASE=Covote GmbH & Co KG +OUI:001819* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001D40* - ID_OUI_FROM_DATABASE=Intel – GE Care Innovations LLC +OUI:001820* + ID_OUI_FROM_DATABASE=w5networks -OUI:001D34* - ID_OUI_FROM_DATABASE=SYRIS Technology Corp +OUI:001808* + ID_OUI_FROM_DATABASE=SightLogix, Inc. -OUI:001D2D* - ID_OUI_FROM_DATABASE=Pylone, Inc. +OUI:00180D* + ID_OUI_FROM_DATABASE=Terabytes Server Storage Tech Corp -OUI:001B2A* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001803* + ID_OUI_FROM_DATABASE=ArcSoft Shanghai Co. LTD -OUI:001B1D* - ID_OUI_FROM_DATABASE=Phoenix International Co., Ltd +OUI:0017F0* + ID_OUI_FROM_DATABASE=SZCOM Broadband Network Technology Co.,Ltd -OUI:001B22* - ID_OUI_FROM_DATABASE=Palit Microsystems ( H.K.) Ltd. +OUI:0017F7* + ID_OUI_FROM_DATABASE=CEM Solutions Pvt Ltd -OUI:001B1B* - ID_OUI_FROM_DATABASE=Siemens AG, +OUI:0017FE* + ID_OUI_FROM_DATABASE=TALOS SYSTEM INC. -OUI:001B16* - ID_OUI_FROM_DATABASE=Celtro Ltd. +OUI:0017D8* + ID_OUI_FROM_DATABASE=Magnum Semiconductor, Inc. -OUI:001B0A* - ID_OUI_FROM_DATABASE=Intelligent Distributed Controls Ltd +OUI:0017DD* + ID_OUI_FROM_DATABASE=Clipsal Australia -OUI:001B0F* - ID_OUI_FROM_DATABASE=Petratec +OUI:0017DF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001AFE* - ID_OUI_FROM_DATABASE=SOFACREAL +OUI:0018C6* + ID_OUI_FROM_DATABASE=OPW Fuel Management Systems -OUI:001B03* - ID_OUI_FROM_DATABASE=Action Technology (SZ) Co., Ltd +OUI:0018CB* + ID_OUI_FROM_DATABASE=Tecobest Technology Limited -OUI:001B68* - ID_OUI_FROM_DATABASE=Modnnet Co., Ltd +OUI:0018BF* + ID_OUI_FROM_DATABASE=Essence Technology Solution, Inc. -OUI:001B62* - ID_OUI_FROM_DATABASE=JHT Optoelectronics Co.,Ltd. +OUI:0018BA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001B61* - ID_OUI_FROM_DATABASE=Digital Acoustics, LLC +OUI:0018B8* + ID_OUI_FROM_DATABASE=New Voice International AG -OUI:001B5C* - ID_OUI_FROM_DATABASE=Azuretec Co., Ltd. +OUI:0018B3* + ID_OUI_FROM_DATABASE=TEC WizHome Co., Ltd. -OUI:001B55* - ID_OUI_FROM_DATABASE=Hurco Automation Ltd. +OUI:0018AC* + ID_OUI_FROM_DATABASE=Shanghai Jiao Da HISYS Technology Co. Ltd. -OUI:001B50* - ID_OUI_FROM_DATABASE=Nizhny Novgorod Factory named after M.Frunze, FSUE (NZiF) +OUI:0018A5* + ID_OUI_FROM_DATABASE=ADigit Technologies Corp. -OUI:001B44* - ID_OUI_FROM_DATABASE=SanDisk Corporation +OUI:0018A7* + ID_OUI_FROM_DATABASE=Yoggie Security Systems LTD. -OUI:001B49* - ID_OUI_FROM_DATABASE=Roberts Radio limited +OUI:001896* + ID_OUI_FROM_DATABASE=Great Well Electronic LTD -OUI:001B42* - ID_OUI_FROM_DATABASE=Wise & Blue +OUI:00189B* + ID_OUI_FROM_DATABASE=Thomson Inc. -OUI:001B3D* - ID_OUI_FROM_DATABASE=EuroTel Spa +OUI:00179E* + ID_OUI_FROM_DATABASE=Sirit Inc -OUI:001B36* - ID_OUI_FROM_DATABASE=Tsubata Engineering Co.,Ltd. (Head Office) +OUI:0017A3* + ID_OUI_FROM_DATABASE=MIX s.r.l. -OUI:001B31* - ID_OUI_FROM_DATABASE=Neural Image. Co. Ltd. +OUI:0017A8* + ID_OUI_FROM_DATABASE=EDM Corporation -OUI:001C56* - ID_OUI_FROM_DATABASE=Pado Systems, Inc. +OUI:001792* + ID_OUI_FROM_DATABASE=Falcom Wireless Comunications Gmbh -OUI:001C5B* - ID_OUI_FROM_DATABASE=Chubb Electronic Security Systems Ltd +OUI:001797* + ID_OUI_FROM_DATABASE=Telsy Elettronica S.p.A. -OUI:001C5D* - ID_OUI_FROM_DATABASE=Leica Microsystems +OUI:001799* + ID_OUI_FROM_DATABASE=SmarTire Systems Inc. -OUI:001C5C* - ID_OUI_FROM_DATABASE=Integrated Medical Systems, Inc. +OUI:00178B* + ID_OUI_FROM_DATABASE=Teledyne Technologies Incorporated -OUI:001C51* - ID_OUI_FROM_DATABASE=Celeno Communications +OUI:00177F* + ID_OUI_FROM_DATABASE=Worldsmart Retech -OUI:001C52* - ID_OUI_FROM_DATABASE=VISIONEE SRL +OUI:001786* + ID_OUI_FROM_DATABASE=wisembed -OUI:001C45* - ID_OUI_FROM_DATABASE=Chenbro Micom Co., Ltd. +OUI:001877* + ID_OUI_FROM_DATABASE=Amplex A/S -OUI:001C4C* - ID_OUI_FROM_DATABASE=Petrotest Instruments +OUI:00186B* + ID_OUI_FROM_DATABASE=Sambu Communics CO., LTD. -OUI:001C39* - ID_OUI_FROM_DATABASE=S Netsystems Inc. +OUI:001870* + ID_OUI_FROM_DATABASE=E28 Shanghai Limited -OUI:001C40* - ID_OUI_FROM_DATABASE=VDG-Security bv +OUI:001863* + ID_OUI_FROM_DATABASE=Veritech Electronics Limited -OUI:001C32* - ID_OUI_FROM_DATABASE=Telian Corporation +OUI:001850* + ID_OUI_FROM_DATABASE=Secfone Kft -OUI:001AC7* - ID_OUI_FROM_DATABASE=UNIPOINT +OUI:001855* + ID_OUI_FROM_DATABASE=Aeromaritime Systembau GmbH -OUI:001AC2* - ID_OUI_FROM_DATABASE=YEC Co.,Ltd. +OUI:001857* + ID_OUI_FROM_DATABASE=Unilever R&D -OUI:001AB8* - ID_OUI_FROM_DATABASE=Anseri Corporation +OUI:001849* + ID_OUI_FROM_DATABASE=Pigeon Point Systems LLC -OUI:001ABD* - ID_OUI_FROM_DATABASE=Impatica Inc. +OUI:0017C7* + ID_OUI_FROM_DATABASE=MARA Systems Consulting AB -OUI:001AB1* - ID_OUI_FROM_DATABASE=Asia Pacific Satellite Industries Co., Ltd. +OUI:0017CE* + ID_OUI_FROM_DATABASE=Screen Service Spa -OUI:001B8C* - ID_OUI_FROM_DATABASE=JMicron Technology Corp. +OUI:0017D3* + ID_OUI_FROM_DATABASE=Etymotic Research, Inc. -OUI:001B91* - ID_OUI_FROM_DATABASE=EFKON AG +OUI:0017BB* + ID_OUI_FROM_DATABASE=Syrinx Industrial Electronics -OUI:001B87* - ID_OUI_FROM_DATABASE=Deepsound Tech. Co., Ltd +OUI:0017B4* + ID_OUI_FROM_DATABASE=Remote Security Systems, LLC -OUI:001B82* - ID_OUI_FROM_DATABASE=Taiwan Semiconductor Co., Ltd. +OUI:0017B6* + ID_OUI_FROM_DATABASE=Aquantia -OUI:001B7B* - ID_OUI_FROM_DATABASE=The Tintometer Ltd +OUI:0017AF* + ID_OUI_FROM_DATABASE=Enermet -OUI:001B74* - ID_OUI_FROM_DATABASE=MiraLink Corporation +OUI:0018E8* + ID_OUI_FROM_DATABASE=Hacetron Corporation -OUI:001B6F* - ID_OUI_FROM_DATABASE=Teletrak Ltd +OUI:0018EF* + ID_OUI_FROM_DATABASE=Escape Communications, Inc. -OUI:001AFC* - ID_OUI_FROM_DATABASE=ModusLink Corporation +OUI:0018E3* + ID_OUI_FROM_DATABASE=Visualgate Systems, Inc. -OUI:001AF2* - ID_OUI_FROM_DATABASE=Dynavisions Schweiz AG +OUI:0018DC* + ID_OUI_FROM_DATABASE=Prostar Co., Ltd. -OUI:001AF7* - ID_OUI_FROM_DATABASE=dataschalt e+a GmbH +OUI:0018E1* + ID_OUI_FROM_DATABASE=Verkerk Service Systemen -OUI:001AED* - ID_OUI_FROM_DATABASE=INCOTEC GmbH +OUI:0018D0* + ID_OUI_FROM_DATABASE=AtRoad, A Trimble Company -OUI:001ADF* - ID_OUI_FROM_DATABASE=Interactivetv Pty Limited +OUI:0018D5* + ID_OUI_FROM_DATABASE=REIGNCOM -OUI:001AE1* - ID_OUI_FROM_DATABASE=EDGE ACCESS INC +OUI:0018A0* + ID_OUI_FROM_DATABASE=Cierma Ascenseurs -OUI:001AE6* - ID_OUI_FROM_DATABASE=Atlanta Advanced Communications Holdings Limited +OUI:001883* + ID_OUI_FROM_DATABASE=FORMOSA21 INC. -OUI:001AD3* - ID_OUI_FROM_DATABASE=Vamp Ltd. +OUI:00188A* + ID_OUI_FROM_DATABASE=Infinova LLC -OUI:001ADA* - ID_OUI_FROM_DATABASE=Biz-2-Me Inc. +OUI:00188F* + ID_OUI_FROM_DATABASE=Montgomery Technology, Inc. -OUI:001ACE* - ID_OUI_FROM_DATABASE=YUPITERU CORPORATION +OUI:00187C* + ID_OUI_FROM_DATABASE=INTERCROSS, LLC -OUI:001BC8* - ID_OUI_FROM_DATABASE=MIURA CO.,LTD +OUI:00187E* + ID_OUI_FROM_DATABASE=RGB Spectrum -OUI:001BC1* - ID_OUI_FROM_DATABASE=HOLUX Technology, Inc. +OUI:00164A* + ID_OUI_FROM_DATABASE=Vibration Technology Limited -OUI:001BB7* - ID_OUI_FROM_DATABASE=Alta Heights Technology Corp. +OUI:001644* + ID_OUI_FROM_DATABASE=LITE-ON Technology Corp. -OUI:001BAB* - ID_OUI_FROM_DATABASE=Telchemy, Incorporated +OUI:001645* + ID_OUI_FROM_DATABASE=Power Distribution, Inc. -OUI:001BB0* - ID_OUI_FROM_DATABASE=BHARAT ELECTRONICS +OUI:00163B* + ID_OUI_FROM_DATABASE=VertexRSI/General Dynamics -OUI:001BA4* - ID_OUI_FROM_DATABASE=S.A.E Afikim +OUI:001640* + ID_OUI_FROM_DATABASE=Asmobile Communication Inc. -OUI:001B9F* - ID_OUI_FROM_DATABASE=Calyptech Pty Ltd +OUI:00163A* + ID_OUI_FROM_DATABASE=YVES TECHNOLOGY CO., LTD. -OUI:001B9D* - ID_OUI_FROM_DATABASE=Novus Security Sp. z o.o. +OUI:001634* + ID_OUI_FROM_DATABASE=Mathtech, Inc. -OUI:001BF6* - ID_OUI_FROM_DATABASE=CONWISE Technology Corporation Ltd. +OUI:00162D* + ID_OUI_FROM_DATABASE=STNet Co., Ltd. -OUI:001BF1* - ID_OUI_FROM_DATABASE=Nanjing SilverNet Software Co., Ltd. +OUI:001621* + ID_OUI_FROM_DATABASE=Colorado Vnet -OUI:001BEC* - ID_OUI_FROM_DATABASE=Netio Technologies Co., Ltd +OUI:00161A* + ID_OUI_FROM_DATABASE=Dametric AB -OUI:001BE7* - ID_OUI_FROM_DATABASE=Postek Electronics Co., Ltd. +OUI:001615* + ID_OUI_FROM_DATABASE=Nittan Company, Limited -OUI:001BE0* - ID_OUI_FROM_DATABASE=TELENOT ELECTRONIC GmbH +OUI:0016C4* + ID_OUI_FROM_DATABASE=SiRF Technology, Inc. -OUI:001BD9* - ID_OUI_FROM_DATABASE=Edgewater Computer Systems +OUI:0016C6* + ID_OUI_FROM_DATABASE=North Atlantic Industries -OUI:001BDB* - ID_OUI_FROM_DATABASE=Valeo VECS +OUI:0016D2* + ID_OUI_FROM_DATABASE=Caspian -OUI:001BD4* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0016BF* + ID_OUI_FROM_DATABASE=PaloDEx Group Oy -OUI:001BCD* - ID_OUI_FROM_DATABASE=DAVISCOMMS (S) PTE LTD +OUI:0016B3* + ID_OUI_FROM_DATABASE=Photonicbridges (China) Co., Ltd. -OUI:001C2D* - ID_OUI_FROM_DATABASE=FlexRadio Systems +OUI:0016AC* + ID_OUI_FROM_DATABASE=Toho Technology Corp. -OUI:001C1C* - ID_OUI_FROM_DATABASE=Center Communication Systems GmbH +OUI:0016B1* + ID_OUI_FROM_DATABASE=KBS -OUI:001C21* - ID_OUI_FROM_DATABASE=Nucsafe Inc. +OUI:0016A7* + ID_OUI_FROM_DATABASE=AWETA G&P -OUI:001C20* - ID_OUI_FROM_DATABASE=CLB Benelux +OUI:001724* + ID_OUI_FROM_DATABASE=Studer Professional Audio GmbH -OUI:001C15* - ID_OUI_FROM_DATABASE=iPhotonix LLC +OUI:001718* + ID_OUI_FROM_DATABASE=Vansco Electronics Oy -OUI:001C16* - ID_OUI_FROM_DATABASE=ThyssenKrupp Elevator +OUI:00171D* + ID_OUI_FROM_DATABASE=DIGIT -OUI:001C10* - ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC +OUI:001711* + ID_OUI_FROM_DATABASE=GE Healthcare Bio-Sciences AB -OUI:001C09* - ID_OUI_FROM_DATABASE=SAE Electronic Co.,Ltd. +OUI:00170C* + ID_OUI_FROM_DATABASE=Twig Com Ltd. -OUI:001C04* - ID_OUI_FROM_DATABASE=Airgain, Inc. +OUI:001707* + ID_OUI_FROM_DATABASE=InGrid, Inc -OUI:001BFD* - ID_OUI_FROM_DATABASE=Dignsys Inc. +OUI:001702* + ID_OUI_FROM_DATABASE=Osung Midicom Co., Ltd -OUI:00192B* - ID_OUI_FROM_DATABASE=Aclara RF Systems Inc. +OUI:001744* + ID_OUI_FROM_DATABASE=Araneo Ltd. -OUI:001930* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00173C* + ID_OUI_FROM_DATABASE=Extreme Engineering Solutions -OUI:00191F* - ID_OUI_FROM_DATABASE=Microlink communications Inc. +OUI:001737* + ID_OUI_FROM_DATABASE=Industrie Dial Face S.p.A. -OUI:001924* - ID_OUI_FROM_DATABASE=LBNL Engineering +OUI:00172B* + ID_OUI_FROM_DATABASE=Global Technologies Inc. -OUI:001911* - ID_OUI_FROM_DATABASE=Just In Mobile Information Technologies (Shanghai) Co., Ltd. +OUI:001730* + ID_OUI_FROM_DATABASE=Automation Electronics -OUI:001918* - ID_OUI_FROM_DATABASE=Interactive Wear AG +OUI:001729* + ID_OUI_FROM_DATABASE=Ubicod Co.LTD -OUI:00190C* - ID_OUI_FROM_DATABASE=Encore Electronics, Inc. +OUI:00169B* + ID_OUI_FROM_DATABASE=Alstom Transport -OUI:001900* - ID_OUI_FROM_DATABASE=Intelliverese - DBA Voicecom +OUI:0016A2* + ID_OUI_FROM_DATABASE=CentraLite Systems, Inc. -OUI:001905* - ID_OUI_FROM_DATABASE=SCHRACK Seconet AG +OUI:001696* + ID_OUI_FROM_DATABASE=QDI Technology (H.K.) Limited -OUI:0018F4* - ID_OUI_FROM_DATABASE=EO TECHNICS Co., Ltd. +OUI:001688* + ID_OUI_FROM_DATABASE=ServerEngines LLC -OUI:0018F6* - ID_OUI_FROM_DATABASE=Thomson Telecom Belgium +OUI:00168A* + ID_OUI_FROM_DATABASE=id-Confirm Inc -OUI:0018FB* - ID_OUI_FROM_DATABASE=Compro Technology +OUI:001683* + ID_OUI_FROM_DATABASE=WEBIO International Co.,.Ltd. -OUI:0019EE* - ID_OUI_FROM_DATABASE=CARLO GAVAZZI CONTROLS SPA-Controls Division +OUI:00167C* + ID_OUI_FROM_DATABASE=iRex Technologies BV -OUI:0019F0* - ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD +OUI:001610* + ID_OUI_FROM_DATABASE=Carina Technology -OUI:0019F5* - ID_OUI_FROM_DATABASE=Imagination Technologies Ltd +OUI:00160B* + ID_OUI_FROM_DATABASE=TVWorks LLC -OUI:0019E9* - ID_OUI_FROM_DATABASE=S-Information Technolgy, Co., Ltd. +OUI:001604* + ID_OUI_FROM_DATABASE=Sigpro -OUI:0019DB* - ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. +OUI:0015FE* + ID_OUI_FROM_DATABASE=SCHILLING ROBOTICS LLC -OUI:0019DD* - ID_OUI_FROM_DATABASE=FEI-Zyfer, Inc. +OUI:0015FD* + ID_OUI_FROM_DATABASE=Complete Media Systems -OUI:0019CA* - ID_OUI_FROM_DATABASE=Broadata Communications, Inc +OUI:0015F8* + ID_OUI_FROM_DATABASE=Kingtronics Industrial Co. Ltd. -OUI:0019CF* - ID_OUI_FROM_DATABASE=SALICRU, S.A. +OUI:0015EC* + ID_OUI_FROM_DATABASE=Boca Devices LLC -OUI:0019D6* - ID_OUI_FROM_DATABASE=LS Cable and System Ltd. +OUI:0015F1* + ID_OUI_FROM_DATABASE=KYLINK Communications Corp. -OUI:0019B4* - ID_OUI_FROM_DATABASE=Intellio Ltd +OUI:001677* + ID_OUI_FROM_DATABASE=Bihl + Wiedemann GmbH -OUI:001A6E* - ID_OUI_FROM_DATABASE=Impro Technologies +OUI:001670* + ID_OUI_FROM_DATABASE=SKNET Corporation -OUI:001A67* - ID_OUI_FROM_DATABASE=Infinite QL Sdn Bhd +OUI:001664* + ID_OUI_FROM_DATABASE=Prod-El SpA -OUI:001A69* - ID_OUI_FROM_DATABASE=Wuhan Yangtze Optical Technology CO.,Ltd. +OUI:001669* + ID_OUI_FROM_DATABASE=MRV Communication (Networks) LTD -OUI:001A62* - ID_OUI_FROM_DATABASE=Data Robotics, Incorporated +OUI:00165D* + ID_OUI_FROM_DATABASE=AirDefense, Inc. -OUI:001A58* - ID_OUI_FROM_DATABASE=CCV Deutschland GmbH - Celectronic eHealth Div. +OUI:001651* + ID_OUI_FROM_DATABASE=Exeo Systems -OUI:001A5D* - ID_OUI_FROM_DATABASE=Mobinnova Corp. +OUI:0015E5* + ID_OUI_FROM_DATABASE=Cheertek Inc. -OUI:001A4C* - ID_OUI_FROM_DATABASE=Crossbow Technology, Inc +OUI:0015DB* + ID_OUI_FROM_DATABASE=Canesta Inc. -OUI:001A51* - ID_OUI_FROM_DATABASE=Alfred Mann Foundation +OUI:0015D4* + ID_OUI_FROM_DATABASE=Emitor AB -OUI:001AAA* - ID_OUI_FROM_DATABASE=Analogic Corp. +OUI:0015C8* + ID_OUI_FROM_DATABASE=FlexiPanel Ltd -OUI:001AA1* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0015C3* + ID_OUI_FROM_DATABASE=Ruf Telematik AG -OUI:001A9C* - ID_OUI_FROM_DATABASE=RightHand Technologies, Inc. +OUI:0015C2* + ID_OUI_FROM_DATABASE=3M Germany -OUI:001A8B* - ID_OUI_FROM_DATABASE=CHUNIL ELECTRIC IND., CO. +OUI:0015BE* + ID_OUI_FROM_DATABASE=Iqua Ltd. -OUI:001A95* - ID_OUI_FROM_DATABASE=Hisense Mobile Communications Technoligy Co.,Ltd. +OUI:0016EF* + ID_OUI_FROM_DATABASE=Koko Fitness, Inc. -OUI:001A84* - ID_OUI_FROM_DATABASE=V One Multimedia Pte Ltd +OUI:0016F4* + ID_OUI_FROM_DATABASE=Eidicom Co., Ltd. -OUI:0019A1* - ID_OUI_FROM_DATABASE=LG INFORMATION & COMM. +OUI:0016E8* + ID_OUI_FROM_DATABASE=Sigma Designs, Inc. -OUI:0019AD* - ID_OUI_FROM_DATABASE=BOBST SA +OUI:0016ED* + ID_OUI_FROM_DATABASE=Digital Safety Technologies, Inc -OUI:0019B2* - ID_OUI_FROM_DATABASE=XYnetsoft Co.,Ltd +OUI:0016DC* + ID_OUI_FROM_DATABASE=ARCHOS -OUI:00199A* - ID_OUI_FROM_DATABASE=EDO-EVI +OUI:0016E1* + ID_OUI_FROM_DATABASE=SiliconStor, Inc. -OUI:00199F* - ID_OUI_FROM_DATABASE=DKT A/S +OUI:0016D7* + ID_OUI_FROM_DATABASE=Sunways AG -OUI:001995* - ID_OUI_FROM_DATABASE=Jurong Hi-Tech (Suzhou)Co.ltd +OUI:0014CB* + ID_OUI_FROM_DATABASE=LifeSync Corporation -OUI:001990* - ID_OUI_FROM_DATABASE=ELM DATA Co., Ltd. +OUI:0014D0* + ID_OUI_FROM_DATABASE=BTI Systems Inc. -OUI:001989* - ID_OUI_FROM_DATABASE=Sonitrol Corporation +OUI:0014C4* + ID_OUI_FROM_DATABASE=Vitelcom Mobile Technology -OUI:001A3E* - ID_OUI_FROM_DATABASE=Faster Technology LLC +OUI:0014BE* + ID_OUI_FROM_DATABASE=Wink communication technology CO.LTD -OUI:001A40* - ID_OUI_FROM_DATABASE=A-FOUR TECH CO., LTD. +OUI:0014BD* + ID_OUI_FROM_DATABASE=incNETWORKS, Inc -OUI:001A2D* - ID_OUI_FROM_DATABASE=The Navvo Group +OUI:0014B8* + ID_OUI_FROM_DATABASE=Hill-Rom -OUI:001A32* - ID_OUI_FROM_DATABASE=ACTIVA MULTIMEDIA +OUI:0014AE* + ID_OUI_FROM_DATABASE=Wizlogics Co., Ltd. -OUI:001A28* - ID_OUI_FROM_DATABASE=ASWT Co., LTD. Taiwan Branch H.K. +OUI:0014B3* + ID_OUI_FROM_DATABASE=CoreStar International Corp -OUI:001A1C* - ID_OUI_FROM_DATABASE=GT&T Engineering Pte Ltd +OUI:00149B* + ID_OUI_FROM_DATABASE=Nokota Communications, LLC -OUI:001A23* - ID_OUI_FROM_DATABASE=Ice Qube, Inc +OUI:00143F* + ID_OUI_FROM_DATABASE=Hotway Technology Corporation -OUI:001A15* - ID_OUI_FROM_DATABASE=gemalto e-Payment +OUI:001431* + ID_OUI_FROM_DATABASE=PDL Electronics Ltd -OUI:001A10* - ID_OUI_FROM_DATABASE=LUCENT TRANS ELECTRONICS CO.,LTD +OUI:001433* + ID_OUI_FROM_DATABASE=Empower Technologies(Canada) Inc. -OUI:001A09* - ID_OUI_FROM_DATABASE=Wayfarer Transit Systems Ltd +OUI:001432* + ID_OUI_FROM_DATABASE=Tarallax Wireless, Inc. -OUI:001A02* - ID_OUI_FROM_DATABASE=SECURE CARE PRODUCTS, INC +OUI:00142C* + ID_OUI_FROM_DATABASE=Koncept International, Inc. -OUI:001A04* - ID_OUI_FROM_DATABASE=Interay Solutions BV +OUI:001425* + ID_OUI_FROM_DATABASE=Galactic Computing Corp. -OUI:001984* - ID_OUI_FROM_DATABASE=ESTIC Corporation +OUI:001420* + ID_OUI_FROM_DATABASE=G-Links networking company -OUI:001976* - ID_OUI_FROM_DATABASE=Xipher Technologies, LLC +OUI:00141B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001978* - ID_OUI_FROM_DATABASE=Datum Systems, Inc. +OUI:00146D* + ID_OUI_FROM_DATABASE=RF Technologies -OUI:00196A* - ID_OUI_FROM_DATABASE=MikroM GmbH +OUI:00146F* + ID_OUI_FROM_DATABASE=Kohler Co -OUI:001971* - ID_OUI_FROM_DATABASE=Guangzhou Unicomp Technology Co.,Ltd +OUI:00146E* + ID_OUI_FROM_DATABASE=H. Stoll GmbH & Co. KG -OUI:001965* - ID_OUI_FROM_DATABASE=YuHua TelTech (ShangHai) Co., Ltd. +OUI:001468* + ID_OUI_FROM_DATABASE=CelPlan International, Inc. -OUI:001960* - ID_OUI_FROM_DATABASE=DoCoMo Systems, Inc. +OUI:001461* + ID_OUI_FROM_DATABASE=CORONA CORPORATION -OUI:001954* - ID_OUI_FROM_DATABASE=Leaf Corporation. +OUI:00145C* + ID_OUI_FROM_DATABASE=Intronics B.V. -OUI:001959* - ID_OUI_FROM_DATABASE=Staccato Communications Inc. +OUI:001455* + ID_OUI_FROM_DATABASE=Coder Electronics Corporation -OUI:00194D* - ID_OUI_FROM_DATABASE=Avago Technologies Sdn Bhd +OUI:001444* + ID_OUI_FROM_DATABASE=Grundfos Holding -OUI:001948* - ID_OUI_FROM_DATABASE=AireSpider Networks +OUI:00144B* + ID_OUI_FROM_DATABASE=Hifn, Inc. -OUI:001941* - ID_OUI_FROM_DATABASE=Pitney Bowes, Inc +OUI:001589* + ID_OUI_FROM_DATABASE=D-MAX Technology Co.,Ltd -OUI:001935* - ID_OUI_FROM_DATABASE=DUERR DENTAL AG +OUI:001582* + ID_OUI_FROM_DATABASE=Pulse Eight Limited -OUI:00193A* - ID_OUI_FROM_DATABASE=OESOLUTIONS +OUI:00157C* + ID_OUI_FROM_DATABASE=Dave Networks, Inc. -OUI:00193C* - ID_OUI_FROM_DATABASE=HighPoint Technologies Incorporated +OUI:001578* + ID_OUI_FROM_DATABASE=Audio / Video Innovations -OUI:001773* - ID_OUI_FROM_DATABASE=Laketune Technologies Co. Ltd +OUI:001573* + ID_OUI_FROM_DATABASE=NewSoft Technology Corporation -OUI:001778* - ID_OUI_FROM_DATABASE=Central Music Co. +OUI:00156C* + ID_OUI_FROM_DATABASE=SANE SYSTEM CO., LTD -OUI:00177A* - ID_OUI_FROM_DATABASE=ASSA ABLOY AB +OUI:001571* + ID_OUI_FROM_DATABASE=Nolan Systems -OUI:00176F* - ID_OUI_FROM_DATABASE=PAX Computer Technology(Shenzhen) Ltd. +OUI:001572* + ID_OUI_FROM_DATABASE=Red-Lemon -OUI:00176A* - ID_OUI_FROM_DATABASE=Avago Technologies +OUI:001565* + ID_OUI_FROM_DATABASE=XIAMEN YEALINK NETWORK TECHNOLOGY CO.,LTD -OUI:001763* - ID_OUI_FROM_DATABASE=Essentia S.p.A. +OUI:001559* + ID_OUI_FROM_DATABASE=Securaplane Technologies, Inc. -OUI:00175E* - ID_OUI_FROM_DATABASE=Zed-3 +OUI:0014A2* + ID_OUI_FROM_DATABASE=Core Micro Systems Inc. -OUI:001750* - ID_OUI_FROM_DATABASE=GSI Group, MicroE Systems +OUI:001494* + ID_OUI_FROM_DATABASE=ESU AG -OUI:001752* - ID_OUI_FROM_DATABASE=DAGS, Inc +OUI:00148F* + ID_OUI_FROM_DATABASE=Protronic (Far East) Ltd. -OUI:001757* - ID_OUI_FROM_DATABASE=RIX TECHNOLOGY LIMITED +OUI:001488* + ID_OUI_FROM_DATABASE=Akorri -OUI:00183D* - ID_OUI_FROM_DATABASE=Vertex Link Corporation +OUI:001483* + ID_OUI_FROM_DATABASE=eXS Inc. -OUI:001844* - ID_OUI_FROM_DATABASE=Heads Up Technologies, Inc. +OUI:001480* + ID_OUI_FROM_DATABASE=Hitachi-LG Data Storage Korea, Inc -OUI:001838* - ID_OUI_FROM_DATABASE=PanAccess Communications,Inc. +OUI:00147B* + ID_OUI_FROM_DATABASE=Iteris, Inc. -OUI:001827* - ID_OUI_FROM_DATABASE=NEC UNIFIED SOLUTIONS NEDERLAND B.V. +OUI:001474* + ID_OUI_FROM_DATABASE=K40 Electronics -OUI:00182C* - ID_OUI_FROM_DATABASE=Ascend Networks, Inc. +OUI:0015B8* + ID_OUI_FROM_DATABASE=Tahoe -OUI:00181B* - ID_OUI_FROM_DATABASE=TaiJin Metal Co., Ltd. +OUI:0015B2* + ID_OUI_FROM_DATABASE=Advanced Industrial Computer, Inc. -OUI:001814* - ID_OUI_FROM_DATABASE=Mitutoyo Corporation +OUI:0015AE* + ID_OUI_FROM_DATABASE=kyung il -OUI:001819* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0015AD* + ID_OUI_FROM_DATABASE=Accedian Networks -OUI:001820* - ID_OUI_FROM_DATABASE=w5networks +OUI:00E0A8* + ID_OUI_FROM_DATABASE=SAT GmbH & Co. -OUI:001808* - ID_OUI_FROM_DATABASE=SightLogix, Inc. +OUI:0015A1* + ID_OUI_FROM_DATABASE=ECA-SINTERS -OUI:00180D* - ID_OUI_FROM_DATABASE=Terabytes Server Storage Tech Corp +OUI:00159C* + ID_OUI_FROM_DATABASE=B-KYUNG SYSTEM Co.,Ltd. -OUI:001803* - ID_OUI_FROM_DATABASE=ArcSoft Shanghai Co. LTD +OUI:001595* + ID_OUI_FROM_DATABASE=Quester Tangent Corporation -OUI:0017F0* - ID_OUI_FROM_DATABASE=SZCOM Broadband Network Technology Co.,Ltd +OUI:00158E* + ID_OUI_FROM_DATABASE=Plustek.INC -OUI:0017F7* - ID_OUI_FROM_DATABASE=CEM Solutions Pvt Ltd +OUI:001552* + ID_OUI_FROM_DATABASE=Wi-Gear Inc. -OUI:0017FE* - ID_OUI_FROM_DATABASE=TALOS SYSTEM INC. +OUI:001548* + ID_OUI_FROM_DATABASE=CUBE TECHNOLOGIES -OUI:0017D8* - ID_OUI_FROM_DATABASE=Magnum Semiconductor, Inc. +OUI:00154D* + ID_OUI_FROM_DATABASE=Netronome Systems, Inc. -OUI:0017DD* - ID_OUI_FROM_DATABASE=Clipsal Australia +OUI:00153C* + ID_OUI_FROM_DATABASE=Kprotech Co., Ltd. -OUI:0017DF* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001543* + ID_OUI_FROM_DATABASE=Aberdeen Test Center -OUI:0018C6* - ID_OUI_FROM_DATABASE=OPW Fuel Management Systems +OUI:001535* + ID_OUI_FROM_DATABASE=OTE Spa -OUI:0018CB* - ID_OUI_FROM_DATABASE=Tecobest Technology Limited +OUI:001537* + ID_OUI_FROM_DATABASE=Ventus Networks -OUI:0018BF* - ID_OUI_FROM_DATABASE=Essence Technology Solution, Inc. +OUI:001536* + ID_OUI_FROM_DATABASE=Powertech co.,Ltd -OUI:0018BA* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001530* + ID_OUI_FROM_DATABASE=EMC Corporation -OUI:0018B8* - ID_OUI_FROM_DATABASE=New Voice International AG +OUI:001529* + ID_OUI_FROM_DATABASE=N3 Corporation -OUI:0018B3* - ID_OUI_FROM_DATABASE=TEC WizHome Co., Ltd. +OUI:0014F9* + ID_OUI_FROM_DATABASE=Vantage Controls -OUI:0018AC* - ID_OUI_FROM_DATABASE=Shanghai Jiao Da HISYS Technology Co. Ltd. +OUI:0014FB* + ID_OUI_FROM_DATABASE=Technical Solutions Inc. -OUI:0018A5* - ID_OUI_FROM_DATABASE=ADigit Technologies Corp. +OUI:0014FA* + ID_OUI_FROM_DATABASE=AsGa S.A. -OUI:0018A7* - ID_OUI_FROM_DATABASE=Yoggie Security Systems LTD. +OUI:0014F4* + ID_OUI_FROM_DATABASE=DekTec Digital Video B.V. -OUI:001896* - ID_OUI_FROM_DATABASE=Great Well Electronic LTD +OUI:0014ED* + ID_OUI_FROM_DATABASE=Airak, Inc. -OUI:00189B* - ID_OUI_FROM_DATABASE=Thomson Inc. +OUI:0014DE* + ID_OUI_FROM_DATABASE=Sage Instruments Inc. -OUI:00179E* - ID_OUI_FROM_DATABASE=Sirit Inc +OUI:0014E3* + ID_OUI_FROM_DATABASE=mm-lab GmbH -OUI:0017A3* - ID_OUI_FROM_DATABASE=MIX s.r.l. +OUI:0014D7* + ID_OUI_FROM_DATABASE=Datastore Technology Corp -OUI:0017A8* - ID_OUI_FROM_DATABASE=EDM Corporation +OUI:001524* + ID_OUI_FROM_DATABASE=Numatics, Inc. -OUI:001792* - ID_OUI_FROM_DATABASE=Falcom Wireless Comunications Gmbh +OUI:00151D* + ID_OUI_FROM_DATABASE=M2I CORPORATION -OUI:001797* - ID_OUI_FROM_DATABASE=Telsy Elettronica S.p.A. +OUI:001513* + ID_OUI_FROM_DATABASE=EFS sas -OUI:001799* - ID_OUI_FROM_DATABASE=SmarTire Systems Inc. +OUI:001507* + ID_OUI_FROM_DATABASE=Renaissance Learning Inc -OUI:00178B* - ID_OUI_FROM_DATABASE=Teledyne Technologies Incorporated +OUI:00129E* + ID_OUI_FROM_DATABASE=Surf Communications Inc. -OUI:00177F* - ID_OUI_FROM_DATABASE=Worldsmart Retech +OUI:001297* + ID_OUI_FROM_DATABASE=O2Micro, Inc. -OUI:001786* - ID_OUI_FROM_DATABASE=wisembed +OUI:001298* + ID_OUI_FROM_DATABASE=MICO ELECTRIC(SHENZHEN) LIMITED -OUI:001877* - ID_OUI_FROM_DATABASE=Amplex A/S +OUI:00128D* + ID_OUI_FROM_DATABASE=STB Datenservice GmbH -OUI:00186B* - ID_OUI_FROM_DATABASE=Sambu Communics CO., LTD. +OUI:00128E* + ID_OUI_FROM_DATABASE=Q-Free ASA -OUI:001870* - ID_OUI_FROM_DATABASE=E28 Shanghai Limited +OUI:001292* + ID_OUI_FROM_DATABASE=Griffin Technology -OUI:001863* - ID_OUI_FROM_DATABASE=Veritech Electronics Limited +OUI:00127C* + ID_OUI_FROM_DATABASE=SWEGON AB -OUI:001850* - ID_OUI_FROM_DATABASE=Secfone Kft +OUI:001281* + ID_OUI_FROM_DATABASE=March Networks S.p.A. -OUI:001855* - ID_OUI_FROM_DATABASE=Aeromaritime Systembau GmbH +OUI:00127B* + ID_OUI_FROM_DATABASE=VIA Networking Technologies, Inc. -OUI:001857* - ID_OUI_FROM_DATABASE=Unilever R&D +OUI:001327* + ID_OUI_FROM_DATABASE=Data Acquisitions limited -OUI:001849* - ID_OUI_FROM_DATABASE=Pigeon Point Systems LLC +OUI:00131D* + ID_OUI_FROM_DATABASE=Scanvaegt International A/S -OUI:0017C7* - ID_OUI_FROM_DATABASE=MARA Systems Consulting AB +OUI:001322* + ID_OUI_FROM_DATABASE=DAQ Electronics, Inc. -OUI:0017CE* - ID_OUI_FROM_DATABASE=Screen Service Spa +OUI:001316* + ID_OUI_FROM_DATABASE=L-S-B Broadcast Technologies GmbH -OUI:0017D3* - ID_OUI_FROM_DATABASE=Etymotic Research, Inc. +OUI:00130F* + ID_OUI_FROM_DATABASE=EGEMEN Bilgisayar Muh San ve Tic LTD STI -OUI:0017BB* - ID_OUI_FROM_DATABASE=Syrinx Industrial Electronics +OUI:0012F7* + ID_OUI_FROM_DATABASE=Xiamen Xinglian Electronics Co., Ltd. -OUI:0017B4* - ID_OUI_FROM_DATABASE=Remote Security Systems, LLC +OUI:0012FE* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. -OUI:0017B6* - ID_OUI_FROM_DATABASE=Aquantia +OUI:001303* + ID_OUI_FROM_DATABASE=GateConnect -OUI:0017AF* - ID_OUI_FROM_DATABASE=Enermet +OUI:0012FD* + ID_OUI_FROM_DATABASE=OPTIMUS IC S.A. -OUI:0018E8* - ID_OUI_FROM_DATABASE=Hacetron Corporation +OUI:00140F* + ID_OUI_FROM_DATABASE=Federal State Unitary Enterprise Leningrad R&D Institute of -OUI:0018EF* - ID_OUI_FROM_DATABASE=Escape Communications, Inc. +OUI:001416* + ID_OUI_FROM_DATABASE=Scosche Industries, Inc. -OUI:0018E3* - ID_OUI_FROM_DATABASE=Visualgate Systems, Inc. +OUI:001406* + ID_OUI_FROM_DATABASE=Go Networks -OUI:0018DC* - ID_OUI_FROM_DATABASE=Prostar Co., Ltd. +OUI:001407* + ID_OUI_FROM_DATABASE=Sperian Protection Instrumentation -OUI:0018E1* - ID_OUI_FROM_DATABASE=Verkerk Service Systemen +OUI:00140C* + ID_OUI_FROM_DATABASE=GKB CCTV CO., LTD. -OUI:0018D0* - ID_OUI_FROM_DATABASE=AtRoad, A Trimble Company +OUI:0013FF* + ID_OUI_FROM_DATABASE=Dage-MTI of MC, Inc. -OUI:0018D5* - ID_OUI_FROM_DATABASE=REIGNCOM +OUI:001400* + ID_OUI_FROM_DATABASE=MINERVA KOREA CO., LTD -OUI:0018A0* - ID_OUI_FROM_DATABASE=Cierma Ascenseurs +OUI:0013FA* + ID_OUI_FROM_DATABASE=LifeSize Communications, Inc -OUI:001883* - ID_OUI_FROM_DATABASE=FORMOSA21 INC. +OUI:0013F3* + ID_OUI_FROM_DATABASE=Giga-byte Communications Inc. -OUI:00188A* - ID_OUI_FROM_DATABASE=Infinova LLC +OUI:0013EE* + ID_OUI_FROM_DATABASE=JBX Designs Inc. -OUI:00188F* - ID_OUI_FROM_DATABASE=Montgomery Technology, Inc. +OUI:0013ED* + ID_OUI_FROM_DATABASE=PSIA -OUI:00187C* - ID_OUI_FROM_DATABASE=INTERCROSS, LLC +OUI:00135A* + ID_OUI_FROM_DATABASE=Project T&E Limited -OUI:00187E* - ID_OUI_FROM_DATABASE=RGB Spectrum +OUI:00135F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00164A* - ID_OUI_FROM_DATABASE=Vibration Technology Limited +OUI:001360* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001644* - ID_OUI_FROM_DATABASE=LITE-ON Technology Corp. +OUI:001352* + ID_OUI_FROM_DATABASE=Naztec, Inc. -OUI:001645* - ID_OUI_FROM_DATABASE=Power Distribution, Inc. +OUI:00134B* + ID_OUI_FROM_DATABASE=ToGoldenNet Technology Inc. -OUI:00163B* - ID_OUI_FROM_DATABASE=VertexRSI/General Dynamics +OUI:00134C* + ID_OUI_FROM_DATABASE=YDT Technology International -OUI:001640* - ID_OUI_FROM_DATABASE=Asmobile Communication Inc. +OUI:00133A* + ID_OUI_FROM_DATABASE=VadaTech Inc. -OUI:00163A* - ID_OUI_FROM_DATABASE=YVES TECHNOLOGY CO., LTD. +OUI:00133F* + ID_OUI_FROM_DATABASE=Eppendorf Instrumente GmbH -OUI:001634* - ID_OUI_FROM_DATABASE=Mathtech, Inc. +OUI:00132C* + ID_OUI_FROM_DATABASE=MAZ Brandenburg GmbH -OUI:00162D* - ID_OUI_FROM_DATABASE=STNet Co., Ltd. +OUI:001339* + ID_OUI_FROM_DATABASE=CCV Deutschland GmbH -OUI:001621* - ID_OUI_FROM_DATABASE=Colorado Vnet +OUI:0013AD* + ID_OUI_FROM_DATABASE=Sendo Ltd -OUI:00161A* - ID_OUI_FROM_DATABASE=Dametric AB +OUI:0013B4* + ID_OUI_FROM_DATABASE=Appear TV -OUI:001615* - ID_OUI_FROM_DATABASE=Nittan Company, Limited +OUI:0013A8* + ID_OUI_FROM_DATABASE=Tanisys Technology -OUI:0016C4* - ID_OUI_FROM_DATABASE=SiRF Technology, Inc. +OUI:0013A7* + ID_OUI_FROM_DATABASE=BATTELLE MEMORIAL INSTITUTE -OUI:0016C6* - ID_OUI_FROM_DATABASE=North Atlantic Industries +OUI:0013A1* + ID_OUI_FROM_DATABASE=Crow Electronic Engeneering -OUI:0016D2* - ID_OUI_FROM_DATABASE=Caspian +OUI:00139A* + ID_OUI_FROM_DATABASE=K-ubique ID Corp. -OUI:0016BF* - ID_OUI_FROM_DATABASE=PaloDEx Group Oy +OUI:001395* + ID_OUI_FROM_DATABASE=congatec AG -OUI:0016B3* - ID_OUI_FROM_DATABASE=Photonicbridges (China) Co., Ltd. +OUI:00138E* + ID_OUI_FROM_DATABASE=FOAB Elektronik AB -OUI:0016AC* - ID_OUI_FROM_DATABASE=Toho Technology Corp. +OUI:001388* + ID_OUI_FROM_DATABASE=WiMedia Alliance -OUI:0016B1* - ID_OUI_FROM_DATABASE=KBS +OUI:0013E4* + ID_OUI_FROM_DATABASE=YANGJAE SYSTEMS CORP. -OUI:0016A7* - ID_OUI_FROM_DATABASE=AWETA G&P +OUI:0013E9* + ID_OUI_FROM_DATABASE=VeriWave, Inc. -OUI:001724* - ID_OUI_FROM_DATABASE=Studer Professional Audio GmbH +OUI:0013E3* + ID_OUI_FROM_DATABASE=CoVi Technologies, Inc. -OUI:001718* - ID_OUI_FROM_DATABASE=Vansco Electronics Oy +OUI:0013DD* + ID_OUI_FROM_DATABASE=Abbott Diagnostics -OUI:00171D* - ID_OUI_FROM_DATABASE=DIGIT +OUI:0013D6* + ID_OUI_FROM_DATABASE=TII NETWORK TECHNOLOGIES, INC. -OUI:001711* - ID_OUI_FROM_DATABASE=GE Healthcare Bio-Sciences AB +OUI:0013D1* + ID_OUI_FROM_DATABASE=KIRK telecom A/S -OUI:00170C* - ID_OUI_FROM_DATABASE=Twig Com Ltd. +OUI:0013CA* + ID_OUI_FROM_DATABASE=Pico Digital -OUI:001707* - ID_OUI_FROM_DATABASE=InGrid, Inc +OUI:0013C3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001702* - ID_OUI_FROM_DATABASE=Osung Midicom Co., Ltd +OUI:0013C4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001744* - ID_OUI_FROM_DATABASE=Araneo Ltd. +OUI:0013BA* + ID_OUI_FROM_DATABASE=ReadyLinks Inc -OUI:00173C* - ID_OUI_FROM_DATABASE=Extreme Engineering Solutions +OUI:0013BE* + ID_OUI_FROM_DATABASE=Virtual Conexions -OUI:001737* - ID_OUI_FROM_DATABASE=Industrie Dial Face S.p.A. +OUI:0013B9* + ID_OUI_FROM_DATABASE=BM SPA -OUI:00172B* - ID_OUI_FROM_DATABASE=Global Technologies Inc. +OUI:0012F3* + ID_OUI_FROM_DATABASE=connectBlue AB -OUI:001730* - ID_OUI_FROM_DATABASE=Automation Electronics +OUI:0012ED* + ID_OUI_FROM_DATABASE=AVG Advanced Technologies -OUI:001729* - ID_OUI_FROM_DATABASE=Ubicod Co.LTD +OUI:0012E6* + ID_OUI_FROM_DATABASE=SPECTEC COMPUTER CO., LTD. -OUI:00169B* - ID_OUI_FROM_DATABASE=Alstom Transport +OUI:0012E1* + ID_OUI_FROM_DATABASE=Alliant Networks, Inc -OUI:0016A2* - ID_OUI_FROM_DATABASE=CentraLite Systems, Inc. +OUI:0012D3* + ID_OUI_FROM_DATABASE=Zetta Systems, Inc. -OUI:001696* - ID_OUI_FROM_DATABASE=QDI Technology (H.K.) Limited +OUI:0012DA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001688* - ID_OUI_FROM_DATABASE=ServerEngines LLC +OUI:0012D4* + ID_OUI_FROM_DATABASE=Princeton Technology, Ltd -OUI:00168A* - ID_OUI_FROM_DATABASE=id-Confirm Inc +OUI:0012C7* + ID_OUI_FROM_DATABASE=SECURAY Technologies Ltd.Co. -OUI:001683* - ID_OUI_FROM_DATABASE=WEBIO International Co.,.Ltd. +OUI:0012CE* + ID_OUI_FROM_DATABASE=Advanced Cybernetics Group -OUI:00167C* - ID_OUI_FROM_DATABASE=iRex Technologies BV +OUI:0012C2* + ID_OUI_FROM_DATABASE=Apex Electronics Factory -OUI:001610* - ID_OUI_FROM_DATABASE=Carina Technology +OUI:0012C1* + ID_OUI_FROM_DATABASE=Check Point Software Technologies -OUI:00160B* - ID_OUI_FROM_DATABASE=TVWorks LLC +OUI:0012B8* + ID_OUI_FROM_DATABASE=G2 Microsystems -OUI:001604* - ID_OUI_FROM_DATABASE=Sigpro +OUI:0012BD* + ID_OUI_FROM_DATABASE=Avantec Manufacturing Limited -OUI:0015FE* - ID_OUI_FROM_DATABASE=SCHILLING ROBOTICS LLC +OUI:0012B7* + ID_OUI_FROM_DATABASE=PTW Freiburg -OUI:0015FD* - ID_OUI_FROM_DATABASE=Complete Media Systems +OUI:0012B1* + ID_OUI_FROM_DATABASE=Dai Nippon Printing Co., Ltd -OUI:0015F8* - ID_OUI_FROM_DATABASE=Kingtronics Industrial Co. Ltd. +OUI:0012A5* + ID_OUI_FROM_DATABASE=Stargen, Inc. -OUI:0015EC* - ID_OUI_FROM_DATABASE=Boca Devices LLC +OUI:0012AA* + ID_OUI_FROM_DATABASE=IEE, Inc. -OUI:0015F1* - ID_OUI_FROM_DATABASE=KYLINK Communications Corp. +OUI:001379* + ID_OUI_FROM_DATABASE=PONDER INFORMATION INDUSTRIES LTD. -OUI:001677* - ID_OUI_FROM_DATABASE=Bihl + Wiedemann GmbH +OUI:001380* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001670* - ID_OUI_FROM_DATABASE=SKNET Corporation +OUI:001385* + ID_OUI_FROM_DATABASE=Add-On Technology Co., LTD. -OUI:001664* - ID_OUI_FROM_DATABASE=Prod-El SpA +OUI:00137F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001669* - ID_OUI_FROM_DATABASE=MRV Communication (Networks) LTD +OUI:00136D* + ID_OUI_FROM_DATABASE=Tentaculus AB -OUI:00165D* - ID_OUI_FROM_DATABASE=AirDefense, Inc. +OUI:001366* + ID_OUI_FROM_DATABASE=Neturity Technologies Inc. -OUI:001651* - ID_OUI_FROM_DATABASE=Exeo Systems +OUI:001258* + ID_OUI_FROM_DATABASE=Activis Polska -OUI:0015E5* - ID_OUI_FROM_DATABASE=Cheertek Inc. +OUI:001251* + ID_OUI_FROM_DATABASE=SILINK -OUI:0015DB* - ID_OUI_FROM_DATABASE=Canesta Inc. +OUI:001252* + ID_OUI_FROM_DATABASE=Citronix, LLC -OUI:0015D4* - ID_OUI_FROM_DATABASE=Emitor AB +OUI:001245* + ID_OUI_FROM_DATABASE=Zellweger Analytics, Inc. -OUI:0015C8* - ID_OUI_FROM_DATABASE=FlexiPanel Ltd +OUI:00124C* + ID_OUI_FROM_DATABASE=BBWM Corporation -OUI:0015C3* - ID_OUI_FROM_DATABASE=Ruf Telematik AG +OUI:001239* + ID_OUI_FROM_DATABASE=S Net Systems Inc. -OUI:0015C2* - ID_OUI_FROM_DATABASE=3M Germany +OUI:001240* + ID_OUI_FROM_DATABASE=AMOI ELECTRONICS CO.,LTD -OUI:0015BE* - ID_OUI_FROM_DATABASE=Iqua Ltd. +OUI:00122D* + ID_OUI_FROM_DATABASE=SiNett Corporation -OUI:0016EF* - ID_OUI_FROM_DATABASE=Koko Fitness, Inc. +OUI:001232* + ID_OUI_FROM_DATABASE=LeWiz Communications Inc. -OUI:0016F4* - ID_OUI_FROM_DATABASE=Eidicom Co., Ltd. +OUI:0011C5* + ID_OUI_FROM_DATABASE=TEN Technology -OUI:0016E8* - ID_OUI_FROM_DATABASE=Sigma Designs, Inc. +OUI:0011C8* + ID_OUI_FROM_DATABASE=Powercom Co., Ltd. -OUI:0016ED* - ID_OUI_FROM_DATABASE=Digital Safety Technologies, Inc +OUI:0011CD* + ID_OUI_FROM_DATABASE=Axsun Technologies -OUI:0016DC* - ID_OUI_FROM_DATABASE=ARCHOS +OUI:0011C6* + ID_OUI_FROM_DATABASE=Seagate Technology -OUI:0016E1* - ID_OUI_FROM_DATABASE=SiliconStor, Inc. +OUI:0011B4* + ID_OUI_FROM_DATABASE=Westermo Teleindustri AB -OUI:0016D7* - ID_OUI_FROM_DATABASE=Sunways AG +OUI:0011B9* + ID_OUI_FROM_DATABASE=Inner Range Pty. Ltd. -OUI:0014CB* - ID_OUI_FROM_DATABASE=LifeSync Corporation +OUI:0011C0* + ID_OUI_FROM_DATABASE=Aday Technology Inc -OUI:0014D0* - ID_OUI_FROM_DATABASE=BTI Systems Inc. +OUI:0011B3* + ID_OUI_FROM_DATABASE=YOSHIMIYA CO.,LTD. -OUI:0014C4* - ID_OUI_FROM_DATABASE=Vitelcom Mobile Technology +OUI:0011AD* + ID_OUI_FROM_DATABASE=Shanghai Ruijie Technology -OUI:0014BE* - ID_OUI_FROM_DATABASE=Wink communication technology CO.LTD +OUI:001138* + ID_OUI_FROM_DATABASE=TAISHIN CO., LTD. -OUI:0014BD* - ID_OUI_FROM_DATABASE=incNETWORKS, Inc +OUI:00113F* + ID_OUI_FROM_DATABASE=Alcatel DI -OUI:0014B8* - ID_OUI_FROM_DATABASE=Hill-Rom +OUI:001133* + ID_OUI_FROM_DATABASE=Siemens Austria SIMEA -OUI:0014AE* - ID_OUI_FROM_DATABASE=Wizlogics Co., Ltd. +OUI:001132* + ID_OUI_FROM_DATABASE=Synology Incorporated -OUI:0014B3* - ID_OUI_FROM_DATABASE=CoreStar International Corp +OUI:001129* + ID_OUI_FROM_DATABASE=Paradise Datacom Ltd. -OUI:00149B* - ID_OUI_FROM_DATABASE=Nokota Communications, LLC +OUI:00112E* + ID_OUI_FROM_DATABASE=CEICOM -OUI:00143F* - ID_OUI_FROM_DATABASE=Hotway Technology Corporation +OUI:001128* + ID_OUI_FROM_DATABASE=Streamit -OUI:001431* - ID_OUI_FROM_DATABASE=PDL Electronics Ltd +OUI:001122* + ID_OUI_FROM_DATABASE=CIMSYS Inc -OUI:001433* - ID_OUI_FROM_DATABASE=Empower Technologies(Canada) Inc. +OUI:001171* + ID_OUI_FROM_DATABASE=DEXTER Communications, Inc. -OUI:001432* - ID_OUI_FROM_DATABASE=Tarallax Wireless, Inc. +OUI:00116A* + ID_OUI_FROM_DATABASE=Domo Ltd -OUI:00142C* - ID_OUI_FROM_DATABASE=Koncept International, Inc. +OUI:001160* + ID_OUI_FROM_DATABASE=ARTDIO Company Co., LTD -OUI:001425* - ID_OUI_FROM_DATABASE=Galactic Computing Corp. +OUI:001154* + ID_OUI_FROM_DATABASE=Webpro Technologies Inc. -OUI:001420* - ID_OUI_FROM_DATABASE=G-Links networking company +OUI:00114B* + ID_OUI_FROM_DATABASE=Francotyp-Postalia GmbH -OUI:00141B* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001145* + ID_OUI_FROM_DATABASE=ValuePoint Networks -OUI:00146D* - ID_OUI_FROM_DATABASE=RF Technologies +OUI:0011A1* + ID_OUI_FROM_DATABASE=VISION NETWARE CO.,LTD -OUI:00146F* - ID_OUI_FROM_DATABASE=Kohler Co +OUI:0011A6* + ID_OUI_FROM_DATABASE=Sypixx Networks -OUI:00146E* - ID_OUI_FROM_DATABASE=H. Stoll GmbH & Co. KG +OUI:00119A* + ID_OUI_FROM_DATABASE=Alkeria srl -OUI:001468* - ID_OUI_FROM_DATABASE=CelPlan International, Inc. +OUI:001190* + ID_OUI_FROM_DATABASE=Digital Design Corporation -OUI:001461* - ID_OUI_FROM_DATABASE=CORONA CORPORATION +OUI:00118A* + ID_OUI_FROM_DATABASE=Viewtran Technology Limited -OUI:00145C* - ID_OUI_FROM_DATABASE=Intronics B.V. +OUI:001194* + ID_OUI_FROM_DATABASE=Chi Mei Communication Systems, Inc. -OUI:001455* - ID_OUI_FROM_DATABASE=Coder Electronics Corporation +OUI:001189* + ID_OUI_FROM_DATABASE=Aerotech Inc -OUI:001444* - ID_OUI_FROM_DATABASE=Grundfos Holding +OUI:001184* + ID_OUI_FROM_DATABASE=Humo Laboratory,Ltd. -OUI:00144B* - ID_OUI_FROM_DATABASE=Hifn, Inc. +OUI:00117D* + ID_OUI_FROM_DATABASE=ZMD America, Inc. -OUI:001589* - ID_OUI_FROM_DATABASE=D-MAX Technology Co.,Ltd +OUI:001178* + ID_OUI_FROM_DATABASE=Chiron Technology Ltd -OUI:001582* - ID_OUI_FROM_DATABASE=Pulse Eight Limited +OUI:001177* + ID_OUI_FROM_DATABASE=Coaxial Networks, Inc. -OUI:00157C* - ID_OUI_FROM_DATABASE=Dave Networks, Inc. +OUI:001223* + ID_OUI_FROM_DATABASE=Pixim -OUI:001578* - ID_OUI_FROM_DATABASE=Audio / Video Innovations +OUI:001228* + ID_OUI_FROM_DATABASE=Data Ltd. -OUI:001573* - ID_OUI_FROM_DATABASE=NewSoft Technology Corporation +OUI:001210* + ID_OUI_FROM_DATABASE=WideRay Corp -OUI:00156C* - ID_OUI_FROM_DATABASE=SANE SYSTEM CO., LTD +OUI:001215* + ID_OUI_FROM_DATABASE=iStor Networks, Inc. -OUI:001571* - ID_OUI_FROM_DATABASE=Nolan Systems +OUI:001216* + ID_OUI_FROM_DATABASE=ICP Internet Communication Payment AG -OUI:001572* - ID_OUI_FROM_DATABASE=Red-Lemon +OUI:001209* + ID_OUI_FROM_DATABASE=Fastrax Ltd -OUI:001565* - ID_OUI_FROM_DATABASE=XIAMEN YEALINK NETWORK TECHNOLOGY CO.,LTD +OUI:001204* + ID_OUI_FROM_DATABASE=u10 Networks, Inc. -OUI:001559* - ID_OUI_FROM_DATABASE=Securaplane Technologies, Inc. +OUI:0011FD* + ID_OUI_FROM_DATABASE=KORG INC. -OUI:0014A2* - ID_OUI_FROM_DATABASE=Core Micro Systems Inc. +OUI:001203* + ID_OUI_FROM_DATABASE=ActivNetworks -OUI:001494* - ID_OUI_FROM_DATABASE=ESU AG +OUI:0011F3* + ID_OUI_FROM_DATABASE=NeoMedia Europe AG -OUI:00148F* - ID_OUI_FROM_DATABASE=Protronic (Far East) Ltd. +OUI:0011E7* + ID_OUI_FROM_DATABASE=WORLDSAT - Texas de France -OUI:001488* - ID_OUI_FROM_DATABASE=Akorri +OUI:0011EC* + ID_OUI_FROM_DATABASE=AVIX INC. -OUI:001483* - ID_OUI_FROM_DATABASE=eXS Inc. +OUI:0011E0* + ID_OUI_FROM_DATABASE=U-MEDIA Communications, Inc. -OUI:001480* - ID_OUI_FROM_DATABASE=Hitachi-LG Data Storage Korea, Inc +OUI:0011DA* + ID_OUI_FROM_DATABASE=Vivaas Technology Inc. -OUI:00147B* - ID_OUI_FROM_DATABASE=Iteris, Inc. +OUI:0011D4* + ID_OUI_FROM_DATABASE=NetEnrich, Inc -OUI:001474* - ID_OUI_FROM_DATABASE=K40 Electronics +OUI:0011D9* + ID_OUI_FROM_DATABASE=TiVo -OUI:0015B8* - ID_OUI_FROM_DATABASE=Tahoe +OUI:00111C* + ID_OUI_FROM_DATABASE=Pleora Technologies Inc. -OUI:0015B2* - ID_OUI_FROM_DATABASE=Advanced Industrial Computer, Inc. +OUI:00110F* + ID_OUI_FROM_DATABASE=netplat,Inc. -OUI:0015AE* - ID_OUI_FROM_DATABASE=kyung il +OUI:001116* + ID_OUI_FROM_DATABASE=COTEAU VERT CO., LTD. -OUI:0015AD* - ID_OUI_FROM_DATABASE=Accedian Networks +OUI:001109* + ID_OUI_FROM_DATABASE=Micro-Star International -OUI:00E0A8* - ID_OUI_FROM_DATABASE=SAT GmbH & Co. +OUI:001103* + ID_OUI_FROM_DATABASE=kawamura electric inc. -OUI:0015A1* - ID_OUI_FROM_DATABASE=ECA-SINTERS +OUI:000FFD* + ID_OUI_FROM_DATABASE=Glorytek Network Inc. -OUI:00159C* - ID_OUI_FROM_DATABASE=B-KYUNG SYSTEM Co.,Ltd. +OUI:000FEE* + ID_OUI_FROM_DATABASE=XTec, Incorporated -OUI:001595* - ID_OUI_FROM_DATABASE=Quester Tangent Corporation +OUI:000FF4* + ID_OUI_FROM_DATABASE=Guntermann & Drunck GmbH -OUI:00158E* - ID_OUI_FROM_DATABASE=Plustek.INC +OUI:001275* + ID_OUI_FROM_DATABASE=Sentilla Corporation -OUI:001552* - ID_OUI_FROM_DATABASE=Wi-Gear Inc. +OUI:00126E* + ID_OUI_FROM_DATABASE=Seidel Elektronik GmbH Nfg.KG -OUI:001548* - ID_OUI_FROM_DATABASE=CUBE TECHNOLOGIES +OUI:001269* + ID_OUI_FROM_DATABASE=Value Electronics -OUI:00154D* - ID_OUI_FROM_DATABASE=Netronome Systems, Inc. +OUI:00125C* + ID_OUI_FROM_DATABASE=Green Hills Software, Inc. -OUI:00153C* - ID_OUI_FROM_DATABASE=Kprotech Co., Ltd. +OUI:000F15* + ID_OUI_FROM_DATABASE=Kjaerulff1 A/S -OUI:001543* - ID_OUI_FROM_DATABASE=Aberdeen Test Center +OUI:000F1A* + ID_OUI_FROM_DATABASE=Gaming Support B.V. -OUI:001535* - ID_OUI_FROM_DATABASE=OTE Spa +OUI:000F0E* + ID_OUI_FROM_DATABASE=WaveSplitter Technologies, Inc. -OUI:001537* - ID_OUI_FROM_DATABASE=Ventus Networks +OUI:000F08* + ID_OUI_FROM_DATABASE=Indagon Oy -OUI:001536* - ID_OUI_FROM_DATABASE=Powertech co.,Ltd +OUI:000F07* + ID_OUI_FROM_DATABASE=Mangrove Systems, Inc. -OUI:001530* - ID_OUI_FROM_DATABASE=EMC Corporation +OUI:000F02* + ID_OUI_FROM_DATABASE=Digicube Technology Co., Ltd -OUI:001529* - ID_OUI_FROM_DATABASE=N3 Corporation +OUI:000EFB* + ID_OUI_FROM_DATABASE=Macey Enterprises -OUI:0014F9* - ID_OUI_FROM_DATABASE=Vantage Controls +OUI:000EF5* + ID_OUI_FROM_DATABASE=iPAC Technology Co., Ltd. -OUI:0014FB* - ID_OUI_FROM_DATABASE=Technical Solutions Inc. +OUI:000EF6* + ID_OUI_FROM_DATABASE=E-TEN Information Systems Co., Ltd. -OUI:0014FA* - ID_OUI_FROM_DATABASE=AsGa S.A. +OUI:000E8A* + ID_OUI_FROM_DATABASE=Avara Technologies Pty. Ltd. -OUI:0014F4* - ID_OUI_FROM_DATABASE=DekTec Digital Video B.V. +OUI:000E83* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0014ED* - ID_OUI_FROM_DATABASE=Airak, Inc. +OUI:000E73* + ID_OUI_FROM_DATABASE=Tpack A/S -OUI:0014DE* - ID_OUI_FROM_DATABASE=Sage Instruments Inc. +OUI:000E7D* + ID_OUI_FROM_DATABASE=Electronics Line 3000 Ltd. -OUI:0014E3* - ID_OUI_FROM_DATABASE=mm-lab GmbH +OUI:000E77* + ID_OUI_FROM_DATABASE=Decru, Inc. -OUI:0014D7* - ID_OUI_FROM_DATABASE=Datastore Technology Corp +OUI:000E7E* + ID_OUI_FROM_DATABASE=ionSign Oy -OUI:001524* - ID_OUI_FROM_DATABASE=Numatics, Inc. +OUI:000E6F* + ID_OUI_FROM_DATABASE=IRIS Corporation Berhad -OUI:00151D* - ID_OUI_FROM_DATABASE=M2I CORPORATION +OUI:000E6A* + ID_OUI_FROM_DATABASE=3Com Ltd -OUI:001513* - ID_OUI_FROM_DATABASE=EFS sas +OUI:000E69* + ID_OUI_FROM_DATABASE=China Electric Power Research Institute -OUI:001507* - ID_OUI_FROM_DATABASE=Renaissance Learning Inc +OUI:000E63* + ID_OUI_FROM_DATABASE=Lemke Diagnostics GmbH -OUI:00129E* - ID_OUI_FROM_DATABASE=Surf Communications Inc. +OUI:000EBC* + ID_OUI_FROM_DATABASE=Paragon Fidelity GmbH -OUI:001297* - ID_OUI_FROM_DATABASE=O2Micro, Inc. +OUI:000EB0* + ID_OUI_FROM_DATABASE=Solutions Radio BV -OUI:001298* - ID_OUI_FROM_DATABASE=MICO ELECTRIC(SHENZHEN) LIMITED +OUI:000EB5* + ID_OUI_FROM_DATABASE=Ecastle Electronics Co., Ltd. -OUI:00128D* - ID_OUI_FROM_DATABASE=STB Datenservice GmbH +OUI:000EAF* + ID_OUI_FROM_DATABASE=CASTEL -OUI:00128E* - ID_OUI_FROM_DATABASE=Q-Free ASA +OUI:000EA9* + ID_OUI_FROM_DATABASE=Shanghai Xun Shi Communications Equipment Ltd. Co. -OUI:001292* - ID_OUI_FROM_DATABASE=Griffin Technology +OUI:000E9D* + ID_OUI_FROM_DATABASE=Tiscali UK Ltd -OUI:00127C* - ID_OUI_FROM_DATABASE=SWEGON AB +OUI:000EA2* + ID_OUI_FROM_DATABASE=McAfee, Inc -OUI:001281* - ID_OUI_FROM_DATABASE=March Networks S.p.A. +OUI:000E90* + ID_OUI_FROM_DATABASE=PONICO CORP. -OUI:00127B* - ID_OUI_FROM_DATABASE=VIA Networking Technologies, Inc. +OUI:000E8F* + ID_OUI_FROM_DATABASE=Sercomm Corp. -OUI:001327* - ID_OUI_FROM_DATABASE=Data Acquisitions limited +OUI:000E96* + ID_OUI_FROM_DATABASE=Cubic Defense Applications, Inc. -OUI:00131D* - ID_OUI_FROM_DATABASE=Scanvaegt International A/S +OUI:000F4E* + ID_OUI_FROM_DATABASE=Cellink -OUI:001322* - ID_OUI_FROM_DATABASE=DAQ Electronics, Inc. +OUI:000F41* + ID_OUI_FROM_DATABASE=Zipher Ltd -OUI:001316* - ID_OUI_FROM_DATABASE=L-S-B Broadcast Technologies GmbH +OUI:000F48* + ID_OUI_FROM_DATABASE=Polypix Inc. -OUI:00130F* - ID_OUI_FROM_DATABASE=EGEMEN Bilgisayar Muh San ve Tic LTD STI +OUI:000F4D* + ID_OUI_FROM_DATABASE=TalkSwitch -OUI:0012F7* - ID_OUI_FROM_DATABASE=Xiamen Xinglian Electronics Co., Ltd. +OUI:000F39* + ID_OUI_FROM_DATABASE=IRIS SENSORS -OUI:0012FE* - ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. +OUI:000F3C* + ID_OUI_FROM_DATABASE=Endeleo Limited -OUI:001303* - ID_OUI_FROM_DATABASE=GateConnect +OUI:000F34* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0012FD* - ID_OUI_FROM_DATABASE=OPTIMUS IC S.A. +OUI:000F2D* + ID_OUI_FROM_DATABASE=CHUNG-HSIN ELECTRIC & MACHINERY MFG.CORP. -OUI:00140F* - ID_OUI_FROM_DATABASE=Federal State Unitary Enterprise Leningrad R&D Institute of +OUI:000F27* + ID_OUI_FROM_DATABASE=TEAL Electronics, Inc. -OUI:001416* - ID_OUI_FROM_DATABASE=Scosche Industries, Inc. +OUI:000F28* + ID_OUI_FROM_DATABASE=Itronix Corporation -OUI:001406* - ID_OUI_FROM_DATABASE=Go Networks +OUI:000F21* + ID_OUI_FROM_DATABASE=Scientific Atlanta, Inc -OUI:001407* - ID_OUI_FROM_DATABASE=Sperian Protection Instrumentation +OUI:000EEF* + ID_OUI_FROM_DATABASE=Private -OUI:00140C* - ID_OUI_FROM_DATABASE=GKB CCTV CO., LTD. +OUI:000EDC* + ID_OUI_FROM_DATABASE=Tellion INC. -OUI:0013FF* - ID_OUI_FROM_DATABASE=Dage-MTI of MC, Inc. +OUI:000EE3* + ID_OUI_FROM_DATABASE=Chiyu Technology Co.,Ltd -OUI:001400* - ID_OUI_FROM_DATABASE=MINERVA KOREA CO., LTD +OUI:000EC8* + ID_OUI_FROM_DATABASE=Zoran Corporation -OUI:0013FA* - ID_OUI_FROM_DATABASE=LifeSize Communications, Inc +OUI:000ECF* + ID_OUI_FROM_DATABASE=PROFIBUS Nutzerorganisation e.V. -OUI:0013F3* - ID_OUI_FROM_DATABASE=Giga-byte Communications Inc. +OUI:000ED4* + ID_OUI_FROM_DATABASE=CRESITT INDUSTRIE -OUI:0013EE* - ID_OUI_FROM_DATABASE=JBX Designs Inc. +OUI:000EC2* + ID_OUI_FROM_DATABASE=Lowrance Electronics, Inc. -OUI:0013ED* - ID_OUI_FROM_DATABASE=PSIA +OUI:000EC1* + ID_OUI_FROM_DATABASE=MYNAH Technologies -OUI:00135A* - ID_OUI_FROM_DATABASE=Project T&E Limited +OUI:000F92* + ID_OUI_FROM_DATABASE=Microhard Systems Inc. -OUI:00135F* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000F99* + ID_OUI_FROM_DATABASE=APAC opto Electronics Inc. -OUI:001360* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000F8D* + ID_OUI_FROM_DATABASE=FAST TV-Server AG -OUI:001352* - ID_OUI_FROM_DATABASE=Naztec, Inc. +OUI:000F80* + ID_OUI_FROM_DATABASE=Trinity Security Systems,Inc. -OUI:00134B* - ID_OUI_FROM_DATABASE=ToGoldenNet Technology Inc. +OUI:000F7F* + ID_OUI_FROM_DATABASE=UBSTORAGE Co.,Ltd. -OUI:00134C* - ID_OUI_FROM_DATABASE=YDT Technology International +OUI:000FC9* + ID_OUI_FROM_DATABASE=Allnet GmbH -OUI:00133A* - ID_OUI_FROM_DATABASE=VadaTech Inc. +OUI:000FBC* + ID_OUI_FROM_DATABASE=Onkey Technologies, Inc. -OUI:00133F* - ID_OUI_FROM_DATABASE=Eppendorf Instrumente GmbH +OUI:000FBB* + ID_OUI_FROM_DATABASE=Nokia Siemens Networks GmbH & Co. KG. -OUI:00132C* - ID_OUI_FROM_DATABASE=MAZ Brandenburg GmbH +OUI:000FB6* + ID_OUI_FROM_DATABASE=Europlex Technologies -OUI:001339* - ID_OUI_FROM_DATABASE=CCV Deutschland GmbH +OUI:000FA9* + ID_OUI_FROM_DATABASE=PC Fabrik -OUI:0013AD* - ID_OUI_FROM_DATABASE=Sendo Ltd +OUI:000FAA* + ID_OUI_FROM_DATABASE=Nexus Technologies -OUI:0013B4* - ID_OUI_FROM_DATABASE=Appear TV +OUI:000FAF* + ID_OUI_FROM_DATABASE=Dialog Inc. -OUI:0013A8* - ID_OUI_FROM_DATABASE=Tanisys Technology +OUI:000FE8* + ID_OUI_FROM_DATABASE=Lobos, Inc. -OUI:0013A7* - ID_OUI_FROM_DATABASE=BATTELLE MEMORIAL INSTITUTE +OUI:000FED* + ID_OUI_FROM_DATABASE=Anam Electronics Co., Ltd -OUI:0013A1* - ID_OUI_FROM_DATABASE=Crow Electronic Engeneering +OUI:000FDC* + ID_OUI_FROM_DATABASE=Ueda Japan Radio Co., Ltd. -OUI:00139A* - ID_OUI_FROM_DATABASE=K-ubique ID Corp. +OUI:000FE1* + ID_OUI_FROM_DATABASE=ID DIGITAL CORPORATION -OUI:001395* - ID_OUI_FROM_DATABASE=congatec AG +OUI:000FD5* + ID_OUI_FROM_DATABASE=Schwechat - RISE -OUI:00138E* - ID_OUI_FROM_DATABASE=FOAB Elektronik AB +OUI:000FCE* + ID_OUI_FROM_DATABASE=Kikusui Electronics Corp. -OUI:001388* - ID_OUI_FROM_DATABASE=WiMedia Alliance +OUI:000F73* + ID_OUI_FROM_DATABASE=RS Automation Co., Ltd -OUI:0013E4* - ID_OUI_FROM_DATABASE=YANGJAE SYSTEMS CORP. +OUI:000F7A* + ID_OUI_FROM_DATABASE=BeiJing NuQX Technology CO.,LTD -OUI:0013E9* - ID_OUI_FROM_DATABASE=VeriWave, Inc. +OUI:000F6D* + ID_OUI_FROM_DATABASE=Midas Engineering -OUI:0013E3* - ID_OUI_FROM_DATABASE=CoVi Technologies, Inc. +OUI:000F67* + ID_OUI_FROM_DATABASE=West Instruments -OUI:0013DD* - ID_OUI_FROM_DATABASE=Abbott Diagnostics +OUI:000F6E* + ID_OUI_FROM_DATABASE=BBox -OUI:0013D6* - ID_OUI_FROM_DATABASE=TII NETWORK TECHNOLOGIES, INC. +OUI:000F60* + ID_OUI_FROM_DATABASE=Lifetron Co.,Ltd -OUI:0013D1* - ID_OUI_FROM_DATABASE=KIRK telecom A/S +OUI:000F5B* + ID_OUI_FROM_DATABASE=Delta Information Systems, Inc. -OUI:0013CA* - ID_OUI_FROM_DATABASE=Pico Digital +OUI:000F54* + ID_OUI_FROM_DATABASE=Entrelogic Corporation -OUI:0013C3* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000D75* + ID_OUI_FROM_DATABASE=Kobian Pte Ltd - Taiwan Branch -OUI:0013C4* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000D7C* + ID_OUI_FROM_DATABASE=Codian Ltd -OUI:0013BA* - ID_OUI_FROM_DATABASE=ReadyLinks Inc +OUI:000D6F* + ID_OUI_FROM_DATABASE=Ember Corporation -OUI:0013BE* - ID_OUI_FROM_DATABASE=Virtual Conexions +OUI:000D69* + ID_OUI_FROM_DATABASE=TMT&D Corporation -OUI:0013B9* - ID_OUI_FROM_DATABASE=BM SPA +OUI:000D70* + ID_OUI_FROM_DATABASE=Datamax Corporation -OUI:0012F3* - ID_OUI_FROM_DATABASE=connectBlue AB +OUI:000D5D* + ID_OUI_FROM_DATABASE=Raritan Computer, Inc -OUI:0012ED* - ID_OUI_FROM_DATABASE=AVG Advanced Technologies +OUI:000D62* + ID_OUI_FROM_DATABASE=Funkwerk Dabendorf GmbH -OUI:0012E6* - ID_OUI_FROM_DATABASE=SPECTEC COMPUTER CO., LTD. +OUI:000D50* + ID_OUI_FROM_DATABASE=Galazar Networks -OUI:0012E1* - ID_OUI_FROM_DATABASE=Alliant Networks, Inc +OUI:000D4A* + ID_OUI_FROM_DATABASE=Steag ETA-Optik -OUI:0012D3* - ID_OUI_FROM_DATABASE=Zetta Systems, Inc. +OUI:000DAB* + ID_OUI_FROM_DATABASE=Parker Hannifin GmbH Electromechanical Division Europe -OUI:0012DA* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000DA7* + ID_OUI_FROM_DATABASE=Private -OUI:0012D4* - ID_OUI_FROM_DATABASE=Princeton Technology, Ltd +OUI:000DA1* + ID_OUI_FROM_DATABASE=MIRAE ITS Co.,LTD. -OUI:0012C7* - ID_OUI_FROM_DATABASE=SECURAY Technologies Ltd.Co. +OUI:000DA2* + ID_OUI_FROM_DATABASE=Infrant Technologies, Inc. -OUI:0012CE* - ID_OUI_FROM_DATABASE=Advanced Cybernetics Group +OUI:000D9B* + ID_OUI_FROM_DATABASE=Heraeus Electro-Nite International N.V. -OUI:0012C2* - ID_OUI_FROM_DATABASE=Apex Electronics Factory +OUI:000D8F* + ID_OUI_FROM_DATABASE=King Tsushin Kogyo Co., LTD. -OUI:0012C1* - ID_OUI_FROM_DATABASE=Check Point Software Technologies +OUI:000D94* + ID_OUI_FROM_DATABASE=AFAR Communications,Inc -OUI:0012B8* - ID_OUI_FROM_DATABASE=G2 Microsystems +OUI:000D82* + ID_OUI_FROM_DATABASE=PHS srl -OUI:0012BD* - ID_OUI_FROM_DATABASE=Avantec Manufacturing Limited +OUI:000D81* + ID_OUI_FROM_DATABASE=Pepperl+Fuchs GmbH -OUI:0012B7* - ID_OUI_FROM_DATABASE=PTW Freiburg +OUI:000DCE* + ID_OUI_FROM_DATABASE=Dynavac Technology Pte Ltd -OUI:0012B1* - ID_OUI_FROM_DATABASE=Dai Nippon Printing Co., Ltd +OUI:000DC8* + ID_OUI_FROM_DATABASE=AirMagnet, Inc -OUI:0012A5* - ID_OUI_FROM_DATABASE=Stargen, Inc. +OUI:000DC2* + ID_OUI_FROM_DATABASE=Private -OUI:0012AA* - ID_OUI_FROM_DATABASE=IEE, Inc. +OUI:000DC7* + ID_OUI_FROM_DATABASE=COSMIC ENGINEERING INC. -OUI:001379* - ID_OUI_FROM_DATABASE=PONDER INFORMATION INDUSTRIES LTD. +OUI:000DBB* + ID_OUI_FROM_DATABASE=Nippon Dentsu Co.,Ltd. -OUI:001380* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000DB5* + ID_OUI_FROM_DATABASE=GLOBALSAT TECHNOLOGY CORPORATION -OUI:001385* - ID_OUI_FROM_DATABASE=Add-On Technology Co., LTD. +OUI:000DAF* + ID_OUI_FROM_DATABASE=Plexus Corp (UK) Ltd -OUI:00137F* +OUI:000D29* ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00136D* - ID_OUI_FROM_DATABASE=Tentaculus AB - -OUI:001366* - ID_OUI_FROM_DATABASE=Neturity Technologies Inc. +OUI:000D23* + ID_OUI_FROM_DATABASE=Smart Solution, Inc -OUI:001258* - ID_OUI_FROM_DATABASE=Activis Polska +OUI:000D17* + ID_OUI_FROM_DATABASE=Turbo Networks Co.Ltd -OUI:001251* - ID_OUI_FROM_DATABASE=SILINK +OUI:000D1C* + ID_OUI_FROM_DATABASE=Amesys Defense -OUI:001252* - ID_OUI_FROM_DATABASE=Citronix, LLC +OUI:000D0A* + ID_OUI_FROM_DATABASE=Projectiondesign as -OUI:001245* - ID_OUI_FROM_DATABASE=Zellweger Analytics, Inc. +OUI:000D09* + ID_OUI_FROM_DATABASE=Yuehua(Zhuhai) Electronic CO. LTD -OUI:00124C* - ID_OUI_FROM_DATABASE=BBWM Corporation +OUI:000D10* + ID_OUI_FROM_DATABASE=Embedtronics Oy -OUI:001239* - ID_OUI_FROM_DATABASE=S Net Systems Inc. +OUI:000D04* + ID_OUI_FROM_DATABASE=Foxboro Eckardt Development GmbH -OUI:001240* - ID_OUI_FROM_DATABASE=AMOI ELECTRONICS CO.,LTD +OUI:000CFD* + ID_OUI_FROM_DATABASE=Hyundai ImageQuest Co.,Ltd. -OUI:00122D* - ID_OUI_FROM_DATABASE=SiNett Corporation +OUI:000D4F* + ID_OUI_FROM_DATABASE=Kenwood Corporation -OUI:001232* - ID_OUI_FROM_DATABASE=LeWiz Communications Inc. +OUI:000D46* + ID_OUI_FROM_DATABASE=Parker SSD Drives -OUI:0011C5* - ID_OUI_FROM_DATABASE=TEN Technology +OUI:000D42* + ID_OUI_FROM_DATABASE=Newbest Development Limited -OUI:0011C8* - ID_OUI_FROM_DATABASE=Powercom Co., Ltd. +OUI:000D3C* + ID_OUI_FROM_DATABASE=i.Tech Dynamic Ltd -OUI:0011CD* - ID_OUI_FROM_DATABASE=Axsun Technologies +OUI:000D36* + ID_OUI_FROM_DATABASE=Wu Han Routon Electronic Co., Ltd -OUI:0011C6* - ID_OUI_FROM_DATABASE=Seagate Technology +OUI:000D3B* + ID_OUI_FROM_DATABASE=Microelectronics Technology Inc. -OUI:0011B4* - ID_OUI_FROM_DATABASE=Westermo Teleindustri AB +OUI:000D2A* + ID_OUI_FROM_DATABASE=Scanmatic AS -OUI:0011B9* - ID_OUI_FROM_DATABASE=Inner Range Pty. Ltd. +OUI:000D2F* + ID_OUI_FROM_DATABASE=AIN Comm.Tech.Co., LTD -OUI:0011C0* - ID_OUI_FROM_DATABASE=Aday Technology Inc +OUI:000DFA* + ID_OUI_FROM_DATABASE=Micro Control Systems Ltd. -OUI:0011B3* - ID_OUI_FROM_DATABASE=YOSHIMIYA CO.,LTD. +OUI:000DF4* + ID_OUI_FROM_DATABASE=Watertek Co. -OUI:0011AD* - ID_OUI_FROM_DATABASE=Shanghai Ruijie Technology +OUI:000DF9* + ID_OUI_FROM_DATABASE=NDS Limited -OUI:001138* - ID_OUI_FROM_DATABASE=TAISHIN CO., LTD. +OUI:000E00* + ID_OUI_FROM_DATABASE=Atrie -OUI:00113F* - ID_OUI_FROM_DATABASE=Alcatel DI +OUI:000DE7* + ID_OUI_FROM_DATABASE=Snap-on OEM Group -OUI:001133* - ID_OUI_FROM_DATABASE=Siemens Austria SIMEA +OUI:000DE8* + ID_OUI_FROM_DATABASE=Nasaco Electronics Pte. Ltd -OUI:001132* - ID_OUI_FROM_DATABASE=Synology Incorporated +OUI:000DED* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:001129* - ID_OUI_FROM_DATABASE=Paradise Datacom Ltd. +OUI:000DE1* + ID_OUI_FROM_DATABASE=Control Products, Inc. -OUI:00112E* - ID_OUI_FROM_DATABASE=CEICOM +OUI:000DD5* + ID_OUI_FROM_DATABASE=O'RITE TECHNOLOGY CO.,LTD -OUI:001128* - ID_OUI_FROM_DATABASE=Streamit +OUI:000DDA* + ID_OUI_FROM_DATABASE=ALLIED TELESIS K.K. -OUI:00111B* - ID_OUI_FROM_DATABASE=Targa Systems Div L-3 Communications Canada +OUI:000E20* + ID_OUI_FROM_DATABASE=ACCESS Systems Americas, Inc. -OUI:001122* - ID_OUI_FROM_DATABASE=CIMSYS Inc +OUI:000E27* + ID_OUI_FROM_DATABASE=Crere Networks, Inc. -OUI:001171* - ID_OUI_FROM_DATABASE=DEXTER Communications, Inc. +OUI:000E14* + ID_OUI_FROM_DATABASE=Visionary Solutions, Inc. -OUI:00116A* - ID_OUI_FROM_DATABASE=Domo Ltd +OUI:000E1B* + ID_OUI_FROM_DATABASE=IAV GmbH -OUI:001160* - ID_OUI_FROM_DATABASE=ARTDIO Company Co., LTD +OUI:000E57* + ID_OUI_FROM_DATABASE=Iworld Networking, Inc. -OUI:001154* - ID_OUI_FROM_DATABASE=Webpro Technologies Inc. +OUI:000E50* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium -OUI:00114B* - ID_OUI_FROM_DATABASE=Francotyp-Postalia GmbH +OUI:000E4A* + ID_OUI_FROM_DATABASE=Changchun Huayu WEBPAD Co.,LTD -OUI:001145* - ID_OUI_FROM_DATABASE=ValuePoint Networks +OUI:000E49* + ID_OUI_FROM_DATABASE=Forsway Scandinavia AB -OUI:0011A1* - ID_OUI_FROM_DATABASE=VISION NETWARE CO.,LTD +OUI:000E3D* + ID_OUI_FROM_DATABASE=Televic N.V. -OUI:0011A6* - ID_OUI_FROM_DATABASE=Sypixx Networks +OUI:000E44* + ID_OUI_FROM_DATABASE=Digital 5, Inc. -OUI:00119A* - ID_OUI_FROM_DATABASE=Alkeria srl +OUI:000E33* + ID_OUI_FROM_DATABASE=Shuko Electronics Co.,Ltd -OUI:001190* - ID_OUI_FROM_DATABASE=Digital Design Corporation +OUI:000E3A* + ID_OUI_FROM_DATABASE=Cirrus Logic -OUI:00118A* - ID_OUI_FROM_DATABASE=Viewtran Technology Limited +OUI:000E2D* + ID_OUI_FROM_DATABASE=Hyundai Digital Technology Co.,Ltd. -OUI:001194* - ID_OUI_FROM_DATABASE=Chi Mei Communication Systems, Inc. +OUI:000CEA* + ID_OUI_FROM_DATABASE=aphona Kommunikationssysteme -OUI:001189* - ID_OUI_FROM_DATABASE=Aerotech Inc +OUI:000CD9* + ID_OUI_FROM_DATABASE=Itcare Co., Ltd -OUI:001184* - ID_OUI_FROM_DATABASE=Humo Laboratory,Ltd. +OUI:000CD3* + ID_OUI_FROM_DATABASE=Prettl Elektronik Radeberg GmbH -OUI:00117D* - ID_OUI_FROM_DATABASE=ZMD America, Inc. +OUI:000CDA* + ID_OUI_FROM_DATABASE=FreeHand Systems, Inc. -OUI:001178* - ID_OUI_FROM_DATABASE=Chiron Technology Ltd +OUI:000CDF* + ID_OUI_FROM_DATABASE=PULNiX America, Inc -OUI:001177* - ID_OUI_FROM_DATABASE=Coaxial Networks, Inc. +OUI:000CC7* + ID_OUI_FROM_DATABASE=Intelligent Computer Solutions Inc. -OUI:001223* - ID_OUI_FROM_DATABASE=Pixim +OUI:000CCC* + ID_OUI_FROM_DATABASE=Aeroscout Ltd. -OUI:001228* - ID_OUI_FROM_DATABASE=Data Ltd. +OUI:000C13* + ID_OUI_FROM_DATABASE=MediaQ -OUI:001210* - ID_OUI_FROM_DATABASE=WideRay Corp +OUI:000C05* + ID_OUI_FROM_DATABASE=RPA Reserch Co., Ltd. -OUI:001215* - ID_OUI_FROM_DATABASE=iStor Networks, Inc. +OUI:000C0C* + ID_OUI_FROM_DATABASE=APPRO TECHNOLOGY INC. -OUI:001216* - ID_OUI_FROM_DATABASE=ICP Internet Communication Payment AG +OUI:000BF4* + ID_OUI_FROM_DATABASE=Private -OUI:001209* - ID_OUI_FROM_DATABASE=Fastrax Ltd +OUI:000BF9* + ID_OUI_FROM_DATABASE=Gemstone Communications, Inc. -OUI:001204* - ID_OUI_FROM_DATABASE=u10 Networks, Inc. +OUI:000C00* + ID_OUI_FROM_DATABASE=BEB Industrie-Elektronik AG -OUI:0011FD* - ID_OUI_FROM_DATABASE=KORG INC. +OUI:000BF3* + ID_OUI_FROM_DATABASE=BAE SYSTEMS -OUI:001203* - ID_OUI_FROM_DATABASE=ActivNetworks +OUI:000C63* + ID_OUI_FROM_DATABASE=Zenith Electronics Corporation -OUI:0011F3* - ID_OUI_FROM_DATABASE=NeoMedia Europe AG +OUI:000C68* + ID_OUI_FROM_DATABASE=SigmaTel, Inc. -OUI:0011E7* - ID_OUI_FROM_DATABASE=WORLDSAT - Texas de France +OUI:000C6F* + ID_OUI_FROM_DATABASE=Amtek system co.,LTD. -OUI:0011EC* - ID_OUI_FROM_DATABASE=AVIX INC. +OUI:000C50* + ID_OUI_FROM_DATABASE=Seagate Technology -OUI:0011E0* - ID_OUI_FROM_DATABASE=U-MEDIA Communications, Inc. +OUI:000C55* + ID_OUI_FROM_DATABASE=Microlink Communications Inc. -OUI:0011DA* - ID_OUI_FROM_DATABASE=Vivaas Technology Inc. +OUI:000C5C* + ID_OUI_FROM_DATABASE=GTN Systems B.V. -OUI:0011D4* - ID_OUI_FROM_DATABASE=NetEnrich, Inc +OUI:000C61* + ID_OUI_FROM_DATABASE=AC Tech corporation DBA Advanced Digital -OUI:0011D9* - ID_OUI_FROM_DATABASE=TiVo +OUI:000CBA* + ID_OUI_FROM_DATABASE=Jamex, Inc. -OUI:00111C* - ID_OUI_FROM_DATABASE=Pleora Technologies Inc. +OUI:000CB9* + ID_OUI_FROM_DATABASE=LEA -OUI:00110F* - ID_OUI_FROM_DATABASE=netplat,Inc. +OUI:000CC0* + ID_OUI_FROM_DATABASE=Genera Oy -OUI:001116* - ID_OUI_FROM_DATABASE=COTEAU VERT CO., LTD. +OUI:000CB4* + ID_OUI_FROM_DATABASE=AutoCell Laboratories, Inc. -OUI:001109* - ID_OUI_FROM_DATABASE=Micro-Star International +OUI:000C34* + ID_OUI_FROM_DATABASE=Vixen Co., Ltd. -OUI:001103* - ID_OUI_FROM_DATABASE=kawamura electric inc. +OUI:000CA2* + ID_OUI_FROM_DATABASE=Harmonic Video Network -OUI:000FFD* - ID_OUI_FROM_DATABASE=Glorytek Network Inc. +OUI:000CA7* + ID_OUI_FROM_DATABASE=Metro (Suzhou) Technologies Co., Ltd. -OUI:000FEE* - ID_OUI_FROM_DATABASE=XTec, Incorporated +OUI:000CA9* + ID_OUI_FROM_DATABASE=Ebtron Inc. -OUI:000FF4* - ID_OUI_FROM_DATABASE=Guntermann & Drunck GmbH +OUI:000CAE* + ID_OUI_FROM_DATABASE=Ailocom Oy -OUI:001275* - ID_OUI_FROM_DATABASE=Sentilla Corporation +OUI:000C42* + ID_OUI_FROM_DATABASE=Routerboard.com -OUI:00126E* - ID_OUI_FROM_DATABASE=Seidel Elektronik GmbH Nfg.KG +OUI:000C44* + ID_OUI_FROM_DATABASE=Automated Interfaces, Inc. -OUI:001269* - ID_OUI_FROM_DATABASE=Value Electronics +OUI:000C39* + ID_OUI_FROM_DATABASE=Sentinel Wireless Inc. -OUI:00125C* - ID_OUI_FROM_DATABASE=Green Hills Software, Inc. +OUI:000C3B* + ID_OUI_FROM_DATABASE=Orion Electric Co., Ltd. -OUI:000F15* - ID_OUI_FROM_DATABASE=Kjaerulff1 A/S +OUI:000C40* + ID_OUI_FROM_DATABASE=Altech Controls -OUI:000F1A* - ID_OUI_FROM_DATABASE=Gaming Support B.V. +OUI:000C3A* + ID_OUI_FROM_DATABASE=Oxance -OUI:000F0E* - ID_OUI_FROM_DATABASE=WaveSplitter Technologies, Inc. +OUI:000C2F* + ID_OUI_FROM_DATABASE=SeorimTechnology Co.,Ltd. -OUI:000F08* - ID_OUI_FROM_DATABASE=Indagon Oy +OUI:000C31* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000F07* - ID_OUI_FROM_DATABASE=Mangrove Systems, Inc. +OUI:000C2A* + ID_OUI_FROM_DATABASE=OCTTEL Communication Co., Ltd. -OUI:000F02* - ID_OUI_FROM_DATABASE=Digicube Technology Co., Ltd +OUI:000C27* + ID_OUI_FROM_DATABASE=Sammy Corporation -OUI:000EFB* - ID_OUI_FROM_DATABASE=Macey Enterprises +OUI:000C18* + ID_OUI_FROM_DATABASE=Zenisu Keisoku Inc. -OUI:000EF5* - ID_OUI_FROM_DATABASE=iPAC Technology Co., Ltd. +OUI:000C20* + ID_OUI_FROM_DATABASE=Fi WIn, Inc. -OUI:000EF6* - ID_OUI_FROM_DATABASE=E-TEN Information Systems Co., Ltd. +OUI:000BED* + ID_OUI_FROM_DATABASE=ELM Inc. -OUI:000E8A* - ID_OUI_FROM_DATABASE=Avara Technologies Pty. Ltd. +OUI:000BF2* + ID_OUI_FROM_DATABASE=Chih-Kan Technology Co., Ltd. -OUI:000E83* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000BE1* + ID_OUI_FROM_DATABASE=Nokia NET Product Operations -OUI:000E73* - ID_OUI_FROM_DATABASE=Tpack A/S +OUI:000BE6* + ID_OUI_FROM_DATABASE=Datel Electronics -OUI:000E7D* - ID_OUI_FROM_DATABASE=Electronics Line 3000 Ltd. +OUI:000BDA* + ID_OUI_FROM_DATABASE=EyeCross Co.,Inc. -OUI:000E77* - ID_OUI_FROM_DATABASE=Decru, Inc. +OUI:000BD1* + ID_OUI_FROM_DATABASE=Aeronix, Inc. -OUI:000E7E* - ID_OUI_FROM_DATABASE=ionSign Oy +OUI:000BC5* + ID_OUI_FROM_DATABASE=SMC Networks, Inc. -OUI:000E6F* - ID_OUI_FROM_DATABASE=IRIS Corporation Berhad +OUI:000BCC* + ID_OUI_FROM_DATABASE=JUSAN, S.A. -OUI:000E6A* - ID_OUI_FROM_DATABASE=3Com Ltd +OUI:000BB9* + ID_OUI_FROM_DATABASE=Imsys AB -OUI:000E69* - ID_OUI_FROM_DATABASE=China Electric Power Research Institute +OUI:000BBE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000E63* - ID_OUI_FROM_DATABASE=Lemke Diagnostics GmbH +OUI:000BB2* + ID_OUI_FROM_DATABASE=SMALLBIG TECHNOLOGY -OUI:000EBC* - ID_OUI_FROM_DATABASE=Paragon Fidelity GmbH +OUI:000BB7* + ID_OUI_FROM_DATABASE=Micro Systems Co.,Ltd. -OUI:000EB0* - ID_OUI_FROM_DATABASE=Solutions Radio BV +OUI:000C96* + ID_OUI_FROM_DATABASE=OQO, Inc. -OUI:000EB5* - ID_OUI_FROM_DATABASE=Ecastle Electronics Co., Ltd. +OUI:000C9B* + ID_OUI_FROM_DATABASE=EE Solutions, Inc -OUI:000EAF* - ID_OUI_FROM_DATABASE=CASTEL +OUI:000C8A* + ID_OUI_FROM_DATABASE=Bose Corporation -OUI:000EA9* - ID_OUI_FROM_DATABASE=Shanghai Xun Shi Communications Equipment Ltd. Co. +OUI:000C8F* + ID_OUI_FROM_DATABASE=Nergal s.r.l. -OUI:000E9D* - ID_OUI_FROM_DATABASE=Tiscali UK Ltd +OUI:000C83* + ID_OUI_FROM_DATABASE=Logical Solutions -OUI:000EA2* - ID_OUI_FROM_DATABASE=McAfee, Inc +OUI:000C88* + ID_OUI_FROM_DATABASE=Apache Micro Peripherals, Inc. -OUI:000E90* - ID_OUI_FROM_DATABASE=PONICO CORP. +OUI:000C74* + ID_OUI_FROM_DATABASE=RIVERTEC CORPORATION -OUI:000E8F* - ID_OUI_FROM_DATABASE=Sercomm Corp. +OUI:000C76* + ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. -OUI:000E96* - ID_OUI_FROM_DATABASE=Cubic Defense Applications, Inc. +OUI:000C7B* + ID_OUI_FROM_DATABASE=ALPHA PROJECT Co.,Ltd. -OUI:000F4E* - ID_OUI_FROM_DATABASE=Cellink +OUI:000B85* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000F41* - ID_OUI_FROM_DATABASE=Zipher Ltd +OUI:000B7F* + ID_OUI_FROM_DATABASE=Align Engineering LLC -OUI:000F48* - ID_OUI_FROM_DATABASE=Polypix Inc. +OUI:000B84* + ID_OUI_FROM_DATABASE=BODET -OUI:000F4D* - ID_OUI_FROM_DATABASE=TalkSwitch +OUI:000B73* + ID_OUI_FROM_DATABASE=Kodeos Communications -OUI:000F39* - ID_OUI_FROM_DATABASE=IRIS SENSORS +OUI:000B78* + ID_OUI_FROM_DATABASE=TAIFATECH INC. -OUI:000F3C* - ID_OUI_FROM_DATABASE=Endeleo Limited +OUI:000B6C* + ID_OUI_FROM_DATABASE=Sychip Inc. -OUI:000F34* +OUI:000B60* ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000F2D* - ID_OUI_FROM_DATABASE=CHUNG-HSIN ELECTRIC & MACHINERY MFG.CORP. +OUI:000B65* + ID_OUI_FROM_DATABASE=Sy.A.C. srl -OUI:000F27* - ID_OUI_FROM_DATABASE=TEAL Electronics, Inc. +OUI:000B57* + ID_OUI_FROM_DATABASE=Silicon Laboratories -OUI:000F28* - ID_OUI_FROM_DATABASE=Itronix Corporation +OUI:000B5C* + ID_OUI_FROM_DATABASE=Newtech Co.,Ltd -OUI:000F21* - ID_OUI_FROM_DATABASE=Scientific Atlanta, Inc +OUI:000B43* + ID_OUI_FROM_DATABASE=Microscan Systems, Inc. -OUI:000EEF* - ID_OUI_FROM_DATABASE=Private +OUI:000B48* + ID_OUI_FROM_DATABASE=sofrel -OUI:000EDC* - ID_OUI_FROM_DATABASE=Tellion INC. +OUI:000B4A* + ID_OUI_FROM_DATABASE=Visimetrics (UK) Ltd -OUI:000EE3* - ID_OUI_FROM_DATABASE=Chiyu Technology Co.,Ltd +OUI:000B35* + ID_OUI_FROM_DATABASE=Quad Bit System co., Ltd. -OUI:000EC8* - ID_OUI_FROM_DATABASE=Zoran Corporation +OUI:000B37* + ID_OUI_FROM_DATABASE=MANUFACTURE DES MONTRES ROLEX SA -OUI:000ECF* - ID_OUI_FROM_DATABASE=PROFIBUS Nutzerorganisation e.V. +OUI:000B3C* + ID_OUI_FROM_DATABASE=Cygnal Integrated Products, Inc. -OUI:000ED4* - ID_OUI_FROM_DATABASE=CRESITT INDUSTRIE +OUI:000B29* + ID_OUI_FROM_DATABASE=LS(LG) Industrial Systems co.,Ltd -OUI:000EC2* - ID_OUI_FROM_DATABASE=Lowrance Electronics, Inc. +OUI:000B30* + ID_OUI_FROM_DATABASE=Beijing Gongye Science & Technology Co.,Ltd -OUI:000EC1* - ID_OUI_FROM_DATABASE=MYNAH Technologies +OUI:000BA8* + ID_OUI_FROM_DATABASE=HANBACK ELECTRONICS CO., LTD. -OUI:000F92* - ID_OUI_FROM_DATABASE=Microhard Systems Inc. +OUI:000B92* + ID_OUI_FROM_DATABASE=Ascom Danmark A/S -OUI:000F99* - ID_OUI_FROM_DATABASE=APAC opto Electronics Inc. +OUI:000B97* + ID_OUI_FROM_DATABASE=Matsushita Electric Industrial Co.,Ltd. -OUI:000F8D* - ID_OUI_FROM_DATABASE=FAST TV-Server AG +OUI:000B9C* + ID_OUI_FROM_DATABASE=TriBeam Technologies, Inc. -OUI:000F80* - ID_OUI_FROM_DATABASE=Trinity Security Systems,Inc. +OUI:000B8B* + ID_OUI_FROM_DATABASE=KERAJET, S.A. -OUI:000F7F* - ID_OUI_FROM_DATABASE=UBSTORAGE Co.,Ltd. +OUI:0009D6* + ID_OUI_FROM_DATABASE=KNC One GmbH -OUI:000FC2* - ID_OUI_FROM_DATABASE=Uniwell Corporation +OUI:0009D5* + ID_OUI_FROM_DATABASE=Signal Communication, Inc. -OUI:000FC9* - ID_OUI_FROM_DATABASE=Allnet GmbH +OUI:0009DC* + ID_OUI_FROM_DATABASE=Galaxis Technology AG -OUI:000FBC* - ID_OUI_FROM_DATABASE=Onkey Technologies, Inc. +OUI:0009C9* + ID_OUI_FROM_DATABASE=BlueWINC Co., Ltd. -OUI:000FBB* - ID_OUI_FROM_DATABASE=Nokia Siemens Networks GmbH & Co. KG. +OUI:0009D0* + ID_OUI_FROM_DATABASE=Solacom Technologies Inc. -OUI:000FB6* - ID_OUI_FROM_DATABASE=Europlex Technologies +OUI:0009BC* + ID_OUI_FROM_DATABASE=Digital Safety Technologies, Inc -OUI:000FA9* - ID_OUI_FROM_DATABASE=PC Fabrik +OUI:0009C1* + ID_OUI_FROM_DATABASE=PROCES-DATA A/S -OUI:000FAA* - ID_OUI_FROM_DATABASE=Nexus Technologies +OUI:0009C4* + ID_OUI_FROM_DATABASE=Medicore Co., Ltd -OUI:000FAF* - ID_OUI_FROM_DATABASE=Dialog Inc. +OUI:00098F* + ID_OUI_FROM_DATABASE=Cetacean Networks -OUI:000FE8* - ID_OUI_FROM_DATABASE=Lobos, Inc. +OUI:00097D* + ID_OUI_FROM_DATABASE=SecWell Networks Oy -OUI:000FED* - ID_OUI_FROM_DATABASE=Anam Electronics Co., Ltd +OUI:00097E* + ID_OUI_FROM_DATABASE=IMI TECHNOLOGY CO., LTD -OUI:000FDC* - ID_OUI_FROM_DATABASE=Ueda Japan Radio Co., Ltd. +OUI:000983* + ID_OUI_FROM_DATABASE=GlobalTop Technology, Inc. -OUI:000FE1* - ID_OUI_FROM_DATABASE=ID DIGITAL CORPORATION +OUI:000970* + ID_OUI_FROM_DATABASE=Vibration Research Corporation -OUI:000FD5* - ID_OUI_FROM_DATABASE=Schwechat - RISE +OUI:000977* + ID_OUI_FROM_DATABASE=Brunner Elektronik AG -OUI:000FCE* - ID_OUI_FROM_DATABASE=Kikusui Electronics Corp. +OUI:000964* + ID_OUI_FROM_DATABASE=Hi-Techniques, Inc. -OUI:000F73* - ID_OUI_FROM_DATABASE=RS Automation Co., Ltd +OUI:00096B* + ID_OUI_FROM_DATABASE=IBM Corp -OUI:000F7A* - ID_OUI_FROM_DATABASE=BeiJing NuQX Technology CO.,LTD +OUI:000957* + ID_OUI_FROM_DATABASE=Supercaller, Inc. -OUI:000F6D* - ID_OUI_FROM_DATABASE=Midas Engineering +OUI:00095C* + ID_OUI_FROM_DATABASE=Philips Medical Systems - Cardiac and Monitoring Systems (CM -OUI:000F67* - ID_OUI_FROM_DATABASE=West Instruments +OUI:000AE3* + ID_OUI_FROM_DATABASE=YANG MEI TECHNOLOGY CO., LTD -OUI:000F6E* - ID_OUI_FROM_DATABASE=BBox +OUI:000AEA* + ID_OUI_FROM_DATABASE=ADAM ELEKTRONIK LTD. ŞTI -OUI:000F60* - ID_OUI_FROM_DATABASE=Lifetron Co.,Ltd +OUI:000ADE* + ID_OUI_FROM_DATABASE=Happy Communication Co., Ltd. -OUI:000F5B* - ID_OUI_FROM_DATABASE=Delta Information Systems, Inc. +OUI:000AD7* + ID_OUI_FROM_DATABASE=Origin ELECTRIC CO.,LTD. -OUI:000F54* - ID_OUI_FROM_DATABASE=Entrelogic Corporation +OUI:000ACB* + ID_OUI_FROM_DATABASE=XPAK MSA Group -OUI:000D75* - ID_OUI_FROM_DATABASE=Kobian Pte Ltd - Taiwan Branch +OUI:000AD0* + ID_OUI_FROM_DATABASE=Niigata Develoment Center, F.I.T. Co., Ltd. -OUI:000D7C* - ID_OUI_FROM_DATABASE=Codian Ltd +OUI:000AD2* + ID_OUI_FROM_DATABASE=JEPICO Corporation -OUI:000D6F* - ID_OUI_FROM_DATABASE=Ember Corporation +OUI:000ABD* + ID_OUI_FROM_DATABASE=Rupprecht & Patashnick Co. -OUI:000D69* - ID_OUI_FROM_DATABASE=TMT&D Corporation +OUI:000ABF* + ID_OUI_FROM_DATABASE=HIROTA SS -OUI:000D70* - ID_OUI_FROM_DATABASE=Datamax Corporation +OUI:000AC4* + ID_OUI_FROM_DATABASE=Daewoo Teletech Co., Ltd -OUI:000D5D* - ID_OUI_FROM_DATABASE=Raritan Computer, Inc +OUI:000AAC* + ID_OUI_FROM_DATABASE=TerraTec Electronic GmbH -OUI:000D62* - ID_OUI_FROM_DATABASE=Funkwerk Dabendorf GmbH +OUI:000AB1* + ID_OUI_FROM_DATABASE=GENETEC Corporation -OUI:000D50* - ID_OUI_FROM_DATABASE=Galazar Networks +OUI:000AB8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000D4A* - ID_OUI_FROM_DATABASE=Steag ETA-Optik +OUI:000AA5* + ID_OUI_FROM_DATABASE=MAXLINK INDUSTRIES LIMITED -OUI:000DAB* - ID_OUI_FROM_DATABASE=Parker Hannifin GmbH Electromechanical Division Europe +OUI:000A8D* + ID_OUI_FROM_DATABASE=EUROTHERM LIMITED -OUI:000DA7* - ID_OUI_FROM_DATABASE=Private +OUI:000A9E* + ID_OUI_FROM_DATABASE=BroadWeb Corportation -OUI:000DA1* - ID_OUI_FROM_DATABASE=MIRAE ITS Co.,LTD. +OUI:000AA0* + ID_OUI_FROM_DATABASE=Cedar Point Communications -OUI:000DA2* - ID_OUI_FROM_DATABASE=Infrant Technologies, Inc. +OUI:000A98* + ID_OUI_FROM_DATABASE=M+F Gwinner GmbH & Co -OUI:000D9B* - ID_OUI_FROM_DATABASE=Heraeus Electro-Nite International N.V. +OUI:000A92* + ID_OUI_FROM_DATABASE=Presonus Corporation -OUI:000D8F* - ID_OUI_FROM_DATABASE=King Tsushin Kogyo Co., LTD. +OUI:000A7E* + ID_OUI_FROM_DATABASE=The Advantage Group -OUI:000D94* - ID_OUI_FROM_DATABASE=AFAR Communications,Inc +OUI:000A85* + ID_OUI_FROM_DATABASE=PLAT'C2,Inc -OUI:000D82* - ID_OUI_FROM_DATABASE=PHS srl +OUI:000A8A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000D81* - ID_OUI_FROM_DATABASE=Pepperl+Fuchs GmbH +OUI:0009B5* + ID_OUI_FROM_DATABASE=3J Tech. Co., Ltd. -OUI:000DCE* - ID_OUI_FROM_DATABASE=Dynavac Technology Pte Ltd +OUI:0009AF* + ID_OUI_FROM_DATABASE=e-generis -OUI:000DC8* - ID_OUI_FROM_DATABASE=AirMagnet, Inc +OUI:0009B0* + ID_OUI_FROM_DATABASE=Onkyo Corporation -OUI:000DC2* - ID_OUI_FROM_DATABASE=Private +OUI:0009A9* + ID_OUI_FROM_DATABASE=Ikanos Communications -OUI:000DC7* - ID_OUI_FROM_DATABASE=COSMIC ENGINEERING INC. +OUI:00099D* + ID_OUI_FROM_DATABASE=Haliplex Communications -OUI:000DBB* - ID_OUI_FROM_DATABASE=Nippon Dentsu Co.,Ltd. +OUI:0009A2* + ID_OUI_FROM_DATABASE=Interface Co., Ltd. -OUI:000DB5* - ID_OUI_FROM_DATABASE=GLOBALSAT TECHNOLOGY CORPORATION +OUI:000990* + ID_OUI_FROM_DATABASE=ACKSYS Communications & systems -OUI:000DAF* - ID_OUI_FROM_DATABASE=Plexus Corp (UK) Ltd +OUI:000996* + ID_OUI_FROM_DATABASE=RDI -OUI:000D29* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00098A* + ID_OUI_FROM_DATABASE=EqualLogic Inc -OUI:000D23* - ID_OUI_FROM_DATABASE=Smart Solution, Inc +OUI:000A77* + ID_OUI_FROM_DATABASE=Bluewire Technologies LLC -OUI:000D17* - ID_OUI_FROM_DATABASE=Turbo Networks Co.Ltd +OUI:000A79* + ID_OUI_FROM_DATABASE=corega K.K -OUI:000D1C* - ID_OUI_FROM_DATABASE=Amesys Defense +OUI:000A72* + ID_OUI_FROM_DATABASE=STEC, INC. -OUI:000D0A* - ID_OUI_FROM_DATABASE=Projectiondesign as +OUI:000A5F* + ID_OUI_FROM_DATABASE=almedio inc. -OUI:000D09* - ID_OUI_FROM_DATABASE=Yuehua(Zhuhai) Electronic CO. LTD +OUI:000A66* + ID_OUI_FROM_DATABASE=MITSUBISHI ELECTRIC SYSTEM & SERVICE CO.,LTD. -OUI:000D10* - ID_OUI_FROM_DATABASE=Embedtronics Oy +OUI:000A6B* + ID_OUI_FROM_DATABASE=Tadiran Telecom Business Systems LTD -OUI:000D04* - ID_OUI_FROM_DATABASE=Foxboro Eckardt Development GmbH +OUI:000A5A* + ID_OUI_FROM_DATABASE=GreenNET Technologies Co.,Ltd. -OUI:000CFD* - ID_OUI_FROM_DATABASE=Hyundai ImageQuest Co.,Ltd. +OUI:000A53* + ID_OUI_FROM_DATABASE=Intronics, Incorporated -OUI:000D4F* - ID_OUI_FROM_DATABASE=Kenwood Corporation +OUI:000A58* + ID_OUI_FROM_DATABASE=Freyer & Siegel Elektronik GmbH & Co. KG -OUI:000D46* - ID_OUI_FROM_DATABASE=Parker SSD Drives +OUI:000A4C* + ID_OUI_FROM_DATABASE=Molecular Devices Corporation -OUI:000D42* - ID_OUI_FROM_DATABASE=Newbest Development Limited +OUI:000B24* + ID_OUI_FROM_DATABASE=AirLogic -OUI:000D3C* - ID_OUI_FROM_DATABASE=i.Tech Dynamic Ltd +OUI:000B1D* + ID_OUI_FROM_DATABASE=LayerZero Power Systems, Inc. -OUI:000D36* - ID_OUI_FROM_DATABASE=Wu Han Routon Electronic Co., Ltd +OUI:000B16* + ID_OUI_FROM_DATABASE=Communication Machinery Corporation -OUI:000D3B* - ID_OUI_FROM_DATABASE=Microelectronics Technology Inc. +OUI:000B18* + ID_OUI_FROM_DATABASE=Private -OUI:000D2A* - ID_OUI_FROM_DATABASE=Scanmatic AS +OUI:000B11* + ID_OUI_FROM_DATABASE=HIMEJI ABC TRADING CO.,LTD. -OUI:000D2F* - ID_OUI_FROM_DATABASE=AIN Comm.Tech.Co., LTD +OUI:000B0A* + ID_OUI_FROM_DATABASE=dBm Optics -OUI:000DFA* - ID_OUI_FROM_DATABASE=Micro Control Systems Ltd. +OUI:000B05* + ID_OUI_FROM_DATABASE=Pacific Broadband Networks -OUI:000DF4* - ID_OUI_FROM_DATABASE=Watertek Co. +OUI:000AFE* + ID_OUI_FROM_DATABASE=NovaPal Ltd -OUI:000DF9* - ID_OUI_FROM_DATABASE=NDS Limited +OUI:000B03* + ID_OUI_FROM_DATABASE=Taekwang Industrial Co., Ltd -OUI:000E00* - ID_OUI_FROM_DATABASE=Atrie +OUI:000AEF* + ID_OUI_FROM_DATABASE=OTRUM ASA -OUI:000DE7* - ID_OUI_FROM_DATABASE=Snap-on OEM Group +OUI:000AF2* + ID_OUI_FROM_DATABASE=NeoAxiom Corp. -OUI:000DE8* - ID_OUI_FROM_DATABASE=Nasaco Electronics Pte. Ltd +OUI:000A05* + ID_OUI_FROM_DATABASE=Widax Corp. -OUI:000DED* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000A0A* + ID_OUI_FROM_DATABASE=SUNIX Co., Ltd. -OUI:000DE1* - ID_OUI_FROM_DATABASE=Control Products, Inc. +OUI:000A0F* + ID_OUI_FROM_DATABASE=Ilryung Telesys, Inc -OUI:000DD5* - ID_OUI_FROM_DATABASE=O'RITE TECHNOLOGY CO.,LTD +OUI:0009FF* + ID_OUI_FROM_DATABASE=X.net 2000 GmbH -OUI:000DDA* - ID_OUI_FROM_DATABASE=ALLIED TELESIS K.K. +OUI:0009FE* + ID_OUI_FROM_DATABASE=Daisy Technologies, Inc. -OUI:000E20* - ID_OUI_FROM_DATABASE=ACCESS Systems Americas, Inc. +OUI:000A00* + ID_OUI_FROM_DATABASE=Mediatek Corp. -OUI:000E27* - ID_OUI_FROM_DATABASE=Crere Networks, Inc. +OUI:0009F6* + ID_OUI_FROM_DATABASE=Shenzhen Eastern Digital Tech Ltd. -OUI:000E14* - ID_OUI_FROM_DATABASE=Visionary Solutions, Inc. +OUI:0009F5* + ID_OUI_FROM_DATABASE=Emerson Network Power Co.,Ltd -OUI:000E1B* - ID_OUI_FROM_DATABASE=IAV GmbH +OUI:0009E8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000E57* - ID_OUI_FROM_DATABASE=Iworld Networking, Inc. +OUI:0009EF* + ID_OUI_FROM_DATABASE=Vocera Communications -OUI:000E50* - ID_OUI_FROM_DATABASE=Thomson Telecom Belgium +OUI:0009E3* + ID_OUI_FROM_DATABASE=Angel Iglesias S.A. -OUI:000E4A* - ID_OUI_FROM_DATABASE=Changchun Huayu WEBPAD Co.,LTD +OUI:000A39* + ID_OUI_FROM_DATABASE=LoPA Information Technology -OUI:000E49* - ID_OUI_FROM_DATABASE=Forsway Scandinavia AB +OUI:000A40* + ID_OUI_FROM_DATABASE=Crown Audio -- Harmanm International -OUI:000E3D* - ID_OUI_FROM_DATABASE=Televic N.V. +OUI:000A45* + ID_OUI_FROM_DATABASE=Audio-Technica Corp. -OUI:000E44* - ID_OUI_FROM_DATABASE=Digital 5, Inc. +OUI:000A47* + ID_OUI_FROM_DATABASE=Allied Vision Technologies -OUI:000E33* - ID_OUI_FROM_DATABASE=Shuko Electronics Co.,Ltd +OUI:000A34* + ID_OUI_FROM_DATABASE=Identicard Systems Incorporated -OUI:000E3A* - ID_OUI_FROM_DATABASE=Cirrus Logic +OUI:000A2D* + ID_OUI_FROM_DATABASE=Cabot Communications Limited -OUI:000E2D* - ID_OUI_FROM_DATABASE=Hyundai Digital Technology Co.,Ltd. +OUI:000A22* + ID_OUI_FROM_DATABASE=Amperion Inc -OUI:000CEA* - ID_OUI_FROM_DATABASE=aphona Kommunikationssysteme +OUI:000A16* + ID_OUI_FROM_DATABASE=Lassen Research -OUI:000CD9* - ID_OUI_FROM_DATABASE=Itcare Co., Ltd +OUI:000A1B* + ID_OUI_FROM_DATABASE=Stream Labs -OUI:000CD3* - ID_OUI_FROM_DATABASE=Prettl Elektronik Radeberg GmbH +OUI:000878* + ID_OUI_FROM_DATABASE=Benchmark Storage Innovations -OUI:000CDA* - ID_OUI_FROM_DATABASE=FreeHand Systems, Inc. +OUI:000872* + ID_OUI_FROM_DATABASE=Sorenson Communications -OUI:000CDF* - ID_OUI_FROM_DATABASE=PULNiX America, Inc +OUI:00087E* + ID_OUI_FROM_DATABASE=Bon Electro-Telecom Inc. -OUI:000CC7* - ID_OUI_FROM_DATABASE=Intelligent Computer Solutions Inc. +OUI:00086B* + ID_OUI_FROM_DATABASE=MIPSYS -OUI:000CCC* - ID_OUI_FROM_DATABASE=Aeroscout Ltd. +OUI:000865* + ID_OUI_FROM_DATABASE=JASCOM CO., LTD -OUI:000C13* - ID_OUI_FROM_DATABASE=MediaQ +OUI:000866* + ID_OUI_FROM_DATABASE=DSX Access Systems, Inc. -OUI:000C05* - ID_OUI_FROM_DATABASE=RPA Reserch Co., Ltd. +OUI:00085F* + ID_OUI_FROM_DATABASE=Picanol N.V. -OUI:000C0C* - ID_OUI_FROM_DATABASE=APPRO TECHNOLOGY INC. +OUI:000859* + ID_OUI_FROM_DATABASE=ShenZhen Unitone Electronics Co., Ltd. -OUI:000BF4* - ID_OUI_FROM_DATABASE=Private +OUI:000853* + ID_OUI_FROM_DATABASE=Schleicher GmbH & Co. Relaiswerke KG + +OUI:000858* + ID_OUI_FROM_DATABASE=Novatechnology Inc. + +OUI:00081D* + ID_OUI_FROM_DATABASE=Ipsil, Incorporated -OUI:000BF9* - ID_OUI_FROM_DATABASE=Gemstone Communications, Inc. +OUI:000829* + ID_OUI_FROM_DATABASE=Aval Nagasaki Corporation -OUI:000C00* - ID_OUI_FROM_DATABASE=BEB Industrie-Elektronik AG +OUI:000823* + ID_OUI_FROM_DATABASE=Texa Corp. -OUI:000BF3* - ID_OUI_FROM_DATABASE=BAE SYSTEMS +OUI:00082A* + ID_OUI_FROM_DATABASE=Powerwallz Network Security -OUI:000C63* - ID_OUI_FROM_DATABASE=Zenith Electronics Corporation +OUI:000817* + ID_OUI_FROM_DATABASE=EmergeCore Networks LLC -OUI:000C68* - ID_OUI_FROM_DATABASE=SigmaTel, Inc. +OUI:00091E* + ID_OUI_FROM_DATABASE=Firstech Technology Corp. -OUI:000C6F* - ID_OUI_FROM_DATABASE=Amtek system co.,LTD. +OUI:000925* + ID_OUI_FROM_DATABASE=VSN Systemen BV -OUI:000C50* - ID_OUI_FROM_DATABASE=Seagate Technology +OUI:000918* + ID_OUI_FROM_DATABASE=SAMSUNG TECHWIN CO.,LTD -OUI:000C55* - ID_OUI_FROM_DATABASE=Microlink Communications Inc. +OUI:000917* + ID_OUI_FROM_DATABASE=WEM Technology Inc -OUI:000C5C* - ID_OUI_FROM_DATABASE=GTN Systems B.V. +OUI:000912* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000C61* - ID_OUI_FROM_DATABASE=AC Tech corporation DBA Advanced Digital +OUI:00090B* + ID_OUI_FROM_DATABASE=MTL Instruments PLC -OUI:000CBA* - ID_OUI_FROM_DATABASE=Jamex, Inc. +OUI:000905* + ID_OUI_FROM_DATABASE=iTEC Technologies Ltd. -OUI:000CB9* - ID_OUI_FROM_DATABASE=LEA +OUI:0008FF* + ID_OUI_FROM_DATABASE=Trilogy Communications Ltd -OUI:000CC0* - ID_OUI_FROM_DATABASE=Genera Oy +OUI:000906* + ID_OUI_FROM_DATABASE=Esteem Networks -OUI:000CB4* - ID_OUI_FROM_DATABASE=AutoCell Laboratories, Inc. +OUI:0008FB* + ID_OUI_FROM_DATABASE=SonoSite, Inc. -OUI:000C34* - ID_OUI_FROM_DATABASE=Vixen Co., Ltd. +OUI:0008F2* + ID_OUI_FROM_DATABASE=C&S Technology -OUI:000CA2* - ID_OUI_FROM_DATABASE=Harmonic Video Network +OUI:0008F7* + ID_OUI_FROM_DATABASE=Hitachi Ltd, Semiconductor & Integrated Circuits Gr -OUI:000CA7* - ID_OUI_FROM_DATABASE=Metro (Suzhou) Technologies Co., Ltd. +OUI:0008ED* + ID_OUI_FROM_DATABASE=ST&T Instrument Corp. -OUI:000CA9* - ID_OUI_FROM_DATABASE=Ebtron Inc. +OUI:0007D1* + ID_OUI_FROM_DATABASE=Spectrum Signal Processing Inc. -OUI:000CAE* - ID_OUI_FROM_DATABASE=Ailocom Oy +OUI:0007CE* + ID_OUI_FROM_DATABASE=Cabletime Limited -OUI:000C42* - ID_OUI_FROM_DATABASE=Routerboard.com +OUI:0007C8* + ID_OUI_FROM_DATABASE=Brain21, Inc. -OUI:000C44* - ID_OUI_FROM_DATABASE=Automated Interfaces, Inc. +OUI:0007BC* + ID_OUI_FROM_DATABASE=Identix Inc. -OUI:000C39* - ID_OUI_FROM_DATABASE=Sentinel Wireless Inc. +OUI:00047C* + ID_OUI_FROM_DATABASE=Skidata AG -OUI:000C3B* - ID_OUI_FROM_DATABASE=Orion Electric Co., Ltd. +OUI:0007BB* + ID_OUI_FROM_DATABASE=Candera Inc. -OUI:000C40* - ID_OUI_FROM_DATABASE=Altech Controls +OUI:0007C2* + ID_OUI_FROM_DATABASE=Netsys Telecom -OUI:000C3A* - ID_OUI_FROM_DATABASE=Oxance +OUI:0007B5* + ID_OUI_FROM_DATABASE=Any One Wireless Ltd. -OUI:000C2F* - ID_OUI_FROM_DATABASE=SeorimTechnology Co.,Ltd. +OUI:0007AF* + ID_OUI_FROM_DATABASE=Red Lion Controls, LP -OUI:000C31* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0007A2* + ID_OUI_FROM_DATABASE=Opteon Corporation -OUI:000C2A* - ID_OUI_FROM_DATABASE=OCTTEL Communication Co., Ltd. +OUI:0007A7* + ID_OUI_FROM_DATABASE=A-Z Inc. -OUI:000C27* - ID_OUI_FROM_DATABASE=Sammy Corporation +OUI:0007A1* + ID_OUI_FROM_DATABASE=VIASYS Healthcare GmbH -OUI:000C18* - ID_OUI_FROM_DATABASE=Zenisu Keisoku Inc. +OUI:0007A8* + ID_OUI_FROM_DATABASE=Haier Group Technologies Ltd. -OUI:000C20* - ID_OUI_FROM_DATABASE=Fi WIn, Inc. +OUI:00094A* + ID_OUI_FROM_DATABASE=Homenet Communications -OUI:000BED* - ID_OUI_FROM_DATABASE=ELM Inc. +OUI:000949* + ID_OUI_FROM_DATABASE=Glyph Technologies Inc. -OUI:000BF2* - ID_OUI_FROM_DATABASE=Chih-Kan Technology Co., Ltd. +OUI:000950* + ID_OUI_FROM_DATABASE=Independent Storage Corporation -OUI:000BE1* - ID_OUI_FROM_DATABASE=Nokia NET Product Operations +OUI:000944* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000BE6* - ID_OUI_FROM_DATABASE=Datel Electronics +OUI:00093D* + ID_OUI_FROM_DATABASE=Newisys,Inc. -OUI:000BDA* - ID_OUI_FROM_DATABASE=EyeCross Co.,Inc. +OUI:000937* + ID_OUI_FROM_DATABASE=Inventec Appliance Corp -OUI:000BD1* - ID_OUI_FROM_DATABASE=Aeronix, Inc. +OUI:000931* + ID_OUI_FROM_DATABASE=Future Internet, Inc. -OUI:000BC5* - ID_OUI_FROM_DATABASE=SMC Networks, Inc. +OUI:000938* + ID_OUI_FROM_DATABASE=Allot Communications -OUI:000BCC* - ID_OUI_FROM_DATABASE=JUSAN, S.A. +OUI:00092A* + ID_OUI_FROM_DATABASE=MYTECS Co.,Ltd. -OUI:000BB9* - ID_OUI_FROM_DATABASE=Imsys AB +OUI:0008B1* + ID_OUI_FROM_DATABASE=ProQuent Systems -OUI:000BBE* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0008AB* + ID_OUI_FROM_DATABASE=EnerLinx.com, Inc. -OUI:000BB2* - ID_OUI_FROM_DATABASE=SMALLBIG TECHNOLOGY +OUI:0008AC* + ID_OUI_FROM_DATABASE=Eltromat GmbH -OUI:000BB7* - ID_OUI_FROM_DATABASE=Micro Systems Co.,Ltd. +OUI:0008A5* + ID_OUI_FROM_DATABASE=Peninsula Systems Inc. -OUI:000C96* - ID_OUI_FROM_DATABASE=OQO, Inc. +OUI:000899* + ID_OUI_FROM_DATABASE=Netbind, Inc. -OUI:000C9B* - ID_OUI_FROM_DATABASE=EE Solutions, Inc +OUI:00089E* + ID_OUI_FROM_DATABASE=Beijing Enter-Net co.LTD -OUI:000C8A* - ID_OUI_FROM_DATABASE=Bose Corporation +OUI:000895* + ID_OUI_FROM_DATABASE=DIRC Technologie GmbH & Co.KG -OUI:000C8F* - ID_OUI_FROM_DATABASE=Nergal s.r.l. +OUI:000891* + ID_OUI_FROM_DATABASE=Lyan Inc. -OUI:000C83* - ID_OUI_FROM_DATABASE=Logical Solutions +OUI:00088B* + ID_OUI_FROM_DATABASE=Tropic Networks Inc. -OUI:000C88* - ID_OUI_FROM_DATABASE=Apache Micro Peripherals, Inc. +OUI:00088A* + ID_OUI_FROM_DATABASE=Minds@Work -OUI:000C74* - ID_OUI_FROM_DATABASE=RIVERTEC CORPORATION +OUI:000885* + ID_OUI_FROM_DATABASE=EMS Dr. Thomas Wünsche -OUI:000C76* - ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. +OUI:0008E8* + ID_OUI_FROM_DATABASE=Excel Master Ltd. -OUI:000C7B* - ID_OUI_FROM_DATABASE=ALPHA PROJECT Co.,Ltd. +OUI:0008E7* + ID_OUI_FROM_DATABASE=SHI ControlSystems,Ltd. -OUI:000B85* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0008E1* + ID_OUI_FROM_DATABASE=Barix AG -OUI:000B7F* - ID_OUI_FROM_DATABASE=Align Engineering LLC +OUI:0008DA* + ID_OUI_FROM_DATABASE=SofaWare Technologies Ltd. -OUI:000B84* - ID_OUI_FROM_DATABASE=BODET +OUI:0008D5* + ID_OUI_FROM_DATABASE=Vanguard Networks Solutions, LLC -OUI:000B73* - ID_OUI_FROM_DATABASE=Kodeos Communications +OUI:0008CE* + ID_OUI_FROM_DATABASE=IPMobileNet Inc. -OUI:000B78* - ID_OUI_FROM_DATABASE=TAIFATECH INC. +OUI:0008C8* + ID_OUI_FROM_DATABASE=Soneticom, Inc. -OUI:000B6C* - ID_OUI_FROM_DATABASE=Sychip Inc. +OUI:0008C4* + ID_OUI_FROM_DATABASE=Hikari Co.,Ltd. -OUI:000B60* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0008BE* + ID_OUI_FROM_DATABASE=XENPAK MSA Group -OUI:000B65* - ID_OUI_FROM_DATABASE=Sy.A.C. srl +OUI:0008B8* + ID_OUI_FROM_DATABASE=E.F. Johnson -OUI:000B57* - ID_OUI_FROM_DATABASE=Silicon Laboratories +OUI:00079B* + ID_OUI_FROM_DATABASE=Aurora Networks -OUI:000B5C* - ID_OUI_FROM_DATABASE=Newtech Co.,Ltd +OUI:00078F* + ID_OUI_FROM_DATABASE=Emkay Innovative Products -OUI:000B4F* - ID_OUI_FROM_DATABASE=Verifone, INC. +OUI:000788* + ID_OUI_FROM_DATABASE=Clipcomm, Inc. -OUI:000B43* - ID_OUI_FROM_DATABASE=Microscan Systems, Inc. +OUI:000779* + ID_OUI_FROM_DATABASE=Sungil Telecom Co., Ltd. -OUI:000B48* - ID_OUI_FROM_DATABASE=sofrel +OUI:000778* + ID_OUI_FROM_DATABASE=GERSTEL GmbH & Co. KG -OUI:000B4A* - ID_OUI_FROM_DATABASE=Visimetrics (UK) Ltd +OUI:00076C* + ID_OUI_FROM_DATABASE=Daehanet, Inc. -OUI:000B35* - ID_OUI_FROM_DATABASE=Quad Bit System co., Ltd. +OUI:00075C* + ID_OUI_FROM_DATABASE=Eastman Kodak Company -OUI:000B37* - ID_OUI_FROM_DATABASE=MANUFACTURE DES MONTRES ROLEX SA +OUI:000768* + ID_OUI_FROM_DATABASE=Danfoss A/S -OUI:000B3C* - ID_OUI_FROM_DATABASE=Cygnal Integrated Products, Inc. +OUI:000762* + ID_OUI_FROM_DATABASE=Group Sense Limited -OUI:000B29* - ID_OUI_FROM_DATABASE=LS(LG) Industrial Systems co.,Ltd +OUI:000755* + ID_OUI_FROM_DATABASE=Lafon -OUI:000B30* - ID_OUI_FROM_DATABASE=Beijing Gongye Science & Technology Co.,Ltd +OUI:00074F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000BA1* - ID_OUI_FROM_DATABASE=SYSCOM Ltd. +OUI:000741* + ID_OUI_FROM_DATABASE=Sierra Automated Systems -OUI:000BA8* - ID_OUI_FROM_DATABASE=HANBACK ELECTRONICS CO., LTD. +OUI:000749* + ID_OUI_FROM_DATABASE=CENiX Inc. -OUI:000B92* - ID_OUI_FROM_DATABASE=Ascom Danmark A/S +OUI:000735* + ID_OUI_FROM_DATABASE=Flarion Technologies, Inc. -OUI:000B97* - ID_OUI_FROM_DATABASE=Matsushita Electric Industrial Co.,Ltd. +OUI:00073B* + ID_OUI_FROM_DATABASE=Tenovis GmbH & Co KG -OUI:000B9C* - ID_OUI_FROM_DATABASE=TriBeam Technologies, Inc. +OUI:000729* + ID_OUI_FROM_DATABASE=Kistler Instrumente AG -OUI:000B8B* - ID_OUI_FROM_DATABASE=KERAJET, S.A. +OUI:00072E* + ID_OUI_FROM_DATABASE=North Node AB -OUI:0009D6* - ID_OUI_FROM_DATABASE=KNC One GmbH +OUI:000728* + ID_OUI_FROM_DATABASE=Neo Telecom -OUI:0009D5* - ID_OUI_FROM_DATABASE=Signal Communication, Inc. +OUI:000718* + ID_OUI_FROM_DATABASE=iCanTek Co., Ltd. -OUI:0009DC* - ID_OUI_FROM_DATABASE=Galaxis Technology AG +OUI:000806* + ID_OUI_FROM_DATABASE=Raonet Systems, Inc. -OUI:0009C9* - ID_OUI_FROM_DATABASE=BlueWINC Co., Ltd. +OUI:0007FD* + ID_OUI_FROM_DATABASE=LANergy Ltd. -OUI:0009D0* - ID_OUI_FROM_DATABASE=Solacom Technologies Inc. +OUI:0007F6* + ID_OUI_FROM_DATABASE=Qqest Software Systems -OUI:0009BC* - ID_OUI_FROM_DATABASE=Digital Safety Technologies, Inc +OUI:0007FC* + ID_OUI_FROM_DATABASE=Adept Systems Inc. -OUI:0009C1* - ID_OUI_FROM_DATABASE=PROCES-DATA A/S +OUI:0007EA* + ID_OUI_FROM_DATABASE=Massana, Inc. -OUI:0009C4* - ID_OUI_FROM_DATABASE=Medicore Co., Ltd +OUI:0007F0* + ID_OUI_FROM_DATABASE=LogiSync LLC -OUI:00098F* - ID_OUI_FROM_DATABASE=Cetacean Networks +OUI:0007E3* + ID_OUI_FROM_DATABASE=Navcom Technology, Inc. -OUI:00097D* - ID_OUI_FROM_DATABASE=SecWell Networks Oy +OUI:0007E4* + ID_OUI_FROM_DATABASE=SoftRadio Co., Ltd. -OUI:00097E* - ID_OUI_FROM_DATABASE=IMI TECHNOLOGY CO., LTD +OUI:0007DD* + ID_OUI_FROM_DATABASE=Cradle Technologies -OUI:000983* - ID_OUI_FROM_DATABASE=GlobalTop Technology, Inc. +OUI:0007D7* + ID_OUI_FROM_DATABASE=Caporis Networks AG -OUI:000970* - ID_OUI_FROM_DATABASE=Vibration Research Corporation +OUI:0006E3* + ID_OUI_FROM_DATABASE=Quantitative Imaging Corporation -OUI:000977* - ID_OUI_FROM_DATABASE=Brunner Elektronik AG +OUI:0006DD* + ID_OUI_FROM_DATABASE=AT & T Laboratories - Cambridge Ltd -OUI:000964* - ID_OUI_FROM_DATABASE=Hi-Techniques, Inc. +OUI:0006A4* + ID_OUI_FROM_DATABASE=INNOWELL Corp. -OUI:00096B* - ID_OUI_FROM_DATABASE=IBM Corp +OUI:0006D3* + ID_OUI_FROM_DATABASE=Alpha Telecom, Inc. U.S.A. -OUI:000957* - ID_OUI_FROM_DATABASE=Supercaller, Inc. +OUI:0006D2* + ID_OUI_FROM_DATABASE=Tundra Semiconductor Corp. -OUI:00095C* - ID_OUI_FROM_DATABASE=Philips Medical Systems - Cardiac and Monitoring Systems (CM +OUI:000647* + ID_OUI_FROM_DATABASE=Etrali S.A. -OUI:000AE3* - ID_OUI_FROM_DATABASE=YANG MEI TECHNOLOGY CO., LTD +OUI:0006D9* + ID_OUI_FROM_DATABASE=IPM-Net S.p.A. -OUI:000AEA* - ID_OUI_FROM_DATABASE=ADAM ELEKTRONIK LTD. ŞTI +OUI:0005EA* + ID_OUI_FROM_DATABASE=Rednix -OUI:000ADE* - ID_OUI_FROM_DATABASE=Happy Communication Co., Ltd. +OUI:0006CD* + ID_OUI_FROM_DATABASE=Leaf Imaging Ltd. -OUI:000AD7* - ID_OUI_FROM_DATABASE=Origin ELECTRIC CO.,LTD. +OUI:0006BC* + ID_OUI_FROM_DATABASE=Macrolink, Inc. -OUI:000ACB* - ID_OUI_FROM_DATABASE=XPAK MSA Group +OUI:0006C6* + ID_OUI_FROM_DATABASE=lesswire AG -OUI:000AD0* - ID_OUI_FROM_DATABASE=Niigata Develoment Center, F.I.T. Co., Ltd. +OUI:000654* + ID_OUI_FROM_DATABASE=Winpresa Building Automation Technologies GmbH -OUI:000AD2* - ID_OUI_FROM_DATABASE=JEPICO Corporation +OUI:0006B6* + ID_OUI_FROM_DATABASE=Nir-Or Israel Ltd. -OUI:000ABD* - ID_OUI_FROM_DATABASE=Rupprecht & Patashnick Co. +OUI:0006B0* + ID_OUI_FROM_DATABASE=Comtech EF Data Corp. -OUI:000ABF* - ID_OUI_FROM_DATABASE=HIROTA SS +OUI:00071F* + ID_OUI_FROM_DATABASE=European Systems Integration -OUI:000AC4* - ID_OUI_FROM_DATABASE=Daewoo Teletech Co., Ltd +OUI:000724* + ID_OUI_FROM_DATABASE=Telemax Co., Ltd. -OUI:000AAC* - ID_OUI_FROM_DATABASE=TerraTec Electronic GmbH +OUI:000707* + ID_OUI_FROM_DATABASE=Interalia Inc. -OUI:000AB1* - ID_OUI_FROM_DATABASE=GENETEC Corporation +OUI:00070C* + ID_OUI_FROM_DATABASE=SVA-Intrusion.com Co. Ltd. -OUI:000AB8* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000711* + ID_OUI_FROM_DATABASE=Acterna -OUI:000AA5* - ID_OUI_FROM_DATABASE=MAXLINK INDUSTRIES LIMITED +OUI:000712* + ID_OUI_FROM_DATABASE=JAL Information Technology -OUI:000A8D* - ID_OUI_FROM_DATABASE=EUROTHERM LIMITED +OUI:0006FA* + ID_OUI_FROM_DATABASE=IP SQUARE Co, Ltd. -OUI:000A9E* - ID_OUI_FROM_DATABASE=BroadWeb Corportation +OUI:0006EF* + ID_OUI_FROM_DATABASE=Maxxan Systems, Inc. -OUI:000AA0* - ID_OUI_FROM_DATABASE=Cedar Point Communications +OUI:0006EA* + ID_OUI_FROM_DATABASE=ELZET80 Mikrocomputer GmbH&Co. KG -OUI:000A98* - ID_OUI_FROM_DATABASE=M+F Gwinner GmbH & Co +OUI:0006E9* + ID_OUI_FROM_DATABASE=Intime Corp. -OUI:000A92* - ID_OUI_FROM_DATABASE=Presonus Corporation +OUI:0005EB* + ID_OUI_FROM_DATABASE=Blue Ridge Networks, Inc. -OUI:000A7E* - ID_OUI_FROM_DATABASE=The Advantage Group +OUI:0005E4* + ID_OUI_FROM_DATABASE=Red Lion Controls Inc. -OUI:000A85* - ID_OUI_FROM_DATABASE=PLAT'C2,Inc +OUI:0005F1* + ID_OUI_FROM_DATABASE=Vrcom, Inc. -OUI:000A8A* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0005FD* + ID_OUI_FROM_DATABASE=PacketLight Networks Ltd. -OUI:0009B5* - ID_OUI_FROM_DATABASE=3J Tech. Co., Ltd. +OUI:0005E2* + ID_OUI_FROM_DATABASE=Creativ Network Technologies -OUI:0009AF* - ID_OUI_FROM_DATABASE=e-generis +OUI:0005DC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0009B0* - ID_OUI_FROM_DATABASE=Onkyo Corporation +OUI:0005E1* + ID_OUI_FROM_DATABASE=Trellis Photonics, Ltd. -OUI:0009A9* - ID_OUI_FROM_DATABASE=Ikanos Communications +OUI:0005D8* + ID_OUI_FROM_DATABASE=Arescom, Inc. -OUI:00099D* - ID_OUI_FROM_DATABASE=Haliplex Communications +OUI:0005D7* + ID_OUI_FROM_DATABASE=Vista Imaging, Inc. -OUI:0009A2* - ID_OUI_FROM_DATABASE=Interface Co., Ltd. +OUI:0005C5* + ID_OUI_FROM_DATABASE=Flaga HF -OUI:000990* - ID_OUI_FROM_DATABASE=ACKSYS Communications & systems +OUI:0005D1* + ID_OUI_FROM_DATABASE=Metavector Technologies -OUI:000996* - ID_OUI_FROM_DATABASE=RDI +OUI:0005D2* + ID_OUI_FROM_DATABASE=DAP Technologies -OUI:00098A* - ID_OUI_FROM_DATABASE=EqualLogic Inc +OUI:0005CB* + ID_OUI_FROM_DATABASE=ROIS Technologies, Inc. -OUI:000A77* - ID_OUI_FROM_DATABASE=Bluewire Technologies LLC +OUI:00057F* + ID_OUI_FROM_DATABASE=Acqis Technology -OUI:000A79* - ID_OUI_FROM_DATABASE=corega K.K +OUI:000579* + ID_OUI_FROM_DATABASE=Universal Control Solution Corp. -OUI:000A72* - ID_OUI_FROM_DATABASE=STEC, INC. +OUI:000575* + ID_OUI_FROM_DATABASE=CDS-Electronics BV -OUI:000A5F* - ID_OUI_FROM_DATABASE=almedio inc. +OUI:00056F* + ID_OUI_FROM_DATABASE=Innomedia Technologies Pvt. Ltd. -OUI:000A66* - ID_OUI_FROM_DATABASE=MITSUBISHI ELECTRIC SYSTEM & SERVICE CO.,LTD. +OUI:000568* + ID_OUI_FROM_DATABASE=Piltofish Networks AB -OUI:000A6B* - ID_OUI_FROM_DATABASE=Tadiran Telecom Business Systems LTD +OUI:000562* + ID_OUI_FROM_DATABASE=Digital View Limited -OUI:000A5A* - ID_OUI_FROM_DATABASE=GreenNET Technologies Co.,Ltd. +OUI:00055C* + ID_OUI_FROM_DATABASE=Kowa Company, Ltd. -OUI:000A53* - ID_OUI_FROM_DATABASE=Intronics, Incorporated +OUI:000556* + ID_OUI_FROM_DATABASE=360 Systems -OUI:000A58* - ID_OUI_FROM_DATABASE=Freyer & Siegel Elektronik GmbH & Co. KG +OUI:000550* + ID_OUI_FROM_DATABASE=Vcomms Connect Limited -OUI:000A4C* - ID_OUI_FROM_DATABASE=Molecular Devices Corporation +OUI:000545* + ID_OUI_FROM_DATABASE=Internet Photonics -OUI:000B24* - ID_OUI_FROM_DATABASE=AirLogic +OUI:00053F* + ID_OUI_FROM_DATABASE=VisionTek, Inc. -OUI:000B1D* - ID_OUI_FROM_DATABASE=LayerZero Power Systems, Inc. +OUI:000546* + ID_OUI_FROM_DATABASE=KDDI Network & Solultions Inc. -OUI:000B16* - ID_OUI_FROM_DATABASE=Communication Machinery Corporation +OUI:0006AA* + ID_OUI_FROM_DATABASE=VT Miltope -OUI:000B18* - ID_OUI_FROM_DATABASE=Private +OUI:0006A9* + ID_OUI_FROM_DATABASE=Universal Instruments Corp. -OUI:000B11* - ID_OUI_FROM_DATABASE=HIMEJI ABC TRADING CO.,LTD. +OUI:0006A0* + ID_OUI_FROM_DATABASE=Mx Imaging -OUI:000B0A* - ID_OUI_FROM_DATABASE=dBm Optics +OUI:00069F* + ID_OUI_FROM_DATABASE=Kuokoa Networks -OUI:000B05* - ID_OUI_FROM_DATABASE=Pacific Broadband Networks +OUI:000699* + ID_OUI_FROM_DATABASE=Vida Design Co. -OUI:000AFE* - ID_OUI_FROM_DATABASE=NovaPal Ltd +OUI:000693* + ID_OUI_FROM_DATABASE=Flexus Computer Technology, Inc. -OUI:000B03* - ID_OUI_FROM_DATABASE=Taekwang Industrial Co., Ltd +OUI:00069A* + ID_OUI_FROM_DATABASE=e & Tel -OUI:000AEF* - ID_OUI_FROM_DATABASE=OTRUM ASA +OUI:00068D* + ID_OUI_FROM_DATABASE=SEPATON, Inc. -OUI:000AF2* - ID_OUI_FROM_DATABASE=NeoAxiom Corp. +OUI:000687* + ID_OUI_FROM_DATABASE=Omnitron Systems Technology, Inc. -OUI:000A05* - ID_OUI_FROM_DATABASE=Widax Corp. +OUI:000680* + ID_OUI_FROM_DATABASE=Card Access, Inc. -OUI:000A0A* - ID_OUI_FROM_DATABASE=SUNIX Co., Ltd. +OUI:000539* + ID_OUI_FROM_DATABASE=A Brand New World in Sweden AB -OUI:000A0F* - ID_OUI_FROM_DATABASE=Ilryung Telesys, Inc +OUI:000526* + ID_OUI_FROM_DATABASE=IPAS GmbH -OUI:0009FF* - ID_OUI_FROM_DATABASE=X.net 2000 GmbH +OUI:00052D* + ID_OUI_FROM_DATABASE=Zoltrix International Limited -OUI:0009FE* - ID_OUI_FROM_DATABASE=Daisy Technologies, Inc. +OUI:00052C* + ID_OUI_FROM_DATABASE=Supreme Magic Corporation -OUI:000A00* - ID_OUI_FROM_DATABASE=Mediatek Corp. +OUI:000520* + ID_OUI_FROM_DATABASE=Smartronix, Inc. -OUI:0009F6* - ID_OUI_FROM_DATABASE=Shenzhen Eastern Digital Tech Ltd. +OUI:00051A* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD. -OUI:0009F5* - ID_OUI_FROM_DATABASE=Emerson Network Power Co.,Ltd +OUI:000510* + ID_OUI_FROM_DATABASE=Infinite Shanghai Communication Terminals Ltd. -OUI:0009E8* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000514* + ID_OUI_FROM_DATABASE=KDT Systems Co., Ltd. -OUI:0009EF* - ID_OUI_FROM_DATABASE=Vocera Communications +OUI:000509* + ID_OUI_FROM_DATABASE=AVOC Nishimura Ltd. -OUI:0009E3* - ID_OUI_FROM_DATABASE=Angel Iglesias S.A. +OUI:000503* + ID_OUI_FROM_DATABASE=ICONAG -OUI:000A39* - ID_OUI_FROM_DATABASE=LoPA Information Technology +OUI:00050A* + ID_OUI_FROM_DATABASE=ICS Spa -OUI:000A40* - ID_OUI_FROM_DATABASE=Crown Audio -- Harmanm International +OUI:0004FF* + ID_OUI_FROM_DATABASE=Acronet Co., Ltd. -OUI:000A45* - ID_OUI_FROM_DATABASE=Audio-Technica Corp. +OUI:000500* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000A47* - ID_OUI_FROM_DATABASE=Allied Vision Technologies +OUI:000641* + ID_OUI_FROM_DATABASE=ITCN -OUI:000A34* - ID_OUI_FROM_DATABASE=Identicard Systems Incorporated +OUI:00063D* + ID_OUI_FROM_DATABASE=Microwave Data Systems Inc. -OUI:000A2D* - ID_OUI_FROM_DATABASE=Cabot Communications Limited +OUI:000631* + ID_OUI_FROM_DATABASE=Calix -OUI:000A22* - ID_OUI_FROM_DATABASE=Amperion Inc +OUI:000630* + ID_OUI_FROM_DATABASE=Adtranz Sweden -OUI:000A16* - ID_OUI_FROM_DATABASE=Lassen Research +OUI:000637* + ID_OUI_FROM_DATABASE=Toptrend-Meta Information (ShenZhen) Inc. -OUI:000A1B* - ID_OUI_FROM_DATABASE=Stream Labs +OUI:000620* + ID_OUI_FROM_DATABASE=Serial System Ltd. -OUI:000878* - ID_OUI_FROM_DATABASE=Benchmark Storage Innovations +OUI:00061A* + ID_OUI_FROM_DATABASE=Zetari Inc. -OUI:000872* - ID_OUI_FROM_DATABASE=Sorenson Communications +OUI:00060C* + ID_OUI_FROM_DATABASE=Melco Industries, Inc. -OUI:00087E* - ID_OUI_FROM_DATABASE=Bon Electro-Telecom Inc. +OUI:000614* + ID_OUI_FROM_DATABASE=Prism Holdings -OUI:00086B* - ID_OUI_FROM_DATABASE=MIPSYS +OUI:000606* + ID_OUI_FROM_DATABASE=RapidWAN, Inc. -OUI:000865* - ID_OUI_FROM_DATABASE=JASCOM CO., LTD +OUI:000677* + ID_OUI_FROM_DATABASE=SICK AG -OUI:000866* - ID_OUI_FROM_DATABASE=DSX Access Systems, Inc. +OUI:000673* + ID_OUI_FROM_DATABASE=TKH Security Solutions USA -OUI:00085F* - ID_OUI_FROM_DATABASE=Picanol N.V. +OUI:000666* + ID_OUI_FROM_DATABASE=Roving Networks -OUI:000859* - ID_OUI_FROM_DATABASE=ShenZhen Unitone Electronics Co., Ltd. +OUI:00066D* + ID_OUI_FROM_DATABASE=Compuprint S.P.A. -OUI:000853* - ID_OUI_FROM_DATABASE=Schleicher GmbH & Co. Relaiswerke KG +OUI:00066C* + ID_OUI_FROM_DATABASE=Robinson Corporation -OUI:000858* - ID_OUI_FROM_DATABASE=Novatechnology Inc. +OUI:000653* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00081D* - ID_OUI_FROM_DATABASE=Ipsil, Incorporated +OUI:00065A* + ID_OUI_FROM_DATABASE=Strix Systems -OUI:000829* - ID_OUI_FROM_DATABASE=Aval Nagasaki Corporation +OUI:00064D* + ID_OUI_FROM_DATABASE=Sencore -OUI:000823* - ID_OUI_FROM_DATABASE=Texa Corp. +OUI:000660* + ID_OUI_FROM_DATABASE=NADEX Co., Ltd. -OUI:00082A* - ID_OUI_FROM_DATABASE=Powerwallz Network Security +OUI:0005B8* + ID_OUI_FROM_DATABASE=Electronic Design Associates, Inc. -OUI:000817* - ID_OUI_FROM_DATABASE=EmergeCore Networks LLC +OUI:0005BF* + ID_OUI_FROM_DATABASE=JustEzy Technology, Inc. -OUI:00091E* - ID_OUI_FROM_DATABASE=Firstech Technology Corp. +OUI:0005AE* + ID_OUI_FROM_DATABASE=Mediaport USA -OUI:000925* - ID_OUI_FROM_DATABASE=VSN Systemen BV +OUI:0005B2* + ID_OUI_FROM_DATABASE=Medison Co., Ltd. -OUI:000918* - ID_OUI_FROM_DATABASE=SAMSUNG TECHWIN CO.,LTD +OUI:00059E* + ID_OUI_FROM_DATABASE=Zinwell Corporation -OUI:000917* - ID_OUI_FROM_DATABASE=WEM Technology Inc +OUI:0005A5* + ID_OUI_FROM_DATABASE=KOTT -OUI:000912* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000598* + ID_OUI_FROM_DATABASE=CRONOS S.r.l. -OUI:00090B* - ID_OUI_FROM_DATABASE=MTL Instruments PLC +OUI:0005A4* + ID_OUI_FROM_DATABASE=Lucid Voice Ltd. -OUI:000905* - ID_OUI_FROM_DATABASE=iTEC Technologies Ltd. +OUI:000592* + ID_OUI_FROM_DATABASE=Pultek Corp. -OUI:0008FF* - ID_OUI_FROM_DATABASE=Trilogy Communications Ltd +OUI:00058B* + ID_OUI_FROM_DATABASE=IPmental, Inc. -OUI:000906* - ID_OUI_FROM_DATABASE=Esteem Networks +OUI:00058C* + ID_OUI_FROM_DATABASE=Opentech Inc. -OUI:0008FB* - ID_OUI_FROM_DATABASE=SonoSite, Inc. +OUI:00037E* + ID_OUI_FROM_DATABASE=PORTech Communications, Inc. -OUI:0008F2* - ID_OUI_FROM_DATABASE=C&S Technology +OUI:000383* + ID_OUI_FROM_DATABASE=Metera Networks, Inc. -OUI:0008F7* - ID_OUI_FROM_DATABASE=Hitachi Ltd, Semiconductor & Integrated Circuits Gr +OUI:000377* + ID_OUI_FROM_DATABASE=Gigabit Wireless -OUI:0008ED* - ID_OUI_FROM_DATABASE=ST&T Instrument Corp. +OUI:00037B* + ID_OUI_FROM_DATABASE=IDEC IZUMI Corporation -OUI:0007D1* - ID_OUI_FROM_DATABASE=Spectrum Signal Processing Inc. +OUI:00036B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0007CE* - ID_OUI_FROM_DATABASE=Cabletime Limited +OUI:000372* + ID_OUI_FROM_DATABASE=ULAN -OUI:0007C8* - ID_OUI_FROM_DATABASE=Brain21, Inc. +OUI:000367* + ID_OUI_FROM_DATABASE=Jasmine Networks, Inc. -OUI:0007BC* - ID_OUI_FROM_DATABASE=Identix Inc. +OUI:00036A* + ID_OUI_FROM_DATABASE=Mainnet, Ltd. -OUI:00047C* - ID_OUI_FROM_DATABASE=Skidata AG +OUI:000364* + ID_OUI_FROM_DATABASE=Scenix Semiconductor, Inc. -OUI:0007BB* - ID_OUI_FROM_DATABASE=Candera Inc. +OUI:00035F* + ID_OUI_FROM_DATABASE=Prüftechnik Condition Monitoring GmbH & Co. KG -OUI:0007C2* - ID_OUI_FROM_DATABASE=Netsys Telecom +OUI:00035C* + ID_OUI_FROM_DATABASE=Saint Song Corp. -OUI:0007B5* - ID_OUI_FROM_DATABASE=Any One Wireless Ltd. +OUI:00034D* + ID_OUI_FROM_DATABASE=Chiaro Networks, Ltd. -OUI:0007AF* - ID_OUI_FROM_DATABASE=Red Lion Controls, LP +OUI:0003FA* + ID_OUI_FROM_DATABASE=TiMetra Networks -OUI:0007A2* - ID_OUI_FROM_DATABASE=Opteon Corporation +OUI:0003F5* + ID_OUI_FROM_DATABASE=Chip2Chip -OUI:0007A7* - ID_OUI_FROM_DATABASE=A-Z Inc. +OUI:0003EE* + ID_OUI_FROM_DATABASE=MKNet Corporation -OUI:0007A1* - ID_OUI_FROM_DATABASE=VIASYS Healthcare GmbH +OUI:0003E8* + ID_OUI_FROM_DATABASE=Wavelength Digital Limited -OUI:0007A8* - ID_OUI_FROM_DATABASE=Haier Group Technologies Ltd. +OUI:0003E3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00094A* - ID_OUI_FROM_DATABASE=Homenet Communications +OUI:0003DC* + ID_OUI_FROM_DATABASE=Lexar Media, Inc. -OUI:000949* - ID_OUI_FROM_DATABASE=Glyph Technologies Inc. +OUI:0003D7* + ID_OUI_FROM_DATABASE=NextNet Wireless, Inc. -OUI:000950* - ID_OUI_FROM_DATABASE=Independent Storage Corporation +OUI:0003D4* + ID_OUI_FROM_DATABASE=Alloptic, Inc. -OUI:000944* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00030B* + ID_OUI_FROM_DATABASE=Hunter Technology, Inc. -OUI:00093D* - ID_OUI_FROM_DATABASE=Newisys,Inc. +OUI:0003D0* + ID_OUI_FROM_DATABASE=KOANKEISO Co., Ltd. -OUI:000937* - ID_OUI_FROM_DATABASE=Inventec Appliance Corp +OUI:0003C9* + ID_OUI_FROM_DATABASE=TECOM Co., Ltd. -OUI:000931* - ID_OUI_FROM_DATABASE=Future Internet, Inc. +OUI:0003C4* + ID_OUI_FROM_DATABASE=Tomra Systems ASA -OUI:000938* - ID_OUI_FROM_DATABASE=Allot Communications +OUI:0004FA* + ID_OUI_FROM_DATABASE=NBS Technologies Inc. -OUI:00092A* - ID_OUI_FROM_DATABASE=MYTECS Co.,Ltd. +OUI:0004F9* + ID_OUI_FROM_DATABASE=Xtera Communications, Inc. -OUI:0008B1* - ID_OUI_FROM_DATABASE=ProQuent Systems +OUI:0004F3* + ID_OUI_FROM_DATABASE=FS FORTH-SYSTEME GmbH -OUI:0008AB* - ID_OUI_FROM_DATABASE=EnerLinx.com, Inc. +OUI:0004E7* + ID_OUI_FROM_DATABASE=Lightpointe Communications, Inc -OUI:0008AC* - ID_OUI_FROM_DATABASE=Eltromat GmbH +OUI:0004ED* + ID_OUI_FROM_DATABASE=Billion Electric Co., Ltd. -OUI:0008A5* - ID_OUI_FROM_DATABASE=Peninsula Systems Inc. +OUI:0004DD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000899* - ID_OUI_FROM_DATABASE=Netbind, Inc. +OUI:0004D6* + ID_OUI_FROM_DATABASE=Takagi Industrial Co., Ltd. -OUI:00089E* - ID_OUI_FROM_DATABASE=Beijing Enter-Net co.LTD +OUI:0004D0* + ID_OUI_FROM_DATABASE=Softlink s.r.o. -OUI:000895* - ID_OUI_FROM_DATABASE=DIRC Technologie GmbH & Co.KG +OUI:0004CA* + ID_OUI_FROM_DATABASE=FreeMs Corp. -OUI:000891* - ID_OUI_FROM_DATABASE=Lyan Inc. +OUI:0004BE* + ID_OUI_FROM_DATABASE=OptXCon, Inc. -OUI:00088B* - ID_OUI_FROM_DATABASE=Tropic Networks Inc. +OUI:0004C3* + ID_OUI_FROM_DATABASE=CASTOR Informatique -OUI:00088A* - ID_OUI_FROM_DATABASE=Minds@Work +OUI:0004C4* + ID_OUI_FROM_DATABASE=Allen & Heath Limited -OUI:000885* - ID_OUI_FROM_DATABASE=EMS Dr. Thomas Wünsche +OUI:0004B7* + ID_OUI_FROM_DATABASE=AMB i.t. Holding -OUI:0008E8* - ID_OUI_FROM_DATABASE=Excel Master Ltd. +OUI:0004B1* + ID_OUI_FROM_DATABASE=Signal Technology, Inc. -OUI:0008E7* - ID_OUI_FROM_DATABASE=SHI ControlSystems,Ltd. +OUI:0004AD* + ID_OUI_FROM_DATABASE=Malibu Networks -OUI:0008E1* - ID_OUI_FROM_DATABASE=Barix AG +OUI:0004AA* + ID_OUI_FROM_DATABASE=Jetstream Communications -OUI:0008DA* - ID_OUI_FROM_DATABASE=SofaWare Technologies Ltd. +OUI:00049D* + ID_OUI_FROM_DATABASE=Ipanema Technologies -OUI:0008D5* - ID_OUI_FROM_DATABASE=Vanguard Networks Solutions, LLC +OUI:000497* + ID_OUI_FROM_DATABASE=MacroSystem Digital Video AG -OUI:0008CE* - ID_OUI_FROM_DATABASE=IPMobileNet Inc. +OUI:000490* + ID_OUI_FROM_DATABASE=Optical Access -OUI:0008C8* - ID_OUI_FROM_DATABASE=Soneticom, Inc. +OUI:00048B* + ID_OUI_FROM_DATABASE=Poscon Corporation -OUI:0008C4* - ID_OUI_FROM_DATABASE=Hikari Co.,Ltd. +OUI:000341* + ID_OUI_FROM_DATABASE=Axon Digital Design -OUI:0008BE* - ID_OUI_FROM_DATABASE=XENPAK MSA Group +OUI:00033E* + ID_OUI_FROM_DATABASE=Tateyama System Laboratory Co., Ltd. -OUI:0008B8* - ID_OUI_FROM_DATABASE=E.F. Johnson +OUI:00033A* + ID_OUI_FROM_DATABASE=Silicon Wave, Inc. -OUI:00079B* - ID_OUI_FROM_DATABASE=Aurora Networks +OUI:000333* + ID_OUI_FROM_DATABASE=Digitel Co., Ltd. -OUI:00078F* - ID_OUI_FROM_DATABASE=Emkay Innovative Products +OUI:00032B* + ID_OUI_FROM_DATABASE=GAI Datenfunksysteme GmbH -OUI:000788* - ID_OUI_FROM_DATABASE=Clipcomm, Inc. +OUI:000327* + ID_OUI_FROM_DATABASE=ACT'L -OUI:000779* - ID_OUI_FROM_DATABASE=Sungil Telecom Co., Ltd. +OUI:00032E* + ID_OUI_FROM_DATABASE=Scope Information Management, Ltd. -OUI:000778* - ID_OUI_FROM_DATABASE=GERSTEL GmbH & Co. KG +OUI:000322* + ID_OUI_FROM_DATABASE=IDIS Co., Ltd. -OUI:00076C* - ID_OUI_FROM_DATABASE=Daehanet, Inc. +OUI:00031E* + ID_OUI_FROM_DATABASE=Optranet, Inc. -OUI:00075C* - ID_OUI_FROM_DATABASE=Eastman Kodak Company +OUI:00B052* + ID_OUI_FROM_DATABASE=Atheros Communications -OUI:000768* - ID_OUI_FROM_DATABASE=Danfoss A/S +OUI:000319* + ID_OUI_FROM_DATABASE=Infineon AG -OUI:000762* - ID_OUI_FROM_DATABASE=Group Sense Limited +OUI:000316* + ID_OUI_FROM_DATABASE=Nobell Communications, Inc. -OUI:000755* - ID_OUI_FROM_DATABASE=Lafon +OUI:000312* + ID_OUI_FROM_DATABASE=TR-Systemtechnik GmbH -OUI:00074F* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000447* + ID_OUI_FROM_DATABASE=Acrowave Systems Co., Ltd. -OUI:000741* - ID_OUI_FROM_DATABASE=Sierra Automated Systems +OUI:00043B* + ID_OUI_FROM_DATABASE=Lava Computer Mfg., Inc. -OUI:000749* - ID_OUI_FROM_DATABASE=CENiX Inc. +OUI:000440* + ID_OUI_FROM_DATABASE=cyberPIXIE, Inc. -OUI:000735* - ID_OUI_FROM_DATABASE=Flarion Technologies, Inc. +OUI:00043A* + ID_OUI_FROM_DATABASE=Intelligent Telecommunications, Inc. -OUI:00073B* - ID_OUI_FROM_DATABASE=Tenovis GmbH & Co KG +OUI:000434* + ID_OUI_FROM_DATABASE=Accelent Systems, Inc. -OUI:000729* - ID_OUI_FROM_DATABASE=Kistler Instrumente AG +OUI:00042D* + ID_OUI_FROM_DATABASE=Sarian Systems, Ltd. -OUI:00072E* - ID_OUI_FROM_DATABASE=North Node AB +OUI:00042E* + ID_OUI_FROM_DATABASE=Netous Technologies, Ltd. -OUI:000728* - ID_OUI_FROM_DATABASE=Neo Telecom +OUI:000428* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000718* - ID_OUI_FROM_DATABASE=iCanTek Co., Ltd. +OUI:000421* + ID_OUI_FROM_DATABASE=Ocular Networks -OUI:000806* - ID_OUI_FROM_DATABASE=Raonet Systems, Inc. +OUI:000417* + ID_OUI_FROM_DATABASE=ELAU AG -OUI:0007FD* - ID_OUI_FROM_DATABASE=LANergy Ltd. +OUI:000411* + ID_OUI_FROM_DATABASE=Inkra Networks, Inc. -OUI:0007F6* - ID_OUI_FROM_DATABASE=Qqest Software Systems +OUI:00040B* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD. -OUI:0007FC* - ID_OUI_FROM_DATABASE=Adept Systems Inc. +OUI:000404* + ID_OUI_FROM_DATABASE=Makino Milling Machine Co., Ltd. -OUI:0007EA* - ID_OUI_FROM_DATABASE=Massana, Inc. +OUI:000481* + ID_OUI_FROM_DATABASE=Econolite Control Products, Inc. -OUI:0007F0* - ID_OUI_FROM_DATABASE=LogiSync LLC +OUI:000486* + ID_OUI_FROM_DATABASE=ITTC, University of Kansas -OUI:0007E3* - ID_OUI_FROM_DATABASE=Navcom Technology, Inc. +OUI:000477* + ID_OUI_FROM_DATABASE=Scalant Systems, Inc. -OUI:0007E4* - ID_OUI_FROM_DATABASE=SoftRadio Co., Ltd. +OUI:000476* + ID_OUI_FROM_DATABASE=3 Com Corporation -OUI:0007DD* - ID_OUI_FROM_DATABASE=Cradle Technologies +OUI:000469* + ID_OUI_FROM_DATABASE=Innocom, Inc. -OUI:0007D7* - ID_OUI_FROM_DATABASE=Caporis Networks AG +OUI:000470* + ID_OUI_FROM_DATABASE=ipUnplugged AB -OUI:0006E3* - ID_OUI_FROM_DATABASE=Quantitative Imaging Corporation +OUI:00046A* + ID_OUI_FROM_DATABASE=Navini Networks -OUI:0006DD* - ID_OUI_FROM_DATABASE=AT & T Laboratories - Cambridge Ltd +OUI:000464* + ID_OUI_FROM_DATABASE=Pulse-Link Inc -OUI:0006A4* - ID_OUI_FROM_DATABASE=INNOWELL Corp. +OUI:00045D* + ID_OUI_FROM_DATABASE=BEKA Elektronik -OUI:0006D3* - ID_OUI_FROM_DATABASE=Alpha Telecom, Inc. U.S.A. +OUI:000457* + ID_OUI_FROM_DATABASE=Universal Access Technology, Inc. -OUI:0006D2* - ID_OUI_FROM_DATABASE=Tundra Semiconductor Corp. +OUI:000451* + ID_OUI_FROM_DATABASE=Medrad, Inc. -OUI:000647* - ID_OUI_FROM_DATABASE=Etrali S.A. +OUI:0003C1* + ID_OUI_FROM_DATABASE=Packet Dynamics Ltd -OUI:0006D9* - ID_OUI_FROM_DATABASE=IPM-Net S.p.A. +OUI:0003BD* + ID_OUI_FROM_DATABASE=OmniCluster Technologies, Inc. -OUI:0005EA* - ID_OUI_FROM_DATABASE=Rednix +OUI:0003B8* + ID_OUI_FROM_DATABASE=NetKit Solutions, LLC -OUI:0006CD* - ID_OUI_FROM_DATABASE=Leaf Imaging Ltd. +OUI:0003B6* + ID_OUI_FROM_DATABASE=QSI Corporation -OUI:0006BC* - ID_OUI_FROM_DATABASE=Macrolink, Inc. +OUI:0003A6* + ID_OUI_FROM_DATABASE=Traxit Technology, Inc. -OUI:0006C6* - ID_OUI_FROM_DATABASE=lesswire AG +OUI:0003AB* + ID_OUI_FROM_DATABASE=Bridge Information Systems -OUI:000654* - ID_OUI_FROM_DATABASE=Winpresa Building Automation Technologies GmbH +OUI:0003A3* + ID_OUI_FROM_DATABASE=MAVIX, Ltd. -OUI:0006B6* - ID_OUI_FROM_DATABASE=Nir-Or Israel Ltd. +OUI:00039F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0006B0* - ID_OUI_FROM_DATABASE=Comtech EF Data Corp. +OUI:00039A* + ID_OUI_FROM_DATABASE=SiConnect -OUI:00071F* - ID_OUI_FROM_DATABASE=European Systems Integration +OUI:00038C* + ID_OUI_FROM_DATABASE=Total Impact -OUI:000724* - ID_OUI_FROM_DATABASE=Telemax Co., Ltd. +OUI:000384* + ID_OUI_FROM_DATABASE=AETA -OUI:000707* - ID_OUI_FROM_DATABASE=Interalia Inc. +OUI:000387* + ID_OUI_FROM_DATABASE=Blaze Network Products -OUI:00070C* - ID_OUI_FROM_DATABASE=SVA-Intrusion.com Co. Ltd. +OUI:000306* + ID_OUI_FROM_DATABASE=Fusion In Tech Co., Ltd. -OUI:000711* - ID_OUI_FROM_DATABASE=Acterna +OUI:000303* + ID_OUI_FROM_DATABASE=JAMA Electronics Co., Ltd. -OUI:000712* - ID_OUI_FROM_DATABASE=JAL Information Technology +OUI:0002FF* + ID_OUI_FROM_DATABASE=Handan BroadInfoCom -OUI:0006FA* - ID_OUI_FROM_DATABASE=IP SQUARE Co, Ltd. +OUI:0002F3* + ID_OUI_FROM_DATABASE=Media Serve Co., Ltd. -OUI:0006EF* - ID_OUI_FROM_DATABASE=Maxxan Systems, Inc. +OUI:0002FA* + ID_OUI_FROM_DATABASE=DX Antenna Co., Ltd. -OUI:0006EA* - ID_OUI_FROM_DATABASE=ELZET80 Mikrocomputer GmbH&Co. KG +OUI:0002ED* + ID_OUI_FROM_DATABASE=DXO Telecom Co., Ltd. -OUI:0006E9* - ID_OUI_FROM_DATABASE=Intime Corp. +OUI:0002E5* + ID_OUI_FROM_DATABASE=Timeware Ltd. -OUI:0005EB* - ID_OUI_FROM_DATABASE=Blue Ridge Networks, Inc. +OUI:0002E8* + ID_OUI_FROM_DATABASE=E.D.&A. -OUI:0005F7* - ID_OUI_FROM_DATABASE=Analog Devices, Inc. +OUI:0002DC* + ID_OUI_FROM_DATABASE=Fujitsu General Limited -OUI:0005E4* - ID_OUI_FROM_DATABASE=Red Lion Controls Inc. +OUI:0002E1* + ID_OUI_FROM_DATABASE=Integrated Network Corporation -OUI:0005F1* - ID_OUI_FROM_DATABASE=Vrcom, Inc. +OUI:0002D5* + ID_OUI_FROM_DATABASE=ACR -OUI:0005FD* - ID_OUI_FROM_DATABASE=PacketLight Networks Ltd. +OUI:0002CE* + ID_OUI_FROM_DATABASE=FoxJet, Inc. -OUI:0005E2* - ID_OUI_FROM_DATABASE=Creativ Network Technologies +OUI:00B0DB* + ID_OUI_FROM_DATABASE=Nextcell, Inc. -OUI:0005DC* +OUI:00B08E* ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0005E1* - ID_OUI_FROM_DATABASE=Trellis Photonics, Ltd. +OUI:00B01C* + ID_OUI_FROM_DATABASE=Westport Technologies -OUI:0005D8* - ID_OUI_FROM_DATABASE=Arescom, Inc. +OUI:00B02D* + ID_OUI_FROM_DATABASE=ViaGate Technologies, Inc. -OUI:0005D7* - ID_OUI_FROM_DATABASE=Vista Imaging, Inc. +OUI:00B03B* + ID_OUI_FROM_DATABASE=HiQ Networks -OUI:0005C5* - ID_OUI_FROM_DATABASE=Flaga HF +OUI:0030A9* + ID_OUI_FROM_DATABASE=Netiverse, Inc. -OUI:0005D1* - ID_OUI_FROM_DATABASE=Metavector Technologies +OUI:00B0F0* + ID_OUI_FROM_DATABASE=CALY NETWORKS -OUI:0005D2* - ID_OUI_FROM_DATABASE=DAP Technologies +OUI:00B086* + ID_OUI_FROM_DATABASE=LocSoft Limited -OUI:0005CB* - ID_OUI_FROM_DATABASE=ROIS Technologies, Inc. +OUI:0030C4* + ID_OUI_FROM_DATABASE=Canon Imaging Systems Inc. -OUI:00057F* - ID_OUI_FROM_DATABASE=Acqis Technology +OUI:00309D* + ID_OUI_FROM_DATABASE=Nimble Microsystems, Inc. -OUI:000579* - ID_OUI_FROM_DATABASE=Universal Control Solution Corp. +OUI:003037* + ID_OUI_FROM_DATABASE=Packard Bell Nec Services -OUI:000575* - ID_OUI_FROM_DATABASE=CDS-Electronics BV +OUI:00302E* + ID_OUI_FROM_DATABASE=Hoft & Wessel AG -OUI:00056F* - ID_OUI_FROM_DATABASE=Innomedia Technologies Pvt. Ltd. +OUI:00301B* + ID_OUI_FROM_DATABASE=SHUTTLE, INC. -OUI:000568* - ID_OUI_FROM_DATABASE=Piltofish Networks AB +OUI:003028* + ID_OUI_FROM_DATABASE=FASE Saldatura srl -OUI:000562* - ID_OUI_FROM_DATABASE=Digital View Limited +OUI:0030FB* + ID_OUI_FROM_DATABASE=AZS Technology AG -OUI:00055C* - ID_OUI_FROM_DATABASE=Kowa Company, Ltd. +OUI:0001DA* + ID_OUI_FROM_DATABASE=WINCOMM Corporation -OUI:000556* - ID_OUI_FROM_DATABASE=360 Systems +OUI:0001DD* + ID_OUI_FROM_DATABASE=Avail Networks -OUI:000550* - ID_OUI_FROM_DATABASE=Vcomms Connect Limited +OUI:0001CE* + ID_OUI_FROM_DATABASE=Custom Micro Products, Ltd. -OUI:000545* - ID_OUI_FROM_DATABASE=Internet Photonics +OUI:0001CA* + ID_OUI_FROM_DATABASE=Geocast Network Systems, Inc. -OUI:00053F* - ID_OUI_FROM_DATABASE=VisionTek, Inc. +OUI:0001B8* + ID_OUI_FROM_DATABASE=Netsensity, Inc. -OUI:000546* - ID_OUI_FROM_DATABASE=KDDI Network & Solultions Inc. +OUI:0001BD* + ID_OUI_FROM_DATABASE=Peterson Electro-Musical Products, Inc. -OUI:0006AA* - ID_OUI_FROM_DATABASE=VT Miltope +OUI:0001B4* + ID_OUI_FROM_DATABASE=Wayport, Inc. -OUI:0006A9* - ID_OUI_FROM_DATABASE=Universal Instruments Corp. +OUI:0001C3* + ID_OUI_FROM_DATABASE=Acromag, Inc. -OUI:0006A0* - ID_OUI_FROM_DATABASE=Mx Imaging +OUI:0001BF* + ID_OUI_FROM_DATABASE=Teleforce Co., Ltd. -OUI:00069F* - ID_OUI_FROM_DATABASE=Kuokoa Networks +OUI:0001AD* + ID_OUI_FROM_DATABASE=Coach Master International d.b.a. CMI Worldwide, Inc. -OUI:000699* - ID_OUI_FROM_DATABASE=Vida Design Co. +OUI:00017E* + ID_OUI_FROM_DATABASE=ADTEK System Science Co., Ltd. -OUI:000693* - ID_OUI_FROM_DATABASE=Flexus Computer Technology, Inc. +OUI:00018A* + ID_OUI_FROM_DATABASE=ROI COMPUTER AG -OUI:00069A* - ID_OUI_FROM_DATABASE=e & Tel +OUI:000119* + ID_OUI_FROM_DATABASE=RTUnet (Australia) -OUI:00068D* - ID_OUI_FROM_DATABASE=SEPATON, Inc. +OUI:000125* + ID_OUI_FROM_DATABASE=YAESU MUSEN CO., LTD. -OUI:000687* - ID_OUI_FROM_DATABASE=Omnitron Systems Technology, Inc. +OUI:000121* + ID_OUI_FROM_DATABASE=Watchguard Technologies, Inc. -OUI:000680* - ID_OUI_FROM_DATABASE=Card Access, Inc. +OUI:000128* + ID_OUI_FROM_DATABASE=EnjoyWeb, Inc. -OUI:000539* - ID_OUI_FROM_DATABASE=A Brand New World in Sweden AB +OUI:000106* + ID_OUI_FROM_DATABASE=Tews Datentechnik GmbH -OUI:000526* - ID_OUI_FROM_DATABASE=IPAS GmbH +OUI:000112* + ID_OUI_FROM_DATABASE=Shark Multimedia Inc. -OUI:00052D* - ID_OUI_FROM_DATABASE=Zoltrix International Limited +OUI:000102* + ID_OUI_FROM_DATABASE=3COM CORPORATION -OUI:00052C* - ID_OUI_FROM_DATABASE=Supreme Magic Corporation +OUI:000115* + ID_OUI_FROM_DATABASE=EXTRATECH CORPORATION -OUI:000520* - ID_OUI_FROM_DATABASE=Smartronix, Inc. +OUI:000109* + ID_OUI_FROM_DATABASE=Nagano Japan Radio Co., Ltd. -OUI:00051A* - ID_OUI_FROM_DATABASE=3COM EUROPE LTD. +OUI:081443* + ID_OUI_FROM_DATABASE=UNIBRAIN S.A. -OUI:000510* - ID_OUI_FROM_DATABASE=Infinite Shanghai Communication Terminals Ltd. +OUI:00B0F5* + ID_OUI_FROM_DATABASE=NetWorth Technologies, Inc. -OUI:000514* - ID_OUI_FROM_DATABASE=KDT Systems Co., Ltd. +OUI:00B019* + ID_OUI_FROM_DATABASE=UTC CCS -OUI:000509* - ID_OUI_FROM_DATABASE=AVOC Nishimura Ltd. +OUI:00B02A* + ID_OUI_FROM_DATABASE=ORSYS GmbH -OUI:000503* - ID_OUI_FROM_DATABASE=ICONAG +OUI:00B0AE* + ID_OUI_FROM_DATABASE=Symmetricom -OUI:00050A* - ID_OUI_FROM_DATABASE=ICS Spa +OUI:000181* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:0004FF* - ID_OUI_FROM_DATABASE=Acronet Co., Ltd. +OUI:00018D* + ID_OUI_FROM_DATABASE=AudeSi Technologies -OUI:000500* +OUI:00019A* + ID_OUI_FROM_DATABASE=LEUNIG GmbH + +OUI:000193* + ID_OUI_FROM_DATABASE=Hanbyul Telecom Co., Ltd. + +OUI:0001A2* + ID_OUI_FROM_DATABASE=Logical Co., Ltd. + +OUI:000196* ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000641* - ID_OUI_FROM_DATABASE=ITCN +OUI:0001A6* + ID_OUI_FROM_DATABASE=Scientific-Atlanta Arcodan A/S -OUI:00063D* - ID_OUI_FROM_DATABASE=Microwave Data Systems Inc. +OUI:000172* + ID_OUI_FROM_DATABASE=TechnoLand Co., LTD. -OUI:000631* - ID_OUI_FROM_DATABASE=Calix +OUI:00303F* + ID_OUI_FROM_DATABASE=TurboComm Tech Inc. -OUI:000630* - ID_OUI_FROM_DATABASE=Adtranz Sweden +OUI:003073* + ID_OUI_FROM_DATABASE=International Microsystems, In -OUI:000637* - ID_OUI_FROM_DATABASE=Toptrend-Meta Information (ShenZhen) Inc. +OUI:00014D* + ID_OUI_FROM_DATABASE=Shin Kin Enterprises Co., Ltd -OUI:000620* - ID_OUI_FROM_DATABASE=Serial System Ltd. +OUI:00016B* + ID_OUI_FROM_DATABASE=LightChip, Inc. -OUI:00061A* - ID_OUI_FROM_DATABASE=Zetari Inc. +OUI:000167* + ID_OUI_FROM_DATABASE=HIOKI E.E. CORPORATION -OUI:00060C* - ID_OUI_FROM_DATABASE=Melco Industries, Inc. +OUI:000215* + ID_OUI_FROM_DATABASE=Cotas Computer Technology A/B -OUI:000614* - ID_OUI_FROM_DATABASE=Prism Holdings +OUI:000211* + ID_OUI_FROM_DATABASE=Nature Worldwide Technology Corp. -OUI:000606* - ID_OUI_FROM_DATABASE=RapidWAN, Inc. +OUI:000209* + ID_OUI_FROM_DATABASE=Shenzhen SED Information Technology Co., Ltd. -OUI:000677* - ID_OUI_FROM_DATABASE=SICK AG +OUI:000205* + ID_OUI_FROM_DATABASE=Hitachi Denshi, Ltd. -OUI:000673* - ID_OUI_FROM_DATABASE=TKH Security Solutions USA +OUI:000202* + ID_OUI_FROM_DATABASE=Amino Communications, Ltd. -OUI:000666* - ID_OUI_FROM_DATABASE=Roving Networks +OUI:0001F6* + ID_OUI_FROM_DATABASE=Association of Musical Electronics Industry -OUI:00066D* - ID_OUI_FROM_DATABASE=Compuprint S.P.A. +OUI:0001ED* + ID_OUI_FROM_DATABASE=SETA Corp. -OUI:00066C* - ID_OUI_FROM_DATABASE=Robinson Corporation +OUI:0001E9* + ID_OUI_FROM_DATABASE=Litton Marine Systems B.V. -OUI:000653* +OUI:0002C6* + ID_OUI_FROM_DATABASE=Data Track Technology PLC + +OUI:0002C2* + ID_OUI_FROM_DATABASE=Net Vision Telecom + +OUI:0002B9* ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00065A* - ID_OUI_FROM_DATABASE=Strix Systems +OUI:0002B4* + ID_OUI_FROM_DATABASE=DAPHNE -OUI:00064D* - ID_OUI_FROM_DATABASE=Sencore +OUI:0002AD* + ID_OUI_FROM_DATABASE=HOYA Corporation -OUI:000660* - ID_OUI_FROM_DATABASE=NADEX Co., Ltd. +OUI:0002A6* + ID_OUI_FROM_DATABASE=Effinet Systems Co., Ltd. -OUI:0005B8* - ID_OUI_FROM_DATABASE=Electronic Design Associates, Inc. +OUI:0002A1* + ID_OUI_FROM_DATABASE=World Wide Packets -OUI:0005BF* - ID_OUI_FROM_DATABASE=JustEzy Technology, Inc. +OUI:00029B* + ID_OUI_FROM_DATABASE=Kreatel Communications AB -OUI:0005AE* - ID_OUI_FROM_DATABASE=Mediaport USA +OUI:00029E* + ID_OUI_FROM_DATABASE=Information Equipment Co., Ltd. -OUI:0005B2* - ID_OUI_FROM_DATABASE=Medison Co., Ltd. +OUI:000296* + ID_OUI_FROM_DATABASE=Lectron Co,. Ltd. -OUI:00059E* - ID_OUI_FROM_DATABASE=Zinwell Corporation +OUI:00028F* + ID_OUI_FROM_DATABASE=Globetek, Inc. -OUI:0005A5* - ID_OUI_FROM_DATABASE=KOTT +OUI:000289* + ID_OUI_FROM_DATABASE=DNE Technologies -OUI:000598* - ID_OUI_FROM_DATABASE=CRONOS S.r.l. +OUI:000285* + ID_OUI_FROM_DATABASE=Riverstone Networks -OUI:0005A4* - ID_OUI_FROM_DATABASE=Lucid Voice Ltd. +OUI:00027E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000592* - ID_OUI_FROM_DATABASE=Pultek Corp. +OUI:000280* + ID_OUI_FROM_DATABASE=Mu Net, Inc. -OUI:00058B* - ID_OUI_FROM_DATABASE=IPmental, Inc. +OUI:000279* + ID_OUI_FROM_DATABASE=Control Applications, Ltd. -OUI:00058C* - ID_OUI_FROM_DATABASE=Opentech Inc. +OUI:000272* + ID_OUI_FROM_DATABASE=CC&C Technologies, Inc. -OUI:00037E* - ID_OUI_FROM_DATABASE=PORTech Communications, Inc. +OUI:00026B* + ID_OUI_FROM_DATABASE=BCM Computers Co., Ltd. -OUI:000383* - ID_OUI_FROM_DATABASE=Metera Networks, Inc. +OUI:00026D* + ID_OUI_FROM_DATABASE=Adept Telecom -OUI:000377* - ID_OUI_FROM_DATABASE=Gigabit Wireless +OUI:000262* + ID_OUI_FROM_DATABASE=Soyo Group Soyo Com Tech Co., Ltd -OUI:00037B* - ID_OUI_FROM_DATABASE=IDEC IZUMI Corporation +OUI:000260* + ID_OUI_FROM_DATABASE=Accordion Networks, Inc. -OUI:00036B* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00025B* + ID_OUI_FROM_DATABASE=Cambridge Silicon Radio -OUI:000372* - ID_OUI_FROM_DATABASE=ULAN +OUI:000087* + ID_OUI_FROM_DATABASE=HITACHI, LTD. -OUI:000367* - ID_OUI_FROM_DATABASE=Jasmine Networks, Inc. +OUI:000252* + ID_OUI_FROM_DATABASE=Carrier Corporation -OUI:00036A* - ID_OUI_FROM_DATABASE=Mainnet, Ltd. +OUI:00024B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000364* - ID_OUI_FROM_DATABASE=Scenix Semiconductor, Inc. +OUI:000246* + ID_OUI_FROM_DATABASE=All-Win Tech Co., Ltd. -OUI:00035F* - ID_OUI_FROM_DATABASE=Prüftechnik Condition Monitoring GmbH & Co. KG +OUI:00017A* + ID_OUI_FROM_DATABASE=Chengdu Maipu Electric Industrial Co., Ltd. -OUI:00035C* - ID_OUI_FROM_DATABASE=Saint Song Corp. +OUI:000235* + ID_OUI_FROM_DATABASE=Paragon Networks International -OUI:00034D* - ID_OUI_FROM_DATABASE=Chiaro Networks, Ltd. +OUI:000238* + ID_OUI_FROM_DATABASE=Serome Technology, Inc. -OUI:0003FA* - ID_OUI_FROM_DATABASE=TiMetra Networks +OUI:000230* + ID_OUI_FROM_DATABASE=Intersoft Electronics -OUI:0003F5* - ID_OUI_FROM_DATABASE=Chip2Chip +OUI:000229* + ID_OUI_FROM_DATABASE=Adtec Corporation -OUI:0003EE* - ID_OUI_FROM_DATABASE=MKNet Corporation +OUI:000225* + ID_OUI_FROM_DATABASE=One Stop Systems -OUI:0003E8* - ID_OUI_FROM_DATABASE=Wavelength Digital Limited +OUI:00021C* + ID_OUI_FROM_DATABASE=Network Elements, Inc. -OUI:0003E3* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:000221* + ID_OUI_FROM_DATABASE=DSP Application, Ltd. -OUI:0003DC* - ID_OUI_FROM_DATABASE=Lexar Media, Inc. +OUI:00016E* + ID_OUI_FROM_DATABASE=Conklin Corporation -OUI:0003D7* - ID_OUI_FROM_DATABASE=NextNet Wireless, Inc. +OUI:00015B* + ID_OUI_FROM_DATABASE=ITALTEL S.p.A/RF-UP-I -OUI:0003D4* - ID_OUI_FROM_DATABASE=Alloptic, Inc. +OUI:000154* + ID_OUI_FROM_DATABASE=G3M Corporation -OUI:00030B* - ID_OUI_FROM_DATABASE=Hunter Technology, Inc. +OUI:000150* + ID_OUI_FROM_DATABASE=GILAT COMMUNICATIONS, LTD. -OUI:0003D0* - ID_OUI_FROM_DATABASE=KOANKEISO Co., Ltd. +OUI:00012E* + ID_OUI_FROM_DATABASE=PC Partner Ltd. -OUI:0003C9* - ID_OUI_FROM_DATABASE=TECOM Co., Ltd. +OUI:00013A* + ID_OUI_FROM_DATABASE=SHELCAD COMMUNICATIONS, LTD. -OUI:0003C4* - ID_OUI_FROM_DATABASE=Tomra Systems ASA +OUI:000141* + ID_OUI_FROM_DATABASE=CABLE PRINT -OUI:0004FA* - ID_OUI_FROM_DATABASE=NBS Technologies Inc. +OUI:000131* + ID_OUI_FROM_DATABASE=Bosch Security Systems, Inc. -OUI:0004F9* - ID_OUI_FROM_DATABASE=Xtera Communications, Inc. +OUI:00013D* + ID_OUI_FROM_DATABASE=RiscStation Ltd. -OUI:0004F3* - ID_OUI_FROM_DATABASE=FS FORTH-SYSTEME GmbH +OUI:000149* + ID_OUI_FROM_DATABASE=T.D.T. Transfer Data Test GmbH -OUI:0004E7* - ID_OUI_FROM_DATABASE=Lightpointe Communications, Inc +OUI:00D047* + ID_OUI_FROM_DATABASE=XN TECHNOLOGIES -OUI:0004ED* - ID_OUI_FROM_DATABASE=Billion Electric Co., Ltd. +OUI:00D018* + ID_OUI_FROM_DATABASE=QWES. COM, INC. -OUI:0004DD* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00D048* + ID_OUI_FROM_DATABASE=ECTON, INC. -OUI:0004D6* - ID_OUI_FROM_DATABASE=Takagi Industrial Co., Ltd. +OUI:00D028* + ID_OUI_FROM_DATABASE=Harmonic, Inc -OUI:0004D0* - ID_OUI_FROM_DATABASE=Softlink s.r.o. +OUI:00D02F* + ID_OUI_FROM_DATABASE=VLSI TECHNOLOGY INC. -OUI:0004CA* - ID_OUI_FROM_DATABASE=FreeMs Corp. +OUI:00D025* + ID_OUI_FROM_DATABASE=XROSSTECH, INC. -OUI:0004BE* - ID_OUI_FROM_DATABASE=OptXCon, Inc. +OUI:00D085* + ID_OUI_FROM_DATABASE=OTIS ELEVATOR COMPANY -OUI:0004C3* - ID_OUI_FROM_DATABASE=CASTOR Informatique +OUI:00D077* + ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES -OUI:0004C4* - ID_OUI_FROM_DATABASE=Allen & Heath Limited +OUI:00D093* + ID_OUI_FROM_DATABASE=TQ - COMPONENTS GMBH -OUI:0004B7* - ID_OUI_FROM_DATABASE=AMB i.t. Holding +OUI:00D013* + ID_OUI_FROM_DATABASE=PRIMEX AEROSPACE COMPANY -OUI:0004B1* - ID_OUI_FROM_DATABASE=Signal Technology, Inc. +OUI:00D056* + ID_OUI_FROM_DATABASE=SOMAT CORPORATION -OUI:0004AD* - ID_OUI_FROM_DATABASE=Malibu Networks +OUI:00D017* + ID_OUI_FROM_DATABASE=SYNTECH INFORMATION CO., LTD. -OUI:0004AA* - ID_OUI_FROM_DATABASE=Jetstream Communications +OUI:00D036* + ID_OUI_FROM_DATABASE=TECHNOLOGY ATLANTA CORP. -OUI:00049D* - ID_OUI_FROM_DATABASE=Ipanema Technologies +OUI:00D0D6* + ID_OUI_FROM_DATABASE=AETHRA TELECOMUNICAZIONI -OUI:000497* - ID_OUI_FROM_DATABASE=MacroSystem Digital Video AG +OUI:003078* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000490* - ID_OUI_FROM_DATABASE=Optical Access +OUI:003003* + ID_OUI_FROM_DATABASE=Phasys Ltd. -OUI:00048B* - ID_OUI_FROM_DATABASE=Poscon Corporation +OUI:0030D5* + ID_OUI_FROM_DATABASE=DResearch GmbH -OUI:000341* - ID_OUI_FROM_DATABASE=Axon Digital Design +OUI:0030CE* + ID_OUI_FROM_DATABASE=Zaffire -OUI:00033E* - ID_OUI_FROM_DATABASE=Tateyama System Laboratory Co., Ltd. +OUI:003095* + ID_OUI_FROM_DATABASE=Procomp Informatics, Ltd. -OUI:00033A* - ID_OUI_FROM_DATABASE=Silicon Wave, Inc. +OUI:003055* + ID_OUI_FROM_DATABASE=Renesas Technology America, Inc. -OUI:000333* - ID_OUI_FROM_DATABASE=Digitel Co., Ltd. +OUI:0030B0* + ID_OUI_FROM_DATABASE=Convergenet Technologies -OUI:00032B* - ID_OUI_FROM_DATABASE=GAI Datenfunksysteme GmbH +OUI:0030CC* + ID_OUI_FROM_DATABASE=Tenor Networks, Inc. -OUI:000327* - ID_OUI_FROM_DATABASE=ACT'L +OUI:003013* + ID_OUI_FROM_DATABASE=NEC Corporation -OUI:00032E* - ID_OUI_FROM_DATABASE=Scope Information Management, Ltd. +OUI:003061* + ID_OUI_FROM_DATABASE=MobyTEL -OUI:000322* - ID_OUI_FROM_DATABASE=IDIS Co., Ltd. +OUI:00D0AB* + ID_OUI_FROM_DATABASE=DELTAKABEL TELECOM CV -OUI:00031E* - ID_OUI_FROM_DATABASE=Optranet, Inc. +OUI:00D0A8* + ID_OUI_FROM_DATABASE=NETWORK ENGINES, INC. -OUI:00B052* - ID_OUI_FROM_DATABASE=Atheros Communications +OUI:00D01C* + ID_OUI_FROM_DATABASE=SBS TECHNOLOGIES, -OUI:000319* - ID_OUI_FROM_DATABASE=Infineon AG +OUI:00D0C0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000316* - ID_OUI_FROM_DATABASE=Nobell Communications, Inc. +OUI:00D051* + ID_OUI_FROM_DATABASE=O2 MICRO, INC. -OUI:000312* - ID_OUI_FROM_DATABASE=TR-Systemtechnik GmbH +OUI:00D06D* + ID_OUI_FROM_DATABASE=ACRISON, INC. -OUI:000447* - ID_OUI_FROM_DATABASE=Acrowave Systems Co., Ltd. +OUI:0050A1* + ID_OUI_FROM_DATABASE=CARLO GAVAZZI, INC. -OUI:00043B* - ID_OUI_FROM_DATABASE=Lava Computer Mfg., Inc. +OUI:00D06C* + ID_OUI_FROM_DATABASE=SHAREWAVE, INC. -OUI:000440* - ID_OUI_FROM_DATABASE=cyberPIXIE, Inc. +OUI:00D03A* + ID_OUI_FROM_DATABASE=ZONEWORX, INC. -OUI:00043A* - ID_OUI_FROM_DATABASE=Intelligent Telecommunications, Inc. +OUI:0050C1* + ID_OUI_FROM_DATABASE=GEMFLEX NETWORKS, LTD. -OUI:000434* - ID_OUI_FROM_DATABASE=Accelent Systems, Inc. +OUI:0050FB* + ID_OUI_FROM_DATABASE=VSK ELECTRONICS -OUI:00042D* - ID_OUI_FROM_DATABASE=Sarian Systems, Ltd. +OUI:005033* + ID_OUI_FROM_DATABASE=MAYAN NETWORKS -OUI:00042E* - ID_OUI_FROM_DATABASE=Netous Technologies, Ltd. +OUI:0030A0* + ID_OUI_FROM_DATABASE=TYCO SUBMARINE SYSTEMS, LTD. -OUI:000428* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0030CB* + ID_OUI_FROM_DATABASE=OMNI FLOW COMPUTERS, INC. -OUI:000421* - ID_OUI_FROM_DATABASE=Ocular Networks +OUI:00306B* + ID_OUI_FROM_DATABASE=CMOS SYSTEMS, INC. -OUI:000417* - ID_OUI_FROM_DATABASE=ELAU AG +OUI:003068* + ID_OUI_FROM_DATABASE=CYBERNETICS TECH. CO., LTD. -OUI:000411* - ID_OUI_FROM_DATABASE=Inkra Networks, Inc. +OUI:0030E3* + ID_OUI_FROM_DATABASE=SEDONA NETWORKS CORP. -OUI:00040B* - ID_OUI_FROM_DATABASE=3COM EUROPE LTD. +OUI:00D007* + ID_OUI_FROM_DATABASE=MIC ASSOCIATES, INC. -OUI:000404* - ID_OUI_FROM_DATABASE=Makino Milling Machine Co., Ltd. +OUI:00D07F* + ID_OUI_FROM_DATABASE=STRATEGY & TECHNOLOGY, LIMITED -OUI:000481* - ID_OUI_FROM_DATABASE=Econolite Control Products, Inc. +OUI:003085* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000486* - ID_OUI_FROM_DATABASE=ITTC, University of Kansas +OUI:003026* + ID_OUI_FROM_DATABASE=HeiTel Digital Video GmbH -OUI:000477* - ID_OUI_FROM_DATABASE=Scalant Systems, Inc. +OUI:0030A6* + ID_OUI_FROM_DATABASE=VIANET TECHNOLOGIES, LTD. -OUI:000476* - ID_OUI_FROM_DATABASE=3 Com Corporation +OUI:003047* + ID_OUI_FROM_DATABASE=NISSEI ELECTRIC CO., LTD. -OUI:000469* - ID_OUI_FROM_DATABASE=Innocom, Inc. +OUI:00D0FC* + ID_OUI_FROM_DATABASE=GRANITE MICROSYSTEMS -OUI:000470* - ID_OUI_FROM_DATABASE=ipUnplugged AB +OUI:00D042* + ID_OUI_FROM_DATABASE=MAHLO GMBH & CO. UG -OUI:00046A* - ID_OUI_FROM_DATABASE=Navini Networks +OUI:00D046* + ID_OUI_FROM_DATABASE=DOLBY LABORATORIES, INC. -OUI:000464* - ID_OUI_FROM_DATABASE=Pulse-Link Inc +OUI:00D0BA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00045D* - ID_OUI_FROM_DATABASE=BEKA Elektronik +OUI:00D0BC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000457* - ID_OUI_FROM_DATABASE=Universal Access Technology, Inc. +OUI:00D0D8* + ID_OUI_FROM_DATABASE=3Com Corporation -OUI:000451* - ID_OUI_FROM_DATABASE=Medrad, Inc. +OUI:00D06B* + ID_OUI_FROM_DATABASE=SR TELECOM INC. -OUI:0003C1* - ID_OUI_FROM_DATABASE=Packet Dynamics Ltd +OUI:0030AA* + ID_OUI_FROM_DATABASE=AXUS MICROSYSTEMS, INC. -OUI:0003BD* - ID_OUI_FROM_DATABASE=OmniCluster Technologies, Inc. +OUI:003043* + ID_OUI_FROM_DATABASE=IDREAM TECHNOLOGIES, PTE. LTD. -OUI:0003B8* - ID_OUI_FROM_DATABASE=NetKit Solutions, LLC +OUI:003010* + ID_OUI_FROM_DATABASE=VISIONETICS INTERNATIONAL -OUI:0003B6* - ID_OUI_FROM_DATABASE=QSI Corporation +OUI:003096* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0003A6* - ID_OUI_FROM_DATABASE=Traxit Technology, Inc. +OUI:003084* + ID_OUI_FROM_DATABASE=ALLIED TELESYN INTERNAIONAL -OUI:0003AB* - ID_OUI_FROM_DATABASE=Bridge Information Systems +OUI:0030CF* + ID_OUI_FROM_DATABASE=TWO TECHNOLOGIES, INC. -OUI:0003A3* - ID_OUI_FROM_DATABASE=MAVIX, Ltd. +OUI:00D0E3* + ID_OUI_FROM_DATABASE=ELE-CHEM ENGINEERING CO., LTD. -OUI:00039F* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00D0ED* + ID_OUI_FROM_DATABASE=XIOX -OUI:00039A* - ID_OUI_FROM_DATABASE=SiConnect +OUI:00D0C2* + ID_OUI_FROM_DATABASE=BALTHAZAR TECHNOLOGY AB -OUI:00038C* - ID_OUI_FROM_DATABASE=Total Impact +OUI:00D0FB* + ID_OUI_FROM_DATABASE=TEK MICROSYSTEMS, INCORPORATED -OUI:000384* - ID_OUI_FROM_DATABASE=AETA +OUI:00D082* + ID_OUI_FROM_DATABASE=IOWAVE INC. -OUI:000387* - ID_OUI_FROM_DATABASE=Blaze Network Products +OUI:00D0AD* + ID_OUI_FROM_DATABASE=TL INDUSTRIES -OUI:000306* - ID_OUI_FROM_DATABASE=Fusion In Tech Co., Ltd. +OUI:00D0DB* + ID_OUI_FROM_DATABASE=MCQUAY INTERNATIONAL -OUI:000303* - ID_OUI_FROM_DATABASE=JAMA Electronics Co., Ltd. +OUI:00D06A* + ID_OUI_FROM_DATABASE=LINKUP SYSTEMS CORPORATION -OUI:0002FF* - ID_OUI_FROM_DATABASE=Handan BroadInfoCom +OUI:00D065* + ID_OUI_FROM_DATABASE=TOKO ELECTRIC -OUI:0002F3* - ID_OUI_FROM_DATABASE=Media Serve Co., Ltd. +OUI:00D08F* + ID_OUI_FROM_DATABASE=ARDENT TECHNOLOGIES, INC. -OUI:0002FA* - ID_OUI_FROM_DATABASE=DX Antenna Co., Ltd. +OUI:00D0E7* + ID_OUI_FROM_DATABASE=VCON TELECOMMUNICATION LTD. -OUI:0002ED* - ID_OUI_FROM_DATABASE=DXO Telecom Co., Ltd. +OUI:00D087* + ID_OUI_FROM_DATABASE=MICROFIRST INC. -OUI:0002E5* - ID_OUI_FROM_DATABASE=Timeware Ltd. +OUI:00D008* + ID_OUI_FROM_DATABASE=MACTELL CORPORATION -OUI:0002E8* - ID_OUI_FROM_DATABASE=E.D.&A. +OUI:003005* + ID_OUI_FROM_DATABASE=Fujitsu Siemens Computers -OUI:0002DC* - ID_OUI_FROM_DATABASE=Fujitsu General Limited +OUI:00304E* + ID_OUI_FROM_DATABASE=BUSTEC PRODUCTION LTD. -OUI:0002E1* - ID_OUI_FROM_DATABASE=Integrated Network Corporation +OUI:0030E0* + ID_OUI_FROM_DATABASE=OXFORD SEMICONDUCTOR LTD. -OUI:0002D5* - ID_OUI_FROM_DATABASE=ACR +OUI:0030A1* + ID_OUI_FROM_DATABASE=WEBGATE Inc. -OUI:0002CE* - ID_OUI_FROM_DATABASE=FoxJet, Inc. +OUI:00303D* + ID_OUI_FROM_DATABASE=IVA CORPORATION -OUI:00B0DB* - ID_OUI_FROM_DATABASE=Nextcell, Inc. +OUI:0030C3* + ID_OUI_FROM_DATABASE=FLUECKIGER ELEKTRONIK AG -OUI:00B08E* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:009047* + ID_OUI_FROM_DATABASE=GIGA FAST E. LTD. -OUI:00B01C* - ID_OUI_FROM_DATABASE=Westport Technologies +OUI:0090CB* + ID_OUI_FROM_DATABASE=Wireless OnLine, Inc. -OUI:00B02D* - ID_OUI_FROM_DATABASE=ViaGate Technologies, Inc. +OUI:00903F* + ID_OUI_FROM_DATABASE=AZTEC RADIOMEDIA -OUI:00B03B* - ID_OUI_FROM_DATABASE=HiQ Networks +OUI:001043* + ID_OUI_FROM_DATABASE=A2 CORPORATION -OUI:0030A9* - ID_OUI_FROM_DATABASE=Netiverse, Inc. +OUI:00108D* + ID_OUI_FROM_DATABASE=Johnson Controls, Inc. -OUI:00B0F0* - ID_OUI_FROM_DATABASE=CALY NETWORKS +OUI:00108E* + ID_OUI_FROM_DATABASE=HUGH SYMONS CONCEPT Technologies Ltd. -OUI:00B086* - ID_OUI_FROM_DATABASE=LocSoft Limited +OUI:001052* + ID_OUI_FROM_DATABASE=METTLER-TOLEDO (ALBSTADT) GMBH -OUI:0030C4* - ID_OUI_FROM_DATABASE=Canon Imaging Systems Inc. +OUI:00100E* + ID_OUI_FROM_DATABASE=MICRO LINEAR COPORATION -OUI:00309D* - ID_OUI_FROM_DATABASE=Nimble Microsystems, Inc. +OUI:0010D7* + ID_OUI_FROM_DATABASE=ARGOSY RESEARCH INC. -OUI:003037* - ID_OUI_FROM_DATABASE=Packard Bell Nec Services +OUI:001059* + ID_OUI_FROM_DATABASE=DIABLO RESEARCH CO. LLC -OUI:00302E* - ID_OUI_FROM_DATABASE=Hoft & Wessel AG +OUI:0010B6* + ID_OUI_FROM_DATABASE=ENTRATA COMMUNICATIONS CORP. -OUI:00301B* - ID_OUI_FROM_DATABASE=SHUTTLE, INC. +OUI:001019* + ID_OUI_FROM_DATABASE=SIRONA DENTAL SYSTEMS GmbH & Co. KG -OUI:003028* - ID_OUI_FROM_DATABASE=FASE Saldatura srl +OUI:001013* + ID_OUI_FROM_DATABASE=Kontron America, Inc. -OUI:0030FB* - ID_OUI_FROM_DATABASE=AZS Technology AG +OUI:0090A4* + ID_OUI_FROM_DATABASE=ALTIGA NETWORKS -OUI:003048* - ID_OUI_FROM_DATABASE=Supermicro Computer, Inc. +OUI:00906C* + ID_OUI_FROM_DATABASE=Sartorius Hamburg GmbH -OUI:0001DA* - ID_OUI_FROM_DATABASE=WINCOMM Corporation +OUI:0090FC* + ID_OUI_FROM_DATABASE=NETWORK COMPUTING DEVICES -OUI:0001E1* - ID_OUI_FROM_DATABASE=Kinpo Electronics, Inc. +OUI:0090A3* + ID_OUI_FROM_DATABASE=Corecess Inc. -OUI:0001DD* - ID_OUI_FROM_DATABASE=Avail Networks +OUI:009022* + ID_OUI_FROM_DATABASE=IVEX -OUI:0001CE* - ID_OUI_FROM_DATABASE=Custom Micro Products, Ltd. +OUI:0090A5* + ID_OUI_FROM_DATABASE=SPECTRA LOGIC -OUI:0001CA* - ID_OUI_FROM_DATABASE=Geocast Network Systems, Inc. +OUI:0090BA* + ID_OUI_FROM_DATABASE=VALID NETWORKS, INC. -OUI:0001B8* - ID_OUI_FROM_DATABASE=Netsensity, Inc. +OUI:0090EE* + ID_OUI_FROM_DATABASE=PERSONAL COMMUNICATIONS TECHNOLOGIES -OUI:0001BD* - ID_OUI_FROM_DATABASE=Peterson Electro-Musical Products, Inc. +OUI:0090CD* + ID_OUI_FROM_DATABASE=ENT-EMPRESA NACIONAL DE TELECOMMUNICACOES, S.A. -OUI:0001B4* - ID_OUI_FROM_DATABASE=Wayport, Inc. +OUI:0090D0* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium -OUI:0001C3* - ID_OUI_FROM_DATABASE=Acromag, Inc. +OUI:009075* + ID_OUI_FROM_DATABASE=NEC DO BRASIL S.A. -OUI:0001BF* - ID_OUI_FROM_DATABASE=Teleforce Co., Ltd. +OUI:00902E* + ID_OUI_FROM_DATABASE=NAMCO LIMITED -OUI:0001AD* - ID_OUI_FROM_DATABASE=Coach Master International d.b.a. CMI Worldwide, Inc. +OUI:0090A0* + ID_OUI_FROM_DATABASE=8X8 INC. -OUI:00017E* - ID_OUI_FROM_DATABASE=ADTEK System Science Co., Ltd. +OUI:00907C* + ID_OUI_FROM_DATABASE=DIGITALCAST, INC. -OUI:00018A* - ID_OUI_FROM_DATABASE=ROI COMPUTER AG +OUI:0090DF* + ID_OUI_FROM_DATABASE=MITSUBISHI CHEMICAL AMERICA, INC. -OUI:000119* - ID_OUI_FROM_DATABASE=RTUnet (Australia) +OUI:009023* + ID_OUI_FROM_DATABASE=ZILOG INC. -OUI:000125* - ID_OUI_FROM_DATABASE=YAESU MUSEN CO., LTD. +OUI:00908A* + ID_OUI_FROM_DATABASE=BAYLY COMMUNICATIONS, INC. -OUI:000121* - ID_OUI_FROM_DATABASE=Watchguard Technologies, Inc. +OUI:009063* + ID_OUI_FROM_DATABASE=COHERENT COMMUNICATIONS SYSTEMS CORPORATION -OUI:000128* - ID_OUI_FROM_DATABASE=EnjoyWeb, Inc. +OUI:009041* + ID_OUI_FROM_DATABASE=APPLIED DIGITAL ACCESS -OUI:000106* - ID_OUI_FROM_DATABASE=Tews Datentechnik GmbH +OUI:0090D8* + ID_OUI_FROM_DATABASE=WHITECROSS SYSTEMS -OUI:000112* - ID_OUI_FROM_DATABASE=Shark Multimedia Inc. +OUI:009011* + ID_OUI_FROM_DATABASE=WAVTrace, Inc. -OUI:000102* - ID_OUI_FROM_DATABASE=3COM CORPORATION +OUI:009040* + ID_OUI_FROM_DATABASE=Siemens Network Convergence LLC -OUI:000115* - ID_OUI_FROM_DATABASE=EXTRATECH CORPORATION +OUI:0090C7* + ID_OUI_FROM_DATABASE=ICOM INC. -OUI:000109* - ID_OUI_FROM_DATABASE=Nagano Japan Radio Co., Ltd. +OUI:009035* + ID_OUI_FROM_DATABASE=ALPHA TELECOM, INC. -OUI:081443* - ID_OUI_FROM_DATABASE=UNIBRAIN S.A. +OUI:009087* + ID_OUI_FROM_DATABASE=ITIS -OUI:00B0F5* - ID_OUI_FROM_DATABASE=NetWorth Technologies, Inc. +OUI:00906E* + ID_OUI_FROM_DATABASE=PRAXON, INC. -OUI:00B019* - ID_OUI_FROM_DATABASE=UTC CCS +OUI:009039* + ID_OUI_FROM_DATABASE=SHASTA NETWORKS -OUI:00B02A* - ID_OUI_FROM_DATABASE=ORSYS GmbH +OUI:00909A* + ID_OUI_FROM_DATABASE=ONE WORLD SYSTEMS, INC. -OUI:00B0AE* - ID_OUI_FROM_DATABASE=Symmetricom +OUI:009053* + ID_OUI_FROM_DATABASE=DAEWOO ELECTRONICS CO., LTD. -OUI:000181* - ID_OUI_FROM_DATABASE=Nortel Networks +OUI:00909E* + ID_OUI_FROM_DATABASE=Critical IO, LLC -OUI:00018D* - ID_OUI_FROM_DATABASE=AudeSi Technologies +OUI:0090C2* + ID_OUI_FROM_DATABASE=JK microsystems, Inc. -OUI:00019A* - ID_OUI_FROM_DATABASE=LEUNIG GmbH +OUI:009091* + ID_OUI_FROM_DATABASE=DigitalScape, Inc. -OUI:000193* - ID_OUI_FROM_DATABASE=Hanbyul Telecom Co., Ltd. +OUI:0090ED* + ID_OUI_FROM_DATABASE=CENTRAL SYSTEM RESEARCH CO., LTD. -OUI:0001A2* - ID_OUI_FROM_DATABASE=Logical Co., Ltd. +OUI:00901B* + ID_OUI_FROM_DATABASE=DIGITAL CONTROLS -OUI:000196* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00905C* + ID_OUI_FROM_DATABASE=EDMI -OUI:0001A6* - ID_OUI_FROM_DATABASE=Scientific-Atlanta Arcodan A/S +OUI:0090D2* + ID_OUI_FROM_DATABASE=ARTEL VIDEO SYSTEMS -OUI:000172* - ID_OUI_FROM_DATABASE=TechnoLand Co., LTD. +OUI:00508C* + ID_OUI_FROM_DATABASE=RSI SYSTEMS -OUI:00303F* - ID_OUI_FROM_DATABASE=TurboComm Tech Inc. +OUI:00502D* + ID_OUI_FROM_DATABASE=ACCEL, INC. -OUI:003073* - ID_OUI_FROM_DATABASE=International Microsystems, In +OUI:0050B8* + ID_OUI_FROM_DATABASE=INOVA COMPUTERS GMBH & CO. KG -OUI:00014D* - ID_OUI_FROM_DATABASE=Shin Kin Enterprises Co., Ltd +OUI:00503A* + ID_OUI_FROM_DATABASE=DATONG ELECTRONICS LTD. -OUI:00016B* - ID_OUI_FROM_DATABASE=LightChip, Inc. +OUI:00508E* + ID_OUI_FROM_DATABASE=OPTIMATION, INC. -OUI:000167* - ID_OUI_FROM_DATABASE=HIOKI E.E. CORPORATION +OUI:0050BB* + ID_OUI_FROM_DATABASE=CMS TECHNOLOGIES -OUI:000215* - ID_OUI_FROM_DATABASE=Cotas Computer Technology A/B +OUI:005051* + ID_OUI_FROM_DATABASE=IWATSU ELECTRIC CO., LTD. -OUI:000211* - ID_OUI_FROM_DATABASE=Nature Worldwide Technology Corp. +OUI:0050BE* + ID_OUI_FROM_DATABASE=FAST MULTIMEDIA AG -OUI:000209* - ID_OUI_FROM_DATABASE=Shenzhen SED Information Technology Co., Ltd. +OUI:0050AD* + ID_OUI_FROM_DATABASE=CommUnique Wireless Corp. -OUI:000205* - ID_OUI_FROM_DATABASE=Hitachi Denshi, Ltd. +OUI:005003* + ID_OUI_FROM_DATABASE=Xrite Inc -OUI:000202* - ID_OUI_FROM_DATABASE=Amino Communications, Ltd. +OUI:005023* + ID_OUI_FROM_DATABASE=PG DESIGN ELECTRONICS, INC. -OUI:0001F6* - ID_OUI_FROM_DATABASE=Association of Musical Electronics Industry +OUI:005039* + ID_OUI_FROM_DATABASE=MARINER NETWORKS -OUI:0001ED* - ID_OUI_FROM_DATABASE=SETA Corp. +OUI:00505A* + ID_OUI_FROM_DATABASE=NETWORK ALCHEMY, INC. -OUI:0001E9* - ID_OUI_FROM_DATABASE=Litton Marine Systems B.V. +OUI:005071* + ID_OUI_FROM_DATABASE=AIWA CO., LTD. -OUI:0002C6* - ID_OUI_FROM_DATABASE=Data Track Technology PLC +OUI:009071* + ID_OUI_FROM_DATABASE=Applied Innovation Inc. -OUI:0002C2* - ID_OUI_FROM_DATABASE=Net Vision Telecom +OUI:009031* + ID_OUI_FROM_DATABASE=MYSTICOM, LTD. -OUI:0002B9* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00901F* + ID_OUI_FROM_DATABASE=ADTEC PRODUCTIONS, INC. -OUI:0002B4* - ID_OUI_FROM_DATABASE=DAPHNE +OUI:009081* + ID_OUI_FROM_DATABASE=ALOHA NETWORKS, INC. -OUI:0002AD* - ID_OUI_FROM_DATABASE=HOYA Corporation +OUI:0090B3* + ID_OUI_FROM_DATABASE=AGRANAT SYSTEMS -OUI:0002A6* - ID_OUI_FROM_DATABASE=Effinet Systems Co., Ltd. +OUI:00500D* + ID_OUI_FROM_DATABASE=SATORI ELECTORIC CO., LTD. -OUI:0002A1* - ID_OUI_FROM_DATABASE=World Wide Packets +OUI:0050EC* + ID_OUI_FROM_DATABASE=OLICOM A/S -OUI:00029B* - ID_OUI_FROM_DATABASE=Kreatel Communications AB +OUI:005083* + ID_OUI_FROM_DATABASE=GILBARCO, INC. -OUI:00029E* - ID_OUI_FROM_DATABASE=Information Equipment Co., Ltd. +OUI:0050CF* + ID_OUI_FROM_DATABASE=VANLINK COMMUNICATION TECHNOLOGY RESEARCH INSTITUTE -OUI:000296* - ID_OUI_FROM_DATABASE=Lectron Co,. Ltd. +OUI:005008* + ID_OUI_FROM_DATABASE=TIVA MICROCOMPUTER CORP. (TMC) -OUI:00028F* - ID_OUI_FROM_DATABASE=Globetek, Inc. +OUI:005001* + ID_OUI_FROM_DATABASE=YAMASHITA SYSTEMS CORP. -OUI:000289* - ID_OUI_FROM_DATABASE=DNE Technologies +OUI:0050B5* + ID_OUI_FROM_DATABASE=FICHET-BAUCHE -OUI:000285* - ID_OUI_FROM_DATABASE=Riverstone Networks +OUI:0050B0* + ID_OUI_FROM_DATABASE=TECHNOLOGY ATLANTA CORPORATION -OUI:00027E* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00504E* + ID_OUI_FROM_DATABASE=SIERRA MONITOR CORP. -OUI:000280* - ID_OUI_FROM_DATABASE=Mu Net, Inc. +OUI:00504D* + ID_OUI_FROM_DATABASE=Tokyo Electron Device Limited -OUI:000279* - ID_OUI_FROM_DATABASE=Control Applications, Ltd. +OUI:0050F7* + ID_OUI_FROM_DATABASE=VENTURE MANUFACTURING (SINGAPORE) LTD. -OUI:000272* - ID_OUI_FROM_DATABASE=CC&C Technologies, Inc. +OUI:005029* + ID_OUI_FROM_DATABASE=1394 PRINTER WORKING GROUP -OUI:00026B* - ID_OUI_FROM_DATABASE=BCM Computers Co., Ltd. +OUI:00E08D* + ID_OUI_FROM_DATABASE=PRESSURE SYSTEMS, INC. -OUI:00026D* - ID_OUI_FROM_DATABASE=Adept Telecom +OUI:00E040* + ID_OUI_FROM_DATABASE=DeskStation Technology, Inc. -OUI:000262* - ID_OUI_FROM_DATABASE=Soyo Group Soyo Com Tech Co., Ltd +OUI:00E0D6* + ID_OUI_FROM_DATABASE=COMPUTER & COMMUNICATION RESEARCH LAB. -OUI:000260* - ID_OUI_FROM_DATABASE=Accordion Networks, Inc. +OUI:00E07E* + ID_OUI_FROM_DATABASE=WALT DISNEY IMAGINEERING -OUI:00025B* - ID_OUI_FROM_DATABASE=Cambridge Silicon Radio +OUI:00E094* + ID_OUI_FROM_DATABASE=OSAI SRL -OUI:000087* - ID_OUI_FROM_DATABASE=HITACHI, LTD. +OUI:00E032* + ID_OUI_FROM_DATABASE=MISYS FINANCIAL SYSTEMS, LTD. -OUI:000252* - ID_OUI_FROM_DATABASE=Carrier Corporation +OUI:00E06B* + ID_OUI_FROM_DATABASE=W&G SPECIAL PRODUCTS -OUI:00024B* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00E01C* + ID_OUI_FROM_DATABASE=Cradlepoint, Inc -OUI:000246* - ID_OUI_FROM_DATABASE=All-Win Tech Co., Ltd. +OUI:00E076* + ID_OUI_FROM_DATABASE=DEVELOPMENT CONCEPTS, INC. -OUI:00017A* - ID_OUI_FROM_DATABASE=Chengdu Maipu Electric Industrial Co., Ltd. +OUI:00E0A7* + ID_OUI_FROM_DATABASE=IPC INFORMATION SYSTEMS, INC. -OUI:000235* - ID_OUI_FROM_DATABASE=Paragon Networks International +OUI:00E0A4* + ID_OUI_FROM_DATABASE=ESAOTE S.p.A. -OUI:000238* - ID_OUI_FROM_DATABASE=Serome Technology, Inc. +OUI:00E080* + ID_OUI_FROM_DATABASE=CONTROL RESOURCES CORPORATION -OUI:000230* - ID_OUI_FROM_DATABASE=Intersoft Electronics +OUI:00E0CC* + ID_OUI_FROM_DATABASE=HERO SYSTEMS, LTD. -OUI:000229* - ID_OUI_FROM_DATABASE=Adtec Corporation +OUI:00E099* + ID_OUI_FROM_DATABASE=SAMSON AG -OUI:000225* - ID_OUI_FROM_DATABASE=One Stop Systems +OUI:0010E9* + ID_OUI_FROM_DATABASE=RAIDTEC LTD. -OUI:00021C* - ID_OUI_FROM_DATABASE=Network Elements, Inc. +OUI:001003* + ID_OUI_FROM_DATABASE=IMATRON, INC. -OUI:000221* - ID_OUI_FROM_DATABASE=DSP Application, Ltd. +OUI:00105A* + ID_OUI_FROM_DATABASE=3COM CORPORATION -OUI:00016E* - ID_OUI_FROM_DATABASE=Conklin Corporation +OUI:0010A9* + ID_OUI_FROM_DATABASE=ADHOC TECHNOLOGIES -OUI:00015B* - ID_OUI_FROM_DATABASE=ITALTEL S.p.A/RF-UP-I +OUI:000400* + ID_OUI_FROM_DATABASE=LEXMARK INTERNATIONAL, INC. -OUI:000154* - ID_OUI_FROM_DATABASE=G3M Corporation +OUI:00101A* + ID_OUI_FROM_DATABASE=PictureTel Corp. -OUI:000150* - ID_OUI_FROM_DATABASE=GILAT COMMUNICATIONS, LTD. +OUI:001097* + ID_OUI_FROM_DATABASE=WinNet Metropolitan Communications Systems, Inc. -OUI:00012E* - ID_OUI_FROM_DATABASE=PC Partner Ltd. +OUI:00106F* + ID_OUI_FROM_DATABASE=TRENTON TECHNOLOGY INC. -OUI:00013A* - ID_OUI_FROM_DATABASE=SHELCAD COMMUNICATIONS, LTD. +OUI:0010DA* + ID_OUI_FROM_DATABASE=Kollmorgen Corp -OUI:000141* - ID_OUI_FROM_DATABASE=CABLE PRINT +OUI:0010DF* + ID_OUI_FROM_DATABASE=RISE COMPUTER INC. -OUI:000131* - ID_OUI_FROM_DATABASE=Bosch Security Systems, Inc. +OUI:00109E* + ID_OUI_FROM_DATABASE=AWARE, INC. -OUI:00013D* - ID_OUI_FROM_DATABASE=RiscStation Ltd. +OUI:001072* + ID_OUI_FROM_DATABASE=GVN TECHNOLOGIES, INC. -OUI:000149* - ID_OUI_FROM_DATABASE=T.D.T. Transfer Data Test GmbH +OUI:00E019* + ID_OUI_FROM_DATABASE=ING. GIORDANO ELETTRONICA -OUI:00D047* - ID_OUI_FROM_DATABASE=XN TECHNOLOGIES +OUI:00E0D7* + ID_OUI_FROM_DATABASE=SUNSHINE ELECTRONICS, INC. -OUI:00D018* - ID_OUI_FROM_DATABASE=QWES. COM, INC. +OUI:00E0DA* + ID_OUI_FROM_DATABASE=Alcatel North America ESD -OUI:00D048* - ID_OUI_FROM_DATABASE=ECTON, INC. +OUI:00E068* + ID_OUI_FROM_DATABASE=MERRIMAC SYSTEMS INC. -OUI:00D028* - ID_OUI_FROM_DATABASE=Harmonic, Inc +OUI:00E01D* + ID_OUI_FROM_DATABASE=WebTV NETWORKS, INC. -OUI:00D02F* - ID_OUI_FROM_DATABASE=VLSI TECHNOLOGY INC. +OUI:00E01F* + ID_OUI_FROM_DATABASE=AVIDIA Systems, Inc. -OUI:00D025* - ID_OUI_FROM_DATABASE=XROSSTECH, INC. +OUI:00E056* + ID_OUI_FROM_DATABASE=HOLONTECH CORPORATION -OUI:00D085* - ID_OUI_FROM_DATABASE=OTIS ELEVATOR COMPANY +OUI:00E0C9* + ID_OUI_FROM_DATABASE=AutomatedLogic Corporation -OUI:00D077* - ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES +OUI:00E030* + ID_OUI_FROM_DATABASE=MELITA INTERNATIONAL CORP. -OUI:00D093* - ID_OUI_FROM_DATABASE=TQ - COMPONENTS GMBH +OUI:00E0BA* + ID_OUI_FROM_DATABASE=BERGHOF AUTOMATIONSTECHNIK GmbH -OUI:00D013* - ID_OUI_FROM_DATABASE=PRIMEX AEROSPACE COMPANY +OUI:00E0B2* + ID_OUI_FROM_DATABASE=TELMAX COMMUNICATIONS CORP. -OUI:00D056* - ID_OUI_FROM_DATABASE=SOMAT CORPORATION +OUI:00E0EF* + ID_OUI_FROM_DATABASE=DIONEX -OUI:00D017* - ID_OUI_FROM_DATABASE=SYNTECH INFORMATION CO., LTD. +OUI:00E0BD* + ID_OUI_FROM_DATABASE=INTERFACE SYSTEMS, INC. -OUI:00D036* - ID_OUI_FROM_DATABASE=TECHNOLOGY ATLANTA CORP. +OUI:00E071* + ID_OUI_FROM_DATABASE=EPIS MICROCOMPUTER -OUI:00D0D6* - ID_OUI_FROM_DATABASE=AETHRA TELECOMUNICAZIONI +OUI:00E0A6* + ID_OUI_FROM_DATABASE=TELOGY NETWORKS, INC. -OUI:003078* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00E026* + ID_OUI_FROM_DATABASE=Redlake MASD LLC -OUI:003003* - ID_OUI_FROM_DATABASE=Phasys Ltd. +OUI:00E0B8* + ID_OUI_FROM_DATABASE=GATEWAY 2000 -OUI:0030D5* - ID_OUI_FROM_DATABASE=DResearch GmbH +OUI:00E088* + ID_OUI_FROM_DATABASE=LTX-Credence CORPORATION -OUI:0030CE* - ID_OUI_FROM_DATABASE=Zaffire +OUI:00E07C* + ID_OUI_FROM_DATABASE=METTLER-TOLEDO, INC. -OUI:003095* - ID_OUI_FROM_DATABASE=Procomp Informatics, Ltd. +OUI:00E08C* + ID_OUI_FROM_DATABASE=NEOPARADIGM LABS, INC. -OUI:003055* - ID_OUI_FROM_DATABASE=Renesas Technology America, Inc. +OUI:00E061* + ID_OUI_FROM_DATABASE=EdgePoint Networks, Inc. -OUI:0030B0* - ID_OUI_FROM_DATABASE=Convergenet Technologies +OUI:00E06E* + ID_OUI_FROM_DATABASE=FAR SYSTEMS S.p.A. -OUI:0030CC* - ID_OUI_FROM_DATABASE=Tenor Networks, Inc. +OUI:00E01B* + ID_OUI_FROM_DATABASE=SPHERE COMMUNICATIONS, INC. -OUI:003013* - ID_OUI_FROM_DATABASE=NEC Corporation +OUI:00E0AE* + ID_OUI_FROM_DATABASE=XAQTI CORPORATION -OUI:003061* - ID_OUI_FROM_DATABASE=MobyTEL +OUI:00E0C8* + ID_OUI_FROM_DATABASE=VIRTUAL ACCESS, LTD. -OUI:00D0AB* - ID_OUI_FROM_DATABASE=DELTAKABEL TELECOM CV +OUI:00101D* + ID_OUI_FROM_DATABASE=WINBOND ELECTRONICS CORP. -OUI:00D0A8* - ID_OUI_FROM_DATABASE=NETWORK ENGINES, INC. +OUI:00105F* + ID_OUI_FROM_DATABASE=ZODIAC DATA SYSTEMS -OUI:00D01C* - ID_OUI_FROM_DATABASE=SBS TECHNOLOGIES, +OUI:0010CB* + ID_OUI_FROM_DATABASE=FACIT K.K. -OUI:00D0C0* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:001075* + ID_OUI_FROM_DATABASE=Segate Technology LLC -OUI:00D051* - ID_OUI_FROM_DATABASE=O2 MICRO, INC. +OUI:001058* + ID_OUI_FROM_DATABASE=ArrowPoint Communications -OUI:00D06D* - ID_OUI_FROM_DATABASE=ACRISON, INC. +OUI:0010A8* + ID_OUI_FROM_DATABASE=RELIANCE COMPUTER CORP. -OUI:0050A1* - ID_OUI_FROM_DATABASE=CARLO GAVAZZI, INC. +OUI:0010AA* + ID_OUI_FROM_DATABASE=MEDIA4, INC. -OUI:00D06C* - ID_OUI_FROM_DATABASE=SHAREWAVE, INC. +OUI:0010E8* + ID_OUI_FROM_DATABASE=TELOCITY, INCORPORATED -OUI:00D03A* - ID_OUI_FROM_DATABASE=ZONEWORX, INC. +OUI:001010* + ID_OUI_FROM_DATABASE=INITIO CORPORATION -OUI:0050C1* - ID_OUI_FROM_DATABASE=GEMFLEX NETWORKS, LTD. +OUI:00E007* + ID_OUI_FROM_DATABASE=Avaya ECS Ltd -OUI:0050FB* - ID_OUI_FROM_DATABASE=VSK ELECTRONICS +OUI:001022* + ID_OUI_FROM_DATABASE=SatCom Media Corporation -OUI:005033* - ID_OUI_FROM_DATABASE=MAYAN NETWORKS +OUI:0010C7* + ID_OUI_FROM_DATABASE=DATA TRANSMISSION NETWORK -OUI:0030A0* - ID_OUI_FROM_DATABASE=TYCO SUBMARINE SYSTEMS, LTD. +OUI:001098* + ID_OUI_FROM_DATABASE=STARNET TECHNOLOGIES, INC. -OUI:0030CB* - ID_OUI_FROM_DATABASE=OMNI FLOW COMPUTERS, INC. +OUI:001096* + ID_OUI_FROM_DATABASE=TRACEWELL SYSTEMS, INC. -OUI:00306B* - ID_OUI_FROM_DATABASE=CMOS SYSTEMS, INC. +OUI:001082* + ID_OUI_FROM_DATABASE=JNA TELECOMMUNICATIONS LIMITED -OUI:003068* - ID_OUI_FROM_DATABASE=CYBERNETICS TECH. CO., LTD. +OUI:001021* + ID_OUI_FROM_DATABASE=ENCANTO NETWORKS, INC. -OUI:0030E3* - ID_OUI_FROM_DATABASE=SEDONA NETWORKS CORP. +OUI:0010CE* + ID_OUI_FROM_DATABASE=VOLAMP, LTD. -OUI:00D007* - ID_OUI_FROM_DATABASE=MIC ASSOCIATES, INC. +OUI:0010B2* + ID_OUI_FROM_DATABASE=COACTIVE AESTHETICS -OUI:00D07F* - ID_OUI_FROM_DATABASE=STRATEGY & TECHNOLOGY, LIMITED +OUI:00109A* + ID_OUI_FROM_DATABASE=NETLINE -OUI:003085* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0010EA* + ID_OUI_FROM_DATABASE=ADEPT TECHNOLOGY -OUI:003026* - ID_OUI_FROM_DATABASE=HeiTel Digital Video GmbH +OUI:0010BD* + ID_OUI_FROM_DATABASE=THE TELECOMMUNICATION TECHNOLOGY COMMITTEE (TTC) -OUI:0030A6* - ID_OUI_FROM_DATABASE=VIANET TECHNOLOGIES, LTD. +OUI:006099* + ID_OUI_FROM_DATABASE=SBE, Inc. -OUI:003047* - ID_OUI_FROM_DATABASE=NISSEI ELECTRIC CO., LTD. +OUI:0060FD* + ID_OUI_FROM_DATABASE=NetICs, Inc. -OUI:00D0FC* - ID_OUI_FROM_DATABASE=GRANITE MICROSYSTEMS +OUI:0060B5* + ID_OUI_FROM_DATABASE=KEBA GmbH -OUI:00D042* - ID_OUI_FROM_DATABASE=MAHLO GMBH & CO. UG +OUI:006027* + ID_OUI_FROM_DATABASE=Superior Modular Products -OUI:00D046* - ID_OUI_FROM_DATABASE=DOLBY LABORATORIES, INC. +OUI:0060C1* + ID_OUI_FROM_DATABASE=WaveSpan Corporation -OUI:00D0BA* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:006005* + ID_OUI_FROM_DATABASE=FEEDBACK DATA LTD. -OUI:00D0BC* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:00607B* + ID_OUI_FROM_DATABASE=FORE SYSTEMS, INC. -OUI:00D0D8* - ID_OUI_FROM_DATABASE=3Com Corporation +OUI:00609C* + ID_OUI_FROM_DATABASE=Perkin-Elmer Incorporated -OUI:00D06B* - ID_OUI_FROM_DATABASE=SR TELECOM INC. +OUI:006007* + ID_OUI_FROM_DATABASE=ACRES GAMING, INC. -OUI:0030AA* - ID_OUI_FROM_DATABASE=AXUS MICROSYSTEMS, INC. +OUI:006035* + ID_OUI_FROM_DATABASE=DALLAS SEMICONDUCTOR, INC. -OUI:003043* - ID_OUI_FROM_DATABASE=IDREAM TECHNOLOGIES, PTE. LTD. +OUI:0060F1* + ID_OUI_FROM_DATABASE=EXP COMPUTER, INC. -OUI:003010* - ID_OUI_FROM_DATABASE=VISIONETICS INTERNATIONAL +OUI:006040* + ID_OUI_FROM_DATABASE=NETRO CORP. -OUI:003096* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:006034* + ID_OUI_FROM_DATABASE=ROBERT BOSCH GmbH -OUI:003084* - ID_OUI_FROM_DATABASE=ALLIED TELESYN INTERNAIONAL +OUI:0060BA* + ID_OUI_FROM_DATABASE=SAHARA NETWORKS, INC. -OUI:0030CF* - ID_OUI_FROM_DATABASE=TWO TECHNOLOGIES, INC. +OUI:006096* + ID_OUI_FROM_DATABASE=T.S. MICROTECH INC. -OUI:00D0E3* - ID_OUI_FROM_DATABASE=ELE-CHEM ENGINEERING CO., LTD. +OUI:00603A* + ID_OUI_FROM_DATABASE=QUICK CONTROLS LTD. -OUI:00D0ED* - ID_OUI_FROM_DATABASE=XIOX +OUI:0060AC* + ID_OUI_FROM_DATABASE=RESILIENCE CORPORATION -OUI:00D0C2* - ID_OUI_FROM_DATABASE=BALTHAZAR TECHNOLOGY AB +OUI:0060EB* + ID_OUI_FROM_DATABASE=FOURTHTRACK SYSTEMS -OUI:00D0FB* - ID_OUI_FROM_DATABASE=TEK MICROSYSTEMS, INCORPORATED +OUI:00606D* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORP. -OUI:00D082* - ID_OUI_FROM_DATABASE=IOWAVE INC. +OUI:006014* + ID_OUI_FROM_DATABASE=EDEC CO., LTD. -OUI:00D0AD* - ID_OUI_FROM_DATABASE=TL INDUSTRIES +OUI:0060E1* + ID_OUI_FROM_DATABASE=ORCKIT COMMUNICATIONS LTD. -OUI:00D0DB* - ID_OUI_FROM_DATABASE=MCQUAY INTERNATIONAL +OUI:006062* + ID_OUI_FROM_DATABASE=TELESYNC, INC. -OUI:00D06A* - ID_OUI_FROM_DATABASE=LINKUP SYSTEMS CORPORATION +OUI:006038* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:00D065* - ID_OUI_FROM_DATABASE=TOKO ELECTRIC +OUI:006095* + ID_OUI_FROM_DATABASE=ACCU-TIME SYSTEMS, INC. -OUI:00D08F* - ID_OUI_FROM_DATABASE=ARDENT TECHNOLOGIES, INC. +OUI:00A016* + ID_OUI_FROM_DATABASE=MICROPOLIS CORP. -OUI:00D0E7* - ID_OUI_FROM_DATABASE=VCON TELECOMMUNICATION LTD. +OUI:00A01C* + ID_OUI_FROM_DATABASE=NASCENT NETWORKS CORPORATION -OUI:00D087* - ID_OUI_FROM_DATABASE=MICROFIRST INC. +OUI:00A0FC* + ID_OUI_FROM_DATABASE=IMAGE SCIENCES, INC. -OUI:00D008* - ID_OUI_FROM_DATABASE=MACTELL CORPORATION +OUI:00A0B7* + ID_OUI_FROM_DATABASE=CORDANT, INC. -OUI:003005* - ID_OUI_FROM_DATABASE=Fujitsu Siemens Computers +OUI:00A037* + ID_OUI_FROM_DATABASE=Mindray DS USA, Inc. -OUI:00304E* - ID_OUI_FROM_DATABASE=BUSTEC PRODUCTION LTD. +OUI:00A04C* + ID_OUI_FROM_DATABASE=INNOVATIVE SYSTEMS & TECHNOLOGIES, INC. -OUI:0030E0* - ID_OUI_FROM_DATABASE=OXFORD SEMICONDUCTOR LTD. +OUI:00A0E9* + ID_OUI_FROM_DATABASE=ELECTRONIC RETAILING SYSTEMS INTERNATIONAL -OUI:0030A1* - ID_OUI_FROM_DATABASE=WEBGATE Inc. +OUI:006078* + ID_OUI_FROM_DATABASE=POWER MEASUREMENT LTD. -OUI:00303D* - ID_OUI_FROM_DATABASE=IVA CORPORATION +OUI:00600D* + ID_OUI_FROM_DATABASE=Digital Logic GmbH -OUI:0030C3* - ID_OUI_FROM_DATABASE=FLUECKIGER ELEKTRONIK AG +OUI:00608A* + ID_OUI_FROM_DATABASE=CITADEL COMPUTER -OUI:009047* - ID_OUI_FROM_DATABASE=GIGA FAST E. LTD. +OUI:00A05D* + ID_OUI_FROM_DATABASE=CS COMPUTER SYSTEME GmbH -OUI:0090CB* - ID_OUI_FROM_DATABASE=Wireless OnLine, Inc. +OUI:00A0BD* + ID_OUI_FROM_DATABASE=I-TECH CORP. -OUI:00903F* - ID_OUI_FROM_DATABASE=AZTEC RADIOMEDIA +OUI:00A0B9* + ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGY, INC. -OUI:001043* - ID_OUI_FROM_DATABASE=A2 CORPORATION +OUI:00A069* + ID_OUI_FROM_DATABASE=Symmetricom, Inc. -OUI:00108D* - ID_OUI_FROM_DATABASE=Johnson Controls, Inc. +OUI:00A07A* + ID_OUI_FROM_DATABASE=ADVANCED PERIPHERALS TECHNOLOGIES, INC. -OUI:00108E* - ID_OUI_FROM_DATABASE=HUGH SYMONS CONCEPT Technologies Ltd. +OUI:00A04E* + ID_OUI_FROM_DATABASE=VOELKER TECHNOLOGIES, INC. -OUI:001052* - ID_OUI_FROM_DATABASE=METTLER-TOLEDO (ALBSTADT) GMBH +OUI:00A05A* + ID_OUI_FROM_DATABASE=KOFAX IMAGE PRODUCTS -OUI:00100E* - ID_OUI_FROM_DATABASE=MICRO LINEAR COPORATION +OUI:00A093* + ID_OUI_FROM_DATABASE=B/E AEROSPACE, Inc. -OUI:0010D7* - ID_OUI_FROM_DATABASE=ARGOSY RESEARCH INC. +OUI:00A0BF* + ID_OUI_FROM_DATABASE=WIRELESS DATA GROUP MOTOROLA -OUI:001059* - ID_OUI_FROM_DATABASE=DIABLO RESEARCH CO. LLC +OUI:00609F* + ID_OUI_FROM_DATABASE=PHAST CORPORATION -OUI:0010B6* - ID_OUI_FROM_DATABASE=ENTRATA COMMUNICATIONS CORP. +OUI:006067* + ID_OUI_FROM_DATABASE=ACER NETXUS INC. -OUI:001019* - ID_OUI_FROM_DATABASE=SIRONA DENTAL SYSTEMS GmbH & Co. KG +OUI:00600C* + ID_OUI_FROM_DATABASE=Eurotech Inc. -OUI:001013* - ID_OUI_FROM_DATABASE=Kontron America, Inc. +OUI:006025* + ID_OUI_FROM_DATABASE=ACTIVE IMAGING PLC -OUI:0090A4* - ID_OUI_FROM_DATABASE=ALTIGA NETWORKS +OUI:006071* + ID_OUI_FROM_DATABASE=MIDAS LAB, INC. -OUI:00906C* - ID_OUI_FROM_DATABASE=Sartorius Hamburg GmbH +OUI:0060A7* + ID_OUI_FROM_DATABASE=MICROSENS GmbH & CO. KG -OUI:0090FC* - ID_OUI_FROM_DATABASE=NETWORK COMPUTING DEVICES +OUI:0060FC* + ID_OUI_FROM_DATABASE=CONSERVATION THROUGH INNOVATION LTD. -OUI:0090A3* - ID_OUI_FROM_DATABASE=Corecess Inc. +OUI:0060D4* + ID_OUI_FROM_DATABASE=ELDAT COMMUNICATION LTD. -OUI:009022* - ID_OUI_FROM_DATABASE=IVEX +OUI:006085* + ID_OUI_FROM_DATABASE=Storage Concepts -OUI:0090A5* - ID_OUI_FROM_DATABASE=SPECTRA LOGIC +OUI:006018* + ID_OUI_FROM_DATABASE=STELLAR ONE CORPORATION -OUI:0090BA* - ID_OUI_FROM_DATABASE=VALID NETWORKS, INC. +OUI:00602B* + ID_OUI_FROM_DATABASE=PEAK AUDIO -OUI:0090EE* - ID_OUI_FROM_DATABASE=PERSONAL COMMUNICATIONS TECHNOLOGIES +OUI:00606F* + ID_OUI_FROM_DATABASE=CLARION CORPORATION OF AMERICA -OUI:0090CD* - ID_OUI_FROM_DATABASE=ENT-EMPRESA NACIONAL DE TELECOMMUNICACOES, S.A. +OUI:0060ED* + ID_OUI_FROM_DATABASE=RICARDO TEST AUTOMATION LTD. -OUI:0090D0* - ID_OUI_FROM_DATABASE=Thomson Telecom Belgium +OUI:0060F6* + ID_OUI_FROM_DATABASE=NEXTEST COMMUNICATIONS PRODUCTS, INC. -OUI:009075* - ID_OUI_FROM_DATABASE=NEC DO BRASIL S.A. +OUI:0060DD* + ID_OUI_FROM_DATABASE=MYRICOM, INC. -OUI:00902E* - ID_OUI_FROM_DATABASE=NAMCO LIMITED +OUI:006092* + ID_OUI_FROM_DATABASE=MICRO/SYS, INC. -OUI:0090A0* - ID_OUI_FROM_DATABASE=8X8 INC. +OUI:006080* + ID_OUI_FROM_DATABASE=MICROTRONIX DATACOM LTD. -OUI:00907C* - ID_OUI_FROM_DATABASE=DIGITALCAST, INC. +OUI:006068* + ID_OUI_FROM_DATABASE=Dialogic Corporation -OUI:0090DF* - ID_OUI_FROM_DATABASE=MITSUBISHI CHEMICAL AMERICA, INC. +OUI:0060DB* + ID_OUI_FROM_DATABASE=NTP ELEKTRONIK A/S -OUI:009023* - ID_OUI_FROM_DATABASE=ZILOG INC. +OUI:00A002* + ID_OUI_FROM_DATABASE=LEEDS & NORTHRUP AUSTRALIA PTY LTD -OUI:00908A* - ID_OUI_FROM_DATABASE=BAYLY COMMUNICATIONS, INC. +OUI:00A0E4* + ID_OUI_FROM_DATABASE=OPTIQUEST -OUI:009063* - ID_OUI_FROM_DATABASE=COHERENT COMMUNICATIONS SYSTEMS CORPORATION +OUI:00A01F* + ID_OUI_FROM_DATABASE=TRICORD SYSTEMS, INC. -OUI:009041* - ID_OUI_FROM_DATABASE=APPLIED DIGITAL ACCESS +OUI:00A0C0* + ID_OUI_FROM_DATABASE=DIGITAL LINK CORP. -OUI:0090D8* - ID_OUI_FROM_DATABASE=WHITECROSS SYSTEMS +OUI:00A043* + ID_OUI_FROM_DATABASE=AMERICAN TECHNOLOGY LABS, INC. -OUI:009011* - ID_OUI_FROM_DATABASE=WAVTrace, Inc. +OUI:00A047* + ID_OUI_FROM_DATABASE=INTEGRATED FITNESS CORP. -OUI:009040* - ID_OUI_FROM_DATABASE=Siemens Network Convergence LLC +OUI:00A07C* + ID_OUI_FROM_DATABASE=TONYANG NYLON CO., LTD. -OUI:0090C7* - ID_OUI_FROM_DATABASE=ICOM INC. +OUI:00A0EC* + ID_OUI_FROM_DATABASE=TRANSMITTON LTD. -OUI:009035* - ID_OUI_FROM_DATABASE=ALPHA TELECOM, INC. +OUI:00A07E* + ID_OUI_FROM_DATABASE=AVID TECHNOLOGY, INC. -OUI:009087* - ID_OUI_FROM_DATABASE=ITIS +OUI:00A035* + ID_OUI_FROM_DATABASE=CYLINK CORPORATION -OUI:00906E* - ID_OUI_FROM_DATABASE=PRAXON, INC. +OUI:00A028* + ID_OUI_FROM_DATABASE=CONNER PERIPHERALS -OUI:009039* - ID_OUI_FROM_DATABASE=SHASTA NETWORKS +OUI:00A0C7* + ID_OUI_FROM_DATABASE=TADIRAN TELECOMMUNICATIONS -OUI:00909A* - ID_OUI_FROM_DATABASE=ONE WORLD SYSTEMS, INC. +OUI:00E0BE* + ID_OUI_FROM_DATABASE=GENROCO INTERNATIONAL, INC. -OUI:009053* - ID_OUI_FROM_DATABASE=DAEWOO ELECTRONICS CO., LTD. +OUI:00E010* + ID_OUI_FROM_DATABASE=HESS SB-AUTOMATENBAU GmbH -OUI:00909E* - ID_OUI_FROM_DATABASE=Critical IO, LLC +OUI:00E0E9* + ID_OUI_FROM_DATABASE=DATA LABS, INC. -OUI:0090C2* - ID_OUI_FROM_DATABASE=JK microsystems, Inc. +OUI:00E0A0* + ID_OUI_FROM_DATABASE=WILTRON CO. -OUI:009091* - ID_OUI_FROM_DATABASE=DigitalScape, Inc. +OUI:00E024* + ID_OUI_FROM_DATABASE=GADZOOX NETWORKS -OUI:0090ED* - ID_OUI_FROM_DATABASE=CENTRAL SYSTEM RESEARCH CO., LTD. +OUI:00E017* + ID_OUI_FROM_DATABASE=EXXACT GmbH -OUI:00901B* - ID_OUI_FROM_DATABASE=DIGITAL CONTROLS +OUI:00603B* + ID_OUI_FROM_DATABASE=AMTEC spa -OUI:00905C* - ID_OUI_FROM_DATABASE=EDMI +OUI:0020E5* + ID_OUI_FROM_DATABASE=APEX DATA, INC. -OUI:0090D2* - ID_OUI_FROM_DATABASE=ARTEL VIDEO SYSTEMS +OUI:00207D* + ID_OUI_FROM_DATABASE=ADVANCED COMPUTER APPLICATIONS -OUI:00508C* - ID_OUI_FROM_DATABASE=RSI SYSTEMS +OUI:0020D0* + ID_OUI_FROM_DATABASE=VERSALYNX CORPORATION -OUI:00502D* - ID_OUI_FROM_DATABASE=ACCEL, INC. +OUI:00206C* + ID_OUI_FROM_DATABASE=EVERGREEN TECHNOLOGY CORP. -OUI:0050B8* - ID_OUI_FROM_DATABASE=INOVA COMPUTERS GMBH & CO. KG +OUI:002012* + ID_OUI_FROM_DATABASE=CAMTRONICS MEDICAL SYSTEMS -OUI:00503A* - ID_OUI_FROM_DATABASE=DATONG ELECTRONICS LTD. +OUI:00200B* + ID_OUI_FROM_DATABASE=OCTAGON SYSTEMS CORP. -OUI:00508E* - ID_OUI_FROM_DATABASE=OPTIMATION, INC. +OUI:00209E* + ID_OUI_FROM_DATABASE=BROWN'S OPERATING SYSTEM SERVICES, LTD. -OUI:0050BB* - ID_OUI_FROM_DATABASE=CMS TECHNOLOGIES +OUI:0020D7* + ID_OUI_FROM_DATABASE=JAPAN MINICOMPUTER SYSTEMS CO., Ltd. -OUI:005051* - ID_OUI_FROM_DATABASE=IWATSU ELECTRIC CO., LTD. +OUI:0020FB* + ID_OUI_FROM_DATABASE=OCTEL COMMUNICATIONS CORP. -OUI:0050BE* - ID_OUI_FROM_DATABASE=FAST MULTIMEDIA AG +OUI:0020B1* + ID_OUI_FROM_DATABASE=COMTECH RESEARCH INC. -OUI:0050AD* - ID_OUI_FROM_DATABASE=CommUnique Wireless Corp. +OUI:002033* + ID_OUI_FROM_DATABASE=SYNAPSE TECHNOLOGIES, INC. -OUI:005016* - ID_OUI_FROM_DATABASE=SST/WOODHEAD INDUSTRIES +OUI:002099* + ID_OUI_FROM_DATABASE=BON ELECTRIC CO., LTD. -OUI:005003* - ID_OUI_FROM_DATABASE=Xrite Inc +OUI:0020AE* + ID_OUI_FROM_DATABASE=ORNET DATA COMMUNICATION TECH. -OUI:005023* - ID_OUI_FROM_DATABASE=PG DESIGN ELECTRONICS, INC. +OUI:0020EA* + ID_OUI_FROM_DATABASE=EFFICIENT NETWORKS, INC. -OUI:005039* - ID_OUI_FROM_DATABASE=MARINER NETWORKS +OUI:0020FF* + ID_OUI_FROM_DATABASE=SYMMETRICAL TECHNOLOGIES -OUI:00505A* - ID_OUI_FROM_DATABASE=NETWORK ALCHEMY, INC. +OUI:00208B* + ID_OUI_FROM_DATABASE=LAPIS TECHNOLOGIES, INC. -OUI:005071* - ID_OUI_FROM_DATABASE=AIWA CO., LTD. +OUI:002069* + ID_OUI_FROM_DATABASE=ISDN SYSTEMS CORPORATION -OUI:009071* - ID_OUI_FROM_DATABASE=Applied Innovation Inc. +OUI:0020BA* + ID_OUI_FROM_DATABASE=CENTER FOR HIGH PERFORMANCE -OUI:009031* - ID_OUI_FROM_DATABASE=MYSTICOM, LTD. +OUI:002006* + ID_OUI_FROM_DATABASE=GARRETT COMMUNICATIONS, INC. -OUI:00901F* - ID_OUI_FROM_DATABASE=ADTEC PRODUCTIONS, INC. +OUI:00A0A2* + ID_OUI_FROM_DATABASE=DIGICOM S.P.A. -OUI:009081* - ID_OUI_FROM_DATABASE=ALOHA NETWORKS, INC. +OUI:00A054* + ID_OUI_FROM_DATABASE=Private -OUI:0090B3* - ID_OUI_FROM_DATABASE=AGRANAT SYSTEMS +OUI:00A030* + ID_OUI_FROM_DATABASE=CAPTOR NV/SA -OUI:00500D* - ID_OUI_FROM_DATABASE=SATORI ELECTORIC CO., LTD. +OUI:00A0B1* + ID_OUI_FROM_DATABASE=FIRST VIRTUAL CORPORATION -OUI:0050EC* - ID_OUI_FROM_DATABASE=OLICOM A/S +OUI:0020CB* + ID_OUI_FROM_DATABASE=PRETEC ELECTRONICS CORP. -OUI:005083* - ID_OUI_FROM_DATABASE=GILBARCO, INC. +OUI:0020AB* + ID_OUI_FROM_DATABASE=MICRO INDUSTRIES CORP. -OUI:0050CF* - ID_OUI_FROM_DATABASE=VANLINK COMMUNICATION TECHNOLOGY RESEARCH INSTITUTE +OUI:00202D* + ID_OUI_FROM_DATABASE=TAIYO CORPORATION -OUI:005008* - ID_OUI_FROM_DATABASE=TIVA MICROCOMPUTER CORP. (TMC) +OUI:00A088* + ID_OUI_FROM_DATABASE=ESSENTIAL COMMUNICATIONS -OUI:005001* - ID_OUI_FROM_DATABASE=YAMASHITA SYSTEMS CORP. +OUI:00A0FA* + ID_OUI_FROM_DATABASE=Marconi Communication GmbH -OUI:0050B5* - ID_OUI_FROM_DATABASE=FICHET-BAUCHE +OUI:00A014* + ID_OUI_FROM_DATABASE=CSIR -OUI:0050B0* - ID_OUI_FROM_DATABASE=TECHNOLOGY ATLANTA CORPORATION +OUI:00A064* + ID_OUI_FROM_DATABASE=KVB/ANALECT -OUI:00504E* - ID_OUI_FROM_DATABASE=SIERRA MONITOR CORP. +OUI:00A07F* + ID_OUI_FROM_DATABASE=GSM-SYNTEL, LTD. -OUI:00504D* - ID_OUI_FROM_DATABASE=Tokyo Electron Device Limited +OUI:00A03E* + ID_OUI_FROM_DATABASE=ATM FORUM -OUI:0050F7* - ID_OUI_FROM_DATABASE=VENTURE MANUFACTURING (SINGAPORE) LTD. +OUI:00A050* + ID_OUI_FROM_DATABASE=CYPRESS SEMICONDUCTOR -OUI:005029* - ID_OUI_FROM_DATABASE=1394 PRINTER WORKING GROUP +OUI:00A098* + ID_OUI_FROM_DATABASE=NetApp -OUI:00E08D* - ID_OUI_FROM_DATABASE=PRESSURE SYSTEMS, INC. +OUI:00A021* + ID_OUI_FROM_DATABASE=General Dynamics -OUI:00E040* - ID_OUI_FROM_DATABASE=DeskStation Technology, Inc. +OUI:00A0A8* + ID_OUI_FROM_DATABASE=RENEX CORPORATION -OUI:00E0D6* - ID_OUI_FROM_DATABASE=COMPUTER & COMMUNICATION RESEARCH LAB. +OUI:002049* + ID_OUI_FROM_DATABASE=COMTRON, INC. -OUI:00E07E* - ID_OUI_FROM_DATABASE=WALT DISNEY IMAGINEERING +OUI:002050* + ID_OUI_FROM_DATABASE=KOREA COMPUTER INC. -OUI:00E094* - ID_OUI_FROM_DATABASE=OSAI SRL +OUI:00203C* + ID_OUI_FROM_DATABASE=EUROTIME AB -OUI:00E032* - ID_OUI_FROM_DATABASE=MISYS FINANCIAL SYSTEMS, LTD. +OUI:002028* + ID_OUI_FROM_DATABASE=WEST EGG SYSTEMS, INC. -OUI:00E06B* - ID_OUI_FROM_DATABASE=W&G SPECIAL PRODUCTS +OUI:002014* + ID_OUI_FROM_DATABASE=GLOBAL VIEW CO., LTD. -OUI:00E01C* - ID_OUI_FROM_DATABASE=Cradlepoint, Inc +OUI:002053* + ID_OUI_FROM_DATABASE=HUNTSVILLE MICROSYSTEMS, INC. -OUI:00E076* - ID_OUI_FROM_DATABASE=DEVELOPMENT CONCEPTS, INC. +OUI:002001* + ID_OUI_FROM_DATABASE=DSP SOLUTIONS, INC. -OUI:00E0A7* - ID_OUI_FROM_DATABASE=IPC INFORMATION SYSTEMS, INC. +OUI:00209C* + ID_OUI_FROM_DATABASE=PRIMARY ACCESS CORP. -OUI:00E0A4* - ID_OUI_FROM_DATABASE=ESAOTE S.p.A. +OUI:0020C5* + ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGY -OUI:00E080* - ID_OUI_FROM_DATABASE=CONTROL RESOURCES CORPORATION +OUI:002009* + ID_OUI_FROM_DATABASE=PACKARD BELL ELEC., INC. -OUI:00E0CC* - ID_OUI_FROM_DATABASE=HERO SYSTEMS, LTD. +OUI:002095* + ID_OUI_FROM_DATABASE=RIVA ELECTRONICS -OUI:00E099* - ID_OUI_FROM_DATABASE=SAMSON AG +OUI:00203F* + ID_OUI_FROM_DATABASE=JUKI CORPORATION -OUI:0010E9* - ID_OUI_FROM_DATABASE=RAIDTEC LTD. +OUI:00C014* + ID_OUI_FROM_DATABASE=TELEMATICS CALABASAS INT'L,INC -OUI:001003* - ID_OUI_FROM_DATABASE=IMATRON, INC. +OUI:00C045* + ID_OUI_FROM_DATABASE=ISOLATION SYSTEMS, LTD. -OUI:00105A* - ID_OUI_FROM_DATABASE=3COM CORPORATION +OUI:00C000* + ID_OUI_FROM_DATABASE=LANOPTICS, LTD. -OUI:0010A9* - ID_OUI_FROM_DATABASE=ADHOC TECHNOLOGIES +OUI:00AA3C* + ID_OUI_FROM_DATABASE=OLIVETTI TELECOM SPA (OLTECO) -OUI:000400* - ID_OUI_FROM_DATABASE=LEXMARK INTERNATIONAL, INC. +OUI:00C079* + ID_OUI_FROM_DATABASE=FONSYS CO.,LTD. -OUI:00101A* - ID_OUI_FROM_DATABASE=PictureTel Corp. +OUI:002011* + ID_OUI_FROM_DATABASE=CANOPUS CO., LTD. -OUI:001097* - ID_OUI_FROM_DATABASE=WinNet Metropolitan Communications Systems, Inc. +OUI:00C00B* + ID_OUI_FROM_DATABASE=NORCONTROL A.S. -OUI:00106F* - ID_OUI_FROM_DATABASE=TRENTON TECHNOLOGY INC. +OUI:00C0C0* + ID_OUI_FROM_DATABASE=SHORE MICROSYSTEMS, INC. -OUI:0010DA* - ID_OUI_FROM_DATABASE=Kollmorgen Corp +OUI:00C00C* + ID_OUI_FROM_DATABASE=RELIA TECHNOLGIES + +OUI:00A0E7* + ID_OUI_FROM_DATABASE=CENTRAL DATA CORPORATION -OUI:0010DF* - ID_OUI_FROM_DATABASE=RISE COMPUTER INC. +OUI:00A068* + ID_OUI_FROM_DATABASE=BHP LIMITED -OUI:00109E* - ID_OUI_FROM_DATABASE=AWARE, INC. +OUI:00A0B3* + ID_OUI_FROM_DATABASE=ZYKRONIX -OUI:001072* - ID_OUI_FROM_DATABASE=GVN TECHNOLOGIES, INC. +OUI:00A06E* + ID_OUI_FROM_DATABASE=AUSTRON, INC. -OUI:00E019* - ID_OUI_FROM_DATABASE=ING. GIORDANO ELETTRONICA +OUI:00A0BB* + ID_OUI_FROM_DATABASE=HILAN GMBH -OUI:00E0D7* - ID_OUI_FROM_DATABASE=SUNSHINE ELECTRONICS, INC. +OUI:00A017* + ID_OUI_FROM_DATABASE=J B M CORPORATION -OUI:00E0DA* - ID_OUI_FROM_DATABASE=Alcatel North America ESD +OUI:0020D5* + ID_OUI_FROM_DATABASE=VIPA GMBH -OUI:00E068* - ID_OUI_FROM_DATABASE=MERRIMAC SYSTEMS INC. +OUI:002079* + ID_OUI_FROM_DATABASE=MIKRON GMBH -OUI:00E01D* - ID_OUI_FROM_DATABASE=WebTV NETWORKS, INC. +OUI:0020FA* + ID_OUI_FROM_DATABASE=GDE SYSTEMS, INC. -OUI:00E01F* - ID_OUI_FROM_DATABASE=AVIDIA Systems, Inc. +OUI:002007* + ID_OUI_FROM_DATABASE=SFA, INC. -OUI:00E056* - ID_OUI_FROM_DATABASE=HOLONTECH CORPORATION +OUI:002062* + ID_OUI_FROM_DATABASE=SCORPION LOGIC, LTD. -OUI:00E0C9* - ID_OUI_FROM_DATABASE=AutomatedLogic Corporation +OUI:00200A* + ID_OUI_FROM_DATABASE=SOURCE-COMM CORP. -OUI:00E030* - ID_OUI_FROM_DATABASE=MELITA INTERNATIONAL CORP. +OUI:002000* + ID_OUI_FROM_DATABASE=LEXMARK INTERNATIONAL, INC. -OUI:00E0BA* - ID_OUI_FROM_DATABASE=BERGHOF AUTOMATIONSTECHNIK GmbH +OUI:002003* + ID_OUI_FROM_DATABASE=PIXEL POWER LTD. -OUI:00E0B2* - ID_OUI_FROM_DATABASE=TELMAX COMMUNICATIONS CORP. +OUI:0020B4* + ID_OUI_FROM_DATABASE=TERMA ELEKTRONIK AS -OUI:00E0EF* - ID_OUI_FROM_DATABASE=DIONEX +OUI:00205B* + ID_OUI_FROM_DATABASE=Kentrox, LLC -OUI:00E0BD* - ID_OUI_FROM_DATABASE=INTERFACE SYSTEMS, INC. +OUI:002030* + ID_OUI_FROM_DATABASE=ANALOG & DIGITAL SYSTEMS -OUI:00E071* - ID_OUI_FROM_DATABASE=EPIS MICROCOMPUTER +OUI:0020A8* + ID_OUI_FROM_DATABASE=SAST TECHNOLOGY CORP. -OUI:00E0A6* - ID_OUI_FROM_DATABASE=TELOGY NETWORKS, INC. +OUI:002066* + ID_OUI_FROM_DATABASE=GENERAL MAGIC, INC. -OUI:00E026* - ID_OUI_FROM_DATABASE=Redlake MASD LLC +OUI:002036* + ID_OUI_FROM_DATABASE=BMC SOFTWARE -OUI:00E0B8* - ID_OUI_FROM_DATABASE=GATEWAY 2000 +OUI:0040BE* + ID_OUI_FROM_DATABASE=BOEING DEFENSE & SPACE -OUI:00E088* - ID_OUI_FROM_DATABASE=LTX-Credence CORPORATION +OUI:004036* + ID_OUI_FROM_DATABASE=Zoom Telephonics, Inc -OUI:00E07C* - ID_OUI_FROM_DATABASE=METTLER-TOLEDO, INC. +OUI:004046* + ID_OUI_FROM_DATABASE=UDC RESEARCH LIMITED -OUI:00E08C* - ID_OUI_FROM_DATABASE=NEOPARADIGM LABS, INC. +OUI:00406A* + ID_OUI_FROM_DATABASE=KENTEK INFORMATION SYSTEMS,INC -OUI:00E061* - ID_OUI_FROM_DATABASE=EdgePoint Networks, Inc. +OUI:0040F2* + ID_OUI_FROM_DATABASE=JANICH & KLASS COMPUTERTECHNIK -OUI:00E06E* - ID_OUI_FROM_DATABASE=FAR SYSTEMS S.p.A. +OUI:004082* + ID_OUI_FROM_DATABASE=LABORATORY EQUIPMENT CORP. -OUI:00E01B* - ID_OUI_FROM_DATABASE=SPHERE COMMUNICATIONS, INC. +OUI:004022* + ID_OUI_FROM_DATABASE=KLEVER COMPUTERS, INC. -OUI:00E0AE* - ID_OUI_FROM_DATABASE=XAQTI CORPORATION +OUI:0040A2* + ID_OUI_FROM_DATABASE=KINGSTAR TECHNOLOGY INC. -OUI:00E0C8* - ID_OUI_FROM_DATABASE=VIRTUAL ACCESS, LTD. +OUI:0040B4* + ID_OUI_FROM_DATABASE=NEXTCOM K.K. -OUI:00101D* - ID_OUI_FROM_DATABASE=WINBOND ELECTRONICS CORP. +OUI:0040D4* + ID_OUI_FROM_DATABASE=GAGE TALKER CORP. -OUI:00105F* - ID_OUI_FROM_DATABASE=ZODIAC DATA SYSTEMS +OUI:004038* + ID_OUI_FROM_DATABASE=TALENT ELECTRIC INCORPORATED -OUI:0010CB* - ID_OUI_FROM_DATABASE=FACIT K.K. +OUI:004018* + ID_OUI_FROM_DATABASE=ADOBE SYSTEMS, INC. -OUI:00108C* - ID_OUI_FROM_DATABASE=FUJITSU TELECOMMUNICATIONS EUROPE, LTD. +OUI:0040B0* + ID_OUI_FROM_DATABASE=BYTEX CORPORATION, ENGINEERING -OUI:001075* - ID_OUI_FROM_DATABASE=Segate Technology LLC +OUI:004040* + ID_OUI_FROM_DATABASE=RING ACCESS, INC. -OUI:001058* - ID_OUI_FROM_DATABASE=ArrowPoint Communications +OUI:0080D7* + ID_OUI_FROM_DATABASE=Fantum Engineering -OUI:0010A8* - ID_OUI_FROM_DATABASE=RELIANCE COMPUTER CORP. +OUI:0080D9* + ID_OUI_FROM_DATABASE=EMK Elektronik GmbH & Co. KG -OUI:0010AA* - ID_OUI_FROM_DATABASE=MEDIA4, INC. +OUI:00806A* + ID_OUI_FROM_DATABASE=ERI (EMPAC RESEARCH INC.) -OUI:0010E8* - ID_OUI_FROM_DATABASE=TELOCITY, INCORPORATED +OUI:00403B* + ID_OUI_FROM_DATABASE=SYNERJET INTERNATIONAL CORP. -OUI:001010* - ID_OUI_FROM_DATABASE=INITIO CORPORATION +OUI:0040AB* + ID_OUI_FROM_DATABASE=ROLAND DG CORPORATION -OUI:00E007* - ID_OUI_FROM_DATABASE=Avaya ECS Ltd +OUI:0040D5* + ID_OUI_FROM_DATABASE=Sartorius Mechatronics T&H GmbH -OUI:001022* - ID_OUI_FROM_DATABASE=SatCom Media Corporation +OUI:004027* + ID_OUI_FROM_DATABASE=SMC MASSACHUSETTS, INC. -OUI:0010C7* - ID_OUI_FROM_DATABASE=DATA TRANSMISSION NETWORK +OUI:00409C* + ID_OUI_FROM_DATABASE=TRANSWARE -OUI:001098* - ID_OUI_FROM_DATABASE=STARNET TECHNOLOGIES, INC. +OUI:00405C* + ID_OUI_FROM_DATABASE=FUTURE SYSTEMS, INC. -OUI:001096* - ID_OUI_FROM_DATABASE=TRACEWELL SYSTEMS, INC. +OUI:00008C* + ID_OUI_FROM_DATABASE=Alloy Computer Products (Australia) Pty Ltd -OUI:001082* - ID_OUI_FROM_DATABASE=JNA TELECOMMUNICATIONS LIMITED +OUI:004000* + ID_OUI_FROM_DATABASE=PCI COMPONENTES DA AMZONIA LTD -OUI:001021* - ID_OUI_FROM_DATABASE=ENCANTO NETWORKS, INC. +OUI:0040C5* + ID_OUI_FROM_DATABASE=MICOM COMMUNICATIONS INC. -OUI:0010CE* - ID_OUI_FROM_DATABASE=VOLAMP, LTD. +OUI:0040AA* + ID_OUI_FROM_DATABASE=Metso Automation -OUI:0010B2* - ID_OUI_FROM_DATABASE=COACTIVE AESTHETICS +OUI:004023* + ID_OUI_FROM_DATABASE=LOGIC CORPORATION -OUI:00109A* - ID_OUI_FROM_DATABASE=NETLINE +OUI:0040A4* + ID_OUI_FROM_DATABASE=ROSE ELECTRONICS -OUI:0010EA* - ID_OUI_FROM_DATABASE=ADEPT TECHNOLOGY +OUI:004048* + ID_OUI_FROM_DATABASE=SMD INFORMATICA S.A. -OUI:0010BD* - ID_OUI_FROM_DATABASE=THE TELECOMMUNICATION TECHNOLOGY COMMITTEE (TTC) +OUI:004025* + ID_OUI_FROM_DATABASE=MOLECULAR DYNAMICS -OUI:006099* - ID_OUI_FROM_DATABASE=SBE, Inc. +OUI:004010* + ID_OUI_FROM_DATABASE=SONIC SYSTEMS, INC. -OUI:0060FD* - ID_OUI_FROM_DATABASE=NetICs, Inc. +OUI:0040CA* + ID_OUI_FROM_DATABASE=FIRST INTERNAT'L COMPUTER, INC -OUI:0060B5* - ID_OUI_FROM_DATABASE=KEBA GmbH +OUI:004050* + ID_OUI_FROM_DATABASE=IRONICS, INCORPORATED -OUI:006027* - ID_OUI_FROM_DATABASE=Superior Modular Products +OUI:00402B* + ID_OUI_FROM_DATABASE=TRIGEM COMPUTER, INC. -OUI:0060C1* - ID_OUI_FROM_DATABASE=WaveSpan Corporation +OUI:00C08C* + ID_OUI_FROM_DATABASE=PERFORMANCE TECHNOLOGIES, INC. -OUI:006041* - ID_OUI_FROM_DATABASE=Yokogawa Electric Corporation +OUI:00C02B* + ID_OUI_FROM_DATABASE=GERLOFF GESELLSCHAFT FUR -OUI:006005* - ID_OUI_FROM_DATABASE=FEEDBACK DATA LTD. +OUI:00C0A7* + ID_OUI_FROM_DATABASE=SEEL LTD. -OUI:00607B* - ID_OUI_FROM_DATABASE=FORE SYSTEMS, INC. +OUI:0040B3* + ID_OUI_FROM_DATABASE=ParTech Inc. -OUI:00609C* - ID_OUI_FROM_DATABASE=Perkin-Elmer Incorporated +OUI:00407D* + ID_OUI_FROM_DATABASE=EXTENSION TECHNOLOGY CORP. -OUI:006007* - ID_OUI_FROM_DATABASE=ACRES GAMING, INC. +OUI:004079* + ID_OUI_FROM_DATABASE=JUKO MANUFACTURE COMPANY, LTD. -OUI:006035* - ID_OUI_FROM_DATABASE=DALLAS SEMICONDUCTOR, INC. +OUI:0040D9* + ID_OUI_FROM_DATABASE=AMERICAN MEGATRENDS INC. -OUI:0060F1* - ID_OUI_FROM_DATABASE=EXP COMPUTER, INC. +OUI:004011* + ID_OUI_FROM_DATABASE=ANDOVER CONTROLS CORPORATION -OUI:006040* - ID_OUI_FROM_DATABASE=NETRO CORP. +OUI:0040C1* + ID_OUI_FROM_DATABASE=BIZERBA-WERKE WILHEIM KRAUT -OUI:006034* - ID_OUI_FROM_DATABASE=ROBERT BOSCH GmbH +OUI:00C06B* + ID_OUI_FROM_DATABASE=OSI PLUS CORPORATION -OUI:0060BA* - ID_OUI_FROM_DATABASE=SAHARA NETWORKS, INC. +OUI:00C06A* + ID_OUI_FROM_DATABASE=ZAHNER-ELEKTRIK GMBH & CO. KG -OUI:006096* - ID_OUI_FROM_DATABASE=T.S. MICROTECH INC. +OUI:00C097* + ID_OUI_FROM_DATABASE=ARCHIPEL SA -OUI:00603A* - ID_OUI_FROM_DATABASE=QUICK CONTROLS LTD. +OUI:00C072* + ID_OUI_FROM_DATABASE=KNX LTD. -OUI:0060AC* - ID_OUI_FROM_DATABASE=RESILIENCE CORPORATION +OUI:00C0EC* + ID_OUI_FROM_DATABASE=DAUPHIN TECHNOLOGY -OUI:0060EB* - ID_OUI_FROM_DATABASE=FOURTHTRACK SYSTEMS +OUI:00C066* + ID_OUI_FROM_DATABASE=DOCUPOINT, INC. -OUI:00606D* - ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORP. +OUI:00C028* + ID_OUI_FROM_DATABASE=JASCO CORPORATION -OUI:006014* - ID_OUI_FROM_DATABASE=EDEC CO., LTD. +OUI:00C0DC* + ID_OUI_FROM_DATABASE=EOS TECHNOLOGIES, INC. -OUI:0060E1* - ID_OUI_FROM_DATABASE=ORCKIT COMMUNICATIONS LTD. +OUI:00C02D* + ID_OUI_FROM_DATABASE=FUJI PHOTO FILM CO., LTD. -OUI:006062* - ID_OUI_FROM_DATABASE=TELESYNC, INC. +OUI:00C0BD* + ID_OUI_FROM_DATABASE=INEX TECHNOLOGIES, INC. -OUI:006038* - ID_OUI_FROM_DATABASE=Nortel Networks +OUI:00C054* + ID_OUI_FROM_DATABASE=NETWORK PERIPHERALS, LTD. -OUI:006095* - ID_OUI_FROM_DATABASE=ACCU-TIME SYSTEMS, INC. +OUI:00C0D5* + ID_OUI_FROM_DATABASE=Werbeagentur Jürgen Siebert -OUI:00A016* - ID_OUI_FROM_DATABASE=MICROPOLIS CORP. +OUI:00C044* + ID_OUI_FROM_DATABASE=EMCOM CORPORATION -OUI:00A01C* - ID_OUI_FROM_DATABASE=NASCENT NETWORKS CORPORATION +OUI:00C050* + ID_OUI_FROM_DATABASE=TOYO DENKI SEIZO K.K. -OUI:00A0FC* - ID_OUI_FROM_DATABASE=IMAGE SCIENCES, INC. +OUI:00408A* + ID_OUI_FROM_DATABASE=TPS TELEPROCESSING SYS. GMBH -OUI:00A0B7* - ID_OUI_FROM_DATABASE=CORDANT, INC. +OUI:0040FD* + ID_OUI_FROM_DATABASE=LXE -OUI:00A037* - ID_OUI_FROM_DATABASE=Mindray DS USA, Inc. +OUI:00403D* + ID_OUI_FROM_DATABASE=Teradata Corporation -OUI:00A04C* - ID_OUI_FROM_DATABASE=INNOVATIVE SYSTEMS & TECHNOLOGIES, INC. +OUI:0040E0* + ID_OUI_FROM_DATABASE=ATOMWIDE LTD. -OUI:00A0E9* - ID_OUI_FROM_DATABASE=ELECTRONIC RETAILING SYSTEMS INTERNATIONAL +OUI:00408C* + ID_OUI_FROM_DATABASE=AXIS COMMUNICATIONS AB -OUI:006078* - ID_OUI_FROM_DATABASE=POWER MEASUREMENT LTD. +OUI:004068* + ID_OUI_FROM_DATABASE=EXTENDED SYSTEMS -OUI:00600D* - ID_OUI_FROM_DATABASE=Digital Logic GmbH +OUI:0040BA* + ID_OUI_FROM_DATABASE=ALLIANT COMPUTER SYSTEMS CORP. -OUI:00608A* - ID_OUI_FROM_DATABASE=CITADEL COMPUTER +OUI:004069* + ID_OUI_FROM_DATABASE=LEMCOM SYSTEMS, INC. -OUI:00A05D* - ID_OUI_FROM_DATABASE=CS COMPUTER SYSTEME GmbH +OUI:0040F8* + ID_OUI_FROM_DATABASE=SYSTEMHAUS DISCOM -OUI:00A0BD* - ID_OUI_FROM_DATABASE=I-TECH CORP. +OUI:004077* + ID_OUI_FROM_DATABASE=MAXTON TECHNOLOGY CORPORATION -OUI:00A0B9* - ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGY, INC. +OUI:0040E7* + ID_OUI_FROM_DATABASE=ARNOS INSTRUMENTS & COMPUTER -OUI:00A069* - ID_OUI_FROM_DATABASE=Symmetricom, Inc. +OUI:0040AC* + ID_OUI_FROM_DATABASE=SUPER WORKSTATION, INC. -OUI:00A07A* - ID_OUI_FROM_DATABASE=ADVANCED PERIPHERALS TECHNOLOGIES, INC. +OUI:00C0AC* + ID_OUI_FROM_DATABASE=GAMBIT COMPUTER COMMUNICATIONS -OUI:00A04E* - ID_OUI_FROM_DATABASE=VOELKER TECHNOLOGIES, INC. +OUI:00C02C* + ID_OUI_FROM_DATABASE=CENTRUM COMMUNICATIONS, INC. -OUI:00A05A* - ID_OUI_FROM_DATABASE=KOFAX IMAGE PRODUCTS +OUI:00C0ED* + ID_OUI_FROM_DATABASE=US ARMY ELECTRONIC -OUI:00A093* - ID_OUI_FROM_DATABASE=B/E AEROSPACE, Inc. +OUI:00C0D1* + ID_OUI_FROM_DATABASE=COMTREE TECHNOLOGY CORPORATION -OUI:00A0BF* - ID_OUI_FROM_DATABASE=WIRELESS DATA GROUP MOTOROLA +OUI:00C0D2* + ID_OUI_FROM_DATABASE=SYNTELLECT, INC. -OUI:00609F* - ID_OUI_FROM_DATABASE=PHAST CORPORATION +OUI:00C0FB* + ID_OUI_FROM_DATABASE=ADVANCED TECHNOLOGY LABS -OUI:006067* - ID_OUI_FROM_DATABASE=ACER NETXUS INC. +OUI:00C092* + ID_OUI_FROM_DATABASE=MENNEN MEDICAL INC. -OUI:00600C* - ID_OUI_FROM_DATABASE=Eurotech Inc. +OUI:00C06C* + ID_OUI_FROM_DATABASE=SVEC COMPUTER CORP. -OUI:006025* - ID_OUI_FROM_DATABASE=ACTIVE IMAGING PLC +OUI:00C02E* + ID_OUI_FROM_DATABASE=NETWIZ -OUI:006071* - ID_OUI_FROM_DATABASE=MIDAS LAB, INC. +OUI:00C05B* + ID_OUI_FROM_DATABASE=NETWORKS NORTHWEST, INC. -OUI:0060A7* - ID_OUI_FROM_DATABASE=MICROSENS GmbH & CO. KG +OUI:00C0BF* + ID_OUI_FROM_DATABASE=TECHNOLOGY CONCEPTS, LTD. -OUI:0060FC* - ID_OUI_FROM_DATABASE=CONSERVATION THROUGH INNOVATION LTD. +OUI:00C0C9* + ID_OUI_FROM_DATABASE=ELSAG BAILEY PROCESS -OUI:0060D4* - ID_OUI_FROM_DATABASE=ELDAT COMMUNICATION LTD. +OUI:00809D* + ID_OUI_FROM_DATABASE=Commscraft Ltd. -OUI:006085* - ID_OUI_FROM_DATABASE=Storage Concepts +OUI:008017* + ID_OUI_FROM_DATABASE=PFU LIMITED -OUI:0060D3* - ID_OUI_FROM_DATABASE=AT&T +OUI:0080F8* + ID_OUI_FROM_DATABASE=MIZAR, INC. -OUI:006018* - ID_OUI_FROM_DATABASE=STELLAR ONE CORPORATION +OUI:008024* + ID_OUI_FROM_DATABASE=KALPANA, INC. -OUI:00602B* - ID_OUI_FROM_DATABASE=PEAK AUDIO +OUI:008074* + ID_OUI_FROM_DATABASE=FISHER CONTROLS -OUI:00606F* - ID_OUI_FROM_DATABASE=CLARION CORPORATION OF AMERICA +OUI:008021* + ID_OUI_FROM_DATABASE=Alcatel Canada Inc. -OUI:0060ED* - ID_OUI_FROM_DATABASE=RICARDO TEST AUTOMATION LTD. +OUI:000055* + ID_OUI_FROM_DATABASE=COMMISSARIAT A L`ENERGIE ATOM. -OUI:0060F6* - ID_OUI_FROM_DATABASE=NEXTEST COMMUNICATIONS PRODUCTS, INC. +OUI:000086* + ID_OUI_FROM_DATABASE=MEGAHERTZ CORPORATION -OUI:0060DD* - ID_OUI_FROM_DATABASE=MYRICOM, INC. +OUI:000092* + ID_OUI_FROM_DATABASE=COGENT DATA TECHNOLOGIES -OUI:006092* - ID_OUI_FROM_DATABASE=MICRO/SYS, INC. +OUI:008068* + ID_OUI_FROM_DATABASE=YAMATECH SCIENTIFIC LTD. -OUI:006080* - ID_OUI_FROM_DATABASE=MICROTRONIX DATACOM LTD. +OUI:0080F2* + ID_OUI_FROM_DATABASE=RAYCOM SYSTEMS INC -OUI:006068* - ID_OUI_FROM_DATABASE=Dialogic Corporation +OUI:0080EA* + ID_OUI_FROM_DATABASE=ADVA Optical Networking Ltd. -OUI:0060DB* - ID_OUI_FROM_DATABASE=NTP ELEKTRONIK A/S +OUI:000067* + ID_OUI_FROM_DATABASE=SOFT * RITE, INC. -OUI:00A002* - ID_OUI_FROM_DATABASE=LEEDS & NORTHRUP AUSTRALIA PTY LTD +OUI:0000E8* + ID_OUI_FROM_DATABASE=ACCTON TECHNOLOGY CORP. -OUI:00A0E4* - ID_OUI_FROM_DATABASE=OPTIQUEST +OUI:0000B2* + ID_OUI_FROM_DATABASE=TELEVIDEO SYSTEMS, INC. -OUI:00A01F* - ID_OUI_FROM_DATABASE=TRICORD SYSTEMS, INC. +OUI:0000EE* + ID_OUI_FROM_DATABASE=NETWORK DESIGNERS, LTD. -OUI:00A0C0* - ID_OUI_FROM_DATABASE=DIGITAL LINK CORP. +OUI:000089* + ID_OUI_FROM_DATABASE=CAYMAN SYSTEMS INC. -OUI:00A043* - ID_OUI_FROM_DATABASE=AMERICAN TECHNOLOGY LABS, INC. +OUI:000021* + ID_OUI_FROM_DATABASE=SUREMAN COMP. & COMMUN. CORP. -OUI:00A047* - ID_OUI_FROM_DATABASE=INTEGRATED FITNESS CORP. +OUI:0000CF* + ID_OUI_FROM_DATABASE=HAYES MICROCOMPUTER PRODUCTS -OUI:00A07C* - ID_OUI_FROM_DATABASE=TONYANG NYLON CO., LTD. +OUI:0000A4* + ID_OUI_FROM_DATABASE=ACORN COMPUTERS LIMITED -OUI:00A0EC* - ID_OUI_FROM_DATABASE=TRANSMITTON LTD. +OUI:000018* + ID_OUI_FROM_DATABASE=WEBSTER COMPUTER CORPORATION -OUI:00A07E* - ID_OUI_FROM_DATABASE=AVID TECHNOLOGY, INC. +OUI:008033* + ID_OUI_FROM_DATABASE=EMS Aviation, Inc. -OUI:00A035* - ID_OUI_FROM_DATABASE=CYLINK CORPORATION +OUI:008052* + ID_OUI_FROM_DATABASE=TECHNICALLY ELITE CONCEPTS -OUI:00A028* - ID_OUI_FROM_DATABASE=CONNER PERIPHERALS +OUI:00804F* + ID_OUI_FROM_DATABASE=DAIKIN INDUSTRIES, LTD. -OUI:00A0C7* - ID_OUI_FROM_DATABASE=TADIRAN TELECOMMUNICATIONS +OUI:00806D* + ID_OUI_FROM_DATABASE=CENTURY SYSTEMS CORP. -OUI:00E0BE* - ID_OUI_FROM_DATABASE=GENROCO INTERNATIONAL, INC. +OUI:00802D* + ID_OUI_FROM_DATABASE=XYLOGICS INC -OUI:00E010* - ID_OUI_FROM_DATABASE=HESS SB-AUTOMATENBAU GmbH +OUI:008048* + ID_OUI_FROM_DATABASE=COMPEX INCORPORATED -OUI:00E0E9* - ID_OUI_FROM_DATABASE=DATA LABS, INC. +OUI:008085* + ID_OUI_FROM_DATABASE=H-THREE SYSTEMS CORPORATION -OUI:00E0A0* - ID_OUI_FROM_DATABASE=WILTRON CO. +OUI:008014* + ID_OUI_FROM_DATABASE=ESPRIT SYSTEMS -OUI:00E024* - ID_OUI_FROM_DATABASE=GADZOOX NETWORKS +OUI:0080B4* + ID_OUI_FROM_DATABASE=SOPHIA SYSTEMS -OUI:00E017* - ID_OUI_FROM_DATABASE=EXXACT GmbH +OUI:00807F* + ID_OUI_FROM_DATABASE=DY-4 INCORPORATED -OUI:00603B* - ID_OUI_FROM_DATABASE=AMTEC spa +OUI:0000E4* + ID_OUI_FROM_DATABASE=IN2 GROUPE INTERTECHNIQUE -OUI:0020E5* - ID_OUI_FROM_DATABASE=APEX DATA, INC. +OUI:000079* + ID_OUI_FROM_DATABASE=NETWORTH INCORPORATED -OUI:00207D* - ID_OUI_FROM_DATABASE=ADVANCED COMPUTER APPLICATIONS +OUI:000075* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:0020D0* - ID_OUI_FROM_DATABASE=VERSALYNX CORPORATION +OUI:004009* + ID_OUI_FROM_DATABASE=TACHIBANA TECTRON CO., LTD. -OUI:00206C* - ID_OUI_FROM_DATABASE=EVERGREEN TECHNOLOGY CORP. +OUI:00409E* + ID_OUI_FROM_DATABASE=CONCURRENT TECHNOLOGIES LTD. -OUI:002012* - ID_OUI_FROM_DATABASE=CAMTRONICS MEDICAL SYSTEMS +OUI:008092* + ID_OUI_FROM_DATABASE=Silex Technology, Inc. -OUI:00200B* - ID_OUI_FROM_DATABASE=OCTAGON SYSTEMS CORP. +OUI:008011* + ID_OUI_FROM_DATABASE=DIGITAL SYSTEMS INT'L. INC. -OUI:00209E* - ID_OUI_FROM_DATABASE=BROWN'S OPERATING SYSTEM SERVICES, LTD. +OUI:008044* + ID_OUI_FROM_DATABASE=SYSTECH COMPUTER CORP. -OUI:0020D7* - ID_OUI_FROM_DATABASE=JAPAN MINICOMPUTER SYSTEMS CO., Ltd. +OUI:00808A* + ID_OUI_FROM_DATABASE=SUMMIT MICROSYSTEMS CORP. -OUI:0020FB* - ID_OUI_FROM_DATABASE=OCTEL COMMUNICATIONS CORP. +OUI:0080E3* + ID_OUI_FROM_DATABASE=CORAL NETWORK CORPORATION -OUI:0020B1* - ID_OUI_FROM_DATABASE=COMTECH RESEARCH INC. +OUI:008072* + ID_OUI_FROM_DATABASE=MICROPLEX SYSTEMS LTD. -OUI:002033* - ID_OUI_FROM_DATABASE=SYNAPSE TECHNOLOGIES, INC. +OUI:008054* + ID_OUI_FROM_DATABASE=FRONTIER TECHNOLOGIES CORP. -OUI:002099* - ID_OUI_FROM_DATABASE=BON ELECTRIC CO., LTD. +OUI:0080AE* + ID_OUI_FROM_DATABASE=HUGHES NETWORK SYSTEMS -OUI:0020AE* - ID_OUI_FROM_DATABASE=ORNET DATA COMMUNICATION TECH. +OUI:0080AF* + ID_OUI_FROM_DATABASE=ALLUMER CO., LTD. -OUI:0020EA* - ID_OUI_FROM_DATABASE=EFFICIENT NETWORKS, INC. +OUI:0080EC* + ID_OUI_FROM_DATABASE=SUPERCOMPUTING SOLUTIONS, INC. -OUI:0020FF* - ID_OUI_FROM_DATABASE=SYMMETRICAL TECHNOLOGIES +OUI:0080A4* + ID_OUI_FROM_DATABASE=LIBERTY ELECTRONICS -OUI:00208B* - ID_OUI_FROM_DATABASE=LAPIS TECHNOLOGIES, INC. +OUI:008073* + ID_OUI_FROM_DATABASE=DWB ASSOCIATES -OUI:002069* - ID_OUI_FROM_DATABASE=ISDN SYSTEMS CORPORATION +OUI:00802B* + ID_OUI_FROM_DATABASE=INTEGRATED MARKETING CO -OUI:0020BA* - ID_OUI_FROM_DATABASE=CENTER FOR HIGH PERFORMANCE +OUI:0080BE* + ID_OUI_FROM_DATABASE=ARIES RESEARCH -OUI:002006* - ID_OUI_FROM_DATABASE=GARRETT COMMUNICATIONS, INC. +OUI:008027* + ID_OUI_FROM_DATABASE=ADAPTIVE SYSTEMS, INC. -OUI:00A0A2* - ID_OUI_FROM_DATABASE=DIGICOM S.P.A. +OUI:0080E2* + ID_OUI_FROM_DATABASE=T.D.I. CO., LTD. -OUI:00A054* - ID_OUI_FROM_DATABASE=Private +OUI:0040EE* + ID_OUI_FROM_DATABASE=OPTIMEM -OUI:00A030* - ID_OUI_FROM_DATABASE=CAPTOR NV/SA +OUI:00405E* + ID_OUI_FROM_DATABASE=NORTH HILLS ISRAEL -OUI:00A0B1* - ID_OUI_FROM_DATABASE=FIRST VIRTUAL CORPORATION +OUI:004072* + ID_OUI_FROM_DATABASE=Applied Innovation Inc. -OUI:0020CB* - ID_OUI_FROM_DATABASE=PRETEC ELECTRONICS CORP. +OUI:004031* + ID_OUI_FROM_DATABASE=KOKUSAI ELECTRIC CO., LTD -OUI:0020AB* - ID_OUI_FROM_DATABASE=MICRO INDUSTRIES CORP. +OUI:00400C* + ID_OUI_FROM_DATABASE=GENERAL MICRO SYSTEMS, INC. -OUI:00202D* - ID_OUI_FROM_DATABASE=TAIYO CORPORATION +OUI:0040E6* + ID_OUI_FROM_DATABASE=C.A.E.N. -OUI:00A088* - ID_OUI_FROM_DATABASE=ESSENTIAL COMMUNICATIONS +OUI:0040FC* + ID_OUI_FROM_DATABASE=IBR COMPUTER TECHNIK GMBH -OUI:00A0FA* - ID_OUI_FROM_DATABASE=Marconi Communication GmbH +OUI:004001* + ID_OUI_FROM_DATABASE=Zero One Technology Co. Ltd. -OUI:00A014* - ID_OUI_FROM_DATABASE=CSIR +OUI:004002* + ID_OUI_FROM_DATABASE=PERLE SYSTEMS LIMITED -OUI:00A064* - ID_OUI_FROM_DATABASE=KVB/ANALECT +OUI:0080DB* + ID_OUI_FROM_DATABASE=GRAPHON CORPORATION -OUI:00A07F* - ID_OUI_FROM_DATABASE=GSM-SYNTEL, LTD. +OUI:0080B1* + ID_OUI_FROM_DATABASE=SOFTCOM A/S -OUI:00A03E* - ID_OUI_FROM_DATABASE=ATM FORUM +OUI:0080D8* + ID_OUI_FROM_DATABASE=NETWORK PERIPHERALS INC. -OUI:00A050* - ID_OUI_FROM_DATABASE=CYPRESS SEMICONDUCTOR +OUI:0080AB* + ID_OUI_FROM_DATABASE=DUKANE NETWORK INTEGRATION -OUI:00A098* - ID_OUI_FROM_DATABASE=NetApp +OUI:00809B* + ID_OUI_FROM_DATABASE=JUSTSYSTEM CORPORATION -OUI:00A021* - ID_OUI_FROM_DATABASE=General Dynamics +OUI:008089* + ID_OUI_FROM_DATABASE=TECNETICS (PTY) LTD. -OUI:00A0A8* - ID_OUI_FROM_DATABASE=RENEX CORPORATION +OUI:000039* + ID_OUI_FROM_DATABASE=TOSHIBA CORPORATION -OUI:002049* - ID_OUI_FROM_DATABASE=COMTRON, INC. +OUI:0000CB* + ID_OUI_FROM_DATABASE=COMPU-SHACK ELECTRONIC GMBH -OUI:002050* - ID_OUI_FROM_DATABASE=KOREA COMPUTER INC. +OUI:0000D1* + ID_OUI_FROM_DATABASE=ADAPTEC INCORPORATED -OUI:00203C* - ID_OUI_FROM_DATABASE=EUROTIME AB +OUI:0000B6* + ID_OUI_FROM_DATABASE=MICRO-MATIC RESEARCH -OUI:002028* - ID_OUI_FROM_DATABASE=WEST EGG SYSTEMS, INC. +OUI:000066* + ID_OUI_FROM_DATABASE=TALARIS SYSTEMS, INC. -OUI:002014* - ID_OUI_FROM_DATABASE=GLOBAL VIEW CO., LTD. +OUI:000014* + ID_OUI_FROM_DATABASE=NETRONIX -OUI:002053* - ID_OUI_FROM_DATABASE=HUNTSVILLE MICROSYSTEMS, INC. +OUI:000072* + ID_OUI_FROM_DATABASE=MINIWARE TECHNOLOGY -OUI:002001* - ID_OUI_FROM_DATABASE=DSP SOLUTIONS, INC. +OUI:0000AB* + ID_OUI_FROM_DATABASE=LOGIC MODELING CORPORATION -OUI:00209C* - ID_OUI_FROM_DATABASE=PRIMARY ACCESS CORP. +OUI:000029* + ID_OUI_FROM_DATABASE=IMC NETWORKS CORP. -OUI:0020C5* - ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGY +OUI:0080CD* + ID_OUI_FROM_DATABASE=MICRONICS COMPUTER, INC. -OUI:002009* - ID_OUI_FROM_DATABASE=PACKARD BELL ELEC., INC. +OUI:008083* + ID_OUI_FROM_DATABASE=AMDAHL -OUI:002095* - ID_OUI_FROM_DATABASE=RIVA ELECTRONICS +OUI:008003* + ID_OUI_FROM_DATABASE=HYTEC ELECTRONICS LTD. -OUI:00203F* - ID_OUI_FROM_DATABASE=JUKI CORPORATION +OUI:00801B* + ID_OUI_FROM_DATABASE=KODIAK TECHNOLOGY -OUI:00C014* - ID_OUI_FROM_DATABASE=TELEMATICS CALABASAS INT'L,INC +OUI:0080CC* + ID_OUI_FROM_DATABASE=MICROWAVE BYPASS SYSTEMS -OUI:00C045* - ID_OUI_FROM_DATABASE=ISOLATION SYSTEMS, LTD. +OUI:080079* + ID_OUI_FROM_DATABASE=THE DROID WORKS -OUI:00C000* - ID_OUI_FROM_DATABASE=LANOPTICS, LTD. +OUI:080077* + ID_OUI_FROM_DATABASE=TSL COMMUNICATIONS LTD. -OUI:00AA3C* - ID_OUI_FROM_DATABASE=OLIVETTI TELECOM SPA (OLTECO) +OUI:080071* + ID_OUI_FROM_DATABASE=MATRA (DSIE) -OUI:00C079* - ID_OUI_FROM_DATABASE=FONSYS CO.,LTD. +OUI:08005F* + ID_OUI_FROM_DATABASE=SABER TECHNOLOGY CORP. -OUI:002011* - ID_OUI_FROM_DATABASE=CANOPUS CO., LTD. +OUI:08005C* + ID_OUI_FROM_DATABASE=FOUR PHASE SYSTEMS -OUI:00C00B* - ID_OUI_FROM_DATABASE=NORCONTROL A.S. +OUI:08005B* + ID_OUI_FROM_DATABASE=VTA TECHNOLOGIES INC. -OUI:00C0C0* - ID_OUI_FROM_DATABASE=SHORE MICROSYSTEMS, INC. +OUI:080058* + ID_OUI_FROM_DATABASE=SYSTEMS CONCEPTS -OUI:00C00C* - ID_OUI_FROM_DATABASE=RELIA TECHNOLGIES +OUI:080050* + ID_OUI_FROM_DATABASE=DAISY SYSTEMS CORP. -OUI:00A0E7* - ID_OUI_FROM_DATABASE=CENTRAL DATA CORPORATION +OUI:080052* + ID_OUI_FROM_DATABASE=INSYSTEC -OUI:00A068* - ID_OUI_FROM_DATABASE=BHP LIMITED +OUI:080047* + ID_OUI_FROM_DATABASE=SEQUENT COMPUTER SYSTEMS INC. -OUI:00A0B3* - ID_OUI_FROM_DATABASE=ZYKRONIX +OUI:080045* + ID_OUI_FROM_DATABASE=CONCURRENT COMPUTER CORP. -OUI:00A06E* - ID_OUI_FROM_DATABASE=AUSTRON, INC. +OUI:080044* + ID_OUI_FROM_DATABASE=DAVID SYSTEMS INC. -OUI:00A0BB* - ID_OUI_FROM_DATABASE=HILAN GMBH +OUI:080041* + ID_OUI_FROM_DATABASE=RACAL-MILGO INFORMATION SYS.. -OUI:00A0C8* - ID_OUI_FROM_DATABASE=ADTRAN INC. +OUI:080038* + ID_OUI_FROM_DATABASE=BULL S.A.S. -OUI:00A017* - ID_OUI_FROM_DATABASE=J B M CORPORATION +OUI:08003C* + ID_OUI_FROM_DATABASE=SCHLUMBERGER WELL SERVICES -OUI:0020D5* - ID_OUI_FROM_DATABASE=VIPA GMBH +OUI:080034* + ID_OUI_FROM_DATABASE=FILENET CORPORATION -OUI:002079* - ID_OUI_FROM_DATABASE=MIKRON GMBH +OUI:08002C* + ID_OUI_FROM_DATABASE=BRITTON LEE INC. -OUI:0020FA* - ID_OUI_FROM_DATABASE=GDE SYSTEMS, INC. +OUI:0000B9* + ID_OUI_FROM_DATABASE=MCDONNELL DOUGLAS COMPUTER SYS -OUI:002007* - ID_OUI_FROM_DATABASE=SFA, INC. +OUI:00002D* + ID_OUI_FROM_DATABASE=CHROMATICS INC -OUI:002062* - ID_OUI_FROM_DATABASE=SCORPION LOGIC, LTD. +OUI:00004A* + ID_OUI_FROM_DATABASE=ADC CODENOLL TECHNOLOGY CORP. -OUI:00200A* - ID_OUI_FROM_DATABASE=SOURCE-COMM CORP. +OUI:0000C0* + ID_OUI_FROM_DATABASE=WESTERN DIGITAL CORPORATION -OUI:002000* - ID_OUI_FROM_DATABASE=LEXMARK INTERNATIONAL, INC. +OUI:000040* + ID_OUI_FROM_DATABASE=APPLICON, INC. -OUI:002003* - ID_OUI_FROM_DATABASE=PIXEL POWER LTD. +OUI:00005D* + ID_OUI_FROM_DATABASE=CS TELECOM -OUI:0020B4* - ID_OUI_FROM_DATABASE=TERMA ELEKTRONIK AS +OUI:08008E* + ID_OUI_FROM_DATABASE=Tandem Computers -OUI:00205B* - ID_OUI_FROM_DATABASE=Kentrox, LLC +OUI:080086* + ID_OUI_FROM_DATABASE=KONICA MINOLTA HOLDINGS, INC. -OUI:002030* - ID_OUI_FROM_DATABASE=ANALOG & DIGITAL SYSTEMS +OUI:080083* + ID_OUI_FROM_DATABASE=Seiko Instruments Inc. -OUI:0020A8* - ID_OUI_FROM_DATABASE=SAST TECHNOLOGY CORP. +OUI:080080* + ID_OUI_FROM_DATABASE=AES DATA INC. -OUI:002066* - ID_OUI_FROM_DATABASE=GENERAL MAGIC, INC. +OUI:080030* + ID_OUI_FROM_DATABASE=ROYAL MELBOURNE INST OF TECH -OUI:002036* - ID_OUI_FROM_DATABASE=BMC SOFTWARE +OUI:080064* + ID_OUI_FROM_DATABASE=Sitasys AG -OUI:0040BE* - ID_OUI_FROM_DATABASE=BOEING DEFENSE & SPACE +OUI:00DD09* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. -OUI:004036* - ID_OUI_FROM_DATABASE=Zoom Telephonics, Inc +OUI:08008A* + ID_OUI_FROM_DATABASE=PerfTech, Inc. -OUI:004046* - ID_OUI_FROM_DATABASE=UDC RESEARCH LIMITED +OUI:00DD04* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. -OUI:00406A* - ID_OUI_FROM_DATABASE=KENTEK INFORMATION SYSTEMS,INC +OUI:080066* + ID_OUI_FROM_DATABASE=AGFA CORPORATION -OUI:0040F2* - ID_OUI_FROM_DATABASE=JANICH & KLASS COMPUTERTECHNIK +OUI:08001A* + ID_OUI_FROM_DATABASE=TIARA/ 10NET -OUI:004082* - ID_OUI_FROM_DATABASE=LABORATORY EQUIPMENT CORP. +OUI:080090* + ID_OUI_FROM_DATABASE=SONOMA SYSTEMS -OUI:004022* - ID_OUI_FROM_DATABASE=KLEVER COMPUTERS, INC. +OUI:08000B* + ID_OUI_FROM_DATABASE=UNISYS CORPORATION -OUI:0040A2* - ID_OUI_FROM_DATABASE=KINGSTAR TECHNOLOGY INC. +OUI:080017* + ID_OUI_FROM_DATABASE=NATIONAL SEMICONDUCTOR -OUI:0040B4* - ID_OUI_FROM_DATABASE=NEXTCOM K.K. +OUI:00005E* + ID_OUI_FROM_DATABASE=ICANN, IANA Department -OUI:0040D4* - ID_OUI_FROM_DATABASE=GAGE TALKER CORP. +OUI:0000AF* + ID_OUI_FROM_DATABASE=Canberra Industries, Inc. -OUI:004038* - ID_OUI_FROM_DATABASE=TALENT ELECTRIC INCORPORATED +OUI:0000EC* + ID_OUI_FROM_DATABASE=MICROPROCESS -OUI:004018* - ID_OUI_FROM_DATABASE=ADOBE SYSTEMS, INC. +OUI:00009E* + ID_OUI_FROM_DATABASE=MARLI S.A. -OUI:0040B0* - ID_OUI_FROM_DATABASE=BYTEX CORPORATION, ENGINEERING +OUI:000042* + ID_OUI_FROM_DATABASE=METIER MANAGEMENT SYSTEMS LTD. -OUI:004040* - ID_OUI_FROM_DATABASE=RING ACCESS, INC. +OUI:00008D* + ID_OUI_FROM_DATABASE=Cryptek Inc. -OUI:0080D7* - ID_OUI_FROM_DATABASE=Fantum Engineering +OUI:000065* + ID_OUI_FROM_DATABASE=Network General Corporation -OUI:0080D9* - ID_OUI_FROM_DATABASE=EMK Elektronik GmbH & Co. KG +OUI:00004D* + ID_OUI_FROM_DATABASE=DCI CORPORATION -OUI:00806A* - ID_OUI_FROM_DATABASE=ERI (EMPAC RESEARCH INC.) +OUI:080024* + ID_OUI_FROM_DATABASE=10NET COMMUNICATIONS/DCA -OUI:00403B* - ID_OUI_FROM_DATABASE=SYNERJET INTERNATIONAL CORP. +OUI:08001E* + ID_OUI_FROM_DATABASE=APOLLO COMPUTER INC. -OUI:0040AB* - ID_OUI_FROM_DATABASE=ROLAND DG CORPORATION +OUI:08001B* + ID_OUI_FROM_DATABASE=EMC Corporation -OUI:0040D5* - ID_OUI_FROM_DATABASE=Sartorius Mechatronics T&H GmbH +OUI:00DD0D* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. -OUI:004027* - ID_OUI_FROM_DATABASE=SMC MASSACHUSETTS, INC. +OUI:AA0002* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION -OUI:00409C* - ID_OUI_FROM_DATABASE=TRANSWARE +OUI:080005* + ID_OUI_FROM_DATABASE=SYMBOLICS INC. -OUI:00405C* - ID_OUI_FROM_DATABASE=FUTURE SYSTEMS, INC. +OUI:000000* + ID_OUI_FROM_DATABASE=XEROX CORPORATION -OUI:00008C* - ID_OUI_FROM_DATABASE=Alloy Computer Products (Australia) Pty Ltd +OUI:0040D6* + ID_OUI_FROM_DATABASE=LOCAMATION B.V. -OUI:004000* - ID_OUI_FROM_DATABASE=PCI COMPONENTES DA AMZONIA LTD +OUI:AA0003* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION -OUI:0040C5* - ID_OUI_FROM_DATABASE=MICOM COMMUNICATIONS INC. +OUI:080008* + ID_OUI_FROM_DATABASE=BOLT BERANEK AND NEWMAN INC. -OUI:0040AA* - ID_OUI_FROM_DATABASE=Metso Automation +OUI:08000E* + ID_OUI_FROM_DATABASE=NCR CORPORATION -OUI:004023* - ID_OUI_FROM_DATABASE=LOGIC CORPORATION +OUI:00006F* + ID_OUI_FROM_DATABASE=Madge Ltd. -OUI:0040A4* - ID_OUI_FROM_DATABASE=ROSE ELECTRONICS +OUI:00005A* + ID_OUI_FROM_DATABASE=SysKonnect GmbH -OUI:004048* - ID_OUI_FROM_DATABASE=SMD INFORMATICA S.A. +OUI:000023* + ID_OUI_FROM_DATABASE=ABB INDUSTRIAL SYSTEMS AB -OUI:004025* - ID_OUI_FROM_DATABASE=MOLECULAR DYNAMICS +OUI:000045* + ID_OUI_FROM_DATABASE=FORD AEROSPACE & COMM. CORP. -OUI:004010* - ID_OUI_FROM_DATABASE=SONIC SYSTEMS, INC. +OUI:0000BC* + ID_OUI_FROM_DATABASE=Rockwell Automation -OUI:0040CA* - ID_OUI_FROM_DATABASE=FIRST INTERNAT'L COMPUTER, INC +OUI:0000C3* + ID_OUI_FROM_DATABASE=HARRIS CORP COMPUTER SYS DIV -OUI:004050* - ID_OUI_FROM_DATABASE=IRONICS, INCORPORATED +OUI:000004* + ID_OUI_FROM_DATABASE=XEROX CORPORATION -OUI:00402B* - ID_OUI_FROM_DATABASE=TRIGEM COMPUTER, INC. +OUI:000009* + ID_OUI_FROM_DATABASE=XEROX CORPORATION -OUI:00C08C* - ID_OUI_FROM_DATABASE=PERFORMANCE TECHNOLOGIES, INC. +OUI:00003D* + ID_OUI_FROM_DATABASE=UNISYS -OUI:00C02B* - ID_OUI_FROM_DATABASE=GERLOFF GESELLSCHAFT FUR +OUI:F82C18* + ID_OUI_FROM_DATABASE=2Wire Inc -OUI:00C0A7* - ID_OUI_FROM_DATABASE=SEEL LTD. +OUI:00173F* + ID_OUI_FROM_DATABASE=Belkin International Inc. -OUI:0040B3* - ID_OUI_FROM_DATABASE=ParTech Inc. +OUI:388602* + ID_OUI_FROM_DATABASE=Flexoptix GmbH -OUI:00407D* - ID_OUI_FROM_DATABASE=EXTENSION TECHNOLOGY CORP. +OUI:F4EB38* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:004079* - ID_OUI_FROM_DATABASE=JUKO MANUFACTURE COMPANY, LTD. +OUI:001E74* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:0040D9* - ID_OUI_FROM_DATABASE=AMERICAN MEGATRENDS INC. +OUI:00604C* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:004011* - ID_OUI_FROM_DATABASE=ANDOVER CONTROLS CORPORATION +OUI:002691* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:0040C1* - ID_OUI_FROM_DATABASE=BIZERBA-WERKE WILHEIM KRAUT +OUI:C0D044* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:00C06B* - ID_OUI_FROM_DATABASE=OSI PLUS CORPORATION +OUI:6C2E85* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:CC33BB* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:00C06A* - ID_OUI_FROM_DATABASE=ZAHNER-ELEKTRIK GMBH & CO. KG +OUI:681590* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:00C097* - ID_OUI_FROM_DATABASE=ARCHIPEL SA +OUI:5464D9* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:00C072* - ID_OUI_FROM_DATABASE=KNX LTD. +OUI:00023F* + ID_OUI_FROM_DATABASE=COMPAL ELECTRONICS, INC. -OUI:00C0EC* - ID_OUI_FROM_DATABASE=DAUPHIN TECHNOLOGY +OUI:0080C2* + ID_OUI_FROM_DATABASE=IEEE 802.1 -OUI:00C066* - ID_OUI_FROM_DATABASE=DOCUPOINT, INC. +OUI:C46699* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. -OUI:00C028* - ID_OUI_FROM_DATABASE=JASCO CORPORATION +OUI:383BC8* + ID_OUI_FROM_DATABASE=2Wire Inc -OUI:00C0DC* - ID_OUI_FROM_DATABASE=EOS TECHNOLOGIES, INC. +OUI:DC7FA4* + ID_OUI_FROM_DATABASE=2Wire Inc -OUI:00C02D* - ID_OUI_FROM_DATABASE=FUJI PHOTO FILM CO., LTD. +OUI:001288* + ID_OUI_FROM_DATABASE=2Wire Inc -OUI:00C0BD* - ID_OUI_FROM_DATABASE=INEX TECHNOLOGIES, INC. +OUI:001EC7* + ID_OUI_FROM_DATABASE=2Wire Inc -OUI:00C054* - ID_OUI_FROM_DATABASE=NETWORK PERIPHERALS, LTD. +OUI:28162E* + ID_OUI_FROM_DATABASE=2Wire Inc -OUI:00C0D5* - ID_OUI_FROM_DATABASE=Werbeagentur Jürgen Siebert +OUI:3CEA4F* + ID_OUI_FROM_DATABASE=2Wire Inc -OUI:00C044* - ID_OUI_FROM_DATABASE=EMCOM CORPORATION +OUI:848F69* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00C050* - ID_OUI_FROM_DATABASE=TOYO DENKI SEIZO K.K. +OUI:90B11C* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00408A* - ID_OUI_FROM_DATABASE=TPS TELEPROCESSING SYS. GMBH +OUI:F8CAB8* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:0040FD* - ID_OUI_FROM_DATABASE=LXE +OUI:24B6FD* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00403D* - ID_OUI_FROM_DATABASE=Teradata Corporation +OUI:000D56* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:0040E0* - ID_OUI_FROM_DATABASE=ATOMWIDE LTD. +OUI:00123F* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00408C* - ID_OUI_FROM_DATABASE=AXIS COMMUNICATIONS AB +OUI:001372* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:004068* - ID_OUI_FROM_DATABASE=EXTENDED SYSTEMS +OUI:74867A* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:0040BA* - ID_OUI_FROM_DATABASE=ALLIANT COMPUTER SYSTEMS CORP. +OUI:3417EB* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:004069* - ID_OUI_FROM_DATABASE=LEMCOM SYSTEMS, INC. +OUI:EC8892* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:0040F8* - ID_OUI_FROM_DATABASE=SYSTEMHAUS DISCOM +OUI:B07994* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:004077* - ID_OUI_FROM_DATABASE=MAXTON TECHNOLOGY CORPORATION +OUI:141AA3* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:0040E7* - ID_OUI_FROM_DATABASE=ARNOS INSTRUMENTS & COMPUTER +OUI:CCC3EA* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:0040AC* - ID_OUI_FROM_DATABASE=SUPER WORKSTATION, INC. +OUI:34BB26* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:00C0AC* - ID_OUI_FROM_DATABASE=GAMBIT COMPUTER COMMUNICATIONS +OUI:40786A* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:00C02C* - ID_OUI_FROM_DATABASE=CENTRUM COMMUNICATIONS, INC. +OUI:0019B9* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00C0ED* - ID_OUI_FROM_DATABASE=US ARMY ELECTRONIC +OUI:002219* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00C0D1* - ID_OUI_FROM_DATABASE=COMTREE TECHNOLOGY CORPORATION +OUI:00B0D0* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00C0D2* - ID_OUI_FROM_DATABASE=SYNTELLECT, INC. +OUI:5C260A* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00C0FB* - ID_OUI_FROM_DATABASE=ADVANCED TECHNOLOGY LABS +OUI:B083FE* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00C092* - ID_OUI_FROM_DATABASE=MENNEN MEDICAL INC. +OUI:141877* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00C06C* - ID_OUI_FROM_DATABASE=SVEC COMPUTER CORP. +OUI:0024E8* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00C02E* - ID_OUI_FROM_DATABASE=NETWIZ +OUI:A48E0A* + ID_OUI_FROM_DATABASE=DeLaval International AB -OUI:00C05B* - ID_OUI_FROM_DATABASE=NETWORKS NORTHWEST, INC. +OUI:00215C* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:00C0BF* - ID_OUI_FROM_DATABASE=TECHNOLOGY CONCEPTS, LTD. +OUI:002315* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:00C0C9* - ID_OUI_FROM_DATABASE=ELSAG BAILEY PROCESS +OUI:001500* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:00809D* - ID_OUI_FROM_DATABASE=Commscraft Ltd. +OUI:104A7D* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:008017* - ID_OUI_FROM_DATABASE=PFU LIMITED +OUI:A4C494* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:0080F8* - ID_OUI_FROM_DATABASE=MIZAR, INC. +OUI:902E1C* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:008024* - ID_OUI_FROM_DATABASE=KALPANA, INC. +OUI:3CFDFE* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:008074* - ID_OUI_FROM_DATABASE=FISHER CONTROLS +OUI:B8BF83* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:008021* - ID_OUI_FROM_DATABASE=Alcatel Canada Inc. +OUI:001DE1* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:000055* - ID_OUI_FROM_DATABASE=COMMISSARIAT A L`ENERGIE ATOM. +OUI:0022FB* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:000086* - ID_OUI_FROM_DATABASE=MEGAHERTZ CORPORATION +OUI:081196* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:000092* - ID_OUI_FROM_DATABASE=COGENT DATA TECHNOLOGIES +OUI:6036DD* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:008068* - ID_OUI_FROM_DATABASE=YAMATECH SCIENTIFIC LTD. +OUI:A0369F* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:0080F2* - ID_OUI_FROM_DATABASE=RAYCOM SYSTEMS INC +OUI:502DA2* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:0080EA* - ID_OUI_FROM_DATABASE=ADVA Optical Networking Ltd. +OUI:4C79BA* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:008025* - ID_OUI_FROM_DATABASE=STOLLMANN GMBH +OUI:4CEB42* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:000067* - ID_OUI_FROM_DATABASE=SOFT * RITE, INC. +OUI:606720* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:0000E8* - ID_OUI_FROM_DATABASE=ACCTON TECHNOLOGY CORP. +OUI:84A6C8* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:0000B2* - ID_OUI_FROM_DATABASE=TELEVIDEO SYSTEMS, INC. +OUI:5891CF* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:0000EE* - ID_OUI_FROM_DATABASE=NETWORK DESIGNERS, LTD. +OUI:88532E* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:000089* - ID_OUI_FROM_DATABASE=CAYMAN SYSTEMS INC. +OUI:0024D7* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:000021* - ID_OUI_FROM_DATABASE=SUREMAN COMP. & COMMUN. CORP. +OUI:C40938* + ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD -OUI:0000CF* - ID_OUI_FROM_DATABASE=HAYES MICROCOMPUTER PRODUCTS +OUI:00AA02* + ID_OUI_FROM_DATABASE=Intel Corporation -OUI:0000A4* - ID_OUI_FROM_DATABASE=ACORN COMPUTERS LIMITED +OUI:5CD2E4* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:000018* - ID_OUI_FROM_DATABASE=WEBSTER COMPUTER CORPORATION +OUI:04BD88* + ID_OUI_FROM_DATABASE=Aruba Networks -OUI:008033* - ID_OUI_FROM_DATABASE=EMS Aviation, Inc. +OUI:000B86* + ID_OUI_FROM_DATABASE=Aruba Networks -OUI:008052* - ID_OUI_FROM_DATABASE=TECHNICALLY ELITE CONCEPTS +OUI:8896F2* + ID_OUI_FROM_DATABASE=Valeo Schalter und Sensoren GmbH -OUI:00804F* - ID_OUI_FROM_DATABASE=DAIKIN INDUSTRIES, LTD. +OUI:80A589* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. -OUI:00806D* - ID_OUI_FROM_DATABASE=CENTURY SYSTEMS CORP. +OUI:0CCC26* + ID_OUI_FROM_DATABASE=Airenetworks -OUI:00802D* - ID_OUI_FROM_DATABASE=XYLOGICS INC +OUI:4CB0E8* + ID_OUI_FROM_DATABASE=Beijing RongZhi xinghua technology co., LTD -OUI:008048* - ID_OUI_FROM_DATABASE=COMPEX INCORPORATED +OUI:4C14A3* + ID_OUI_FROM_DATABASE=TCL Technoly Electronics (Huizhou) Co., Ltd. -OUI:008085* - ID_OUI_FROM_DATABASE=H-THREE SYSTEMS CORPORATION +OUI:F48E38* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:008014* - ID_OUI_FROM_DATABASE=ESPRIT SYSTEMS +OUI:D887D5* + ID_OUI_FROM_DATABASE=Leadcore Technology CO.,LTD -OUI:0080B4* - ID_OUI_FROM_DATABASE=SOPHIA SYSTEMS +OUI:00DA55* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:00807F* - ID_OUI_FROM_DATABASE=DY-4 INCORPORATED +OUI:80D21D* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. -OUI:0000E4* - ID_OUI_FROM_DATABASE=IN2 GROUPE INTERTECHNIQUE +OUI:705A0F* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:000079* - ID_OUI_FROM_DATABASE=NETWORTH INCORPORATED +OUI:586356* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED -OUI:000075* - ID_OUI_FROM_DATABASE=Nortel Networks +OUI:B046FC* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. -OUI:004009* - ID_OUI_FROM_DATABASE=TACHIBANA TECTRON CO., LTD. +OUI:08A95A* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. -OUI:00409E* - ID_OUI_FROM_DATABASE=CONCURRENT TECHNOLOGIES LTD. +OUI:6CADF8* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. -OUI:008092* - ID_OUI_FROM_DATABASE=Silex Technology, Inc. +OUI:54271E* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. -OUI:008011* - ID_OUI_FROM_DATABASE=DIGITAL SYSTEMS INT'L. INC. +OUI:008C54* + ID_OUI_FROM_DATABASE=ADB Broadband Italia -OUI:008044* - ID_OUI_FROM_DATABASE=SYSTECH COMPUTER CORP. +OUI:F0842F* + ID_OUI_FROM_DATABASE=ADB Broadband Italia -OUI:00808A* - ID_OUI_FROM_DATABASE=SUMMIT MICROSYSTEMS CORP. +OUI:8CB864* + ID_OUI_FROM_DATABASE=AcSiP Technology Corp. -OUI:0080E3* - ID_OUI_FROM_DATABASE=CORAL NETWORK CORPORATION +OUI:0020E0* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc -OUI:008072* - ID_OUI_FROM_DATABASE=MICROPLEX SYSTEMS LTD. +OUI:0004E3* + ID_OUI_FROM_DATABASE=Accton Technology Corp -OUI:008054* - ID_OUI_FROM_DATABASE=FRONTIER TECHNOLOGIES CORP. +OUI:409558* + ID_OUI_FROM_DATABASE=Aisino Corporation -OUI:0080AE* - ID_OUI_FROM_DATABASE=HUGHES NETWORK SYSTEMS +OUI:00D0C9* + ID_OUI_FROM_DATABASE=ADVANTECH CO., LTD. -OUI:0080AF* - ID_OUI_FROM_DATABASE=ALLUMER CO., LTD. +OUI:002553* + ID_OUI_FROM_DATABASE=ADB Broadband Italia -OUI:0080EC* - ID_OUI_FROM_DATABASE=SUPERCOMPUTING SOLUTIONS, INC. +OUI:00238E* + ID_OUI_FROM_DATABASE=ADB Broadband Italia -OUI:0080A4* - ID_OUI_FROM_DATABASE=LIBERTY ELECTRONICS +OUI:001CA2* + ID_OUI_FROM_DATABASE=ADB Broadband Italia -OUI:008073* - ID_OUI_FROM_DATABASE=DWB ASSOCIATES +OUI:0017C2* + ID_OUI_FROM_DATABASE=ADB Broadband Italia -OUI:00802B* - ID_OUI_FROM_DATABASE=INTEGRATED MARKETING CO +OUI:D0D412* + ID_OUI_FROM_DATABASE=ADB Broadband Italia -OUI:0080BE* - ID_OUI_FROM_DATABASE=ARIES RESEARCH +OUI:000FA3* + ID_OUI_FROM_DATABASE=Alpha Networks Inc. -OUI:008027* - ID_OUI_FROM_DATABASE=ADAPTIVE SYSTEMS, INC. +OUI:001D6A* + ID_OUI_FROM_DATABASE=Alpha Networks Inc. -OUI:0080E2* - ID_OUI_FROM_DATABASE=T.D.I. CO., LTD. +OUI:0000F4* + ID_OUI_FROM_DATABASE=Allied Telesis, Inc. -OUI:0040EE* - ID_OUI_FROM_DATABASE=OPTIMEM +OUI:10AE60* + ID_OUI_FROM_DATABASE=Private -OUI:00405E* - ID_OUI_FROM_DATABASE=NORTH HILLS ISRAEL +OUI:F04F7C* + ID_OUI_FROM_DATABASE=Private -OUI:004072* - ID_OUI_FROM_DATABASE=Applied Innovation Inc. +OUI:70F1A1* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation -OUI:004031* - ID_OUI_FROM_DATABASE=KOKUSAI ELECTRIC CO., LTD +OUI:6CFAA7* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. -OUI:00400C* - ID_OUI_FROM_DATABASE=GENERAL MICRO SYSTEMS, INC. +OUI:0024EF* + ID_OUI_FROM_DATABASE=Sony Mobile Communications AB -OUI:0040E6* - ID_OUI_FROM_DATABASE=C.A.E.N. +OUI:6C0E0D* + ID_OUI_FROM_DATABASE=Sony Mobile Communications AB -OUI:0040FC* - ID_OUI_FROM_DATABASE=IBR COMPUTER TECHNIK GMBH +OUI:B4527D* + ID_OUI_FROM_DATABASE=Sony Mobile Communications AB -OUI:004001* - ID_OUI_FROM_DATABASE=Zero One Technology Co. Ltd. +OUI:E063E5* + ID_OUI_FROM_DATABASE=Sony Mobile Communications AB -OUI:004002* - ID_OUI_FROM_DATABASE=PERLE SYSTEMS LIMITED +OUI:000E07* + ID_OUI_FROM_DATABASE=Sony Mobile Communications AB -OUI:0080DB* - ID_OUI_FROM_DATABASE=GRAPHON CORPORATION +OUI:001A75* + ID_OUI_FROM_DATABASE=Sony Mobile Communications AB -OUI:0080B1* - ID_OUI_FROM_DATABASE=SOFTCOM A/S +OUI:0016B8* + ID_OUI_FROM_DATABASE=Sony Mobile Communications AB -OUI:0080D8* - ID_OUI_FROM_DATABASE=NETWORK PERIPHERALS INC. +OUI:001D28* + ID_OUI_FROM_DATABASE=Sony Mobile Communications AB -OUI:0080AB* - ID_OUI_FROM_DATABASE=DUKANE NETWORK INTEGRATION +OUI:001FE4* + ID_OUI_FROM_DATABASE=Sony Mobile Communications AB -OUI:00809B* - ID_OUI_FROM_DATABASE=JUSTSYSTEM CORPORATION +OUI:002298* + ID_OUI_FROM_DATABASE=Sony Mobile Communications AB -OUI:008089* - ID_OUI_FROM_DATABASE=TECNETICS (PTY) LTD. +OUI:24FD52* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation -OUI:000039* - ID_OUI_FROM_DATABASE=TOSHIBA CORPORATION +OUI:2016D8* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation -OUI:0000CB* - ID_OUI_FROM_DATABASE=COMPU-SHACK ELECTRONIC GMBH +OUI:9CB70D* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation -OUI:0000D1* - ID_OUI_FROM_DATABASE=ADAPTEC INCORPORATED +OUI:1C659D* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation -OUI:0000B6* - ID_OUI_FROM_DATABASE=MICRO-MATIC RESEARCH +OUI:001B9E* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP -OUI:000066* - ID_OUI_FROM_DATABASE=TALARIS SYSTEMS, INC. +OUI:E0CA94* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP -OUI:000014* - ID_OUI_FROM_DATABASE=NETRONIX +OUI:C0D962* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP -OUI:000072* - ID_OUI_FROM_DATABASE=MINIWARE TECHNOLOGY +OUI:00150C* + ID_OUI_FROM_DATABASE=AVM GmbH -OUI:0000AB* - ID_OUI_FROM_DATABASE=LOGIC MODELING CORPORATION +OUI:744401* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:000029* - ID_OUI_FROM_DATABASE=IMC NETWORKS CORP. +OUI:E091F5* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:0080CD* - ID_OUI_FROM_DATABASE=MICRONICS COMPUTER, INC. +OUI:001B2F* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:008083* - ID_OUI_FROM_DATABASE=AMDAHL +OUI:00223F* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:008003* - ID_OUI_FROM_DATABASE=HYTEC ELECTRONICS LTD. +OUI:E0469A* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:00801B* - ID_OUI_FROM_DATABASE=KODIAK TECHNOLOGY +OUI:F40B93* + ID_OUI_FROM_DATABASE=BlackBerry RTS -OUI:0080CC* - ID_OUI_FROM_DATABASE=MICROWAVE BYPASS SYSTEMS +OUI:68ED43* + ID_OUI_FROM_DATABASE=BlackBerry RTS -OUI:080079* - ID_OUI_FROM_DATABASE=THE DROID WORKS +OUI:34BB1F* + ID_OUI_FROM_DATABASE=BlackBerry RTS -OUI:080077* - ID_OUI_FROM_DATABASE=TSL COMMUNICATIONS LTD. +OUI:489D24* + ID_OUI_FROM_DATABASE=BlackBerry RTS -OUI:080071* - ID_OUI_FROM_DATABASE=MATRA (DSIE) +OUI:000F86* + ID_OUI_FROM_DATABASE=BlackBerry RTS -OUI:08006A* - ID_OUI_FROM_DATABASE=ATT BELL LABORATORIES +OUI:001333* + ID_OUI_FROM_DATABASE=BaudTec Corporation -OUI:08005F* - ID_OUI_FROM_DATABASE=SABER TECHNOLOGY CORP. +OUI:507E5D* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation -OUI:08005C* - ID_OUI_FROM_DATABASE=FOUR PHASE SYSTEMS +OUI:849CA6* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation -OUI:08005B* - ID_OUI_FROM_DATABASE=VTA TECHNOLOGIES INC. +OUI:1CC63C* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation -OUI:080058* - ID_OUI_FROM_DATABASE=SYSTEMS CONCEPTS +OUI:C02506* + ID_OUI_FROM_DATABASE=AVM GmbH -OUI:080050* - ID_OUI_FROM_DATABASE=DAISY SYSTEMS CORP. +OUI:0896D7* + ID_OUI_FROM_DATABASE=AVM GmbH -OUI:080052* - ID_OUI_FROM_DATABASE=INSYSTEC +OUI:008EF2* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:080047* - ID_OUI_FROM_DATABASE=SEQUENT COMPUTER SYSTEMS INC. +OUI:4494FC* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:080045* - ID_OUI_FROM_DATABASE=CONCURRENT COMPUTER CORP. +OUI:20E52A* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:080044* - ID_OUI_FROM_DATABASE=DAVID SYSTEMS INC. +OUI:9CD36D* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:080041* - ID_OUI_FROM_DATABASE=RACAL-MILGO INFORMATION SYS.. +OUI:C40415* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:080038* - ID_OUI_FROM_DATABASE=BULL S.A.S. +OUI:08BD43* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:08003C* - ID_OUI_FROM_DATABASE=SCHLUMBERGER WELL SERVICES +OUI:4C09D4* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation -OUI:080034* - ID_OUI_FROM_DATABASE=FILENET CORPORATION +OUI:DC446D* + ID_OUI_FROM_DATABASE=Allwinner Technology Co., Ltd -OUI:08002C* - ID_OUI_FROM_DATABASE=BRITTON LEE INC. +OUI:BC620E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:0000B9* - ID_OUI_FROM_DATABASE=MCDONNELL DOUGLAS COMPUTER SYS +OUI:78F557* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:00002D* - ID_OUI_FROM_DATABASE=CHROMATICS INC +OUI:E02861* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:00004A* - ID_OUI_FROM_DATABASE=ADC CODENOLL TECHNOLOGY CORP. +OUI:C4473F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:0000C0* - ID_OUI_FROM_DATABASE=WESTERN DIGITAL CORPORATION +OUI:000AF7* + ID_OUI_FROM_DATABASE=Broadcom -OUI:000040* - ID_OUI_FROM_DATABASE=APPLICON, INC. +OUI:000DB6* + ID_OUI_FROM_DATABASE=Broadcom -OUI:00005D* - ID_OUI_FROM_DATABASE=CS TELECOM +OUI:18C086* + ID_OUI_FROM_DATABASE=Broadcom -OUI:08008E* - ID_OUI_FROM_DATABASE=Tandem Computers +OUI:C03E0F* + ID_OUI_FROM_DATABASE=BSkyB Ltd -OUI:080086* - ID_OUI_FROM_DATABASE=KONICA MINOLTA HOLDINGS, INC. +OUI:0020D4* + ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. -OUI:080083* - ID_OUI_FROM_DATABASE=Seiko Instruments Inc. +OUI:00001D* + ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. -OUI:080080* - ID_OUI_FROM_DATABASE=AES DATA INC. +OUI:0060BB* + ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. -OUI:080030* - ID_OUI_FROM_DATABASE=ROYAL MELBOURNE INST OF TECH +OUI:D0542D* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. -OUI:080064* - ID_OUI_FROM_DATABASE=Sitasys AG +OUI:001FC7* + ID_OUI_FROM_DATABASE=Casio Hitachi Mobile Communications Co., Ltd. -OUI:00DD09* - ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. +OUI:ACEE9E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:08008A* - ID_OUI_FROM_DATABASE=PerfTech, Inc. +OUI:C08997* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00DD04* - ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. +OUI:2827BF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:080066* - ID_OUI_FROM_DATABASE=AGFA CORPORATION +OUI:F05B7B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:08001A* - ID_OUI_FROM_DATABASE=TIARA/ 10NET +OUI:7CF90E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:080090* - ID_OUI_FROM_DATABASE=SONOMA SYSTEMS +OUI:AC5A14* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:08000B* - ID_OUI_FROM_DATABASE=UNISYS CORPORATION +OUI:B0C559* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:080017* - ID_OUI_FROM_DATABASE=NATIONAL SEMICONDUCTOR +OUI:BCD11F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00005E* - ID_OUI_FROM_DATABASE=ICANN, IANA Department +OUI:A0B4A5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:0000AF* - ID_OUI_FROM_DATABASE=Canberra Industries, Inc. +OUI:80656D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:0000EC* - ID_OUI_FROM_DATABASE=MICROPROCESS +OUI:48137E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00009E* - ID_OUI_FROM_DATABASE=MARLI S.A. +OUI:E83A12* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:000042* - ID_OUI_FROM_DATABASE=METIER MANAGEMENT SYSTEMS LTD. +OUI:9C0298* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00008D* - ID_OUI_FROM_DATABASE=Cryptek Inc. +OUI:6C8336* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:000065* - ID_OUI_FROM_DATABASE=Network General Corporation +OUI:B8C68E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00004D* - ID_OUI_FROM_DATABASE=DCI CORPORATION +OUI:74458A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:080024* - ID_OUI_FROM_DATABASE=10NET COMMUNICATIONS/DCA +OUI:A49A58* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:08001E* - ID_OUI_FROM_DATABASE=APOLLO COMPUTER INC. +OUI:B4EF39* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:08001B* - ID_OUI_FROM_DATABASE=EMC Corporation +OUI:14A364* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00DD0D* - ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. +OUI:3CA10D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:AA0002* - ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION +OUI:206E9C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:080005* - ID_OUI_FROM_DATABASE=SYMBOLICS INC. +OUI:183F47* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:000000* - ID_OUI_FROM_DATABASE=XEROX CORPORATION +OUI:0C715D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:0040D6* - ID_OUI_FROM_DATABASE=LOCAMATION B.V. +OUI:0C1420* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:800010* - ID_OUI_FROM_DATABASE=ATT BELL LABORATORIES +OUI:A80600* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:AA0003* - ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION +OUI:6CF373* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:080008* - ID_OUI_FROM_DATABASE=BOLT BERANEK AND NEWMAN INC. +OUI:90F1AA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:08000E* - ID_OUI_FROM_DATABASE=NCR CORPORATION +OUI:C4576E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00006F* - ID_OUI_FROM_DATABASE=Madge Ltd. +OUI:78BDBC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:00005A* - ID_OUI_FROM_DATABASE=SysKonnect GmbH +OUI:3872C0* + ID_OUI_FROM_DATABASE=Comtrend Corporation -OUI:000023* - ID_OUI_FROM_DATABASE=ABB INDUSTRIAL SYSTEMS AB +OUI:F4068D* + ID_OUI_FROM_DATABASE=devolo AG -OUI:000045* - ID_OUI_FROM_DATABASE=FORD AEROSPACE & COMM. CORP. +OUI:000BCA* + ID_OUI_FROM_DATABASE=DATAVAN TC -OUI:0000BC* - ID_OUI_FROM_DATABASE=Rockwell Automation +OUI:00507F* + ID_OUI_FROM_DATABASE=DrayTek Corp. -OUI:0000C3* - ID_OUI_FROM_DATABASE=HARRIS CORP COMPUTER SYS DIV +OUI:3C8970* + ID_OUI_FROM_DATABASE=Neosfar -OUI:000004* - ID_OUI_FROM_DATABASE=XEROX CORPORATION +OUI:C43655* + ID_OUI_FROM_DATABASE=Shenzhen Fenglian Technology Co., Ltd. -OUI:000009* - ID_OUI_FROM_DATABASE=XEROX CORPORATION +OUI:78CB68* + ID_OUI_FROM_DATABASE=DAEHAP HYPER-TECH -OUI:00003D* - ID_OUI_FROM_DATABASE=UNISYS +OUI:001A7F* + ID_OUI_FROM_DATABASE=GCI Science & Technology Co.,LTD -OUI:F82C18* - ID_OUI_FROM_DATABASE=2Wire Inc +OUI:00054F* + ID_OUI_FROM_DATABASE=Private -OUI:00173F* - ID_OUI_FROM_DATABASE=Belkin International Inc. +OUI:D04D2C* + ID_OUI_FROM_DATABASE=Roku, Inc. -OUI:388602* - ID_OUI_FROM_DATABASE=Flexoptix GmbH +OUI:E00C7F* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. -OUI:F4EB38* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:58BDA3* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. -OUI:001E74* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:0025A0* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. -OUI:00604C* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:002659* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. -OUI:002691* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:8C56C5* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. -OUI:C0D044* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:CC9E00* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. -OUI:6C2E85* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:001656* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. -OUI:CC33BB* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:00191D* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. -OUI:681590* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:0019FD* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. -OUI:5464D9* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:001EA9* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. -OUI:00023F* - ID_OUI_FROM_DATABASE=COMPAL ELECTRONICS, INC. +OUI:A84481* + ID_OUI_FROM_DATABASE=Nokia Corporation -OUI:0080C2* - ID_OUI_FROM_DATABASE=IEEE 802.1 +OUI:8844F6* + ID_OUI_FROM_DATABASE=Nokia Corporation -OUI:C46699* - ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. +OUI:A87B39* + ID_OUI_FROM_DATABASE=Nokia Corporation -OUI:383BC8* - ID_OUI_FROM_DATABASE=2Wire Inc +OUI:14C126* + ID_OUI_FROM_DATABASE=Nokia Corporation -OUI:DC7FA4* - ID_OUI_FROM_DATABASE=2Wire Inc +OUI:4C2578* + ID_OUI_FROM_DATABASE=Nokia Corporation -OUI:001288* - ID_OUI_FROM_DATABASE=2Wire Inc +OUI:001EA4* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S -OUI:001EC7* - ID_OUI_FROM_DATABASE=2Wire Inc +OUI:001262* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S -OUI:28162E* - ID_OUI_FROM_DATABASE=2Wire Inc +OUI:00174B* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S -OUI:3CEA4F* - ID_OUI_FROM_DATABASE=2Wire Inc +OUI:002547* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S -OUI:848F69* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:001DE9* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S -OUI:90B11C* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:001D3B* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S -OUI:F8CAB8* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:0014A7* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S -OUI:24B6FD* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:001CD6* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S -OUI:000D56* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:D099D5* + ID_OUI_FROM_DATABASE=Alcatel-Lucent -OUI:00123F* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:DC0077* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:001372* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:0060DC* + ID_OUI_FROM_DATABASE=NEC Magnus Communications,Ltd. -OUI:74867A* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:F45C89* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:3417EB* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:0021FD* + ID_OUI_FROM_DATABASE=LACROIX TRAFFIC S.A.U -OUI:EC8892* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:4CB44A* + ID_OUI_FROM_DATABASE=NANOWAVE Technologies Inc. -OUI:B07994* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:78C3E9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:141AA3* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:9C5C8E* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. -OUI:CCC3EA* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:70884D* + ID_OUI_FROM_DATABASE=JAPAN RADIO CO., LTD. -OUI:34BB26* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:4C55CC* + ID_OUI_FROM_DATABASE=Zentri Pty Ltd -OUI:40786A* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:BCEC5D* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:0019B9* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:DC415F* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:002219* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:30636B* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:00B0D0* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:84683E* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:5C260A* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:C88722* + ID_OUI_FROM_DATABASE=Lumenpulse -OUI:B083FE* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:FC1A11* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. -OUI:141877* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:30A9DE* + ID_OUI_FROM_DATABASE=LG Innotek -OUI:0024E8* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:E0CDFD* + ID_OUI_FROM_DATABASE=Beijing E3Control Technology Co, LTD -OUI:A48E0A* - ID_OUI_FROM_DATABASE=DeLaval International AB +OUI:208B37* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd -OUI:00215C* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:08BE77* + ID_OUI_FROM_DATABASE=Green Electronics -OUI:002315* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:280C28* + ID_OUI_FROM_DATABASE=Unigen DataStorage Corporation -OUI:001500* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:980CA5* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. -OUI:104A7D* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:1CC035* + ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. -OUI:A4C494* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:34543C* + ID_OUI_FROM_DATABASE=TAKAOKA TOKO CO.,LTD. -OUI:902E1C* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:D49524* + ID_OUI_FROM_DATABASE=Clover Network, Inc. -OUI:3CFDFE* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:0034DA* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:B8BF83* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:9046A2* + ID_OUI_FROM_DATABASE=Tedipay UK Ltd -OUI:001DE1* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:6479A7* + ID_OUI_FROM_DATABASE=Phison Electronics Corp. -OUI:0022FB* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:C83870* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:081196* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:288335* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:6036DD* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:44783E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:A0369F* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:202D07* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:502DA2* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:0452C7* + ID_OUI_FROM_DATABASE=Bose Corporation -OUI:4C79BA* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:D4612E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:4CEB42* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:1C6758* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:606720* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:E85659* + ID_OUI_FROM_DATABASE=Advanced-Connectek Inc. -OUI:84A6C8* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:8801F2* + ID_OUI_FROM_DATABASE=Vitec System Engineering Inc. -OUI:5891CF* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:FC084A* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED -OUI:88532E* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:D4AD2D* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD -OUI:0024D7* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:48555F* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD -OUI:C40938* - ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD +OUI:847BEB* + ID_OUI_FROM_DATABASE=Dell Inc. -OUI:00AA02* - ID_OUI_FROM_DATABASE=Intel Corporation +OUI:F8C96C* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD -OUI:5CD2E4* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:34BF90* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD -OUI:04BD88* - ID_OUI_FROM_DATABASE=Aruba Networks +OUI:D467E7* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD -OUI:000B86* - ID_OUI_FROM_DATABASE=Aruba Networks +OUI:04C1B9* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:689361* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. -OUI:8896F2* - ID_OUI_FROM_DATABASE=Valeo Schalter und Sensoren GmbH +OUI:A082AC* + ID_OUI_FROM_DATABASE=Linear DMS Solutions Sdn. Bhd. -OUI:80A589* - ID_OUI_FROM_DATABASE=AzureWave Technology Inc. +OUI:002697* + ID_OUI_FROM_DATABASE=Alpha Technologies Inc. -OUI:0CCC26* - ID_OUI_FROM_DATABASE=Airenetworks +OUI:4CB8B5* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd -OUI:4CB0E8* - ID_OUI_FROM_DATABASE=Beijing RongZhi xinghua technology co., LTD +OUI:1CABC0* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc -OUI:4C14A3* - ID_OUI_FROM_DATABASE=TCL Technoly Electronics (Huizhou) Co., Ltd. +OUI:84E323* + ID_OUI_FROM_DATABASE=Green Wave Telecommunication SDN BHD -OUI:F48E38* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:44650D* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. -OUI:D887D5* - ID_OUI_FROM_DATABASE=Leadcore Technology CO.,LTD +OUI:D897BA* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION -OUI:00DA55* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:7071BC* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION -OUI:80D21D* - ID_OUI_FROM_DATABASE=AzureWave Technology Inc. +OUI:E06995* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION -OUI:705A0F* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:54D9E4* + ID_OUI_FROM_DATABASE=BRILLIANTTS CO., LTD -OUI:586356* - ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED +OUI:E4F3F5* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. -OUI:B046FC* - ID_OUI_FROM_DATABASE=MitraStar Technology Corp. +OUI:00089F* + ID_OUI_FROM_DATABASE=EFM Networks -OUI:08A95A* - ID_OUI_FROM_DATABASE=AzureWave Technology Inc. +OUI:00185C* + ID_OUI_FROM_DATABASE=EDSLAB Technologies -OUI:6CADF8* - ID_OUI_FROM_DATABASE=AzureWave Technology Inc. +OUI:000E2E* + ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. -OUI:54271E* - ID_OUI_FROM_DATABASE=AzureWave Technology Inc. +OUI:00020E* + ID_OUI_FROM_DATABASE=ECI Telecom Ltd. -OUI:008C54* - ID_OUI_FROM_DATABASE=ADB Broadband Italia +OUI:00115B* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. -OUI:F0842F* - ID_OUI_FROM_DATABASE=ADB Broadband Italia +OUI:000795* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. -OUI:8CB864* - ID_OUI_FROM_DATABASE=AcSiP Technology Corp. +OUI:B8AEED* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. -OUI:0020E0* - ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc +OUI:C03FD5* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. -OUI:0004E3* - ID_OUI_FROM_DATABASE=Accton Technology Corp +OUI:7427EA* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. -OUI:409558* - ID_OUI_FROM_DATABASE=Aisino Corporation +OUI:0000C9* + ID_OUI_FROM_DATABASE=Emulex Corporation -OUI:00D0C9* - ID_OUI_FROM_DATABASE=ADVANTECH CO., LTD. +OUI:001A45* + ID_OUI_FROM_DATABASE=GN Netcom A/S -OUI:002553* - ID_OUI_FROM_DATABASE=ADB Broadband Italia +OUI:00168F* + ID_OUI_FROM_DATABASE=GN Netcom A/S -OUI:00238E* - ID_OUI_FROM_DATABASE=ADB Broadband Italia +OUI:083FBC* + ID_OUI_FROM_DATABASE=zte corporation -OUI:001CA2* - ID_OUI_FROM_DATABASE=ADB Broadband Italia +OUI:042AE2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0017C2* - ID_OUI_FROM_DATABASE=ADB Broadband Italia +OUI:1C1B0D* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. -OUI:D0D412* - ID_OUI_FROM_DATABASE=ADB Broadband Italia +OUI:00104F* + ID_OUI_FROM_DATABASE=Oracle Corporation -OUI:000FA3* - ID_OUI_FROM_DATABASE=Alpha Networks Inc. +OUI:000782* + ID_OUI_FROM_DATABASE=Oracle Corporation -OUI:001D6A* - ID_OUI_FROM_DATABASE=Alpha Networks Inc. +OUI:E42F56* + ID_OUI_FROM_DATABASE=OptoMET GmbH -OUI:0000F4* - ID_OUI_FROM_DATABASE=Allied Telesis, Inc. +OUI:00A045* + ID_OUI_FROM_DATABASE=PHOENIX CONTACT Electronics GmbH -OUI:10AE60* - ID_OUI_FROM_DATABASE=Private +OUI:00266C* + ID_OUI_FROM_DATABASE=INVENTEC Corporation -OUI:F04F7C* - ID_OUI_FROM_DATABASE=Private +OUI:001E25* + ID_OUI_FROM_DATABASE=INTEK DIGITAL -OUI:70F1A1* - ID_OUI_FROM_DATABASE=Liteon Technology Corporation +OUI:A0B662* + ID_OUI_FROM_DATABASE=Acutvista Innovation Co., Ltd. -OUI:6CFAA7* - ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. +OUI:00C0F0* + ID_OUI_FROM_DATABASE=Kingston Technology Company, Inc. -OUI:0024EF* - ID_OUI_FROM_DATABASE=Sony Mobile Communications AB +OUI:4C8FA5* + ID_OUI_FROM_DATABASE=Jastec -OUI:6C0E0D* - ID_OUI_FROM_DATABASE=Sony Mobile Communications AB +OUI:000C49* + ID_OUI_FROM_DATABASE=Dangaard Telecom Denmark A/S -OUI:B4527D* - ID_OUI_FROM_DATABASE=Sony Mobile Communications AB +OUI:CCE17F* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:E063E5* - ID_OUI_FROM_DATABASE=Sony Mobile Communications AB +OUI:44F477* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:000E07* - ID_OUI_FROM_DATABASE=Sony Mobile Communications AB +OUI:5C4527* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:001A75* - ID_OUI_FROM_DATABASE=Sony Mobile Communications AB +OUI:F01C2D* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:0016B8* - ID_OUI_FROM_DATABASE=Sony Mobile Communications AB +OUI:F8C001* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:001D28* - ID_OUI_FROM_DATABASE=Sony Mobile Communications AB +OUI:78FE3D* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:001FE4* - ID_OUI_FROM_DATABASE=Sony Mobile Communications AB +OUI:54E032* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:002298* - ID_OUI_FROM_DATABASE=Sony Mobile Communications AB +OUI:3C6104* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:24FD52* - ID_OUI_FROM_DATABASE=Liteon Technology Corporation +OUI:BC7574* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:2016D8* - ID_OUI_FROM_DATABASE=Liteon Technology Corporation +OUI:20A680* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:9CB70D* - ID_OUI_FROM_DATABASE=Liteon Technology Corporation +OUI:0019E2* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:1C659D* - ID_OUI_FROM_DATABASE=Liteon Technology Corporation +OUI:001F12* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:001B9E* - ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP +OUI:0024DC* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:E0CA94* - ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP +OUI:50C58D* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:C0D962* - ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP +OUI:000585* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:00150C* - ID_OUI_FROM_DATABASE=AVM GmbH +OUI:003146* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:744401* - ID_OUI_FROM_DATABASE=NETGEAR +OUI:80ACAC* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:E091F5* - ID_OUI_FROM_DATABASE=NETGEAR +OUI:50DD4F* + ID_OUI_FROM_DATABASE=Automation Components, Inc -OUI:001B2F* - ID_OUI_FROM_DATABASE=NETGEAR +OUI:904D4A* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:00223F* - ID_OUI_FROM_DATABASE=NETGEAR +OUI:7C79E8* + ID_OUI_FROM_DATABASE=PayRange Inc. -OUI:E0469A* - ID_OUI_FROM_DATABASE=NETGEAR +OUI:540593* + ID_OUI_FROM_DATABASE=WOORI ELEC Co.,Ltd -OUI:F40B93* - ID_OUI_FROM_DATABASE=BlackBerry RTS +OUI:A067BE* + ID_OUI_FROM_DATABASE=Sicon srl -OUI:68ED43* - ID_OUI_FROM_DATABASE=BlackBerry RTS +OUI:C4CAD9* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited -OUI:34BB1F* - ID_OUI_FROM_DATABASE=BlackBerry RTS +OUI:74258A* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited -OUI:489D24* - ID_OUI_FROM_DATABASE=BlackBerry RTS +OUI:70F96D* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited -OUI:000F86* - ID_OUI_FROM_DATABASE=BlackBerry RTS +OUI:00260F* + ID_OUI_FROM_DATABASE=Linn Products Ltd -OUI:001333* - ID_OUI_FROM_DATABASE=BaudTec Corporation +OUI:F845AD* + ID_OUI_FROM_DATABASE=Konka Group Co., Ltd. -OUI:507E5D* - ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation +OUI:000358* + ID_OUI_FROM_DATABASE=Hanyang Digitech Co.Ltd -OUI:849CA6* - ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation +OUI:000761* + ID_OUI_FROM_DATABASE=29530 -OUI:1CC63C* - ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation +OUI:60512C* + ID_OUI_FROM_DATABASE=TCT mobile ltd -OUI:C02506* - ID_OUI_FROM_DATABASE=AVM GmbH +OUI:905F2E* + ID_OUI_FROM_DATABASE=TCT mobile ltd -OUI:0896D7* - ID_OUI_FROM_DATABASE=AVM GmbH +OUI:4C0B3A* + ID_OUI_FROM_DATABASE=TCT mobile ltd -OUI:008EF2* - ID_OUI_FROM_DATABASE=NETGEAR +OUI:C02FF1* + ID_OUI_FROM_DATABASE=Volta Networks -OUI:4494FC* - ID_OUI_FROM_DATABASE=NETGEAR +OUI:4882F2* + ID_OUI_FROM_DATABASE=Appel Elektronik GmbH -OUI:20E52A* - ID_OUI_FROM_DATABASE=NETGEAR +OUI:0C5101* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:9CD36D* - ID_OUI_FROM_DATABASE=NETGEAR +OUI:086D41* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:C40415* - ID_OUI_FROM_DATABASE=NETGEAR +OUI:04D3CF* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:08BD43* - ID_OUI_FROM_DATABASE=NETGEAR +OUI:30C82A* + ID_OUI_FROM_DATABASE=WI-BIZ srl -OUI:4C09D4* - ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation +OUI:0062EC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:DC446D* - ID_OUI_FROM_DATABASE=Allwinner Technology Co., Ltd +OUI:0C8A87* + ID_OUI_FROM_DATABASE=AgLogica Holdings, Inc -OUI:BC620E* +OUI:34A2A2* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:78F557* +OUI:20F17C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:E02861* +OUI:34B354* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:C4473F* +OUI:749D8F* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:000AF7* - ID_OUI_FROM_DATABASE=Broadcom +OUI:346AC2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:000DB6* - ID_OUI_FROM_DATABASE=Broadcom +OUI:50F5DA* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. -OUI:18C086* - ID_OUI_FROM_DATABASE=Broadcom +OUI:8CD2E9* + ID_OUI_FROM_DATABASE=NIPPON SMT Co.Ltd -OUI:C03E0F* - ID_OUI_FROM_DATABASE=BSkyB Ltd +OUI:C83DFC* + ID_OUI_FROM_DATABASE=Pioneer DJ Corporation -OUI:0020D4* - ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. +OUI:0016FB* + ID_OUI_FROM_DATABASE=SHENZHEN MTC CO LTD -OUI:00001D* - ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. +OUI:381DD9* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED -OUI:0060BB* - ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. +OUI:6C9522* + ID_OUI_FROM_DATABASE=Scalys -OUI:D0542D* - ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. +OUI:8C59C3* + ID_OUI_FROM_DATABASE=ADB Italia -OUI:001FC7* - ID_OUI_FROM_DATABASE=Casio Hitachi Mobile Communications Co., Ltd. +OUI:60C0BF* + ID_OUI_FROM_DATABASE=ON Semiconductor -OUI:ACEE9E* +OUI:98398E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:C08997* +OUI:348A7B* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:2827BF* +OUI:BC765E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:F05B7B* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:E0A8B8* + ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited -OUI:7CF90E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:B88198* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:AC5A14* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:E4FB8F* + ID_OUI_FROM_DATABASE=MOBIWIRE MOBILES (NINGBO) CO.,LTD -OUI:B0C559* +OUI:78009E* ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:BCD11F* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:C8AFE3* + ID_OUI_FROM_DATABASE=Hefei Radio Communication Technology Co., Ltd -OUI:A0B4A5* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:7C3548* + ID_OUI_FROM_DATABASE=Transcend Information -OUI:80656D* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:E83A97* + ID_OUI_FROM_DATABASE=Toshiba Corporation -OUI:48137E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:9C8ECD* + ID_OUI_FROM_DATABASE=Amcrest Technologies -OUI:E83A12* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:282536* + ID_OUI_FROM_DATABASE=SHENZHEN HOLATEK CO.,LTD -OUI:9C0298* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:FCA89A* + ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd -OUI:6C8336* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:B8F8BE* + ID_OUI_FROM_DATABASE=BLUECOM -OUI:B8C68E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:6073BC* + ID_OUI_FROM_DATABASE=zte corporation -OUI:74458A* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:90EED9* + ID_OUI_FROM_DATABASE=UNIVERSAL DE DESARROLLOS ELECTRÓNICOS, SA -OUI:A49A58* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:043110* + ID_OUI_FROM_DATABASE=Inspur Group Co., Ltd. -OUI:B4EF39* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:00215B* + ID_OUI_FROM_DATABASE=SenseAnywhere -OUI:14A364* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:C816BD* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. -OUI:3CA10D* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:587E61* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. -OUI:206E9C* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:340AFF* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. -OUI:183F47* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:F85A00* + ID_OUI_FROM_DATABASE=Sanford LP -OUI:0C715D* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:5067F0* + ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation -OUI:0C1420* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:C86C87* + ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation -OUI:A80600* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:D8E0B8* + ID_OUI_FROM_DATABASE=BULAT LLC -OUI:6CF373* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:68C44D* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:90F1AA* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:48FCB6* + ID_OUI_FROM_DATABASE=LAVA INTERNATIONAL(H.K) LIMITED -OUI:C4576E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:CC3540* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:78BDBC* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:C42795* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:3872C0* - ID_OUI_FROM_DATABASE=Comtrend Corporation +OUI:58238C* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:F4068D* - ID_OUI_FROM_DATABASE=devolo AG +OUI:705A9E* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:000BCA* - ID_OUI_FROM_DATABASE=DATAVAN TC +OUI:80C6AB* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:00507F* - ID_OUI_FROM_DATABASE=DrayTek Corp. +OUI:90A4DE* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation -OUI:3C8970* - ID_OUI_FROM_DATABASE=Neosfar +OUI:3C970E* + ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd. -OUI:C43655* - ID_OUI_FROM_DATABASE=Shenzhen Fenglian Technology Co., Ltd. +OUI:30144A* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation -OUI:78CB68* - ID_OUI_FROM_DATABASE=DAEHAP HYPER-TECH +OUI:A854B2* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation -OUI:001A7F* - ID_OUI_FROM_DATABASE=GCI Science & Technology Co.,LTD +OUI:38BC1A* + ID_OUI_FROM_DATABASE=MEIZU Technology Co., Ltd. -OUI:00054F* - ID_OUI_FROM_DATABASE=Private +OUI:0004A3* + ID_OUI_FROM_DATABASE=Microchip Technology Inc. -OUI:D04D2C* - ID_OUI_FROM_DATABASE=Roku, Inc. +OUI:E0DDC0* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. -OUI:E00C7F* - ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. +OUI:982F3C* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. -OUI:58BDA3* - ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. +OUI:380DD4* + ID_OUI_FROM_DATABASE=Primax Electronics Ltd. + +OUI:98FDB4* + ID_OUI_FROM_DATABASE=Primax Electronics Ltd. + +OUI:00157D* + ID_OUI_FROM_DATABASE=POSDATA -OUI:0025A0* - ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. +OUI:F8E61A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:002659* - ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. +OUI:888322* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:8C56C5* - ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. +OUI:84B541* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:CC9E00* - ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. +OUI:18DC56* + ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd -OUI:001656* - ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. +OUI:001F46* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:00191D* - ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. +OUI:001F0A* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:0019FD* - ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. +OUI:00130A* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:001EA9* - ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. +OUI:001E7E* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:A84481* - ID_OUI_FROM_DATABASE=Nokia Corporation +OUI:001C9C* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:8844F6* - ID_OUI_FROM_DATABASE=Nokia Corporation +OUI:000CF8* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:A87B39* - ID_OUI_FROM_DATABASE=Nokia Corporation +OUI:000CF7* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:14C126* - ID_OUI_FROM_DATABASE=Nokia Corporation +OUI:001E1F* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:4C2578* - ID_OUI_FROM_DATABASE=Nokia Corporation +OUI:001C17* + ID_OUI_FROM_DATABASE=Nortel Networks -OUI:001EA4* - ID_OUI_FROM_DATABASE=Nokia Danmark A/S +OUI:00182E* + ID_OUI_FROM_DATABASE=XStreamHD -OUI:001262* - ID_OUI_FROM_DATABASE=Nokia Danmark A/S +OUI:50016B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:00174B* - ID_OUI_FROM_DATABASE=Nokia Danmark A/S +OUI:58986F* + ID_OUI_FROM_DATABASE=Revolution Display -OUI:002547* - ID_OUI_FROM_DATABASE=Nokia Danmark A/S +OUI:28AC67* + ID_OUI_FROM_DATABASE=Mach Power, Rappresentanze Internazionali s.r.l. -OUI:001DE9* - ID_OUI_FROM_DATABASE=Nokia Danmark A/S +OUI:B0B28F* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS -OUI:001D3B* - ID_OUI_FROM_DATABASE=Nokia Danmark A/S +OUI:DC1A01* + ID_OUI_FROM_DATABASE=Ecoliv Technology ( Shenzhen ) Ltd. -OUI:0014A7* - ID_OUI_FROM_DATABASE=Nokia Danmark A/S +OUI:7CFE90* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. -OUI:001CD6* - ID_OUI_FROM_DATABASE=Nokia Danmark A/S +OUI:0002C9* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. -OUI:D099D5* - ID_OUI_FROM_DATABASE=Alcatel-Lucent +OUI:D05FB8* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:DC0077* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. +OUI:C4BE84* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:0060DC* - ID_OUI_FROM_DATABASE=NEC Magnus Communications,Ltd. +OUI:78A504* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:9CAED3* - ID_OUI_FROM_DATABASE=Seiko Epson Corporation +OUI:7C669D* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:F45C89* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:D03972* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:8C3C4A* - ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS,INC +OUI:E0E5CF* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:0021FD* - ID_OUI_FROM_DATABASE=LACROIX TRAFFIC S.A.U +OUI:7CEC79* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:4CB44A* - ID_OUI_FROM_DATABASE=NANOWAVE Technologies Inc. +OUI:74D6EA* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:78C3E9* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:0017EB* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:9C5C8E* - ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. +OUI:883314* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:70884D* - ID_OUI_FROM_DATABASE=JAPAN RADIO CO., LTD. +OUI:84DD20* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:102AB3* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd +OUI:1C4593* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:4C55CC* - ID_OUI_FROM_DATABASE=Zentri Pty Ltd +OUI:5C6B32* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:BCEC5D* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:0017E4* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:DC415F* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:D03761* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:30636B* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:0024BA* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:84683E* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:0022A5* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:C88722* - ID_OUI_FROM_DATABASE=Lumenpulse +OUI:0021BA* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:FC1A11* - ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. +OUI:001833* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:30A9DE* - ID_OUI_FROM_DATABASE=LG Innotek +OUI:D8952F* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:E0CDFD* - ID_OUI_FROM_DATABASE=Beijing E3Control Technology Co, LTD +OUI:649C8E* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:208B37* - ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd +OUI:F4FC32* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:08BE77* - ID_OUI_FROM_DATABASE=Green Electronics +OUI:74DAEA* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:280C28* - ID_OUI_FROM_DATABASE=Unigen DataStorage Corporation +OUI:04A316* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:980CA5* - ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. +OUI:98072D* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:1CC035* - ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. +OUI:001AB6* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:34543C* - ID_OUI_FROM_DATABASE=TAKAOKA TOKO CO.,LTD. +OUI:C8A030* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:D49524* - ID_OUI_FROM_DATABASE=Clover Network, Inc. +OUI:34B1F7* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:0034DA* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) +OUI:C4EDBA* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:9046A2* - ID_OUI_FROM_DATABASE=Tedipay UK Ltd +OUI:A40DBC* + ID_OUI_FROM_DATABASE=Xiamen Intretech Inc. -OUI:6479A7* - ID_OUI_FROM_DATABASE=Phison Electronics Corp. +OUI:EC8EAE* + ID_OUI_FROM_DATABASE=Nagravision SA -OUI:C83870* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:606405* + ID_OUI_FROM_DATABASE=Texas Instruments -OUI:288335* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:708BCD* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. -OUI:44783E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:001A21* + ID_OUI_FROM_DATABASE=Brookhuis Applied Technologies BV -OUI:202D07* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:00A00E* + ID_OUI_FROM_DATABASE=NetScout Systems, Inc. -OUI:0452C7* - ID_OUI_FROM_DATABASE=Bose Corporation +OUI:1C330E* + ID_OUI_FROM_DATABASE=PernixData -OUI:D4612E* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:345760* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. -OUI:1C6758* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:343DC4* + ID_OUI_FROM_DATABASE=BUFFALO.INC -OUI:E85659* - ID_OUI_FROM_DATABASE=Advanced-Connectek Inc. +OUI:6CEFC6* + ID_OUI_FROM_DATABASE=SHENZHEN TWOWING TECHNOLOGIES CO.,LTD. -OUI:34E70B* - ID_OUI_FROM_DATABASE=Beijing HAN Networks Co., Ltd +OUI:986B3D* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:8801F2* - ID_OUI_FROM_DATABASE=Vitec System Engineering Inc. +OUI:CC65AD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:FC084A* - ID_OUI_FROM_DATABASE=FUJITSU LIMITED +OUI:789684* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:D4AD2D* - ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD +OUI:90C792* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:48555F* - ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD +OUI:0015CF* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:847BEB* - ID_OUI_FROM_DATABASE=Dell Inc. +OUI:386BBB* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:F8C96C* - ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD +OUI:00E06F* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:34BF90* - ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD +OUI:0004BD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:D467E7* - ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD +OUI:5C571A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:04C1B9* - ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD +OUI:001DD0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:689361* - ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. +OUI:001DD5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:A082AC* - ID_OUI_FROM_DATABASE=Linear DMS Solutions Sdn. Bhd. +OUI:001DCF* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:002697* - ID_OUI_FROM_DATABASE=Alpha Technologies Inc. +OUI:E8ED05* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:4CB8B5* - ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd +OUI:901ACA* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:1CABC0* - ID_OUI_FROM_DATABASE=Hitron Technologies. Inc +OUI:002A10* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:84E323* - ID_OUI_FROM_DATABASE=Green Wave Telecommunication SDN BHD +OUI:74E7C6* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:44650D* - ID_OUI_FROM_DATABASE=Amazon Technologies Inc. +OUI:74F612* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:D897BA* - ID_OUI_FROM_DATABASE=PEGATRON CORPORATION +OUI:DC4517* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:7071BC* - ID_OUI_FROM_DATABASE=PEGATRON CORPORATION +OUI:F80BBE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:E06995* - ID_OUI_FROM_DATABASE=PEGATRON CORPORATION +OUI:6CC1D2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:54D9E4* - ID_OUI_FROM_DATABASE=BRILLIANTTS CO., LTD +OUI:145BD1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:E4F3F5* - ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +OUI:B077AC* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:00089F* - ID_OUI_FROM_DATABASE=EFM Networks +OUI:B81619* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:00185C* - ID_OUI_FROM_DATABASE=EDSLAB Technologies +OUI:A41588* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:000E2E* - ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. +OUI:38700C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:00020E* - ID_OUI_FROM_DATABASE=ECI Telecom Ltd. +OUI:FC51A4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:00115B* - ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. +OUI:287AEE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:000795* - ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. +OUI:641269* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:B8AEED* - ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. +OUI:001CC3* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:C03FD5* - ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. +OUI:14D4FE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:7427EA* - ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. +OUI:70B14E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:0000C9* - ID_OUI_FROM_DATABASE=Emulex Corporation +OUI:D82522* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:001A45* - ID_OUI_FROM_DATABASE=GN Netcom A/S +OUI:707630* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:00168F* - ID_OUI_FROM_DATABASE=GN Netcom A/S +OUI:000CE5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:083FBC* - ID_OUI_FROM_DATABASE=zte corporation +OUI:000E5C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:042AE2* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:0015A8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:1C1B0D* - ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. +OUI:001700* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:903809* - ID_OUI_FROM_DATABASE=Ericsson AB +OUI:0019A6* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:00104F* - ID_OUI_FROM_DATABASE=Oracle Corporation +OUI:0014E8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:000782* - ID_OUI_FROM_DATABASE=Oracle Corporation +OUI:002180* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:E42F56* - ID_OUI_FROM_DATABASE=OptoMET GmbH +OUI:0026BA* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:00A045* - ID_OUI_FROM_DATABASE=PHOENIX CONTACT Electronics GmbH +OUI:002641* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:00266C* - ID_OUI_FROM_DATABASE=INVENTEC Corporation +OUI:002374* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:001E25* - ID_OUI_FROM_DATABASE=INTEK DIGITAL +OUI:0025F2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:A0B662* - ID_OUI_FROM_DATABASE=Acutvista Innovation Co., Ltd. +OUI:0019C0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:00C0F0* - ID_OUI_FROM_DATABASE=Kingston Technology Company, Inc. +OUI:886AB1* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. -OUI:4C8FA5* - ID_OUI_FROM_DATABASE=Jastec +OUI:44D6E1* + ID_OUI_FROM_DATABASE=Snuza International Pty. Ltd. -OUI:000C49* - ID_OUI_FROM_DATABASE=Dangaard Telecom Denmark A/S +OUI:0015B9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:CCE17F* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:001DF6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:44F477* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:ECE09B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:5C4527* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:606BBD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:F01C2D* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:0000F0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:F8C001* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:4844F7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:78FE3D* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:DC7144* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. -OUI:54E032* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:A00BBA* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. -OUI:3C6104* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:1C5A3E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:BC7574* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:F47B5E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:20A680* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:C44619* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:0019E2* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:F0F002* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:001F12* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:889FFA* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:0024DC* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:5CAC4C* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:50C58D* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:18F46A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:000585* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:3859F9* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:003146* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:BC8556* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:80ACAC* - ID_OUI_FROM_DATABASE=Juniper Networks +OUI:9C2A70* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:50DD4F* - ID_OUI_FROM_DATABASE=Automation Components, Inc +OUI:F82FA8* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:904D4A* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:0CEEE6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:7C79E8* - ID_OUI_FROM_DATABASE=PayRange Inc. +OUI:0C6076* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:540593* - ID_OUI_FROM_DATABASE=WOORI ELEC Co.,Ltd +OUI:90FBA6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:A067BE* - ID_OUI_FROM_DATABASE=Sicon srl +OUI:00197D* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:C4CAD9* - ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited +OUI:001C26* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:74258A* - ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited +OUI:9CAD97* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:70F96D* - ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited +OUI:2C8158* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:00260F* - ID_OUI_FROM_DATABASE=Linn Products Ltd +OUI:142D27* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:F845AD* - ID_OUI_FROM_DATABASE=Konka Group Co., Ltd. +OUI:843DC6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:000358* - ID_OUI_FROM_DATABASE=Hanyang Digitech Co.Ltd +OUI:407C7D* + ID_OUI_FROM_DATABASE=Nokia -OUI:000761* - ID_OUI_FROM_DATABASE=29530 +OUI:BC52B4* + ID_OUI_FROM_DATABASE=Nokia -OUI:60512C* - ID_OUI_FROM_DATABASE=TCT mobile ltd +OUI:FC2FAA* + ID_OUI_FROM_DATABASE=Nokia -OUI:905F2E* - ID_OUI_FROM_DATABASE=TCT mobile ltd +OUI:903AA0* + ID_OUI_FROM_DATABASE=Nokia -OUI:4C0B3A* - ID_OUI_FROM_DATABASE=TCT mobile ltd +OUI:702526* + ID_OUI_FROM_DATABASE=Nokia -OUI:C02FF1* - ID_OUI_FROM_DATABASE=Volta Networks +OUI:38F7B2* + ID_OUI_FROM_DATABASE=SEOJUN ELECTRIC -OUI:4882F2* - ID_OUI_FROM_DATABASE=Appel Elektronik GmbH +OUI:7802B7* + ID_OUI_FROM_DATABASE=ShenZhen Ultra Easy Technology CO.,LTD -OUI:0C5101* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:88AD43* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION -OUI:086D41* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:E4186B* + ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation -OUI:04D3CF* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:6C71BD* + ID_OUI_FROM_DATABASE=EZELINK TELECOM -OUI:30C82A* - ID_OUI_FROM_DATABASE=WI-BIZ srl +OUI:842519* + ID_OUI_FROM_DATABASE=Samsung Electronics -OUI:0062EC* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:88DEA9* + ID_OUI_FROM_DATABASE=Roku, Inc. -OUI:0C8A87* - ID_OUI_FROM_DATABASE=AgLogica Holdings, Inc +OUI:FC83C6* + ID_OUI_FROM_DATABASE=N-Radio Technologies Co., Ltd. -OUI:34A2A2* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:B4E782* + ID_OUI_FROM_DATABASE=Vivalnk -OUI:20F17C* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:008701* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:34B354* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:FC4203* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:749D8F* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:1C232C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:346AC2* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:08010F* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD -OUI:50F5DA* - ID_OUI_FROM_DATABASE=Amazon Technologies Inc. +OUI:CCA260* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD -OUI:8CD2E9* - ID_OUI_FROM_DATABASE=NIPPON SMT Co.Ltd +OUI:0015FF* + ID_OUI_FROM_DATABASE=Novatel Wireless Solutions, Inc. -OUI:C83DFC* - ID_OUI_FROM_DATABASE=Pioneer DJ Corporation +OUI:203CAE* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:0016FB* - ID_OUI_FROM_DATABASE=SHENZHEN MTC CO LTD +OUI:748D08* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:381DD9* - ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED +OUI:00D78F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:6C9522* - ID_OUI_FROM_DATABASE=Scalys +OUI:A03BE3* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:8C59C3* - ID_OUI_FROM_DATABASE=ADB Italia +OUI:18E29F* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. -OUI:60C0BF* - ID_OUI_FROM_DATABASE=ON Semiconductor +OUI:886B0F* + ID_OUI_FROM_DATABASE=Bluegiga Technologies OY -OUI:98398E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:98541B* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:348A7B* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:CC61E5* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:BC765E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:404E36* + ID_OUI_FROM_DATABASE=HTC Corporation -OUI:E0A8B8* - ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited +OUI:9CB206* + ID_OUI_FROM_DATABASE=PROCENTEC -OUI:B88198* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:1C40E8* + ID_OUI_FROM_DATABASE=SHENZHEN PROGRESS&WIN TECHNOLOGY CO.,LTD -OUI:E4FB8F* - ID_OUI_FROM_DATABASE=MOBIWIRE MOBILES (NINGBO) CO.,LTD +OUI:C8D3FF* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:78009E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:805EC0* + ID_OUI_FROM_DATABASE=YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD. -OUI:C8AFE3* - ID_OUI_FROM_DATABASE=Hefei Radio Communication Technology Co., Ltd +OUI:307496* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:7C3548* - ID_OUI_FROM_DATABASE=Transcend Information +OUI:708A09* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:E83A97* - ID_OUI_FROM_DATABASE=Toshiba Corporation +OUI:149D09* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:9C8ECD* - ID_OUI_FROM_DATABASE=Amcrest Technologies +OUI:008025* + ID_OUI_FROM_DATABASE=Telit Wireless Solutions GmbH -OUI:282536* - ID_OUI_FROM_DATABASE=SHENZHEN HOLATEK CO.,LTD +OUI:0001E1* + ID_OUI_FROM_DATABASE=Kinpo Electronics, Inc. -OUI:FCA89A* - ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd +OUI:006041* + ID_OUI_FROM_DATABASE=Yokogawa Digital Computer Corporation -OUI:B8F8BE* - ID_OUI_FROM_DATABASE=BLUECOM +OUI:14A78B* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. -OUI:6073BC* +OUI:D0608C* ID_OUI_FROM_DATABASE=zte corporation -OUI:90EED9* - ID_OUI_FROM_DATABASE=UNIVERSAL DE DESARROLLOS ELECTRÓNICOS, SA - -OUI:043110* - ID_OUI_FROM_DATABASE=Inspur Group Co., Ltd. +OUI:009EC8* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:00215B* - ID_OUI_FROM_DATABASE=SenseAnywhere +OUI:ACF7F3* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:C816BD* - ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. +OUI:102AB3* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:587E61* - ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. +OUI:584498* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:340AFF* - ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. +OUI:A086C6* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:F85A00* - ID_OUI_FROM_DATABASE=Sanford LP +OUI:7C1DD9* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:5067F0* - ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation +OUI:C8662C* + ID_OUI_FROM_DATABASE=Beijing Haitai Fangyuan High Technology Co,.Ltd. -OUI:C86C87* - ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation +OUI:CC8CDA* + ID_OUI_FROM_DATABASE=Shenzhen Wei Da Intelligent Technology Go.,Ltd -OUI:D8E0B8* - ID_OUI_FROM_DATABASE=BULAT LLC +OUI:D436DB* + ID_OUI_FROM_DATABASE=Jiangsu Toppower Automotive Electronics Co., Ltd -OUI:68C44D* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:64A68F* + ID_OUI_FROM_DATABASE=Zhongshan Readboy Electronics Co.,Ltd -OUI:48FCB6* - ID_OUI_FROM_DATABASE=LAVA INTERNATIONAL(H.K) LIMITED +OUI:58EF68* + ID_OUI_FROM_DATABASE=Belkin International Inc. -OUI:CC3540* - ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. +OUI:003048* + ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. -OUI:C42795* - ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. +OUI:001438* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise -OUI:58238C* - ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. +OUI:50D753* + ID_OUI_FROM_DATABASE=CONELCOM GmbH -OUI:705A9E* - ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. +OUI:4C38D5* + ID_OUI_FROM_DATABASE=MITAC COMPUTING TECHNOLOGY CORPORATION -OUI:80C6AB* - ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. +OUI:688AF0* + ID_OUI_FROM_DATABASE=zte corporation -OUI:90A4DE* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation +OUI:000BA1* + ID_OUI_FROM_DATABASE=Fujikura Solutions Ltd. -OUI:3C970E* - ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd. +OUI:AC587B* + ID_OUI_FROM_DATABASE=JCT Healthcare -OUI:30144A* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation +OUI:B0B98A* + ID_OUI_FROM_DATABASE=NETGEAR -OUI:A854B2* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation +OUI:30E171* + ID_OUI_FROM_DATABASE=Hewlett Packard -OUI:38BC1A* - ID_OUI_FROM_DATABASE=MEIZU Technology Co., Ltd. +OUI:D490E0* + ID_OUI_FROM_DATABASE=Wachendorff Automation GmbH & Co KG -OUI:0004A3* - ID_OUI_FROM_DATABASE=Microchip Technology Inc. +OUI:8C3C4A* + ID_OUI_FROM_DATABASE=NAKAYO Inc OUI:98CF53* ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. @@ -60683,680 +62945,416 @@ OUI:F06BCA* OUI:3423BA* ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) -OUI:D022BE* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) - -OUI:D02544* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) - -OUI:BC20A4* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:14F42A* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:BC851F* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:B85E7B* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:C462EA* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:0023D6* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:002491* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:001B98* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:44F459* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:34C3AC* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:94D771* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:4C3C16* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:9401C2* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:B43A28* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:A8C83A* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:849FB5* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:D0C1B1* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:F008F1* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:782079* - ID_OUI_FROM_DATABASE=ID Tech - -OUI:98234E* - ID_OUI_FROM_DATABASE=Micromedia AG - -OUI:E80036* - ID_OUI_FROM_DATABASE=Befs co,. ltd - -OUI:24590B* - ID_OUI_FROM_DATABASE=White Sky Inc. Limited - -OUI:10C60C* - ID_OUI_FROM_DATABASE=Domino UK Ltd - -OUI:3842A6* - ID_OUI_FROM_DATABASE=Ingenieurbuero Stahlkopf - -OUI:E866C4* - ID_OUI_FROM_DATABASE=Diamanti - -OUI:78471D* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:3816D1* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:004A77* - ID_OUI_FROM_DATABASE=zte corporation - -OUI:D48890* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:002566* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:00265F* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:001628* - ID_OUI_FROM_DATABASE=Magicard Ltd - -OUI:E4C801* - ID_OUI_FROM_DATABASE=BLU Products Inc - -OUI:00A6CA* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc - -OUI:9C7DA3* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:F02FA7* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:883FD3* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:A04E01* - ID_OUI_FROM_DATABASE=CENTRAL ENGINEERING co.,ltd. - -OUI:245CBF* - ID_OUI_FROM_DATABASE=NCSE - -OUI:84CD62* - ID_OUI_FROM_DATABASE=ShenZhen IDWELL Technology CO.,Ltd - -OUI:DC9FDB* - ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. - -OUI:B0958E* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. - -OUI:001A39* - ID_OUI_FROM_DATABASE=Merten GmbH&CoKG - -OUI:007B18* - ID_OUI_FROM_DATABASE=SENTRY Co., LTD. - -OUI:144D67* - ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. - -OUI:34F39A* - ID_OUI_FROM_DATABASE=Intel Corporate - -OUI:20A8B9* - ID_OUI_FROM_DATABASE=Siemens - -OUI:C81B5C* - ID_OUI_FROM_DATABASE=BCTech - -OUI:3C2AF4* - ID_OUI_FROM_DATABASE=Brother Industries, LTD. - -OUI:20719E* - ID_OUI_FROM_DATABASE=SF Technology Co.,Ltd - -OUI:E0DDC0* - ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. - -OUI:982F3C* - ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. - -OUI:380DD4* - ID_OUI_FROM_DATABASE=Primax Electronics Ltd. - -OUI:98FDB4* - ID_OUI_FROM_DATABASE=Primax Electronics Ltd. - -OUI:00157D* - ID_OUI_FROM_DATABASE=POSDATA - -OUI:F8E61A* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:888322* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:84B541* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:18DC56* - ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd - -OUI:001F46* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:001F0A* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:00130A* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:001E7E* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:001C9C* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:000CF8* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:000CF7* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:001E1F* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:001C17* - ID_OUI_FROM_DATABASE=Nortel Networks - -OUI:00182E* - ID_OUI_FROM_DATABASE=XStreamHD - -OUI:50016B* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:58986F* - ID_OUI_FROM_DATABASE=Revolution Display - -OUI:28AC67* - ID_OUI_FROM_DATABASE=Mach Power, Rappresentanze Internazionali s.r.l. - -OUI:B0B28F* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS - -OUI:DC1A01* - ID_OUI_FROM_DATABASE=Ecoliv Technology ( Shenzhen ) Ltd. - -OUI:7CFE90* - ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. - -OUI:0002C9* - ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. - -OUI:D05FB8* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:C4BE84* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:78A504* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:7C669D* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:D03972* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:E0E5CF* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:7CEC79* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:74D6EA* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:0017EB* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:883314* - ID_OUI_FROM_DATABASE=Texas Instruments - -OUI:84DD20* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:D022BE* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) -OUI:1C4593* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:D02544* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) -OUI:5C6B32* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:BC20A4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:0017E4* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:14F42A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:D03761* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:BC851F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:0024BA* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:B85E7B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:0022A5* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:C462EA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:0021BA* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:0023D6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:001833* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:002491* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:D8952F* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:001B98* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:649C8E* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:44F459* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:F4FC32* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:34C3AC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:74DAEA* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:94D771* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:04A316* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:4C3C16* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:98072D* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:9401C2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:001AB6* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:B43A28* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:C8A030* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:A8C83A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:34B1F7* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:849FB5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:C4EDBA* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:D0C1B1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:A40DBC* - ID_OUI_FROM_DATABASE=Xiamen Intretech Inc. +OUI:F008F1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:EC8EAE* - ID_OUI_FROM_DATABASE=Nagravision SA +OUI:782079* + ID_OUI_FROM_DATABASE=ID Tech -OUI:606405* - ID_OUI_FROM_DATABASE=Texas Instruments +OUI:98234E* + ID_OUI_FROM_DATABASE=Micromedia AG -OUI:708BCD* - ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. +OUI:E80036* + ID_OUI_FROM_DATABASE=Befs co,. ltd -OUI:001A21* - ID_OUI_FROM_DATABASE=Brookhuis Applied Technologies BV +OUI:24590B* + ID_OUI_FROM_DATABASE=White Sky Inc. Limited -OUI:00A00E* - ID_OUI_FROM_DATABASE=NetScout Systems, Inc. +OUI:10C60C* + ID_OUI_FROM_DATABASE=Domino UK Ltd -OUI:1C330E* - ID_OUI_FROM_DATABASE=PernixData +OUI:3842A6* + ID_OUI_FROM_DATABASE=Ingenieurbuero Stahlkopf -OUI:345760* - ID_OUI_FROM_DATABASE=MitraStar Technology Corp. +OUI:E866C4* + ID_OUI_FROM_DATABASE=Diamanti -OUI:343DC4* - ID_OUI_FROM_DATABASE=BUFFALO.INC +OUI:78471D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:6CEFC6* - ID_OUI_FROM_DATABASE=SHENZHEN TWOWING TECHNOLOGIES CO.,LTD. +OUI:3816D1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:986B3D* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:004A77* + ID_OUI_FROM_DATABASE=zte corporation -OUI:CC65AD* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:D48890* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:789684* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:002566* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:90C792* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:00265F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:0015CF* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:001628* + ID_OUI_FROM_DATABASE=Magicard Ltd -OUI:386BBB* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:E4C801* + ID_OUI_FROM_DATABASE=BLU Products Inc -OUI:00E06F* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:00A6CA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0004BD* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:9C7DA3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:5C571A* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:F02FA7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:001DD0* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:883FD3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:001DD5* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:A04E01* + ID_OUI_FROM_DATABASE=CENTRAL ENGINEERING co.,ltd. -OUI:001DCF* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:245CBF* + ID_OUI_FROM_DATABASE=NCSE -OUI:E8ED05* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:84CD62* + ID_OUI_FROM_DATABASE=ShenZhen IDWELL Technology CO.,Ltd -OUI:901ACA* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:DC9FDB* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. -OUI:002A10* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:B0958E* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:74E7C6* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:001A39* + ID_OUI_FROM_DATABASE=Merten GmbH&CoKG -OUI:74F612* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:007B18* + ID_OUI_FROM_DATABASE=SENTRY Co., LTD. -OUI:DC4517* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:144D67* + ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. -OUI:F80BBE* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:34F39A* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:6CC1D2* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:20A8B9* + ID_OUI_FROM_DATABASE=Siemens -OUI:145BD1* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:C81B5C* + ID_OUI_FROM_DATABASE=BCTech -OUI:B077AC* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:3C2AF4* + ID_OUI_FROM_DATABASE=Brother Industries, LTD. -OUI:B81619* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:20719E* + ID_OUI_FROM_DATABASE=SF Technology Co.,Ltd -OUI:A41588* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:7C95B1* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. -OUI:38700C* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:206C8A* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. -OUI:FC51A4* +OUI:5CE30E* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:287AEE* +OUI:7823AE* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:641269* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:E49E12* + ID_OUI_FROM_DATABASE=FREEBOX SAS -OUI:001CC3* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:D854A2* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. -OUI:14D4FE* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:E01C41* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. -OUI:70B14E* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:C8675E* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. -OUI:D82522* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:D4C8B0* + ID_OUI_FROM_DATABASE=Prime Electronics & Satellitics Inc. -OUI:707630* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:000FC2* + ID_OUI_FROM_DATABASE=Uniwell Corporation -OUI:000CE5* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:A4E6B1* + ID_OUI_FROM_DATABASE=Shanghai Joindata Technology Co.,Ltd. -OUI:000E5C* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:B4B384* + ID_OUI_FROM_DATABASE=ShenZhen Figigantic Electronic Co.,Ltd -OUI:0015A8* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:D46A6A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. -OUI:001700* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:A8A5E2* + ID_OUI_FROM_DATABASE=MSF-Vathauer Antriebstechnik GmbH & Co KG -OUI:0019A6* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:00425A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0014E8* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:000B4F* + ID_OUI_FROM_DATABASE=Verifone -OUI:002180* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:007686* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:0026BA* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:74FF4C* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd -OUI:002641* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:A02C36* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED -OUI:002374* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:F8D027* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation -OUI:0025F2* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:44D244* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation -OUI:0019C0* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:9CAED3* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation -OUI:886AB1* - ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. +OUI:341E6B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:44D6E1* - ID_OUI_FROM_DATABASE=Snuza International Pty. Ltd. +OUI:48F97C* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD -OUI:0015B9* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:B47447* + ID_OUI_FROM_DATABASE=CoreOS -OUI:001DF6* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:ACC1EE* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:ECE09B* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:CCA219* + ID_OUI_FROM_DATABASE=SHENZHEN ALONG INVESTMENT CO.,LTD -OUI:606BBD* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:94A04E* + ID_OUI_FROM_DATABASE=Bostex Technology Co., LTD -OUI:0000F0* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:8CA5A1* + ID_OUI_FROM_DATABASE=Oregano Systems - Design & Consulting GmbH -OUI:4844F7* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:64B0A6* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:DC7144* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. +OUI:84FCAC* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:A00BBA* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. +OUI:6C19C0* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:1C5A3E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:20AB37* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:F47B5E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:186590* + ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:C44619* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:2C0BE9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc -OUI:F0F002* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:2C6373* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD -OUI:889FFA* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:9CCC83* + ID_OUI_FROM_DATABASE=Juniper Networks -OUI:5CAC4C* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:90505A* + ID_OUI_FROM_DATABASE=unGlue, Inc -OUI:18F46A* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:60D262* + ID_OUI_FROM_DATABASE=Tzukuri Pty Ltd -OUI:3859F9* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:34FCB9* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise -OUI:BC8556* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:B0E5ED* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:9C2A70* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:C81451* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:F82FA8* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:C486E9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:0CEEE6* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:D8C771* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:0C6076* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:F0C850* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:90FBA6* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:5425EA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:00197D* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:2816AD* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:001C26* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:00A0C8* + ID_OUI_FROM_DATABASE=Adtran Inc -OUI:9CAD97* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:1CB857* + ID_OUI_FROM_DATABASE=Becon Technologies Co,.Ltd. -OUI:2C8158* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:70918F* + ID_OUI_FROM_DATABASE=Weber-Stephen Products LLC -OUI:142D27* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:803A0A* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. -OUI:843DC6* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:002207* + ID_OUI_FROM_DATABASE=Inteno Broadband Technology AB -OUI:407C7D* - ID_OUI_FROM_DATABASE=Nokia +OUI:3C7F6F* + ID_OUI_FROM_DATABASE=Telechips, Inc. -OUI:BC52B4* - ID_OUI_FROM_DATABASE=Nokia +OUI:0060D3* + ID_OUI_FROM_DATABASE=AT&T -OUI:FC2FAA* - ID_OUI_FROM_DATABASE=Nokia +OUI:800010* + ID_OUI_FROM_DATABASE=AT&T -OUI:903AA0* - ID_OUI_FROM_DATABASE=Nokia +OUI:08006A* + ID_OUI_FROM_DATABASE=AT&T -OUI:702526* - ID_OUI_FROM_DATABASE=Nokia +OUI:48A380* + ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co.,Ltd. -OUI:38F7B2* - ID_OUI_FROM_DATABASE=SEOJUN ELECTRIC +OUI:5CBA37* + ID_OUI_FROM_DATABASE=Microsoft Corporation -OUI:7802B7* - ID_OUI_FROM_DATABASE=ShenZhen Ultra Easy Technology CO.,LTD +OUI:C4836F* + ID_OUI_FROM_DATABASE=Ciena Corporation -OUI:88AD43* - ID_OUI_FROM_DATABASE=PEGATRON CORPORATION +OUI:C87324* + ID_OUI_FROM_DATABASE=Sow Cheng Technology Co. Ltd. -OUI:E4186B* - ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation +OUI:6854FD* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. -OUI:6C71BD* - ID_OUI_FROM_DATABASE=EZELINK TELECOM +OUI:3CF862* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:842519* - ID_OUI_FROM_DATABASE=Samsung Electronics +OUI:0823B2* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. -OUI:88DEA9* - ID_OUI_FROM_DATABASE=Roku, Inc. +OUI:88C3B3* + ID_OUI_FROM_DATABASE=SOVICO -OUI:FC83C6* - ID_OUI_FROM_DATABASE=N-Radio Technologies Co., Ltd. +OUI:54C415* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. -OUI:B4E782* - ID_OUI_FROM_DATABASE=Vivalnk +OUI:E05124* + ID_OUI_FROM_DATABASE=NXP Semiconductors -OUI:008701* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:005016* + ID_OUI_FROM_DATABASE=Molex Canada Ltd -OUI:FC4203* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:0005F7* + ID_OUI_FROM_DATABASE=Analog Devices, Inc. -OUI:1C232C* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:A084CB* + ID_OUI_FROM_DATABASE=SonicSensory,Inc. -OUI:08010F* - ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD +OUI:7802F8* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd -OUI:CCA260* - ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD +OUI:00238A* + ID_OUI_FROM_DATABASE=Ciena Corporation -OUI:0015FF* - ID_OUI_FROM_DATABASE=Novatel Wireless Solutions, Inc. +OUI:34E70B* + ID_OUI_FROM_DATABASE=HAN Networks Co., Ltd -OUI:203CAE* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:D47AE2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:748D08* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:903809* + ID_OUI_FROM_DATABASE=Ericsson AB -OUI:00D78F* - ID_OUI_FROM_DATABASE=Cisco Systems, Inc +OUI:542B57* + ID_OUI_FROM_DATABASE=Night Owl SP -OUI:A03BE3* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:00111B* + ID_OUI_FROM_DATABASE=Targa Systems Div L-3 Communications -OUI:18E29F* - ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. +OUI:2C7E81* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:886B0F* - ID_OUI_FROM_DATABASE=Bluegiga Technologies OY +OUI:EC01EE* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD -OUI:001438* - ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise +OUI:B8224F* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD -OUI:98541B* - ID_OUI_FROM_DATABASE=Intel Corporate +OUI:702084* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co., Ltd. -OUI:CC61E5* - ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company +OUI:F42B48* + ID_OUI_FROM_DATABASE=Ubiqam -OUI:404E36* - ID_OUI_FROM_DATABASE=HTC Corporation +OUI:68CC6E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:9CB206* - ID_OUI_FROM_DATABASE=PROCENTEC +OUI:00108C* + ID_OUI_FROM_DATABASE=Fujitsu Services Ltd -OUI:1C40E8* - ID_OUI_FROM_DATABASE=SHENZHEN PROGRESS&WIN TECHNOLOGY CO.,LTD +OUI:98D3D2* + ID_OUI_FROM_DATABASE=MEKRA Lang GmbH & Co. KG -OUI:C8D3FF* - ID_OUI_FROM_DATABASE=Hewlett Packard +OUI:F4DC41* + ID_OUI_FROM_DATABASE=YOUNGZONE CULTURE (SHANGHAI) CORP OUI:2C3996* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS @@ -61397,9 +63395,6 @@ OUI:7081EB* OUI:086698* ID_OUI_FROM_DATABASE=Apple, Inc. -OUI:002926* - ID_OUI_FROM_DATABASE=Applied Optoelectronics, Inc Taiwan Branch - OUI:2CFD37* ID_OUI_FROM_DATABASE=Blue Calypso, Inc. @@ -61445,9 +63440,6 @@ OUI:1CA770* OUI:C42F90* ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. -OUI:9C5D12* - ID_OUI_FROM_DATABASE=Aerohive Networks Inc. - OUI:A42BB0* ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. @@ -61622,9 +63614,6 @@ OUI:D837BE* OUI:A4516F* ID_OUI_FROM_DATABASE=Microsoft Mobile Oy -OUI:FC64BA* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - OUI:246081* ID_OUI_FROM_DATABASE=razberi technologies @@ -61877,21 +63866,6 @@ OUI:9017AC* OUI:94049C* ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:C46AB7* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:68DFDD* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:64B473* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:7451BA* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - -OUI:3480B3* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - OUI:5006AB* ID_OUI_FROM_DATABASE=Cisco Systems, Inc @@ -62975,9 +64949,6 @@ OUI:A8329A* OUI:B40AC6* ID_OUI_FROM_DATABASE=DEXON Systems Ltd. -OUI:480C49* - ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS,INC - OUI:5CB8CB* ID_OUI_FROM_DATABASE=Allis Communications @@ -63212,12 +65183,6 @@ OUI:D86194* OUI:589CFC* ID_OUI_FROM_DATABASE=FreeBSD Foundation -OUI:602103* - ID_OUI_FROM_DATABASE=STCUBE.INC - -OUI:085DDD* - ID_OUI_FROM_DATABASE=Mercury Corporation - OUI:98349D* ID_OUI_FROM_DATABASE=Krauss Maffei Technologies GmbH @@ -63488,9 +65453,6 @@ OUI:C0A39E* OUI:088E4F* ID_OUI_FROM_DATABASE=SF Software Solutions -OUI:E8EADA* - ID_OUI_FROM_DATABASE=Denkovi Assembly Electroncs LTD - OUI:DCAE04* ID_OUI_FROM_DATABASE=CELOXICA Ltd @@ -63587,9 +65549,6 @@ OUI:90DA4E* OUI:7038B4* ID_OUI_FROM_DATABASE=Low Tech Solutions -OUI:AC1826* - ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION - OUI:4C804F* ID_OUI_FROM_DATABASE=Armstrong Monitoring Corp @@ -63632,9 +65591,6 @@ OUI:D8DCE9* OUI:54112F* ID_OUI_FROM_DATABASE=Sulzer Pump Solutions Finland Oy -OUI:E0DCA0* - ID_OUI_FROM_DATABASE=Siemens Electrical Apparatus Ltd., Suzhou Chengdu Branch - OUI:4C55B8* ID_OUI_FROM_DATABASE=Turkcell Teknoloji @@ -64154,9 +66110,6 @@ OUI:64F242* OUI:60F281* ID_OUI_FROM_DATABASE=TRANWO TECHNOLOGY CO., LTD. -OUI:B0E892* - ID_OUI_FROM_DATABASE=SEIKO EPSON CORPORATION - OUI:642400* ID_OUI_FROM_DATABASE=Xorcom Ltd. @@ -64229,9 +66182,6 @@ OUI:78BEBD* OUI:3C9174* ID_OUI_FROM_DATABASE=ALONG COMMUNICATION TECHNOLOGY -OUI:B8E937* - ID_OUI_FROM_DATABASE=Sonos, Inc. - OUI:E8D0FA* ID_OUI_FROM_DATABASE=MKS Instruments Deutschland GmbH @@ -64685,9 +66635,6 @@ OUI:D4F63F* OUI:4C0289* ID_OUI_FROM_DATABASE=LEX COMPUTECH CO., LTD -OUI:C0E54E* - ID_OUI_FROM_DATABASE=DENX Computer Systems GmbH - OUI:E435FB* ID_OUI_FROM_DATABASE=Sabre Technology (Hull) Ltd @@ -65426,9 +67373,6 @@ OUI:F0BDF1* OUI:288915* ID_OUI_FROM_DATABASE=CashGuard Sverige AB -OUI:180675* - ID_OUI_FROM_DATABASE=DILAX Intelcom GmbH - OUI:40618E* ID_OUI_FROM_DATABASE=Stella-Green Co @@ -65930,9 +67874,6 @@ OUI:0025A3* OUI:00259C* ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC -OUI:002590* - ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. - OUI:002580* ID_OUI_FROM_DATABASE=Equipson S.A. @@ -66431,9 +68372,6 @@ OUI:002377* OUI:002371* ID_OUI_FROM_DATABASE=SOAM Systel -OUI:002365* - ID_OUI_FROM_DATABASE=ELKA-Elektronik GmbH - OUI:00236A* ID_OUI_FROM_DATABASE=SmartRG Inc @@ -66629,9 +68567,6 @@ OUI:0021B8* OUI:0021B1* ID_OUI_FROM_DATABASE=DIGITAL SOLUTIONS LTD -OUI:001F82* - ID_OUI_FROM_DATABASE=Cal-Comp Electronics & Communications Co., Ltd - OUI:001F7D* ID_OUI_FROM_DATABASE=embedded wireless GmbH @@ -67268,9 +69203,6 @@ OUI:001BCB* OUI:001BC4* ID_OUI_FROM_DATABASE=Ultratec, Inc. -OUI:001BB5* - ID_OUI_FROM_DATABASE=ZF Electronics GmbH - OUI:001BAE* ID_OUI_FROM_DATABASE=Micro Control Systems, Inc @@ -67382,9 +69314,6 @@ OUI:0019AA* OUI:0019AF* ID_OUI_FROM_DATABASE=Rigol Technologies, Inc. -OUI:001992* - ID_OUI_FROM_DATABASE=ADTRAN INC. - OUI:001997* ID_OUI_FROM_DATABASE=Soft Device Sdn Bhd @@ -72785,9 +74714,6 @@ OUI:944452* OUI:08863B* ID_OUI_FROM_DATABASE=Belkin International Inc. -OUI:2082C0* - ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd - OUI:001556* ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS @@ -72890,9 +74816,6 @@ OUI:F8E079* OUI:1430C6* ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company -OUI:044E06* - ID_OUI_FROM_DATABASE=Ericsson AB - OUI:000D67* ID_OUI_FROM_DATABASE=Ericsson @@ -73475,9 +75398,6 @@ OUI:0025DC* OUI:001CFC* ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd -OUI:00D0EC* - ID_OUI_FROM_DATABASE=NAKAYO TELECOMMUNICATIONS,INC - OUI:8CC661* ID_OUI_FROM_DATABASE=Current, powered by GE @@ -73829,428 +75749,80 @@ OUI:600810* OUI:C85B76* ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd -OUI:001AE8* - ID_OUI_FROM_DATABASE=Unify Software and Solutions GmbH & Co. KG - -OUI:945907* - ID_OUI_FROM_DATABASE=Shanghai HITE-BELDEN Network Technology Co., Ltd. - -OUI:48C663* - ID_OUI_FROM_DATABASE=GTO Access Systems LLC - -OUI:606453* - ID_OUI_FROM_DATABASE=AOD Co.,Ltd. - -OUI:6C98EB* - ID_OUI_FROM_DATABASE=Riverbed Technology, Inc. - -OUI:DC293A* - ID_OUI_FROM_DATABASE=Shenzhen Nuoshi Technology Co., LTD. - -OUI:40562D* - ID_OUI_FROM_DATABASE=Smartron India Pvt ltd - -OUI:70288B* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:00809F* - ID_OUI_FROM_DATABASE=ALE International - -OUI:B0D7CC* - ID_OUI_FROM_DATABASE=Tridonic GmbH & Co KG - -OUI:7C574E* - ID_OUI_FROM_DATABASE=COBI GmbH - -OUI:34C0F9* - ID_OUI_FROM_DATABASE=Rockwell Automation - -OUI:20C047* - ID_OUI_FROM_DATABASE=Verizon - -OUI:AC0481* - ID_OUI_FROM_DATABASE=Jiangsu Huaxing Electronics Co., Ltd. - -OUI:FC2D5E* - ID_OUI_FROM_DATABASE=zte corporation - -OUI:E811CA* - ID_OUI_FROM_DATABASE=SHANDONG KAER ELECTRIC.CO.,LTD - -OUI:ECD68A* - ID_OUI_FROM_DATABASE=Shenzhen JMicron Intelligent Technology Developmen - -OUI:1C77F6* - ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD - -OUI:08D0B7* - ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. - -OUI:28285D* - ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation - -OUI:5CF4AB* - ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation - -OUI:4C9EFF* - ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation - -OUI:0023F8* - ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation - -OUI:B0B2DC* - ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation - -OUI:90EF68* - ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation - -OUI:00248D* - ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. - -OUI:54276C* - ID_OUI_FROM_DATABASE=Jiangsu Houge Technology Corp. - -OUI:00CB00* - ID_OUI_FROM_DATABASE=Private - -OUI:FCFFAA* - ID_OUI_FROM_DATABASE=IEEE Registration Authority - -OUI:40D855* - ID_OUI_FROM_DATABASE=IEEE Registration Authority - -OUI:48DF37* - ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise - -OUI:9C93E4* - ID_OUI_FROM_DATABASE=Private - -OUI:005079* - ID_OUI_FROM_DATABASE=Private - -OUI:0028F8* - ID_OUI_FROM_DATABASE=Intel Corporate - -OUI:8416F9* - ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. - -OUI:C44BD1* - ID_OUI_FROM_DATABASE=Wallys Communications Teachnologies Co.,Ltd. - -OUI:2057AF* - ID_OUI_FROM_DATABASE=Shenzhen FH-NET OPTOELECTRONICS CO.,LTD - -OUI:34EA34* - ID_OUI_FROM_DATABASE=HangZhou Gubei Electronics Technology Co.,Ltd - -OUI:F8A9D0* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) - -OUI:CCFA00* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) - -OUI:BCF5AC* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) - -OUI:00AA70* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) - -OUI:F01C13* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) - -OUI:CC2D8C* - ID_OUI_FROM_DATABASE=LG ELECTRONICS INC - -OUI:344DF7* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) - -OUI:C49A02* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) - -OUI:0022A9* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) - -OUI:0025E5* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) - -OUI:10F96F* - ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) - -OUI:00116E* - ID_OUI_FROM_DATABASE=Peplink International Ltd. - -OUI:A091C8* - ID_OUI_FROM_DATABASE=zte corporation - -OUI:002597* - ID_OUI_FROM_DATABASE=Kalki Communication Technologies - -OUI:882BD7* - ID_OUI_FROM_DATABASE=ADDÉNERGIE TECHNOLOGIES - -OUI:9CA5C0* - ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. - -OUI:B4A5EF* - ID_OUI_FROM_DATABASE=Sercomm Corporation. - -OUI:3044A1* - ID_OUI_FROM_DATABASE=Shanghai Nanchao Information Technology - -OUI:C4F1D1* - ID_OUI_FROM_DATABASE=BEIJING SOGOU TECHNOLOGY DEVELOPMENT CO., LTD. - -OUI:38A28C* - ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. - -OUI:58528A* - ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation - -OUI:BCC00F* - ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD - -OUI:B0C287* - ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. - -OUI:CC03FA* - ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. - -OUI:28BE9B* - ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. - -OUI:509F3B* - ID_OUI_FROM_DATABASE=OI ELECTRIC CO.,LTD - -OUI:E4029B* - ID_OUI_FROM_DATABASE=Intel Corporate - -OUI:6002B4* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation - -OUI:98EECB* - ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation - -OUI:70E284* - ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation - -OUI:80EA23* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation - -OUI:D88039* - ID_OUI_FROM_DATABASE=Microchip Technology Inc. - -OUI:001D72* - ID_OUI_FROM_DATABASE=Wistron Neweb Corporation - -OUI:FC3D93* - ID_OUI_FROM_DATABASE=LONGCHEER TELECOMMUNICATION LIMITED - -OUI:48F7C0* - ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. - -OUI:00409F* - ID_OUI_FROM_DATABASE=Telco Systems, Inc. - -OUI:00E09E* - ID_OUI_FROM_DATABASE=Quantum Corporation - -OUI:00148C* - ID_OUI_FROM_DATABASE=General Dynamics Mission Systems - -OUI:A47174* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:D4A148* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:D065CA* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:8CEBC6* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:B808D7* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD - -OUI:FCF152* - ID_OUI_FROM_DATABASE=Sony Corporation - -OUI:784476* - ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. - -OUI:00183A* - ID_OUI_FROM_DATABASE=Westell Technologies Inc. - -OUI:E89A8F* - ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. - -OUI:001B24* - ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. - -OUI:CC52AF* - ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. - -OUI:001A6B* - ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. - -OUI:00DD0A* - ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. - -OUI:00039D* - ID_OUI_FROM_DATABASE=Qisda Corporation - -OUI:000B0E* - ID_OUI_FROM_DATABASE=Trapeze Networks - -OUI:002318* - ID_OUI_FROM_DATABASE=Toshiba - -OUI:E89D87* - ID_OUI_FROM_DATABASE=Toshiba - -OUI:E8E0B7* - ID_OUI_FROM_DATABASE=Toshiba - -OUI:001428* - ID_OUI_FROM_DATABASE=Vocollect Inc - -OUI:006B9E* - ID_OUI_FROM_DATABASE=Vizio, Inc - -OUI:0024FF* - ID_OUI_FROM_DATABASE=QLogic Corporation - -OUI:00A0C6* - ID_OUI_FROM_DATABASE=Qualcomm Inc. - -OUI:ECAAA0* - ID_OUI_FROM_DATABASE=PEGATRON CORPORATION - -OUI:E8886C* - ID_OUI_FROM_DATABASE=Shenzhen SC Technologies Co.,LTD - -OUI:DC35F1* - ID_OUI_FROM_DATABASE=Positivo Informática SA. - -OUI:EC6881* - ID_OUI_FROM_DATABASE=Palo Alto Networks - -OUI:44334C* - ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD - -OUI:D84FB8* - ID_OUI_FROM_DATABASE=LG ELECTRONICS - -OUI:9C220E* - ID_OUI_FROM_DATABASE=TASCAN Systems GmbH - -OUI:0CA402* - ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD - -OUI:00164D* - ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD - -OUI:FCFAF7* - ID_OUI_FROM_DATABASE=Shanghai Baud Data Communication Co.,Ltd. - -OUI:C8E776* - ID_OUI_FROM_DATABASE=PTCOM Technology - -OUI:5C497D* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd - -OUI:0005CD* - ID_OUI_FROM_DATABASE=D&M Holdings Inc. - -OUI:E0286D* - ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH - -OUI:7487A9* - ID_OUI_FROM_DATABASE=OCT Technology Co., Ltd. - -OUI:34AA99* - ID_OUI_FROM_DATABASE=Nokia - -OUI:C4084A* - ID_OUI_FROM_DATABASE=Nokia - -OUI:8C90D3* - ID_OUI_FROM_DATABASE=Nokia - -OUI:0C54B9* - ID_OUI_FROM_DATABASE=Nokia +OUI:001AE8* + ID_OUI_FROM_DATABASE=Unify Software and Solutions GmbH & Co. KG -OUI:444E1A* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:945907* + ID_OUI_FROM_DATABASE=Shanghai HITE-BELDEN Network Technology Co., Ltd. -OUI:E8E5D6* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:48C663* + ID_OUI_FROM_DATABASE=GTO Access Systems LLC -OUI:5492BE* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:606453* + ID_OUI_FROM_DATABASE=AOD Co.,Ltd. -OUI:0021D1* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:6C98EB* + ID_OUI_FROM_DATABASE=Riverbed Technology, Inc. -OUI:101DC0* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:DC293A* + ID_OUI_FROM_DATABASE=Shenzhen Nuoshi Technology Co., LTD. -OUI:0023B9* - ID_OUI_FROM_DATABASE=Airbus Defence and Space Deutschland GmbH +OUI:40562D* + ID_OUI_FROM_DATABASE=Smartron India Pvt ltd -OUI:2047ED* - ID_OUI_FROM_DATABASE=BSkyB Ltd +OUI:70288B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd -OUI:C8F946* - ID_OUI_FROM_DATABASE=LOCOSYS Technology Inc. +OUI:00809F* + ID_OUI_FROM_DATABASE=ALE International -OUI:D41D71* - ID_OUI_FROM_DATABASE=Palo Alto Networks +OUI:B0D7CC* + ID_OUI_FROM_DATABASE=Tridonic GmbH & Co KG -OUI:5C2443* - ID_OUI_FROM_DATABASE=O-Sung Telecom Co., Ltd. +OUI:7C574E* + ID_OUI_FROM_DATABASE=COBI GmbH -OUI:1861C7* - ID_OUI_FROM_DATABASE=lemonbeat GmbH +OUI:34C0F9* + ID_OUI_FROM_DATABASE=Rockwell Automation -OUI:9CDC71* - ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise +OUI:20C047* + ID_OUI_FROM_DATABASE=Verizon -OUI:C8028F* - ID_OUI_FROM_DATABASE=Nova Electronics (Shanghai) Co., Ltd. +OUI:AC0481* + ID_OUI_FROM_DATABASE=Jiangsu Huaxing Electronics Co., Ltd. -OUI:240D65* - ID_OUI_FROM_DATABASE=Shenzhen Vsun Communication Technology Co., Ltd. +OUI:FC2D5E* + ID_OUI_FROM_DATABASE=zte corporation -OUI:D8452B* - ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. +OUI:E811CA* + ID_OUI_FROM_DATABASE=SHANDONG KAER ELECTRIC.CO.,LTD -OUI:2CDD95* - ID_OUI_FROM_DATABASE=Taicang T&W Electronics +OUI:ECD68A* + ID_OUI_FROM_DATABASE=Shenzhen JMicron Intelligent Technology Developmen -OUI:5C9960* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:1C77F6* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD -OUI:CC088D* - ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:08D0B7* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. -OUI:0080FB* - ID_OUI_FROM_DATABASE=BVM LIMITED +OUI:28285D* + ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation -OUI:107223* - ID_OUI_FROM_DATABASE=TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO +OUI:5CF4AB* + ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation -OUI:AC84C9* - ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS +OUI:4C9EFF* + ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation -OUI:14EDBB* - ID_OUI_FROM_DATABASE=2Wire Inc +OUI:0023F8* + ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation -OUI:44BA46* - ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD +OUI:B0B2DC* + ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation -OUI:B4D135* - ID_OUI_FROM_DATABASE=Cloudistics +OUI:90EF68* + ID_OUI_FROM_DATABASE=ZyXEL Communications Corporation OUI:A8AD3D* ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd @@ -74432,40 +76004,76 @@ OUI:001830* OUI:1CBA8C* ID_OUI_FROM_DATABASE=Texas Instruments -OUI:7CA97D* - ID_OUI_FROM_DATABASE=Objenious - OUI:58FB84* ID_OUI_FROM_DATABASE=Intel Corporate OUI:E0E7BB* ID_OUI_FROM_DATABASE=Nureva, Inc. +OUI:7CA97D* + ID_OUI_FROM_DATABASE=Objenious + OUI:BC8AA3* ID_OUI_FROM_DATABASE=NHN Entertainment OUI:70A84C* ID_OUI_FROM_DATABASE=MONAD., Inc. -OUI:407009* +OUI:00D088* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:94877C* +OUI:001675* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:001DD2* +OUI:0016B5* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:9C3426* +OUI:001784* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:3C7A8A* +OUI:0017E2* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:000FCC* +OUI:CC7D37* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:BCCAB5* +OUI:001A77* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:984B4A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0015A4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0015A3* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:7CBFB1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:8096B1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00909C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001180* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0017EE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:407009* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:94877C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DD2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:9C3426* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. OUI:5C8FE0* @@ -74486,303 +76094,684 @@ OUI:00A289* OUI:ACEC80* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:0015A4* +OUI:3C7A8A* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:0015A3* +OUI:000FCC* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:7CBFB1* +OUI:BCCAB5* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:8096B1* +OUI:80F503* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:00909C* +OUI:8496D8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:D42C0F* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E0B7B1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0024A0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:C0C522* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:5CB066* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002210* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00211E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E48399* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002636* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0012C9* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001CFB* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001C12* ID_OUI_FROM_DATABASE=ARRIS Group, Inc. -OUI:001180* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:001FC4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:6C1E90* + ID_OUI_FROM_DATABASE=Hansol Technics Co., Ltd. + +OUI:486DBB* + ID_OUI_FROM_DATABASE=Vestel Elektronik San ve Tic. A.Ş. + +OUI:E09DFA* + ID_OUI_FROM_DATABASE=Wanan Hongsheng Electronic Co.Ltd + +OUI:34E71C* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:182861* + ID_OUI_FROM_DATABASE=AirTies Wireless Networks + +OUI:8841FC* + ID_OUI_FROM_DATABASE=AirTies Wireless Networks + +OUI:182666* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C06599* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:CC07AB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E84E84* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:50FC9F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E432CB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:889B39* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BCB1F3* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:38ECE4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:CCF9E8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F0E77E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5CE8EB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B8D9CE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:70F927* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:301966* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:28BAB5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:103B59* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6CB7F4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001EE1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0018AF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BC72B1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:78F7BE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F49F54* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7C11CB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A4CAA0* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:00214C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001632* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D0667B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:38AA3C* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:206432* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:002637* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:001377* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:50B7C3* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8018A7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5CA39D* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:B88EDF* + ID_OUI_FROM_DATABASE=Zencheer Communication Technology Co., Ltd. + +OUI:D85DE2* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:707781* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:606DC7* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:681401* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:0071CC* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:F866D1* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:F80D43* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:002268* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:001FE1* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:002556* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:00265C* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:90CDB6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:001E4C* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:F8DA0C* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:9034FC* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:906EBB* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:342387* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:689423* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:B8763F* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:1C3E84* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:C01885* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:785968* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:1C666D* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:CCAF78* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:904CE5* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:B01041* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:7487A9* + ID_OUI_FROM_DATABASE=OCT Technology Co., Ltd. + +OUI:E0286D* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:444E1A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E8E5D6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5492BE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:101DC0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0021D1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5CA933* + ID_OUI_FROM_DATABASE=Luma Home + +OUI:2CDD95* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:AC84C9* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:107223* + ID_OUI_FROM_DATABASE=TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO + +OUI:CCB0DA* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:14EDBB* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:44BA46* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:B4D135* + ID_OUI_FROM_DATABASE=Cloudistics + +OUI:085DDD* + ID_OUI_FROM_DATABASE=MERCURY CORPORATION + +OUI:6CEC5A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. CO.,Ltd. + +OUI:5001D9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:44C346* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:884477* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:047503* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:2C402B* + ID_OUI_FROM_DATABASE=Smart iBlue Technology Limited + +OUI:180675* + ID_OUI_FROM_DATABASE=Dilax Intelcom GmbH + +OUI:30AEA4* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:0C4933* + ID_OUI_FROM_DATABASE=Sichuan Jiuzhou Electronic Technology Co., Ltd. + +OUI:7828CA* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:B8E937* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:B05216* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:002926* + ID_OUI_FROM_DATABASE=Applied Optoelectronics, Inc Taiwan Branch + +OUI:68DFDD* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:C46AB7* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:FC64BA* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:2082C0* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:3480B3* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:7451BA* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:64B473* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:8C2FA6* + ID_OUI_FROM_DATABASE=Solid Optics B.V. + +OUI:B0A2E7* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:BCA8A6* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:101331* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:38AFD7* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:28993A* + ID_OUI_FROM_DATABASE=Arista Networks + +OUI:B0E892* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation -OUI:0017EE* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:AC1826* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation -OUI:00D088* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:886639* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:001675* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:D8197A* + ID_OUI_FROM_DATABASE=Nuheara Ltd -OUI:0016B5* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:8CE117* + ID_OUI_FROM_DATABASE=zte corporation -OUI:001784* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:64136C* + ID_OUI_FROM_DATABASE=zte corporation -OUI:0017E2* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:0005CD* + ID_OUI_FROM_DATABASE=D&M Holdings Inc. -OUI:CC7D37* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:8C9351* + ID_OUI_FROM_DATABASE=Jigowatts Inc. -OUI:001A77* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:D838FC* + ID_OUI_FROM_DATABASE=Ruckus Wireless -OUI:984B4A* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:00248D* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. -OUI:80F503* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:54276C* + ID_OUI_FROM_DATABASE=Jiangsu Houge Technology Corp. -OUI:8496D8* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:00CB00* + ID_OUI_FROM_DATABASE=Private -OUI:D42C0F* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:FCFFAA* + ID_OUI_FROM_DATABASE=IEEE Registration Authority -OUI:E0B7B1* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:40D855* + ID_OUI_FROM_DATABASE=IEEE Registration Authority -OUI:002210* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:48DF37* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise -OUI:00211E* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:9C93E4* + ID_OUI_FROM_DATABASE=Private -OUI:E48399* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:005079* + ID_OUI_FROM_DATABASE=Private -OUI:002636* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:0028F8* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:0024A0* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:8416F9* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. -OUI:0012C9* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:C44BD1* + ID_OUI_FROM_DATABASE=Wallys Communications Teachnologies Co.,Ltd. -OUI:001CFB* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:2057AF* + ID_OUI_FROM_DATABASE=Shenzhen FH-NET OPTOELECTRONICS CO.,LTD -OUI:001C12* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:34EA34* + ID_OUI_FROM_DATABASE=HangZhou Gubei Electronics Technology Co.,Ltd -OUI:001FC4* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:F8A9D0* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:C0C522* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:CCFA00* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:5CB066* - ID_OUI_FROM_DATABASE=ARRIS Group, Inc. +OUI:BCF5AC* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:486DBB* - ID_OUI_FROM_DATABASE=Vestel Elektronik San ve Tic. A.Ş. +OUI:00AA70* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:6C1E90* - ID_OUI_FROM_DATABASE=Hansol Technics Co., Ltd. +OUI:F01C13* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:E09DFA* - ID_OUI_FROM_DATABASE=Wanan Hongsheng Electronic Co.Ltd +OUI:CC2D8C* + ID_OUI_FROM_DATABASE=LG ELECTRONICS INC -OUI:34E71C* - ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd +OUI:344DF7* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:182861* - ID_OUI_FROM_DATABASE=AirTies Wireless Networks +OUI:C49A02* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:8841FC* - ID_OUI_FROM_DATABASE=AirTies Wireless Networks +OUI:0022A9* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:BCB1F3* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:0025E5* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:38ECE4* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:10F96F* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) -OUI:CCF9E8* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:00116E* + ID_OUI_FROM_DATABASE=Peplink International Ltd. -OUI:F0E77E* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:A091C8* + ID_OUI_FROM_DATABASE=zte corporation -OUI:5CE8EB* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:002597* + ID_OUI_FROM_DATABASE=Kalki Communication Technologies -OUI:B8D9CE* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:882BD7* + ID_OUI_FROM_DATABASE=ADDÉNERGIE TECHNOLOGIES -OUI:6CB7F4* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:9CA5C0* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. -OUI:182666* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:B4A5EF* + ID_OUI_FROM_DATABASE=Sercomm Corporation. -OUI:C06599* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:3044A1* + ID_OUI_FROM_DATABASE=Shanghai Nanchao Information Technology -OUI:CC07AB* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:C4F1D1* + ID_OUI_FROM_DATABASE=BEIJING SOGOU TECHNOLOGY DEVELOPMENT CO., LTD. -OUI:E84E84* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:38A28C* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. -OUI:50FC9F* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:58528A* + ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation -OUI:E432CB* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:BCC00F* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD -OUI:889B39* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:B0C287* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:BC72B1* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:CC03FA* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:78F7BE* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:28BE9B* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:70F927* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:509F3B* + ID_OUI_FROM_DATABASE=OI ELECTRIC CO.,LTD -OUI:301966* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:E4029B* + ID_OUI_FROM_DATABASE=Intel Corporate -OUI:28BAB5* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:6002B4* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation -OUI:103B59* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:98EECB* + ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation -OUI:7C11CB* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:70E284* + ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation -OUI:A4CAA0* - ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD +OUI:80EA23* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation -OUI:001EE1* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:D88039* + ID_OUI_FROM_DATABASE=Microchip Technology Inc. -OUI:F49F54* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:FC3D93* + ID_OUI_FROM_DATABASE=LONGCHEER TELECOMMUNICATION LIMITED -OUI:0018AF* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:48F7C0* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. -OUI:00214C* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:00409F* + ID_OUI_FROM_DATABASE=Telco Systems, Inc. -OUI:001632* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:00E09E* + ID_OUI_FROM_DATABASE=Quantum Corporation -OUI:D0667B* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:00148C* + ID_OUI_FROM_DATABASE=General Dynamics Mission Systems -OUI:001377* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:A47174* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:50B7C3* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:D4A148* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:5CA39D* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. +OUI:D065CA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:38AA3C* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. +OUI:8CEBC6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:206432* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. +OUI:B808D7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD -OUI:8018A7* - ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd +OUI:FCF152* + ID_OUI_FROM_DATABASE=Sony Corporation -OUI:002637* - ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. +OUI:784476* + ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. -OUI:B88EDF* - ID_OUI_FROM_DATABASE=Zencheer Communication Technology Co., Ltd. +OUI:00183A* + ID_OUI_FROM_DATABASE=Westell Technologies Inc. -OUI:707781* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:E89A8F* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. -OUI:606DC7* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:001B24* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. -OUI:681401* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:CC52AF* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. -OUI:0071CC* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:001A6B* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. -OUI:F866D1* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:00DD0A* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. -OUI:F80D43* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:00039D* + ID_OUI_FROM_DATABASE=Qisda Corporation -OUI:785968* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:000B0E* + ID_OUI_FROM_DATABASE=Trapeze Networks -OUI:002556* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:002318* + ID_OUI_FROM_DATABASE=Toshiba -OUI:00265C* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:E89D87* + ID_OUI_FROM_DATABASE=Toshiba -OUI:90CDB6* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:E8E0B7* + ID_OUI_FROM_DATABASE=Toshiba -OUI:001E4C* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:001428* + ID_OUI_FROM_DATABASE=Vocollect Inc -OUI:F8DA0C* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:006B9E* + ID_OUI_FROM_DATABASE=Vizio, Inc -OUI:342387* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:0024FF* + ID_OUI_FROM_DATABASE=QLogic Corporation -OUI:9034FC* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:00A0C6* + ID_OUI_FROM_DATABASE=Qualcomm Inc. -OUI:906EBB* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:ECAAA0* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION -OUI:1C666D* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:E8886C* + ID_OUI_FROM_DATABASE=Shenzhen SC Technologies Co.,LTD -OUI:CCAF78* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:DC35F1* + ID_OUI_FROM_DATABASE=Positivo Informática SA. -OUI:904CE5* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:EC6881* + ID_OUI_FROM_DATABASE=Palo Alto Networks -OUI:002268* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:44334C* + ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD -OUI:001FE1* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:D84FB8* + ID_OUI_FROM_DATABASE=LG ELECTRONICS -OUI:689423* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:9C220E* + ID_OUI_FROM_DATABASE=TASCAN Systems GmbH -OUI:B8763F* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:0CA402* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD -OUI:1C3E84* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:00164D* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD -OUI:C01885* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:FCFAF7* + ID_OUI_FROM_DATABASE=Shanghai Baud Data Communication Co.,Ltd. -OUI:B01041* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:C8E776* + ID_OUI_FROM_DATABASE=PTCOM Technology -OUI:D85DE2* - ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. +OUI:5C497D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd OUI:949AA9* ID_OUI_FROM_DATABASE=Microsoft Corporation +OUI:C4084A* + ID_OUI_FROM_DATABASE=Nokia + +OUI:0C54B9* + ID_OUI_FROM_DATABASE=Nokia + +OUI:8C90D3* + ID_OUI_FROM_DATABASE=Nokia + +OUI:34AA99* + ID_OUI_FROM_DATABASE=Nokia + OUI:F8633F* ID_OUI_FROM_DATABASE=Intel Corporate @@ -74795,11 +76784,38 @@ OUI:A42983* OUI:702E22* ID_OUI_FROM_DATABASE=zte corporation +OUI:0023B9* + ID_OUI_FROM_DATABASE=Airbus Defence and Space Deutschland GmbH + OUI:B0C128* ID_OUI_FROM_DATABASE=Adler ELREHA GmbH -OUI:5CA933* - ID_OUI_FROM_DATABASE=Luma Home +OUI:C8F946* + ID_OUI_FROM_DATABASE=LOCOSYS Technology Inc. + +OUI:2047ED* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:D41D71* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:5C2443* + ID_OUI_FROM_DATABASE=O-Sung Telecom Co., Ltd. + +OUI:1861C7* + ID_OUI_FROM_DATABASE=lemonbeat GmbH + +OUI:9CDC71* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:240D65* + ID_OUI_FROM_DATABASE=Shenzhen Vsun Communication Technology Co., Ltd. + +OUI:D8452B* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:C8028F* + ID_OUI_FROM_DATABASE=Nova Electronics (Shanghai) Co., Ltd. OUI:60EFC6* ID_OUI_FROM_DATABASE=Shenzhen Chima Technologies Co Limited @@ -74813,12 +76829,21 @@ OUI:20DBAB* OUI:000DF0* ID_OUI_FROM_DATABASE=QCOM TECHNOLOGY INC. +OUI:5C9960* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + OUI:5CF7E6* ID_OUI_FROM_DATABASE=Apple, Inc. OUI:A0D795* ID_OUI_FROM_DATABASE=Apple, Inc. +OUI:CC088D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0080FB* + ID_OUI_FROM_DATABASE=BVM LIMITED + OUI:002722* ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. @@ -74831,9 +76856,6 @@ OUI:B4FBE4* OUI:188B15* ID_OUI_FROM_DATABASE=ShenZhen ZhongRuiJing Technology co.,LTD -OUI:CCB0DA* - ID_OUI_FROM_DATABASE=Liteon Technology Corporation - OUI:E02CF3* ID_OUI_FROM_DATABASE=MRS Electronic GmbH @@ -74851,3 +76873,156 @@ OUI:C0854C* OUI:00FD45* ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:9C83BF* + ID_OUI_FROM_DATABASE=PRO-VISION, Inc. + +OUI:9C13AB* + ID_OUI_FROM_DATABASE=Chanson Water Co., Ltd. + +OUI:883C1C* + ID_OUI_FROM_DATABASE=MERCURY CORPORATION + +OUI:9C5D12* + ID_OUI_FROM_DATABASE=Aerohive Networks Inc. + +OUI:001F82* + ID_OUI_FROM_DATABASE=Cal-Comp Electronics & Communications Company Ltd. + +OUI:E47DBD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0C0227* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:C0288D* + ID_OUI_FROM_DATABASE=Logitech, Inc + +OUI:9C1E95* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:E078A3* + ID_OUI_FROM_DATABASE=Shanghai Winner Information Technology Co.,Inc + +OUI:B49691* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:9CD9CB* + ID_OUI_FROM_DATABASE=Lesira Manufacturing Pty Ltd + +OUI:34D270* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:002590* + ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. + +OUI:187532* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:E0DCA0* + ID_OUI_FROM_DATABASE=Siemens Industrial Automation Products Ltd Chengdu + +OUI:DCD255* + ID_OUI_FROM_DATABASE=Kinpo Electronics, Inc. + +OUI:805A04* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:B0EE7B* + ID_OUI_FROM_DATABASE=Roku, Inc + +OUI:E8EADA* + ID_OUI_FROM_DATABASE=Denkovi Assembly Electronics LTD + +OUI:480C49* + ID_OUI_FROM_DATABASE=NAKAYO Inc + +OUI:00D0EC* + ID_OUI_FROM_DATABASE=NAKAYO Inc + +OUI:B0702D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D0C5F3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60F445* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00B362* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F86214* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C0E54E* + ID_OUI_FROM_DATABASE=ARIES Embedded GmbH + +OUI:001D72* + ID_OUI_FROM_DATABASE=Wistron Corporation + +OUI:0C73BE* + ID_OUI_FROM_DATABASE=Dongguan Haimai Electronie Technology Co.,Ltd + +OUI:20780B* + ID_OUI_FROM_DATABASE=Delta Faucet Company + +OUI:24D51C* + ID_OUI_FROM_DATABASE=Zhongtian broadband technology co., LTD + +OUI:E44790* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:28FECD* + ID_OUI_FROM_DATABASE=Lemobile Information Technology (Beijing) Co., Ltd. + +OUI:001992* + ID_OUI_FROM_DATABASE=Adtran Inc + +OUI:002365* + ID_OUI_FROM_DATABASE=Insta Elektro GmbH + +OUI:4C1694* + ID_OUI_FROM_DATABASE=shenzhen sibituo Technology Co., Ltd + +OUI:6C160E* + ID_OUI_FROM_DATABASE=ShotTracker + +OUI:7C1015* + ID_OUI_FROM_DATABASE=Brilliant Home Technology, Inc. + +OUI:4C7872* + ID_OUI_FROM_DATABASE=Cav. Uff. Giacomo Cimberio S.p.A. + +OUI:5CAF06* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:78C1A7* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:540384* + ID_OUI_FROM_DATABASE=Hangkong Nano IC Technologies Co., Ltd + +OUI:004BF3* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:28A24B* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:044E06* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:001BB5* + ID_OUI_FROM_DATABASE=Cherry GmbH + +OUI:6014B3* + ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. + +OUI:602103* + ID_OUI_FROM_DATABASE=I4VINE, INC + +OUI:B81DAA* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:407D0F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD diff --git a/hwdb/20-acpi-vendor.hwdb b/hwdb/20-acpi-vendor.hwdb index 3731b33656..c0fe421c11 100644 --- a/hwdb/20-acpi-vendor.hwdb +++ b/hwdb/20-acpi-vendor.hwdb @@ -9,6 +9,9 @@ acpi:3NOD*: ID_VENDOR_FROM_DATABASE=Shenzhen three Connaught Information Technology Co., Ltd. (3nod Group) +acpi:AANT*: + ID_VENDOR_FROM_DATABASE=AAEON Technology Inc. + acpi:AAVA*: ID_VENDOR_FROM_DATABASE=Aava Mobile Oy @@ -72,6 +75,9 @@ acpi:FRSC*: acpi:FTSC*: ID_VENDOR_FROM_DATABASE=FocalTech Systems Co., Ltd. +acpi:GHSW*: + ID_VENDOR_FROM_DATABASE=Green Hills Software + acpi:GOOG*: ID_VENDOR_FROM_DATABASE=Google, Inc. @@ -126,6 +132,9 @@ acpi:LNRO*: acpi:LNUX*: ID_VENDOR_FROM_DATABASE=The Linux Foundation +acpi:MCHP*: + ID_VENDOR_FROM_DATABASE=Microchip Technology Inc + acpi:MIPI*: ID_VENDOR_FROM_DATABASE=MIPI Alliance @@ -228,6 +237,9 @@ acpi:AAE*: acpi:AAM*: ID_VENDOR_FROM_DATABASE=Aava Mobile Oy +acpi:AAN*: + ID_VENDOR_FROM_DATABASE=AAEON Technology Inc. + acpi:AAT*: ID_VENDOR_FROM_DATABASE=Ann Arbor Technologies @@ -879,6 +891,9 @@ acpi:AXB*: acpi:AXC*: ID_VENDOR_FROM_DATABASE=AXIOMTEK CO., LTD. +acpi:AXE*: + ID_VENDOR_FROM_DATABASE=Axell Corporation + acpi:AXE*: ID_VENDOR_FROM_DATABASE=D-Link Systems Inc @@ -3684,6 +3699,9 @@ acpi:KOW*: acpi:KPC*: ID_VENDOR_FROM_DATABASE=King Phoenix Company +acpi:KPT*: + ID_VENDOR_FROM_DATABASE=TPK Holding Co., Ltd + acpi:KRL*: ID_VENDOR_FROM_DATABASE=Krell Industries Inc. @@ -6420,6 +6438,9 @@ acpi:TDC*: acpi:TDD*: ID_VENDOR_FROM_DATABASE=Tandberg Data Display AS +acpi:TDG*: + ID_VENDOR_FROM_DATABASE=Six15 Technologies + acpi:TDK*: ID_VENDOR_FROM_DATABASE=TDK USA Corporation @@ -6858,6 +6879,9 @@ acpi:UMG*: acpi:UMM*: ID_VENDOR_FROM_DATABASE=Universal Multimedia +acpi:UMT*: + ID_VENDOR_FROM_DATABASE=UltiMachine + acpi:UNA*: ID_VENDOR_FROM_DATABASE=Unisys DSD diff --git a/hwdb/20-pci-vendor-model.hwdb b/hwdb/20-pci-vendor-model.hwdb index 0c829c8aec..ea190ff7ca 100644 --- a/hwdb/20-pci-vendor-model.hwdb +++ b/hwdb/20-pci-vendor-model.hwdb @@ -644,6 +644,60 @@ pci:v00001000d00000013* pci:v00001000d00000013sv00001000sd00001000* ID_MODEL_FROM_DATABASE=53c875a (LSI53C875A PCI to Ultra SCSI Controller) +pci:v00001000d00000014* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 + +pci:v00001000d00000014sv00001028sd00001FD4* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (PERC H745P MX) + +pci:v00001000d00000014sv00001D49sd00000602* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (ThinkSystem RAID 930-16i 4GB Flash PCIe 12Gb Adapter) + +pci:v00001000d00000016* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 + +pci:v00001000d00000016sv00001028sd00001FC9* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (PERC H840 Adapter) + +pci:v00001000d00000016sv00001028sd00001FCB* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (PERC H740P Adapter) + +pci:v00001000d00000016sv00001028sd00001FCD* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (PERC H740P Mini) + +pci:v00001000d00000016sv00001028sd00001FCF* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (PERC H740P Mini) + +pci:v00001000d00000016sv00001D49sd00000601* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (ThinkSystem RAID 930-8i 2GB Flash PCIe 12Gb Adapter) + +pci:v00001000d00000016sv00001D49sd00000603* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (ThinkSystem RAID 930-24i 4GB Flash PCIe 12Gb Adapter) + +pci:v00001000d00000016sv00001D49sd00000604* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (ThinkSystem RAID 930-8e 4GB Flash PCIe 12Gb Adapter) + +pci:v00001000d00000017* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3408 + +pci:v00001000d00000017sv00001D49sd00000500* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3408 (ThinkSystem RAID 530-8i PCIe 12Gb Adapter) + +pci:v00001000d00000017sv00001D49sd00000502* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3408 (ThinkSystem RAID 530-8i Dense Adapter) + +pci:v00001000d0000001B* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3504 + +pci:v00001000d0000001Bsv00001D49sd00000605* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3504 (ThinkSystem RAID 930-4i 2GB Flash Flex Adapter) + +pci:v00001000d0000001C* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3404 + +pci:v00001000d0000001Csv00001D49sd00000501* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3404 (ThinkSystem RAID 530-4i Flex Adapter) + pci:v00001000d00000020* ID_MODEL_FROM_DATABASE=53c1010 Ultra3 SCSI Adapter @@ -962,6 +1016,12 @@ pci:v00001000d0000005D* pci:v00001000d0000005Dsv00001000sd00009361* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (MegaRAID SAS 9361-8i) +pci:v00001000d0000005Dsv00001000sd00009364* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (MegaRAID SAS 9364-8i) + +pci:v00001000d0000005Dsv00001000sd0000936A* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (MegaRAID SAS 9364-8i) + pci:v00001000d0000005Dsv00001028sd00001F41* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H830 Adapter) @@ -992,12 +1052,18 @@ pci:v00001000d0000005Dsv00001028sd00001F4F* pci:v00001000d0000005Dsv00001028sd00001F54* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC FD33xD) +pci:v00001000d0000005Dsv00001028sd00001FD1* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730P MX) + pci:v00001000d0000005Dsv000017AAsd00001052* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkServer RAID 720i) pci:v00001000d0000005Dsv000017AAsd00001053* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkServer RAID 720ix) +pci:v00001000d0000005Dsv00001D49sd00000600* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkSystem RAID 730-8i 1GB Cache PCIe 12Gb Adapter) + pci:v00001000d0000005E* ID_MODEL_FROM_DATABASE=SAS1066 PCI-X Fusion-MPT SAS @@ -1427,6 +1493,9 @@ pci:v00001000d00000087sv00001000sd00003020* pci:v00001000d00000087sv00001000sd00003040* ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (9207-8e SAS2.1 HBA) +pci:v00001000d00000087sv00001000sd00003050* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (SAS9217-8i) + pci:v00001000d00000087sv00001590sd00000044* ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (H220i) @@ -1457,12 +1526,57 @@ pci:v00001000d00000096* pci:v00001000d00000097* ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 +pci:v00001000d00000097sv00001000sd00003090* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (SAS9311-8i) + +pci:v00001000d00000097sv00001000sd000030E0* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (SAS9300-8i) + pci:v00001000d00000097sv00001028sd00001F45* - ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (12GB/s HBA internal) + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (HBA330 Adapter) pci:v00001000d00000097sv00001028sd00001F46* ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (12Gbps HBA) +pci:v00001000d00000097sv00001028sd00001F53* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (HBA330 Mini) + +pci:v00001000d00000097sv00001028sd00001FD2* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (HBA330 MX) + +pci:v00001000d00000097sv00001028sd00001FD3* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (HBA330 MMZ) + +pci:v00001000d000000AB* + ID_MODEL_FROM_DATABASE=SAS3516 Fusion-MPT Tri-Mode RAID On Chip (ROC) + +pci:v00001000d000000AC* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) + +pci:v00001000d000000ACsv00001D49sd00000201* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 9400-16i PCIe 12Gb HBA) + +pci:v00001000d000000ACsv00001D49sd00000203* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 9400-16e PCIe 12Gb HBA) + +pci:v00001000d000000AE* + ID_MODEL_FROM_DATABASE=SAS3508 Fusion-MPT Tri-Mode RAID On Chip (ROC) + +pci:v00001000d000000AF* + ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) + +pci:v00001000d000000AFsv00001D49sd00000200* + ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 9400-8i PCIe 12Gb HBA) + +pci:v00001000d000000AFsv00001D49sd00000202* + ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 9400-8e PCIe 12Gb HBA) + +pci:v00001000d000000BE* + ID_MODEL_FROM_DATABASE=SAS3504 Fusion-MPT Tri-Mode RAID On Chip (ROC) + +pci:v00001000d000000BF* + ID_MODEL_FROM_DATABASE=SAS3404 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) + pci:v00001000d000000C0* ID_MODEL_FROM_DATABASE=SAS3324 PCI-Express Fusion-MPT SAS-3 @@ -1508,6 +1622,15 @@ pci:v00001000d000000CF* pci:v00001000d000000CFsv00001000sd00009370* ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3324 [Intruder] (MegaRAID SAS 9361-24i) +pci:v00001000d000000D0* + ID_MODEL_FROM_DATABASE=SAS3716 Fusion-MPT Tri-Mode RAID Controller Chip (ROC) + +pci:v00001000d000000D1* + ID_MODEL_FROM_DATABASE=SAS3616 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) + +pci:v00001000d000000D3* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3716W + pci:v00001000d00000407* ID_MODEL_FROM_DATABASE=MegaRAID @@ -4560,31 +4683,34 @@ pci:v00001002d0000665Fsv00001682sd00007360* ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R7 360) pci:v00001002d00006660* - ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430] pci:v00001002d00006660sv00001028sd000005EA* - ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon HD 8670M) + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430] (Radeon HD 8670M) pci:v00001002d00006660sv00001028sd000006BF* - ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M335) + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430] (Radeon R5 M335) pci:v00001002d00006660sv0000103Csd00001970* - ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon HD 8670M) + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430] (Radeon HD 8670M) pci:v00001002d00006660sv0000103Csd000080BE* - ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330) + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430] (Radeon R5 M330) pci:v00001002d00006660sv0000103Csd00008136* - ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330) + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430] (Radeon R5 M330) pci:v00001002d00006660sv000017AAsd00003804* - ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330) + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430] (Radeon R5 M330) pci:v00001002d00006660sv000017AAsd00003809* - ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330) + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430] (Radeon R5 M330) + +pci:v00001002d00006660sv000017AAsd0000381A* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430] (Radeon R5 M430) pci:v00001002d00006660sv000017AAsd0000390C* - ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330] (Radeon R5 M330) + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430] (Radeon R5 M330) pci:v00001002d00006663* ID_MODEL_FROM_DATABASE=Sun PRO [Radeon HD 8570A/8570M] @@ -4592,6 +4718,9 @@ pci:v00001002d00006663* pci:v00001002d00006663sv00001025sd00000846* ID_MODEL_FROM_DATABASE=Sun PRO [Radeon HD 8570A/8570M] (Radeon HD 8570A) +pci:v00001002d00006663sv000017AAsd00003805* + ID_MODEL_FROM_DATABASE=Sun PRO [Radeon HD 8570A/8570M] (Radeon HD 8570M) + pci:v00001002d00006664* ID_MODEL_FROM_DATABASE=Jet XT [Radeon R5 M240] @@ -6348,7 +6477,49 @@ pci:v00001002d000067C0* ID_MODEL_FROM_DATABASE=Ellesmere [Polaris10] pci:v00001002d000067DF* - ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 480] + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] + +pci:v00001002d000067DFsv00001002sd00000B37* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480) + +pci:v00001002d000067DFsv00001043sd000004A8* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480) + +pci:v00001002d000067DFsv00001043sd000004B0* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470) + +pci:v00001002d000067DFsv00001043sd000004FB* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480) + +pci:v00001002d000067DFsv00001462sd00003411* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470) + +pci:v00001002d000067DFsv00001462sd00003413* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480) + +pci:v00001002d000067DFsv0000148Csd00002372* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480) + +pci:v00001002d000067DFsv0000148Csd00002373* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470) + +pci:v00001002d000067DFsv00001682sd00009470* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470) + +pci:v00001002d000067DFsv00001682sd00009480* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480) + +pci:v00001002d000067DFsv0000174Bsd0000E347* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470/480) + +pci:v00001002d000067DFsv0000174Bsd0000E349* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470) + +pci:v00001002d000067DFsv00001787sd0000A470* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 470) + +pci:v00001002d000067DFsv00001787sd0000A480* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480] (Radeon RX 480) pci:v00001002d000067E0* ID_MODEL_FROM_DATABASE=Baffin [Polaris11] @@ -6365,6 +6536,9 @@ pci:v00001002d000067E9* pci:v00001002d000067EB* ID_MODEL_FROM_DATABASE=Baffin [Polaris11] +pci:v00001002d000067EF* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460] + pci:v00001002d000067FF* ID_MODEL_FROM_DATABASE=Baffin [Polaris11] @@ -8328,76 +8502,82 @@ pci:v00001002d000068FE* ID_MODEL_FROM_DATABASE=Cedar LE pci:v00001002d00006900* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] pci:v00001002d00006900sv00001025sd00001056* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M360 / R8 M365DX) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M360 / R8 M365DX) pci:v00001002d00006900sv00001028sd00000640* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260/M265) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260/M265) pci:v00001002d00006900sv00001028sd00000643* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260/M265) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260/M265) pci:v00001002d00006900sv00001028sd0000067F* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) + +pci:v00001002d00006900sv00001028sd00000767* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M445) pci:v00001002d00006900sv00001028sd0000130A* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006900sv0000103Csd00002263* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006900sv0000103Csd00002269* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006900sv0000103Csd000022C6* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006900sv0000103Csd000022C8* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006900sv0000103Csd0000808C* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006900sv0000103Csd00008099* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M360) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M360) pci:v00001002d00006900sv0000103Csd000080B5* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M360) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M360) pci:v00001002d00006900sv0000103Csd000080B9* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M360) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M360) pci:v00001002d00006900sv0000103Csd0000811C* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M340) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M340) + +pci:v00001002d00006900sv0000103Csd00008226* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M440) pci:v00001002d00006900sv000010CFsd00001906* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006900sv00001170sd00009979* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M360) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M360) pci:v00001002d00006900sv00001179sd0000F903* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006900sv00001179sd0000F922* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006900sv00001179sd0000F923* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006900sv00001179sd0000F934* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006900sv000017AAsd00003822* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M360) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M360) pci:v00001002d00006900sv000017AAsd00003824* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M360) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M360) pci:v00001002d00006900sv000017AAsd00005021* - ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360] (Radeon R7 M260) + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445] (Radeon R7 M260) pci:v00001002d00006901* ID_MODEL_FROM_DATABASE=Topaz PRO [Radeon R5 M255] @@ -8405,6 +8585,9 @@ pci:v00001002d00006901* pci:v00001002d00006901sv0000103Csd00001318* ID_MODEL_FROM_DATABASE=Topaz PRO [Radeon R5 M255] (Radeon R6 M255DX) +pci:v00001002d00006907* + ID_MODEL_FROM_DATABASE=Meso XT [Radeon R5 M315] + pci:v00001002d00006921* ID_MODEL_FROM_DATABASE=Amethyst XT [Radeon R9 M295X] @@ -8819,6 +9002,9 @@ pci:v00001002d00007300* pci:v00001002d00007300sv00001002sd00000B36* ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon R9 FURY X / NANO) +pci:v00001002d00007300sv00001002sd00001B36* + ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon Pro Duo) + pci:v00001002d00007300sv00001043sd0000049E* ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon R9 FURY) @@ -9387,7 +9573,7 @@ pci:v00001002d000095CF* ID_MODEL_FROM_DATABASE=RV620 GL [FirePro 2260] pci:v00001002d0000960F* - ID_MODEL_FROM_DATABASE=RS780 HDMI Audio [Radeon (HD) 3000 Series] + ID_MODEL_FROM_DATABASE=RS780 HDMI Audio [Radeon 3000/3100 / HD 3200/3300] pci:v00001002d00009610* ID_MODEL_FROM_DATABASE=RS780 [Radeon HD 3200] @@ -9684,7 +9870,7 @@ pci:v00001002d00009919* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7500G] pci:v00001002d00009920* - ID_MODEL_FROM_DATABASE=Liverpool Graphics + ID_MODEL_FROM_DATABASE=Liverpool [Playstation 4 APU] pci:v00001002d00009921* ID_MODEL_FROM_DATABASE=Liverpool HDMI/DP Audio Controller @@ -9741,28 +9927,31 @@ pci:v00001002d000099A4* ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7400G] pci:v00001002d0000AA00* - ID_MODEL_FROM_DATABASE=R600 HDMI Audio [Radeon HD 2900 Series] + ID_MODEL_FROM_DATABASE=R600 HDMI Audio [Radeon HD 2900 GT/PRO/XT] + +pci:v00001002d0000AA01* + ID_MODEL_FROM_DATABASE=RV635 HDMI Audio [Radeon HD 3650/3730/3750] pci:v00001002d0000AA08* - ID_MODEL_FROM_DATABASE=RV630 HDMI Audio [Radeon HD 2600 Series] + ID_MODEL_FROM_DATABASE=RV630 HDMI Audio [Radeon HD 2600 PRO/XT / HD 3610] pci:v00001002d0000AA10* - ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350/2400 Series] + ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350 PRO / 2400 PRO/XT / HD 3410] pci:v00001002d0000AA10sv0000174Bsd0000AA10* - ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350/2400 Series] (Radeon HD 2400 PRO) + ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350 PRO / 2400 PRO/XT / HD 3410] (Radeon HD 2400 PRO) pci:v00001002d0000AA10sv000018BCsd0000AA10* - ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350/2400 Series] (Radeon HD 2400 PRO) + ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350 PRO / 2400 PRO/XT / HD 3410] (Radeon HD 2400 PRO) pci:v00001002d0000AA18* ID_MODEL_FROM_DATABASE=RV670/680 HDMI Audio [Radeon HD 3690/3800 Series] pci:v00001002d0000AA20* - ID_MODEL_FROM_DATABASE=RV635 HDMI Audio [Radeon HD 3600 Series] + ID_MODEL_FROM_DATABASE=RV635 HDMI Audio [Radeon HD 3650/3730/3750] pci:v00001002d0000AA28* - ID_MODEL_FROM_DATABASE=RV620 HDMI Audio [Radeon HD 3400 Series] + ID_MODEL_FROM_DATABASE=RV620 HDMI Audio [Radeon HD 3450/3470/3550/3570] pci:v00001002d0000AA30* ID_MODEL_FROM_DATABASE=RV770 HDMI Audio [Radeon HD 4850/4870] @@ -9777,7 +9966,7 @@ pci:v00001002d0000AA38sv0000103Csd00003628* ID_MODEL_FROM_DATABASE=RV710/730 HDMI Audio [Radeon HD 4000 series] (dv6-1190en) pci:v00001002d0000AA50* - ID_MODEL_FROM_DATABASE=Cypress HDMI Audio [Radeon HD 5800 Series] + ID_MODEL_FROM_DATABASE=Cypress HDMI Audio [Radeon HD 5830/5850/5870 / 6850/6870 Rebrand] pci:v00001002d0000AA58* ID_MODEL_FROM_DATABASE=Juniper HDMI Audio [Radeon HD 5700 Series] @@ -9792,31 +9981,31 @@ pci:v00001002d0000AA60sv00001025sd00000347* ID_MODEL_FROM_DATABASE=Redwood HDMI Audio [Radeon HD 5000 Series] (Aspire 7740G) pci:v00001002d0000AA68* - ID_MODEL_FROM_DATABASE=Cedar HDMI Audio [Radeon HD 5400/6300 Series] + ID_MODEL_FROM_DATABASE=Cedar HDMI Audio [Radeon HD 5400/6300/7300 Series] pci:v00001002d0000AA68sv00001028sd0000AA68* - ID_MODEL_FROM_DATABASE=Cedar HDMI Audio [Radeon HD 5400/6300 Series] (XPS 8300) + ID_MODEL_FROM_DATABASE=Cedar HDMI Audio [Radeon HD 5400/6300/7300 Series] (XPS 8300) pci:v00001002d0000AA80* - ID_MODEL_FROM_DATABASE=Cayman/Antilles HDMI Audio [Radeon HD 6900 Series] + ID_MODEL_FROM_DATABASE=Cayman/Antilles HDMI Audio [Radeon HD 6930/6950/6970/6990] pci:v00001002d0000AA88* - ID_MODEL_FROM_DATABASE=Barts HDMI Audio [Radeon HD 6800 Series] + ID_MODEL_FROM_DATABASE=Barts HDMI Audio [Radeon HD 6790/6850/6870 / 7720 OEM] pci:v00001002d0000AA90* - ID_MODEL_FROM_DATABASE=Turks/Whistler HDMI Audio [Radeon HD 6000 Series] + ID_MODEL_FROM_DATABASE=Turks HDMI Audio [Radeon HD 6500/6600 / 6700M Series] pci:v00001002d0000AA90sv00001028sd000004A3* - ID_MODEL_FROM_DATABASE=Turks/Whistler HDMI Audio [Radeon HD 6000 Series] (Precision M4600) + ID_MODEL_FROM_DATABASE=Turks HDMI Audio [Radeon HD 6500/6600 / 6700M Series] (Precision M4600) pci:v00001002d0000AA98* - ID_MODEL_FROM_DATABASE=Caicos HDMI Audio [Radeon HD 6400 Series] + ID_MODEL_FROM_DATABASE=Caicos HDMI Audio [Radeon HD 6450 / 7450/8450/8490 OEM / R5 230/235/235X OEM] pci:v00001002d0000AA98sv0000174Bsd0000AA98* - ID_MODEL_FROM_DATABASE=Caicos HDMI Audio [Radeon HD 6400 Series] (Radeon HD 6450 1GB DDR3) + ID_MODEL_FROM_DATABASE=Caicos HDMI Audio [Radeon HD 6450 / 7450/8450/8490 OEM / R5 230/235/235X OEM] (Radeon HD 6450 1GB DDR3) pci:v00001002d0000AAA0* - ID_MODEL_FROM_DATABASE=Tahiti XT HDMI Audio [Radeon HD 7970 Series] + ID_MODEL_FROM_DATABASE=Tahiti HDMI Audio [Radeon HD 7870 XT / 7950/7970] pci:v00001002d0000AAB0* ID_MODEL_FROM_DATABASE=Cape Verde/Pitcairn HDMI Audio [Radeon HD 7700/7800 Series] @@ -9825,7 +10014,7 @@ pci:v00001002d0000AAC0* ID_MODEL_FROM_DATABASE=Tobago HDMI Audio [Radeon R7 360 / R9 360 OEM] pci:v00001002d0000AAC8* - ID_MODEL_FROM_DATABASE=Hawaii HDMI Audio + ID_MODEL_FROM_DATABASE=Hawaii HDMI Audio [Radeon R9 290/290X / 390/390X] pci:v00001002d0000AAD8* ID_MODEL_FROM_DATABASE=Tonga HDMI Audio [Radeon R9 285/380] @@ -9834,7 +10023,7 @@ pci:v00001002d0000AAD8sv0000174Bsd0000AAD8* ID_MODEL_FROM_DATABASE=Tonga HDMI Audio [Radeon R9 285/380] (Radeon R9 285/380 HDMI Audio) pci:v00001002d0000AAE8* - ID_MODEL_FROM_DATABASE=Fiji HDMI/DP Audio Controller + ID_MODEL_FROM_DATABASE=Fiji HDMI/DP Audio [Radeon R9 Nano / FURY/FURY X] pci:v00001002d0000AC00* ID_MODEL_FROM_DATABASE=Theater 600 Pro @@ -13094,6 +13283,21 @@ pci:v0000102Bd00000540sv0000102Bsd00002280* pci:v0000102Bd00000540sv0000102Bsd000022C0* ID_MODEL_FROM_DATABASE=M91XX (M9128 LP PCIe x16) +pci:v0000102Bd00000550* + ID_MODEL_FROM_DATABASE=SV2 + +pci:v0000102Bd00000550sv0000102Bsd000000C0* + ID_MODEL_FROM_DATABASE=SV2 (MURA-IPX-I4EF) + +pci:v0000102Bd00000550sv0000102Bsd000000C1* + ID_MODEL_FROM_DATABASE=SV2 (MURA-IPX-I4DF) + +pci:v0000102Bd00000550sv0000102Bsd000000C3* + ID_MODEL_FROM_DATABASE=SV2 (MURA-IPX-I4DHF) + +pci:v0000102Bd00000550sv0000102Bsd000000C5* + ID_MODEL_FROM_DATABASE=SV2 (MURA-IPX-I4EHF) + pci:v0000102Bd00000D10* ID_MODEL_FROM_DATABASE=MGA Ultima/Impression @@ -21605,6 +21809,9 @@ pci:v000010B5d00008547* pci:v000010B5d00008548* ID_MODEL_FROM_DATABASE=PEX 8548 48-lane, 9-port PCI Express Switch +pci:v000010B5d00008603* + ID_MODEL_FROM_DATABASE=PEX 8603 3-lane, 3-Port PCI Express Gen 2 (5.0 GT/s) Switch + pci:v000010B5d00008604* ID_MODEL_FROM_DATABASE=PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch @@ -21683,6 +21890,9 @@ pci:v000010B5d00008717* pci:v000010B5d00008718* ID_MODEL_FROM_DATABASE=PEX 8718 16-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch +pci:v000010B5d00008724* + ID_MODEL_FROM_DATABASE=PEX 8724 24-Lane, 6-Port PCI Express Gen 3 (8 GT/s) Switch, 19 x 19mm FCBGA + pci:v000010B5d00008732* ID_MODEL_FROM_DATABASE=PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch @@ -21692,6 +21902,9 @@ pci:v000010B5d00008734* pci:v000010B5d00008747* ID_MODEL_FROM_DATABASE=PEX 8747 48-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch +pci:v000010B5d00008748* + ID_MODEL_FROM_DATABASE=PEX 8748 48-Lane, 12-Port PCI Express Gen 3 (8 GT/s) Switch, 27 x 27mm FCBGA + pci:v000010B5d000087B0* ID_MODEL_FROM_DATABASE=PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch @@ -22103,6 +22316,9 @@ pci:v000010B5d00009656sv00001885sd00000701* pci:v000010B5d00009733* ID_MODEL_FROM_DATABASE=PEX 9733 33-lane, 9-port PCI Express Gen 3 (8.0 GT/s) Switch +pci:v000010B5d00009733sv00001D49sd00000001* + ID_MODEL_FROM_DATABASE=PEX 9733 33-lane, 9-port PCI Express Gen 3 (8.0 GT/s) Switch (ThinkSystem P310W-4P NVMe Switch Card) + pci:v000010B5d00009749* ID_MODEL_FROM_DATABASE=PEX 9749 49-lane, 13-port PCI Express Gen 3 (8.0 GT/s) Switch @@ -30255,7 +30471,7 @@ pci:v000010DEd00001140sv0000144Dsd0000C10D* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) pci:v000010DEd00001140sv0000144Dsd0000C652* - ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M on NP300E5C series laptop) pci:v000010DEd00001140sv0000144Dsd0000C709* ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) @@ -31298,6 +31514,9 @@ pci:v000010DEd000013F9* pci:v000010DEd000013FA* ID_MODEL_FROM_DATABASE=GM204GLM [Quadro M3000M] +pci:v000010DEd000013FAsv000010DEsd000011C9* + ID_MODEL_FROM_DATABASE=GM204GLM [Quadro M3000M] (Quadro M3000 SE) + pci:v000010DEd000013FB* ID_MODEL_FROM_DATABASE=GM204GLM [Quadro M5500] @@ -31374,11 +31593,17 @@ pci:v000010DEd000017FD* ID_MODEL_FROM_DATABASE=GM200GL [Tesla M40] pci:v000010DEd00001B00* - ID_MODEL_FROM_DATABASE=GP102 + ID_MODEL_FROM_DATABASE=GP102 [TITAN X] pci:v000010DEd00001B01* ID_MODEL_FROM_DATABASE=GP102 +pci:v000010DEd00001B30* + ID_MODEL_FROM_DATABASE=GP102GL [Quadro P6000] + +pci:v000010DEd00001B38* + ID_MODEL_FROM_DATABASE=GP102GL [Tesla P40] + pci:v000010DEd00001B70* ID_MODEL_FROM_DATABASE=GP102GL @@ -31397,11 +31622,14 @@ pci:v000010DEd00001B82* pci:v000010DEd00001B83* ID_MODEL_FROM_DATABASE=GP104 +pci:v000010DEd00001BA0* + ID_MODEL_FROM_DATABASE=GP104M [GeForce GTX 1080] + pci:v000010DEd00001BA1* ID_MODEL_FROM_DATABASE=GP104M [GeForce GTX 1070] pci:v000010DEd00001BB0* - ID_MODEL_FROM_DATABASE=GP104GL + ID_MODEL_FROM_DATABASE=GP104GL [Quadro P5000] pci:v000010DEd00001BB1* ID_MODEL_FROM_DATABASE=GP104GL @@ -31422,14 +31650,23 @@ pci:v000010DEd00001C01* ID_MODEL_FROM_DATABASE=GP106 pci:v000010DEd00001C02* - ID_MODEL_FROM_DATABASE=GP106 + ID_MODEL_FROM_DATABASE=GP106 [GeForce GTX 1060 3GB] pci:v000010DEd00001C03* - ID_MODEL_FROM_DATABASE=GP106 [GeForce GTX 1060] + ID_MODEL_FROM_DATABASE=GP106 [GeForce GTX 1060 6GB] + +pci:v000010DEd00001C20* + ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1060] pci:v000010DEd00001C30* ID_MODEL_FROM_DATABASE=GP106GL +pci:v000010DEd00001C35* + ID_MODEL_FROM_DATABASE=GP106 + +pci:v000010DEd00001C60* + ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1060] + pci:v000010DEd00001C70* ID_MODEL_FROM_DATABASE=GP106GL @@ -31437,10 +31674,10 @@ pci:v000010DEd00001C80* ID_MODEL_FROM_DATABASE=GP107 pci:v000010DEd00001C81* - ID_MODEL_FROM_DATABASE=GP107 + ID_MODEL_FROM_DATABASE=GP107 [GeForce GTX 1050] pci:v000010DEd00001C82* - ID_MODEL_FROM_DATABASE=GP107 + ID_MODEL_FROM_DATABASE=GP107 [GeForce GTX 1050 Ti] pci:v000010DEd00001CA7* ID_MODEL_FROM_DATABASE=GP107GL @@ -31958,6 +32195,9 @@ pci:v000010ECd0000525A* pci:v000010ECd00005286* ID_MODEL_FROM_DATABASE=RTS5286 PCI Express Card Reader +pci:v000010ECd00005287* + ID_MODEL_FROM_DATABASE=RTL8411B PCI Express Card Reader + pci:v000010ECd00005288* ID_MODEL_FROM_DATABASE=RTS5288 PCI Express Card Reader @@ -32003,6 +32243,9 @@ pci:v000010ECd00008136* pci:v000010ECd00008136sv0000103Csd00001985* ID_MODEL_FROM_DATABASE=RTL8101/2/6E PCI Express Fast/Gigabit Ethernet controller (Pavilion 17-e163sg Notebook PC) +pci:v000010ECd00008136sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=RTL8101/2/6E PCI Express Fast/Gigabit Ethernet controller (Compaq 500B Microtower) + pci:v000010ECd00008136sv0000103Csd00002AB1* ID_MODEL_FROM_DATABASE=RTL8101/2/6E PCI Express Fast/Gigabit Ethernet controller (Pavilion p6774) @@ -32237,6 +32480,9 @@ pci:v000010ECd00008168sv0000105Bsd00000D7C* pci:v000010ECd00008168sv000010ECsd00008168* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (RTL8111/8168 PCI Express Gigabit Ethernet controller) +pci:v000010ECd00008168sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (RTL8168 on a NP300E5C series laptop) + pci:v000010ECd00008168sv00001458sd0000E000* ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Onboard Ethernet) @@ -32327,6 +32573,9 @@ pci:v000010ECd00008174* pci:v000010ECd00008176* ID_MODEL_FROM_DATABASE=RTL8188CE 802.11b/g/n WiFi Adapter +pci:v000010ECd00008176sv00001043sd000084B5* + ID_MODEL_FROM_DATABASE=RTL8188CE 802.11b/g/n WiFi Adapter (PCE-N10) + pci:v000010ECd00008176sv00001A3Bsd00001139* ID_MODEL_FROM_DATABASE=RTL8188CE 802.11b/g/n WiFi Adapter (AW-NE139H Half-size Mini PCIe Card) @@ -32369,6 +32618,9 @@ pci:v000010ECd00008192* pci:v000010ECd00008193* ID_MODEL_FROM_DATABASE=RTL8192DE Wireless LAN Controller +pci:v000010ECd00008196* + ID_MODEL_FROM_DATABASE=RTL8196 Integrated PCI-e Bridge + pci:v000010ECd00008197* ID_MODEL_FROM_DATABASE=SmartLAN56 56K Modem @@ -32453,6 +32705,12 @@ pci:v000010EEd00003FC5* pci:v000010EEd00003FC6* ID_MODEL_FROM_DATABASE=RME Hammerfall DSP MADI +pci:v000010EEd00007038* + ID_MODEL_FROM_DATABASE=FPGA Card XC7VX690T + +pci:v000010EEd00007038sv000017AAsd0000402F* + ID_MODEL_FROM_DATABASE=FPGA Card XC7VX690T (FPGA XC7VX690T-3FFG1157E) + pci:v000010EEd00008380* ID_MODEL_FROM_DATABASE=Ellips ProfiXpress Profibus Master @@ -35603,6 +35861,9 @@ pci:v0000111Dd00008088sv00001093sd00007600* pci:v0000111Dd00008088sv00001093sd00007602* ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8384) +pci:v0000111Dd0000808E* + ID_MODEL_FROM_DATABASE=PES24NT24G2 PCI Express Switch + pci:v0000111Dd0000808F* ID_MODEL_FROM_DATABASE=PES32NT8AG2 @@ -40490,6 +40751,36 @@ pci:v000011F8d00008032sv0000117Csd0000003B* pci:v000011F8d00008032sv0000117Csd0000003C* ID_MODEL_FROM_DATABASE=ATTO Celerity FC8xEN (Celerity FC-84EN Fibre Channel Adapter) +pci:v000011F8d00008053* + ID_MODEL_FROM_DATABASE=PM8053 SXP 12G 24-port SAS/SATA expander + +pci:v000011F8d00008054* + ID_MODEL_FROM_DATABASE=PM8054 SXP 12G 36-port SAS/SATA expander + +pci:v000011F8d00008055* + ID_MODEL_FROM_DATABASE=PM8055 SXP 12G 48-port SAS/SATA expander + +pci:v000011F8d00008056* + ID_MODEL_FROM_DATABASE=PM8056 SXP 12G 68-port SAS/SATA expander + +pci:v000011F8d00008060* + ID_MODEL_FROM_DATABASE=PM8060 SRCv 12G eight-port SAS/SATA RoC + +pci:v000011F8d00008063* + ID_MODEL_FROM_DATABASE=PM8063 SRCv 12G 16-port SAS/SATA RoC + +pci:v000011F8d00008070* + ID_MODEL_FROM_DATABASE=PM8070 Tachyon SPCv 12G eight-port SAS/SATA controller + +pci:v000011F8d00008071* + ID_MODEL_FROM_DATABASE=PM8071 Tachyon SPCve 12G eight-port SAS/SATA controller + +pci:v000011F8d00008072* + ID_MODEL_FROM_DATABASE=PM8072 Tachyon SPCv 12G 16-port SAS/SATA controller + +pci:v000011F8d00008073* + ID_MODEL_FROM_DATABASE=PM8073 Tachyon SPCve 12G 16-port SAS/SATA controller + pci:v000011F9* ID_VENDOR_FROM_DATABASE=I-Cube Inc @@ -44426,6 +44717,9 @@ pci:v00001360d00000207* pci:v00001360d00000208* ID_MODEL_FROM_DATABASE=GPS180AMC GPS Receiver (PCI Express / MicroTCA / AdvancedMC) +pci:v00001360d00000209* + ID_MODEL_FROM_DATABASE=GRC181PEX GPS/GLONASS/BEIDOU receiver (PCI Express) + pci:v00001360d00000301* ID_MODEL_FROM_DATABASE=TCR510PCI IRIG Timecode Reader @@ -47822,6 +48116,201 @@ pci:v00001425d0000589B* pci:v00001425d0000589C* ID_MODEL_FROM_DATABASE=T520-509C Unified Wire Ethernet Controller [VF] +pci:v00001425d00006001* + ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller + +pci:v00001425d00006002* + ID_MODEL_FROM_DATABASE=T6225-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006003* + ID_MODEL_FROM_DATABASE=T6425-CR Unified Wire Ethernet Controller + +pci:v00001425d00006004* + ID_MODEL_FROM_DATABASE=T6425-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006005* + ID_MODEL_FROM_DATABASE=T6225-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006006* + ID_MODEL_FROM_DATABASE=T62100-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006007* + ID_MODEL_FROM_DATABASE=T62100-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d00006008* + ID_MODEL_FROM_DATABASE=T62100-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006009* + ID_MODEL_FROM_DATABASE=T6210-BT Unified Wire Ethernet Controller + +pci:v00001425d0000600D* + ID_MODEL_FROM_DATABASE=T62100-CR Unified Wire Ethernet Controller + +pci:v00001425d00006011* + ID_MODEL_FROM_DATABASE=T6225-LL-CR Unified Wire Ethernet Controller + +pci:v00001425d00006014* + ID_MODEL_FROM_DATABASE=T61100-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006015* + ID_MODEL_FROM_DATABASE=T6201-BT Unified Wire Ethernet Controller + +pci:v00001425d00006401* + ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller + +pci:v00001425d00006402* + ID_MODEL_FROM_DATABASE=T6225-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006403* + ID_MODEL_FROM_DATABASE=T6425-CR Unified Wire Ethernet Controller + +pci:v00001425d00006404* + ID_MODEL_FROM_DATABASE=T6425-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006405* + ID_MODEL_FROM_DATABASE=T6225-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006406* + ID_MODEL_FROM_DATABASE=T62100-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006407* + ID_MODEL_FROM_DATABASE=T62100-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d00006408* + ID_MODEL_FROM_DATABASE=T62100-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006409* + ID_MODEL_FROM_DATABASE=T6210-BT Unified Wire Ethernet Controller + +pci:v00001425d0000640D* + ID_MODEL_FROM_DATABASE=T62100-CR Unified Wire Ethernet Controller + +pci:v00001425d00006411* + ID_MODEL_FROM_DATABASE=T6225-LL-CR Unified Wire Ethernet Controller + +pci:v00001425d00006414* + ID_MODEL_FROM_DATABASE=T61100-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006415* + ID_MODEL_FROM_DATABASE=T6201-BT Unified Wire Ethernet Controller + +pci:v00001425d00006501* + ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Storage Controller + +pci:v00001425d00006502* + ID_MODEL_FROM_DATABASE=T6225-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006503* + ID_MODEL_FROM_DATABASE=T6425-CR Unified Wire Storage Controller + +pci:v00001425d00006504* + ID_MODEL_FROM_DATABASE=T6425-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006505* + ID_MODEL_FROM_DATABASE=T6225-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006506* + ID_MODEL_FROM_DATABASE=T62100-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006507* + ID_MODEL_FROM_DATABASE=T62100-LP-CR Unified Wire Storage Controller + +pci:v00001425d00006508* + ID_MODEL_FROM_DATABASE=T62100-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006509* + ID_MODEL_FROM_DATABASE=T6210-BT Unified Wire Storage Controller + +pci:v00001425d0000650D* + ID_MODEL_FROM_DATABASE=T62100-CR Unified Wire Storage Controller + +pci:v00001425d00006511* + ID_MODEL_FROM_DATABASE=T6225-LL-CR Unified Wire Storage Controller + +pci:v00001425d00006514* + ID_MODEL_FROM_DATABASE=T61100-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006515* + ID_MODEL_FROM_DATABASE=T6201-BT Unified Wire Storage Controller + +pci:v00001425d00006601* + ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Storage Controller + +pci:v00001425d00006602* + ID_MODEL_FROM_DATABASE=T6225-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006603* + ID_MODEL_FROM_DATABASE=T6425-CR Unified Wire Storage Controller + +pci:v00001425d00006604* + ID_MODEL_FROM_DATABASE=T6425-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006605* + ID_MODEL_FROM_DATABASE=T6225-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006606* + ID_MODEL_FROM_DATABASE=T62100-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006607* + ID_MODEL_FROM_DATABASE=T62100-LP-CR Unified Wire Storage Controller + +pci:v00001425d00006608* + ID_MODEL_FROM_DATABASE=T62100-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006609* + ID_MODEL_FROM_DATABASE=T6210-BT Unified Wire Storage Controller + +pci:v00001425d0000660D* + ID_MODEL_FROM_DATABASE=T62100-CR Unified Wire Storage Controller + +pci:v00001425d00006611* + ID_MODEL_FROM_DATABASE=T6225-LL-CR Unified Wire Storage Controller + +pci:v00001425d00006614* + ID_MODEL_FROM_DATABASE=T61100-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006615* + ID_MODEL_FROM_DATABASE=T6201-BT Unified Wire Storage Controller + +pci:v00001425d00006801* + ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006802* + ID_MODEL_FROM_DATABASE=T6225-SO-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006803* + ID_MODEL_FROM_DATABASE=T6425-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006804* + ID_MODEL_FROM_DATABASE=T6425-SO-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006805* + ID_MODEL_FROM_DATABASE=T6225-OCP-SO Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006806* + ID_MODEL_FROM_DATABASE=T62100-OCP-SO Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006807* + ID_MODEL_FROM_DATABASE=T62100-LP-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006808* + ID_MODEL_FROM_DATABASE=T62100-SO-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006809* + ID_MODEL_FROM_DATABASE=T6210-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000680D* + ID_MODEL_FROM_DATABASE=T62100-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006811* + ID_MODEL_FROM_DATABASE=T6225-LL-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006814* + ID_MODEL_FROM_DATABASE=T61100-OCP-SO Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006815* + ID_MODEL_FROM_DATABASE=T6201-BT Unified Wire Ethernet Controller [VF] + pci:v00001425d0000A000* ID_MODEL_FROM_DATABASE=PE10K Unified Wire Ethernet Controller @@ -48804,7 +49293,7 @@ pci:v000014E3* ID_VENDOR_FROM_DATABASE=AMTELCO pci:v000014E4* - ID_VENDOR_FROM_DATABASE=Broadcom Corporation + ID_VENDOR_FROM_DATABASE=Broadcom Limited pci:v000014E4d00000576* ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n @@ -49944,49 +50433,70 @@ pci:v000014E4d000016C7sv000014E4sd0000000A* ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NetXtreme BCM5703 1000Base-SX) pci:v000014E4d000016C8* - ID_MODEL_FROM_DATABASE=BCM57301 NetXtreme-C Single-port 10Gb Ethernet + ID_MODEL_FROM_DATABASE=BCM57301 NetXtreme-C 10Gb Ethernet Controller pci:v000014E4d000016C9* - ID_MODEL_FROM_DATABASE=BCM57302 NetXtreme-C Dual-port 10Gb/25Gb Ethernet + ID_MODEL_FROM_DATABASE=BCM57302 NetXtreme-C 10Gb/25Gb Ethernet Controller pci:v000014E4d000016CA* - ID_MODEL_FROM_DATABASE=BCM57304 NetXtreme-C Dual-port 10Gb/25Gb/40Gb/50Gb Ethernet + ID_MODEL_FROM_DATABASE=BCM57304 NetXtreme-C 10Gb/25Gb/40Gb/50Gb Ethernet Controller pci:v000014E4d000016CB* ID_MODEL_FROM_DATABASE=BCM57304 NetXtreme-C Ethernet Virtual Function +pci:v000014E4d000016CC* + ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E Ethernet Partition + pci:v000014E4d000016CE* - ID_MODEL_FROM_DATABASE=BCM57311 NetXtreme-C Single-port 10Gb RDMA Ethernet + ID_MODEL_FROM_DATABASE=BCM57311 NetXtreme-C 10Gb RDMA Ethernet Controller pci:v000014E4d000016CF* - ID_MODEL_FROM_DATABASE=BCM57312 NetXtreme-C Dual-port 10Gb/25Gb RDMA Ethernet + ID_MODEL_FROM_DATABASE=BCM57312 NetXtreme-C 10Gb/25Gb RDMA Ethernet Controller pci:v000014E4d000016D0* - ID_MODEL_FROM_DATABASE=BCM57402 NetXtreme-E Dual-port 10Gb Ethernet + ID_MODEL_FROM_DATABASE=BCM57402 NetXtreme-E 10Gb Ethernet Controller pci:v000014E4d000016D1* - ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E Dual-port 10Gb/25Gb Ethernet + ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E 10Gb/25Gb Ethernet Controller pci:v000014E4d000016D2* - ID_MODEL_FROM_DATABASE=BCM57406 NetXtreme-E Dual-port 10GBase-T Ethernet + ID_MODEL_FROM_DATABASE=BCM57406 NetXtreme-E 10GBASE-T Ethernet Controller pci:v000014E4d000016D3* ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E Ethernet Virtual Function pci:v000014E4d000016D4* - ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E Ethernet Partition + ID_MODEL_FROM_DATABASE=BCM57402 NetXtreme-E Ethernet Partition + +pci:v000014E4d000016D5* + ID_MODEL_FROM_DATABASE=BCM57407 NetXtreme-E 10GBase-T Ethernet Controller pci:v000014E4d000016D6* - ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E Dual-port 10Gb RDMA Ethernet + ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller pci:v000014E4d000016D7* - ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E Dual-port 10Gb/25Gb RDMA Ethernet + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller + +pci:v000014E4d000016D7sv00001590sd0000020E* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (Ethernet 25Gb 2-port 631SFP28 Adapter) + +pci:v000014E4d000016D7sv00001590sd00000211* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (Ethernet 25Gb 2-port 631FLR-SFP28 Adapter) pci:v000014E4d000016D8* - ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Dual-port 10GBase-T RDMA Ethernet + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E 10GBase-T RDMA Ethernet Controller + +pci:v000014E4d000016D8sv00001590sd0000020C* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E 10GBase-T RDMA Ethernet Controller (Ethernet 10Gb 2-port 535T Adapter) + +pci:v000014E4d000016D8sv00001590sd00000212* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E 10GBase-T RDMA Ethernet Controller (Ethernet 10Gb 2-port 535FLR-T Adapter) pci:v000014E4d000016D9* - ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E Dual-port 10GBase-T RDMA Ethernet + ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E 10GBASE-T RDMA Ethernet Controller + +pci:v000014E4d000016D9sv0000108Esd00004866* + ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E 10GBASE-T RDMA Ethernet Controller (Dual Port 10GBase-T Ethernet Controller) pci:v000014E4d000016DC* ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E Ethernet Virtual Function @@ -49995,16 +50505,37 @@ pci:v000014E4d000016DD* ID_MODEL_FROM_DATABASE=NetLink BCM5781 Gigabit Ethernet PCI Express pci:v000014E4d000016DE* - ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E Ethernet Partition + ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E Ethernet Partition pci:v000014E4d000016DF* - ID_MODEL_FROM_DATABASE=BCM57314 NetXtreme-C Dual-port 10Gb/25Gb/40Gb/50Gb RDMA Ethernet + ID_MODEL_FROM_DATABASE=BCM57314 NetXtreme-C 10Gb/25Gb/40Gb/50Gb RDMA Ethernet Controller pci:v000014E4d000016E1* ID_MODEL_FROM_DATABASE=BCM57314 NetXtreme-C Ethernet Virtual Function pci:v000014E4d000016E2* - ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E Dual-port 10Gb/25Gb RDMA Ethernet + ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller + +pci:v000014E4d000016E2sv0000108Esd00004866* + ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (Dual Port 10Gb/25Gb SFP28 Ethernet Controller) + +pci:v000014E4d000016E3* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E 10Gb RDMA Ethernet Controller + +pci:v000014E4d000016E7* + ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E Ethernet Partition + +pci:v000014E4d000016E8* + ID_MODEL_FROM_DATABASE=BCM57406 NetXtreme-E Ethernet Partition + +pci:v000014E4d000016E9* + ID_MODEL_FROM_DATABASE=BCM57407 NetXtreme-E 25Gb Ethernet Controller + +pci:v000014E4d000016EC* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E Ethernet Partition + +pci:v000014E4d000016EE* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Ethernet Partition pci:v000014E4d000016F3* ID_MODEL_FROM_DATABASE=NetXtreme BCM5727 Gigabit Ethernet PCIe @@ -52091,6 +52622,9 @@ pci:v00001524d00001410sv00001025sd0000003C* pci:v00001524d00001410sv00001025sd0000005A* ID_MODEL_FROM_DATABASE=CB1410 Cardbus Controller (TravelMate 290) +pci:v00001524d00001410sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=CB1410 Cardbus Controller (530 Laptop) + pci:v00001524d00001411* ID_MODEL_FROM_DATABASE=CB-710/2/4 Cardbus Controller @@ -52235,6 +52769,9 @@ pci:v00001542d00009278* pci:v00001542d00009287* ID_MODEL_FROM_DATABASE=Analog Output Card +pci:v00001542d00009290* + ID_MODEL_FROM_DATABASE=FPGA Card + pci:v00001543* ID_VENDOR_FROM_DATABASE=SILICON Laboratories @@ -52760,6 +53297,12 @@ pci:v000015B3d0000020B* pci:v000015B3d0000020D* ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Flash Recovery] +pci:v000015B3d0000024E* + ID_MODEL_FROM_DATABASE=MT53100 [Spectrum-2, Flash recovery mode] + +pci:v000015B3d0000024F* + ID_MODEL_FROM_DATABASE=MT53100 [Spectrum-2, Flash recovery mode] + pci:v000015B3d00000262* ID_MODEL_FROM_DATABASE=MT27710 [ConnectX-4 Lx Programmable] EN @@ -52799,6 +53342,9 @@ pci:v000015B3d00001006* pci:v000015B3d00001007* ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] +pci:v000015B3d00001007sv00001014sd000004EB* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (2-Port 10GbE NIC and RoCE SR PCIe3) + pci:v000015B3d00001007sv0000103Csd000022F3* ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (InfiniBand FDR/Ethernet 10Gb/40Gb 2-port 544+QSFP Adapter) @@ -52863,16 +53409,16 @@ pci:v000015B3d00001016* ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx Virtual Function] pci:v000015B3d00001017* - ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5, PCIe 3.0] + ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5] pci:v000015B3d00001018* - ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Virtual Function] + ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5 Virtual Function] pci:v000015B3d00001019* - ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5, PCIe 4.0] + ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Ex] pci:v000015B3d0000101A* - ID_MODEL_FROM_DATABASE=MT28830 + ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Ex Virtual Function] pci:v000015B3d0000101B* ID_MODEL_FROM_DATABASE=MT28831 @@ -52895,6 +53441,12 @@ pci:v000015B3d00001020* pci:v000015B3d00001021* ID_MODEL_FROM_DATABASE=MT28861 +pci:v000015B3d00001974* + ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 PCIe Bridge] + +pci:v000015B3d00001975* + ID_MODEL_FROM_DATABASE=MT416842 Family [BlueField SoC PCIe Bridge] + pci:v000015B3d00005274* ID_MODEL_FROM_DATABASE=MT21108 InfiniBridge @@ -52961,6 +53513,9 @@ pci:v000015B3d00006746sv0000103Csd00003349* pci:v000015B3d00006750* ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] +pci:v000015B3d00006750sv00001014sd00000461* + ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (2-Port 10 GbE RoCE SR LP PCIe2 (rev b0)) + pci:v000015B3d00006750sv000015B3sd00000018* ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (HP 10 GbE PCI-e G2 Dual-Port NIC (rev C1)) @@ -52997,6 +53552,15 @@ pci:v000015B3d00007122* pci:v000015B3d00007123* ID_MODEL_FROM_DATABASE=NPS-600 network interface VF +pci:v000015B3d0000A2D0* + ID_MODEL_FROM_DATABASE=MT416842 + +pci:v000015B3d0000A2D1* + ID_MODEL_FROM_DATABASE=MT416842 + +pci:v000015B3d0000A2D3* + ID_MODEL_FROM_DATABASE=MT416842 BlueField multicore SoC family VF + pci:v000015B3d0000C738* ID_MODEL_FROM_DATABASE=MT51136 @@ -53018,6 +53582,9 @@ pci:v000015B3d0000CB84* pci:v000015B3d0000CF08* ID_MODEL_FROM_DATABASE=MT53236 +pci:v000015B3d0000CF6C* + ID_MODEL_FROM_DATABASE=MT53100 [Spectrum-2, 64 x 100GbE switch] + pci:v000015B3d0000D2F0* ID_MODEL_FROM_DATABASE=Switch-IB 3 HDR (200Gbps) switch @@ -53822,6 +54389,9 @@ pci:v0000165Cd00007191* pci:v0000165Cd000071A1* ID_MODEL_FROM_DATABASE=Proc10a_66S +pci:v0000165Cd000071B1* + ID_MODEL_FROM_DATABASE=Proc10A + pci:v0000165D* ID_VENDOR_FROM_DATABASE=Hsing Tech. Enterprise Co., Ltd. @@ -54548,6 +55118,9 @@ pci:v0000168Cd00000032sv0000103Csd00001838* pci:v0000168Cd00000032sv0000105Bsd0000E044* ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (Unex DHXA-225) +pci:v0000168Cd00000032sv0000144Dsd0000410E* + ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (AR9485WB-EG 802.11b/g/n mini-PCIe card on a series 3 laptop) + pci:v0000168Cd00000032sv00001A3Bsd00001186* ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (AW-NE186H) @@ -54947,9 +55520,39 @@ pci:v000016D5d00007013* pci:v000016D5d00007014* ID_MODEL_FROM_DATABASE=AP445: 32-Channel Isolated Digital Output Module +pci:v000016D5d00007016* + ID_MODEL_FROM_DATABASE=AP470 48-Channel TTL Level Digital Input/Output Module + pci:v000016D5d00007018* ID_MODEL_FROM_DATABASE=AP408: 32-Channel Digital I/O Module +pci:v000016D5d0000701A* + ID_MODEL_FROM_DATABASE=AP220-16 12-Bit, 16-Channel Analog Output Module + +pci:v000016D5d0000701B* + ID_MODEL_FROM_DATABASE=AP231-16 16-Bit, 16-Channel Analog Output Module + +pci:v000016D5d00007021* + ID_MODEL_FROM_DATABASE=APA7-201 Reconfigurable Artix-7 FPGA module 48 TTL channels + +pci:v000016D5d00007022* + ID_MODEL_FROM_DATABASE=APA7-202 Reconfigurable Artix-7 FPGA module 24 RS485 channels + +pci:v000016D5d00007023* + ID_MODEL_FROM_DATABASE=APA7-203 Reconfigurable Artix-7 FPGA module 24 TTL & 12 RS485 channels + +pci:v000016D5d00007024* + ID_MODEL_FROM_DATABASE=APA7-204 Reconfigurable Artix-7 FPGA module 24 LVDS channels + +pci:v000016D5d00007042* + ID_MODEL_FROM_DATABASE=AP482 Counter Timer Module with TTL Level Input/Output + +pci:v000016D5d00007043* + ID_MODEL_FROM_DATABASE=AP483 Counter Timer Module with TTL Level and RS422 Input/Output + +pci:v000016D5d00007044* + ID_MODEL_FROM_DATABASE=AP484 Counter Timer Module with RS422 Input/Output + pci:v000016DA* ID_VENDOR_FROM_DATABASE=Advantech Co., Ltd. @@ -55605,7 +56208,7 @@ pci:v000017C2* ID_VENDOR_FROM_DATABASE=Newisys, Inc. pci:v000017CB* - ID_VENDOR_FROM_DATABASE=Airgo Networks, Inc. + ID_VENDOR_FROM_DATABASE=Qualcomm pci:v000017CBd00000001* ID_MODEL_FROM_DATABASE=AGN100 802.11 a/b/g True MIMO Wireless Card @@ -55625,12 +56228,21 @@ pci:v000017CBd00000002sv00001385sd00006D00* pci:v000017CBd00000002sv00001737sd00000054* ID_MODEL_FROM_DATABASE=AGN300 802.11 a/b/g True MIMO Wireless Card (WPC54GX4 v1 802.11g Wireless-G Notebook Adapter with SRX400) +pci:v000017CBd00000400* + ID_MODEL_FROM_DATABASE=Datacenter Technologies QDF2432 PCI Express Root Port + +pci:v000017CBd00000401* + ID_MODEL_FROM_DATABASE=Datacenter Technologies QDF2400 PCI Express Root Port + pci:v000017CC* ID_VENDOR_FROM_DATABASE=NetChip Technology, Inc pci:v000017CCd00002280* ID_MODEL_FROM_DATABASE=USB 2.0 +pci:v000017CD* + ID_VENDOR_FROM_DATABASE=Cadence Design Systems, Inc. + pci:v000017CF* ID_VENDOR_FROM_DATABASE=Z-Com, Inc. @@ -55994,6 +56606,9 @@ pci:v000017F3* pci:v000017F3d00001010* ID_MODEL_FROM_DATABASE=R1010 IDE Controller +pci:v000017F3d00002012* + ID_MODEL_FROM_DATABASE=M2012/R3308 VGA-compatible graphics adapter + pci:v000017F3d00006020* ID_MODEL_FROM_DATABASE=R6020 North Bridge @@ -56624,6 +57239,9 @@ pci:v000018D2* pci:v000018D2d00003069* ID_MODEL_FROM_DATABASE=DC-105v2 ISDN controller +pci:v000018D4* + ID_VENDOR_FROM_DATABASE=Celestica + pci:v000018D8* ID_VENDOR_FROM_DATABASE=Dialogue Technology Corp. @@ -58118,6 +58736,9 @@ pci:v000019A2d00000714sv0000103Csd00003315* pci:v000019A2d00000714sv0000103Csd0000337B* ID_MODEL_FROM_DATABASE=OneConnect 10Gb FCoE Initiator (be3) (NC554FLB 10Gb 2-port FlexFabric Converged Network Adapter) +pci:v000019A2d00000800* + ID_MODEL_FROM_DATABASE=ServerView iRMC HTI + pci:v000019A8* ID_VENDOR_FROM_DATABASE=DAQDATA GmbH @@ -59120,9 +59741,15 @@ pci:v00001BB1d00000100* pci:v00001BB1d00000100sv00001BB1sd00000101* ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro XF1440) +pci:v00001BB1d00000100sv00001BB1sd00000103* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5000) + pci:v00001BB1d00000100sv00001BB1sd00000121* ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro XM1440) +pci:v00001BB1d00000100sv00001BB1sd00000123* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5000) + pci:v00001BB1d00000100sv00001BB1sd000001A1* ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro XP7102) @@ -59201,6 +59828,12 @@ pci:v00001BEE* pci:v00001BEEd00000003* ID_MODEL_FROM_DATABASE=CAN-IB200/PCIe +pci:v00001BEF* + ID_VENDOR_FROM_DATABASE=Lantiq + +pci:v00001BEFd00000011* + ID_MODEL_FROM_DATABASE=MIPS SoC PCI Express Port + pci:v00001BF4* ID_VENDOR_FROM_DATABASE=VTI Instruments Corporation @@ -59223,7 +59856,25 @@ pci:v00001C09d00004256* ID_MODEL_FROM_DATABASE=10G-PCIE3-8D-2S pci:v00001C09d00004258* - ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-2S + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-2S Network Adapter + +pci:v00001C09d00004260* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-4S Network Adapter + +pci:v00001C09d00004261* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-4S Network Adapter + +pci:v00001C09d00004262* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-4S Network Adapter + +pci:v00001C09d00004263* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-4S Network Adapter + +pci:v00001C09d00004264* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-2S Network Adapter + +pci:v00001C09d00004265* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-2S Network Adapter pci:v00001C1C* ID_VENDOR_FROM_DATABASE=Symphony @@ -59498,6 +60149,18 @@ pci:v00001D6Cd0000100E* pci:v00001D6Cd00004200* ID_MODEL_FROM_DATABASE=A5PL-E1-10GETI [10 GbE Ethernet Traffic Instrument] +pci:v00001D78* + ID_VENDOR_FROM_DATABASE=DERA + +pci:v00001D8F* + ID_VENDOR_FROM_DATABASE=Enyx + +pci:v00001D95* + ID_VENDOR_FROM_DATABASE=Graphcore Ltd + +pci:v00001DA1* + ID_VENDOR_FROM_DATABASE=Teko Telecom S.r.l. + pci:v00001DE1* ID_VENDOR_FROM_DATABASE=Tekram Technology Co.,Ltd. @@ -59646,7 +60309,10 @@ pci:v00001FC9d00004026* ID_MODEL_FROM_DATABASE=TN9610 10GbE SFP+ Ethernet Adapter pci:v00001FC9d00004027* - ID_MODEL_FROM_DATABASE=TN9710 10GBase-T/NBASE-T Ethernet Adapter + ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter + +pci:v00001FC9d00004527* + ID_MODEL_FROM_DATABASE=TN9710Q 5GBase-T/NBASE-T Ethernet Adapter pci:v00001FCC* ID_VENDOR_FROM_DATABASE=StreamLabs @@ -61883,6 +62549,9 @@ pci:v00008086d00000101sv00001028sd000004B2* pci:v00008086d00000101sv0000106Bsd000000DC* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port (MacBookPro8,2 [Core i7, 15", 2011]) +pci:v00008086d00000101sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port (NP300E5C series laptop) + pci:v00008086d00000102* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller @@ -61907,6 +62576,9 @@ pci:v00008086d00000104sv00001028sd000004DA* pci:v00008086d00000104sv0000106Bsd000000DC* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (MacBookPro8,2 [Core i7, 15", 2011]) +pci:v00008086d00000104sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (NP300E5C series laptop) + pci:v00008086d00000105* ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port @@ -61946,6 +62618,9 @@ pci:v00008086d00000116* pci:v00008086d00000116sv00001028sd000004DA* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (Vostro 3750) +pci:v00008086d00000116sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (integrated HD 3000 graphics controller on NP300E5C series laptop) + pci:v00008086d00000122* ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller @@ -64457,6 +65132,9 @@ pci:v00008086d00001067* pci:v00008086d00001068* ID_MODEL_FROM_DATABASE=82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller Mobile +pci:v00008086d00001068sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller Mobile (530 Laptop) + pci:v00008086d00001069* ID_MODEL_FROM_DATABASE=82562EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller Mobile @@ -65189,6 +65867,9 @@ pci:v00008086d000010FBsv0000103Csd00002159* pci:v00008086d000010FBsv0000108Esd00007B11* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) +pci:v00008086d000010FBsv00001170sd0000004C* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (82599 DP 10G Mezzanine Adapter) + pci:v00008086d000010FBsv00001734sd000011A9* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (10 Gigabit Dual Port Network Connection) @@ -65201,6 +65882,21 @@ pci:v00008086d000010FBsv000017AAsd00004007* pci:v00008086d000010FBsv000017AAsd0000402B* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (82599ES 10Gb 2-port Server Adapter X520-DA2) +pci:v00008086d000010FBsv000017AAsd0000402F* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (FPGA Card XC7VX690T-3FFG1157E) + +pci:v00008086d000010FBsv000018D4sd00000C09* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (82599ES 10Gb 2-port SFP+ OCP Mezz Card MOP81-I-10GS2) + +pci:v00008086d000010FBsv00001BD4sd0000001B* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (10G SFP+ DP ER102Fi4 Rack Adapter) + +pci:v00008086d000010FBsv00001BD4sd0000002F* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (10G SFP+ DP EP102Fi4A Adapter) + +pci:v00008086d000010FBsv00001BD4sd00000032* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (10G SFP+ DP EP102Fi4 Adapter) + pci:v00008086d000010FBsv00008086sd00000002* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-DA2) @@ -65219,6 +65915,9 @@ pci:v00008086d000010FBsv00008086sd0000000A* pci:v00008086d000010FBsv00008086sd0000000C* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) +pci:v00008086d000010FBsv00008086sd000010A6* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (82599ES 10Gb 2 port Server Adapter X520-DA2) + pci:v00008086d000010FBsv00008086sd00007A11* ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) @@ -66014,12 +66713,33 @@ pci:v00008086d00001521* pci:v00008086d00001521sv00001028sd00000602* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 2P I350-t LOM) +pci:v00008086d00001521sv00001028sd00000693* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 2P I350-t LOM) + +pci:v00008086d00001521sv00001028sd000006E2* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 2P I350-t LOM) + +pci:v00008086d00001521sv00001028sd00000757* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit I350-t LOM) + +pci:v00008086d00001521sv00001028sd0000075A* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit I350-t LOM) + pci:v00008086d00001521sv00001028sd00001F60* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 4P I350-t rNDC) pci:v00008086d00001521sv00001028sd00001F62* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 4P X540/I350 rNDC) +pci:v00008086d00001521sv00001028sd00001FA8* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 10G 4P X550/I350 rNDC) + +pci:v00008086d00001521sv00001028sd00001FA9* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 10G 4P X550 rNDC) + +pci:v00008086d00001521sv00001028sd00001FAA* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 4P X550/I350 rNDC) + pci:v00008086d00001521sv00001028sd0000FF9A* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 4P X710/I350 rNDC) @@ -66074,6 +66794,15 @@ pci:v00008086d00001521sv000017AAsd00001074* pci:v00008086d00001521sv000017AAsd00004005* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection +pci:v00008086d00001521sv000018D4sd00000C07* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (I350 1Gb 2-port RJ45 OCP Mezz Card MOP41-I-1GT2) + +pci:v00008086d00001521sv00001BD4sd0000001D* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (1G base-T QP EP014Ti1 Adapter) + +pci:v00008086d00001521sv00001BD4sd00000035* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (1G base-T QP EP014Ti1 Adapter) + pci:v00008086d00001521sv00008086sd00000001* ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T4) @@ -66203,6 +66932,15 @@ pci:v00008086d00001528sv000017AAsd00001073* pci:v00008086d00001528sv000017AAsd00004006* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 +pci:v00008086d00001528sv00001BD4sd0000001A* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (10G base-T DP ER102Ti3 Rack Adapter) + +pci:v00008086d00001528sv00001BD4sd00000033* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (10G base-T DP EP102Ti3 Adapter) + +pci:v00008086d00001528sv00001BD4sd00000034* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (10G base-T DP EP102Ti3A Adapter) + pci:v00008086d00001528sv00008086sd00000001* ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet Converged Network Adapter X540-T2) @@ -66323,6 +67061,12 @@ pci:v00008086d00001557* pci:v00008086d00001557sv000017AAsd00004008* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection (82599EN 10 Gigabit Network Connection) +pci:v00008086d00001557sv00001BD4sd0000001C* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection (10G SFP+ SP ER101Fi4 Rack Adapter) + +pci:v00008086d00001557sv00001BD4sd00000030* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection (10G SFP+ SP EP101Fi4A Adapter) + pci:v00008086d00001557sv00008086sd00000001* ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection (Ethernet OCP Server Adapter X520-1) @@ -66365,6 +67109,21 @@ pci:v00008086d00001560* pci:v00008086d00001563* ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T +pci:v00008086d00001563sv00001028sd00001FA8* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10G 4P X550/I350 rNDC) + +pci:v00008086d00001563sv00001028sd00001FA9* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10G 4P X550 rNDC) + +pci:v00008086d00001563sv00001590sd000000D1* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10Gb 2-port 562T Adapter) + +pci:v00008086d00001563sv00001590sd000000D2* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10Gb 2-port 562FLR-T Adapter) + +pci:v00008086d00001563sv000018D4sd00000C08* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (X550 10Gb 2-port RJ45 OCP Mezz Card MOP81-I-10GT2) + pci:v00008086d00001563sv00008086sd00000001* ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T2) @@ -66437,6 +67196,12 @@ pci:v00008086d00001572sv00001137sd00000000* pci:v00008086d00001572sv00001137sd0000013B* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged NIC X710-4) +pci:v00008086d00001572sv00001590sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10GbE 4P 563SFP+ Adapter) + +pci:v00008086d00001572sv00001590sd00000225* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10GbE 4P 563SFP+ Adapter) + pci:v00008086d00001572sv000017AAsd00000000* ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (ThinkServer X710 AnyFabric for 10GbE SFP+) @@ -66612,19 +67377,19 @@ pci:v00008086d00001587* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane pci:v00008086d00001587sv0000103Csd00000000* - ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HP Flex-20 20Gb 2-port 660FLB Adapter) + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HPE Ethernet 10/20Gb 2-port 660FLB Adapter) pci:v00008086d00001587sv0000103Csd000022FE* - ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HP Flex-20 20Gb 2-port 660FLB Adapter) + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HPE Ethernet 10/20Gb 2-port 660FLB Adapter) pci:v00008086d00001588* ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane pci:v00008086d00001588sv0000103Csd00000000* - ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HP Flex-20 20Gb 2-port 660M Adapter) + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HPE Ethernet 10/20Gb 2-port 660M Adapter) pci:v00008086d00001588sv0000103Csd000022FF* - ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HP Flex-20 20Gb 2-port 660M Adapter) + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (HPE Ethernet 10/20Gb 2-port 660M Adapter) pci:v00008086d00001589* ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T @@ -66647,6 +67412,39 @@ pci:v00008086d00001589sv00008086sd00000002* pci:v00008086d00001589sv00008086sd00001003* ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T) +pci:v00008086d0000158A* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE backplane + +pci:v00008086d0000158B* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 + +pci:v00008086d0000158Bsv00008086sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710) + +pci:v00008086d0000158Bsv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710-2) + +pci:v00008086d0000158Bsv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710-2) + +pci:v00008086d0000158Bsv00008086sd00000003* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710-1) + +pci:v00008086d0000158Bsv00008086sd00000004* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710-1) + +pci:v00008086d0000158Bsv00008086sd00000005* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter OCP XXV710-2) + +pci:v00008086d0000158Bsv00008086sd00000006* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter OCP XXV710-2) + +pci:v00008086d0000158Bsv00008086sd00000007* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter OCP XXV710-1) + +pci:v00008086d0000158Bsv00008086sd00000008* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter OCP XXV710-1) + pci:v00008086d000015A0* ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I218-LM @@ -66884,12 +67682,18 @@ pci:v00008086d00001904* pci:v00008086d00001904sv00001028sd000006F3* ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers (Latitude 3570) +pci:v00008086d00001904sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers (B51-80 Laptop) + pci:v00008086d00001905* ID_MODEL_FROM_DATABASE=Skylake PCIe Controller (x8) pci:v00008086d00001906* ID_MODEL_FROM_DATABASE=HD Graphics 510 +pci:v00008086d00001906sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=HD Graphics 510 (B51-80 Laptop) + pci:v00008086d00001908* ID_MODEL_FROM_DATABASE=Skylake Host Bridge/DRAM Registers @@ -67043,9 +67847,78 @@ pci:v00008086d00001962* pci:v00008086d00001962sv0000105Asd00000000* ID_MODEL_FROM_DATABASE=80960RM (i960RM) Microprocessor (SuperTrak SX6000 I2O CPU) +pci:v00008086d000019AC* + ID_MODEL_FROM_DATABASE=DNV SMBus Contoller - Host + +pci:v00008086d000019B0* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 0 + +pci:v00008086d000019B1* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 0 + +pci:v00008086d000019B2* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 0 + +pci:v00008086d000019B3* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 0 + +pci:v00008086d000019B4* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 0 + +pci:v00008086d000019B5* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 0 + +pci:v00008086d000019B6* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 0 + +pci:v00008086d000019B7* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 0 + +pci:v00008086d000019BE* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 0 + +pci:v00008086d000019BF* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 0 + +pci:v00008086d000019C0* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 1 + +pci:v00008086d000019C1* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 1 + +pci:v00008086d000019C2* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 1 + +pci:v00008086d000019C3* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 1 + +pci:v00008086d000019C4* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 1 + +pci:v00008086d000019C5* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 1 + +pci:v00008086d000019C6* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 1 + +pci:v00008086d000019C7* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 1 + +pci:v00008086d000019CE* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 1 + +pci:v00008086d000019CF* + ID_MODEL_FROM_DATABASE=DNV SATA Controller 1 + +pci:v00008086d000019DC* + ID_MODEL_FROM_DATABASE=DNV LPC or eSPI + pci:v00008086d000019DF* ID_MODEL_FROM_DATABASE=DNV SMBus controller +pci:v00008086d000019E0* + ID_MODEL_FROM_DATABASE=DNV SPI Controller + pci:v00008086d00001A21* ID_MODEL_FROM_DATABASE=82840 840 [Carmel] Chipset Host Bridge (Hub A) @@ -67679,6 +68552,9 @@ pci:v00008086d00001E00* pci:v00008086d00001E01* ID_MODEL_FROM_DATABASE=7 Series Chipset Family 4-port SATA Controller [IDE mode] +pci:v00008086d00001E01sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 4-port SATA Controller [IDE mode] (NP300E5C series laptop) + pci:v00008086d00001E02* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family 6-port SATA Controller [AHCI mode] @@ -67700,6 +68576,9 @@ pci:v00008086d00001E03sv00001043sd00001477* pci:v00008086d00001E03sv00001043sd00001517* ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (Zenbook Prime UX31A) +pci:v00008086d00001E03sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (NP300E5C series laptop) + pci:v00008086d00001E04* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SATA Controller [RAID mode] @@ -67718,26 +68597,32 @@ pci:v00008086d00001E08* pci:v00008086d00001E09* ID_MODEL_FROM_DATABASE=7 Series Chipset Family 2-port SATA Controller [IDE mode] +pci:v00008086d00001E09sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 2-port SATA Controller [IDE mode] (NP300E5C series laptop) + pci:v00008086d00001E0E* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SATA Controller [RAID mode] pci:v00008086d00001E10* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 pci:v00008086d00001E10sv00001043sd0000108D* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (VivoBook X202EV) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (VivoBook X202EV) pci:v00008086d00001E10sv00001043sd00001477* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (N56VZ) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (N56VZ) pci:v00008086d00001E10sv00001043sd00001517* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (Zenbook Prime UX31A) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (Zenbook Prime UX31A) pci:v00008086d00001E10sv00001043sd000084CA* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (P8H77-I Motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (P8H77-I Motherboard) + +pci:v00008086d00001E10sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (NP300E5C series laptop) pci:v00008086d00001E10sv00001849sd00001E10* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 1 (Motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (Motherboard) pci:v00008086d00001E12* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2 @@ -67755,16 +68640,19 @@ pci:v00008086d00001E14* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 3 pci:v00008086d00001E16* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 4 + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 4 pci:v00008086d00001E16sv00001043sd0000108D* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 4 (VivoBook X202EV) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 4 (VivoBook X202EV) pci:v00008086d00001E16sv00001043sd00001477* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 4 (N56VZ) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 4 (N56VZ) + +pci:v00008086d00001E16sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 4 (NP300E5C series laptop) pci:v00008086d00001E16sv00001849sd00001618* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 4 (Z77 Extreme4 motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 4 (Z77 Extreme4 motherboard) pci:v00008086d00001E18* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 5 @@ -67791,46 +68679,52 @@ pci:v00008086d00001E1Esv00001849sd00001E1E* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 8 (Motherboard) pci:v00008086d00001E20* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller pci:v00008086d00001E20sv00001028sd0000054B* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (Dell XPS One 2710) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (Dell XPS One 2710) pci:v00008086d00001E20sv00001043sd0000108D* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (VivoBook X202EV) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (VivoBook X202EV) pci:v00008086d00001E20sv00001043sd00001477* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (N56VZ) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (N56VZ) pci:v00008086d00001E20sv00001043sd00001517* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (Zenbook Prime UX31A) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (Zenbook Prime UX31A) pci:v00008086d00001E20sv00001043sd00008415* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (P8H77-I Motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (P8H77-I Motherboard) pci:v00008086d00001E20sv00001043sd00008445* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (ASUS P8Z77-V LX Motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (ASUS P8Z77-V LX Motherboard) + +pci:v00008086d00001E20sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (NP300E5C series laptop) pci:v00008086d00001E20sv00001849sd00001898* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family High Definition Audio Controller (Z77 Extreme4 motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (Z77 Extreme4 motherboard) pci:v00008086d00001E22* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller pci:v00008086d00001E22sv00001043sd0000108D* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (VivoBook X202EV) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (VivoBook X202EV) pci:v00008086d00001E22sv00001043sd00001477* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (N56VZ) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (N56VZ) pci:v00008086d00001E22sv00001043sd00001517* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (Zenbook Prime UX31A) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (Zenbook Prime UX31A) pci:v00008086d00001E22sv00001043sd000084CA* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (P8 series motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (P8 series motherboard) + +pci:v00008086d00001E22sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (NP300E5C series laptop) pci:v00008086d00001E22sv00001849sd00001E22* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SMBus Controller (Motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (Motherboard) pci:v00008086d00001E24* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family Thermal Management Controller @@ -67842,40 +68736,46 @@ pci:v00008086d00001E25* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family DMI to PCI Bridge pci:v00008086d00001E26* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 pci:v00008086d00001E26sv00001043sd0000108D* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (VivoBook X202EV) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (VivoBook X202EV) pci:v00008086d00001E26sv00001043sd00001477* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (N56VZ) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (N56VZ) pci:v00008086d00001E26sv00001043sd00001517* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (Zenbook Prime UX31A) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (Zenbook Prime UX31A) pci:v00008086d00001E26sv00001043sd000084CA* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (P8 series motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (P8 series motherboard) + +pci:v00008086d00001E26sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (NP300E5C series laptop) pci:v00008086d00001E26sv00001849sd00001E26* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1 (Motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (Motherboard) pci:v00008086d00001E2D* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 pci:v00008086d00001E2Dsv00001043sd0000108D* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (VivoBook X202EV) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (VivoBook X202EV) pci:v00008086d00001E2Dsv00001043sd00001477* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (N56VZ) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (N56VZ) pci:v00008086d00001E2Dsv00001043sd00001517* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (Zenbook Prime UX31A) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (Zenbook Prime UX31A) pci:v00008086d00001E2Dsv00001043sd000084CA* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (P8 series motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (P8 series motherboard) + +pci:v00008086d00001E2Dsv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (NP300E5C series laptop) pci:v00008086d00001E2Dsv00001849sd00001E2D* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2 (Motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (Motherboard) pci:v00008086d00001E31* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller @@ -67902,22 +68802,25 @@ pci:v00008086d00001E33* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family LAN Controller pci:v00008086d00001E3A* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 pci:v00008086d00001E3Asv00001043sd0000108D* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (VivoBook X202EV) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (VivoBook X202EV) pci:v00008086d00001E3Asv00001043sd00001477* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (N56VZ) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (N56VZ) pci:v00008086d00001E3Asv00001043sd00001517* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (Zenbook Prime UX31A) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (Zenbook Prime UX31A) pci:v00008086d00001E3Asv00001043sd000084CA* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (P8 series motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (P8 series motherboard) + +pci:v00008086d00001E3Asv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (NP300E5C series laptop) pci:v00008086d00001E3Asv00001849sd00001E3A* - ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #1 (Motherboard) + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (Motherboard) pci:v00008086d00001E3B* ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #2 @@ -68030,6 +68933,9 @@ pci:v00008086d00001E5C* pci:v00008086d00001E5D* ID_MODEL_FROM_DATABASE=HM75 Express Chipset LPC Controller +pci:v00008086d00001E5Dsv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=HM75 Express Chipset LPC Controller (NP300E5C series laptop) + pci:v00008086d00001E5E* ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller @@ -68834,6 +69740,9 @@ pci:v00008086d00002448sv00001458sd00005000* pci:v00008086d00002448sv00001734sd00001055* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Amilo M1420) +pci:v00008086d00002448sv000017AAsd00002013* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (ThinkPad R60e) + pci:v00008086d00002448sv000017AAsd000020AE* ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (ThinkPad T61/R61) @@ -70430,6 +71339,15 @@ pci:v00008086d000024F0sv000010A9sd00008030* pci:v00008086d000024F0sv000010A9sd00008031* ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-path HFI 100 Series, 2-port B-board) +pci:v00008086d000024F0sv00001590sd000000E7* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (100Gb 1-port OP101 QSFP28 x8 PCIe Gen3 with Intel Omni-Path Adapter) + +pci:v00008086d000024F0sv00001590sd000000E8* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (100Gb 1-port OP101 QSFP28 x16 PCIe Gen3 with Intel Omni-Path Adapter) + +pci:v00008086d000024F0sv00001590sd0000021C* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Apollo 100Gb 1-port Intel Omni-Path Architecture 860z Mezzanine FIO Adapter) + pci:v00008086d000024F0sv000015D9sd00000934* ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, SIOM Module) @@ -72059,6 +72977,9 @@ pci:v00008086d000027A0sv0000103Csd000030A1* pci:v00008086d000027A0sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (Compaq nw8440) +pci:v00008086d000027A0sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (530 Laptop) + pci:v00008086d000027A0sv00001043sd00001237* ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (A6J-Q008) @@ -72089,6 +73010,9 @@ pci:v00008086d000027A2* pci:v00008086d000027A2sv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (NC2400) +pci:v00008086d000027A2sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (530 Laptop) + pci:v00008086d000027A2sv000017AAsd0000201A* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (ThinkPad R60/T60/X60 series) @@ -72101,6 +73025,9 @@ pci:v00008086d000027A6* pci:v00008086d000027A6sv0000103Csd000030A1* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (NC2400) +pci:v00008086d000027A6sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (530 Laptop) + pci:v00008086d000027A6sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (CC11/CL11 integrated graphics (secondary)) @@ -72137,6 +73064,9 @@ pci:v00008086d000027B8* pci:v00008086d000027B8sv00001028sd000001E6* ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (PowerEdge 860) +pci:v00008086d000027B8sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (Compaq 500B Microtower) + pci:v00008086d000027B8sv00001043sd00008179* ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (P5KPL-VM Motherboard) @@ -72167,6 +73097,9 @@ pci:v00008086d000027B9sv0000103Csd000030A1* pci:v00008086d000027B9sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (Compaq nw8440) +pci:v00008086d000027B9sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (530 Laptop) + pci:v00008086d000027B9sv00001071sd00008209* ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (Medion MIM 2240 Notebook PC [MD98100]) @@ -72212,6 +73145,9 @@ pci:v00008086d000027C0sv00001028sd000001DF* pci:v00008086d000027C0sv00001028sd000001E6* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (PowerEdge 860) +pci:v00008086d000027C0sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (Compaq 500B Microtower) + pci:v00008086d000027C0sv00001043sd00008179* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (P5KPL-VM Motherboard) @@ -72296,6 +73232,9 @@ pci:v00008086d000027C5sv0000103Csd0000309F* pci:v00008086d000027C5sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] (Compaq nw8440) +pci:v00008086d000027C5sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] (530 Laptop) + pci:v00008086d000027C5sv000017AAsd0000200D* ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] (ThinkPad R60/T60/X60 series) @@ -72323,6 +73262,9 @@ pci:v00008086d000027C8sv00001028sd000001E6* pci:v00008086d000027C8sv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Pavilion A1512X) +pci:v00008086d000027C8sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Compaq 500B Microtower) + pci:v00008086d000027C8sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Compaq nx9420 Notebook) @@ -72332,6 +73274,9 @@ pci:v00008086d000027C8sv0000103Csd000030A1* pci:v00008086d000027C8sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Compaq nw8440) +pci:v00008086d000027C8sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (530 Laptop) + pci:v00008086d000027C8sv00001043sd00001237* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (A6J-Q008) @@ -72392,6 +73337,9 @@ pci:v00008086d000027C9sv00001028sd000001E6* pci:v00008086d000027C9sv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Pavilion A1512X) +pci:v00008086d000027C9sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Compaq 500B Microtower) + pci:v00008086d000027C9sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Compaq nx9420 Notebook) @@ -72461,6 +73409,9 @@ pci:v00008086d000027CAsv00001028sd000001E6* pci:v00008086d000027CAsv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Pavilion A1512X) +pci:v00008086d000027CAsv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Compaq 500B Microtower) + pci:v00008086d000027CAsv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Compaq nx9420 Notebook) @@ -72524,6 +73475,9 @@ pci:v00008086d000027CBsv00001028sd000001DF* pci:v00008086d000027CBsv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Pavilion A1512X) +pci:v00008086d000027CBsv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Compaq 500B Microtower) + pci:v00008086d000027CBsv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Compaq nx9420 Notebook) @@ -72590,6 +73544,9 @@ pci:v00008086d000027CCsv00001028sd000001E6* pci:v00008086d000027CCsv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Pavilion A1512X) +pci:v00008086d000027CCsv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Compaq 500B Microtower) + pci:v00008086d000027CCsv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Compaq nx9420 Notebook) @@ -72599,6 +73556,9 @@ pci:v00008086d000027CCsv0000103Csd000030A1* pci:v00008086d000027CCsv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Compaq nw8440) +pci:v00008086d000027CCsv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (530 Laptop) + pci:v00008086d000027CCsv00001043sd00001237* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (A6J-Q008) @@ -72659,6 +73619,9 @@ pci:v00008086d000027D0sv00001462sd00007418* pci:v00008086d000027D0sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (CC11/CL11) +pci:v00008086d000027D0sv000017AAsd00002011* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (ThinkPad R60e) + pci:v00008086d000027D0sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Desktop Board D425KT) @@ -72683,6 +73646,9 @@ pci:v00008086d000027D2sv00001462sd00007418* pci:v00008086d000027D2sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (CC11/CL11) +pci:v00008086d000027D2sv000017AAsd00002011* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (ThinkPad R60e) + pci:v00008086d000027D2sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Desktop Board D425KT) @@ -72701,6 +73667,9 @@ pci:v00008086d000027D4sv00001462sd00007418* pci:v00008086d000027D4sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (CC11/CL11) +pci:v00008086d000027D4sv000017AAsd00002011* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (ThinkPad R60e) + pci:v00008086d000027D4sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (Desktop Board D425KT) @@ -72722,6 +73691,9 @@ pci:v00008086d000027D6sv00001462sd00007418* pci:v00008086d000027D6sv00001775sd000011CC* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (CC11/CL11) +pci:v00008086d000027D6sv000017AAsd00002011* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (ThinkPad R60e) + pci:v00008086d000027D6sv00008086sd0000544B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (Desktop Board D425KT) @@ -72737,6 +73709,9 @@ pci:v00008086d000027D8sv00001028sd000001D7* pci:v00008086d000027D8sv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Pavilion A1512X) +pci:v00008086d000027D8sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Compaq 500B Microtower) + pci:v00008086d000027D8sv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Compaq nx9420 Notebook) @@ -72746,6 +73721,9 @@ pci:v00008086d000027D8sv0000103Csd000030A1* pci:v00008086d000027D8sv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Compaq nw8440) +pci:v00008086d000027D8sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (530 Laptop) + pci:v00008086d000027D8sv00001043sd00001123* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (A6J-Q008) @@ -72839,6 +73817,9 @@ pci:v00008086d000027DAsv00001028sd000001E6* pci:v00008086d000027DAsv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Pavilion A1512X) +pci:v00008086d000027DAsv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Compaq 500B Microtower) + pci:v00008086d000027DAsv00001043sd00008179* ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (P5KPL-VM Motherboard) @@ -72914,6 +73895,9 @@ pci:v00008086d000027DFsv00001028sd000001E6* pci:v00008086d000027DFsv0000103Csd00002A3B* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Pavilion A1512X) +pci:v00008086d000027DFsv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Compaq 500B Microtower) + pci:v00008086d000027DFsv0000103Csd0000309F* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Compaq nx9420 Notebook) @@ -72923,6 +73907,9 @@ pci:v00008086d000027DFsv0000103Csd000030A1* pci:v00008086d000027DFsv0000103Csd000030A3* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Compaq nw8440) +pci:v00008086d000027DFsv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (530 Laptop) + pci:v00008086d000027DFsv00001043sd00001237* ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (A6J-Q008) @@ -73055,6 +74042,24 @@ pci:v00008086d00002825sv00001462sd00007235* pci:v00008086d00002826* ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller +pci:v00008086d00002826sv00001D49sd00000100* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (ThinkSystem RAID 331) + +pci:v00008086d00002826sv00001D49sd00000101* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (ThinkSystem RAID 331) + +pci:v00008086d00002826sv00001D49sd00000102* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (ThinkSystem RAID 331) + +pci:v00008086d00002826sv00001D49sd00000103* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (ThinkSystem RAID 331) + +pci:v00008086d00002826sv00001D49sd00000104* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (ThinkSystem RAID 331) + +pci:v00008086d00002826sv00001D49sd00000105* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (ThinkSystem RAID 331) + pci:v00008086d00002827* ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [RAID mode] @@ -75311,12 +76316,18 @@ pci:v00008086d00002E29* pci:v00008086d00002E30* ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller +pci:v00008086d00002E30sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller (Compaq 500B Microtower) + pci:v00008086d00002E31* ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port pci:v00008086d00002E32* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller +pci:v00008086d00002E32sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller (Compaq 500B Microtower) + pci:v00008086d00002E33* ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller @@ -75485,6 +76496,15 @@ pci:v00008086d00002F0A* pci:v00008086d00002F0B* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 +pci:v00008086d00002F0D* + ID_MODEL_FROM_DATABASE=Haswell Xeon Non-Transparent Bridge (Back-to-back) + +pci:v00008086d00002F0E* + ID_MODEL_FROM_DATABASE=Haswell Xeon Non-Transparent Bridge (Primary Side) + +pci:v00008086d00002F0F* + ID_MODEL_FROM_DATABASE=Haswell Xeon Non-Transparent Bridge (Secondary Side) + pci:v00008086d00002F10* ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug @@ -76745,11 +77765,11 @@ pci:v00008086d000037CD* pci:v00008086d000037CE* ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE backplane -pci:v00008086d000037CEsv00001590sd00000200* +pci:v00008086d000037CEsv00001590sd00000215* ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE backplane (Ethernet 10Gb 2-port 568i Adapter) -pci:v00008086d000037CEsv00008086sd00000215* - ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE backplane (Ethernet 10Gb 2-port 568i Adapter) +pci:v00008086d000037CEsv000017AAsd00004023* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE backplane (Intel Ethernet Connection X722 for 10GbE backplane) pci:v00008086d000037CF* ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE QSFP+ @@ -76757,12 +77777,33 @@ pci:v00008086d000037CF* pci:v00008086d000037D0* ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ +pci:v00008086d000037D0sv000017AAsd00004020* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ (Intel Ethernet Connection X722 for 10G SFP+) + +pci:v00008086d000037D0sv000017AAsd00004021* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ (Intel Ethernet Connection X722 for 10G SFP+) + pci:v00008086d000037D1* ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE +pci:v00008086d000037D1sv000017AAsd00004020* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE (Intel Ethernet Connection X722 for 1GbE) + +pci:v00008086d000037D1sv000017AAsd00004021* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE (Intel Ethernet Connection X722 for 1GbE) + +pci:v00008086d000037D1sv000017AAsd00004022* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE (Intel Ethernet Connection X722 for 1GbE) + pci:v00008086d000037D2* ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T +pci:v00008086d000037D2sv000017AAsd00004020* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T (Intel Ethernet Connection X722 for 10GBASE) + +pci:v00008086d000037D2sv000017AAsd00004021* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T (Intel Ethernet Connection X722 for 10GBASE) + pci:v00008086d000037D3* ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ @@ -78017,6 +79058,9 @@ pci:v00008086d00004224* pci:v00008086d00004227* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection +pci:v00008086d00004227sv00008086sd00001010* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (ThinkPad R60e) + pci:v00008086d00004227sv00008086sd00001011* ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (ThinkPad T60/R60e/X60s) @@ -80396,24 +81440,51 @@ pci:v00008086d00009D03* pci:v00008086d00009D03sv00001028sd000006F3* ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] (Latitude 3570) +pci:v00008086d00009D03sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] (B51-80 Laptop) + pci:v00008086d00009D14* ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #5 +pci:v00008086d00009D14sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #5 (B51-80 Laptop) + pci:v00008086d00009D15* ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #6 +pci:v00008086d00009D15sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #6 (B51-80 Laptop) + +pci:v00008086d00009D16* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #7 + +pci:v00008086d00009D17* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #8 + +pci:v00008086d00009D18* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #9 + +pci:v00008086d00009D18sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #9 (B51-80 Laptop) + pci:v00008086d00009D21* ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC pci:v00008086d00009D21sv00001028sd000006F3* ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (Latitude 3570) +pci:v00008086d00009D21sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (B51-80 Laptop) + pci:v00008086d00009D23* ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus pci:v00008086d00009D23sv00001028sd000006F3* ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (Latitude 3570) +pci:v00008086d00009D23sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (B51-80 Laptop) + pci:v00008086d00009D27* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO UART Controller #0 @@ -80435,18 +81506,33 @@ pci:v00008086d00009D2F* pci:v00008086d00009D2Fsv00001028sd000006F3* ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller (Latitude 3570) +pci:v00008086d00009D2Fsv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller (B51-80 Laptop) + pci:v00008086d00009D31* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem pci:v00008086d00009D31sv00001028sd000006F3* ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (Latitude 3570) +pci:v00008086d00009D31sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (B51-80 Laptop) + pci:v00008086d00009D3A* ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 pci:v00008086d00009D3Asv00001028sd000006F3* ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (Latitude 3570) +pci:v00008086d00009D3Asv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (B51-80 Laptop) + +pci:v00008086d00009D43* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller + +pci:v00008086d00009D43sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (B51-80 Laptop) + pci:v00008086d00009D48* ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller @@ -80486,6 +81572,9 @@ pci:v00008086d00009D70* pci:v00008086d00009D70sv00001028sd000006F3* ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (Latitude 3570) +pci:v00008086d00009D70sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (B51-80 Laptop) + pci:v00008086d0000A000* ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge @@ -80786,6 +81875,9 @@ pci:v00008086d0000A170* pci:v00008086d0000A182* ID_MODEL_FROM_DATABASE=Lewisburg SATA Controller [AHCI mode] +pci:v00008086d0000A186* + ID_MODEL_FROM_DATABASE=Lewisburg SATA Controller [RAID mode] + pci:v00008086d0000A190* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #1 @@ -80891,6 +81983,9 @@ pci:v00008086d0000A1C7* pci:v00008086d0000A1D2* ID_MODEL_FROM_DATABASE=Lewisburg SSATA Controller [AHCI mode] +pci:v00008086d0000A1D6* + ID_MODEL_FROM_DATABASE=Lewisburg SSATA Controller [RAID mode] + pci:v00008086d0000A1E7* ID_MODEL_FROM_DATABASE=Lewisburg PCI Express Root Port #17 @@ -80924,6 +82019,30 @@ pci:v00008086d0000A1FB* pci:v00008086d0000A1FC* ID_MODEL_FROM_DATABASE=Lewisburg IE: HECI #3 +pci:v00008086d0000A202* + ID_MODEL_FROM_DATABASE=Lewisburg SATA Controller [AHCI mode] + +pci:v00008086d0000A206* + ID_MODEL_FROM_DATABASE=Lewisburg SATA Controller [RAID mode] + +pci:v00008086d0000A223* + ID_MODEL_FROM_DATABASE=Lewisburg SMBus + +pci:v00008086d0000A224* + ID_MODEL_FROM_DATABASE=Lewisburg SPI Controller + +pci:v00008086d0000A242* + ID_MODEL_FROM_DATABASE=Lewisburg LPC or eSPI Controller + +pci:v00008086d0000A243* + ID_MODEL_FROM_DATABASE=Lewisburg LPC or eSPI Controller + +pci:v00008086d0000A252* + ID_MODEL_FROM_DATABASE=Lewisburg SSATA Controller [AHCI mode] + +pci:v00008086d0000A256* + ID_MODEL_FROM_DATABASE=Lewisburg SSATA Controller [RAID mode] + pci:v00008086d0000A620* ID_MODEL_FROM_DATABASE=6400/6402 Advanced Memory Buffer (AMB) diff --git a/hwdb/20-usb-vendor-model.hwdb b/hwdb/20-usb-vendor-model.hwdb index fec0fb4daa..ec0c26fc35 100644 --- a/hwdb/20-usb-vendor-model.hwdb +++ b/hwdb/20-usb-vendor-model.hwdb @@ -287,9 +287,15 @@ usb:v03EBp2140* usb:v03EBp2141* ID_MODEL_FROM_DATABASE=ICE debugger +usb:v03EBp2145* + ID_MODEL_FROM_DATABASE=ATMEGA328P-XMINI (CDC ACM) + usb:v03EBp2310* ID_MODEL_FROM_DATABASE=EVK11xx evaluation board +usb:v03EBp2404* + ID_MODEL_FROM_DATABASE=The Micro + usb:v03EBp2FE4* ID_MODEL_FROM_DATABASE=ATxmega32A4U DFU bootloader @@ -1058,6 +1064,9 @@ usb:v03F0p2212* usb:v03F0p2217* ID_MODEL_FROM_DATABASE=color LaserJet 9500 MFP +usb:v03F0p222A* + ID_MODEL_FROM_DATABASE=LaserJet Pro MFP M125nw + usb:v03F0p2302* ID_MODEL_FROM_DATABASE=PhotoSmart 7600 series @@ -1328,6 +1337,9 @@ usb:v03F0p3902* usb:v03F0p3912* ID_MODEL_FROM_DATABASE=Officejet Pro 8500 +usb:v03F0p3917* + ID_MODEL_FROM_DATABASE=LaserJet P2014 + usb:v03F0p3A02* ID_MODEL_FROM_DATABASE=PhotoSmart 7150 @@ -1814,6 +1826,9 @@ usb:v03F0p8804* usb:v03F0p8904* ID_MODEL_FROM_DATABASE=DeskJet 6940 series +usb:v03F0p8911* + ID_MODEL_FROM_DATABASE=Deskjet 1050 J410 + usb:v03F0p8C07* ID_MODEL_FROM_DATABASE=Digital Stereo Headset @@ -6207,7 +6222,7 @@ usb:v045Ep0084* ID_MODEL_FROM_DATABASE=Basic Optical Mouse usb:v045Ep008A* - ID_MODEL_FROM_DATABASE=Wireless Keyboard and Mouse + ID_MODEL_FROM_DATABASE=Wireless Optical Desktop Receiver 2.0A usb:v045Ep008B* ID_MODEL_FROM_DATABASE=Dual Receiver Wireless Mouse (IntelliPoint) @@ -6863,6 +6878,9 @@ usb:v045Ep0797* usb:v045Ep07A5* ID_MODEL_FROM_DATABASE=Wireless Receiver 1461C +usb:v045Ep07B9* + ID_MODEL_FROM_DATABASE=Wired Keyboard 200 + usb:v045Ep07CA* ID_MODEL_FROM_DATABASE=Surface Pro 3 Docking Station Audio Device @@ -7598,6 +7616,9 @@ usb:v046Dp0B02* usb:v046Dp8801* ID_MODEL_FROM_DATABASE=Video Camera +usb:v046DpB014* + ID_MODEL_FROM_DATABASE=Bluetooth Mouse M336/M337/M535 + usb:v046DpB305* ID_MODEL_FROM_DATABASE=BT Mini-Receiver @@ -7955,6 +7976,9 @@ usb:v046DpC22D* usb:v046DpC22E* ID_MODEL_FROM_DATABASE=G510 Gaming Keyboard onboard audio +usb:v046DpC231* + ID_MODEL_FROM_DATABASE=G13 Virtual Mouse + usb:v046DpC245* ID_MODEL_FROM_DATABASE=G400 Optical Mouse @@ -8021,6 +8045,9 @@ usb:v046DpC2A0* usb:v046DpC2A1* ID_MODEL_FROM_DATABASE=WingMan Force Feedback Mouse +usb:v046DpC2AB* + ID_MODEL_FROM_DATABASE=G13 Joystick + usb:v046DpC301* ID_MODEL_FROM_DATABASE=iTouch Keyboard @@ -8093,6 +8120,9 @@ usb:v046DpC31C* usb:v046DpC31D* ID_MODEL_FROM_DATABASE=Media Keyboard K200 +usb:v046DpC332* + ID_MODEL_FROM_DATABASE=G502 Proteus Spectrum Optical Mouse + usb:v046DpC401* ID_MODEL_FROM_DATABASE=TrackMan Marble Wheel @@ -9170,6 +9200,9 @@ usb:v0482p0203* usb:v0482p0204* ID_MODEL_FROM_DATABASE=iBurst Terminal +usb:v0482p0408* + ID_MODEL_FROM_DATABASE=FS-1320D Printer + usb:v0483* ID_VENDOR_FROM_DATABASE=STMicroelectronics @@ -9551,6 +9584,9 @@ usb:v0499p1054* usb:v0499p160F* ID_MODEL_FROM_DATABASE=P-105 +usb:v0499p1613* + ID_MODEL_FROM_DATABASE=Clavinova CLP535 + usb:v0499p2000* ID_MODEL_FROM_DATABASE=DGP-7 @@ -10334,6 +10370,9 @@ usb:v04A9p10C4* usb:v04A9p10C9* ID_MODEL_FROM_DATABASE=PIXIMA iP4600 Printer +usb:v04A9p10E3* + ID_MODEL_FROM_DATABASE=PIXMA iX6850 Printer + usb:v04A9p1404* ID_MODEL_FROM_DATABASE=W6400PG @@ -12146,6 +12185,9 @@ usb:v04B4p4611* usb:v04B4p4616* ID_MODEL_FROM_DATABASE=Flash Disk (TPP) +usb:v04B4p4624* + ID_MODEL_FROM_DATABASE=DS-Xtreme Flash Card + usb:v04B4p5201* ID_MODEL_FROM_DATABASE=Combi Keyboard-Hub (Hub) @@ -12407,6 +12449,9 @@ usb:v04B8p0143* usb:v04B8p0144* ID_MODEL_FROM_DATABASE=GT-S85 +usb:v04B8p0151* + ID_MODEL_FROM_DATABASE=Perfection V800 Photo + usb:v04B8p0202* ID_MODEL_FROM_DATABASE=Receipt Printer M129C/TM-T70 @@ -13094,6 +13139,9 @@ usb:v04C5p10FE* usb:v04C5p1150* ID_MODEL_FROM_DATABASE=fi-6230 +usb:v04C5p125A* + ID_MODEL_FROM_DATABASE=PalmSecure Sensor Device - MP + usb:v04C5p201D* ID_MODEL_FROM_DATABASE=SATA 3.0 6Gbit/s Adaptor [GROOVY] @@ -13136,6 +13184,9 @@ usb:v04C8p072D* usb:v04CA* ID_VENDOR_FROM_DATABASE=Lite-On Technology Corp. +usb:v04CAp004B* + ID_MODEL_FROM_DATABASE=Keyboard + usb:v04CAp004F* ID_MODEL_FROM_DATABASE=SK-9020 keyboard @@ -13148,6 +13199,9 @@ usb:v04CAp2004* usb:v04CAp2006* ID_MODEL_FROM_DATABASE=Broadcom BCM43142A0 Bluetooth Device +usb:v04CAp2007* + ID_MODEL_FROM_DATABASE=Broadcom BCM43142A0 Bluetooth Device + usb:v04CAp3005* ID_MODEL_FROM_DATABASE=Atheros Bluetooth @@ -13625,6 +13679,9 @@ usb:v04D8pE11C* usb:v04D8pF2C4* ID_MODEL_FROM_DATABASE=Macareux-labs Hygrometry Temperature Sensor +usb:v04D8pF2F7* + ID_MODEL_FROM_DATABASE=Yepkit YKUSH + usb:v04D8pF3AA* ID_MODEL_FROM_DATABASE=Macareux-labs Usbce Bootloader mode @@ -13724,6 +13781,9 @@ usb:v04D9p2834* usb:v04D9pA01C* ID_MODEL_FROM_DATABASE=wireless multimedia keyboard with trackball [Trust ADURA 17911] +usb:v04D9pA050* + ID_MODEL_FROM_DATABASE=Chatman V1 + usb:v04D9pA055* ID_MODEL_FROM_DATABASE=Keyboard @@ -14276,6 +14336,9 @@ usb:v04E8p1006* usb:v04E8p130C* ID_MODEL_FROM_DATABASE=NX100 +usb:v04E8p1323* + ID_MODEL_FROM_DATABASE=WB700 Camera + usb:v04E8p1F05* ID_MODEL_FROM_DATABASE=S2 Portable [JMicron] (500GB) @@ -15179,6 +15242,9 @@ usb:v04F2pB1CF* usb:v04F2pB1D6* ID_MODEL_FROM_DATABASE=CNF9055 Toshiba Webcam +usb:v04F2pB1D8* + ID_MODEL_FROM_DATABASE=1.3M Webcam + usb:v04F2pB1E4* ID_MODEL_FROM_DATABASE=Toshiba Integrated Webcam @@ -18611,6 +18677,9 @@ usb:v0557p2011* usb:v0557p2202* ID_MODEL_FROM_DATABASE=CS124U Miniview II KVM Switch +usb:v0557p2212* + ID_MODEL_FROM_DATABASE=Keyboard/Mouse + usb:v0557p2213* ID_MODEL_FROM_DATABASE=CS682 2-Port USB 2.0 DVI KVM Switch @@ -18636,7 +18705,7 @@ usb:v0557p7820* ID_MODEL_FROM_DATABASE=UC-2322 2xSerial Ports [mos7820] usb:v0557p8021* - ID_MODEL_FROM_DATABASE=CS1764A [CubiQ DVI KVMP Switch] + ID_MODEL_FROM_DATABASE=Hub usb:v0558* ID_VENDOR_FROM_DATABASE=Truevision, Inc. @@ -21623,6 +21692,9 @@ usb:v05ACp0263* usb:v05ACp0267* ID_MODEL_FROM_DATABASE=Magic Keyboard A1644 +usb:v05ACp0269* + ID_MODEL_FROM_DATABASE=Magic Mouse 2 (Lightning connector) + usb:v05ACp0273* ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) @@ -23384,6 +23456,9 @@ usb:v05E3p0743* usb:v05E3p0745* ID_MODEL_FROM_DATABASE=Logilink CR0012 +usb:v05E3p0748* + ID_MODEL_FROM_DATABASE=All-in-One Cardreader + usb:v05E3p0751* ID_MODEL_FROM_DATABASE=microSD Card Reader @@ -23612,6 +23687,9 @@ usb:v05FDp262F* usb:v05FDpDAAE* ID_MODEL_FROM_DATABASE=Game Shark +usb:v05FDpDBAE* + ID_MODEL_FROM_DATABASE=Datel XBoxMC + usb:v05FE* ID_VENDOR_FROM_DATABASE=Chic Technology Corp. @@ -23789,6 +23867,12 @@ usb:v0616* usb:v0617* ID_VENDOR_FROM_DATABASE=Swiss Federal Insitute of Technology +usb:v0617p000A* + ID_MODEL_FROM_DATABASE=Thymio-II + +usb:v0617p000C* + ID_MODEL_FROM_DATABASE=Thymio-II Wireless + usb:v0618* ID_VENDOR_FROM_DATABASE=MacAlly @@ -24206,6 +24290,9 @@ usb:v064EpF102* usb:v064EpF103* ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam [R5U877] +usb:v064EpF209* + ID_MODEL_FROM_DATABASE=HP Webcam + usb:v064EpF300* ID_MODEL_FROM_DATABASE=UVC 0.3M Webcam @@ -27812,6 +27899,12 @@ usb:v0781p5580* usb:v0781p5581* ID_MODEL_FROM_DATABASE=Ultra +usb:v0781p5583* + ID_MODEL_FROM_DATABASE=Ultra Fit + +usb:v0781p5591* + ID_MODEL_FROM_DATABASE=Ultra Flair + usb:v0781p5E10* ID_MODEL_FROM_DATABASE=Encrypted @@ -31874,6 +31967,12 @@ usb:v091Ep0004* usb:v091Ep0200* ID_MODEL_FROM_DATABASE=Data Card Programmer (install) +usb:v091Ep086E* + ID_MODEL_FROM_DATABASE=Forerunner 735XT + +usb:v091Ep097F* + ID_MODEL_FROM_DATABASE=Forerunner 235 + usb:v091Ep1200* ID_MODEL_FROM_DATABASE=Data Card Programmer @@ -32069,6 +32168,9 @@ usb:v0930p000C* usb:v0930p0010* ID_MODEL_FROM_DATABASE=Gigabeat S (mtp) +usb:v0930p01BF* + ID_MODEL_FROM_DATABASE=2.5"External Hard Disk + usb:v0930p0200* ID_MODEL_FROM_DATABASE=Integrated Bluetooth (Taiyo Yuden) @@ -32657,6 +32759,9 @@ usb:v0955p7030* usb:v0955p7100* ID_MODEL_FROM_DATABASE=Tegra Device +usb:v0955p7210* + ID_MODEL_FROM_DATABASE=SHIELD Controller + usb:v0955p7820* ID_MODEL_FROM_DATABASE=Tegra 2 AC100 developer mode @@ -32753,9 +32858,27 @@ usb:v0968* usb:v096E* ID_VENDOR_FROM_DATABASE=Feitian Technologies, Inc. +usb:v096Ep0005* + ID_MODEL_FROM_DATABASE=ePass2000 + usb:v096Ep0120* ID_MODEL_FROM_DATABASE=Microcosm Ltd Dinkey +usb:v096Ep0305* + ID_MODEL_FROM_DATABASE=ePass2000Auto + +usb:v096Ep0309* + ID_MODEL_FROM_DATABASE=ePass3000GM + +usb:v096Ep0401* + ID_MODEL_FROM_DATABASE=ePass3000 + +usb:v096Ep0702* + ID_MODEL_FROM_DATABASE=ePass3003 + +usb:v096Ep0703* + ID_MODEL_FROM_DATABASE=ePass3003Auto + usb:v096Ep0802* ID_MODEL_FROM_DATABASE=ePass2000 (G&D STARCOS SPK 2.4) @@ -32903,6 +33026,9 @@ usb:v099Ap713A* usb:v099Ap7160* ID_MODEL_FROM_DATABASE=Hyper Slim Keyboard +usb:v099E* + ID_VENDOR_FROM_DATABASE=Trimble Navigation, Ltd + usb:v09A3* ID_VENDOR_FROM_DATABASE=PairGain Technologies @@ -33071,6 +33197,33 @@ usb:v09CA* usb:v09CAp5544* ID_MODEL_FROM_DATABASE=PIO +usb:v09CB* + ID_VENDOR_FROM_DATABASE=FLIR Systems + +usb:v09CBp1001* + ID_MODEL_FROM_DATABASE=Network Adapter + +usb:v09CBp1002* + ID_MODEL_FROM_DATABASE=Ex-Series RNDIS interface + +usb:v09CBp1004* + ID_MODEL_FROM_DATABASE=Ex-Series UVC interface + +usb:v09CBp1005* + ID_MODEL_FROM_DATABASE=Ex-Series RNDIS and UVC interface + +usb:v09CBp1006* + ID_MODEL_FROM_DATABASE=Ex-Series RNDIS and MSD interface + +usb:v09CBp1007* + ID_MODEL_FROM_DATABASE=Ex-Series UVC and MSD interface + +usb:v09CBp1008* + ID_MODEL_FROM_DATABASE=Serial Port + +usb:v09CBp1996* + ID_MODEL_FROM_DATABASE=FLIR ONE Camera + usb:v09CC* ID_VENDOR_FROM_DATABASE=Workbit Corp. @@ -33105,7 +33258,7 @@ usb:v09D3p000B* ID_MODEL_FROM_DATABASE=Bluetooth Adapter class 1 [BlueLight] usb:v09D7* - ID_VENDOR_FROM_DATABASE=Novatel Wireless + ID_VENDOR_FROM_DATABASE=NovAtel Inc. usb:v09D7p0100* ID_MODEL_FROM_DATABASE=NovAtel FlexPack GPS receiver @@ -33146,6 +33299,9 @@ usb:v09DAp0260* usb:v09DAp032B* ID_MODEL_FROM_DATABASE=Wireless Mouse (Battery Free) +usb:v09DAp1068* + ID_MODEL_FROM_DATABASE=Bloody A90 Mouse + usb:v09DAp8090* ID_MODEL_FROM_DATABASE=X-718BK Oscar Optical Gaming Mouse @@ -33878,9 +34034,15 @@ usb:v0A5Cp2151* usb:v0A5Cp2154* ID_MODEL_FROM_DATABASE=BCM92046DG-CL1ROM Bluetooth 2.1 UHE Dongle +usb:v0A5Cp216A* + ID_MODEL_FROM_DATABASE=BCM43142A0 Bluetooth + usb:v0A5Cp216C* ID_MODEL_FROM_DATABASE=BCM43142A0 Bluetooth Device +usb:v0A5Cp216D* + ID_MODEL_FROM_DATABASE=BCM43142A0 Bluetooth 4.0 + usb:v0A5Cp216F* ID_MODEL_FROM_DATABASE=BCM20702A0 Bluetooth @@ -33965,6 +34127,9 @@ usb:v0A5Cp5804* usb:v0A5Cp6300* ID_MODEL_FROM_DATABASE=Pirelli Remote NDIS Device +usb:v0A5Cp6410* + ID_MODEL_FROM_DATABASE=BCM20703A1 Bluetooth 4.1 + LE + usb:v0A5CpBD11* ID_MODEL_FROM_DATABASE=TiVo AG0100 802.11bg Wireless Adapter [Broadcom BCM4320] @@ -35048,6 +35213,12 @@ usb:v0B05p17CB* usb:v0B05p17D1* ID_MODEL_FROM_DATABASE=AC51 802.11a/b/g/n/ac Wireless Adapter [Mediatek MT7610/Ralink RT2870] +usb:v0B05p180A* + ID_MODEL_FROM_DATABASE=Broadcom BCM20702 Single-Chip Bluetooth 4.0 + LE + +usb:v0B05p1825* + ID_MODEL_FROM_DATABASE=Qualcomm Bluetooth 4.1 + usb:v0B05p4C80* ID_MODEL_FROM_DATABASE=Transformer Pad TF300TG @@ -35123,18 +35294,33 @@ usb:v0B0Dp0000* usb:v0B0E* ID_VENDOR_FROM_DATABASE=GN Netcom +usb:v0B0Ep0348* + ID_MODEL_FROM_DATABASE=Jabra UC VOICE 550a MS + usb:v0B0Ep034C* ID_MODEL_FROM_DATABASE=Jabra UC Voice 750 MS +usb:v0B0Ep0410* + ID_MODEL_FROM_DATABASE=Jabra SPEAK 410 + usb:v0B0Ep0420* ID_MODEL_FROM_DATABASE=Jabra SPEAK 510 usb:v0B0Ep094D* ID_MODEL_FROM_DATABASE=GN Netcom / Jabra REVO Wireless +usb:v0B0Ep1017* + ID_MODEL_FROM_DATABASE=Jabra PRO 930 + usb:v0B0Ep1022* ID_MODEL_FROM_DATABASE=Jabra PRO 9450, Type 9400BS (DECT Headset) +usb:v0B0Ep1041* + ID_MODEL_FROM_DATABASE=Jabra PRO 9460 + +usb:v0B0Ep1900* + ID_MODEL_FROM_DATABASE=Jabra Biz 1900 + usb:v0B0Ep2007* ID_MODEL_FROM_DATABASE=GN 2000 Stereo Corded Headset @@ -35198,6 +35384,9 @@ usb:v0B33* usb:v0B33p0020* ID_MODEL_FROM_DATABASE=ShuttleXpress +usb:v0B33p0030* + ID_MODEL_FROM_DATABASE=ShuttlePro v2 + usb:v0B33p0700* ID_MODEL_FROM_DATABASE=RollerMouse Pro @@ -35375,6 +35564,12 @@ usb:v0B48p3012* usb:v0B48p3014* ID_MODEL_FROM_DATABASE=TT-TVStick CT2-4400 +usb:v0B48p3015* + ID_MODEL_FROM_DATABASE=TT-connect CT2-4650 CI + +usb:v0B48p3017* + ID_MODEL_FROM_DATABASE=TT-connect S2-4650 CI + usb:v0B49* ID_VENDOR_FROM_DATABASE=ASCII Corp. @@ -35619,7 +35814,7 @@ usb:v0B95p772B* ID_MODEL_FROM_DATABASE=AX88772B usb:v0B95p7E2B* - ID_MODEL_FROM_DATABASE=AX88772B + ID_MODEL_FROM_DATABASE=AX88772B Fast Ethernet Controller usb:v0B96* ID_VENDOR_FROM_DATABASE=Sewon Telecom @@ -36305,15 +36500,24 @@ usb:v0BB4p0CA5* usb:v0BB4p0CAE* ID_MODEL_FROM_DATABASE=T-Mobile MyTouch 4G Slide [Doubleshot] +usb:v0BB4p0DE5* + ID_MODEL_FROM_DATABASE=One (M7) + usb:v0BB4p0DEA* ID_MODEL_FROM_DATABASE=M7_UL [HTC One] usb:v0BB4p0F25* ID_MODEL_FROM_DATABASE=One M8 +usb:v0BB4p0F63* + ID_MODEL_FROM_DATABASE=Desire 610 Via MTP + usb:v0BB4p0F64* ID_MODEL_FROM_DATABASE=Desire 601 +usb:v0BB4p0FB4* + ID_MODEL_FROM_DATABASE=Remote NDIS based Device + usb:v0BB4p0FF8* ID_MODEL_FROM_DATABASE=Desire HD (Tethering Mode) @@ -36386,6 +36590,9 @@ usb:v0BC2p2200* usb:v0BC2p2300* ID_MODEL_FROM_DATABASE=Expansion Portable +usb:v0BC2p231A* + ID_MODEL_FROM_DATABASE=Expansion Portable + usb:v0BC2p2320* ID_MODEL_FROM_DATABASE=USB 3.0 bridge [Portable Expansion Drive] @@ -36425,6 +36632,9 @@ usb:v0BC2p5030* usb:v0BC2p5031* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex USB 3.0 +usb:v0BC2p5032* + ID_MODEL_FROM_DATABASE=SATA cable + usb:v0BC2p5070* ID_MODEL_FROM_DATABASE=FreeAgent GoFlex Desk @@ -36461,9 +36671,15 @@ usb:v0BC2pAB20* usb:v0BC2pAB21* ID_MODEL_FROM_DATABASE=Backup Plus Slim +usb:v0BC2pAB24* + ID_MODEL_FROM_DATABASE=Backup Plus Portable Drive + usb:v0BC2pAB31* ID_MODEL_FROM_DATABASE=Backup Plus Desktop Drive (5TB) +usb:v0BC2pAB34* + ID_MODEL_FROM_DATABASE=Backup Plus + usb:v0BC3* ID_VENDOR_FROM_DATABASE=IPWireless, Inc. @@ -36563,6 +36779,9 @@ usb:v0BDAp0107* usb:v0BDAp0108* ID_MODEL_FROM_DATABASE=Mass Storage Device +usb:v0BDAp0109* + ID_MODEL_FROM_DATABASE=microSDXC Card Reader [Hama 00091047] + usb:v0BDAp0111* ID_MODEL_FROM_DATABASE=RTS5111 Card Reader Controller @@ -36600,7 +36819,7 @@ usb:v0BDAp0152* ID_MODEL_FROM_DATABASE=Mass Storage Device usb:v0BDAp0153* - ID_MODEL_FROM_DATABASE=Mass Storage Device + ID_MODEL_FROM_DATABASE=3-in-1 (SD/SDHC/SDXC) Card Reader usb:v0BDAp0156* ID_MODEL_FROM_DATABASE=Mass Storage Device @@ -36644,6 +36863,9 @@ usb:v0BDAp0186* usb:v0BDAp0301* ID_MODEL_FROM_DATABASE=multicard reader +usb:v0BDAp0307* + ID_MODEL_FROM_DATABASE=Card Reader + usb:v0BDAp1724* ID_MODEL_FROM_DATABASE=RTL8723AU 802.11n WLAN Adapter @@ -36659,18 +36881,33 @@ usb:v0BDAp2838* usb:v0BDAp5401* ID_MODEL_FROM_DATABASE=RTL 8153 USB 3.0 hub with gigabit ethernet +usb:v0BDAp570C* + ID_MODEL_FROM_DATABASE=Asus laptop camera + usb:v0BDAp5730* ID_MODEL_FROM_DATABASE=HP 2.0MP High Definition Webcam usb:v0BDAp5775* ID_MODEL_FROM_DATABASE=HP "Truevision HD" laptop camera +usb:v0BDAp57B3* + ID_MODEL_FROM_DATABASE=Acer 640 × 480 laptop camera + +usb:v0BDAp57DA* + ID_MODEL_FROM_DATABASE=Built-In Video Camera + usb:v0BDAp8150* ID_MODEL_FROM_DATABASE=RTL8150 Fast Ethernet Adapter usb:v0BDAp8151* ID_MODEL_FROM_DATABASE=RTL8151 Adapteon Business Mobile Networks BV +usb:v0BDAp8152* + ID_MODEL_FROM_DATABASE=RTL8152 Fast Ethernet Adapter + +usb:v0BDAp8153* + ID_MODEL_FROM_DATABASE=RTL8153 Gigabit Ethernet Adapter + usb:v0BDAp8171* ID_MODEL_FROM_DATABASE=RTL8188SU 802.11n WLAN Adapter @@ -36698,6 +36935,9 @@ usb:v0BDAp8187* usb:v0BDAp8189* ID_MODEL_FROM_DATABASE=RTL8187B Wireless 802.11g 54Mbps Network Adapter +usb:v0BDAp818B* + ID_MODEL_FROM_DATABASE=ACT-WNP-UA-005 802.11b/g/n WLAN Adapter + usb:v0BDAp8192* ID_MODEL_FROM_DATABASE=RTL8191SU 802.11n Wireless Adapter @@ -36752,6 +36992,9 @@ usb:v0BDBp190A* usb:v0BDBp190B* ID_MODEL_FROM_DATABASE=C3607w v2 Mobile Broadband Module +usb:v0BDBp1926* + ID_MODEL_FROM_DATABASE=H5321 gw Mobile Broadband Driver + usb:v0BDC* ID_VENDOR_FROM_DATABASE=Y Media Corp. @@ -36851,6 +37094,9 @@ usb:v0BF8p100F* usb:v0BF8p1017* ID_MODEL_FROM_DATABASE=Keyboard KB SCR +usb:v0BF8p101F* + ID_MODEL_FROM_DATABASE=Fujitsu Full HD Pro Webcam + usb:v0BFD* ID_VENDOR_FROM_DATABASE=Kvaser AB @@ -37562,6 +37808,18 @@ usb:v0C45p648B* usb:v0C45p64BD* ID_MODEL_FROM_DATABASE=Sony Visual Communication Camera +usb:v0C45p64D2* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v0C45p651B* + ID_MODEL_FROM_DATABASE=HP Webcam + +usb:v0C45p6705* + ID_MODEL_FROM_DATABASE=Integrated HD Webcam + +usb:v0C45p6710* + ID_MODEL_FROM_DATABASE=Integrated Webcam + usb:v0C45p7401* ID_MODEL_FROM_DATABASE=TEMPer Temperature Sensor @@ -38075,6 +38333,12 @@ usb:v0CA7* usb:v0CAD* ID_VENDOR_FROM_DATABASE=Motorola CGISS +usb:v0CADp1030* + ID_MODEL_FROM_DATABASE=APX Series Radio + +usb:v0CADp1602* + ID_MODEL_FROM_DATABASE=IMPRES Battery Data Reader + usb:v0CADp9001* ID_MODEL_FROM_DATABASE=PowerPad Pocket PC Device @@ -38174,9 +38438,6 @@ usb:v0CC5* usb:v0CC6* ID_VENDOR_FROM_DATABASE=Intermagic Corp. -usb:v0CC7* - ID_VENDOR_FROM_DATABASE=Kontron Medical AG - usb:v0CC8* ID_VENDOR_FROM_DATABASE=Technotools Corp. @@ -38279,6 +38540,9 @@ usb:v0CCDp0086* usb:v0CCDp008E* ID_MODEL_FROM_DATABASE=Cinergy HTC XS +usb:v0CCDp0096* + ID_MODEL_FROM_DATABASE=Grabby + usb:v0CCDp0097* ID_MODEL_FROM_DATABASE=Cinergy T RC MKII @@ -38297,6 +38561,12 @@ usb:v0CCDp00B3* usb:v0CCDp00E0* ID_MODEL_FROM_DATABASE=NOXON DAB/DAB+ Stick V2 +usb:v0CCDp0102* + ID_MODEL_FROM_DATABASE=Cinergy S2 Stick + +usb:v0CCDp0105* + ID_MODEL_FROM_DATABASE=Cinergy S2 Box + usb:v0CCDp10A7* ID_MODEL_FROM_DATABASE=TerraTec G3 @@ -38472,7 +38742,7 @@ usb:v0CF2p6250* ID_MODEL_FROM_DATABASE=SD card reader (UB6250) usb:v0CF3* - ID_VENDOR_FROM_DATABASE=Atheros Communications, Inc. + ID_VENDOR_FROM_DATABASE=Qualcomm Atheros Communications usb:v0CF3p0001* ID_MODEL_FROM_DATABASE=AR5523 @@ -38519,9 +38789,15 @@ usb:v0CF3p3004* usb:v0CF3p3005* ID_MODEL_FROM_DATABASE=AR3011 Bluetooth +usb:v0CF3p3007* + ID_MODEL_FROM_DATABASE=AR3012 Bluetooth 4.0 (no firmware) + usb:v0CF3p3008* ID_MODEL_FROM_DATABASE=Bluetooth (AR3011) +usb:v0CF3p311F* + ID_MODEL_FROM_DATABASE=AR3012 Bluetooth + usb:v0CF3p7015* ID_MODEL_FROM_DATABASE=TP-Link TL-WN821N v3 / TL-WN822N v2 802.11n [Atheros AR7010+AR9287] @@ -38537,6 +38813,9 @@ usb:v0CF3pB002* usb:v0CF3pB003* ID_MODEL_FROM_DATABASE=Ubiquiti WiFiStationEXT 802.11n [Atheros AR9271] +usb:v0CF3pE006* + ID_MODEL_FROM_DATABASE=Dell Wireless 1802 Bluetooth 4.0 LE + usb:v0CF4* ID_VENDOR_FROM_DATABASE=Fomtex Corp. @@ -39584,6 +39863,9 @@ usb:v0DBAp1000* usb:v0DBAp3000* ID_MODEL_FROM_DATABASE=Mbox 2 +usb:v0DBApB011* + ID_MODEL_FROM_DATABASE=Eleven Rack + usb:v0DBC* ID_VENDOR_FROM_DATABASE=A&D Medical @@ -39611,6 +39893,9 @@ usb:v0DBFp0300* usb:v0DBFp0333* ID_MODEL_FROM_DATABASE=Storage Adapter +usb:v0DBFp0502* + ID_MODEL_FROM_DATABASE=FSC Storagebird XL hard disk + usb:v0DBFp0707* ID_MODEL_FROM_DATABASE=ZIV Drive @@ -39639,7 +39924,7 @@ usb:v0DC3p1702* ID_MODEL_FROM_DATABASE=ASEKey usb:v0DC4* - ID_VENDOR_FROM_DATABASE=Macpower Peripherals, Ltd + ID_VENDOR_FROM_DATABASE=inXtron, Inc. usb:v0DC4p0040* ID_MODEL_FROM_DATABASE=Mass Storage Device @@ -39959,12 +40244,18 @@ usb:v0DF6p0060* usb:v0DF6p0062* ID_MODEL_FROM_DATABASE=WLA-5000 802.11abgn [Ralink RT3572] +usb:v0DF6p006F* + ID_MODEL_FROM_DATABASE=WLA-5100 + usb:v0DF6p0072* ID_MODEL_FROM_DATABASE=AX88179 Gigabit Ethernet [Sitecom] usb:v0DF6p061C* ID_MODEL_FROM_DATABASE=LN-028 Network USB 2.0 Adapter +usb:v0DF6p214A* + ID_MODEL_FROM_DATABASE=IDE/SATA Combo Adapter [CN-330] + usb:v0DF6p21F4* ID_MODEL_FROM_DATABASE=44 St Bluetooth Device @@ -40178,20 +40469,11 @@ usb:v0E35* usb:v0E36* ID_VENDOR_FROM_DATABASE=TiePie engineering -usb:v0E36p0008* - ID_MODEL_FROM_DATABASE=Handyscope HS3 - usb:v0E36p0009* - ID_MODEL_FROM_DATABASE=Handyscope HS3 (br) - -usb:v0E36p000A* - ID_MODEL_FROM_DATABASE=Handyscope HS4 + ID_MODEL_FROM_DATABASE=Handyscope HS3 usb:v0E36p000B* - ID_MODEL_FROM_DATABASE=Handyscope HS4 (br) - -usb:v0E36p000E* - ID_MODEL_FROM_DATABASE=Handyscope HS4-DIFF + ID_MODEL_FROM_DATABASE=Handyscope HS4 usb:v0E36p000F* ID_MODEL_FROM_DATABASE=Handyscope HS4-DIFF (br) @@ -40496,12 +40778,18 @@ usb:v0E8Dp0004* usb:v0E8Dp0023* ID_MODEL_FROM_DATABASE=S103 +usb:v0E8Dp00A5* + ID_MODEL_FROM_DATABASE=GSM modem [Medion Surfstick Model:S4222] + usb:v0E8Dp1806* ID_MODEL_FROM_DATABASE=Samsung SE-208 Slim Portable DVD Writer usb:v0E8Dp1836* ID_MODEL_FROM_DATABASE=Samsung SE-S084 Super WriteMaster Slim External DVD writer +usb:v0E8Dp1956* + ID_MODEL_FROM_DATABASE=Samsung SE-506 Portable BluRay Disc Writer + usb:v0E8Dp2000* ID_MODEL_FROM_DATABASE=MT65xx Preloader @@ -40856,6 +41144,15 @@ usb:v0F0Dp0011* usb:v0F0E* ID_VENDOR_FROM_DATABASE=Energy Full Corp. +usb:v0F0F* + ID_VENDOR_FROM_DATABASE=Silego Technology Inc + +usb:v0F0Fp0006* + ID_MODEL_FROM_DATABASE=GreenPak Universal Dev Board (Active Mode) + +usb:v0F0Fp8006* + ID_MODEL_FROM_DATABASE=GreenPak Universal Dev Board (Reset Mode) + usb:v0F11* ID_VENDOR_FROM_DATABASE=LD Didactic GmbH @@ -40913,6 +41210,9 @@ usb:v0F14* usb:v0F14p0012* ID_MODEL_FROM_DATABASE=Vital'Act 3S +usb:v0F14p0038* + ID_MODEL_FROM_DATABASE=XIRING Smart Card Terminal LEO V2 + usb:v0F18* ID_VENDOR_FROM_DATABASE=Finger Lakes Instrumentation @@ -41375,6 +41675,24 @@ usb:v0FCEp0172* usb:v0FCEp0177* ID_MODEL_FROM_DATABASE=Xperia Ion [Mass Storage] +usb:v0FCEp0188* + ID_MODEL_FROM_DATABASE=ST26i + +usb:v0FCEp019C* + ID_MODEL_FROM_DATABASE=C6833 + +usb:v0FCEp019E* + ID_MODEL_FROM_DATABASE=C6903 + +usb:v0FCEp01A5* + ID_MODEL_FROM_DATABASE=SO-04F + +usb:v0FCEp01A7* + ID_MODEL_FROM_DATABASE=D5503 + +usb:v0FCEp01BA* + ID_MODEL_FROM_DATABASE=D6603 [Xperia Z3] + usb:v0FCEp01BB* ID_MODEL_FROM_DATABASE=D5803 [Xperia Z3 Compact] (MTP mode) @@ -41426,6 +41744,9 @@ usb:v0FCEp5177* usb:v0FCEp518C* ID_MODEL_FROM_DATABASE=C1605 [Xperia E dual] MTD mode +usb:v0FCEp51A7* + ID_MODEL_FROM_DATABASE=D5503 (Xperia Z1 Compact) + usb:v0FCEp614F* ID_MODEL_FROM_DATABASE=Xperia X12 (debug mode) @@ -41594,6 +41915,42 @@ usb:v0FCEpE167* usb:v0FCEpE19B* ID_MODEL_FROM_DATABASE=C2005 [Xperia M dual] (Mass Storage) +usb:v0FCEpE1A9* + ID_MODEL_FROM_DATABASE=D5303 + +usb:v0FCEpE1AA* + ID_MODEL_FROM_DATABASE=D2303 + +usb:v0FCEpE1AD* + ID_MODEL_FROM_DATABASE=D5103 + +usb:v0FCEpE1B0* + ID_MODEL_FROM_DATABASE=D6708 + +usb:v0FCEpE1B5* + ID_MODEL_FROM_DATABASE=D2004 + +usb:v0FCEpE1BA* + ID_MODEL_FROM_DATABASE=D6683 + +usb:v0FCEpE1BB* + ID_MODEL_FROM_DATABASE=SO-02G + +usb:v0FCEpE1BC* + ID_MODEL_FROM_DATABASE=D2203 + +usb:v0FCEpE1C0* + ID_MODEL_FROM_DATABASE=SGP621 + +usb:v0FCEpE1C2* + ID_MODEL_FROM_DATABASE=D2533 + +usb:v0FCEpE1C9* + ID_MODEL_FROM_DATABASE=E6553 + +usb:v0FCEpE1CF* + ID_MODEL_FROM_DATABASE=SGP771 + usb:v0FCEpF0FA* ID_MODEL_FROM_DATABASE=MN800 / Smartwatch 2 (DFU mode) @@ -41690,6 +42047,9 @@ usb:v0FE0p0101* usb:v0FE0p0200* ID_MODEL_FROM_DATABASE=Bluetooth Keypad +usb:v0FE2* + ID_VENDOR_FROM_DATABASE=Air Techniques + usb:v0FE4* ID_VENDOR_FROM_DATABASE=IN-Tech Electronics, Ltd @@ -41697,7 +42057,7 @@ usb:v0FE5* ID_VENDOR_FROM_DATABASE=Greenconn (U.S.A.), Inc. usb:v0FE6* - ID_VENDOR_FROM_DATABASE=Kontron (Industrial Computer Source / ICS Advent) + ID_VENDOR_FROM_DATABASE=ICS Advent usb:v0FE6p8101* ID_MODEL_FROM_DATABASE=DM9601 Fast Ethernet Adapter @@ -41714,6 +42074,9 @@ usb:v0FE9* usb:v0FE9p4020* ID_MODEL_FROM_DATABASE=TViX M-6500 +usb:v0FE9p9010* + ID_MODEL_FROM_DATABASE=FusionRemote IR receiver + usb:v0FE9pDB00* ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T (MT352+LgZ201) (uninitialized) @@ -41831,8 +42194,11 @@ usb:v1004p61FC* usb:v1004p61FE* ID_MODEL_FROM_DATABASE=Optimus Android Phone [USB tethering mode] +usb:v1004p627F* + ID_MODEL_FROM_DATABASE=G3 (VS985) Android Phone (MTP/Download mode) + usb:v1004p6300* - ID_MODEL_FROM_DATABASE=G2/Optimus Android Phone + ID_MODEL_FROM_DATABASE=G2/Optimus Android Phone [Charge mode] usb:v1004p631C* ID_MODEL_FROM_DATABASE=G2/Optimus Android Phone [MTP mode] @@ -41847,7 +42213,7 @@ usb:v1004p631F* ID_MODEL_FROM_DATABASE=Optimus Android Phone (Charge Mode) usb:v1004p633E* - ID_MODEL_FROM_DATABASE=G2 Android Phone [MTP mode] + ID_MODEL_FROM_DATABASE=G2/G3 Android Phone [MTP/PTP/Download mode] usb:v1004p6344* ID_MODEL_FROM_DATABASE=G2 Android Phone [tethering mode] @@ -42365,15 +42731,33 @@ usb:v1058p0748* usb:v1058p07A8* ID_MODEL_FROM_DATABASE=My Passport (WDBBEP), My Passport for Mac (WDBLUZ) +usb:v1058p07AE* + ID_MODEL_FROM_DATABASE=My Passport Edge for Mac (WDBJBH) + +usb:v1058p07BA* + ID_MODEL_FROM_DATABASE=PiDrive (WDLB) + usb:v1058p0810* ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBZFP) +usb:v1058p0816* + ID_MODEL_FROM_DATABASE=My Passport Air (WDBBLW) + usb:v1058p0820* ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBMWV, WDBZFP) +usb:v1058p0822* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBBUZ) + +usb:v1058p0824* + ID_MODEL_FROM_DATABASE=My Passport Slim (WDBPDZ) + usb:v1058p0830* ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBZFP) +usb:v1058p0837* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBBKD) + usb:v1058p0900* ID_MODEL_FROM_DATABASE=MyBook Essential External HDD @@ -42386,6 +42770,9 @@ usb:v1058p0902* usb:v1058p0903* ID_MODEL_FROM_DATABASE=My Book Premium Edition +usb:v1058p0905* + ID_MODEL_FROM_DATABASE=My Book Pro Edition II (WD10000C033-001) + usb:v1058p0910* ID_MODEL_FROM_DATABASE=My Book Essential Edition (Green Ring) (WDG1U) @@ -42410,6 +42797,9 @@ usb:v1058p1042* usb:v1058p1048* ID_MODEL_FROM_DATABASE=Elements Portable (WDBU6Y) +usb:v1058p1078* + ID_MODEL_FROM_DATABASE=Elements Portable (WDBUZG) + usb:v1058p107C* ID_MODEL_FROM_DATABASE=Elements Desktop (WDBWLG) @@ -42456,7 +42846,16 @@ usb:v1058p1140* ID_MODEL_FROM_DATABASE=My Book Essential (WDBACW) usb:v1058p1230* - ID_MODEL_FROM_DATABASE=My Book (WDBFJK0030HBK) + ID_MODEL_FROM_DATABASE=My Book (WDBFJK) + +usb:v1058p1235* + ID_MODEL_FROM_DATABASE=My Book (WDBFJK0040HBK) + +usb:v1058p259D* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBBKD) + +usb:v1058p259F* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WD10JMVW) usb:v1059* ID_VENDOR_FROM_DATABASE=Giesecke & Devrient GmbH @@ -49376,9 +49775,72 @@ usb:v18ECp3299* usb:v18ECp3366* ID_MODEL_FROM_DATABASE=Bresser Biolux NV +usb:v18F8* + ID_VENDOR_FROM_DATABASE=[Maxxter] + +usb:v18F8p0F99* + ID_MODEL_FROM_DATABASE=Optical gaming mouse + +usb:v18FB* + ID_VENDOR_FROM_DATABASE=Scriptel Corporation + +usb:v18FBp01C0* + ID_MODEL_FROM_DATABASE=ST1501-STN + +usb:v18FBp01C1* + ID_MODEL_FROM_DATABASE=ST1526-STN + +usb:v18FBp01C2* + ID_MODEL_FROM_DATABASE=ST1501-PYJ + +usb:v18FBp01C3* + ID_MODEL_FROM_DATABASE=ST1501B-PYJ + +usb:v18FBp01C4* + ID_MODEL_FROM_DATABASE=ST1501-PUN + +usb:v18FBp01C5* + ID_MODEL_FROM_DATABASE=ST1401-STN + +usb:v18FBp01C7* + ID_MODEL_FROM_DATABASE=ST1526-PYJ + +usb:v18FBp01C8* + ID_MODEL_FROM_DATABASE=ST1501-ECA + +usb:v18FBp01C9* + ID_MODEL_FROM_DATABASE=ST1476-STN + +usb:v18FBp01CB* + ID_MODEL_FROM_DATABASE=ST1571-STN + +usb:v18FBp0200* + ID_MODEL_FROM_DATABASE=ST1500 + +usb:v18FBp0201* + ID_MODEL_FROM_DATABASE=ST1550 + +usb:v18FBp0202* + ID_MODEL_FROM_DATABASE=ST1525 + +usb:v18FBp0204* + ID_MODEL_FROM_DATABASE=ST1400 + +usb:v18FBp0206* + ID_MODEL_FROM_DATABASE=ST1475 + +usb:v18FBp0207* + ID_MODEL_FROM_DATABASE=ST1570 + usb:v18FD* ID_VENDOR_FROM_DATABASE=FineArch Inc. +usb:v1901* + ID_VENDOR_FROM_DATABASE=GE Healthcare + +usb:v1901p0015* + ID_MODEL_FROM_DATABASE=Nemo Tracker + usb:v1908* ID_VENDOR_FROM_DATABASE=GEMBIRD @@ -49409,6 +49871,12 @@ usb:v1915p2235* usb:v1915p2236* ID_MODEL_FROM_DATABASE=Linksys WUSB11 v3.0 802.11b Adapter [Intersil PRISM 3] +usb:v191C* + ID_VENDOR_FROM_DATABASE=Innovative Technology LTD + +usb:v191Cp4104* + ID_MODEL_FROM_DATABASE=Banknote validator NV-150 + usb:v1923* ID_VENDOR_FROM_DATABASE=FitLinxx @@ -49535,6 +50003,12 @@ usb:v1934p0702* usb:v1934p5168* ID_MODEL_FROM_DATABASE=F71610A or F71612A Consumer Infrared Receiver/Transceiver +usb:v1938* + ID_VENDOR_FROM_DATABASE=Meinberg Funkuhren GmbH & Co. KG + +usb:v1938p0501* + ID_MODEL_FROM_DATABASE=TCR51USB IRIG Time Code Reader + usb:v1941* ID_VENDOR_FROM_DATABASE=Dream Link @@ -51309,19 +51783,19 @@ usb:v1D50* ID_VENDOR_FROM_DATABASE=OpenMoko, Inc. usb:v1D50p1DB5* - ID_MODEL_FROM_DATABASE=IDBG DFU + ID_MODEL_FROM_DATABASE=IDBG (DFU) usb:v1D50p1DB6* ID_MODEL_FROM_DATABASE=IDBG usb:v1D50p5117* - ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner kernel usbnet (g_ether, CDC Ethernet) Mode + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner kernel usbnet (g_ether, CDC Ethernet) mode usb:v1D50p5118* - ID_MODEL_FROM_DATABASE=Debug Board (FT2232D) for Neo1973/FreeRunner + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner Debug board (V2+) usb:v1D50p5119* - ID_MODEL_FROM_DATABASE=GTA01/GTA02 U-Boot Bootloader + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner u-boot cdc_acm serial port usb:v1D50p511A* ID_MODEL_FROM_DATABASE=HXD8 u-boot usbtty CDC ACM Mode @@ -51336,31 +51810,34 @@ usb:v1D50p511D* ID_MODEL_FROM_DATABASE=QT2410 u-boot usbtty CDC ACM mode usb:v1D50p5120* - ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner u-boot generic serial mode + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner u-boot usbtty generic serial usb:v1D50p5121* ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner kernel mass storage (g_storage) mode usb:v1D50p5122* - ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner kernel usbnet (g_ether, RNDIS) mode + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner kernel cdc_ether USB network usb:v1D50p5123* - ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner internal Bluetooth CSR4 module + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner internal USB CSR4 module usb:v1D50p5124* ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner Bluetooth Device ID service +usb:v1D50p5300* + ID_MODEL_FROM_DATABASE=Rockbox + usb:v1D50p6000* ID_MODEL_FROM_DATABASE=Ubertooth Zero usb:v1D50p6001* - ID_MODEL_FROM_DATABASE=Ubertooth Zero DFU + ID_MODEL_FROM_DATABASE=Ubertooth Zero (DFU) usb:v1D50p6002* ID_MODEL_FROM_DATABASE=Ubertooth One usb:v1D50p6003* - ID_MODEL_FROM_DATABASE=Ubertooth One DFU + ID_MODEL_FROM_DATABASE=Ubertooth One (DFU) usb:v1D50p6004* ID_MODEL_FROM_DATABASE=LeoLipo @@ -51380,26 +51857,620 @@ usb:v1D50p6008* usb:v1D50p6009* ID_MODEL_FROM_DATABASE=Adjacent Reality Tracker +usb:v1D50p600A* + ID_MODEL_FROM_DATABASE=AVR Programmer + +usb:v1D50p600B* + ID_MODEL_FROM_DATABASE=Hypna Go Go + +usb:v1D50p600C* + ID_MODEL_FROM_DATABASE=CatNip LPC1343 development board + +usb:v1D50p600D* + ID_MODEL_FROM_DATABASE=Enhanced RoboBrrd Brain board + +usb:v1D50p600E* + ID_MODEL_FROM_DATABASE=OpenRISC Ordb2a-ep4ce22 development board + +usb:v1D50p600F* + ID_MODEL_FROM_DATABASE=Paparazzi Lisa/M (DFU) + +usb:v1D50p6010* + ID_MODEL_FROM_DATABASE=OpenPipe: OSHW Bagpipes MIDI controller + +usb:v1D50p6011* + ID_MODEL_FROM_DATABASE=LeoLipo (DFU) + +usb:v1D50p6012* + ID_MODEL_FROM_DATABASE=Universal C64 Cartridge + +usb:v1D50p6013* + ID_MODEL_FROM_DATABASE=DiscFerret magnetic disc analyser (bootloader) + +usb:v1D50p6014* + ID_MODEL_FROM_DATABASE=DiscFerret magnetic disc analyser + +usb:v1D50p6015* + ID_MODEL_FROM_DATABASE=Smoothieboard + +usb:v1D50p6016* + ID_MODEL_FROM_DATABASE=phInterface + +usb:v1D50p6017* + ID_MODEL_FROM_DATABASE=Black Magic Debug Probe (DFU) + +usb:v1D50p6018* + ID_MODEL_FROM_DATABASE=Black Magic Debug Probe (Application) + +usb:v1D50p6019* + ID_MODEL_FROM_DATABASE=4pi 5 axis motion controller + +usb:v1D50p601A* + ID_MODEL_FROM_DATABASE=Paparazzi Lisa/M + +usb:v1D50p601B* + ID_MODEL_FROM_DATABASE=IST-2 chronograph for bullet speeds + +usb:v1D50p601C* + ID_MODEL_FROM_DATABASE=EPOSMote II + +usb:v1D50p601E* + ID_MODEL_FROM_DATABASE=5x5 STM32 prototyping board + +usb:v1D50p601F* + ID_MODEL_FROM_DATABASE=uNSF + +usb:v1D50p6020* + ID_MODEL_FROM_DATABASE=Toad3 + +usb:v1D50p6021* + ID_MODEL_FROM_DATABASE=AlphaSphere + +usb:v1D50p6022* + ID_MODEL_FROM_DATABASE=LightPack + +usb:v1D50p6023* + ID_MODEL_FROM_DATABASE=Pixelkit + +usb:v1D50p6024* + ID_MODEL_FROM_DATABASE=Illucia + +usb:v1D50p6025* + ID_MODEL_FROM_DATABASE=Keyglove (HID) + +usb:v1D50p6027* + ID_MODEL_FROM_DATABASE=Key64 Keyboard + usb:v1D50p6028* ID_MODEL_FROM_DATABASE=Teensy 2.0 Development Board [ErgoDox Keyboard] +usb:v1D50p602A* + ID_MODEL_FROM_DATABASE=Marlin 2.0 (Mass Storage) + usb:v1D50p602B* ID_MODEL_FROM_DATABASE=FPGALink +usb:v1D50p602C* + ID_MODEL_FROM_DATABASE=5nes5snes (5x8) + +usb:v1D50p602D* + ID_MODEL_FROM_DATABASE=5nes5snes (4x12) + +usb:v1D50p602E* + ID_MODEL_FROM_DATABASE=Flexibity + +usb:v1D50p602F* + ID_MODEL_FROM_DATABASE=K-copter + +usb:v1D50p6030* + ID_MODEL_FROM_DATABASE=USB-oscope + +usb:v1D50p6031* + ID_MODEL_FROM_DATABASE=Handmade GSM GPS tracker + +usb:v1D50p6033* + ID_MODEL_FROM_DATABASE=frobiac / adnw keyboard + +usb:v1D50p6034* + ID_MODEL_FROM_DATABASE=Tiflomag Ergo 2 + +usb:v1D50p6035* + ID_MODEL_FROM_DATABASE=FreeLaserTag Gun + +usb:v1D50p6036* + ID_MODEL_FROM_DATABASE=FreeLaserTag Big Brother + +usb:v1D50p6037* + ID_MODEL_FROM_DATABASE=FreeLaserTag Node + +usb:v1D50p6038* + ID_MODEL_FROM_DATABASE=Monaka + +usb:v1D50p6039* + ID_MODEL_FROM_DATABASE=eXtreme Feedback Device + +usb:v1D50p603A* + ID_MODEL_FROM_DATABASE=TiLDA + +usb:v1D50p603B* + ID_MODEL_FROM_DATABASE=Raspiface + +usb:v1D50p603C* + ID_MODEL_FROM_DATABASE=Paparazzi (bootloader) + +usb:v1D50p603D* + ID_MODEL_FROM_DATABASE=Paparazzi (Serial) + +usb:v1D50p603E* + ID_MODEL_FROM_DATABASE=Paparazzi (Mass Storage) + +usb:v1D50p603F* + ID_MODEL_FROM_DATABASE=airGuitar + +usb:v1D50p6040* + ID_MODEL_FROM_DATABASE=moco + +usb:v1D50p6041* + ID_MODEL_FROM_DATABASE=AlphaSphere (bootloader) + +usb:v1D50p6042* + ID_MODEL_FROM_DATABASE=Dspace robot controller + +usb:v1D50p6043* + ID_MODEL_FROM_DATABASE=pc-power + +usb:v1D50p6044* + ID_MODEL_FROM_DATABASE=open-usb-can (DFU) + +usb:v1D50p6045* + ID_MODEL_FROM_DATABASE=open-usb-can + +usb:v1D50p6046* + ID_MODEL_FROM_DATABASE=mimus-weigand + +usb:v1D50p6047* + ID_MODEL_FROM_DATABASE=RfCat Chronos Dongle + +usb:v1D50p6048* + ID_MODEL_FROM_DATABASE=RfCat Dons Dongle + +usb:v1D50p6049* + ID_MODEL_FROM_DATABASE=RfCat Chronos bootloader + +usb:v1D50p604A* + ID_MODEL_FROM_DATABASE=RfCat Dons bootloader + usb:v1D50p604B* ID_MODEL_FROM_DATABASE=HackRF Jawbreaker Software-Defined Radio +usb:v1D50p604C* + ID_MODEL_FROM_DATABASE=Makibox A6 + +usb:v1D50p604D* + ID_MODEL_FROM_DATABASE=Paella Pulse height analyzer + +usb:v1D50p604E* + ID_MODEL_FROM_DATABASE=Miniscope v2b + +usb:v1D50p604F* + ID_MODEL_FROM_DATABASE=Miniscope v2c + +usb:v1D50p6050* + ID_MODEL_FROM_DATABASE=GoodFET + +usb:v1D50p6051* + ID_MODEL_FROM_DATABASE=pinocc.io + +usb:v1D50p6052* + ID_MODEL_FROM_DATABASE=APB Team Robotic Development Board + usb:v1D50p6053* ID_MODEL_FROM_DATABASE=Darkgame Controller +usb:v1D50p6054* + ID_MODEL_FROM_DATABASE=Satlab/AAUSAT3 BlueBox + +usb:v1D50p6056* + ID_MODEL_FROM_DATABASE=The Glitch + +usb:v1D50p605B* + ID_MODEL_FROM_DATABASE=RfCat YARD Stick One + +usb:v1D50p605C* + ID_MODEL_FROM_DATABASE=YARD Stick One bootloader + +usb:v1D50p605D* + ID_MODEL_FROM_DATABASE=Funky Sensor v2 + +usb:v1D50p605E* + ID_MODEL_FROM_DATABASE=Blinkiverse Analog LED Fader + +usb:v1D50p605F* + ID_MODEL_FROM_DATABASE=Small DIP package Cypress FX2 + +usb:v1D50p6060* + ID_MODEL_FROM_DATABASE=Data logger using the Cypress FX2 + +usb:v1D50p6061* + ID_MODEL_FROM_DATABASE=Power Manager + +usb:v1D50p6063* + ID_MODEL_FROM_DATABASE=CPC FPGA + +usb:v1D50p6064* + ID_MODEL_FROM_DATABASE=CPC FPGA (DFU) + +usb:v1D50p6065* + ID_MODEL_FROM_DATABASE=CPC FPGA (Serial) + +usb:v1D50p6066* + ID_MODEL_FROM_DATABASE=Nuand BladeRF + +usb:v1D50p6067* + ID_MODEL_FROM_DATABASE=Orbotron 9000 (Serial) + +usb:v1D50p6068* + ID_MODEL_FROM_DATABASE=Orbotron 9000 (HID) + +usb:v1D50p6069* + ID_MODEL_FROM_DATABASE=xser (DFU) + +usb:v1D50p606A* + ID_MODEL_FROM_DATABASE=xser (legacy) + +usb:v1D50p606B* + ID_MODEL_FROM_DATABASE=S08-245, urJtag compatible firmware for S08JS + +usb:v1D50p606C* + ID_MODEL_FROM_DATABASE=Blinkytape full-color light tape + +usb:v1D50p606D* + ID_MODEL_FROM_DATABASE=TinyG open source motion controller + +usb:v1D50p606E* + ID_MODEL_FROM_DATABASE=Reefangel Evolution 1.0 + +usb:v1D50p6070* + ID_MODEL_FROM_DATABASE=Open Pinball Project + +usb:v1D50p6071* + ID_MODEL_FROM_DATABASE=The Glitch HID + +usb:v1D50p6072* + ID_MODEL_FROM_DATABASE=The Glitch Disk + +usb:v1D50p6073* + ID_MODEL_FROM_DATABASE=The Glitch Serial + +usb:v1D50p6074* + ID_MODEL_FROM_DATABASE=The Glitch MIDI + +usb:v1D50p6075* + ID_MODEL_FROM_DATABASE=The Glitch RawHID + +usb:v1D50p6076* + ID_MODEL_FROM_DATABASE=Vultureprog BIOS chip programmer + +usb:v1D50p6077* + ID_MODEL_FROM_DATABASE=PaintDuino + +usb:v1D50p6078* + ID_MODEL_FROM_DATABASE=DTplug + +usb:v1D50p607A* + ID_MODEL_FROM_DATABASE=Fadecandy + +usb:v1D50p607B* + ID_MODEL_FROM_DATABASE=RCDongle for IR remote control + +usb:v1D50p607C* + ID_MODEL_FROM_DATABASE=OpenVizsla USB sniffer/analyzer + +usb:v1D50p607D* + ID_MODEL_FROM_DATABASE=Spark Core Arduino-compatible board with WiFi + +usb:v1D50p607F* + ID_MODEL_FROM_DATABASE=Spark Core Arduino-compatible board with WiFi (bootloader) + +usb:v1D50p6080* + ID_MODEL_FROM_DATABASE=arcin arcade controller + +usb:v1D50p6081* + ID_MODEL_FROM_DATABASE=BladeRF (bootloader) + +usb:v1D50p6082* + ID_MODEL_FROM_DATABASE=Facecandy (DFU) + +usb:v1D50p6083* + ID_MODEL_FROM_DATABASE=LightUp (bootloader) + +usb:v1D50p6084* + ID_MODEL_FROM_DATABASE=arcin arcade controller (DFU) + +usb:v1D50p6085* + ID_MODEL_FROM_DATABASE=IRKit for controlloing home electronics from iOS devices + +usb:v1D50p6086* + ID_MODEL_FROM_DATABASE=OneRNG entropy device + +usb:v1D50p6088* + ID_MODEL_FROM_DATABASE=picp PIC16F145x based PIC16F145x programmer + usb:v1D50p6089* - ID_MODEL_FROM_DATABASE=Great Scott Gadgets HackRF One + ID_MODEL_FROM_DATABASE=Great Scott Gadgets HackRF One SDR + +usb:v1D50p608A* + ID_MODEL_FROM_DATABASE=BLEduino + +usb:v1D50p608B* + ID_MODEL_FROM_DATABASE=Loctronix ASR-2300 SDR/motion sensing module + +usb:v1D50p608C* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p608D* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p608E* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p608F* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6090* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6091* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6092* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6093* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6094* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6095* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6096* + ID_MODEL_FROM_DATABASE=LightUp (sketch) + +usb:v1D50p6097* + ID_MODEL_FROM_DATABASE=Tessel JavaScript enabled Microcontroller with built-in WiFi + +usb:v1D50p6098* + ID_MODEL_FROM_DATABASE=RFIDler + +usb:v1D50p6099* + ID_MODEL_FROM_DATABASE=RASDR Radio Astronomy SDR Rx Interface + +usb:v1D50p609A* + ID_MODEL_FROM_DATABASE=RASDR Radio Astronomy SDR Tx Interface + +usb:v1D50p609B* + ID_MODEL_FROM_DATABASE=RASDR Radio Astronomy SDR (bootloader) + +usb:v1D50p609C* + ID_MODEL_FROM_DATABASE=antiAFK keyboard + +usb:v1D50p609D* + ID_MODEL_FROM_DATABASE=PIC16F145x bootloader + +usb:v1D50p609E* + ID_MODEL_FROM_DATABASE=Clyde Lamp by Fabule (bootloader) + +usb:v1D50p609F* + ID_MODEL_FROM_DATABASE=Clyde Lamp by Fabule (sketch) + +usb:v1D50p60A0* + ID_MODEL_FROM_DATABASE=Smoothiepanel robotic control interface usb:v1D50p60A1* ID_MODEL_FROM_DATABASE=Airspy +usb:v1D50p60A2* + ID_MODEL_FROM_DATABASE=barebox (DFU) + +usb:v1D50p60A3* + ID_MODEL_FROM_DATABASE=keyboard (bootloader) + +usb:v1D50p60A4* + ID_MODEL_FROM_DATABASE=Papilio Duo (AVR) + +usb:v1D50p60A5* + ID_MODEL_FROM_DATABASE=Papilio Duo (FPGA) + +usb:v1D50p60A6* + ID_MODEL_FROM_DATABASE=HydraBus/HydraNFC (bootloader) + +usb:v1D50p60A7* + ID_MODEL_FROM_DATABASE=HydraBus/HydraNFC + +usb:v1D50p60A8* + ID_MODEL_FROM_DATABASE=reserved + +usb:v1D50p60A9* + ID_MODEL_FROM_DATABASE=Blinky Light Controller (DFU) + +usb:v1D50p60AA* + ID_MODEL_FROM_DATABASE=Blinky Light Controller + +usb:v1D50p60AB* + ID_MODEL_FROM_DATABASE=AllPixel + +usb:v1D50p60AC* + ID_MODEL_FROM_DATABASE=OpenBLT generic microcontroller (bootloader) + +usb:v1D50p60B0* + ID_MODEL_FROM_DATABASE=Waterott Arduino based Clock (caterina bootloader) + +usb:v1D50p60B1* + ID_MODEL_FROM_DATABASE=Drinkbot (processing) + +usb:v1D50p60B2* + ID_MODEL_FROM_DATABASE=Drinkbot (OTG-tablet support) + +usb:v1D50p60B3* + ID_MODEL_FROM_DATABASE=calc.pw password generator device (standard) + +usb:v1D50p60B4* + ID_MODEL_FROM_DATABASE=calc.pw password generator device (enhanced) + +usb:v1D50p60B5* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (FX2) - Unconfigured device + +usb:v1D50p60B6* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (FX2) - Firmware load/upgrade + +usb:v1D50p60B7* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (FX2) - HDMI/DVI Capture Device + +usb:v1D50p60B8* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (Soft+UTMI) - Unconfigured device + +usb:v1D50p60B9* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (Soft+UTMI) - Firmware upgrade + +usb:v1D50p60BA* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (Soft+UTMI) - HDMI/DVI Capture Device + +usb:v1D50p60BC* + ID_MODEL_FROM_DATABASE=Simple CC25xx programmer / serial board + +usb:v1D50p60BD* + ID_MODEL_FROM_DATABASE=Open Source control interface for multimedia applications + +usb:v1D50p60BE* + ID_MODEL_FROM_DATABASE=Pixelmatix Aurora (bootloader) + +usb:v1D50p60BF* + ID_MODEL_FROM_DATABASE=Pixelmatix Aurora + +usb:v1D50p60C1* + ID_MODEL_FROM_DATABASE=BrewBit Model-T pOSHW temperature controller for homebrewers (bootloader) + +usb:v1D50p60C2* + ID_MODEL_FROM_DATABASE=BrewBit Model-T pOSHW temperature controller for homebrewers + +usb:v1D50p60C3* + ID_MODEL_FROM_DATABASE=X Antenna Tracker arduino board + +usb:v1D50p60C6* + ID_MODEL_FROM_DATABASE=USBtrng hardware random number generator + +usb:v1D50p60C7* + ID_MODEL_FROM_DATABASE=Zubax GNSS positioning module for light UAV systems + +usb:v1D50p60C8* + ID_MODEL_FROM_DATABASE=Xlink data transfer and control system for Commodore C64 + +usb:v1D50p60C9* + ID_MODEL_FROM_DATABASE=random number generator + +usb:v1D50p60CA* + ID_MODEL_FROM_DATABASE=FinalKey password manager + +usb:v1D50p60CB* + ID_MODEL_FROM_DATABASE=PteroDAQ Data Acquisition on FRDM-KL25Z and future boards + +usb:v1D50p60CC* + ID_MODEL_FROM_DATABASE=LamDiNao + +usb:v1D50p60DE* + ID_MODEL_FROM_DATABASE=Cryptech.is random number generator + +usb:v1D50p60DF* + ID_MODEL_FROM_DATABASE=Numato Opsis HDMI2USB board (unconfigured) + +usb:v1D50p60E0* + ID_MODEL_FROM_DATABASE=Numato Opsis HDMI2USB board (JTAG Programming Mode) + +usb:v1D50p60E1* + ID_MODEL_FROM_DATABASE=Numato Opsis HDMI2USB board (User Mode) + +usb:v1D50p60E2* + ID_MODEL_FROM_DATABASE=Osmocom SIMtrace 2 (DFU) + +usb:v1D50p60E3* + ID_MODEL_FROM_DATABASE=Osmocom SIMtrace 2 + +usb:v1D50p60E4* + ID_MODEL_FROM_DATABASE=3D printed racing game - (Catalina CDC bootloader) + +usb:v1D50p60E5* + ID_MODEL_FROM_DATABASE=3D printed racing game + +usb:v1D50p60E6* + ID_MODEL_FROM_DATABASE=replacement for GoodFET/FaceDancer - GreatFet + +usb:v1D50p60E7* + ID_MODEL_FROM_DATABASE=replacement for GoodFET/FaceDancer - GreatFet target + +usb:v1D50p60E8* + ID_MODEL_FROM_DATABASE=Alpen Clack keyboard + +usb:v1D50p60E9* + ID_MODEL_FROM_DATABASE=keyman64 keyboard itercepter + +usb:v1D50p60EA* + ID_MODEL_FROM_DATABASE=Wiggleport FPGA-based I/O board + +usb:v1D50p60EC* + ID_MODEL_FROM_DATABASE=Duet 3D Printer Controller + +usb:v1D50p60F0* + ID_MODEL_FROM_DATABASE=UDAD-T1 data aquisition device (boot) + +usb:v1D50p60F1* + ID_MODEL_FROM_DATABASE=UDAD-T1 data aquisition device + +usb:v1D50p60F2* + ID_MODEL_FROM_DATABASE=UDAD-T2 data aquisition device (boot) + +usb:v1D50p60F3* + ID_MODEL_FROM_DATABASE=UDAD-T2 data aquisition device + +usb:v1D50p60F4* + ID_MODEL_FROM_DATABASE=Uniti ARC motor controller + +usb:v1D50p60F5* + ID_MODEL_FROM_DATABASE=EightByEight Blinky Badge (DFU) + +usb:v1D50p60F6* + ID_MODEL_FROM_DATABASE=EightByEight Blinky Badge + +usb:v1D50p60F7* + ID_MODEL_FROM_DATABASE=cardio NFC/RFID card reader (bootloader) + +usb:v1D50p60F8* + ID_MODEL_FROM_DATABASE=cardio NFC/RFID card reader + +usb:v1D50p60FC* + ID_MODEL_FROM_DATABASE=OnlyKey Two-factor Authentication and Password Solution + +usb:v1D50p6100* + ID_MODEL_FROM_DATABASE=overlay64 video overlay module + +usb:v1D50p6104* + ID_MODEL_FROM_DATABASE=ScopeFun open source instrumentation + +usb:v1D50p6108* + ID_MODEL_FROM_DATABASE=Myriad-RF LimeSDR + +usb:v1D50p610C* + ID_MODEL_FROM_DATABASE=Magic Keys (boot) + +usb:v1D50p610D* + ID_MODEL_FROM_DATABASE=Magic Keys + +usb:v1D50p8085* + ID_MODEL_FROM_DATABASE=Box0 (box0-v5) + usb:v1D50pCC15* - ID_MODEL_FROM_DATABASE=CCCAMP2015 rad1o badge + ID_MODEL_FROM_DATABASE=rad1o badge for CCC congress 2015 usb:v1D57* ID_VENDOR_FROM_DATABASE=Xenta @@ -53531,6 +54602,12 @@ usb:v2A45p200C* usb:v2A45p2012* ID_MODEL_FROM_DATABASE=MX Phone (MTP & ACM) +usb:v2B24* + ID_VENDOR_FROM_DATABASE=KeepKey LLC + +usb:v2B24p0001* + ID_MODEL_FROM_DATABASE=Bitcoin hardware wallet + usb:v2C02* ID_VENDOR_FROM_DATABASE=Planex Communications -- cgit v1.2.3-54-g00ecf From a1e2ef7ec912902d8142e7cb5830cbfb47dba86c Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Thu, 3 Nov 2016 13:16:42 -0400 Subject: Revert "sd-bus: use PRIu64 instead of casting" (#4556) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 75ead2b753cb9586f3f208326446081baab70da1. Follow up for #4546: > @@ -848,8 +848,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { if (k->src_id == KDBUS_SRC_ID_KERNEL) bus_message_set_sender_driver(bus, m); else { - xsprintf(m->sender_buffer, ":1.%llu", - (unsigned long long)k->src_id); + xsprintf(m->sender_buffer, ":1.%"PRIu64, k->src_id); This produces: src/libsystemd/sd-bus/bus-kernel.c: In function ‘bus_kernel_make_message’: src/libsystemd/sd-bus/bus-kernel.c:851:44: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 4 has type ‘__u64 {aka long long unsigned int}’ [-Wformat=] xsprintf(m->sender_buffer, ":1.%"PRIu64, k->src_id); ^ --- src/libsystemd/sd-bus/bus-kernel.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index ad468572f3..59398b841d 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -848,7 +848,8 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { if (k->src_id == KDBUS_SRC_ID_KERNEL) bus_message_set_sender_driver(bus, m); else { - xsprintf(m->sender_buffer, ":1.%"PRIu64, k->src_id); + xsprintf(m->sender_buffer, ":1.%llu", + (unsigned long long)k->src_id); m->sender = m->creds.unique_name = m->sender_buffer; } @@ -859,7 +860,8 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { else if (k->dst_id == KDBUS_DST_ID_NAME) m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */ else { - xsprintf(m->destination_buffer, ":1.%"PRIu64, k->dst_id); + xsprintf(m->destination_buffer, ":1.%llu", + (unsigned long long)k->dst_id); m->destination = m->destination_buffer; } -- cgit v1.2.3-54-g00ecf From cd4a5eff38f32bea5f1815f203972a6f1199a25b Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Thu, 10 Nov 2016 05:33:13 +0100 Subject: core: don't use the unified hierarchy for the systemd cgroup yet (#4628) Too many things don't get along with the unified hierarchy yet: * https://github.com/opencontainers/runc/issues/1175 * https://github.com/docker/docker/issues/28109 * https://github.com/lxc/lxc/issues/1280 So revert the default to the legacy hierarchy for now. Developers of the above software can opt into the unified hierarchy with "systemd.legacy_systemd_cgroup_controller=0". --- src/basic/cgroup-util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index cede835920..134e6e3664 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -2423,10 +2423,10 @@ bool cg_is_unified_systemd_controller_wanted(void) { r = get_proc_cmdline_key("systemd.legacy_systemd_cgroup_controller=", &value); if (r < 0) - return true; + return false; if (r == 0) - wanted = true; + wanted = false; else wanted = parse_boolean(value) <= 0; } -- cgit v1.2.3-54-g00ecf From a839ee75d85c4f1d3183b8955c62d54f6a8dec88 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Fri, 11 Nov 2016 10:54:54 -0500 Subject: basic/virt: fix userns check on CONFIG_USER_NS=n kernel (#4651) ENOENT should be treated as "false", but because of the broken errno check it was treated as an error. So ConditionVirtualization=user-namespaces probably returned the correct answer, but only by accident. Fixes #4608. --- src/basic/virt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/virt.c b/src/basic/virt.c index 69b0f96183..d8d57381ad 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -496,7 +496,7 @@ static int userns_has_mapping(const char *name) { f = fopen(name, "re"); if (!f) { log_debug_errno(errno, "Failed to open %s: %m", name); - return errno == -ENOENT ? false : -errno; + return errno == ENOENT ? false : -errno; } n = getline(&buf, &n_allocated, f); -- cgit v1.2.3-54-g00ecf From 2eaef25e43b8df349906b50ff95c4df383b7ba5a Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 12 Nov 2016 10:05:24 -0500 Subject: build-sys: do not install ctrl-alt-del.target symlink twice It was a harmless but pointless duplication. Fixes #4655. Note: in general we try to install as little as possible in /etc/systemd/{system,user}. We only install .wants links there for units which are "user configurable", i.e. which have an [Install] section. Most our units and aliases are not user configurable, do not have an [Install] section, and must be symlinked statically during installation. A few units do have an [Install] section, and are enabled through symlinks in /etc/ during installation using GENERAL_ALIASES. It *would* be possible to not create those symlinks, and instead require 'systemctl preset' to be invoked after installation, but GENERAL_ALIASES works well enough. --- Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index f7652c2346..35ec60f736 100644 --- a/Makefile.am +++ b/Makefile.am @@ -633,7 +633,6 @@ EXTRA_DIST += \ units/halt-local.service.in GENERAL_ALIASES += \ - $(systemunitdir)/reboot.target $(pkgsysconfdir)/system/ctrl-alt-del.target \ $(systemunitdir)/machines.target $(pkgsysconfdir)/system/multi-user.target.wants/machines.target dist_doc_DATA = \ -- cgit v1.2.3-54-g00ecf From 49e5f27c53a1a1716a8e660fb27cfbfe8ea67de5 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Sun, 27 Nov 2016 17:05:39 -0500 Subject: device: Avoid calling unit_free(NULL) in device setup logic (#4748) Since a581e45ae8f9bb5c, there's a few function calls to unit_new_for_name which will unit_free on failure. Prior to this commit, a failure would result in calling unit_free with a NULL unit, and hit an assertion failure, seen at least via device_setup_unit: Assertion 'u' failed at src/core/unit.c:519, function unit_free(). Aborting. Fixes #4747 https://bugs.archlinux.org/task/51950 --- src/core/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/device.c b/src/core/device.c index bd87a447cd..4b9e84aeb6 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -365,7 +365,7 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa fail: log_unit_warning_errno(u, r, "Failed to set up device unit: %m"); - if (delete) + if (delete && u) unit_free(u); return r; -- cgit v1.2.3-54-g00ecf From d9454c44bc1854a291f6c37dfce378c9b6067d0b Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Wed, 9 Nov 2016 08:00:26 -0500 Subject: disable RestrictAddressFamilies on i686 Shit's broke, yo. https://github.com/systemd/systemd/issues/4575 --- src/core/execute.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/execute.c b/src/core/execute.c index f13ca30395..85ee82c3e1 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1254,6 +1254,10 @@ static int apply_address_families(const Unit* u, const ExecContext *c) { Iterator i; int r; +#if defined(__i386__) + return 0; +#endif + assert(c); if (skip_seccomp_unavailable(u, "RestrictAddressFamilies=")) -- cgit v1.2.3-54-g00ecf From 39d73c22eb6c47a01c97b2378d252dc498de4ff6 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Wed, 9 Nov 2016 11:14:03 -0500 Subject: Revert "nspawn: try to bind mount resolved's resolv.conf snippet into the container" This reverts commit 3539724c26a1b2b00c4eb3c004b635a4b8647de6. --- src/nspawn/nspawn.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index c56af6e6f4..dea54c70b4 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1309,35 +1309,24 @@ static int setup_resolv_conf(const char *dest) { /* Fix resolv.conf, if possible */ where = prefix_roota(dest, "/etc/resolv.conf"); - if (access("/usr/lib/systemd/resolv.conf", F_OK) >= 0) { - /* resolved is enabled on the host. In this, case bind mount its static resolv.conf file into the - * container, so that the container can use the host's resolver. Given that network namespacing is - * disabled it's only natural of the container also uses the host's resolver. It also has the big - * advantage that the container will be able to follow the host's DNS server configuration changes - * transparently. */ - - r = mount_verbose(LOG_WARNING, "/usr/lib/systemd/resolv.conf", where, NULL, MS_BIND, NULL); - if (r >= 0) - return mount_verbose(LOG_ERR, NULL, where, NULL, - MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); - } - - /* If that didn't work, let's copy the file */ r = copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW, 0644, 0); if (r < 0) { - /* If the file already exists as symlink, let's suppress the warning, under the assumption that - * resolved or something similar runs inside and the symlink points there. + /* If the file already exists as symlink, let's + * suppress the warning, under the assumption that + * resolved or something similar runs inside and the + * symlink points there. * - * If the disk image is read-only, there's also no point in complaining. + * If the disk image is read-only, there's also no + * point in complaining. */ log_full_errno(IN_SET(r, -ELOOP, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, - "Failed to copy /etc/resolv.conf to %s, ignoring: %m", where); + "Failed to copy /etc/resolv.conf to %s: %m", where); return 0; } r = userns_lchown(where, 0, 0); if (r < 0) - log_warning_errno(r, "Failed to chown /etc/resolv.conf, ignoring: %m"); + log_warning_errno(r, "Failed to chown /etc/resolv.conf: %m"); return 0; } -- cgit v1.2.3-54-g00ecf From 6ac128c84e425a3048f7eee0ec00b9494b34cb63 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 25 May 2016 12:19:20 -0400 Subject: FSDG: man/: Refer to the operating system as GNU/Linux. This is not a blind replacement of "Linux" with "GNU/Linux". In some cases, "Linux" is (correctly) used to refer to just the kernel. In others, it is in a string for which code must also be adjusted; these instances are not included in this commit. --- man/daemon.xml | 4 ++-- man/sd-bus-errors.xml | 2 +- man/sd_bus_error_add_map.xml | 2 +- man/systemd.xml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/man/daemon.xml b/man/daemon.xml index 485c66225e..a649749683 100644 --- a/man/daemon.xml +++ b/man/daemon.xml @@ -168,7 +168,7 @@ New-Style Daemons - Modern services for Linux should be implemented as + Modern services for GNU/Linux should be implemented as new-style daemons. This makes it easier to supervise and control them at runtime and simplifies their implementation. @@ -309,7 +309,7 @@ as detailed in the LSB Linux Standard Base Core Specification. This method of - activation is supported ubiquitously on Linux init systems, both + activation is supported ubiquitously on GNU/Linux init systems, both old-style and new-style systems. Among other issues, SysV init scripts have the disadvantage of involving shell scripts in the boot process. New-style init systems generally employ updated diff --git a/man/sd-bus-errors.xml b/man/sd-bus-errors.xml index 055af7a682..d2b81f4e4a 100644 --- a/man/sd-bus-errors.xml +++ b/man/sd-bus-errors.xml @@ -126,7 +126,7 @@ In addition to this list, in sd-bus, the special error namespace System.Error. is used to map - arbitrary Linux system errors (as defined by errno3) to D-Bus errors and back. For example, the error EUCLEAN is mapped to diff --git a/man/sd_bus_error_add_map.xml b/man/sd_bus_error_add_map.xml index 139bd77d8c..7dc1ef6c90 100644 --- a/man/sd_bus_error_add_map.xml +++ b/man/sd_bus_error_add_map.xml @@ -82,7 +82,7 @@ The sd_bus_error_add_map() call may be used to register additional mappings for converting D-Bus errors - to Linux errno-style errors. The mappings + to GNU/Linux errno-style errors. The mappings defined with this call are consulted by calls such as sd_bus_error_set3 or diff --git a/man/systemd.xml b/man/systemd.xml index 7f24a874ed..79d8aedbbc 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -61,7 +61,7 @@ Description - systemd is a system and service manager for Linux operating + systemd is a system and service manager for GNU/Linux operating systems. When run as first process on boot (as PID 1), it acts as init system that brings up and maintains userspace services. -- cgit v1.2.3-54-g00ecf From 9146dc0afb1118a988ce79a249d5e5235b7b52c8 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 25 May 2016 12:23:40 -0400 Subject: FSDG: os-release: Default to PRETTY_NAME "GNU/Linux" instead of "Linux". --- man/kernel-install.xml | 2 +- man/os-release.xml | 2 +- src/analyze/analyze.c | 2 +- src/core/main.c | 4 ++-- src/firstboot/firstboot.c | 2 +- src/kernel-install/90-loaderentry.install | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/man/kernel-install.xml b/man/kernel-install.xml index 4a8a46cef4..32e6169f63 100644 --- a/man/kernel-install.xml +++ b/man/kernel-install.xml @@ -109,7 +109,7 @@ PRETTY_NAME parameter specified in /etc/os-release or /usr/lib/os-release (if the former is - missing), or "Linux + missing), or "GNU/Linux KERNEL-VERSION", if unset. If the file initrd is found next to the linux file, the initrd will be added to diff --git a/man/os-release.xml b/man/os-release.xml index 99bbb61004..27d18749dc 100644 --- a/man/os-release.xml +++ b/man/os-release.xml @@ -210,7 +210,7 @@ suitable for presentation to the user. May or may not contain a release code name or OS version of some kind, as suitable. If not set, defaults to - PRETTY_NAME="Linux". Example: + PRETTY_NAME="GNU/Linux". Example: PRETTY_NAME="Fedora 17 (Beefy Miracle)". diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index cbf9354a7a..66830695f3 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -653,7 +653,7 @@ static int analyze_plot(sd_bus *bus) { svg("\n"); svg("%s", pretty_times); svg("%s %s (%s %s %s) %s %s", - isempty(host->os_pretty_name) ? "Linux" : host->os_pretty_name, + isempty(host->os_pretty_name) ? "GNU/Linux" : host->os_pretty_name, strempty(host->hostname), strempty(host->kernel_name), strempty(host->kernel_release), diff --git a/src/core/main.c b/src/core/main.c index 94602611a7..f07ed71b31 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1246,11 +1246,11 @@ static int status_welcome(void) { return status_printf(NULL, false, false, "\nWelcome to \x1B[%sm%s\x1B[0m!\n", isempty(ansi_color) ? "1" : ansi_color, - isempty(pretty_name) ? "Linux" : pretty_name); + isempty(pretty_name) ? "GNU/Linux" : pretty_name); else return status_printf(NULL, false, false, "\nWelcome to %s!\n", - isempty(pretty_name) ? "Linux" : pretty_name); + isempty(pretty_name) ? "GNU/Linux" : pretty_name); } static int write_container_id(void) { diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index c9e8e54ee3..83a21eaf0e 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -96,7 +96,7 @@ static void print_welcome(void) { log_warning_errno(r, "Failed to read os-release file: %m"); printf("\nWelcome to your new installation of %s!\nPlease configure a few basic system settings:\n\n", - isempty(pretty_name) ? "Linux" : pretty_name); + isempty(pretty_name) ? "GNU/Linux" : pretty_name); press_any_key(); diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install index a0bca05c9a..af9f0f9ccd 100644 --- a/src/kernel-install/90-loaderentry.install +++ b/src/kernel-install/90-loaderentry.install @@ -38,7 +38,7 @@ elif [[ -f /usr/lib/os-release ]]; then fi if ! [[ $PRETTY_NAME ]]; then - PRETTY_NAME="Linux $KERNEL_VERSION" + PRETTY_NAME="GNU/Linux $KERNEL_VERSION" fi declare -a BOOT_OPTIONS -- cgit v1.2.3-54-g00ecf From 3e3e302ae4a0f0a3da5f376febd74e5a54268e93 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 25 May 2016 12:24:56 -0400 Subject: FSDG: os-release: Default to NAME "GNU/Linux" instead of "Linux". --- man/os-release.xml | 2 +- src/journal-remote/journal-gatewayd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/man/os-release.xml b/man/os-release.xml index 27d18749dc..a88d16b171 100644 --- a/man/os-release.xml +++ b/man/os-release.xml @@ -121,7 +121,7 @@ A string identifying the operating system, without a version component, and suitable for presentation to the user. If not set, defaults to - NAME=Linux. Example: + NAME=GNU/Linux. Example: NAME=Fedora or NAME="Debian GNU/Linux". diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index 7325adee8f..6611a355d4 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -805,7 +805,7 @@ static int request_handler_machine( SD_ID128_FORMAT_VAL(mid), SD_ID128_FORMAT_VAL(bid), hostname_cleanup(hostname), - os_name ? os_name : "Linux", + os_name ? os_name : "GNU/Linux", v ? v : "bare", usage, cutoff_from, -- cgit v1.2.3-54-g00ecf From 271900c9a53eae6eefcbb7f059d979e3a126e4af Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 25 May 2016 12:28:30 -0400 Subject: FSDG: os-release: Default ID to "gnu-linux" instead of "linux". As far as I can tell, no code in this repository actually uses the ID field, so this is just a man page change. --- man/os-release.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/os-release.xml b/man/os-release.xml index a88d16b171..caf60f41a3 100644 --- a/man/os-release.xml +++ b/man/os-release.xml @@ -145,7 +145,7 @@ the operating system, excluding any version information and suitable for processing by scripts or usage in generated filenames. If not set, defaults to - ID=linux. Example: + ID=gnu-linux. Example: ID=fedora or ID=debian. -- cgit v1.2.3-54-g00ecf From 7079d34e7e79f02d63307b792108b90b89ca10e5 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 25 May 2016 12:31:20 -0400 Subject: FSDG: systemd-resolved: Default to hostname "gnu-linux" instead of "linux" --- src/resolve/resolved-manager.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 0954641c20..6630585d13 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -430,12 +430,12 @@ static int manager_watch_hostname(Manager *m) { r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname); if (r < 0) { - log_info("Defaulting to hostname 'linux'."); - m->llmnr_hostname = strdup("linux"); + log_info("Defaulting to hostname 'gnu-linux'."); + m->llmnr_hostname = strdup("gnu-linux"); if (!m->llmnr_hostname) return log_oom(); - m->mdns_hostname = strdup("linux.local"); + m->mdns_hostname = strdup("gnu-linux.local"); if (!m->mdns_hostname) return log_oom(); } else -- cgit v1.2.3-54-g00ecf From 74625a5644f634f73177aaccba6ea34f2f5e37e8 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 25 May 2016 12:32:21 -0400 Subject: FSDG: man/: Use FSDG operating systems as examples. --- man/os-release.xml | 49 +++++++++++++++++++++++++------------------------ man/systemd-nspawn.xml | 37 +++++++++++++------------------------ 2 files changed, 38 insertions(+), 48 deletions(-) diff --git a/man/os-release.xml b/man/os-release.xml index caf60f41a3..2811f434c5 100644 --- a/man/os-release.xml +++ b/man/os-release.xml @@ -122,7 +122,7 @@ without a version component, and suitable for presentation to the user. If not set, defaults to NAME=GNU/Linux. Example: - NAME=Fedora or NAME="Debian + NAME=BLAG or NAME="gNewSense GNU/Linux". @@ -133,8 +133,8 @@ version, excluding any OS name information, possibly including a release code name, and suitable for presentation to the user. This field is optional. Example: - VERSION=17 or VERSION="17 (Beefy - Miracle)". + VERSION=210k or VERSION="210k + (Spartakus)". @@ -146,8 +146,8 @@ suitable for processing by scripts or usage in generated filenames. If not set, defaults to ID=gnu-linux. Example: - ID=fedora or - ID=debian. + ID=blag or + ID=gnewsense. @@ -168,9 +168,9 @@ should be listed in order of how closely the local operating system relates to the listed ones, starting with the closest. This field is optional. Example: for an operating system with - ID=centos, an assignment of + ID=blag, an assignment of ID_LIKE="rhel fedora" would be appropriate. - For an operating system with ID=ubuntu, an + For an operating system with ID=gnewsense, an assignment of ID_LIKE=debian is appropriate. @@ -199,8 +199,8 @@ identifying the operating system version, excluding any OS name information or release code name, and suitable for processing by scripts or usage in generated filenames. This - field is optional. Example: VERSION_ID=17 - or VERSION_ID=11.04. + field is optional. Example: VERSION_ID=210k + or VERSION_ID=7.0. @@ -211,8 +211,8 @@ a release code name or OS version of some kind, as suitable. If not set, defaults to PRETTY_NAME="GNU/Linux". Example: - PRETTY_NAME="Fedora 17 (Beefy - Miracle)". + PRETTY_NAME="BLAG 210k + (Spartakus)". @@ -235,7 +235,7 @@ Common Platform Enumeration Specification as proposed by the NIST. This field is optional. Example: - CPE_NAME="cpe:/o:fedoraproject:fedora:17" + CPE_NAME="cpe:/o:blagblagblag:blag:210k" @@ -270,8 +270,8 @@ one URL shall be listed in each setting. If multiple resources need to be referenced, it is recommended to provide an online landing page linking all available resources. Examples: - HOME_URL="https://fedoraproject.org/" and - BUG_REPORT_URL="https://bugzilla.redhat.com/" + HOME_URL="https://www.blagblagblag.org/" and + BUG_REPORT_URL="https://blag.fsf.org/" @@ -346,21 +346,22 @@ recommended to prefix new fields with an OS specific name in order to avoid name clashes. Applications reading this file must ignore unknown fields. Example: - DEBIAN_BTS="debbugs://bugs.debian.org/" + DEBIAN_BTS="debbugs://bugs.gnewsense.org/"
Example - NAME=Fedora -VERSION="17 (Beefy Miracle)" -ID=fedora -VERSION_ID=17 -PRETTY_NAME="Fedora 17 (Beefy Miracle)" -ANSI_COLOR="0;34" -CPE_NAME="cpe:/o:fedoraproject:fedora:17" -HOME_URL="https://fedoraproject.org/" -BUG_REPORT_URL="https://bugzilla.redhat.com/" + NAME=Parabola +VERSION="rolling-release" +ID=parabola +ID_LIKE=arch +VERSION_ID=rolling-release +PRETTY_NAME="Parabola GNU/Linux-libre" +ANSI_COLOR="1;35" +CPE_NAME="cpe:/o:parabola:parabola:rolling-release" +HOME_URL="https://www.parabola.nu/" +BUG_REPORT_URL="https://labs.parabola.nu/" diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index f153034296..c449edee89 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -1012,46 +1012,35 @@ Examples - Download a Fedora image and start a shell in it + Build and boot a minimal BLAG distribution in a container - # machinectl pull-raw --verify=no http://ftp.halifax.rwth-aachen.de/fedora/linux/releases/24/CloudImages/x86_64/images/Fedora-Cloud-Base-24-1.2.x86_64.raw.xz -# systemd-nspawn -M Fedora-Cloud-Base-24-1.2.x86_64.raw - - This downloads an image using - machinectl1 - and opens a shell in it. - - - - Build and boot a minimal Fedora distribution in a container - - # dnf -y --releasever=23 --installroot=/srv/mycontainer --disablerepo='*' --enablerepo=fedora --enablerepo=updates install systemd passwd dnf fedora-release vim-minimal + # dnf -y --releasever=210k --installroot=/srv/mycontainer --disablerepo='*' --enablerepo=blag --enablerepo=updates install systemd passwd dnf blag-release vim-minimal # systemd-nspawn -bD /srv/mycontainer - This installs a minimal Fedora distribution into the + This installs a minimal BLAG distribution into the directory /srv/mycontainer/ and then boots an OS in a namespace container in it. - Spawn a shell in a container of a minimal Debian unstable distribution + Spawn a shell in a container of a minimal gNewSense Ucclia distribution - # debootstrap --arch=amd64 unstable ~/debian-tree/ -# systemd-nspawn -D ~/debian-tree/ + # debootstrap --arch=amd64 ucclia ~/gnewsense-tree/ +# systemd-nspawn -D ~/gnewsense-tree/ - This installs a minimal Debian unstable distribution into - the directory ~/debian-tree/ and then + This installs a minimal gNewSense unstable distribution into + the directory ~/gnewsense-tree/ and then spawns a shell in a namespace container in it. - Boot a minimal Arch Linux distribution in a container + Boot a minimal Parabola distribution in a container - # pacstrap -c -d ~/arch-tree/ base -# systemd-nspawn -bD ~/arch-tree/ + # pacstrap -c -d ~/parabola-tree/ base +# systemd-nspawn -bD ~/parabola-tree/ - This installs a minimal Arch Linux distribution into the - directory ~/arch-tree/ and then boots an OS + This installs a minimal Parabola distribution into the + directory ~/parabola-tree/ and then boots an OS in a namespace container in it. -- cgit v1.2.3-54-g00ecf From 5fb2a20a29c2cc0494d5a31e175a8e3ff0b2d3e2 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 17 Dec 2016 00:41:20 -0500 Subject: # Rename "Linux Boot Manager" -> "Systemd Boot Manager" sed -i 's|Linux Boot Manager|Systemd Boot Manager|' src/boot/bootctl.c --- src/boot/bootctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index dc11b0d9db..d53f8b2a6f 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -835,13 +835,13 @@ static int install_variables(const char *esp_path, "Failed to determine current boot order: %m"); if (first || r == 0) { - r = efi_add_boot_option(slot, "Linux Boot Manager", + r = efi_add_boot_option(slot, "Systemd Boot Manager", part, pstart, psize, uuid, path); if (r < 0) return log_error_errno(r, "Failed to create EFI Boot variable entry: %m"); - log_info("Created EFI boot entry \"Linux Boot Manager\"."); + log_info("Created EFI boot entry \"Systemd Boot Manager\"."); } return insert_into_order(slot, first); -- cgit v1.2.3-54-g00ecf