質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Q&A

解決済

1回答

1435閲覧

seteuid等によるユーザー・グループの変更を、/proc/PID/の所有者に反映させたい

hirura

総合スコア19

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

0クリップ

投稿2020/05/09 12:41

前提・実現したいこと

あるプログラムをrootユーザーで実行し、プログラム中でseteuid等で一般ユーザー(例:user1)にします。

一般ユーザー(user1)が実行する別のプログラムで、上記プログラムのPIDの/proc/PID/fd/等のディレクトリ・ファイルを読み込みたいです。

/proc/PID/fd/等の所有者が、一般ユーザー(user1)になれば、実現できると思っています。

実際、ログインシェルのPIDでは、/proc/PID/以下のディレクトリ・ファイルは全て、そのユーザーが所有者でした(試したこと、に記載)。

seteuid等のシステムコール・関数とは別に、何かべつの処理が必要なのでしょうか。

発生している問題・エラーメッセージ

環境は、Fedora 32、Linux kernel 5.6 です。

$ uname -a Linux localhost.localdomain 5.6.6-300.fc32.x86_64 #1 SMP Tue Apr 21 13:44:19 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

端末1で、下記の通り実行(setresuid.cのソースコードは後述)しました。

$ sudo cat /etc/passwd | grep user1 user1:x:1234:1234::/home/user1:/bin/bash $ gcc setresuid.c $ sudo ./a.out pid: 142188 ruid 0, euid 0, suid 0 ruid 1234, euid 1234, suid 1234 sleep (この状態で放置)

端末2で、下記の通り、/proc/PID/fd/や、/proc/PID/のファイル一覧を取得したところ、次のように、ユーザーがroot(一部はuser1、なぜ???)になっており、Permission deniedとなるものがあります。

$ id uid=1234(user1) gid=1234(user1) groups=1234(user1) $ ls -l /proc/142188/fd/ ls: cannot open directory '/proc/142188/fd/': Permission denied $ ls -l /proc/142188/ ls: cannot read symbolic link '/proc/142188/cwd': Permission denied ls: cannot read symbolic link '/proc/142188/root': Permission denied ls: cannot read symbolic link '/proc/142188/exe': Permission denied total 0 -r--r--r-- 1 root root 0 May 9 21:13 arch_status dr-xr-xr-x 2 user1 root 0 May 9 21:13 attr -rw-r--r-- 1 root root 0 May 9 21:13 autogroup -r-------- 1 root root 0 May 9 21:13 auxv (snip) dr-x------ 2 root root 0 May 9 21:13 fd (snip)

該当のソースコード

c

1#define _GNU_SOURCE 2#include <unistd.h> 3#include <stdio.h> 4#include <stdlib.h> 5 6int main(void) 7{ 8 uid_t ruid, euid, suid; 9 10 printf("pid: %d\n", getpid()); 11 12 getresuid(&ruid, &euid, &suid); 13 printf("ruid %ld, euid %ld, suid %ld\n", (long)ruid, (long)euid, (long)suid); 14 15 if (setresuid(1234, 1234, 1234) < 0){ 16 perror("setresuid"); 17 exit(1); 18 } 19 20 getresuid(&ruid, &euid, &suid); 21 printf("ruid %ld, euid %ld, suid %ld\n", (long)ruid, (long)euid, (long)suid); 22 23 printf("sleep\n"); 24 sleep(3600); 25 26 return 0; 27}

試したこと

一方、suやsudoコマンドでユーザーを切り替えて起動したシェル等は、/proc/PID/の所有者がそのユーザー(例:user1)になっていました。

