実行中のプロセスのユーザー/グループ設定をどのように更新しますか?

実行中のプロセスのユーザー/グループ設定をどのように更新しますか?

初期ログイングループなど、一部のユーザー設定を変更するか、新しいグループに追加するとします。これでsu userこの新しい設定を使用できます。ただし、以前に実行されていたすべてのプロセスはまだ以前と同じ権限を持っています。

実行中のアクティビティを終了せずに、実行中の特定のプロセスがユーザーとグループの設定を強制的に再読み込みして再初期化できるようにするには/etc/passwdどうすればよいですか。そしてdoを使用してプロセスに接続しようとしました/etc/groupが、結果(成功)にもかかわらず、プロセスはまだ同じデータを保持します(実行時に別のグループが表示されることを確認)。gdbprint setuid(MY_USER_ID)0bashgroups

答え1

非常に興味深い試みです。実際、プロセスの補足グループ(で定義されている/etc/group)は次のように設定されます。setgroupsシステムコール。CAP_SETGID権限またはルートが必要です。

だからあなたはこれを行うことができます:

# id
uid=0(root) gid=0(root) groups=0(root)

# gdb -q id
Reading symbols from id...(no debugging symbols found)...done.
(gdb) b getgroups
Breakpoint 1 at 0x401990
(gdb) run
Starting program: /usr/bin/id 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, getgroups () at ../sysdeps/unix/syscall-template.S:81
81  ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) call setgroups(5, {1, 2, 3, 4, 5})
$1 = 0
(gdb) d 1
(gdb) c
Continuing.
uid=0(root) gid=0(root) groups=0(root),1(daemon),2(bin),3(sys),4(adm),5(tty)
[Inferior 1 (process 8059) exited normally]
(gdb) 

答え2

無意味な運動のようです。

ターゲットプロセスに資格情報を切り替えるために必要なすべての権限がないだけでなく、uid / gidがどこかに保存され、積極的に使用される可能性があるため、予期しない資格情報の変更によって実際に問題が発生する可能性があります。

ファイル、sysv ipcなど、誰が所有者であるかを知るさまざまなオブジェクトがあります。

したがって、すべてのターゲットプロセスを/中止/、可能なすべての場所を更新する必要があります。

ただし、一部のプロセスは中断することなくカーネルでブロックできます。今どうなりますか?

おもちゃの目的でプロセスの資格情報を変更するにはカーネルモジュールが必要ですが、ブロックされたプロセスを簡単に処理することはできません。

つまり、あなたが本当に達成したいことは何ですか?なぜ?

答え3

はい、私もこの問題によく直面しています。これはLinuxカーネルの欠陥(一部のデータセキュリティの問題を引き起こす可能性がある)なので、ユーザーレベルのプログラムではこれを行うことはできません。そのため、これを行うために明示的にカーネルモジュールプログラムを作成しました。

#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)。これはLinuxシステム管理者にとって便利です。

関連情報