Commit 13bbbfbea759 ("bpf: Add bpf_dynptr_read and bpf_dynptr_write") added the bpf_dynptr_write() and bpf_dynptr_read() APIs. However, it will be needed for some dynptr types to pass in flags as well (e.g. when writing to a skb, the user may like to invalidate the hash or recompute the checksum). This patch adds a "u64 flags" arg to the bpf_dynptr_read() and bpf_dynptr_write() APIs before their UAPI signature freezes where we then cannot change them anymore with a 5.19.x released kernel.
Unified · Split
| @@ -5222,22 +5222,25 @@ union bpf_attr { · 5221 unmodified lines | ||
| 5222 | 5222 | * Return |
| 5223 | 5223 | * Nothing. Always succeeds. |
| 5224 | 5224 | * |
| 5225 | − * long bpf_dynptr_read(void *dst, u32 len, struct bpf_dynptr *src, u32 offset) | |
| 5225 | + * long bpf_dynptr_read(void *dst, u32 len, struct bpf_dynptr *src, u32 offset, u64 flags) | |
| 5226 | 5226 | * Description |
| 5227 | 5227 | * Read *len* bytes from *src* into *dst*, starting from *offset* |
| 5228 | 5228 | * into *src*. |
| 5229 | + * *flags* is currently unused. | |
| 5229 | 5230 | * Return |
| 5230 | 5231 | * 0 on success, -E2BIG if *offset* + *len* exceeds the length |
| 5231 | − * of *src*'s data, -EINVAL if *src* is an invalid dynptr. | |
| 5232 | + * of *src*'s data, -EINVAL if *src* is an invalid dynptr or if | |
| 5233 | + * *flags* is not 0. | |
| 5232 | 5234 | * |
| 5233 | − * long bpf_dynptr_write(struct bpf_dynptr *dst, u32 offset, void *src, u32 len) | |
| 5235 | + * long bpf_dynptr_write(struct bpf_dynptr *dst, u32 offset, void *src, u32 len, u64 flags) | |
| 5234 | 5236 | * Description |
| 5235 | 5237 | * Write *len* bytes from *src* into *dst*, starting from *offset* |
| 5236 | 5238 | * into *dst*. |
| 5239 | + * *flags* is currently unused. | |
| 5237 | 5240 | * Return |
| 5238 | 5241 | * 0 on success, -E2BIG if *offset* + *len* exceeds the length |
| 5239 | 5242 | * of *dst*'s data, -EINVAL if *dst* is an invalid dynptr or if *dst* |
| 5240 | − * is a read-only dynptr. | |
| 5243 | + * is a read-only dynptr or if *flags* is not 0. | |
| 5241 | 5244 | * |
| 5242 | 5245 | * void *bpf_dynptr_data(struct bpf_dynptr *ptr, u32 offset, u32 len) |
| 5243 | 5246 | * Description |
| @@ -1497,11 +1497,12 @@ const struct bpf_func_proto bpf_dynptr_from_mem_proto = { · 1496 unmodified lines | ||
| 1497 | 1497 | .arg4_type = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL | MEM_UNINIT, |
| 1498 | 1498 | }; |
| 1499 | 1499 | |
| 1500 | −BPF_CALL_4(bpf_dynptr_read, void *, dst, u32, len, struct bpf_dynptr_kern *, src, u32, offset) | |
| 1500 | +BPF_CALL_5(bpf_dynptr_read, void *, dst, u32, len, struct bpf_dynptr_kern *, src, | |
| 1501 | + u32, offset, u64, flags) | |
| 1501 | 1502 | { |
| 1502 | 1503 | int err; |
| 1503 | 1504 | |
| 1504 | − if (!src->data) | |
| 1505 | + if (!src->data || flags) | |
| 1505 | 1506 | return -EINVAL; |
| 1506 | 1507 | |
| 1507 | 1508 | err = bpf_dynptr_check_off_len(src, offset, len); |
| @@ -1521,13 +1522,15 @@ const struct bpf_func_proto bpf_dynptr_read_proto = { · 13 unmodified lines | ||
| 1521 | 1522 | .arg2_type = ARG_CONST_SIZE_OR_ZERO, |
| 1522 | 1523 | .arg3_type = ARG_PTR_TO_DYNPTR, |
| 1523 | 1524 | .arg4_type = ARG_ANYTHING, |
| 1525 | + .arg5_type = ARG_ANYTHING, | |
| 1524 | 1526 | }; |
| 1525 | 1527 | |
| 1526 | −BPF_CALL_4(bpf_dynptr_write, struct bpf_dynptr_kern *, dst, u32, offset, void *, src, u32, len) | |
| 1528 | +BPF_CALL_5(bpf_dynptr_write, struct bpf_dynptr_kern *, dst, u32, offset, void *, src, | |
| 1529 | + u32, len, u64, flags) | |
| 1527 | 1530 | { |
| 1528 | 1531 | int err; |
| 1529 | 1532 | |
| 1530 | − if (!dst->data || bpf_dynptr_is_rdonly(dst)) | |
| 1533 | + if (!dst->data || flags || bpf_dynptr_is_rdonly(dst)) | |
| 1531 | 1534 | return -EINVAL; |
| 1532 | 1535 | |
| 1533 | 1536 | err = bpf_dynptr_check_off_len(dst, offset, len); |
| @@ -1547,6 +1550,7 @@ const struct bpf_func_proto bpf_dynptr_write_proto = { · 13 unmodified lines | ||
| 1547 | 1550 | .arg2_type = ARG_ANYTHING, |
| 1548 | 1551 | .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, |
| 1549 | 1552 | .arg4_type = ARG_CONST_SIZE_OR_ZERO, |
| 1553 | + .arg5_type = ARG_ANYTHING, | |
| 1550 | 1554 | }; |
| 1551 | 1555 | |
| 1552 | 1556 | BPF_CALL_3(bpf_dynptr_data, struct bpf_dynptr_kern *, ptr, u32, offset, u32, len) |
| @@ -5222,22 +5222,25 @@ union bpf_attr { · 5221 unmodified lines | ||
| 5222 | 5222 | * Return |
| 5223 | 5223 | * Nothing. Always succeeds. |
| 5224 | 5224 | * |
| 5225 | − * long bpf_dynptr_read(void *dst, u32 len, struct bpf_dynptr *src, u32 offset) | |
| 5225 | + * long bpf_dynptr_read(void *dst, u32 len, struct bpf_dynptr *src, u32 offset, u64 flags) | |
| 5226 | 5226 | * Description |
| 5227 | 5227 | * Read *len* bytes from *src* into *dst*, starting from *offset* |
| 5228 | 5228 | * into *src*. |
| 5229 | + * *flags* is currently unused. | |
| 5229 | 5230 | * Return |
| 5230 | 5231 | * 0 on success, -E2BIG if *offset* + *len* exceeds the length |
| 5231 | − * of *src*'s data, -EINVAL if *src* is an invalid dynptr. | |
| 5232 | + * of *src*'s data, -EINVAL if *src* is an invalid dynptr or if | |
| 5233 | + * *flags* is not 0. | |
| 5232 | 5234 | * |
| 5233 | − * long bpf_dynptr_write(struct bpf_dynptr *dst, u32 offset, void *src, u32 len) | |
| 5235 | + * long bpf_dynptr_write(struct bpf_dynptr *dst, u32 offset, void *src, u32 len, u64 flags) | |
| 5234 | 5236 | * Description |
| 5235 | 5237 | * Write *len* bytes from *src* into *dst*, starting from *offset* |
| 5236 | 5238 | * into *dst*. |
| 5239 | + * *flags* is currently unused. | |
| 5237 | 5240 | * Return |
| 5238 | 5241 | * 0 on success, -E2BIG if *offset* + *len* exceeds the length |
| 5239 | 5242 | * of *dst*'s data, -EINVAL if *dst* is an invalid dynptr or if *dst* |
| 5240 | − * is a read-only dynptr. | |
| 5243 | + * is a read-only dynptr or if *flags* is not 0. | |
| 5241 | 5244 | * |
| 5242 | 5245 | * void *bpf_dynptr_data(struct bpf_dynptr *ptr, u32 offset, u32 len) |
| 5243 | 5246 | * Description |
| @@ -140,12 +140,12 @@ int use_after_invalid(void *ctx) · 139 unmodified lines | ||
| 140 | 140 | |
| 141 | 141 | bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(read_data), 0, &ptr); |
| 142 | 142 | |
| 143 | − bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0); | |
| 143 | + bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0); | |
| 144 | 144 | |
| 145 | 145 | bpf_ringbuf_submit_dynptr(&ptr, 0); |
| 146 | 146 | |
| 147 | 147 | /* this should fail */ |
| 148 | − bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0); | |
| 148 | + bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0); | |
| 149 | 149 | |
| 150 | 150 | return 0; |
| 151 | 151 | } |
| @@ -338,7 +338,7 @@ int invalid_helper2(void *ctx) · 186 unmodified lines | ||
| 338 | 338 | get_map_val_dynptr(&ptr); |
| 339 | 339 | |
| 340 | 340 | /* this should fail */ |
| 341 | − bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 8, 0); | |
| 341 | + bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 8, 0, 0); | |
| 342 | 342 | |
| 343 | 343 | return 0; |
| 344 | 344 | } |
| @@ -377,7 +377,7 @@ int invalid_write2(void *ctx) · 32 unmodified lines | ||
| 377 | 377 | memcpy((void *)&ptr + 8, &x, sizeof(x)); |
| 378 | 378 | |
| 379 | 379 | /* this should fail */ |
| 380 | − bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0); | |
| 380 | + bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0); | |
| 381 | 381 | |
| 382 | 382 | bpf_ringbuf_submit_dynptr(&ptr, 0); |
| 383 | 383 | |
| @@ -473,7 +473,7 @@ int invalid_read2(void *ctx) · 89 unmodified lines | ||
| 473 | 473 | get_map_val_dynptr(&ptr); |
| 474 | 474 | |
| 475 | 475 | /* this should fail */ |
| 476 | − bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 1, 0); | |
| 476 | + bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 1, 0, 0); | |
| 477 | 477 | |
| 478 | 478 | return 0; |
| 479 | 479 | } |
| @@ -43,10 +43,10 @@ int test_read_write(void *ctx) · 42 unmodified lines | ||
| 43 | 43 | bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(write_data), 0, &ptr); |
| 44 | 44 | |
| 45 | 45 | /* Write data into the dynptr */ |
| 46 | − err = err ?: bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data)); | |
| 46 | + err = bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0); | |
| 47 | 47 | |
| 48 | 48 | /* Read the data that was written into the dynptr */ |
| 49 | − err = err ?: bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0); | |
| 49 | + err = err ?: bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0); | |
| 50 | 50 | |
| 51 | 51 | /* Ensure the data we read matches the data we wrote */ |
| 52 | 52 | for (i = 0; i < sizeof(read_data); i++) { |