提交 237fead6 编写于 作者: M Michael Halcrow 提交者: Linus Torvalds

[PATCH] ecryptfs: fs/Makefile and fs/Kconfig

eCryptfs is a stacked cryptographic filesystem for Linux.  It is derived from
Erez Zadok's Cryptfs, implemented through the FiST framework for generating
stacked filesystems.  eCryptfs extends Cryptfs to provide advanced key
management and policy features.  eCryptfs stores cryptographic metadata in the
header of each file written, so that encrypted files can be copied between
hosts; the file will be decryptable with the proper key, and there is no need
to keep track of any additional information aside from what is already in the
encrypted file itself.

[akpm@osdl.org: updates for ongoing API changes]
[bunk@stusta.de: cleanups]
[akpm@osdl.org: alpha build fix]
[akpm@osdl.org: cleanups]
[tytso@mit.edu: inode-diet updates]
[pbadari@us.ibm.com: generic_file_*_read/write() interface updates]
[rdunlap@xenotime.net: printk format fixes]
[akpm@osdl.org: make slab creation and teardown table-driven]
Signed-off-by: NPhillip Hellewell <phillip@hellewell.homeip.net>
Signed-off-by: NMichael Halcrow <mhalcrow@us.ibm.com>
Signed-off-by: NErez Zadok <ezk@cs.sunysb.edu>
Signed-off-by: NAdrian Bunk <bunk@stusta.de>
Signed-off-by: NStephan Mueller <smueller@chronox.de>
Signed-off-by: N"Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: NBadari Pulavarty <pbadari@us.ibm.com>
Signed-off-by: NRandy Dunlap <rdunlap@xenotime.net>
Signed-off-by: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 f7aa2638
eCryptfs: A stacked cryptographic filesystem for Linux
eCryptfs is free software. Please see the file COPYING for details.
For documentation, please see the files in the doc/ subdirectory. For
building and installation instructions please see the INSTALL file.
Maintainer: Phillip Hellewell
Lead developer: Michael A. Halcrow <mhalcrow@us.ibm.com>
Developers: Michael C. Thompson
Kent Yoder
Web Site: http://ecryptfs.sf.net
This software is currently undergoing development. Make sure to
maintain a backup copy of any data you write into eCryptfs.
eCryptfs requires the userspace tools downloadable from the
SourceForge site:
http://sourceforge.net/projects/ecryptfs/
Userspace requirements include:
- David Howells' userspace keyring headers and libraries (version
1.0 or higher), obtainable from
http://people.redhat.com/~dhowells/keyutils/
- Libgcrypt
NOTES
In the beta/experimental releases of eCryptfs, when you upgrade
eCryptfs, you should copy the files to an unencrypted location and
then copy the files back into the new eCryptfs mount to migrate the
files.
MOUNT-WIDE PASSPHRASE
Create a new directory into which eCryptfs will write its encrypted
files (i.e., /root/crypt). Then, create the mount point directory
(i.e., /mnt/crypt). Now it's time to mount eCryptfs:
mount -t ecryptfs /root/crypt /mnt/crypt
You should be prompted for a passphrase and a salt (the salt may be
blank).
Try writing a new file:
echo "Hello, World" > /mnt/crypt/hello.txt
The operation will complete. Notice that there is a new file in
/root/crypt that is at least 12288 bytes in size (depending on your
host page size). This is the encrypted underlying file for what you
just wrote. To test reading, from start to finish, you need to clear
the user session keyring:
keyctl clear @u
Then umount /mnt/crypt and mount again per the instructions given
above.
cat /mnt/crypt/hello.txt
NOTES
eCryptfs version 0.1 should only be mounted on (1) empty directories
or (2) directories containing files only created by eCryptfs. If you
mount a directory that has pre-existing files not created by eCryptfs,
then behavior is undefined. Do not run eCryptfs in higher verbosity
levels unless you are doing so for the sole purpose of debugging or
development, since secret values will be written out to the system log
in that case.
Mike Halcrow
mhalcrow@us.ibm.com
......@@ -977,6 +977,13 @@ L: ebtables-devel@lists.sourceforge.net
W: http://ebtables.sourceforge.net/
S: Maintained
ECRYPT FILE SYSTEM
P: Mike Halcrow, Phillip Hellewell
M: mhalcrow@us.ibm.com, phillip@hellewell.homeip.net
L: ecryptfs-devel@lists.sourceforge.net
W: http://ecryptfs.sourceforge.net/
S: Supported
EDAC-CORE
P: Doug Thompson
M: norsk5@xmission.com
......
......@@ -995,6 +995,18 @@ config AFFS_FS
To compile this file system support as a module, choose M here: the
module will be called affs. If unsure, say N.
config ECRYPT_FS
tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
depends on EXPERIMENTAL && KEYS && CRYPTO
help
Encrypted filesystem that operates on the VFS layer. See
<file:Documentation/ecryptfs.txt> to learn more about
eCryptfs. Userspace components are required and can be
obtained from <http://ecryptfs.sf.net>.
To compile this file system support as a module, choose M here: the
module will be called ecryptfs.
config HFS_FS
tristate "Apple Macintosh file system support (EXPERIMENTAL)"
depends on BLOCK && EXPERIMENTAL
......
......@@ -75,6 +75,7 @@ obj-$(CONFIG_BFS_FS) += bfs/
obj-$(CONFIG_ISO9660_FS) += isofs/
obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+
obj-$(CONFIG_HFS_FS) += hfs/
obj-$(CONFIG_ECRYPT_FS) += ecryptfs/
obj-$(CONFIG_VXFS_FS) += freevxfs/
obj-$(CONFIG_NFS_FS) += nfs/
obj-$(CONFIG_EXPORTFS) += exportfs/
......
#
# Makefile for the Linux 2.6 eCryptfs
#
obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o debug.o
此差异已折叠。
/**
* eCryptfs: Linux filesystem encryption layer
* Functions only useful for debugging.
*
* Copyright (C) 2006 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "ecryptfs_kernel.h"
/**
* ecryptfs_dump_auth_tok - debug function to print auth toks
*
* This function will print the contents of an ecryptfs authentication
* token.
*/
void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok)
{
char salt[ECRYPTFS_SALT_SIZE * 2 + 1];
char sig[ECRYPTFS_SIG_SIZE_HEX + 1];
ecryptfs_printk(KERN_DEBUG, "Auth tok at mem loc [%p]:\n",
auth_tok);
if (ECRYPTFS_CHECK_FLAG(auth_tok->flags, ECRYPTFS_PRIVATE_KEY)) {
ecryptfs_printk(KERN_DEBUG, " * private key type\n");
ecryptfs_printk(KERN_DEBUG, " * (NO PRIVATE KEY SUPPORT "
"IN ECRYPTFS VERSION 0.1)\n");
} else {
ecryptfs_printk(KERN_DEBUG, " * passphrase type\n");
ecryptfs_to_hex(salt, auth_tok->token.password.salt,
ECRYPTFS_SALT_SIZE);
salt[ECRYPTFS_SALT_SIZE * 2] = '\0';
ecryptfs_printk(KERN_DEBUG, " * salt = [%s]\n", salt);
if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags,
ECRYPTFS_PERSISTENT_PASSWORD)) {
ecryptfs_printk(KERN_DEBUG, " * persistent\n");
}
memcpy(sig, auth_tok->token.password.signature,
ECRYPTFS_SIG_SIZE_HEX);
sig[ECRYPTFS_SIG_SIZE_HEX] = '\0';
ecryptfs_printk(KERN_DEBUG, " * signature = [%s]\n", sig);
}
ecryptfs_printk(KERN_DEBUG, " * session_key.flags = [0x%x]\n",
auth_tok->session_key.flags);
if (auth_tok->session_key.flags
& ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT)
ecryptfs_printk(KERN_DEBUG,
" * Userspace decrypt request set\n");
if (auth_tok->session_key.flags
& ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT)
ecryptfs_printk(KERN_DEBUG,
" * Userspace encrypt request set\n");
if (auth_tok->session_key.flags & ECRYPTFS_CONTAINS_DECRYPTED_KEY) {
ecryptfs_printk(KERN_DEBUG, " * Contains decrypted key\n");
ecryptfs_printk(KERN_DEBUG,
" * session_key.decrypted_key_size = [0x%x]\n",
auth_tok->session_key.decrypted_key_size);
ecryptfs_printk(KERN_DEBUG, " * Decrypted session key "
"dump:\n");
if (ecryptfs_verbosity > 0)
ecryptfs_dump_hex(auth_tok->session_key.decrypted_key,
ECRYPTFS_DEFAULT_KEY_BYTES);
}
if (auth_tok->session_key.flags & ECRYPTFS_CONTAINS_ENCRYPTED_KEY) {
ecryptfs_printk(KERN_DEBUG, " * Contains encrypted key\n");
ecryptfs_printk(KERN_DEBUG,
" * session_key.encrypted_key_size = [0x%x]\n",
auth_tok->session_key.encrypted_key_size);
ecryptfs_printk(KERN_DEBUG, " * Encrypted session key "
"dump:\n");
if (ecryptfs_verbosity > 0)
ecryptfs_dump_hex(auth_tok->session_key.encrypted_key,
auth_tok->session_key.
encrypted_key_size);
}
}
/**
* ecryptfs_dump_hex - debug hex printer
* @data: string of bytes to be printed
* @bytes: number of bytes to print
*
* Dump hexadecimal representation of char array
*/
void ecryptfs_dump_hex(char *data, int bytes)
{
int i = 0;
int add_newline = 1;
if (ecryptfs_verbosity < 1)
return;
if (bytes != 0) {
printk(KERN_DEBUG "0x%.2x.", (unsigned char)data[i]);
i++;
}
while (i < bytes) {
printk("0x%.2x.", (unsigned char)data[i]);
i++;
if (i % 16 == 0) {
printk("\n");
add_newline = 0;
} else
add_newline = 1;
}
if (add_newline)
printk("\n");
}
/**
* eCryptfs: Linux filesystem encryption layer
*
* Copyright (C) 1997-2003 Erez Zadok
* Copyright (C) 2001-2003 Stony Brook University
* Copyright (C) 2004-2006 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <linux/dcache.h>
#include <linux/namei.h>
#include "ecryptfs_kernel.h"
/**
* ecryptfs_d_revalidate - revalidate an ecryptfs dentry
* @dentry: The ecryptfs dentry
* @nd: The associated nameidata
*
* Called when the VFS needs to revalidate a dentry. This
* is called whenever a name lookup finds a dentry in the
* dcache. Most filesystems leave this as NULL, because all their
* dentries in the dcache are valid.
*
* Returns 1 if valid, 0 otherwise.
*
*/
static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
{
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
struct dentry *dentry_save;
struct vfsmount *vfsmount_save;
int rc = 1;
if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
goto out;
dentry_save = nd->dentry;
vfsmount_save = nd->mnt;
nd->dentry = lower_dentry;
nd->mnt = lower_mnt;
rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd);
nd->dentry = dentry_save;
nd->mnt = vfsmount_save;
out:
return rc;
}
struct kmem_cache *ecryptfs_dentry_info_cache;
/**
* ecryptfs_d_release
* @dentry: The ecryptfs dentry
*
* Called when a dentry is really deallocated.
*/
static void ecryptfs_d_release(struct dentry *dentry)
{
struct dentry *lower_dentry;
lower_dentry = ecryptfs_dentry_to_lower(dentry);
if (ecryptfs_dentry_to_private(dentry))
kmem_cache_free(ecryptfs_dentry_info_cache,
ecryptfs_dentry_to_private(dentry));
if (lower_dentry)
dput(lower_dentry);
return;
}
struct dentry_operations ecryptfs_dops = {
.d_revalidate = ecryptfs_d_revalidate,
.d_release = ecryptfs_d_release,
};
/**
* eCryptfs: Linux filesystem encryption layer
* Kernel declarations.
*
* Copyright (C) 1997-2003 Erez Zadok
* Copyright (C) 2001-2003 Stony Brook University
* Copyright (C) 2004-2006 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef ECRYPTFS_KERNEL_H
#define ECRYPTFS_KERNEL_H
#include <keys/user-type.h>
#include <linux/fs.h>
#include <linux/scatterlist.h>
/* Version verification for shared data structures w/ userspace */
#define ECRYPTFS_VERSION_MAJOR 0x00
#define ECRYPTFS_VERSION_MINOR 0x04
#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x01
/* These flags indicate which features are supported by the kernel
* module; userspace tools such as the mount helper read
* ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine
* how to behave. */
#define ECRYPTFS_VERSIONING_PASSPHRASE 0x00000001
#define ECRYPTFS_VERSIONING_PUBKEY 0x00000002
#define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
#define ECRYPTFS_VERSIONING_POLICY 0x00000008
#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
| ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH)
#define ECRYPTFS_MAX_PASSWORD_LENGTH 64
#define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
#define ECRYPTFS_SALT_SIZE 8
#define ECRYPTFS_SALT_SIZE_HEX (ECRYPTFS_SALT_SIZE*2)
/* The original signature size is only for what is stored on disk; all
* in-memory representations are expanded hex, so it better adapted to
* be passed around or referenced on the command line */
#define ECRYPTFS_SIG_SIZE 8
#define ECRYPTFS_SIG_SIZE_HEX (ECRYPTFS_SIG_SIZE*2)
#define ECRYPTFS_PASSWORD_SIG_SIZE ECRYPTFS_SIG_SIZE_HEX
#define ECRYPTFS_MAX_KEY_BYTES 64
#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512
#define ECRYPTFS_DEFAULT_IV_BYTES 16
#define ECRYPTFS_FILE_VERSION 0x01
#define ECRYPTFS_DEFAULT_HEADER_EXTENT_SIZE 8192
#define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096
#define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192
#define RFC2440_CIPHER_DES3_EDE 0x02
#define RFC2440_CIPHER_CAST_5 0x03
#define RFC2440_CIPHER_BLOWFISH 0x04
#define RFC2440_CIPHER_AES_128 0x07
#define RFC2440_CIPHER_AES_192 0x08
#define RFC2440_CIPHER_AES_256 0x09
#define RFC2440_CIPHER_TWOFISH 0x0a
#define RFC2440_CIPHER_CAST_6 0x0b
#define ECRYPTFS_SET_FLAG(flag_bit_vector, flag) (flag_bit_vector |= (flag))
#define ECRYPTFS_CLEAR_FLAG(flag_bit_vector, flag) (flag_bit_vector &= ~(flag))
#define ECRYPTFS_CHECK_FLAG(flag_bit_vector, flag) (flag_bit_vector & (flag))
/**
* For convenience, we may need to pass around the encrypted session
* key between kernel and userspace because the authentication token
* may not be extractable. For example, the TPM may not release the
* private key, instead requiring the encrypted data and returning the
* decrypted data.
*/
struct ecryptfs_session_key {
#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT 0x00000001
#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT 0x00000002
#define ECRYPTFS_CONTAINS_DECRYPTED_KEY 0x00000004
#define ECRYPTFS_CONTAINS_ENCRYPTED_KEY 0x00000008
u32 flags;
u32 encrypted_key_size;
u32 decrypted_key_size;
u8 encrypted_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES];
u8 decrypted_key[ECRYPTFS_MAX_KEY_BYTES];
};
struct ecryptfs_password {
u32 password_bytes;
s32 hash_algo;
u32 hash_iterations;
u32 session_key_encryption_key_bytes;
#define ECRYPTFS_PERSISTENT_PASSWORD 0x01
#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02
u32 flags;
/* Iterated-hash concatenation of salt and passphrase */
u8 session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
/* Always in expanded hex */
u8 salt[ECRYPTFS_SALT_SIZE];
};
enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY};
/* May be a password or a private key */
struct ecryptfs_auth_tok {
u16 version; /* 8-bit major and 8-bit minor */
u16 token_type;
u32 flags;
struct ecryptfs_session_key session_key;
u8 reserved[32];
union {
struct ecryptfs_password password;
/* Private key is in future eCryptfs releases */
} token;
} __attribute__ ((packed));
void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok);
extern void ecryptfs_to_hex(char *dst, char *src, size_t src_size);
extern void ecryptfs_from_hex(char *dst, char *src, int dst_size);
struct ecryptfs_key_record {
unsigned char type;
size_t enc_key_size;
unsigned char sig[ECRYPTFS_SIG_SIZE];
unsigned char enc_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES];
};
struct ecryptfs_auth_tok_list {
struct ecryptfs_auth_tok *auth_tok;
struct list_head list;
};
struct ecryptfs_crypt_stat;
struct ecryptfs_mount_crypt_stat;
struct ecryptfs_page_crypt_context {
struct page *page;
#define ECRYPTFS_PREPARE_COMMIT_MODE 0
#define ECRYPTFS_WRITEPAGE_MODE 1
unsigned int mode;
union {
struct file *lower_file;
struct writeback_control *wbc;
} param;
};
static inline struct ecryptfs_auth_tok *
ecryptfs_get_key_payload_data(struct key *key)
{
return (struct ecryptfs_auth_tok *)
(((struct user_key_payload*)key->payload.data)->data);
}
#define ECRYPTFS_SUPER_MAGIC 0xf15f
#define ECRYPTFS_MAX_KEYSET_SIZE 1024
#define ECRYPTFS_MAX_CIPHER_NAME_SIZE 32
#define ECRYPTFS_MAX_NUM_ENC_KEYS 64
#define ECRYPTFS_MAX_NUM_KEYSIGS 2 /* TODO: Make this a linked list */
#define ECRYPTFS_MAX_IV_BYTES 16 /* 128 bits */
#define ECRYPTFS_SALT_BYTES 2
#define MAGIC_ECRYPTFS_MARKER 0x3c81b7f5
#define MAGIC_ECRYPTFS_MARKER_SIZE_BYTES 8 /* 4*2 */
#define ECRYPTFS_FILE_SIZE_BYTES 8
#define ECRYPTFS_DEFAULT_CIPHER "aes"
#define ECRYPTFS_DEFAULT_KEY_BYTES 16
#define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC
#define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C
#define ECRYPTFS_TAG_11_PACKET_TYPE 0xED
#define MD5_DIGEST_SIZE 16
/**
* This is the primary struct associated with each encrypted file.
*
* TODO: cache align/pack?
*/
struct ecryptfs_crypt_stat {
#define ECRYPTFS_STRUCT_INITIALIZED 0x00000001
#define ECRYPTFS_POLICY_APPLIED 0x00000002
#define ECRYPTFS_NEW_FILE 0x00000004
#define ECRYPTFS_ENCRYPTED 0x00000008
#define ECRYPTFS_SECURITY_WARNING 0x00000010
#define ECRYPTFS_ENABLE_HMAC 0x00000020
#define ECRYPTFS_ENCRYPT_IV_PAGES 0x00000040
#define ECRYPTFS_KEY_VALID 0x00000080
u32 flags;
unsigned int file_version;
size_t iv_bytes;
size_t num_keysigs;
size_t header_extent_size;
size_t num_header_extents_at_front;
size_t extent_size; /* Data extent size; default is 4096 */
size_t key_size;
size_t extent_shift;
unsigned int extent_mask;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
struct crypto_tfm *tfm;
struct crypto_tfm *md5_tfm; /* Crypto context for generating
* the initialization vectors */
unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE];
unsigned char key[ECRYPTFS_MAX_KEY_BYTES];
unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES];
unsigned char keysigs[ECRYPTFS_MAX_NUM_KEYSIGS][ECRYPTFS_SIG_SIZE_HEX];
struct mutex cs_tfm_mutex;
struct mutex cs_md5_tfm_mutex;
struct mutex cs_mutex;
};
/* inode private data. */
struct ecryptfs_inode_info {
struct inode vfs_inode;
struct inode *wii_inode;
struct ecryptfs_crypt_stat crypt_stat;
};
/* dentry private data. Each dentry must keep track of a lower
* vfsmount too. */
struct ecryptfs_dentry_info {
struct dentry *wdi_dentry;
struct vfsmount *lower_mnt;
struct ecryptfs_crypt_stat *crypt_stat;
};
/**
* This struct is to enable a mount-wide passphrase/salt combo. This
* is more or less a stopgap to provide similar functionality to other
* crypto filesystems like EncFS or CFS until full policy support is
* implemented in eCryptfs.
*/
struct ecryptfs_mount_crypt_stat {
/* Pointers to memory we do not own, do not free these */
#define ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED 0x00000001
u32 flags;
struct ecryptfs_auth_tok *global_auth_tok;
struct key *global_auth_tok_key;
size_t global_default_cipher_key_size;
struct crypto_tfm *global_key_tfm;
struct mutex global_key_tfm_mutex;
unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE
+ 1];
unsigned char global_auth_tok_sig[ECRYPTFS_SIG_SIZE_HEX + 1];
};
/* superblock private data. */
struct ecryptfs_sb_info {
struct super_block *wsi_sb;
struct ecryptfs_mount_crypt_stat mount_crypt_stat;
};
/* file private data. */
struct ecryptfs_file_info {
struct file *wfi_file;
struct ecryptfs_crypt_stat *crypt_stat;
};
/* auth_tok <=> encrypted_session_key mappings */
struct ecryptfs_auth_tok_list_item {
unsigned char encrypted_session_key[ECRYPTFS_MAX_KEY_BYTES];
struct list_head list;
struct ecryptfs_auth_tok auth_tok;
};
static inline struct ecryptfs_file_info *
ecryptfs_file_to_private(struct file *file)
{
return (struct ecryptfs_file_info *)file->private_data;
}
static inline void
ecryptfs_set_file_private(struct file *file,
struct ecryptfs_file_info *file_info)
{
file->private_data = file_info;
}
static inline struct file *ecryptfs_file_to_lower(struct file *file)
{
return ((struct ecryptfs_file_info *)file->private_data)->wfi_file;
}
static inline void
ecryptfs_set_file_lower(struct file *file, struct file *lower_file)
{
((struct ecryptfs_file_info *)file->private_data)->wfi_file =
lower_file;
}
static inline struct ecryptfs_inode_info *
ecryptfs_inode_to_private(struct inode *inode)
{
return container_of(inode, struct ecryptfs_inode_info, vfs_inode);
}
static inline struct inode *ecryptfs_inode_to_lower(struct inode *inode)
{
return ecryptfs_inode_to_private(inode)->wii_inode;
}
static inline void
ecryptfs_set_inode_lower(struct inode *inode, struct inode *lower_inode)
{
ecryptfs_inode_to_private(inode)->wii_inode = lower_inode;
}
static inline struct ecryptfs_sb_info *
ecryptfs_superblock_to_private(struct super_block *sb)
{
return (struct ecryptfs_sb_info *)sb->s_fs_info;
}
static inline void
ecryptfs_set_superblock_private(struct super_block *sb,
struct ecryptfs_sb_info *sb_info)
{
sb->s_fs_info = sb_info;
}
static inline struct super_block *
ecryptfs_superblock_to_lower(struct super_block *sb)
{
return ((struct ecryptfs_sb_info *)sb->s_fs_info)->wsi_sb;
}
static inline void
ecryptfs_set_superblock_lower(struct super_block *sb,
struct super_block *lower_sb)
{
((struct ecryptfs_sb_info *)sb->s_fs_info)->wsi_sb = lower_sb;
}
static inline struct ecryptfs_dentry_info *
ecryptfs_dentry_to_private(struct dentry *dentry)
{
return (struct ecryptfs_dentry_info *)dentry->d_fsdata;
}
static inline void
ecryptfs_set_dentry_private(struct dentry *dentry,
struct ecryptfs_dentry_info *dentry_info)
{
dentry->d_fsdata = dentry_info;
}
static inline struct dentry *
ecryptfs_dentry_to_lower(struct dentry *dentry)
{
return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->wdi_dentry;
}
static inline void
ecryptfs_set_dentry_lower(struct dentry *dentry, struct dentry *lower_dentry)
{
((struct ecryptfs_dentry_info *)dentry->d_fsdata)->wdi_dentry =
lower_dentry;
}
static inline struct vfsmount *
ecryptfs_dentry_to_lower_mnt(struct dentry *dentry)
{
return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_mnt;
}
static inline void
ecryptfs_set_dentry_lower_mnt(struct dentry *dentry, struct vfsmount *lower_mnt)
{
((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_mnt =
lower_mnt;
}
#define ecryptfs_printk(type, fmt, arg...) \
__ecryptfs_printk(type "%s: " fmt, __FUNCTION__, ## arg);
void __ecryptfs_printk(const char *fmt, ...);
extern const struct file_operations ecryptfs_main_fops;
extern const struct file_operations ecryptfs_dir_fops;
extern struct inode_operations ecryptfs_main_iops;
extern struct inode_operations ecryptfs_dir_iops;
extern struct inode_operations ecryptfs_symlink_iops;
extern struct super_operations ecryptfs_sops;
extern struct dentry_operations ecryptfs_dops;
extern struct address_space_operations ecryptfs_aops;
extern int ecryptfs_verbosity;
extern struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
extern struct kmem_cache *ecryptfs_file_info_cache;
extern struct kmem_cache *ecryptfs_dentry_info_cache;
extern struct kmem_cache *ecryptfs_inode_info_cache;
extern struct kmem_cache *ecryptfs_sb_info_cache;
extern struct kmem_cache *ecryptfs_header_cache_0;
extern struct kmem_cache *ecryptfs_header_cache_1;
extern struct kmem_cache *ecryptfs_header_cache_2;
extern struct kmem_cache *ecryptfs_lower_page_cache;
int ecryptfs_interpose(struct dentry *hidden_dentry,
struct dentry *this_dentry, struct super_block *sb,
int flag);
int ecryptfs_fill_zeros(struct file *file, loff_t new_length);
int ecryptfs_decode_filename(struct ecryptfs_crypt_stat *crypt_stat,
const char *name, int length,
char **decrypted_name);
int ecryptfs_encode_filename(struct ecryptfs_crypt_stat *crypt_stat,
const char *name, int length,
char **encoded_name);
struct dentry *ecryptfs_lower_dentry(struct dentry *this_dentry);
void ecryptfs_copy_attr_atime(struct inode *dest, const struct inode *src);
void ecryptfs_copy_attr_all(struct inode *dest, const struct inode *src);
void ecryptfs_copy_inode_size(struct inode *dst, const struct inode *src);
void ecryptfs_dump_hex(char *data, int bytes);
int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
int sg_size);
int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat);
void ecryptfs_rotate_iv(unsigned char *iv);
void ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat);
void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat);
void ecryptfs_destruct_mount_crypt_stat(
struct ecryptfs_mount_crypt_stat *mount_crypt_stat);
int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat);
int ecryptfs_write_inode_size_to_header(struct file *lower_file,
struct inode *lower_inode,
struct inode *inode);
int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
struct file *lower_file,
unsigned long lower_page_index, int byte_offset,
int region_bytes);
int
ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode,
struct file *lower_file, int byte_offset,
int region_size);
int ecryptfs_copy_page_to_lower(struct page *page, struct inode *lower_inode,
struct file *lower_file);
int ecryptfs_do_readpage(struct file *file, struct page *page,
pgoff_t lower_page_index);
int ecryptfs_grab_and_map_lower_page(struct page **lower_page,
char **lower_virt,
struct inode *lower_inode,
unsigned long lower_page_index);
int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
struct inode *lower_inode,
struct writeback_control *wbc);
int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx);
int ecryptfs_decrypt_page(struct file *file, struct page *page);
int ecryptfs_write_headers(struct dentry *ecryptfs_dentry,
struct file *lower_file);
int ecryptfs_write_headers_virt(char *page_virt,
struct ecryptfs_crypt_stat *crypt_stat,
struct dentry *ecryptfs_dentry);
int ecryptfs_read_headers(struct dentry *ecryptfs_dentry,
struct file *lower_file);
int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry);
int contains_ecryptfs_marker(char *data);
int ecryptfs_read_header_region(char *data, struct dentry *dentry,
struct vfsmount *mnt);
u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat);
int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code);
void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat);
int ecryptfs_generate_key_packet_set(char *dest_base,
struct ecryptfs_crypt_stat *crypt_stat,
struct dentry *ecryptfs_dentry,
size_t *len, size_t max);
int process_request_key_err(long err_code);
int
ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
unsigned char *src, struct dentry *ecryptfs_dentry);
int ecryptfs_truncate(struct dentry *dentry, loff_t new_length);
int
ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm,
char *cipher_name, size_t key_size);
int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode);
int ecryptfs_inode_set(struct inode *inode, void *lower_inode);
void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode);
#endif /* #ifndef ECRYPTFS_KERNEL_H */
/**
* eCryptfs: Linux filesystem encryption layer
*
* Copyright (C) 1997-2004 Erez Zadok
* Copyright (C) 2001-2004 Stony Brook University
* Copyright (C) 2004-2006 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
* Michael C. Thompson <mcthomps@us.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <linux/file.h>
#include <linux/poll.h>
#include <linux/mount.h>
#include <linux/pagemap.h>
#include <linux/security.h>
#include <linux/smp_lock.h>
#include <linux/compat.h>
#include "ecryptfs_kernel.h"
/**
* ecryptfs_llseek
* @file: File we are seeking in
* @offset: The offset to seek to
* @origin: 2 - offset from i_size; 1 - offset from f_pos
*
* Returns the position we have seeked to, or negative on error
*/
static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin)
{
loff_t rv;
loff_t new_end_pos;
int rc;
int expanding_file = 0;
struct inode *inode = file->f_mapping->host;
/* If our offset is past the end of our file, we're going to
* need to grow it so we have a valid length of 0's */
new_end_pos = offset;
switch (origin) {
case 2:
new_end_pos += i_size_read(inode);
expanding_file = 1;
break;
case 1:
new_end_pos += file->f_pos;
if (new_end_pos > i_size_read(inode)) {
ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) "
"> i_size_read(inode)(=[0x%.16x])\n",
new_end_pos, i_size_read(inode));
expanding_file = 1;
}
break;
default:
if (new_end_pos > i_size_read(inode)) {
ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) "
"> i_size_read(inode)(=[0x%.16x])\n",
new_end_pos, i_size_read(inode));
expanding_file = 1;
}
}
ecryptfs_printk(KERN_DEBUG, "new_end_pos = [0x%.16x]\n", new_end_pos);
if (expanding_file) {
rc = ecryptfs_truncate(file->f_dentry, new_end_pos);
if (rc) {
rv = rc;
ecryptfs_printk(KERN_ERR, "Error on attempt to "
"truncate to (higher) offset [0x%.16x];"
" rc = [%d]\n", new_end_pos, rc);
goto out;
}
}
rv = generic_file_llseek(file, offset, origin);
out:
return rv;
}
/**
* ecryptfs_read_update_atime
*
* generic_file_read updates the atime of upper layer inode. But, it
* doesn't give us a chance to update the atime of the lower layer
* inode. This function is a wrapper to generic_file_read. It
* updates the atime of the lower level inode if generic_file_read
* returns without any errors. This is to be used only for file reads.
* The function to be used for directory reads is ecryptfs_read.
*/
static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
int rc;
struct dentry *lower_dentry;
struct vfsmount *lower_vfsmount;
struct file *file = iocb->ki_filp;
rc = generic_file_aio_read(iocb, iov, nr_segs, pos);
/*
* Even though this is a async interface, we need to wait
* for IO to finish to update atime
*/
if (-EIOCBQUEUED == rc)
rc = wait_on_sync_kiocb(iocb);
if (rc >= 0) {
lower_dentry = ecryptfs_dentry_to_lower(file->f_dentry);
lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_dentry);
touch_atime(lower_vfsmount, lower_dentry);
}
return rc;
}
struct ecryptfs_getdents_callback {
void *dirent;
struct dentry *dentry;
filldir_t filldir;
int err;
int filldir_called;
int entries_written;
};
/* Inspired by generic filldir in fs/readir.c */
static int
ecryptfs_filldir(void *dirent, const char *name, int namelen, loff_t offset,
u64 ino, unsigned int d_type)
{
struct ecryptfs_crypt_stat *crypt_stat;
struct ecryptfs_getdents_callback *buf =
(struct ecryptfs_getdents_callback *)dirent;
int rc;
int decoded_length;
char *decoded_name;
crypt_stat = ecryptfs_dentry_to_private(buf->dentry)->crypt_stat;
buf->filldir_called++;
decoded_length = ecryptfs_decode_filename(crypt_stat, name, namelen,
&decoded_name);
if (decoded_length < 0) {
rc = decoded_length;
goto out;
}
rc = buf->filldir(buf->dirent, decoded_name, decoded_length, offset,
ino, d_type);
kfree(decoded_name);
if (rc >= 0)
buf->entries_written++;
out:
return rc;
}
/**
* ecryptfs_readdir
* @file: The ecryptfs file struct
* @dirent: Directory entry
* @filldir: The filldir callback function
*/
static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
{
int rc;
struct file *lower_file;
struct inode *inode;
struct ecryptfs_getdents_callback buf;
lower_file = ecryptfs_file_to_lower(file);
lower_file->f_pos = file->f_pos;
inode = file->f_dentry->d_inode;
memset(&buf, 0, sizeof(buf));
buf.dirent = dirent;
buf.dentry = file->f_dentry;
buf.filldir = filldir;
retry:
buf.filldir_called = 0;
buf.entries_written = 0;
buf.err = 0;
rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf);
if (buf.err)
rc = buf.err;
if (buf.filldir_called && !buf.entries_written)
goto retry;
file->f_pos = lower_file->f_pos;
if (rc >= 0)
ecryptfs_copy_attr_atime(inode, lower_file->f_dentry->d_inode);
return rc;
}
struct kmem_cache *ecryptfs_file_info_cache;
/**
* ecryptfs_open
* @inode: inode speciying file to open
* @file: Structure to return filled in
*
* Opens the file specified by inode.
*
* Returns zero on success; non-zero otherwise
*/
static int ecryptfs_open(struct inode *inode, struct file *file)
{
int rc = 0;
struct ecryptfs_crypt_stat *crypt_stat = NULL;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
struct dentry *ecryptfs_dentry = file->f_dentry;
/* Private value of ecryptfs_dentry allocated in
* ecryptfs_lookup() */
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
struct inode *lower_inode = NULL;
struct file *lower_file = NULL;
struct vfsmount *lower_mnt;
struct ecryptfs_file_info *file_info;
int lower_flags;
/* Released in ecryptfs_release or end of function if failure */
file_info = kmem_cache_alloc(ecryptfs_file_info_cache, SLAB_KERNEL);
ecryptfs_set_file_private(file, file_info);
if (!file_info) {
ecryptfs_printk(KERN_ERR,
"Error attempting to allocate memory\n");
rc = -ENOMEM;
goto out;
}
memset(file_info, 0, sizeof(*file_info));
lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
mount_crypt_stat = &ecryptfs_superblock_to_private(
ecryptfs_dentry->d_sb)->mount_crypt_stat;
mutex_lock(&crypt_stat->cs_mutex);
if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) {
ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n");
/* Policy code enabled in future release */
ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED);
ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
}
mutex_unlock(&crypt_stat->cs_mutex);
/* This mntget & dget is undone via fput when the file is released */
dget(lower_dentry);
lower_flags = file->f_flags;
if ((lower_flags & O_ACCMODE) == O_WRONLY)
lower_flags = (lower_flags & O_ACCMODE) | O_RDWR;
if (file->f_flags & O_APPEND)
lower_flags &= ~O_APPEND;
lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
mntget(lower_mnt);
/* Corresponding fput() in ecryptfs_release() */
lower_file = dentry_open(lower_dentry, lower_mnt, lower_flags);
if (IS_ERR(lower_file)) {
rc = PTR_ERR(lower_file);
ecryptfs_printk(KERN_ERR, "Error opening lower file\n");
goto out_puts;
}
ecryptfs_set_file_lower(file, lower_file);
/* Isn't this check the same as the one in lookup? */
lower_inode = lower_dentry->d_inode;
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
rc = 0;
goto out;
}
mutex_lock(&crypt_stat->cs_mutex);
if (i_size_read(lower_inode) < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
if (!(mount_crypt_stat->flags
& ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
rc = -EIO;
printk(KERN_WARNING "Attempt to read file that is "
"not in a valid eCryptfs format, and plaintext "
"passthrough mode is not enabled; returning "
"-EIO\n");
mutex_unlock(&crypt_stat->cs_mutex);
goto out_puts;
}
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
rc = 0;
mutex_unlock(&crypt_stat->cs_mutex);
goto out;
} else if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
ECRYPTFS_POLICY_APPLIED)
|| !ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
ECRYPTFS_KEY_VALID)) {
rc = ecryptfs_read_headers(ecryptfs_dentry, lower_file);
if (rc) {
ecryptfs_printk(KERN_DEBUG,
"Valid headers not found\n");
if (!(mount_crypt_stat->flags
& ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
rc = -EIO;
printk(KERN_WARNING "Attempt to read file that "
"is not in a valid eCryptfs format, "
"and plaintext passthrough mode is not "
"enabled; returning -EIO\n");
mutex_unlock(&crypt_stat->cs_mutex);
goto out_puts;
}
ECRYPTFS_CLEAR_FLAG(crypt_stat->flags,
ECRYPTFS_ENCRYPTED);
rc = 0;
mutex_unlock(&crypt_stat->cs_mutex);
goto out;
}
}
mutex_unlock(&crypt_stat->cs_mutex);
ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = [0x%.16x] "
"size: [0x%.16x]\n", inode, inode->i_ino,
i_size_read(inode));
ecryptfs_set_file_lower(file, lower_file);
goto out;
out_puts:
mntput(lower_mnt);
dput(lower_dentry);
kmem_cache_free(ecryptfs_file_info_cache,
ecryptfs_file_to_private(file));
out:
return rc;
}
static int ecryptfs_flush(struct file *file, fl_owner_t td)
{
int rc = 0;
struct file *lower_file = NULL;
lower_file = ecryptfs_file_to_lower(file);
if (lower_file->f_op && lower_file->f_op->flush)
rc = lower_file->f_op->flush(lower_file, td);
return rc;
}
static int ecryptfs_release(struct inode *inode, struct file *file)
{
struct file *lower_file = ecryptfs_file_to_lower(file);
struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file);
struct inode *lower_inode = ecryptfs_inode_to_lower(inode);
fput(lower_file);
inode->i_blocks = lower_inode->i_blocks;
kmem_cache_free(ecryptfs_file_info_cache, file_info);
return 0;
}
static int
ecryptfs_fsync(struct file *file, struct dentry *dentry, int datasync)
{
struct file *lower_file = ecryptfs_file_to_lower(file);
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
struct inode *lower_inode = lower_dentry->d_inode;
int rc = -EINVAL;
if (lower_inode->i_fop->fsync) {
mutex_lock(&lower_inode->i_mutex);
rc = lower_inode->i_fop->fsync(lower_file, lower_dentry,
datasync);
mutex_unlock(&lower_inode->i_mutex);
}
return rc;
}
static int ecryptfs_fasync(int fd, struct file *file, int flag)
{
int rc = 0;
struct file *lower_file = NULL;
lower_file = ecryptfs_file_to_lower(file);
if (lower_file->f_op && lower_file->f_op->fasync)
rc = lower_file->f_op->fasync(fd, lower_file, flag);
return rc;
}
static ssize_t ecryptfs_sendfile(struct file *file, loff_t * ppos,
size_t count, read_actor_t actor, void *target)
{
struct file *lower_file = NULL;
int rc = -EINVAL;
lower_file = ecryptfs_file_to_lower(file);
if (lower_file->f_op && lower_file->f_op->sendfile)
rc = lower_file->f_op->sendfile(lower_file, ppos, count,
actor, target);
return rc;
}
static int ecryptfs_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
const struct file_operations ecryptfs_dir_fops = {
.readdir = ecryptfs_readdir,
.ioctl = ecryptfs_ioctl,
.mmap = generic_file_mmap,
.open = ecryptfs_open,
.flush = ecryptfs_flush,
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
.sendfile = ecryptfs_sendfile,
};
const struct file_operations ecryptfs_main_fops = {
.llseek = ecryptfs_llseek,
.read = do_sync_read,
.aio_read = ecryptfs_read_update_atime,
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.readdir = ecryptfs_readdir,
.ioctl = ecryptfs_ioctl,
.mmap = generic_file_mmap,
.open = ecryptfs_open,
.flush = ecryptfs_flush,
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
.sendfile = ecryptfs_sendfile,
};
static int
ecryptfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
int rc = 0;
struct file *lower_file = NULL;
if (ecryptfs_file_to_private(file))
lower_file = ecryptfs_file_to_lower(file);
if (lower_file && lower_file->f_op && lower_file->f_op->ioctl)
rc = lower_file->f_op->ioctl(ecryptfs_inode_to_lower(inode),
lower_file, cmd, arg);
else
rc = -ENOTTY;
return rc;
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册