geteuid系统调用及示例

geteuid 函数详解

  1. 函数介绍

geteuid 是 Linux 系统中用于获取进程有效用户 ID(Effective User ID)的系统调用。可以把有效用户 ID 想象成”进程当前正在使用的身份证明”——它决定了进程当前拥有的权限级别。

data-ad-format="fluid" data-ad-layout-key="-7k+ex-4a-9w+4a">

在 Linux 系统中,每个进程都有两个重要的用户 ID:

  • 真实用户 ID(real UID): 进程实际所属的用户

  • 有效用户 ID(effective UID): 进程当前使用的用户身份(用于权限检查)

这就像是一个人有真实身份和当前扮演的角色。比如一个系统管理员(真实身份)可能暂时切换到普通用户角色(有效身份)来执行某些操作。

geteuid 就是获取进程当前”扮演的角色”的用户 ID。

  1. 函数原型
1
2
3
4
5
#include <unistd.h>
#include <sys/types.h>

uid_t geteuid(void);

  1. 功能

geteuid 函数用于获取调用进程的有效用户 ID(effective user ID)。有效用户 ID 用于权限检查,决定了进程可以访问哪些资源和执行哪些操作。

  1. 参数

geteuid 函数不需要任何参数。

  1. 返回值
  • 成功: 返回调用进程的有效用户 ID(uid_t 类型)

  • 注意: 此函数不会失败,总是成功返回

  1. 相关函数
  • getuid: 获取真实用户 ID(real user ID)

  • getgid: 获取真实组 ID(real group ID)

  • getegid: 获取有效组 ID(effective group ID)

  • setuid: 设置用户 ID

  • seteuid: 设置有效用户 ID

  • setreuid: 同时设置真实和有效用户 ID

  1. 用户 ID 类型说明

Linux 系统中有几种不同的用户 ID:

用户 ID 类型说明真实用户 ID (real UID)进程实际所属的用户,由 getuid 返回有效用户 ID (effective UID)用于权限检查的用户 ID,由 geteuid 返回保存的设置用户 ID (saved set-user-ID)保存的用户 ID,用于权限切换

  1. 示例代码

示例1:基础用法 - 获取进程用户 ID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

int main() {
uid_t real_uid, effective_uid;
struct passwd *pwd_info;

printf("=== 进程用户 ID 信息 ===\n\n");

// 获取真实用户 ID
real_uid = getuid();
printf("真实用户 ID (real UID): %d\n", real_uid);

// 获取有效用户 ID
effective_uid = geteuid();
printf("有效用户 ID (effective UID): %d\n", effective_uid);

// 获取用户名信息
pwd_info = getpwuid(real_uid);
if (pwd_info != NULL) {
printf("真实用户名: %s\n", pwd_info->pw_name);
printf("主目录: %s\n", pwd_info->pw_dir);
printf("登录 shell: %s\n", pwd_info->pw_shell);
} else {
printf("无法获取真实用户信息\n");
}

// 获取有效用户信息
pwd_info = getpwuid(effective_uid);
if (pwd_info != NULL) {
printf("有效用户名: %s\n", pwd_info->pw_name);
} else {
printf("无法获取有效用户信息\n");
}

// 判断权限级别
printf("\n权限状态:\n");
if (effective_uid == 0) {
printf("✓ 进程具有 root 权限\n");
} else if (real_uid == 0 && effective_uid != 0) {
printf("⚠ 进程已放弃 root 权限\n");
} else {
printf("✗ 进程为普通用户权限\n");
}

if (real_uid == effective_uid) {
printf("✓ 真实 UID 和有效 UID 相同\n");
} else {
printf("⚠ 真实 UID 和有效 UID 不同\n");
}

return 0;
}

示例2:权限检查和安全验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <string.h>

// 权限检查函数
void check_permissions() {
uid_t real_uid = getuid();
uid_t effective_uid = geteuid();
gid_t real_gid = getgid();
gid_t effective_gid = getegid();

printf("=== 权限检查 ===\n");

// 用户权限检查
printf("用户权限:\n");
printf(" 真实 UID: %d", real_uid);
struct passwd *pwd = getpwuid(real_uid);
if (pwd) printf(" (%s)", pwd->pw_name);
printf("\n");

printf(" 有效 UID: %d", effective_uid);
pwd = getpwuid(effective_uid);
if (pwd) printf(" (%s)", pwd->pw_name);
if (effective_uid == 0) {
printf(" &#91;ROOT 权限!]");
}
printf("\n");

// 组权限检查
printf("组权限:\n");
printf(" 真实 GID: %d\n", real_gid);
printf(" 有效 GID: %d", effective_gid);
if (effective_gid == 0) {
printf(" &#91;ROOT 组权限!]");
}
printf("\n");

// 安全状态分析
printf("\n安全状态分析:\n");
if (effective_uid == 0) {
printf(" ⚠ 危险: 进程以 root 权限运行\n");
printf(" 建议: 在完成特权操作后立即降低权限\n");
} else if (real_uid == 0 && effective_uid != 0) {
printf(" ✓ 良好: 已安全放弃 root 权限\n");
} else {
printf(" ✓ 正常: 以普通用户权限运行\n");
}
}

