Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754437AbdCFO7b (ORCPT ); Mon, 6 Mar 2017 09:59:31 -0500 Received: from mail-db5eur01on0119.outbound.protection.outlook.com ([104.47.2.119]:53760 "EHLO EUR01-DB5-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753162AbdCFO6v (ORCPT ); Mon, 6 Mar 2017 09:58:51 -0500 Authentication-Results: vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=none action=none header.from=virtuozzo.com; From: Dmitry Safonov To: CC: <0x7f454c46@gmail.com>, Dmitry Safonov , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , Andy Lutomirski , Borislav Petkov , , , Cyrill Gorcunov , "Kirill A. Shutemov" , Shuah Khan , Subject: [PATCHv6 5/5] selftests/x86: add test for 32-bit mmap() return addr Date: Mon, 6 Mar 2017 17:17:21 +0300 Message-ID: <20170306141721.9188-6-dsafonov@virtuozzo.com> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20170306141721.9188-1-dsafonov@virtuozzo.com> References: <20170306141721.9188-1-dsafonov@virtuozzo.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [195.214.232.6] X-ClientProxiedBy: DB6PR1001CA0021.EURPRD10.PROD.OUTLOOK.COM (10.171.79.31) To VI1PR0801MB1742.eurprd08.prod.outlook.com (10.168.67.20) X-MS-Office365-Filtering-Correlation-Id: e130aec1-3664-4927-c15a-08d4649c132a X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001);SRVR:VI1PR0801MB1742; X-Microsoft-Exchange-Diagnostics: 1;VI1PR0801MB1742;3:zH0I3LSbgNF7k84PZ1QW68GLZ9ivYT++taZkc0Do/R5daTgNBsG+0/5RPN+gMyiOph+RbSMH6gEYzuI4tZLcz5CPH/S45iehSujFb1OYr49hP76d28HpH7qKC/I3BV8Sbwq0Gq1QOs4GeMFGarl3QeeMPXujHATEKhyDlCW/OgvuuaOud5qRxO3WXa8WwuWEbCgZyXnL/BG69Gr0YL94GzNSTzVD0Yxup+QsIt2c2wcoSqOgVTU1vms2LBOeEF+JBuPujCiydGLmH7GW9f78HQ==;25:w6D5LMue1hnKeZTNLOUKiseMBLvhN6OLV1RoeYjNhoMUzgYRQUF9tYpf8eempuY4PbquJGk9YvIXlMSKadpM9aKlBmiFrDVv29fsv84IG4WNZKPg6u/HHq8XceY84k5UfyPy3OTuRhsbtbHhNOYEHYOoOlhHvxnoLeXjGrTyIWQ8Ih0vhJPtZOK5KLw/Y3w8tD7qd6Ppqa/HECelsDCVy57cfv9+lNCApn7XUPQ9Wlo8y1qRRr3ks6PKlK+F+dXV/ehCGOLi4UNdjJ6rbAWuEyqQ+H5h9GaT395bJEQxa49t66uBfsMeQxHLYFg4ayyfOjgMmesnbAOHwMW05hjAmn7TgtsBjNL5uRmQggZrDJKPIqWmKAC74+Z3rD67CPmivP0oD0Z9RvNTl/sC/b0fiaYwl43vhnpmT/erU9yxXMx7lEplybuhdqVetgAqGY9zpvvojbw5JHKdwUJOXMNjcg== X-Microsoft-Exchange-Diagnostics: 1;VI1PR0801MB1742;31:ZJy2F2lAQQmEtXQ/a+Ocpy+lqud8QZfjwH+XfZFmzBuQNchv/ed/mixO5lpLQbbqJh0AsrFSwcTgSsu5Bt9TgyrhFobk9A8DAbvxfZuoiz6x/OVoGVvCRhDk5Wci60hnacDk8gR80aS7QZThOtaUeHhhfNPHyzvcWfLMB8syt82FJB8dH4SBTUG8dC6DKd2sxIl0ykVMIkNLA/D8IUks/Qsq0T9U9uiy5eOdjBhmzIo=;20:T97mLecA/LagVX/zpw9t2Lnf55ykQuVB9cHGGkuF6jzeQ67mrEiC+bjzdneLDfUxyX77UgKLJ1R4j6yw5Ln5b3mrFUVu0CETh60Hh/Cb/e470owuczYaPkyU0sg5iW9R0l3ygEhBAsH69TYxdmDjMZGFQZJ2xVjfJiZ1VnbD7xRk+sCj9Jm/Km5fi8hR4sNGNx35EcjyfB/9rW/pJQqOeK27kPDegnDcD8q6cXpPeuwxTvwuQwEFxiWDaZ73MKJFDew14xg4mod+f89YkEAm3S6KXTDqmAhNNPp7ZPeoTgUtzZ5EWf3z8yegPYTQTbWnJubJj5blTS0KU26BSQnJtFK/az5acLiisIEFspHA+gAzuoJ9BZSv+decgs6MFY/hDrVpy/6fqnWqnKwrMrEBqAX3QJtCBpdJ5Qo8c0mznfU= 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)(8121501046)(5005006)(3002001)(10201501046)(6041248)(20161123560025)(20161123562025)(20161123555025)(20161123564025)(20161123558025)(6072148);SRVR:VI1PR0801MB1742;BCL:0;PCL:0;RULEID:;SRVR:VI1PR0801MB1742; X-Microsoft-Exchange-Diagnostics: 1;VI1PR0801MB1742;4:R6TRMDyzkzWxXune/Gd1bH8M5O4nn668RFc0bWWeoBr558f2cfBBViX3bjCeWyC7FkPySRLA1aI7kN/idLKZzodJSke2Gi8uRr6NrTTFagbvpYBc7JgNy/fRiE5QTlDXIjGsq3FgGZtAC+8A5fCeeblx85Iz4PuxxyJ+sXZ+fPQsPJ35UWuAahiNS0AXfTWkjumDIOM33qV1tscItG+IxfA/Ne4SDSLwAVA0GzVkAA4RWT+jCv0oGhEgAg+a9wf9/Hbs/UKyVUKB12mkxDHh5ncnulZvrPhnecdzE8YdKrjt3FX7AM6IWPz6L5z2XXd2/nPwV95s1EZORFCzjrCxzS8syNMyBS6jI2eGaexdTA22ef9220qdHx1owKhRvKpzccJoE4hdRKL6zfnu6X0V3sBgPoW+lhg79R9qhbXeSSA8lsO0mv2HJr2o7p8ZRozxf92/F3SC+3FnZtJK89uzRzKxDovavNJOjkCAVG+xIQshsbrEm1AJuNbMQaymiEzdPtIGZP87LP3LAx2HFp76ocwdlMZTm2eZBsctFadeWc4feirA6QKa+kFz7dHL3uGaPghAVMSClgevU47j8gmOSWGXs5ez1AYS0BvuzAUM3f3zgovrZ+EGydYVjjSL/N/DMto59hhun+EG2QILKiy+fQ== X-Forefront-PRVS: 0238AEEDB0 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(7916002)(39450400003)(2906002)(110136004)(6916009)(6666003)(2950100002)(305945005)(8676002)(53416004)(38730400002)(81166006)(6512007)(50466002)(42186005)(7416002)(1076002)(7736002)(5660300001)(53936002)(5003940100001)(76176999)(50986999)(48376002)(25786008)(66066001)(575784001)(54906002)(86362001)(92566002)(189998001)(50226002)(2351001)(3846002)(4326008)(47776003)(33646002)(36756003)(6116002)(6506006)(6486002);DIR:OUT;SFP:1102;SCL:1;SRVR:VI1PR0801MB1742;H:dsafonov.sw.ru;FPR:;SPF:None;MLV:sfv;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;VI1PR0801MB1742;23:Stt8xyof57sU3AAvdkaN7PNQ0COSPxnx1aON0L0?= =?us-ascii?Q?JAt3LPOGKBWkHAFZOqEBs0ynPcAJpBPfDKZNgVzD+XIpO0oSHcI9Eu1pOYR+?= =?us-ascii?Q?v9u8JQe1Jb7JolnOTqmKYnn8oyE4ezNVWTL7IrM7GSdKDmleN0a6xQihryVM?= =?us-ascii?Q?Ec7zwFSmPqmji271t/wXhehXQprMkQp/imLcF9GiHptBP/wrKmKqYESFPiRq?= =?us-ascii?Q?9EftnAlFBS6cIG8wFzo77iNFZHGIRCUdmf3RwcycaIuDs2N7PPZS94FQy66L?= =?us-ascii?Q?9TWGHbXDAP+ipAPzzTGIkm5CSBq7iR/JA7evkTa0I2LqNxJ2NYNmb8cUPQNU?= =?us-ascii?Q?31ljjf1zR0XobMR2br8vNO5vjsAtc8TX78MuAeNkAUkQpjpZ4OHfZamIPIJb?= =?us-ascii?Q?JLhW3q2qRoJKjEQrjaodbzeJfKpLpQBZNhrWHrOvkVgM0ozwCV7UdrdQ86HM?= =?us-ascii?Q?vwy4oSTH0nNc/VNKg5ZawgC6LJEYOPSpVZ85QTyHNiMKOQLK4GCJNTT9+Ygz?= =?us-ascii?Q?tWdl4iwDH0AVW1L6o5JiVg8dcAC2kJqM3AMHyyD7z5DimL28pTXRzBKfikmn?= =?us-ascii?Q?/9uZWmEs+v/djVRo+8X36aRIcdmYpvcEwb56NNi4f2G5VX99zuTQhdx7RfuV?= =?us-ascii?Q?U5LJJqM6NQrmpw1Arvweuvr/66DXixkrWkxnvNPocwdXvPRPqMuc/oOlgjja?= =?us-ascii?Q?vxwgqoRef8C/gUxX+AqasG930j3EDoTCB8pYgjsZB+Pj98ojHu3VePAWZI7z?= =?us-ascii?Q?kxd+0KBsmIDl6dMsTaT2YhoMZpKyJmFhstYagoI1pWV2V/gtzoHIr24eTXGv?= =?us-ascii?Q?Snh5z2l7nxq5o+nkL//r8M2dwZUh4cZSbmMeJhllHxLImQugZRalWAIThK5O?= =?us-ascii?Q?gksxHiCjRjuXtBHxG3YcXvulGHmvoSimuxlETxvpT0B1598KRGfJcgvkd+tl?= =?us-ascii?Q?/v5m6rxtM+1R8Vgt0yh9pQaXkriKUsN1xOBFQe/XJVxD3OxpcL/qTMFP+uRw?= =?us-ascii?Q?g0aF3NFU+a9uEvqR8X20lNIG5PfxKqcm5pQ9FMiSbivm8h7WHXlgMDFu0yME?= =?us-ascii?Q?RvbP5wPI=3D?= X-Microsoft-Exchange-Diagnostics: 1;VI1PR0801MB1742;6:+SRey6CouD80T1oUJqvdIk2mpx29EXowJSySzWsfOM9PIlkrIbiu6EdJkSp/1oKDN/ylEv1l6Stm3y9BDHGabilwiysUHjvSdUSzaWe/BnhBzwuuprHabGeKhNxHDQEeFJTVgBmopgfJgPwhf7iB6AXzvc4Nii0xWbGw7qQ5DvhFz5Izh6YpU2zFH/h22+kN7yLhVLFXRaP4YmkRp7nhpYp03n/u48RTNxmwU2m7paHQ3aMTES1ttBJnGyF83L8XdLYQwbzGSWQA3PgOzuYgSm1m/BAW6fpq6wd1Roael54/ip/dzrdm3PUbhjDte1279CDU8uVET8RmIunPOlmw65mJesWbhPlD/+ShyMhRIO+0yD3vhU/PBErq6yq3z3RPr7zItqwCnCDZ2mq45KLHIw==;5:v8oqlpB5MeBrhpjtLAQcxGaVU6jZUbGDNXeSAOp2gaam/cToCLre3NyKEnC2Ffq3pRrG3yet+f63Fp+Sj6sh++cDfCk/QMPHgvu7XYCD+V29GBU0jEy8BqrfDEsbrPpSlNmBVLJWjsKMRwKucmozAA==;24:XDTgmQN53unV3tE+oD5R+PiEneoluVXLGOCi0gCc7eFmIPd6yziwQx2SKD7u9nhOagfW47bQkNpuFb2hNq5lzoKtgroEY/Sy1yCnwhhZ4cM= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;VI1PR0801MB1742;7:rjxpmPSmqw9SORtBWVLVTqPWjn0eHhk0yEqWUWx4DqUj+fIpfxqxLgm+M7gMGX8eSlGu9BWuX0AieWZQSqUNcIHqSDl3StMQ4hoQF+N9yJKKycwxj/UnJMgoOGJJzXI+8vxWyeQkspAa5BM2iy1Tx7LGHi9ChEzoR+SIw3FjALd4vqGhZabk2sojWyJoiE5WzRtkrV8NazPJnd8zoNLuaqLtzRe4O5Szsj54+HjYMHxsdbL3Y5n486ZwtdDq8FdeJhEfK0I65xFkIi6KXG6JvuXGEhFkK9bEVuVpD4qemfKeb1tZXaUVxjE4bIGkRsPQjIWdhNrlUZ+6H2CIYdrsUA==;20:vdkoxe9oNdIqOx9zBTFdchesVrLrgGyTmCDrmZ+mEEQrEsU+XejUDTiBpeRaVlmsB92OaVnHA7xSD2MwUOPJfpjcG43wW372t3Z+pplQ6zsJs4Yc/YH9QFj3eohnmMNjx4I+NPo59wyGaIYX8e4yU/87kJvtC6uHwVsXcFiJuPQ= X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Mar 2017 14:21:24.9704 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0801MB1742 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6854 Lines: 251 This test calls 32-bit mmap() through int 0x80 and checks /proc/self/maps for allocated VMA's address - it should be downer than 4 Gb. Just accessing allocated with mmap pointer will not work, as we could have some VMA placed on the same address as lower 4 bytes of the new mapping. As allocation is top-down by default (unless legacy personality was set), we can expect that mmap() will allocate memory over 4Gb if mmap_base has been computed not correctly. 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 38e0a9ca5d71..959224d6750d 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 sysret_rip +TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip 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.1