diff --git a/config-linux.md b/config-linux.md
index c71757494..2d8f2e49a 100644
--- a/config-linux.md
+++ b/config-linux.md
@@ -1040,6 +1040,51 @@ Example sending a single `seccompFd` file descriptor in the `SCM_RIGHTS` array:
}
```
+## io_uring
+
+**`ioUring`** (object, OPTIONAL) restricts the [io_uring(7)][io_uring.7] operations that the container process can submit.
+io_uring operations are not system calls, so [seccomp](#configLinuxSeccomp) cannot filter them.
+Whether the io_uring system calls themselves are allowed is controlled by seccomp.
+
+* **`ops`** *(array of strings, REQUIRED)* - the io_uring operations that are allowed.
+ All other operations are denied, and an empty array denies all operations.
+ Whether an operation is allowed does not depend on its submission flags (`IOSQE_*`).
+ Values are names of the `IORING_OP_*` constants from ``, for example `IORING_OP_READ`.
+ The runtime MUST generate an error if it does not recognize a value.
+ The runtime MUST ignore a recognized value that the kernel does not support.
+* **`socketFamilies`** *(array of strings, OPTIONAL)* - the address families that `IORING_OP_SOCKET` can create.
+ If this property is not set, any address family is allowed.
+ If it is set, it MUST NOT be empty; to deny all sockets, leave `IORING_OP_SOCKET` out of `ops`.
+ Values are names of the `AF_*` constants from ``, for example `AF_INET`.
+ The runtime MUST generate an error if it does not recognize a value.
+ The runtime MUST generate an error if this property is set and `ops` does not contain `IORING_OP_SOCKET`.
+
+The runtime MUST apply the restrictions before the container process is executed, so that they apply to the container process and all of its descendants.
+If the runtime cannot apply the restrictions, it MUST generate an error.
+Applying `ioUring` SHOULD NOT prevent the container process from registering further io_uring restrictions of its own.
+The restrictions only apply to io_uring instances created after they are applied.
+An io_uring instance passed into the container, for example with `SCM_RIGHTS`, is not restricted.
+
+### Example
+
+```json
+"ioUring": {
+ "ops": [
+ "IORING_OP_READ",
+ "IORING_OP_WRITE",
+ "IORING_OP_SEND",
+ "IORING_OP_RECV",
+ "IORING_OP_ACCEPT",
+ "IORING_OP_SOCKET"
+ ],
+ "socketFamilies": [
+ "AF_UNIX",
+ "AF_INET",
+ "AF_INET6"
+ ]
+}
+```
+
## Rootfs Mount Propagation
**`rootfsPropagation`** (string, OPTIONAL) sets the rootfs's mount propagation.
@@ -1140,6 +1185,7 @@ subset of the available options.
[full.4]: https://man7.org/linux/man-pages/man4/full.4.html
[set_mempolicy.2]: https://man7.org/linux/man-pages/man2/set_mempolicy.2.html
+[io_uring.7]: https://man7.org/linux/man-pages/man7/io_uring.7.html
[mknod.1]: https://man7.org/linux/man-pages/man1/mknod.1.html
[mknod.2]: https://man7.org/linux/man-pages/man2/mknod.2.html
[namespaces.7_2]: https://man7.org/linux/man-pages/man7/namespaces.7.html
diff --git a/features-linux.md b/features-linux.md
index 3331266dd..9ec66ce75 100644
--- a/features-linux.md
+++ b/features-linux.md
@@ -165,6 +165,44 @@ Irrelevant to the kernel version of the host operating system.
}
```
+## io_uring
+
+**`ioUring`** (object, OPTIONAL) represents the runtime's implementation status of io_uring restrictions.
+Irrelevant to the kernel version of the host operating system.
+
+* **`enabled`** (bool, OPTIONAL) represents whether the runtime supports io_uring restrictions.
+* **`ops`** (array of strings, OPTIONAL) The recognized names of the io_uring operations.
+ The runtime MUST recognize the elements in this array in the [`ops` property of the `linux.ioUring` object in `config.json`](config-linux.md#configLinuxIoUring).
+* **`socketFamilies`** (array of strings, OPTIONAL) The recognized names of the address families.
+ The runtime MUST recognize the elements in this array in the [`socketFamilies` property of the `linux.ioUring` object in `config.json`](config-linux.md#configLinuxIoUring).
+
+### Example
+
+```json
+"ioUring": {
+ "enabled": true,
+ "ops": [
+ "IORING_OP_NOP",
+ "IORING_OP_READV",
+ "IORING_OP_WRITEV",
+ "IORING_OP_READ",
+ "IORING_OP_WRITE",
+ "IORING_OP_SEND",
+ "IORING_OP_RECV",
+ "IORING_OP_ACCEPT",
+ "IORING_OP_SOCKET"
+ ],
+ "socketFamilies": [
+ "AF_UNIX",
+ "AF_INET",
+ "AF_INET6",
+ "AF_NETLINK",
+ "AF_PACKET",
+ "AF_VSOCK"
+ ]
+}
+```
+
## AppArmor
**`apparmor`** (object, OPTIONAL) represents the runtime's implementation status of AppArmor.
diff --git a/features.md b/features.md
index 9c729591a..136feb940 100644
--- a/features.md
+++ b/features.md
@@ -348,6 +348,18 @@ Here is a full example for reference.
"SECCOMP_FILTER_FLAG_LOG"
]
},
+ "ioUring": {
+ "enabled": true,
+ "ops": [
+ "IORING_OP_READ",
+ "IORING_OP_WRITE"
+ ],
+ "socketFamilies": [
+ "AF_UNIX",
+ "AF_INET",
+ "AF_INET6"
+ ]
+ },
"apparmor": {
"enabled": true
},
diff --git a/schema/config-linux.json b/schema/config-linux.json
index 778561d89..613b14a00 100644
--- a/schema/config-linux.json
+++ b/schema/config-linux.json
@@ -250,6 +250,27 @@
"defaultAction"
]
},
+ "ioUring": {
+ "type": "object",
+ "properties": {
+ "ops": {
+ "type": "array",
+ "items": {
+ "$ref": "defs-linux.json#/definitions/IoUringOp"
+ }
+ },
+ "socketFamilies": {
+ "type": "array",
+ "items": {
+ "$ref": "defs-linux.json#/definitions/SocketFamily"
+ },
+ "minItems": 1
+ }
+ },
+ "required": [
+ "ops"
+ ]
+ },
"sysctl": {
"$ref": "defs.json#/definitions/mapStringString"
},
diff --git a/schema/defs-linux.json b/schema/defs-linux.json
index edc0a523c..a0e7545ac 100644
--- a/schema/defs-linux.json
+++ b/schema/defs-linux.json
@@ -266,6 +266,14 @@
"allow"
]
},
+ "IoUringOp": {
+ "type": "string",
+ "pattern": "^IORING_OP_[A-Z0-9_]+$"
+ },
+ "SocketFamily": {
+ "type": "string",
+ "pattern": "^AF_[A-Z0-9_]+$"
+ },
"MemoryPolicyMode": {
"type": "string",
"enum": [
diff --git a/schema/features-linux.json b/schema/features-linux.json
index fcf3df7d6..43204ea62 100644
--- a/schema/features-linux.json
+++ b/schema/features-linux.json
@@ -74,6 +74,26 @@
}
}
},
+ "ioUring": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "ops": {
+ "type": "array",
+ "items": {
+ "$ref": "defs-linux.json#/definitions/IoUringOp"
+ }
+ },
+ "socketFamilies": {
+ "type": "array",
+ "items": {
+ "$ref": "defs-linux.json#/definitions/SocketFamily"
+ }
+ }
+ }
+ },
"apparmor": {
"type": "object",
"properties": {
diff --git a/schema/test/config/bad/linux-io-uring-empty-families.json b/schema/test/config/bad/linux-io-uring-empty-families.json
new file mode 100644
index 000000000..789638c36
--- /dev/null
+++ b/schema/test/config/bad/linux-io-uring-empty-families.json
@@ -0,0 +1,14 @@
+{
+ "ociVersion": "1.0.0",
+ "root": {
+ "path": "rootfs"
+ },
+ "linux": {
+ "ioUring": {
+ "ops": [
+ "IORING_OP_SOCKET"
+ ],
+ "socketFamilies": []
+ }
+ }
+}
diff --git a/schema/test/config/bad/linux-io-uring-invalid-op.json b/schema/test/config/bad/linux-io-uring-invalid-op.json
new file mode 100644
index 000000000..c79455729
--- /dev/null
+++ b/schema/test/config/bad/linux-io-uring-invalid-op.json
@@ -0,0 +1,13 @@
+{
+ "ociVersion": "1.0.0",
+ "root": {
+ "path": "rootfs"
+ },
+ "linux": {
+ "ioUring": {
+ "ops": [
+ "read"
+ ]
+ }
+ }
+}
diff --git a/schema/test/config/bad/linux-io-uring.json b/schema/test/config/bad/linux-io-uring.json
new file mode 100644
index 000000000..2e63cfdd4
--- /dev/null
+++ b/schema/test/config/bad/linux-io-uring.json
@@ -0,0 +1,13 @@
+{
+ "ociVersion": "1.0.0",
+ "root": {
+ "path": "rootfs"
+ },
+ "linux": {
+ "ioUring": {
+ "socketFamilies": [
+ "AF_INET"
+ ]
+ }
+ }
+}
diff --git a/schema/test/config/good/linux-io-uring.json b/schema/test/config/good/linux-io-uring.json
new file mode 100644
index 000000000..18817ab4e
--- /dev/null
+++ b/schema/test/config/good/linux-io-uring.json
@@ -0,0 +1,19 @@
+{
+ "ociVersion": "1.0.0",
+ "root": {
+ "path": "rootfs"
+ },
+ "linux": {
+ "ioUring": {
+ "ops": [
+ "IORING_OP_READ",
+ "IORING_OP_WRITE",
+ "IORING_OP_SOCKET"
+ ],
+ "socketFamilies": [
+ "AF_UNIX",
+ "AF_INET6"
+ ]
+ }
+ }
+}
diff --git a/specs-go/config.go b/specs-go/config.go
index 711eb9e17..18e04fbcf 100644
--- a/specs-go/config.go
+++ b/specs-go/config.go
@@ -242,6 +242,8 @@ type Linux struct {
NetDevices map[string]LinuxNetDevice `json:"netDevices,omitempty"`
// Seccomp specifies the seccomp security settings for the container.
Seccomp *LinuxSeccomp `json:"seccomp,omitempty"`
+ // IOUring restricts the io_uring operations available to the container.
+ IOUring *LinuxIOUring `json:"ioUring,omitempty"`
// RootfsPropagation is the rootfs mount propagation mode for the container.
RootfsPropagation string `json:"rootfsPropagation,omitempty"`
// MaskedPaths masks over the provided paths inside the container.
@@ -892,6 +894,17 @@ type LinuxIntelRdt struct {
EnableMonitoring bool `json:"enableMonitoring,omitempty"`
}
+// LinuxIOUring restricts the io_uring operations available to the container.
+type LinuxIOUring struct {
+ // Ops is the list of allowed io_uring operations, e.g., "IORING_OP_READ".
+ // All other operations are denied.
+ Ops []string `json:"ops"`
+ // SocketFamilies is the list of address families that IORING_OP_SOCKET
+ // can create, e.g., "AF_INET". Nil or empty means any address family;
+ // to deny all sockets, leave IORING_OP_SOCKET out of Ops.
+ SocketFamilies []string `json:"socketFamilies,omitempty"`
+}
+
// LinuxMemoryPolicy represents input for the set_mempolicy syscall.
type LinuxMemoryPolicy struct {
// Mode for the set_mempolicy syscall.
diff --git a/specs-go/features/features.go b/specs-go/features/features.go
index 7b4c40640..d7bf626f4 100644
--- a/specs-go/features/features.go
+++ b/specs-go/features/features.go
@@ -44,6 +44,7 @@ type Linux struct {
Cgroup *Cgroup `json:"cgroup,omitempty"`
Seccomp *Seccomp `json:"seccomp,omitempty"`
+ IOUring *IOUring `json:"ioUring,omitempty"`
Apparmor *Apparmor `json:"apparmor,omitempty"`
Selinux *Selinux `json:"selinux,omitempty"`
IntelRdt *IntelRdt `json:"intelRdt,omitempty"`
@@ -109,6 +110,21 @@ type Seccomp struct {
SupportedFlags []string `json:"supportedFlags,omitempty"`
}
+// IOUring represents the "ioUring" field.
+type IOUring struct {
+ // Enabled is true if io_uring restrictions support is compiled in.
+ // Nil value means "unknown", not "false".
+ Enabled *bool `json:"enabled,omitempty"`
+
+ // Ops is the list of the recognized io_uring operations, e.g., "IORING_OP_READ".
+ // Nil value means "unknown", not "no support for any operation".
+ Ops []string `json:"ops,omitempty"`
+
+ // SocketFamilies is the list of the recognized address families, e.g., "AF_INET".
+ // Nil value means "unknown", not "no support for any address family".
+ SocketFamilies []string `json:"socketFamilies,omitempty"`
+}
+
// Apparmor represents the "apparmor" field.
type Apparmor struct {
// Enabled is true if AppArmor support is compiled in.