Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

Perlmonks Mush, revisited (Perl as as scripting language)

by BUU (Prior)
on Jun 05, 2004 at 06:47 UTC ( #361390=perlmeditation: print w/replies, xml ) Need Help??

I was, inspired, by some of the previous posts talking about this type of stuff so I went out and spent some time researching various options. The thing itself isn't so difficult, writing the server, writing the client, communication, etc. The tricky part, and that part thats caused me to give up, is using perl as a scripting language. The problem with perl, of course, is that it's so powerful, that if you tried to use it as a scripting language people could easily mess up stuff, where stuff is the file system, your running processes, the game itelf, etc.

This is what I came up with to "Secure" perl as a scripting language.

Each object would basically have it's own perl code that described it. How exactly this would work I haven't decided yet, but it would be based around some sort of event module, so the code making up the module would be compiled, then some event would be passed to it, it would execute based on the event and return it's response, then the server would do stuff based on the response.

Step one, the server code decides it needs to execute an object, as it were, so it loads the perl code for that object and forks a new copy of the perl interpreter(open3(in,out,er,"perl");).

This child is then
  1. Chrooted/chdired to an empty directory someplace
  2. Rlimited, with fairly stricts limits on cpu time, memory and processes
  3. The owner changed to a user with no privledges anywhere, read or write or exec.
Then the child gets passed the perl code that makes up the object, it executes it and passes back it's response (probably via a frozen datastructure of some sort which is thawed by the server) and the server does stuff based on the response.

As far as I can tell, this series of events should be ultimately secure -- in the sense that the object code cannot mess with the server or the system in any destructive manner.

The problem, is speed. Forking is slow, as people who use mod_cgi in apache well know. Forking and then execing perl, on my benchmark, could be done around 1500 times a second. Now in my benchmark, the exec'd perl didn't actually do anything, so doing lots of stuff will slow this figure down considerably. And even though this sounds like a really big number, it's not. 10 users in a room with 10 objects. Someone does something, 10 forks. The object does somethng, another 10 forks. Repeat for each user and object.

So in short, this doesn't sound practical, but I can't see another way of *safely* using perl as as scripting language. The "mod_perl" like solution, which is a long running process that executes this code, isn't practical for a number of reasons. The main one is that the process has to be seperate to be able to be chrooted/rlimited, and the strict rlimits would kill this process, and secondly because the perl code could interfer with other perl code, like on shared mod_perl servers.

(Note, I have looked at Safe, and while it looks nice, it can't prevent everything such as cpu or memory "attacks", and I don't particuraly trust it)

I did another fork benchmark, this time doing "exec perl -e'use CGI;'" after my fork in the "timethese" subroutine, and while it still claims "1428/s", it took 250 wallclock seconds to execute (0.00 usr, 0.70 sys + 217.93 cusr 27.38 csys = 246.01 CPU )so I suspect something isn't being properly accounted for. Probably because the fork's childrens cpu time isn't being counted or something. So forking a perl interpreter for every object is really a non good idea.

Replies are listed 'Best First'.
Re: Perlmonks Mush, revisited (Perl as as scripting language)
by jepri (Parson) on Jun 05, 2004 at 11:33 UTC
    Perl has always worked closely with the system, and tends to rely on the underlying OS for services like security. Which is really where that sort of thing should be. You'll only be reinventing the wheel doing your own full blown security fraemwork.

    So instead, try Mooix. It works with perl.

    I didn't believe in evil until I dated it.

      The problem with mooix, as far as I can tell, is it just punts the idea of security on the scripts you write by making "programmer" some kind of priveldged class. Thats not really what I was looking for.
Re: Perlmonks Mush, revisited (Perl as as scripting language)
by revdiablo (Prior) on Jun 05, 2004 at 20:50 UTC

    As we were talking about this on IRC, I mentioned something that I might not have fully explained. In order to avoid the forking overhead, you could instead have one -- or maybe one for each user? The details aren't as important as the concept -- persistant perl executable that is chrooted, secured, etc. You could hand this process various bits of code, which it would then execute and return whatever needs to be returned.

    This is all within the realm of standard IPC. You'd have to work out some sort of protocol, consider concurrency issues, etc. I wouldn't be surprised if there are already CPAN modules to take care of some of the work for you, but I don't know of any off the top of my head. This all adds complexity, but the overhead gain may be a net win. You'd have to experiment to be sure.


      The problem with this is that it would be impossible to impose appropiate rlimits upon this long running process, the cpu limit would kill the stupid thing, so I'm concerned about this "mod_perl" like process using up too many resources on the box.
Re: Perlmonks Mush, revisited (Perl as as scripting language)
by Solo (Deacon) on Jun 06, 2004 at 15:40 UTC
    I'm not sure I really get your concept of a Perl MUSH, but what if you were to use something like Template Toolkit as the scripting language, and allow its [% PERL %] directive only after a user has attained a 'rank' that helps assure they are not going to intentionally abuse the system?

    There is still the chance of accidental or unintentional abuse, or the patient malcontent willing to earn the rank needed to really bring down the system.

    You said you wanted to be around when I made a mistake; well, this could be it, sweetheart.
Re: Perlmonks Mush, revisited (Perl as as scripting language)
by Kageneko (Scribe) on Jun 07, 2004 at 16:49 UTC
    Random thoughts:

    * Go multithreaded. Have 10 interpreter threads and a monitor thread. If a particular thread is taking too long at a task, the monitor will kill the thread and start a new one.

    * Fork the interpreter children at the beginning and trade data with them via pipes. In your mush's MainLoop, have it check some kind of magic data for the End-of-processing message. If things take too long, send SIGHUP (or something) to the child and have the child kill things.

    Implementation details are left up to the reader. These are just ideas :)

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://361390]
Approved by Zaxo
Front-paged by jeffa
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2022-05-27 18:14 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (97 votes). Check out past polls.