Commit e77000cc authored by Eric Biggers's avatar Eric Biggers
Browse files

fsverity: simplify handling of errors during initcall

Since CONFIG_FS_VERITY is a bool, not a tristate, fs/verity/ can only be
builtin or absent entirely; it can't be a loadable module.  Therefore,
the error code that gets returned from the fsverity_init() initcall is
never used.  If any part of the initcall does fail, which should never
happen, the kernel will be left in a bad state.

Following the usual convention for builtin code, just panic the kernel
if any of part of the initcall fails.

Link: https://lore.kernel.org/r/20230705212743.42180-2-ebiggers@kernel.org


Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
parent 5d37a119
Loading
Loading
Loading
Loading
+4 −7
Original line number Diff line number Diff line
@@ -118,8 +118,7 @@ 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 */

@@ -127,7 +126,7 @@ void __init fsverity_exit_info_cache(void);
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 +135,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 */
+3 −21
Original line number Diff line number Diff line
@@ -33,28 +33,10 @@ 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_signature();
	return 0;

err_exit_workqueue:
	fsverity_exit_workqueue();
err_exit_info_cache:
	fsverity_exit_info_cache();
	return err;
}
late_initcall(fsverity_init)
+5 −13
Original line number Diff line number Diff line
@@ -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,
	fsverity_info_cachep = KMEM_CACHE_USERCOPY(
					fsverity_info,
					SLAB_RECLAIM_ACCOUNT | SLAB_PANIC,
					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;
}
+14 −28
Original line number Diff line number Diff line
@@ -109,43 +109,29 @@ static struct ctl_table fsverity_sysctl_table[] = {
	{ }
};

static int __init fsverity_sysctl_init(void)
static void __init fsverity_sysctl_init(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;
	fsverity_sysctl_header = register_sysctl("fs/verity",
						 fsverity_sysctl_table);
	if (!fsverity_sysctl_header)
		panic("fsverity sysctl registration failed");
}
#else /* !CONFIG_SYSCTL */
static inline int __init fsverity_sysctl_init(void)
static inline void fsverity_sysctl_init(void)
{
	return 0;
}
#endif /* !CONFIG_SYSCTL */

int __init fsverity_init_signature(void)
void __init fsverity_init_signature(void)
{
	struct key *ring;
	int err;

	ring = keyring_alloc(".fs-verity", KUIDT_INIT(0), KGIDT_INIT(0),
	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;
	if (IS_ERR(fsverity_keyring))
		panic("failed to allocate \".fs-verity\" keyring");

	fsverity_keyring = ring;
	return 0;

err_put_ring:
	key_put(ring);
	return err;
	fsverity_sysctl_init();
}
+2 −9
Original line number Diff line number Diff line
@@ -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");
}