问题描述
我正在编写一个将在sudo下运行的C应用程序。
我需要获取原始登录用户的UID。
我正在调用getuid,文档说明该状态将返回真实的UID。
我假设这将是登录用户的UID,但它返回的是0,这是根UID。
是否有一个api调用,可让我获取已登录用户的UID。
我知道SUDO_UID,但希望避免使用环境变量(或者我只是感到困难)。
解决方法
这是我的解决方案,不使用依赖于stat()
和/proc/<pid>
中文件的环境变量,因此这使其仅适用于linux。
基本上,它会经过进程树,直到找到(sudo)
或pid=1
为止,如果找到sudo,它将显示调用它的父进程以及该进程的uid。
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,sizeof(struct process_info));
if(pid > 0) {
char proc_path[64];
FILE* proc_stat;
memset(&proc_path,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.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
,
在运行systemd(或更准确地说是systemd-logind
)的系统上,您可以使用sd_pid_get_owner_uid
获取启动当前会话的用户:
gradient: LinearGradient(
begin: Alignment.topLeft,end: Alignment.bottomRight,colors: [
Color(0x0ffd6dcf4).withOpacity(0),Colors.white.withOpacity(1),],stops: [
0.3,1
])
您需要链接到#include <systemd/sd-login.h>
…
uid_t user_id;
if (sd_pid_get_owner(0,&user_id) != 0)
… /* handle error */
printf("UID: %ju\n",(uintmax_t) user_id);
。
此ID将指示已登录系统的用户。它不适用于没有登录会话的进程(例如,系统服务),但是在这种情况下,可以说该进程没有登录用户。如果用户有权启动新的会话或服务,他们也可以隐藏其原始登录会话。