All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets
@ 2023-04-21 16:27 Daan De Meyer
  2023-04-21 16:27 ` [PATCH bpf-next v3 01/10] selftests/bpf: Add missing section name tests for getpeername/getsockname Daan De Meyer
                   ` (9 more replies)
  0 siblings, 10 replies; 25+ messages in thread
From: Daan De Meyer @ 2023-04-21 16:27 UTC (permalink / raw)
  To: bpf; +Cc: Daan De Meyer, martin.lau, kernel-team

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 and access the sockaddr via
CORE
* 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 is
extended to expose the unix socket path (sun_path) and the socket address
length to the bpf program. For unix sockets, the address length is writable,
for the other socket address hook types, the address length is only readable.

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.

Daan De Meyer (10):
  selftests/bpf: Add missing section name tests for
    getpeername/getsockname
  selftests/bpf: Track sockaddr length in sock addr tests
  bpf: Allow read access to addr_len from cgroup sockaddr programs
  bpf: Add BTF_KFUNC_HOOK_SOCK_ADDR
  bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf
  bpf: Implement cgroup sockaddr hooks for unix sockets
  libbpf: Add support for cgroup unix socket address hooks
  bpftool: Add support for cgroup unix socket address hooks
  selftests/bpf: Add tests for cgroup unix socket address hooks
  documentation/bpf: Document cgroup unix socket address hooks

 Documentation/bpf/libbpf/program_types.rst    |  12 +
 include/linux/bpf-cgroup-defs.h               |   6 +
 include/linux/bpf-cgroup.h                    | 102 ++++---
 include/linux/filter.h                        |   1 +
 include/uapi/linux/bpf.h                      |  14 +-
 kernel/bpf/btf.c                              |   3 +
 kernel/bpf/cgroup.c                           |  27 +-
 kernel/bpf/syscall.c                          |  18 ++
 kernel/bpf/verifier.c                         |   7 +-
 net/core/filter.c                             |  69 ++++-
 net/ipv4/af_inet.c                            |   8 +-
 net/ipv4/ping.c                               |   8 +-
 net/ipv4/tcp_ipv4.c                           |   8 +-
 net/ipv4/udp.c                                |  17 +-
 net/ipv6/af_inet6.c                           |   8 +-
 net/ipv6/ping.c                               |   8 +-
 net/ipv6/tcp_ipv6.c                           |   8 +-
 net/ipv6/udp.c                                |  14 +-
 net/unix/af_unix.c                            | 102 ++++++-
 .../bpftool/Documentation/bpftool-cgroup.rst  |  21 +-
 tools/bpf/bpftool/cgroup.c                    |  17 +-
 tools/bpf/bpftool/common.c                    |   6 +
 tools/include/uapi/linux/bpf.h                |  14 +-
 tools/lib/bpf/libbpf.c                        |  12 +
 tools/testing/selftests/bpf/bpf_kfuncs.h      |  13 +
 .../selftests/bpf/prog_tests/section_names.c  |  50 ++++
 .../testing/selftests/bpf/progs/bindun_prog.c |  59 ++++
 .../selftests/bpf/progs/connectun_prog.c      |  53 ++++
 .../selftests/bpf/progs/recvmsgun_prog.c      |  59 ++++
 .../selftests/bpf/progs/sendmsgun_prog.c      |  53 ++++
 tools/testing/selftests/bpf/test_sock_addr.c  | 263 ++++++++++++++----
 31 files changed, 917 insertions(+), 143 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/bindun_prog.c
 create mode 100644 tools/testing/selftests/bpf/progs/connectun_prog.c
 create mode 100644 tools/testing/selftests/bpf/progs/recvmsgun_prog.c
 create mode 100644 tools/testing/selftests/bpf/progs/sendmsgun_prog.c

--
2.40.0


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v3 01/10] selftests/bpf: Add missing section name tests for getpeername/getsockname
  2023-04-21 16:27 [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets Daan De Meyer
@ 2023-04-21 16:27 ` Daan De Meyer
  2023-04-21 16:27 ` [PATCH bpf-next v3 02/10] selftests/bpf: Track sockaddr length in sock addr tests Daan De Meyer
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 25+ messages in thread
From: Daan De Meyer @ 2023-04-21 16:27 UTC (permalink / raw)
  To: bpf; +Cc: Daan De Meyer, martin.lau, kernel-team

These were missed when these hooks were first added so add them now
instead to make sure every sockaddr hook has a matching section name
test.

Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
---
 .../selftests/bpf/prog_tests/section_names.c  | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/section_names.c b/tools/testing/selftests/bpf/prog_tests/section_names.c
index 8b571890c57e..fc5248e94a01 100644
--- a/tools/testing/selftests/bpf/prog_tests/section_names.c
+++ b/tools/testing/selftests/bpf/prog_tests/section_names.c
@@ -158,6 +158,26 @@ 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/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},
+	},
 };
 
 static void test_prog_type_by_name(const struct sec_name_test *test)
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v3 02/10] selftests/bpf: Track sockaddr length in sock addr tests
  2023-04-21 16:27 [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets Daan De Meyer
  2023-04-21 16:27 ` [PATCH bpf-next v3 01/10] selftests/bpf: Add missing section name tests for getpeername/getsockname Daan De Meyer
@ 2023-04-21 16:27 ` Daan De Meyer
  2023-04-21 16:27 ` [PATCH bpf-next v3 03/10] bpf: Allow read access to addr_len from cgroup sockaddr programs Daan De Meyer
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 25+ messages in thread
From: Daan De Meyer @ 2023-04-21 16:27 UTC (permalink / raw)
  To: bpf; +Cc: Daan De Meyer, martin.lau, kernel-team

In preparation for adding unix socket support to the bpf cgroup
socket address hooks, start tracking the sockaddr length in the
sockaddr tests which will be required when adding tests for unix
sockets.

Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
---
 tools/testing/selftests/bpf/test_sock_addr.c | 130 ++++++++++++-------
 1 file changed, 85 insertions(+), 45 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_sock_addr.c b/tools/testing/selftests/bpf/test_sock_addr.c
index 2c89674fc62c..6a618c8f477c 100644
--- a/tools/testing/selftests/bpf/test_sock_addr.c
+++ b/tools/testing/selftests/bpf/test_sock_addr.c
@@ -604,7 +604,7 @@ static struct sock_addr_test tests[] = {
 };
 
 static int mk_sockaddr(int domain, const char *ip, unsigned short port,
-		       struct sockaddr *addr, socklen_t addr_len)
+		       struct sockaddr *addr, socklen_t *addr_len)
 {
 	struct sockaddr_in6 *addr6;
 	struct sockaddr_in *addr4;
@@ -614,10 +614,10 @@ static int mk_sockaddr(int domain, const char *ip, unsigned short port,
 		return -1;
 	}
 
-	memset(addr, 0, addr_len);
+	memset(addr, 0, *addr_len);
 
 	if (domain == AF_INET) {
-		if (addr_len < sizeof(struct sockaddr_in))
+		if (*addr_len < sizeof(struct sockaddr_in))
 			return -1;
 		addr4 = (struct sockaddr_in *)addr;
 		addr4->sin_family = domain;
@@ -626,8 +626,9 @@ static int mk_sockaddr(int domain, const char *ip, unsigned short port,
 			log_err("Invalid IPv4: %s", ip);
 			return -1;
 		}
+		*addr_len = sizeof(struct sockaddr_in);
 	} else if (domain == AF_INET6) {
-		if (addr_len < sizeof(struct sockaddr_in6))
+		if (*addr_len < sizeof(struct sockaddr_in6))
 			return -1;
 		addr6 = (struct sockaddr_in6 *)addr;
 		addr6->sin6_family = domain;
@@ -636,6 +637,7 @@ static int mk_sockaddr(int domain, const char *ip, unsigned short port,
 			log_err("Invalid IPv6: %s", ip);
 			return -1;
 		}
+		*addr_len = sizeof(struct sockaddr_in6);
 	}
 
 	return 0;
@@ -749,6 +751,7 @@ static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
 {
 	struct sockaddr_in dst4_rw_addr;
 	struct in_addr src4_rw_ip;
+	socklen_t dst4_rw_addr_len = sizeof(dst4_rw_addr);
 
 	if (inet_pton(AF_INET, SRC4_REWRITE_IP, (void *)&src4_rw_ip) != 1) {
 		log_err("Invalid IPv4: %s", SRC4_REWRITE_IP);
@@ -757,7 +760,7 @@ static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
 
 	if (mk_sockaddr(AF_INET, SERV4_REWRITE_IP, SERV4_REWRITE_PORT,
 			(struct sockaddr *)&dst4_rw_addr,
-			sizeof(dst4_rw_addr)) == -1)
+			&dst4_rw_addr_len) == -1)
 		return -1;
 
 	struct bpf_insn insns[] = {
@@ -812,6 +815,7 @@ static int sendmsg6_rw_dst_asm_prog_load(const struct sock_addr_test *test,
 {
 	struct sockaddr_in6 dst6_rw_addr;
 	struct in6_addr src6_rw_ip;
+	socklen_t dst6_rw_addr_len = sizeof(dst6_rw_addr);
 
 	if (inet_pton(AF_INET6, SRC6_REWRITE_IP, (void *)&src6_rw_ip) != 1) {
 		log_err("Invalid IPv6: %s", SRC6_REWRITE_IP);
@@ -820,7 +824,7 @@ static int sendmsg6_rw_dst_asm_prog_load(const struct sock_addr_test *test,
 
 	if (mk_sockaddr(AF_INET6, rw_dst_ip, SERV6_REWRITE_PORT,
 			(struct sockaddr *)&dst6_rw_addr,
-			sizeof(dst6_rw_addr)) == -1)
+			&dst6_rw_addr_len) == -1)
 		return -1;
 
 	struct bpf_insn insns[] = {
@@ -885,8 +889,9 @@ static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test)
 	return load_path(test, SENDMSG6_PROG_PATH);
 }
 
-static int cmp_addr(const struct sockaddr_storage *addr1,
-		    const struct sockaddr_storage *addr2, int cmp_port)
+static int cmp_addr(const struct sockaddr_storage *addr1, socklen_t addr1_len,
+		    const struct sockaddr_storage *addr2, socklen_t addr2_len,
+		    int cmp_port)
 {
 	const struct sockaddr_in *four1, *four2;
 	const struct sockaddr_in6 *six1, *six2;
@@ -894,6 +899,9 @@ static int cmp_addr(const struct sockaddr_storage *addr1,
 	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;
@@ -911,7 +919,8 @@ static int cmp_addr(const struct sockaddr_storage *addr1,
 }
 
 static int cmp_sock_addr(info_fn fn, int sock1,
-			 const struct sockaddr_storage *addr2, int cmp_port)
+			 const struct sockaddr_storage *addr2,
+			 socklen_t addr2_len, int cmp_port)
 {
 	struct sockaddr_storage addr1;
 	socklen_t len1 = sizeof(addr1);
@@ -920,22 +929,28 @@ static int cmp_sock_addr(info_fn fn, int sock1,
 	if (fn(sock1, (struct sockaddr *)&addr1, (socklen_t *)&len1) != 0)
 		return -1;
 
-	return cmp_addr(&addr1, addr2, cmp_port);
+	return cmp_addr(&addr1, len1, addr2, addr2_len, cmp_port);
 }
 
-static int cmp_local_ip(int sock1, const struct sockaddr_storage *addr2)
+static int cmp_local_ip(int sock1, const struct sockaddr_storage *addr2,
+			socklen_t addr2_len)
 {
-	return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 0);
+	return cmp_sock_addr(getsockname, sock1, addr2, addr2_len,
+			     /*cmp_port*/ 0);
 }
 
-static int cmp_local_addr(int sock1, const struct sockaddr_storage *addr2)
+static int cmp_local_addr(int sock1, const struct sockaddr_storage *addr2,
+			  socklen_t addr2_len)
 {
-	return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 1);
+	return cmp_sock_addr(getsockname, sock1, addr2, addr2_len,
+			     /*cmp_port*/ 1);
 }
 
-static int cmp_peer_addr(int sock1, const struct sockaddr_storage *addr2)
+static int cmp_peer_addr(int sock1, const struct sockaddr_storage *addr2,
+			 socklen_t addr2_len)
 {
-	return cmp_sock_addr(getpeername, sock1, addr2, /*cmp_port*/ 1);
+	return cmp_sock_addr(getpeername, sock1, addr2, addr2_len,
+			     /*cmp_port*/ 1);
 }
 
 static int start_server(int type, const struct sockaddr_storage *addr,
@@ -1109,7 +1124,8 @@ static int fastconnect_to_server(const struct sockaddr_storage *addr,
 				 MSG_FASTOPEN, &sendmsg_err);
 }
 
-static int recvmsg_from_client(int sockfd, struct sockaddr_storage *src_addr)
+static int recvmsg_from_client(int sockfd, struct sockaddr_storage *src_addr,
+			       socklen_t *src_addr_len)
 {
 	struct timeval tv;
 	struct msghdr hdr;
@@ -1133,31 +1149,39 @@ static int recvmsg_from_client(int sockfd, struct sockaddr_storage *src_addr)
 
 	memset(&hdr, 0, sizeof(hdr));
 	hdr.msg_name = src_addr;
-	hdr.msg_namelen = sizeof(struct sockaddr_storage);
+	hdr.msg_namelen = *src_addr_len;
 	hdr.msg_iov = &iov;
 	hdr.msg_iovlen = 1;
 
-	return recvmsg(sockfd, &hdr, 0);
+	if (recvmsg(sockfd, &hdr, 0) < 0)
+		return -1;
+
+	*src_addr_len = hdr.msg_namelen;
+	return 0;
 }
 
 static int init_addrs(const struct sock_addr_test *test,
 		      struct sockaddr_storage *requested_addr,
+		      socklen_t *requested_addr_len,
 		      struct sockaddr_storage *expected_addr,
-		      struct sockaddr_storage *expected_src_addr)
+		      socklen_t *expected_addr_len,
+		      struct sockaddr_storage *expected_src_addr,
+		      socklen_t *expected_src_addr_len)
 {
-	socklen_t addr_len = sizeof(struct sockaddr_storage);
-
 	if (mk_sockaddr(test->domain, test->expected_ip, test->expected_port,
-			(struct sockaddr *)expected_addr, addr_len) == -1)
+			(struct sockaddr *)expected_addr,
+			expected_addr_len) == -1)
 		goto err;
 
 	if (mk_sockaddr(test->domain, test->requested_ip, test->requested_port,
-			(struct sockaddr *)requested_addr, addr_len) == -1)
+			(struct sockaddr *)requested_addr,
+			requested_addr_len) == -1)
 		goto err;
 
 	if (test->expected_src_ip &&
 	    mk_sockaddr(test->domain, test->expected_src_ip, 0,
-			(struct sockaddr *)expected_src_addr, addr_len) == -1)
+			(struct sockaddr *)expected_src_addr,
+			expected_src_addr_len) == -1)
 		goto err;
 
 	return 0;
@@ -1167,25 +1191,28 @@ static int init_addrs(const struct sock_addr_test *test,
 
 static int run_bind_test_case(const struct sock_addr_test *test)
 {
-	socklen_t addr_len = sizeof(struct sockaddr_storage);
 	struct sockaddr_storage requested_addr;
 	struct sockaddr_storage expected_addr;
+	socklen_t requested_addr_len = sizeof(struct sockaddr_storage);
+	socklen_t expected_addr_len = sizeof(struct sockaddr_storage);
 	int clientfd = -1;
 	int servfd = -1;
 	int err = 0;
 
-	if (init_addrs(test, &requested_addr, &expected_addr, NULL))
+	if (init_addrs(test, &requested_addr, &requested_addr_len,
+		       &expected_addr, &expected_addr_len, NULL, NULL))
 		goto err;
 
-	servfd = start_server(test->type, &requested_addr, addr_len);
+	servfd = start_server(test->type, &requested_addr, requested_addr_len);
 	if (servfd == -1)
 		goto err;
 
-	if (cmp_local_addr(servfd, &expected_addr))
+	if (cmp_local_addr(servfd, &expected_addr, expected_addr_len))
 		goto err;
 
 	/* Try to connect to server just in case */
-	clientfd = connect_to_server(test->type, &expected_addr, addr_len);
+	clientfd = connect_to_server(test->type, &expected_addr,
+				     expected_addr_len);
 	if (clientfd == -1)
 		goto err;
 
@@ -1204,28 +1231,33 @@ static int run_connect_test_case(const struct sock_addr_test *test)
 	struct sockaddr_storage expected_src_addr;
 	struct sockaddr_storage requested_addr;
 	struct sockaddr_storage expected_addr;
+	socklen_t expected_src_addr_len = sizeof(struct sockaddr_storage);
+	socklen_t requested_addr_len = sizeof(struct sockaddr_storage);
+	socklen_t expected_addr_len = sizeof(struct sockaddr_storage);
 	int clientfd = -1;
 	int servfd = -1;
 	int err = 0;
 
-	if (init_addrs(test, &requested_addr, &expected_addr,
-		       &expected_src_addr))
+	if (init_addrs(test, &requested_addr, &requested_addr_len,
+		       &expected_addr, &expected_addr_len, &expected_src_addr,
+		       &expected_src_addr_len))
 		goto err;
 
 	/* Prepare server to connect to */
-	servfd = start_server(test->type, &expected_addr, addr_len);
+	servfd = start_server(test->type, &expected_addr, expected_addr_len);
 	if (servfd == -1)
 		goto err;
 
-	clientfd = connect_to_server(test->type, &requested_addr, addr_len);
+	clientfd = connect_to_server(test->type, &requested_addr,
+				     requested_addr_len);
 	if (clientfd == -1)
 		goto err;
 
 	/* Make sure src and dst addrs were overridden properly */
-	if (cmp_peer_addr(clientfd, &expected_addr))
+	if (cmp_peer_addr(clientfd, &expected_addr, expected_addr_len))
 		goto err;
 
-	if (cmp_local_ip(clientfd, &expected_src_addr))
+	if (cmp_local_ip(clientfd, &expected_src_addr, expected_src_addr_len))
 		goto err;
 
 	if (test->type == SOCK_STREAM) {
@@ -1235,10 +1267,11 @@ static int run_connect_test_case(const struct sock_addr_test *test)
 			goto err;
 
 		/* Make sure src and dst addrs were overridden properly */
-		if (cmp_peer_addr(clientfd, &expected_addr))
+		if (cmp_peer_addr(clientfd, &expected_addr, expected_addr_len))
 			goto err;
 
-		if (cmp_local_ip(clientfd, &expected_src_addr))
+		if (cmp_local_ip(clientfd, &expected_src_addr,
+				 expected_src_addr_len))
 			goto err;
 	}
 
@@ -1253,11 +1286,14 @@ static int run_connect_test_case(const struct sock_addr_test *test)
 
 static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
 {
-	socklen_t addr_len = sizeof(struct sockaddr_storage);
 	struct sockaddr_storage expected_addr;
 	struct sockaddr_storage server_addr;
 	struct sockaddr_storage sendmsg_addr;
 	struct sockaddr_storage recvmsg_addr;
+	socklen_t expected_addr_len = sizeof(struct sockaddr_storage);
+	socklen_t server_addr_len = sizeof(struct sockaddr_storage);
+	socklen_t sendmsg_addr_len = sizeof(struct sockaddr_storage);
+	socklen_t recvmsg_addr_len = sizeof(struct sockaddr_storage);
 	int clientfd = -1;
 	int servfd = -1;
 	int set_cmsg;
@@ -1266,11 +1302,12 @@ static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
 	if (test->type != SOCK_DGRAM)
 		goto err;
 
-	if (init_addrs(test, &sendmsg_addr, &server_addr, &expected_addr))
+	if (init_addrs(test, &sendmsg_addr, &sendmsg_addr_len, &server_addr,
+		       &server_addr_len, &expected_addr, &expected_addr_len))
 		goto err;
 
 	/* Prepare server to sendmsg to */
-	servfd = start_server(test->type, &server_addr, addr_len);
+	servfd = start_server(test->type, &server_addr, server_addr_len);
 	if (servfd == -1)
 		goto err;
 
@@ -1279,8 +1316,8 @@ static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
 			close(clientfd);
 
 		clientfd = sendmsg_to_server(test->type, &sendmsg_addr,
-					     addr_len, set_cmsg, /*flags*/0,
-					     &err);
+					     sendmsg_addr_len, set_cmsg,
+					     /*flags*/ 0, &err);
 		if (err)
 			goto out;
 		else if (clientfd == -1)
@@ -1298,10 +1335,13 @@ static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
 		 * specific packet may differ from the one used by default and
 		 * returned by getsockname(2).
 		 */
-		if (recvmsg_from_client(servfd, &recvmsg_addr) == -1)
+		if (recvmsg_from_client(servfd, &recvmsg_addr,
+					&recvmsg_addr_len) == -1)
 			goto err;
 
-		if (cmp_addr(&recvmsg_addr, &expected_addr, /*cmp_port*/0))
+		if (cmp_addr(&recvmsg_addr, recvmsg_addr_len, &expected_addr,
+			     expected_addr_len,
+			     /*cmp_port*/ 0))
 			goto err;
 	}
 
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v3 03/10] bpf: Allow read access to addr_len from cgroup sockaddr programs
  2023-04-21 16:27 [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets Daan De Meyer
  2023-04-21 16:27 ` [PATCH bpf-next v3 01/10] selftests/bpf: Add missing section name tests for getpeername/getsockname Daan De Meyer
  2023-04-21 16:27 ` [PATCH bpf-next v3 02/10] selftests/bpf: Track sockaddr length in sock addr tests Daan De Meyer
@ 2023-04-21 16:27 ` Daan De Meyer
  2023-04-21 20:55   ` Alexei Starovoitov
  2023-04-26 22:07   ` Martin KaFai Lau
  2023-04-21 16:27 ` [PATCH bpf-next v3 04/10] bpf: Add BTF_KFUNC_HOOK_SOCK_ADDR Daan De Meyer
                   ` (6 subsequent siblings)
  9 siblings, 2 replies; 25+ messages in thread
From: Daan De Meyer @ 2023-04-21 16:27 UTC (permalink / raw)
  To: bpf; +Cc: Daan De Meyer, martin.lau, kernel-team

As prep for adding unix socket support to the cgroup sockaddr hooks,
let's expose the sockaddr addrlen in bpf_sock_addr_kern. While not
important for AF_INET or AF_INET6, the sockaddr length is important
when working with AF_UNIX sockaddrs as the size of the sockaddr cannot
be determined just from the address family or the sockaddr's contents.

__cgroup_bpf_run_filter_sock_addr() is modified to return the addr_len
in preparation for adding unix socket support for which we'll need to
return the modified address length.

Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
---
 include/linux/bpf-cgroup.h | 73 +++++++++++++++++++-------------------
 include/linux/filter.h     |  1 +
 kernel/bpf/cgroup.c        | 16 +++++++--
 net/ipv4/af_inet.c         |  8 ++---
 net/ipv4/ping.c            |  8 ++++-
 net/ipv4/tcp_ipv4.c        |  8 ++++-
 net/ipv4/udp.c             | 17 ++++++---
 net/ipv6/af_inet6.c        |  8 ++---
 net/ipv6/ping.c            |  8 ++++-
 net/ipv6/tcp_ipv6.c        |  8 ++++-
 net/ipv6/udp.c             | 14 ++++++--
 11 files changed, 111 insertions(+), 58 deletions(-)

diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
index 57e9e109257e..f3f5adf3881f 100644
--- a/include/linux/bpf-cgroup.h
+++ b/include/linux/bpf-cgroup.h
@@ -120,6 +120,7 @@ int __cgroup_bpf_run_filter_sk(struct sock *sk,
 
 int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
 				      struct sockaddr *uaddr,
+				      u32 uaddrlen,
 				      enum cgroup_bpf_attach_type atype,
 				      void *t_ctx,
 				      u32 *flags);
@@ -230,22 +231,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 +257,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 +277,29 @@ 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_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_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_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_UDP4_RECVMSG_LOCK(sk, uaddr)			\
-	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_UDP4_RECVMSG, NULL)
+#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)			\
-	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, CGROUP_UDP6_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)
 
 /* 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 +478,24 @@ 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_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_UDP4_RECVMSG_LOCK(sk, uaddr, uaddrlen) ({ 0; })
+#define BPF_CGROUP_RUN_PROG_UDP6_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; })
diff --git a/include/linux/filter.h b/include/linux/filter.h
index bbce89937fde..89e891003c03 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -1294,6 +1294,7 @@ struct bpf_sock_addr_kern {
 	 */
 	u64 tmp_reg;
 	void *t_ctx;	/* Attach type specific context. */
