cat /proc/$PID/status
해당 줄을 실행하고 보면 프로세스의 보충 그룹을 볼 수 있습니다 Groups:
.
이 프로세스 값을 수정하는 방법은 무엇입니까?
/etc/group
이러한 값은 일반적 으로 사용자가 파일에 구성하지만 해당 파일의 변경 사항이 커널 데이터 구조에 즉시 전파되지는 않는다는 것을 알고 있습니다 . 사용자 공간 프로그램이 커널에서 이러한 값을 어떻게 설정하는지 알고 싶습니다.
답변1
시스템 호출을 사용하여 프로세스의 보충 그룹을 설정할 수 있습니다 setgroups
.
답변2
이를 위해 특별히 커널 모듈 프로그램을 만들었습니다.
#include <linux/cred.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pid.h>
#include <linux/pid_namespace.h>
#include <linux/printk.h>
#include <linux/sched.h>
#include <linux/uidgid.h>
static int arg_pid=0;
static int arg_gid=0;
static char *arg_act="add";
module_param(arg_pid, int, 0);
MODULE_PARM_DESC(arg_pid, "PID of the process");
module_param(arg_gid, int, 0);
MODULE_PARM_DESC(arg_gid, "GID of the group to add to PID's supplimentary groups");
module_param(arg_act, charp, 0);
MODULE_PARM_DESC(arg_act, "action to perform: add/remove/list/query");
struct pid *pid_struct = NULL;
struct task_struct *task = NULL;
struct cred *real_cd = NULL;
struct cred *effe_cd = NULL;
struct group_info *gi = NULL;
struct group_info *new_gi = NULL;
bool query(int gid, struct group_info *gi){
for(int x=0; x<gi->ngroups; ++x)
if(gid==gi->gid[x].val) return true;
return false;
}
int init_module(void) {
if(arg_pid==0){
pr_info("Error: Usage: insmod supgroup.ko arg_pid=## arg_gid=## (arg_act='add/remove/list/query') && rmmod supgroup\n");
return 0;
}
pid_struct = find_get_pid(arg_pid);
if(pid_struct==NULL){
pr_info("Error: find_get_pid() failed\n");
return 0;
}
task = pid_task(pid_struct, PIDTYPE_PID);
if(task==NULL){
pr_info("Error: pid_task() failed\n");
return 0;
}
if(task->real_cred==NULL){
pr_info("Error: task->real_cred == NULL\n");
return 0;
}
gi = task->real_cred->group_info;
if(gi==NULL){
pr_info("Error: task->real_cred->group_info == NULL\n");
return 0;
}
if(!strcmp(arg_act, "add")){
if(query(arg_gid, gi)){
pr_info("GID %d is already in PID %d's supplementary group list\n", arg_gid, arg_pid);
return 0;
}
new_gi = groups_alloc(gi->ngroups+1);
if(new_gi==NULL){
pr_info("Error: groups_alloc() failed, out of kernel memory?\n");
return 0;
}
for(int x=0; x<gi->ngroups; ++x)
new_gi->gid[x] = gi->gid[x];
new_gi->gid[gi->ngroups].val = arg_gid;
groups_sort(new_gi);
// forcefully set group_info
get_cred((const struct cred *)new_gi);
*(struct group_info**)(&task->real_cred->group_info) = new_gi;
*(struct group_info**)(&task->cred->group_info) = new_gi;
pr_info("Added GID %d to PID %d's supplementary groups\n", arg_gid, arg_pid);
}else if(!strcmp(arg_act, "remove")){
if(!query(arg_gid, gi)){
pr_info("GID %d is not in PID %d's supplementary group list\n", arg_gid, arg_pid);
return 0;
}
new_gi = groups_alloc(gi->ngroups-1);
if(new_gi==NULL){
pr_info("Error: groups_alloc() failed, out of kernel memory?\n");
return 0;
}
for(int x=0,y=0; x<gi->ngroups; ++x)
if(gi->gid[x].val != arg_gid){
new_gi->gid[y] = gi->gid[x];
y++;
}
// forcefully set group_info
get_cred((const struct cred *)new_gi);
*(struct group_info**)(&task->real_cred->group_info) = new_gi;
*(struct group_info**)(&task->cred->group_info) = new_gi;
pr_info("Removed GID %d from PID %d's supplementary groups\n", arg_gid, arg_pid);
}else if(!strcmp(arg_act, "list")){
pr_info("Listing PID %d's supplementary groups' GIDs: ", arg_pid);
for(int x=0; x<gi->ngroups; ++x)
pr_info("%d ", gi->gid[x].val);
pr_info("Done\n");
}else if(!strcmp(arg_act, "query")){
pr_info("GID %d is %s PID %d's supplementary group list\n", arg_gid, query(arg_gid, gi)?"in":"not in", arg_pid);
}
return 0;
}
void cleanup_module(void){}
MODULE_LICENSE("GPL");
내 Github 저장소에서 사용법을 확인하세요(https://github.com/xuancong84/supgroup). 이는 실행 중인 프로세스에 대한 보충 그룹 정보를 업데이트하는 데 유용합니다.