Skip to content

Commit 1455c69

Browse files
committed
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
2 parents 42595ce + 861261f commit 1455c69

File tree

9 files changed

+81
-15
lines changed

9 files changed

+81
-15
lines changed

Documentation/filesystems/fscrypt.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,17 @@ from a passphrase or other low-entropy user credential.
633633
FS_IOC_GET_ENCRYPTION_PWSALT is deprecated. Instead, prefer to
634634
generate and manage any needed salt(s) in userspace.
635635

636+
Getting a file's encryption nonce
637+
---------------------------------
638+
639+
Since Linux v5.7, the ioctl FS_IOC_GET_ENCRYPTION_NONCE is supported.
640+
On encrypted files and directories it gets the inode's 16-byte nonce.
641+
On unencrypted files and directories, it fails with ENODATA.
642+
643+
This ioctl can be useful for automated tests which verify that the
644+
encryption is being done correctly. It is not needed for normal use
645+
of fscrypt.
646+
636647
Adding keys
637648
-----------
638649

fs/crypto/fscrypt_private.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,26 @@ static inline int fscrypt_context_size(const union fscrypt_context *ctx)
7676
return 0;
7777
}
7878

79+
/* Check whether an fscrypt_context has a recognized version number and size */
80+
static inline bool fscrypt_context_is_valid(const union fscrypt_context *ctx,
81+
int ctx_size)
82+
{
83+
return ctx_size >= 1 && ctx_size == fscrypt_context_size(ctx);
84+
}
85+
86+
/* Retrieve the context's nonce, assuming the context was already validated */
87+
static inline const u8 *fscrypt_context_nonce(const union fscrypt_context *ctx)
88+
{
89+
switch (ctx->version) {
90+
case FSCRYPT_CONTEXT_V1:
91+
return ctx->v1.nonce;
92+
case FSCRYPT_CONTEXT_V2:
93+
return ctx->v2.nonce;
94+
}
95+
WARN_ON(1);
96+
return NULL;
97+
}
98+
7999
#undef fscrypt_policy
80100
union fscrypt_policy {
81101
u8 version;

fs/crypto/keysetup.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -425,20 +425,8 @@ int fscrypt_get_encryption_info(struct inode *inode)
425425
goto out;
426426
}
427427

428-
switch (ctx.version) {
429-
case FSCRYPT_CONTEXT_V1:
430-
memcpy(crypt_info->ci_nonce, ctx.v1.nonce,
431-
FS_KEY_DERIVATION_NONCE_SIZE);
432-
break;
433-
case FSCRYPT_CONTEXT_V2:
434-
memcpy(crypt_info->ci_nonce, ctx.v2.nonce,
435-
FS_KEY_DERIVATION_NONCE_SIZE);
436-
break;
437-
default:
438-
WARN_ON(1);
439-
res = -EINVAL;
440-
goto out;
441-
}
428+
memcpy(crypt_info->ci_nonce, fscrypt_context_nonce(&ctx),
429+
FS_KEY_DERIVATION_NONCE_SIZE);
442430

443431
if (!fscrypt_supported_policy(&crypt_info->ci_policy, inode)) {
444432
res = -EINVAL;

fs/crypto/policy.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
258258
{
259259
memset(policy_u, 0, sizeof(*policy_u));
260260

261-
if (ctx_size <= 0 || ctx_size != fscrypt_context_size(ctx_u))
261+
if (!fscrypt_context_is_valid(ctx_u, ctx_size))
262262
return -EINVAL;
263263

264264
switch (ctx_u->version) {
@@ -481,6 +481,25 @@ int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *uarg)
481481
}
482482
EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_policy_ex);
483483

