Re: [apparmor] Cache update broken

2012-08-07 Thread John Johansen
On 08/04/2012 06:53 AM, Christian Boltz wrote:
 Hello,
 
 I received a bugreport that loading AppArmor needs 25 seconds at boot:
 https://bugzilla.novell.com/show_bug.cgi?id=774529
 I can reproduce the problem on my system (AppArmor 2.8.0)
 
 It looks like the cache is not updated, and (for obvious reasons) the 
 outdated cache isn't used.
 
 # grep '^[^#]' /etc/apparmor/parser.conf
 write-cache
 show-cache
 
 # apparmor_parser -r /etc/apparmor.d/usr.lib.dovecot.deliver 
 Cache read/write disabled: /sys/kernel/security/apparmor/features does 
 not match /etc/apparmor.d/cache/.features
 Cache miss: /etc/apparmor.d/usr.lib.dovecot.deliver
 
 Expected behaviour IMHO: update the cache and the .features file.
 
 Any idea what is wrong? (A patch would be even better ;-)
 
 

Alright attached is a first pass at a patch.

The bug basically comes down to the apparmor cache will not be updated
by --write-cache when .features does not match because the parser processes
policy one profile at a time is trying to avoid having profiles of different
binary versions in the cache.

The solution is to clear the cache. Ubuntu is doing this in the init
scripts but suse went with using the defaults file and always setting the
--write-cache option.

The patch adds a --clear-cache option to the parser

There are is still documentation to be done and decisions about defaults,
currently --clear-cache has the following behavior

  it clears the cache if --write-cache is enabled and the cache features
  do not match.

We could
1. change current behavior to be on by default, and change to a no-clear-cache
   flag.

2. make --clear-cache always clear the cache
   2.1 regardless of whether --write-cache is enabled
   2.2 regardless of whether features do not match
   2.3 regardless of both --write-cache and features not matching


Also note currently it is only clearing out regular files, in a non-recursive
manner.

---

apparmor: add the ability to clear the profile cache

Add the ability to clear out the binary profile cache. This removes the
need to have a separate script to handle the logic of checking and
removing the cache if it is out of date.

The parser already does all the checking to determine cache validity
so it makes sense to allow the parser to clear out inconsistent cache
when it has been instructed to update the cache.

Signed-off-by: John Johnansen john.johan...@canonical.com

---

=== modified file 'parser/parser_main.c'
--- parser/parser_main.c2012-07-17 23:00:53 +
+++ parser/parser_main.c2012-08-07 15:55:43 +
@@ -24,6 +24,7 @@
 #include string.h
 #include stdlib.h
 #include stdarg.h
+#include stddef.h
 #include getopt.h
 #include errno.h
 #include fcntl.h
@@ -71,6 +72,7 @@
 int skip_cache = 0;
 int skip_read_cache = 0;
 int write_cache = 0;
+int clear_cache = 0;   /* only applies if write is set */
 int preprocess_only = 0;
 int skip_mode_force = 0;
 struct timespec mru_tstamp;
@@ -109,6 +111,8 @@
{skip-read-cache, 0, 0, 'T'},
{write-cache, 0, 0, 'W'},
{show-cache,  0, 0, 'k'},
+   {clear-cache, 0, 0, 128}, /* no short option */
+   {no-clear-cache,  0, 0, 129}, /* no short option */
{cache-loc,   1, 0, 'L'},
{debug,   0, 0, 'd'},
{dump,1, 0, 'D'},
@@ -151,6 +155,7 @@
   -K, --skip-cacheDo not attempt to load or save cached 
profiles\n
   -T, --skip-read-cache   Do not attempt to load cached 
profiles\n
   -W, --write-cache   Save cached profile (force with -T)\n
+  --clear-cache   Clear cache\n
   -L, --cache-loc n   Set the location of the profile cache\n
   -q, --quiet Don't emit warnings\n
   -v, --verbose   Show profile names as they load\n
@@ -527,6 +532,12 @@
case 'T':
skip_read_cache = 1;
break;
+   case 128:
+   clear_cache = 1;
+   break;
+   case 129:
+   clear_cache = 0;
+   break;
case 'L':
cacheloc = strdup(optarg);
break;
@@ -1165,6 +1176,120 @@
return retval;
 }
 
+static int dir_for_each(const char *dname,
+   int (* callback)(const char *, struct dirent *,
+struct stat *)) {
+   struct dirent *dirent, *ent;
+   char *path = NULL;
+   DIR *dir = NULL;
+   int error;
+
+   dirent = malloc(offsetof(struct dirent, d_name) +
+   pathconf(dname, _PC_NAME_MAX) + 1);
+   if (!dirent) {
+   PDEBUG(_(could not alloc dirent));
+   return -1;
+   }
+
+   PDEBUG(Opened cache directory \%s\\n, dname);
+   if (!(dir = opendir(dname))) {
+   free(dirent);
+   PDEBUG(_(opendir failed '%s'), dname);
+   return 

Re: [apparmor] Cache update broken

2012-08-07 Thread John Johansen
On 08/07/2012 09:58 AM, Seth Arnold wrote:
 The patch reads well, though the --help needs to indicate that the flag only 
 works if --write-cache is given _and_the features don't match.
 
 I would much rather --clear-cache be a debugging tool for sysadmin use that 
 immediately and directly clears the cache, and introduce a different name for 
 this option. I propose --clear-cache-if-needed.
 
I am okay with --clear-cache-if-needed but its going to be used as more than a 
debugging tool
suse will be using it in conjunction with --write-cache to clear the cache out 
when the
feature set changes.

 I think the test (yay tests) would read better with this changed to use cmp 
 -s:
 
 +echo -n monkey | diff -q $basedir/cache/$profile - | grep -q 'differ' || { 
 echo FAIL; exit 1; }
 
 +echo -n monkey | cmp -s $basedir/cache/$profile || { echo FAIL; exit 1; }
 
sure


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


Re: [apparmor] Cache update broken

2012-08-07 Thread Christian Boltz
Hello,

John, thanks for honoring the golden rules of bad programming in your 
patch! I'm especially talking about rule 18 - take great care in 
setting bad defaults ;-)

Am Dienstag, 7. August 2012 schrieb Seth Arnold:
 I expect --clear-cache-if-needed to be the default set in the config
 file 

Let me ask a simple question: Can you give me a good reason _not_ to 
automatically clear the cache if .features differs, and to keep an 
outdated cache? [1]

IMHO most people want their cache updated automatically, and it doesn't 
make much sense to force everybody to add --clear-cache-if-needed to the 
initscript or the config file.

Can we please make it the default _without_ the need for an additional 
parameter or config option?


If you really want, feel free to introduce a 
--never-clear-cache-automatically
parrameter / config file option - but I doubt many people will use it 
;-)

 -- redundant for ubuntu but also a chance to bring both
 initscripts together again -- at least for this feature.

I don't know the history and background why there are separate 
initscripts (pointers welcome), but I'm a big fan of avoiding duplicate 
work (especially if I have to maintain the duplicate ;-))

 A direct --clear-cache would just be a debugging tool for admins, and
 rarely used (hopefully) at that.

Indeed. It might be a nice feature, but I'd give it a low priority [2].
The avarage admin most probably knows how to delete all files in a 
directory ;-)


Regards,

Christian Boltz

[1] oh, now I remember: 
rule 22 - invent new ways to make your program slow 
;-)

[2] aa-enable is more important IMHO because it needs to
a) delete a symlink
b) load the profile
-- 
Ich selbst benutze kweather nicht (ich guck einfach aus dem Fenster).
[Hartmut Meyer in suse-linux]


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


Re: [apparmor] Cache update broken

2012-08-07 Thread John Johansen
On 08/07/2012 01:34 PM, Christian Boltz wrote:
 Hello,
 
 John, thanks for honoring the golden rules of bad programming in your 
 patch! I'm especially talking about rule 18 - take great care in 
 setting bad defaults ;-)
 
Hehe I did it on purpose to get a discussion of what it should be on
list :)

