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  }