$ sudo su - user1 [user1@localhost ~]$ id uid=1234(user1) gid=1234(user1) groups=1234(user1) [user1@localhost ~]$ echo $$ 142257 [user1@localhost ~]$ ls -l /proc/142257/ total 0 -r--r--r-- 1 user1 user1 0 May 9 21:24 arch_status dr-xr-xr-x 2 user1 user1 0 May 9 21:24 attr -rw-r--r-- 1 user1 user1 0 May 9 21:24 autogroup -r-------- 1 user1 user1 0 May 9 21:24 auxv (snip) dr-x------ 2 user1 user1 0 May 9 21:24 fd (snip) [user1@localhost ~]$ ls -l /proc/142257/fd/ total 0 lrwx------ 1 user1 user1 64 May 9 21:35 0 -> /dev/pts/4 lrwx------ 1 user1 user1 64 May 9 21:35 1 -> /dev/pts/4 lrwx------ 1 user1 user1 64 May 9 21:35 2 -> /dev/pts/4 lrwx------ 1 user1 user1 64 May 9 21:35 255 -> /dev/pts/4 lr-x------ 1 user1 user1 64 May 9 21:35 3 -> /var/lib/sss/mc/passwd

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

suのようなことがしたいのであれば、setresuid()の後、execve()しないと、/proc/PID以下のオーナーは書き換わらないようです。自分自身をexecve()しても大丈夫でです。

getchar()の前後でls -l /proc/PIDすると変化が分かります。

C

1int main(int argc, char **argv) 2{ 3 uid_t ruid, euid, suid; 4 if(argc>1){ // 引数があればスリープする 5 printf("sleeping\n"); 6 sleep(3600); 7 exit(0); 8 } 9 10 printf("pid: %d\n", getpid()); 11 12 getresuid(&ruid, &euid, &suid); 13 printf("ruid %ld, euid %ld, suid %ld\n", (long)ruid, (long)euid, (long)suid); 14 15 if (setresuid(1234, 1234, 1234) < 0){ 16 perror("setresuid"); 17 exit(1); 18 } 19 20 getresuid(&ruid, &euid, &suid); 21 printf("ruid %ld, euid %ld, suid %ld\n", (long)ruid, (long)euid, (long)suid); 22 23 printf("sleep OK?"); 24 getchar(); 25 execl("/tmp/foo","SLEEP","arg1",NULL); //自分自身を引数を付けてexecする 26 perror("exec"); 27 exit(1); 28}

なお、setresuid()時点で/proc/PID自体のオーナーは書き換わってます。
fork()すれば子プロセスは書き換わるかと思ったけど、fork()ではそのままコピーされるだけですね。

投稿2020/05/09 13:46

otn

総合スコア84555

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirura

2020/05/09 15:33

ご回答ありがとうございます。execは盲点でした。forkは私も試してダメだったのと、suでもsudoでもownerが更新されていたので、考えていませんでした。 でも、root権限で特権ポートをopenし、fork、seteuidしてacceptするようなプログラムは世の中に溢れているはずなので、もう少し調べてみようと思います。
otn

2020/05/09 15:38

> root権限で特権ポートをopenし、fork、seteuidしてacceptするようなプログラム は、 > 一般ユーザー(user1)が実行する別のプログラムで、上記プログラムのPIDの/proc/PID/fd/等のディレクトリ・ファイルを読み込みたいです。 とは違う話ですよね。
hirura

2020/05/10 02:02

はい、違う話です。そういうプログラムで/proc/PID/の所有者がどうなっているのか、調べてみようと。 sshdの場合、forc/execしたプログラムから所有者が変わっているようでした。やはりexec必須なのでしょうかね。 ``` $ ssh localhost -l user1 'sh -c "echo $$; sleep 60"' 145389 ``` ``` $ pstree -psuS 145389 systemd(1)───sshd(611)───sshd(145386)───sshd(145388,user1)───sh(145389)───sleep(145403) $ sudo ls -al /proc/145388/ | head -n 5 total 0 dr-xr-xr-x 9 user1 user1 0 May 10 10:57 . dr-xr-xr-x 194 root root 0 May 2 19:23 .. -r--r--r-- 1 root root 0 May 10 10:58 arch_status dr-xr-xr-x 2 user1 user1 0 May 10 10:58 attr $ sudo ls -al /proc/145389/ | head -n 5 total 0 dr-xr-xr-x 9 user1 user1 0 May 10 10:57 . dr-xr-xr-x 194 root root 0 May 2 19:23 .. -r--r--r-- 1 user1 user1 0 May 10 10:57 arch_status dr-xr-xr-x 2 user1 user1 0 May 10 10:57 attr ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問