github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/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_setenv("SNAP_CONFINE_DEBUG", "1", true); 220 } 221 sc_do_mount("/foo", "/bar", "ext4", MS_RDONLY, NULL); 222 223 g_test_message("expected sc_do_mount not to return"); 224 sc_reset_faults(); 225 g_test_fail(); 226 return; 227 } 228 g_test_trap_subprocess(NULL, 0, 0); 229 g_test_trap_assert_failed(); 230 if (GPOINTER_TO_INT(snap_debug) == 0) { 231 g_test_trap_assert_stderr 232 ("cannot perform operation: mount -t ext4 -o ro /foo /bar: Permission denied\n"); 233 } else { 234 /* with snap_debug the debug output hides the actual mount commands *but* 235 * they are still shown if there was an error 236 */ 237 g_test_trap_assert_stderr 238 ("DEBUG: performing operation: (disabled) use debug build to see details\n" 239 "cannot perform operation: mount -t ext4 -o ro /foo /bar: Permission denied\n"); 240 } 241 } 242 243 static bool broken_umount(struct sc_fault_state *state, void *ptr) 244 { 245 errno = EACCES; 246 return true; 247 } 248 249 static void test_sc_do_umount(gconstpointer snap_debug) 250 { 251 if (g_test_subprocess()) { 252 sc_break("umount", broken_umount); 253 if (GPOINTER_TO_INT(snap_debug) == 1) { 254 g_setenv("SNAP_CONFINE_DEBUG", "1", true); 255 } 256 sc_do_umount("/foo", MNT_DETACH); 257 258 g_test_message("expected sc_do_umount not to return"); 259 sc_reset_faults(); 260 g_test_fail(); 261 return; 262 } 263 g_test_trap_subprocess(NULL, 0, 0); 264 g_test_trap_assert_failed(); 265 if (GPOINTER_TO_INT(snap_debug) == 0) { 266 g_test_trap_assert_stderr 267 ("cannot perform operation: umount --lazy /foo: Permission denied\n"); 268 } else { 269 /* with snap_debug the debug output hides the actual mount commands *but* 270 * they are still shown if there was an error 271 */ 272 g_test_trap_assert_stderr 273 ("DEBUG: performing operation: (disabled) use debug build to see details\n" 274 "cannot perform operation: umount --lazy /foo: Permission denied\n"); 275 } 276 } 277 278 static bool missing_mount(struct sc_fault_state *state, void *ptr) 279 { 280 errno = ENOENT; 281 return true; 282 } 283 284 static void test_sc_do_optional_mount_missing(void) 285 { 286 sc_break("mount", missing_mount); 287 bool ok = sc_do_optional_mount("/foo", "/bar", "ext4", MS_RDONLY, NULL); 288 g_assert_false(ok); 289 sc_reset_faults(); 290 } 291 292 static void test_sc_do_optional_mount_failure(gconstpointer snap_debug) 293 { 294 if (g_test_subprocess()) { 295 sc_break("mount", broken_mount); 296 if (GPOINTER_TO_INT(snap_debug) == 1) { 297 g_setenv("SNAP_CONFINE_DEBUG", "1", true); 298 } 299 (void)sc_do_optional_mount("/foo", "/bar", "ext4", MS_RDONLY, 300 NULL); 301 302 g_test_message("expected sc_do_mount not to return"); 303 sc_reset_faults(); 304 g_test_fail(); 305 return; 306 } 307 g_test_trap_subprocess(NULL, 0, 0); 308 g_test_trap_assert_failed(); 309 if (GPOINTER_TO_INT(snap_debug) == 0) { 310 g_test_trap_assert_stderr 311 ("cannot perform operation: mount -t ext4 -o ro /foo /bar: Permission denied\n"); 312 } else { 313 /* with snap_debug the debug output hides the actual mount commands *but* 314 * they are still shown if there was an error 315 */ 316 g_test_trap_assert_stderr 317 ("DEBUG: performing operation: (disabled) use debug build to see details\n" 318 "cannot perform operation: mount -t ext4 -o ro /foo /bar: Permission denied\n"); 319 } 320 } 321 322 static void __attribute__((constructor)) init(void) 323 { 324 g_test_add_func("/mount/sc_mount_opt2str", test_sc_mount_opt2str); 325 g_test_add_func("/mount/sc_mount_cmd", test_sc_mount_cmd); 326 g_test_add_func("/mount/sc_umount_cmd", test_sc_umount_cmd); 327 g_test_add_data_func("/mount/sc_do_mount", GINT_TO_POINTER(0), 328 test_sc_do_mount); 329 g_test_add_data_func("/mount/sc_do_umount", GINT_TO_POINTER(0), 330 test_sc_do_umount); 331 g_test_add_data_func("/mount/sc_do_mount_with_debug", 332 GINT_TO_POINTER(1), test_sc_do_mount); 333 g_test_add_data_func("/mount/sc_do_umount_with_debug", 334 GINT_TO_POINTER(1), test_sc_do_umount); 335 g_test_add_func("/mount/sc_do_optional_mount_missing", 336 test_sc_do_optional_mount_missing); 337 g_test_add_data_func("/mount/sc_do_optional_mount_failure", 338 GINT_TO_POINTER(0), 339 test_sc_do_optional_mount_failure); 340 g_test_add_data_func("/mount/sc_do_optional_mount_failure_with_debug", 341 GINT_TO_POINTER(1), 342 test_sc_do_optional_mount_failure); 343 }