Basically I was hoping for more input than just our little discussion,
and the change is really easy to make so a 2nd iteration won't take
very long.

 Am Dienstag, 7. August 2012 schrieb Seth Arnold:
 I expect --clear-cache-if-needed to be the default set in the config
 file 
 
 Let me ask a simple question: Can you give me a good reason _not_ to 
 automatically clear the cache if .features differs, and to keep an 
 outdated cache? [1]
 
well I can think of a corner case where you are booting between different
kernels, and want to keep one. But I don't really think that is a good
reason, and I think the proper solution for that is having separate caches
for each kernel.

 IMHO most people want their cache updated automatically, and it doesn't 
 make much sense to force everybody to add --clear-cache-if-needed to the 
 initscript or the config file.
 
 Can we please make it the default _without_ the need for an additional 
 parameter or config option?
 
 
Well I suspect that is what we will do

 If you really want, feel free to introduce a 
 --never-clear-cache-automatically
 parrameter / config file option - but I doubt many people will use it 
 ;-)
 
 -- redundant for ubuntu but also a chance to bring both
 initscripts together again -- at least for this feature.
 
 I don't know the history and background why there are separate 
 initscripts (pointers welcome), but I'm a big fan of avoiding duplicate 
 work (especially if I have to maintain the duplicate ;-))
 
Well the history is fairly simple, Ubuntu added caching support when it
was in a very early iteration in the parser. I can't remember whether
there was even time stamp checks in the first iteration that shipped
(you could do that by dumping the profile out using -S and using a
separate utility to do the actual load).

But I do know that timestamp changes within include files where not taken
into account and cache clearing was being done by a script.

The goal has always been to merge back changes where appropriate or
replace the code as thing in the upstream project progressed. So keeping
the old script behavior isn't necessarily a goal. Using the --write-cache
with cache-clearing will have to be brought up and discussed.

I specifically mentioned that suse was going to use this for its cache
in my reply to Seth because I misunderstood what he was saying about a
debug option. Of course he is right, a clear cache option that isn't
default does feel like an admin debug option.


 A direct --clear-cache would just be a debugging tool for admins, and
 rarely used (hopefully) at that.
 
 Indeed. It might be a nice feature, but I'd give it a low priority [2].
 The avarage admin most probably knows how to delete all files in a 
 directory ;-)
 
yeah well thankfully that debug option is really easy to do now.

 
 Regards,
 
 Christian Boltz
 
 [1] oh, now I remember: 
 rule 22 - invent new ways to make your program slow 
 ;-)
 
Having broken cache management is a new way to make your program slow?

:)

 [2] aa-enable is more important IMHO because it needs to
 a) delete a symlink
 b) load the profile
 
sure that make sense, but I'll way it against I am in the patch right
now and can add it with just a few lines of code while its fresh in
my mind.


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


Re: [apparmor] Cache update broken

2012-08-07 Thread John Johansen
On 08/04/2012 06:53 AM, Christian Boltz wrote:
 Hello,
 
okay attached is v2 of the patch, its changes are:

* makes cache clearing the default behavior if --write-cache is enabled
* changes --no-clear-cache to --skip-bad-cache (really the same thing but
  hopefully a better name?)
* adds a --purge-cache debug option to force the cache to be cleared
  regardless of state
* adds documentation to the apparmor_parser man page

---

apparmor: add clearing the profile cache when inconsistent

Add the ability to clear out the binary profile cache. This removes the
need to have a separate script to handle the logic of checking and
removing the cache if it is out of date.

The parser already does all the checking to determine cache validity
so it makes sense to allow the parser to clear out inconsistent cache
when it has been instructed to update the cache.

Signed-off-by: John Johnansen john.johan...@canonical.com

---

=== modified file 'parser/apparmor_parser.pod'
--- parser/apparmor_parser.pod  2012-02-24 12:21:59 +
+++ parser/apparmor_parser.pod  2012-08-07 22:06:34 +
@@ -138,6 +138,15 @@
 is running with --replace, it may make sense to also use
 --skip-read-cache with the --write-cache option.
 
+=item -W, --purge-cache
+
+Unconditionally clear out cached profiles.
+
+=item -W, --skip-bad-cache
+
+Skip updating the cache if it contains cached profiles in a bad or
+inconsistant state
+
 =item -L, --cache-loc
 
 Set the location of the cache directory.  If not specified the cache location

