The listmount syscall returns a list of mount IDs under the req.mnt_id.
This is meant to be used in conjunction with statmount(2) in order to
provide a way to iterate and discover mounted file systems.
The statmount syscall returns information about a mount, storing it in
the buffer pointed to by smbuf. The returned buffer is a struct
statmount which is of size bufsize.
Declare a sys_{lis,sta}tmount wrapper in priv_syswrap-linux.h and hook it
for {amd64,arm,arm64,mips64,nanomips,ppc32,ppc64,riscv64,s390x,x86}-linux
using LINXY with PRE and POST handler in syswrap-linux.c
Both syscalls need CAP_SYS_ADMIN, to successfully test.
Resolves: https://bugs.kde.org/show_bug.cgi?id=502968
504936 Add FreeBSD amd64 sysarch subcommands AMD64_SET_TLSBASE and
AMD64_GET_TLSBASE
505228 Wrap linux specific mseal syscall
+502968 Wrap linux specific syscalls 457 (listmount) and 458 (statmount)
To see details of a given bug, visit
https://bugs.kde.org/show_bug.cgi?id=XXXXXX
// Since Linux 6.6
DECL_TEMPLATE(linux, sys_fchmodat2);
+// Since Linux 6.8
+DECL_TEMPLATE(linux, sys_listmount);
+DECL_TEMPLATE(linux, sys_statmount);
+
// Since Linux 6.10
DECL_TEMPLATE(linux, sys_mseal);
LINXY(__NR_cachestat, sys_cachestat), // 451
LINX_(__NR_fchmodat2, sys_fchmodat2), // 452
+ LINXY(__NR_statmount, sys_statmount), // 457
+ LINXY(__NR_listmount, sys_listmount), // 458
LINX_(__NR_mseal, sys_mseal), // 462
};
LINXY(__NR_cachestat, sys_cachestat), // 451
LINX_(__NR_fchmodat2, sys_fchmodat2), // 452
+ LINXY(__NR_statmount, sys_statmount), // 457
+ LINXY(__NR_listmount, sys_listmount), // 458
LINX_(__NR_mseal, sys_mseal), // 462
};
LINXY(__NR_cachestat, sys_cachestat), // 451
LINX_(__NR_fchmodat2, sys_fchmodat2), // 452
+ LINXY(__NR_statmount, sys_statmount), // 457
+ LINXY(__NR_listmount, sys_listmount), // 458
LINX_(__NR_mseal, sys_mseal), // 462
};
SET_STATUS_Failure(VKI_ENOMEM);
}
+PRE(sys_statmount)
+{
+ // int syscall(SYS_statmount, struct mnt_id_req *req,
+ // struct statmount *smbuf, size_t bufsize,
+ // unsigned long flags);
+ FUSE_COMPATIBLE_MAY_BLOCK();
+ PRINT("sys_statmount ( %#" FMT_REGWORD "x, %#" FMT_REGWORD "x, %lu, %#" FMT_REGWORD "x)", ARG1, ARG2, ARG3, ARG4);
+ PRE_REG_READ4(long, "statmount", struct vki_mnt_id_req *, req, struct vki_statmount *, smbuf, vki_size_t, bufsize, unsigned long, flags);
+
+ struct vki_mnt_id_req *req = (struct vki_mnt_id_req *)(Addr)ARG1;
+ if (!ML_(safe_to_deref) ((void *)&req->size, sizeof(vki_size_t)))
+ PRE_MEM_READ("statmount(req)", ARG1, sizeof(struct vki_mnt_id_req));
+ else
+ PRE_MEM_READ("statmount(req)", ARG1, req->size);
+
+ struct vki_statmount *smbuf = (struct vki_statmount *)(Addr)ARG2;
+ if (!ML_(safe_to_deref) ((void *)&smbuf->size, sizeof(struct vki_statmount)))
+ PRE_MEM_WRITE("statmount(smbuf)", ARG2, sizeof(struct vki_statmount));
+ else
+ PRE_MEM_WRITE("statmount(smbuf)", ARG2, ARG3);
+}
+
+POST(sys_statmount)
+{
+ struct vki_statmount *smbuf = (struct vki_statmount *)(Addr)ARG2;
+ POST_MEM_WRITE((Addr)smbuf, smbuf->size);
+}
+
+PRE(sys_listmount)
+{
+ // int syscall(SYS_listmount, struct mnt_id_req *req,
+ // uint64_t *mnt_ids, size_t nr_mnt_ids,
+ // unsigned long flags);
+ FUSE_COMPATIBLE_MAY_BLOCK();
+ PRINT("sys_listmount ( %#" FMT_REGWORD "x, %#" FMT_REGWORD "x, %lu, %#" FMT_REGWORD "x)", ARG1, ARG2, ARG3, ARG4);
+ PRE_REG_READ4(long, "listmount", struct vki_mnt_id_req *, req, vki_uint64_t *, mnt_ids, vki_size_t, nr_mnt_ids, unsigned long, flags);
+
+ struct vki_mnt_id_req *req = (struct vki_mnt_id_req *)(Addr)ARG1;
+ if (!ML_(safe_to_deref) ((void *)&req->size, sizeof(vki_size_t)))
+ PRE_MEM_READ("listmount(req)", ARG1, sizeof(struct vki_mnt_id_req));
+ else
+ PRE_MEM_READ("listmount(req)", ARG1, req->size);
+
+ PRE_MEM_WRITE("listmount(mnt_ids)", ARG2, ARG3 * sizeof(vki_uint64_t));
+}
+
+POST(sys_listmount)
+{
+ if (RES > 0) {
+ POST_MEM_WRITE(ARG2, RES * sizeof(vki_uint64_t));
+ }
+}
+
PRE(sys_syncfs)
{
*flags |= SfMayBlock;
LINXY(__NR_cachestat, sys_cachestat), // 451
LINX_(__NR_fchmodat2, sys_fchmodat2), // 452
+ LINX_(__NR_statmount, sys_statmount), // 457
+ LINX_(__NR_listmount, sys_listmount), // 458
LINX_(__NR_mseal, sys_mseal), // 462
};
LINXY (__NR_cachestat, sys_cachestat),
LINX_ (__NR_fchmodat2, sys_fchmodat2),
LINXY (__NR_userfaultfd, sys_userfaultfd),
+ LINXY (__NR_statmount, sys_statmount),
+ LINXY (__NR_listmount, sys_listmount),
LINX_ (__NR_mseal, sys_mseal),
};
LINX_ (__NR_landlock_restrict_self, sys_landlock_restrict_self),
LINXY (__NR_cachestat, sys_cachestat),
LINX_ (__NR_fchmodat2, sys_fchmodat2),
+ LINXY (__NR_statmount, sys_statmount),
+ LINXY (__NR_listmount, sys_listmount),
LINX_ (__NR_mseal, sys_mseal),
};
LINXY(__NR_cachestat, sys_cachestat), // 451
LINX_ (__NR_fchmodat2, sys_fchmodat2), // 452
+ LINXY (__NR_statmount, sys_statmount), // 457
+ LINXY (__NR_listmount, sys_listmount), // 458
LINX_ (__NR_mseal, sys_mseal), // 462
};
LINXY (__NR_cachestat, sys_cachestat), // 451
LINX_ (__NR_fchmodat2, sys_fchmodat2), // 452
+ LINXY (__NR_statmount, sys_statmount), // 457
+ LINXY (__NR_listmount, sys_listmount), // 458
LINX_ (__NR_mseal, sys_mseal), // 462
};
LINXY(__NR_memfd_secret, sys_memfd_secret), /* 447 */
LINXY(__NR_cachestat, sys_cachestat), /* 451 */
LINX_(__NR_fchmodat2, sys_fchmodat2), /* 452 */
+ LINXY(__NR_statmount, sys_statmount), /* 457 */
+ LINXY(__NR_listmount, sys_listmount), /* 458 */
LINX_(__NR_mseal, sys_mseal), /* 462 */
};
LINXY (__NR_cachestat, sys_cachestat), // 451
LINX_ (__NR_fchmodat2, sys_fchmodat2), // 452
+ LINXY (__NR_statmount, sys_statmount), // 457
+ LINXY (__NR_listmount, sys_listmount), // 458
LINX_ (__NR_mseal, sys_mseal), // 462
};
LINXY(__NR_cachestat, sys_cachestat), // 451
LINX_(__NR_fchmodat2, sys_fchmodat2), // 452
+ LINXY(__NR_statmount, sys_statmount), // 457
+ LINXY(__NR_listmount, sys_listmount), // 458
LINX_(__NR_mseal, sys_mseal), // 462
};
vki_size_t sigsetsize;
};
+//----------------------------------------------------------------------
+// From uapi/linux/mount.h
+//----------------------------------------------------------------------
+
+struct vki_mnt_id_req {
+ __vki_u32 size;
+ __vki_u32 spare;
+ __vki_u64 mnt_id;
+ __vki_u64 param;
+ __vki_u64 mnt_ns_id;
+};
+
+struct vki_statmount {
+ __vki_u32 size; /* Total size, including strings */
+ __vki_u32 mnt_opts; /* [str] Mount options of the mount */
+ __vki_u64 mask; /* What results were written */
+ __vki_u32 sb_dev_major; /* Device ID */
+ __vki_u32 sb_dev_minor;
+ __vki_u64 sb_magic; /* ..._SUPER_MAGIC */
+ __vki_u32 sb_flags; /* SB_{RDONLY,SYNCHRONOUS,DIRSYNC,LAZYTIME} */
+ __vki_u32 fs_type; /* [str] Filesystem type */
+ __vki_u64 mnt_id; /* Unique ID of mount */
+ __vki_u64 mnt_parent_id; /* Unique ID of parent (for root == mnt_id) */
+ __vki_u32 mnt_id_old; /* Reused IDs used in proc/.../mountinfo */
+ __vki_u32 mnt_parent_id_old;
+ __vki_u64 mnt_attr; /* MOUNT_ATTR_... */
+ __vki_u64 mnt_propagation; /* MS_{SHARED,SLAVE,PRIVATE,UNBINDABLE} */
+ __vki_u64 mnt_peer_group; /* ID of shared peer group */
+ __vki_u64 mnt_master; /* Mount receives propagation from this ID */
+ __vki_u64 propagate_from; /* Propagation from in current namespace */
+ __vki_u32 mnt_root; /* [str] Root of mount relative to root of fs */
+ __vki_u32 mnt_point; /* [str] Mountpoint relative to current root */
+ __vki_u64 mnt_ns_id; /* ID of the mount namespace */
+ __vki_u64 __spare2[49];
+ char str[]; /* Variable size part containing strings */
+};
+
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/
#define __NR_cachestat 451
#define __NR_fchmodat2 452
+#define __NR_statmount 457
+#define __NR_listmount 458
#define __NR_mseal 462
#endif