Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp5579631imm; Tue, 12 Jun 2018 09:55:54 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKTywj4MvtqQ5z3efJdYYHMy+fcHLJXeV5UzuOjO5EoHaZRCeBVuTtF+3XADEPjiM2UGcnw X-Received: by 2002:a17:902:6b09:: with SMTP id o9-v6mr1248788plk.256.1528822554393; Tue, 12 Jun 2018 09:55:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528822554; cv=none; d=google.com; s=arc-20160816; b=Fo2wBDulPXC2Owr6e/2J/d5SvIjH6DsDQ80cTtAEXW9s6fc6kwDaUaLjr4fcwfHMYW r41uuk7p6rm5wuMHaIR63FafR52BNeN0PvHDT7JNNv4Qqa+Px0ju7U95fy/Hz4Nk9FA1 qNkKo24F3zprUxvqfhZk/5K9O7YucqRi98i+nVpYTrrIH7450fjc/qLmsk2yiqIMHV3y t1Xi93nrqfDBXRDgvky8Uu1MOYgqqNyV+W9JQglQC5h8SGpuiV6p1MeHvwSFKNdyPBJV QnEYwJSRPlgX4gRGOIuXCbB2wmiTX/eZTGaFEDCKnntTgJuNDWbGZFXeMBPpXlMVs6Uo ZlAw== 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 :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=Dautlj7peoGIeGRq8MYXl83u7TnbvtuZ8RAjDagDtJE=; b=ood6CXgj07OTV06VIwAeNRS0UBoEJDIw9Usrmbm+lBt1SAKSc5mCDn2riq9TiH3ZPZ 15W0tspPMNkpBPwnH3Vq2ku7HjF0TZ1aQ7TvwHhjpo9VtLKfvNTqxp9442fH1Uxmlh4I XyNXCCCU9uMh0/UJg9qw93Sm/7IuJjwbZjsMQ7iZ0Q5lOAzhPqC0sxL+TWShH9QS8HTO ILe2o2SBFqoMC48Hfjo1BXaLkJpwfSq8QW3DL6LO0cWxvvfLgi5W7pcZmVYH6qfIGLxt Y/ZRtqdGapwjj0J5RNsZfub1fgSNL1mK5+6VIzOpyXU73lfTKZ+slk0HWtcu9ND+ixCz swYw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=WQlKVjZ+; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g7-v6si458898pgu.152.2018.06.12.09.55.39; Tue, 12 Jun 2018 09:55:54 -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=@kernel.org header.s=default header.b=WQlKVjZ+; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934647AbeFLQzS (ORCPT + 99 others); Tue, 12 Jun 2018 12:55:18 -0400 Received: from mail.kernel.org ([198.145.29.99]:57836 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933835AbeFLQyt (ORCPT ); Tue, 12 Jun 2018 12:54:49 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id DAE74208B9; Tue, 12 Jun 2018 16:54:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1528822488; bh=JFeAE4uEWL2FExPttE5RtOMse4AcMcZ7+U6PvGBfARk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WQlKVjZ+MfO/YsaZMPOh+ywvmdRsn0Sj6nYY9XiviXWyS8noUWVyYbhp+bAlXqQMk m7Gm5Fny98KXTwstV3Ymuj2tptNm/Q+C0vStlj/8lkZh2/llWM4ArZZkaSPF9kG4cy kDcoYt7P2CAIjgrdgJXbKjJ3PvpDfeG2Qe437LgQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Kees Cook , Dan Carpenter , Al Viro , Willy Tarreau , Dave Airlie , Linus Torvalds Subject: [PATCH 3.18 09/21] mmap: introduce sane default mmap limits Date: Tue, 12 Jun 2018 18:52:06 +0200 Message-Id: <20180612164825.789715889@linuxfoundation.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180612164825.401145490@linuxfoundation.org> References: <20180612164825.401145490@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Linus Torvalds commit be83bbf806822b1b89e0a0f23cd87cddc409e429 upstream. The internal VM "mmap()" interfaces are based on the mmap target doing everything using page indexes rather than byte offsets, because traditionally (ie 32-bit) we had the situation that the byte offset didn't fit in a register. So while the mmap virtual address was limited by the word size of the architecture, the backing store was not. So we're basically passing "pgoff" around as a page index, in order to be able to describe backing store locations that are much bigger than the word size (think files larger than 4GB etc). But while this all makes a ton of sense conceptually, we've been dogged by various drivers that don't really understand this, and internally work with byte offsets, and then try to work with the page index by turning it into a byte offset with "pgoff << PAGE_SHIFT". Which obviously can overflow. Adding the size of the mapping to it to get the byte offset of the end of the backing store just exacerbates the problem, and if you then use this overflow-prone value to check various limits of your device driver mmap capability, you're just setting yourself up for problems. The correct thing for drivers to do is to do their limit math in page indices, the way the interface is designed. Because the generic mmap code _does_ test that the index doesn't overflow, since that's what the mmap code really cares about. HOWEVER. Finding and fixing various random drivers is a sisyphean task, so let's just see if we can just make the core mmap() code do the limiting for us. Realistically, the only "big" backing stores we need to care about are regular files and block devices, both of which are known to do this properly, and which have nice well-defined limits for how much data they can access. So let's special-case just those two known cases, and then limit other random mmap users to a backing store that still fits in "unsigned long". Realistically, that's not much of a limit at all on 64-bit, and on 32-bit architectures the only worry might be the GPU drivers, which can have big physical address spaces. To make it possible for drivers like that to say that they are 64-bit clean, this patch does repurpose the "FMODE_UNSIGNED_OFFSET" bit in the file flags to allow drivers to mark their file descriptors as safe in the full 64-bit mmap address space. [ The timing for doing this is less than optimal, and this should really go in a merge window. But realistically, this needs wide testing more than it needs anything else, and being main-line is the only way to do that. So the earlier the better, even if it's outside the proper development cycle - Linus ] Cc: Kees Cook Cc: Dan Carpenter Cc: Al Viro Cc: Willy Tarreau Cc: Dave Airlie Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/mmap.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1271,6 +1271,35 @@ static inline int mlock_future_check(str return 0; } +static inline u64 file_mmap_size_max(struct file *file, struct inode *inode) +{ + if (S_ISREG(inode->i_mode)) + return inode->i_sb->s_maxbytes; + + if (S_ISBLK(inode->i_mode)) + return MAX_LFS_FILESIZE; + + /* Special "we do even unsigned file positions" case */ + if (file->f_mode & FMODE_UNSIGNED_OFFSET) + return 0; + + /* Yes, random drivers might want more. But I'm tired of buggy drivers */ + return ULONG_MAX; +} + +static inline bool file_mmap_ok(struct file *file, struct inode *inode, + unsigned long pgoff, unsigned long len) +{ + u64 maxsize = file_mmap_size_max(file, inode); + + if (maxsize && len > maxsize) + return false; + maxsize -= len; + if (pgoff > maxsize >> PAGE_SHIFT) + return false; + return true; +} + /* * The caller must hold down_write(¤t->mm->mmap_sem). */ @@ -1338,6 +1367,9 @@ unsigned long do_mmap_pgoff(struct file if (file) { struct inode *inode = file_inode(file); + if (!file_mmap_ok(file, inode, pgoff, len)) + return -EOVERFLOW; + switch (flags & MAP_TYPE) { case MAP_SHARED: if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE))