Commit 56735be0 authored by Theodore Ts'o's avatar Theodore Ts'o

Merge branch 'fscrypt' into d

parents a121103c a5d431ef
config FS_ENCRYPTION config FS_ENCRYPTION
tristate "FS Encryption (Per-file encryption)" tristate "FS Encryption (Per-file encryption)"
depends on BLOCK
select CRYPTO select CRYPTO
select CRYPTO_AES select CRYPTO_AES
select CRYPTO_CBC select CRYPTO_CBC
......
obj-$(CONFIG_FS_ENCRYPTION) += fscrypto.o obj-$(CONFIG_FS_ENCRYPTION) += fscrypto.o
fscrypto-y := crypto.o fname.o policy.o keyinfo.o fscrypto-y := crypto.o fname.o policy.o keyinfo.o
fscrypto-$(CONFIG_BLOCK) += bio.o
/*
* This contains encryption functions for per-file encryption.
*
* Copyright (C) 2015, Google, Inc.
* Copyright (C) 2015, Motorola Mobility
*
* Written by Michael Halcrow, 2014.
*
* Filename encryption additions
* Uday Savagaonkar, 2014
* Encryption policy handling additions
* Ildar Muslukhov, 2014
* Add fscrypt_pullback_bio_page()
* Jaegeuk Kim, 2015.
*
* This has not yet undergone a rigorous security audit.
*
* The usage of AES-XTS should conform to recommendations in NIST
* Special Publication 800-38E and IEEE P1619/D16.
*/
#include <linux/pagemap.h>
#include <linux/module.h>
#include <linux/bio.h>
#include <linux/namei.h>
#include "fscrypt_private.h"
/*
* Call fscrypt_decrypt_page on every single page, reusing the encryption
* context.
*/
static void completion_pages(struct work_struct *work)
{
struct fscrypt_ctx *ctx =
container_of(work, struct fscrypt_ctx, r.work);
struct bio *bio = ctx->r.bio;
struct bio_vec *bv;
int i;
bio_for_each_segment_all(bv, bio, i) {
struct page *page = bv->bv_page;
int ret = fscrypt_decrypt_page(page->mapping->host, page,
PAGE_SIZE, 0, page->index);
if (ret) {
WARN_ON_ONCE(1);
SetPageError(page);
} else {
SetPageUptodate(page);
}
unlock_page(page);
}
fscrypt_release_ctx(ctx);
bio_put(bio);
}
void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *ctx, struct bio *bio)
{
INIT_WORK(&ctx->r.work, completion_pages);
ctx->r.bio = bio;
queue_work(fscrypt_read_workqueue, &ctx->r.work);
}
EXPORT_SYMBOL(fscrypt_decrypt_bio_pages);
void fscrypt_pullback_bio_page(struct page **page, bool restore)
{
struct fscrypt_ctx *ctx;
struct page *bounce_page;
/* The bounce data pages are unmapped. */
if ((*page)->mapping)
return;
/* The bounce data page is unmapped. */
bounce_page = *page;
ctx = (struct fscrypt_ctx *)page_private(bounce_page);
/* restore control page */
*page = ctx->w.control_page;
if (restore)
fscrypt_restore_control_page(bounce_page);
}
EXPORT_SYMBOL(fscrypt_pullback_bio_page);
int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len)
{
struct fscrypt_ctx *ctx;
struct page *ciphertext_page = NULL;
struct bio *bio;
int ret, err = 0;
BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE);
ctx = fscrypt_get_ctx(inode, GFP_NOFS);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
ciphertext_page = fscrypt_alloc_bounce_page(ctx, GFP_NOWAIT);
if (IS_ERR(ciphertext_page)) {
err = PTR_ERR(ciphertext_page);
goto errout;
}
while (len--) {
err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk,
ZERO_PAGE(0), ciphertext_page,
PAGE_SIZE, 0, GFP_NOFS);
if (err)
goto errout;
bio = bio_alloc(GFP_NOWAIT, 1);
if (!bio) {
err = -ENOMEM;
goto errout;
}
bio->bi_bdev = inode->i_sb->s_bdev;
bio->bi_iter.bi_sector =
pblk << (inode->i_sb->s_blocksize_bits - 9);
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
ret = bio_add_page(bio, ciphertext_page,
inode->i_sb->s_blocksize, 0);
if (ret != inode->i_sb->s_blocksize) {
/* should never happen! */
WARN_ON(1);
bio_put(bio);
err = -EIO;
goto errout;
}
err = submit_bio_wait(bio);
if ((err == 0) && bio->bi_error)
err = -EIO;
bio_put(bio);
if (err)
goto errout;
lblk++;
pblk++;
}
err = 0;
errout:
fscrypt_release_ctx(ctx);
return err;
}
EXPORT_SYMBOL(fscrypt_zeroout_range);
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/bio.h>
#include <linux/dcache.h> #include <linux/dcache.h>
#include <linux/namei.h> #include <linux/namei.h>
#include "fscrypt_private.h" #include "fscrypt_private.h"
...@@ -44,7 +43,7 @@ static mempool_t *fscrypt_bounce_page_pool = NULL; ...@@ -44,7 +43,7 @@ static mempool_t *fscrypt_bounce_page_pool = NULL;
static LIST_HEAD(fscrypt_free_ctxs); static LIST_HEAD(fscrypt_free_ctxs);
static DEFINE_SPINLOCK(fscrypt_ctx_lock); static DEFINE_SPINLOCK(fscrypt_ctx_lock);
static struct workqueue_struct *fscrypt_read_workqueue; struct workqueue_struct *fscrypt_read_workqueue;
static DEFINE_MUTEX(fscrypt_init_mutex); static DEFINE_MUTEX(fscrypt_init_mutex);
static struct kmem_cache *fscrypt_ctx_cachep; static struct kmem_cache *fscrypt_ctx_cachep;
...@@ -141,16 +140,10 @@ static void page_crypt_complete(struct crypto_async_request *req, int res) ...@@ -141,16 +140,10 @@ static void page_crypt_complete(struct crypto_async_request *req, int res)
complete(&ecr->completion); complete(&ecr->completion);
} }
typedef enum { int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw,
FS_DECRYPT = 0, u64 lblk_num, struct page *src_page,
FS_ENCRYPT, struct page *dest_page, unsigned int len,
} fscrypt_direction_t; unsigned int offs, gfp_t gfp_flags)
static int do_page_crypto(const struct inode *inode,
fscrypt_direction_t rw, u64 lblk_num,
struct page *src_page, struct page *dest_page,
unsigned int len, unsigned int offs,
gfp_t gfp_flags)
{ {
struct { struct {
__le64 index; __le64 index;
...@@ -205,7 +198,8 @@ static int do_page_crypto(const struct inode *inode, ...@@ -205,7 +198,8 @@ static int do_page_crypto(const struct inode *inode,
return 0; return 0;
} }
static struct page *alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags) struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx,
gfp_t gfp_flags)
{ {
ctx->w.bounce_page = mempool_alloc(fscrypt_bounce_page_pool, gfp_flags); ctx->w.bounce_page = mempool_alloc(fscrypt_bounce_page_pool, gfp_flags);
if (ctx->w.bounce_page == NULL) if (ctx->w.bounce_page == NULL)
...@@ -260,9 +254,9 @@ struct page *fscrypt_encrypt_page(const struct inode *inode, ...@@ -260,9 +254,9 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
if (inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES) { if (inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES) {
/* with inplace-encryption we just encrypt the page */ /* with inplace-encryption we just encrypt the page */
err = do_page_crypto(inode, FS_ENCRYPT, lblk_num, err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num, page,
page, ciphertext_page, ciphertext_page, len, offs,
len, offs, gfp_flags); gfp_flags);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
...@@ -276,14 +270,14 @@ struct page *fscrypt_encrypt_page(const struct inode *inode, ...@@ -276,14 +270,14 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
return (struct page *)ctx; return (struct page *)ctx;
/* The encryption operation will require a bounce page. */ /* The encryption operation will require a bounce page. */
ciphertext_page = alloc_bounce_page(ctx, gfp_flags); ciphertext_page = fscrypt_alloc_bounce_page(ctx, gfp_flags);
if (IS_ERR(ciphertext_page)) if (IS_ERR(ciphertext_page))
goto errout; goto errout;
ctx->w.control_page = page; ctx->w.control_page = page;
err = do_page_crypto(inode, FS_ENCRYPT, lblk_num, err = fscrypt_do_page_crypto(inode, FS_ENCRYPT, lblk_num,
page, ciphertext_page, page, ciphertext_page, len, offs,
len, offs, gfp_flags); gfp_flags);
if (err) { if (err) {
ciphertext_page = ERR_PTR(err); ciphertext_page = ERR_PTR(err);
goto errout; goto errout;
...@@ -320,72 +314,11 @@ int fscrypt_decrypt_page(const struct inode *inode, struct page *page, ...@@ -320,72 +314,11 @@ int fscrypt_decrypt_page(const struct inode *inode, struct page *page,
if (!(inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES)) if (!(inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES))
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
return do_page_crypto(inode, FS_DECRYPT, lblk_num, page, page, len, return fscrypt_do_page_crypto(inode, FS_DECRYPT, lblk_num, page, page,
offs, GFP_NOFS); len, offs, GFP_NOFS);
} }
EXPORT_SYMBOL(fscrypt_decrypt_page); EXPORT_SYMBOL(fscrypt_decrypt_page);
int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len)
{
struct fscrypt_ctx *ctx;
struct page *ciphertext_page = NULL;
struct bio *bio;
int ret, err = 0;
BUG_ON(inode->i_sb->s_blocksize != PAGE_SIZE);
ctx = fscrypt_get_ctx(inode, GFP_NOFS);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
ciphertext_page = alloc_bounce_page(ctx, GFP_NOWAIT);
if (IS_ERR(ciphertext_page)) {
err = PTR_ERR(ciphertext_page);
goto errout;
}
while (len--) {
err = do_page_crypto(inode, FS_ENCRYPT, lblk,
ZERO_PAGE(0), ciphertext_page,
PAGE_SIZE, 0, GFP_NOFS);
if (err)
goto errout;
bio = bio_alloc(GFP_NOWAIT, 1);
if (!bio) {
err = -ENOMEM;
goto errout;
}
bio->bi_bdev = inode->i_sb->s_bdev;
bio->bi_iter.bi_sector =
pblk << (inode->i_sb->s_blocksize_bits - 9);
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
ret = bio_add_page(bio, ciphertext_page,
inode->i_sb->s_blocksize, 0);
if (ret != inode->i_sb->s_blocksize) {
/* should never happen! */
WARN_ON(1);
bio_put(bio);
err = -EIO;
goto errout;
}
err = submit_bio_wait(bio);
if ((err == 0) && bio->bi_error)
err = -EIO;
bio_put(bio);
if (err)
goto errout;
lblk++;
pblk++;
}
err = 0;
errout:
fscrypt_release_ctx(ctx);
return err;
}
EXPORT_SYMBOL(fscrypt_zeroout_range);
/* /*
* Validate dentries for encrypted directories to make sure we aren't * Validate dentries for encrypted directories to make sure we aren't
* potentially caching stale data after a key has been added or * potentially caching stale data after a key has been added or
...@@ -442,64 +375,6 @@ const struct dentry_operations fscrypt_d_ops = { ...@@ -442,64 +375,6 @@ const struct dentry_operations fscrypt_d_ops = {
}; };
EXPORT_SYMBOL(fscrypt_d_ops); EXPORT_SYMBOL(fscrypt_d_ops);
/*
* Call fscrypt_decrypt_page on every single page, reusing the encryption
* context.
*/
static void completion_pages(struct work_struct *work)
{
struct fscrypt_ctx *ctx =
container_of(work, struct fscrypt_ctx, r.work);
struct bio *bio = ctx->r.bio;
struct bio_vec *bv;
int i;
bio_for_each_segment_all(bv, bio, i) {
struct page *page = bv->bv_page;
int ret = fscrypt_decrypt_page(page->mapping->host, page,
PAGE_SIZE, 0, page->index);
if (ret) {
WARN_ON_ONCE(1);
SetPageError(page);
} else {
SetPageUptodate(page);
}
unlock_page(page);
}
fscrypt_release_ctx(ctx);
bio_put(bio);
}
void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *ctx, struct bio *bio)
{
INIT_WORK(&ctx->r.work, completion_pages);
ctx->r.bio = bio;
queue_work(fscrypt_read_workqueue, &ctx->r.work);
}
EXPORT_SYMBOL(fscrypt_decrypt_bio_pages);
void fscrypt_pullback_bio_page(struct page **page, bool restore)
{
struct fscrypt_ctx *ctx;
struct page *bounce_page;
/* The bounce data pages are unmapped. */
if ((*page)->mapping)
return;
/* The bounce data page is unmapped. */
bounce_page = *page;
ctx = (struct fscrypt_ctx *)page_private(bounce_page);
/* restore control page */
*page = ctx->w.control_page;
if (restore)
fscrypt_restore_control_page(bounce_page);
}
EXPORT_SYMBOL(fscrypt_pullback_bio_page);
void fscrypt_restore_control_page(struct page *page) void fscrypt_restore_control_page(struct page *page)
{ {
struct fscrypt_ctx *ctx; struct fscrypt_ctx *ctx;
......
...@@ -332,7 +332,7 @@ int fscrypt_fname_usr_to_disk(struct inode *inode, ...@@ -332,7 +332,7 @@ int fscrypt_fname_usr_to_disk(struct inode *inode,
* in a directory. Consequently, a user space name cannot be mapped to * in a directory. Consequently, a user space name cannot be mapped to
* a disk-space name * a disk-space name
*/ */
return -EACCES; return -ENOKEY;
} }
EXPORT_SYMBOL(fscrypt_fname_usr_to_disk); EXPORT_SYMBOL(fscrypt_fname_usr_to_disk);
...@@ -367,7 +367,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, ...@@ -367,7 +367,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
return 0; return 0;
} }
if (!lookup) if (!lookup)
return -EACCES; return -ENOKEY;
/* /*
* We don't have the key and we are doing a lookup; decode the * We don't have the key and we are doing a lookup; decode the
......
...@@ -71,6 +71,11 @@ struct fscrypt_info { ...@@ -71,6 +71,11 @@ struct fscrypt_info {
u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE]; u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE];
}; };
typedef enum {
FS_DECRYPT = 0,
FS_ENCRYPT,
} fscrypt_direction_t;
#define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001 #define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001
#define FS_CTX_HAS_BOUNCE_BUFFER_FL 0x00000002 #define FS_CTX_HAS_BOUNCE_BUFFER_FL 0x00000002
...@@ -85,7 +90,16 @@ struct fscrypt_completion_result { ...@@ -85,7 +90,16 @@ struct fscrypt_completion_result {
/* crypto.c */ /* crypto.c */
int fscrypt_initialize(unsigned int cop_flags); extern int fscrypt_initialize(unsigned int cop_flags);
extern struct workqueue_struct *fscrypt_read_workqueue;
extern int fscrypt_do_page_crypto(const struct inode *inode,
fscrypt_direction_t rw, u64 lblk_num,
struct page *src_page,
struct page *dest_page,
unsigned int len, unsigned int offs,
gfp_t gfp_flags);
extern struct page *fscrypt_alloc_bounce_page(struct fscrypt_ctx *ctx,
gfp_t gfp_flags);
/* keyinfo.c */ /* keyinfo.c */
extern int fscrypt_get_crypt_info(struct inode *); extern int fscrypt_get_crypt_info(struct inode *);
......
...@@ -77,26 +77,22 @@ static int derive_key_aes(u8 deriving_key[FS_AES_128_ECB_KEY_SIZE], ...@@ -77,26 +77,22 @@ static int derive_key_aes(u8 deriving_key[FS_AES_128_ECB_KEY_SIZE],
static int validate_user_key(struct fscrypt_info *crypt_info, static int validate_user_key(struct fscrypt_info *crypt_info,
struct fscrypt_context *ctx, u8 *raw_key, struct fscrypt_context *ctx, u8 *raw_key,
u8 *prefix, int prefix_size) const char *prefix)
{ {
u8 *full_key_descriptor; char *description;
struct key *keyring_key; struct key *keyring_key;
struct fscrypt_key *master_key; struct fscrypt_key *master_key;
const struct user_key_payload *ukp; const struct user_key_payload *ukp;
int full_key_len = prefix_size + (FS_KEY_DESCRIPTOR_SIZE * 2) + 1;
int res; int res;
full_key_descriptor = kmalloc(full_key_len, GFP_NOFS); description = kasprintf(GFP_NOFS, "%s%*phN", prefix,
if (!full_key_descriptor) FS_KEY_DESCRIPTOR_SIZE,
ctx->master_key_descriptor);
if (!description)
return -ENOMEM; return -ENOMEM;
memcpy(full_key_descriptor, prefix, prefix_size); keyring_key = request_key(&key_type_logon, description, NULL);
sprintf(full_key_descriptor + prefix_size, kfree(description);
"%*phN", FS_KEY_DESCRIPTOR_SIZE,
ctx->master_key_descriptor);
full_key_descriptor[full_key_len - 1] = '\0';
keyring_key = request_key(&key_type_logon, full_key_descriptor, NULL);
kfree(full_key_descriptor);
if (IS_ERR(keyring_key)) if (IS_ERR(keyring_key))
return PTR_ERR(keyring_key); return PTR_ERR(keyring_key);
...@@ -206,12 +202,16 @@ int fscrypt_get_crypt_info(struct inode *inode) ...@@ -206,12 +202,16 @@ int fscrypt_get_crypt_info(struct inode *inode)
res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
if (res < 0) { if (res < 0) {
if (!fscrypt_dummy_context_enabled(inode)) if (!fscrypt_dummy_context_enabled(inode) ||
inode->i_sb->s_cop->is_encrypted(inode))
return res; return res;
/* Fake up a context for an unencrypted directory */
memset(&ctx, 0, sizeof(ctx));
ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS; ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS; ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS;
ctx.flags = 0; memset(ctx.master_key_descriptor, 0x42, FS_KEY_DESCRIPTOR_SIZE);
res = sizeof(ctx);
} else if (res != sizeof(ctx)) { } else if (res != sizeof(ctx)) {
return -EINVAL; return -EINVAL;
} }
...@@ -247,21 +247,10 @@ int fscrypt_get_crypt_info(struct inode *inode) ...@@ -247,21 +247,10 @@ int fscrypt_get_crypt_info(struct inode *inode)
if (!raw_key) if (!raw_key)
goto out; goto out;
if (fscrypt_dummy_context_enabled(inode)) { res = validate_user_key(crypt_info, &ctx, raw_key, FS_KEY_DESC_PREFIX);
memset(raw_key, 0x42, keysize/2);
memset(raw_key+keysize/2, 0x24, keysize - (keysize/2));
goto got_key;
}
res = validate_user_key(crypt_info, &ctx, raw_key,
FS_KEY_DESC_PREFIX, FS_KEY_DESC_PREFIX_SIZE);
if (res && inode->i_sb->s_cop->key_prefix) { if (res && inode->i_sb->s_cop->key_prefix) {
u8 *prefix = NULL; int res2 = validate_user_key(crypt_info, &ctx, raw_key,
int prefix_size, res2; inode->i_sb->s_cop->key_prefix);
prefix_size = inode->i_sb->s_cop->key_prefix(inode, &prefix);
res2 = validate_user_key(crypt_info, &ctx, raw_key,
prefix, prefix_size);
if (res2) { if (res2) {
if (res2 == -ENOKEY) if (res2 == -ENOKEY)
res = -ENOKEY; res = -ENOKEY;
...@@ -270,7 +259,6 @@ int fscrypt_get_crypt_info(struct inode *inode) ...@@ -270,7 +259,6 @@ int fscrypt_get_crypt_info(struct inode *inode)
} else if (res) { } else if (res) {
goto out; goto out;
} }
got_key:
ctfm = crypto_alloc_skcipher(cipher_str, 0, 0); ctfm = crypto_alloc_skcipher(cipher_str, 0, 0);
if (!ctfm || IS_ERR(ctfm)) { if (!ctfm || IS_ERR(ctfm)) {
res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; res = ctfm ? PTR_ERR(ctfm) : -ENOMEM;
......
...@@ -13,37 +13,20 @@ ...@@ -13,37 +13,20 @@
#include <linux/mount.h> #include <linux/mount.h>
#include "fscrypt_private.h" #include "fscrypt_private.h"
static int inode_has_encryption_context(struct inode *inode)
{
if (!inode->i_sb->s_cop->get_context)
return 0;
return (inode->i_sb->s_cop->get_context(inode, NULL, 0L) > 0);
}
/* /*
* check whether the policy is consistent with the encryption context * check whether an encryption policy is consistent with an encryption context
* for the inode
*/ */
static int is_encryption_context_consistent_with_policy(struct inode *inode, static bool is_encryption_context_consistent_with_policy(
const struct fscrypt_context *ctx,
const struct fscrypt_policy *policy) const struct fscrypt_policy *policy)
{ {
struct fscrypt_context ctx; return memcmp(ctx->master_key_descriptor, policy->master_key_descriptor,
int res;
if (!inode->i_sb->s_cop->get_context)
return 0;
res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
if (res != sizeof(ctx))
return 0;
return (memcmp(ctx.master_key_descriptor, policy->master_key_descriptor,
FS_KEY_DESCRIPTOR_SIZE) == 0 && FS_KEY_DESCRIPTOR_SIZE) == 0 &&
(ctx.flags == policy->flags) && (ctx->flags == policy->flags) &&
(ctx.contents_encryption_mode == (ctx->contents_encryption_mode ==
policy->contents_encryption_mode) && policy->contents_encryption_mode) &&
(ctx.filenames_encryption_mode == (ctx->filenames_encryption_mode ==
policy->filenames_encryption_mode)); policy->filenames_encryption_mode);
} }
static int create_encryption_context_from_policy(struct inode *inode, static int create_encryption_context_from_policy(struct inode *inode,
...@@ -66,20 +49,12 @@ static int create_encryption_context_from_policy(struct inode *inode, ...@@ -66,20 +49,12 @@ static int create_encryption_context_from_policy(struct inode *inode,
FS_KEY_DESCRIPTOR_SIZE); FS_KEY_DESCRIPTOR_SIZE);
if (!fscrypt_valid_contents_enc_mode( if (!fscrypt_valid_contents_enc_mode(
policy->contents_encryption_mode)) { policy->contents_encryption_mode))
printk(KERN_WARNING
"%s: Invalid contents encryption mode %d\n", __func__,
policy->contents_encryption_mode);
return -EINVAL; return -EINVAL;
}
if (!fscrypt_valid_filenames_enc_mode( if (!fscrypt_valid_filenames_enc_mode(
policy->filenames_encryption_mode)) { policy->filenames_encryption_mode))
printk(KERN_WARNING
"%s: Invalid filenames encryption mode %d\n", __func__,
policy->filenames_encryption_mode);
return -EINVAL; return -EINVAL;
}
if (policy->flags & ~FS_POLICY_FLAGS_VALID) if (policy->flags & ~FS_POLICY_FLAGS_VALID)
return -EINVAL; return -EINVAL;
...@@ -98,6 +73,7 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) ...@@ -98,6 +73,7 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg)
struct fscrypt_policy policy; struct fscrypt_policy policy;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
int ret; int ret;
struct fscrypt_context ctx;
if (copy_from_user(&policy, arg, sizeof(policy))) if (copy_from_user(&policy, arg, sizeof(policy)))
return -EFAULT; return -EFAULT;
...@@ -114,9 +90,10 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) ...@@ -114,9 +90,10 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg)
inode_lock(inode); inode_lock(inode);
if (!inode_has_encryption_context(inode)) { ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
if (ret == -ENODATA) {
if (!S_ISDIR(inode->i_mode)) if (!S_ISDIR(inode->i_mode))
ret = -EINVAL; ret = -ENOTDIR;
else if (!inode->i_sb->s_cop->empty_dir) else if (!inode->i_sb->s_cop->empty_dir)
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
else if (!inode->i_sb->s_cop->empty_dir(inode)) else if (!inode->i_sb->s_cop->empty_dir(inode))
...@@ -124,12 +101,14 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) ...@@ -124,12 +101,14 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg)
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 (ret == sizeof(ctx) &&
is_encryption_context_consistent_with_policy(&ctx,
&policy)) { &policy)) {
printk(KERN_WARNING /* The file already uses the same encryption policy. */
"%s: Policy inconsistent with encryption context\n", ret = 0;
__func__); } else if (ret >= 0 || ret == -ERANGE) {
ret = -EINVAL; /* The file already uses a different encryption policy. */
ret = -EEXIST;
} }
inode_unlock(inode); inode_unlock(inode);
...@@ -151,8 +130,10 @@ int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg) ...@@ -151,8 +130,10 @@ int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg)
return -ENODATA; return -ENODATA;
res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
if (res < 0 && res != -ERANGE)
return res;
if (res != sizeof(ctx)) if (res != sizeof(ctx))
return -ENODATA; return -EINVAL;
if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1)
return -EINVAL; return -EINVAL;
...@@ -217,9 +198,9 @@ EXPORT_SYMBOL(fscrypt_has_permitted_context); ...@@ -217,9 +198,9 @@ EXPORT_SYMBOL(fscrypt_has_permitted_context);
* @parent: Parent inode from which the context is inherited. * @parent: Parent inode from which the context is inherited.
* @child: Child inode that inherits the context from @parent. * @child: Child inode that inherits the context from @parent.
* @fs_data: private data given by FS. * @fs_data: private data given by FS.
* @preload: preload child i_crypt_info * @preload: preload child i_crypt_info if true
* *
* Return: Zero on success, non-zero otherwise * Return: 0 on success, -errno on failure
*/ */
int fscrypt_inherit_context(struct inode *parent, struct inode *child, int fscrypt_inherit_context(struct inode *parent, struct inode *child,
void *fs_data, bool preload) void *fs_data, bool preload)
...@@ -240,19 +221,11 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child, ...@@ -240,19 +221,11 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child,
return -ENOKEY; return -ENOKEY;
ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1; ctx.format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
if (fscrypt_dummy_context_enabled(parent)) {
ctx.contents_encryption_mode = FS_ENCRYPTION_MODE_AES_256_XTS;
ctx.filenames_encryption_mode = FS_ENCRYPTION_MODE_AES_256_CTS;
ctx.flags = 0;
memset(ctx.master_key_descriptor, 0x42, FS_KEY_DESCRIPTOR_SIZE);
res = 0;
} else {
ctx.contents_encryption_mode = ci->ci_data_mode; ctx.contents_encryption_mode = ci->ci_data_mode;
ctx.filenames_encryption_mode = ci->ci_filename_mode; ctx.filenames_encryption_mode = ci->ci_filename_mode;
ctx.flags = ci->ci_flags; ctx.flags = ci->ci_flags;
memcpy(ctx.master_key_descriptor, ci->ci_master_key, memcpy(ctx.master_key_descriptor, ci->ci_master_key,
FS_KEY_DESCRIPTOR_SIZE); FS_KEY_DESCRIPTOR_SIZE);
}
get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE); get_random_bytes(ctx.nonce, FS_KEY_DERIVATION_NONCE_SIZE);
res = parent->i_sb->s_cop->set_context(child, &ctx, res = parent->i_sb->s_cop->set_context(child, &ctx,
sizeof(ctx), fs_data); sizeof(ctx), fs_data);
......
...@@ -1343,11 +1343,6 @@ struct ext4_super_block { ...@@ -1343,11 +1343,6 @@ struct ext4_super_block {
/* Number of quota types we support */ /* Number of quota types we support */
#define EXT4_MAXQUOTAS 3 #define EXT4_MAXQUOTAS 3
#ifdef CONFIG_EXT4_FS_ENCRYPTION
#define EXT4_KEY_DESC_PREFIX "ext4:"
#define EXT4_KEY_DESC_PREFIX_SIZE 5
#endif
/* /*
* fourth extended-fs super-block data in memory * fourth extended-fs super-block data in memory
*/ */
...@@ -1517,12 +1512,6 @@ struct ext4_sb_info { ...@@ -1517,12 +1512,6 @@ struct ext4_sb_info {
/* Barrier between changing inodes' journal flags and writepages ops. */ /* Barrier between changing inodes' journal flags and writepages ops. */
struct percpu_rw_semaphore s_journal_flag_rwsem; struct percpu_rw_semaphore s_journal_flag_rwsem;
/* Encryption support */
#ifdef CONFIG_EXT4_FS_ENCRYPTION
u8 key_prefix[EXT4_KEY_DESC_PREFIX_SIZE];
u8 key_prefix_size;
#endif
}; };
static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
......
...@@ -771,7 +771,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, ...@@ -771,7 +771,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
if (!fscrypt_has_encryption_key(dir)) if (!fscrypt_has_encryption_key(dir))
return ERR_PTR(-EPERM); return ERR_PTR(-ENOKEY);
if (!handle) if (!handle)
nblocks += EXT4_DATA_TRANS_BLOCKS(dir->i_sb); nblocks += EXT4_DATA_TRANS_BLOCKS(dir->i_sb);
encrypt = 1; encrypt = 1;
......
...@@ -1378,6 +1378,8 @@ static struct buffer_head * ext4_find_entry (struct inode *dir, ...@@ -1378,6 +1378,8 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
return NULL; return NULL;
retval = ext4_fname_setup_filename(dir, d_name, 1, &fname); retval = ext4_fname_setup_filename(dir, d_name, 1, &fname);
if (retval == -ENOENT)
return NULL;
if (retval) if (retval)
return ERR_PTR(retval); return ERR_PTR(retval);
...@@ -3088,7 +3090,7 @@ static int ext4_symlink(struct inode *dir, ...@@ -3088,7 +3090,7 @@ static int ext4_symlink(struct inode *dir,
if (err) if (err)
return err; return err;
if (!fscrypt_has_encryption_key(dir)) if (!fscrypt_has_encryption_key(dir))
return -EPERM; return -ENOKEY;
disk_link.len = (fscrypt_fname_encrypted_size(dir, len) + disk_link.len = (fscrypt_fname_encrypted_size(dir, len) +
sizeof(struct fscrypt_symlink_data)); sizeof(struct fscrypt_symlink_data));
sd = kzalloc(disk_link.len, GFP_KERNEL); sd = kzalloc(disk_link.len, GFP_KERNEL);
...@@ -3525,6 +3527,12 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -3525,6 +3527,12 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
EXT4_I(old_dentry->d_inode)->i_projid))) EXT4_I(old_dentry->d_inode)->i_projid)))
return -EXDEV; return -EXDEV;
if ((ext4_encrypted_inode(old_dir) &&
!fscrypt_has_encryption_key(old_dir)) ||
(ext4_encrypted_inode(new_dir) &&
!fscrypt_has_encryption_key(new_dir)))
return -ENOKEY;
retval = dquot_initialize(old.dir); retval = dquot_initialize(old.dir);
if (retval) if (retval)
return retval; return retval;
...@@ -3725,6 +3733,12 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -3725,6 +3733,12 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
int retval; int retval;
struct timespec ctime; struct timespec ctime;
if ((ext4_encrypted_inode(old_dir) &&
!fscrypt_has_encryption_key(old_dir)) ||
(ext4_encrypted_inode(new_dir) &&
!fscrypt_has_encryption_key(new_dir)))
return -ENOKEY;
if ((ext4_encrypted_inode(old_dir) || if ((ext4_encrypted_inode(old_dir) ||
ext4_encrypted_inode(new_dir)) && ext4_encrypted_inode(new_dir)) &&
(old_dir != new_dir) && (old_dir != new_dir) &&
......
...@@ -1100,12 +1100,6 @@ static int ext4_get_context(struct inode *inode, void *ctx, size_t len) ...@@ -1100,12 +1100,6 @@ static int ext4_get_context(struct inode *inode, void *ctx, size_t len)
EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len); EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len);
} }
static int ext4_key_prefix(struct inode *inode, u8 **key)
{
*key = EXT4_SB(inode->i_sb)->key_prefix;
return EXT4_SB(inode->i_sb)->key_prefix_size;
}
static int ext4_prepare_context(struct inode *inode) static int ext4_prepare_context(struct inode *inode)
{ {
return ext4_convert_inline_data(inode); return ext4_convert_inline_data(inode);
...@@ -1180,8 +1174,8 @@ static unsigned ext4_max_namelen(struct inode *inode) ...@@ -1180,8 +1174,8 @@ static unsigned ext4_max_namelen(struct inode *inode)
} }
static struct fscrypt_operations ext4_cryptops = { static struct fscrypt_operations ext4_cryptops = {
.key_prefix = "ext4:",
.get_context = ext4_get_context, .get_context = ext4_get_context,
.key_prefix = ext4_key_prefix,
.prepare_context = ext4_prepare_context, .prepare_context = ext4_prepare_context,
.set_context = ext4_set_context, .set_context = ext4_set_context,
.dummy_context = ext4_dummy_context, .dummy_context = ext4_dummy_context,
...@@ -4218,11 +4212,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -4218,11 +4212,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
ratelimit_state_init(&sbi->s_msg_ratelimit_state, 5 * HZ, 10); ratelimit_state_init(&sbi->s_msg_ratelimit_state, 5 * HZ, 10);
kfree(orig_data); kfree(orig_data);
#ifdef CONFIG_EXT4_FS_ENCRYPTION
memcpy(sbi->key_prefix, EXT4_KEY_DESC_PREFIX,
EXT4_KEY_DESC_PREFIX_SIZE);
sbi->key_prefix_size = EXT4_KEY_DESC_PREFIX_SIZE;
#endif
return 0; return 0;
cantfind_ext4: cantfind_ext4:
......
...@@ -268,6 +268,9 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir, ...@@ -268,6 +268,9 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
err = fscrypt_setup_filename(dir, child, 1, &fname); err = fscrypt_setup_filename(dir, child, 1, &fname);
if (err) { if (err) {
if (err == -ENOENT)
*res_page = NULL;
else
*res_page = ERR_PTR(err); *res_page = ERR_PTR(err);
return NULL; return NULL;
} }
......
...@@ -760,10 +760,6 @@ enum { ...@@ -760,10 +760,6 @@ enum {
MAX_TIME, MAX_TIME,
}; };
#ifdef CONFIG_F2FS_FS_ENCRYPTION
#define F2FS_KEY_DESC_PREFIX "f2fs:"
#define F2FS_KEY_DESC_PREFIX_SIZE 5
#endif
struct f2fs_sb_info { struct f2fs_sb_info {
struct super_block *sb; /* pointer to VFS super block */ struct super_block *sb; /* pointer to VFS super block */
struct proc_dir_entry *s_proc; /* proc entry */ struct proc_dir_entry *s_proc; /* proc entry */
...@@ -771,11 +767,6 @@ struct f2fs_sb_info { ...@@ -771,11 +767,6 @@ struct f2fs_sb_info {
int valid_super_block; /* valid super block no */ int valid_super_block; /* valid super block no */
unsigned long s_flag; /* flags for sbi */ unsigned long s_flag; /* flags for sbi */
#ifdef CONFIG_F2FS_FS_ENCRYPTION
u8 key_prefix[F2FS_KEY_DESC_PREFIX_SIZE];
u8 key_prefix_size;
#endif
#ifdef CONFIG_BLK_DEV_ZONED #ifdef CONFIG_BLK_DEV_ZONED
unsigned int blocks_per_blkz; /* F2FS blocks per zone */ unsigned int blocks_per_blkz; /* F2FS blocks per zone */
unsigned int log_blocks_per_blkz; /* log2 F2FS blocks per zone */ unsigned int log_blocks_per_blkz; /* log2 F2FS blocks per zone */
......
...@@ -403,7 +403,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -403,7 +403,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
return err; return err;
if (!fscrypt_has_encryption_key(dir)) if (!fscrypt_has_encryption_key(dir))
return -EPERM; return -ENOKEY;
disk_link.len = (fscrypt_fname_encrypted_size(dir, len) + disk_link.len = (fscrypt_fname_encrypted_size(dir, len) +
sizeof(struct fscrypt_symlink_data)); sizeof(struct fscrypt_symlink_data));
...@@ -447,7 +447,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry, ...@@ -447,7 +447,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
goto err_out; goto err_out;
if (!fscrypt_has_encryption_key(inode)) { if (!fscrypt_has_encryption_key(inode)) {
err = -EPERM; err = -ENOKEY;
goto err_out; goto err_out;
} }
......
...@@ -1156,12 +1156,6 @@ static int f2fs_get_context(struct inode *inode, void *ctx, size_t len) ...@@ -1156,12 +1156,6 @@ static int f2fs_get_context(struct inode *inode, void *ctx, size_t len)
ctx, len, NULL); ctx, len, NULL);
} }
static int f2fs_key_prefix(struct inode *inode, u8 **key)
{
*key = F2FS_I_SB(inode)->key_prefix;
return F2FS_I_SB(inode)->key_prefix_size;
}
static int f2fs_set_context(struct inode *inode, const void *ctx, size_t len, static int f2fs_set_context(struct inode *inode, const void *ctx, size_t len,
void *fs_data) void *fs_data)
{ {
...@@ -1177,8 +1171,8 @@ static unsigned f2fs_max_namelen(struct inode *inode) ...@@ -1177,8 +1171,8 @@ static unsigned f2fs_max_namelen(struct inode *inode)
} }
static struct fscrypt_operations f2fs_cryptops = { static struct fscrypt_operations f2fs_cryptops = {
.key_prefix = "f2fs:",
.get_context = f2fs_get_context, .get_context = f2fs_get_context,
.key_prefix = f2fs_key_prefix,
.set_context = f2fs_set_context, .set_context = f2fs_set_context,
.is_encrypted = f2fs_encrypted_inode, .is_encrypted = f2fs_encrypted_inode,
.empty_dir = f2fs_empty_dir, .empty_dir = f2fs_empty_dir,
...@@ -1518,12 +1512,6 @@ static void init_sb_info(struct f2fs_sb_info *sbi) ...@@ -1518,12 +1512,6 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
mutex_init(&sbi->wio_mutex[NODE]); mutex_init(&sbi->wio_mutex[NODE]);
mutex_init(&sbi->wio_mutex[DATA]); mutex_init(&sbi->wio_mutex[DATA]);
spin_lock_init(&sbi->cp_lock); spin_lock_init(&sbi->cp_lock);
#ifdef CONFIG_F2FS_FS_ENCRYPTION
memcpy(sbi->key_prefix, F2FS_KEY_DESC_PREFIX,
F2FS_KEY_DESC_PREFIX_SIZE);
sbi->key_prefix_size = F2FS_KEY_DESC_PREFIX_SIZE;
#endif
} }
static int init_percpu_info(struct f2fs_sb_info *sbi) static int init_percpu_info(struct f2fs_sb_info *sbi)
......
...@@ -26,15 +26,6 @@ static unsigned int ubifs_crypt_max_namelen(struct inode *inode) ...@@ -26,15 +26,6 @@ static unsigned int ubifs_crypt_max_namelen(struct inode *inode)
return UBIFS_MAX_NLEN; return UBIFS_MAX_NLEN;
} }
static int ubifs_key_prefix(struct inode *inode, u8 **key)
{
static char prefix[] = "ubifs:";
*key = prefix;
return sizeof(prefix) - 1;
}
int ubifs_encrypt(const struct inode *inode, struct ubifs_data_node *dn, int ubifs_encrypt(const struct inode *inode, struct ubifs_data_node *dn,
unsigned int in_len, unsigned int *out_len, int block) unsigned int in_len, unsigned int *out_len, int block)
{ {
...@@ -88,10 +79,10 @@ int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn, ...@@ -88,10 +79,10 @@ int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn,
struct fscrypt_operations ubifs_crypt_operations = { struct fscrypt_operations ubifs_crypt_operations = {
.flags = FS_CFLG_OWN_PAGES, .flags = FS_CFLG_OWN_PAGES,
.key_prefix = "ubifs:",
.get_context = ubifs_crypt_get_context, .get_context = ubifs_crypt_get_context,
.set_context = ubifs_crypt_set_context, .set_context = ubifs_crypt_set_context,
.is_encrypted = __ubifs_crypt_is_encrypted, .is_encrypted = __ubifs_crypt_is_encrypted,
.empty_dir = ubifs_crypt_empty_dir, .empty_dir = ubifs_crypt_empty_dir,
.max_namelen = ubifs_crypt_max_namelen, .max_namelen = ubifs_crypt_max_namelen,
.key_prefix = ubifs_key_prefix,
}; };
...@@ -35,7 +35,6 @@ struct fscrypt_ctx { ...@@ -35,7 +35,6 @@ struct fscrypt_ctx {
struct list_head free_list; /* Free list */ struct list_head free_list; /* Free list */
}; };
u8 flags; /* Flags */ u8 flags; /* Flags */
u8 mode; /* Encryption mode for tfm */
}; };
/** /**
...@@ -86,8 +85,8 @@ struct fscrypt_name { ...@@ -86,8 +85,8 @@ struct fscrypt_name {
*/ */
struct fscrypt_operations { struct fscrypt_operations {
unsigned int flags; unsigned int flags;
const char *key_prefix;
int (*get_context)(struct inode *, void *, size_t); int (*get_context)(struct inode *, void *, size_t);
int (*key_prefix)(struct inode *, u8 **);
int (*prepare_context)(struct inode *); int (*prepare_context)(struct inode *);
int (*set_context)(struct inode *, const void *, size_t, void *); int (*set_context)(struct inode *, const void *, size_t, void *);
int (*dummy_context)(struct inode *); int (*dummy_context)(struct inode *);
...@@ -174,11 +173,8 @@ extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, ...@@ -174,11 +173,8 @@ extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
u64, gfp_t); u64, gfp_t);
extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int, extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int,
unsigned int, u64); unsigned int, u64);
extern void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *, struct bio *);
extern void fscrypt_pullback_bio_page(struct page **, bool);
extern void fscrypt_restore_control_page(struct page *); extern void fscrypt_restore_control_page(struct page *);
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
unsigned int);
/* policy.c */ /* policy.c */
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 *);
...@@ -201,6 +197,12 @@ extern int fscrypt_fname_disk_to_usr(struct inode *, u32, u32, ...@@ -201,6 +197,12 @@ extern int fscrypt_fname_disk_to_usr(struct inode *, u32, u32,
const struct fscrypt_str *, struct fscrypt_str *); const struct fscrypt_str *, struct fscrypt_str *);
extern int fscrypt_fname_usr_to_disk(struct inode *, const struct qstr *, extern int fscrypt_fname_usr_to_disk(struct inode *, const struct qstr *,
struct fscrypt_str *); struct fscrypt_str *);
/* bio.c */
extern void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *, struct bio *);
extern void fscrypt_pullback_bio_page(struct page **, bool);
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
unsigned int);
#endif #endif
/* crypto.c */ /* crypto.c */
......
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