From 65fe9c319f91579ee336ccaeba90df3e7f252ee6 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 23 Nov 2018 01:24:34 +0900 Subject: [PATCH 1/2] sd-device-monitor: fix subsystem filter This fixes a bug introduced by 759d9f3f8d07af2940bb3783acc3985ee47adfa5. Fixes #10882. --- src/libsystemd/sd-device/device-monitor.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c index bb50257a0df..05e7ec07159 100644 --- a/src/libsystemd/sd-device/device-monitor.c +++ b/src/libsystemd/sd-device/device-monitor.c @@ -648,13 +648,12 @@ _public_ int sd_device_monitor_filter_update(sd_device_monitor *m) { /* jump if subsystem does not match */ bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1); } else { - hash = string_hash32(devtype); - /* jump if subsystem does not match */ bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 3); /* load device devtype value in A */ bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, filter_devtype_hash)); /* jump if value does not match */ + hash = string_hash32(devtype); bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1); } From a5a59a24478fc356aa2049e1e01ac347d06be58c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 23 Nov 2018 02:47:51 +0900 Subject: [PATCH 2/2] test: add more tests for subsystem filter --- .../sd-device/test-sd-device-monitor.c | 74 +++++++++++-------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/src/libsystemd/sd-device/test-sd-device-monitor.c b/src/libsystemd/sd-device/test-sd-device-monitor.c index b703bdee2d2..9e5ca11fe93 100644 --- a/src/libsystemd/sd-device/test-sd-device-monitor.c +++ b/src/libsystemd/sd-device/test-sd-device-monitor.c @@ -24,19 +24,15 @@ static int monitor_handler(sd_device_monitor *m, sd_device *d, void *userdata) { return sd_event_exit(sd_device_monitor_get_event(m), 0); } -static int test_loopback(bool subsystem_filter, bool tag_filter, bool use_bpf) { +static int test_send_receive_one(sd_device *device, bool subsystem_filter, bool tag_filter, bool use_bpf) { _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; - _cleanup_(sd_device_unrefp) sd_device *loopback = NULL; - const char *syspath, *subsystem, *tag; + const char *syspath, *subsystem, *tag, *devtype = NULL; int r; - log_info("/* %s(subsystem_filter=%s, tag_filter=%s, use_bpf=%s) */", __func__, - true_false(subsystem_filter), true_false(tag_filter), true_false(use_bpf)); + log_device_info(device, "/* %s(subsystem_filter=%s, tag_filter=%s, use_bpf=%s) */", __func__, + true_false(subsystem_filter), true_false(tag_filter), true_false(use_bpf)); - assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0); - assert_se(sd_device_get_syspath(loopback, &syspath) >= 0); - assert_se(device_add_property(loopback, "ACTION", "add") >= 0); - assert_se(device_add_property(loopback, "SEQNUM", "10") >= 0); + assert_se(sd_device_get_syspath(device, &syspath) >= 0); assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); @@ -48,18 +44,20 @@ static int test_loopback(bool subsystem_filter, bool tag_filter, bool use_bpf) { assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0); if (subsystem_filter) { - assert_se(sd_device_get_subsystem(loopback, &subsystem) >= 0); - assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, NULL) >= 0); + assert_se(sd_device_get_subsystem(device, &subsystem) >= 0); + (void) sd_device_get_devtype(device, &devtype); + assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, devtype) >= 0); } if (tag_filter) - FOREACH_DEVICE_TAG(loopback, tag) + FOREACH_DEVICE_TAG(device, tag) assert_se(sd_device_monitor_filter_add_match_tag(monitor_client, tag) >= 0); if ((subsystem_filter || tag_filter) && use_bpf) assert_se(sd_device_monitor_filter_update(monitor_client) >= 0); - r = device_monitor_send_device(monitor_server, monitor_client, loopback); + /* Do not use assert_se() here. */ + r = device_monitor_send_device(monitor_server, monitor_client, device); if (r < 0) return log_error_errno(r, "Failed to send loopback device: %m"); @@ -68,20 +66,16 @@ static int test_loopback(bool subsystem_filter, bool tag_filter, bool use_bpf) { return 0; } -static void test_subsystem_filter(void) { +static void test_subsystem_filter(sd_device *device) { _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; - _cleanup_(sd_device_unrefp) sd_device *loopback = NULL; const char *syspath, *subsystem, *p, *s; sd_device *d; log_info("/* %s */", __func__); - assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0); - assert_se(sd_device_get_syspath(loopback, &syspath) >= 0); - assert_se(sd_device_get_subsystem(loopback, &subsystem) >= 0); - assert_se(device_add_property(loopback, "ACTION", "add") >= 0); - assert_se(device_add_property(loopback, "SEQNUM", "10") >= 0); + assert_se(sd_device_get_syspath(device, &syspath) >= 0); + assert_se(sd_device_get_subsystem(device, &subsystem) >= 0); assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); @@ -104,11 +98,12 @@ static void test_subsystem_filter(void) { } log_info("Sending device subsystem:%s syspath:%s", subsystem, syspath); - assert_se(device_monitor_send_device(monitor_server, monitor_client, loopback) >= 0); + assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 0); } int main(int argc, char *argv[]) { + _cleanup_(sd_device_unrefp) sd_device *loopback = NULL, *sda = NULL; int r; test_setup_logging(LOG_INFO); @@ -116,20 +111,41 @@ int main(int argc, char *argv[]) { if (getuid() != 0) return log_tests_skipped("not root"); - r = test_loopback(false, false, false); + assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0); + assert_se(device_add_property(loopback, "ACTION", "add") >= 0); + assert_se(device_add_property(loopback, "SEQNUM", "10") >= 0); + + r = test_send_receive_one(loopback, false, false, false); if (r < 0) { assert_se(r == -EPERM && detect_container() > 0); return log_tests_skipped("Running in container? Skipping remaining tests"); } - assert_se(test_loopback( true, false, false) >= 0); - assert_se(test_loopback(false, true, false) >= 0); - assert_se(test_loopback( true, true, false) >= 0); - assert_se(test_loopback( true, false, true) >= 0); - assert_se(test_loopback(false, true, true) >= 0); - assert_se(test_loopback( true, true, true) >= 0); + assert_se(test_send_receive_one(loopback, true, false, false) >= 0); + assert_se(test_send_receive_one(loopback, false, true, false) >= 0); + assert_se(test_send_receive_one(loopback, true, true, false) >= 0); + assert_se(test_send_receive_one(loopback, true, false, true) >= 0); + assert_se(test_send_receive_one(loopback, false, true, true) >= 0); + assert_se(test_send_receive_one(loopback, true, true, true) >= 0); - test_subsystem_filter(); + test_subsystem_filter(loopback); + + r = sd_device_new_from_subsystem_sysname(&sda, "block", "sda"); + if (r < 0) { + log_info_errno(r, "Failed to create sd_device for sda, skipping remaining tests: %m"); + return 0; + } + + assert_se(device_add_property(sda, "ACTION", "change") >= 0); + assert_se(device_add_property(sda, "SEQNUM", "11") >= 0); + + assert_se(test_send_receive_one(sda, false, false, false) >= 0); + assert_se(test_send_receive_one(sda, true, false, false) >= 0); + assert_se(test_send_receive_one(sda, false, true, false) >= 0); + assert_se(test_send_receive_one(sda, true, true, false) >= 0); + assert_se(test_send_receive_one(sda, true, false, true) >= 0); + assert_se(test_send_receive_one(sda, false, true, true) >= 0); + assert_se(test_send_receive_one(sda, true, true, true) >= 0); return 0; }