Received: by 10.223.164.200 with SMTP id h8csp923609wrb; Mon, 6 Nov 2017 01:03:05 -0800 (PST) X-Google-Smtp-Source: ABhQp+T6SgPz23p2t2me+AODddRPsXRZEJ1edSHk2ViO5gRnkz/Zi4d2g3Byx8inOpMOwa67B9ay X-Received: by 10.99.130.74 with SMTP id w71mr14881996pgd.25.1509958985127; Mon, 06 Nov 2017 01:03:05 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1509958985; cv=none; d=google.com; s=arc-20160816; b=hW3o8bZXW8SPWDmt+13QEKjq+ezN6XFHHvze3529nC+y+JAdzAxZZXkxt6ER/usXtd Y3IksBDbxVXIH/cXOPJJP9ziKHwDy8svltcVDKBgYXQ7tCmByujVEIybs/UkokSzGiF5 mWwivcqcEkajc2D/uCw09e5oywYNuOYVlo0hE3uoyK8YighW1qCh0dM0RnRm6WPZ2xK9 adNGEG+/Hn0GFDtCyrHeFZXm1/wJg00+7+7Dz7wel+1xORFr9a+5IQZqkuifW4qmT90l fwvZ0qqRh6HHauMqyCxmjP8McDizxur2R5m8Gp0kHDj9A8Hms+2VvdPAWq5XhXWrTJOS 0YJg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=tIq5+w8xbfhqwng3GAAIgJG/lwo2RaeSaMDerLVjEok=; b=PhPpt9pBnX5orx7N0b7f/fdR4Zj/B1bX54/fm9FhUnEUvwcCnNVnSCxju9K0ka7WXy cRy+msxjwzm/fAKx7c568yt7KxyqJZfNQn6AuGPbAcMSjISdqh3o5yDhg9O1RBDq2KFD Y1UnNghOG8w07juwykoZFzbRTG8LpnEM2LSgncUf0eqtvXBLR6oyXEEk2v7SUZWbfhhp rWnXSkyDKOPonrXy0YQzyKHdKSFthhL7oatd+vkCL026mQjDEFGgRsotqzp24Tj2BSte jK5h/UP7pZDZg+rKn6mEp5wyziDYB6kAxAXWNs9cLUeJGRG+CbU9RPJZD3jtS5A8SpV2 8nYA== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=RPvQYzLG; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w8si11039653pgc.769.2017.11.06.01.02.51; Mon, 06 Nov 2017 01:03:05 -0800 (PST) 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=fail header.i=@gmail.com header.s=20161025 header.b=RPvQYzLG; 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752755AbdKFJAw (ORCPT + 98 others); Mon, 6 Nov 2017 04:00:52 -0500 Received: from mail-qk0-f193.google.com ([209.85.220.193]:51042 "EHLO mail-qk0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752344AbdKFJAr (ORCPT ); Mon, 6 Nov 2017 04:00:47 -0500 Received: by mail-qk0-f193.google.com with SMTP id o187so10012069qke.7; Mon, 06 Nov 2017 01:00:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=tIq5+w8xbfhqwng3GAAIgJG/lwo2RaeSaMDerLVjEok=; b=RPvQYzLGlr3ow0TtVWBWN2taqEWB5Z85eFEIUYFK+wtD5EUaLL4viktV+H7ANCnrE9 JyXtD4Wnb8KNJQuaj8NsCYM+H5hIH7xW1pnMwi6EEWiCTuPnkxrovoNpz/7X5RdQAO9o QmO85NIR9q8MyEbWhbzdrIoS5pg76kghwXZBFXnYRhV6oxdeFWGofkwsFBrAenOU0D4v 4yGpcNctSAYs1Ty5WxK6WshLqxxotPBCNmb5AqMtvh6TY4YMjALJ0rHBEiMnpuu8XApb V3rXzEPwxsF6UcbW9d1udoQmwcVYIhhIaReaebXBMGYQqfwUOR2FmHCS2D6lWj3upsBb IRqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=tIq5+w8xbfhqwng3GAAIgJG/lwo2RaeSaMDerLVjEok=; b=tVcIcr8mWzMqpYzt3Wu+/CaMX5DQVhg9QIAyaof5i1+2MoTZwzb5DQlLZ04GaOE1q/ WyujqYkwjFdk3Qwk5ZKljrz+Zjr3pWJ014G3uDt+gXD6EQQyQ7Iz3b3qDfXnSh3iUdlf kLLzDKU/LaUREyGEZV/eao7AgKnbmSNQbPrT9EjX+SQvl/VbV7JW472dS7Vg1P9DoUQi LfUc+6QWA59KEj5d1X74Ns+OrP+VWJYm+bq8n1He+uQnSEpiCDPxe0C38b855vVkgVnZ V/63QzpYV6oSGLlSXpS6YqvFhX9sNEBIgw/Kui1L8CfMDLuCKI7JUmNqyAo1yxO1xaFI ST4g== X-Gm-Message-State: AJaThX6y9H8zj1lxWtXalzStqSdCCmO7FdUqB2uSixLb8nS2HgYh43+F amXbHT162yGYFDOtJPy5wJI= X-Received: by 10.55.214.25 with SMTP id t25mr2253561qki.225.1509958845242; Mon, 06 Nov 2017 01:00:45 -0800 (PST) Received: from localhost.localdomain (50-39-103-96.bvtn.or.frontiernet.net. [50.39.103.96]) by smtp.gmail.com with ESMTPSA id r26sm8001094qki.42.2017.11.06.01.00.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 06 Nov 2017 01:00:44 -0800 (PST) From: Ram Pai To: mpe@ellerman.id.au, mingo@redhat.com, akpm@linux-foundation.org, corbet@lwn.net, arnd@arndb.de Cc: linuxppc-dev@lists.ozlabs.org, linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, dave.hansen@intel.com, benh@kernel.crashing.org, paulus@samba.org, khandual@linux.vnet.ibm.com, aneesh.kumar@linux.vnet.ibm.com, bsingharora@gmail.com, hbabu@us.ibm.com, mhocko@kernel.org, bauerman@linux.vnet.ibm.com, ebiederm@xmission.com, linuxram@us.ibm.com Subject: [PATCH v9 51/51] selftests/powerpc: Add core file test for Protection Key register Date: Mon, 6 Nov 2017 00:57:43 -0800 Message-Id: <1509958663-18737-52-git-send-email-linuxram@us.ibm.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1509958663-18737-1-git-send-email-linuxram@us.ibm.com> References: <1509958663-18737-1-git-send-email-linuxram@us.ibm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Thiago Jung Bauermann This test verifies that the AMR is being written to a process' core file. Signed-off-by: Thiago Jung Bauermann --- tools/testing/selftests/powerpc/ptrace/Makefile | 2 +- tools/testing/selftests/powerpc/ptrace/core-pkey.c | 438 ++++++++++++++++++++ 2 files changed, 439 insertions(+), 1 deletions(-) create mode 100644 tools/testing/selftests/powerpc/ptrace/core-pkey.c diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index fd896b2..ca25fda 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ - ptrace-tm-spd-vsx ptrace-tm-spr ptrace-pkey + ptrace-tm-spd-vsx ptrace-tm-spr ptrace-pkey core-pkey include ../../lib.mk diff --git a/tools/testing/selftests/powerpc/ptrace/core-pkey.c b/tools/testing/selftests/powerpc/ptrace/core-pkey.c new file mode 100644 index 0000000..2328f8c --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/core-pkey.c @@ -0,0 +1,438 @@ +/* + * Ptrace test for Memory Protection Key registers + * + * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. + * Copyright (C) 2017 IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ptrace.h" + +#ifndef __NR_pkey_alloc +#define __NR_pkey_alloc 384 +#endif + +#ifndef __NR_pkey_free +#define __NR_pkey_free 385 +#endif + +#ifndef NT_PPC_PKEY +#define NT_PPC_PKEY 0x110 +#endif + +#ifndef PKEY_DISABLE_EXECUTE +#define PKEY_DISABLE_EXECUTE 0x4 +#endif + +#define AMR_BITS_PER_PKEY 2 +#define PKEY_REG_BITS (sizeof(u64) * 8) +#define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey + 1) * AMR_BITS_PER_PKEY)) + +#define CORE_FILE_LIMIT (5 * 1024 * 1024) /* 5 MB should be enough */ + +static const char core_pattern_file[] = "/proc/sys/kernel/core_pattern"; + +static const char user_write[] = "[User Write (Running)]"; +static const char core_read_running[] = "[Core Read (Running)]"; + +/* Information shared between the parent and the child. */ +struct shared_info { + /* AMR value the parent expects to read in the core file. */ + unsigned long amr; + + /* IAMR value the parent expects to read from the child. */ + unsigned long iamr; + + /* UAMOR value the parent expects to read from the child. */ + unsigned long uamor; + + /* When the child crashed. */ + time_t core_time; +}; + +static int sys_pkey_alloc(unsigned long flags, unsigned long init_access_rights) +{ + return syscall(__NR_pkey_alloc, flags, init_access_rights); +} + +static int sys_pkey_free(int pkey) +{ + return syscall(__NR_pkey_free, pkey); +} + +static int increase_core_file_limit(void) +{ + struct rlimit rlim; + int ret; + + ret = getrlimit(RLIMIT_CORE, &rlim); + FAIL_IF(ret); + + if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < CORE_FILE_LIMIT) { + rlim.rlim_cur = CORE_FILE_LIMIT; + + if (rlim.rlim_max != RLIM_INFINITY && + rlim.rlim_max < CORE_FILE_LIMIT) + rlim.rlim_max = CORE_FILE_LIMIT; + + ret = setrlimit(RLIMIT_CORE, &rlim); + FAIL_IF(ret); + } + + ret = getrlimit(RLIMIT_FSIZE, &rlim); + FAIL_IF(ret); + + if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < CORE_FILE_LIMIT) { + rlim.rlim_cur = CORE_FILE_LIMIT; + + if (rlim.rlim_max != RLIM_INFINITY && + rlim.rlim_max < CORE_FILE_LIMIT) + rlim.rlim_max = CORE_FILE_LIMIT; + + ret = setrlimit(RLIMIT_FSIZE, &rlim); + FAIL_IF(ret); + } + + return TEST_PASS; +} + +static int child(struct shared_info *info) +{ + bool disable_execute = true; + int pkey1, pkey2, pkey3; + int *ptr, ret; + + ret = increase_core_file_limit(); + FAIL_IF(ret); + + /* Get some pkeys so that we can change their bits in the AMR. */ + pkey1 = sys_pkey_alloc(0, PKEY_DISABLE_EXECUTE); + if (pkey1 < 0) { + pkey1 = sys_pkey_alloc(0, 0); + FAIL_IF(pkey1 < 0); + + disable_execute = false; + } + + pkey2 = sys_pkey_alloc(0, 0); + FAIL_IF(pkey2 < 0); + + pkey3 = sys_pkey_alloc(0, 0); + FAIL_IF(pkey3 < 0); + + info->amr = 3ul << pkeyshift(pkey1) | 2ul << pkeyshift(pkey2); + + if (disable_execute) + info->iamr = 1ul << pkeyshift(pkey1); + else + info->iamr = 0; + + info->uamor = 3ul << pkeyshift(pkey1) | 3ul << pkeyshift(pkey2); + + printf("%-30s AMR: %016lx pkey1: %d pkey2: %d pkey3: %d\n", + user_write, info->amr, pkey1, pkey2, pkey3); + + mtspr(SPRN_AMR, info->amr); + + /* + * We won't use pkey3. This tests whether the kernel restores the UAMOR + * permissions after a key is freed. + */ + sys_pkey_free(pkey3); + + info->core_time = time(NULL); + + /* Crash. */ + ptr = 0; + *ptr = 1; + + /* Shouldn't get here. */ + FAIL_IF(true); + + return TEST_FAIL; +} + +/* Return file size if filename exists and pass sanity check, or zero if not. */ +static off_t try_core_file(const char *filename, struct shared_info *info, + pid_t pid) +{ + struct stat buf; + int ret; + + ret = stat(filename, &buf); + if (ret == -1) + return TEST_FAIL; + + /* Make sure we're not using a stale core file. */ + return buf.st_mtime >= info->core_time ? buf.st_size : TEST_FAIL; +} + +static Elf64_Nhdr *next_note(Elf64_Nhdr *nhdr) +{ + return (void *) nhdr + sizeof(*nhdr) + + __ALIGN_KERNEL(nhdr->n_namesz, 4) + + __ALIGN_KERNEL(nhdr->n_descsz, 4); +} + +static int check_core_file(struct shared_info *info, Elf64_Ehdr *ehdr, + off_t core_size) +{ + unsigned long *regs; + Elf64_Phdr *phdr; + Elf64_Nhdr *nhdr; + size_t phdr_size; + void *p = ehdr, *note; + int ret; + + ret = memcmp(ehdr->e_ident, ELFMAG, SELFMAG); + FAIL_IF(ret); + + FAIL_IF(ehdr->e_type != ET_CORE); + FAIL_IF(ehdr->e_machine != EM_PPC64); + FAIL_IF(ehdr->e_phoff == 0 || ehdr->e_phnum == 0); + + /* + * e_phnum is at most 65535 so calculating the size of the + * program header cannot overflow. + */ + phdr_size = sizeof(*phdr) * ehdr->e_phnum; + + /* Sanity check the program header table location. */ + FAIL_IF(ehdr->e_phoff + phdr_size < ehdr->e_phoff); + FAIL_IF(ehdr->e_phoff + phdr_size > core_size); + + /* Find the PT_NOTE segment. */ + for (phdr = p + ehdr->e_phoff; + (void *) phdr < p + ehdr->e_phoff + phdr_size; + phdr += ehdr->e_phentsize) + if (phdr->p_type == PT_NOTE) + break; + + FAIL_IF((void *) phdr >= p + ehdr->e_phoff + phdr_size); + + /* Find the NT_PPC_PKEY note. */ + for (nhdr = p + phdr->p_offset; + (void *) nhdr < p + phdr->p_offset + phdr->p_filesz; + nhdr = next_note(nhdr)) + if (nhdr->n_type == NT_PPC_PKEY) + break; + + FAIL_IF((void *) nhdr >= p + phdr->p_offset + phdr->p_filesz); + FAIL_IF(nhdr->n_descsz == 0); + + p = nhdr; + note = p + sizeof(*nhdr) + __ALIGN_KERNEL(nhdr->n_namesz, 4); + + regs = (unsigned long *) note; + + printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n", + core_read_running, regs[0], regs[1], regs[2]); + + FAIL_IF(regs[0] != info->amr); + FAIL_IF(regs[1] != info->iamr); + FAIL_IF(regs[2] != info->uamor); + + return TEST_PASS; +} + +static int parent(struct shared_info *info, pid_t pid) +{ + char *filenames, *filename[3]; + int fd, i, ret, status; + off_t core_size; + void *core; + + ret = wait(&status); + if (ret != pid) { + printf("Child's exit status not captured\n"); + return TEST_FAIL; + } else if (!WIFSIGNALED(status) || !WCOREDUMP(status)) { + printf("Child didn't dump core\n"); + return TEST_FAIL; + } + + /* Construct array of core file names to try. */ + + filename[0] = filenames = malloc(PATH_MAX); + if (!filenames) { + perror("Error allocating memory"); + return TEST_FAIL; + } + + ret = snprintf(filename[0], PATH_MAX, "core-pkey.%d", pid); + if (ret < 0 || ret >= PATH_MAX) { + ret = TEST_FAIL; + goto out; + } + + filename[1] = filename[0] + ret + 1; + ret = snprintf(filename[1], PATH_MAX - ret - 1, "core.%d", pid); + if (ret < 0 || ret >= PATH_MAX - ret - 1) { + ret = TEST_FAIL; + goto out; + } + filename[2] = "core"; + + for (i = 0; i < 3; i++) { + core_size = try_core_file(filename[i], info, pid); + if (core_size != TEST_FAIL) + break; + } + + if (i == 3) { + printf("Couldn't find core file\n"); + ret = TEST_FAIL; + goto out; + } + + fd = open(filename[i], O_RDONLY); + if (fd == -1) { + perror("Error opening core file"); + ret = TEST_FAIL; + goto out; + } + + core = mmap(NULL, core_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (core == (void *) -1) { + perror("Error mmaping core file"); + ret = TEST_FAIL; + goto out; + } + + ret = check_core_file(info, core, core_size); + + munmap(core, core_size); + close(fd); + unlink(filename[i]); + + out: + free(filenames); + + return ret; +} + +static int write_core_pattern(const char *core_pattern) +{ + size_t len = strlen(core_pattern), ret; + FILE *f; + + f = fopen(core_pattern_file, "w"); + if (!f) { + perror("Error writing to core_pattern file"); + return TEST_FAIL; + } + + ret = fwrite(core_pattern, 1, len, f); + fclose(f); + if (ret != len) { + perror("Error writing to core_pattern file"); + return TEST_FAIL; + } + + return TEST_PASS; +} + +static int setup_core_pattern(char **core_pattern_, bool *changed_) +{ + FILE *f; + char *core_pattern; + int ret; + + core_pattern = malloc(PATH_MAX); + if (!core_pattern) { + perror("Error allocating memory"); + return TEST_FAIL; + } + + f = fopen(core_pattern_file, "r"); + if (!f) { + perror("Error opening core_pattern file"); + ret = TEST_FAIL; + goto out; + } + + ret = fread(core_pattern, 1, PATH_MAX, f); + fclose(f); + if (!ret) { + perror("Error reading core_pattern file"); + ret = TEST_FAIL; + goto out; + } + + /* Check whether we can predict the name of the core file. */ + if (!strcmp(core_pattern, "core") || !strcmp(core_pattern, "core.%p")) + *changed_ = false; + else { + ret = write_core_pattern("core-pkey.%p"); + if (ret) + goto out; + + *changed_ = true; + } + + *core_pattern_ = core_pattern; + ret = TEST_PASS; + + out: + if (ret) + free(core_pattern); + + return ret; +} + +static int core_pkey(void) +{ + char *core_pattern; + bool changed_core_pattern; + struct shared_info *info; + int shm_id; + int ret; + pid_t pid; + + ret = setup_core_pattern(&core_pattern, &changed_core_pattern); + if (ret) + return ret; + + shm_id = shmget(IPC_PRIVATE, sizeof(*info), 0777 | IPC_CREAT); + info = shmat(shm_id, NULL, 0); + + pid = fork(); + if (pid < 0) { + perror("fork() failed"); + ret = TEST_FAIL; + } else if (pid == 0) + ret = child(info); + else + ret = parent(info, pid); + + shmdt(info); + + if (pid) { + shmctl(shm_id, IPC_RMID, NULL); + + if (changed_core_pattern) + write_core_pattern(core_pattern); + } + + free(core_pattern); + + return ret; +} + +int main(int argc, char *argv[]) +{ + return test_harness(core_pkey, "core_pkey"); +} -- 1.7.1 From 1583204000372725963@xxx Sun Nov 05 05:49:52 +0000 2017 X-GM-THRID: 1583204000372725963 X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread