Compare commits

...

No commits in common. "c9s" and "c8-stream-3.0" have entirely different histories.

18 changed files with 99 additions and 1557 deletions

8
.gitignore vendored
View File

@ -1,7 +1 @@
/libslirp-v4.0.0.tar.gz SOURCES/libslirp-4.3.1.tar.xz
/libslirp-v4.1.0.tar.gz
/libslirp-v4.2.0.tar.gz
/libslirp-v4.3.0.tar.gz
/libslirp-4.3.0.tar.xz
/libslirp-4.3.1.tar.xz
/libslirp-4.4.0.tar.xz

View File

@ -1 +1 @@
5ef4ed055299eab0703d4c49da552fdb61357f13 libslirp-4.4.0.tar.xz f69c50c264a465bde6fe0cd6b577e2f1c0b20ece SOURCES/libslirp-4.3.1.tar.xz

View File

@ -1,54 +0,0 @@
From 87f5d0c70bdb46d467d32e3c3a8d7a472c97e148 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Fri, 4 Jun 2021 15:58:25 +0400
Subject: [PATCH 1/7] Add mtod_check()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Recent security issues demonstrate the lack of safety care when casting
a mbuf to a particular structure type. At least, it should check that
the buffer is large enough. The following patches will make use of this
function.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
(cherry picked from commit 93e645e72a056ec0b2c16e0299fc5c6b94e4ca17)
---
src/mbuf.c | 11 +++++++++++
src/mbuf.h | 1 +
2 files changed, 12 insertions(+)
diff --git a/src/mbuf.c b/src/mbuf.c
index 54ec721..cb2e971 100644
--- a/src/mbuf.c
+++ b/src/mbuf.c
@@ -222,3 +222,14 @@ struct mbuf *dtom(Slirp *slirp, void *dat)
return (struct mbuf *)0;
}
+
+void *mtod_check(struct mbuf *m, size_t len)
+{
+ if (m->m_len >= len) {
+ return m->m_data;
+ }
+
+ DEBUG_ERROR("mtod failed");
+
+ return NULL;
+}
diff --git a/src/mbuf.h b/src/mbuf.h
index 546e785..2015e32 100644
--- a/src/mbuf.h
+++ b/src/mbuf.h
@@ -118,6 +118,7 @@ void m_inc(struct mbuf *, int);
void m_adj(struct mbuf *, int);
int m_copy(struct mbuf *, struct mbuf *, int, int);
struct mbuf *dtom(Slirp *, void *);
+void *mtod_check(struct mbuf *, size_t len);
static inline void ifs_init(struct mbuf *ifm)
{
--
2.29.0

View File

@ -1,30 +0,0 @@
From c9f314f6e315a5518432761fea864196a290f799 Mon Sep 17 00:00:00 2001
From: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Date: Thu, 17 Jun 2021 18:01:32 +0900
Subject: [PATCH] Fix "DHCP broken in libslirp v4.6.0"
Fix issue 48
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
---
src/bootp.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/bootp.c b/src/bootp.c
index cafa1eb..0a35873 100644
--- a/src/bootp.c
+++ b/src/bootp.c
@@ -359,7 +359,9 @@ static void bootp_reply(Slirp *slirp,
daddr.sin_addr.s_addr = 0xffffffffu;
- m->m_len = sizeof(struct bootp_t) - sizeof(struct ip) - sizeof(struct udphdr);
+ assert ((q - rbp->bp_vend + 1) <= DHCP_OPT_LEN);
+
+ m->m_len = sizeof(struct bootp_t) + (q - rbp->bp_vend + 1) - sizeof(struct ip) - sizeof(struct udphdr);
udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
}
--
2.29.0

View File

@ -1,186 +0,0 @@
From c6fcedf4f53e070dfcb7a6910624705cdcc0a027 Mon Sep 17 00:00:00 2001
From: Doug Evans <dje@google.com>
Date: Tue, 23 Feb 2021 15:23:19 -0800
Subject: [PATCH 1/2] New utility slirp_ether_ntoa
... and call it everywhere a macaddr is pretty-printed.
Signed-off-by: Doug Evans <dje@google.com>
(cherry picked from commit ac00ba460e101bbce0a167b4f0517378a0fbe6b8)
---
src/arp_table.c | 12 +++++++-----
src/ndp_table.c | 18 ++++++++++--------
src/slirp.c | 11 +++++------
src/util.c | 11 +++++++++++
src/util.h | 8 ++++++++
5 files changed, 41 insertions(+), 19 deletions(-)
diff --git a/src/arp_table.c b/src/arp_table.c
index 959e5b9ec0af..ba8c8a4eee88 100644
--- a/src/arp_table.c
+++ b/src/arp_table.c
@@ -34,11 +34,12 @@ void arp_table_add(Slirp *slirp, uint32_t ip_addr,
~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr;
ArpTable *arptbl = &slirp->arp_table;
int i;
+ char ethaddr_str[ETH_ADDRSTRLEN];
DEBUG_CALL("arp_table_add");
DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){ .s_addr = ip_addr }));
- DEBUG_ARG("hw addr = %02x:%02x:%02x:%02x:%02x:%02x", ethaddr[0], ethaddr[1],
- ethaddr[2], ethaddr[3], ethaddr[4], ethaddr[5]);
+ DEBUG_ARG("hw addr = %s", slirp_ether_ntoa(ethaddr, ethaddr_str,
+ sizeof(ethaddr_str)));
if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
/* Do not register broadcast addresses */
@@ -67,6 +68,7 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr;
ArpTable *arptbl = &slirp->arp_table;
int i;
+ char ethaddr_str[ETH_ADDRSTRLEN];
DEBUG_CALL("arp_table_search");
DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){ .s_addr = ip_addr }));
@@ -81,9 +83,9 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
for (i = 0; i < ARP_TABLE_SIZE; i++) {
if (arptbl->table[i].ar_sip == ip_addr) {
memcpy(out_ethaddr, arptbl->table[i].ar_sha, ETH_ALEN);
- DEBUG_ARG("found hw addr = %02x:%02x:%02x:%02x:%02x:%02x",
- out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
- out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]);
+ DEBUG_ARG("found hw addr = %s",
+ slirp_ether_ntoa(out_ethaddr, ethaddr_str,
+ sizeof(ethaddr_str)));
return 1;
}
}
diff --git a/src/ndp_table.c b/src/ndp_table.c
index 110d6ea0e43f..61ae8e0468fc 100644
--- a/src/ndp_table.c
+++ b/src/ndp_table.c
@@ -12,13 +12,14 @@ void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr,
char addrstr[INET6_ADDRSTRLEN];
NdpTable *ndp_table = &slirp->ndp_table;
int i;
+ char ethaddr_str[ETH_ADDRSTRLEN];
inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);
DEBUG_CALL("ndp_table_add");
DEBUG_ARG("ip = %s", addrstr);
- DEBUG_ARG("hw addr = %02x:%02x:%02x:%02x:%02x:%02x", ethaddr[0], ethaddr[1],
- ethaddr[2], ethaddr[3], ethaddr[4], ethaddr[5]);
+ DEBUG_ARG("hw addr = %s", slirp_ether_ntoa(ethaddr, ethaddr_str,
+ sizeof(ethaddr_str)));
if (IN6_IS_ADDR_MULTICAST(&ip_addr) || in6_zero(&ip_addr)) {
/* Do not register multicast or unspecified addresses */
@@ -50,6 +51,7 @@ bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr,
char addrstr[INET6_ADDRSTRLEN];
NdpTable *ndp_table = &slirp->ndp_table;
int i;
+ char ethaddr_str[ETH_ADDRSTRLEN];
inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);
@@ -66,18 +68,18 @@ bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr,
out_ethaddr[3] = ip_addr.s6_addr[13];
out_ethaddr[4] = ip_addr.s6_addr[14];
out_ethaddr[5] = ip_addr.s6_addr[15];
- DEBUG_ARG("multicast addr = %02x:%02x:%02x:%02x:%02x:%02x",
- out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
- out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]);
+ DEBUG_ARG("multicast addr = %s",
+ slirp_ether_ntoa(out_ethaddr, ethaddr_str,
+ sizeof(ethaddr_str)));
return 1;
}
for (i = 0; i < NDP_TABLE_SIZE; i++) {
if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) {
memcpy(out_ethaddr, ndp_table->table[i].eth_addr, ETH_ALEN);
- DEBUG_ARG("found hw addr = %02x:%02x:%02x:%02x:%02x:%02x",
- out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
- out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]);
+ DEBUG_ARG("found hw addr = %s",
+ slirp_ether_ntoa(out_ethaddr, ethaddr_str,
+ sizeof(ethaddr_str)));
return 1;
}
}
diff --git a/src/slirp.c b/src/slirp.c
index abb6f9a966d8..1f2513a9e1a4 100644
--- a/src/slirp.c
+++ b/src/slirp.c
@@ -1054,6 +1054,7 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
uint8_t ethaddr[ETH_ALEN];
const struct ip *iph = (const struct ip *)ifm->m_data;
int ret;
+ char ethaddr_str[ETH_ADDRSTRLEN];
if (ifm->m_len + ETH_HLEN > sizeof(buf)) {
return 1;
@@ -1079,12 +1080,10 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
}
memcpy(eh->h_dest, ethaddr, ETH_ALEN);
- DEBUG_ARG("src = %02x:%02x:%02x:%02x:%02x:%02x", eh->h_source[0],
- eh->h_source[1], eh->h_source[2], eh->h_source[3],
- eh->h_source[4], eh->h_source[5]);
- DEBUG_ARG("dst = %02x:%02x:%02x:%02x:%02x:%02x", eh->h_dest[0],
- eh->h_dest[1], eh->h_dest[2], eh->h_dest[3], eh->h_dest[4],
- eh->h_dest[5]);
+ DEBUG_ARG("src = %s", slirp_ether_ntoa(eh->h_source, ethaddr_str,
+ sizeof(ethaddr_str)));
+ DEBUG_ARG("dst = %s", slirp_ether_ntoa(eh->h_dest, ethaddr_str,
+ sizeof(ethaddr_str)));
memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
slirp_send_packet_all(slirp, buf, ifm->m_len + ETH_HLEN);
return 1;
diff --git a/src/util.c b/src/util.c
index 2d8fb9642e76..67ef66786f54 100644
--- a/src/util.c
+++ b/src/util.c
@@ -427,3 +427,14 @@ int slirp_fmt0(char *str, size_t size, const char *format, ...)
return rv;
}
+
+const char *slirp_ether_ntoa(const uint8_t *addr, char *out_str,
+ size_t out_str_size)
+{
+ assert(out_str_size >= ETH_ADDRSTRLEN);
+
+ slirp_fmt0(out_str, out_str_size, "%02x:%02x:%02x:%02x:%02x:%02x",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+ return out_str;
+}
diff --git a/src/util.h b/src/util.h
index d67b3d0de9aa..8134db961779 100644
--- a/src/util.h
+++ b/src/util.h
@@ -84,6 +84,7 @@ struct iovec {
#define SCALE_MS 1000000
#define ETH_ALEN 6
+#define ETH_ADDRSTRLEN 18 /* "xx:xx:xx:xx:xx:xx", with trailing NUL */
#define ETH_HLEN 14
#define ETH_P_IP (0x0800) /* Internet Protocol packet */
#define ETH_P_ARP (0x0806) /* Address Resolution packet */
@@ -186,4 +187,11 @@ void slirp_pstrcpy(char *buf, int buf_size, const char *str);
int slirp_fmt(char *str, size_t size, const char *format, ...) G_GNUC_PRINTF(3, 4);
int slirp_fmt0(char *str, size_t size, const char *format, ...) G_GNUC_PRINTF(3, 4);
+/*
+ * Pretty print a MAC address into out_str.
+ * As a convenience returns out_str.
+ */
+const char *slirp_ether_ntoa(const uint8_t *addr, char *out_str,
+ size_t out_str_len);
+
#endif
--
2.34.1.428.gdcc0cd074f0c

View File

@ -1,412 +0,0 @@
From 5f19b8960548bd0704ae7054dce599ec1abcf258 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Mon, 4 Mar 2024 22:49:39 +0400
Subject: [PATCH] ip: Enforce strict aliasing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
JIRA: RHEL-27868
Sometimes ipq were casted to ipasfrag, and the original and casted
pointer were used simultaneously in ip_reass(). GCC 12.1.0 assumes
these pointers are not aliases, and therefore incorrectly the pointed
data will not be modified when it is actually modified with another
pointer.
To fix this problem, introduce a new type "ipas", which is a universal
type denoting an entry in the assembly queue and contains union for
specialization as queue head (frequently referred as "q" or "ipq" in
the source code) or IP fragment ("f" or "ipf").
This bug was found by Alexander Bulekov when fuzzing QEMU:
https://patchew.org/QEMU/20230129053316.1071513-1-alxndr@bu.edu/
The fixed test case is:
fuzz/crash_449dd4ad72212627fe3245c875f79a7033cc5382
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
(cherry picked from commit 26be815b86e8d49add8c9a8b320239b9594ff03d)
[ Marc-André - various backport conflicts in ip_input.c ]
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
src/ip.h | 21 ++----
src/ip_input.c | 170 ++++++++++++++++++++++++-------------------------
2 files changed, 91 insertions(+), 100 deletions(-)
diff --git a/src/ip.h b/src/ip.h
index e5d4aa8..ab1144d 100644
--- a/src/ip.h
+++ b/src/ip.h
@@ -209,10 +209,8 @@ struct ipovly {
* being reassembled is attached to one of these structures.
* They are timed out after ipq_ttl drops to 0, and may also
* be reclaimed if memory becomes tight.
- * size 28 bytes
*/
struct ipq {
- struct qlink frag_link; /* to ip headers of fragments */
struct qlink ip_link; /* to other reass headers */
uint8_t ipq_ttl; /* time for reass q to live */
uint8_t ipq_p; /* protocol of this fragment */
@@ -220,23 +218,16 @@ struct ipq {
struct in_addr ipq_src, ipq_dst;
};
-/*
- * Ip header, when holding a fragment.
- *
- * Note: ipf_link must be at same offset as frag_link above
- */
-struct ipasfrag {
- struct qlink ipf_link;
- struct ip ipf_ip;
+struct ipas {
+ struct qlink link;
+ union {
+ struct ipq ipq;
+ struct ip ipf_ip;
+ };
};
-G_STATIC_ASSERT(offsetof(struct ipq, frag_link) ==
- offsetof(struct ipasfrag, ipf_link));
-
#define ipf_off ipf_ip.ip_off
#define ipf_tos ipf_ip.ip_tos
#define ipf_len ipf_ip.ip_len
-#define ipf_next ipf_link.next
-#define ipf_prev ipf_link.prev
#endif
diff --git a/src/ip_input.c b/src/ip_input.c
index 7f017a2..aac56a9 100644
--- a/src/ip_input.c
+++ b/src/ip_input.c
@@ -41,8 +41,8 @@
static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp);
static void ip_freef(Slirp *slirp, struct ipq *fp);
-static void ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev);
-static void ip_deq(register struct ipasfrag *p);
+static void ip_enq(register struct ipas *p, register struct ipas *prev);
+static void ip_deq(register struct ipas *p);
/*
* IP initialization: fill in IP protocol switch table.
@@ -144,7 +144,7 @@ void ip_input(struct mbuf *m)
* XXX This should fail, don't fragment yet
*/
if (ip->ip_off & ~IP_DF) {
- register struct ipq *fp;
+ register struct ipq *q;
struct qlink *l;
/*
* Look for queue of fragments
@@ -152,14 +152,14 @@ void ip_input(struct mbuf *m)
*/
for (l = slirp->ipq.ip_link.next; l != &slirp->ipq.ip_link;
l = l->next) {
- fp = container_of(l, struct ipq, ip_link);
- if (ip->ip_id == fp->ipq_id &&
- ip->ip_src.s_addr == fp->ipq_src.s_addr &&
- ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
- ip->ip_p == fp->ipq_p)
+ q = container_of(l, struct ipq, ip_link);
+ if (ip->ip_id == q->ipq_id &&
+ ip->ip_src.s_addr == q->ipq_src.s_addr &&
+ ip->ip_dst.s_addr == q->ipq_dst.s_addr &&
+ ip->ip_p == q->ipq_p)
goto found;
}
- fp = NULL;
+ q = NULL;
found:
/*
@@ -181,12 +181,12 @@ void ip_input(struct mbuf *m)
* attempt reassembly; if it succeeds, proceed.
*/
if (ip->ip_tos & 1 || ip->ip_off) {
- ip = ip_reass(slirp, ip, fp);
+ ip = ip_reass(slirp, ip, q);
if (ip == NULL)
return;
m = dtom(slirp, ip);
- } else if (fp)
- ip_freef(slirp, fp);
+ } else if (q)
+ ip_freef(slirp, q);
} else
ip->ip_len -= hlen;
@@ -212,24 +212,25 @@ bad:
m_free(m);
}
-#define iptofrag(P) ((struct ipasfrag *)(((char *)(P)) - sizeof(struct qlink)))
-#define fragtoip(P) ((struct ip *)(((char *)(P)) + sizeof(struct qlink)))
+#define iptoas(P) container_of((P), struct ipas, ipf_ip)
+#define astoip(P) (&(P)->ipf_ip)
/*
* Take incoming datagram fragment and try to
* reassemble it into whole datagram. If a chain for
* reassembly of this datagram already exists, then it
- * is given as fp; otherwise have to make a chain.
+ * is given as q; otherwise have to make a chain.
*/
-static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
+static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *q)
{
register struct mbuf *m = dtom(slirp, ip);
- register struct ipasfrag *q;
+ struct ipas *first = container_of(q, struct ipas, ipq);
+ register struct ipas *cursor;
int hlen = ip->ip_hl << 2;
int i, next;
DEBUG_CALL("ip_reass");
DEBUG_ARG("ip = %p", ip);
- DEBUG_ARG("fp = %p", fp);
+ DEBUG_ARG("q = %p", q);
DEBUG_ARG("m = %p", m);
/*
@@ -243,30 +244,30 @@ static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
/*
* If first fragment to arrive, create a reassembly queue.
*/
- if (fp == NULL) {
+ if (q == NULL) {
struct mbuf *t = m_get(slirp);
if (t == NULL) {
goto dropfrag;
}
- fp = mtod(t, struct ipq *);
- insque(&fp->ip_link, &slirp->ipq.ip_link);
- fp->ipq_ttl = IPFRAGTTL;
- fp->ipq_p = ip->ip_p;
- fp->ipq_id = ip->ip_id;
- fp->frag_link.next = fp->frag_link.prev = &fp->frag_link;
- fp->ipq_src = ip->ip_src;
- fp->ipq_dst = ip->ip_dst;
- q = (struct ipasfrag *)fp;
+ first = mtod(t, struct ipas *);
+ q = &first->ipq;
+ slirp_insque(&q->ip_link, &slirp->ipq.ip_link);
+ q->ipq_ttl = IPFRAGTTL;
+ q->ipq_p = ip->ip_p;
+ q->ipq_id = ip->ip_id;
+ first->link.next = first->link.prev = first;
+ q->ipq_src = ip->ip_src;
+ q->ipq_dst = ip->ip_dst;
+ cursor = first;
goto insert;
}
/*
* Find a segment which begins after this one does.
*/
- for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
- q = q->ipf_next)
- if (q->ipf_off > ip->ip_off)
+ for (cursor = first->link.next; cursor != first; cursor = cursor->link.next)
+ if (cursor->ipf_off > ip->ip_off)
break;
/*
@@ -274,8 +275,8 @@ static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
* our data already. If so, drop the data from the incoming
* segment. If it provides all of our data, drop us.
*/
- if (q->ipf_prev != &fp->frag_link) {
- struct ipasfrag *pq = q->ipf_prev;
+ if (cursor->link.prev != first) {
+ struct ipas *pq = cursor->link.prev;
i = pq->ipf_off + pq->ipf_len - ip->ip_off;
if (i > 0) {
if (i >= ip->ip_len)
@@ -290,18 +291,17 @@ static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
* While we overlap succeeding segments trim them or,
* if they are completely covered, dequeue them.
*/
- while (q != (struct ipasfrag *)&fp->frag_link &&
- ip->ip_off + ip->ip_len > q->ipf_off) {
- struct ipasfrag *prev;
- i = (ip->ip_off + ip->ip_len) - q->ipf_off;
- if (i < q->ipf_len) {
- q->ipf_len -= i;
- q->ipf_off += i;
- m_adj(dtom(slirp, q), i);
+ while (cursor != first && ip->ip_off + ip->ip_len > cursor->ipf_off) {
+ struct ipas *prev;
+ i = (ip->ip_off + ip->ip_len) - cursor->ipf_off;
+ if (i < cursor->ipf_len) {
+ cursor->ipf_len -= i;
+ cursor->ipf_off += i;
+ m_adj(dtom(slirp, cursor), i);
break;
}
- prev = q;
- q = q->ipf_next;
+ prev = cursor;
+ cursor = cursor->link.next;
ip_deq(prev);
m_free(dtom(slirp, prev));
}
@@ -311,28 +311,27 @@ insert:
* Stick new segment in its place;
* check for complete reassembly.
*/
- ip_enq(iptofrag(ip), q->ipf_prev);
+ ip_enq(iptoas(ip), cursor->link.prev);
next = 0;
- for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
- q = q->ipf_next) {
- if (q->ipf_off != next)
+ for (cursor = first->link.next; cursor != first; cursor = cursor->link.next) {
+ if (cursor->ipf_off != next)
return NULL;
- next += q->ipf_len;
+ next += cursor->ipf_len;
}
- if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1)
+ if (((struct ipas *)(cursor->link.prev))->ipf_tos & 1)
return NULL;
/*
* Reassembly is complete; concatenate fragments.
*/
- q = fp->frag_link.next;
- m = dtom(slirp, q);
- int delta = (char *)q - (m->m_flags & M_EXT ? m->m_ext : m->m_dat);
-
- q = (struct ipasfrag *)q->ipf_next;
- while (q != (struct ipasfrag *)&fp->frag_link) {
- struct mbuf *t = dtom(slirp, q);
- q = (struct ipasfrag *)q->ipf_next;
+ cursor = first->link.next;
+ m = dtom(slirp, cursor);
+ int delta = (char *)cursor - (m->m_flags & M_EXT ? m->m_ext : m->m_dat);
+
+ cursor = cursor->link.next;
+ while (cursor != first) {
+ struct mbuf *t = dtom(slirp, cursor);
+ cursor = cursor->link.next;
m_cat(m, t);
}
@@ -342,25 +341,25 @@ insert:
* dequeue and discard fragment reassembly header.
* Make header visible.
*/
- q = fp->frag_link.next;
+ cursor = first->link.next;
/*
* If the fragments concatenated to an mbuf that's bigger than the total
* size of the fragment and the mbuf was not already using an m_ext buffer,
- * then an m_ext buffer was alloced. But fp->ipq_next points to the old
+ * then an m_ext buffer was alloced. But q->ipq_next points to the old
* buffer (in the mbuf), so we must point ip into the new buffer.
*/
if (m->m_flags & M_EXT) {
- q = (struct ipasfrag *)(m->m_ext + delta);
+ cursor = (struct ipas *)(m->m_ext + delta);
}
- ip = fragtoip(q);
+ ip = astoip(cursor);
ip->ip_len = next;
ip->ip_tos &= ~1;
- ip->ip_src = fp->ipq_src;
- ip->ip_dst = fp->ipq_dst;
- remque(&fp->ip_link);
- (void)m_free(dtom(slirp, fp));
+ ip->ip_src = q->ipq_src;
+ ip->ip_dst = q->ipq_dst;
+ slirp_remque(&q->ip_link);
+ m_free(dtom(slirp, q));
m->m_len += (ip->ip_hl << 2);
m->m_data -= (ip->ip_hl << 2);
@@ -375,41 +374,42 @@ dropfrag:
* Free a fragment reassembly header and all
* associated datagrams.
*/
-static void ip_freef(Slirp *slirp, struct ipq *fp)
+static void ip_freef(Slirp *slirp, struct ipq *q)
{
- register struct ipasfrag *q, *p;
+ struct ipas *first = container_of(q, struct ipas, ipq);
+ register struct ipas *cursor, *next;
- for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
- q = p) {
- p = q->ipf_next;
- ip_deq(q);
- m_free(dtom(slirp, q));
+ for (cursor = first->link.next; cursor != first; cursor = next) {
+ next = cursor->link.next;
+ ip_deq(cursor);
+ m_free(dtom(slirp, cursor));
}
- remque(&fp->ip_link);
- (void)m_free(dtom(slirp, fp));
+
+ slirp_remque(&q->ip_link);
+ m_free(dtom(slirp, q));
}
/*
* Put an ip fragment on a reassembly chain.
* Like insque, but pointers in middle of structure.
*/
-static void ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
+static void ip_enq(register struct ipas *p, register struct ipas *prev)
{
DEBUG_CALL("ip_enq");
DEBUG_ARG("prev = %p", prev);
- p->ipf_prev = prev;
- p->ipf_next = prev->ipf_next;
- ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p;
- prev->ipf_next = p;
+ p->link.prev = prev;
+ p->link.next = prev->link.next;
+ ((struct ipas *)(prev->link.next))->link.prev = p;
+ prev->link.next = p;
}
/*
* To ip_enq as remque is to insque.
*/
-static void ip_deq(register struct ipasfrag *p)
+static void ip_deq(register struct ipas *p)
{
- ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
- ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
+ ((struct ipas *)(p->link.prev))->link.next = p->link.next;
+ ((struct ipas *)(p->link.next))->link.prev = p->link.prev;
}
/*
@@ -429,10 +429,10 @@ void ip_slowtimo(Slirp *slirp)
return;
while (l != &slirp->ipq.ip_link) {
- struct ipq *fp = container_of(l, struct ipq, ip_link);
+ struct ipq *q = container_of(l, struct ipq, ip_link);
l = l->next;
- if (--fp->ipq_ttl == 0) {
- ip_freef(slirp, fp);
+ if (--q->ipq_ttl == 0) {
+ ip_freef(slirp, q);
}
}
}
--
2.44.0

View File

@ -1,173 +0,0 @@
From 849c972aa16a85c860f67d7e7f1fbe58e45187d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Wed, 9 Feb 2022 22:15:08 +0400
Subject: [PATCH 2/2] Replace inet_ntoa() with safer inet_ntop()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
inet_ntoa() returns a static pointer which is subject to safety issues.
Use the recommended alternative.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
src/arp_table.c | 8 ++++++--
src/ip_icmp.c | 10 ++++++----
src/misc.c | 22 +++++++++++++---------
src/socket.c | 5 +++--
src/udp.c | 5 +++--
5 files changed, 31 insertions(+), 19 deletions(-)
diff --git a/src/arp_table.c b/src/arp_table.c
index ba8c8a4eee88..3cf2ecc238bc 100644
--- a/src/arp_table.c
+++ b/src/arp_table.c
@@ -35,9 +35,11 @@ void arp_table_add(Slirp *slirp, uint32_t ip_addr,
ArpTable *arptbl = &slirp->arp_table;
int i;
char ethaddr_str[ETH_ADDRSTRLEN];
+ char addr[INET_ADDRSTRLEN];
DEBUG_CALL("arp_table_add");
- DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){ .s_addr = ip_addr }));
+ DEBUG_ARG("ip = %s", inet_ntop(AF_INET, &(struct in_addr){ .s_addr = ip_addr },
+ addr, sizeof(addr)));
DEBUG_ARG("hw addr = %s", slirp_ether_ntoa(ethaddr, ethaddr_str,
sizeof(ethaddr_str)));
@@ -69,9 +71,11 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
ArpTable *arptbl = &slirp->arp_table;
int i;
char ethaddr_str[ETH_ADDRSTRLEN];
+ char addr[INET_ADDRSTRLEN];
DEBUG_CALL("arp_table_search");
- DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){ .s_addr = ip_addr }));
+ DEBUG_ARG("ip = %s", inet_ntop(AF_INET, &(struct in_addr){ .s_addr = ip_addr },
+ addr, sizeof(addr)));
/* If broadcast address */
if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
diff --git a/src/ip_icmp.c b/src/ip_icmp.c
index f4d686b0222d..26e44a3fd49c 100644
--- a/src/ip_icmp.c
+++ b/src/ip_icmp.c
@@ -291,10 +291,12 @@ void icmp_forward_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsi
goto end_error;
ip = mtod(msrc, struct ip *);
if (slirp_debug & DBG_MISC) {
- char bufa[20], bufb[20];
- slirp_pstrcpy(bufa, sizeof(bufa), inet_ntoa(ip->ip_src));
- slirp_pstrcpy(bufb, sizeof(bufb), inet_ntoa(ip->ip_dst));
- DEBUG_MISC(" %.16s to %.16s", bufa, bufb);
+ char addr_src[INET_ADDRSTRLEN];
+ char addr_dst[INET_ADDRSTRLEN];
+
+ inet_ntop(AF_INET, &ip->ip_src, addr_src, sizeof(addr_src));
+ inet_ntop(AF_INET, &ip->ip_dst, addr_dst, sizeof(addr_dst));
+ DEBUG_MISC(" %.16s to %.16s", addr_src, addr_dst);
}
if (ip->ip_off & IP_OFFMASK)
goto end_error; /* Only reply to fragment 0 */
diff --git a/src/misc.c b/src/misc.c
index e6bc0a207d0b..1306f68eb539 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -293,6 +293,7 @@ char *slirp_connection_info(Slirp *slirp)
uint16_t dst_port;
struct socket *so;
const char *state;
+ char addr[INET_ADDRSTRLEN];
char buf[20];
g_string_append_printf(str,
@@ -322,10 +323,11 @@ char *slirp_connection_info(Slirp *slirp)
}
slirp_fmt0(buf, sizeof(buf), " TCP[%s]", state);
g_string_append_printf(str, "%-19s %3d %15s %5d ", buf, so->s,
- src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) :
- "*",
+ src.sin_addr.s_addr ?
+ inet_ntop(AF_INET, &src.sin_addr, addr, sizeof(addr)) : "*",
ntohs(src.sin_port));
- g_string_append_printf(str, "%15s %5d %5d %5d\n", inet_ntoa(dst_addr),
+ g_string_append_printf(str, "%15s %5d %5d %5d\n",
+ inet_ntop(AF_INET, &dst_addr, addr, sizeof(addr)),
ntohs(dst_port), so->so_rcv.sb_cc,
so->so_snd.sb_cc);
}
@@ -346,10 +348,11 @@ char *slirp_connection_info(Slirp *slirp)
dst_port = so->so_fport;
}
g_string_append_printf(str, "%-19s %3d %15s %5d ", buf, so->s,
- src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) :
- "*",
+ src.sin_addr.s_addr ?
+ inet_ntop(AF_INET, &src.sin_addr, addr, sizeof(addr)) : "*",
ntohs(src.sin_port));
- g_string_append_printf(str, "%15s %5d %5d %5d\n", inet_ntoa(dst_addr),
+ g_string_append_printf(str, "%15s %5d %5d %5d\n",
+ inet_ntop(AF_INET, &dst_addr, addr, sizeof(addr)),
ntohs(dst_port), so->so_rcv.sb_cc,
so->so_snd.sb_cc);
}
@@ -360,9 +363,10 @@ char *slirp_connection_info(Slirp *slirp)
src.sin_addr = so->so_laddr;
dst_addr = so->so_faddr;
g_string_append_printf(str, "%-19s %3d %15s - ", buf, so->s,
- src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) :
- "*");
- g_string_append_printf(str, "%15s - %5d %5d\n", inet_ntoa(dst_addr),
+ src.sin_addr.s_addr ?
+ inet_ntop(AF_INET, &src.sin_addr, addr, sizeof(addr)) : "*");
+ g_string_append_printf(str, "%15s - %5d %5d\n",
+ inet_ntop(AF_INET, &dst_addr, addr, sizeof(addr)),
so->so_rcv.sb_cc, so->so_snd.sb_cc);
}
diff --git a/src/socket.c b/src/socket.c
index c0b02ad131f3..6607e319ad6c 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -743,13 +743,14 @@ struct socket *tcp_listen(Slirp *slirp, uint32_t haddr, unsigned hport,
struct sockaddr_in addr;
struct socket *so;
int s, opt = 1;
+ char inet_addr[INET_ADDRSTRLEN];
socklen_t addrlen = sizeof(addr);
memset(&addr, 0, addrlen);
DEBUG_CALL("tcp_listen");
- DEBUG_ARG("haddr = %s", inet_ntoa((struct in_addr){ .s_addr = haddr }));
+ DEBUG_ARG("haddr = %s", inet_ntop(AF_INET, &(struct in_addr){ .s_addr = haddr }, inet_addr, sizeof(inet_addr)));
DEBUG_ARG("hport = %d", ntohs(hport));
- DEBUG_ARG("laddr = %s", inet_ntoa((struct in_addr){ .s_addr = laddr }));
+ DEBUG_ARG("laddr = %s", inet_ntop(AF_INET, &(struct in_addr){ .s_addr = laddr }, inet_addr, sizeof(inet_addr)));
DEBUG_ARG("lport = %d", ntohs(lport));
DEBUG_ARG("flags = %x", flags);
diff --git a/src/udp.c b/src/udp.c
index e4578aa94ed5..0547cd6fc5c3 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -248,14 +248,15 @@ bad:
int udp_output(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr,
struct sockaddr_in *daddr, int iptos)
{
+ char addr[INET_ADDRSTRLEN];
register struct udpiphdr *ui;
int error = 0;
DEBUG_CALL("udp_output");
DEBUG_ARG("so = %p", so);
DEBUG_ARG("m = %p", m);
- DEBUG_ARG("saddr = %s", inet_ntoa(saddr->sin_addr));
- DEBUG_ARG("daddr = %s", inet_ntoa(daddr->sin_addr));
+ DEBUG_ARG("saddr = %s", inet_ntop(AF_INET, &saddr->sin_addr, addr, sizeof(addr)));
+ DEBUG_ARG("daddr = %s", inet_ntop(AF_INET, &daddr->sin_addr, addr, sizeof(addr)));
/*
* Adjust for header
--
2.34.1.428.gdcc0cd074f0c

View File

@ -1,161 +0,0 @@
From f0d4faae8258385338bc1ec252250454346b7ef7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Fri, 4 Jun 2021 19:25:28 +0400
Subject: [PATCH 2/7] bootp: limit vendor-specific area to input packet memory
buffer
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
sizeof(bootp_t) currently holds DHCP_OPT_LEN. Remove this optional field
from the structure, to help with the following patch checking for
minimal header size. Modify the bootp_reply() function to take the
buffer boundaries and avoiding potential buffer overflow.
Related to CVE-2021-3592.
https://gitlab.freedesktop.org/slirp/libslirp/-/issues/44
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
(cherry picked from commit f13cad45b25d92760bb0ad67bec0300a4d7d5275)
---
src/bootp.c | 26 +++++++++++++++-----------
src/bootp.h | 2 +-
src/mbuf.c | 5 +++++
src/mbuf.h | 1 +
4 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/src/bootp.c b/src/bootp.c
index 46e9681..e0db8d1 100644
--- a/src/bootp.c
+++ b/src/bootp.c
@@ -92,21 +92,22 @@ found:
return bc;
}
-static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
+static void dhcp_decode(const struct bootp_t *bp,
+ const uint8_t *bp_end,
+ int *pmsg_type,
struct in_addr *preq_addr)
{
- const uint8_t *p, *p_end;
+ const uint8_t *p;
int len, tag;
*pmsg_type = 0;
preq_addr->s_addr = htonl(0L);
p = bp->bp_vend;
- p_end = p + DHCP_OPT_LEN;
if (memcmp(p, rfc1533_cookie, 4) != 0)
return;
p += 4;
- while (p < p_end) {
+ while (p < bp_end) {
tag = p[0];
if (tag == RFC1533_PAD) {
p++;
@@ -114,10 +115,10 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
break;
} else {
p++;
- if (p >= p_end)
+ if (p >= bp_end)
break;
len = *p++;
- if (p + len > p_end) {
+ if (p + len > bp_end) {
break;
}
DPRINTF("dhcp: tag=%d len=%d\n", tag, len);
@@ -144,7 +145,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
}
}
-static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
+static void bootp_reply(Slirp *slirp,
+ const struct bootp_t *bp,
+ const uint8_t *bp_end)
{
BOOTPClient *bc = NULL;
struct mbuf *m;
@@ -157,7 +160,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
uint8_t client_ethaddr[ETH_ALEN];
/* extract exact DHCP msg type */
- dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
+ dhcp_decode(bp, bp_end, &dhcp_msg_type, &preq_addr);
DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
if (preq_addr.s_addr != htonl(0L))
DPRINTF(" req_addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr));
@@ -179,9 +182,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
return;
}
m->m_data += IF_MAXLINKHDR;
+ m_inc(m, sizeof(struct bootp_t) + DHCP_OPT_LEN);
rbp = (struct bootp_t *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
- memset(rbp, 0, sizeof(struct bootp_t));
+ memset(rbp, 0, sizeof(struct bootp_t) + DHCP_OPT_LEN);
if (dhcp_msg_type == DHCPDISCOVER) {
if (preq_addr.s_addr != htonl(0L)) {
@@ -235,7 +239,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */
q = rbp->bp_vend;
- end = (uint8_t *)&rbp[1];
+ end = rbp->bp_vend + DHCP_OPT_LEN;
memcpy(q, rfc1533_cookie, 4);
q += 4;
@@ -364,6 +368,6 @@ void bootp_input(struct mbuf *m)
struct bootp_t *bp = mtod(m, struct bootp_t *);
if (bp->bp_op == BOOTP_REQUEST) {
- bootp_reply(m->slirp, bp);
+ bootp_reply(m->slirp, bp, m_end(m));
}
}
diff --git a/src/bootp.h b/src/bootp.h
index a57fa51..31ce5fd 100644
--- a/src/bootp.h
+++ b/src/bootp.h
@@ -114,7 +114,7 @@ struct bootp_t {
uint8_t bp_hwaddr[16];
uint8_t bp_sname[64];
char bp_file[128];
- uint8_t bp_vend[DHCP_OPT_LEN];
+ uint8_t bp_vend[];
};
typedef struct {
diff --git a/src/mbuf.c b/src/mbuf.c
index cb2e971..0c1a530 100644
--- a/src/mbuf.c
+++ b/src/mbuf.c
@@ -233,3 +233,8 @@ void *mtod_check(struct mbuf *m, size_t len)
return NULL;
}
+
+void *m_end(struct mbuf *m)
+{
+ return m->m_data + m->m_len;
+}
diff --git a/src/mbuf.h b/src/mbuf.h
index 2015e32..a9752a3 100644
--- a/src/mbuf.h
+++ b/src/mbuf.h
@@ -119,6 +119,7 @@ void m_adj(struct mbuf *, int);
int m_copy(struct mbuf *, struct mbuf *, int, int);
struct mbuf *dtom(Slirp *, void *);
void *mtod_check(struct mbuf *, size_t len);
+void *m_end(struct mbuf *);
static inline void ifs_init(struct mbuf *ifm)
{
--
2.29.0

View File

@ -1,36 +0,0 @@
From 0f017f39a390d8fa4ae817f45fbf71a0c8332860 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Fri, 4 Jun 2021 16:15:14 +0400
Subject: [PATCH 3/7] bootp: check bootp_input buffer size
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes: CVE-2021-3592
Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/44
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
(cherry picked from commit 2eca0838eee1da96204545e22cdaed860d9d7c6c)
---
src/bootp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/bootp.c b/src/bootp.c
index e0db8d1..cafa1eb 100644
--- a/src/bootp.c
+++ b/src/bootp.c
@@ -365,9 +365,9 @@ static void bootp_reply(Slirp *slirp,
void bootp_input(struct mbuf *m)
{
- struct bootp_t *bp = mtod(m, struct bootp_t *);
+ struct bootp_t *bp = mtod_check(m, sizeof(struct bootp_t));
- if (bp->bp_op == BOOTP_REQUEST) {
+ if (bp && bp->bp_op == BOOTP_REQUEST) {
bootp_reply(m->slirp, bp, m_end(m));
}
}
--
2.29.0

View File

@ -1,36 +0,0 @@
From 30feadb676a0792036a0f64309235c5767e2ee76 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Fri, 4 Jun 2021 16:32:55 +0400
Subject: [PATCH 4/7] upd6: check udp6_input buffer size
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes: CVE-2021-3593
Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/45
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
(cherry picked from commit de71c15de66ba9350bf62c45b05f8fbff166517b)
---
src/udp6.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/udp6.c b/src/udp6.c
index fdd8089..236b962 100644
--- a/src/udp6.c
+++ b/src/udp6.c
@@ -29,7 +29,10 @@ void udp6_input(struct mbuf *m)
ip = mtod(m, struct ip6 *);
m->m_len -= iphlen;
m->m_data += iphlen;
- uh = mtod(m, struct udphdr *);
+ uh = mtod_check(m, sizeof(struct udphdr));
+ if (uh == NULL) {
+ goto bad;
+ }
m->m_len += iphlen;
m->m_data -= iphlen;
--
2.29.0

View File

@ -1,37 +0,0 @@
From 31aaf902aa6ba31ab8f41543b2d4da8c01f3b861 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Fri, 4 Jun 2021 16:34:30 +0400
Subject: [PATCH 5/7] tftp: check tftp_input buffer size
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes: CVE-2021-3595
Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/46
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
(cherry picked from commit 3f17948137155f025f7809fdc38576d5d2451c3d)
---
src/tftp.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/tftp.c b/src/tftp.c
index c6950ee..e06911d 100644
--- a/src/tftp.c
+++ b/src/tftp.c
@@ -446,7 +446,11 @@ static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas,
void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m)
{
- struct tftp_t *tp = (struct tftp_t *)m->m_data;
+ struct tftp_t *tp = mtod_check(m, offsetof(struct tftp_t, x.tp_buf));
+
+ if (tp == NULL) {
+ return;
+ }
switch (ntohs(tp->tp_op)) {
case TFTP_RRQ:
--
2.29.0

View File

@ -1,249 +0,0 @@
From c8665ebbdadb72f7c2cb74b9704f68704c13653b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Fri, 4 Jun 2021 20:01:20 +0400
Subject: [PATCH 6/7] tftp: introduce a header structure
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Instead of using a composed structure and potentially reading past the
incoming buffer, use a different structure for the header.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
(cherry picked from commit 990163cf3ac86b7875559f49602c4d76f46f6f30)
---
src/tftp.c | 60 ++++++++++++++++++++++++++++--------------------------
src/tftp.h | 6 +++++-
2 files changed, 36 insertions(+), 30 deletions(-)
diff --git a/src/tftp.c b/src/tftp.c
index e06911d..a19c889 100644
--- a/src/tftp.c
+++ b/src/tftp.c
@@ -50,7 +50,7 @@ static void tftp_session_terminate(struct tftp_session *spt)
}
static int tftp_session_allocate(Slirp *slirp, struct sockaddr_storage *srcsas,
- struct tftp_t *tp)
+ struct tftphdr *hdr)
{
struct tftp_session *spt;
int k;
@@ -75,7 +75,7 @@ found:
memcpy(&spt->client_addr, srcsas, sockaddr_size(srcsas));
spt->fd = -1;
spt->block_size = 512;
- spt->client_port = tp->udp.uh_sport;
+ spt->client_port = hdr->udp.uh_sport;
spt->slirp = slirp;
tftp_session_update(spt);
@@ -84,7 +84,7 @@ found:
}
static int tftp_session_find(Slirp *slirp, struct sockaddr_storage *srcsas,
- struct tftp_t *tp)
+ struct tftphdr *hdr)
{
struct tftp_session *spt;
int k;
@@ -94,7 +94,7 @@ static int tftp_session_find(Slirp *slirp, struct sockaddr_storage *srcsas,
if (tftp_session_in_use(spt)) {
if (sockaddr_equal(&spt->client_addr, srcsas)) {
- if (spt->client_port == tp->udp.uh_sport) {
+ if (spt->client_port == hdr->udp.uh_sport) {
return k;
}
}
@@ -148,13 +148,13 @@ static struct tftp_t *tftp_prep_mbuf_data(struct tftp_session *spt,
}
static void tftp_udp_output(struct tftp_session *spt, struct mbuf *m,
- struct tftp_t *recv_tp)
+ struct tftphdr *hdr)
{
if (spt->client_addr.ss_family == AF_INET6) {
struct sockaddr_in6 sa6, da6;
sa6.sin6_addr = spt->slirp->vhost_addr6;
- sa6.sin6_port = recv_tp->udp.uh_dport;
+ sa6.sin6_port = hdr->udp.uh_dport;
da6.sin6_addr = ((struct sockaddr_in6 *)&spt->client_addr)->sin6_addr;
da6.sin6_port = spt->client_port;
@@ -163,7 +163,7 @@ static void tftp_udp_output(struct tftp_session *spt, struct mbuf *m,
struct sockaddr_in sa4, da4;
sa4.sin_addr = spt->slirp->vhost_addr;
- sa4.sin_port = recv_tp->udp.uh_dport;
+ sa4.sin_port = hdr->udp.uh_dport;
da4.sin_addr = ((struct sockaddr_in *)&spt->client_addr)->sin_addr;
da4.sin_port = spt->client_port;
@@ -185,14 +185,14 @@ static int tftp_send_oack(struct tftp_session *spt, const char *keys[],
tp = tftp_prep_mbuf_data(spt, m);
- tp->tp_op = htons(TFTP_OACK);
+ tp->hdr.tp_op = htons(TFTP_OACK);
for (i = 0; i < nb; i++) {
n += slirp_fmt0(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s", keys[i]);
n += slirp_fmt0(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%u", values[i]);
}
- m->m_len = G_SIZEOF_MEMBER(struct tftp_t, tp_op) + n;
- tftp_udp_output(spt, m, recv_tp);
+ m->m_len = G_SIZEOF_MEMBER(struct tftp_t, hdr.tp_op) + n;
+ tftp_udp_output(spt, m, &recv_tp->hdr);
return 0;
}
@@ -213,21 +213,21 @@ static void tftp_send_error(struct tftp_session *spt, uint16_t errorcode,
tp = tftp_prep_mbuf_data(spt, m);
- tp->tp_op = htons(TFTP_ERROR);
+ tp->hdr.tp_op = htons(TFTP_ERROR);
tp->x.tp_error.tp_error_code = htons(errorcode);
slirp_pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg),
msg);
m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX + 2) + 3 +
strlen(msg) - sizeof(struct udphdr);
- tftp_udp_output(spt, m, recv_tp);
+ tftp_udp_output(spt, m, &recv_tp->hdr);
out:
tftp_session_terminate(spt);
}
static void tftp_send_next_block(struct tftp_session *spt,
- struct tftp_t *recv_tp)
+ struct tftphdr *hdr)
{
struct mbuf *m;
struct tftp_t *tp;
@@ -241,7 +241,7 @@ static void tftp_send_next_block(struct tftp_session *spt,
tp = tftp_prep_mbuf_data(spt, m);
- tp->tp_op = htons(TFTP_DATA);
+ tp->hdr.tp_op = htons(TFTP_DATA);
tp->x.tp_data.tp_block_nr = htons((spt->block_nr + 1) & 0xffff);
nobytes = tftp_read_data(spt, spt->block_nr, tp->x.tp_data.tp_buf,
@@ -259,7 +259,7 @@ static void tftp_send_next_block(struct tftp_session *spt,
m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX - nobytes) -
sizeof(struct udphdr);
- tftp_udp_output(spt, m, recv_tp);
+ tftp_udp_output(spt, m, hdr);
if (nobytes == spt->block_size) {
tftp_session_update(spt);
@@ -282,12 +282,12 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas,
int nb_options = 0;
/* check if a session already exists and if so terminate it */
- s = tftp_session_find(slirp, srcsas, tp);
+ s = tftp_session_find(slirp, srcsas, &tp->hdr);
if (s >= 0) {
tftp_session_terminate(&slirp->tftp_sessions[s]);
}
- s = tftp_session_allocate(slirp, srcsas, tp);
+ s = tftp_session_allocate(slirp, srcsas, &tp->hdr);
if (s < 0) {
return;
@@ -413,29 +413,29 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas,
}
spt->block_nr = 0;
- tftp_send_next_block(spt, tp);
+ tftp_send_next_block(spt, &tp->hdr);
}
static void tftp_handle_ack(Slirp *slirp, struct sockaddr_storage *srcsas,
- struct tftp_t *tp, int pktlen)
+ struct tftphdr *hdr)
{
int s;
- s = tftp_session_find(slirp, srcsas, tp);
+ s = tftp_session_find(slirp, srcsas, hdr);
if (s < 0) {
return;
}
- tftp_send_next_block(&slirp->tftp_sessions[s], tp);
+ tftp_send_next_block(&slirp->tftp_sessions[s], hdr);
}
static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas,
- struct tftp_t *tp, int pktlen)
+ struct tftphdr *hdr)
{
int s;
- s = tftp_session_find(slirp, srcsas, tp);
+ s = tftp_session_find(slirp, srcsas, hdr);
if (s < 0) {
return;
@@ -446,23 +446,25 @@ static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas,
void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m)
{
- struct tftp_t *tp = mtod_check(m, offsetof(struct tftp_t, x.tp_buf));
+ struct tftphdr *hdr = mtod_check(m, sizeof(struct tftphdr));
- if (tp == NULL) {
+ if (hdr == NULL) {
return;
}
- switch (ntohs(tp->tp_op)) {
+ switch (ntohs(hdr->tp_op)) {
case TFTP_RRQ:
- tftp_handle_rrq(m->slirp, srcsas, tp, m->m_len);
+ tftp_handle_rrq(m->slirp, srcsas,
+ mtod(m, struct tftp_t *),
+ m->m_len);
break;
case TFTP_ACK:
- tftp_handle_ack(m->slirp, srcsas, tp, m->m_len);
+ tftp_handle_ack(m->slirp, srcsas, hdr);
break;
case TFTP_ERROR:
- tftp_handle_error(m->slirp, srcsas, tp, m->m_len);
+ tftp_handle_error(m->slirp, srcsas, hdr);
break;
}
}
diff --git a/src/tftp.h b/src/tftp.h
index 6d75478..cafab03 100644
--- a/src/tftp.h
+++ b/src/tftp.h
@@ -20,9 +20,13 @@
#define TFTP_FILENAME_MAX 512
#define TFTP_BLOCKSIZE_MAX 1428
-struct tftp_t {
+struct tftphdr {
struct udphdr udp;
uint16_t tp_op;
+} SLIRP_PACKED;
+
+struct tftp_t {
+ struct tftphdr hdr;
union {
struct {
uint16_t tp_block_nr;
--
2.29.0

View File

@ -1,36 +0,0 @@
From ca41f7eaa58d3f63a3df58d812b3cec32343ab6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Fri, 4 Jun 2021 16:40:23 +0400
Subject: [PATCH 7/7] udp: check upd_input buffer size
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes: CVE-2021-3594
Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/47
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
(cherry picked from commit 74572be49247c8c5feae7c6e0b50c4f569ca9824)
---
src/udp.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/udp.c b/src/udp.c
index 050cee4..e4578aa 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -94,7 +94,10 @@ void udp_input(register struct mbuf *m, int iphlen)
/*
* Get IP and UDP header together in first mbuf.
*/
- ip = mtod(m, struct ip *);
+ ip = mtod_check(m, iphlen + sizeof(struct udphdr));
+ if (ip == NULL) {
+ goto bad;
+ }
uh = (struct udphdr *)((char *)ip + iphlen);
/*
--
2.29.0

View File

@ -1,3 +0,0 @@
# libslirp
The libslirp package

97
SPECS/libslirp.spec Normal file
View File

@ -0,0 +1,97 @@
Name: libslirp
Version: 4.3.1
Release: 1%{?dist}
Summary: A general purpose TCP-IP emulator
# check the SPDX tags in source files for details
License: BSD and MIT
URL: https://gitlab.freedesktop.org/slirp/%{name}
Source0: https://elmarco.fedorapeople.org/libslirp-%{version}.tar.xz
BuildRequires: git-core
BuildRequires: meson
BuildRequires: gcc
BuildRequires: glib2-devel
%description
A general purpose TCP-IP emulator used by virtual machine hypervisors
to provide virtual networking services.
%package devel
Summary: Development files for %{name}
Requires: %{name}%{?_isa} = %{version}-%{release}
%description devel
The %{name}-devel package contains libraries and header files for
developing applications that use %{name}.
%prep
%autosetup -S git_am
%build
%meson
%meson_build
%install
%meson_install
%files
%license COPYRIGHT
%doc README.md CHANGELOG.md
%{_libdir}/%{name}.so.0*
%files devel
%dir %{_includedir}/slirp/
%{_includedir}/slirp/*
%{_libdir}/%{name}.so
%{_libdir}/pkgconfig/slirp.pc
%changelog
* Thu Jul 30 2020 Jindrich Novy <jnovy@redhat.com> - 4.3.1-1
- update to https://gitlab.freedesktop.org/slirp/libslirp/-/releases/v4.3.1
- Related: #1821193
* Wed Jul 08 2020 Jindrich Novy <jnovy@redhat.com> - 4.3.0-5
- replace patch for CVE-2020-10756 with dedicated upstream one
- Related: #1821193
* Fri Jul 03 2020 Jindrich Novy <jnovy@redhat.com> - 4.3.0-4
- fix "CVE-2020-10756 QEMU: slirp: networking out-of-bounds read information disclosure vulnerability"
- Related: #1821193
* Thu May 28 2020 Jindrich Novy <jnovy@redhat.com> - 4.3.0-3
- fix static analysis issues merged upstream
(https://gitlab.freedesktop.org/slirp/libslirp/-/merge_requests/41)
- Related: #1821193
* Mon May 11 2020 Jindrich Novy <jnovy@redhat.com> - 4.3.0-2
- initial libslirp build for container-tools 8.3.0 module
- Resolves: #1821193
* Thu Apr 23 2020 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.3.0-1
- New v4.3.0 release
* Mon Apr 20 2020 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.2.0-2
- CVE-2020-1983 fix
* Tue Mar 17 2020 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.2.0-1
- New v4.2.0 release
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 4.1.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Tue Dec 03 2019 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.1.0-1
- New v4.1.0 release
* Fri Aug 2 2019 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.0.0-3
- Fix CVE-2019-14378, rhbz#1735654
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 4.0.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Wed May 22 2019 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.0.0-1
- Initial package, rhbz#1712980

View File

@ -1,6 +0,0 @@
# recipients: jnovy, lsm5, santiago
--- !Policy
product_versions:
- rhel-9
decision_context: osci_compose_gate
rules: []

View File

@ -1,129 +0,0 @@
Name: libslirp
Version: 4.4.0
Release: 8%{?dist}
Summary: A general purpose TCP-IP emulator
# check the SPDX tags in source files for details
License: BSD and MIT
URL: https://gitlab.freedesktop.org/slirp/%{name}
Source0: %{url}/-/archive/v%{version}/%{name}-%{version}.tar.xz
Patch0001: 0001-Add-mtod_check.patch
Patch0002: 0002-bootp-limit-vendor-specific-area-to-input-packet-mem.patch
Patch0003: 0003-bootp-check-bootp_input-buffer-size.patch
Patch0004: 0004-upd6-check-udp6_input-buffer-size.patch
Patch0005: 0005-tftp-check-tftp_input-buffer-size.patch
Patch0006: 0006-tftp-introduce-a-header-structure.patch
Patch0007: 0007-udp-check-upd_input-buffer-size.patch
Patch0008: 0001-Fix-DHCP-broken-in-libslirp-v4.6.0.patch
Patch0009: 0001-New-utility-slirp_ether_ntoa.patch
Patch0010: 0002-Replace-inet_ntoa-with-safer-inet_ntop.patch
Patch0011: 0001-ip-Enforce-strict-aliasing.patch
BuildRequires: git-core
BuildRequires: meson
BuildRequires: gcc
BuildRequires: glib2-devel
%description
A general purpose TCP-IP emulator used by virtual machine hypervisors
to provide virtual networking services.
%package devel
Summary: Development files for %{name}
Requires: %{name}%{?_isa} = %{version}-%{release}
%description devel
The %{name}-devel package contains libraries and header files for
developing applications that use %{name}.
%prep
%autosetup -S git_am
%build
%meson
%meson_build
%install
%meson_install
%files
%license COPYRIGHT
%doc README.md CHANGELOG.md
%{_libdir}/%{name}.so.0*
%files devel
%dir %{_includedir}/slirp/
%{_includedir}/slirp/*
%{_libdir}/%{name}.so
%{_libdir}/pkgconfig/slirp.pc
%changelog
* Mon Jun 03 2024 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.4.0-8
- Backport upstream commit b09dbd9557 ("ip: Enforce strict aliasing")
Fixes JIRA RHEL-27868
* Fri Feb 11 2022 Jindrich Novy <jnovy@redhat.com> - 4.4.0-7
- fix also socket.c, thanks to Marc-André Lureau
- Related: #2000051
* Fri Feb 11 2022 Jindrich Novy <jnovy@redhat.com> - 4.4.0-6
- add patches fixing gating tests from Marc-André Lureau
- Related: #2000051
* Wed Feb 09 2022 Jindrich Novy <jnovy@redhat.com> - 4.4.0-5
- add gating.yaml
- Related: #2000051
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 4.4.0-4
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Fri Jun 18 2021 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.4.0-3
- Fix CVE-2021-3592 CVE-2021-3593 CVE-2021-3594 CVE-2021-3595 out-of-bounds access
Resolves: rhbz#1970826 rhbz#1970839 rhbz#1970857 rhbz#1970847
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 4.4.0-2
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Wed Dec 2 18:19:30 +04 2020 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.4.0-1
- new version
* Fri Nov 27 20:10:28 +04 2020 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.3.1-3
- Fix CVE-2020-29129 CVE-2020-29130 out-of-bounds access while processing ARP/NCSI packets
rhbz#1902232
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 4.3.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Wed Jul 08 2020 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.3.1-1
- New v4.3.1 release
* Thu Apr 23 2020 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.3.0-1
- New v4.3.0 release
* Mon Apr 20 2020 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.2.0-2
- CVE-2020-1983 fix
* Tue Mar 17 2020 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.2.0-1
- New v4.2.0 release
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 4.1.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Tue Dec 03 2019 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.1.0-1
- New v4.1.0 release
* Fri Aug 2 2019 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.0.0-3
- Fix CVE-2019-14378, rhbz#1735654
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 4.0.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Wed May 22 2019 Marc-André Lureau <marcandre.lureau@redhat.com> - 4.0.0-1
- Initial package, rhbz#1712980

View File

@ -1 +0,0 @@
SHA512 (libslirp-4.4.0.tar.xz) = 5b02d1ed505af6cfa1db3b1f3dc785f16e7518ab8c3f9abe02a2dc277a5dce2ba120617c0f27d9be8a8471e087612a7ac184af348bd3f0517f2715bb57517445