mirror of
https://github.com/SELinuxProject/selinux
synced 2025-02-28 23:40:35 +00:00
In Fedora/RHEL's selinux-policy package we ship a pre-built SELinux policy store in the RPMs. When updating the main policy RPM, care must be taken to rebuild the policy using `semodule -B` if there are any other SELinux modules installed (whether shipped via another RPM or manually installed locally). However, this way of shipping/managing the policy creates complications on systems, where system files are managed by rpm-ostree (such as Fedora CoreOS or Red Hat CoreOS), where the "package update" process is more sophisticated. (Disclaimer: The following is written according to my current limited understanding of rpm-ostree and may not be entirely accurate, but the gist of it should match the reality.) Basically, one can think of rpm-ostree as a kind of Git for system files. The package content is provided on a "branch", where each "commit" represents a set of package updates layered on top of the previous commit (i.e. it is a rolling release with some defined package content snapshots). The user can then maintain their own branch with additional package updates/installations/... and "rebase" it on top of the main branch as needed. On top of that, the user can also have additional configuration files (or modifications to existing files) in /etc, which represent an additional layer on top of the package content. When updating the system (i.e. rebasing on a new "commit" of the "main branch"), the files on the running system are not touched and the new system state is prepared under a new root directory, which is chrooted into on the next reboot. When an rpm-ostree system is updated, there are three moments when the SELinux module store needs to be rebuilt to ensure that all modules are included in the binary policy: 1. When the local RPM installations are applied on top of the base system snapshot. 2. When local user configuartion is applied on top of that. 3. On system shutdown, to ensure that any changes in local configuration performed since (2.) are reflected in the final new system image. Forcing a full rebuild at each step is not optimal and in many cases is not necessary, as the user may not have any custom modules installed. Thus, this patch extends libsemanage to compute a checksum of the content of all enabled modules, which is stored in the store, and adds a flag to the libsemanage handle that instructs it to check the module content checksum against the one from the last successful transaction and force a full policy rebuild if they don't match. This will allow rpm-ostree systems to potentially reduce delays when reconciling the module store when applying updates. I wasn't able to measure any noticeable overhead of the hash computation, which is now added for every transaction (both before and after this change a full policy rebuild took about 7 seconds on my test x86 VM). With the new option check_ext_changes enabled, rebuilding a policy store with unchanged modules took only about 0.96 seconds. Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
178 lines
7.3 KiB
C
178 lines
7.3 KiB
C
/* Authors: Joshua Brindle <jbrindle@tresys.com>
|
|
* Jason Tang <jtang@tresys.com>
|
|
*
|
|
* Copyright (C) 2005 Tresys Technology, LLC
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#ifndef _SEMANAGE_HANDLE_H_
|
|
#define _SEMANAGE_HANDLE_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
/* All accesses with semanage are through a "semanage_handle". The
|
|
* handle may ultimately reference local config files,
|
|
* the binary policy file, a module store, or a policy management server.
|
|
*/
|
|
struct semanage_handle;
|
|
typedef struct semanage_handle semanage_handle_t;
|
|
|
|
/* Create and return a semanage handle.
|
|
The handle is initially in the disconnected state. */
|
|
extern semanage_handle_t *semanage_handle_create(void);
|
|
|
|
/* Deallocate all space associated with a semanage_handle_t, including
|
|
* the pointer itself. CAUTION: this function does not disconnect
|
|
* from the backend; be sure that a semanage_disconnect() was
|
|
* previously called if the handle was connected. */
|
|
extern void semanage_handle_destroy(semanage_handle_t *);
|
|
|
|
/* This is the type of connection to the store, for now only
|
|
* direct is supported */
|
|
enum semanage_connect_type {
|
|
SEMANAGE_CON_INVALID = 0, SEMANAGE_CON_DIRECT,
|
|
SEMANAGE_CON_POLSERV_LOCAL, SEMANAGE_CON_POLSERV_REMOTE
|
|
};
|
|
|
|
/* This function allows you to specify the store to connect to.
|
|
* It must be called after semanage_handle_create but before
|
|
* semanage_connect. The argument should be the full path to the store.
|
|
*/
|
|
extern void semanage_select_store(semanage_handle_t * handle, char *path,
|
|
enum semanage_connect_type storetype);
|
|
|
|
/* Just reload the policy */
|
|
extern int semanage_reload_policy(semanage_handle_t * handle);
|
|
|
|
/* set whether to reload the policy or not after a commit,
|
|
* 1 for yes (default), 0 for no */
|
|
extern void semanage_set_reload(semanage_handle_t * handle, int do_reload);
|
|
|
|
/* set whether to rebuild the policy on commit, even if no
|
|
* changes were performed.
|
|
* 1 for yes, 0 for no (default) */
|
|
extern void semanage_set_rebuild(semanage_handle_t * handle, int do_rebuild);
|
|
|
|
/* set whether to rebuild the policy on commit when potential changes
|
|
* to module files since last rebuild are detected,
|
|
* 1 for yes (default), 0 for no */
|
|
extern void semanage_set_check_ext_changes(semanage_handle_t * handle, int do_check);
|
|
|
|
/* Fills *compiler_path with the location of the hll compiler sh->conf->compiler_directory_path
|
|
* corresponding to lang_ext.
|
|
* Upon success returns 0, -1 on error. */
|
|
extern int semanage_get_hll_compiler_path(semanage_handle_t *sh, char *lang_ext, char **compiler_path);
|
|
|
|
/* create the store if it does not exist, this only has an effect on
|
|
* direct connections and must be called before semanage_connect
|
|
* 1 for yes, 0 for no (default) */
|
|
extern void semanage_set_create_store(semanage_handle_t * handle, int create_store);
|
|
|
|
/*Get whether or not dontaudits will be disabled upon commit */
|
|
extern int semanage_get_disable_dontaudit(semanage_handle_t * handle);
|
|
|
|
/* Set whether or not to disable dontaudits upon commit */
|
|
extern void semanage_set_disable_dontaudit(semanage_handle_t * handle, int disable_dontaudit);
|
|
|
|
/* Set whether or not to execute setfiles to check file contexts upon commit */
|
|
extern void semanage_set_check_contexts(semanage_handle_t * sh, int do_check_contexts);
|
|
|
|
/* Get the default priority. */
|
|
extern uint16_t semanage_get_default_priority(semanage_handle_t *sh);
|
|
|
|
/* Set the default priority. */
|
|
extern int semanage_set_default_priority(semanage_handle_t *sh, uint16_t priority);
|
|
|
|
/* Check whether policy is managed via libsemanage on this system.
|
|
* Must be called prior to trying to connect.
|
|
* Return 1 if policy is managed via libsemanage on this system,
|
|
* 0 if policy is not managed, or -1 on error.
|
|
*/
|
|
extern int semanage_is_managed(semanage_handle_t *);
|
|
|
|
/* "Connect" to a manager based on the configuration and
|
|
* associate the provided handle with the connection.
|
|
* If the connect fails then this function returns a negative value,
|
|
* else it returns zero.
|
|
*/
|
|
extern int semanage_connect(semanage_handle_t *);
|
|
|
|
/* Disconnect from the manager given by the handle. If already
|
|
* disconnected then this function does nothing. Return 0 if
|
|
* disconnected properly or already disconnected, negative value on
|
|
* error. */
|
|
extern int semanage_disconnect(semanage_handle_t *);
|
|
|
|
/* Attempt to obtain a transaction lock on the manager. If another
|
|
* process has the lock then this function may block, depending upon
|
|
* the timeout value in the handle.
|
|
*
|
|
* Note that if the semanage_handle has not yet obtained a transaction
|
|
* lock whenever a writer function is called, there will be an
|
|
* implicit call to this function. */
|
|
extern int semanage_begin_transaction(semanage_handle_t *);
|
|
|
|
/* Attempt to commit all changes since this transaction began. If the
|
|
* commit is successful then increment the "policy sequence number"
|
|
* and then release the transaction lock. Return that policy number
|
|
* afterwards, or -1 on error.
|
|
*/
|
|
extern int semanage_commit(semanage_handle_t *);
|
|
|
|
#define SEMANAGE_CAN_READ 1
|
|
#define SEMANAGE_CAN_WRITE 2
|
|
/* returns SEMANAGE_CAN_READ or SEMANAGE_CAN_WRITE if the store is readable
|
|
* or writable, respectively. <0 if an error occurred */
|
|
extern int semanage_access_check(semanage_handle_t * sh);
|
|
|
|
/* returns 0 if not connected, 1 if connected */
|
|
extern int semanage_is_connected(semanage_handle_t * sh);
|
|
|
|
/* returns 1 if policy is MLS, 0 otherwise. */
|
|
extern int semanage_mls_enabled(semanage_handle_t *sh);
|
|
|
|
/* Change to alternate semanage root path */
|
|
extern int semanage_set_root(const char *path);
|
|
|
|
/* Get the current semanage root path */
|
|
extern const char * semanage_root(void);
|
|
|
|
/* Get whether or not needless unused branch of tunables would be preserved */
|
|
extern int semanage_get_preserve_tunables(semanage_handle_t * handle);
|
|
|
|
/* Set whether or not to preserve the needless unused branch of tunables */
|
|
extern void semanage_set_preserve_tunables(semanage_handle_t * handle, int preserve_tunables);
|
|
|
|
/* Get the flag value for whether or not caching is ignored for compiled CIL modules from HLL files */
|
|
extern int semanage_get_ignore_module_cache(semanage_handle_t *handle);
|
|
|
|
/* Set semanage_handle flag for whether or not to ignore caching of compiled CIL modules from HLL files */
|
|
extern void semanage_set_ignore_module_cache(semanage_handle_t *handle, int ignore_module_cache);
|
|
|
|
/* set the store root path for semanage output files */
|
|
extern void semanage_set_store_root(semanage_handle_t *sh, const char *store_root);
|
|
|
|
/* META NOTES
|
|
*
|
|
* For all functions a non-negative number indicates success. For some
|
|
* functions a >=0 returned value is the "policy sequence number". This
|
|
* number keeps tracks of policy revisions and is used to detect if
|
|
* one semanage client has committed policy changes while another is
|
|
* still connected.
|
|
*/
|
|
|
|
#endif
|