LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-06-2011, 07:34 AM   #16
xerox
Member
 
Registered: Mar 2011
Posts: 43

Original Poster
Rep: Reputation: 0

What would I have to change with respect to php and my script.
 
Old 05-06-2011, 07:46 AM   #17
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by xerox View Post
What would I have to change with respect to php and my script.

What exactly you do not understand in

http://www.linuxquestions.org/questi...6/#post4347166
http://www.linuxquestions.org/questi...6/#post4347666

?

Last edited by Sergei Steshenko; 05-06-2011 at 07:49 AM.
 
0 members found this post helpful.
Old 05-06-2011, 12:42 PM   #18
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
I disagree with Sergei in that I think a named pipe is much safer (and a nice privilege barrier) than having a PHP script create a file.

Let me illustrate. Save the below script in e.g. /usr/local/bin/interfacer. Create /var/lib/interfacer, owned by a user with sufficient rights, with read and traverse access to everybody, and write access for only the user: u=rwx,g=rx,o=rx. Then, run this script as that user.
Code:
#!/bin/bash
CONTROL=/var/lib/interfacer/control
PIDFILE=/var/run/interfacer.pid

# If the named pipe already exists, this script is already running.
if [ -p "$CONTROL" ]; then
    echo "$CONTROL exists; already running." >&2
    exit 1
fi

# Automatically remove the pipe and the pid file when done.
trap "rm -f '$CONTROL' '$PIDFILE'" EXIT

# If this is running as a service, we need to ignore HUP and USR1 signals.
trap "" HUP USR1

# Try creating the named pipe.
# If this fails, the trap will (try to) remove $CONTROL.
if ! mknod -m 0622 "$CONTROL" p ; then
    echo "Cannot create $CONTROL." >&2
    exit 1
fi

# Save the PID of this process in the pid file.
if ! echo "$$" > "$PIDFILE" ; then
    echo "Cannot write pid to $PIDFILE." >&2
    exit 1
fi

# At this point, we probably need to be quiet.
# You could redirect output and error to a log file here.
exec <  /dev/null
exec  > /dev/null
exec 2> /dev/null

# Infinite loop.
while [ 1 ] ; do

    # Grab up to a megabyte from the pipe.
    read -N 1048576 LINE < "$CONTROL"

    /* Remove unused characters from LINE. */
    LINE="${LINE//[^-.0-9A-Za-z_]/}"

    /* Process commands from the named pipe. */
    case "$LINE" in

        interface)
            /usr/local/wifi/bin/interface
            ;;

    esac
done

exit 0
If you want to run that from an init script, or otherwise want it to run as a daemon, start it in a new session, in the background of a subshell:
Code:
( setsid /usr/local/bin/interfacer & )
In your PHP scripts, you only need to do
PHP Code:
file_put_contents('/var/lib/interfacer/control'"interface\n"); 
to have the service script act. You can quite easily extend this for other scripts, too.

Note that this does use a bit more resources than the CGI alternative, because you have to have the Bash script (and therefore Bash shell) running all the time. It blocks in the read, so it does not consume any CPU time, but it does use memory (about a megabyte on x86, but most of that is code and thus shared; only about 250 kilobytes of unshareable data). If you have using a board with very little RAM, this is something you should be aware of.

Hope this helps.
 
1 members found this post helpful.
Old 05-06-2011, 02:39 PM   #19
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Nominal Animal View Post
I disagree with Sergei in that I think a named pipe is much safer (and a nice privilege barrier) than having a PHP script create a file.
...
Named pipe requires more attention than just creating a file. Try writing to named pipe while the the other side is not reading from it, for example.

I suggested the simplest and most forgiving solution possible. And very easy to debug.
 
1 members found this post helpful.
Old 05-06-2011, 08:05 PM   #20
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by Sergei Steshenko View Post
Named pipe requires more attention than just creating a file. Try writing to named pipe while the the other side is not reading from it, for example.
Stalling/blocking in the case of no reader is easy to work around: just set an empty SIGALRM handler, and a short timeout alarm. The write operation will then fail when the alarm goes off.

Here's a working PHP example:
Code:
<?PHP

define("CONTROL_PIPE", "/var/lib/interfacer/control");
define("CONTROL_TIMEOUT", 3); /* An integer number of seconds */

/* Set up an empty SIGALRM handler.
 * Note: User ticks are not needed, since nothing() does not need
 * to be executed by the PHP interpreter.
*/
function nothing () { return; }
pcntl_signal(SIGALRM, 'nothing', FALSE);

/* Write a string to interfacer.
 * Returns 0 if success, error code otherwise.
 *
 * Any pending timeout (alarm) will be re-armed,
 * not counting the time spent in this function.
*/
function interfacer($command)
{
    if (!is_string($command))
        return 1; /* Command is not a string */

    $length = @strlen($command);
    if ($length < 1)
        return 2; /* Empty command */

    if (@filetype(CONTROL_PIPE) != 'fifo')
        return 3; /* No control pipe */

    /* Write $command to CONTROL_PIPE, with a
     * CONTROL_TIMEOUT -second timeout.
    */
    $pending = pcntl_alarm(CONTROL_TIMEOUT);
    $result = @file_put_contents(CONTROL_PIPE, $command);
    pcntl_alarm($pending);

    if ($result < $length)
        return 4; /* Cannot write to the pipe */

    /* Success. */
    return 0;
}

$result = interfacer("interface");
if ($result !== 0)
    echo "Failed (reason $result)\n";
else
    echo "Success!\n";
?>
(In a PHP page, each $result value should probably produce a different message.)

Quote:
Originally Posted by Sergei Steshenko View Post
I suggested the simplest and most forgiving solution possible.
I disagree, at least with the "most forgiving" part.
  1. The service script will have to either monitor the directory with the marker file (via e.g. inotifywait), or periodically check the existence of the file. inotifywait is usually not part of the default install. Periodically checking the file existence will consume power; depending on the period, the small board may not get into real deep sleep states.
  2. Using files the PHP script has no indication of whether the service is active or not.
    With the above PHP snippet and named pipes, the PHP can detect if the service is not running.
  3. Allowing PHP scripts to create files is a security risk. (The risk is significantly smaller if the using a dedicated directory outside the web tree.)
    The main source of the danger is not this PHP script (since you can make it very secure), but the fact that all other PHP scripts on your server can write there too. If there is a bug in one of them, an attacker can upload files, and even binaries to that directory, making certain attack vectors much easier.
  4. Using a named pipe the filesystem access mode for the pipe works as a privilege separation barrier. The client (the PHP running as the same user as Apache in this case) only requires write access to the pipe. The server script I wrote earlier does not assume anything about the data from the pipe, and will discard extraneous data and possibly malign characters (escape sequences and whatnot).
Therefore, I claim named pipes are more forgiving than files, and overall a better choice.
 
1 members found this post helpful.
Old 05-09-2011, 12:49 AM   #21
xerox
Member
 
Registered: Mar 2011
Posts: 43

Original Poster
Rep: Reputation: 0
I tried the script, the interfacer was running in background and i included the extra line in the php. I also has exec() call to the binary. However the wlan0 interface is still up and ifdown has not been executed.
 
Old 05-09-2011, 03:58 AM   #22
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Nominal Animal View Post
... Periodically checking the file existence will consume power; depending on the period, the small board may not get into real deep sleep states.
...
?????????????

How does 'sleep(1)' consume power other than the fact that kernel once per second allows the task to check file existence ? And how can you prove that checking availability of data in a pip consumes less power ? Checking availability of data is also a periodic check - of circular buffer position.
 
1 members found this post helpful.
Old 05-09-2011, 07:55 AM   #23
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by xerox View Post
I tried the script ...
Try to implement the simplest version I've suggested - it's very easy to debug. And security is not much of a concern - when you have it working, it'll be easy to add security measures.
 
1 members found this post helpful.
Old 05-09-2011, 08:04 AM   #24
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Nominal Animal View Post
...[*] Allowing PHP scripts to create files is a security risk. (The risk is significantly smaller if the using a dedicated directory outside the web tree.)
The main source of the danger is not this PHP script (since you can make it very secure), but the fact that all other PHP scripts on your server can write there too. If there is a bug in one of them, an attacker can upload files, and even binaries to that directory, making certain attack vectors much easier.
...
Somehow I'm not scared. Or no more scared than realizing that living contains risk of death.

To be more particular:
  1. A partition with no exec mounting can be created, so whatever an attacker uploads won't be executable;
  2. Either RAMFS or TMPFS have a provision of limiting the filesystem size, so the attacker won't be able to upload much. The needed size is very small - one zero length request file plus whatever directory records take;
  3. The root process monitoring creation/existence of the request file can unconditionally delete all other files. In fact, assuming the request file is called 'request' the acknowledge action can be not just 'rm request', but rather 'rm -rf *' - the action, of course, should be taken in the directory containing the request file.
.

