You configured Samba and Windows says Access Denied
You added a share to smb.conf and restarted the service. The Windows client sees the share, but clicking it returns Access Denied. Or the share appears, you can read files, but saving a document fails with a permission error. You checked the Linux file permissions. They look correct. You even ran chmod 777 on the directory just to test, and the error persists.
The culprit is SELinux. It is blocking the smbd process from touching the files, even though the filesystem permissions allow it. SELinux enforces Mandatory Access Control. It checks labels on processes and files before allowing access. If the labels do not match the policy, the access is denied. The denial happens silently in the application. You see the error on the client, but the Fedora terminal shows nothing wrong.
What's actually happening
Linux file permissions control access based on user and group ownership. SELinux adds a second layer. It controls what processes can do based on security contexts attached to files and processes. Think of file permissions as the key to the door. SELinux is the security guard checking your badge. You can have the right key, but if your badge does not match the zone, the guard stops you.
Samba runs in a confined domain called smbd_t. By default, this domain is only allowed to access files labeled for Samba. The standard label for Samba shares is samba_share_t. Home directories carry a different label, usually user_home_t. Custom directories might have default_t or public_content_t depending on where you created them. When smbd tries to read or write a file with the wrong label, SELinux denies the operation. The denial is logged in the audit subsystem. The client receives a generic permission error.
SELinux also uses booleans. These are switches defined in the policy that toggle specific behaviors without writing custom rules. The boolean samba_enable_home_dirs controls whether Samba is allowed to access user home directories. It is off by default for security. Enabling it tells SELinux to trust Samba with home directories. This is safer than relaxing the entire policy.
Check the boolean before you edit permissions. SELinux denials happen silently in the app logs.
Enable home directory sharing
If you are sharing user home directories, you need to enable the boolean. This allows Samba to access directories under /home.
Run this command to check the current state.
# Check if the boolean is currently off. This tells you if SELinux is the blocker.
getsebool samba_enable_home_dirs
If the output shows samba_enable_home_dirs --> off, enable it permanently.
# -P writes the change to disk so it survives reboots. Without -P, the setting resets on restart.
sudo setsebool -P samba_enable_home_dirs on
The -P flag is essential. It persists the change to the SELinux configuration store. Without it, the boolean reverts to off after a reboot. You will spend hours debugging a share that works until the server restarts.
Verify the change took effect.
# Confirm the boolean is now on. The output should show samba_enable_home_dirs --> on.
getsebool samba_enable_home_dirs
Home directories use the user_home_t label. The boolean allows smbd_t to access user_home_t. You do not need to change file labels for home directories. The boolean handles the cross-domain access.
Run getsebool immediately after the change. The setting applies instantly without a service restart.
Fix custom share directories
If you are sharing a custom directory like /srv/samba/data or /var/shared, the boolean does not help. The directory needs the correct SELinux context. Samba expects files to be labeled samba_share_t.
First, check the current label on your share directory.
# -Z shows the SELinux context. Look for the type at the end of the output.
ls -ldZ /path/to/share
If the output shows a type other than samba_share_t, the label is wrong. You might see default_t, var_t, or public_content_t. Restore the correct label using restorecon.
# -R applies recursively. -v prints what changes. This fixes the label on the directory and its contents.
sudo restorecon -Rv /path/to/share
restorecon looks up the policy rules and applies the default label for the path. For standard Samba paths, the policy knows to use samba_share_t. If the directory is new or in a non-standard location, restorecon might not change anything because the policy has no rule for that path.
If restorecon does not fix the label, you need to define a custom file context rule. This tells SELinux what label to apply to your specific path.
# -a adds a new rule. -t sets the type. This tells SELinux that /srv/samba/data should be samba_share_t.
sudo semanage fcontext -a -t samba_share_t "/srv/samba/data(/.*)?"
After adding the rule, run restorecon again to apply it.
# Apply the new rule to the filesystem. The label changes immediately.
sudo restorecon -Rv /srv/samba/data
Verify the label is now correct.
# Confirm the type is samba_share_t. The output should end with samba_share_t.
ls -ldZ /srv/samba/data
Never use chcon for permanent fixes. chcon changes the label on the filesystem directly. It does not update the policy. The change vanishes after a relabel or package update. Use semanage fcontext to define the rule, then restorecon to apply it. The rule survives relabels.
Trust the policy defaults. Custom labels drift over time, booleans stay stable.
Verify the fix and check logs
After enabling the boolean or fixing the context, test the share from the client machine. Local root access can mask SELinux denials. Root often bypasses DAC checks, and some tools run with elevated privileges. The client test proves the configuration works for normal users.
If the share is still blocked, check the SELinux logs. Denials are recorded in the audit log. The setroubleshoot service summarizes them in plain text.
# -t setroubleshoot filters for the SELinux summary messages. This is easier to read than raw AVC denials.
journalctl -t setroubleshoot | tail -20
Look for messages mentioning smbd and samba_share_t. The summary explains what was denied and suggests a fix. If you see a denial for write or open, the context is likely still wrong. If you see a denial for search on /home, the boolean might be off.
You can also search for raw AVC denials. These are the low-level records.
# grep for smbd denials in the journal. This shows the exact operation that was blocked.
journalctl | grep "avc: denied" | grep smbd | tail -10
Raw denials show the process, operation, and target context. They are harder to read but useful when setroubleshoot is not installed. The setroubleshoot package is included in Fedora Workstation. Server installations might need it installed.
Check the firewall if SELinux is not the issue. Samba requires ports 139 and 445. Fedora's firewall blocks these by default.
# Add the samba service to the firewall. This opens the required ports permanently.
sudo firewall-cmd --permanent --add-service=samba
sudo firewall-cmd --reload
Run firewall-cmd --reload after every rule change. The runtime configuration and persistent configuration diverge otherwise. You might add a rule and wonder why it does not work until you reload.
Test from the client machine. Local root access can mask SELinux denials if you are not careful.
Common pitfalls and error patterns
Forgetting the -P flag on setsebool is the most common mistake. The boolean works until reboot. The share breaks after an update or restart. You assume the configuration drifted. It did not. The boolean reset. Always use -P for permanent changes.
Using chcon instead of semanage creates fragile setups. chcon changes the label on disk. It does not update the policy database. When restorecon runs during a package update or manual relabel, it overwrites the chcon change with the policy default. The share breaks again. Use semanage fcontext to define the rule. The rule persists.
Editing the wrong smb.conf file causes confusion. Fedora keeps the main configuration in /etc/samba/smb.conf. Files in /usr/lib/samba ship with the package. Do not edit files in /usr/lib. Changes there are overwritten by updates. Edit /etc. The package manager respects user modifications in /etc.
Ignoring the firewall leads to false positives. You fix SELinux, but the client still cannot connect. The firewall drops the packets. You blame SELinux again. Check the firewall. Run firewall-cmd --list-all to see active services. If samba is not in the list, the ports are closed.
Misinterpreting Access Denied errors wastes time. Windows clients report Access Denied for many reasons. It could be SMB protocol version mismatch, user authentication failure, or network path issues. Check the Samba logs in /var/log/samba/. Look for auth errors or NT_STATUS_ACCESS_DENIED. SELinux denials appear in the audit log, not the Samba logs. Correlate the timestamps. If the Samba log shows a connection but the audit log shows a denial at the same time, SELinux is the blocker.
Run journalctl -xe first. Read the actual error before guessing.
When to use this vs alternatives
Use setsebool when you need to toggle a global policy switch like home directory access. Use restorecon when a directory has the wrong label but the policy defines a correct default. Use semanage fcontext when you are creating a new share path that the policy does not know about yet. Use chcon only for temporary debugging that you will revert immediately. Disable SELinux only when you are running unconfined legacy software that cannot be labeled and you accept the security risk.
Trust the package manager. Manual file edits drift, snapshots stay.