/** * vtpmx_ioc_new_dev - handler for the %VTPM_PROXY_IOC_NEW_DEV ioctl * @file: /dev/vtpmx * @ioctl: the ioctl number * @arg: pointer to the struct vtpmx_proxy_new_dev * * Creates an anonymous file that is used by the process acting as a TPM to * communicate with the client processes. The function will also add a new TPM * device through which data is proxied to this TPM acting process. The caller * will be provided with a file descriptor to communicate with the clients and * major and minor numbers for the TPM device. */ static long vtpmx_ioc_new_dev(struct file *file, unsigned int ioctl, unsigned long arg) { void __user *argp = (void __user *)arg; struct vtpm_proxy_new_dev __user *vtpm_new_dev_p; struct vtpm_proxy_new_dev vtpm_new_dev; struct file *vtpm_file; if (!capable(CAP_SYS_ADMIN)) return -EPERM; vtpm_new_dev_p = argp; if (copy_from_user(&vtpm_new_dev, vtpm_new_dev_p, sizeof(vtpm_new_dev))) return -EFAULT; vtpm_file = vtpm_proxy_create_device(&vtpm_new_dev); if (IS_ERR(vtpm_file)) return PTR_ERR(vtpm_file); if (copy_to_user(vtpm_new_dev_p, &vtpm_new_dev, sizeof(vtpm_new_dev))) { put_unused_fd(vtpm_new_dev.fd); fput(vtpm_file); return -EFAULT; } fd_install(vtpm_new_dev.fd, vtpm_file); return 0; }
/* * vtpmx_fops_ioctl: ioctl on /dev/vtpmx * * Return value: * Returns 0 on success, a negative error code otherwise. */ static long vtpmx_fops_ioctl(struct file *f, unsigned int ioctl, unsigned long arg) { void __user *argp = (void __user *)arg; struct vtpm_proxy_new_dev __user *vtpm_new_dev_p; struct vtpm_proxy_new_dev vtpm_new_dev; struct file *file; switch (ioctl) { case VTPM_PROXY_IOC_NEW_DEV: if (!capable(CAP_SYS_ADMIN)) return -EPERM; vtpm_new_dev_p = argp; if (copy_from_user(&vtpm_new_dev, vtpm_new_dev_p, sizeof(vtpm_new_dev))) return -EFAULT; file = vtpm_proxy_create_device(&vtpm_new_dev); if (IS_ERR(file)) return PTR_ERR(file); if (copy_to_user(vtpm_new_dev_p, &vtpm_new_dev, sizeof(vtpm_new_dev))) { put_unused_fd(vtpm_new_dev.fd); fput(file); return -EFAULT; } fd_install(vtpm_new_dev.fd, file); return 0; default: return -ENOIOCTLCMD; } }