+	u32 uaddrlen;
 };
 
 struct bpf_sock_ops_kern {
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index 53edb8ad2471..c2191f0e138e 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -1449,6 +1449,7 @@ 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: Size of the sockaddr struct provided by user
  * @type: 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
@@ -1457,10 +1458,12 @@ EXPORT_SYMBOL(__cgroup_bpf_run_filter_sk);
  * socket is expected to be of type INET or INET6.
  *
  * This function will return %-EPERM if an attached program is found and
- * returned value != 1 during execution. In all other cases, 0 is returned.
+ * returned value != 1 during execution. In all other cases, the new address
+ * length of the sockaddr is returned.
  */
 int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
 				      struct sockaddr *uaddr,
+				      u32 uaddrlen,
 				      enum cgroup_bpf_attach_type atype,
 				      void *t_ctx,
 				      u32 *flags)
@@ -1469,9 +1472,11 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
 		.sk = sk,
 		.uaddr = uaddr,
 		.t_ctx = t_ctx,
+		.uaddrlen = uaddrlen,
 	};
 	struct sockaddr_storage unspec;
 	struct cgroup *cgrp;
+	int ret;
 
 	/* Check socket family since not all sockets represent network
 	 * endpoint (e.g. AF_UNIX).
@@ -1482,11 +1487,16 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
 	if (!ctx.uaddr) {
 		memset(&unspec, 0, sizeof(unspec));
 		ctx.uaddr = (struct sockaddr *)&unspec;
+		ctx.uaddrlen = sizeof(unspec);
 	}
 
 	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)
+		return ret;
+
+	return (int) ctx.uaddrlen;
 }
 EXPORT_SYMBOL(__cgroup_bpf_run_filter_sock_addr);
 
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 940062e08f57..6b3e5d77d354 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -446,9 +446,9 @@ int inet_bind(struct socket *sock, 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)
+	if (err < 0)
 		return err;
 
 	return __inet_bind(sk, uaddr, addr_len, flags);
@@ -785,7 +785,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, sizeof(*sin),
 				       CGROUP_INET4_GETPEERNAME);
 	} else {
 		__be32 addr = inet->inet_rcv_saddr;
@@ -793,7 +793,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, sizeof(*sin),
 				       CGROUP_INET4_GETSOCKNAME);
 	}
 	release_sock(sk);
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 5178a3f3cb53..9192cf5cd3ef 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -304,6 +304,8 @@ EXPORT_SYMBOL_GPL(ping_close);
 static int ping_pre_connect(struct sock *sk, struct sockaddr *uaddr,
 			    int addr_len)
 {
+	int err;
+
 	/* This check is replicated from __ip4_datagram_connect() and
 	 * intended to prevent BPF program called below from accessing bytes
 	 * that are out of the bound specified by user in addr_len.
@@ -311,7 +313,11 @@ 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);
+	err = BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr, addr_len);
+	if (err < 0)
+		return err;
+
+	return 0;
 }
 
 /* Checks the bind address and possibly modifies sk->sk_bound_dev_if. */
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 39bda2b1066e..50fed4e1820d 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -184,6 +184,8 @@ EXPORT_SYMBOL_GPL(tcp_twsk_unique);
 static int tcp_v4_pre_connect(struct sock *sk, struct sockaddr *uaddr,
 			      int addr_len)
 {
+	int err;
+
 	/* This check is replicated from tcp_v4_connect() and intended to
 	 * prevent BPF program called below from accessing bytes that are out
 	 * of the bound specified by user in addr_len.
@@ -193,7 +195,11 @@ 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);
+	err = BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr, addr_len);
+	if (err < 0)
+		return err;
+
+	return 0;
 }
 
 /* This will initiate an outgoing connection. */
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index aa32afd871ee..8f4b64252b51 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1157,8 +1157,10 @@ 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);
-		if (err)
+					    (struct sockaddr *)usin,
+					    msg->msg_namelen,
+					    &ipc.addr);
+		if (err < 0)
 			goto out_free;
 		if (usin) {
 			if (usin->sin_port == 0) {
@@ -1927,7 +1929,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_sk(sk)->gro_enabled)
@@ -1959,6 +1962,8 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
 
 int udp_pre_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
+	int err;
+
 	/* This check is replicated from __ip4_datagram_connect() and
 	 * intended to prevent BPF program called below from accessing bytes
 	 * that are out of the bound specified by user in addr_len.
@@ -1966,7 +1971,11 @@ 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);
+	err = BPF_CGROUP_RUN_PROG_INET4_CONNECT_LOCK(sk, uaddr, addr_len);
+	if (err < 0)
+		return err;
+
+	return 0;
 }
 EXPORT_SYMBOL(udp_pre_connect);
 
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e1b679a590c9..acba6a47ae44 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -455,9 +455,9 @@ int inet6_bind(struct socket *sock, 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)
+	if (err < 0)
 		return err;
 
 	return __inet6_bind(sk, uaddr, addr_len, flags);
@@ -534,7 +534,7 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
 		sin->sin6_addr = sk->sk_v6_daddr;
 		if (np->sndflow)
 			sin->sin6_flowinfo = np->flow_label;
-		BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin,
+		BPF_CGROUP_RUN_SA_PROG(sk, (struct sockaddr *)sin, sizeof(*sin),
 				       CGROUP_INET6_GETPEERNAME);
 	} else {
 		if (ipv6_addr_any(&sk->sk_v6_rcv_saddr))
@@ -542,7 +542,7 @@ 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, sizeof(*sin),
 				       CGROUP_INET6_GETSOCKNAME);
 	}
 	sin->sin6_scope_id = ipv6_iface_scope_id(&sin->sin6_addr,
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index c4835dbdfcff..d3630cad2c21 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -48,6 +48,8 @@ static int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
 static int ping_v6_pre_connect(struct sock *sk, struct sockaddr *uaddr,
 			       int addr_len)
 {
+	int err;
+
 	/* This check is replicated from __ip6_datagram_connect() and
 	 * intended to prevent BPF program called below from accessing
 	 * bytes that are out of the bound specified by user in addr_len.
@@ -56,7 +58,11 @@ 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);
+	err = BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr, addr_len);
+	if (err < 0)
+		return err;
+
+	return 0;
 }
 
 static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 244cf86c4cbb..a59db6b3e41f 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -130,6 +130,8 @@ static u32 tcp_v6_init_ts_off(const struct net *net, const struct sk_buff *skb)
 static int tcp_v6_pre_connect(struct sock *sk, struct sockaddr *uaddr,
 			      int addr_len)
 {
+	int err;
+
 	/* This check is replicated from tcp_v6_connect() and intended to
 	 * prevent BPF program called below from accessing bytes that are out
 	 * of the bound specified by user in addr_len.
@@ -139,7 +141,11 @@ 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);
+	err = BPF_CGROUP_RUN_PROG_INET6_CONNECT(sk, uaddr, addr_len);
+	if (err < 0)
+		return err;
+
+	return 0;
 }
 
 static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index e5a337e6b970..bc6c9a5586bf 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -429,7 +429,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_sk(sk)->gro_enabled)
@@ -1154,6 +1155,8 @@ static void udp_v6_flush_pending_frames(struct sock *sk)
 static int udpv6_pre_connect(struct sock *sk, struct sockaddr *uaddr,
 			     int addr_len)
 {
+	int err;
+
 	if (addr_len < offsetofend(struct sockaddr, sa_family))
 		return -EINVAL;
 	/* The following checks are replicated from __ip6_datagram_connect()
@@ -1169,7 +1172,11 @@ 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);
+	err = BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr, addr_len);
+	if (err < 0)
+		return err;
+
+	return 0;
 }
 
 /**
@@ -1522,8 +1529,9 @@ 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,
+					   msg->msg_namelen,
 					   &fl6->saddr);
-		if (err)
+		if (err < 0)
 			goto out_no_dst;
 		if (sin6) {
 			if (ipv6_addr_v4mapped(&sin6->sin6_addr)) {
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v3 04/10] bpf: Add BTF_KFUNC_HOOK_SOCK_ADDR
  2023-04-21 16:27 [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets Daan De Meyer
                   ` (2 preceding siblings ...)
  2023-04-21 16:27 ` [PATCH bpf-next v3 03/10] bpf: Allow read access to addr_len from cgroup sockaddr programs Daan De Meyer
@ 2023-04-21 16:27 ` Daan De Meyer
  2023-04-26 21:35   ` Martin KaFai Lau
  2023-04-21 16:27 ` [PATCH bpf-next v3 05/10] bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf Daan De Meyer
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 25+ messages in thread
From: Daan De Meyer @ 2023-04-21 16:27 UTC (permalink / raw)
  To: bpf; +Cc: Daan De Meyer, martin.lau, kernel-team

In preparation for adding a sock addr specific kfunc, let's add the
necessary hook for it.

Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
---
 kernel/bpf/btf.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index a0887ee44e89..1ec9a8590c72 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -212,6 +212,7 @@ enum btf_kfunc_hook {
 	BTF_KFUNC_HOOK_SK_SKB,
 	BTF_KFUNC_HOOK_SOCKET_FILTER,
 	BTF_KFUNC_HOOK_LWT,
+	BTF_KFUNC_HOOK_SOCK_ADDR,
 	BTF_KFUNC_HOOK_MAX,
 };
 
@@ -7802,6 +7803,8 @@ static int bpf_prog_type_to_kfunc_hook(enum bpf_prog_type prog_type)
 	case BPF_PROG_TYPE_LWT_XMIT:
 	case BPF_PROG_TYPE_LWT_SEG6LOCAL:
 		return BTF_KFUNC_HOOK_LWT;
+	case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
+		return BTF_KFUNC_HOOK_SOCK_ADDR;
 	default:
 		return BTF_KFUNC_HOOK_MAX;
 	}
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v3 05/10] bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf
  2023-04-21 16:27 [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets Daan De Meyer
                   ` (3 preceding siblings ...)
  2023-04-21 16:27 ` [PATCH bpf-next v3 04/10] bpf: Add BTF_KFUNC_HOOK_SOCK_ADDR Daan De Meyer
@ 2023-04-21 16:27 ` Daan De Meyer
  2023-04-21 21:01   ` Alexei Starovoitov
  2023-04-26 21:30   ` Martin KaFai Lau
  2023-04-21 16:27 ` [PATCH bpf-next v3 06/10] bpf: Implement cgroup sockaddr hooks for unix sockets Daan De Meyer
                   ` (4 subsequent siblings)
  9 siblings, 2 replies; 25+ messages in thread
From: Daan De Meyer @ 2023-04-21 16:27 UTC (permalink / raw)
  To: bpf; +Cc: Daan De Meyer, martin.lau, kernel-team

As prep for adding unix socket support to the cgroup sockaddr hooks,
let's add a kfunc bpf_sock_addr_set() that allows modifying the
sockaddr length from bpf. This is required to allow modifying AF_UNIX
sockaddrs correctly.

Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
---
 net/core/filter.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/net/core/filter.c b/net/core/filter.c
index 44fb997434ad..1c656e2d7b58 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -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);
@@ -11670,6 +11671,44 @@ __bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_buff *xdp, u64 flags,
 
 	return 0;
 }
+
+__bpf_kfunc int bpf_sock_addr_set(struct bpf_sock_addr_kern *sa_kern,
+				  const void *addr, u32 addrlen__sz)
+{
+	const struct sockaddr *sa = addr;
+
+	if (addrlen__sz <= offsetof(struct sockaddr, sa_family))
+		return -EINVAL;
+
+	if (addrlen__sz > sizeof(struct sockaddr_storage))
+		return -EINVAL;
+
+	if (sa->sa_family != sa_kern->uaddr->sa_family)
+		return -EINVAL;
+
+	switch (sa->sa_family) {
+	case AF_INET:
+		if (addrlen__sz < sizeof(struct sockaddr_in))
+			return -EINVAL;
+		break;
+	case AF_INET6:
+		if (addrlen__sz < SIN6_LEN_RFC2133)
+			return -EINVAL;
+		break;
+	case AF_UNIX:
+		if (addrlen__sz <= offsetof(struct sockaddr_un, sun_path) ||
+		    addrlen__sz > sizeof(struct sockaddr_un))
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	memcpy(sa_kern->uaddr, sa, addrlen__sz);
+	sa_kern->uaddrlen = addrlen__sz;
+
+	return 0;
+}
 __diag_pop();
 
 int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags,
@@ -11694,6 +11733,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)
+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,
@@ -11704,6 +11747,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;
@@ -11717,6 +11765,8 @@ static int __init bpf_kfunc_init(void)
 	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_IN, &bpf_kfunc_set_skb);
 	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);
-	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);
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v3 06/10] bpf: Implement cgroup sockaddr hooks for unix sockets
  2023-04-21 16:27 [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets Daan De Meyer
                   ` (4 preceding siblings ...)
  2023-04-21 16:27 ` [PATCH bpf-next v3 05/10] bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf Daan De Meyer
@ 2023-04-21 16:27 ` Daan De Meyer
  2023-04-21 16:27 ` [PATCH bpf-next v3 07/10] libbpf: Add support for cgroup unix socket address hooks Daan De Meyer
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 25+ messages in thread
From: Daan De Meyer @ 2023-04-21 16:27 UTC (permalink / raw)
  To: bpf; +Cc: Daan De Meyer, martin.lau, kernel-team

These hooks allows intercepting bind(), connect(), getsockname(),
getpeername(), sendmsg() and recvmsg() for unix sockets. The unix
socket hooks get write access to the address length because the
address length is not fixed when dealing with unix sockets and
needs to be modified when a unix socket address is modified by
the hook. Because abstract socket unix addresses start with a
NUL byte, we cannot recalculate the socket address in kernelspace
after running the hook by calculating the length of the unix socket
path using strlen().

Write support is added for uaddrlen to allow the unix socket hooks
to modify the sockaddr length from the bpf program.

This hook can be used when users want to multiplex syscall to a
single unix socket to multiple different processes behind the scenes
by redirecting the connect() and other syscalls to process specific
sockets.

Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
---
 include/linux/bpf-cgroup-defs.h |   6 ++
 include/linux/bpf-cgroup.h      |  29 ++++++++-
 include/uapi/linux/bpf.h        |  14 +++--
 kernel/bpf/cgroup.c             |  11 +++-
 kernel/bpf/syscall.c            |  18 ++++++
 kernel/bpf/verifier.c           |   7 ++-
 net/core/filter.c               |  17 +++++-
 net/unix/af_unix.c              | 102 +++++++++++++++++++++++++++++---
 tools/include/uapi/linux/bpf.h  |  14 +++--
 9 files changed, 196 insertions(+), 22 deletions(-)

diff --git a/include/linux/bpf-cgroup-defs.h b/include/linux/bpf-cgroup-defs.h
index 7b121bd780eb..8196ccb81915 100644
--- a/include/linux/bpf-cgroup-defs.h
+++ b/include/linux/bpf-cgroup-defs.h
@@ -26,21 +26,27 @@ enum cgroup_bpf_attach_type {
 	CGROUP_DEVICE,
 	CGROUP_INET4_BIND,
 	CGROUP_INET6_BIND,
+	CGROUP_UNIX_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,
diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
index f3f5adf3881f..91138371f476 100644
--- a/include/linux/bpf-cgroup.h
+++ b/include/linux/bpf-cgroup.h
@@ -46,21 +46,27 @@ to_cgroup_bpf_attach_type(enum bpf_attach_type attach_type)
 	CGROUP_ATYPE(CGROUP_DEVICE);
 	CGROUP_ATYPE(CGROUP_INET4_BIND);
 	CGROUP_ATYPE(CGROUP_INET6_BIND);
+	CGROUP_ATYPE(CGROUP_UNIX_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;
@@ -272,9 +278,13 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
 	__ret;								       \
 })
 
+#define BPF_CGROUP_RUN_PROG_UNIX_BIND_LOCK(sk, uaddr, uaddrlen)			\
+	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_UNIX_BIND, NULL)
+
 #define BPF_CGROUP_PRE_CONNECT_ENABLED(sk)				       \
 	((cgroup_bpf_enabled(CGROUP_INET4_CONNECT) ||		       \
-	  cgroup_bpf_enabled(CGROUP_INET6_CONNECT)) &&		       \
+	  cgroup_bpf_enabled(CGROUP_INET6_CONNECT) ||		       \
+	  cgroup_bpf_enabled(CGROUP_UNIX_CONNECT)) &&		       \
 	 (sk)->sk_prot->pre_connect)
 
 #define BPF_CGROUP_RUN_PROG_INET4_CONNECT(sk, uaddr, uaddrlen)			\
@@ -283,24 +293,36 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
 #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_UNIX_CONNECT(sk, uaddr, uaddrlen)			\
+	BPF_CGROUP_RUN_SA_PROG(sk, uaddr, uaddrlen, CGROUP_UNIX_CONNECT)
+
 #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, uaddrlen)		\
 	BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, uaddrlen, CGROUP_INET6_CONNECT, NULL)
 
+#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_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_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_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
  * sk_to_full_sk().
@@ -486,16 +508,21 @@ static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map,
 #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, uaddrlen, atype, flags) ({ 0; })
+#define BPF_CGROUP_RUN_PROG_UNIX_BIND_LOCK(sk, uaddr, uaddrlen) ({ 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, 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(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; })
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 4b20a7269bee..58ed37ac0436 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -1034,6 +1034,12 @@ enum bpf_attach_type {
 	BPF_TRACE_KPROBE_MULTI,
 	BPF_LSM_CGROUP,
 	BPF_STRUCT_OPS,
+	BPF_CGROUP_UNIX_BIND,
+	BPF_CGROUP_UNIX_CONNECT,
+	BPF_CGROUP_UNIX_SENDMSG,
+	BPF_CGROUP_UNIX_RECVMSG,
+	BPF_CGROUP_UNIX_GETPEERNAME,
+	BPF_CGROUP_UNIX_GETSOCKNAME,
 	__MAX_BPF_ATTACH_TYPE
 };
 
@@ -2611,8 +2617,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:
@@ -2850,8 +2856,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
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index c2191f0e138e..2cf01cbaf489 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -1455,7 +1455,7 @@ EXPORT_SYMBOL(__cgroup_bpf_run_filter_sk);
  * @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, the new address
@@ -1481,7 +1481,8 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
 	/* 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) {
@@ -2511,10 +2512,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;
@@ -2526,10 +2530,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;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index bcf1a1920ddd..170ec8ad38d3 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2390,16 +2390,22 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type,
 		switch (expected_attach_type) {
 		case BPF_CGROUP_INET4_BIND:
 		case BPF_CGROUP_INET6_BIND:
+		case BPF_CGROUP_UNIX_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;
@@ -3453,16 +3459,22 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
 		return BPF_PROG_TYPE_CGROUP_SOCK;
 	case BPF_CGROUP_INET4_BIND:
 	case BPF_CGROUP_INET6_BIND:
+	case BPF_CGROUP_UNIX_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;
@@ -3618,18 +3630,24 @@ static int bpf_prog_query(const union bpf_attr *attr,
 	case BPF_CGROUP_INET_SOCK_RELEASE:
 	case BPF_CGROUP_INET4_BIND:
 	case BPF_CGROUP_INET6_BIND:
+	case BPF_CGROUP_UNIX_BIND:
 	case BPF_CGROUP_INET4_POST_BIND:
 	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:
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 1e05355facdc..3645a693c54e 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -13756,14 +13756,19 @@ static int check_return_code(struct bpf_verifier_env *env)
 	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)
 			range = tnum_range(0, 3);
+		if (env->prog->expected_attach_type == BPF_CGROUP_UNIX_BIND)
+			range = tnum_range(0, 1);
 		break;
 	case BPF_PROG_TYPE_CGROUP_SKB:
 		if (env->prog->expected_attach_type == BPF_CGROUP_INET_EGRESS) {
diff --git a/net/core/filter.c b/net/core/filter.c
index 1c656e2d7b58..2f90fb3a9a64 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -7747,6 +7747,7 @@ sock_addr_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 		switch (prog->expected_attach_type) {
 		case BPF_CGROUP_INET4_CONNECT:
 		case BPF_CGROUP_INET6_CONNECT:
+		case BPF_CGROUP_UNIX_CONNECT:
 			return &bpf_bind_proto;
 		default:
 			return NULL;
@@ -7775,16 +7776,22 @@ sock_addr_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 		switch (prog->expected_attach_type) {
 		case BPF_CGROUP_INET4_BIND:
 		case BPF_CGROUP_INET6_BIND:
+		case BPF_CGROUP_UNIX_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;
@@ -7793,16 +7800,22 @@ sock_addr_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 		switch (prog->expected_attach_type) {
 		case BPF_CGROUP_INET4_BIND:
 		case BPF_CGROUP_INET6_BIND:
+		case BPF_CGROUP_UNIX_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;
@@ -8850,8 +8863,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):
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index fb31e8a4409e..5109596e5437 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -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"
 
@@ -1303,6 +1304,14 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	struct sock *sk = sock->sk;
 	int err;
 
+	if (cgroup_bpf_enabled(CGROUP_UNIX_BIND)) {
+		err = BPF_CGROUP_RUN_PROG_UNIX_BIND_LOCK(sk, uaddr, addr_len);
+		if (err < 0)
+			return err;
+
+		addr_len = err;
+	}
+
 	if (addr_len == offsetof(struct sockaddr_un, sun_path) &&
 	    sunaddr->sun_family == AF_UNIX)
 		return unix_autobind(sk);
@@ -1357,6 +1366,15 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
 		goto out;
 
 	if (addr->sa_family != AF_UNSPEC) {
+		if (cgroup_bpf_enabled(CGROUP_UNIX_CONNECT)) {
+			err = BPF_CGROUP_RUN_PROG_UNIX_CONNECT_LOCK(sk, addr,
+								    alen);
+			if (err < 0)
+				goto out;
+
+			alen = err;
+		}
+
 		err = unix_validate_addr(sunaddr, alen);
 		if (err)
 			goto out;
@@ -1465,6 +1483,15 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
 	int err;
 	int st;
 
+	if (cgroup_bpf_enabled(CGROUP_UNIX_CONNECT)) {
+		err = BPF_CGROUP_RUN_PROG_UNIX_CONNECT_LOCK(sk, uaddr,
+							    addr_len);
+		if (err < 0)
+			goto out;
+
+		addr_len = err;
+	}
+
 	err = unix_validate_addr(sunaddr, addr_len);
 	if (err)
 		goto out;
@@ -1725,7 +1752,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
 	struct sock *sk = sock->sk;
 	struct unix_address *addr;
 	DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
-	int err = 0;
+	int addr_len = 0, err = 0;
 
 	if (peer) {
 		sk = unix_peer_get(sk);
@@ -1742,14 +1769,39 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
 	if (!addr) {
 		sunaddr->sun_family = AF_UNIX;
 		sunaddr->sun_path[0] = 0;
-		err = offsetof(struct sockaddr_un, sun_path);
+		addr_len = offsetof(struct sockaddr_un, sun_path);
 	} else {
-		err = addr->len;
+		addr_len = addr->len;
 		memcpy(sunaddr, addr->name, addr->len);
 	}
+
+	if (peer && cgroup_bpf_enabled(CGROUP_UNIX_GETPEERNAME)) {
+		err = BPF_CGROUP_RUN_SA_PROG(sk, uaddr, addr_len,
+					     CGROUP_UNIX_GETPEERNAME);
+		if (err < 0)
+			goto out;
+
+		addr_len = err;
+
+		err = unix_validate_addr(sunaddr, addr_len);
+		if (err)
+			goto out;
+	} else if (cgroup_bpf_enabled(CGROUP_UNIX_GETSOCKNAME)) {
+		err = BPF_CGROUP_RUN_SA_PROG(sk, uaddr, addr_len,
+					     CGROUP_UNIX_GETSOCKNAME);
+		if (err < 0)
+			goto out;
+
+		addr_len = err;
+
+		err = unix_validate_addr(sunaddr, addr_len);
+		if (err)
+			goto out;
+	}
+
 	sock_put(sk);
 out:
-	return err;
+	return err ?: addr_len;
 }
 
 static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb)
@@ -1911,6 +1963,17 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
 		goto out;
 
 	if (msg->msg_namelen) {
+		if (cgroup_bpf_enabled(CGROUP_UNIX_SENDMSG)) {
+			err = BPF_CGROUP_RUN_PROG_UNIX_SENDMSG_LOCK(sk,
+								    msg->msg_name,
+								    msg->msg_namelen,
+								    NULL);
+			if (err < 0)
+				goto out;
+
+			msg->msg_namelen = err;
+		}
+
 		err = unix_validate_addr(sunaddr, msg->msg_namelen);
 		if (err)
 			goto out;
@@ -2418,14 +2481,32 @@ static int unix_seqpacket_recvmsg(struct socket *sock, struct msghdr *msg,
 	return unix_dgram_recvmsg(sock, msg, size, flags);
 }
 
-static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
+static int unix_recvmsg_copy_addr(struct msghdr *msg, struct sock *sk)
 {
 	struct unix_address *addr = smp_load_acquire(&unix_sk(sk)->addr);
+	int err;
 
 	if (addr) {
 		msg->msg_namelen = addr->len;
 		memcpy(msg->msg_name, addr->name, addr->len);
+
+		if (cgroup_bpf_enabled(CGROUP_UNIX_RECVMSG)) {
+			err = BPF_CGROUP_RUN_PROG_UNIX_RECVMSG_LOCK(sk,
+								    msg->msg_name,
+								    msg->msg_namelen);
+			if (err < 0)
+				return err;
+
+			msg->msg_namelen = err;
+
+			err = unix_validate_addr(msg->msg_name,
+						 msg->msg_namelen);
+			if (err)
+				return err;
+		}
 	}
+
+	return 0;
 }
 
 int __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size,
@@ -2480,8 +2561,11 @@ int __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size,
 						EPOLLOUT | EPOLLWRNORM |
 						EPOLLWRBAND);
 
-	if (msg->msg_name)
-		unix_copy_addr(msg, skb->sk);
+	if (msg->msg_name) {
+		err = unix_recvmsg_copy_addr(msg, skb->sk);
+		if (err)
+			goto out_free;
+	}
 
 	if (size > skb->len - skip)
 		size = skb->len - skip;
@@ -2835,7 +2919,9 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
 		if (state->msg && state->msg->msg_name) {
 			DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr,
 					 state->msg->msg_name);
-			unix_copy_addr(state->msg, skb->sk);
+			err = unix_recvmsg_copy_addr(state->msg, skb->sk);
+			if (err)
+				break;
 			sunaddr = NULL;
 		}
 
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 4b20a7269bee..58ed37ac0436 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -1034,6 +1034,12 @@ enum bpf_attach_type {
 	BPF_TRACE_KPROBE_MULTI,
 	BPF_LSM_CGROUP,
 	BPF_STRUCT_OPS,
+	BPF_CGROUP_UNIX_BIND,
+	BPF_CGROUP_UNIX_CONNECT,
+	BPF_CGROUP_UNIX_SENDMSG,
+	BPF_CGROUP_UNIX_RECVMSG,
+	BPF_CGROUP_UNIX_GETPEERNAME,
+	BPF_CGROUP_UNIX_GETSOCKNAME,
 	__MAX_BPF_ATTACH_TYPE
 };
 
@@ -2611,8 +2617,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:
@@ -2850,8 +2856,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
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v3 07/10] libbpf: Add support for cgroup unix socket address hooks
  2023-04-21 16:27 [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets Daan De Meyer
                   ` (5 preceding siblings ...)
  2023-04-21 16:27 ` [PATCH bpf-next v3 06/10] bpf: Implement cgroup sockaddr hooks for unix sockets Daan De Meyer
@ 2023-04-21 16:27 ` Daan De Meyer
  2023-04-21 16:27 ` [PATCH bpf-next v3 08/10] bpftool: " Daan De Meyer
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 25+ messages in thread
From: Daan De Meyer @ 2023-04-21 16:27 UTC (permalink / raw)
  To: bpf; +Cc: Daan De Meyer, martin.lau, kernel-team

Add the necessary plumbing to hook up the new cgroup unix sockaddr
hooks into libbpf.

Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
---
 tools/lib/bpf/libbpf.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 2600d8384252..0c4f67c3d9b9 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -80,19 +80,25 @@ static const char * const attach_type_name[] = {
 	[BPF_CGROUP_DEVICE]		= "cgroup_device",
 	[BPF_CGROUP_INET4_BIND]		= "cgroup_inet4_bind",
 	[BPF_CGROUP_INET6_BIND]		= "cgroup_inet6_bind",
+	[BPF_CGROUP_UNIX_BIND]		= "cgroup_unix_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",
@@ -8693,16 +8699,22 @@ static const struct bpf_sec_def section_defs[] = {
 	SEC_DEF("cgroup/post_bind6",	CGROUP_SOCK, BPF_CGROUP_INET6_POST_BIND, SEC_ATTACHABLE),
 	SEC_DEF("cgroup/bind4",		CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_BIND, SEC_ATTACHABLE),
 	SEC_DEF("cgroup/bind6",		CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_BIND, SEC_ATTACHABLE),
+	SEC_DEF("cgroup/bindun",	CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_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/connectun",	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/sendmsgun",	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/recvmsgun",	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/getpeernameun", 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/getsocknameun", 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),
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v3 08/10] bpftool: Add support for cgroup unix socket address hooks
  2023-04-21 16:27 [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets Daan De Meyer
                   ` (6 preceding siblings ...)
  2023-04-21 16:27 ` [PATCH bpf-next v3 07/10] libbpf: Add support for cgroup unix socket address hooks Daan De Meyer
@ 2023-04-21 16:27 ` Daan De Meyer
  2023-04-21 20:35   ` Quentin Monnet
  2023-04-21 16:27 ` [PATCH bpf-next v3 09/10] selftests/bpf: Add tests " Daan De Meyer
  2023-04-21 16:27 ` [PATCH bpf-next v3 10/10] documentation/bpf: Document " Daan De Meyer
  9 siblings, 1 reply; 25+ messages in thread
From: Daan De Meyer @ 2023-04-21 16:27 UTC (permalink / raw)
  To: bpf; +Cc: Daan De Meyer, martin.lau, kernel-team

Add the necessary plumbing to hook up the new cgroup unix sockaddr
hooks into bpftool.

Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
---
 .../bpftool/Documentation/bpftool-cgroup.rst  | 21 ++++++++++++++-----
 tools/bpf/bpftool/cgroup.c                    | 17 ++++++++-------
 tools/bpf/bpftool/common.c                    |  6 ++++++
 3 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
index bd015ec9847b..a2d990fa623b 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
@@ -34,13 +34,16 @@ CGROUP COMMANDS
 |	*ATTACH_TYPE* := { **cgroup_inet_ingress** | **cgroup_inet_egress** |
 |		**cgroup_inet_sock_create** | **cgroup_sock_ops** |
 |		**cgroup_device** | **cgroup_inet4_bind** | **cgroup_inet6_bind** |
-|		**cgroup_inet4_post_bind** | **cgroup_inet6_post_bind** |
-|		**cgroup_inet4_connect** | **cgroup_inet6_connect** |
+|		**cgroup_unix_bind** | **cgroup_inet4_post_bind** |
+|		**cgroup_inet6_post_bind** | **cgroup_inet4_connect** |
+|		**cgroup_inet6_connect** | **cgroup_unix_connect** |
 |		**cgroup_inet4_getpeername** | **cgroup_inet6_getpeername** |
-|		**cgroup_inet4_getsockname** | **cgroup_inet6_getsockname** |
-|		**cgroup_udp4_sendmsg** | **cgroup_udp6_sendmsg** |
+|		**cgroup_unix_getpeername** | **cgroup_inet4_getsockname** |
+|		**cgroup_inet6_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** }
 
@@ -98,25 +101,33 @@ DESCRIPTION
 		  **device** device access (since 4.15);
 		  **bind4** call to bind(2) for an inet4 socket (since 4.17);
 		  **bind6** call to bind(2) for an inet6 socket (since 4.17);
+		  **bindun** call to bind(2) for a unix socket (since 6.3);
 		  **post_bind4** return from bind(2) for an inet4 socket (since 4.17);
 		  **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);
+		  **connectun** call to connect(2) for a unix socket (since 6.3);
 		  **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);
+		  **sendmsgun** call to sendto(2), sendmsg(2), sendmmsg(2) for
+		  an unconnected unix socket (since 6.3);
 		  **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);
+		  **recvmsgun** call to recvfrom(2), recvmsg(2), recvmmsg(2) for
+		  an unconnected unix socket (since 6.3);
 		  **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);
+		  **getpeernameun** call to getpeername(2) for a unix socket (since 6.3);
 		  **getsockname4** call to getsockname(2) for an inet4 socket (since 5.8);
 		  **getsockname6** call to getsockname(2) for an inet6 socket (since 5.8).
+		  **getsocknameun** call to getsockname(2) for a unix socket (since 6.3);
 		  **sock_release** closing an userspace inet socket (since 5.9).
 
 	**bpftool cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
diff --git a/tools/bpf/bpftool/cgroup.c b/tools/bpf/bpftool/cgroup.c
index ac846b0805b4..a9700e00064c 100644
--- a/tools/bpf/bpftool/cgroup.c
+++ b/tools/bpf/bpftool/cgroup.c
@@ -26,13 +26,16 @@
 	"       ATTACH_TYPE := { cgroup_inet_ingress | cgroup_inet_egress |\n" \
 	"                        cgroup_inet_sock_create | cgroup_sock_ops |\n" \
 	"                        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_inet6_bind | cgroup_unix_bind |\n" \
+	"                        cgroup_inet4_post_bind | cgroup_inet6_post_bind |\n" \
+	"                        cgroup_inet4_connect | cgroup_inet6_connect |\n" \
+	"                        cgroup_unix_connect | cgroup_inet4_getpeername |\n" \
+	"                        cgroup_inet6_getpeername | cgroup_unix_getpeername |\n" \
+	"                        cgroup_inet4_getsockname | cgroup_inet6_getsockname |\n" \
+	"                        cgroup_unix_getsockname | cgroup_udp4_sendmsg |\n" \
+	"                        cgroup_udp6_sendmsg | cgroup_unix_sendmsg |\n" \
+	"                        cgroup_udp4_recvmsg | cgroup_udp6_recvmsg |\n" \
+	"                        cgroup_unix_recvmsg | cgroup_sysctl |\n" \
 	"                        cgroup_getsockopt | cgroup_setsockopt |\n" \
 	"                        cgroup_inet_sock_release }"
 
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index 5a73ccf14332..71c219b186aa 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -1067,19 +1067,25 @@ const char *bpf_attach_type_input_str(enum bpf_attach_type t)
 	case BPF_CGROUP_DEVICE:			return "device";
 	case BPF_CGROUP_INET4_BIND:		return "bind4";
 	case BPF_CGROUP_INET6_BIND:		return "bind6";
+	case BPF_CGROUP_UNIX_BIND:		return "bindun";
 	case BPF_CGROUP_INET4_CONNECT:		return "connect4";
 	case BPF_CGROUP_INET6_CONNECT:		return "connect6";
+	case BPF_CGROUP_UNIX_CONNECT:		return "connectun";
 	case BPF_CGROUP_INET4_POST_BIND:	return "post_bind4";
 	case BPF_CGROUP_INET6_POST_BIND:	return "post_bind6";
 	case BPF_CGROUP_INET4_GETPEERNAME:	return "getpeername4";
 	case BPF_CGROUP_INET6_GETPEERNAME:	return "getpeername6";
+	case BPF_CGROUP_UNIX_GETPEERNAME:	return "getpeernameun";
 	case BPF_CGROUP_INET4_GETSOCKNAME:	return "getsockname4";
 	case BPF_CGROUP_INET6_GETSOCKNAME:	return "getsockname6";
+	case BPF_CGROUP_UNIX_GETSOCKNAME:	return "getsocknameun";
 	case BPF_CGROUP_UDP4_SENDMSG:		return "sendmsg4";
 	case BPF_CGROUP_UDP6_SENDMSG:		return "sendmsg6";
+	case BPF_CGROUP_UNIX_SENDMSG:		return "sendmsgun";
 	case BPF_CGROUP_SYSCTL:			return "sysctl";
 	case BPF_CGROUP_UDP4_RECVMSG:		return "recvmsg4";
 	case BPF_CGROUP_UDP6_RECVMSG:		return "recvmsg6";
+	case BPF_CGROUP_UNIX_RECVMSG:		return "recvmsgun";
 	case BPF_CGROUP_GETSOCKOPT:		return "getsockopt";
 	case BPF_CGROUP_SETSOCKOPT:		return "setsockopt";
 	case BPF_TRACE_RAW_TP:			return "raw_tp";
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v3 09/10] selftests/bpf: Add tests for cgroup unix socket address hooks
  2023-04-21 16:27 [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets Daan De Meyer
                   ` (7 preceding siblings ...)
  2023-04-21 16:27 ` [PATCH bpf-next v3 08/10] bpftool: " Daan De Meyer
@ 2023-04-21 16:27 ` Daan De Meyer
  2023-04-26 21:57   ` Martin KaFai Lau
  2023-04-26 22:13   ` Martin KaFai Lau
  2023-04-21 16:27 ` [PATCH bpf-next v3 10/10] documentation/bpf: Document " Daan De Meyer
  9 siblings, 2 replies; 25+ messages in thread
From: Daan De Meyer @ 2023-04-21 16:27 UTC (permalink / raw)
  To: bpf; +Cc: Daan De Meyer, martin.lau, kernel-team

The unix socket address hooks do not support modifying the source
address so we skip source address checks when we're running a unix
socket address hook test.

Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
---
 tools/testing/selftests/bpf/bpf_kfuncs.h      |  13 ++
 .../selftests/bpf/prog_tests/section_names.c  |  30 ++++
 .../testing/selftests/bpf/progs/bindun_prog.c |  59 ++++++++
 .../selftests/bpf/progs/connectun_prog.c      |  53 +++++++
 .../selftests/bpf/progs/recvmsgun_prog.c      |  59 ++++++++
 .../selftests/bpf/progs/sendmsgun_prog.c      |  53 +++++++
 tools/testing/selftests/bpf/test_sock_addr.c  | 137 +++++++++++++++++-
 7 files changed, 397 insertions(+), 7 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/bindun_prog.c
 create mode 100644 tools/testing/selftests/bpf/progs/connectun_prog.c
 create mode 100644 tools/testing/selftests/bpf/progs/recvmsgun_prog.c
 create mode 100644 tools/testing/selftests/bpf/progs/sendmsgun_prog.c

diff --git a/tools/testing/selftests/bpf/bpf_kfuncs.h b/tools/testing/selftests/bpf/bpf_kfuncs.h
index 8c993ec8ceea..dbdec3d5152e 100644
--- a/tools/testing/selftests/bpf/bpf_kfuncs.h
+++ b/tools/testing/selftests/bpf/bpf_kfuncs.h
@@ -1,6 +1,8 @@
 #ifndef __BPF_KFUNCS__
 #define __BPF_KFUNCS__
 
+struct bpf_sock_addr_kern;
+
 /* Description
  *  Initializes an skb-type dynptr
  * Returns
@@ -35,4 +37,15 @@ extern void *bpf_dynptr_slice(const struct bpf_dynptr *ptr, __u32 offset,
 extern void *bpf_dynptr_slice_rdwr(const struct bpf_dynptr *ptr, __u32 offset,
 			      void *buffer, __u32 buffer__szk) __ksym;
 
+/* Description
+ *  Modify the contents of a sockaddr.
+ * Returns__bpf_kfunc
+ *  -EINVAL if the sockaddr family does not match, the sockaddr is too small or
+ *  too big, 0 if the sockaddr was successfully modified.
+ */
+extern int bpf_sock_addr_set(struct bpf_sock_addr_kern *sa_kern,
+			     const void *addr, __u32 addrlen__sz) __ksym;
+
+void *bpf_rdonly_cast(void *obj, __u32 btf_id) __ksym;
+
 #endif
diff --git a/tools/testing/selftests/bpf/prog_tests/section_names.c b/tools/testing/selftests/bpf/prog_tests/section_names.c
index fc5248e94a01..51ebc8e6065d 100644
--- a/tools/testing/selftests/bpf/prog_tests/section_names.c
+++ b/tools/testing/selftests/bpf/prog_tests/section_names.c
@@ -113,6 +113,11 @@ static struct sec_name_test tests[] = {
 		{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_BIND},
 		{0, BPF_CGROUP_INET6_BIND},
 	},
+	{
+		"cgroup/bindun",
+		{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UNIX_BIND},
+		{0, BPF_CGROUP_UNIX_BIND},
+	},
 	{
 		"cgroup/connect4",
 		{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_CONNECT},
@@ -123,6 +128,11 @@ static struct sec_name_test tests[] = {
 		{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_CONNECT},
 		{0, BPF_CGROUP_INET6_CONNECT},
 	},
+	{
+		"cgroup/connectun",
+		{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 +143,11 @@ static struct sec_name_test tests[] = {
 		{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG},
 		{0, BPF_CGROUP_UDP6_SENDMSG},
 	},
+	{
+		"cgroup/sendmsgun",
+		{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 +158,11 @@ static struct sec_name_test tests[] = {
 		{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_RECVMSG},
 		{0, BPF_CGROUP_UDP6_RECVMSG},
 	},
+	{
+		"cgroup/recvmsgun",
+		{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},
@@ -168,6 +188,11 @@ static struct sec_name_test tests[] = {
 		{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_GETPEERNAME},
 		{0, BPF_CGROUP_INET6_GETPEERNAME},
 	},
+	{
+		"cgroup/getpeernameun",
+		{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},
@@ -178,6 +203,11 @@ static struct sec_name_test tests[] = {
 		{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_GETSOCKNAME},
 		{0, BPF_CGROUP_INET6_GETSOCKNAME},
 	},
+	{
+		"cgroup/getsocknameun",
+		{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)
diff --git a/tools/testing/selftests/bpf/progs/bindun_prog.c b/tools/testing/selftests/bpf/progs/bindun_prog.c
new file mode 100644
index 000000000000..60addb5a9c96
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/bindun_prog.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022 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"
+
+#ifndef AF_UNIX
+#define AF_UNIX 1
+#endif
+
+#define DST_REWRITE_PATH	"\0bpf_cgroup_unix_test_rewrite"
+
+void *bpf_cast_to_kern_ctx(void *) __ksym;
+
+SEC("cgroup/bindun")
+int bind_un_prog(struct bpf_sock_addr *ctx)
+{
+	struct bpf_sock *sk = ctx->sk;
+	struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
+	struct sockaddr_un *sa_kern_unaddr;
+	struct sockaddr_un unaddr = {
+		.sun_family = AF_UNIX,
+	};
+	__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
+			  sizeof(DST_REWRITE_PATH) - 1;
+	int ret;
+
+	if (!sk)
+		return 0;
+
+	if (sk->family != AF_UNIX)
+		return 0;
+
+	if (ctx->type != SOCK_STREAM && ctx->type != SOCK_DGRAM)
+		return 0;
+
+	memcpy(unaddr.sun_path, DST_REWRITE_PATH, sizeof(DST_REWRITE_PATH) - 1);
+
+	ret = bpf_sock_addr_set(sa_kern, (struct sockaddr *) &unaddr, unaddrlen);
+	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, DST_REWRITE_PATH,
+		   sizeof(DST_REWRITE_PATH) - 1) != 0)
+		return 0;
+
+	return 1;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/connectun_prog.c b/tools/testing/selftests/bpf/progs/connectun_prog.c
new file mode 100644
index 000000000000..ac7209bd326f
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/connectun_prog.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022 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"
+
+#ifndef AF_UNIX
+#define AF_UNIX 1
+#endif
+
+#define DST_REWRITE_PATH	"\0bpf_cgroup_unix_test_rewrite"
+
+void *bpf_cast_to_kern_ctx(void *) __ksym;
+
+SEC("cgroup/connectun")
+int connect_un_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;
+	struct sockaddr_un unaddr = {
+		.sun_family = AF_UNIX,
+	};
+	__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
+			  sizeof(DST_REWRITE_PATH) - 1;
+	int ret;
+
+	if (ctx->type != SOCK_STREAM && ctx->type != SOCK_DGRAM)
+		return 0;
+
+	memcpy(unaddr.sun_path, DST_REWRITE_PATH, sizeof(DST_REWRITE_PATH) - 1);
+
+	/* Rewrite destination. */
+	ret = bpf_sock_addr_set(sa_kern, (struct sockaddr *) &unaddr, unaddrlen);
+	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, DST_REWRITE_PATH,
+		   sizeof(DST_REWRITE_PATH) - 1) != 0)
+		return 0;
+
+	return 1;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/recvmsgun_prog.c b/tools/testing/selftests/bpf/progs/recvmsgun_prog.c
new file mode 100644
index 000000000000..4567aad723ee
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/recvmsgun_prog.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022 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"
+
+#ifndef AF_UNIX
+#define AF_UNIX 1
+#endif
+
+#define SERVUN_PATH		"\0bpf_cgroup_unix_test"
+
+void *bpf_cast_to_kern_ctx(void *) __ksym;
+
+SEC("cgroup/recvmsgun")
+int recvmsgun_prog(struct bpf_sock_addr *ctx)
+{
+	struct bpf_sock *sk = ctx->sk;
+	struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
+	struct sockaddr_un *sa_kern_unaddr;
+	struct sockaddr_un unaddr = {
+		.sun_family = AF_UNIX,
+	};
+	__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
+			  sizeof(SERVUN_PATH) - 1;
+	int ret;
+
+	if (!sk)
+		return 1;
+
+	if (sk->family != AF_UNIX)
+		return 1;
+
+	if (ctx->type != SOCK_STREAM && ctx->type != SOCK_DGRAM)
+		return 1;
+
+	memcpy(unaddr.sun_path, SERVUN_PATH, sizeof(SERVUN_PATH) - 1);
+
+	ret = bpf_sock_addr_set(sa_kern, (struct sockaddr *) &unaddr, unaddrlen);
+	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_PATH,
+		   sizeof(SERVUN_PATH) - 1) != 0)
+		return 1;
+
+	return 1;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/sendmsgun_prog.c b/tools/testing/selftests/bpf/progs/sendmsgun_prog.c
new file mode 100644
index 000000000000..3e4fe0859421
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/sendmsgun_prog.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022 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"
+
+#ifndef AF_UNIX
+#define AF_UNIX 1
+#endif
+
+#define DST_REWRITE_PATH	"\0bpf_cgroup_unix_test_rewrite"
+
+void *bpf_cast_to_kern_ctx(void *) __ksym;
+
+SEC("cgroup/sendmsgun")
+int sendmsg_un_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;
+	struct sockaddr_un unaddr = {
+		.sun_family = AF_UNIX,
+	};
+	__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
+			  sizeof(DST_REWRITE_PATH) - 1;
+	int ret;
+
+	if (ctx->type != SOCK_DGRAM)
+		return 0;
+
+	memcpy(unaddr.sun_path, DST_REWRITE_PATH, sizeof(DST_REWRITE_PATH) - 1);
+
+	/* Rewrite destination. */
+	ret = bpf_sock_addr_set(sa_kern, (struct sockaddr *) &unaddr, unaddrlen);
+	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, DST_REWRITE_PATH,
+		   sizeof(DST_REWRITE_PATH) - 1) != 0)
+		return 0;
+
+	return 1;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_sock_addr.c b/tools/testing/selftests/bpf/test_sock_addr.c
index 6a618c8f477c..c96322bcc6c8 100644
--- a/tools/testing/selftests/bpf/test_sock_addr.c
+++ b/tools/testing/selftests/bpf/test_sock_addr.c
@@ -12,6 +12,7 @@
 #include <sys/types.h>
 #include <sys/select.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 
 #include <linux/filter.h>
 
@@ -28,12 +29,16 @@
 #define CG_PATH	"/foo"
 #define CONNECT4_PROG_PATH	"./connect4_prog.bpf.o"
 #define CONNECT6_PROG_PATH	"./connect6_prog.bpf.o"
+#define CONNECTUN_PROG_PATH	"./connectun_prog.bpf.o"
 #define SENDMSG4_PROG_PATH	"./sendmsg4_prog.bpf.o"
 #define SENDMSG6_PROG_PATH	"./sendmsg6_prog.bpf.o"
+#define SENDMSGUN_PROG_PATH	"./sendmsgun_prog.bpf.o"
 #define RECVMSG4_PROG_PATH	"./recvmsg4_prog.bpf.o"
 #define RECVMSG6_PROG_PATH	"./recvmsg6_prog.bpf.o"
+#define RECVMSGUN_PROG_PATH	"./recvmsgun_prog.bpf.o"
 #define BIND4_PROG_PATH		"./bind4_prog.bpf.o"
 #define BIND6_PROG_PATH		"./bind6_prog.bpf.o"
+#define BINDUN_PROG_PATH	"./bindun_prog.bpf.o"
 
 #define SERV4_IP		"192.168.1.254"
 #define SERV4_REWRITE_IP	"127.0.0.1"
@@ -51,6 +56,9 @@
 #define SERV6_PORT		6060
 #define SERV6_REWRITE_PORT	6666
 
+#define SERVUN_ADDRESS		"bpf_cgroup_unix_test"
+#define SERVUN_REWRITE_ADDRESS	"bpf_cgroup_unix_test_rewrite"
+
 #define INET_NTOP_BUF	40
 
 struct sock_addr_test;
@@ -88,8 +96,10 @@ struct sock_addr_test {
 
 static int bind4_prog_load(const struct sock_addr_test *test);
 static int bind6_prog_load(const struct sock_addr_test *test);
+static int bindun_prog_load(const struct sock_addr_test *test);
 static int connect4_prog_load(const struct sock_addr_test *test);
 static int connect6_prog_load(const struct sock_addr_test *test);
+static int connectun_prog_load(const struct sock_addr_test *test);
 static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
 static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
 static int recvmsg_allow_prog_load(const struct sock_addr_test *test);
@@ -102,6 +112,8 @@ static int recvmsg6_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
+static int sendmsgun_prog_load(const struct sock_addr_test *test);
+static int recvmsgun_prog_load(const struct sock_addr_test *test);
 
 static struct sock_addr_test tests[] = {
 	/* bind */
@@ -217,6 +229,20 @@ static struct sock_addr_test tests[] = {
 		NULL,
 		SUCCESS,
 	},
+	{
+		"bindun: rewrite path",
+		bindun_prog_load,
+		BPF_CGROUP_UNIX_BIND,
+		BPF_CGROUP_UNIX_BIND,
+		AF_UNIX,
+		SOCK_STREAM,
+		SERVUN_ADDRESS,
+		0,
+		SERVUN_REWRITE_ADDRESS,
+		0,
+		NULL,
+		SUCCESS,
+	},
 
 	/* connect */
 	{
@@ -331,6 +357,34 @@ static struct sock_addr_test tests[] = {
 		SRC6_REWRITE_IP,
 		SUCCESS,
 	},
+	{
+		"connectun: rewrite SOCK_STREAM path",
+		connectun_prog_load,
+		BPF_CGROUP_UNIX_CONNECT,
+		BPF_CGROUP_UNIX_CONNECT,
+		AF_UNIX,
+		SOCK_STREAM,
+		SERVUN_ADDRESS,
+		0,
+		SERVUN_REWRITE_ADDRESS,
+		0,
+		NULL,
+		SUCCESS,
+	},
+	{
+		"connectun: rewrite SOCK_DGRAM path",
+		connectun_prog_load,
+		BPF_CGROUP_UNIX_CONNECT,
+		BPF_CGROUP_UNIX_CONNECT,
+		AF_UNIX,
+		SOCK_DGRAM,
+		SERVUN_ADDRESS,
+		0,
+		SERVUN_REWRITE_ADDRESS,
+		0,
+		NULL,
+		SUCCESS,
+	},
 
 	/* sendmsg */
 	{
@@ -515,6 +569,20 @@ static struct sock_addr_test tests[] = {
 		SRC6_REWRITE_IP,
 		SYSCALL_EPERM,
 	},
+	{
+		"sendmsgun: rewrite SOCK_DGRAM path",
+		sendmsgun_prog_load,
+		BPF_CGROUP_UNIX_SENDMSG,
+		BPF_CGROUP_UNIX_SENDMSG,
+		AF_UNIX,
+		SOCK_DGRAM,
+		SERVUN_ADDRESS,
+		0,
+		SERVUN_REWRITE_ADDRESS,
+		0,
+		NULL,
+		SUCCESS,
+	},
 
 	/* recvmsg */
 	{
@@ -601,6 +669,20 @@ static struct sock_addr_test tests[] = {
 		SERV6_IP,
 		SUCCESS,
 	},
+	{
+		"recvmsgun: rewrite SOCK_DGRAM path",
+		recvmsgun_prog_load,
+		BPF_CGROUP_UNIX_RECVMSG,
+		BPF_CGROUP_UNIX_RECVMSG,
+		AF_UNIX,
+		SOCK_DGRAM,
+		SERVUN_REWRITE_ADDRESS,
+		0,
+		SERVUN_REWRITE_ADDRESS,
+		0,
+		NULL,
+		SUCCESS,
+	},
 };
 
 static int mk_sockaddr(int domain, const char *ip, unsigned short port,
@@ -608,8 +690,9 @@ static int mk_sockaddr(int domain, const char *ip, unsigned short port,
 {
 	struct sockaddr_in6 *addr6;
 	struct sockaddr_in *addr4;
+	struct sockaddr_un *addrun;
 
-	if (domain != AF_INET && domain != AF_INET6) {
+	if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNIX) {
 		log_err("Unsupported address family");
 		return -1;
 	}
@@ -638,6 +721,15 @@ static int mk_sockaddr(int domain, const char *ip, unsigned short port,
 			return -1;
 		}
 		*addr_len = sizeof(struct sockaddr_in6);
+	} else if (domain == AF_UNIX) {
+		if (*addr_len < sizeof(struct sockaddr_un))
+			return -1;
+		addrun = (struct sockaddr_un *)addr;
+		addrun->sun_family = domain;
+		addrun->sun_path[0] = 0;
+		strcpy(addrun->sun_path + 1, ip);
+		*addr_len = offsetof(struct sockaddr_un, sun_path) + 1 +
+			    strlen(ip);
 	}
 
 	return 0;
@@ -706,6 +798,11 @@ static int bind6_prog_load(const struct sock_addr_test *test)
 	return load_path(test, BIND6_PROG_PATH);
 }
 
+static int bindun_prog_load(const struct sock_addr_test *test)
+{
+	return load_path(test, BINDUN_PROG_PATH);
+}
+
 static int connect4_prog_load(const struct sock_addr_test *test)
 {
 	return load_path(test, CONNECT4_PROG_PATH);
@@ -716,6 +813,11 @@ static int connect6_prog_load(const struct sock_addr_test *test)
 	return load_path(test, CONNECT6_PROG_PATH);
 }
 
+static int connectun_prog_load(const struct sock_addr_test *test)
+{
+	return load_path(test, CONNECTUN_PROG_PATH);
+}
+
 static int xmsg_ret_only_prog_load(const struct sock_addr_test *test,
 				   int32_t rc)
 {
@@ -889,12 +991,23 @@ static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test)
 	return load_path(test, SENDMSG6_PROG_PATH);
 }
 
+static int sendmsgun_prog_load(const struct sock_addr_test *test)
+{
+	return load_path(test, SENDMSGUN_PROG_PATH);
+}
+
+static int recvmsgun_prog_load(const struct sock_addr_test *test)
+{
+	return load_path(test, RECVMSGUN_PROG_PATH);
+}
+
 static int cmp_addr(const struct sockaddr_storage *addr1, socklen_t addr1_len,
 		    const struct sockaddr_storage *addr2, socklen_t addr2_len,
 		    int 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;
@@ -913,6 +1026,10 @@ static int cmp_addr(const struct sockaddr_storage *addr1, socklen_t addr1_len,
 		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;
@@ -992,7 +1109,7 @@ static int connect_to_server(int type, const struct sockaddr_storage *addr,
 
 	domain = addr->ss_family;
 
-	if (domain != AF_INET && domain != AF_INET6) {
+	if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNIX) {
 		log_err("Unsupported address family");
 		goto err;
 	}
@@ -1066,7 +1183,7 @@ static int sendmsg_to_server(int type, const struct sockaddr_storage *addr,
 
 	domain = addr->ss_family;
 
-	if (domain != AF_INET && domain != AF_INET6) {
+	if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNIX) {
 		log_err("Unsupported address family");
 		goto err;
 	}
@@ -1095,7 +1212,7 @@ static int sendmsg_to_server(int type, const struct sockaddr_storage *addr,
 			hdr.msg_control = &control6;
 			hdr.msg_controllen = sizeof(control6.buf);
 		}
-		if (init_pktinfo(domain, CMSG_FIRSTHDR(&hdr))) {
+		if (domain != AF_UNIX && init_pktinfo(domain, CMSG_FIRSTHDR(&hdr))) {
 			log_err("Fail to init pktinfo");
 			goto err;
 		}
@@ -1257,10 +1374,11 @@ static int run_connect_test_case(const struct sock_addr_test *test)
 	if (cmp_peer_addr(clientfd, &expected_addr, expected_addr_len))
 		goto err;
 
-	if (cmp_local_ip(clientfd, &expected_src_addr, expected_src_addr_len))
+	if (test->domain != AF_UNIX &&
+	    cmp_local_ip(clientfd, &expected_src_addr, expected_src_addr_len))
 		goto err;
 
-	if (test->type == SOCK_STREAM) {
+	if (test->domain != AF_UNIX && test->type == SOCK_STREAM) {
 		/* Test TCP Fast Open scenario */
 		clientfd = fastconnect_to_server(&requested_addr, addr_len);
 		if (clientfd == -1)
@@ -1339,7 +1457,8 @@ static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
 					&recvmsg_addr_len) == -1)
 			goto err;
 
-		if (cmp_addr(&recvmsg_addr, recvmsg_addr_len, &expected_addr,
+		if (test->domain != AF_UNIX &&
+		    cmp_addr(&recvmsg_addr, recvmsg_addr_len, &expected_addr,
 			     expected_addr_len,
 			     /*cmp_port*/ 0))
 			goto err;
@@ -1382,18 +1501,22 @@ static int run_test_case(int cgfd, const struct sock_addr_test *test)
 	switch (test->attach_type) {
 	case BPF_CGROUP_INET4_BIND:
 	case BPF_CGROUP_INET6_BIND:
+	case BPF_CGROUP_UNIX_BIND:
 		err = run_bind_test_case(test);
 		break;
 	case BPF_CGROUP_INET4_CONNECT:
 	case BPF_CGROUP_INET6_CONNECT:
+	case BPF_CGROUP_UNIX_CONNECT:
 		err = run_connect_test_case(test);
 		break;
 	case BPF_CGROUP_UDP4_SENDMSG:
 	case BPF_CGROUP_UDP6_SENDMSG:
+	case BPF_CGROUP_UNIX_SENDMSG:
 		err = run_xmsg_test_case(test, 1);
 		break;
 	case BPF_CGROUP_UDP4_RECVMSG:
 	case BPF_CGROUP_UDP6_RECVMSG:
+	case BPF_CGROUP_UNIX_RECVMSG:
 		err = run_xmsg_test_case(test, 0);
 		break;
 	default:
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH bpf-next v3 10/10] documentation/bpf: Document cgroup unix socket address hooks
  2023-04-21 16:27 [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets Daan De Meyer
                   ` (8 preceding siblings ...)
  2023-04-21 16:27 ` [PATCH bpf-next v3 09/10] selftests/bpf: Add tests " Daan De Meyer
@ 2023-04-21 16:27 ` Daan De Meyer
  9 siblings, 0 replies; 25+ messages in thread
From: Daan De Meyer @ 2023-04-21 16:27 UTC (permalink / raw)
  To: bpf; +Cc: Daan De Meyer, martin.lau, kernel-team

Update the documentation to mention the new cgroup unix sockaddr
hooks.

Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
---
 Documentation/bpf/libbpf/program_types.rst | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/Documentation/bpf/libbpf/program_types.rst b/Documentation/bpf/libbpf/program_types.rst
index ad4d4d5eecb0..06168ad73d5e 100644
--- a/Documentation/bpf/libbpf/program_types.rst
+++ b/Documentation/bpf/libbpf/program_types.rst
@@ -56,6 +56,18 @@ described in more detail in the footnotes.
 |                                           | ``BPF_CGROUP_UDP6_RECVMSG``            | ``cgroup/recvmsg6``              |           |
 +                                           +----------------------------------------+----------------------------------+-----------+
 |                                           | ``BPF_CGROUP_UDP6_SENDMSG``            | ``cgroup/sendmsg6``              |           |
+|                                           +----------------------------------------+----------------------------------+-----------+
+|                                           | ``BPF_CGROUP_UNIX_BIND``               | ``cgroup/bindun``                |           |
+|                                           +----------------------------------------+----------------------------------+-----------+
+|                                           | ``BPF_CGROUP_UNIX_CONNECT``            | ``cgroup/connectun``             |           |
+|                                           +----------------------------------------+----------------------------------+-----------+
+|                                           | ``BPF_CGROUP_UNIX_SENDMSG``            | ``cgroup/sendmsgun``             |           |
+|                                           +----------------------------------------+----------------------------------+-----------+
+|                                           | ``BPF_CGROUP_UNIX_RECVMSG``            | ``cgroup/recvmsgun``             |           |
+|                                           +----------------------------------------+----------------------------------+-----------+
+|                                           | ``BPF_CGROUP_UNIX_GETPEERNAME``        | ``cgroup/getpeernameun``         |           |
+|                                           +----------------------------------------+----------------------------------+-----------+
+|                                           | ``BPF_CGROUP_UNIX_GETSOCKNAME``        | ``cgroup/getsocknameun``         |           |
 +-------------------------------------------+----------------------------------------+----------------------------------+-----------+
 | ``BPF_PROG_TYPE_CGROUP_SOCK``             | ``BPF_CGROUP_INET4_POST_BIND``         | ``cgroup/post_bind4``            |           |
 +                                           +----------------------------------------+----------------------------------+-----------+
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 08/10] bpftool: Add support for cgroup unix socket address hooks
  2023-04-21 16:27 ` [PATCH bpf-next v3 08/10] bpftool: " Daan De Meyer
@ 2023-04-21 20:35   ` Quentin Monnet
  0 siblings, 0 replies; 25+ messages in thread
From: Quentin Monnet @ 2023-04-21 20:35 UTC (permalink / raw)
  To: Daan De Meyer; +Cc: bpf, martin.lau, kernel-team

On Fri, 21 Apr 2023 at 17:31, Daan De Meyer <daan.j.demeyer@gmail.com> wrote:
>
> Add the necessary plumbing to hook up the new cgroup unix sockaddr
> hooks into bpftool.
>
> Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
> ---
>  .../bpftool/Documentation/bpftool-cgroup.rst  | 21 ++++++++++++++-----
>  tools/bpf/bpftool/cgroup.c                    | 17 ++++++++-------
>  tools/bpf/bpftool/common.c                    |  6 ++++++
>  3 files changed, 32 insertions(+), 12 deletions(-)
>
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> index bd015ec9847b..a2d990fa623b 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
> @@ -34,13 +34,16 @@ CGROUP COMMANDS
>  |      *ATTACH_TYPE* := { **cgroup_inet_ingress** | **cgroup_inet_egress** |
>  |              **cgroup_inet_sock_create** | **cgroup_sock_ops** |
>  |              **cgroup_device** | **cgroup_inet4_bind** | **cgroup_inet6_bind** |
> -|              **cgroup_inet4_post_bind** | **cgroup_inet6_post_bind** |
> -|              **cgroup_inet4_connect** | **cgroup_inet6_connect** |
> +|              **cgroup_unix_bind** | **cgroup_inet4_post_bind** |
> +|              **cgroup_inet6_post_bind** | **cgroup_inet4_connect** |
> +|              **cgroup_inet6_connect** | **cgroup_unix_connect** |
>  |              **cgroup_inet4_getpeername** | **cgroup_inet6_getpeername** |
> -|              **cgroup_inet4_getsockname** | **cgroup_inet6_getsockname** |
> -|              **cgroup_udp4_sendmsg** | **cgroup_udp6_sendmsg** |
> +|              **cgroup_unix_getpeername** | **cgroup_inet4_getsockname** |
> +|              **cgroup_inet6_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** }
>
> @@ -98,25 +101,33 @@ DESCRIPTION
>                   **device** device access (since 4.15);
>                   **bind4** call to bind(2) for an inet4 socket (since 4.17);
>                   **bind6** call to bind(2) for an inet6 socket (since 4.17);
> +                 **bindun** call to bind(2) for a unix socket (since 6.3);
>                   **post_bind4** return from bind(2) for an inet4 socket (since 4.17);
>                   **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);
> +                 **connectun** call to connect(2) for a unix socket (since 6.3);
>                   **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);
> +                 **sendmsgun** call to sendto(2), sendmsg(2), sendmmsg(2) for
> +                 an unconnected unix socket (since 6.3);
>                   **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);
> +                 **recvmsgun** call to recvfrom(2), recvmsg(2), recvmmsg(2) for
> +                 an unconnected unix socket (since 6.3);
>                   **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);
> +                 **getpeernameun** call to getpeername(2) for a unix socket (since 6.3);
>                   **getsockname4** call to getsockname(2) for an inet4 socket (since 5.8);
>                   **getsockname6** call to getsockname(2) for an inet6 socket (since 5.8).
> +                 **getsocknameun** call to getsockname(2) for a unix socket (since 6.3);
>                   **sock_release** closing an userspace inet socket (since 5.9).
>
>         **bpftool cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
> diff --git a/tools/bpf/bpftool/cgroup.c b/tools/bpf/bpftool/cgroup.c
> index ac846b0805b4..a9700e00064c 100644
> --- a/tools/bpf/bpftool/cgroup.c
> +++ b/tools/bpf/bpftool/cgroup.c
> @@ -26,13 +26,16 @@
>         "       ATTACH_TYPE := { cgroup_inet_ingress | cgroup_inet_egress |\n" \
>         "                        cgroup_inet_sock_create | cgroup_sock_ops |\n" \
>         "                        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_inet6_bind | cgroup_unix_bind |\n" \
> +       "                        cgroup_inet4_post_bind | cgroup_inet6_post_bind |\n" \
> +       "                        cgroup_inet4_connect | cgroup_inet6_connect |\n" \
> +       "                        cgroup_unix_connect | cgroup_inet4_getpeername |\n" \
> +       "                        cgroup_inet6_getpeername | cgroup_unix_getpeername |\n" \
> +       "                        cgroup_inet4_getsockname | cgroup_inet6_getsockname |\n" \
> +       "                        cgroup_unix_getsockname | cgroup_udp4_sendmsg |\n" \
> +       "                        cgroup_udp6_sendmsg | cgroup_unix_sendmsg |\n" \
> +       "                        cgroup_udp4_recvmsg | cgroup_udp6_recvmsg |\n" \
> +       "                        cgroup_unix_recvmsg | cgroup_sysctl |\n" \
>         "                        cgroup_getsockopt | cgroup_setsockopt |\n" \
>         "                        cgroup_inet_sock_release }"
>
> diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
> index 5a73ccf14332..71c219b186aa 100644
> --- a/tools/bpf/bpftool/common.c
> +++ b/tools/bpf/bpftool/common.c
> @@ -1067,19 +1067,25 @@ const char *bpf_attach_type_input_str(enum bpf_attach_type t)
>         case BPF_CGROUP_DEVICE:                 return "device";
>         case BPF_CGROUP_INET4_BIND:             return "bind4";
>         case BPF_CGROUP_INET6_BIND:             return "bind6";
> +       case BPF_CGROUP_UNIX_BIND:              return "bindun";
>         case BPF_CGROUP_INET4_CONNECT:          return "connect4";
>         case BPF_CGROUP_INET6_CONNECT:          return "connect6";
> +       case BPF_CGROUP_UNIX_CONNECT:           return "connectun";
>         case BPF_CGROUP_INET4_POST_BIND:        return "post_bind4";
>         case BPF_CGROUP_INET6_POST_BIND:        return "post_bind6";
>         case BPF_CGROUP_INET4_GETPEERNAME:      return "getpeername4";
>         case BPF_CGROUP_INET6_GETPEERNAME:      return "getpeername6";
> +       case BPF_CGROUP_UNIX_GETPEERNAME:       return "getpeernameun";
>         case BPF_CGROUP_INET4_GETSOCKNAME:      return "getsockname4";
>         case BPF_CGROUP_INET6_GETSOCKNAME:      return "getsockname6";
> +       case BPF_CGROUP_UNIX_GETSOCKNAME:       return "getsocknameun";
>         case BPF_CGROUP_UDP4_SENDMSG:           return "sendmsg4";
>         case BPF_CGROUP_UDP6_SENDMSG:           return "sendmsg6";
> +       case BPF_CGROUP_UNIX_SENDMSG:           return "sendmsgun";
>         case BPF_CGROUP_SYSCTL:                 return "sysctl";
>         case BPF_CGROUP_UDP4_RECVMSG:           return "recvmsg4";
>         case BPF_CGROUP_UDP6_RECVMSG:           return "recvmsg6";
> +       case BPF_CGROUP_UNIX_RECVMSG:           return "recvmsgun";
>         case BPF_CGROUP_GETSOCKOPT:             return "getsockopt";
>         case BPF_CGROUP_SETSOCKOPT:             return "setsockopt";
>         case BPF_TRACE_RAW_TP:                  return "raw_tp";
> --
> 2.40.0
>

Thanks a lot for this! I have two comments.

First, function bpf_attach_type_input_str() is for legacy attach types
names, those that bpftool used before commit 1ba5ad36e00f ("bpftool:
Use libbpf_bpf_attach_type_str") and that are kept for backwards
compatibility. Now we use type names provided by libbpf, so adding
them to attach_type_name in libbpf as you do in patch 7 should be
enough for bpftool to pick up the relevant names. The
bpftool-cgroup.rst man page still uses the legacy names, which I
didn't realise before your patch, and I'll need to fix. But for this
patch I think we're good without adding alternative names, and by
documenting the "cgroup/bindun" etc. forms in the man page.

Another thing is that you updated the list of types to attach programs
to cgroups, which is good, but ideally we would also need to document
the new program "types" that we can pass on the command line to
bpftool for loading programs, before attaching them (for example, we
have "bpftool prog load <elf.o> </pinned/path> type cgroup/connect4").
This means updating do_help() in prog.c, the list in
Documentation/bpftool-prog.rst, and BPFTOOL_PROG_LOAD_TYPES in
bash-completion/bpftool. Could you please update them too?

Thanks,
Quentin

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 03/10] bpf: Allow read access to addr_len from cgroup sockaddr programs
  2023-04-21 16:27 ` [PATCH bpf-next v3 03/10] bpf: Allow read access to addr_len from cgroup sockaddr programs Daan De Meyer
@ 2023-04-21 20:55   ` Alexei Starovoitov
  2023-04-24 13:58     ` Daan De Meyer
  2023-04-26 22:07   ` Martin KaFai Lau
  1 sibling, 1 reply; 25+ messages in thread
From: Alexei Starovoitov @ 2023-04-21 20:55 UTC (permalink / raw)
  To: Daan De Meyer; +Cc: bpf, martin.lau, kernel-team

On Fri, Apr 21, 2023 at 06:27:11PM +0200, Daan De Meyer wrote:
>   *
>   * This function will return %-EPERM if an attached program is found and
> - * returned value != 1 during execution. In all other cases, 0 is returned.
> + * returned value != 1 during execution. In all other cases, the new address
> + * length of the sockaddr is returned.
>   */
>  int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
>  				      struct sockaddr *uaddr,
> +				      u32 uaddrlen,
>  				      enum cgroup_bpf_attach_type atype,
>  				      void *t_ctx,
>  				      u32 *flags)
> @@ -1469,9 +1472,11 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
>  		.sk = sk,
>  		.uaddr = uaddr,
>  		.t_ctx = t_ctx,
> +		.uaddrlen = uaddrlen,
>  	};
>  	struct sockaddr_storage unspec;
>  	struct cgroup *cgrp;
> +	int ret;
>  
>  	/* Check socket family since not all sockets represent network
>  	 * endpoint (e.g. AF_UNIX).
> @@ -1482,11 +1487,16 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
>  	if (!ctx.uaddr) {
>  		memset(&unspec, 0, sizeof(unspec));
>  		ctx.uaddr = (struct sockaddr *)&unspec;
> +		ctx.uaddrlen = sizeof(unspec);
>  	}
>  
>  	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)
> +		return ret;
> +
> +	return (int) ctx.uaddrlen;

But that is big behavioral change..
instead of 0 or 1 now it will be sizeof(unspec) or 1?
That will surely break some of the __cgroup_bpf_run_filter_sock_addr callers.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 05/10] bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf
  2023-04-21 16:27 ` [PATCH bpf-next v3 05/10] bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf Daan De Meyer
@ 2023-04-21 21:01   ` Alexei Starovoitov
  2023-04-24 14:07     ` Daan De Meyer
  2023-04-26 21:30   ` Martin KaFai Lau
  1 sibling, 1 reply; 25+ messages in thread
From: Alexei Starovoitov @ 2023-04-21 21:01 UTC (permalink / raw)
  To: Daan De Meyer; +Cc: bpf, martin.lau, kernel-team

On Fri, Apr 21, 2023 at 06:27:13PM +0200, Daan De Meyer wrote:
> As prep for adding unix socket support to the cgroup sockaddr hooks,
> let's add a kfunc bpf_sock_addr_set() that allows modifying the
> sockaddr length from bpf. This is required to allow modifying AF_UNIX
> sockaddrs correctly.
> 
> Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
> ---
>  net/core/filter.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 51 insertions(+), 1 deletion(-)
> 
> diff --git a/net/core/filter.c b/net/core/filter.c
> index 44fb997434ad..1c656e2d7b58 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -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);
> @@ -11670,6 +11671,44 @@ __bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_buff *xdp, u64 flags,
>  
>  	return 0;
>  }
> +
> +__bpf_kfunc int bpf_sock_addr_set(struct bpf_sock_addr_kern *sa_kern,
> +				  const void *addr, u32 addrlen__sz)

I think the verifier doesn't check validity of void* pointer for kfuncs.
Should it be 'struct sockaddr_un *' ?

> +{
> +	const struct sockaddr *sa = addr;
> +
> +	if (addrlen__sz <= offsetof(struct sockaddr, sa_family))
> +		return -EINVAL;
> +
> +	if (addrlen__sz > sizeof(struct sockaddr_storage))
> +		return -EINVAL;
> +
> +	if (sa->sa_family != sa_kern->uaddr->sa_family)
> +		return -EINVAL;
> +
> +	switch (sa->sa_family) {
> +	case AF_INET:
> +		if (addrlen__sz < sizeof(struct sockaddr_in))
> +			return -EINVAL;
> +		break;
> +	case AF_INET6:
> +		if (addrlen__sz < SIN6_LEN_RFC2133)
> +			return -EINVAL;
> +		break;
> +	case AF_UNIX:
> +		if (addrlen__sz <= offsetof(struct sockaddr_un, sun_path) ||
> +		    addrlen__sz > sizeof(struct sockaddr_un))
> +			return -EINVAL;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	memcpy(sa_kern->uaddr, sa, addrlen__sz);
> +	sa_kern->uaddrlen = addrlen__sz;
> +
> +	return 0;
> +}
>  __diag_pop();
>  
>  int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags,
> @@ -11694,6 +11733,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)

It probably needs KF_TRUSTED_ARGS.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 03/10] bpf: Allow read access to addr_len from cgroup sockaddr programs
  2023-04-21 20:55   ` Alexei Starovoitov
@ 2023-04-24 13:58     ` Daan De Meyer
  2023-04-26  0:05       ` Alexei Starovoitov
  0 siblings, 1 reply; 25+ messages in thread
From: Daan De Meyer @ 2023-04-24 13:58 UTC (permalink / raw)
  To: Alexei Starovoitov; +Cc: bpf, martin.lau, kernel-team

> On Fri, Apr 21, 2023 at 06:27:11PM +0200, Daan De Meyer wrote:
> >   *
> >   * This function will return %-EPERM if an attached program is found and
> > - * returned value != 1 during execution. In all other cases, 0 is returned.
> > + * returned value != 1 during execution. In all other cases, the new address
> > + * length of the sockaddr is returned.
> >   */
> >  int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> >                                     struct sockaddr *uaddr,
> > +                                   u32 uaddrlen,
> >                                     enum cgroup_bpf_attach_type atype,
> >                                     void *t_ctx,
> >                                     u32 *flags)
> > @@ -1469,9 +1472,11 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> >               .sk = sk,
> >               .uaddr = uaddr,
> >               .t_ctx = t_ctx,
> > +             .uaddrlen = uaddrlen,
> >       };
> >       struct sockaddr_storage unspec;
> >       struct cgroup *cgrp;
> > +     int ret;
> >
> >       /* Check socket family since not all sockets represent network
> >        * endpoint (e.g. AF_UNIX).
> > @@ -1482,11 +1487,16 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> >       if (!ctx.uaddr) {
> >               memset(&unspec, 0, sizeof(unspec));
> >               ctx.uaddr = (struct sockaddr *)&unspec;
> > +             ctx.uaddrlen = sizeof(unspec);
> >       }
> >
> >       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)
> > +             return ret;
> > +
> > +     return (int) ctx.uaddrlen;
>
> But that is big behavioral change..
> instead of 0 or 1 now it will be sizeof(unspec) or 1?
> That will surely break some of the __cgroup_bpf_run_filter_sock_addr callers.

It will now always return the size of the addrlen as set by the bpf
program or the original addrlen if the bpf program did not change it.
I modified all the callers of __cgroup_bpf_run_filter_sock_addr() to
ignore the returned addrlen so as to not introduce any breakages. Only
when unix socket support is introduced in the following patch do we
actually start making use of the addrlen returned by
__cgroup_bpf_run_filter_sock_addr(). Alternatively, I can pass in an
optional pointer to __cgroup_bpf_run_filter_sock_addr() which is set
to the modified addrlen if it is provided and then only make use of
this in af_unix.c, but I figure since we're already returning an int,
we can use that to propagate the modified address length as well.

bpf_prog_run_array_cg() will return either 0 or -EPERM so we'll either
return an error if an error occurs or the modified address length if
no error occurs.

For the default size of the address length if none is provided, I used
sizeof(unspec) since that's the size of the memory we provide to the
BPF program, but I suppose that zero could also make sense here, to
indicate that we're providing an empty address. Let me know which one
is preferred.


On Fri, 21 Apr 2023 at 22:55, Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Fri, Apr 21, 2023 at 06:27:11PM +0200, Daan De Meyer wrote:
> >   *
> >   * This function will return %-EPERM if an attached program is found and
> > - * returned value != 1 during execution. In all other cases, 0 is returned.
> > + * returned value != 1 during execution. In all other cases, the new address
> > + * length of the sockaddr is returned.
> >   */
> >  int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> >                                     struct sockaddr *uaddr,
> > +                                   u32 uaddrlen,
> >                                     enum cgroup_bpf_attach_type atype,
> >                                     void *t_ctx,
> >                                     u32 *flags)
> > @@ -1469,9 +1472,11 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> >               .sk = sk,
> >               .uaddr = uaddr,
> >               .t_ctx = t_ctx,
> > +             .uaddrlen = uaddrlen,
> >       };
> >       struct sockaddr_storage unspec;
> >       struct cgroup *cgrp;
> > +     int ret;
> >
> >       /* Check socket family since not all sockets represent network
> >        * endpoint (e.g. AF_UNIX).
> > @@ -1482,11 +1487,16 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> >       if (!ctx.uaddr) {
> >               memset(&unspec, 0, sizeof(unspec));
> >               ctx.uaddr = (struct sockaddr *)&unspec;
> > +             ctx.uaddrlen = sizeof(unspec);
> >       }
> >
> >       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)
> > +             return ret;
> > +
> > +     return (int) ctx.uaddrlen;
>
> But that is big behavioral change..
> instead of 0 or 1 now it will be sizeof(unspec) or 1?
> That will surely break some of the __cgroup_bpf_run_filter_sock_addr callers.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 05/10] bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf
  2023-04-21 21:01   ` Alexei Starovoitov
@ 2023-04-24 14:07     ` Daan De Meyer
  2023-04-26  0:10       ` Alexei Starovoitov
  0 siblings, 1 reply; 25+ messages in thread
From: Daan De Meyer @ 2023-04-24 14:07 UTC (permalink / raw)
  To: Alexei Starovoitov; +Cc: bpf, martin.lau, kernel-team

bpf_sock_addr_set
> On Fri, Apr 21, 2023 at 06:27:13PM +0200, Daan De Meyer wrote:
> > As prep for adding unix socket support to the cgroup sockaddr hooks,
> > let's add a kfunc bpf_sock_addr_set() that allows modifying the
> > sockaddr length from bpf. This is required to allow modifying AF_UNIX
> > sockaddrs correctly.
> >
> > Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
> > ---
> >  net/core/filter.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 51 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/core/filter.c b/net/core/filter.c
> > index 44fb997434ad..1c656e2d7b58 100644
> > --- a/net/core/filter.c
> > +++ b/net/core/filter.c
> > @@ -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);
> > @@ -11670,6 +11671,44 @@ __bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_buff *xdp, u64 flags,
> >
> >       return 0;
> >  }
> > +
> > +__bpf_kfunc int bpf_sock_addr_set(struct bpf_sock_addr_kern *sa_kern,
> > +                               const void *addr, u32 addrlen__sz)
>
> I think the verifier doesn't check validity of void* pointer for kfuncs.
> Should it be 'struct sockaddr_un *' ?

I had to make it 'void *' because the __sz tag only works on void
pointers. If it should be 'struct sockaddr_un *', how do I make the
addrlen__sz tag work properly?

> > +{
> > +     const struct sockaddr *sa = addr;
> > +
> > +     if (addrlen__sz <= offsetof(struct sockaddr, sa_family))
> > +             return -EINVAL;
> > +
> > +     if (addrlen__sz > sizeof(struct sockaddr_storage))
> > +             return -EINVAL;
> > +
> > +     if (sa->sa_family != sa_kern->uaddr->sa_family)
> > +             return -EINVAL;
> > +
> > +     switch (sa->sa_family) {
> > +     case AF_INET:
> > +             if (addrlen__sz < sizeof(struct sockaddr_in))
> > +                     return -EINVAL;
> > +             break;
> > +     case AF_INET6:
> > +             if (addrlen__sz < SIN6_LEN_RFC2133)
> > +                     return -EINVAL;
> > +             break;
> > +     case AF_UNIX:
> > +             if (addrlen__sz <= offsetof(struct sockaddr_un, sun_path) ||
> > +                 addrlen__sz > sizeof(struct sockaddr_un))
> > +                     return -EINVAL;
> > +             break;
> > +     default:
> > +             return -EINVAL;
> > +     }
> > +
> > +     memcpy(sa_kern->uaddr, sa, addrlen__sz);
> > +     sa_kern->uaddrlen = addrlen__sz;
> > +
> > +     return 0;
> > +}
> >  __diag_pop();
> >
> >  int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags,
> > @@ -11694,6 +11733,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)
>
> It probably needs KF_TRUSTED_ARGS.

If I understand the documentation of `KF_TRUSTED_ARGS` correctly, this
wouldn't allow me to pass arbitrary sockaddr structs into
bpf_sock_addr_set() anymore since those wouldn't be trusted?


On Fri, 21 Apr 2023 at 23:01, Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Fri, Apr 21, 2023 at 06:27:13PM +0200, Daan De Meyer wrote:
> > As prep for adding unix socket support to the cgroup sockaddr hooks,
> > let's add a kfunc bpf_sock_addr_set() that allows modifying the
> > sockaddr length from bpf. This is required to allow modifying AF_UNIX
> > sockaddrs correctly.
> >
> > Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
> > ---
> >  net/core/filter.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 51 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/core/filter.c b/net/core/filter.c
> > index 44fb997434ad..1c656e2d7b58 100644
> > --- a/net/core/filter.c
> > +++ b/net/core/filter.c
> > @@ -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);
> > @@ -11670,6 +11671,44 @@ __bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_buff *xdp, u64 flags,
> >
> >       return 0;
> >  }
> > +
> > +__bpf_kfunc int bpf_sock_addr_set(struct bpf_sock_addr_kern *sa_kern,
> > +                               const void *addr, u32 addrlen__sz)
>
> I think the verifier doesn't check validity of void* pointer for kfuncs.
> Should it be 'struct sockaddr_un *' ?
>
> > +{
> > +     const struct sockaddr *sa = addr;
> > +
> > +     if (addrlen__sz <= offsetof(struct sockaddr, sa_family))
> > +             return -EINVAL;
> > +
> > +     if (addrlen__sz > sizeof(struct sockaddr_storage))
> > +             return -EINVAL;
> > +
> > +     if (sa->sa_family != sa_kern->uaddr->sa_family)
> > +             return -EINVAL;
> > +
> > +     switch (sa->sa_family) {
> > +     case AF_INET:
> > +             if (addrlen__sz < sizeof(struct sockaddr_in))
> > +                     return -EINVAL;
> > +             break;
> > +     case AF_INET6:
> > +             if (addrlen__sz < SIN6_LEN_RFC2133)
> > +                     return -EINVAL;
> > +             break;
> > +     case AF_UNIX:
> > +             if (addrlen__sz <= offsetof(struct sockaddr_un, sun_path) ||
> > +                 addrlen__sz > sizeof(struct sockaddr_un))
> > +                     return -EINVAL;
> > +             break;
> > +     default:
> > +             return -EINVAL;
> > +     }
> > +
> > +     memcpy(sa_kern->uaddr, sa, addrlen__sz);
> > +     sa_kern->uaddrlen = addrlen__sz;
> > +
> > +     return 0;
> > +}
> >  __diag_pop();
> >
> >  int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags,
> > @@ -11694,6 +11733,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)
>
> It probably needs KF_TRUSTED_ARGS.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 03/10] bpf: Allow read access to addr_len from cgroup sockaddr programs
  2023-04-24 13:58     ` Daan De Meyer
@ 2023-04-26  0:05       ` Alexei Starovoitov
  2023-04-26 13:46         ` Daan De Meyer
  0 siblings, 1 reply; 25+ messages in thread
From: Alexei Starovoitov @ 2023-04-26  0:05 UTC (permalink / raw)
  To: Daan De Meyer; +Cc: bpf, martin.lau, kernel-team

On Mon, Apr 24, 2023 at 03:58:24PM +0200, Daan De Meyer wrote:
> > On Fri, Apr 21, 2023 at 06:27:11PM +0200, Daan De Meyer wrote:
> > >   *
> > >   * This function will return %-EPERM if an attached program is found and
> > > - * returned value != 1 during execution. In all other cases, 0 is returned.
> > > + * returned value != 1 during execution. In all other cases, the new address
> > > + * length of the sockaddr is returned.
> > >   */
> > >  int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> > >                                     struct sockaddr *uaddr,
> > > +                                   u32 uaddrlen,
> > >                                     enum cgroup_bpf_attach_type atype,
> > >                                     void *t_ctx,
> > >                                     u32 *flags)
> > > @@ -1469,9 +1472,11 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> > >               .sk = sk,
> > >               .uaddr = uaddr,
> > >               .t_ctx = t_ctx,
> > > +             .uaddrlen = uaddrlen,
> > >       };
> > >       struct sockaddr_storage unspec;
> > >       struct cgroup *cgrp;
> > > +     int ret;
> > >
> > >       /* Check socket family since not all sockets represent network
> > >        * endpoint (e.g. AF_UNIX).
> > > @@ -1482,11 +1487,16 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> > >       if (!ctx.uaddr) {
> > >               memset(&unspec, 0, sizeof(unspec));
> > >               ctx.uaddr = (struct sockaddr *)&unspec;
> > > +             ctx.uaddrlen = sizeof(unspec);
> > >       }
> > >
> > >       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)
> > > +             return ret;
> > > +
> > > +     return (int) ctx.uaddrlen;
> >
> > But that is big behavioral change..
> > instead of 0 or 1 now it will be sizeof(unspec) or 1?
> > That will surely break some of the __cgroup_bpf_run_filter_sock_addr callers.
> 
> It will now always return the size of the addrlen as set by the bpf
> program or the original addrlen if the bpf program did not change it.
> I modified all the callers of __cgroup_bpf_run_filter_sock_addr() to
> ignore the returned addrlen so as to not introduce any breakages. Only
> when unix socket support is introduced in the following patch do we
> actually start making use of the addrlen returned by
> __cgroup_bpf_run_filter_sock_addr(). Alternatively, I can pass in an
> optional pointer to __cgroup_bpf_run_filter_sock_addr() which is set
> to the modified addrlen if it is provided and then only make use of
> this in af_unix.c, but I figure since we're already returning an int,
> we can use that to propagate the modified address length as well.
> 
> bpf_prog_run_array_cg() will return either 0 or -EPERM so we'll either
> return an error if an error occurs or the modified address length if
> no error occurs.
> 
> For the default size of the address length if none is provided, I used
> sizeof(unspec) since that's the size of the memory we provide to the
> BPF program, but I suppose that zero could also make sense here, to
> indicate that we're providing an empty address. Let me know which one
> is preferred.

I still don't understand how it's possible to modify the callers to
have correct behavior.

- return bpf_prog_run_array_cg();
+ ret = bpf_prog_run_array_cg();
+       if (ret)
+               return ret;
+
+       return (int) ctx.uaddrlen;

It used to return 0 or 1.
Now 1 is indistinguishable between 1 from prog and 0 from prog, but uaddrlen == 1.
I don't see how callers can deal with that.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 05/10] bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf
  2023-04-24 14:07     ` Daan De Meyer
@ 2023-04-26  0:10       ` Alexei Starovoitov
  2023-04-26 13:51         ` Daan De Meyer
  0 siblings, 1 reply; 25+ messages in thread
From: Alexei Starovoitov @ 2023-04-26  0:10 UTC (permalink / raw)
  To: Daan De Meyer; +Cc: bpf, martin.lau, kernel-team

On Mon, Apr 24, 2023 at 04:07:13PM +0200, Daan De Meyer wrote:
> bpf_sock_addr_set
> > On Fri, Apr 21, 2023 at 06:27:13PM +0200, Daan De Meyer wrote:
> > > As prep for adding unix socket support to the cgroup sockaddr hooks,
> > > let's add a kfunc bpf_sock_addr_set() that allows modifying the
> > > sockaddr length from bpf. This is required to allow modifying AF_UNIX
> > > sockaddrs correctly.
> > >
> > > Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
> > > ---
> > >  net/core/filter.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++-
> > >  1 file changed, 51 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/net/core/filter.c b/net/core/filter.c
> > > index 44fb997434ad..1c656e2d7b58 100644
> > > --- a/net/core/filter.c
> > > +++ b/net/core/filter.c
> > > @@ -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);
> > > @@ -11670,6 +11671,44 @@ __bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_buff *xdp, u64 flags,
> > >
> > >       return 0;
> > >  }
> > > +
> > > +__bpf_kfunc int bpf_sock_addr_set(struct bpf_sock_addr_kern *sa_kern,
> > > +                               const void *addr, u32 addrlen__sz)
> >
> > I think the verifier doesn't check validity of void* pointer for kfuncs.
> > Should it be 'struct sockaddr_un *' ?
> 
> I had to make it 'void *' because the __sz tag only works on void
> pointers. 

Why do you think so?

__bpf_kfunc struct nf_conn___init *
bpf_xdp_ct_alloc(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple,
                 u32 tuple__sz, struct bpf_ct_opts *opts, u32 opts__sz)
hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
                   enum hid_report_type rtype, enum hid_class_request reqtype)

> If it should be 'struct sockaddr_un *', how do I make the
> addrlen__sz tag work properly?
> 
> > > +{
> > > +     const struct sockaddr *sa = addr;
> > > +
> > > +     if (addrlen__sz <= offsetof(struct sockaddr, sa_family))
> > > +             return -EINVAL;
> > > +
> > > +     if (addrlen__sz > sizeof(struct sockaddr_storage))
> > > +             return -EINVAL;
> > > +
> > > +     if (sa->sa_family != sa_kern->uaddr->sa_family)
> > > +             return -EINVAL;
> > > +
> > > +     switch (sa->sa_family) {
> > > +     case AF_INET:
> > > +             if (addrlen__sz < sizeof(struct sockaddr_in))
> > > +                     return -EINVAL;
> > > +             break;
> > > +     case AF_INET6:
> > > +             if (addrlen__sz < SIN6_LEN_RFC2133)
> > > +                     return -EINVAL;
> > > +             break;
> > > +     case AF_UNIX:
> > > +             if (addrlen__sz <= offsetof(struct sockaddr_un, sun_path) ||
> > > +                 addrlen__sz > sizeof(struct sockaddr_un))
> > > +                     return -EINVAL;
> > > +             break;
> > > +     default:
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     memcpy(sa_kern->uaddr, sa, addrlen__sz);
> > > +     sa_kern->uaddrlen = addrlen__sz;
> > > +
> > > +     return 0;
> > > +}
> > >  __diag_pop();
> > >
> > >  int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags,
> > > @@ -11694,6 +11733,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)
> >
> > It probably needs KF_TRUSTED_ARGS.
> 
> If I understand the documentation of `KF_TRUSTED_ARGS` correctly, this
> wouldn't allow me to pass arbitrary sockaddr structs into
> bpf_sock_addr_set() anymore since those wouldn't be trusted?

KF_TRUSTED_ARGS won't allow legacy and untrusted PTR_TO_BTF_ID to
be passed into as 1st arg == struct bpf_sock_addr_kern *.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 03/10] bpf: Allow read access to addr_len from cgroup sockaddr programs
  2023-04-26  0:05       ` Alexei Starovoitov
@ 2023-04-26 13:46         ` Daan De Meyer
  0 siblings, 0 replies; 25+ messages in thread
From: Daan De Meyer @ 2023-04-26 13:46 UTC (permalink / raw)
  To: Alexei Starovoitov; +Cc: bpf, martin.lau, kernel-team

> On Mon, Apr 24, 2023 at 03:58:24PM +0200, Daan De Meyer wrote:
> > > On Fri, Apr 21, 2023 at 06:27:11PM +0200, Daan De Meyer wrote:
> > > >   *
> > > >   * This function will return %-EPERM if an attached program is found and
> > > > - * returned value != 1 during execution. In all other cases, 0 is returned.
> > > > + * returned value != 1 during execution. In all other cases, the new address
> > > > + * length of the sockaddr is returned.
> > > >   */
> > > >  int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> > > >                                     struct sockaddr *uaddr,
> > > > +                                   u32 uaddrlen,
> > > >                                     enum cgroup_bpf_attach_type atype,
> > > >                                     void *t_ctx,
> > > >                                     u32 *flags)
> > > > @@ -1469,9 +1472,11 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> > > >               .sk = sk,
> > > >               .uaddr = uaddr,
> > > >               .t_ctx = t_ctx,
> > > > +             .uaddrlen = uaddrlen,
> > > >       };
> > > >       struct sockaddr_storage unspec;
> > > >       struct cgroup *cgrp;
> > > > +     int ret;
> > > >
> > > >       /* Check socket family since not all sockets represent network
> > > >        * endpoint (e.g. AF_UNIX).
> > > > @@ -1482,11 +1487,16 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> > > >       if (!ctx.uaddr) {
> > > >               memset(&unspec, 0, sizeof(unspec));
> > > >               ctx.uaddr = (struct sockaddr *)&unspec;
> > > > +             ctx.uaddrlen = sizeof(unspec);
> > > >       }
> > > >
> > > >       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)
> > > > +             return ret;
> > > > +
> > > > +     return (int) ctx.uaddrlen;
> > >
> > > But that is big behavioral change..
> > > instead of 0 or 1 now it will be sizeof(unspec) or 1?
> > > That will surely break some of the __cgroup_bpf_run_filter_sock_addr callers.
> >
> > It will now always return the size of the addrlen as set by the bpf
> > program or the original addrlen if the bpf program did not change it.
> > I modified all the callers of __cgroup_bpf_run_filter_sock_addr() to
> > ignore the returned addrlen so as to not introduce any breakages. Only
> > when unix socket support is introduced in the following patch do we
> > actually start making use of the addrlen returned by
> > __cgroup_bpf_run_filter_sock_addr(). Alternatively, I can pass in an
> > optional pointer to __cgroup_bpf_run_filter_sock_addr() which is set
> > to the modified addrlen if it is provided and then only make use of
> > this in af_unix.c, but I figure since we're already returning an int,
> > we can use that to propagate the modified address length as well.
> >
> > bpf_prog_run_array_cg() will return either 0 or -EPERM so we'll either
> > return an error if an error occurs or the modified address length if
> > no error occurs.
> >
> > For the default size of the address length if none is provided, I used
> > sizeof(unspec) since that's the size of the memory we provide to the
> > BPF program, but I suppose that zero could also make sense here, to
> > indicate that we're providing an empty address. Let me know which one
> > is preferred.
>
> I still don't understand how it's possible to modify the callers to
> have correct behavior.
>
> - return bpf_prog_run_array_cg();
> + ret = bpf_prog_run_array_cg();
> +       if (ret)
> +               return ret;
> +
> +       return (int) ctx.uaddrlen;
>
> It used to return 0 or 1.
> Now 1 is indistinguishable between 1 from prog and 0 from prog, but uaddrlen == 1.
> I don't see how callers can deal with that.

I think I'm missing something crucial somewhere. If I understand
bpf_prog_run_array_cg(() correctly, when called with retval = 0, it
will return -EPERM on failure and 0 on success. If I understand that
correctly, with this change, we'll still return -EPERM on failure but
instead of returning 0 on success, we'll now return the address
length. Am I misunderstanding how bpf_prog_run_array_cg() behaves in
this case?


On Wed, 26 Apr 2023 at 02:06, Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Mon, Apr 24, 2023 at 03:58:24PM +0200, Daan De Meyer wrote:
> > > On Fri, Apr 21, 2023 at 06:27:11PM +0200, Daan De Meyer wrote:
> > > >   *
> > > >   * This function will return %-EPERM if an attached program is found and
> > > > - * returned value != 1 during execution. In all other cases, 0 is returned.
> > > > + * returned value != 1 during execution. In all other cases, the new address
> > > > + * length of the sockaddr is returned.
> > > >   */
> > > >  int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> > > >                                     struct sockaddr *uaddr,
> > > > +                                   u32 uaddrlen,
> > > >                                     enum cgroup_bpf_attach_type atype,
> > > >                                     void *t_ctx,
> > > >                                     u32 *flags)
> > > > @@ -1469,9 +1472,11 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> > > >               .sk = sk,
> > > >               .uaddr = uaddr,
> > > >               .t_ctx = t_ctx,
> > > > +             .uaddrlen = uaddrlen,
> > > >       };
> > > >       struct sockaddr_storage unspec;
> > > >       struct cgroup *cgrp;
> > > > +     int ret;
> > > >
> > > >       /* Check socket family since not all sockets represent network
> > > >        * endpoint (e.g. AF_UNIX).
> > > > @@ -1482,11 +1487,16 @@ int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
> > > >       if (!ctx.uaddr) {
> > > >               memset(&unspec, 0, sizeof(unspec));
> > > >               ctx.uaddr = (struct sockaddr *)&unspec;
> > > > +             ctx.uaddrlen = sizeof(unspec);
> > > >       }
> > > >
> > > >       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)
> > > > +             return ret;
> > > > +
> > > > +     return (int) ctx.uaddrlen;
> > >
> > > But that is big behavioral change..
> > > instead of 0 or 1 now it will be sizeof(unspec) or 1?
> > > That will surely break some of the __cgroup_bpf_run_filter_sock_addr callers.
> >
> > It will now always return the size of the addrlen as set by the bpf
> > program or the original addrlen if the bpf program did not change it.
> > I modified all the callers of __cgroup_bpf_run_filter_sock_addr() to
> > ignore the returned addrlen so as to not introduce any breakages. Only
> > when unix socket support is introduced in the following patch do we
> > actually start making use of the addrlen returned by
> > __cgroup_bpf_run_filter_sock_addr(). Alternatively, I can pass in an
> > optional pointer to __cgroup_bpf_run_filter_sock_addr() which is set
> > to the modified addrlen if it is provided and then only make use of
> > this in af_unix.c, but I figure since we're already returning an int,
> > we can use that to propagate the modified address length as well.
> >
> > bpf_prog_run_array_cg() will return either 0 or -EPERM so we'll either
> > return an error if an error occurs or the modified address length if
> > no error occurs.
> >
> > For the default size of the address length if none is provided, I used
> > sizeof(unspec) since that's the size of the memory we provide to the
> > BPF program, but I suppose that zero could also make sense here, to
> > indicate that we're providing an empty address. Let me know which one
> > is preferred.
>
> I still don't understand how it's possible to modify the callers to
> have correct behavior.
>
> - return bpf_prog_run_array_cg();
> + ret = bpf_prog_run_array_cg();
> +       if (ret)
> +               return ret;
> +
> +       return (int) ctx.uaddrlen;
>
> It used to return 0 or 1.
> Now 1 is indistinguishable between 1 from prog and 0 from prog, but uaddrlen == 1.
> I don't see how callers can deal with that.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 05/10] bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf
  2023-04-26  0:10       ` Alexei Starovoitov
@ 2023-04-26 13:51         ` Daan De Meyer
  0 siblings, 0 replies; 25+ messages in thread
From: Daan De Meyer @ 2023-04-26 13:51 UTC (permalink / raw)
  To: Alexei Starovoitov; +Cc: bpf, martin.lau, kernel-team

> On Mon, Apr 24, 2023 at 04:07:13PM +0200, Daan De Meyer wrote:
> > bpf_sock_addr_set
> > > On Fri, Apr 21, 2023 at 06:27:13PM +0200, Daan De Meyer wrote:
> > > > As prep for adding unix socket support to the cgroup sockaddr hooks,
> > > > let's add a kfunc bpf_sock_addr_set() that allows modifying the
> > > > sockaddr length from bpf. This is required to allow modifying AF_UNIX
> > > > sockaddrs correctly.
> > > >
> > > > Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
> > > > ---
> > > >  net/core/filter.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++-
> > > >  1 file changed, 51 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/net/core/filter.c b/net/core/filter.c
> > > > index 44fb997434ad..1c656e2d7b58 100644
> > > > --- a/net/core/filter.c
> > > > +++ b/net/core/filter.c
> > > > @@ -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);
> > > > @@ -11670,6 +11671,44 @@ __bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_buff *xdp, u64 flags,
> > > >
> > > >       return 0;
> > > >  }
> > > > +
> > > > +__bpf_kfunc int bpf_sock_addr_set(struct bpf_sock_addr_kern *sa_kern,
> > > > +                               const void *addr, u32 addrlen__sz)
> > >
> > > I think the verifier doesn't check validity of void* pointer for kfuncs.
> > > Should it be 'struct sockaddr_un *' ?
> >
> > I had to make it 'void *' because the __sz tag only works on void
> > pointers.
>
> Why do you think so?
>
> __bpf_kfunc struct nf_conn___init *
> bpf_xdp_ct_alloc(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple,
>                  u32 tuple__sz, struct bpf_ct_opts *opts, u32 opts__sz)
> hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
>                    enum hid_report_type rtype, enum hid_class_request reqtype)
> KF_TRUSTED_ARGS won't allow legacy and untrusted PTR_TO_BTF_ID to
> be passed into as 1st arg == struct bpf_sock_addr_kern *.

Because of the following check in get_kfunc_ptr_arg_type():

if (!btf_type_is_scalar(ref_t) && !__btf_type_is_scalar_struct(env,
meta->btf, ref_t, 0) &&
(arg_mem_size ? !btf_type_is_void(ref_t) : 1)) {
        verbose(env, "arg#%d pointer type %s %s must point to
%sscalar, or struct with scalar\n",
        argno, btf_type_str(ref_t), ref_tname, arg_mem_size ? "void, " : "");
        return -EINVAL;
}

I was hitting this error when addr was sockaddr_un * instead of void
*. Will KF_TRUSTED_ARGS
bypass that check?


On Wed, 26 Apr 2023 at 02:10, Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Mon, Apr 24, 2023 at 04:07:13PM +0200, Daan De Meyer wrote:
> > bpf_sock_addr_set
> > > On Fri, Apr 21, 2023 at 06:27:13PM +0200, Daan De Meyer wrote:
> > > > As prep for adding unix socket support to the cgroup sockaddr hooks,
> > > > let's add a kfunc bpf_sock_addr_set() that allows modifying the
> > > > sockaddr length from bpf. This is required to allow modifying AF_UNIX
> > > > sockaddrs correctly.
> > > >
> > > > Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
> > > > ---
> > > >  net/core/filter.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++-
> > > >  1 file changed, 51 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/net/core/filter.c b/net/core/filter.c
> > > > index 44fb997434ad..1c656e2d7b58 100644
> > > > --- a/net/core/filter.c
> > > > +++ b/net/core/filter.c
> > > > @@ -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);
> > > > @@ -11670,6 +11671,44 @@ __bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_buff *xdp, u64 flags,
> > > >
> > > >       return 0;
> > > >  }
> > > > +
> > > > +__bpf_kfunc int bpf_sock_addr_set(struct bpf_sock_addr_kern *sa_kern,
> > > > +                               const void *addr, u32 addrlen__sz)
> > >
> > > I think the verifier doesn't check validity of void* pointer for kfuncs.
> > > Should it be 'struct sockaddr_un *' ?
> >
> > I had to make it 'void *' because the __sz tag only works on void
> > pointers.
>
> Why do you think so?
>
> __bpf_kfunc struct nf_conn___init *
> bpf_xdp_ct_alloc(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple,
>                  u32 tuple__sz, struct bpf_ct_opts *opts, u32 opts__sz)
> hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
>                    enum hid_report_type rtype, enum hid_class_request reqtype)
>
> > If it should be 'struct sockaddr_un *', how do I make the
> > addrlen__sz tag work properly?
> >
> > > > +{
> > > > +     const struct sockaddr *sa = addr;
> > > > +
> > > > +     if (addrlen__sz <= offsetof(struct sockaddr, sa_family))
> > > > +             return -EINVAL;
> > > > +
> > > > +     if (addrlen__sz > sizeof(struct sockaddr_storage))
> > > > +             return -EINVAL;
> > > > +
> > > > +     if (sa->sa_family != sa_kern->uaddr->sa_family)
> > > > +             return -EINVAL;
> > > > +
> > > > +     switch (sa->sa_family) {
> > > > +     case AF_INET:
> > > > +             if (addrlen__sz < sizeof(struct sockaddr_in))
> > > > +                     return -EINVAL;
> > > > +             break;
> > > > +     case AF_INET6:
> > > > +             if (addrlen__sz < SIN6_LEN_RFC2133)
> > > > +                     return -EINVAL;
> > > > +             break;
> > > > +     case AF_UNIX:
> > > > +             if (addrlen__sz <= offsetof(struct sockaddr_un, sun_path) ||
> > > > +                 addrlen__sz > sizeof(struct sockaddr_un))
> > > > +                     return -EINVAL;
> > > > +             break;
> > > > +     default:
> > > > +             return -EINVAL;
> > > > +     }
> > > > +
> > > > +     memcpy(sa_kern->uaddr, sa, addrlen__sz);
> > > > +     sa_kern->uaddrlen = addrlen__sz;
> > > > +
> > > > +     return 0;
> > > > +}
> > > >  __diag_pop();
> > > >
> > > >  int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags,
> > > > @@ -11694,6 +11733,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)
> > >
> > > It probably needs KF_TRUSTED_ARGS.
> >
> > If I understand the documentation of `KF_TRUSTED_ARGS` correctly, this
> > wouldn't allow me to pass arbitrary sockaddr structs into
> > bpf_sock_addr_set() anymore since those wouldn't be trusted?
>
> KF_TRUSTED_ARGS won't allow legacy and untrusted PTR_TO_BTF_ID to
> be passed into as 1st arg == struct bpf_sock_addr_kern *.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 05/10] bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf
  2023-04-21 16:27 ` [PATCH bpf-next v3 05/10] bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf Daan De Meyer
  2023-04-21 21:01   ` Alexei Starovoitov
@ 2023-04-26 21:30   ` Martin KaFai Lau
  1 sibling, 0 replies; 25+ messages in thread
From: Martin KaFai Lau @ 2023-04-26 21:30 UTC (permalink / raw)
  To: Daan De Meyer; +Cc: kernel-team, bpf

On 4/21/23 9:27 AM, Daan De Meyer wrote:
> As prep for adding unix socket support to the cgroup sockaddr hooks,
> let's add a kfunc bpf_sock_addr_set() that allows modifying the
> sockaddr length from bpf. This is required to allow modifying AF_UNIX
> sockaddrs correctly.
> 
> Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
> ---
>   net/core/filter.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 51 insertions(+), 1 deletion(-)
> 
> diff --git a/net/core/filter.c b/net/core/filter.c
> index 44fb997434ad..1c656e2d7b58 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -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);
> @@ -11670,6 +11671,44 @@ __bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_buff *xdp, u64 flags,
>   
>   	return 0;
>   }
> +
> +__bpf_kfunc int bpf_sock_addr_set(struct bpf_sock_addr_kern *sa_kern,
> +				  const void *addr, u32 addrlen__sz)
> +{
> +	const struct sockaddr *sa = addr;
> +
> +	if (addrlen__sz <= offsetof(struct sockaddr, sa_family))
> +		return -EINVAL;
> +
> +	if (addrlen__sz > sizeof(struct sockaddr_storage))
> +		return -EINVAL;
> +
> +	if (sa->sa_family != sa_kern->uaddr->sa_family)
> +		return -EINVAL;
> +
> +	switch (sa->sa_family) {
> +	case AF_INET:
> +		if (addrlen__sz < sizeof(struct sockaddr_in))
> +			return -EINVAL;
> +		break;
> +	case AF_INET6:
> +		if (addrlen__sz < SIN6_LEN_RFC2133)
> +			return -EINVAL;
> +		break;
> +	case AF_UNIX:
> +		if (addrlen__sz <= offsetof(struct sockaddr_un, sun_path) ||
> +		    addrlen__sz > sizeof(struct sockaddr_un))
> +			return -EINVAL;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	memcpy(sa_kern->uaddr, sa, addrlen__sz);

Can you check whether the current inet* hooks can support changing sin[6]_* 
other than the sin[6]_addr part? e.g. from looking at inet6_getname(), bpf prog 
changing sin6_scope_id does not get through. Also, if I read the patches 
correctly, an increased sa_kern->uaddrlen is getting silently ignored for 
inet[6] hooks and it does not look right. e.g. for IPv6, what if the bpf prog 
set uaddrlen larger to include the sin6_scope_id?

or tweak the kfunc a little to only allow changing the sin[6]_addr and sun_path. 
Something like this (uncompiled code):

__bpf_kfunc int bpf_sock_addr_set(struct bpf_sock_addr_kern *sa_kern,
				  const u8 *addr, u32 addrlen__sz)
{
	struct sockaddr *sa = sa_kern->uaddr;
	struct sockaddr_in *sa4;
	struct sockaddr_in6 *sa6;
	struct sockaddr_un *un;

	switch (sa_kern->sk->sk_family) {
	case AF_INET:
		if (addrlen__sz != 4)
			return -EINVAL;
		sa4 = (struct sockaddr_in *)sa;
		sa4->sin_addr.s_addr = *(__be32 *)addr;
		break;
	case AF_INET6:
		if (addrlen__sz != 16)
			return -EINVAL;
		sa6 = (struct sockaddr_in6 *)sa;
		memcpy(sa6->sin6_addr.s6_addr, addr, 16);
		break;
	case AF_UNIX:
		if (addrlen__sz > UNIX_PATH_MAX)
			return -EINVAL;
		un = (struct sockaddr_un *)sa;
		memcpy(un->sun_path, addr, addrlen__sz);
		/* uaddrlen is only for the length of the sun_path
		 *(and sin[6]_addr too?)
		 */
		sa_kern->uaddrlen = addrlen__sz;
		break;
	default:
		/* impossible */
		WARN_ON_ONCE(1);
		return -EINVAL;
	}

	return 0;
}

> +	sa_kern->uaddrlen = addrlen__sz;
> +
> +	return 0;
> +}
>   __diag_pop();


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 04/10] bpf: Add BTF_KFUNC_HOOK_SOCK_ADDR
  2023-04-21 16:27 ` [PATCH bpf-next v3 04/10] bpf: Add BTF_KFUNC_HOOK_SOCK_ADDR Daan De Meyer
@ 2023-04-26 21:35   ` Martin KaFai Lau
  0 siblings, 0 replies; 25+ messages in thread
From: Martin KaFai Lau @ 2023-04-26 21:35 UTC (permalink / raw)
  To: Daan De Meyer; +Cc: kernel-team, bpf

On 4/21/23 9:27 AM, Daan De Meyer wrote:
> In preparation for adding a sock addr specific kfunc, let's add the
> necessary hook for it.

Please combine this patch with patch 5.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 09/10] selftests/bpf: Add tests for cgroup unix socket address hooks
  2023-04-21 16:27 ` [PATCH bpf-next v3 09/10] selftests/bpf: Add tests " Daan De Meyer
@ 2023-04-26 21:57   ` Martin KaFai Lau
  2023-04-26 22:13   ` Martin KaFai Lau
  1 sibling, 0 replies; 25+ messages in thread
From: Martin KaFai Lau @ 2023-04-26 21:57 UTC (permalink / raw)
  To: Daan De Meyer; +Cc: kernel-team, bpf

On 4/21/23 9:27 AM, Daan De Meyer wrote:
> The unix socket address hooks do not support modifying the source
> address so we skip source address checks when we're running a unix
> socket address hook test.
> 
> Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
> ---
>   tools/testing/selftests/bpf/bpf_kfuncs.h      |  13 ++
>   .../selftests/bpf/prog_tests/section_names.c  |  30 ++++
>   .../testing/selftests/bpf/progs/bindun_prog.c |  59 ++++++++
>   .../selftests/bpf/progs/connectun_prog.c      |  53 +++++++
>   .../selftests/bpf/progs/recvmsgun_prog.c      |  59 ++++++++
>   .../selftests/bpf/progs/sendmsgun_prog.c      |  53 +++++++
>   tools/testing/selftests/bpf/test_sock_addr.c  | 137 +++++++++++++++++-
>   7 files changed, 397 insertions(+), 7 deletions(-)
>   create mode 100644 tools/testing/selftests/bpf/progs/bindun_prog.c
>   create mode 100644 tools/testing/selftests/bpf/progs/connectun_prog.c
>   create mode 100644 tools/testing/selftests/bpf/progs/recvmsgun_prog.c
>   create mode 100644 tools/testing/selftests/bpf/progs/sendmsgun_prog.c
> 
> diff --git a/tools/testing/selftests/bpf/bpf_kfuncs.h b/tools/testing/selftests/bpf/bpf_kfuncs.h
> index 8c993ec8ceea..dbdec3d5152e 100644
> --- a/tools/testing/selftests/bpf/bpf_kfuncs.h
> +++ b/tools/testing/selftests/bpf/bpf_kfuncs.h
> @@ -1,6 +1,8 @@
>   #ifndef __BPF_KFUNCS__
>   #define __BPF_KFUNCS__
>   
> +struct bpf_sock_addr_kern;
> +
>   /* Description
>    *  Initializes an skb-type dynptr
>    * Returns
> @@ -35,4 +37,15 @@ extern void *bpf_dynptr_slice(const struct bpf_dynptr *ptr, __u32 offset,
>   extern void *bpf_dynptr_slice_rdwr(const struct bpf_dynptr *ptr, __u32 offset,
>   			      void *buffer, __u32 buffer__szk) __ksym;
>   
> +/* Description
> + *  Modify the contents of a sockaddr.
> + * Returns__bpf_kfunc
> + *  -EINVAL if the sockaddr family does not match, the sockaddr is too small or
> + *  too big, 0 if the sockaddr was successfully modified.
> + */
> +extern int bpf_sock_addr_set(struct bpf_sock_addr_kern *sa_kern,
> +			     const void *addr, __u32 addrlen__sz) __ksym;


It needs some negative tests, like
- addrlen__sz > UNIX_PATH_MAX for AF_UNIX test.
- addrlen__sz is larger than the size of addr in the stack.

> diff --git a/tools/testing/selftests/bpf/progs/bindun_prog.c b/tools/testing/selftests/bpf/progs/bindun_prog.c
> new file mode 100644
> index 000000000000..60addb5a9c96
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/bindun_prog.c
> @@ -0,0 +1,59 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2022 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"
> +
> +#ifndef AF_UNIX
> +#define AF_UNIX 1

Move it to bpf_tracing_net.h. AF_INET[6] is already there.

> +#endif
> +
> +#define DST_REWRITE_PATH	"\0bpf_cgroup_unix_test_rewrite"
> +
> +void *bpf_cast_to_kern_ctx(void *) __ksym;
> +
> +SEC("cgroup/bindun")
> +int bind_un_prog(struct bpf_sock_addr *ctx)
> +{
> +	struct bpf_sock *sk = ctx->sk;
> +	struct bpf_sock_addr_kern *sa_kern = bpf_cast_to_kern_ctx(ctx);
> +	struct sockaddr_un *sa_kern_unaddr;
> +	struct sockaddr_un unaddr = {
> +		.sun_family = AF_UNIX,
> +	};
> +	__u32 unaddrlen = offsetof(struct sockaddr_un, sun_path) +
> +			  sizeof(DST_REWRITE_PATH) - 1;
> +	int ret;
> +
> +	if (!sk)
> +		return 0;
> +
> +	if (sk->family != AF_UNIX)
> +		return 0;
> +
> +	if (ctx->type != SOCK_STREAM && ctx->type != SOCK_DGRAM)
> +		return 0;
> +
> +	memcpy(unaddr.sun_path, DST_REWRITE_PATH, sizeof(DST_REWRITE_PATH) - 1);
> +
> +	ret = bpf_sock_addr_set(sa_kern, (struct sockaddr *) &unaddr, unaddrlen);
> +	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, DST_REWRITE_PATH,
> +		   sizeof(DST_REWRITE_PATH) - 1) != 0)
> +		return 0;
> +
> +	return 1;
> +}
> +
> +char _license[] SEC("license") = "GPL";
> diff --git a/tools/testing/selftests/bpf/progs/connectun_prog.c b/tools/testing/selftests/bpf/progs/connectun_prog.c
> new file mode 100644
> index 000000000000..ac7209bd326f
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/connectun_prog.c
> @@ -0,0 +1,53 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2022 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"
> +
> +#ifndef AF_UNIX
> +#define AF_UNIX 1
> +#endif
> +
> +#define DST_REWRITE_PATH	"\0bpf_cgroup_unix_test_rewrite"
> +
> +void *bpf_cast_to_kern_ctx(void *) __ksym;

Move it to bpf_kfuncs.h also?



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 03/10] bpf: Allow read access to addr_len from cgroup sockaddr programs
  2023-04-21 16:27 ` [PATCH bpf-next v3 03/10] bpf: Allow read access to addr_len from cgroup sockaddr programs Daan De Meyer
  2023-04-21 20:55   ` Alexei Starovoitov
@ 2023-04-26 22:07   ` Martin KaFai Lau
  1 sibling, 0 replies; 25+ messages in thread
