mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 15:22:21 -04:00
selftests: net: getsockopt_iter: add raw ICMP_FILTER coverage
Exercise the raw getsockopt path now backed by sockopt_t. ICMP_FILTER returns a fixed-size struct and, unlike the int/u64 options already covered, clamps the length down to the user buffer on a short read instead of failing, so check that semantic explicitly along with the exact and oversized cases, the -EOPNOTSUPP path on a non-ICMP raw socket, and an unknown optname. Signed-off-by: Breno Leitao <leitao@debian.org> Acked-by: Stanislav Fomichev <sdf@fomichev.me> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/20260630-getsockopt_phase2-v2-4-193335f3d4d1@debian.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
committed by
Paolo Abeni
parent
9588d5da17
commit
f4d5e3a5c7
@@ -11,6 +11,8 @@
|
||||
* that always reports the required buffer length back via optlen,
|
||||
* even when the user buffer is too small to receive any group bits.
|
||||
* - vsock: SO_VM_SOCKETS_BUFFER_SIZE covers the u64 path.
|
||||
* - raw: ICMP_FILTER covers a fixed-size struct payload that clamps
|
||||
* the length down on a short buffer instead of failing.
|
||||
*
|
||||
* Author: Breno Leitao <leitao@debian.org>
|
||||
*/
|
||||
@@ -24,12 +26,20 @@
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/time_types.h>
|
||||
#include <linux/vm_sockets.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include "kselftest_harness.h"
|
||||
|
||||
#ifndef AF_VSOCK
|
||||
#define AF_VSOCK 40
|
||||
#endif
|
||||
#ifndef SOL_RAW
|
||||
#define SOL_RAW 255
|
||||
#endif
|
||||
#ifndef ICMP_FILTER
|
||||
#define ICMP_FILTER 1
|
||||
#endif
|
||||
|
||||
/* ---------- netlink ---------- */
|
||||
|
||||
@@ -297,4 +307,91 @@ TEST_F(vsock, connect_timeout_old_exact)
|
||||
ASSERT_EQ(sizeof(tv), optlen);
|
||||
}
|
||||
|
||||
/* ---------- raw (ipv4) ---------- */
|
||||
|
||||
FIXTURE(raw)
|
||||
{
|
||||
int fd;
|
||||
};
|
||||
|
||||
FIXTURE_SETUP(raw)
|
||||
{
|
||||
struct icmp_filter filt = { .data = 0xdeadbeef };
|
||||
|
||||
self->fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
if (self->fd < 0)
|
||||
SKIP(return, "SOCK_RAW/ICMP socket: %s", strerror(errno));
|
||||
|
||||
if (setsockopt(self->fd, SOL_RAW, ICMP_FILTER, &filt, sizeof(filt)) < 0)
|
||||
SKIP(return, "set ICMP_FILTER: %s", strerror(errno));
|
||||
}
|
||||
|
||||
FIXTURE_TEARDOWN(raw)
|
||||
{
|
||||
if (self->fd >= 0)
|
||||
close(self->fd);
|
||||
}
|
||||
|
||||
TEST_F(raw, icmpfilter_exact)
|
||||
{
|
||||
struct icmp_filter filt = {};
|
||||
socklen_t optlen = sizeof(filt);
|
||||
|
||||
ASSERT_EQ(0, getsockopt(self->fd, SOL_RAW, ICMP_FILTER,
|
||||
&filt, &optlen));
|
||||
ASSERT_EQ(sizeof(filt), optlen);
|
||||
ASSERT_EQ(0xdeadbeef, filt.data);
|
||||
}
|
||||
|
||||
TEST_F(raw, icmpfilter_oversize_clamped)
|
||||
{
|
||||
char buf[16] = {};
|
||||
socklen_t optlen = sizeof(buf);
|
||||
|
||||
ASSERT_EQ(0, getsockopt(self->fd, SOL_RAW, ICMP_FILTER,
|
||||
buf, &optlen));
|
||||
ASSERT_EQ(sizeof(struct icmp_filter), optlen);
|
||||
}
|
||||
|
||||
/* Unlike the int/u64 options above, ICMP_FILTER clamps the length down
|
||||
* to the user buffer instead of returning EINVAL: a short buffer
|
||||
* succeeds and reports the truncated length back via optlen.
|
||||
*/
|
||||
TEST_F(raw, icmpfilter_undersize_clamped)
|
||||
{
|
||||
char buf[2] = {};
|
||||
socklen_t optlen = sizeof(buf);
|
||||
|
||||
ASSERT_EQ(0, getsockopt(self->fd, SOL_RAW, ICMP_FILTER,
|
||||
buf, &optlen));
|
||||
ASSERT_EQ(sizeof(buf), optlen);
|
||||
}
|
||||
|
||||
TEST_F(raw, icmpfilter_wrong_proto)
|
||||
{
|
||||
struct icmp_filter filt;
|
||||
socklen_t optlen = sizeof(filt);
|
||||
int fd;
|
||||
|
||||
fd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
|
||||
if (fd < 0)
|
||||
SKIP(return, "SOCK_RAW/UDP socket: %s", strerror(errno));
|
||||
|
||||
ASSERT_EQ(-1, getsockopt(fd, SOL_RAW, ICMP_FILTER, &filt, &optlen));
|
||||
ASSERT_EQ(EOPNOTSUPP, errno);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
TEST_F(raw, bad_optname)
|
||||
{
|
||||
socklen_t optlen;
|
||||
int val;
|
||||
|
||||
optlen = sizeof(val);
|
||||
|
||||
ASSERT_EQ(-1, getsockopt(self->fd, SOL_RAW, 0x7fff, &val, &optlen));
|
||||
ASSERT_EQ(ENOPROTOOPT, errno);
|
||||
ASSERT_EQ(sizeof(val), optlen);
|
||||
}
|
||||
|
||||
TEST_HARNESS_MAIN
|
||||
|
||||
Reference in New Issue
Block a user