(root)/
strace-6.5/
tests/
mount_setattr.c
       1  /*
       2   * Check decoding of mount_setattr syscall.
       3   *
       4   * Copyright (c) 2019-2021 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  #include "scno.h"
      12  
      13  #include <limits.h>
      14  #include <stdio.h>
      15  #include <stdint.h>
      16  #include <string.h>
      17  #include <unistd.h>
      18  #include <linux/fcntl.h>
      19  #include <linux/mount.h>
      20  
      21  static const char *rcstr;
      22  
      23  static long
      24  k_mount_setattr(const unsigned int dfd,
      25  		const void *fname,
      26  		const unsigned int flags,
      27  		const void *attr,
      28  		kernel_ulong_t size)
      29  {
      30  	const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
      31  	const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
      32  	const kernel_ulong_t arg1 = fill | dfd;
      33  	const kernel_ulong_t arg2 = (uintptr_t) fname;
      34  	const kernel_ulong_t arg3 = fill | flags;
      35  	const kernel_ulong_t arg4 = (uintptr_t) attr;
      36  	const kernel_ulong_t arg5 = size;
      37  	const long rc =
      38  		syscall(__NR_mount_setattr, arg1, arg2, arg3, arg4, arg5, bad);
      39  	rcstr = sprintrc(rc);
      40  	return rc;
      41  }
      42  
      43  int
      44  main(void)
      45  {
      46  	skip_if_unavailable("/proc/self/fd/");
      47  
      48  #ifndef PATH_TRACING
      49  	char *cwd = get_fd_path(get_dir_fd("."));
      50  #endif
      51  	static const char path_full[] = "/dev/full";
      52  	const char *const path = tail_memdup(path_full, sizeof(path_full));
      53  	char *const fname = tail_alloc(PATH_MAX);
      54  	const void *const efault = fname + PATH_MAX;
      55  	const char *const empty = efault - 1;
      56  	fill_memory_ex(fname, PATH_MAX, '0', 10);
      57  	TAIL_ALLOC_OBJECT_CONST_PTR(struct mount_attr, attr);
      58  	struct mount_attr *const attr_big = tail_alloc(sizeof(*attr_big) + 8);
      59  	static const struct strval32 valid_flags =
      60  		{ ARG_STR(AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT|AT_EMPTY_PATH|AT_RECURSIVE) };
      61          const unsigned int dfd = 9;
      62  
      63  	k_mount_setattr(-1, 0, AT_SYMLINK_NOFOLLOW, efault, -1U);
      64  #ifndef PATH_TRACING
      65  	printf("mount_setattr(-1, NULL, %s, %p, %u) = %s\n",
      66  	       "AT_SYMLINK_NOFOLLOW", efault, -1U, rcstr);
      67  #endif
      68  
      69  	k_mount_setattr(-100, fname, 0, attr, MOUNT_ATTR_SIZE_VER0 - 1);
      70  #ifndef PATH_TRACING
      71  	printf("mount_setattr(AT_FDCWD<%s>, \"%.*s\"..., 0, %p, %u) = %s\n",
      72  	       cwd, (int) PATH_MAX - 1, fname,
      73  	       attr, MOUNT_ATTR_SIZE_VER0 - 1, rcstr);
      74  #endif
      75  
      76  	fname[PATH_MAX - 1] = '\0';
      77  	k_mount_setattr(dfd, fname, -1U,
      78  			1 + (void *) attr, MOUNT_ATTR_SIZE_VER0);
      79  	printf("mount_setattr(%d<%s>, \"%s\", %s|%#x, %p, %u) = %s\n",
      80  	       dfd, path, fname, valid_flags.str, ~valid_flags.val,
      81  	       1 + (void *) attr, MOUNT_ATTR_SIZE_VER0, rcstr);
      82  
      83  	k_mount_setattr(-1, efault, valid_flags.val,
      84  			1 + (void *) attr, MOUNT_ATTR_SIZE_VER0 - 1);
      85  #ifndef PATH_TRACING
      86  	printf("mount_setattr(-1, %p, %s, %p, %u) = %s\n",
      87  	       efault, valid_flags.str,
      88  	       1 + (void *) attr, MOUNT_ATTR_SIZE_VER0 - 1, rcstr);
      89  #endif
      90  
      91  	k_mount_setattr(-1, empty, ~valid_flags.val, 0, MOUNT_ATTR_SIZE_VER0);
      92  #ifndef PATH_TRACING
      93  	printf("mount_setattr(-1, \"\", %#x /* AT_??? */, NULL, %u) = %s\n",
      94  	       ~valid_flags.val, MOUNT_ATTR_SIZE_VER0, rcstr);
      95  #endif
      96  
      97  	static const struct strval64 valid_attr =
      98  		{ ARG_STR(MOUNT_ATTR_RDONLY|MOUNT_ATTR_NOSUID|MOUNT_ATTR_NODEV|MOUNT_ATTR_NOEXEC|MOUNT_ATTR_NOATIME|MOUNT_ATTR_STRICTATIME|MOUNT_ATTR_NODIRATIME|MOUNT_ATTR_IDMAP|MOUNT_ATTR_NOSYMFOLLOW) };
      99  
     100  	for (unsigned int j = 0; j < 4; ++j) {
     101  		struct mount_attr *const a = j > 1 ? attr_big : attr;
     102  		const size_t size = j ? sizeof(*a) + 8 : sizeof(*a);
     103  
     104  		if (j == 3)
     105  			memset(attr_big + 1, 0, 8);
     106  		else
     107  			fill_memory(attr_big + 1, 8);
     108  
     109  		a->attr_set = 0xffffffff00000000ULL;
     110  		a->attr_clr = 0;
     111  		a->propagation = MS_UNBINDABLE;
     112  		a->userns_fd = dfd;
     113  
     114  		k_mount_setattr(-1, path, 0, a, size);
     115  		printf("mount_setattr(-1, \"%s\", 0"
     116  		       ", {attr_set=0xffffffff00000000 /* MOUNT_ATTR_??? */"
     117  		       ", attr_clr=0, propagation=%s, userns_fd=%u",
     118  		       path, "MS_UNBINDABLE", dfd);
     119  		if (j == 1)
     120  			printf(", ???");
     121  		if (j == 2) {
     122  			printf(", /* bytes %zu..%zu */ \"\\x80\\x81"
     123  			       "\\x82\\x83\\x84\\x85\\x86\\x87\"",
     124  			       sizeof(*a), sizeof(*a) + 7);
     125  		}
     126  		printf("}, %zu) = %s\n", size, rcstr);
     127  
     128  		a->attr_set = valid_attr.val;
     129  		a->attr_clr = ~valid_attr.val;
     130  		a->propagation = MS_PRIVATE | MS_SHARED;
     131  		a->userns_fd = dfd;
     132  
     133  		k_mount_setattr(-1, path, 0, a, size);
     134  		printf("mount_setattr(-1, \"%s\", 0"
     135  		       ", {attr_set=%s, attr_clr=%#llx /* MOUNT_ATTR_??? */"
     136  		       ", propagation=%#x /* MS_??? */, userns_fd=%d<%s>",
     137  		       path, valid_attr.str, (unsigned long long) a->attr_clr,
     138  		       MS_PRIVATE | MS_SHARED, dfd, path);
     139  		if (j == 1)
     140  			printf(", ???");
     141  		if (j == 2) {
     142  			printf(", /* bytes %zu..%zu */ \"\\x80\\x81"
     143  			       "\\x82\\x83\\x84\\x85\\x86\\x87\"",
     144  			       sizeof(*a), sizeof(*a) + 7);
     145  		}
     146  		printf("}, %zu) = %s\n", size, rcstr);
     147  
     148  		a->attr_set = MOUNT_ATTR_NOSUID;
     149  		a->attr_clr = MOUNT_ATTR_NODEV;
     150  		a->propagation = MS_SLAVE;
     151  		a->userns_fd = 0xdefaced00000000ULL | dfd;
     152  
     153  		k_mount_setattr(dfd, empty, AT_EMPTY_PATH, a, size);
     154  		printf("mount_setattr(%d<%s>, \"\", %s, {attr_set=%s, attr_clr=%s"
     155  		       ", propagation=%s, userns_fd=%llu",
     156  		       dfd, path, "AT_EMPTY_PATH",
     157  		       "MOUNT_ATTR_NOSUID", "MOUNT_ATTR_NODEV", "MS_SLAVE",
     158  		       (unsigned long long) a->userns_fd);
     159  		if (j == 1)
     160  			printf(", ???");
     161  		if (j == 2) {
     162  			printf(", /* bytes %zu..%zu */ \"\\x80\\x81"
     163  			       "\\x82\\x83\\x84\\x85\\x86\\x87\"",
     164  			       sizeof(*a), sizeof(*a) + 7);
     165  		}
     166  		printf("}, %zu) = %s\n", size, rcstr);
     167  	}
     168  
     169  	puts("+++ exited with 0 +++");
     170  	return 0;
     171  }