diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/Makefile | 6 | ||||
| -rw-r--r-- | test/ring-leak.c | 108 | 
2 files changed, 112 insertions, 2 deletions
| diff --git a/test/Makefile b/test/Makefile index 1ec920d..db8b09a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,10 +1,10 @@  CFLAGS ?= -g -O2 -Wall -D_GNU_SOURCE -L../src/ -all_targets += io_uring-test io_uring-cp poll poll-cancel +all_targets += io_uring-test io_uring-cp poll poll-cancel ring-leak  all: $(all_targets) -test_srcs := io_uring-test.c io_uring-cp.c poll.c poll-cancel.c +test_srcs := io_uring-test.c io_uring-cp.c poll.c poll-cancel.c ring-leak.c  test_objs := $(patsubst %.c,%.ol,$(test_srcs)) @@ -16,5 +16,7 @@ poll: poll.c  	$(CC) $(CFLAGS) -o $@ poll.c -luring  poll-cancel: poll-cancel.c  	$(CC) $(CFLAGS) -o $@ poll-cancel.c -luring +ring-leak: ring-leak.c +	$(CC) $(CFLAGS) -o $@ ring-leak.c -luring  clean:  	rm -f $(all_targets) $(test_objs) diff --git a/test/ring-leak.c b/test/ring-leak.c new file mode 100644 index 0000000..5f12ac7 --- /dev/null +++ b/test/ring-leak.c @@ -0,0 +1,108 @@ +/* + * Based on description from Al Viro - this demonstrates a leak of the + * io_uring instance, by sending the io_uring fd over a UNIX socket. + * + * See: + * + * https://lore.kernel.org/linux-block/20190129192702.3605-1-axboe@kernel.dk/T/#m6c87fc64e4d063786af6ec6fadce3ac1e95d3184 + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <signal.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/syscall.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <linux/fs.h> + +#include "../src/liburing.h" + +static int io_uring_register_files(int ring_fd, int fd1, int fd2) +{ +	__s32 *fds; + +	fds = calloc(2, sizeof(__s32)); +	fds[0] = fd1; +	fds[1] = fd2; + +	return io_uring_register(ring_fd, IORING_REGISTER_FILES, fds, 2); +} + +static int get_ring_fd(void) +{ +	struct io_uring_params p; +	int fd; + +	memset(&p, 0, sizeof(p)); + +	fd = io_uring_setup(2, &p); +	if (fd < 0) { +		perror("io_uring_setup"); +		return -1; +	} + +	return fd; +} + +static void send_fd(int socket, int fd) +{ +	char buf[CMSG_SPACE(sizeof(fd))]; +	struct cmsghdr *cmsg; +	struct msghdr msg; + +	memset(buf, 0, sizeof(buf)); +	memset(&msg, 0, sizeof(msg)); + +	msg.msg_control = buf; +	msg.msg_controllen = sizeof(buf); + +	cmsg = CMSG_FIRSTHDR(&msg); +	cmsg->cmsg_level = SOL_SOCKET; +	cmsg->cmsg_type = SCM_RIGHTS; +	cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); + +	memmove(CMSG_DATA(cmsg), &fd, sizeof(fd)); + +	msg.msg_controllen = CMSG_SPACE(sizeof(fd)); + +	if (sendmsg(socket, &msg, 0) < 0) +		perror("sendmsg"); +} + +int main(int argc, char *argv[]) +{ +	int sp[2], pid, ring_fd, ret; + +	if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sp) != 0) { +		perror("Failed to create Unix-domain socket pair\n"); +		return 1; +	} + +	ring_fd = get_ring_fd(); +	if (ring_fd < 0) +		return 1; + +	ret = io_uring_register_files(ring_fd, sp[0], sp[1]); +	if (ret < 0) { +		perror("register files"); +		return 1; +	} + +	pid = fork(); +	if (pid) { +		printf("Sending fd %d\n", ring_fd); + +		send_fd(sp[0], ring_fd); +	} + +	close(ring_fd); +	close(sp[0]); +	close(sp[1]); +	return 0; +} | 
