LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Execute with group permission but write with other permission? (https://www.linuxquestions.org/questions/linux-newbie-8/execute-with-group-permission-but-write-with-other-permission-4175459814/)

Karmaflute 04-27-2013 03:48 PM

Execute with group permission but write with other permission?
 
I want to allow users of a group to execute a script which then writes out to a file. I want users to run this script to write to the file but not be allowed to write to the file directly.

How might I accomplish this?

chrism01 04-27-2013 06:59 PM

I think you'd have to use suid if this was a binary, causing the program to run as the program user, not as the user.
However, suid is not honoured by the kernel for scripts, due to security issues.
Running a script is the same as running the cmds yourself, so I'm not sure you can accomplish what you want.
Perhaps if you told us why you think you need this ie what are you trying to achieve.

You could try using inotifywait to change the file ownerships upon creation http://linux.die.net/man/1/inotifywait.
See here http://www.linuxquestions.org/questi...364/page2.html

Erik_FL 04-27-2013 07:08 PM

You may be able to use the "setuid" bit on the script to run it as a different user. In other words, a non-privileged user runs the script, but the script file has the "setuid" bit set on its permissions. The owner of the script has permission to write the file. Alternatively you can use "setgid" to run the script as a member of a different group.

Some Linux distos do not allow "setuid" (and possibly not "setgid") for scripts.

Here's a link to a good explanation about that.

Tuxation - setuid on shell scripts


As an example, suppose you give "mygroup" execute permission for a script or program. That means the program's group id must be "mygroup". If the owner of the program is "mygroupadmin" then you also set the "setuid" bit so the program runs as "mygroupadmin" no matter who runs the program. The program creates a file, and sets the file permissions to deny "mygroup" write premission. The file has "mygroupadmin" as the owner with write permission.

You have to be careful about other permissions too. If "mygroup" has write access to the directory, then anyone in the group can delete the file. To prevent file deletion you have to deny directory write access to "mygroup". Or, set the "sticky" bit on the directory so that only the owner of the directory or owner of files in the directory can delete files.

Since the program is creating and writing a file, you also have to be careful of how symbolic links are handled in the directory. For example, if someone creates a symbolic link having the file name, then the program might write to a completely different file. To avoid that problem, set the "sticky" bit on the directory.

Although it is tempting to use "setuid" to run a program as "root" you should avoid doing that. Create a separate user account just for running the program. Give the user account only the minimum required permissions and group membership in order to do what it needs.

When a program creates files, the default is to create files owned by that user, and the primary group of that user. Set the user's primary group to the group that you want to own the files it creates. You can add other groups for the user as secondary groups to allow access to files belonging to those other groups.

Karmaflute 04-28-2013 01:43 PM

I've written a C++ program and given it the user stick bit (chmod u+s). I can confirm that when the group user (505) runs the application their effective userid is the owner (503) by doing this:

Code:

cout << geteuid() << endl
As expected, it outputs 503 (the file owner).

However, if I execute the program as 505 (the group user) and have it try to open a file owned by 503 using ofstream, I get a permission denied error. When executed by 503, the program runs and the file opens just fine with ofstream.

When using system() in the program to run a shell script which echos $UID it displays "505" instead of the expected "503".

Why is it that the program runs as the owner but cannot then write to files or run programs as that user? It reverts back to 505.

lleb 04-28-2013 01:48 PM

Quote:

Originally Posted by chrism01 (Post 4940233)
I think you'd have to use suid if this was a binary, causing the program to run as the program user, not as the user.
However, suid is not honoured by the kernel for scripts, due to security issues.
Running a script is the same as running the cmds yourself, so I'm not sure you can accomplish what you want.
Perhaps if you told us why you think you need this ie what are you trying to achieve.

You could try using inotifywait to change the file ownerships upon creation http://linux.die.net/man/1/inotifywait.
See here http://www.linuxquestions.org/questi...364/page2.html

question, for something like that could he use su -c user "foo" to execute something as an other user? or would that require the script to originally be run as root or with an expect script passing the other users password in plane text?

Karmaflute 04-28-2013 02:03 PM

User 505 does not have permission to run applications owned by 503. I use the u+s sticky bit to allow 505 to execute a program owned by 503 "as" 503 using group permission and the user stick bit.

Erik_FL 04-28-2013 03:18 PM

Quote:

Originally Posted by Karmaflute (Post 4940646)
When using system() in the program to run a shell script which echos $UID it displays "505" instead of the expected "503".

Does the program call the function "setuid(503)" before running the shell script? Without that I believe that any child processes will have the real user ID, 505 instead of the program's user ID.

Karmaflute 04-28-2013 03:22 PM

I tried that. Even though geteuid() returns 503, getuid() still returns 505 despite calling setuid(503) in the actual C++ code. The sticky bit automatically sets the effective user id (geteuid()) but not the actual user id (setuid()). setuid() is supposed to set this but it does not.

Edit:

I've found that by calling this:

Code:

setreuid(geteuid(), -1)
I can set the real user id to the effective userid (what I'd expected setuid() to do). Now both geteuid() and getuid() return 503 (the file owner) rather than 505 (the group user executing the program).

However, I am still unable to write to a file owned by 503.

Any other suggestions?

Karmaflute 04-28-2013 03:38 PM

I was wrong. setreuid() did indeed fix the problem; I had a typo which made it appear as if the problem persisted.

I am using CentOS 6.4. It's possible that for security reasons it requires applications to explicitly set themselves to the real user id rather than the effective user id to take advantage of the sticky bit.

The solution in c/c++ is to use setreuid(). Is there alternative to this function for use in bash scripts?

PTrenholme 04-28-2013 03:43 PM

Consider setting up a process to write the file and using dmesg request the process to write the data. The write message would need to include the pid of the requesting process, and it could do some confirmation processing (sending additional messages as needed) to confirm that the requesting process is one authorized to write to the file.

In this approach, only the daemon would actually need the write permission, not the script or user. (The script could start the daemon with a suid if necessary, but you could start it as a system service during boot, and have it wake up when dmesg needed it.)

Karmaflute 04-28-2013 03:55 PM

I'm already doing something similar with a poll script and a queue file. The problem is that if I were to allow scripts to write to the queue with group permission then I would have to give the group itself permission to write to the queue; which is a security hole if I want to restrict which users in the group get to send which commands to the queue.

By using the sticky bit on a file which only its owner has permission to write to the queue, I can effectively close this loop. I can then limit which users can access which commands by setting permissions on the sticky-bit file. Only users who can run this file get to write to the queue.

Erik_FL 04-28-2013 04:32 PM

Probably only "root" can change the user ID, but that should not matter since the effective user ID should be used to determine file access permissions.

I have three other suggestions.

There is a "setfsuid( )" function that you can use to set the user ID for file accesses. You should not have to use "setfsuid( )" because "seteuid( )" should have set the file-system user ID.

Make sure that the script file does not have the "setuid" bit set. That could change the effective user ID back to 505 when running the script.

If you still cannot gain access the the file, make "root" the owner of the program. Then have the program call "setuid(503)" or "seteuid(503)". Using "setuid(503)" is preferred since it permanently reduces privilege.

Unfortunately I haven't written any Linux programs so I can't give you any advice from experience. There are quite a few explanations on the Internet of the various functions to set the user ID.

chrism01 04-28-2013 06:35 PM

You could also use sudo to enable the group to run the prog (or even a script) as a completely different user.
The output file would then be unavailable to the group, assuming it (file) has a different group setting as well.

PTrenholme 04-29-2013 01:04 PM

Quote:

Originally Posted by Karmaflute (Post 4940700)
[...]which is a security hole if I want to restrict which users in the group get to send which commands to the queue.[...]

Why not create another group for that sub-group of users?:scratch: There is no (practical) limit to the number of groups of which a user cane be a member.

chrism01 04-29-2013 08:51 PM

He also said
Quote:

but not be allowed to write to the file directly.
If they are in the group that runs the prog to create the file, normally they'd be able to access the file directly as well...


All times are GMT -5. The time now is 10:41 AM.