[apparmor] [PATCH 2/2] Set cache file tstamp to the mtime of most recent policy file tstamps

John Johansen john.johansen at canonical.com
Fri Jun 5 22:24:23 UTC 2015


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.johansen at 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




More information about the AppArmor mailing list