diff options
author | Martin KaFai Lau <kafai@fb.com> | 2018-03-24 14:44:23 -0400 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-03-26 03:58:17 -0400 |
commit | 77d2e05abd45886dcad2b632c738cf46b9f7c19e (patch) | |
tree | dab2d5beef6275329e8ed3dbaff7f720d6f05f6c | |
parent | b9193c1b61ddb97da4713155b0d580e41fb544ac (diff) |
bpf: Add bpf_verifier_vlog() and bpf_verifier_log_needed()
The BTF (BPF Type Format) verifier needs to reuse the current
BPF verifier log. Hence, it requires the following changes:
(1) Expose log_write() in verifier.c for other users.
Its name is renamed to bpf_verifier_vlog().
(2) The BTF verifier also needs to check
'log->level && log->ubuf && !bpf_verifier_log_full(log);'
independently outside of the current log_write(). It is
because the BTF verifier will do one-check before
making multiple calls to btf_verifier_vlog to log
the details of a type.
Hence, this check is also re-factored to a new function
bpf_verifier_log_needed(). Since it is re-factored,
we can check it before va_start() in the current
bpf_verifier_log_write() and verbose().
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r-- | include/linux/bpf_verifier.h | 7 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 19 |
2 files changed, 18 insertions, 8 deletions
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index c30668414b22..7e61c395fddf 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h | |||
@@ -166,6 +166,11 @@ static inline bool bpf_verifier_log_full(const struct bpf_verifier_log *log) | |||
166 | return log->len_used >= log->len_total - 1; | 166 | return log->len_used >= log->len_total - 1; |
167 | } | 167 | } |
168 | 168 | ||
169 | static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log) | ||
170 | { | ||
171 | return log->level && log->ubuf && !bpf_verifier_log_full(log); | ||
172 | } | ||
173 | |||
169 | #define BPF_MAX_SUBPROGS 256 | 174 | #define BPF_MAX_SUBPROGS 256 |
170 | 175 | ||
171 | /* single container for all structs | 176 | /* single container for all structs |
@@ -192,6 +197,8 @@ struct bpf_verifier_env { | |||
192 | u32 subprog_cnt; | 197 | u32 subprog_cnt; |
193 | }; | 198 | }; |
194 | 199 | ||
200 | void bpf_verifier_vlog(struct bpf_verifier_log *log, const char *fmt, | ||
201 | va_list args); | ||
195 | __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, | 202 | __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, |
196 | const char *fmt, ...); | 203 | const char *fmt, ...); |
197 | 204 | ||
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 1e84e02ff733..8acd2207e412 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
@@ -168,15 +168,11 @@ struct bpf_call_arg_meta { | |||
168 | 168 | ||
169 | static DEFINE_MUTEX(bpf_verifier_lock); | 169 | static DEFINE_MUTEX(bpf_verifier_lock); |
170 | 170 | ||
171 | static void log_write(struct bpf_verifier_env *env, const char *fmt, | 171 | void bpf_verifier_vlog(struct bpf_verifier_log *log, const char *fmt, |
172 | va_list args) | 172 | va_list args) |
173 | { | 173 | { |
174 | struct bpf_verifier_log *log = &env->log; | ||
175 | unsigned int n; | 174 | unsigned int n; |
176 | 175 | ||
177 | if (!log->level || !log->ubuf || bpf_verifier_log_full(log)) | ||
178 | return; | ||
179 | |||
180 | n = vscnprintf(log->kbuf, BPF_VERIFIER_TMP_LOG_SIZE, fmt, args); | 176 | n = vscnprintf(log->kbuf, BPF_VERIFIER_TMP_LOG_SIZE, fmt, args); |
181 | 177 | ||
182 | WARN_ONCE(n >= BPF_VERIFIER_TMP_LOG_SIZE - 1, | 178 | WARN_ONCE(n >= BPF_VERIFIER_TMP_LOG_SIZE - 1, |
@@ -200,18 +196,25 @@ __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, | |||
200 | { | 196 | { |
201 | va_list args; | 197 | va_list args; |
202 | 198 | ||
199 | if (!bpf_verifier_log_needed(&env->log)) | ||
200 | return; | ||
201 | |||
203 | va_start(args, fmt); | 202 | va_start(args, fmt); |
204 | log_write(env, fmt, args); | 203 | bpf_verifier_vlog(&env->log, fmt, args); |
205 | va_end(args); | 204 | va_end(args); |
206 | } | 205 | } |
207 | EXPORT_SYMBOL_GPL(bpf_verifier_log_write); | 206 | EXPORT_SYMBOL_GPL(bpf_verifier_log_write); |
208 | 207 | ||
209 | __printf(2, 3) static void verbose(void *private_data, const char *fmt, ...) | 208 | __printf(2, 3) static void verbose(void *private_data, const char *fmt, ...) |
210 | { | 209 | { |
210 | struct bpf_verifier_env *env = private_data; | ||
211 | va_list args; | 211 | va_list args; |
212 | 212 | ||
213 | if (!bpf_verifier_log_needed(&env->log)) | ||
214 | return; | ||
215 | |||
213 | va_start(args, fmt); | 216 | va_start(args, fmt); |
214 | log_write(private_data, fmt, args); | 217 | bpf_verifier_vlog(&env->log, fmt, args); |
215 | va_end(args); | 218 | va_end(args); |
216 | } | 219 | } |
217 | 220 | ||