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

selftests/landlock: Fix TCP bind(AF_UNSPEC) test case

The nominal error code for bind(AF_UNSPEC) on an IPv6 socket
is -EAFNOSUPPORT, not -EINVAL. -EINVAL is only returned when
the supplied address struct is too short, which happens to be
the case in current selftests because they treat AF_UNSPEC
like IPv4 sockets do: as an alias for AF_INET (which is a
16-byte struct instead of the 24 bytes required by IPv6
sockets).

Make the union large enough for any address (by adding struct
sockaddr_storage to the union), and make AF_UNSPEC addresses
large enough for any family.

Test for -EAFNOSUPPORT instead, and add a dedicated test case
for truncated inputs with -EINVAL.

Fixes: a549d055a22e ("selftests/landlock: Add network tests")
Signed-off-by: Matthieu Buffet <matthieu@buffet.re>
Link: https://lore.kernel.org/r/20251027190726.626244-2-matthieu@buffet.re
Signed-off-by: Mickaël Salaün <mic@digikod.net>

authored by

Matthieu Buffet and committed by
Mickaël Salaün
bd09d9a0 e4d82cbc

+16 -1
+1
tools/testing/selftests/landlock/common.h
··· 237 237 struct sockaddr_un unix_addr; 238 238 socklen_t unix_addr_len; 239 239 }; 240 + struct sockaddr_storage _largest; 240 241 }; 241 242 }; 242 243
+15 -1
tools/testing/selftests/landlock/net_test.c
··· 121 121 { 122 122 switch (srv->protocol.domain) { 123 123 case AF_UNSPEC: 124 + if (minimal) 125 + return sizeof(sa_family_t); 126 + return sizeof(struct sockaddr_storage); 127 + 124 128 case AF_INET: 125 129 return sizeof(srv->ipv4_addr); 126 130 ··· 762 758 bind_fd = socket_variant(&self->srv0); 763 759 ASSERT_LE(0, bind_fd); 764 760 761 + /* Tries to bind with too small addrlen. */ 762 + EXPECT_EQ(-EINVAL, bind_variant_addrlen( 763 + bind_fd, &self->unspec_any0, 764 + get_addrlen(&self->unspec_any0, true) - 1)); 765 + 765 766 /* Allowed bind on AF_UNSPEC/INADDR_ANY. */ 766 767 ret = bind_variant(bind_fd, &self->unspec_any0); 767 768 if (variant->prot.domain == AF_INET) { ··· 775 766 TH_LOG("Failed to bind to unspec/any socket: %s", 776 767 strerror(errno)); 777 768 } 769 + } else if (variant->prot.domain == AF_INET6) { 770 + EXPECT_EQ(-EAFNOSUPPORT, ret); 778 771 } else { 779 772 EXPECT_EQ(-EINVAL, ret); 780 773 } ··· 803 792 } else { 804 793 EXPECT_EQ(0, ret); 805 794 } 795 + } else if (variant->prot.domain == AF_INET6) { 796 + EXPECT_EQ(-EAFNOSUPPORT, ret); 806 797 } else { 807 798 EXPECT_EQ(-EINVAL, ret); 808 799 } ··· 814 801 bind_fd = socket_variant(&self->srv0); 815 802 ASSERT_LE(0, bind_fd); 816 803 ret = bind_variant(bind_fd, &self->unspec_srv0); 817 - if (variant->prot.domain == AF_INET) { 804 + if (variant->prot.domain == AF_INET || 805 + variant->prot.domain == AF_INET6) { 818 806 EXPECT_EQ(-EAFNOSUPPORT, ret); 819 807 } else { 820 808 EXPECT_EQ(-EINVAL, ret)