History

bpf: Add bpf_dynptr_read and bpf_dynptr_write

This patch adds two helper functions, bpf_dynptr_read and bpf_dynptr_write: long bpf_dynptr_read(void *dst, u32 len, struct bpf_dynptr *src, u32 offset); long bpf_dynptr_write(struct bpf_dynptr *dst, u32 offset, void *src, u32 len); The dynptr passed into these functions must be valid dynptrs that have been initialized.

Joanne Koong committed 4 years ago

Commit 13bbbfb1 parent bc34dee3 files · +116 −0Browse files

Showing the changes to kernel (1 of 3 files). Show all

Unified · Split

kernel/bpf/helpers.c+78−0
@@ -1417,12 +1417,24 @@ const struct bpf_func_proto bpf_kptr_xchg_proto = { · 1416 unmodified lines
1417 */1417 */
1418#define DYNPTR_MAX_SIZE ((1UL << 24) - 1)1418#define DYNPTR_MAX_SIZE ((1UL << 24) - 1)
1419#define DYNPTR_TYPE_SHIFT 281419#define DYNPTR_TYPE_SHIFT 28
1420#define DYNPTR_SIZE_MASK 0xFFFFFF
1421#define DYNPTR_RDONLY_BIT BIT(31)
1422
1423static bool bpf_dynptr_is_rdonly(struct bpf_dynptr_kern *ptr)
1424{
1425 return ptr->size & DYNPTR_RDONLY_BIT;
1426}
1420 1427
1421static void bpf_dynptr_set_type(struct bpf_dynptr_kern *ptr, enum bpf_dynptr_type type)1428static void bpf_dynptr_set_type(struct bpf_dynptr_kern *ptr, enum bpf_dynptr_type type)
1422{1429{
1423 ptr->size |= type << DYNPTR_TYPE_SHIFT;1430 ptr->size |= type << DYNPTR_TYPE_SHIFT;
1424}1431}
1425 1432
1433static u32 bpf_dynptr_get_size(struct bpf_dynptr_kern *ptr)
1434{
1435 return ptr->size & DYNPTR_SIZE_MASK;
1436}
1437
1426int bpf_dynptr_check_size(u32 size)1438int bpf_dynptr_check_size(u32 size)
1427{1439{
1428 return size > DYNPTR_MAX_SIZE ? -E2BIG : 0;1440 return size > DYNPTR_MAX_SIZE ? -E2BIG : 0;
@@ -1442,6 +1454,16 @@ void bpf_dynptr_set_null(struct bpf_dynptr_kern *ptr) · 13 unmodified lines
1442 memset(ptr, 0, sizeof(*ptr));1454 memset(ptr, 0, sizeof(*ptr));
1443}1455}
1444 1456
1457static int bpf_dynptr_check_off_len(struct bpf_dynptr_kern *ptr, u32 offset, u32 len)
1458{
1459 u32 size = bpf_dynptr_get_size(ptr);
1460
1461 if (len > size || offset > size - len)
1462 return -E2BIG;
1463
1464 return 0;
1465}
1466
1445BPF_CALL_4(bpf_dynptr_from_mem, void *, data, u32, size, u64, flags, struct bpf_dynptr_kern *, ptr)1467BPF_CALL_4(bpf_dynptr_from_mem, void *, data, u32, size, u64, flags, struct bpf_dynptr_kern *, ptr)
1446{1468{
1447 int err;1469 int err;
@@ -1475,6 +1497,58 @@ const struct bpf_func_proto bpf_dynptr_from_mem_proto = { · 27 unmodified lines
1475 .arg4_type = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL | MEM_UNINIT,1497 .arg4_type = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL | MEM_UNINIT,
1476};1498};
1477 1499
1500BPF_CALL_4(bpf_dynptr_read, void *, dst, u32, len, struct bpf_dynptr_kern *, src, u32, offset)
1501{
1502 int err;
1503
1504 if (!src->data)
1505 return -EINVAL;
1506
1507 err = bpf_dynptr_check_off_len(src, offset, len);
1508 if (err)
1509 return err;
1510
1511 memcpy(dst, src->data + src->offset + offset, len);
1512
1513 return 0;
1514}
1515
1516const struct bpf_func_proto bpf_dynptr_read_proto = {
1517 .func = bpf_dynptr_read,
1518 .gpl_only = false,
1519 .ret_type = RET_INTEGER,
1520 .arg1_type = ARG_PTR_TO_UNINIT_MEM,
1521 .arg2_type = ARG_CONST_SIZE_OR_ZERO,
1522 .arg3_type = ARG_PTR_TO_DYNPTR,
1523 .arg4_type = ARG_ANYTHING,
1524};
1525
1526BPF_CALL_4(bpf_dynptr_write, struct bpf_dynptr_kern *, dst, u32, offset, void *, src, u32, len)
1527{
1528 int err;
1529
1530 if (!dst->data || bpf_dynptr_is_rdonly(dst))
1531 return -EINVAL;
1532
1533 err = bpf_dynptr_check_off_len(dst, offset, len);
1534 if (err)
1535 return err;
1536
1537 memcpy(dst->data + dst->offset + offset, src, len);
1538
1539 return 0;
1540}
1541
1542const struct bpf_func_proto bpf_dynptr_write_proto = {
1543 .func = bpf_dynptr_write,
1544 .gpl_only = false,
1545 .ret_type = RET_INTEGER,
1546 .arg1_type = ARG_PTR_TO_DYNPTR,
1547 .arg2_type = ARG_ANYTHING,
1548 .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
1549 .arg4_type = ARG_CONST_SIZE_OR_ZERO,
1550};
1551
1478const struct bpf_func_proto bpf_get_current_task_proto __weak;1552const struct bpf_func_proto bpf_get_current_task_proto __weak;
1479const struct bpf_func_proto bpf_get_current_task_btf_proto __weak;1553const struct bpf_func_proto bpf_get_current_task_btf_proto __weak;
1480const struct bpf_func_proto bpf_probe_read_user_proto __weak;1554const struct bpf_func_proto bpf_probe_read_user_proto __weak;
@@ -1537,6 +1611,10 @@ bpf_base_func_proto(enum bpf_func_id func_id) · 56 unmodified lines
1537 return &bpf_strncmp_proto;1611 return &bpf_strncmp_proto;
1538 case BPF_FUNC_dynptr_from_mem:1612 case BPF_FUNC_dynptr_from_mem:
1539 return &bpf_dynptr_from_mem_proto;1613 return &bpf_dynptr_from_mem_proto;
1614 case BPF_FUNC_dynptr_read:
1615 return &bpf_dynptr_read_proto;
1616 case BPF_FUNC_dynptr_write:
1617 return &bpf_dynptr_write_proto;
1540 default:1618 default:
1541 break;1619 break;
1542 }1620 }