]> git.proxmox.com Git - mirror_lxc.git/blob - src/tests/cve-2019-5736.c
Merge pull request #4003 from brauner/2021-10-19.fixes
[mirror_lxc.git] / src / tests / cve-2019-5736.c
1 /* liblxcapi
2 *
3 * Copyright © 2019 Christian Brauner <christian.brauner@ubuntu.com>.
4 * Copyright © 2019 Canonical Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef _GNU_SOURCE
21 #define _GNU_SOURCE 1
22 #endif
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <lxc/lxccontainer.h>
26 #include <signal.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <unistd.h>
33
34 #include "lxctest.h"
35 #include "utils.h"
36
37 #define MYNAME "shortlived"
38
39 static int destroy_container(void)
40 {
41 int status, ret;
42 pid_t pid = fork();
43
44 if (pid < 0) {
45 perror("fork");
46 return -1;
47 }
48 if (pid == 0) {
49 execlp("lxc-destroy", "lxc-destroy", "-f", "-n", MYNAME, NULL);
50 exit(EXIT_FAILURE);
51 }
52 again:
53 ret = waitpid(pid, &status, 0);
54 if (ret == -1) {
55 if (errno == EINTR)
56 goto again;
57 perror("waitpid");
58 return -1;
59 }
60 if (ret != pid)
61 goto again;
62 if (!WIFEXITED(status)) { // did not exit normally
63 fprintf(stderr, "%d: lxc-create exited abnormally\n", __LINE__);
64 return -1;
65 }
66 return WEXITSTATUS(status);
67 }
68
69 static int create_container(void)
70 {
71 int status, ret;
72 pid_t pid = fork();
73
74 if (pid < 0) {
75 perror("fork");
76 return -1;
77 }
78 if (pid == 0) {
79 execlp("lxc-create", "lxc-create", "-t", "busybox", "-n", MYNAME, NULL);
80 exit(EXIT_FAILURE);
81 }
82 again:
83 ret = waitpid(pid, &status, 0);
84 if (ret == -1) {
85 if (errno == EINTR)
86 goto again;
87 perror("waitpid");
88 return -1;
89 }
90 if (ret != pid)
91 goto again;
92 if (!WIFEXITED(status)) { // did not exit normally
93 fprintf(stderr, "%d: lxc-create exited abnormally\n", __LINE__);
94 return -1;
95 }
96 return WEXITSTATUS(status);
97 }
98
99 int main(int argc, char *argv[])
100 {
101 int i;
102 const char *s;
103 bool b;
104 struct lxc_container *c;
105 int ret = EXIT_FAILURE;
106
107 /* test a real container */
108 c = lxc_container_new(MYNAME, NULL);
109 if (!c) {
110 fprintf(stderr, "%d: error creating lxc_container %s\n", __LINE__, MYNAME);
111 goto out;
112 }
113
114 if (c->is_defined(c)) {
115 fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME);
116 goto out;
117 }
118
119 if (create_container() < 0) {
120 fprintf(stderr, "%d: failed to create a container\n", __LINE__);
121 goto out;
122 }
123
124 b = c->is_defined(c);
125 if (!b) {
126 fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME);
127 goto out;
128 }
129
130 s = c->state(c);
131 if (!s || strcmp(s, "STOPPED")) {
132 fprintf(stderr, "%d: %s is in state %s, not in STOPPED.\n", __LINE__, c->name, s ? s : "undefined");
133 goto out;
134 }
135
136 b = c->load_config(c, NULL);
137 if (!b) {
138 fprintf(stderr, "%d: %s failed to read its config\n", __LINE__, c->name);
139 goto out;
140 }
141
142 if (!c->set_config_item(c, "lxc.init.cmd", "echo hello")) {
143 fprintf(stderr, "%d: failed setting lxc.init.cmd\n", __LINE__);
144 goto out;
145 }
146
147 c->want_daemonize(c, true);
148
149 if (setenv("LXC_MEMFD_REXEC", "1", 1)) {
150 fprintf(stderr, "%d: failed to set LXC_MEMFD_REXEC evironment variable\n", __LINE__);
151 goto out;
152 }
153
154 /* Test whether we can start a really short-lived daemonized container. */
155 for (i = 0; i < 10; i++) {
156 if (!c->startl(c, 0, NULL)) {
157 fprintf(stderr, "%d: %s failed to start on %dth iteration\n", __LINE__, c->name, i);
158 goto out;
159 }
160
161 if (!c->wait(c, "STOPPED", 30)) {
162 fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i);
163 goto out;
164 }
165 }
166
167 /* Test whether we can start a really short-lived daemonized container with lxc-init. */
168 for (i = 0; i < 10; i++) {
169 if (!c->startl(c, 1, NULL)) {
170 fprintf(stderr, "%d: %s failed to start on %dth iteration\n", __LINE__, c->name, i);
171 goto out;
172 }
173
174 if (!c->wait(c, "STOPPED", 30)) {
175 fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i);
176 goto out;
177 }
178 }
179
180 c->stop(c);
181
182 fprintf(stderr, "all lxc_container tests passed for %s\n", c->name);
183 ret = EXIT_SUCCESS;
184
185 out:
186 if (c) {
187 c->stop(c);
188 destroy_container();
189 }
190 lxc_container_put(c);
191 exit(ret);
192 }