问题描述
我正在编写一个将在sudo下运行的C应用程序.
I'm writing a C application that will be run under sudo.
我需要获取原始登录用户的UID.
I need to get the original logged in users UID.
我正在调用getuid,文档说明该状态将返回真实的UID.
I'm calling getuid which the documentation states will return the real UID.
我假设这将是登录用户的UID,但它返回的是0,这是根UID.
I assumed this would be the logged in user's UID but it instead returns 0 which is the root UID.
是否有一个api调用,可以让我获取登录用户的UID.
Is there an api call which will allow me to get the logged in users UID.
我知道SUDO_UID,但希望避免使用环境变量(或者我只是感到困难).
I'm aware of SUDO_UID but would prefer to avoid environment variables (or am I just being difficult).
推荐答案
这是我的解决方案,不使用依赖于stat()
和/proc/<pid>
中文件的环境变量,因此仅适用于linux.基本上,它会经过进程树,直到找到(sudo)
或pid=1
,如果找到sudo,它将显示调用它的父进程以及该进程的uid.
Here is my solution without using environment variables relying on stat()
and files in /proc/<pid>
, so this makes it linux only.Basically it goes trough the process tree until it finds (sudo)
or pid=1
, if sudo is found it shows the parent process that called it and the uid for that.
hello_sudoer.c
:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
struct process_info {
pid_t pid;
// max file name is 255 + 2 for "()" in /proc/<pid>/stat
char process_name[257];
char status;
pid_t ppid; // parent process id
uid_t uid; // uid of this process
};
struct process_info get_process_info(pid_t pid){
struct process_info pi;
struct stat* s = malloc(sizeof(struct stat));
memset(&pi, 0, sizeof(struct process_info));
if(pid > 0) {
char proc_path[64];
FILE* proc_stat;
memset(&proc_path, 0, sizeof(proc_path));
sprintf(proc_path , "/proc/%d/stat", pid);
proc_stat = fopen(proc_path, "r");
if (proc_stat != NULL) {
fscanf(proc_stat, "%d %s %c %d",
&pi.pid,
pi.process_name,
&pi.status,
&pi.ppid);
// stat struct doesn't have the parent process id
// as is only checking on the file properies of /proc/<pid> directory
// so we can't get the info needed only with stat(2)
// and stat file doesn't have uid so we can't only use that
// we need both
stat(proc_path, s);
pi.uid = s -> st_uid;
free(s);
fclose(proc_stat);
}
}
return pi;
}
void print_process_info(struct process_info pi){
printf("pid=%d file_name=%s status=%c uid=%d ppid=%d\n",
pi.pid, pi.process_name, pi.status, pi.uid, pi.ppid);
}
int main()
{
pid_t pid = getpid();
while (pid > 0) {
struct process_info pi = get_process_info(pid);
print_process_info(pi);
if( strcmp("(sudo)" , pi.process_name) == 0 ) {
// found sudo
struct process_info sudo_parent_info = get_process_info(pi.ppid);
printf("user that ran sudo is uid=%d, from process: \n",
sudo_parent_info.uid);
print_process_info(sudo_parent_info);
break;
}
pid = pi.ppid;
}
return 0;
}
示例输出:
pid=41769 file_name=(hello_sudoer.o) status=R uid=0 ppid=41749
pid=41749 file_name=(sudo) status=S uid=0 ppid=20078
user that ran sudo is uid=1000, from process:
pid=20078 file_name=(bash) status=S uid=1000 ppid=5985
这篇关于在sudo下运行时如何从C获取loggin用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!