sudo? sudon’t! Stupid “sudoers.d”

If you don’t know what “sudo” is, then this isn’t the post for you… it’s going to get technical and Linuxy. Let’s start with the summary, as it’s the most important part of this post:

If you use /etc/sudoers.d/ don’t create files in the directory – create them elsewhere, ‘chmod’ them, and only then copy them in.
Edit: You can also use the ‘visudo’ command to create and edit the files – see the comments for more details.

Now for the story about how I came to this discovery…

For reasons that I’ll describe in a future post, I have a need to be able to trigger the “chvt” command from a keyboard shortcut. More specifically I want to run “gksudo chvt 1”, as using chvt to switch from a graphical screen to a console requires superuser privileges on my Ubuntu box. This prompts for my password, which seems a little redundant as I can use CTRL-ALT-F1 to the same effect without having to enter a password. So I decided to add an entry to the sudoers file in order to grant myself passwordless access to the chvt command.

I went wandering over to /etc and found not only the expected “sudoers” file, but also a “sudoers.d” directory. This directory contained a single README file, as follows:

#
# As of Debian version 1.7.2p1-1, the default /etc/sudoers file created on
# installation of the package now includes the directive:
#
# #includedir /etc/sudoers.d
#
# This will cause sudo to read and parse any files in the /etc/sudoers.d
# directory that do not end in ‘~’ or contain a ‘.’ character.
#
# Note that there must be at least one file in the sudoers.d directory (this
# one will do), and all files in this directory should be mode 0440.
#
# Note also, that because the sudoers file is not a ‘conffile’ in the Debian
# sense, and sudoers contents can vary widely, no attempt is made to add this
# directive to existing sudoers files on upgrade. Feel free to add the above
# directive to the end of your /etc/sudoers file to enable this functionality
# for existing installations if you wish!
#

That seemed like just what I wanted. I could create my sudoers command in a file of its own, safe in the knowledge that it wouldn’t get trampled by any future upgrades that affect the sudoers file itself. I copied and pasted the #includedir line into my sudoers file (using “sudo visudo”), then set about adding my sudoers directive in a file I named “chvt”:


> cd /etc/sudoers.d/
> sudo touch chvt
> sudo chmod 0440 chvt

BANG!

My terminal was filled with a lengthy backtrace, but scrolling back up to the top, I found this little nugget:

sudo: /etc/sudoers.d/chvt is mode 0644, should be 0440

Well thanks for that marvellous insight – I was just trying to set it to 0440 when you stopped me, you stupid machine.

Because I committed the heinous crime of creating an empty file in /etc/sudoers.d/ “sudo” won’t work at all. I can’t correct the permissions, I can’t delete or move the file: in short, I’ve lost administrator access to my machine. All for the sake of an empty file.

Now I can understand sudo throwing a wobbly and quitting if it can’t parse the sudoers file – blindly proceeding to read a malformed file could be a quick route to a buffer overflow attack or similar. But dying completely because an empty file has the wrong permissions seems a little draconian. Yes, that README did say “…and all files in this directory should be mode 0440” – but “should be” isn’t quite the same as “…MUST be 0440, or I’ll DIE!!!”. Here’s an idea: if you don’t like the permissions, just don’t read the file – there’s no need to get all suicidal about it.

It seems that the only way to recover from this situation is to reboot the machine: either booting from a Live CD, or selecting the recovery console during the GRUB boot sequence. You can then remove or change the permissions of the offending file and everything will be back to normal after you restart the machine. It does seem like a lot of hassle caused by a zero length file though – thank goodness I didn’t do this on a production server!

All of which leads back to the summary at the top of this post: Don’t create files directly in /etc/sudoers.d/ If you do use the #includedir directive in your sudoers file, make sure you create your files elsewhere, set the permissions to 0440, and only then copy them into place.

Edit: You can also use the ‘visudo’ command to create and edit the files – see the comments for more details.

19 Comments

  1. Jim Fischer says:

    Or, you can use the program ‘visudo’ to create and edit files in the /etc/sudoers.d/ folder, as stated in the “#includedir” section of the sudoers(5) man page–i.e.,

    [root]$ visudo -f /etc/sudoers.d/chvt

  2. Mark says:

    Thanks for the comment. I did check the sudo, sudoers and visudo man pages and found them far more confusing and opaque than most man pages – the fact that the sudoers man page starts with a “Quick Guide to EBNF” is a clear indication that it’s not designed as a quick reference guide.

    FWIW nothing I’ve read (other than your comment) makes it at all clear that visudo can be used to create files in the sudoers.d folder. Even the visudo(8) man page refers to the -f option as allowing visudo to “edit (or check) the sudoers file of your choice” – no mention of creating. As a result I had assumed that I needed to create the file first, before I could pass it to visudo. I don’t know if your sudoers(5) man page is different to mine, but I found no mention of creating the files with visudo in the “#includedir” section, only of editing them.

  3. J says:

    If you haven’t set a root password on your machine…well, you might want to in the future. It’s there for situations like these. su – would have let you fix this easily.

    I agree that sudo has some of the worst documentation ever. However, I don’t tend to use sudo to edit any of sudo’s config, I always do it as root (or use visudo) just because of situations like this. It’s also a good idea, when dealing with things that can backfire badly, to simply do sudo su – and then proceed normally (as root). Just my $0.02.

  4. Mark says:

    Luckily I’m technically savvy enough to handle these sorts of problems on my own machine even without setting a root password. Yes it required a reboot from a live CD, but it was just an annoyance rather than a real issue. I just posted the article as a warning for anyone else who might have thought along similar lines to me. Generally I do use sudo su if I’m going to do some more significant admin work – but in this case I was simply caught out by the fact that just creating a file using “touch” was enough to upset sudo, which isn’t documented anywhere I’ve seen.

    FWIW I did plan to use visudo to edit the file once it was created – but as I mentioned in my reply to the previous comment, nowhere does it indicate that you should also use visudo to create the file in the first place.

  5. Chien Po says:

    If only I had read this _before_ doing exactly what you did. Oy! As someone who’s read the sudo docs in the past and used it regularly, I agree that the man page(s) in no way help one to AVOID this situation.

    If only distros would perhaps just mention this in /etc/sudoers.d/README then a single sentence could stop a lot of annoyance.

  6. mp035 says:

    Thanks for posting this article, you just saved me from doing the exact same thing!

  7. AmigoNico says:

    I was just about to do the same thing, for the same reasons (thought it sounded cleaner to create a separate file for my mod’s, but visudo didn’t seem to support that) and fortunately ran across this post before shooting myself in the foot. Kudos!

    And I agree entirely — if there’s something wrong with a file, just ignore it!

  8. Aguseguedre says:

    I have read this post late. I have the same problem I created a file with the comand
    ALL= NOPASSWD: /usr/sbin/firestarter and I have the sudoers.d file empty.

    Could you tell me step by step(Like I was 3 years old) what can I do to reestar visudo.d

    I tried with live CD I can copy the original visudo.d file but I can copy in the damaged file.
    Regards

  9. Mark says:

    If the file you’ve created isn’t yet in the sudoers.d directory, I would delete the file and start again, creating it using the visudo command as suggested by other commenters (see the end of this comment).

    That leaves you with the problem that your sudoers.d directory is empty. If you read the README that is in there by default (posted in the body of this article), you’ll see these lines:

    # Note that there must be at least one file in the sudoers.d directory (this
    # one will do), and all files in this directory should be mode 0440.

    So your real problem is that the directory is empty. When booted from a Live CD you should be able to mount your hard drive and then, in a terminal, navigate to the /mnt/disk/etc/sudoers.d directory (where /mnt/disk is whatever mount point is the right one for your drive). Once in there you can use “sudo visudo -f ./README” to create a suitable file – I’d suggest copying the text from this post to get you back to what was originally in the file.

    Reboot and confirm that you can use sudo again, then follow similar steps on your normal system (using “sudo visudo -f /etc/sudoers.d/firestarter”) to create your new file.

  10. Luis says:

    Hi! I want to thank you for posting this lifetime-saving warning, I have been able to happily sail through these muddy waters of sudoers by following your advice :) I have made a post summarizing my journey, if you would allow me, in here: http://luiseth.wordpress.com/2012/04/15/in-a-nutshell-add-permissions-with-configuration-files-in-etcsudoers-d/

  11. Mark, I’d like to introduce you to your new friend: umask. Your umask determines the default permissions when creating new files and folders, and typically has the default value of 0022 (in octal, just like chmod values). The umask is subtracted (masked, hence the name) from full permissions when files are created, so a file created with a mask of 0000 would get 0666, and with 0022, 0644. So to create files with 0440 permission, set the umask to 0226 first. When you’ve finished, set the umask back to what it was. Running umask with no arguments tells you its current setting.

    Example:
    U=`umask`
    umask 0226
    touch z
    ls -al z
    -r–r—– 1 root root 0 Sep 5 13:45 z
    umask $U

    HTH

  12. Mark says:

    Thanks for the info. I was already aware of umask, but it wouldn’t have helped in this case, because the problem wasn’t that I created a file with the wrong permissions, the problem was that the documentation failed to make it clear that doing so would be so catastrophic. Had I know that, I would have created the file elsewhere, in which case a simple “touch, chmod, mv” would have done the trick.

    As other people have mentioned, the best approach is probably to use visudo to create the file, but again the documentation is lacking and implied that visudo could only be used to edit files, not create them.

  13. Eugene says:

    Assuming you have a local file chvt you can use install to copy and set proper attributes in one command:

    sudo install -m 440 -o root -g root ./chvt /etc/sudoers.d/chvt

  14. Mark says:

    Thanks. I’d never come across the “install” command before. It’s always good to add another weapon to my command line arsenal.

  15. naja melan says:

    > there is no reason to be all suicidal about it

    Actually, there is. Sudo defines that in case of multiple lines matching for a user, the last one stands.

    sudoers.d is parsed after sudoers. So potentially a file in sudoers.d could restrict permissions for someone, so it makes sense from a security standpoint to guarantee that either the entire set of files is parsed correctly or none at all, but not some.

    It’s maybe confusing about the .d workflow, but you should consider the set of files like one configuration file. If sudo can’t parse some lines in it’s configuration file, would you prefer it:

    1. gets all suicidal about it
    2. ignores just those lines
    3. prints a warning (potentially to an attacker) about which lines are malformed

    Guess what’s the only option that’s ever going to pass a security audit?

    greets

  16. Joe says:

    I fell into the same trap and lost my sudo option. I found (at least on Ubuntu 14.04) that pkexec can be used to eradicate the offending sudoers.d file and get things back to normal. That said, use of visudo is probably a good approach unless you are totally allergic to terminal-style editors.

  17. Hal Fisher says:

    I vote the whole sudoers.d directory and requirement is thrown out! Screwed me, no way to save it on my raspberry pi system. Was doing something that suggested a new file be created in this directory. If I had known it was that dangerous I never would have done it. Sure, I wrote the wrong thing (I tried to exit a cat with “exit” then “quit” and those got added to the file till I finally found the correct exact to be… wait for it… ^D (I had no idea that ^ meant ctrl). Hey, if you ever want more than the hardest geek to use linux, this directory, and the possibility of hosing your whole system, HAS TO BE TAKEN OUT!!!!!! Till then, give me the safety of Windows :/

  18. Steve Parker says:

    Or you could use install:

    install -m 0600 /dev/null /etc/sudoers.d/chvt

    It is also useful to have a root shell in another window, when messing with sudoers, so that you can undo anything nasty.

  19. R. Hartman says:

    As you describe it this is impossible on CentOS6.6, as I cannot cd into /etc/sudoers.d to begin with: Permission denied (/etc/sudoers.d has mode 0440). So I have to be root already to even create the file. If I do that, as root, the file is created with mode 0644 and I can change it to 0440 without problems.

    Alternatively, if, as non-privileged user, I use
    “sudo touch /etc/sudoers.d/test”
    “sudo chmod 0440 /etc/sudoers.d/test”
    no problems occur either.

    So either it’s a distribution-related problem or it was a bug that has since been fixed.

2 Trackbacks

Leave a comment