From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751607AbdA0VUc (ORCPT ); Fri, 27 Jan 2017 16:20:32 -0500 Received: from mail-db5eur01on0120.outbound.protection.outlook.com ([104.47.2.120]:23264 "EHLO EUR01-DB5-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751812AbdA0VSj (ORCPT ); Fri, 27 Jan 2017 16:18:39 -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: [PATCHv3 5/5] selftests/x86: add test to check compat mmap() return addr Date: Sat, 28 Jan 2017 00:00:29 +0300 Message-ID: <20170127210029.31566-6-dsafonov@virtuozzo.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170127210029.31566-1-dsafonov@virtuozzo.com> References: <20170127210029.31566-1-dsafonov@virtuozzo.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [195.214.232.6] X-ClientProxiedBy: VI1PR07CA0097.eurprd07.prod.outlook.com (10.165.229.151) To DB6PR0801MB1735.eurprd08.prod.outlook.com (10.169.226.150) X-MS-Office365-Filtering-Correlation-Id: 5aa3c8c3-db16-42b8-4bdf-08d446f7945a X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001);SRVR:DB6PR0801MB1735; X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1735;3:8ZHOL0jUOa3ofvLZFBIDMxrZWOSznPnq/tcX4zbznX+sLS0eKJwLs8BxDR0Lm+7FsM9nUd+GHmLd10NhZ7K+RUlserXeJldvPP4rQM9GdC2D7ZQVMFqHKUq3QHXMiOorDUA/bmbV1viawwA8esMdVz46WbwUa0DvBcmLeCGoCBzxHZP+JwcTFGC91Qgp0AMjQAewq4Pg4l+1XN6pdksBrN7L0bb2V+mXxe1RM+pg1/4FA+PFUC8myPS0x/d+01rHHvngePikdnXqNV+2sHQi8A==;25:i8Utvt3iy8aVp9LYACLRW8Dl2oEry/0WjukJiLMcHahCBBtqnpwpiwCEPpNTuk1PJAV0eA2EF6VR2R1ImGD94ROvbXYr4jzZ5trkvyvbS/tVH04FJ4lFlNEd13R5dygkKZF7PkJibJRcsoNrjp6B8a5ydgBPcPiJdDLqSdmHNa7Z7ULAC9uoCS+9dgwT+pBEjQb81CzwMKQt7k/w5lmn4n5BoCvP6z+f0/7JFODcWzqiyEQvCgXc7jzqo++dEr9u/67PChhapj5Fa8e+7MiKYL/sYvvFwZkWsypYDLngoxKsmGrW8Teu77tFNXZsDT0hOv9UZ2vbXslejqUdowQM+R6n4Ub5L+6qzk4LOt1X0bjtN1xjZ5a/6dg+qFEc/XrjzGlOET9/tXY2k2ZOkFdXCiGFyFl5j8vffWIp5Tw9YLS8cvBBXh3Tn6q6wH7V0/Jydd0WgMk8DkAQA6bnIv8+PA== X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1735;31:Y8GgiyJjvDi3ALDqAqQIT7QygAIhD78fncb81a/o7vtbtSuhj+aQuwfVa5jUe1GlycTuOC/MOTmPMHfCTesacVXe+LHpa0yApzqqZjTmxIdPBrPNmbmT2IGP34ny4wk2bXZC7vq22qlKucPXFKH8B2s/aXHK18y0FqPojPcuqL8GfKyHZZ4KGrEqEIlYhLVDUJTSSfyg/AE1ON7PR1TKSkLrrTUxu6Jb1uZtmeB8/DTMuOfOrFk2gq/GgrilMMHU;20:qGlwKWrdTXwhvIisLq4ggs4BTjhNebC9hdMGuC79gcfKEnNh6OLmLFWc7o4dxsCBvUllT/3EYIaeByfA15iq5MjlK+3iv0o14KVHmykymWXHHgjb69DwFng+E+TxiXoGN2T9umtYJi4IGu1sFjiIPXJ/aYqqG0ZnZUXHzLCnfzu0YKK1eY4vi2uMs4cEUsRyFl+2zXlm1swwyhXsWGc7fKqOVoeAajUnis3rY/SNllL5hwG2kHOw1hh5r7ghcp3Z 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)(10201501046)(3002001)(6041248)(20161123562025)(20161123555025)(20161123560025)(20161123564025)(6072148);SRVR:DB6PR0801MB1735;BCL:0;PCL:0;RULEID:;SRVR:DB6PR0801MB1735; X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1735;4:krIp9cCtCwZMvrtSLoGFDHrjZcKlckZU/8rqBRgV/1jjMy2qDaa8fgqxio9N2cE9KkvZmCobJ+ddftccXtybew1eRFFWFC3eNxTxv0qwFbvzmmz0BPJ10bwjKG8M08DU5TL55qlDyQzxtL8Owk+WsYEtxnSmNYuyhJL3G3rNsSWEbtwCWznO32vWcwDiitWxZsue+MWlTDt+CWS0AzlUMZ3Z63w5S24FJfHhO9/1IAYscHc2IGc7E/+emQROxZM6DeFimGyxJ/TxRx8EdYlmtInHR3oc5lGtQlEzxaD3snQxfGl8C5M5f4yw3naMoFf8Wap+O1phgFDeT4b10pl6V6tikMxjvclVTJZvAehOYe8PPCa7LJ/9+KhR31V3ZQa2yvhJbFcRyRaJSSAfuY1ZLM6hHR0IHFU9XE5gWGDJs/f9beqrRDaJpM3mRcyuuB3LJcSw9qfaFG08kThihCT2bs8ScU9sWEoLrUCleva5MWOQEHmxep67JueCU3nDmwxNs08uhsSUuZ6U2xxGcw8OhAEhky0hI5aTPxtBjWUa/MWLNFI1ACagpgD5FUf/4JMkUnvS7qZOUxcxkI29eBoL26IDjlm9jRfddWlO/vLg4Qg3f6JoaF3SfQif7oFOKhTl X-Forefront-PRVS: 0200DDA8BE X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(7916002)(39410400002)(39450400003)(39830400002)(189002)(199003)(81156014)(8676002)(81166006)(50226002)(5660300001)(69596002)(3846002)(5003940100001)(68736007)(6116002)(38730400001)(25786008)(39060400001)(53936002)(6506006)(6512007)(6486002)(54906002)(2950100002)(6666003)(6916009)(110136003)(50466002)(48376002)(36756003)(189998001)(76176999)(50986999)(97736004)(42186005)(86362001)(101416001)(53416004)(92566002)(1076002)(4326007)(47776003)(2906002)(7416002)(305945005)(7736002)(66066001)(105586002)(33646002)(106356001)(2351001)(2004002);DIR:OUT;SFP:1102;SCL:1;SRVR:DB6PR0801MB1735;H:dsafonov.sw.ru;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;DB6PR0801MB1735;23:GyZo30WlvoRuO1ymZVIfrNCSoSBffy0EWGfOVwy?= =?us-ascii?Q?VldbU/fsO2+CoDR6E4GyxcR+UTAjfgQfxRScRYxibTnABfTKtk61NoWC6axw?= =?us-ascii?Q?6XJAxDkzR5a8ZPNnDZxrG+m9mnVzQzDGZ1T+lfEHkxMrXPNXJ67uboTK9h9C?= =?us-ascii?Q?w1XLvEgyt7Hs0hNPtDCFJQqO55PUUuxPC+wsS0ifRzz5Qh3DubSYqTPWX9jn?= =?us-ascii?Q?56VN9pA+YJP2Z68MKxLmSd5a/hDbx8mMK/joYR8CmUuBytZXxNiI6BYAKdrR?= =?us-ascii?Q?aMKj2eSyVjRDA9ExqkyQnn1hAW6eGo9Zus0a9l6/YyywQKGIt7GTpYUlX5nA?= =?us-ascii?Q?bAZVLadw6TIQ3PtqzmRmaoTPK/83RU/xW4w5gEykJz5GqTXqjMOFcBhsmCPf?= =?us-ascii?Q?f/S7HcjJmB1kGteY0GI5a8buH03h3URKJF7uY/FDrqoV44a45V+3hWuWO2Co?= =?us-ascii?Q?Fq+X2kqUnKCbBokmm8yh09kiuKaHgJ3/MAWtdirgESiyDHuqUXhWrvZmEooM?= =?us-ascii?Q?s/TW9J0H6uZmia+8Jfbk8FSDs78TIBxhMNlipT/+SQwen7Bb5HRKzQ7GUzNg?= =?us-ascii?Q?5zSkc8IjzicNLiX/TLHAp02rIsBRbaEMhPQ2eLiTuWitn28iRx6Y5VjnwAzI?= =?us-ascii?Q?x1VbU3yicoc11qV+V49DQJqyaE5TlSrgTIJY2q7kgunNwSCEZcCxAp2WWLe5?= =?us-ascii?Q?ZPNGY9NqEAEJFHwTJYatlG6G8IRlzwPFmQO2qpMK+AG1xxyBkQqCVL/zw0EU?= =?us-ascii?Q?4heTJw36IFJI+qq7DQAzOkO2/gN9SQdEOSfwKr4CXTWgMaZ5VGHT3126fvlY?= =?us-ascii?Q?0wDjdQihLDPWo9NEBXaqC0VtwugSKq//NZzP5YkdQBRMKnItXVlaAmZNcGqX?= =?us-ascii?Q?yxs0VNkJa7ha4Oux5byYuPbU1/fAcU05HrV8tWBY60RGpQuRuz9vXxwA/t8d?= =?us-ascii?Q?N8q2ITaI8ibZYJTECcNpJ7r9Tu+ZmJ2LgYzzgLRPwGxdDD4frWMAPyS9jit8?= =?us-ascii?Q?FV07ck7mOuKBjGkW5/an0aCEicxRJoM3/MJ0Vw/qRlGZdVnLhelPYYwzeY3i?= =?us-ascii?Q?UnS3BwcJIjWl5j1hEG7vh3cb1YX22wtU4LVQa3gNU8tirS7fx7jTGPCXud5c?= =?us-ascii?Q?wDGhM5bWNVrJZ7Cm65M2RieUNuYJzFXCZ4dsMeVJ/bpYVpETMbU2MvEnSave?= =?us-ascii?Q?Js2c1bFX9nmCUKNj0IFEvvEfPQyuuduOA7F2UqPQez7xXrpxcnVrPTaWhky+?= =?us-ascii?Q?TCE56hrhFqptODaDRpD5cRRDpAVVGdPkm/9dyLMEWMBKlPgVCeqjcFD3LBqo?= =?us-ascii?Q?LDDLzesA/JEyf1IrXV+9lTNw=3D?= X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1735;6:ZkWK6EXQYEY9Q9Wt7+G3/1Ts+leNFE9YJohLqofLjJWD66uWon69SlJ8rUGlIn81utzKB3/QZiP4JqqJOMblJ05WTzyuOBAtoWq0x6BIEHw4sd4iP+lcaMaokeJ3dt4uTO1N7NgtYLqpo6FI86feXZD6GXk7NJLaPEW0ZARgU81h3zdhWkKF45t/tkORzuPfz2hAabPGykqyhUWdsGYsY3oS0SKLcQVRE3+wK97n7jH7ZOr9BJn0TICtKTCRU9bm2kInK5p0FA/2GbDrDYot8DpW5dvmGnOwvezUd48FOXUJjgHzjftH/9ah0L3+UMnHCYfKgS20+QiRdFowJjZvsxUMaNXqubp5L8zFonHVZfgalu4ROhEYARAVi4wAI6JMaLOlTcl9qrZete1QVXtgdA45Fkr0k07CLahiq2vbIfM=;5:cVFoHFWyAo5xkbSD5ptc1VAWje0lhNCBwGz630U+67kXSnabTZAhJk/9yNfhLlB8S4eRNDr98Xv5fzzz2eKLRl6eQu9kqq7SV5/9Sus8DMuG1oZJDSMK7uZcm+5SEUNPi8wwLt722M4tgBYr2itVdA==;24:+0ryUwe/TGqKTKAFVFINy7nHWMCninySP3Fix1hZqtZMQhwxYUTw3oImRy0kxtpTOfz3xma+8cap/Gy6SJrGN7JLJplQlqcsh/lmkzIyg5s= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;DB6PR0801MB1735;7:hgORa02Nq3kdaSZW+TJ6OSPovuFW0Hh7eW1zmins26gWCuP6U3PilkLMRRSHIV391Wuv4vePbagIxRr4ZKK78t/f6vKaZWsSIQV+5VSOOqLJSqGR5a2u0YdLCL1GXAWcd5QADmeO5HGINnxntVSiFvo/LcnvZDlUveiECnKD4pI9QwndHQ/Cs22Z4bJSyflR4TKYql2OSxsSLYpW9OmVjpVEcsPvqulvntmZr8uErj2/hRc3xyEpRBvJXItYL7P6YFVPIdrvbQNHGWBSRYUrLtaQ61Bxy4FB50R4DT4MJEUmkb+cNR1OLRryq6uOUhP8QoQAq9v/J16Yq74/m8EH3QTPIEuIXITFZjz2ZH1r/mHaD3+ydHDjQ9TsEA3TxiAtZ0NukBcS2kuKCnZvJPOP/XBqXq/8S3x6cDrdubWDYw1IT8kprj1LW7nidhnR0AAqjUxNcmzW7LLo9/1jScb6TQ==;20:uyF6ui8b4lvm6FkJ0KdWs+dC9oft0wBn0V71E45HoxZw3yM0HTzJAbr2fO/j9mo+2cp53E3N9qdzJmHU2yc4RQw5Piw0/yOUhc76m+zs9ANH0Xw0dIpVnkH7gTOl6pJS4CljHOBmwmL5jzTrHN8WYv5cA7ZDvgJeS+elBaK+OCE= X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jan 2017 21:00:51.2913 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR0801MB1735 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