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

selftests/landlock: Add audit tests for network

Test all network blockers:
- net.bind_tcp
- net.connect_tcp

Test coverage for security/landlock is 94.0% of 1525 lines according to
gcc/gcov-14.

Cc: Günther Noack <gnoack@google.com>
Cc: Paul Moore <paul@paul-moore.com>
Link: https://lore.kernel.org/r/20250320190717.2287696-28-mic@digikod.net
[mic: Update test coverage]
Signed-off-by: Mickaël Salaün <mic@digikod.net>

+132
+132
tools/testing/selftests/landlock/net_test.c
··· 20 20 #include <sys/syscall.h> 21 21 #include <sys/un.h> 22 22 23 + #include "audit.h" 23 24 #include "common.h" 24 25 25 26 const short sock_port_start = (1 << 10); ··· 1867 1866 1868 1867 EXPECT_EQ(0, close(connect_fd)); 1869 1868 EXPECT_EQ(0, close(bind_fd)); 1869 + } 1870 + 1871 + static int matches_log_tcp(const int audit_fd, const char *const blockers, 1872 + const char *const dir_addr, const char *const addr, 1873 + const char *const dir_port) 1874 + { 1875 + static const char log_template[] = REGEX_LANDLOCK_PREFIX 1876 + " blockers=%s %s=%s %s=1024$"; 1877 + /* 1878 + * Max strlen(blockers): 16 1879 + * Max strlen(dir_addr): 5 1880 + * Max strlen(addr): 12 1881 + * Max strlen(dir_port): 4 1882 + */ 1883 + char log_match[sizeof(log_template) + 37]; 1884 + int log_match_len; 1885 + 1886 + log_match_len = snprintf(log_match, sizeof(log_match), log_template, 1887 + blockers, dir_addr, addr, dir_port); 1888 + if (log_match_len > sizeof(log_match)) 1889 + return -E2BIG; 1890 + 1891 + return audit_match_record(audit_fd, AUDIT_LANDLOCK_ACCESS, log_match, 1892 + NULL); 1893 + } 1894 + 1895 + FIXTURE(audit) 1896 + { 1897 + struct service_fixture srv0; 1898 + struct audit_filter audit_filter; 1899 + int audit_fd; 1900 + }; 1901 + 1902 + FIXTURE_VARIANT(audit) 1903 + { 1904 + const char *const addr; 1905 + const struct protocol_variant prot; 1906 + }; 1907 + 1908 + /* clang-format off */ 1909 + FIXTURE_VARIANT_ADD(audit, ipv4) { 1910 + /* clang-format on */ 1911 + .addr = "127\\.0\\.0\\.1", 1912 + .prot = { 1913 + .domain = AF_INET, 1914 + .type = SOCK_STREAM, 1915 + }, 1916 + }; 1917 + 1918 + /* clang-format off */ 1919 + FIXTURE_VARIANT_ADD(audit, ipv6) { 1920 + /* clang-format on */ 1921 + .addr = "::1", 1922 + .prot = { 1923 + .domain = AF_INET6, 1924 + .type = SOCK_STREAM, 1925 + }, 1926 + }; 1927 + 1928 + FIXTURE_SETUP(audit) 1929 + { 1930 + ASSERT_EQ(0, set_service(&self->srv0, variant->prot, 0)); 1931 + setup_loopback(_metadata); 1932 + 1933 + set_cap(_metadata, CAP_AUDIT_CONTROL); 1934 + self->audit_fd = audit_init_with_exe_filter(&self->audit_filter); 1935 + EXPECT_LE(0, self->audit_fd); 1936 + disable_caps(_metadata); 1937 + }; 1938 + 1939 + FIXTURE_TEARDOWN(audit) 1940 + { 1941 + set_cap(_metadata, CAP_AUDIT_CONTROL); 1942 + EXPECT_EQ(0, audit_cleanup(self->audit_fd, &self->audit_filter)); 1943 + clear_cap(_metadata, CAP_AUDIT_CONTROL); 1944 + } 1945 + 1946 + TEST_F(audit, bind) 1947 + { 1948 + const struct landlock_ruleset_attr ruleset_attr = { 1949 + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 1950 + LANDLOCK_ACCESS_NET_CONNECT_TCP, 1951 + }; 1952 + struct audit_records records; 1953 + int ruleset_fd, sock_fd; 1954 + 1955 + ruleset_fd = 1956 + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 1957 + ASSERT_LE(0, ruleset_fd); 1958 + enforce_ruleset(_metadata, ruleset_fd); 1959 + EXPECT_EQ(0, close(ruleset_fd)); 1960 + 1961 + sock_fd = socket_variant(&self->srv0); 1962 + ASSERT_LE(0, sock_fd); 1963 + EXPECT_EQ(-EACCES, bind_variant(sock_fd, &self->srv0)); 1964 + EXPECT_EQ(0, matches_log_tcp(self->audit_fd, "net\\.bind_tcp", "saddr", 1965 + variant->addr, "src")); 1966 + 1967 + EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 1968 + EXPECT_EQ(0, records.access); 1969 + EXPECT_EQ(1, records.domain); 1970 + 1971 + EXPECT_EQ(0, close(sock_fd)); 1972 + } 1973 + 1974 + TEST_F(audit, connect) 1975 + { 1976 + const struct landlock_ruleset_attr ruleset_attr = { 1977 + .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | 1978 + LANDLOCK_ACCESS_NET_CONNECT_TCP, 1979 + }; 1980 + struct audit_records records; 1981 + int ruleset_fd, sock_fd; 1982 + 1983 + ruleset_fd = 1984 + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0); 1985 + ASSERT_LE(0, ruleset_fd); 1986 + enforce_ruleset(_metadata, ruleset_fd); 1987 + EXPECT_EQ(0, close(ruleset_fd)); 1988 + 1989 + sock_fd = socket_variant(&self->srv0); 1990 + ASSERT_LE(0, sock_fd); 1991 + EXPECT_EQ(-EACCES, connect_variant(sock_fd, &self->srv0)); 1992 + EXPECT_EQ(0, matches_log_tcp(self->audit_fd, "net\\.connect_tcp", 1993 + "daddr", variant->addr, "dest")); 1994 + 1995 + EXPECT_EQ(0, audit_count_records(self->audit_fd, &records)); 1996 + EXPECT_EQ(0, records.access); 1997 + EXPECT_EQ(1, records.domain); 1998 + 1999 + EXPECT_EQ(0, close(sock_fd)); 1870 2000 } 1871 2001 1872 2002 TEST_HARNESS_MAIN