Skip to content

Instantly share code, notes, and snippets.

@sitano
Last active April 29, 2022 13:21
Show Gist options
  • Save sitano/187ac7f2ff3bba079b6fbcbccd4863fd to your computer and use it in GitHub Desktop.
Save sitano/187ac7f2ff3bba079b6fbcbccd4863fd to your computer and use it in GitHub Desktop.
ruby_fork_pgkill_test.rb
$stdin.sync = true;
$stdout.sync = true;
$a = true
def handle(id, sig)
puts id.to_s + " got " + sig.to_s + " at " + Process.pid.to_s
$a = false
end
def def!(id)
Proc.new { |sig| handle(id, sig) }
end
def trap_all(id)
trap(0, def!(id))
trap("TERM", def!(id))
trap("INT", def!(id))
end
pid = Process.fork do
Process.fork do
trap_all 1
while $a
puts "1t "+Process.pid.to_s
sleep 1
end
end
Process.fork do
trap_all 2
while $a
puts "2t "+Process.pid.to_s
sleep 1
end
end
end
puts "start"
Process.wait pid
puts "forked"
Process.fork do
trap_all 3
while $a
puts "3t "+Process.pid.to_s
sleep 1
end
end
puts "waiting"
trap_all 0
system("ps ax -o pid,ppid,pgid,sess,tty,tpgid,cmd --forest | grep [1].rb")
while a
sleep 1
end
puts "exiting..."
sleep 5
puts "end"
@sitano
Copy link
Author

sitano commented Apr 28, 2022

       command:
          - /usr/bin/tini
          - -s
          - -vvv
          - /bin/dash
          - --
          - -c
        args:
          - echo '$stdout.sync = true; $a = true; def handle(id, sig); puts id.to_s + " got " + sig.to_s + " at " + Process.pid.to_s; $a = false; end; def def!(id); Proc.new { |sig| handle(id, sig) }; end; def trap_all(id); trap(0, def!(id)); trap("TERM", def!(id)); trap("INT", def!(id)); end; pid = Process.fork do; Process.fork do;   trap_all 1;   while $a;   puts "1t "+Process.pid.to_s;   sleep 1;   end; end; Process.fork do;   trap_all 2;   while $a;   puts "2t "+Process.pid.to_s;   sleep 1;   end; end; end; puts "start"; puts "forked"; puts "waiting"; trap_all 0; puts "trapped"; while $a; puts "step"; sleep 1; end; puts "exiting..."; sleep 5; puts "end";' > /app/1.rb;
            exec su -p -c 'exec ruby /app/1.rb' -l user;

results in a tree

ps ax -o pid,ppid,pgid,sess,tty,tpgid,cmd --forest
    PID    PPID    PGID    SESS TT         TPGID CMD
      1       0       1       1 ?             -1 /usr/bin/tini -s -v -p SIGINT /bin/dash -- -c
      7       1       7       1 ?             -1 su -p -c exec ruby /app/1.rb -l slug
     10       7      10      10 ?             -1  \_ ruby /app/1.rb
     14      10      10      10 ?             -1      \_ [ruby] <defunct>
     17       1      10      10 ?             -1 ruby /app/1.rb
     20       1      10      10 ?             -1 ruby /app/1.rb

so that when we downscale a pod to 0 all the processes in a PGID=10 receive a SIGTERM signal :OMG:

@sitano
Copy link
Author

sitano commented Apr 29, 2022

so the reason is that there are many implementations of su and they are all very different. for example:

the one that is in the k8s Pod's is from the shadow's repo does kill(-PID, signo) that actually broadcasts the SIGTERM.

https://launchpad.net/ubuntu/+source/shadow/1:4.5-1ubuntu2.2

su however is not recommended for dropping privileges http://jdebp.info/FGA/dont-abuse-su-for-dropping-privileges.html. and for fixing that I will try to move to https://github.com/daemontools/daemontools/blob/master/src/setuidgid.c.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment