* [PATCH v2 04/11] VSOCK: extract connect/accept functions from vsock_diag_test.c
From: Stefano Garzarella @ 2019-08-01 15:25 UTC (permalink / raw)
To: netdev
Cc: kvm, Stefan Hajnoczi, Dexuan Cui, virtualization, David S. Miller,
Jorgen Hansen, linux-kernel
In-Reply-To: <20190801152541.245833-1-sgarzare@redhat.com>
From: Stefan Hajnoczi <stefanha@redhat.com>
Many test cases will need to connect to the server or accept incoming
connections. This patch extracts these operations into utility
functions that can be reused.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
---
tools/testing/vsock/util.c | 108 ++++++++++++++++++++++++++
tools/testing/vsock/util.h | 6 ++
tools/testing/vsock/vsock_diag_test.c | 81 ++-----------------
3 files changed, 119 insertions(+), 76 deletions(-)
diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c
index f40f45b36d2f..f838bcee3589 100644
--- a/tools/testing/vsock/util.c
+++ b/tools/testing/vsock/util.c
@@ -11,8 +11,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
+#include <unistd.h>
#include "timeout.h"
+#include "control.h"
#include "util.h"
/* Install signal handlers */
@@ -41,6 +43,112 @@ unsigned int parse_cid(const char *str)
return n;
}
+/* Connect to <cid, port> and return the file descriptor. */
+int vsock_stream_connect(unsigned int cid, unsigned int port)
+{
+ union {
+ struct sockaddr sa;
+ struct sockaddr_vm svm;
+ } addr = {
+ .svm = {
+ .svm_family = AF_VSOCK,
+ .svm_port = port,
+ .svm_cid = cid,
+ },
+ };
+ int ret;
+ int fd;
+
+ control_expectln("LISTENING");
+
+ fd = socket(AF_VSOCK, SOCK_STREAM, 0);
+
+ timeout_begin(TIMEOUT);
+ do {
+ ret = connect(fd, &addr.sa, sizeof(addr.svm));
+ timeout_check("connect");
+ } while (ret < 0 && errno == EINTR);
+ timeout_end();
+
+ if (ret < 0) {
+ int old_errno = errno;
+
+ close(fd);
+ fd = -1;
+ errno = old_errno;
+ }
+ return fd;
+}
+
+/* Listen on <cid, port> and return the first incoming connection. The remote
+ * address is stored to clientaddrp. clientaddrp may be NULL.
+ */
+int vsock_stream_accept(unsigned int cid, unsigned int port,
+ struct sockaddr_vm *clientaddrp)
+{
+ union {
+ struct sockaddr sa;
+ struct sockaddr_vm svm;
+ } addr = {
+ .svm = {
+ .svm_family = AF_VSOCK,
+ .svm_port = port,
+ .svm_cid = cid,
+ },
+ };
+ union {
+ struct sockaddr sa;
+ struct sockaddr_vm svm;
+ } clientaddr;
+ socklen_t clientaddr_len = sizeof(clientaddr.svm);
+ int fd;
+ int client_fd;
+ int old_errno;
+
+ fd = socket(AF_VSOCK, SOCK_STREAM, 0);
+
+ if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) {
+ perror("bind");
+ exit(EXIT_FAILURE);
+ }
+
+ if (listen(fd, 1) < 0) {
+ perror("listen");
+ exit(EXIT_FAILURE);
+ }
+
+ control_writeln("LISTENING");
+
+ timeout_begin(TIMEOUT);
+ do {
+ client_fd = accept(fd, &clientaddr.sa, &clientaddr_len);
+ timeout_check("accept");
+ } while (client_fd < 0 && errno == EINTR);
+ timeout_end();
+
+ old_errno = errno;
+ close(fd);
+ errno = old_errno;
+
+ if (client_fd < 0)
+ return client_fd;
+
+ if (clientaddr_len != sizeof(clientaddr.svm)) {
+ fprintf(stderr, "unexpected addrlen from accept(2), %zu\n",
+ (size_t)clientaddr_len);
+ exit(EXIT_FAILURE);
+ }
+ if (clientaddr.sa.sa_family != AF_VSOCK) {
+ fprintf(stderr, "expected AF_VSOCK from accept(2), got %d\n",
+ clientaddr.sa.sa_family);
+ exit(EXIT_FAILURE);
+ }
+
+ if (clientaddrp)
+ *clientaddrp = clientaddr.svm;
+ return client_fd;
+}
+
/* Run test cases. The program terminates if a failure occurs. */
void run_tests(const struct test_case *test_cases,
const struct test_opts *opts)
diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h
index 033e7d59a42a..1786305cfddd 100644
--- a/tools/testing/vsock/util.h
+++ b/tools/testing/vsock/util.h
@@ -2,6 +2,9 @@
#ifndef UTIL_H
#define UTIL_H
+#include <sys/socket.h>
+#include <linux/vm_sockets.h>
+
/* Tests can either run as the client or the server */
enum test_mode {
TEST_MODE_UNSET,
@@ -30,6 +33,9 @@ struct test_case {
void init_signals(void);
unsigned int parse_cid(const char *str);
+int vsock_stream_connect(unsigned int cid, unsigned int port);
+int vsock_stream_accept(unsigned int cid, unsigned int port,
+ struct sockaddr_vm *clientaddrp);
void run_tests(const struct test_case *test_cases,
const struct test_opts *opts);
diff --git a/tools/testing/vsock/vsock_diag_test.c b/tools/testing/vsock/vsock_diag_test.c
index 944c8a72eed7..abd7dc2a9631 100644
--- a/tools/testing/vsock/vsock_diag_test.c
+++ b/tools/testing/vsock/vsock_diag_test.c
@@ -13,13 +13,11 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
-#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/list.h>
#include <linux/net.h>
#include <linux/netlink.h>
-#include <linux/vm_sockets.h>
#include <linux/sock_diag.h>
#include <linux/vm_sockets_diag.h>
#include <netinet/tcp.h>
@@ -378,33 +376,12 @@ static void test_listen_socket_server(const struct test_opts *opts)
static void test_connect_client(const struct test_opts *opts)
{
- union {
- struct sockaddr sa;
- struct sockaddr_vm svm;
- } addr = {
- .svm = {
- .svm_family = AF_VSOCK,
- .svm_port = 1234,
- .svm_cid = opts->peer_cid,
- },
- };
int fd;
- int ret;
LIST_HEAD(sockets);
struct vsock_stat *st;
- control_expectln("LISTENING");
-
- fd = socket(AF_VSOCK, SOCK_STREAM, 0);
-
- timeout_begin(TIMEOUT);
- do {
- ret = connect(fd, &addr.sa, sizeof(addr.svm));
- timeout_check("connect");
- } while (ret < 0 && errno == EINTR);
- timeout_end();
-
- if (ret < 0) {
+ fd = vsock_stream_connect(opts->peer_cid, 1234);
+ if (fd < 0) {
perror("connect");
exit(EXIT_FAILURE);
}
@@ -424,66 +401,19 @@ static void test_connect_client(const struct test_opts *opts)
static void test_connect_server(const struct test_opts *opts)
{
- union {
- struct sockaddr sa;
- struct sockaddr_vm svm;
- } addr = {
- .svm = {
- .svm_family = AF_VSOCK,
- .svm_port = 1234,
- .svm_cid = VMADDR_CID_ANY,
- },
- };
- union {
- struct sockaddr sa;
- struct sockaddr_vm svm;
- } clientaddr;
- socklen_t clientaddr_len = sizeof(clientaddr.svm);
- LIST_HEAD(sockets);
struct vsock_stat *st;
- int fd;
+ LIST_HEAD(sockets);
int client_fd;
- fd = socket(AF_VSOCK, SOCK_STREAM, 0);
-
- if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) {
- perror("bind");
- exit(EXIT_FAILURE);
- }
-
- if (listen(fd, 1) < 0) {
- perror("listen");
- exit(EXIT_FAILURE);
- }
-
- control_writeln("LISTENING");
-
- timeout_begin(TIMEOUT);
- do {
- client_fd = accept(fd, &clientaddr.sa, &clientaddr_len);
- timeout_check("accept");
- } while (client_fd < 0 && errno == EINTR);
- timeout_end();
-
+ client_fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
if (client_fd < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
- if (clientaddr.sa.sa_family != AF_VSOCK) {
- fprintf(stderr, "expected AF_VSOCK from accept(2), got %d\n",
- clientaddr.sa.sa_family);
- exit(EXIT_FAILURE);
- }
- if (clientaddr.svm.svm_cid != opts->peer_cid) {
- fprintf(stderr, "expected peer CID %u from accept(2), got %u\n",
- opts->peer_cid, clientaddr.svm.svm_cid);
- exit(EXIT_FAILURE);
- }
read_vsock_stat(&sockets);
- check_num_sockets(&sockets, 2);
- find_vsock_stat(&sockets, fd);
+ check_num_sockets(&sockets, 1);
st = find_vsock_stat(&sockets, client_fd);
check_socket_state(st, TCP_ESTABLISHED);
@@ -491,7 +421,6 @@ static void test_connect_server(const struct test_opts *opts)
control_expectln("DONE");
close(client_fd);
- close(fd);
free_sock_stat(&sockets);
}
--
2.20.1
^ permalink raw reply related
* [PATCH v2 10/11] vsock_test: skip read() in test_stream*close tests on a VMCI host
From: Stefano Garzarella @ 2019-08-01 15:25 UTC (permalink / raw)
To: netdev
Cc: kvm, Stefan Hajnoczi, Dexuan Cui, virtualization, David S. Miller,
Jorgen Hansen, linux-kernel
In-Reply-To: <20190801152541.245833-1-sgarzare@redhat.com>
When VMCI transport is used, if the guest closes a connection,
all data is gone and EOF is returned, so we should skip the read
of data written by the peer before closing the connection.
Reported-by: Jorgen Hansen <jhansen@vmware.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
---
tools/testing/vsock/vsock_test.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
index cb606091489f..64adf45501ca 100644
--- a/tools/testing/vsock/vsock_test.c
+++ b/tools/testing/vsock/vsock_test.c
@@ -71,6 +71,7 @@ static void test_stream_client_close_client(const struct test_opts *opts)
static void test_stream_client_close_server(const struct test_opts *opts)
{
+ unsigned int local_cid;
int fd;
fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
@@ -79,16 +80,27 @@ static void test_stream_client_close_server(const struct test_opts *opts)
exit(EXIT_FAILURE);
}
+ local_cid = vsock_get_local_cid(fd);
+
control_expectln("CLOSED");
send_byte(fd, -EPIPE);
- recv_byte(fd, 1);
+
+ /* Skip the read of data wrote by the peer if we are on VMCI and
+ * we are on the host side, because when the guest closes a
+ * connection, all data is gone and EOF is returned.
+ */
+ if (!(opts->transport == TEST_TRANSPORT_VMCI &&
+ local_cid == VMADDR_CID_HOST))
+ recv_byte(fd, 1);
+
recv_byte(fd, 0);
close(fd);
}
static void test_stream_server_close_client(const struct test_opts *opts)
{
+ unsigned int local_cid;
int fd;
fd = vsock_stream_connect(opts->peer_cid, 1234);
@@ -97,10 +109,20 @@ static void test_stream_server_close_client(const struct test_opts *opts)
exit(EXIT_FAILURE);
}
+ local_cid = vsock_get_local_cid(fd);
+
control_expectln("CLOSED");
send_byte(fd, -EPIPE);
- recv_byte(fd, 1);
+
+ /* Skip the read of data wrote by the peer if we are on VMCI and
+ * we are on the host side, because when the guest closes a
+ * connection, all data is gone and EOF is returned.
+ */
+ if (!(opts->transport == TEST_TRANSPORT_VMCI &&
+ local_cid == VMADDR_CID_HOST))
+ recv_byte(fd, 1);
+
recv_byte(fd, 0);
close(fd);
}
--
2.20.1
^ permalink raw reply related
* [PATCH v2 11/11] vsock_test: wait for the remote to close the connection
From: Stefano Garzarella @ 2019-08-01 15:25 UTC (permalink / raw)
To: netdev
Cc: kvm, Stefan Hajnoczi, Dexuan Cui, virtualization, David S. Miller,
Jorgen Hansen, linux-kernel
In-Reply-To: <20190801152541.245833-1-sgarzare@redhat.com>
Before check if a send returns -EPIPE, we need to make sure the
connection is closed.
To do that, we use epoll API to wait EPOLLRDHUP or EPOLLHUP events
on the socket.
Reported-by: Jorgen Hansen <jhansen@vmware.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
---
tools/testing/vsock/util.c | 38 ++++++++++++++++++++++++++++++++
tools/testing/vsock/util.h | 1 +
tools/testing/vsock/vsock_test.c | 10 +++++++++
3 files changed, 49 insertions(+)
diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c
index 41b94495ecb1..425181fe196c 100644
--- a/tools/testing/vsock/util.c
+++ b/tools/testing/vsock/util.c
@@ -14,6 +14,7 @@
#include <signal.h>
#include <unistd.h>
#include <assert.h>
+#include <sys/epoll.h>
#include "timeout.h"
#include "control.h"
@@ -61,6 +62,43 @@ unsigned int vsock_get_local_cid(int fd)
return svm.svm_cid;
}
+/* Wait for the remote to close the connection */
+void vsock_wait_remote_close(int fd)
+{
+ struct epoll_event ev;
+ int epollfd, nfds;
+
+ epollfd = epoll_create1(0);
+ if (epollfd == -1) {
+ perror("epoll_create1");
+ exit(EXIT_FAILURE);
+ }
+
+ ev.events = EPOLLRDHUP | EPOLLHUP;
+ ev.data.fd = fd;
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
+ perror("epoll_ctl");
+ exit(EXIT_FAILURE);
+ }
+
+ nfds = epoll_wait(epollfd, &ev, 1, TIMEOUT * 1000);
+ if (nfds == -1) {
+ perror("epoll_wait");
+ exit(EXIT_FAILURE);
+ }
+
+ if (nfds == 0) {
+ fprintf(stderr, "epoll_wait timed out\n");
+ exit(EXIT_FAILURE);
+ }
+
+ assert(nfds == 1);
+ assert(ev.events & (EPOLLRDHUP | EPOLLHUP));
+ assert(ev.data.fd == fd);
+
+ close(epollfd);
+}
+
/* Connect to <cid, port> and return the file descriptor. */
int vsock_stream_connect(unsigned int cid, unsigned int port)
{
diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h
index 7fdb8100f035..89816966c05b 100644
--- a/tools/testing/vsock/util.h
+++ b/tools/testing/vsock/util.h
@@ -45,6 +45,7 @@ int vsock_stream_connect(unsigned int cid, unsigned int port);
int vsock_stream_accept(unsigned int cid, unsigned int port,
struct sockaddr_vm *clientaddrp);
unsigned int vsock_get_local_cid(int fd);
+void vsock_wait_remote_close(int fd);
void send_byte(int fd, int expected_ret);
void recv_byte(int fd, int expected_ret);
void run_tests(const struct test_case *test_cases,
diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
index 64adf45501ca..a664675bec5a 100644
--- a/tools/testing/vsock/vsock_test.c
+++ b/tools/testing/vsock/vsock_test.c
@@ -84,6 +84,11 @@ static void test_stream_client_close_server(const struct test_opts *opts)
control_expectln("CLOSED");
+ /* Wait for the remote to close the connection, before check
+ * -EPIPE error on send.
+ */
+ vsock_wait_remote_close(fd);
+
send_byte(fd, -EPIPE);
/* Skip the read of data wrote by the peer if we are on VMCI and
@@ -113,6 +118,11 @@ static void test_stream_server_close_client(const struct test_opts *opts)
control_expectln("CLOSED");
+ /* Wait for the remote to close the connection, before check
+ * -EPIPE error on send.
+ */
+ vsock_wait_remote_close(fd);
+
send_byte(fd, -EPIPE);
/* Skip the read of data wrote by the peer if we are on VMCI and
--
2.20.1
^ permalink raw reply related
* [PATCH v2 09/11] vsock_test: add --transport parameter
From: Stefano Garzarella @ 2019-08-01 15:25 UTC (permalink / raw)
To: netdev
Cc: kvm, Stefan Hajnoczi, Dexuan Cui, virtualization, David S. Miller,
Jorgen Hansen, linux-kernel
In-Reply-To: <20190801152541.245833-1-sgarzare@redhat.com>
Add new --transport parameter to skip some tests or checks
not supported by a specific transport.
Suggested-by: Jorgen Hansen <jhansen@vmware.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
---
tools/testing/vsock/util.h | 8 ++++++++
tools/testing/vsock/vsock_test.c | 20 +++++++++++++++++++-
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h
index 379e02ab59bb..7fdb8100f035 100644
--- a/tools/testing/vsock/util.h
+++ b/tools/testing/vsock/util.h
@@ -12,9 +12,17 @@ enum test_mode {
TEST_MODE_SERVER
};
+enum test_transport {
+ TEST_TRANSPORT_UNSET,
+ TEST_TRANSPORT_VMCI,
+ TEST_TRANSPORT_VIRTIO,
+ TEST_TRANSPORT_HYPERV
+};
+
/* Test runner options */
struct test_opts {
enum test_mode mode;
+ enum test_transport transport;
unsigned int peer_cid;
};
diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
index 06099d037405..cb606091489f 100644
--- a/tools/testing/vsock/vsock_test.c
+++ b/tools/testing/vsock/vsock_test.c
@@ -218,6 +218,11 @@ static const struct option longopts[] = {
.has_arg = required_argument,
.val = 'p',
},
+ {
+ .name = "transport",
+ .has_arg = required_argument,
+ .val = 't',
+ },
{
.name = "help",
.has_arg = no_argument,
@@ -228,7 +233,7 @@ static const struct option longopts[] = {
static void usage(void)
{
- fprintf(stderr, "Usage: vsock_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid>\n"
+ fprintf(stderr, "Usage: vsock_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid> [--transport=vmci|virtio|hyperv]\n"
"\n"
" Server: vsock_test --control-port=1234 --mode=server --peer-cid=3\n"
" Client: vsock_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n"
@@ -252,6 +257,7 @@ int main(int argc, char **argv)
const char *control_port = NULL;
struct test_opts opts = {
.mode = TEST_MODE_UNSET,
+ .transport = TEST_TRANSPORT_UNSET,
.peer_cid = VMADDR_CID_ANY,
};
@@ -283,6 +289,18 @@ int main(int argc, char **argv)
case 'P':
control_port = optarg;
break;
+ case 't':
+ if (strcmp(optarg, "vmci") == 0)
+ opts.transport = TEST_TRANSPORT_VMCI;
+ else if (strcmp(optarg, "virtio") == 0)
+ opts.transport = TEST_TRANSPORT_VIRTIO;
+ else if (strcmp(optarg, "hyperv") == 0)
+ opts.transport = TEST_TRANSPORT_HYPERV;
+ else {
+ fprintf(stderr, "--transport must be \"vmci\" or \"virtio\" or \"hyperv\"\n");
+ return EXIT_FAILURE;
+ }
+ break;
case '?':
default:
usage();
--
2.20.1
^ permalink raw reply related
* [PATCH v2 08/11] VSOCK: add vsock_get_local_cid() test utility
From: Stefano Garzarella @ 2019-08-01 15:25 UTC (permalink / raw)
To: netdev
Cc: kvm, Stefan Hajnoczi, Dexuan Cui, virtualization, David S. Miller,
Jorgen Hansen, linux-kernel
In-Reply-To: <20190801152541.245833-1-sgarzare@redhat.com>
This patch adds utility to get local CID, useful to
understand if we are in the host or guest.
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
---
tools/testing/vsock/util.c | 17 +++++++++++++++++
tools/testing/vsock/util.h | 1 +
2 files changed, 18 insertions(+)
diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c
index d46a6e079b96..41b94495ecb1 100644
--- a/tools/testing/vsock/util.c
+++ b/tools/testing/vsock/util.c
@@ -13,6 +13,7 @@
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
+#include <assert.h>
#include "timeout.h"
#include "control.h"
@@ -44,6 +45,22 @@ unsigned int parse_cid(const char *str)
return n;
}
+/* Get the local CID */
+unsigned int vsock_get_local_cid(int fd)
+{
+ struct sockaddr_vm svm;
+ socklen_t svm_len = sizeof(svm);
+
+ if (getsockname(fd, (struct sockaddr *) &svm, &svm_len)) {
+ perror("getsockname");
+ exit(EXIT_FAILURE);
+ }
+
+ assert(svm.svm_family == AF_VSOCK);
+
+ return svm.svm_cid;
+}
+
/* Connect to <cid, port> and return the file descriptor. */
int vsock_stream_connect(unsigned int cid, unsigned int port)
{
diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h
index fe524d393d67..379e02ab59bb 100644
--- a/tools/testing/vsock/util.h
+++ b/tools/testing/vsock/util.h
@@ -36,6 +36,7 @@ unsigned int parse_cid(const char *str);
int vsock_stream_connect(unsigned int cid, unsigned int port);
int vsock_stream_accept(unsigned int cid, unsigned int port,
struct sockaddr_vm *clientaddrp);
+unsigned int vsock_get_local_cid(int fd);
void send_byte(int fd, int expected_ret);
void recv_byte(int fd, int expected_ret);
void run_tests(const struct test_case *test_cases,
--
2.20.1
^ permalink raw reply related
* [PATCH v2 07/11] VSOCK: add AF_VSOCK test cases
From: Stefano Garzarella @ 2019-08-01 15:25 UTC (permalink / raw)
To: netdev
Cc: kvm, Stefan Hajnoczi, Dexuan Cui, virtualization, David S. Miller,
Jorgen Hansen, linux-kernel
In-Reply-To: <20190801152541.245833-1-sgarzare@redhat.com>
From: Stefan Hajnoczi <stefanha@redhat.com>
The vsock_test.c program runs a test suite of AF_VSOCK test cases.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
---
v2:
* Drop unnecessary includes [Stefan]
* Aligned with the current SPDX [Stefano]
* Set MULTICONN_NFDS to 100 [Stefano]
* Change (i % 1) in (i % 2) in the 'multiconn' test [Stefano]
---
tools/testing/vsock/.gitignore | 1 +
tools/testing/vsock/Makefile | 5 +-
tools/testing/vsock/README | 1 +
tools/testing/vsock/vsock_test.c | 312 +++++++++++++++++++++++++++++++
4 files changed, 317 insertions(+), 2 deletions(-)
create mode 100644 tools/testing/vsock/vsock_test.c
diff --git a/tools/testing/vsock/.gitignore b/tools/testing/vsock/.gitignore
index dc5f11faf530..7f7a2ccc30c4 100644
--- a/tools/testing/vsock/.gitignore
+++ b/tools/testing/vsock/.gitignore
@@ -1,2 +1,3 @@
*.d
+vsock_test
vsock_diag_test
diff --git a/tools/testing/vsock/Makefile b/tools/testing/vsock/Makefile
index a916878a2d8c..f8293c6910c9 100644
--- a/tools/testing/vsock/Makefile
+++ b/tools/testing/vsock/Makefile
@@ -1,10 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
all: test
-test: vsock_diag_test
+test: vsock_test vsock_diag_test
+vsock_test: vsock_test.o timeout.o control.o util.o
vsock_diag_test: vsock_diag_test.o timeout.o control.o util.o
CFLAGS += -g -O2 -Werror -Wall -I. -I../../include -I../../../usr/include -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -D_GNU_SOURCE
.PHONY: all test clean
clean:
- ${RM} *.o *.d vsock_diag_test
+ ${RM} *.o *.d vsock_test vsock_diag_test
-include *.d
diff --git a/tools/testing/vsock/README b/tools/testing/vsock/README
index cf7dc64273bf..4d5045e7d2c3 100644
--- a/tools/testing/vsock/README
+++ b/tools/testing/vsock/README
@@ -5,6 +5,7 @@ Hyper-V.
The following tests are available:
+ * vsock_test - core AF_VSOCK socket functionality
* vsock_diag_test - vsock_diag.ko module for listing open sockets
The following prerequisite steps are not automated and must be performed prior
diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
new file mode 100644
index 000000000000..06099d037405
--- /dev/null
+++ b/tools/testing/vsock/vsock_test.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * vsock_test - vsock.ko test suite
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * Author: Stefan Hajnoczi <stefanha@redhat.com>
+ */
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "timeout.h"
+#include "control.h"
+#include "util.h"
+
+static void test_stream_connection_reset(const struct test_opts *opts)
+{
+ union {
+ struct sockaddr sa;
+ struct sockaddr_vm svm;
+ } addr = {
+ .svm = {
+ .svm_family = AF_VSOCK,
+ .svm_port = 1234,
+ .svm_cid = opts->peer_cid,
+ },
+ };
+ int ret;
+ int fd;
+
+ fd = socket(AF_VSOCK, SOCK_STREAM, 0);
+
+ timeout_begin(TIMEOUT);
+ do {
+ ret = connect(fd, &addr.sa, sizeof(addr.svm));
+ timeout_check("connect");
+ } while (ret < 0 && errno == EINTR);
+ timeout_end();
+
+ if (ret != -1) {
+ fprintf(stderr, "expected connect(2) failure, got %d\n", ret);
+ exit(EXIT_FAILURE);
+ }
+ if (errno != ECONNRESET) {
+ fprintf(stderr, "unexpected connect(2) errno %d\n", errno);
+ exit(EXIT_FAILURE);
+ }
+
+ close(fd);
+}
+
+static void test_stream_client_close_client(const struct test_opts *opts)
+{
+ int fd;
+
+ fd = vsock_stream_connect(opts->peer_cid, 1234);
+ if (fd < 0) {
+ perror("connect");
+ exit(EXIT_FAILURE);
+ }
+
+ send_byte(fd, 1);
+ close(fd);
+ control_writeln("CLOSED");
+}
+
+static void test_stream_client_close_server(const struct test_opts *opts)
+{
+ int fd;
+
+ fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
+ if (fd < 0) {
+ perror("accept");
+ exit(EXIT_FAILURE);
+ }
+
+ control_expectln("CLOSED");
+
+ send_byte(fd, -EPIPE);
+ recv_byte(fd, 1);
+ recv_byte(fd, 0);
+ close(fd);
+}
+
+static void test_stream_server_close_client(const struct test_opts *opts)
+{
+ int fd;
+
+ fd = vsock_stream_connect(opts->peer_cid, 1234);
+ if (fd < 0) {
+ perror("connect");
+ exit(EXIT_FAILURE);
+ }
+
+ control_expectln("CLOSED");
+
+ send_byte(fd, -EPIPE);
+ recv_byte(fd, 1);
+ recv_byte(fd, 0);
+ close(fd);
+}
+
+static void test_stream_server_close_server(const struct test_opts *opts)
+{
+ int fd;
+
+ fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
+ if (fd < 0) {
+ perror("accept");
+ exit(EXIT_FAILURE);
+ }
+
+ send_byte(fd, 1);
+ close(fd);
+ control_writeln("CLOSED");
+}
+
+/* With the standard socket sizes, VMCI is able to support about 100
+ * concurrent stream connections.
+ */
+#define MULTICONN_NFDS 100
+
+static void test_stream_multiconn_client(const struct test_opts *opts)
+{
+ int fds[MULTICONN_NFDS];
+ int i;
+
+ for (i = 0; i < MULTICONN_NFDS; i++) {
+ fds[i] = vsock_stream_connect(opts->peer_cid, 1234);
+ if (fds[i] < 0) {
+ perror("connect");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ for (i = 0; i < MULTICONN_NFDS; i++) {
+ if (i % 2)
+ recv_byte(fds[i], 1);
+ else
+ send_byte(fds[i], 1);
+ }
+
+ for (i = 0; i < MULTICONN_NFDS; i++)
+ close(fds[i]);
+}
+
+static void test_stream_multiconn_server(const struct test_opts *opts)
+{
+ int fds[MULTICONN_NFDS];
+ int i;
+
+ for (i = 0; i < MULTICONN_NFDS; i++) {
+ fds[i] = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
+ if (fds[i] < 0) {
+ perror("accept");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ for (i = 0; i < MULTICONN_NFDS; i++) {
+ if (i % 2)
+ send_byte(fds[i], 1);
+ else
+ recv_byte(fds[i], 1);
+ }
+
+ for (i = 0; i < MULTICONN_NFDS; i++)
+ close(fds[i]);
+}
+
+static struct test_case test_cases[] = {
+ {
+ .name = "SOCK_STREAM connection reset",
+ .run_client = test_stream_connection_reset,
+ },
+ {
+ .name = "SOCK_STREAM client close",
+ .run_client = test_stream_client_close_client,
+ .run_server = test_stream_client_close_server,
+ },
+ {
+ .name = "SOCK_STREAM server close",
+ .run_client = test_stream_server_close_client,
+ .run_server = test_stream_server_close_server,
+ },
+ {
+ .name = "SOCK_STREAM multiple connections",
+ .run_client = test_stream_multiconn_client,
+ .run_server = test_stream_multiconn_server,
+ },
+ {},
+};
+
+static const char optstring[] = "";
+static const struct option longopts[] = {
+ {
+ .name = "control-host",
+ .has_arg = required_argument,
+ .val = 'H',
+ },
+ {
+ .name = "control-port",
+ .has_arg = required_argument,
+ .val = 'P',
+ },
+ {
+ .name = "mode",
+ .has_arg = required_argument,
+ .val = 'm',
+ },
+ {
+ .name = "peer-cid",
+ .has_arg = required_argument,
+ .val = 'p',
+ },
+ {
+ .name = "help",
+ .has_arg = no_argument,
+ .val = '?',
+ },
+ {},
+};
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: vsock_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid>\n"
+ "\n"
+ " Server: vsock_test --control-port=1234 --mode=server --peer-cid=3\n"
+ " Client: vsock_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n"
+ "\n"
+ "Run vsock.ko tests. Must be launched in both guest\n"
+ "and host. One side must use --mode=client and\n"
+ "the other side must use --mode=server.\n"
+ "\n"
+ "A TCP control socket connection is used to coordinate tests\n"
+ "between the client and the server. The server requires a\n"
+ "listen address and the client requires an address to\n"
+ "connect to.\n"
+ "\n"
+ "The CID of the other side must be given with --peer-cid=<cid>.\n");
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv)
+{
+ const char *control_host = NULL;
+ const char *control_port = NULL;
+ struct test_opts opts = {
+ .mode = TEST_MODE_UNSET,
+ .peer_cid = VMADDR_CID_ANY,
+ };
+
+ init_signals();
+
+ for (;;) {
+ int opt = getopt_long(argc, argv, optstring, longopts, NULL);
+
+ if (opt == -1)
+ break;
+
+ switch (opt) {
+ case 'H':
+ control_host = optarg;
+ break;
+ case 'm':
+ if (strcmp(optarg, "client") == 0)
+ opts.mode = TEST_MODE_CLIENT;
+ else if (strcmp(optarg, "server") == 0)
+ opts.mode = TEST_MODE_SERVER;
+ else {
+ fprintf(stderr, "--mode must be \"client\" or \"server\"\n");
+ return EXIT_FAILURE;
+ }
+ break;
+ case 'p':
+ opts.peer_cid = parse_cid(optarg);
+ break;
+ case 'P':
+ control_port = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+
+ if (!control_port)
+ usage();
+ if (opts.mode == TEST_MODE_UNSET)
+ usage();
+ if (opts.peer_cid == VMADDR_CID_ANY)
+ usage();
+
+ if (!control_host) {
+ if (opts.mode != TEST_MODE_SERVER)
+ usage();
+ control_host = "0.0.0.0";
+ }
+
+ control_init(control_host, control_port,
+ opts.mode == TEST_MODE_SERVER);
+
+ run_tests(test_cases, &opts);
+
+ control_cleanup();
+ return EXIT_SUCCESS;
+}
--
2.20.1
^ permalink raw reply related
* [PATCH v2 06/11] VSOCK: add send_byte()/recv_byte() test utilities
From: Stefano Garzarella @ 2019-08-01 15:25 UTC (permalink / raw)
To: netdev
Cc: kvm, Stefan Hajnoczi, Dexuan Cui, virtualization, David S. Miller,
Jorgen Hansen, linux-kernel
In-Reply-To: <20190801152541.245833-1-sgarzare@redhat.com>
From: Stefan Hajnoczi <stefanha@redhat.com>
Test cases will want to transfer data. This patch adds utility
functions to do this.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
---
tools/testing/vsock/util.c | 99 ++++++++++++++++++++++++++++++++++++++
tools/testing/vsock/util.h | 2 +
2 files changed, 101 insertions(+)
diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c
index 4280a56ba677..d46a6e079b96 100644
--- a/tools/testing/vsock/util.c
+++ b/tools/testing/vsock/util.c
@@ -9,6 +9,7 @@
#include <errno.h>
#include <stdio.h>
+#include <stdint.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
@@ -149,6 +150,104 @@ int vsock_stream_accept(unsigned int cid, unsigned int port,
return client_fd;
}
+/* Transmit one byte and check the return value.
+ *
+ * expected_ret:
+ * <0 Negative errno (for testing errors)
+ * 0 End-of-file
+ * 1 Success
+ */
+void send_byte(int fd, int expected_ret)
+{
+ const uint8_t byte = 'A';
+ ssize_t nwritten;
+
+ timeout_begin(TIMEOUT);
+ do {
+ nwritten = write(fd, &byte, sizeof(byte));
+ timeout_check("write");
+ } while (nwritten < 0 && errno == EINTR);
+ timeout_end();
+
+ if (expected_ret < 0) {
+ if (nwritten != -1) {
+ fprintf(stderr, "bogus write(2) return value %zd\n",
+ nwritten);
+ exit(EXIT_FAILURE);
+ }
+ if (errno != -expected_ret) {
+ perror("write");
+ exit(EXIT_FAILURE);
+ }
+ return;
+ }
+
+ if (nwritten < 0) {
+ perror("write");
+ exit(EXIT_FAILURE);
+ }
+ if (nwritten == 0) {
+ if (expected_ret == 0)
+ return;
+
+ fprintf(stderr, "unexpected EOF while sending byte\n");
+ exit(EXIT_FAILURE);
+ }
+ if (nwritten != sizeof(byte)) {
+ fprintf(stderr, "bogus write(2) return value %zd\n", nwritten);
+ exit(EXIT_FAILURE);
+ }
+}
+
+/* Receive one byte and check the return value.
+ *
+ * expected_ret:
+ * <0 Negative errno (for testing errors)
+ * 0 End-of-file
+ * 1 Success
+ */
+void recv_byte(int fd, int expected_ret)
+{
+ uint8_t byte;
+ ssize_t nread;
+
+ timeout_begin(TIMEOUT);
+ do {
+ nread = read(fd, &byte, sizeof(byte));
+ timeout_check("read");
+ } while (nread < 0 && errno == EINTR);
+ timeout_end();
+
+ if (expected_ret < 0) {
+ if (nread != -1) {
+ fprintf(stderr, "bogus read(2) return value %zd\n",
+ nread);
+ exit(EXIT_FAILURE);
+ }
+ if (errno != -expected_ret) {
+ perror("read");
+ exit(EXIT_FAILURE);
+ }
+ return;
+ }
+
+ if (nread < 0) {
+ perror("read");
+ exit(EXIT_FAILURE);
+ }
+ if (nread == 0) {
+ if (expected_ret == 0)
+ return;
+
+ fprintf(stderr, "unexpected EOF while receiving byte\n");
+ exit(EXIT_FAILURE);
+ }
+ if (nread != sizeof(byte)) {
+ fprintf(stderr, "bogus read(2) return value %zd\n", nread);
+ exit(EXIT_FAILURE);
+ }
+}
+
/* Run test cases. The program terminates if a failure occurs. */
void run_tests(const struct test_case *test_cases,
const struct test_opts *opts)
diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h
index 1786305cfddd..fe524d393d67 100644
--- a/tools/testing/vsock/util.h
+++ b/tools/testing/vsock/util.h
@@ -36,6 +36,8 @@ unsigned int parse_cid(const char *str);
int vsock_stream_connect(unsigned int cid, unsigned int port);
int vsock_stream_accept(unsigned int cid, unsigned int port,
struct sockaddr_vm *clientaddrp);
+void send_byte(int fd, int expected_ret);
+void recv_byte(int fd, int expected_ret);
void run_tests(const struct test_case *test_cases,
const struct test_opts *opts);
--
2.20.1
^ permalink raw reply related
* [PATCH v2 05/11] VSOCK: add full barrier between test cases
From: Stefano Garzarella @ 2019-08-01 15:25 UTC (permalink / raw)
To: netdev
Cc: kvm, Stefan Hajnoczi, Dexuan Cui, virtualization, David S. Miller,
Jorgen Hansen, linux-kernel
In-Reply-To: <20190801152541.245833-1-sgarzare@redhat.com>
From: Stefan Hajnoczi <stefanha@redhat.com>
See code comment for details.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
---
tools/testing/vsock/util.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c
index f838bcee3589..4280a56ba677 100644
--- a/tools/testing/vsock/util.c
+++ b/tools/testing/vsock/util.c
@@ -161,10 +161,24 @@ void run_tests(const struct test_case *test_cases,
printf("%s...", test_cases[i].name);
fflush(stdout);
- if (opts->mode == TEST_MODE_CLIENT)
+ if (opts->mode == TEST_MODE_CLIENT) {
+ /* Full barrier before executing the next test. This
+ * ensures that client and server are executing the
+ * same test case. In particular, it means whoever is
+ * faster will not see the peer still executing the
+ * last test. This is important because port numbers
+ * can be used by multiple test cases.
+ */
+ control_expectln("NEXT");
+ control_writeln("NEXT");
+
run = test_cases[i].run_client;
- else
+ } else {
+ control_writeln("NEXT");
+ control_expectln("NEXT");
+
run = test_cases[i].run_server;
+ }
if (run)
run(opts);
--
2.20.1
^ permalink raw reply related
* [PATCH v2 03/11] VSOCK: extract utility functions from vsock_diag_test.c
From: Stefano Garzarella @ 2019-08-01 15:25 UTC (permalink / raw)
To: netdev
Cc: kvm, Stefan Hajnoczi, Dexuan Cui, virtualization, David S. Miller,
Jorgen Hansen, linux-kernel
In-Reply-To: <20190801152541.245833-1-sgarzare@redhat.com>
From: Stefan Hajnoczi <stefanha@redhat.com>
Move useful functions into a separate file in preparation for more
vsock test programs.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
---
v2:
* aligned with the current SPDX [Stefano]
---
tools/testing/vsock/Makefile | 2 +-
tools/testing/vsock/util.c | 66 +++++++++++++++++++
tools/testing/vsock/util.h | 36 +++++++++++
tools/testing/vsock/vsock_diag_test.c | 92 +++++++--------------------
4 files changed, 125 insertions(+), 71 deletions(-)
create mode 100644 tools/testing/vsock/util.c
create mode 100644 tools/testing/vsock/util.h
diff --git a/tools/testing/vsock/Makefile b/tools/testing/vsock/Makefile
index d41a4e13960a..a916878a2d8c 100644
--- a/tools/testing/vsock/Makefile
+++ b/tools/testing/vsock/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
all: test
test: vsock_diag_test
-vsock_diag_test: vsock_diag_test.o timeout.o control.o
+vsock_diag_test: vsock_diag_test.o timeout.o control.o util.o
CFLAGS += -g -O2 -Werror -Wall -I. -I../../include -I../../../usr/include -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -D_GNU_SOURCE
.PHONY: all test clean
diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c
new file mode 100644
index 000000000000..f40f45b36d2f
--- /dev/null
+++ b/tools/testing/vsock/util.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * vsock test utilities
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * Author: Stefan Hajnoczi <stefanha@redhat.com>
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+
+#include "timeout.h"
+#include "util.h"
+
+/* Install signal handlers */
+void init_signals(void)
+{
+ struct sigaction act = {
+ .sa_handler = sigalrm,
+ };
+
+ sigaction(SIGALRM, &act, NULL);
+ signal(SIGPIPE, SIG_IGN);
+}
+
+/* Parse a CID in string representation */
+unsigned int parse_cid(const char *str)
+{
+ char *endptr = NULL;
+ unsigned long n;
+
+ errno = 0;
+ n = strtoul(str, &endptr, 10);
+ if (errno || *endptr != '\0') {
+ fprintf(stderr, "malformed CID \"%s\"\n", str);
+ exit(EXIT_FAILURE);
+ }
+ return n;
+}
+
+/* Run test cases. The program terminates if a failure occurs. */
+void run_tests(const struct test_case *test_cases,
+ const struct test_opts *opts)
+{
+ int i;
+
+ for (i = 0; test_cases[i].name; i++) {
+ void (*run)(const struct test_opts *opts);
+
+ printf("%s...", test_cases[i].name);
+ fflush(stdout);
+
+ if (opts->mode == TEST_MODE_CLIENT)
+ run = test_cases[i].run_client;
+ else
+ run = test_cases[i].run_server;
+
+ if (run)
+ run(opts);
+
+ printf("ok\n");
+ }
+}
diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h
new file mode 100644
index 000000000000..033e7d59a42a
--- /dev/null
+++ b/tools/testing/vsock/util.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef UTIL_H
+#define UTIL_H
+
+/* Tests can either run as the client or the server */
+enum test_mode {
+ TEST_MODE_UNSET,
+ TEST_MODE_CLIENT,
+ TEST_MODE_SERVER
+};
+
+/* Test runner options */
+struct test_opts {
+ enum test_mode mode;
+ unsigned int peer_cid;
+};
+
+/* A test case definition. Test functions must print failures to stderr and
+ * terminate with exit(EXIT_FAILURE).
+ */
+struct test_case {
+ const char *name; /* human-readable name */
+
+ /* Called when test mode is TEST_MODE_CLIENT */
+ void (*run_client)(const struct test_opts *opts);
+
+ /* Called when test mode is TEST_MODE_SERVER */
+ void (*run_server)(const struct test_opts *opts);
+};
+
+void init_signals(void);
+unsigned int parse_cid(const char *str);
+void run_tests(const struct test_case *test_cases,
+ const struct test_opts *opts);
+
+#endif /* UTIL_H */
diff --git a/tools/testing/vsock/vsock_diag_test.c b/tools/testing/vsock/vsock_diag_test.c
index fc391e041954..944c8a72eed7 100644
--- a/tools/testing/vsock/vsock_diag_test.c
+++ b/tools/testing/vsock/vsock_diag_test.c
@@ -9,12 +9,10 @@
#include <getopt.h>
#include <stdio.h>
-#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
-#include <signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -28,12 +26,7 @@
#include "timeout.h"
#include "control.h"
-
-enum test_mode {
- TEST_MODE_UNSET,
- TEST_MODE_CLIENT,
- TEST_MODE_SERVER
-};
+#include "util.h"
/* Per-socket status */
struct vsock_stat {
@@ -334,7 +327,7 @@ static void free_sock_stat(struct list_head *sockets)
free(st);
}
-static void test_no_sockets(unsigned int peer_cid)
+static void test_no_sockets(const struct test_opts *opts)
{
LIST_HEAD(sockets);
@@ -345,7 +338,7 @@ static void test_no_sockets(unsigned int peer_cid)
free_sock_stat(&sockets);
}
-static void test_listen_socket_server(unsigned int peer_cid)
+static void test_listen_socket_server(const struct test_opts *opts)
{
union {
struct sockaddr sa;
@@ -383,7 +376,7 @@ static void test_listen_socket_server(unsigned int peer_cid)
free_sock_stat(&sockets);
}
-static void test_connect_client(unsigned int peer_cid)
+static void test_connect_client(const struct test_opts *opts)
{
union {
struct sockaddr sa;
@@ -392,7 +385,7 @@ static void test_connect_client(unsigned int peer_cid)
.svm = {
.svm_family = AF_VSOCK,
.svm_port = 1234,
- .svm_cid = peer_cid,
+ .svm_cid = opts->peer_cid,
},
};
int fd;
@@ -429,7 +422,7 @@ static void test_connect_client(unsigned int peer_cid)
free_sock_stat(&sockets);
}
-static void test_connect_server(unsigned int peer_cid)
+static void test_connect_server(const struct test_opts *opts)
{
union {
struct sockaddr sa;
@@ -481,9 +474,9 @@ static void test_connect_server(unsigned int peer_cid)
clientaddr.sa.sa_family);
exit(EXIT_FAILURE);
}
- if (clientaddr.svm.svm_cid != peer_cid) {
+ if (clientaddr.svm.svm_cid != opts->peer_cid) {
fprintf(stderr, "expected peer CID %u from accept(2), got %u\n",
- peer_cid, clientaddr.svm.svm_cid);
+ opts->peer_cid, clientaddr.svm.svm_cid);
exit(EXIT_FAILURE);
}
@@ -502,11 +495,7 @@ static void test_connect_server(unsigned int peer_cid)
free_sock_stat(&sockets);
}
-static struct {
- const char *name;
- void (*run_client)(unsigned int peer_cid);
- void (*run_server)(unsigned int peer_cid);
-} test_cases[] = {
+static struct test_case test_cases[] = {
{
.name = "No sockets",
.run_server = test_no_sockets,
@@ -523,30 +512,6 @@ static struct {
{},
};
-static void init_signals(void)
-{
- struct sigaction act = {
- .sa_handler = sigalrm,
- };
-
- sigaction(SIGALRM, &act, NULL);
- signal(SIGPIPE, SIG_IGN);
-}
-
-static unsigned int parse_cid(const char *str)
-{
- char *endptr = NULL;
- unsigned long int n;
-
- errno = 0;
- n = strtoul(str, &endptr, 10);
- if (errno || *endptr != '\0') {
- fprintf(stderr, "malformed CID \"%s\"\n", str);
- exit(EXIT_FAILURE);
- }
- return n;
-}
-
static const char optstring[] = "";
static const struct option longopts[] = {
{
@@ -601,9 +566,10 @@ int main(int argc, char **argv)
{
const char *control_host = NULL;
const char *control_port = NULL;
- int mode = TEST_MODE_UNSET;
- unsigned int peer_cid = VMADDR_CID_ANY;
- int i;
+ struct test_opts opts = {
+ .mode = TEST_MODE_UNSET,
+ .peer_cid = VMADDR_CID_ANY,
+ };
init_signals();
@@ -619,16 +585,16 @@ int main(int argc, char **argv)
break;
case 'm':
if (strcmp(optarg, "client") == 0)
- mode = TEST_MODE_CLIENT;
+ opts.mode = TEST_MODE_CLIENT;
else if (strcmp(optarg, "server") == 0)
- mode = TEST_MODE_SERVER;
+ opts.mode = TEST_MODE_SERVER;
else {
fprintf(stderr, "--mode must be \"client\" or \"server\"\n");
return EXIT_FAILURE;
}
break;
case 'p':
- peer_cid = parse_cid(optarg);
+ opts.peer_cid = parse_cid(optarg);
break;
case 'P':
control_port = optarg;
@@ -641,35 +607,21 @@ int main(int argc, char **argv)
if (!control_port)
usage();
- if (mode == TEST_MODE_UNSET)
+ if (opts.mode == TEST_MODE_UNSET)
usage();
- if (peer_cid == VMADDR_CID_ANY)
+ if (opts.peer_cid == VMADDR_CID_ANY)
usage();
if (!control_host) {
- if (mode != TEST_MODE_SERVER)
+ if (opts.mode != TEST_MODE_SERVER)
usage();
control_host = "0.0.0.0";
}
- control_init(control_host, control_port, mode == TEST_MODE_SERVER);
-
- for (i = 0; test_cases[i].name; i++) {
- void (*run)(unsigned int peer_cid);
+ control_init(control_host, control_port,
+ opts.mode == TEST_MODE_SERVER);
- printf("%s...", test_cases[i].name);
- fflush(stdout);
-
- if (mode == TEST_MODE_CLIENT)
- run = test_cases[i].run_client;
- else
- run = test_cases[i].run_server;
-
- if (run)
- run(peer_cid);
-
- printf("ok\n");
- }
+ run_tests(test_cases, &opts);
control_cleanup();
return EXIT_SUCCESS;
--
2.20.1
^ permalink raw reply related
* Re: [PATCH rdma-next 0/3] ODP support for mlx5 DC QPs
From: Leon Romanovsky @ 2019-08-01 14:55 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Doug Ledford, RDMA mailing list, Michael Guralnik, Moni Shoua,
Saeed Mahameed, linux-netdev
In-Reply-To: <20190801142432.GD23885@mellanox.com>
On Thu, Aug 01, 2019 at 02:24:37PM +0000, Jason Gunthorpe wrote:
> On Thu, Aug 01, 2019 at 03:21:36PM +0300, Leon Romanovsky wrote:
> > From: Leon Romanovsky <leonro@mellanox.com>
> >
> > From Michael,
> >
> > The series adds support for on-demand paging for DC transport.
> > Adding handling of DC WQE parsing upon page faults and exposing
> > capabilities.
> >
> > As DC is mlx-only transport, the capabilities are exposed to the user
> > using the direct-verbs mechanism. Namely through the mlx5dv_query_device.
>
> The cover letter should like to the RDMA core PR that uses the new
> API...
PR will be send in near future by Yishai. I don't have PR links at the
submission stage yet.
Thanks
>
> Jason
^ permalink raw reply
* Re: [PATCH bpf] libbpf: set BTF FD for prog only when there is supported .BTF.ext data
From: Alexei Starovoitov @ 2019-08-01 15:47 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: bpf, Network Development, Alexei Starovoitov, Daniel Borkmann,
Andrey Ignatov, Andrii Nakryiko, Kernel Team
In-Reply-To: <20190801072405.2835116-1-andriin@fb.com>
On Thu, Aug 1, 2019 at 12:41 AM Andrii Nakryiko <andriin@fb.com> wrote:
>
> 5d01ab7bac46 ("libbpf: fix erroneous multi-closing of BTF FD")
> introduced backwards-compatibility issue, manifesting itself as -E2BIG
> error returned on program load due to unknown non-zero btf_fd attribute
> value for BPF_PROG_LOAD sys_bpf() sub-command.
>
> This patch fixes bug by ensuring that we only ever associate BTF FD with
> program if there is a BTF.ext data that was successfully loaded into
> kernel, which automatically means kernel supports func_info/line_info
> and associated BTF FD for progs (checked and ensured also by BTF
> sanitization code).
>
> Fixes: 5d01ab7bac46 ("libbpf: fix erroneous multi-closing of BTF FD")
> Reported-by: Andrey Ignatov <rdna@fb.com>
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Applied. Thanks
^ permalink raw reply
* Re: [PATCH v2 10/11] vsock_test: skip read() in test_stream*close tests on a VMCI host
From: Sergei Shtylyov @ 2019-08-01 15:53 UTC (permalink / raw)
To: Stefano Garzarella, netdev
Cc: kvm, Stefan Hajnoczi, Dexuan Cui, virtualization, David S. Miller,
Jorgen Hansen, linux-kernel
In-Reply-To: <20190801152541.245833-11-sgarzare@redhat.com>
Hello!
On 08/01/2019 06:25 PM, Stefano Garzarella wrote:
> When VMCI transport is used, if the guest closes a connection,
> all data is gone and EOF is returned, so we should skip the read
> of data written by the peer before closing the connection.
>
> Reported-by: Jorgen Hansen <jhansen@vmware.com>
> Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
> ---
> tools/testing/vsock/vsock_test.c | 26 ++++++++++++++++++++++++--
> 1 file changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
> index cb606091489f..64adf45501ca 100644
> --- a/tools/testing/vsock/vsock_test.c
> +++ b/tools/testing/vsock/vsock_test.c
[...]
> @@ -79,16 +80,27 @@ static void test_stream_client_close_server(const struct test_opts *opts)
> exit(EXIT_FAILURE);
> }
>
> + local_cid = vsock_get_local_cid(fd);
> +
> control_expectln("CLOSED");
>
> send_byte(fd, -EPIPE);
> - recv_byte(fd, 1);
> +
> + /* Skip the read of data wrote by the peer if we are on VMCI and
s/wrote/written/?
> + * we are on the host side, because when the guest closes a
> + * connection, all data is gone and EOF is returned.
> + */
> + if (!(opts->transport == TEST_TRANSPORT_VMCI &&
> + local_cid == VMADDR_CID_HOST))
> + recv_byte(fd, 1);
> +
> recv_byte(fd, 0);
> close(fd);
> }
[...]
MBR, Sergei
^ permalink raw reply
* Re: [PATCH v2 10/11] vsock_test: skip read() in test_stream*close tests on a VMCI host
From: Stefano Garzarella @ 2019-08-01 15:58 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: netdev, kvm, Stefan Hajnoczi, Dexuan Cui, virtualization,
David S. Miller, Jorgen Hansen, linux-kernel
In-Reply-To: <79ffb2a6-8ed2-cce2-7704-ed872446c0fe@cogentembedded.com>
On Thu, Aug 01, 2019 at 06:53:32PM +0300, Sergei Shtylyov wrote:
> Hello!
>
Hi :)
> On 08/01/2019 06:25 PM, Stefano Garzarella wrote:
>
> > When VMCI transport is used, if the guest closes a connection,
> > all data is gone and EOF is returned, so we should skip the read
> > of data written by the peer before closing the connection.
> >
> > Reported-by: Jorgen Hansen <jhansen@vmware.com>
> > Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
> > ---
> > tools/testing/vsock/vsock_test.c | 26 ++++++++++++++++++++++++--
> > 1 file changed, 24 insertions(+), 2 deletions(-)
> >
> > diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
> > index cb606091489f..64adf45501ca 100644
> > --- a/tools/testing/vsock/vsock_test.c
> > +++ b/tools/testing/vsock/vsock_test.c
> [...]
> > @@ -79,16 +80,27 @@ static void test_stream_client_close_server(const struct test_opts *opts)
> > exit(EXIT_FAILURE);
> > }
> >
> > + local_cid = vsock_get_local_cid(fd);
> > +
> > control_expectln("CLOSED");
> >
> > send_byte(fd, -EPIPE);
> > - recv_byte(fd, 1);
> > +
> > + /* Skip the read of data wrote by the peer if we are on VMCI and
>
> s/wrote/written/?
>
Thanks, I'll fix it!
Stefano
> > + * we are on the host side, because when the guest closes a
> > + * connection, all data is gone and EOF is returned.
> > + */
> > + if (!(opts->transport == TEST_TRANSPORT_VMCI &&
> > + local_cid == VMADDR_CID_HOST))
> > + recv_byte(fd, 1);
> > +
> > recv_byte(fd, 0);
> > close(fd);
> > }
> [...]
>
> MBR, Sergei
--
^ permalink raw reply
* RE: [PATCH v2 00/11] VSOCK: add vsock_test test suite
From: Dexuan Cui @ 2019-08-01 16:16 UTC (permalink / raw)
To: Stefano Garzarella, netdev@vger.kernel.org
Cc: kvm@vger.kernel.org, Stefan Hajnoczi,
virtualization@lists.linux-foundation.org, David S. Miller,
Jorgen Hansen, linux-kernel@vger.kernel.org
In-Reply-To: <20190801152541.245833-1-sgarzare@redhat.com>
> From: Stefano Garzarella <sgarzare@redhat.com>
> Sent: Thursday, August 1, 2019 8:26 AM
>
> The vsock_diag.ko module already has a test suite but the core AF_VSOCK
> functionality has no tests. This patch series adds several test cases that
> exercise AF_VSOCK SOCK_STREAM socket semantics (send/recv,
> connect/accept,
> half-closed connections, simultaneous connections).
>
> Dexuan: Do you think can be useful to test HyperV?
Hi Stefano,
Thanks! This should be useful, though I have to write the Windows host side
code to use the test program(s). :-)
Thanks,
-- Dexuan
^ permalink raw reply
* Re: [PATCH v1 2/2] net: npcm: add NPCM7xx EMC 10/100 Ethernet driver
From: David Miller @ 2019-08-01 16:27 UTC (permalink / raw)
To: avifishman70
Cc: venture, yuenn, benjaminfair, robh+dt, mark.rutland, gregkh,
tmaimon77, tali.perry1, openbmc, netdev, devicetree, linux-kernel,
tglx
In-Reply-To: <20190801072611.27935-3-avifishman70@gmail.com>
From: Avi Fishman <avifishman70@gmail.com>
Date: Thu, 1 Aug 2019 10:26:11 +0300
> +#Eternet 10/100 EMC
"Ethernet"
> +#ifdef CONFIG_NPCM7XX_EMC_ETH_DEBUG
> +#define DEBUG
> +#endif
Please don't control the DEBUG define in this way.
> +#if defined CONFIG_NPCM7XX_EMC_ETH_DEBUG || defined CONFIG_DEBUG_FS
> +#define REG_PRINT(reg_name) {t = scnprintf(next, size, "%-10s = %08X\n", \
> + #reg_name, readl(ether->reg + (reg_name))); size -= t; next += t; }
> +#define DUMP_PRINT(f, x...) {t = scnprintf(next, size, f, ## x); size -= t; \
> + next += t; }
Really, get rid of this custom debugging infrastructure and just use
generic facilities the kernel has for this, as designed.
> +static int npcm7xx_info_dump(char *buf, int count, struct net_device *netdev)
> +{
> + struct npcm7xx_ether *ether = netdev_priv(netdev);
> + struct npcm7xx_txbd *txbd;
> + struct npcm7xx_rxbd *rxbd;
> + unsigned long flags;
> + unsigned int i, cur, txd_offset, rxd_offset;
> + char *next = buf;
> + unsigned int size = count;
> + int t;
> + int is_locked = spin_is_locked(ðer->lock);
Reverse christmas tree (longest to shortest) ordering for local variables
please.
Audit your entire submission for this problem.
^ permalink raw reply
* [PATCH] iwlwifi: remove redundant assignment to variable bufsz
From: Colin King @ 2019-08-01 16:44 UTC (permalink / raw)
To: Johannes Berg, Emmanuel Grumbach, Luca Coelho,
Intel Linux Wireless, Kalle Valo, David S . Miller,
linux-wireless, netdev
Cc: kernel-janitors, linux-kernel
From: Colin Ian King <colin.king@canonical.com>
The variable bufsz is being initialized with a value that is never
read and it is being updated later with a new value. The
initialization is redundant and can be removed.
Addresses-Coverity: ("Unused value")
Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index f5df5b370d78..addbbb78b1af 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -2542,7 +2542,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
char *buf;
int pos = 0, i, ret;
- size_t bufsz = sizeof(buf);
+ size_t bufsz;
bufsz = sizeof(char) * 121 * trans->num_rx_queues;
--
2.20.1
^ permalink raw reply related
* Re: [PATCH net-next] net/mlx5e: Allow dropping specific tunnel packets
From: David Miller @ 2019-08-01 16:48 UTC (permalink / raw)
To: xiangxia.m.yue; +Cc: roid, saeedm, netdev
In-Reply-To: <1564648859-17369-1-git-send-email-xiangxia.m.yue@gmail.com>
From: xiangxia.m.yue@gmail.com
Date: Thu, 1 Aug 2019 16:40:59 +0800
> From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
>
> In some case, we don't want to allow specific tunnel packets
> to host that can avoid to take up high CPU (e.g network attacks).
> But other tunnel packets which not matched in hardware will be
> sent to host too.
>
> $ tc filter add dev vxlan_sys_4789 \
> protocol ip chain 0 parent ffff: prio 1 handle 1 \
> flower dst_ip 1.1.1.100 ip_proto tcp dst_port 80 \
> enc_dst_ip 2.2.2.100 enc_key_id 100 enc_dst_port 4789 \
> action tunnel_key unset pipe action drop
>
> Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
Saeed, please pick this up.
Thank you.
^ permalink raw reply
* Re: [PATCH net] ibmveth: use net_err_ratelimited when set_multicast_list
From: David Miller @ 2019-08-01 16:51 UTC (permalink / raw)
To: liuhangbin; +Cc: netdev, tlfalcon
In-Reply-To: <20190801090347.8258-1-liuhangbin@gmail.com>
From: Hangbin Liu <liuhangbin@gmail.com>
Date: Thu, 1 Aug 2019 17:03:47 +0800
> When setting lots of multicast list on ibmveth, e.g. add 3000 membership on a
> multicast group, the following error message flushes our log file
>
> 8507 [ 901.478251] ibmveth 30000003 env3: h_multicast_ctrl rc=4 when adding an entry to the filter table
> ...
> 1718386 [ 5636.808658] ibmveth 30000003 env3: h_multicast_ctrl rc=4 when adding an entry to the filter table
>
> We got 1.5 million lines of messages in 1.3h. Let's replace netdev_err() by
> net_err_ratelimited() to avoid this issue. I don't use netdev_err_once() in
> case h_multicast_ctrl() return different lpar_rc types.
>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Let's work on fixing what causes this problem, or adding a retry
mechanism, rather than making the message less painful.
What is worse is that these failures are not in any way communicated
back up the callchain to show that the operation didn't complete
sucessfully.
This is a real mess in behavior and error handling, don't make it
worse please.
^ permalink raw reply
* Re: [PATCH v2 net-next] be2net: disable bh with spin_lock in be_process_mcc
From: David Miller @ 2019-08-01 16:55 UTC (permalink / raw)
To: kda; +Cc: sathya.perla, ajit.khaparde, sriharsha.basavapatna, netdev
In-Reply-To: <20190801092420.34502-1-dkirjanov@suse.com>
From: Denis Kirjanov <kda@linux-powerpc.org>
Date: Thu, 1 Aug 2019 11:24:20 +0200
> be_process_mcc() is invoked in 3 different places and
> always with BHs disabled except the be_poll function
> but since it's invoked from softirq with BHs
> disabled it won't hurt.
>
> v1->v2: added explanation to the patch
>
> Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
Like Willem I see no benefit at all to this change.
^ permalink raw reply
* Re: [PATCH bpf-next v10 10/10] landlock: Add user and kernel documentation for Landlock
From: Mickaël Salaün @ 2019-08-01 17:03 UTC (permalink / raw)
To: Randy Dunlap, Mickaël Salaün, linux-kernel
Cc: Alexander Viro, Alexei Starovoitov, Andrew Morton,
Andy Lutomirski, Arnaldo Carvalho de Melo, Casey Schaufler,
Daniel Borkmann, David Drysdale, David S . Miller,
Eric W . Biederman, James Morris, Jann Horn, John Johansen,
Jonathan Corbet, Kees Cook, Michael Kerrisk, Paul Moore,
Sargun Dhillon, Serge E . Hallyn, Shuah Khan, Stephen Smalley,
Tejun Heo, Tetsuo Handa, Thomas Graf, Tycho Andersen, Will Drewry,
kernel-hardening, linux-api, linux-fsdevel, linux-security-module,
netdev
In-Reply-To: <88e90c22-1b78-c2f2-8823-fa776265361c@infradead.org>
Thanks for this spelling fixes. Some comments:
On 31/07/2019 03:53, Randy Dunlap wrote:
> On 7/21/19 2:31 PM, Mickaël Salaün wrote:
>> This documentation can be built with the Sphinx framework.
>>
>> Signed-off-by: Mickaël Salaün <mic@digikod.net>
>> Cc: Alexei Starovoitov <ast@kernel.org>
>> Cc: Andy Lutomirski <luto@amacapital.net>
>> Cc: Daniel Borkmann <daniel@iogearbox.net>
>> Cc: David S. Miller <davem@davemloft.net>
>> Cc: James Morris <jmorris@namei.org>
>> Cc: Jonathan Corbet <corbet@lwn.net>
>> Cc: Kees Cook <keescook@chromium.org>
>> Cc: Serge E. Hallyn <serge@hallyn.com>
>> ---
>>
>> Changes since v9:
>> * update with expected attach type and expected attach triggers
>>
>> Changes since v8:
>> * remove documentation related to chaining and tagging according to this
>> patch series
>>
>> Changes since v7:
>> * update documentation according to the Landlock revamp
>>
>> Changes since v6:
>> * add a check for ctx->event
>> * rename BPF_PROG_TYPE_LANDLOCK to BPF_PROG_TYPE_LANDLOCK_RULE
>> * rename Landlock version to ABI to better reflect its purpose and add a
>> dedicated changelog section
>> * update tables
>> * relax no_new_privs recommendations
>> * remove ABILITY_WRITE related functions
>> * reword rule "appending" to "prepending" and explain it
>> * cosmetic fixes
>>
>> Changes since v5:
>> * update the rule hierarchy inheritance explanation
>> * briefly explain ctx->arg2
>> * add ptrace restrictions
>> * explain EPERM
>> * update example (subtype)
>> * use ":manpage:"
>> ---
>> Documentation/security/index.rst | 1 +
>> Documentation/security/landlock/index.rst | 20 +++
>> Documentation/security/landlock/kernel.rst | 99 ++++++++++++++
>> Documentation/security/landlock/user.rst | 147 +++++++++++++++++++++
>> 4 files changed, 267 insertions(+)
>> create mode 100644 Documentation/security/landlock/index.rst
>> create mode 100644 Documentation/security/landlock/kernel.rst
>> create mode 100644 Documentation/security/landlock/user.rst
>
>
>> diff --git a/Documentation/security/landlock/kernel.rst b/Documentation/security/landlock/kernel.rst
>> new file mode 100644
>> index 000000000000..7d1e06d544bf
>> --- /dev/null
>> +++ b/Documentation/security/landlock/kernel.rst
>> @@ -0,0 +1,99 @@
>> +==============================
>> +Landlock: kernel documentation
>> +==============================
>> +
>> +eBPF properties
>> +===============
>> +
>> +To get an expressive language while still being safe and small, Landlock is
>> +based on eBPF. Landlock should be usable by untrusted processes and must
>> +therefore expose a minimal attack surface. The eBPF bytecode is minimal,
>> +powerful, widely used and designed to be used by untrusted applications. Thus,
>> +reusing the eBPF support in the kernel enables a generic approach while
>> +minimizing new code.
>> +
>> +An eBPF program has access to an eBPF context containing some fields used to
>> +inspect the current object. These arguments can be used directly (e.g. cookie)
>> +or passed to helper functions according to their types (e.g. inode pointer). It
>> +is then possible to do complex access checks without race conditions or
>> +inconsistent evaluation (i.e. `incorrect mirroring of the OS code and state
>> +<https://www.ndss-symposium.org/ndss2003/traps-and-pitfalls-practical-problems-system-call-interposition-based-security-tools/>`_).
>> +
>> +A Landlock hook describes a particular access type. For now, there is two
>
> there are two
>
>> +hooks dedicated to filesystem related operations: LANDLOCK_HOOK_FS_PICK and
>> +LANDLOCK_HOOK_FS_WALK. A Landlock program is tied to one hook. This makes it
>> +possible to statically check context accesses, potentially performed by such
>> +program, and hence prevents kernel address leaks and ensure the right use of
>
> ensures
>
>> +hook arguments with eBPF functions. Any user can add multiple Landlock
>> +programs per Landlock hook. They are stacked and evaluated one after the
>> +other, starting from the most recent program, as seccomp-bpf does with its
>> +filters. Underneath, a hook is an abstraction over a set of LSM hooks.
>> +
>> +
>> +Guiding principles
>> +==================
>> +
>> +Unprivileged use
>> +----------------
>> +
>> +* Landlock helpers and context should be usable by any unprivileged and
>> + untrusted program while following the system security policy enforced by
>> + other access control mechanisms (e.g. DAC, LSM).
>> +
>> +
>> +Landlock hook and context
>> +-------------------------
>> +
>> +* A Landlock hook shall be focused on access control on kernel objects instead
>> + of syscall filtering (i.e. syscall arguments), which is the purpose of
>> + seccomp-bpf.
>> +* A Landlock context provided by a hook shall express the minimal and more
>> + generic interface to control an access for a kernel object.
>> +* A hook shall guaranty that all the BPF function calls from a program are> + safe. Thus, the related Landlock context arguments shall always be of the
>> + same type for a particular hook. For example, a network hook could share
>> + helpers with a file hook because of UNIX socket. However, the same helpers
>> + may not be compatible for a file system handle and a net handle.
>> +* Multiple hooks may use the same context interface.
>> +
>> +
>> +Landlock helpers
>> +----------------
>> +
>> +* Landlock helpers shall be as generic as possible while at the same time being
>> + as simple as possible and following the syscall creation principles (cf.
>> + *Documentation/adding-syscalls.txt*).
>> +* The only behavior change allowed on a helper is to fix a (logical) bug to
>> + match the initial semantic.
>> +* Helpers shall be reentrant, i.e. only take inputs from arguments (e.g. from
>> + the BPF context), to enable a hook to use a cache. Future program options
>> + might change this cache behavior.
>> +* It is quite easy to add new helpers to extend Landlock. The main concern
>> + should be about the possibility to leak information from the kernel that may
>> + not be accessible otherwise (i.e. side-channel attack).
>> +
>> +
>> +Questions and answers
>> +=====================
>> +
>> +Why not create a custom hook for each kind of action?
>> +-----------------------------------------------------
>> +
>> +Landlock programs can handle these checks. Adding more exceptions to the
>> +kernel code would lead to more code complexity. A decision to ignore a kind of
>> +action can and should be done at the beginning of a Landlock program.
>> +
>> +
>> +Why a program does not return an errno or a kill code?
>> +------------------------------------------------------
>> +
>> +seccomp filters can return multiple kind of code, including an errno value or a
>
> kinds
>
>> +kill signal, which may be convenient for access control. Those return codes
>> +are hardwired in the userland ABI. Instead, Landlock's approach is to return a
>> +boolean to allow or deny an action, which is much simpler and more generic.
>> +Moreover, we do not really have a choice because, unlike to seccomp, Landlock
>> +programs are not enforced at the syscall entry point but may be executed at any
>> +point in the kernel (through LSM hooks) where an errno return code may not make
>> +sense. However, with this simple ABI and with the ability to call helpers,
>> +Landlock may gain features similar to seccomp-bpf in the future while being
>> +compatible with previous programs.
>> diff --git a/Documentation/security/landlock/user.rst b/Documentation/security/landlock/user.rst
>> new file mode 100644
>> index 000000000000..14c4f3b377bd
>> --- /dev/null
>> +++ b/Documentation/security/landlock/user.rst
>> @@ -0,0 +1,147 @@
>> +================================
>> +Landlock: userland documentation
>> +================================
>> +
>> +Landlock programs
>> +=================
>> +
>> +eBPF programs are used to create security programs. They are contained and can
>> +call only a whitelist of dedicated functions. Moreover, they can only loop
>> +under strict conditions, which protects from denial of service. More
>> +information on BPF can be found in *Documentation/networking/filter.txt*.
>> +
>> +
>> +Writing a program
>> +-----------------
>> +
>> +To enforce a security policy, a thread first needs to create a Landlock program.
>> +The easiest way to write an eBPF program depicting a security program is to write
>> +it in the C language. As described in *samples/bpf/README.rst*, LLVM can
>> +compile such programs. Files *samples/bpf/landlock1_kern.c* and those in
>> +*tools/testing/selftests/landlock/* can be used as examples.
>> +
>> +Once the eBPF program is created, the next step is to create the metadata
>> +describing the Landlock program. This metadata includes an expected attach type which
>> +contains the hook type to which the program is tied, and expected attach
>> +triggers which identify the actions for which the program should be run.
>> +
>> +A hook is a policy decision point which exposes the same context type for
>> +each program evaluation.
>> +
>> +A Landlock hook describes the kind of kernel object for which a program will be
>> +triggered to allow or deny an action. For example, the hook
>> +BPF_LANDLOCK_FS_PICK can be triggered every time a landlocked thread performs a
>> +set of action related to the filesystem (e.g. open, read, write, mount...).
>
> actions
>
>> +This actions are identified by the `triggers` bitfield.
>> +
>> +The next step is to fill a :c:type:`struct bpf_load_program_attr
>> +<bpf_load_program_attr>` with BPF_PROG_TYPE_LANDLOCK_HOOK, the expected attach
>> +type and other BPF program metadata. This bpf_attr must then be passed to the
>> +:manpage:`bpf(2)` syscall alongside the BPF_PROG_LOAD command. If everything
>> +is deemed correct by the kernel, the thread gets a file descriptor referring to
>> +this program.
>> +
>> +In the following code, the *insn* variable is an array of BPF instructions
>> +which can be extracted from an ELF file as is done in bpf_load_file() from
>> +*samples/bpf/bpf_load.c*.
>
> A little confusing. Is there a mixup of <insn> and <insns>?
Indeed, a typo was inserted with a rewrite of this part.
>
>> +
>> +.. code-block:: c
>> +
>> + int prog_fd;
>> + struct bpf_load_program_attr load_attr;
>> +
>> + memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
>> + load_attr.prog_type = BPF_PROG_TYPE_LANDLOCK_HOOK;
>> + load_attr.expected_attach_type = BPF_LANDLOCK_FS_PICK;
>> + load_attr.expected_attach_triggers = LANDLOCK_TRIGGER_FS_PICK_OPEN;
>> + load_attr.insns = insns;
>> + load_attr.insns_cnt = sizeof(insn) / sizeof(struct bpf_insn);
>> + load_attr.license = "GPL";
>> +
>> + prog_fd = bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz);
>> + if (prog_fd == -1)
>> + exit(1);
>> +
>> +
>> +Enforcing a program
>> +-------------------
>> +
>> +Once the Landlock program has been created or received (e.g. through a UNIX
>> +socket), the thread willing to sandbox itself (and its future children) should
>> +perform the following two steps.
>> +
>> +The thread should first request to never be allowed to get new privileges with a
>> +call to :manpage:`prctl(2)` and the PR_SET_NO_NEW_PRIVS option. More
>> +information can be found in *Documentation/prctl/no_new_privs.txt*.
>> +
>> +.. code-block:: c
>> +
>> + if (prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0))
>> + exit(1);
>> +
>> +A thread can apply a program to itself by using the :manpage:`seccomp(2)` syscall.
>> +The operation is SECCOMP_PREPEND_LANDLOCK_PROG, the flags must be empty and the
>> +*args* argument must point to a valid Landlock program file descriptor.
>> +
>> +.. code-block:: c
>> +
>> + if (seccomp(SECCOMP_PREPEND_LANDLOCK_PROG, 0, &fd))
>> + exit(1);
>> +
>> +If the syscall succeeds, the program is now enforced on the calling thread and
>> +will be enforced on all its subsequently created children of the thread as
>> +well. Once a thread is landlocked, there is no way to remove this security
>> +policy, only stacking more restrictions is allowed. The program evaluation is
>> +performed from the newest to the oldest.
>> +
>> +When a syscall ask for an action on a kernel object, if this action is denied,
>
> asks
>
>> +then an EACCES errno code is returned through the syscall.
>> +
>> +
>> +.. _inherited_programs:
>> +
>> +Inherited programs
>> +------------------
>> +
>> +Every new thread resulting from a :manpage:`clone(2)` inherits Landlock program
>> +restrictions from its parent. This is similar to the seccomp inheritance as
>> +described in *Documentation/prctl/seccomp_filter.txt*.
>> +
>> +
>> +Ptrace restrictions
>> +-------------------
>> +
>> +A landlocked process has less privileges than a non-landlocked process and must
>> +then be subject to additional restrictions when manipulating another process.
>> +To be allowed to use :manpage:`ptrace(2)` and related syscalls on a target
>> +process, a landlocked process must have a subset of the target process programs.
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> Maybe that last statement is correct, but it seems to me that it is missing something.
What about this:
To be allowed to trace a process (using :manpage:`ptrace(2)`), a
landlocked tracer process must only be constrained by a subset (possibly
empty) of the Landlock programs which are also applied to the tracee.
This ensure that the tracer has less or the same constraints than the
tracee, hence protecting against privilege escalation.
>
>> +
>> +
>> +Landlock structures and constants
>> +=================================
>> +
>> +Hook types
>> +----------
>> +
>> +.. kernel-doc:: include/uapi/linux/landlock.h
>> + :functions: landlock_hook_type
>> +
>> +
>> +Contexts
>> +--------
>> +
>> +.. kernel-doc:: include/uapi/linux/landlock.h
>> + :functions: landlock_ctx_fs_pick landlock_ctx_fs_walk landlock_ctx_fs_get
>> +
>> +
>> +Triggers for fs_pick
>> +--------------------
>> +
>> +.. kernel-doc:: include/uapi/linux/landlock.h
>> + :functions: landlock_triggers
>> +
>> +
>> +Additional documentation
>> +========================
>> +
>> +See https://landlock.io
>>
>
>
--
Mickaël Salaün
ANSSI/SDE/ST/LAM
Les données à caractère personnel recueillies et traitées dans le cadre de cet échange, le sont à seule fin d’exécution d’une relation professionnelle et s’opèrent dans cette seule finalité et pour la durée nécessaire à cette relation. Si vous souhaitez faire usage de vos droits de consultation, de rectification et de suppression de vos données, veuillez contacter contact.rgpd@sgdsn.gouv.fr. Si vous avez reçu ce message par erreur, nous vous remercions d’en informer l’expéditeur et de détruire le message. The personal data collected and processed during this exchange aims solely at completing a business relationship and is limited to the necessary duration of that relationship. If you wish to use your rights of consultation, rectification and deletion of your data, please contact: contact.rgpd@sgdsn.gouv.fr. If you have received this message in error, we thank you for informing the sender and destroying the message.
^ permalink raw reply
* Re: [PATCH net v2] mvpp2: fix panic on module removal
From: David Miller @ 2019-08-01 17:08 UTC (permalink / raw)
To: mcroce
Cc: netdev, miquel.raynal, linux-kernel, lorenzo, antoine.tenart,
maxime.chevallier, mw, stefanc
In-Reply-To: <20190801121330.30823-1-mcroce@redhat.com>
From: Matteo Croce <mcroce@redhat.com>
Date: Thu, 1 Aug 2019 14:13:30 +0200
> mvpp2 uses a delayed workqueue to gather traffic statistics.
> On module removal the workqueue can be destroyed before calling
> cancel_delayed_work_sync() on its works.
> Fix it by moving the destroy_workqueue() call after mvpp2_port_remove().
> Also remove an unneeded call to flush_workqueue()
...
> Fixes: 118d6298f6f0 ("net: mvpp2: add ethtool GOP statistics")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Signed-off-by: Matteo Croce <mcroce@redhat.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* Re: [PATCH net-next] mvpp2: use devm_platform_ioremap_resource() to simplify code
From: David Miller @ 2019-08-01 17:15 UTC (permalink / raw)
To: yuehaibing; +Cc: antoine.tenart, maxime.chevallier, linux-kernel, netdev
In-Reply-To: <20190801122202.7800-1-yuehaibing@huawei.com>
From: YueHaibing <yuehaibing@huawei.com>
Date: Thu, 1 Aug 2019 20:22:02 +0800
> Use devm_platform_ioremap_resource() to simplify the code a bit.
> This is detected by coccinelle.
>
> Reported-by: Hulk Robot <hulkci@huawei.com>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] net: dsa: lantiq: use devm_platform_ioremap_resource() to simplify code
From: David Miller @ 2019-08-01 17:15 UTC (permalink / raw)
To: yuehaibing
Cc: hauke, andrew, vivien.didelot, f.fainelli, linux-kernel, netdev
In-Reply-To: <20190801122546.8516-1-yuehaibing@huawei.com>
From: YueHaibing <yuehaibing@huawei.com>
Date: Thu, 1 Aug 2019 20:25:46 +0800
> Use devm_platform_ioremap_resource() to simplify the code a bit.
> This is detected by coccinelle.
>
> Reported-by: Hulk Robot <hulkci@huawei.com>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] net: dsa: b53: use devm_platform_ioremap_resource() to simplify code
From: David Miller @ 2019-08-01 17:15 UTC (permalink / raw)
To: yuehaibing; +Cc: f.fainelli, andrew, vivien.didelot, linux-kernel, netdev
In-Reply-To: <20190801122732.37216-1-yuehaibing@huawei.com>
From: YueHaibing <yuehaibing@huawei.com>
Date: Thu, 1 Aug 2019 20:27:32 +0800
> Use devm_platform_ioremap_resource() to simplify the code a bit.
> This is detected by coccinelle.
>
> Reported-by: Hulk Robot <hulkci@huawei.com>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] net: dsa: bcm_sf2: use devm_platform_ioremap_resource() to simplify code
From: David Miller @ 2019-08-01 17:15 UTC (permalink / raw)
To: yuehaibing; +Cc: andrew, vivien.didelot, f.fainelli, linux-kernel, netdev
In-Reply-To: <20190801122911.30992-1-yuehaibing@huawei.com>
From: YueHaibing <yuehaibing@huawei.com>
Date: Thu, 1 Aug 2019 20:29:11 +0800
> Use devm_platform_ioremap_resource() to simplify the code a bit.
> This is detected by coccinelle.
>
> Reported-by: Hulk Robot <hulkci@huawei.com>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Applied.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox