[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.