From patchwork Fri Jul 31 16:31:02 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= X-Patchwork-Id: 502694 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id AB8781402DE for ; Sat, 1 Aug 2015 02:34:04 +1000 (AEST) Received: from localhost ([::1]:45202 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZLDFy-0000Gg-S6 for incoming@patchwork.ozlabs.org; Fri, 31 Jul 2015 12:34:02 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45082) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZLDDf-0004QA-7p for qemu-devel@nongnu.org; Fri, 31 Jul 2015 12:31:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZLDDY-00085U-Tb for qemu-devel@nongnu.org; Fri, 31 Jul 2015 12:31:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:47166) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZLDDY-00085E-NA for qemu-devel@nongnu.org; Fri, 31 Jul 2015 12:31:32 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (Postfix) with ESMTPS id 61D7636B4EA; Fri, 31 Jul 2015 16:31:32 +0000 (UTC) Received: from localhost.localdomain.com (vpn1-4-231.ams2.redhat.com [10.36.4.231]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t6VGVGaX000893; Fri, 31 Jul 2015 12:31:30 -0400 From: "Daniel P. Berrange" To: qemu-devel@nongnu.org Date: Fri, 31 Jul 2015 17:31:02 +0100 Message-Id: <1438360263-25445-10-git-send-email-berrange@redhat.com> In-Reply-To: <1438360263-25445-1-git-send-email-berrange@redhat.com> References: <1438360263-25445-1-git-send-email-berrange@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Peter Maydell Subject: [Qemu-devel] [PATCH RFC 09/10] maint: add check for use of POSIX functions which are not reentrant safe X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Imports a rule from libvirt to make sure that for any POSIX function which is not reentrant safe, the _r variant is used in the source. While it is entirely possible that many of the QEMU uses are in fact safe, it is pretty difficult to prove that conclusively due to the increasing use of 3rd party libraries. For features like spice, glusterfs, rbd, iscsi these libraries may either be used from QEMU non-main threads, or can be secretly using threads themselves behind QEMU's back. Given this, the only safe thing todo is to forbid all use of the non-reentrant safe POSIX functions. While Linux platforms have long had the full set of _r variants, other OS may not be so lucky, particularly Mingw32, so fixing this will require some portability code on various platforms. Since fixing the current QEMU usage is non-trivial, the check is disabled for any functions QEMU currently relies on. IOW, this check merely stops the current problem getting any worse. Future work will have to look at fixing existing violations. Signed-off-by: Daniel P. Berrange --- Makefile.nonreentrant | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++ cfg.mk | 14 ++++++ 2 files changed, 134 insertions(+) create mode 100644 Makefile.nonreentrant diff --git a/Makefile.nonreentrant b/Makefile.nonreentrant new file mode 100644 index 0000000..687d39b --- /dev/null +++ b/Makefile.nonreentrant @@ -0,0 +1,120 @@ +## Functions for sc_prohibit_nonreentrant -*- makefile -*- +## +## Copyright (C) 2009-2010, 2013 Red Hat, Inc. +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library. If not, see +## . + +# +# Generated by running the following on Fedora 9: +# +# nm -D --defined-only /lib/libc.so.6 \ +# | grep '_r$' \ +# | awk '{print $3}' \ +# | grep -v __ \ +# | grep -v qsort \ # Red herring since we don't need to pass extra args to qsort comparator +# | grep -v readdir \ # This is safe as long as each DIR * instance is only used by one thread +# | sort \ +# | uniq \ +# | sed -e 's/_r//' +# +# Also manually add in all inet_* functions some of which +# are not threadsafe and do not have _r variants. They are +# all deprecated in favour of getnameinfo/getaddrinfo +# + +# Current QEMU violations are commented out. Eventual goal +# is to uncomment all these functions, once QEMU code is +# fixed +NON_REENTRANT = +NON_REENTRANT += asctime +NON_REENTRANT += ctime +NON_REENTRANT += drand48 +NON_REENTRANT += ecvt +NON_REENTRANT += erand48 +NON_REENTRANT += ether_aton +NON_REENTRANT += ether_ntoa +#NON_REENTRANT += fcvt +NON_REENTRANT += fgetgrent +NON_REENTRANT += fgetpwent +NON_REENTRANT += fgetspent +NON_REENTRANT += getaliasbyname +NON_REENTRANT += getaliasent +NON_REENTRANT += getdate +NON_REENTRANT += getgrent +NON_REENTRANT += getgrgid +NON_REENTRANT += getgrnam +NON_REENTRANT += gethostbyaddr +NON_REENTRANT += gethostbyname2 +#NON_REENTRANT += gethostbyname +NON_REENTRANT += gethostent +NON_REENTRANT += getlogin +#NON_REENTRANT += getmntent +NON_REENTRANT += getnetbyaddr +NON_REENTRANT += getnetbyname +NON_REENTRANT += getnetent +NON_REENTRANT += getnetgrent +NON_REENTRANT += getprotobyname +NON_REENTRANT += getprotobynumber +NON_REENTRANT += getprotoent +NON_REENTRANT += getpwent +#NON_REENTRANT += getpwnam +#NON_REENTRANT += getpwuid +NON_REENTRANT += getrpcbyname +NON_REENTRANT += getrpcbynumber +NON_REENTRANT += getrpcent +NON_REENTRANT += getservbyname +NON_REENTRANT += getservbyport +NON_REENTRANT += getservent +NON_REENTRANT += getspent +NON_REENTRANT += getspnam +NON_REENTRANT += getutent +NON_REENTRANT += getutid +NON_REENTRANT += getutline +#NON_REENTRANT += gmtime +NON_REENTRANT += hcreate +NON_REENTRANT += hdestroy +NON_REENTRANT += hsearch +NON_REENTRANT += initstate +NON_REENTRANT += jrand48 +NON_REENTRANT += lcong48 +#NON_REENTRANT += localtime +NON_REENTRANT += lrand48 +NON_REENTRANT += mrand48 +NON_REENTRANT += nrand48 +#NON_REENTRANT += ptsname +NON_REENTRANT += qecvt +NON_REENTRANT += qfcvt +#NON_REENTRANT += random +#NON_REENTRANT += rand +NON_REENTRANT += seed48 +NON_REENTRANT += setstate +NON_REENTRANT += sgetspent +NON_REENTRANT += srand48 +#NON_REENTRANT += srandom +#NON_REENTRANT += strerror +#NON_REENTRANT += strtok +NON_REENTRANT += tmpnam +NON_REENTRANT += ttyname +#NON_REENTRANT += inet_addr +#NON_REENTRANT += inet_aton +NON_REENTRANT += inet_lnaof +NON_REENTRANT += inet_makeaddr +NON_REENTRANT += inet_netof +NON_REENTRANT += inet_network +NON_REENTRANT += inet_nsap_addr +NON_REENTRANT += inet_nsap_ntoa +#NON_REENTRANT += inet_ntoa +#NON_REENTRANT += inet_ntop +#NON_REENTRANT += inet_pton diff --git a/cfg.mk b/cfg.mk index 39e4124..2f98c1a 100644 --- a/cfg.mk +++ b/cfg.mk @@ -128,6 +128,20 @@ sc_copyright_format: halt='spell Red Hat as two words' \ $(_sc_search_regexp) +# Use a subshell for each function, to give the optimal warning message. +include $(srcdir)/Makefile.nonreentrant + +sc_prohibit_nonreentrant: + @for i in $(NON_REENTRANT) ; \ + do \ + (prohibit="\\<$$i *\\(" \ + in_vc_files='\.[ch]$$' \ + halt="use $${i}_r, not $$i" \ + $(_sc_search_regexp) \ + ) || fail=1; \ + done ; \ + exit $$fail + # We don't use this feature of maint.mk. prev_version_file = /dev/null