Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'vfs-6.16-rc1.selftests' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs selftests updates from Christian Brauner:
"This contains various cleanups, fixes, and extensions for out
filesystem selftests"

* tag 'vfs-6.16-rc1.selftests' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
selftests/fs/mount-notify: add a test variant running inside userns
selftests/filesystems: create setup_userns() helper
selftests/filesystems: create get_unique_mnt_id() helper
selftests/fs/mount-notify: build with tools include dir
selftests/mount_settattr: remove duplicate syscall definitions
selftests/pidfd: move syscall definitions into wrappers.h
selftests/fs/statmount: build with tools include dir
selftests/filesystems: move wrapper.h out of overlayfs subdir
selftests/mount_settattr: ensure that ext4 filesystem can be created
selftests/mount_settattr: add missing STATX_MNT_ID_UNIQUE define
selftests/mount_settattr: don't define sys_open_tree() twice

+1317 -250
+274
tools/include/uapi/linux/fanotify.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 + #ifndef _UAPI_LINUX_FANOTIFY_H 3 + #define _UAPI_LINUX_FANOTIFY_H 4 + 5 + #include <linux/types.h> 6 + 7 + /* the following events that user-space can register for */ 8 + #define FAN_ACCESS 0x00000001 /* File was accessed */ 9 + #define FAN_MODIFY 0x00000002 /* File was modified */ 10 + #define FAN_ATTRIB 0x00000004 /* Metadata changed */ 11 + #define FAN_CLOSE_WRITE 0x00000008 /* Writable file closed */ 12 + #define FAN_CLOSE_NOWRITE 0x00000010 /* Unwritable file closed */ 13 + #define FAN_OPEN 0x00000020 /* File was opened */ 14 + #define FAN_MOVED_FROM 0x00000040 /* File was moved from X */ 15 + #define FAN_MOVED_TO 0x00000080 /* File was moved to Y */ 16 + #define FAN_CREATE 0x00000100 /* Subfile was created */ 17 + #define FAN_DELETE 0x00000200 /* Subfile was deleted */ 18 + #define FAN_DELETE_SELF 0x00000400 /* Self was deleted */ 19 + #define FAN_MOVE_SELF 0x00000800 /* Self was moved */ 20 + #define FAN_OPEN_EXEC 0x00001000 /* File was opened for exec */ 21 + 22 + #define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ 23 + #define FAN_FS_ERROR 0x00008000 /* Filesystem error */ 24 + 25 + #define FAN_OPEN_PERM 0x00010000 /* File open in perm check */ 26 + #define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */ 27 + #define FAN_OPEN_EXEC_PERM 0x00040000 /* File open/exec in perm check */ 28 + /* #define FAN_DIR_MODIFY 0x00080000 */ /* Deprecated (reserved) */ 29 + 30 + #define FAN_PRE_ACCESS 0x00100000 /* Pre-content access hook */ 31 + #define FAN_MNT_ATTACH 0x01000000 /* Mount was attached */ 32 + #define FAN_MNT_DETACH 0x02000000 /* Mount was detached */ 33 + 34 + #define FAN_EVENT_ON_CHILD 0x08000000 /* Interested in child events */ 35 + 36 + #define FAN_RENAME 0x10000000 /* File was renamed */ 37 + 38 + #define FAN_ONDIR 0x40000000 /* Event occurred against dir */ 39 + 40 + /* helper events */ 41 + #define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */ 42 + #define FAN_MOVE (FAN_MOVED_FROM | FAN_MOVED_TO) /* moves */ 43 + 44 + /* flags used for fanotify_init() */ 45 + #define FAN_CLOEXEC 0x00000001 46 + #define FAN_NONBLOCK 0x00000002 47 + 48 + /* These are NOT bitwise flags. Both bits are used together. */ 49 + #define FAN_CLASS_NOTIF 0x00000000 50 + #define FAN_CLASS_CONTENT 0x00000004 51 + #define FAN_CLASS_PRE_CONTENT 0x00000008 52 + 53 + /* Deprecated - do not use this in programs and do not add new flags here! */ 54 + #define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \ 55 + FAN_CLASS_PRE_CONTENT) 56 + 57 + #define FAN_UNLIMITED_QUEUE 0x00000010 58 + #define FAN_UNLIMITED_MARKS 0x00000020 59 + #define FAN_ENABLE_AUDIT 0x00000040 60 + 61 + /* Flags to determine fanotify event format */ 62 + #define FAN_REPORT_PIDFD 0x00000080 /* Report pidfd for event->pid */ 63 + #define FAN_REPORT_TID 0x00000100 /* event->pid is thread id */ 64 + #define FAN_REPORT_FID 0x00000200 /* Report unique file id */ 65 + #define FAN_REPORT_DIR_FID 0x00000400 /* Report unique directory id */ 66 + #define FAN_REPORT_NAME 0x00000800 /* Report events with name */ 67 + #define FAN_REPORT_TARGET_FID 0x00001000 /* Report dirent target id */ 68 + #define FAN_REPORT_FD_ERROR 0x00002000 /* event->fd can report error */ 69 + #define FAN_REPORT_MNT 0x00004000 /* Report mount events */ 70 + 71 + /* Convenience macro - FAN_REPORT_NAME requires FAN_REPORT_DIR_FID */ 72 + #define FAN_REPORT_DFID_NAME (FAN_REPORT_DIR_FID | FAN_REPORT_NAME) 73 + /* Convenience macro - FAN_REPORT_TARGET_FID requires all other FID flags */ 74 + #define FAN_REPORT_DFID_NAME_TARGET (FAN_REPORT_DFID_NAME | \ 75 + FAN_REPORT_FID | FAN_REPORT_TARGET_FID) 76 + 77 + /* Deprecated - do not use this in programs and do not add new flags here! */ 78 + #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \ 79 + FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\ 80 + FAN_UNLIMITED_MARKS) 81 + 82 + /* flags used for fanotify_modify_mark() */ 83 + #define FAN_MARK_ADD 0x00000001 84 + #define FAN_MARK_REMOVE 0x00000002 85 + #define FAN_MARK_DONT_FOLLOW 0x00000004 86 + #define FAN_MARK_ONLYDIR 0x00000008 87 + /* FAN_MARK_MOUNT is 0x00000010 */ 88 + #define FAN_MARK_IGNORED_MASK 0x00000020 89 + #define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040 90 + #define FAN_MARK_FLUSH 0x00000080 91 + /* FAN_MARK_FILESYSTEM is 0x00000100 */ 92 + #define FAN_MARK_EVICTABLE 0x00000200 93 + /* This bit is mutually exclusive with FAN_MARK_IGNORED_MASK bit */ 94 + #define FAN_MARK_IGNORE 0x00000400 95 + 96 + /* These are NOT bitwise flags. Both bits can be used togther. */ 97 + #define FAN_MARK_INODE 0x00000000 98 + #define FAN_MARK_MOUNT 0x00000010 99 + #define FAN_MARK_FILESYSTEM 0x00000100 100 + #define FAN_MARK_MNTNS 0x00000110 101 + 102 + /* 103 + * Convenience macro - FAN_MARK_IGNORE requires FAN_MARK_IGNORED_SURV_MODIFY 104 + * for non-inode mark types. 105 + */ 106 + #define FAN_MARK_IGNORE_SURV (FAN_MARK_IGNORE | FAN_MARK_IGNORED_SURV_MODIFY) 107 + 108 + /* Deprecated - do not use this in programs and do not add new flags here! */ 109 + #define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ 110 + FAN_MARK_REMOVE |\ 111 + FAN_MARK_DONT_FOLLOW |\ 112 + FAN_MARK_ONLYDIR |\ 113 + FAN_MARK_MOUNT |\ 114 + FAN_MARK_IGNORED_MASK |\ 115 + FAN_MARK_IGNORED_SURV_MODIFY |\ 116 + FAN_MARK_FLUSH) 117 + 118 + /* Deprecated - do not use this in programs and do not add new flags here! */ 119 + #define FAN_ALL_EVENTS (FAN_ACCESS |\ 120 + FAN_MODIFY |\ 121 + FAN_CLOSE |\ 122 + FAN_OPEN) 123 + 124 + /* 125 + * All events which require a permission response from userspace 126 + */ 127 + /* Deprecated - do not use this in programs and do not add new flags here! */ 128 + #define FAN_ALL_PERM_EVENTS (FAN_OPEN_PERM |\ 129 + FAN_ACCESS_PERM) 130 + 131 + /* Deprecated - do not use this in programs and do not add new flags here! */ 132 + #define FAN_ALL_OUTGOING_EVENTS (FAN_ALL_EVENTS |\ 133 + FAN_ALL_PERM_EVENTS |\ 134 + FAN_Q_OVERFLOW) 135 + 136 + #define FANOTIFY_METADATA_VERSION 3 137 + 138 + struct fanotify_event_metadata { 139 + __u32 event_len; 140 + __u8 vers; 141 + __u8 reserved; 142 + __u16 metadata_len; 143 + __aligned_u64 mask; 144 + __s32 fd; 145 + __s32 pid; 146 + }; 147 + 148 + #define FAN_EVENT_INFO_TYPE_FID 1 149 + #define FAN_EVENT_INFO_TYPE_DFID_NAME 2 150 + #define FAN_EVENT_INFO_TYPE_DFID 3 151 + #define FAN_EVENT_INFO_TYPE_PIDFD 4 152 + #define FAN_EVENT_INFO_TYPE_ERROR 5 153 + #define FAN_EVENT_INFO_TYPE_RANGE 6 154 + #define FAN_EVENT_INFO_TYPE_MNT 7 155 + 156 + /* Special info types for FAN_RENAME */ 157 + #define FAN_EVENT_INFO_TYPE_OLD_DFID_NAME 10 158 + /* Reserved for FAN_EVENT_INFO_TYPE_OLD_DFID 11 */ 159 + #define FAN_EVENT_INFO_TYPE_NEW_DFID_NAME 12 160 + /* Reserved for FAN_EVENT_INFO_TYPE_NEW_DFID 13 */ 161 + 162 + /* Variable length info record following event metadata */ 163 + struct fanotify_event_info_header { 164 + __u8 info_type; 165 + __u8 pad; 166 + __u16 len; 167 + }; 168 + 169 + /* 170 + * Unique file identifier info record. 171 + * This structure is used for records of types FAN_EVENT_INFO_TYPE_FID, 172 + * FAN_EVENT_INFO_TYPE_DFID and FAN_EVENT_INFO_TYPE_DFID_NAME. 173 + * For FAN_EVENT_INFO_TYPE_DFID_NAME there is additionally a null terminated 174 + * name immediately after the file handle. 175 + */ 176 + struct fanotify_event_info_fid { 177 + struct fanotify_event_info_header hdr; 178 + __kernel_fsid_t fsid; 179 + /* 180 + * Following is an opaque struct file_handle that can be passed as 181 + * an argument to open_by_handle_at(2). 182 + */ 183 + unsigned char handle[]; 184 + }; 185 + 186 + /* 187 + * This structure is used for info records of type FAN_EVENT_INFO_TYPE_PIDFD. 188 + * It holds a pidfd for the pid that was responsible for generating an event. 189 + */ 190 + struct fanotify_event_info_pidfd { 191 + struct fanotify_event_info_header hdr; 192 + __s32 pidfd; 193 + }; 194 + 195 + struct fanotify_event_info_error { 196 + struct fanotify_event_info_header hdr; 197 + __s32 error; 198 + __u32 error_count; 199 + }; 200 + 201 + struct fanotify_event_info_range { 202 + struct fanotify_event_info_header hdr; 203 + __u32 pad; 204 + __u64 offset; 205 + __u64 count; 206 + }; 207 + 208 + struct fanotify_event_info_mnt { 209 + struct fanotify_event_info_header hdr; 210 + __u64 mnt_id; 211 + }; 212 + 213 + /* 214 + * User space may need to record additional information about its decision. 215 + * The extra information type records what kind of information is included. 216 + * The default is none. We also define an extra information buffer whose 217 + * size is determined by the extra information type. 218 + * 219 + * If the information type is Audit Rule, then the information following 220 + * is the rule number that triggered the user space decision that 221 + * requires auditing. 222 + */ 223 + 224 + #define FAN_RESPONSE_INFO_NONE 0 225 + #define FAN_RESPONSE_INFO_AUDIT_RULE 1 226 + 227 + struct fanotify_response { 228 + __s32 fd; 229 + __u32 response; 230 + }; 231 + 232 + struct fanotify_response_info_header { 233 + __u8 type; 234 + __u8 pad; 235 + __u16 len; 236 + }; 237 + 238 + struct fanotify_response_info_audit_rule { 239 + struct fanotify_response_info_header hdr; 240 + __u32 rule_number; 241 + __u32 subj_trust; 242 + __u32 obj_trust; 243 + }; 244 + 245 + /* Legit userspace responses to a _PERM event */ 246 + #define FAN_ALLOW 0x01 247 + #define FAN_DENY 0x02 248 + /* errno other than EPERM can specified in upper byte of deny response */ 249 + #define FAN_ERRNO_BITS 8 250 + #define FAN_ERRNO_SHIFT (32 - FAN_ERRNO_BITS) 251 + #define FAN_ERRNO_MASK ((1 << FAN_ERRNO_BITS) - 1) 252 + #define FAN_DENY_ERRNO(err) \ 253 + (FAN_DENY | ((((__u32)(err)) & FAN_ERRNO_MASK) << FAN_ERRNO_SHIFT)) 254 + 255 + #define FAN_AUDIT 0x10 /* Bitmask to create audit record for result */ 256 + #define FAN_INFO 0x20 /* Bitmask to indicate additional information */ 257 + 258 + /* No fd set in event */ 259 + #define FAN_NOFD -1 260 + #define FAN_NOPIDFD FAN_NOFD 261 + #define FAN_EPIDFD -2 262 + 263 + /* Helper functions to deal with fanotify_event_metadata buffers */ 264 + #define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata)) 265 + 266 + #define FAN_EVENT_NEXT(meta, len) ((len) -= (meta)->event_len, \ 267 + (struct fanotify_event_metadata*)(((char *)(meta)) + \ 268 + (meta)->event_len)) 269 + 270 + #define FAN_EVENT_OK(meta, len) ((long)(len) >= (long)FAN_EVENT_METADATA_LEN && \ 271 + (long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && \ 272 + (long)(meta)->event_len <= (long)(len)) 273 + 274 + #endif /* _UAPI_LINUX_FANOTIFY_H */
+235
tools/include/uapi/linux/mount.h
··· 1 + #ifndef _UAPI_LINUX_MOUNT_H 2 + #define _UAPI_LINUX_MOUNT_H 3 + 4 + #include <linux/types.h> 5 + 6 + /* 7 + * These are the fs-independent mount-flags: up to 32 flags are supported 8 + * 9 + * Usage of these is restricted within the kernel to core mount(2) code and 10 + * callers of sys_mount() only. Filesystems should be using the SB_* 11 + * equivalent instead. 12 + */ 13 + #define MS_RDONLY 1 /* Mount read-only */ 14 + #define MS_NOSUID 2 /* Ignore suid and sgid bits */ 15 + #define MS_NODEV 4 /* Disallow access to device special files */ 16 + #define MS_NOEXEC 8 /* Disallow program execution */ 17 + #define MS_SYNCHRONOUS 16 /* Writes are synced at once */ 18 + #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ 19 + #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ 20 + #define MS_DIRSYNC 128 /* Directory modifications are synchronous */ 21 + #define MS_NOSYMFOLLOW 256 /* Do not follow symlinks */ 22 + #define MS_NOATIME 1024 /* Do not update access times. */ 23 + #define MS_NODIRATIME 2048 /* Do not update directory access times */ 24 + #define MS_BIND 4096 25 + #define MS_MOVE 8192 26 + #define MS_REC 16384 27 + #define MS_VERBOSE 32768 /* War is peace. Verbosity is silence. 28 + MS_VERBOSE is deprecated. */ 29 + #define MS_SILENT 32768 30 + #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ 31 + #define MS_UNBINDABLE (1<<17) /* change to unbindable */ 32 + #define MS_PRIVATE (1<<18) /* change to private */ 33 + #define MS_SLAVE (1<<19) /* change to slave */ 34 + #define MS_SHARED (1<<20) /* change to shared */ 35 + #define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */ 36 + #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ 37 + #define MS_I_VERSION (1<<23) /* Update inode I_version field */ 38 + #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ 39 + #define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */ 40 + 41 + /* These sb flags are internal to the kernel */ 42 + #define MS_SUBMOUNT (1<<26) 43 + #define MS_NOREMOTELOCK (1<<27) 44 + #define MS_NOSEC (1<<28) 45 + #define MS_BORN (1<<29) 46 + #define MS_ACTIVE (1<<30) 47 + #define MS_NOUSER (1<<31) 48 + 49 + /* 50 + * Superblock flags that can be altered by MS_REMOUNT 51 + */ 52 + #define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\ 53 + MS_LAZYTIME) 54 + 55 + /* 56 + * Old magic mount flag and mask 57 + */ 58 + #define MS_MGC_VAL 0xC0ED0000 59 + #define MS_MGC_MSK 0xffff0000 60 + 61 + /* 62 + * open_tree() flags. 63 + */ 64 + #define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */ 65 + #define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */ 66 + 67 + /* 68 + * move_mount() flags. 69 + */ 70 + #define MOVE_MOUNT_F_SYMLINKS 0x00000001 /* Follow symlinks on from path */ 71 + #define MOVE_MOUNT_F_AUTOMOUNTS 0x00000002 /* Follow automounts on from path */ 72 + #define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */ 73 + #define MOVE_MOUNT_T_SYMLINKS 0x00000010 /* Follow symlinks on to path */ 74 + #define MOVE_MOUNT_T_AUTOMOUNTS 0x00000020 /* Follow automounts on to path */ 75 + #define MOVE_MOUNT_T_EMPTY_PATH 0x00000040 /* Empty to path permitted */ 76 + #define MOVE_MOUNT_SET_GROUP 0x00000100 /* Set sharing group instead */ 77 + #define MOVE_MOUNT_BENEATH 0x00000200 /* Mount beneath top mount */ 78 + #define MOVE_MOUNT__MASK 0x00000377 79 + 80 + /* 81 + * fsopen() flags. 82 + */ 83 + #define FSOPEN_CLOEXEC 0x00000001 84 + 85 + /* 86 + * fspick() flags. 87 + */ 88 + #define FSPICK_CLOEXEC 0x00000001 89 + #define FSPICK_SYMLINK_NOFOLLOW 0x00000002 90 + #define FSPICK_NO_AUTOMOUNT 0x00000004 91 + #define FSPICK_EMPTY_PATH 0x00000008 92 + 93 + /* 94 + * The type of fsconfig() call made. 95 + */ 96 + enum fsconfig_command { 97 + FSCONFIG_SET_FLAG = 0, /* Set parameter, supplying no value */ 98 + FSCONFIG_SET_STRING = 1, /* Set parameter, supplying a string value */ 99 + FSCONFIG_SET_BINARY = 2, /* Set parameter, supplying a binary blob value */ 100 + FSCONFIG_SET_PATH = 3, /* Set parameter, supplying an object by path */ 101 + FSCONFIG_SET_PATH_EMPTY = 4, /* Set parameter, supplying an object by (empty) path */ 102 + FSCONFIG_SET_FD = 5, /* Set parameter, supplying an object by fd */ 103 + FSCONFIG_CMD_CREATE = 6, /* Create new or reuse existing superblock */ 104 + FSCONFIG_CMD_RECONFIGURE = 7, /* Invoke superblock reconfiguration */ 105 + FSCONFIG_CMD_CREATE_EXCL = 8, /* Create new superblock, fail if reusing existing superblock */ 106 + }; 107 + 108 + /* 109 + * fsmount() flags. 110 + */ 111 + #define FSMOUNT_CLOEXEC 0x00000001 112 + 113 + /* 114 + * Mount attributes. 115 + */ 116 + #define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only */ 117 + #define MOUNT_ATTR_NOSUID 0x00000002 /* Ignore suid and sgid bits */ 118 + #define MOUNT_ATTR_NODEV 0x00000004 /* Disallow access to device special files */ 119 + #define MOUNT_ATTR_NOEXEC 0x00000008 /* Disallow program execution */ 120 + #define MOUNT_ATTR__ATIME 0x00000070 /* Setting on how atime should be updated */ 121 + #define MOUNT_ATTR_RELATIME 0x00000000 /* - Update atime relative to mtime/ctime. */ 122 + #define MOUNT_ATTR_NOATIME 0x00000010 /* - Do not update access times. */ 123 + #define MOUNT_ATTR_STRICTATIME 0x00000020 /* - Always perform atime updates */ 124 + #define MOUNT_ATTR_NODIRATIME 0x00000080 /* Do not update directory access times */ 125 + #define MOUNT_ATTR_IDMAP 0x00100000 /* Idmap mount to @userns_fd in struct mount_attr. */ 126 + #define MOUNT_ATTR_NOSYMFOLLOW 0x00200000 /* Do not follow symlinks */ 127 + 128 + /* 129 + * mount_setattr() 130 + */ 131 + struct mount_attr { 132 + __u64 attr_set; 133 + __u64 attr_clr; 134 + __u64 propagation; 135 + __u64 userns_fd; 136 + }; 137 + 138 + /* List of all mount_attr versions. */ 139 + #define MOUNT_ATTR_SIZE_VER0 32 /* sizeof first published struct */ 140 + 141 + 142 + /* 143 + * Structure for getting mount/superblock/filesystem info with statmount(2). 144 + * 145 + * The interface is similar to statx(2): individual fields or groups can be 146 + * selected with the @mask argument of statmount(). Kernel will set the @mask 147 + * field according to the supported fields. 148 + * 149 + * If string fields are selected, then the caller needs to pass a buffer that 150 + * has space after the fixed part of the structure. Nul terminated strings are 151 + * copied there and offsets relative to @str are stored in the relevant fields. 152 + * If the buffer is too small, then EOVERFLOW is returned. The actually used 153 + * size is returned in @size. 154 + */ 155 + struct statmount { 156 + __u32 size; /* Total size, including strings */ 157 + __u32 mnt_opts; /* [str] Options (comma separated, escaped) */ 158 + __u64 mask; /* What results were written */ 159 + __u32 sb_dev_major; /* Device ID */ 160 + __u32 sb_dev_minor; 161 + __u64 sb_magic; /* ..._SUPER_MAGIC */ 162 + __u32 sb_flags; /* SB_{RDONLY,SYNCHRONOUS,DIRSYNC,LAZYTIME} */ 163 + __u32 fs_type; /* [str] Filesystem type */ 164 + __u64 mnt_id; /* Unique ID of mount */ 165 + __u64 mnt_parent_id; /* Unique ID of parent (for root == mnt_id) */ 166 + __u32 mnt_id_old; /* Reused IDs used in proc/.../mountinfo */ 167 + __u32 mnt_parent_id_old; 168 + __u64 mnt_attr; /* MOUNT_ATTR_... */ 169 + __u64 mnt_propagation; /* MS_{SHARED,SLAVE,PRIVATE,UNBINDABLE} */ 170 + __u64 mnt_peer_group; /* ID of shared peer group */ 171 + __u64 mnt_master; /* Mount receives propagation from this ID */ 172 + __u64 propagate_from; /* Propagation from in current namespace */ 173 + __u32 mnt_root; /* [str] Root of mount relative to root of fs */ 174 + __u32 mnt_point; /* [str] Mountpoint relative to current root */ 175 + __u64 mnt_ns_id; /* ID of the mount namespace */ 176 + __u32 fs_subtype; /* [str] Subtype of fs_type (if any) */ 177 + __u32 sb_source; /* [str] Source string of the mount */ 178 + __u32 opt_num; /* Number of fs options */ 179 + __u32 opt_array; /* [str] Array of nul terminated fs options */ 180 + __u32 opt_sec_num; /* Number of security options */ 181 + __u32 opt_sec_array; /* [str] Array of nul terminated security options */ 182 + __u64 supported_mask; /* Mask flags that this kernel supports */ 183 + __u32 mnt_uidmap_num; /* Number of uid mappings */ 184 + __u32 mnt_uidmap; /* [str] Array of uid mappings (as seen from callers namespace) */ 185 + __u32 mnt_gidmap_num; /* Number of gid mappings */ 186 + __u32 mnt_gidmap; /* [str] Array of gid mappings (as seen from callers namespace) */ 187 + __u64 __spare2[43]; 188 + char str[]; /* Variable size part containing strings */ 189 + }; 190 + 191 + /* 192 + * Structure for passing mount ID and miscellaneous parameters to statmount(2) 193 + * and listmount(2). 194 + * 195 + * For statmount(2) @param represents the request mask. 196 + * For listmount(2) @param represents the last listed mount id (or zero). 197 + */ 198 + struct mnt_id_req { 199 + __u32 size; 200 + __u32 spare; 201 + __u64 mnt_id; 202 + __u64 param; 203 + __u64 mnt_ns_id; 204 + }; 205 + 206 + /* List of all mnt_id_req versions. */ 207 + #define MNT_ID_REQ_SIZE_VER0 24 /* sizeof first published struct */ 208 + #define MNT_ID_REQ_SIZE_VER1 32 /* sizeof second published struct */ 209 + 210 + /* 211 + * @mask bits for statmount(2) 212 + */ 213 + #define STATMOUNT_SB_BASIC 0x00000001U /* Want/got sb_... */ 214 + #define STATMOUNT_MNT_BASIC 0x00000002U /* Want/got mnt_... */ 215 + #define STATMOUNT_PROPAGATE_FROM 0x00000004U /* Want/got propagate_from */ 216 + #define STATMOUNT_MNT_ROOT 0x00000008U /* Want/got mnt_root */ 217 + #define STATMOUNT_MNT_POINT 0x00000010U /* Want/got mnt_point */ 218 + #define STATMOUNT_FS_TYPE 0x00000020U /* Want/got fs_type */ 219 + #define STATMOUNT_MNT_NS_ID 0x00000040U /* Want/got mnt_ns_id */ 220 + #define STATMOUNT_MNT_OPTS 0x00000080U /* Want/got mnt_opts */ 221 + #define STATMOUNT_FS_SUBTYPE 0x00000100U /* Want/got fs_subtype */ 222 + #define STATMOUNT_SB_SOURCE 0x00000200U /* Want/got sb_source */ 223 + #define STATMOUNT_OPT_ARRAY 0x00000400U /* Want/got opt_... */ 224 + #define STATMOUNT_OPT_SEC_ARRAY 0x00000800U /* Want/got opt_sec... */ 225 + #define STATMOUNT_SUPPORTED_MASK 0x00001000U /* Want/got supported mask flags */ 226 + #define STATMOUNT_MNT_UIDMAP 0x00002000U /* Want/got uidmap... */ 227 + #define STATMOUNT_MNT_GIDMAP 0x00004000U /* Want/got gidmap... */ 228 + 229 + /* 230 + * Special @mnt_id values that can be passed to listmount 231 + */ 232 + #define LSMT_ROOT 0xffffffffffffffff /* root mount */ 233 + #define LISTMOUNT_REVERSE (1 << 0) /* List later mounts first */ 234 + 235 + #endif /* _UAPI_LINUX_MOUNT_H */
+45
tools/include/uapi/linux/nsfs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 + #ifndef __LINUX_NSFS_H 3 + #define __LINUX_NSFS_H 4 + 5 + #include <linux/ioctl.h> 6 + #include <linux/types.h> 7 + 8 + #define NSIO 0xb7 9 + 10 + /* Returns a file descriptor that refers to an owning user namespace */ 11 + #define NS_GET_USERNS _IO(NSIO, 0x1) 12 + /* Returns a file descriptor that refers to a parent namespace */ 13 + #define NS_GET_PARENT _IO(NSIO, 0x2) 14 + /* Returns the type of namespace (CLONE_NEW* value) referred to by 15 + file descriptor */ 16 + #define NS_GET_NSTYPE _IO(NSIO, 0x3) 17 + /* Get owner UID (in the caller's user namespace) for a user namespace */ 18 + #define NS_GET_OWNER_UID _IO(NSIO, 0x4) 19 + /* Get the id for a mount namespace */ 20 + #define NS_GET_MNTNS_ID _IOR(NSIO, 0x5, __u64) 21 + /* Translate pid from target pid namespace into the caller's pid namespace. */ 22 + #define NS_GET_PID_FROM_PIDNS _IOR(NSIO, 0x6, int) 23 + /* Return thread-group leader id of pid in the callers pid namespace. */ 24 + #define NS_GET_TGID_FROM_PIDNS _IOR(NSIO, 0x7, int) 25 + /* Translate pid from caller's pid namespace into a target pid namespace. */ 26 + #define NS_GET_PID_IN_PIDNS _IOR(NSIO, 0x8, int) 27 + /* Return thread-group leader id of pid in the target pid namespace. */ 28 + #define NS_GET_TGID_IN_PIDNS _IOR(NSIO, 0x9, int) 29 + 30 + struct mnt_ns_info { 31 + __u32 size; 32 + __u32 nr_mounts; 33 + __u64 mnt_ns_id; 34 + }; 35 + 36 + #define MNT_NS_INFO_SIZE_VER0 16 /* size of first published struct */ 37 + 38 + /* Get information about namespace. */ 39 + #define NS_MNT_GET_INFO _IOR(NSIO, 10, struct mnt_ns_info) 40 + /* Get next namespace. */ 41 + #define NS_MNT_GET_NEXT _IOR(NSIO, 11, struct mnt_ns_info) 42 + /* Get previous namespace. */ 43 + #define NS_MNT_GET_PREV _IOR(NSIO, 12, struct mnt_ns_info) 44 + 45 + #endif /* __LINUX_NSFS_H */
+1
tools/testing/selftests/filesystems/mount-notify/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 /*_test 3 + /*_test_ns
+7 -2
tools/testing/selftests/filesystems/mount-notify/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-or-later 2 2 3 - CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES) 4 - TEST_GEN_PROGS := mount-notify_test 3 + CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES) $(TOOLS_INCLUDES) 4 + LDLIBS += -lcap 5 + 6 + TEST_GEN_PROGS := mount-notify_test mount-notify_test_ns 5 7 6 8 include ../../lib.mk 9 + 10 + $(OUTPUT)/mount-notify_test: ../utils.c 11 + $(OUTPUT)/mount-notify_test_ns: ../utils.c
+8 -30
tools/testing/selftests/filesystems/mount-notify/mount-notify_test.c
··· 8 8 #include <string.h> 9 9 #include <sys/stat.h> 10 10 #include <sys/mount.h> 11 - #include <linux/fanotify.h> 12 11 #include <unistd.h> 13 - #include <sys/fanotify.h> 14 12 #include <sys/syscall.h> 15 13 16 14 #include "../../kselftest_harness.h" 17 15 #include "../statmount/statmount.h" 16 + #include "../utils.h" 18 17 19 - #ifndef FAN_MNT_ATTACH 20 - struct fanotify_event_info_mnt { 21 - struct fanotify_event_info_header hdr; 22 - __u64 mnt_id; 23 - }; 24 - #define FAN_MNT_ATTACH 0x01000000 /* Mount was attached */ 18 + // Needed for linux/fanotify.h 19 + #ifndef __kernel_fsid_t 20 + typedef struct { 21 + int val[2]; 22 + } __kernel_fsid_t; 25 23 #endif 26 24 27 - #ifndef FAN_MNT_DETACH 28 - #define FAN_MNT_DETACH 0x02000000 /* Mount was detached */ 29 - #endif 30 - 31 - #ifndef FAN_REPORT_MNT 32 - #define FAN_REPORT_MNT 0x00004000 /* Report mount events */ 33 - #endif 34 - 35 - #ifndef FAN_MARK_MNTNS 36 - #define FAN_MARK_MNTNS 0x00000110 37 - #endif 38 - 39 - static uint64_t get_mnt_id(struct __test_metadata *const _metadata, 40 - const char *path) 41 - { 42 - struct statx sx; 43 - 44 - ASSERT_EQ(statx(AT_FDCWD, path, 0, STATX_MNT_ID_UNIQUE, &sx), 0); 45 - ASSERT_TRUE(!!(sx.stx_mask & STATX_MNT_ID_UNIQUE)); 46 - return sx.stx_mnt_id; 47 - } 25 + #include <sys/fanotify.h> 48 26 49 27 static const char root_mntpoint_templ[] = "/tmp/mount-notify_test_root.XXXXXX"; 50 28 ··· 72 94 73 95 ASSERT_EQ(mkdir("b", 0700), 0); 74 96 75 - self->root_id = get_mnt_id(_metadata, "/"); 97 + self->root_id = get_unique_mnt_id("/"); 76 98 ASSERT_NE(self->root_id, 0); 77 99 78 100 for (i = 0; i < NUM_FAN_FDS; i++) {
+557
tools/testing/selftests/filesystems/mount-notify/mount-notify_test_ns.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + // Copyright (c) 2025 Miklos Szeredi <miklos@szeredi.hu> 3 + 4 + #define _GNU_SOURCE 5 + #include <fcntl.h> 6 + #include <sched.h> 7 + #include <stdio.h> 8 + #include <string.h> 9 + #include <sys/stat.h> 10 + #include <sys/mount.h> 11 + #include <unistd.h> 12 + #include <sys/syscall.h> 13 + 14 + #include "../../kselftest_harness.h" 15 + #include "../../pidfd/pidfd.h" 16 + #include "../statmount/statmount.h" 17 + #include "../utils.h" 18 + 19 + // Needed for linux/fanotify.h 20 + #ifndef __kernel_fsid_t 21 + typedef struct { 22 + int val[2]; 23 + } __kernel_fsid_t; 24 + #endif 25 + 26 + #include <sys/fanotify.h> 27 + 28 + static const char root_mntpoint_templ[] = "/tmp/mount-notify_test_root.XXXXXX"; 29 + 30 + static const int mark_types[] = { 31 + FAN_MARK_FILESYSTEM, 32 + FAN_MARK_MOUNT, 33 + FAN_MARK_INODE 34 + }; 35 + 36 + static const int mark_cmds[] = { 37 + FAN_MARK_ADD, 38 + FAN_MARK_REMOVE, 39 + FAN_MARK_FLUSH 40 + }; 41 + 42 + #define NUM_FAN_FDS ARRAY_SIZE(mark_cmds) 43 + 44 + FIXTURE(fanotify) { 45 + int fan_fd[NUM_FAN_FDS]; 46 + char buf[256]; 47 + unsigned int rem; 48 + void *next; 49 + char root_mntpoint[sizeof(root_mntpoint_templ)]; 50 + int orig_root; 51 + int orig_ns_fd; 52 + int ns_fd; 53 + uint64_t root_id; 54 + }; 55 + 56 + FIXTURE_SETUP(fanotify) 57 + { 58 + int i, ret; 59 + 60 + self->orig_ns_fd = open("/proc/self/ns/mnt", O_RDONLY); 61 + ASSERT_GE(self->orig_ns_fd, 0); 62 + 63 + ret = setup_userns(); 64 + ASSERT_EQ(ret, 0); 65 + 66 + self->ns_fd = open("/proc/self/ns/mnt", O_RDONLY); 67 + ASSERT_GE(self->ns_fd, 0); 68 + 69 + strcpy(self->root_mntpoint, root_mntpoint_templ); 70 + ASSERT_NE(mkdtemp(self->root_mntpoint), NULL); 71 + 72 + self->orig_root = open("/", O_PATH | O_CLOEXEC); 73 + ASSERT_GE(self->orig_root, 0); 74 + 75 + ASSERT_EQ(mount("tmpfs", self->root_mntpoint, "tmpfs", 0, NULL), 0); 76 + 77 + ASSERT_EQ(chroot(self->root_mntpoint), 0); 78 + 79 + ASSERT_EQ(chdir("/"), 0); 80 + 81 + ASSERT_EQ(mkdir("a", 0700), 0); 82 + 83 + ASSERT_EQ(mkdir("b", 0700), 0); 84 + 85 + self->root_id = get_unique_mnt_id("/"); 86 + ASSERT_NE(self->root_id, 0); 87 + 88 + for (i = 0; i < NUM_FAN_FDS; i++) { 89 + int fan_fd = fanotify_init(FAN_REPORT_FID, 0); 90 + // Verify that watching tmpfs mounted inside userns is allowed 91 + ret = fanotify_mark(fan_fd, FAN_MARK_ADD | mark_types[i], 92 + FAN_OPEN, AT_FDCWD, "/"); 93 + ASSERT_EQ(ret, 0); 94 + // ...but watching entire orig root filesystem is not allowed 95 + ret = fanotify_mark(fan_fd, FAN_MARK_ADD | FAN_MARK_FILESYSTEM, 96 + FAN_OPEN, self->orig_root, "."); 97 + ASSERT_NE(ret, 0); 98 + close(fan_fd); 99 + 100 + self->fan_fd[i] = fanotify_init(FAN_REPORT_MNT | FAN_NONBLOCK, 101 + 0); 102 + ASSERT_GE(self->fan_fd[i], 0); 103 + // Verify that watching mntns where group was created is allowed 104 + ret = fanotify_mark(self->fan_fd[i], FAN_MARK_ADD | 105 + FAN_MARK_MNTNS, 106 + FAN_MNT_ATTACH | FAN_MNT_DETACH, 107 + self->ns_fd, NULL); 108 + ASSERT_EQ(ret, 0); 109 + // ...but watching orig mntns is not allowed 110 + ret = fanotify_mark(self->fan_fd[i], FAN_MARK_ADD | 111 + FAN_MARK_MNTNS, 112 + FAN_MNT_ATTACH | FAN_MNT_DETACH, 113 + self->orig_ns_fd, NULL); 114 + ASSERT_NE(ret, 0); 115 + // On fd[0] we do an extra ADD that changes nothing. 116 + // On fd[1]/fd[2] we REMOVE/FLUSH which removes the mark. 117 + ret = fanotify_mark(self->fan_fd[i], mark_cmds[i] | 118 + FAN_MARK_MNTNS, 119 + FAN_MNT_ATTACH | FAN_MNT_DETACH, 120 + self->ns_fd, NULL); 121 + ASSERT_EQ(ret, 0); 122 + } 123 + 124 + self->rem = 0; 125 + } 126 + 127 + FIXTURE_TEARDOWN(fanotify) 128 + { 129 + int i; 130 + 131 + ASSERT_EQ(self->rem, 0); 132 + for (i = 0; i < NUM_FAN_FDS; i++) 133 + close(self->fan_fd[i]); 134 + 135 + ASSERT_EQ(fchdir(self->orig_root), 0); 136 + 137 + ASSERT_EQ(chroot("."), 0); 138 + 139 + EXPECT_EQ(umount2(self->root_mntpoint, MNT_DETACH), 0); 140 + EXPECT_EQ(chdir(self->root_mntpoint), 0); 141 + EXPECT_EQ(chdir("/"), 0); 142 + EXPECT_EQ(rmdir(self->root_mntpoint), 0); 143 + } 144 + 145 + static uint64_t expect_notify(struct __test_metadata *const _metadata, 146 + FIXTURE_DATA(fanotify) *self, 147 + uint64_t *mask) 148 + { 149 + struct fanotify_event_metadata *meta; 150 + struct fanotify_event_info_mnt *mnt; 151 + unsigned int thislen; 152 + 153 + if (!self->rem) { 154 + ssize_t len; 155 + int i; 156 + 157 + for (i = NUM_FAN_FDS - 1; i >= 0; i--) { 158 + len = read(self->fan_fd[i], self->buf, 159 + sizeof(self->buf)); 160 + if (i > 0) { 161 + // Groups 1,2 should get EAGAIN 162 + ASSERT_EQ(len, -1); 163 + ASSERT_EQ(errno, EAGAIN); 164 + } else { 165 + // Group 0 should get events 166 + ASSERT_GT(len, 0); 167 + } 168 + } 169 + 170 + self->rem = len; 171 + self->next = (void *) self->buf; 172 + } 173 + 174 + meta = self->next; 175 + ASSERT_TRUE(FAN_EVENT_OK(meta, self->rem)); 176 + 177 + thislen = meta->event_len; 178 + self->rem -= thislen; 179 + self->next += thislen; 180 + 181 + *mask = meta->mask; 182 + thislen -= sizeof(*meta); 183 + 184 + mnt = ((void *) meta) + meta->event_len - thislen; 185 + 186 + ASSERT_EQ(thislen, sizeof(*mnt)); 187 + 188 + return mnt->mnt_id; 189 + } 190 + 191 + static void expect_notify_n(struct __test_metadata *const _metadata, 192 + FIXTURE_DATA(fanotify) *self, 193 + unsigned int n, uint64_t mask[], uint64_t mnts[]) 194 + { 195 + unsigned int i; 196 + 197 + for (i = 0; i < n; i++) 198 + mnts[i] = expect_notify(_metadata, self, &mask[i]); 199 + } 200 + 201 + static uint64_t expect_notify_mask(struct __test_metadata *const _metadata, 202 + FIXTURE_DATA(fanotify) *self, 203 + uint64_t expect_mask) 204 + { 205 + uint64_t mntid, mask; 206 + 207 + mntid = expect_notify(_metadata, self, &mask); 208 + ASSERT_EQ(expect_mask, mask); 209 + 210 + return mntid; 211 + } 212 + 213 + 214 + static void expect_notify_mask_n(struct __test_metadata *const _metadata, 215 + FIXTURE_DATA(fanotify) *self, 216 + uint64_t mask, unsigned int n, uint64_t mnts[]) 217 + { 218 + unsigned int i; 219 + 220 + for (i = 0; i < n; i++) 221 + mnts[i] = expect_notify_mask(_metadata, self, mask); 222 + } 223 + 224 + static void verify_mount_ids(struct __test_metadata *const _metadata, 225 + const uint64_t list1[], const uint64_t list2[], 226 + size_t num) 227 + { 228 + unsigned int i, j; 229 + 230 + // Check that neither list has any duplicates 231 + for (i = 0; i < num; i++) { 232 + for (j = 0; j < num; j++) { 233 + if (i != j) { 234 + ASSERT_NE(list1[i], list1[j]); 235 + ASSERT_NE(list2[i], list2[j]); 236 + } 237 + } 238 + } 239 + // Check that all list1 memebers can be found in list2. Together with 240 + // the above it means that the list1 and list2 represent the same sets. 241 + for (i = 0; i < num; i++) { 242 + for (j = 0; j < num; j++) { 243 + if (list1[i] == list2[j]) 244 + break; 245 + } 246 + ASSERT_NE(j, num); 247 + } 248 + } 249 + 250 + static void check_mounted(struct __test_metadata *const _metadata, 251 + const uint64_t mnts[], size_t num) 252 + { 253 + ssize_t ret; 254 + uint64_t *list; 255 + 256 + list = malloc((num + 1) * sizeof(list[0])); 257 + ASSERT_NE(list, NULL); 258 + 259 + ret = listmount(LSMT_ROOT, 0, 0, list, num + 1, 0); 260 + ASSERT_EQ(ret, num); 261 + 262 + verify_mount_ids(_metadata, mnts, list, num); 263 + 264 + free(list); 265 + } 266 + 267 + static void setup_mount_tree(struct __test_metadata *const _metadata, 268 + int log2_num) 269 + { 270 + int ret, i; 271 + 272 + ret = mount("", "/", NULL, MS_SHARED, NULL); 273 + ASSERT_EQ(ret, 0); 274 + 275 + for (i = 0; i < log2_num; i++) { 276 + ret = mount("/", "/", NULL, MS_BIND, NULL); 277 + ASSERT_EQ(ret, 0); 278 + } 279 + } 280 + 281 + TEST_F(fanotify, bind) 282 + { 283 + int ret; 284 + uint64_t mnts[2] = { self->root_id }; 285 + 286 + ret = mount("/", "/", NULL, MS_BIND, NULL); 287 + ASSERT_EQ(ret, 0); 288 + 289 + mnts[1] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH); 290 + ASSERT_NE(mnts[0], mnts[1]); 291 + 292 + check_mounted(_metadata, mnts, 2); 293 + 294 + // Cleanup 295 + uint64_t detach_id; 296 + ret = umount("/"); 297 + ASSERT_EQ(ret, 0); 298 + 299 + detach_id = expect_notify_mask(_metadata, self, FAN_MNT_DETACH); 300 + ASSERT_EQ(detach_id, mnts[1]); 301 + 302 + check_mounted(_metadata, mnts, 1); 303 + } 304 + 305 + TEST_F(fanotify, move) 306 + { 307 + int ret; 308 + uint64_t mnts[2] = { self->root_id }; 309 + uint64_t move_id; 310 + 311 + ret = mount("/", "/a", NULL, MS_BIND, NULL); 312 + ASSERT_EQ(ret, 0); 313 + 314 + mnts[1] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH); 315 + ASSERT_NE(mnts[0], mnts[1]); 316 + 317 + check_mounted(_metadata, mnts, 2); 318 + 319 + ret = move_mount(AT_FDCWD, "/a", AT_FDCWD, "/b", 0); 320 + ASSERT_EQ(ret, 0); 321 + 322 + move_id = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH | FAN_MNT_DETACH); 323 + ASSERT_EQ(move_id, mnts[1]); 324 + 325 + // Cleanup 326 + ret = umount("/b"); 327 + ASSERT_EQ(ret, 0); 328 + 329 + check_mounted(_metadata, mnts, 1); 330 + } 331 + 332 + TEST_F(fanotify, propagate) 333 + { 334 + const unsigned int log2_num = 4; 335 + const unsigned int num = (1 << log2_num); 336 + uint64_t mnts[num]; 337 + 338 + setup_mount_tree(_metadata, log2_num); 339 + 340 + expect_notify_mask_n(_metadata, self, FAN_MNT_ATTACH, num - 1, mnts + 1); 341 + 342 + mnts[0] = self->root_id; 343 + check_mounted(_metadata, mnts, num); 344 + 345 + // Cleanup 346 + int ret; 347 + uint64_t mnts2[num]; 348 + ret = umount2("/", MNT_DETACH); 349 + ASSERT_EQ(ret, 0); 350 + 351 + ret = mount("", "/", NULL, MS_PRIVATE, NULL); 352 + ASSERT_EQ(ret, 0); 353 + 354 + mnts2[0] = self->root_id; 355 + expect_notify_mask_n(_metadata, self, FAN_MNT_DETACH, num - 1, mnts2 + 1); 356 + verify_mount_ids(_metadata, mnts, mnts2, num); 357 + 358 + check_mounted(_metadata, mnts, 1); 359 + } 360 + 361 + TEST_F(fanotify, fsmount) 362 + { 363 + int ret, fs, mnt; 364 + uint64_t mnts[2] = { self->root_id }; 365 + 366 + fs = fsopen("tmpfs", 0); 367 + ASSERT_GE(fs, 0); 368 + 369 + ret = fsconfig(fs, FSCONFIG_CMD_CREATE, 0, 0, 0); 370 + ASSERT_EQ(ret, 0); 371 + 372 + mnt = fsmount(fs, 0, 0); 373 + ASSERT_GE(mnt, 0); 374 + 375 + close(fs); 376 + 377 + ret = move_mount(mnt, "", AT_FDCWD, "/a", MOVE_MOUNT_F_EMPTY_PATH); 378 + ASSERT_EQ(ret, 0); 379 + 380 + close(mnt); 381 + 382 + mnts[1] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH); 383 + ASSERT_NE(mnts[0], mnts[1]); 384 + 385 + check_mounted(_metadata, mnts, 2); 386 + 387 + // Cleanup 388 + uint64_t detach_id; 389 + ret = umount("/a"); 390 + ASSERT_EQ(ret, 0); 391 + 392 + detach_id = expect_notify_mask(_metadata, self, FAN_MNT_DETACH); 393 + ASSERT_EQ(detach_id, mnts[1]); 394 + 395 + check_mounted(_metadata, mnts, 1); 396 + } 397 + 398 + TEST_F(fanotify, reparent) 399 + { 400 + uint64_t mnts[6] = { self->root_id }; 401 + uint64_t dmnts[3]; 402 + uint64_t masks[3]; 403 + unsigned int i; 404 + int ret; 405 + 406 + // Create setup with a[1] -> b[2] propagation 407 + ret = mount("/", "/a", NULL, MS_BIND, NULL); 408 + ASSERT_EQ(ret, 0); 409 + 410 + ret = mount("", "/a", NULL, MS_SHARED, NULL); 411 + ASSERT_EQ(ret, 0); 412 + 413 + ret = mount("/a", "/b", NULL, MS_BIND, NULL); 414 + ASSERT_EQ(ret, 0); 415 + 416 + ret = mount("", "/b", NULL, MS_SLAVE, NULL); 417 + ASSERT_EQ(ret, 0); 418 + 419 + expect_notify_mask_n(_metadata, self, FAN_MNT_ATTACH, 2, mnts + 1); 420 + 421 + check_mounted(_metadata, mnts, 3); 422 + 423 + // Mount on a[3], which is propagated to b[4] 424 + ret = mount("/", "/a", NULL, MS_BIND, NULL); 425 + ASSERT_EQ(ret, 0); 426 + 427 + expect_notify_mask_n(_metadata, self, FAN_MNT_ATTACH, 2, mnts + 3); 428 + 429 + check_mounted(_metadata, mnts, 5); 430 + 431 + // Mount on b[5], not propagated 432 + ret = mount("/", "/b", NULL, MS_BIND, NULL); 433 + ASSERT_EQ(ret, 0); 434 + 435 + mnts[5] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH); 436 + 437 + check_mounted(_metadata, mnts, 6); 438 + 439 + // Umount a[3], which is propagated to b[4], but not b[5] 440 + // This will result in b[5] "falling" on b[2] 441 + ret = umount("/a"); 442 + ASSERT_EQ(ret, 0); 443 + 444 + expect_notify_n(_metadata, self, 3, masks, dmnts); 445 + verify_mount_ids(_metadata, mnts + 3, dmnts, 3); 446 + 447 + for (i = 0; i < 3; i++) { 448 + if (dmnts[i] == mnts[5]) { 449 + ASSERT_EQ(masks[i], FAN_MNT_ATTACH | FAN_MNT_DETACH); 450 + } else { 451 + ASSERT_EQ(masks[i], FAN_MNT_DETACH); 452 + } 453 + } 454 + 455 + mnts[3] = mnts[5]; 456 + check_mounted(_metadata, mnts, 4); 457 + 458 + // Cleanup 459 + ret = umount("/b"); 460 + ASSERT_EQ(ret, 0); 461 + 462 + ret = umount("/a"); 463 + ASSERT_EQ(ret, 0); 464 + 465 + ret = umount("/b"); 466 + ASSERT_EQ(ret, 0); 467 + 468 + expect_notify_mask_n(_metadata, self, FAN_MNT_DETACH, 3, dmnts); 469 + verify_mount_ids(_metadata, mnts + 1, dmnts, 3); 470 + 471 + check_mounted(_metadata, mnts, 1); 472 + } 473 + 474 + TEST_F(fanotify, rmdir) 475 + { 476 + uint64_t mnts[3] = { self->root_id }; 477 + int ret; 478 + 479 + ret = mount("/", "/a", NULL, MS_BIND, NULL); 480 + ASSERT_EQ(ret, 0); 481 + 482 + ret = mount("/", "/a/b", NULL, MS_BIND, NULL); 483 + ASSERT_EQ(ret, 0); 484 + 485 + expect_notify_mask_n(_metadata, self, FAN_MNT_ATTACH, 2, mnts + 1); 486 + 487 + check_mounted(_metadata, mnts, 3); 488 + 489 + ret = chdir("/a"); 490 + ASSERT_EQ(ret, 0); 491 + 492 + ret = fork(); 493 + ASSERT_GE(ret, 0); 494 + 495 + if (ret == 0) { 496 + chdir("/"); 497 + unshare(CLONE_NEWNS); 498 + mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL); 499 + umount2("/a", MNT_DETACH); 500 + // This triggers a detach in the other namespace 501 + rmdir("/a"); 502 + exit(0); 503 + } 504 + wait(NULL); 505 + 506 + expect_notify_mask_n(_metadata, self, FAN_MNT_DETACH, 2, mnts + 1); 507 + check_mounted(_metadata, mnts, 1); 508 + 509 + // Cleanup 510 + ret = chdir("/"); 511 + ASSERT_EQ(ret, 0); 512 + } 513 + 514 + TEST_F(fanotify, pivot_root) 515 + { 516 + uint64_t mnts[3] = { self->root_id }; 517 + uint64_t mnts2[3]; 518 + int ret; 519 + 520 + ret = mount("tmpfs", "/a", "tmpfs", 0, NULL); 521 + ASSERT_EQ(ret, 0); 522 + 523 + mnts[2] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH); 524 + 525 + ret = mkdir("/a/new", 0700); 526 + ASSERT_EQ(ret, 0); 527 + 528 + ret = mkdir("/a/old", 0700); 529 + ASSERT_EQ(ret, 0); 530 + 531 + ret = mount("/a", "/a/new", NULL, MS_BIND, NULL); 532 + ASSERT_EQ(ret, 0); 533 + 534 + mnts[1] = expect_notify_mask(_metadata, self, FAN_MNT_ATTACH); 535 + check_mounted(_metadata, mnts, 3); 536 + 537 + ret = syscall(SYS_pivot_root, "/a/new", "/a/new/old"); 538 + ASSERT_EQ(ret, 0); 539 + 540 + expect_notify_mask_n(_metadata, self, FAN_MNT_ATTACH | FAN_MNT_DETACH, 2, mnts2); 541 + verify_mount_ids(_metadata, mnts, mnts2, 2); 542 + check_mounted(_metadata, mnts, 3); 543 + 544 + // Cleanup 545 + ret = syscall(SYS_pivot_root, "/old", "/old/a/new"); 546 + ASSERT_EQ(ret, 0); 547 + 548 + ret = umount("/a/new"); 549 + ASSERT_EQ(ret, 0); 550 + 551 + ret = umount("/a"); 552 + ASSERT_EQ(ret, 0); 553 + 554 + check_mounted(_metadata, mnts, 1); 555 + } 556 + 557 + TEST_HARNESS_MAIN
+1 -1
tools/testing/selftests/filesystems/overlayfs/Makefile
··· 4 4 CFLAGS += $(KHDR_INCLUDES) 5 5 LDLIBS += -lcap 6 6 7 - LOCAL_HDRS += wrappers.h log.h 7 + LOCAL_HDRS += ../wrappers.h log.h 8 8 9 9 TEST_GEN_PROGS := dev_in_maps 10 10 TEST_GEN_PROGS += set_layers_via_fds
+1 -1
tools/testing/selftests/filesystems/overlayfs/dev_in_maps.c
··· 17 17 18 18 #include "../../kselftest.h" 19 19 #include "log.h" 20 - #include "wrappers.h" 20 + #include "../wrappers.h" 21 21 22 22 static long get_file_dev_and_inode(void *addr, struct statx *stx) 23 23 {
+1 -1
tools/testing/selftests/filesystems/overlayfs/set_layers_via_fds.c
··· 16 16 #include "../../pidfd/pidfd.h" 17 17 #include "log.h" 18 18 #include "../utils.h" 19 - #include "wrappers.h" 19 + #include "../wrappers.h" 20 20 21 21 FIXTURE(set_layers_via_fds) { 22 22 int pidfd;
+45 -1
tools/testing/selftests/filesystems/overlayfs/wrappers.h tools/testing/selftests/filesystems/wrappers.h
··· 9 9 #include <linux/mount.h> 10 10 #include <sys/syscall.h> 11 11 12 + #ifndef STATX_MNT_ID_UNIQUE 13 + #define STATX_MNT_ID_UNIQUE 0x00004000U /* Want/got extended stx_mount_id */ 14 + #endif 15 + 12 16 static inline int sys_fsopen(const char *fsname, unsigned int flags) 13 17 { 14 18 return syscall(__NR_fsopen, fsname, flags); ··· 40 36 #define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */ 41 37 #endif 42 38 39 + #ifndef MOVE_MOUNT_T_EMPTY_PATH 40 + #define MOVE_MOUNT_T_EMPTY_PATH 0x00000040 /* Empty to path permitted */ 41 + #endif 42 + 43 + #ifndef __NR_move_mount 44 + #if defined __alpha__ 45 + #define __NR_move_mount 539 46 + #elif defined _MIPS_SIM 47 + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ 48 + #define __NR_move_mount 4429 49 + #endif 50 + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ 51 + #define __NR_move_mount 6429 52 + #endif 53 + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ 54 + #define __NR_move_mount 5429 55 + #endif 56 + #else 57 + #define __NR_move_mount 429 58 + #endif 59 + #endif 60 + 43 61 static inline int sys_move_mount(int from_dfd, const char *from_pathname, 44 62 int to_dfd, const char *to_pathname, 45 63 unsigned int flags) ··· 79 53 #endif 80 54 81 55 #ifndef AT_RECURSIVE 82 - #define AT_RECURSIVE 0x8000 56 + #define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */ 57 + #endif 58 + 59 + #ifndef __NR_open_tree 60 + #if defined __alpha__ 61 + #define __NR_open_tree 538 62 + #elif defined _MIPS_SIM 63 + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ 64 + #define __NR_open_tree 4428 65 + #endif 66 + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ 67 + #define __NR_open_tree 6428 68 + #endif 69 + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ 70 + #define __NR_open_tree 5428 71 + #endif 72 + #else 73 + #define __NR_open_tree 428 74 + #endif 83 75 #endif 84 76 85 77 static inline int sys_open_tree(int dfd, const char *filename, unsigned int flags)
+5 -1
tools/testing/selftests/filesystems/statmount/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-or-later 2 2 3 - CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES) 3 + CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES) $(TOOLS_INCLUDES) 4 + LDLIBS += -lcap 5 + 4 6 TEST_GEN_PROGS := statmount_test statmount_test_ns listmount_test 5 7 6 8 include ../../lib.mk 9 + 10 + $(OUTPUT)/statmount_test_ns: ../utils.c
+36
tools/testing/selftests/filesystems/statmount/statmount.h
··· 7 7 #include <linux/mount.h> 8 8 #include <asm/unistd.h> 9 9 10 + #ifndef __NR_statmount 11 + #if defined __alpha__ 12 + #define __NR_statmount 567 13 + #elif defined _MIPS_SIM 14 + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ 15 + #define __NR_statmount 4457 16 + #endif 17 + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ 18 + #define __NR_statmount 6457 19 + #endif 20 + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ 21 + #define __NR_statmount 5457 22 + #endif 23 + #else 24 + #define __NR_statmount 457 25 + #endif 26 + #endif 27 + 28 + #ifndef __NR_listmount 29 + #if defined __alpha__ 30 + #define __NR_listmount 568 31 + #elif defined _MIPS_SIM 32 + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ 33 + #define __NR_listmount 4458 34 + #endif 35 + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ 36 + #define __NR_listmount 6458 37 + #endif 38 + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ 39 + #define __NR_listmount 5458 40 + #endif 41 + #else 42 + #define __NR_listmount 458 43 + #endif 44 + #endif 45 + 10 46 static inline int statmount(uint64_t mnt_id, uint64_t mnt_ns_id, uint64_t mask, 11 47 struct statmount *buf, size_t bufsize, 12 48 unsigned int flags)
+5 -81
tools/testing/selftests/filesystems/statmount/statmount_test_ns.c
··· 14 14 #include <linux/stat.h> 15 15 16 16 #include "statmount.h" 17 + #include "../utils.h" 17 18 #include "../../kselftest.h" 18 19 19 20 #define NSID_PASS 0 ··· 79 78 return NSID_PASS; 80 79 } 81 80 82 - static int get_mnt_id(const char *path, uint64_t *mnt_id) 83 - { 84 - struct statx sx; 85 - int ret; 86 - 87 - ret = statx(AT_FDCWD, path, 0, STATX_MNT_ID_UNIQUE, &sx); 88 - if (ret == -1) { 89 - ksft_print_msg("retrieving unique mount ID for %s: %s\n", path, 90 - strerror(errno)); 91 - return NSID_ERROR; 92 - } 93 - 94 - if (!(sx.stx_mask & STATX_MNT_ID_UNIQUE)) { 95 - ksft_print_msg("no unique mount ID available for %s\n", path); 96 - return NSID_ERROR; 97 - } 98 - 99 - *mnt_id = sx.stx_mnt_id; 100 - return NSID_PASS; 101 - } 102 - 103 - static int write_file(const char *path, const char *val) 104 - { 105 - int fd = open(path, O_WRONLY); 106 - size_t len = strlen(val); 107 - int ret; 108 - 109 - if (fd == -1) { 110 - ksft_print_msg("opening %s for write: %s\n", path, strerror(errno)); 111 - return NSID_ERROR; 112 - } 113 - 114 - ret = write(fd, val, len); 115 - if (ret == -1) { 116 - ksft_print_msg("writing to %s: %s\n", path, strerror(errno)); 117 - return NSID_ERROR; 118 - } 119 - if (ret != len) { 120 - ksft_print_msg("short write to %s\n", path); 121 - return NSID_ERROR; 122 - } 123 - 124 - ret = close(fd); 125 - if (ret == -1) { 126 - ksft_print_msg("closing %s\n", path); 127 - return NSID_ERROR; 128 - } 129 - 130 - return NSID_PASS; 131 - } 132 - 133 81 static int setup_namespace(void) 134 82 { 135 - int ret; 136 - char buf[32]; 137 - uid_t uid = getuid(); 138 - gid_t gid = getgid(); 139 - 140 - ret = unshare(CLONE_NEWNS|CLONE_NEWUSER|CLONE_NEWPID); 141 - if (ret == -1) 142 - ksft_exit_fail_msg("unsharing mountns and userns: %s\n", 143 - strerror(errno)); 144 - 145 - sprintf(buf, "0 %d 1", uid); 146 - ret = write_file("/proc/self/uid_map", buf); 147 - if (ret != NSID_PASS) 148 - return ret; 149 - ret = write_file("/proc/self/setgroups", "deny"); 150 - if (ret != NSID_PASS) 151 - return ret; 152 - sprintf(buf, "0 %d 1", gid); 153 - ret = write_file("/proc/self/gid_map", buf); 154 - if (ret != NSID_PASS) 155 - return ret; 156 - 157 - ret = mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL); 158 - if (ret == -1) { 159 - ksft_print_msg("making mount tree private: %s\n", 160 - strerror(errno)); 83 + if (setup_userns() != 0) 161 84 return NSID_ERROR; 162 - } 163 85 164 86 return NSID_PASS; 165 87 } ··· 98 174 if (ret != NSID_PASS) 99 175 return ret; 100 176 101 - ret = get_mnt_id("/", &root_id); 102 - if (ret != NSID_PASS) 103 - return ret; 177 + root_id = get_unique_mnt_id("/"); 178 + if (!root_id) 179 + return NSID_ERROR; 104 180 105 181 ret = statmount(root_id, 0, STATMOUNT_MNT_NS_ID, &sm, sizeof(sm), 0); 106 182 if (ret == -1) {
+88
tools/testing/selftests/filesystems/utils.c
··· 18 18 #include <sys/types.h> 19 19 #include <sys/wait.h> 20 20 #include <sys/xattr.h> 21 + #include <sys/mount.h> 21 22 23 + #include "../kselftest.h" 24 + #include "wrappers.h" 22 25 #include "utils.h" 23 26 24 27 #define MAX_USERNS_LEVEL 32 ··· 450 447 return fret; 451 448 } 452 449 450 + static int write_file(const char *path, const char *val) 451 + { 452 + int fd = open(path, O_WRONLY); 453 + size_t len = strlen(val); 454 + int ret; 455 + 456 + if (fd == -1) { 457 + ksft_print_msg("opening %s for write: %s\n", path, strerror(errno)); 458 + return -1; 459 + } 460 + 461 + ret = write(fd, val, len); 462 + if (ret == -1) { 463 + ksft_print_msg("writing to %s: %s\n", path, strerror(errno)); 464 + return -1; 465 + } 466 + if (ret != len) { 467 + ksft_print_msg("short write to %s\n", path); 468 + return -1; 469 + } 470 + 471 + ret = close(fd); 472 + if (ret == -1) { 473 + ksft_print_msg("closing %s\n", path); 474 + return -1; 475 + } 476 + 477 + return 0; 478 + } 479 + 480 + int setup_userns(void) 481 + { 482 + int ret; 483 + char buf[32]; 484 + uid_t uid = getuid(); 485 + gid_t gid = getgid(); 486 + 487 + ret = unshare(CLONE_NEWNS|CLONE_NEWUSER|CLONE_NEWPID); 488 + if (ret) { 489 + ksft_exit_fail_msg("unsharing mountns and userns: %s\n", 490 + strerror(errno)); 491 + return ret; 492 + } 493 + 494 + sprintf(buf, "0 %d 1", uid); 495 + ret = write_file("/proc/self/uid_map", buf); 496 + if (ret) 497 + return ret; 498 + ret = write_file("/proc/self/setgroups", "deny"); 499 + if (ret) 500 + return ret; 501 + sprintf(buf, "0 %d 1", gid); 502 + ret = write_file("/proc/self/gid_map", buf); 503 + if (ret) 504 + return ret; 505 + 506 + ret = mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL); 507 + if (ret) { 508 + ksft_print_msg("making mount tree private: %s\n", strerror(errno)); 509 + return ret; 510 + } 511 + 512 + return 0; 513 + } 514 + 453 515 /* caps_down - lower all effective caps */ 454 516 int caps_down(void) 455 517 { ··· 566 498 out: 567 499 cap_free(caps); 568 500 return fret; 501 + } 502 + 503 + uint64_t get_unique_mnt_id(const char *path) 504 + { 505 + struct statx sx; 506 + int ret; 507 + 508 + ret = statx(AT_FDCWD, path, 0, STATX_MNT_ID_UNIQUE, &sx); 509 + if (ret == -1) { 510 + ksft_print_msg("retrieving unique mount ID for %s: %s\n", path, 511 + strerror(errno)); 512 + return 0; 513 + } 514 + 515 + if (!(sx.stx_mask & STATX_MNT_ID_UNIQUE)) { 516 + ksft_print_msg("no unique mount ID available for %s\n", path); 517 + return 0; 518 + } 519 + 520 + return sx.stx_mnt_id; 569 521 }
+3
tools/testing/selftests/filesystems/utils.h
··· 27 27 extern int cap_down(cap_value_t down); 28 28 29 29 extern bool switch_ids(uid_t uid, gid_t gid); 30 + extern int setup_userns(void); 30 31 31 32 static inline bool switch_userns(int fd, uid_t uid, gid_t gid, bool drop_caps) 32 33 { ··· 42 41 43 42 return true; 44 43 } 44 + 45 + extern uint64_t get_unique_mnt_id(const char *path); 45 46 46 47 #endif /* __IDMAP_UTILS_H */
+2
tools/testing/selftests/mount_setattr/Makefile
··· 2 2 # Makefile for mount selftests. 3 3 CFLAGS = -g $(KHDR_INCLUDES) -Wall -O2 -pthread 4 4 5 + LOCAL_HDRS += ../filesystems/wrappers.h 6 + 5 7 TEST_GEN_PROGS := mount_setattr_test 6 8 7 9 include ../lib.mk
+2 -59
tools/testing/selftests/mount_setattr/mount_setattr_test.c
··· 20 20 #include <stdarg.h> 21 21 #include <linux/mount.h> 22 22 23 - #include "../filesystems/overlayfs/wrappers.h" 23 + #include "../filesystems/wrappers.h" 24 24 #include "../kselftest_harness.h" 25 25 26 26 #ifndef CLONE_NEWNS ··· 107 107 #endif 108 108 #endif 109 109 110 - #ifndef __NR_open_tree 111 - #if defined __alpha__ 112 - #define __NR_open_tree 538 113 - #elif defined _MIPS_SIM 114 - #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ 115 - #define __NR_open_tree 4428 116 - #endif 117 - #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ 118 - #define __NR_open_tree 6428 119 - #endif 120 - #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ 121 - #define __NR_open_tree 5428 122 - #endif 123 - #elif defined __ia64__ 124 - #define __NR_open_tree (428 + 1024) 125 - #else 126 - #define __NR_open_tree 428 127 - #endif 128 - #endif 129 - 130 - #ifndef __NR_move_mount 131 - #if defined __alpha__ 132 - #define __NR_move_mount 539 133 - #elif defined _MIPS_SIM 134 - #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ 135 - #define __NR_move_mount 4429 136 - #endif 137 - #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ 138 - #define __NR_move_mount 6429 139 - #endif 140 - #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ 141 - #define __NR_move_mount 5429 142 - #endif 143 - #elif defined __ia64__ 144 - #define __NR_move_mount (428 + 1024) 145 - #else 146 - #define __NR_move_mount 429 147 - #endif 148 - #endif 149 - 150 110 #ifndef MOUNT_ATTR_IDMAP 151 111 #define MOUNT_ATTR_IDMAP 0x00100000 152 112 #endif ··· 119 159 struct mount_attr *attr, size_t size) 120 160 { 121 161 return syscall(__NR_mount_setattr, dfd, path, flags, attr, size); 122 - } 123 - 124 - #ifndef OPEN_TREE_CLONE 125 - #define OPEN_TREE_CLONE 1 126 - #endif 127 - 128 - #ifndef OPEN_TREE_CLOEXEC 129 - #define OPEN_TREE_CLOEXEC O_CLOEXEC 130 - #endif 131 - 132 - #ifndef AT_RECURSIVE 133 - #define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */ 134 - #endif 135 - 136 - static inline int sys_open_tree(int dfd, const char *filename, unsigned int flags) 137 - { 138 - return syscall(__NR_open_tree, dfd, filename, flags); 139 162 } 140 163 141 164 static ssize_t write_nointr(int fd, const void *buf, size_t count) ··· 1019 1076 ASSERT_EQ(mkdir("/mnt/D", 0777), 0); 1020 1077 img_fd = openat(-EBADF, "/mnt/C/ext4.img", O_CREAT | O_WRONLY, 0600); 1021 1078 ASSERT_GE(img_fd, 0); 1022 - ASSERT_EQ(ftruncate(img_fd, 1024 * 2048), 0); 1079 + ASSERT_EQ(ftruncate(img_fd, 2147483648 /* 2 GB */), 0); 1023 1080 ASSERT_EQ(system("mkfs.ext4 -q /mnt/C/ext4.img"), 0); 1024 1081 ASSERT_EQ(system("mount -o loop -t ext4 /mnt/C/ext4.img /mnt/D/"), 0); 1025 1082 ASSERT_EQ(close(img_fd), 0);
+1 -73
tools/testing/selftests/pidfd/pidfd_bind_mount.c
··· 15 15 16 16 #include "pidfd.h" 17 17 #include "../kselftest_harness.h" 18 - 19 - #ifndef __NR_open_tree 20 - #if defined __alpha__ 21 - #define __NR_open_tree 538 22 - #elif defined _MIPS_SIM 23 - #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ 24 - #define __NR_open_tree 4428 25 - #endif 26 - #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ 27 - #define __NR_open_tree 6428 28 - #endif 29 - #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ 30 - #define __NR_open_tree 5428 31 - #endif 32 - #elif defined __ia64__ 33 - #define __NR_open_tree (428 + 1024) 34 - #else 35 - #define __NR_open_tree 428 36 - #endif 37 - #endif 38 - 39 - #ifndef __NR_move_mount 40 - #if defined __alpha__ 41 - #define __NR_move_mount 539 42 - #elif defined _MIPS_SIM 43 - #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ 44 - #define __NR_move_mount 4429 45 - #endif 46 - #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ 47 - #define __NR_move_mount 6429 48 - #endif 49 - #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ 50 - #define __NR_move_mount 5429 51 - #endif 52 - #elif defined __ia64__ 53 - #define __NR_move_mount (428 + 1024) 54 - #else 55 - #define __NR_move_mount 429 56 - #endif 57 - #endif 58 - 59 - #ifndef MOVE_MOUNT_F_EMPTY_PATH 60 - #define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */ 61 - #endif 62 - 63 - #ifndef MOVE_MOUNT_F_EMPTY_PATH 64 - #define MOVE_MOUNT_T_EMPTY_PATH 0x00000040 /* Empty to path permitted */ 65 - #endif 66 - 67 - static inline int sys_move_mount(int from_dfd, const char *from_pathname, 68 - int to_dfd, const char *to_pathname, 69 - unsigned int flags) 70 - { 71 - return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, 72 - to_pathname, flags); 73 - } 74 - 75 - #ifndef OPEN_TREE_CLONE 76 - #define OPEN_TREE_CLONE 1 77 - #endif 78 - 79 - #ifndef OPEN_TREE_CLOEXEC 80 - #define OPEN_TREE_CLOEXEC O_CLOEXEC 81 - #endif 82 - 83 - #ifndef AT_RECURSIVE 84 - #define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */ 85 - #endif 86 - 87 - static inline int sys_open_tree(int dfd, const char *filename, unsigned int flags) 88 - { 89 - return syscall(__NR_open_tree, dfd, filename, flags); 90 - } 18 + #include "../filesystems/wrappers.h" 91 19 92 20 FIXTURE(pidfd_bind_mount) { 93 21 char template[PATH_MAX];