diff --git a/Dockerfile b/Dockerfile index 0093d55..b72953f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ COPY gadgets gadgets # Build gadgets RUN mkdir -p build/gadgets && \ - for gadget in fs-restrict cap-restrict ptrace-restrict binary-attestation; do \ + for gadget in fs-restrict cap-restrict ptrace-restrict socket-restrict binary-attestation; do \ echo "Building gadget: $gadget" && \ ig image build \ --local \ diff --git a/Makefile b/Makefile index ec3eea9..9b107d9 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ GOARCHS := amd64 arm64 LDFLAGS := -X github.com/inspektor-gadget/inspektor-gadget/internal/version.version=v0.47.0 \ -X main.Version=$(IMAGE_TAG) \ -w -s -extldflags "-static" -GADGETS := fs-restrict cap-restrict ptrace-restrict binary-attestation +GADGETS := fs-restrict cap-restrict ptrace-restrict socket-restrict binary-attestation CONFORM_VERSION ?= v0.1.0-alpha.30 # This version number must be kept in sync with CI workflow lint one. @@ -89,6 +89,10 @@ run-fs-restrict: run-cap-restrict: sudo -E ig run $(CONTAINER_REPO)/cap-restrict:$(IMAGE_TAG) $$PARAMS +.PHONY: run-socket-restrict +run-socket-restrict: + sudo -E ig run $(CONTAINER_REPO)/socket-restrict:$(IMAGE_TAG) $$PARAMS + .PHONY: push push: for gadget in $(GADGETS); do \ diff --git a/README.md b/README.md index 856c740..aeb08e5 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Today, Micromize attaches eBPF programs to LSM hooks and enforces: - **Strict container boundaries** — blocks filesystem escapes and host access - **Capability restriction** — prevents privilege escalation via `unshare`/`clone`/`setns` - **Ptrace blocking** — eliminates ptrace-based debugging/injection attacks +- **Socket restriction** — blocks `AF_ALG` (kernel crypto userspace API) socket usage in containers, mitigating CVE-2026-31431 and related attack surface - **Execution integrity** — SBOM + runtime hash validation via `bpf_ima_file_hash` Policies are loaded before container start and enforced at execution time. No runtime replacement. No learning mode. Kernel-native enforcement. diff --git a/cmd/micromize/embeds.go b/cmd/micromize/embeds.go index fb48ddf..53bcc75 100644 --- a/cmd/micromize/embeds.go +++ b/cmd/micromize/embeds.go @@ -29,5 +29,8 @@ var capRestrictGadgetBytes []byte //go:embed build/ptrace-restrict.tar var ptraceRestrictGadgetBytes []byte +//go:embed build/socket-restrict.tar +var socketRestrictGadgetBytes []byte + //go:embed build/binary-attestation.tar var binaryAttestationGadgetBytes []byte diff --git a/cmd/micromize/embeds_dev.go b/cmd/micromize/embeds_dev.go index 999534a..370e4f3 100644 --- a/cmd/micromize/embeds_dev.go +++ b/cmd/micromize/embeds_dev.go @@ -19,4 +19,5 @@ package main var fsRestrictGadgetBytes []byte var capRestrictGadgetBytes []byte var ptraceRestrictGadgetBytes []byte +var socketRestrictGadgetBytes []byte var binaryAttestationGadgetBytes []byte diff --git a/cmd/micromize/root.go b/cmd/micromize/root.go index 723d061..2554621 100644 --- a/cmd/micromize/root.go +++ b/cmd/micromize/root.go @@ -37,6 +37,7 @@ const ( fsRestrictGadgetImageRepo = "ghcr.io/micromize-dev/micromize/fs-restrict" capRestrictGadgetImageRepo = "ghcr.io/micromize-dev/micromize/cap-restrict" ptraceRestrictGadgetImageRepo = "ghcr.io/micromize-dev/micromize/ptrace-restrict" + socketRestrictGadgetImageRepo = "ghcr.io/micromize-dev/micromize/socket-restrict" binaryAttestationGadgetImageRepo = "ghcr.io/micromize-dev/micromize/binary-attestation" ) @@ -161,6 +162,12 @@ func run(ctx context.Context) error { Params: commonParams, }) + registry.Register("socket-restrict", &gadget.GadgetConfig{ + Bytes: socketRestrictGadgetBytes, + ImageName: fmt.Sprintf("%s:%s", socketRestrictGadgetImageRepo, Version), + Params: commonParams, + }) + registry.Register("binary-attestation", &gadget.GadgetConfig{ Bytes: binaryAttestationGadgetBytes, ImageName: fmt.Sprintf("%s:%s", binaryAttestationGadgetImageRepo, Version), diff --git a/gadgets/socket-restrict/README.md b/gadgets/socket-restrict/README.md new file mode 100644 index 0000000..723351d --- /dev/null +++ b/gadgets/socket-restrict/README.md @@ -0,0 +1,27 @@ +# socket-restrict + +Restrict dangerous socket primitives in containers. + +This gadget blocks all `AF_ALG` (kernel crypto userspace API) socket usage +inside containers. `AF_ALG` is rarely needed in containerized production +workloads — most TLS, SSH, and dm-crypt use cases never touch it — and +blocking it eliminates a class of kernel attack surface from the container +boundary. + +The initial motivation is CVE-2026-31431 (Copy Fail), a Linux kernel local +privilege escalation in `algif_aead` that can be triggered via `AF_ALG` +sockets. This gadget blocks the entire killchain at socket creation time, +before any vulnerable kernel path is reached. + +## Hooks + +| Hook | Purpose | +|---|---| +| `lsm/socket_create` | Block `AF_ALG` socket creation (main choke point) | +| `lsm/socket_bind` | Defense-in-depth: block `AF_ALG` bind if a socket FD exists from before policy load. Preserves `alg_type`/`alg_name` for visibility. | + +## Getting Started + +```bash +sudo ig run ghcr.io/micromize-dev/micromize/gadgets/socket-restrict:latest +``` diff --git a/gadgets/socket-restrict/gadget.yaml b/gadgets/socket-restrict/gadget.yaml new file mode 100644 index 0000000..d3a3dfa --- /dev/null +++ b/gadgets/socket-restrict/gadget.yaml @@ -0,0 +1,55 @@ +name: socket-restrict +description: Restrict dangerous socket primitives in containers +homepageURL: https://github.com/micromize-dev/micromize/tree/main/gadgets/socket-restrict +documentationURL: https://github.com/micromize-dev/micromize/tree/main/gadgets/socket-restrict +sourceURL: https://github.com/micromize-dev/micromize/tree/main/gadgets/socket-restrict +datasources: + socket_restrict: + fields: + alg_name: + annotations: + description: The AF_ALG algorithm name requested by the process + alg_type: + annotations: + description: The AF_ALG algorithm type requested by the process + event_type: + annotations: + description: Numeric event type identifier + family: + annotations: + description: Socket address family + process: + annotations: + description: The process attempting a restricted socket operation + reason: + annotations: + description: Human-readable reason for the event + timestamp_raw: + annotations: + description: Timestamp of the event +params: + ebpf: + enforce: + key: enforce + defaultValue: "true" + description: Enforce the restriction (block) or just audit + targ_comm: + key: targ_comm + defaultValue: "" + description: Process name (comm) + targ_gid: + key: targ_gid + defaultValue: "" + description: Group ID + targ_pid: + key: targ_pid + defaultValue: "" + description: Process ID + targ_tid: + key: targ_tid + defaultValue: "" + description: Thread ID + targ_uid: + key: targ_uid + defaultValue: "" + description: User ID diff --git a/gadgets/socket-restrict/program.bpf.c b/gadgets/socket-restrict/program.bpf.c new file mode 100644 index 0000000..95da65c --- /dev/null +++ b/gadgets/socket-restrict/program.bpf.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note +/* Copyright (c) 2024 micromize-Authors */ + +#include "program.bpf.h" + +#include + +#include +#include +#include + +const volatile int enforce = 1; +GADGET_PARAM(enforce); + +GADGET_TRACER_MAP(events, 1024 * 256); + +GADGET_TRACER(socket_restrict, events, event); + +// Block AF_ALG socket creation — main choke point. +SEC("lsm/socket_create") +int BPF_PROG(micromize_socket_create, int family, int type, int protocol, + int kern) { + if (kern) + return 0; + + if (gadget_should_discard_data_current()) + return 0; + + if (family != AF_ALG) + return 0; + + struct event *event; + event = gadget_reserve_buf(&events, sizeof(*event)); + if (!event) { + if (enforce) + return -EPERM; + return 0; + } + + gadget_process_populate(&event->process); + event->timestamp_raw = bpf_ktime_get_boot_ns(); + event->event_type = EVENT_TYPE_SOCKET_AF_ALG_CREATE; + event->family = AF_ALG; + event->alg_type[0] = '\0'; + event->alg_name[0] = '\0'; + + gadget_submit_buf(ctx, &events, event, sizeof(*event)); + + if (enforce) + return -EPERM; + + return 0; +} + +// Defense-in-depth: block AF_ALG bind if a socket FD exists from before +// policy load. Preserves alg_type/alg_name for visibility. +SEC("lsm/socket_bind") +int BPF_PROG(micromize_socket_bind, struct socket *sock, + struct sockaddr *address, int addrlen) { + (void)sock; + + if (gadget_should_discard_data_current()) + return 0; + + if (!address || addrlen < SOCKADDR_ALG_TYPE_END) + return 0; + + __u16 family = 0; + bpf_probe_read_kernel(&family, sizeof(family), address); + if (family != AF_ALG) + return 0; + + struct event *event; + event = gadget_reserve_buf(&events, sizeof(*event)); + if (!event) { + if (enforce) + return -EPERM; + return 0; + } + + gadget_process_populate(&event->process); + event->timestamp_raw = bpf_ktime_get_boot_ns(); + event->event_type = EVENT_TYPE_SOCKET_AF_ALG_BIND; + event->family = family; + + bpf_probe_read_kernel(event->alg_type, SOCKADDR_ALG_TYPE_LEN, + (const char *)address + SOCKADDR_ALG_TYPE_OFFSET); + event->alg_type[SOCKADDR_ALG_TYPE_LEN] = '\0'; + + if (addrlen >= SOCKADDR_ALG_MIN_LEN) { + bpf_probe_read_kernel(event->alg_name, SOCKADDR_ALG_NAME_LEN, + (const char *)address + SOCKADDR_ALG_NAME_OFFSET); + event->alg_name[SOCKADDR_ALG_NAME_LEN - 1] = '\0'; + } else { + event->alg_name[0] = '\0'; + } + + gadget_submit_buf(ctx, &events, event, sizeof(*event)); + + if (enforce) + return -EPERM; + + return 0; +} + +char LICENSE[] SEC("license") = "GPL"; diff --git a/gadgets/socket-restrict/program.bpf.h b/gadgets/socket-restrict/program.bpf.h new file mode 100644 index 0000000..79f559d --- /dev/null +++ b/gadgets/socket-restrict/program.bpf.h @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note +/* Copyright (c) 2024 micromize-Authors */ + +#include +#include + +#ifndef EPERM +#define EPERM 1 +#endif + +#ifndef AF_ALG +#define AF_ALG 38 +#endif + +#define SOCKADDR_ALG_TYPE_OFFSET 2 +#define SOCKADDR_ALG_TYPE_LEN 14 +#define SOCKADDR_ALG_TYPE_END (SOCKADDR_ALG_TYPE_OFFSET + SOCKADDR_ALG_TYPE_LEN) + +#define SOCKADDR_ALG_NAME_OFFSET 24 +#define SOCKADDR_ALG_NAME_LEN 64 +#define SOCKADDR_ALG_MIN_LEN (SOCKADDR_ALG_NAME_OFFSET + SOCKADDR_ALG_NAME_LEN) + +#define EVENT_ALG_TYPE_LEN (SOCKADDR_ALG_TYPE_LEN + 1) + +struct event { + gadget_timestamp timestamp_raw; + struct gadget_process process; + __u32 event_type; + __u32 family; + char alg_type[EVENT_ALG_TYPE_LEN]; + char alg_name[SOCKADDR_ALG_NAME_LEN]; +}; diff --git a/include/micromize/event_types.h b/include/micromize/event_types.h index 9c4aca3..1197916 100644 --- a/include/micromize/event_types.h +++ b/include/micromize/event_types.h @@ -24,6 +24,10 @@ enum micromize_event_type { EVENT_TYPE_HASH_MISMATCH = 8, EVENT_TYPE_UNATTESTED_SHARED_OBJECT = 9, EVENT_TYPE_SHARED_OBJECT_HASH_MISMATCH = 10, + + // socket-restrict + EVENT_TYPE_SOCKET_AF_ALG_CREATE = 11, + EVENT_TYPE_SOCKET_AF_ALG_BIND = 12, }; #endif /* __MICROMIZE_EVENT_TYPES_H */ diff --git a/internal/operators/operators.go b/internal/operators/operators.go index 4a9b400..c76deb2 100644 --- a/internal/operators/operators.go +++ b/internal/operators/operators.go @@ -307,6 +307,8 @@ const ( eventTypeHashMismatch = 8 eventTypeUnattestedSharedObject = 9 eventTypeSharedObjectHashMismatch = 10 + eventTypeSocketAFAlgCreate = 11 + eventTypeSocketAFAlgBind = 12 ) var eventTypeNames = map[uint32]string{ @@ -321,6 +323,8 @@ var eventTypeNames = map[uint32]string{ eventTypeHashMismatch: "hash_mismatch", eventTypeUnattestedSharedObject: "unattested_shared_object", eventTypeSharedObjectHashMismatch: "shared_object_hash_mismatch", + eventTypeSocketAFAlgCreate: "af_alg_socket_create", + eventTypeSocketAFAlgBind: "af_alg_socket_bind", } // NewEventTypeOperator creates an operator that enriches events with a diff --git a/internal/operators/output.go b/internal/operators/output.go index 9ba0ed0..d9392fa 100644 --- a/internal/operators/output.go +++ b/internal/operators/output.go @@ -39,6 +39,8 @@ var eventDescriptions = map[uint32]string{ eventTypeHashMismatch: "Binary hash mismatch detected", eventTypeUnattestedSharedObject: "Unattested shared object loaded", eventTypeSharedObjectHashMismatch: "Shared object hash mismatch detected", + eventTypeSocketAFAlgCreate: "AF_ALG socket creation blocked", + eventTypeSocketAFAlgBind: "AF_ALG socket bind blocked", } var eventEmojis = map[uint32]string{} @@ -73,6 +75,10 @@ type eventFields struct { // Cap-restrict specific cap datasource.FieldAccessor syscall datasource.FieldAccessor + + // socket-restrict specific + algType datasource.FieldAccessor + algName datasource.FieldAccessor } var ( @@ -173,6 +179,8 @@ func collectEventFields(ds datasource.DataSource, etField datasource.FieldAccess f.cap = ds.GetField("cap") f.syscall = ds.GetField("syscall") + f.algType = ds.GetField("alg_type") + f.algName = ds.GetField("alg_name") return f } @@ -205,6 +213,12 @@ func formatAndPrintEvent(f *eventFields, data datasource.Data) { if filename := fieldStr(f.filename, data); filename != "" { fmt.Fprintf(&sb, ". Filename: %s", filename) } + if algType := fieldStr(f.algType, data); algType != "" { + fmt.Fprintf(&sb, ". AF_ALG type: %s", algType) + if algName := fieldStr(f.algName, data); algName != "" { + fmt.Fprintf(&sb, ". Algorithm: %s", algName) + } + } // Show image name only for Docker (non-k8s) environments if fieldStr(f.k8sNamespace, data) == "" { diff --git a/tests/integration/cases/08_af_alg_aead_restrict.sh b/tests/integration/cases/08_af_alg_aead_restrict.sh new file mode 100644 index 0000000..090067c --- /dev/null +++ b/tests/integration/cases/08_af_alg_aead_restrict.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Test: AF_ALG AEAD restriction inside container +# Verify that the CVE-2026-31431 killchain is blocked before algif_aead is reached. + +test_af_alg_aead_restrict() { + begin_test "AF_ALG AEAD socket blocked inside container" + + if ! command -v go &>/dev/null; then + fail_test "go is required to build the AF_ALG probe" + return + fi + + local probe_bin="${ROOTFS_DIR}/bin/af-alg-aead-probe" + if ! (cd "$REPO_ROOT" && CGO_ENABLED=0 GOOS=linux GOARCH="$ARCH" go build -o "$probe_bin" ./tests/integration/probes/af_alg_aead); then + fail_test "failed to build AF_ALG probe" + return + fi + + local bundle="${TEST_TMPDIR}/bundle-af-alg" + local cid="micromize-test-af-alg" + + create_bundle "$bundle" "$ROOTFS_DIR" /bin/af-alg-aead-probe + + local output + output=$(runc run "$cid" -b "$bundle" 2>&1) + local rc=$? + + if [[ $rc -ne 0 ]]; then + fail_test "AF_ALG probe exited with ${rc}: ${output}" + runc delete -f "$cid" 2>/dev/null || true + return + fi + + if echo "$output" | grep -qF "blocked: AF_ALG"; then + pass_test + else + fail_test "Expected AF_ALG AEAD bind to be blocked, got: ${output}" + fi + + runc delete -f "$cid" 2>/dev/null || true +} + +test_af_alg_aead_restrict diff --git a/tests/integration/cases/09_af_alg_hash_restrict.sh b/tests/integration/cases/09_af_alg_hash_restrict.sh new file mode 100644 index 0000000..a28b0a3 --- /dev/null +++ b/tests/integration/cases/09_af_alg_hash_restrict.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Test: AF_ALG hash (non-AEAD) restriction inside container +# Verify that the generic AF_ALG policy blocks non-AEAD types too. + +test_af_alg_hash_restrict() { + begin_test "AF_ALG hash socket blocked inside container" + + if ! command -v go &>/dev/null; then + fail_test "go is required to build the AF_ALG hash probe" + return + fi + + local probe_bin="${ROOTFS_DIR}/bin/af-alg-hash-probe" + if ! (cd "$REPO_ROOT" && CGO_ENABLED=0 GOOS=linux GOARCH="$ARCH" go build -o "$probe_bin" ./tests/integration/probes/af_alg_hash); then + fail_test "failed to build AF_ALG hash probe" + return + fi + + local bundle="${TEST_TMPDIR}/bundle-af-alg-hash" + local cid="micromize-test-af-alg-hash" + + create_bundle "$bundle" "$ROOTFS_DIR" /bin/af-alg-hash-probe + + local output + output=$(runc run "$cid" -b "$bundle" 2>&1) + local rc=$? + + if [[ $rc -ne 0 ]]; then + fail_test "AF_ALG hash probe exited with ${rc}: ${output}" + runc delete -f "$cid" 2>/dev/null || true + return + fi + + if echo "$output" | grep -qF "blocked: AF_ALG"; then + pass_test + else + fail_test "Expected AF_ALG hash to be blocked, got: ${output}" + fi + + runc delete -f "$cid" 2>/dev/null || true +} + +test_af_alg_hash_restrict diff --git a/tests/integration/cases/10_normal_sockets.sh b/tests/integration/cases/10_normal_sockets.sh new file mode 100644 index 0000000..7411f19 --- /dev/null +++ b/tests/integration/cases/10_normal_sockets.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# Test: Normal TCP/UDP sockets still work inside container +# Verify the AF_ALG policy does not block ordinary networking. + +test_normal_sockets() { + begin_test "TCP and UDP sockets still work inside container" + + if ! command -v go &>/dev/null; then + fail_test "go is required to build the TCP socket probe" + return + fi + + local probe_bin="${ROOTFS_DIR}/bin/tcp-socket-probe" + if ! (cd "$REPO_ROOT" && CGO_ENABLED=0 GOOS=linux GOARCH="$ARCH" go build -o "$probe_bin" ./tests/integration/probes/tcp_socket); then + fail_test "failed to build TCP socket probe" + return + fi + + local bundle="${TEST_TMPDIR}/bundle-tcp-socket" + local cid="micromize-test-tcp-socket" + + create_bundle "$bundle" "$ROOTFS_DIR" /bin/tcp-socket-probe + + local output + output=$(runc run "$cid" -b "$bundle" 2>&1) + local rc=$? + + if [[ $rc -ne 0 ]]; then + fail_test "TCP socket probe exited with ${rc}: ${output}" + runc delete -f "$cid" 2>/dev/null || true + return + fi + + if echo "$output" | grep -qF "ok: TCP and UDP sockets work normally"; then + pass_test + else + fail_test "Expected normal sockets to work, got: ${output}" + fi + + runc delete -f "$cid" 2>/dev/null || true +} + +test_normal_sockets diff --git a/tests/integration/probes/af_alg_aead/main.go b/tests/integration/probes/af_alg_aead/main.go new file mode 100644 index 0000000..68abeb9 --- /dev/null +++ b/tests/integration/probes/af_alg_aead/main.go @@ -0,0 +1,66 @@ +// Copyright The micromize authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "os" + "syscall" + "unsafe" +) + +const ( + afALG = 38 + sockSeqpacket = 5 +) + +type sockaddrALG struct { + Family uint16 + Type [14]byte + Feat uint32 + Mask uint32 + Name [64]byte +} + +func main() { + fd, err := syscall.Socket(afALG, sockSeqpacket, 0) + if err != nil { + if err == syscall.EPERM || err == syscall.EACCES { + fmt.Printf("blocked: AF_ALG socket creation denied: %v\n", err) + return + } + fmt.Printf("socket-error: %v\n", err) + os.Exit(2) + } + defer syscall.Close(fd) //nolint:errcheck + + addr := sockaddrALG{Family: afALG} + copy(addr.Type[:], "aead") + copy(addr.Name[:], "authencesn(hmac(sha256),cbc(aes))") + + _, _, errno := syscall.Syscall(syscall.SYS_BIND, uintptr(fd), uintptr(unsafe.Pointer(&addr)), unsafe.Sizeof(addr)) //nolint:gosec // Required for AF_ALG sockaddr + if errno == 0 { + fmt.Println("not-blocked: AF_ALG AEAD bind succeeded") + os.Exit(42) + } + + if errno == syscall.EPERM || errno == syscall.EACCES { + fmt.Printf("blocked: AF_ALG AEAD bind denied: %v\n", errno) + return + } + + fmt.Printf("bind-error: %v\n", errno) + os.Exit(2) +} diff --git a/tests/integration/probes/af_alg_hash/main.go b/tests/integration/probes/af_alg_hash/main.go new file mode 100644 index 0000000..3a5720e --- /dev/null +++ b/tests/integration/probes/af_alg_hash/main.go @@ -0,0 +1,66 @@ +// Copyright The micromize authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "os" + "syscall" + "unsafe" +) + +const ( + afALG = 38 + sockSeqpacket = 5 +) + +type sockaddrALG struct { + Family uint16 + Type [14]byte + Feat uint32 + Mask uint32 + Name [64]byte +} + +func main() { + fd, err := syscall.Socket(afALG, sockSeqpacket, 0) + if err != nil { + if err == syscall.EPERM || err == syscall.EACCES { + fmt.Printf("blocked: AF_ALG socket creation denied: %v\n", err) + return + } + fmt.Printf("socket-error: %v\n", err) + os.Exit(2) + } + defer syscall.Close(fd) //nolint:errcheck + + addr := sockaddrALG{Family: afALG} + copy(addr.Type[:], "hash") + copy(addr.Name[:], "sha256") + + _, _, errno := syscall.Syscall(syscall.SYS_BIND, uintptr(fd), uintptr(unsafe.Pointer(&addr)), unsafe.Sizeof(addr)) //nolint:gosec // Required for AF_ALG sockaddr + if errno == 0 { + fmt.Println("not-blocked: AF_ALG hash bind succeeded") + os.Exit(42) + } + + if errno == syscall.EPERM || errno == syscall.EACCES { + fmt.Printf("blocked: AF_ALG hash bind denied: %v\n", errno) + return + } + + fmt.Printf("bind-error: %v\n", errno) + os.Exit(2) +} diff --git a/tests/integration/probes/tcp_socket/main.go b/tests/integration/probes/tcp_socket/main.go new file mode 100644 index 0000000..4d8db6e --- /dev/null +++ b/tests/integration/probes/tcp_socket/main.go @@ -0,0 +1,39 @@ +// Copyright The micromize authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "os" + "syscall" +) + +func main() { + fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0) + if err != nil { + fmt.Printf("blocked: TCP socket creation failed: %v\n", err) + os.Exit(1) + } + syscall.Close(fd) //nolint:errcheck,gosec + + fd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0) + if err != nil { + fmt.Printf("blocked: UDP socket creation failed: %v\n", err) + os.Exit(1) + } + syscall.Close(fd) //nolint:errcheck,gosec + + fmt.Println("ok: TCP and UDP sockets work normally") +}