Skip to content

07 · Linux, processes, files, and network diagnosis

Depth: developed lesson with local experiments · Prerequisite: foundations · Time: three 90-minute sessions.

This chapter connects a running program to its identity, files, listening socket, and HTTP decisions. It develops core operating-system and networking reasoning; advanced Linux privilege escalation, namespaces and packet analysis remain separate coverage gaps.

Outcomes

  • Distinguish a process, its account context, a file permission, and an application permission.
  • Explain the owner/group/other mode bits without claiming they describe every access-control mechanism.
  • Separate transport failure from an HTTP denial or missing route.
  • Use a controlled hostname mapping without confusing it with a DNS observation.

Session one: process and file authority

A process is a running execution context. The account name shown in your shell is one clue about its authority, not a summary of all permissions the process might exercise. On your own Linux lab host, collect:

id
uname -s
ps -p $$ -o pid=,ppid=,comm=

$$ is the current shell's process ID. Record the actual platform: macOS is not Linux, even when some commands have similar names. Process flags and available diagnostic tools differ across systems.

Linux inode metadata includes owner and group IDs and permission bits. The familiar owner/group/other read, write and execute bits describe important discretionary permissions, but ACLs and other mechanisms may also affect access. Directory permissions have different consequences from file permissions, so do not interpret a directory's execute bit as permission to run its contents. See inode(7).

Use this bounded POSIX exercise on Linux or macOS. It creates a fresh temporary directory, changes only its own file, and removes that directory on exit:

from pathlib import Path
import os
import stat
import tempfile

with tempfile.TemporaryDirectory(prefix="deadwire-permissions-") as directory:
    path = Path(directory) / "synthetic.txt"
    path.write_text("synthetic training data\n", encoding="utf-8")
    for mode in (0o600, 0o640):
        path.chmod(mode)
        info = path.stat()
        print({"mode": oct(stat.S_IMODE(info.st_mode)),
               "owner_uid": info.st_uid,
               "group_gid": info.st_gid,
               "current_euid": os.geteuid()})

Save the block as a private exercise file and run it with python3. Predict the mode output before executing it. Octal 600 gives owner read/write bits; 640 adds the group-read bit. The exercise observes metadata. Because it runs under one identity, it does not prove how a different account would be authorized. Root/capability behavior, ACLs and directory traversal require their own tests.

Session two: find the layer that answered

Start the fixed web fixture in one terminal:

python3 -m labs.web_boundary --mode fixed

On Linux, a read-only listener inspection can use:

ss -lnt

If that tool is absent, record the environment gap; do not pretend a different operating system produced Linux output. Listener output identifies a socket, not the business rule implemented behind it.

From a second terminal, run one request at a time:

curl --noproxy '*' --include --max-time 5 http://127.0.0.1:8080/api/health
curl --noproxy '*' --include --max-time 5 http://127.0.0.1:8080/missing
curl --noproxy '*' --include --max-time 5 -H 'X-Lab-User: alice' http://127.0.0.1:8080/api/records/202

In the supplied fixed fixture, expect 200, 404 and 403 respectively. All three are HTTP responses: a server received enough of the exchange to return an application-layer status. A denial is therefore different from failure to establish the connection.

Stop the server with Ctrl-C. Repeat the health request. If no other process has taken the port, curl should fail to connect rather than receive HTTP 403. If it still gets a response, investigate the process and address instead of writing the expected result into your notes.

The curl options bound the request duration, show headers, and avoid configured proxies for these local requests. Curl's exit status is separate from the HTTP status; without a fail-on-HTTP-error option, an HTTP error response need not be a command failure. Consult the curl manual.

Session three: hostname mapping is not DNS evidence

Restart the fixed server. This command tells curl to connect a fictional hostname to loopback for this request:

curl --noproxy '*' --include --max-time 5 \
  --resolve lab.invalid:8080:127.0.0.1 \
  http://lab.invalid:8080/api/health

The fixture should return 403 because it requires its exact loopback Host authority. You reached the server; the refusal comes from the fixture's Host check. Now keep the connection mapping and explicitly provide the authority that this fixture expects:

curl --noproxy '*' --include --max-time 5 \
  --resolve lab.invalid:8080:127.0.0.1 \
  -H 'Host: 127.0.0.1:8080' \
  http://lab.invalid:8080/api/health

Expect the fixed health response. This is a laboratory separation of connection destination from HTTP authority. It is not a production DNS change or a general authentication bypass. --resolve supplies a curl-local address mapping, so this experiment does not prove that any DNS resolver answered. See the manual's resolve option.

Make a diagnostic decision table

Observation Narrow conclusion Still unresolved
Name lookup fails The client did not obtain an address through that attempted method Whether an address-based connection would work
Connection is refused The connection attempt was rejected Which process or network component caused it
Request times out The operation exceeded the configured time budget Drop, delay, path, service or other cause
HTTP 404 An HTTP responder reported a missing resource/route Whether another route exists or permissions hide it
HTTP 403 An HTTP responder denied this request Which rule denied it; inspect the response and configuration
HTTP 200 The responder reported success for this request Whether the returned result obeys the intended authorization rule

Treat the table as an investigation aid, not an automatic diagnosis. For example, a proxy or gateway can answer before the intended application. Correlate the fixture's request ID and server log to establish which application handled your case.

Evidence

Submit the platform/identity record, both permission-mode observations, the three live HTTP results, the stopped-server result, and the two hostname-mapping results. Add a layer diagram from process to destination to HTTP decision. Keep expected and observed results in separate columns.

Acceptance requires explaining why HTTP denial still demonstrates communication with a responder, why the hostname exercise is not a DNS test, and why mode bits alone do not establish another account's effective access.

Safety and scope

Use only your own process metadata, the newly created temporary file, and the bundled loopback server. Do not scan a subnet or change system permissions. The file exercise is POSIX-specific; Windows students can complete the network portion and use a separate approved Linux environment for native Linux work.

Teach-back

  1. Which facts belong to the process, filesystem, transport and application layers?
  2. Why can curl complete an HTTP exchange whose status is an error?
  3. How do you distinguish a configured address mapping from a resolver response?
  4. Which additional test would establish access under a second account?

Continue: Windows and Active Directory, then Kerberos and identity.