Skip to content

Commit 3bb156a

Browse files
committed
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
2 parents cc0a38d + 919dc32 commit 3bb156a

File tree

6 files changed

+79
-103
lines changed

6 files changed

+79
-103
lines changed

fs/verity/fsverity_private.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,16 @@ void fsverity_free_info(struct fsverity_info *vi);
118118
int fsverity_get_descriptor(struct inode *inode,
119119
struct fsverity_descriptor **desc_ret);
120120

121-
int __init fsverity_init_info_cache(void);
122-
void __init fsverity_exit_info_cache(void);
121+
void __init fsverity_init_info_cache(void);
123122

124123
/* signature.c */
125124

126125
#ifdef CONFIG_FS_VERITY_BUILTIN_SIGNATURES
126+
extern int fsverity_require_signatures;
127127
int fsverity_verify_signature(const struct fsverity_info *vi,
128128
const u8 *signature, size_t sig_size);
129129

130-
int __init fsverity_init_signature(void);
130+
void __init fsverity_init_signature(void);
131131
#else /* !CONFIG_FS_VERITY_BUILTIN_SIGNATURES */
132132
static inline int
133133
fsverity_verify_signature(const struct fsverity_info *vi,
@@ -136,15 +136,13 @@ fsverity_verify_signature(const struct fsverity_info *vi,
136136
return 0;
137137
}
138138

139-
static inline int fsverity_init_signature(void)
139+
static inline void fsverity_init_signature(void)
140140
{
141-
return 0;
142141
}
143142
#endif /* !CONFIG_FS_VERITY_BUILTIN_SIGNATURES */
144143

145144
/* verify.c */
146145

147-
int __init fsverity_init_workqueue(void);
148-
void __init fsverity_exit_workqueue(void);
146+
void __init fsverity_init_workqueue(void);
149147

150148
#endif /* _FSVERITY_PRIVATE_H */

fs/verity/hash_algs.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,14 @@ void __init fsverity_check_hash_algs(void)
226226
if (!alg->name)
227227
continue;
228228

229+
/*
230+
* 0 must never be allocated as an FS_VERITY_HASH_ALG_* value,
231+
* as it is reserved for users that use 0 to mean unspecified or
232+
* a default value. fs/verity/ itself doesn't care and doesn't
233+
* have a default algorithm, but some users make use of this.
234+
*/
235+
BUG_ON(i == 0);
236+
229237
BUG_ON(alg->digest_size > FS_VERITY_MAX_DIGEST_SIZE);
230238

231239
/*

fs/verity/init.c

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,37 @@
99

1010
#include <linux/ratelimit.h>
1111

12+
#ifdef CONFIG_SYSCTL
13+
static struct ctl_table_header *fsverity_sysctl_header;
14+
15+
static struct ctl_table fsverity_sysctl_table[] = {
16+
#ifdef CONFIG_FS_VERITY_BUILTIN_SIGNATURES
17+
{
18+
.procname = "require_signatures",
19+
.data = &fsverity_require_signatures,
20+
.maxlen = sizeof(int),
21+
.mode = 0644,
22+
.proc_handler = proc_dointvec_minmax,
23+
.extra1 = SYSCTL_ZERO,
24+
.extra2 = SYSCTL_ONE,
25+
},
26+
#endif
27+
{ }
28+
};
29+
30+
static void __init fsverity_init_sysctl(void)
31+
{
32+
fsverity_sysctl_header = register_sysctl("fs/verity",
33+
fsverity_sysctl_table);
34+
if (!fsverity_sysctl_header)
35+
panic("fsverity sysctl registration failed");
36+
}
37+
#else /* CONFIG_SYSCTL */
38+
static inline void fsverity_init_sysctl(void)
39+
{
40+
}
41+
#endif /* !CONFIG_SYSCTL */
42+
1243
void fsverity_msg(const struct inode *inode, const char *level,
1344
const char *fmt, ...)
1445
{
@@ -33,28 +64,11 @@ void fsverity_msg(const struct inode *inode, const char *level,
3364

3465
static int __init fsverity_init(void)
3566
{
36-
int err;
37-
3867
fsverity_check_hash_algs();
39-
40-
err = fsverity_init_info_cache();
41-
if (err)
42-
return err;
43-
44-
err = fsverity_init_workqueue();
45-
if (err)
46-
goto err_exit_info_cache;
47-
48-
err = fsverity_init_signature();
49-
if (err)
50-
goto err_exit_workqueue;
51-
68+
fsverity_init_info_cache();
69+
fsverity_init_workqueue();
70+
fsverity_init_sysctl();
71+
fsverity_init_signature();
5272
return 0;
53-
54-
err_exit_workqueue:
55-
fsverity_exit_workqueue();
56-
err_exit_info_cache:
57-
fsverity_exit_info_cache();
58-
return err;
5973
}
6074
late_initcall(fsverity_init)

fs/verity/open.c

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -408,18 +408,10 @@ void __fsverity_cleanup_inode(struct inode *inode)
408408
}
409409
EXPORT_SYMBOL_GPL(__fsverity_cleanup_inode);
410410

411-
int __init fsverity_init_info_cache(void)
411+
void __init fsverity_init_info_cache(void)
412412
{
413-
fsverity_info_cachep = KMEM_CACHE_USERCOPY(fsverity_info,
414-
SLAB_RECLAIM_ACCOUNT,
415-
file_digest);
416-
if (!fsverity_info_cachep)
417-
return -ENOMEM;
418-
return 0;
419-
}
420-
421-
void __init fsverity_exit_info_cache(void)
422-
{
423-
kmem_cache_destroy(fsverity_info_cachep);
424-
fsverity_info_cachep = NULL;
413+
fsverity_info_cachep = KMEM_CACHE_USERCOPY(
414+
fsverity_info,
415+
SLAB_RECLAIM_ACCOUNT | SLAB_PANIC,
416+
file_digest);
425417
}

fs/verity/signature.c

Lines changed: 24 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
* /proc/sys/fs/verity/require_signatures
2525
* If 1, all verity files must have a valid builtin signature.
2626
*/
27-
static int fsverity_require_signatures;
27+
int fsverity_require_signatures;
2828

2929
/*
3030
* Keyring that contains the trusted X.509 certificates.
@@ -62,6 +62,22 @@ int fsverity_verify_signature(const struct fsverity_info *vi,
6262
return 0;
6363
}
6464

65+
if (fsverity_keyring->keys.nr_leaves_on_tree == 0) {
66+
/*
67+
* The ".fs-verity" keyring is empty, due to builtin signatures
68+
* being supported by the kernel but not actually being used.
69+
* In this case, verify_pkcs7_signature() would always return an
70+
* error, usually ENOKEY. It could also be EBADMSG if the
71+
* PKCS#7 is malformed, but that isn't very important to
72+
* distinguish. So, just skip to ENOKEY to avoid the attack
73+
* surface of the PKCS#7 parser, which would otherwise be
74+
* reachable by any task able to execute FS_IOC_ENABLE_VERITY.
75+
*/
76+
fsverity_err(inode,
77+
"fs-verity keyring is empty, rejecting signed file!");
78+
return -ENOKEY;
79+
}
80+
6581
d = kzalloc(sizeof(*d) + hash_alg->digest_size, GFP_KERNEL);
6682
if (!d)
6783
return -ENOMEM;
@@ -93,59 +109,14 @@ int fsverity_verify_signature(const struct fsverity_info *vi,
93109
return 0;
94110
}
95111

96-
#ifdef CONFIG_SYSCTL
97-
static struct ctl_table_header *fsverity_sysctl_header;
98-
99-
static struct ctl_table fsverity_sysctl_table[] = {
100-
{
101-
.procname = "require_signatures",
102-
.data = &fsverity_require_signatures,
103-
.maxlen = sizeof(int),
104-
.mode = 0644,
105-
.proc_handler = proc_dointvec_minmax,
106-
.extra1 = SYSCTL_ZERO,
107-
.extra2 = SYSCTL_ONE,
108-
},
109-
{ }
110-
};
111-
112-
static int __init fsverity_sysctl_init(void)
113-
{
114-
fsverity_sysctl_header = register_sysctl("fs/verity", fsverity_sysctl_table);
115-
if (!fsverity_sysctl_header) {
116-
pr_err("sysctl registration failed!\n");
117-
return -ENOMEM;
118-
}
119-
return 0;
120-
}
121-
#else /* !CONFIG_SYSCTL */
122-
static inline int __init fsverity_sysctl_init(void)
112+
void __init fsverity_init_signature(void)
123113
{
124-
return 0;
125-
}
126-
#endif /* !CONFIG_SYSCTL */
127-
128-
int __init fsverity_init_signature(void)
129-
{
130-
struct key *ring;
131-
int err;
132-
133-
ring = keyring_alloc(".fs-verity", KUIDT_INIT(0), KGIDT_INIT(0),
134-
current_cred(), KEY_POS_SEARCH |
114+
fsverity_keyring =
115+
keyring_alloc(".fs-verity", KUIDT_INIT(0), KGIDT_INIT(0),
116+
current_cred(), KEY_POS_SEARCH |
135117
KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE |
136118
KEY_USR_SEARCH | KEY_USR_SETATTR,
137-
KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
138-
if (IS_ERR(ring))
139-
return PTR_ERR(ring);
140-
141-
err = fsverity_sysctl_init();
142-
if (err)
143-
goto err_put_ring;
144-
145-
fsverity_keyring = ring;
146-
return 0;
147-
148-
err_put_ring:
149-
key_put(ring);
150-
return err;
119+
KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
120+
if (IS_ERR(fsverity_keyring))
121+
panic("failed to allocate \".fs-verity\" keyring");
151122
}

fs/verity/verify.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ void fsverity_enqueue_verify_work(struct work_struct *work)
346346
}
347347
EXPORT_SYMBOL_GPL(fsverity_enqueue_verify_work);
348348

349-
int __init fsverity_init_workqueue(void)
349+
void __init fsverity_init_workqueue(void)
350350
{
351351
/*
352352
* Use a high-priority workqueue to prioritize verification work, which
@@ -360,12 +360,5 @@ int __init fsverity_init_workqueue(void)
360360
WQ_HIGHPRI,
361361
num_online_cpus());
362362
if (!fsverity_read_workqueue)
363-
return -ENOMEM;
364-
return 0;
365-
}
366-
367-
void __init fsverity_exit_workqueue(void)
368-
{
369-
destroy_workqueue(fsverity_read_workqueue);
370-
fsverity_read_workqueue = NULL;
363+
panic("failed to allocate fsverity_read_queue");
371364
}

0 commit comments

Comments
 (0)