Learn SELinux - NFS, Samba & Network Services
Episode 11 of 23

Learn SELinux - NFS, Samba & Network Services

Securing network services with SELinux: NFS labeling and mount options including noexec, the consequences of storage shared between hosts, samba booleans and contexts for exporting directories and homes, and port labeling for non-standard services.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 10, you protected containers — but data still has to move between hosts. File sharing through NFS and Samba is the backbone of enterprise environments: shared storage for applications, user home directories, and data used by many servers at once. Unfortunately, once data crosses the network, the SELinux labeling rules you've learned become more complicated.

This episode 11 covers three things: how labels survive (or don't) on NFS, how Samba interacts with file types and booleans, and port labeling for non-standard services.

NFS and Labeling: Who Holds the Label?

On a local filesystem, file labels are determined and managed by the host itself. With NFS, the story is different: exported files don't carry the SELinux labeling system automatically. As a consequence, from the client's side, NFS files appear with a special type called nfs_t:

View file labels on an NFS mount
ls -Z /mnt/web/index.html

The problem is that nfs_t is a very permissive type: almost all domains are allowed to read it. For ordinary data that's fine, but for sensitive data it's an open invitation. Labeling with semanage fcontext on the client side has no effect on NFS files — labels come from the server, not the client.

The solution is to force the label at mount time with the context option:

Mount NFS with a forced context
sudo mount -t nfs -o context="system_u:object_r:httpd_sys_content_t:s0" server:/export /mnt/web

Important

The context= option forces the entire share contents to use one identical type — low flexibility, but that's exactly its strength: you know precisely who's allowed to read that data. Alternatively, use NFS with NFS labeling (security labels) support when both sides and the filesystems support it, so labels are sent from the server along with every file. Unfortunately not all kernels and filesystems are ready, so context= remains the most portable choice.

noexec on Data Shares

Note that NFS allows binary execution from a mount by default. For shares that only store data (backup, upload, archives), execution is pure risk: an attacker who manages to drop a binary on the share doesn't need extra effort to run it. Mounting with noexec closes that gap:

LinuxMount NFS data without execution
sudo mount -t nfs -o noexec,nodev,nosuid server:/data /mnt/data

Also combine nodev and nosuid for general-purpose shares. The rule of thumb: shares whose contents aren't programs — always noexec.

The Consequences of Shared Storage

One directory shared by many hosts carries labeling consequences that often go unnoticed:

  • Cross-host consistency. Host A writes files with a certain context, host B reads them. If the two hosts use different context= options, the result is a confusing denial on one side. Set one standard context per share, and propagate it to all hosts.
  • The MCS level travels along. A share with the category level s0:c1 can only be read by hosts or processes whose level matches. Make sure all share consumers have the same level range, or MCS denials will appear silently.
  • Relabeling on the client is useless. restorecon on the client side doesn't change NFS file labels. Label changes must go through the server or mount options — don't waste debugging time in the wrong direction.

Warning

Don't treat an NFS share as a "just dump it there" place without thinking about level and type. Two hosts with different policies writing to the same share is one of the hardest SELinux denials to diagnose in production — because the error appears on the side that isn't writing. Document the type and level of every share, and apply it with provisioning tooling so it's consistent from the start.

Samba: Booleans and Contexts

Samba (the SMB/CIFS protocol) exports Linux directories to Windows and Linux clients. The smbd daemon runs in the smbd_t domain, and its rules follow the patterns you already know: shared directories must have a special label, and booleans control the scope of exports.

Dedicated share directories are labeled samba_share_t:

Prepare a samba share directory
sudo semanage fcontext -a -t samba_share_t "/srv/share(/.*)?"
sudo restorecon -Rv /srv/share

After that, add the directory to the Samba configuration and smbd_t can read its contents. Three main booleans control the export scope:

NeedSolution
Export user home directoriessamba_enable_home_dirs on
Export all files smbd can readsamba_export_all_ro on
Export all files with write accesssamba_export_all_rw on

User homes need a special boolean because home directories are labeled user_home_t — a type smbd_t may not read by default. Enabling samba_enable_home_dirs lets smbd into homes in a controlled way:

Allow samba to access user homes
sudo setsebool -P samba_enable_home_dirs on

Tip

samba_export_all_rw and samba_export_all_ro are emergency doors: they allow smbd to read almost all files on the system, not just directories labeled samba_share_t. Use them only for short-term migration, then switch to proper directory labeling. A permanent "export all" is the same as opening up SELinux for the entire Samba service.

Port Labeling for Non-Standard Services

The principle you learned in episode 9 applies to all network services: a port the policy doesn't know is a port without a label, and a domain trying to bind or connect to it will hit a name_bind or name_connect denial. Look at the port labels already known:

View samba and NFS port labels
semanage port -l | grep -E 'smbd|nfs'

Standard ports are already labeled: smbd_port_t for 139 and 445, nfsd_port_t for 2049. When a service runs on a non-standard port — for example Samba on port 4450 or a web app on 8080 — add a new label:

Label non-standard ports
sudo semanage port -a -t smbd_port_t -p tcp 4450
sudo semanage port -a -t http_port_t -p tcp 8080

Note

Think of ports as a building's entry doors. The SELinux policy has a list of "official doors" for each domain: http_port_t for httpd, smbd_port_t for samba, and so on. Opening a new door without registering it in semanage port makes the security guard (SELinux) refuse anyone passing through — even though everything looks normal at the UNIX permission level. This is the source of the most confusing denials for those who don't yet understand it.

Closing

In this episode 11, you've understood the uniqueness of cross-network labeling: NFS files labeled with the permissive nfs_t and the context= solution at mount time with noexec, the consequences of sharing storage between hosts with different policies, samba booleans and the samba_share_t context for Samba exports, and non-standard port labeling with semanage port.

The key takeaways:

  • NFS labels come from the server; on the client use the context= option and noexec for data.
  • A share used by many hosts must have documented, consistent types and levels.
  • Connect non-standard services to the policy via semanage port, not by turning off SELinux.

Starting with this episode, we shift from securing built-in services to building protection for special cases. In episode 12, we'll discuss Virtualization & Custom Policies — protecting the KVM hypervisor and virtual machines, and writing custom policies from scratch for applications that have no built-in policy.

Learn SELinux - NFS, Samba & Network Services | Learn SELinux