3

I'm trying to write a program and integrate it with gui built with Gtk+. The exe that is to be called by the gui however has the setuid bit set. However gtk does not allow this exe to run as specified by the gtk community. They however say that we have to write separate helper programs and all. I really dont understand what that means. Can anyone please shed some light on how to overcome this problem? I really need an immediate solution.

3 Answers3

4

I think that the GTK+ team's heart is in the right place when they warn here against using GTK+ in setuid programs. But I have two observations, and a workaround.

First, it is one thing to warn against such a practice, and another thing entirely to make such a practice seemingly impossible. It irritates me to think of designers who say "There is no valid reason for users to do XXX", and then go out of their way to make XXX impossible. Warn of the risk, and let the user take the risk.

Second, the GTK+ team confuses "setuid" with "setuid root". Here's an example of where the distinction is important. In this example, I want not to expand the privileges of a program using GTK+, but to reduce them. Under certain circumstances, I want to be able to run Firefox (well, iceweasel, but it's basically the same) crippled so it can look at only local files, with no network capability. So I've set up iptables in my Linux system so that a particular (artificially created) user has no access to the outside world. I want to be able to run Firefox as that user, no matter which user I actually am. Assuming that the restricted user's uid and gid are 1234, the following general idea will work. Build it as setuid root. Hope this helps.

EDIT 2014-02-22 15:13 UTC

I neglected to mention that you can substitute 0 for each 1234, and you've got root. One could argue that this would be a totally bad idea, and I guess I can understand that point.

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int    ar_argc,
     char **ar_argv
    )
{
  setenv("HOME","/u/wally",1);

  /* Set other environment variables as appropriate. */

  if(setgid(1234))
  {
    fprintf(stderr,"setgid() fail\n");
    exit(1);
  };
  if(setuid(1234))
  {
    fprintf(stderr,"setuid() fail\n");
    exit(1);
  };

  /* Use execl() and friends, or system(), to do what you want here. */

  return 0;
}
Bill Evans at Mariposa
  • 3,590
  • 1
  • 18
  • 22
  • 1
    To add the last little bits for others: add "system(ar_argv[1]);" under that comment, save this code as wally.c, then: switch to root (e.g. "sudo su"), build it (e.g. "gcc -o wally wally.c"), setuid it (e.g. "chmod +s wally"), switch back to normal user (e.g. "exit"), run it (e.g. "./wally firefox") – 8forty Oct 04 '17 at 15:38
4

First question: why is your program setuid? Writing setuid programs is not a game that should be played by self-professed Linux newbies. They're dangerous. They're useful - do not get me wrong. But they are dangerous and difficult to write securely.

The GTK+ project states their view on setuid programs very forthrightly at 'GTK+ - Using setuid'. They give their reasons - good ones. They indicate how to avoid problems:

In the opinion of the GTK+ team, the only correct way to write a setuid program with a graphical user interface is to have a setuid backend that communicates with the non-setuid graphical user interface via a mechanism such as a pipe and that considers the input it receives to be untrusted.

Since you're supposed to write a helper program, have you looked for examples? It is likely that they're given. Is your program itself a GUI application?


I need root privileges [...] to open some peripheral devices, read the data available in their memory, and then close them...this cannot be done without root perms...also the data read is processed and displayed simultaneously using GTK.

So, this is exactly the sort of scenario that the GTK+ team describe. You need a small setuid root program that is launched by your GUI, and that is connected to it by pipes or a Unix-domain socket, or some similar technique.

When you need data from the peripheral, your main application writes a request to the daemon/helper and then waits for a response containing the data.

In outline, you will have code in your GUI to:

  • LaunchDaemon(): this will create the plumbing (pipes or socket), fork, and the child will sort out the file descriptors (closing what it does not need) before launching the daemon process.
  • RequestDaemon(): this will package up a request to the daemon/helper, writing the information to the daemon, and reading back the response.
  • TerminateDaemon(): this will close the connections to the daemon/helper; it will know that it has no more work to do and will exit.

Meanwhile, your daemon/helper program will:

  • Settle into a nice comfy loop that:
    • reads a request from standard input
    • checks it for validity
    • executes the request
    • formats a response (error, or normal)
    • writes that back to the main GUI
    • repeats
  • When it gets EOF from the input, it terminates.
  • If at all possible, it will open the device once, and then drop root privileges.
    • This minimizes the exposure to attack.
    • If the program is no longer running as root, it cannot be abused into doing things that only root can do.
    • Once a file is open, the permissions are not checked again (so the daemon running as root can open the file, and then throw away its root privileges, if it won't reopen the file).

You should still look at whether the permissions on the peripheral are correct - or why you are needing to read data from something that only root is supposed to be able to read from.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1) yeah..true i am a newbie...but i kno what my program is doing...it will not run without suid as it needs root permissions to run...2) i am looking out for examples on the net...some people say we mmust use sockets...i'm still searching for a good example...3) yeah....the other program that needs to be called by the main gui is also a gtk program..it has to display a few images after processing them....but my doubt still remains...wat is exactly meant by a helper program – linuxnewbie Jan 16 '11 at 15:23
  • Why does your program need root privileges? Do not write GUI programs that need root privileges - they're too damn dangerous (that's the gist of what the GTK+ team says, and I agree with them; they cannot guarantee that there aren't devastating security flaws in the system that an attacker can abuse). What exactly does your program need root privileges for? Can you have a daemon program that is non-GUI (small) and setuid that gets a request from your GUI code, carefully does whatever it is that needs root privileges, and sends back an answer to the requesting (GUI) program? If not, why not? – Jonathan Leffler Jan 16 '11 at 15:34
  • i need root previledges coz i need to open some peripheral devices and read the data available in their memory and then close them...this cannot be done without root perms...also the datra read is processed and displayed simultaneously usin gtk... – linuxnewbie Jan 16 '11 at 15:40
0

Often, it is better to set up the system such that the device files can be opened by a non-root user, and then let normal non-root processes talk to them.

ndim
  • 35,870
  • 12
  • 47
  • 57