1
0

Merge tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd

Pull iommufd fixes from Jason Gunthorpe:
 "Some changes to the userspace selftest framework cause the iommufd
  tests to start failing. This turned out to be bugs in the iommufd side
  that were just getting uncovered.

   - Deal with MAP_HUGETLB mmaping more than requested even when in
     MAP_FIXED mode

   - Fixup missing error flow cleanup in the test

   - Check that the memory allocations suceeded

   - Suppress some bogus gcc 'may be used uninitialized' warnings"

* tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd:
  iommufd/selftest: Fix build warnings due to uninitialized mfd
  iommufd/selftest: Add asserts testing global mfd
  iommufd/selftest: Add missing close(mfd) in memfd_mmap()
  iommufd/selftest: Fix iommufd_dirty_tracking with large hugepage sizes
This commit is contained in:
Linus Torvalds
2025-07-02 09:23:56 -07:00
2 changed files with 36 additions and 13 deletions

View File

@@ -54,6 +54,8 @@ static __attribute__((constructor)) void setup_sizes(void)
mfd_buffer = memfd_mmap(BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
&mfd);
assert(mfd_buffer != MAP_FAILED);
assert(mfd > 0);
}
FIXTURE(iommufd)
@@ -1746,13 +1748,15 @@ TEST_F(iommufd_mock_domain, all_aligns)
unsigned int end;
uint8_t *buf;
int prot = PROT_READ | PROT_WRITE;
int mfd;
int mfd = -1;
if (variant->file)
buf = memfd_mmap(buf_size, prot, MAP_SHARED, &mfd);
else
buf = mmap(0, buf_size, prot, self->mmap_flags, -1, 0);
ASSERT_NE(MAP_FAILED, buf);
if (variant->file)
ASSERT_GT(mfd, 0);
check_refs(buf, buf_size, 0);
/*
@@ -1798,13 +1802,15 @@ TEST_F(iommufd_mock_domain, all_aligns_copy)
unsigned int end;
uint8_t *buf;
int prot = PROT_READ | PROT_WRITE;
int mfd;
int mfd = -1;
if (variant->file)
buf = memfd_mmap(buf_size, prot, MAP_SHARED, &mfd);
else
buf = mmap(0, buf_size, prot, self->mmap_flags, -1, 0);
ASSERT_NE(MAP_FAILED, buf);
if (variant->file)
ASSERT_GT(mfd, 0);
check_refs(buf, buf_size, 0);
/*
@@ -2008,6 +2014,7 @@ FIXTURE_VARIANT(iommufd_dirty_tracking)
FIXTURE_SETUP(iommufd_dirty_tracking)
{
size_t mmap_buffer_size;
unsigned long size;
int mmap_flags;
void *vrc;
@@ -2022,22 +2029,33 @@ FIXTURE_SETUP(iommufd_dirty_tracking)
self->fd = open("/dev/iommu", O_RDWR);
ASSERT_NE(-1, self->fd);
rc = posix_memalign(&self->buffer, HUGEPAGE_SIZE, variant->buffer_size);
if (rc || !self->buffer) {
SKIP(return, "Skipping buffer_size=%lu due to errno=%d",
variant->buffer_size, rc);
}
mmap_flags = MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED;
mmap_buffer_size = variant->buffer_size;
if (variant->hugepages) {
/*
* MAP_POPULATE will cause the kernel to fail mmap if THPs are
* not available.
*/
mmap_flags |= MAP_HUGETLB | MAP_POPULATE;
/*
* Allocation must be aligned to the HUGEPAGE_SIZE, because the
* following mmap() will automatically align the length to be a
* multiple of the underlying huge page size. Failing to do the
* same at this allocation will result in a memory overwrite by
* the mmap().
*/
if (mmap_buffer_size < HUGEPAGE_SIZE)
mmap_buffer_size = HUGEPAGE_SIZE;
}
rc = posix_memalign(&self->buffer, HUGEPAGE_SIZE, mmap_buffer_size);
if (rc || !self->buffer) {
SKIP(return, "Skipping buffer_size=%lu due to errno=%d",
mmap_buffer_size, rc);
}
assert((uintptr_t)self->buffer % HUGEPAGE_SIZE == 0);
vrc = mmap(self->buffer, variant->buffer_size, PROT_READ | PROT_WRITE,
vrc = mmap(self->buffer, mmap_buffer_size, PROT_READ | PROT_WRITE,
mmap_flags, -1, 0);
assert(vrc == self->buffer);
@@ -2066,8 +2084,8 @@ FIXTURE_SETUP(iommufd_dirty_tracking)
FIXTURE_TEARDOWN(iommufd_dirty_tracking)
{
munmap(self->buffer, variant->buffer_size);
munmap(self->bitmap, DIV_ROUND_UP(self->bitmap_size, BITS_PER_BYTE));
free(self->buffer);
free(self->bitmap);
teardown_iommufd(self->fd, _metadata);
}

View File

@@ -60,13 +60,18 @@ static inline void *memfd_mmap(size_t length, int prot, int flags, int *mfd_p)
{
int mfd_flags = (flags & MAP_HUGETLB) ? MFD_HUGETLB : 0;
int mfd = memfd_create("buffer", mfd_flags);
void *buf = MAP_FAILED;
if (mfd <= 0)
return MAP_FAILED;
if (ftruncate(mfd, length))
return MAP_FAILED;
goto out;
*mfd_p = mfd;
return mmap(0, length, prot, flags, mfd, 0);
buf = mmap(0, length, prot, flags, mfd, 0);
out:
if (buf == MAP_FAILED)
close(mfd);
return buf;
}
/*