# 3.12.2 Socket Identity

_Peios / Peios technical reference / PKM / KACS / Network Objects_

> The governing identity KACS stamps on every inet socket for network policy — which token, taken when, and how the engine reads it.

Network policy speaks of programs, and a packet carries no program. What
carries one is the socket: KACS records on every `AF_INET` and
`AF_INET6` socket the **identity that governs its traffic**, and the
network policy engine (Chapter 6, §6.9) reads it at the first judgment
of each flow. [*net.socket.stamp-on-inet-sockets] AF_UNIX sockets carry the peer-identity machinery of
§3.5 instead and are not stamped.

## 3.12.2.1 The stamp

The stamp is the caller's **effective token** — the impersonation token
during impersonation, the primary otherwise — held by a counted
reference, together with the process facts of that moment: the process
GUID (§3.3.2), the thread-group id, and the task's `comm`. [*net.socket.stamp-contents] Choosing the
effective token means a service thread acting for a client attributes
the socket to the client, exactly as file creation and audit do under
impersonation; the service's own identity is then not on the socket for
that flow.

It is taken at every act that commits the socket to a role, and the
last one governs: [*net.socket.last-act-governs]

| Act | Where |
|---|---|
| creation | `socket_post_create`; a kernel socket (`sock_create_kern`) is stamped as the **kernel's**, with no token [*net.socket.kernel-socket-stamp] |
| `bind(2)` | after the port reservation permits it (§3.12.1) |
| `listen(2)` | `socket_listen` |
| `connect(2)` | `socket_connect` |
| `accept(2)` | `sk_clone_security`: the child inherits the listener's stamp, its own reference [*net.socket.accept-inherits] |
| `KACS_SO_RESTAMP` | any state: the caller's effective identity replaces the stamp |

Restamping is what makes a hand-off well defined. A listener opened by
one program and passed to another — socket activation, a descriptor
store, a broker — is governed by whichever program last committed it,
and a program that receives a socket it did not create can say so
explicitly with `KACS_SO_RESTAMP`, self-gated like every attestation of
one's own identity. [*net.socket.restamp-self-gated] Sockets that never pass through these hooks (a task
with no token in early boot) read as *unstamped*, which the engine
treats as the kernel's and confesses. [*net.socket.unstamped-reads-kernel]

## 3.12.2.2 Reading it

The engine reads the stamp with `pkm_kacs_socket_owner()`
(`<linux/peios_ntfe.h>`): a counted token reference the caller releases
with `pkm_kacs_socket_owner_put()`, and a copy of the kind, GUID, pid and
comm. [*net.socket.owner-accessor] The copy is what makes the facts outlive the process; the
reference is what makes them outlive the socket — a flow keeps its
identity for its life (§6.9) even after the socket that started it is
gone. The fields live under their own lock, taken with bottom halves
disabled, because both the accept path and the engine's read run in
softirq context.

## 3.12.2.3 Final release

Once the socket's last user is gone, KACS releases the token references
and security descriptor owned by the socket. This also releases any
peer, listener, binder and send-cache references; each field owns its
own reference even when several refer to the same token. Final cleanup
can run from an RCU callback and must not sleep or acquire the locks
used to coordinate live socket users. It has exclusive ownership at
this point. References already taken by a flow or another reader remain
valid until that reader releases them. [*net.socket.final-release-rcu-safe]

## 3.12.2.4 Tracing [*net.socket.tracing]

Every stamp emits `kacs:kacs_socket_token` with reason `owner`; the
`max_imp` field carries the kind (1 program, 2 kernel). See Appendix
3.C.
