github.com/tompreston/snapd@v0.0.0-20210817193607-954edfcb9611/cmd/libsnap-confine-private/mount-opt-test.c (about) 1 /* 2 * Copyright (C) 2016 Canonical Ltd 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 3 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 * 16 */ 17 18 #include "mount-opt.h" 19 #include "mount-opt.c" 20 21 #include <errno.h> 22 #include <sys/mount.h> 23 24 #include <glib.h> 25 26 static void test_sc_mount_opt2str(void) 27 { 28 char buf[1000] = { 0 }; 29 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, 0), ==, ""); 30 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_RDONLY), ==, "ro"); 31 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_NOSUID), ==, 32 "nosuid"); 33 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_NODEV), ==, 34 "nodev"); 35 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_NOEXEC), ==, 36 "noexec"); 37 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_SYNCHRONOUS), ==, 38 "sync"); 39 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_REMOUNT), ==, 40 "remount"); 41 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_MANDLOCK), ==, 42 "mand"); 43 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_DIRSYNC), ==, 44 "dirsync"); 45 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_NOATIME), ==, 46 "noatime"); 47 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_NODIRATIME), ==, 48 "nodiratime"); 49 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_BIND), ==, "bind"); 50 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_REC | MS_BIND), ==, 51 "rbind"); 52 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_MOVE), ==, "move"); 53 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_SILENT), ==, 54 "silent"); 55 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_POSIXACL), ==, 56 "acl"); 57 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_UNBINDABLE), ==, 58 "unbindable"); 59 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_PRIVATE), ==, 60 "private"); 61 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_REC | MS_PRIVATE), 62 ==, "rprivate"); 63 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_SLAVE), ==, 64 "slave"); 65 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_REC | MS_SLAVE), 66 ==, "rslave"); 67 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_SHARED), ==, 68 "shared"); 69 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_REC | MS_SHARED), 70 ==, "rshared"); 71 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_RELATIME), ==, 72 "relatime"); 73 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_KERNMOUNT), ==, 74 "kernmount"); 75 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_I_VERSION), ==, 76 "iversion"); 77 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_STRICTATIME), ==, 78 "strictatime"); 79 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_LAZYTIME), ==, 80 "lazytime"); 81 // MS_NOSEC is not defined in userspace 82 // MS_BORN is not defined in userspace 83 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_ACTIVE), ==, 84 "active"); 85 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, MS_NOUSER), ==, 86 "nouser"); 87 g_assert_cmpstr(sc_mount_opt2str(buf, sizeof buf, 0x300), ==, "0x300"); 88 // random compositions do work 89 g_assert_cmpstr(sc_mount_opt2str 90 (buf, sizeof buf, MS_RDONLY | MS_NOEXEC | MS_BIND), ==, 91 "ro,noexec,bind"); 92 } 93 94 static void test_sc_mount_cmd(void) 95 { 96 char cmd[10000] = { 0 }; 97 98 // Typical mount 99 sc_mount_cmd(cmd, sizeof cmd, "/dev/sda3", "/mnt", "ext4", MS_RDONLY, 100 NULL); 101 g_assert_cmpstr(cmd, ==, "mount -t ext4 -o ro /dev/sda3 /mnt"); 102 103 // Bind mount 104 sc_mount_cmd(cmd, sizeof cmd, "/source", "/target", NULL, MS_BIND, 105 NULL); 106 g_assert_cmpstr(cmd, ==, "mount --bind /source /target"); 107 108 // + recursive 109 sc_mount_cmd(cmd, sizeof cmd, "/source", "/target", NULL, 110 MS_BIND | MS_REC, NULL); 111 g_assert_cmpstr(cmd, ==, "mount --rbind /source /target"); 112 113 // Shared subtree mount 114 sc_mount_cmd(cmd, sizeof cmd, "/place", "none", NULL, MS_SHARED, NULL); 115 g_assert_cmpstr(cmd, ==, "mount --make-shared /place"); 116 117 sc_mount_cmd(cmd, sizeof cmd, "/place", "none", NULL, MS_SLAVE, NULL); 118 g_assert_cmpstr(cmd, ==, "mount --make-slave /place"); 119 120 sc_mount_cmd(cmd, sizeof cmd, "/place", "none", NULL, MS_PRIVATE, NULL); 121 g_assert_cmpstr(cmd, ==, "mount --make-private /place"); 122 123 sc_mount_cmd(cmd, sizeof cmd, "/place", "none", NULL, MS_UNBINDABLE, 124 NULL); 125 g_assert_cmpstr(cmd, ==, "mount --make-unbindable /place"); 126 127 // + recursive 128 sc_mount_cmd(cmd, sizeof cmd, "/place", "none", NULL, 129 MS_SHARED | MS_REC, NULL); 130 g_assert_cmpstr(cmd, ==, "mount --make-rshared /place"); 131 132 sc_mount_cmd(cmd, sizeof cmd, "/place", "none", NULL, MS_SLAVE | MS_REC, 133 NULL); 134 g_assert_cmpstr(cmd, ==, "mount --make-rslave /place"); 135 136 sc_mount_cmd(cmd, sizeof cmd, "/place", "none", NULL, 137 MS_PRIVATE | MS_REC, NULL); 138 g_assert_cmpstr(cmd, ==, "mount --make-rprivate /place"); 139 140 sc_mount_cmd(cmd, sizeof cmd, "/place", "none", NULL, 141 MS_UNBINDABLE | MS_REC, NULL); 142 g_assert_cmpstr(cmd, ==, "mount --make-runbindable /place"); 143 144 // Move 145 sc_mount_cmd(cmd, sizeof cmd, "/from", "/to", NULL, MS_MOVE, NULL); 146 g_assert_cmpstr(cmd, ==, "mount --move /from /to"); 147 148 // Monster (invalid but let's format it) 149 char from[PATH_MAX] = { 0 }; 150 char to[PATH_MAX] = { 0 }; 151 for (int i = 1; i < PATH_MAX - 1; ++i) { 152 from[i] = 'a'; 153 to[i] = 'b'; 154 } 155 from[0] = '/'; 156 to[0] = '/'; 157 from[PATH_MAX - 1] = 0; 158 to[PATH_MAX - 1] = 0; 159 int opts = MS_BIND | MS_MOVE | MS_SHARED | MS_SLAVE | MS_PRIVATE | 160 MS_UNBINDABLE | MS_REC | MS_RDONLY | MS_NOSUID | MS_NODEV | 161 MS_NOEXEC | MS_SYNCHRONOUS | MS_REMOUNT | MS_MANDLOCK | MS_DIRSYNC | 162 MS_NOATIME | MS_NODIRATIME | MS_BIND | MS_SILENT | MS_POSIXACL | 163 MS_RELATIME | MS_KERNMOUNT | MS_I_VERSION | MS_STRICTATIME | 164 MS_LAZYTIME; 165 const char *fstype = "fstype"; 166 sc_mount_cmd(cmd, sizeof cmd, from, to, fstype, opts, NULL); 167 const char *expected = 168 "mount -t fstype " 169 "--rbind --move --make-rshared --make-rslave --make-rprivate --make-runbindable " 170 "-o ro,nosuid,nodev,noexec,sync,remount,mand,dirsync,noatime,nodiratime,silent," 171 "acl,relatime,kernmount,iversion,strictatime,lazytime " 172 "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " 173 "/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; 174 g_assert_cmpstr(cmd, ==, expected); 175 } 176 177 static void test_sc_umount_cmd(void) 178 { 179 char cmd[1000] = { 0 }; 180 181 // Typical umount 182 sc_umount_cmd(cmd, sizeof cmd, "/mnt/foo", 0); 183 g_assert_cmpstr(cmd, ==, "umount /mnt/foo"); 184 185 // Force 186 sc_umount_cmd(cmd, sizeof cmd, "/mnt/foo", MNT_FORCE); 187 g_assert_cmpstr(cmd, ==, "umount --force /mnt/foo"); 188 189 // Detach 190 sc_umount_cmd(cmd, sizeof cmd, "/mnt/foo", MNT_DETACH); 191 g_assert_cmpstr(cmd, ==, "umount --lazy /mnt/foo"); 192 193 // Expire 194 sc_umount_cmd(cmd, sizeof cmd, "/mnt/foo", MNT_EXPIRE); 195 g_assert_cmpstr(cmd, ==, "umount --expire /mnt/foo"); 196 197 // O_NOFOLLOW variant for umount 198 sc_umount_cmd(cmd, sizeof cmd, "/mnt/foo", UMOUNT_NOFOLLOW); 199 g_assert_cmpstr(cmd, ==, "umount --no-follow /mnt/foo"); 200 201 // Everything at once 202 sc_umount_cmd(cmd, sizeof cmd, "/mnt/foo", 203 MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW); 204 g_assert_cmpstr(cmd, ==, 205 "umount --force --lazy --expire --no-follow /mnt/foo"); 206 } 207 208 static bool broken_mount(struct sc_fault_state *state, void *ptr) 209 { 210 errno = EACCES; 211 return true; 212 } 213 214 static void test_sc_do_mount(gconstpointer snap_debug) 215 { 216 if (g_test_subprocess()) { 217 sc_break("mount", broken_mount); 218 if (GPOINTER_TO_INT(snap_debug) == 1) { 219 g_assert_true(g_setenv 220 ("SNAP_CONFINE_DEBUG", "1", true)); 221 } 222 sc_do_mount("/foo", "/bar", "ext4", MS_RDONLY, NULL); 223 224 g_test_message("expected sc_do_mount not to return"); 225 sc_reset_faults(); 226 g_test_fail(); 227 return; 228 } 229 g_test_trap_subprocess(NULL, 0, 0); 230 g_test_trap_assert_failed(); 231 if (GPOINTER_TO_INT(snap_debug) == 0) { 232 g_test_trap_assert_stderr 233 ("cannot perform operation: mount -t ext4 -o ro /foo /bar: Permission denied\n"); 234 } else { 235 /* with snap_debug the debug output hides the actual mount commands *but* 236 * they are still shown if there was an error 237 */ 238 g_test_trap_assert_stderr 239 ("DEBUG: performing operation: (disabled) use debug build to see details\n" 240 "cannot perform operation: mount -t ext4 -o ro /foo /bar: Permission denied\n"); 241 } 242 } 243 244 static bool broken_umount(struct sc_fault_state *state, void *ptr) 245 { 246 errno = EACCES; 247 return true; 248 } 249 250 static void test_sc_do_umount(gconstpointer snap_debug) 251 { 252 if (g_test_subprocess()) { 253 sc_break("umount", broken_umount); 254 if (GPOINTER_TO_INT(snap_debug) == 1) { 255 g_assert_true(g_setenv 256 ("SNAP_CONFINE_DEBUG", "1", true)); 257 } 258 sc_do_umount("/foo", MNT_DETACH); 259 260 g_test_message("expected sc_do_umount not to return"); 261 sc_reset_faults(); 262 g_test_fail(); 263 return; 264 } 265 g_test_trap_subprocess(NULL, 0, 0); 266 g_test_trap_assert_failed(); 267 if (GPOINTER_TO_INT(snap_debug) == 0) { 268 g_test_trap_assert_stderr 269 ("cannot perform operation: umount --lazy /foo: Permission denied\n"); 270 } else { 271 /* with snap_debug the debug output hides the actual mount commands *but* 272 * they are still shown if there was an error 273 */ 274 g_test_trap_assert_stderr 275 ("DEBUG: performing operation: (disabled) use debug build to see details\n" 276 "cannot perform operation: umount --lazy /foo: Permission denied\n"); 277 } 278 } 279 280 static bool missing_mount(struct sc_fault_state *state, void *ptr) 281 { 282 errno = ENOENT; 283 return true; 284 } 285 286 static void test_sc_do_optional_mount_missing(void) 287 { 288 sc_break("mount", missing_mount); 289 bool ok = sc_do_optional_mount("/foo", "/bar", "ext4", MS_RDONLY, NULL); 290 g_assert_false(ok); 291 sc_reset_faults(); 292 } 293 294 static void test_sc_do_optional_mount_failure(gconstpointer snap_debug) 295 { 296 if (g_test_subprocess()) { 297 sc_break("mount", broken_mount); 298 if (GPOINTER_TO_INT(snap_debug) == 1) { 299 g_assert_true(g_setenv 300 ("SNAP_CONFINE_DEBUG", "1", true)); 301 } 302 (void)sc_do_optional_mount("/foo", "/bar", "ext4", MS_RDONLY, 303 NULL); 304 305 g_test_message("expected sc_do_mount not to return"); 306 sc_reset_faults(); 307 g_test_fail(); 308 return; 309 } 310 g_test_trap_subprocess(NULL, 0, 0); 311 g_test_trap_assert_failed(); 312 if (GPOINTER_TO_INT(snap_debug) == 0) { 313 g_test_trap_assert_stderr 314 ("cannot perform operation: mount -t ext4 -o ro /foo /bar: Permission denied\n"); 315 } else { 316 /* with snap_debug the debug output hides the actual mount commands *but* 317 * they are still shown if there was an error 318 */ 319 g_test_trap_assert_stderr 320 ("DEBUG: performing operation: (disabled) use debug build to see details\n" 321 "cannot perform operation: mount -t ext4 -o ro /foo /bar: Permission denied\n"); 322 } 323 } 324 325 static void __attribute__((constructor)) init(void) 326 { 327 g_test_add_func("/mount/sc_mount_opt2str", test_sc_mount_opt2str); 328 g_test_add_func("/mount/sc_mount_cmd", test_sc_mount_cmd); 329 g_test_add_func("/mount/sc_umount_cmd", test_sc_umount_cmd); 330 g_test_add_data_func("/mount/sc_do_mount", GINT_TO_POINTER(0), 331 test_sc_do_mount); 332 g_test_add_data_func("/mount/sc_do_umount", GINT_TO_POINTER(0), 333 test_sc_do_umount); 334 g_test_add_data_func("/mount/sc_do_mount_with_debug", 335 GINT_TO_POINTER(1), test_sc_do_mount); 336 g_test_add_data_func("/mount/sc_do_umount_with_debug", 337 GINT_TO_POINTER(1), test_sc_do_umount); 338 g_test_add_func("/mount/sc_do_optional_mount_missing", 339 test_sc_do_optional_mount_missing); 340 g_test_add_data_func("/mount/sc_do_optional_mount_failure", 341 GINT_TO_POINTER(0), 342 test_sc_do_optional_mount_failure); 343 g_test_add_data_func("/mount/sc_do_optional_mount_failure_with_debug", 344 GINT_TO_POINTER(1), 345 test_sc_do_optional_mount_failure); 346 }