bpf: decode BPF_PROG_QUERY command
BPF_PROG_QUERY was introduced in Linux commit v4.15-rc1~84^2~558^2~6. * xlat/bpf_commands.in (BPF_PROG_QUERY): New constant. * xlat/bpf_query_flags.in: New file. * bpf.c: Include it. (DECL_BPF_CMD_DECODER): Add priv argument for passing tcb private data. (BEGIN_BPF_CMD_DECODER(BPF_PROG_QUERY)): New function. (SYS_FUNC(bpf)) <bpf_cmd_decoders>: Add BPF_PROG_QUERY entry. (SYS_FUNC(bpf)): Fetch buf on entering and exiting, pass buf on exiting, retrieve private data on exiting, pass it to decoder as well, explicitly rework rc handling logic for size argument printing. * bpf_attr.h (struct BPF_PROG_QUERY_struct): New structure declaration. (BPF_PROG_QUERY_struct_size, expected_BPF_PROG_QUERY_struct_size): New macro. * tests/bpf.c: Add checks for BPF_PROG_QUERY command.
This commit is contained in:
parent
459ea39686
commit
39f61ef513
97
bpf.c
97
bpf.c
@ -45,13 +45,21 @@
|
||||
#include "xlat/bpf_map_update_elem_flags.h"
|
||||
#include "xlat/bpf_attach_type.h"
|
||||
#include "xlat/bpf_attach_flags.h"
|
||||
#include "xlat/bpf_query_flags.h"
|
||||
|
||||
/** Storage for all the data that is needed to be stored on entering. */
|
||||
struct bpf_priv_data {
|
||||
bool bpf_prog_query_stored;
|
||||
uint32_t bpf_prog_query_prog_cnt;
|
||||
};
|
||||
|
||||
#define DECL_BPF_CMD_DECODER(bpf_cmd_decoder) \
|
||||
int \
|
||||
bpf_cmd_decoder(struct tcb *const tcp, \
|
||||
const kernel_ulong_t addr, \
|
||||
const unsigned int size, \
|
||||
void *const data) \
|
||||
void *const data, \
|
||||
struct bpf_priv_data *priv) \
|
||||
/* End of DECL_BPF_CMD_DECODER definition. */
|
||||
|
||||
#define BEGIN_BPF_CMD_DECODER(bpf_cmd) \
|
||||
@ -313,6 +321,53 @@ BEGIN_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD)
|
||||
}
|
||||
END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD)
|
||||
|
||||
BEGIN_BPF_CMD_DECODER(BPF_PROG_QUERY)
|
||||
{
|
||||
uint64_t prog_id_buf;
|
||||
|
||||
if (entering(tcp)) {
|
||||
PRINT_FIELD_FD("{query={", attr, target_fd, tcp);
|
||||
PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type,
|
||||
"BPF_???");
|
||||
PRINT_FIELD_FLAGS(", ", attr, query_flags, bpf_query_flags,
|
||||
"BPF_F_QUERY_???");
|
||||
PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags,
|
||||
"BPF_F_???");
|
||||
|
||||
tprints(", prog_ids=");
|
||||
|
||||
if (!priv)
|
||||
priv = xcalloc(1, sizeof(*priv));
|
||||
|
||||
priv->bpf_prog_query_stored = true;
|
||||
priv->bpf_prog_query_prog_cnt = attr.prog_cnt;
|
||||
|
||||
set_tcb_priv_data(tcp, priv, free);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The issue here is that we can't pass pointers bigger than
|
||||
* (our) kernel long ti print_array, so we opt out from decoding
|
||||
* the array.
|
||||
*/
|
||||
if (syserror(tcp) || attr.prog_ids > max_kaddr())
|
||||
printaddr64(attr.prog_ids);
|
||||
else
|
||||
print_array(tcp, attr.prog_ids, attr.prog_cnt, &prog_id_buf,
|
||||
sizeof(prog_id_buf), umoven_or_printaddr,
|
||||
print_uint64_array_member, 0);
|
||||
|
||||
tprints(", prog_cnt=");
|
||||
if (priv && priv->bpf_prog_query_stored
|
||||
&& priv->bpf_prog_query_prog_cnt != attr.prog_cnt)
|
||||
tprintf("%" PRIu32 " => ", priv->bpf_prog_query_prog_cnt);
|
||||
tprintf("%" PRIu32, attr.prog_cnt);
|
||||
tprints("}");
|
||||
}
|
||||
END_BPF_CMD_DECODER(RVAL_DECODED)
|
||||
|
||||
SYS_FUNC(bpf)
|
||||
{
|
||||
static const bpf_cmd_decoder_t bpf_cmd_decoders[] = {
|
||||
@ -332,38 +387,38 @@ SYS_FUNC(bpf)
|
||||
BPF_CMD_ENTRY(BPF_PROG_GET_FD_BY_ID),
|
||||
BPF_CMD_ENTRY(BPF_MAP_GET_FD_BY_ID),
|
||||
BPF_CMD_ENTRY(BPF_OBJ_GET_INFO_BY_FD),
|
||||
BPF_CMD_ENTRY(BPF_PROG_QUERY),
|
||||
};
|
||||
|
||||
static char *buf;
|
||||
struct bpf_priv_data *priv = NULL;
|
||||
|
||||
const unsigned int cmd = tcp->u_arg[0];
|
||||
const kernel_ulong_t addr = tcp->u_arg[1];
|
||||
const unsigned int size = tcp->u_arg[2];
|
||||
int rc;
|
||||
int rc = RVAL_DECODED;
|
||||
|
||||
if (!buf)
|
||||
buf = xmalloc(get_pagesize());
|
||||
|
||||
if (entering(tcp)) {
|
||||
static char *buf;
|
||||
|
||||
if (!buf)
|
||||
buf = xmalloc(get_pagesize());
|
||||
|
||||
printxval(bpf_commands, cmd, "BPF_???");
|
||||
tprints(", ");
|
||||
|
||||
if (size > 0
|
||||
&& size <= get_pagesize()
|
||||
&& cmd < ARRAY_SIZE(bpf_cmd_decoders)
|
||||
&& bpf_cmd_decoders[cmd]) {
|
||||
rc = umoven_or_printaddr(tcp, addr, size, buf)
|
||||
? RVAL_DECODED
|
||||
: bpf_cmd_decoders[cmd](tcp, addr, size, buf);
|
||||
} else {
|
||||
printaddr(addr);
|
||||
rc = RVAL_DECODED;
|
||||
}
|
||||
} else {
|
||||
rc = bpf_cmd_decoders[cmd](tcp, addr, size, NULL) | RVAL_DECODED;
|
||||
priv = get_tcb_priv_data(tcp);
|
||||
}
|
||||
|
||||
if (rc & RVAL_DECODED)
|
||||
if (size > 0
|
||||
&& size <= get_pagesize()
|
||||
&& cmd < ARRAY_SIZE(bpf_cmd_decoders)
|
||||
&& bpf_cmd_decoders[cmd]) {
|
||||
if (!umoven_or_printaddr_ignore_syserror(tcp, addr, size, buf))
|
||||
rc = bpf_cmd_decoders[cmd](tcp, addr, size, buf, priv);
|
||||
} else {
|
||||
printaddr(addr);
|
||||
}
|
||||
|
||||
if (exiting(tcp) || (rc & RVAL_DECODED))
|
||||
tprintf(", %u", size);
|
||||
|
||||
return rc;
|
||||
|
13
bpf_attr.h
13
bpf_attr.h
@ -200,4 +200,17 @@ struct BPF_OBJ_GET_INFO_BY_FD_struct /* info */ {
|
||||
sizeof(struct BPF_OBJ_GET_INFO_BY_FD_struct)
|
||||
#define expected_BPF_OBJ_GET_INFO_BY_FD_struct_size 16
|
||||
|
||||
struct BPF_PROG_QUERY_struct /* query */ {
|
||||
uint32_t target_fd;
|
||||
uint32_t attach_type;
|
||||
uint32_t query_flags;
|
||||
uint32_t attach_flags;
|
||||
uint64_t ATTRIBUTE_ALIGNED(8) prog_ids;
|
||||
uint32_t prog_cnt;
|
||||
};
|
||||
|
||||
#define BPF_PROG_QUERY_struct_size \
|
||||
offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt)
|
||||
#define expected_BPF_PROG_QUERY_struct_size 28
|
||||
|
||||
#endif /* !STRACE_BPF_ATTR_H */
|
||||
|
61
tests/bpf.c
61
tests/bpf.c
@ -76,6 +76,7 @@ union bpf_attr_data {
|
||||
BPF_ATTR_DATA_FIELD(BPF_PROG_GET_FD_BY_ID);
|
||||
BPF_ATTR_DATA_FIELD(BPF_MAP_GET_FD_BY_ID);
|
||||
BPF_ATTR_DATA_FIELD(BPF_OBJ_GET_INFO_BY_FD);
|
||||
BPF_ATTR_DATA_FIELD(BPF_PROG_QUERY);
|
||||
char char_data[256];
|
||||
};
|
||||
|
||||
@ -697,6 +698,65 @@ static const struct bpf_attr_check BPF_OBJ_GET_INFO_BY_FD_checks[] = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* TODO: This is a read/write cmd and we do not check exiting path yet */
|
||||
static const struct bpf_attr_check BPF_PROG_QUERY_checks[] = {
|
||||
{
|
||||
.data = { .BPF_PROG_QUERY_data = { .target_fd = -1 } },
|
||||
.size = offsetofend(struct BPF_PROG_QUERY_struct, target_fd),
|
||||
.str = "query={target_fd=-1"
|
||||
", attach_type=BPF_CGROUP_INET_INGRESS, query_flags=0"
|
||||
", attach_flags=0, prog_ids=NULL, prog_cnt=0}",
|
||||
},
|
||||
{ /* 1 */
|
||||
.data = { .BPF_PROG_QUERY_data = {
|
||||
.target_fd = 3141592653U,
|
||||
.attach_type = 6,
|
||||
.query_flags = 1,
|
||||
.attach_flags = 3,
|
||||
} },
|
||||
.size = offsetofend(struct BPF_PROG_QUERY_struct, attach_flags),
|
||||
.str = "query={target_fd=-1153374643"
|
||||
", attach_type=BPF_CGROUP_DEVICE"
|
||||
", query_flags=BPF_F_QUERY_EFFECTIVE"
|
||||
", attach_flags=BPF_F_ALLOW_OVERRIDE|BPF_F_ALLOW_MULTI"
|
||||
", prog_ids=NULL, prog_cnt=0}",
|
||||
},
|
||||
{ /* 2 */
|
||||
.data = { .BPF_PROG_QUERY_data = {
|
||||
.target_fd = 3141592653U,
|
||||
.attach_type = 7,
|
||||
.query_flags = 0xfffffffe,
|
||||
.attach_flags = 0xfffffffc,
|
||||
.prog_ids = 0xffffffffffffffffULL,
|
||||
.prog_cnt = 2718281828,
|
||||
} },
|
||||
.size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
|
||||
.str = "query={target_fd=-1153374643"
|
||||
", attach_type=0x7 /* BPF_??? */"
|
||||
", query_flags=0xfffffffe /* BPF_F_QUERY_??? */"
|
||||
", attach_flags=0xfffffffc /* BPF_F_??? */"
|
||||
", prog_ids=0xffffffffffffffff, prog_cnt=2718281828}",
|
||||
},
|
||||
{ /* 3 */
|
||||
.data = { .BPF_PROG_QUERY_data = {
|
||||
.target_fd = 3141592653U,
|
||||
.attach_type = 0xfeedface,
|
||||
.query_flags = 0xdeadf00d,
|
||||
.attach_flags = 0xbeefcafe,
|
||||
.prog_ids = 0xffffffffffffffffULL,
|
||||
.prog_cnt = 0,
|
||||
} },
|
||||
.size = offsetofend(struct BPF_PROG_QUERY_struct, prog_cnt),
|
||||
.str = "query={target_fd=-1153374643"
|
||||
", attach_type=0xfeedface /* BPF_??? */"
|
||||
", query_flags=BPF_F_QUERY_EFFECTIVE|0xdeadf00c"
|
||||
", attach_flags=BPF_F_ALLOW_MULTI|0xbeefcafc"
|
||||
", prog_ids=0xffffffffffffffff, prog_cnt=0}",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
#define CHK(cmd_) \
|
||||
{ \
|
||||
cmd_, #cmd_, \
|
||||
@ -724,6 +784,7 @@ main(void)
|
||||
CHK(BPF_PROG_GET_FD_BY_ID),
|
||||
CHK(BPF_MAP_GET_FD_BY_ID),
|
||||
CHK(BPF_OBJ_GET_INFO_BY_FD),
|
||||
CHK(BPF_PROG_QUERY),
|
||||
};
|
||||
|
||||
page_size = get_page_size();
|
||||
|
@ -14,3 +14,4 @@ BPF_MAP_GET_NEXT_ID 12
|
||||
BPF_PROG_GET_FD_BY_ID 13
|
||||
BPF_MAP_GET_FD_BY_ID 14
|
||||
BPF_OBJ_GET_INFO_BY_FD 15
|
||||
BPF_PROG_QUERY 16
|
||||
|
1
xlat/bpf_query_flags.in
Normal file
1
xlat/bpf_query_flags.in
Normal file
@ -0,0 +1 @@
|
||||
BPF_F_QUERY_EFFECTIVE (1U << 0)
|
Loading…
x
Reference in New Issue
Block a user