strange behaviour with system("vsftpd") call

Hi

I am having a bit of a problem with this strange behaviour of system().
On my portux (2.6.12) runs a server, that answers to
requests coming from a PC
connected through the ETH cable, and a linux driver that catches the
interrupts generated by a device and reads its FIFO.
The driver is loaded by the server (started after the boot) with
the call

system("insmod tdc.ko");

Communication with the device occurs using a "/dev/tdc 240 0" node
which I create immediately after booting Portux.
When the server is started, the file "/dev/tdc" is opened.
When the server is restarted, I first close the file, then issue

system("rmmod tdc");

If I issue the "rmmod" command before having closed the file, I get
the error message "Resource temporarily unavailable".
And everything worked fine til now.
Now I decided to start an FTP server when Portux receives a certain
command coming from the PC.
When the user wants to start the FTP server, I issue a

system("vsftpd");

inside my own server.
And the server actually starts. The problem is that when I restart
my own server and I issue a close "/dev/tdc" file and then

system("rmmod tdc");

I get ALWAYS the error message "Resource temporarily unavailable".
Even if I kill my own server I cannot remove the module.
I must first kill the FTP server. Then I am allowed to issue a
"rmmod tdc" from the console to remove the module.
I simulated all this with a micro program and a very simple driver.

Best regards

Paolo Celani

AttachmentSize
test.zip17.14 KB

Re: strange behaviour with system("vsftpd") call

system() is not exactly the silver bullet when starting child processes...
system() itself uses fork() to start the child process (i.e. vsftpd), and does not close the handles inherited to the child process, so your program has an open handle to /dev/tdc, and the vsftpd server also has an (inherited) handle to /dev/tdc.

you can circumventing this by replacing the system("vsftpd") call with:

// I assume that fd_tdc is the handle to /dev/tdc
#include 
...

pid_t vsftpd_pid = fork();
if (vsftpd_pid == 0)
{
  // I am the child process
  fclose(fd_tdc);
  // close other file handles, or redirect them, close memmap()s etc.

  // do a chdir() to vsftpd's working dir?
  // chroot() ?
  
  if (execv("/sbin/vsftpd", 0) == -1)    // 1st arg = full path (adjust!), 2nd arg = char * const arg[] = program arguments
  {
    perror("error execv()ing vsftpd"); 
    exit(2);
  }
}
else if (vsftpd_pid == -1)
{
  perror("error fork()ing");
  exit(2);
}
// else I am the parent process, continue
...

a detailed description of fork is on the manpage: http://linux.die.net/man/3/fork

you could use execvp() instead of execv(), but it is considered unsafe to let the shell look for binaries that are executed as child programs (one could manipulate the PATH environment variable and inject a program file named vsftpd that would be found before the original one...)

regards
Bernd Linsel

Re: strange behaviour with system("vsftpd") call

Thank you for the very detailed answer.
I completely overlooked this problem.
Am I right if I say that, if the command executed by system() completes
and exits immediately (which is the case for "insmod tdc_int2.ko" and
"rmmod tdc_int2" but not for "vsftpd"), all resources/file handles that
the child process inherits from the parent after the successful fork()
are freed (by which I mean that the parent is again the sole owner
of thise resources/file handles) ?
This explains why I never had problem with "insmod" and "rmmod" and
other file handles I use.
The problem therefore appeared with "vsftpd" because it does not
complete immediately but it "lives" alongside its parent.
Am I right?

Best regards

Paolo Celani

Re: strange behaviour with system("vsftpd") call

yes, that's completely correct

Syndicate content