Bug #19724
closedDir.home returns incorrect home directory
Description
This is probably related to 16787.
From the patch on that issue I conclude that ruby uses getlogin and co to obtain the name of the logged-in user, but that is not valid. Ruby must use the uid of the running process since the user that logged in may since have switched to a different user-id (e.g. using sudo -u <user> -i
). This will cause getlogin to still report the name that the user logged in at the current terminal, but that is not the user that ruby should be using.
E.g., If I ssh into a machine as root, and then use sudo -u user -i and then run a ruby process that tries to write to "my" home directory it fails (most commonly in trying to access /root/.gem or similar).
I know why ruby originally wanted to use getlogin (at least according to comments on the above issue), which was to support multiple login names having the same UID but different home directories. To the best of my knowledge, this was always an invalid configuration. Usernames and UIDs in the PW DB should have a 1-to-1 mapping. In any case getlogin is not the right answer, since it does not yield the login name of the running process.
It is particularly bad since ruby uses this method even if ${HOME} is set!
This is on current up-to-date Ubuntu 22.04.
Updated by jeremyevans0 (Jeremy Evans) over 1 year ago
Looking at the implementation of rb_default_home_dir
, $HOME
is always checked, and getlogin
/getpwnam
is only used when $HOME
is not set. If $HOME
is not set, then Ruby does use getlogin
, but that appears to be intentional, not a bug. This behavior dates back to Ruby 2.4 (Ruby 1.9-2.3 and below have Dir.home
raise ArgumentError
if $HOME
is not set).
Changing this behavior would not be backwards compatible, and I'm sure in many cases the current behavior is desirable. If you want different behavior, it would be advisable to set $HOME
:
require 'etc'
ENV['HOME'] = Etc.getpwuid.dir
Example:
# running ruby using doas/sudo
ENV['HOME']
# => "/root"
Dir.home
# => "/root"
ENV.delete 'HOME'
Dir.home
# => "/home/jeremy"
require 'etc'
ENV['HOME'] = Etc.getpwuid.dir
Dir.home
# => "/root"
I think we should update the Dir.home
documentation to better describe the current behavior.
Updated by seb (Sebastian Unger) over 1 year ago
Ok, my apologies. This was caused by one part of a rather big ruby system passing :unsetenv_others
into the options for Process.spawn
with value true
and one of the processes spawned that way was itself a ruby process. It was that inner ruby process that died since this caused the HOME variable to be unset.
You can close this issue.
Updated by jeremyevans0 (Jeremy Evans) over 1 year ago
- Status changed from Open to Closed