Re: [RFC PATCH] security,anon_inodes,kvm: enable security support for anon inodes

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

 



On 2/13/20 2:41 PM, Stephen Smalley wrote:
An example of a sample program and policy will follow in a follow-up
to this patch to demonstrate the effect on userfaultfd and kvm.

Attached are example test programs and policies to demonstrate the change in behavior before and after this RFC patch for userfaultfd and kvm. The test policies can be edited to selectively allow specific permissions for testing various scenarios, but with the defaults in them, one should see the following behavior:

sudo semodule -i kvm.cil userfaultfd.cil
make kvm userfaultfd

Before:

(no labeling/access control applied by SELinux to userfaultfd files or to anon inodes created by kvm)

$ ./userfaultfd
api: 170
features: 510
ioctls: 9223372036854775811

read: Resource temporarily unavailable

$ ./kvm
api version: 12

created vm

created vcpu

rax: 0
rbx: 0
rcx: 0
rdx: 1536
rdi: 0
rsi: 0
rsp: 0
rbp: 0
r8: 0
r9: 0
r10: 0
r11: 0
r12: 0
r13: 0
r14: 0
r15: 0
rip: 65520
rflags: 2

created device

checked device attr

After:

(SELinux ioctl whitelisting used to selectively deny access)

./userfaultfd
UFFDIO_API: Permission denied

$ ./kvm
api version: 12

created vm

created vcpu

KVM_GET_REGS: Permission denied

Attachment: kvm.cil
Description: application/vnd.ms-artgalry

Attachment: userfaultfd.cil
Description: application/vnd.ms-artgalry

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/kvm.h>

void print_regs(const struct kvm_regs *regs)
{
	printf("rax: %llu\n", regs->rax);
	printf("rbx: %llu\n", regs->rbx);
	printf("rcx: %llu\n", regs->rcx);
	printf("rdx: %llu\n", regs->rdx);
	printf("rdi: %llu\n", regs->rdi);
	printf("rsi: %llu\n", regs->rsi);
	printf("rsp: %llu\n", regs->rsp);
	printf("rbp: %llu\n", regs->rbp);
	printf("r8: %llu\n", regs->r8);
	printf("r9: %llu\n", regs->r9);
	printf("r10: %llu\n", regs->r10);
	printf("r11: %llu\n", regs->r11);
	printf("r12: %llu\n", regs->r12);
	printf("r13: %llu\n", regs->r13);
	printf("r14: %llu\n", regs->r14);
	printf("r15: %llu\n", regs->r15);
	printf("rip: %llu\n", regs->rip);
	printf("rflags: %llu\n", regs->rflags);

	printf("\n");
}

void print_device_attr(const struct kvm_device_attr *dev_attr)
{
	printf("flags: %u\n", dev_attr->flags);
	printf("group: %u\n", dev_attr->group);
	printf("attr: %llu\n", dev_attr->attr);
	printf("addr: %llu\n", dev_attr->addr);

	printf("\n");
}

int main(void)
{
	int fd = open("/dev/kvm", O_RDWR);
	if (fd < 0) {
		perror("/dev/kvm");
		return -1;
	}

	int ret = ioctl(fd, KVM_GET_API_VERSION, 0);
	if (ret < 0) {
		perror("KVM_GET_API_VERSION");
		return -1;
	}

	printf("api version: %d\n\n", ret);

	int vmfd = ioctl(fd, KVM_CREATE_VM, 0);
	if (vmfd < 0) {
		perror("KVM_CREATE_VM");
		return -1;
	}

	printf("created vm\n\n");

	int vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0);
	if (vcpufd < 0) {
		perror("KVM_CREATE_VCPU");
		return -1;
	}

	printf("created vcpu\n\n");

	struct kvm_regs regs;
	if (ioctl(vcpufd, KVM_GET_REGS, &regs) < 0) {
		perror("KVM_GET_REGS");
		return -1;
	}

	print_regs(&regs);

	struct kvm_create_device dev = {0};
	dev.type = KVM_DEV_TYPE_VFIO;

	if (ioctl(vmfd, KVM_CREATE_DEVICE, &dev) < 0) {
		perror("KVM_CREATE_DEVICE");
		return -1;
	}

	printf("created device\n\n");

	struct kvm_device_attr dev_attr = {0};
	dev_attr.group = KVM_DEV_VFIO_GROUP;
	dev_attr.attr = KVM_DEV_VFIO_GROUP_ADD;
	if (ioctl(dev.fd, KVM_HAS_DEVICE_ATTR, &dev_attr) < 0) {
		perror("KVM_HAS_DEVICE_ATTR");
		return -1;
	}

	printf("checked device attr\n\n");

	return 0;
}
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>

#include <linux/userfaultfd.h>

void print_api(const struct uffdio_api *api)
{
	printf("api: %llu\n", api->api);
	printf("features: %llu\n", api->features);
	printf("ioctls: %llu\n", api->ioctls);

	printf("\n");
}

int main(void)
{
	long uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
	if (uffd < 0) {
		perror("syscall(userfaultfd)");
		return -1;
	}

	struct uffdio_api api = {0};
	api.api = UFFD_API;
	if (ioctl(uffd, UFFDIO_API, &api) < 0) {
		perror("UFFDIO_API");
		return -1;
	}

	print_api(&api);

	struct uffd_msg msg = {0};
	ssize_t count = read(uffd, &msg, sizeof(msg));
	if (count < 0) {
		perror("read");
		return -1;
	} else if (count == 0) {
		printf("read EOF\n\n");
	}

	printf("read uffd\n\n");

	return 0;
}

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux