From patchwork Tue Aug 20 15:18:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyril Hrubis X-Patchwork-Id: 1150247 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46CZFB64C2z9sND for ; Wed, 21 Aug 2019 01:18:38 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 86BD73C1D05 for ; Tue, 20 Aug 2019 17:18:35 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-3.smtp.seeweb.it (in-3.smtp.seeweb.it [IPv6:2001:4b78:1:20::3]) by picard.linux.it (Postfix) with ESMTP id 4865C3C1CE7 for ; Tue, 20 Aug 2019 17:18:34 +0200 (CEST) Received: from mx1.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-3.smtp.seeweb.it (Postfix) with ESMTPS id 230E51A00CBA for ; Tue, 20 Aug 2019 17:18:33 +0200 (CEST) Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id B4EB0AE4D for ; Tue, 20 Aug 2019 15:18:32 +0000 (UTC) From: Cyril Hrubis To: ltp@lists.linux.it Date: Tue, 20 Aug 2019 17:18:27 +0200 Message-Id: <20190820151831.7418-2-chrubis@suse.cz> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190820151831.7418-1-chrubis@suse.cz> References: <20190820151831.7418-1-chrubis@suse.cz> MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.99.2 at in-3.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.2 required=7.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, SPF_HELO_NONE,SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-3.smtp.seeweb.it Subject: [LTP] [PATCH v2 1/5] lib/tst_device: Export more functions. X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Export tst_attach_device() and tst_deteach_device() which will be later on used by a kernel netlink uevent tests. Signed-off-by: Cyril Hrubis Reviewed-by: Clemens Famulla-Conrad --- include/tst_device.h | 7 +++++++ lib/tst_device.c | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/tst_device.h b/include/tst_device.h index f0ddc3e93..c6e7b45b1 100644 --- a/include/tst_device.h +++ b/include/tst_device.h @@ -50,6 +50,13 @@ int tst_clear_device(const char *dev); * */ int tst_find_free_loopdev(const char *path, size_t path_len); + + +int tst_attach_device(const char *dev_path, const char *file_path); + + +int tst_detach_device(const char *dev_path); + /* * Reads test block device stat file and returns the bytes written since the * last call of this function. diff --git a/lib/tst_device.c b/lib/tst_device.c index 22abdef46..10f71901d 100644 --- a/lib/tst_device.c +++ b/lib/tst_device.c @@ -139,7 +139,7 @@ int tst_find_free_loopdev(char *path, size_t path_len) return -1; } -static int attach_device(const char *dev, const char *file) +int tst_attach_device(const char *dev, const char *file) { int dev_fd, file_fd; struct loop_info loopinfo; @@ -185,7 +185,7 @@ static int attach_device(const char *dev, const char *file) return 0; } -static int detach_device(const char *dev) +int tst_detach_device(const char *dev) { int dev_fd, ret, i; @@ -284,7 +284,7 @@ const char *tst_acquire_device__(unsigned int size) if (tst_find_free_loopdev(dev_path, sizeof(dev_path)) == -1) return NULL; - if (attach_device(dev_path, DEV_FILE)) + if (tst_attach_device(dev_path, DEV_FILE)) return NULL; device_acquired = 1; @@ -329,7 +329,7 @@ int tst_release_device(const char *dev) * * The file image is deleted in tst_rmdir(); */ - ret = detach_device(dev); + ret = tst_detach_device(dev); device_acquired = 0; From patchwork Tue Aug 20 15:18:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyril Hrubis X-Patchwork-Id: 1150249 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=2001:1418:10:5::2; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Received: from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46CZFS1P6Jz9sNk for ; Wed, 21 Aug 2019 01:18:52 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 51EF13C1D05 for ; Tue, 20 Aug 2019 17:18:49 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-3.smtp.seeweb.it (in-3.smtp.seeweb.it [217.194.8.3]) by picard.linux.it (Postfix) with ESMTP id 612093C1CF4 for ; Tue, 20 Aug 2019 17:18:34 +0200 (CEST) Received: from mx1.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-3.smtp.seeweb.it (Postfix) with ESMTPS id 95D141A00CA4 for ; Tue, 20 Aug 2019 17:18:33 +0200 (CEST) Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 46A67AEEE for ; Tue, 20 Aug 2019 15:18:33 +0000 (UTC) From: Cyril Hrubis To: ltp@lists.linux.it Date: Tue, 20 Aug 2019 17:18:28 +0200 Message-Id: <20190820151831.7418-3-chrubis@suse.cz> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190820151831.7418-1-chrubis@suse.cz> References: <20190820151831.7418-1-chrubis@suse.cz> MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.99.2 at in-3.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.2 required=7.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, SPF_HELO_NONE,SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-3.smtp.seeweb.it Subject: [LTP] [PATCH v2 2/5] kernel/uevent: Add uevent01 X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Simple test that attached and detaches a file to a loop device and checks that kernel broadcasts correct events to the kernel uevent broadcast group. Signed-off-by: Cyril Hrubis --- runtest/uevent | 1 + scenario_groups/default | 1 + testcases/kernel/uevents/.gitignore | 1 + testcases/kernel/uevents/Makefile | 6 + testcases/kernel/uevents/uevent.h | 176 ++++++++++++++++++++++++++++ testcases/kernel/uevents/uevent01.c | 90 ++++++++++++++ 6 files changed, 275 insertions(+) create mode 100644 runtest/uevent create mode 100644 testcases/kernel/uevents/.gitignore create mode 100644 testcases/kernel/uevents/Makefile create mode 100644 testcases/kernel/uevents/uevent.h create mode 100644 testcases/kernel/uevents/uevent01.c diff --git a/runtest/uevent b/runtest/uevent new file mode 100644 index 000000000..e9cdf26b8 --- /dev/null +++ b/runtest/uevent @@ -0,0 +1 @@ +uevent01 uevent01 diff --git a/scenario_groups/default b/scenario_groups/default index 093f5f706..62ae0759d 100644 --- a/scenario_groups/default +++ b/scenario_groups/default @@ -29,3 +29,4 @@ input cve crypto kernel_misc +uevent diff --git a/testcases/kernel/uevents/.gitignore b/testcases/kernel/uevents/.gitignore new file mode 100644 index 000000000..53d0b546a --- /dev/null +++ b/testcases/kernel/uevents/.gitignore @@ -0,0 +1 @@ +uevent01 diff --git a/testcases/kernel/uevents/Makefile b/testcases/kernel/uevents/Makefile new file mode 100644 index 000000000..cba769739 --- /dev/null +++ b/testcases/kernel/uevents/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +top_srcdir ?= ../../.. + +include $(top_srcdir)/include/mk/testcases.mk +include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/uevents/uevent.h b/testcases/kernel/uevents/uevent.h new file mode 100644 index 000000000..2c32dd534 --- /dev/null +++ b/testcases/kernel/uevents/uevent.h @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2019 Cyril Hrubis + */ + +#ifndef UEVENT_H__ +#define UEVENT_H__ + +#include "tst_netlink.h" + +/* + * There are two broadcast groups defined for the NETLINK_KOBJECT_UEVENT. The + * primary consument of the KERNEL group is udev which handles the hotplug + * events and then, once udev does it's magic the events are rebroadcasted to + * the UDEV group which is consumed by various daemons in the userspace. + */ +enum monitor_netlink_group { + MONITOR_GROUP_NONE, + MONITOR_GROUP_KERNEL, + MONITOR_GROUP_UDEV, +}; + +/* + * The messages received from the NETLINK_KOBJECT_UEVENT socket are stored as a + * sequence of a null-terminated strings. First in the buffer is a summary of a + * action i.e. "$ACTION@$DEVPATH" which is then followed by a bunch of + * key-value pairs. + * + * For example attaching a file to loopback device generates event: + * + * "change@/devices/virtual/block/loop0\0 + * ACTION=change\0 + * DEVPATH=/devices/virtual/block/loop0\0 + * SUBSYSTEM=block\0 + * MAJOR=7\0 + * MINOR=0\0 + * DEVNAME=loop0\0 + * DEVTYPE=disk\0 + * SEQNUM=2677\0" + */ + +/* + * Prints uevent. + */ +static inline void print_uevent(const char *event, int len) +{ + int consumed = 0; + + tst_res(TINFO, "Got uevent:"); + + while (consumed < len) { + tst_res(TINFO, "%s", event); + int l = strlen(event) + 1; + consumed += l; + event += l; + } +} + +/* + * Uevents read from the socket are matched against this description. + * + * The msg is the overall action description e.g. + * "add@/class/input/input4/mouse1" which has to be matched exactly before we + * event attempt to check the key-value pairs stored in the values array. The + * event is considered to match if all key-value pairs in the values has been + * found in the received event. + */ +struct uevent_desc { + const char *msg; + int value_cnt; + const char **values; +}; + +static inline int uevent_match(const char *event, int len, + const struct uevent_desc *uevent) +{ + int consumed = 0; + int val_matches = 0; + + if (memcmp(event, uevent->msg, strlen(uevent->msg))) + return 0; + + int l = strlen(event) + 1; + + consumed += l; + event += l; + + while (consumed < len) { + int i; + for (i = 0; i < uevent->value_cnt; i++) { + if (!strcmp(event, uevent->values[i])) { + val_matches++; + break; + } + } + + l = strlen(event) + 1; + consumed += l; + event += l; + } + + return val_matches == uevent->value_cnt; +} + +static inline int open_uevent_netlink(void) +{ + int fd; + struct sockaddr_nl nl_addr = { + .nl_family = AF_NETLINK, + .nl_groups = MONITOR_GROUP_KERNEL, + }; + + fd = SAFE_SOCKET(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); + + SAFE_BIND(fd, (struct sockaddr *)&nl_addr, sizeof(nl_addr)); + + return fd; +} + +/* + * Reads events from uevent netlink socket until all expected events passed in + * the uevent array are matched. + */ +static inline void wait_for_uevents(int fd, const struct uevent_desc *const uevents[]) +{ + int i = 0; + + while (1) { + int len; + char buf[4096]; + + len = recv(fd, &buf, sizeof(buf), 0); + + if (len == 0) + continue; + + print_uevent(buf, len); + + if (uevent_match(buf, len, uevents[i])) { + tst_res(TPASS, "Got expected UEVENT"); + if (!uevents[++i]) { + close(fd); + exit(0); + } + } + } +} + +/* + * Waits 5 seconds for a child to exit, kills the child after a timeout. + */ +static inline void wait_for_pid(int pid) +{ + int status, ret; + int retries = 5000; + + do { + ret = waitpid(pid, &status, WNOHANG); + usleep(1000); + } while (ret == 0 && retries--); + + if (ret == pid) { + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) + return; + + tst_res(TFAIL, "Child exitted with %s", tst_strstatus(status)); + } + + SAFE_KILL(pid, SIGKILL); + + SAFE_WAITPID(pid, NULL, 0); + + tst_res(TFAIL, "Did not get all expected UEVENTS"); +} + +#endif /* UEVENT_H__ */ diff --git a/testcases/kernel/uevents/uevent01.c b/testcases/kernel/uevents/uevent01.c new file mode 100644 index 000000000..41cd01b1f --- /dev/null +++ b/testcases/kernel/uevents/uevent01.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2019 Cyril Hrubis + */ + +/* + * Very simple uevent netlink socket test. + * + * We fork a child that listens for a kernel events while parents attaches and + * detaches a loop device which should produce two change events. + */ + +#include +#include +#include +#include "tst_test.h" + +#include "uevent.h" + +static void generate_device_events(const char *dev_path) +{ + tst_fill_file("loop.img", 0, 1024, 1024); + + tst_res(TINFO, "Attaching device %s", dev_path); + tst_attach_device(dev_path, "loop.img"); + tst_res(TINFO, "Detaching device %s", dev_path); + tst_detach_device(dev_path); +} + +static void verify_uevent(void) +{ + int pid, fd, dev_num; + char dev_path[1024]; + char ev_msg[1024]; + char ev_dev_path[1024]; + char ev_dev_minor[128]; + char ev_dev_name[128]; + + struct uevent_desc desc = { + .msg = ev_msg, + .value_cnt = 7, + .values = (const char*[]) { + "ACTION=change", + ev_dev_path, + "SUBSYSTEM=block", + "MAJOR=7", + ev_dev_minor, + ev_dev_name, + "DEVTYPE=disk", + } + }; + + dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path)); + + snprintf(ev_msg, sizeof(ev_msg), + "change@/devices/virtual/block/loop%i", dev_num); + + snprintf(ev_dev_path, sizeof(ev_dev_path), + "DEVPATH=/devices/virtual/block/loop%i", dev_num); + + snprintf(ev_dev_minor, sizeof(ev_dev_minor), "MINOR=%i", dev_num); + snprintf(ev_dev_name, sizeof(ev_dev_name), "DEVNAME=loop%i", dev_num); + + const struct uevent_desc *const uevents[] = { + &desc, + &desc, + NULL + }; + + pid = SAFE_FORK(); + if (!pid) { + fd = open_uevent_netlink(); + TST_CHECKPOINT_WAKE(0); + wait_for_uevents(fd, uevents); + } + + TST_CHECKPOINT_WAIT(0); + + generate_device_events(dev_path); + + wait_for_pid(pid); +} + +static struct tst_test test = { + .test_all = verify_uevent, + .forks_child = 1, + .needs_tmpdir = 1, + .needs_checkpoints = 1, + .needs_root = 1, +}; From patchwork Tue Aug 20 15:18:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyril Hrubis X-Patchwork-Id: 1150250 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=213.254.12.146; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Received: from picard.linux.it (picard.linux.it [213.254.12.146]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46CZFZ4LV0z9sNk for ; Wed, 21 Aug 2019 01:18:58 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id E46A73C1D6C for ; Tue, 20 Aug 2019 17:18:55 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-4.smtp.seeweb.it (in-4.smtp.seeweb.it [IPv6:2001:4b78:1:20::4]) by picard.linux.it (Postfix) with ESMTP id CB9F93C1D00 for ; Tue, 20 Aug 2019 17:18:34 +0200 (CEST) Received: from mx1.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-4.smtp.seeweb.it (Postfix) with ESMTPS id E6EFC1000AC4 for ; Tue, 20 Aug 2019 17:18:27 +0200 (CEST) Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id C650BAF33 for ; Tue, 20 Aug 2019 15:18:33 +0000 (UTC) From: Cyril Hrubis To: ltp@lists.linux.it Date: Tue, 20 Aug 2019 17:18:29 +0200 Message-Id: <20190820151831.7418-4-chrubis@suse.cz> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190820151831.7418-1-chrubis@suse.cz> References: <20190820151831.7418-1-chrubis@suse.cz> MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.99.2 at in-4.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.2 required=7.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, SPF_HELO_NONE,SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-4.smtp.seeweb.it Subject: [LTP] [PATCH v2 3/5] kernel/uevent: Add uevent02 X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" Similar to uevent01 but we create and remove a tun network card instead. Signed-off-by: Cyril Hrubis --- runtest/uevent | 1 + testcases/kernel/uevents/.gitignore | 1 + testcases/kernel/uevents/uevent02.c | 141 ++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 testcases/kernel/uevents/uevent02.c diff --git a/runtest/uevent b/runtest/uevent index e9cdf26b8..30b1114a4 100644 --- a/runtest/uevent +++ b/runtest/uevent @@ -1 +1,2 @@ uevent01 uevent01 +uevent02 uevent02 diff --git a/testcases/kernel/uevents/.gitignore b/testcases/kernel/uevents/.gitignore index 53d0b546a..0afc95534 100644 --- a/testcases/kernel/uevents/.gitignore +++ b/testcases/kernel/uevents/.gitignore @@ -1 +1,2 @@ uevent01 +uevent02 diff --git a/testcases/kernel/uevents/uevent02.c b/testcases/kernel/uevents/uevent02.c new file mode 100644 index 000000000..2c28d1810 --- /dev/null +++ b/testcases/kernel/uevents/uevent02.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2019 Cyril Hrubis + */ + +/* + * Very simple uevent netlink socket test. + * + * We fork a child that listens for a kernel events while parents creates and removes + * a tun network device which should produce two several add and remove events. + */ + +#include +#include +#include +#include +#include + +#include "tst_test.h" + +#include "uevent.h" + +#define TUN_PATH "/dev/net/tun" + +static void generate_tun_uevents(void) +{ + int fd = SAFE_OPEN(TUN_PATH, O_RDWR); + + struct ifreq ifr = { + .ifr_flags = IFF_TUN, + .ifr_name = "ltp-tun0", + }; + + SAFE_IOCTL(fd, TUNSETIFF, (void*)&ifr); + + SAFE_IOCTL(fd, TUNSETPERSIST, 0); + + SAFE_CLOSE(fd); +} + +static void verify_uevent(void) +{ + int pid, fd; + + struct uevent_desc add = { + .msg = "add@/devices/virtual/net/ltp-tun0", + .value_cnt = 0, + .values = (const char*[]) { + "ACTION=add", + "DEVPATH=/devices/virtual/net/ltp-tun0", + "SUBSYSTEM=net", + "ITERFACE=ltp-tun0", + } + }; + + struct uevent_desc add_rx = { + .msg = "add@/devices/virtual/net/ltp-tun0/queues/rx-0", + .value_cnt = 0, + .values = (const char*[]) { + "ACTION=add", + "DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0", + "SUBSYSTEM=queueus", + } + }; + + struct uevent_desc add_tx = { + .msg = "add@/devices/virtual/net/ltp-tun0/queues/tx-0", + .value_cnt = 0, + .values = (const char*[]) { + "ACTION=add", + "DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0", + "SUBSYSTEM=queueus", + } + }; + + struct uevent_desc rem_rx = { + .msg = "remove@/devices/virtual/net/ltp-tun0/queues/rx-0", + .value_cnt = 0, + .values = (const char*[]) { + "ACTION=remove", + "DEVPATH=/devices/virtual/net/ltp-tun0/queues/rx-0", + "SUBSYSTEM=queueus", + } + }; + + struct uevent_desc rem_tx = { + .msg = "remove@/devices/virtual/net/ltp-tun0/queues/tx-0", + .value_cnt = 0, + .values = (const char*[]) { + "ACTION=remove", + "DEVPATH=/devices/virtual/net/ltp-tun0/queues/tx-0", + "SUBSYSTEM=queueus", + } + }; + + struct uevent_desc rem = { + .msg = "remove@/devices/virtual/net/ltp-tun0", + .value_cnt = 0, + .values = (const char*[]) { + "ACTION=remove", + "DEVPATH=/devices/virtual/net/ltp-tun0", + "SUBSYSTEM=net", + "ITERFACE=ltp-tun0", + } + }; + + const struct uevent_desc *const uevents[] = { + &add, + &add_rx, + &add_tx, + &rem_rx, + &rem_tx, + &rem, + NULL + }; + + pid = SAFE_FORK(); + if (!pid) { + fd = open_uevent_netlink(); + TST_CHECKPOINT_WAKE(0); + wait_for_uevents(fd, uevents); + } + + TST_CHECKPOINT_WAIT(0); + + generate_tun_uevents(); + + wait_for_pid(pid); +} + +static struct tst_test test = { + .test_all = verify_uevent, + .forks_child = 1, + .needs_tmpdir = 1, + .needs_checkpoints = 1, + .needs_root = 1, + .needs_drivers = (const char *const []) { + "tun", + NULL + }, +}; From patchwork Tue Aug 20 15:18:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyril Hrubis X-Patchwork-Id: 1150251 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=2001:1418:10:5::2; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Received: from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46CZFj3nN3z9sN1 for ; Wed, 21 Aug 2019 01:19:05 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 670FF3C1D78 for ; Tue, 20 Aug 2019 17:19:02 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-2.smtp.seeweb.it (in-2.smtp.seeweb.it [IPv6:2001:4b78:1:20::2]) by picard.linux.it (Postfix) with ESMTP id 577923C1D17 for ; Tue, 20 Aug 2019 17:18:35 +0200 (CEST) Received: from mx1.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-2.smtp.seeweb.it (Postfix) with ESMTPS id C166C6000F4 for ; Tue, 20 Aug 2019 17:18:34 +0200 (CEST) Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 62826ABF6 for ; Tue, 20 Aug 2019 15:18:34 +0000 (UTC) From: Cyril Hrubis To: ltp@lists.linux.it Date: Tue, 20 Aug 2019 17:18:30 +0200 Message-Id: <20190820151831.7418-5-chrubis@suse.cz> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190820151831.7418-1-chrubis@suse.cz> References: <20190820151831.7418-1-chrubis@suse.cz> MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.99.2 at in-2.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.3 required=7.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, SPF_HELO_NONE, SPF_PASS, WEIRD_QUOTING autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-2.smtp.seeweb.it Subject: [LTP] [PATCH v2 4/5] libs/libltpuinput: Add uinput library. X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" I to be used in the uevent03 test. Also I will convert the uinput testcases to new library and make use of this library as well. Signed-off-by: Cyril Hrubis --- include/tst_uinput.h | 48 +++++++++++ libs/libltpuinput/Makefile | 12 +++ libs/libltpuinput/tst_uinput.c | 143 +++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 include/tst_uinput.h create mode 100644 libs/libltpuinput/Makefile create mode 100644 libs/libltpuinput/tst_uinput.c diff --git a/include/tst_uinput.h b/include/tst_uinput.h new file mode 100644 index 000000000..dddbd9921 --- /dev/null +++ b/include/tst_uinput.h @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2019 Cyril Hrubis + */ + +#ifndef TST_UINPUT_H__ +#define TST_UINPUT_H__ + +/** + * Tries to open the uinput device. + * + * Returns file descriptor on success, -1 on failure. + */ +int open_uinput(void); + +/** + * Creates virtual input device. + * + * @fd File descriptor returned by open_uinput(). + */ +void create_input_device(int fd); + +/** + * Parses /proc/bus/input/devices and returns the handlers strings for our + * virtual device, which is list of input devices that receive events from the + * device separated by whitestpaces. + * + * Returns newly allocated string, list of handlers separated by whitespaces, + * or NULL in a case of failure. + */ +char *get_input_handlers(void); + +/** + * Sets up the virtual device to appear as a mouse, this must be called before + * the call to create_input_device(). + * + * @fd File descriptor as returned by open_uinput(). + */ +void setup_mouse_events(int fd); + +/** + * Destroys virtual input device. + * + * @fd File descriptor returned by open_uinput(). + */ +void destroy_input_device(int fd); + +#endif /* TST_UINPUT_H__ */ diff --git a/libs/libltpuinput/Makefile b/libs/libltpuinput/Makefile new file mode 100644 index 000000000..dd2a6c096 --- /dev/null +++ b/libs/libltpuinput/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) Cyril Hrubis + +top_srcdir ?= ../.. + +include $(top_srcdir)/include/mk/env_pre.mk + +LIB := libltpuinput.a + +include $(top_srcdir)/include/mk/lib.mk +include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/libs/libltpuinput/tst_uinput.c b/libs/libltpuinput/tst_uinput.c new file mode 100644 index 000000000..61d06138e --- /dev/null +++ b/libs/libltpuinput/tst_uinput.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2015 Cedric Hnyda + * Copyright (c) 2019 Cyril Hrubis + */ + +#include +#include +#include +#include + +#define TST_NO_DEFAULT_MAIN +#include "tst_test.h" + +#include "tst_uinput.h" + +#define VIRTUAL_DEVICE "virtual-device-ltp" + +static const char *uinput_paths[] = { + "/dev/input/uinput", + "/dev/uinput", +}; + +int open_uinput(void) +{ + unsigned int i; + int fd; + + for (i = 0; i < ARRAY_SIZE(uinput_paths); i++) { + fd = open(uinput_paths[i], O_WRONLY | O_NONBLOCK); + + if (fd > 0) { + tst_res(TINFO, "Found uinput dev at %s", uinput_paths[i]); + return fd; + } + + if (fd < 0 && errno != ENOENT) { + tst_brk(TBROK | TERRNO, "open(%s)", uinput_paths[i]); + } + } + + return -1; +} + +#define HANDLERS_PREFIX "Handlers=" + +static char *parse_handlers(char *line) +{ + char *handlers; + + handlers = strstr(line, HANDLERS_PREFIX) + sizeof(HANDLERS_PREFIX) - 1; + + handlers[strlen(handlers) - 1] = 0; + + return strdup(handlers); +} + +char *get_input_handlers(void) +{ + FILE *file; + char line[1024]; + int flag = 0; + + file = fopen("/proc/bus/input/devices", "r"); + if (!file) + return NULL; + + while (fgets(line, sizeof(line), file)) { + if (strstr(line, "N: Name=\""VIRTUAL_DEVICE"\"")) + flag = 1; + + if (flag) { + if (line[0] == 'H') + return parse_handlers(line); + + if (line[0] == '\n') + flag = 0; + } + } + + fclose(file); + return NULL; +} + +static int check_device(void) +{ + FILE *file; + char line[256]; + + file = fopen("/proc/bus/input/devices", "r"); + if (!file) + return 0; + + while (fgets(line, 256, file)) { + if (strstr(line, VIRTUAL_DEVICE)) + return 1; + } + + fclose(file); + + return 0; +} + +void setup_mouse_events(int fd) +{ + SAFE_IOCTL(fd, UI_SET_EVBIT, EV_KEY); + SAFE_IOCTL(fd, UI_SET_KEYBIT, BTN_LEFT); + SAFE_IOCTL(fd, UI_SET_EVBIT, EV_REL); + SAFE_IOCTL(fd, UI_SET_RELBIT, REL_X); + SAFE_IOCTL(fd, UI_SET_RELBIT, REL_Y); +} + +void destroy_input_device(int fd) +{ + SAFE_IOCTL(fd, UI_DEV_DESTROY, NULL); + SAFE_CLOSE(fd); +} + +void create_input_device(int fd) +{ + int nb; + struct uinput_user_dev uidev = { + .name = VIRTUAL_DEVICE, + .id = { + .bustype = BUS_USB, + .vendor = 0x1, + .product = 0x1, + .version = 1, + } + }; + + SAFE_WRITE(1, fd, &uidev, sizeof(uidev)); + SAFE_IOCTL(fd, UI_DEV_CREATE, NULL); + + for (nb = 100; nb > 0; nb--) { + if (check_device()) + return; + usleep(10000); + } + + destroy_input_device(fd); + tst_brk(TBROK, "Failed to create device"); +} From patchwork Tue Aug 20 15:18:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyril Hrubis X-Patchwork-Id: 1150252 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.linux.it (client-ip=2001:1418:10:5::2; helo=picard.linux.it; envelope-from=ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Received: from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46CZFt6RNNz9sN1 for ; Wed, 21 Aug 2019 01:19:13 +1000 (AEST) Received: from picard.linux.it (localhost [IPv6:::1]) by picard.linux.it (Postfix) with ESMTP id 3B1463C1D0E for ; Tue, 20 Aug 2019 17:19:10 +0200 (CEST) X-Original-To: ltp@lists.linux.it Delivered-To: ltp@picard.linux.it Received: from in-2.smtp.seeweb.it (in-2.smtp.seeweb.it [217.194.8.2]) by picard.linux.it (Postfix) with ESMTP id 019723C1D24 for ; Tue, 20 Aug 2019 17:18:36 +0200 (CEST) Received: from mx1.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by in-2.smtp.seeweb.it (Postfix) with ESMTPS id 7CA9D6000F4 for ; Tue, 20 Aug 2019 17:18:35 +0200 (CEST) Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id E6F31AEEE for ; Tue, 20 Aug 2019 15:18:34 +0000 (UTC) From: Cyril Hrubis To: ltp@lists.linux.it Date: Tue, 20 Aug 2019 17:18:31 +0200 Message-Id: <20190820151831.7418-6-chrubis@suse.cz> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190820151831.7418-1-chrubis@suse.cz> References: <20190820151831.7418-1-chrubis@suse.cz> MIME-Version: 1.0 X-Virus-Scanned: clamav-milter 0.99.2 at in-2.smtp.seeweb.it X-Virus-Status: Clean X-Spam-Status: No, score=0.2 required=7.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, SPF_HELO_NONE,SPF_PASS autolearn=disabled version=3.4.0 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on in-2.smtp.seeweb.it Subject: [LTP] [PATCH v2 5/5] kernel/uevent: Add uevent03 X-BeenThere: ltp@lists.linux.it X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux Test Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ltp-bounces+incoming=patchwork.ozlabs.org@lists.linux.it Sender: "ltp" This time we create a virtual input device, a mouse, and validate the result. Signed-off-by: Cyril Hrubis --- runtest/uevent | 1 + testcases/kernel/uevents/.gitignore | 1 + testcases/kernel/uevents/Makefile | 4 + testcases/kernel/uevents/uevent03.c | 240 ++++++++++++++++++++++++++++ 4 files changed, 246 insertions(+) create mode 100644 testcases/kernel/uevents/uevent03.c diff --git a/runtest/uevent b/runtest/uevent index 30b1114a4..0b59c8723 100644 --- a/runtest/uevent +++ b/runtest/uevent @@ -1,2 +1,3 @@ uevent01 uevent01 uevent02 uevent02 +uevent03 uevent03 diff --git a/testcases/kernel/uevents/.gitignore b/testcases/kernel/uevents/.gitignore index 0afc95534..7818f7308 100644 --- a/testcases/kernel/uevents/.gitignore +++ b/testcases/kernel/uevents/.gitignore @@ -1,2 +1,3 @@ uevent01 uevent02 +uevent03 diff --git a/testcases/kernel/uevents/Makefile b/testcases/kernel/uevents/Makefile index cba769739..d5ceb0719 100644 --- a/testcases/kernel/uevents/Makefile +++ b/testcases/kernel/uevents/Makefile @@ -2,5 +2,9 @@ top_srcdir ?= ../../.. +LTPLIBS = ltpuinput + +uevent03: LDLIBS += -lltpuinput + include $(top_srcdir)/include/mk/testcases.mk include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/uevents/uevent03.c b/testcases/kernel/uevents/uevent03.c new file mode 100644 index 000000000..26790967c --- /dev/null +++ b/testcases/kernel/uevents/uevent03.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2019 Cyril Hrubis + */ + +/* + * Very simple uevent netlink socket test. + * + * We fork a child that listens for a kernel events while parents creates and + * removes a virtual mouse which produces add and remove event for the device + * itself and for two event handlers called eventX and mouseY. + */ + +#include +#include +#include +#include + +#include + +#include "tst_test.h" +#include "tst_uinput.h" +#include "uevent.h" + +static int mouse_fd; + +static void create_uinput_mouse(void) +{ + mouse_fd = open_uinput(); + setup_mouse_events(mouse_fd); + create_input_device(mouse_fd); +} + +static void destroy_uinput_mouse(void) +{ + destroy_input_device(mouse_fd); +} + +static void get_minor_major(char *device, char *minor, char *major, size_t buf_sizes) +{ + char path[1024]; + struct stat stbuf; + + snprintf(path, sizeof(path), "/dev/input/%s", device); + + SAFE_STAT(path, &stbuf); + + snprintf(major, buf_sizes, "MAJOR=%i", major(stbuf.st_rdev)); + snprintf(minor, buf_sizes, "MINOR=%i", minor(stbuf.st_rdev)); +} + +#define MINOR_MAJOR_SIZE 32 + +static void verify_uevent(void) +{ + int pid, fd; + char sysname[64]; + char add_msg[1024]; + char rem_msg[1024]; + char dev_path[1024]; + char add_msg_event1[1024]; + char rem_msg_event1[1024]; + char dev_path_event1[1024]; + char add_msg_event2[1024]; + char rem_msg_event2[1024]; + char dev_path_event2[1024]; + char dev_name1[1024]; + char dev_name2[1024]; + + char minor_event1[MINOR_MAJOR_SIZE]; + char minor_event2[MINOR_MAJOR_SIZE]; + char major_event1[MINOR_MAJOR_SIZE]; + char major_event2[MINOR_MAJOR_SIZE]; + + char *handlers, *handler1, *handler2; + + struct uevent_desc add = { + .msg = add_msg, + .value_cnt = 7, + .values = (const char*[]) { + "ACTION=add", + dev_path, + "SUBSYSTEM=input", + "NAME=\"virtual-device-ltp\"", + "PROP=0", + "EV=7", + "REL=3", + } + }; + + struct uevent_desc add_event1 = { + .msg = add_msg_event1, + .value_cnt = 6, + .values = (const char*[]) { + "ACTION=add", + "SUBSYSTEM=input", + dev_name1, + dev_path_event1, + minor_event1, + major_event1, + } + }; + + struct uevent_desc add_event2 = { + .msg = add_msg_event2, + .value_cnt = 6, + .values = (const char*[]) { + "ACTION=add", + "SUBSYSTEM=input", + dev_name2, + dev_path_event2, + minor_event2, + major_event2, + } + }; + + struct uevent_desc rem_event1 = { + .msg = rem_msg_event1, + .value_cnt = 6, + .values = (const char*[]) { + "ACTION=remove", + "SUBSYSTEM=input", + dev_name1, + dev_path_event1, + minor_event1, + major_event1, + } + }; + + struct uevent_desc rem_event2 = { + .msg = rem_msg_event2, + .value_cnt = 6, + .values = (const char*[]) { + "ACTION=remove", + "SUBSYSTEM=input", + dev_name2, + dev_path_event2, + minor_event2, + major_event2, + } + }; + + struct uevent_desc rem = { + .msg = rem_msg, + .value_cnt = 7, + .values = (const char*[]) { + "ACTION=remove", + dev_path, + "SUBSYSTEM=input", + "NAME=\"virtual-device-ltp\"", + "PROP=0", + "EV=7", + "REL=3", + } + }; + + const struct uevent_desc *const uevents[] = { + &add, + &add_event1, + &add_event2, + &rem_event1, + &rem_event2, + &rem, + NULL + }; + + fd = open_uevent_netlink(); + + create_uinput_mouse(); + + SAFE_IOCTL(mouse_fd, UI_GET_SYSNAME(sizeof(sysname)), sysname); + handlers = get_input_handlers(); + + handler1 = strtok(handlers, " "); + get_minor_major(handler1, minor_event1, major_event1, MINOR_MAJOR_SIZE); + + handler2 = strtok(NULL, " "); + get_minor_major(handler2, minor_event2, major_event2, MINOR_MAJOR_SIZE); + + destroy_uinput_mouse(); + + tst_res(TINFO, "Sysname: %s", sysname); + tst_res(TINFO, "Handlers: %s", handlers); + + snprintf(add_msg, sizeof(add_msg), + "add@/devices/virtual/input/%s", sysname); + + snprintf(rem_msg, sizeof(rem_msg), + "remove@/devices/virtual/input/%s", sysname); + + snprintf(dev_path, sizeof(dev_path), + "DEVPATH=/devices/virtual/input/%s", sysname); + + + snprintf(add_msg_event1, sizeof(add_msg_event1), + "add@/devices/virtual/input/%s/%s", sysname, handler1); + + snprintf(rem_msg_event1, sizeof(rem_msg_event1), + "remove@/devices/virtual/input/%s/%s", sysname, handler1); + + snprintf(dev_path_event1, sizeof(dev_path_event1), + "DEVPATH=/devices/virtual/input/%s/%s", sysname, handler1); + + snprintf(dev_name1, sizeof(dev_name1), + "DEVNAME=input/%s", handler1); + + + snprintf(add_msg_event2, sizeof(add_msg_event2), + "add@/devices/virtual/input/%s/%s", sysname, handler2); + + snprintf(rem_msg_event2, sizeof(rem_msg_event2), + "remove@/devices/virtual/input/%s/%s", sysname, handler2); + + snprintf(dev_path_event2, sizeof(dev_path_event2), + "DEVPATH=/devices/virtual/input/%s/%s", sysname, handler2); + + snprintf(dev_name2, sizeof(dev_name2), + "DEVNAME=input/%s", handler2); + + free(handlers); + + pid = SAFE_FORK(); + if (!pid) + wait_for_uevents(fd, uevents); + + SAFE_CLOSE(fd); + wait_for_pid(pid); +} + +static struct tst_test test = { + .test_all = verify_uevent, + .forks_child = 1, + .needs_tmpdir = 1, + .needs_checkpoints = 1, + .needs_drivers = (const char *const[]) { + "uinput", + NULL + }, + .needs_root = 1, +};