162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * eCryptfs: Linux filesystem encryption layer
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 1997-2003 Erez Zadok
662306a36Sopenharmony_ci * Copyright (C) 2001-2003 Stony Brook University
762306a36Sopenharmony_ci * Copyright (C) 2004-2006 International Business Machines Corp.
862306a36Sopenharmony_ci *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
962306a36Sopenharmony_ci *              Michael C. Thompson <mcthomps@us.ibm.com>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/fs.h>
1362306a36Sopenharmony_ci#include <linux/mount.h>
1462306a36Sopenharmony_ci#include <linux/key.h>
1562306a36Sopenharmony_ci#include <linux/slab.h>
1662306a36Sopenharmony_ci#include <linux/seq_file.h>
1762306a36Sopenharmony_ci#include <linux/file.h>
1862306a36Sopenharmony_ci#include <linux/statfs.h>
1962306a36Sopenharmony_ci#include <linux/magic.h>
2062306a36Sopenharmony_ci#include "ecryptfs_kernel.h"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistruct kmem_cache *ecryptfs_inode_info_cache;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/**
2562306a36Sopenharmony_ci * ecryptfs_alloc_inode - allocate an ecryptfs inode
2662306a36Sopenharmony_ci * @sb: Pointer to the ecryptfs super block
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci * Called to bring an inode into existence.
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci * Only handle allocation, setting up structures should be done in
3162306a36Sopenharmony_ci * ecryptfs_read_inode. This is because the kernel, between now and
3262306a36Sopenharmony_ci * then, will 0 out the private data pointer.
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * Returns a pointer to a newly allocated inode, NULL otherwise
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_cistatic struct inode *ecryptfs_alloc_inode(struct super_block *sb)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	struct ecryptfs_inode_info *inode_info;
3962306a36Sopenharmony_ci	struct inode *inode = NULL;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	inode_info = alloc_inode_sb(sb, ecryptfs_inode_info_cache, GFP_KERNEL);
4262306a36Sopenharmony_ci	if (unlikely(!inode_info))
4362306a36Sopenharmony_ci		goto out;
4462306a36Sopenharmony_ci	if (ecryptfs_init_crypt_stat(&inode_info->crypt_stat)) {
4562306a36Sopenharmony_ci		kmem_cache_free(ecryptfs_inode_info_cache, inode_info);
4662306a36Sopenharmony_ci		goto out;
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ci	mutex_init(&inode_info->lower_file_mutex);
4962306a36Sopenharmony_ci	atomic_set(&inode_info->lower_file_count, 0);
5062306a36Sopenharmony_ci	inode_info->lower_file = NULL;
5162306a36Sopenharmony_ci	inode = &inode_info->vfs_inode;
5262306a36Sopenharmony_ciout:
5362306a36Sopenharmony_ci	return inode;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic void ecryptfs_free_inode(struct inode *inode)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	struct ecryptfs_inode_info *inode_info;
5962306a36Sopenharmony_ci	inode_info = ecryptfs_inode_to_private(inode);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	kmem_cache_free(ecryptfs_inode_info_cache, inode_info);
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/**
6562306a36Sopenharmony_ci * ecryptfs_destroy_inode
6662306a36Sopenharmony_ci * @inode: The ecryptfs inode
6762306a36Sopenharmony_ci *
6862306a36Sopenharmony_ci * This is used during the final destruction of the inode.  All
6962306a36Sopenharmony_ci * allocation of memory related to the inode, including allocated
7062306a36Sopenharmony_ci * memory in the crypt_stat struct, will be released here.
7162306a36Sopenharmony_ci * There should be no chance that this deallocation will be missed.
7262306a36Sopenharmony_ci */
7362306a36Sopenharmony_cistatic void ecryptfs_destroy_inode(struct inode *inode)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	struct ecryptfs_inode_info *inode_info;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	inode_info = ecryptfs_inode_to_private(inode);
7862306a36Sopenharmony_ci	BUG_ON(inode_info->lower_file);
7962306a36Sopenharmony_ci	ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat);
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci/**
8362306a36Sopenharmony_ci * ecryptfs_statfs
8462306a36Sopenharmony_ci * @dentry: The ecryptfs dentry
8562306a36Sopenharmony_ci * @buf: The struct kstatfs to fill in with stats
8662306a36Sopenharmony_ci *
8762306a36Sopenharmony_ci * Get the filesystem statistics. Currently, we let this pass right through
8862306a36Sopenharmony_ci * to the lower filesystem and take no action ourselves.
8962306a36Sopenharmony_ci */
9062306a36Sopenharmony_cistatic int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf)
9162306a36Sopenharmony_ci{
9262306a36Sopenharmony_ci	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
9362306a36Sopenharmony_ci	int rc;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	if (!lower_dentry->d_sb->s_op->statfs)
9662306a36Sopenharmony_ci		return -ENOSYS;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	rc = lower_dentry->d_sb->s_op->statfs(lower_dentry, buf);
9962306a36Sopenharmony_ci	if (rc)
10062306a36Sopenharmony_ci		return rc;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	buf->f_type = ECRYPTFS_SUPER_MAGIC;
10362306a36Sopenharmony_ci	rc = ecryptfs_set_f_namelen(&buf->f_namelen, buf->f_namelen,
10462306a36Sopenharmony_ci	       &ecryptfs_superblock_to_private(dentry->d_sb)->mount_crypt_stat);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return rc;
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/**
11062306a36Sopenharmony_ci * ecryptfs_evict_inode
11162306a36Sopenharmony_ci * @inode: The ecryptfs inode
11262306a36Sopenharmony_ci *
11362306a36Sopenharmony_ci * Called by iput() when the inode reference count reached zero
11462306a36Sopenharmony_ci * and the inode is not hashed anywhere.  Used to clear anything
11562306a36Sopenharmony_ci * that needs to be, before the inode is completely destroyed and put
11662306a36Sopenharmony_ci * on the inode free list. We use this to drop out reference to the
11762306a36Sopenharmony_ci * lower inode.
11862306a36Sopenharmony_ci */
11962306a36Sopenharmony_cistatic void ecryptfs_evict_inode(struct inode *inode)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	truncate_inode_pages_final(&inode->i_data);
12262306a36Sopenharmony_ci	clear_inode(inode);
12362306a36Sopenharmony_ci	iput(ecryptfs_inode_to_lower(inode));
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/*
12762306a36Sopenharmony_ci * ecryptfs_show_options
12862306a36Sopenharmony_ci *
12962306a36Sopenharmony_ci * Prints the mount options for a given superblock.
13062306a36Sopenharmony_ci * Returns zero; does not fail.
13162306a36Sopenharmony_ci */
13262306a36Sopenharmony_cistatic int ecryptfs_show_options(struct seq_file *m, struct dentry *root)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	struct super_block *sb = root->d_sb;
13562306a36Sopenharmony_ci	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
13662306a36Sopenharmony_ci		&ecryptfs_superblock_to_private(sb)->mount_crypt_stat;
13762306a36Sopenharmony_ci	struct ecryptfs_global_auth_tok *walker;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
14062306a36Sopenharmony_ci	list_for_each_entry(walker,
14162306a36Sopenharmony_ci			    &mount_crypt_stat->global_auth_tok_list,
14262306a36Sopenharmony_ci			    mount_crypt_stat_list) {
14362306a36Sopenharmony_ci		if (walker->flags & ECRYPTFS_AUTH_TOK_FNEK)
14462306a36Sopenharmony_ci			seq_printf(m, ",ecryptfs_fnek_sig=%s", walker->sig);
14562306a36Sopenharmony_ci		else
14662306a36Sopenharmony_ci			seq_printf(m, ",ecryptfs_sig=%s", walker->sig);
14762306a36Sopenharmony_ci	}
14862306a36Sopenharmony_ci	mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	seq_printf(m, ",ecryptfs_cipher=%s",
15162306a36Sopenharmony_ci		mount_crypt_stat->global_default_cipher_name);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	if (mount_crypt_stat->global_default_cipher_key_size)
15462306a36Sopenharmony_ci		seq_printf(m, ",ecryptfs_key_bytes=%zd",
15562306a36Sopenharmony_ci			   mount_crypt_stat->global_default_cipher_key_size);
15662306a36Sopenharmony_ci	if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)
15762306a36Sopenharmony_ci		seq_printf(m, ",ecryptfs_passthrough");
15862306a36Sopenharmony_ci	if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED)
15962306a36Sopenharmony_ci		seq_printf(m, ",ecryptfs_xattr_metadata");
16062306a36Sopenharmony_ci	if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
16162306a36Sopenharmony_ci		seq_printf(m, ",ecryptfs_encrypted_view");
16262306a36Sopenharmony_ci	if (mount_crypt_stat->flags & ECRYPTFS_UNLINK_SIGS)
16362306a36Sopenharmony_ci		seq_printf(m, ",ecryptfs_unlink_sigs");
16462306a36Sopenharmony_ci	if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY)
16562306a36Sopenharmony_ci		seq_printf(m, ",ecryptfs_mount_auth_tok_only");
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	return 0;
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ciconst struct super_operations ecryptfs_sops = {
17162306a36Sopenharmony_ci	.alloc_inode = ecryptfs_alloc_inode,
17262306a36Sopenharmony_ci	.destroy_inode = ecryptfs_destroy_inode,
17362306a36Sopenharmony_ci	.free_inode = ecryptfs_free_inode,
17462306a36Sopenharmony_ci	.statfs = ecryptfs_statfs,
17562306a36Sopenharmony_ci	.remount_fs = NULL,
17662306a36Sopenharmony_ci	.evict_inode = ecryptfs_evict_inode,
17762306a36Sopenharmony_ci	.show_options = ecryptfs_show_options
17862306a36Sopenharmony_ci};
179