--- /dev/null
+From 392371f70db6fe3df79a6e2306092857c4615a4b Mon Sep 17 00:00:00 2001
+From: Michael Tremer <michael.tremer@ipfire.org>
+Date: Fri, 8 Mar 2013 11:02:18 +0100
+Subject: [PATCH 04/19] Create an extra namespace for build environments and
+ private network.
+
+Create a python binding for unshare(2) and use this to
+unshare the IPC and UTS namespace (if the kernel supports that).
+
+Also add the option to use private networking in the container.
+---
+ examples/builder.conf | 6 ++++++
+ python/pakfire/builder.py | 18 +++++++++++++++++-
+ python/pakfire/cli.py | 40 ++++++++++++++++++++++++++++------------
+ python/src/_pakfiremodule.c | 13 +++++++++++++
+ python/src/util.c | 22 ++++++++++++++++++++++
+ python/src/util.h | 1 +
+ 6 files changed, 87 insertions(+), 13 deletions(-)
+
+diff --git a/examples/builder.conf b/examples/builder.conf
+index 128a118..978c7d9 100644
+--- a/examples/builder.conf
++++ b/examples/builder.conf
+@@ -23,6 +23,12 @@ file = /var/log/pakfire-builder.log
+ # Create loop devices in build environment.
+ #use_loop_devices = true
+
++# Use private network.
++# Setting this to true will result in the build
++# chroot having its own network - i.e. no network connection
++# to the outside world.
++#private_network = false
++
+ [ccache]
+ # Turn on compression to get more files into the cache.
+ #compress = true
+diff --git a/python/pakfire/builder.py b/python/pakfire/builder.py
+index 250a659..5cb00aa 100644
+--- a/python/pakfire/builder.py
++++ b/python/pakfire/builder.py
+@@ -69,7 +69,7 @@ class BuildEnviron(object):
+ # The version of the kernel this machine is running.
+ kernel_version = os.uname()[2]
+
+- def __init__(self, pakfire, filename=None, distro_name=None, build_id=None, logfile=None, release_build=True):
++ def __init__(self, pakfire, filename=None, distro_name=None, build_id=None, logfile=None, release_build=True, **kwargs):
+ self.pakfire = pakfire
+
+ # Check if the given pakfire instance is of the correct type.
+@@ -117,6 +117,7 @@ class BuildEnviron(object):
+ "enable_icecream" : self.config.get_bool("builder", "use_icecream", False),
+ "sign_packages" : False,
+ "buildroot_tmpfs" : self.config.get_bool("builder", "use_tmpfs", False),
++ "private_network" : self.config.get_bool("builder", "private_network", False),
+ }
+
+ # Get ccache settings.
+@@ -130,6 +131,9 @@ class BuildEnviron(object):
+ if self.keyring.get_host_key(secret=True):
+ self.settings["sign_packages"] = True
+
++ # Add settings from keyword arguments.
++ self.settings.update(kwargs)
++
+ # Where do we put the result?
+ self.resultdir = os.path.join(self.pakfire.path, "result")
+
+@@ -164,6 +168,14 @@ class BuildEnviron(object):
+ def start(self):
+ assert not self.pakfire.initialized, "Pakfire has already been initialized"
+
++ # Unshare namepsace.
++ # If this fails because the kernel has no support for CLONE_NEWIPC or CLONE_NEWUTS,
++ # we try to fall back to just set CLONE_NEWNS.
++ try:
++ _pakfire.unshare(_pakfire.SCHED_CLONE_NEWNS|_pakfire.SCHED_CLONE_NEWIPC|_pakfire.SCHED_CLONE_NEWUTS)
++ except RuntimeError, e:
++ _pakfire.unshare(_pakfire.SCHED_CLONE_NEWNS)
++
+ # Mount the directories.
+ self._mountall()
+
+@@ -173,6 +185,10 @@ class BuildEnviron(object):
+ # Initialize pakfire instance.
+ self.pakfire.initialize()
+
++ # Optionally enable private networking.
++ if self.settings.get("private_network", None):
++ _pakfire.unshare(_pakfire.SCHED_CLONE_NEWNET)
++
+ # Populate /dev.
+ self.populate_dev()
+
+diff --git a/python/pakfire/cli.py b/python/pakfire/cli.py
+index 232aad8..a80b397 100644
+--- a/python/pakfire/cli.py
++++ b/python/pakfire/cli.py
+@@ -543,6 +543,8 @@ class CliBuilder(Cli):
+ help=_("Run a shell after a successful build."))
+ sub_build.add_argument("--no-install-test", action="store_true",
+ help=_("Do not perform the install test."))
++ sub_build.add_argument("--private-network", action="store_true",
++ help=_("Disable network in container."))
+
+ def parse_command_shell(self):
+ # Implement the "shell" command.
+@@ -554,6 +556,8 @@ class CliBuilder(Cli):
+
+ sub_shell.add_argument("-m", "--mode", nargs="?", default="development",
+ help=_("Mode to run in. Is either 'release' or 'development' (default)."))
++ sub_shell.add_argument("--private-network", action="store_true",
++ help=_("Disable network in container."))
+
+ def parse_command_dist(self):
+ # Implement the "dist" command.
+@@ -580,22 +584,25 @@ class CliBuilder(Cli):
+ else:
+ raise FileNotFoundError, pkg
+
+- # Check whether to enable the install test.
+- install_test = not self.args.no_install_test
++ # Build argument list.
++ kwargs = {
++ "after_shell" : self.args.after_shell,
++ # Check whether to enable the install test.
++ "install_test" : not self.args.no_install_test,
++ "result_dir" : [self.args.resultdir,],
++ "shell" : True,
++ }
+
+ if self.args.mode == "release":
+- release_build = True
++ kwargs["release_build"] = True
+ else:
+- release_build = False
++ kwargs["release_build"] = False
++
++ if self.args.private_network:
++ kwargs["private_network"] = True
+
+ p = self.create_pakfire()
+- p.build(pkg,
+- install_test=install_test,
+- resultdirs=[self.args.resultdir,],
+- shell=True,
+- after_shell=self.args.after_shell,
+- release_build=release_build,
+- )
++ p.build(pkg, **kwargs)
+
+ def handle_shell(self):
+ pkg = None
+@@ -617,7 +624,16 @@ class CliBuilder(Cli):
+ release_build = False
+
+ p = self.create_pakfire()
+- p.shell(pkg, release_build=release_build)
++
++ kwargs = {
++ "release_build" : release_build,
++ }
++
++ # Private network
++ if self.args.private_network:
++ kwargs["private_network"] = True
++
++ p.shell(pkg, **kwargs)
+
+ def handle_dist(self):
+ # Get the packages from the command line options
+diff --git a/python/src/_pakfiremodule.c b/python/src/_pakfiremodule.c
+index 4c94c5a..c208634 100644
+--- a/python/src/_pakfiremodule.c
++++ b/python/src/_pakfiremodule.c
+@@ -18,9 +18,14 @@
+ # #
+ #############################################################################*/
+
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
+ #include <Python.h>
+
+ #include <locale.h>
++#include <sched.h>
+ #include <sys/personality.h>
+
+ #include "capabilities.h"
+@@ -43,6 +48,7 @@ static PyMethodDef pakfireModuleMethods[] = {
+ {"set_capabilities", (PyCFunction)set_capabilities, METH_VARARGS, NULL},
+ {"personality", (PyCFunction)_personality, METH_VARARGS, NULL},
+ {"sync", (PyCFunction)_sync, METH_NOARGS, NULL},
++ {"unshare", (PyCFunction)_unshare, METH_VARARGS, NULL},
+ { NULL, NULL, 0, NULL }
+ };
+
+@@ -275,6 +281,13 @@ void init_pakfire(void) {
+ PyDict_SetItemString(d, "PERSONALITY_LINUX", Py_BuildValue("i", PER_LINUX));
+ PyDict_SetItemString(d, "PERSONALITY_LINUX32", Py_BuildValue("i", PER_LINUX32));
+
++ // Namespace stuff
++ PyDict_SetItemString(d, "SCHED_CLONE_NEWIPC", Py_BuildValue("i", CLONE_NEWIPC));
++ PyDict_SetItemString(d, "SCHED_CLONE_NEWPID", Py_BuildValue("i", CLONE_NEWPID));
++ PyDict_SetItemString(d, "SCHED_CLONE_NEWNET", Py_BuildValue("i", CLONE_NEWNET));
++ PyDict_SetItemString(d, "SCHED_CLONE_NEWNS", Py_BuildValue("i", CLONE_NEWNS));
++ PyDict_SetItemString(d, "SCHED_CLONE_NEWUTS", Py_BuildValue("i", CLONE_NEWUTS));
++
+ // Add constants for relations
+ PyDict_SetItemString(d, "REL_EQ", Py_BuildValue("i", REL_EQ));
+ PyDict_SetItemString(d, "REL_LT", Py_BuildValue("i", REL_LT));
+diff --git a/python/src/util.c b/python/src/util.c
+index ed555f5..acea90a 100644
+--- a/python/src/util.c
++++ b/python/src/util.c
+@@ -18,11 +18,18 @@
+ # #
+ #############################################################################*/
+
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
+ #include <Python.h>
+
++#include <errno.h>
++#include <sched.h>
+ #include <sys/personality.h>
+ #include <unistd.h>
+
++#include "config.h"
+ #include "util.h"
+
+ PyObject *_personality(PyObject *self, PyObject *args) {
+@@ -52,6 +59,21 @@ PyObject *_sync(PyObject *self, PyObject *args) {
+ Py_RETURN_NONE;
+ }
+
++PyObject *_unshare(PyObject *self, PyObject *args) {
++ int flags = 0;
++
++ if (!PyArg_ParseTuple(args, "i", &flags)) {
++ return NULL;
++ }
++
++ int ret = unshare(flags);
++ if (ret < 0) {
++ return PyErr_SetFromErrno(PyExc_RuntimeError);
++ }
++
++ return Py_BuildValue("i", ret);
++}
++
+ PyObject *version_compare(PyObject *self, PyObject *args) {
+ Pool *pool;
+ const char *evr1, *evr2;
+diff --git a/python/src/util.h b/python/src/util.h
+index 6ed9d14..0322d1c 100644
+--- a/python/src/util.h
++++ b/python/src/util.h
+@@ -27,6 +27,7 @@
+
+ extern PyObject *_personality(PyObject *self, PyObject *args);
+ extern PyObject *_sync(PyObject *self, PyObject *args);
++extern PyObject *_unshare(PyObject *self, PyObject *args);
+ extern PyObject *version_compare(PyObject *self, PyObject *args);
+
+ #endif
+--
+1.8.1.4
+