summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-03-16 15:20:08 -0400
committerDavid S. Miller <davem@davemloft.net>2019-03-16 15:20:08 -0400
commit0aedadcf6b4863a0d6eaad05a26425cc52944027 (patch)
treed64f583138091cfe886c45dabdfa5cb8efb41eb4 /tools
parent4589e28db46ee4961edfd794c5bb43887d38c8e5 (diff)
parent86be36f6502c52ddb4b85938145324fd07332da1 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2019-03-16 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) Fix a umem memory leak on cleanup in AF_XDP, from Björn. 2) Fix BTF to properly resolve forward-declared enums into their corresponding full enum definition types during deduplication, from Andrii. 3) Fix libbpf to reject invalid flags in xsk_socket__create(), from Magnus. 4) Fix accessing invalid pointer returned from bpf_tcp_sock() and bpf_sk_fullsock() after bpf_sk_release() was called, from Martin. 5) Fix generation of load/store DW instructions in PPC JIT, from Naveen. 6) Various fixes in BPF helper function documentation in bpf.h UAPI header used to bpf-helpers(7) man page, from Quentin. 7) Fix segfault in BPF test_progs when prog loading failed, from Yonghong. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools')
-rw-r--r--tools/include/uapi/linux/bpf.h188
-rw-r--r--tools/lib/bpf/btf.c51
-rw-r--r--tools/lib/bpf/libbpf.c13
-rw-r--r--tools/lib/bpf/xsk.c15
-rw-r--r--tools/testing/selftests/bpf/bpf_helpers.h2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/map_lock.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/spinlock.c2
-rw-r--r--tools/testing/selftests/bpf/progs/test_sock_fields_kern.c88
-rw-r--r--tools/testing/selftests/bpf/test_btf.c44
-rw-r--r--tools/testing/selftests/bpf/test_sock_fields.c134
-rw-r--r--tools/testing/selftests/bpf/verifier/ref_tracking.c168
-rw-r--r--tools/testing/selftests/bpf/verifier/sock.c4
12 files changed, 582 insertions, 129 deletions
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 3c38ac9a92a7..929c8e537a14 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -502,16 +502,6 @@ union bpf_attr {
502 * Return 502 * Return
503 * 0 on success, or a negative error in case of failure. 503 * 0 on success, or a negative error in case of failure.
504 * 504 *
505 * int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags)
506 * Description
507 * Push an element *value* in *map*. *flags* is one of:
508 *
509 * **BPF_EXIST**
510 * If the queue/stack is full, the oldest element is removed to
511 * make room for this.
512 * Return
513 * 0 on success, or a negative error in case of failure.
514 *
515 * int bpf_probe_read(void *dst, u32 size, const void *src) 505 * int bpf_probe_read(void *dst, u32 size, const void *src)
516 * Description 506 * Description
517 * For tracing programs, safely attempt to read *size* bytes from 507 * For tracing programs, safely attempt to read *size* bytes from
@@ -1435,14 +1425,14 @@ union bpf_attr {
1435 * u64 bpf_get_socket_cookie(struct bpf_sock_addr *ctx) 1425 * u64 bpf_get_socket_cookie(struct bpf_sock_addr *ctx)
1436 * Description 1426 * Description
1437 * Equivalent to bpf_get_socket_cookie() helper that accepts 1427 * Equivalent to bpf_get_socket_cookie() helper that accepts
1438 * *skb*, but gets socket from **struct bpf_sock_addr** contex. 1428 * *skb*, but gets socket from **struct bpf_sock_addr** context.
1439 * Return 1429 * Return
1440 * A 8-byte long non-decreasing number. 1430 * A 8-byte long non-decreasing number.
1441 * 1431 *
1442 * u64 bpf_get_socket_cookie(struct bpf_sock_ops *ctx) 1432 * u64 bpf_get_socket_cookie(struct bpf_sock_ops *ctx)
1443 * Description 1433 * Description
1444 * Equivalent to bpf_get_socket_cookie() helper that accepts 1434 * Equivalent to bpf_get_socket_cookie() helper that accepts
1445 * *skb*, but gets socket from **struct bpf_sock_ops** contex. 1435 * *skb*, but gets socket from **struct bpf_sock_ops** context.
1446 * Return 1436 * Return
1447 * A 8-byte long non-decreasing number. 1437 * A 8-byte long non-decreasing number.
1448 * 1438 *
@@ -2098,52 +2088,52 @@ union bpf_attr {
2098 * Return 2088 * Return
2099 * 0 on success, or a negative error in case of failure. 2089 * 0 on success, or a negative error in case of failure.
2100 * 2090 *
2101 * int bpf_rc_keydown(void *ctx, u32 protocol, u64 scancode, u32 toggle) 2091 * int bpf_rc_repeat(void *ctx)
2102 * Description 2092 * Description
2103 * This helper is used in programs implementing IR decoding, to 2093 * This helper is used in programs implementing IR decoding, to
2104 * report a successfully decoded key press with *scancode*, 2094 * report a successfully decoded repeat key message. This delays
2105 * *toggle* value in the given *protocol*. The scancode will be 2095 * the generation of a key up event for previously generated
2106 * translated to a keycode using the rc keymap, and reported as 2096 * key down event.
2107 * an input key down event. After a period a key up event is
2108 * generated. This period can be extended by calling either
2109 * **bpf_rc_keydown**\ () again with the same values, or calling
2110 * **bpf_rc_repeat**\ ().
2111 * 2097 *
2112 * Some protocols include a toggle bit, in case the button was 2098 * Some IR protocols like NEC have a special IR message for
2113 * released and pressed again between consecutive scancodes. 2099 * repeating last button, for when a button is held down.
2114 * 2100 *
2115 * The *ctx* should point to the lirc sample as passed into 2101 * The *ctx* should point to the lirc sample as passed into
2116 * the program. 2102 * the program.
2117 * 2103 *
2118 * The *protocol* is the decoded protocol number (see
2119 * **enum rc_proto** for some predefined values).
2120 *
2121 * This helper is only available is the kernel was compiled with 2104 * This helper is only available is the kernel was compiled with
2122 * the **CONFIG_BPF_LIRC_MODE2** configuration option set to 2105 * the **CONFIG_BPF_LIRC_MODE2** configuration option set to
2123 * "**y**". 2106 * "**y**".
2124 * Return 2107 * Return
2125 * 0 2108 * 0
2126 * 2109 *
2127 * int bpf_rc_repeat(void *ctx) 2110 * int bpf_rc_keydown(void *ctx, u32 protocol, u64 scancode, u32 toggle)
2128 * Description 2111 * Description
2129 * This helper is used in programs implementing IR decoding, to 2112 * This helper is used in programs implementing IR decoding, to
2130 * report a successfully decoded repeat key message. This delays 2113 * report a successfully decoded key press with *scancode*,
2131 * the generation of a key up event for previously generated 2114 * *toggle* value in the given *protocol*. The scancode will be
2132 * key down event. 2115 * translated to a keycode using the rc keymap, and reported as
2116 * an input key down event. After a period a key up event is
2117 * generated. This period can be extended by calling either
2118 * **bpf_rc_keydown**\ () again with the same values, or calling
2119 * **bpf_rc_repeat**\ ().
2133 * 2120 *
2134 * Some IR protocols like NEC have a special IR message for 2121 * Some protocols include a toggle bit, in case the button was
2135 * repeating last button, for when a button is held down. 2122 * released and pressed again between consecutive scancodes.
2136 * 2123 *
2137 * The *ctx* should point to the lirc sample as passed into 2124 * The *ctx* should point to the lirc sample as passed into
2138 * the program. 2125 * the program.
2139 * 2126 *
2127 * The *protocol* is the decoded protocol number (see
2128 * **enum rc_proto** for some predefined values).
2129 *
2140 * This helper is only available is the kernel was compiled with 2130 * This helper is only available is the kernel was compiled with
2141 * the **CONFIG_BPF_LIRC_MODE2** configuration option set to 2131 * the **CONFIG_BPF_LIRC_MODE2** configuration option set to
2142 * "**y**". 2132 * "**y**".
2143 * Return 2133 * Return
2144 * 0 2134 * 0
2145 * 2135 *
2146 * uint64_t bpf_skb_cgroup_id(struct sk_buff *skb) 2136 * u64 bpf_skb_cgroup_id(struct sk_buff *skb)
2147 * Description 2137 * Description
2148 * Return the cgroup v2 id of the socket associated with the *skb*. 2138 * Return the cgroup v2 id of the socket associated with the *skb*.
2149 * This is roughly similar to the **bpf_get_cgroup_classid**\ () 2139 * This is roughly similar to the **bpf_get_cgroup_classid**\ ()
@@ -2159,30 +2149,12 @@ union bpf_attr {
2159 * Return 2149 * Return
2160 * The id is returned or 0 in case the id could not be retrieved. 2150 * The id is returned or 0 in case the id could not be retrieved.
2161 * 2151 *
2162 * u64 bpf_skb_ancestor_cgroup_id(struct sk_buff *skb, int ancestor_level)
2163 * Description
2164 * Return id of cgroup v2 that is ancestor of cgroup associated
2165 * with the *skb* at the *ancestor_level*. The root cgroup is at
2166 * *ancestor_level* zero and each step down the hierarchy
2167 * increments the level. If *ancestor_level* == level of cgroup
2168 * associated with *skb*, then return value will be same as that
2169 * of **bpf_skb_cgroup_id**\ ().
2170 *
2171 * The helper is useful to implement policies based on cgroups
2172 * that are upper in hierarchy than immediate cgroup associated
2173 * with *skb*.
2174 *
2175 * The format of returned id and helper limitations are same as in
2176 * **bpf_skb_cgroup_id**\ ().
2177 * Return
2178 * The id is returned or 0 in case the id could not be retrieved.
2179 *
2180 * u64 bpf_get_current_cgroup_id(void) 2152 * u64 bpf_get_current_cgroup_id(void)
2181 * Return 2153 * Return
2182 * A 64-bit integer containing the current cgroup id based 2154 * A 64-bit integer containing the current cgroup id based
2183 * on the cgroup within which the current task is running. 2155 * on the cgroup within which the current task is running.
2184 * 2156 *
2185 * void* get_local_storage(void *map, u64 flags) 2157 * void *bpf_get_local_storage(void *map, u64 flags)
2186 * Description 2158 * Description
2187 * Get the pointer to the local storage area. 2159 * Get the pointer to the local storage area.
2188 * The type and the size of the local storage is defined 2160 * The type and the size of the local storage is defined
@@ -2209,6 +2181,24 @@ union bpf_attr {
2209 * Return 2181 * Return
2210 * 0 on success, or a negative error in case of failure. 2182 * 0 on success, or a negative error in case of failure.
2211 * 2183 *
2184 * u64 bpf_skb_ancestor_cgroup_id(struct sk_buff *skb, int ancestor_level)
2185 * Description
2186 * Return id of cgroup v2 that is ancestor of cgroup associated
2187 * with the *skb* at the *ancestor_level*. The root cgroup is at
2188 * *ancestor_level* zero and each step down the hierarchy
2189 * increments the level. If *ancestor_level* == level of cgroup
2190 * associated with *skb*, then return value will be same as that
2191 * of **bpf_skb_cgroup_id**\ ().
2192 *
2193 * The helper is useful to implement policies based on cgroups
2194 * that are upper in hierarchy than immediate cgroup associated
2195 * with *skb*.
2196 *
2197 * The format of returned id and helper limitations are same as in
2198 * **bpf_skb_cgroup_id**\ ().
2199 * Return
2200 * The id is returned or 0 in case the id could not be retrieved.
2201 *
2212 * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) 2202 * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags)
2213 * Description 2203 * Description
2214 * Look for TCP socket matching *tuple*, optionally in a child 2204 * Look for TCP socket matching *tuple*, optionally in a child
@@ -2289,6 +2279,16 @@ union bpf_attr {
2289 * Return 2279 * Return
2290 * 0 on success, or a negative error in case of failure. 2280 * 0 on success, or a negative error in case of failure.
2291 * 2281 *
2282 * int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags)
2283 * Description
2284 * Push an element *value* in *map*. *flags* is one of:
2285 *
2286 * **BPF_EXIST**
2287 * If the queue/stack is full, the oldest element is
2288 * removed to make room for this.
2289 * Return
2290 * 0 on success, or a negative error in case of failure.
2291 *
2292 * int bpf_map_pop_elem(struct bpf_map *map, void *value) 2292 * int bpf_map_pop_elem(struct bpf_map *map, void *value)
2293 * Description 2293 * Description
2294 * Pop an element from *map*. 2294 * Pop an element from *map*.
@@ -2343,29 +2343,94 @@ union bpf_attr {
2343 * Return 2343 * Return
2344 * 0 2344 * 0
2345 * 2345 *
2346 * int bpf_spin_lock(struct bpf_spin_lock *lock)
2347 * Description
2348 * Acquire a spinlock represented by the pointer *lock*, which is
2349 * stored as part of a value of a map. Taking the lock allows to
2350 * safely update the rest of the fields in that value. The
2351 * spinlock can (and must) later be released with a call to
2352 * **bpf_spin_unlock**\ (\ *lock*\ ).
2353 *
2354 * Spinlocks in BPF programs come with a number of restrictions
2355 * and constraints:
2356 *
2357 * * **bpf_spin_lock** objects are only allowed inside maps of
2358 * types **BPF_MAP_TYPE_HASH** and **BPF_MAP_TYPE_ARRAY** (this
2359 * list could be extended in the future).
2360 * * BTF description of the map is mandatory.
2361 * * The BPF program can take ONE lock at a time, since taking two
2362 * or more could cause dead locks.
2363 * * Only one **struct bpf_spin_lock** is allowed per map element.
2364 * * When the lock is taken, calls (either BPF to BPF or helpers)
2365 * are not allowed.
2366 * * The **BPF_LD_ABS** and **BPF_LD_IND** instructions are not
2367 * allowed inside a spinlock-ed region.
2368 * * The BPF program MUST call **bpf_spin_unlock**\ () to release
2369 * the lock, on all execution paths, before it returns.
2370 * * The BPF program can access **struct bpf_spin_lock** only via
2371 * the **bpf_spin_lock**\ () and **bpf_spin_unlock**\ ()
2372 * helpers. Loading or storing data into the **struct
2373 * bpf_spin_lock** *lock*\ **;** field of a map is not allowed.
2374 * * To use the **bpf_spin_lock**\ () helper, the BTF description
2375 * of the map value must be a struct and have **struct
2376 * bpf_spin_lock** *anyname*\ **;** field at the top level.
2377 * Nested lock inside another struct is not allowed.
2378 * * The **struct bpf_spin_lock** *lock* field in a map value must
2379 * be aligned on a multiple of 4 bytes in that value.
2380 * * Syscall with command **BPF_MAP_LOOKUP_ELEM** does not copy
2381 * the **bpf_spin_lock** field to user space.
2382 * * Syscall with command **BPF_MAP_UPDATE_ELEM**, or update from
2383 * a BPF program, do not update the **bpf_spin_lock** field.
2384 * * **bpf_spin_lock** cannot be on the stack or inside a
2385 * networking packet (it can only be inside of a map values).
2386 * * **bpf_spin_lock** is available to root only.
2387 * * Tracing programs and socket filter programs cannot use
2388 * **bpf_spin_lock**\ () due to insufficient preemption checks
2389 * (but this may change in the future).
2390 * * **bpf_spin_lock** is not allowed in inner maps of map-in-map.
2391 * Return
2392 * 0
2393 *
2394 * int bpf_spin_unlock(struct bpf_spin_lock *lock)
2395 * Description
2396 * Release the *lock* previously locked by a call to
2397 * **bpf_spin_lock**\ (\ *lock*\ ).
2398 * Return
2399 * 0
2400 *
2346 * struct bpf_sock *bpf_sk_fullsock(struct bpf_sock *sk) 2401 * struct bpf_sock *bpf_sk_fullsock(struct bpf_sock *sk)
2347 * Description 2402 * Description
2348 * This helper gets a **struct bpf_sock** pointer such 2403 * This helper gets a **struct bpf_sock** pointer such
2349 * that all the fields in bpf_sock can be accessed. 2404 * that all the fields in this **bpf_sock** can be accessed.
2350 * Return 2405 * Return
2351 * A **struct bpf_sock** pointer on success, or NULL in 2406 * A **struct bpf_sock** pointer on success, or **NULL** in
2352 * case of failure. 2407 * case of failure.
2353 * 2408 *
2354 * struct bpf_tcp_sock *bpf_tcp_sock(struct bpf_sock *sk) 2409 * struct bpf_tcp_sock *bpf_tcp_sock(struct bpf_sock *sk)
2355 * Description 2410 * Description
2356 * This helper gets a **struct bpf_tcp_sock** pointer from a 2411 * This helper gets a **struct bpf_tcp_sock** pointer from a
2357 * **struct bpf_sock** pointer. 2412 * **struct bpf_sock** pointer.
2358 *
2359 * Return 2413 * Return
2360 * A **struct bpf_tcp_sock** pointer on success, or NULL in 2414 * A **struct bpf_tcp_sock** pointer on success, or **NULL** in
2361 * case of failure. 2415 * case of failure.
2362 * 2416 *
2363 * int bpf_skb_ecn_set_ce(struct sk_buf *skb) 2417 * int bpf_skb_ecn_set_ce(struct sk_buf *skb)
2364 * Description 2418 * Description
2365 * Sets ECN of IP header to ce (congestion encountered) if 2419 * Set ECN (Explicit Congestion Notification) field of IP header
2366 * current value is ect (ECN capable). Works with IPv6 and IPv4. 2420 * to **CE** (Congestion Encountered) if current value is **ECT**
2367 * Return 2421 * (ECN Capable Transport). Otherwise, do nothing. Works with IPv6
2368 * 1 if set, 0 if not set. 2422 * and IPv4.
2423 * Return
2424 * 1 if the **CE** flag is set (either by the current helper call
2425 * or because it was already present), 0 if it is not set.
2426 *
2427 * struct bpf_sock *bpf_get_listener_sock(struct bpf_sock *sk)
2428 * Description
2429 * Return a **struct bpf_sock** pointer in **TCP_LISTEN** state.
2430 * **bpf_sk_release**\ () is unnecessary and not allowed.
2431 * Return
2432 * A **struct bpf_sock** pointer on success, or **NULL** in
2433 * case of failure.
2369 */ 2434 */
2370#define __BPF_FUNC_MAPPER(FN) \ 2435#define __BPF_FUNC_MAPPER(FN) \
2371 FN(unspec), \ 2436 FN(unspec), \
@@ -2465,7 +2530,8 @@ union bpf_attr {
2465 FN(spin_unlock), \ 2530 FN(spin_unlock), \
2466 FN(sk_fullsock), \ 2531 FN(sk_fullsock), \
2467 FN(tcp_sock), \ 2532 FN(tcp_sock), \
2468 FN(skb_ecn_set_ce), 2533 FN(skb_ecn_set_ce), \
2534 FN(get_listener_sock),
2469 2535
2470/* integer value in 'imm' field of BPF_CALL instruction selects which helper 2536/* integer value in 'imm' field of BPF_CALL instruction selects which helper
2471 * function eBPF program intends to call 2537 * function eBPF program intends to call
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 1b8d8cdd3575..87e3020ac1bc 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -1602,16 +1602,12 @@ static bool btf_equal_int(struct btf_type *t1, struct btf_type *t2)
1602/* Calculate type signature hash of ENUM. */ 1602/* Calculate type signature hash of ENUM. */
1603static __u32 btf_hash_enum(struct btf_type *t) 1603static __u32 btf_hash_enum(struct btf_type *t)
1604{ 1604{
1605 struct btf_enum *member = (struct btf_enum *)(t + 1); 1605 __u32 h;
1606 __u32 vlen = BTF_INFO_VLEN(t->info);
1607 __u32 h = btf_hash_common(t);
1608 int i;
1609 1606
1610 for (i = 0; i < vlen; i++) { 1607 /* don't hash vlen and enum members to support enum fwd resolving */
1611 h = hash_combine(h, member->name_off); 1608 h = hash_combine(0, t->name_off);
1612 h = hash_combine(h, member->val); 1609 h = hash_combine(h, t->info & ~0xffff);
1613 member++; 1610 h = hash_combine(h, t->size);
1614 }
1615 return h; 1611 return h;
1616} 1612}
1617 1613
@@ -1637,6 +1633,22 @@ static bool btf_equal_enum(struct btf_type *t1, struct btf_type *t2)
1637 return true; 1633 return true;
1638} 1634}
1639 1635
1636static inline bool btf_is_enum_fwd(struct btf_type *t)
1637{
1638 return BTF_INFO_KIND(t->info) == BTF_KIND_ENUM &&
1639 BTF_INFO_VLEN(t->info) == 0;
1640}
1641
1642static bool btf_compat_enum(struct btf_type *t1, struct btf_type *t2)
1643{
1644 if (!btf_is_enum_fwd(t1) && !btf_is_enum_fwd(t2))
1645 return btf_equal_enum(t1, t2);
1646 /* ignore vlen when comparing */
1647 return t1->name_off == t2->name_off &&
1648 (t1->info & ~0xffff) == (t2->info & ~0xffff) &&
1649 t1->size == t2->size;
1650}
1651
1640/* 1652/*
1641 * Calculate type signature hash of STRUCT/UNION, ignoring referenced type IDs, 1653 * Calculate type signature hash of STRUCT/UNION, ignoring referenced type IDs,
1642 * as referenced type IDs equivalence is established separately during type 1654 * as referenced type IDs equivalence is established separately during type
@@ -1860,6 +1872,17 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id)
1860 new_id = cand_node->type_id; 1872 new_id = cand_node->type_id;
1861 break; 1873 break;
1862 } 1874 }
1875 if (d->opts.dont_resolve_fwds)
1876 continue;
1877 if (btf_compat_enum(t, cand)) {
1878 if (btf_is_enum_fwd(t)) {
1879 /* resolve fwd to full enum */
1880 new_id = cand_node->type_id;
1881 break;
1882 }
1883 /* resolve canonical enum fwd to full enum */
1884 d->map[cand_node->type_id] = type_id;
1885 }
1863 } 1886 }
1864 break; 1887 break;
1865 1888
@@ -2084,15 +2107,15 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
2084 return fwd_kind == real_kind; 2107 return fwd_kind == real_kind;
2085 } 2108 }
2086 2109
2087 if (cand_type->info != canon_type->info)
2088 return 0;
2089
2090 switch (cand_kind) { 2110 switch (cand_kind) {
2091 case BTF_KIND_INT: 2111 case BTF_KIND_INT:
2092 return btf_equal_int(cand_type, canon_type); 2112 return btf_equal_int(cand_type, canon_type);
2093 2113
2094 case BTF_KIND_ENUM: 2114 case BTF_KIND_ENUM:
2095 return btf_equal_enum(cand_type, canon_type); 2115 if (d->opts.dont_resolve_fwds)
2116 return btf_equal_enum(cand_type, canon_type);
2117 else
2118 return btf_compat_enum(cand_type, canon_type);
2096 2119
2097 case BTF_KIND_FWD: 2120 case BTF_KIND_FWD:
2098 return btf_equal_common(cand_type, canon_type); 2121 return btf_equal_common(cand_type, canon_type);
@@ -2103,6 +2126,8 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
2103 case BTF_KIND_PTR: 2126 case BTF_KIND_PTR:
2104 case BTF_KIND_TYPEDEF: 2127 case BTF_KIND_TYPEDEF:
2105 case BTF_KIND_FUNC: 2128 case BTF_KIND_FUNC:
2129 if (cand_type->info != canon_type->info)
2130 return 0;
2106 return btf_dedup_is_equiv(d, cand_type->type, canon_type->type); 2131 return btf_dedup_is_equiv(d, cand_type->type, canon_type->type);
2107 2132
2108 case BTF_KIND_ARRAY: { 2133 case BTF_KIND_ARRAY: {
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index d5b830d60601..5e977d2688da 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -835,12 +835,19 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
835 obj->efile.maps_shndx = idx; 835 obj->efile.maps_shndx = idx;
836 else if (strcmp(name, BTF_ELF_SEC) == 0) { 836 else if (strcmp(name, BTF_ELF_SEC) == 0) {
837 obj->btf = btf__new(data->d_buf, data->d_size); 837 obj->btf = btf__new(data->d_buf, data->d_size);
838 if (IS_ERR(obj->btf) || btf__load(obj->btf)) { 838 if (IS_ERR(obj->btf)) {
839 pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n", 839 pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
840 BTF_ELF_SEC, PTR_ERR(obj->btf)); 840 BTF_ELF_SEC, PTR_ERR(obj->btf));
841 if (!IS_ERR(obj->btf))
842 btf__free(obj->btf);
843 obj->btf = NULL; 841 obj->btf = NULL;
842 continue;
843 }
844 err = btf__load(obj->btf);
845 if (err) {
846 pr_warning("Error loading %s into kernel: %d. Ignored and continue.\n",
847 BTF_ELF_SEC, err);
848 btf__free(obj->btf);
849 obj->btf = NULL;
850 err = 0;
844 } 851 }
845 } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) { 852 } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) {
846 btf_ext_data = data; 853 btf_ext_data = data;
diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c
index f98ac82c9aea..8d0078b65486 100644
--- a/tools/lib/bpf/xsk.c
+++ b/tools/lib/bpf/xsk.c
@@ -126,8 +126,8 @@ static void xsk_set_umem_config(struct xsk_umem_config *cfg,
126 cfg->frame_headroom = usr_cfg->frame_headroom; 126 cfg->frame_headroom = usr_cfg->frame_headroom;
127} 127}
128 128
129static void xsk_set_xdp_socket_config(struct xsk_socket_config *cfg, 129static int xsk_set_xdp_socket_config(struct xsk_socket_config *cfg,
130 const struct xsk_socket_config *usr_cfg) 130 const struct xsk_socket_config *usr_cfg)
131{ 131{
132 if (!usr_cfg) { 132 if (!usr_cfg) {
133 cfg->rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS; 133 cfg->rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS;
@@ -135,14 +135,19 @@ static void xsk_set_xdp_socket_config(struct xsk_socket_config *cfg,
135 cfg->libbpf_flags = 0; 135 cfg->libbpf_flags = 0;
136 cfg->xdp_flags = 0; 136 cfg->xdp_flags = 0;
137 cfg->bind_flags = 0; 137 cfg->bind_flags = 0;
138 return; 138 return 0;
139 } 139 }
140 140
141 if (usr_cfg->libbpf_flags & ~XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)
142 return -EINVAL;
143
141 cfg->rx_size = usr_cfg->rx_size; 144 cfg->rx_size = usr_cfg->rx_size;
142 cfg->tx_size = usr_cfg->tx_size; 145 cfg->tx_size = usr_cfg->tx_size;
143 cfg->libbpf_flags = usr_cfg->libbpf_flags; 146 cfg->libbpf_flags = usr_cfg->libbpf_flags;
144 cfg->xdp_flags = usr_cfg->xdp_flags; 147 cfg->xdp_flags = usr_cfg->xdp_flags;
145 cfg->bind_flags = usr_cfg->bind_flags; 148 cfg->bind_flags = usr_cfg->bind_flags;
149
150 return 0;
146} 151}
147 152
148int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area, __u64 size, 153int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area, __u64 size,
@@ -557,7 +562,9 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
557 } 562 }
558 strncpy(xsk->ifname, ifname, IFNAMSIZ); 563 strncpy(xsk->ifname, ifname, IFNAMSIZ);
559 564
560 xsk_set_xdp_socket_config(&xsk->config, usr_config); 565 err = xsk_set_xdp_socket_config(&xsk->config, usr_config);
566 if (err)
567 goto out_socket;
561 568
562 if (rx) { 569 if (rx) {
563 err = setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING, 570 err = setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING,
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index c9433a496d54..c81fc350f7ad 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -180,6 +180,8 @@ static struct bpf_sock *(*bpf_sk_fullsock)(struct bpf_sock *sk) =
180 (void *) BPF_FUNC_sk_fullsock; 180 (void *) BPF_FUNC_sk_fullsock;
181static struct bpf_tcp_sock *(*bpf_tcp_sock)(struct bpf_sock *sk) = 181static struct bpf_tcp_sock *(*bpf_tcp_sock)(struct bpf_sock *sk) =
182 (void *) BPF_FUNC_tcp_sock; 182 (void *) BPF_FUNC_tcp_sock;
183static struct bpf_sock *(*bpf_get_listener_sock)(struct bpf_sock *sk) =
184 (void *) BPF_FUNC_get_listener_sock;
183static int (*bpf_skb_ecn_set_ce)(void *ctx) = 185static int (*bpf_skb_ecn_set_ce)(void *ctx) =
184 (void *) BPF_FUNC_skb_ecn_set_ce; 186 (void *) BPF_FUNC_skb_ecn_set_ce;
185 187
diff --git a/tools/testing/selftests/bpf/prog_tests/map_lock.c b/tools/testing/selftests/bpf/prog_tests/map_lock.c
index 90f8a206340a..ee99368c595c 100644
--- a/tools/testing/selftests/bpf/prog_tests/map_lock.c
+++ b/tools/testing/selftests/bpf/prog_tests/map_lock.c
@@ -37,7 +37,7 @@ void test_map_lock(void)
37 const char *file = "./test_map_lock.o"; 37 const char *file = "./test_map_lock.o";
38 int prog_fd, map_fd[2], vars[17] = {}; 38 int prog_fd, map_fd[2], vars[17] = {};
39 pthread_t thread_id[6]; 39 pthread_t thread_id[6];
40 struct bpf_object *obj; 40 struct bpf_object *obj = NULL;
41 int err = 0, key = 0, i; 41 int err = 0, key = 0, i;
42 void *ret; 42 void *ret;
43 43
diff --git a/tools/testing/selftests/bpf/prog_tests/spinlock.c b/tools/testing/selftests/bpf/prog_tests/spinlock.c
index 9a573a9675d7..114ebe6a438e 100644
--- a/tools/testing/selftests/bpf/prog_tests/spinlock.c
+++ b/tools/testing/selftests/bpf/prog_tests/spinlock.c
@@ -5,7 +5,7 @@ void test_spinlock(void)
5{ 5{
6 const char *file = "./test_spin_lock.o"; 6 const char *file = "./test_spin_lock.o";
7 pthread_t thread_id[4]; 7 pthread_t thread_id[4];
8 struct bpf_object *obj; 8 struct bpf_object *obj = NULL;
9 int prog_fd; 9 int prog_fd;
10 int err = 0, i; 10 int err = 0, i;
11 void *ret; 11 void *ret;
diff --git a/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c b/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c
index de1a43e8f610..37328f148538 100644
--- a/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c
+++ b/tools/testing/selftests/bpf/progs/test_sock_fields_kern.c
@@ -8,38 +8,51 @@
8#include "bpf_helpers.h" 8#include "bpf_helpers.h"
9#include "bpf_endian.h" 9#include "bpf_endian.h"
10 10
11enum bpf_array_idx { 11enum bpf_addr_array_idx {
12 SRV_IDX, 12 ADDR_SRV_IDX,
13 CLI_IDX, 13 ADDR_CLI_IDX,
14 __NR_BPF_ARRAY_IDX, 14 __NR_BPF_ADDR_ARRAY_IDX,
15};
16
17enum bpf_result_array_idx {
18 EGRESS_SRV_IDX,
19 EGRESS_CLI_IDX,
20 INGRESS_LISTEN_IDX,
21 __NR_BPF_RESULT_ARRAY_IDX,
22};
23
24enum bpf_linum_array_idx {
25 EGRESS_LINUM_IDX,
26 INGRESS_LINUM_IDX,
27 __NR_BPF_LINUM_ARRAY_IDX,
15}; 28};
16 29
17struct bpf_map_def SEC("maps") addr_map = { 30struct bpf_map_def SEC("maps") addr_map = {
18 .type = BPF_MAP_TYPE_ARRAY, 31 .type = BPF_MAP_TYPE_ARRAY,
19 .key_size = sizeof(__u32), 32 .key_size = sizeof(__u32),
20 .value_size = sizeof(struct sockaddr_in6), 33 .value_size = sizeof(struct sockaddr_in6),
21 .max_entries = __NR_BPF_ARRAY_IDX, 34 .max_entries = __NR_BPF_ADDR_ARRAY_IDX,
22}; 35};
23 36
24struct bpf_map_def SEC("maps") sock_result_map = { 37struct bpf_map_def SEC("maps") sock_result_map = {
25 .type = BPF_MAP_TYPE_ARRAY, 38 .type = BPF_MAP_TYPE_ARRAY,
26 .key_size = sizeof(__u32), 39 .key_size = sizeof(__u32),
27 .value_size = sizeof(struct bpf_sock), 40 .value_size = sizeof(struct bpf_sock),
28 .max_entries = __NR_BPF_ARRAY_IDX, 41 .max_entries = __NR_BPF_RESULT_ARRAY_IDX,
29}; 42};
30 43
31struct bpf_map_def SEC("maps") tcp_sock_result_map = { 44struct bpf_map_def SEC("maps") tcp_sock_result_map = {
32 .type = BPF_MAP_TYPE_ARRAY, 45 .type = BPF_MAP_TYPE_ARRAY,
33 .key_size = sizeof(__u32), 46 .key_size = sizeof(__u32),
34 .value_size = sizeof(struct bpf_tcp_sock), 47 .value_size = sizeof(struct bpf_tcp_sock),
35 .max_entries = __NR_BPF_ARRAY_IDX, 48 .max_entries = __NR_BPF_RESULT_ARRAY_IDX,
36}; 49};
37 50
38struct bpf_map_def SEC("maps") linum_map = { 51struct bpf_map_def SEC("maps") linum_map = {
39 .type = BPF_MAP_TYPE_ARRAY, 52 .type = BPF_MAP_TYPE_ARRAY,
40 .key_size = sizeof(__u32), 53 .key_size = sizeof(__u32),
41 .value_size = sizeof(__u32), 54 .value_size = sizeof(__u32),
42 .max_entries = 1, 55 .max_entries = __NR_BPF_LINUM_ARRAY_IDX,
43}; 56};
44 57
45static bool is_loopback6(__u32 *a6) 58static bool is_loopback6(__u32 *a6)
@@ -100,18 +113,20 @@ static void tpcpy(struct bpf_tcp_sock *dst,
100 113
101#define RETURN { \ 114#define RETURN { \
102 linum = __LINE__; \ 115 linum = __LINE__; \
103 bpf_map_update_elem(&linum_map, &idx0, &linum, 0); \ 116 bpf_map_update_elem(&linum_map, &linum_idx, &linum, 0); \
104 return 1; \ 117 return 1; \
105} 118}
106 119
107SEC("cgroup_skb/egress") 120SEC("cgroup_skb/egress")
108int read_sock_fields(struct __sk_buff *skb) 121int egress_read_sock_fields(struct __sk_buff *skb)
109{ 122{
110 __u32 srv_idx = SRV_IDX, cli_idx = CLI_IDX, idx; 123 __u32 srv_idx = ADDR_SRV_IDX, cli_idx = ADDR_CLI_IDX, result_idx;
111 struct sockaddr_in6 *srv_sa6, *cli_sa6; 124 struct sockaddr_in6 *srv_sa6, *cli_sa6;
112 struct bpf_tcp_sock *tp, *tp_ret; 125 struct bpf_tcp_sock *tp, *tp_ret;
113 struct bpf_sock *sk, *sk_ret; 126 struct bpf_sock *sk, *sk_ret;
114 __u32 linum, idx0 = 0; 127 __u32 linum, linum_idx;
128
129 linum_idx = EGRESS_LINUM_IDX;
115 130
116 sk = skb->sk; 131 sk = skb->sk;
117 if (!sk || sk->state == 10) 132 if (!sk || sk->state == 10)
@@ -132,14 +147,55 @@ int read_sock_fields(struct __sk_buff *skb)
132 RETURN; 147 RETURN;
133 148
134 if (sk->src_port == bpf_ntohs(srv_sa6->sin6_port)) 149 if (sk->src_port == bpf_ntohs(srv_sa6->sin6_port))
135 idx = srv_idx; 150 result_idx = EGRESS_SRV_IDX;
136 else if (sk->src_port == bpf_ntohs(cli_sa6->sin6_port)) 151 else if (sk->src_port == bpf_ntohs(cli_sa6->sin6_port))
137 idx = cli_idx; 152 result_idx = EGRESS_CLI_IDX;
138 else 153 else
139 RETURN; 154 RETURN;
140 155
141 sk_ret = bpf_map_lookup_elem(&sock_result_map, &idx); 156 sk_ret = bpf_map_lookup_elem(&sock_result_map, &result_idx);
142 tp_ret = bpf_map_lookup_elem(&tcp_sock_result_map, &idx); 157 tp_ret = bpf_map_lookup_elem(&tcp_sock_result_map, &result_idx);
158 if (!sk_ret || !tp_ret)
159 RETURN;
160
161 skcpy(sk_ret, sk);
162 tpcpy(tp_ret, tp);
163
164 RETURN;
165}
166
167SEC("cgroup_skb/ingress")
168int ingress_read_sock_fields(struct __sk_buff *skb)
169{
170 __u32 srv_idx = ADDR_SRV_IDX, result_idx = INGRESS_LISTEN_IDX;
171 struct bpf_tcp_sock *tp, *tp_ret;
172 struct bpf_sock *sk, *sk_ret;
173 struct sockaddr_in6 *srv_sa6;
174 __u32 linum, linum_idx;
175
176 linum_idx = INGRESS_LINUM_IDX;
177
178 sk = skb->sk;
179 if (!sk || sk->family != AF_INET6 || !is_loopback6(sk->src_ip6))
180 RETURN;
181
182 srv_sa6 = bpf_map_lookup_elem(&addr_map, &srv_idx);
183 if (!srv_sa6 || sk->src_port != bpf_ntohs(srv_sa6->sin6_port))
184 RETURN;
185
186 if (sk->state != 10 && sk->state != 12)
187 RETURN;
188
189 sk = bpf_get_listener_sock(sk);
190 if (!sk)
191 RETURN;
192
193 tp = bpf_tcp_sock(sk);
194 if (!tp)
195 RETURN;
196
197 sk_ret = bpf_map_lookup_elem(&sock_result_map, &result_idx);
198 tp_ret = bpf_map_lookup_elem(&tcp_sock_result_map, &result_idx);
143 if (!sk_ret || !tp_ret) 199 if (!sk_ret || !tp_ret)
144 RETURN; 200 RETURN;
145 201
diff --git a/tools/testing/selftests/bpf/test_btf.c b/tools/testing/selftests/bpf/test_btf.c
index 38797aa627a7..23e3b314ca60 100644
--- a/tools/testing/selftests/bpf/test_btf.c
+++ b/tools/testing/selftests/bpf/test_btf.c
@@ -5874,6 +5874,50 @@ const struct btf_dedup_test dedup_tests[] = {
5874 .dont_resolve_fwds = false, 5874 .dont_resolve_fwds = false,
5875 }, 5875 },
5876}, 5876},
5877{
5878 .descr = "dedup: enum fwd resolution",
5879 .input = {
5880 .raw_types = {
5881 /* [1] fwd enum 'e1' before full enum */
5882 BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 4),
5883 /* [2] full enum 'e1' after fwd */
5884 BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
5885 BTF_ENUM_ENC(NAME_NTH(2), 123),
5886 /* [3] full enum 'e2' before fwd */
5887 BTF_TYPE_ENC(NAME_NTH(3), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
5888 BTF_ENUM_ENC(NAME_NTH(4), 456),
5889 /* [4] fwd enum 'e2' after full enum */
5890 BTF_TYPE_ENC(NAME_NTH(3), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 4),
5891 /* [5] incompatible fwd enum with different size */
5892 BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 1),
5893 /* [6] incompatible full enum with different value */
5894 BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
5895 BTF_ENUM_ENC(NAME_NTH(2), 321),
5896 BTF_END_RAW,
5897 },
5898 BTF_STR_SEC("\0e1\0e1_val\0e2\0e2_val"),
5899 },
5900 .expect = {
5901 .raw_types = {
5902 /* [1] full enum 'e1' */
5903 BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
5904 BTF_ENUM_ENC(NAME_NTH(2), 123),
5905 /* [2] full enum 'e2' */
5906 BTF_TYPE_ENC(NAME_NTH(3), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
5907 BTF_ENUM_ENC(NAME_NTH(4), 456),
5908 /* [3] incompatible fwd enum with different size */
5909 BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 1),
5910 /* [4] incompatible full enum with different value */
5911 BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
5912 BTF_ENUM_ENC(NAME_NTH(2), 321),
5913 BTF_END_RAW,
5914 },
5915 BTF_STR_SEC("\0e1\0e1_val\0e2\0e2_val"),
5916 },
5917 .opts = {
5918 .dont_resolve_fwds = false,
5919 },
5920},
5877 5921
5878}; 5922};
5879 5923
diff --git a/tools/testing/selftests/bpf/test_sock_fields.c b/tools/testing/selftests/bpf/test_sock_fields.c
index bc8943938bf5..dcae7f664dce 100644
--- a/tools/testing/selftests/bpf/test_sock_fields.c
+++ b/tools/testing/selftests/bpf/test_sock_fields.c
@@ -16,10 +16,23 @@
16#include "cgroup_helpers.h" 16#include "cgroup_helpers.h"
17#include "bpf_rlimit.h" 17#include "bpf_rlimit.h"
18 18
19enum bpf_array_idx { 19enum bpf_addr_array_idx {
20 SRV_IDX, 20 ADDR_SRV_IDX,
21 CLI_IDX, 21 ADDR_CLI_IDX,
22 __NR_BPF_ARRAY_IDX, 22 __NR_BPF_ADDR_ARRAY_IDX,
23};
24
25enum bpf_result_array_idx {
26 EGRESS_SRV_IDX,
27 EGRESS_CLI_IDX,
28 INGRESS_LISTEN_IDX,
29 __NR_BPF_RESULT_ARRAY_IDX,
30};
31
32enum bpf_linum_array_idx {
33 EGRESS_LINUM_IDX,
34 INGRESS_LINUM_IDX,
35 __NR_BPF_LINUM_ARRAY_IDX,
23}; 36};
24 37
25#define CHECK(condition, tag, format...) ({ \ 38#define CHECK(condition, tag, format...) ({ \
@@ -41,8 +54,16 @@ static int linum_map_fd;
41static int addr_map_fd; 54static int addr_map_fd;
42static int tp_map_fd; 55static int tp_map_fd;
43static int sk_map_fd; 56static int sk_map_fd;
44static __u32 srv_idx = SRV_IDX; 57
45static __u32 cli_idx = CLI_IDX; 58static __u32 addr_srv_idx = ADDR_SRV_IDX;
59static __u32 addr_cli_idx = ADDR_CLI_IDX;
60
61static __u32 egress_srv_idx = EGRESS_SRV_IDX;
62static __u32 egress_cli_idx = EGRESS_CLI_IDX;
63static __u32 ingress_listen_idx = INGRESS_LISTEN_IDX;
64
65static __u32 egress_linum_idx = EGRESS_LINUM_IDX;
66static __u32 ingress_linum_idx = INGRESS_LINUM_IDX;
46 67
47static void init_loopback6(struct sockaddr_in6 *sa6) 68static void init_loopback6(struct sockaddr_in6 *sa6)
48{ 69{
@@ -93,29 +114,46 @@ static void print_tp(const struct bpf_tcp_sock *tp)
93 114
94static void check_result(void) 115static void check_result(void)
95{ 116{
96 struct bpf_tcp_sock srv_tp, cli_tp; 117 struct bpf_tcp_sock srv_tp, cli_tp, listen_tp;
97 struct bpf_sock srv_sk, cli_sk; 118 struct bpf_sock srv_sk, cli_sk, listen_sk;
98 __u32 linum, idx0 = 0; 119 __u32 ingress_linum, egress_linum;
99 int err; 120 int err;
100 121
101 err = bpf_map_lookup_elem(linum_map_fd, &idx0, &linum); 122 err = bpf_map_lookup_elem(linum_map_fd, &egress_linum_idx,
123 &egress_linum);
102 CHECK(err == -1, "bpf_map_lookup_elem(linum_map_fd)", 124 CHECK(err == -1, "bpf_map_lookup_elem(linum_map_fd)",
103 "err:%d errno:%d", err, errno); 125 "err:%d errno:%d", err, errno);
104 126
105 err = bpf_map_lookup_elem(sk_map_fd, &srv_idx, &srv_sk); 127 err = bpf_map_lookup_elem(linum_map_fd, &ingress_linum_idx,
106 CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &srv_idx)", 128 &ingress_linum);
129 CHECK(err == -1, "bpf_map_lookup_elem(linum_map_fd)",
130 "err:%d errno:%d", err, errno);
131
132 err = bpf_map_lookup_elem(sk_map_fd, &egress_srv_idx, &srv_sk);
133 CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &egress_srv_idx)",
134 "err:%d errno:%d", err, errno);
135 err = bpf_map_lookup_elem(tp_map_fd, &egress_srv_idx, &srv_tp);
136 CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &egress_srv_idx)",
137 "err:%d errno:%d", err, errno);
138
139 err = bpf_map_lookup_elem(sk_map_fd, &egress_cli_idx, &cli_sk);
140 CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &egress_cli_idx)",
107 "err:%d errno:%d", err, errno); 141 "err:%d errno:%d", err, errno);
108 err = bpf_map_lookup_elem(tp_map_fd, &srv_idx, &srv_tp); 142 err = bpf_map_lookup_elem(tp_map_fd, &egress_cli_idx, &cli_tp);
109 CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &srv_idx)", 143 CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &egress_cli_idx)",
110 "err:%d errno:%d", err, errno); 144 "err:%d errno:%d", err, errno);
111 145
112 err = bpf_map_lookup_elem(sk_map_fd, &cli_idx, &cli_sk); 146 err = bpf_map_lookup_elem(sk_map_fd, &ingress_listen_idx, &listen_sk);
113 CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &cli_idx)", 147 CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &ingress_listen_idx)",
114 "err:%d errno:%d", err, errno); 148 "err:%d errno:%d", err, errno);
115 err = bpf_map_lookup_elem(tp_map_fd, &cli_idx, &cli_tp); 149 err = bpf_map_lookup_elem(tp_map_fd, &ingress_listen_idx, &listen_tp);
116 CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &cli_idx)", 150 CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &ingress_listen_idx)",
117 "err:%d errno:%d", err, errno); 151 "err:%d errno:%d", err, errno);
118 152
153 printf("listen_sk: ");
154 print_sk(&listen_sk);
155 printf("\n");
156
119 printf("srv_sk: "); 157 printf("srv_sk: ");
120 print_sk(&srv_sk); 158 print_sk(&srv_sk);
121 printf("\n"); 159 printf("\n");
@@ -124,6 +162,10 @@ static void check_result(void)
124 print_sk(&cli_sk); 162 print_sk(&cli_sk);
125 printf("\n"); 163 printf("\n");
126 164
165 printf("listen_tp: ");
166 print_tp(&listen_tp);
167 printf("\n");
168
127 printf("srv_tp: "); 169 printf("srv_tp: ");
128 print_tp(&srv_tp); 170 print_tp(&srv_tp);
129 printf("\n"); 171 printf("\n");
@@ -132,6 +174,19 @@ static void check_result(void)
132 print_tp(&cli_tp); 174 print_tp(&cli_tp);
133 printf("\n"); 175 printf("\n");
134 176
177 CHECK(listen_sk.state != 10 ||
178 listen_sk.family != AF_INET6 ||
179 listen_sk.protocol != IPPROTO_TCP ||
180 memcmp(listen_sk.src_ip6, &in6addr_loopback,
181 sizeof(listen_sk.src_ip6)) ||
182 listen_sk.dst_ip6[0] || listen_sk.dst_ip6[1] ||
183 listen_sk.dst_ip6[2] || listen_sk.dst_ip6[3] ||
184 listen_sk.src_port != ntohs(srv_sa6.sin6_port) ||
185 listen_sk.dst_port,
186 "Unexpected listen_sk",
187 "Check listen_sk output. ingress_linum:%u",
188 ingress_linum);
189
135 CHECK(srv_sk.state == 10 || 190 CHECK(srv_sk.state == 10 ||
136 !srv_sk.state || 191 !srv_sk.state ||
137 srv_sk.family != AF_INET6 || 192 srv_sk.family != AF_INET6 ||
@@ -142,7 +197,8 @@ static void check_result(void)
142 sizeof(srv_sk.dst_ip6)) || 197 sizeof(srv_sk.dst_ip6)) ||
143 srv_sk.src_port != ntohs(srv_sa6.sin6_port) || 198 srv_sk.src_port != ntohs(srv_sa6.sin6_port) ||
144 srv_sk.dst_port != cli_sa6.sin6_port, 199 srv_sk.dst_port != cli_sa6.sin6_port,
145 "Unexpected srv_sk", "Check srv_sk output. linum:%u", linum); 200 "Unexpected srv_sk", "Check srv_sk output. egress_linum:%u",
201 egress_linum);
146 202
147 CHECK(cli_sk.state == 10 || 203 CHECK(cli_sk.state == 10 ||
148 !cli_sk.state || 204 !cli_sk.state ||
@@ -154,21 +210,31 @@ static void check_result(void)
154 sizeof(cli_sk.dst_ip6)) || 210 sizeof(cli_sk.dst_ip6)) ||
155 cli_sk.src_port != ntohs(cli_sa6.sin6_port) || 211 cli_sk.src_port != ntohs(cli_sa6.sin6_port) ||
156 cli_sk.dst_port != srv_sa6.sin6_port, 212 cli_sk.dst_port != srv_sa6.sin6_port,
157 "Unexpected cli_sk", "Check cli_sk output. linum:%u", linum); 213 "Unexpected cli_sk", "Check cli_sk output. egress_linum:%u",
214 egress_linum);
215
216 CHECK(listen_tp.data_segs_out ||
217 listen_tp.data_segs_in ||
218 listen_tp.total_retrans ||
219 listen_tp.bytes_acked,
220 "Unexpected listen_tp", "Check listen_tp output. ingress_linum:%u",
221 ingress_linum);
158 222
159 CHECK(srv_tp.data_segs_out != 1 || 223 CHECK(srv_tp.data_segs_out != 1 ||
160 srv_tp.data_segs_in || 224 srv_tp.data_segs_in ||
161 srv_tp.snd_cwnd != 10 || 225 srv_tp.snd_cwnd != 10 ||
162 srv_tp.total_retrans || 226 srv_tp.total_retrans ||
163 srv_tp.bytes_acked != DATA_LEN, 227 srv_tp.bytes_acked != DATA_LEN,
164 "Unexpected srv_tp", "Check srv_tp output. linum:%u", linum); 228 "Unexpected srv_tp", "Check srv_tp output. egress_linum:%u",
229 egress_linum);
165 230
166 CHECK(cli_tp.data_segs_out || 231 CHECK(cli_tp.data_segs_out ||
167 cli_tp.data_segs_in != 1 || 232 cli_tp.data_segs_in != 1 ||
168 cli_tp.snd_cwnd != 10 || 233 cli_tp.snd_cwnd != 10 ||
169 cli_tp.total_retrans || 234 cli_tp.total_retrans ||
170 cli_tp.bytes_received != DATA_LEN, 235 cli_tp.bytes_received != DATA_LEN,
171 "Unexpected cli_tp", "Check cli_tp output. linum:%u", linum); 236 "Unexpected cli_tp", "Check cli_tp output. egress_linum:%u",
237 egress_linum);
172} 238}
173 239
174static void test(void) 240static void test(void)
@@ -211,10 +277,10 @@ static void test(void)
211 err, errno); 277 err, errno);
212 278
213 /* Update addr_map with srv_sa6 and cli_sa6 */ 279 /* Update addr_map with srv_sa6 and cli_sa6 */
214 err = bpf_map_update_elem(addr_map_fd, &srv_idx, &srv_sa6, 0); 280 err = bpf_map_update_elem(addr_map_fd, &addr_srv_idx, &srv_sa6, 0);
215 CHECK(err, "map_update", "err:%d errno:%d", err, errno); 281 CHECK(err, "map_update", "err:%d errno:%d", err, errno);
216 282
217 err = bpf_map_update_elem(addr_map_fd, &cli_idx, &cli_sa6, 0); 283 err = bpf_map_update_elem(addr_map_fd, &addr_cli_idx, &cli_sa6, 0);
218 CHECK(err, "map_update", "err:%d errno:%d", err, errno); 284 CHECK(err, "map_update", "err:%d errno:%d", err, errno);
219 285
220 /* Connect from cli_sa6 to srv_sa6 */ 286 /* Connect from cli_sa6 to srv_sa6 */
@@ -273,9 +339,9 @@ int main(int argc, char **argv)
273 struct bpf_prog_load_attr attr = { 339 struct bpf_prog_load_attr attr = {
274 .file = "test_sock_fields_kern.o", 340 .file = "test_sock_fields_kern.o",
275 .prog_type = BPF_PROG_TYPE_CGROUP_SKB, 341 .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
276 .expected_attach_type = BPF_CGROUP_INET_EGRESS,
277 }; 342 };
278 int cgroup_fd, prog_fd, err; 343 int cgroup_fd, egress_fd, ingress_fd, err;
344 struct bpf_program *ingress_prog;
279 struct bpf_object *obj; 345 struct bpf_object *obj;
280 struct bpf_map *map; 346 struct bpf_map *map;
281 347
@@ -293,12 +359,24 @@ int main(int argc, char **argv)
293 err = join_cgroup(TEST_CGROUP); 359 err = join_cgroup(TEST_CGROUP);
294 CHECK(err, "join_cgroup", "err:%d errno:%d", err, errno); 360 CHECK(err, "join_cgroup", "err:%d errno:%d", err, errno);
295 361
296 err = bpf_prog_load_xattr(&attr, &obj, &prog_fd); 362 err = bpf_prog_load_xattr(&attr, &obj, &egress_fd);
297 CHECK(err, "bpf_prog_load_xattr()", "err:%d", err); 363 CHECK(err, "bpf_prog_load_xattr()", "err:%d", err);
298 364
299 err = bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_INET_EGRESS, 0); 365 ingress_prog = bpf_object__find_program_by_title(obj,
366 "cgroup_skb/ingress");
367 CHECK(!ingress_prog,
368 "bpf_object__find_program_by_title(cgroup_skb/ingress)",
369 "not found");
370 ingress_fd = bpf_program__fd(ingress_prog);
371
372 err = bpf_prog_attach(egress_fd, cgroup_fd, BPF_CGROUP_INET_EGRESS, 0);
300 CHECK(err == -1, "bpf_prog_attach(CPF_CGROUP_INET_EGRESS)", 373 CHECK(err == -1, "bpf_prog_attach(CPF_CGROUP_INET_EGRESS)",
301 "err:%d errno%d", err, errno); 374 "err:%d errno%d", err, errno);
375
376 err = bpf_prog_attach(ingress_fd, cgroup_fd,
377 BPF_CGROUP_INET_INGRESS, 0);
378 CHECK(err == -1, "bpf_prog_attach(CPF_CGROUP_INET_INGRESS)",
379 "err:%d errno%d", err, errno);
302 close(cgroup_fd); 380 close(cgroup_fd);
303 381
304 map = bpf_object__find_map_by_name(obj, "addr_map"); 382 map = bpf_object__find_map_by_name(obj, "addr_map");
diff --git a/tools/testing/selftests/bpf/verifier/ref_tracking.c b/tools/testing/selftests/bpf/verifier/ref_tracking.c
index 3ed3593bd8b6..923f2110072d 100644
--- a/tools/testing/selftests/bpf/verifier/ref_tracking.c
+++ b/tools/testing/selftests/bpf/verifier/ref_tracking.c
@@ -605,3 +605,171 @@
605 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 605 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
606 .result = ACCEPT, 606 .result = ACCEPT,
607}, 607},
608{
609 "reference tracking: use ptr from bpf_tcp_sock() after release",
610 .insns = {
611 BPF_SK_LOOKUP,
612 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
613 BPF_EXIT_INSN(),
614 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
615 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
616 BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
617 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
618 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
619 BPF_EMIT_CALL(BPF_FUNC_sk_release),
620 BPF_EXIT_INSN(),
621 BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
622 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
623 BPF_EMIT_CALL(BPF_FUNC_sk_release),
624 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_tcp_sock, snd_cwnd)),
625 BPF_EXIT_INSN(),
626 },
627 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
628 .result = REJECT,
629 .errstr = "invalid mem access",
630},
631{
632 "reference tracking: use ptr from bpf_sk_fullsock() after release",
633 .insns = {
634 BPF_SK_LOOKUP,
635 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
636 BPF_EXIT_INSN(),
637 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
638 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
639 BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
640 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
641 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
642 BPF_EMIT_CALL(BPF_FUNC_sk_release),
643 BPF_EXIT_INSN(),
644 BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
645 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
646 BPF_EMIT_CALL(BPF_FUNC_sk_release),
647 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_sock, type)),
648 BPF_EXIT_INSN(),
649 },
650 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
651 .result = REJECT,
652 .errstr = "invalid mem access",
653},
654{
655 "reference tracking: use ptr from bpf_sk_fullsock(tp) after release",
656 .insns = {
657 BPF_SK_LOOKUP,
658 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
659 BPF_EXIT_INSN(),
660 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
661 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
662 BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
663 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
664 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
665 BPF_EMIT_CALL(BPF_FUNC_sk_release),
666 BPF_EXIT_INSN(),
667 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
668 BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
669 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
670 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
671 BPF_EMIT_CALL(BPF_FUNC_sk_release),
672 BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 1),
673 BPF_EXIT_INSN(),
674 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
675 BPF_EXIT_INSN(),
676 },
677 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
678 .result = REJECT,
679 .errstr = "invalid mem access",
680},
681{
682 "reference tracking: use sk after bpf_sk_release(tp)",
683 .insns = {
684 BPF_SK_LOOKUP,
685 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
686 BPF_EXIT_INSN(),
687 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
688 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
689 BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
690 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
691 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
692 BPF_EMIT_CALL(BPF_FUNC_sk_release),
693 BPF_EXIT_INSN(),
694 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
695 BPF_EMIT_CALL(BPF_FUNC_sk_release),
696 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
697 BPF_EXIT_INSN(),
698 },
699 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
700 .result = REJECT,
701 .errstr = "invalid mem access",
702},
703{
704 "reference tracking: use ptr from bpf_get_listener_sock() after bpf_sk_release(sk)",
705 .insns = {
706 BPF_SK_LOOKUP,
707 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
708 BPF_EXIT_INSN(),
709 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
710 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
711 BPF_EMIT_CALL(BPF_FUNC_get_listener_sock),
712 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
713 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
714 BPF_EMIT_CALL(BPF_FUNC_sk_release),
715 BPF_EXIT_INSN(),
716 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
717 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
718 BPF_EMIT_CALL(BPF_FUNC_sk_release),
719 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, src_port)),
720 BPF_EXIT_INSN(),
721 },
722 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
723 .result = ACCEPT,
724},
725{
726 "reference tracking: bpf_sk_release(listen_sk)",
727 .insns = {
728 BPF_SK_LOOKUP,
729 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
730 BPF_EXIT_INSN(),
731 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
732 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
733 BPF_EMIT_CALL(BPF_FUNC_get_listener_sock),
734 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
735 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
736 BPF_EMIT_CALL(BPF_FUNC_sk_release),
737 BPF_EXIT_INSN(),
738 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
739 BPF_EMIT_CALL(BPF_FUNC_sk_release),
740 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
741 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
742 BPF_EMIT_CALL(BPF_FUNC_sk_release),
743 BPF_EXIT_INSN(),
744 },
745 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
746 .result = REJECT,
747 .errstr = "reference has not been acquired before",
748},
749{
750 /* !bpf_sk_fullsock(sk) is checked but !bpf_tcp_sock(sk) is not checked */
751 "reference tracking: tp->snd_cwnd after bpf_sk_fullsock(sk) and bpf_tcp_sock(sk)",
752 .insns = {
753 BPF_SK_LOOKUP,
754 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
755 BPF_EXIT_INSN(),
756 BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
757 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
758 BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
759 BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
760 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
761 BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
762 BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
763 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 3),
764 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
765 BPF_EMIT_CALL(BPF_FUNC_sk_release),
766 BPF_EXIT_INSN(),
767 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_8, offsetof(struct bpf_tcp_sock, snd_cwnd)),
768 BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
769 BPF_EMIT_CALL(BPF_FUNC_sk_release),
770 BPF_EXIT_INSN(),
771 },
772 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
773 .result = REJECT,
774 .errstr = "invalid mem access",
775},
diff --git a/tools/testing/selftests/bpf/verifier/sock.c b/tools/testing/selftests/bpf/verifier/sock.c
index 0ddfdf76aba5..416436231fab 100644
--- a/tools/testing/selftests/bpf/verifier/sock.c
+++ b/tools/testing/selftests/bpf/verifier/sock.c
@@ -342,7 +342,7 @@
342 }, 342 },
343 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 343 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
344 .result = REJECT, 344 .result = REJECT,
345 .errstr = "type=sock_common expected=sock", 345 .errstr = "reference has not been acquired before",
346}, 346},
347{ 347{
348 "bpf_sk_release(bpf_sk_fullsock(skb->sk))", 348 "bpf_sk_release(bpf_sk_fullsock(skb->sk))",
@@ -380,5 +380,5 @@
380 }, 380 },
381 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 381 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
382 .result = REJECT, 382 .result = REJECT,
383 .errstr = "type=tcp_sock expected=sock", 383 .errstr = "reference has not been acquired before",
384}, 384},