Re: [PATCH v2 1/2] KVM: arm64: Filter out invalid core register IDs in KVM_GET_REG_LIST

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Dec 14, 2018 at 02:41:21PM +0000, Dave Martin wrote:
> On Fri, Dec 14, 2018 at 03:25:45PM +0100, Andrew Jones wrote:
> > 
> > Hi Dave,
> > 
> > The below looks like a nice kvm selftest. Care to fit it into that
> > framework (tools/testing/selftests/kvm/) and post it?
> 
> Sure, it makes sense not to drop this on the floor.  Do you feel the
> test needs to go in alongside the fix, or is it alright if I repost this
> later on?

I'm fine with it getting posted whenever. I'll just be happy that it gets
posted :-)

Thanks,
drew

> 
> It will need a bit of cleanup, and I'm juggling other stuff too...
> 
> Cheers
> ---Dave
> 
> > 
> > Thanks,
> > drew
> > 
> > > [1]
> > > 
> > > #include <assert.h>
> > > #include <errno.h>
> > > #include <limits.h>
> > > #include <stddef.h>
> > > #include <stdio.h>
> > > #include <stdlib.h>
> > > #include <stdint.h>
> > > #include <string.h>
> > > #include <fcntl.h>
> > > #include <sys/ioctl.h>
> > > #include <linux/kvm.h>
> > > 
> > > #define KVM_PATH "/dev/kvm"
> > > 
> > > #define ARRAY_SIZE(array) (sizeof (array) / sizeof *(array))
> > > 
> > > static int get_reg_list(int vcpu, struct kvm_reg_list **pregs, size_t *psize)
> > > {
> > > 	struct kvm_reg_list *regs = *pregs;
> > > 	size_t num_needed = 0;
> > > 	const size_t reg_offset = (char *)&regs->reg - (char *)regs;
> > > 
> > > 	while (1) {
> > > 		size_t size_needed = num_needed * sizeof regs->reg[0]
> > > 					+ reg_offset;
> > > 		if (size_needed > *psize) {
> > > 			regs = realloc(regs, size_needed);
> > > 			if (!regs)
> > > 				goto nomem;
> > > 
> > > 			*pregs = regs;
> > > 			*psize = size_needed;
> > > 		}
> > > 
> > > 		regs->n = (*psize - reg_offset) / sizeof regs->reg[0];
> > > 		if (!ioctl(vcpu, KVM_GET_REG_LIST, regs))
> > > 			break;
> > > 
> > > 		if (errno != E2BIG) {
> > > 			perror("KVM_GET_REG_LIST");
> > > 			goto error;
> > > 		}
> > > 
> > > 		num_needed = regs->n;
> > > 	}
> > > 
> > > 	return 0;	
> > > 
> > > nomem:
> > > 	errno = ENOMEM;
> > > 	perror(NULL);
> > > error:
> > > 	return -1;
> > > }
> > > 
> > > int main(void)
> > > {
> > > 	int fail = 0;
> > > 	int kvm_fd, vm, vcpu;
> > > 	struct kvm_vcpu_init init;
> > > 	size_t i;
> > > 	struct kvm_reg_list *regs = NULL;
> > > 	size_t regs_size = 0;
> > > 	uint64_t regdata[2];
> > > 	struct kvm_one_reg reg;
> > > 
> > > 	kvm_fd = open(KVM_PATH, O_RDWR);
> > > 	if (kvm_fd == -1) {
> > > 		perror(KVM_PATH);
> > > 		goto error;
> > > 	}
> > > 
> > > 	vm = ioctl(kvm_fd, KVM_CREATE_VM, 0);
> > > 	if (vm == -1) {
> > > 		perror("KVM_CREATE_VM");
> > > 		goto error;
> > > 	}
> > > 
> > > 	if (ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init)) {
> > > 		perror("KVM_ARM_PREFERRED_TARGET");
> > > 		goto error;
> > > 	}
> > > 
> > > 	printf("KVM_ARM_PREFERRED_TARGET:\n"
> > > 	       "\ttarget = %lu\n",
> > > 	       (unsigned long)init.target);
> > > 	for (i = 0; i < ARRAY_SIZE(init.features); ++i)
> > > 		printf("\tfeatures[0] = 0x%.8lx\n",
> > > 		       (unsigned long)init.features[i]);
> > > 	
> > > 	vcpu = ioctl(vm, KVM_CREATE_VCPU, 0);
> > > 	if (vcpu == -1) {
> > > 		perror("KVM_CREATE_VCPU");
> > > 		goto error;
> > > 	}
> > > 
> > > 	if (!get_reg_list(vcpu, &regs, &regs_size)) {
> > > 		fputs("Strange, KVM_GET_REG_LIST succeeded before KVM_VCPU_INIT!\n",
> > > 		      stderr);
> > > 			
> > > 		goto error;
> > > 	}
> > > 
> > > 	if (ioctl(vcpu, KVM_ARM_VCPU_INIT, &init)) {
> > > 		perror("KVM_ARM_VCPU_INIT");
> > > 		goto error;
> > > 	}
> > > 
> > > 	if (get_reg_list(vcpu, &regs, &regs_size))
> > > 		goto error;
> > > 
> > > 	assert(1 <= -1ULL >> 32);
> > > 	assert(ULONG_MAX >= (1ULL << 32) - 1);
> > > 	for (i = 0; i < regs->n; ++i) {
> > > 		size_t size;
> > > 		char const *s1 = "OK", *s2 = "", *s3 = "";;
> > > 
> > > 		size = (size_t)1 << ((regs->reg[i] & KVM_REG_SIZE_MASK) >>
> > > 				     KVM_REG_SIZE_SHIFT);
> > > 		if (size < 4 || size > 16) {
> > > 			s1 = "BADSIZE";
> > > 			fail = 1;
> > > 		} else {
> > > 			memset(&reg, 0, sizeof reg);
> > > 
> > > 			reg.id = regs->reg[i];
> > > 			reg.addr = (__u64)&regdata;
> > > 			if (ioctl(vcpu, KVM_GET_ONE_REG, &reg)) {
> > > 				s1 = "FAIL (";
> > > 				s2 = strerror(errno);
> > > 				s3 = ")";
> > > 				fail = 1;
> > > 			}
> > > 		}
> > > 
> > > 		printf("\t0x%.16lx\t%s%s%s\n",
> > > 		       (unsigned long)reg.id, s1, s2, s3);
> > > 	
> > > 	}
> > > 
> > > 	if (ferror(stdout) || fflush(stdout))
> > > 		goto stdout_error;
> > > 	
> > > 	if (fail) {
> > > 		puts("FAIL");
> > > 		goto error;
> > > 	}
> > > 
> > > 	if (puts("\nPASS") == EOF || fclose(stdout))
> > > 		goto stdout_error;
> > > 
> > > 	return EXIT_SUCCESS;
> > > 
> > > stdout_error:
> > > 	fputs("I/O error", stderr);
> > > error:
> > > 	return EXIT_FAILURE;
> > > }
> > > _______________________________________________
> > > kvmarm mailing list
> > > kvmarm@xxxxxxxxxxxxxxxxxxxxx
> > > https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
> > _______________________________________________
> > kvmarm mailing list
> > kvmarm@xxxxxxxxxxxxxxxxxxxxx
> > https://lists.cs.columbia.edu/mailman/listinfo/kvmarm



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux