[Bug 273626] Memory leak in ioctl nvme passthrough commands
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 273626] Memory leak in ioctl nvme passthrough commands"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 273626] Memory leak in ioctl nvme passthrough commands"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 273626] Memory leak in ioctl nvme passthrough commands"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 273626] Memory leak in ioctl nvme passthrough commands"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 273626] Memory leak in ioctl nvme passthrough commands"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 07 Sep 2023 21:36:02 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=273626 Bug ID: 273626 Summary: Memory leak in ioctl nvme passthrough commands Product: Base System Version: 13.2-STABLE Hardware: Any OS: Any Status: New Severity: Affects Some People Priority: --- Component: kern Assignee: bugs@FreeBSD.org Reporter: david.sloan@eideticom.com When running nvme passthrough commands through the ioctl interface buffers are never released from the kernel and increase the wired memory count permanently. This will eventually lead to system lockup if enough buffers are sent through the passthrough command interface. This can be replicated with C program at the end of this bug report, which will leak 512 KB of memory per execution. We have tested this on 13.2 and 15-current with the same result. On inspection of sys/dev/nvme/nvme_ctrlr.c it appears that nvme_ctrlr_passthrough_cmd() is missing a call to vunmapbuf() on exit when user buffers are mapped. Applying the diff: diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c index c4a75090174..608b738a1ff 100644 --- a/sys/dev/nvme/nvme_ctrlr.c +++ b/sys/dev/nvme/nvme_ctrlr.c @@ -1361,8 +1361,9 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, mtx_sleep(pt, mtx, PRIBIO, "nvme_pt", 0); mtx_unlock(mtx); -err: if (buf != NULL) { + vunmapbuf(buf); +err: uma_zfree(pbuf_zone, buf); PRELE(curproc); } Resolves the issue. Example program to reproduce the issue: #include <dev/nvme/nvme.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> #include <unistd.h> #define SZ_512K (512 * 1024) int nvme_read(int fd, void *data, size_t len, uint64_t pos) { // Assumes device with 512 byte lbas struct nvme_pt_command pt = { .cmd = { .opc = NVME_OPC_READ, // LBA .cdw10 = (pos / 512) & 0xffffffff, .cdw11 = (pos / 512) >> 32, // nblocks .cdw12 = len / 512 - 1, }, .buf = data, .len = len, .is_read = 1, }; return ioctl(fd, NVME_PASSTHROUGH_CMD, &pt); } int main(int argc, const char **argv) { void *buf; int rc; int fd; if (argc != 2) { fprintf(stderr, "Expected single nvme namespace argument\n"); exit(1); } fd = open(argv[1], O_RDWR); if (fd == -1) { fprintf(stderr, "error opening device %s: %m\n", argv[1]); exit(1); } rc = posix_memalign(&buf, 4096, SZ_512K); if (rc) { errno = rc; fprintf(stderr, "error allocating buffer %m\n"); exit(1); } rc = nvme_read(fd, buf, SZ_512K, 0); if (rc) { fprintf(stderr, "error reading from nvme device: %m\n"); exit(1); } free(buf); close(fd); return 0; } -- You are receiving this mail because: You are the assignee for the bug.