policy to systemd
Russell Coker <[email protected]> Sat, 21 Dec 2024 13:23:44 +1100
| Newsgroups | org.kernel.vger.selinux-refpolicy |
|---|---|
| Message-ID | <9420284.CDJkKcVGEf@cupcakke> |
I've attached an early version of a program to generate systemd security settings from SE Linux policy. The aim of this is to lock down daemons on non-SE systems while using tested policy and to also act as a second level of security on SE Linux systems while giving a lower score for "systemd-analyze security". Anyone have any ideas for how to automatically determine SystemCallFilter values from policy? -- My Main Blog http://etbe.coker.com.au/ My Documents Blog http://doc.coker.com.au/
pol2systemd.pl
(application/x-perl, 4.1 KB)
#!/usr/bin/perl
use strict;
# takes a single parameter of a domain for a daemon and generates systemd
# security rules based on the SE Linux policy
my @RestrictAddressFamilies;
push @RestrictAddressFamilies, "AF_NETLINK";
my @SystemCallFilter;
my %cfg;
foreach ('PrivateDevices', 'RestrictSUIDSGID', 'ProtectHome', 'ProtectClock', 'MemoryDenyWriteExecute', 'RestrictNamespaces', 'ProtectKernelLogs', 'ProtectControlGroups', 'ProtectKernelModules', 'ProtectHostname', 'ProtectKernelTunables', 'PrivateTmp', 'NoNewPrivileges')
{
$cfg{$_} = "true";
}
my $CapabilityBoundingSet = "";
open(TRANS, "sesearch -T -s $ARGV[0] -c process|") or die "Can't run sesearch";
while(<TRANS>)
{
$cfg{NoNewPrivileges} = "false";
}
close(TRANS);
open(ALLOW, "sesearch -A -s $ARGV[0]|") or die "Can't run sesearch";
while(<ALLOW>)
{
chomp;
# remove boolean checks, anything allowed with any boolean is added
$_ =~ s/ \[.*$//;
# remove trailing ;
$_ =~ s/;//;
if($_ =~ ":capability ")
{
$_ =~ s/^.*:capability //;
$CapabilityBoundingSet .= $_;
if($CapabilityBoundingSet =~ "CAP_MKNOD")
{
$cfg{PrivateDevices} = "false";
}
next;
}
if($_ =~ ":chr_file ")
{
if($_ =~ "console_device_t" or $_ =~ "_devpts_t" or $_ =~ "ptynode" or $_ =~ "tty_device_t" or $_ =~ "ttynode" or $_ =~ "devtty_t" or $_ =~ "null_device_t" or $_ =~ "urandom_device_t" or $_ =~ "zero_device_t")
{
next;
}
$cfg{PrivateDevices} = "false";
next;
}
if($_ =~ ":blk_file ")
{
$cfg{PrivateDevices} = "false";
next;
}
if($_ =~ /exec_t.*relabel/)
{
$cfg{RestrictSUIDSGID} = "false";
}
if($_ =~ /:tmp_t/)
{
$cfg{PrivateTmp} = "false";
}
if($_ =~ "home_root_t" or $_ =~ "user_home_dir_t")
{
if(not $_ =~ "nsswitch_domain")
{
$cfg{ProtectHome} = "false";
}
next;
}
if($_ =~ /process.*execmem/)
{
$cfg{MemoryDenyWriteExecute} = "false";
next;
}
if($_ =~ /cap_userns/ or $_ =~ /cap2_userns/)
{
$cfg{RestrictNamespaces} = "false";
next;
}
if($_ =~ /cgroup.*write/)
{
$cfg{ProtectControlGroups} = "false";
next;
}
if($_ =~ /kernel_t:system module_request/)
{
$cfg{ProtectKernelModules} = "false";
next;
}
if($_ =~ /sysctl_.*write/)
{
$cfg{ProtectKernelTunables} = "false";
next;
}
if($_ =~ /udp_socket/ or $_ =~ /tcp_socket/)
{
push @RestrictAddressFamilies, "AF_INET AF_INET6";
next;
}
if($_ =~ /unix_.*_socket/)
{
push @RestrictAddressFamilies, "AF_UNIX";
next;
}
if($_ =~ /packet_socket/)
{
push @RestrictAddressFamilies, "AF_PACKET";
next;
}
}
close(ALLOW);
my $ProtectSystem = "strict";
open(STRICTWRITE, "(sesearch -A -s $ARGV[0] -c dir -p write ; sesearch -A -s $ARGV[0] -c file -p write)|") or die "Can't run sesearch";
while(<STRICTWRITE>)
{
$ProtectSystem = "full";
open(ETC, "(sesearch -A -s $ARGV[0] -t configfile -c dir -p write ; sesearch -A -s $ARGV[0] -t configfile -c file -p write)|") or die "Can't run sesearch";
while(<ETC>)
{
$ProtectSystem = "true";
last;
}
close(ETC);
last;
}
close(STRICTWRITE);
$CapabilityBoundingSet =~ s/[\{\}]/ /g;
$CapabilityBoundingSet =~ s/ / /g;
$CapabilityBoundingSet = uc($CapabilityBoundingSet);
$CapabilityBoundingSet = join(" CAP_", split(/ /, $CapabilityBoundingSet));
if (length($CapabilityBoundingSet) > 0)
{
$CapabilityBoundingSet = "CAP_" . $CapabilityBoundingSet;
}
if($CapabilityBoundingSet =~ "CAP_SETGID" or $CapabilityBoundingSet =~ "CAP_SETUID")
{
$cfg{RestrictSUIDSGID} = "false";
}
if($CapabilityBoundingSet =~ "CAP_SYS_TIME")
{
$cfg{ProtectClock} = "false";
}
if($CapabilityBoundingSet =~ "CAP_SYSLOG")
{
$cfg{ProtectKernelLogs} = "false";
}
if($CapabilityBoundingSet =~ "CAP_SYS_ADMIN")
{
$cfg{ProtectHostname} = "false";
}
print "CapabilityBoundingSet=$CapabilityBoundingSet\n";
print "ProtectSystem=$ProtectSystem\n";
foreach (keys(%cfg))
{
print "$_=$cfg{$_}\n";
}
# from https://perlmaven.com/unique-values-in-an-array-in-perl
sub uniq
{
my %h = map { $_ => 1 } @_;
keys %h
};
my $res = join(" ", uniq(@RestrictAddressFamilies));
print "RestrictAddressFamilies=$res\n";