Improve bpf wrapper to check arguments more carefully

This commit is contained in:
Tom Hughes 2018-08-14 20:46:22 +01:00
parent 0097176525
commit 488a5b8bb6
2 changed files with 192 additions and 100 deletions

View File

@ -11649,34 +11649,59 @@ static UInt bpf_obj_get_info_size(Int fd)
PRE(sys_bpf)
{
union vki_bpf_attr *attr = (union vki_bpf_attr *)(Addr)ARG2;
UInt res, key_size, value_size, size;
UInt res, key_size, value_size;
PRINT("sys_bpf ( %ld, %#" FMT_REGWORD "x, %" FMT_REGWORD "u )",
ARG1, ARG2, ARG3);
PRE_REG_READ3(long, "bpf",
int, cmd, union vki_bpf_attr *, attr, unsigned int, size);
PRINT("bpf ( %ld, %" FMT_REGWORD "u, %" FMT_REGWORD "u )",
ARG1, ARG2, ARG3);
size = *(UInt *)(Addr)ARG3;
switch (ARG1) {
case VKI_BPF_PROG_GET_NEXT_ID:
case VKI_BPF_MAP_GET_NEXT_ID:
PRE_MEM_WRITE("bpf(attr->next_id", (Addr)&attr->next_id, sizeof(attr->next_id));
break;
case VKI_BPF_PROG_GET_FD_BY_ID:
PRE_MEM_READ("bpf(attr->prog_id", (Addr)&attr->prog_id, sizeof(attr->prog_id));
break;
case VKI_BPF_MAP_GET_FD_BY_ID:
PRE_MEM_READ("bpf(attr->map_id", (Addr)&attr->map_id, sizeof(attr->map_id));
break;
case VKI_BPF_BTF_GET_FD_BY_ID:
PRE_MEM_READ("bpf(attr->btf_id", (Addr)&attr->btf_id, sizeof(attr->btf_id));
break;
case VKI_BPF_MAP_CREATE:
if (!ML_(safe_to_deref)(attr, ARG3)) {
SET_STATUS_Failure(VKI_EINVAL);
break;
}
PRE_MEM_READ("bpf(attr->map_flags", (Addr)&attr->map_flags, sizeof(attr->map_flags));
if (attr->map_flags & VKI_BPF_F_NUMA_NODE)
PRE_MEM_READ("bpf(attr->numa_node", (Addr)&attr->numa_node, sizeof(attr->numa_node));
PRE_MEM_READ("bpf(attr->map_type", (Addr)&attr->map_type, sizeof(attr->map_type));
PRE_MEM_READ("bpf(attr->map_ifindex", (Addr)&attr->map_ifindex, sizeof(attr->map_ifindex));
PRE_MEM_READ("bpf(attr->max_entries", (Addr)&attr->max_entries, sizeof(attr->max_entries));
PRE_MEM_READ("bpf(attr->key_size", (Addr)&attr->key_size, sizeof(attr->key_size));
PRE_MEM_READ("bpf(attr->value_size", (Addr)&attr->value_size, sizeof(attr->value_size));
pre_asciiz_str(tid, (unsigned long int)attr->map_name,
VKI_BPF_OBJ_NAME_LEN, "bpf(attr->map_name)");
switch (attr->map_type) {
case VKI_BPF_MAP_TYPE_ARRAY_OF_MAPS:
case VKI_BPF_MAP_TYPE_HASH_OF_MAPS:
PRE_MEM_READ("bpf(attr->inner_map_fd", (Addr)&attr->inner_map_fd, sizeof(attr->inner_map_fd));
if (!ML_(fd_allowed)(attr->inner_map_fd, "bpf", tid, False))
SET_STATUS_Failure(VKI_EBADF);
break;
case VKI_BPF_MAP_TYPE_ARRAY:
if (ARG3 >= offsetof(union vki_bpf_attr, btf_value_type_id) + sizeof(__vki_u32)) {
PRE_MEM_READ("bpf(attr->btf_key_type_id", (Addr)&attr->btf_key_type_id, sizeof(attr->btf_key_type_id));
PRE_MEM_READ("bpf(attr->btf_value_type_id", (Addr)&attr->btf_value_type_id, sizeof(attr->btf_value_type_id));
if (attr->btf_key_type_id && attr->btf_value_type_id) {
PRE_MEM_READ("bpf(attr->btf_id", (Addr)&attr->btf_id, sizeof(attr->btf_id));
if (!ML_(fd_allowed)(attr->btf_fd, "bpf", tid, False)) {
SET_STATUS_Failure(VKI_EBADF);
break;
}
}
}
break;
case VKI_BPF_MAP_TYPE_UNSPEC:
case VKI_BPF_MAP_TYPE_HASH:
case VKI_BPF_MAP_TYPE_ARRAY:
case VKI_BPF_MAP_TYPE_PROG_ARRAY:
case VKI_BPF_MAP_TYPE_PERF_EVENT_ARRAY:
case VKI_BPF_MAP_TYPE_PERCPU_HASH:
@ -11694,28 +11719,13 @@ PRE(sys_bpf)
default:
break;
}
/*
* For kernels recent enough (4.18+) to have BTF support, deal with
* BTF info. Kernel only uses the file descriptor for map types that
* support BTF information (see bpf_map_support_seq_show() in kernel),
* but we do not have a way to probe that. Let's hope that
* attr->btf_key_type_id and attr->btf_value_type_id will remain NULL
* if BTF info is not needed.
*/
if (size >= offsetof(union vki_bpf_attr, btf_value_type_id) +
sizeof(__vki_u32)) {
if (attr->btf_key_type_id && attr->btf_value_type_id) {
if (!ML_(fd_allowed)(attr->btf_fd, "bpf", tid, False)) {
SET_STATUS_Failure(VKI_EBADF);
break;
}
}
}
break;
case VKI_BPF_MAP_LOOKUP_ELEM:
/* Perform a lookup on an eBPF map. Read key, write value. */
if (ML_(safe_to_deref)(attr, ARG3) &&
attr->key != 0 && attr->value != 0) {
PRE_MEM_READ("bpf(attr->key)", (Addr)&attr->key, sizeof(attr->key));
PRE_MEM_READ("bpf(attr->value)", (Addr)&attr->value, sizeof(attr->value));
PRE_MEM_READ("bpf(attr->map_fd)", (Addr)&attr->map_fd, sizeof(attr->map_fd));
if (ML_(safe_to_deref)(attr, ARG3)) {
if (!ML_(fd_allowed)(attr->map_fd, "bpf", tid, False)) {
SET_STATUS_Failure(VKI_EBADF);
break;
@ -11729,8 +11739,11 @@ PRE(sys_bpf)
break;
case VKI_BPF_MAP_UPDATE_ELEM:
/* Add or update a map element in kernel. Read key, read value. */
if (ML_(safe_to_deref)(attr, ARG3) &&
attr->key != 0 && attr->value != 0) {
PRE_MEM_READ("bpf(attr->key)", (Addr)&attr->key, sizeof(attr->key));
PRE_MEM_READ("bpf(attr->value)", (Addr)&attr->value, sizeof(attr->value));
PRE_MEM_READ("bpf(attr->map_fd)", (Addr)&attr->map_fd, sizeof(attr->map_fd));
PRE_MEM_READ("bpf(attr->flags)", (Addr)&attr->flags, sizeof(attr->flags));
if (ML_(safe_to_deref)(attr, ARG3)) {
if (!ML_(fd_allowed)(attr->map_fd, "bpf", tid, False)) {
SET_STATUS_Failure(VKI_EBADF);
break;
@ -11744,7 +11757,9 @@ PRE(sys_bpf)
break;
case VKI_BPF_MAP_DELETE_ELEM:
/* Delete a map element in kernel. Read key from user space. */
if (ML_(safe_to_deref)(attr, ARG3) && attr->key != 0) {
PRE_MEM_READ("bpf(attr->key)", (Addr)&attr->key, sizeof(attr->key));
PRE_MEM_READ("bpf(attr->map_fd)", (Addr)&attr->map_fd, sizeof(attr->map_fd));
if (ML_(safe_to_deref)(attr, ARG3)) {
if (!ML_(fd_allowed)(attr->map_fd, "bpf", tid, False)) {
SET_STATUS_Failure(VKI_EBADF);
break;
@ -11756,8 +11771,11 @@ PRE(sys_bpf)
break;
case VKI_BPF_MAP_GET_NEXT_KEY:
/* From a key, get next key for the map. Read key, write next key. */
if (ML_(safe_to_deref)(attr, ARG3) &&
attr->key != 0 && attr->next_key != 0) {
PRE_MEM_READ("bpf(attr->key)", (Addr)&attr->key, sizeof(attr->key));
PRE_MEM_READ("bpf(attr->next_key)", (Addr)&attr->next_key, sizeof(attr->next_key));
PRE_MEM_READ("bpf(attr->map_fd)", (Addr)&attr->map_fd, sizeof(attr->map_fd));
PRE_MEM_READ("bpf(attr->flags)", (Addr)&attr->flags, sizeof(attr->flags));
if (ML_(safe_to_deref)(attr, ARG3)) {
if (!ML_(fd_allowed)(attr->map_fd, "bpf", tid, False)) {
SET_STATUS_Failure(VKI_EBADF);
break;
@ -11771,18 +11789,27 @@ PRE(sys_bpf)
break;
case VKI_BPF_PROG_LOAD:
/* Load a program into the kernel from an array of instructions. */
PRE_MEM_READ("bpf(attr->prog_type)", (Addr)&attr->prog_type, sizeof(attr->prog_type));
PRE_MEM_READ("bpf(attr->prog_flags)", (Addr)&attr->prog_flags, sizeof(attr->prog_flags));
PRE_MEM_READ("bpf(attr->license)", (Addr)&attr->license, sizeof(attr->license));
PRE_MEM_READ("bpf(attr->insn_cnt)", (Addr)&attr->insn_cnt, sizeof(attr->insn_cnt));
PRE_MEM_READ("bpf(attr->expected_attach_type)", (Addr)&attr->expected_attach_type, sizeof(attr->expected_attach_type));
PRE_MEM_READ("bpf(attr->prog_ifindex)", (Addr)&attr->prog_ifindex, sizeof(attr->prog_ifindex));
PRE_MEM_READ("bpf(attr->log_level)", (Addr)&attr->log_level, sizeof(attr->log_level));
PRE_MEM_READ("bpf(attr->log_buf)", (Addr)&attr->log_buf, sizeof(attr->log_buf));
PRE_MEM_READ("bpf(attr->log_size)", (Addr)&attr->log_size, sizeof(attr->log_size));
pre_asciiz_str(tid, (Addr)attr->prog_name, VKI_BPF_OBJ_NAME_LEN, "bpf(attr->prog_name)");
if (ML_(safe_to_deref)(attr, ARG3)) {
if (attr->prog_type == VKI_BPF_PROG_TYPE_KPROBE)
PRE_MEM_READ("bpf(attr->kern_version)", (Addr)&attr->kern_version, sizeof(attr->kern_version));
/* Read instructions, license, program name. */
PRE_MEM_READ("bpf(attr->insns)", attr->insns,
attr->insn_cnt * sizeof(struct vki_bpf_insn));
/* License is limited to 128 characters in kernel/bpf/syscall.c. */
pre_asciiz_str(tid, attr->license, 128, "bpf(attr->license)");
pre_asciiz_str(tid, (unsigned long int)attr->prog_name,
VKI_BPF_OBJ_NAME_LEN, "bpf(attr->prog_name)");
/* Possibly write up to log_len into user space log buffer. */
if (attr->log_level && attr->log_size > 128 && attr->log_buf != 0)
PRE_MEM_WRITE("bpf(attr->log_buf)",
attr->log_buf, attr->log_size);
if (attr->log_level || attr->log_size || attr->log_buf)
PRE_MEM_WRITE("bpf(attr->log_buf)", attr->log_buf, attr->log_size);
}
break;
case VKI_BPF_OBJ_PIN:
@ -11790,78 +11817,61 @@ PRE(sys_bpf)
/* fall through */
case VKI_BPF_OBJ_GET:
/* Get pinned eBPF program or map. Read path name. */
PRE_MEM_READ("bpf(attr->file_flags)", (Addr)&attr->file_flags, sizeof(attr->file_flags));
PRE_MEM_READ("bpf(attr->pathname)", (Addr)&attr->pathname, sizeof(attr->pathname));
PRE_MEM_READ("bpf(attr->bpf_fd)", (Addr)&attr->bpf_fd, sizeof(attr->bpf_fd));
if (ML_(safe_to_deref)(attr, ARG3)) {
if (!ML_(fd_allowed)(attr->bpf_fd, "bpf", tid, False)) {
SET_STATUS_Failure(VKI_EBADF);
break;
}
pre_asciiz_str(tid, attr->pathname, VKI_BPF_OBJ_NAME_LEN,
"bpf(attr->pathname)");
pre_asciiz_str(tid, attr->pathname, VKI_BPF_OBJ_NAME_LEN, "bpf(attr->pathname)");
}
break;
case VKI_BPF_PROG_ATTACH:
case VKI_BPF_PROG_DETACH:
/* Detach eBPF program from kernel attach point. */
PRE_MEM_READ("bpf(attr->attach_type)", (Addr)&attr->attach_type, sizeof(attr->attach_type));
PRE_MEM_READ("bpf(attr->target_fd)", (Addr)&attr->target_fd, sizeof(attr->target_fd));
if (ML_(safe_to_deref)(attr, ARG3)) {
switch (attr->attach_type) {
case VKI_BPF_SK_SKB_STREAM_PARSER:
case VKI_BPF_SK_SKB_STREAM_VERDICT:
case VKI_BPF_SK_MSG_VERDICT:
/*
* The above attach types do not use attr->attach_bpf_fd.
* Just check attr->target_fd and exit.
*/
if (!ML_(fd_allowed)(attr->target_fd, "bpf", tid, False))
SET_STATUS_Failure(VKI_EBADF);
return;
case VKI_BPF_CGROUP_INET_INGRESS:
case VKI_BPF_CGROUP_INET_EGRESS:
case VKI_BPF_CGROUP_INET_SOCK_CREATE:
case VKI_BPF_CGROUP_SOCK_OPS:
case VKI_BPF_CGROUP_DEVICE:
case VKI_BPF_CGROUP_INET4_BIND:
case VKI_BPF_CGROUP_INET6_BIND:
case VKI_BPF_CGROUP_INET4_CONNECT:
case VKI_BPF_CGROUP_INET6_CONNECT:
case VKI_BPF_CGROUP_INET4_POST_BIND:
case VKI_BPF_CGROUP_INET6_POST_BIND:
case VKI_BPF_CGROUP_UDP4_SENDMSG:
case VKI_BPF_CGROUP_UDP6_SENDMSG:
case VKI_BPF_LIRC_MODE2:
default:
break;
}
}
/* fall through */
case VKI_BPF_PROG_ATTACH:
/* Attach eBPF program to kernel attach point. */
if (ML_(safe_to_deref)(attr, ARG3)) {
if (!ML_(fd_allowed)(attr->target_fd, "bpf", tid, False) ||
!ML_(fd_allowed)(attr->attach_bpf_fd, "bpf", tid, False)) {
if (!ML_(fd_allowed)(attr->target_fd, "bpf", tid, False))
SET_STATUS_Failure(VKI_EBADF);
break;
if (ARG1 == VKI_BPF_PROG_ATTACH ||
(attr->attach_type != VKI_BPF_SK_SKB_STREAM_PARSER &&
attr->attach_type != VKI_BPF_SK_SKB_STREAM_VERDICT &&
attr->attach_type != VKI_BPF_SK_MSG_VERDICT)) {
PRE_MEM_READ("bpf(attr->attach_bpf_fd)", (Addr)&attr->attach_bpf_fd, sizeof(attr->attach_bpf_fd));
if (!ML_(fd_allowed)(attr->attach_bpf_fd, "bpf", tid, False))
SET_STATUS_Failure(VKI_EBADF);
}
}
break;
case VKI_BPF_PROG_TEST_RUN:
/* Test prog. Read data_in, write up to data_size_out to data_out. */
if (ML_(safe_to_deref)(attr, ARG3) &&
attr->test.data_in != 0 && attr->test.data_out != 0) {
PRE_MEM_READ("bpf(attr->test.prog_fd)", (Addr)&attr->test.prog_fd, sizeof(attr->test.prog_fd));
PRE_MEM_READ("bpf(attr->test.repeat)", (Addr)&attr->test.repeat, sizeof(attr->test.repeat));
PRE_MEM_READ("bpf(attr->test.data_size_in)", (Addr)&attr->test.data_size_in, sizeof(attr->test.data_size_in));
PRE_MEM_READ("bpf(attr->test.data_in)", (Addr)&attr->test.data_in, sizeof(attr->test.data_in));
PRE_MEM_READ("bpf(attr->test.data_out)", (Addr)&attr->test.data_out, sizeof(attr->test.data_out));
PRE_MEM_WRITE("bpf(attr->test.retval)", (Addr)&attr->test.retval, sizeof(attr->test.retval));
PRE_MEM_WRITE("bpf(attr->test.data_size_out)", (Addr)&attr->test.data_size_out, sizeof(attr->test.data_size_out));
PRE_MEM_WRITE("bpf(attr->test.duration)", (Addr)&attr->test.duration, sizeof(attr->test.duration));
if (ML_(safe_to_deref)(attr, ARG3)) {
if (!ML_(fd_allowed)(attr->test.prog_fd, "bpf", tid, False)) {
SET_STATUS_Failure(VKI_EBADF);
break;
}
PRE_MEM_READ("bpf(attr->test.data_in)",
attr->test.data_in, attr->test.data_size_in);
/*
* TODO: Kernel writes to data_out but we do not know the size yet.
* PRE_MEM_WRITE("bpf(attr->test.data_out)",
* attr->test.data_out, ??);
*/
PRE_MEM_READ("bpf(attr->test.data_in)", attr->test.data_in, attr->test.data_size_in);
/* should be data_size_in + VKI_XDP_PACKET_HEADROOM for VKI_BPF_PROG_TYPE_XDP */
PRE_MEM_WRITE("bpf(attr->test.data_out)", attr->test.data_out, attr->test.data_size_in);
}
break;
case VKI_BPF_OBJ_GET_INFO_BY_FD:
/* Get info for eBPF map or program. Write info. */
if (ML_(safe_to_deref)(attr, ARG3) && attr->info.info != 0) {
PRE_MEM_READ("bpf(attr->info.bpf_fd)", (Addr)&attr->info.bpf_fd, sizeof(attr->info.bpf_fd));
PRE_MEM_READ("bpf(attr->info.info)", (Addr)&attr->info.info, sizeof(attr->info.info));
PRE_MEM_READ("bpf(attr->info.info_len)", (Addr)&attr->info.info_len, sizeof(attr->info.info_len));
if (ML_(safe_to_deref)(attr, ARG3)) {
if (!ML_(fd_allowed)(attr->info.bpf_fd, "bpf", tid, False)) {
SET_STATUS_Failure(VKI_EBADF);
break;
@ -11874,8 +11884,9 @@ PRE(sys_bpf)
else
PRE_MEM_WRITE("bpf(attr->info.info)", attr->info.info,
VG_MIN(attr->info.info_len,
VG_MAX(sizeof(struct vki_bpf_prog_info),
sizeof(struct vki_bpf_map_info))));
VG_MAX(VG_MAX(sizeof(struct vki_bpf_prog_info),
sizeof(struct vki_bpf_map_info)),
sizeof(struct vki_bpf_btf_info))));
}
break;
case VKI_BPF_PROG_QUERY:
@ -11883,17 +11894,29 @@ PRE(sys_bpf)
* Query list of eBPF program attached to cgroup.
* Write array of ids (up to attr->query.prog_cnt u32-long ids).
*/
if (ML_(safe_to_deref)(attr, ARG3) && attr->query.prog_ids != 0) {
PRE_MEM_READ("bpf(attr->query.query_flags)", (Addr)&attr->query.query_flags, sizeof(attr->query.query_flags));
PRE_MEM_READ("bpf(attr->query.attach_type)", (Addr)&attr->query.attach_type, sizeof(attr->query.attach_type));
PRE_MEM_READ("bpf(attr->query.target_fd)", (Addr)&attr->query.target_fd, sizeof(attr->query.target_fd));
PRE_MEM_READ("bpf(attr->query.prog_cnt)", (Addr)&attr->query.prog_cnt, sizeof(attr->query.prog_cnt));
PRE_MEM_WRITE("bpf(attr->query.attach_flags)", (Addr)&attr->query.attach_flags, sizeof(attr->query.attach_flags));
if (ML_(safe_to_deref)(attr, ARG3)) {
if (!ML_(fd_allowed)(attr->query.target_fd, "bpf", tid, False)) {
SET_STATUS_Failure(VKI_EBADF);
break;
}
PRE_MEM_WRITE("bpf(attr->query.prog_ids)", attr->query.prog_ids,
attr->query.prog_cnt * sizeof(__vki_u32));
if (attr->query.prog_cnt > 0) {
PRE_MEM_READ("bpf(attr->query.prog_ids)", (Addr)&attr->query.prog_ids, sizeof(attr->query.prog_ids));
if (attr->query.prog_ids) {
PRE_MEM_WRITE("bpf(attr->query.prog_ids)", attr->query.prog_ids,
attr->query.prog_cnt * sizeof(__vki_u32));
}
}
}
break;
case VKI_BPF_RAW_TRACEPOINT_OPEN:
/* Open raw tracepoint. Read tracepoint name. */
PRE_MEM_READ("bpf(attr->raw_tracepoint.name)", (Addr)&attr->raw_tracepoint.name, sizeof(attr->raw_tracepoint.name));
PRE_MEM_READ("bpf(attr->raw_tracepoint.prog_fd)", (Addr)&attr->raw_tracepoint.prog_fd, sizeof(attr->raw_tracepoint.prog_fd));
if (ML_(safe_to_deref)(attr, ARG3)) {
if (!ML_(fd_allowed)(attr->raw_tracepoint.prog_fd,
"bpf", tid, False)) {
@ -11907,17 +11930,30 @@ PRE(sys_bpf)
break;
case VKI_BPF_BTF_LOAD:
/* Load BTF information about a program into the kernel. */
PRE_MEM_READ("bpf(attr->btf)", (Addr)&attr->btf, sizeof(attr->btf));
PRE_MEM_READ("bpf(attr->btf_size)", (Addr)&attr->btf_size, sizeof(attr->btf_size));
PRE_MEM_READ("bpf(attr->btf_log_buf)", (Addr)&attr->btf_log_buf, sizeof(attr->btf_log_buf));
PRE_MEM_READ("bpf(attr->btf_log_size)", (Addr)&attr->btf_log_size, sizeof(attr->btf_log_size));
PRE_MEM_READ("bpf(attr->btf_log_level)", (Addr)&attr->btf_log_level, sizeof(attr->btf_log_level));
if (ML_(safe_to_deref)(attr, ARG3)) {
/* Read BTF data. */
PRE_MEM_READ("bpf(attr->btf)", attr->btf, attr->btf_size);
/* Possibly write up to btf_log_len into user space log buffer. */
if (attr->btf_log_level && attr->btf_log_size > 128 &&
attr->btf_log_buf != 0)
if (attr->btf_log_level || attr->btf_log_size || attr->btf_log_buf)
PRE_MEM_WRITE("bpf(attr->btf_log_buf)",
attr->btf_log_buf, attr->btf_log_size);
}
case VKI_BPF_TASK_FD_QUERY:
/* Get info about the task. Write collected info. */
PRE_MEM_READ("bpf(attr->task_fd_query.pid)", (Addr)&attr->task_fd_query.pid, sizeof(attr->task_fd_query.pid));
PRE_MEM_READ("bpf(attr->task_fd_query.fd)", (Addr)&attr->task_fd_query.fd, sizeof(attr->task_fd_query.fd));
PRE_MEM_READ("bpf(attr->task_fd_query.flags)", (Addr)&attr->task_fd_query.flags, sizeof(attr->task_fd_query.flags));
PRE_MEM_READ("bpf(attr->task_fd_query.buf_len)", (Addr)&attr->task_fd_query.buf_len, sizeof(attr->task_fd_query.buf_len));
PRE_MEM_READ("bpf(attr->task_fd_query.buf)", (Addr)&attr->task_fd_query.buf, sizeof(attr->task_fd_query.buf));
PRE_MEM_WRITE("bpf(attr->task_fd_query.prog_id)", (Addr)&attr->task_fd_query.prog_id, sizeof(attr->task_fd_query.prog_id));
PRE_MEM_WRITE("bpf(attr->task_fd_query.fd_type)", (Addr)&attr->task_fd_query.fd_type, sizeof(attr->task_fd_query.fd_type));
PRE_MEM_WRITE("bpf(attr->task_fd_query.probe_offset)", (Addr)&attr->task_fd_query.probe_offset, sizeof(attr->task_fd_query.probe_offset));
PRE_MEM_WRITE("bpf(attr->task_fd_query.probe_addr)", (Addr)&attr->task_fd_query.probe_addr, sizeof(attr->task_fd_query.probe_addr));
if (ML_(safe_to_deref)(attr, ARG3)) {
if (!ML_(fd_allowed)(attr->task_fd_query.fd, "bpf", tid, False)) {
SET_STATUS_Failure(VKI_EBADF);
@ -11947,13 +11983,15 @@ POST(sys_bpf)
vg_assert(SUCCESS);
switch (ARG1) {
case VKI_BPF_PROG_GET_NEXT_ID:
case VKI_BPF_MAP_GET_NEXT_ID:
POST_MEM_WRITE(attr->next_id, sizeof(attr->next_id));
break;
case VKI_BPF_MAP_UPDATE_ELEM:
case VKI_BPF_MAP_DELETE_ELEM:
case VKI_BPF_OBJ_PIN:
case VKI_BPF_PROG_ATTACH:
case VKI_BPF_PROG_DETACH:
case VKI_BPF_PROG_GET_NEXT_ID:
case VKI_BPF_MAP_GET_NEXT_ID:
break;
/* Following commands have bpf() return a file descriptor. */
case VKI_BPF_MAP_CREATE:
@ -11990,17 +12028,22 @@ POST(sys_bpf)
} else {
if (VG_(clo_track_fds))
ML_(record_fd_open_nameless)(tid, RES);
if (attr->log_level)
POST_MEM_WRITE(attr->log_buf, attr->log_size);
}
if (attr->log_level || attr->log_size || attr->log_buf)
POST_MEM_WRITE(attr->log_buf, attr->log_size);
break;
case VKI_BPF_PROG_TEST_RUN:
POST_MEM_WRITE((Addr)&attr->test.retval, sizeof(attr->test.retval));
POST_MEM_WRITE((Addr)&attr->test.data_size_out, sizeof(attr->test.data_size_out));
POST_MEM_WRITE((Addr)&attr->test.duration, sizeof(attr->test.duration));
POST_MEM_WRITE(attr->test.data_out, attr->test.data_size_out);
break;
case VKI_BPF_OBJ_GET_INFO_BY_FD:
POST_MEM_WRITE(attr->info.info, attr->info.info_len);
break;
case VKI_BPF_PROG_QUERY:
POST_MEM_WRITE((Addr)&attr->query.attach_flags, sizeof(attr->query.attach_flags));
POST_MEM_WRITE((Addr)&attr->query.prog_cnt, sizeof(attr->query.prog_cnt));
if (attr->query.prog_ids)
POST_MEM_WRITE(attr->query.prog_ids,
attr->query.prog_cnt * sizeof(__vki_u32));
@ -12013,12 +12056,16 @@ POST(sys_bpf)
} else {
if (VG_(clo_track_fds))
ML_(record_fd_open_nameless)(tid, RES);
if (attr->btf_log_level)
POST_MEM_WRITE(attr->btf_log_buf, attr->btf_log_size);
}
if (attr->btf_log_level)
POST_MEM_WRITE(attr->btf_log_buf, attr->btf_log_size);
break;
case VKI_BPF_TASK_FD_QUERY:
POST_MEM_WRITE(attr->task_fd_query.buf, attr->task_fd_query.buf_len);
POST_MEM_WRITE((Addr)&attr->task_fd_query.prog_id, sizeof(attr->task_fd_query.prog_id));
POST_MEM_WRITE((Addr)&attr->task_fd_query.fd_type, sizeof(attr->task_fd_query.fd_type));
POST_MEM_WRITE((Addr)&attr->task_fd_query.probe_offset, sizeof(attr->task_fd_query.probe_offset));
POST_MEM_WRITE((Addr)&attr->task_fd_query.probe_addr, sizeof(attr->task_fd_query.probe_addr));
break;
default:
VG_(message)(Vg_DebugMsg,

View File

@ -242,6 +242,8 @@ typedef __vki_u64 vki_uint64_t;
typedef __vki_u16 __vki_le16;
#define __vki_aligned_u64 __vki_u64 __attribute__((aligned(8)))
//----------------------------------------------------------------------
// From linux-2.6.8.1/include/linux/limits.h
//----------------------------------------------------------------------
@ -4887,6 +4889,30 @@ enum vki_bpf_map_type {
VKI_BPF_MAP_TYPE_SOCKHASH,
};
enum vki_bpf_prog_type {
VKI_BPF_PROG_TYPE_UNSPEC,
VKI_BPF_PROG_TYPE_SOCKET_FILTER,
VKI_BPF_PROG_TYPE_KPROBE,
VKI_BPF_PROG_TYPE_SCHED_CLS,
VKI_BPF_PROG_TYPE_SCHED_ACT,
VKI_BPF_PROG_TYPE_TRACEPOINT,
VKI_BPF_PROG_TYPE_XDP,
VKI_BPF_PROG_TYPE_PERF_EVENT,
VKI_BPF_PROG_TYPE_CGROUP_SKB,
VKI_BPF_PROG_TYPE_CGROUP_SOCK,
VKI_BPF_PROG_TYPE_LWT_IN,
VKI_BPF_PROG_TYPE_LWT_OUT,
VKI_BPF_PROG_TYPE_LWT_XMIT,
VKI_BPF_PROG_TYPE_SOCK_OPS,
VKI_BPF_PROG_TYPE_SK_SKB,
VKI_BPF_PROG_TYPE_CGROUP_DEVICE,
VKI_BPF_PROG_TYPE_SK_MSG,
VKI_BPF_PROG_TYPE_RAW_TRACEPOINT,
VKI_BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
VKI_BPF_PROG_TYPE_LWT_SEG6LOCAL,
VKI_BPF_PROG_TYPE_LIRC_MODE2,
};
enum vki_bpf_attach_type {
VKI_BPF_CGROUP_INET_INGRESS,
VKI_BPF_CGROUP_INET_EGRESS,
@ -4908,9 +4934,11 @@ enum vki_bpf_attach_type {
__VKI_MAX_BPF_ATTACH_TYPE
};
/* Specify numa node during map creation */
#define VKI_BPF_F_NUMA_NODE (1U << 2)
#define VKI_BPF_OBJ_NAME_LEN 16U
#define __vki_aligned_u64 __vki_u64 __attribute__((aligned(8)))
union vki_bpf_attr {
struct { /* anonymous struct used by BPF_MAP_CREATE command */
__vki_u32 map_type; /* one of enum bpf_map_type */
@ -5040,6 +5068,8 @@ union vki_bpf_attr {
} task_fd_query;
} __attribute__((aligned(8)));
#define VKI_XDP_PACKET_HEADROOM 256
#define VKI_BPF_TAG_SIZE 8
struct vki_bpf_prog_info {
@ -5056,8 +5086,13 @@ struct vki_bpf_prog_info {
__vki_aligned_u64 map_ids;
char name[VKI_BPF_OBJ_NAME_LEN];
__vki_u32 ifindex;
__vki_u32 gpl_compatible:1;
__vki_u64 netns_dev;
__vki_u64 netns_ino;
__vki_u32 nr_jited_ksyms;
__vki_u32 nr_jited_func_lens;
__vki_aligned_u64 jited_ksyms;
__vki_aligned_u64 jited_func_lens;
} __attribute__((aligned(8)));
struct vki_bpf_map_info {
@ -5069,8 +5104,18 @@ struct vki_bpf_map_info {
__vki_u32 map_flags;
char name[VKI_BPF_OBJ_NAME_LEN];
__vki_u32 ifindex;
__vki_u32 :32;
__vki_u64 netns_dev;
__vki_u64 netns_ino;
__vki_u32 btf_id;
__vki_u32 btf_key_type_id;
__vki_u32 btf_value_type_id;
} __attribute__((aligned(8)));
struct vki_bpf_btf_info {
__vki_aligned_u64 btf;
__vki_u32 btf_size;
__vki_u32 id;
} __attribute__((aligned(8)));
/*--------------------------------------------------------------------*/