]> git.ipfire.org Git - people/ms/ipfire-3.x.git/blame - pakfire/patches/0004-Create-an-extra-namespace-for-build-environments-and.patch
python: Update to 2.7.5.
[people/ms/ipfire-3.x.git] / pakfire / patches / 0004-Create-an-extra-namespace-for-build-environments-and.patch
CommitLineData
eac44f69
MT
1From 392371f70db6fe3df79a6e2306092857c4615a4b Mon Sep 17 00:00:00 2001
2From: Michael Tremer <michael.tremer@ipfire.org>
3Date: Fri, 8 Mar 2013 11:02:18 +0100
4Subject: [PATCH 04/19] Create an extra namespace for build environments and
5 private network.
6
7Create a python binding for unshare(2) and use this to
8unshare the IPC and UTS namespace (if the kernel supports that).
9
10Also add the option to use private networking in the container.
11---
12 examples/builder.conf | 6 ++++++
13 python/pakfire/builder.py | 18 +++++++++++++++++-
14 python/pakfire/cli.py | 40 ++++++++++++++++++++++++++++------------
15 python/src/_pakfiremodule.c | 13 +++++++++++++
16 python/src/util.c | 22 ++++++++++++++++++++++
17 python/src/util.h | 1 +
18 6 files changed, 87 insertions(+), 13 deletions(-)
19
20diff --git a/examples/builder.conf b/examples/builder.conf
21index 128a118..978c7d9 100644
22--- a/examples/builder.conf
23+++ b/examples/builder.conf
24@@ -23,6 +23,12 @@ file = /var/log/pakfire-builder.log
25 # Create loop devices in build environment.
26 #use_loop_devices = true
27
28+# Use private network.
29+# Setting this to true will result in the build
30+# chroot having its own network - i.e. no network connection
31+# to the outside world.
32+#private_network = false
33+
34 [ccache]
35 # Turn on compression to get more files into the cache.
36 #compress = true
37diff --git a/python/pakfire/builder.py b/python/pakfire/builder.py
38index 250a659..5cb00aa 100644
39--- a/python/pakfire/builder.py
40+++ b/python/pakfire/builder.py
41@@ -69,7 +69,7 @@ class BuildEnviron(object):
42 # The version of the kernel this machine is running.
43 kernel_version = os.uname()[2]
44
45- def __init__(self, pakfire, filename=None, distro_name=None, build_id=None, logfile=None, release_build=True):
46+ def __init__(self, pakfire, filename=None, distro_name=None, build_id=None, logfile=None, release_build=True, **kwargs):
47 self.pakfire = pakfire
48
49 # Check if the given pakfire instance is of the correct type.
50@@ -117,6 +117,7 @@ class BuildEnviron(object):
51 "enable_icecream" : self.config.get_bool("builder", "use_icecream", False),
52 "sign_packages" : False,
53 "buildroot_tmpfs" : self.config.get_bool("builder", "use_tmpfs", False),
54+ "private_network" : self.config.get_bool("builder", "private_network", False),
55 }
56
57 # Get ccache settings.
58@@ -130,6 +131,9 @@ class BuildEnviron(object):
59 if self.keyring.get_host_key(secret=True):
60 self.settings["sign_packages"] = True
61
62+ # Add settings from keyword arguments.
63+ self.settings.update(kwargs)
64+
65 # Where do we put the result?
66 self.resultdir = os.path.join(self.pakfire.path, "result")
67
68@@ -164,6 +168,14 @@ class BuildEnviron(object):
69 def start(self):
70 assert not self.pakfire.initialized, "Pakfire has already been initialized"
71
72+ # Unshare namepsace.
73+ # If this fails because the kernel has no support for CLONE_NEWIPC or CLONE_NEWUTS,
74+ # we try to fall back to just set CLONE_NEWNS.
75+ try:
76+ _pakfire.unshare(_pakfire.SCHED_CLONE_NEWNS|_pakfire.SCHED_CLONE_NEWIPC|_pakfire.SCHED_CLONE_NEWUTS)
77+ except RuntimeError, e:
78+ _pakfire.unshare(_pakfire.SCHED_CLONE_NEWNS)
79+
80 # Mount the directories.
81 self._mountall()
82
83@@ -173,6 +185,10 @@ class BuildEnviron(object):
84 # Initialize pakfire instance.
85 self.pakfire.initialize()
86
87+ # Optionally enable private networking.
88+ if self.settings.get("private_network", None):
89+ _pakfire.unshare(_pakfire.SCHED_CLONE_NEWNET)
90+
91 # Populate /dev.
92 self.populate_dev()
93
94diff --git a/python/pakfire/cli.py b/python/pakfire/cli.py
95index 232aad8..a80b397 100644
96--- a/python/pakfire/cli.py
97+++ b/python/pakfire/cli.py
98@@ -543,6 +543,8 @@ class CliBuilder(Cli):
99 help=_("Run a shell after a successful build."))
100 sub_build.add_argument("--no-install-test", action="store_true",
101 help=_("Do not perform the install test."))
102+ sub_build.add_argument("--private-network", action="store_true",
103+ help=_("Disable network in container."))
104
105 def parse_command_shell(self):
106 # Implement the "shell" command.
107@@ -554,6 +556,8 @@ class CliBuilder(Cli):
108
109 sub_shell.add_argument("-m", "--mode", nargs="?", default="development",
110 help=_("Mode to run in. Is either 'release' or 'development' (default)."))
111+ sub_shell.add_argument("--private-network", action="store_true",
112+ help=_("Disable network in container."))
113
114 def parse_command_dist(self):
115 # Implement the "dist" command.
116@@ -580,22 +584,25 @@ class CliBuilder(Cli):
117 else:
118 raise FileNotFoundError, pkg
119
120- # Check whether to enable the install test.
121- install_test = not self.args.no_install_test
122+ # Build argument list.
123+ kwargs = {
124+ "after_shell" : self.args.after_shell,
125+ # Check whether to enable the install test.
126+ "install_test" : not self.args.no_install_test,
127+ "result_dir" : [self.args.resultdir,],
128+ "shell" : True,
129+ }
130
131 if self.args.mode == "release":
132- release_build = True
133+ kwargs["release_build"] = True
134 else:
135- release_build = False
136+ kwargs["release_build"] = False
137+
138+ if self.args.private_network:
139+ kwargs["private_network"] = True
140
141 p = self.create_pakfire()
142- p.build(pkg,
143- install_test=install_test,
144- resultdirs=[self.args.resultdir,],
145- shell=True,
146- after_shell=self.args.after_shell,
147- release_build=release_build,
148- )
149+ p.build(pkg, **kwargs)
150
151 def handle_shell(self):
152 pkg = None
153@@ -617,7 +624,16 @@ class CliBuilder(Cli):
154 release_build = False
155
156 p = self.create_pakfire()
157- p.shell(pkg, release_build=release_build)
158+
159+ kwargs = {
160+ "release_build" : release_build,
161+ }
162+
163+ # Private network
164+ if self.args.private_network:
165+ kwargs["private_network"] = True
166+
167+ p.shell(pkg, **kwargs)
168
169 def handle_dist(self):
170 # Get the packages from the command line options
171diff --git a/python/src/_pakfiremodule.c b/python/src/_pakfiremodule.c
172index 4c94c5a..c208634 100644
173--- a/python/src/_pakfiremodule.c
174+++ b/python/src/_pakfiremodule.c
175@@ -18,9 +18,14 @@
176 # #
177 #############################################################################*/
178
179+#ifndef _GNU_SOURCE
180+#define _GNU_SOURCE
181+#endif
182+
183 #include <Python.h>
184
185 #include <locale.h>
186+#include <sched.h>
187 #include <sys/personality.h>
188
189 #include "capabilities.h"
190@@ -43,6 +48,7 @@ static PyMethodDef pakfireModuleMethods[] = {
191 {"set_capabilities", (PyCFunction)set_capabilities, METH_VARARGS, NULL},
192 {"personality", (PyCFunction)_personality, METH_VARARGS, NULL},
193 {"sync", (PyCFunction)_sync, METH_NOARGS, NULL},
194+ {"unshare", (PyCFunction)_unshare, METH_VARARGS, NULL},
195 { NULL, NULL, 0, NULL }
196 };
197
198@@ -275,6 +281,13 @@ void init_pakfire(void) {
199 PyDict_SetItemString(d, "PERSONALITY_LINUX", Py_BuildValue("i", PER_LINUX));
200 PyDict_SetItemString(d, "PERSONALITY_LINUX32", Py_BuildValue("i", PER_LINUX32));
201
202+ // Namespace stuff
203+ PyDict_SetItemString(d, "SCHED_CLONE_NEWIPC", Py_BuildValue("i", CLONE_NEWIPC));
204+ PyDict_SetItemString(d, "SCHED_CLONE_NEWPID", Py_BuildValue("i", CLONE_NEWPID));
205+ PyDict_SetItemString(d, "SCHED_CLONE_NEWNET", Py_BuildValue("i", CLONE_NEWNET));
206+ PyDict_SetItemString(d, "SCHED_CLONE_NEWNS", Py_BuildValue("i", CLONE_NEWNS));
207+ PyDict_SetItemString(d, "SCHED_CLONE_NEWUTS", Py_BuildValue("i", CLONE_NEWUTS));
208+
209 // Add constants for relations
210 PyDict_SetItemString(d, "REL_EQ", Py_BuildValue("i", REL_EQ));
211 PyDict_SetItemString(d, "REL_LT", Py_BuildValue("i", REL_LT));
212diff --git a/python/src/util.c b/python/src/util.c
213index ed555f5..acea90a 100644
214--- a/python/src/util.c
215+++ b/python/src/util.c
216@@ -18,11 +18,18 @@
217 # #
218 #############################################################################*/
219
220+#ifndef _GNU_SOURCE
221+#define _GNU_SOURCE
222+#endif
223+
224 #include <Python.h>
225
226+#include <errno.h>
227+#include <sched.h>
228 #include <sys/personality.h>
229 #include <unistd.h>
230
231+#include "config.h"
232 #include "util.h"
233
234 PyObject *_personality(PyObject *self, PyObject *args) {
235@@ -52,6 +59,21 @@ PyObject *_sync(PyObject *self, PyObject *args) {
236 Py_RETURN_NONE;
237 }
238
239+PyObject *_unshare(PyObject *self, PyObject *args) {
240+ int flags = 0;
241+
242+ if (!PyArg_ParseTuple(args, "i", &flags)) {
243+ return NULL;
244+ }
245+
246+ int ret = unshare(flags);
247+ if (ret < 0) {
248+ return PyErr_SetFromErrno(PyExc_RuntimeError);
249+ }
250+
251+ return Py_BuildValue("i", ret);
252+}
253+
254 PyObject *version_compare(PyObject *self, PyObject *args) {
255 Pool *pool;
256 const char *evr1, *evr2;
257diff --git a/python/src/util.h b/python/src/util.h
258index 6ed9d14..0322d1c 100644
259--- a/python/src/util.h
260+++ b/python/src/util.h
261@@ -27,6 +27,7 @@
262
263 extern PyObject *_personality(PyObject *self, PyObject *args);
264 extern PyObject *_sync(PyObject *self, PyObject *args);
265+extern PyObject *_unshare(PyObject *self, PyObject *args);
266 extern PyObject *version_compare(PyObject *self, PyObject *args);
267
268 #endif
269--
2701.8.1.4
271