@@ -3107,34 +3107,7 @@ static inline gfp_t bpf_memcg_flags(gfp_t flags)
return flags;
}
-#define BPF_GENERIC_TMP_LOG_SIZE 256
-
-struct bpf_generic_log {
- char kbuf[BPF_GENERIC_TMP_LOG_SIZE];
- char __user *ubuf;
- u32 len_used;
- u32 len_total;
-};
-
-__printf(2, 3) void bpf_generic_log_write(struct bpf_generic_log *log,
- const char *fmt, ...);
-static inline void bpf_generic_log_init(struct bpf_generic_log *log,
- const struct bpf_generic_user_log *ulog)
-{
- log->ubuf = (char __user *) (unsigned long) ulog->log_buf;
- log->len_total = ulog->log_size;
- log->len_used = 0;
-}
-
-#define BPF_GENERIC_LOG_WRITE(log, ulog, fmt, ...) do { \
- const char *____fmt = (fmt); \
- bpf_generic_log_init(log, ulog); \
- bpf_generic_log_write(log, ____fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define BPF_GENERIC_ULOG_WRITE(ulog, fmt, ...) do { \
- struct bpf_generic_log ____log; \
- BPF_GENERIC_LOG_WRITE(&____log, ulog, fmt, ##__VA_ARGS__); \
-} while (0)
+__printf(2, 3) void bpf_ulog_once(const struct bpf_generic_user_log *ulog,
+ const char *fmt, ...);
#endif /* _LINUX_BPF_H */
@@ -1549,7 +1549,6 @@ union bpf_attr {
};
__u32 attach_type; /* attach type */
__u32 flags; /* extra flags */
- struct bpf_generic_user_log log; /* user log */
union {
__u32 target_btf_id; /* btf_id of target to attach to */
struct {
@@ -1585,6 +1584,9 @@ union bpf_attr {
__s32 priority;
__u32 flags;
} netfilter;
+ struct {
+ struct bpf_generic_user_log ulog; /* user log */
+ } xdp;
};
} link_create;
@@ -326,15 +326,32 @@ __printf(2, 3) void bpf_log(struct bpf_verifier_log *log,
}
EXPORT_SYMBOL_GPL(bpf_log);
-static inline void __bpf_generic_log_write(struct bpf_generic_log *log, const char *fmt,
- va_list args)
+#define BPF_USER_TMP_LOG_SIZE 256
+
+struct bpf_user_log {
+ char kbuf[BPF_USER_TMP_LOG_SIZE];
+ char __user *ubuf;
+ u32 len_used;
+ u32 len_total;
+};
+
+static inline void bpf_ulog_init(struct bpf_user_log *log,
+ const struct bpf_generic_user_log *ulog)
+{
+ log->ubuf = (char __user *) (unsigned long) ulog->log_buf;
+ log->len_total = ulog->log_size;
+ log->len_used = 0;
+}
+
+static inline void bpf_ulog_write(struct bpf_user_log *log,
+ const char *fmt, va_list args)
{
unsigned int n;
- n = vscnprintf(log->kbuf, BPF_GENERIC_TMP_LOG_SIZE, fmt, args);
+ n = vscnprintf(log->kbuf, BPF_USER_TMP_LOG_SIZE, fmt, args);
- WARN_ONCE(n >= BPF_GENERIC_TMP_LOG_SIZE - 1,
- "bpf generic log truncated - local buffer too short\n");
+ WARN_ONCE(n >= BPF_USER_TMP_LOG_SIZE - 1,
+ "bpf user log line truncated - local buffer too short\n");
n = min(log->len_total - log->len_used - 1, n);
log->kbuf[n] = '\0';
@@ -345,16 +362,18 @@ static inline void __bpf_generic_log_write(struct bpf_generic_log *log, const ch
log->ubuf = NULL;
}
-__printf(2, 3) void bpf_generic_log_write(struct bpf_generic_log *log,
- const char *fmt, ...)
+__printf(2, 3) void bpf_ulog_once(const struct bpf_generic_user_log *ulog,
+ const char *fmt, ...)
{
+ struct bpf_user_log log;
va_list args;
- if (!log->ubuf || !log->len_total)
+ if (!ulog->log_buf || !ulog->log_size)
return;
+ bpf_ulog_init(&log, ulog);
va_start(args, fmt);
- __bpf_generic_log_write(log, fmt, args);
+ bpf_ulog_write(&log, fmt, args);
va_end(args);
}
-EXPORT_SYMBOL_GPL(bpf_generic_log_write);
+EXPORT_SYMBOL_GPL(bpf_ulog_once);
@@ -9409,13 +9409,6 @@ static const struct bpf_link_ops bpf_xdp_link_lops = {
.update_prog = bpf_xdp_link_update,
};
-static inline void bpf_xdp_link_log(const union bpf_attr *attr, struct netlink_ext_ack *extack)
-{
- const struct bpf_generic_user_log *ulog = &attr->link_create.log;
-
- BPF_GENERIC_ULOG_WRITE(ulog, extack->_msg);
-}
-
int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
{
struct net *net = current->nsproxy->net_ns;
@@ -9454,7 +9447,7 @@ int bpf_xdp_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
if (err) {
link->dev = NULL;
bpf_link_cleanup(&link_primer);
- bpf_xdp_link_log(attr, &extack);
+ bpf_ulog_once(&attr->link_create.xdp.ulog, extack._msg);
goto out_put_dev;
}
@@ -1549,7 +1549,6 @@ union bpf_attr {
};
__u32 attach_type; /* attach type */
__u32 flags; /* extra flags */
- struct bpf_generic_user_log log; /* user log */
union {
__u32 target_btf_id; /* btf_id of target to attach to */
struct {
@@ -1585,6 +1584,9 @@ union bpf_attr {
__s32 priority;
__u32 flags;
} netfilter;
+ struct {
+ struct bpf_generic_user_log ulog; /* user log */
+ } xdp;
};
} link_create;
Commit 42c4e63ef36ea9b5ae50 (bpf: Introduce bpf generic log) is introduced to back propagate the error message in dev_xdp_attach() to user space when users provide buffer to receive the error message. But it breaks uapi and exposes many log details in header file. To overcome the shortcomings, a) make the struct bpf_generic_user_log as one field of the union in link_create of struct bpf_attr, b) hide log details in log_ulog_once() and let its declaration in header file. Furthermore, it's not a good idea to reuse bpf_verifier_log infra. Or, a warning comes up: net/core/dev.c: In function 'bpf_xdp_link_log.isra.0': net/core/dev.c:9093:1: warning: the frame size of 1056 bytes is larger than 1024 bytes [-Wframe-larger-than=] 9093 | } | As a result, a small kernel buffer, like 256 bytes, is preferred to cache error message, then copy_to_user(). Then, unlike verifier to provide more and more error details, bpf user log is only able to provide a simple error message limit 255 chars for every time. Signed-off-by: Leon Hwang <hffilwlqm@gmail.com> --- include/linux/bpf.h | 31 ++------------------------- include/uapi/linux/bpf.h | 4 +++- kernel/bpf/log.c | 39 +++++++++++++++++++++++++--------- net/core/dev.c | 9 +------- tools/include/uapi/linux/bpf.h | 4 +++- 5 files changed, 38 insertions(+), 49 deletions(-)