From: Wesley J Landaker Date: 2003-06-03T10:29:16+09:00 Subject: setuid/setgid ruby scripts --Boundary-00=_Wl/2+CZn0nstYF1 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Hey folks, Yesterday I needed to make a program setgid, but as you probably know, you can't (at least, not under linux) just set the setuid or setgid bits, as it won't be honored for #! scripts. Anyway, my first solution was to embed a ruby script in an executable and have the executable run it. That worked, but was a little bit annoying to write, and lost the advantage of being easily modifiable (easily==no recompile, etc). So, I made a "better" version that was just: #include int main(int argc, char *argv[]) { const char *script = "/absolute/path/to/ruby/script.rb" execv(script, argv); } And then setuid the result. Anyway, I was just wondering if anyone has ever needed to make a ruby script setuid or setgid before--and if so, how did you go about doing it? Any comments about this solution in general? Seems like it's possible that there could be some sort of potential exploit through environment poisoning or something, but I can't think of anything off-hand. (In this example, it was setgid to a specific single-task group, so I'm not too worried about it; but as a general case, it would be more important to think about...) (For the curious, the actual application is a nethack restore-saved-game script, for those of us who sometimes like to cheat at nethack (mostly my wife, but sometimes me too!). Code attached. ;) -- Wesley J. Landaker - wjl@icecavern.net OpenPGP FP: C99E DF40 54F6 B625 FD48 B509 A3DE 8D79 541F F830 --Boundary-00=_Wl/2+CZn0nstYF1 Content-Type: text/x-c++src; charset="utf-8"; name="nethack_restore.cpp" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="nethack_restore.cpp" #include int main(int, char *argv[]) { const char *script = "/usr/local/bin/nethack_restore-script.rb"; execv(script, argv); } --Boundary-00=_Wl/2+CZn0nstYF1 Content-Type: text/plain; charset="utf-8"; name="nethack_restore-script.rb" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="nethack_restore-script.rb" #!/usr/bin/ruby require 'ftools' if ARGV.length == 0 puts "Usage: nethack_restore " puts " Will restore the given filename as your nethack saved game." exit 1 end $saved_game = ARGV.shift $nethack_save_dir = "/usr/games/lib/nethackdir/save/" $user_id = Process.uid File.open("/etc/passwd").each { |line| if line =~ /^([^:]+):[^:]+:#{$user_id}:/ $user_name = $1 break end } $new_game = "#{$nethack_save_dir}#{$user_id.to_s}#{$user_name}.gz" $saved_game.untaint $new_game.untaint puts "Copying #{$saved_game} to #{$new_game}" File.cp($saved_game, $new_game) --Boundary-00=_Wl/2+CZn0nstYF1--