2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 01:57:43 +00:00

parser: Move policy cache functionality into policy_cache.c

Signed-off-by: John Johansen <john.johansen@canonical.com>
[tyhicks: Fixed build failures]
[tyhicks: Fixed bug where a warning was being printed when it shouldn't]
[tyhicks: Forward ported to trunk]
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
This commit is contained in:
John Johansen 2015-03-25 17:09:26 -05:00 committed by Tyler Hicks
parent 4970d40e0d
commit 2a082ee543
6 changed files with 119 additions and 80 deletions

View File

@ -427,7 +427,7 @@ extern void free_aliases(void);
extern int profile_merge_rules(Profile *prof);
/* parser_interface.c */
extern int load_profile(int option, Profile *prof);
extern int load_profile(int option, Profile *prof, int cache_fd);
extern void sd_serialize_profile(std::ostringstream &buf, Profile *prof,
int flatten);
extern int sd_load_buffer(int option, char *buffer, int size);
@ -448,9 +448,9 @@ extern int process_profile_policydb(Profile *prof);
extern int post_merge_rules(void);
extern int merge_hat_rules(Profile *prof);
extern Profile *merge_policy(Profile *a, Profile *b);
extern int load_policy(int option);
extern int load_policy(int option, int cache_fd);
extern int load_hats(std::ostringstream &buf, Profile *prof);
extern int load_flattened_hats(Profile *prof, int option);
extern int load_flattened_hats(Profile *prof, int option, int cache_fd);
extern void dump_policy_hats(Profile *prof);
extern void dump_policy_names(void);
void dump_policy(void);

View File

@ -42,7 +42,7 @@
#define SD_STR_LEN (sizeof(u16))
int __sd_serialize_profile(int option, Profile *prof);
int __sd_serialize_profile(int option, Profile *prof, int cache_fd);
static void print_error(int error)
{
@ -83,13 +83,13 @@ static void print_error(int error)
}
}
int load_profile(int option, Profile *prof)
int load_profile(int option, Profile *prof, int cache_fd)
{
int retval = 0;
int error = 0;
PDEBUG("Serializing policy for %s.\n", prof->name);
retval = __sd_serialize_profile(option, prof);
retval = __sd_serialize_profile(option, prof, cache_fd);
if (retval < 0) {
error = retval; /* yeah, we'll just report the last error */
@ -475,8 +475,7 @@ void sd_serialize_top_profile(std::ostringstream &buf, Profile *profile)
sd_serialize_profile(buf, profile, profile->parent ? 1 : 0);
}
int cache_fd = -1;
int __sd_serialize_profile(int option, Profile *prof)
int __sd_serialize_profile(int option, Profile *prof, int cache_fd)
{
autoclose int fd = -1;
int error = -ENOMEM, size, wsize;
@ -555,7 +554,7 @@ int __sd_serialize_profile(int option, Profile *prof)
}
if (!prof->hat_table.empty() && option != OPTION_REMOVE) {
if (load_flattened_hats(prof, option) == 0)
if (load_flattened_hats(prof, option, cache_fd) == 0)
return 0;
}

View File

@ -695,10 +695,10 @@ int test_for_dir_mode(const char *basename, const char *linkdir)
int process_profile(int option, const char *profilename)
{
struct stat stat_bin;
int retval = 0;
autofree char *cachename = NULL;
autofree char *cachetemp = NULL;
autofree const char *cachename = NULL;
autofree const char *cachetmpname = NULL;
autoclose int cachetmp = -1;
const char *basename = NULL;
/* per-profile states */
@ -737,24 +737,8 @@ int process_profile(int option, const char *profilename)
/* setup cachename and tstamp */
if (!force_complain && !skip_cache) {
if (asprintf(&cachename, "%s/%s", cacheloc, basename)<0) {
PERROR(_("Memory allocation error."));
exit(1);
}
if (!skip_read_cache) {
if (stat(cachename, &stat_bin) == 0 &&
stat_bin.st_size > 0) {
if (valid_cached_file_version(cachename))
set_mru_tstamp(stat_bin.st_ctim);
else if (!cond_clear_cache)
write_cache = 0;
} else {
if (!cond_clear_cache)
write_cache = 0;
if (debug_cache)
pwarn("%s: Invalid or missing cache file '%s' (%s)\n", progname, cachename, strerror(errno));
}
}
cachename = cache_filename(cacheloc, basename);
valid_read_cache(cachename);
}
}
@ -773,36 +757,20 @@ int process_profile(int option, const char *profilename)
* TODO: Add support for caching profiles in an alternate namespace
* TODO: Add support for embedded namespace defines if they aren't
* removed from the language.
* TODO: test profile->ns NOT profile_ns (must be after parse)
*/
if (profile_ns)
skip_cache = 1;
/* Do secondary test to see if cached binary profile is good,
* instead of checking against a presupplied list of files
* use the timestamps from the files that were parsed.
* Parsing the profile is slower that doing primary cache check
* its still faster than doing full compilation
*/
if (cachename) {
/* Load a binary cache if it exists and is newest */
if (!mru_skip_cache) {
if (show_cache)
PERROR("Cache hit: %s\n", cachename);
if (cache_hit(cachename)) {
retval = process_binary(option, cachename);
if (!retval || skip_bad_cache_rebuild)
return retval;
}
if (write_cache) {
/* Otherwise, set up to save a cached copy */
if (asprintf(&cachetemp, "%s-XXXXXX", cachename)<0) {
perror("asprintf");
return ENOMEM;
}
if ( (cache_fd = mkstemp(cachetemp)) < 0) {
perror("mkstemp");
return ENOMEM;
}
}
cachetmp = setup_cache_tmp(&cachetmpname, cachename);
}
if (show_cache)
@ -838,32 +806,18 @@ int process_profile(int option, const char *profilename)
goto out;
}
retval = load_policy(option);
out:
if (cachetemp) {
/* Only install the generate cache file if it parsed correctly
and did not have write/close errors */
int useable_cache = (cache_fd != -1 && retval == 0);
if (cache_fd != -1) {
if (close(cache_fd))
useable_cache = 0;
cache_fd = -1;
}
if (useable_cache) {
if (rename(cachetemp, cachename) < 0) {
pwarn("Warning failed to write cache: %s\n", cachename);
unlink(cachetemp);
}
else if (show_cache)
PERROR("Wrote cache: %s\n", cachename);
}
else {
unlink(cachetemp);
PERROR("Warning failed to create cache: %s\n", basename);
/* cache file generated by load_policy */
retval = load_policy(option, cachetmp);
if (retval == 0 && write_cache) {
if (cachetmp == -1) {
unlink(cachetmpname);
PERROR("Warning failed to create cache: %s\n",
basename);
} else {
install_cache(cachetmpname, cachename);
}
}
out:
return retval;
}

View File

@ -220,12 +220,12 @@ static int profile_add_hat_rules(Profile *prof)
return 0;
}
int load_policy_list(ProfileList &list, int option)
int load_policy_list(ProfileList &list, int option, int cache_fd)
{
int res = 0;
for (ProfileList::iterator i = list.begin(); i != list.end(); i++) {
res = load_profile(option, *i);
res = load_profile(option, *i, cache_fd);
if (res != 0)
break;
}
@ -233,14 +233,14 @@ int load_policy_list(ProfileList &list, int option)
return res;
}
int load_flattened_hats(Profile *prof, int option)
int load_flattened_hats(Profile *prof, int option, int cache_fd)
{
return load_policy_list(prof->hat_table, option);
return load_policy_list(prof->hat_table, option, cache_fd);
}
int load_policy(int option)
int load_policy(int option, int cache_fd)
{
return load_policy_list(policy_list, option);
return load_policy_list(policy_list, option, cache_fd);
}
int load_hats(std::ostringstream &buf, Profile *prof)

View File

@ -145,3 +145,84 @@ error:
return -1;
}
char *cache_filename(const char *cacheloc, const char *basename)
{
char *cachename;
if (asprintf(&cachename, "%s/%s", cacheloc, basename) < 0) {
PERROR(_("Memory allocation error."));
exit(1);
}
return cachename;
}
void valid_read_cache(const char *cachename)
{
struct stat stat_bin;
/* Load a binary cache if it exists and is newest */
if (!skip_read_cache) {
if (stat(cachename, &stat_bin) == 0 &&
stat_bin.st_size > 0) {
if (valid_cached_file_version(cachename))
set_mru_tstamp(stat_bin.st_ctim);
else if (!cond_clear_cache)
write_cache = 0;
} else {
if (!cond_clear_cache)
write_cache = 0;
if (debug_cache)
pwarn("%s: Invalid or missing cache file '%s' (%s)\n", progname, cachename, strerror(errno));
}
}
}
int cache_hit(const char *cachename)
{
if (!mru_skip_cache) {
if (show_cache)
PERROR("Cache hit: %s\n", cachename);
return true;
}
return false;
}
int setup_cache_tmp(const char **cachetmpname, const char *cachename)
{
char *tmpname;
int cache_fd = -1;
*cachetmpname = NULL;
if (write_cache) {
/* Otherwise, set up to save a cached copy */
if (asprintf(&tmpname, "%s-XXXXXX", cachename)<0) {
perror("asprintf");
exit(1);
}
if ((cache_fd = mkstemp(tmpname)) < 0) {
perror("mkstemp");
exit(1);
}
*cachetmpname = tmpname;
}
return cache_fd;
}
void install_cache(const char *cachetmpname, const char *cachename)
{
/* Only install the generate cache file if it parsed correctly
and did not have write/close errors */
if (cachetmpname) {
if (rename(cachetmpname, cachename) < 0) {
pwarn("Warning failed to write cache: %s\n", cachename);
unlink(cachetmpname);
}
else if (show_cache) {
PERROR("Wrote cache: %s\n", cachename);
}
}
}

View File

@ -41,5 +41,10 @@ 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 *cacheloc, 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);
#endif /* __AA_POLICY_CACHE_H */