I very strongly suggest sticking to KISS and "don't panic" principles.
 
1 members found this post helpful.
Old 05-09-2011, 12:42 PM   #25
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by Sergei Steshenko View Post
?????????????

How does 'sleep(1)' consume power other than the fact that kernel once per second allows the task to check file existence ?
That is the reason. Small boards often use a tickless kernel, and use larger intervals (for filesystem caching et cetera) to avoid waking up the kernel too often. Depending on the board, the differences are surprisingly large.

Quote:
Originally Posted by Sergei Steshenko View Post
And how can you prove that checking availability of data in a pip consumes less power ? Checking availability of data is also a periodic check - of circular buffer position.
There is no periodic check with a named pipe.

Named pipe will block a reader in open(), until there is a writer present. If you bother to strace the script, you'd see that it blocks in the open() syscall; this means that the kernel will not give it any CPU time before a writer opens the named pipe. This allows the kernel to go into any sleep state.
 
1 members found this post helpful.
Old 05-09-2011, 12:53 PM   #26
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by Sergei Steshenko View Post
A partition with no exec mounting can be created, so whatever an attacker uploads won't be executable;
That will not prevent the attacker from uploading shell or PHP scripts. PHP ignores the noexec flag (scripts are just data files to it), and shell scripts can be sourced instead of executed directly. Uploaded binaries are rare, but scripts are often used for making the machine a drop box.

Quote:
Originally Posted by Sergei Steshenko View Post
Either RAMFS or TMPFS have a provision of limiting the filesystem size, so the attacker won't be able to upload much. The needed size is very small - one zero length request file plus whatever directory records take
A good idea, especially if you use flag directories (since their creation is atomic) instead of files. However, this means a new filesystem, additional system-level configuration, and plenty of resources taken up in the kernel.

Quote:
Originally Posted by Sergei Steshenko View Post
The root process monitoring creation/existence of the request file can unconditionally delete all other files.
Another good idea, except that any small typo or bug in the script may cause it to inadvertently remove the wrong tree.

Quote:
Originally Posted by Sergei Steshenko View Post
I very strongly suggest sticking to KISS and "don't panic" principles.
I fully agree. I just believe named pipes are simpler, safer, and more appropriate for this.
 
1 members found this post helpful.
Old 05-09-2011, 01:02 PM   #27
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by xerox View Post
I tried the script, the interfacer was running in background and i included the extra line in the php. I also has exec() call to the binary. However the wlan0 interface is still up and ifdown has not been executed.
Did you run the interfacer with sufficient privileges, i.e. as root in your case? I suspect /usr/local/wifi/bin/interface is called, but with insufficient privileges to take down the interface. I did test both the script and the PHP code, and it works for me.

I suggest you change
Code:
exec  > /dev/null
exec 2> /dev/null
to
Code:
exec  >> /tmp/interfacer.log
exec 2>> /tmp/interfacer.log
to log any errors or output you get from the interfacer script.
 
1 members found this post helpful.
Old 05-09-2011, 01:34 PM   #28
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Nominal Animal View Post

...
Another good idea, except that any small typo or bug in the script may cause it to inadvertently remove the wrong tree.
...
OK, then

Code:
rm -rf /full/path/to/request/dir/*
.
 
1 members found this post helpful.
Old 05-09-2011, 01:48 PM   #29
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
And, if the OP is working on some kind of wireless router and its web interface, power consumption doesn't matter - it's not a battery operated device in the first place.
 
1 members found this post helpful.
Old 05-09-2011, 02:45 PM   #30
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by Sergei Steshenko View Post
And, if the OP is working on some kind of wireless router and its web interface, power consumption doesn't matter - it's not a battery operated device in the first place.
Thermal issues do matter. Usually these devices do have a very low TDP, but often even worse cooling. Allowing the CPU all the opportunity to sleep will help.

Do you have any specific reason to avoid named pipes here? I showed both the reader side (56 lines in Bash) and safe writer side (46 lines of PHP). As far as I know they are safe and complete for this use case, and IMHO quite simple. I don't know how much simpler than that you can get, and stay safe!
 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How can you see if a binary is running? Muscovy Linux - General 2 08-19-2010 11:13 PM
running binary using C fs11 Programming 2 09-08-2007 03:24 AM
Mandrake 10.1 PHP Binary Path TotalDefiance Linux - Software 3 03-21-2005 10:16 AM
php executable binary apt Programming 4 12-08-2004 08:46 AM
Php to return a binary not html logicdisaster Programming 3 10-07-2004 01:25 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:03 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration