aboutsummaryrefslogtreecommitdiffstats
path: root/main/lxc/CVE-2018-6556.patch
blob: e2857ea715c6a15b385ab94775ff2212ecdc96a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
From 5eb45428b312e978fb9e294dde16efb14dd9fa4d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner@ubuntu.com>
Date: Wed, 25 Jul 2018 19:56:54 +0200
Subject: [PATCH] CVE 2018-6556: verify netns fd in lxc-user-nic

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>

Patch-Source: https://github.com/lxc/lxc/commit/5eb45428b312e978fb9e294dde16efb14dd9fa4d
              https://github.com/lxc/lxc/commit/f96f5f3c1341e73ee51c8b49bef4ba571c562d8c
---
 src/lxc/lxc_user_nic.c | 35 ++++++++++++++++++++++++++++++++---
 src/lxc/utils.c        | 12 ++++++++++++
 src/lxc/utils.h        |  5 +++++
 3 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/src/lxc/lxc_user_nic.c b/src/lxc/lxc_user_nic.c
index 2a5c3a43a..b7c72abd7 100644
--- a/src/lxc/lxc_user_nic.c
+++ b/src/lxc/lxc_user_nic.c
@@ -1129,12 +1129,41 @@ int main(int argc, char *argv[])
 			exit(EXIT_FAILURE);
 		}
 	} else if (request == LXC_USERNIC_DELETE) {
-		netns_fd = open(args.pid, O_RDONLY);
+		char opath[LXC_PROC_PID_FD_LEN];
+
+		/* Open the path with O_PATH which will not trigger an actual
+		 * open(). Don't report an errno to the caller to not leak
+		 * information whether the path exists or not.
+		 * When stracing setuid is stripped so this is not a concern
+		 * either.
+		 */
+		netns_fd = open(args.pid, O_PATH | O_CLOEXEC);
 		if (netns_fd < 0) {
-			usernic_error("Could not open \"%s\": %s\n", args.pid,
-				      strerror(errno));
+			usernic_error("Failed to open \"%s\"\n", args.pid);
 			exit(EXIT_FAILURE);
 		}
+
+		if (!fhas_fs_type(netns_fd, NSFS_MAGIC)) {
+			usernic_error("Path \"%s\" does not refer to a network namespace path\n", args.pid);
+			close(netns_fd);
+			exit(EXIT_FAILURE);
+		}
+
+		ret = snprintf(opath, sizeof(opath), "/proc/self/fd/%d", netns_fd);
+		if (ret < 0 || (size_t)ret >= sizeof(opath)) {
+			close(netns_fd);
+			exit(EXIT_FAILURE);
+		}
+
+		/* Now get an fd that we can use in setns() calls. */
+		ret = open(opath, O_RDONLY | O_CLOEXEC);
+		if (ret < 0) {
+			usernic_error("Failed to open \"%s\": %s\n", args.pid, strerror(errno));
+			close(netns_fd);
+			exit(EXIT_FAILURE);
+		}
+		close(netns_fd);
+		netns_fd = ret;
 	}
 
 	if (!create_db_dir(LXC_USERNIC_DB)) {
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 10e14b7f3..eb0af8222 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -2319,6 +2319,18 @@ bool has_fs_type(const char *path, fs_type_magic magic_val)
 	return has_type;
 }
 
+bool fhas_fs_type(int fd, fs_type_magic magic_val)
+{
+	int ret;
+	struct statfs sb;
+
+	ret = fstatfs(fd, &sb);
+	if (ret < 0)
+		return false;
+
+	return is_fs_type(&sb, magic_val);
+}
+
 bool lxc_nic_exists(char *nic)
 {
 #define __LXC_SYS_CLASS_NET_LEN 15 + IFNAMSIZ + 1
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index a2bad89db..e4d8519db 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -99,6 +99,17 @@
 #define LXC_NUMSTRLEN64 21
 #define LXC_LINELEN 4096
 #define LXC_IDMAPLEN 4096
+/* /proc/       =    6
+ *                +
+ * <pid-as-str> =   LXC_NUMSTRLEN64
+ *                +
+ * /fd/         =    4
+ *                +
+ * <fd-as-str>  =   LXC_NUMSTRLEN64
+ *                +
+ * \0           =    1
+ */
+#define LXC_PROC_PID_FD_LEN (6 + LXC_NUMSTRLEN64 + 4 + LXC_NUMSTRLEN64 + 1)
 
 /* returns 1 on success, 0 if there were any failures */
 extern int lxc_rmdir_onedev(char *path, const char *exclude);
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index e4d8519db..56fed0a42 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -94,6 +94,10 @@
 #define CGROUP2_SUPER_MAGIC 0x63677270
 #endif
 
+#ifndef NSFS_MAGIC
+#define NSFS_MAGIC 0x6e736673
+#endif
+
 /* Useful macros */
 /* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */
 #define LXC_NUMSTRLEN64 21
@@ -555,6 +559,7 @@ extern void *must_realloc(void *orig, size_t sz);
 /* __typeof__ should be safe to use with all compilers. */
 typedef __typeof__(((struct statfs *)NULL)->f_type) fs_type_magic;
 extern bool has_fs_type(const char *path, fs_type_magic magic_val);
+extern bool fhas_fs_type(int fd, fs_type_magic magic_val);
 extern bool is_fs_type(const struct statfs *fs, fs_type_magic magic_val);
 extern bool lxc_nic_exists(char *nic);
 extern int lxc_make_tmpfile(char *template, bool rm);