mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 01:57:43 +00:00
parser: Create initial interface for policy cache
This API has the same look-and-feel of the previous aa_features API. The cache setup code was heavily dependent on globals set by CLI options. Options such as "skip the read cache", or "skip the write cache", or "don't clear the cache if it isn't valid", won't be useful for all aa_policy_cache API users so some of that logic was lifted out of the API. The constructor function still provides a bool parameter that specifies if the cache should be created or not. If the policy cache is invalid (currently meaning that the cache features file doesn't match the kernel features file), then a new aa_policy_cache object is still created but a call to aa_policy_cache_is_valid() will return false. The caller can then decide what to do (create a new valid cache, stop, etc.) Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Acked-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
d93d00cca9
commit
f0fcf23231
@ -875,6 +875,7 @@ static void setup_flags(void)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
aa_policy_cache *policy_cache;
|
||||
int retval, last_error;
|
||||
int i;
|
||||
int optind;
|
||||
@ -907,29 +908,48 @@ int main(int argc, char *argv[])
|
||||
|
||||
setup_flags();
|
||||
|
||||
if (!cacheloc && asprintf(&cacheloc, "%s/cache", basedir) == -1) {
|
||||
PERROR(_("Memory allocation error."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (force_clear_cache) {
|
||||
if (clear_cache_files(cacheloc)) {
|
||||
PERROR(_("Failed to clear cache files (%s): %s\n"),
|
||||
cacheloc, strerror(errno));
|
||||
if ((!skip_cache && (write_cache || !skip_read_cache)) ||
|
||||
force_clear_cache) {
|
||||
if (!cacheloc && asprintf(&cacheloc, "%s/cache", basedir) == -1) {
|
||||
PERROR(_("Memory allocation error."));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (force_clear_cache) {
|
||||
if (clear_cache_files(cacheloc)) {
|
||||
PERROR(_("Failed to clear cache files (%s): %s\n"),
|
||||
cacheloc, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (create_cache_dir)
|
||||
pwarn(_("The --create-cache-dir option is deprecated. Please use --write-cache.\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
retval = setup_cache(features, cacheloc);
|
||||
if (retval) {
|
||||
PERROR(_("Failed setting up policy cache (%s): %s\n"),
|
||||
cacheloc, strerror(errno));
|
||||
return 1;
|
||||
if (create_cache_dir)
|
||||
pwarn(_("The --create-cache-dir option is deprecated. Please use --write-cache.\n"));
|
||||
|
||||
retval = aa_policy_cache_new(&policy_cache, features, cacheloc,
|
||||
write_cache);
|
||||
if (retval) {
|
||||
if (errno != ENOENT) {
|
||||
PERROR(_("Failed setting up policy cache (%s): %s\n"),
|
||||
cacheloc, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
write_cache = 0;
|
||||
skip_read_cache = 0;
|
||||
} else if (!aa_policy_cache_is_valid(policy_cache)) {
|
||||
if (write_cache && cond_clear_cache &&
|
||||
aa_policy_cache_create(policy_cache)) {
|
||||
skip_read_cache = 1;
|
||||
} else if (!write_cache || !cond_clear_cache) {
|
||||
if (show_cache)
|
||||
PERROR("Cache read/write disabled: Policy cache is invalid\n");
|
||||
write_cache = 0;
|
||||
skip_read_cache = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retval = last_error = 0;
|
||||
|
@ -35,6 +35,14 @@
|
||||
|
||||
#define le16_to_cpu(x) ((uint16_t)(le16toh (*(uint16_t *) x)))
|
||||
|
||||
struct aa_policy_cache {
|
||||
unsigned int ref_count;
|
||||
aa_features *features;
|
||||
aa_features *kernel_features;
|
||||
char *path;
|
||||
char *features_path;
|
||||
};
|
||||
|
||||
const char header_string[] = "\004\010\000version\000\002";
|
||||
#define HEADER_STRING_SIZE 12
|
||||
bool valid_cached_file_version(const char *cachename)
|
||||
@ -107,37 +115,44 @@ int clear_cache_files(const char *path)
|
||||
return dirat_for_each(NULL, path, NULL, clear_cache_cb);
|
||||
}
|
||||
|
||||
int create_cache(const char *cachedir, const char *path, aa_features *features)
|
||||
static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
|
||||
{
|
||||
struct stat stat_file;
|
||||
autofclose FILE * f = NULL;
|
||||
|
||||
if (clear_cache_files(cachedir) != 0)
|
||||
if (clear_cache_files(policy_cache->path) != 0)
|
||||
goto error;
|
||||
|
||||
create_file:
|
||||
if (aa_features_write_to_file(features, path) == -1)
|
||||
if (aa_features_write_to_file(features,
|
||||
policy_cache->features_path) == -1)
|
||||
goto error;
|
||||
|
||||
aa_features_unref(policy_cache->features);
|
||||
policy_cache->features = aa_features_ref(features);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
/* does the dir exist? */
|
||||
if (stat(cachedir, &stat_file) == -1) {
|
||||
if (mkdir(cachedir, 0700) == 0)
|
||||
if (stat(policy_cache->path, &stat_file) == -1) {
|
||||
if (mkdir(policy_cache->path, 0700) == 0)
|
||||
goto create_file;
|
||||
if (show_cache)
|
||||
PERROR(_("Can't create cache directory: %s\n"), cachedir);
|
||||
PERROR(_("Can't create cache directory: %s\n"),
|
||||
policy_cache->path);
|
||||
} else if (!S_ISDIR(stat_file.st_mode)) {
|
||||
if (show_cache)
|
||||
PERROR(_("File in cache directory location: %s\n"), cachedir);
|
||||
PERROR(_("File in cache directory location: %s\n"),
|
||||
policy_cache->path);
|
||||
} else {
|
||||
if (show_cache)
|
||||
PERROR(_("Can't update cache directory: %s\n"), cachedir);
|
||||
PERROR(_("Can't update cache directory: %s\n"),
|
||||
policy_cache->path);
|
||||
}
|
||||
|
||||
if (show_cache)
|
||||
PERROR("Cache write disabled: cannot create %s\n", path);
|
||||
PERROR("Cache write disabled: cannot create %s\n",
|
||||
policy_cache->features_path);
|
||||
write_cache = 0;
|
||||
|
||||
return -1;
|
||||
@ -224,45 +239,126 @@ void install_cache(const char *cachetmpname, const char *cachename)
|
||||
}
|
||||
}
|
||||
|
||||
int setup_cache(aa_features *kernel_features, const char *cacheloc)
|
||||
static int init_cache_features(aa_policy_cache *policy_cache,
|
||||
aa_features *kernel_features, bool create)
|
||||
{
|
||||
autofree char *cache_features_path = NULL;
|
||||
aa_features *cache_features;
|
||||
if (aa_features_new(&policy_cache->features,
|
||||
policy_cache->features_path)) {
|
||||
policy_cache->features = NULL;
|
||||
if (!create || errno != ENOENT)
|
||||
return -1;
|
||||
|
||||
if (!cacheloc) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deal with cache directory versioning:
|
||||
* - If cache/.features is missing, create it if --write-cache.
|
||||
* - If cache/.features exists, and does not match features_string,
|
||||
* force cache reading/writing off.
|
||||
*/
|
||||
if (asprintf(&cache_features_path, "%s/.features", cacheloc) == -1) {
|
||||
PERROR(_("Memory allocation error."));
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!aa_features_new(&cache_features, cache_features_path)) {
|
||||
if (!aa_features_is_equal(kernel_features, cache_features)) {
|
||||
if (write_cache && cond_clear_cache) {
|
||||
if (create_cache(cacheloc, cache_features_path,
|
||||
kernel_features))
|
||||
skip_read_cache = 1;
|
||||
} else {
|
||||
if (show_cache)
|
||||
PERROR("Cache read/write disabled: Police cache is invalid\n");
|
||||
write_cache = 0;
|
||||
skip_read_cache = 1;
|
||||
}
|
||||
}
|
||||
aa_features_unref(cache_features);
|
||||
} else if (write_cache) {
|
||||
create_cache(cacheloc, cache_features_path, kernel_features);
|
||||
return create_cache(policy_cache, kernel_features);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_new - create a new policy_cache from a path
|
||||
* @policy_cache: will point to the address of an allocated and initialized
|
||||
* aa_policy_cache_new object upon success
|
||||
* @kernel_features: features representing the currently running kernel
|
||||
* @path: path to the policy cache
|
||||
* @create: true if the cache should be created if it doesn't already exist
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set and *@policy_cache
|
||||
* pointing to NULL
|
||||
*/
|
||||
int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
||||
aa_features *kernel_features, const char *path,
|
||||
bool create)
|
||||
{
|
||||
aa_policy_cache *pc;
|
||||
|
||||
*policy_cache = NULL;
|
||||
|
||||
if (!path) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pc = (aa_policy_cache *) calloc(1, sizeof(*pc));
|
||||
if (!pc) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
aa_policy_cache_ref(pc);
|
||||
|
||||
pc->path = strdup(path);
|
||||
if (!pc->path) {
|
||||
aa_policy_cache_unref(pc);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (asprintf(&pc->features_path, "%s/.features", pc->path) == -1) {
|
||||
pc->features_path = NULL;
|
||||
aa_policy_cache_unref(pc);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (init_cache_features(pc, kernel_features, create)) {
|
||||
int save = errno;
|
||||
|
||||
aa_policy_cache_unref(pc);
|
||||
errno = save;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pc->kernel_features = aa_features_ref(kernel_features);
|
||||
*policy_cache = pc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_ref - increments the ref count of a policy_cache
|
||||
* @policy_cache: the policy_cache
|
||||
*
|
||||
* Returns: the policy_cache
|
||||
*/
|
||||
aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache)
|
||||
{
|
||||
atomic_inc(&policy_cache->ref_count);
|
||||
return policy_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_unref - decrements the ref count and frees the policy_cache when 0
|
||||
* @policy_cache: the policy_cache (can be NULL)
|
||||
*/
|
||||
void aa_policy_cache_unref(aa_policy_cache *policy_cache)
|
||||
{
|
||||
if (policy_cache && atomic_dec_and_test(&policy_cache->ref_count)) {
|
||||
free(policy_cache->features_path);
|
||||
free(policy_cache->path);
|
||||
free(policy_cache);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_is_valid - checks if the policy_cache is valid for the currently running kernel
|
||||
* @policy_cache: the policy_cache
|
||||
*
|
||||
* Returns: true if the policy_cache is valid for the currently running kernel,
|
||||
* false if not
|
||||
*/
|
||||
bool aa_policy_cache_is_valid(aa_policy_cache *policy_cache)
|
||||
{
|
||||
return aa_features_is_equal(policy_cache->features,
|
||||
policy_cache->kernel_features);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_create - creates a valid policy_cache for the currently running kernel
|
||||
* @policy_cache: the policy_cache
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set and features pointing to
|
||||
* NULL
|
||||
*/
|
||||
int aa_policy_cache_create(aa_policy_cache *policy_cache)
|
||||
{
|
||||
return create_cache(policy_cache, policy_cache->kernel_features);
|
||||
}
|
||||
|
@ -42,12 +42,20 @@ void set_mru_tstamp(struct timespec t);
|
||||
void update_mru_tstamp(FILE *file, const char *path);
|
||||
bool valid_cached_file_version(const char *cachename);
|
||||
int clear_cache_files(const char *path);
|
||||
int create_cache(const char *cachedir, const char *path, const char *features);
|
||||
char *cache_filename(const char *cachedir, const char *basename);
|
||||
void valid_read_cache(const char *cachename);
|
||||
int cache_hit(const char *cachename);
|
||||
int setup_cache_tmp(const char **cachetmpname, const char *cachename);
|
||||
void install_cache(const char *cachetmpname, const char *cachename);
|
||||
int setup_cache(aa_features *kernel_features, const char *cacheloc);
|
||||
|
||||
typedef struct aa_policy_cache aa_policy_cache;
|
||||
|
||||
int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
||||
aa_features *kernel_features, const char *path,
|
||||
bool create);
|
||||
aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);
|
||||
void aa_policy_cache_unref(aa_policy_cache *policy_cache);
|
||||
bool aa_policy_cache_is_valid(aa_policy_cache *policy_cache);
|
||||
int aa_policy_cache_create(aa_policy_cache *policy_cache);
|
||||
|
||||
#endif /* __AA_POLICY_CACHE_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user