Skip to content

QUESTION: make lib works when run program as another user. #63

Closed

Description

@dyorgio

I'm trying to start my program with root to another users on machine.

I already tried "runuser"(-l and -u) and "su username", but no way to make it works.

The best try, for now was:

sudo runuser -l username -c "DISPLAY=:0 XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP program-name"

The program works, without error, but no icon appears :(, somebody have any glue who to make it works?

Activity

  1. dyorgio commented on Sep 17, 2017

    @dyorgio
    Author

    Almost done with:

    sudo su username /bin/sh -c "XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP program-name"

    But this warning appears:

    18:29:30.061 [main] WARN dorkbox.systemTray.SystemTray - Attempting to load the SystemTray as the 'root/sudo' user. This will likely not work because of dbus restrictions. Using the Swing Tray type instead.
    

    But process is running as my user:
    captura de tela 2017-09-17 as 18 30 31

  2. dorkbox commented on Sep 17, 2017

    @dorkbox
    Owner

    What OS and window manager?

    In most cases, because of the way dbus works, the application running must also be the same user that the desktop is running under. There are ways around it, but involve managing the dbus directly, which is far to much effort for me.

    See if you can get it to work without using sudo at all, since the check for running as root is via System.getenv("SUDO_USER").

    Since it's super easy to add a "root override", where all root checks are disabled I'll do that real quick. If it works, it works, if not - there's nothing I know of to make it work.

  3. dyorgio commented on Sep 17, 2017

    @dyorgio
    Author

    I'm testing in Ubuntu 16.04 with Unity.

    Sadly it doesn't work with:

    dorkbox.systemTray.SystemTray.AUTO_FIX_INCONSISTENCIES = false;

    I tried only with su, but before I need to enter in a bash with sudo (same thing at the end).
    :(.

    My application needs a "service" that start my program on users sessions if it is not open (crashed or terminated by user), like a auto-restart (keep alive).

    Can you give me some advices about manage bus directly?

  4. dorkbox commented on Sep 17, 2017

    @dorkbox
    Owner

    (this specifically has to do with app-indicators. I just pushed version 3.7, which has SystemTray.ENABLE_ROOT_CHECK

  5. dorkbox commented on Sep 17, 2017

    @dorkbox
    Owner

    I have no idea how to manage the dbus directly. My research ended when I discovered that it is not easy. However, I've tested against Ubuntu 16.04 + Unity, and the fallback "Swing" tray type worked in a VM.

  6. dyorgio commented on Sep 17, 2017

    @dyorgio
    Author

    Yes, I can confirm that swing is working here too :).

  7. dorkbox commented on Sep 17, 2017

    @dorkbox
    Owner

    Ah, good to know swing works in more than a VM. Can you try 3.7 and tell me if SystemTray.ENABLE_ROOT_CHECK=false works in your situation? All it does is disable the warning + swing fallback (since SystemTray.AUTO_FIX_INCONSISTENCIES does a lot of things, it's best to leave that true)

  8. dorkbox commented on Sep 17, 2017

    @dorkbox
    Owner

    As far as DBUS stuff goes, If you can get a C example running (I have some test examples in the test directory), I can probably port that to java.

  9. dyorgio commented on Sep 17, 2017

    @dyorgio
    Author

    I got it!

    Using this command it works (with root warning):

    sudo su username /bin/sh -c "DBUS_SESSION_BUS_ADDRESS='unix:abstract=/tmp/dbus-cLtEoBPmgC' XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP program-name"
    

    I get "unix:abstract=/tmp/dbus-cLtEoBPmgC" from /run/user/{uid}/dbus-session.

    What do you think? it is a good start point to include into lib?

    EDIT: it works without sudo(root) but my service runs as root like user.

  10. dorkbox commented on Sep 17, 2017

    @dorkbox
    Owner

    Awesome! Thanks for figuring it out - i'll definitely include that info.

    If you want, you can disable the root warning/checks via SystemTray.ENABLE_ROOT_CHECK=false now.

  11. dyorgio commented on Sep 19, 2017

    @dyorgio
    Author

    Example to run as user with root:

            // Get dbus-daemon PID
            Process process = Runtime.getRuntime().exec(new String[]{//
                "/bin/sh", "-c", //
                "ps aux | grep \"^" + user + " \" | grep \"dbus-daemon\" | grep \"unix:\" | awk '{print $2}'" //
            });
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String pid = reader.readLine();
            reader.close();
    
            // Read DBUS env values
            Map<String, String> dbusEnv = new HashMap();
            process = Runtime.getRuntime().exec(new String[]{//
                "/bin/sh", "-c", //
                "cat /proc/" + pid + "/environ | tr '\\0' '\\n'" //
            });
            
            reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            int splitIndex;
            while ((line = reader.readLine()) != null) {
                splitIndex = line.indexOf('=');
                if (splitIndex != -1) {
                    dbusEnv.put(line.substring(0, splitIndex), line.substring(splitIndex + 1));
                }
            }
            reader.close();
    
            String xdgDesktop = dbusEnv.get("XDG_CURRENT_DESKTOP");
            if (xdgDesktop == null) {
                xdgDesktop = "Unity"; // Ubuntu Rules!
            }
    
            String display = dbusEnv.get("DISPLAY");
            if (display == null) {
                display = ":0"; // display default
            }
    
            String dbusAddress = dbusEnv.get("DBUS_SESSION_BUS_ADDRESS");
    
            process = Runtime.getRuntime().exec(new String[]{//
                "runuser", //
                user,//
                "-c",//
                "/bin/sh -c \"DISPLAY=" + display + " DBUS_SESSION_BUS_ADDRESS=" + dbusAddress + " XDG_CURRENT_DESKTOP=" + xdgDesktop + " YOUR-COMMAND\""//
            });
  12. dorkbox commented on Sep 19, 2017

    @dorkbox
    Owner

    Perfect! May I add this as a Utility method under Apache 2.0?

  13. dyorgio commented on Sep 19, 2017

    @dyorgio
    Author

    @dorkbox always :D

  14. tresf commented on Sep 19, 2017

    @tresf
  15. dyorgio commented on Sep 19, 2017

    @dyorgio
    Author

    @tresf, if GNOME_DESKTOP_SESSION_ID is present in dbus-daemon env vars yes, you just need to include in your version this:

    dbusEnv.get("GNOME_DESKTOP_SESSION_ID");

    In my Ubuntu I don't have this, only theses:

    XDG_SESSION_TYPE=x11
    DESKTOP_SESSION=ubuntu
    DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-cLtEoBPmgC
    SESSIONTYPE=gnome-session
    XDG_SESSION_ID=c2
    XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0
    XDG_SESSION_DESKTOP=ubuntu
    GDMSESSION=ubuntu
    DESKTOP_SESSION=ubuntu
    XDG_CURRENT_DESKTOP=Unity
    XDG_SESSION_DESKTOP=ubuntu

    EDIT: @tresf, looking at your linked issue I think that the problem is <3.7 fallback to swing, if you use this solution and version +3.7 it will be solved.

  16. tresf commented on Sep 19, 2017

    @tresf

    @dyorgio thanks. If you think you can tackle the linked stackoverflow article, we'd be willing to put a bounty on it.

  17. dyorgio commented on Sep 20, 2017

    @dyorgio
    Author

    @tresf Done :), please, tell us if it works or not.

  18. tresf commented on Nov 12, 2018

    @tresf

    @dorkbox thanks to the help of @dyorgio, we've shimmed some logic into another project which can read environment variables for the user which is running the sudo command...

    This is a bash script -- and one which makes quite a bit of assumptions -- but it seems to work rather well. Feel free to use any portions of it under whichever license you choose.

    #!/bin/bash
    
    # Provide user environmental variables to the sudo environment
    function sudo_env() {
        userid="$(logname 2>/dev/null || echo $SUDO_USER)"
        pid=$(ps aux |grep "^$userid" |grep "dbus-daemon" | grep "unix:" |awk '{print $2}')
        # Replace null delimiters with newline for grep
        envt=$(cat "/proc/$pid/environ" 2> /dev/null |tr '\0' '\n')
    
        # List of environmental variables to use; adjust as needed
        # UPSTART_SESSION must come before GNOME_DESKTOP_SESSION_ID
        exports=( "UPSTART_SESSION" "DISPLAY" "DBUS_SESSION_BUS_ADDRESS" "XDG_CURRENT_DESKTOP" "GNOME_DESKTOP_SESSION_ID" )
    
        for i in "${exports[@]}"; do
            # Re-set the variable within this session by name
            # Careful, this technique won't yet work with spaces
            if echo "$envt" | grep "^$i=" > /dev/null 2>&1; then
                eval "$(echo "$envt" | grep "^$i=")" > /dev/null 2>&1
    	    export $i > /dev/null 2>&1
    	elif initctl --user get-env $i > /dev/null 2>&1; then
                eval "$i=$(initctl --user get-env $i)" > /dev/null 2>&1
    	    export $i > /dev/null 2>&1
    	fi
    
            echo -e "        $i=${!i}"
        done
    }
    
    sudo_env
  19. dyorgio commented on Jun 14, 2019

    @dyorgio
    Author

    Hi guys,

    In last fedora (30) dbus-daemon was replaced (I guess) by dbus-broker-launch, but I can't make it works with SystemTray Lib, no appindicator is showing and if I pass mouse over tray area, process is killed by SIGTRAP signal....

    If I run same application as user, everything works... Anybody tried to run an app that uses this lib with root as another user with success on Fedora 30?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions