From patchwork Thu Mar 3 14:15:38 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ed Schouten X-Patchwork-Id: 8493021 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 882459F8A8 for ; Thu, 3 Mar 2016 14:16:04 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8833F20254 for ; Thu, 3 Mar 2016 14:16:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3FF242022A for ; Thu, 3 Mar 2016 14:16:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757529AbcCCOQA (ORCPT ); Thu, 3 Mar 2016 09:16:00 -0500 Received: from mail-wm0-f47.google.com ([74.125.82.47]:37915 "EHLO mail-wm0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756738AbcCCOP7 (ORCPT ); Thu, 3 Mar 2016 09:15:59 -0500 Received: by mail-wm0-f47.google.com with SMTP id l68so33431967wml.1 for ; Thu, 03 Mar 2016 06:15:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuxi-nl.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=Z1xz1hXZlqmSwQYAH7mx9kvenuWPB431TeSrCik3lYs=; b=g2E7zz763W3j/vrlhCvpLYNr0ltxC94uMOF7hBv3y3OiF3SL/zoxNdbAYCBlgwlZJz Lu75C2B1q7RXAr+aDYLZOWOFHZPdh7LZAWpXxUTRqjhDn/924bRU+uVJetq3oE4NkYcE WlRbg2cy0f4K6wkd/czPU+mDyh7MgjzJ8OciJpw9ahXX+sV84O6g628rxe2zq2yOHUeV 2N2BjOjKhTd1bESUCDd67RpMRlsl1kwKYwJxnsbg2283BuQCfRdZQGWuC/d+MK3Tb6iw dGSNT9+zq1nfgIiZUrqQFxtUL6voaFLTAIKSj5pVh0ijnzedrRdgluHuhsMbvb8MG6MY vUEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=Z1xz1hXZlqmSwQYAH7mx9kvenuWPB431TeSrCik3lYs=; b=lyMhghCz7AFrynC9BiiPZu6Zdz0fkwuMXJMYgorHe+0tShldx3uKbsxLyGVen3/wAF gmuK5gtsCGKJdAJyfo71U1i0MPDREaxQHHp+UTQIAh0Es8fOe3mFZGDr3l2zqKc/7QFx JBc4+kLbp6woUxY1Gyvi7BN0ILdSrx+IgpHdSMUTHHxgyxzhcOHZBRMXSYvAhYwA9X4q IWg/H5qf12xyydaInKv97ro3fteioeH1O1C7152/wfjiXxQwZ3fa0px05NfbXOab3yTx XhleDPK1DEJl2p8GlcSDYuiORYLc7FLQRz2mwWas9FpdaVKZGu2xF5L8drqa03gPR8ga E67g== X-Gm-Message-State: AD7BkJLpS3ieNAJAX+x5O7e+usHXZKQ5b9gPqrNAgvT0R25YgEdfkqgLLxmsAC4L93dGwA== X-Received: by 10.194.83.101 with SMTP id p5mr3264880wjy.141.1457014557768; Thu, 03 Mar 2016 06:15:57 -0800 (PST) Received: from d.dynamic.ziggo.nl (541BCC50.cm-5-4d.dynamic.ziggo.nl. [84.27.204.80]) by smtp.gmail.com with ESMTPSA id i1sm40723262wjs.45.2016.03.03.06.15.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 03 Mar 2016 06:15:57 -0800 (PST) From: Ed Schouten To: linux-fsdevel@vger.kernel.org Cc: Ed Schouten Subject: [PATCH] Let the ELF binfmts test against the OSABI field. Date: Thu, 3 Mar 2016 15:15:38 +0100 Message-Id: <1457014538-1185-1-git-send-email-ed@nuxi.nl> X-Mailer: git-send-email 2.5.0 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP While implementing an alternative binfmt for a pure capability-based runtime environment[1], I noticed that our current binfmts don't test against the OSABI field. This can for example be observed by trying to execute a (statically linked) FreeBSD binary on Linux: $ ./sbin/init zsh: segmentation fault (core dumped) ./sbin/init Introduce a new macro called elf_check_linux_magic() that we can use to validate that an ELF header is suitable for use on Linux, similar to how the existing elf_check_arch() macro validates that an ELF header is suitable for the current architecture. Let this macro match both ELFOSABI_NONE and ELFOSABI_LINUX, as the former is actually used more commonly. This allows people to experiment with custom ELF binfmts without having the standard binfmt taking preference. If we now try to execute our FreeBSD binary we get an error message instead, as no matching binfmt exists: $ ./sbin/init zsh: exec format error: ./sbin/init [1] CloudABI: https://www.youtube.com/watch?v=62cYMmSY2Dc Signed-off-by: Ed Schouten --- fs/binfmt_elf.c | 6 +++--- fs/binfmt_elf_fdpic.c | 2 +- fs/binfmt_em86.c | 2 +- include/linux/elf.h | 9 +++++++++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 7d914c6..95b1ece 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -697,7 +697,7 @@ static int load_elf_binary(struct linux_binprm *bprm) retval = -ENOEXEC; /* First of all, some simple consistency checks */ - if (memcmp(loc->elf_ex.e_ident, ELFMAG, SELFMAG) != 0) + if (!elf_check_linux_magic(&loc->elf_ex)) goto out; if (loc->elf_ex.e_type != ET_EXEC && loc->elf_ex.e_type != ET_DYN) @@ -800,7 +800,7 @@ static int load_elf_binary(struct linux_binprm *bprm) if (elf_interpreter) { retval = -ELIBBAD; /* Not an ELF interpreter */ - if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) + if (!elf_check_linux_magic(&loc->interp_elf_ex)) goto out_free_dentry; /* Verify the interpreter has a valid arch */ if (!elf_check_arch(&loc->interp_elf_ex)) @@ -1122,7 +1122,7 @@ static int load_elf_library(struct file *file) if (retval != sizeof(elf_ex)) goto out; - if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0) + if (!elf_check_linux_magic(&elf_ex)) goto out; /* First of all, some simple consistency checks */ diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index b1adb92..4000005 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -106,7 +106,7 @@ module_exit(exit_elf_fdpic_binfmt); static int is_elf(struct elfhdr *hdr, struct file *file) { - if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0) + if (!elf_check_linux_magic(hdr)) return 0; if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) return 0; diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c index 4905385..fc68231 100644 --- a/fs/binfmt_em86.c +++ b/fs/binfmt_em86.c @@ -32,7 +32,7 @@ static int load_em86(struct linux_binprm *bprm) /* Make sure this is a Linux/Intel ELF executable... */ elf_ex = *((struct elfhdr *)bprm->buf); - if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0) + if (!elf_check_linux_magic(&elf_ex)) return -ENOEXEC; /* First of all, some simple consistency checks */ diff --git a/include/linux/elf.h b/include/linux/elf.h index 20fa8d8..f1ed95b 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -46,6 +46,15 @@ extern Elf64_Dyn _DYNAMIC []; struct file; struct coredump_params; +/* + * Returns true if the ELF header corresponds with a valid ELF file that + * is supposed to be used on Linux. + */ +#define elf_check_linux_magic(hdr) \ + (memcmp((hdr)->e_ident, ELFMAG, SELFMAG) == 0 && \ + ((hdr)->e_ident[EI_OSABI] == ELFOSABI_NONE || \ + (hdr)->e_ident[EI_OSABI] == ELFOSABI_LINUX)) + #ifndef ARCH_HAVE_EXTRA_ELF_NOTES static inline int elf_coredump_extra_notes_size(void) { return 0; } static inline int elf_coredump_extra_notes_write(struct coredump_params *cprm) { return 0; }