// 安全操作示例
void secure_operation_example() {
uid_t real_uid = getuid();
uid_t effective_uid = geteuid();

printf("\n=== 安全操作示例 ===\n");

if (effective_uid == 0) {
printf("检测到 root 权限,执行特权操作...\n");

// 模拟特权操作
printf(" 执行系统管理任务...\n");
printf(" 修改系统配置...\n");
printf(" 访问受保护资源...\n");

// 如果真实 UID 不是 root,可以安全地放弃权限
if (real_uid != 0) {
printf(" 准备放弃 root 权限...\n");
// 注意:实际代码中需要使用 setuid() 系列函数
}
} else {
printf("以普通用户权限执行操作...\n");
printf(" 执行用户级任务...\n");
printf(" 访问用户文件...\n");
}
}

int main() {
printf("=== 进程身份和权限管理系统 ===\n\n");

// 显示基本进程信息
printf("进程基本信息:\n");
printf(" 进程 ID: %d\n", getpid());
printf(" 父进程 ID: %d\n", getppid());
printf(" 真实 UID: %d\n", getuid());
printf(" 有效 UID: %d\n", geteuid());
printf(" 真实 GID: %d\n", getgid());
printf(" 有效 GID: %d\n\n", getegid());

// 权限检查
check_permissions();

// 安全操作示例
secure_operation_example();

printf("\n=== 安全建议 ===\n");
printf("1. 遵循最小权限原则\n");
printf("2. 及时放弃不需要的特权\n");
printf("3. 定期检查有效 UID 和真实 UID\n");
printf("4. 避免长时间以 root 权限运行\n");

return 0;
}

示例3:完整的身份验证和权限管理系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>

// 用户信息结构体
struct user_info {
uid_t uid;
gid_t gid;
char username&#91;256];
char groupname&#91;256];
char homedir&#91;256];
int is_root;
int has_privileges;
};

// 获取用户信息
int get_user_information(struct user_info *info) {
struct passwd *pwd;
struct group *grp;

// 获取 UID 和 GID
info->uid = geteuid();
info->gid = getegid();

// 获取用户信息
pwd = getpwuid(info->uid);
if (pwd) {
strncpy(info->username, pwd->pw_name, sizeof(info->username) - 1);
info->username&#91;sizeof(info->username) - 1] = '\0';
strncpy(info->homedir, pwd->pw_dir, sizeof(info->homedir) - 1);
info->homedir&#91;sizeof(info->homedir) - 1] = '\0';
} else {
snprintf(info->username, sizeof(info->username), "uid_%d", info->uid);
strcpy(info->homedir, "/tmp");
}

// 获取组信息
grp = getgrgid(info->gid);
if (grp) {
strncpy(info->groupname, grp->gr_name, sizeof(info->groupname) - 1);
info->groupname&#91;sizeof(info->groupname) - 1] = '\0';
} else {
snprintf(info->groupname, sizeof(info->groupname), "gid_%d", info->gid);
}

// 设置权限标志
info->is_root = (info->uid == 0);
info->has_privileges = (info->uid == 0 || info->gid == 0);

return 0;
}

// 显示用户信息
void display_user_info(const struct user_info *info) {
printf("=== 当前用户信息 ===\n");
printf("用户名: %s\n", info->username);
printf("用户 ID: %d\n", info->uid);
printf("组名: %s\n", info->groupname);
printf("组 ID: %d\n", info->gid);
printf("主目录: %s\n", info->homedir);
printf("权限状态: %s\n",
info->is_root ? "ROOT 权限" :
info->has_privileges ? "特权用户" : "普通用户");
}

// 权限验证函数
int check_operation_permission(const char *operation) {
struct user_info info;
get_user_information(&info);

printf("权限检查: %s\n", operation);

// 根据操作类型检查权限
if (strcmp(operation, "read_system_files") == 0) {
// 读取系统文件通常需要 root 权限
return info.is_root ? 1 : 0;
} else if (strcmp(operation, "write_user_files") == 0) {
// 写入用户文件通常只需要有效权限
return 1; // 假设总是允许
} else if (strcmp(operation, "network_admin") == 0) {
// 网络管理需要 root 权限
return info.is_root ? 1 : 0;
} else {
// 默认情况下,普通操作允许
return 1;
}
}

