forked from canonical/snapd
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ns-support-test.c
154 lines (142 loc) · 4.6 KB
/
ns-support-test.c
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
* Copyright (C) 2016 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ns-support.h"
#include "ns-support.c"
#include "../libsnap-confine-private/cleanup-funcs.h"
#include "../libsnap-confine-private/test-utils.h"
#include <errno.h>
#include <linux/magic.h> // for NSFS_MAGIC
#include <sys/utsname.h>
#include <sys/vfs.h>
#include <glib.h>
#include <glib/gstdio.h>
// Set alternate namespace directory
static void sc_set_ns_dir(const char *dir)
{
sc_ns_dir = dir;
}
// A variant of unsetenv that is compatible with GDestroyNotify
static void my_unsetenv(const char *k)
{
unsetenv(k);
}
// Use temporary directory for namespace groups.
//
// The directory is automatically reset to the real value at the end of the
// test.
static const char *sc_test_use_fake_ns_dir(void)
{
char *ns_dir = NULL;
if (g_test_subprocess()) {
// Check if the environment variable is set. If so then someone is already
// managing the temporary directory and we should not create a new one.
ns_dir = getenv("SNAP_CONFINE_NS_DIR");
g_assert_nonnull(ns_dir);
} else {
ns_dir = g_dir_make_tmp(NULL, NULL);
g_assert_nonnull(ns_dir);
g_test_queue_free(ns_dir);
g_assert_cmpint(setenv("SNAP_CONFINE_NS_DIR", ns_dir, 0), ==,
0);
g_test_queue_destroy((GDestroyNotify) my_unsetenv,
"SNAP_CONFINE_NS_DIR");
g_test_queue_destroy((GDestroyNotify) rm_rf_tmp, ns_dir);
}
g_test_queue_destroy((GDestroyNotify) sc_set_ns_dir, SC_NS_DIR);
sc_set_ns_dir(ns_dir);
return ns_dir;
}
// Check that allocating a namespace group sets up internal data structures to
// safe values.
static void test_sc_alloc_mount_ns(void)
{
struct sc_mount_ns *group = NULL;
group = sc_alloc_mount_ns();
g_test_queue_free(group);
g_assert_nonnull(group);
g_assert_cmpint(group->dir_fd, ==, -1);
g_assert_cmpint(group->pipe_master[0], ==, -1);
g_assert_cmpint(group->pipe_master[1], ==, -1);
g_assert_cmpint(group->pipe_helper[0], ==, -1);
g_assert_cmpint(group->pipe_helper[1], ==, -1);
g_assert_cmpint(group->child, ==, 0);
g_assert_null(group->name);
}
// Initialize a namespace group.
//
// The group is automatically destroyed at the end of the test.
static struct sc_mount_ns *sc_test_open_mount_ns(const char *group_name)
{
// Initialize a namespace group
struct sc_mount_ns *group = NULL;
if (group_name == NULL) {
group_name = "test-group";
}
group = sc_open_mount_ns(group_name);
g_test_queue_destroy((GDestroyNotify) sc_close_mount_ns, group);
// Check if the returned group data looks okay
g_assert_nonnull(group);
g_assert_cmpint(group->dir_fd, !=, -1);
g_assert_cmpint(group->pipe_master[0], ==, -1);
g_assert_cmpint(group->pipe_master[1], ==, -1);
g_assert_cmpint(group->pipe_helper[0], ==, -1);
g_assert_cmpint(group->pipe_helper[1], ==, -1);
g_assert_cmpint(group->child, ==, 0);
g_assert_cmpstr(group->name, ==, group_name);
return group;
}
// Check that initializing a namespace group creates the appropriate
// filesystem structure.
static void test_sc_open_mount_ns(void)
{
const char *ns_dir = sc_test_use_fake_ns_dir();
sc_test_open_mount_ns(NULL);
// Check that the group directory exists
g_assert_true(g_file_test
(ns_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
}
// Sanity check, ensure that the namespace filesystem identifier is what we
// expect, aka NSFS_MAGIC.
static void test_nsfs_fs_id(void)
{
struct utsname uts;
if (uname(&uts) < 0) {
g_test_message("cannot use uname(2)");
g_test_fail();
return;
}
int major, minor;
if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
g_test_message("cannot use sscanf(2) to parse kernel release");
g_test_fail();
return;
}
if (major < 3 || (major == 3 && minor < 19)) {
g_test_skip("this test needs kernel 3.19+");
return;
}
struct statfs buf;
int err = statfs("/proc/self/ns/mnt", &buf);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(buf.f_type, ==, NSFS_MAGIC);
}
static void __attribute__((constructor)) init(void)
{
g_test_add_func("/ns/sc_alloc_mount_ns", test_sc_alloc_mount_ns);
g_test_add_func("/ns/sc_open_mount_ns", test_sc_open_mount_ns);
g_test_add_func("/ns/nsfs_fs_id", test_nsfs_fs_id);
}