From 5620d31b78fda7d5db0b85fcceca9c2cabe8f155 Mon Sep 17 00:00:00 2001 From: Ken'ichi Ohmichi Date: Mon, 8 Jun 2009 17:18:43 +0900 Subject: Cleanup: Integrate similar code to cgroup_get_uid_gid_from_procfs(). CHANGELOG of v2.1: ================ * Rebase the patch for commit '340feae163c4797a6cb1247b3812c1ccdc52fa41'. There are some similar functions for getting process's data (uid, gid) from /proc//status file, so this patch integrates these functions into one cgroup_get_uid_gid_from_procfs(). Signed-off-by: Ken'ichi Ohmichi Reviewed-By: Jan Safranek Signed-off-by: Dhaval Giani --- src/api.c | 55 ++++++++++++++++++++++++++++++ src/daemon/cgrulesengd.c | 56 ++++--------------------------- src/daemon/cgrulesengd.h | 7 ---- src/libcgroup-internal.h | 2 ++ src/libcgroup.map | 1 + src/tools/cgclassify.c | 87 ++---------------------------------------------- 6 files changed, 68 insertions(+), 140 deletions(-) diff --git a/src/api.c b/src/api.c index 9a379d6..ccea89c 100644 --- a/src/api.c +++ b/src/api.c @@ -2473,3 +2473,58 @@ int cgroup_get_task_begin(char *cgroup, char *controller, void **handle, return ret; } + +/** + * Get process data (euid and egid) from /proc//status file. + * @param pid: The process id + * @param euid: The uid of param pid + * @param egid: The gid of param pid + * @return 0 on success, > 0 on error. + */ +int cgroup_get_uid_gid_from_procfs(pid_t pid, uid_t *euid, gid_t *egid) +{ + FILE *f; + char path[FILENAME_MAX]; + char buf[4092]; + uid_t ruid, suid, fsuid; + gid_t rgid, sgid, fsgid; + bool found_euid = false; + bool found_egid = false; + + sprintf(path, "/proc/%d/status", pid); + f = fopen(path, "r"); + if (!f) + return ECGROUPNOTEXIST; + + while (fgets(buf, sizeof(buf), f)) { + if (!strncmp(buf, "Uid:", 4)) { + if (sscanf((buf + 5), "%d%d%d%d", &ruid, euid, + &suid, &fsuid) != 4) + break; + cgroup_dbg("Scanned proc values are %d %d %d %d\n", + ruid, *euid, suid, fsuid); + found_euid = true; + } else if (!strncmp(buf, "Gid:", 4)) { + if (sscanf((buf + 5), "%d%d%d%d", &rgid, egid, + &sgid, &fsgid) != 4) + break; + cgroup_dbg("Scanned proc values are %d %d %d %d\n", + rgid, *egid, sgid, fsgid); + found_egid = true; + } + if (found_euid && found_egid) + break; + } + fclose(f); + if (!found_euid || !found_egid) { + /* + * This method doesn't match the file format of + * /proc//status. The format has been changed + * and we should catch up the change. + */ + cgroup_dbg("The invlid file format of /proc/%d/status.\n", pid); + return ECGFAIL; + } + return 0; +} + diff --git a/src/daemon/cgrulesengd.c b/src/daemon/cgrulesengd.c index 1a7b321..4c71283 100644 --- a/src/daemon/cgrulesengd.c +++ b/src/daemon/cgrulesengd.c @@ -33,6 +33,7 @@ #include "libcgroup.h" #include "cgrulesengd.h" +#include "../libcgroup-internal.h" #include #include @@ -140,52 +141,6 @@ void flog(int level, const char *format, ...) } } -static int cgre_get_euid_egid_from_status(pid_t pid, uid_t *euid, gid_t *egid) -{ - /* Handle for the /proc/PID/status file */ - FILE *f; - - /* Path for /proc/PID/status file */ - char path[FILENAME_MAX]; - - /* Temporary buffer */ - char buf[4092]; - - /* UID data */ - uid_t ruid, suid, fsuid; - - /* GID data */ - gid_t rgid, sgid, fsgid; - - /* - * First, we need to open the /proc/PID/status file so that we can - * get the effective UID and GID for the process that we're working - * on. This process is probably not us, so we can't just call - * geteuid() or getegid(). - */ - sprintf(path, "/proc/%d/status", pid); - f = fopen(path, "r"); - if (!f) { - flog(LOG_WARNING, "Failed to open %s", path); - return 1; - } - - /* Have the eUID, need to find the eGID. */ - memset(buf, '\0', sizeof(buf)); - while (fgets(buf, sizeof(buf), f)) { - if (!strncmp(buf, "Uid:", 4)) { - sscanf((buf + 5), "%d%d%d%d", &ruid, euid, - &suid, &fsuid); - } else if (!strncmp(buf, "Gid:", 4)) { - sscanf((buf + 5), "%d%d%d%d", &rgid, egid, - &sgid, &fsgid); - } - memset(buf, '\0', sizeof(buf)); - } - fclose(f); - return 0; -} - struct parent_info { __u64 timestamp; pid_t pid; @@ -325,10 +280,13 @@ int cgre_process_event(const struct proc_event *ev, const int type) default: break; } - if (cgre_get_euid_egid_from_status(pid, &euid, &egid)) - /* cgre_get_euid_egid_from_status() returns 1 if it fails to - * open /proc//status file and that is not a problem. */ + ret = cgroup_get_uid_gid_from_procfs(pid, &euid, &egid); + if (ret == ECGROUPNOTEXIST) + /* cgroup_get_uid_gid_from_procfs() returns ECGROUPNOTEXIST + * if a process finished and that is not a problem. */ return 0; + else if (ret) + return ret; /* * Now that we have the UID, the GID, and the PID, we can make a call diff --git a/src/daemon/cgrulesengd.h b/src/daemon/cgrulesengd.h index 1840143..506cb5d 100644 --- a/src/daemon/cgrulesengd.h +++ b/src/daemon/cgrulesengd.h @@ -31,13 +31,6 @@ __BEGIN_DECLS #define __USE_GNU #endif -/* A simple macro for printing messages only when CGROUP_DEBUG is defined. */ -#ifdef CGROUP_DEBUG - #define cgroup_dbg(a...) printf(a) -#else - #define cgroup_dbg(a...) do {} while (0) -#endif /* CGROUP_DEBUG */ - /* The following ten macros are all for the Netlink code. */ #define SEND_MESSAGE_LEN (NLMSG_LENGTH(sizeof(struct cn_msg) + \ sizeof(enum proc_cn_mcast_op))) diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index 9e69f10..a80ae38 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -90,6 +90,8 @@ struct cgroup_rule_list { /* Internal API */ char *cg_build_path(char *name, char *path, char *type); +int cgroup_get_uid_gid_from_procfs(pid_t pid, uid_t *euid, gid_t *egid); + /* * config related API diff --git a/src/libcgroup.map b/src/libcgroup.map index 539687f..8d330e6 100644 --- a/src/libcgroup.map +++ b/src/libcgroup.map @@ -63,4 +63,5 @@ global: cgroup_read_stats_next; cgroup_read_stats_end; cgroup_get_controller; + cgroup_get_uid_gid_from_procfs; } CGROUP_0.33; diff --git a/src/tools/cgclassify.c b/src/tools/cgclassify.c index de10510..ceaca34 100644 --- a/src/tools/cgclassify.c +++ b/src/tools/cgclassify.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -30,80 +31,6 @@ #define TEMP_BUF 81 -/* - * Go through /proc//status file to determine the euid of the - * process. - * It returns 0 on success and negative values on failure. - */ - -int euid_of_pid(pid_t pid) -{ - FILE *fp; - char path[FILENAME_MAX]; - char buf[TEMP_BUF]; - uid_t ruid, euid, suid, fsuid; - - sprintf(path, "/proc/%d/status", pid); - fp = fopen(path, "r"); - if (!fp) { - cgroup_dbg("Error in opening file %s:%s\n", path, - strerror(errno)); - return -1; - } - - while (fgets(buf, TEMP_BUF, fp)) { - if (!strncmp(buf, "Uid:", 4)) { - sscanf((buf + 5), "%d%d%d%d", (int *)&ruid, - (int *)&euid, (int *)&suid, (int *)&fsuid); - cgroup_dbg("Scanned proc values are %d %d %d %d\n", - ruid, euid, suid, fsuid); - fclose(fp); - return euid; - } - } - fclose(fp); - - /* If we are here, we could not find euid. Return error. */ - return -1; -} - -/* - * Go through /proc//status file to determine the egid of the - * process. - * It returns 0 on success and negative values on failure. - */ - -int egid_of_pid(pid_t pid) -{ - FILE *fp; - char path[FILENAME_MAX]; - char buf[TEMP_BUF]; - gid_t rgid, egid, sgid, fsgid; - - sprintf(path, "/proc/%d/status", pid); - fp = fopen(path, "r"); - if (!fp) { - cgroup_dbg("Error in opening file %s:%s\n", path, - strerror(errno)); - return -1; - } - - while (fgets(buf, TEMP_BUF, fp)) { - if (!strncmp(buf, "Gid:", 4)) { - sscanf((buf + 5), "%d%d%d%d", (int *)&rgid, - (int *)&egid, (int *)&sgid, (int *)&fsgid); - cgroup_dbg("Scanned proc values are %d %d %d %d\n", - rgid, egid, sgid, fsgid); - fclose(fp); - return egid; - } - } - fclose(fp); - - /* If we are here, we could not find egid. Return error. */ - return -1; -} - /* * Change process group as specified on command line. */ @@ -137,16 +64,8 @@ int change_group_uid_gid(pid_t pid) int ret; /* Put pid into right cgroup as per rules in /etc/cgrules.conf */ - euid = euid_of_pid(pid); - if (euid == -1) { - fprintf(stderr, "Error in determining euid of" - " pid %d\n", pid); - return -1; - } - - egid = egid_of_pid(pid); - if (egid == -1) { - fprintf(stderr, "Error in determining egid of" + if (cgroup_get_uid_gid_from_procfs(pid, &euid, &egid)) { + fprintf(stderr, "Error in determining euid/egid of" " pid %d\n", pid); return -1; } -- cgit