aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin KaFai Lau <kafai@fb.com>2018-03-24 14:44:23 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2018-03-26 03:58:17 -0400
commit77d2e05abd45886dcad2b632c738cf46b9f7c19e (patch)
treedab2d5beef6275329e8ed3dbaff7f720d6f05f6c
parentb9193c1b61ddb97da4713155b0d580e41fb544ac (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.h7
-rw-r--r--kernel/bpf/verifier.c19
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
169static 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
200void 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
169static DEFINE_MUTEX(bpf_verifier_lock); 169static DEFINE_MUTEX(bpf_verifier_lock);
170 170
171static void log_write(struct bpf_verifier_env *env, const char *fmt, 171void 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}
207EXPORT_SYMBOL_GPL(bpf_verifier_log_write); 206EXPORT_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