=== modified file 'parser/parser_main.c'
--- parser/parser_main.c2012-07-17 23:00:53 +
+++ parser/parser_main.c2012-08-07 22:00:54 +
@@ -24,6 +24,7 @@
 #include string.h
 #include stdlib.h
 #include stdarg.h
+#include stddef.h
 #include getopt.h
 #include errno.h
 #include fcntl.h
@@ -71,6 +72,8 @@
 int skip_cache = 0;
 int skip_read_cache = 0;
 int write_cache = 0;
+int cond_clear_cache = 1;  /* only applies if write is set */
+int force_clear_cache = 0; /* force clearing regargless of state */
 int preprocess_only = 0;
 int skip_mode_force = 0;
 struct timespec mru_tstamp;
@@ -109,6 +112,8 @@
{skip-read-cache, 0, 0, 'T'},
{write-cache, 0, 0, 'W'},
{show-cache,  0, 0, 'k'},
+   {skip-bad-cache,  0, 0, 129}, /* no short option */
+   {purge-cache, 0, 0, 130}, /* no short option */
{cache-loc,   1, 0, 'L'},
{debug,   0, 0, 'd'},
{dump,1, 0, 'D'},
@@ -151,6 +156,8 @@
   -K, --skip-cacheDo not attempt to load or save cached 
profiles\n
   -T, --skip-read-cache   Do not attempt to load cached 
profiles\n
   -W, --write-cache   Save cached profile (force with -T)\n
+  --skip-bad-cacheDon't clear cache if out of sync\n
+  --purge-cache   Clear cache regardless of its state\n
   -L, --cache-loc n   Set the location of the profile cache\n
   -q, --quiet Don't emit warnings\n
   -v, --verbose   Show profile names as they load\n
@@ -527,6 +534,12 @@
case 'T':
skip_read_cache = 1;
break;
+   case 129:
+   cond_clear_cache = 0;
+   break;
+   case 130:
+   force_clear_cache = 1;
+   break;
case 'L':
cacheloc = strdup(optarg);
break;
@@ -1165,11 +1178,128 @@
return retval;
 }
 
+static int dir_for_each(const char *dname,
+   int (* callback)(const char *, struct dirent *,
+struct stat *)) {
+   struct dirent *dirent, *ent;
+   char *path = NULL;
+   DIR *dir = NULL;
+   int error;
+
+   dirent = malloc(offsetof(struct dirent, d_name) +
+   pathconf(dname, _PC_NAME_MAX) + 1);
+   if (!dirent) {
+   PDEBUG(_(could not alloc dirent));
+   return -1;
+   }
+
+   PDEBUG(Opened cache directory \%s\\n, dname);
+   if (!(dir = opendir(dname))) {
+   free(dirent);
+   PDEBUG(_(opendir failed '%s'), dname);
+   return -1;
+   }
+
+   for (error = readdir_r(dir, dirent, ent);
+error == 0  ent != NULL;
+error = readdir_r(dir, dirent, ent)) {
+   struct stat my_stat;
+
+   if (strcmp(dirent-d_name, .) == 0 ||
+   strcmp(dirent-d_name, ..) == 0)
+   continue;
+
+   if (asprintf(path, %s/%s, dname, dirent-d_name)  0)
+   {
+   PDEBUG(_(Memory allocation error.));
+   goto fail;
+   }
+   
+   if (stat(path, my_stat)) {
+   PDEBUG(_(stat failed for '%s'), path);
+   goto fail;
+

Re: [apparmor] Cache update broken

2012-08-07 Thread Seth Arnold
Excellent, it feels much improved despite breaking Christian's Rules. :)

Could you add another monkey test for --purge-cache?

The short option -W leaked into the manpage update.

Thanks John.
-Original Message-
From: John Johansen john.johan...@canonical.com
Sender: apparmor-boun...@lists.ubuntu.com
Date: Tue, 07 Aug 2012 15:14:21 
To: Christian Boltzappar...@cboltz.de
Cc: apparmor@lists.ubuntu.com
Subject: Re: [apparmor] Cache update broken

On 08/04/2012 06:53 AM, Christian Boltz wrote:
 Hello,
 
okay attached is v2 of the patch, its changes are:

* makes cache clearing the default behavior if --write-cache is enabled
* changes --no-clear-cache to --skip-bad-cache (really the same thing but
  hopefully a better name?)
* adds a --purge-cache debug option to force the cache to be cleared
  regardless of state
* adds documentation to the apparmor_parser man page

---

apparmor: add clearing the profile cache when inconsistent

Add the ability to clear out the binary profile cache. This removes the
need to have a separate script to handle the logic of checking and
removing the cache if it is out of date.

The parser already does all the checking to determine cache validity
so it makes sense to allow the parser to clear out inconsistent cache
when it has been instructed to update the cache.

Signed-off-by: John Johnansen john.johan...@canonical.com

---

=== modified file 'parser/apparmor_parser.pod'
--- parser/apparmor_parser.pod  2012-02-24 12:21:59 +
+++ parser/apparmor_parser.pod  2012-08-07 22:06:34 +
@@ -138,6 +138,15 @@
 is running with --replace, it may make sense to also use
 --skip-read-cache with the --write-cache option.
 
+=item -W, --purge-cache
+
+Unconditionally clear out cached profiles.
+
+=item -W, --skip-bad-cache
+
+Skip updating the cache if it contains cached profiles in a bad or
+inconsistant state
+
 =item -L, --cache-loc
 
 Set the location of the cache directory.  If not specified the cache location

=== modified file 'parser/parser_main.c'
--- parser/parser_main.c2012-07-17 23:00:53 +
+++ parser/parser_main.c2012-08-07 22:00:54 +
@@ -24,6 +24,7 @@
 #include string.h
 #include stdlib.h
 #include stdarg.h
+#include stddef.h
 #include getopt.h
 #include errno.h
 #include fcntl.h
@@ -71,6 +72,8 @@
 int skip_cache = 0;
 int skip_read_cache = 0;
 int write_cache = 0;
+int cond_clear_cache = 1;  /* only applies if write is set */
+int force_clear_cache = 0; /* force clearing regargless of state */
 int preprocess_only = 0;
 int skip_mode_force = 0;
 struct timespec mru_tstamp;
@@ -109,6 +112,8 @@
{skip-read-cache, 0, 0, 'T'},
{write-cache, 0, 0, 'W'},
{show-cache,  0, 0, 'k'},
+   {skip-bad-cache,  0, 0, 129}, /* no short option */
+   {purge-cache, 0, 0, 130}, /* no short option */
{cache-loc,   1, 0, 'L'},
{debug,   0, 0, 'd'},
{dump,1, 0, 'D'},
@@ -151,6 +156,8 @@
   -K, --skip-cacheDo not attempt to load or save cached 
profiles\n
   -T, --skip-read-cache   Do not attempt to load cached 
profiles\n
   -W, --write-cache   Save cached profile (force with -T)\n
+  --skip-bad-cacheDon't clear cache if out of sync\n
+  --purge-cache   Clear cache regardless of its state\n
   -L, --cache-loc n   Set the location of the profile cache\n
   -q, --quiet Don't emit warnings\n
   -v, --verbose   Show profile names as they load\n
@@ -527,6 +534,12 @@
case 'T':
skip_read_cache = 1;
break;
+   case 129:
+   cond_clear_cache = 0;
+   break;
+   case 130:
+   force_clear_cache = 1;
+   break;
case 'L':
cacheloc = strdup(optarg);
break;
@@ -1165,11 +1178,128 @@
return retval;
 }
 
+static int dir_for_each(const char *dname,
+   int (* callback)(const char *, struct dirent *,
+struct stat *)) {
+   struct dirent *dirent, *ent;
+   char *path = NULL;
+   DIR *dir = NULL;
+   int error;
+
+   dirent = malloc(offsetof(struct dirent, d_name) +
+   pathconf(dname, _PC_NAME_MAX) + 1);
+   if (!dirent) {
+   PDEBUG(_(could not alloc dirent));
+   return -1;
+   }
+
+   PDEBUG(Opened cache directory \%s\\n, dname);
+   if (!(dir = opendir(dname))) {
+   free(dirent);
+   PDEBUG(_(opendir failed '%s'), dname);
+   return -1;
+   }
+
+   for (error = readdir_r(dir, dirent, ent);
+error == 0  ent != NULL;
+error = readdir_r(dir, dirent, ent)) {
+   struct stat my_stat;
+
+   if (strcmp(dirent-d_name, .) 

Re: [apparmor] Cache update broken

2012-08-07 Thread John Johansen
On 08/07/2012 03:26 PM, Seth Arnold wrote:
 Excellent, it feels much improved despite breaking Christian's Rules. :)
 
heh, well hopefully this version fixes that

 Could you add another monkey test for --purge-cache?
 
sure

 The short option -W leaked into the manpage update.
 
fixed, thanks


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


Re: [apparmor] Cache update broken

2012-08-07 Thread Christian Boltz
Hello,

(I've seen the updated patch and already submitted it to a test package 
in the OBS in home:cboltz - but I'll comment on this mail nevertheless. 
Most of the comments below should have a SCNR marker - don't take them 
too serious ;-)

Am Dienstag, 7. August 2012 schrieb John Johansen:
 On 08/07/2012 01:34 PM, Christian Boltz wrote:
  John, thanks for honoring the golden rules of bad programming in
  your
  patch! I'm especially talking about rule 18 - take great care in
  setting bad defaults ;-)
 
 Hehe I did it on purpose to get a discussion of what it should be on
 list :)

Looks like it worked ;-)

  Am Dienstag, 7. August 2012 schrieb Seth Arnold:
  I expect --clear-cache-if-needed to be the default set in the
  config
  file
  
  Let me ask a simple question: Can you give me a good reason _not_ to
  automatically clear the cache if .features differs, and to keep an
  outdated cache? [1]
 
 well I can think of a corner case where you are booting between
 different kernels, and want to keep one. But I don't really think
 that is a good reason, 

That's indeed a corner case - but OTOH people doing this will waste 
lots of time with booting - updating the cache every time they choose 
another kernel is only a small part of this and won't hurt much.

 and I think the proper solution for that is
 having separate caches for each kernel.

... and run a cleanup script whenever an old kernel is removed? 
That's of course possible, but I'd say it's not worth the effort. 
(Hey, it's just a cache, and worst thing that can happen is that we 
waste some seconds.)

  -- redundant for ubuntu but also a chance to bring both
  initscripts together again -- at least for this feature.
  
  I don't know the history and background why there are separate
  initscripts (pointers welcome), but I'm a big fan of avoiding
  duplicate work (especially if I have to maintain the duplicate ;-))
 
 Well the history is fairly simple, Ubuntu added caching support when
 it was in a very early iteration in the parser. [...]

Sounds like someone didn't like if blocks ;-)
Hmmm... Wasn't there something? Wait...

Rule 14: Don't use small if blocks. Use cp instead.

*SCNR*

  [1] oh, now I remember:
  rule 22 - invent new ways to make your program slow
  
  ;-)
 
 Having broken cache management is a new way to make your program slow?
 :)

Yes - it makes booting slow because it keeps the useless cache. I'm not 
sure if someone used this method before to slow down booting ;-) so it 
might really be really new.
(I'm talking about the load the AppArmor profiles part of booting 
here, of course.)

  [2] aa-enable is more important IMHO because it needs to
  a) delete a symlink
  b) load the profile
 
 sure that make sense, but I'll way it against I am in the patch right
 now and can add it with just a few lines of code while its fresh in
 my mind.

Of course. My footnote was more about at which position of your 
wishlist would you place these features?  That's all ;-)
If we get a lower-priority feature nearly for free, I won't object ;-)


Regards,

Christian Boltz
-- 
 [1] Schmerzen wg. einer Zerrung
 --
 Nicht alles, was hinkt, ist ein Vergleich.
In manchen Fällen ist es auch ein David Haller... *SCNR*
[ David Haller und Mario van der Linde in suse-linux]


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