Commit 3c894cb2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 7e4a6b57 9a96876e
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -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);
}

+7 −2
Original line number Diff line number Diff line
@@ -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;
}

/*