From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751480AbdAPMhJ (ORCPT ); Mon, 16 Jan 2017 07:37:09 -0500 Received: from mail-he1eur01on0092.outbound.protection.outlook.com ([104.47.0.92]:45234 "EHLO EUR01-HE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751416AbdAPMhB (ORCPT ); Mon, 16 Jan 2017 07:37:01 -0500 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=dsafonov@virtuozzo.com; From: Dmitry Safonov To: CC: <0x7f454c46@gmail.com>, Dmitry Safonov , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , Andy Lutomirski , Borislav Petkov , , , Shuah Khan , Subject: [PATCHv2 5/5] selftests/x86: add test to check compat mmap() return addr Date: Mon, 16 Jan 2017 15:33:10 +0300 Message-ID: <20170116123310.22697-6-dsafonov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170116123310.22697-1-dsafonov@virtuozzo.com> References: <20170116123310.22697-1-dsafonov@virtuozzo.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [195.214.232.6] X-ClientProxiedBy: VI1PR09CA0071.eurprd09.prod.outlook.com (10.174.49.143) To AM5PR0801MB1731.eurprd08.prod.outlook.com (10.169.247.9) X-MS-Office365-Filtering-Correlation-Id: d6f7d7c6-80e8-4a09-144c-08d43e0c54a2 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001);SRVR:AM5PR0801MB1731; X-Microsoft-Exchange-Diagnostics: 1;AM5PR0801MB1731;3:ZKsqUHG7GW+gFxgn6IlsoxjoY6ZJ2Em2ti7NHFBfgr5HqHOOTAR5dw97nAueEBeGzPxM/xbv15aufRPIXzVrtycm/nv+iwSQtfwB5286brtvey2l8wPTwaypeQCRc689DPFXnzJRot/tJvXDA1Z75OPYrn0zpcwOY6jEBvre+bj3UTNMxpiGfLAOOsH9KYn3JMr6hrMQ/C5d302tt5Gw6X0jglm7Y4aqAY9MTzJKYZunpSEK8Xf5X9Y5XqVGeyVKC3HDm/z8PN92E49YFTWmFg== X-Microsoft-Exchange-Diagnostics: 1;AM5PR0801MB1731;25:bIMLOCoOkkzlfwJhL6h5sY5YTg5JowGM+NeevXY6DQOGk/x0gEpfAPDf9G3kiOr/VQ+G8mQxMTvHiUYm+YG2F2rbu7y0CVKKDi7gzhlXzGRdOpMf49UE4Bfb+VYsxg70Gy9PDAke2zURUFx62EEqfEyemaiQQ8IlkLk+npYkTYy776ZqSIKKVk0TAEfrfKLXybl4of7w5Y+kirbASGPg0g+I4XqRd5KN0on1++T61wj1oT3RFmFwrLFomgnISJ0jRL+QZvsR0wualyPh7mrr0bH4vfOKgaMOZM1go+Q4i7FxtasONdZ/w9TTxCdUX6WqGMWWxl8xd5XueSeL1G4MMMjH7zq96FJjcf77lp/e1SPVu6K/99egtxvHHazXDB+DcQApiwsJms2cuynRq0J2gQWT79niNISbMAhTQWpa2eLlbJSDPxSTOybBC449BpxJXdaw45g6bY2lHWQzCcfGi2CFff+KC580sr3F5S1hraAsVOd17J31gXX0VFD0bljGQMse/b6jSThaIimDUHwWtKDS7b3vxxuMtyPBZon4pRFLzdsDJ1WOqcqP1dkfhgcinEmHw/VEqa2blNmEeEL1r2xADvx1VOH4K03fsNCE5JbTCgVK/bf0w/arEG8cBfZdXhZNx0/ZeYH1MXAsCW6XXAoPHoo4i+69XsMLTMx6O3axxW6POyAhmYie/wqRSMO7nkEzeKfg+D261tJvcTlepaocRfQJd582/4/9hmb/CHc= X-Microsoft-Exchange-Diagnostics: 1;AM5PR0801MB1731;31:4ZiQUuPOhyejH9Jg5mEm7P9MFlDg1XLQxpTem4Tw7wGKfc+prj3E24H4aRZtOKGzsC+rHN6BvEO8+R4GVLp/nh4elBn4iKT1Aov/gzcP8xbMkEJqwPKW4E9dZryCFA+NcsshSRYDw7ObLAIswWVtOI9g7mRd2FN0mfD9l2yEiuZPY5NQuidHiynLKGiuapVx9Bc9FG+tkCAQk0z9MDYo3R6ZFgC7SAjIK1cQqf65qlQiBQiVc7XMW8W0lj7c5qUY;20:9H+1/kVjjanbDhEP2jzhiZ7rOcmHXwHijHv63U9gCPFuUkTdWL7yW7PVaA79sm5NBq+Ff40+D5nX/4cQtr/2jMd8Btw/+o8xR2LASW08jkNclGMtWuFR2lbX3zHIxzCe832TD/7U8dxUVxFxvmsMEQKBzEmgSJwQ5UDnMe5nDcOKtMBfIrnOx74BEY5nqLypzk2s3PgQvrTu6l4C+WplZ3vykqwAgm+v33jPMuRXCaKu5aK/2jEq/HaHQevYht7d X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(9452136761055); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040375)(601004)(2401047)(5005006)(8121501046)(3002001)(10201501046)(6041248)(20161123560025)(20161123558021)(20161123555025)(20161123562025)(20161123564025)(6072148);SRVR:AM5PR0801MB1731;BCL:0;PCL:0;RULEID:;SRVR:AM5PR0801MB1731; X-Microsoft-Exchange-Diagnostics: 1;AM5PR0801MB1731;4:FYitd62PtSc6o/BPxEaRyyD64fC1WV8XlZEo27cebu3Z9KHPgZu14gJnRA60yw3m5ybUmG+cIfgWF9XoQgyy4r0Ot5Y9fmDIeRHeIk/5fNdz0r4yZ3vVGX2ZfqfSKv/DkKUcGMcAPyldFo7GN36z5mCW5JEJKGcXWBkzpLgh6dr6OhTOrsdsLaOrVAauYzNdfsCGT6Hie2rMFvLFr3W5tYv6rQ0LAR5eSt3Hig1Z6RVwImh2ZnFTJ5S8VYE17Bz0RUbWc6jD+diTenR9d4DxYOqDqWua1PzTYNVbyMzu6Py8HJJWVU9ZdHT9XehIGEv/oY0Y+xutjir/9zCPO1U4Ns9hQapl/qs5yByybzStihvRonuMylwc1itj+0O9amyiGgUM8fS3qw54kyO4h/FxNaUfEpIsK9/kEuwNVHdCf+UjQLFEr9jC7cUE0xg5qj4VLdM/ROFhHm+3vx3ZOIJQjE4Ln3wuUf7JIclCHQop1lyVfWNmToXk0hkatw+AZb/IANhKC1gAIi7Lu9m3ynkPDj/Fy3ty1dXDyapv2BvI44/I5KIjcCQcY5cIJEFcFQdSBmIdkDqcUyzWhF3Kjo9acmv72mx1xSW2PssraBJf4yYEyKaZEYNxWOOAkaIiXKoR4nb3MuTRGlHZBgf2y9IQPA== X-Forefront-PRVS: 01894AD3B8 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(7916002)(39830400002)(39450400003)(39410400002)(189002)(199003)(50986999)(76176999)(47776003)(50226002)(66066001)(48376002)(5660300001)(50466002)(92566002)(5003940100001)(189998001)(101416001)(68736007)(97736004)(6506006)(105586002)(6666003)(27001)(2906002)(7416002)(106356001)(6486002)(8676002)(6916009)(53416004)(2950100002)(4326007)(6512007)(54906002)(7736002)(42186005)(33646002)(69596002)(25786008)(36756003)(86362001)(6116002)(3846002)(2351001)(305945005)(38730400001)(81156014)(110136003)(1076002)(39060400001)(81166006)(2004002);DIR:OUT;SFP:1102;SCL:1;SRVR:AM5PR0801MB1731;H:dsafonov.sw.ru;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;AM5PR0801MB1731;23:UQpQaCUC551ak2fmBF60qc3QiivNPugGAVi3tvV?= =?us-ascii?Q?1fwj8/DG8IefWNjbHmdjBK4W/g0s/V9JQoD/0Y6GKoEga9kndaHShLrKQx/y?= =?us-ascii?Q?HxKKfLs+TYGc55mF1kn3gC2MgrgXdh8yUe5yEPRfKNtxu5LKH2MaxNHpuFu2?= =?us-ascii?Q?0vMvxPC45AE5LqTZslQwHO1f6dZdVodjDgXzp31ROG9qwnJbo96mrOkcHJmP?= =?us-ascii?Q?7vTbr1WtDXEnDEoXJ9jhxXcDLtlBa6mMwleMT68s9MkPIjjN2GOzNVuQRXbF?= =?us-ascii?Q?Ig++kkgikyaLIH6BShG9OzuC52ALd5phvbGH8FWjKlX31lgqwwHQJvSTW2M9?= =?us-ascii?Q?NfFIAcoElWLRV/0rToX6Cn+rsdlBpOfHcI9MqHWaD3YbsF/VtheXA17OhLYn?= =?us-ascii?Q?JGWGme57Yt4THCuApVcgDy+5aJjkU1lzK10jSQh8x+ohAcUqN+Kji1AZ3yc9?= =?us-ascii?Q?XW/qUgiutiJjKDbTmSKtNJ6+7RDer3vpl4RCPCeqdMQkeLsUFps5UVx5p6q5?= =?us-ascii?Q?QrNMlenee6naIhFBYpIGrPn5vhFoJdsB9BKTR6hILgCmjYBhzYX5srTO582i?= =?us-ascii?Q?AARZRemS83TGoAW8rLDCdlty8qURwXfQn7G03CdYnkOoqY4j5QtYpd7++jn0?= =?us-ascii?Q?torOPacxcOkcIiUEXiyuCmq3NN/xbZ/iUG74BGAgHUdUYGIC7Q4GbBwko9BN?= =?us-ascii?Q?YBkxpI5FKnXNGB/yxK+u1LEknjDCCAY7KM4c4mqSWazYIpYKzIeQ9xJi8+vX?= =?us-ascii?Q?BsssC3klUhptQ+iS0wQGsJ01ju5/d2gHFSSd/ENllHpKSzbUltvRtzswD2u/?= =?us-ascii?Q?zvcDa0XMAeORw2SitUwrJ7/CUpaPFG+aZO140D3mOiWMODdvanwB0q+I4pN1?= =?us-ascii?Q?hCAcy1dTAMxKvejQgMxsX3BSkuOigeooiKbcA5dVSY+Gh+OGe1oY9ExKymdB?= =?us-ascii?Q?3cDmvfI8U3sp99d4RPOYqmOu2Gt8R3ZjtN3arsrWCwpFzKu2c0taxpUgWKeS?= =?us-ascii?Q?5AXD1hYcWpU55p56D6/vWu8yg3jRYq3+O4XGJ82inRq77qvGJcjJ4cHhjo6N?= =?us-ascii?Q?X3dj5pLKM0d/XJO/uBKeiX/X6TSCqIWkzTLs5fdHhlfEpYEDWTQmoqYG1+h3?= =?us-ascii?Q?eSUKJoRKhasVwPkIT1r8yFwCPY11LVHkUUpNCUPA0malZoZYc7R50VlXy+f7?= =?us-ascii?Q?wFMsMEDnjQe9OCCCa4yhZBiaufKPFSQGRjHY3HEZnillfxwBCImM4NrODzNv?= =?us-ascii?Q?4ENBqYldAO+N7uwqhw3nqifFdxuQrGbsaO7ZXwKTwAa9zIonyItAlGu0lI+H?= =?us-ascii?Q?CwalXR4RjDAiamkpPug0J1/U=3D?= X-Microsoft-Exchange-Diagnostics: 1;AM5PR0801MB1731;6:I6KgPBGTR+ZSNEpywavRQ0nK9SammHe8I+21Ihoi6pqsJtSgkTkCODyDjp4TLMppcgp7goh0zzxDu5JFJJkuGmvhB7f8TvAm4Pr9yMlHxchDtdKKMVJ7Nr5QbM07wSCZwVrxiA5rMJKmlrtJqtZI30gn1R/QG8YcAd1jyxYRRkH7+AsNipkjbUmordrhRtv+0LNA2zPdx5WRldfNqodVcNqa0wyb7E6G5OVzBsZ9AF7cu+Ouv8lVgZ3UFbQDWcaa2wZujFxpw480N0XGeA8zF1Vti1K9O1vAZD9Qgte/qCY9+YaBv0S6ilS1yqZCDYHDCNmSJ2G+UjaUKrgwV3MBTeRcOIT2PMXnkN1EdosXl7fEXRT2MV53QxgvAjMPxxyzkQU4mz2V3+oFZgfoMaoy7RfXwp0xolB6FqXIH3l3SAo=;5:bIf8s5QJEyFEDxqsgaWSIeI2YniWXwGDOFRR+O4HwNH7kD+GiNqeKcbNMTK5zAwkEG7Szv4/z+T4AjX5yL7nQTwrYd2rN/oCOTGIOhU+hWj7RxkUhxS3VuWAtCiXH+d3/g5fwckI1qtvsVp4sGABqQ==;24:AUFSveLZDHsiJWGfXPcqM9/itPEZ2IWVO10FhZITQNAjcnc3V4yJWXVrDsz2cCl8jWZSucVPdKy2beIjZY29GE/fnDTAy+56WJA/z7s+bSU= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;AM5PR0801MB1731;7:YLYONZlTcUMW4vezP7edZ/TPfaQLzbM9JlBY6yySdYlaaH+ob0F0ndPMPOk6fL/4IrJRgKyjzxNAurSmwdSAcBAziEu4oS9jl4lvoxUm/8aPyforS6gD9SLlCIiP46kcl33dVvVnxl7H8TQMrDlLCwwg3GCreg/ZoaaKbFnp4LEXL604T+DPj7RB0fjT/+RUL4Xak73xHa8sHTP+iN2zBwrNKcOkLrpapj3iBkSkPiAOVpkttXCfSY6VjOnNsqOIQaMc8PTH4whq433Z518KkNX+tNx6+LcUxkcwyDSwnostH8lr413Ipj0iL9wcdeMvtRONjG2iqxAl7yt6kyxmZaaXD+IPBlX3a6ch3wHI82d/jhDRjOzgqka2SSjk++axFgyADKGKcWMHVEtELu6sBJsuJDEn82yMfTIC1fRVeso87arMjxZrslo7KBvrWmBLvH5AtcIjUiNcnx8qP0UgxA==;20:3roK+UB6yyFK4bZKojPG3JZhAGNMVTaoHcLgNfypbD+SwoQ7bf4Rkw6bv5LZupiPlZ1knBHv6MJHLXyAQiPjfaxkdDATxc9cj11G2OkOXnCJN8O+Esb9l9RxaRArrvV6OZjD4S+tYIJ1LBo04tVie6+l8UZMddetbLlL7P48UC4= X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 Jan 2017 12:36:43.5421 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM5PR0801MB1731 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We can't just add segfault handler and use addr, returned by compat mmap() syscall, because the lower 4 bytes can be the same as already existed VMA. So, the test parses /proc/self/maps file, founds new VMAs those appeared after compatible sys_mmap() and checks if mmaped VMA is in that list. On failure it prints: [NOTE] Allocated mmap 0x6f36a000, sized 0x400000 [NOTE] New mapping appeared: 0x7f936f36a000 [FAIL] Found VMA [0x7f936f36a000, 0x7f936f76a000] in maps file, that was allocated with compat syscall Cc: Shuah Khan Cc: linux-kselftest@vger.kernel.org Signed-off-by: Dmitry Safonov --- tools/testing/selftests/x86/Makefile | 2 +- tools/testing/selftests/x86/test_compat_mmap.c | 208 +++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/x86/test_compat_mmap.c diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index 8c1cb423cfe6..9c3e746a6064 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -10,7 +10,7 @@ TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_sysc TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \ vdso_restorer -TARGETS_C_64BIT_ONLY := fsgsbase +TARGETS_C_64BIT_ONLY := fsgsbase test_compat_mmap TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY) diff --git a/tools/testing/selftests/x86/test_compat_mmap.c b/tools/testing/selftests/x86/test_compat_mmap.c new file mode 100644 index 000000000000..245d9407653e --- /dev/null +++ b/tools/testing/selftests/x86/test_compat_mmap.c @@ -0,0 +1,208 @@ +/* + * Check that compat 32-bit mmap() returns address < 4Gb on 64-bit. + * + * Copyright (c) 2017 Dmitry Safonov (Virtuozzo) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +#include +#include + +#include +#include +#include +#include +#include + +#define PAGE_SIZE 4096 +#define MMAP_SIZE (PAGE_SIZE*1024) +#define MAX_VMAS 50 +#define BUF_SIZE 1024 + +#ifndef __NR32_mmap2 +#define __NR32_mmap2 192 +#endif + +struct syscall_args32 { + uint32_t nr, arg0, arg1, arg2, arg3, arg4, arg5; +}; + +static void do_full_int80(struct syscall_args32 *args) +{ + asm volatile ("int $0x80" + : "+a" (args->nr), + "+b" (args->arg0), "+c" (args->arg1), "+d" (args->arg2), + "+S" (args->arg3), "+D" (args->arg4), + "+rbp" (args->arg5) + : : "r8", "r9", "r10", "r11"); +} + +void *mmap2(void *addr, size_t len, int prot, int flags, + int fildes, off_t off) +{ + struct syscall_args32 s; + + s.nr = __NR32_mmap2; + s.arg0 = (uint32_t)(uintptr_t)addr; + s.arg1 = (uint32_t)len; + s.arg2 = prot; + s.arg3 = flags; + s.arg4 = fildes; + s.arg5 = (uint32_t)off; + + do_full_int80(&s); + + return (void *)(uintptr_t)s.nr; +} + +struct vm_area { + unsigned long start; + unsigned long end; +}; + +static struct vm_area vmas_before_mmap[MAX_VMAS]; +static struct vm_area vmas_after_mmap[MAX_VMAS]; + +static char buf[BUF_SIZE]; + +int parse_maps(struct vm_area *vmas) +{ + FILE *maps; + int i; + + maps = fopen("/proc/self/maps", "r"); + if (maps == NULL) { + printf("[ERROR]\tFailed to open maps file: %m\n"); + return -1; + } + + for (i = 0; i < MAX_VMAS; i++) { + struct vm_area *v = &vmas[i]; + char *end; + + if (fgets(buf, BUF_SIZE, maps) == NULL) + break; + + v->start = strtoul(buf, &end, 16); + v->end = strtoul(end + 1, NULL, 16); + //printf("[NOTE]\tVMA: [%#lx, %#lx]\n", v->start, v->end); + } + + if (i == MAX_VMAS) { + printf("[ERROR]\tNumber of VMAs is bigger than reserved array's size\n"); + return -1; + } + + if (fclose(maps)) { + printf("[ERROR]\tFailed to close maps file: %m\n"); + return -1; + } + return 0; +} + +int compare_vmas(struct vm_area *vmax, struct vm_area *vmay) +{ + if (vmax->start > vmay->start) + return 1; + if (vmax->start < vmay->start) + return -1; + if (vmax->end > vmay->end) + return 1; + if (vmax->end < vmay->end) + return -1; + return 0; +} + +unsigned long vma_size(struct vm_area *v) +{ + return v->end - v->start; +} + +int find_new_vma_like(struct vm_area *vma) +{ + int i, j = 0, found_alike = -1; + + for (i = 0; i < MAX_VMAS && j < MAX_VMAS; i++, j++) { + int cmp = compare_vmas(&vmas_before_mmap[i], + &vmas_after_mmap[j]); + + if (cmp == 0) + continue; + if (cmp < 0) {/* Lost mapping */ + printf("[NOTE]\tLost mapping: %#lx\n", + vmas_before_mmap[i].start); + j--; + continue; + } + + printf("[NOTE]\tNew mapping appeared: %#lx\n", + vmas_after_mmap[j].start); + i--; + if (!compare_vmas(&vmas_after_mmap[j], vma)) + return 0; + + if (((vmas_after_mmap[j].start & 0xffffffff) == vma->start) && + (vma_size(&vmas_after_mmap[j]) == vma_size(vma))) + found_alike = j; + } + + /* Left new vmas in tail */ + for (; i < MAX_VMAS; i++) + if (!compare_vmas(&vmas_after_mmap[j], vma)) + return 0; + + if (found_alike != -1) { + printf("[FAIL]\tFound VMA [%#lx, %#lx] in maps file, that was allocated with compat syscall\n", + vmas_after_mmap[found_alike].start, + vmas_after_mmap[found_alike].end); + return -1; + } + + printf("[ERROR]\tCan't find [%#lx, %#lx] in maps file\n", + vma->start, vma->end); + return -1; +} + +int main(int argc, char **argv) +{ + void *map; + struct vm_area vma; + + if (parse_maps(vmas_before_mmap)) { + printf("[ERROR]\tFailed to parse maps file\n"); + return 1; + } + + map = mmap2(0, MMAP_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (((uintptr_t)map) % PAGE_SIZE) { + printf("[ERROR]\tmmap2 failed: %d\n", + (~(uint32_t)(uintptr_t)map) + 1); + return 1; + } else { + printf("[NOTE]\tAllocated mmap %p, sized %#x\n", map, MMAP_SIZE); + } + + if (parse_maps(vmas_after_mmap)) { + printf("[ERROR]\tFailed to parse maps file\n"); + return 1; + } + + munmap(map, MMAP_SIZE); + + vma.start = (unsigned long)(uintptr_t)map; + vma.end = vma.start + MMAP_SIZE; + if (find_new_vma_like(&vma)) + return 1; + + printf("[OK]\n"); + + return 0; +} -- 2.11.0