9

I would like to spawn a process suspended, possibly in the context of another user (e.g. via sudo -u ...), set up some iptables rules for the spawned process, continue running the process, and remove the iptable rules when the process exists.

Is there any standart means (bash, corutils, etc.) that allows me to achieve the above? In particular, how can I spawn a process in a suspended state and get its pid?

hanshans
  • 91
  • 1
  • 2
  • Why do you need to start the process before configuring the environment? This sound like a typical use of fork/exec combo. – Šimon Tóth Apr 24 '11 at 20:16
  • I have to make sure that all communication gets through my custom iptables. – hanshans Apr 24 '11 at 20:19
  • 1
    @Let_Me_Be because iptables needs to know the PID to operate on, in this case – Robin Green Apr 24 '11 at 20:20
  • @hanshans You didn't answer my question. I'm asking why you need to start the process before you will configure it. The normal process is to configure the environment and then start the process. This just seems weird. – Šimon Tóth Apr 24 '11 at 20:21
  • @Robin Well, that is still normal fork/exec scenario. But never mind, I'm obviously missing the point. – Šimon Tóth Apr 24 '11 at 20:23
  • is there any bash magic to actually implement such a fork/exec scenario? – hanshans Apr 24 '11 at 20:26

5 Answers5

5

Write a wrapper script start-stopped.sh like this:

#!/bin/sh
kill -STOP $$                                    # suspend myself 
                                                 # ... until I receive SIGCONT
exec $@                                          # exec argument list

And then call it like:

sudo -u $SOME_USER start-stopped.sh mycommand &  # start mycommand in stopped state
MYCOMMAND_PID=$!
setup_iptables $MYCOMMAND_PID                    # use its PID to setup iptables
sudo -u $SOME_USER kill -CONT $MYCOMMAND_PID     # make mycommand continue
wait $MYCOMMAND_PID                              # wait for its termination
MYCOMMAND_EXIT_STATUS=$?                         
teardown_iptables                                # remove iptables rules
report $MYCOMMAND_EXIT_STATUS                    # report errors, if necessary

All this is overkill, however. You don't need to spawn your process in a suspended state to get the job done. Just make a wrapper script setup_iptables_and_start:

#!/bin/sh
setup_iptables $$             # use my own PID to setup iptables
exec sudo -u $SOME_USER $@    # exec'ed command will have same PID

And then call it like

setup_iptables_and_start mycommand || report errors
teardown_iptables
Hans Lub
  • 5,513
  • 1
  • 23
  • 43
3

You can write a C wrapper for your program that will do something like this :

  1. fork and print child pid.
  2. In the child, wait for user to press Enter. This puts the child in sleep and you can add the rules with the pid.
  3. Once rules are added, user presses enter. The child runs your original program, either using exec or system.

Will this work?

Edit: Actually you can do above procedure with a shell script. Try following bash script:

#!/bin/bash

echo "Pid is $$"
echo -n "Press Enter.." 
read 
exec $@

You can run this as /bin/bash ./run.sh <your command>

Rumple Stiltskin
  • 9,597
  • 1
  • 20
  • 25
0

One way to do it is to enlist gdb to pause the program at the start of its main function (using the command "break main"). This will guarantee that the process is suspended fast enough (although some initialisation routines can run before main, they probably won't do anything relevant). However, for this you will need debugging information for the program you want to start suspended.

I suggest you try this manually first, see how it works, and then work out how to script what you've done.

Alternatively, it may be possible to constrain the process (if indeed that is what you're trying to do!) without using iptables, using SELinux or a ptrace-based tool like sydbox instead.

Robin Green
  • 32,079
  • 16
  • 104
  • 187
  • 1
    no, this will not work. I need a generic tool that works with any application. – hanshans Apr 24 '11 at 20:17
  • What about SELinux or sydbox? (I see now that I should have made that part of my answer into a separate answer.) – Robin Green Apr 24 '11 at 20:19
  • SELinux seems to be overkill for what I want to do (does Debian 6 even support this), but I will try to look into sydbox – hanshans Apr 24 '11 at 20:23
0

You probably need the PID of a program you're starting, before that program actually starts running. You could do it like this.

  • Start a plain script
  • Force the script to wait
    • You can probably use suspend which is a bash builitin but in the worst case you can make it stop itself with a signal
  • Use the PID of the bash process in every way you want
  • Restart the stopped bash process (SIGCONT) and do an exec - another builtin - starting your real process (it will inherit the PID)
cnicutar
  • 178,505
  • 25
  • 365
  • 392
0

I suppose you could write a util yourself that forks, and wherein the child of the fork suspends itself just before doing an exec. Otherwise, consider using an LD_PRELOAD lib to do your 'custom' business.

If you care about making that secure, you should probably look at bigger guns (with chroot, perhaps paravirtualization, user mode linux etc. etc);

Last tip: if you don't mind doing some more coding, the ptrace interface should allow you to do what you describe (since it is used to implement debuggers with)

sehe
  • 374,641
  • 47
  • 450
  • 633