mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 19:13:47 +02:00
Merge branch 'Add cgroup sockaddr hooks for unix sockets'
Daan De Meyer says: ==================== Changes since v10: * Removed extra check from bpf_sock_addr_set_sun_path() again in favor of calling unix_validate_addr() everywhere in af_unix.c before calling the hooks. Changes since v9: * Renamed bpf_sock_addr_set_unix_addr() to bpf_sock_addr_set_sun_path() and rennamed arguments to match the new name. * Added an extra check to bpf_sock_addr_set_sun_path() to disallow changing the address of an unnamed unix socket. * Removed unnecessary NULL check on uaddrlen in __cgroup_bpf_run_filter_sock_addr(). Changes since v8: * Added missing test programs to last patch Changes since v7: * Fixed formatting nit in comment * Renamed from cgroup/connectun to cgroup/connect_unix (and similar for all other hooks) Changes since v6: * Actually removed bpf_bind() helper for AF_UNIX hooks. * Fixed merge conflict * Updated comment to mention uaddrlen is read-only for AF_INET[6] * Removed unnecessary forward declaration of struct sock_addr_test * Removed unused BPF_CGROUP_RUN_PROG_UNIX_CONNECT() * Fixed formatting nit reported by checkpatch * Added more information to commit message about recvmsg() on connected socket Changes since v5: * Fixed kernel version in bpftool documentation (6.3 => 6.7). * Added connection mode socket recvmsg() test. * Removed bpf_bind() helper for AF_UNIX hooks. * Added missing getpeernameun and getsocknameun BPF test programs. * Added note for bind() test being unused currently. Changes since v4: * Dropped support for intercepting bind() as when using bind() with unix sockets and a pathname sockaddr, bind() will create an inode in the filesystem that needs to be cleaned up. If the address is rewritten, users might try to clean up the wrong file and leak the actual socket file in the filesystem. * Changed bpf_sock_addr_set_unix_addr() to use BTF_KFUNC_HOOK_CGROUP_SKB instead of BTF_KFUNC_HOOK_COMMON. * Removed unix socket related changes from BPF_CGROUP_PRE_CONNECT_ENABLED() as unix sockets do not support pre-connect. * Added tests for getpeernameun and getsocknameun hooks. * We now disallow an empty sockaddr in bpf_sock_addr_set_unix_addr() similar to unix_validate_addr(). * Removed unnecessary cgroup_bpf_enabled() checks * Removed unnecessary error checks Changes since v3: * Renamed bpf_sock_addr_set_addr() to bpf_sock_addr_set_unix_addr() and made it only operate on AF_UNIX sockaddrs. This is because for the other families, users usually want to configure more than just the address so a generic interface will not fit the bill here. e.g. for AF_INET and AF_INET6, users would generally also want to be able to configure the port which the current interface doesn't support. So we expose an AF_UNIX specific function instead. * Made the tests in the new sock addr tests more generic (similar to test_sock_addr.c), this should make it easier to migrate the other sock addr tests in the future. * Removed the new kfunc hook and attached to BTF_KFUNC_HOOK_COMMON instead * Set uaddrlen to 0 when the family is AF_UNSPEC * Pass in the addrlen to the hook from IPv6 code * Fixed mount directory mkdir() to ignore EEXIST Changes since v2: * Configuring the sock addr is now done via a new kfunc bpf_sock_addr_set() * The addrlen is exposed as u32 in bpf_sock_addr_kern * Selftests are updated to use the new kfunc * Selftests are now added as a new sock_addr test in prog_tests/ * Added BTF_KFUNC_HOOK_SOCK_ADDR for BPF_PROG_TYPE_CGROUP_SOCK_ADDR * __cgroup_bpf_run_filter_sock_addr() now returns the modified addrlen Changes since v1: * Split into multiple patches instead of one single patch * Added unix support for all socket address hooks instead of only connect() * Switched approach to expose the socket address length to the bpf hook instead of recalculating the socket address length in kernelspace to properly support abstract unix socket addresses * Modified socket address hook tests to calculate the socket address length once and pass it around everywhere instead of recalculating the actual unix socket address length on demand. * Added some missing section name tests for getpeername()/getsockname() This patch series extends the cgroup sockaddr hooks to include support for unix sockets. To add support for unix sockets, struct bpf_sock_addr_kern is extended to expose the socket address length to the bpf program. Along with that, a new kfunc bpf_sock_addr_set_unix_addr() is added to safely allow modifying an AF_UNIX sockaddr from bpf programs. I intend to use these new hooks in systemd to reimplement the LogNamespace= feature, which allows running multiple instances of systemd-journald to process the logs of different services. systemd-journald also processes syslog messages, so currently, using log namespaces means all services running in the same log namespace have to live in the same private mount namespace so that systemd can mount the journal namespace's associated syslog socket over /dev/log to properly direct syslog messages from all services running in that log namespace to the correct systemd-journald instance. We want to relax this requirement so that processes running in disjoint mount namespaces can still run in the same log namespace. To achieve this, we can use these new hooks to rewrite the socket address of any connect(), sendto(), ... syscalls to /dev/log to the socket address of the journal namespace's syslog socket instead, which will transparently do the redirection without requiring use of a mount namespace and mounting over /dev/log. Aside from the above usecase, these hooks can more generally be used to transparently redirect unix sockets to different addresses as required by services. ==================== Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
This commit is contained in:
commit
d2dc885b8c
|
|
@ -56,6 +56,16 @@ described in more detail in the footnotes.
|
|||
| | ``BPF_CGROUP_UDP6_RECVMSG`` | ``cgroup/recvmsg6`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UDP6_SENDMSG`` | ``cgroup/sendmsg6`` | |
|
||||
| +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UNIX_CONNECT`` | ``cgroup/connect_unix`` | |
|
||||
| +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UNIX_SENDMSG`` | ``cgroup/sendmsg_unix`` | |
|
||||
| +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UNIX_RECVMSG`` | ``cgroup/recvmsg_unix`` | |
|
||||
| +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UNIX_GETPEERNAME`` | ``cgroup/getpeername_unix`` | |
|
||||
| +----------------------------------------+----------------------------------+-----------+
|
||||
| | ``BPF_CGROUP_UNIX_GETSOCKNAME`` | ``cgroup/getsockname_unix`` | |
|
||||
+-------------------------------------------+----------------------------------------+----------------------------------+-----------+
|
||||
| ``BPF_PROG_TYPE_CGROUP_SOCK`` | ``BPF_CGROUP_INET4_POST_BIND`` | ``cgroup/post_bind4`` | |
|
||||
+ +----------------------------------------+----------------------------------+-----------+
|
||||
|
|
|
|||
|
|
@ -28,19 +28,24 @@ enum cgroup_bpf_attach_type {
|
|||
CGROUP_INET6_BIND,
|
||||
CGROUP_INET4_CONNECT,
|
||||
CGROUP_INET6_CONNECT,
|
||||
CGROUP_UNIX_CONNECT,
|
||||
CGROUP_INET4_POST_BIND,
|
||||
CGROUP_INET6_POST_BIND,
|
||||
CGROUP_UDP4_SENDMSG,
|
||||
CGROUP_UDP6_SENDMSG,
|
||||
CGROUP_UNIX_SENDMSG,
|
||||
CGROUP_SYSCTL,
|
||||
CGROUP_UDP4_RECVMSG,
|
||||
CGROUP_UDP6_RECVMSG,
|
||||
CGROUP_UNIX_RECVMSG,
|
||||
CGROUP_GETSOCKOPT,
|
||||
CGROUP_SETSOCKOPT,
|
||||
CGROUP_INET4_GETPEERNAME,
|
||||
CGROUP_INET6_GETPEERNAME,
|
||||
CGROUP_UNIX_GETPEERNAME,
|
||||
CGROUP_INET4_GETSOCKNAME,
|
||||
CGROUP_INET6_GETSOCKNAME,
|
||||
CGROUP_UNIX_GETSOCKNAME,
|
||||
CGROUP_INET_SOCK_RELEASE,
|
||||
CGROUP_LSM_START,
|
||||
CGROUP_LSM_END = CGROUP_LSM_START + CGROUP_LSM_NUM - 1,
|
||||
|
|
|
|||
|
|
@ -48,19 +48,24 @@ to_cgroup_bpf_attach_type(enum bpf_attach_type attach_type)
|
|||
CGROUP_ATYPE(CGROUP_INET6_BIND);
|
||||
CGROUP_ATYPE(CGROUP_INET4_CONNECT);
|
||||
CGROUP_ATYPE(CGROUP_INET6_CONNECT);
|
||||
CGROUP_ATYPE(CGROUP_UNIX_CONNECT);
|
||||
CGROUP_ATYPE(CGROUP_INET4_POST_BIND);
|
||||
CGROUP_ATYPE(CGROUP_INET6_POST_BIND);
|
||||
CGROUP_ATYPE(CGROUP_UDP4_SENDMSG);
|
||||
CGROUP_ATYPE(CGROUP_UDP6_SENDMSG);
|
||||
CGROUP_ATYPE(CGROUP_UNIX_SENDMSG);
|
||||
CGROUP_ATYPE(CGROUP_SYSCTL);
|
||||
CGROUP_ATYPE(CGROUP_UDP4_RECVMSG);
|
||||
CGROUP_ATYPE(CGROUP_UDP6_RECVMSG);
|
||||
CGROUP_ATYPE(CGROUP_UNIX_RECVMSG);
|
||||
CGROUP_ATYPE(CGROUP_GETSOCKOPT);
|
||||
CGROUP_ATYPE(CGROUP_SETSOCKOPT);
|
||||
CGROUP_ATYPE(CGROUP_INET4_GETPEERNAME);
|
||||
CGROUP_ATYPE(CGROUP_INET6_GETPEERNAME);
|
||||
CGROUP_ATYPE(CGROUP_UNIX_GETPEERNAME);
|
||||
CGROUP_ATYPE(CGROUP_INET4_GETSOCKNAME);
|
||||
CGROUP_ATYPE(CGROUP_INET6_GETSOCKNAME);
|
||||
CGROUP_ATYPE(CGROUP_UNIX_GETSOCKNAME);
|
||||
CGROUP_ATYPE(CGROUP_INET_SOCK_RELEASE);
|
||||
default:
|
||||
return CGROUP_BPF_ATTACH_TYPE_INVALID;
|
||||
|
|
@ -120,6 +125,7 @@ int __cgroup_bpf_run_filter_sk(struct sock *sk,
|
|||
|
||||
int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
|
||||
struct sockaddr *uaddr,
|
||||
int *uaddrlen,
|
||||
enum cgroup_bpf_attach_type atype,
|
||||
void *t_ctx,
|
||||
u32 *flags);
|
||||
|
|
@ -230,22 +236,22 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
|
|||
#define BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk) \
|
||||
BPF_CGROUP_RUN_SK_PROG(sk, CGROUP_INET6_POST_BIND)
|
||||
|
||||
#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, atype) \
|
||||
#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, uaddrlen, atype) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
if (cgroup_bpf_enabled(atype)) \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, atype, \
|
||||
NULL, NULL); \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, uaddrlen, \
|
||||
atype, NULL, NULL); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, atype, t_ctx) \
|
||||
#define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, atype, t_ctx) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
if (cgroup_bpf_enabled(atype)) { \
|
||||
lock_sock(sk); \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, atype, \
|
||||
t_ctx, NULL); \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, uaddrlen, \
|
||||
atype, t_ctx, NULL); \
|
||||
release_sock(sk); \
|
||||
} \
|
||||
__ret; \
|
||||
|
|
@ -256,14 +262,14 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
|
|||
* (at bit position 0) is to indicate CAP_NET_BIND_SERVICE capability check
|
||||
* should be bypassed (BPF_RET_BIND_NO_CAP_NET_BIND_SERVICE).
|
||||
*/
|
||||
#define BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr, atype, bind_flags) \
|
||||
#define BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr, uaddrlen, atype, bind_flags) \
|
||||
({ \
|
||||
u32 __flags = 0; \
|
||||
int __ret = 0; \
|
||||
if (cgroup_bpf_enabled(atype)) { \
|
||||
lock_sock(sk); \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, atype, \
|
||||
NULL, &__flags); \
|
||||
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, uaddrlen, \
|
||||
atype, NULL, &__flags); \
|
||||
release_sock(sk); \
|
||||
if (__flags & BPF_RET_BIND_NO_CAP_NET_BIND_SERVICE) \
|
||||
*bind_flags |= BIND_NO_CAP_NET_BIND_SERVICE; \
|
||||
|
|
@ -276,29 +282,38 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
|
|||
cgroup_bpf_enabled(CGROUP_INET6_CONNECT)) && \
|
||||
(sk)->sk_prot->pre_connect)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, uaddr, CGROUP_INET4_CONNECT)
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, uaddr, uaddrlen, CGROUP_INET4_CONNECT)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, uaddr, CGROUP_INET6_CONNECT)
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, uaddr, uaddrlen, CGROUP_INET6_CONNECT)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_INET4_CONNECT, NULL)
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_INET4_CONNECT, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_INET6_CONNECT, NULL)
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_INET6_CONNECT, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_UDP4_SENDMSG, t_ctx)
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_CONNECT_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UNIX_CONNECT, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_UDP6_SENDMSG, t_ctx)
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UDP4_SENDMSG, t_ctx)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_UDP4_RECVMSG, NULL)
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UDP6_SENDMSG, t_ctx)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_UDP6_RECVMSG, NULL)
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UNIX_SENDMSG, t_ctx)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UDP4_RECVMSG, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UDP6_RECVMSG, NULL)
|
||||
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_RECVMSG_LOCK(sk, uaddr, uaddrlen) \
|
||||
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UNIX_RECVMSG, NULL)
|
||||
|
||||
/* The SOCK_OPS"_SK" macro should be used when sock_ops->sk is not a
|
||||
* fullsock and its parent fullsock cannot be traced by
|
||||
|
|
@ -477,24 +492,27 @@ static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map,
|
|||
}
|
||||
|
||||
#define cgroup_bpf_enabled(atype) (0)
|
||||
#define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, atype, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, atype) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, atype, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_SA_PROG(sk, uaddr, uaddrlen, atype) ({ 0; })
|
||||
#define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (0)
|
||||
#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET_EGRESS(sk,skb) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET_SOCK(sk) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET_SOCK_RELEASE(sk) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr, atype, flags) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr, uaddrlen, atype, flags) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_POST_BIND(sk) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_POST_BIND(sk) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_CONNECT_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_SENDMSG_LOCK(sk, uaddr, uaddrlen, t_ctx) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_UNIX_RECVMSG_LOCK(sk, uaddr, uaddrlen) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(atype, major, minor, access) ({ 0; })
|
||||
#define BPF_CGROUP_RUN_PROG_SYSCTL(head,table,write,buf,count,pos) ({ 0; })
|
||||
|
|
|
|||
|
|
@ -1335,6 +1335,7 @@ struct bpf_sock_addr_kern {
|
|||
*/
|
||||
u64 tmp_reg;
|
||||
void *t_ctx; /* Attach type specific context. */
|
||||
u32 uaddrlen;
|
||||
};
|
||||
|
||||
struct bpf_sock_ops_kern {
|
||||
|
|
|
|||
|
|
@ -1047,6 +1047,11 @@ enum bpf_attach_type {
|
|||
BPF_TCX_INGRESS,
|
||||
BPF_TCX_EGRESS,
|
||||
BPF_TRACE_UPROBE_MULTI,
|
||||
BPF_CGROUP_UNIX_CONNECT,
|
||||
BPF_CGROUP_UNIX_SENDMSG,
|
||||
BPF_CGROUP_UNIX_RECVMSG,
|
||||
BPF_CGROUP_UNIX_GETPEERNAME,
|
||||
BPF_CGROUP_UNIX_GETSOCKNAME,
|
||||
__MAX_BPF_ATTACH_TYPE
|
||||
};
|
||||
|
||||
|
|
@ -2704,8 +2709,8 @@ union bpf_attr {
|
|||
* *bpf_socket* should be one of the following:
|
||||
*
|
||||
* * **struct bpf_sock_ops** for **BPF_PROG_TYPE_SOCK_OPS**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**
|
||||
* and **BPF_CGROUP_INET6_CONNECT**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**,
|
||||
* **BPF_CGROUP_INET6_CONNECT** and **BPF_CGROUP_UNIX_CONNECT**.
|
||||
*
|
||||
* This helper actually implements a subset of **setsockopt()**.
|
||||
* It supports the following *level*\ s:
|
||||
|
|
@ -2943,8 +2948,8 @@ union bpf_attr {
|
|||
* *bpf_socket* should be one of the following:
|
||||
*
|
||||
* * **struct bpf_sock_ops** for **BPF_PROG_TYPE_SOCK_OPS**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**
|
||||
* and **BPF_CGROUP_INET6_CONNECT**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**,
|
||||
* **BPF_CGROUP_INET6_CONNECT** and **BPF_CGROUP_UNIX_CONNECT**.
|
||||
*
|
||||
* This helper actually implements a subset of **getsockopt()**.
|
||||
* It supports the same set of *optname*\ s that is supported by
|
||||
|
|
|
|||
|
|
@ -7850,6 +7850,7 @@ static int bpf_prog_type_to_kfunc_hook(enum bpf_prog_type prog_type)
|
|||
case BPF_PROG_TYPE_SYSCALL:
|
||||
return BTF_KFUNC_HOOK_SYSCALL;
|
||||
case BPF_PROG_TYPE_CGROUP_SKB:
|
||||
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
|
||||
return BTF_KFUNC_HOOK_CGROUP_SKB;
|
||||
case BPF_PROG_TYPE_SCHED_ACT:
|
||||
return BTF_KFUNC_HOOK_SCHED_ACT;
|
||||
|
|
|
|||
|
|
@ -1450,18 +1450,22 @@ EXPORT_SYMBOL(__cgroup_bpf_run_filter_sk);
|
|||
* provided by user sockaddr
|
||||
* @sk: sock struct that will use sockaddr
|
||||
* @uaddr: sockaddr struct provided by user
|
||||
* @uaddrlen: Pointer to the size of the sockaddr struct provided by user. It is
|
||||
* read-only for AF_INET[6] uaddr but can be modified for AF_UNIX
|
||||
* uaddr.
|
||||
* @atype: The type of program to be executed
|
||||
* @t_ctx: Pointer to attach type specific context
|
||||
* @flags: Pointer to u32 which contains higher bits of BPF program
|
||||
* return value (OR'ed together).
|
||||
*
|
||||
* socket is expected to be of type INET or INET6.
|
||||
* socket is expected to be of type INET, INET6 or UNIX.
|
||||
*
|
||||
* This function will return %-EPERM if an attached program is found and
|
||||
* returned value != 1 during execution. In all other cases, 0 is returned.
|
||||
*/
|
||||
int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
|
||||
struct sockaddr *uaddr,
|
||||
int *uaddrlen,
|
||||
enum cgroup_bpf_attach_type atype,
|
||||
void *t_ctx,
|
||||
u32 *flags)
|
||||
|
|
@ -1473,21 +1477,31 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
|
|||
};
|
||||
struct sockaddr_storage unspec;
|
||||
struct cgroup *cgrp;
|
||||
int ret;
|
||||
|
||||
/* Check socket family since not all sockets represent network
|
||||
* endpoint (e.g. AF_UNIX).
|
||||
*/
|
||||
if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
|
||||
if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6 &&
|
||||
sk->sk_family != AF_UNIX)
|
||||
return 0;
|
||||
|
||||
if (!ctx.uaddr) {
|
||||
memset(&unspec, 0, sizeof(unspec));
|
||||
ctx.uaddr = (struct sockaddr *)&unspec;
|
||||
ctx.uaddrlen = 0;
|
||||
} else {
|
||||
ctx.uaddrlen = *uaddrlen;
|
||||
}
|
||||
|
||||
cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
|
||||
return bpf_prog_run_array_cg(&cgrp->bpf, atype, &ctx, bpf_prog_run,
|
||||
0, flags);
|
||||
ret = bpf_prog_run_array_cg(&cgrp->bpf, atype, &ctx, bpf_prog_run,
|
||||
0, flags);
|
||||
|
||||
if (!ret && uaddr)
|
||||
*uaddrlen = ctx.uaddrlen;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(__cgroup_bpf_run_filter_sock_addr);
|
||||
|
||||
|
|
@ -2520,10 +2534,13 @@ cgroup_common_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|||
case BPF_CGROUP_SOCK_OPS:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
return NULL;
|
||||
default:
|
||||
return &bpf_get_retval_proto;
|
||||
|
|
@ -2535,10 +2552,13 @@ cgroup_common_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|||
case BPF_CGROUP_SOCK_OPS:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
return NULL;
|
||||
default:
|
||||
return &bpf_set_retval_proto;
|
||||
|
|
|
|||
|
|
@ -2446,14 +2446,19 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
|
|||
case BPF_CGROUP_INET6_BIND:
|
||||
case BPF_CGROUP_INET4_CONNECT:
|
||||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UNIX_CONNECT:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UNIX_SENDMSG:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
@ -3678,14 +3683,19 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
|
|||
case BPF_CGROUP_INET6_BIND:
|
||||
case BPF_CGROUP_INET4_CONNECT:
|
||||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UNIX_CONNECT:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UNIX_SENDMSG:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
return BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
|
||||
case BPF_CGROUP_SOCK_OPS:
|
||||
return BPF_PROG_TYPE_SOCK_OPS;
|
||||
|
|
@ -3942,14 +3952,19 @@ static int bpf_prog_query(const union bpf_attr *attr,
|
|||
case BPF_CGROUP_INET6_POST_BIND:
|
||||
case BPF_CGROUP_INET4_CONNECT:
|
||||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UNIX_CONNECT:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UNIX_SENDMSG:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
case BPF_CGROUP_SOCK_OPS:
|
||||
case BPF_CGROUP_DEVICE:
|
||||
case BPF_CGROUP_SYSCTL:
|
||||
|
|
|
|||
|
|
@ -14797,10 +14797,13 @@ static int check_return_code(struct bpf_verifier_env *env, int regno)
|
|||
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
|
||||
if (env->prog->expected_attach_type == BPF_CGROUP_UDP4_RECVMSG ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_UDP6_RECVMSG ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_UNIX_RECVMSG ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET4_GETPEERNAME ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET6_GETPEERNAME ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_UNIX_GETPEERNAME ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET4_GETSOCKNAME ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET6_GETSOCKNAME)
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET6_GETSOCKNAME ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_UNIX_GETSOCKNAME)
|
||||
range = tnum_range(1, 1);
|
||||
if (env->prog->expected_attach_type == BPF_CGROUP_INET4_BIND ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_INET6_BIND)
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@
|
|||
#include <net/xdp.h>
|
||||
#include <net/mptcp.h>
|
||||
#include <net/netfilter/nf_conntrack_bpf.h>
|
||||
#include <linux/un.h>
|
||||
|
||||
static const struct bpf_func_proto *
|
||||
bpf_sk_base_func_proto(enum bpf_func_id func_id);
|
||||
|
|
@ -7874,14 +7875,19 @@ sock_addr_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|||
case BPF_CGROUP_INET6_BIND:
|
||||
case BPF_CGROUP_INET4_CONNECT:
|
||||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UNIX_CONNECT:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UNIX_SENDMSG:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
return &bpf_sock_addr_setsockopt_proto;
|
||||
default:
|
||||
return NULL;
|
||||
|
|
@ -7892,14 +7898,19 @@ sock_addr_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|||
case BPF_CGROUP_INET6_BIND:
|
||||
case BPF_CGROUP_INET4_CONNECT:
|
||||
case BPF_CGROUP_INET6_CONNECT:
|
||||
case BPF_CGROUP_UNIX_CONNECT:
|
||||
case BPF_CGROUP_UDP4_RECVMSG:
|
||||
case BPF_CGROUP_UDP6_RECVMSG:
|
||||
case BPF_CGROUP_UNIX_RECVMSG:
|
||||
case BPF_CGROUP_UDP4_SENDMSG:
|
||||
case BPF_CGROUP_UDP6_SENDMSG:
|
||||
case BPF_CGROUP_UNIX_SENDMSG:
|
||||
case BPF_CGROUP_INET4_GETPEERNAME:
|
||||
case BPF_CGROUP_INET6_GETPEERNAME:
|
||||
case BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
case BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
case BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
case BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
return &bpf_sock_addr_getsockopt_proto;
|
||||
default:
|
||||
return NULL;
|
||||
|
|
@ -8947,8 +8958,8 @@ static bool sock_addr_is_valid_access(int off, int size,
|
|||
if (off % size != 0)
|
||||
return false;
|
||||
|
||||
/* Disallow access to IPv6 fields from IPv4 contex and vise
|
||||
* versa.
|
||||
/* Disallow access to fields not belonging to the attach type's address
|
||||
* family.
|
||||
*/
|
||||
switch (off) {
|
||||
case bpf_ctx_range(struct bpf_sock_addr, user_ip4):
|
||||
|
|
@ -11768,6 +11779,27 @@ __bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_buff *xdp, u64 flags,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__bpf_kfunc int bpf_sock_addr_set_sun_path(struct bpf_sock_addr_kern *sa_kern,
|
||||
const u8 *sun_path, u32 sun_path__sz)
|
||||
{
|
||||
struct sockaddr_un *un;
|
||||
|
||||
if (sa_kern->sk->sk_family != AF_UNIX)
|
||||
return -EINVAL;
|
||||
|
||||
/* We do not allow changing the address to unnamed or larger than the
|
||||
* maximum allowed address size for a unix sockaddr.
|
||||
*/
|
||||
if (sun_path__sz == 0 || sun_path__sz > UNIX_PATH_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
un = (struct sockaddr_un *)sa_kern->uaddr;
|
||||
memcpy(un->sun_path, sun_path, sun_path__sz);
|
||||
sa_kern->uaddrlen = offsetof(struct sockaddr_un, sun_path) + sun_path__sz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
__diag_pop();
|
||||
|
||||
int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags,
|
||||
|
|
@ -11792,6 +11824,10 @@ BTF_SET8_START(bpf_kfunc_check_set_xdp)
|
|||
BTF_ID_FLAGS(func, bpf_dynptr_from_xdp)
|
||||
BTF_SET8_END(bpf_kfunc_check_set_xdp)
|
||||
|
||||
BTF_SET8_START(bpf_kfunc_check_set_sock_addr)
|
||||
BTF_ID_FLAGS(func, bpf_sock_addr_set_sun_path)
|
||||
BTF_SET8_END(bpf_kfunc_check_set_sock_addr)
|
||||
|
||||
static const struct btf_kfunc_id_set bpf_kfunc_set_skb = {
|
||||
.owner = THIS_MODULE,
|
||||
.set = &bpf_kfunc_check_set_skb,
|
||||
|
|
@ -11802,6 +11838,11 @@ static const struct btf_kfunc_id_set bpf_kfunc_set_xdp = {
|
|||
.set = &bpf_kfunc_check_set_xdp,
|
||||
};
|
||||
|
||||
static const struct btf_kfunc_id_set bpf_kfunc_set_sock_addr = {
|
||||
.owner = THIS_MODULE,
|
||||
.set = &bpf_kfunc_check_set_sock_addr,
|
||||
};
|
||||
|
||||
static int __init bpf_kfunc_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -11816,7 +11857,9 @@ static int __init bpf_kfunc_init(void)
|
|||
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_XMIT, &bpf_kfunc_set_skb);
|
||||
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_SEG6LOCAL, &bpf_kfunc_set_skb);
|
||||
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_NETFILTER, &bpf_kfunc_set_skb);
|
||||
return ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &bpf_kfunc_set_xdp);
|
||||
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &bpf_kfunc_set_xdp);
|
||||
return ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
|
||||
&bpf_kfunc_set_sock_addr);
|
||||
}
|
||||
late_initcall(bpf_kfunc_init);
|
||||
|
||||
|
|
|
|||
|
|
@ -452,7 +452,7 @@ int inet_bind_sk(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|||
/* BPF prog is run before any checks are done so that if the prog
|
||||
* changes context in a wrong way it will be caught.
|
||||
*/
|
||||
err = BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr,
|
||||
err = BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr, &addr_len,
|
||||
CGROUP_INET4_BIND, &flags);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
@ -788,6 +788,7 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr,
|
|||
struct sock *sk = sock->sk;
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr);
|
||||
int sin_addr_len = sizeof(*sin);
|
||||
|
||||
sin->sin_family = AF_INET;
|
||||
lock_sock(sk);
|
||||
|
|
@ -800,7 +801,7 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr,
|
|||
}
|
||||
sin->sin_port = inet->inet_dport;
|
||||
sin->sin_addr.s_addr = inet->inet_daddr;
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin,
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, &sin_addr_len,
|
||||
CGROUP_INET4_GETPEERNAME);
|
||||
} else {
|
||||
__be32 addr = inet->inet_rcv_saddr;
|
||||
|
|
@ -808,7 +809,7 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr,
|
|||
addr = inet->inet_saddr;
|
||||
sin->sin_port = inet->inet_sport;
|
||||
sin->sin_addr.s_addr = addr;
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin,
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, &sin_addr_len,
|
||||
CGROUP_INET4_GETSOCKNAME);
|
||||
}
|
||||
release_sock(sk);
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ static int ping_pre_connect(struct sock *sk, struct sockaddr *uaddr,
|
|||
if (addr_len < sizeof(struct sockaddr_in))
|
||||
return -EINVAL;
|
||||
|
||||
return BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr);
|
||||
return BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr, &addr_len);
|
||||
}
|
||||
|
||||
/* Checks the bind address and possibly modifies sk->sk_bound_dev_if. */
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ static int tcp_v4_pre_connect(struct sock *sk, struct sockaddr *uaddr,
|
|||
|
||||
sock_owned_by_me(sk);
|
||||
|
||||
return BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr);
|
||||
return BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr, &addr_len);
|
||||
}
|
||||
|
||||
/* This will initiate an outgoing connection. */
|
||||
|
|
|
|||
|
|
@ -1143,7 +1143,9 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||
|
||||
if (cgroup_bpf_enabled(CGROUP_UDP4_SENDMSG) && !connected) {
|
||||
err = BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk,
|
||||
(struct sockaddr *)usin, &ipc.addr);
|
||||
(struct sockaddr *)usin,
|
||||
&msg->msg_namelen,
|
||||
&ipc.addr);
|
||||
if (err)
|
||||
goto out_free;
|
||||
if (usin) {
|
||||
|
|
@ -1865,7 +1867,8 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
|
|||
*addr_len = sizeof(*sin);
|
||||
|
||||
BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk,
|
||||
(struct sockaddr *)sin);
|
||||
(struct sockaddr *)sin,
|
||||
addr_len);
|
||||
}
|
||||
|
||||
if (udp_test_bit(GRO_ENABLED, sk))
|
||||
|
|
@ -1904,7 +1907,7 @@ int udp_pre_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|||
if (addr_len < sizeof(struct sockaddr_in))
|
||||
return -EINVAL;
|
||||
|
||||
return BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr);
|
||||
return BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr, &addr_len);
|
||||
}
|
||||
EXPORT_SYMBOL(udp_pre_connect);
|
||||
|
||||
|
|
|
|||
|
|
@ -454,7 +454,7 @@ int inet6_bind_sk(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|||
/* BPF prog is run before any checks are done so that if the prog
|
||||
* changes context in a wrong way it will be caught.
|
||||
*/
|
||||
err = BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr,
|
||||
err = BPF_CGROUP_RUN_PROG_INET_BIND_LOCK(sk, uaddr, &addr_len,
|
||||
CGROUP_INET6_BIND, &flags);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
@ -520,6 +520,7 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
|
|||
int peer)
|
||||
{
|
||||
struct sockaddr_in6 *sin = (struct sockaddr_in6 *)uaddr;
|
||||
int sin_addr_len = sizeof(*sin);
|
||||
struct sock *sk = sock->sk;
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
|
|
@ -539,7 +540,7 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
|
|||
sin->sin6_addr = sk->sk_v6_daddr;
|
||||
if (inet6_test_bit(SNDFLOW, sk))
|
||||
sin->sin6_flowinfo = np->flow_label;
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin,
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, &sin_addr_len,
|
||||
CGROUP_INET6_GETPEERNAME);
|
||||
} else {
|
||||
if (ipv6_addr_any(&sk->sk_v6_rcv_saddr))
|
||||
|
|
@ -547,13 +548,13 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
|
|||
else
|
||||
sin->sin6_addr = sk->sk_v6_rcv_saddr;
|
||||
sin->sin6_port = inet->inet_sport;
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin,
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, &sin_addr_len,
|
||||
CGROUP_INET6_GETSOCKNAME);
|
||||
}
|
||||
sin->sin6_scope_id = ipv6_iface_scope_id(&sin->sin6_addr,
|
||||
sk->sk_bound_dev_if);
|
||||
release_sock(sk);
|
||||
return sizeof(*sin);
|
||||
return sin_addr_len;
|
||||
}
|
||||
EXPORT_SYMBOL(inet6_getname);
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ static int ping_v6_pre_connect(struct sock *sk, struct sockaddr *uaddr,
|
|||
if (addr_len < SIN6_LEN_RFC2133)
|
||||
return -EINVAL;
|
||||
|
||||
return BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr);
|
||||
return BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr, &addr_len);
|
||||
}
|
||||
|
||||
static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ static int tcp_v6_pre_connect(struct sock *sk, struct sockaddr *uaddr,
|
|||
|
||||
sock_owned_by_me(sk);
|
||||
|
||||
return BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr);
|
||||
return BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr, &addr_len);
|
||||
}
|
||||
|
||||
static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
|
||||
|
|
|
|||
|
|
@ -410,7 +410,8 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
|
|||
*addr_len = sizeof(*sin6);
|
||||
|
||||
BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk,
|
||||
(struct sockaddr *)sin6);
|
||||
(struct sockaddr *)sin6,
|
||||
addr_len);
|
||||
}
|
||||
|
||||
if (udp_test_bit(GRO_ENABLED, sk))
|
||||
|
|
@ -1157,7 +1158,7 @@ static int udpv6_pre_connect(struct sock *sk, struct sockaddr *uaddr,
|
|||
if (addr_len < SIN6_LEN_RFC2133)
|
||||
return -EINVAL;
|
||||
|
||||
return BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr);
|
||||
return BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr, &addr_len);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1510,6 +1511,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|||
if (cgroup_bpf_enabled(CGROUP_UDP6_SENDMSG) && !connected) {
|
||||
err = BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk,
|
||||
(struct sockaddr *)sin6,
|
||||
&addr_len,
|
||||
&fl6->saddr);
|
||||
if (err)
|
||||
goto out_no_dst;
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@
|
|||
#include <linux/freezer.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/btf_ids.h>
|
||||
#include <linux/bpf-cgroup.h>
|
||||
|
||||
#include "scm.h"
|
||||
|
||||
|
|
@ -1381,6 +1382,10 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
|
|||
if (err)
|
||||
goto out;
|
||||
|
||||
err = BPF_CGROUP_RUN_PROG_UNIX_CONNECT_LOCK(sk, addr, &alen);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
|
||||
test_bit(SOCK_PASSPIDFD, &sock->flags)) &&
|
||||
!unix_sk(sk)->addr) {
|
||||
|
|
@ -1490,6 +1495,10 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
|
|||
if (err)
|
||||
goto out;
|
||||
|
||||
err = BPF_CGROUP_RUN_PROG_UNIX_CONNECT_LOCK(sk, uaddr, &addr_len);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
|
||||
test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) {
|
||||
err = unix_autobind(sk);
|
||||
|
|
@ -1770,6 +1779,13 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
|
|||
} else {
|
||||
err = addr->len;
|
||||
memcpy(sunaddr, addr->name, addr->len);
|
||||
|
||||
if (peer)
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, uaddr, &err,
|
||||
CGROUP_UNIX_GETPEERNAME);
|
||||
else
|
||||
BPF_CGROUP_RUN_SA_PROG(sk, uaddr, &err,
|
||||
CGROUP_UNIX_GETSOCKNAME);
|
||||
}
|
||||
sock_put(sk);
|
||||
out:
|
||||
|
|
@ -1922,6 +1938,13 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
|
|||
err = unix_validate_addr(sunaddr, msg->msg_namelen);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = BPF_CGROUP_RUN_PROG_UNIX_SENDMSG_LOCK(sk,
|
||||
msg->msg_name,
|
||||
&msg->msg_namelen,
|
||||
NULL);
|
||||
if (err)
|
||||
goto out;
|
||||
} else {
|
||||
sunaddr = NULL;
|
||||
err = -ENOTCONN;
|
||||
|
|
@ -2390,9 +2413,14 @@ int __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size,
|
|||
EPOLLOUT | EPOLLWRNORM |
|
||||
EPOLLWRBAND);
|
||||
|
||||
if (msg->msg_name)
|
||||
if (msg->msg_name) {
|
||||
unix_copy_addr(msg, skb->sk);
|
||||
|
||||
BPF_CGROUP_RUN_PROG_UNIX_RECVMSG_LOCK(sk,
|
||||
msg->msg_name,
|
||||
&msg->msg_namelen);
|
||||
}
|
||||
|
||||
if (size > skb->len - skip)
|
||||
size = skb->len - skip;
|
||||
else if (size < skb->len - skip)
|
||||
|
|
@ -2744,6 +2772,11 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
|
|||
DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr,
|
||||
state->msg->msg_name);
|
||||
unix_copy_addr(state->msg, skb->sk);
|
||||
|
||||
BPF_CGROUP_RUN_PROG_UNIX_RECVMSG_LOCK(sk,
|
||||
state->msg->msg_name,
|
||||
&state->msg->msg_namelen);
|
||||
|
||||
sunaddr = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,11 +36,14 @@ CGROUP COMMANDS
|
|||
| **cgroup_device** | **cgroup_inet4_bind** | **cgroup_inet6_bind** |
|
||||
| **cgroup_inet4_post_bind** | **cgroup_inet6_post_bind** |
|
||||
| **cgroup_inet4_connect** | **cgroup_inet6_connect** |
|
||||
| **cgroup_inet4_getpeername** | **cgroup_inet6_getpeername** |
|
||||
| **cgroup_unix_connect** | **cgroup_inet4_getpeername** |
|
||||
| **cgroup_inet6_getpeername** | **cgroup_unix_getpeername** |
|
||||
| **cgroup_inet4_getsockname** | **cgroup_inet6_getsockname** |
|
||||
| **cgroup_udp4_sendmsg** | **cgroup_udp6_sendmsg** |
|
||||
| **cgroup_unix_getsockname** | **cgroup_udp4_sendmsg** |
|
||||
| **cgroup_udp6_sendmsg** | **cgroup_unix_sendmsg** |
|
||||
| **cgroup_udp4_recvmsg** | **cgroup_udp6_recvmsg** |
|
||||
| **cgroup_sysctl** | **cgroup_getsockopt** | **cgroup_setsockopt** |
|
||||
| **cgroup_unix_recvmsg** | **cgroup_sysctl** |
|
||||
| **cgroup_getsockopt** | **cgroup_setsockopt** |
|
||||
| **cgroup_inet_sock_release** }
|
||||
| *ATTACH_FLAGS* := { **multi** | **override** }
|
||||
|
||||
|
|
@ -102,21 +105,28 @@ DESCRIPTION
|
|||
**post_bind6** return from bind(2) for an inet6 socket (since 4.17);
|
||||
**connect4** call to connect(2) for an inet4 socket (since 4.17);
|
||||
**connect6** call to connect(2) for an inet6 socket (since 4.17);
|
||||
**connect_unix** call to connect(2) for a unix socket (since 6.7);
|
||||
**sendmsg4** call to sendto(2), sendmsg(2), sendmmsg(2) for an
|
||||
unconnected udp4 socket (since 4.18);
|
||||
**sendmsg6** call to sendto(2), sendmsg(2), sendmmsg(2) for an
|
||||
unconnected udp6 socket (since 4.18);
|
||||
**sendmsg_unix** call to sendto(2), sendmsg(2), sendmmsg(2) for
|
||||
an unconnected unix socket (since 6.7);
|
||||
**recvmsg4** call to recvfrom(2), recvmsg(2), recvmmsg(2) for
|
||||
an unconnected udp4 socket (since 5.2);
|
||||
**recvmsg6** call to recvfrom(2), recvmsg(2), recvmmsg(2) for
|
||||
an unconnected udp6 socket (since 5.2);
|
||||
**recvmsg_unix** call to recvfrom(2), recvmsg(2), recvmmsg(2) for
|
||||
an unconnected unix socket (since 6.7);
|
||||
**sysctl** sysctl access (since 5.2);
|
||||
**getsockopt** call to getsockopt (since 5.3);
|
||||
**setsockopt** call to setsockopt (since 5.3);
|
||||
**getpeername4** call to getpeername(2) for an inet4 socket (since 5.8);
|
||||
**getpeername6** call to getpeername(2) for an inet6 socket (since 5.8);
|
||||
**getpeername_unix** call to getpeername(2) for a unix socket (since 6.7);
|
||||
**getsockname4** call to getsockname(2) for an inet4 socket (since 5.8);
|
||||
**getsockname6** call to getsockname(2) for an inet6 socket (since 5.8).
|
||||
**getsockname_unix** call to getsockname(2) for a unix socket (since 6.7);
|
||||
**sock_release** closing an userspace inet socket (since 5.9).
|
||||
|
||||
**bpftool cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
|
||||
|
|
|
|||
|
|
@ -47,9 +47,11 @@ PROG COMMANDS
|
|||
| **cgroup/sock** | **cgroup/dev** | **lwt_in** | **lwt_out** | **lwt_xmit** |
|
||||
| **lwt_seg6local** | **sockops** | **sk_skb** | **sk_msg** | **lirc_mode2** |
|
||||
| **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** |
|
||||
| **cgroup/connect4** | **cgroup/connect6** | **cgroup/getpeername4** | **cgroup/getpeername6** |
|
||||
| **cgroup/getsockname4** | **cgroup/getsockname6** | **cgroup/sendmsg4** | **cgroup/sendmsg6** |
|
||||
| **cgroup/recvmsg4** | **cgroup/recvmsg6** | **cgroup/sysctl** |
|
||||
| **cgroup/connect4** | **cgroup/connect6** | **cgroup/connect_unix** |
|
||||
| **cgroup/getpeername4** | **cgroup/getpeername6** | **cgroup/getpeername_unix** |
|
||||
| **cgroup/getsockname4** | **cgroup/getsockname6** | **cgroup/getsockname_unix** |
|
||||
| **cgroup/sendmsg4** | **cgroup/sendmsg6** | **cgroup/sendmsg_unix** |
|
||||
| **cgroup/recvmsg4** | **cgroup/recvmsg6** | **cgroup/recvmsg_unix** | **cgroup/sysctl** |
|
||||
| **cgroup/getsockopt** | **cgroup/setsockopt** | **cgroup/sock_release** |
|
||||
| **struct_ops** | **fentry** | **fexit** | **freplace** | **sk_lookup**
|
||||
| }
|
||||
|
|
|
|||
|
|
@ -480,13 +480,13 @@ _bpftool()
|
|||
action tracepoint raw_tracepoint \
|
||||
xdp perf_event cgroup/skb cgroup/sock \
|
||||
cgroup/dev lwt_in lwt_out lwt_xmit \
|
||||
lwt_seg6local sockops sk_skb sk_msg \
|
||||
lirc_mode2 cgroup/bind4 cgroup/bind6 \
|
||||
cgroup/connect4 cgroup/connect6 \
|
||||
cgroup/getpeername4 cgroup/getpeername6 \
|
||||
cgroup/getsockname4 cgroup/getsockname6 \
|
||||
cgroup/sendmsg4 cgroup/sendmsg6 \
|
||||
cgroup/recvmsg4 cgroup/recvmsg6 \
|
||||
lwt_seg6local sockops sk_skb sk_msg lirc_mode2 \
|
||||
cgroup/bind4 cgroup/bind6 \
|
||||
cgroup/connect4 cgroup/connect6 cgroup/connect_unix \
|
||||
cgroup/getpeername4 cgroup/getpeername6 cgroup/getpeername_unix \
|
||||
cgroup/getsockname4 cgroup/getsockname6 cgroup/getsockname_unix \
|
||||
cgroup/sendmsg4 cgroup/sendmsg6 cgroup/sendmsg_unix \
|
||||
cgroup/recvmsg4 cgroup/recvmsg6 cgroup/recvmsg_unix \
|
||||
cgroup/post_bind4 cgroup/post_bind6 \
|
||||
cgroup/sysctl cgroup/getsockopt \
|
||||
cgroup/setsockopt cgroup/sock_release struct_ops \
|
||||
|
|
|
|||
|
|
@ -28,13 +28,15 @@
|
|||
" cgroup_device | cgroup_inet4_bind |\n" \
|
||||
" cgroup_inet6_bind | cgroup_inet4_post_bind |\n" \
|
||||
" cgroup_inet6_post_bind | cgroup_inet4_connect |\n" \
|
||||
" cgroup_inet6_connect | cgroup_inet4_getpeername |\n" \
|
||||
" cgroup_inet6_getpeername | cgroup_inet4_getsockname |\n" \
|
||||
" cgroup_inet6_getsockname | cgroup_udp4_sendmsg |\n" \
|
||||
" cgroup_udp6_sendmsg | cgroup_udp4_recvmsg |\n" \
|
||||
" cgroup_udp6_recvmsg | cgroup_sysctl |\n" \
|
||||
" cgroup_getsockopt | cgroup_setsockopt |\n" \
|
||||
" cgroup_inet_sock_release }"
|
||||
" cgroup_inet6_connect | cgroup_unix_connect |\n" \
|
||||
" cgroup_inet4_getpeername | cgroup_inet6_getpeername |\n" \
|
||||
" cgroup_unix_getpeername | cgroup_inet4_getsockname |\n" \
|
||||
" cgroup_inet6_getsockname | cgroup_unix_getsockname |\n" \
|
||||
" cgroup_udp4_sendmsg | cgroup_udp6_sendmsg |\n" \
|
||||
" cgroup_unix_sendmsg | cgroup_udp4_recvmsg |\n" \
|
||||
" cgroup_udp6_recvmsg | cgroup_unix_recvmsg |\n" \
|
||||
" cgroup_sysctl | cgroup_getsockopt |\n" \
|
||||
" cgroup_setsockopt | cgroup_inet_sock_release }"
|
||||
|
||||
static unsigned int query_flags;
|
||||
static struct btf *btf_vmlinux;
|
||||
|
|
|
|||
|
|
@ -2475,9 +2475,10 @@ static int do_help(int argc, char **argv)
|
|||
" sk_reuseport | flow_dissector | cgroup/sysctl |\n"
|
||||
" cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n"
|
||||
" cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n"
|
||||
" cgroup/getpeername4 | cgroup/getpeername6 |\n"
|
||||
" cgroup/getsockname4 | cgroup/getsockname6 | cgroup/sendmsg4 |\n"
|
||||
" cgroup/sendmsg6 | cgroup/recvmsg4 | cgroup/recvmsg6 |\n"
|
||||
" cgroup/connect_unix | cgroup/getpeername4 | cgroup/getpeername6 |\n"
|
||||
" cgroup/getpeername_unix | cgroup/getsockname4 | cgroup/getsockname6 |\n"
|
||||
" cgroup/getsockname_unix | cgroup/sendmsg4 | cgroup/sendmsg6 |\n"
|
||||
" cgroup/sendmsg°unix | cgroup/recvmsg4 | cgroup/recvmsg6 | cgroup/recvmsg_unix |\n"
|
||||
" cgroup/getsockopt | cgroup/setsockopt | cgroup/sock_release |\n"
|
||||
" struct_ops | fentry | fexit | freplace | sk_lookup }\n"
|
||||
" ATTACH_TYPE := { sk_msg_verdict | sk_skb_verdict | sk_skb_stream_verdict |\n"
|
||||
|
|
|
|||
|
|
@ -1047,6 +1047,11 @@ enum bpf_attach_type {
|
|||
BPF_TCX_INGRESS,
|
||||
BPF_TCX_EGRESS,
|
||||
BPF_TRACE_UPROBE_MULTI,
|
||||
BPF_CGROUP_UNIX_CONNECT,
|
||||
BPF_CGROUP_UNIX_SENDMSG,
|
||||
BPF_CGROUP_UNIX_RECVMSG,
|
||||
BPF_CGROUP_UNIX_GETPEERNAME,
|
||||
BPF_CGROUP_UNIX_GETSOCKNAME,
|
||||
__MAX_BPF_ATTACH_TYPE
|
||||
};
|
||||
|
||||
|
|
@ -2704,8 +2709,8 @@ union bpf_attr {
|
|||
* *bpf_socket* should be one of the following:
|
||||
*
|
||||
* * **struct bpf_sock_ops** for **BPF_PROG_TYPE_SOCK_OPS**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**
|
||||
* and **BPF_CGROUP_INET6_CONNECT**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**,
|
||||
* **BPF_CGROUP_INET6_CONNECT** and **BPF_CGROUP_UNIX_CONNECT**.
|
||||
*
|
||||
* This helper actually implements a subset of **setsockopt()**.
|
||||
* It supports the following *level*\ s:
|
||||
|
|
@ -2943,8 +2948,8 @@ union bpf_attr {
|
|||
* *bpf_socket* should be one of the following:
|
||||
*
|
||||
* * **struct bpf_sock_ops** for **BPF_PROG_TYPE_SOCK_OPS**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**
|
||||
* and **BPF_CGROUP_INET6_CONNECT**.
|
||||
* * **struct bpf_sock_addr** for **BPF_CGROUP_INET4_CONNECT**,
|
||||
* **BPF_CGROUP_INET6_CONNECT** and **BPF_CGROUP_UNIX_CONNECT**.
|
||||
*
|
||||
* This helper actually implements a subset of **getsockopt()**.
|
||||
* It supports the same set of *optname*\ s that is supported by
|
||||
|
|
|
|||
|
|
@ -82,17 +82,22 @@ static const char * const attach_type_name[] = {
|
|||
[BPF_CGROUP_INET6_BIND] = "cgroup_inet6_bind",
|
||||
[BPF_CGROUP_INET4_CONNECT] = "cgroup_inet4_connect",
|
||||
[BPF_CGROUP_INET6_CONNECT] = "cgroup_inet6_connect",
|
||||
[BPF_CGROUP_UNIX_CONNECT] = "cgroup_unix_connect",
|
||||
[BPF_CGROUP_INET4_POST_BIND] = "cgroup_inet4_post_bind",
|
||||
[BPF_CGROUP_INET6_POST_BIND] = "cgroup_inet6_post_bind",
|
||||
[BPF_CGROUP_INET4_GETPEERNAME] = "cgroup_inet4_getpeername",
|
||||
[BPF_CGROUP_INET6_GETPEERNAME] = "cgroup_inet6_getpeername",
|
||||
[BPF_CGROUP_UNIX_GETPEERNAME] = "cgroup_unix_getpeername",
|
||||
[BPF_CGROUP_INET4_GETSOCKNAME] = "cgroup_inet4_getsockname",
|
||||
[BPF_CGROUP_INET6_GETSOCKNAME] = "cgroup_inet6_getsockname",
|
||||
[BPF_CGROUP_UNIX_GETSOCKNAME] = "cgroup_unix_getsockname",
|
||||
[BPF_CGROUP_UDP4_SENDMSG] = "cgroup_udp4_sendmsg",
|
||||
[BPF_CGROUP_UDP6_SENDMSG] = "cgroup_udp6_sendmsg",
|
||||
[BPF_CGROUP_UNIX_SENDMSG] = "cgroup_unix_sendmsg",
|
||||
[BPF_CGROUP_SYSCTL] = "cgroup_sysctl",
|
||||
[BPF_CGROUP_UDP4_RECVMSG] = "cgroup_udp4_recvmsg",
|
||||
[BPF_CGROUP_UDP6_RECVMSG] = "cgroup_udp6_recvmsg",
|
||||
[BPF_CGROUP_UNIX_RECVMSG] = "cgroup_unix_recvmsg",
|
||||
[BPF_CGROUP_GETSOCKOPT] = "cgroup_getsockopt",
|
||||
[BPF_CGROUP_SETSOCKOPT] = "cgroup_setsockopt",
|
||||
[BPF_SK_SKB_STREAM_PARSER] = "sk_skb_stream_parser",
|
||||
|
|
@ -8960,14 +8965,19 @@ static const struct bpf_sec_def section_defs[] = {
|
|||
SEC_DEF("cgroup/bind6", CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_BIND, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/connect4", CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_CONNECT, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/connect6", CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_CONNECT, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/connect_unix", CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_CONNECT, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/sendmsg4", CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_SENDMSG, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/sendmsg6", CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/sendmsg_unix", CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_SENDMSG, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/recvmsg4", CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_RECVMSG, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/recvmsg6", CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_RECVMSG, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/recvmsg_unix", CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_RECVMSG, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/getpeername4", CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_GETPEERNAME, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/getpeername6", CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_GETPEERNAME, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/getpeername_unix", CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_GETPEERNAME, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/getsockname4", CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_GETSOCKNAME, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/getsockname6", CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_GETSOCKNAME, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/getsockname_unix", CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_GETSOCKNAME, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/sysctl", CGROUP_SYSCTL, BPF_CGROUP_SYSCTL, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/getsockopt", CGROUP_SOCKOPT, BPF_CGROUP_GETSOCKOPT, SEC_ATTACHABLE),
|
||||
SEC_DEF("cgroup/setsockopt", CGROUP_SOCKOPT, BPF_CGROUP_SETSOCKOPT, SEC_ATTACHABLE),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef __BPF_KFUNCS__
|
||||
#define __BPF_KFUNCS__
|
||||
|
||||
struct bpf_sock_addr_kern;
|
||||
|
||||
/* Description
|
||||
* Initializes an skb-type dynptr
|
||||
* Returns
|
||||
|
|
@ -41,4 +43,16 @@ extern bool bpf_dynptr_is_rdonly(const struct bpf_dynptr *ptr) __ksym;
|
|||
extern __u32 bpf_dynptr_size(const struct bpf_dynptr *ptr) __ksym;
|
||||
extern int bpf_dynptr_clone(const struct bpf_dynptr *ptr, struct bpf_dynptr *clone__init) __ksym;
|
||||
|
||||
/* Description
|
||||
* Modify the address of a AF_UNIX sockaddr.
|
||||
* Returns__bpf_kfunc
|
||||
* -EINVAL if the address size is too big or, 0 if the sockaddr was successfully modified.
|
||||
*/
|
||||
extern int bpf_sock_addr_set_sun_path(struct bpf_sock_addr_kern *sa_kern,
|
||||
const __u8 *sun_path, __u32 sun_path__sz) __ksym;
|
||||
|
||||
void *bpf_cast_to_kern_ctx(void *) __ksym;
|
||||
|
||||
void *bpf_rdonly_cast(void *obj, __u32 btf_id) __ksym;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -199,6 +199,11 @@ int setup_cgroup_environment(void)
|
|||
|
||||
format_cgroup_path(cgroup_workdir, "");
|
||||
|
||||
if (mkdir(CGROUP_MOUNT_PATH, 0777) && errno != EEXIST) {
|
||||
log_err("mkdir mount");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unshare(CLONE_NEWNS)) {
|
||||
log_err("unshare");
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/in.h>
|
||||
|
|
@ -257,6 +258,26 @@ static int connect_fd_to_addr(int fd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int connect_to_addr(const struct sockaddr_storage *addr, socklen_t addrlen, int type)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = socket(addr->ss_family, type, 0);
|
||||
if (fd < 0) {
|
||||
log_err("Failed to create client socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect_fd_to_addr(fd, addr, addrlen, false))
|
||||
goto error_close;
|
||||
|
||||
return fd;
|
||||
|
||||
error_close:
|
||||
save_errno_close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const struct network_helper_opts default_opts;
|
||||
|
||||
int connect_to_fd_opts(int server_fd, const struct network_helper_opts *opts)
|
||||
|
|
@ -380,6 +401,19 @@ int make_sockaddr(int family, const char *addr_str, __u16 port,
|
|||
if (len)
|
||||
*len = sizeof(*sin6);
|
||||
return 0;
|
||||
} else if (family == AF_UNIX) {
|
||||
/* Note that we always use abstract unix sockets to avoid having
|
||||
* to clean up leftover files.
|
||||
*/
|
||||
struct sockaddr_un *sun = (void *)addr;
|
||||
|
||||
memset(addr, 0, sizeof(*sun));
|
||||
sun->sun_family = family;
|
||||
sun->sun_path[0] = 0;
|
||||
strcpy(sun->sun_path + 1, addr_str);
|
||||
if (len)
|
||||
*len = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(addr_str);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ int *start_reuseport_server(int family, int type, const char *addr_str,
|
|||
__u16 port, int timeout_ms,
|
||||
unsigned int nr_listens);
|
||||
void free_fds(int *fds, unsigned int nr_close_fds);
|
||||
int connect_to_addr(const struct sockaddr_storage *addr, socklen_t len, int type);
|
||||
int connect_to_fd(int server_fd, int timeout_ms);
|
||||
int connect_to_fd_opts(int server_fd, const struct network_helper_opts *opts);
|
||||
int connect_fd_to_fd(int client_fd, int server_fd, int timeout_ms);
|
||||
|
|
|
|||
|
|
@ -123,6 +123,11 @@ static struct sec_name_test tests[] = {
|
|||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_CONNECT},
|
||||
{0, BPF_CGROUP_INET6_CONNECT},
|
||||
},
|
||||
{
|
||||
"cgroup/connect_unix",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_CONNECT},
|
||||
{0, BPF_CGROUP_UNIX_CONNECT},
|
||||
},
|
||||
{
|
||||
"cgroup/sendmsg4",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_SENDMSG},
|
||||
|
|
@ -133,6 +138,11 @@ static struct sec_name_test tests[] = {
|
|||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG},
|
||||
{0, BPF_CGROUP_UDP6_SENDMSG},
|
||||
},
|
||||
{
|
||||
"cgroup/sendmsg_unix",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_SENDMSG},
|
||||
{0, BPF_CGROUP_UNIX_SENDMSG},
|
||||
},
|
||||
{
|
||||
"cgroup/recvmsg4",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_RECVMSG},
|
||||
|
|
@ -143,6 +153,11 @@ static struct sec_name_test tests[] = {
|
|||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_RECVMSG},
|
||||
{0, BPF_CGROUP_UDP6_RECVMSG},
|
||||
},
|
||||
{
|
||||
"cgroup/recvmsg_unix",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_RECVMSG},
|
||||
{0, BPF_CGROUP_UNIX_RECVMSG},
|
||||
},
|
||||
{
|
||||
"cgroup/sysctl",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL},
|
||||
|
|
@ -158,6 +173,36 @@ static struct sec_name_test tests[] = {
|
|||
{0, BPF_PROG_TYPE_CGROUP_SOCKOPT, BPF_CGROUP_SETSOCKOPT},
|
||||
{0, BPF_CGROUP_SETSOCKOPT},
|
||||
},
|
||||
{
|
||||
"cgroup/getpeername4",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_GETPEERNAME},
|
||||
{0, BPF_CGROUP_INET4_GETPEERNAME},
|
||||
},
|
||||
{
|
||||
"cgroup/getpeername6",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_GETPEERNAME},
|
||||
{0, BPF_CGROUP_INET6_GETPEERNAME},
|
||||
},
|
||||
{
|
||||
"cgroup/getpeername_unix",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_GETPEERNAME},
|
||||
{0, BPF_CGROUP_UNIX_GETPEERNAME},
|
||||
},
|
||||
{
|
||||
"cgroup/getsockname4",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_GETSOCKNAME},
|
||||
{0, BPF_CGROUP_INET4_GETSOCKNAME},
|
||||
},
|
||||
{
|
||||
"cgroup/getsockname6",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_GETSOCKNAME},
|
||||
{0, BPF_CGROUP_INET6_GETSOCKNAME},
|
||||
},
|
||||
{
|
||||
"cgroup/getsockname_unix",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_GETSOCKNAME},
|
||||
{0, BPF_CGROUP_UNIX_GETSOCKNAME},
|
||||
},
|
||||
};
|
||||
|
||||
static void test_prog_type_by_name(const struct sec_name_test *test)
|
||||
|
|
|
|||
612
tools/testing/selftests/bpf/prog_tests/sock_addr.c
Normal file
612
tools/testing/selftests/bpf/prog_tests/sock_addr.c
Normal file
|
|
@ -0,0 +1,612 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "test_progs.h"
|
||||
|
||||
#include "connect_unix_prog.skel.h"
|
||||
#include "sendmsg_unix_prog.skel.h"
|
||||
#include "recvmsg_unix_prog.skel.h"
|
||||
#include "getsockname_unix_prog.skel.h"
|
||||
#include "getpeername_unix_prog.skel.h"
|
||||
#include "network_helpers.h"
|
||||
|
||||
#define SERVUN_ADDRESS "bpf_cgroup_unix_test"
|
||||
#define SERVUN_REWRITE_ADDRESS "bpf_cgroup_unix_test_rewrite"
|
||||
#define SRCUN_ADDRESS "bpf_cgroup_unix_test_src"
|
||||
|
||||
enum sock_addr_test_type {
|
||||
SOCK_ADDR_TEST_BIND,
|
||||
SOCK_ADDR_TEST_CONNECT,
|
||||
SOCK_ADDR_TEST_SENDMSG,
|
||||
SOCK_ADDR_TEST_RECVMSG,
|
||||
SOCK_ADDR_TEST_GETSOCKNAME,
|
||||
SOCK_ADDR_TEST_GETPEERNAME,
|
||||
};
|
||||
|
||||
typedef void *(*load_fn)(int cgroup_fd);
|
||||
typedef void (*destroy_fn)(void *skel);
|
||||
|
||||
struct sock_addr_test {
|
||||
enum sock_addr_test_type type;
|
||||
const char *name;
|
||||
/* BPF prog properties */
|
||||
load_fn loadfn;
|
||||
destroy_fn destroyfn;
|
||||
/* Socket properties */
|
||||
int socket_family;
|
||||
int socket_type;
|
||||
/* IP:port pairs for BPF prog to override */
|
||||
const char *requested_addr;
|
||||
unsigned short requested_port;
|
||||
const char *expected_addr;
|
||||
unsigned short expected_port;
|
||||
const char *expected_src_addr;
|
||||
};
|
||||
|
||||
static void *connect_unix_prog_load(int cgroup_fd)
|
||||
{
|
||||
struct connect_unix_prog *skel;
|
||||
|
||||
skel = connect_unix_prog__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open"))
|
||||
goto cleanup;
|
||||
|
||||
skel->links.connect_unix_prog = bpf_program__attach_cgroup(
|
||||
skel->progs.connect_unix_prog, cgroup_fd);
|
||||
if (!ASSERT_OK_PTR(skel->links.connect_unix_prog, "prog_attach"))
|
||||
goto cleanup;
|
||||
|
||||
return skel;
|
||||
cleanup:
|
||||
connect_unix_prog__destroy(skel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void connect_unix_prog_destroy(void *skel)
|
||||
{
|
||||
connect_unix_prog__destroy(skel);
|
||||
}
|
||||
|
||||
static void *sendmsg_unix_prog_load(int cgroup_fd)
|
||||
{
|
||||
struct sendmsg_unix_prog *skel;
|
||||
|
||||
skel = sendmsg_unix_prog__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open"))
|
||||
goto cleanup;
|
||||
|
||||
skel->links.sendmsg_unix_prog = bpf_program__attach_cgroup(
|
||||
skel->progs.sendmsg_unix_prog, cgroup_fd);
|
||||
if (!ASSERT_OK_PTR(skel->links.sendmsg_unix_prog, "prog_attach"))
|
||||
goto cleanup;
|
||||
|
||||
return skel;
|
||||
cleanup:
|
||||
sendmsg_unix_prog__destroy(skel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sendmsg_unix_prog_destroy(void *skel)
|
||||
{
|
||||
sendmsg_unix_prog__destroy(skel);
|
||||
}
|
||||
|
||||
static void *recvmsg_unix_prog_load(int cgroup_fd)
|
||||
{
|
||||
struct recvmsg_unix_prog *skel;
|
||||
|
||||
skel = recvmsg_unix_prog__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open"))
|
||||
goto cleanup;
|
||||
|
||||
skel->links.recvmsg_unix_prog = bpf_program__attach_cgroup(
|
||||
skel->progs.recvmsg_unix_prog, cgroup_fd);
|
||||
if (!ASSERT_OK_PTR(skel->links.recvmsg_unix_prog, "prog_attach"))
|
||||
goto cleanup;
|
||||
|
||||
return skel;
|
||||
cleanup:
|
||||
recvmsg_unix_prog__destroy(skel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void recvmsg_unix_prog_destroy(void *skel)
|
||||
{
|
||||
recvmsg_unix_prog__destroy(skel);
|
||||
}
|
||||
|
||||
static void *getsockname_unix_prog_load(int cgroup_fd)
|
||||
{
|
||||
struct getsockname_unix_prog *skel;
|
||||
|
||||
skel = getsockname_unix_prog__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open"))
|
||||
goto cleanup;
|
||||
|
||||
skel->links.getsockname_unix_prog = bpf_program__attach_cgroup(
|
||||
skel->progs.getsockname_unix_prog, cgroup_fd);
|
||||
if (!ASSERT_OK_PTR(skel->links.getsockname_unix_prog, "prog_attach"))
|
||||
goto cleanup;
|
||||
|
||||
return skel;
|
||||
cleanup:
|
||||
getsockname_unix_prog__destroy(skel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void getsockname_unix_prog_destroy(void *skel)
|
||||
{
|
||||
getsockname_unix_prog__destroy(skel);
|
||||
}
|
||||
|
||||
static void *getpeername_unix_prog_load(int cgroup_fd)
|
||||
{
|
||||
struct getpeername_unix_prog *skel;
|
||||
|
||||
skel = getpeername_unix_prog__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open"))
|
||||
goto cleanup;
|
||||
|
||||
skel->links.getpeername_unix_prog = bpf_program__attach_cgroup(
|
||||
skel->progs.getpeername_unix_prog, cgroup_fd);
|
||||
if (!ASSERT_OK_PTR(skel->links.getpeername_unix_prog, "prog_attach"))
|
||||
goto cleanup;
|
||||
|
||||
return skel;
|
||||
cleanup:
|
||||
getpeername_unix_prog__destroy(skel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void getpeername_unix_prog_destroy(void *skel)
|
||||
{
|
||||
getpeername_unix_prog__destroy(skel);
|
||||
}
|
||||
|
||||
static struct sock_addr_test tests[] = {
|
||||
{
|
||||
SOCK_ADDR_TEST_CONNECT,
|
||||
"connect_unix",
|
||||
connect_unix_prog_load,
|
||||
connect_unix_prog_destroy,
|
||||
AF_UNIX,
|
||||
SOCK_STREAM,
|
||||
SERVUN_ADDRESS,
|
||||
0,
|
||||
SERVUN_REWRITE_ADDRESS,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
SOCK_ADDR_TEST_SENDMSG,
|
||||
"sendmsg_unix",
|
||||
sendmsg_unix_prog_load,
|
||||
sendmsg_unix_prog_destroy,
|
||||
AF_UNIX,
|
||||
SOCK_DGRAM,
|
||||
SERVUN_ADDRESS,
|
||||
0,
|
||||
SERVUN_REWRITE_ADDRESS,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
SOCK_ADDR_TEST_RECVMSG,
|
||||
"recvmsg_unix-dgram",
|
||||
recvmsg_unix_prog_load,
|
||||
recvmsg_unix_prog_destroy,
|
||||
AF_UNIX,
|
||||
SOCK_DGRAM,
|
||||
SERVUN_REWRITE_ADDRESS,
|
||||
0,
|
||||
SERVUN_REWRITE_ADDRESS,
|
||||
0,
|
||||
SERVUN_ADDRESS,
|
||||
},
|
||||
{
|
||||
SOCK_ADDR_TEST_RECVMSG,
|
||||
"recvmsg_unix-stream",
|
||||
recvmsg_unix_prog_load,
|
||||
recvmsg_unix_prog_destroy,
|
||||
AF_UNIX,
|
||||
SOCK_STREAM,
|
||||
SERVUN_REWRITE_ADDRESS,
|
||||
0,
|
||||
SERVUN_REWRITE_ADDRESS,
|
||||
0,
|
||||
SERVUN_ADDRESS,
|
||||
},
|
||||
{
|
||||
SOCK_ADDR_TEST_GETSOCKNAME,
|
||||
"getsockname_unix",
|
||||
getsockname_unix_prog_load,
|
||||
getsockname_unix_prog_destroy,
|
||||
AF_UNIX,
|
||||
SOCK_STREAM,
|
||||
SERVUN_ADDRESS,
|
||||
0,
|
||||
SERVUN_REWRITE_ADDRESS,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
SOCK_ADDR_TEST_GETPEERNAME,
|
||||
"getpeername_unix",
|
||||
getpeername_unix_prog_load,
|
||||
getpeername_unix_prog_destroy,
|
||||
AF_UNIX,
|
||||
SOCK_STREAM,
|
||||
SERVUN_ADDRESS,
|
||||
0,
|
||||
SERVUN_REWRITE_ADDRESS,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
||||
typedef int (*info_fn)(int, struct sockaddr *, socklen_t *);
|
||||
|
||||
static int cmp_addr(const struct sockaddr_storage *addr1, socklen_t addr1_len,
|
||||
const struct sockaddr_storage *addr2, socklen_t addr2_len,
|
||||
bool cmp_port)
|
||||
{
|
||||
const struct sockaddr_in *four1, *four2;
|
||||
const struct sockaddr_in6 *six1, *six2;
|
||||
const struct sockaddr_un *un1, *un2;
|
||||
|
||||
if (addr1->ss_family != addr2->ss_family)
|
||||
return -1;
|
||||
|
||||
if (addr1_len != addr2_len)
|
||||
return -1;
|
||||
|
||||
if (addr1->ss_family == AF_INET) {
|
||||
four1 = (const struct sockaddr_in *)addr1;
|
||||
four2 = (const struct sockaddr_in *)addr2;
|
||||
return !((four1->sin_port == four2->sin_port || !cmp_port) &&
|
||||
four1->sin_addr.s_addr == four2->sin_addr.s_addr);
|
||||
} else if (addr1->ss_family == AF_INET6) {
|
||||
six1 = (const struct sockaddr_in6 *)addr1;
|
||||
six2 = (const struct sockaddr_in6 *)addr2;
|
||||
return !((six1->sin6_port == six2->sin6_port || !cmp_port) &&
|
||||
!memcmp(&six1->sin6_addr, &six2->sin6_addr,
|
||||
sizeof(struct in6_addr)));
|
||||
} else if (addr1->ss_family == AF_UNIX) {
|
||||
un1 = (const struct sockaddr_un *)addr1;
|
||||
un2 = (const struct sockaddr_un *)addr2;
|
||||
return memcmp(un1, un2, addr1_len);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cmp_sock_addr(info_fn fn, int sock1,
|
||||
const struct sockaddr_storage *addr2,
|
||||
socklen_t addr2_len, bool cmp_port)
|
||||
{
|
||||
struct sockaddr_storage addr1;
|
||||
socklen_t len1 = sizeof(addr1);
|
||||
|
||||
memset(&addr1, 0, len1);
|
||||
if (fn(sock1, (struct sockaddr *)&addr1, (socklen_t *)&len1) != 0)
|
||||
return -1;
|
||||
|
||||
return cmp_addr(&addr1, len1, addr2, addr2_len, cmp_port);
|
||||
}
|
||||
|
||||
static int cmp_local_addr(int sock1, const struct sockaddr_storage *addr2,
|
||||
socklen_t addr2_len, bool cmp_port)
|
||||
{
|
||||
return cmp_sock_addr(getsockname, sock1, addr2, addr2_len, cmp_port);
|
||||
}
|
||||
|
||||
static int cmp_peer_addr(int sock1, const struct sockaddr_storage *addr2,
|
||||
socklen_t addr2_len, bool cmp_port)
|
||||
{
|
||||
return cmp_sock_addr(getpeername, sock1, addr2, addr2_len, cmp_port);
|
||||
}
|
||||
|
||||
static void test_bind(struct sock_addr_test *test)
|
||||
{
|
||||
struct sockaddr_storage expected_addr;
|
||||
socklen_t expected_addr_len = sizeof(struct sockaddr_storage);
|
||||
int serv = -1, client = -1, err;
|
||||
|
||||
serv = start_server(test->socket_family, test->socket_type,
|
||||
test->requested_addr, test->requested_port, 0);
|
||||
if (!ASSERT_GE(serv, 0, "start_server"))
|
||||
goto cleanup;
|
||||
|
||||
err = make_sockaddr(test->socket_family,
|
||||
test->expected_addr, test->expected_port,
|
||||
&expected_addr, &expected_addr_len);
|
||||
if (!ASSERT_EQ(err, 0, "make_sockaddr"))
|
||||
goto cleanup;
|
||||
|
||||
err = cmp_local_addr(serv, &expected_addr, expected_addr_len, true);
|
||||
if (!ASSERT_EQ(err, 0, "cmp_local_addr"))
|
||||
goto cleanup;
|
||||
|
||||
/* Try to connect to server just in case */
|
||||
client = connect_to_addr(&expected_addr, expected_addr_len, test->socket_type);
|
||||
if (!ASSERT_GE(client, 0, "connect_to_addr"))
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
if (client != -1)
|
||||
close(client);
|
||||
if (serv != -1)
|
||||
close(serv);
|
||||
}
|
||||
|
||||
static void test_connect(struct sock_addr_test *test)
|
||||
{
|
||||
struct sockaddr_storage addr, expected_addr, expected_src_addr;
|
||||
socklen_t addr_len = sizeof(struct sockaddr_storage),
|
||||
expected_addr_len = sizeof(struct sockaddr_storage),
|
||||
expected_src_addr_len = sizeof(struct sockaddr_storage);
|
||||
int serv = -1, client = -1, err;
|
||||
|
||||
serv = start_server(test->socket_family, test->socket_type,
|
||||
test->expected_addr, test->expected_port, 0);
|
||||
if (!ASSERT_GE(serv, 0, "start_server"))
|
||||
goto cleanup;
|
||||
|
||||
err = make_sockaddr(test->socket_family, test->requested_addr, test->requested_port,
|
||||
&addr, &addr_len);
|
||||
if (!ASSERT_EQ(err, 0, "make_sockaddr"))
|
||||
goto cleanup;
|
||||
|
||||
client = connect_to_addr(&addr, addr_len, test->socket_type);
|
||||
if (!ASSERT_GE(client, 0, "connect_to_addr"))
|
||||
goto cleanup;
|
||||
|
||||
err = make_sockaddr(test->socket_family, test->expected_addr, test->expected_port,
|
||||
&expected_addr, &expected_addr_len);
|
||||
if (!ASSERT_EQ(err, 0, "make_sockaddr"))
|
||||
goto cleanup;
|
||||
|
||||
if (test->expected_src_addr) {
|
||||
err = make_sockaddr(test->socket_family, test->expected_src_addr, 0,
|
||||
&expected_src_addr, &expected_src_addr_len);
|
||||
if (!ASSERT_EQ(err, 0, "make_sockaddr"))
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
err = cmp_peer_addr(client, &expected_addr, expected_addr_len, true);
|
||||
if (!ASSERT_EQ(err, 0, "cmp_peer_addr"))
|
||||
goto cleanup;
|
||||
|
||||
if (test->expected_src_addr) {
|
||||
err = cmp_local_addr(client, &expected_src_addr, expected_src_addr_len, false);
|
||||
if (!ASSERT_EQ(err, 0, "cmp_local_addr"))
|
||||
goto cleanup;
|
||||
}
|
||||
cleanup:
|
||||
if (client != -1)
|
||||
close(client);
|
||||
if (serv != -1)
|
||||
close(serv);
|
||||
}
|
||||
|
||||
static void test_xmsg(struct sock_addr_test *test)
|
||||
{
|
||||
struct sockaddr_storage addr, src_addr;
|
||||
socklen_t addr_len = sizeof(struct sockaddr_storage),
|
||||
src_addr_len = sizeof(struct sockaddr_storage);
|
||||
struct msghdr hdr;
|
||||
struct iovec iov;
|
||||
char data = 'a';
|
||||
int serv = -1, client = -1, err;
|
||||
|
||||
/* Unlike the other tests, here we test that we can rewrite the src addr
|
||||
* with a recvmsg() hook.
|
||||
*/
|
||||
|
||||
serv = start_server(test->socket_family, test->socket_type,
|
||||
test->expected_addr, test->expected_port, 0);
|
||||
if (!ASSERT_GE(serv, 0, "start_server"))
|
||||
goto cleanup;
|
||||
|
||||
client = socket(test->socket_family, test->socket_type, 0);
|
||||
if (!ASSERT_GE(client, 0, "socket"))
|
||||
goto cleanup;
|
||||
|
||||
/* AF_UNIX sockets have to be bound to something to trigger the recvmsg bpf program. */
|
||||
if (test->socket_family == AF_UNIX) {
|
||||
err = make_sockaddr(AF_UNIX, SRCUN_ADDRESS, 0, &src_addr, &src_addr_len);
|
||||
if (!ASSERT_EQ(err, 0, "make_sockaddr"))
|
||||
goto cleanup;
|
||||
|
||||
err = bind(client, (const struct sockaddr *) &src_addr, src_addr_len);
|
||||
if (!ASSERT_OK(err, "bind"))
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
err = make_sockaddr(test->socket_family, test->requested_addr, test->requested_port,
|
||||
&addr, &addr_len);
|
||||
if (!ASSERT_EQ(err, 0, "make_sockaddr"))
|
||||
goto cleanup;
|
||||
|
||||
if (test->socket_type == SOCK_DGRAM) {
|
||||
memset(&iov, 0, sizeof(iov));
|
||||
iov.iov_base = &data;
|
||||
iov.iov_len = sizeof(data);
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.msg_name = (void *)&addr;
|
||||
hdr.msg_namelen = addr_len;
|
||||
hdr.msg_iov = &iov;
|
||||
hdr.msg_iovlen = 1;
|
||||
|
||||
err = sendmsg(client, &hdr, 0);
|
||||
if (!ASSERT_EQ(err, sizeof(data), "sendmsg"))
|
||||
goto cleanup;
|
||||
} else {
|
||||
/* Testing with connection-oriented sockets is only valid for
|
||||
* recvmsg() tests.
|
||||
*/
|
||||
if (!ASSERT_EQ(test->type, SOCK_ADDR_TEST_RECVMSG, "recvmsg"))
|
||||
goto cleanup;
|
||||
|
||||
err = connect(client, (const struct sockaddr *)&addr, addr_len);
|
||||
if (!ASSERT_OK(err, "connect"))
|
||||
goto cleanup;
|
||||
|
||||
err = send(client, &data, sizeof(data), 0);
|
||||
if (!ASSERT_EQ(err, sizeof(data), "send"))
|
||||
goto cleanup;
|
||||
|
||||
err = listen(serv, 0);
|
||||
if (!ASSERT_OK(err, "listen"))
|
||||
goto cleanup;
|
||||
|
||||
err = accept(serv, NULL, NULL);
|
||||
if (!ASSERT_GE(err, 0, "accept"))
|
||||
goto cleanup;
|
||||
|
||||
close(serv);
|
||||
serv = err;
|
||||
}
|
||||
|
||||
addr_len = src_addr_len = sizeof(struct sockaddr_storage);
|
||||
|
||||
err = recvfrom(serv, &data, sizeof(data), 0, (struct sockaddr *) &src_addr, &src_addr_len);
|
||||
if (!ASSERT_EQ(err, sizeof(data), "recvfrom"))
|
||||
goto cleanup;
|
||||
|
||||
ASSERT_EQ(data, 'a', "data mismatch");
|
||||
|
||||
if (test->expected_src_addr) {
|
||||
err = make_sockaddr(test->socket_family, test->expected_src_addr, 0,
|
||||
&addr, &addr_len);
|
||||
if (!ASSERT_EQ(err, 0, "make_sockaddr"))
|
||||
goto cleanup;
|
||||
|
||||
err = cmp_addr(&src_addr, src_addr_len, &addr, addr_len, false);
|
||||
if (!ASSERT_EQ(err, 0, "cmp_addr"))
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (client != -1)
|
||||
close(client);
|
||||
if (serv != -1)
|
||||
close(serv);
|
||||
}
|
||||
|
||||
static void test_getsockname(struct sock_addr_test *test)
|
||||
{
|
||||
struct sockaddr_storage expected_addr;
|
||||
socklen_t expected_addr_len = sizeof(struct sockaddr_storage);
|
||||
int serv = -1, err;
|
||||
|
||||
serv = start_server(test->socket_family, test->socket_type,
|
||||
test->requested_addr, test->requested_port, 0);
|
||||
if (!ASSERT_GE(serv, 0, "start_server"))
|
||||
goto cleanup;
|
||||
|
||||
err = make_sockaddr(test->socket_family,
|
||||
test->expected_addr, test->expected_port,
|
||||
&expected_addr, &expected_addr_len);
|
||||
if (!ASSERT_EQ(err, 0, "make_sockaddr"))
|
||||
goto cleanup;
|
||||
|
||||
err = cmp_local_addr(serv, &expected_addr, expected_addr_len, true);
|
||||
if (!ASSERT_EQ(err, 0, "cmp_local_addr"))
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
if (serv != -1)
|
||||
close(serv);
|
||||
}
|
||||
|
||||
static void test_getpeername(struct sock_addr_test *test)
|
||||
{
|
||||
struct sockaddr_storage addr, expected_addr;
|
||||
socklen_t addr_len = sizeof(struct sockaddr_storage),
|
||||
expected_addr_len = sizeof(struct sockaddr_storage);
|
||||
int serv = -1, client = -1, err;
|
||||
|
||||
serv = start_server(test->socket_family, test->socket_type,
|
||||
test->requested_addr, test->requested_port, 0);
|
||||
if (!ASSERT_GE(serv, 0, "start_server"))
|
||||
goto cleanup;
|
||||
|
||||
err = make_sockaddr(test->socket_family, test->requested_addr, test->requested_port,
|
||||
&addr, &addr_len);
|
||||
if (!ASSERT_EQ(err, 0, "make_sockaddr"))
|
||||
goto cleanup;
|
||||
|
||||
client = connect_to_addr(&addr, addr_len, test->socket_type);
|
||||
if (!ASSERT_GE(client, 0, "connect_to_addr"))
|
||||
goto cleanup;
|
||||
|
||||
err = make_sockaddr(test->socket_family, test->expected_addr, test->expected_port,
|
||||
&expected_addr, &expected_addr_len);
|
||||
if (!ASSERT_EQ(err, 0, "make_sockaddr"))
|
||||
goto cleanup;
|
||||
|
||||
err = cmp_peer_addr(client, &expected_addr, expected_addr_len, true);
|
||||
if (!ASSERT_EQ(err, 0, "cmp_peer_addr"))
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
if (client != -1)
|
||||
close(client);
|
||||
if (serv != -1)
|
||||
close(serv);
|
||||
}
|
||||
|
||||
void test_sock_addr(void)
|
||||
{
|
||||
int cgroup_fd = -1;
|
||||
void *skel;
|
||||
|
||||
cgroup_fd = test__join_cgroup("/sock_addr");
|
||||
if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup"))
|
||||
goto cleanup;
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(tests); ++i) {
|
||||
struct sock_addr_test *test = &tests[i];
|
||||
|
||||
if (!test__start_subtest(test->name))
|
||||
continue;
|
||||
|
||||
skel = test->loadfn(cgroup_fd);
|
||||
if (!skel)
|
||||
continue;
|
||||
|
||||
switch (test->type) {
|
||||
/* Not exercised yet but we leave this code here for when the
|
||||
* INET and INET6 sockaddr tests are migrated to this file in
|
||||
* the future.
|
||||
*/
|
||||
case SOCK_ADDR_TEST_BIND:
|
||||
test_bind(test);
|
||||
break;
|
||||
case SOCK_ADDR_TEST_CONNECT:
|
||||
test_connect(test);
|
||||
break;
|
||||
case SOCK_ADDR_TEST_SENDMSG:
|
||||
case SOCK_ADDR_TEST_RECVMSG:
|
||||
test_xmsg(test);
|
||||
break;
|
||||
case SOCK_ADDR_TEST_GETSOCKNAME:
|
||||
test_getsockname(test);
|
||||
break;
|
||||
case SOCK_ADDR_TEST_GETPEERNAME:
|
||||
test_getpeername(test);
|
||||
break;
|
||||
default:
|
||||
ASSERT_TRUE(false, "Unknown sock addr test type");
|
||||
break;
|
||||
}
|
||||
|
||||
test->destroyfn(skel);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (cgroup_fd >= 0)
|
||||
close(cgroup_fd);
|
||||
}
|
||||
40
tools/testing/selftests/bpf/progs/connect_unix_prog.c
Normal file
40
tools/testing/selftests/bpf/progs/connect_unix_prog.c
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#include "vmlinux.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include "bpf_kfuncs.h"
|
||||
|
||||
__u8 SERVUN_REWRITE_ADDRESS[] = "\0bpf_cgroup_unix_test_rewrite";
|
||||
|
||||
SEC("cgroup/connect_unix")
|
||||
int connect_unix_prog(struct bpf_sock_addr *ctx)
|
||||
{
|
||||
struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
|
||||
struct sockaddr_un *sa_kern_unaddr;
|
||||
__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1;
|
||||
int ret;
|
||||
|
||||
/* Rewrite destination. */
|
||||
ret = bpf_sock_addr_set_sun_path(sa_kern, SERVUN_REWRITE_ADDRESS,
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
if (sa_kern->uaddrlen != unaddrlen)
|
||||
return 0;
|
||||
|
||||
sa_kern_unaddr = bpf_rdonly_cast(sa_kern->uaddr,
|
||||
bpf_core_type_id_kernel(struct sockaddr_un));
|
||||
if (memcmp(sa_kern_unaddr->sun_path, SERVUN_REWRITE_ADDRESS,
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1) != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
39
tools/testing/selftests/bpf/progs/getpeername_unix_prog.c
Normal file
39
tools/testing/selftests/bpf/progs/getpeername_unix_prog.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#include "vmlinux.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include "bpf_kfuncs.h"
|
||||
|
||||
__u8 SERVUN_REWRITE_ADDRESS[] = "\0bpf_cgroup_unix_test_rewrite";
|
||||
|
||||
SEC("cgroup/getpeername_unix")
|
||||
int getpeername_unix_prog(struct bpf_sock_addr *ctx)
|
||||
{
|
||||
struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
|
||||
struct sockaddr_un *sa_kern_unaddr;
|
||||
__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1;
|
||||
int ret;
|
||||
|
||||
ret = bpf_sock_addr_set_sun_path(sa_kern, SERVUN_REWRITE_ADDRESS,
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1);
|
||||
if (ret)
|
||||
return 1;
|
||||
|
||||
if (sa_kern->uaddrlen != unaddrlen)
|
||||
return 1;
|
||||
|
||||
sa_kern_unaddr = bpf_rdonly_cast(sa_kern->uaddr,
|
||||
bpf_core_type_id_kernel(struct sockaddr_un));
|
||||
if (memcmp(sa_kern_unaddr->sun_path, SERVUN_REWRITE_ADDRESS,
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1) != 0)
|
||||
return 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
39
tools/testing/selftests/bpf/progs/getsockname_unix_prog.c
Normal file
39
tools/testing/selftests/bpf/progs/getsockname_unix_prog.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#include "vmlinux.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include "bpf_kfuncs.h"
|
||||
|
||||
__u8 SERVUN_REWRITE_ADDRESS[] = "\0bpf_cgroup_unix_test_rewrite";
|
||||
|
||||
SEC("cgroup/getsockname_unix")
|
||||
int getsockname_unix_prog(struct bpf_sock_addr *ctx)
|
||||
{
|
||||
struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
|
||||
struct sockaddr_un *sa_kern_unaddr;
|
||||
__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1;
|
||||
int ret;
|
||||
|
||||
ret = bpf_sock_addr_set_sun_path(sa_kern, SERVUN_REWRITE_ADDRESS,
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1);
|
||||
if (ret)
|
||||
return 1;
|
||||
|
||||
if (sa_kern->uaddrlen != unaddrlen)
|
||||
return 1;
|
||||
|
||||
sa_kern_unaddr = bpf_rdonly_cast(sa_kern->uaddr,
|
||||
bpf_core_type_id_kernel(struct sockaddr_un));
|
||||
if (memcmp(sa_kern_unaddr->sun_path, SERVUN_REWRITE_ADDRESS,
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1) != 0)
|
||||
return 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
39
tools/testing/selftests/bpf/progs/recvmsg_unix_prog.c
Normal file
39
tools/testing/selftests/bpf/progs/recvmsg_unix_prog.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#include "vmlinux.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include "bpf_kfuncs.h"
|
||||
|
||||
__u8 SERVUN_ADDRESS[] = "\0bpf_cgroup_unix_test";
|
||||
|
||||
SEC("cgroup/recvmsg_unix")
|
||||
int recvmsg_unix_prog(struct bpf_sock_addr *ctx)
|
||||
{
|
||||
struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
|
||||
struct sockaddr_un *sa_kern_unaddr;
|
||||
__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
|
||||
sizeof(SERVUN_ADDRESS) - 1;
|
||||
int ret;
|
||||
|
||||
ret = bpf_sock_addr_set_sun_path(sa_kern, SERVUN_ADDRESS,
|
||||
sizeof(SERVUN_ADDRESS) - 1);
|
||||
if (ret)
|
||||
return 1;
|
||||
|
||||
if (sa_kern->uaddrlen != unaddrlen)
|
||||
return 1;
|
||||
|
||||
sa_kern_unaddr = bpf_rdonly_cast(sa_kern->uaddr,
|
||||
bpf_core_type_id_kernel(struct sockaddr_un));
|
||||
if (memcmp(sa_kern_unaddr->sun_path, SERVUN_ADDRESS,
|
||||
sizeof(SERVUN_ADDRESS) - 1) != 0)
|
||||
return 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
40
tools/testing/selftests/bpf/progs/sendmsg_unix_prog.c
Normal file
40
tools/testing/selftests/bpf/progs/sendmsg_unix_prog.c
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
|
||||
|
||||
#include "vmlinux.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include "bpf_kfuncs.h"
|
||||
|
||||
__u8 SERVUN_REWRITE_ADDRESS[] = "\0bpf_cgroup_unix_test_rewrite";
|
||||
|
||||
SEC("cgroup/sendmsg_unix")
|
||||
int sendmsg_unix_prog(struct bpf_sock_addr *ctx)
|
||||
{
|
||||
struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
|
||||
struct sockaddr_un *sa_kern_unaddr;
|
||||
__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1;
|
||||
int ret;
|
||||
|
||||
/* Rewrite destination. */
|
||||
ret = bpf_sock_addr_set_sun_path(sa_kern, SERVUN_REWRITE_ADDRESS,
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
if (sa_kern->uaddrlen != unaddrlen)
|
||||
return 0;
|
||||
|
||||
sa_kern_unaddr = bpf_rdonly_cast(sa_kern->uaddr,
|
||||
bpf_core_type_id_kernel(struct sockaddr_un));
|
||||
if (memcmp(sa_kern_unaddr->sun_path, SERVUN_REWRITE_ADDRESS,
|
||||
sizeof(SERVUN_REWRITE_ADDRESS) - 1) != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
Loading…
Reference in New Issue
Block a user