]> git.ipfire.org Git - people/ms/ipfire-3.x.git/blobdiff - pakfire/patches/0004-Create-an-extra-namespace-for-build-environments-and.patch
pakfire: Sync with upstream.
[people/ms/ipfire-3.x.git] / pakfire / patches / 0004-Create-an-extra-namespace-for-build-environments-and.patch
diff --git a/pakfire/patches/0004-Create-an-extra-namespace-for-build-environments-and.patch b/pakfire/patches/0004-Create-an-extra-namespace-for-build-environments-and.patch
new file mode 100644 (file)
index 0000000..fd1eeeb
--- /dev/null
@@ -0,0 +1,271 @@
+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
+