Skip to content

Commit 5271d18

Browse files
committed
Create SELinux policy for netatalk daemons, GitHub #2113
1 parent c567147 commit 5271d18

File tree

6 files changed

+384
-0
lines changed

6 files changed

+384
-0
lines changed

distrib/selinux/README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Netatalk SELinux Policy Module
2+
3+
This directory contains a SELinux policy module for Netatalk that provides security contexts and rules for
4+
running Netatalk services on SELinux-enabled systems.
5+
6+
## Quick Start
7+
8+
To build and install the policy module:
9+
10+
```shell
11+
./netatalk.sh
12+
```
13+
14+
This will compile the policy, install it, and generate an RPM package for distribution.
15+
16+
## Policy Overview
17+
18+
The policy defines the following security contexts:
19+
20+
- _netatalk_t_ - Domain for Netatalk processes
21+
- _netatalk_exec_t_ - Type for executable files
22+
- _netatalk_etc_t_ - Type for configuration files
23+
- _netatalk_var_lib_t_ - Type for variable data
24+
- _netatalk_lock_t_ - Type for lock files
25+
- _netatalk_log_t_ - Type for log files
26+
27+
## Troubleshooting
28+
29+
If you encounter AVC denials, you can update the policy by running:
30+
31+
```shell
32+
./netatalk.sh --update
33+
```
34+
35+
This will analyze the audit log for new required permissions and offer to update the policy accordingly.
36+
37+
## Further Reading
38+
39+
For detailed information about SELinux policies and security contexts:
40+
41+
- [SELinux Project Wiki](https://github.com/SELinuxProject/selinux/wiki)
42+
- [Red Hat SELinux Guide](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/using_selinux/index)
43+
- [Fedora SELinux Guide](https://docs.fedoraproject.org/en-US/quick-docs/getting-started-with-selinux/)

distrib/selinux/netatalk.fc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Netatalk executables - all run in the same domain due to forking structure
2+
/usr/sbin/netatalk -- gen_context(system_u:object_r:netatalk_exec_t,s0)
3+
/usr/sbin/afpd -- gen_context(system_u:object_r:netatalk_exec_t,s0)
4+
/usr/sbin/cnid_metad -- gen_context(system_u:object_r:netatalk_exec_t,s0)
5+
/usr/sbin/cnid_dbd -- gen_context(system_u:object_r:netatalk_exec_t,s0)
6+
7+
# Configuration files
8+
/etc/netatalk(/.*)? gen_context(system_u:object_r:netatalk_etc_t,s0)
9+
/etc/netatalk/afp\.conf -- gen_context(system_u:object_r:netatalk_etc_t,s0)
10+
/etc/netatalk/dbus-session\.conf -- gen_context(system_u:object_r:netatalk_etc_t,s0)
11+
/etc/netatalk/extmap\.conf -- gen_context(system_u:object_r:netatalk_etc_t,s0)
12+
13+
# Variable data
14+
/var/lib/netatalk/CNID(/.*)? gen_context(system_u:object_r:netatalk_var_lib_t,s0)
15+
/var/lib/netatalk/afp_signature\.conf -- gen_context(system_u:object_r:netatalk_var_lib_t,s0)
16+
/var/lib/netatalk/afp_voluuid\.conf -- gen_context(system_u:object_r:netatalk_var_lib_t,s0)
17+
/var/lock/netatalk(/.*)? gen_context(system_u:object_r:netatalk_lock_t,s0)
18+
19+
# Log files
20+
/var/log/netatalk\.log -- gen_context(system_u:object_r:netatalk_log_t,s0)
21+
/var/log/netatalk(/.*)? gen_context(system_u:object_r:netatalk_log_t,s0)

distrib/selinux/netatalk.if

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
2+
## <summary>policy for netatalk</summary>
3+
4+
########################################
5+
## <summary>
6+
## Execute netatalk_exec_t in the netatalk domain.
7+
## </summary>
8+
## <param name="domain">
9+
## <summary>
10+
## Domain allowed to transition.
11+
## </summary>
12+
## </param>
13+
#
14+
interface(`netatalk_domtrans',`
15+
gen_require(`
16+
type netatalk_t, netatalk_exec_t;
17+
')
18+
19+
corecmd_search_bin($1)
20+
domtrans_pattern($1, netatalk_exec_t, netatalk_t)
21+
')
22+
23+
########################################
24+
## <summary>
25+
## Execute netatalk in the caller domain.
26+
## </summary>
27+
## <param name="domain">
28+
## <summary>
29+
## Domain allowed access.
30+
## </summary>
31+
## </param>
32+
#
33+
interface(`netatalk_exec',`
34+
gen_require(`
35+
type netatalk_exec_t;
36+
')
37+
38+
corecmd_search_bin($1)
39+
can_exec($1, netatalk_exec_t)
40+
')
41+
42+
########################################
43+
## <summary>
44+
## Read netatalk configuration files.
45+
## </summary>
46+
## <param name="domain">
47+
## <summary>
48+
## Domain allowed access.
49+
## </summary>
50+
## </param>
51+
#
52+
interface(`netatalk_read_config',`
53+
gen_require(`
54+
type netatalk_etc_t;
55+
')
56+
57+
files_search_etc($1)
58+
allow $1 netatalk_etc_t:dir list_dir_perms;
59+
allow $1 netatalk_etc_t:file read_file_perms;
60+
')
61+
62+
########################################
63+
## <summary>
64+
## Manage netatalk log files.
65+
## </summary>
66+
## <param name="domain">
67+
## <summary>
68+
## Domain allowed access.
69+
## </summary>
70+
## </param>
71+
#
72+
interface(`netatalk_manage_log',`
73+
gen_require(`
74+
type netatalk_log_t;
75+
')
76+
77+
logging_search_logs($1)
78+
allow $1 netatalk_log_t:dir rw_dir_perms;
79+
allow $1 netatalk_log_t:file manage_file_perms;
80+
')
81+
82+
# Additional rules for the new types
83+
allow netatalk_t netatalk_etc_t:dir list_dir_perms;
84+
allow netatalk_t netatalk_etc_t:file read_file_perms;
85+
86+
allow netatalk_t netatalk_var_lib_t:dir manage_dir_perms;
87+
allow netatalk_t netatalk_var_lib_t:file manage_file_perms;
88+
89+
allow netatalk_t netatalk_lock_t:dir manage_dir_perms;
90+
allow netatalk_t netatalk_lock_t:file manage_file_perms;
91+
92+
allow netatalk_t netatalk_log_t:dir manage_dir_perms;
93+
allow netatalk_t netatalk_log_t:file manage_file_perms;

distrib/selinux/netatalk.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/sh -e
2+
3+
DIRNAME=$(dirname $0)
4+
cd $DIRNAME
5+
USAGE="$0 [ --update ]"
6+
if [ $(id -u) != 0 ]; then
7+
echo 'You must be root to run this script'
8+
exit 1
9+
fi
10+
11+
if [ $# -eq 1 ]; then
12+
if [ "$1" = "--update" ]; then
13+
time=$(ls -l --time-style="+%x %X" netatalk.te | awk '{ printf "%s %s", $6, $7 }')
14+
rules=$(ausearch --start $time -m avc --raw -se netatalk)
15+
if [ x"$rules" != "x" ]; then
16+
echo "Found avc's to update policy with"
17+
echo -e "$rules" | audit2allow -R
18+
echo "Do you want these changes added to policy [y/n]?"
19+
read ANS
20+
if [ "$ANS" = "y" -o "$ANS" = "Y" ]; then
21+
echo "Updating policy"
22+
echo -e "$rules" | audit2allow -R >> netatalk.te
23+
# Fall though and rebuild policy
24+
else
25+
exit 0
26+
fi
27+
else
28+
echo "No new avcs found"
29+
exit 0
30+
fi
31+
else
32+
echo -e $USAGE
33+
exit 1
34+
fi
35+
elif [ $# -ge 2 ]; then
36+
echo -e $USAGE
37+
exit 1
38+
fi
39+
40+
echo "Building and Loading Policy"
41+
set -x
42+
make -f /usr/share/selinux/devel/Makefile netatalk.pp || exit
43+
/usr/sbin/semodule -i netatalk.pp
44+
45+
# Generate a man page of the installed module
46+
sepolicy manpage -p . -d netatalk_t
47+
# Fixing the file context on /usr/local/sbin/netatalk
48+
/sbin/restorecon -F -R -v /usr/sbin/netatalk
49+
# Generate a rpm package for the newly generated policy
50+
51+
pwd=$(pwd)
52+
rpmbuild --define "_sourcedir ${pwd}" --define "_specdir ${pwd}" --define "_builddir ${pwd}" --define "_srcrpmdir ${pwd}" --define "_rpmdir ${pwd}" --define "_buildrootdir ${pwd}/.build" -ba netatalk_selinux.spec

distrib/selinux/netatalk.te

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
policy_module(netatalk, 1.0.0)
2+
3+
########################################
4+
#
5+
# Declarations
6+
#
7+
8+
type netatalk_t;
9+
type netatalk_exec_t;
10+
init_daemon_domain(netatalk_t, netatalk_exec_t)
11+
12+
# Ensure proper entrypoint
13+
allow netatalk_t netatalk_exec_t:file entrypoint;
14+
15+
# Allow netatalk to execute and transition to its child daemons
16+
# This handles the forking structure: netatalk -> afpd, cnid_metad -> cnid_dbd
17+
allow netatalk_t netatalk_exec_t:file execute;
18+
domtrans_pattern(netatalk_t, netatalk_exec_t, netatalk_t)
19+
20+
# Configuration files
21+
type netatalk_etc_t;
22+
files_config_file(netatalk_etc_t)
23+
24+
# Variable library files
25+
type netatalk_var_lib_t;
26+
files_type(netatalk_var_lib_t)
27+
28+
# Lock files
29+
type netatalk_lock_t;
30+
files_lock_file(netatalk_lock_t)
31+
32+
# Log files
33+
type netatalk_log_t;
34+
logging_log_file(netatalk_log_t)
35+
36+
########################################
37+
#
38+
# netatalk local policy
39+
#
40+
41+
# Basic process and IPC permissions
42+
allow netatalk_t self:process { fork signal_perms };
43+
allow netatalk_t self:fifo_file rw_fifo_file_perms;
44+
allow netatalk_t self:unix_stream_socket create_stream_socket_perms;
45+
46+
# Process management for forking daemons
47+
allow netatalk_t self:process { setrlimit setpgid setsched };
48+
49+
# Allow netatalk to bind to privileged ports
50+
allow netatalk_t self:capability net_bind_service;
51+
52+
# Socket permissions
53+
allow netatalk_t self:netlink_route_socket { bind create getattr nlmsg_read };
54+
allow netatalk_t self:tcp_socket { bind create ioctl listen setopt };
55+
allow netatalk_t self:udp_socket { connect create getattr };
56+
allow netatalk_t self:unix_dgram_socket { connect create };
57+
58+
# Core command execution and binary mapping
59+
corecmd_exec_bin(netatalk_t)
60+
corecmd_exec_shell(netatalk_t)
61+
corecmd_mmap_bin_files(netatalk_t)
62+
63+
# Network binding permissions
64+
corenet_tcp_bind_dhcpd_port(netatalk_t)
65+
corenet_tcp_bind_generic_node(netatalk_t)
66+
corenet_tcp_bind_generic_port(netatalk_t)
67+
corenet_udp_bind_generic_node(netatalk_t)
68+
corenet_udp_bind_generic_port(netatalk_t)
69+
70+
# D-Bus communication
71+
dbus_read_pid_sock_files(netatalk_t)
72+
dbus_stream_connect_system_dbusd(netatalk_t)
73+
dbus_write_pid_sock_files(netatalk_t)
74+
75+
# File and lock management
76+
files_create_lock_dirs(netatalk_t)
77+
files_manage_generic_locks(netatalk_t)
78+
files_rw_var_files(netatalk_t)
79+
files_search_locks(netatalk_t)
80+
files_read_etc_files(netatalk_t)
81+
82+
# Kernel communication
83+
kernel_dgram_send(netatalk_t)
84+
kernel_read_proc_files(netatalk_t)
85+
kernel_read_system_state(netatalk_t)
86+
87+
# Logging
88+
logging_create_devlog_dev(netatalk_t)
89+
logging_read_syslog_pid(netatalk_t)
90+
logging_send_syslog_msg(netatalk_t)
91+
92+
# System network configuration
93+
sysnet_read_config(netatalk_t)
94+
95+
# Interactive and standard daemon permissions
96+
domain_use_interactive_fds(netatalk_t)
97+
98+
# Allow systemd to transition to netatalk
99+
init_domtrans_script(netatalk_exec_t)
100+
101+
# Additional permissions that might be needed
102+
auth_use_nsswitch(netatalk_t)
103+
miscfiles_read_localization(netatalk_t)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# vim: sw=4:ts=4:et
2+
3+
4+
%define relabel_files() \
5+
restorecon -R /usr/sbin/netatalk; \
6+
7+
%define selinux_policyver 41.44-1
8+
9+
Name: netatalk_selinux
10+
Version: 1.0
11+
Release: 1%{?dist}
12+
Summary: SELinux policy module for netatalk
13+
14+
Group: System Environment/Base
15+
License: GPLv2+
16+
URL: http://HOSTNAME
17+
Source0: netatalk.pp
18+
Source1: netatalk.if
19+
Source2: netatalk_selinux.8
20+
21+
22+
Requires: policycoreutils-python-utils, libselinux-utils
23+
Requires(post): selinux-policy-base >= %{selinux_policyver}, policycoreutils-python-utils
24+
Requires(postun): policycoreutils-python-utils
25+
BuildArch: noarch
26+
27+
%description
28+
This package installs and sets up the SELinux policy security module for netatalk.
29+
30+
%install
31+
install -d %{buildroot}%{_datadir}/selinux/packages
32+
install -m 644 %{SOURCE0} %{buildroot}%{_datadir}/selinux/packages
33+
install -d %{buildroot}%{_datadir}/selinux/devel/include/contrib
34+
install -m 644 %{SOURCE1} %{buildroot}%{_datadir}/selinux/devel/include/contrib/
35+
install -d %{buildroot}%{_mandir}/man8/
36+
install -m 644 %{SOURCE2} %{buildroot}%{_mandir}/man8/netatalk_selinux.8
37+
install -d %{buildroot}/etc/selinux/targeted/contexts/users/
38+
39+
40+
%post
41+
semodule -n -i %{_datadir}/selinux/packages/netatalk.pp
42+
43+
if [ $1 -eq 1 ]; then
44+
45+
fi
46+
if /usr/sbin/selinuxenabled ; then
47+
/usr/sbin/load_policy
48+
%relabel_files
49+
fi;
50+
exit 0
51+
52+
%postun
53+
if [ $1 -eq 0 ]; then
54+
55+
semodule -n -r netatalk
56+
if /usr/sbin/selinuxenabled ; then
57+
/usr/sbin/load_policy
58+
%relabel_files
59+
fi;
60+
fi;
61+
exit 0
62+
63+
%files
64+
%attr(0600,root,root) %{_datadir}/selinux/packages/netatalk.pp
65+
%{_datadir}/selinux/devel/include/contrib/netatalk.if
66+
%{_mandir}/man8/netatalk_selinux.8.*
67+
68+
69+
%changelog
70+
* Fri Jun 27 2025 Daniel Markstedt <[email protected]> 1.0-1
71+
- Initial version
72+

0 commit comments

Comments
 (0)