Articles
SELinux Interview Questions: Diagnose Access Denials Without Disabling Enforcement
Practice SELinux interview questions with a worked AVC denial, persistent file labels, port and boolean decisions, and checks that keep enforcement enabled.
A web server returns “permission denied.” The file is readable, the directory permissions look reasonable, and restarting the service changes nothing. An interviewer asks what you would do next. A useful SELinux answer starts by identifying the denied access and ends by proving a narrow, persistent repair.
The central idea: Unix permissions, SELinux labels, service configuration, and the application's intended behavior answer different questions. Trace all four before deciding which one to change. Disabling enforcement supplies neither a durable diagnosis nor a suitably scoped fix.
Evidence boundary: This guide uses official RHEL 9 documentation and upstream command manuals checked on October 4, 2026. The web-service trace below is an original interview exercise, not output captured from a running host. Policy types and available tools depend on the installed distribution and policy. No candidate reports are used to claim that a particular employer asks these questions.
If you want a broader troubleshooting prompt first, practice How would you troubleshoot Linux services?, then return to the specific denial below.
Why can SELinux reject access when Unix permissions allow it?
Official fact: SELinux provides mandatory access control. In enforcing mode, policy denials are enforced; permissive mode allows accesses that policy would deny while recording relevant audit events. A process domain and an object's security context matter beyond ordinary ownership and mode bits. See the SELinux manual.
For an interview, explain the checks separately. Does the actual service identity have ordinary access to the file and each parent directory? What SELinux domain is the requesting process running in? What label does the object actually carry? Does the active policy permit that domain to perform this operation on this object class and type?
A successful read from an administrator's shell does not answer the service-domain question. Likewise, changing a file to be world-readable cannot establish an SELinux permission. The same pathname can appear in two tests with different identities, domains, namespaces, or mounts. State which test reproduced the failure before interpreting its result.
A compact answer is: “I would correlate the failed service request with an AVC, inspect its source and target contexts, and compare the intended file label with the actual one. I would keep enforcement enabled while testing the scoped repair.”
Read an AVC as an access request, not a command recommendation
Consider this original, abbreviated fixture. Apache serves static content from /srv/interview-site. Assume ordinary file access and directory traversal have already been checked under the service identity. A deployed file retained a home-directory label.
avc: denied { read } for pid=4201 comm="httpd"
path="/srv/interview-site/index.html"
scontext=system_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:user_home_t:s0
tclass=file permissive=0
The line is schematic; a real audit event contains additional fields. Read it as a structured statement:
| Evidence | Interpretation in this exercise | Next check |
|---|---|---|
httpd_t in scontext | The requester is in the web-server domain | Confirm the PID/domain matches the affected service |
user_home_t in tcontext | The file carries a home-content type | Compare its actual and expected labels |
{ read }, tclass=file | The denied operation concerns reading a file | Avoid investigating a port-binding problem first |
permissive=0 | This event describes an enforced denial | Correlate it with the failing request and timestamp |
| File path and process information | Useful correlation clues | Inspect related records in the same audit event |
Inference from the fixture: A label mismatch is a strong hypothesis because static site content and a home-content type do not fit the stated design. It is not proof that every user_home_t denial should be relabeled. The application could be trying to read a private home file that should remain inaccessible.
Use a fresh reproduction window. Official guidance: Red Hat starts denial investigation with Audit records and cautions against generating an allow module before checking labels and service configuration. Its troubleshooting chapter also explains that missing search results require checking the logging path.
getenforce
sudo ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent
ps -eZ
ls -Zd /srv/interview-site
ls -Z /srv/interview-site/index.html
These are diagnostic examples, not commands executed for this article. The ausearch manual documents message-type and time filters and event-oriented output. Record the request time, relevant event identifier, executable, and path. A pile of older denials can send you toward an unrelated repair.
What makes a label repair persistent?
The important distinction is between the label currently stored on an object and the configured label expected for a pathname.
Official fact: chcon changes a file's security context. It does not create a persistent pathname-to-label rule. semanage fcontext manages those rules; restorecon applies the expected context to files. Their manuals describe separate responsibilities: chcon, semanage fcontext, and restorecon.
This distinction gives you a useful follow-up answer. A label changed manually may remain on the same inode across a reboot, yet a subsequent restore operation or replacement file can expose the missing persistent configuration. “Temporary” does not mean that every reboot necessarily erases chcon.
For the exercise, first inspect expected labels with matchpathcon, which compares paths against file-context definitions. Its manual documents verification with -V. Also inspect existing local customizations before adding another rule.
matchpathcon /srv/interview-site/index.html
sudo semanage fcontext -l -C
Official RHEL example, adapted to our path: Static Apache content in a nonstandard directory can use httpd_sys_content_t. The configuration and relabeling are separate steps in Red Hat's nonstandard-service configuration guidance.
# Example assumes this exact local rule does not already exist.
sudo semanage fcontext -a -t httpd_sys_content_t \
'/srv/interview-site(/.*)?'
# Preview label changes, then apply within the intended tree.
sudo restorecon -nRv /srv/interview-site
sudo restorecon -Rv /srv/interview-site
matchpathcon -V /srv/interview-site/index.html
If the exact local rule already exists, review and modify it deliberately rather than repeatedly adding it. Avoid a broad /srv(/.*)? rule when only one subtree is website content. The semanage fcontext manual warns that local rule ordering has special precedence; a newer broad rule can defeat your intended labeling.
Reasoning about scope: This service only needs to read static content. A writable-content type would grant a different class of access and needs a separate design justification. Identify upload or cache directories separately instead of treating every website file as writable.
How do labels, port mappings, booleans, and policy changes differ?
Do not pick a repair solely because a search result contains the word “httpd.” Start with the denied operation and object class.
| Original follow-up | Evidence to inspect | Decision to explain |
|---|---|---|
| The service cannot read static content | File context, expected context, parent directories | Repair a justified label mismatch |
| The service cannot bind its configured port | name_bind, socket class, protocol and port type | Inspect the relevant SELinux port mapping |
| The service cannot connect to its database | Destination, operation, service policy and booleans | Determine whether an existing supported option fits |
| A correctly configured custom service needs new access | Domain, object types, required operations and policy version | Review a minimal policy change with the security owner |
Official fact: semanage port manages SELinux port definitions. A port label is not a firewall rule, and changing it does not establish that a process can bind an occupied socket. Inspect the protocol as well as the port number. See the port-management manual.
For the database case, describe the intended connection before selecting a boolean. Official fact: getsebool displays boolean state. Supported booleans and their meaning are policy-specific; consult the installed service policy documentation instead of enabling every similarly named switch. See getsebool.
Inference: An access attempt that contradicts the service's design could reflect a configuration bug or compromise. A denial is evidence about an attempted operation, not an instruction to authorize it. Generated allow rules need review for their domain, type, class, permission, and expected lifecycle. In a supported RHEL environment, also check the vendor's guidance and support boundaries before adopting a custom module.
What if no AVC appears, or the first fix reveals another denial?
“No matching AVC” is an observation about one search, not a complete verdict about the host. Confirm the time window and machine, check whether the Audit daemon is running, and inspect the relevant journal or available kernel messages. Some denials can be suppressed by dontaudit rules. Changing diagnostic logging and changing enforcement are separate actions; any temporary logging change needs a planned restoration.
A request can also fail through ordinary permissions, application configuration, missing files, mount behavior, or another security layer. Explain what evidence would distinguish these possibilities. Reproducing the request once with a known timestamp is usually more informative than changing several controls together.
In our exercise, fixing the file label might expose a directory-search denial earlier in the path, or the request could now reach an application error. Recheck the exact operation. Do not declare success merely because the original AVC stopped appearing.
A second denial deserves a second diagnosis. It does not automatically justify extending the first repair to a larger subtree or generating permissions for everything the process attempted during an unrelated workload.
Prove the repair through a deployment regression
This original verification matrix distinguishes an operational fix from a one-time successful read:
| Test | Expected result | Why it matters |
|---|---|---|
| Fetch the intended static page under enforcing mode | Correct response from the actual service | Confirms the user-visible operation |
| Verify the page and directory labels | Match the approved file-context rule | Checks the explanation behind the response |
| Replace the page using the real deployment mechanism | Relabel if needed; page remains readable afterward | Exercises newly created or moved files |
| Attempt an unrelated private-file read through the same domain in a controlled test | Remains denied under the intended policy | Detects an overly broad repair |
| Recheck the fresh audit window | No unexplained denial for the intended request | Confirms the diagnosis rather than log disappearance |
State how deployment applies labels. A persistent rule gives relabeling tools a durable target; it does not guarantee that every copying or moving mechanism automatically applies that target. Treat label verification as part of the deployment contract.
A clear interview close is: “The observed requester was httpd_t, the target carried user_home_t, and the operation was file read. For this approved static-content subtree, I configured the expected content type and applied it with restorecon. I would verify the request and a fresh deployment under enforcement, then confirm unrelated access remains restricted.”