Commit db717d8e authored by Eric Biggers's avatar Eric Biggers Committed by Theodore Ts'o

fscrypto: move ioctl processing more fully into common code

Multiple bugs were recently fixed in the "set encryption policy" ioctl.
To make it clear that fscrypt_process_policy() and fscrypt_get_policy()
implement ioctls and therefore their implementations must take standard
security and correctness precautions, rename them to
fscrypt_ioctl_set_policy() and fscrypt_ioctl_get_policy().  Make the
latter take in a struct file * to make it consistent with the former.
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 80481235
...@@ -93,16 +93,19 @@ static int create_encryption_context_from_policy(struct inode *inode, ...@@ -93,16 +93,19 @@ static int create_encryption_context_from_policy(struct inode *inode,
return inode->i_sb->s_cop->set_context(inode, &ctx, sizeof(ctx), NULL); return inode->i_sb->s_cop->set_context(inode, &ctx, sizeof(ctx), NULL);
} }
int fscrypt_process_policy(struct file *filp, int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg)
const struct fscrypt_policy *policy)
{ {
struct fscrypt_policy policy;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
int ret; int ret;
if (copy_from_user(&policy, arg, sizeof(policy)))
return -EFAULT;
if (!inode_owner_or_capable(inode)) if (!inode_owner_or_capable(inode))
return -EACCES; return -EACCES;
if (policy->version != 0) if (policy.version != 0)
return -EINVAL; return -EINVAL;
ret = mnt_want_write_file(filp); ret = mnt_want_write_file(filp);
...@@ -120,9 +123,9 @@ int fscrypt_process_policy(struct file *filp, ...@@ -120,9 +123,9 @@ int fscrypt_process_policy(struct file *filp,
ret = -ENOTEMPTY; ret = -ENOTEMPTY;
else else
ret = create_encryption_context_from_policy(inode, ret = create_encryption_context_from_policy(inode,
policy); &policy);
} else if (!is_encryption_context_consistent_with_policy(inode, } else if (!is_encryption_context_consistent_with_policy(inode,
policy)) { &policy)) {
printk(KERN_WARNING printk(KERN_WARNING
"%s: Policy inconsistent with encryption context\n", "%s: Policy inconsistent with encryption context\n",
__func__); __func__);
...@@ -134,11 +137,13 @@ int fscrypt_process_policy(struct file *filp, ...@@ -134,11 +137,13 @@ int fscrypt_process_policy(struct file *filp,
mnt_drop_write_file(filp); mnt_drop_write_file(filp);
return ret; return ret;
} }
EXPORT_SYMBOL(fscrypt_process_policy); EXPORT_SYMBOL(fscrypt_ioctl_set_policy);
int fscrypt_get_policy(struct inode *inode, struct fscrypt_policy *policy) int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg)
{ {
struct inode *inode = file_inode(filp);
struct fscrypt_context ctx; struct fscrypt_context ctx;
struct fscrypt_policy policy;
int res; int res;
if (!inode->i_sb->s_cop->get_context || if (!inode->i_sb->s_cop->get_context ||
...@@ -151,15 +156,18 @@ int fscrypt_get_policy(struct inode *inode, struct fscrypt_policy *policy) ...@@ -151,15 +156,18 @@ int fscrypt_get_policy(struct inode *inode, struct fscrypt_policy *policy)
if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1)
return -EINVAL; return -EINVAL;
policy->version = 0; policy.version = 0;
policy->contents_encryption_mode = ctx.contents_encryption_mode; policy.contents_encryption_mode = ctx.contents_encryption_mode;
policy->filenames_encryption_mode = ctx.filenames_encryption_mode; policy.filenames_encryption_mode = ctx.filenames_encryption_mode;
policy->flags = ctx.flags; policy.flags = ctx.flags;
memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor, memcpy(policy.master_key_descriptor, ctx.master_key_descriptor,
FS_KEY_DESCRIPTOR_SIZE); FS_KEY_DESCRIPTOR_SIZE);
if (copy_to_user(arg, &policy, sizeof(policy)))
return -EFAULT;
return 0; return 0;
} }
EXPORT_SYMBOL(fscrypt_get_policy); EXPORT_SYMBOL(fscrypt_ioctl_get_policy);
int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
{ {
......
...@@ -2338,8 +2338,8 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname) { } ...@@ -2338,8 +2338,8 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname) { }
#define fscrypt_pullback_bio_page fscrypt_notsupp_pullback_bio_page #define fscrypt_pullback_bio_page fscrypt_notsupp_pullback_bio_page
#define fscrypt_restore_control_page fscrypt_notsupp_restore_control_page #define fscrypt_restore_control_page fscrypt_notsupp_restore_control_page
#define fscrypt_zeroout_range fscrypt_notsupp_zeroout_range #define fscrypt_zeroout_range fscrypt_notsupp_zeroout_range
#define fscrypt_process_policy fscrypt_notsupp_process_policy #define fscrypt_ioctl_set_policy fscrypt_notsupp_ioctl_set_policy
#define fscrypt_get_policy fscrypt_notsupp_get_policy #define fscrypt_ioctl_get_policy fscrypt_notsupp_ioctl_get_policy
#define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context #define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context
#define fscrypt_inherit_context fscrypt_notsupp_inherit_context #define fscrypt_inherit_context fscrypt_notsupp_inherit_context
#define fscrypt_get_encryption_info fscrypt_notsupp_get_encryption_info #define fscrypt_get_encryption_info fscrypt_notsupp_get_encryption_info
......
...@@ -765,22 +765,12 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -765,22 +765,12 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
} }
case EXT4_IOC_PRECACHE_EXTENTS: case EXT4_IOC_PRECACHE_EXTENTS:
return ext4_ext_precache(inode); return ext4_ext_precache(inode);
case EXT4_IOC_SET_ENCRYPTION_POLICY: {
#ifdef CONFIG_EXT4_FS_ENCRYPTION
struct fscrypt_policy policy;
case EXT4_IOC_SET_ENCRYPTION_POLICY:
if (!ext4_has_feature_encrypt(sb)) if (!ext4_has_feature_encrypt(sb))
return -EOPNOTSUPP; return -EOPNOTSUPP;
return fscrypt_ioctl_set_policy(filp, (const void __user *)arg);
if (copy_from_user(&policy,
(struct fscrypt_policy __user *)arg,
sizeof(policy)))
return -EFAULT;
return fscrypt_process_policy(filp, &policy);
#else
return -EOPNOTSUPP;
#endif
}
case EXT4_IOC_GET_ENCRYPTION_PWSALT: { case EXT4_IOC_GET_ENCRYPTION_PWSALT: {
int err, err2; int err, err2;
struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_sb_info *sbi = EXT4_SB(sb);
...@@ -817,23 +807,9 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -817,23 +807,9 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
case EXT4_IOC_GET_ENCRYPTION_POLICY: { case EXT4_IOC_GET_ENCRYPTION_POLICY:
#ifdef CONFIG_EXT4_FS_ENCRYPTION return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
struct fscrypt_policy policy;
int err = 0;
if (!ext4_encrypted_inode(inode))
return -ENOENT;
err = fscrypt_get_policy(inode, &policy);
if (err)
return err;
if (copy_to_user((void __user *)arg, &policy, sizeof(policy)))
return -EFAULT;
return 0;
#else
return -EOPNOTSUPP;
#endif
}
case EXT4_IOC_FSGETXATTR: case EXT4_IOC_FSGETXATTR:
{ {
struct fsxattr fa; struct fsxattr fa;
......
...@@ -2453,8 +2453,8 @@ static inline bool f2fs_may_encrypt(struct inode *inode) ...@@ -2453,8 +2453,8 @@ static inline bool f2fs_may_encrypt(struct inode *inode)
#define fscrypt_pullback_bio_page fscrypt_notsupp_pullback_bio_page #define fscrypt_pullback_bio_page fscrypt_notsupp_pullback_bio_page
#define fscrypt_restore_control_page fscrypt_notsupp_restore_control_page #define fscrypt_restore_control_page fscrypt_notsupp_restore_control_page
#define fscrypt_zeroout_range fscrypt_notsupp_zeroout_range #define fscrypt_zeroout_range fscrypt_notsupp_zeroout_range
#define fscrypt_process_policy fscrypt_notsupp_process_policy #define fscrypt_ioctl_set_policy fscrypt_notsupp_ioctl_set_policy
#define fscrypt_get_policy fscrypt_notsupp_get_policy #define fscrypt_ioctl_get_policy fscrypt_notsupp_ioctl_get_policy
#define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context #define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context
#define fscrypt_inherit_context fscrypt_notsupp_inherit_context #define fscrypt_inherit_context fscrypt_notsupp_inherit_context
#define fscrypt_get_encryption_info fscrypt_notsupp_get_encryption_info #define fscrypt_get_encryption_info fscrypt_notsupp_get_encryption_info
......
...@@ -1752,31 +1752,16 @@ static bool uuid_is_nonzero(__u8 u[16]) ...@@ -1752,31 +1752,16 @@ static bool uuid_is_nonzero(__u8 u[16])
static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg) static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg)
{ {
struct fscrypt_policy policy;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
if (copy_from_user(&policy, (struct fscrypt_policy __user *)arg,
sizeof(policy)))
return -EFAULT;
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return fscrypt_process_policy(filp, &policy); return fscrypt_ioctl_set_policy(filp, (const void __user *)arg);
} }
static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg) static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg)
{ {
struct fscrypt_policy policy; return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
struct inode *inode = file_inode(filp);
int err;
err = fscrypt_get_policy(inode, &policy);
if (err)
return err;
if (copy_to_user((struct fscrypt_policy __user *)arg, &policy, sizeof(policy)))
return -EFAULT;
return 0;
} }
static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg) static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg)
......
...@@ -259,8 +259,8 @@ extern void fscrypt_restore_control_page(struct page *); ...@@ -259,8 +259,8 @@ extern void fscrypt_restore_control_page(struct page *);
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
unsigned int); unsigned int);
/* policy.c */ /* policy.c */
extern int fscrypt_process_policy(struct file *, const struct fscrypt_policy *); extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
extern int fscrypt_get_policy(struct inode *, struct fscrypt_policy *); extern int fscrypt_ioctl_get_policy(struct file *, void __user *);
extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_has_permitted_context(struct inode *, struct inode *);
extern int fscrypt_inherit_context(struct inode *, struct inode *, extern int fscrypt_inherit_context(struct inode *, struct inode *,
void *, bool); void *, bool);
...@@ -334,14 +334,14 @@ static inline int fscrypt_notsupp_zeroout_range(const struct inode *i, pgoff_t p ...@@ -334,14 +334,14 @@ static inline int fscrypt_notsupp_zeroout_range(const struct inode *i, pgoff_t p
} }
/* policy.c */ /* policy.c */
static inline int fscrypt_notsupp_process_policy(struct file *f, static inline int fscrypt_notsupp_ioctl_set_policy(struct file *f,
const struct fscrypt_policy *p) const void __user *arg)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int fscrypt_notsupp_get_policy(struct inode *i, static inline int fscrypt_notsupp_ioctl_get_policy(struct file *f,
struct fscrypt_policy *p) void __user *arg)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment