diff options
author | \"Ken'ichi Ohmichi\ <oomichi@mxs.nes.nec.co.jp> | 2009-05-08 01:46:02 +0530 |
---|---|---|
committer | Balbir Singh <balbir@linux.vnet.ibm.com> | 2009-05-08 01:46:02 +0530 |
commit | 8953fc07c0498d1ddd9a04dc549ffb85862f4c5f (patch) | |
tree | 173db54f5d559bccf423b79c9464bd4d29ede084 /src/daemon/cgrulesengd.c | |
parent | 485fe65a0daa23899d1e4c02620036a265560a57 (diff) | |
download | libcg-8953fc07c0498d1ddd9a04dc549ffb85862f4c5f.tar.gz libcg-8953fc07c0498d1ddd9a04dc549ffb85862f4c5f.tar.xz libcg-8953fc07c0498d1ddd9a04dc549ffb85862f4c5f.zip |
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 <oomichi@mxs.nes.nec.co.jp>
Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Diffstat (limited to 'src/daemon/cgrulesengd.c')
-rw-r--r-- | src/daemon/cgrulesengd.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/daemon/cgrulesengd.c b/src/daemon/cgrulesengd.c index 74d12e1..07d4a5d 100644 --- a/src/daemon/cgrulesengd.c +++ b/src/daemon/cgrulesengd.c @@ -180,6 +180,91 @@ static int cgre_get_euid_egid_from_status(pid_t pid, uid_t *euid, gid_t *egid) 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_event *ev, const int type) 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_event *ev, const int type) 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_event *ev, const int type) " 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_hdr) 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; } |