unix: add mount_setattr support for linux

This brings in mount_setattr(2) support, added to Linux 5.12 kernel and
documented at https://man7.org/linux/man-pages/man2/mount_setattr.2.html

Change-Id: I5609980c18aef80f9429a8c8cec8c1e129f74ab7
Reviewed-on: https://go-review.googlesource.com/c/sys/+/363444
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
diff --git a/unix/linux/types.go b/unix/linux/types.go
index b43a528..1238146 100644
--- a/unix/linux/types.go
+++ b/unix/linux/types.go
@@ -877,6 +877,8 @@
 	AT_STATX_FORCE_SYNC   = C.AT_STATX_FORCE_SYNC
 	AT_STATX_DONT_SYNC    = C.AT_STATX_DONT_SYNC
 
+	AT_RECURSIVE = C.AT_RECURSIVE
+
 	AT_SYMLINK_FOLLOW   = C.AT_SYMLINK_FOLLOW
 	AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
 
@@ -3865,3 +3867,7 @@
 	SHM_RDONLY = C.SHM_RDONLY
 	SHM_RND    = C.SHM_RND
 )
+
+// mount_setattr
+
+type MountAttr C.struct_mount_attr
diff --git a/unix/mkerrors.sh b/unix/mkerrors.sh
index a74ef58..4945739 100755
--- a/unix/mkerrors.sh
+++ b/unix/mkerrors.sh
@@ -239,6 +239,7 @@
 #include <linux/magic.h>
 #include <linux/memfd.h>
 #include <linux/module.h>
+#include <linux/mount.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netlink.h>
 #include <linux/net_namespace.h>
@@ -520,7 +521,7 @@
 		$2 ~ /^HW_MACHINE$/ ||
 		$2 ~ /^SYSCTL_VERS/ ||
 		$2 !~ "MNT_BITS" &&
-		$2 ~ /^(MS|MNT|UMOUNT)_/ ||
+		$2 ~ /^(MS|MNT|MOUNT|UMOUNT)_/ ||
 		$2 ~ /^NS_GET_/ ||
 		$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
 		$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ ||
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index bc9dc2e..4bc5baf 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -1775,6 +1775,16 @@
 	return mount(source, target, fstype, flags, datap)
 }
 
+//sys	mountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr, size uintptr) (err error) = SYS_MOUNT_SETATTR
+
+// MountSetattr is a wrapper for mount_setattr(2).
+// https://man7.org/linux/man-pages/man2/mount_setattr.2.html
+//
+// Requires kernel >= 5.12.
+func MountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr) error {
+	return mountSetattr(dirfd, pathname, flags, attr, unsafe.Sizeof(*attr))
+}
+
 func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	if raceenabled {
 		raceReleaseMerge(unsafe.Pointer(&ioSync))
diff --git a/unix/zerrors_linux.go b/unix/zerrors_linux.go
index 4e4e7f8..d175aae 100644
--- a/unix/zerrors_linux.go
+++ b/unix/zerrors_linux.go
@@ -1476,6 +1476,18 @@
 	MNT_FORCE                                   = 0x1
 	MODULE_INIT_IGNORE_MODVERSIONS              = 0x1
 	MODULE_INIT_IGNORE_VERMAGIC                 = 0x2
+	MOUNT_ATTR_IDMAP                            = 0x100000
+	MOUNT_ATTR_NOATIME                          = 0x10
+	MOUNT_ATTR_NODEV                            = 0x4
+	MOUNT_ATTR_NODIRATIME                       = 0x80
+	MOUNT_ATTR_NOEXEC                           = 0x8
+	MOUNT_ATTR_NOSUID                           = 0x2
+	MOUNT_ATTR_NOSYMFOLLOW                      = 0x200000
+	MOUNT_ATTR_RDONLY                           = 0x1
+	MOUNT_ATTR_RELATIME                         = 0x0
+	MOUNT_ATTR_SIZE_VER0                        = 0x20
+	MOUNT_ATTR_STRICTATIME                      = 0x20
+	MOUNT_ATTR__ATIME                           = 0x70
 	MSDOS_SUPER_MAGIC                           = 0x4d44
 	MSG_BATCH                                   = 0x40000
 	MSG_CMSG_CLOEXEC                            = 0x40000000
diff --git a/unix/zsyscall_linux.go b/unix/zsyscall_linux.go
index fe6c232..93edda4 100644
--- a/unix/zsyscall_linux.go
+++ b/unix/zsyscall_linux.go
@@ -409,6 +409,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func mountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr, size uintptr) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(pathname)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_MOUNT_SETATTR, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(unsafe.Pointer(attr)), uintptr(size), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Acct(path string) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
diff --git a/unix/ztypes_linux.go b/unix/ztypes_linux.go
index d887d9b..37b5214 100644
--- a/unix/ztypes_linux.go
+++ b/unix/ztypes_linux.go
@@ -743,6 +743,8 @@
 	AT_STATX_FORCE_SYNC   = 0x2000
 	AT_STATX_DONT_SYNC    = 0x4000
 
+	AT_RECURSIVE = 0x8000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 
@@ -3959,3 +3961,10 @@
 	SHM_RDONLY = 0x1000
 	SHM_RND    = 0x2000
 )
+
+type MountAttr struct {
+	Attr_set    uint64
+	Attr_clr    uint64
+	Propagation uint64
+	Userns_fd   uint64
+}