Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
56735be0
Commit
56735be0
authored
Jan 08, 2017
by
Theodore Ts'o
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'fscrypt' into d
parents
a121103c
a5d431ef
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
263 additions
and
301 deletions
+263
-301
fs/crypto/Kconfig
fs/crypto/Kconfig
+0
-1
fs/crypto/Makefile
fs/crypto/Makefile
+1
-0
fs/crypto/bio.c
fs/crypto/bio.c
+145
-0
fs/crypto/crypto.c
fs/crypto/crypto.c
+16
-141
fs/crypto/fname.c
fs/crypto/fname.c
+2
-2
fs/crypto/fscrypt_private.h
fs/crypto/fscrypt_private.h
+15
-1
fs/crypto/keyinfo.c
fs/crypto/keyinfo.c
+17
-29
fs/crypto/policy.c
fs/crypto/policy.c
+34
-61
fs/ext4/ext4.h
fs/ext4/ext4.h
+0
-11
fs/ext4/ialloc.c
fs/ext4/ialloc.c
+1
-1
fs/ext4/namei.c
fs/ext4/namei.c
+15
-1
fs/ext4/super.c
fs/ext4/super.c
+1
-12
fs/f2fs/dir.c
fs/f2fs/dir.c
+4
-1
fs/f2fs/f2fs.h
fs/f2fs/f2fs.h
+0
-9
fs/f2fs/namei.c
fs/f2fs/namei.c
+2
-2
fs/f2fs/super.c
fs/f2fs/super.c
+1
-13
fs/ubifs/crypto.c
fs/ubifs/crypto.c
+1
-10
include/linux/fscrypto.h
include/linux/fscrypto.h
+8
-6
No files found.
fs/crypto/Kconfig
View file @
56735be0
config FS_ENCRYPTION
tristate "FS Encryption (Per-file encryption)"
depends on BLOCK
select CRYPTO
select CRYPTO_AES
select CRYPTO_CBC
...
...
fs/crypto/Makefile
View file @
56735be0
obj-$(CONFIG_FS_ENCRYPTION)
+=
fscrypto.o
fscrypto-y
:=
crypto.o fname.o policy.o keyinfo.o
fscrypto-$(CONFIG_BLOCK)
+=
bio.o
fs/crypto/bio.c
0 → 100644
View file @
56735be0
/*
* 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
);
fs/crypto/crypto.c
View file @
56735be0
...
...
@@ -24,7 +24,6 @@
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <linux/ratelimit.h>
#include <linux/bio.h>
#include <linux/dcache.h>
#include <linux/namei.h>
#include "fscrypt_private.h"
...
...
@@ -44,7 +43,7 @@ static mempool_t *fscrypt_bounce_page_pool = NULL;
static
LIST_HEAD
(
fscrypt_free_ctxs
);
static
DEFINE_SPINLOCK
(
fscrypt_ctx_lock
);
st
atic
st
ruct
workqueue_struct
*
fscrypt_read_workqueue
;
struct
workqueue_struct
*
fscrypt_read_workqueue
;
static
DEFINE_MUTEX
(
fscrypt_init_mutex
);
static
struct
kmem_cache
*
fscrypt_ctx_cachep
;
...
...
@@ -141,16 +140,10 @@ static void page_crypt_complete(struct crypto_async_request *req, int res)
complete
(
&
ecr
->
completion
);
}
typedef
enum
{
FS_DECRYPT
=
0
,
FS_ENCRYPT
,
}
fscrypt_direction_t
;
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
)
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
)
{
struct
{
__le64
index
;
...
...
@@ -205,7 +198,8 @@ static int do_page_crypto(const struct inode *inode,
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
);
if
(
ctx
->
w
.
bounce_page
==
NULL
)
...
...
@@ -260,9 +254,9 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
if
(
inode
->
i_sb
->
s_cop
->
flags
&
FS_CFLG_OWN_PAGES
)
{
/* with inplace-encryption we just encrypt the page */
err
=
do_page_crypto
(
inode
,
FS_ENCRYPT
,
lblk_num
,
page
,
ciphertext_page
,
len
,
offs
,
gfp_flags
);
err
=
fscrypt_do_page_crypto
(
inode
,
FS_ENCRYPT
,
lblk_num
,
page
,
ciphertext_page
,
len
,
offs
,
gfp_flags
);
if
(
err
)
return
ERR_PTR
(
err
);
...
...
@@ -276,14 +270,14 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
return
(
struct
page
*
)
ctx
;
/* 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
))
goto
errout
;
ctx
->
w
.
control_page
=
page
;
err
=
do_page_crypto
(
inode
,
FS_ENCRYPT
,
lblk_num
,
page
,
ciphertext_page
,
len
,
offs
,
gfp_flags
);
err
=
fscrypt_
do_page_crypto
(
inode
,
FS_ENCRYPT
,
lblk_num
,
page
,
ciphertext_page
,
len
,
offs
,
gfp_flags
);
if
(
err
)
{
ciphertext_page
=
ERR_PTR
(
err
);
goto
errout
;
...
...
@@ -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
))
BUG_ON
(
!
PageLocked
(
page
));
return
do_page_crypto
(
inode
,
FS_DECRYPT
,
lblk_num
,
page
,
page
,
len
,
offs
,
GFP_NOFS
);
return
fscrypt_do_page_crypto
(
inode
,
FS_DECRYPT
,
lblk_num
,
page
,
page
,
len
,
offs
,
GFP_NOFS
);
}
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
* potentially caching stale data after a key has been added or
...
...
@@ -442,64 +375,6 @@ const struct dentry_operations 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
)
{
struct
fscrypt_ctx
*
ctx
;
...
...
fs/crypto/fname.c
View file @
56735be0
...
...
@@ -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
* a disk-space name
*/
return
-
E
ACCES
;
return
-
E
NOKEY
;
}
EXPORT_SYMBOL
(
fscrypt_fname_usr_to_disk
);
...
...
@@ -367,7 +367,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
return
0
;
}
if
(
!
lookup
)
return
-
E
ACCES
;
return
-
E
NOKEY
;
/*
* We don't have the key and we are doing a lookup; decode the
...
...
fs/crypto/fscrypt_private.h
View file @
56735be0
...
...
@@ -71,6 +71,11 @@ struct fscrypt_info {
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_HAS_BOUNCE_BUFFER_FL 0x00000002
...
...
@@ -85,7 +90,16 @@ struct fscrypt_completion_result {
/* 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 */
extern
int
fscrypt_get_crypt_info
(
struct
inode
*
);
...
...
fs/crypto/keyinfo.c
View file @
56735be0
...
...
@@ -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
,
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
fscrypt_key
*
master_key
;
const
struct
user_key_payload
*
ukp
;
int
full_key_len
=
prefix_size
+
(
FS_KEY_DESCRIPTOR_SIZE
*
2
)
+
1
;
int
res
;
full_key_descriptor
=
kmalloc
(
full_key_len
,
GFP_NOFS
);
if
(
!
full_key_descriptor
)
description
=
kasprintf
(
GFP_NOFS
,
"%s%*phN"
,
prefix
,
FS_KEY_DESCRIPTOR_SIZE
,
ctx
->
master_key_descriptor
);
if
(
!
description
)
return
-
ENOMEM
;
memcpy
(
full_key_descriptor
,
prefix
,
prefix_size
);
sprintf
(
full_key_descriptor
+
prefix_size
,
"%*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
);
keyring_key
=
request_key
(
&
key_type_logon
,
description
,
NULL
);
kfree
(
description
);
if
(
IS_ERR
(
keyring_key
))
return
PTR_ERR
(
keyring_key
);
...
...
@@ -206,12 +202,16 @@ int fscrypt_get_crypt_info(struct inode *inode)
res
=
inode
->
i_sb
->
s_cop
->
get_context
(
inode
,
&
ctx
,
sizeof
(
ctx
));
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
;
/* Fake up a context for an unencrypted directory */
memset
(
&
ctx
,
0
,
sizeof
(
ctx
));
ctx
.
format
=
FS_ENCRYPTION_CONTEXT_FORMAT_V1
;
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
=
sizeof
(
ctx
);
}
else
if
(
res
!=
sizeof
(
ctx
))
{
return
-
EINVAL
;
}
...
...
@@ -247,21 +247,10 @@ int fscrypt_get_crypt_info(struct inode *inode)
if
(
!
raw_key
)
goto
out
;
if
(
fscrypt_dummy_context_enabled
(
inode
))
{
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
);
res
=
validate_user_key
(
crypt_info
,
&
ctx
,
raw_key
,
FS_KEY_DESC_PREFIX
);
if
(
res
&&
inode
->
i_sb
->
s_cop
->
key_prefix
)
{
u8
*
prefix
=
NULL
;
int
prefix_size
,
res2
;
prefix_size
=
inode
->
i_sb
->
s_cop
->
key_prefix
(
inode
,
&
prefix
);
res2
=
validate_user_key
(
crypt_info
,
&
ctx
,
raw_key
,
prefix
,
prefix_size
);
int
res2
=
validate_user_key
(
crypt_info
,
&
ctx
,
raw_key
,
inode
->
i_sb
->
s_cop
->
key_prefix
);
if
(
res2
)
{
if
(
res2
==
-
ENOKEY
)
res
=
-
ENOKEY
;
...
...
@@ -270,7 +259,6 @@ int fscrypt_get_crypt_info(struct inode *inode)
}
else
if
(
res
)
{
goto
out
;
}
got_key:
ctfm
=
crypto_alloc_skcipher
(
cipher_str
,
0
,
0
);
if
(
!
ctfm
||
IS_ERR
(
ctfm
))
{
res
=
ctfm
?
PTR_ERR
(
ctfm
)
:
-
ENOMEM
;
...
...
fs/crypto/policy.c
View file @
56735be0
...
...
@@ -13,37 +13,20 @@
#include <linux/mount.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
* for the inode
* check whether an encryption policy is consistent with an encryption context
*/
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
)
{
struct
fscrypt_context
ctx
;
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
&&
(
ctx
.
flags
==
policy
->
flags
)
&&
(
ctx
.
contents_encryption_mode
==
policy
->
contents_encryption_mode
)
&&
(
ctx
.
filenames_encryption_mode
==
policy
->
filenames_encryption_mode
));
return
memcmp
(
ctx
->
master_key_descriptor
,
policy
->
master_key_descriptor
,
FS_KEY_DESCRIPTOR_SIZE
)
==
0
&&
(
ctx
->
flags
==
policy
->
flags
)
&&
(
ctx
->
contents_encryption_mode
==
policy
->
contents_encryption_mode
)
&&
(
ctx
->
filenames_encryption_mode
==
policy
->
filenames_encryption_mode
);
}
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
);
if
(
!
fscrypt_valid_contents_enc_mode
(
policy
->
contents_encryption_mode
))
{
printk
(
KERN_WARNING
"%s: Invalid contents encryption mode %d
\n
"
,
__func__
,
policy
->
contents_encryption_mode
);
policy
->
contents_encryption_mode
))
return
-
EINVAL
;
}
if
(
!
fscrypt_valid_filenames_enc_mode
(
policy
->
filenames_encryption_mode
))
{
printk
(
KERN_WARNING
"%s: Invalid filenames encryption mode %d
\n
"
,
__func__
,
policy
->
filenames_encryption_mode
);
policy
->
filenames_encryption_mode
))
return
-
EINVAL
;
}
if
(
policy
->
flags
&
~
FS_POLICY_FLAGS_VALID
)
return
-
EINVAL
;
...
...
@@ -98,6 +73,7 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg)
struct
fscrypt_policy
policy
;
struct
inode
*
inode
=
file_inode
(
filp
);
int
ret
;
struct
fscrypt_context
ctx
;
if
(
copy_from_user
(
&
policy
,
arg
,
sizeof
(
policy
)))
return
-
EFAULT
;
...
...
@@ -114,9 +90,10 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg)
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
))
ret
=
-
E
INVAL
;
ret
=
-
E
NOTDIR
;
else
if
(
!
inode
->
i_sb
->
s_cop
->
empty_dir
)
ret
=
-
EOPNOTSUPP
;
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)
else
ret
=
create_encryption_context_from_policy
(
inode
,
&
policy
);
}
else
if
(
!
is_encryption_context_consistent_with_policy
(
inode
,
&
policy
))
{
printk
(
KERN_WARNING
"%s: Policy inconsistent with encryption context
\n
"
,
__func__
);
ret
=
-
EINVAL
;
}
else
if
(
ret
==
sizeof
(
ctx
)
&&
is_encryption_context_consistent_with_policy
(
&
ctx
,
&
policy
))
{
/* The file already uses the same encryption policy. */
ret
=
0
;
}
else
if
(
ret
>=
0
||
ret
==
-
ERANGE
)
{
/* The file already uses a different encryption policy. */
ret
=
-
EEXIST
;
}
inode_unlock
(
inode
);
...
...
@@ -151,8 +130,10 @@ int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg)
return
-
ENODATA
;
res
=
inode
->
i_sb
->
s_cop
->
get_context
(
inode
,
&
ctx
,
sizeof
(
ctx
));
if
(
res
<
0
&&
res
!=
-
ERANGE
)
return
res
;
if
(
res
!=
sizeof
(
ctx
))
return
-
E
NODATA
;
return
-
E
INVAL
;
if
(
ctx
.
format
!=
FS_ENCRYPTION_CONTEXT_FORMAT_V1
)
return
-
EINVAL
;
...
...
@@ -217,9 +198,9 @@ EXPORT_SYMBOL(fscrypt_has_permitted_context);
* @parent: Parent inode from which the context is inherited.
* @child: Child inode that inherits the context from @parent.
* @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 otherwis
e
* Return:
0 on success, -errno on failur
e
*/
int
fscrypt_inherit_context
(
struct
inode
*
parent
,
struct
inode
*
child
,
void
*
fs_data
,
bool
preload
)
...
...
@@ -240,19 +221,11 @@ int fscrypt_inherit_context(struct inode *parent, struct inode *child,
return
-
ENOKEY
;
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
.
filenames_encryption_mode
=
ci
->
ci_filename_mode
;
ctx
.
flags
=
ci
->
ci_flags
;
memcpy
(
ctx
.
master_key_descriptor
,
ci
->
ci_master_key
,
FS_KEY_DESCRIPTOR_SIZE
);
}
ctx
.
contents_encryption_mode
=
ci
->
ci_data_mode
;
ctx
.
filenames_encryption_mode
=
ci
->
ci_filename_mode
;
ctx
.
flags
=
ci
->
ci_flags
;
memcpy
(
ctx
.
master_key_descriptor
,
ci
->
ci_master_key
,
FS_KEY_DESCRIPTOR_SIZE
);
get_random_bytes
(
ctx
.
nonce
,
FS_KEY_DERIVATION_NONCE_SIZE
);
res
=
parent
->
i_sb
->
s_cop
->
set_context
(
child
,
&
ctx
,
sizeof
(
ctx
),
fs_data
);
...
...
fs/ext4/ext4.h
View file @
56735be0
...
...
@@ -1343,11 +1343,6 @@ struct ext4_super_block {
/* Number of quota types we support */
#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
*/
...
...
@@ -1517,12 +1512,6 @@ struct ext4_sb_info {
/* Barrier between changing inodes' journal flags and writepages ops. */
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
)
...
...
fs/ext4/ialloc.c
View file @
56735be0
...
...
@@ -771,7 +771,7 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir,
if
(
err
)
return
ERR_PTR
(
err
);
if
(
!
fscrypt_has_encryption_key
(
dir
))
return
ERR_PTR
(
-
E
PERM
);
return
ERR_PTR
(
-
E
NOKEY
);
if
(
!
handle
)
nblocks
+=
EXT4_DATA_TRANS_BLOCKS
(
dir
->
i_sb
);
encrypt
=
1
;
...
...
fs/ext4/namei.c
View file @
56735be0
...
...
@@ -1378,6 +1378,8 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
return
NULL
;
retval
=
ext4_fname_setup_filename
(
dir
,
d_name
,
1
,
&
fname
);
if
(
retval
==
-
ENOENT
)
return
NULL
;
if
(
retval
)
return
ERR_PTR
(
retval
);
...
...
@@ -3088,7 +3090,7 @@ static int ext4_symlink(struct inode *dir,
if
(
err
)
return
err
;
if
(
!
fscrypt_has_encryption_key
(
dir
))
return
-
E
PERM
;
return
-
E
NOKEY
;
disk_link
.
len
=
(
fscrypt_fname_encrypted_size
(
dir
,
len
)
+
sizeof
(
struct
fscrypt_symlink_data
));
sd
=
kzalloc
(
disk_link
.
len
,
GFP_KERNEL
);
...
...
@@ -3525,6 +3527,12 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
EXT4_I
(
old_dentry
->
d_inode
)
->
i_projid
)))
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
);
if
(
retval
)
return
retval
;
...
...
@@ -3725,6 +3733,12 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
int
retval
;
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
)
||
ext4_encrypted_inode
(
new_dir
))
&&
(
old_dir
!=
new_dir
)
&&
...
...
fs/ext4/super.c
View file @
56735be0
...
...
@@ -1100,12 +1100,6 @@ static int ext4_get_context(struct inode *inode, void *ctx, size_t 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
)
{
return
ext4_convert_inline_data
(
inode
);
...
...
@@ -1180,8 +1174,8 @@ static unsigned ext4_max_namelen(struct inode *inode)
}
static
struct
fscrypt_operations
ext4_cryptops
=
{
.
key_prefix
=
"ext4:"
,
.
get_context
=
ext4_get_context
,
.
key_prefix
=
ext4_key_prefix
,
.
prepare_context
=
ext4_prepare_context
,
.
set_context
=
ext4_set_context
,
.
dummy_context
=
ext4_dummy_context
,
...
...
@@ -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
);
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
;
cantfind_ext4:
...
...
fs/f2fs/dir.c
View file @
56735be0
...
...
@@ -268,7 +268,10 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
err
=
fscrypt_setup_filename
(
dir
,
child
,
1
,
&
fname
);
if
(
err
)
{
*
res_page
=
ERR_PTR
(
err
);
if
(
err
==
-
ENOENT
)
*
res_page
=
NULL
;
else
*
res_page
=
ERR_PTR
(
err
);
return
NULL
;
}
...
...
fs/f2fs/f2fs.h
View file @
56735be0
...
...
@@ -760,10 +760,6 @@ enum {
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
super_block
*
sb
;
/* pointer to VFS super block */
struct
proc_dir_entry
*
s_proc
;
/* proc entry */
...
...
@@ -771,11 +767,6 @@ struct f2fs_sb_info {
int
valid_super_block
;
/* valid super block no */
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
unsigned
int
blocks_per_blkz
;
/* F2FS blocks per zone */
unsigned
int
log_blocks_per_blkz
;
/* log2 F2FS blocks per zone */
...
...
fs/f2fs/namei.c
View file @
56735be0
...
...
@@ -403,7 +403,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
return
err
;
if
(
!
fscrypt_has_encryption_key
(
dir
))
return
-
E
PERM
;
return
-
E
NOKEY
;
disk_link
.
len
=
(
fscrypt_fname_encrypted_size
(
dir
,
len
)
+
sizeof
(
struct
fscrypt_symlink_data
));
...
...
@@ -447,7 +447,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
goto
err_out
;
if
(
!
fscrypt_has_encryption_key
(
inode
))
{
err
=
-
E
PERM
;
err
=
-
E
NOKEY
;
goto
err_out
;
}
...
...
fs/f2fs/super.c
View file @
56735be0
...
...
@@ -1156,12 +1156,6 @@ static int f2fs_get_context(struct inode *inode, void *ctx, size_t len)
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
,
void
*
fs_data
)
{
...
...
@@ -1177,8 +1171,8 @@ static unsigned f2fs_max_namelen(struct inode *inode)
}
static
struct
fscrypt_operations
f2fs_cryptops
=
{
.
key_prefix
=
"f2fs:"
,
.
get_context
=
f2fs_get_context
,
.
key_prefix
=
f2fs_key_prefix
,
.
set_context
=
f2fs_set_context
,
.
is_encrypted
=
f2fs_encrypted_inode
,
.
empty_dir
=
f2fs_empty_dir
,
...
...
@@ -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
[
DATA
]);
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
)
...
...
fs/ubifs/crypto.c
View file @
56735be0
...
...
@@ -26,15 +26,6 @@ static unsigned int ubifs_crypt_max_namelen(struct inode *inode)
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
,
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,
struct
fscrypt_operations
ubifs_crypt_operations
=
{
.
flags
=
FS_CFLG_OWN_PAGES
,
.
key_prefix
=
"ubifs:"
,
.
get_context
=
ubifs_crypt_get_context
,
.
set_context
=
ubifs_crypt_set_context
,
.
is_encrypted
=
__ubifs_crypt_is_encrypted
,
.
empty_dir
=
ubifs_crypt_empty_dir
,
.
max_namelen
=
ubifs_crypt_max_namelen
,
.
key_prefix
=
ubifs_key_prefix
,
};
include/linux/fscrypto.h
View file @
56735be0
...
...
@@ -35,7 +35,6 @@ struct fscrypt_ctx {
struct
list_head
free_list
;
/* Free list */
};
u8
flags
;
/* Flags */
u8
mode
;
/* Encryption mode for tfm */
};
/**
...
...
@@ -86,8 +85,8 @@ struct fscrypt_name {
*/
struct
fscrypt_operations
{
unsigned
int
flags
;
const
char
*
key_prefix
;
int
(
*
get_context
)(
struct
inode
*
,
void
*
,
size_t
);
int
(
*
key_prefix
)(
struct
inode
*
,
u8
**
);
int
(
*
prepare_context
)(
struct
inode
*
);
int
(
*
set_context
)(
struct
inode
*
,
const
void
*
,
size_t
,
void
*
);
int
(
*
dummy_context
)(
struct
inode
*
);
...
...
@@ -174,11 +173,8 @@ extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
u64
,
gfp_t
);
extern
int
fscrypt_decrypt_page
(
const
struct
inode
*
,
struct
page
*
,
unsigned
int
,
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
int
fscrypt_zeroout_range
(
const
struct
inode
*
,
pgoff_t
,
sector_t
,
unsigned
int
);
/* policy.c */
extern
int
fscrypt_ioctl_set_policy
(
struct
file
*
,
const
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,
const
struct
fscrypt_str
*
,
struct
fscrypt_str
*
);
extern
int
fscrypt_fname_usr_to_disk
(
struct
inode
*
,
const
struct
qstr
*
,
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
/* crypto.c */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment