3

Say one has a resource hungry command that users on a server need to run. I want to wrap said command with a wrapper script that will parse the arguments passed and ensure that the command is only being used under certain conditions or times.

The problem is that if the program itself is not executable the wrapper won't be able to run it either. I'd also like the command not to run as root.

Is this possible?

10
  • Interesting question. I'm not sure what you mean by not wanting the command to be executed as root, though. I was assuming you were asking about sudo configuration. How do you plan to limit permissions to the executable in the first place?
    – Wildcard
    Dec 31 '15 at 7:45
  • @Wildcard - I'm not sure. I was thinking of somehow turning off executable permissions for all users, and then perhaps running the script through a group that does, but I'm really not sure.
    – nbubis
    Dec 31 '15 at 7:49
  • i dont get it - if the program is not executable, then how would it be run with any number of arguments under any condition? i mean - how do you usually run it?
    – mikeserv
    Dec 31 '15 at 7:56
  • @mikeserv right now all users have exec permissions. I want them to only be able to run the command under certain conditions that will be determined by my wrapper
    – nbubis
    Dec 31 '15 at 8:00
  • well, if it is a wrapper that determines it, then just do that thing you said with groups. user/group nobody is often used like that. read your wrapper on a shell's stdin - save no input history. put the execution code in a function: ok(){ your_program; }, the condition checks in another. if the checks turn out do nothing, if not redefine the execution function: ok(){ exec <&- </dev/null; } and call ok at the tail end of the checks regardless.
    – mikeserv
    Dec 31 '15 at 8:09
2

The simple answer is: It is not possible to force your users to use your wrapper script.

The reason for this is fairly simple; a shell script is an interpreted program. That means that bash (or some other shell process) must read the file in order to run the commands that are called in it.

This in turn means that a user who has permission to run the wrapper script, must have permission to do everything that is done in the wrapper script. In the vast majority of cases*, a shell script, even one with lots of internal logic and conditionals, does exactly the same thing when you run it as it would if you typed the entire script into your command prompt, line by line.

If you are merely trying to make it difficult for uneducated users to slow down your system, there are a multitude of ways of doing this, such as what @mikeserv suggests in a comment on your question. I can think of at least five more ways offhand**, many of which could be used in combination; the crucial thing to understand about these is that they're not secure. They don't actually prevent the user from using the command directly instead of the wrapper script, and they also don't (and can't) prevent the user from making his own copy of the wrapper script (which he must have read permissions on to be able to run at all) and modifying it however he likes.

It is possible to write a short C program to perform the function of your wrapper script, which compiles to a binary executable, and then make that C program SUID*** so it is the only way the user can run the command you are talking about, but that's beyond my scope and area of expertise.

Other options involve extremely odd workarounds (hacks) like setting a cronjob to modify your sudoers file to allow permissions to run the command only during specific times of day...but that's getting really, really weird and Bad Idea territory.


I think the standard way to accomplish this (although still without forcing tech-savvy users to use your wrapper script) would be:

(I'll pretend the command to restrict is date.)

  1. Ensure that inside your script, its call to date uses the absolute path: /bin/date (You can find out what this is by running which date.) Also ensure your script has a proper shebang, so that it can be run without needing to type bash ./myscript but can just be run as ./myscript, and ensure it is readable and executable by everyone. (chmod 555 myscript)
  2. Put your wrapper script in /usr/local/bin/ and rename it as date.
  3. Check that users have /usr/local/bin at the start of their $PATH variable. (Just log in as a user and run echo "$PATH".) They should already have this by default. It doesn't have to be at the very start as long as it's in their path before /bin (or whatever the location of the original date command is).

If they don't have it in their path, you can add it by running: echo 'PATH="/usr/local/bin:$PATH"' | sudo tee /etc/profile.d/my_path_prefix.sh

Now any time a user tries to run the command directly, he will actually be running your wrapper script, because the directory where your wrapper script is appears first in his $PATH.


A much more hack-y "blackhat" sort of a solution would be to actually mask the original binary, not by putting another version earlier in the path for users, but by putting the wrapper script in place of the command itself, in its original location. Use at your own risk:

  1. Put the command itself somewhere outside the normal bin directories so no one has it in their path. You could move it to, for example, /var/local. (There may be a better place, but this is a hack already, so it doesn't matter much, does it?)
  2. Ensure that the call to the date within your wrapper script points to the new location for date—its absolute path: /var/local/date in my example.
  3. Move your wrapper script into date's old location, with date's original name.

The main caveat is that every time anyone tries to run that command, including system init scripts, they will get your wrapper script instead.

This is purely a hack and would not qualify as good system administration. But it is possible and you may as well know that it could be done. The better solution is what I posted above.


*The exceptions to this have to do with modifying the environment and programs that behave differently when they are run interactively vs. when they are run from a script. These exceptions have nothing to do with permissions, though, so they're not relevant to this discussion.

**Ask about them in the comments if you are interested and I'll expand on them.

***NOT suid root. If you do this, just create a user, put him in a group which is the only one with permission to run the command you are talking about (chmod 010 or something) and then chown your fresh-compiled wrapper binary to be owned by that user and set its suid bit with chmod 4511.

7
  • What makes a C code program different from a script?
    – nbubis
    Dec 31 '15 at 8:43
  • @nbubis, because executing a compiled C program only depends upon having execute permission, not read permission, and because the suid bit cannot apply to scripts. This is how it is possible for some binary executables (such as compiled C programs) to do things that the user running them does not have permission to do, such as change the /etc/passwd file by running passwd—such binaries have the suid bit set to make this possible.
    – Wildcard
    Dec 31 '15 at 8:56
  • @nbubis, by the way, a "binary" or "binary file" just means that the contents of the file is not just text. It might even include text, like a Microsoft Word document, but it's not just text in the file. (A .doc has a lot of formatting information.) An executable binary such as a C program only has meaning to the computer; it's instructions for the computer to execute rather than text for a human to read. C programs are compiled, that is, turned into machine instructions for the computer, from C source code which is written by humans and read by humans. Does that help? :)
    – Wildcard
    Dec 31 '15 at 9:15
  • Can't I get the same effect by just adding ALL HOST command to/etc/sudoers?
    – nbubis
    Dec 31 '15 at 9:20
  • @nbubis I thought you didn't want the command to run as root? If you don't mind having the command run as root, then sure, add it to sudoers. But how does that help with your wrapper script conditional checks?
    – Wildcard
    Dec 31 '15 at 9:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.