Path: blob/master/tools/testing/selftests/drivers/s390x/uvdevice/test_uvdevice.c
26292 views
// SPDX-License-Identifier: GPL-2.01/*2* selftest for the Ultravisor UAPI device3*4* Copyright IBM Corp. 20225* Author(s): Steffen Eiden <[email protected]>6*/78#include <stdint.h>9#include <fcntl.h>10#include <errno.h>11#include <sys/ioctl.h>12#include <sys/mman.h>1314#include <asm/uvdevice.h>1516#include "../../../kselftest_harness.h"1718#define UV_PATH "/dev/uv"19#define BUFFER_SIZE 0x20020FIXTURE(uvio_fixture) {21int uv_fd;22struct uvio_ioctl_cb uvio_ioctl;23uint8_t buffer[BUFFER_SIZE];24__u64 fault_page;25};2627FIXTURE_VARIANT(uvio_fixture) {28unsigned long ioctl_cmd;29uint32_t arg_size;30};3132FIXTURE_VARIANT_ADD(uvio_fixture, att) {33.ioctl_cmd = UVIO_IOCTL_ATT,34.arg_size = sizeof(struct uvio_attest),35};3637FIXTURE_SETUP(uvio_fixture)38{39self->uv_fd = open(UV_PATH, O_ACCMODE);4041self->uvio_ioctl.argument_addr = (__u64)self->buffer;42self->uvio_ioctl.argument_len = variant->arg_size;43self->fault_page =44(__u64)mmap(NULL, (size_t)getpagesize(), PROT_NONE, MAP_ANONYMOUS, -1, 0);45}4647FIXTURE_TEARDOWN(uvio_fixture)48{49if (self->uv_fd)50close(self->uv_fd);51munmap((void *)self->fault_page, (size_t)getpagesize());52}5354TEST_F(uvio_fixture, fault_ioctl_arg)55{56int rc, errno_cache;5758rc = ioctl(self->uv_fd, variant->ioctl_cmd, NULL);59errno_cache = errno;60ASSERT_EQ(rc, -1);61ASSERT_EQ(errno_cache, EFAULT);6263rc = ioctl(self->uv_fd, variant->ioctl_cmd, self->fault_page);64errno_cache = errno;65ASSERT_EQ(rc, -1);66ASSERT_EQ(errno_cache, EFAULT);67}6869TEST_F(uvio_fixture, fault_uvio_arg)70{71int rc, errno_cache;7273self->uvio_ioctl.argument_addr = 0;74rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);75errno_cache = errno;76ASSERT_EQ(rc, -1);77ASSERT_EQ(errno_cache, EFAULT);7879self->uvio_ioctl.argument_addr = self->fault_page;80rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);81errno_cache = errno;82ASSERT_EQ(rc, -1);83ASSERT_EQ(errno_cache, EFAULT);84}8586/*87* Test to verify that IOCTLs with invalid values in the ioctl_control block88* are rejected.89*/90TEST_F(uvio_fixture, inval_ioctl_cb)91{92int rc, errno_cache;9394self->uvio_ioctl.argument_len = 0;95rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);96errno_cache = errno;97ASSERT_EQ(rc, -1);98ASSERT_EQ(errno_cache, EINVAL);99100self->uvio_ioctl.argument_len = (uint32_t)-1;101rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);102errno_cache = errno;103ASSERT_EQ(rc, -1);104ASSERT_EQ(errno_cache, EINVAL);105self->uvio_ioctl.argument_len = variant->arg_size;106107self->uvio_ioctl.flags = (uint32_t)-1;108rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);109errno_cache = errno;110ASSERT_EQ(rc, -1);111ASSERT_EQ(errno_cache, EINVAL);112self->uvio_ioctl.flags = 0;113114memset(self->uvio_ioctl.reserved14, 0xff, sizeof(self->uvio_ioctl.reserved14));115rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);116errno_cache = errno;117ASSERT_EQ(rc, -1);118ASSERT_EQ(errno_cache, EINVAL);119120memset(&self->uvio_ioctl, 0x11, sizeof(self->uvio_ioctl));121rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);122ASSERT_EQ(rc, -1);123}124125TEST_F(uvio_fixture, inval_ioctl_cmd)126{127int rc, errno_cache;128uint8_t nr = _IOC_NR(variant->ioctl_cmd);129unsigned long cmds[] = {130_IOWR('a', nr, struct uvio_ioctl_cb),131_IOWR(UVIO_TYPE_UVC, nr, int),132_IO(UVIO_TYPE_UVC, nr),133_IOR(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb),134_IOW(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb),135};136137for (size_t i = 0; i < ARRAY_SIZE(cmds); i++) {138rc = ioctl(self->uv_fd, cmds[i], &self->uvio_ioctl);139errno_cache = errno;140ASSERT_EQ(rc, -1);141ASSERT_EQ(errno_cache, ENOTTY);142}143}144145struct test_attest_buffer {146uint8_t arcb[0x180];147uint8_t meas[64];148uint8_t add[32];149};150151FIXTURE(attest_fixture) {152int uv_fd;153struct uvio_ioctl_cb uvio_ioctl;154struct uvio_attest uvio_attest;155struct test_attest_buffer attest_buffer;156__u64 fault_page;157};158159FIXTURE_SETUP(attest_fixture)160{161self->uv_fd = open(UV_PATH, O_ACCMODE);162163self->uvio_ioctl.argument_addr = (__u64)&self->uvio_attest;164self->uvio_ioctl.argument_len = sizeof(self->uvio_attest);165166self->uvio_attest.arcb_addr = (__u64)&self->attest_buffer.arcb;167self->uvio_attest.arcb_len = sizeof(self->attest_buffer.arcb);168169self->uvio_attest.meas_addr = (__u64)&self->attest_buffer.meas;170self->uvio_attest.meas_len = sizeof(self->attest_buffer.meas);171172self->uvio_attest.add_data_addr = (__u64)&self->attest_buffer.add;173self->uvio_attest.add_data_len = sizeof(self->attest_buffer.add);174self->fault_page =175(__u64)mmap(NULL, (size_t)getpagesize(), PROT_NONE, MAP_ANONYMOUS, -1, 0);176}177178FIXTURE_TEARDOWN(attest_fixture)179{180if (self->uv_fd)181close(self->uv_fd);182munmap((void *)self->fault_page, (size_t)getpagesize());183}184185static void att_inval_sizes_test(uint32_t *size, uint32_t max_size, bool test_zero,186struct __test_metadata *_metadata,187FIXTURE_DATA(attest_fixture) *self)188{189int rc, errno_cache;190uint32_t tmp = *size;191192if (test_zero) {193*size = 0;194rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);195errno_cache = errno;196ASSERT_EQ(rc, -1);197ASSERT_EQ(errno_cache, EINVAL);198}199*size = max_size + 1;200rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);201errno_cache = errno;202ASSERT_EQ(rc, -1);203ASSERT_EQ(errno_cache, EINVAL);204*size = tmp;205}206207/*208* Test to verify that attestation IOCTLs with invalid values in the UVIO209* attestation control block are rejected.210*/211TEST_F(attest_fixture, att_inval_request)212{213int rc, errno_cache;214215att_inval_sizes_test(&self->uvio_attest.add_data_len, UVIO_ATT_ADDITIONAL_MAX_LEN,216false, _metadata, self);217att_inval_sizes_test(&self->uvio_attest.meas_len, UVIO_ATT_MEASUREMENT_MAX_LEN,218true, _metadata, self);219att_inval_sizes_test(&self->uvio_attest.arcb_len, UVIO_ATT_ARCB_MAX_LEN,220true, _metadata, self);221222self->uvio_attest.reserved136 = (uint16_t)-1;223rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);224errno_cache = errno;225ASSERT_EQ(rc, -1);226ASSERT_EQ(errno_cache, EINVAL);227228memset(&self->uvio_attest, 0x11, sizeof(self->uvio_attest));229rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);230ASSERT_EQ(rc, -1);231}232233static void att_inval_addr_test(__u64 *addr, struct __test_metadata *_metadata,234FIXTURE_DATA(attest_fixture) *self)235{236int rc, errno_cache;237__u64 tmp = *addr;238239*addr = 0;240rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);241errno_cache = errno;242ASSERT_EQ(rc, -1);243ASSERT_EQ(errno_cache, EFAULT);244*addr = self->fault_page;245rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);246errno_cache = errno;247ASSERT_EQ(rc, -1);248ASSERT_EQ(errno_cache, EFAULT);249*addr = tmp;250}251252TEST_F(attest_fixture, att_inval_addr)253{254att_inval_addr_test(&self->uvio_attest.arcb_addr, _metadata, self);255att_inval_addr_test(&self->uvio_attest.add_data_addr, _metadata, self);256att_inval_addr_test(&self->uvio_attest.meas_addr, _metadata, self);257}258259int main(int argc, char **argv)260{261int fd = open(UV_PATH, O_ACCMODE);262263if (fd < 0)264ksft_exit_skip("No uv-device or cannot access " UV_PATH "\n"265"Enable CONFIG_S390_UV_UAPI and check the access rights on "266UV_PATH ".\n");267close(fd);268return test_harness_run(argc, argv);269}270271272