fscrypt updates for 5.7
Add an ioctl FS_IOC_GET_ENCRYPTION_NONCE which retrieves a file's encryption nonce. This makes it easier to write automated tests which verify that fscrypt is doing the encryption correctly. -----BEGIN PGP SIGNATURE----- iIoEABYIADIWIQSacvsUNc7UX4ntmEPzXCl4vpKOKwUCXoIg/RQcZWJpZ2dlcnNA Z29vZ2xlLmNvbQAKCRDzXCl4vpKOK2mZAQDjEil0Kf8AqZhjPuJSRrbifkzEPfu+ 4EmERSyBZ5OCLgEA155kKnL5jiz7b5DRS9wGEw+drGpW8I7WfhTGv/XjoQs= =2jU9 -----END PGP SIGNATURE----- Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt Pull fscrypt updates from Eric Biggers: "Add an ioctl FS_IOC_GET_ENCRYPTION_NONCE which retrieves a file's encryption nonce. This makes it easier to write automated tests which verify that fscrypt is doing the encryption correctly" * tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt: ubifs: wire up FS_IOC_GET_ENCRYPTION_NONCE f2fs: wire up FS_IOC_GET_ENCRYPTION_NONCE ext4: wire up FS_IOC_GET_ENCRYPTION_NONCE fscrypt: add FS_IOC_GET_ENCRYPTION_NONCE ioctl
This commit is contained in:
commit
1455c69900
|
@ -633,6 +633,17 @@ from a passphrase or other low-entropy user credential.
|
||||||
FS_IOC_GET_ENCRYPTION_PWSALT is deprecated. Instead, prefer to
|
FS_IOC_GET_ENCRYPTION_PWSALT is deprecated. Instead, prefer to
|
||||||
generate and manage any needed salt(s) in userspace.
|
generate and manage any needed salt(s) in userspace.
|
||||||
|
|
||||||
|
Getting a file's encryption nonce
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
Since Linux v5.7, the ioctl FS_IOC_GET_ENCRYPTION_NONCE is supported.
|
||||||
|
On encrypted files and directories it gets the inode's 16-byte nonce.
|
||||||
|
On unencrypted files and directories, it fails with ENODATA.
|
||||||
|
|
||||||
|
This ioctl can be useful for automated tests which verify that the
|
||||||
|
encryption is being done correctly. It is not needed for normal use
|
||||||
|
of fscrypt.
|
||||||
|
|
||||||
Adding keys
|
Adding keys
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,26 @@ static inline int fscrypt_context_size(const union fscrypt_context *ctx)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check whether an fscrypt_context has a recognized version number and size */
|
||||||
|
static inline bool fscrypt_context_is_valid(const union fscrypt_context *ctx,
|
||||||
|
int ctx_size)
|
||||||
|
{
|
||||||
|
return ctx_size >= 1 && ctx_size == fscrypt_context_size(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the context's nonce, assuming the context was already validated */
|
||||||
|
static inline const u8 *fscrypt_context_nonce(const union fscrypt_context *ctx)
|
||||||
|
{
|
||||||
|
switch (ctx->version) {
|
||||||
|
case FSCRYPT_CONTEXT_V1:
|
||||||
|
return ctx->v1.nonce;
|
||||||
|
case FSCRYPT_CONTEXT_V2:
|
||||||
|
return ctx->v2.nonce;
|
||||||
|
}
|
||||||
|
WARN_ON(1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#undef fscrypt_policy
|
#undef fscrypt_policy
|
||||||
union fscrypt_policy {
|
union fscrypt_policy {
|
||||||
u8 version;
|
u8 version;
|
||||||
|
|
|
@ -425,20 +425,8 @@ int fscrypt_get_encryption_info(struct inode *inode)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ctx.version) {
|
memcpy(crypt_info->ci_nonce, fscrypt_context_nonce(&ctx),
|
||||||
case FSCRYPT_CONTEXT_V1:
|
|
||||||
memcpy(crypt_info->ci_nonce, ctx.v1.nonce,
|
|
||||||
FS_KEY_DERIVATION_NONCE_SIZE);
|
FS_KEY_DERIVATION_NONCE_SIZE);
|
||||||
break;
|
|
||||||
case FSCRYPT_CONTEXT_V2:
|
|
||||||
memcpy(crypt_info->ci_nonce, ctx.v2.nonce,
|
|
||||||
FS_KEY_DERIVATION_NONCE_SIZE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
WARN_ON(1);
|
|
||||||
res = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fscrypt_supported_policy(&crypt_info->ci_policy, inode)) {
|
if (!fscrypt_supported_policy(&crypt_info->ci_policy, inode)) {
|
||||||
res = -EINVAL;
|
res = -EINVAL;
|
||||||
|
|
|
@ -258,7 +258,7 @@ int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
|
||||||
{
|
{
|
||||||
memset(policy_u, 0, sizeof(*policy_u));
|
memset(policy_u, 0, sizeof(*policy_u));
|
||||||
|
|
||||||
if (ctx_size <= 0 || ctx_size != fscrypt_context_size(ctx_u))
|
if (!fscrypt_context_is_valid(ctx_u, ctx_size))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (ctx_u->version) {
|
switch (ctx_u->version) {
|
||||||
|
@ -481,6 +481,25 @@ int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *uarg)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_policy_ex);
|
EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_policy_ex);
|
||||||
|
|
||||||
|
/* FS_IOC_GET_ENCRYPTION_NONCE: retrieve file's encryption nonce for testing */
|
||||||
|
int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg)
|
||||||
|
{
|
||||||
|
struct inode *inode = file_inode(filp);
|
||||||
|
union fscrypt_context ctx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (!fscrypt_context_is_valid(&ctx, ret))
|
||||||
|
return -EINVAL;
|
||||||
|
if (copy_to_user(arg, fscrypt_context_nonce(&ctx),
|
||||||
|
FS_KEY_DERIVATION_NONCE_SIZE))
|
||||||
|
return -EFAULT;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_nonce);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fscrypt_has_permitted_context() - is a file's encryption policy permitted
|
* fscrypt_has_permitted_context() - is a file's encryption policy permitted
|
||||||
* within its directory?
|
* within its directory?
|
||||||
|
|
|
@ -1210,6 +1210,11 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
return fscrypt_ioctl_get_key_status(filp, (void __user *)arg);
|
return fscrypt_ioctl_get_key_status(filp, (void __user *)arg);
|
||||||
|
|
||||||
|
case FS_IOC_GET_ENCRYPTION_NONCE:
|
||||||
|
if (!ext4_has_feature_encrypt(sb))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
return fscrypt_ioctl_get_nonce(filp, (void __user *)arg);
|
||||||
|
|
||||||
case EXT4_IOC_CLEAR_ES_CACHE:
|
case EXT4_IOC_CLEAR_ES_CACHE:
|
||||||
{
|
{
|
||||||
if (!inode_owner_or_capable(inode))
|
if (!inode_owner_or_capable(inode))
|
||||||
|
@ -1370,6 +1375,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
case FS_IOC_REMOVE_ENCRYPTION_KEY:
|
case FS_IOC_REMOVE_ENCRYPTION_KEY:
|
||||||
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
|
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
|
||||||
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
|
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
|
||||||
|
case FS_IOC_GET_ENCRYPTION_NONCE:
|
||||||
case EXT4_IOC_SHUTDOWN:
|
case EXT4_IOC_SHUTDOWN:
|
||||||
case FS_IOC_GETFSMAP:
|
case FS_IOC_GETFSMAP:
|
||||||
case FS_IOC_ENABLE_VERITY:
|
case FS_IOC_ENABLE_VERITY:
|
||||||
|
|
|
@ -2423,6 +2423,14 @@ static int f2fs_ioc_get_encryption_key_status(struct file *filp,
|
||||||
return fscrypt_ioctl_get_key_status(filp, (void __user *)arg);
|
return fscrypt_ioctl_get_key_status(filp, (void __user *)arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int f2fs_ioc_get_encryption_nonce(struct file *filp, unsigned long arg)
|
||||||
|
{
|
||||||
|
if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp))))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
return fscrypt_ioctl_get_nonce(filp, (void __user *)arg);
|
||||||
|
}
|
||||||
|
|
||||||
static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
|
static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct inode *inode = file_inode(filp);
|
struct inode *inode = file_inode(filp);
|
||||||
|
@ -3437,6 +3445,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
return f2fs_ioc_remove_encryption_key_all_users(filp, arg);
|
return f2fs_ioc_remove_encryption_key_all_users(filp, arg);
|
||||||
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
|
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
|
||||||
return f2fs_ioc_get_encryption_key_status(filp, arg);
|
return f2fs_ioc_get_encryption_key_status(filp, arg);
|
||||||
|
case FS_IOC_GET_ENCRYPTION_NONCE:
|
||||||
|
return f2fs_ioc_get_encryption_nonce(filp, arg);
|
||||||
case F2FS_IOC_GARBAGE_COLLECT:
|
case F2FS_IOC_GARBAGE_COLLECT:
|
||||||
return f2fs_ioc_gc(filp, arg);
|
return f2fs_ioc_gc(filp, arg);
|
||||||
case F2FS_IOC_GARBAGE_COLLECT_RANGE:
|
case F2FS_IOC_GARBAGE_COLLECT_RANGE:
|
||||||
|
@ -3611,6 +3621,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
case FS_IOC_REMOVE_ENCRYPTION_KEY:
|
case FS_IOC_REMOVE_ENCRYPTION_KEY:
|
||||||
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
|
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
|
||||||
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
|
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
|
||||||
|
case FS_IOC_GET_ENCRYPTION_NONCE:
|
||||||
case F2FS_IOC_GARBAGE_COLLECT:
|
case F2FS_IOC_GARBAGE_COLLECT:
|
||||||
case F2FS_IOC_GARBAGE_COLLECT_RANGE:
|
case F2FS_IOC_GARBAGE_COLLECT_RANGE:
|
||||||
case F2FS_IOC_WRITE_CHECKPOINT:
|
case F2FS_IOC_WRITE_CHECKPOINT:
|
||||||
|
|
|
@ -208,6 +208,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
|
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
|
||||||
return fscrypt_ioctl_get_key_status(file, (void __user *)arg);
|
return fscrypt_ioctl_get_key_status(file, (void __user *)arg);
|
||||||
|
|
||||||
|
case FS_IOC_GET_ENCRYPTION_NONCE:
|
||||||
|
return fscrypt_ioctl_get_nonce(file, (void __user *)arg);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
}
|
}
|
||||||
|
@ -230,6 +233,7 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
case FS_IOC_REMOVE_ENCRYPTION_KEY:
|
case FS_IOC_REMOVE_ENCRYPTION_KEY:
|
||||||
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
|
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
|
||||||
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
|
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
|
||||||
|
case FS_IOC_GET_ENCRYPTION_NONCE:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
|
|
|
@ -139,6 +139,7 @@ extern void fscrypt_free_bounce_page(struct page *bounce_page);
|
||||||
extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
|
extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
|
||||||
extern int fscrypt_ioctl_get_policy(struct file *, void __user *);
|
extern int fscrypt_ioctl_get_policy(struct file *, void __user *);
|
||||||
extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *);
|
extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *);
|
||||||
|
extern int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg);
|
||||||
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);
|
||||||
|
@ -300,6 +301,11 @@ static inline int fscrypt_ioctl_get_policy_ex(struct file *filp,
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int fscrypt_has_permitted_context(struct inode *parent,
|
static inline int fscrypt_has_permitted_context(struct inode *parent,
|
||||||
struct inode *child)
|
struct inode *child)
|
||||||
{
|
{
|
||||||
|
|
|
@ -163,6 +163,7 @@ struct fscrypt_get_key_status_arg {
|
||||||
#define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg)
|
#define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg)
|
||||||
#define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg)
|
#define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg)
|
||||||
#define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg)
|
#define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg)
|
||||||
|
#define FS_IOC_GET_ENCRYPTION_NONCE _IOR('f', 27, __u8[16])
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue