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  }