+/*
+The software in this package is distributed under the GNU General
+Public License version 2 (with a special exception described below).
+
+A copy of GNU General Public License (GPL) is included in this distribution,
+in the file COPYING.GPL.
+
+As a special exception, if other files instantiate templates or use macros
+or inline functions from this file, or you compile this file and link it
+with other works to produce a work based on this file, this file
+does not by itself cause the resulting work to be covered
+by the GNU General Public License.
+
+However the source code for this file must still be made available
+in accordance with section (3) of the GNU General Public License.
+
+This exception does not invalidate any other reasons why a work based
+on this file might be covered by the GNU General Public License.
+*/
/***************************************************************************
* Copyright (C) 2008 by Intra2net AG - Thomas Jarosch *
- * thomas.jarosch@intra2net.com *
- * http://www.intra2net.com *
***************************************************************************/
#include <sys/types.h>
#include <unistd.h>
+#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
return false;
}
+ // Initialize additional groups the user is a member of
+ if (initgroups(username.c_str(), getgid()) == -1)
+ return false;
+
if (setuid(my_user.Uid))
return false;
}
+
+ return true;
+}
+
+static const char *const EXE_DELETED_MARKER = " (deleted)";
+
+/** @brief Remove the deletion marker from a binary name, if applicable.
+ *
+ * @param exe Binary name as obtained from ``/proc/$PID/exe``.
+ *
+ * @return The input binary name with a trailing `` (deleted)`` removed.
+ *
+ * From proc(5):
+ *
+ * /proc/[pid]/exe
+ * […] If the pathname has been unlinked, the symbolic link will
+ * contain the string '(deleted)' appended to the original pathname.
+ *
+ * Which introduces an ambiguity if the path of the actual binary ends in
+ * `` (deleted)``.
+ */
+static inline std::string
+strip_deleted_marker (const std::string &exe)
+{
+ if (exe.size () <= sizeof (*EXE_DELETED_MARKER)) {
+ /* This binary name can’t possibly contain a deleted marker. */
+ return exe;
+ }
+
+ const size_t found = exe.rfind (EXE_DELETED_MARKER);
+ if (found == std::string::npos) {
+ /* Input does not contain the deleted marker. */
+ return exe;
+ }
+
+ return exe.substr (0, found);
}
/**
std::vector< pid_t > fuzz1_result;
std::vector< pid_t > fuzz2_result;
result.clear();
+
+ if (name.empty()) return false;
if (!get_dir("/proc", entries)) return false;
+
for (std::vector< std::string >::const_iterator it= entries.begin();
it != entries.end();
++it)
I2n::Stat stat(exe_path, false);
if (not stat or not stat.is_link()) continue;
std::string real_exe= read_link(exe_path);
- if (real_exe == name)
+ if (!real_exe.empty())
{
- result.push_back( pid );
- continue;
+ // we got the path of the exe
+ if (real_exe == name || strip_deleted_marker (real_exe) == name)
+ {
+ result.push_back( pid );
+ continue;
+ }
+
+ std::string proc_stat= read_file( base_path + "/stat");
+ if (proc_stat.empty()) continue; // process vanished
+
+ //TODO some more fuzz tests here?! (cmdline, stat(us))
+
+ real_exe = basename (real_exe);
+ if (real_exe == name || strip_deleted_marker (real_exe) == name)
+ {
+ fuzz2_result.push_back(pid);
+ continue;
+ }
}
-
- std::string proc_stat= read_file( base_path + "/stat");
- if (proc_stat.empty()) continue; // process vanished
-
- //TODO some more fuzz tests here?! (cmdline, stat(us))
-
- if (basename(real_exe) == name)
+ else
{
- fuzz2_result.push_back(pid);
- continue;
+ // we haven't got the path of the exe
+ // this can happen e.g. with processes owned by other users
+ // -> parse the commandline instead
+ std::string cmdline = read_file(base_path + "/cmdline");
+ if (cmdline.empty()) continue;
+
+ // in /proc/*/cmdline, the parameters are split by nullbytes, we only care for the first parameter
+ if (cmdline.find('\0') != string::npos)
+ cmdline.erase(cmdline.find('\0'));
+
+ if (cmdline == name)
+ {
+ result.push_back( pid );
+ continue;
+ }
+
+ if (basename(cmdline) == name)
+ {
+ fuzz2_result.push_back(pid);
+ continue;
+ }
}
}
if (result.empty())