# UID/EUID subshell solutions

**URL:** <https://www.ruby-forum.com/t/uid-euid-subshell-solutions/79097>\
**Category:** Ruby\
**Created:** [December 12, 2006, 3:35am UTC](https://www.ruby-forum.com/t/uid-euid-subshell-solutions/79097 "2006-12-12T03:35:03Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![lynxinator](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/848f3c/32.png) [@lynxinator](https://www.ruby-forum.com/u/lynxinator)\
**Post date:** [December 12, 2006, 3:35am UTC](https://www.ruby-forum.com/t/uid-euid-subshell-solutions/79097/1 "2006-12-12T03:35:03Z")

</div>

Hi,

I’m having inconsistent behaviour with running external commands as  
other users, and the time has apparently come to use something akin  
to a fork and popen3 to get something approximating consistent  
bahaviour.

I’m currently setting EUID and executing external commands, but some  
shells ignore that (which is apparently the “standard”).

I need some solution that will allow me (when running as root) to run  
shell commands as another user and capture stdout and (hopefully)  
stderr. This basically means fork and run Process.uid = blah, but  
there’s some IPC to do too.

Is there a semi-standard pattern for doing this, or does someone have  
some simple example code I can use?

Thanks,  
Luke

## – The major difference between a thing that might go wrong and a thing that cannot possibly go wrong is that when a thing that cannot possibly goes wrong goes wrong it usually turns out to be impossible to get at or repair. – Douglas Adams, Mostly Harmless

Luke K. | [http://reductivelabs.com](http://reductivelabs.com) | [http://madstop.com](http://madstop.com)

---

<div class="post-metadata">

**Author:** ![lynxinator](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/848f3c/32.png) [@lynxinator](https://www.ruby-forum.com/u/lynxinator)\
**Post date:** [December 12, 2006, 4:17am UTC](https://www.ruby-forum.com/t/uid-euid-subshell-solutions/79097/2 "2006-12-12T04:17:08Z")

</div>

Luke K. wrote:

> Hi,
> 
> I’m having inconsistent behaviour with running external commands as  
> other users, and the time has apparently come to use something akin  
> to a fork and popen3 to get something approximating consistent  
> bahaviour.
> 
> I’m currently setting EUID and executing external commands, but some  
> shells ignore that (which is apparently the “standard”).

This is a very desirable shell behavior, to avoid an obvious hacker  
vulnerability.

> I need some solution that will allow me (when running as root) to run  
> shell commands as another user and capture stdout and (hopefully)  
> stderr. This basically means fork and run Process.uid = blah, but  
> there’s some IPC to do too.
> 
> Is there a semi-standard pattern for doing this, or does someone have  
> some simple example code I can use?

`su (username) -c (command)`

---

<div class="post-metadata">

**Author:** ![lynxinator](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/848f3c/32.png) [@lynxinator](https://www.ruby-forum.com/u/lynxinator)\
**Post date:** [December 17, 2006, 2:09am UTC](https://www.ruby-forum.com/t/uid-euid-subshell-solutions/79097/3 "2006-12-17T02:09:25Z")

</div>

On Dec 11, 2006, at 9:15 PM, Paul L. wrote:

> Luke K. wrote:
> 
> > I’m currently setting EUID and executing external commands, but some  
> > shells ignore that (which is apparently the “standard”).
> 
> This is a very desirable shell behavior, to avoid an obvious hacker  
> vulnerability.

I don’t see how it’s an obvious vulnerability; I thought the kernel  
was just as protective of UID as it as of EUID.

> > I need some solution that will allow me (when running as root) to run  
> > shell commands as another user and capture stdout and (hopefully)  
> > stderr. This basically means fork and run Process.uid = blah, but  
> > there’s some IPC to do too.
> > 
> > Is there a semi-standard pattern for doing this, or does someone have  
> > some simple example code I can use?
> 
> `su (username) -c (command)`

This isn’t very cross-platform, unfortunately; I’m looking more for a  
Ruby implementation, rather than shell, and I specifically require  
support on as many platforms as possible. This is for Puppet[1],  
which attempts to provide an abstraction layer across different \*nix  
machines, so it’s very important that it be as easy to make it work  
on many platforms.

1 - [http://reductivelabs.com/projects/puppet](http://reductivelabs.com/projects/puppet)

## – Like frozen sentries of the serengeti, the century-old termite mounds had withstood all tests of time and foe - all tests, that is, except the one involving drunken aardvarks and a stolen wrecking ball." – Gary Larson

Luke K. | [http://reductivelabs.com](http://reductivelabs.com) | [http://madstop.com](http://madstop.com)

---

<div class="post-metadata">

**Author:** ![lynxinator](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/848f3c/32.png) [@lynxinator](https://www.ruby-forum.com/u/lynxinator)\
**Post date:** [December 20, 2006, 7:29pm UTC](https://www.ruby-forum.com/t/uid-euid-subshell-solutions/79097/4 "2006-12-20T19:29:04Z")

</div>

On Dec 11, 2006, at 8:33 PM, Luke K. wrote:

> Hi,
> 
> I’m having inconsistent behaviour with running external commands as  
> other users, and the time has apparently come to use something akin  
> to a fork and popen3 to get something approximating consistent  
> bahaviour.

This ended up being my solution:

[http://madstop.com/articles/2006/12/19/shell-commands-and-uid](http://madstop.com/articles/2006/12/19/shell-commands-and-uid)

```
 def execute(command, user = nil, group = nil)
     IO.popen("-") do |f|
         if f
             text = f.read
             return text
         else
             $stderr.close
             $stderr = $stdout.dup
             Process.uid = user if user
             Process.gid = group if group
             system(*command)
             exit!
         end
     end
 end

```

## – Men never do evil so completely and cheerfully as when they do it from a religious conviction. --Blaise Pascal

Luke K. | [http://reductivelabs.com](http://reductivelabs.com) | [http://madstop.com](http://madstop.com)
