summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/virt.c5
-rw-r--r--src/basic/virt.h1
-rw-r--r--src/core/dbus-socket.c1
-rw-r--r--src/core/load-fragment-gperf.gperf.m41
-rw-r--r--src/core/main.c12
-rw-r--r--src/core/service.c1
-rw-r--r--src/core/service.h1
-rw-r--r--src/core/socket.c185
-rw-r--r--src/core/socket.h16
-rw-r--r--src/coredump/coredump.c111
-rw-r--r--src/journal/.gitignore1
-rw-r--r--src/login/logind-user.c2
-rw-r--r--src/machine/machinectl.c18
-rw-r--r--src/test/test-condition.c12
-rw-r--r--src/test/test-execute.c15
-rw-r--r--src/test/test-path-util.c3
-rw-r--r--src/test/test-process-util.c3
17 files changed, 364 insertions, 24 deletions
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,
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/main.c b/src/core/main.c
index f2adca7d2b..c46d886653 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;
@@ -1415,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);
}
@@ -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 &&
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);
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index dcc09fcc6d..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;
@@ -933,11 +1016,13 @@ 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, *core_container_cmdline = NULL;
_cleanup_free_ char *exe = NULL, *comm = NULL;
const char *context[_CONTEXT_MAX];
- struct iovec iovec[25];
+ bool proc_self_root_is_slash;
+ struct iovec iovec[27];
size_t n_iovec = 0;
uid_t owner_uid;
const char *p;
@@ -1110,6 +1195,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);
@@ -1119,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) {
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.*
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 {
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;
}
diff --git a/src/test/test-condition.c b/src/test/test-condition.c
index 987862f1c6..66003aa6bd 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) {
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index 77ef4e8b2a..1d24115b5c 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);
@@ -91,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
@@ -111,6 +122,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);
}
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);
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());
}