Пример #1
0
/**
 * kdbus_copy_from_user() - copy aligned data from user-space
 * @dest:	target buffer in kernel memory
 * @user_ptr:	user-provided source buffer
 * @size:	memory size to copy from user
 *
 * This copies @size bytes from @user_ptr into the kernel, just like
 * copy_from_user() does. But we enforce an 8-byte alignment and reject any
 * unaligned user-space pointers.
 *
 * Return: 0 on success, negative error code on failure.
 */
int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size)
{
	if (!KDBUS_IS_ALIGNED8((uintptr_t)user_ptr))
		return -EFAULT;

	if (copy_from_user(dest, user_ptr, size))
		return -EFAULT;

	return 0;
}
Пример #2
0
static long
kdbus_memfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	struct kdbus_memfile *mf = file->private_data;
	long ret = 0;

	mutex_lock(&mf->lock);
	switch (cmd) {
	case KDBUS_CMD_MEMFD_SIZE_GET: {
		u64 size = i_size_read(file_inode(mf->fp));

		if (!KDBUS_IS_ALIGNED8(arg)) {
			ret = -EFAULT;
			goto exit;
		}

		if (copy_to_user(argp, &size, sizeof(__u64))) {
			ret = -EFAULT;
			goto exit;
		}
		break;
	}

	case KDBUS_CMD_MEMFD_SIZE_SET: {
		u64 size;

		if (!KDBUS_IS_ALIGNED8(arg)) {
			ret = -EFAULT;
			goto exit;
		}

		if (copy_from_user(&size, argp, sizeof(__u64))) {
			ret = -EFAULT;
			goto exit;
		}

		/* deny a writable access to a sealed file */
		if (mf->sealed) {
			if (size == i_size_read(file_inode(mf->fp)))
				ret = -EALREADY;
			else
				ret = -EPERM;
			goto exit;
		}

		if (size != i_size_read(file_inode(mf->fp)))
			ret = vfs_truncate(&mf->fp->f_path, size);
		break;
	}

	case KDBUS_CMD_MEMFD_SEAL_GET: {
		int __user *addr = argp;

		if (put_user(mf->sealed, addr)) {
			ret = -EFAULT;
			goto exit;
		}
		break;
	}

	case KDBUS_CMD_MEMFD_SEAL_SET: {
		struct mm_struct *mm = current->mm;

		/*
		 * Make sure we have only one single user of the file
		 * before we seal, we rely on the fact there is no
		 * any other possibly writable references to the file.
		 *
		 * Protect mmap() racing against us, take mm->mmap_sem
		 * when accessing mf->sealed.
		 */
		down_read(&mm->mmap_sem);
		if (file_count(mf->fp) != 1) {
			if (mf->sealed == !!argp)
				ret = -EALREADY;
			else
				ret = -ETXTBSY;
		}

		if (ret == 0)
			mf->sealed = !!argp;
		up_read(&mm->mmap_sem);
		break;
	}

	default:
		ret = -ENOTTY;
		break;
	}

exit:
	mutex_unlock(&mf->lock);
	return ret;
}