mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-01 14:55:10 +00:00
Merge from trunk revs 1495 and 1496: Update how cache validation is
done to fix the bug where abstraction updates do not cause the cache file to become invalid. Nominated-by: John Johansen <john.johansen@canonical.com> Acked-By: Steve Beattie <sbeattie@ubuntu.com>
This commit is contained in:
@@ -235,6 +235,8 @@ extern int conf_verbose;
|
|||||||
extern int kernel_load;
|
extern int kernel_load;
|
||||||
extern int regex_type;
|
extern int regex_type;
|
||||||
extern int perms_create;
|
extern int perms_create;
|
||||||
|
extern struct timespec mru_tstamp;
|
||||||
|
extern void update_mru_tstamp(FILE *file);
|
||||||
extern void pwarn(char *fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
|
extern void pwarn(char *fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
|
||||||
|
|
||||||
extern FILE *yyin;
|
extern FILE *yyin;
|
||||||
|
@@ -102,6 +102,7 @@ void include_filename(char *filename, int search)
|
|||||||
|
|
||||||
if (S_ISREG(my_stat.st_mode)) {
|
if (S_ISREG(my_stat.st_mode)) {
|
||||||
yyin = include_file;
|
yyin = include_file;
|
||||||
|
update_mru_tstamp(include_file);
|
||||||
PDEBUG("Opened include \"%s\"\n", fullpath);
|
PDEBUG("Opened include \"%s\"\n", fullpath);
|
||||||
push_include_stack(fullpath);
|
push_include_stack(fullpath);
|
||||||
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
||||||
@@ -150,6 +151,7 @@ void include_filename(char *filename, int search)
|
|||||||
if (!(yyin = fopen(dirent_path,"r")))
|
if (!(yyin = fopen(dirent_path,"r")))
|
||||||
yyerror(_("Could not open '%s' in '%s'"), dirent_path, filename);
|
yyerror(_("Could not open '%s' in '%s'"), dirent_path, filename);
|
||||||
PDEBUG("Opened include \"%s\" in \"%s\"\n", dirent_path, filename);
|
PDEBUG("Opened include \"%s\" in \"%s\"\n", dirent_path, filename);
|
||||||
|
update_mru_tstamp(yyin);
|
||||||
push_include_stack(dirent_path);
|
push_include_stack(dirent_path);
|
||||||
yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
|
yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
|
||||||
}
|
}
|
||||||
|
@@ -79,6 +79,7 @@ int read_implies_exec = 1;
|
|||||||
int read_implies_exec = 0;
|
int read_implies_exec = 0;
|
||||||
#endif
|
#endif
|
||||||
int preprocess_only = 0;
|
int preprocess_only = 0;
|
||||||
|
struct timespec mru_tstamp;
|
||||||
|
|
||||||
char *subdomainbase = NULL;
|
char *subdomainbase = NULL;
|
||||||
char *match_string = NULL;
|
char *match_string = NULL;
|
||||||
@@ -716,6 +717,7 @@ int process_binary(int option, char *profilename)
|
|||||||
|
|
||||||
void reset_parser(char *filename)
|
void reset_parser(char *filename)
|
||||||
{
|
{
|
||||||
|
memset(&mru_tstamp, 0, sizeof(mru_tstamp));
|
||||||
free_aliases();
|
free_aliases();
|
||||||
free_symtabs();
|
free_symtabs();
|
||||||
free_policies();
|
free_policies();
|
||||||
@@ -723,13 +725,27 @@ void reset_parser(char *filename)
|
|||||||
reset_include_stack(filename);
|
reset_include_stack(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* returns true if time is more recent than mru_tstamp */
|
||||||
|
#define mru_t_cmp(a) \
|
||||||
|
(((a).tv_sec == (mru_tstamp).tv_sec) ? \
|
||||||
|
(a).tv_nsec > (mru_tstamp).tv_nsec : (a).tv_sec > (mru_tstamp).tv_sec)
|
||||||
|
|
||||||
|
void update_mru_tstamp(FILE *file)
|
||||||
|
{
|
||||||
|
struct stat stat_file;
|
||||||
|
if (fstat(fileno(file), &stat_file))
|
||||||
|
return;
|
||||||
|
if (mru_t_cmp(stat_file.st_ctim))
|
||||||
|
mru_tstamp = stat_file.st_ctim;
|
||||||
|
}
|
||||||
|
|
||||||
int process_profile(int option, char *profilename)
|
int process_profile(int option, char *profilename)
|
||||||
{
|
{
|
||||||
struct stat stat_text;
|
|
||||||
struct stat stat_bin;
|
struct stat stat_bin;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
char * cachename = NULL;
|
char * cachename = NULL;
|
||||||
char * cachetemp = NULL;
|
char * cachetemp = NULL;
|
||||||
|
char *basename = NULL;
|
||||||
|
|
||||||
/* per-profile states */
|
/* per-profile states */
|
||||||
force_complain = opt_force_complain;
|
force_complain = opt_force_complain;
|
||||||
@@ -748,7 +764,7 @@ int process_profile(int option, char *profilename)
|
|||||||
if (profilename && option != OPTION_REMOVE) {
|
if (profilename && option != OPTION_REMOVE) {
|
||||||
/* make decisions about disabled or complain-mode profiles */
|
/* make decisions about disabled or complain-mode profiles */
|
||||||
char *target = NULL;
|
char *target = NULL;
|
||||||
char *basename = strrchr(profilename, '/');
|
basename = strrchr(profilename, '/');
|
||||||
if (basename)
|
if (basename)
|
||||||
basename++;
|
basename++;
|
||||||
else
|
else
|
||||||
@@ -779,34 +795,53 @@ int process_profile(int option, char *profilename)
|
|||||||
}
|
}
|
||||||
free(target);
|
free(target);
|
||||||
|
|
||||||
if (!force_complain && !skip_cache) {
|
/* TODO: add primary cache check.
|
||||||
fstat(fileno(yyin), &stat_text);
|
* If .file for cached binary exists get the list of profile
|
||||||
if (asprintf(&cachename, "%s/%s/%s", basedir, "cache", basename)<0) {
|
* names and check their time stamps.
|
||||||
|
*/
|
||||||
|
/* TODO: primary cache miss/hit messages */
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_parser(profilename);
|
||||||
|
if (yyin) {
|
||||||
|
yyrestart(yyin);
|
||||||
|
update_mru_tstamp(yyin);
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = yyparse();
|
||||||
|
if (retval != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* 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 ((profilename && option != OPTION_REMOVE) && !force_complain &&
|
||||||
|
!skip_cache) {
|
||||||
|
if (asprintf(&cachename, "%s/%s/%s", basedir, "cache", basename)<0) {
|
||||||
|
perror("asprintf");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/* Load a binary cache if it exists and is newest */
|
||||||
|
if (!skip_read_cache &&
|
||||||
|
stat(cachename, &stat_bin) == 0 &&
|
||||||
|
stat_bin.st_size > 0 && (mru_t_cmp(stat_bin.st_mtim))) {
|
||||||
|
if (show_cache)
|
||||||
|
PERROR("Cache hit: %s\n", cachename);
|
||||||
|
retval = process_binary(option, cachename);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (write_cache) {
|
||||||
|
/* Otherwise, set up to save a cached copy */
|
||||||
|
if (asprintf(&cachetemp, "%s/%s/%s-XXXXXX", basedir, "cache", basename)<0) {
|
||||||
perror("asprintf");
|
perror("asprintf");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
/* Load a binary cache if it exists and is newest */
|
if ( (cache_fd = mkstemp(cachetemp)) < 0) {
|
||||||
if (!skip_read_cache &&
|
perror("mkstemp");
|
||||||
stat(cachename, &stat_bin) == 0 &&
|
exit(1);
|
||||||
stat_bin.st_size > 0 &&
|
|
||||||
(stat_bin.st_mtim.tv_sec > stat_text.st_ctim.tv_sec ||
|
|
||||||
(stat_bin.st_mtim.tv_sec == stat_text.st_ctim.tv_sec &&
|
|
||||||
stat_bin.st_mtim.tv_nsec >= stat_text.st_ctim.tv_nsec))) {
|
|
||||||
if (show_cache)
|
|
||||||
PERROR("Cache hit: %s\n", cachename);
|
|
||||||
retval = process_binary(option, cachename);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (write_cache) {
|
|
||||||
/* Otherwise, set up to save a cached copy */
|
|
||||||
if (asprintf(&cachetemp, "%s/%s/%s-XXXXXX", basedir, "cache", basename)<0) {
|
|
||||||
perror("asprintf");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if ( (cache_fd = mkstemp(cachetemp)) < 0) {
|
|
||||||
perror("mkstemp");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -814,14 +849,6 @@ int process_profile(int option, char *profilename)
|
|||||||
if (show_cache)
|
if (show_cache)
|
||||||
PERROR("Cache miss: %s\n", profilename ? profilename : "stdin");
|
PERROR("Cache miss: %s\n", profilename ? profilename : "stdin");
|
||||||
|
|
||||||
if (yyin)
|
|
||||||
yyrestart(yyin);
|
|
||||||
reset_parser(profilename);
|
|
||||||
|
|
||||||
retval = yyparse();
|
|
||||||
if (retval != 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (preprocess_only)
|
if (preprocess_only)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user