fs/crypto/crypto.c

Source file repositories/reference/linux-study-clean/fs/crypto/crypto.c

File Facts

System
Linux kernel
Corpus path
fs/crypto/crypto.c
Extension
.c
Size
13717 bytes
Lines
419
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (err) {
			fscrypt_free_bounce_page(ciphertext_page);
			return ERR_PTR(err);
		}
	}
	SetPagePrivate(ciphertext_page);
	set_page_private(ciphertext_page, (unsigned long)folio);
	return ciphertext_page;
}
EXPORT_SYMBOL(fscrypt_encrypt_pagecache_blocks);

/**
 * fscrypt_encrypt_block_inplace() - Encrypt a filesystem block in-place
 * @inode:     The inode to which this block belongs
 * @page:      The page containing the block to encrypt
 * @len:       Size of block to encrypt.  This must be a multiple of
 *		FSCRYPT_CONTENTS_ALIGNMENT.
 * @offs:      Byte offset within @page at which the block to encrypt begins
 * @lblk_num:  Filesystem logical block number of the block, i.e. the 0-based
 *		number of the block within the file
 *
 * Encrypt a possibly-compressed filesystem block that is located in an
 * arbitrary page, not necessarily in the original pagecache page.  The @inode
 * and @lblk_num must be specified, as they can't be determined from @page.
 *
 * This is not compatible with fscrypt_operations::supports_subblock_data_units.
 *
 * Return: 0 on success; -errno on failure
 */
int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
				  unsigned int len, unsigned int offs,
				  u64 lblk_num)
{
	if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
		return -EOPNOTSUPP;
	return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode),
				       FS_ENCRYPT, lblk_num, page, page, len,
				       offs);
}
EXPORT_SYMBOL(fscrypt_encrypt_block_inplace);

/**
 * fscrypt_decrypt_pagecache_blocks() - Decrypt data from a pagecache folio
 * @folio: the pagecache folio containing the data to decrypt
 * @len: size of the data to decrypt, in bytes
 * @offs: offset within @folio of the data to decrypt, in bytes
 *
 * Decrypt data that has just been read from an encrypted file.  The data must
 * be located in a pagecache folio that is still locked and not yet uptodate.
 * The length and offset of the data must be aligned to the file's crypto data
 * unit size.  Alignment to the filesystem block size fulfills this requirement,
 * as the filesystem block size is always a multiple of the data unit size.
 *
 * Return: 0 on success; -errno on failure
 */
int fscrypt_decrypt_pagecache_blocks(struct folio *folio, size_t len,
				     size_t offs)
{
	const struct inode *inode = folio->mapping->host;
	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
	const unsigned int du_bits = ci->ci_data_unit_bits;
	const unsigned int du_size = 1U << du_bits;
	u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) +
		    (offs >> du_bits);
	size_t i;
	int err;

	if (WARN_ON_ONCE(!folio_test_locked(folio)))
		return -EINVAL;

	if (WARN_ON_ONCE(len <= 0 || !IS_ALIGNED(len | offs, du_size)))
		return -EINVAL;

	for (i = offs; i < offs + len; i += du_size, index++) {
		struct page *page = folio_page(folio, i >> PAGE_SHIFT);

		err = fscrypt_crypt_data_unit(ci, FS_DECRYPT, index, page,
					      page, du_size, i & ~PAGE_MASK);
		if (err)
			return err;
	}
	return 0;
}
EXPORT_SYMBOL(fscrypt_decrypt_pagecache_blocks);

/**
 * fscrypt_decrypt_block_inplace() - Decrypt a filesystem block in-place
 * @inode:     The inode to which this block belongs
 * @page:      The page containing the block to decrypt
 * @len:       Size of block to decrypt.  This must be a multiple of

Annotation

Implementation Notes