diff --git a/src/tools/genpolicy/genpolicy-settings.json b/src/tools/genpolicy/genpolicy-settings.json index 8a5f6324e0..56f8154fc4 100644 --- a/src/tools/genpolicy/genpolicy-settings.json +++ b/src/tools/genpolicy/genpolicy-settings.json @@ -335,6 +335,15 @@ "^AZURE_AUTHORITY_HOST=https://login\\.microsoftonline\\.com/$" ] }, + "UpdateInterfaceRequest": { + "allow_raw_flags": 128, + "forbidden_names": [ + "lo" + ], + "forbidden_hw_addrs": [ + "00:00:00:00:00:00" + ] + }, "CopyFileRequest": [ "$(sfprefix)" ], diff --git a/src/tools/genpolicy/rules.rego b/src/tools/genpolicy/rules.rego index 2794ef74f1..51a052234f 100644 --- a/src/tools/genpolicy/rules.rego +++ b/src/tools/genpolicy/rules.rego @@ -38,7 +38,7 @@ default StopTracingRequest := false default TtyWinResizeRequest := true default UpdateContainerRequest := false default UpdateEphemeralMountsRequest := false -default UpdateInterfaceRequest := true +default UpdateInterfaceRequest := false default UpdateRoutesRequest := false default WaitProcessRequest := true default WriteStreamRequest := false @@ -1332,6 +1332,27 @@ UpdateRoutesRequest { print("UpdateRoutesRequest: true") } +UpdateInterfaceRequest { + print("UpdateInterfaceRequest: input =", input) + print("UpdateInterfaceRequest: policy =", policy_data.request_defaults.UpdateInterfaceRequest) + + i_interface := input.interface + p_flags := policy_data.request_defaults.UpdateInterfaceRequest.allow_raw_flags + + # Typically, just IFF_NOARP is used. + bits.and(i_interface.raw_flags, bits.negate(p_flags)) == 0 + + p_names := policy_data.request_defaults.UpdateInterfaceRequest.forbidden_names + + not i_interface.name in p_names + + p_hwaddrs := policy_data.request_defaults.UpdateInterfaceRequest.forbidden_hw_addrs + + not i_interface.hwAddr in p_hwaddrs + + print("UpdateInterfaceRequest: true") +} + CloseStdinRequest { policy_data.request_defaults.CloseStdinRequest == true } diff --git a/src/tools/genpolicy/src/policy.rs b/src/tools/genpolicy/src/policy.rs index d7c93c95e9..b9e7e187c9 100644 --- a/src/tools/genpolicy/src/policy.rs +++ b/src/tools/genpolicy/src/policy.rs @@ -344,6 +344,19 @@ pub struct UpdateRoutesRequestDefaults { forbidden_source_regex: Vec, } +/// UpdateInterfaceRequest settings from genpolicy-settings.json. +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct UpdateInterfaceRequestDefaults { + /// Raw flag bitmask explicitly allowed to configure + allow_raw_flags: u32, + + /// Explicitly blocked interface names. Intent is to block changes to loopback interface. + forbidden_names: Vec, + + /// Explicitly blocked mac addresses. Intent is to block changes to loopback interface. + forbidden_hw_addrs: Vec, +} + /// Settings specific to each kata agent endpoint, loaded from /// genpolicy-settings.json. #[derive(Clone, Debug, Serialize, Deserialize)] @@ -360,6 +373,9 @@ pub struct RequestDefaults { /// Allow the host to update routes for devices other than the loopback. pub UpdateRoutesRequest: UpdateRoutesRequestDefaults, + /// Allow the host to configure only used raw_flags and reject names/mac addresses of the loopback. + pub UpdateInterfaceRequest: UpdateInterfaceRequestDefaults, + /// Allow the Host to close stdin for a container. Typically used with WriteStreamRequest. pub CloseStdinRequest: bool, diff --git a/src/tools/genpolicy/tests/main.rs b/src/tools/genpolicy/tests/main.rs index 45103e3526..26d7e676c3 100644 --- a/src/tools/genpolicy/tests/main.rs +++ b/src/tools/genpolicy/tests/main.rs @@ -12,7 +12,8 @@ mod tests { use std::str; use protocols::agent::{ - CopyFileRequest, CreateContainerRequest, CreateSandboxRequest, UpdateRoutesRequest, + CopyFileRequest, CreateContainerRequest, CreateSandboxRequest, UpdateInterfaceRequest, + UpdateRoutesRequest, }; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; @@ -142,6 +143,11 @@ mod tests { runtests::("updateroutes").await; } + #[tokio::test] + async fn test_update_interface() { + runtests::("updateinterface").await; + } + #[tokio::test] async fn test_create_container_network_namespace() { runtests::("createcontainer/network_namespace").await; diff --git a/src/tools/genpolicy/tests/testdata/updateinterface/pod.yaml b/src/tools/genpolicy/tests/testdata/updateinterface/pod.yaml new file mode 100644 index 0000000000..7ac6554ed9 --- /dev/null +++ b/src/tools/genpolicy/tests/testdata/updateinterface/pod.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Pod +metadata: + name: dummy +spec: + runtimeClassName: kata-cc-isolation + containers: + - name: dummy + image: registry.k8s.io/pause:3.6@sha256:3d380ca8864549e74af4b29c10f9cb0956236dfb01c40ca076fb6c37253234db diff --git a/src/tools/genpolicy/tests/testdata/updateinterface/testcases.json b/src/tools/genpolicy/tests/testdata/updateinterface/testcases.json new file mode 100644 index 0000000000..70ebb4200c --- /dev/null +++ b/src/tools/genpolicy/tests/testdata/updateinterface/testcases.json @@ -0,0 +1,97 @@ +[ + { + "description": "no flags", + "allowed": true, + "request": { + "interface": { + "device": "eth0", + "name": "eth0", + "IPAddresses": [ + {"family":0, "address":"10.244.0.14", "mask":"24"}, + {"family":1, "address":"fe80::6474:9fff:fe6a:9601", "mask":"64"} + ], + "mtu": 1500, + "hwAddr": "66:74:9f:6a:96:01", + "pciPath": "", + "type_": "", + "raw_flags": 0 + } + } + }, + { + "description": "allowed arp flag", + "allowed": true, + "request": { + "interface": { + "device": "eth0", + "name": "eth0", + "IPAddresses": [ + {"family":0, "address":"10.244.0.14", "mask":"24"}, + {"family":1, "address":"fe80::6474:9fff:fe6a:9601", "mask":"64"} + ], + "mtu": 1500, + "hwAddr": "66:74:9f:6a:96:01", + "pciPath": "", + "type_": "", + "raw_flags": 128 + } + } + }, + { + "description": "forbidden flag", + "allowed": false, + "request": { + "interface": { + "device": "eth0", + "name": "eth0", + "IPAddresses": [ + {"family":0, "address":"10.244.0.14", "mask":"24"}, + {"family":1, "address":"fe80::6474:9fff:fe6a:9601", "mask":"64"} + ], + "mtu": 1500, + "hwAddr": "66:74:9f:6a:96:01", + "pciPath": "", + "type_": "", + "raw_flags": 64 + } + } + }, + { + "description": "forbidden name", + "allowed": false, + "request": { + "interface": { + "device": "eth0", + "name": "lo", + "IPAddresses": [ + {"family":0, "address":"10.244.0.14", "mask":"24"}, + {"family":1, "address":"fe80::6474:9fff:fe6a:9601", "mask":"64"} + ], + "mtu": 1500, + "hwAddr": "66:74:9f:6a:96:01", + "pciPath": "", + "type_": "", + "raw_flags": 0 + } + } + }, + { + "description": "forbidden hwAddr", + "allowed": false, + "request": { + "interface": { + "device": "eth0", + "name": "eth0", + "IPAddresses": [ + {"family":0, "address":"10.244.0.14", "mask":"24"}, + {"family":1, "address":"fe80::6474:9fff:fe6a:9601", "mask":"64"} + ], + "mtu": 1500, + "hwAddr": "00:00:00:00:00:00", + "pciPath": "", + "type_": "", + "raw_flags": 0 + } + } + } +]