Re: [PATCH net v4 4/4] test/vsock: copy to user failure test

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hmmm, that's really strange, i don't see CV in mailing lists. Here it is anyway:

Subject: [PATCH net v4 0/4] several updates to virtio/vsock

Hello,

this patchset evolved from previous v2 version (see link below). It does
several updates to virtio/vsock:
1) Changes 'virtio_transport_inc/dec_rx_pkt()' interface. Now instead of
   using skbuff state ('head' and 'data' pointers) to update 'fwd_cnt'
   and 'rx_bytes', integer value is passed as an input argument. This
   makes code more simple, because in this case we don't need to update
   skbuff state before calling 'virtio_transport_inc/dec_rx_pkt()'. In
   more common words - we don't need to change skbuff state to update
   'rx_bytes' and 'fwd_cnt' correctly.
2) For SOCK_STREAM, when copying data to user fails, current skbuff is
   not dropped. Next read attempt will use same skbuff and last offset.
   Instead of 'skb_dequeue()', 'skb_peek()' + '__skb_unlink()' are used.
   This behaviour was implemented before skbuff support.
3) For SOCK_SEQPACKET it removes unneeded 'skb_pull()' call, because for
   this type of socket each skbuff is used only once: after removing it
   from socket's queue, it will be freed anyway.

Test for 2) also added:
Test tries to 'recv()' data to NULL buffer, then does 'recv()' with valid
buffer. For SOCK_STREAM second 'recv()' must return data, because skbuff
must not be dropped, but for SOCK_SEQPACKET skbuff will be dropped by
kernel, and 'recv()' will return EAGAIN.

Link to v1 on lore:
https://lore.kernel.org/netdev/c2d3e204-89d9-88e9-8a15-3fe027e56b4b@xxxxxxxxxxxxxx/

Link to v2 on lore:
https://lore.kernel.org/netdev/a7ab414b-5e41-c7b6-250b-e8401f335859@xxxxxxxxxxxxxx/

Link to v3 on lore:
https://lore.kernel.org/netdev/0abeec42-a11d-3a51-453b-6acf76604f2e@xxxxxxxxxxxxxx/

Change log:

v1 -> v2:
 - For SOCK_SEQPACKET call 'skb_pull()' also in case of copy failure or
   dropping skbuff (when we just waiting message end).
 - Handle copy failure for SOCK_STREAM in the same manner (plus free
   current skbuff).
 - Replace bug repdroducer with new test in vsock_test.c

v2 -> v3:
 - Replace patch which removes 'skb->len' subtraction from function
   'virtio_transport_dec_rx_pkt()' with patch which updates functions
   'virtio_transport_inc/dec_rx_pkt()' by passing integer argument
   instead of skbuff pointer.
 - Replace patch which drops skbuff when copying to user fails with
   patch which changes this behaviour by keeping skbuff in queue until
   it has no data.
 - Add patch for SOCK_SEQPACKET which removes redundant 'skb_pull()'
   call on read.
 - I remove "Fixes" tag from all patches, because all of them now change
   code logic, not only fix something.

v3 -> v4:
 - Update commit messages in all patches except test.
 - Add "Fixes" tag to all patches except test.

Arseniy Krasnov (4):
  virtio/vsock: don't use skbuff state to account credit
  virtio/vsock: remove redundant 'skb_pull()' call
  virtio/vsock: don't drop skbuff on copy failure
  test/vsock: copy to user failure test

 net/vmw_vsock/virtio_transport_common.c |  29 +++---
 tools/testing/vsock/vsock_test.c        | 118 ++++++++++++++++++++++++
 2 files changed, 131 insertions(+), 16 deletions(-)

-- 
2.25.1


