/** * 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; }
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; }