From nobody Thu Nov 6 08:27:00 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1540150356219170.36186809972776; Sun, 21 Oct 2018 12:32:36 -0700 (PDT) Received: from localhost ([::1]:59982 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gEJSc-0002ZM-09 for importer@patchew.org; Sun, 21 Oct 2018 15:32:26 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60417) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gEJQn-0001iC-4b for qemu-devel@nongnu.org; Sun, 21 Oct 2018 15:30:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gEJQl-0003iW-AY for qemu-devel@nongnu.org; Sun, 21 Oct 2018 15:30:32 -0400 Received: from hera.aquilenet.fr ([2a0c:e300::1]:55682) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gEJQi-0003g5-5h; Sun, 21 Oct 2018 15:30:29 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id DD25BCEE; Sun, 21 Oct 2018 21:30:16 +0200 (CEST) Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1GCJk4MkSkeJ; Sun, 21 Oct 2018 21:30:15 +0200 (CEST) Received: from function (unknown [IPv6:2a01:cb19:181:c200:9eb6:d0ff:fe88:c3c7]) by hera.aquilenet.fr (Postfix) with ESMTPSA id 94D6A1675; Sun, 21 Oct 2018 21:30:15 +0200 (CEST) Received: from samy by function with local (Exim 4.91) (envelope-from ) id 1gEJQU-0005rr-V5; Sun, 21 Oct 2018 21:30:14 +0200 X-Virus-Scanned: Debian amavisd-new at aquilenet.fr From: Samuel Thibault To: qemu-devel@nongnu.org, peter.maydell@linaro.org Date: Sun, 21 Oct 2018 21:30:13 +0200 Message-Id: <20181021193014.22512-2-samuel.thibault@ens-lyon.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181021193014.22512-1-samuel.thibault@ens-lyon.org> References: <20181021193014.22512-1-samuel.thibault@ens-lyon.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a0c:e300::1 Subject: [Qemu-devel] [PULL 1/2] slirp: Add sanity check for str option length X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jan.kiszka@siemens.com, Fam Zheng , qemu-stable@nongnu.org, stefanha@redhat.com, Samuel Thibault Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Fam Zheng When user provides a long domainname or hostname that doesn't fit in the DHCP packet, we mustn't overflow the response packet buffer. Instead, report errors, following the g_warning() in the slirp->vdnssearch branch. Also check the strlen against 256 when initializing slirp, which limit is also from the protocol where one byte represents the string length. This gives an early error before the warning which is harder to notice or diagnose. Reported-by: Thomas Huth Reviewed-by: Thomas Huth Cc: qemu-stable@nongnu.org Signed-off-by: Fam Zheng Tested-by: Gerd Hoffmann Signed-off-by: Samuel Thibault --- net/slirp.c | 9 +++++++++ slirp/bootp.c | 32 ++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/net/slirp.c b/net/slirp.c index 99884de204..da6c0a1a5c 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -350,6 +350,15 @@ static int net_slirp_init(NetClientState *peer, const = char *model, return -1; } =20 + if (vdomainname && strlen(vdomainname) > 255) { + error_setg(errp, "'domainname' parameter cannot exceed 255 bytes"); + return -1; + } + + if (vhostname && strlen(vhostname) > 255) { + error_setg(errp, "'vhostname' parameter cannot exceed 255 bytes"); + return -1; + } =20 nc =3D qemu_new_net_client(&net_slirp_info, peer, model, name); =20 diff --git a/slirp/bootp.c b/slirp/bootp.c index 9e7b53ba94..1e8185f0ec 100644 --- a/slirp/bootp.c +++ b/slirp/bootp.c @@ -159,6 +159,7 @@ static void bootp_reply(Slirp *slirp, const struct boot= p_t *bp) struct in_addr preq_addr; int dhcp_msg_type, val; uint8_t *q; + uint8_t *end; uint8_t client_ethaddr[ETH_ALEN]; =20 /* extract exact DHCP msg type */ @@ -240,6 +241,7 @@ static void bootp_reply(Slirp *slirp, const struct boot= p_t *bp) rbp->bp_siaddr =3D saddr.sin_addr; /* Server IP address */ =20 q =3D rbp->bp_vend; + end =3D (uint8_t *)&rbp[1]; memcpy(q, rfc1533_cookie, 4); q +=3D 4; =20 @@ -292,24 +294,33 @@ static void bootp_reply(Slirp *slirp, const struct bo= otp_t *bp) =20 if (*slirp->client_hostname) { val =3D strlen(slirp->client_hostname); - *q++ =3D RFC1533_HOSTNAME; - *q++ =3D val; - memcpy(q, slirp->client_hostname, val); - q +=3D val; + if (q + val + 2 >=3D end) { + g_warning("DHCP packet size exceeded, " + "omitting host name option."); + } else { + *q++ =3D RFC1533_HOSTNAME; + *q++ =3D val; + memcpy(q, slirp->client_hostname, val); + q +=3D val; + } } =20 if (slirp->vdomainname) { val =3D strlen(slirp->vdomainname); - *q++ =3D RFC1533_DOMAINNAME; - *q++ =3D val; - memcpy(q, slirp->vdomainname, val); - q +=3D val; + if (q + val + 2 >=3D end) { + g_warning("DHCP packet size exceeded, " + "omitting domain name option."); + } else { + *q++ =3D RFC1533_DOMAINNAME; + *q++ =3D val; + memcpy(q, slirp->vdomainname, val); + q +=3D val; + } } =20 if (slirp->vdnssearch) { - size_t spaceleft =3D sizeof(rbp->bp_vend) - (q - rbp->bp_vend); val =3D slirp->vdnssearch_len; - if (val + 1 > spaceleft) { + if (q + val >=3D end) { g_warning("DHCP packet size exceeded, " "omitting domain-search option."); } else { @@ -331,6 +342,7 @@ static void bootp_reply(Slirp *slirp, const struct boot= p_t *bp) memcpy(q, nak_msg, sizeof(nak_msg) - 1); q +=3D sizeof(nak_msg) - 1; } + assert(q < end); *q =3D RFC1533_END; =20 daddr.sin_addr.s_addr =3D 0xffffffffu; --=20 2.19.1 From nobody Thu Nov 6 08:27:00 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1540150362525516.7600187140981; Sun, 21 Oct 2018 12:32:42 -0700 (PDT) Received: from localhost ([::1]:59983 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gEJSd-0002Zx-F3 for importer@patchew.org; Sun, 21 Oct 2018 15:32:27 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60414) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gEJQn-0001iB-0h for qemu-devel@nongnu.org; Sun, 21 Oct 2018 15:30:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gEJQj-0003iI-As for qemu-devel@nongnu.org; Sun, 21 Oct 2018 15:30:31 -0400 Received: from hera.aquilenet.fr ([2a0c:e300::1]:55698) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gEJQe-0003g9-38 for qemu-devel@nongnu.org; Sun, 21 Oct 2018 15:30:25 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id 763011675; Sun, 21 Oct 2018 21:30:17 +0200 (CEST) Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id EDNoXS35V63E; Sun, 21 Oct 2018 21:30:16 +0200 (CEST) Received: from function (unknown [IPv6:2a01:cb19:181:c200:9eb6:d0ff:fe88:c3c7]) by hera.aquilenet.fr (Postfix) with ESMTPSA id A71BB1677; Sun, 21 Oct 2018 21:30:15 +0200 (CEST) Received: from samy by function with local (Exim 4.91) (envelope-from ) id 1gEJQU-0005rt-Vs; Sun, 21 Oct 2018 21:30:14 +0200 X-Virus-Scanned: Debian amavisd-new at aquilenet.fr From: Samuel Thibault To: qemu-devel@nongnu.org, peter.maydell@linaro.org Date: Sun, 21 Oct 2018 21:30:14 +0200 Message-Id: <20181021193014.22512-3-samuel.thibault@ens-lyon.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181021193014.22512-1-samuel.thibault@ens-lyon.org> References: <20181021193014.22512-1-samuel.thibault@ens-lyon.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a0c:e300::1 Subject: [Qemu-devel] [PULL 2/2] slirp: Implement RFC2132 TFTP server name X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jan.kiszka@siemens.com, Fam Zheng , stefanha@redhat.com, Samuel Thibault Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Fam Zheng This new usernet option can be used to add data for option 66 (tftp server name) in the BOOTP reply, which is useful in PXE based automatic OS install such as OpenBSD. Signed-off-by: Fam Zheng Reviewed-by: Thomas Huth Tested-by: Gerd Hoffmann Signed-off-by: Samuel Thibault --- net/slirp.c | 12 ++++++++++-- qapi/net.json | 5 ++++- qemu-options.hx | 7 ++++++- slirp/bootp.c | 13 +++++++++++++ slirp/bootp.h | 1 + slirp/libslirp.h | 1 + slirp/slirp.c | 2 ++ slirp/slirp.h | 1 + 8 files changed, 38 insertions(+), 4 deletions(-) diff --git a/net/slirp.c b/net/slirp.c index da6c0a1a5c..f6dc03963a 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -150,6 +150,7 @@ static int net_slirp_init(NetClientState *peer, const c= har *model, const char *vnameserver, const char *vnameserver= 6, const char *smb_export, const char *vsmbserver, const char **dnssearch, const char *vdomainname, + const char *tftp_server_name, Error **errp) { /* default settings according to historic slirp */ @@ -360,6 +361,11 @@ static int net_slirp_init(NetClientState *peer, const = char *model, return -1; } =20 + if (tftp_server_name && strlen(tftp_server_name) > 255) { + error_setg(errp, "'tftp-server-name' parameter cannot exceed 255 b= ytes"); + return -1; + } + nc =3D qemu_new_net_client(&net_slirp_info, peer, model, name); =20 snprintf(nc->info_str, sizeof(nc->info_str), @@ -370,7 +376,8 @@ static int net_slirp_init(NetClientState *peer, const c= har *model, =20 s->slirp =3D slirp_init(restricted, ipv4, net, mask, host, ipv6, ip6_prefix, vprefix6_len, ip6_host, - vhostname, tftp_export, bootfile, dhcp, + vhostname, tftp_server_name, + tftp_export, bootfile, dhcp, dns, ip6_dns, dnssearch, vdomainname, s); QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry); =20 @@ -907,7 +914,8 @@ int net_init_slirp(const Netdev *netdev, const char *na= me, user->ipv6_host, user->hostname, user->tftp, user->bootfile, user->dhcpstart, user->dns, user->ipv6_dns, user->smb, - user->smbserver, dnssearch, user->domainname, err= p); + user->smbserver, dnssearch, user->domainname, + user->tftp_server_name, errp); =20 while (slirp_configs) { config =3D slirp_configs; diff --git a/qapi/net.json b/qapi/net.json index c86f351161..8f99fd911d 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -174,6 +174,8 @@ # # @guestfwd: forward guest TCP connections # +# @tftp-server-name: RFC2132 "TFTP server name" string (Since 3.1) +# # Since: 1.2 ## { 'struct': 'NetdevUserOptions', @@ -198,7 +200,8 @@ '*smb': 'str', '*smbserver': 'str', '*hostfwd': ['String'], - '*guestfwd': ['String'] } } + '*guestfwd': ['String'], + '*tftp-server-name': 'str' } } =20 ## # @NetdevTapOptions: diff --git a/qemu-options.hx b/qemu-options.hx index 214ce396f9..08f8516a9a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1823,7 +1823,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, " [,ipv6[=3Don|off]][,ipv6-net=3Daddr[/int]][,ipv6-host=3Daddr= ]\n" " [,restrict=3Don|off][,hostname=3Dhost][,dhcpstart=3Daddr]\n" " [,dns=3Daddr][,ipv6-dns=3Daddr][,dnssearch=3Ddomain][,domain= name=3Ddomain]\n" - " [,tftp=3Ddir][,bootfile=3Df][,hostfwd=3Drule][,guestfwd=3Dru= le]" + " [,tftp=3Ddir][,tftp-server-name=3Dname][,bootfile=3Df][,host= fwd=3Drule][,guestfwd=3Drule]" #ifndef _WIN32 "[,smb=3Ddir[,smbserver=3Dadd= r]]\n" #endif @@ -2060,6 +2060,11 @@ server. The files in @var{dir} will be exposed as th= e root of a TFTP server. The TFTP client on the guest must be configured in binary mode (use the co= mmand @code{bin} of the Unix TFTP client). =20 +@item tftp-server-name=3D@var{name} +In BOOTP reply, broadcast @var{name} as the "TFTP server name" (RFC2132 op= tion +66). This can be used to advise the guest to load boot files or configurat= ions +from a different server than the host address. + @item bootfile=3D@var{file} When using the user mode network stack, broadcast @var{file} as the BOOTP filename. In conjunction with @option{tftp}, this can be used to network b= oot diff --git a/slirp/bootp.c b/slirp/bootp.c index 1e8185f0ec..7b1af73c95 100644 --- a/slirp/bootp.c +++ b/slirp/bootp.c @@ -318,6 +318,19 @@ static void bootp_reply(Slirp *slirp, const struct boo= tp_t *bp) } } =20 + if (slirp->tftp_server_name) { + val =3D strlen(slirp->tftp_server_name); + if (q + val + 2 >=3D end) { + g_warning("DHCP packet size exceeded, " + "omitting tftp-server-name option."); + } else { + *q++ =3D RFC2132_TFTP_SERVER_NAME; + *q++ =3D val; + memcpy(q, slirp->tftp_server_name, val); + q +=3D val; + } + } + if (slirp->vdnssearch) { val =3D slirp->vdnssearch_len; if (q + val >=3D end) { diff --git a/slirp/bootp.h b/slirp/bootp.h index 394525733e..4043489835 100644 --- a/slirp/bootp.h +++ b/slirp/bootp.h @@ -70,6 +70,7 @@ #define RFC2132_MAX_SIZE 57 #define RFC2132_RENEWAL_TIME 58 #define RFC2132_REBIND_TIME 59 +#define RFC2132_TFTP_SERVER_NAME 66 =20 #define DHCPDISCOVER 1 #define DHCPOFFER 2 diff --git a/slirp/libslirp.h b/slirp/libslirp.h index 740408a96e..42e42e9a2a 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -13,6 +13,7 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct= in_addr vnetwork, bool in6_enabled, struct in6_addr vprefix_addr6, uint8_t vprefix_len, struct in6_addr vhost6, const char *vhostname, + const char *tftp_server_name, const char *tftp_path, const char *bootfile, struct in_addr vdhcp_start, struct in_addr vnameserver, struct in6_addr vnameserver6, const char **vdnssearch, diff --git a/slirp/slirp.c b/slirp/slirp.c index 5c3bd6163f..51de41fc02 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -283,6 +283,7 @@ Slirp *slirp_init(int restricted, bool in_enabled, stru= ct in_addr vnetwork, bool in6_enabled, struct in6_addr vprefix_addr6, uint8_t vprefix_len, struct in6_addr vhost6, const char *vhostname, + const char *tftp_server_name, const char *tftp_path, const char *bootfile, struct in_addr vdhcp_start, struct in_addr vnameserver, struct in6_addr vnameserver6, const char **vdnssearch, @@ -321,6 +322,7 @@ Slirp *slirp_init(int restricted, bool in_enabled, stru= ct in_addr vnetwork, slirp->vdhcp_startaddr =3D vdhcp_start; slirp->vnameserver_addr =3D vnameserver; slirp->vnameserver_addr6 =3D vnameserver6; + slirp->tftp_server_name =3D g_strdup(tftp_server_name); =20 if (vdnssearch) { translate_dnssearch(slirp, vdnssearch); diff --git a/slirp/slirp.h b/slirp/slirp.h index 10b410898a..b80725a0d6 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -212,6 +212,7 @@ struct Slirp { /* tftp states */ char *tftp_prefix; struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; + char *tftp_server_name; =20 ArpTable arp_table; NdpTable ndp_table; --=20 2.19.1