Project

General

Profile

Actions

Bug #19724

closed

Dir.home returns incorrect home directory

Added by seb (Sebastian Unger) about 1 year ago. Updated about 1 year ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux-gnu]
[ruby-core:113879]

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) about 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) about 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.

Actions #3

Updated by jeremyevans0 (Jeremy Evans) about 1 year ago

  • Status changed from Open to Closed
Actions

Also available in: Atom PDF

Like1
Like0Like0Like0