Luckily the bash test built-in can check for any of these.
The following script sets the following variables:
suid
sgid
stickybit
To either true or false.
#!/bin/bash
set -e
while read -r line ; do
if ! read -r file_name existing_mode ; then
continue
fi
string_length_existing_mode="${#existing_mode}"
suid=false
sgid=false
stickybit=false
if [ "$string_length_existing_mode" = "4" ]; then
if test -u "$file_name" ; then
suid=true
echo "suid - file_name: '$file_name' | existing_mode: '$existing_mode'"
fi
if test -g "$file_name" ; then
sgid=true
echo "gid - file_name: '$file_name' | existing_mode: '$existing_mode'"
fi
if test -k "$file_name" ; then
stickybit=true
echo "sticky - file_name: '$file_name' | existing_mode: '$existing_mode'"
fi
fi
if [ "$string_length_existing_mode" -gt "4" ]; then
error_code=2
echo "error 2..." >&2
continue
fi
if [ "$string_length_existing_mode" -lt "3" ]; then
error_code=3
echo "error 3..." >&2
continue
fi
done < <( stat -c "%n %a" /usr/bin/* )
I’ve simplified your script above and used it in this. I use stat -c "%n %a %U %G" $(find ${file} -type f) instead of stat -c "%n %a %U %G" ${file}/* as the * won’t find files like /usr/bin/dir/file. It will only look for /usr/bin/file. $(find ...) probably isn’t the correct way to do this though.
I’ve also used --update for dpkg-statoverride instead of chmod/chown.
The while read -r line part in set_file_perms is still breaking due to it parsing empty lines and I don’t know how to fix that.
Some directories like /usr/local/lib/python2.7/site-packages are SGID and removing that might break things.
When executing the script I also get some errors but they don’t seem important.
root@host:/usr/lib/security-misc# ./permission-hardening
dpkg-statoverride: warning: stripping trailing /
dpkg-statoverride: warning: no override present
dpkg-statoverride: warning: stripping trailing /
dpkg-statoverride: warning: no override present
suid - file_name: '/usr/bin/sudo' | existing_mode: '4755'
dpkg-statoverride: warning: stripping trailing /
dpkg-statoverride: warning: no override present
dpkg-statoverride: warning: stripping trailing /
dpkg-statoverride: warning: no override present
ERROR: File '/lib32/' does not exist!
dpkg-statoverride: warning: stripping trailing /
dpkg-statoverride: warning: no override present
ERROR: File '/usr/lib32/' does not exist!
ERROR: File '/usr/lib64/' does not exist!
dpkg-statoverride: warning: stripping trailing /
dpkg-statoverride: warning: no override present
ERROR: File '/usr/local/lib32/' does not exist!
ERROR: File '/usr/local/lib64/' does not exist!
stat: cannot stat '/usr/bin/bwrap/**': Not a directory
stat: cannot stat '/usr/lib/policykit-1/polkit-agent-helper-1/**': Not a directory
stat: cannot stat '/usr/lib/dbus-1.0/dbus-daemon-launch-helper/**': Not a directory
root@host:/usr/lib/security-misc#
There is still a code path where unset nosuid might not be set.
if [ "${mode}" = "nosuid" ]; then
nosuid=true
I’d suggest to add nosuid="" or nosuid=false on top. I.e.
nosuid=""
if [ "${mode}" = "nosuid" ]; then
nosuid=true
Then we could be sure it is reset in any case.
Could you please add the license header?
Need more debugging. I recocommend to set -x at the top or to echo the dpkg-statoverwrite command before executing it.
Because it’s a folder.
if ! [ -e "${file}" ]; then
will return non-zero, i.e. throw that error message. To check for folder
if [ -d "${file}" ]; then
Also we might not call it file but file_system_object since it could be anything (file, folder, device, socket). Also file is a non-ideal name since file is a standard command line tool.
It is probably running:
stat -c "%n %a %U %G" /usr/bin/bwrap/**
stat: cannot stat ‘/usr/bin/bwrap/**’: Not a directory
This won’t work. add_statoverride_entry needs to check if it is a file or a folder.
I’m working on enabling hardening features in security-misc for newer kernel versions (e.g. init_on_{,free,alloc} or lockdown) but I’m having trouble figuring out how to check if the current kernel version is greater or equal to the version the feature was introduced in.
e.g. for lockdown I have
kver="$(uname -r)"
if [ "${kver}" -ge "5.4" ]; then
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX lockdown=confidentiality"
fi
but this fails with an error saying “integer expression expected”.
I think the errors are because the numbers both have dots in them. Removing the dots makes it work fine.
Is this required? What happens when enabling lockdown=confidentiality on a too old kernel? It’s simply ignored? If the answer is yes, then that is not so bad. Or does something break? Well, then the “if” needs to be sorted indeed.
Lockdown specifically won’t break, the parameter will just be ignored, but we do need to compare versions to figure out whether to use init_on_alloc=1 init_on_free=1 or page_poison=1 slub_debug=P.