|
Packit Service |
102278 |
/* Authors: Karl MacMillan <kmacmillan@tresys.com>
|
|
Packit Service |
102278 |
* Joshua Brindle <jbrindle@tresys.com>
|
|
Packit Service |
102278 |
* Jason Tang <jtang@tresys.com>
|
|
Packit Service |
102278 |
* Christopher Ashworth <cashworth@tresys.com>
|
|
Packit Service |
102278 |
* Chris PeBenito <cpebenito@tresys.com>
|
|
Packit Service |
102278 |
* Caleb Case <ccase@tresys.com>
|
|
Packit Service |
102278 |
*
|
|
Packit Service |
102278 |
* Copyright (C) 2004-2006,2009 Tresys Technology, LLC
|
|
Packit Service |
102278 |
* Copyright (C) 2005 Red Hat, Inc.
|
|
Packit Service |
102278 |
*
|
|
Packit Service |
102278 |
* This library is free software; you can redistribute it and/or
|
|
Packit Service |
102278 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit Service |
102278 |
* License as published by the Free Software Foundation; either
|
|
Packit Service |
102278 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit Service |
102278 |
*
|
|
Packit Service |
102278 |
* This library is distributed in the hope that it will be useful,
|
|
Packit Service |
102278 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
102278 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
102278 |
* Lesser General Public License for more details.
|
|
Packit Service |
102278 |
*
|
|
Packit Service |
102278 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
102278 |
* License along with this library; if not, write to the Free Software
|
|
Packit Service |
102278 |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* This file contains semanage routines that manipulate the files on a
|
|
Packit Service |
102278 |
* local module store. Sandbox routines, used by both source and
|
|
Packit Service |
102278 |
* direct connections, are here as well.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
struct dbase_policydb;
|
|
Packit Service |
102278 |
typedef struct dbase_policydb dbase_t;
|
|
Packit Service |
102278 |
#define DBASE_DEFINED
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
#include "semanage_store.h"
|
|
Packit Service |
102278 |
#include "database_policydb.h"
|
|
Packit Service |
102278 |
#include "handle.h"
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
#include <selinux/selinux.h>
|
|
Packit Service |
102278 |
#include <sepol/policydb.h>
|
|
Packit Service |
102278 |
#include <sepol/module.h>
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
#include <assert.h>
|
|
Packit Service |
102278 |
#include <ctype.h>
|
|
Packit Service |
102278 |
#include <dirent.h>
|
|
Packit Service |
102278 |
#include <errno.h>
|
|
Packit Service |
102278 |
#include <fcntl.h>
|
|
Packit Service |
102278 |
#include <stdio.h>
|
|
Packit Service |
102278 |
#include <stdio_ext.h>
|
|
Packit Service |
102278 |
#include <stdlib.h>
|
|
Packit Service |
102278 |
#include <string.h>
|
|
Packit Service |
102278 |
#include <unistd.h>
|
|
Packit Service |
102278 |
#include <sys/file.h>
|
|
Packit Service |
102278 |
#include <sys/stat.h>
|
|
Packit Service |
102278 |
#include <sys/types.h>
|
|
Packit Service |
102278 |
#include <sys/wait.h>
|
|
Packit Service |
102278 |
#include <limits.h>
|
|
Packit Service |
102278 |
#include <libgen.h>
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
#include "debug.h"
|
|
Packit Service |
102278 |
#include "utilities.h"
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
#define SEMANAGE_CONF_FILE "semanage.conf"
|
|
Packit Service |
102278 |
/* relative path names to enum semanage_paths to special files and
|
|
Packit Service |
102278 |
* directories for the module store */
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
#define TRUE 1
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
enum semanage_file_defs {
|
|
Packit Service |
102278 |
SEMANAGE_ROOT,
|
|
Packit Service |
102278 |
SEMANAGE_TRANS_LOCK,
|
|
Packit Service |
102278 |
SEMANAGE_READ_LOCK,
|
|
Packit Service |
102278 |
SEMANAGE_NUM_FILES
|
|
Packit Service |
102278 |
};
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static char *semanage_paths[SEMANAGE_NUM_STORES][SEMANAGE_STORE_NUM_PATHS];
|
|
Packit Service |
102278 |
static char *semanage_files[SEMANAGE_NUM_FILES] = { NULL };
|
|
Packit Service |
102278 |
static int semanage_paths_initialized = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* These are paths relative to the bottom of the module store */
|
|
Packit Service |
102278 |
static const char *semanage_relative_files[SEMANAGE_NUM_FILES] = {
|
|
Packit Service |
102278 |
"",
|
|
Packit Service |
102278 |
"/semanage.trans.LOCK",
|
|
Packit Service |
102278 |
"/semanage.read.LOCK"
|
|
Packit Service |
102278 |
};
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static const char *semanage_store_paths[SEMANAGE_NUM_STORES] = {
|
|
Packit Service |
102278 |
"/active",
|
|
Packit Service |
102278 |
"/previous",
|
|
Packit Service |
102278 |
"/tmp"
|
|
Packit Service |
102278 |
};
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* relative path names to enum sandbox_paths for special files within
|
|
Packit Service |
102278 |
* a sandbox */
|
|
Packit Service |
102278 |
static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
|
|
Packit Service |
102278 |
"",
|
|
Packit Service |
102278 |
"/modules",
|
|
Packit Service |
102278 |
"/policy.linked",
|
|
Packit Service |
102278 |
"/homedir_template",
|
|
Packit Service |
102278 |
"/file_contexts.template",
|
|
Packit Service |
102278 |
"/commit_num",
|
|
Packit Service |
102278 |
"/pkeys.local",
|
|
Packit Service |
102278 |
"/ibendports.local",
|
|
Packit Service |
102278 |
"/ports.local",
|
|
Packit Service |
102278 |
"/interfaces.local",
|
|
Packit Service |
102278 |
"/nodes.local",
|
|
Packit Service |
102278 |
"/booleans.local",
|
|
Packit Service |
102278 |
"/seusers.local",
|
|
Packit Service |
102278 |
"/seusers.linked",
|
|
Packit Service |
102278 |
"/users.local",
|
|
Packit Service |
102278 |
"/users_extra.local",
|
|
Packit Service |
102278 |
"/users_extra.linked",
|
|
Packit Service |
102278 |
"/users_extra",
|
|
Packit Service |
102278 |
"/disable_dontaudit",
|
|
Packit Service |
102278 |
"/preserve_tunables",
|
|
Packit Service |
102278 |
"/modules/disabled",
|
|
Packit Service |
102278 |
"/policy.kern",
|
|
Packit Service |
102278 |
"/file_contexts.local",
|
|
Packit Service |
102278 |
"/file_contexts.homedirs",
|
|
Packit Service |
102278 |
"/file_contexts",
|
|
Packit Service |
102278 |
"/seusers"
|
|
Packit Service |
102278 |
};
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static char const * const semanage_final_prefix[SEMANAGE_FINAL_NUM] = {
|
|
Packit Service |
102278 |
"/final",
|
|
Packit Service |
102278 |
"",
|
|
Packit Service |
102278 |
};
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static char *semanage_final[SEMANAGE_FINAL_NUM] = { NULL };
|
|
Packit Service |
102278 |
static char *semanage_final_suffix[SEMANAGE_FINAL_PATH_NUM] = { NULL };
|
|
Packit Service |
102278 |
static char *semanage_final_paths[SEMANAGE_FINAL_NUM][SEMANAGE_FINAL_PATH_NUM] = {{ NULL }};
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* A node used in a linked list of file contexts; used for sorting.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
typedef struct semanage_file_context_node {
|
|
Packit Service |
102278 |
char *path;
|
|
Packit Service |
102278 |
char *file_type;
|
|
Packit Service |
102278 |
char *context;
|
|
Packit Service |
102278 |
int path_len;
|
|
Packit Service |
102278 |
int effective_len;
|
|
Packit Service |
102278 |
int type_len;
|
|
Packit Service |
102278 |
int context_len;
|
|
Packit Service |
102278 |
int meta; /* position of first meta char in path, -1 if none */
|
|
Packit Service |
102278 |
struct semanage_file_context_node *next;
|
|
Packit Service |
102278 |
} semanage_file_context_node_t;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* A node used in a linked list of buckets that contain
|
|
Packit Service |
102278 |
* semanage_file_context_node lists. Used for sorting.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
typedef struct semanage_file_context_bucket {
|
|
Packit Service |
102278 |
semanage_file_context_node_t *data;
|
|
Packit Service |
102278 |
struct semanage_file_context_bucket *next;
|
|
Packit Service |
102278 |
} semanage_file_context_bucket_t;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* A node used in a linked list of netfilter rules.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
typedef struct semanage_netfilter_context_node {
|
|
Packit Service |
102278 |
char *rule;
|
|
Packit Service |
102278 |
size_t rule_len;
|
|
Packit Service |
102278 |
struct semanage_netfilter_context_node *next;
|
|
Packit Service |
102278 |
} semanage_netfilter_context_node_t;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Initialize the paths to config file, lock files and store root.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static int semanage_init_paths(const char *root)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
size_t len, prefix_len;
|
|
Packit Service |
102278 |
int i;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!root)
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
prefix_len = strlen(root);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < SEMANAGE_NUM_FILES; i++) {
|
|
Packit Service |
102278 |
len = (strlen(semanage_relative_files[i]) + prefix_len);
|
|
Packit Service |
102278 |
semanage_files[i] = calloc(len + 1, sizeof(char));
|
|
Packit Service |
102278 |
if (!semanage_files[i])
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
sprintf(semanage_files[i], "%s%s", root,
|
|
Packit Service |
102278 |
semanage_relative_files[i]);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* This initializes the paths inside the stores, this is only necessary
|
|
Packit Service |
102278 |
* when directly accessing the store
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static int semanage_init_store_paths(const char *root)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int i, j;
|
|
Packit Service |
102278 |
size_t len;
|
|
Packit Service |
102278 |
size_t prefix_len;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!root)
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
prefix_len = strlen(root);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < SEMANAGE_NUM_STORES; i++) {
|
|
Packit Service |
102278 |
for (j = 0; j < SEMANAGE_STORE_NUM_PATHS; j++) {
|
|
Packit Service |
102278 |
len = prefix_len + strlen(semanage_store_paths[i])
|
|
Packit Service |
102278 |
+ strlen(semanage_sandbox_paths[j]);
|
|
Packit Service |
102278 |
semanage_paths[i][j] = calloc(len + 1, sizeof(char));
|
|
Packit Service |
102278 |
if (!semanage_paths[i][j])
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
sprintf(semanage_paths[i][j], "%s%s%s", root,
|
|
Packit Service |
102278 |
semanage_store_paths[i],
|
|
Packit Service |
102278 |
semanage_sandbox_paths[j]);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static int semanage_init_final(semanage_handle_t *sh, const char *prefix)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
assert(sh);
|
|
Packit Service |
102278 |
assert(prefix);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int status = 0;
|
|
Packit Service |
102278 |
size_t len;
|
|
Packit Service |
102278 |
const char *store_path = sh->conf->store_path;
|
|
Packit Service |
102278 |
size_t store_len = strlen(store_path);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* SEMANAGE_FINAL_TMP */
|
|
Packit Service |
102278 |
len = strlen(semanage_root()) +
|
|
Packit Service |
102278 |
strlen(prefix) +
|
|
Packit Service |
102278 |
strlen("/") +
|
|
Packit Service |
102278 |
strlen(semanage_final_prefix[SEMANAGE_FINAL_TMP]) +
|
|
Packit Service |
102278 |
store_len;
|
|
Packit Service |
102278 |
semanage_final[SEMANAGE_FINAL_TMP] = malloc(len + 1);
|
|
Packit Service |
102278 |
if (semanage_final[SEMANAGE_FINAL_TMP] == NULL) {
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
sprintf(semanage_final[SEMANAGE_FINAL_TMP],
|
|
Packit Service |
102278 |
"%s%s%s/%s",
|
|
Packit Service |
102278 |
semanage_root(),
|
|
Packit Service |
102278 |
prefix,
|
|
Packit Service |
102278 |
semanage_final_prefix[SEMANAGE_FINAL_TMP],
|
|
Packit Service |
102278 |
store_path);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* SEMANAGE_FINAL_SELINUX */
|
|
Packit Service |
102278 |
const char *selinux_root = selinux_path();
|
|
Packit Service |
102278 |
len = strlen(semanage_root()) +
|
|
Packit Service |
102278 |
strlen(selinux_root) +
|
|
Packit Service |
102278 |
strlen(semanage_final_prefix[SEMANAGE_FINAL_SELINUX]) +
|
|
Packit Service |
102278 |
store_len;
|
|
Packit Service |
102278 |
semanage_final[SEMANAGE_FINAL_SELINUX] = malloc(len + 1);
|
|
Packit Service |
102278 |
if (semanage_final[SEMANAGE_FINAL_SELINUX] == NULL) {
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
sprintf(semanage_final[SEMANAGE_FINAL_SELINUX],
|
|
Packit Service |
102278 |
"%s%s%s%s",
|
|
Packit Service |
102278 |
semanage_root(),
|
|
Packit Service |
102278 |
selinux_root,
|
|
Packit Service |
102278 |
semanage_final_prefix[SEMANAGE_FINAL_SELINUX],
|
|
Packit Service |
102278 |
store_path);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
if (status != 0) {
|
|
Packit Service |
102278 |
int i;
|
|
Packit Service |
102278 |
for (i = 0; i < SEMANAGE_FINAL_NUM; i++) {
|
|
Packit Service |
102278 |
free(semanage_final[i]);
|
|
Packit Service |
102278 |
semanage_final[i] = NULL;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return status;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static int semanage_init_final_suffix(semanage_handle_t *sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int ret = 0;
|
|
Packit Service |
102278 |
int status = 0;
|
|
Packit Service |
102278 |
char path[PATH_MAX];
|
|
Packit Service |
102278 |
size_t offset = strlen(selinux_policy_root());
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_final_suffix[SEMANAGE_FINAL_TOPLEVEL] = strdup("");
|
|
Packit Service |
102278 |
if (semanage_final_suffix[SEMANAGE_FINAL_TOPLEVEL] == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to allocate space for policy top level path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_final_suffix[SEMANAGE_FC] =
|
|
Packit Service |
102278 |
strdup(selinux_file_context_path() + offset);
|
|
Packit Service |
102278 |
if (semanage_final_suffix[SEMANAGE_FC] == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to allocate space for file context path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (asprintf(&semanage_final_suffix[SEMANAGE_FC_BIN], "%s.bin",
|
|
Packit Service |
102278 |
semanage_final_suffix[SEMANAGE_FC]) < 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to allocate space for file context path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_final_suffix[SEMANAGE_FC_HOMEDIRS] =
|
|
Packit Service |
102278 |
strdup(selinux_file_context_homedir_path() + offset);
|
|
Packit Service |
102278 |
if (semanage_final_suffix[SEMANAGE_FC_HOMEDIRS] == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to allocate space for file context home directory path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (asprintf(&semanage_final_suffix[SEMANAGE_FC_HOMEDIRS_BIN], "%s.bin",
|
|
Packit Service |
102278 |
semanage_final_suffix[SEMANAGE_FC_HOMEDIRS]) < 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to allocate space for file context home directory path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_final_suffix[SEMANAGE_FC_LOCAL] =
|
|
Packit Service |
102278 |
strdup(selinux_file_context_local_path() + offset);
|
|
Packit Service |
102278 |
if (semanage_final_suffix[SEMANAGE_FC_LOCAL] == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to allocate space for local file context path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (asprintf(&semanage_final_suffix[SEMANAGE_FC_LOCAL_BIN], "%s.bin",
|
|
Packit Service |
102278 |
semanage_final_suffix[SEMANAGE_FC_LOCAL]) < 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to allocate space for local file context path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_final_suffix[SEMANAGE_NC] =
|
|
Packit Service |
102278 |
strdup(selinux_netfilter_context_path() + offset);
|
|
Packit Service |
102278 |
if (semanage_final_suffix[SEMANAGE_NC] == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to allocate space for netfilter context path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_final_suffix[SEMANAGE_SEUSERS] =
|
|
Packit Service |
102278 |
strdup(selinux_usersconf_path() + offset);
|
|
Packit Service |
102278 |
if (semanage_final_suffix[SEMANAGE_SEUSERS] == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to allocate space for userconf path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
ret = snprintf(path,
|
|
Packit Service |
102278 |
sizeof(path),
|
|
Packit Service |
102278 |
"%s.%d",
|
|
Packit Service |
102278 |
selinux_binary_policy_path() + offset,
|
|
Packit Service |
102278 |
sh->conf->policyvers);
|
|
Packit Service |
102278 |
if (ret < 0 || ret >= (int)sizeof(path)) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to compose policy binary path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_final_suffix[SEMANAGE_KERNEL] = strdup(path);
|
|
Packit Service |
102278 |
if (semanage_final_suffix[SEMANAGE_KERNEL] == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to allocate space for policy binary path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
if (status != 0) {
|
|
Packit Service |
102278 |
int i;
|
|
Packit Service |
102278 |
for (i = 0; i < SEMANAGE_FINAL_PATH_NUM; i++) {
|
|
Packit Service |
102278 |
free(semanage_final_suffix[i]);
|
|
Packit Service |
102278 |
semanage_final_suffix[i] = NULL;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return status;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Initialize final paths. */
|
|
Packit Service |
102278 |
static int semanage_init_final_paths(semanage_handle_t *sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int status = 0;
|
|
Packit Service |
102278 |
int i, j;
|
|
Packit Service |
102278 |
size_t len;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < SEMANAGE_FINAL_NUM; i++) {
|
|
Packit Service |
102278 |
for (j = 0; j < SEMANAGE_FINAL_PATH_NUM; j++) {
|
|
Packit Service |
102278 |
len = strlen(semanage_final[i])
|
|
Packit Service |
102278 |
+ strlen(semanage_final_suffix[j]);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_final_paths[i][j] = malloc(len + 1);
|
|
Packit Service |
102278 |
if (semanage_final_paths[i][j] == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to allocate space for policy final path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
sprintf(semanage_final_paths[i][j],
|
|
Packit Service |
102278 |
"%s%s",
|
|
Packit Service |
102278 |
semanage_final[i],
|
|
Packit Service |
102278 |
semanage_final_suffix[j]);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
if (status != 0) {
|
|
Packit Service |
102278 |
for (i = 0; i < SEMANAGE_FINAL_NUM; i++) {
|
|
Packit Service |
102278 |
for (j = 0; j < SEMANAGE_FINAL_PATH_NUM; j++) {
|
|
Packit Service |
102278 |
free(semanage_final_paths[i][j]);
|
|
Packit Service |
102278 |
semanage_final_paths[i][j] = NULL;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return status;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* THIS MUST BE THE FIRST FUNCTION CALLED IN THIS LIBRARY. If the
|
|
Packit Service |
102278 |
* library has nnot been initialized yet then call the functions that
|
|
Packit Service |
102278 |
* initialize the path variables. This function does nothing if it
|
|
Packit Service |
102278 |
* was previously called and that call was successful. Return 0 on
|
|
Packit Service |
102278 |
* success, -1 on error.
|
|
Packit Service |
102278 |
*
|
|
Packit Service |
102278 |
* Note that this function is NOT thread-safe.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_check_init(semanage_handle_t *sh, const char *prefix)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int rc;
|
|
Packit Service |
102278 |
if (semanage_paths_initialized == 0) {
|
|
Packit Service |
102278 |
char root[PATH_MAX];
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rc = snprintf(root,
|
|
Packit Service |
102278 |
sizeof(root),
|
|
Packit Service |
102278 |
"%s%s/%s",
|
|
Packit Service |
102278 |
semanage_root(),
|
|
Packit Service |
102278 |
prefix,
|
|
Packit Service |
102278 |
sh->conf->store_path);
|
|
Packit Service |
102278 |
if (rc < 0 || rc >= (int)sizeof(root))
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rc = semanage_init_paths(root);
|
|
Packit Service |
102278 |
if (rc)
|
|
Packit Service |
102278 |
return rc;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rc = semanage_init_store_paths(root);
|
|
Packit Service |
102278 |
if (rc)
|
|
Packit Service |
102278 |
return rc;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rc = semanage_init_final(sh, prefix);
|
|
Packit Service |
102278 |
if (rc)
|
|
Packit Service |
102278 |
return rc;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rc = semanage_init_final_suffix(sh);
|
|
Packit Service |
102278 |
if (rc)
|
|
Packit Service |
102278 |
return rc;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rc = semanage_init_final_paths(sh);
|
|
Packit Service |
102278 |
if (rc)
|
|
Packit Service |
102278 |
return rc;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_paths_initialized = 1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Given a definition number, return a file name from the paths array */
|
|
Packit Service |
102278 |
const char *semanage_fname(enum semanage_sandbox_defs file_enum)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
return semanage_sandbox_paths[file_enum];
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Given a store location (active/previous/tmp) and a definition
|
|
Packit Service |
102278 |
* number, return a fully-qualified path to that file or directory.
|
|
Packit Service |
102278 |
* The caller must not alter the string returned (and hence why this
|
|
Packit Service |
102278 |
* function return type is const).
|
|
Packit Service |
102278 |
*
|
|
Packit Service |
102278 |
* This function shall never return a NULL, assuming that
|
|
Packit Service |
102278 |
* semanage_check_init() was previously called.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
const char *semanage_path(enum semanage_store_defs store,
|
|
Packit Service |
102278 |
enum semanage_sandbox_defs path_name)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
assert(semanage_paths[store][path_name]);
|
|
Packit Service |
102278 |
return semanage_paths[store][path_name];
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Given a store location (tmp or selinux) and a definition
|
|
Packit Service |
102278 |
* number, return a fully-qualified path to that file or directory.
|
|
Packit Service |
102278 |
* The caller must not alter the string returned (and hence why this
|
|
Packit Service |
102278 |
* function return type is const).
|
|
Packit Service |
102278 |
*
|
|
Packit Service |
102278 |
* This function shall never return a NULL, assuming that
|
|
Packit Service |
102278 |
* semanage_check_init() was previously called.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
const char *semanage_final_path(enum semanage_final_defs store,
|
|
Packit Service |
102278 |
enum semanage_final_path_defs path_name)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
assert(semanage_final_paths[store][path_name]);
|
|
Packit Service |
102278 |
return semanage_final_paths[store][path_name];
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Return a fully-qualified path + filename to the semanage
|
|
Packit Service |
102278 |
* configuration file. If semanage.conf file in the semanage
|
|
Packit Service |
102278 |
* root is cannot be read, use the default semanage.conf as a
|
|
Packit Service |
102278 |
* fallback.
|
|
Packit Service |
102278 |
*
|
|
Packit Service |
102278 |
* The caller is responsible for freeing the returned string.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
char *semanage_conf_path(void)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
char *semanage_conf = NULL;
|
|
Packit Service |
102278 |
int len;
|
|
Packit Service |
102278 |
struct stat sb;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
len = strlen(semanage_root()) + strlen(selinux_path()) + strlen(SEMANAGE_CONF_FILE);
|
|
Packit Service |
102278 |
semanage_conf = calloc(len + 1, sizeof(char));
|
|
Packit Service |
102278 |
if (!semanage_conf)
|
|
Packit Service |
102278 |
return NULL;
|
|
Packit Service |
102278 |
snprintf(semanage_conf, len + 1, "%s%s%s", semanage_root(), selinux_path(),
|
|
Packit Service |
102278 |
SEMANAGE_CONF_FILE);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (stat(semanage_conf, &sb) != 0 && errno == ENOENT) {
|
|
Packit Service |
102278 |
snprintf(semanage_conf, len + 1, "%s%s", selinux_path(), SEMANAGE_CONF_FILE);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return semanage_conf;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/**************** functions that create module store ***************/
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Check that the semanage store exists. If 'create' is non-zero then
|
|
Packit Service |
102278 |
* create the directories. Returns 0 if module store exists (either
|
|
Packit Service |
102278 |
* already or just created), -1 if does not exist or could not be
|
|
Packit Service |
102278 |
* read, or -2 if it could not create the store. */
|
|
Packit Service |
102278 |
int semanage_create_store(semanage_handle_t * sh, int create)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
struct stat sb;
|
|
Packit Service |
102278 |
const char *path = semanage_files[SEMANAGE_ROOT];
|
|
Packit Service |
102278 |
int fd;
|
|
Packit Service |
102278 |
mode_t mask;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (stat(path, &sb) == -1) {
|
|
Packit Service |
102278 |
if (errno == ENOENT && create) {
|
|
Packit Service |
102278 |
mask = umask(0077);
|
|
Packit Service |
102278 |
if (mkdir(path, S_IRWXU) == -1) {
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
ERR(sh, "Could not create module store at %s.",
|
|
Packit Service |
102278 |
path);
|
|
Packit Service |
102278 |
return -2;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
if (create)
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"Could not read from module store at %s.",
|
|
Packit Service |
102278 |
path);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
if (!S_ISDIR(sb.st_mode)) {
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"Module store at %s is not a directory.",
|
|
Packit Service |
102278 |
path);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
|
|
Packit Service |
102278 |
if (stat(path, &sb) == -1) {
|
|
Packit Service |
102278 |
if (errno == ENOENT && create) {
|
|
Packit Service |
102278 |
mask = umask(0077);
|
|
Packit Service |
102278 |
if (mkdir(path, S_IRWXU) == -1) {
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"Could not create module store, active subdirectory at %s.",
|
|
Packit Service |
102278 |
path);
|
|
Packit Service |
102278 |
return -2;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"Could not read from module store, active subdirectory at %s.",
|
|
Packit Service |
102278 |
path);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
if (!S_ISDIR(sb.st_mode)) {
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"Module store active subdirectory at %s is not a directory.",
|
|
Packit Service |
102278 |
path);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
|
|
Packit Service |
102278 |
if (stat(path, &sb) == -1) {
|
|
Packit Service |
102278 |
if (errno == ENOENT && create) {
|
|
Packit Service |
102278 |
mask = umask(0077);
|
|
Packit Service |
102278 |
if (mkdir(path, S_IRWXU) == -1) {
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"Could not create module store, active modules subdirectory at %s.",
|
|
Packit Service |
102278 |
path);
|
|
Packit Service |
102278 |
return -2;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"Could not read from module store, active modules subdirectory at %s.",
|
|
Packit Service |
102278 |
path);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
if (!S_ISDIR(sb.st_mode)) {
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"Module store active modules subdirectory at %s is not a directory.",
|
|
Packit Service |
102278 |
path);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
path = semanage_files[SEMANAGE_READ_LOCK];
|
|
Packit Service |
102278 |
if (stat(path, &sb) == -1) {
|
|
Packit Service |
102278 |
if (errno == ENOENT && create) {
|
|
Packit Service |
102278 |
mask = umask(0077);
|
|
Packit Service |
102278 |
if ((fd = creat(path, S_IRUSR | S_IWUSR)) == -1) {
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
ERR(sh, "Could not create lock file at %s.",
|
|
Packit Service |
102278 |
path);
|
|
Packit Service |
102278 |
return -2;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
close(fd);
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
ERR(sh, "Could not read lock file at %s.", path);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
if (!S_ISREG(sb.st_mode)) {
|
|
Packit Service |
102278 |
ERR(sh, "Object at %s is not a lock file.", path);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* returns <0 if the active store cannot be read or doesn't exist
|
|
Packit Service |
102278 |
* 0 if the store exists but the lock file cannot be accessed
|
|
Packit Service |
102278 |
* SEMANAGE_CAN_READ if the store can be read and the lock file used
|
|
Packit Service |
102278 |
* SEMANAGE_CAN_WRITE if the modules directory and binary policy dir can be written to
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_store_access_check(void)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
const char *path;
|
|
Packit Service |
102278 |
int rc = -1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* read access on active store */
|
|
Packit Service |
102278 |
path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
|
|
Packit Service |
102278 |
if (access(path, R_OK | X_OK) != 0)
|
|
Packit Service |
102278 |
goto out;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* we can read the active store meaning it is managed
|
|
Packit Service |
102278 |
* so now we return 0 to indicate no error */
|
|
Packit Service |
102278 |
rc = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* read access on lock file required for locking
|
|
Packit Service |
102278 |
* write access necessary if the lock file does not exist
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
path = semanage_files[SEMANAGE_READ_LOCK];
|
|
Packit Service |
102278 |
if (access(path, R_OK) != 0) {
|
|
Packit Service |
102278 |
if (access(path, F_OK) == 0) {
|
|
Packit Service |
102278 |
goto out;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
path = semanage_files[SEMANAGE_ROOT];
|
|
Packit Service |
102278 |
if (access(path, R_OK | W_OK | X_OK) != 0) {
|
|
Packit Service |
102278 |
goto out;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* everything needed for reading has been checked */
|
|
Packit Service |
102278 |
rc = SEMANAGE_CAN_READ;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* check the modules directory */
|
|
Packit Service |
102278 |
path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
|
|
Packit Service |
102278 |
if (access(path, R_OK | W_OK | X_OK) != 0)
|
|
Packit Service |
102278 |
goto out;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rc = SEMANAGE_CAN_WRITE;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
out:
|
|
Packit Service |
102278 |
return rc;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/********************* other I/O functions *********************/
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Callback used by scandir() to select files. */
|
|
Packit Service |
102278 |
static int semanage_filename_select(const struct dirent *d)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
if (d->d_name[0] == '.'
|
|
Packit Service |
102278 |
&& (d->d_name[1] == '\0'
|
|
Packit Service |
102278 |
|| (d->d_name[1] == '.' && d->d_name[2] == '\0')))
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
return 1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Copies a file from src to dst. If dst already exists then
|
|
Packit Service |
102278 |
* overwrite it. Returns 0 on success, -1 on error. */
|
|
Packit Service |
102278 |
int semanage_copy_file(const char *src, const char *dst, mode_t mode,
|
|
Packit Service |
102278 |
bool syncrequired)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int in, out, retval = 0, amount_read, n, errsv = errno;
|
|
Packit Service |
102278 |
char tmp[PATH_MAX];
|
|
Packit Service |
102278 |
char buf[4192];
|
|
Packit Service |
102278 |
mode_t mask;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
n = snprintf(tmp, PATH_MAX, "%s.tmp", dst);
|
|
Packit Service |
102278 |
if (n < 0 || n >= PATH_MAX)
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if ((in = open(src, O_RDONLY)) == -1) {
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!mode)
|
|
Packit Service |
102278 |
mode = S_IRUSR | S_IWUSR;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
mask = umask(0);
|
|
Packit Service |
102278 |
if ((out = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, mode)) == -1) {
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
errsv = errno;
|
|
Packit Service |
102278 |
close(in);
|
|
Packit Service |
102278 |
retval = -1;
|
|
Packit Service |
102278 |
goto out;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
while (retval == 0 && (amount_read = read(in, buf, sizeof(buf))) > 0) {
|
|
Packit Service |
102278 |
if (write(out, buf, amount_read) != amount_read) {
|
|
Packit Service |
102278 |
if (errno)
|
|
Packit Service |
102278 |
errsv = errno;
|
|
Packit Service |
102278 |
else
|
|
Packit Service |
102278 |
errsv = EIO;
|
|
Packit Service |
102278 |
retval = -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (amount_read < 0) {
|
|
Packit Service |
102278 |
errsv = errno;
|
|
Packit Service |
102278 |
retval = -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
close(in);
|
|
Packit Service |
102278 |
if (syncrequired && fsync(out) < 0) {
|
|
Packit Service |
102278 |
errsv = errno;
|
|
Packit Service |
102278 |
retval = -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (close(out) < 0) {
|
|
Packit Service |
102278 |
errsv = errno;
|
|
Packit Service |
102278 |
retval = -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!retval && rename(tmp, dst) == -1)
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
out:
|
|
Packit Service |
102278 |
errno = errsv;
|
|
Packit Service |
102278 |
return retval;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static int semanage_copy_dir_flags(const char *src, const char *dst, int flag);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Copies all of the files from src to dst, recursing into
|
|
Packit Service |
102278 |
* subdirectories. Returns 0 on success, -1 on error. */
|
|
Packit Service |
102278 |
static int semanage_copy_dir(const char *src, const char *dst)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
return semanage_copy_dir_flags(src, dst, 1);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Copies all of the dirs from src to dst, recursing into
|
|
Packit Service |
102278 |
* subdirectories. If flag == 1, then copy regular files as
|
|
Packit Service |
102278 |
* well. Returns 0 on success, -1 on error. */
|
|
Packit Service |
102278 |
static int semanage_copy_dir_flags(const char *src, const char *dst, int flag)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int i, len = 0, retval = -1;
|
|
Packit Service |
102278 |
struct stat sb;
|
|
Packit Service |
102278 |
struct dirent **names = NULL;
|
|
Packit Service |
102278 |
char path[PATH_MAX], path2[PATH_MAX];
|
|
Packit Service |
102278 |
mode_t mask;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if ((len = scandir(src, &names, semanage_filename_select, NULL)) == -1) {
|
|
Packit Service |
102278 |
fprintf(stderr, "Could not read the contents of %s: %s\n", src, strerror(errno));
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (stat(dst, &sb) != 0) {
|
|
Packit Service |
102278 |
mask = umask(0077);
|
|
Packit Service |
102278 |
if (mkdir(dst, S_IRWXU) != 0) {
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
fprintf(stderr, "Could not create %s: %s\n", dst, strerror(errno));
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < len; i++) {
|
|
Packit Service |
102278 |
snprintf(path, sizeof(path), "%s/%s", src, names[i]->d_name);
|
|
Packit Service |
102278 |
/* stat() to see if this entry is a file or not since
|
|
Packit Service |
102278 |
* d_type isn't set properly on XFS */
|
|
Packit Service |
102278 |
if (stat(path, &sb)) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
snprintf(path2, sizeof(path2), "%s/%s", dst, names[i]->d_name);
|
|
Packit Service |
102278 |
if (S_ISDIR(sb.st_mode)) {
|
|
Packit Service |
102278 |
mask = umask(0077);
|
|
Packit Service |
102278 |
if (mkdir(path2, 0700) == -1 ||
|
|
Packit Service |
102278 |
semanage_copy_dir_flags(path, path2, flag) == -1) {
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
} else if (S_ISREG(sb.st_mode) && flag == 1) {
|
|
Packit Service |
102278 |
mask = umask(0077);
|
|
Packit Service |
102278 |
if (semanage_copy_file(path, path2, sb.st_mode,
|
|
Packit Service |
102278 |
false) < 0) {
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
retval = 0;
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
for (i = 0; names != NULL && i < len; i++) {
|
|
Packit Service |
102278 |
free(names[i]);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
free(names);
|
|
Packit Service |
102278 |
return retval;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Recursively removes the contents of a directory along with the
|
|
Packit Service |
102278 |
* directory itself. Returns 0 on success, non-zero on error. */
|
|
Packit Service |
102278 |
int semanage_remove_directory(const char *path)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
struct dirent **namelist = NULL;
|
|
Packit Service |
102278 |
int num_entries, i;
|
|
Packit Service |
102278 |
if ((num_entries = scandir(path, &namelist, semanage_filename_select,
|
|
Packit Service |
102278 |
NULL)) == -1) {
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
for (i = 0; i < num_entries; i++) {
|
|
Packit Service |
102278 |
char s[PATH_MAX];
|
|
Packit Service |
102278 |
struct stat buf;
|
|
Packit Service |
102278 |
snprintf(s, sizeof(s), "%s/%s", path, namelist[i]->d_name);
|
|
Packit Service |
102278 |
if (stat(s, &buf) == -1) {
|
|
Packit Service |
102278 |
return -2;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (S_ISDIR(buf.st_mode)) {
|
|
Packit Service |
102278 |
int retval;
|
|
Packit Service |
102278 |
if ((retval = semanage_remove_directory(s)) != 0) {
|
|
Packit Service |
102278 |
return retval;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
if (remove(s) == -1) {
|
|
Packit Service |
102278 |
return -3;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
free(namelist[i]);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
free(namelist);
|
|
Packit Service |
102278 |
if (rmdir(path) == -1) {
|
|
Packit Service |
102278 |
return -4;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int semanage_mkpath(semanage_handle_t *sh, const char *path)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
char fn[PATH_MAX];
|
|
Packit Service |
102278 |
char *c;
|
|
Packit Service |
102278 |
int rc = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (strlen(path) >= PATH_MAX) {
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (c = strcpy(fn, path) + 1; *c != '\0'; c++) {
|
|
Packit Service |
102278 |
if (*c != '/') {
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
*c = '\0';
|
|
Packit Service |
102278 |
rc = semanage_mkdir(sh, fn);
|
|
Packit Service |
102278 |
if (rc < 0) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
*c = '/';
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
rc = semanage_mkdir(sh, fn);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
return rc;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int semanage_mkdir(semanage_handle_t *sh, const char *path)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int status = 0;
|
|
Packit Service |
102278 |
struct stat sb;
|
|
Packit Service |
102278 |
mode_t mask;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* check if directory already exists */
|
|
Packit Service |
102278 |
if (stat(path, &sb) != 0) {
|
|
Packit Service |
102278 |
/* make the modules directory */
|
|
Packit Service |
102278 |
mask = umask(0077);
|
|
Packit Service |
102278 |
if (mkdir(path, S_IRWXU) != 0) {
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
ERR(sh, "Cannot make directory at %s", path);
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
else {
|
|
Packit Service |
102278 |
/* check that it really is a directory */
|
|
Packit Service |
102278 |
if (!S_ISDIR(sb.st_mode)) {
|
|
Packit Service |
102278 |
ERR(sh, "Directory path taken by non-directory file at %s.", path);
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
return status;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/********************* sandbox management routines *********************/
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Creates a sandbox for a single client. Returns 0 if a
|
|
Packit Service |
102278 |
* sandbox was created, -1 on error.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_make_sandbox(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
const char *sandbox = semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL);
|
|
Packit Service |
102278 |
struct stat buf;
|
|
Packit Service |
102278 |
int errsv;
|
|
Packit Service |
102278 |
mode_t mask;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (stat(sandbox, &buf) == -1) {
|
|
Packit Service |
102278 |
if (errno != ENOENT) {
|
|
Packit Service |
102278 |
ERR(sh, "Error scanning directory %s.", sandbox);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
errno = 0;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
/* remove the old sandbox */
|
|
Packit Service |
102278 |
if (semanage_remove_directory(sandbox) != 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Error removing old sandbox directory %s.",
|
|
Packit Service |
102278 |
sandbox);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
mask = umask(0077);
|
|
Packit Service |
102278 |
if (mkdir(sandbox, S_IRWXU) == -1 ||
|
|
Packit Service |
102278 |
semanage_copy_dir(semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL),
|
|
Packit Service |
102278 |
sandbox) == -1) {
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
ERR(sh, "Could not copy files to sandbox %s.", sandbox);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
errsv = errno;
|
|
Packit Service |
102278 |
semanage_remove_directory(sandbox);
|
|
Packit Service |
102278 |
errno = errsv;
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Create final temporary space. Returns -1 on error 0 on success. */
|
|
Packit Service |
102278 |
int semanage_make_final(semanage_handle_t *sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int status = 0;
|
|
Packit Service |
102278 |
int ret = 0;
|
|
Packit Service |
102278 |
char fn[PATH_MAX];
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Create tmp dir if it does not exist. */
|
|
Packit Service |
102278 |
ret = snprintf(fn,
|
|
Packit Service |
102278 |
sizeof(fn),
|
|
Packit Service |
102278 |
"%s%s%s",
|
|
Packit Service |
102278 |
semanage_root(),
|
|
Packit Service |
102278 |
sh->conf->store_root_path,
|
|
Packit Service |
102278 |
semanage_final_prefix[SEMANAGE_FINAL_TMP]);
|
|
Packit Service |
102278 |
if (ret < 0 || ret >= (int)sizeof(fn)) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to compose the final tmp path.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
ret = semanage_mkdir(sh, fn);
|
|
Packit Service |
102278 |
if (ret != 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to create temporary directory for final files at %s", fn);
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Delete store specific dir if it exists. */
|
|
Packit Service |
102278 |
ret = semanage_remove_directory(
|
|
Packit Service |
102278 |
semanage_final_path(SEMANAGE_FINAL_TMP,
|
|
Packit Service |
102278 |
SEMANAGE_FINAL_TOPLEVEL));
|
|
Packit Service |
102278 |
if (ret < -1) {
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
// Build final directory structure
|
|
Packit Service |
102278 |
int i;
|
|
Packit Service |
102278 |
for (i = 1; i < SEMANAGE_FINAL_PATH_NUM; i++) {
|
|
Packit Service |
102278 |
if (strlen(semanage_final_path(SEMANAGE_FINAL_TMP, i)) >= sizeof(fn)) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to compose the final paths.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
strcpy(fn, semanage_final_path(SEMANAGE_FINAL_TMP, i));
|
|
Packit Service |
102278 |
ret = semanage_mkpath(sh, dirname(fn));
|
|
Packit Service |
102278 |
if (ret < 0) {
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
return status;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* qsort comparison function for semanage_get_active_modules. */
|
|
Packit Service |
102278 |
static int semanage_get_active_modules_cmp(const void *a, const void *b)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
semanage_module_info_t *aa = (semanage_module_info_t *)a;
|
|
Packit Service |
102278 |
semanage_module_info_t *bb = (semanage_module_info_t *)b;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return strcmp(aa->name, bb->name);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int semanage_get_cil_paths(semanage_handle_t * sh,
|
|
Packit Service |
102278 |
semanage_module_info_t *modinfos,
|
|
Packit Service |
102278 |
int num_modinfos,
|
|
Packit Service |
102278 |
char *** filenames)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
char path[PATH_MAX];
|
|
Packit Service |
102278 |
char **names = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int ret;
|
|
Packit Service |
102278 |
int status = 0;
|
|
Packit Service |
102278 |
int i = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
names = calloc(num_modinfos, sizeof(*names));
|
|
Packit Service |
102278 |
if (names == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Error allocating space for filenames.");
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < num_modinfos; i++) {
|
|
Packit Service |
102278 |
ret = semanage_module_get_path(
|
|
Packit Service |
102278 |
sh,
|
|
Packit Service |
102278 |
&modinfos[i],
|
|
Packit Service |
102278 |
SEMANAGE_MODULE_PATH_CIL,
|
|
Packit Service |
102278 |
path,
|
|
Packit Service |
102278 |
sizeof(path));
|
|
Packit Service |
102278 |
if (ret != 0) {
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
names[i] = strdup(path);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (names[i] == NULL) {
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
if (status != 0) {
|
|
Packit Service |
102278 |
for (i = 0; i < num_modinfos; i++) {
|
|
Packit Service |
102278 |
free(names[i]);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
free(names);
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
*filenames = names;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return status;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Scans the modules directory for the current semanage handler. This
|
|
Packit Service |
102278 |
* might be the active directory or sandbox, depending upon if the
|
|
Packit Service |
102278 |
* handler has a transaction lock. Allocates and fills in *modinfos
|
|
Packit Service |
102278 |
* with an array of module infos; length of array is stored in
|
|
Packit Service |
102278 |
* *num_modules. The caller is responsible for free()ing *modinfos and its
|
|
Packit Service |
102278 |
* individual elements. Upon success returns 0, -1 on error.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_get_active_modules(semanage_handle_t * sh,
|
|
Packit Service |
102278 |
semanage_module_info_t ** modinfo,
|
|
Packit Service |
102278 |
int *num_modules)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
assert(sh);
|
|
Packit Service |
102278 |
assert(modinfo);
|
|
Packit Service |
102278 |
assert(num_modules);
|
|
Packit Service |
102278 |
*modinfo = NULL;
|
|
Packit Service |
102278 |
*num_modules = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int status = 0;
|
|
Packit Service |
102278 |
int ret = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int i = 0;
|
|
Packit Service |
102278 |
int j = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_list_t *list = NULL;
|
|
Packit Service |
102278 |
semanage_list_t *found = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_module_info_t *all_modinfos = NULL;
|
|
Packit Service |
102278 |
int all_modinfos_len = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
void *tmp = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* get all modules */
|
|
Packit Service |
102278 |
ret = semanage_module_list_all(sh, &all_modinfos, &all_modinfos_len);
|
|
Packit Service |
102278 |
if (ret != 0) {
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (all_modinfos_len == 0) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* allocate enough for worst case */
|
|
Packit Service |
102278 |
(*modinfo) = calloc(all_modinfos_len, sizeof(**modinfo));
|
|
Packit Service |
102278 |
if ((*modinfo) == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Error allocating space for module information.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* for each highest priority, enabled module get its path */
|
|
Packit Service |
102278 |
semanage_list_destroy(&list);
|
|
Packit Service |
102278 |
j = 0;
|
|
Packit Service |
102278 |
for (i = 0; i < all_modinfos_len; i++) {
|
|
Packit Service |
102278 |
/* check if enabled */
|
|
Packit Service |
102278 |
if (all_modinfos[i].enabled != 1) continue;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* check if we've seen this before (i.e. highest priority) */
|
|
Packit Service |
102278 |
found = semanage_list_find(list, all_modinfos[i].name);
|
|
Packit Service |
102278 |
if (found == NULL) {
|
|
Packit Service |
102278 |
ret = semanage_list_push(&list, all_modinfos[i].name);
|
|
Packit Service |
102278 |
if (ret != 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Failed to add module name to list of known names.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
else continue;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (semanage_module_info_clone(sh, &all_modinfos[i], &(*modinfo)[j]) != 0) {
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
j += 1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
*num_modules = j;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (j == 0) {
|
|
Packit Service |
102278 |
free(*modinfo);
|
|
Packit Service |
102278 |
*modinfo = NULL;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* realloc the array to its min size */
|
|
Packit Service |
102278 |
tmp = realloc(*modinfo, j * sizeof(**modinfo));
|
|
Packit Service |
102278 |
if (tmp == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Error allocating space for filenames.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
*modinfo = tmp;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* sort array on module name */
|
|
Packit Service |
102278 |
qsort(*modinfo,
|
|
Packit Service |
102278 |
*num_modules,
|
|
Packit Service |
102278 |
sizeof(**modinfo),
|
|
Packit Service |
102278 |
semanage_get_active_modules_cmp);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
semanage_list_destroy(&list);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < all_modinfos_len; i++) {
|
|
Packit Service |
102278 |
semanage_module_info_destroy(sh, &all_modinfos[i]);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
free(all_modinfos);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (status != 0) {
|
|
Packit Service |
102278 |
for (i = 0; i < j; i++) {
|
|
Packit Service |
102278 |
semanage_module_info_destroy(sh, &(*modinfo)[i]);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
free(*modinfo);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return status;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/******************* routines that run external programs *******************/
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Appends a single character to a string. Returns a pointer to the
|
|
Packit Service |
102278 |
* realloc()ated string. If out of memory return NULL; original
|
|
Packit Service |
102278 |
* string will remain untouched.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static char *append(char *s, char c)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
size_t len = (s == NULL ? 0 : strlen(s));
|
|
Packit Service |
102278 |
char *new_s = realloc(s, len + 2);
|
|
Packit Service |
102278 |
if (new_s == NULL) {
|
|
Packit Service |
102278 |
return NULL;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
s = new_s;
|
|
Packit Service |
102278 |
s[len] = c;
|
|
Packit Service |
102278 |
s[len + 1] = '\0';
|
|
Packit Service |
102278 |
return s;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Append string 't' to string 's', realloc()ating 's' as needed. 't'
|
|
Packit Service |
102278 |
* may be safely free()d afterwards. Returns a pointer to the
|
|
Packit Service |
102278 |
* realloc()ated 's'. If out of memory return NULL; original strings
|
|
Packit Service |
102278 |
* will remain untouched.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static char *append_str(char *s, const char *t)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
size_t s_len = (s == NULL ? 0 : strlen(s));
|
|
Packit Service |
102278 |
size_t t_len;
|
|
Packit Service |
102278 |
char *new_s;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (t == NULL) {
|
|
Packit Service |
102278 |
return s;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
t_len = strlen(t);
|
|
Packit Service |
102278 |
new_s = realloc(s, s_len + t_len + 1);
|
|
Packit Service |
102278 |
if (new_s == NULL) {
|
|
Packit Service |
102278 |
return NULL;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
s = new_s;
|
|
Packit Service |
102278 |
memcpy(s + s_len, t, t_len);
|
|
Packit Service |
102278 |
s[s_len + t_len] = '\0';
|
|
Packit Service |
102278 |
return s;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/*
|
|
Packit Service |
102278 |
* Append an argument string to an argument vector. Replaces the
|
|
Packit Service |
102278 |
* argument pointer passed in. Returns -1 on error. Increments
|
|
Packit Service |
102278 |
* 'num_args' on success.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static int append_arg(char ***argv, int *num_args, const char *arg)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
char **a;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
a = realloc(*argv, sizeof(**argv) * (*num_args + 1));
|
|
Packit Service |
102278 |
if (a == NULL)
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
*argv = a;
|
|
Packit Service |
102278 |
a[*num_args] = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (arg) {
|
|
Packit Service |
102278 |
a[*num_args] = strdup(arg);
|
|
Packit Service |
102278 |
if (!a[*num_args])
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
(*num_args)++;
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* free()s all strings within a null-terminated argument vector, as
|
|
Packit Service |
102278 |
* well as the pointer itself. */
|
|
Packit Service |
102278 |
static void free_argv(char **argv)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int i;
|
|
Packit Service |
102278 |
for (i = 0; argv != NULL && argv[i] != NULL; i++) {
|
|
Packit Service |
102278 |
free(argv[i]);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
free(argv);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Take an argument string and split and place into an argument
|
|
Packit Service |
102278 |
* vector. Respect normal quoting, double-quoting, and backslash
|
|
Packit Service |
102278 |
* conventions. Perform substitutions on $@ and $< symbols. Returns
|
|
Packit Service |
102278 |
* a NULL-terminated argument vector; caller is responsible for
|
|
Packit Service |
102278 |
* free()ing the vector and its elements. */
|
|
Packit Service |
102278 |
static char **split_args(const char *arg0, char *arg_string,
|
|
Packit Service |
102278 |
const char *new_name, const char *old_name)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
char **argv = NULL, *s, *arg = NULL, *targ;
|
|
Packit Service |
102278 |
int num_args = 0, in_quote = 0, in_dquote = 0, rc;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
rc = append_arg(&argv, &num_args, arg0);
|
|
Packit Service |
102278 |
if (rc)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
s = arg_string;
|
|
Packit Service |
102278 |
/* parse the argument string one character at a time,
|
|
Packit Service |
102278 |
* repsecting quotes and other special characters */
|
|
Packit Service |
102278 |
while (s != NULL && *s != '\0') {
|
|
Packit Service |
102278 |
switch (*s) {
|
|
Packit Service |
102278 |
case '\\':{
|
|
Packit Service |
102278 |
if (*(s + 1) == '\0') {
|
|
Packit Service |
102278 |
targ = append(arg, '\\');
|
|
Packit Service |
102278 |
if (targ == NULL)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
arg = targ;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
targ = append(arg, *(s + 1));
|
|
Packit Service |
102278 |
if (targ == NULL)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
arg = targ;
|
|
Packit Service |
102278 |
s++;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
case '\'':{
|
|
Packit Service |
102278 |
if (in_dquote) {
|
|
Packit Service |
102278 |
targ = append(arg, *s);
|
|
Packit Service |
102278 |
if (targ == NULL)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
arg = targ;
|
|
Packit Service |
102278 |
} else if (in_quote) {
|
|
Packit Service |
102278 |
in_quote = 0;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
in_quote = 1;
|
|
Packit Service |
102278 |
targ = append(arg, '\0');
|
|
Packit Service |
102278 |
if (targ == NULL)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
arg = targ;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
case '\"':{
|
|
Packit Service |
102278 |
if (in_quote) {
|
|
Packit Service |
102278 |
targ = append(arg, *s);
|
|
Packit Service |
102278 |
if (targ == NULL)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
arg = targ;
|
|
Packit Service |
102278 |
} else if (in_dquote) {
|
|
Packit Service |
102278 |
in_dquote = 0;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
in_dquote = 1;
|
|
Packit Service |
102278 |
targ = append(arg, '\0');
|
|
Packit Service |
102278 |
if (targ == NULL)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
arg = targ;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
case '$':{
|
|
Packit Service |
102278 |
switch (*(s + 1)) {
|
|
Packit Service |
102278 |
case '@':{
|
|
Packit Service |
102278 |
targ = append_str(arg, new_name);
|
|
Packit Service |
102278 |
if (targ == NULL)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
arg = targ;
|
|
Packit Service |
102278 |
s++;
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
case '<':{
|
|
Packit Service |
102278 |
targ = append_str(arg, old_name);
|
|
Packit Service |
102278 |
if (targ == NULL)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
arg = targ;
|
|
Packit Service |
102278 |
s++;
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
default:{
|
|
Packit Service |
102278 |
targ = append(arg, *s);
|
|
Packit Service |
102278 |
if (targ == NULL)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
arg = targ;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
default:{
|
|
Packit Service |
102278 |
if (isspace(*s) && !in_quote && !in_dquote) {
|
|
Packit Service |
102278 |
if (arg != NULL) {
|
|
Packit Service |
102278 |
rc = append_arg(&argv, &num_args, arg);
|
|
Packit Service |
102278 |
if (rc)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
free(arg);
|
|
Packit Service |
102278 |
arg = NULL;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
if ((targ = append(arg, *s)) == NULL) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
arg = targ;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
s++;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (arg != NULL) {
|
|
Packit Service |
102278 |
rc = append_arg(&argv, &num_args, arg);
|
|
Packit Service |
102278 |
if (rc)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
free(arg);
|
|
Packit Service |
102278 |
arg = NULL;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
/* explicitly add a NULL at the end */
|
|
Packit Service |
102278 |
rc = append_arg(&argv, &num_args, NULL);
|
|
Packit Service |
102278 |
if (rc)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
return argv;
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
free_argv(argv);
|
|
Packit Service |
102278 |
free(arg);
|
|
Packit Service |
102278 |
return NULL;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Take the arguments given in v->args and expand any $ macros within.
|
|
Packit Service |
102278 |
* Split the arguments into different strings (argv). Next fork and
|
|
Packit Service |
102278 |
* execute the process. BE SURE THAT ALL FILE DESCRIPTORS ARE SET TO
|
|
Packit Service |
102278 |
* CLOSE-ON-EXEC. Take the return value of the child process and
|
|
Packit Service |
102278 |
* return it, -1 on error.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static int semanage_exec_prog(semanage_handle_t * sh,
|
|
Packit Service |
102278 |
external_prog_t * e, const char *new_name,
|
|
Packit Service |
102278 |
const char *old_name)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
char **argv;
|
|
Packit Service |
102278 |
pid_t forkval;
|
|
Packit Service |
102278 |
int status = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
argv = split_args(e->path, e->args, new_name, old_name);
|
|
Packit Service |
102278 |
if (argv == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Out of memory!");
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* no need to use pthread_atfork() -- child will not be using
|
|
Packit Service |
102278 |
* any mutexes. */
|
|
Packit Service |
102278 |
forkval = vfork();
|
|
Packit Service |
102278 |
if (forkval == 0) {
|
|
Packit Service |
102278 |
/* child process. file descriptors will be closed
|
|
Packit Service |
102278 |
* because they were set as close-on-exec. */
|
|
Packit Service |
102278 |
execve(e->path, argv, NULL);
|
|
Packit Service |
102278 |
_exit(EXIT_FAILURE); /* if execve() failed */
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
free_argv(argv);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (forkval == -1) {
|
|
Packit Service |
102278 |
ERR(sh, "Error while forking process.");
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* parent process. wait for child to finish */
|
|
Packit Service |
102278 |
if (waitpid(forkval, &status, 0) == -1 || !WIFEXITED(status)) {
|
|
Packit Service |
102278 |
ERR(sh, "Child process %s did not exit cleanly.",
|
|
Packit Service |
102278 |
e->path);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
return WEXITSTATUS(status);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* reloads the policy pointed to by the handle, used locally by install
|
|
Packit Service |
102278 |
* and exported for user reload requests */
|
|
Packit Service |
102278 |
int semanage_reload_policy(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int r = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!sh)
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if ((r = semanage_exec_prog(sh, sh->conf->load_policy, "", "")) != 0) {
|
|
Packit Service |
102278 |
ERR(sh, "load_policy returned error code %d.", r);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
return r;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
hidden_def(semanage_reload_policy)
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* This expands the file_context.tmpl file to file_context and homedirs.template */
|
|
Packit Service |
102278 |
int semanage_split_fc(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
FILE *file_con = NULL;
|
|
Packit Service |
102278 |
int fc = -1, hd = -1, retval = -1;
|
|
Packit Service |
102278 |
char buf[PATH_MAX] = { 0 };
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* I use fopen here instead of open so that I can use fgets which only reads a single line */
|
|
Packit Service |
102278 |
file_con = fopen(semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL), "r");
|
|
Packit Service |
102278 |
if (!file_con) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not open %s for reading.",
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL));
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
fc = open(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC),
|
|
Packit Service |
102278 |
O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
|
Packit Service |
102278 |
if (fc < 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not open %s for writing.",
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC));
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
hd = open(semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL),
|
|
Packit Service |
102278 |
O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
|
Packit Service |
102278 |
if (hd < 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not open %s for writing.",
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL));
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
while (fgets_unlocked(buf, PATH_MAX, file_con)) {
|
|
Packit Service |
102278 |
if (!strncmp(buf, "HOME_DIR", 8) ||
|
|
Packit Service |
102278 |
!strncmp(buf, "HOME_ROOT", 9) || strstr(buf, "ROLE") ||
|
|
Packit Service |
102278 |
strstr(buf, "USER")) {
|
|
Packit Service |
102278 |
/* This contains one of the template variables, write it to homedir.template */
|
|
Packit Service |
102278 |
if (write(hd, buf, strlen(buf)) < 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Write to %s failed.",
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_TMP,
|
|
Packit Service |
102278 |
SEMANAGE_HOMEDIR_TMPL));
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
if (write(fc, buf, strlen(buf)) < 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Write to %s failed.",
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC));
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
retval = 0;
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
if (file_con)
|
|
Packit Service |
102278 |
fclose(file_con);
|
|
Packit Service |
102278 |
if (fc >= 0)
|
|
Packit Service |
102278 |
close(fc);
|
|
Packit Service |
102278 |
if (hd >= 0)
|
|
Packit Service |
102278 |
close(hd);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return retval;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static int sefcontext_compile(semanage_handle_t * sh, const char *path) {
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int r;
|
|
Packit Service |
102278 |
struct stat sb;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (stat(path, &sb) < 0) {
|
|
Packit Service |
102278 |
if (errno != ENOENT) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if ((r = semanage_exec_prog(sh, sh->conf->sefcontext_compile, path, "")) != 0) {
|
|
Packit Service |
102278 |
ERR(sh, "sefcontext_compile returned error code %d. Compiling %s", r, path);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static int semanage_validate_and_compile_fcontexts(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int status = -1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sh->do_check_contexts) {
|
|
Packit Service |
102278 |
int ret;
|
|
Packit Service |
102278 |
ret = semanage_exec_prog(
|
|
Packit Service |
102278 |
sh,
|
|
Packit Service |
102278 |
sh->conf->setfiles,
|
|
Packit Service |
102278 |
semanage_final_path(SEMANAGE_FINAL_TMP,
|
|
Packit Service |
102278 |
SEMANAGE_KERNEL),
|
|
Packit Service |
102278 |
semanage_final_path(SEMANAGE_FINAL_TMP,
|
|
Packit Service |
102278 |
SEMANAGE_FC));
|
|
Packit Service |
102278 |
if (ret != 0) {
|
|
Packit Service |
102278 |
ERR(sh, "setfiles returned error code %d.", ret);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sefcontext_compile(sh,
|
|
Packit Service |
102278 |
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC)) != 0) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sefcontext_compile(sh,
|
|
Packit Service |
102278 |
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_LOCAL)) != 0) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sefcontext_compile(sh,
|
|
Packit Service |
102278 |
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_HOMEDIRS)) != 0) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
status = 0;
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
return status;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Load the contexts of the final tmp into the final selinux directory.
|
|
Packit Service |
102278 |
* Return 0 on success, -3 on error.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static int semanage_install_final_tmp(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int status = -3;
|
|
Packit Service |
102278 |
int ret = 0;
|
|
Packit Service |
102278 |
int i = 0;
|
|
Packit Service |
102278 |
const char *src = NULL;
|
|
Packit Service |
102278 |
const char *dst = NULL;
|
|
Packit Service |
102278 |
struct stat sb;
|
|
Packit Service |
102278 |
char fn[PATH_MAX];
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* For each of the final files install it if it exists.
|
|
Packit Service |
102278 |
* i = 1 to avoid copying the top level directory.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
for (i = 1; i < SEMANAGE_FINAL_PATH_NUM; i++) {
|
|
Packit Service |
102278 |
src = semanage_final_path(SEMANAGE_FINAL_TMP, i);
|
|
Packit Service |
102278 |
dst = semanage_final_path(SEMANAGE_FINAL_SELINUX, i);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* skip file if src doesn't exist */
|
|
Packit Service |
102278 |
if (stat(src, &sb) != 0) continue;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* skip genhomedircon if configured */
|
|
Packit Service |
102278 |
if (sh->conf->disable_genhomedircon &&
|
|
Packit Service |
102278 |
i == SEMANAGE_FC_HOMEDIRS) continue;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (strlen(dst) >= sizeof(fn)) {
|
|
Packit Service |
102278 |
ERR(sh, "Unable to compose the final paths.");
|
|
Packit Service |
102278 |
status = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
strcpy(fn, dst);
|
|
Packit Service |
102278 |
ret = semanage_mkpath(sh, dirname(fn));
|
|
Packit Service |
102278 |
if (ret < 0) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
ret = semanage_copy_file(src, dst, sh->conf->file_mode,
|
|
Packit Service |
102278 |
true);
|
|
Packit Service |
102278 |
if (ret < 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not copy %s to %s.", src, dst);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!sh->do_reload)
|
|
Packit Service |
102278 |
goto skip_reload;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* This stats what libselinux says the active store is (according to config)
|
|
Packit Service |
102278 |
* and what we are installing to, to decide if they are the same store. If
|
|
Packit Service |
102278 |
* they are not then we do not reload policy.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
const char *really_active_store = selinux_policy_root();
|
|
Packit Service |
102278 |
struct stat astore;
|
|
Packit Service |
102278 |
struct stat istore;
|
|
Packit Service |
102278 |
const char *storepath = semanage_final_path(SEMANAGE_FINAL_SELINUX,
|
|
Packit Service |
102278 |
SEMANAGE_FINAL_TOPLEVEL);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (stat(really_active_store, &astore) == 0) {
|
|
Packit Service |
102278 |
if (stat(storepath, &istore)) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not stat store path %s.", storepath);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!(astore.st_ino == istore.st_ino &&
|
|
Packit Service |
102278 |
astore.st_dev == istore.st_dev)) {
|
|
Packit Service |
102278 |
/* They are not the same store */
|
|
Packit Service |
102278 |
goto skip_reload;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} else if (errno == ENOENT &&
|
|
Packit Service |
102278 |
strcmp(really_active_store, storepath) != 0) {
|
|
Packit Service |
102278 |
errno = 0;
|
|
Packit Service |
102278 |
goto skip_reload;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (semanage_reload_policy(sh)) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
skip_reload:
|
|
Packit Service |
102278 |
status = 0;
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
return status;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Prepare the sandbox to be installed by making a backup of the
|
|
Packit Service |
102278 |
* current active directory. Then copy the sandbox to the active
|
|
Packit Service |
102278 |
* directory. Return the new commit number on success, negative
|
|
Packit Service |
102278 |
* values on error. */
|
|
Packit Service |
102278 |
static int semanage_commit_sandbox(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int commit_number, fd, retval;
|
|
Packit Service |
102278 |
char write_buf[32];
|
|
Packit Service |
102278 |
const char *commit_filename =
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_TMP, SEMANAGE_COMMIT_NUM_FILE);
|
|
Packit Service |
102278 |
ssize_t amount_written;
|
|
Packit Service |
102278 |
const char *active = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
|
|
Packit Service |
102278 |
const char *backup =
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_PREVIOUS, SEMANAGE_TOPLEVEL);
|
|
Packit Service |
102278 |
const char *sandbox = semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL);
|
|
Packit Service |
102278 |
struct stat buf;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* update the commit number */
|
|
Packit Service |
102278 |
if ((commit_number = semanage_direct_get_serial(sh)) < 0) {
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
commit_number++;
|
|
Packit Service |
102278 |
memset(write_buf, 0, sizeof(write_buf));
|
|
Packit Service |
102278 |
snprintf(write_buf, sizeof(write_buf), "%d", commit_number);
|
|
Packit Service |
102278 |
if ((fd =
|
|
Packit Service |
102278 |
open(commit_filename, O_WRONLY | O_CREAT | O_TRUNC,
|
|
Packit Service |
102278 |
S_IRUSR | S_IWUSR)) == -1) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not open commit number file %s for writing.",
|
|
Packit Service |
102278 |
commit_filename);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
amount_written = write(fd, write_buf, sizeof(write_buf));
|
|
Packit Service |
102278 |
if (amount_written == -1) {
|
|
Packit Service |
102278 |
ERR(sh, "Error while writing commit number to %s.",
|
|
Packit Service |
102278 |
commit_filename);
|
|
Packit Service |
102278 |
close(fd);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
close(fd);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
retval = commit_number;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (semanage_get_active_lock(sh) < 0) {
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
/* make the backup of the current active directory */
|
|
Packit Service |
102278 |
if (stat(backup, &buf) == 0) {
|
|
Packit Service |
102278 |
if (S_ISDIR(buf.st_mode) &&
|
|
Packit Service |
102278 |
semanage_remove_directory(backup) != 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not remove previous backup %s.", backup);
|
|
Packit Service |
102278 |
retval = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} else if (errno != ENOENT) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not stat directory %s.", backup);
|
|
Packit Service |
102278 |
retval = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (rename(active, backup) == -1) {
|
|
Packit Service |
102278 |
ERR(sh, "Error while renaming %s to %s.", active, backup);
|
|
Packit Service |
102278 |
retval = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* clean up some files from the sandbox before install */
|
|
Packit Service |
102278 |
/* remove homedir_template from sandbox */
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (rename(sandbox, active) == -1) {
|
|
Packit Service |
102278 |
ERR(sh, "Error while renaming %s to %s.", sandbox, active);
|
|
Packit Service |
102278 |
/* note that if an error occurs during the next
|
|
Packit Service |
102278 |
* function then the store will be left in an
|
|
Packit Service |
102278 |
* inconsistent state */
|
|
Packit Service |
102278 |
if (rename(backup, active) < 0)
|
|
Packit Service |
102278 |
ERR(sh, "Error while renaming %s back to %s.", backup,
|
|
Packit Service |
102278 |
active);
|
|
Packit Service |
102278 |
retval = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (semanage_install_final_tmp(sh) != 0) {
|
|
Packit Service |
102278 |
/* note that if an error occurs during the next three
|
|
Packit Service |
102278 |
* function then the store will be left in an
|
|
Packit Service |
102278 |
* inconsistent state */
|
|
Packit Service |
102278 |
int errsv = errno;
|
|
Packit Service |
102278 |
if (rename(active, sandbox) < 0)
|
|
Packit Service |
102278 |
ERR(sh, "Error while renaming %s back to %s.", active,
|
|
Packit Service |
102278 |
sandbox);
|
|
Packit Service |
102278 |
else if (rename(backup, active) < 0)
|
|
Packit Service |
102278 |
ERR(sh, "Error while renaming %s back to %s.", backup,
|
|
Packit Service |
102278 |
active);
|
|
Packit Service |
102278 |
else
|
|
Packit Service |
102278 |
semanage_install_final_tmp(sh);
|
|
Packit Service |
102278 |
errno = errsv;
|
|
Packit Service |
102278 |
retval = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!sh->conf->save_previous) {
|
|
Packit Service |
102278 |
int errsv = errno;
|
|
Packit Service |
102278 |
if (semanage_remove_directory(backup) != 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not delete previous directory %s.", backup);
|
|
Packit Service |
102278 |
retval = -1;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
errno = errsv;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
semanage_release_active_lock(sh);
|
|
Packit Service |
102278 |
return retval;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Takes the kernel policy in a sandbox, move it to the active
|
|
Packit Service |
102278 |
* directory, copy it to the binary policy path, then load it. Upon
|
|
Packit Service |
102278 |
* error move the active directory back to the sandbox. This function
|
|
Packit Service |
102278 |
* should be placed within a mutex lock to ensure that it runs
|
|
Packit Service |
102278 |
* atomically. Returns commit number on success, -1 on error.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_install_sandbox(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int retval = -1, commit_num = -1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sh->conf->load_policy == NULL) {
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"No load_policy program specified in configuration file.");
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (sh->conf->setfiles == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "No setfiles program specified in configuration file.");
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sh->conf->sefcontext_compile == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "No sefcontext_compile program specified in configuration file.");
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (semanage_validate_and_compile_fcontexts(sh) < 0)
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if ((commit_num = semanage_commit_sandbox(sh)) < 0) {
|
|
Packit Service |
102278 |
retval = commit_num;
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
retval = commit_num;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
return retval;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/********************* functions that manipulate lock *********************/
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
static int semanage_get_lock(semanage_handle_t * sh,
|
|
Packit Service |
102278 |
const char *lock_name, const char *lock_file)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int fd;
|
|
Packit Service |
102278 |
struct timeval origtime, curtime;
|
|
Packit Service |
102278 |
int got_lock = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if ((fd = open(lock_file, O_RDONLY)) == -1) {
|
|
Packit Service |
102278 |
if ((fd =
|
|
Packit Service |
102278 |
open(lock_file, O_RDWR | O_CREAT | O_TRUNC,
|
|
Packit Service |
102278 |
S_IRUSR | S_IWUSR)) == -1) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not open direct %s at %s.", lock_name,
|
|
Packit Service |
102278 |
lock_file);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not set close-on-exec for %s at %s.", lock_name,
|
|
Packit Service |
102278 |
lock_file);
|
|
Packit Service |
102278 |
close(fd);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sh->timeout == 0) {
|
|
Packit Service |
102278 |
/* return immediately */
|
|
Packit Service |
102278 |
origtime.tv_sec = 0;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
origtime.tv_sec = sh->timeout;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
origtime.tv_usec = 0;
|
|
Packit Service |
102278 |
do {
|
|
Packit Service |
102278 |
curtime.tv_sec = 1;
|
|
Packit Service |
102278 |
curtime.tv_usec = 0;
|
|
Packit Service |
102278 |
if (flock(fd, LOCK_EX | LOCK_NB) == 0) {
|
|
Packit Service |
102278 |
got_lock = 1;
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
} else if (errno != EAGAIN) {
|
|
Packit Service |
102278 |
ERR(sh, "Error obtaining direct %s at %s.", lock_name,
|
|
Packit Service |
102278 |
lock_file);
|
|
Packit Service |
102278 |
close(fd);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (origtime.tv_sec > 0 || sh->timeout == -1) {
|
|
Packit Service |
102278 |
if (select(0, NULL, NULL, NULL, &curtime) == -1) {
|
|
Packit Service |
102278 |
if (errno == EINTR) {
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"Error while waiting to get direct %s at %s.",
|
|
Packit Service |
102278 |
lock_name, lock_file);
|
|
Packit Service |
102278 |
close(fd);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
origtime.tv_sec--;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} while (origtime.tv_sec > 0 || sh->timeout == -1);
|
|
Packit Service |
102278 |
if (!got_lock) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not get direct %s at %s.", lock_name, lock_file);
|
|
Packit Service |
102278 |
close(fd);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
return fd;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Locking for the module store for transactions. This is very basic
|
|
Packit Service |
102278 |
* locking of the module store and doesn't do anything if the module
|
|
Packit Service |
102278 |
* store is being manipulated with a program not using this library
|
|
Packit Service |
102278 |
* (but the policy should prevent that). Returns 0 on success, -1 if
|
|
Packit Service |
102278 |
* it could not obtain a lock.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_get_trans_lock(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
const char *lock_file = semanage_files[SEMANAGE_TRANS_LOCK];
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sh->u.direct.translock_file_fd >= 0)
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
sh->u.direct.translock_file_fd =
|
|
Packit Service |
102278 |
semanage_get_lock(sh, "transaction lock", lock_file);
|
|
Packit Service |
102278 |
if (sh->u.direct.translock_file_fd >= 0) {
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Locking for the module store for active store reading; this also includes
|
|
Packit Service |
102278 |
* the file containing the commit number. This is very basic locking
|
|
Packit Service |
102278 |
* of the module store and doesn't do anything if the module store is
|
|
Packit Service |
102278 |
* being manipulated with a program not using this library (but the
|
|
Packit Service |
102278 |
* policy should prevent that). Returns 0 on success, -1 if it could
|
|
Packit Service |
102278 |
* not obtain a lock.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_get_active_lock(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
const char *lock_file = semanage_files[SEMANAGE_READ_LOCK];
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sh->u.direct.activelock_file_fd >= 0)
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
sh->u.direct.activelock_file_fd =
|
|
Packit Service |
102278 |
semanage_get_lock(sh, "read lock", lock_file);
|
|
Packit Service |
102278 |
if (sh->u.direct.activelock_file_fd >= 0) {
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Releases the transaction lock. Does nothing if there was not one already
|
|
Packit Service |
102278 |
* there. */
|
|
Packit Service |
102278 |
void semanage_release_trans_lock(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int errsv = errno;
|
|
Packit Service |
102278 |
if (sh->u.direct.translock_file_fd >= 0) {
|
|
Packit Service |
102278 |
flock(sh->u.direct.translock_file_fd, LOCK_UN);
|
|
Packit Service |
102278 |
close(sh->u.direct.translock_file_fd);
|
|
Packit Service |
102278 |
sh->u.direct.translock_file_fd = -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
errno = errsv;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Releases the read lock. Does nothing if there was not one already
|
|
Packit Service |
102278 |
* there. */
|
|
Packit Service |
102278 |
void semanage_release_active_lock(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int errsv = errno;
|
|
Packit Service |
102278 |
if (sh->u.direct.activelock_file_fd >= 0) {
|
|
Packit Service |
102278 |
flock(sh->u.direct.activelock_file_fd, LOCK_UN);
|
|
Packit Service |
102278 |
close(sh->u.direct.activelock_file_fd);
|
|
Packit Service |
102278 |
sh->u.direct.activelock_file_fd = -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
errno = errsv;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Read the current commit number from the commit number file which
|
|
Packit Service |
102278 |
* the handle is pointing, resetting the file pointer afterwards.
|
|
Packit Service |
102278 |
* Return it (a non-negative number), or -1 on error. */
|
|
Packit Service |
102278 |
int semanage_direct_get_serial(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
char buf[32];
|
|
Packit Service |
102278 |
int fd, commit_number;
|
|
Packit Service |
102278 |
ssize_t amount_read;
|
|
Packit Service |
102278 |
const char *commit_filename;
|
|
Packit Service |
102278 |
memset(buf, 0, sizeof(buf));
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sh->is_in_transaction) {
|
|
Packit Service |
102278 |
commit_filename =
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_TMP, SEMANAGE_COMMIT_NUM_FILE);
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
commit_filename =
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_COMMIT_NUM_FILE);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if ((fd = open(commit_filename, O_RDONLY)) == -1) {
|
|
Packit Service |
102278 |
if (errno == ENOENT) {
|
|
Packit Service |
102278 |
/* the commit number file does not exist yet,
|
|
Packit Service |
102278 |
* so assume that the number is 0 */
|
|
Packit Service |
102278 |
errno = 0;
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
ERR(sh, "Could not open commit number file %s.",
|
|
Packit Service |
102278 |
commit_filename);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
amount_read = read(fd, buf, sizeof(buf));
|
|
Packit Service |
102278 |
if (amount_read == -1) {
|
|
Packit Service |
102278 |
ERR(sh, "Error while reading commit number from %s.",
|
|
Packit Service |
102278 |
commit_filename);
|
|
Packit Service |
102278 |
commit_number = -1;
|
|
Packit Service |
102278 |
} else if (sscanf(buf, "%d", &commit_number) != 1) {
|
|
Packit Service |
102278 |
/* if nothing was read, assume that the commit number is 0 */
|
|
Packit Service |
102278 |
commit_number = 0;
|
|
Packit Service |
102278 |
} else if (commit_number < 0) {
|
|
Packit Service |
102278 |
/* read file ought never have negative values */
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"Commit number file %s is corrupted; it should only contain a non-negative integer.",
|
|
Packit Service |
102278 |
commit_filename);
|
|
Packit Service |
102278 |
commit_number = -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
close(fd);
|
|
Packit Service |
102278 |
return commit_number;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* HIGHER LEVEL COMMIT FUNCTIONS */
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int semanage_load_files(semanage_handle_t * sh, cil_db_t *cildb, char **filenames, int numfiles)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int retval = 0;
|
|
Packit Service |
102278 |
FILE *fp;
|
|
Packit Service |
102278 |
ssize_t size;
|
|
Packit Service |
102278 |
char *data = NULL;
|
|
Packit Service |
102278 |
char *filename;
|
|
Packit Service |
102278 |
int i;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < numfiles; i++) {
|
|
Packit Service |
102278 |
filename = filenames[i];
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if ((fp = fopen(filename, "rb")) == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not open module file %s for reading.", filename);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if ((size = bunzip(sh, fp, &data)) <= 0) {
|
|
Packit Service |
102278 |
rewind(fp);
|
|
Packit Service |
102278 |
__fsetlocking(fp, FSETLOCKING_BYCALLER);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (fseek(fp, 0, SEEK_END) != 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Failed to determine size of file %s.", filename);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
size = ftell(fp);
|
|
Packit Service |
102278 |
rewind(fp);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
data = malloc(size);
|
|
Packit Service |
102278 |
if (fread(data, size, 1, fp) != 1) {
|
|
Packit Service |
102278 |
ERR(sh, "Failed to read file %s.", filename);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
fclose(fp);
|
|
Packit Service |
102278 |
fp = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
retval = cil_add_file(cildb, filename, data, size);
|
|
Packit Service |
102278 |
if (retval != SEPOL_OK) {
|
|
Packit Service |
102278 |
ERR(sh, "Error while reading from file %s.", filename);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
free(data);
|
|
Packit Service |
102278 |
data = NULL;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return retval;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
if (fp != NULL) {
|
|
Packit Service |
102278 |
fclose(fp);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
free(data);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/*
|
|
Packit Service |
102278 |
* Expands the policy contained within *base
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/**
|
|
Packit Service |
102278 |
* Read the policy from the sandbox (linked or kernel)
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_read_policydb(semanage_handle_t * sh, sepol_policydb_t * in,
|
|
Packit Service |
102278 |
enum semanage_sandbox_defs file)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int retval = STATUS_ERR;
|
|
Packit Service |
102278 |
const char *kernel_filename = NULL;
|
|
Packit Service |
102278 |
struct sepol_policy_file *pf = NULL;
|
|
Packit Service |
102278 |
FILE *infile = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if ((kernel_filename =
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_ACTIVE, file)) == NULL) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if ((infile = fopen(kernel_filename, "r")) == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not open kernel policy %s for reading.",
|
|
Packit Service |
102278 |
kernel_filename);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
__fsetlocking(infile, FSETLOCKING_BYCALLER);
|
|
Packit Service |
102278 |
if (sepol_policy_file_create(&pf)) {
|
|
Packit Service |
102278 |
ERR(sh, "Out of memory!");
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
sepol_policy_file_set_fp(pf, infile);
|
|
Packit Service |
102278 |
sepol_policy_file_set_handle(pf, sh->sepolh);
|
|
Packit Service |
102278 |
if (sepol_policydb_read(in, pf) == -1) {
|
|
Packit Service |
102278 |
ERR(sh, "Error while reading kernel policy from %s.",
|
|
Packit Service |
102278 |
kernel_filename);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
retval = STATUS_SUCCESS;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
if (infile != NULL) {
|
|
Packit Service |
102278 |
fclose(infile);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
sepol_policy_file_free(pf);
|
|
Packit Service |
102278 |
return retval;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
/**
|
|
Packit Service |
102278 |
* Writes the policy to the sandbox (linked or kernel)
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_write_policydb(semanage_handle_t * sh, sepol_policydb_t * out,
|
|
Packit Service |
102278 |
enum semanage_sandbox_defs file)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
int retval = STATUS_ERR;
|
|
Packit Service |
102278 |
const char *kernel_filename = NULL;
|
|
Packit Service |
102278 |
struct sepol_policy_file *pf = NULL;
|
|
Packit Service |
102278 |
FILE *outfile = NULL;
|
|
Packit Service |
102278 |
mode_t mask = umask(0077);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if ((kernel_filename =
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_TMP, file)) == NULL) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if ((outfile = fopen(kernel_filename, "wb")) == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Could not open kernel policy %s for writing.",
|
|
Packit Service |
102278 |
kernel_filename);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
__fsetlocking(outfile, FSETLOCKING_BYCALLER);
|
|
Packit Service |
102278 |
if (sepol_policy_file_create(&pf)) {
|
|
Packit Service |
102278 |
ERR(sh, "Out of memory!");
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
sepol_policy_file_set_fp(pf, outfile);
|
|
Packit Service |
102278 |
sepol_policy_file_set_handle(pf, sh->sepolh);
|
|
Packit Service |
102278 |
if (sepol_policydb_write(out, pf) == -1) {
|
|
Packit Service |
102278 |
ERR(sh, "Error while writing kernel policy to %s.",
|
|
Packit Service |
102278 |
kernel_filename);
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
retval = STATUS_SUCCESS;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
if (outfile != NULL) {
|
|
Packit Service |
102278 |
fclose(outfile);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
umask(mask);
|
|
Packit Service |
102278 |
sepol_policy_file_free(pf);
|
|
Packit Service |
102278 |
return retval;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Execute the module verification programs for each source module.
|
|
Packit Service |
102278 |
* Returns 0 if every verifier returned success, -1 on error.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_verify_modules(semanage_handle_t * sh,
|
|
Packit Service |
102278 |
char **module_filenames, int num_modules)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int i, retval;
|
|
Packit Service |
102278 |
semanage_conf_t *conf = sh->conf;
|
|
Packit Service |
102278 |
if (conf->mod_prog == NULL) {
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
for (i = 0; i < num_modules; i++) {
|
|
Packit Service |
102278 |
char *module = module_filenames[i];
|
|
Packit Service |
102278 |
external_prog_t *e;
|
|
Packit Service |
102278 |
for (e = conf->mod_prog; e != NULL; e = e->next) {
|
|
Packit Service |
102278 |
if ((retval =
|
|
Packit Service |
102278 |
semanage_exec_prog(sh, e, module, "$<")) != 0) {
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Execute the linker verification programs for the linked (but not
|
|
Packit Service |
102278 |
* expanded) base. Returns 0 if every verifier returned success, -1
|
|
Packit Service |
102278 |
* on error.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_verify_linked(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
external_prog_t *e;
|
|
Packit Service |
102278 |
semanage_conf_t *conf = sh->conf;
|
|
Packit Service |
102278 |
const char *linked_filename =
|
|
Packit Service |
102278 |
semanage_path(SEMANAGE_TMP, SEMANAGE_LINKED);
|
|
Packit Service |
102278 |
int retval = -1;
|
|
Packit Service |
102278 |
if (conf->linked_prog == NULL) {
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
for (e = conf->linked_prog; e != NULL; e = e->next) {
|
|
Packit Service |
102278 |
if (semanage_exec_prog(sh, e, linked_filename, "$<") != 0) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
retval = 0;
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
return retval;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Execute each of the kernel verification programs. Returns 0 if
|
|
Packit Service |
102278 |
* every verifier returned success, -1 on error.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_verify_kernel(semanage_handle_t * sh)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int retval = -1;
|
|
Packit Service |
102278 |
const char *kernel_filename =
|
|
Packit Service |
102278 |
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL);
|
|
Packit Service |
102278 |
semanage_conf_t *conf = sh->conf;
|
|
Packit Service |
102278 |
external_prog_t *e;
|
|
Packit Service |
102278 |
if (conf->kernel_prog == NULL) {
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
for (e = conf->kernel_prog; e != NULL; e = e->next) {
|
|
Packit Service |
102278 |
if (semanage_exec_prog(sh, e, kernel_filename, "$<") != 0) {
|
|
Packit Service |
102278 |
goto cleanup;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
retval = 0;
|
|
Packit Service |
102278 |
cleanup:
|
|
Packit Service |
102278 |
return retval;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/********************* functions that sort file contexts *********************/
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Free the given node. */
|
|
Packit Service |
102278 |
static void semanage_fc_node_destroy(semanage_file_context_node_t * x)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
free(x->path);
|
|
Packit Service |
102278 |
free(x->file_type);
|
|
Packit Service |
102278 |
free(x->context);
|
|
Packit Service |
102278 |
free(x);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Free the linked list of nodes starting at the given node. */
|
|
Packit Service |
102278 |
static void semanage_fc_node_list_destroy(semanage_file_context_node_t * x)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
semanage_file_context_node_t *temp;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
while (x) {
|
|
Packit Service |
102278 |
temp = x;
|
|
Packit Service |
102278 |
x = x->next;
|
|
Packit Service |
102278 |
semanage_fc_node_destroy(temp);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Free the linked list of buckets (and their node lists)
|
|
Packit Service |
102278 |
* starting at the given bucket. */
|
|
Packit Service |
102278 |
static void semanage_fc_bucket_list_destroy(semanage_file_context_bucket_t * x)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
semanage_file_context_bucket_t *temp;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
while (x) {
|
|
Packit Service |
102278 |
temp = x;
|
|
Packit Service |
102278 |
x = x->next;
|
|
Packit Service |
102278 |
semanage_fc_node_list_destroy(temp->data);
|
|
Packit Service |
102278 |
free(temp);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Compares two file contexts' regular expressions and returns:
|
|
Packit Service |
102278 |
* -1 if a is less specific than b
|
|
Packit Service |
102278 |
* 0 if a and be are equally specific
|
|
Packit Service |
102278 |
* 1 if a is more specific than b
|
|
Packit Service |
102278 |
* The comparison is based on the following heuristics,
|
|
Packit Service |
102278 |
* in order from most important to least important, given a and b:
|
|
Packit Service |
102278 |
* If a is a regular expression and b is not,
|
|
Packit Service |
102278 |
* -> a is less specific than b.
|
|
Packit Service |
102278 |
* If a's stem length is shorter than b's stem length,
|
|
Packit Service |
102278 |
* -> a is less specific than b.
|
|
Packit Service |
102278 |
* If a's string length is shorter than b's string length,
|
|
Packit Service |
102278 |
* -> a is less specific than b.
|
|
Packit Service |
102278 |
* If a does not have a specified type and b does not,
|
|
Packit Service |
102278 |
* -> a is less specific than b.
|
|
Packit Service |
102278 |
* FIXME: These heuristics are imperfect, but good enough for
|
|
Packit Service |
102278 |
* now. A proper comparison would determine which (if either)
|
|
Packit Service |
102278 |
* regular expression is a subset of the other.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static int semanage_fc_compare(semanage_file_context_node_t * a,
|
|
Packit Service |
102278 |
semanage_file_context_node_t * b)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int a_has_meta = (a->meta >= 0);
|
|
Packit Service |
102278 |
int b_has_meta = (b->meta >= 0);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Check to see if either a or b are regexes
|
|
Packit Service |
102278 |
* and the other isn't. */
|
|
Packit Service |
102278 |
if (a_has_meta && !b_has_meta)
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
if (b_has_meta && !a_has_meta)
|
|
Packit Service |
102278 |
return 1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Check to see if either a or b have a shorter stem
|
|
Packit Service |
102278 |
* length than the other. */
|
|
Packit Service |
102278 |
if (a->meta < b->meta)
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
if (b->meta < a->meta)
|
|
Packit Service |
102278 |
return 1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Check to see if either a or b have a shorter string
|
|
Packit Service |
102278 |
* length than the other. */
|
|
Packit Service |
102278 |
if (a->effective_len < b->effective_len)
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
if (b->effective_len < a->effective_len)
|
|
Packit Service |
102278 |
return 1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Check to see if either a or b has a specified type
|
|
Packit Service |
102278 |
* and the other doesn't. */
|
|
Packit Service |
102278 |
if (!a->file_type && b->file_type)
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
if (!b->file_type && a->file_type)
|
|
Packit Service |
102278 |
return 1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* If none of the above conditions were satisfied,
|
|
Packit Service |
102278 |
* then a and b are equally specific. */
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Merges two sorted file context linked lists into a single sorted one.
|
|
Packit Service |
102278 |
* The left list is assumed to represent nodes that came first in the original ordering.
|
|
Packit Service |
102278 |
* The final sorted list is returned.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static semanage_file_context_node_t
|
|
Packit Service |
102278 |
* semanage_fc_merge(semanage_file_context_node_t * left,
|
|
Packit Service |
102278 |
semanage_file_context_node_t * right)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
semanage_file_context_node_t *head;
|
|
Packit Service |
102278 |
semanage_file_context_node_t *current;
|
|
Packit Service |
102278 |
semanage_file_context_node_t *tail;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!left)
|
|
Packit Service |
102278 |
return right;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!right)
|
|
Packit Service |
102278 |
return left;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (semanage_fc_compare(left, right) == 1) {
|
|
Packit Service |
102278 |
head = tail = right;
|
|
Packit Service |
102278 |
right = right->next;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
head = tail = left;
|
|
Packit Service |
102278 |
left = left->next;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
while (left && right) {
|
|
Packit Service |
102278 |
/* if left was more specific than right,
|
|
Packit Service |
102278 |
* insert right before left. Otherwise leave order alone. */
|
|
Packit Service |
102278 |
if (semanage_fc_compare(left, right) == 1) {
|
|
Packit Service |
102278 |
current = right;
|
|
Packit Service |
102278 |
right = right->next;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
current = left;
|
|
Packit Service |
102278 |
left = left->next;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
tail = tail->next = current;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
tail->next = (left != NULL) ? left : right;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return head;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Sorts file contexts from least specific to most specific.
|
|
Packit Service |
102278 |
* A bucket linked list is passed in. Upon completion,
|
|
Packit Service |
102278 |
* there is only one bucket (pointed to by master) that
|
|
Packit Service |
102278 |
* contains a linked list of all the file contexts in sorted order.
|
|
Packit Service |
102278 |
* Explanation of the algorithm:
|
|
Packit Service |
102278 |
* This is a stable implementation of an iterative merge sort.
|
|
Packit Service |
102278 |
* Each bucket initially has a linked list of file contexts
|
|
Packit Service |
102278 |
* that are 1 node long.
|
|
Packit Service |
102278 |
* Each pass, buckets (and the nodes they contain) are merged
|
|
Packit Service |
102278 |
* two at time.
|
|
Packit Service |
102278 |
* Buckets are merged until there is only one bucket left,
|
|
Packit Service |
102278 |
* containing the list of file contexts, sorted.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static void semanage_fc_merge_sort(semanage_file_context_bucket_t * master)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
semanage_file_context_bucket_t *current;
|
|
Packit Service |
102278 |
semanage_file_context_bucket_t *temp;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Loop until master is the only bucket left.
|
|
Packit Service |
102278 |
* When we stop master contains the sorted list. */
|
|
Packit Service |
102278 |
while (master->next) {
|
|
Packit Service |
102278 |
current = master;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Merge buckets two-by-two.
|
|
Packit Service |
102278 |
* If there is an odd number of buckets, the last
|
|
Packit Service |
102278 |
* bucket will be left alone, which corresponds
|
|
Packit Service |
102278 |
* to the operation of merging it with an empty bucket. */
|
|
Packit Service |
102278 |
while (current) {
|
|
Packit Service |
102278 |
if (current->next) {
|
|
Packit Service |
102278 |
current->data =
|
|
Packit Service |
102278 |
semanage_fc_merge(current->data,
|
|
Packit Service |
102278 |
current->next->data);
|
|
Packit Service |
102278 |
temp = current->next;
|
|
Packit Service |
102278 |
current->next = current->next->next;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Free the (now empty) second bucket.
|
|
Packit Service |
102278 |
* (This does not touch the node list
|
|
Packit Service |
102278 |
* in the bucket because it has been
|
|
Packit Service |
102278 |
* shifted over to the first bucket. */
|
|
Packit Service |
102278 |
free(temp);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
current = current->next;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Compute the location of the first regular expression
|
|
Packit Service |
102278 |
* meta character in the path of the given node, if it exists.
|
|
Packit Service |
102278 |
* On return:
|
|
Packit Service |
102278 |
* fc_node->meta = position of meta character, if it exists
|
|
Packit Service |
102278 |
* (-1 corresponds to no character)
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static void semanage_fc_find_meta(semanage_file_context_node_t * fc_node)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
int c = 0;
|
|
Packit Service |
102278 |
int escape_chars = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
fc_node->meta = -1;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Note: this while loop has been adapted from
|
|
Packit Service |
102278 |
* spec_hasMetaChars in matchpathcon.c from
|
|
Packit Service |
102278 |
* libselinux-1.22. */
|
|
Packit Service |
102278 |
while (fc_node->path[c] != '\0') {
|
|
Packit Service |
102278 |
switch (fc_node->path[c]) {
|
|
Packit Service |
102278 |
case '.':
|
|
Packit Service |
102278 |
case '^':
|
|
Packit Service |
102278 |
case '$':
|
|
Packit Service |
102278 |
case '?':
|
|
Packit Service |
102278 |
case '*':
|
|
Packit Service |
102278 |
case '+':
|
|
Packit Service |
102278 |
case '|':
|
|
Packit Service |
102278 |
case '[':
|
|
Packit Service |
102278 |
case '(':
|
|
Packit Service |
102278 |
case '{':
|
|
Packit Service |
102278 |
fc_node->meta = c - escape_chars;
|
|
Packit Service |
102278 |
return;
|
|
Packit Service |
102278 |
case '\\':
|
|
Packit Service |
102278 |
/* If an escape character is found,
|
|
Packit Service |
102278 |
* skip the next character. */
|
|
Packit Service |
102278 |
c++;
|
|
Packit Service |
102278 |
escape_chars++;
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
c++;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Replicates strchr, but limits search to buf_len characters. */
|
|
Packit Service |
102278 |
static char *semanage_strnchr(const char *buf, size_t buf_len, char c)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
size_t idx = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (buf == NULL)
|
|
Packit Service |
102278 |
return NULL;
|
|
Packit Service |
102278 |
if (buf_len <= 0)
|
|
Packit Service |
102278 |
return NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
while (idx < buf_len) {
|
|
Packit Service |
102278 |
if (buf[idx] == c)
|
|
Packit Service |
102278 |
return (char *)buf + idx;
|
|
Packit Service |
102278 |
idx++;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return NULL;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Returns a pointer to the end of line character in the given buffer.
|
|
Packit Service |
102278 |
* Used in the context of a file context char buffer that we will be
|
|
Packit Service |
102278 |
* parsing and sorting.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
static char *semanage_get_line_end(const char *buf, size_t buf_len)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
char *line_end = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (buf == NULL)
|
|
Packit Service |
102278 |
return NULL;
|
|
Packit Service |
102278 |
if (buf_len <= 0)
|
|
Packit Service |
102278 |
return NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
line_end = semanage_strnchr(buf, buf_len, '\n');
|
|
Packit Service |
102278 |
if (!line_end)
|
|
Packit Service |
102278 |
line_end = semanage_strnchr(buf, buf_len, '\r');
|
|
Packit Service |
102278 |
if (!line_end)
|
|
Packit Service |
102278 |
line_end = semanage_strnchr(buf, buf_len, EOF);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return line_end;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Entry function for sorting a set of file context lines.
|
|
Packit Service |
102278 |
* Returns 0 on success, -1 on failure.
|
|
Packit Service |
102278 |
* Allocates a buffer pointed to by sorted_buf that contains the sorted lines.
|
|
Packit Service |
102278 |
* sorted_buf_len is set to the size of this buffer.
|
|
Packit Service |
102278 |
* This buffer is guaranteed to have a final \0 character.
|
|
Packit Service |
102278 |
* This buffer must be released by the caller.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_fc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len,
|
|
Packit Service |
102278 |
char **sorted_buf, size_t * sorted_buf_len)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
size_t start, finish, regex_len, type_len, context_len;
|
|
Packit Service |
102278 |
size_t line_len, buf_remainder, i;
|
|
Packit Service |
102278 |
ssize_t sanity_check;
|
|
Packit Service |
102278 |
const char *line_buf, *line_end;
|
|
Packit Service |
102278 |
char *sorted_buf_pos;
|
|
Packit Service |
102278 |
int escape_chars, just_saw_escape;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
semanage_file_context_node_t *temp;
|
|
Packit Service |
102278 |
semanage_file_context_node_t *head;
|
|
Packit Service |
102278 |
semanage_file_context_node_t *current;
|
|
Packit Service |
102278 |
semanage_file_context_bucket_t *master;
|
|
Packit Service |
102278 |
semanage_file_context_bucket_t *bcurrent;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
i = 0;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sh == NULL) {
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (buf == NULL) {
|
|
Packit Service |
102278 |
ERR(sh, "Received NULL buffer.");
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (buf_len <= 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Received buffer of length 0.");
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Initialize the head of the linked list
|
|
Packit Service |
102278 |
* that will contain a node for each file context line. */
|
|
Packit Service |
102278 |
head = current =
|
|
Packit Service |
102278 |
(semanage_file_context_node_t *) calloc(1,
|
|
Packit Service |
102278 |
sizeof
|
|
Packit Service |
102278 |
(semanage_file_context_node_t));
|
|
Packit Service |
102278 |
if (!head) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure allocating memory.");
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Parse the char buffer into a semanage_file_context_node_t linked list. */
|
|
Packit Service |
102278 |
line_buf = buf;
|
|
Packit Service |
102278 |
buf_remainder = buf_len;
|
|
Packit Service |
102278 |
while ((line_end = semanage_get_line_end(line_buf, buf_remainder))) {
|
|
Packit Service |
102278 |
line_len = line_end - line_buf + 1;
|
|
Packit Service |
102278 |
sanity_check = buf_remainder - line_len;
|
|
Packit Service |
102278 |
buf_remainder = buf_remainder - line_len;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (sanity_check < 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure parsing file context buffer.");
|
|
Packit Service |
102278 |
semanage_fc_node_list_destroy(head);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (line_len == 0 || line_len == 1) {
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Skip the whitespace at the front of the line. */
|
|
Packit Service |
102278 |
for (i = 0; i < line_len; i++) {
|
|
Packit Service |
102278 |
if (!isspace(line_buf[i]))
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Check for a blank line. */
|
|
Packit Service |
102278 |
if (i >= line_len) {
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Check if the line is a comment. */
|
|
Packit Service |
102278 |
if (line_buf[i] == '#') {
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Allocate a new node. */
|
|
Packit Service |
102278 |
temp =
|
|
Packit Service |
102278 |
(semanage_file_context_node_t *) calloc(1,
|
|
Packit Service |
102278 |
sizeof
|
|
Packit Service |
102278 |
(semanage_file_context_node_t));
|
|
Packit Service |
102278 |
if (!temp) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure allocating memory.");
|
|
Packit Service |
102278 |
semanage_fc_node_list_destroy(head);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
temp->next = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Extract the regular expression from the line. */
|
|
Packit Service |
102278 |
escape_chars = 0;
|
|
Packit Service |
102278 |
just_saw_escape = 0;
|
|
Packit Service |
102278 |
start = i;
|
|
Packit Service |
102278 |
while (i < line_len && (!isspace(line_buf[i]))) {
|
|
Packit Service |
102278 |
if (line_buf[i] == '\\') {
|
|
Packit Service |
102278 |
if (!just_saw_escape) {
|
|
Packit Service |
102278 |
escape_chars++;
|
|
Packit Service |
102278 |
just_saw_escape = 1;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
/* We're looking at an escaped
|
|
Packit Service |
102278 |
escape. Reset our flag. */
|
|
Packit Service |
102278 |
just_saw_escape = 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
just_saw_escape = 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
i++;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
finish = i;
|
|
Packit Service |
102278 |
regex_len = finish - start;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (regex_len == 0) {
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"WARNING: semanage_fc_sort: Regex of length 0.");
|
|
Packit Service |
102278 |
semanage_fc_node_destroy(temp);
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
temp->path = (char *)strndup(&line_buf[start], regex_len);
|
|
Packit Service |
102278 |
if (!temp->path) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure allocating memory.");
|
|
Packit Service |
102278 |
semanage_fc_node_destroy(temp);
|
|
Packit Service |
102278 |
semanage_fc_node_list_destroy(head);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Skip the whitespace after the regular expression. */
|
|
Packit Service |
102278 |
for (; i < line_len; i++) {
|
|
Packit Service |
102278 |
if (!isspace(line_buf[i]))
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (i == line_len) {
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"WARNING: semanage_fc_sort: Incomplete context. %s", temp->path);
|
|
Packit Service |
102278 |
semanage_fc_node_destroy(temp);
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Extract the inode type from the line (if it exists). */
|
|
Packit Service |
102278 |
if (line_buf[i] == '-') {
|
|
Packit Service |
102278 |
type_len = 2; /* defined as '--', '-d', '-f', etc. */
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (i + type_len >= line_len) {
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"WARNING: semanage_fc_sort: Incomplete context. %s", temp->path);
|
|
Packit Service |
102278 |
semanage_fc_node_destroy(temp);
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Record the inode type. */
|
|
Packit Service |
102278 |
temp->file_type =
|
|
Packit Service |
102278 |
(char *)strndup(&line_buf[i], type_len);
|
|
Packit Service |
102278 |
if (!temp->file_type) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure allocating memory.");
|
|
Packit Service |
102278 |
semanage_fc_node_destroy(temp);
|
|
Packit Service |
102278 |
semanage_fc_node_list_destroy(head);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
i += type_len;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Skip the whitespace after the type. */
|
|
Packit Service |
102278 |
for (; i < line_len; i++) {
|
|
Packit Service |
102278 |
if (!isspace(line_buf[i]))
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
if (i == line_len) {
|
|
Packit Service |
102278 |
ERR(sh,
|
|
Packit Service |
102278 |
"WARNING: semanage_fc_sort: Incomplete context. %s", temp->path);
|
|
Packit Service |
102278 |
semanage_fc_node_destroy(temp);
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
type_len = 0; /* inode type did not exist in the file context */
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Extract the context from the line. */
|
|
Packit Service |
102278 |
start = i;
|
|
Packit Service |
102278 |
while (i < line_len && (!isspace(line_buf[i])))
|
|
Packit Service |
102278 |
i++;
|
|
Packit Service |
102278 |
finish = i;
|
|
Packit Service |
102278 |
context_len = finish - start;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
temp->context = (char *)strndup(&line_buf[start], context_len);
|
|
Packit Service |
102278 |
if (!temp->context) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure allocating memory.");
|
|
Packit Service |
102278 |
semanage_fc_node_destroy(temp);
|
|
Packit Service |
102278 |
semanage_fc_node_list_destroy(head);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Initialize the data about the file context. */
|
|
Packit Service |
102278 |
temp->path_len = regex_len;
|
|
Packit Service |
102278 |
temp->effective_len = regex_len - escape_chars;
|
|
Packit Service |
102278 |
temp->type_len = type_len;
|
|
Packit Service |
102278 |
temp->context_len = context_len;
|
|
Packit Service |
102278 |
semanage_fc_find_meta(temp);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Add this node to the end of the linked list. */
|
|
Packit Service |
102278 |
current->next = temp;
|
|
Packit Service |
102278 |
current = current->next;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Create the bucket linked list from the node linked list. */
|
|
Packit Service |
102278 |
current = head->next;
|
|
Packit Service |
102278 |
bcurrent = master = (semanage_file_context_bucket_t *)
|
|
Packit Service |
102278 |
calloc(1, sizeof(semanage_file_context_bucket_t));
|
|
Packit Service |
102278 |
if (!master) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure allocating memory.");
|
|
Packit Service |
102278 |
semanage_fc_node_list_destroy(head);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Free the head node, as it is no longer used. */
|
|
Packit Service |
102278 |
semanage_fc_node_destroy(head);
|
|
Packit Service |
102278 |
head = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Place each node into a bucket. */
|
|
Packit Service |
102278 |
while (current) {
|
|
Packit Service |
102278 |
bcurrent->data = current;
|
|
Packit Service |
102278 |
current = current->next;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Detach the node in the bucket from the old list. */
|
|
Packit Service |
102278 |
bcurrent->data->next = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* If we need another bucket, add one to the end. */
|
|
Packit Service |
102278 |
if (current) {
|
|
Packit Service |
102278 |
bcurrent->next = (semanage_file_context_bucket_t *)
|
|
Packit Service |
102278 |
calloc(1, sizeof(semanage_file_context_bucket_t));
|
|
Packit Service |
102278 |
if (!(bcurrent->next)) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure allocating memory.");
|
|
Packit Service |
102278 |
semanage_fc_bucket_list_destroy(master);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
bcurrent = bcurrent->next;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Sort the bucket list. */
|
|
Packit Service |
102278 |
semanage_fc_merge_sort(master);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* First, calculate how much space we'll need for
|
|
Packit Service |
102278 |
* the newly sorted block of data. (We don't just
|
|
Packit Service |
102278 |
* use buf_len for this because we have extracted
|
|
Packit Service |
102278 |
* comments and whitespace.) */
|
|
Packit Service |
102278 |
i = 0;
|
|
Packit Service |
102278 |
current = master->data;
|
|
Packit Service |
102278 |
while (current) {
|
|
Packit Service |
102278 |
i += current->path_len + 1; /* +1 for a tab */
|
|
Packit Service |
102278 |
if (current->file_type) {
|
|
Packit Service |
102278 |
i += current->type_len + 1; /* +1 for a tab */
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
i += current->context_len + 1; /* +1 for a newline */
|
|
Packit Service |
102278 |
current = current->next;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
i = i + 1; /* +1 for trailing \0 */
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Allocate the buffer for the sorted list. */
|
|
Packit Service |
102278 |
*sorted_buf = calloc(i, sizeof(char));
|
|
Packit Service |
102278 |
if (!*sorted_buf) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure allocating memory.");
|
|
Packit Service |
102278 |
semanage_fc_bucket_list_destroy(master);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
*sorted_buf_len = i;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Output the sorted semanage_file_context linked list to the char buffer. */
|
|
Packit Service |
102278 |
sorted_buf_pos = *sorted_buf;
|
|
Packit Service |
102278 |
current = master->data;
|
|
Packit Service |
102278 |
while (current) {
|
|
Packit Service |
102278 |
/* Output the path. */
|
|
Packit Service |
102278 |
i = current->path_len + 1; /* +1 for tab */
|
|
Packit Service |
102278 |
snprintf(sorted_buf_pos, i + 1, "%s\t", current->path);
|
|
Packit Service |
102278 |
sorted_buf_pos = sorted_buf_pos + i;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Output the type, if there is one. */
|
|
Packit Service |
102278 |
if (current->file_type) {
|
|
Packit Service |
102278 |
i = strlen(current->file_type) + 1; /* +1 for tab */
|
|
Packit Service |
102278 |
snprintf(sorted_buf_pos, i + 1, "%s\t",
|
|
Packit Service |
102278 |
current->file_type);
|
|
Packit Service |
102278 |
sorted_buf_pos = sorted_buf_pos + i;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Output the context. */
|
|
Packit Service |
102278 |
i = strlen(current->context) + 1; /* +1 for newline */
|
|
Packit Service |
102278 |
snprintf(sorted_buf_pos, i + 1, "%s\n", current->context);
|
|
Packit Service |
102278 |
sorted_buf_pos = sorted_buf_pos + i;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
current = current->next;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Clean up. */
|
|
Packit Service |
102278 |
semanage_fc_bucket_list_destroy(master);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Sanity check. */
|
|
Packit Service |
102278 |
sorted_buf_pos++;
|
|
Packit Service |
102278 |
if ((sorted_buf_pos - *sorted_buf) != (ssize_t) * sorted_buf_len) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure writing sorted buffer.");
|
|
Packit Service |
102278 |
free(*sorted_buf);
|
|
Packit Service |
102278 |
*sorted_buf = NULL;
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/********************* functions that sort netfilter contexts *********************/
|
|
Packit Service |
102278 |
#define NC_SORT_NAMES { "pre", "base", "module", "local", "post" }
|
|
Packit Service |
102278 |
#define NC_SORT_NAMES_LEN { 3, 4, 6, 5, 4 }
|
|
Packit Service |
102278 |
#define NC_SORT_NEL 5
|
|
Packit Service |
102278 |
static void semanage_nc_destroy_ruletab(semanage_netfilter_context_node_t *
|
|
Packit Service |
102278 |
ruletab[NC_SORT_NEL][2])
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
semanage_netfilter_context_node_t *curr, *next;
|
|
Packit Service |
102278 |
int i;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
for (i = 0; i < NC_SORT_NEL; i++) {
|
|
Packit Service |
102278 |
for (curr = ruletab[i][0]; curr != NULL; curr = next) {
|
|
Packit Service |
102278 |
next = curr->next;
|
|
Packit Service |
102278 |
free(curr->rule);
|
|
Packit Service |
102278 |
free(curr);
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Entry function for sorting a set of netfilter context lines.
|
|
Packit Service |
102278 |
* Returns 0 on success, -1 on failure.
|
|
Packit Service |
102278 |
* Allocates a buffer pointed to by sorted_buf that contains the sorted lines.
|
|
Packit Service |
102278 |
* sorted_buf_len is set to the size of this buffer.
|
|
Packit Service |
102278 |
* This buffer is guaranteed to have a final \0 character.
|
|
Packit Service |
102278 |
* This buffer must be released by the caller.
|
|
Packit Service |
102278 |
*/
|
|
Packit Service |
102278 |
int semanage_nc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len,
|
|
Packit Service |
102278 |
char **sorted_buf, size_t * sorted_buf_len)
|
|
Packit Service |
102278 |
{
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* parsing bits */
|
|
Packit Service |
102278 |
const char *priority_names[] = NC_SORT_NAMES;
|
|
Packit Service |
102278 |
const int priority_names_len[] = NC_SORT_NAMES_LEN;
|
|
Packit Service |
102278 |
size_t line_len, buf_remainder, i, offset;
|
|
Packit Service |
102278 |
const char *line_buf, *line_end;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* ruletab bits */
|
|
Packit Service |
102278 |
/* keep track of the head (index 0) and tail (index 1) with this array */
|
|
Packit Service |
102278 |
semanage_netfilter_context_node_t *ruletab[NC_SORT_NEL][2];
|
|
Packit Service |
102278 |
semanage_netfilter_context_node_t *curr, *node;
|
|
Packit Service |
102278 |
int priority;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* sorted buffer bits */
|
|
Packit Service |
102278 |
char *sorted_buf_pos;
|
|
Packit Service |
102278 |
size_t count;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* initialize ruletab */
|
|
Packit Service |
102278 |
memset(ruletab, 0,
|
|
Packit Service |
102278 |
NC_SORT_NEL * 2 * sizeof(semanage_netfilter_context_node_t *));
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* while lines to be read */
|
|
Packit Service |
102278 |
line_buf = buf;
|
|
Packit Service |
102278 |
buf_remainder = buf_len;
|
|
Packit Service |
102278 |
while ((line_end = semanage_get_line_end(line_buf, buf_remainder))) {
|
|
Packit Service |
102278 |
line_len = line_end - line_buf + 1;
|
|
Packit Service |
102278 |
buf_remainder = buf_remainder - line_len;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (line_len == 0 || line_len == 1) {
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Skip the whitespace at the front of the line. */
|
|
Packit Service |
102278 |
for (i = 0; i < line_len; i++) {
|
|
Packit Service |
102278 |
if (!isspace(line_buf[i]))
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Check for a blank line. */
|
|
Packit Service |
102278 |
if (i >= line_len) {
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Check if the line is a comment. */
|
|
Packit Service |
102278 |
if (line_buf[i] == '#') {
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
continue;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* extract priority */
|
|
Packit Service |
102278 |
priority = -1;
|
|
Packit Service |
102278 |
offset = 0;
|
|
Packit Service |
102278 |
for (i = 0; i < NC_SORT_NEL; i++) {
|
|
Packit Service |
102278 |
if (strncmp
|
|
Packit Service |
102278 |
(line_buf, priority_names[i],
|
|
Packit Service |
102278 |
priority_names_len[i]) == 0) {
|
|
Packit Service |
102278 |
priority = i;
|
|
Packit Service |
102278 |
offset = priority_names_len[i];
|
|
Packit Service |
102278 |
break;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (priority < 0) {
|
|
Packit Service |
102278 |
ERR(sh, "Netfilter context line missing priority.");
|
|
Packit Service |
102278 |
semanage_nc_destroy_ruletab(ruletab);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* skip over whitespace */
|
|
Packit Service |
102278 |
for (; offset < line_len && isspace(line_buf[offset]);
|
|
Packit Service |
102278 |
offset++) ;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* load rule into node */
|
|
Packit Service |
102278 |
node = (semanage_netfilter_context_node_t *)
|
|
Packit Service |
102278 |
malloc(sizeof(semanage_netfilter_context_node_t));
|
|
Packit Service |
102278 |
if (!node) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure allocating memory.");
|
|
Packit Service |
102278 |
semanage_nc_destroy_ruletab(ruletab);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
node->rule =
|
|
Packit Service |
102278 |
(char *)strndup(line_buf + offset, line_len - offset);
|
|
Packit Service |
102278 |
node->rule_len = line_len - offset;
|
|
Packit Service |
102278 |
node->next = NULL;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
if (!node->rule) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure allocating memory.");
|
|
Packit Service |
102278 |
free(node);
|
|
Packit Service |
102278 |
semanage_nc_destroy_ruletab(ruletab);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* add node to rule table */
|
|
Packit Service |
102278 |
if (ruletab[priority][0] && ruletab[priority][1]) {
|
|
Packit Service |
102278 |
/* add to end of list, update tail pointer */
|
|
Packit Service |
102278 |
ruletab[priority][1]->next = node;
|
|
Packit Service |
102278 |
ruletab[priority][1] = node;
|
|
Packit Service |
102278 |
} else {
|
|
Packit Service |
102278 |
/* this list is empty, make head and tail point to the node */
|
|
Packit Service |
102278 |
ruletab[priority][0] = ruletab[priority][1] = node;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
line_buf = line_end + 1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* First, calculate how much space we'll need for
|
|
Packit Service |
102278 |
* the newly sorted block of data. (We don't just
|
|
Packit Service |
102278 |
* use buf_len for this because we have extracted
|
|
Packit Service |
102278 |
* comments and whitespace.) Start at 1 for trailing \0 */
|
|
Packit Service |
102278 |
count = 1;
|
|
Packit Service |
102278 |
for (i = 0; i < NC_SORT_NEL; i++)
|
|
Packit Service |
102278 |
for (curr = ruletab[i][0]; curr != NULL; curr = curr->next)
|
|
Packit Service |
102278 |
count += curr->rule_len;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* Allocate the buffer for the sorted list. */
|
|
Packit Service |
102278 |
*sorted_buf = calloc(count, sizeof(char));
|
|
Packit Service |
102278 |
if (!*sorted_buf) {
|
|
Packit Service |
102278 |
ERR(sh, "Failure allocating memory.");
|
|
Packit Service |
102278 |
semanage_nc_destroy_ruletab(ruletab);
|
|
Packit Service |
102278 |
return -1;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
*sorted_buf_len = count;
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* write out rule buffer */
|
|
Packit Service |
102278 |
sorted_buf_pos = *sorted_buf;
|
|
Packit Service |
102278 |
for (i = 0; i < NC_SORT_NEL; i++) {
|
|
Packit Service |
102278 |
for (curr = ruletab[i][0]; curr != NULL; curr = curr->next) {
|
|
Packit Service |
102278 |
/* put rule into buffer */
|
|
Packit Service |
102278 |
snprintf(sorted_buf_pos, curr->rule_len + 1, "%s\n", curr->rule); /* +1 for newline */
|
|
Packit Service |
102278 |
sorted_buf_pos = sorted_buf_pos + curr->rule_len;
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
}
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
/* free ruletab */
|
|
Packit Service |
102278 |
semanage_nc_destroy_ruletab(ruletab);
|
|
Packit Service |
102278 |
|
|
Packit Service |
102278 |
return 0;
|
|
Packit Service |
102278 |
}
|