Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
codejail
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
codejail
Commits
a8a2de57
Commit
a8a2de57
authored
Apr 09, 2013
by
Ned Batchelder
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor code_jail to accommodate non-Python code.
parent
543de052
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
46 additions
and
32 deletions
+46
-32
codejail/django_integration.py
+2
-2
codejail/jail_code.py
+28
-18
codejail/safe_exec.py
+3
-3
codejail/tests/test_jailpy.py
+13
-9
No files found.
codejail/django_integration.py
View file @
a8a2de57
...
...
@@ -3,7 +3,7 @@
from
django.core.exceptions
import
MiddlewareNotUsed
from
django.conf
import
settings
import
codejail.jail
py
import
codejail.jail
_code
class
ConfigureCodeJailMiddleware
(
object
):
...
...
@@ -13,5 +13,5 @@ class ConfigureCodeJailMiddleware(object):
python_bin
=
settings
.
CODE_JAIL
.
get
(
'python_bin'
)
if
python_bin
:
user
=
settings
.
CODE_JAIL
[
'user'
]
codejail
.
jail
py
.
configure
(
python_bin
,
user
=
user
)
codejail
.
jail
_code
.
configure
(
"python"
,
python_bin
,
user
=
user
)
raise
MiddlewareNotUsed
codejail/jail
py
.py
→
codejail/jail
_code
.py
View file @
a8a2de57
...
...
@@ -19,39 +19,49 @@ log = logging.getLogger(__name__)
# TODO: limit too much stdout data?
# Configure the
Python command
# Configure the
commands
PYTHON_CMD
=
None
# COMMANDS is a map from an abstract command name to a list of command-line
# pieces, such as subprocess.Popen wants.
COMMANDS
=
{}
def
configure
(
python_bin
,
user
=
None
):
"""Configure the jailpy module."""
global
PYTHON_CMD
PYTHON_CMD
=
[]
def
configure
(
command
,
bin_path
,
user
=
None
):
"""Configure a command for jail_code to use.
`command` is the abstract command you're configuring, such as "python" or
"node". `bin_path` is the path to the binary. `user`, if provided, is
the user name to run the command under.
"""
cmd_argv
=
[]
if
user
:
PYTHON_CMD
.
extend
([
'sudo'
,
'-u'
,
'sandbox'
])
PYTHON_CMD
.
extend
([
python_bin
,
'-E'
])
cmd_argv
.
extend
([
'sudo'
,
'-u'
,
'sandbox'
])
cmd_argv
.
extend
([
bin_path
,
'-E'
])
COMMANDS
[
command
]
=
cmd_argv
def
is_configured
():
return
bool
(
PYTHON_CMD
)
def
is_configured
(
command
):
return
command
in
COMMANDS
# By default, look where our current Python is, and maybe there's a
# python-sandbox alongside. Only do this if running in a virtualenv.
if
hasattr
(
sys
,
'real_prefix'
):
if
os
.
path
.
isdir
(
sys
.
prefix
+
"-sandbox"
):
configure
(
sys
.
prefix
+
"-sandbox/bin/python"
,
"sandbox"
)
configure
(
"python"
,
sys
.
prefix
+
"-sandbox/bin/python"
,
"sandbox"
)
class
JailResult
(
object
):
"""A passive object for us to return from jail
py
."""
"""A passive object for us to return from jail
_code
."""
def
__init__
(
self
):
self
.
stdout
=
self
.
stderr
=
self
.
status
=
None
def
jailpy
(
code
,
files
=
None
,
argv
=
None
,
stdin
=
None
):
"""
Run Python code in a jailed subprocess.
def
jail_code
(
command
,
code
,
files
=
None
,
argv
=
None
,
stdin
=
None
):
"""Run code in a jailed subprocess.
`command` is an abstract command ("python", "node", ...) that must have
been configured using `configure`.
`code` is a string containing the Python code to run.
...
...
@@ -64,8 +74,8 @@ def jailpy(code, files=None, argv=None, stdin=None):
.status: return status of the process: an int, 0 for successful
"""
if
not
PYTHON_CMD
:
raise
Exception
(
"jail
py needs to be configured"
)
if
not
is_configured
(
command
)
:
raise
Exception
(
"jail
_code needs to be configured for
%
r"
%
command
)
with
temp_directory
(
delete_when_done
=
True
)
as
tmpdir
:
...
...
@@ -83,7 +93,7 @@ def jailpy(code, files=None, argv=None, stdin=None):
with
open
(
os
.
path
.
join
(
tmpdir
,
"jailed_code.py"
),
"w"
)
as
jailed
:
jailed
.
write
(
code
)
cmd
=
PYTHON_CMD
+
[
'jailed_code.py'
]
+
(
argv
or
[])
cmd
=
COMMANDS
[
command
]
+
[
'jailed_code.py'
]
+
(
argv
or
[])
subproc
=
subprocess
.
Popen
(
cmd
,
preexec_fn
=
set_process_limits
,
cwd
=
tmpdir
,
...
...
codejail/safe_exec.py
View file @
a8a2de57
...
...
@@ -7,7 +7,7 @@ import shutil
import
sys
import
textwrap
from
codejail
import
jail
py
from
codejail
import
jail
_code
from
codejail.util
import
temp_directory
,
change_directory
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -85,7 +85,7 @@ def safe_exec(code, globals_dict, files=None, python_path=None):
log
.
debug
(
"Exec:
%
s"
,
code
)
log
.
debug
(
"Stdin:
%
s"
,
stdin
)
res
=
jail
py
.
jailpy
(
jailed_code
,
stdin
=
stdin
,
files
=
files
)
res
=
jail
_code
.
jail_code
(
"python"
,
jailed_code
,
stdin
=
stdin
,
files
=
files
)
if
res
.
status
!=
0
:
raise
Exception
(
"Couldn't execute jailed code:
%
s"
%
res
.
stderr
)
globals_dict
.
update
(
json
.
loads
(
res
.
stdout
))
...
...
@@ -144,5 +144,5 @@ def not_safe_exec(code, globals_dict, files=None, python_path=None):
# Running Python code in the sandbox makes it difficult to debug.
# Change 0 to 1 to run the code directly.
if
0
or
not
jail
py
.
is_configured
(
):
if
0
or
not
jail
_code
.
is_configured
(
"python"
):
safe_exec
=
not_safe_exec
codejail/tests/test_jailpy.py
View file @
a8a2de57
"""Test jail
py
.py"""
"""Test jail
_code
.py"""
import
os.path
import
textwrap
import
unittest
from
nose.plugins.skip
import
SkipTest
from
codejail.jail
py
import
jailpy
,
is_configured
from
codejail.jail
_code
import
jail_code
,
is_configured
dedent
=
textwrap
.
dedent
class
JailPyHelpers
(
object
):
"""Assert helpers for jailpy tests."""
def
jailpy
(
*
args
,
**
kwargs
):
return
jail_code
(
"python"
,
*
args
,
**
kwargs
)
class
JailCodeHelpers
(
object
):
"""Assert helpers for jail_code tests."""
def
setUp
(
self
):
super
(
Jail
Py
Helpers
,
self
)
.
setUp
()
if
not
is_configured
():
super
(
Jail
Code
Helpers
,
self
)
.
setUp
()
if
not
is_configured
(
"python"
):
raise
SkipTest
def
assertResultOk
(
self
,
res
):
...
...
@@ -22,7 +26,7 @@ class JailPyHelpers(object):
self
.
assertEqual
(
res
.
status
,
0
)
class
TestFeatures
(
Jail
Py
Helpers
,
unittest
.
TestCase
):
class
TestFeatures
(
Jail
Code
Helpers
,
unittest
.
TestCase
):
def
test_hello_world
(
self
):
res
=
jailpy
(
"print 'Hello, world!'"
)
self
.
assertResultOk
(
res
)
...
...
@@ -64,7 +68,7 @@ class TestFeatures(JailPyHelpers, unittest.TestCase):
self
.
assertEqual
(
res
.
stdout
,
'Look: Hello there.
\n\n
'
)
class
TestLimits
(
Jail
Py
Helpers
,
unittest
.
TestCase
):
class
TestLimits
(
Jail
Code
Helpers
,
unittest
.
TestCase
):
def
test_cant_use_too_much_memory
(
self
):
res
=
jailpy
(
"print sum(range(100000000))"
)
self
.
assertNotEqual
(
res
.
status
,
0
)
...
...
@@ -114,7 +118,7 @@ class TestLimits(JailPyHelpers, unittest.TestCase):
# TODO: fork
class
TestMalware
(
Jail
Py
Helpers
,
unittest
.
TestCase
):
class
TestMalware
(
Jail
Code
Helpers
,
unittest
.
TestCase
):
def
test_crash_cpython
(
self
):
# http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html
res
=
jailpy
(
dedent
(
"""
\
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment