mirror of
https://github.com/SELinuxProject/selinux
synced 2024-12-23 14:32:08 +00:00
8673854fb8
Throughout libsepol, values taken from sepolicy are used in places where length == 0 or length == <saturated> matter, find and fix these. Also, correct any type mismatches noticed along the way. Signed-off-by: William Roberts <william.c.roberts@intel.com>
345 lines
8.1 KiB
C
345 lines
8.1 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include <sepol/policydb/policydb.h>
|
|
#include <sepol/policydb/services.h>
|
|
#include "context_internal.h"
|
|
|
|
#include "debug.h"
|
|
#include "context.h"
|
|
#include "handle.h"
|
|
#include "mls.h"
|
|
#include "private.h"
|
|
|
|
/* ----- Compatibility ---- */
|
|
int policydb_context_isvalid(const policydb_t * p, const context_struct_t * c)
|
|
{
|
|
|
|
return context_is_valid(p, c);
|
|
}
|
|
|
|
int sepol_check_context(const char *context)
|
|
{
|
|
|
|
return sepol_context_to_sid((const sepol_security_context_t)context,
|
|
strlen(context) + 1, NULL);
|
|
}
|
|
|
|
/* ---- End compatibility --- */
|
|
|
|
/*
|
|
* Return 1 if the fields in the security context
|
|
* structure `c' are valid. Return 0 otherwise.
|
|
*/
|
|
int context_is_valid(const policydb_t * p, const context_struct_t * c)
|
|
{
|
|
|
|
role_datum_t *role;
|
|
user_datum_t *usrdatum;
|
|
ebitmap_t types, roles;
|
|
int ret = 1;
|
|
|
|
ebitmap_init(&types);
|
|
ebitmap_init(&roles);
|
|
if (!c->role || c->role > p->p_roles.nprim)
|
|
return 0;
|
|
|
|
if (!c->user || c->user > p->p_users.nprim)
|
|
return 0;
|
|
|
|
if (!c->type || c->type > p->p_types.nprim)
|
|
return 0;
|
|
|
|
if (c->role != OBJECT_R_VAL) {
|
|
/*
|
|
* Role must be authorized for the type.
|
|
*/
|
|
role = p->role_val_to_struct[c->role - 1];
|
|
if (!role || !ebitmap_get_bit(&role->cache, c->type - 1))
|
|
/* role may not be associated with type */
|
|
return 0;
|
|
|
|
/*
|
|
* User must be authorized for the role.
|
|
*/
|
|
usrdatum = p->user_val_to_struct[c->user - 1];
|
|
if (!usrdatum)
|
|
return 0;
|
|
|
|
if (!ebitmap_get_bit(&usrdatum->cache, c->role - 1))
|
|
/* user may not be associated with role */
|
|
return 0;
|
|
}
|
|
|
|
if (!mls_context_isvalid(p, c))
|
|
return 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Write the security context string representation of
|
|
* the context structure `context' into a dynamically
|
|
* allocated string of the correct size. Set `*scontext'
|
|
* to point to this string and set `*scontext_len' to
|
|
* the length of the string.
|
|
*/
|
|
int context_to_string(sepol_handle_t * handle,
|
|
const policydb_t * policydb,
|
|
const context_struct_t * context,
|
|
char **result, size_t * result_len)
|
|
{
|
|
|
|
char *scontext = NULL;
|
|
size_t scontext_len = 0;
|
|
char *ptr;
|
|
|
|
/* Compute the size of the context. */
|
|
scontext_len +=
|
|
strlen(policydb->p_user_val_to_name[context->user - 1]) + 1;
|
|
scontext_len +=
|
|
strlen(policydb->p_role_val_to_name[context->role - 1]) + 1;
|
|
scontext_len += strlen(policydb->p_type_val_to_name[context->type - 1]);
|
|
scontext_len += mls_compute_context_len(policydb, context);
|
|
|
|
/* We must null terminate the string */
|
|
scontext_len += 1;
|
|
|
|
/* Allocate space for the context; caller must free this space. */
|
|
scontext = malloc(scontext_len);
|
|
if (!scontext)
|
|
goto omem;
|
|
scontext[scontext_len - 1] = '\0';
|
|
|
|
/*
|
|
* Copy the user name, role name and type name into the context.
|
|
*/
|
|
ptr = scontext;
|
|
sprintf(ptr, "%s:%s:%s",
|
|
policydb->p_user_val_to_name[context->user - 1],
|
|
policydb->p_role_val_to_name[context->role - 1],
|
|
policydb->p_type_val_to_name[context->type - 1]);
|
|
|
|
ptr +=
|
|
strlen(policydb->p_user_val_to_name[context->user - 1]) + 1 +
|
|
strlen(policydb->p_role_val_to_name[context->role - 1]) + 1 +
|
|
strlen(policydb->p_type_val_to_name[context->type - 1]);
|
|
|
|
mls_sid_to_context(policydb, context, &ptr);
|
|
|
|
*result = scontext;
|
|
*result_len = scontext_len;
|
|
return STATUS_SUCCESS;
|
|
|
|
omem:
|
|
ERR(handle, "out of memory, could not convert " "context to string");
|
|
free(scontext);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
/*
|
|
* Create a context structure from the given record
|
|
*/
|
|
int context_from_record(sepol_handle_t * handle,
|
|
const policydb_t * policydb,
|
|
context_struct_t ** cptr,
|
|
const sepol_context_t * record)
|
|
{
|
|
|
|
context_struct_t *scontext = NULL;
|
|
user_datum_t *usrdatum;
|
|
role_datum_t *roldatum;
|
|
type_datum_t *typdatum;
|
|
|
|
/* Hashtab keys are not constant - suppress warnings */
|
|
char *user = strdup(sepol_context_get_user(record));
|
|
char *role = strdup(sepol_context_get_role(record));
|
|
char *type = strdup(sepol_context_get_type(record));
|
|
const char *mls = sepol_context_get_mls(record);
|
|
|
|
scontext = (context_struct_t *) malloc(sizeof(context_struct_t));
|
|
if (!user || !role || !type || !scontext) {
|
|
ERR(handle, "out of memory");
|
|
goto err;
|
|
}
|
|
context_init(scontext);
|
|
|
|
/* User */
|
|
usrdatum = (user_datum_t *) hashtab_search(policydb->p_users.table,
|
|
(hashtab_key_t) user);
|
|
if (!usrdatum) {
|
|
ERR(handle, "user %s is not defined", user);
|
|
goto err_destroy;
|
|
}
|
|
scontext->user = usrdatum->s.value;
|
|
|
|
/* Role */
|
|
roldatum = (role_datum_t *) hashtab_search(policydb->p_roles.table,
|
|
(hashtab_key_t) role);
|
|
if (!roldatum) {
|
|
ERR(handle, "role %s is not defined", role);
|
|
goto err_destroy;
|
|
}
|
|
scontext->role = roldatum->s.value;
|
|
|
|
/* Type */
|
|
typdatum = (type_datum_t *) hashtab_search(policydb->p_types.table,
|
|
(hashtab_key_t) type);
|
|
if (!typdatum || typdatum->flavor == TYPE_ATTRIB) {
|
|
ERR(handle, "type %s is not defined", type);
|
|
goto err_destroy;
|
|
}
|
|
scontext->type = typdatum->s.value;
|
|
|
|
/* MLS */
|
|
if (mls && !policydb->mls) {
|
|
ERR(handle, "MLS is disabled, but MLS context \"%s\" found",
|
|
mls);
|
|
goto err_destroy;
|
|
} else if (!mls && policydb->mls) {
|
|
ERR(handle, "MLS is enabled, but no MLS context found");
|
|
goto err_destroy;
|
|
}
|
|
if (mls && (mls_from_string(handle, policydb, mls, scontext) < 0))
|
|
goto err_destroy;
|
|
|
|
/* Validity check */
|
|
if (!context_is_valid(policydb, scontext)) {
|
|
if (mls) {
|
|
ERR(handle,
|
|
"invalid security context: \"%s:%s:%s:%s\"",
|
|
user, role, type, mls);
|
|
} else {
|
|
ERR(handle,
|
|
"invalid security context: \"%s:%s:%s\"",
|
|
user, role, type);
|
|
}
|
|
goto err_destroy;
|
|
}
|
|
|
|
*cptr = scontext;
|
|
free(user);
|
|
free(type);
|
|
free(role);
|
|
return STATUS_SUCCESS;
|
|
|
|
err_destroy:
|
|
errno = EINVAL;
|
|
context_destroy(scontext);
|
|
|
|
err:
|
|
free(scontext);
|
|
free(user);
|
|
free(type);
|
|
free(role);
|
|
ERR(handle, "could not create context structure");
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
/*
|
|
* Create a record from the given context structure
|
|
*/
|
|
int context_to_record(sepol_handle_t * handle,
|
|
const policydb_t * policydb,
|
|
const context_struct_t * context,
|
|
sepol_context_t ** record)
|
|
{
|
|
|
|
sepol_context_t *tmp_record = NULL;
|
|
char *mls = NULL;
|
|
|
|
if (sepol_context_create(handle, &tmp_record) < 0)
|
|
goto err;
|
|
|
|
if (sepol_context_set_user(handle, tmp_record,
|
|
policydb->p_user_val_to_name[context->user -
|
|
1]) < 0)
|
|
goto err;
|
|
|
|
if (sepol_context_set_role(handle, tmp_record,
|
|
policydb->p_role_val_to_name[context->role -
|
|
1]) < 0)
|
|
goto err;
|
|
|
|
if (sepol_context_set_type(handle, tmp_record,
|
|
policydb->p_type_val_to_name[context->type -
|
|
1]) < 0)
|
|
goto err;
|
|
|
|
if (policydb->mls) {
|
|
if (mls_to_string(handle, policydb, context, &mls) < 0)
|
|
goto err;
|
|
|
|
if (sepol_context_set_mls(handle, tmp_record, mls) < 0)
|
|
goto err;
|
|
}
|
|
|
|
free(mls);
|
|
*record = tmp_record;
|
|
return STATUS_SUCCESS;
|
|
|
|
err:
|
|
ERR(handle, "could not create context record");
|
|
sepol_context_free(tmp_record);
|
|
free(mls);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
/*
|
|
* Create a context structure from the provided string.
|
|
*/
|
|
int context_from_string(sepol_handle_t * handle,
|
|
const policydb_t * policydb,
|
|
context_struct_t ** cptr,
|
|
const char *con_str, size_t con_str_len)
|
|
{
|
|
|
|
char *con_cpy = NULL;
|
|
sepol_context_t *ctx_record = NULL;
|
|
|
|
if (zero_or_saturated(con_str_len)) {
|
|
ERR(handle, "Invalid context length");
|
|
goto err;
|
|
}
|
|
|
|
/* sepol_context_from_string expects a NULL-terminated string */
|
|
con_cpy = malloc(con_str_len + 1);
|
|
if (!con_cpy) {
|
|
ERR(handle, "out of memory");
|
|
goto err;
|
|
}
|
|
|
|
memcpy(con_cpy, con_str, con_str_len);
|
|
con_cpy[con_str_len] = '\0';
|
|
|
|
if (sepol_context_from_string(handle, con_cpy, &ctx_record) < 0)
|
|
goto err;
|
|
|
|
/* Now create from the data structure */
|
|
if (context_from_record(handle, policydb, cptr, ctx_record) < 0)
|
|
goto err;
|
|
|
|
free(con_cpy);
|
|
sepol_context_free(ctx_record);
|
|
return STATUS_SUCCESS;
|
|
|
|
err:
|
|
ERR(handle, "could not create context structure");
|
|
free(con_cpy);
|
|
sepol_context_free(ctx_record);
|
|
return STATUS_ERR;
|
|
}
|
|
|
|
int sepol_context_check(sepol_handle_t * handle,
|
|
const sepol_policydb_t * policydb,
|
|
const sepol_context_t * context)
|
|
{
|
|
|
|
context_struct_t *con = NULL;
|
|
int ret = context_from_record(handle, &policydb->p, &con, context);
|
|
context_destroy(con);
|
|
free(con);
|
|
return ret;
|
|
}
|