Skip to content
Commits on Source (15)
  • Marc-André Lureau's avatar
    21f1d933
  • Jindrich Novy's avatar
    Fix possible infinite loops and use-after-free · 0b83636e
    Jindrich Novy authored
    
    
    Error: USE_AFTER_FREE (CWE-416): [#def1]
    libslirp-4.3.0/src/ip_icmp.c:79: freed_arg: "icmp_detach" frees "slirp->icmp.so_next".
    libslirp-4.3.0/src/ip_icmp.c:79: deref_arg: Calling "icmp_detach" dereferences freed pointer "slirp->icmp.so_next".
       77|   {
       78|       while (slirp->icmp.so_next != &slirp->icmp) {
       79|->         icmp_detach(slirp->icmp.so_next);
       80|       }
       81|   }
    
    Error: USE_AFTER_FREE (CWE-416): [#def27]
    libslirp-4.3.0/src/udp.c:56: freed_arg: "udp_detach" frees "slirp->udb.so_next".
    libslirp-4.3.0/src/udp.c:56: deref_arg: Calling "udp_detach" dereferences freed pointer "slirp->udb.so_next".
       54|   {
       55|       while (slirp->udb.so_next != &slirp->udb) {
       56|->         udp_detach(slirp->udb.so_next);
       57|       }
       58|   }
    
    Signed-off-by: default avatarJindrich Novy <jnovy@redhat.com>
    Reviewed-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
    0b83636e
  • Jindrich Novy's avatar
    Use secure string copy to avoid overflow · 2d79c0b7
    Jindrich Novy authored
    
    
    Error: STRING_OVERFLOW (CWE-120): [#def2]
    libslirp-4.3.0/src/ip_icmp.c:277: fixed_size_dest: You might overrun the 20-character fixed-size string "bufa" by copying the return value of "inet_ntoa" without checking the length.
      275|       if (slirp_debug & DBG_MISC) {
      276|           char bufa[20], bufb[20];
      277|->         strcpy(bufa, inet_ntoa(ip->ip_src));
      278|           strcpy(bufb, inet_ntoa(ip->ip_dst));
      279|           DEBUG_MISC(" %.16s to %.16s", bufa, bufb);
    
    Error: STRING_OVERFLOW (CWE-120): [#def3]
    libslirp-4.3.0/src/ip_icmp.c:278: fixed_size_dest: You might overrun the 20-character fixed-size string "bufb" by copying the return value of "inet_ntoa" without checking the length.
      276|           char bufa[20], bufb[20];
      277|           strcpy(bufa, inet_ntoa(ip->ip_src));
      278|->         strcpy(bufb, inet_ntoa(ip->ip_dst));
      279|           DEBUG_MISC(" %.16s to %.16s", bufa, bufb);
      280|       }
    
    Signed-off-by: default avatarJindrich Novy <jnovy@redhat.com>
    Reviewed-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
    2d79c0b7
  • Jindrich Novy's avatar
    Be sure to initialize sockaddr structure · b0fc01a6
    Jindrich Novy authored
    
    
    Error: UNINIT (CWE-457): [#def30]
    libslirp-4.3.0/src/udp.c:325: var_decl: Declaring variable "addr" without initializer.
    libslirp-4.3.0/src/udp.c:342: uninit_use_in_call: Using uninitialized value "addr". Field "addr.sin_zero" is uninitialized when calling "bind".
    
    Signed-off-by: default avatarJindrich Novy <jnovy@redhat.com>
    Reviewed-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
    b0fc01a6
  • Jindrich Novy's avatar
    Check lseek() for failure · 961a676e
    Jindrich Novy authored
    
    
    Error: CHECKED_RETURN (CWE-252): [#def26]
    libslirp-4.3.0/src/tftp.c:121: check_return: Calling "lseek(spt->fd, block_nr * spt->block_size, 0)" without checking return value. This library function may fail and return an error code.
      119|
      120|       if (len) {
      121|->         lseek(spt->fd, block_nr * spt->block_size, SEEK_SET);
      122|
      123|           bytes_read = read(spt->fd, buf, len);
    
    Signed-off-by: default avatarJindrich Novy <jnovy@redhat.com>
    Reviewed-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
    961a676e
  • philmd's avatar
    Fix win32 builds by using the SLIRP_PACKED definition · bcaaa53a
    philmd authored and Samuel Thibault's avatar Samuel Thibault committed
    
    
    A packed struct needs different gcc attributes for compilations
    with MinGW compilers because glib-2.0 adds compiler flag
    -mms-bitfields which modifies the packing algorithm.
    
    Attribute gcc_struct reverses the negative effects of -mms-bitfields.
    
    We already have the SLIRP_PACKED definition for that, use it.
    
    Signed-off-by: default avatarPhilippe Mathieu-Daudé <philmd@redhat.com>
    Reviewed-by: default avatarSamuel Thibault <samuel.thibault@ens-lyon.org>
    bcaaa53a
  • philmd's avatar
    Fix constness warnings · 6826a991
    philmd authored and Samuel Thibault's avatar Samuel Thibault committed
    
    
    Fix the following GCC warnings:
    
      src/ncsi.c: In function ‘ncsi_input’:
      src/ncsi.c:139:31: error: cast discards ‘const’ qualifier from pointer target type [-Werror=cast-qual]
        139 |     struct ncsi_pkt_hdr *nh = (struct ncsi_pkt_hdr *)(pkt + ETH_HLEN);
            |                               ^
      src/dnssearch.c: In function ‘translate_dnssearch’:
      src/dnssearch.c:242:33: error: cast discards ‘const’ qualifier from pointer target type [-Werror=cast-qual]
        242 |     num_domains = g_strv_length((GStrv)names);
            |                                 ^
      src/slirp.c: In function ‘arp_input’:
      src/slirp.c:747:31: error: cast discards ‘const’ qualifier from pointer target type [-Werror=cast-qual]
        747 |     struct slirp_arphdr *ah = (struct slirp_arphdr *)(pkt + ETH_HLEN);
            |                               ^
      src/dnssearch.c: In function ‘translate_dnssearch’:
      src/dnssearch.c:242:33: error: cast discards ‘const’ qualifier from pointer target type [-Werror=cast-qual]
        242 |     num_domains = g_strv_length((const GStrv)names);
            |                                 ^
      src/slirp.c: In function ‘arp_input’:
      src/slirp.c:764:48: error: passing argument 3 of ‘arp_table_add’ discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
        764 |             arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
            |                                              ~~^~~~~~~~
      In file included from src/slirp.c:25:
      src/slirp.h:101:60: note: expected ‘uint8_t *’ {aka ‘unsigned char *’} but argument is of type ‘const unsigned char *’
        101 | void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]);
            |                                                    ~~~~~~~~^~~~~~~~~~~~~~~~~
      src/slirp.c:783:48: error: passing argument 3 of ‘arp_table_add’ discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
        783 |             arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
            |                                              ~~^~~~~~~~
      In file included from src/slirp.c:25:
      src/slirp.h:101:60: note: expected ‘uint8_t *’ {aka ‘unsigned char *’} but argument is of type ‘const unsigned char *’
        101 | void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]);
            |                                                    ~~~~~~~~^~~~~~~~~~~~~~~~~
      src/slirp.c:804:44: error: passing argument 3 of ‘arp_table_add’ discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
        804 |         arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
            |                                          ~~^~~~~~~~
      In file included from src/slirp.c:25:
      src/slirp.h:101:60: note: expected ‘uint8_t *’ {aka ‘unsigned char *’} but argument is of type ‘const unsigned char *’
        101 | void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]);
            |                                                    ~~~~~~~~^~~~~~~~~~~~~~~~~
    
    Signed-off-by: default avatarPhilippe Mathieu-Daudé <philmd@redhat.com>
    Reviewed-by: default avatarSamuel Thibault <samuel.thibault@ens-lyon.org>
    6826a991
  • philmd's avatar
    Remove unnecessary break · d877d74b
    philmd authored and Samuel Thibault's avatar Samuel Thibault committed
    
    
    The code is unreachable, so no need to break.
    This silence static analyzer warnings.
    
    Signed-off-by: default avatarPhilippe Mathieu-Daudé <philmd@redhat.com>
    Reviewed-by: default avatarSamuel Thibault <samuel.thibault@ens-lyon.org>
    d877d74b
  • Ralf Haferkamp's avatar
    Drop bogus IPv6 messages · c7ede54c
    Ralf Haferkamp authored
    Drop IPv6 message shorter than what's mentioned in the payload
    length header (+ the size of the IPv6 header). They're invalid an could
    lead to data leakage in icmp6_send_echoreply().
    c7ede54c
  • Ralf Haferkamp's avatar
    Fix MTU check · f1941d6d
    Ralf Haferkamp authored
    The size for Header has to be accounted for as well.
    f1941d6d
  • Samuel Thibault's avatar
    Merge branch 'ip6_payload_len' into 'master' · ebf7bc3a
    Samuel Thibault authored
    Drop bogus IPv6 messages
    
    See merge request !44
    ebf7bc3a
  • Marc-André Lureau's avatar
    util: do not silently truncate · 088ecbe8
    Marc-André Lureau authored
    
    
    snprintf() always nul-terminate.
    
    The return value is the number of business bytes that would be produced
    if the buffer was large enough.
    
    If it returns N for a N size buffer, it means truncation occurred (and
    we lost one business byte).
    
    Related to: #22
    
    Signed-off-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
    088ecbe8
  • Marc-André Lureau's avatar
    Merge branch 'slirp-fmt-truncate' into 'master' · 53a3a938
    Marc-André Lureau authored
    util: do not silently truncate
    
    See merge request !45
    53a3a938
  • Marc-André Lureau's avatar
    Release v4.3.1 · 376187c4
    Marc-André Lureau authored
    376187c4
  • Marc-André Lureau's avatar
    Merge branch 'release-v4.3.1' into 'master' · a62d3673
    Marc-André Lureau authored
    Release v4.3.1
    
    See merge request !46
    a62d3673
......@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [4.3.1] - 2020-07-08
### Changed
- A silent truncation could occur in `slirp_fmt()`, which will now print a
critical message. See also #22.
### Fixed
- CVE-2020-10756 - Drop bogus IPv6 messages that could lead to data leakage.
See !44 and !42.
- Fix win32 builds by using the SLIRP_PACKED definition.
- Various coverity scan errors fixed. !41
- Fix new GCC warnings. !43
## [4.3.0] - 2020-04-22
### Added
......@@ -89,6 +104,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Standalone project, removing any QEMU dependency.
- License clarifications.
[4.3.1]: https://gitlab.freedesktop.org/slirp/libslirp/compare/v4.3.0...v4.3.1
[4.3.0]: https://gitlab.freedesktop.org/slirp/libslirp/compare/v4.2.0...v4.3.0
[4.2.0]: https://gitlab.freedesktop.org/slirp/libslirp/compare/v4.1.0...v4.2.0
[4.1.0]: https://gitlab.freedesktop.org/slirp/libslirp/compare/v4.0.0...v4.1.0
......
......@@ -4,7 +4,7 @@ BUILD_DIR ?= .
LIBSLIRP = $(BUILD_DIR)/libslirp.a
SLIRP_MAJOR_VERSION = 4
SLIRP_MINOR_VERSION = 3
SLIRP_MICRO_VERSION = 0
SLIRP_MICRO_VERSION = 1
SLIRP_VERSION_STRING = "$(SLIRP_MAJOR_VERSION).$(SLIRP_MINOR_VERSION).$(SLIRP_MICRO_VERSION)-git"
all: $(LIBSLIRP)
......
......@@ -37,7 +37,7 @@ conf.set_quoted('SLIRP_VERSION_STRING', version)
# fixed, change:
# REVISION += 1
lt_current = 2
lt_revision = 1
lt_revision = 2
lt_age = 2
lt_version = '@0@.@1@.@2@'.format(lt_current - lt_age, lt_age, lt_revision)
......
......@@ -27,7 +27,8 @@
#include <string.h>
void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN])
void arp_table_add(Slirp *slirp, uint32_t ip_addr,
const uint8_t ethaddr[ETH_ALEN])
{
const uint32_t broadcast_addr =
~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr;
......
......@@ -239,7 +239,7 @@ int translate_dnssearch(Slirp *s, const char **names)
uint8_t *result = NULL, *outptr;
CompactDomain *domains = NULL;
num_domains = g_strv_length((GStrv)names);
num_domains = g_strv_length((GStrv)(void *)names);
if (num_domains == 0) {
return -2;
}
......
......@@ -119,7 +119,6 @@ void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code)
break;
default:
g_assert_not_reached();
break;
}
t->m_data += ICMP6_ERROR_MINLEN;
memcpy(t->m_data, m->m_data, error_data_len);
......
......@@ -44,11 +44,18 @@ void ip6_input(struct mbuf *m)
goto bad;
}
if (ntohs(ip6->ip_pl) > slirp->if_mtu) {
if (ntohs(ip6->ip_pl) + sizeof(struct ip6) > slirp->if_mtu) {
icmp6_send_error(m, ICMP6_TOOBIG, 0);
goto bad;
}
// Check if the message size is big enough to hold what's
// set in the payload length header. If not this is an invalid
// packet
if (m->m_len < ntohs(ip6->ip_pl) + sizeof(struct ip6)) {
goto bad;
}
/* check ip_ttl for a correct ICMP reply */
if (ip6->ip_hl == 0) {
icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS);
......
......@@ -75,8 +75,11 @@ void icmp_init(Slirp *slirp)
void icmp_cleanup(Slirp *slirp)
{
while (slirp->icmp.so_next != &slirp->icmp) {
icmp_detach(slirp->icmp.so_next);
struct socket *so, *so_next;
for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) {
so_next = so->so_next;
icmp_detach(so);
}
}
......@@ -274,8 +277,8 @@ void icmp_send_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsize,
ip = mtod(msrc, struct ip *);
if (slirp_debug & DBG_MISC) {
char bufa[20], bufb[20];
strcpy(bufa, inet_ntoa(ip->ip_src));
strcpy(bufb, inet_ntoa(ip->ip_dst));
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);
}
if (ip->ip_off & IP_OFFMASK)
......
......@@ -136,7 +136,8 @@ static const struct ncsi_rsp_handler {
void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
{
struct ncsi_pkt_hdr *nh = (struct ncsi_pkt_hdr *)(pkt + ETH_HLEN);
const struct ncsi_pkt_hdr *nh =
(const struct ncsi_pkt_hdr *)(pkt + ETH_HLEN);
uint8_t ncsi_reply[ETH_HLEN + NCSI_MAX_LEN];
struct ethhdr *reh = (struct ethhdr *)ncsi_reply;
struct ncsi_rsp_pkt_hdr *rnh =
......
......@@ -751,7 +751,8 @@ void slirp_pollfds_poll(Slirp *slirp, int select_error,
static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
{
struct slirp_arphdr *ah = (struct slirp_arphdr *)(pkt + ETH_HLEN);
const struct slirp_arphdr *ah =
(const struct slirp_arphdr *)(pkt + ETH_HLEN);
uint8_t arp_reply[MAX(ETH_HLEN + sizeof(struct slirp_arphdr), 64)];
struct ethhdr *reh = (struct ethhdr *)arp_reply;
struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_reply + ETH_HLEN);
......@@ -974,7 +975,6 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
default:
g_assert_not_reached();
break;
}
memcpy(eh->h_dest, ethaddr, ETH_ALEN);
......
......@@ -98,7 +98,8 @@ typedef struct ArpTable {
int next_victim;
} ArpTable;
void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]);
void arp_table_add(Slirp *slirp, uint32_t ip_addr,
const uint8_t ethaddr[ETH_ALEN]);
bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
uint8_t out_ethaddr[ETH_ALEN]);
......
......@@ -551,7 +551,6 @@ void sorecvfrom(struct socket *so)
break;
default:
g_assert_not_reached();
break;
}
/*
......@@ -603,7 +602,6 @@ void sorecvfrom(struct socket *so)
break;
default:
g_assert_not_reached();
break;
}
m_free(m);
} else {
......@@ -639,7 +637,6 @@ void sorecvfrom(struct socket *so)
break;
default:
g_assert_not_reached();
break;
}
} /* rx error */
} /* if ping packet */
......
......@@ -118,7 +118,9 @@ static int tftp_read_data(struct tftp_session *spt, uint32_t block_nr,
}
if (len) {
lseek(spt->fd, block_nr * spt->block_size, SEEK_SET);
if (lseek(spt->fd, block_nr * spt->block_size, SEEK_SET) == (off_t)-1) {
return -1;
}
bytes_read = read(spt->fd, buf, len);
}
......
......@@ -4,6 +4,8 @@
#ifndef SLIRP_TFTP_H
#define SLIRP_TFTP_H
#include "util.h"
#define TFTP_SESSIONS_MAX 20
#define TFTP_SERVER 69
......@@ -32,7 +34,7 @@ struct tftp_t {
} tp_error;
char tp_buf[TFTP_BLOCKSIZE_MAX + 2];
} x;
} __attribute__((packed));
} SLIRP_PACKED;
struct tftp_session {
Slirp *slirp;
......
......@@ -52,7 +52,10 @@ void udp_init(Slirp *slirp)
void udp_cleanup(Slirp *slirp)
{
while (slirp->udb.so_next != &slirp->udb) {
struct socket *so, *so_next;
for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) {
so_next = so->so_next;
udp_detach(slirp->udb.so_next);
}
}
......@@ -326,6 +329,7 @@ struct socket *udp_listen(Slirp *slirp, uint32_t haddr, unsigned hport,
struct socket *so;
socklen_t addrlen = sizeof(struct sockaddr_in);
memset(&addr, 0, sizeof(addr));
so = socreate(slirp);
so->s = slirp_socket(AF_INET, SOCK_DGRAM, 0);
if (so->s < 0) {
......
......@@ -392,7 +392,7 @@ int slirp_fmt(char *str, size_t size, const char *format, ...)
rv = slirp_vsnprintf(str, size, format, args);
va_end(args);
if (rv > size) {
if (rv >= size) {
g_critical("slirp_fmt() truncation");
}
......