aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Orr <martin@martinorr.name>2012-03-26 17:31:25 +0200
committerEric Paris <eparis@redhat.com>2012-03-28 14:52:14 -0400
commit72ea5dec7cbbc1c62a0850eff3a7a91df42bc104 (patch)
tree521ec9fdc25822b4ad4a282b33ef17d1f424e075
parent38e93bad1ffd99e698d24541793148e1da587389 (diff)
downloadandroid_external_selinux-72ea5dec7cbbc1c62a0850eff3a7a91df42bc104.tar.gz
android_external_selinux-72ea5dec7cbbc1c62a0850eff3a7a91df42bc104.tar.bz2
android_external_selinux-72ea5dec7cbbc1c62a0850eff3a7a91df42bc104.zip
policycoreutils: Fix infinite loop with inotify on 2.6.31 kernels
With kernel 2.6.31, restorecond uses 99% of my CPU. This is because removing and readding the watch on utmp triggers inotify to return an IN_IGNORED event for the old watch descriptor. If the watch gets allocated the same wd when it is readded, then restorecond thinks that utmp has changed, so removes and readds the watch again, potentially looping. With kernel <= 2.6.30, this never happened, because the kernel didn't reuse watch descriptors. So the IN_IGNORED event comes with a wd that is no longer in use, and gets ignored. But kernel 2.6.31 reuses the same watch descriptor. The kernel has been fixed to not reuse watch descriptors. However as some kernels do reuse them, and its possible they may again, this patch fixes that by ignoring inotify events whose only bit set is IN_IGNORED. Signed-off-by: Martin Orr <martin@martinorr.name> Signed-off-by: Manoj Srivastava <srivasta@debian.org> Signed-off-by: Laurent Bigonville <bigon@debian.org> Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Dan Walsh <dwalsh@redhat.com>
-rw-r--r--policycoreutils/restorecond/watch.c28
1 files changed, 15 insertions, 13 deletions
diff --git a/policycoreutils/restorecond/watch.c b/policycoreutils/restorecond/watch.c
index 6a833c30..9a45cba0 100644
--- a/policycoreutils/restorecond/watch.c
+++ b/policycoreutils/restorecond/watch.c
@@ -186,20 +186,22 @@ int watch(int fd, const char *watch_file)
printf("wd=%d mask=%u cookie=%u len=%u\n",
event->wd, event->mask,
event->cookie, event->len);
- if (event->wd == master_wd)
- read_config(fd, watch_file);
- else {
- switch (utmpwatcher_handle(fd, event->wd)) {
- case -1: /* Message was not for utmpwatcher */
- if (event->len)
- watch_list_find(event->wd, event->name);
- break;
- case 1: /* utmp has changed need to reload */
+ if (event->mask & ~IN_IGNORED) {
+ if (event->wd == master_wd)
read_config(fd, watch_file);
- break;
-
- default: /* No users logged in or out */
- break;
+ else {
+ switch (utmpwatcher_handle(fd, event->wd)) {
+ case -1: /* Message was not for utmpwatcher */
+ if (event->len)
+ watch_list_find(event->wd, event->name);
+ break;
+ case 1: /* utmp has changed need to reload */
+ read_config(fd, watch_file);
+ break;
+
+ default: /* No users logged in or out */
+ break;
+ }
}
}