[Haskell-cafe] More on the random idea

Donald Bruce Stewart dons at cse.unsw.edu.au
Sat May 26 06:07:10 EDT 2007

> Since the online lambdabot still doesn't seem to want to talk to me, 
> I've been thinking about how I might rectify the situation...
> Apparently GHC has a flag that makes it execute a Haskell expression 
> directly. For example,
> C:\> ghc -e "map (2*) [1,2,3]"
> [2,4,6]
> Now, if I could just figure out how to make a web server call GHC... I'm 
> laughing!
> Oh, but there is the *minor* detail that I am literally allowing 
> unauthenticated users to perform arbitrary code execution. For example,
> C:\> ghc -e "writeFile \"Test.txt\" \"Hi mum!\""
> (Generates a file on my harddrive "Test.txt" containing the text "Hi mum!".)
> AFAIK, Lambdabot dissalows any expression that performs IO. In Haskell, 
> this is beautifully easy: reject any expression having an IO type. And 
> it seems that GHC accepts not just an *expression*, but a *command*. In 
> particular, this works:
> C:\> ghc -e ":t writeFile \"Test.txt\" \"Hi mum!\""
> writeFile "Test.txt" "Hi mum!" :: IO ()
> However, when you consider that the result type could be "IO ()" or "IO 
> String" or "IO [Either (Maybe Int, (String, Bool)) [Either (Int -> 
> String) (Complex Integer)]]", and the expression itself may well contain 
> the "::" sequence... you see we have a nontrivial parsing task here! 
> (Get the parsing wrong and somebody might be able to do Evil Things to 
> the box.)

Don't use parsing for security, use the type checker. By using 'show',
you can write an instance for IO a that renders all IO harmless. Then
just wrap your user's arbitrary expression in 'show. 

This is what lambdabot does. So we have:

Safe, pure expressions, just shown:

    20:04  dons> > map (^2) [1..]
    20:04  lambdabot> [1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361,400,441,484...

IO, shown, by a Show instance that renders it harmless:

    20:04  dons> > readFile "/etc/passwd"
    20:04  lambdabot>  <IO [Char]>

And we can then play some clever tricks for functions:

    20:04  dons> > ord
    20:04  lambdabot>  <Char -> Int>

> The other possibility is to somehow run GHC under a user context that 
> doesn't *have* write access to anything on the filesystem. That way 
> there is no margin for error.

Well, that's overkill, when you have a pure language, with a strong type
system that tags IO. :-)

> This leaves only the problem of how to make a web server call GHC. I can 
> think of a number of possibilities.
> - Write my own HTTP server from scratch. (Not keen...)
> - Configure Apache to do it. (Is that physically possible?)
> - Use Apache and some bizzare Perl scripting to do the actual call. 
> (Assuming *that* is possible.)
> - Use Apache and some Perl scripts to write the data to a text file, and 
> write a small Haskell program to poll the filesystem waiting for request 
> files to appear, run then though GHC, and put the result back into a 
> file. Write another Perl script to slurp up the result and send it back 
> to the caller.
> - Doesn't Java have a free HTTP server implementation? Maybe I could use 
> that...
> - ...others?

You could also just use 'runplugs' from lambdabot, which also handles
non-terminating programs :-)

> (I'm not sure why this should be, but it seems that Don has made several 
> replies to my emails that didn't show up in my inbox, and only show up 
> on the list archives. Oh well, anyway...)
> I lurk on the POV-Ray NNTP server, and we recently had quite a 
> discussion about Haskell. I'd *love* to be able to say to people "hey, 
> you don't even need to bother working out how to install GHC, just CLICK 
> THIS LINK and you can play with Haskell instantly!" But at the moment 
> I'm not entirely sure how to set this up. Ideas?

Yeah, an online solution to this would be good. lambdabot gives us a
start, lambdaweb goes further. But the last 5% need more work.

-- Don

More information about the Haskell-Cafe mailing list