From patchwork Mon Sep 26 14:22:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Janis Danisevskis X-Patchwork-Id: 9350775 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 748C3607D6 for ; Mon, 26 Sep 2016 14:27:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 62DBC28AE1 for ; Mon, 26 Sep 2016 14:27:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5746628AFF; Mon, 26 Sep 2016 14:27:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-3.6 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RCVD_IN_SORBS_SPAM,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from emsm-gh1-uea11.nsa.gov (smtp.nsa.gov [8.44.101.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 199C728AE1 for ; Mon, 26 Sep 2016 14:27:06 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.30,400,1470700800"; d="scan'208";a="19545556" IronPort-PHdr: =?us-ascii?q?9a23=3A6TtE0R9Bppqtu/9uRHKM819IXTAuvvDOBiVQ1KB8?= =?us-ascii?q?1escTK2v8tzYMVDF4r011RmSDN+dsqkP1buempujcFRI2YyGvnEGfc4EfD4+ou?= =?us-ascii?q?JSoTYdBtWYA1bwNv/gYn9yNs1DUFh44yPzahANS47AblHf6ke/8SQVUk2mc1Ek?= =?us-ascii?q?fKKsQcWM3oye7KObw9XreQJGhT6wM/tZDS6dikHvjPQQmpZoMa0ryxHE8TNicu?= =?us-ascii?q?VSwn50dxrIx06vrvqq+NZf1wgY+7d4r48TZ579Zbg1QYZVBzU+aSh1uJWq5lH/?= =?us-ascii?q?Sl6U638dVHgGugZZCAjCqhfhV9H+tTW+/vFw0S+WJ8r3QfUwWC++x7t6Qx/vzi?= =?us-ascii?q?EcPng293+Twtd8l4pHsRmhoFp52IeSb4aLcLJ8YajUZ89AbXZQVcZWESpaC8Wz?= =?us-ascii?q?aJVLR+gNNOBZtKHyoFwBqRb4Dg6pV831zTodpHbw3LZy/+0nEBrLwhcjHslG5H?= =?us-ascii?q?bYpdP0L48bV+yvy6jEiz7EaqUFin/G9IHUf0V58rm3VrVqfJ+KkUQ=3D?= X-IPAS-Result: =?us-ascii?q?A2GmBACnL+lX/wHyM5BdGwEBAQMBAQEJAQEBFwEBBAEBCgE?= =?us-ascii?q?BgxIBAQEBAR6BRQ67Ah2HYkwBAQEBAQEBAQIBAlsngjIEAwMVBTk8AQEBAQEBI?= =?us-ascii?q?wINYQEEAg8VEwYBAQwgCwECAwkCFwUkCAgDAS0DAQUBCwMVBwsFGAQBiCmkCoE?= =?us-ascii?q?yPjKKVoUwAQEFh3kMARwIEIQXghCIahEBhV0dmXuPaolWJYVuSI5dMYERVIMLD?= =?us-ascii?q?hyBUXGFR3iBJwEBAQ?= Received: from unknown (HELO tarius.tycho.ncsc.mil) ([144.51.242.1]) by emsm-gh1-uea11.nsa.gov with ESMTP; 26 Sep 2016 14:26:42 +0000 Received: from prometheus.infosec.tycho.ncsc.mil (prometheus [192.168.25.40]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id u8QEQISw025112; Mon, 26 Sep 2016 10:26:24 -0400 Received: from tarius.tycho.ncsc.mil (tarius.infosec.tycho.ncsc.mil [144.51.242.1]) by prometheus.infosec.tycho.ncsc.mil (8.15.2/8.15.2) with ESMTP id u8QENCr3252927 for ; Mon, 26 Sep 2016 10:23:12 -0400 Received: from goalie.tycho.ncsc.mil (goalie [144.51.242.250]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id u8QENCOe024768 for ; Mon, 26 Sep 2016 10:23:12 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A1CuAADcLulXgCtSfUpdHAEBBAEBCgEBgz0BAQEBAYFjDrZzhBOGHoFdTAECAQEBAQECEwEBCQsLCReFFQEVFRkBATcBLGgBBQEOFRIiiCmkBYEyPjKKVoUwAQEFiAApCBCEF4IQi2QLgmodmXuPaolWhhNIjl0xgRGDXw4cgVFxh2YBAQE X-IPAS-Result: A1CuAADcLulXgCtSfUpdHAEBBAEBCgEBgz0BAQEBAYFjDrZzhBOGHoFdTAECAQEBAQECEwEBCQsLCReFFQEVFRkBATcBLGgBBQEOFRIiiCmkBYEyPjKKVoUwAQEFiAApCBCEF4IQi2QLgmodmXuPaolWhhNIjl0xgRGDXw4cgVFxh2YBAQE X-IronPort-AV: E=Sophos;i="5.30,400,1470715200"; d="scan'208";a="5728777" Received: from emsm-gh1-uea10.corp.nsa.gov (HELO emsm-gh1-uea10.nsa.gov) ([10.208.41.36]) by goalie.tycho.ncsc.mil with ESMTP; 26 Sep 2016 10:23:01 -0400 IronPort-PHdr: =?us-ascii?q?9a23=3AfUYuHBTJD+aeO+RO64vP/EaLAtpsv+yvbD5Q0YIu?= =?us-ascii?q?jvd0So/mwa65YBON2/xhgRfzUJnB7Loc0qyN4vqmADdLv8fJmUtBWaQEbwUCh8?= =?us-ascii?q?QSkl5oK+++Imq/EsTXaTcnFt9JTl5v8iLzG0FUHMHjew+a+SXqvnYsExnyfTB4?= =?us-ascii?q?Ov7yUtaLyZ/mjabroNaNMk1hv3mUWftKNhK4rAHc5IE9oLBJDeIP8CbPuWZCYO?= =?us-ascii?q?9MxGlldhq5lhf44dqsrtY4q3wD88Qa8NRcXKnAcq85VeYQTGh+cjN92Mq+rhTH?= =?us-ascii?q?TA2S9lMAQ24WlVxOGAGD4xbkGt/qvyL8uvB62SXfOcztUZgoSD+i6OFtUxauhy?= =?us-ascii?q?AZc3Yi/Hr/lt17jKUdpgmo4RN43cqcYp6ePeBiJIvBbNgaQixHRc8XWCtfRsu+?= =?us-ascii?q?Y4IJDvEpMuFfoI3w4VAJqEiQHw6pUcHmzD5TzlP/26wh3vo6EgDdlFgiE9sIsW?= =?us-ascii?q?/8pdP5LqATXaa+y6yenmaLVO9fxTqosNuASRsmu/zZAep9?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0H3AQAzLulXgCtSfUpdHAEBBAEBCgEBF?= =?us-ascii?q?wEBBAEBCgEBgxIBAQEBAYFjDrZzhBOGHoFdTAEBAQEBAQEBAgECEAEBCQsLCRc?= =?us-ascii?q?xgjIKGjk8AQEBAQEBIwINYQEVFRkBATcBLGgBBQEOFRIiiCmkBYEyPjKKVoUwA?= =?us-ascii?q?QEFiAApCBCEF4IQi2QLgmodmXuPaolWhhNIjl0xgRGDXw4cgVFxh2YBAQE?= X-IPAS-Result: =?us-ascii?q?A0H3AQAzLulXgCtSfUpdHAEBBAEBCgEBFwEBBAEBCgEBgxI?= =?us-ascii?q?BAQEBAYFjDrZzhBOGHoFdTAEBAQEBAQEBAgECEAEBCQsLCRcxgjIKGjk8AQEBA?= =?us-ascii?q?QEBIwINYQEVFRkBATcBLGgBBQEOFRIiiCmkBYEyPjKKVoUwAQEFiAApCBCEF4I?= =?us-ascii?q?Qi2QLgmodmXuPaolWhhNIjl0xgRGDXw4cgVFxh2YBAQE?= X-IronPort-AV: E=Sophos;i="5.30,400,1470700800"; d="scan'208";a="17962184" Received: from mail-wm0-f43.google.com ([74.125.82.43]) by emsm-gh1-uea10.nsa.gov with ESMTP/TLS/AES128-GCM-SHA256; 26 Sep 2016 14:22:55 +0000 Received: by mail-wm0-f43.google.com with SMTP id l132so155150416wmf.0 for ; Mon, 26 Sep 2016 07:22:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=android.com; s=20120917; h=from:to:cc:subject:date:message-id; bh=MXWEviwDsPDB0UCJ6ClB6e2H/aGLeZFTKrdySWiaYWg=; b=RFwfUo5/UBhENaRLRujjNwQUMJb62tbZNgcW9XXLZ1rQuzqNKXxEb9jksPfdz9ViYi d/Df5yTwXS1sn2QmeuO+vTEvsiM9PkQmZpczQElaUgIcryZpKgvwrwxq1kkMrA7MeGdy d9cAORdCbldS3R2zP42NJWLG4Q7R4lv+EJn9VA2vWusq/Xwc2oipuXdH0Ro5pQ1Bgp9X YkaFP/HwZKO21365hl4ANgZNGy2cM+EJE8dedaED799ahAXn0wbn3yPgPNwB8kDnw8tZ EKPtDg4f/JkzlNCISzhRFOZLCE1BM0M8dq11qhF0xT2TUnK9HlocUu919DjuTx6zhvQe g4Uw== 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=MXWEviwDsPDB0UCJ6ClB6e2H/aGLeZFTKrdySWiaYWg=; b=MA7YFdGgI39YpotRSKMIcsvJiB/OATTMHsEe8tZoV4rCpPiCSuLkv1A0RyYWxO5Odz UlIb6gDw+m1xbctmqt+6DQ+gU1zIbt5k7KtMyZqZ02+dfqpUk0ZIyxWFM/WIRakkwItf 0+B91ug01rnHoPpEFazr18jBEDLpjnLd8Ds8raj5rojoRXrNWgkMjora1OuZ4pQ1k9JM 6tZqqW7buf9yJ8Sh0U/e4UyvbMXe0D79R8Ehd0CRH20Gqf/jHfs1s7M6c+mbjdqnlbsP Hutc9A9pD/TXtphFYOMVapOZZC4taIkbVVZru565MdSNGQ1vW0U27NZyLrdhHJ8OSvSp 92Vg== X-Gm-Message-State: AA6/9RnnGLMqurB43SgyA4Zgw3vZFyuRqB+pbEf5HC9lwO51Tg8qroMQw1fzr7zalCCrSg== X-Received: by 10.28.143.82 with SMTP id r79mr13665392wmd.7.1474899773573; Mon, 26 Sep 2016 07:22:53 -0700 (PDT) Received: from jdanis.lon.corp.google.com ([100.120.40.90]) by smtp.gmail.com with ESMTPSA id o2sm22677563wjo.3.2016.09.26.07.22.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 26 Sep 2016 07:22:52 -0700 (PDT) From: Janis Danisevskis To: selinux@tycho.nsa.gov, seandroid-list@tycho.nsa.gov, sds@tycho.nsa.gov, jwcart2@tycho.nsa.gov, jdanis@google.com Subject: [PATCH 1/3] libselinux: Add architecture string to file_context.bin Date: Mon, 26 Sep 2016 15:22:34 +0100 Message-Id: <1474899756-93610-1-git-send-email-jdanis@android.com> X-Mailer: git-send-email 2.8.0.rc3.226.g39d4020 X-Mailman-Approved-At: Mon, 26 Sep 2016 10:24:56 -0400 X-BeenThere: selinux@tycho.nsa.gov X-Mailman-Version: 2.1.20 Precedence: list List-Id: "Security-Enhanced Linux \(SELinux\) mailing list" List-Post: List-Help: Cc: Janis Danisevskis MIME-Version: 1.0 Errors-To: selinux-bounces@tycho.nsa.gov Sender: "Selinux" X-Virus-Scanned: ClamAV using ClamSMTP Serialized precompiled regular expressins are architecture dependent when using PCRE2. This patch - bumps the SELINUX_COMPILED_FCONTEXT version to 5 and - adds a field to the output indicating the architecture compatibility. libselinux can cope with an architecture mismatch by ignoring the precompiled data in the input file and recompiling the regular expressions at runtime. It can also load older versions of file_contexts.bin if they where built with sefcontext_compile using the exact same version of the pcre1/2 as selinux. Signed-off-by: Janis Danisevskis --- libselinux/src/label_file.c | 44 +++++++++++++++++++++++++++++- libselinux/src/label_file.h | 4 ++- libselinux/src/regex.c | 50 ++++++++++++++++++++++++++++++++--- libselinux/src/regex.h | 15 ++++++++++- libselinux/utils/sefcontext_compile.c | 13 +++++++++ 5 files changed, 120 insertions(+), 6 deletions(-) diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c index 7156825..9abc1d6 100644 --- a/libselinux/src/label_file.c +++ b/libselinux/src/label_file.c @@ -126,6 +126,8 @@ static int load_mmap(FILE *fp, size_t len, struct selabel_handle *rec, uint32_t i, magic, version; uint32_t entry_len, stem_map_len, regex_array_len; const char *reg_version; + const char *reg_arch; + char reg_arch_matches = 1; mmap_area = malloc(sizeof(*mmap_area)); if (!mmap_area) { @@ -159,6 +161,10 @@ static int load_mmap(FILE *fp, size_t len, struct selabel_handle *rec, if (!reg_version) return -1; + reg_arch = regex_arch_string(); + if (!reg_arch) + return -1; + if (version >= SELINUX_COMPILED_FCONTEXT_PCRE_VERS) { len = strlen(reg_version); @@ -188,7 +194,43 @@ static int load_mmap(FILE *fp, size_t len, struct selabel_handle *rec, return -1; } free(str_buf); + + if (version >= SELINUX_COMPILED_FCONTEXT_REGEX_ARCH) { + len = strlen(reg_arch); + + rc = next_entry(&entry_len, mmap_area, + sizeof(uint32_t)); + if (rc < 0) + return -1; + + /* Check arch string lengths */ + if (len != entry_len) { + /* + * Skip the entry and conclude that we have + * a mismatch, which is not fatal. + */ + next_entry(NULL, mmap_area, entry_len); + reg_arch_matches = 0; + goto end_arch_check; + } + + /* Check if arch string mismatch */ + str_buf = malloc(entry_len + 1); + if (!str_buf) + return -1; + + rc = next_entry(str_buf, mmap_area, entry_len); + if (rc < 0) { + free(str_buf); + return -1; + } + + str_buf[entry_len] = '\0'; + reg_arch_matches = strcmp(str_buf, reg_arch) == 0; + free(str_buf); + } } +end_arch_check: /* allocate the stems_data array */ rc = next_entry(&stem_map_len, mmap_area, sizeof(uint32_t)); @@ -349,7 +391,7 @@ static int load_mmap(FILE *fp, size_t len, struct selabel_handle *rec, spec->prefix_len = prefix_len; } - rc = regex_load_mmap(mmap_area, &spec->regex); + rc = regex_load_mmap(mmap_area, &spec->regex, reg_arch_matches); if (rc < 0) goto out; diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h index 88f4294..00c0a5c 100644 --- a/libselinux/src/label_file.h +++ b/libselinux/src/label_file.h @@ -24,8 +24,10 @@ #define SELINUX_COMPILED_FCONTEXT_PCRE_VERS 2 #define SELINUX_COMPILED_FCONTEXT_MODE 3 #define SELINUX_COMPILED_FCONTEXT_PREFIX_LEN 4 +#define SELINUX_COMPILED_FCONTEXT_REGEX_ARCH 5 -#define SELINUX_COMPILED_FCONTEXT_MAX_VERS SELINUX_COMPILED_FCONTEXT_PREFIX_LEN +#define SELINUX_COMPILED_FCONTEXT_MAX_VERS \ + SELINUX_COMPILED_FCONTEXT_REGEX_ARCH /* A file security context specification. */ struct spec { diff --git a/libselinux/src/regex.c b/libselinux/src/regex.c index 750088e..a3b427b 100644 --- a/libselinux/src/regex.c +++ b/libselinux/src/regex.c @@ -7,6 +7,44 @@ #include "label_file.h" #ifdef USE_PCRE2 +#define REGEX_ARCH_SIZE_T PCRE2_SIZE +#else +#define REGEX_ARCH_SIZE_T size_t +#endif + +#ifndef __BYTE_ORDER__ +#error __BYTE_ORDER__ not defined. Unable to determine endianness. +#endif + +#ifdef USE_PCRE2 +char const *regex_arch_string(void) +{ + static char arch_string_buffer[32]; + static char const *arch_string = ""; + char const *endianness = NULL; + int rc; + + if (arch_string[0] == '\0') { + if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + endianness = "el"; + else if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + endianness = "eb"; + + if (!endianness) + return NULL; + + rc = snprintf(arch_string_buffer, sizeof(arch_string_buffer), + "%zu-%zu-%s", sizeof(void *), + sizeof(REGEX_ARCH_SIZE_T), + endianness); + if (rc < 0) + abort(); + + arch_string = &arch_string_buffer[0]; + } + return arch_string; +} + struct regex_data { pcre2_code *regex; /* compiled regular expression */ /* @@ -56,7 +94,8 @@ char const *regex_version(void) return version_buf; } -int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex) +int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex, + int do_load_precompregex) { int rc; uint32_t entry_len; @@ -65,7 +104,7 @@ int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex) if (rc < 0) return -1; - if (entry_len) { + if (entry_len && do_load_precompregex) { /* * this should yield exactly one because we store one pattern at * a time @@ -195,6 +234,10 @@ int regex_cmp(struct regex_data *regex1, struct regex_data *regex2) } #else // !USE_PCRE2 +char const *regex_arch_string(void) +{ + return "N/A"; +} /* Prior to version 8.20, libpcre did not have pcre_free_study() */ #if (PCRE_MAJOR < 8 || (PCRE_MAJOR == 8 && PCRE_MINOR < 20)) @@ -247,7 +290,8 @@ char const *regex_version(void) return pcre_version(); } -int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex) +int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex, + int unused __attribute__((unused))) { int rc; uint32_t entry_len; diff --git a/libselinux/src/regex.h b/libselinux/src/regex.h index 810b3c5..186c5ec 100644 --- a/libselinux/src/regex.h +++ b/libselinux/src/regex.h @@ -34,6 +34,16 @@ struct regex_error_data { struct mmap_area; /** + * regex_arch_string return a string that represents the pointer width, the + * width of what the backend considers a size type, and the endianness of the + * system that this library was build for. (e.g. for x86_64: "8-8-el"). + * This is required when loading stored regular espressions. PCRE2 regular + * expressions are not portable across architectures that do not have a + * matching arch-string. + */ +char const *regex_arch_string(void) hidden; + +/** * regex_verison returns the version string of the underlying regular * regular expressions library. In the case of PCRE it just returns the * result of pcre_version(). In the case of PCRE2, the very first time this @@ -86,12 +96,15 @@ int regex_prepare_data(struct regex_data **regex, char const *pattern_string, * representation of the precompiled pattern. * @arg regex If successful, the structure returned through *regex was allocated * with regex_data_create and must be freed with regex_data_free. + * @arg do_load_precompregex If non-zero precompiled patterns get loaded from + * the mmap region (ignored by PCRE1 back-end). * * @retval 0 on success * @retval -1 on error */ int regex_load_mmap(struct mmap_area *map_area, - struct regex_data **regex) hidden; + struct regex_data **regex, + int do_load_precompregex) hidden; /** * This function stores a precompiled regular expression to a file. * In the case of PCRE, it just dumps the binary representation of the diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c index 70853e7..d91db9a 100644 --- a/libselinux/utils/sefcontext_compile.c +++ b/libselinux/utils/sefcontext_compile.c @@ -103,6 +103,7 @@ static int write_binary_file(struct saved_data *data, int fd, uint32_t i; int rc; const char *reg_version; + const char *reg_arch; bin_file = fdopen(fd, "w"); if (!bin_file) { @@ -133,6 +134,18 @@ static int write_binary_file(struct saved_data *data, int fd, if (len != section_len) goto err; + /* write regex arch string */ + reg_arch = regex_arch_string(); + if (!reg_arch) + goto err; + section_len = strlen(reg_arch); + len = fwrite(§ion_len, sizeof(uint32_t), 1, bin_file); + if (len != 1) + goto err; + len = fwrite(reg_arch, sizeof(char), section_len, bin_file); + if (len != section_len) + goto err; + /* write the number of stems coming */ section_len = data->num_stems; len = fwrite(§ion_len, sizeof(uint32_t), 1, bin_file);