Skip to content

Commit

Permalink
Merge branch 'net-virtio-vsock'
Browse files Browse the repository at this point in the history
  • Loading branch information
davem330 committed Mar 16, 2023
2 parents cd35601 + 7e699d2 commit 1a200b5
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 16 deletions.
29 changes: 13 additions & 16 deletions net/vmw_vsock/virtio_transport_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,21 +241,18 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
}

static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
struct sk_buff *skb)
u32 len)
{
if (vvs->rx_bytes + skb->len > vvs->buf_alloc)
if (vvs->rx_bytes + len > vvs->buf_alloc)
return false;

vvs->rx_bytes += skb->len;
vvs->rx_bytes += len;
return true;
}

static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs,
struct sk_buff *skb)
u32 len)
{
int len;

len = skb_headroom(skb) - sizeof(struct virtio_vsock_hdr) - skb->len;
vvs->rx_bytes -= len;
vvs->fwd_cnt += len;
}
Expand Down Expand Up @@ -367,7 +364,7 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,

spin_lock_bh(&vvs->rx_lock);
while (total < len && !skb_queue_empty(&vvs->rx_queue)) {
skb = __skb_dequeue(&vvs->rx_queue);
skb = skb_peek(&vvs->rx_queue);

bytes = len - total;
if (bytes > skb->len)
Expand All @@ -388,10 +385,11 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
skb_pull(skb, bytes);

if (skb->len == 0) {
virtio_transport_dec_rx_pkt(vvs, skb);
u32 pkt_len = le32_to_cpu(virtio_vsock_hdr(skb)->len);

virtio_transport_dec_rx_pkt(vvs, pkt_len);
__skb_unlink(skb, &vvs->rx_queue);
consume_skb(skb);
} else {
__skb_queue_head(&vvs->rx_queue, skb);
}
}

Expand Down Expand Up @@ -437,17 +435,17 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,

while (!msg_ready) {
struct virtio_vsock_hdr *hdr;
size_t pkt_len;

skb = __skb_dequeue(&vvs->rx_queue);
if (!skb)
break;
hdr = virtio_vsock_hdr(skb);
pkt_len = (size_t)le32_to_cpu(hdr->len);

if (dequeued_len >= 0) {
size_t pkt_len;
size_t bytes_to_copy;

pkt_len = (size_t)le32_to_cpu(hdr->len);
bytes_to_copy = min(user_buf_len, pkt_len);

if (bytes_to_copy) {
Expand All @@ -466,7 +464,6 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
dequeued_len = err;
} else {
user_buf_len -= bytes_to_copy;
skb_pull(skb, bytes_to_copy);
}

spin_lock_bh(&vvs->rx_lock);
Expand All @@ -484,7 +481,7 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
msg->msg_flags |= MSG_EOR;
}

virtio_transport_dec_rx_pkt(vvs, skb);
virtio_transport_dec_rx_pkt(vvs, pkt_len);
kfree_skb(skb);
}

Expand Down Expand Up @@ -1040,7 +1037,7 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk,

spin_lock_bh(&vvs->rx_lock);

can_enqueue = virtio_transport_inc_rx_pkt(vvs, skb);
can_enqueue = virtio_transport_inc_rx_pkt(vvs, len);
if (!can_enqueue) {
free_pkt = true;
goto out;
Expand Down
118 changes: 118 additions & 0 deletions tools/testing/vsock/vsock_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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,
},
{},
};

Expand Down

0 comments on commit 1a200b5

Please sign in to comment.