0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <stdint.h>
0010 #include <fcntl.h>
0011 #include <errno.h>
0012 #include <sys/ioctl.h>
0013 #include <sys/mman.h>
0014
0015 #include <asm/uvdevice.h>
0016
0017 #include "../../../kselftest_harness.h"
0018
0019 #define UV_PATH "/dev/uv"
0020 #define BUFFER_SIZE 0x200
0021 FIXTURE(uvio_fixture) {
0022 int uv_fd;
0023 struct uvio_ioctl_cb uvio_ioctl;
0024 uint8_t buffer[BUFFER_SIZE];
0025 __u64 fault_page;
0026 };
0027
0028 FIXTURE_VARIANT(uvio_fixture) {
0029 unsigned long ioctl_cmd;
0030 uint32_t arg_size;
0031 };
0032
0033 FIXTURE_VARIANT_ADD(uvio_fixture, att) {
0034 .ioctl_cmd = UVIO_IOCTL_ATT,
0035 .arg_size = sizeof(struct uvio_attest),
0036 };
0037
0038 FIXTURE_SETUP(uvio_fixture)
0039 {
0040 self->uv_fd = open(UV_PATH, O_ACCMODE);
0041
0042 self->uvio_ioctl.argument_addr = (__u64)self->buffer;
0043 self->uvio_ioctl.argument_len = variant->arg_size;
0044 self->fault_page =
0045 (__u64)mmap(NULL, (size_t)getpagesize(), PROT_NONE, MAP_ANONYMOUS, -1, 0);
0046 }
0047
0048 FIXTURE_TEARDOWN(uvio_fixture)
0049 {
0050 if (self->uv_fd)
0051 close(self->uv_fd);
0052 munmap((void *)self->fault_page, (size_t)getpagesize());
0053 }
0054
0055 TEST_F(uvio_fixture, fault_ioctl_arg)
0056 {
0057 int rc, errno_cache;
0058
0059 rc = ioctl(self->uv_fd, variant->ioctl_cmd, NULL);
0060 errno_cache = errno;
0061 ASSERT_EQ(rc, -1);
0062 ASSERT_EQ(errno_cache, EFAULT);
0063
0064 rc = ioctl(self->uv_fd, variant->ioctl_cmd, self->fault_page);
0065 errno_cache = errno;
0066 ASSERT_EQ(rc, -1);
0067 ASSERT_EQ(errno_cache, EFAULT);
0068 }
0069
0070 TEST_F(uvio_fixture, fault_uvio_arg)
0071 {
0072 int rc, errno_cache;
0073
0074 self->uvio_ioctl.argument_addr = 0;
0075 rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);
0076 errno_cache = errno;
0077 ASSERT_EQ(rc, -1);
0078 ASSERT_EQ(errno_cache, EFAULT);
0079
0080 self->uvio_ioctl.argument_addr = self->fault_page;
0081 rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);
0082 errno_cache = errno;
0083 ASSERT_EQ(rc, -1);
0084 ASSERT_EQ(errno_cache, EFAULT);
0085 }
0086
0087
0088
0089
0090
0091 TEST_F(uvio_fixture, inval_ioctl_cb)
0092 {
0093 int rc, errno_cache;
0094
0095 self->uvio_ioctl.argument_len = 0;
0096 rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);
0097 errno_cache = errno;
0098 ASSERT_EQ(rc, -1);
0099 ASSERT_EQ(errno_cache, EINVAL);
0100
0101 self->uvio_ioctl.argument_len = (uint32_t)-1;
0102 rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);
0103 errno_cache = errno;
0104 ASSERT_EQ(rc, -1);
0105 ASSERT_EQ(errno_cache, EINVAL);
0106 self->uvio_ioctl.argument_len = variant->arg_size;
0107
0108 self->uvio_ioctl.flags = (uint32_t)-1;
0109 rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);
0110 errno_cache = errno;
0111 ASSERT_EQ(rc, -1);
0112 ASSERT_EQ(errno_cache, EINVAL);
0113 self->uvio_ioctl.flags = 0;
0114
0115 memset(self->uvio_ioctl.reserved14, 0xff, sizeof(self->uvio_ioctl.reserved14));
0116 rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);
0117 errno_cache = errno;
0118 ASSERT_EQ(rc, -1);
0119 ASSERT_EQ(errno_cache, EINVAL);
0120
0121 memset(&self->uvio_ioctl, 0x11, sizeof(self->uvio_ioctl));
0122 rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl);
0123 ASSERT_EQ(rc, -1);
0124 }
0125
0126 TEST_F(uvio_fixture, inval_ioctl_cmd)
0127 {
0128 int rc, errno_cache;
0129 uint8_t nr = _IOC_NR(variant->ioctl_cmd);
0130 unsigned long cmds[] = {
0131 _IOWR('a', nr, struct uvio_ioctl_cb),
0132 _IOWR(UVIO_TYPE_UVC, nr, int),
0133 _IO(UVIO_TYPE_UVC, nr),
0134 _IOR(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb),
0135 _IOW(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb),
0136 };
0137
0138 for (size_t i = 0; i < ARRAY_SIZE(cmds); i++) {
0139 rc = ioctl(self->uv_fd, cmds[i], &self->uvio_ioctl);
0140 errno_cache = errno;
0141 ASSERT_EQ(rc, -1);
0142 ASSERT_EQ(errno_cache, ENOTTY);
0143 }
0144 }
0145
0146 struct test_attest_buffer {
0147 uint8_t arcb[0x180];
0148 uint8_t meas[64];
0149 uint8_t add[32];
0150 };
0151
0152 FIXTURE(attest_fixture) {
0153 int uv_fd;
0154 struct uvio_ioctl_cb uvio_ioctl;
0155 struct uvio_attest uvio_attest;
0156 struct test_attest_buffer attest_buffer;
0157 __u64 fault_page;
0158 };
0159
0160 FIXTURE_SETUP(attest_fixture)
0161 {
0162 self->uv_fd = open(UV_PATH, O_ACCMODE);
0163
0164 self->uvio_ioctl.argument_addr = (__u64)&self->uvio_attest;
0165 self->uvio_ioctl.argument_len = sizeof(self->uvio_attest);
0166
0167 self->uvio_attest.arcb_addr = (__u64)&self->attest_buffer.arcb;
0168 self->uvio_attest.arcb_len = sizeof(self->attest_buffer.arcb);
0169
0170 self->uvio_attest.meas_addr = (__u64)&self->attest_buffer.meas;
0171 self->uvio_attest.meas_len = sizeof(self->attest_buffer.meas);
0172
0173 self->uvio_attest.add_data_addr = (__u64)&self->attest_buffer.add;
0174 self->uvio_attest.add_data_len = sizeof(self->attest_buffer.add);
0175 self->fault_page =
0176 (__u64)mmap(NULL, (size_t)getpagesize(), PROT_NONE, MAP_ANONYMOUS, -1, 0);
0177 }
0178
0179 FIXTURE_TEARDOWN(attest_fixture)
0180 {
0181 if (self->uv_fd)
0182 close(self->uv_fd);
0183 munmap((void *)self->fault_page, (size_t)getpagesize());
0184 }
0185
0186 static void att_inval_sizes_test(uint32_t *size, uint32_t max_size, bool test_zero,
0187 struct __test_metadata *_metadata,
0188 FIXTURE_DATA(attest_fixture) *self)
0189 {
0190 int rc, errno_cache;
0191 uint32_t tmp = *size;
0192
0193 if (test_zero) {
0194 *size = 0;
0195 rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);
0196 errno_cache = errno;
0197 ASSERT_EQ(rc, -1);
0198 ASSERT_EQ(errno_cache, EINVAL);
0199 }
0200 *size = max_size + 1;
0201 rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);
0202 errno_cache = errno;
0203 ASSERT_EQ(rc, -1);
0204 ASSERT_EQ(errno_cache, EINVAL);
0205 *size = tmp;
0206 }
0207
0208
0209
0210
0211
0212 TEST_F(attest_fixture, att_inval_request)
0213 {
0214 int rc, errno_cache;
0215
0216 att_inval_sizes_test(&self->uvio_attest.add_data_len, UVIO_ATT_ADDITIONAL_MAX_LEN,
0217 false, _metadata, self);
0218 att_inval_sizes_test(&self->uvio_attest.meas_len, UVIO_ATT_MEASUREMENT_MAX_LEN,
0219 true, _metadata, self);
0220 att_inval_sizes_test(&self->uvio_attest.arcb_len, UVIO_ATT_ARCB_MAX_LEN,
0221 true, _metadata, self);
0222
0223 self->uvio_attest.reserved136 = (uint16_t)-1;
0224 rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);
0225 errno_cache = errno;
0226 ASSERT_EQ(rc, -1);
0227 ASSERT_EQ(errno_cache, EINVAL);
0228
0229 memset(&self->uvio_attest, 0x11, sizeof(self->uvio_attest));
0230 rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);
0231 ASSERT_EQ(rc, -1);
0232 }
0233
0234 static void att_inval_addr_test(__u64 *addr, struct __test_metadata *_metadata,
0235 FIXTURE_DATA(attest_fixture) *self)
0236 {
0237 int rc, errno_cache;
0238 __u64 tmp = *addr;
0239
0240 *addr = 0;
0241 rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);
0242 errno_cache = errno;
0243 ASSERT_EQ(rc, -1);
0244 ASSERT_EQ(errno_cache, EFAULT);
0245 *addr = self->fault_page;
0246 rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl);
0247 errno_cache = errno;
0248 ASSERT_EQ(rc, -1);
0249 ASSERT_EQ(errno_cache, EFAULT);
0250 *addr = tmp;
0251 }
0252
0253 TEST_F(attest_fixture, att_inval_addr)
0254 {
0255 att_inval_addr_test(&self->uvio_attest.arcb_addr, _metadata, self);
0256 att_inval_addr_test(&self->uvio_attest.add_data_addr, _metadata, self);
0257 att_inval_addr_test(&self->uvio_attest.meas_addr, _metadata, self);
0258 }
0259
0260 static void __attribute__((constructor)) __constructor_order_last(void)
0261 {
0262 if (!__constructor_order)
0263 __constructor_order = _CONSTRUCTOR_ORDER_BACKWARD;
0264 }
0265
0266 int main(int argc, char **argv)
0267 {
0268 int fd = open(UV_PATH, O_ACCMODE);
0269
0270 if (fd < 0)
0271 ksft_exit_skip("No uv-device or cannot access " UV_PATH "\n"
0272 "Enable CONFIG_S390_UV_UAPI and check the access rights on "
0273 UV_PATH ".\n");
0274 close(fd);
0275 return test_harness_run(argc, argv);
0276 }