TL;DR: A process is a running program plus the things the kernel attaches to it: a private virtual address space, credentials (user, groups, capabilities), open handles and limits. One process cannot read another's memory because each has its own page tables, which only the kernel can change, so the other process's physical pages are simply not addressable. Isolation is then deliberately relaxed through debugging interfaces (
ptrace, Windows debug privileges), shared memory, IPC and inherited handles, and each of those doors has its own access check. Threads inside one process share the address space, so there is no isolation between them at all.
How to approach it
Define the process by what the kernel tracks, explain the mechanism that isolates memory, then list the legitimate ways across and the check guarding each. Close with the security consequence: a process boundary is only as strong as the most permissive of those doors, and it is not a boundary between threads.
A strong answer
Address space
Own page tables
- Other processes' memory is not addressable
- Only the kernel edits page tables
Credentials
UID, GIDs, capabilities
- Checked on every privileged request
Handles
Files, sockets, pipes
- Inherited by children unless marked close-on-exec
Door: debugging
ptrace, debug privileges
- Same-user debugging allowed by default on many systems
- Yama ptrace_scope restricts it
Door: shared memory and IPC
Mapped regions, sockets
- Each with its own access check
Threads
Share everything
- No isolation between threads of one process
What the kernel keeps per process.
- An address space: page tables mapping virtual addresses to physical memory, with per-page permissions (read, write, execute, user or supervisor).
- Credentials: on Linux the real, effective and saved user and group IDs plus capability sets; on Windows an access token with SIDs, groups, privileges and an integrity level.
- Handles: file descriptors or Windows handles to files, sockets, pipes and other objects, each opened with specific rights.
- Limits and accounting: resource limits, cgroup membership, the namespace set it lives in.
Why one process cannot read another's memory. A process only ever issues virtual addresses. The memory management unit translates them using the current process's page tables, which the kernel switches on every context switch. If another process's pages are not in your tables, no address you can form reaches them; trying to touch an unmapped address faults. Only the kernel can edit page tables, so the guarantee holds as long as the kernel is correct.
The doors, and their locks.
| Mechanism | What it allows | The access check |
|---|---|---|
ptrace (Linux), ReadProcessMemory/debug privilege (Windows) | Read and write another process's memory and registers | Same user and not more privileged, or a capability (CAP_SYS_PTRACE); Yama ptrace_scope can restrict further; SeDebugPrivilege on Windows bypasses most checks |
/proc/<pid>/mem and friends | Memory access through the filesystem | The same ptrace access rules |
| Shared memory, memory-mapped files | Pages deliberately mapped into both | Permissions on the shared object or file |
| Pipes, sockets, message queues, COM/RPC | Data exchange | Permissions on the endpoint; the receiver must treat data as untrusted |
Inherited handles across fork/exec or CreateProcess | A child gets the parent's open descriptors | The parent's choice; forgetting O_CLOEXEC leaks descriptors to children |
This is why "same user" means "no real isolation" on a classic desktop: two processes under one account can usually debug each other. Browsers and mobile platforms add sandboxing (separate users, seccomp or Seatbelt policies, restricted tokens) precisely because the default process boundary between same-user processes is weak.
Threads. Threads in one process share the address space and handles. A bug in one thread can corrupt data used by another, and a plugin loaded into a process has the process's full access. If you need isolation, you need a separate process with different credentials, not a thread.
Where this shows up in an interview about AI systems. A model-serving process that loads a third-party model with a code-executing loader runs that code with the server's credentials and address space. Moving the loader into a separate, less privileged process with no network and no secrets is the process-isolation answer to an AI supply-chain problem.
What interviewers probe next
- "What is inherited across fork and exec?" The child starts with the parent's credentials, environment, open descriptors (unless marked close-on-exec), working directory and resource limits.
execreplaces the memory image but keeps descriptors, which is how secrets leak into helper programs. - "How would you stop a compromised process from debugging others of the same user?" Raise
ptrace_scope, run sensitive work under its own user, and use a sandbox profile that denies process inspection. - "Is a process boundary enough for untrusted code?" Only if the process also runs with minimal credentials and a reduced system call surface. The shared kernel remains the weak point.
What if?
What if · interview follow-ups
Hold your answer as the constraints change
You run two services on one Linux host: a public API and a billing worker that holds payment credentials.
Start here
What is a process, security-wise?
What does the kernel track for each process?
A running program plus what the kernel attaches: a private virtual address space, credentials (user, groups, capabilities), open handles and limits.
Carry it forwardProcesses bundle memory, credentials and handles.
Weak answerThinking processes are just running code.
Constraint changes
Why can one process not read another's memory?
How could one process see another's memory?
Each has its own page tables, which only the kernel can change, so the other process's physical pages are simply not mapped. Debugging interfaces such as ptrace are the exception and are permission-controlled.
Carry it forwardSeparate page tables isolate memory.
Weak answerForgetting debug interfaces.
Constraint changes
What if both services run as the same user?
Which checks compare users?
Then a compromised API can signal, debug or read files of the billing worker, including its credentials, because user-based checks treat them as the same principal.
Carry it forwardSame user means weak separation.
Weak answerRunning all services as one account.
Constraint changes
How would you separate them?
What would a compromised API need to reach billing?
Different users, restricted ptrace, separate filesystems or containers with namespaces, credentials readable only by the billing user, and ideally separate hosts or VMs given the credential's value.
Carry it forwardSeparate identities, filesystems and preferably hosts.
Weak answerRelying only on process memory isolation.
Constraint changes
What about the shared kernel?
What do both processes depend on?
Both still share the kernel, so a kernel bug in the API's reach could expose the billing worker. High-value workloads deserve separate VMs or hosts.
Carry it forwardShared kernel is shared risk.
Weak answerTreating process isolation as absolute.
Now defend it
How would you deploy the two services?
Run them as different users with ptrace restricted, separate filesystems and namespaces, billing credentials readable only by the billing user and ideally fetched at runtime, and given their value, place the billing worker on a separate VM or host from the public API.
How it's scored
Weak: "Each process has its own memory." No mechanism, no exceptions.
Hire: Explains virtual memory and page tables, credentials and handles, and names ptrace and shared memory as deliberate ways across.
Strong Hire: Lists the doors with their access checks, explains why same-user processes are weakly isolated, distinguishes threads, and applies process separation to a real design such as isolating a model loader.
Common mistakes
- Saying processes are isolated "by the hardware" without the kernel's page tables in the story.
- Forgetting that debugging interfaces exist and are governed by user and capability checks.
- Treating threads as isolated from each other.
- Ignoring descriptors inherited by child processes.