Changelog v2:
* Use clock_gettime(2) for getting timestamp since a system boot.
* Change parent_info's memory to dynamic allocation.
This patch is for changing the cgroup of a forked process while parent
changing.
This patch adds the following sequence:
1. Store both the timestamp and the process-id when changing the cgroup.
2. If receiving a PROC_EVENT_FORK packet, check its parent-pid and its
timestamp.
3. If its parent-pid and the stored process-id are same and its timestamp
is older than the stored timestamp, change the cgroup of forked process.
Thanks
Ken'ichi Ohmichi
Signed-off-by: Ken'ichi Ohmichi <[email protected]>
---
diff -rpuN a/src/daemon/Makefile.in b/src/daemon/Makefile.in
--- a/src/daemon/Makefile.in 2009-04-22 19:18:18.000000000 +0900
+++ b/src/daemon/Makefile.in 2009-05-07 11:03:08.000000000 +0900
@@ -101,7 +101,7 @@ INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LDFLAGS = @LDFLAGS@
+LDFLAGS = @LDFLAGS@ -lrt
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
diff -rpuN a/src/daemon/cgrulesengd.c b/src/daemon/cgrulesengd.c
--- a/src/daemon/cgrulesengd.c 2009-05-07 10:31:17.000000000 +0900
+++ b/src/daemon/cgrulesengd.c 2009-05-07 10:59:53.000000000 +0900
@@ -180,6 +180,91 @@ static int cgre_get_euid_egid_from_statu
return 0;
}
+struct parent_info {
+ __u64 timestamp;
+ pid_t pid;
+};
+struct array_parent_info {
+ int index;
+ int num_allocation;
+ struct parent_info **parent_info;
+};
+struct array_parent_info array_pi;
+
+static int cgre_store_parent_info(pid_t pid)
+{
+ __u64 uptime_ns;
+ struct timespec tp;
+ struct parent_info *info;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) < 0) {
+ flog(LOG_WARNING, "Failed to get time");
+ return 1;
+ }
+ uptime_ns = ((__u64)tp.tv_sec * 1000 * 1000 * 1000 ) + tp.tv_nsec;
+
+ if (array_pi.index >= array_pi.num_allocation) {
+ array_pi.num_allocation += 100;
+ array_pi.parent_info = realloc(array_pi.parent_info,
+ sizeof(info) * array_pi.num_allocation);
+ if (!array_pi.parent_info) {
+ flog(LOG_WARNING, "Failed to allocate memory");
+ return 1;
+ }
+ }
+ info = calloc(1, sizeof(struct parent_info));
+ if (!info) {
+ flog(LOG_WARNING, "Failed to allocate memory");
+ return 1;
+ }
+ info->timestamp = uptime_ns;
+ info->pid = pid;
+
+ array_pi.parent_info[array_pi.index] = info;
+ array_pi.index++;
+
+ return 0;
+}
+
+static void cgre_remove_old_parent_info(__u64 key_timestamp)
+{
+ int i, j;
+
+ for (i = 0; i < array_pi.index; i++) {
+ if (key_timestamp < array_pi.parent_info[i]->timestamp)
+ continue;
+ free(array_pi.parent_info[i]);
+ for (j = i; j < array_pi.index - 1; j++)
+ array_pi.parent_info[j] = array_pi.parent_info[j + 1];
+ array_pi.index--;
+ i--;
+ }
+ return;
+}
+
+static int cgre_was_parent_changed_when_forking(const struct proc_event *ev)
+{
+ int i;
+ pid_t parent_pid;
+ __u64 timestamp_child;
+ __u64 timestamp_parent;
+
+ parent_pid = ev->event_data.fork.parent_pid;
+ timestamp_child = ev->timestamp_ns;
+
+ cgre_remove_old_parent_info(timestamp_child);
+
+ for (i = 0; i < array_pi.index; i++) {
+ if (parent_pid != array_pi.parent_info[i]->pid)
+ continue;
+ timestamp_parent = array_pi.parent_info[i]->timestamp;
+ if (timestamp_child > timestamp_parent)
+ continue;
+ return 1;
+ }
+ return 0;
+}
+
/**
* Process an event from the kernel, and determine the correct UID/GID/PID to
* pass to libcgroup. Then, libcgroup will decide the cgroup to move the PID
@@ -201,6 +286,15 @@ int cgre_process_event(const struct proc
case PROC_EVENT_GID:
pid = ev->event_data.id.process_pid;
break;
+ case PROC_EVENT_FORK:
+ /*
+ * If this process was forked while changing parent's cgroup,
+ * this process's cgroup also should be changed.
+ */
+ if (!cgre_was_parent_changed_when_forking(ev))
+ return 0;
+ pid = ev->event_data.fork.child_pid;
+ break;
default:
break;
}
@@ -229,6 +323,12 @@ int cgre_process_event(const struct proc
ev->event_data.id.e.egid,
pid, CGFLAG_USECACHE);
break;
+ case PROC_EVENT_FORK:
+ log_uid = euid;
+ log_gid = egid;
+ ret = cgroup_change_cgroup_uid_gid_flags(euid,
+ egid, pid, CGFLAG_USECACHE);
+ break;
default:
break;
}
@@ -242,6 +342,7 @@ int cgre_process_event(const struct proc
" FAILED! (Error Code: %d)", log_pid, log_uid, log_gid,
ret);
} else {
+ ret = cgre_store_parent_info(pid);
flog(LOG_INFO, "Cgroup change for PID: %d, UID: %d, GID: %d OK",
log_pid, log_uid, log_gid);
}
@@ -282,6 +383,9 @@ int cgre_handle_msg(struct cn_msg *cn_hd
ev->event_data.id.e.egid);
ret = cgre_process_event(ev, PROC_EVENT_GID);
break;
+ case PROC_EVENT_FORK:
+ ret = cgre_process_event(ev, PROC_EVENT_FORK);
+ break;
default:
break;
}
------------------------------------------------------------------------------
The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your
production scanning environment may not be a perfect world - but thanks to
Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700
Series Scanner you'll get full speed at 300 dpi even with all image
processing features enabled. http://p.sf.net/sfu/kodak-com
_______________________________________________
Libcg-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libcg-devel