tags:

views:

137

answers:

4

Hello,

I am writing an application that requires root user privileges to execute. If executed by a non root user, it exits and terminates with a perror message such as:

    pthread_getschedparam: Operation not permitted

I would like to make the application more user friendly. As part of its early initialization I would like it to check if it is being executed by root or not. And if not root, it would present a message indicating that it can only be run by root, and then terminate.

Thanks in advance for your help.

+8  A: 

getuid or geteuid would be the obvious choices.

Jerry Coffin
Might want to explain the difference...
R..
Thank you. I have easily created the logic that uses getuid(), and it now does what I wanted.
John Rocha
+8  A: 

I would recommend NOT making this change, but instead improving your error message. It's doubtful that your application actually needs to "be root"; instead it needs certain privileges which root has, but which operating systems with fine-grained security controls might be able to grant to the application without giving it full root access. Even if that's not possible now, it may be possible 6 months or 2 years from now, and users are going to be irritated if your program is refusing to run based on backwards assumptions about the permission model rather than just checking that it succeeds in performing the privileged operations it needs to.

R..
With things like AppArmor and SELinux, the reverse is true as well, the process can be running as root and not be able to access some of the things you take for granted (such as being able to write anywhere), so I agree, a more precise error message is the better option.
HalfBrian
I hear what you are saying, but this error message is out of my hands. It comes from perror() and/or strerror(). Moreover, its not immediately clear what the fault reason is.In this case the errno returned was EPERM which perror() and strerror() translated into "Operation not permitted"When reading the man pages for pthread_setschedparam() (ACK, I just realized a typo in my error output above), it wasn't immediatelyobvious to me which errno was returned, but I eventually honed in on EPERM which has two fault reason which boiled down to "user permissions" or "invalid parameters"
John Rocha
Although, I suppose I could add this getuid() check if the pthread_setschedparam() fails with EPERM, and if its not root give a suggestion to try again as root?Ultimately this will protect me from my QA team which will run the application as non-root, it'll fail with the message listed above and they'll log a defect saying its broken. Even if the documentation says it must be run with root privileges. I want to try and make it as clear as possible at the failure point what the problem is.
John Rocha
When you call pthread_setschedparam, check and see if it fails with EPERM. If so, print a nice message that the user lacks permissions needed for the program to function and suggest running as root.
R..
+5  A: 

What you really want to check for is if you have the right capability set (CAP_SYS_NICE I think is the capability you need) see man pages capabilities (7) and capget (2) this way it won't error out if you have the ability to do what you want, but you aren't root.

Spudd86
Capabilities are very Linux-specific, so using this method will hurt the portability of your program. My favorite way to test for the ability to perform privileged operations is just to try the operation and check for errors.
R..
@spudd86: Thanks for the tip. I will look into this.@R..: Thanks for the warning. Coincidentally enough I am writing a Linux application. Granted portability is nice. I could abstract this check so that if it is ported to another platform they can extend the check as appropriate for their platform.
John Rocha
Well if it's just for the sake of printing friendlier output, you could just put it all inside #ifdef HAVE_CAPABILITIES or such, and thereby skip the code if it's run on other systems.
R..
+3  A: 
#include <unistd.h> // getuid
#include <stdio.h> // printf

int main()
{
    if (getuid()) printf("%s", "You must be root!\n");
    else printf("%s", "OK, you are root.\n");
    return 0;
}
Vanni Totaro
+1 for writing `if (getuid())` rather than `if (getuid()!=0)`. :-) If the program is supposed to work with suid though, you may want to use geteuid() rather than getuid().
R..