python-dataproperty: bump version to 0.17.0
[buildroot-gz.git] / package / lxc / 0001-CVE-2017-5985-Ensure-target-netns-is-caller-owned.patch
blob79d19b3afb40787a44144a1b8cb235d2066a22d4
1 From 16af238036a5464ae8f2420ed3af214f0de875f9 Mon Sep 17 00:00:00 2001
2 From: Christian Brauner <christian.brauner@ubuntu.com>
3 Date: Sat, 28 Jan 2017 13:02:34 +0100
4 Subject: [PATCH] CVE-2017-5985: Ensure target netns is caller-owned
6 Before this commit, lxc-user-nic could potentially have been tricked into
7 operating on a network namespace over which the caller did not hold privilege.
9 This commit ensures that the caller is privileged over the network namespace by
10 temporarily dropping privilege.
12 Launchpad: https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/1654676
13 Reported-by: Jann Horn <jannh@google.com>
14 Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
15 Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
16 ---
17 src/lxc/lxc_user_nic.c | 119 ++++++++++++++++++++++++++++++++++++-------------
18 1 file changed, 87 insertions(+), 32 deletions(-)
20 diff --git a/src/lxc/lxc_user_nic.c b/src/lxc/lxc_user_nic.c
21 index 409a53a1..96dc3986 100644
22 --- a/src/lxc/lxc_user_nic.c
23 +++ b/src/lxc/lxc_user_nic.c
24 @@ -50,6 +50,14 @@
25 #include "utils.h"
26 #include "network.h"
28 +#define usernic_debug_stream(stream, format, ...) \
29 + do { \
30 + fprintf(stream, "%s: %d: %s: " format, __FILE__, __LINE__, \
31 + __func__, __VA_ARGS__); \
32 + } while (false)
34 +#define usernic_error(format, ...) usernic_debug_stream(stderr, format, __VA_ARGS__)
36 static void usage(char *me, bool fail)
38 fprintf(stderr, "Usage: %s lxcpath name pid type bridge nicname\n", me);
39 @@ -670,68 +678,115 @@ again:
42 #define VETH_DEF_NAME "eth%d"
44 static int rename_in_ns(int pid, char *oldname, char **newnamep)
46 - int fd = -1, ofd = -1, ret, ifindex = -1;
47 + uid_t ruid, suid, euid;
48 + int fret = -1;
49 + int fd = -1, ifindex = -1, ofd = -1, ret;
50 bool grab_newname = false;
52 ofd = lxc_preserve_ns(getpid(), "net");
53 if (ofd < 0) {
54 - fprintf(stderr, "Failed opening network namespace path for '%d'.", getpid());
55 - return -1;
56 + usernic_error("Failed opening network namespace path for '%d'.", getpid());
57 + return fret;
60 fd = lxc_preserve_ns(pid, "net");
61 if (fd < 0) {
62 - fprintf(stderr, "Failed opening network namespace path for '%d'.", pid);
63 - return -1;
64 + usernic_error("Failed opening network namespace path for '%d'.", pid);
65 + goto do_partial_cleanup;
66 + }
68 + ret = getresuid(&ruid, &euid, &suid);
69 + if (ret < 0) {
70 + usernic_error("Failed to retrieve real, effective, and saved "
71 + "user IDs: %s\n",
72 + strerror(errno));
73 + goto do_partial_cleanup;
74 + }
76 + ret = setns(fd, CLONE_NEWNET);
77 + close(fd);
78 + fd = -1;
79 + if (ret < 0) {
80 + usernic_error("Failed to setns() to the network namespace of "
81 + "the container with PID %d: %s.\n",
82 + pid, strerror(errno));
83 + goto do_partial_cleanup;
86 - if (setns(fd, 0) < 0) {
87 - fprintf(stderr, "setns to container network namespace\n");
88 - goto out_err;
89 + ret = setresuid(ruid, ruid, 0);
90 + if (ret < 0) {
91 + usernic_error("Failed to drop privilege by setting effective "
92 + "user id and real user id to %d, and saved user "
93 + "ID to 0: %s.\n",
94 + ruid, strerror(errno));
95 + // COMMENT(brauner): It's ok to jump to do_full_cleanup here
96 + // since setresuid() will succeed when trying to set real,
97 + // effective, and saved to values they currently have.
98 + goto do_full_cleanup;
100 - close(fd); fd = -1;
102 if (!*newnamep) {
103 grab_newname = true;
104 *newnamep = VETH_DEF_NAME;
105 - if (!(ifindex = if_nametoindex(oldname))) {
106 - fprintf(stderr, "failed to get netdev index\n");
107 - goto out_err;
109 + ifindex = if_nametoindex(oldname);
110 + if (!ifindex) {
111 + usernic_error("Failed to get netdev index: %s.\n", strerror(errno));
112 + goto do_full_cleanup;
115 - if ((ret = lxc_netdev_rename_by_name(oldname, *newnamep)) < 0) {
116 - fprintf(stderr, "Error %d renaming netdev %s to %s in container\n", ret, oldname, *newnamep);
117 - goto out_err;
119 + ret = lxc_netdev_rename_by_name(oldname, *newnamep);
120 + if (ret < 0) {
121 + usernic_error("Error %d renaming netdev %s to %s in container.\n", ret, oldname, *newnamep);
122 + goto do_full_cleanup;
125 if (grab_newname) {
126 - char ifname[IFNAMSIZ], *namep = ifname;
127 + char ifname[IFNAMSIZ];
128 + char *namep = ifname;
130 if (!if_indextoname(ifindex, namep)) {
131 - fprintf(stderr, "Failed to get new netdev name\n");
132 - goto out_err;
133 + usernic_error("Failed to get new netdev name: %s.\n", strerror(errno));
134 + goto do_full_cleanup;
137 *newnamep = strdup(namep);
138 if (!*newnamep)
139 - goto out_err;
140 + goto do_full_cleanup;
142 - if (setns(ofd, 0) < 0) {
143 - fprintf(stderr, "Error returning to original netns\n");
144 - close(ofd);
145 - return -1;
147 + fret = 0;
149 +do_full_cleanup:
150 + ret = setresuid(ruid, euid, suid);
151 + if (ret < 0) {
152 + usernic_error("Failed to restore privilege by setting effective "
153 + "user id to %d, real user id to %d, and saved user "
154 + "ID to %d: %s.\n",
155 + ruid, euid, suid, strerror(errno));
156 + fret = -1;
157 + // COMMENT(brauner): setns() should fail if setresuid() doesn't
158 + // succeed but there's no harm in falling through; keeps the
159 + // code cleaner.
161 - close(ofd);
163 - return 0;
164 + ret = setns(ofd, CLONE_NEWNET);
165 + if (ret < 0) {
166 + usernic_error("Failed to setns() to original network namespace "
167 + "of PID %d: %s.\n",
168 + ofd, strerror(errno));
169 + fret = -1;
172 -out_err:
173 - if (ofd >= 0)
174 - close(ofd);
175 - if (setns(ofd, 0) < 0)
176 - fprintf(stderr, "Error returning to original network namespace\n");
177 +do_partial_cleanup:
178 if (fd >= 0)
179 close(fd);
180 - return -1;
181 + close(ofd);
183 + return fret;
188 2.11.0