1*d717b7e8SChristian Brauner // SPDX-License-Identifier: GPL-2.0-only 2*d717b7e8SChristian Brauner /* Copyright (c) 2026 Christian Brauner */ 3*d717b7e8SChristian Brauner 4*d717b7e8SChristian Brauner #include <errno.h> 5*d717b7e8SChristian Brauner #include <string.h> 6*d717b7e8SChristian Brauner #include <unistd.h> 7*d717b7e8SChristian Brauner #include <sys/xattr.h> 8*d717b7e8SChristian Brauner #include <sys/socket.h> 9*d717b7e8SChristian Brauner #include <netinet/in.h> 10*d717b7e8SChristian Brauner #include <test_progs.h> 11*d717b7e8SChristian Brauner 12*d717b7e8SChristian Brauner #include "sock_read_xattr.skel.h" 13*d717b7e8SChristian Brauner 14*d717b7e8SChristian Brauner static const char xattr_value[] = "bpf_sock_value"; 15*d717b7e8SChristian Brauner static const char xattr_name[] = "user.bpf_test"; 16*d717b7e8SChristian Brauner 17*d717b7e8SChristian Brauner static void test_read_sock_xattr(void) 18*d717b7e8SChristian Brauner { 19*d717b7e8SChristian Brauner struct sockaddr_in addr = {}; 20*d717b7e8SChristian Brauner struct sock_read_xattr *skel = NULL; 21*d717b7e8SChristian Brauner struct bpf_link *link = NULL; 22*d717b7e8SChristian Brauner int sock_fd = -1, err; 23*d717b7e8SChristian Brauner 24*d717b7e8SChristian Brauner sock_fd = socket(AF_INET, SOCK_STREAM, 0); 25*d717b7e8SChristian Brauner if (!ASSERT_OK_FD(sock_fd, "socket")) 26*d717b7e8SChristian Brauner return; 27*d717b7e8SChristian Brauner 28*d717b7e8SChristian Brauner err = fsetxattr(sock_fd, xattr_name, xattr_value, sizeof(xattr_value), 0); 29*d717b7e8SChristian Brauner if (!ASSERT_OK(err, "fsetxattr")) 30*d717b7e8SChristian Brauner goto out; 31*d717b7e8SChristian Brauner 32*d717b7e8SChristian Brauner skel = sock_read_xattr__open_and_load(); 33*d717b7e8SChristian Brauner if (!ASSERT_OK_PTR(skel, "sock_read_xattr__open_and_load")) 34*d717b7e8SChristian Brauner goto out; 35*d717b7e8SChristian Brauner 36*d717b7e8SChristian Brauner skel->bss->monitored_pid = sys_gettid(); 37*d717b7e8SChristian Brauner 38*d717b7e8SChristian Brauner /* Only attach the functional program; the verifier-only programs 39*d717b7e8SChristian Brauner * above are not pid-gated and would clobber the shared globals. 40*d717b7e8SChristian Brauner */ 41*d717b7e8SChristian Brauner link = bpf_program__attach(skel->progs.read_sock_xattr); 42*d717b7e8SChristian Brauner if (!ASSERT_OK_PTR(link, "attach read_sock_xattr")) 43*d717b7e8SChristian Brauner goto out; 44*d717b7e8SChristian Brauner 45*d717b7e8SChristian Brauner addr.sin_family = AF_INET; 46*d717b7e8SChristian Brauner addr.sin_port = htons(1234); 47*d717b7e8SChristian Brauner addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 48*d717b7e8SChristian Brauner /* Only the lsm/socket_connect hook matters; the connect may fail. */ 49*d717b7e8SChristian Brauner connect(sock_fd, (struct sockaddr *)&addr, sizeof(addr)); 50*d717b7e8SChristian Brauner 51*d717b7e8SChristian Brauner ASSERT_EQ(skel->data->read_ret, sizeof(xattr_value), "read_ret"); 52*d717b7e8SChristian Brauner ASSERT_STREQ(skel->bss->value, xattr_value, "value"); 53*d717b7e8SChristian Brauner 54*d717b7e8SChristian Brauner out: 55*d717b7e8SChristian Brauner bpf_link__destroy(link); 56*d717b7e8SChristian Brauner if (sock_fd >= 0) 57*d717b7e8SChristian Brauner close(sock_fd); 58*d717b7e8SChristian Brauner sock_read_xattr__destroy(skel); 59*d717b7e8SChristian Brauner } 60*d717b7e8SChristian Brauner 61*d717b7e8SChristian Brauner void test_sock_xattr(void) 62*d717b7e8SChristian Brauner { 63*d717b7e8SChristian Brauner RUN_TESTS(sock_read_xattr); 64*d717b7e8SChristian Brauner 65*d717b7e8SChristian Brauner if (test__start_subtest("read_sock_xattr")) 66*d717b7e8SChristian Brauner test_read_sock_xattr(); 67*d717b7e8SChristian Brauner } 68