【问题标题】:OSX: proc_pidinfo returns 0 for other user's processesOSX:proc_pidinfo 为其他用户的进程返回 0
【发布时间】:2020-12-29 08:50:40
【问题描述】:

我需要获取有关在 Mac OSX 上运行的进程的一些信息(PID、UID、GID、进程名称)。我试过proc_pidinfo。对于我自己的流程,它工作正常。但是,对于其他用户拥有的进程,返回 0。这个函数没有文档,但根据information found on Internet,它应该返回写入提供的缓冲区的字节数。在其他用户的进程上调用该函数返回0,表示没有提供任何信息。

例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <libproc.h>


int main(int argc, char *argv[])
{
    pid_t pid;
    struct proc_bsdinfo proc;

    if (argc == 2)
        pid = atoi(argv[1]);
    else
        pid = getpid();

    int st = proc_pidinfo(pid, PROC_PIDTBSDINFO, 0,
                         &proc, PROC_PIDTBSDINFO_SIZE);

    if (st != PROC_PIDTBSDINFO_SIZE) {
        fprintf(stderr, "Cannot get process info");
        return 1;
    }
    printf(" pid: %d\n", (int)proc.pbi_pid);
    printf("ppid: %d\n", (int)proc.pbi_ppid);
    printf("comm: %s\n",      proc.pbi_comm);
    printf("name: %s\n",      proc.pbi_name);
    printf(" uid: %d\n", (int)proc.pbi_uid);
    printf(" gid: %d\n", (int)proc.pbi_gid);

    return 0;
}

运行这个程序产生:

 $ ./pidinfo
 pid: 30519
ppid: 8434
comm: pidinfo
name: pidinfo
 uid: 501
 gid: 20
 $ ./pidinfo 1
Cannot get process info
 $ sudo ./pidinfo 1
 pid: 1
ppid: 0
comm: launchd
name: launchd
 uid: 0
 gid: 0

这很奇怪,因为我可以从ps(1) 获得所有这些信息。但后来我检查了 OSX 上的 pstop 都是 SUID 二进制文件,这符合 proc_pidinfo 的行为:

 $ ls -l `which ps` `which top`
-rwsr-xr-x  1 root  wheel  51008  5 maj 08:06 /bin/ps
-r-sr-xr-x  1 root  wheel  87952  5 maj 08:05 /usr/bin/top

但是,Activity Monitor 可以在没有 SUID 的情况下工作。

那么,我的问题是,为什么proc_pidinfo 只提供关于我自己的流程的信息?我可以让它给我有关其他流程的信息吗?如果没有,如何在不解析ps(1) 输出的情况下获取此信息?

【问题讨论】:

  • 过去,Activity Monitor 确实使用了 SUID 工具,不过现在已经改为使用以root 运行的启动守护进程:/usr/libexec/sysmond,也可能还有/usr/libexec/systemstatsd...
  • 我认为如果你以 root 权限运行proc_pidinfo,你将能够获取所有进程的信息。
  • 如果我使用sudo 运行我的程序,它可以工作 - 请参阅我的示例。但我不想以 root 身份运行我的程序。

标签: c macos


【解决方案1】:

你可以使用:

int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize);

结合 proc_pidinfo 来获取许多其他 pids 信息,例如:

#include <unistd.h>
#include <stdlib.h>
#include <mach/mach.h>
#include <libproc.h>
#include <mach/mach_time.h>
#include <sys/sysctl.h>
#include <mach-o/ldsyms.h>
#include <stdio.h>

void procpid(pid_t pid)
{ struct proc_bsdinfo proc;
  int st = proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc, PROC_PIDTBSDINFO_SIZE);
  printf("name: %s\n", proc.pbi_name);
}

void pidlist(void)
{ int bufsize = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
  pid_t pids[2 * bufsize / sizeof(pid_t)];
  bufsize = proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids));
  size_t num_pids = bufsize / sizeof(pid_t);
  int i = 0;
  while (i < num_pids)
  { printf("pid[%d]::%d\n", i, pids[i]);
    procpid(pids[i]);
    printf("\n-------------------------------\n\n");
    i += 1; }}

int main(void)
{ pidlist();
  return(42); }

【讨论】:

    【解决方案2】:

    我发现 macOS Mojave(版本 10.14.4)有 struct proc_bsdshortinfo,它是 struct proc_bsdinfo 的子集。你可以通过使用它而不是struct proc_bsdinfo来获取其他用户的进程而无需SUID。

    嗯,我不知道它是从哪个版本开始的。

    已编辑:它至少从 macOS 10.10.5 (Yosemite) 开始可用。
    再次编辑:它可能从 Mac OS X 10.7 (Lion) 开始可用) 因为如果定义了__MAC_10_7,tmux 使用struct proc_bsdshortinfo。见here

    例子:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #include <libproc.h>
    
    int main(int argc, char *argv[])
    {
        pid_t pid;
        struct proc_bsdshortinfo proc;
    
        if (argc == 2)
            pid = atoi(argv[1]);
        else
            pid = getpid();
    
        int st = proc_pidinfo(pid, PROC_PIDT_SHORTBSDINFO, 0,
                             &proc, PROC_PIDT_SHORTBSDINFO_SIZE);
    
        if (st != PROC_PIDT_SHORTBSDINFO_SIZE) {
            fprintf(stderr, "Cannot get process info\n");
            return 1;
        }
        printf(" pid: %d\n", (int)proc.pbsi_pid);
        printf("ppid: %d\n", (int)proc.pbsi_ppid);
        printf("comm: %s\n",      proc.pbsi_comm);
        //printf("name: %s\n",      proc.pbsi_name);
        printf(" uid: %d\n", (int)proc.pbsi_uid);
        printf(" gid: %d\n", (int)proc.pbsi_gid);
    
        return 0;
    }
    

    这个程序打印:

    $ ./pidinfo 
     pid: 3025
    ppid: 250
    comm: pidinfo
     uid: 501
     gid: 20
    $ ./pidinfo 1
     pid: 1
    ppid: 0
    comm: launchd
     uid: 0
     gid: 0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-16
      • 1970-01-01
      • 1970-01-01
      • 2020-09-04
      • 1970-01-01
      • 2015-02-23
      • 2013-03-27
      相关资源
      最近更新 更多