How does sudo handle $HOME differently since 19.10?
For years, Ubuntu has shipped a patched version of sudo
that preserves $HOME
by default. Besides Ubuntu and its derivatives, very few other operating systems (perhaps no others) do this. It has been decided that this causes more problems than it solves, and starting in Ubuntu 19.10, $HOME
is no longer one of the few environment variables sudo
preserves.
In terms of what the change is and how it affects users, the key points are:
-
As of Ubuntu 19.10,
sudo command
does whatsudo -H command
does in previous releases. It can indeed be used in cases that would have previously advisedsudo -H
, including to run GUI applications as root or another user. Running graphical programs as root at all remains controversial. But in 19.10 you can runsudo gedit
with the exact same effect assudo -H gedit
. In 19.10, commands likesudo gedit
no longer create annoying file ownership problems in your home directory. -
This applies even on systems upgraded to 19.10 from an earlier release, even when the upgrade doesn't change your
/etc/sudoers
file. The change is in the source code of thesudo
program itself, not in its default configuration files. (It can be overridden in asudoers
file, but you'd probably know if you did this.) -
It doesn't--and won't--apply to releases prior to 19.10. Before 19.10,
sudo
preserves$HOME
by default, and future updates tosudo
won't change that. For example, 18.04 LTS will always have the old behavior, even in future point releases. -
sudo -H command
still works fine. If you're in the habit of using that, no problem. You just don't have to, on a 19.10 system. -
Most commands you run with
sudo
won't behave differently. In the overwhelming majority of situations where you would not have passed-H
, you could have. Some users do rely on or otherwise prefer the old behavior of preserving$HOME
. But that often had unintended effects. So if you were relying on this, you still might not want to override the change in asudoers
file.
See also WinEunuuchs2Unix's answer to Why should users never use normal sudo to start graphical applications?
Why The Change
As the changelog puts it (under "sudo (1.8.27-1ubuntu2) eoan"):
This restores sudo handling of $HOME to what everyone else does
"Everyone else" refers to the upstream sudo
project (hosted here) and also seemingly all other operating systems that contain sudo
, except those that derive from Ubuntu.
There's more to it, though. This is also considered to fix a security bug, as described in Ubuntu patch to add HOME to env_keep makes custom commands vulnerable by default. The history was concisely summarized in this comment there by Steve Langasek (whom you may have heard of), which I quote in full:
This change was originally introduced in response to bug #760140.
The upstream change in sudo was never accompanied by a CVE, and the behavior change was never applied to previous releases of Ubuntu, so it didn't seem security sensitive at the time.
I am not opposed to changing this to behave the way Simon describes, but I defer to the Security Team here.
Todd C. Miller, who maintains the upstream sudo
project (very actively, and for many years now), was also asked for input on the issue. He explained the reason sudo
resets (i.e., does not preserve) $HOME
:
On Thu, 16 May 2019 07:48:40 -0400, Dan Streetman wrote:
I've cc'ed sudo-users, so the question to the upstream sudo list can be summarized as:
How likely would it be for upstream sudo to add HOME to env_keep by default?Extremely unlikely. Prior to sudo 1.7.4 the HOME and MAIL environment variables were preserved in the environment by default. This can lead to programs using config files the original user's home directory, which has security implications, so the default was changed in 1.7.4.
In the old days, sudo did little more than change the uid. These days sudo tries to run the command in an environment that closely matches what you would get by logging in as that user. This has proven to be safer as it more closely matches the assumptions other programs make.
We ask because Ubuntu carries a patch that adds HOME to env_keep, unlike the default upstream, or any other Linux/Unix. We are considering removing that patch, to match upstream defaults, of not including HOME in env_keep.
I would be supportive of that. I believe that resetting HOME is the safer default.
- todd
(I have altered the formatting from the original message to display properly in this medium.)
As of 19.10, the downstream sudo
in Ubuntu behaves as the upstream sudo
(and sudo
in other operating systems, including Debian) have behaved for many years. For more detailed information on the history of this change and the developments that preceded it, including numerous links for further reading, see the "sudo
and $HOME
: The Last 20 Years" section below.
Huh? a.k.a. Why it (sometimes) matters what sudo
does with $HOME
Programs you run that need the location of your home directory often examine the value of the $HOME
environment variable. One important case is when a program tries to store and access configuration files in the home directory of the user running it. Programs typically go by the value of $HOME
. Sometimes when you run a program as a substitute user--for example, as the root account--it is appealing to have that program use your settings. But this can also get messy, in two ways:
-
Usually when you run a command as another user, you want it to work mostly the same way as if that user had run it. But if it is a command whose behavior can be radically altered by the fact that you ran it--which happens if its behavior is heavily customized by data read from files found inside the directory named in
$HOME
--then this goal is not achieved.When you're permitted to perform any action you choose as any user including root (which in Ubuntu is conferred by membership in the
sudo
group), the issue is mostly one of accident. However, if you are a limited user and you have been permitted to run only specific commands withsudo
, then being able to manipulate what those commands do has serious security implications. The bug report that led to the change in 19.10 was specifically motivated by that problem (and includes a compelling example of it). -
If you run a command as another user and the command makes changes to its configuration in the directory named in
$HOME
, an attempt is made to write the changes to files in that location. When the substitute user is not root, as insudo -u username command
, this typically fails and produces error messages, which is mildly annoying but not serious.But in the common case that the substitute user is root, as in
sudo command
, this succeeds, but if any new files are created, they are owned by root, and your user account no longer has full access to all its own configuration files. This can be fixed bychown
ing the files back, so the problem is most severe in the case of graphical applications, whose complexity can make it so more files, in more places, are involved (and where it has been reported to sometimes make login difficult, though usually the problem is less severe than that).
What changed, and why all 19.10 systems have the change
A short whitelist of environment variables that are not reset by default is hard-coded in sudo
itself. In Ubuntu releases prior to 19.10, an Ubuntu-specific patch adds $HOME
to this whitelist. It is compiled into a binary file used by sudo
, so upgrading to a version of sudo
that does not have the patch removes it from the whitelist.
The patch was removed in 19.10. So upgrading to 19.10 or higher will always apply the change, even when no configuration files associated with sudo
are modified.
It is still possible to configure any version of sudo
to preserve $HOME
(see below). In the extremely unusual case that you did this before 19.10--when such a configuration would have made no difference--and kept that configuration across an upgrade, $HOME
would still be preserved. But you would presumably remember having done this strange thing.
If your upgrade to 19.10 (or later) failed and gave you an only partially upgraded system with a version of sudo
from before 19.10, then sudo
on that system still preserves $HOME
by default. This is almost the only case where sudo
would preserve $HOME
in 19.10 (or later) without you knowing about it--though you would still have been informed, during the release upgrade, that not all packages could be upgraded.
The easiest way to see directly that the patch is gone in the source code of sudo
in Ubuntu 19.10 is to compare https://git.launchpad.net/ubuntu/+source/sudo/tree/debian/patches?h=ubuntu/disco-security to https://git.launchpad.net/ubuntu/+source/sudo/tree/debian/patches?h=ubuntu/eoan.
Still, if you are not sure how your system is configured, you can run sudo printenv HOME
to find out.
Resetting $HOME
in Ubuntu 19.04 and earlier
Although updates to sudo
in Ubuntu 19.04 and earlier may include changes to the documentation to explain the situation, the way sudo
treats $HOME
in those releases has not been and will not be changed by any updates. Most users will not want to bother manually changing how sudo
works on systems where they are already using it without problems. However, if you like, you can make sudo
reset $HOME
on those systems, even without upgrading them.
Any particular time you run sudo
, you can use the -H
/--set-home
option to reset $HOME
:
sudo -H command
Or you can use -i
. This does more than reset $HOME
. sudo -i command
behaves as if you logged in as root, ran command
, and logged out; sudo -i
by itself behaves as if you logged in as root and places you in an interactive root shell. This differs from sudo -s
, which starts an interactive shell that is not a login shell. Before Ubuntu 19.10, sudo -s
preserves $HOME
; that is, regardless of version, the -s
option does not carry any behavior that affects how $HOME
is treated. It is meaningful to use -H
and -s
together. You can also use any of -H
, -i
, and -s
with -u user
to become user
rather than root. Finally, using sudo
via the graphical frontends gksu
or gksudo
(still available in 16.04 LTS, though you may need to install the gksu
package) resets $HOME
.
If you want to reconfigure sudo
so that it always resets $HOME
, you can enable the always_set_home
option in a sudoers
file:
Defaults always_set_home
You would add that line to /etc/sudoers
or, better, to a new file in /etc/sudoers.d/
. Either way, you should use visudo
to edit the file, so you get the benefit of syntax checking. (A syntax error in any sudoers
file causes sudo
to refuse to work at all. This is a hassle, though it can be fixed.)
For example, on some of my pre-19.10 systems, I created and edited /etc/sudoers.d/always_set_home
by running:
sudo visudo -f /etc/sudoers.d/always_set_home
In the file, I wrote the above Defaults
line. The filename need not be always_set_home
--it can be whatever you like, so long as it contains no .
or ~
character. The word on the Defaults
line does, of course, need to be exactly always_set_home
.
(One reason to prefer making a new file in /etc/sudoers.d/
to modifying the existing /etc/sudoers
file is that, if a future update ever does change the default /etc/sudoers
file, you can accept the new file without losing your customizations. Another reason is that it is immediately clear that you have changed the configuration, and where your changes may be found.)
If you do this and later wish to run an individual sudo
command that preserves $HOME
, you can do that the same way you would do it in 19.10 (see below).
Preserving $HOME
in Ubuntu 19.10 and later
The way sudo
treats $HOME
has been changed for a reason. (See the above sections, as well as the detailed history section below.) But if you really want to make sudo
continue to preserve $HOME
, even in 19.10 and later, you can configure this behavior in a sudoers
file.
Any particular time you run sudo
, you can tell it to preserve $HOME
with --preserve-env=HOME
:
sudo --preserve-env=HOME command
This is the form of --preserve-env
that is documented as --preserve-env=list
in the sudo
manpage. It is also possible to use --preserve-env
with no list operand, which is the same as -E
; that preserves all environment variables. But there's rarely a good reason to do that, especially if your goal is just to preserve $HOME
. If you don't like typing --preserve-env=HOME
, you could define a shell alias or shell function or write a script that lets you run a shorter command to do it. Even better would be to seldom preserve $HOME
(see the section below on alternatives to doing so).
More generally, you can make sudo
preserve any particular environment variable varname
with --preserve-env=varname
. (You may also see code that effectively preserves $HOME
by setting it explicitly in the command sudo
runs, such as with sudo HOME="$HOME" command
. This also works. It is quite different from HOME="$HOME" sudo command
, which would not keep sudo
from resetting $HOME
.)
Or if you really want to make sudo
always preserve $HOME
, you can do this by adding $HOME
to env_keep
in a sudoers
file:
Defaults env_keep += "HOME"
That can go in /etc/sudoers
or a file in /etc/sudoers.d/
. Although I stress I don't recommend doing this at all, if you decide to do it then I'd suggest creating and editing /etc/sudoers.d/keep-home
(call the file what you like, so long as the name doesn't contain .
or ~
) by running:
sudo visudo -f /etc/sudoers.d/keep-home
Then you can put that Defaults
line in the file.
The reason to use +=
instead of merely =
is that there are a handful of other environment variables, hard-coded into sudo
itself, that are preserved by default, and that you probably want preserved. If you used =
, then only the environment variables you listed explicitly in the file would be preserved. In this case, that would be just $HOME
. More information about the grammar of sudoers
files is available in sudoers(5).
As for why I suggest making a file in /etc/sudoers.d/
instead of editing /etc/sudoers
--and why you should definitely use visudo
either way--see my comments in the "Resetting $HOME
in Ubuntu 19.04 and earlier" section above.
Alternatives to Preserving $HOME
Most of the time you use sudo
, the best alternative to preserving $HOME
is to do nothing. Most sudo
commands have the same effect (and some work slightly better) without $HOME
preserved. However, I am aware of two popular use cases for preserving $HOME
.
Using your text editor configuration and/or plugins to edit files owned by root or another user. sudoedit
, or equivalently sudo -e
, is an ideal alternative for this. It runs the editor as you, you edit a temporary copy of the file, and the file is updated when you quit the editor. Since the editor runs as you, it uses your configuration and plugins automatically, and does so without any risk of failing in opaque and unexpected ways with permission denied errors or making files in your home directory inaccessible to you. To edit file
:
sudoedit file
To edit file
with editor
instead of the default editor:
SUDO_EDITOR=editor sudoedit file
For example, SUDO_EDITOR=vim sudoedit /etc/apt/sources.list
edits /etc/apt/sources.list
with vim
.
To decide what editor to use, sudoedit
consults the environment variable $SUDO_EDITOR
; if that's unset, it consults $VISUAL
; if that's unset, it consults $EDITOR
; if that's unset, it tries editor commands from a hard-coded list, which in practice in Ubuntu means it uses editor
. Typically that resolves to /usr/bin/editor
, which is a symlink. If you want to change the default editor systemwide then you can change what /usr/bin/editor
points to by running sudo update-alternatives --config editor
. You can also set one of those three environment variables, which is a good way to change what sudoedit
edits with for just one user.
Making programs you only run as root use specific configuration files. If a program you run as root looks in $HOME
for its configuration, then you can just put that configuration in (or move that configuration to) root's home directory, /root
.
Resetting $HOME
when you don't know what release you're using
You may sometimes write a command and not know what release of Ubuntu (or what operating systems besides Ubuntu) it will run on. For example, you may be writing a script that you will run on multiple machines.
sudo
continues to accept the -H
option, with the same effect it always had. It just happens that, starting on 19.10, sudo
without -H
does the same thing (unless you have configured it to do otherwise) as sudo -H
.
To write portable sudo
commands that reset $HOME
, you can continue using:
sudo -H command
(Also as before, if all the actions performed in your script need to be done as root, it's probably better not to use sudo
in your script and just run the script as root with sudo
.)
sudo
and $HOME
: The Last 20 Years
Around the turn of the century, the upstream sudo
project introduced the env_reset
option, which makes sudo
reset most environment variables. This option is enabled unless disabled explicitly in a sudoers
file. (It is possible to enable it explicitly, which Defaults env_reset
in Debian and Ubuntu's /etc/sudoers
file does, but this is not actually necessary.) Before sudo
had env_reset
, all environment variables were preserved unchanged. With env_reset
, only a handful of variables were preserved. This included $HOME
.
In July of 2010, $HOME
was removed from that small whitelist and thus no longer preserved by default.
In September of 2010, a bug report about documenting that in the sudo
package in Debian was filed. As far as I can tell, there was no controversy about, or objection to, the change itself, from Debian developers. (But see below.)
In February of 2011, the change had come further downstream from Debian to Ubuntu and Ubuntu developers discussed whether or not it was desirable.
In April of 2011, the change was reported as a bug, referencing that discussion. (Some behavior resulting from the change had been reported as a bug the day before that.) At least at the time, this was considered to be a regression ("the Debian maintainer already tried to fix this once but it appears the fix was incomplete"). I haven't found any such Debian bug report, but that doesn't mean there wasn't one; furthermore, a change could have been made without one. I suspect, though, that it may have been an erroneous reference to that documentation bug.
The next day, the development release of Ubuntu was updated with a downstream, Ubuntu-only patch, to re-add $HOME
to the list of environment variables sudo
preserved by default. I believe this was done quickly so as to make it into the release of Ubuntu 11.04. The effect was that sudo
in 11.04, as in previous Ubuntu releases, preserved $HOME
by default.
In November of 2011, a bug was reported about how the documentation for sudo
in Ubuntu said $HOME
was reset. That is, the manpage in Ubuntu correctly described the behavior of upstream sudo
but not the patched behavior in Ubuntu.
In September of 2014, a bug was reported pointing out some of the problems with having sudo
preserve $HOME
by default and arguing that the problem with running graphical programs with normal sudo
is not that it's inherently dangerous (often cited to this wiki page) but that sudo
's unusual handling of $HOME
in Ubuntu makes it dangerous and should be considered a bug. It appears there was significant interest in this bug report, including from Ubuntu developers, even though it would be some time before it would be fixed.
In March of 2016, the bug that would later become the main reference for the problems with sudo
preserving $HOME
was reported. Initially, this bug report focused specifically on the security problem that users who are not administrators (i.e., cannot run arbitrary commands as root), but who have been permitted to run specific commands with sudo
, can maliciously alter the behavior of some programs, and in some cases even gain full control of the system. It recommended a narrow change that would attempt to address that case specifically, while still having $HOME
preserved when members of the sudo
group run commands as root or another user.
In April of 2019, a bug was reported objecting to the behavior of sudo
preserving $HOME
by default, even when sudo -s
is used.
Later that month, discussion resumed on the March 2016 bug, toward the possible resolution of removing the Ubuntu-specific patch altogether. This broadened the focus of that bug report beyond the specific security vulnerability it described. The goal of making sudo
in Ubuntu treat $HOME
the same way upstream sudo
(and sudo
in other operating systems) treats it, starting in Ubuntu 19.10, was articulated.
In May of 2019, a bug was reported about how programs (including non-graphical programs) that use launchpadlib suffer configuration file ownership problems because sudo
preserves $HOME
.
A week later, another mailing list discussion on "how sudo handles $HOME" took place (see also this archive page), showcasing a range of views on how sudo
ought to treat $HOME
. One preference that was uncontroversial was that if a change were to be made, it should only be to 19.10 and later, and not be made in any updates for previous releases. The question arose of whether upstream sudo
would continue resetting $HOME
in future versions.
The upstream sudo
maintainer, when consulted about this, made clear that no such upstream change is planned and supported the view that the downstream version of sudo
in Ubuntu should also reset $HOME
by default. That message, posted originally on the sudo-users mailing list, was quoted in a comment on the March 2016 bug report.
In June 2019, Ubuntu developers made plans to remove the patch that makes sudo
in Ubuntu preserve $HOME
.
About a week later, the change was made in Ubuntu's repositories. This change applies starting in 19.10. The only change that will be made to sudo
in earlier releases is to update the documentation so it clearly and correctly describes the behavior of sudo
in those releases.
Acknowledgements
- Zanna helped me figure out what this should cover and how to cover it, and she gave feedback on multiple fragments and drafts of it as I wrote them (see conversation back then, more recently starting here, then here, here, there, and finally here and there).
- Seth and DK Bose encouraged me to write this (see conversation around here and there).
-
WinEunuuchs2Unix wrote that excellent answer and expanded it to cover how
sudo
changed in 19.10, which preceded this Q&A and (as far as I know) was the first information about the change posted to Ask Ubuntu.