From: Martin KaFai Lau @ 2023-04-26 22:07 UTC (permalink / raw)
  To: Daan De Meyer; +Cc: kernel-team, bpf

On 4/21/23 9:27 AM, Daan De Meyer wrote:
> As prep for adding unix socket support to the cgroup sockaddr hooks,
> let's expose the sockaddr addrlen in bpf_sock_addr_kern. While not
> important for AF_INET or AF_INET6, the sockaddr length is important
> when working with AF_UNIX sockaddrs as the size of the sockaddr cannot
> be determined just from the address family or the sockaddr's contents.
> 
> __cgroup_bpf_run_filter_sock_addr() is modified to return the addr_len
> in preparation for adding unix socket support for which we'll need to
> return the modified address length.
> 
> Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
> ---
>   include/linux/bpf-cgroup.h | 73 +++++++++++++++++++-------------------
>   include/linux/filter.h     |  1 +
>   kernel/bpf/cgroup.c        | 16 +++++++--
>   net/ipv4/af_inet.c         |  8 ++---
>   net/ipv4/ping.c            |  8 ++++-
>   net/ipv4/tcp_ipv4.c        |  8 ++++-
>   net/ipv4/udp.c             | 17 ++++++---
>   net/ipv6/af_inet6.c        |  8 ++---
>   net/ipv6/ping.c            |  8 ++++-
>   net/ipv6/tcp_ipv6.c        |  8 ++++-
>   net/ipv6/udp.c             | 14 ++++++--
>   11 files changed, 111 insertions(+), 58 deletions(-)
> 
> diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
> index 57e9e109257e..f3f5adf3881f 100644
> --- a/include/linux/bpf-cgroup.h
> +++ b/include/linux/bpf-cgroup.h
> @@ -120,6 +120,7 @@ int __cgroup_bpf_run_filter_sk(struct sock *sk,
>   
>   int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
>   				      struct sockaddr *uaddr,
> +				      u32 uaddrlen,

If the bpf_sock_addr_set() kfunc can only change the sin[6]_addr and unix_path 
(the comment in patch 5), the "u32 uaddrlen" can be changed to "u32 *uaddrlen" 
here. The new unix_path length can be passed back to af_unix.c in "*uaddrlen". 
The inet[6] code path can just pass NULL and most of the code churn in this 
patch will no longer be needed?


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH bpf-next v3 09/10] selftests/bpf: Add tests for cgroup unix socket address hooks
  2023-04-21 16:27 ` [PATCH bpf-next v3 09/10] selftests/bpf: Add tests " Daan De Meyer
  2023-04-26 21:57   ` Martin KaFai Lau
@ 2023-04-26 22:13   ` Martin KaFai Lau
  1 sibling, 0 replies; 25+ messages in thread
From: Martin KaFai Lau @ 2023-04-26 22:13 UTC (permalink / raw)
  To: Daan De Meyer; +Cc: kernel-team, bpf

On 4/21/23 9:27 AM, Daan De Meyer wrote:
> The unix socket address hooks do not support modifying the source
> address so we skip source address checks when we're running a unix
> socket address hook test.

Another thing came to my mind. The test_sock_addr.c should have been moved to 
the test_progs.c infra. The bpf CI does not run test_sock_addr.sh.

Please at least consider adding the new AF_UNIX tests in this patch to 
test_progs.c infra instead of continue adding them to test_sock_addr.c.


^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2023-04-26 22:13 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-21 16:27 [PATCH bpf-next v3 00/10] Add cgroup sockaddr hooks for unix sockets Daan De Meyer
2023-04-21 16:27 ` [PATCH bpf-next v3 01/10] selftests/bpf: Add missing section name tests for getpeername/getsockname Daan De Meyer
2023-04-21 16:27 ` [PATCH bpf-next v3 02/10] selftests/bpf: Track sockaddr length in sock addr tests Daan De Meyer
2023-04-21 16:27 ` [PATCH bpf-next v3 03/10] bpf: Allow read access to addr_len from cgroup sockaddr programs Daan De Meyer
2023-04-21 20:55   ` Alexei Starovoitov
2023-04-24 13:58     ` Daan De Meyer
2023-04-26  0:05       ` Alexei Starovoitov
2023-04-26 13:46         ` Daan De Meyer
2023-04-26 22:07   ` Martin KaFai Lau
2023-04-21 16:27 ` [PATCH bpf-next v3 04/10] bpf: Add BTF_KFUNC_HOOK_SOCK_ADDR Daan De Meyer
2023-04-26 21:35   ` Martin KaFai Lau
2023-04-21 16:27 ` [PATCH bpf-next v3 05/10] bpf: Add bpf_sock_addr_set() to allow writing sockaddr len from bpf Daan De Meyer
2023-04-21 21:01   ` Alexei Starovoitov
2023-04-24 14:07     ` Daan De Meyer
2023-04-26  0:10       ` Alexei Starovoitov
2023-04-26 13:51         ` Daan De Meyer
2023-04-26 21:30   ` Martin KaFai Lau
2023-04-21 16:27 ` [PATCH bpf-next v3 06/10] bpf: Implement cgroup sockaddr hooks for unix sockets Daan De Meyer
2023-04-21 16:27 ` [PATCH bpf-next v3 07/10] libbpf: Add support for cgroup unix socket address hooks Daan De Meyer
2023-04-21 16:27 ` [PATCH bpf-next v3 08/10] bpftool: " Daan De Meyer
2023-04-21 20:35   ` Quentin Monnet
2023-04-21 16:27 ` [PATCH bpf-next v3 09/10] selftests/bpf: Add tests " Daan De Meyer
2023-04-26 21:57   ` Martin KaFai Lau
2023-04-26 22:13   ` Martin KaFai Lau
2023-04-21 16:27 ` [PATCH bpf-next v3 10/10] documentation/bpf: Document " Daan De Meyer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.