]>
Commit | Line | Data |
---|---|---|
3aee6018 FG |
1 | From 590b215c4f5225cfb7fb58d9c56fabd5197bfdac Mon Sep 17 00:00:00 2001 |
2 | From: Christian Brauner <christian.brauner@ubuntu.com> | |
3 | Date: Wed, 25 Jul 2018 19:56:54 +0200 | |
4 | Subject: [PATCH] CVE 2018-6556: verify netns fd in lxc-user-nic | |
5 | MIME-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com> | |
10 | (cherry picked from commit c1cf54ebf251fdbad1e971679614e81649f1c032) | |
11 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
12 | --- | |
13 | src/lxc/utils.h | 5 +++++ | |
14 | src/lxc/cmd/lxc_user_nic.c | 35 ++++++++++++++++++++++++++++++++--- | |
15 | src/lxc/utils.c | 12 ++++++++++++ | |
16 | 3 files changed, 49 insertions(+), 3 deletions(-) | |
17 | ||
18 | diff --git a/src/lxc/utils.h b/src/lxc/utils.h | |
19 | index ed486853..4dff26ae 100644 | |
20 | --- a/src/lxc/utils.h | |
21 | +++ b/src/lxc/utils.h | |
22 | @@ -95,6 +95,10 @@ | |
23 | #define CGROUP2_SUPER_MAGIC 0x63677270 | |
24 | #endif | |
25 | ||
26 | +#ifndef NSFS_MAGIC | |
27 | +#define NSFS_MAGIC 0x6e736673 | |
28 | +#endif | |
29 | + | |
30 | /* Useful macros */ | |
31 | /* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */ | |
32 | #define LXC_NUMSTRLEN64 21 | |
33 | @@ -580,6 +584,7 @@ extern void *must_realloc(void *orig, size_t sz); | |
34 | /* __typeof__ should be safe to use with all compilers. */ | |
35 | typedef __typeof__(((struct statfs *)NULL)->f_type) fs_type_magic; | |
36 | extern bool has_fs_type(const char *path, fs_type_magic magic_val); | |
37 | +extern bool fhas_fs_type(int fd, fs_type_magic magic_val); | |
38 | extern bool is_fs_type(const struct statfs *fs, fs_type_magic magic_val); | |
39 | extern bool lxc_nic_exists(char *nic); | |
40 | extern int lxc_make_tmpfile(char *template, bool rm); | |
41 | diff --git a/src/lxc/cmd/lxc_user_nic.c b/src/lxc/cmd/lxc_user_nic.c | |
42 | index ec9cd97e..c5beb6c8 100644 | |
43 | --- a/src/lxc/cmd/lxc_user_nic.c | |
44 | +++ b/src/lxc/cmd/lxc_user_nic.c | |
45 | @@ -1179,12 +1179,41 @@ int main(int argc, char *argv[]) | |
46 | exit(EXIT_FAILURE); | |
47 | } | |
48 | } else if (request == LXC_USERNIC_DELETE) { | |
49 | - netns_fd = open(args.pid, O_RDONLY); | |
50 | + char opath[LXC_PROC_PID_FD_LEN]; | |
51 | + | |
52 | + /* Open the path with O_PATH which will not trigger an actual | |
53 | + * open(). Don't report an errno to the caller to not leak | |
54 | + * information whether the path exists or not. | |
55 | + * When stracing setuid is stripped so this is not a concern | |
56 | + * either. | |
57 | + */ | |
58 | + netns_fd = open(args.pid, O_PATH | O_CLOEXEC); | |
59 | if (netns_fd < 0) { | |
60 | - usernic_error("Could not open \"%s\": %s\n", args.pid, | |
61 | - strerror(errno)); | |
62 | + usernic_error("Failed to open \"%s\"\n", args.pid); | |
63 | + exit(EXIT_FAILURE); | |
64 | + } | |
65 | + | |
66 | + if (!fhas_fs_type(netns_fd, NSFS_MAGIC)) { | |
67 | + usernic_error("Path \"%s\" does not refer to a network namespace path\n", args.pid); | |
68 | + close(netns_fd); | |
69 | + exit(EXIT_FAILURE); | |
70 | + } | |
71 | + | |
72 | + ret = snprintf(opath, sizeof(opath), "/proc/self/fd/%d", netns_fd); | |
73 | + if (ret < 0 || (size_t)ret >= sizeof(opath)) { | |
74 | + close(netns_fd); | |
75 | + exit(EXIT_FAILURE); | |
76 | + } | |
77 | + | |
78 | + /* Now get an fd that we can use in setns() calls. */ | |
79 | + ret = open(opath, O_RDONLY | O_CLOEXEC); | |
80 | + if (ret < 0) { | |
81 | + usernic_error("Failed to open \"%s\": %s\n", args.pid, strerror(errno)); | |
82 | + close(netns_fd); | |
83 | exit(EXIT_FAILURE); | |
84 | } | |
85 | + close(netns_fd); | |
86 | + netns_fd = ret; | |
87 | } | |
88 | ||
89 | if (!create_db_dir(LXC_USERNIC_DB)) { | |
90 | diff --git a/src/lxc/utils.c b/src/lxc/utils.c | |
91 | index 9771b900..e6f600f9 100644 | |
92 | --- a/src/lxc/utils.c | |
93 | +++ b/src/lxc/utils.c | |
94 | @@ -2551,6 +2551,18 @@ bool has_fs_type(const char *path, fs_type_magic magic_val) | |
95 | return has_type; | |
96 | } | |
97 | ||
98 | +bool fhas_fs_type(int fd, fs_type_magic magic_val) | |
99 | +{ | |
100 | + int ret; | |
101 | + struct statfs sb; | |
102 | + | |
103 | + ret = fstatfs(fd, &sb); | |
104 | + if (ret < 0) | |
105 | + return false; | |
106 | + | |
107 | + return is_fs_type(&sb, magic_val); | |
108 | +} | |
109 | + | |
110 | bool lxc_nic_exists(char *nic) | |
111 | { | |
112 | #define __LXC_SYS_CLASS_NET_LEN 15 + IFNAMSIZ + 1 | |
113 | -- | |
114 | 2.18.0 | |
115 |