-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
-