Commit ff1beacc authored by Nick Kralevich's avatar Nick Kralevich
Browse files

external/libselinux: Delete all files

This repository was removed from the manifest in
https://android-review.googlesource.com/293506. The files in
this stale manifest are polluting search results.

Test: unneeded. Deleting stale files.
Change-Id: I067c23b991b0da88bb61b179c9e00f6c405f5ad1
parent d4828b3b
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.
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)
#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
/*
* 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_ */
#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
/*
* 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_ */
#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
This diff is collapsed.
This diff is collapsed.
/*
* 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;
}
/*
* 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_ */
/*
* 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;
}
/*
* 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_ */
/*
* 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;
}
/*
* 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;
}
/*
* 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_ */
#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;
}
This diff is collapsed.
#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;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment