Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp184049imm; Thu, 10 May 2018 18:14:33 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpUhp1ANiI1sA7zigW1Gf+Gb8WKfp7msZoLEeyBfRUS8nfGDJ1bK+XdRAH27LFkjCG2971D X-Received: by 2002:a65:62d0:: with SMTP id m16-v6mr428222pgv.279.1526001273260; Thu, 10 May 2018 18:14:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526001273; cv=none; d=google.com; s=arc-20160816; b=qCpcMa4cNlrm3I46zueD2xY6NvzA9TzqAuf0axsEDL1b8bidQoVej7S+TS2gmIrVP9 9Prq38gMG5+Wo+hLN3jBqDM0edXCZjzewZFMNKaELsyJRui+aYZErWn3/M0E+Q0+9Mcy nNKNpO3skw1po402nKoeN+M0I5frGikA+HZMakM9UMEeAsOqLJIMPKaKVTV+f1SGyjH2 jb09gi+rBbtTnIW2BVtblWizfQNea5o7S9bImdNyd/tdXRKbqm219rQ6gZGXQQ8xTWOG xk1xaUOhhOst42vwRwKKe4Cq6gpCabbiVkxtdfGtFIXy9ZCtbNhPAtk/YzY5fxfaR0c3 lftA== 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=/chGaxTZ+N5QKGfwgG7rsBnR2Ueobs60uoHITzXEUcg=; b=LdeusIZWT+A1nbUBzr9Hqgn93/OZr7YvAIEq24ek0pgyNxCtpE5ZMUsTvFjUHX9ois iKNq30yGSkU4rLHNqfEosszw3llaK0WFXYEYHzQ0W9vrwFJNGw4n1PL6eyin4pr4zzaZ hL+1k7yd3MA5dyxlIsrIkWUiNV0CV17weeW71/WucYNmtZ5JBlr5rlABUYotK2jw+kxv WepZsuBZouziKs/Ih5oOYTB2FtsAVmfPkGSrdCmJ1llvQwntlJE7lHOVgxBOvQx8ZSq7 QidJCppCNZgK6wnTlo+l9GIawpnuRo09izloUn6FFF2jNGMoJ41joXyA79HDryKSsGnl iiTQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@alliedtelesis.co.nz header.s=mail header.b=NeB0yW6Y; 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=alliedtelesis.co.nz Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s83-v6si2044409pfg.175.2018.05.10.18.14.18; Thu, 10 May 2018 18:14:33 -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=@alliedtelesis.co.nz header.s=mail header.b=NeB0yW6Y; 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=alliedtelesis.co.nz Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752017AbeEKBN5 (ORCPT + 99 others); Thu, 10 May 2018 21:13:57 -0400 Received: from gate2.alliedtelesis.co.nz ([202.36.163.20]:33529 "EHLO gate2.alliedtelesis.co.nz" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750806AbeEKBNz (ORCPT ); Thu, 10 May 2018 21:13:55 -0400 Received: from mmarshal3.atlnz.lc (mmarshal3.atlnz.lc [10.32.18.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by gate2.alliedtelesis.co.nz (Postfix) with ESMTPS id D0FDF8365F; Fri, 11 May 2018 13:13:53 +1200 (NZST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alliedtelesis.co.nz; s=mail; t=1526001233; bh=/chGaxTZ+N5QKGfwgG7rsBnR2Ueobs60uoHITzXEUcg=; h=From:To:Cc:Subject:Date; b=NeB0yW6YVA4qrmxUOKUDGDM59Bnm7EpyK4XoNszne+Rf9LyDtZEtI57WnT3Md9v5O YxEAwyD8Dz8kb7ecpepCTRPPbL3nmLGhbNNLgdX2GB1yET3UYEsBEaJnnzr6TSdaUT PyQ8h/uDLGdpu1UZcHhoUJyyTKcZZvWOPs8lryR0= Received: from smtp (Not Verified[10.32.16.33]) by mmarshal3.atlnz.lc with Trustwave SEG (v7,5,8,10121) id ; Fri, 11 May 2018 13:11:22 +1200 Received: from hamishm-dl.ws.atlnz.lc (hamishm-dl.ws.atlnz.lc [10.33.22.10]) by smtp (Postfix) with ESMTP id E244E13EDDC; Fri, 11 May 2018 13:11:18 +1200 (NZST) Received: by hamishm-dl.ws.atlnz.lc (Postfix, from userid 1133) id AB362547117; Fri, 11 May 2018 13:11:17 +1200 (NZST) From: Hamish Martin To: gregkh@linuxfoundation.org Cc: linux-kernel@vger.kernel.org, Hamish Martin Subject: [PATCH 0/2] Prevent kernel oops on UIO device remove with open fds Date: Fri, 11 May 2018 13:11:03 +1200 Message-Id: <20180511011105.12193-1-hamish.martin@alliedtelesis.co.nz> X-Mailer: git-send-email 2.16.2 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org If a UIO device is removed while a user space app has an open file descriptor to that device's /dev/uio* file, a kernel oops can occur when the file descriptor is ultimately closed. The oops is triggered by dereferencing either the uio_listener struct's 'dev' pointer, or at the next level, when dereferencing a stale 'info' pointer on that dev. To resolve this we now increment the reference count for the uio_device and prevent the destruction of the uio_device until all open file descriptors are closed. A further consequence of resolving the stale pointers to the uio_device is that it exposes an issue with the independent life cycles of the uio_device and its related uio_info. The uio_info struct is allocated by the user of the uio subsystem and connected to a uio_device at registration time (see __uio_register_device()). When the device corresponding to that uio_info is unregistered and the memory for the uio_info is freed, the uio_device is left with a stale pointer which may still be used in the file system ops (uio_poll(), uio_read(), etc) To resolve this second issue, we now lock alteration or access of the 'info' member of the uio_device struct and alter the accessing code to handle that pointer being null. This patch series contains two patches. The first is a cosmetic change to the return paths from uio_write to facilitate easier review of the second patch. The second patch contains the change to prevent destruction of the uio_device while file descriptors to it remain open and the additional locking to prevent the use of a stale 'info' pointer. This patch series is heavily based on the work done by Brian Russell (formerly of Brocade) in May 2015. His last version of an attempt to fix this is seen here: https://patchwork.kernel.org/patch/6057431/ My new addition is the locking around use of the info pointer. It is my proposed solution to Brian's last comment about what he had left unfinished: "It needs a bit more work. uio_info needs to live as long as the corresponding uio_device. Since they seem to always be 1:1, uio_info could embedded within uio_device (but then all the users of uio need changed) or uio_info could be a refcounted object." For further info here is an example of the kernel oops this patch series is trying to resolve. Output is from a 4.17.0-rc1 kernel with a test app opening a uio device and doing select with the fd, then removing the UIO device while the select is still happening: Unable to handle kernel paging request for data at address 0x6b6b6b6b6b6b6d63 Faulting instruction address: 0xc000000000605c98 Oops: Kernel access of bad area, sig: 11 [#1] BE PREEMPT SMP NR_CPUS=8 CoreNet Generic Modules linked in: CPU: 6 PID: 282 Comm: uio_tester Not tainted 4.17.0-rc1-at1+ #8 NIP: c000000000605c98 LR: c000000000211d8c CTR: c000000000605c60 REGS: c0000000f02f3480 TRAP: 0300 Not tainted (4.17.0-rc1-at1+) MSR: 000000008202b000 CR: 24284448 XER: 20000000 DEAR: 6b6b6b6b6b6b6d63 ESR: 0000000000000000 SOFTE: 0 GPR00: c000000000211d8c c0000000f02f3700 c000000000dc7d00 c0000000ef365bc0 GPR04: c0000000f02f3800 0000000000000000 c0000000ef4b9b58 0000000000000006 GPR08: c000000000605c60 6b6b6b6b6b6b6b6b 0000000000000000 0000000000000016 GPR12: 0000000042284448 c00000003fffd440 0000000000000004 0000000000000003 GPR16: 0000000000000008 0000000000000000 00000000ef365bc0 0000000000000000 GPR20: c0000000f02f3c00 0000000000000000 0000000000000000 c0000000ef365bc0 GPR24: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 GPR28: c0000000f02f3800 c0000000ef365bc0 c0000000f02c2c68 c0000000efd01d20 NIP [c000000000605c98] .uio_poll+0x38/0xe0 LR [c000000000211d8c] .do_select+0x39c/0x7a0 Call Trace: [c0000000f02f3700] [c0000000f02f3790] 0xc0000000f02f3790 (unreliable) [c0000000f02f3790] [c000000000211d8c] .do_select+0x39c/0x7a0 [c0000000f02f3b90] [c000000000212eac] .core_sys_select+0x22c/0x320 [c0000000f02f3d70] [c000000000213098] .__se_sys_select+0xf8/0x170 [c0000000f02f3e30] [c000000000000674] system_call+0x58/0x64 Instruction dump: f8010010 fba1ffe8 fbc1fff0 fbe1fff8 f821ff71 7c7d1b78 7c9c2378 60000000 60000000 ebdd00c0 ebfe0000 e93f0038 2fa90000 40de0030 3c60ffff ---[ end trace 8badf75b83f45856 ]--- Hamish Martin (2): uio: Reduce return paths from uio_write() uio: Prevent device destruction while fds are open drivers/uio/uio.c | 121 ++++++++++++++++++++++++++++++++------------- include/linux/uio_driver.h | 3 +- 2 files changed, 90 insertions(+), 34 deletions(-) -- 2.16.2