[ruby-dev:15026] setuid and seteuid
From:
nagai@...
Date:
2001-11-02 08:57:39 UTC
List:
ruby-dev #15026
永井@知能.九工大です.
長いこと放置状態になっていた件です.(^_^;
ようやく,少し時間ができたので,自分なりに検討してみました.
で,結論から言えば,
==========================================================
Process.uid(id)
if setreuid が存在 then setreuid(-1,id)
else setuid が存在 then setuid(id)
else setruid が存在 then setruid(id)
else 非サポート
Process.euid(id)
if setreuid が存在 then setreuid(id,-1)
else seteuid が存在 then seteuid(id)
else 非サポート
Process.swap_uid --- 新設
if setreuid が存在 then setreuid(geteuid(),getuid())
else 非サポート
==========================================================
というのではどうだろうかと思ってます.
頭の中がごちゃごちゃになってしまったんで強い自信はないんですが,
以下,叩き台として,思考過程のメモの一部を添えます.
途中でミスがあるのは承知してますが,
結論に関係のない部分のミスは修正していません.
結論に影響する部分に誤りがあれば修正いただけると助かります.
なお,r r r などと書いているのは,
ある時点での実ユーザID (uid),実効ユーザID (euid),
保存ユーザID (sid) の 3 項組です.
r は root , 1 と 2 は何らかの一般ユーザ ID
( 1 と 2 とは別のユーザ ID ) を表していると思ってください.
==========================================================
-------------------------------------------------------
uid, euid, sid のすべてが異なる情况が生じるのは
(r r r) から sid に影響しない setreuid(1,2) ,
または (1 r r) から seteuid(2) [ != setreuid(-1,2) ] によって
(1 2 r) に到達する場合のみ.
したがって,(1 2 3) のようなものは考慮の必要なし.
-------------------------------------------------------
(00) r r r : root での起点
(01) 1 1 1 : 一般ユーザでの起点 ==> id 変更不能 == 終点
(10) r 1 1 : root + set-user-idビット(一般)
(11) 1 r r : 一般ユーザ + set-uer-idビット(root)
(12) 1 2 2 : 一般ユーザ + set-user-idビット(一般)
(13) 2 1 1
(14) 2 r r
(20) r r 1
(21) r 1 r
(22) 1 r 1
(23) 1 1 r
(30) 1 1 2
(31) 2 2 1
(32) 1 2 1
(40) 1 2 r
(41) 2 1 r
-------------------------------------------------------
setuid , seteuid , setreuid
setuid は,euid==0 なら uid=euid=sid=NEW_ID
euid!=0 なら NEW_ID==uid or sid に限り euid=NEW_ID
seteuid は,euid==0 なら euid=NEW_ID
euid!=0 なら NEW_ID==uid or sid に限り euid=NEW_ID
setreuid は,Linux, Sun では euid が旧 uid と違えば sid も変化し.
NetBSD(?) では uid が変化した場合だけに変化.
特権がなければ,uid の変更は不可.
-------------------------------------------------------
情况の仮定
(a) setuid のみ
(b) setreuid のみ
(c) setuid + seteuid
-------------------------------------------------------
(00) --> (01)
(a) setuid(1)
(b) setreuid(1,1)
(c) setuid(1)
(11), (14), (20), (22) からも同じ.
-------------------------------------------------------
(00) への直接パス
(11) or (14) or (22)
(a) setuid(r)
(b) setreuid(r,r)
(c) setuid(r)
-------------------------------------------------------
set-user-id ビットの代行
(00) --> (10) のパス
(a) 不可能
(b) Linux,Sun : setreuid(-1,1) : NetBSD(?) と同じ手でも可
NetBSD(?) : setreuid(1,-1)==>(1 r r);setreuid(r,1)
(c) 不可能
(00) --> (11) のパス : (14) も同様
(a) 不可能
(b) setreuid(1,-1)
(c) 不可能
(00) --> (12) のパス : (13) も同様
(a) 不可能
(b) setreuid(1,2)
(c) 不可能
-------------------------------------------------------
(00) から set-user-id ビット以外へ変換可能な直接パス
(21) へのパス
(c) seteuid(1)
(20), (22), (23), (30), (31), (32), (40), (41) へのパス
到達不能
-------------------------------------------------------
(00) 以外からそれぞれへ変換可能な直接パス
(10) へのパス
(11) から (b) setreuid(r,1) <id交換>
(20) から (b) setreuid(-1,1)
(c) seteuid(1)
(11) へのパス
(10) から (b) setreuid(1,r) <id交換>
(20) から (b) setreuid(1,-1)
(21) から (b) setreuid(1,r) <id交換>
(23) から (a) setuid(r)
(b) setreuid(-1,r)
(c) setuid(r) or seteuid(r)
(40) から (a) setuid(r)
(b) setreuid(-1,r)
(c) setuid(r) or seteuid(r)
(12) へのパス
(11) から (b) setreuid(-1,2)
(13) から (b) setreuid(1,2) <id交換>
(20) から (b) setreuid(1,2)
(30) から (a) setuid(2)
(b) setreuid(-1,2)
(c) setuid(2) or seteuid(2)
(41) から (b) setreuid(1,2) <id交換>
(13) へのパス
(11) から (b) setreuid(2,1)
(12) から (b) setreuid(2,1) <id交換>
(20) から (b) setreuid(2,1)
(31) から (a) setuid(1)
(b) setreuid(-1,1)
(c) setuid(1) or seteuid(1)
(40) から (b) setreuid(2,1) <id交換>
(14) へのパス
(11) から (b) setreuid(2,-1)
(20) から (b) setreuid(2,-1)
(21') r 2 r から (b) setreuid(2,r) <id交換>
(23') 2 2 r から (a) setuid(r)
(b) setreuid(-1,r)
(c) setuid(r) or seteuid(r)
(41) から (a) setuid(r)
(b) setreuid(-1,r)
(c) setuid(r) or seteuid(r)
(20) へのパス
(10) から (a) setuid(r) : 非特権ユーザの状態なので seteuid(r) に同じ
(b) setreuid(-1,r)
(c) setuid(r) or seteuid(r)
(21) へのパス
到達不能 : (00) から (c) seteuid(1) 以外では不可能
(22) へのパス
到達不能
(23) へのパス
(11) から (b) setreuid(-1,1)
(c) seteuid(1)
(30) へのパス
(12) から (a) setuid(1) : 非特権ユーザの状態なので seteuid(1) に同じ
(b) setreuid(-1,1)
(c) setuid(1) or seteuid(1)
(31) へのパス
(13) から (a) setuid(2) : 非特権ユーザの状態なので seteuid(2) に同じ
(b) setreuid(-1,2)
(c) setuid(2) or seteuid(2)
(32) へのパス
到達不能 : (22) からなら可だが,(22) が到達不能
(40) へのパス
(11) から (b) setreuid(-1,2)
(c) seteuid(2)
(41) へのパス
(14) から (b) setreuid(-1,1)
(c) seteuid(1)
-------------------------------------------------------
sid が存在しない環境での set-user-id ビットの代行
(00) --> (10) (r 1) のパス
(a) 不可能
(b) setreuid(-1,1) : sid が存在する場合の NetBSD(?) の方法も使える
(c) seteuid(1)
(00) --> (11) (1 r) のパス
(a) 不可能
(b) setreuid(1,-1)
(c) 不可能
(00) --> (12) のパス
(a) 不可能
(b) setreuid(1,2)
(c) 不可能
-------------------------------------------------------
sid が存在しない環境での同等関係
(20) == (00) : sid は意味をなさない (root権限を持つため)
(21) ?= (10) : 推移可能な状態を考えると,同等とみなしていい?
(22) == (11) : sid は意味をなさない (root権限を持つため)
(23) == XX : sid がなければ同等の情况は作れない
(30) == XX : sid がなければ同等の情况は作れない
(31) == XX : sid がなければ同等の情况は作れない
(32) ?= (12) : 推移可能な状態を考えると,同等とみなしていい?
(40) == XX : sid がなければ同等の情况は作れない
(41) == XX : sid がなければ同等の情况は作れない
考える必要があるは
(00) r r
(01) 1 1
(10) r 1
(11) 1 r
(12) 1 2
(13) 2 1
(14) 2 r
-------------------------------------------------------
(00) 以外からそれぞれへ変換可能な直接パス (sid が存在しない環境)
(01) 1 1
(11) から (a) setuid(1)
(b) setreuid(-1,1)
(c) setuid(1) or seteuid(1)
(12) から (a) setuid(1)
(b) setreuid(-1,1)
(c) setuid(1) or seteuid(1)
(13) から (a) setuid(2) : (2 2) => (1 1) とみなす
(b) setreuid(-1,2) : (2 2) => (1 1) とみなす
(c) setuid(2) or seteuid(2) : (2 2) => (1 1) とみなす
(14) から (a) setuid(1)
(b) setreuid(1,1)
(c) setuid(1)
(10) r 1
(11) から (b) setreuid(r,1) <id交換>
(11) 1 r
(10) から (b) setreuid(1,r) <id交換>
(12) 1 2
(11) から (b) setreuid(-1,2)
(c) seteuid(2)
(13) から (b) setreuid(1,2) <id交換>
(13) 2 1
(11) から (b) setreuid(2,1)
(12) から (b) setreuid(2,1) <id交換>
(14) から (b) setreuid(-1,1)
(c) seteuid(1)
(14) 2 r
(10') r 2 からとすれば (11) と同様
-------------------------------------------------------
suid-ruby
(11) が起点
(11) --> (00)
(a) setuid(r)
(b) setreuid(r,r)
(c) setuid(r)
(11) --> (01)
(a) setuid(1)
(b) setreuid(1,1)
(c) setuid(1)
(11) --> (10)
(a) 不可能
(b) setreuid(r,1)
(c) 不可能
(11) --> (12)
(a) 不可能
(b) setreuid(-1,2)
(c) 不可能
-------------------------------------------------------
情况の仮定の追加
(d) setuid + <id交換> == (a) + <id交換>
(e) setuid + seteuid + <id交換> == (c) + <id交換>
-------------------------------------------------------
suid-ruby
(11) --> (00)
(d) setuid(r)
(e) setuid(r)
(11) --> (01)
(d) setuid(1)
(e) setuid(1)
(11) --> (10)
(d) <id交換>
(e) <id交換>
(11) --> (12)
(d) 不可能
(e) seteuid(2)==>(1 2 r);<id交換>==>(2 1 1);<id交換>
-------------------------------------------------------
(d),(e) の設定で (00) 以外からそれぞれへ変換可能な直接パス
(10) へのパス
(11) から (d) <id交換>
(e) <id交換>
(20) から (e) seteuid(1)
(11) へのパス
(10) から (d) <id交換>
(e) <id交換>
(21) から (d) <id交換>
(e) <id交換>
(23) から (d) setuid(r)
(e) setuid(r) or seteuid(r)
(40) から (d) setuid(r)
(e) setuid(r) or seteuid(r)
(12) へのパス
(13) から (d) <id交換>
(e) <id交換>
(30) から (d) setuid(2)
(e) setuid(2) or seteuid(2)
(41) から (d) <id交換>
(e) <id交換>
(13) へのパス
(12) から (d) <id交換>
(e) <id交換>
(31) から (d) setuid(1)
(e) setuid(1) or seteuid(1)
(40) から (d) <id交換>
(e) <id交換>
(14) へのパス
(21') r 2 r から (d) <id交換>
(e) <id交換>
(23') 2 2 r から (d) setuid(r)
(e) setuid(r) or seteuid(r)
(41) から (d) setuid(r)
(e) setuid(r) or seteuid(r)
(20) へのパス
(10) から (d) setuid(r)
(e) setuid(r) or seteuid(r)
(21) へのパス
到達不能 : (00) から (e) seteuid(1) 以外では不可能
(22) へのパス
到達不能
(23) へのパス
(11) から (e) seteuid(1)
(30) へのパス
(12) から (d) setuid(1)
(e) setuid(1) or seteuid(1)
(31) へのパス
(13) から (d) setuid(2)
(e) setuid(2) or seteuid(2)
(32) へのパス
到達不能 : (22) からなら可だが,(22) が到達不能
(40) へのパス
(11) から (e) seteuid(2)
(41) へのパス
(14) から (e) seteuid(1)
-------------------------------------------------------
(11) からの到達パス
(00) (a) setuid(r)
(b) setreuid(r,-1)
(c) setuid(r)
(d) setuid(r)
(e) setuid(r)
(01) (a) setuid(1)
(b) setreuid(-1,1)
(c) setuid(1)
(d) setuid(1)
(e) setuid(1)
(10) (a) 到達不能
(b) <id交換>
(c) 到達不能
(d) <id交換>
(e) <id交換>
(12) (a) 到達不能
(b) setreuid(-1,2)
(c) 到達不能
(d) 到達不能
(e) seteuid(2)==>(1 2 r);<id交換>==>(2 1 1);<id交換>
(13) (a) 到達不能
(b) setreuid(2,1) [ or setreuid(-1,2)==>(1 2 ?);<id交換> ]
(c) 到達不能
(d) 到達不能
(e) seteuid(2)==>(1 2 r);<id交換>
(14) (a) 到達不能
(b) setreuid(2,-1)
(c) 到達不能
(d) 到達不能
(e) setuid(r)==>(r r r);seteuid(2)==>(r 2 r);<id交換>
(20) (a) 到達不能
(b) setreuid(-1,r)
(c) 到達不能
(d) <id交換>==>(r 1 1);setuid(r)
(e) <id交換>==>(r 1 1);setuid(r) or seteuid(r)
(21) (a) 到達不能
(b) 到達不能
(c) setuid(r)==>(r r r);seteuid(1)
(d) 到達不能
(e) setuid(r)==>(r r r);seteuid(1)
(23) (a) 到達不能
(b) setreuid(-1,1)
(c) seteuid(1)
(d) 到達不能
(e) seteuid(1)
(30) (a) 到達不能
(b) setreuid(-1,2)==>(1 2 2);setreuid(-1,1)
(c) 到達不能
(d) 到達不能
(e) seteuid(2)==>(1 2 r);<id交換>==>(2 1 1);<id交換>==>(1 2 2);
setuid(1) or seteuid(1)
(31) (a) 到達不能
(b) setreuid(2,1)==>(2 1 1);setreuid(-1,2)
[ or setreuid(-1,2)==>(1 2 ?);<id交換>==>(2 1 1);setreuid(-1,2) ]
(c) 到達不能
(d) 到達不能
(e) seteuid(2)==>(1 2 r);<id交換>==>(2 1 1);setuid(2) or seteuid(2)
(40) (a) 到達不能
(b) 到達不能
(c) seteuid(2)
(d) 到達不能
(e) seteuid(2)
(41) (a) 到達不能
(b) 到達不能
(c) 到達不能
(d) 到達不能
(e) setuid(r)==>(r r r);seteuid(2)==>(r 2 r);<id交換>;seteuid(1)
-------------------------------------------------------
(11) からの到達パス (sid が存在しない環境)
(00) (a) setuid(r)
(b) setreuid(r,-1)
(c) setuid(r)
(d) setuid(r)
(e) setuid(r)
(01) (a) setuid(1)
(b) setreuid(-1,1)
(c) setuid(1)
(d) setuid(1)
(e) setuid(1)
(10) (a) 到達不能
(b) <id交換>
(c) 到達不能
(d) <id交換>
(e) <id交換>
(12) (a) 到達不能
(b) setreuid(-1,2)
(c) seteuid(2)
(d) 到達不能
(e) seteuid(2)
[ seteuid(2)==>(1 2 (r));<id交換>==>(2 1 (1));<id交換> でも同じ ]
(13) (a) 到達不能
(b) setreuid(2,1) [ or setreuid(-1,2)==>(1 2 (?));<id交換> ]
(c) 到達不能
(d) 到達不能
(e) seteuid(2)==>(1 2 (r));<id交換>
(14) (a) 到達不能
(b) setreuid(2,-1)
(c) 到達不能
(d) 到達不能
(e) setuid(r)==>(r r (r));seteuid(2)==>(r 2 (r));<id交換>
-------------------------------------------------------
設定 (e) なら全ケースで OK
sid が存在する環境での (11) からの (e) での到達パスを
そのまま sid が存在しない環境に適用しても,無駄は出るが,問題なし.
-------------------------------------------------------
情况の仮定の追加
(f) setuid と setreuid しか持たない
-------------------------------------------------------
suid-ruby
(11) --> (00)
(f) setuid(r)
(11) --> (01)
(f) setuid(1)
(11) --> (10)
(f) <id交換>
(11) --> (12)
(f) setreuid(-1,2)
[ seteuid(2) == setreuid(-1,2) とした場合の
(e) seteuid(2)==>(1 2 r);<id交換>==>(2 1 1);<id交換> でも同じ ]
-------------------------------------------------------
(f) の設定で (00) 以外からそれぞれへ変換可能な直接パス
(10) へのパス
(11) から (f) <id交換>
(20) から (f) setreuid(-1,1)
[ seteuid(1) == setreuid(-1,1) とした場合の (e) と同じ ]
(11) へのパス
(10) から (f) <id交換>
(21) から (f) <id交換>
(23) から (f) setuid(r) or setreuid(-1,r)
[ seteuid(1) == setreuid(-1,1) とした場合の (e) と同じ ]
# (40) から (f) setuid(r) or setreuid(-1,r)
# [ seteuid(1) == setreuid(-1,1) とした場合の (e) と同じ ]
(12) へのパス
(13) から (f) <id交換>
(30) から (f) setuid(2) or setreuid(-1,2)
[ seteuid(2) == setreuid(-1,2) とした場合の (e) と同じ ]
# (41) から (f) <id交換>
(13) へのパス
(12) から (f) <id交換>
(31) から (f) setuid(1) or setreuid(-1,1)
[ seteuid(1) == setreuid(-1,1) とした場合の (e) と同じ ]
# (40) から (f) <id交換>
(14) へのパス
(21') r 2 r から (f) <id交換>
(23') 2 2 r から (f) setuid(r) or setreuid(-1,r)
[ seteuid(r) == setreuid(-1,r) とした場合の (e) と同じ ]
# (41) から (f) setuid(r) or setreuid(-1,r)
# [ seteuid(r) == setreuid(-1,r) とした場合の (e) と同じ ]
(20) へのパス
(10) から (f) setuid(r)
(21) へのパス
到達不能
(22) へのパス
到達不能
(23) へのパス
(11) から (f) setreuid(-1,1)
[ seteuid(1) == setreuid(-1,1) とした場合の (e) と同じ ]
(30) へのパス
(12) から (f) setuid(1) or setreuid(-1,1)
[ seteuid(1) == setreuid(-1,1) とした場合の (e) と同じ ]
(31) へのパス
(13) から (f) setuid(2) or seteuid(-1,2)
[ seteuid(2) == setreuid(-1,2) とした場合の (e) と同じ ]
(32) へのパス
到達不能
(40) へのパス
到達不能
(41) へのパス
到達不能
-------------------------------------------------------
seteuid が存在しない場合,
(21), (40), (41) への到達可能性が失われる.
それ以外は,seteuid(x) == setreuid(-1,x) とすることで (e) と同等.
-------------------------------------------------------
[結論???]
・(21), (40), (41) へ到達できない環境が発生するのはあきらめる.
・Process.uid(id)
if setreuid が存在 then setreuid(-1,id)
else setuid が存在 then setuid(id)
else setruid が存在 then setruid(id)
else あきらめる
Process.euid(id)
if setreuid が存在 then setreuid(id,-1)
else seteuid が存在 then seteuid(id)
else あきらめる
Process.swap_uid --- 新設
if setreuid が存在 then setreuid(geteuid(),getuid())
else あきらめる
-------------------------------------------------------
==========================================================
--
永井 秀利 (九工大 知能情報)
nagai@ai.kyutech.ac.jp