os.getlogin() Error

Cameron Simpson cs at zip.com.au
Thu May 4 19:00:58 EDT 2017


On 04May2017 15:03, Wildman <best_lay at yahoo.com> wrote:
>I tried testing on Mint and Ubuntu and the program would crash.  The
>GUI would appear briefly and disappear.  On Ubuntu a crash report was
>created so I was able to figure out what was going on.  It had the
>traceback and showed that os.getlogin threw an error.  This is from
>the crash report:
>
>PythonArgs: ['/opt/linfo-tk/linfo-tk.py']
>Traceback:
> Traceback (most recent call last):
>   File "/opt/linfo-tk/linfo-tk.py", line 1685, in <module>
>     app = Window(root)
>   File "/opt/linfo-tk/linfo-tk.py", line 1393, in __init__
>     txt = function()
>   File "/opt/linfo-tk/linfo-tk.py", line 316, in userinfo
>     user = os.getlogin()
> OSError: [Errno 25] Inappropriate ioctl for device

This usually means that the program does not have a controlling terminal.

>The program installs using the Debian package system (.deb) and an
>entry is created in the Applications Menu.  The strange thing is
>that the crash only occurs when the program is run from the menu.
>If I open a terminal and run the program from there, the program
>runs fine.

And this supports that.

getlogin is not magic, and can be overused. The Python docs say "Return the 
name of the user logged in on the controlling terminal of the process." Clearly 
that will fail.

When you start from a terminal, your command will have that as its controlling 
terminal unless it has gone out of its way not to. When you start from a menu, 
usually that menu system will not be associated with a terminal. In this case 
you need to fall back on other methods of figuring out "who is logged in".

>I found a little info on the web about this but it was not clear
>whether it is a bug in Linux or a bug in the os module.  I also
>found a couple of work-arounds but neither of them will work for
>my purposes.
>
>    user = pwd.getpwuid(os.getuid())[0]
>    user = getpass.getuser()
>
>I will try to explain...
>The program reports system information based on the user's name.
>Things such as passwd, groups and shadow info.  However, the
>program must have elevated privileges to get the shadow info so
>the program has the option to 'restart as root' so the shadow
>information will be obtainable.
>
>If the program is restarting as root, the work-arounds report
>the user as 'root'.

The "shadow" information is normally concealed for good reason.  I appreciate 
that you're trying to only report that information for the current user, but 
you should consider whether you should report it at all.

Personally I would be reluctant to write a program that "restarts as root"; it 
feels like a tool where a bug would lead easily to privilege escalation - that 
the calling user (not root, and from root's point of view untrustworthy) might 
get it to perform extra tasks beyond your plan AS ROOT. Risky.

>Is there a way to get the actual user name or is there a fix
>or a better work-around for the os.getlogin() function?

The standard way is not to "restart as root", but to write a setuid program. It 
still has all the pitfalls of any program running as root (the change for bugs 
to let the calling user do something they should not be allowed to do), but you 
can examine the value from os.getuid(): it will be the _calling_ user, while 
os.geteuid() will be the effective user (root in your case). Then the 
workaround will be effective.

You should also _minimise_ the time and work your program does as root. Along 
the lines of:

  ... program invoked setuid ...
  look up os.getuid() to find the uid of the invoker
  read as little as possible of the privileged info (i.e. shadow) as required
  os.setuid() BACK TO THE ORIGINAL USER SO YOU ARE NO LONGER ROOT
  ... do everything else ...

Part of your problem is that "who is the currently logged in user" is a 
nebulous idea. Supposing you were to address the lack of controlling terminal 
by seeing who is logged into the console. That is a little trusting. Supposing 
_you_ are logged into the console, running X11. And while so, _I_ ssh into your 
machine and run your program without a controlling terminal. Then your program 
will _mistakenly_ presume the logged in user is _you_ (because, after all, 
you're logged in), and report _your_ information to _me_.

For all that setuid programs have their own security issues, at least they 
_know_ who they were invoked by from os.getuid(), without playing insecure 
guessing games around "who is logged in". Because the latter is not equivalent 
to "whose information should I access?"

I hope this points a way forward.

Personally I would usually resist accessing information not available as the 
user, and avoid the need to run as root at all.

Cheers,
Cameron Simpson <cs at zip.com.au>



More information about the Python-list mailing list