static bool GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) { struct kinfo_proc proc_kinfo; size_t proc_kinfo_size; if (process_info.ProcessIDIsValid()) { int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)process_info.GetProcessID() }; proc_kinfo_size = sizeof(struct kinfo_proc); if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) { if (proc_kinfo_size > 0) { process_info.SetParentProcessID (proc_kinfo.ki_ppid); process_info.SetUserID (proc_kinfo.ki_ruid); process_info.SetGroupID (proc_kinfo.ki_rgid); process_info.SetEffectiveUserID (proc_kinfo.ki_uid); if (proc_kinfo.ki_ngroups > 0) process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]); else process_info.SetEffectiveGroupID (UINT32_MAX); return true; } } } process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID); process_info.SetUserID (UINT32_MAX); process_info.SetGroupID (UINT32_MAX); process_info.SetEffectiveUserID (UINT32_MAX); process_info.SetEffectiveGroupID (UINT32_MAX); return false; }
uint32_t Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) { process_infos.Clear(); AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); if (!snapshot.IsValid()) return 0; PROCESSENTRY32 pe = {0}; pe.dwSize = sizeof(PROCESSENTRY32); if (Process32First(snapshot.get(), &pe)) { do { AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr); ProcessInstanceInfo process; process.SetExecutableFile(FileSpec(pe.szExeFile, false), true); process.SetProcessID(pe.th32ProcessID); process.SetParentProcessID(pe.th32ParentProcessID); GetProcessExecutableAndTriple(handle, process); if (match_info.MatchAllProcesses() || match_info.Matches(process)) process_infos.Append(process); } while (Process32Next(snapshot.get(), &pe)); } return process_infos.GetSize(); }
static bool GetNetBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) { ::kvm_t *kdp; char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */ struct ::kinfo_proc2 *proc_kinfo; const int pid = process_info.GetProcessID(); int nproc; if (!process_info.ProcessIDIsValid()) goto error; if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) goto error; if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_PID, pid, sizeof(struct ::kinfo_proc2), &nproc)) == NULL) { ::kvm_close(kdp); goto error; } if (nproc < 1) { ::kvm_close(kdp); /* XXX: we don't check for error here */ goto error; } process_info.SetParentProcessID (proc_kinfo->p_ppid); process_info.SetUserID (proc_kinfo->p_ruid); process_info.SetGroupID (proc_kinfo->p_rgid); process_info.SetEffectiveUserID (proc_kinfo->p_uid); process_info.SetEffectiveGroupID (proc_kinfo->p_gid); ::kvm_close(kdp); /* XXX: we don't check for error here */ return true; error: process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID); process_info.SetUserID (UINT32_MAX); process_info.SetGroupID (UINT32_MAX); process_info.SetEffectiveUserID (UINT32_MAX); process_info.SetEffectiveGroupID (UINT32_MAX); return false; }
static bool GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid) { tracerpid = 0; process_info.Clear(); ::memset (&stat_info, 0, sizeof(stat_info)); stat_info.ppid = LLDB_INVALID_PROCESS_ID; // Use special code here because proc/[pid]/exe is a symbolic link. char link_path[PATH_MAX]; char exe_path[PATH_MAX] = ""; if (snprintf (link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) <= 0) return false; ssize_t len = readlink (link_path, exe_path, sizeof(exe_path) - 1); if (len <= 0) return false; // readlink does not append a null byte. exe_path[len] = 0; // If the binary has been deleted, the link name has " (deleted)" appended. // Remove if there. static const ssize_t deleted_len = strlen(" (deleted)"); if (len > deleted_len && !strcmp(exe_path + len - deleted_len, " (deleted)")) { exe_path[len - deleted_len] = 0; } else { GetELFProcessCPUType (exe_path, process_info); } process_info.SetProcessID(pid); process_info.GetExecutableFile().SetFile(exe_path, false); lldb::DataBufferSP buf_sp; // Get the process environment. buf_sp = ReadProcPseudoFile(pid, "environ"); Args &info_env = process_info.GetEnvironmentEntries(); char *next_var = (char *)buf_sp->GetBytes(); char *end_buf = next_var + buf_sp->GetByteSize(); while (next_var < end_buf && 0 != *next_var) { info_env.AppendArgument(next_var); next_var += strlen(next_var) + 1; } // Get the commond line used to start the process. buf_sp = ReadProcPseudoFile(pid, "cmdline"); // Grab Arg0 first. char *cmd = (char *)buf_sp->GetBytes(); process_info.SetArg0(cmd); // Now process any remaining arguments. Args &info_args = process_info.GetArguments(); char *next_arg = cmd + strlen(cmd) + 1; end_buf = cmd + buf_sp->GetByteSize(); while (next_arg < end_buf && 0 != *next_arg) { info_args.AppendArgument(next_arg); next_arg += strlen(next_arg) + 1; } // Read /proc/$PID/stat to get our parent pid. if (ReadProcPseudoFileStat (pid, stat_info)) { process_info.SetParentProcessID (stat_info.ppid); } // Get User and Group IDs and get tracer pid. GetLinuxProcessUserAndGroup (pid, process_info, tracerpid); return true; }
static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo, ProcessState &State, ::pid_t &TracerPid) { auto BufferOrError = getProcFile(Pid, "status"); if (!BufferOrError) return false; llvm::StringRef Rest = BufferOrError.get()->getBuffer(); while(!Rest.empty()) { llvm::StringRef Line; std::tie(Line, Rest) = Rest.split('\n'); if (Line.consume_front("Gid:")) { // Real, effective, saved set, and file system GIDs. Read the first two. Line = Line.ltrim(); uint32_t RGid, EGid; Line.consumeInteger(10, RGid); Line = Line.ltrim(); Line.consumeInteger(10, EGid); ProcessInfo.SetGroupID(RGid); ProcessInfo.SetEffectiveGroupID(EGid); } else if (Line.consume_front("Uid:")) { // Real, effective, saved set, and file system UIDs. Read the first two. Line = Line.ltrim(); uint32_t RUid, EUid; Line.consumeInteger(10, RUid); Line = Line.ltrim(); Line.consumeInteger(10, EUid); ProcessInfo.SetUserID(RUid); ProcessInfo.SetEffectiveUserID(EUid); } else if (Line.consume_front("PPid:")) { ::pid_t PPid; Line.ltrim().consumeInteger(10, PPid); ProcessInfo.SetParentProcessID(PPid); } else if (Line.consume_front("State:")) { char S = Line.ltrim().front(); switch (S) { case 'R': State = ProcessState::Running; break; case 'S': State = ProcessState::Sleeping; break; case 'D': State = ProcessState::DiskSleep; break; case 'Z': State = ProcessState::Zombie; break; case 'T': State = ProcessState::TracedOrStopped; break; case 'W': State = ProcessState::Paging; break; } } else if (Line.consume_front("TracerPid:")) { Line = Line.ltrim(); Line.consumeInteger(10, TracerPid); } } return true; }