Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2701170imu; Mon, 19 Nov 2018 04:53:34 -0800 (PST) X-Google-Smtp-Source: AJdET5dhq7fXJnFfKZLuEX/4l4q1VJANHX1SFVJGIdR97AzJChuI6opL2PphsZCYHkqco3IrNuQZ X-Received: by 2002:a17:902:107:: with SMTP id 7-v6mr22484428plb.267.1542632014377; Mon, 19 Nov 2018 04:53:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542632014; cv=none; d=google.com; s=arc-20160816; b=y0RIBMO47YUI4vQNsoHjDHBZKzpl4u+4bUjN8PJDi36CiItaewgcA7uxqSvB6MdG5U DgbeHhSuaVqZ3OpyPnrviIZySFY8O5R9EJ9zBBUDS5A0tYNST/nbtBDlwOAngIFcPMkA MyR3prUhZWoQtN/WTZeFJq0PNnruXV9SRW/8WwOcirt7+zhsPdTVIGDCZD55a1c2n2rC 7X/f0g6NsklDy1sni9HodvDGAJTGBPeVtQ+vz89l/MOSqm4p4nwlfmAR8MavE+OK4E4G 5ZuPadxwIQ8ZPXI/3/EcH85UcDaudLKBCD4stcvlbRodQtwEgCgNU9X4UMyNaDgHB4/Z Mf6g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :message-id:in-reply-to:subject:cc:to:from:date; bh=iuCS7kPCM81tErKuZGOeegUiymvs+BJN9Xuz6o+F8LY=; b=sY1JzFF+wlH1+P81MprvJao9H526hfLr0tk2zPtDnLH78fFZvKeyPtsafzVqlw0Y0q LZHpxxaiGF0pvSJi6JafOZF/WUHyJ/qFn5BfE44ymiAUiJtrJqemHEDv2ZarWc78aY8O j3be1YoBeTx4dhr4iW82I2mf7J4HoK5YEwjJCptB7I2jC3UaX5Vk7vwGgrquGySqG7HJ YzhGtZyIxN5xOsk7JP55IpvT6CeyINXNbYm2H0jPfCy6DDZrZLysgXA57uXSmuvOqzAO rQ1tfa2KC0qEqoTfIpBR/idBdwUWLqWUskbpGh0f1wQTrOc/eIxVFb7UAA4JN7yYUGU6 6pBw== ARC-Authentication-Results: i=1; mx.google.com; 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=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y6si22731496pll.384.2018.11.19.04.53.18; Mon, 19 Nov 2018 04:53:34 -0800 (PST) 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; 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=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728933AbeKSXQF (ORCPT + 99 others); Mon, 19 Nov 2018 18:16:05 -0500 Received: from mx2.suse.de ([195.135.220.15]:39956 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728818AbeKSXQF (ORCPT ); Mon, 19 Nov 2018 18:16:05 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 04FB2AFB6; Mon, 19 Nov 2018 12:52:30 +0000 (UTC) Date: Mon, 19 Nov 2018 13:52:28 +0100 (CET) From: Jiri Kosina To: Eric Biggers cc: David Herrmann , Benjamin Tissoires , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com, Dmitry Vyukov , Dmitry Torokhov , syzbot+72473edc9bf4eb1c6556@syzkaller.appspotmail.com, stable@vger.kernel.org, Jann Horn , Andy Lutomirski , David Herrmann Subject: Re: [PATCH v2] HID: uhid: forbid UHID_CREATE under KERNEL_DS or elevated privileges In-Reply-To: <20181114215509.163600-1-ebiggers@kernel.org> Message-ID: References: <20181114215509.163600-1-ebiggers@kernel.org> User-Agent: Alpine 2.21 (LSU 202 2017-01-01) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org [ David added to CC ] On Wed, 14 Nov 2018, Eric Biggers wrote: > From: Eric Biggers > > When a UHID_CREATE command is written to the uhid char device, a > copy_from_user() is done from a user pointer embedded in the command. > When the address limit is KERNEL_DS, e.g. as is the case during > sys_sendfile(), this can read from kernel memory. Alternatively, > information can be leaked from a setuid binary that is tricked to write > to the file descriptor. Therefore, forbid UHID_CREATE in these cases. > > No other commands in uhid_char_write() are affected by this bug and > UHID_CREATE is marked as "obsolete", so apply the restriction to > UHID_CREATE only rather than to uhid_char_write() entirely. > > Thanks to Dmitry Vyukov for adding uhid definitions to syzkaller and to > Jann Horn for commit 9da3f2b740544 ("x86/fault: BUG() when uaccess > helpers fault on kernel addresses"), allowing this bug to be found. > > Reported-by: syzbot+72473edc9bf4eb1c6556@syzkaller.appspotmail.com > Fixes: d365c6cfd337 ("HID: uhid: add UHID_CREATE and UHID_DESTROY events") > Cc: # v3.6+ > Cc: Jann Horn > Cc: Andy Lutomirski > Signed-off-by: Eric Biggers Thanks for the patch. I however believe the fix below is more generic, and would prefer taking that one in case noone sees any major flaw in that I've overlooked. Thanks. From: David Herrmann Subject: [PATCH] HID: uhid: prevent splice(2) The kernel has a default implementation of splice(2) for writing from a pipe into an arbitrary file. This behavior can be overriden by providing an f_op.splice_write() callback. Unfortunately, the default implementation of splice_write() takes page by page from the source pipe, calls kmap() and passes the mapped page as kernel-address to f_op.write(). Thus, it uses standard write(2) to implement splice(2). However, since the page is kernel-mapped, they have to `set_fs(get_ds())`. This is mostly fine, but UHID takes command-streams through write(2), and thus it might interpret the data taken as pointers. If called with KERNEL_DS, you can trick UHID to allow kernel-space pointers as well. As a simple fix, prevent splice(2) on UHID. It is unsecure, but it is also non-functional. We need a linear mapping of the input in UHID, so chunked input from splice(2) makes no sense, anyway. Reported-by: syzbot+72473edc9bf4eb1c6556@syzkaller.appspotmail.com Signed-off-by: David Herrmann --- drivers/hid/uhid.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 3c5507313606..fefedc0b4dc6 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -753,6 +753,15 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer, return ret ? ret : count; } +static ssize_t uhid_char_splice_write(struct pipe_inode_info *pipe, + struct file *out, + loff_t *ppos, + size_t len, + unsigned int flags) +{ + return -EOPNOTSUPP; +} + static __poll_t uhid_char_poll(struct file *file, poll_table *wait) { struct uhid_device *uhid = file->private_data; @@ -771,6 +780,7 @@ static const struct file_operations uhid_fops = { .release = uhid_char_release, .read = uhid_char_read, .write = uhid_char_write, + .splice_write = uhid_char_splice_write, .poll = uhid_char_poll, .llseek = no_llseek, }; -- Jiri Kosina SUSE Labs