a0bdc392de
* aosp/upstream-f2fs-stable-linux-6.1.y: fscrypt: support decrypting data from large folios fsverity: support verifying data from large folios fsverity.rst: update git repo URL for fsverity-utils ext4: allow verity with fs block size < PAGE_SIZE fs/buffer.c: support fsverity in block_read_full_folio() f2fs: simplify f2fs_readpage_limit() ext4: simplify ext4_readpage_limit() fsverity: support enabling with tree block size < PAGE_SIZE fsverity: support verification with tree block size < PAGE_SIZE fsverity: replace fsverity_hash_page() with fsverity_hash_block() fsverity: use EFBIG for file too large to enable verity fsverity: store log2(digest_size) precomputed fsverity: simplify Merkle tree readahead size calculation fsverity: use unsigned long for level_start fsverity: remove debug messages and CONFIG_FS_VERITY_DEBUG fsverity: pass pos and size to ->write_merkle_tree_block fsverity: optimize fsverity_cleanup_inode() on non-verity files fsverity: optimize fsverity_prepare_setattr() on non-verity files fsverity: optimize fsverity_file_open() on non-verity files fscrypt: clean up fscrypt_add_test_dummy_key() fs/super.c: stop calling fscrypt_destroy_keyring() from __put_super() f2fs: stop calling fscrypt_add_test_dummy_key() ext4: stop calling fscrypt_add_test_dummy_key() fscrypt: add the test dummy encryption key on-demand f2fs: drop unnecessary arg for f2fs_ioc_*() f2fs: Revert "f2fs: truncate blocks in batch in __complete_revoke_list()" f2fs: synchronize atomic write aborts f2fs: fix wrong segment count f2fs: replace si->sbi w/ sbi in stat_show() f2fs: export ipu policy in debugfs f2fs: make kobj_type structures constant f2fs: fix to do sanity check on extent cache correctly f2fs: add missing description for ipu_policy node f2fs: fix to set ipu policy f2fs: fix typos in comments f2fs: fix kernel crash due to null io->bio f2fs: use iostat_lat_type directly as a parameter in the iostat_update_and_unbind_ctx() f2fs: add sysfs nodes to set last_age_weight f2fs: fix f2fs_show_options to show nogc_merge mount option f2fs: fix cgroup writeback accounting with fs-layer encryption f2fs: fix wrong calculation of block age f2fs: fix to update age extent in f2fs_do_zero_range() f2fs: fix to update age extent correctly during truncation f2fs: fix to avoid potential memory corruption in __update_iostat_latency() f2fs: retry to update the inode page given data corruption f2fs: fix to handle F2FS_IOC_START_ATOMIC_REPLACE in f2fs_compat_ioctl() f2fs: clean up i_compress_flag and i_compress_level usage f2fs: reduce stack memory cost by using bitfield in struct f2fs_io_info f2fs: factor the read/write tracing logic into a helper f2fs: remove __has_curseg_space f2fs: refactor next blk selection f2fs: remove __allocate_new_section f2fs: refactor __allocate_new_segment f2fs: add a f2fs_curseg_valid_blocks helper f2fs: simplify do_checkpoint f2fs: remove __add_sum_entry f2fs: fix to abort atomic write only during do_exist() f2fs: allow set compression option of files without blocks f2fs: fix information leak in f2fs_move_inline_dirents() fs: f2fs: initialize fsdata in pagecache_write() f2fs: fix to check warm_data_age_threshold f2fs: return true if all cmd were issued or no cmd need to be issued for f2fs_issue_discard_timeout() f2fs: clarify compress level bit offset f2fs: fix to show discard_unit mount opt f2fs: fix to do sanity check on extent cache correctly f2fs: remove unneeded f2fs_cp_error() in f2fs_create_whiteout() f2fs: clear atomic_write_task in f2fs_abort_atomic_write() f2fs: introduce trace_f2fs_replace_atomic_write_block f2fs: introduce discard_io_aware_gran sysfs node f2fs: drop useless initializer and unneeded local variable f2fs: add iostat support for flush f2fs: support accounting iostat count and avg_bytes f2fs: convert discard_wake and gc_wake to bool type f2fs: convert to use MIN_DISCARD_GRANULARITY macro f2fs: merge f2fs_show_injection_info() into time_to_inject() f2fs: add a f2fs_ prefix to punch_hole() and expand_inode_data() f2fs: remove unnecessary blank lines f2fs: mark f2fs_init_compress_mempool w/ __init f2fs: judge whether discard_unit is section only when have CONFIG_BLK_DEV_ZONED f2fs: start freeing cluster pages from the unused number MAINTAINERS: Add f2fs's patchwork f2fs: deliver the accumulated 'issued' to __issue_discard_cmd_orderly() f2fs: avoid to check PG_error flag f2fs: add missing doc for fault injection sysfs f2fs: fix to avoid potential deadlock f2fs: introduce IS_F2FS_IPU_* macro f2fs: refactor the hole reporting and allocation logic in f2fs_map_blocks f2fs: factor out a f2fs_map_no_dnode f2fs: factor a f2fs_map_blocks_cached helper f2fs: remove the create argument to f2fs_map_blocks f2fs: remove f2fs_get_block docs: f2fs: fix html doc error f2fs: simplify __allocate_data_block f2fs: reflow prepare_write_begin f2fs: f2fs_do_map_lock f2fs: add a f2fs_get_block_locked helper f2fs: add a f2fs_lookup_extent_cache_block helper f2fs: split __submit_bio f2fs: rename F2FS_MAP_UNWRITTEN to F2FS_MAP_DELALLOC f2fs: decouple F2FS_MAP_ from buffer head flags f2fs: don't rely on F2FS_MAP_* in f2fs_iomap_begin f2fs: fix to call clear_page_private_reference in .{release,invalid}_folio f2fs: remove unused PAGE_PRIVATE_ATOMIC_WRITE f2fs: fix to support .migrate_folio for compressed inode f2fs: file: drop useless initializer in expand_inode_data() Bug: 264705711 Bug: 269384820 Bug: 269593531 Change-Id: Ib84dc3389b6a06068a10d427c03f6dbc034831a6 Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
179 lines
4.7 KiB
C
179 lines
4.7 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Verification of builtin signatures
|
|
*
|
|
* Copyright 2019 Google LLC
|
|
*/
|
|
|
|
#include "fsverity_private.h"
|
|
|
|
#include <linux/cred.h>
|
|
#include <linux/key.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/verification.h>
|
|
|
|
/*
|
|
* /proc/sys/fs/verity/require_signatures
|
|
* If 1, all verity files must have a valid builtin signature.
|
|
*/
|
|
static int fsverity_require_signatures;
|
|
|
|
/*
|
|
* Keyring that contains the trusted X.509 certificates.
|
|
*
|
|
* Only root (kuid=0) can modify this. Also, root may use
|
|
* keyctl_restrict_keyring() to prevent any more additions.
|
|
*/
|
|
static struct key *fsverity_keyring;
|
|
|
|
/**
|
|
* fsverity_verify_signature() - check a verity file's signature
|
|
* @vi: the file's fsverity_info
|
|
* @signature: the file's built-in signature
|
|
* @sig_size: size of signature in bytes, or 0 if no signature
|
|
*
|
|
* If the file includes a signature of its fs-verity file digest, verify it
|
|
* against the certificates in the fs-verity keyring.
|
|
*
|
|
* Return: 0 on success (signature valid or not required); -errno on failure
|
|
*/
|
|
int fsverity_verify_signature(const struct fsverity_info *vi,
|
|
const u8 *signature, size_t sig_size)
|
|
{
|
|
unsigned int digest_algorithm =
|
|
vi->tree_params.hash_alg - fsverity_hash_algs;
|
|
|
|
return __fsverity_verify_signature(vi->inode, signature, sig_size,
|
|
vi->file_digest, digest_algorithm);
|
|
}
|
|
|
|
/**
|
|
* __fsverity_verify_signature() - check a verity file's signature
|
|
* @inode: the file's inode
|
|
* @signature: the file's signature
|
|
* @sig_size: size of @signature. Can be 0 if there is no signature
|
|
* @file_digest: the file's digest
|
|
* @digest_algorithm: the digest algorithm used
|
|
*
|
|
* Takes the file's digest and optional signature and verifies the signature
|
|
* against the digest and the fs-verity keyring if appropriate
|
|
*
|
|
* Return: 0 on success (signature valid or not required); -errno on failure
|
|
*/
|
|
int __fsverity_verify_signature(const struct inode *inode, const u8 *signature,
|
|
size_t sig_size, const u8 *file_digest,
|
|
unsigned int digest_algorithm)
|
|
{
|
|
struct fsverity_formatted_digest *d;
|
|
struct fsverity_hash_alg *hash_alg = fsverity_get_hash_alg(inode,
|
|
digest_algorithm);
|
|
int err;
|
|
|
|
if (IS_ERR(hash_alg))
|
|
return PTR_ERR(hash_alg);
|
|
|
|
if (sig_size == 0) {
|
|
if (fsverity_require_signatures) {
|
|
fsverity_err(inode,
|
|
"require_signatures=1, rejecting unsigned file!");
|
|
return -EPERM;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
d = kzalloc(sizeof(*d) + hash_alg->digest_size, GFP_KERNEL);
|
|
if (!d)
|
|
return -ENOMEM;
|
|
memcpy(d->magic, "FSVerity", 8);
|
|
d->digest_algorithm = cpu_to_le16(hash_alg - fsverity_hash_algs);
|
|
d->digest_size = cpu_to_le16(hash_alg->digest_size);
|
|
memcpy(d->digest, file_digest, hash_alg->digest_size);
|
|
|
|
err = verify_pkcs7_signature(d, sizeof(*d) + hash_alg->digest_size,
|
|
signature, sig_size, fsverity_keyring,
|
|
VERIFYING_UNSPECIFIED_SIGNATURE,
|
|
NULL, NULL);
|
|
kfree(d);
|
|
|
|
if (err) {
|
|
if (err == -ENOKEY)
|
|
fsverity_err(inode,
|
|
"File's signing cert isn't in the fs-verity keyring");
|
|
else if (err == -EKEYREJECTED)
|
|
fsverity_err(inode, "Incorrect file signature");
|
|
else if (err == -EBADMSG)
|
|
fsverity_err(inode, "Malformed file signature");
|
|
else
|
|
fsverity_err(inode, "Error %d verifying file signature",
|
|
err);
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(__fsverity_verify_signature);
|
|
|
|
#ifdef CONFIG_SYSCTL
|
|
static struct ctl_table_header *fsverity_sysctl_header;
|
|
|
|
static const struct ctl_path fsverity_sysctl_path[] = {
|
|
{ .procname = "fs", },
|
|
{ .procname = "verity", },
|
|
{ }
|
|
};
|
|
|
|
static struct ctl_table fsverity_sysctl_table[] = {
|
|
{
|
|
.procname = "require_signatures",
|
|
.data = &fsverity_require_signatures,
|
|
.maxlen = sizeof(int),
|
|
.mode = 0644,
|
|
.proc_handler = proc_dointvec_minmax,
|
|
.extra1 = SYSCTL_ZERO,
|
|
.extra2 = SYSCTL_ONE,
|
|
},
|
|
{ }
|
|
};
|
|
|
|
static int __init fsverity_sysctl_init(void)
|
|
{
|
|
fsverity_sysctl_header = register_sysctl_paths(fsverity_sysctl_path,
|
|
fsverity_sysctl_table);
|
|
if (!fsverity_sysctl_header) {
|
|
pr_err("sysctl registration failed!\n");
|
|
return -ENOMEM;
|
|
}
|
|
return 0;
|
|
}
|
|
#else /* !CONFIG_SYSCTL */
|
|
static inline int __init fsverity_sysctl_init(void)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif /* !CONFIG_SYSCTL */
|
|
|
|
int __init fsverity_init_signature(void)
|
|
{
|
|
struct key *ring;
|
|
int err;
|
|
|
|
ring = keyring_alloc(".fs-verity", KUIDT_INIT(0), KGIDT_INIT(0),
|
|
current_cred(), KEY_POS_SEARCH |
|
|
KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE |
|
|
KEY_USR_SEARCH | KEY_USR_SETATTR,
|
|
KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
|
|
if (IS_ERR(ring))
|
|
return PTR_ERR(ring);
|
|
|
|
err = fsverity_sysctl_init();
|
|
if (err)
|
|
goto err_put_ring;
|
|
|
|
fsverity_keyring = ring;
|
|
return 0;
|
|
|
|
err_put_ring:
|
|
key_put(ring);
|
|
return err;
|
|
}
|