summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MODULE_LICENSE_PUBLIC_DOMAIN0
-rw-r--r--NOTICE21
-rw-r--r--README.android62
-rw-r--r--include/selinux/android.h56
-rw-r--r--include/selinux/avc.h507
-rw-r--r--include/selinux/context.h50
-rw-r--r--include/selinux/label.h167
-rw-r--r--include/selinux/selinux.h291
-rw-r--r--src/android.c1538
-rw-r--r--src/avc.c1121
-rw-r--r--src/avc_internal.c292
-rw-r--r--src/avc_internal.h182
-rw-r--r--src/avc_sidtab.c152
-rw-r--r--src/avc_sidtab.h36
-rw-r--r--src/booleans.c263
-rw-r--r--src/callbacks.c124
-rw-r--r--src/callbacks.h30
-rw-r--r--src/canonicalize_context.c62
-rw-r--r--src/checkAccess.c62
-rw-r--r--src/check_context.c33
-rw-r--r--src/compute_av.c72
-rw-r--r--src/compute_create.c61
-rw-r--r--src/context.c197
-rw-r--r--src/context_internal.h14
-rw-r--r--src/deny_unknown.c40
-rw-r--r--src/disable.c38
-rw-r--r--src/dso.h23
-rw-r--r--src/enabled.c54
-rw-r--r--src/fgetfilecon.c51
-rw-r--r--src/freecon.c11
-rw-r--r--src/fsetfilecon.c15
-rw-r--r--src/get_initial_context.c55
-rw-r--r--src/getenforce.c40
-rw-r--r--src/getfilecon.c50
-rw-r--r--src/getpeercon.c45
-rw-r--r--src/init.c123
-rw-r--r--src/label.c173
-rw-r--r--src/label_android_property.c350
-rw-r--r--src/label_file.c859
-rw-r--r--src/label_file.h474
-rw-r--r--src/label_internal.h95
-rw-r--r--src/label_support.c117
-rw-r--r--src/lgetfilecon.c50
-rw-r--r--src/load_policy.c41
-rw-r--r--src/lsetfilecon.c15
-rw-r--r--src/mapping.c210
-rw-r--r--src/mapping.h41
-rw-r--r--src/policy.h28
-rw-r--r--src/policyvers.c45
-rw-r--r--src/procattr.c176
-rw-r--r--src/regex.c391
-rw-r--r--src/regex.h166
-rw-r--r--src/selinux_internal.h132
-rw-r--r--src/selinux_netlink.h31
-rw-r--r--src/sestatus.c349
-rw-r--r--src/setenforce.c37
-rw-r--r--src/setfilecon.c15
-rw-r--r--src/stringrep.c277
-rw-r--r--utils/sefcontext_compile.c363
59 files changed, 0 insertions, 10373 deletions
diff --git a/MODULE_LICENSE_PUBLIC_DOMAIN b/MODULE_LICENSE_PUBLIC_DOMAIN
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_PUBLIC_DOMAIN
+++ /dev/null
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index d386268..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,21 +0,0 @@
-This library (libselinux) is public domain software, i.e. not copyrighted.
-
-Warranty Exclusion
-------------------
-You agree that this software is a
-non-commercially developed program that may contain "bugs" (as that
-term is used in the industry) and that it may not function as intended.
-The software is licensed "as is". NSA makes no, and hereby expressly
-disclaims all, warranties, express, implied, statutory, or otherwise
-with respect to the software, including noninfringement and the implied
-warranties of merchantability and fitness for a particular purpose.
-
-Limitation of Liability
------------------------
-In no event will NSA be liable for any damages, including loss of data,
-lost profits, cost of cover, or other special, incidental,
-consequential, direct or indirect damages arising from the software or
-the use thereof, however caused and on any theory of liability. This
-limitation will apply even if NSA has been advised of the possibility
-of such damage. You acknowledge that this is a reasonable allocation of
-risk.
diff --git a/README.android b/README.android
deleted file mode 100644
index e01f889..0000000
--- a/README.android
+++ /dev/null
@@ -1,62 +0,0 @@
-This directory contains a small port of libselinux for Android.
-It was originally forked in mid-2011, circa libselinux 2.1.0.
-Some changes have been cherry-picked from the upstream libselinux.
-Upstream git repository is https://github.com/SELinuxProject/selinux
-(libselinux subdirectory) and official releases are available from
-https://github.com/SELinuxProject/selinux/wiki/Releases.
-
-This fork differs from upstream libselinux in at least the following ways:
-
-* Dependencies on glibc-specific features have been removed/replaced
-in order to work with bionic,
-
-* Legacy code and compatibility interfaces have been removed,
-
-* Many interfaces, functions, and files are omitted since they are
-unused in Android,
-
-* The python bindings are omitted since they are unused in Android,
-
-* The setrans (context translation) support has been removed since
-there is no need for MLS label translation in Android and the support
-imposes extra overhead on calls passing security contexts,
-
-* The SELinux policy files are all located in / rather than under
-/etc/selinux since /etc is not available in Android until /system
-is mounted and use fixed paths, not dependent on /etc/selinux/config,
-
-* The kernel policy file (sepolicy in Android, policy.N in Linux) does
-not include a version suffix since Android does not need to support
-booting multiple kernels,
-
-* The policy loading logic does not support automatic downgrading of
-the kernel policy file to a version known to the kernel, since this
-requires libsepol on the device and is only needed to support mixing
-and matching kernels and userspace easily,
-
-* The selabel interface and label_file backend have been extended to
-support label-by-symlink and partial matching support for use by ueventd
-in labeling device nodes based on stable symlink names and by init for
-optimizing its restorecon_recursive of /sys,
-
-* Since the fork, upstream libselinux has switched the label_file
-backend to use a binary version of the file_contexts file
-(file_contexts.bin) that contains precompiled versions of the pcre
-regexes. This reduces the time to load the file_contexts
-configuration, which in Linux can be significant due to the large
-number of entries (> 5000). As Android has far fewer entries (~400),
-this has not yet seemed necessary.
-
-* restorecon functionality, including recursive restorecon, has been
-fully implemented within new libselinux functions, along with optimizations
-to prune the tree walk if no change has occurred in file_contexts since
-the last restorecon,
-
-* Support for new Android-specific SELinux configuration files, such
-as seapp_contexts, property_contexts, and service_contexts, has been
-added.
-
-New files added for Android:
-* libselinux/include/selinux/android.h
-* libselinux/src/android.c
-* libselinux/src/label_android_property.c (later added upstream)
diff --git a/include/selinux/android.h b/include/selinux/android.h
deleted file mode 100644
index 21a41a0..0000000
--- a/include/selinux/android.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef _SELINUX_ANDROID_H_
-#define _SELINUX_ANDROID_H_
-
-#include <stdbool.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <selinux/label.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern struct selabel_handle* selinux_android_file_context_handle(void);
-
-extern struct selabel_handle* selinux_android_prop_context_handle(void);
-
-extern struct selabel_handle* selinux_android_service_context_handle(void);
-
-extern void selinux_android_set_sehandle(const struct selabel_handle *hndl);
-
-extern int selinux_android_load_policy(void);
-
-extern int selinux_android_setcon(const char *con);
-
-extern int selinux_android_setcontext(uid_t uid,
- bool isSystemServer,
- const char *seinfo,
- const char *name);
-
-extern int selinux_android_setfilecon(const char *pkgdir,
- const char *pkgname,
- const char *seinfo,
- uid_t uid);
-
-extern int selinux_log_callback(int type, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-
-#define SELINUX_ANDROID_RESTORECON_NOCHANGE 1
-#define SELINUX_ANDROID_RESTORECON_VERBOSE 2
-#define SELINUX_ANDROID_RESTORECON_RECURSE 4
-#define SELINUX_ANDROID_RESTORECON_FORCE 8
-#define SELINUX_ANDROID_RESTORECON_DATADATA 16
-extern int selinux_android_restorecon(const char *file, unsigned int flags);
-
-extern int selinux_android_restorecon_pkgdir(const char *pkgdir,
- const char *seinfo,
- uid_t uid,
- unsigned int flags);
-
-extern int selinux_android_seapp_context_reload(void);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/include/selinux/avc.h b/include/selinux/avc.h
deleted file mode 100644
index 8a1a6df..0000000
--- a/include/selinux/avc.h
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * Access vector cache interface for object managers.
- *
- * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
- */
-#ifndef _SELINUX_AVC_H_
-#define _SELINUX_AVC_H_
-
-#include <stdint.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <selinux/selinux.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * SID format and operations
- */
-struct security_id {
- char * ctx;
- unsigned int refcnt;
-};
-typedef struct security_id *security_id_t;
-
-#define SECSID_WILD (security_id_t)NULL /* unspecified SID */
-
-/**
- * avc_sid_to_context - get copy of context corresponding to SID.
- * @sid: input SID
- * @ctx: pointer to context reference
- *
- * Return a copy of the security context corresponding to the input
- * @sid in the memory referenced by @ctx. The caller is expected to
- * free the context with freecon(). Return %0 on success, -%1 on
- * failure, with @errno set to %ENOMEM if insufficient memory was
- * available to make the copy, or %EINVAL if the input SID is invalid.
- */
-int avc_sid_to_context(security_id_t sid, char ** ctx);
-int avc_sid_to_context_raw(security_id_t sid, char ** ctx);
-
-/**
- * avc_context_to_sid - get SID for context.
- * @ctx: input security context
- * @sid: pointer to SID reference
- *
- * Look up security context @ctx in SID table, making
- * a new entry if @ctx is not found. Increment the
- * reference counter for the SID. Store a pointer
- * to the SID structure into the memory referenced by @sid,
- * returning %0 on success or -%1 on error with @errno set.
- */
-int avc_context_to_sid(const char * ctx, security_id_t * sid);
-int avc_context_to_sid_raw(const char * ctx, security_id_t * sid);
-
-/**
- * sidget - increment SID reference counter.
- * @sid: SID reference
- *
- * Increment the reference counter for @sid, indicating that
- * @sid is in use by an (additional) object. Return the
- * new reference count, or zero if @sid is invalid (has zero
- * reference count). Note that avc_context_to_sid() also
- * increments reference counts.
- */
-int sidget(security_id_t sid);
-
-/**
- * sidput - decrement SID reference counter.
- * @sid: SID reference
- *
- * Decrement the reference counter for @sid, indicating that
- * a reference to @sid is no longer in use. Return the
- * new reference count. When the reference count reaches
- * zero, the SID is invalid, and avc_context_to_sid() must
- * be called to obtain a new SID for the security context.
- */
-int sidput(security_id_t sid);
-
-/**
- * avc_get_initial_sid - get SID for an initial kernel security identifier
- * @name: input name of initial kernel security identifier
- * @sid: pointer to a SID reference
- *
- * Get the context for an initial kernel security identifier specified by
- * @name using security_get_initial_context() and then call
- * avc_context_to_sid() to get the corresponding SID.
- */
-int avc_get_initial_sid(const char *name, security_id_t * sid);
-
-/*
- * AVC entry
- */
-struct avc_entry;
-struct avc_entry_ref {
- struct avc_entry *ae;
-};
-
-/**
- * avc_entry_ref_init - initialize an AVC entry reference.
- * @aeref: pointer to avc entry reference structure
- *
- * Use this macro to initialize an avc entry reference structure
- * before first use. These structures are passed to avc_has_perm(),
- * which stores cache entry references in them. They can increase
- * performance on repeated queries.
- */
-#define avc_entry_ref_init(aeref) ((aeref)->ae = NULL)
-
-/*
- * User-provided callbacks for memory, auditing, and locking
- */
-
-/* These structures are passed by reference to avc_init(). Passing
- * a NULL reference will cause the AVC to use a default. The default
- * memory callbacks are malloc() and free(). The default logging method
- * is to print on stderr. If no thread callbacks are passed, a separate
- * listening thread won't be started for kernel policy change messages.
- * If no locking callbacks are passed, no locking will take place.
- */
-struct avc_memory_callback {
- /* malloc() equivalent. */
- void *(*func_malloc) (size_t size);
- /* free() equivalent. */
- void (*func_free) (void *ptr);
- /* Note that these functions should set errno on failure.
- If not, some avc routines may return -1 without errno set. */
-};
-
-struct avc_log_callback {
- /* log the printf-style format and arguments. */
- void (*func_log) (const char *fmt, ...);
- /* store a string representation of auditdata (corresponding
- to the given security class) into msgbuf. */
- void (*func_audit) (void *auditdata, security_class_t cls,
- char *msgbuf, size_t msgbufsize);
-};
-
-struct avc_thread_callback {
- /* create and start a thread, returning an opaque pointer to it;
- the thread should run the given function. */
- void *(*func_create_thread) (void (*run) (void));
- /* cancel a given thread and free its resources. */
- void (*func_stop_thread) (void *thread);
-};
-
-struct avc_lock_callback {
- /* create a lock and return an opaque pointer to it. */
- void *(*func_alloc_lock) (void);
- /* obtain a given lock, blocking if necessary. */
- void (*func_get_lock) (void *lock);
- /* release a given lock. */
- void (*func_release_lock) (void *lock);
- /* destroy a given lock (free memory, etc.) */
- void (*func_free_lock) (void *lock);
-};
-
-/*
- * Available options
- */
-
-/* no-op option, useful for unused slots in an array of options */
-#define AVC_OPT_UNUSED 0
-/* override kernel enforcing mode (boolean value) */
-#define AVC_OPT_SETENFORCE 1
-
-/*
- * AVC operations
- */
-
-/**
- * avc_init - Initialize the AVC.
- * @msgprefix: prefix for log messages
- * @mem_callbacks: user-supplied memory callbacks
- * @log_callbacks: user-supplied logging callbacks
- * @thread_callbacks: user-supplied threading callbacks
- * @lock_callbacks: user-supplied locking callbacks
- *
- * Initialize the access vector cache. Return %0 on
- * success or -%1 with @errno set on failure.
- * If @msgprefix is NULL, use "uavc". If any callback
- * structure references are NULL, use default methods
- * for those callbacks (see the definition of the callback
- * structures above).
- */
-int avc_init(const char *msgprefix,
- const struct avc_memory_callback *mem_callbacks,
- const struct avc_log_callback *log_callbacks,
- const struct avc_thread_callback *thread_callbacks,
- const struct avc_lock_callback *lock_callbacks);
-
-/**
- * avc_open - Initialize the AVC.
- * @opts: array of selabel_opt structures specifying AVC options or NULL.
- * @nopts: number of elements in opts array or zero for no options.
- *
- * This function is identical to avc_init(), except the message prefix
- * is set to "avc" and any callbacks desired should be specified via
- * selinux_set_callback(). Available options are listed above.
- */
-int avc_open(struct selinux_opt *opts, unsigned nopts);
-
-/**
- * avc_cleanup - Remove unused SIDs and AVC entries.
- *
- * Search the SID table for SID structures with zero
- * reference counts, and remove them along with all
- * AVC entries that reference them. This can be used
- * to return memory to the system.
- */
-void avc_cleanup(void);
-
-/**
- * avc_reset - Flush the cache and reset statistics.
- *
- * Remove all entries from the cache and reset all access
- * statistics (as returned by avc_cache_stats()) to zero.
- * The SID mapping is not affected. Return %0 on success,
- * -%1 with @errno set on error.
- */
-int avc_reset(void);
-
-/**
- * avc_destroy - Free all AVC structures.
- *
- * Destroy all AVC structures and free all allocated
- * memory. User-supplied locking, memory, and audit
- * callbacks will be retained, but security-event
- * callbacks will not. All SID's will be invalidated.
- * User must call avc_init() if further use of AVC is desired.
- */
-void avc_destroy(void);
-
-/**
- * avc_has_perm_noaudit - Check permissions but perform no auditing.
- * @ssid: source security identifier
- * @tsid: target security identifier
- * @tclass: target security class
- * @requested: requested permissions, interpreted based on @tclass
- * @aeref: AVC entry reference
- * @avd: access vector decisions
- *
- * Check the AVC to determine whether the @requested permissions are granted
- * for the SID pair (@ssid, @tsid), interpreting the permissions
- * based on @tclass, and call the security server on a cache miss to obtain
- * a new decision and add it to the cache. Update @aeref to refer to an AVC
- * entry with the resulting decisions, and return a copy of the decisions
- * in @avd. Return %0 if all @requested permissions are granted, -%1 with
- * @errno set to %EACCES if any permissions are denied, or to another value
- * upon other errors. This function is typically called by avc_has_perm(),
- * but may also be called directly to separate permission checking from
- * auditing, e.g. in cases where a lock must be held for the check but
- * should be released for the auditing.
- */
-int avc_has_perm_noaudit(security_id_t ssid,
- security_id_t tsid,
- security_class_t tclass,
- access_vector_t requested,
- struct avc_entry_ref *aeref, struct av_decision *avd);
-
-/**
- * avc_has_perm - Check permissions and perform any appropriate auditing.
- * @ssid: source security identifier
- * @tsid: target security identifier
- * @tclass: target security class
- * @requested: requested permissions, interpreted based on @tclass
- * @aeref: AVC entry reference
- * @auditdata: auxiliary audit data
- *
- * Check the AVC to determine whether the @requested permissions are granted
- * for the SID pair (@ssid, @tsid), interpreting the permissions
- * based on @tclass, and call the security server on a cache miss to obtain
- * a new decision and add it to the cache. Update @aeref to refer to an AVC
- * entry with the resulting decisions. Audit the granting or denial of
- * permissions in accordance with the policy. Return %0 if all @requested
- * permissions are granted, -%1 with @errno set to %EACCES if any permissions
- * are denied or to another value upon other errors.
- */
-int avc_has_perm(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t requested,
- struct avc_entry_ref *aeref, void *auditdata);
-
-/**
- * avc_audit - Audit the granting or denial of permissions.
- * @ssid: source security identifier
- * @tsid: target security identifier
- * @tclass: target security class
- * @requested: requested permissions
- * @avd: access vector decisions
- * @result: result from avc_has_perm_noaudit
- * @auditdata: auxiliary audit data
- *
- * Audit the granting or denial of permissions in accordance
- * with the policy. This function is typically called by
- * avc_has_perm() after a permission check, but can also be
- * called directly by callers who use avc_has_perm_noaudit()
- * in order to separate the permission check from the auditing.
- * For example, this separation is useful when the permission check must
- * be performed under a lock, to allow the lock to be released
- * before calling the auditing code.
- */
-void avc_audit(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t requested,
- struct av_decision *avd, int result, void *auditdata);
-
-/**
- * avc_compute_create - Compute SID for labeling a new object.
- * @ssid: source security identifier
- * @tsid: target security identifier
- * @tclass: target security class
- * @newsid: pointer to SID reference
- *
- * Call the security server to obtain a context for labeling a
- * new object. Look up the context in the SID table, making
- * a new entry if not found. Increment the reference counter
- * for the SID. Store a pointer to the SID structure into the
- * memory referenced by @newsid, returning %0 on success or -%1 on
- * error with @errno set.
- */
-int avc_compute_create(security_id_t ssid,
- security_id_t tsid,
- security_class_t tclass, security_id_t * newsid);
-
-/**
- * avc_compute_member - Compute SID for polyinstantation.
- * @ssid: source security identifier
- * @tsid: target security identifier
- * @tclass: target security class
- * @newsid: pointer to SID reference
- *
- * Call the security server to obtain a context for labeling an
- * object instance. Look up the context in the SID table, making
- * a new entry if not found. Increment the reference counter
- * for the SID. Store a pointer to the SID structure into the
- * memory referenced by @newsid, returning %0 on success or -%1 on
- * error with @errno set.
- */
-int avc_compute_member(security_id_t ssid,
- security_id_t tsid,
- security_class_t tclass, security_id_t * newsid);
-
-/*
- * security event callback facility
- */
-
-/* security events */
-#define AVC_CALLBACK_GRANT 1
-#define AVC_CALLBACK_TRY_REVOKE 2
-#define AVC_CALLBACK_REVOKE 4
-#define AVC_CALLBACK_RESET 8
-#define AVC_CALLBACK_AUDITALLOW_ENABLE 16
-#define AVC_CALLBACK_AUDITALLOW_DISABLE 32
-#define AVC_CALLBACK_AUDITDENY_ENABLE 64
-#define AVC_CALLBACK_AUDITDENY_DISABLE 128
-
-/**
- * avc_add_callback - Register a callback for security events.
- * @callback: callback function
- * @events: bitwise OR of desired security events
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions
- *
- * Register a callback function for events in the set @events
- * related to the SID pair (@ssid, @tsid) and
- * and the permissions @perms, interpreting
- * @perms based on @tclass. Returns %0 on success or
- * -%1 if insufficient memory exists to add the callback.
- */
-int avc_add_callback(int (*callback)
- (uint32_t event, security_id_t ssid,
- security_id_t tsid, security_class_t tclass,
- access_vector_t perms,
- access_vector_t * out_retained),
- uint32_t events, security_id_t ssid,
- security_id_t tsid, security_class_t tclass,
- access_vector_t perms);
-
-/*
- * AVC statistics
- */
-
-/* If set, cache statistics are tracked. This may
- * become a compile-time option in the future.
- */
-#define AVC_CACHE_STATS 1
-
-struct avc_cache_stats {
- unsigned entry_lookups;
- unsigned entry_hits;
- unsigned entry_misses;
- unsigned entry_discards;
- unsigned cav_lookups;
- unsigned cav_hits;
- unsigned cav_probes;
- unsigned cav_misses;
-};
-
-/**
- * avc_cache_stats - get cache access statistics.
- * @stats: reference to statistics structure
- *
- * Fill the supplied structure with information about AVC
- * activity since the last call to avc_init() or
- * avc_reset(). See the structure definition for
- * details.
- */
-void avc_cache_stats(struct avc_cache_stats *stats);
-
-/**
- * avc_av_stats - log av table statistics.
- *
- * Log a message with information about the size and
- * distribution of the access vector table. The audit
- * callback is used to print the message.
- */
-void avc_av_stats(void);
-
-/**
- * avc_sid_stats - log SID table statistics.
- *
- * Log a message with information about the size and
- * distribution of the SID table. The audit callback
- * is used to print the message.
- */
-void avc_sid_stats(void);
-
-/**
- * avc_netlink_open - Create a netlink socket and connect to the kernel.
- */
-int avc_netlink_open(int blocking);
-
-/**
- * avc_netlink_loop - Wait for netlink messages from the kernel
- */
-void avc_netlink_loop(void);
-
-/**
- * avc_netlink_close - Close the netlink socket
- */
-void avc_netlink_close(void);
-
-/**
- * avc_netlink_acquire_fd - Acquire netlink socket fd.
- *
- * Allows the application to manage messages from the netlink socket in
- * its own main loop.
- */
-int avc_netlink_acquire_fd(void);
-
-/**
- * avc_netlink_release_fd - Release netlink socket fd.
- *
- * Returns ownership of the netlink socket to the library.
- */
-void avc_netlink_release_fd(void);
-
-/**
- * avc_netlink_check_nb - Check netlink socket for new messages.
- *
- * Called by the application when using avc_netlink_acquire_fd() to
- * process kernel netlink events.
- */
-int avc_netlink_check_nb(void);
-
-/**
- * selinux_status_open - Open and map SELinux kernel status page
- *
- */
-int selinux_status_open(int fallback);
-
-/**
- * selinux_status_close - Unmap and close SELinux kernel status page
- *
- */
-void selinux_status_close(void);
-
-/**
- * selinux_status_updated - Inform us whether the kernel status has been updated
- *
- */
-int selinux_status_updated(void);
-
-/**
- * selinux_status_getenforce - Get the enforce flag value
- *
- */
-int selinux_status_getenforce(void);
-
-/**
- * selinux_status_policyload - Get the number of policy reloaded
- *
- */
-int selinux_status_policyload(void);
-
-/**
- * selinux_status_deny_unknown - Get the behavior for undefined classes/permissions
- *
- */
-int selinux_status_deny_unknown(void);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* _SELINUX_AVC_H_ */
diff --git a/include/selinux/context.h b/include/selinux/context.h
deleted file mode 100644
index 949fb1e..0000000
--- a/include/selinux/context.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef _SELINUX_CONTEXT_H_
-#define _SELINUX_CONTEXT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Functions to deal with security contexts in user space.
- */
-
- typedef struct {
- void *ptr;
- } context_s_t;
-
- typedef context_s_t *context_t;
-
-/* Return a new context initialized to a context string */
-
- extern context_t context_new(const char *);
-
-/*
- * Return a pointer to the string value of the context_t
- * Valid until the next call to context_str or context_free
- * for the same context_t*
- */
-
- extern char *context_str(context_t);
-
-/* Free the storage used by a context */
- extern void context_free(context_t);
-
-/* Get a pointer to the string value of a context component */
-
- extern const char *context_type_get(context_t);
- extern const char *context_range_get(context_t);
- extern const char *context_role_get(context_t);
- extern const char *context_user_get(context_t);
-
-/* Set a context component. Returns nonzero if unsuccessful */
-
- extern int context_type_set(context_t, const char *);
- extern int context_range_set(context_t, const char *);
- extern int context_role_set(context_t, const char *);
- extern int context_user_set(context_t, const char *);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/include/selinux/label.h b/include/selinux/label.h
deleted file mode 100644
index 07eff74..0000000
--- a/include/selinux/label.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Labeling interface for userspace object managers and others.
- *
- * Author : Eamon Walsh <ewalsh@tycho.nsa.gov>
- */
-#ifndef _SELABEL_H_
-#define _SELABEL_H_
-
-#include <stdbool.h>
-#include <sys/types.h>
-#include <selinux/selinux.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Opaque type used for all label handles.
- */
-
-struct selabel_handle;
-
-/*
- * Available backends.
- */
-
-/* file contexts */
-#define SELABEL_CTX_FILE 0
-/* media contexts */
-#define SELABEL_CTX_MEDIA 1
-/* x contexts */
-#define SELABEL_CTX_X 2
-/* db objects */
-#define SELABEL_CTX_DB 3
-/* Android property contexts */
-#define SELABEL_CTX_ANDROID_PROP 4
-/* Android service contexts */
-#define SELABEL_CTX_ANDROID_SERVICE 5
-
-/*
- * Available options
- */
-
-/* no-op option, useful for unused slots in an array of options */
-#define SELABEL_OPT_UNUSED 0
-/* validate contexts before returning them (boolean value) */
-#define SELABEL_OPT_VALIDATE 1
-/* don't use local customizations to backend data (boolean value) */
-#define SELABEL_OPT_BASEONLY 2
-/* specify an alternate path to use when loading backend data */
-#define SELABEL_OPT_PATH 3
-/* select a subset of the search space as an optimization (file backend) */
-#define SELABEL_OPT_SUBSET 4
-/* total number of options */
-#define SELABEL_NOPT 5
-
-/*
- * Label operations
- */
-
-/**
- * selabel_open - Create a labeling handle.
- * @backend: one of the constants specifying a supported labeling backend.
- * @opts: array of selabel_opt structures specifying label options or NULL.
- * @nopts: number of elements in opts array or zero for no options.
- *
- * Open a labeling backend for use. The available backend identifiers are
- * listed above. Options may be provided via the opts parameter; available
- * options are listed above. Not all options may be supported by every
- * backend. Return value is the created handle on success or NULL with
- * @errno set on failure.
- */
-struct selabel_handle *selabel_open(unsigned int backend,
- const struct selinux_opt *opts,
- unsigned nopts);
-
-/**
- * selabel_close - Close a labeling handle.
- * @handle: specifies handle to close
- *
- * Destroy the specified handle, closing files, freeing allocated memory,
- * etc. The handle may not be further used after it has been closed.
- */
-void selabel_close(struct selabel_handle *handle);
-
-/**
- * selabel_lookup - Perform labeling lookup operation.
- * @handle: specifies backend instance to query
- * @con: returns the appropriate context with which to label the object
- * @key: string input to lookup operation
- * @type: numeric input to the lookup operation
- *
- * Perform a labeling lookup operation. Return %0 on success, -%1 with
- * @errno set on failure. The key and type arguments are the inputs to the
- * lookup operation; appropriate values are dictated by the backend in use.
- * The result is returned in the memory pointed to by @con and must be freed
- * by the user with freecon().
- */
-int selabel_lookup(struct selabel_handle *handle, char **con,
- const char *key, int type);
-int selabel_lookup_raw(struct selabel_handle *handle, char **con,
- const char *key, int type);
-
-bool selabel_partial_match(struct selabel_handle *handle, const char *key);
-
-int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
- const char *key, const char **aliases, int type);
-
-enum selabel_cmp_result {
- SELABEL_SUBSET,
- SELABEL_EQUAL,
- SELABEL_SUPERSET,
- SELABEL_INCOMPARABLE
-};
-
-/**
- * selabel_cmp - Compare two label configurations.
- * @h1: handle for the first label configuration
- * @h2: handle for the first label configuration
- *
- * Compare two label configurations.
- * Return %SELABEL_SUBSET if @h1 is a subset of @h2, %SELABEL_EQUAL
- * if @h1 is identical to @h2, %SELABEL_SUPERSET if @h1 is a superset
- * of @h2, and %SELABEL_INCOMPARABLE if @h1 and @h2 are incomparable.
- */
-enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1,
- struct selabel_handle *h2);
-
-/**
- * selabel_stats - log labeling operation statistics.
- * @handle: specifies backend instance to query
- *
- * Log a message with information about the number of queries performed,
- * number of unused matching entries, or other operational statistics.
- * Message is backend-specific, some backends may not output a message.
- */
-void selabel_stats(struct selabel_handle *handle);
-
-/*
- * Type codes used by specific backends
- */
-
-/* X backend */
-#define SELABEL_X_PROP 1
-#define SELABEL_X_EXT 2
-#define SELABEL_X_CLIENT 3
-#define SELABEL_X_EVENT 4
-#define SELABEL_X_SELN 5
-#define SELABEL_X_POLYPROP 6
-#define SELABEL_X_POLYSELN 7
-
-/* DB backend */
-#define SELABEL_DB_DATABASE 1
-#define SELABEL_DB_SCHEMA 2
-#define SELABEL_DB_TABLE 3
-#define SELABEL_DB_COLUMN 4
-#define SELABEL_DB_SEQUENCE 5
-#define SELABEL_DB_VIEW 6
-#define SELABEL_DB_PROCEDURE 7
-#define SELABEL_DB_BLOB 8
-#define SELABEL_DB_TUPLE 9
-#define SELABEL_DB_LANGUAGE 10
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* _SELABEL_H_ */
diff --git a/include/selinux/selinux.h b/include/selinux/selinux.h
deleted file mode 100644
index 8827da8..0000000
--- a/include/selinux/selinux.h
+++ /dev/null
@@ -1,291 +0,0 @@
-#ifndef _SELINUX_H_
-#define _SELINUX_H_
-
-#include <sys/types.h>
-#include <stdarg.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Return 1 if we are running on a SELinux kernel, or 0 if not or -1 if we get an error. */
-extern int is_selinux_enabled(void);
-/* Return 1 if we are running on a SELinux MLS kernel, or 0 otherwise. */
-extern int is_selinux_mls_enabled(void);
-
-/* No longer used; here for compatibility with legacy callers. */
-typedef char *security_context_t;
-
-/* Free the memory allocated for a context by any of the below get* calls. */
-extern void freecon(char * con);
-
-/* Free the memory allocated for a context array by security_compute_user. */
-extern void freeconary(char ** con);
-
-/* Wrappers for the /proc/pid/attr API. */
-
-/* Get current context, and set *con to refer to it.
- Caller must free via freecon. */
-extern int getcon(char ** con);
-
-/* Set the current security context to con.
- Note that use of this function requires that the entire application
- be trusted to maintain any desired separation between the old and new
- security contexts, unlike exec-based transitions performed via setexeccon.
- When possible, decompose your application and use setexeccon()+execve()
- instead. Note that the application may lose access to its open descriptors
- as a result of a setcon() unless policy allows it to use descriptors opened
- by the old context. */
-extern int setcon(const char * con);
-
-/* Get context of process identified by pid, and
- set *con to refer to it. Caller must free via freecon. */
-extern int getpidcon(pid_t pid, char ** con);
-
-/* Get previous context (prior to last exec), and set *con to refer to it.
- Caller must free via freecon. */
-extern int getprevcon(char ** con);
-
-/* Get exec context, and set *con to refer to it.
- Sets *con to NULL if no exec context has been set, i.e. using default.
- If non-NULL, caller must free via freecon. */
-extern int getexeccon(char ** con);
-
-/* Set exec security context for the next execve.
- Call with NULL if you want to reset to the default. */
-extern int setexeccon(const char * con);
-
-/* Get fscreate context, and set *con to refer to it.
- Sets *con to NULL if no fs create context has been set, i.e. using default.
- If non-NULL, caller must free via freecon. */
-extern int getfscreatecon(char ** con);
-
-/* Set the fscreate security context for subsequent file creations.
- Call with NULL if you want to reset to the default. */
-extern int setfscreatecon(const char * context);
-
-/* Get keycreate context, and set *con to refer to it.
- Sets *con to NULL if no key create context has been set, i.e. using default.
- If non-NULL, caller must free via freecon. */
-extern int getkeycreatecon(char ** con);
-
-/* Set the keycreate security context for subsequent key creations.
- Call with NULL if you want to reset to the default. */
-extern int setkeycreatecon(const char * context);
-
-/* Get sockcreate context, and set *con to refer to it.
- Sets *con to NULL if no socket create context has been set, i.e. using default.
- If non-NULL, caller must free via freecon. */
-extern int getsockcreatecon(char ** con);
-
-/* Set the sockcreate security context for subsequent socket creations.
- Call with NULL if you want to reset to the default. */
-extern int setsockcreatecon(const char * context);
-
-/* Wrappers for the xattr API. */
-
-/* Get file context, and set *con to refer to it.
- Caller must free via freecon. */
-extern int getfilecon(const char *path, char ** con);
-extern int lgetfilecon(const char *path, char ** con);
-extern int fgetfilecon(int fd, char ** con);
-
-/* Set file context */
-extern int setfilecon(const char *path, const char *con);
-extern int lsetfilecon(const char *path, const char *con);
-extern int fsetfilecon(int fd, const char *con);
-
-/* Wrappers for the socket API */
-
-/* Get context of peer socket, and set *con to refer to it.
- Caller must free via freecon. */
-extern int getpeercon(int fd, char ** con);
-
-/* Wrappers for the selinuxfs (policy) API. */
-
-typedef unsigned int access_vector_t;
-typedef unsigned short security_class_t;
-
-struct av_decision {
- access_vector_t allowed;
- access_vector_t decided;
- access_vector_t auditallow;
- access_vector_t auditdeny;
- unsigned int seqno;
- unsigned int flags;
-};
-
-/* Definitions of av_decision.flags */
-#define SELINUX_AVD_FLAGS_PERMISSIVE 0x0001
-
-/* Structure for passing options, used by AVC and label subsystems */
-struct selinux_opt {
- int type;
- const char *value;
-};
-
-/* Callback facilities */
-union selinux_callback {
- /* log the printf-style format and arguments,
- with the type code indicating the type of message */
- int
-#ifdef __GNUC__
-__attribute__ ((format(printf, 2, 3)))
-#endif
- (*func_log) (int type, const char *fmt, ...);
- /* store a string representation of auditdata (corresponding
- to the given security class) into msgbuf. */
- int (*func_audit) (void *auditdata, security_class_t cls,
- char *msgbuf, size_t msgbufsize);
- /* validate the supplied context, modifying if necessary */
- int (*func_validate) (char **ctx);
- /* netlink callback for setenforce message */
- int (*func_setenforce) (int enforcing);
- /* netlink callback for policyload message */
- int (*func_policyload) (int seqno);
-};
-
-#define SELINUX_CB_LOG 0
-#define SELINUX_CB_AUDIT 1
-#define SELINUX_CB_VALIDATE 2
-#define SELINUX_CB_SETENFORCE 3
-#define SELINUX_CB_POLICYLOAD 4
-
-extern union selinux_callback selinux_get_callback(int type);
-extern void selinux_set_callback(int type, union selinux_callback cb);
-
- /* Logging type codes, passed to the logging callback */
-#define SELINUX_ERROR 0
-#define SELINUX_WARNING 1
-#define SELINUX_INFO 2
-#define SELINUX_AVC 3
-
-/* Compute an access decision. */
-extern int security_compute_av(const char * scon,
- const char * tcon,
- security_class_t tclass,
- access_vector_t requested,
- struct av_decision *avd);
-
-/* Compute a labeling decision and set *newcon to refer to it.
- Caller must free via freecon. */
-extern int security_compute_create(const char * scon,
- const char * tcon,
- security_class_t tclass,
- char ** newcon);
-
-/* Compute a relabeling decision and set *newcon to refer to it.
- Caller must free via freecon. */
-extern int security_compute_relabel(const char * scon,
- const char * tcon,
- security_class_t tclass,
- char ** newcon);
-
-/* Compute a polyinstantiation member decision and set *newcon to refer to it.
- Caller must free via freecon. */
-extern int security_compute_member(const char * scon,
- const char * tcon,
- security_class_t tclass,
- char ** newcon);
-
-/* Compute the set of reachable user contexts and set *con to refer to
- the NULL-terminated array of contexts. Caller must free via freeconary. */
-extern int security_compute_user(const char * scon,
- const char *username,
- char *** con);
-
-/* Load a policy configuration. */
-extern int security_load_policy(void *data, size_t len);
-
-/* Get the context of an initial kernel security identifier by name.
- Caller must free via freecon */
-extern int security_get_initial_context(const char *name,
- char ** con);
-
-/* Translate boolean strict to name value pair. */
-typedef struct {
- const char *name;
- int value;
-} SELboolean;
-/* save a list of booleans in a single transaction. */
-extern int security_set_boolean_list(size_t boolcnt,
- SELboolean * const boollist, int permanent);
-
-/* Check the validity of a security context. */
-extern int security_check_context(const char * con);
-
-/* Canonicalize a security context. */
-extern int security_canonicalize_context(const char * con,
- char ** canoncon);
-
-/* Get the enforce flag value. */
-extern int security_getenforce(void);
-
-/* Set the enforce flag value. */
-extern int security_setenforce(int value);
-
-/* Get the behavior for undefined classes/permissions */
-extern int security_deny_unknown(void);
-
-/* Disable SELinux at runtime (must be done prior to initial policy load). */
-extern int security_disable(void);
-
-/* Get the policy version number. */
-extern int security_policyvers(void);
-
-/* Get the boolean names */
-extern int security_get_boolean_names(char ***names, int *len);
-
-/* Get the pending value for the boolean */
-extern int security_get_boolean_pending(const char *name);
-
-/* Get the active value for the boolean */
-extern int security_get_boolean_active(const char *name);
-
-/* Set the pending value for the boolean */
-extern int security_set_boolean(const char *name, int value);
-
-/* Commit the pending values for the booleans */
-extern int security_commit_booleans(void);
-
-/* Userspace class mapping support */
-struct security_class_mapping {
- const char *name;
- const char *perms[sizeof(access_vector_t) * 8 + 1];
-};
-
-extern int selinux_set_mapping(struct security_class_mapping *map);
-
-/* Common helpers */
-
-/* Convert between security class values and string names */
-extern security_class_t string_to_security_class(const char *name);
-extern const char *security_class_to_string(security_class_t cls);
-
-/* Convert between individual access vector permissions and string names */
-extern const char *security_av_perm_to_string(security_class_t tclass,
- access_vector_t perm);
-extern access_vector_t string_to_av_perm(security_class_t tclass,
- const char *name);
-
-/* Returns an access vector in a string representation. User must free the
- * returned string via free(). */
-extern int security_av_string(security_class_t tclass,
- access_vector_t av, char **result);
-
-/* Check permissions and perform appropriate auditing. */
-extern int selinux_check_access(const char * scon,
- const char * tcon,
- const char *tclass,
- const char *perm, void *aux);
-
-/* Set the path to the selinuxfs mount point explicitly.
- Normally, this is determined automatically during libselinux
- initialization, but this is not always possible, e.g. for /sbin/init
- which performs the initial mount of selinuxfs. */
-void set_selinuxmnt(const char *mnt);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/src/android.c b/src/android.c
deleted file mode 100644
index ff3a277..0000000
--- a/src/android.c
+++ /dev/null
@@ -1,1538 +0,0 @@
-#include <sys/types.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <ctype.h>
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/xattr.h>
-#include <fcntl.h>
-#include <fts.h>
-#include <selinux/selinux.h>
-#include <selinux/context.h>
-#include <selinux/android.h>
-#include <selinux/label.h>
-#include <selinux/avc.h>
-#include <openssl/sha.h>
-#include <private/android_filesystem_config.h>
-#include <log/log.h>
-#include "policy.h"
-#include "callbacks.h"
-#include "selinux_internal.h"
-#include "label_internal.h"
-#include <fnmatch.h>
-#include <limits.h>
-#include <sys/vfs.h>
-#include <linux/magic.h>
-#include <libgen.h>
-#include <packagelistparser/packagelistparser.h>
-
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
-
-/*
- * XXX Where should this configuration file be located?
- * Needs to be accessible by zygote and installd when
- * setting credentials for app processes and setting permissions
- * on app data directories.
- */
-static char const * const seapp_contexts_file = "/seapp_contexts";
-
-static const struct selinux_opt seopts =
- { SELABEL_OPT_PATH, "/file_contexts.bin" };
-
-static const char *const sepolicy_file = "/sepolicy";
-
-static const struct selinux_opt seopts_prop =
- { SELABEL_OPT_PATH, "/property_contexts" };
-
-static const struct selinux_opt seopts_service =
- { SELABEL_OPT_PATH, "/service_contexts" };
-
-enum levelFrom {
- LEVELFROM_NONE,
- LEVELFROM_APP,
- LEVELFROM_USER,
- LEVELFROM_ALL
-};
-
-#if DEBUG
-static char const * const levelFromName[] = {
- "none",
- "app",
- "user",
- "all"
-};
-#endif
-
-struct prefix_str {
- size_t len;
- char *str;
- char is_prefix;
-};
-
-static void free_prefix_str(struct prefix_str *p)
-{
- if (!p)
- return;
- free(p->str);
-}
-
-struct seapp_context {
- /* input selectors */
- bool isSystemServer;
- bool isEphemeralAppSet;
- bool isEphemeralApp;
- bool isOwnerSet;
- bool isOwner;
- struct prefix_str user;
- char *seinfo;
- struct prefix_str name;
- struct prefix_str path;
- bool isPrivAppSet;
- bool isPrivApp;
- /* outputs */
- char *domain;
- char *type;
- char *level;
- enum levelFrom levelFrom;
-};
-
-static void free_seapp_context(struct seapp_context *s)
-{
- if (!s)
- return;
-
- free_prefix_str(&s->user);
- free(s->seinfo);
- free_prefix_str(&s->name);
- free_prefix_str(&s->path);
- free(s->domain);
- free(s->type);
- free(s->level);
-}
-
-static bool seapp_contexts_dup = false;
-
-static int seapp_context_cmp(const void *A, const void *B)
-{
- const struct seapp_context *const *sp1 = (const struct seapp_context *const *) A;
- const struct seapp_context *const *sp2 = (const struct seapp_context *const *) B;
- const struct seapp_context *s1 = *sp1, *s2 = *sp2;
- bool dup;
-
- /* Give precedence to isSystemServer=true. */
- if (s1->isSystemServer != s2->isSystemServer)
- return (s1->isSystemServer ? -1 : 1);
-
- /* Give precedence to a specified isEphemeral= over an
- * unspecified isEphemeral=. */
- if (s1->isEphemeralAppSet != s2->isEphemeralAppSet)
- return (s1->isEphemeralAppSet ? -1 : 1);
-
-
- /* Give precedence to a specified isOwner= over an unspecified isOwner=. */
- if (s1->isOwnerSet != s2->isOwnerSet)
- return (s1->isOwnerSet ? -1 : 1);
-
- /* Give precedence to a specified user= over an unspecified user=. */
- if (s1->user.str && !s2->user.str)
- return -1;
- if (!s1->user.str && s2->user.str)
- return 1;
-
- if (s1->user.str) {
- /* Give precedence to a fixed user= string over a prefix. */
- if (s1->user.is_prefix != s2->user.is_prefix)
- return (s2->user.is_prefix ? -1 : 1);
-
- /* Give precedence to a longer prefix over a shorter prefix. */
- if (s1->user.is_prefix && s1->user.len != s2->user.len)
- return (s1->user.len > s2->user.len) ? -1 : 1;
- }
-
- /* Give precedence to a specified seinfo= over an unspecified seinfo=. */
- if (s1->seinfo && !s2->seinfo)
- return -1;
- if (!s1->seinfo && s2->seinfo)
- return 1;
-
- /* Give precedence to a specified name= over an unspecified name=. */
- if (s1->name.str && !s2->name.str)
- return -1;
- if (!s1->name.str && s2->name.str)
- return 1;
-
- if (s1->name.str) {
- /* Give precedence to a fixed name= string over a prefix. */
- if (s1->name.is_prefix != s2->name.is_prefix)
- return (s2->name.is_prefix ? -1 : 1);
-
- /* Give precedence to a longer prefix over a shorter prefix. */
- if (s1->name.is_prefix && s1->name.len != s2->name.len)
- return (s1->name.len > s2->name.len) ? -1 : 1;
- }
-
- /* Give precedence to a specified path= over an unspecified path=. */
- if (s1->path.str && !s2->path.str)
- return -1;
- if (!s1->path.str && s2->path.str)
- return 1;
-
- if (s1->path.str) {
- /* Give precedence to a fixed path= string over a prefix. */
- if (s1->path.is_prefix != s2->path.is_prefix)
- return (s2->path.is_prefix ? -1 : 1);
-
- /* Give precedence to a longer prefix over a shorter prefix. */
- if (s1->path.is_prefix && s1->path.len != s2->path.len)
- return (s1->path.len > s2->path.len) ? -1 : 1;
- }
-
- /* Give precedence to a specified isPrivApp= over an unspecified isPrivApp=. */
- if (s1->isPrivAppSet != s2->isPrivAppSet)
- return (s1->isPrivAppSet ? -1 : 1);
-
- /*
- * Check for a duplicated entry on the input selectors.
- * We already compared isSystemServer, isOwnerSet, and isOwner above.
- * We also have already checked that both entries specify the same
- * string fields, so if s1 has a non-NULL string, then so does s2.
- */
- dup = (!s1->user.str || !strcmp(s1->user.str, s2->user.str)) &&
- (!s1->seinfo || !strcmp(s1->seinfo, s2->seinfo)) &&
- (!s1->name.str || !strcmp(s1->name.str, s2->name.str)) &&
- (!s1->path.str || !strcmp(s1->path.str, s2->path.str));
- if (dup) {
- seapp_contexts_dup = true;
- selinux_log(SELINUX_ERROR, "seapp_contexts: Duplicated entry\n");
- if (s1->user.str)
- selinux_log(SELINUX_ERROR, " user=%s\n", s1->user.str);
- if (s1->seinfo)
- selinux_log(SELINUX_ERROR, " seinfo=%s\n", s1->seinfo);
- if (s1->name.str)
- selinux_log(SELINUX_ERROR, " name=%s\n", s1->name.str);
- if (s1->path.str)
- selinux_log(SELINUX_ERROR, " path=%s\n", s1->path.str);
- }
-
- /* Anything else has equal precedence. */
- return 0;
-}
-
-static struct seapp_context **seapp_contexts = NULL;
-static int nspec = 0;
-
-static void free_seapp_contexts(void)
-{
- int n;
-
- if (!seapp_contexts)
- return;
-
- for (n = 0; n < nspec; n++)
- free_seapp_context(seapp_contexts[n]);
-
- free(seapp_contexts);
- seapp_contexts = NULL;
- nspec = 0;
-}
-
-int selinux_android_seapp_context_reload(void)
-{
- FILE *fp = NULL;
- char line_buf[BUFSIZ];
- char *token;
- unsigned lineno;
- struct seapp_context *cur;
- char *p, *name = NULL, *value = NULL, *saveptr;
- size_t len;
- int n, ret;
-
- fp = fopen(seapp_contexts_file, "re");
- if (!fp) {
- selinux_log(SELINUX_ERROR, "%s: could not open any seapp_contexts file", __FUNCTION__);
- return -1;
- }
-
- free_seapp_contexts();
-
- nspec = 0;
- while (fgets(line_buf, sizeof line_buf - 1, fp)) {
- p = line_buf;
- while (isspace(*p))
- p++;
- if (*p == '#' || *p == 0)
- continue;
- nspec++;
- }
-
- seapp_contexts = (struct seapp_context **) calloc(nspec, sizeof(struct seapp_context *));
- if (!seapp_contexts)
- goto oom;
-
- rewind(fp);
- nspec = 0;
- lineno = 1;
- while (fgets(line_buf, sizeof line_buf - 1, fp)) {
- len = strlen(line_buf);
- if (line_buf[len - 1] == '\n')
- line_buf[len - 1] = 0;
- p = line_buf;
- while (isspace(*p))
- p++;
- if (*p == '#' || *p == 0)
- continue;
-
- cur = (struct seapp_context *) calloc(1, sizeof(struct seapp_context));
- if (!cur)
- goto oom;
-
- token = strtok_r(p, " \t", &saveptr);
- if (!token) {
- free_seapp_context(cur);
- goto err;
- }
-
- while (1) {
- name = token;
- value = strchr(name, '=');
- if (!value) {
- free_seapp_context(cur);
- goto err;
- }
- *value++ = 0;
-
- if (!strcasecmp(name, "isSystemServer")) {
- if (!strcasecmp(value, "true"))
- cur->isSystemServer = true;
- else if (!strcasecmp(value, "false"))
- cur->isSystemServer = false;
- else {
- free_seapp_context(cur);
- goto err;
- }
- } else if (!strcasecmp(name, "isEphemeralApp")) {
- cur->isEphemeralAppSet = true;
- if (!strcasecmp(value, "true"))
- cur->isEphemeralApp = true;
- else if (!strcasecmp(value, "false"))
- cur->isEphemeralApp = false;
- else {
- free_seapp_context(cur);
- goto err;
- }
- } else if (!strcasecmp(name, "isOwner")) {
- cur->isOwnerSet = true;
- if (!strcasecmp(value, "true"))
- cur->isOwner = true;
- else if (!strcasecmp(value, "false"))
- cur->isOwner = false;
- else {
- free_seapp_context(cur);
- goto err;
- }
- } else if (!strcasecmp(name, "user")) {
- if (cur->user.str) {
- free_seapp_context(cur);
- goto err;
- }
- cur->user.str = strdup(value);
- if (!cur->user.str) {
- free_seapp_context(cur);
- goto oom;
- }
- cur->user.len = strlen(cur->user.str);
- if (cur->user.str[cur->user.len-1] == '*')
- cur->user.is_prefix = 1;
- } else if (!strcasecmp(name, "seinfo")) {
- if (cur->seinfo) {
- free_seapp_context(cur);
- goto err;
- }
- cur->seinfo = strdup(value);
- if (!cur->seinfo) {
- free_seapp_context(cur);
- goto oom;
- }
- if (strstr(value, ":")) {
- free_seapp_context(cur);
- goto err;
- }
- } else if (!strcasecmp(name, "name")) {
- if (cur->name.str) {
- free_seapp_context(cur);
- goto err;
- }
- cur->name.str = strdup(value);
- if (!cur->name.str) {
- free_seapp_context(cur);
- goto oom;
- }
- cur->name.len = strlen(cur->name.str);
- if (cur->name.str[cur->name.len-1] == '*')
- cur->name.is_prefix = 1;
- } else if (!strcasecmp(name, "domain")) {
- if (cur->domain) {
- free_seapp_context(cur);
- goto err;
- }
- cur->domain = strdup(value);
- if (!cur->domain) {
- free_seapp_context(cur);
- goto oom;
- }
- } else if (!strcasecmp(name, "type")) {
- if (cur->type) {
- free_seapp_context(cur);
- goto err;
- }
- cur->type = strdup(value);
- if (!cur->type) {
- free_seapp_context(cur);
- goto oom;
- }
- } else if (!strcasecmp(name, "levelFromUid")) {
- if (cur->levelFrom) {
- free_seapp_context(cur);
- goto err;
- }
- if (!strcasecmp(value, "true"))
- cur->levelFrom = LEVELFROM_APP;
- else if (!strcasecmp(value, "false"))
- cur->levelFrom = LEVELFROM_NONE;
- else {
- free_seapp_context(cur);
- goto err;
- }
- } else if (!strcasecmp(name, "levelFrom")) {
- if (cur->levelFrom) {
- free_seapp_context(cur);
- goto err;
- }
- if (!strcasecmp(value, "none"))
- cur->levelFrom = LEVELFROM_NONE;
- else if (!strcasecmp(value, "app"))
- cur->levelFrom = LEVELFROM_APP;
- else if (!strcasecmp(value, "user"))
- cur->levelFrom = LEVELFROM_USER;
- else if (!strcasecmp(value, "all"))
- cur->levelFrom = LEVELFROM_ALL;
- else {
- free_seapp_context(cur);
- goto err;
- }
- } else if (!strcasecmp(name, "level")) {
- if (cur->level) {
- free_seapp_context(cur);
- goto err;
- }
- cur->level = strdup(value);
- if (!cur->level) {
- free_seapp_context(cur);
- goto oom;
- }
- } else if (!strcasecmp(name, "path")) {
- if (cur->path.str) {
- free_seapp_context(cur);
- goto err;
- }
- cur->path.str = strdup(value);
- if (!cur->path.str) {
- free_seapp_context(cur);
- goto oom;
- }
- cur->path.len = strlen(cur->path.str);
- if (cur->path.str[cur->path.len-1] == '*')
- cur->path.is_prefix = 1;
- } else if (!strcasecmp(name, "isPrivApp")) {
- cur->isPrivAppSet = true;
- if (!strcasecmp(value, "true"))
- cur->isPrivApp = true;
- else if (!strcasecmp(value, "false"))
- cur->isPrivApp = false;
- else {
- free_seapp_context(cur);
- goto err;
- }
- } else {
- free_seapp_context(cur);
- goto err;
- }
-
- token = strtok_r(NULL, " \t", &saveptr);
- if (!token)
- break;
- }
-
- if (cur->name.str &&
- (!cur->seinfo || !strcmp(cur->seinfo, "default"))) {
- selinux_log(SELINUX_ERROR, "%s: No specific seinfo value specified with name=\"%s\", on line %u: insecure configuration!\n",
- seapp_contexts_file, cur->name.str, lineno);
- free_seapp_context(cur);
- goto err;
- }
-
- seapp_contexts[nspec] = cur;
- nspec++;
- lineno++;
- }
-
- qsort(seapp_contexts, nspec, sizeof(struct seapp_context *),
- seapp_context_cmp);
-
- if (seapp_contexts_dup)
- goto err;
-
-#if DEBUG
- {
- int i;
- for (i = 0; i < nspec; i++) {
- cur = seapp_contexts[i];
- selinux_log(SELINUX_INFO, "%s: isSystemServer=%s isEphemeralApp=%s isOwner=%s user=%s seinfo=%s "
- "name=%s path=%s isPrivApp=%s -> domain=%s type=%s level=%s levelFrom=%s",
- __FUNCTION__,
- cur->isSystemServer ? "true" : "false",
- cur->isEphemeralAppSet ? (cur->isEphemeralApp ? "true" : "false") : "null",
- cur->isOwnerSet ? (cur->isOwner ? "true" : "false") : "null",
- cur->user.str,
- cur->seinfo, cur->name.str, cur->path.str,
- cur->isPrivAppSet ? (cur->isPrivApp ? "true" : "false") : "null",
- cur->domain, cur->type, cur->level,
- levelFromName[cur->levelFrom]);
- }
- }
-#endif
-
- ret = 0;
-
-out:
- fclose(fp);
- return ret;
-
-err:
- selinux_log(SELINUX_ERROR, "%s: Invalid entry on line %u\n",
- seapp_contexts_file, lineno);
- free_seapp_contexts();
- ret = -1;
- goto out;
-oom:
- selinux_log(SELINUX_ERROR,
- "%s: Out of memory\n", __FUNCTION__);
- free_seapp_contexts();
- ret = -1;
- goto out;
-}
-
-
-static void seapp_context_init(void)
-{
- selinux_android_seapp_context_reload();
-}
-
-static pthread_once_t once = PTHREAD_ONCE_INIT;
-
-/*
- * Max id that can be mapped to category set uniquely
- * using the current scheme.
- */
-#define CAT_MAPPING_MAX_ID (0x1<<16)
-
-enum seapp_kind {
- SEAPP_TYPE,
- SEAPP_DOMAIN
-};
-
-#define PRIVILEGED_APP_STR ":privapp"
-#define EPHEMERAL_APP_STR ":ephemeralapp"
-
-static int seinfo_parse(char *dest, const char *src, size_t size)
-{
- size_t len;
- char *p;
-
- if ((p = strchr(src, ':')) != NULL)
- len = p - src;
- else
- len = strlen(src);
-
- if (len > size - 1)
- return -1;
-
- strncpy(dest, src, len);
- dest[len] = '\0';
-
- return 0;
-}
-
-static int seapp_context_lookup(enum seapp_kind kind,
- uid_t uid,
- bool isSystemServer,
- const char *seinfo,
- const char *pkgname,
- const char *path,
- context_t ctx)
-{
- struct passwd *pwd;
- bool isOwner;
- const char *username = NULL;
- struct seapp_context *cur = NULL;
- int i;
- size_t n;
- uid_t userid;
- uid_t appid;
- bool isPrivApp = false;
- bool isEphemeralApp = false;
- char parsedseinfo[BUFSIZ];
-
- __selinux_once(once, seapp_context_init);
-
- if (seinfo) {
- if (seinfo_parse(parsedseinfo, seinfo, BUFSIZ))
- goto err;
- isPrivApp = strstr(seinfo, PRIVILEGED_APP_STR) ? true : false;
- isEphemeralApp = strstr(seinfo, EPHEMERAL_APP_STR) ? true : false;
- seinfo = parsedseinfo;
- }
-
- userid = uid / AID_USER;
- isOwner = (userid == 0);
- appid = uid % AID_USER;
- if (appid < AID_APP) {
- /*
- * This code is Android specific, bionic guarantees that
- * calls to non-reentrant getpwuid() are thread safe.
- */
-#ifndef __BIONIC__
-#warning "This code assumes that getpwuid is thread safe, only true with Bionic!"
-#endif
- pwd = getpwuid(appid);
- if (!pwd)
- goto err;
-
- username = pwd->pw_name;
-
- } else if (appid < AID_ISOLATED_START) {
- username = "_app";
- appid -= AID_APP;
- } else {
- username = "_isolated";
- appid -= AID_ISOLATED_START;
- }
-
- if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID)
- goto err;
-
- for (i = 0; i < nspec; i++) {
- cur = seapp_contexts[i];
-
- if (cur->isSystemServer != isSystemServer)
- continue;
-
- if (cur->isEphemeralAppSet && cur->isEphemeralApp != isEphemeralApp)
- continue;
-
- if (cur->isOwnerSet && cur->isOwner != isOwner)
- continue;
-
- if (cur->user.str) {
- if (cur->user.is_prefix) {
- if (strncasecmp(username, cur->user.str, cur->user.len-1))
- continue;
- } else {
- if (strcasecmp(username, cur->user.str))
- continue;
- }
- }
-
- if (cur->seinfo) {
- if (!seinfo || strcasecmp(seinfo, cur->seinfo))
- continue;
- }
-
- if (cur->name.str) {
- if(!pkgname)
- continue;
-
- if (cur->name.is_prefix) {
- if (strncasecmp(pkgname, cur->name.str, cur->name.len-1))
- continue;
- } else {
- if (strcasecmp(pkgname, cur->name.str))
- continue;
- }
- }
-
- if (cur->isPrivAppSet && cur->isPrivApp != isPrivApp)
- continue;
-
- if (cur->path.str) {
- if (!path)
- continue;
-
- if (cur->path.is_prefix) {
- if (strncmp(path, cur->path.str, cur->path.len-1))
- continue;
- } else {
- if (strcmp(path, cur->path.str))
- continue;
- }
- }
-
- if (kind == SEAPP_TYPE && !cur->type)
- continue;
- else if (kind == SEAPP_DOMAIN && !cur->domain)
- continue;
-
- if (kind == SEAPP_TYPE) {
- if (context_type_set(ctx, cur->type))
- goto oom;
- } else if (kind == SEAPP_DOMAIN) {
- if (context_type_set(ctx, cur->domain))
- goto oom;
- }
-
- if (cur->levelFrom != LEVELFROM_NONE) {
- char level[255];
- switch (cur->levelFrom) {
- case LEVELFROM_APP:
- snprintf(level, sizeof level, "s0:c%u,c%u",
- appid & 0xff,
- 256 + (appid>>8 & 0xff));
- break;
- case LEVELFROM_USER:
- snprintf(level, sizeof level, "s0:c%u,c%u",
- 512 + (userid & 0xff),
- 768 + (userid>>8 & 0xff));
- break;
- case LEVELFROM_ALL:
- snprintf(level, sizeof level, "s0:c%u,c%u,c%u,c%u",
- appid & 0xff,
- 256 + (appid>>8 & 0xff),
- 512 + (userid & 0xff),
- 768 + (userid>>8 & 0xff));
- break;
- default:
- goto err;
- }
- if (context_range_set(ctx, level))
- goto oom;
- } else if (cur->level) {
- if (context_range_set(ctx, cur->level))
- goto oom;
- }
-
- break;
- }
-
- if (kind == SEAPP_DOMAIN && i == nspec) {
- /*
- * No match.
- * Fail to prevent staying in the zygote's context.
- */
- selinux_log(SELINUX_ERROR,
- "%s: No match for app with uid %d, seinfo %s, name %s\n",
- __FUNCTION__, uid, seinfo, pkgname);
-
- if (security_getenforce() == 1)
- goto err;
- }
-
- return 0;
-err:
- return -1;
-oom:
- return -2;
-}
-
-int selinux_android_setfilecon(const char *pkgdir,
- const char *pkgname,
- const char *seinfo,
- uid_t uid)
-{
- char *orig_ctx_str = NULL;
- char *ctx_str = NULL;
- context_t ctx = NULL;
- int rc = -1;
-
- if (is_selinux_enabled() <= 0)
- return 0;
-
- rc = getfilecon(pkgdir, &ctx_str);
- if (rc < 0)
- goto err;
-
- ctx = context_new(ctx_str);
- orig_ctx_str = ctx_str;
- if (!ctx)
- goto oom;
-
- rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, NULL, ctx);
- if (rc == -1)
- goto err;
- else if (rc == -2)
- goto oom;
-
- ctx_str = context_str(ctx);
- if (!ctx_str)
- goto oom;
-
- rc = security_check_context(ctx_str);
- if (rc < 0)
- goto err;
-
- if (strcmp(ctx_str, orig_ctx_str)) {
- rc = setfilecon(pkgdir, ctx_str);
- if (rc < 0)
- goto err;
- }
-
- rc = 0;
-out:
- freecon(orig_ctx_str);
- context_free(ctx);
- return rc;
-err:
- selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n",
- __FUNCTION__, pkgdir, uid, strerror(errno));
- rc = -1;
- goto out;
-oom:
- selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
- rc = -1;
- goto out;
-}
-
-int selinux_android_setcon(const char *con)
-{
- int ret = setcon(con);
- if (ret)
- return ret;
- /*
- System properties must be reinitialized after setcon() otherwise the
- previous property files will be leaked since mmap()'ed regions are not
- closed as a result of setcon().
- */
- return __system_properties_init();
-}
-
-int selinux_android_setcontext(uid_t uid,
- bool isSystemServer,
- const char *seinfo,
- const char *pkgname)
-{
- char *orig_ctx_str = NULL, *ctx_str;
- context_t ctx = NULL;
- int rc = -1;
-
- if (is_selinux_enabled() <= 0)
- return 0;
-
- rc = getcon(&ctx_str);
- if (rc)
- goto err;
-
- ctx = context_new(ctx_str);
- orig_ctx_str = ctx_str;
- if (!ctx)
- goto oom;
-
- rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, NULL, ctx);
- if (rc == -1)
- goto err;
- else if (rc == -2)
- goto oom;
-
- ctx_str = context_str(ctx);
- if (!ctx_str)
- goto oom;
-
- rc = security_check_context(ctx_str);
- if (rc < 0)
- goto err;
-
- if (strcmp(ctx_str, orig_ctx_str)) {
- rc = selinux_android_setcon(ctx_str);
- if (rc < 0)
- goto err;
- }
-
- rc = 0;
-out:
- freecon(orig_ctx_str);
- context_free(ctx);
- avc_netlink_close();
- return rc;
-err:
- if (isSystemServer)
- selinux_log(SELINUX_ERROR,
- "%s: Error setting context for system server: %s\n",
- __FUNCTION__, strerror(errno));
- else
- selinux_log(SELINUX_ERROR,
- "%s: Error setting context for app with uid %d, seinfo %s: %s\n",
- __FUNCTION__, uid, seinfo, strerror(errno));
-
- rc = -1;
- goto out;
-oom:
- selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
- rc = -1;
- goto out;
-}
-
-static struct selabel_handle *fc_sehandle = NULL;
-#define FC_DIGEST_SIZE SHA_DIGEST_LENGTH
-static uint8_t fc_digest[FC_DIGEST_SIZE];
-
-static bool compute_file_contexts_hash(uint8_t c_digest[])
-{
- int fd;
- struct stat sb;
- void *map;
-
- fd = open(seopts.value, O_CLOEXEC | O_RDONLY | O_NOFOLLOW);
- if (fd < 0) {
- selinux_log(SELINUX_ERROR, "SELinux: Could not open %s: %s\n",
- seopts.value, strerror(errno));
- return false;
- }
- if (fstat(fd, &sb) < 0) {
- selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
- seopts.value, strerror(errno));
- close(fd);
- return false;
- }
- map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (map == MAP_FAILED) {
- selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
- seopts.value, strerror(errno));
- close(fd);
- return false;
- }
- SHA1(map, sb.st_size, c_digest);
- munmap(map, sb.st_size);
- close(fd);
-
- return true;
-}
-
-static void file_context_init(void)
-{
- if (!fc_sehandle)
- fc_sehandle = selinux_android_file_context_handle();
-}
-
-
-
-static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
-
-#define PKGTAB_SIZE 256
-static struct pkg_info *pkgTab[PKGTAB_SIZE];
-
-static unsigned int pkghash(const char *pkgname)
-{
- unsigned int h = 7;
- for (; *pkgname; pkgname++) {
- h = h * 31 + *pkgname;
- }
- return h & (PKGTAB_SIZE - 1);
-}
-
-static bool pkg_parse_callback(pkg_info *info, void *userdata) {
-
- (void) userdata;
-
- unsigned int hash = pkghash(info->name);
- if (pkgTab[hash])
- info->private_data = pkgTab[hash];
- pkgTab[hash] = info;
- return true;
-}
-
-static void package_info_init(void)
-{
-
- bool rc = packagelist_parse(pkg_parse_callback, NULL);
- if (!rc) {
- selinux_log(SELINUX_ERROR, "SELinux: Could NOT parse package list\n");
- return;
- }
-
-#if DEBUG
- {
- unsigned int hash, buckets, entries, chainlen, longestchain;
- struct pkg_info *info = NULL;
-
- buckets = entries = longestchain = 0;
- for (hash = 0; hash < PKGTAB_SIZE; hash++) {
- if (pkgTab[hash]) {
- buckets++;
- chainlen = 0;
- for (info = pkgTab[hash]; info; info = (pkg_info *)info->private_data) {
- chainlen++;
- selinux_log(SELINUX_INFO, "%s: name=%s uid=%u debuggable=%s dataDir=%s seinfo=%s\n",
- __FUNCTION__,
- info->name, info->uid, info->debuggable ? "true" : "false", info->data_dir, info->seinfo);
- }
- entries += chainlen;
- if (longestchain < chainlen)
- longestchain = chainlen;
- }
- }
- selinux_log(SELINUX_INFO, "SELinux: %d pkg entries and %d/%d buckets used, longest chain %d\n", entries, buckets, PKGTAB_SIZE, longestchain);
- }
-#endif
-
-}
-
-static pthread_once_t pkg_once = PTHREAD_ONCE_INIT;
-
-struct pkg_info *package_info_lookup(const char *name)
-{
- struct pkg_info *info;
- unsigned int hash;
-
- __selinux_once(pkg_once, package_info_init);
-
- hash = pkghash(name);
- for (info = pkgTab[hash]; info; info = (pkg_info *)info->private_data) {
- if (!strcmp(name, info->name))
- return info;
- }
- return NULL;
-}
-
-/* The path prefixes of package data directories. */
-#define DATA_DATA_PATH "/data/data"
-#define DATA_USER_PATH "/data/user"
-#define DATA_USER_DE_PATH "/data/user_de"
-#define EXPAND_USER_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?/user"
-#define EXPAND_USER_DE_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?/user_de"
-#define DATA_DATA_PREFIX DATA_DATA_PATH "/"
-#define DATA_USER_PREFIX DATA_USER_PATH "/"
-#define DATA_USER_DE_PREFIX DATA_USER_DE_PATH "/"
-
-static int pkgdir_selabel_lookup(const char *pathname,
- const char *seinfo,
- uid_t uid,
- char **secontextp)
-{
- char *pkgname = NULL, *end = NULL;
- struct pkg_info *info = NULL;
- char *secontext = *secontextp;
- context_t ctx = NULL;
- int rc = 0;
-
- /* Skip directory prefix before package name. */
- if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1)) {
- pathname += sizeof(DATA_DATA_PREFIX) - 1;
- } else if (!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) {
- pathname += sizeof(DATA_USER_PREFIX) - 1;
- while (isdigit(*pathname))
- pathname++;
- if (*pathname == '/')
- pathname++;
- else
- return 0;
- } else if (!strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1)) {
- pathname += sizeof(DATA_USER_DE_PREFIX) - 1;
- while (isdigit(*pathname))
- pathname++;
- if (*pathname == '/')
- pathname++;
- else
- return 0;
- } else if (!fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
- pathname += sizeof(EXPAND_USER_PATH);
- while (isdigit(*pathname))
- pathname++;
- if (*pathname == '/')
- pathname++;
- else
- return 0;
- } else if (!fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
- pathname += sizeof(EXPAND_USER_DE_PATH);
- while (isdigit(*pathname))
- pathname++;
- if (*pathname == '/')
- pathname++;
- else
- return 0;
- } else
- return 0;
-
- if (!(*pathname))
- return 0;
-
- pkgname = strdup(pathname);
- if (!pkgname)
- return -1;
-
- for (end = pkgname; *end && *end != '/'; end++)
- ;
- pathname = end;
- if (*end)
- pathname++;
- *end = '\0';
-
- if (!seinfo) {
- info = package_info_lookup(pkgname);
- if (!info) {
- selinux_log(SELINUX_WARNING, "SELinux: Could not look up information for package %s, cannot restorecon %s.\n",
- pkgname, pathname);
- free(pkgname);
- return -1;
- }
- }
-
- ctx = context_new(secontext);
- if (!ctx)
- goto err;
-
- rc = seapp_context_lookup(SEAPP_TYPE, info ? info->uid : uid, 0,
- info ? info->seinfo : seinfo, info ? info->name : pkgname, pathname, ctx);
- if (rc < 0)
- goto err;
-
- secontext = context_str(ctx);
- if (!secontext)
- goto err;
-
- if (!strcmp(secontext, *secontextp))
- goto out;
-
- rc = security_check_context(secontext);
- if (rc < 0)
- goto err;
-
- freecon(*secontextp);
- *secontextp = strdup(secontext);
- if (!(*secontextp))
- goto err;
-
- rc = 0;
-
-out:
- free(pkgname);
- context_free(ctx);
- return rc;
-err:
- selinux_log(SELINUX_ERROR, "%s: Error looking up context for path %s, pkgname %s, seinfo %s, uid %u: %s\n",
- __FUNCTION__, pathname, pkgname, info->seinfo, info->uid, strerror(errno));
- rc = -1;
- goto out;
-}
-
-#define RESTORECON_LAST "security.restorecon_last"
-
-static int restorecon_sb(const char *pathname, const struct stat *sb,
- bool nochange, bool verbose,
- const char *seinfo, uid_t uid)
-{
- char *secontext = NULL;
- char *oldsecontext = NULL;
- int rc = 0;
-
- if (selabel_lookup(fc_sehandle, &secontext, pathname, sb->st_mode) < 0)
- return 0; /* no match, but not an error */
-
- if (lgetfilecon(pathname, &oldsecontext) < 0)
- goto err;
-
- /*
- * For subdirectories of /data/data or /data/user, we ignore selabel_lookup()
- * and use pkgdir_selabel_lookup() instead. Files within those directories
- * have different labeling rules, based off of /seapp_contexts, and
- * installd is responsible for managing these labels instead of init.
- */
- if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
- !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
- !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
- !fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME) ||
- !fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
- if (pkgdir_selabel_lookup(pathname, seinfo, uid, &secontext) < 0)
- goto err;
- }
-
- if (strcmp(oldsecontext, secontext) != 0) {
- if (verbose)
- selinux_log(SELINUX_INFO,
- "SELinux: Relabeling %s from %s to %s.\n", pathname, oldsecontext, secontext);
- if (!nochange) {
- if (lsetfilecon(pathname, secontext) < 0)
- goto err;
- }
- }
-
- rc = 0;
-
-out:
- freecon(oldsecontext);
- freecon(secontext);
- return rc;
-
-err:
- selinux_log(SELINUX_ERROR,
- "SELinux: Could not set context for %s: %s\n",
- pathname, strerror(errno));
- rc = -1;
- goto out;
-}
-
-#define SYS_PATH "/sys"
-#define SYS_PREFIX SYS_PATH "/"
-
-static int selinux_android_restorecon_common(const char* pathname_orig,
- const char *seinfo,
- uid_t uid,
- unsigned int flags)
-{
- bool nochange = (flags & SELINUX_ANDROID_RESTORECON_NOCHANGE) ? true : false;
- bool verbose = (flags & SELINUX_ANDROID_RESTORECON_VERBOSE) ? true : false;
- bool recurse = (flags & SELINUX_ANDROID_RESTORECON_RECURSE) ? true : false;
- bool force = (flags & SELINUX_ANDROID_RESTORECON_FORCE) ? true : false;
- bool datadata = (flags & SELINUX_ANDROID_RESTORECON_DATADATA) ? true : false;
- bool issys;
- bool setrestoreconlast = true;
- struct stat sb;
- struct statfs sfsb;
- FTS *fts;
- FTSENT *ftsent;
- char *pathname = NULL, *pathdnamer = NULL, *pathdname, *pathbname;
- char * paths[2] = { NULL , NULL };
- int ftsflags = FTS_NOCHDIR | FTS_XDEV | FTS_PHYSICAL;
- int error, sverrno;
- char xattr_value[FC_DIGEST_SIZE];
- ssize_t size;
-
- if (is_selinux_enabled() <= 0)
- return 0;
-
- __selinux_once(fc_once, file_context_init);
-
- if (!fc_sehandle)
- return 0;
-
- /*
- * Convert passed-in pathname to canonical pathname by resolving realpath of
- * containing dir, then appending last component name.
- */
- pathbname = basename(pathname_orig);
- if (!strcmp(pathbname, "/") || !strcmp(pathbname, ".") || !strcmp(pathbname, "..")) {
- pathname = realpath(pathname_orig, NULL);
- if (!pathname)
- goto realpatherr;
- } else {
- pathdname = dirname(pathname_orig);
- pathdnamer = realpath(pathdname, NULL);
- if (!pathdnamer)
- goto realpatherr;
- if (!strcmp(pathdnamer, "/"))
- error = asprintf(&pathname, "/%s", pathbname);
- else
- error = asprintf(&pathname, "%s/%s", pathdnamer, pathbname);
- if (error < 0)
- goto oom;
- }
-
- paths[0] = pathname;
- issys = (!strcmp(pathname, SYS_PATH)
- || !strncmp(pathname, SYS_PREFIX, sizeof(SYS_PREFIX)-1)) ? true : false;
-
- if (!recurse) {
- if (lstat(pathname, &sb) < 0) {
- error = -1;
- goto cleanup;
- }
-
- error = restorecon_sb(pathname, &sb, nochange, verbose, seinfo, uid);
- goto cleanup;
- }
-
- /*
- * Ignore restorecon_last on /data/data or /data/user
- * since their labeling is based on seapp_contexts and seinfo
- * assignments rather than file_contexts and is managed by
- * installd rather than init.
- */
- if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
- !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
- !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
- !fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME) ||
- !fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME))
- setrestoreconlast = false;
-
- /* Also ignore on /sys since it is regenerated on each boot regardless. */
- if (issys)
- setrestoreconlast = false;
-
- /* Ignore files on in-memory filesystems */
- if (statfs(pathname, &sfsb) == 0) {
- if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC)
- setrestoreconlast = false;
- }
-
- if (setrestoreconlast) {
- size = getxattr(pathname, RESTORECON_LAST, xattr_value, sizeof fc_digest);
- if (!force && size == sizeof fc_digest && memcmp(fc_digest, xattr_value, sizeof fc_digest) == 0) {
- selinux_log(SELINUX_INFO,
- "SELinux: Skipping restorecon_recursive(%s)\n",
- pathname);
- error = 0;
- goto cleanup;
- }
- }
-
- fts = fts_open(paths, ftsflags, NULL);
- if (!fts) {
- error = -1;
- goto cleanup;
- }
-
- error = 0;
- while ((ftsent = fts_read(fts)) != NULL) {
- switch (ftsent->fts_info) {
- case FTS_DC:
- selinux_log(SELINUX_ERROR,
- "SELinux: Directory cycle on %s.\n", ftsent->fts_path);
- errno = ELOOP;
- error = -1;
- goto out;
- case FTS_DP:
- continue;
- case FTS_DNR:
- selinux_log(SELINUX_ERROR,
- "SELinux: Could not read %s: %s.\n", ftsent->fts_path, strerror(errno));
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- case FTS_NS:
- selinux_log(SELINUX_ERROR,
- "SELinux: Could not stat %s: %s.\n", ftsent->fts_path, strerror(errno));
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- case FTS_ERR:
- selinux_log(SELINUX_ERROR,
- "SELinux: Error on %s: %s.\n", ftsent->fts_path, strerror(errno));
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- case FTS_D:
- if (issys && !selabel_partial_match(fc_sehandle, ftsent->fts_path)) {
- fts_set(fts, ftsent, FTS_SKIP);
- continue;
- }
-
- if (!datadata &&
- (!strcmp(ftsent->fts_path, DATA_DATA_PATH) ||
- !strncmp(ftsent->fts_path, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
- !strncmp(ftsent->fts_path, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
- !fnmatch(EXPAND_USER_PATH, ftsent->fts_path, FNM_LEADING_DIR|FNM_PATHNAME) ||
- !fnmatch(EXPAND_USER_DE_PATH, ftsent->fts_path, FNM_LEADING_DIR|FNM_PATHNAME))) {
- // Don't label anything below this directory.
- fts_set(fts, ftsent, FTS_SKIP);
- // but fall through and make sure we label the directory itself
- }
- /* fall through */
- default:
- error |= restorecon_sb(ftsent->fts_path, ftsent->fts_statp, nochange, verbose, seinfo, uid);
- break;
- }
- }
-
- // Labeling successful. Mark the top level directory as completed.
- if (setrestoreconlast && !nochange && !error)
- setxattr(pathname, RESTORECON_LAST, fc_digest, sizeof fc_digest, 0);
-
-out:
- sverrno = errno;
- (void) fts_close(fts);
- errno = sverrno;
-cleanup:
- free(pathdnamer);
- free(pathname);
- return error;
-oom:
- sverrno = errno;
- selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__);
- errno = sverrno;
- error = -1;
- goto cleanup;
-realpatherr:
- sverrno = errno;
- selinux_log(SELINUX_ERROR, "SELinux: Could not get canonical path for %s restorecon: %s.\n",
- pathname_orig, strerror(errno));
- errno = sverrno;
- error = -1;
- goto cleanup;
-}
-
-int selinux_android_restorecon(const char *file, unsigned int flags)
-{
- return selinux_android_restorecon_common(file, NULL, -1, flags);
-}
-
-int selinux_android_restorecon_pkgdir(const char *pkgdir,
- const char *seinfo,
- uid_t uid,
- unsigned int flags)
-{
- return selinux_android_restorecon_common(pkgdir, seinfo, uid, flags | SELINUX_ANDROID_RESTORECON_DATADATA);
-}
-
-struct selabel_handle* selinux_android_file_context_handle(void)
-{
- char *path = NULL;
- struct selabel_handle *sehandle;
- struct selinux_opt fc_opts[] = {
- { SELABEL_OPT_PATH, path },
- { SELABEL_OPT_BASEONLY, (char *)1 }
- };
-
- fc_opts[0].value = seopts.value;
-
- sehandle = selabel_open(SELABEL_CTX_FILE, fc_opts, 2);
-
- if (!sehandle) {
- selinux_log(SELINUX_ERROR, "%s: Error getting file context handle (%s)\n",
- __FUNCTION__, strerror(errno));
- return NULL;
- }
- if (!compute_file_contexts_hash(fc_digest)) {
- selabel_close(sehandle);
- return NULL;
- }
- selinux_log(SELINUX_INFO, "SELinux: Loaded file_contexts contexts from %s.\n",
- fc_opts[0].value);
-
- return sehandle;
-}
-
-struct selabel_handle* selinux_android_prop_context_handle(void)
-{
- struct selabel_handle* sehandle;
-
- sehandle = selabel_open(SELABEL_CTX_ANDROID_PROP,
- &seopts_prop, 1);
- if (!sehandle) {
- selinux_log(SELINUX_ERROR, "%s: Error getting property context handle (%s)\n",
- __FUNCTION__, strerror(errno));
- return NULL;
- }
- selinux_log(SELINUX_INFO, "SELinux: Loaded property_contexts from %s.\n",
- seopts_prop.value);
-
- return sehandle;
-}
-
-struct selabel_handle* selinux_android_service_context_handle(void)
-{
- struct selabel_handle* sehandle;
-
- sehandle = selabel_open(SELABEL_CTX_ANDROID_SERVICE,
- &seopts_service, 1);
-
- if (!sehandle) {
- selinux_log(SELINUX_ERROR, "%s: Error getting service context handle (%s)\n",
- __FUNCTION__, strerror(errno));
- return NULL;
- }
- selinux_log(SELINUX_INFO, "SELinux: Loaded service_contexts from %s.\n",
- seopts_service.value);
-
- return sehandle;
-}
-
-void selinux_android_set_sehandle(const struct selabel_handle *hndl)
-{
- fc_sehandle = (struct selabel_handle *) hndl;
-}
-
-int selinux_android_load_policy(void)
-{
- int fd = -1, rc;
- struct stat sb;
- void *map = NULL;
- static int load_successful = 0;
-
- /*
- * Since updating policy at runtime has been abolished
- * we just check whether a policy has been loaded before
- * and return if this is the case.
- * There is no point in reloading policy.
- */
- if (load_successful){
- selinux_log(SELINUX_WARNING, "SELinux: Attempted reload of SELinux policy!/n");
- return 0;
- }
-
- set_selinuxmnt(SELINUXMNT);
- fd = open(sepolicy_file, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
- if (fd < 0) {
- selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n",
- strerror(errno));
- return -1;
- }
- if (fstat(fd, &sb) < 0) {
- selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
- sepolicy_file, strerror(errno));
- close(fd);
- return -1;
- }
- map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (map == MAP_FAILED) {
- selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
- sepolicy_file, strerror(errno));
- close(fd);
- return -1;
- }
-
- rc = security_load_policy(map, sb.st_size);
- if (rc < 0) {
- selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n",
- strerror(errno));
- munmap(map, sb.st_size);
- close(fd);
- return -1;
- }
-
- munmap(map, sb.st_size);
- close(fd);
- selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", sepolicy_file);
- load_successful = 1;
- return 0;
-}
-
-int selinux_log_callback(int type, const char *fmt, ...)
-{
- va_list ap;
- int priority;
- char *strp;
-
- switch(type) {
- case SELINUX_WARNING:
- priority = ANDROID_LOG_WARN;
- break;
- case SELINUX_INFO:
- priority = ANDROID_LOG_INFO;
- break;
- default:
- priority = ANDROID_LOG_ERROR;
- break;
- }
-
- va_start(ap, fmt);
- if (vasprintf(&strp, fmt, ap) != -1) {
- LOG_PRI(priority, "SELinux", "%s", strp);
- LOG_EVENT_STRING(AUDITD_LOG_TAG, strp);
- free(strp);
- }
- va_end(ap);
- return 0;
-}
diff --git a/src/avc.c b/src/avc.c
deleted file mode 100644
index 528d897..0000000
--- a/src/avc.c
+++ /dev/null
@@ -1,1121 +0,0 @@
-/*
- * Implementation of the userspace access vector cache (AVC).
- *
- * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
- *
- * Derived from the kernel AVC implementation by
- * Stephen Smalley <sds@epoch.ncsc.mil> and
- * James Morris <jmorris@redhat.com>.
- */
-#include <selinux/avc.h>
-#include "selinux_internal.h"
-#include <assert.h>
-#include "avc_sidtab.h"
-#include "avc_internal.h"
-
-#define AVC_CACHE_SLOTS 512
-#define AVC_CACHE_MAXNODES 410
-
-struct avc_entry {
- security_id_t ssid;
- security_id_t tsid;
- security_class_t tclass;
- struct av_decision avd;
- security_id_t create_sid;
- int used; /* used recently */
-};
-
-struct avc_node {
- struct avc_entry ae;
- struct avc_node *next;
-};
-
-struct avc_cache {
- struct avc_node *slots[AVC_CACHE_SLOTS];
- uint32_t lru_hint; /* LRU hint for reclaim scan */
- uint32_t active_nodes;
- uint32_t latest_notif; /* latest revocation notification */
-};
-
-struct avc_callback_node {
- int (*callback) (uint32_t event, security_id_t ssid,
- security_id_t tsid,
- security_class_t tclass, access_vector_t perms,
- access_vector_t * out_retained);
- uint32_t events;
- security_id_t ssid;
- security_id_t tsid;
- security_class_t tclass;
- access_vector_t perms;
- struct avc_callback_node *next;
-};
-
-static void *avc_netlink_thread = NULL;
-static void *avc_lock = NULL;
-static void *avc_log_lock = NULL;
-static struct avc_node *avc_node_freelist = NULL;
-static struct avc_cache avc_cache;
-static char *avc_audit_buf = NULL;
-static struct avc_cache_stats cache_stats;
-static struct avc_callback_node *avc_callbacks = NULL;
-static struct sidtab avc_sidtab;
-
-static inline int avc_hash(security_id_t ssid,
- security_id_t tsid, security_class_t tclass)
-{
- return ((uintptr_t) ssid ^ ((uintptr_t) tsid << 2) ^ tclass)
- & (AVC_CACHE_SLOTS - 1);
-}
-
-int avc_context_to_sid(const char * ctx, security_id_t * sid)
-{
- int rc;
- /* avc_init needs to be called before this function */
- assert(avc_running);
-
- avc_get_lock(avc_lock);
- rc = sidtab_context_to_sid(&avc_sidtab, ctx, sid);
- avc_release_lock(avc_lock);
- return rc;
-}
-
-int avc_sid_to_context(security_id_t sid, char ** ctx)
-{
- int rc;
- *ctx = NULL;
- avc_get_lock(avc_lock);
- *ctx = strdup(sid->ctx); /* caller must free via freecon */
- rc = *ctx ? 0 : -1;
- avc_release_lock(avc_lock);
- return rc;
-}
-
-int avc_get_initial_sid(const char * name, security_id_t * sid)
-{
- int rc;
- char * con;
-
- rc = security_get_initial_context(name, &con);
- if (rc < 0)
- return rc;
- rc = avc_context_to_sid(con, sid);
-
- freecon(con);
-
- return rc;
-}
-
-int avc_open(struct selinux_opt *opts, unsigned nopts)
-{
- avc_setenforce = 0;
-
- while (nopts--)
- switch(opts[nopts].type) {
- case AVC_OPT_SETENFORCE:
- avc_setenforce = 1;
- avc_enforcing = !!opts[nopts].value;
- break;
- }
-
- return avc_init("avc", NULL, NULL, NULL, NULL);
-}
-
-int avc_init(const char *prefix,
- const struct avc_memory_callback *mem_cb,
- const struct avc_log_callback *log_cb,
- const struct avc_thread_callback *thread_cb,
- const struct avc_lock_callback *lock_cb)
-{
- struct avc_node *new;
- int i, rc = 0;
-
- if (avc_running)
- return 0;
-
- if (prefix)
- strncpy(avc_prefix, prefix, AVC_PREFIX_SIZE - 1);
-
- set_callbacks(mem_cb, log_cb, thread_cb, lock_cb);
-
- avc_lock = avc_alloc_lock();
- avc_log_lock = avc_alloc_lock();
-
- memset(&cache_stats, 0, sizeof(cache_stats));
-
- for (i = 0; i < AVC_CACHE_SLOTS; i++)
- avc_cache.slots[i] = 0;
- avc_cache.lru_hint = 0;
- avc_cache.active_nodes = 0;
- avc_cache.latest_notif = 0;
-
- rc = sidtab_init(&avc_sidtab);
- if (rc) {
- avc_log(SELINUX_ERROR,
- "%s: unable to initialize SID table\n",
- avc_prefix);
- goto out;
- }
-
- avc_audit_buf = (char *)avc_malloc(AVC_AUDIT_BUFSIZE);
- if (!avc_audit_buf) {
- avc_log(SELINUX_ERROR,
- "%s: unable to allocate audit buffer\n",
- avc_prefix);
- rc = -1;
- goto out;
- }
-
- for (i = 0; i < AVC_CACHE_MAXNODES; i++) {
- new = avc_malloc(sizeof(*new));
- if (!new) {
- avc_log(SELINUX_WARNING,
- "%s: warning: only got %d av entries\n",
- avc_prefix, i);
- break;
- }
- memset(new, 0, sizeof(*new));
- new->next = avc_node_freelist;
- avc_node_freelist = new;
- }
-
- if (!avc_setenforce) {
- rc = security_getenforce();
- if (rc < 0) {
- avc_log(SELINUX_ERROR,
- "%s: could not determine enforcing mode: %s\n",
- avc_prefix,
- strerror(errno));
- goto out;
- }
- avc_enforcing = rc;
- }
-
- rc = avc_netlink_open(0);
- if (rc < 0) {
- avc_log(SELINUX_ERROR,
- "%s: can't open netlink socket: %d (%s)\n",
- avc_prefix, errno, strerror(errno));
- goto out;
- }
- if (avc_using_threads) {
- avc_netlink_thread = avc_create_thread(&avc_netlink_loop);
- avc_netlink_trouble = 0;
- }
- avc_running = 1;
- out:
- return rc;
-}
-
-void avc_cache_stats(struct avc_cache_stats *p)
-{
- memcpy(p, &cache_stats, sizeof(cache_stats));
-}
-
-void avc_sid_stats(void)
-{
- /* avc_init needs to be called before this function */
- assert(avc_running);
- avc_get_lock(avc_log_lock);
- avc_get_lock(avc_lock);
- sidtab_sid_stats(&avc_sidtab, avc_audit_buf, AVC_AUDIT_BUFSIZE);
- avc_release_lock(avc_lock);
- avc_log(SELINUX_INFO, "%s", avc_audit_buf);
- avc_release_lock(avc_log_lock);
-}
-
-void avc_av_stats(void)
-{
- int i, chain_len, max_chain_len, slots_used;
- struct avc_node *node;
-
- avc_get_lock(avc_lock);
-
- slots_used = 0;
- max_chain_len = 0;
- for (i = 0; i < AVC_CACHE_SLOTS; i++) {
- node = avc_cache.slots[i];
- if (node) {
- slots_used++;
- chain_len = 0;
- while (node) {
- chain_len++;
- node = node->next;
- }
- if (chain_len > max_chain_len)
- max_chain_len = chain_len;
- }
- }
-
- avc_release_lock(avc_lock);
-
- avc_log(SELINUX_INFO, "%s: %d AV entries and %d/%d buckets used, "
- "longest chain length %d\n", avc_prefix,
- avc_cache.active_nodes,
- slots_used, AVC_CACHE_SLOTS, max_chain_len);
-}
-
-hidden_def(avc_av_stats)
-
-static inline struct avc_node *avc_reclaim_node(void)
-{
- struct avc_node *prev, *cur;
- int try;
- uint32_t hvalue;
-
- hvalue = avc_cache.lru_hint;
- for (try = 0; try < 2; try++) {
- do {
- prev = NULL;
- cur = avc_cache.slots[hvalue];
- while (cur) {
- if (!cur->ae.used)
- goto found;
-
- cur->ae.used = 0;
-
- prev = cur;
- cur = cur->next;
- }
- hvalue = (hvalue + 1) & (AVC_CACHE_SLOTS - 1);
- } while (hvalue != avc_cache.lru_hint);
- }
-
- errno = ENOMEM; /* this was a panic in the kernel... */
- return NULL;
-
- found:
- avc_cache.lru_hint = hvalue;
-
- if (prev == NULL)
- avc_cache.slots[hvalue] = cur->next;
- else
- prev->next = cur->next;
-
- return cur;
-}
-
-static inline void avc_clear_avc_entry(struct avc_entry *ae)
-{
- memset(ae, 0, sizeof(*ae));
-}
-
-static inline struct avc_node *avc_claim_node(security_id_t ssid,
- security_id_t tsid,
- security_class_t tclass)
-{
- struct avc_node *new;
- int hvalue;
-
- if (!avc_node_freelist)
- avc_cleanup();
-
- if (avc_node_freelist) {
- new = avc_node_freelist;
- avc_node_freelist = avc_node_freelist->next;
- avc_cache.active_nodes++;
- } else {
- new = avc_reclaim_node();
- if (!new)
- goto out;
- }
-
- hvalue = avc_hash(ssid, tsid, tclass);
- avc_clear_avc_entry(&new->ae);
- new->ae.used = 1;
- new->ae.ssid = ssid;
- new->ae.tsid = tsid;
- new->ae.tclass = tclass;
- new->next = avc_cache.slots[hvalue];
- avc_cache.slots[hvalue] = new;
-
- out:
- return new;
-}
-
-static inline struct avc_node *avc_search_node(security_id_t ssid,
- security_id_t tsid,
- security_class_t tclass,
- int *probes)
-{
- struct avc_node *cur;
- int hvalue;
- int tprobes = 1;
-
- hvalue = avc_hash(ssid, tsid, tclass);
- cur = avc_cache.slots[hvalue];
- while (cur != NULL &&
- (ssid != cur->ae.ssid ||
- tclass != cur->ae.tclass || tsid != cur->ae.tsid)) {
- tprobes++;
- cur = cur->next;
- }
-
- if (cur == NULL) {
- /* cache miss */
- goto out;
- }
-
- /* cache hit */
- if (probes)
- *probes = tprobes;
-
- cur->ae.used = 1;
-
- out:
- return cur;
-}
-
-/**
- * avc_lookup - Look up an AVC entry.
- * @ssid: source security identifier
- * @tsid: target security identifier
- * @tclass: target security class
- * @requested: requested permissions, interpreted based on @tclass
- * @aeref: AVC entry reference
- *
- * Look up an AVC entry that is valid for the
- * @requested permissions between the SID pair
- * (@ssid, @tsid), interpreting the permissions
- * based on @tclass. If a valid AVC entry exists,
- * then this function updates @aeref to refer to the
- * entry and returns %0. Otherwise, -1 is returned.
- */
-static int avc_lookup(security_id_t ssid, security_id_t tsid,
- security_class_t tclass,
- access_vector_t requested, struct avc_entry_ref *aeref)
-{
- struct avc_node *node;
- int probes, rc = 0;
-
- avc_cache_stats_incr(cav_lookups);
- node = avc_search_node(ssid, tsid, tclass, &probes);
-
- if (node && ((node->ae.avd.decided & requested) == requested)) {
- avc_cache_stats_incr(cav_hits);
- avc_cache_stats_add(cav_probes, probes);
- aeref->ae = &node->ae;
- goto out;
- }
-
- avc_cache_stats_incr(cav_misses);
- rc = -1;
- out:
- return rc;
-}
-
-/**
- * avc_insert - Insert an AVC entry.
- * @ssid: source security identifier
- * @tsid: target security identifier
- * @tclass: target security class
- * @ae: AVC entry
- * @aeref: AVC entry reference
- *
- * Insert an AVC entry for the SID pair
- * (@ssid, @tsid) and class @tclass.
- * The access vectors and the sequence number are
- * normally provided by the security server in
- * response to a security_compute_av() call. If the
- * sequence number @ae->avd.seqno is not less than the latest
- * revocation notification, then the function copies
- * the access vectors into a cache entry, updates
- * @aeref to refer to the entry, and returns %0.
- * Otherwise, this function returns -%1 with @errno set to %EAGAIN.
- */
-static int avc_insert(security_id_t ssid, security_id_t tsid,
- security_class_t tclass,
- struct avc_entry *ae, struct avc_entry_ref *aeref)
-{
- struct avc_node *node;
- int rc = 0;
-
- if (ae->avd.seqno < avc_cache.latest_notif) {
- avc_log(SELINUX_WARNING,
- "%s: seqno %d < latest_notif %d\n", avc_prefix,
- ae->avd.seqno, avc_cache.latest_notif);
- errno = EAGAIN;
- rc = -1;
- goto out;
- }
-
- node = avc_claim_node(ssid, tsid, tclass);
- if (!node) {
- rc = -1;
- goto out;
- }
-
- memcpy(&node->ae.avd, &ae->avd, sizeof(ae->avd));
- aeref->ae = &node->ae;
- out:
- return rc;
-}
-
-void avc_cleanup(void)
-{
-}
-
-hidden_def(avc_cleanup)
-
-int avc_reset(void)
-{
- struct avc_callback_node *c;
- int i, ret, rc = 0, errsave = 0;
- struct avc_node *node, *tmp;
- errno = 0;
-
- if (!avc_running)
- return 0;
-
- avc_get_lock(avc_lock);
-
- for (i = 0; i < AVC_CACHE_SLOTS; i++) {
- node = avc_cache.slots[i];
- while (node) {
- tmp = node;
- node = node->next;
- avc_clear_avc_entry(&tmp->ae);
- tmp->next = avc_node_freelist;
- avc_node_freelist = tmp;
- avc_cache.active_nodes--;
- }
- avc_cache.slots[i] = 0;
- }
- avc_cache.lru_hint = 0;
-
- avc_release_lock(avc_lock);
-
- memset(&cache_stats, 0, sizeof(cache_stats));
-
- for (c = avc_callbacks; c; c = c->next) {
- if (c->events & AVC_CALLBACK_RESET) {
- ret = c->callback(AVC_CALLBACK_RESET, 0, 0, 0, 0, 0);
- if (ret && !rc) {
- rc = ret;
- errsave = errno;
- }
- }
- }
- errno = errsave;
- return rc;
-}
-
-hidden_def(avc_reset)
-
-void avc_destroy(void)
-{
- struct avc_callback_node *c;
- struct avc_node *node, *tmp;
- int i;
- /* avc_init needs to be called before this function */
- assert(avc_running);
-
- avc_get_lock(avc_lock);
-
- if (avc_using_threads)
- avc_stop_thread(avc_netlink_thread);
- avc_netlink_close();
-
- for (i = 0; i < AVC_CACHE_SLOTS; i++) {
- node = avc_cache.slots[i];
- while (node) {
- tmp = node;
- node = node->next;
- avc_free(tmp);
- }
- }
- while (avc_node_freelist) {
- tmp = avc_node_freelist;
- avc_node_freelist = tmp->next;
- avc_free(tmp);
- }
- avc_release_lock(avc_lock);
-
- while (avc_callbacks) {
- c = avc_callbacks;
- avc_callbacks = c->next;
- avc_free(c);
- }
- sidtab_destroy(&avc_sidtab);
- avc_free_lock(avc_lock);
- avc_free_lock(avc_log_lock);
- avc_free(avc_audit_buf);
- avc_running = 0;
-}
-
-/* ratelimit stuff put aside for now --EFW */
-#if 0
-/*
- * Copied from net/core/utils.c:net_ratelimit and modified for
- * use by the AVC audit facility.
- */
-#define AVC_MSG_COST 5*HZ
-#define AVC_MSG_BURST 10*5*HZ
-
-/*
- * This enforces a rate limit: not more than one kernel message
- * every 5secs to make a denial-of-service attack impossible.
- */
-static int avc_ratelimit(void)
-{
- static unsigned long toks = 10 * 5 * HZ;
- static unsigned long last_msg;
- static int missed, rc = 0;
- unsigned long now = jiffies;
- void *ratelimit_lock = avc_alloc_lock();
-
- avc_get_lock(ratelimit_lock);
- toks += now - last_msg;
- last_msg = now;
- if (toks > AVC_MSG_BURST)
- toks = AVC_MSG_BURST;
- if (toks >= AVC_MSG_COST) {
- int lost = missed;
- missed = 0;
- toks -= AVC_MSG_COST;
- avc_release_lock(ratelimit_lock);
- if (lost) {
- avc_log(SELINUX_WARNING,
- "%s: %d messages suppressed.\n", avc_prefix,
- lost);
- }
- rc = 1;
- goto out;
- }
- missed++;
- avc_release_lock(ratelimit_lock);
- out:
- avc_free_lock(ratelimit_lock);
- return rc;
-}
-
-static inline int check_avc_ratelimit(void)
-{
- if (avc_enforcing)
- return avc_ratelimit();
- else {
- /* If permissive, then never suppress messages. */
- return 1;
- }
-}
-#endif /* ratelimit stuff */
-
-/**
- * avc_dump_av - Display an access vector in human-readable form.
- * @tclass: target security class
- * @av: access vector
- */
-static void avc_dump_av(security_class_t tclass, access_vector_t av)
-{
- const char *permstr;
- access_vector_t bit = 1;
-
- if (av == 0) {
- log_append(avc_audit_buf, " null");
- return;
- }
-
- log_append(avc_audit_buf, " {");
-
- while (av) {
- if (av & bit) {
- permstr = security_av_perm_to_string(tclass, bit);
- if (!permstr)
- break;
- log_append(avc_audit_buf, " %s", permstr);
- av &= ~bit;
- }
- bit <<= 1;
- }
-
- if (av)
- log_append(avc_audit_buf, " 0x%x", av);
- log_append(avc_audit_buf, " }");
-}
-
-/**
- * avc_dump_query - Display a SID pair and a class in human-readable form.
- * @ssid: source security identifier
- * @tsid: target security identifier
- * @tclass: target security class
- */
-static void avc_dump_query(security_id_t ssid, security_id_t tsid,
- security_class_t tclass)
-{
- avc_get_lock(avc_lock);
-
- log_append(avc_audit_buf, "scontext=%s tcontext=%s",
- ssid->ctx, tsid->ctx);
-
- avc_release_lock(avc_lock);
- log_append(avc_audit_buf, " tclass=%s",
- security_class_to_string(tclass));
-}
-
-void avc_audit(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t requested,
- struct av_decision *avd, int result, void *a)
-{
- access_vector_t denied, audited;
-
- denied = requested & ~avd->allowed;
- if (denied)
- audited = denied & avd->auditdeny;
- else if (!requested || result)
- audited = denied = requested;
- else
- audited = requested & avd->auditallow;
- if (!audited)
- return;
-#if 0
- if (!check_avc_ratelimit())
- return;
-#endif
- /* prevent overlapping buffer writes */
- avc_get_lock(avc_log_lock);
- snprintf(avc_audit_buf, AVC_AUDIT_BUFSIZE,
- "%s: %s ", avc_prefix, (denied || !requested) ? "denied" : "granted");
- avc_dump_av(tclass, audited);
- log_append(avc_audit_buf, " for ");
-
- /* get any extra information printed by the callback */
- avc_suppl_audit(a, tclass, avc_audit_buf + strlen(avc_audit_buf),
- AVC_AUDIT_BUFSIZE - strlen(avc_audit_buf));
-
- log_append(avc_audit_buf, " ");
- avc_dump_query(ssid, tsid, tclass);
-
- /* append permissive=0|1 like the kernel at the end */
- if (denied || !requested)
- log_append(avc_audit_buf, " permissive=%d", !result);
-
- log_append(avc_audit_buf, "\n");
- avc_log(SELINUX_AVC, "%s", avc_audit_buf);
-
- avc_release_lock(avc_log_lock);
-}
-
-hidden_def(avc_audit)
-
-
-static void avd_init(struct av_decision *avd)
-{
- avd->allowed = 0;
- avd->auditallow = 0;
- avd->auditdeny = 0xffffffff;
- avd->seqno = avc_cache.latest_notif;
- avd->flags = 0;
-}
-
-int avc_has_perm_noaudit(security_id_t ssid,
- security_id_t tsid,
- security_class_t tclass,
- access_vector_t requested,
- struct avc_entry_ref *aeref, struct av_decision *avd)
-{
- struct avc_entry *ae;
- int rc = 0;
- struct avc_entry entry;
- access_vector_t denied;
- struct avc_entry_ref ref;
-
- if (avd)
- avd_init(avd);
-
- if (!avc_using_threads && !avc_app_main_loop) {
- (void)avc_netlink_check_nb();
- }
-
- if (!aeref) {
- avc_entry_ref_init(&ref);
- aeref = &ref;
- }
-
- avc_get_lock(avc_lock);
- avc_cache_stats_incr(entry_lookups);
- ae = aeref->ae;
- if (ae) {
- if (ae->ssid == ssid &&
- ae->tsid == tsid &&
- ae->tclass == tclass &&
- ((ae->avd.decided & requested) == requested)) {
- avc_cache_stats_incr(entry_hits);
- ae->used = 1;
- } else {
- avc_cache_stats_incr(entry_discards);
- ae = 0;
- }
- }
-
- if (!ae) {
- avc_cache_stats_incr(entry_misses);
- rc = avc_lookup(ssid, tsid, tclass, requested, aeref);
- if (rc) {
- rc = security_compute_av(ssid->ctx, tsid->ctx,
- tclass, requested,
- &entry.avd);
- if (rc && errno == EINVAL && !avc_enforcing) {
- rc = errno = 0;
- goto out;
- }
- if (rc)
- goto out;
- rc = avc_insert(ssid, tsid, tclass, &entry, aeref);
- if (rc)
- goto out;
- }
- ae = aeref->ae;
- }
-
- if (avd)
- memcpy(avd, &ae->avd, sizeof(*avd));
-
- denied = requested & ~(ae->avd.allowed);
-
- if (!requested || denied) {
- if (!avc_enforcing ||
- (ae->avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE))
- ae->avd.allowed |= requested;
- else {
- errno = EACCES;
- rc = -1;
- }
- }
-
- out:
- avc_release_lock(avc_lock);
- return rc;
-}
-
-hidden_def(avc_has_perm_noaudit)
-
-int avc_has_perm(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t requested,
- struct avc_entry_ref *aeref, void *auditdata)
-{
- struct av_decision avd;
- int errsave, rc;
-
- rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &avd);
- errsave = errno;
- avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
- errno = errsave;
- return rc;
-}
-
-int avc_compute_create(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, security_id_t *newsid)
-{
- int rc;
- struct avc_entry_ref aeref;
- struct avc_entry entry;
- char * ctx;
-
- *newsid = NULL;
- avc_entry_ref_init(&aeref);
-
- avc_get_lock(avc_lock);
-
- /* check for a cached entry */
- rc = avc_lookup(ssid, tsid, tclass, 0, &aeref);
- if (rc) {
- /* need to make a cache entry for this tuple */
- rc = security_compute_av(ssid->ctx, tsid->ctx,
- tclass, 0, &entry.avd);
- if (rc)
- goto out;
- rc = avc_insert(ssid, tsid, tclass, &entry, &aeref);
- if (rc)
- goto out;
- }
-
- /* check for a saved compute_create value */
- if (!aeref.ae->create_sid) {
- /* need to query the kernel policy */
- rc = security_compute_create(ssid->ctx, tsid->ctx, tclass,
- &ctx);
- if (rc)
- goto out;
- rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid);
- freecon(ctx);
- if (rc)
- goto out;
-
- aeref.ae->create_sid = *newsid;
- } else {
- /* found saved value */
- *newsid = aeref.ae->create_sid;
- }
-
- rc = 0;
-out:
- avc_release_lock(avc_lock);
- return rc;
-}
-
-int avc_add_callback(int (*callback) (uint32_t event, security_id_t ssid,
- security_id_t tsid,
- security_class_t tclass,
- access_vector_t perms,
- access_vector_t * out_retained),
- uint32_t events, security_id_t ssid,
- security_id_t tsid,
- security_class_t tclass, access_vector_t perms)
-{
- struct avc_callback_node *c;
- int rc = 0;
-
- c = avc_malloc(sizeof(*c));
- if (!c) {
- rc = -1;
- goto out;
- }
-
- c->callback = callback;
- c->events = events;
- c->ssid = ssid;
- c->tsid = tsid;
- c->tclass = tclass;
- c->perms = perms;
- c->next = avc_callbacks;
- avc_callbacks = c;
- out:
- return rc;
-}
-
-static inline int avc_sidcmp(security_id_t x, security_id_t y)
-{
- return (x == y || x == SECSID_WILD || y == SECSID_WILD);
-}
-
-static inline void avc_update_node(uint32_t event, struct avc_node *node,
- access_vector_t perms)
-{
- switch (event) {
- case AVC_CALLBACK_GRANT:
- node->ae.avd.allowed |= perms;
- break;
- case AVC_CALLBACK_TRY_REVOKE:
- case AVC_CALLBACK_REVOKE:
- node->ae.avd.allowed &= ~perms;
- break;
- case AVC_CALLBACK_AUDITALLOW_ENABLE:
- node->ae.avd.auditallow |= perms;
- break;
- case AVC_CALLBACK_AUDITALLOW_DISABLE:
- node->ae.avd.auditallow &= ~perms;
- break;
- case AVC_CALLBACK_AUDITDENY_ENABLE:
- node->ae.avd.auditdeny |= perms;
- break;
- case AVC_CALLBACK_AUDITDENY_DISABLE:
- node->ae.avd.auditdeny &= ~perms;
- break;
- }
-}
-
-static int avc_update_cache(uint32_t event, security_id_t ssid,
- security_id_t tsid, security_class_t tclass,
- access_vector_t perms)
-{
- struct avc_node *node;
- int i;
-
- avc_get_lock(avc_lock);
-
- if (ssid == SECSID_WILD || tsid == SECSID_WILD) {
- /* apply to all matching nodes */
- for (i = 0; i < AVC_CACHE_SLOTS; i++) {
- for (node = avc_cache.slots[i]; node; node = node->next) {
- if (avc_sidcmp(ssid, node->ae.ssid) &&
- avc_sidcmp(tsid, node->ae.tsid) &&
- tclass == node->ae.tclass) {
- avc_update_node(event, node, perms);
- }
- }
- }
- } else {
- /* apply to one node */
- node = avc_search_node(ssid, tsid, tclass, 0);
- if (node) {
- avc_update_node(event, node, perms);
- }
- }
-
- avc_release_lock(avc_lock);
-
- return 0;
-}
-
-/* avc_control - update cache and call callbacks
- *
- * This should not be called directly; use the individual event
- * functions instead.
- */
-static int avc_control(uint32_t event, security_id_t ssid,
- security_id_t tsid, security_class_t tclass,
- access_vector_t perms,
- uint32_t seqno, access_vector_t * out_retained)
-{
- struct avc_callback_node *c;
- access_vector_t tretained = 0, cretained = 0;
- int ret, rc = 0, errsave = 0;
- errno = 0;
-
- /*
- * try_revoke only removes permissions from the cache
- * state if they are not retained by the object manager.
- * Hence, try_revoke must wait until after the callbacks have
- * been invoked to update the cache state.
- */
- if (event != AVC_CALLBACK_TRY_REVOKE)
- avc_update_cache(event, ssid, tsid, tclass, perms);
-
- for (c = avc_callbacks; c; c = c->next) {
- if ((c->events & event) &&
- avc_sidcmp(c->ssid, ssid) &&
- avc_sidcmp(c->tsid, tsid) &&
- c->tclass == tclass && (c->perms & perms)) {
- cretained = 0;
- ret = c->callback(event, ssid, tsid, tclass,
- (c->perms & perms), &cretained);
- if (ret && !rc) {
- rc = ret;
- errsave = errno;
- }
- if (!ret)
- tretained |= cretained;
- }
- }
-
- if (event == AVC_CALLBACK_TRY_REVOKE) {
- /* revoke any unretained permissions */
- perms &= ~tretained;
- avc_update_cache(event, ssid, tsid, tclass, perms);
- *out_retained = tretained;
- }
-
- avc_get_lock(avc_lock);
- if (seqno > avc_cache.latest_notif)
- avc_cache.latest_notif = seqno;
- avc_release_lock(avc_lock);
-
- errno = errsave;
- return rc;
-}
-
-/**
- * avc_ss_grant - Grant previously denied permissions.
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions to grant
- * @seqno: policy sequence number
- */
-int avc_ss_grant(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t perms,
- uint32_t seqno)
-{
- return avc_control(AVC_CALLBACK_GRANT,
- ssid, tsid, tclass, perms, seqno, 0);
-}
-
-/**
- * avc_ss_try_revoke - Try to revoke previously granted permissions.
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions to grant
- * @seqno: policy sequence number
- * @out_retained: subset of @perms that are retained
- *
- * Try to revoke previously granted permissions, but
- * only if they are not retained as migrated permissions.
- * Return the subset of permissions that are retained via @out_retained.
- */
-int avc_ss_try_revoke(security_id_t ssid, security_id_t tsid,
- security_class_t tclass,
- access_vector_t perms, uint32_t seqno,
- access_vector_t * out_retained)
-{
- return avc_control(AVC_CALLBACK_TRY_REVOKE,
- ssid, tsid, tclass, perms, seqno, out_retained);
-}
-
-/**
- * avc_ss_revoke - Revoke previously granted permissions.
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions to grant
- * @seqno: policy sequence number
- *
- * Revoke previously granted permissions, even if
- * they are retained as migrated permissions.
- */
-int avc_ss_revoke(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t perms,
- uint32_t seqno)
-{
- return avc_control(AVC_CALLBACK_REVOKE,
- ssid, tsid, tclass, perms, seqno, 0);
-}
-
-/**
- * avc_ss_reset - Flush the cache and revalidate migrated permissions.
- * @seqno: policy sequence number
- */
-int avc_ss_reset(uint32_t seqno)
-{
- int rc;
-
- rc = avc_reset();
-
- avc_get_lock(avc_lock);
- if (seqno > avc_cache.latest_notif)
- avc_cache.latest_notif = seqno;
- avc_release_lock(avc_lock);
-
- return rc;
-}
-
-/**
- * avc_ss_set_auditallow - Enable or disable auditing of granted permissions.
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions to grant
- * @seqno: policy sequence number
- * @enable: enable flag.
- */
-int avc_ss_set_auditallow(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t perms,
- uint32_t seqno, uint32_t enable)
-{
- if (enable)
- return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE,
- ssid, tsid, tclass, perms, seqno, 0);
- else
- return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE,
- ssid, tsid, tclass, perms, seqno, 0);
-}
-
-/**
- * avc_ss_set_auditdeny - Enable or disable auditing of denied permissions.
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions to grant
- * @seqno: policy sequence number
- * @enable: enable flag.
- */
-int avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t perms,
- uint32_t seqno, uint32_t enable)
-{
- if (enable)
- return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE,
- ssid, tsid, tclass, perms, seqno, 0);
- else
- return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE,
- ssid, tsid, tclass, perms, seqno, 0);
-}
diff --git a/src/avc_internal.c b/src/avc_internal.c
deleted file mode 100644
index c89a886..0000000
--- a/src/avc_internal.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Callbacks for user-supplied memory allocation, supplemental
- * auditing, and locking routines.
- *
- * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
- *
- * Netlink code derived in part from sample code by
- * James Morris <jmorris@redhat.com>.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <poll.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <linux/types.h>
-#include <linux/netlink.h>
-#include "callbacks.h"
-#include "selinux_netlink.h"
-#include "avc_internal.h"
-
-#ifndef NETLINK_SELINUX
-#define NETLINK_SELINUX 7
-#endif
-
-/* callback pointers */
-void *(*avc_func_malloc) (size_t) = NULL;
-void (*avc_func_free) (void *) = NULL;
-
-void (*avc_func_log) (const char *, ...) = NULL;
-void (*avc_func_audit) (void *, security_class_t, char *, size_t) = NULL;
-
-int avc_using_threads = 0;
-int avc_app_main_loop = 0;
-void *(*avc_func_create_thread) (void (*)(void)) = NULL;
-void (*avc_func_stop_thread) (void *) = NULL;
-
-void *(*avc_func_alloc_lock) (void) = NULL;
-void (*avc_func_get_lock) (void *) = NULL;
-void (*avc_func_release_lock) (void *) = NULL;
-void (*avc_func_free_lock) (void *) = NULL;
-
-/* message prefix string and avc enforcing mode */
-char avc_prefix[AVC_PREFIX_SIZE] = "uavc";
-int avc_running = 0;
-int avc_enforcing = 1;
-int avc_setenforce = 0;
-int avc_netlink_trouble = 0;
-
-/* netlink socket code */
-static int fd = -1;
-
-int avc_netlink_open(int blocking)
-{
- int len, rc = 0;
- struct sockaddr_nl addr;
-
- fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_SELINUX);
- if (fd < 0) {
- rc = fd;
- goto out;
- }
-
- if (!blocking && fcntl(fd, F_SETFL, O_NONBLOCK)) {
- close(fd);
- fd = -1;
- rc = -1;
- goto out;
- }
-
- len = sizeof(addr);
-
- memset(&addr, 0, len);
- addr.nl_family = AF_NETLINK;
- addr.nl_groups = SELNL_GRP_AVC;
-
- if (bind(fd, (struct sockaddr *)&addr, len) < 0) {
- close(fd);
- fd = -1;
- rc = -1;
- goto out;
- }
- out:
- return rc;
-}
-
-void avc_netlink_close(void)
-{
- if (fd >= 0)
- close(fd);
- fd = -1;
-}
-
-static int avc_netlink_receive(char *buf, unsigned buflen, int blocking)
-{
- int rc;
- struct pollfd pfd = { fd, POLLIN | POLLPRI, 0 };
- struct sockaddr_nl nladdr;
- socklen_t nladdrlen = sizeof nladdr;
- struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
-
- do {
- rc = poll(&pfd, 1, (blocking ? -1 : 0));
- } while (rc < 0 && errno == EINTR);
-
- if (rc == 0 && !blocking) {
- errno = EWOULDBLOCK;
- return -1;
- }
- else if (rc < 1) {
- avc_log(SELINUX_ERROR, "%s: netlink poll: error %d\n",
- avc_prefix, errno);
- return rc;
- }
-
- rc = recvfrom(fd, buf, buflen, 0, (struct sockaddr *)&nladdr,
- &nladdrlen);
- if (rc < 0)
- return rc;
-
- if (nladdrlen != sizeof nladdr) {
- avc_log(SELINUX_WARNING,
- "%s: warning: netlink address truncated, len %d?\n",
- avc_prefix, nladdrlen);
- return -1;
- }
-
- if (nladdr.nl_pid) {
- avc_log(SELINUX_WARNING,
- "%s: warning: received spoofed netlink packet from: %d\n",
- avc_prefix, nladdr.nl_pid);
- return -1;
- }
-
- if (rc == 0) {
- avc_log(SELINUX_WARNING,
- "%s: warning: received EOF on netlink socket\n",
- avc_prefix);
- errno = EBADFD;
- return -1;
- }
-
- if (nlh->nlmsg_flags & MSG_TRUNC || nlh->nlmsg_len > (unsigned)rc) {
- avc_log(SELINUX_WARNING,
- "%s: warning: incomplete netlink message\n",
- avc_prefix);
- return -1;
- }
-
- return 0;
-}
-
-static int avc_netlink_process(char *buf)
-{
- int rc;
- struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
-
- switch (nlh->nlmsg_type) {
- case NLMSG_ERROR:{
- struct nlmsgerr *err = NLMSG_DATA(nlh);
-
- /* Netlink ack */
- if (err->error == 0)
- break;
-
- errno = -err->error;
- avc_log(SELINUX_ERROR,
- "%s: netlink error: %d\n", avc_prefix, errno);
- return -1;
- }
-
- case SELNL_MSG_SETENFORCE:{
- struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
- avc_log(SELINUX_INFO,
- "%s: received setenforce notice (enforcing=%d)\n",
- avc_prefix, msg->val);
- if (avc_setenforce)
- break;
- avc_enforcing = msg->val;
- if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
- avc_log(SELINUX_ERROR,
- "%s: cache reset returned %d (errno %d)\n",
- avc_prefix, rc, errno);
- return rc;
- }
- rc = selinux_netlink_setenforce(msg->val);
- if (rc < 0)
- return rc;
- break;
- }
-
- case SELNL_MSG_POLICYLOAD:{
- struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
- avc_log(SELINUX_INFO,
- "%s: received policyload notice (seqno=%d)\n",
- avc_prefix, msg->seqno);
- rc = avc_ss_reset(msg->seqno);
- if (rc < 0) {
- avc_log(SELINUX_ERROR,
- "%s: cache reset returned %d (errno %d)\n",
- avc_prefix, rc, errno);
- return rc;
- }
- rc = selinux_netlink_policyload(msg->seqno);
- if (rc < 0)
- return rc;
- break;
- }
-
- default:
- avc_log(SELINUX_WARNING,
- "%s: warning: unknown netlink message %d\n",
- avc_prefix, nlh->nlmsg_type);
- }
- return 0;
-}
-
-int avc_netlink_check_nb(void)
-{
- int rc;
- char buf[1024] __attribute__ ((aligned));
-
- while (1) {
- errno = 0;
- rc = avc_netlink_receive(buf, sizeof(buf), 0);
- if (rc < 0) {
- if (errno == EWOULDBLOCK)
- return 0;
- if (errno == 0 || errno == EINTR)
- continue;
- else {
- avc_log(SELINUX_ERROR,
- "%s: netlink recvfrom: error %d\n",
- avc_prefix, errno);
- return rc;
- }
- }
-
- (void)avc_netlink_process(buf);
- }
- return 0;
-}
-
-/* run routine for the netlink listening thread */
-void avc_netlink_loop(void)
-{
- int rc;
- char buf[1024] __attribute__ ((aligned));
-
- while (1) {
- errno = 0;
- rc = avc_netlink_receive(buf, sizeof(buf), 1);
- if (rc < 0) {
- if (errno == 0 || errno == EINTR)
- continue;
- else {
- avc_log(SELINUX_ERROR,
- "%s: netlink recvfrom: error %d\n",
- avc_prefix, errno);
- break;
- }
- }
-
- rc = avc_netlink_process(buf);
- if (rc < 0)
- break;
- }
-
- close(fd);
- fd = -1;
- avc_netlink_trouble = 1;
- avc_log(SELINUX_ERROR,
- "%s: netlink thread: errors encountered, terminating\n",
- avc_prefix);
-}
-
-int avc_netlink_acquire_fd(void)
-{
- avc_app_main_loop = 1;
-
- return fd;
-}
-
-void avc_netlink_release_fd(void)
-{
- avc_app_main_loop = 0;
-}
diff --git a/src/avc_internal.h b/src/avc_internal.h
deleted file mode 100644
index 53610e8..0000000
--- a/src/avc_internal.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * This file describes the internal interface used by the AVC
- * for calling the user-supplied memory allocation, supplemental
- * auditing, and locking routine, as well as incrementing the
- * statistics fields.
- *
- * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
- */
-#ifndef _SELINUX_AVC_INTERNAL_H_
-#define _SELINUX_AVC_INTERNAL_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <selinux/avc.h>
-#include "callbacks.h"
-#include "dso.h"
-
-/* callback pointers */
-extern void *(*avc_func_malloc) (size_t) hidden;
-extern void (*avc_func_free) (void *)hidden;
-
-extern void (*avc_func_log) (const char *, ...)hidden;
-extern void (*avc_func_audit) (void *, security_class_t, char *, size_t)hidden;
-
-extern int avc_using_threads hidden;
-extern int avc_app_main_loop hidden;
-extern void *(*avc_func_create_thread) (void (*)(void))hidden;
-extern void (*avc_func_stop_thread) (void *)hidden;
-
-extern void *(*avc_func_alloc_lock) (void)hidden;
-extern void (*avc_func_get_lock) (void *)hidden;
-extern void (*avc_func_release_lock) (void *)hidden;
-extern void (*avc_func_free_lock) (void *)hidden;
-
-static inline void set_callbacks(const struct avc_memory_callback *mem_cb,
- const struct avc_log_callback *log_cb,
- const struct avc_thread_callback *thread_cb,
- const struct avc_lock_callback *lock_cb)
-{
- if (mem_cb) {
- avc_func_malloc = mem_cb->func_malloc;
- avc_func_free = mem_cb->func_free;
- }
- if (log_cb) {
- avc_func_log = log_cb->func_log;
- avc_func_audit = log_cb->func_audit;
- }
- if (thread_cb) {
- avc_using_threads = 1;
- avc_func_create_thread = thread_cb->func_create_thread;
- avc_func_stop_thread = thread_cb->func_stop_thread;
- }
- if (lock_cb) {
- avc_func_alloc_lock = lock_cb->func_alloc_lock;
- avc_func_get_lock = lock_cb->func_get_lock;
- avc_func_release_lock = lock_cb->func_release_lock;
- avc_func_free_lock = lock_cb->func_free_lock;
- }
-}
-
-/* message prefix and enforcing mode*/
-#define AVC_PREFIX_SIZE 16
-extern char avc_prefix[AVC_PREFIX_SIZE] hidden;
-extern int avc_running hidden;
-extern int avc_enforcing hidden;
-extern int avc_setenforce hidden;
-
-/* user-supplied callback interface for avc */
-static inline void *avc_malloc(size_t size)
-{
- return avc_func_malloc ? avc_func_malloc(size) : malloc(size);
-}
-
-static inline void avc_free(void *ptr)
-{
- if (avc_func_free)
- avc_func_free(ptr);
- else
- free(ptr);
-}
-
-/* this is a macro in order to use the variadic capability. */
-#define avc_log(type, format...) \
- if (avc_func_log) \
- avc_func_log(format); \
- else \
- selinux_log(type, format);
-
-static inline void avc_suppl_audit(void *ptr, security_class_t class,
- char *buf, size_t len)
-{
- if (avc_func_audit)
- avc_func_audit(ptr, class, buf, len);
- else
- selinux_audit(ptr, class, buf, len);
-}
-
-static inline void *avc_create_thread(void (*run) (void))
-{
- return avc_func_create_thread ? avc_func_create_thread(run) : NULL;
-}
-
-static inline void avc_stop_thread(void *thread)
-{
- if (avc_func_stop_thread)
- avc_func_stop_thread(thread);
-}
-
-static inline void *avc_alloc_lock(void)
-{
- return avc_func_alloc_lock ? avc_func_alloc_lock() : NULL;
-}
-
-static inline void avc_get_lock(void *lock)
-{
- if (avc_func_get_lock)
- avc_func_get_lock(lock);
-}
-
-static inline void avc_release_lock(void *lock)
-{
- if (avc_func_release_lock)
- avc_func_release_lock(lock);
-}
-
-static inline void avc_free_lock(void *lock)
-{
- if (avc_func_free_lock)
- avc_func_free_lock(lock);
-}
-
-/* statistics helper routines */
-#ifdef AVC_CACHE_STATS
-
-#define avc_cache_stats_incr(field) \
- cache_stats.field ++;
-#define avc_cache_stats_add(field, num) \
- cache_stats.field += num;
-
-#else
-
-#define avc_cache_stats_incr(field)
-#define avc_cache_stats_add(field, num)
-
-#endif
-
-/* logging helper routines */
-#define AVC_AUDIT_BUFSIZE 1024
-
-/* again, we need the variadic capability here */
-#define log_append(buf,format...) \
- snprintf(buf+strlen(buf), AVC_AUDIT_BUFSIZE-strlen(buf), format)
-
-/* internal callbacks */
-int avc_ss_grant(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t perms,
- uint32_t seqno) hidden;
-int avc_ss_try_revoke(security_id_t ssid, security_id_t tsid,
- security_class_t tclass,
- access_vector_t perms, uint32_t seqno,
- access_vector_t * out_retained) hidden;
-int avc_ss_revoke(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t perms,
- uint32_t seqno) hidden;
-int avc_ss_reset(uint32_t seqno) hidden;
-int avc_ss_set_auditallow(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t perms,
- uint32_t seqno, uint32_t enable) hidden;
-int avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid,
- security_class_t tclass, access_vector_t perms,
- uint32_t seqno, uint32_t enable) hidden;
-
-/* netlink kernel message code */
-extern int avc_netlink_trouble hidden;
-
-hidden_proto(avc_av_stats)
- hidden_proto(avc_cleanup)
- hidden_proto(avc_reset)
- hidden_proto(avc_audit)
- hidden_proto(avc_has_perm_noaudit)
-#endif /* _SELINUX_AVC_INTERNAL_H_ */
diff --git a/src/avc_sidtab.c b/src/avc_sidtab.c
deleted file mode 100644
index 52f21df..0000000
--- a/src/avc_sidtab.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Implementation of the userspace SID hashtable.
- *
- * Author : Eamon Walsh, <ewalsh@epoch.ncsc.mil>
- */
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include "selinux_internal.h"
-#include <selinux/avc.h>
-#include "avc_sidtab.h"
-#include "avc_internal.h"
-
-static inline unsigned sidtab_hash(const char * key)
-{
- char *p, *keyp;
- unsigned int size;
- unsigned int val;
-
- val = 0;
- keyp = (char *)key;
- size = strlen(keyp);
- for (p = keyp; (unsigned int)(p - keyp) < size; p++)
- val =
- (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p);
- return val & (SIDTAB_SIZE - 1);
-}
-
-int sidtab_init(struct sidtab *s)
-{
- int i, rc = 0;
-
- s->htable = (struct sidtab_node **)avc_malloc
- (sizeof(struct sidtab_node *) * SIDTAB_SIZE);
-
- if (!s->htable) {
- rc = -1;
- goto out;
- }
- for (i = 0; i < SIDTAB_SIZE; i++)
- s->htable[i] = NULL;
- s->nel = 0;
- out:
- return rc;
-}
-
-int sidtab_insert(struct sidtab *s, const char * ctx)
-{
- int hvalue, rc = 0;
- struct sidtab_node *newnode;
- char * newctx;
-
- newnode = (struct sidtab_node *)avc_malloc(sizeof(*newnode));
- if (!newnode) {
- rc = -1;
- goto out;
- }
- newctx = (char *) strdup(ctx);
- if (!newctx) {
- rc = -1;
- avc_free(newnode);
- goto out;
- }
-
- hvalue = sidtab_hash(newctx);
- newnode->next = s->htable[hvalue];
- newnode->sid_s.ctx = newctx;
- newnode->sid_s.refcnt = 1; /* unused */
- s->htable[hvalue] = newnode;
- s->nel++;
- out:
- return rc;
-}
-
-int
-sidtab_context_to_sid(struct sidtab *s,
- const char * ctx, security_id_t * sid)
-{
- int hvalue, rc = 0;
- struct sidtab_node *cur;
-
- *sid = NULL;
- hvalue = sidtab_hash(ctx);
-
- loop:
- cur = s->htable[hvalue];
- while (cur != NULL && strcmp(cur->sid_s.ctx, ctx))
- cur = cur->next;
-
- if (cur == NULL) { /* need to make a new entry */
- rc = sidtab_insert(s, ctx);
- if (rc)
- goto out;
- goto loop; /* find the newly inserted node */
- }
-
- *sid = &cur->sid_s;
- out:
- return rc;
-}
-
-void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen)
-{
- int i, chain_len, slots_used, max_chain_len;
- struct sidtab_node *cur;
-
- slots_used = 0;
- max_chain_len = 0;
- for (i = 0; i < SIDTAB_SIZE; i++) {
- cur = h->htable[i];
- if (cur) {
- slots_used++;
- chain_len = 0;
- while (cur) {
- chain_len++;
- cur = cur->next;
- }
-
- if (chain_len > max_chain_len)
- max_chain_len = chain_len;
- }
- }
-
- snprintf(buf, buflen,
- "%s: %d SID entries and %d/%d buckets used, longest "
- "chain length %d\n", avc_prefix, h->nel, slots_used,
- SIDTAB_SIZE, max_chain_len);
-}
-
-void sidtab_destroy(struct sidtab *s)
-{
- int i;
- struct sidtab_node *cur, *temp;
-
- if (!s)
- return;
-
- for (i = 0; i < SIDTAB_SIZE; i++) {
- cur = s->htable[i];
- while (cur != NULL) {
- temp = cur;
- cur = cur->next;
- freecon(temp->sid_s.ctx);
- avc_free(temp);
- }
- s->htable[i] = NULL;
- }
- avc_free(s->htable);
- s->htable = NULL;
-}
diff --git a/src/avc_sidtab.h b/src/avc_sidtab.h
deleted file mode 100644
index bce9b87..0000000
--- a/src/avc_sidtab.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * A security identifier table (sidtab) is a hash table
- * of security context structures indexed by SID value.
- */
-#ifndef _SELINUX_AVC_SIDTAB_H_
-#define _SELINUX_AVC_SIDTAB_H_
-
-#include <selinux/selinux.h>
-#include <selinux/avc.h>
-#include "dso.h"
-
-struct sidtab_node {
- struct security_id sid_s;
- struct sidtab_node *next;
-};
-
-#define SIDTAB_HASH_BITS 7
-#define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS)
-#define SIDTAB_HASH_MASK (SIDTAB_HASH_BUCKETS-1)
-#define SIDTAB_SIZE SIDTAB_HASH_BUCKETS
-
-struct sidtab {
- struct sidtab_node **htable;
- unsigned nel;
-};
-
-int sidtab_init(struct sidtab *s) hidden;
-int sidtab_insert(struct sidtab *s, const char * ctx) hidden;
-
-int sidtab_context_to_sid(struct sidtab *s,
- const char * ctx, security_id_t * sid) hidden;
-
-void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen) hidden;
-void sidtab_destroy(struct sidtab *s) hidden;
-
-#endif /* _SELINUX_AVC_SIDTAB_H_ */
diff --git a/src/booleans.c b/src/booleans.c
deleted file mode 100644
index 17e0ad8..0000000
--- a/src/booleans.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Author: Karl MacMillan <kmacmillan@tresys.com>
- *
- * Modified:
- * Dan Walsh <dwalsh@redhat.com> - Added security_load_booleans().
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fnmatch.h>
-#include <limits.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "selinux_internal.h"
-#include "policy.h"
-
-#define SELINUX_BOOL_DIR "/booleans/"
-
-static int filename_select(const struct dirent *d)
-{
- if (d->d_name[0] == '.'
- && (d->d_name[1] == '\0'
- || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
- return 0;
- return 1;
-}
-
-int security_get_boolean_names(char ***names, int *len)
-{
- char path[PATH_MAX];
- int i, rc;
- struct dirent **namelist;
- char **n;
-
- assert(len);
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s%s", selinux_mnt, SELINUX_BOOL_DIR);
- *len = scandir(path, &namelist, &filename_select, alphasort);
- if (*len <= 0) {
- return -1;
- }
-
- n = (char **)malloc(sizeof(char *) * *len);
- if (!n) {
- rc = -1;
- goto bad;
- }
-
- for (i = 0; i < *len; i++) {
- n[i] = strdup(namelist[i]->d_name);
- if (!n[i]) {
- rc = -1;
- goto bad_freen;
- }
- }
- rc = 0;
- *names = n;
- out:
- for (i = 0; i < *len; i++) {
- free(namelist[i]);
- }
- free(namelist);
- return rc;
- bad_freen:
- for (--i; i >= 0; --i)
- free(n[i]);
- free(n);
- bad:
- goto out;
-}
-
-hidden_def(security_get_boolean_names)
-#define STRBUF_SIZE 3
-static int get_bool_value(const char *name, char **buf)
-{
- int fd, len;
- char *fname = NULL;
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- *buf = (char *)malloc(sizeof(char) * (STRBUF_SIZE + 1));
- if (!*buf)
- goto out;
- (*buf)[STRBUF_SIZE] = 0;
-
- len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR);
- fname = (char *)malloc(sizeof(char) * len);
- if (!fname)
- goto out;
- snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name);
-
- fd = open(fname, O_RDONLY);
- if (fd < 0)
- goto out;
-
- len = read(fd, *buf, STRBUF_SIZE);
- close(fd);
- if (len != STRBUF_SIZE)
- goto out;
-
- free(fname);
- return 0;
- out:
- if (*buf)
- free(*buf);
- if (fname)
- free(fname);
- return -1;
-}
-
-int security_get_boolean_pending(const char *name)
-{
- char *buf;
- int val;
-
- if (get_bool_value(name, &buf))
- return -1;
-
- if (atoi(&buf[1]))
- val = 1;
- else
- val = 0;
- free(buf);
- return val;
-}
-
-int security_get_boolean_active(const char *name)
-{
- char *buf;
- int val;
-
- if (get_bool_value(name, &buf))
- return -1;
-
- buf[1] = '\0';
- if (atoi(buf))
- val = 1;
- else
- val = 0;
- free(buf);
- return val;
-}
-
-hidden_def(security_get_boolean_active)
-
-int security_set_boolean(const char *name, int value)
-{
- int fd, ret, len;
- char buf[2], *fname;
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
- if (value < 0 || value > 1) {
- errno = EINVAL;
- return -1;
- }
-
- len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR);
- fname = (char *)malloc(sizeof(char) * len);
- if (!fname)
- return -1;
- snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name);
-
- fd = open(fname, O_WRONLY);
- if (fd < 0) {
- ret = -1;
- goto out;
- }
-
- if (value)
- buf[0] = '1';
- else
- buf[0] = '0';
- buf[1] = '\0';
-
- ret = write(fd, buf, 2);
- close(fd);
- out:
- free(fname);
- if (ret > 0)
- return 0;
- else
- return -1;
-}
-
-hidden_def(security_set_boolean)
-
-int security_commit_booleans(void)
-{
- int fd, ret;
- char buf[2];
- char path[PATH_MAX];
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s/commit_pending_bools", selinux_mnt);
- fd = open(path, O_WRONLY);
- if (fd < 0)
- return -1;
-
- buf[0] = '1';
- buf[1] = '\0';
-
- ret = write(fd, buf, 2);
- close(fd);
-
- if (ret > 0)
- return 0;
- else
- return -1;
-}
-
-hidden_def(security_commit_booleans)
-
-static void rollback(SELboolean * boollist, int end)
-{
- int i;
-
- for (i = 0; i < end; i++)
- security_set_boolean(boollist[i].name,
- security_get_boolean_active(boollist[i].
- name));
-}
-
-int security_set_boolean_list(size_t boolcnt, SELboolean * const boollist,
- int permanent __attribute__((unused)))
-{
-
- size_t i;
- for (i = 0; i < boolcnt; i++) {
- if (security_set_boolean(boollist[i].name, boollist[i].value)) {
- rollback(boollist, i);
- return -1;
- }
- }
-
- /* OK, let's do the commit */
- if (security_commit_booleans()) {
- return -1;
- }
-
- return 0;
-}
diff --git a/src/callbacks.c b/src/callbacks.c
deleted file mode 100644
index c3cf98b..0000000
--- a/src/callbacks.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * User-supplied callbacks and default implementations.
- * Class and permission mappings.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <selinux/selinux.h>
-#include "callbacks.h"
-
-/* default implementations */
-static int __attribute__ ((format(printf, 2, 3)))
-default_selinux_log(int type __attribute__((unused)), const char *fmt, ...)
-{
- int rc;
- va_list ap;
- va_start(ap, fmt);
- rc = vfprintf(stderr, fmt, ap);
- va_end(ap);
- return rc;
-}
-
-static int
-default_selinux_audit(void *ptr __attribute__((unused)),
- security_class_t cls __attribute__((unused)),
- char *buf __attribute__((unused)),
- size_t len __attribute__((unused)))
-{
- return 0;
-}
-
-static int
-default_selinux_validate(char **ctx)
-{
- return security_check_context(*ctx);
-}
-
-static int
-default_selinux_setenforce(int enforcing __attribute__((unused)))
-{
- return 0;
-}
-
-static int
-default_selinux_policyload(int seqno __attribute__((unused)))
-{
- return 0;
-}
-
-/* callback pointers */
-int __attribute__ ((format(printf, 2, 3)))
-(*selinux_log)(int, const char *, ...) =
- default_selinux_log;
-
-int
-(*selinux_audit) (void *, security_class_t, char *, size_t) =
- default_selinux_audit;
-
-int
-(*selinux_validate)(char **ctx) =
- default_selinux_validate;
-
-int
-(*selinux_netlink_setenforce) (int enforcing) =
- default_selinux_setenforce;
-
-int
-(*selinux_netlink_policyload) (int seqno) =
- default_selinux_policyload;
-
-/* callback setting function */
-void
-selinux_set_callback(int type, union selinux_callback cb)
-{
- switch (type) {
- case SELINUX_CB_LOG:
- selinux_log = cb.func_log;
- break;
- case SELINUX_CB_AUDIT:
- selinux_audit = cb.func_audit;
- break;
- case SELINUX_CB_VALIDATE:
- selinux_validate = cb.func_validate;
- break;
- case SELINUX_CB_SETENFORCE:
- selinux_netlink_setenforce = cb.func_setenforce;
- break;
- case SELINUX_CB_POLICYLOAD:
- selinux_netlink_policyload = cb.func_policyload;
- break;
- }
-}
-
-/* callback getting function */
-union selinux_callback
-selinux_get_callback(int type)
-{
- union selinux_callback cb;
-
- switch (type) {
- case SELINUX_CB_LOG:
- cb.func_log = selinux_log;
- break;
- case SELINUX_CB_AUDIT:
- cb.func_audit = selinux_audit;
- break;
- case SELINUX_CB_VALIDATE:
- cb.func_validate = selinux_validate;
- break;
- case SELINUX_CB_SETENFORCE:
- cb.func_setenforce = selinux_netlink_setenforce;
- break;
- case SELINUX_CB_POLICYLOAD:
- cb.func_policyload = selinux_netlink_policyload;
- break;
- default:
- memset(&cb, 0, sizeof(cb));
- errno = EINVAL;
- break;
- }
- return cb;
-}
diff --git a/src/callbacks.h b/src/callbacks.h
deleted file mode 100644
index 2a572e0..0000000
--- a/src/callbacks.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * This file describes the callbacks passed to selinux_init() and available
- * for use from the library code. They all have default implementations.
- */
-#ifndef _SELINUX_CALLBACKS_H_
-#define _SELINUX_CALLBACKS_H_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <selinux/selinux.h>
-#include "dso.h"
-
-/* callback pointers */
-extern int __attribute__ ((format(printf, 2, 3)))
-(*selinux_log) (int type, const char *, ...) hidden;
-
-extern int
-(*selinux_audit) (void *, security_class_t, char *, size_t) hidden;
-
-extern int
-(*selinux_validate)(char **ctx) hidden;
-
-extern int
-(*selinux_netlink_setenforce) (int enforcing) hidden;
-
-extern int
-(*selinux_netlink_policyload) (int seqno) hidden;
-
-#endif /* _SELINUX_CALLBACKS_H_ */
diff --git a/src/canonicalize_context.c b/src/canonicalize_context.c
deleted file mode 100644
index b8f874f..0000000
--- a/src/canonicalize_context.c
+++ /dev/null
@@ -1,62 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include "selinux_internal.h"
-#include "policy.h"
-#include <limits.h>
-
-int security_canonicalize_context(const char * con,
- char ** canoncon)
-{
- char path[PATH_MAX];
- char *buf;
- size_t size;
- int fd, ret;
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s/context", selinux_mnt);
- fd = open(path, O_RDWR);
- if (fd < 0)
- return -1;
-
- size = selinux_page_size;
- buf = malloc(size);
- if (!buf) {
- ret = -1;
- goto out;
- }
- strncpy(buf, con, size);
-
- ret = write(fd, buf, strlen(buf) + 1);
- if (ret < 0)
- goto out2;
-
- memset(buf, 0, size);
- ret = read(fd, buf, size - 1);
- if (ret < 0 && errno == EINVAL) {
- /* Fall back to the original context for kernels
- that do not support the extended interface. */
- strncpy(buf, con, size);
- }
-
- *canoncon = strdup(buf);
- if (!(*canoncon)) {
- ret = -1;
- goto out2;
- }
- ret = 0;
- out2:
- free(buf);
- out:
- close(fd);
- return ret;
-}
-
diff --git a/src/checkAccess.c b/src/checkAccess.c
deleted file mode 100644
index dc11cf7..0000000
--- a/src/checkAccess.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-#include <unistd.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <errno.h>
-#include "selinux_internal.h"
-#include <selinux/avc.h>
-#include "avc_internal.h"
-
-static pthread_once_t once = PTHREAD_ONCE_INIT;
-static int selinux_enabled;
-
-static void avc_init_once(void)
-{
- selinux_enabled = is_selinux_enabled();
- if (selinux_enabled == 1)
- avc_open(NULL, 0);
-}
-
-int selinux_check_access(const char * scon, const char * tcon, const char *class, const char *perm, void *aux) {
- int rc;
- security_id_t scon_id;
- security_id_t tcon_id;
- security_class_t sclass;
- access_vector_t av;
-
- __selinux_once(once, avc_init_once);
-
- if (selinux_enabled != 1)
- return 0;
-
- rc = avc_context_to_sid(scon, &scon_id);
- if (rc < 0)
- return rc;
-
- rc = avc_context_to_sid(tcon, &tcon_id);
- if (rc < 0)
- return rc;
-
- sclass = string_to_security_class(class);
- if (sclass == 0) {
- rc = errno;
- avc_log(SELINUX_ERROR, "Unknown class %s", class);
- if (security_deny_unknown() == 0)
- return 0;
- errno = rc;
- return -1;
- }
-
- av = string_to_av_perm(sclass, perm);
- if (av == 0) {
- rc = errno;
- avc_log(SELINUX_ERROR, "Unknown permission %s for class %s", perm, class);
- if (security_deny_unknown() == 0)
- return 0;
- errno = rc;
- return -1;
- }
-
- return avc_has_perm (scon_id, tcon_id, sclass, av, NULL, aux);
-}
-
diff --git a/src/check_context.c b/src/check_context.c
deleted file mode 100644
index 7471194..0000000
--- a/src/check_context.c
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include "selinux_internal.h"
-#include "policy.h"
-#include <limits.h>
-
-int security_check_context(const char * con)
-{
- char path[PATH_MAX];
- int fd, ret;
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s/context", selinux_mnt);
- fd = open(path, O_RDWR);
- if (fd < 0)
- return -1;
-
- ret = write(fd, con, strlen(con) + 1);
- close(fd);
- if (ret < 0)
- return -1;
- return 0;
-}
-
diff --git a/src/compute_av.c b/src/compute_av.c
deleted file mode 100644
index d6f76f8..0000000
--- a/src/compute_av.c
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <limits.h>
-#include "selinux_internal.h"
-#include "policy.h"
-#include "mapping.h"
-
-int security_compute_av(const char * scon,
- const char * tcon,
- security_class_t tclass,
- access_vector_t requested,
- struct av_decision *avd)
-{
- char path[PATH_MAX];
- char *buf;
- size_t len;
- int fd, ret;
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s/access", selinux_mnt);
- fd = open(path, O_RDWR);
- if (fd < 0)
- return -1;
-
- len = selinux_page_size;
- buf = malloc(len);
- if (!buf) {
- ret = -1;
- goto out;
- }
-
- snprintf(buf, len, "%s %s %hu %x", scon, tcon,
- unmap_class(tclass), unmap_perm(tclass, requested));
-
- ret = write(fd, buf, strlen(buf));
- if (ret < 0)
- goto out2;
-
- memset(buf, 0, len);
- ret = read(fd, buf, len - 1);
- if (ret < 0)
- goto out2;
-
- ret = sscanf(buf, "%x %x %x %x %u %x",
- &avd->allowed, &avd->decided,
- &avd->auditallow, &avd->auditdeny,
- &avd->seqno, &avd->flags);
- if (ret < 5) {
- ret = -1;
- goto out2;
- } else if (ret < 6)
- avd->flags = 0;
-
- map_decision(tclass, avd);
-
- ret = 0;
- out2:
- free(buf);
- out:
- close(fd);
- return ret;
-}
-
diff --git a/src/compute_create.c b/src/compute_create.c
deleted file mode 100644
index d3b16c9..0000000
--- a/src/compute_create.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <limits.h>
-#include "selinux_internal.h"
-#include "policy.h"
-#include "mapping.h"
-
-int security_compute_create(const char * scon,
- const char * tcon,
- security_class_t tclass,
- char ** newcon)
-{
- char path[PATH_MAX];
- char *buf;
- size_t size;
- int fd, ret;
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s/create", selinux_mnt);
- fd = open(path, O_RDWR);
- if (fd < 0)
- return -1;
-
- size = selinux_page_size;
- buf = malloc(size);
- if (!buf) {
- ret = -1;
- goto out;
- }
- snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass));
-
- ret = write(fd, buf, strlen(buf));
- if (ret < 0)
- goto out2;
-
- memset(buf, 0, size);
- ret = read(fd, buf, size - 1);
- if (ret < 0)
- goto out2;
-
- *newcon = strdup(buf);
- if (!(*newcon)) {
- ret = -1;
- goto out2;
- }
- ret = 0;
- out2:
- free(buf);
- out:
- close(fd);
- return ret;
-}
diff --git a/src/context.c b/src/context.c
deleted file mode 100644
index 66abea1..0000000
--- a/src/context.c
+++ /dev/null
@@ -1,197 +0,0 @@
-#include "context_internal.h"
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#define COMP_USER 0
-#define COMP_ROLE 1
-#define COMP_TYPE 2
-#define COMP_RANGE 3
-
-typedef struct {
- char *current_str; /* This is made up-to-date only when needed */
- char *(component[4]);
-} context_private_t;
-
-/*
- * Allocate a new context, initialized from str. There must be 3 or
- * 4 colon-separated components and no whitespace in any component other
- * than the MLS component.
- */
-context_t context_new(const char *str)
-{
- int i, count;
- errno = 0;
- context_private_t *n =
- (context_private_t *) malloc(sizeof(context_private_t));
- context_t result = (context_t) malloc(sizeof(context_s_t));
- const char *p, *tok;
-
- if (result)
- result->ptr = n;
- else
- free(n);
- if (n == 0 || result == 0) {
- goto err;
- }
- n->current_str = n->component[0] = n->component[1] = n->component[2] =
- n->component[3] = 0;
- for (i = count = 0, p = str; *p; p++) {
- switch (*p) {
- case ':':
- count++;
- break;
- case '\n':
- case '\t':
- case '\r':
- goto err; /* sanity check */
- case ' ':
- if (count < 3)
- goto err; /* sanity check */
- }
- }
- /*
- * Could be anywhere from 2 - 5
- * e.g user:role:type to user:role:type:sens1:cata-sens2:catb
- */
- if (count < 2 || count > 5) { /* might not have a range */
- goto err;
- }
-
- n->component[3] = 0;
- for (i = 0, tok = str; *tok; i++) {
- if (i < 3)
- for (p = tok; *p && *p != ':'; p++) { /* empty */
- } else {
- /* MLS range is one component */
- for (p = tok; *p; p++) { /* empty */
- }
- }
- n->component[i] = (char *)malloc(p - tok + 1);
- if (n->component[i] == 0)
- goto err;
- strncpy(n->component[i], tok, p - tok);
- n->component[i][p - tok] = '\0';
- tok = *p ? p + 1 : p;
- }
- return result;
- err:
- if (errno == 0) errno = EINVAL;
- context_free(result);
- return 0;
-}
-
-hidden_def(context_new)
-
-static void conditional_free(char **v)
-{
- if (*v) {
- free(*v);
- }
- *v = 0;
-}
-
-/*
- * free all storage used by a context. Safe to call with
- * null pointer.
- */
-void context_free(context_t context)
-{
- context_private_t *n;
- int i;
- if (context) {
- n = context->ptr;
- if (n) {
- conditional_free(&n->current_str);
- for (i = 0; i < 4; i++) {
- conditional_free(&n->component[i]);
- }
- free(n);
- }
- free(context);
- }
-}
-
-hidden_def(context_free)
-
-/*
- * Return a pointer to the string value of the context.
- */
-char *context_str(context_t context)
-{
- context_private_t *n = context->ptr;
- int i;
- size_t total = 0;
- conditional_free(&n->current_str);
- for (i = 0; i < 4; i++) {
- if (n->component[i]) {
- total += strlen(n->component[i]) + 1;
- }
- }
- n->current_str = malloc(total);
- if (n->current_str != 0) {
- char *cp = n->current_str;
-
- strcpy(cp, n->component[0]);
- cp += strlen(cp);
- for (i = 1; i < 4; i++) {
- if (n->component[i]) {
- *cp++ = ':';
- strcpy(cp, n->component[i]);
- cp += strlen(cp);
- }
- }
- }
- return n->current_str;
-}
-
-hidden_def(context_str)
-
-/* Returns nonzero iff failed */
-static int set_comp(context_private_t * n, int idx, const char *str)
-{
- char *t = NULL;
- const char *p;
- if (str) {
- t = (char *)malloc(strlen(str) + 1);
- if (!t) {
- return 1;
- }
- for (p = str; *p; p++) {
- if (*p == '\t' || *p == '\n' || *p == '\r' ||
- ((*p == ':' || *p == ' ') && idx != COMP_RANGE)) {
- free(t);
- errno = EINVAL;
- return 1;
- }
- }
- strcpy(t, str);
- }
- conditional_free(&n->component[idx]);
- n->component[idx] = t;
- return 0;
-}
-
-#define def_get(name,tag) \
-const char * context_ ## name ## _get(context_t context) \
-{ \
- context_private_t *n = context->ptr; \
- return n->component[tag]; \
-} \
-hidden_def(context_ ## name ## _get)
-
-def_get(type, COMP_TYPE)
- def_get(user, COMP_USER)
- def_get(range, COMP_RANGE)
- def_get(role, COMP_ROLE)
-#define def_set(name,tag) \
-int context_ ## name ## _set(context_t context, const char* str) \
-{ \
- return set_comp(context->ptr,tag,str);\
-} \
-hidden_def(context_ ## name ## _set)
- def_set(type, COMP_TYPE)
- def_set(role, COMP_ROLE)
- def_set(user, COMP_USER)
- def_set(range, COMP_RANGE)
diff --git a/src/context_internal.h b/src/context_internal.h
deleted file mode 100644
index 3c71e80..0000000
--- a/src/context_internal.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <selinux/context.h>
-#include "dso.h"
-
-hidden_proto(context_new)
- hidden_proto(context_free)
- hidden_proto(context_str)
- hidden_proto(context_type_set)
- hidden_proto(context_type_get)
- hidden_proto(context_role_set)
- hidden_proto(context_role_get)
- hidden_proto(context_user_set)
- hidden_proto(context_user_get)
- hidden_proto(context_range_set)
- hidden_proto(context_range_get)
diff --git a/src/deny_unknown.c b/src/deny_unknown.c
deleted file mode 100644
index c93998a..0000000
--- a/src/deny_unknown.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include "selinux_internal.h"
-#include "policy.h"
-#include <stdio.h>
-#include <limits.h>
-
-int security_deny_unknown(void)
-{
- int fd, ret, deny_unknown = 0;
- char path[PATH_MAX];
- char buf[20];
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof(path), "%s/deny_unknown", selinux_mnt);
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return -1;
-
- memset(buf, 0, sizeof(buf));
- ret = read(fd, buf, sizeof(buf) - 1);
- close(fd);
- if (ret < 0)
- return -1;
-
- if (sscanf(buf, "%d", &deny_unknown) != 1)
- return -1;
-
- return deny_unknown;
-}
-
-hidden_def(security_deny_unknown);
diff --git a/src/disable.c b/src/disable.c
deleted file mode 100644
index dac0f5b..0000000
--- a/src/disable.c
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include "selinux_internal.h"
-#include "policy.h"
-#include <stdio.h>
-#include <limits.h>
-
-int security_disable(void)
-{
- int fd, ret;
- char path[PATH_MAX];
- char buf[20];
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s/disable", selinux_mnt);
- fd = open(path, O_WRONLY);
- if (fd < 0)
- return -1;
-
- buf[0] = '1';
- buf[1] = '\0';
- ret = write(fd, buf, strlen(buf));
- close(fd);
- if (ret < 0)
- return -1;
-
- return 0;
-}
-
-hidden_def(security_disable)
diff --git a/src/dso.h b/src/dso.h
deleted file mode 100644
index 12c3d11..0000000
--- a/src/dso.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _SELINUX_DSO_H
-#define _SELINUX_DSO_H 1
-
-#ifdef SHARED
-# define hidden __attribute__ ((visibility ("hidden")))
-# define hidden_proto(fct) __hidden_proto (fct, fct##_internal)
-# define __hidden_proto(fct, internal) \
- extern __typeof (fct) internal; \
- extern __typeof (fct) fct __asm (#internal) hidden;
-# if defined(__alpha__) || defined(__mips__)
-# define hidden_def(fct) \
- asm (".globl " #fct "\n" #fct " = " #fct "_internal");
-# else
-# define hidden_def(fct) \
- asm (".globl " #fct "\n.set " #fct ", " #fct "_internal");
-#endif
-#else
-# define hidden
-# define hidden_proto(fct)
-# define hidden_def(fct)
-#endif
-
-#endif
diff --git a/src/enabled.c b/src/enabled.c
deleted file mode 100644
index c60eb19..0000000
--- a/src/enabled.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include "selinux_internal.h"
-#include <stdlib.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include "policy.h"
-
-int is_selinux_enabled(void)
-{
- /* init_selinuxmnt() gets called before this function. We
- * will assume that if a selinux file system is mounted, then
- * selinux is enabled. */
- return (selinux_mnt ? 1 : 0);
-}
-
-hidden_def(is_selinux_enabled)
-
-/*
- * Function: is_selinux_mls_enabled()
- * Return: 1 on success
- * 0 on failure
- */
-int is_selinux_mls_enabled(void)
-{
- char buf[20], path[PATH_MAX];
- int fd, ret, enabled = 0;
-
- if (!selinux_mnt)
- return enabled;
-
- snprintf(path, sizeof path, "%s/mls", selinux_mnt);
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return enabled;
-
- memset(buf, 0, sizeof buf);
-
- do {
- ret = read(fd, buf, sizeof buf - 1);
- } while (ret < 0 && errno == EINTR);
- close(fd);
- if (ret < 0)
- return enabled;
-
- if (!strcmp(buf, "1"))
- enabled = 1;
-
- return enabled;
-}
-
-hidden_def(is_selinux_mls_enabled)
diff --git a/src/fgetfilecon.c b/src/fgetfilecon.c
deleted file mode 100644
index 33cdc27..0000000
--- a/src/fgetfilecon.c
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/xattr.h>
-#include "selinux_internal.h"
-#include "policy.h"
-
-int fgetfilecon(int fd, char ** context)
-{
- char *buf;
- ssize_t size;
- ssize_t ret;
-
- size = INITCONTEXTLEN + 1;
- buf = malloc(size);
- if (!buf)
- return -1;
- memset(buf, 0, size);
-
- ret = fgetxattr(fd, XATTR_NAME_SELINUX, buf, size - 1);
- if (ret < 0 && errno == ERANGE) {
- char *newbuf;
-
- size = fgetxattr(fd, XATTR_NAME_SELINUX, NULL, 0);
- if (size < 0)
- goto out;
-
- size++;
- newbuf = realloc(buf, size);
- if (!newbuf)
- goto out;
-
- buf = newbuf;
- memset(buf, 0, size);
- ret = fgetxattr(fd, XATTR_NAME_SELINUX, buf, size - 1);
- }
- out:
- if (ret == 0) {
- /* Re-map empty attribute values to errors. */
- errno = EOPNOTSUPP;
- ret = -1;
- }
- if (ret < 0)
- free(buf);
- else
- *context = buf;
- return ret;
-}
-
diff --git a/src/freecon.c b/src/freecon.c
deleted file mode 100644
index 5290dfa..0000000
--- a/src/freecon.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <unistd.h>
-#include "selinux_internal.h"
-#include <stdlib.h>
-#include <errno.h>
-
-void freecon(char * con)
-{
- free(con);
-}
-
-hidden_def(freecon)
diff --git a/src/fsetfilecon.c b/src/fsetfilecon.c
deleted file mode 100644
index 17f8875..0000000
--- a/src/fsetfilecon.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/xattr.h>
-#include "selinux_internal.h"
-#include "policy.h"
-
-int fsetfilecon(int fd, const char *context)
-{
- return fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1,
- 0);
-}
-
diff --git a/src/get_initial_context.c b/src/get_initial_context.c
deleted file mode 100644
index 64863dd..0000000
--- a/src/get_initial_context.c
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include "selinux_internal.h"
-#include "policy.h"
-#include <limits.h>
-
-#define SELINUX_INITCON_DIR "/initial_contexts/"
-
-int security_get_initial_context(const char * name, char ** con)
-{
- char path[PATH_MAX];
- char *buf;
- size_t size;
- int fd, ret;
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s%s%s",
- selinux_mnt, SELINUX_INITCON_DIR, name);
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return -1;
-
- size = selinux_page_size;
- buf = malloc(size);
- if (!buf) {
- ret = -1;
- goto out;
- }
- memset(buf, 0, size);
- ret = read(fd, buf, size - 1);
- if (ret < 0)
- goto out2;
-
- *con = strdup(buf);
- if (!(*con)) {
- ret = -1;
- goto out2;
- }
- ret = 0;
- out2:
- free(buf);
- out:
- close(fd);
- return ret;
-}
-
diff --git a/src/getenforce.c b/src/getenforce.c
deleted file mode 100644
index 4fb516a..0000000
--- a/src/getenforce.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include "selinux_internal.h"
-#include "policy.h"
-#include <stdio.h>
-#include <limits.h>
-
-int security_getenforce(void)
-{
- int fd, ret, enforce = 0;
- char path[PATH_MAX];
- char buf[20];
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s/enforce", selinux_mnt);
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return -1;
-
- memset(buf, 0, sizeof buf);
- ret = read(fd, buf, sizeof buf - 1);
- close(fd);
- if (ret < 0)
- return -1;
-
- if (sscanf(buf, "%d", &enforce) != 1)
- return -1;
-
- return enforce;
-}
-
-hidden_def(security_getenforce)
diff --git a/src/getfilecon.c b/src/getfilecon.c
deleted file mode 100644
index 02037de..0000000
--- a/src/getfilecon.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include "selinux_internal.h"
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/xattr.h>
-#include "policy.h"
-
-int getfilecon(const char *path, char ** context)
-{
- char *buf;
- ssize_t size;
- ssize_t ret;
-
- size = INITCONTEXTLEN + 1;
- buf = malloc(size);
- if (!buf)
- return -1;
- memset(buf, 0, size);
-
- ret = getxattr(path, XATTR_NAME_SELINUX, buf, size - 1);
- if (ret < 0 && errno == ERANGE) {
- char *newbuf;
-
- size = getxattr(path, XATTR_NAME_SELINUX, NULL, 0);
- if (size < 0)
- goto out;
-
- size++;
- newbuf = realloc(buf, size);
- if (!newbuf)
- goto out;
-
- buf = newbuf;
- memset(buf, 0, size);
- ret = getxattr(path, XATTR_NAME_SELINUX, buf, size - 1);
- }
- out:
- if (ret == 0) {
- /* Re-map empty attribute values to errors. */
- errno = EOPNOTSUPP;
- ret = -1;
- }
- if (ret < 0)
- free(buf);
- else
- *context = buf;
- return ret;
-}
diff --git a/src/getpeercon.c b/src/getpeercon.c
deleted file mode 100644
index 3bd29dc..0000000
--- a/src/getpeercon.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include "selinux_internal.h"
-#include "policy.h"
-
-#ifndef SO_PEERSEC
-#define SO_PEERSEC 31
-#endif
-
-int getpeercon(int fd, char ** context)
-{
- char *buf;
- socklen_t size;
- ssize_t ret;
-
- size = INITCONTEXTLEN + 1;
- buf = malloc(size);
- if (!buf)
- return -1;
- memset(buf, 0, size);
-
- ret = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &size);
- if (ret < 0 && errno == ERANGE) {
- char *newbuf;
-
- newbuf = realloc(buf, size);
- if (!newbuf)
- goto out;
-
- buf = newbuf;
- memset(buf, 0, size);
- ret = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &size);
- }
- out:
- if (ret < 0)
- free(buf);
- else
- *context = buf;
- return ret;
-}
-
diff --git a/src/init.c b/src/init.c
deleted file mode 100644
index 65bc01b..0000000
--- a/src/init.c
+++ /dev/null
@@ -1,123 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <dlfcn.h>
-
-#ifdef DARWIN
-#include <sys/param.h>
-#include <sys/mount.h>
-#else
-#include <sys/vfs.h>
-#endif
-
-#include <stdint.h>
-#include <limits.h>
-
-#include "dso.h"
-#include "policy.h"
-#include "selinux_internal.h"
-
-char *selinux_mnt = NULL;
-int selinux_page_size = 0;
-
-static void init_selinuxmnt(void)
-{
- char buf[BUFSIZ], *p;
- FILE *fp=NULL;
- struct statfs sfbuf;
- int rc;
- char *bufp;
- int exists = 0;
-
- if (selinux_mnt)
- return;
-
- /* We check to see if the preferred mount point for selinux file
- * system has a selinuxfs. */
- do {
- rc = statfs(SELINUXMNT, &sfbuf);
- } while (rc < 0 && errno == EINTR);
- if (rc == 0) {
- if ((uint32_t)sfbuf.f_type == (uint32_t)SELINUX_MAGIC) {
- selinux_mnt = strdup(SELINUXMNT);
- return;
- }
- }
-
- /* Drop back to detecting it the long way. */
- fp = fopen("/proc/filesystems", "r");
- if (!fp)
- return;
-
- while ((bufp = fgets(buf, sizeof buf - 1, fp)) != NULL) {
- if (strstr(buf, "selinuxfs")) {
- exists = 1;
- break;
- }
- }
-
- if (!exists)
- goto out;
-
- fclose(fp);
-
- /* At this point, the usual spot doesn't have an selinuxfs so
- * we look around for it */
- fp = fopen("/proc/mounts", "r");
- if (!fp)
- goto out;
-
- while ((bufp = fgets(buf, sizeof buf - 1, fp)) != NULL) {
- char *tmp;
- p = strchr(buf, ' ');
- if (!p)
- goto out;
- p++;
- tmp = strchr(p, ' ');
- if (!tmp)
- goto out;
- if (!strncmp(tmp + 1, "selinuxfs ", 10)) {
- *tmp = '\0';
- break;
- }
- }
-
- /* If we found something, dup it */
- if (bufp)
- selinux_mnt = strdup(p);
-
- out:
- if (fp)
- fclose(fp);
- return;
-}
-
-void fini_selinuxmnt(void)
-{
- free(selinux_mnt);
- selinux_mnt = NULL;
-}
-
-void set_selinuxmnt(const char *mnt)
-{
- selinux_mnt = strdup(mnt);
-}
-
-hidden_def(set_selinuxmnt)
-
-static void init_lib(void) __attribute__ ((constructor));
-static void init_lib(void)
-{
- selinux_page_size = sysconf(_SC_PAGE_SIZE);
- init_selinuxmnt();
-}
-
-static void fini_lib(void) __attribute__ ((destructor));
-static void fini_lib(void)
-{
- fini_selinuxmnt();
-}
diff --git a/src/label.c b/src/label.c
deleted file mode 100644
index 6a67b65..0000000
--- a/src/label.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Generalized labeling frontend for userspace object managers.
- *
- * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
- */
-
-#include <sys/types.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <selinux/selinux.h>
-#include "callbacks.h"
-#include "label_internal.h"
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-typedef int (*selabel_initfunc)(struct selabel_handle *rec,
- const struct selinux_opt *opts,
- unsigned nopts);
-
-static selabel_initfunc initfuncs[] = {
- &selabel_file_init,
- NULL,
- NULL,
- NULL,
- &selabel_property_init,
- &selabel_service_init,
-};
-
-/*
- * Validation functions
- */
-
-static inline int selabel_is_validate_set(const struct selinux_opt *opts,
- unsigned n)
-{
- while (n--)
- if (opts[n].type == SELABEL_OPT_VALIDATE)
- return !!opts[n].value;
-
- return 0;
-}
-
-int selabel_validate(struct selabel_handle *rec,
- struct selabel_lookup_rec *contexts)
-{
- int rc = 0;
-
- if (!rec->validating || contexts->validated)
- goto out;
-
- rc = selinux_validate(&contexts->ctx_raw);
- if (rc < 0)
- goto out;
-
- contexts->validated = 1;
-out:
- return rc;
-}
-
-/*
- * Public API
- */
-
-struct selabel_handle *selabel_open(unsigned int backend,
- const struct selinux_opt *opts,
- unsigned nopts)
-{
- struct selabel_handle *rec = NULL;
-
- if (backend >= ARRAY_SIZE(initfuncs)) {
- errno = EINVAL;
- goto out;
- }
-
- if (initfuncs[backend] == NULL)
- goto out;
-
- rec = (struct selabel_handle *)malloc(sizeof(*rec));
- if (!rec)
- goto out;
-
- memset(rec, 0, sizeof(*rec));
- rec->backend = backend;
- rec->validating = selabel_is_validate_set(opts, nopts);
-
- if ((*initfuncs[backend])(rec, opts, nopts)) {
- free(rec->spec_file);
- free(rec);
- rec = NULL;
- }
-
-out:
- return rec;
-}
-
-static struct selabel_lookup_rec *
-selabel_lookup_common(struct selabel_handle *rec,
- const char *key, int type)
-{
- struct selabel_lookup_rec *lr;
- lr = rec->func_lookup(rec, key, type);
- if (!lr)
- return NULL;
-
- return lr;
-}
-
-int selabel_lookup(struct selabel_handle *rec, char **con,
- const char *key, int type)
-{
- struct selabel_lookup_rec *lr;
-
- lr = selabel_lookup_common(rec, key, type);
- if (!lr)
- return -1;
-
- *con = strdup(lr->ctx_raw);
- return *con ? 0 : -1;
-}
-
-bool selabel_partial_match(struct selabel_handle *rec, const char *key)
-{
- if (!rec->func_partial_match) {
- /*
- * If the label backend does not support partial matching,
- * then assume a match is possible.
- */
- return true;
- }
- return rec->func_partial_match(rec, key);
-}
-
-int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
- const char *key, const char **aliases, int type)
-{
- struct selabel_lookup_rec *lr;
-
- if (!rec->func_lookup_best_match) {
- errno = ENOTSUP;
- return -1;
- }
-
- lr = rec->func_lookup_best_match(rec, key, aliases, type);
- if (!lr)
- return -1;
-
- *con = strdup(lr->ctx_raw);
- return *con ? 0 : -1;
-}
-
-enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1,
- struct selabel_handle *h2)
-{
- if (!h1->func_cmp || h1->func_cmp != h2->func_cmp)
- return SELABEL_INCOMPARABLE;
-
- return h1->func_cmp(h1, h2);
-}
-
-void selabel_close(struct selabel_handle *rec)
-{
- rec->func_close(rec);
- free(rec->spec_file);
- free(rec);
-}
-
-void selabel_stats(struct selabel_handle *rec)
-{
- rec->func_stats(rec);
-}
diff --git a/src/label_android_property.c b/src/label_android_property.c
deleted file mode 100644
index b0a807c..0000000
--- a/src/label_android_property.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Property Service contexts backend for labeling Android
- * property keys
- */
-
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "callbacks.h"
-#include "label_internal.h"
-
-/* A property security context specification. */
-typedef struct spec {
- struct selabel_lookup_rec lr; /* holds contexts for lookup result */
- char *property_key; /* property key string */
-} spec_t;
-
-/* Our stored configuration */
-struct saved_data {
- /*
- * The array of specifications is sorted for longest
- * prefix match
- */
- spec_t *spec_arr;
- unsigned int nspec; /* total number of specifications */
-};
-
-static int cmp(const void *A, const void *B)
-{
- const struct spec *sp1 = A, *sp2 = B;
-
- if (strncmp(sp1->property_key, "*", 1) == 0)
- return 1;
- if (strncmp(sp2->property_key, "*", 1) == 0)
- return -1;
-
- size_t L1 = strlen(sp1->property_key);
- size_t L2 = strlen(sp2->property_key);
-
- return (L1 < L2) - (L1 > L2);
-}
-
-/*
- * Warn about duplicate specifications.
- */
-static int nodups_specs(struct saved_data *data, const char *path)
-{
- int rc = 0;
- unsigned int ii, jj;
- struct spec *curr_spec, *spec_arr = data->spec_arr;
-
- for (ii = 0; ii < data->nspec; ii++) {
- curr_spec = &spec_arr[ii];
- for (jj = ii + 1; jj < data->nspec; jj++) {
- if (!strcmp(spec_arr[jj].property_key,
- curr_spec->property_key)) {
- rc = -1;
- errno = EINVAL;
- if (strcmp(spec_arr[jj].lr.ctx_raw,
- curr_spec->lr.ctx_raw)) {
- selinux_log
- (SELINUX_ERROR,
- "%s: Multiple different specifications for %s (%s and %s).\n",
- path, curr_spec->property_key,
- spec_arr[jj].lr.ctx_raw,
- curr_spec->lr.ctx_raw);
- } else {
- selinux_log
- (SELINUX_ERROR,
- "%s: Multiple same specifications for %s.\n",
- path, curr_spec->property_key);
- }
- }
- }
- }
- return rc;
-}
-
-static int process_line(struct selabel_handle *rec,
- const char *path, char *line_buf,
- int pass, unsigned lineno)
-{
- int items;
- char *prop = NULL, *context = NULL;
- struct saved_data *data = (struct saved_data *)rec->data;
- spec_t *spec_arr = data->spec_arr;
- unsigned int nspec = data->nspec;
- const char *errbuf = NULL;
-
- items = read_spec_entries(line_buf, &errbuf, 2, &prop, &context);
- if (items < 0) {
- items = errno;
- selinux_log(SELINUX_ERROR,
- "%s: line %u error due to: %s\n", path,
- lineno, errbuf ?: strerror(errno));
- errno = items;
- return -1;
- }
-
- if (items == 0)
- return items;
-
- if (items != 2) {
- selinux_log(SELINUX_ERROR,
- "%s: line %u is missing fields\n", path,
- lineno);
- free(prop);
- errno = EINVAL;
- return -1;
- }
-
- if (pass == 0) {
- free(prop);
- free(context);
- } else if (pass == 1) {
- /* On the second pass, process and store the specification in spec. */
- spec_arr[nspec].property_key = prop;
- spec_arr[nspec].lr.ctx_raw = context;
-
- if (rec->validating) {
- if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) {
- selinux_log(SELINUX_ERROR,
- "%s: line %u has invalid context %s\n",
- path, lineno, spec_arr[nspec].lr.ctx_raw);
- errno = EINVAL;
- return -1;
- }
- }
- }
-
- data->nspec = ++nspec;
- return 0;
-}
-
-static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
- unsigned n)
-{
- struct saved_data *data = (struct saved_data *)rec->data;
- const char *path = NULL;
- FILE *fp;
- char line_buf[BUFSIZ];
- unsigned int lineno, maxnspec, pass;
- int status = -1;
- struct stat sb;
-
- /* Process arguments */
- while (n--)
- switch (opts[n].type) {
- case SELABEL_OPT_PATH:
- path = opts[n].value;
- break;
- }
-
- if (!path)
- return -1;
-
- /* Open the specification file. */
- if ((fp = fopen(path, "r")) == NULL)
- return -1;
-
- if (fstat(fileno(fp), &sb) < 0)
- goto finish;
- errno = EINVAL;
- if (!S_ISREG(sb.st_mode))
- goto finish;
-
- /*
- * Two passes of the specification file. First is to get the size.
- * After the first pass, the spec array is malloced to the appropriate
- * size. Second pass is to populate the spec array and check for
- * dups.
- */
- maxnspec = UINT_MAX / sizeof(spec_t);
- for (pass = 0; pass < 2; pass++) {
- data->nspec = 0;
- lineno = 0;
-
- while (fgets(line_buf, sizeof(line_buf) - 1, fp)
- && data->nspec < maxnspec) {
- if (process_line(rec, path, line_buf, pass, ++lineno)
- != 0)
- goto finish;
- }
-
- if (pass == 1) {
- status = nodups_specs(data, path);
-
- if (status)
- goto finish;
- }
-
- if (pass == 0) {
- if (data->nspec == 0) {
- status = 0;
- goto finish;
- }
-
- if (NULL == (data->spec_arr =
- malloc(sizeof(spec_t) * data->nspec)))
- goto finish;
-
- memset(data->spec_arr, 0, sizeof(spec_t) * data->nspec);
- maxnspec = data->nspec;
- rewind(fp);
- }
- }
-
- qsort(data->spec_arr, data->nspec, sizeof(struct spec), cmp);
-
- status = 0;
-finish:
- fclose(fp);
- return status;
-}
-
-/*
- * Backend interface routines
- */
-static void closef(struct selabel_handle *rec)
-{
- struct saved_data *data = (struct saved_data *)rec->data;
- struct spec *spec;
- unsigned int i;
-
- for (i = 0; i < data->nspec; i++) {
- spec = &data->spec_arr[i];
- free(spec->property_key);
- free(spec->lr.ctx_raw);
- free(spec->lr.ctx_trans);
- }
-
- if (data->spec_arr)
- free(data->spec_arr);
-
- free(data);
-}
-
-static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
- const char *key,
- int __attribute__((unused)) type)
-{
- struct saved_data *data = (struct saved_data *)rec->data;
- spec_t *spec_arr = data->spec_arr;
- unsigned int i;
- struct selabel_lookup_rec *ret = NULL;
-
- if (!data->nspec) {
- errno = ENOENT;
- goto finish;
- }
-
- for (i = 0; i < data->nspec; i++) {
- if (strncmp(spec_arr[i].property_key, key,
- strlen(spec_arr[i].property_key)) == 0) {
- break;
- }
- if (strncmp(spec_arr[i].property_key, "*", 1) == 0)
- break;
- }
-
- if (i >= data->nspec) {
- /* No matching specification. */
- errno = ENOENT;
- goto finish;
- }
-
- ret = &spec_arr[i].lr;
-
-finish:
- return ret;
-}
-
-static struct selabel_lookup_rec *service_lookup(struct selabel_handle *rec,
- const char *key,
- int __attribute__((unused)) type)
-{
- struct saved_data *data = (struct saved_data *) rec->data;
- spec_t *spec_arr = data->spec_arr;
- unsigned int i;
- struct selabel_lookup_rec *ret = NULL;
-
- if (!data->nspec) {
- errno = ENOENT;
- goto finish;
- }
-
- for (i = 0; i < data->nspec; i++) {
- if (strcmp(spec_arr[i].property_key, key) == 0) {
- break;
- }
- if (strcmp(spec_arr[i].property_key, "*") == 0) break;
- }
-
- if (i >= data->nspec) {
- /* No matching specification. */
- errno = ENOENT;
- goto finish;
- }
-
- ret = &spec_arr[i].lr;
-
-finish:
- return ret;
-}
-
-static void stats(struct selabel_handle __attribute__((unused)) *rec)
-{
- selinux_log(SELINUX_WARNING, "'stats' functionality not implemented.\n");
-}
-
-int selabel_property_init(struct selabel_handle *rec,
- const struct selinux_opt *opts,
- unsigned nopts)
-{
- struct saved_data *data;
-
- data = (struct saved_data *)malloc(sizeof(*data));
- if (!data)
- return -1;
- memset(data, 0, sizeof(*data));
-
- rec->data = data;
- rec->func_close = &closef;
- rec->func_stats = &stats;
- rec->func_lookup = &lookup;
-
- return init(rec, opts, nopts);
-}
-
-int selabel_service_init(struct selabel_handle *rec,
- const struct selinux_opt *opts,
- unsigned nopts)
-{
- struct saved_data *data;
-
- data = (struct saved_data *)calloc(1, sizeof(*data));
- if (!data)
- return -1;
-
- rec->data = data;
- rec->func_close = &closef;
- rec->func_stats = &stats;
- rec->func_lookup = &service_lookup;
-
- return init(rec, opts, nopts);
-}
diff --git a/src/label_file.c b/src/label_file.c
deleted file mode 100644
index d3e67c0..0000000
--- a/src/label_file.c
+++ /dev/null
@@ -1,859 +0,0 @@
-/*
- * File contexts backend for labeling system
- *
- * Author : Eamon Walsh <ewalsh@tycho.nsa.gov>
- * Author : Stephen Smalley <sds@tycho.nsa.gov>
- */
-
-#include <assert.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "callbacks.h"
-#include "label_internal.h"
-#include "label_file.h"
-
-/*
- * Internals, mostly moved over from matchpathcon.c
- */
-
-/* return the length of the text that is the stem of a file name */
-static int get_stem_from_file_name(const char *const buf)
-{
- const char *tmp = strchr(buf + 1, '/');
-
- if (!tmp)
- return 0;
- return tmp - buf;
-}
-
-/* find the stem of a file name, returns the index into stem_arr (or -1 if
- * there is no match - IE for a file in the root directory or a regex that is
- * too complex for us). Makes buf point to the text AFTER the stem. */
-static int find_stem_from_file(struct saved_data *data, const char **buf)
-{
- int i;
- int stem_len = get_stem_from_file_name(*buf);
-
- if (!stem_len)
- return -1;
- for (i = 0; i < data->num_stems; i++) {
- if (stem_len == data->stem_arr[i].len
- && !strncmp(*buf, data->stem_arr[i].buf, stem_len)) {
- *buf += stem_len;
- return i;
- }
- }
- return -1;
-}
-
-/*
- * Warn about duplicate specifications.
- */
-static int nodups_specs(struct saved_data *data, const char *path)
-{
- int rc = 0;
- unsigned int ii, jj;
- struct spec *curr_spec, *spec_arr = data->spec_arr;
-
- for (ii = 0; ii < data->nspec; ii++) {
- curr_spec = &spec_arr[ii];
- for (jj = ii + 1; jj < data->nspec; jj++) {
- if ((!strcmp(spec_arr[jj].regex_str,
- curr_spec->regex_str))
- && (!spec_arr[jj].mode || !curr_spec->mode
- || spec_arr[jj].mode == curr_spec->mode)) {
- rc = -1;
- errno = EINVAL;
- if (strcmp(spec_arr[jj].lr.ctx_raw,
- curr_spec->lr.ctx_raw)) {
- selinux_log
- (SELINUX_ERROR,
- "%s: Multiple different specifications for %s (%s and %s).\n",
- path, curr_spec->regex_str,
- spec_arr[jj].lr.ctx_raw,
- curr_spec->lr.ctx_raw);
- } else {
- selinux_log
- (SELINUX_ERROR,
- "%s: Multiple same specifications for %s.\n",
- path, curr_spec->regex_str);
- }
- }
- }
- }
- return rc;
-}
-
-static int load_mmap(struct selabel_handle *rec, const char *path,
- struct stat *sb, bool isbinary)
-{
- struct saved_data *data = (struct saved_data *)rec->data;
- char mmap_path[PATH_MAX + 1];
- int mmapfd;
- int rc;
- struct stat mmap_stat;
- char *addr, *str_buf;
- size_t len;
- int *stem_map;
- struct mmap_area *mmap_area;
- uint32_t i, magic, version;
- uint32_t entry_len, stem_map_len, regex_array_len;
-
- if (isbinary) {
- len = strlen(path);
- if (len >= sizeof(mmap_path))
- return -1;
- strcpy(mmap_path, path);
- } else {
- rc = snprintf(mmap_path, sizeof(mmap_path), "%s.bin", path);
- if (rc >= (int)sizeof(mmap_path))
- return -1;
- }
-
- mmapfd = open(mmap_path, O_RDONLY | O_CLOEXEC);
- if (mmapfd < 0)
- return -1;
-
- rc = fstat(mmapfd, &mmap_stat);
- if (rc < 0) {
- close(mmapfd);
- return -1;
- }
-
- /* if mmap is old, ignore it */
- if (mmap_stat.st_mtime < sb->st_mtime) {
- close(mmapfd);
- return -1;
- }
-
- /* ok, read it in... */
- len = mmap_stat.st_size;
- len += (sysconf(_SC_PAGE_SIZE) - 1);
- len &= ~(sysconf(_SC_PAGE_SIZE) - 1);
-
- mmap_area = malloc(sizeof(*mmap_area));
- if (!mmap_area) {
- close(mmapfd);
- return -1;
- }
-
- addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, mmapfd, 0);
- close(mmapfd);
- if (addr == MAP_FAILED) {
- free(mmap_area);
- perror("mmap");
- return -1;
- }
-
- /* save where we mmap'd the file to cleanup on close() */
- mmap_area->addr = mmap_area->next_addr = addr;
- mmap_area->len = mmap_area->next_len = len;
- mmap_area->next = data->mmap_areas;
- data->mmap_areas = mmap_area;
-
- /* check if this looks like an fcontext file */
- rc = next_entry(&magic, mmap_area, sizeof(uint32_t));
- if (rc < 0 || magic != SELINUX_MAGIC_COMPILED_FCONTEXT)
- return -1;
-
- /* check if this version is higher than we understand */
- rc = next_entry(&version, mmap_area, sizeof(uint32_t));
- if (rc < 0 || version > SELINUX_COMPILED_FCONTEXT_MAX_VERS)
- return -1;
-
- if (version >= SELINUX_COMPILED_FCONTEXT_PCRE_VERS) {
- if (!regex_version()) {
- return -1;
- }
- len = strlen(regex_version());
-
- rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
- if (rc < 0)
- return -1;
-
- /* Check version lengths */
- if (len != entry_len)
- return -1;
-
- /* Check if pcre version 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';
- if ((strcmp(str_buf, regex_version()) != 0)) {
- free(str_buf);
- return -1;
- }
- free(str_buf);
- }
-
- /* allocate the stems_data array */
- rc = next_entry(&stem_map_len, mmap_area, sizeof(uint32_t));
- if (rc < 0 || !stem_map_len)
- return -1;
-
- /*
- * map indexed by the stem # in the mmap file and contains the stem
- * number in the data stem_arr
- */
- stem_map = calloc(stem_map_len, sizeof(*stem_map));
- if (!stem_map)
- return -1;
-
- for (i = 0; i < stem_map_len; i++) {
- char *buf;
- uint32_t stem_len;
- int newid;
-
- /* the length does not inlude the nul */
- rc = next_entry(&stem_len, mmap_area, sizeof(uint32_t));
- if (rc < 0 || !stem_len) {
- rc = -1;
- goto err;
- }
-
- /* Check for stem_len wrap around. */
- if (stem_len < UINT32_MAX) {
- buf = (char *)mmap_area->next_addr;
- /* Check if over-run before null check. */
- rc = next_entry(NULL, mmap_area, (stem_len + 1));
- if (rc < 0)
- goto err;
-
- if (buf[stem_len] != '\0') {
- rc = -1;
- goto err;
- }
- } else {
- rc = -1;
- goto err;
- }
-
- /* store the mapping between old and new */
- newid = find_stem(data, buf, stem_len);
- if (newid < 0) {
- newid = store_stem(data, buf, stem_len);
- if (newid < 0) {
- rc = newid;
- goto err;
- }
- data->stem_arr[newid].from_mmap = 1;
- }
- stem_map[i] = newid;
- }
-
- /* allocate the regex array */
- rc = next_entry(&regex_array_len, mmap_area, sizeof(uint32_t));
- if (rc < 0 || !regex_array_len) {
- rc = -1;
- goto err;
- }
-
- for (i = 0; i < regex_array_len; i++) {
- struct spec *spec;
- int32_t stem_id, meta_chars;
- uint32_t mode = 0, prefix_len = 0;
-
- rc = grow_specs(data);
- if (rc < 0)
- goto err;
-
- spec = &data->spec_arr[data->nspec];
- spec->from_mmap = 1;
- spec->regcomp = 1;
-
- /* Process context */
- rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
- if (rc < 0 || !entry_len) {
- rc = -1;
- goto err;
- }
-
- str_buf = malloc(entry_len);
- if (!str_buf) {
- rc = -1;
- goto err;
- }
- rc = next_entry(str_buf, mmap_area, entry_len);
- if (rc < 0)
- goto err;
-
- if (str_buf[entry_len - 1] != '\0') {
- free(str_buf);
- rc = -1;
- goto err;
- }
- spec->lr.ctx_raw = str_buf;
-
- if (strcmp(spec->lr.ctx_raw, "<<none>>") && rec->validating) {
- if (selabel_validate(rec, &spec->lr) < 0) {
- selinux_log(SELINUX_ERROR,
- "%s: context %s is invalid\n", mmap_path, spec->lr.ctx_raw);
- goto err;
- }
- }
-
- /* Process regex string */
- rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
- if (rc < 0 || !entry_len) {
- rc = -1;
- goto err;
- }
-
- spec->regex_str = (char *)mmap_area->next_addr;
- rc = next_entry(NULL, mmap_area, entry_len);
- if (rc < 0)
- goto err;
-
- if (spec->regex_str[entry_len - 1] != '\0') {
- rc = -1;
- goto err;
- }
-
- /* Process mode */
- if (version >= SELINUX_COMPILED_FCONTEXT_MODE)
- rc = next_entry(&mode, mmap_area, sizeof(uint32_t));
- else
- rc = next_entry(&mode, mmap_area, sizeof(mode_t));
- if (rc < 0)
- goto err;
-
- spec->mode = mode;
-
- /* map the stem id from the mmap file to the data->stem_arr */
- rc = next_entry(&stem_id, mmap_area, sizeof(int32_t));
- if (rc < 0)
- goto err;
-
- if (stem_id < 0 || stem_id >= (int32_t)stem_map_len)
- spec->stem_id = -1;
- else
- spec->stem_id = stem_map[stem_id];
-
- /* retrieve the hasMetaChars bit */
- rc = next_entry(&meta_chars, mmap_area, sizeof(uint32_t));
- if (rc < 0)
- goto err;
-
- spec->hasMetaChars = meta_chars;
- /* and prefix length for use by selabel_lookup_best_match */
- if (version >= SELINUX_COMPILED_FCONTEXT_PREFIX_LEN) {
- rc = next_entry(&prefix_len, mmap_area,
- sizeof(uint32_t));
- if (rc < 0)
- goto err;
-
- spec->prefix_len = prefix_len;
- }
-
- rc = regex_load_mmap(mmap_area, &spec->regex);
- if (rc < 0)
- goto err;
-#ifndef NO_PERSISTENTLY_STORED_PATTERNS
- spec->regcomp = 1;
-#else
- spec->regcomp = 0;
-#endif
-
- data->nspec++;
- }
-
- /* win */
- rc = 0;
-err:
- free(stem_map);
-
- return rc;
-}
-
-static int process_file(const char *path, const char *suffix,
- struct selabel_handle *rec, const char *prefix)
-{
- FILE *fp;
- struct stat sb;
- unsigned int lineno;
- size_t line_len = 0;
- char *line_buf = NULL;
- int rc;
- char stack_path[PATH_MAX + 1];
- bool isbinary = false;
- uint32_t magic;
-
- /* append the path suffix if we have one */
- if (suffix) {
- rc = snprintf(stack_path, sizeof(stack_path),
- "%s.%s", path, suffix);
- if (rc >= (int)sizeof(stack_path)) {
- errno = ENAMETOOLONG;
- return -1;
- }
- path = stack_path;
- }
-
- /* Open the specification file. */
- fp = fopen(path, "r");
- if (fp) {
- if (fstat(fileno(fp), &sb) < 0)
- return -1;
- if (!S_ISREG(sb.st_mode)) {
- errno = EINVAL;
- return -1;
- }
-
- if (fread(&magic, sizeof magic, 1, fp) != 1) {
- errno = EINVAL;
- fclose(fp);
- return -1;
- }
-
- if (magic == SELINUX_MAGIC_COMPILED_FCONTEXT) {
- /* file_contexts.bin format */
- fclose(fp);
- fp = NULL;
- isbinary = true;
- } else {
- rewind(fp);
- }
- } else {
- /*
- * Text file does not exist, so clear the timestamp
- * so that we will always pass the timestamp comparison
- * with the bin file in load_mmap().
- */
- sb.st_mtime = 0;
- }
-
- rc = load_mmap(rec, path, &sb, isbinary);
- if (rc == 0)
- goto out;
-
- if (!fp)
- return -1; /* no text or bin file */
-
- /*
- * Then do detailed validation of the input and fill the spec array
- */
- lineno = 0;
- rc = 0;
- while (getline(&line_buf, &line_len, fp) > 0) {
- rc = process_line(rec, path, prefix, line_buf, ++lineno);
- if (rc)
- goto out;
- }
-
-out:
- free(line_buf);
- if (fp)
- fclose(fp);
- return rc;
-}
-
-static void closef(struct selabel_handle *rec);
-
-static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
- unsigned n)
-{
- struct saved_data *data = (struct saved_data *)rec->data;
- const char *path = NULL;
- const char *prefix = NULL;
- int status = -1, baseonly = 0;
-
- /* Process arguments */
- while (n--)
- switch(opts[n].type) {
- case SELABEL_OPT_PATH:
- path = opts[n].value;
- break;
- case SELABEL_OPT_SUBSET:
- prefix = opts[n].value;
- break;
- case SELABEL_OPT_BASEONLY:
- baseonly = !!opts[n].value;
- break;
- }
-
- rec->spec_file = strdup(path);
-
- /*
- * The do detailed validation of the input and fill the spec array
- */
- status = process_file(path, NULL, rec, prefix);
- if (status)
- goto finish;
-
- if (rec->validating) {
- status = nodups_specs(data, path);
- if (status)
- goto finish;
- }
-
- if (!baseonly) {
- status = process_file(path, "homedirs", rec, prefix);
- if (status && errno != ENOENT)
- goto finish;
-
- status = process_file(path, "local", rec, prefix);
- if (status && errno != ENOENT)
- goto finish;
- }
-
- status = sort_specs(data);
-
-finish:
- if (status)
- closef(rec);
-
- return status;
-}
-
-/*
- * Backend interface routines
- */
-static void closef(struct selabel_handle *rec)
-{
- struct saved_data *data = (struct saved_data *)rec->data;
- struct mmap_area *area, *last_area;
- struct spec *spec;
- struct stem *stem;
- unsigned int i;
-
- for (i = 0; i < data->nspec; i++) {
- spec = &data->spec_arr[i];
- free(spec->lr.ctx_trans);
- free(spec->lr.ctx_raw);
- if (spec->from_mmap)
- continue;
- free(spec->regex_str);
- free(spec->type_str);
- regex_data_free(spec->regex);
- }
-
- for (i = 0; i < (unsigned int)data->num_stems; i++) {
- stem = &data->stem_arr[i];
- if (stem->from_mmap)
- continue;
- free(stem->buf);
- }
-
- if (data->spec_arr)
- free(data->spec_arr);
- if (data->stem_arr)
- free(data->stem_arr);
-
- area = data->mmap_areas;
- while (area) {
- munmap(area->addr, area->len);
- last_area = area;
- area = area->next;
- free(last_area);
- }
- free(data);
-}
-
-static struct spec *lookup_common(struct selabel_handle *rec,
- const char *key,
- int type,
- bool partial)
-{
- struct saved_data *data = (struct saved_data *)rec->data;
- struct spec *spec_arr = data->spec_arr;
- int i, rc, file_stem;
- mode_t mode = (mode_t)type;
- const char *buf;
- struct spec *ret = NULL;
- char *clean_key = NULL;
- const char *prev_slash, *next_slash;
- unsigned int sofar = 0;
- struct regex_error_data regex_error_data;
-
- if (!data->nspec) {
- errno = ENOENT;
- goto finish;
- }
-
- /* Remove duplicate slashes */
- if ((next_slash = strstr(key, "//"))) {
- clean_key = (char *) malloc(strlen(key) + 1);
- if (!clean_key)
- goto finish;
- prev_slash = key;
- while (next_slash) {
- memcpy(clean_key + sofar, prev_slash, next_slash - prev_slash);
- sofar += next_slash - prev_slash;
- prev_slash = next_slash + 1;
- next_slash = strstr(prev_slash, "//");
- }
- strcpy(clean_key + sofar, prev_slash);
- key = clean_key;
- }
-
- buf = key;
- file_stem = find_stem_from_file(data, &buf);
- mode &= S_IFMT;
-
- /*
- * Check for matching specifications in reverse order, so that
- * the last matching specification is used.
- */
- for (i = data->nspec - 1; i >= 0; i--) {
- struct spec *spec = &spec_arr[i];
- /* if the spec in question matches no stem or has the same
- * stem as the file AND if the spec in question has no mode
- * specified or if the mode matches the file mode then we do
- * a regex check */
- if ((spec->stem_id == -1 || spec->stem_id == file_stem) &&
- (!mode || !spec->mode || mode == spec->mode)) {
- if (compile_regex(data, spec, &regex_error_data) < 0)
- goto finish;
- if (spec->stem_id == -1)
- rc = regex_match(spec->regex, key, partial);
- else
- rc = regex_match(spec->regex, buf, partial);
- if (rc == REGEX_MATCH) {
- spec->matches++;
- break;
- } else if (partial && rc == REGEX_MATCH_PARTIAL)
- break;
-
- if (rc == REGEX_NO_MATCH)
- continue;
-
- errno = ENOENT;
- /* else it's an error */
- goto finish;
- }
- }
-
- if (i < 0 || strcmp(spec_arr[i].lr.ctx_raw, "<<none>>") == 0) {
- /* No matching specification. */
- errno = ENOENT;
- goto finish;
- }
-
- errno = 0;
- ret = &spec_arr[i];
-
-finish:
- free(clean_key);
- return ret;
-}
-
-static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
- const char *key, int type)
-{
- struct spec *spec;
-
- spec = lookup_common(rec, key, type, false);
- if (spec)
- return &spec->lr;
- return NULL;
-}
-
-static bool partial_match(struct selabel_handle *rec, const char *key)
-{
- return lookup_common(rec, key, 0, true) ? true : false;
-}
-
-static struct selabel_lookup_rec *lookup_best_match(struct selabel_handle *rec,
- const char *key,
- const char **aliases,
- int type)
-{
- size_t n, i;
- int best = -1;
- struct spec **specs;
- size_t prefix_len = 0;
- struct selabel_lookup_rec *lr = NULL;
-
- if (!aliases || !aliases[0])
- return lookup(rec, key, type);
-
- for (n = 0; aliases[n]; n++)
- ;
-
- specs = calloc(n+1, sizeof(struct spec *));
- if (!specs)
- return NULL;
- specs[0] = lookup_common(rec, key, type, false);
- if (specs[0]) {
- if (!specs[0]->hasMetaChars) {
- /* exact match on key */
- lr = &specs[0]->lr;
- goto out;
- }
- best = 0;
- prefix_len = specs[0]->prefix_len;
- }
- for (i = 1; i <= n; i++) {
- specs[i] = lookup_common(rec, aliases[i-1], type, false);
- if (specs[i]) {
- if (!specs[i]->hasMetaChars) {
- /* exact match on alias */
- lr = &specs[i]->lr;
- goto out;
- }
- if (specs[i]->prefix_len > prefix_len) {
- best = i;
- prefix_len = specs[i]->prefix_len;
- }
- }
- }
-
- if (best >= 0) {
- /* longest fixed prefix match on key or alias */
- lr = &specs[best]->lr;
- } else {
- errno = ENOENT;
- }
-
-out:
- free(specs);
- return lr;
-}
-
-static enum selabel_cmp_result incomp(struct spec *spec1, struct spec *spec2, const char *reason, int i, int j)
-{
- selinux_log(SELINUX_INFO,
- "selabel_cmp: mismatched %s on entry %d: (%s, %x, %s) vs entry %d: (%s, %x, %s)\n",
- reason,
- i, spec1->regex_str, spec1->mode, spec1->lr.ctx_raw,
- j, spec2->regex_str, spec2->mode, spec2->lr.ctx_raw);
- return SELABEL_INCOMPARABLE;
-}
-
-static enum selabel_cmp_result cmp(struct selabel_handle *h1,
- struct selabel_handle *h2)
-{
- struct saved_data *data1 = (struct saved_data *)h1->data;
- struct saved_data *data2 = (struct saved_data *)h2->data;
- unsigned int i, nspec1 = data1->nspec, j, nspec2 = data2->nspec;
- struct spec *spec_arr1 = data1->spec_arr, *spec_arr2 = data2->spec_arr;
- struct stem *stem_arr1 = data1->stem_arr, *stem_arr2 = data2->stem_arr;
- bool skipped1 = false, skipped2 = false;
-
- i = 0;
- j = 0;
- while (i < nspec1 && j < nspec2) {
- struct spec *spec1 = &spec_arr1[i];
- struct spec *spec2 = &spec_arr2[j];
-
- /*
- * Because sort_specs() moves exact pathnames to the
- * end, we might need to skip over additional regex
- * entries that only exist in one of the configurations.
- */
- if (!spec1->hasMetaChars && spec2->hasMetaChars) {
- j++;
- skipped2 = true;
- continue;
- }
-
- if (spec1->hasMetaChars && !spec2->hasMetaChars) {
- i++;
- skipped1 = true;
- continue;
- }
-
- if (spec1->regcomp && spec2->regcomp) {
- if (regex_cmp(spec1->regex, spec2->regex) == SELABEL_INCOMPARABLE){
- return incomp(spec1, spec2, "regex", i, j);
- }
- } else {
- if (strcmp(spec1->regex_str, spec2->regex_str))
- return incomp(spec1, spec2, "regex_str", i, j);
- }
-
- if (spec1->mode != spec2->mode)
- return incomp(spec1, spec2, "mode", i, j);
-
- if (spec1->stem_id == -1 && spec2->stem_id != -1)
- return incomp(spec1, spec2, "stem_id", i, j);
- if (spec2->stem_id == -1 && spec1->stem_id != -1)
- return incomp(spec1, spec2, "stem_id", i, j);
- if (spec1->stem_id != -1 && spec2->stem_id != -1) {
- struct stem *stem1 = &stem_arr1[spec1->stem_id];
- struct stem *stem2 = &stem_arr2[spec2->stem_id];
- if (stem1->len != stem2->len ||
- strncmp(stem1->buf, stem2->buf, stem1->len))
- return incomp(spec1, spec2, "stem", i, j);
- }
-
- if (strcmp(spec1->lr.ctx_raw, spec2->lr.ctx_raw))
- return incomp(spec1, spec2, "ctx_raw", i, j);
-
- i++;
- j++;
- }
-
- if ((skipped1 || i < nspec1) && !skipped2)
- return SELABEL_SUPERSET;
- if ((skipped2 || j < nspec2) && !skipped1)
- return SELABEL_SUBSET;
- if (skipped1 && skipped2)
- return SELABEL_INCOMPARABLE;
- return SELABEL_EQUAL;
-}
-
-
-static void stats(struct selabel_handle *rec)
-{
- struct saved_data *data = (struct saved_data *)rec->data;
- unsigned int i, nspec = data->nspec;
- struct spec *spec_arr = data->spec_arr;
-
- for (i = 0; i < nspec; i++) {
- if (spec_arr[i].matches == 0) {
- if (spec_arr[i].type_str) {
- selinux_log(SELINUX_WARNING,
- "Warning! No matches for (%s, %s, %s)\n",
- spec_arr[i].regex_str,
- spec_arr[i].type_str,
- spec_arr[i].lr.ctx_raw);
- } else {
- selinux_log(SELINUX_WARNING,
- "Warning! No matches for (%s, %s)\n",
- spec_arr[i].regex_str,
- spec_arr[i].lr.ctx_raw);
- }
- }
- }
-}
-
-int selabel_file_init(struct selabel_handle *rec, const struct selinux_opt *opts,
- unsigned nopts)
-{
- struct saved_data *data;
-
- data = (struct saved_data *)malloc(sizeof(*data));
- if (!data)
- return -1;
- memset(data, 0, sizeof(*data));
-
- rec->data = data;
- rec->func_close = &closef;
- rec->func_stats = &stats;
- rec->func_lookup = &lookup;
- rec->func_partial_match = &partial_match;
- rec->func_lookup_best_match = &lookup_best_match;
- rec->func_cmp = &cmp;
-
- return init(rec, opts, nopts);
-}
diff --git a/src/label_file.h b/src/label_file.h
deleted file mode 100644
index d0ff254..0000000
--- a/src/label_file.h
+++ /dev/null
@@ -1,474 +0,0 @@
-#ifndef _SELABEL_FILE_H_
-#define _SELABEL_FILE_H_
-
-#include <errno.h>
-#include <string.h>
-
-#include <sys/stat.h>
-
-/*
- * Android: regex.h/c was introduced to hold all dependencies on the regular
- * expression back-end when we started supporting PCRE2. regex.h defines a
- * minimal interface required by libselinux, so that the remaining code
- * can be agnostic about the underlying implementation.
- */
-#include "regex.h"
-
-#include "callbacks.h"
-#include "label_internal.h"
-
-#define SELINUX_MAGIC_COMPILED_FCONTEXT 0xf97cff8a
-
-/* Version specific changes */
-#define SELINUX_COMPILED_FCONTEXT_NOPCRE_VERS 1
-#define SELINUX_COMPILED_FCONTEXT_PCRE_VERS 2
-#define SELINUX_COMPILED_FCONTEXT_MODE 3
-#define SELINUX_COMPILED_FCONTEXT_PREFIX_LEN 4
-
-#define SELINUX_COMPILED_FCONTEXT_MAX_VERS SELINUX_COMPILED_FCONTEXT_PREFIX_LEN
-
-/* A file security context specification. */
-struct spec {
- struct selabel_lookup_rec lr; /* holds contexts for lookup result */
- char *regex_str; /* regular expession string for diagnostics */
- char *type_str; /* type string for diagnostic messages */
- struct regex_data * regex; /* backend dependent regular expression data */
- mode_t mode; /* mode format value */
- int matches; /* number of matching pathnames */
- int stem_id; /* indicates which stem-compression item */
- char hasMetaChars; /* regular expression has meta-chars */
- char regcomp; /* regex_str has been compiled to regex */
- char from_mmap; /* this spec is from an mmap of the data */
- size_t prefix_len; /* length of fixed path prefix */
-};
-
-/* A regular expression stem */
-struct stem {
- char *buf;
- int len;
- char from_mmap;
-};
-
-/* Where we map the file in during selabel_open() */
-struct mmap_area {
- void *addr; /* Start addr + len used to release memory at close */
- size_t len;
- void *next_addr; /* Incremented by next_entry() */
- size_t next_len; /* Decremented by next_entry() */
- struct mmap_area *next;
-};
-
-/* Our stored configuration */
-struct saved_data {
- /*
- * The array of specifications, initially in the same order as in
- * the specification file. Sorting occurs based on hasMetaChars.
- */
- struct spec *spec_arr;
- unsigned int nspec;
- unsigned int alloc_specs;
-
- /*
- * The array of regular expression stems.
- */
- struct stem *stem_arr;
- int num_stems;
- int alloc_stems;
- struct mmap_area *mmap_areas;
-};
-
-static inline mode_t string_to_mode(char *mode)
-{
- size_t len;
-
- if (!mode)
- return 0;
- len = strlen(mode);
- if (mode[0] != '-' || len != 2)
- return -1;
- switch (mode[1]) {
- case 'b':
- return S_IFBLK;
- case 'c':
- return S_IFCHR;
- case 'd':
- return S_IFDIR;
- case 'p':
- return S_IFIFO;
- case 'l':
- return S_IFLNK;
- case 's':
- return S_IFSOCK;
- case '-':
- return S_IFREG;
- default:
- return -1;
- }
- /* impossible to get here */
- return 0;
-}
-
-static inline int grow_specs(struct saved_data *data)
-{
- struct spec *specs;
- size_t new_specs, total_specs;
-
- if (data->nspec < data->alloc_specs)
- return 0;
-
- new_specs = data->nspec + 16;
- total_specs = data->nspec + new_specs;
-
- specs = realloc(data->spec_arr, total_specs * sizeof(*specs));
- if (!specs) {
- perror("realloc");
- return -1;
- }
-
- /* blank the new entries */
- memset(&specs[data->nspec], 0, new_specs * sizeof(*specs));
-
- data->spec_arr = specs;
- data->alloc_specs = total_specs;
- return 0;
-}
-
-/* Determine if the regular expression specification has any meta characters. */
-static inline void spec_hasMetaChars(struct spec *spec)
-{
- char *c;
- int len;
- char *end;
-
- c = spec->regex_str;
- len = strlen(spec->regex_str);
- end = c + len;
-
- spec->hasMetaChars = 0;
- spec->prefix_len = len;
-
- /* Look at each character in the RE specification string for a
- * meta character. Return when any meta character reached. */
- while (c < end) {
- switch (*c) {
- case '.':
- case '^':
- case '$':
- case '?':
- case '*':
- case '+':
- case '|':
- case '[':
- case '(':
- case '{':
- spec->hasMetaChars = 1;
- spec->prefix_len = c - spec->regex_str;
- return;
- case '\\': /* skip the next character */
- c++;
- break;
- default:
- break;
-
- }
- c++;
- }
-}
-
-/* Move exact pathname specifications to the end. */
-static inline int sort_specs(struct saved_data *data)
-{
- struct spec *spec_copy;
- struct spec spec;
- unsigned int i;
- int front, back;
- size_t len = sizeof(*spec_copy);
-
- spec_copy = malloc(len * data->nspec);
- if (!spec_copy)
- return -1;
-
- /* first move the exact pathnames to the back */
- front = 0;
- back = data->nspec - 1;
- for (i = 0; i < data->nspec; i++) {
- if (data->spec_arr[i].hasMetaChars)
- memcpy(&spec_copy[front++], &data->spec_arr[i], len);
- else
- memcpy(&spec_copy[back--], &data->spec_arr[i], len);
- }
-
- /*
- * now the exact pathnames are at the end, but they are in the reverse
- * order. Since 'front' is now the first of the 'exact' we can run
- * that part of the array switching the front and back element.
- */
- back = data->nspec - 1;
- while (front < back) {
- /* save the front */
- memcpy(&spec, &spec_copy[front], len);
- /* move the back to the front */
- memcpy(&spec_copy[front], &spec_copy[back], len);
- /* put the old front in the back */
- memcpy(&spec_copy[back], &spec, len);
- front++;
- back--;
- }
-
- free(data->spec_arr);
- data->spec_arr = spec_copy;
-
- return 0;
-}
-
-/* Return the length of the text that can be considered the stem, returns 0
- * if there is no identifiable stem */
-static inline int get_stem_from_spec(const char *const buf)
-{
- const char *tmp = strchr(buf + 1, '/');
- const char *ind;
-
- if (!tmp)
- return 0;
-
- for (ind = buf; ind < tmp; ind++) {
- if (strchr(".^$?*+|[({", (int)*ind))
- return 0;
- }
- return tmp - buf;
-}
-
-/*
- * return the stemid given a string and a length
- */
-static inline int find_stem(struct saved_data *data, const char *buf,
- int stem_len)
-{
- int i;
-
- for (i = 0; i < data->num_stems; i++) {
- if (stem_len == data->stem_arr[i].len &&
- !strncmp(buf, data->stem_arr[i].buf, stem_len))
- return i;
- }
-
- return -1;
-}
-
-/* returns the index of the new stored object */
-static inline int store_stem(struct saved_data *data, char *buf, int stem_len)
-{
- int num = data->num_stems;
-
- if (data->alloc_stems == num) {
- struct stem *tmp_arr;
-
- data->alloc_stems = data->alloc_stems * 2 + 16;
- tmp_arr = realloc(data->stem_arr,
- sizeof(*tmp_arr) * data->alloc_stems);
- if (!tmp_arr)
- return -1;
- data->stem_arr = tmp_arr;
- }
- data->stem_arr[num].len = stem_len;
- data->stem_arr[num].buf = buf;
- data->stem_arr[num].from_mmap = 0;
- data->num_stems++;
-
- return num;
-}
-
-/* find the stem of a file spec, returns the index into stem_arr for a new
- * or existing stem, (or -1 if there is no possible stem - IE for a file in
- * the root directory or a regex that is too complex for us). */
-static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
-{
- int stem_len = get_stem_from_spec(buf);
- int stemid;
- char *stem;
-
- if (!stem_len)
- return -1;
-
- stemid = find_stem(data, buf, stem_len);
- if (stemid >= 0)
- return stemid;
-
- /* not found, allocate a new one */
- stem = strndup(buf, stem_len);
- if (!stem)
- return -1;
-
- return store_stem(data, stem, stem_len);
-}
-
-/* This will always check for buffer over-runs and either read the next entry
- * if buf != NULL or skip over the entry (as these areas are mapped in the
- * current buffer). */
-static inline int next_entry(void *buf, struct mmap_area *fp, size_t bytes)
-{
- if (bytes > fp->next_len)
- return -1;
-
- if (buf)
- memcpy(buf, fp->next_addr, bytes);
-
- fp->next_addr = (char *)fp->next_addr + bytes;
- fp->next_len -= bytes;
- return 0;
-}
-
-static inline int compile_regex(struct saved_data *data, struct spec *spec,
- struct regex_error_data * error_data)
-{
- char *reg_buf, *anchored_regex, *cp;
- struct stem *stem_arr = data->stem_arr;
- size_t len;
- int rc;
-
- if (spec->regcomp)
- return 0; /* already done */
-
- /* Skip the fixed stem. */
- reg_buf = spec->regex_str;
- if (spec->stem_id >= 0)
- reg_buf += stem_arr[spec->stem_id].len;
-
- /* Anchor the regular expression. */
- len = strlen(reg_buf);
- cp = anchored_regex = malloc(len + 3);
- if (!anchored_regex)
- return -1;
-
- /* Create ^...$ regexp. */
- *cp++ = '^';
- memcpy(cp, reg_buf, len);
- cp += len;
- *cp++ = '$';
- *cp = '\0';
-
- /* Compile the regular expression. */
- rc = regex_prepare_data(&spec->regex, anchored_regex, error_data);
- free(anchored_regex);
- if (rc < 0) {
- return -1;
- }
-
- /* Done. */
- spec->regcomp = 1;
-
- return 0;
-}
-
-/* This service is used by label_file.c process_file() and
- * utils/sefcontext_compile.c */
-static inline int process_line(struct selabel_handle *rec,
- const char *path, const char *prefix,
- char *line_buf, unsigned lineno)
-{
- int items, len, rc;
- char *regex = NULL, *type = NULL, *context = NULL;
- struct saved_data *data = (struct saved_data *)rec->data;
- struct spec *spec_arr;
- unsigned int nspec = data->nspec;
- char const *errbuf;
- struct regex_error_data error_data;
-
- items = read_spec_entries(line_buf, &errbuf, 3, &regex, &type, &context);
- if (items < 0) {
- rc = errno;
- selinux_log(SELINUX_ERROR,
- "%s: line %u error due to: %s\n", path,
- lineno, errbuf ?: strerror(errno));
- errno = rc;
- return -1;
- }
-
- if (items == 0)
- return items;
-
- if (items < 2) {
- selinux_log(SELINUX_ERROR,
- "%s: line %u is missing fields\n", path,
- lineno);
- if (items == 1)
- free(regex);
- errno = EINVAL;
- return -1;
- } else if (items == 2) {
- /* The type field is optional. */
- context = type;
- type = 0;
- }
-
- len = get_stem_from_spec(regex);
- if (len && prefix && strncmp(prefix, regex, len)) {
- /* Stem of regex does not match requested prefix, discard. */
- free(regex);
- free(type);
- free(context);
- return 0;
- }
-
- rc = grow_specs(data);
- if (rc)
- return rc;
-
- spec_arr = data->spec_arr;
-
- /* process and store the specification in spec. */
- spec_arr[nspec].stem_id = find_stem_from_spec(data, regex);
- spec_arr[nspec].regex_str = regex;
-
- spec_arr[nspec].type_str = type;
- spec_arr[nspec].mode = 0;
-
- spec_arr[nspec].lr.ctx_raw = context;
-
- /*
- * bump data->nspecs to cause closef() to cover it in its free
- * but do not bump nspec since it's used below.
- */
- data->nspec++;
-
- if (rec->validating &&
- compile_regex(data, &spec_arr[nspec], &error_data)) {
- selinux_log(SELINUX_ERROR,
- "%s: line %u has invalid regex %s: %s\n",
- path, lineno, regex,
- (errbuf ? errbuf : "out of memory"));
- errno = EINVAL;
- return -1;
- }
-
- if (type) {
- mode_t mode = string_to_mode(type);
-
- if (mode == (mode_t)-1) {
- selinux_log(SELINUX_ERROR,
- "%s: line %u has invalid file type %s\n",
- path, lineno, type);
- errno = EINVAL;
- return -1;
- }
- spec_arr[nspec].mode = mode;
- }
-
- /* Determine if specification has
- * any meta characters in the RE */
- spec_hasMetaChars(&spec_arr[nspec]);
-
- if (strcmp(context, "<<none>>") && rec->validating) {
- if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) {
- selinux_log(SELINUX_ERROR,
- "%s: line %u has invalid context %s\n",
- path, lineno, spec_arr[nspec].lr.ctx_raw);
- errno = EINVAL;
- return -1;
- }
- }
-
- return 0;
-}
-
-#endif /* _SELABEL_FILE_H_ */
diff --git a/src/label_internal.h b/src/label_internal.h
deleted file mode 100644
index cca44d5..0000000
--- a/src/label_internal.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * This file describes the internal interface used by the labeler
- * for calling the user-supplied memory allocation, validation,
- * and locking routine.
- *
- * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
- */
-#ifndef _SELABEL_INTERNAL_H_
-#define _SELABEL_INTERNAL_H_
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <selinux/selinux.h>
-#include <selinux/label.h>
-#include "dso.h"
-
-/*
- * Installed backends
- */
-int selabel_file_init(struct selabel_handle *rec, const struct selinux_opt *opts,
- unsigned nopts) hidden;
-int selabel_media_init(struct selabel_handle *rec, const struct selinux_opt *opts,
- unsigned nopts) hidden;
-int selabel_x_init(struct selabel_handle *rec, const struct selinux_opt *opts,
- unsigned nopts) hidden;
-int selabel_db_init(struct selabel_handle *rec,
- const struct selinux_opt *opts, unsigned nopts) hidden;
-int selabel_property_init(struct selabel_handle *rec,
- const struct selinux_opt *opts, unsigned nopts) hidden;
-int selabel_service_init(struct selabel_handle *rec,
- const struct selinux_opt *opts, unsigned nopts) hidden;
-
-/*
- * Labeling internal structures
- */
-struct selabel_sub {
- char *src;
- int slen;
- char *dst;
- struct selabel_sub *next;
-};
-
-struct selabel_lookup_rec {
- char * ctx_raw;
- char * ctx_trans;
- int validated;
-};
-
-struct selabel_handle {
- /* arguments that were passed to selabel_open */
- unsigned int backend;
- int validating;
-
- /* labeling operations */
- struct selabel_lookup_rec *(*func_lookup) (struct selabel_handle *h,
- const char *key, int type);
- void (*func_close) (struct selabel_handle *h);
- void (*func_stats) (struct selabel_handle *h);
- bool (*func_partial_match) (struct selabel_handle *h, const char *key);
- struct selabel_lookup_rec *(*func_lookup_best_match)
- (struct selabel_handle *h,
- const char *key,
- const char **aliases,
- int type);
- enum selabel_cmp_result (*func_cmp)(struct selabel_handle *h1,
- struct selabel_handle *h2);
-
- /* supports backend-specific state information */
- void *data;
-
- /*
- * The main spec file used. Note for file contexts the local and/or
- * homedirs could also have been used to resolve a context.
- */
- char *spec_file;
-
- /* substitution support */
- struct selabel_sub *dist_subs;
- struct selabel_sub *subs;
-};
-
-/*
- * Validation function
- */
-extern int
-selabel_validate(struct selabel_handle *rec,
- struct selabel_lookup_rec *contexts) hidden;
-
-/*
- * The read_spec_entries function may be used to
- * replace sscanf to read entries from spec files.
- */
-extern int read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...);
-
-#endif /* _SELABEL_INTERNAL_H_ */
diff --git a/src/label_support.c b/src/label_support.c
deleted file mode 100644
index e226d51..0000000
--- a/src/label_support.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * This file contains helper functions for labeling support.
- *
- * Author : Richard Haines <richard_c_haines@btinternet.com>
- */
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-#include "label_internal.h"
-
-/*
- * The read_spec_entries and read_spec_entry functions may be used to
- * replace sscanf to read entries from spec files. The file and
- * property services now use these.
- */
-
-/*
- * Read an entry from a spec file (e.g. file_contexts)
- * entry - Buffer to allocate for the entry.
- * ptr - current location of the line to be processed.
- * returns - 0 on success and *entry is set to be a null
- * terminated value. On Error it returns -1 and
- errno will be set.
- *
- */
-static inline int read_spec_entry(char **entry, char **ptr, int *len, const char **errbuf)
-{
- *entry = NULL;
- char *tmp_buf = NULL;
-
- while (isspace(**ptr) && **ptr != '\0')
- (*ptr)++;
-
- tmp_buf = *ptr;
- *len = 0;
-
- while (!isspace(**ptr) && **ptr != '\0') {
- if (!isascii(**ptr)) {
- errno = EINVAL;
- *errbuf = "Non-ASCII characters found";
- return -1;
- }
- (*ptr)++;
- (*len)++;
- }
-
- if (*len) {
- *entry = strndup(tmp_buf, *len);
- if (!*entry)
- return -1;
- }
-
- return 0;
-}
-
-/*
- * line_buf - Buffer containing the spec entries .
- * errbuf - Double pointer used for passing back specific error messages.
- * num_args - The number of spec parameter entries to process.
- * ... - A 'char **spec_entry' for each parameter.
- * returns - The number of items processed. On error, it returns -1 with errno
- * set and may set errbuf to a specific error message.
- *
- * This function calls read_spec_entry() to do the actual string processing.
- * As such, can return anything from that function as well.
- */
-int hidden read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...)
-{
- char **spec_entry, *buf_p;
- int len, rc, items, entry_len = 0;
- va_list ap;
-
- *errbuf = NULL;
-
- len = strlen(line_buf);
- if (line_buf[len - 1] == '\n')
- line_buf[len - 1] = '\0';
- else
- /* Handle case if line not \n terminated by bumping
- * the len for the check below (as the line is NUL
- * terminated by getline(3)) */
- len++;
-
- buf_p = line_buf;
- while (isspace(*buf_p))
- buf_p++;
-
- /* Skip comment lines and empty lines. */
- if (*buf_p == '#' || *buf_p == '\0')
- return 0;
-
- /* Process the spec file entries */
- va_start(ap, num_args);
-
- items = 0;
- while (items < num_args) {
- spec_entry = va_arg(ap, char **);
-
- if (len - 1 == buf_p - line_buf) {
- va_end(ap);
- return items;
- }
-
- rc = read_spec_entry(spec_entry, &buf_p, &entry_len, errbuf);
- if (rc < 0) {
- va_end(ap);
- return rc;
- }
- if (entry_len)
- items++;
- }
- va_end(ap);
- return items;
-}
diff --git a/src/lgetfilecon.c b/src/lgetfilecon.c
deleted file mode 100644
index 22851a4..0000000
--- a/src/lgetfilecon.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/xattr.h>
-#include "selinux_internal.h"
-#include "policy.h"
-
-int lgetfilecon(const char *path, char ** context)
-{
- char *buf;
- ssize_t size;
- ssize_t ret;
-
- size = INITCONTEXTLEN + 1;
- buf = malloc(size);
- if (!buf)
- return -1;
- memset(buf, 0, size);
-
- ret = lgetxattr(path, XATTR_NAME_SELINUX, buf, size - 1);
- if (ret < 0 && errno == ERANGE) {
- char *newbuf;
-
- size = lgetxattr(path, XATTR_NAME_SELINUX, NULL, 0);
- if (size < 0)
- goto out;
-
- size++;
- newbuf = realloc(buf, size);
- if (!newbuf)
- goto out;
-
- buf = newbuf;
- memset(buf, 0, size);
- ret = lgetxattr(path, XATTR_NAME_SELINUX, buf, size - 1);
- }
- out:
- if (ret == 0) {
- /* Re-map empty attribute values to errors. */
- errno = EOPNOTSUPP;
- ret = -1;
- }
- if (ret < 0)
- free(buf);
- else
- *context = buf;
- return ret;
-}
diff --git a/src/load_policy.c b/src/load_policy.c
deleted file mode 100644
index 51a178a..0000000
--- a/src/load_policy.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/utsname.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-#include "selinux_internal.h"
-#include <dlfcn.h>
-#include "policy.h"
-#include <limits.h>
-#include "callbacks.h"
-
-int security_load_policy(void *data, size_t len)
-{
- char path[PATH_MAX];
- int fd, ret;
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s/load", selinux_mnt);
- fd = open(path, O_RDWR | O_CLOEXEC);
- if (fd < 0)
- return -1;
-
- ret = write(fd, data, len);
- close(fd);
- if (ret < 0)
- return -1;
- return 0;
-}
-
-hidden_def(security_load_policy)
diff --git a/src/lsetfilecon.c b/src/lsetfilecon.c
deleted file mode 100644
index 7147f9e..0000000
--- a/src/lsetfilecon.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/xattr.h>
-#include "selinux_internal.h"
-#include "policy.h"
-
-int lsetfilecon(const char *path, const char *context)
-{
- return lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1,
- 0);
-}
-
diff --git a/src/mapping.c b/src/mapping.c
deleted file mode 100644
index f205804..0000000
--- a/src/mapping.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Class and permission mappings.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <selinux/selinux.h>
-#include <selinux/avc.h>
-#include "mapping.h"
-
-/*
- * Class and permission mappings
- */
-
-struct selinux_mapping {
- security_class_t value; /* real, kernel value */
- unsigned num_perms;
- access_vector_t perms[sizeof(access_vector_t) * 8];
-};
-
-static struct selinux_mapping *current_mapping = NULL;
-static security_class_t current_mapping_size = 0;
-
-/*
- * Mapping setting function
- */
-
-int
-selinux_set_mapping(struct security_class_mapping *map)
-{
- size_t size = sizeof(struct selinux_mapping);
- security_class_t i, j;
- unsigned k;
-
- free(current_mapping);
- current_mapping = NULL;
- current_mapping_size = 0;
-
- if (avc_reset() < 0)
- goto err;
-
- /* Find number of classes in the input mapping */
- if (!map) {
- errno = EINVAL;
- goto err;
- }
- i = 0;
- while (map[i].name)
- i++;
-
- /* Allocate space for the class records, plus one for class zero */
- current_mapping = (struct selinux_mapping *)calloc(++i, size);
- if (!current_mapping)
- goto err;
-
- /* Store the raw class and permission values */
- j = 0;
- while (map[j].name) {
- struct security_class_mapping *p_in = map + (j++);
- struct selinux_mapping *p_out = current_mapping + j;
-
- p_out->value = string_to_security_class(p_in->name);
- if (!p_out->value)
- goto err2;
-
- k = 0;
- while (p_in->perms[k]) {
- /* An empty permission string skips ahead */
- if (!*p_in->perms[k]) {
- k++;
- continue;
- }
- p_out->perms[k] = string_to_av_perm(p_out->value,
- p_in->perms[k]);
- if (!p_out->perms[k])
- goto err2;
- k++;
- }
- p_out->num_perms = k;
- }
-
- /* Set the mapping size here so the above lookups are "raw" */
- current_mapping_size = i;
- return 0;
-err2:
- free(current_mapping);
- current_mapping = NULL;
- current_mapping_size = 0;
-err:
- return -1;
-}
-
-/*
- * Get real, kernel values from mapped values
- */
-
-security_class_t
-unmap_class(security_class_t tclass)
-{
- if (tclass < current_mapping_size)
- return current_mapping[tclass].value;
-
- /* If here no mapping set or the class requested is not valid. */
- if (current_mapping_size != 0) {
- errno = EINVAL;
- return 0;
- }
- else
- return tclass;
-}
-
-access_vector_t
-unmap_perm(security_class_t tclass, access_vector_t tperm)
-{
- if (tclass < current_mapping_size) {
- unsigned i;
- access_vector_t kperm = 0;
-
- for (i=0; i<current_mapping[tclass].num_perms; i++)
- if (tperm & (1<<i)) {
- kperm |= current_mapping[tclass].perms[i];
- tperm &= ~(1<<i);
- }
- return kperm;
- }
-
- /* If here no mapping set or the perm requested is not valid. */
- if (current_mapping_size != 0) {
- errno = EINVAL;
- return 0;
- }
- else
- return tperm;
-}
-
-/*
- * Get mapped values from real, kernel values
- */
-
-security_class_t
-map_class(security_class_t kclass)
-{
- security_class_t i;
-
- for (i=0; i<current_mapping_size; i++)
- if (current_mapping[i].value == kclass)
- return i;
-
-/* If here no mapping set or the class requested is not valid. */
- if (current_mapping_size != 0) {
- errno = EINVAL;
- return 0;
- }
- else
- return kclass;
-}
-
-access_vector_t
-map_perm(security_class_t tclass, access_vector_t kperm)
-{
- if (tclass < current_mapping_size) {
- unsigned i;
- access_vector_t tperm = 0;
-
- for (i=0; i<current_mapping[tclass].num_perms; i++)
- if (kperm & current_mapping[tclass].perms[i]) {
- tperm |= 1<<i;
- kperm &= ~current_mapping[tclass].perms[i];
- }
-
- if (tperm == 0) {
- errno = EINVAL;
- return 0;
- }
- else
- return tperm;
- }
- return kperm;
-}
-
-void
-map_decision(security_class_t tclass, struct av_decision *avd)
-{
- if (tclass < current_mapping_size) {
- unsigned i;
- access_vector_t result;
-
- for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
- if (avd->allowed & current_mapping[tclass].perms[i])
- result |= 1<<i;
- avd->allowed = result;
-
- for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
- if (avd->decided & current_mapping[tclass].perms[i])
- result |= 1<<i;
- avd->decided = result;
-
- for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
- if (avd->auditallow & current_mapping[tclass].perms[i])
- result |= 1<<i;
- avd->auditallow = result;
-
- for (i=0, result=0; i<current_mapping[tclass].num_perms; i++)
- if (avd->auditdeny & current_mapping[tclass].perms[i])
- result |= 1<<i;
- avd->auditdeny = result;
- }
-}
diff --git a/src/mapping.h b/src/mapping.h
deleted file mode 100644
index b96756b..0000000
--- a/src/mapping.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This file describes the class and permission mappings used to
- * hide the kernel numbers from userspace by allowing userspace object
- * managers to specify a list of classes and permissions.
- */
-#ifndef _SELINUX_MAPPING_H_
-#define _SELINUX_MAPPING_H_
-
-#include <selinux/selinux.h>
-
-/*
- * Get real, kernel values from mapped values
- */
-
-extern security_class_t
-unmap_class(security_class_t tclass);
-
-extern access_vector_t
-unmap_perm(security_class_t tclass, access_vector_t tperm);
-
-/*
- * Get mapped values from real, kernel values
- */
-
-extern security_class_t
-map_class(security_class_t kclass);
-
-extern access_vector_t
-map_perm(security_class_t tclass, access_vector_t kperm);
-
-extern void
-map_decision(security_class_t tclass, struct av_decision *avd);
-
-/*mapping is not used for embedded build*/
-#ifdef DISABLE_AVC
-#define unmap_perm(x,y) y
-#define unmap_class(x) x
-#define map_decision(x,y)
-#endif
-
-#endif /* _SELINUX_MAPPING_H_ */
diff --git a/src/policy.h b/src/policy.h
deleted file mode 100644
index 92a416e..0000000
--- a/src/policy.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef _POLICY_H_
-#define _POLICY_H_
-
-/* Private definitions used internally by libselinux. */
-
-/* xattr name for SELinux attributes. */
-#define XATTR_NAME_SELINUX "security.selinux"
-
-/* Initial length guess for getting contexts. */
-#define INITCONTEXTLEN 255
-
-/* selinuxfs magic number */
-#define SELINUX_MAGIC 0xf97cff8c
-
-/* Preferred selinuxfs mount point directory paths. */
-#define SELINUXMNT "/sys/fs/selinux"
-#define OLDSELINUXMNT "/selinux"
-
-/* selinuxfs filesystem type string. */
-#define SELINUXFS "selinuxfs"
-
-/* selinuxfs mount point determined at runtime */
-extern char *selinux_mnt;
-
-/* First version of policy supported in mainline Linux. */
-#define DEFAULT_POLICY_VERSION 15
-
-#endif
diff --git a/src/policyvers.c b/src/policyvers.c
deleted file mode 100644
index 284a7f7..0000000
--- a/src/policyvers.c
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include "selinux_internal.h"
-#include <stdio.h>
-#include "policy.h"
-#include "dso.h"
-#include <limits.h>
-
-int security_policyvers(void)
-{
- int fd, ret;
- char path[PATH_MAX];
- char buf[20];
- unsigned vers = DEFAULT_POLICY_VERSION;
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s/policyvers", selinux_mnt);
- fd = open(path, O_RDONLY);
- if (fd < 0) {
- if (errno == ENOENT)
- return vers;
- else
- return -1;
- }
- memset(buf, 0, sizeof buf);
- ret = read(fd, buf, sizeof buf - 1);
- close(fd);
- if (ret < 0)
- return -1;
-
- if (sscanf(buf, "%u", &vers) != 1)
- return -1;
-
- return vers;
-}
-
-hidden_def(security_policyvers)
diff --git a/src/procattr.c b/src/procattr.c
deleted file mode 100644
index 74c0012..0000000
--- a/src/procattr.c
+++ /dev/null
@@ -1,176 +0,0 @@
-#include <sys/syscall.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include "selinux_internal.h"
-#include "policy.h"
-
-#ifdef HOST
-static pid_t gettid(void)
-{
- return syscall(__NR_gettid);
-}
-#endif
-
-static int openattr(pid_t pid, const char *attr, int flags)
-{
- int fd, rc;
- char *path;
- pid_t tid;
-
- if (pid > 0) {
- rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr);
- } else if (pid == 0) {
- rc = asprintf(&path, "/proc/thread-self/attr/%s", attr);
- if (rc < 0)
- return -1;
- fd = open(path, flags | O_CLOEXEC);
- if (fd >= 0 || errno != ENOENT)
- goto out;
- free(path);
- tid = gettid();
- rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr);
- } else {
- errno = EINVAL;
- return -1;
- }
- if (rc < 0)
- return -1;
-
- fd = open(path, flags | O_CLOEXEC);
-out:
- free(path);
- return fd;
-}
-
-static int getprocattrcon(char ** context,
- pid_t pid, const char *attr)
-{
- char *buf;
- size_t size;
- int fd;
- ssize_t ret;
- int errno_hold;
-
- fd = openattr(pid, attr, O_RDONLY);
- if (fd < 0)
- return -1;
-
- size = selinux_page_size;
- buf = malloc(size);
- if (!buf) {
- ret = -1;
- goto out;
- }
- memset(buf, 0, size);
-
- do {
- ret = read(fd, buf, size - 1);
- } while (ret < 0 && errno == EINTR);
- if (ret < 0)
- goto out2;
-
- if (ret == 0) {
- *context = NULL;
- goto out2;
- }
-
- *context = strdup(buf);
- if (!(*context)) {
- ret = -1;
- goto out2;
- }
- ret = 0;
- out2:
- free(buf);
- out:
- errno_hold = errno;
- close(fd);
- errno = errno_hold;
- return ret;
-}
-
-static int setprocattrcon(const char * context,
- pid_t pid, const char *attr)
-{
- int fd;
- ssize_t ret;
- int errno_hold;
-
- fd = openattr(pid, attr, O_RDWR);
- if (fd < 0)
- return -1;
- if (context)
- do {
- ret = write(fd, context, strlen(context) + 1);
- } while (ret < 0 && errno == EINTR);
- else
- do {
- ret = write(fd, NULL, 0); /* clear */
- } while (ret < 0 && errno == EINTR);
- errno_hold = errno;
- close(fd);
- errno = errno_hold;
- if (ret < 0)
- return -1;
- else
- return 0;
-}
-
-#define getselfattr_def(fn, attr) \
- int get##fn(char **c) \
- { \
- return getprocattrcon(c, 0, #attr); \
- }
-
-#define setselfattr_def(fn, attr) \
- int set##fn(const char * c) \
- { \
- return setprocattrcon(c, 0, #attr); \
- }
-
-#define all_selfattr_def(fn, attr) \
- getselfattr_def(fn, attr) \
- setselfattr_def(fn, attr)
-
-#define getpidattr_def(fn, attr) \
- int get##fn(pid_t pid, char **c) \
- { \
- if (pid <= 0) { \
- errno = EINVAL; \
- return -1; \
- } else { \
- return getprocattrcon(c, pid, #attr); \
- } \
- }
-
-all_selfattr_def(con, current)
- getpidattr_def(pidcon, current)
- getselfattr_def(prevcon, prev)
- all_selfattr_def(execcon, exec)
- all_selfattr_def(fscreatecon, fscreate)
- all_selfattr_def(sockcreatecon, sockcreate)
- all_selfattr_def(keycreatecon, keycreate)
-
- hidden_def(getcon_raw)
- hidden_def(getcon)
- hidden_def(getexeccon_raw)
- hidden_def(getfilecon_raw)
- hidden_def(getfilecon)
- hidden_def(getfscreatecon_raw)
- hidden_def(getkeycreatecon_raw)
- hidden_def(getpeercon_raw)
- hidden_def(getpidcon_raw)
- hidden_def(getprevcon_raw)
- hidden_def(getprevcon)
- hidden_def(getsockcreatecon_raw)
- hidden_def(setcon_raw)
- hidden_def(setexeccon_raw)
- hidden_def(setexeccon)
- hidden_def(setfilecon_raw)
- hidden_def(setfscreatecon_raw)
- hidden_def(setkeycreatecon_raw)
- hidden_def(setsockcreatecon_raw)
diff --git a/src/regex.c b/src/regex.c
deleted file mode 100644
index 32fe6ab..0000000
--- a/src/regex.c
+++ /dev/null
@@ -1,391 +0,0 @@
-#include <assert.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "regex.h"
-#include "label_file.h"
-
-int regex_prepare_data(struct regex_data ** regex, char const * pattern_string,
- struct regex_error_data * errordata) {
- memset(errordata, 0, sizeof(struct regex_error_data));
- *regex = regex_data_create();
- if (!(*regex))
- return -1;
-#ifdef USE_PCRE2
- (*regex)->regex = pcre2_compile((PCRE2_SPTR)pattern_string,
- PCRE2_ZERO_TERMINATED,
- PCRE2_DOTALL,
- &errordata->error_code,
- &errordata->error_offset, NULL);
-#else
- (*regex)->regex = pcre_compile(pattern_string, PCRE_DOTALL,
- &errordata->error_buffer,
- &errordata->error_offset, NULL);
-#endif
- if (!(*regex)->regex) {
- goto err;
- }
-
-#ifdef USE_PCRE2
- (*regex)->match_data =
- pcre2_match_data_create_from_pattern((*regex)->regex, NULL);
- if (!(*regex)->match_data) {
- goto err;
- }
-#else
- (*regex)->sd = pcre_study((*regex)->regex, 0, &errordata->error_buffer);
- if (!(*regex)->sd && errordata->error_buffer) {
- goto err;
- }
- (*regex)->extra_owned = !!(*regex)->sd;
-#endif
- return 0;
-
-err: regex_data_free(*regex);
- *regex = NULL;
- return -1;
-}
-
-char const * regex_version() {
-#ifdef USE_PCRE2
- static int initialized = 0;
- static char * version_string = NULL;
- size_t version_string_len;
- if (!initialized) {
- version_string_len = pcre2_config(PCRE2_CONFIG_VERSION, NULL);
- version_string = (char*) malloc(version_string_len);
- if (!version_string) {
- return NULL;
- }
- pcre2_config(PCRE2_CONFIG_VERSION, version_string);
- initialized = 1;
- }
- return version_string;
-#else
- return pcre_version();
-#endif
-}
-
-int regex_load_mmap(struct mmap_area * mmap_area, struct regex_data ** regex) {
- int rc;
- size_t entry_len, info_len;
-
- rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
-#ifdef USE_PCRE2
- if (rc < 0)
- return -1;
-
-#ifndef NO_PERSISTENTLY_STORED_PATTERNS
- /* this should yield exactly one because we store one pattern at a time
- */
- rc = pcre2_serialize_get_number_of_codes(mmap_area->next_addr);
- if (rc != 1)
- return -1;
-
- *regex = regex_data_create();
- if (!*regex)
- return -1;
-
- rc = pcre2_serialize_decode(&(*regex)->regex, 1,
- (PCRE2_SPTR)mmap_area->next_addr, NULL);
- if (rc != 1)
- goto err;
-
- (*regex)->match_data =
- pcre2_match_data_create_from_pattern((*regex)->regex, NULL);
- if (!(*regex)->match_data)
- goto err;
-
-#endif /* NO_PERSISTENTLY_STORED_PATTERNS */
- /* and skip the decoded bit */
- rc = next_entry(NULL, mmap_area, entry_len);
- if (rc < 0)
- goto err;
-
- return 0;
-#else
- if (rc < 0 || !entry_len) {
- rc = -1;
- return -1;
- }
- *regex = regex_data_create();
- if (!(*regex))
- return -1;
-
- (*regex)->regex = (pcre *) mmap_area->next_addr;
- rc = next_entry(NULL, mmap_area, entry_len);
- if (rc < 0)
- goto err;
-
- /* Check that regex lengths match. pcre_fullinfo()
- * also validates its magic number. */
- rc = pcre_fullinfo((*regex)->regex, NULL, PCRE_INFO_SIZE, &info_len);
- if (rc < 0 || info_len != entry_len) {
- goto err;
- }
-
- rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
- if (rc < 0 || !entry_len) {
- goto err;
- }
- (*regex)->lsd.study_data = (void *) mmap_area->next_addr;
- (*regex)->lsd.flags |= PCRE_EXTRA_STUDY_DATA;
- rc = next_entry(NULL, mmap_area, entry_len);
- if (rc < 0)
- goto err;
-
- /* Check that study data lengths match. */
- rc = pcre_fullinfo((*regex)->regex, &(*regex)->lsd,
- PCRE_INFO_STUDYSIZE,
- &info_len);
- if (rc < 0 || info_len != entry_len) {
- goto err;
- }
- (*regex)->extra_owned = 0;
- return 0;
-#endif
- err: regex_data_free(*regex);
- *regex = NULL;
- return -1;
-}
-
-int regex_writef(struct regex_data * regex, FILE * fp) {
- int rc;
- size_t len;
-#ifdef USE_PCRE2
- PCRE2_UCHAR * bytes;
- PCRE2_SIZE to_write;
-
-#ifndef NO_PERSISTENTLY_STORED_PATTERNS
- /* encode the patter for serialization */
- rc = pcre2_serialize_encode(&regex->regex, 1, &bytes, &to_write, NULL);
- if (rc != 1)
- return -1;
-
-#else
- (void)regex; // silence unused parameter warning
- to_write = 0;
-#endif
- /* write serialized pattern's size */
- len = fwrite(&to_write, sizeof(uint32_t), 1, fp);
- if (len != 1) {
-#ifndef NO_PERSISTENTLY_STORED_PATTERNS
- pcre2_serialize_free(bytes);
-#endif
- return -1;
- }
-
-#ifndef NO_PERSISTENTLY_STORED_PATTERNS
- /* write serialized pattern */
- len = fwrite(bytes, 1, to_write, fp);
- if (len != to_write) {
- pcre2_serialize_free(bytes);
- return -1;
- }
- pcre2_serialize_free(bytes);
-#endif
-#else
- uint32_t to_write;
- size_t size;
- pcre_extra * sd = regex->extra_owned ? regex->sd : &regex->lsd;
-
- /* determine the size of the pcre data in bytes */
- rc = pcre_fullinfo(regex->regex, NULL, PCRE_INFO_SIZE, &size);
- if (rc < 0)
- return -1;
-
- /* write the number of bytes in the pcre data */
- to_write = size;
- len = fwrite(&to_write, sizeof(uint32_t), 1, fp);
- if (len != 1)
- return -1;
-
- /* write the actual pcre data as a char array */
- len = fwrite(regex->regex, 1, to_write, fp);
- if (len != to_write)
- return -1;
-
- /* determine the size of the pcre study info */
- rc = pcre_fullinfo(regex->regex, sd, PCRE_INFO_STUDYSIZE, &size);
- if (rc < 0)
- return -1;
-
- /* write the number of bytes in the pcre study data */
- to_write = size;
- len = fwrite(&to_write, sizeof(uint32_t), 1, fp);
- if (len != 1)
- return -1;
-
- /* write the actual pcre study data as a char array */
- len = fwrite(sd->study_data, 1, to_write, fp);
- if (len != to_write)
- return -1;
-#endif
- return 0;
-}
-
-struct regex_data * regex_data_create() {
- struct regex_data * dummy = (struct regex_data*) malloc(
- sizeof(struct regex_data));
- if (dummy) {
- memset(dummy, 0, sizeof(struct regex_data));
- }
- return dummy;
-}
-
-void regex_data_free(struct regex_data * regex) {
- if (regex) {
-#ifdef USE_PCRE2
- if (regex->regex) {
- pcre2_code_free(regex->regex);
- }
- if (regex->match_data) {
- pcre2_match_data_free(regex->match_data);
- }
-#else
- if (regex->regex)
- pcre_free(regex->regex);
- if (regex->extra_owned && regex->sd) {
- pcre_free_study(regex->sd);
- }
-#endif
- free(regex);
- }
-}
-
-int regex_match(struct regex_data * regex, char const * subject, int partial) {
- int rc;
-#ifdef USE_PCRE2
- rc = pcre2_match(regex->regex,
- (PCRE2_SPTR)subject, PCRE2_ZERO_TERMINATED, 0,
- partial ? PCRE2_PARTIAL_SOFT : 0, regex->match_data,
- NULL);
- if (rc > 0)
- return REGEX_MATCH;
- switch (rc) {
- case PCRE2_ERROR_PARTIAL:
- return REGEX_MATCH_PARTIAL;
- case PCRE2_ERROR_NOMATCH:
- return REGEX_NO_MATCH;
- default:
- return REGEX_ERROR;
- }
-#else
- rc = pcre_exec(regex->regex,
- regex->extra_owned ? regex->sd : &regex->lsd, subject,
- strlen(subject), 0, partial ? PCRE_PARTIAL_SOFT : 0,
- NULL,
- 0);
- switch (rc) {
- case 0:
- return REGEX_MATCH;
- case PCRE_ERROR_PARTIAL:
- return REGEX_MATCH_PARTIAL;
- case PCRE_ERROR_NOMATCH:
- return REGEX_NO_MATCH;
- default:
- return REGEX_ERROR;
- }
-#endif
-}
-
-/* TODO Replace this compare function with something that actually compares the
- * regular expressions.
- * This compare function basically just compares the binary representations of
- * the automatons, and because this representation contains pointers and
- * metadata, it can only return a match if regex1 == regex2.
- * Preferably, this function would be replaced with an algorithm that computes
- * the equivalence of the automatons systematically.
- */
-int regex_cmp(struct regex_data * regex1, struct regex_data * regex2) {
- int rc;
- size_t len1, len2;
-#ifdef USE_PCRE2
- rc = pcre2_pattern_info(regex1->regex, PCRE2_INFO_SIZE, &len1);
- assert(rc == 0);
- rc = pcre2_pattern_info(regex2->regex, PCRE2_INFO_SIZE, &len2);
- assert(rc == 0);
- if (len1 != len2 || memcmp(regex1->regex, regex2->regex, len1))
- return SELABEL_INCOMPARABLE;
-#else
- rc = pcre_fullinfo(regex1->regex, NULL, PCRE_INFO_SIZE, &len1);
- assert(rc == 0);
- rc = pcre_fullinfo(regex2->regex, NULL, PCRE_INFO_SIZE, &len2);
- assert(rc == 0);
- if (len1 != len2 || memcmp(regex1->regex, regex2->regex, len1))
- return SELABEL_INCOMPARABLE;
-#endif
- return SELABEL_EQUAL;
-}
-
-void regex_format_error(struct regex_error_data const * error_data,
- char * buffer, size_t buf_size) {
- unsigned the_end_length = buf_size > 4 ? 4 : buf_size;
- char * ptr = &buffer[buf_size - the_end_length];
- int rc = 0;
- size_t pos = 0;
- if (!buffer || !buf_size)
- return;
- rc = snprintf(buffer, buf_size, "REGEX back-end error: ");
- if (rc < 0)
- /* If snprintf fails it constitutes a logical error that needs
- * fixing.
- */
- abort();
-
- pos += rc;
- if (pos >= buf_size)
- goto truncated;
-
- if (error_data->error_offset > 0) {
-#ifdef USE_PCRE2
- rc = snprintf(buffer + pos, buf_size - pos, "At offset %zu: ",
- error_data->error_offset);
-#else
- rc = snprintf(buffer + pos, buf_size - pos, "At offset %d: ",
- error_data->error_offset);
-#endif
- if (rc < 0)
- abort();
-
- }
- pos += rc;
- if (pos >= buf_size)
- goto truncated;
-
-#ifdef USE_PCRE2
- rc = pcre2_get_error_message(error_data->error_code,
- (PCRE2_UCHAR*)(buffer + pos),
- buf_size - pos);
- if (rc == PCRE2_ERROR_NOMEMORY)
- goto truncated;
-#else
- rc = snprintf(buffer + pos, buf_size - pos, "%s",
- error_data->error_buffer);
- if (rc < 0)
- abort();
-
- if ((size_t)rc < strlen(error_data->error_buffer))
- goto truncated;
-#endif
-
- return;
-
-truncated:
- /* replace end of string with "..." to indicate that it was truncated */
- switch (the_end_length) {
- /* no break statements, fall-through is intended */
- case 4:
- *ptr++ = '.';
- case 3:
- *ptr++ = '.';
- case 2:
- *ptr++ = '.';
- case 1:
- *ptr++ = '\0';
- default:
- break;
- }
- return;
-}
diff --git a/src/regex.h b/src/regex.h
deleted file mode 100644
index 7b74f32..0000000
--- a/src/regex.h
+++ /dev/null
@@ -1,166 +0,0 @@
-#ifndef SRC_REGEX_H_
-#define SRC_REGEX_H_
-
-#include <stdio.h>
-
-#ifdef USE_PCRE2
-#include <pcre2.h>
-#else
-#include <pcre.h>
-#endif
-
-enum {
- REGEX_MATCH,
- REGEX_MATCH_PARTIAL,
- REGEX_NO_MATCH,
- REGEX_ERROR = -1,
-};
-
-#ifdef USE_PCRE2
-struct regex_data {
- pcre2_code * regex; /* compiled regular expression */
- pcre2_match_data * match_data; /* match data block required for the compiled
- pattern in regex2 */
-};
-
-struct regex_error_data {
- int error_code;
- PCRE2_SIZE error_offset;
-};
-
-/* ^^^^^^ USE_PCRE2 ^^^^^^ */
-#else
-/* vvvvvv USE_PCRE vvvvvv */
-
-/* Prior to version 8.20, libpcre did not have pcre_free_study() */
-#if (PCRE_MAJOR < 8 || (PCRE_MAJOR == 8 && PCRE_MINOR < 20))
-#define pcre_free_study pcre_free
-#endif
-
-struct regex_data {
- pcre *regex; /* compiled regular expression */
- int extra_owned;
- union {
- pcre_extra *sd; /* pointer to extra compiled stuff */
- pcre_extra lsd; /* used to hold the mmap'd version */
- };
-};
-
-struct regex_error_data {
- char const * error_buffer;
- int error_offset;
-};
-
-#endif /* USE_PCRE2 */
-
-struct mmap_area;
-
-/**
- * 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
- * function is called it allocates a buffer large enough to hold the version
- * string and reads the PCRE2_CONFIG_VERSION option to fill the buffer.
- * The allocated buffer will linger in memory until the calling process is being
- * reaped.
- *
- * It may return NULL on error.
- */
-char const * regex_version();
-/**
- * This constructor function allocates a buffer for a regex_data structure.
- * The buffer is being initialized with zeroes.
- */
-struct regex_data * regex_data_create();
-/**
- * This complementary destructor function frees the a given regex_data buffer.
- * It also frees any non NULL member pointers with the appropriate pcreX_X_free
- * function. For PCRE this function respects the extra_owned field and frees
- * the pcre_extra data conditionally. Calling this function on a NULL pointer is
- * save.
- */
-void regex_data_free(struct regex_data * regex);
-/**
- * This function compiles the regular expression. Additionally, it prepares
- * data structures required by the different underlying engines. For PCRE
- * it calls pcre_study to generate optional data required for optimized
- * execution of the compiled pattern. In the case of PCRE2, it allocates
- * a pcre2_match_data structure of appropriate size to hold all possible
- * matches created by the 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 pattern_string The pattern string that is to be compiled.
- * @arg errordata A pointer to a regex_error_data structure must be passed
- * to this function. This structure depends on the underlying
- * implementation. It can be passed to regex_format_error
- * to generate a human readable error message.
- * @retval 0 on success
- * @retval -1 on error
- */
-int regex_prepare_data(struct regex_data ** regex, char const * pattern_string,
- struct regex_error_data * errordata);
-/**
- * This function loads a serialized precompiled pattern from a contiguous
- * data region given by map_area.
- *
- * @arg map_area Description of the memory region holding a serialized
- * 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.
- *
- * @retval 0 on success
- * @retval -1 on error
- */
-int regex_load_mmap(struct mmap_area * map_area, struct regex_data ** regex);
-/**
- * This function stores a precompiled regular expression to a file.
- * In the case of PCRE, it just dumps the binary representation of the
- * precomplied pattern into a file. In the case of PCRE2, it uses the
- * serialization function provided by the library.
- *
- * @arg regex The precomplied regular expression data.
- * @arg fp A file stream specifying the output file.
- */
-int regex_writef(struct regex_data * regex, FILE * fp);
-/**
- * This function applies a precompiled pattern to a subject string and
- * returns whether or not a match was found.
- *
- * @arg regex The precompiled pattern.
- * @arg subject The subject string.
- * @arg partial Boolean indicating if partial matches are wanted. A nonzero
- * value is equivalent to specifying PCRE[2]_PARTIAL_SOFT as
- * option to pcre_exec of pcre2_match.
- * @retval REGEX_MATCH if a match was found
- * @retval REGEX_MATCH_PARTIAL if a partial match was found
- * @retval REGEX_NO_MATCH if no match was found
- * @retval REGEX_ERROR if an error was encountered during the execution of the
- * regular expression
- */
-int regex_match(struct regex_data * regex, char const * subject, int partial);
-/**
- * This function compares two compiled regular expressions (regex1 and regex2).
- * It compares the binary representations of the compiled patterns. It is a very
- * crude approximation because the binary representation holds data like
- * reference counters, that has nothing to do with the actual state machine.
- *
- * @retval SELABEL_EQUAL if the pattern's binary representations are exactly
- * the same
- * @retval SELABEL_INCOMPARABLE otherwise
- */
-int regex_cmp(struct regex_data * regex1, struct regex_data * regex2);
-/**
- * This function takes the error data returned by regex_prepare_data and turns
- * it in to a human readable error message.
- * If the buffer given to hold the error message is to small it truncates the
- * message and indicates the truncation with an ellipsis ("...") at the end of
- * the buffer.
- *
- * @arg error_data Error data as returned by regex_prepare_data.
- * @arg buffer String buffer to hold the formated error string.
- * @arg buf_size Total size of the given bufer in bytes.
- */
-void regex_format_error(struct regex_error_data const * error_data,
- char * buffer, size_t buf_size);
-#endif /* SRC_REGEX_H_ */
diff --git a/src/selinux_internal.h b/src/selinux_internal.h
deleted file mode 100644
index 5087bb6..0000000
--- a/src/selinux_internal.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#include <selinux/selinux.h>
-#include <pthread.h>
-#include "dso.h"
-
-hidden_proto(selinux_mkload_policy)
- hidden_proto(set_selinuxmnt)
- hidden_proto(security_disable)
- hidden_proto(security_policyvers)
- hidden_proto(security_load_policy)
- hidden_proto(security_get_boolean_active)
- hidden_proto(security_get_boolean_names)
- hidden_proto(security_set_boolean)
- hidden_proto(security_commit_booleans)
- hidden_proto(security_check_context)
- hidden_proto(security_check_context_raw)
- hidden_proto(security_canonicalize_context)
- hidden_proto(security_canonicalize_context_raw)
- hidden_proto(security_compute_av)
- hidden_proto(security_compute_av_raw)
- hidden_proto(security_compute_av_flags)
- hidden_proto(security_compute_av_flags_raw)
- hidden_proto(security_compute_user)
- hidden_proto(security_compute_user_raw)
- hidden_proto(security_compute_create)
- hidden_proto(security_compute_create_raw)
- hidden_proto(security_compute_member_raw)
- hidden_proto(security_compute_relabel_raw)
- hidden_proto(is_selinux_enabled)
- hidden_proto(is_selinux_mls_enabled)
- hidden_proto(freecon)
- hidden_proto(freeconary)
- hidden_proto(getprevcon)
- hidden_proto(getprevcon_raw)
- hidden_proto(getcon)
- hidden_proto(getcon_raw)
- hidden_proto(setcon_raw)
- hidden_proto(getpeercon_raw)
- hidden_proto(getpidcon_raw)
- hidden_proto(getexeccon_raw)
- hidden_proto(getfilecon)
- hidden_proto(getfilecon_raw)
- hidden_proto(lgetfilecon_raw)
- hidden_proto(fgetfilecon_raw)
- hidden_proto(setfilecon_raw)
- hidden_proto(lsetfilecon_raw)
- hidden_proto(fsetfilecon_raw)
- hidden_proto(setexeccon)
- hidden_proto(setexeccon_raw)
- hidden_proto(getfscreatecon_raw)
- hidden_proto(getkeycreatecon_raw)
- hidden_proto(getsockcreatecon_raw)
- hidden_proto(setfscreatecon_raw)
- hidden_proto(setkeycreatecon_raw)
- hidden_proto(setsockcreatecon_raw)
- hidden_proto(security_getenforce)
- hidden_proto(security_setenforce)
- hidden_proto(security_deny_unknown)
- hidden_proto(selinux_binary_policy_path)
- hidden_proto(selinux_default_context_path)
- hidden_proto(selinux_securetty_types_path)
- hidden_proto(selinux_failsafe_context_path)
- hidden_proto(selinux_removable_context_path)
- hidden_proto(selinux_virtual_domain_context_path)
- hidden_proto(selinux_virtual_image_context_path)
- hidden_proto(selinux_file_context_path)
- hidden_proto(selinux_file_context_homedir_path)
- hidden_proto(selinux_file_context_local_path)
- hidden_proto(selinux_file_context_subs_path)
- hidden_proto(selinux_netfilter_context_path)
- hidden_proto(selinux_homedir_context_path)
- hidden_proto(selinux_user_contexts_path)
- hidden_proto(selinux_booleans_path)
- hidden_proto(selinux_customizable_types_path)
- hidden_proto(selinux_media_context_path)
- hidden_proto(selinux_x_context_path)
- hidden_proto(selinux_sepgsql_context_path)
- hidden_proto(selinux_path)
- hidden_proto(selinux_check_passwd_access)
- hidden_proto(selinux_check_securetty_context)
- hidden_proto(matchpathcon_init_prefix)
- hidden_proto(selinux_users_path)
- hidden_proto(selinux_usersconf_path);
-hidden_proto(selinux_translations_path);
-hidden_proto(selinux_colors_path);
-hidden_proto(selinux_getenforcemode);
-hidden_proto(selinux_getpolicytype);
-hidden_proto(selinux_raw_to_trans_context);
-hidden_proto(selinux_trans_to_raw_context);
- hidden_proto(selinux_raw_context_to_color);
-hidden_proto(security_get_initial_context);
-hidden_proto(security_get_initial_context_raw);
-hidden_proto(selinux_reset_config);
-
-extern int selinux_page_size hidden;
-
-/* Make pthread_once optional */
-#pragma weak pthread_once
-#pragma weak pthread_key_create
-#pragma weak pthread_key_delete
-#pragma weak pthread_setspecific
-
-/* Call handler iff the first call. */
-#define __selinux_once(ONCE_CONTROL, INIT_FUNCTION) \
- do { \
- if (pthread_once != NULL) \
- pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \
- else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \
- INIT_FUNCTION (); \
- (ONCE_CONTROL) = 2; \
- } \
- } while (0)
-
-/* Pthread key macros */
-#define __selinux_key_create(KEY, DESTRUCTOR) \
- do { \
- if (pthread_key_create != NULL) \
- pthread_key_create(KEY, DESTRUCTOR); \
- } while (0)
-
-#define __selinux_key_delete(KEY) \
- do { \
- if (pthread_key_delete != NULL) \
- pthread_key_delete(KEY); \
- } while (0)
-
-#define __selinux_setspecific(KEY, VALUE) \
- do { \
- if (pthread_setspecific != NULL) \
- pthread_setspecific(KEY, VALUE); \
- } while (0)
-
-
diff --git a/src/selinux_netlink.h b/src/selinux_netlink.h
deleted file mode 100644
index 88ef551..0000000
--- a/src/selinux_netlink.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Netlink event notifications for SELinux.
- *
- * Author: James Morris <jmorris@redhat.com>
- */
-#ifndef _LINUX_SELINUX_NETLINK_H
-#define _LINUX_SELINUX_NETLINK_H
-
-/* Message types. */
-#define SELNL_MSG_BASE 0x10
-enum {
- SELNL_MSG_SETENFORCE = SELNL_MSG_BASE,
- SELNL_MSG_POLICYLOAD,
- SELNL_MSG_MAX
-};
-
-/* Multicast groups */
-#define SELNL_GRP_NONE 0x00000000
-#define SELNL_GRP_AVC 0x00000001 /* AVC notifications */
-#define SELNL_GRP_ALL 0xffffffff
-
-/* Message structures */
-struct selnl_msg_setenforce {
- int32_t val;
-};
-
-struct selnl_msg_policyload {
- uint32_t seqno;
-};
-
-#endif /* _LINUX_SELINUX_NETLINK_H */
diff --git a/src/sestatus.c b/src/sestatus.c
deleted file mode 100644
index ed29dc5..0000000
--- a/src/sestatus.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * sestatus.c
- *
- * APIs to reference SELinux kernel status page (/selinux/status)
- *
- * Author: KaiGai Kohei <kaigai@ak.jp.nec.com>
- *
- */
-#include <fcntl.h>
-#include <limits.h>
-#include <sched.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include "avc_internal.h"
-#include "policy.h"
-
-/*
- * copied from the selinux/include/security.h
- */
-struct selinux_status_t
-{
- uint32_t version; /* version number of thie structure */
- uint32_t sequence; /* sequence number of seqlock logic */
- uint32_t enforcing; /* current setting of enforcing mode */
- uint32_t policyload; /* times of policy reloaded */
- uint32_t deny_unknown; /* current setting of deny_unknown */
- /* version > 0 support above status */
-} __attribute((packed));
-
-/*
- * `selinux_status'
- *
- * NULL : not initialized yet
- * MAP_FAILED : opened, but fallback-mode
- * Valid Pointer : opened and mapped correctly
- */
-static struct selinux_status_t *selinux_status = NULL;
-static int selinux_status_fd;
-static uint32_t last_seqno;
-
-static uint32_t fallback_sequence;
-static int fallback_enforcing;
-static int fallback_policyload;
-
-/*
- * read_sequence
- *
- * A utility routine to reference kernel status page according to
- * seqlock logic. Since selinux_status->sequence is an odd value during
- * the kernel status page being updated, we try to synchronize completion
- * of this updating, but we assume it is rare.
- * The sequence is almost even number.
- *
- * __sync_synchronize is a portable memory barrier for various kind
- * of architecture that is supported by GCC.
- */
-static inline uint32_t read_sequence(struct selinux_status_t *status)
-{
- uint32_t seqno = 0;
-
- do {
- /*
- * No need for sched_yield() in the first trial of
- * this loop.
- */
- if (seqno & 0x0001)
- sched_yield();
-
- seqno = status->sequence;
-
- __sync_synchronize();
-
- } while (seqno & 0x0001);
-
- return seqno;
-}
-
-/*
- * selinux_status_updated
- *
- * It returns whether something has been happened since the last call.
- * Because `selinux_status->sequence' shall be always incremented on
- * both of setenforce/policyreload events, so differences from the last
- * value informs us something has been happened.
- */
-int selinux_status_updated(void)
-{
- uint32_t curr_seqno;
- int result = 0;
-
- if (selinux_status == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if (selinux_status == MAP_FAILED) {
- if (avc_netlink_check_nb() < 0)
- return -1;
-
- curr_seqno = fallback_sequence;
- } else {
- curr_seqno = read_sequence(selinux_status);
- }
-
- /*
- * `curr_seqno' is always even-number, so it does not match with
- * `last_seqno' being initialized to odd-number in the first call.
- * We never return 'something was updated' in the first call,
- * because this function focuses on status-updating since the last
- * invocation.
- */
- if (last_seqno & 0x0001)
- last_seqno = curr_seqno;
-
- if (last_seqno != curr_seqno)
- {
- last_seqno = curr_seqno;
- result = 1;
- }
- return result;
-}
-
-/*
- * selinux_status_getenforce
- *
- * It returns the current performing mode of SELinux.
- * 1 means currently we run in enforcing mode, or 0 means permissive mode.
- */
-int selinux_status_getenforce(void)
-{
- uint32_t seqno;
- uint32_t enforcing;
-
- if (selinux_status == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if (selinux_status == MAP_FAILED) {
- if (avc_netlink_check_nb() < 0)
- return -1;
-
- return fallback_enforcing;
- }
-
- /* sequence must not be changed during references */
- do {
- seqno = read_sequence(selinux_status);
-
- enforcing = selinux_status->enforcing;
-
- } while (seqno != read_sequence(selinux_status));
-
- return enforcing ? 1 : 0;
-}
-
-/*
- * selinux_status_policyload
- *
- * It returns times of policy reloaded on the running system.
- * Note that it is not a reliable value on fallback-mode until it receives
- * the first event message via netlink socket, so, a correct usage of this
- * value is to compare it with the previous value to detect policy reloaded
- * event.
- */
-int selinux_status_policyload(void)
-{
- uint32_t seqno;
- uint32_t policyload;
-
- if (selinux_status == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if (selinux_status == MAP_FAILED) {
- if (avc_netlink_check_nb() < 0)
- return -1;
-
- return fallback_policyload;
- }
-
- /* sequence must not be changed during references */
- do {
- seqno = read_sequence(selinux_status);
-
- policyload = selinux_status->policyload;
-
- } while (seqno != read_sequence(selinux_status));
-
- return policyload;
-}
-
-/*
- * selinux_status_deny_unknown
- *
- * It returns a guideline to handle undefined object classes or permissions.
- * 0 means SELinux treats policy queries on undefined stuff being allowed,
- * however, 1 means such queries are denied.
- */
-int selinux_status_deny_unknown(void)
-{
- uint32_t seqno;
- uint32_t deny_unknown;
-
- if (selinux_status == NULL) {
- errno = EINVAL;
- return -1;
- }
-
- if (selinux_status == MAP_FAILED)
- return security_deny_unknown();
-
- /* sequence must not be changed during references */
- do {
- seqno = read_sequence(selinux_status);
-
- deny_unknown = selinux_status->deny_unknown;
-
- } while (seqno != read_sequence(selinux_status));
-
- return deny_unknown ? 1 : 0;
-}
-
-/*
- * callback routines for fallback case using netlink socket
- */
-static int fallback_cb_setenforce(int enforcing)
-{
- fallback_sequence += 2;
- fallback_enforcing = enforcing;
-
- return 0;
-}
-
-static int fallback_cb_policyload(int policyload)
-{
- fallback_sequence += 2;
- fallback_policyload = policyload;
-
- return 0;
-}
-
-/*
- * selinux_status_open
- *
- * It tries to open and mmap kernel status page (/selinux/status).
- * Since Linux 2.6.37 or later supports this feature, we may run
- * fallback routine using a netlink socket on older kernels, if
- * the supplied `fallback' is not zero.
- * It returns 0 on success, or -1 on error.
- */
-int selinux_status_open(int fallback)
-{
- int fd;
- char path[PATH_MAX];
- long pagesize;
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- pagesize = sysconf(_SC_PAGESIZE);
- if (pagesize < 0)
- return -1;
-
- snprintf(path, sizeof(path), "%s/status", selinux_mnt);
- fd = open(path, O_RDONLY | O_CLOEXEC);
- if (fd < 0)
- goto error;
-
- selinux_status = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0);
- if (selinux_status == MAP_FAILED) {
- close(fd);
- goto error;
- }
- selinux_status_fd = fd;
- last_seqno = (uint32_t)(-1);
-
- return 0;
-
-error:
- /*
- * If caller wants fallback routine, we try to provide
- * an equivalent functionality using existing netlink
- * socket, although it needs system call invocation to
- * receive event notification.
- */
- if (fallback && avc_netlink_open(0) == 0) {
- union selinux_callback cb;
-
- /* register my callbacks */
- cb.func_setenforce = fallback_cb_setenforce;
- selinux_set_callback(SELINUX_CB_SETENFORCE, cb);
- cb.func_policyload = fallback_cb_policyload;
- selinux_set_callback(SELINUX_CB_POLICYLOAD, cb);
-
- /* mark as fallback mode */
- selinux_status = MAP_FAILED;
- selinux_status_fd = avc_netlink_acquire_fd();
- last_seqno = (uint32_t)(-1);
-
- fallback_sequence = 0;
- fallback_enforcing = security_getenforce();
- fallback_policyload = 0;
-
- return 1;
- }
- selinux_status = NULL;
-
- return -1;
-}
-
-/*
- * selinux_status_close
- *
- * It unmap and close the kernel status page, or close netlink socket
- * if fallback mode.
- */
-void selinux_status_close(void)
-{
- long pagesize;
-
- /* not opened */
- if (selinux_status == NULL)
- return;
-
- /* fallback-mode */
- if (selinux_status == MAP_FAILED)
- {
- avc_netlink_release_fd();
- avc_netlink_close();
- selinux_status = NULL;
- return;
- }
-
- pagesize = sysconf(_SC_PAGESIZE);
- /* not much we can do other than leak memory */
- if (pagesize > 0)
- munmap(selinux_status, pagesize);
- selinux_status = NULL;
-
- close(selinux_status_fd);
- selinux_status_fd = -1;
- last_seqno = (uint32_t)(-1);
-}
diff --git a/src/setenforce.c b/src/setenforce.c
deleted file mode 100644
index e5e7612..0000000
--- a/src/setenforce.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include "selinux_internal.h"
-#include "policy.h"
-#include <stdio.h>
-#include <limits.h>
-
-int security_setenforce(int value)
-{
- int fd, ret;
- char path[PATH_MAX];
- char buf[20];
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return -1;
- }
-
- snprintf(path, sizeof path, "%s/enforce", selinux_mnt);
- fd = open(path, O_RDWR);
- if (fd < 0)
- return -1;
-
- snprintf(buf, sizeof buf, "%d", value);
- ret = write(fd, buf, strlen(buf));
- close(fd);
- if (ret < 0)
- return -1;
-
- return 0;
-}
-
-hidden_def(security_setenforce)
diff --git a/src/setfilecon.c b/src/setfilecon.c
deleted file mode 100644
index 81322f8..0000000
--- a/src/setfilecon.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/xattr.h>
-#include "selinux_internal.h"
-#include "policy.h"
-
-int setfilecon(const char *path, const char *context)
-{
- return setxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1,
- 0);
-}
-
diff --git a/src/stringrep.c b/src/stringrep.c
deleted file mode 100644
index c867222..0000000
--- a/src/stringrep.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * String representation support for classes and permissions.
- */
-#include <sys/stat.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <ctype.h>
-#include "selinux_internal.h"
-#include "policy.h"
-#include "mapping.h"
-
-#define MAXVECTORS 8*sizeof(access_vector_t)
-
-struct discover_class_node {
- char *name;
- security_class_t value;
- char **perms;
-
- struct discover_class_node *next;
-};
-
-static struct discover_class_node *discover_class_cache = NULL;
-
-static struct discover_class_node * get_class_cache_entry_name(const char *s)
-{
- struct discover_class_node *node = discover_class_cache;
-
- for (; node != NULL && strcmp(s,node->name) != 0; node = node->next);
-
- return node;
-}
-
-static struct discover_class_node * get_class_cache_entry_value(security_class_t c)
-{
- struct discover_class_node *node = discover_class_cache;
-
- for (; node != NULL && c != node->value; node = node->next);
-
- return node;
-}
-
-static struct discover_class_node * discover_class(const char *s)
-{
- int fd, ret;
- char path[PATH_MAX];
- char buf[20];
- DIR *dir;
- struct dirent *dentry;
- size_t i;
-
- struct discover_class_node *node;
-
- if (!selinux_mnt) {
- errno = ENOENT;
- return NULL;
- }
-
- /* allocate a node */
- node = malloc(sizeof(struct discover_class_node));
- if (node == NULL)
- return NULL;
-
- /* allocate array for perms */
- node->perms = calloc(MAXVECTORS,sizeof(char*));
- if (node->perms == NULL)
- goto err1;
-
- /* load up the name */
- node->name = strdup(s);
- if (node->name == NULL)
- goto err2;
-
- /* load up class index */
- snprintf(path, sizeof path, "%s/class/%s/index", selinux_mnt,s);
- fd = open(path, O_RDONLY);
- if (fd < 0)
- goto err3;
-
- memset(buf, 0, sizeof(buf));
- ret = read(fd, buf, sizeof(buf) - 1);
- close(fd);
- if (ret < 0)
- goto err3;
-
- if (sscanf(buf, "%hu", &node->value) != 1)
- goto err3;
-
- /* load up permission indicies */
- snprintf(path, sizeof path, "%s/class/%s/perms",selinux_mnt,s);
- dir = opendir(path);
- if (dir == NULL)
- goto err3;
-
- dentry = readdir(dir);
- while (dentry != NULL) {
- unsigned int value;
- struct stat m;
-
- snprintf(path, sizeof path, "%s/class/%s/perms/%s", selinux_mnt,s,dentry->d_name);
- fd = open(path, O_RDONLY | O_CLOEXEC);
- if (fd < 0)
- goto err4;
-
- if (fstat(fd, &m) < 0) {
- close(fd);
- goto err4;
- }
-
- if (m.st_mode & S_IFDIR) {
- close(fd);
- dentry = readdir(dir);
- continue;
- }
-
- memset(buf, 0, sizeof(buf));
- ret = read(fd, buf, sizeof(buf) - 1);
- close(fd);
- if (ret < 0)
- goto err4;
-
- if (sscanf(buf, "%u", &value) != 1)
- goto err4;
-
- if (value == 0 || value > MAXVECTORS)
- goto err4;
-
- node->perms[value-1] = strdup(dentry->d_name);
- if (node->perms[value-1] == NULL)
- goto err4;
-
- dentry = readdir(dir);
- }
- closedir(dir);
-
- node->next = discover_class_cache;
- discover_class_cache = node;
-
- return node;
-
-err4:
- closedir(dir);
- for (i=0; i<MAXVECTORS; i++)
- free(node->perms[i]);
-err3:
- free(node->name);
-err2:
- free(node->perms);
-err1:
- free(node);
- return NULL;
-}
-
-security_class_t string_to_security_class(const char *s)
-{
- struct discover_class_node *node;
-
- node = get_class_cache_entry_name(s);
- if (node == NULL) {
- node = discover_class(s);
-
- if (node == NULL) {
- errno = EINVAL;
- return 0;
- }
- }
-
- return map_class(node->value);
-}
-
-access_vector_t string_to_av_perm(security_class_t tclass, const char *s)
-{
- struct discover_class_node *node;
- security_class_t kclass = unmap_class(tclass);
-
- node = get_class_cache_entry_value(kclass);
- if (node != NULL) {
- size_t i;
- for (i=0; i<MAXVECTORS && node->perms[i] != NULL; i++)
- if (strcmp(node->perms[i],s) == 0)
- return map_perm(tclass, 1<<i);
- }
-
- errno = EINVAL;
- return 0;
-}
-
-const char *security_class_to_string(security_class_t tclass)
-{
- struct discover_class_node *node;
-
- tclass = unmap_class(tclass);
-
- node = get_class_cache_entry_value(tclass);
- if (node)
- return node->name;
- return NULL;
-}
-
-const char *security_av_perm_to_string(security_class_t tclass,
- access_vector_t av)
-{
- struct discover_class_node *node;
- size_t i;
-
- av = unmap_perm(tclass, av);
- tclass = unmap_class(tclass);
-
- node = get_class_cache_entry_value(tclass);
- if (av && node)
- for (i = 0; i<MAXVECTORS; i++)
- if ((1<<i) & av)
- return node->perms[i];
-
- return NULL;
-}
-
-int security_av_string(security_class_t tclass, access_vector_t av, char **res)
-{
- unsigned int i = 0;
- size_t len = 5;
- access_vector_t tmp = av;
- int rc = 0;
- const char *str;
- char *ptr;
-
- /* first pass computes the required length */
- while (tmp) {
- if (tmp & 1) {
- str = security_av_perm_to_string(tclass, av & (1<<i));
- if (str)
- len += strlen(str) + 1;
- else {
- rc = -1;
- errno = EINVAL;
- goto out;
- }
- }
- tmp >>= 1;
- i++;
- }
-
- *res = malloc(len);
- if (!*res) {
- rc = -1;
- goto out;
- }
-
- /* second pass constructs the string */
- i = 0;
- tmp = av;
- ptr = *res;
-
- if (!av) {
- sprintf(ptr, "null");
- goto out;
- }
-
- ptr += sprintf(ptr, "{ ");
- while (tmp) {
- if (tmp & 1)
- ptr += sprintf(ptr, "%s ", security_av_perm_to_string(
- tclass, av & (1<<i)));
- tmp >>= 1;
- i++;
- }
- sprintf(ptr, "}");
-out:
- return rc;
-}
diff --git a/utils/sefcontext_compile.c b/utils/sefcontext_compile.c
deleted file mode 100644
index f88c756..0000000
--- a/utils/sefcontext_compile.c
+++ /dev/null
@@ -1,363 +0,0 @@
-#include <ctype.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <getopt.h>
-#include <limits.h>
-#include <selinux/selinux.h>
-
-#include "../src/label_file.h"
-#include "../src/regex.h"
-
-static int validate_context(char __attribute__ ((unused)) **ctx)
-{
- return 0;
-}
-
-static int process_file(struct selabel_handle *rec, const char *filename)
-{
- unsigned int line_num;
- int rc;
- char *line_buf = NULL;
- size_t line_len = 0;
- FILE *context_file;
- const char *prefix = NULL;
-
- context_file = fopen(filename, "r");
- if (!context_file) {
- fprintf(stderr, "Error opening %s: %s\n",
- filename, strerror(errno));
- return -1;
- }
-
- line_num = 0;
- rc = 0;
- while (getline(&line_buf, &line_len, context_file) > 0) {
- rc = process_line(rec, filename, prefix, line_buf, ++line_num);
- if (rc)
- goto out;
- }
-out:
- free(line_buf);
- fclose(context_file);
- return rc;
-}
-
-/*
- * File Format
- *
- * u32 - magic number
- * u32 - version
- * u32 - length of pcre version EXCLUDING nul
- * char - pcre version string EXCLUDING nul
- * u32 - number of stems
- * ** Stems
- * u32 - length of stem EXCLUDING nul
- * char - stem char array INCLUDING nul
- * u32 - number of regexs
- * ** Regexes
- * u32 - length of upcoming context INCLUDING nul
- * char - char array of the raw context
- * u32 - length of the upcoming regex_str
- * char - char array of the original regex string including the stem.
- * u32 - mode bits for >= SELINUX_COMPILED_FCONTEXT_MODE
- * mode_t for <= SELINUX_COMPILED_FCONTEXT_PCRE_VERS
- * s32 - stemid associated with the regex
- * u32 - spec has meta characters
- * u32 - The specs prefix_len if >= SELINUX_COMPILED_FCONTEXT_PREFIX_LEN
- * u32 - data length of the pcre regex
- * char - a bufer holding the raw pcre regex info
- * u32 - data length of the pcre regex study daya
- * char - a buffer holding the raw pcre regex study data
- */
-static int write_binary_file(struct saved_data *data, int fd)
-{
- struct spec *specs = data->spec_arr;
- FILE *bin_file;
- size_t len;
- uint32_t magic = SELINUX_MAGIC_COMPILED_FCONTEXT;
- uint32_t section_len;
- uint32_t i;
- int rc;
-
- bin_file = fdopen(fd, "w");
- if (!bin_file) {
- perror("fopen output_file");
- exit(EXIT_FAILURE);
- }
-
- /* write some magic number */
- len = fwrite(&magic, sizeof(uint32_t), 1, bin_file);
- if (len != 1)
- goto err;
-
- /* write the version */
- section_len = SELINUX_COMPILED_FCONTEXT_MAX_VERS;
- len = fwrite(&section_len, sizeof(uint32_t), 1, bin_file);
- if (len != 1)
- goto err;
-
- /* write version of the regex back-end */
- if (!regex_version())
- goto err;
- section_len = strlen(regex_version());
- len = fwrite(&section_len, sizeof(uint32_t), 1, bin_file);
- if (len != 1)
- goto err;
- len = fwrite(regex_version(), 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(&section_len, sizeof(uint32_t), 1, bin_file);
- if (len != 1)
- goto err;
-
- for (i = 0; i < section_len; i++) {
- char *stem = data->stem_arr[i].buf;
- uint32_t stem_len = data->stem_arr[i].len;
-
- /* write the strlen (aka no nul) */
- len = fwrite(&stem_len, sizeof(uint32_t), 1, bin_file);
- if (len != 1)
- goto err;
-
- /* include the nul in the file */
- stem_len += 1;
- len = fwrite(stem, sizeof(char), stem_len, bin_file);
- if (len != stem_len)
- goto err;
- }
-
- /* write the number of regexes coming */
- section_len = data->nspec;
- len = fwrite(&section_len, sizeof(uint32_t), 1, bin_file);
- if (len != 1)
- goto err;
-
- for (i = 0; i < section_len; i++) {
- char *context = specs[i].lr.ctx_raw;
- char *regex_str = specs[i].regex_str;
- mode_t mode = specs[i].mode;
- size_t prefix_len = specs[i].prefix_len;
- int32_t stem_id = specs[i].stem_id;
- struct regex_data *re = specs[i].regex;
- uint32_t to_write;
- size_t size;
-
- /* length of the context string (including nul) */
- to_write = strlen(context) + 1;
- len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file);
- if (len != 1)
- goto err;
-
- /* original context strin (including nul) */
- len = fwrite(context, sizeof(char), to_write, bin_file);
- if (len != to_write)
- goto err;
-
- /* length of the original regex string (including nul) */
- to_write = strlen(regex_str) + 1;
- len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file);
- if (len != 1)
- goto err;
-
- /* original regex string */
- len = fwrite(regex_str, sizeof(char), to_write, bin_file);
- if (len != to_write)
- goto err;
-
- /* binary F_MODE bits */
- to_write = mode;
- len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file);
- if (len != 1)
- goto err;
-
- /* stem for this regex (could be -1) */
- len = fwrite(&stem_id, sizeof(stem_id), 1, bin_file);
- if (len != 1)
- goto err;
-
- /* does this spec have a metaChar? */
- to_write = specs[i].hasMetaChars;
- len = fwrite(&to_write, sizeof(to_write), 1, bin_file);
- if (len != 1)
- goto err;
-
- /* For SELINUX_COMPILED_FCONTEXT_PREFIX_LEN */
- to_write = prefix_len;
- len = fwrite(&to_write, sizeof(to_write), 1, bin_file);
- if (len != 1)
- goto err;
-
- /* Write regex related data */
- rc = regex_writef(re, bin_file);
- if (rc < 0)
- goto err;
- }
-
- rc = 0;
-out:
- fclose(bin_file);
- return rc;
-err:
- rc = -1;
- goto out;
-}
-
-static void free_specs(struct saved_data *data)
-{
- struct spec *specs = data->spec_arr;
- unsigned int num_entries = data->nspec;
- unsigned int i;
-
- for (i = 0; i < num_entries; i++) {
- free(specs[i].lr.ctx_raw);
- free(specs[i].lr.ctx_trans);
- free(specs[i].regex_str);
- free(specs[i].type_str);
- regex_data_free(specs[i].regex);
- }
- free(specs);
-
- num_entries = data->num_stems;
- for (i = 0; i < num_entries; i++)
- free(data->stem_arr[i].buf);
- free(data->stem_arr);
-
- memset(data, 0, sizeof(*data));
-}
-
-static void usage(const char *progname)
-{
- fprintf(stderr,
- "usage: %s [-o out_file] fc_file\n"
- "Where:\n\t"
- "-o Optional file name of the PCRE formatted binary\n\t"
- " file to be output. If not specified the default\n\t"
- " will be fc_file with the .bin suffix appended.\n\t"
- "fc_file The text based file contexts file to be processed.\n",
- progname);
- exit(EXIT_FAILURE);
-}
-
-int main(int argc, char *argv[])
-{
- const char *path = NULL;
- const char *out_file = NULL;
- char stack_path[PATH_MAX + 1];
- char *tmp = NULL;
- int fd, rc, opt;
- struct stat buf;
- struct selabel_handle *rec = NULL;
- struct saved_data *data = NULL;
-
- if (argc < 2)
- usage(argv[0]);
-
- while ((opt = getopt(argc, argv, "o:")) > 0) {
- switch (opt) {
- case 'o':
- out_file = optarg;
- break;
- default:
- usage(argv[0]);
- }
- }
-
- if (optind >= argc)
- usage(argv[0]);
-
- path = argv[optind];
- if (stat(path, &buf) < 0) {
- fprintf(stderr, "Can not stat: %s: %m\n", path);
- exit(EXIT_FAILURE);
- }
-
- /* Generate dummy handle for process_line() function */
- rec = (struct selabel_handle *)calloc(1, sizeof(*rec));
- if (!rec) {
- fprintf(stderr, "Failed to calloc handle\n");
- exit(EXIT_FAILURE);
- }
- rec->backend = SELABEL_CTX_FILE;
-
- /* Need to set validation on to get the bin file generated by the
- * process_line function, however as the bin file being generated
- * may not be related to the currently loaded policy (that it
- * would be validated against), then set callback to ignore any
- * validation. */
- rec->validating = 1;
- selinux_set_callback(SELINUX_CB_VALIDATE,
- (union selinux_callback)&validate_context);
-
- data = (struct saved_data *)calloc(1, sizeof(*data));
- if (!data) {
- fprintf(stderr, "Failed to calloc saved_data\n");
- free(rec);
- exit(EXIT_FAILURE);
- }
-
- rec->data = data;
-
- rc = process_file(rec, path);
- if (rc < 0)
- goto err;
-
- rc = sort_specs(data);
- if (rc)
- goto err;
-
- if (out_file)
- rc = snprintf(stack_path, sizeof(stack_path), "%s", out_file);
- else
- rc = snprintf(stack_path, sizeof(stack_path), "%s.bin", path);
-
- if (rc < 0 || rc >= (int)sizeof(stack_path))
- goto err;
-
- tmp = malloc(strlen(stack_path) + 7);
- if (!tmp)
- goto err;
-
- rc = sprintf(tmp, "%sXXXXXX", stack_path);
- if (rc < 0)
- goto err;
-
- fd = mkstemp(tmp);
- if (fd < 0)
- goto err;
-
- rc = fchmod(fd, buf.st_mode);
- if (rc < 0) {
- perror("fchmod failed to set permission on compiled regexs");
- goto err_unlink;
- }
-
- rc = write_binary_file(data, fd);
- if (rc < 0)
- goto err_unlink;
-
- rc = rename(tmp, stack_path);
- if (rc < 0)
- goto err_unlink;
-
- rc = 0;
-out:
- free_specs(data);
- free(rec);
- free(data);
- free(tmp);
- return rc;
-
-err_unlink:
- unlink(tmp);
-err:
- rc = -1;
- goto out;
-}