]>
Commit | Line | Data |
---|---|---|
eac44f69 MT |
1 | From 392371f70db6fe3df79a6e2306092857c4615a4b Mon Sep 17 00:00:00 2001 |
2 | From: Michael Tremer <michael.tremer@ipfire.org> | |
3 | Date: Fri, 8 Mar 2013 11:02:18 +0100 | |
4 | Subject: [PATCH 04/19] Create an extra namespace for build environments and | |
5 | private network. | |
6 | ||
7 | Create a python binding for unshare(2) and use this to | |
8 | unshare the IPC and UTS namespace (if the kernel supports that). | |
9 | ||
10 | Also 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 | ||
20 | diff --git a/examples/builder.conf b/examples/builder.conf | |
21 | index 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 | |
37 | diff --git a/python/pakfire/builder.py b/python/pakfire/builder.py | |
38 | index 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 | ||
94 | diff --git a/python/pakfire/cli.py b/python/pakfire/cli.py | |
95 | index 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 | |
171 | diff --git a/python/src/_pakfiremodule.c b/python/src/_pakfiremodule.c | |
172 | index 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)); | |
212 | diff --git a/python/src/util.c b/python/src/util.c | |
213 | index 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; | |
257 | diff --git a/python/src/util.h b/python/src/util.h | |
258 | index 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 | -- | |
270 | 1.8.1.4 | |
271 |