Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'cgroup-helpers'

Daniel Borkmann says:

====================
This adds various straight-forward helper improvements and additions to BPF
cgroup based connect(), sendmsg(), recvmsg() and bind-related hooks which
would allow to implement more fine-grained policies and improve current load
balancer limitations we're seeing. For details please see individual patches.
I've tested them on Kubernetes & Cilium and also added selftests for the small
verifier extension. Thanks!
====================

Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+336 -14
+2
include/linux/bpf.h
··· 233 233 ARG_CONST_SIZE_OR_ZERO, /* number of bytes accessed from memory or 0 */ 234 234 235 235 ARG_PTR_TO_CTX, /* pointer to context */ 236 + ARG_PTR_TO_CTX_OR_NULL, /* pointer to context or NULL */ 236 237 ARG_ANYTHING, /* any (initialized) argument is ok */ 237 238 ARG_PTR_TO_SPIN_LOCK, /* pointer to bpf_spin_lock */ 238 239 ARG_PTR_TO_SOCK_COMMON, /* pointer to sock_common */ ··· 1501 1500 extern const struct bpf_func_proto bpf_sock_map_update_proto; 1502 1501 extern const struct bpf_func_proto bpf_sock_hash_update_proto; 1503 1502 extern const struct bpf_func_proto bpf_get_current_cgroup_id_proto; 1503 + extern const struct bpf_func_proto bpf_get_current_ancestor_cgroup_id_proto; 1504 1504 extern const struct bpf_func_proto bpf_msg_redirect_hash_proto; 1505 1505 extern const struct bpf_func_proto bpf_msg_redirect_map_proto; 1506 1506 extern const struct bpf_func_proto bpf_sk_redirect_hash_proto;
+6 -1
include/net/cls_cgroup.h
··· 45 45 sock_cgroup_set_classid(skcd, classid); 46 46 } 47 47 48 + static inline u32 __task_get_classid(struct task_struct *task) 49 + { 50 + return task_cls_state(task)->classid; 51 + } 52 + 48 53 static inline u32 task_get_classid(const struct sk_buff *skb) 49 54 { 50 - u32 classid = task_cls_state(current)->classid; 55 + u32 classid = __task_get_classid(current); 51 56 52 57 /* Due to the nature of the classifier it is required to ignore all 53 58 * packets originating from softirq context as accessing `current'
+10
include/net/net_namespace.h
··· 168 168 #ifdef CONFIG_XFRM 169 169 struct netns_xfrm xfrm; 170 170 #endif 171 + 172 + atomic64_t net_cookie; /* written once */ 173 + 171 174 #if IS_ENABLED(CONFIG_IP_VS) 172 175 struct netns_ipvs *ipvs; 173 176 #endif ··· 276 273 277 274 void net_drop_ns(void *); 278 275 276 + u64 net_gen_cookie(struct net *net); 277 + 279 278 #else 280 279 281 280 static inline struct net *get_net(struct net *net) ··· 303 298 static inline int check_net(const struct net *net) 304 299 { 305 300 return 1; 301 + } 302 + 303 + static inline u64 net_gen_cookie(struct net *net) 304 + { 305 + return 0; 306 306 } 307 307 308 308 #define net_drop_ns NULL
+34 -1
include/uapi/linux/bpf.h
··· 2950 2950 * restricted to raw_tracepoint bpf programs. 2951 2951 * Return 2952 2952 * 0 on success, or a negative error in case of failure. 2953 + * 2954 + * u64 bpf_get_netns_cookie(void *ctx) 2955 + * Description 2956 + * Retrieve the cookie (generated by the kernel) of the network 2957 + * namespace the input *ctx* is associated with. The network 2958 + * namespace cookie remains stable for its lifetime and provides 2959 + * a global identifier that can be assumed unique. If *ctx* is 2960 + * NULL, then the helper returns the cookie for the initial 2961 + * network namespace. The cookie itself is very similar to that 2962 + * of bpf_get_socket_cookie() helper, but for network namespaces 2963 + * instead of sockets. 2964 + * Return 2965 + * A 8-byte long opaque number. 2966 + * 2967 + * u64 bpf_get_current_ancestor_cgroup_id(int ancestor_level) 2968 + * Description 2969 + * Return id of cgroup v2 that is ancestor of the cgroup associated 2970 + * with the current task at the *ancestor_level*. The root cgroup 2971 + * is at *ancestor_level* zero and each step down the hierarchy 2972 + * increments the level. If *ancestor_level* == level of cgroup 2973 + * associated with the current task, then return value will be the 2974 + * same as that of **bpf_get_current_cgroup_id**\ (). 2975 + * 2976 + * The helper is useful to implement policies based on cgroups 2977 + * that are upper in hierarchy than immediate cgroup associated 2978 + * with the current task. 2979 + * 2980 + * The format of returned id and helper limitations are same as in 2981 + * **bpf_get_current_cgroup_id**\ (). 2982 + * Return 2983 + * The id is returned or 0 in case the id could not be retrieved. 2953 2984 */ 2954 2985 #define __BPF_FUNC_MAPPER(FN) \ 2955 2986 FN(unspec), \ ··· 3104 3073 FN(jiffies64), \ 3105 3074 FN(read_branch_records), \ 3106 3075 FN(get_ns_current_pid_tgid), \ 3107 - FN(xdp_output), 3076 + FN(xdp_output), \ 3077 + FN(get_netns_cookie), \ 3078 + FN(get_current_ancestor_cgroup_id), 3108 3079 3109 3080 /* integer value in 'imm' field of BPF_CALL instruction selects which helper 3110 3081 * function eBPF program intends to call
+1
kernel/bpf/core.c
··· 2156 2156 const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak; 2157 2157 const struct bpf_func_proto bpf_get_current_comm_proto __weak; 2158 2158 const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak; 2159 + const struct bpf_func_proto bpf_get_current_ancestor_cgroup_id_proto __weak; 2159 2160 const struct bpf_func_proto bpf_get_local_storage_proto __weak; 2160 2161 const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto __weak; 2161 2162
+18
kernel/bpf/helpers.c
··· 340 340 .ret_type = RET_INTEGER, 341 341 }; 342 342 343 + BPF_CALL_1(bpf_get_current_ancestor_cgroup_id, int, ancestor_level) 344 + { 345 + struct cgroup *cgrp = task_dfl_cgroup(current); 346 + struct cgroup *ancestor; 347 + 348 + ancestor = cgroup_ancestor(cgrp, ancestor_level); 349 + if (!ancestor) 350 + return 0; 351 + return cgroup_id(ancestor); 352 + } 353 + 354 + const struct bpf_func_proto bpf_get_current_ancestor_cgroup_id_proto = { 355 + .func = bpf_get_current_ancestor_cgroup_id, 356 + .gpl_only = false, 357 + .ret_type = RET_INTEGER, 358 + .arg1_type = ARG_ANYTHING, 359 + }; 360 + 343 361 #ifdef CONFIG_CGROUP_BPF 344 362 DECLARE_PER_CPU(struct bpf_cgroup_storage*, 345 363 bpf_cgroup_storage[MAX_BPF_CGROUP_STORAGE_TYPE]);
+10 -6
kernel/bpf/verifier.c
··· 3461 3461 expected_type = CONST_PTR_TO_MAP; 3462 3462 if (type != expected_type) 3463 3463 goto err_type; 3464 - } else if (arg_type == ARG_PTR_TO_CTX) { 3464 + } else if (arg_type == ARG_PTR_TO_CTX || 3465 + arg_type == ARG_PTR_TO_CTX_OR_NULL) { 3465 3466 expected_type = PTR_TO_CTX; 3466 - if (type != expected_type) 3467 - goto err_type; 3468 - err = check_ctx_reg(env, reg, regno); 3469 - if (err < 0) 3470 - return err; 3467 + if (!(register_is_null(reg) && 3468 + arg_type == ARG_PTR_TO_CTX_OR_NULL)) { 3469 + if (type != expected_type) 3470 + goto err_type; 3471 + err = check_ctx_reg(env, reg, regno); 3472 + if (err < 0) 3473 + return err; 3474 + } 3471 3475 } else if (arg_type == ARG_PTR_TO_SOCK_COMMON) { 3472 3476 expected_type = PTR_TO_SOCK_COMMON; 3473 3477 /* Any sk pointer can be ARG_PTR_TO_SOCK_COMMON */
+101 -5
net/core/filter.c
··· 2642 2642 .arg4_type = ARG_ANYTHING, 2643 2643 }; 2644 2644 2645 + #ifdef CONFIG_CGROUP_NET_CLASSID 2646 + BPF_CALL_0(bpf_get_cgroup_classid_curr) 2647 + { 2648 + return __task_get_classid(current); 2649 + } 2650 + 2651 + static const struct bpf_func_proto bpf_get_cgroup_classid_curr_proto = { 2652 + .func = bpf_get_cgroup_classid_curr, 2653 + .gpl_only = false, 2654 + .ret_type = RET_INTEGER, 2655 + }; 2656 + #endif 2657 + 2645 2658 BPF_CALL_1(bpf_get_cgroup_classid, const struct sk_buff *, skb) 2646 2659 { 2647 2660 return task_get_classid(skb); ··· 4130 4117 .arg1_type = ARG_PTR_TO_CTX, 4131 4118 }; 4132 4119 4120 + BPF_CALL_1(bpf_get_socket_cookie_sock, struct sock *, ctx) 4121 + { 4122 + return sock_gen_cookie(ctx); 4123 + } 4124 + 4125 + static const struct bpf_func_proto bpf_get_socket_cookie_sock_proto = { 4126 + .func = bpf_get_socket_cookie_sock, 4127 + .gpl_only = false, 4128 + .ret_type = RET_INTEGER, 4129 + .arg1_type = ARG_PTR_TO_CTX, 4130 + }; 4131 + 4133 4132 BPF_CALL_1(bpf_get_socket_cookie_sock_ops, struct bpf_sock_ops_kern *, ctx) 4134 4133 { 4135 4134 return sock_gen_cookie(ctx->sk); ··· 4152 4127 .gpl_only = false, 4153 4128 .ret_type = RET_INTEGER, 4154 4129 .arg1_type = ARG_PTR_TO_CTX, 4130 + }; 4131 + 4132 + static u64 __bpf_get_netns_cookie(struct sock *sk) 4133 + { 4134 + #ifdef CONFIG_NET_NS 4135 + return net_gen_cookie(sk ? sk->sk_net.net : &init_net); 4136 + #else 4137 + return 0; 4138 + #endif 4139 + } 4140 + 4141 + BPF_CALL_1(bpf_get_netns_cookie_sock, struct sock *, ctx) 4142 + { 4143 + return __bpf_get_netns_cookie(ctx); 4144 + } 4145 + 4146 + static const struct bpf_func_proto bpf_get_netns_cookie_sock_proto = { 4147 + .func = bpf_get_netns_cookie_sock, 4148 + .gpl_only = false, 4149 + .ret_type = RET_INTEGER, 4150 + .arg1_type = ARG_PTR_TO_CTX_OR_NULL, 4151 + }; 4152 + 4153 + BPF_CALL_1(bpf_get_netns_cookie_sock_addr, struct bpf_sock_addr_kern *, ctx) 4154 + { 4155 + return __bpf_get_netns_cookie(ctx ? ctx->sk : NULL); 4156 + } 4157 + 4158 + static const struct bpf_func_proto bpf_get_netns_cookie_sock_addr_proto = { 4159 + .func = bpf_get_netns_cookie_sock_addr, 4160 + .gpl_only = false, 4161 + .ret_type = RET_INTEGER, 4162 + .arg1_type = ARG_PTR_TO_CTX_OR_NULL, 4155 4163 }; 4156 4164 4157 4165 BPF_CALL_1(bpf_get_socket_uid, struct sk_buff *, skb) ··· 4205 4147 .arg1_type = ARG_PTR_TO_CTX, 4206 4148 }; 4207 4149 4208 - BPF_CALL_5(bpf_sockopt_event_output, struct bpf_sock_ops_kern *, bpf_sock, 4209 - struct bpf_map *, map, u64, flags, void *, data, u64, size) 4150 + BPF_CALL_5(bpf_event_output_data, void *, ctx, struct bpf_map *, map, u64, flags, 4151 + void *, data, u64, size) 4210 4152 { 4211 4153 if (unlikely(flags & ~(BPF_F_INDEX_MASK))) 4212 4154 return -EINVAL; ··· 4214 4156 return bpf_event_output(map, flags, data, size, NULL, 0, NULL); 4215 4157 } 4216 4158 4217 - static const struct bpf_func_proto bpf_sockopt_event_output_proto = { 4218 - .func = bpf_sockopt_event_output, 4159 + static const struct bpf_func_proto bpf_event_output_data_proto = { 4160 + .func = bpf_event_output_data, 4219 4161 .gpl_only = true, 4220 4162 .ret_type = RET_INTEGER, 4221 4163 .arg1_type = ARG_PTR_TO_CTX, ··· 6012 5954 return &bpf_get_current_uid_gid_proto; 6013 5955 case BPF_FUNC_get_local_storage: 6014 5956 return &bpf_get_local_storage_proto; 5957 + case BPF_FUNC_get_socket_cookie: 5958 + return &bpf_get_socket_cookie_sock_proto; 5959 + case BPF_FUNC_get_netns_cookie: 5960 + return &bpf_get_netns_cookie_sock_proto; 5961 + case BPF_FUNC_perf_event_output: 5962 + return &bpf_event_output_data_proto; 5963 + case BPF_FUNC_get_current_pid_tgid: 5964 + return &bpf_get_current_pid_tgid_proto; 5965 + case BPF_FUNC_get_current_comm: 5966 + return &bpf_get_current_comm_proto; 5967 + #ifdef CONFIG_CGROUPS 5968 + case BPF_FUNC_get_current_cgroup_id: 5969 + return &bpf_get_current_cgroup_id_proto; 5970 + case BPF_FUNC_get_current_ancestor_cgroup_id: 5971 + return &bpf_get_current_ancestor_cgroup_id_proto; 5972 + #endif 5973 + #ifdef CONFIG_CGROUP_NET_CLASSID 5974 + case BPF_FUNC_get_cgroup_classid: 5975 + return &bpf_get_cgroup_classid_curr_proto; 5976 + #endif 6015 5977 default: 6016 5978 return bpf_base_func_proto(func_id); 6017 5979 } ··· 6056 5978 } 6057 5979 case BPF_FUNC_get_socket_cookie: 6058 5980 return &bpf_get_socket_cookie_sock_addr_proto; 5981 + case BPF_FUNC_get_netns_cookie: 5982 + return &bpf_get_netns_cookie_sock_addr_proto; 6059 5983 case BPF_FUNC_get_local_storage: 6060 5984 return &bpf_get_local_storage_proto; 5985 + case BPF_FUNC_perf_event_output: 5986 + return &bpf_event_output_data_proto; 5987 + case BPF_FUNC_get_current_pid_tgid: 5988 + return &bpf_get_current_pid_tgid_proto; 5989 + case BPF_FUNC_get_current_comm: 5990 + return &bpf_get_current_comm_proto; 5991 + #ifdef CONFIG_CGROUPS 5992 + case BPF_FUNC_get_current_cgroup_id: 5993 + return &bpf_get_current_cgroup_id_proto; 5994 + case BPF_FUNC_get_current_ancestor_cgroup_id: 5995 + return &bpf_get_current_ancestor_cgroup_id_proto; 5996 + #endif 5997 + #ifdef CONFIG_CGROUP_NET_CLASSID 5998 + case BPF_FUNC_get_cgroup_classid: 5999 + return &bpf_get_cgroup_classid_curr_proto; 6000 + #endif 6061 6001 #ifdef CONFIG_INET 6062 6002 case BPF_FUNC_sk_lookup_tcp: 6063 6003 return &bpf_sock_addr_sk_lookup_tcp_proto; ··· 6318 6222 case BPF_FUNC_get_local_storage: 6319 6223 return &bpf_get_local_storage_proto; 6320 6224 case BPF_FUNC_perf_event_output: 6321 - return &bpf_sockopt_event_output_proto; 6225 + return &bpf_event_output_data_proto; 6322 6226 case BPF_FUNC_sk_storage_get: 6323 6227 return &bpf_sk_storage_get_proto; 6324 6228 case BPF_FUNC_sk_storage_delete:
+15
net/core/net_namespace.c
··· 69 69 70 70 static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS; 71 71 72 + static atomic64_t cookie_gen; 73 + 74 + u64 net_gen_cookie(struct net *net) 75 + { 76 + while (1) { 77 + u64 res = atomic64_read(&net->net_cookie); 78 + 79 + if (res) 80 + return res; 81 + res = atomic64_inc_return(&cookie_gen); 82 + atomic64_cmpxchg(&net->net_cookie, 0, res); 83 + } 84 + } 85 + 72 86 static struct net_generic *net_alloc_generic(void) 73 87 { 74 88 struct net_generic *ng; ··· 1101 1087 panic("Could not allocate generic netns"); 1102 1088 1103 1089 rcu_assign_pointer(init_net.gen, ng); 1090 + net_gen_cookie(&init_net); 1104 1091 1105 1092 down_write(&pernet_ops_rwsem); 1106 1093 if (setup_net(&init_net, &init_user_ns))
+34 -1
tools/include/uapi/linux/bpf.h
··· 2950 2950 * restricted to raw_tracepoint bpf programs. 2951 2951 * Return 2952 2952 * 0 on success, or a negative error in case of failure. 2953 + * 2954 + * u64 bpf_get_netns_cookie(void *ctx) 2955 + * Description 2956 + * Retrieve the cookie (generated by the kernel) of the network 2957 + * namespace the input *ctx* is associated with. The network 2958 + * namespace cookie remains stable for its lifetime and provides 2959 + * a global identifier that can be assumed unique. If *ctx* is 2960 + * NULL, then the helper returns the cookie for the initial 2961 + * network namespace. The cookie itself is very similar to that 2962 + * of bpf_get_socket_cookie() helper, but for network namespaces 2963 + * instead of sockets. 2964 + * Return 2965 + * A 8-byte long opaque number. 2966 + * 2967 + * u64 bpf_get_current_ancestor_cgroup_id(int ancestor_level) 2968 + * Description 2969 + * Return id of cgroup v2 that is ancestor of the cgroup associated 2970 + * with the current task at the *ancestor_level*. The root cgroup 2971 + * is at *ancestor_level* zero and each step down the hierarchy 2972 + * increments the level. If *ancestor_level* == level of cgroup 2973 + * associated with the current task, then return value will be the 2974 + * same as that of **bpf_get_current_cgroup_id**\ (). 2975 + * 2976 + * The helper is useful to implement policies based on cgroups 2977 + * that are upper in hierarchy than immediate cgroup associated 2978 + * with the current task. 2979 + * 2980 + * The format of returned id and helper limitations are same as in 2981 + * **bpf_get_current_cgroup_id**\ (). 2982 + * Return 2983 + * The id is returned or 0 in case the id could not be retrieved. 2953 2984 */ 2954 2985 #define __BPF_FUNC_MAPPER(FN) \ 2955 2986 FN(unspec), \ ··· 3104 3073 FN(jiffies64), \ 3105 3074 FN(read_branch_records), \ 3106 3075 FN(get_ns_current_pid_tgid), \ 3107 - FN(xdp_output), 3076 + FN(xdp_output), \ 3077 + FN(get_netns_cookie), \ 3078 + FN(get_current_ancestor_cgroup_id), 3108 3079 3109 3080 /* integer value in 'imm' field of BPF_CALL instruction selects which helper 3110 3081 * function eBPF program intends to call
+105
tools/testing/selftests/bpf/verifier/ctx.c
··· 91 91 .result = REJECT, 92 92 .errstr = "variable ctx access var_off=(0x0; 0x4)", 93 93 }, 94 + { 95 + "pass ctx or null check, 1: ctx", 96 + .insns = { 97 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 98 + BPF_FUNC_get_netns_cookie), 99 + BPF_MOV64_IMM(BPF_REG_0, 0), 100 + BPF_EXIT_INSN(), 101 + }, 102 + .prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, 103 + .expected_attach_type = BPF_CGROUP_UDP6_SENDMSG, 104 + .result = ACCEPT, 105 + }, 106 + { 107 + "pass ctx or null check, 2: null", 108 + .insns = { 109 + BPF_MOV64_IMM(BPF_REG_1, 0), 110 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 111 + BPF_FUNC_get_netns_cookie), 112 + BPF_MOV64_IMM(BPF_REG_0, 0), 113 + BPF_EXIT_INSN(), 114 + }, 115 + .prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, 116 + .expected_attach_type = BPF_CGROUP_UDP6_SENDMSG, 117 + .result = ACCEPT, 118 + }, 119 + { 120 + "pass ctx or null check, 3: 1", 121 + .insns = { 122 + BPF_MOV64_IMM(BPF_REG_1, 1), 123 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 124 + BPF_FUNC_get_netns_cookie), 125 + BPF_MOV64_IMM(BPF_REG_0, 0), 126 + BPF_EXIT_INSN(), 127 + }, 128 + .prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, 129 + .expected_attach_type = BPF_CGROUP_UDP6_SENDMSG, 130 + .result = REJECT, 131 + .errstr = "R1 type=inv expected=ctx", 132 + }, 133 + { 134 + "pass ctx or null check, 4: ctx - const", 135 + .insns = { 136 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612), 137 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 138 + BPF_FUNC_get_netns_cookie), 139 + BPF_MOV64_IMM(BPF_REG_0, 0), 140 + BPF_EXIT_INSN(), 141 + }, 142 + .prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, 143 + .expected_attach_type = BPF_CGROUP_UDP6_SENDMSG, 144 + .result = REJECT, 145 + .errstr = "dereference of modified ctx ptr", 146 + }, 147 + { 148 + "pass ctx or null check, 5: null (connect)", 149 + .insns = { 150 + BPF_MOV64_IMM(BPF_REG_1, 0), 151 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 152 + BPF_FUNC_get_netns_cookie), 153 + BPF_MOV64_IMM(BPF_REG_0, 0), 154 + BPF_EXIT_INSN(), 155 + }, 156 + .prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, 157 + .expected_attach_type = BPF_CGROUP_INET4_CONNECT, 158 + .result = ACCEPT, 159 + }, 160 + { 161 + "pass ctx or null check, 6: null (bind)", 162 + .insns = { 163 + BPF_MOV64_IMM(BPF_REG_1, 0), 164 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 165 + BPF_FUNC_get_netns_cookie), 166 + BPF_MOV64_IMM(BPF_REG_0, 0), 167 + BPF_EXIT_INSN(), 168 + }, 169 + .prog_type = BPF_PROG_TYPE_CGROUP_SOCK, 170 + .expected_attach_type = BPF_CGROUP_INET4_POST_BIND, 171 + .result = ACCEPT, 172 + }, 173 + { 174 + "pass ctx or null check, 7: ctx (bind)", 175 + .insns = { 176 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 177 + BPF_FUNC_get_socket_cookie), 178 + BPF_MOV64_IMM(BPF_REG_0, 0), 179 + BPF_EXIT_INSN(), 180 + }, 181 + .prog_type = BPF_PROG_TYPE_CGROUP_SOCK, 182 + .expected_attach_type = BPF_CGROUP_INET4_POST_BIND, 183 + .result = ACCEPT, 184 + }, 185 + { 186 + "pass ctx or null check, 8: null (bind)", 187 + .insns = { 188 + BPF_MOV64_IMM(BPF_REG_1, 0), 189 + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 190 + BPF_FUNC_get_socket_cookie), 191 + BPF_MOV64_IMM(BPF_REG_0, 0), 192 + BPF_EXIT_INSN(), 193 + }, 194 + .prog_type = BPF_PROG_TYPE_CGROUP_SOCK, 195 + .expected_attach_type = BPF_CGROUP_INET4_POST_BIND, 196 + .result = REJECT, 197 + .errstr = "R1 type=inv expected=ctx", 198 + },