From 71d69b74f62f6e1c3539f42a14b0652b979fcf1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=B8=E0=A4=AE=E0=A5=80=E0=A4=B0=20=E0=A4=B8=E0=A4=BF?= =?UTF-8?q?=E0=A4=82=E0=A4=B9=20Sameer=20Singh?= Date: Fri, 27 Dec 2024 03:47:35 +0530 Subject: [PATCH 1/8] sk-inet: Add support for checkpoint/restore of ICMP sockets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently there is no option to checkpoint/restore programs that use ICMP sockets, such as `ping`. This patch adds support for the same. Fixes #2557 Signed-off-by: समीर सिंह Sameer Singh --- criu/sk-inet.c | 7 +++++-- criu/sockets.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/criu/sk-inet.c b/criu/sk-inet.c index 92f53e5697..c930f681dd 100644 --- a/criu/sk-inet.c +++ b/criu/sk-inet.c @@ -125,6 +125,8 @@ static int can_dump_ipproto(unsigned int ino, int proto, int type) case IPPROTO_TCP: case IPPROTO_UDP: case IPPROTO_UDPLITE: + case IPPROTO_ICMP: + case IPPROTO_ICMPV6: break; default: pr_err("Unsupported proto %d for socket %x\n", proto, ino); @@ -915,8 +917,9 @@ static int open_inet_sk(struct file_desc *d, int *new_fd) } if (ie->src_port) { - if (inet_bind(sk, ii)) - goto err; + if (ie->proto != IPPROTO_ICMP && ie->proto != IPPROTO_ICMPV6) + if (inet_bind(sk, ii)) + goto err; } /* diff --git a/criu/sockets.c b/criu/sockets.c index f9ce999bed..808d991453 100644 --- a/criu/sockets.c +++ b/criu/sockets.c @@ -131,10 +131,12 @@ enum socket_cl_bits { INET_UDP_CL_BIT, INET_UDPLITE_CL_BIT, INET_RAW_CL_BIT, + INET_ICMP_CL_BIT, INET6_TCP_CL_BIT, INET6_UDP_CL_BIT, INET6_UDPLITE_CL_BIT, INET6_RAW_CL_BIT, + INET6_ICMP_CL_BIT, UNIX_CL_BIT, PACKET_CL_BIT, _MAX_CL_BIT, @@ -161,6 +163,8 @@ static inline enum socket_cl_bits get_collect_bit_nr(unsigned int family, unsign return INET_UDPLITE_CL_BIT; if (proto == IPPROTO_RAW) return INET_RAW_CL_BIT; + if (proto == IPPROTO_ICMP) + return INET_ICMP_CL_BIT; } if (family == AF_INET6) { if (proto == IPPROTO_TCP) @@ -171,6 +175,8 @@ static inline enum socket_cl_bits get_collect_bit_nr(unsigned int family, unsign return INET6_UDPLITE_CL_BIT; if (proto == IPPROTO_RAW) return INET6_RAW_CL_BIT; + if (proto == IPPROTO_ICMPV6) + return INET6_ICMP_CL_BIT; } pr_err("Unknown pair family %d proto %d\n", family, proto); @@ -282,6 +288,12 @@ void preload_socket_modules(void) req.r.i.sdiag_protocol = IPPROTO_RAW; probe_diag(nl, &req, -ENOENT); + req.r.i.sdiag_protocol = IPPROTO_ICMP; + probe_diag(nl, &req, -ENOENT); + + req.r.i.sdiag_protocol = IPPROTO_ICMPV6; + probe_diag(nl, &req, -ENOENT); + close(nl); pr_info("Done probing\n"); } @@ -773,6 +785,10 @@ static int inet_receive_one(struct nlmsghdr *h, struct ns_id *ns, void *arg) case IPPROTO_RAW: type = SOCK_RAW; break; + case IPPROTO_ICMP: + case IPPROTO_ICMPV6: + type = SOCK_DGRAM; + break; default: BUG_ON(1); return -1; @@ -797,7 +813,7 @@ static int collect_err(int err, struct ns_id *ns, void *arg) char family[32], proto[32]; char msg[256]; - snprintf(msg, sizeof(msg), "Sockects collect procedure family %s proto %s", + snprintf(msg, sizeof(msg), "Sockets collect procedure family %s proto %s", socket_family_name(gr->family, family, sizeof(family)), socket_proto_name(gr->protocol, proto, sizeof(proto))); @@ -905,6 +921,13 @@ int collect_sockets(struct ns_id *ns) if (tmp) err = tmp; + /* Collect IPv4 ICMP sockets */ + req.r.i.sdiag_family = AF_INET; + req.r.i.sdiag_protocol = IPPROTO_ICMP; + req.r.i.idiag_ext = 0; + req.r.i.idiag_states = -1; /* All */ + set_collect_bit(req.r.n.sdiag_family, req.r.n.sdiag_protocol); + /* Collect IPv6 TCP sockets */ req.r.i.sdiag_family = AF_INET6; req.r.i.sdiag_protocol = IPPROTO_TCP; @@ -944,6 +967,13 @@ int collect_sockets(struct ns_id *ns) if (tmp) err = tmp; + /* Collect IPv6 ICMP sockets */ + req.r.i.sdiag_family = AF_INET6; + req.r.i.sdiag_protocol = IPPROTO_ICMPV6; + req.r.i.idiag_ext = 0; + req.r.i.idiag_states = -1; /* All */ + set_collect_bit(req.r.n.sdiag_family, req.r.n.sdiag_protocol); + req.r.p.sdiag_family = AF_PACKET; req.r.p.sdiag_protocol = 0; req.r.p.pdiag_show = PACKET_SHOW_INFO | PACKET_SHOW_MCLIST | PACKET_SHOW_FANOUT | PACKET_SHOW_RING_CFG; From 5238f0770c86898d86603c36d737a8e80483a1ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=B8=E0=A4=AE=E0=A5=80=E0=A4=B0=20=E0=A4=B8=E0=A4=BF?= =?UTF-8?q?=E0=A4=82=E0=A4=B9=20Sameer=20Singh?= Date: Sat, 28 Dec 2024 09:35:11 +0530 Subject: [PATCH 2/8] test: add a static test for ICMP socket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a ZDTM static test for the ICMP socket feature. Signed-off-by: समीर सिंह Sameer Singh --- test/zdtm/static/Makefile | 1 + test/zdtm/static/socket_icmp.c | 109 +++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 test/zdtm/static/socket_icmp.c diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index 71a1b6a535..b48474348f 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -35,6 +35,7 @@ TST_NOFILE := \ socket_udp-corked \ socket6_udp \ socket_udp_shutdown \ + socket_icmp \ sk-freebind \ sk-freebind-false \ socket_udplite \ diff --git a/test/zdtm/static/socket_icmp.c b/test/zdtm/static/socket_icmp.c new file mode 100644 index 0000000000..b2d24658ba --- /dev/null +++ b/test/zdtm/static/socket_icmp.c @@ -0,0 +1,109 @@ +#include "zdtmtst.h" + +const char *test_doc = "static test for ICMP socket\n"; +const char *test_author = "समीर सिंह Sameer Singh \n"; + +/* Description: + * Send a ping to localhost using ICMP socket + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PACKET_SIZE 64 +#define RECV_TIMEOUT 1 + +int ping(void) +{ + int ret, sock, seq = 0, recv_len = 0; + char packet[PACKET_SIZE], recv_packet[PACKET_SIZE]; + + struct timeval tv; + struct icmphdr icmp_header, *icmp_reply; + struct sockaddr_in addr, recv_addr; + socklen_t addr_len; + + sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP); + if (sock < 0) { + pr_perror("Can't create socket"); + return 1; + } + + + tv.tv_sec = RECV_TIMEOUT; + tv.tv_usec = 0; + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { + pr_perror("Can't set socket option"); + return 1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + + for (;;) { + memset(&icmp_header, 0, sizeof(icmp_header)); + icmp_header.type = ICMP_ECHO; + icmp_header.code = 0; + icmp_header.un.echo.id = getpid(); + icmp_header.un.echo.sequence = seq++; + + memcpy(packet, &icmp_header, sizeof(icmp_header)); + memset(packet + sizeof(icmp_header), 0xa5, + PACKET_SIZE - sizeof(icmp_header)); + + ret = sendto(sock, packet, PACKET_SIZE, 0, + (struct sockaddr *)&addr, sizeof(addr)); + + if (ret < 0) { + fail("Can't send"); + return 1; + } + + addr_len = sizeof(recv_addr); + + ret = recvfrom(sock, recv_packet, sizeof(recv_packet), 0, + (struct sockaddr*)&recv_addr, &addr_len); + + if (ret < 0) { + fail("Can't recv"); + return 1; + } + + icmp_reply = (struct icmphdr *)recv_packet; + + if (icmp_reply->type == ICMP_ECHOREPLY) { + printf("%d bytes from %s: icmp_seq=%d\n", + recv_len, + inet_ntoa(recv_addr.sin_addr), + icmp_reply->un.echo.sequence); + } + + sleep(1); + } + + close(sock); +} + +int main(int argc, char **argv) +{ + int ret; + test_init(argc, argv); + + test_daemon(); + test_waitsig(); + + ret = ping(); + if (ret == 1) + fail("Cannot ping"); + + pass(); + return 0; +} From 433f91c4b8205e8b3b980b6bd8393ac1bf9eefa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=B8=E0=A4=AE=E0=A5=80=E0=A4=B0=20=E0=A4=B8=E0=A4=BF?= =?UTF-8?q?=E0=A4=82=E0=A4=B9=20Sameer=20Singh?= Date: Wed, 1 Jan 2025 17:22:13 +0530 Subject: [PATCH 3/8] zdtm: set net.ipv4.ping_group_range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ZDTM test suite creates separate network namespaces to run tests. These namespaces do not preserve the value of the sysctl variable `net.ipv4.ping_group_range` which allows the creation of unprivileged ICMP sockets. This commit modifies the variable after the namespaces have been created to allow every GID to create unprivileged ICMP sockets. Signed-off-by: समीर सिंह Sameer Singh --- test/zdtm/lib/ns.c | 19 +++++++++++++++++++ test/zdtm/lib/sysctl.c | 27 +++++++++++++++++++++++++++ test/zdtm/lib/sysctl.h | 1 + test/zdtm_ct.c | 5 +++++ 4 files changed, 52 insertions(+) diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c index 3c0dbdeb80..55b9cf0fcd 100644 --- a/test/zdtm/lib/ns.c +++ b/test/zdtm/lib/ns.c @@ -20,6 +20,7 @@ #include #include "zdtmtst.h" +#include "sysctl.h" #include "ns.h" int criu_status_in = -1, criu_status_in_peer = -1, criu_status_out = -1; @@ -157,6 +158,16 @@ static int prepare_mntns(void) return 0; } +static int set_ping_group_range(void) +{ + if (sysctl_write_str("/proc/sys/net/ipv4/ping_group_range", "0 2147483647")) { + fprintf(stderr, "sysctl_write_str() failed: %m\n"); + return -1; + } + + return 0; +} + static int prepare_namespaces(void) { if (setuid(0) || setgid(0) || setgroups(0, NULL)) { @@ -332,6 +343,10 @@ int ns_init(int argc, char **argv) if (create_timens()) exit(1); + if (set_ping_group_range() < 0) { + exit(1); + } + if (init_notify()) { fprintf(stderr, "Can't init pre-dump notification: %m"); exit(1); @@ -525,6 +540,10 @@ void ns_create(int argc, char **argv) unlink(pidfile); pidfile = pidf; + if (set_ping_group_range() < 0) { + exit(1); + } + if (write_pidfile(pid)) exit(1); diff --git a/test/zdtm/lib/sysctl.c b/test/zdtm/lib/sysctl.c index 9583ec3df5..6f0d3ac56c 100644 --- a/test/zdtm/lib/sysctl.c +++ b/test/zdtm/lib/sysctl.c @@ -57,3 +57,30 @@ int sysctl_write_int(const char *name, int val) close(fd); return ret; } + +int sysctl_write_str(const char *name, const char *val) +{ + int fd; + int ret; + char buf[16]; + + fd = open(name, O_WRONLY); + if (fd < 0) { + pr_perror("Can't open %s", name); + return fd; + } + + sprintf(buf, "%s\n", val); + + ret = write(fd, buf, strlen(buf)); + if (ret < 0) { + pr_perror("Can't write %s into %s", val, name); + ret = -errno; + goto err; + } + + ret = 0; +err: + close(fd); + return ret; +} diff --git a/test/zdtm/lib/sysctl.h b/test/zdtm/lib/sysctl.h index 67129102fe..b47829fc9f 100644 --- a/test/zdtm/lib/sysctl.h +++ b/test/zdtm/lib/sysctl.h @@ -3,5 +3,6 @@ extern int sysctl_read_int(const char *name, int *data); extern int sysctl_write_int(const char *name, int val); +extern int sysctl_write_str(const char *name, const char *val); #endif diff --git a/test/zdtm_ct.c b/test/zdtm_ct.c index 44316893da..eb94b1782f 100644 --- a/test/zdtm_ct.c +++ b/test/zdtm_ct.c @@ -11,6 +11,8 @@ #include #include +#include "zdtm/lib/sysctl.h" + #ifndef CLONE_NEWTIME #define CLONE_NEWTIME 0x00000080 /* New time namespace */ #endif @@ -112,6 +114,9 @@ int main(int argc, char **argv) if (!uid) { if (create_timens()) exit(1); + // Allow all GIDs to open an unprivileged ICMP socket + if (sysctl_write_str("/proc/sys/net/ipv4/ping_group_range", "0 2147483647")) + exit(1); if (mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL)) { fprintf(stderr, "mount(/, S_REC | MS_SLAVE)): %m"); return 1; From 3c6ab129ea63ca0762ef34af81b3040a238246d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=B8=E0=A4=AE=E0=A5=80=E0=A4=B0=20=E0=A4=B8=E0=A4=BF?= =?UTF-8?q?=E0=A4=82=E0=A4=B9=20Sameer=20Singh?= Date: Wed, 1 Jan 2025 17:31:32 +0530 Subject: [PATCH 4/8] sk-inet: Checkpoint/Restore net.ipv4.ping_group_range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dump and restore the net.ipv4.ping_group_range variable to allow the creation of unprivileged ICMP sockets. Signed-off-by: समीर सिंह Sameer Singh --- criu/sk-inet.c | 32 ++++++++++++++++++++++++++++++++ criu/sockets.c | 2 +- images/sk-inet.proto | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/criu/sk-inet.c b/criu/sk-inet.c index c930f681dd..83503f2c3b 100644 --- a/criu/sk-inet.c +++ b/criu/sk-inet.c @@ -32,6 +32,7 @@ #include "rst-malloc.h" #include "sockets.h" #include "sk-inet.h" +#include "sysctl.h" #include "protobuf.h" #include "util.h" #include "namespaces.h" @@ -481,6 +482,23 @@ static int do_dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p, int fa goto err; } + if (type == SOCK_DGRAM && (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)) { + char buffer[16]; + + struct sysctl_req req[] = { + { "net/ipv4/ping_group_range", &buffer, CTL_STR(16) }, + }; + + ret = sysctl_op(req, ARRAY_SIZE(req), CTL_READ, CLONE_NEWNET); + if (ret < 0) { + pr_perror("Failed to read ping group range"); + goto err; + } + + buffer[strlen(buffer)] = '\0'; + ie.ping_grp_range = buffer; + } + sk->cork = false; if (type != SOCK_RAW) { switch (proto) { @@ -877,6 +895,20 @@ static int open_inet_sk(struct file_desc *d, int *new_fd) if (run_setsockcreatecon(fle->fe)) return -1; + if (ie->type == SOCK_DGRAM && (ie->proto == IPPROTO_ICMP || ie->proto == IPPROTO_ICMPV6)) { + if (strlen(ie->ping_grp_range) > 1) { + int ret; + struct sysctl_req req[] = { + { "net/ipv4/ping_group_range", ie->ping_grp_range, CTL_STR(strlen(ie->ping_grp_range)) }, + }; + ret = sysctl_op(req, ARRAY_SIZE(req), CTL_WRITE, CLONE_NEWNET); + if (ret < 0) { + pr_perror("Failed to set ping_group_range"); + return -1; + } + } + } + sk = socket(ie->family, ie->type, ie->proto); if (sk < 0) { pr_perror("Can't create inet socket"); diff --git a/criu/sockets.c b/criu/sockets.c index 808d991453..0affccad02 100644 --- a/criu/sockets.c +++ b/criu/sockets.c @@ -65,7 +65,7 @@ const char *socket_proto_name(unsigned int proto, char *nm, size_t size) [IPPROTO_IPV6] = __stringify_1(IPPROTO_IPV6), [IPPROTO_RSVP] = __stringify_1(IPPROTO_RSVP), [IPPROTO_GRE] = __stringify_1(IPPROTO_GRE), [IPPROTO_ESP] = __stringify_1(IPPROTO_ESP), [IPPROTO_AH] = __stringify_1(IPPROTO_AH), [IPPROTO_UDPLITE] = __stringify_1(IPPROTO_UDPLITE), - [IPPROTO_RAW] = __stringify_1(IPPROTO_RAW), + [IPPROTO_RAW] = __stringify_1(IPPROTO_RAW), [IPPROTO_ICMPV6] = __stringify_1(IPPROTO_ICMPV6), }; return __socket_const_name(nm, size, protos, ARRAY_SIZE(protos), proto); } diff --git a/images/sk-inet.proto b/images/sk-inet.proto index 2c709e0181..d9cec562b8 100644 --- a/images/sk-inet.proto +++ b/images/sk-inet.proto @@ -58,4 +58,5 @@ message inet_sk_entry { optional uint32 ns_id = 18; optional sk_shutdown shutdown = 19; optional tcp_opts_entry tcp_opts = 20; + optional string ping_grp_range = 21; } From e7dafb6ee4227e17a6dc1b3772ab3af49aadef78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=B8=E0=A4=AE=E0=A5=80=E0=A4=B0=20=E0=A4=B8=E0=A4=BF?= =?UTF-8?q?=E0=A4=82=E0=A4=B9=20Sameer=20Singh?= Date: Wed, 1 Jan 2025 21:14:46 +0530 Subject: [PATCH 5/8] zdtm: set net.ipv4.ping_group_range to 40000-50000 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the sysctl variable net.ipv4.ping_group_range to 40000-50000 to allow other tests to pass. Signed-off-by: समीर सिंह Sameer Singh --- criu/sk-inet.c | 34 +++++++++++++++++----------------- test/zdtm/lib/ns.c | 7 ++----- test/zdtm_ct.c | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/criu/sk-inet.c b/criu/sk-inet.c index 83503f2c3b..067b171ce0 100644 --- a/criu/sk-inet.c +++ b/criu/sk-inet.c @@ -482,23 +482,6 @@ static int do_dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p, int fa goto err; } - if (type == SOCK_DGRAM && (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)) { - char buffer[16]; - - struct sysctl_req req[] = { - { "net/ipv4/ping_group_range", &buffer, CTL_STR(16) }, - }; - - ret = sysctl_op(req, ARRAY_SIZE(req), CTL_READ, CLONE_NEWNET); - if (ret < 0) { - pr_perror("Failed to read ping group range"); - goto err; - } - - buffer[strlen(buffer)] = '\0'; - ie.ping_grp_range = buffer; - } - sk->cork = false; if (type != SOCK_RAW) { switch (proto) { @@ -595,6 +578,23 @@ static int do_dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p, int fa if (dump_socket_opts(lfd, &skopts)) goto err; + if (type == SOCK_DGRAM && (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)) { + char buffer[16]; + + struct sysctl_req req[] = { + { "net/ipv4/ping_group_range", &buffer, CTL_STR(16) }, + }; + + ret = sysctl_op(req, ARRAY_SIZE(req), CTL_READ, CLONE_NEWNET); + if (ret < 0) { + pr_perror("Failed to read ping group range"); + goto err; + } + + buffer[strlen(buffer)] = '\0'; + ie.ping_grp_range = buffer; + } + pr_info("Dumping inet socket at %d\n", p->fd); show_one_inet("Dumping", sk); show_one_inet_img("Dumped", &ie); diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c index 55b9cf0fcd..7c78e0ada7 100644 --- a/test/zdtm/lib/ns.c +++ b/test/zdtm/lib/ns.c @@ -160,7 +160,8 @@ static int prepare_mntns(void) static int set_ping_group_range(void) { - if (sysctl_write_str("/proc/sys/net/ipv4/ping_group_range", "0 2147483647")) { + // Allow GIDs 40000-50000 to open an unprivileged ICMP socket + if (sysctl_write_str("/proc/sys/net/ipv4/ping_group_range", "40000 50000")) { fprintf(stderr, "sysctl_write_str() failed: %m\n"); return -1; } @@ -540,10 +541,6 @@ void ns_create(int argc, char **argv) unlink(pidfile); pidfile = pidf; - if (set_ping_group_range() < 0) { - exit(1); - } - if (write_pidfile(pid)) exit(1); diff --git a/test/zdtm_ct.c b/test/zdtm_ct.c index eb94b1782f..1fc3b2befe 100644 --- a/test/zdtm_ct.c +++ b/test/zdtm_ct.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -11,8 +12,6 @@ #include #include -#include "zdtm/lib/sysctl.h" - #ifndef CLONE_NEWTIME #define CLONE_NEWTIME 0x00000080 /* New time namespace */ #endif @@ -93,6 +92,33 @@ static int create_timens(void) return 0; } +static int sysctl_write_str(const char *name, const char *val) +{ + int fd; + int ret; + char buf[16]; + + fd = open(name, O_WRONLY); + if (fd < 0) { + fprintf(stderr, "Can't open %s: %m\n", name); + return fd; + } + + sprintf(buf, "%s\n", val); + + ret = write(fd, buf, strlen(buf)); + if (ret < 0) { + fprintf(stderr, "Can't write %s into %s: %m\n", val, name); + ret = -errno; + goto err; + } + + ret = 0; +err: + close(fd); + return ret; +} + int main(int argc, char **argv) { uid_t uid; @@ -114,8 +140,8 @@ int main(int argc, char **argv) if (!uid) { if (create_timens()) exit(1); - // Allow all GIDs to open an unprivileged ICMP socket - if (sysctl_write_str("/proc/sys/net/ipv4/ping_group_range", "0 2147483647")) + // Allow GIDs 40000-50000 to open an unprivileged ICMP socket + if (sysctl_write_str("/proc/sys/net/ipv4/ping_group_range", "40000 50000")) exit(1); if (mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL)) { fprintf(stderr, "mount(/, S_REC | MS_SLAVE)): %m"); From d6d05752010e59b00be2e8aa582a18c46ae2776c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=B8=E0=A4=AE=E0=A5=80=E0=A4=B0=20=E0=A4=B8=E0=A4=BF?= =?UTF-8?q?=E0=A4=82=E0=A4=B9=20Sameer=20Singh?= Date: Wed, 1 Jan 2025 21:20:45 +0530 Subject: [PATCH 6/8] test: modify the IP4/ICMP test and add a test for IP6/ICMP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit modify the IP4/ICMP test so that the socket is created before the call to `test_daemon()` and `test_waitsig()`. Also add a test IP6/ICMP. Signed-off-by: समीर सिंह Sameer Singh --- test/zdtm/static/Makefile | 1 + test/zdtm/static/socket6_icmp.c | 95 ++++++++++++++++++++++++++++++ test/zdtm/static/socket6_icmp.desc | 1 + test/zdtm/static/socket_icmp.c | 81 +++++++++++-------------- test/zdtm/static/socket_icmp.desc | 1 + 5 files changed, 132 insertions(+), 47 deletions(-) create mode 100644 test/zdtm/static/socket6_icmp.c create mode 100644 test/zdtm/static/socket6_icmp.desc create mode 100644 test/zdtm/static/socket_icmp.desc diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index b48474348f..e0409f6f84 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -36,6 +36,7 @@ TST_NOFILE := \ socket6_udp \ socket_udp_shutdown \ socket_icmp \ + socket6_icmp \ sk-freebind \ sk-freebind-false \ socket_udplite \ diff --git a/test/zdtm/static/socket6_icmp.c b/test/zdtm/static/socket6_icmp.c new file mode 100644 index 0000000000..5e0ec7bfe4 --- /dev/null +++ b/test/zdtm/static/socket6_icmp.c @@ -0,0 +1,95 @@ +#include "zdtmtst.h" + +const char *test_doc = "static test for IP6/ICMP socket\n"; +const char *test_author = "समीर सिंह Sameer Singh \n"; + +/* Description: + * Send a ping to localhost using IP6/ICMP socket + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PACKET_SIZE 64 +#define RECV_TIMEOUT 1 + +static int echo_id = 1234; + +int main(int argc, char **argv) +{ + int ret, sock, seq = 0, recv_len = 0; + char packet[PACKET_SIZE], recv_packet[PACKET_SIZE]; + + struct timeval tv; + struct icmp6_hdr icmp_header, *icmp_reply; + struct sockaddr_in6 addr, recv_addr; + socklen_t addr_len; + + test_init(argc, argv); + + sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); + if (sock < 0) { + pr_perror("Can't create socket"); + return 1; + } + + tv.tv_sec = RECV_TIMEOUT; + tv.tv_usec = 0; + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { + pr_perror("Can't set socket option"); + return 1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + inet_pton(AF_INET6, "::1", &addr.sin6_addr); + + memset(&icmp_header, 0, sizeof(icmp_header)); + icmp_header.icmp6_type = ICMP6_ECHO_REQUEST; + icmp_header.icmp6_code = 0; + icmp_header.icmp6_id = echo_id; + icmp_header.icmp6_seq = seq; + + memcpy(packet, &icmp_header, sizeof(icmp_header)); + memset(packet + sizeof(icmp_header), 0xa5, + PACKET_SIZE - sizeof(icmp_header)); + + test_daemon(); + test_waitsig(); + + ret = sendto(sock, packet, PACKET_SIZE, 0, + (struct sockaddr *)&addr, sizeof(addr)); + + if (ret < 0) { + pr_perror("Can't send"); + return 1; + } + + addr_len = sizeof(recv_addr); + + recv_len = recvfrom(sock, recv_packet, sizeof(recv_packet), 0, + (struct sockaddr *)&recv_addr, &addr_len); + + if (recv_len < 0) { + pr_perror("Can't recv"); + return 1; + } + + icmp_reply = (struct icmp6_hdr *)recv_packet; + + if (icmp_reply->icmp6_type != ICMP6_ECHO_REPLY) { + fail("Got no ICMP_ECHO_REPLY"); + return 1; + } + + close(sock); + pass(); + return 0; +} diff --git a/test/zdtm/static/socket6_icmp.desc b/test/zdtm/static/socket6_icmp.desc new file mode 100644 index 0000000000..7b6fcbc22b --- /dev/null +++ b/test/zdtm/static/socket6_icmp.desc @@ -0,0 +1 @@ +{'flavor': 'h ns'} \ No newline at end of file diff --git a/test/zdtm/static/socket_icmp.c b/test/zdtm/static/socket_icmp.c index b2d24658ba..bf47a8cec2 100644 --- a/test/zdtm/static/socket_icmp.c +++ b/test/zdtm/static/socket_icmp.c @@ -17,12 +17,14 @@ const char *test_author = "समीर सिंह Sameer Singh #include -#define PACKET_SIZE 64 +#define PACKET_SIZE 64 #define RECV_TIMEOUT 1 -int ping(void) +static int echo_id = 1234; + +int main(int argc, char **argv) { - int ret, sock, seq = 0, recv_len = 0; + int ret, sock, seq = 0; char packet[PACKET_SIZE], recv_packet[PACKET_SIZE]; struct timeval tv; @@ -30,13 +32,14 @@ int ping(void) struct sockaddr_in addr, recv_addr; socklen_t addr_len; + test_init(argc, argv); + sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP); if (sock < 0) { pr_perror("Can't create socket"); return 1; } - tv.tv_sec = RECV_TIMEOUT; tv.tv_usec = 0; if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { @@ -48,61 +51,45 @@ int ping(void) addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - for (;;) { - memset(&icmp_header, 0, sizeof(icmp_header)); - icmp_header.type = ICMP_ECHO; - icmp_header.code = 0; - icmp_header.un.echo.id = getpid(); - icmp_header.un.echo.sequence = seq++; + memset(&icmp_header, 0, sizeof(icmp_header)); + icmp_header.type = ICMP_ECHO; + icmp_header.code = 0; + icmp_header.un.echo.id = echo_id; + icmp_header.un.echo.sequence = seq; - memcpy(packet, &icmp_header, sizeof(icmp_header)); - memset(packet + sizeof(icmp_header), 0xa5, - PACKET_SIZE - sizeof(icmp_header)); + memcpy(packet, &icmp_header, sizeof(icmp_header)); + memset(packet + sizeof(icmp_header), 0xa5, + PACKET_SIZE - sizeof(icmp_header)); - ret = sendto(sock, packet, PACKET_SIZE, 0, - (struct sockaddr *)&addr, sizeof(addr)); + test_daemon(); + test_waitsig(); - if (ret < 0) { - fail("Can't send"); - return 1; - } + ret = sendto(sock, packet, PACKET_SIZE, 0, + (struct sockaddr *)&addr, sizeof(addr)); - addr_len = sizeof(recv_addr); + if (ret < 0) { + fail("Can't send"); + return 1; + } - ret = recvfrom(sock, recv_packet, sizeof(recv_packet), 0, - (struct sockaddr*)&recv_addr, &addr_len); + addr_len = sizeof(recv_addr); - if (ret < 0) { - fail("Can't recv"); - return 1; - } + ret = recvfrom(sock, recv_packet, sizeof(recv_packet), 0, + (struct sockaddr *)&recv_addr, &addr_len); - icmp_reply = (struct icmphdr *)recv_packet; + if (ret < 0) { + fail("Can't recv"); + return 1; + } - if (icmp_reply->type == ICMP_ECHOREPLY) { - printf("%d bytes from %s: icmp_seq=%d\n", - recv_len, - inet_ntoa(recv_addr.sin_addr), - icmp_reply->un.echo.sequence); - } + icmp_reply = (struct icmphdr *)recv_packet; - sleep(1); + if (icmp_reply->type != ICMP_ECHOREPLY) { + fail("Got no ICMP_ECHO_REPLY"); + return 1; } close(sock); -} - -int main(int argc, char **argv) -{ - int ret; - test_init(argc, argv); - - test_daemon(); - test_waitsig(); - - ret = ping(); - if (ret == 1) - fail("Cannot ping"); pass(); return 0; diff --git a/test/zdtm/static/socket_icmp.desc b/test/zdtm/static/socket_icmp.desc new file mode 100644 index 0000000000..7b6fcbc22b --- /dev/null +++ b/test/zdtm/static/socket_icmp.desc @@ -0,0 +1 @@ +{'flavor': 'h ns'} \ No newline at end of file From 3ee179eddc40b4e69ebf56f025ab0acb57ba25a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=B8=E0=A4=AE=E0=A5=80=E0=A4=B0=20=E0=A4=B8=E0=A4=BF?= =?UTF-8?q?=E0=A4=82=E0=A4=B9=20Sameer=20Singh?= Date: Thu, 9 Jan 2025 14:04:49 +0530 Subject: [PATCH 7/8] zdtm: set net.ipv4.ping_group_range to 0-58468 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the sysctl variable net.ipv4.ping_group_range to 0-58468 since the zdtm test GID is in this range. Signed-off-by: समीर सिंह Sameer Singh --- test/zdtm/lib/ns.c | 4 ++-- test/zdtm_ct.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c index 7c78e0ada7..e0e8a6e3b1 100644 --- a/test/zdtm/lib/ns.c +++ b/test/zdtm/lib/ns.c @@ -160,8 +160,8 @@ static int prepare_mntns(void) static int set_ping_group_range(void) { - // Allow GIDs 40000-50000 to open an unprivileged ICMP socket - if (sysctl_write_str("/proc/sys/net/ipv4/ping_group_range", "40000 50000")) { + // Allow GIDs 0-58468 to open an unprivileged ICMP socket + if (sysctl_write_str("/proc/sys/net/ipv4/ping_group_range", "0 58468")) { fprintf(stderr, "sysctl_write_str() failed: %m\n"); return -1; } diff --git a/test/zdtm_ct.c b/test/zdtm_ct.c index 1fc3b2befe..b598cfe06d 100644 --- a/test/zdtm_ct.c +++ b/test/zdtm_ct.c @@ -140,8 +140,8 @@ int main(int argc, char **argv) if (!uid) { if (create_timens()) exit(1); - // Allow GIDs 40000-50000 to open an unprivileged ICMP socket - if (sysctl_write_str("/proc/sys/net/ipv4/ping_group_range", "40000 50000")) + // Allow GIDs 0-58468 to open an unprivileged ICMP socket + if (sysctl_write_str("/proc/sys/net/ipv4/ping_group_range", "0 58468")) exit(1); if (mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL)) { fprintf(stderr, "mount(/, S_REC | MS_SLAVE)): %m"); From a5b5985f3a44974c32ce8fc94ce7eac3220d9153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=B8=E0=A4=AE=E0=A5=80=E0=A4=B0=20=E0=A4=B8=E0=A4=BF?= =?UTF-8?q?=E0=A4=82=E0=A4=B9=20Sameer=20Singh?= Date: Sat, 11 Jan 2025 07:03:38 +0530 Subject: [PATCH 8/8] sk-inet: Duplicate and free ping_group_range buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the `stack-use-after-scope` error from the address sanitizer since the local variable `buffer`, goes out of scope. Signed-off-by: समीर सिंह Sameer Singh --- criu/sk-inet.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/criu/sk-inet.c b/criu/sk-inet.c index 067b171ce0..8bd5356e7b 100644 --- a/criu/sk-inet.c +++ b/criu/sk-inet.c @@ -592,7 +592,10 @@ static int do_dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p, int fa } buffer[strlen(buffer)] = '\0'; - ie.ping_grp_range = buffer; + + ie.ping_grp_range = xstrdup(buffer); + if (!ie.ping_grp_range) + goto err; } pr_info("Dumping inet socket at %d\n", p->fd); @@ -645,6 +648,7 @@ static int do_dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p, int fa xfree(ie.src_addr); xfree(ie.dst_addr); xfree(ie.ifname); + xfree(ie.ping_grp_range); return err; }