[mapplauncherd] Create cgroup for each process if possible. Fixes MER#1896

Signed-off-by: Aleksey Mikhaylov <a.mikhaylov@omprussia.ru>
pull/1/head
Aleksey Mikhaylov 8 years ago
parent 6439643867
commit a480e5fd36

@ -38,9 +38,11 @@
#include <stdexcept>
#include <syslog.h>
#include <dirent.h>
#include <algorithm>
#include <fstream>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <grp.h>
@ -401,6 +403,96 @@ static bool isPrivileged(AppData *appData)
return privileged;
}
struct NotCharacter {
char c;
NotCharacter(const char &c) : c(c) {}
bool operator()(const char &c) const { return c != this->c; }
};
static bool mkdirRecursive(const int dirfd, const std::string &path) {
static const mode_t MODE = 0775;
struct stat st;
std::string relative;
std::string::const_iterator begin, next;
for (std::string::const_iterator i = path.begin(); i != path.end(); i = next) {
begin = std::find_if(i, path.end(), NotCharacter('/'));
next = std::find(begin, path.end(), '/');
relative.append(begin, next);
relative.append(1, '/');
if (fstatat(dirfd, relative.c_str(), &st, 0)) {
if (mkdirat(dirfd, relative.c_str(), MODE) && errno != EEXIST) {
return false;
}
} else if (!S_ISDIR(st.st_mode)) {
return false;
}
}
return true;
}
static void setCgroup(const std::string &exePath) {
static const char *BOOSTER_CGROUP_TREE = "/sys/fs/cgroup/booster";
static const char *CGROUP_PROCS = "cgroup.procs";
static const char *PROC_PID = "0";
int fd = -1;
DIR *dir = NULL;
char *cpath = NULL;
std::string path;
dir = opendir(BOOSTER_CGROUP_TREE);
if (!dir) {
Logger::logDebug("No named booster cgroup hierarchy '%s'", BOOSTER_CGROUP_TREE);
goto early;
}
cpath = realpath(exePath.c_str(), NULL);
if (!cpath) {
Logger::logDebug("Cannot resolve exe path '%s'", exePath.c_str());
goto early;
}
path = cpath;
if (!mkdirRecursive(dirfd(dir), path)) {
Logger::logDebug("Cannot create cgroup '%s'", path.c_str());
goto early;
}
path.erase(path.begin(), std::find_if(path.begin(), path.end(), NotCharacter('/')));
path = path + '/' + CGROUP_PROCS;
fd = openat(dirfd(dir), path.c_str(), O_WRONLY);
if (fd < 0) {
Logger::logDebug("Cannot open '%s' for writing", path.c_str());
goto early;
}
if (write(fd, PROC_PID, strlen(PROC_PID)) < 0) {
Logger::logDebug("Cannot move itself to cgroup before launch");
goto early;
}
early:
if (dir) {
closedir(dir);
}
if (cpath) {
free(cpath);
}
if (fd >= 0) {
close(fd);
}
return;
}
void Booster::setEnvironmentBeforeLaunch()
{
// Possibly restore process priority
@ -409,6 +501,8 @@ void Booster::setEnvironmentBeforeLaunch()
if (!errno && cur_prio < m_appData->priority())
setpriority(PRIO_PROCESS, 0, m_appData->priority());
setCgroup(m_appData->fileName());
// Currently, we only have two levels of privileges:
// privileged and non-privileged.
// Going forward, this could be improved to support

Loading…
Cancel
Save