From patchwork Tue Nov 28 14:35:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 119883 Delivered-To: patches@linaro.org Received: by 10.80.225.132 with SMTP id k4csp3165852edl; Tue, 28 Nov 2017 06:35:34 -0800 (PST) X-Google-Smtp-Source: AGs4zMZSZsmbPMCk8odnORMADzewe/KK1Ja1aOKlxOk7YRTIeYF+jYkEeuEedDXbD4BPa1rMJ/OW X-Received: by 10.159.203.132 with SMTP id ay4mr31925225plb.400.1511879734357; Tue, 28 Nov 2017 06:35:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1511879734; cv=none; d=google.com; s=arc-20160816; b=Me9JIYzs02LHV4PGna3YdIrM5qchjyy2JKHJSKeC+/mqWQ8HwPg8OfT9qLUSrI5mSv JPL3c5HyWfx/nUcQL6iDh1hHvmER5qQ5NDWG74kVLeqd1V5INB36VGnq+d9KhmuCqKKo Cz57q5OvS1mjXaXOV/VvftpYCCRbDBOUCsp2cQqYHncN9GwlocL5OPi2HJvrFZP9wY/I W+nPEhAtTFLbqGnigKKThL2WM2+BVQMqhwFwzVjsiaaW3ffbLb4pKtR07YX1w1sRwQKv K7bzl/Q0g8ACyYlMmXsnx4OSj3zX51SzOAyeIh1YW55TR356XXkBacuS23Ays8uZgH/W 278g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=message-id:date:subject:cc:to:from:arc-authentication-results; bh=VqMhWPLcicRpXfPIWE6Fc/bX6dq7kOw9h0sSBIbOvSo=; b=KKf2NR6J5XHqSNuUkpyo3PhVD5iZPhvhrnI1b5R5w9ex6pxiBU9pZ0QrbYfeBYAeQj eGMRnf393rVOKnmxg0xrsNYyHNMUtxEbzWnGI05lTnmQzTEB5F9KPJuqB4mwMspe/GQE fc3jEo2/zNc0STSYCvsLGNi1fMvGFgh1xHXJK0Ap1ufNV6CvVW/fL52t39XFLWZG437i y2LuA+UruIT8CgBUfNVxNRDUP9Y0q6+rmo68XvcFSRrr7r53fDpxqVX0oIvfkjR3RSiM l6WBaxcFHxkwxwo8+eYvpOdZpTMcYg5fkkIRsXOwK7odHUxp9bL0o7dtJpVID0DJrU8Q 795Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id i76si24399551pgc.416.2017.11.28.06.35.33 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 28 Nov 2017 06:35:33 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1eJgys-00020Q-Nt; Tue, 28 Nov 2017 14:35:26 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Paolo Bonzini , Richard Henderson , Riku Voipio , Laurent Vivier Subject: [PATCH 0/2] linux-user: Fix race between threads in page_unprotect() Date: Tue, 28 Nov 2017 14:35:23 +0000 Message-Id: <1511879725-9576-1-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 If multiple guest threads in user-mode emulation write to a page which QEMU has marked read-only because of cached TCG translations, the threads can race in page_unprotect: * threads A & B both try to do a write to a page with code in it at the same time (ie which we've made non-writeable, so SEGV) * they race into the signal handler with this faulting address * thread A happens to get to page_unprotect() first and takes the mmap lock, so thread B sits waiting for it to be done * A then finds the page, marks it PAGE_WRITE and mprotect()s it writable * A can then continue OK (returns from signal handler to retry the memory access) * ...but when B gets the mmap lock it finds that the page is already PAGE_WRITE, and so it exits page_unprotect() via the "not due to protected translation" code path, and wrongly delivers the signal to the guest rather than just retrying the access In particular, this meant that trying to run 'javac' in user-mode emulation would fail with a spurious guest SIGSEGV. Handle this by making page_unprotect() assume that a call for a page which is already PAGE_WRITE is due to a race of this sort and return a "fault handled" indication. Since this would cause an infinite loop if we ever called page_unprotect() for some other kind of fault than "write failed due to bad access permissions", tighten the condition in handle_cpu_signal() to check the signal number and si_code, and add a comment so that if somebody does ever find themselves debugging an infinite loop of faults they have some clue about why. (The trick for identifying the correct setting for current_tb_invalidated for thread B (needed to handle the precise-SMC case) is due to Richard Henderson. Paolo Bonzini suggested just relying on si_code rather than trying anything more complicated.) I'm slightly nervous about assuming that we get SEGV with SEGV_ACCERR on a write if and only if the page permissions are set to non-writeable (for instance https://www.mail-archive.com/tech@openbsd.org/msg40358.html is a surprisingly recent patch to fix this for OpenBSD/x86, and I would be unsurprised if QEMU usermode itself got the si_code wrong, and the Boehm gc code at https://github.com/ivmai/bdwgc/blob/master/os_dep.c#L3182 is quite convoluted), but on the other hand we really ought in theory to be able to rely on si_code, and trying to handle this some other way gets pretty convoluted... thanks -- PMM Peter Maydell (2): linux-user: Propagate siginfo_t through to handle_cpu_signal() page_unprotect(): handle calls to pages that are PAGE_WRITE accel/tcg/translate-all.c | 50 ++++++++++++++++++++++++++++----------------- accel/tcg/user-exec.c | 52 +++++++++++++++++++++++------------------------ 2 files changed, 57 insertions(+), 45 deletions(-) -- 2.7.4