Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp5244122imm; Tue, 19 Jun 2018 07:23:38 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJ0t3eWdjWEuNAmOb20j5umyYo3ImiWAxDwkNC+JJE/TqTEiuuJOfTdnrsaNElXLIKRSTSb X-Received: by 2002:a62:4a0c:: with SMTP id x12-v6mr18471297pfa.142.1529418218760; Tue, 19 Jun 2018 07:23:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529418218; cv=none; d=google.com; s=arc-20160816; b=ZCCmBHmQ65BnS2riX4IS8n13Mc/LDmMlYP+N2UdKYMfsV8xFN5ahVXtzs25FgCdR2n wsMzd7A0JU0idGxB6iJAOMxT/KXcmIEuGKv9uhm2EWcdgY/Xyvy1AbuYwLt9IAQy9eRB 92ynPUFFVQAppwUd/URWGFoTwVBydR3/S8xTUQms6wUP14/nWa1ZTmHlM8WFO7KpcCJG 5HLYlTfp9DqH26xCNvwa8kwelonnzzcKpX6w0smY8+WkwPY8ISw0vh+gX17D7c0xMWDE p9fSq757DuA2mkORa3bR9vGhfTRZYn1sLtTPFfBItHcJJUeObnh9bKKTSJEuBkGKj8eS EZZg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=vC2CIpmxItSaYTUDqk0v7nYcpAsoyMho6obHN6uFDI4=; b=F3M00dH15njIK81/nE7k3V6YqGL+11e3rTZGBnCGyY2T3dXOCBlXnsu3WUwqinqiTG kDWgUzbyu82MX1Joy7+3u3Dr3LnHJnLKfDhjLLeifVaseS6IEQmUUX54KDUNI1Ic+BfY GsR2A/ctS/fiA0u6aBsrvOsqP1uFiH8U2Ys6SnhHsT7/L4gsEIrgPTp5HBjCQH48EoJ4 Zo6i06uPqRb9fmPoxv7omzG9Oo+xeaLmFxyE7XGoICD0HRrLKooVGA1gtyuoGRIkuENh 9EWBjO8zSrYLCCg6CZu+o0pulQ5kCsg/VQ+D7wr9Zx4asWDPEDEv1JZ4ZISWGDy0GnGS mwSw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@synopsys.com header.s=mail header.b=Pi9Q97Oy; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=synopsys.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z7-v6si14367423pgz.284.2018.06.19.07.23.24; Tue, 19 Jun 2018 07:23:38 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@synopsys.com header.s=mail header.b=Pi9Q97Oy; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=synopsys.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S937707AbeFSOWO (ORCPT + 99 others); Tue, 19 Jun 2018 10:22:14 -0400 Received: from smtprelay.synopsys.com ([198.182.37.59]:47006 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S937442AbeFSOWN (ORCPT ); Tue, 19 Jun 2018 10:22:13 -0400 Received: from mailhost.synopsys.com (mailhost1.synopsys.com [10.12.238.239]) by smtprelay.synopsys.com (Postfix) with ESMTP id 49DF11E04A8; Tue, 19 Jun 2018 16:22:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1529418131; bh=z4igt6nrBsenZCXI52OTBmYJ4wbjji5enGqF74bCV64=; h=From:To:Cc:Subject:Date:From; b=Pi9Q97OyC53F7qvpEwUsnjqbO2c/5L73UtnOHaeiP5/Avlo2LJyBa0urlf+Uunitm e64ff3PlI5OU1eOOSOvfofEtLs1XnySoDXadT9XtzxVwM9y1wkDAWjKF8Fdz4kf13c BLhUrTr6JHCWQDF/HwmO2LHzUaKTLuERFbZfJXyrv8ripseeZxls97LIi2KjPwhBg3 qPx2jmmUVbXbBh6/BMhyTqtS/1isNHUCw93ekMRQPjdmeD8HkuORHJltWJ/0/BkwO2 0PLCCbFhHBEKeRPcg1b7HX7fmrPzzT8nVzJPOtNCXz5IrbpH87tJ3DbwMPZq9WlTDy 0WCjqVAY3l8YA== Received: from abrodkin-7480l.internal.synopsys.com (unknown [10.121.8.87]) by mailhost.synopsys.com (Postfix) with ESMTP id 98A885E09; Tue, 19 Jun 2018 07:22:08 -0700 (PDT) From: Alexey Brodkin To: linux-snps-arc@lists.infradead.org Cc: linux-kernel@vger.kernel.org, Vineet Gupta , Peter Zijlstra , Alexey Brodkin , Max Filippov , linux-arch@vger.kernel.org Subject: [PATCH v2] ARC: Improve cmpxchg syscall implementation Date: Tue, 19 Jun 2018 17:22:05 +0300 Message-Id: <20180619142205.20493-1-abrodkin@synopsys.com> X-Mailer: git-send-email 2.17.1 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Peter Zijlstra arc_usr_cmpxchg syscall is supposed to be used on platforms that lack support of Load-Locked/Store-Conditional instructions in hardware. And in that case we mimic missing hardware features with help of kernel's sycall that "atomically" checks current value in memory and then if it matches caller expectation new value is written to that same location. What's important in the description above: - Check-and-exchange must be "atomical" which means preemption must be disabled during entire "transaction" - Data accessed is from user-space, i.e. we're dealing with virtual addresses And in current implementation we have a couple of problems: 1. We do disable preemprion around __get_user() & __put_user() but that in its turn disables page fault handler. That means if a pointer to user's data has no mapping in the TLB we won't be able to access required data. Instead software "exception handling" code from __get_user_fn() will return -EFAULT. 2. What's worse if we're dealing with data from not yet allocated page (think of pre-copy-on-write state) we'll successfully read data but on write we'll silently return to user-space with correct result (which we really read just before). That leads to very strange problems in user-space app further down the line because new value was never written to the destination. 3. Regardless of what went wrong we'll return from syscall and user-space application will continue to execute. Even if user's pointer was completely bogus. In case of hardware LL/SC that app would have been killed by the kernel. With that change we attempt to imrove on all 3 items above: 1. We still disable preemption around write of user's data but if we happen to fail with write we're enabling preemption and try to fix-up page fault so that we have a correct permission for writing user's data. Then re-try again in "atomic" context. 2. If real page fault fails or even access_ok() returns false we send SIGSEGV to the user-space process so if something goes seriously wrong we'll know about it much earlier. Signed-off-by: Peter Zijlstra Signed-off-by: Alexey Brodkin Cc: Vineet Gupta Cc: Max Filippov Cc: linux-arch@vger.kernel.org --- Changes v1 -> v2: * Peter's almost clean-room reimplmentation with less paranoid checks and direct invocation of fixup_user_fault() for in-place update of write permissions. arch/arc/kernel/process.c | 48 ++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index 5ac3b547453f..7a7742fba77a 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -47,7 +47,9 @@ SYSCALL_DEFINE0(arc_gettls) SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new) { struct pt_regs *regs = current_pt_regs(); - int uval = -EFAULT; + struct page *page; + u32 val; + int ret; /* * This is only for old cores lacking LLOCK/SCOND, which by defintion @@ -60,23 +62,47 @@ SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new) /* Z indicates to userspace if operation succeded */ regs->status32 &= ~STATUS_Z_MASK; - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; + ret = access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)); + if (!ret) + goto fail; +again: preempt_disable(); - if (__get_user(uval, uaddr)) - goto done; + ret = __get_user(val, uaddr); + if (ret) + goto fault; - if (uval == expected) { - if (!__put_user(new, uaddr)) - regs->status32 |= STATUS_Z_MASK; - } + if (val != expected) + goto out; + + ret = __put_user(new, uaddr); + if (ret) + goto fault; + + regs->status32 |= STATUS_Z_MASK; + +out: + preempt_enable(); + return val; -done: +fault: preempt_enable(); - return uval; + if (unlikely(ret != -EFAULT)) + goto fail; + + down_read(¤t->mm->mmap_sem); + ret = fixup_user_fault(current, current->mm, uaddr, FAULT_FLAG_WRITE, + NULL); + up_read(¤t->mm->mmap_sem); + + if (likely(!ret)) + goto again; + +fail: + force_sig(SIGSEGV, current); + return ret; } #ifdef CONFIG_ISA_ARCV2 -- 2.17.1