From patchwork Thu Jun 13 11:45:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ondrej Mosnacek X-Patchwork-Id: 10992285 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DFCB415E6 for ; Thu, 13 Jun 2019 15:26:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CDCD2212BE for ; Thu, 13 Jun 2019 15:26:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C221521327; Thu, 13 Jun 2019 15:26:23 +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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D4D13212BE for ; Thu, 13 Jun 2019 15:26:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727607AbfFMP0W (ORCPT ); Thu, 13 Jun 2019 11:26:22 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:33386 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729212AbfFMLqF (ORCPT ); Thu, 13 Jun 2019 07:46:05 -0400 Received: by mail-wm1-f68.google.com with SMTP id h19so6435999wme.0 for ; Thu, 13 Jun 2019 04:46:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=94t7dcXKOLS7NrIeRejEq30uSZ21aj47SocKv7pipiM=; b=XfrSjOkDjDey66BJpK3hdQtCn0W+KkOtnG6iBhVWbNHhEPT/a78StOWGLqx2KzaY3J FrMPMSyFytnF5lFZaJ8jzz5V2IWyh0WVTxnotz8rZlSF5f9tSPkGyndkdPiR/xKHhhWg gY7nVHmXfroc7Nded7BZFJkIouO5+cPAo4V2uDcRXTYvYEuUQ3cHIIAX192GS2ijdqUi BOWwAIplDED04soXmtnhgOtMAeBgUWbzh0k86fOJxv4SZGDsX6tppWpGoYJjOR1gBb8E WQH3oKSS6tP6uc/qoI0voT3d1JN1qwW7EhPN48IlfFiuEumnYrBARfFrcHXTiRUAnnSn UNZQ== X-Gm-Message-State: APjAAAVFHLDeA6cEixiJbAnl99p7l1oFUrOp+WFNCLCHJKQlMzN9EvqM D7BQ+3xWzh2X3pl1udaR4gIZ1Avv9co= X-Google-Smtp-Source: APXvYqzSfZv2FR1BzDhfIyzQHt+yJR1mc8W9mAXYLx5vTSsFAdKg677JjsgFvN+bpQ/82RZjmVAOiw== X-Received: by 2002:a05:600c:291:: with SMTP id 17mr3393812wmk.32.1560426361879; Thu, 13 Jun 2019 04:46:01 -0700 (PDT) Received: from localhost.localdomain.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id b203sm2906357wmd.41.2019.06.13.04.46.01 for (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Thu, 13 Jun 2019 04:46:01 -0700 (PDT) From: Ondrej Mosnacek To: selinux@vger.kernel.org Subject: [PATCH userspace v4 1/4] libsepol: add a function to optimize kernel policy Date: Thu, 13 Jun 2019 13:45:55 +0200 Message-Id: <20190613114558.32621-2-omosnace@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613114558.32621-1-omosnace@redhat.com> References: <20190613114558.32621-1-omosnace@redhat.com> MIME-Version: 1.0 Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add sepol_policydb_optimize(), which checks a kernel policy for redundant rules (i.e. those that are covered by an existing more general rule) and removes them. Results on Fedora 29 policy: WITHOUT OPTIMIZATION: # time semodule -B real 0m21,280s user 0m18,636s sys 0m2,525s $ wc -c /sys/fs/selinux/policy 8692158 /sys/fs/selinux/policy $ seinfo (edited) Allow: 113159 Dontaudit: 10297 Total: 123156 WITH OPTIMIZATION ENABLED: # time semodule -B real 0m22,825s user 0m20,178s sys 0m2,520s $ wc -c /sys/fs/selinux/policy 8096158 /sys/fs/selinux/policy $ seinfo (edited) Allow: 66334 Dontaudit: 7480 Total: 73814 Signed-off-by: Ondrej Mosnacek --- libsepol/include/sepol/policydb.h | 5 + libsepol/include/sepol/policydb/policydb.h | 2 + libsepol/src/libsepol.map.in | 5 + libsepol/src/optimize.c | 378 +++++++++++++++++++++ libsepol/src/policydb_public.c | 5 + 5 files changed, 395 insertions(+) create mode 100644 libsepol/src/optimize.c diff --git a/libsepol/include/sepol/policydb.h b/libsepol/include/sepol/policydb.h index 6769b913..792913dd 100644 --- a/libsepol/include/sepol/policydb.h +++ b/libsepol/include/sepol/policydb.h @@ -100,6 +100,11 @@ extern int sepol_policydb_set_handle_unknown(sepol_policydb_t * p, extern int sepol_policydb_set_target_platform(sepol_policydb_t * p, int target_platform); +/* + * Optimize the policy by removing redundant rules. + */ +extern int sepol_policydb_optimize(sepol_policydb_t * p); + /* * Read a policydb from a policy file. * This automatically sets the type and version based on the diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h index 591ce6e0..a279382e 100644 --- a/libsepol/include/sepol/policydb/policydb.h +++ b/libsepol/include/sepol/policydb/policydb.h @@ -636,6 +636,8 @@ extern int policydb_user_cache(hashtab_key_t key, extern int policydb_reindex_users(policydb_t * p); +extern int policydb_optimize(policydb_t * p); + extern void policydb_destroy(policydb_t * p); extern int policydb_load_isids(policydb_t * p, sidtab_t * s); diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in index d879016c..6358e51f 100644 --- a/libsepol/src/libsepol.map.in +++ b/libsepol/src/libsepol.map.in @@ -59,3 +59,8 @@ LIBSEPOL_1.1 { sepol_polcap_getnum; sepol_polcap_getname; } LIBSEPOL_1.0; + +LIBSEPOL_1.2 { + global: + sepol_optimize_policy; +} LIBSEPOL_1.1; diff --git a/libsepol/src/optimize.c b/libsepol/src/optimize.c new file mode 100644 index 00000000..3780b68b --- /dev/null +++ b/libsepol/src/optimize.c @@ -0,0 +1,378 @@ +/* + * Author: Ondrej Mosnacek + * + * Copyright (C) 2019 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Binary policy optimization. + * + * Defines the policydb_optimize() function, which finds and removes + * redundant rules from the binary policy to reduce its size and potentially + * improve rule matching times. Only rules that are already covered by a + * more general rule are removed. The resulting policy is functionally + * equivalent to the original one. + */ + +#include +#include + +/* builds map: type/attribute -> {all attributes that are a superset of it} */ +static ebitmap_t *build_type_map(const policydb_t *p) +{ + unsigned int i, k; + ebitmap_t *map = malloc(p->p_types.nprim * sizeof(ebitmap_t)); + if (!map) + return NULL; + + for (i = 0; i < p->p_types.nprim; i++) { + if (p->type_val_to_struct[i] && + p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) { + if (ebitmap_cpy(&map[i], &p->type_attr_map[i])) + goto err; + } else { + ebitmap_t *types_i = &p->attr_type_map[i]; + + ebitmap_init(&map[i]); + for (k = 0; k < p->p_types.nprim; k++) { + ebitmap_t *types_k = &p->attr_type_map[k]; + + if (ebitmap_contains(types_k, types_i)) { + if (ebitmap_set_bit(&map[i], k, 1)) + goto err; + } + } + } + } + return map; +err: + for (k = 0; k <= i; k++) + ebitmap_destroy(&map[k]); + free(map); + return NULL; +} + +static void destroy_type_map(const policydb_t *p, ebitmap_t *type_map) +{ + unsigned int i; + for (i = 0; i < p->p_types.nprim; i++) + ebitmap_destroy(&type_map[i]); + free(type_map); +} + +static int process_xperms(uint32_t *p1, const uint32_t *p2) +{ + size_t i; + int ret = 1; + + for (i = 0; i < EXTENDED_PERMS_LEN; i++) { + p1[i] &= ~p2[i]; + if (p1[i] != 0) + ret = 0; + } + return ret; +} + +static int process_avtab_datum(uint16_t specified, + avtab_datum_t *d1, const avtab_datum_t *d2) +{ + /* inverse logic needed for AUDITDENY rules */ + if (specified & AVTAB_AUDITDENY) + return (d1->data |= ~d2->data) == UINT32_C(0xFFFFFFFF); + + if (specified & AVTAB_AV) + return (d1->data &= ~d2->data) == 0; + + if (specified & AVTAB_XPERMS) { + avtab_extended_perms_t *x1 = d1->xperms; + const avtab_extended_perms_t *x2 = d2->xperms; + + if (x1->specified == AVTAB_XPERMS_IOCTLFUNCTION) { + if (x2->specified == AVTAB_XPERMS_IOCTLFUNCTION) { + if (x1->driver != x2->driver) + return 0; + return process_xperms(x1->perms, x2->perms); + } + if (x2->specified == AVTAB_XPERMS_IOCTLDRIVER) + return xperm_test(x1->driver, x2->perms); + } else if (x1->specified == AVTAB_XPERMS_IOCTLDRIVER) { + if (x2->specified == AVTAB_XPERMS_IOCTLFUNCTION) + return 0; + + if (x2->specified == AVTAB_XPERMS_IOCTLDRIVER) + return process_xperms(x1->perms, x2->perms); + } + return 0; + } + return 0; +} + +/* checks if avtab contains a rule that covers the given rule */ +static int is_avrule_redundant(avtab_ptr_t entry, avtab_t *tab, + const ebitmap_t *type_map) +{ + unsigned int i, k, s_idx, t_idx; + ebitmap_node_t *snode, *tnode; + avtab_datum_t *d1, *d2; + avtab_key_t key; + + /* we only care about AV rules */ + if (!(entry->key.specified & (AVTAB_AV|AVTAB_XPERMS))) + return 0; + + s_idx = entry->key.source_type - 1; + t_idx = entry->key.target_type - 1; + + key.target_class = entry->key.target_class; + key.specified = entry->key.specified; + + d1 = &entry->datum; + + ebitmap_for_each_positive_bit(&type_map[s_idx], snode, i) { + key.source_type = i + 1; + + ebitmap_for_each_positive_bit(&type_map[t_idx], tnode, k) { + if (s_idx == i && t_idx == k) + continue; + + key.target_type = k + 1; + + d2 = avtab_search(tab, &key); + if (!d2) + continue; + + if (process_avtab_datum(key.specified, d1, d2)) + return 1; + } + } + return 0; +} + +static int is_type_attr(policydb_t *p, unsigned int id) +{ + return p->type_val_to_struct[id]->flavor == TYPE_ATTRIB; +} + +static int is_avrule_with_attr(avtab_ptr_t entry, policydb_t *p) +{ + unsigned int s_idx = entry->key.source_type - 1; + unsigned int t_idx = entry->key.target_type - 1; + + return is_type_attr(p, s_idx) || is_type_attr(p, t_idx); +} + +/* checks if conditional list contains a rule that covers the given rule */ +static int is_cond_rule_redundant(avtab_ptr_t e1, cond_av_list_t *list, + const ebitmap_t *type_map) +{ + unsigned int s1, t1, c1, k1, s2, t2, c2, k2; + + /* we only care about AV rules */ + if (!(e1->key.specified & (AVTAB_AV|AVTAB_XPERMS))) + return 0; + + s1 = e1->key.source_type - 1; + t1 = e1->key.target_type - 1; + c1 = e1->key.target_class; + k1 = e1->key.specified; + + for (; list; list = list->next) { + avtab_ptr_t e2 = list->node; + + s2 = e2->key.source_type - 1; + t2 = e2->key.target_type - 1; + c2 = e2->key.target_class; + k2 = e2->key.specified; + + if (k1 != k2 || c1 != c2) + continue; + + if (s1 == s2 && t1 == t2) + continue; + if (!ebitmap_get_bit(&type_map[s1], s2)) + continue; + if (!ebitmap_get_bit(&type_map[t1], t2)) + continue; + + if (process_avtab_datum(k1, &e1->datum, &e2->datum)) + return 1; + } + return 0; +} + +static void optimize_avtab(policydb_t *p, const ebitmap_t *type_map) +{ + avtab_t *tab = &p->te_avtab; + unsigned int i; + avtab_ptr_t *cur; + + for (i = 0; i < tab->nslot; i++) { + cur = &tab->htable[i]; + while (*cur) { + if (is_avrule_redundant(*cur, tab, type_map)) { + /* redundant rule -> remove it */ + avtab_ptr_t tmp = *cur; + + *cur = tmp->next; + if (tmp->key.specified & AVTAB_XPERMS) + free(tmp->datum.xperms); + free(tmp); + + tab->nel--; + } else { + /* rule not redundant -> move to next rule */ + cur = &(*cur)->next; + } + } + } +} + +/* find redundant rules in (*cond) and put them into (*del) */ +static void optimize_cond_av_list(cond_av_list_t **cond, cond_av_list_t **del, + policydb_t *p, const ebitmap_t *type_map) +{ + cond_av_list_t **listp = cond; + cond_av_list_t *pcov = NULL; + cond_av_list_t **pcov_cur = &pcov; + + /* + * Separate out all "potentially covering" rules (src or tgt is an attr) + * and move them to the end of the list. This is needed to avoid + * polynomial complexity when almost all rules are expanded. + */ + while (*cond) { + if (is_avrule_with_attr((*cond)->node, p)) { + cond_av_list_t *tmp = *cond; + + *cond = tmp->next; + tmp->next = pcov; + pcov = tmp; + } else { + cond = &(*cond)->next; + } + } + /* link the "potentially covering" rules to the end of the list */ + *cond = pcov; + + /* now go through the list and find the redundant rules */ + cond = listp; + pcov_cur = &pcov; + while (*cond) { + /* needed because pcov itself may get deleted */ + if (*cond == pcov) + pcov_cur = cond; + /* + * First check if covered by an unconditional rule, then also + * check if covered by another rule in the same list. + */ + if (is_avrule_redundant((*cond)->node, &p->te_avtab, type_map) || + is_cond_rule_redundant((*cond)->node, *pcov_cur, type_map)) { + cond_av_list_t *tmp = *cond; + + *cond = tmp->next; + tmp->next = *del; + *del = tmp; + } else { + cond = &(*cond)->next; + } + } +} + +static void optimize_cond_avtab(policydb_t *p, const ebitmap_t *type_map) +{ + avtab_t *tab = &p->te_cond_avtab; + unsigned int i; + avtab_ptr_t *cur; + cond_node_t **cond; + cond_av_list_t **avcond, *del = NULL; + + /* First go through all conditionals and collect redundant rules. */ + cond = &p->cond_list; + while (*cond) { + optimize_cond_av_list(&(*cond)->true_list, &del, p, type_map); + optimize_cond_av_list(&(*cond)->false_list, &del, p, type_map); + /* TODO: maybe also check for rules present in both lists */ + + /* nothing left in both lists -> remove the whole conditional */ + if (!(*cond)->true_list && !(*cond)->false_list) { + cond_node_t *cond_tmp = *cond; + + *cond = cond_tmp->next; + cond_node_destroy(cond_tmp); + free(cond_tmp); + } else { + cond = &(*cond)->next; + } + } + + if (!del) + return; + + /* + * Now go through the whole cond_avtab and remove all rules that are + * found in the 'del' list. + */ + for (i = 0; i < tab->nslot; i++) { + cur = &tab->htable[i]; + while (*cur) { + int redundant = 0; + avcond = &del; + while (*avcond) { + if ((*avcond)->node == *cur) { + cond_av_list_t *cond_tmp = *avcond; + + *avcond = cond_tmp->next; + free(cond_tmp); + redundant = 1; + break; + } else { + avcond = &(*avcond)->next; + } + } + if (redundant) { + avtab_ptr_t tmp = *cur; + + *cur = tmp->next; + if (tmp->key.specified & AVTAB_XPERMS) + free(tmp->datum.xperms); + free(tmp); + + tab->nel--; + } else { + cur = &(*cur)->next; + } + } + } +} + +int policydb_optimize(policydb_t *p) +{ + ebitmap_t *type_map; + + if (p->policy_type != POLICY_KERN) + return -1; + + type_map = build_type_map(p); + if (!type_map) + return -1; + + optimize_avtab(p, type_map); + optimize_cond_avtab(p, type_map); + + destroy_type_map(p, type_map); + return 0; +} diff --git a/libsepol/src/policydb_public.c b/libsepol/src/policydb_public.c index e7218423..747a43ff 100644 --- a/libsepol/src/policydb_public.c +++ b/libsepol/src/policydb_public.c @@ -169,6 +169,11 @@ int sepol_policydb_set_target_platform(sepol_policydb_t * sp, return 0; } +int sepol_policydb_optimize(sepol_policydb_t * p) +{ + return policydb_optimize(&p->p); +} + int sepol_policydb_read(sepol_policydb_t * p, sepol_policy_file_t * pf) { return policydb_read(&p->p, &pf->pf, 0); From patchwork Thu Jun 13 11:45:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ondrej Mosnacek X-Patchwork-Id: 10992287 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 43A2913AF for ; Thu, 13 Jun 2019 15:26:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3247F212BE for ; Thu, 13 Jun 2019 15:26:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 26B5F21327; Thu, 13 Jun 2019 15:26:31 +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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9C960212BE for ; Thu, 13 Jun 2019 15:26:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728331AbfFMP0W (ORCPT ); Thu, 13 Jun 2019 11:26:22 -0400 Received: from mail-wm1-f65.google.com ([209.85.128.65]:34512 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729216AbfFMLqE (ORCPT ); Thu, 13 Jun 2019 07:46:04 -0400 Received: by mail-wm1-f65.google.com with SMTP id w9so6440623wmd.1 for ; Thu, 13 Jun 2019 04:46:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Pt2qT3+bo4o+3RMCu3laPePon0gCUEX1f5s3e1eN4QI=; b=BfYS4v1O00BBSYB0dI2niu4ubucvvO73xZ/imbVRQqwIG5L91eVJkFr3CZ6L4ee3qq CuSLaZuOLEZDjsM1SEaBgCjAlsswVYS32fBfmDbVBhTzAZj6OYCi2/xgGdDMcti+hOH1 vgAMiVSf00P3HRD5DvgmeV0KkinICNUSQIavmp8kG7FplRwQyttXg2pCZxb1ew3HHX2z eKYWhwqNWOaad4uNNsLw6TUGR4nNIeTveG/UvWZ7quUAxup71UIrXgQKNN0gFdmWfPE6 2m/9H+L5ZUxB1CiMLnFUABv9+rSeBMbXBkndDfd9fio4S2xcaSu5/V0/mV+G8Ft190PB zJZA== X-Gm-Message-State: APjAAAWWbEz83Ysy6eqUIzy61p851j3/MApzLliCOebZsGg4v72tN1NT dW2BnfdHmezfiRFD6uqEW1DUk1fvQi4= X-Google-Smtp-Source: APXvYqzCSI/lQswTmdSCLsmWocfFogeQs0EzJSfyeMnXUmrAHLMcXErFn1cAOlu0Fx4Mb9MjFWpgTQ== X-Received: by 2002:a1c:40c6:: with SMTP id n189mr3387125wma.118.1560426362656; Thu, 13 Jun 2019 04:46:02 -0700 (PDT) Received: from localhost.localdomain.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id b203sm2906357wmd.41.2019.06.13.04.46.01 for (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Thu, 13 Jun 2019 04:46:02 -0700 (PDT) From: Ondrej Mosnacek To: selinux@vger.kernel.org Subject: [PATCH userspace v4 2/4] libsemanage: optionally optimize policy on rebuild Date: Thu, 13 Jun 2019 13:45:56 +0200 Message-Id: <20190613114558.32621-3-omosnace@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613114558.32621-1-omosnace@redhat.com> References: <20190613114558.32621-1-omosnace@redhat.com> MIME-Version: 1.0 Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When building binary policy, optionally run it through sepol_policydb_optimize() just before writing it out. Add an optimize-policy variable to semanage.conf(5) that controls whether optimization will be applied during libsemanage operations. Signed-off-by: Ondrej Mosnacek --- libsemanage/man/man5/semanage.conf.5 | 5 +++++ libsemanage/src/conf-parse.y | 15 ++++++++++++++- libsemanage/src/conf-scan.l | 1 + libsemanage/src/direct_api.c | 7 +++++++ libsemanage/src/semanage_conf.h | 1 + 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/libsemanage/man/man5/semanage.conf.5 b/libsemanage/man/man5/semanage.conf.5 index 8f8de55a..8efc7dd5 100644 --- a/libsemanage/man/man5/semanage.conf.5 +++ b/libsemanage/man/man5/semanage.conf.5 @@ -121,6 +121,11 @@ and by default it is set to "false". Please note that since this option deletes all HLL files, an updated HLL compiler will not be able to recompile the original HLL file into CIL. In order to compile the original HLL file into CIL, the same HLL file will need to be reinstalled. +.TP +.B optimize-policy +When set to "true", the kernel policy will be optimized upon rebuilds. +It can be set to either "true" or "false" and by default it is set to "false". + .SH "SEE ALSO" .TP semanage(8) diff --git a/libsemanage/src/conf-parse.y b/libsemanage/src/conf-parse.y index b527e893..9bf9364a 100644 --- a/libsemanage/src/conf-parse.y +++ b/libsemanage/src/conf-parse.y @@ -59,7 +59,7 @@ static int parse_errors; char *s; } -%token MODULE_STORE VERSION EXPAND_CHECK FILE_MODE SAVE_PREVIOUS SAVE_LINKED TARGET_PLATFORM COMPILER_DIR IGNORE_MODULE_CACHE STORE_ROOT +%token MODULE_STORE VERSION EXPAND_CHECK FILE_MODE SAVE_PREVIOUS SAVE_LINKED TARGET_PLATFORM COMPILER_DIR IGNORE_MODULE_CACHE STORE_ROOT OPTIMIZE_POLICY %token LOAD_POLICY_START SETFILES_START SEFCONTEXT_COMPILE_START DISABLE_GENHOMEDIRCON HANDLE_UNKNOWN USEPASSWD IGNOREDIRS %token BZIP_BLOCKSIZE BZIP_SMALL REMOVE_HLL %token VERIFY_MOD_START VERIFY_LINKED_START VERIFY_KERNEL_START BLOCK_END @@ -95,6 +95,7 @@ single_opt: module_store | bzip_blocksize | bzip_small | remove_hll + | optimize_policy ; module_store: MODULE_STORE '=' ARG { @@ -268,6 +269,17 @@ remove_hll: REMOVE_HLL'=' ARG { free($3); } +optimize_policy: OPTIMIZE_POLICY '=' ARG { + if (strcasecmp($3, "false") == 0) { + current_conf->optimize_policy = 0; + } else if (strcasecmp($3, "true") == 0) { + current_conf->optimize_policy = 1; + } else { + yyerror("optimize-policy can only be 'true' or 'false'"); + } + free($3); +} + command_block: command_start external_opts BLOCK_END { if (new_external->path == NULL) { @@ -352,6 +364,7 @@ static int semanage_conf_init(semanage_conf_t * conf) conf->bzip_small = 0; conf->ignore_module_cache = 0; conf->remove_hll = 0; + conf->optimize_policy = 0; conf->save_previous = 0; conf->save_linked = 0; diff --git a/libsemanage/src/conf-scan.l b/libsemanage/src/conf-scan.l index 607bbf0b..b06a896c 100644 --- a/libsemanage/src/conf-scan.l +++ b/libsemanage/src/conf-scan.l @@ -54,6 +54,7 @@ handle-unknown return HANDLE_UNKNOWN; bzip-blocksize return BZIP_BLOCKSIZE; bzip-small return BZIP_SMALL; remove-hll return REMOVE_HLL; +optimize-policy return OPTIMIZE_POLICY; "[load_policy]" return LOAD_POLICY_START; "[setfiles]" return SETFILES_START; "[sefcontext_compile]" return SEFCONTEXT_COMPILE_START; diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c index c58961be..0153091f 100644 --- a/libsemanage/src/direct_api.c +++ b/libsemanage/src/direct_api.c @@ -1461,6 +1461,13 @@ rebuild: cil_db_destroy(&cildb); + /* Remove redundancies in binary policy if requested. */ + if (sh->conf->optimize_policy) { + retval = sepol_policydb_optimize(out); + if (retval < 0) + goto cleanup; + } + /* Write the linked policy before merging local changes. */ retval = semanage_write_policydb(sh, out, SEMANAGE_LINKED); diff --git a/libsemanage/src/semanage_conf.h b/libsemanage/src/semanage_conf.h index c99ac8c7..23c4b8b4 100644 --- a/libsemanage/src/semanage_conf.h +++ b/libsemanage/src/semanage_conf.h @@ -47,6 +47,7 @@ typedef struct semanage_conf { int bzip_small; int remove_hll; int ignore_module_cache; + int optimize_policy; char *ignoredirs; /* ";" separated of list for genhomedircon to ignore */ struct external_prog *load_policy; struct external_prog *setfiles; From patchwork Thu Jun 13 11:45:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ondrej Mosnacek X-Patchwork-Id: 10992281 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 59A4B18A6 for ; Thu, 13 Jun 2019 15:26:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 49427212BE for ; Thu, 13 Jun 2019 15:26:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3DC9F21EEB; Thu, 13 Jun 2019 15:26:22 +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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D7BFD212BE for ; Thu, 13 Jun 2019 15:26:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727966AbfFMP0V (ORCPT ); Thu, 13 Jun 2019 11:26:21 -0400 Received: from mail-wm1-f66.google.com ([209.85.128.66]:35756 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729220AbfFMLqG (ORCPT ); Thu, 13 Jun 2019 07:46:06 -0400 Received: by mail-wm1-f66.google.com with SMTP id c6so9809104wml.0 for ; Thu, 13 Jun 2019 04:46:04 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=QS17Kf4IFQ3CkNgeh/iJndUe8J5r8dyCU5F990FbKuI=; b=gk+KpVABkPJSDZhoQJw5awa6/azXWBKYwFV+vd28rqMRxrgGznum05+dJXXdiEjqw3 YP6ZdplARqYPV7STE7NmxXh8mdPcduy26/ubNmgfZZb+/CB3nsJfIbjLOSnGldVK6OoY HCPOPiWar+4QEJKbU9EAgdztV6egBgvNVdrHxhfCVhrRHaTLTMV6CzmoSE0fCTpxE2+h 3oboeZ6OypzpfrNt+VyFV35XysdBKTLqAsjNvYhoRA2N/97moPdLvFndqxS6o94TTmVj KmGrnYq01SEnyVOGHb5dDIRJ7nKtD+E8IRV5zs9yA8Jd9VeZ+o/YryrZypxhNq7qqOoP yxhw== X-Gm-Message-State: APjAAAVeDeBxcxJwiKzbVcF8BplKbzYXwUs5w/ki880d/88go2BhPNK1 aHOwE4C8nePCISlj8JfKlEZLxk3jpvs= X-Google-Smtp-Source: APXvYqxSeOdtYFF6sgbe8VyPJ5CcjHUkLPO67FsbpSLpV56WyctQuMgqqxkJQXkl505rrO1TfLWYig== X-Received: by 2002:a1c:be0a:: with SMTP id o10mr3411941wmf.91.1560426363601; Thu, 13 Jun 2019 04:46:03 -0700 (PDT) Received: from localhost.localdomain.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id b203sm2906357wmd.41.2019.06.13.04.46.02 for (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Thu, 13 Jun 2019 04:46:02 -0700 (PDT) From: Ondrej Mosnacek To: selinux@vger.kernel.org Subject: [PATCH userspace v4 3/4] secilc: add flag to enable policy optimization Date: Thu, 13 Jun 2019 13:45:57 +0200 Message-Id: <20190613114558.32621-4-omosnace@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613114558.32621-1-omosnace@redhat.com> References: <20190613114558.32621-1-omosnace@redhat.com> MIME-Version: 1.0 Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add a command-line option -O/--optimize to optimize the final policydb using sepol_policydb_optimize() before writing it out. Signed-off-by: Ondrej Mosnacek --- secilc/secilc.8.xml | 5 +++++ secilc/secilc.c | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/secilc/secilc.8.xml b/secilc/secilc.8.xml index e08a9624..2b734f09 100644 --- a/secilc/secilc.8.xml +++ b/secilc/secilc.8.xml @@ -95,6 +95,11 @@ Expand type attributes with fewer than <SIZE> members. + + + Optimize final policy (remove redundant rules). + + Increment verbosity level. diff --git a/secilc/secilc.c b/secilc/secilc.c index ad6862ba..186c5a73 100644 --- a/secilc/secilc.c +++ b/secilc/secilc.c @@ -68,6 +68,7 @@ static __attribute__((__noreturn__)) void usage(const char *prog) printf(" -G, --expand-generated Expand and remove auto-generated attributes\n"); printf(" -X, --expand-size Expand type attributes with fewer than \n"); printf(" members.\n"); + printf(" -O, --optimize optimize final policy\n"); printf(" -v, --verbose increment verbosity level\n"); printf(" -h, --help display usage information\n"); exit(1); @@ -97,6 +98,7 @@ int main(int argc, char *argv[]) int policyvers = POLICYDB_VERSION_MAX; int attrs_expand_generated = 0; int attrs_expand_size = -1; + int optimize = 0; int opt_char; int opt_index = 0; char *fc_buf = NULL; @@ -117,12 +119,13 @@ int main(int argc, char *argv[]) {"filecontexts", required_argument, 0, 'f'}, {"expand-generated", no_argument, 0, 'G'}, {"expand-size", required_argument, 0, 'X'}, + {"optimize", no_argument, 0, 'O'}, {0, 0, 0, 0} }; int i; while (1) { - opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PDmNc:GX:", long_opts, &opt_index); + opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PDmNOc:GX:n", long_opts, &opt_index); if (opt_char == -1) { break; } @@ -211,6 +214,9 @@ int main(int argc, char *argv[]) } break; } + case 'O': + optimize = 1; + break; case 'h': usage(argv[0]); case '?': @@ -294,6 +300,14 @@ int main(int argc, char *argv[]) goto exit; } + if (optimize) { + rc = sepol_policydb_optimize(pdb); + if (rc != SEPOL_OK) { + fprintf(stderr, "Failed to optimize policydb\n"); + goto exit; + } + } + if (output == NULL) { int size = snprintf(NULL, 0, "policy.%d", policyvers); output = malloc((size + 1) * sizeof(char)); From patchwork Thu Jun 13 11:45:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ondrej Mosnacek X-Patchwork-Id: 10992279 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4378913AF for ; Thu, 13 Jun 2019 15:26:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 324BE219AC for ; Thu, 13 Jun 2019 15:26:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2693221327; Thu, 13 Jun 2019 15:26:22 +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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B8042219AC for ; Thu, 13 Jun 2019 15:26:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728280AbfFMP0V (ORCPT ); Thu, 13 Jun 2019 11:26:21 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:43408 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729221AbfFMLqH (ORCPT ); Thu, 13 Jun 2019 07:46:07 -0400 Received: by mail-wr1-f67.google.com with SMTP id p13so10324416wru.10 for ; Thu, 13 Jun 2019 04:46:05 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=noc+4n7n8rJoqKCZ+8pPcl9Q42KnX0P3ic9sERe4fMw=; b=BA/4FViYtpiBlRpHUNV4sxPBDYvCKLeBYLqTxmAYlDc3HxXe3oo05htHsj9mFgo4/Y vi0Kv94NrNKsFCK562mjf9rpEX7pTKP+wCjAhP7AYZLR0QAaTYAvdIMlf2OJmqbyFfOe JfeWE+pqXPp+3UNEHShg/bX24CFwOgu+JjGsZLRU1TGGtnmCnIaF3scogwwcO4Q+90Pk HTdwKMh+5GA8ZG/+4K617MQST+65cyZxkfh9dmz71AwlA34Pv40892GvmODxS+03djPC cl43RSWsyoxeK6C+XYz9lI4Rh0ntMkkGQWn8fSzdtJd34ioccBEvfdr1XTTXbNOb05gM IzXA== X-Gm-Message-State: APjAAAUfJHy2lXE9LV3Yu3dc8pkekDModmwofZy8b1aTQ9DxZig32VH8 uTnMkr/HXud9p4eTOcHbbWvM4AdllIc= X-Google-Smtp-Source: APXvYqy6kLsO/tkJAoIFyJyk7AIPAoPjwJIqa5zEChEp3fY38wgcdJJvlUlEEzqssc52wZ8uPEIIog== X-Received: by 2002:a05:6000:1289:: with SMTP id f9mr20971212wrx.125.1560426364641; Thu, 13 Jun 2019 04:46:04 -0700 (PDT) Received: from localhost.localdomain.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id b203sm2906357wmd.41.2019.06.13.04.46.03 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Thu, 13 Jun 2019 04:46:03 -0700 (PDT) From: Ondrej Mosnacek To: selinux@vger.kernel.org Cc: James Carter Subject: [PATCH userspace v4 4/4] checkpolicy: add flag to enable policy optimization Date: Thu, 13 Jun 2019 13:45:58 +0200 Message-Id: <20190613114558.32621-5-omosnace@redhat.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190613114558.32621-1-omosnace@redhat.com> References: <20190613114558.32621-1-omosnace@redhat.com> MIME-Version: 1.0 Sender: selinux-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: James Carter Add the command-line option 'O' to checkpolicy to cause kernel policies to be optimized by calling policydb_optimize() before being written out. This option can be used on conf files and binary kernel policies, but not when converting a conf file to CIL. Signed-off-by: James Carter [omosnace: make commit desc more consistent with the other patches] [omosnace: fix a typo in the commit message] [omosnace: directly use policydb_optimize() as also the rest of code already uses other policydb_*() functions...] [omosnace: update man page] Signed-off-by: Ondrej Mosnacek --- checkpolicy/checkpolicy.8 | 3 +++ checkpolicy/checkpolicy.c | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/checkpolicy/checkpolicy.8 b/checkpolicy/checkpolicy.8 index 8f7dad41..1552f497 100644 --- a/checkpolicy/checkpolicy.8 +++ b/checkpolicy/checkpolicy.8 @@ -48,6 +48,9 @@ Sort ocontexts before writing out the binary policy. This option makes output of .B \-t,\-\-target Specify the target platform (selinux or xen). .TP +.B \-O,\-\-optimize +Optimize the final kernel policy (remove redundant rules). +.TP .B \-V,\-\-version Show version information. .TP diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c index e0a00f7c..f928ec06 100644 --- a/checkpolicy/checkpolicy.c +++ b/checkpolicy/checkpolicy.c @@ -394,7 +394,7 @@ int main(int argc, char **argv) size_t scontext_len, pathlen; unsigned int i; unsigned int protocol, port; - unsigned int binary = 0, debug = 0, sort = 0, cil = 0, conf = 0; + unsigned int binary = 0, debug = 0, sort = 0, cil = 0, conf = 0, optimize = 0; struct val_to_name v; int ret, ch, fd, target = SEPOL_TARGET_SELINUX; unsigned int nel, uret; @@ -419,11 +419,12 @@ int main(int argc, char **argv) {"cil", no_argument, NULL, 'C'}, {"conf",no_argument, NULL, 'F'}, {"sort", no_argument, NULL, 'S'}, + {"optimize", no_argument, NULL, 'O'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; - while ((ch = getopt_long(argc, argv, "o:t:dbU:MCFSVc:h", long_options, NULL)) != -1) { + while ((ch = getopt_long(argc, argv, "o:t:dbU:MCFSVc:Oh", long_options, NULL)) != -1) { switch (ch) { case 'o': outfile = optarg; @@ -466,6 +467,9 @@ int main(int argc, char **argv) case 'S': sort = 1; break; + case 'O': + optimize = 1; + break; case 'M': mlspol = 1; break; @@ -625,6 +629,14 @@ int main(int argc, char **argv) if (policydb_load_isids(&policydb, &sidtab)) exit(1); + if (optimize && policydbp->policy_type == POLICY_KERN) { + ret = policydb_optimize(policydbp); + if (ret) { + fprintf(stderr, "%s: error optimizing policy\n", argv[0]); + exit(1); + } + } + if (outfile) { outfp = fopen(outfile, "w"); if (!outfp) {