From patchwork Mon Feb 24 20:30:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michel Lespinasse X-Patchwork-Id: 11401527 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E6FA6924 for ; Mon, 24 Feb 2020 20:32:01 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 97DF020675 for ; Mon, 24 Feb 2020 20:32:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Al+YErrt" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 97DF020675 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 60B136B00A9; Mon, 24 Feb 2020 15:31:56 -0500 (EST) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 5E4A76B00AB; Mon, 24 Feb 2020 15:31:56 -0500 (EST) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 4D0F86B00AC; Mon, 24 Feb 2020 15:31:56 -0500 (EST) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0193.hostedemail.com [216.40.44.193]) by kanga.kvack.org (Postfix) with ESMTP id 2B6426B00A9 for ; Mon, 24 Feb 2020 15:31:56 -0500 (EST) Received: from smtpin07.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id D4F0B824556B for ; Mon, 24 Feb 2020 20:31:55 +0000 (UTC) X-FDA: 76526166990.07.crime33_2de195c3e161c X-Spam-Summary: 2,0,0,057942ae03598f9d,d41d8cd98f00b204,3ujjuxgykcgkdhsrlunvvnsl.jvtspube-ttrchjr.vyn@flex--walken.bounces.google.com,,RULES_HIT:1:2:41:69:152:355:379:541:800:960:966:973:988:989:1260:1277:1313:1314:1345:1359:1437:1516:1518:1593:1594:1605:1730:1747:1777:1792:2196:2199:2393:2559:2562:2903:2915:3138:3139:3140:3141:3142:3152:3865:3866:3867:3868:3870:3871:3872:3874:4050:4250:4321:4385:5007:6120:6261:6653:7903:9036:9969:10004:11026:11473:11658:11914:12043:12048:12291:12296:12297:12438:12555:12683:12895:13149:13230:14659:21080:21324:21444:21451:21627:21990:30054:30056:30069:30070,0,RBL:209.85.210.202:@flex--walken.bounces.google.com:.lbl8.mailshell.net-66.100.201.100 62.18.0.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:23,LUA_SUMMARY:none X-HE-Tag: crime33_2de195c3e161c X-Filterd-Recvd-Size: 10333 Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.202]) by imf10.hostedemail.com (Postfix) with ESMTP for ; Mon, 24 Feb 2020 20:31:55 +0000 (UTC) Received: by mail-pf1-f202.google.com with SMTP id r127so7346723pfc.11 for ; Mon, 24 Feb 2020 12:31:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=NWiCHn5xo2/acy0ISkHXtkw4mgVPjpjyZNm+7prgHvI=; b=Al+YErrt1g2sfPG9K29Q4bjVc4FkFSvBgN01HKgJYctMtVDCC0DULgYHSmpS+HV2bR mS3K9McS6K654Bo/Lf3t5M0MSnTdEQHmIxsLUnbzp0gfmG2z/qwaAeV9n7vuEQwcI6vH wrvxRpylpmw4IBBBAjJejnQSq1tU3ELr4JLsjqHPwhnGzKH4re/039f6QVB4Yr+U9m1l 9CY5SxQVw6j5rGhCXPTYvhhJW9G8dDTap1uZeoFeZAcntDLxKBo0106Qc6wtoKH8Dzcs +szl0F9ehXcZsmjfUra0nk4iYPewnJw8Dhgg5INk1Ic5h1jrcpPFMLIwRhpMY1CXaCdE Z4Yw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=NWiCHn5xo2/acy0ISkHXtkw4mgVPjpjyZNm+7prgHvI=; b=a58mcqxK6+HgDeweGwkhmj4q4JB/RC+CphRLwACmfbFTkViqjBsqcoq9DcUYDnPUj9 FNEIZHsLmctqhuGMFCoMq81au7czB9dcq3Bwuq5UwUXkFWxxsNEvq5qg70RQLZDMi0K5 xOxfljFJL1lN6rC154hYG0dFR1I3LGzeEBvaWh6rq5cuKwXYDm0V8BZbFWqkQ5Ym7Ltf 15oy5oD5i7KUkAkht1eHzipAP0q4bjk2lKdrYZwuyt+WgGNoKfexyQyxoWCgziwDnVLJ ygSsM49keCXHF4IybyM/cP4O5Crg5tsR2F890Swin3bX4aFHXzjLonlWbAuJG+v1ZLv3 S1Mw== X-Gm-Message-State: APjAAAUogCkoBnbk/pIF5xg1u0bO2qXkYprM2xChBghWzLKlHaaOvIso V7/DjZWafcT8WB5CC/yEWQpMYKWMp6U= X-Google-Smtp-Source: APXvYqzUwTltMAgwNpHpmvlHDbZr1oEBQEcRLcPHPk/htNz4ZUv0fFcYE5jHBp3uzPgldUljTfQtUJgAB2I= X-Received: by 2002:a65:4b83:: with SMTP id t3mr53611496pgq.195.1582576314189; Mon, 24 Feb 2020 12:31:54 -0800 (PST) Date: Mon, 24 Feb 2020 12:30:55 -0800 In-Reply-To: <20200224203057.162467-1-walken@google.com> Message-Id: <20200224203057.162467-23-walken@google.com> Mime-Version: 1.0 References: <20200224203057.162467-1-walken@google.com> X-Mailer: git-send-email 2.25.0.265.gbab2e86ba0-goog Subject: [RFC PATCH 22/24] do_mmap: implement locked argument From: Michel Lespinasse To: Peter Zijlstra , Andrew Morton , Laurent Dufour , Vlastimil Babka , Matthew Wilcox , "Liam R . Howlett" , Jerome Glisse , Davidlohr Bueso , David Rientjes Cc: linux-mm , Michel Lespinasse X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: When locked is true, preserve the current behavior - the do_mmap() caller is expected to already hold a coarse write lock on current->mmap_sem When locked is false, change do_mmap() to acquiring the appropriate MM locks. do_mmap() still acquires a coarse lock in this change, but can now be locally changed to acquire a fine grained lock in the future. Signed-off-by: Michel Lespinasse --- mm/mmap.c | 106 ++++++++++++++++++++++++++++++++++++----------------- mm/nommu.c | 19 +++++++++- 2 files changed, 89 insertions(+), 36 deletions(-) diff --git mm/mmap.c mm/mmap.c index 2868e61927a1..75755f1cbd0b 100644 --- mm/mmap.c +++ mm/mmap.c @@ -1406,22 +1406,29 @@ unsigned long do_mmap(struct file *file, unsigned long addr, if ((pgoff + (len >> PAGE_SHIFT)) < pgoff) return -EOVERFLOW; + if (!locked && mm_write_lock_killable(mm)) + return -EINTR; + /* Too many mappings? */ - if (mm->map_count > sysctl_max_map_count) - return -ENOMEM; + if (mm->map_count > sysctl_max_map_count) { + addr = -ENOMEM; + goto unlock; + } /* Obtain the address to map to. we verify (or select) it and ensure * that it represents a valid section of the address space. */ addr = get_unmapped_area(file, addr, len, pgoff, flags); if (IS_ERR_VALUE(addr)) - return addr; + goto unlock; if (flags & MAP_FIXED_NOREPLACE) { struct vm_area_struct *vma = find_vma(mm, addr); - if (vma && vma->vm_start < addr + len) - return -EEXIST; + if (vma && vma->vm_start < addr + len) { + addr = -EEXIST; + goto unlock; + } } if (prot == PROT_EXEC) { @@ -1437,19 +1444,24 @@ unsigned long do_mmap(struct file *file, unsigned long addr, vm_flags |= calc_vm_prot_bits(prot, pkey) | calc_vm_flag_bits(flags) | mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; - if (flags & MAP_LOCKED) - if (!can_do_mlock()) - return -EPERM; + if ((flags & MAP_LOCKED) && !can_do_mlock()) { + addr = -EPERM; + goto unlock; + } - if (mlock_future_check(mm, vm_flags, len)) - return -EAGAIN; + if (mlock_future_check(mm, vm_flags, len)) { + addr = -EAGAIN; + goto unlock; + } if (file) { struct inode *inode = file_inode(file); unsigned long flags_mask; - if (!file_mmap_ok(file, inode, pgoff, len)) - return -EOVERFLOW; + if (!file_mmap_ok(file, inode, pgoff, len)) { + addr = -EOVERFLOW; + goto unlock; + } flags_mask = LEGACY_MAP_MASK | file->f_op->mmap_supported_flags; @@ -1465,27 +1477,37 @@ unsigned long do_mmap(struct file *file, unsigned long addr, flags &= LEGACY_MAP_MASK; /* fall through */ case MAP_SHARED_VALIDATE: - if (flags & ~flags_mask) - return -EOPNOTSUPP; + if (flags & ~flags_mask) { + addr = -EOPNOTSUPP; + goto unlock; + } if (prot & PROT_WRITE) { - if (!(file->f_mode & FMODE_WRITE)) - return -EACCES; - if (IS_SWAPFILE(file->f_mapping->host)) - return -ETXTBSY; + if (!(file->f_mode & FMODE_WRITE)) { + addr = -EACCES; + goto unlock; + } + if (IS_SWAPFILE(file->f_mapping->host)) { + addr = -ETXTBSY; + goto unlock; + } } /* * Make sure we don't allow writing to an append-only * file.. */ - if (IS_APPEND(inode) && (file->f_mode & FMODE_WRITE)) - return -EACCES; + if (IS_APPEND(inode) && (file->f_mode & FMODE_WRITE)) { + addr = -EACCES; + goto unlock; + } /* * Make sure there are no mandatory locks on the file. */ - if (locks_verify_locked(file)) - return -EAGAIN; + if (locks_verify_locked(file)) { + addr = -EAGAIN; + goto unlock; + } vm_flags |= VM_SHARED | VM_MAYSHARE; if (!(file->f_mode & FMODE_WRITE)) @@ -1493,28 +1515,39 @@ unsigned long do_mmap(struct file *file, unsigned long addr, /* fall through */ case MAP_PRIVATE: - if (!(file->f_mode & FMODE_READ)) - return -EACCES; + if (!(file->f_mode & FMODE_READ)) { + addr = -EACCES; + goto unlock; + } if (path_noexec(&file->f_path)) { - if (vm_flags & VM_EXEC) - return -EPERM; + if (vm_flags & VM_EXEC) { + addr = -EPERM; + goto unlock; + } vm_flags &= ~VM_MAYEXEC; } - if (!file->f_op->mmap) - return -ENODEV; - if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) - return -EINVAL; + if (!file->f_op->mmap) { + addr = -ENODEV; + goto unlock; + } + if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) { + addr = -EINVAL; + goto unlock; + } break; default: - return -EINVAL; + addr = -EINVAL; + goto unlock; } } else { switch (flags & MAP_TYPE) { case MAP_SHARED: - if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) - return -EINVAL; + if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) { + addr = -EINVAL; + goto unlock; + } /* * Ignore pgoff. */ @@ -1528,7 +1561,8 @@ unsigned long do_mmap(struct file *file, unsigned long addr, pgoff = addr >> PAGE_SHIFT; break; default: - return -EINVAL; + addr = -EINVAL; + goto unlock; } } @@ -1551,6 +1585,10 @@ unsigned long do_mmap(struct file *file, unsigned long addr, ((vm_flags & VM_LOCKED) || (flags & (MAP_POPULATE | MAP_NONBLOCK)) == MAP_POPULATE)) *populate = len; + +unlock: + if (!locked) + mm_write_unlock(mm); return addr; } diff --git mm/nommu.c mm/nommu.c index a2c2bf8d7676..7fb1db89d4f8 100644 --- mm/nommu.c +++ mm/nommu.c @@ -1107,6 +1107,7 @@ unsigned long do_mmap(struct file *file, unsigned long *populate, struct list_head *uf) { + struct mm_struct *mm = current->mm; struct vm_area_struct *vma; struct vm_region *region; struct rb_node *rb; @@ -1115,12 +1116,18 @@ unsigned long do_mmap(struct file *file, *populate = 0; + if (!locked && mm_write_lock_killable(mm)) + return -EINTR; + /* decide whether we should attempt the mapping, and if so what sort of * mapping */ ret = validate_mmap_request(file, addr, len, prot, flags, pgoff, &capabilities); - if (ret < 0) + if (ret < 0) { + if (!locked) + mm_write_unlock(mm); return ret; + } /* we ignore the address hint */ addr = 0; @@ -1135,7 +1142,7 @@ unsigned long do_mmap(struct file *file, if (!region) goto error_getting_region; - vma = vm_area_alloc(current->mm); + vma = vm_area_alloc(mm); if (!vma) goto error_getting_vma; @@ -1289,6 +1296,8 @@ unsigned long do_mmap(struct file *file, } up_write(&nommu_region_sem); + if (!locked) + mm_write_unlock(mm); return result; @@ -1301,6 +1310,8 @@ unsigned long do_mmap(struct file *file, if (vma->vm_file) fput(vma->vm_file); vm_area_free(vma); + if (!locked) + mm_write_unlock(mm); return ret; sharing_violation: @@ -1314,12 +1325,16 @@ unsigned long do_mmap(struct file *file, pr_warn("Allocation of vma for %lu byte allocation from process %d failed\n", len, current->pid); show_free_areas(0, NULL); + if (!locked) + mm_write_unlock(mm); return -ENOMEM; error_getting_region: pr_warn("Allocation of vm region for %lu byte allocation from process %d failed\n", len, current->pid); show_free_areas(0, NULL); + if (!locked) + mm_write_unlock(mm); return -ENOMEM; }