// 模拟受保护操作
void perform_protected_operation(const char *operation) {
printf("\n--- 尝试执行操作: %s ---\n", operation);

if (check_operation_permission(operation)) {
printf("✓ 权限检查通过\n");
printf(" 执行操作: %s\n", operation);

// 模拟操作执行
if (strcmp(operation, "read_system_files") == 0) {
printf(" 读取 /etc/shadow...\n");
printf(" 读取系统配置文件...\n");
} else if (strcmp(operation, "network_admin") == 0) {
printf(" 配置网络接口...\n");
printf(" 修改防火墙规则...\n");
}

printf(" 操作完成\n");
} else {
printf("✗ 权限不足,拒绝执行操作\n");
printf(" 需要 ROOT 权限才能执行此操作\n");
}
}

// 显示安全建议
void show_security_advice(const struct user_info *info) {
printf("\n=== 安全建议 ===\n");

if (info->is_root) {
printf("⚠ 警告: 当前以 ROOT 权限运行\n");
printf(" 建议:\n");
printf(" 1. 完成必要操作后立即切换到普通用户\n");
printf(" 2. 避免在 root 权限下运行不必要的程序\n");
printf(" 3. 定期审计 root 权限的使用情况\n");
} else if (info->has_privileges) {
printf("⚠ 注意: 具有特权权限\n");
printf(" 建议:\n");
printf(" 1. 谨慎使用特权功能\n");
printf(" 2. 遵循最小权限原则\n");
} else {
printf("✓ 信息: 以普通用户权限运行\n");
printf(" 建议:\n");
printf(" 1. 如需特权操作,请使用 sudo\n");
printf(" 2. 保持系统和软件更新\n");
}
}

int main() {
struct user_info current_user;

printf("=== 高级身份验证和权限管理系统 ===\n\n");

// 获取并显示用户信息
get_user_information(&current_user);
display_user_info(&current_user);

// 执行各种受保护操作
perform_protected_operation("read_system_files");
perform_protected_operation("write_user_files");
perform_protected_operation("network_admin");

// 显示安全建议
show_security_advice(&current_user);

printf("\n=== 系统信息 ===\n");
printf("进程 ID: %d\n", getpid());
printf("父进程 ID: %d\n", getppid());
printf("真实 UID: %d\n", getuid());
printf("有效 UID: %d\n", geteuid());
printf("真实 GID: %d\n", getgid());
printf("有效 GID: %d\n", getegid());

return 0;
}

编译和运行说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 编译示例程序
gcc -o geteuid_example1 example1.c
gcc -o geteuid_example2 example2.c
gcc -o geteuid_example3 example3.c

# 运行示例
./geteuid_example1
./geteuid_example2
./geteuid_example3

# 以 root 权限运行(需要 sudo)
sudo ./geteuid_example1
sudo ./geteuid_example2
sudo ./geteuid_example3

命令行查看用户信息

1
2
3
4
5
6
7
8
9
10
11
12
13
# 查看当前用户信息
id

# 查看特定用户信息
id username

# 查看当前进程信息
ps -eo pid,ppid,uid,euid,gid,egid,comm

# 查看用户数据库
cat /etc/passwd
cat /etc/group

重要注意事项

不会失败: geteuid 总是成功返回,不需要错误检查

实时性: 返回的是调用时刻的有效用户 ID

权限检查: 有效 UID 用于所有权限检查

安全关键: 在安全敏感程序中要特别注意有效 UID

继承性: 子进程继承父进程的有效 UID

实际应用场景

权限验证: 在执行特权操作前检查有效 UID

安全审计: 记录操作的有效用户身份

访问控制: 根据有效 UID 控制资源访问

特权管理: 管理程序的特权级别切换

日志记录: 在日志中记录有效的用户身份

常见用户 ID 含义

用户 ID用户名说明0root超级用户1daemon系统守护进程用户2bin系统二进制文件用户5sync用于同步操作的用户37www-dataWeb 服务器用户65534nobody无特权用户

与相关函数的配合使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 完整的身份信息获取
uid_t real_uid = getuid(); // 真实用户 ID
uid_t effective_uid = geteuid(); // 有效用户 ID
gid_t real_gid = getgid(); // 真实组 ID
gid_t effective_gid = getegid(); // 有效组 ID

// 权限切换示例
if (geteuid() == 0) {
// 当前有 root 权限,执行特权操作
// ...
// 完成后可以放弃权限
// setuid(getuid()); // 切换到真实 UID
}

安全最佳实践

最小权限原则: 只在必要时获取特权

及时放弃权限: 完成特权操作后立即降低权限

验证身份: 在关键操作前验证有效 UID

避免持久化: 不要长时间保持高权限运行

日志记录: 记录所有特权操作的身份信息

这些示例展示了 geteuid 函数的各种使用方法,从基本的用户 ID 获取到完整的权限管理系统,帮助你全面理解 Linux 系统中的用户权限管理机制。

getgid系统调用及示例-CSDN博客

geteuid系统调用及示例-CSDN博客

data-ad-format="auto" data-full-width-responsive="true">