mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-18 02:46:06 +00:00
fsverity updates for 6.6
Several cleanups for fs/verity/, including two commits that make the builtin signature support more cleanly separated from the base feature. -----BEGIN PGP SIGNATURE----- iIoEABYIADIWIQSacvsUNc7UX4ntmEPzXCl4vpKOKwUCZOwXSRQcZWJpZ2dlcnNA Z29vZ2xlLmNvbQAKCRDzXCl4vpKOK+kzAP9UsTtZjjQLvEDF6OYlysFLQppDrmk0 zh9iH/Z7qT8BQwEA0azRHW5/FDLvkHZWsU0QCLjDpUPrNHc712aeM1pLpgc= =zOdL -----END PGP SIGNATURE----- Merge tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fsverity/linux Pull fsverity updates from Eric Biggers: "Several cleanups for fs/verity/, including two commits that make the builtin signature support more cleanly separated from the base feature" * tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fsverity/linux: fsverity: skip PKCS#7 parser when keyring is empty fsverity: move sysctl registration out of signature.c fsverity: simplify handling of errors during initcall fsverity: explicitly check that there is no algorithm 0
This commit is contained in:
commit
3bb156a556
@ -118,16 +118,16 @@ void fsverity_free_info(struct fsverity_info *vi);
|
||||
int fsverity_get_descriptor(struct inode *inode,
|
||||
struct fsverity_descriptor **desc_ret);
|
||||
|
||||
int __init fsverity_init_info_cache(void);
|
||||
void __init fsverity_exit_info_cache(void);
|
||||
void __init fsverity_init_info_cache(void);
|
||||
|
||||
/* signature.c */
|
||||
|
||||
#ifdef CONFIG_FS_VERITY_BUILTIN_SIGNATURES
|
||||
extern int fsverity_require_signatures;
|
||||
int fsverity_verify_signature(const struct fsverity_info *vi,
|
||||
const u8 *signature, size_t sig_size);
|
||||
|
||||
int __init fsverity_init_signature(void);
|
||||
void __init fsverity_init_signature(void);
|
||||
#else /* !CONFIG_FS_VERITY_BUILTIN_SIGNATURES */
|
||||
static inline int
|
||||
fsverity_verify_signature(const struct fsverity_info *vi,
|
||||
@ -136,15 +136,13 @@ fsverity_verify_signature(const struct fsverity_info *vi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int fsverity_init_signature(void)
|
||||
static inline void fsverity_init_signature(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CONFIG_FS_VERITY_BUILTIN_SIGNATURES */
|
||||
|
||||
/* verify.c */
|
||||
|
||||
int __init fsverity_init_workqueue(void);
|
||||
void __init fsverity_exit_workqueue(void);
|
||||
void __init fsverity_init_workqueue(void);
|
||||
|
||||
#endif /* _FSVERITY_PRIVATE_H */
|
||||
|
@ -226,6 +226,14 @@ void __init fsverity_check_hash_algs(void)
|
||||
if (!alg->name)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* 0 must never be allocated as an FS_VERITY_HASH_ALG_* value,
|
||||
* as it is reserved for users that use 0 to mean unspecified or
|
||||
* a default value. fs/verity/ itself doesn't care and doesn't
|
||||
* have a default algorithm, but some users make use of this.
|
||||
*/
|
||||
BUG_ON(i == 0);
|
||||
|
||||
BUG_ON(alg->digest_size > FS_VERITY_MAX_DIGEST_SIZE);
|
||||
|
||||
/*
|
||||
|
@ -9,6 +9,37 @@
|
||||
|
||||
#include <linux/ratelimit.h>
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
static struct ctl_table_header *fsverity_sysctl_header;
|
||||
|
||||
static struct ctl_table fsverity_sysctl_table[] = {
|
||||
#ifdef CONFIG_FS_VERITY_BUILTIN_SIGNATURES
|
||||
{
|
||||
.procname = "require_signatures",
|
||||
.data = &fsverity_require_signatures,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = SYSCTL_ZERO,
|
||||
.extra2 = SYSCTL_ONE,
|
||||
},
|
||||
#endif
|
||||
{ }
|
||||
};
|
||||
|
||||
static void __init fsverity_init_sysctl(void)
|
||||
{
|
||||
fsverity_sysctl_header = register_sysctl("fs/verity",
|
||||
fsverity_sysctl_table);
|
||||
if (!fsverity_sysctl_header)
|
||||
panic("fsverity sysctl registration failed");
|
||||
}
|
||||
#else /* CONFIG_SYSCTL */
|
||||
static inline void fsverity_init_sysctl(void)
|
||||
{
|
||||
}
|
||||
#endif /* !CONFIG_SYSCTL */
|
||||
|
||||
void fsverity_msg(const struct inode *inode, const char *level,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
@ -33,28 +64,11 @@ void fsverity_msg(const struct inode *inode, const char *level,
|
||||
|
||||
static int __init fsverity_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
fsverity_check_hash_algs();
|
||||
|
||||
err = fsverity_init_info_cache();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = fsverity_init_workqueue();
|
||||
if (err)
|
||||
goto err_exit_info_cache;
|
||||
|
||||
err = fsverity_init_signature();
|
||||
if (err)
|
||||
goto err_exit_workqueue;
|
||||
|
||||
fsverity_init_info_cache();
|
||||
fsverity_init_workqueue();
|
||||
fsverity_init_sysctl();
|
||||
fsverity_init_signature();
|
||||
return 0;
|
||||
|
||||
err_exit_workqueue:
|
||||
fsverity_exit_workqueue();
|
||||
err_exit_info_cache:
|
||||
fsverity_exit_info_cache();
|
||||
return err;
|
||||
}
|
||||
late_initcall(fsverity_init)
|
||||
|
@ -408,18 +408,10 @@ void __fsverity_cleanup_inode(struct inode *inode)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__fsverity_cleanup_inode);
|
||||
|
||||
int __init fsverity_init_info_cache(void)
|
||||
void __init fsverity_init_info_cache(void)
|
||||
{
|
||||
fsverity_info_cachep = KMEM_CACHE_USERCOPY(fsverity_info,
|
||||
SLAB_RECLAIM_ACCOUNT,
|
||||
file_digest);
|
||||
if (!fsverity_info_cachep)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init fsverity_exit_info_cache(void)
|
||||
{
|
||||
kmem_cache_destroy(fsverity_info_cachep);
|
||||
fsverity_info_cachep = NULL;
|
||||
fsverity_info_cachep = KMEM_CACHE_USERCOPY(
|
||||
fsverity_info,
|
||||
SLAB_RECLAIM_ACCOUNT | SLAB_PANIC,
|
||||
file_digest);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
* /proc/sys/fs/verity/require_signatures
|
||||
* If 1, all verity files must have a valid builtin signature.
|
||||
*/
|
||||
static int fsverity_require_signatures;
|
||||
int fsverity_require_signatures;
|
||||
|
||||
/*
|
||||
* Keyring that contains the trusted X.509 certificates.
|
||||
@ -62,6 +62,22 @@ int fsverity_verify_signature(const struct fsverity_info *vi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fsverity_keyring->keys.nr_leaves_on_tree == 0) {
|
||||
/*
|
||||
* The ".fs-verity" keyring is empty, due to builtin signatures
|
||||
* being supported by the kernel but not actually being used.
|
||||
* In this case, verify_pkcs7_signature() would always return an
|
||||
* error, usually ENOKEY. It could also be EBADMSG if the
|
||||
* PKCS#7 is malformed, but that isn't very important to
|
||||
* distinguish. So, just skip to ENOKEY to avoid the attack
|
||||
* surface of the PKCS#7 parser, which would otherwise be
|
||||
* reachable by any task able to execute FS_IOC_ENABLE_VERITY.
|
||||
*/
|
||||
fsverity_err(inode,
|
||||
"fs-verity keyring is empty, rejecting signed file!");
|
||||
return -ENOKEY;
|
||||
}
|
||||
|
||||
d = kzalloc(sizeof(*d) + hash_alg->digest_size, GFP_KERNEL);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
@ -93,59 +109,14 @@ int fsverity_verify_signature(const struct fsverity_info *vi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
static struct ctl_table_header *fsverity_sysctl_header;
|
||||
|
||||
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)
|
||||
void __init fsverity_init_signature(void)
|
||||
{
|
||||
fsverity_sysctl_header = register_sysctl("fs/verity", 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 |
|
||||
fsverity_keyring =
|
||||
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;
|
||||
KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
|
||||
if (IS_ERR(fsverity_keyring))
|
||||
panic("failed to allocate \".fs-verity\" keyring");
|
||||
}
|
||||
|
@ -346,7 +346,7 @@ void fsverity_enqueue_verify_work(struct work_struct *work)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsverity_enqueue_verify_work);
|
||||
|
||||
int __init fsverity_init_workqueue(void)
|
||||
void __init fsverity_init_workqueue(void)
|
||||
{
|
||||
/*
|
||||
* Use a high-priority workqueue to prioritize verification work, which
|
||||
@ -360,12 +360,5 @@ int __init fsverity_init_workqueue(void)
|
||||
WQ_HIGHPRI,
|
||||
num_online_cpus());
|
||||
if (!fsverity_read_workqueue)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init fsverity_exit_workqueue(void)
|
||||
{
|
||||
destroy_workqueue(fsverity_read_workqueue);
|
||||
fsverity_read_workqueue = NULL;
|
||||
panic("failed to allocate fsverity_read_queue");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user