On 14.03.2023 13:47, Arseniy Krasnov wrote:
> This adds SOCK_STREAM and SOCK_SEQPACKET tests for invalid buffer case.
> It tries to read data to NULL buffer (data already presents in socket's
> queue), then uses valid buffer. For SOCK_STREAM second read must return
> data, because skbuff is not dropped, but for SOCK_SEQPACKET skbuff will
> be dropped by kernel, and 'recv()' will return EAGAIN.
> 
> Signed-off-by: Arseniy Krasnov <AVKrasnov@xxxxxxxxxxxxxx>
> Reviewed-by: Stefano Garzarella <sgarzare@xxxxxxxxxx>
> ---
>  tools/testing/vsock/vsock_test.c | 118 +++++++++++++++++++++++++++++++
>  1 file changed, 118 insertions(+)
> 
> diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
> index 67e9f9df3a8c..3de10dbb50f5 100644
> --- a/tools/testing/vsock/vsock_test.c
> +++ b/tools/testing/vsock/vsock_test.c
> @@ -860,6 +860,114 @@ static void test_stream_poll_rcvlowat_client(const struct test_opts *opts)
>  	close(fd);
>  }
>  
> +#define INV_BUF_TEST_DATA_LEN 512
> +
> +static void test_inv_buf_client(const struct test_opts *opts, bool stream)
> +{
> +	unsigned char data[INV_BUF_TEST_DATA_LEN] = {0};
> +	ssize_t ret;
> +	int fd;
> +
> +	if (stream)
> +		fd = vsock_stream_connect(opts->peer_cid, 1234);
> +	else
> +		fd = vsock_seqpacket_connect(opts->peer_cid, 1234);
> +
> +	if (fd < 0) {
> +		perror("connect");
> +		exit(EXIT_FAILURE);
> +	}
> +
> +	control_expectln("SENDDONE");
> +
> +	/* Use invalid buffer here. */
> +	ret = recv(fd, NULL, sizeof(data), 0);
> +	if (ret != -1) {
> +		fprintf(stderr, "expected recv(2) failure, got %zi\n", ret);
> +		exit(EXIT_FAILURE);
> +	}
> +
> +	if (errno != ENOMEM) {
> +		fprintf(stderr, "unexpected recv(2) errno %d\n", errno);
> +		exit(EXIT_FAILURE);
> +	}
> +
> +	ret = recv(fd, data, sizeof(data), MSG_DONTWAIT);
> +
> +	if (stream) {
> +		/* For SOCK_STREAM we must continue reading. */
> +		if (ret != sizeof(data)) {
> +			fprintf(stderr, "expected recv(2) success, got %zi\n", ret);
> +			exit(EXIT_FAILURE);
> +		}
> +		/* Don't check errno in case of success. */
> +	} else {
> +		/* For SOCK_SEQPACKET socket's queue must be empty. */
> +		if (ret != -1) {
> +			fprintf(stderr, "expected recv(2) failure, got %zi\n", ret);
> +			exit(EXIT_FAILURE);
> +		}
> +
> +		if (errno != EAGAIN) {
> +			fprintf(stderr, "unexpected recv(2) errno %d\n", errno);
> +			exit(EXIT_FAILURE);
> +		}
> +	}
> +
> +	control_writeln("DONE");
> +
> +	close(fd);
> +}
> +
> +static void test_inv_buf_server(const struct test_opts *opts, bool stream)
> +{
> +	unsigned char data[INV_BUF_TEST_DATA_LEN] = {0};
> +	ssize_t res;
> +	int fd;
> +
> +	if (stream)
> +		fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
> +	else
> +		fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL);
> +
> +	if (fd < 0) {
> +		perror("accept");
> +		exit(EXIT_FAILURE);
> +	}
> +
> +	res = send(fd, data, sizeof(data), 0);
> +	if (res != sizeof(data)) {
> +		fprintf(stderr, "unexpected send(2) result %zi\n", res);
> +		exit(EXIT_FAILURE);
> +	}
> +
> +	control_writeln("SENDDONE");
> +
> +	control_expectln("DONE");
> +
> +	close(fd);
> +}
> +
> +static void test_stream_inv_buf_client(const struct test_opts *opts)
> +{
> +	test_inv_buf_client(opts, true);
> +}
> +
> +static void test_stream_inv_buf_server(const struct test_opts *opts)
> +{
> +	test_inv_buf_server(opts, true);
> +}
> +
> +static void test_seqpacket_inv_buf_client(const struct test_opts *opts)
> +{
> +	test_inv_buf_client(opts, false);
> +}
> +
> +static void test_seqpacket_inv_buf_server(const struct test_opts *opts)
> +{
> +	test_inv_buf_server(opts, false);
> +}
> +
>  static struct test_case test_cases[] = {
>  	{
>  		.name = "SOCK_STREAM connection reset",
> @@ -920,6 +1028,16 @@ static struct test_case test_cases[] = {
>  		.run_client = test_seqpacket_bigmsg_client,
>  		.run_server = test_seqpacket_bigmsg_server,
>  	},
> +	{
> +		.name = "SOCK_STREAM test invalid buffer",
> +		.run_client = test_stream_inv_buf_client,
> +		.run_server = test_stream_inv_buf_server,
> +	},
> +	{
> +		.name = "SOCK_SEQPACKET test invalid buffer",
> +		.run_client = test_seqpacket_inv_buf_client,
> +		.run_server = test_seqpacket_inv_buf_server,
> +	},
>  	{},
>  };
>  



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux