*/
#include "tests_common.h"
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
+#include <grp.h>
+#include <errno.h>
+#include <vector>
+#include <algorithm>
int DB::Transaction::db_result = PC_OPERATION_SUCCESS;
#endif
}
-void closeFdPtr(int *fd)
-{
- close(*fd);
-}
-
/**
* Dropping root privileges
* returns 0 on success, 1 on error
*/
-int drop_root_privileges(void)
+int drop_root_privileges(uid_t appUid, gid_t appGid)
{
if (getuid() == 0) {
/* process is running as root, drop privileges */
- if (setgid(APP_GID) != 0)
+ if (setgid(appGid) != 0)
return 1;
- if (setuid(APP_UID) != 0)
+ if (setuid(appUid) != 0)
return 1;
}
uid_t uid = getuid();
- if (uid == APP_UID)
+ if (uid == appUid)
return 0;
return 1;
RUNNER_ASSERT_MSG(ret == 0, "Error in smack_set_label_for_self(): " << ret << ", line: " << line);
}
+/*
+ * Add a new group to the current process groups.
+ */
+void add_process_group(const char* group_name)
+{
+ // get group ID by group name
+ group *gr = getgrnam(group_name);
+ RUNNER_ASSERT_ERRNO_MSG(gr != nullptr, "getgrnam failed on '" << group_name << "' group");
+ const gid_t new_group_id = gr->gr_gid;
+
+ // get number of groups that the current process belongs to
+ int ngroups = getgroups(0, nullptr);
+
+ //allocate groups table + space for new group entry
+ std::vector<gid_t> groups(ngroups + 1);
+ getgroups(ngroups, groups.data());
+
+ // check if the process already belongs to the group
+ if (std::find(groups.begin(), groups.end(), new_group_id) != groups.end()) return;
+
+ // add new group & apply change
+ groups[ngroups] = new_group_id;
+ int ret = setgroups(groups.size(), groups.data());
+ RUNNER_ASSERT_ERRNO_MSG(ret == 0, "setgroups() failed");
+}
+
+/*
+ * Remove specific group from the current process groups.
+ */
+void remove_process_group(const char* group_name)
+{
+ // get group ID by group name
+ group *gr = getgrnam(group_name);
+ RUNNER_ASSERT_ERRNO_MSG(gr != nullptr, "getgrnam failed on '" << group_name << "' group");
+ const gid_t new_group_id = gr->gr_gid;
+
+ int ngroups = getgroups(0, nullptr);
+ std::vector<gid_t> groups(ngroups);
+ getgroups(ngroups, groups.data());
+
+ // remove group from the list
+ groups.erase(std::remove(groups.begin(), groups.end(), new_group_id), groups.end());
+
+ if (groups.size() != (size_t)ngroups) {
+ // apply change
+ int ret = setgroups(groups.size(), groups.data());
+ RUNNER_ASSERT_ERRNO_MSG(ret == 0, "setgroups() failed");
+ }
+}
+
+std::string formatCstr(const char *cstr)
+{
+ if (!cstr)
+ return std::string("nullptr");
+ return std::string("\"") + cstr + "\"";
+}
+
+int files_compare(int fd1, int fd2)
+{
+ //for getting files sizes
+ struct stat fs1, fs2;
+
+ //handlers for mmap()
+ void *h1 = MAP_FAILED;
+ void *h2 = MAP_FAILED;
+
+ //getting files information
+ RUNNER_ASSERT_ERRNO_MSG(fstat(fd1, &fs1) == 0, "fstat failed");
+ RUNNER_ASSERT_ERRNO_MSG(fstat(fd2, &fs2) == 0, "fstat failed");
+
+ if (fs1.st_size < fs2.st_size) {
+ return -1;
+ }
+
+ if (fs1.st_size > fs2.st_size) {
+ return 1;
+ }
+
+ //since Linux 2.6.12, mmap returns EINVAL if length is 0
+ //if both lengths are 0, files are actually the same
+ if (0 == fs1.st_size && 0 == fs2.st_size) {
+ return 0;
+ }
+
+ //mapping files to process memory
+ RUNNER_ASSERT_ERRNO_MSG((h1 = mmap(0, fs1.st_size, PROT_READ, MAP_SHARED, fd1, 0 )) != MAP_FAILED,
+ "mmap failed for fd=" << fd1);
+
+ if ((h2 = mmap(0, fs2.st_size, PROT_READ, MAP_SHARED, fd2, 0 )) == MAP_FAILED) {
+ munmap(h1, fs1.st_size);
+ RUNNER_ASSERT_MSG(h2 != MAP_FAILED, "mmap failed for fd=" << fd2
+ << ". " << strerror(errno));
+ }
+
+ int result = memcmp(h1, h2, fs1.st_size);
+ munmap(h1, fs1.st_size);
+ munmap(h2, fs2.st_size);
+
+ return result;
+}
+
+void mkdirSafe(const std::string &path, mode_t mode)
+{
+ RUNNER_ASSERT_ERRNO_MSG(0 == mkdir(path.c_str(), mode) || errno == EEXIST,
+ "mkdir for <" << path << "> with mode <" << mode << "> failed");
+}
+
+void mktreeSafe(const std::string &path, mode_t mode)
+{
+ // Create subsequent parent directories
+ // Assume that path is absolute - i.e. starts with '/'
+ for (size_t pos = 0; (pos = path.find("/", pos + 1)) != std::string::npos; )
+ mkdirSafe(path.substr(0, pos).c_str(), mode);
+
+ mkdirSafe(path, mode);
+}
+
+void creatSafe(const std::string &path, mode_t mode)
+{
+ RUNNER_ASSERT_ERRNO_MSG(-1 != creat(path.c_str(), mode),
+ "creat for <" << path << "> with mode <" << mode << "> failed");
+}
+
+void symlinkSafe(const std::string &targetPath, const std::string &linkPath)
+{
+ RUNNER_ASSERT_ERRNO_MSG(0 == symlink(targetPath.c_str(), linkPath.c_str()),
+ "symlink for <" << linkPath << "> to <" << targetPath << "> failed");
+}
+
+void removeDir(const std::string &path)
+{
+ DIR *d = opendir(path.c_str());
+
+ if (nullptr == d) {
+ RUNNER_ASSERT_ERRNO_MSG(errno == ENOENT, "opendir of <" << path << "> failed");
+ return;
+ }
+
+ struct dirent *dirEntry;
+ while (nullptr != (dirEntry = readdir(d))) {
+ std::string entryName(dirEntry->d_name);
+ if (entryName == "." || entryName == "..")
+ continue;
+
+ std::string entryPath(path + "/" + entryName);
+ struct stat st;
+
+ RUNNER_ASSERT_ERRNO_MSG(0 == lstat(entryPath.c_str(), &st),
+ "stat for <" << entryPath << "> failed");
+ if (S_ISDIR(st.st_mode))
+ removeDir(entryPath);
+ else
+ RUNNER_ASSERT_ERRNO_MSG(0 == unlink(entryPath.c_str()),
+ "unlink for <" << entryPath << "> failed");
+ }
+
+ closedir(d);
+
+ RUNNER_ASSERT_ERRNO_MSG(0 == rmdir(path.c_str()), "rmdir for <" << path << "> failed");
+}