Currently the cache file has its mtime set to its creation time, but this
can lead to cache issues when a policy file is updated separately from
the cache file so that is possible a policy file is newer than the
what the cache file was generated from but still fails the comparison
because the generated cache file has a newer timestamp.

Signed-off-by: John Johansen <john.johan...@canonical.com>
---
 parser/parser.h       |  1 -
 parser/parser_main.c  |  5 +++--
 parser/policy_cache.c | 25 +++++++++++++++++++------
 parser/policy_cache.h | 12 +++++++-----
 4 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/parser/parser.h b/parser/parser.h
index f4566b9..f27e18b 100644
--- a/parser/parser.h
+++ b/parser/parser.h
@@ -333,7 +333,6 @@ extern int abort_on_error;
 extern int skip_bad_cache_rebuild;
 extern int mru_skip_cache;
 extern int debug_cache;
-extern struct timespec mru_tstamp;
 
 /* provided by parser_lex.l (cannot be used in tst builds) */
 extern FILE *yyin;
diff --git a/parser/parser_main.c b/parser/parser_main.c
index cff0813..f274d00 100644
--- a/parser/parser_main.c
+++ b/parser/parser_main.c
@@ -76,7 +76,7 @@ int abort_on_error = 0;                       /* stop 
processing profiles if error */
 int skip_bad_cache_rebuild = 0;
 int mru_skip_cache = 1;
 int debug_cache = 0;
-struct timespec mru_tstamp;
+struct timespec cache_tstamp, mru_policy_tstamp;
 
 static char *apparmorfs = NULL;
 static char *cacheloc = NULL;
@@ -645,7 +645,8 @@ int process_binary(int option, aa_kernel_interface 
*kernel_interface,
 
 void reset_parser(const char *filename)
 {
-       memset(&mru_tstamp, 0, sizeof(mru_tstamp));
+       memset(&mru_policy_tstamp, 0, sizeof(mru_policy_tstamp));
+       memset(&cache_tstamp, 0, sizeof(cache_tstamp));
        mru_skip_cache = 1;
        free_aliases();
        free_symtabs();
diff --git a/parser/policy_cache.c b/parser/policy_cache.c
index 65829a6..4ba732c 100644
--- a/parser/policy_cache.c
+++ b/parser/policy_cache.c
@@ -25,6 +25,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include <sys/stat.h>
+#include <sys/time.h>
+#include <utime.h>
 
 #include "lib.h"
 #include "parser.h"
@@ -70,22 +72,27 @@ bool valid_cached_file_version(const char *cachename)
 }
 
 
-void set_mru_tstamp(struct timespec t)
+void set_cache_tstamp(struct timespec t)
 {
        mru_skip_cache = 0;
-       mru_tstamp = t;
+       cache_tstamp = t;
 }
 
 void update_mru_tstamp(FILE *file, const char *name)
 {
        struct stat stat_file;
-       if (fstat(fileno(file), &stat_file) || (mru_tstamp.tv_sec == 0 && 
mru_tstamp.tv_nsec == 0))
+       if (fstat(fileno(file), &stat_file))
                return;
-       if (mru_t_cmp(stat_file.st_mtim)) {
+       if (tstamp_cmp(mru_policy_tstamp, stat_file.st_mtim) < 0)
+               /* keep track of the most recent policy tstamp */
+               mru_policy_tstamp = stat_file.st_mtim;
+       if (tstamp_is_null(cache_tstamp))
+               return;
+       if (tstamp_cmp(stat_file.st_mtim, cache_tstamp) > 0) {
                if (debug_cache)
                        pwarn("%s: file '%s' is newer than cache file\n", 
progname, name);
                mru_skip_cache = 1;
-       }
+       }
 }
 
 char *cache_filename(const char *cachedir, const char *basename)
@@ -109,7 +116,7 @@ void valid_read_cache(const char *cachename)
                if (stat(cachename, &stat_bin) == 0 &&
                    stat_bin.st_size > 0) {
                        if (valid_cached_file_version(cachename))
-                               set_mru_tstamp(stat_bin.st_mtim);
+                               set_cache_tstamp(stat_bin.st_mtim);
                        else if (!cond_clear_cache)
                                write_cache = 0;
                } else {
@@ -159,6 +166,12 @@ 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) {
+               struct timeval t;
+               /* set the mtime of the cache file to the most newest mtime
+                * of policy files used to generate it
+                */
+               TIMESPEC_TO_TIMEVAL(&t, &mru_policy_tstamp);
+               utimes(cachetmpname, &t);
                if (rename(cachetmpname, cachename) < 0) {
                        pwarn("Warning failed to write cache: %s\n", cachename);
                        unlink(cachetmpname);
diff --git a/parser/policy_cache.h b/parser/policy_cache.h
index 3c3e85d..693370d 100644
--- a/parser/policy_cache.h
+++ b/parser/policy_cache.h
@@ -19,12 +19,14 @@
 #ifndef __AA_POLICY_CACHE_H
 #define __AA_POLICY_CACHE_H
 
-extern struct timespec mru_tstamp;
+extern struct timespec cache_tstamp, mru_policy_tstamp;
 
 /* 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)
+#define tstamp_cmp(a, b)                                               \
+  (((a).tv_sec == (b).tv_sec) ?                                                
\
+   ((a).tv_nsec - (b).tv_nsec) :                                       \
+   ((a).tv_sec - (b).tv_sec))
+#define tstamp_is_null(a) ((a).tv_sec == 0 && (a).tv_nsec == 0)
 
 extern int show_cache;
 extern int skip_cache;
@@ -36,7 +38,7 @@ extern int create_cache_dir;          /* create the cache dir 
if missing? */
 extern int mru_skip_cache;
 extern int debug_cache;
 
-void set_mru_tstamp(struct timespec t);
+void set_cache_tstamp(struct timespec t);
 void update_mru_tstamp(FILE *file, const char *path);
 bool valid_cached_file_version(const char *cachename);
 char *cache_filename(const char *cachedir, const char *basename);
-- 
2.1.4


-- 
AppArmor mailing list
AppArmor@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to