The sudo command is available on many UNIX platforms and is a default part of most major Linux distributions. It provides a way for regular users to run commands as superusers without permanently compromising the system.
In this tutorial, we take a look at system permissions, how they can affect stability, and how to restore them in case of issues. Our main example is an error that sudo might throw upon invocation. First, we talk about permissions in general. Next, we check what problems are associated with incorrect permissions. After that, we focus on sudo as a concrete example. Finally, we explore system-wide permissions corruption and how we can deal with it.
We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments.
The Linux installation process usually initializes these settings as metadata in the filesystem. Yet, the filesystem configuration is fluent and changes as we use the system.
For example, installing packages, extracting files, and downloading files can all contribute to new file permission settings. Of course, we can also manually change them with the standard chown and chmod commands.
However, doing so can be dangerous due to the possible negative effects in many areas:
- system configuration
- manual and tool-based file and directory handling
- remote access
- general security
- system stability
In other words, since everything is a file in Linux, and permissions usually belong to the file level, they can affect all parts of a system.
3. Problems with Permissions
Lack of control or too much of it over certain areas of an installation can be detrimental. In fact, this can lead to many related problems:
- preventing the use of certain tools directly or indirectly
- startup problems due to the incorrect removal of the x executable flag
- system lockout
Although we can sometimes bypass permission problems, they shouldn’t be ignored. But how do permissions become incorrect in the first place?
Commonly, mistakes can happen when we try to recursively change directory permissions:
# chown --recursive baeldung /$VAR # chown -R user1 /$VAR
In the simple commands above, just having an empty variable such as $VAR after a / slash or using the latter instead of a period (.) can run chown or chmod over the whole root filesystem. This has a grave impact on all mounted filesystems, every system directory like /dev and /etc, but also /opt and any other objects under /.
Further, after such an action, tools critical to the usage of a Linux installation can become unusable.
4. sudo Permissions Issues
In fact, both of them rely on the proper permission settings to deny random actors from manipulating the system. Otherwise, we may end up with an error:
$ sudo test sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set
First, /usr/bin/sudo is the location of our sudo binary. While this is usually the default path, it can vary. Next, we see uid, short for user ID. Moreover, uid 0 designates root.
Finally, the setuid mechanism is activated by setting the setuid bit. It’s responsible for running a process with a user ID that’s different from the one of the users that started it.
5. Solving sudo Binary Permissions Error
To reiterate, /usr/bin/sudo should be owned by root while also having the setuid bit set. Let’s ensure both conditions are fulfilled:
$ su - Password: # chown root:root /usr/bin/sudo # chmod a=rx,u+ws /usr/bin/sudo
Notably, we might have to log in as root since sudo is out of order. After that, we use chown to take ownership of the /usr/bin/sudo executable and set its setuid (u+s) bit via chmod.
At this point, we should be able to use sudo as long as the problematic permissions on its binary were the only hindrance:
$ sudo test [sudo] password for baeldung: $
On the other hand, we might still experience problems, as the impact may run deeper.
6. System Corruption
Even after correcting the permissions of the sudo binary, using it can present issues:
$ sudo test sudo: /etc/sudoers is owned by uid 1000, should be 0 sudo: no valid sudoers sources found, quitting sudo: error initializing audit plugin sudoers_audit
In short, this means the /etc/sudoers permissions are also incorrect. Of course, we can fix them, too, along with the sudo library:
# chown root:root /etc/sudoers # chmod u=r,g=r,o= /etc/sudoers # chown root:root /usr/lib/sudo/sudoers.so # chmod a=r,u+ws /usr/lib/sudo/sudoers.so
However, since /usr/bin/sudo and /etc/sudoers are related files in two separate locations, we can assume the changes are also linked. Moreover, it’s highly likely that there is either targeted malicious activity or general system corruption.
While heavy forensics might be required in the former case, there are ways to check for the latter.
6.1. Manual Scan
One easy way to check for permission problems is by using ls:
$ ls -l /etc -rw-r--r-- 1 baeldung baeldung 2981 Oct 20 10:20 adduser.conf -rw-r--r-- 1 baeldung baeldung 44 Oct 20 01:20 adjtime -rw-r--r-- 1 baeldung baeldung 401 Feb 2 02:02 anacrontab [...]
Here, we expect /etc and its contents to be owned by root with only the owning group of /etc/shadow and /etc/gshadow being shadow. In this case, another user is the owner, which usually hints at problems.
To scan other folders, we can either use ls -lR for recursive checks or use alternative tools like find.
After confirming there are system-wide permissions issues, we have several options.
6.2. Base Repair
As usual, a full backup should be the first step before any repair attempts.
Once in the root recovery shell, we remount the filesystem for read and write access and correct the necessary permissions:
# mount -o remount / # chmod -R 755 /bin /boot /dev /etc/ /home /lib /lib64 \ /media /mnt /opt /run /sbin /srv /usr /var # chmod -R 777 /initrd.img /vmlinuz # chmod -R 1777 /tmp # chmod -R 555 /sys # chmod -R 555 /proc # chmod -R 700 /root
# stat --format='%A %a %n' /* lrwxrwxrwx 777 /bin drwxr-xr-x 755 /boot drwxr-xr-x 755 /dev drwxr-xr-x 744 /etc [...]
While this solution leads to a very open environment and may leave a broken sudo in the process, it’s usually a way to boot an otherwise unbootable operating system. Further, any additional fixes can be based on boot messages and knowledge about the specifics of the current setup.
6.3. Finer Repair
Another option to revert to a relatively stable permissions structure is to mirror a healthy one of the same distribution:
# find / -name '*' -printf '%m %p\0' > baseperm
Of course, there are many pitfalls of this approach:
- any additional installed packages aren’t part of the output
- customized permissions don’t persist
- differences in the filesystem tree structure can mean problems
Thus, this is another good point to make a backup. After doing so, we can use the perl interpreter to apply baseperm on the broken system:
# perl -0ne '$_ =~ m/^(\d*\d\d\d) (.*)\0$/; print "chmod $1 $2\n"; chmod oct($1), $2;' baseperm [...]
Here, we use -e to execute a silent (-n) one-liner with NULL as the record separator (-0) and the baseperm file as the input. The Perl code processes each record to get the path and permissions, so it can run chmod with them while also providing some feedback.
At this point, our permissions should be closer to what they were before the corruption. Naturally, we need to manually restore any setuid bits.
Finally, we can always copy any user files to a new install or simply perform a reinstall. In fact, if at all possible, this is usually the recommended option due to the many problems and security holes manual fixes can lead to.
In this article, we learned that a Linux system depends on its permissions, how they can affect it, and how to remedy global permission issues. Moreover, we specifically looked at the sudo tool as an example.
In conclusion, while the best way to recover from an accidental recursive change in permissions is a reinstall, there are options to try before resorting to that measure.