484+
/* FS_IOC_GET_ENCRYPTION_NONCE: retrieve file's encryption nonce for testing */
485+
int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg)
486+
{
487+
struct inode *inode = file_inode(filp);
488+
union fscrypt_context ctx;
489+
int ret;
490+
491+
ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
492+
if (ret < 0)
493+
return ret;
494+
if (!fscrypt_context_is_valid(&ctx, ret))
495+
return -EINVAL;
496+
if (copy_to_user(arg, fscrypt_context_nonce(&ctx),
497+
FS_KEY_DERIVATION_NONCE_SIZE))
498+
return -EFAULT;
499+
return 0;
500+
}
501+
EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_nonce);
502+
484503
/**
485504
* fscrypt_has_permitted_context() - is a file's encryption policy permitted
486505
* within its directory?

fs/ext4/ioctl.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,11 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
12101210
return -EOPNOTSUPP;
12111211
return fscrypt_ioctl_get_key_status(filp, (void __user *)arg);
12121212

1213+
case FS_IOC_GET_ENCRYPTION_NONCE:
1214+
if (!ext4_has_feature_encrypt(sb))
1215+
return -EOPNOTSUPP;
1216+
return fscrypt_ioctl_get_nonce(filp, (void __user *)arg);
1217+
12131218
case EXT4_IOC_CLEAR_ES_CACHE:
12141219
{
12151220
if (!inode_owner_or_capable(inode))
@@ -1370,6 +1375,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
13701375
case FS_IOC_REMOVE_ENCRYPTION_KEY:
13711376
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
13721377
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
1378+
case FS_IOC_GET_ENCRYPTION_NONCE:
13731379
case EXT4_IOC_SHUTDOWN:
13741380
case FS_IOC_GETFSMAP:
13751381
case FS_IOC_ENABLE_VERITY:

fs/f2fs/file.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2423,6 +2423,14 @@ static int f2fs_ioc_get_encryption_key_status(struct file *filp,
24232423
return fscrypt_ioctl_get_key_status(filp, (void __user *)arg);
24242424
}
24252425

2426+
static int f2fs_ioc_get_encryption_nonce(struct file *filp, unsigned long arg)
2427+
{
2428+
if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp))))
2429+
return -EOPNOTSUPP;
2430+
2431+
return fscrypt_ioctl_get_nonce(filp, (void __user *)arg);
2432+
}
2433+
24262434
static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
24272435
{
24282436
struct inode *inode = file_inode(filp);
@@ -3437,6 +3445,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
34373445
return f2fs_ioc_remove_encryption_key_all_users(filp, arg);
34383446
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
34393447
return f2fs_ioc_get_encryption_key_status(filp, arg);
3448+
case FS_IOC_GET_ENCRYPTION_NONCE:
3449+
return f2fs_ioc_get_encryption_nonce(filp, arg);
34403450
case F2FS_IOC_GARBAGE_COLLECT:
34413451
return f2fs_ioc_gc(filp, arg);
34423452
case F2FS_IOC_GARBAGE_COLLECT_RANGE:
@@ -3611,6 +3621,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
36113621
case FS_IOC_REMOVE_ENCRYPTION_KEY:
36123622
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
36133623
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
3624+
case FS_IOC_GET_ENCRYPTION_NONCE:
36143625
case F2FS_IOC_GARBAGE_COLLECT:
36153626
case F2FS_IOC_GARBAGE_COLLECT_RANGE:
36163627
case F2FS_IOC_WRITE_CHECKPOINT:

fs/ubifs/ioctl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
208208
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
209209
return fscrypt_ioctl_get_key_status(file, (void __user *)arg);
210210

211+
case FS_IOC_GET_ENCRYPTION_NONCE:
212+
return fscrypt_ioctl_get_nonce(file, (void __user *)arg);
213+
211214
default:
212215
return -ENOTTY;
213216
}
@@ -230,6 +233,7 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
230233
case FS_IOC_REMOVE_ENCRYPTION_KEY:
231234
case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS:
232235
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
236+
case FS_IOC_GET_ENCRYPTION_NONCE:
233237
break;
234238
default:
235239
return -ENOIOCTLCMD;

include/linux/fscrypt.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ extern void fscrypt_free_bounce_page(struct page *bounce_page);
139139
extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
140140
extern int fscrypt_ioctl_get_policy(struct file *, void __user *);
141141
extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *);
142+
extern int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg);
142143
extern int fscrypt_has_permitted_context(struct inode *, struct inode *);
143144
extern int fscrypt_inherit_context(struct inode *, struct inode *,
144145
void *, bool);
@@ -300,6 +301,11 @@ static inline int fscrypt_ioctl_get_policy_ex(struct file *filp,
300301
return -EOPNOTSUPP;
301302
}
302303

304+
static inline int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg)
305+
{
306+
return -EOPNOTSUPP;
307+
}
308+
303309
static inline int fscrypt_has_permitted_context(struct inode *parent,
304310
struct inode *child)
305311
{

include/uapi/linux/fscrypt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ struct fscrypt_get_key_status_arg {
163163
#define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg)
164164
#define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg)
165165
#define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg)
166+
#define FS_IOC_GET_ENCRYPTION_NONCE _IOR('f', 27, __u8[16])
166167

167168
/**********************************************************************/
168169

0 commit comments

Comments
 (0)