aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/filter.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index b39c869d22e3..1f6a26c4f8b9 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3110,6 +3110,36 @@ void bpf_warn_invalid_xdp_action(u32 act)
3110} 3110}
3111EXPORT_SYMBOL_GPL(bpf_warn_invalid_xdp_action); 3111EXPORT_SYMBOL_GPL(bpf_warn_invalid_xdp_action);
3112 3112
3113static bool __is_valid_sock_ops_access(int off, int size)
3114{
3115 if (off < 0 || off >= sizeof(struct bpf_sock_ops))
3116 return false;
3117 /* The verifier guarantees that size > 0. */
3118 if (off % size != 0)
3119 return false;
3120 if (size != sizeof(__u32))
3121 return false;
3122
3123 return true;
3124}
3125
3126static bool sock_ops_is_valid_access(int off, int size,
3127 enum bpf_access_type type,
3128 struct bpf_insn_access_aux *info)
3129{
3130 if (type == BPF_WRITE) {
3131 switch (off) {
3132 case offsetof(struct bpf_sock_ops, op) ...
3133 offsetof(struct bpf_sock_ops, replylong[3]):
3134 break;
3135 default:
3136 return false;
3137 }
3138 }
3139
3140 return __is_valid_sock_ops_access(off, size);
3141}
3142
3113static u32 bpf_convert_ctx_access(enum bpf_access_type type, 3143static u32 bpf_convert_ctx_access(enum bpf_access_type type,
3114 const struct bpf_insn *si, 3144 const struct bpf_insn *si,
3115 struct bpf_insn *insn_buf, 3145 struct bpf_insn *insn_buf,
@@ -3379,6 +3409,138 @@ static u32 xdp_convert_ctx_access(enum bpf_access_type type,
3379 return insn - insn_buf; 3409 return insn - insn_buf;
3380} 3410}
3381 3411
3412static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
3413 const struct bpf_insn *si,
3414 struct bpf_insn *insn_buf,
3415 struct bpf_prog *prog)
3416{
3417 struct bpf_insn *insn = insn_buf;
3418 int off;
3419
3420 switch (si->off) {
3421 case offsetof(struct bpf_sock_ops, op) ...
3422 offsetof(struct bpf_sock_ops, replylong[3]):
3423 BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, op) !=
3424 FIELD_SIZEOF(struct bpf_sock_ops_kern, op));
3425 BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, reply) !=
3426 FIELD_SIZEOF(struct bpf_sock_ops_kern, reply));
3427 BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, replylong) !=
3428 FIELD_SIZEOF(struct bpf_sock_ops_kern, replylong));
3429 off = si->off;
3430 off -= offsetof(struct bpf_sock_ops, op);
3431 off += offsetof(struct bpf_sock_ops_kern, op);
3432 if (type == BPF_WRITE)
3433 *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
3434 off);
3435 else
3436 *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
3437 off);
3438 break;
3439
3440 case offsetof(struct bpf_sock_ops, family):
3441 BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
3442
3443 *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
3444 struct bpf_sock_ops_kern, sk),
3445 si->dst_reg, si->src_reg,
3446 offsetof(struct bpf_sock_ops_kern, sk));
3447 *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
3448 offsetof(struct sock_common, skc_family));
3449 break;
3450
3451 case offsetof(struct bpf_sock_ops, remote_ip4):
3452 BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
3453
3454 *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
3455 struct bpf_sock_ops_kern, sk),
3456 si->dst_reg, si->src_reg,
3457 offsetof(struct bpf_sock_ops_kern, sk));
3458 *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
3459 offsetof(struct sock_common, skc_daddr));
3460 break;
3461
3462 case offsetof(struct bpf_sock_ops, local_ip4):
3463 BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_rcv_saddr) != 4);
3464
3465 *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
3466 struct bpf_sock_ops_kern, sk),
3467 si->dst_reg, si->src_reg,
3468 offsetof(struct bpf_sock_ops_kern, sk));
3469 *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
3470 offsetof(struct sock_common,
3471 skc_rcv_saddr));
3472 break;
3473
3474 case offsetof(struct bpf_sock_ops, remote_ip6[0]) ...
3475 offsetof(struct bpf_sock_ops, remote_ip6[3]):
3476#if IS_ENABLED(CONFIG_IPV6)
3477 BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
3478 skc_v6_daddr.s6_addr32[0]) != 4);
3479
3480 off = si->off;
3481 off -= offsetof(struct bpf_sock_ops, remote_ip6[0]);
3482 *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
3483 struct bpf_sock_ops_kern, sk),
3484 si->dst_reg, si->src_reg,
3485 offsetof(struct bpf_sock_ops_kern, sk));
3486 *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
3487 offsetof(struct sock_common,
3488 skc_v6_daddr.s6_addr32[0]) +
3489 off);
3490#else
3491 *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
3492#endif
3493 break;
3494
3495 case offsetof(struct bpf_sock_ops, local_ip6[0]) ...
3496 offsetof(struct bpf_sock_ops, local_ip6[3]):
3497#if IS_ENABLED(CONFIG_IPV6)
3498 BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
3499 skc_v6_rcv_saddr.s6_addr32[0]) != 4);
3500
3501 off = si->off;
3502 off -= offsetof(struct bpf_sock_ops, local_ip6[0]);
3503 *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
3504 struct bpf_sock_ops_kern, sk),
3505 si->dst_reg, si->src_reg,
3506 offsetof(struct bpf_sock_ops_kern, sk));
3507 *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
3508 offsetof(struct sock_common,
3509 skc_v6_rcv_saddr.s6_addr32[0]) +
3510 off);
3511#else
3512 *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
3513#endif
3514 break;
3515
3516 case offsetof(struct bpf_sock_ops, remote_port):
3517 BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
3518
3519 *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
3520 struct bpf_sock_ops_kern, sk),
3521 si->dst_reg, si->src_reg,
3522 offsetof(struct bpf_sock_ops_kern, sk));
3523 *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
3524 offsetof(struct sock_common, skc_dport));
3525#ifndef __BIG_ENDIAN_BITFIELD
3526 *insn++ = BPF_ALU32_IMM(BPF_LSH, si->dst_reg, 16);
3527#endif
3528 break;
3529
3530 case offsetof(struct bpf_sock_ops, local_port):
3531 BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
3532
3533 *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
3534 struct bpf_sock_ops_kern, sk),
3535 si->dst_reg, si->src_reg,
3536 offsetof(struct bpf_sock_ops_kern, sk));
3537 *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
3538 offsetof(struct sock_common, skc_num));
3539 break;
3540 }
3541 return insn - insn_buf;
3542}
3543
3382const struct bpf_verifier_ops sk_filter_prog_ops = { 3544const struct bpf_verifier_ops sk_filter_prog_ops = {
3383 .get_func_proto = sk_filter_func_proto, 3545 .get_func_proto = sk_filter_func_proto,
3384 .is_valid_access = sk_filter_is_valid_access, 3546 .is_valid_access = sk_filter_is_valid_access,
@@ -3428,6 +3590,12 @@ const struct bpf_verifier_ops cg_sock_prog_ops = {
3428 .convert_ctx_access = sock_filter_convert_ctx_access, 3590 .convert_ctx_access = sock_filter_convert_ctx_access,
3429}; 3591};
3430 3592
3593const struct bpf_verifier_ops sock_ops_prog_ops = {
3594 .get_func_proto = bpf_base_func_proto,
3595 .is_valid_access = sock_ops_is_valid_access,
3596 .convert_ctx_access = sock_ops_convert_ctx_access,
3597};
3598
3431int sk_detach_filter(struct sock *sk) 3599int sk_detach_filter(struct sock *sk)
3432{ 3600{
3433 int ret = -ENOENT; 3601 int ret = -ENOENT;