Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Root running Informix utilities via su -c

125 views
Skip to first unread message

Red Valsen

unread,
Oct 20, 2003, 9:56:24 AM10/20/03
to
This dead horse has had the flesh flayed from its bones years ago, but
I discovered a new twist -- which purportedly didn't work.

I attempted to run an alter statement during a postinstall script in a
Solaris pkgadd package thus:

su informix -c "alter table bla add (col1 char)"|dbaccess
databasename

On one database -- which some dork had granted privileges to root --
the statement ran just fine; the other, configured correctly for
production, received "No connect permission" error. Fine and well --
CDI posts from 4/2001 indicate this should happen. However, I
implemented the workaround from those posts which should have failed,
but didn't: I modified the postinstall script to cat out the alter
statement to a file; chowned the file to 'informix' and chmoded it
SETUID, too; then had root execute the file as informix:

su informix -c commandfile

WTF? It worked this time. So: Executing from the command line won't
work, but from a SETUID script file it does. Can somebody (Jonathen?)
explain this weird phenomenon? -- in one case dbaccess is getting the
real userid of 'root', in the other case 'informix', all by chmod'ing
4xxx?

Running IDS 7.31.UC-4 on Solaris 2.7/Intel (don't ask).

Art S. Kagel

unread,
Oct 20, 2003, 4:34:07 PM10/20/03
to
On Mon, 20 Oct 2003 09:56:24 -0400, Red Valsen wrote:

Su only forks once which leaves the real user id accessible. But the SETUID
bit causes the shell to perform a fork also after changing the userid which
now, along with the fork performed by the 'su informix', makes for two forks as
'informix' which obliterates the original real userid. That's how it's done in
servers that need to run as a particular user with their real and effective
userids changed - fork twice after changing user ids.

Art S. Kagel

Jonathan Leffler

unread,
Oct 21, 2003, 1:36:36 AM10/21/03
to
Red Valsen wrote:

> This dead horse has had the flesh flayed from its bones years ago, but
> I discovered a new twist -- which purportedly didn't work.
>
> I attempted to run an alter statement during a postinstall script in a
> Solaris pkgadd package thus:
>
> su informix -c "alter table bla add (col1 char)"|dbaccess
> databasename

Hmmmm...taken literally, that sets the real and effective UID to
informix and runs a shell that runs a command called alter with
arguments 'table', 'bla', 'add', and probably syntax errors on the
open parentheses - or does something with a subshell and a program
called col1 given an argument char. The non-erroneous output from
that is sent to dbaccess databasename (presumably, email/news put a
linebreak in the wrong place).

Note that DB-Access is signally not run SUID anything. If you want
DB-Access run like that too, the whole process needs to be done rather
differently:

echo 'alter table bla add (col1 char(1) not null)' |
su informix -c "dbaccess databasename -"

This runs the echo command as root (it'll probably work), and the
dbaccess command as informix, rather than vice versa. [You also
forgot the NOT NULL constraint, and the size of a CHAR field is
CHAR(1); I prefer to be explicit :-) Of course, NOT NULL doesn't work
if the table already has data in it, unless you also specify a default
clause - but that is then concentrating too much on the SQL and not
enough on the Unix!]

I don't like that much either; I'd write:

su informix -c "sqlcmd -d databasename -e 'alter table bla add(col1
char(1) not null)'"

(Actually - the echo | su formulation is version 2; it isn't as bad as
version 1 which had both the echo and the dbaccess running as
informix. That was messier - and more worthy of "I don't like that
much".)

> On one database -- which some dork had granted privileges to root --
> the statement ran just fine; the other, configured correctly for
> production, received "No connect permission" error. Fine and well --

Yes - the error was probably correct.

> CDI posts from 4/2001 indicate this should happen.

Found them. TinyURL saves 325 characters:

http://tinyurl.com/rp7d

> However, I
> implemented the workaround from those posts which should have failed,
> but didn't: I modified the postinstall script to cat out the alter
> statement to a file; chowned the file to 'informix' and chmoded it
> SETUID, too; then had root execute the file as informix:
>
> su informix -c commandfile
>
> WTF? It worked this time.

Of course - as I explained earlier, it is the DB-Access command that
must be run as user informix. By putting everything - echo/cat and
dbaccess into the commandfile, everything in there is run by informix,
so it works as you wanted.

Please remove the SETUID permissions from the script - SETUID scripts
are even more fraught with danger than SUID programs. Not to mention
that it had no effect on the process anyway.

> So: Executing from the command line won't
> work, but from a SETUID script file it does. Can somebody (Jonathen?)

Err, is that me, Rad? :-)

> explain this weird phenomenon? -- in one case dbaccess is getting the
> real userid of 'root', in the other case 'informix', all by chmod'ing
> 4xxx?

In the first case, you didn't run DB-Access with the su command.
In the second case, you did.
In the first case, the real UID of DB-Access was root because you had
not changed it with su informix.
In the second case, the real UID of DB-Access was informix because the
whole command was run by 'su informix'.

> Running IDS 7.31.UC-4 on Solaris 2.7/Intel (don't ask).

Thanks for the platform information - not incredibly important this
time, but always a good idea to include it.

--
Jonathan Leffler #include <disclaimer.h>
Email: jlef...@earthlink.net, jlef...@us.ibm.com
Guardian of DBD::Informix v2003.04 -- http://dbi.perl.org/

Jonathan Leffler

unread,
Oct 21, 2003, 2:03:59 AM10/21/03
to
Art S. Kagel wrote:

> On Mon, 20 Oct 2003 09:56:24 -0400, Red Valsen wrote:
>
> Su only forks once which leaves the real user id accessible. But the SETUID
> bit causes the shell to perform a fork also after changing the userid which
> now, along with the fork performed by the 'su informix', makes for two forks as
> 'informix' which obliterates the original real userid. That's how it's done in
> servers that need to run as a particular user with their real and effective
> userids changed - fork twice after changing user ids.

Dear Art,

Are you sure?

The purpose of the 'su' command is to set both the real and effective
user ID of the process. I'm pretty sure it also removes the saved UID
too - I'd take that under advisement. And su doesn't fork - it exec's!

At USENIX 2002, Chen Wagner and Dean presented a paper called "Setuid
Demystified" which described the behaviour of the various setuid()
variant system calls on different platforms. You can find it online
at http://www.cs.berkeley.edu/~daw/papers/setuid-usenix02.pdf (Google
on the title and feeling lucky).

Now, when the shell is run by 'su', it has real and effective UID of
informix (su informix -c "something..."). If that something is a SUID
informix shell script, one of a few things happens - slightly
dependent on your Unix platform. Most likely, the SUID property is
ignored. Failing that, the kernel notes that the script is SUID
informix and carefully changes the effective UID from informix to
informix. However, since the script didn't seem to have a #!/bin/sh
at the top, I'd lay odds that the SUID properties were ignored. The
shell might notice that the command was simply 'commandfile' and read
the file itself, or it might fork and the child might read the file
and execute the contents (while the parent waits for the child to exit
so it can exit too).

I don't recognize the double fork stuff as an idiom that works with
UID setting issues. It might be relevant to daemon processes wishing
to ensure they are not affected by the death of the shell that invoked
them - but that's not done like that for anything to do with [RES]UID
values.

>>This dead horse has had the flesh flayed from its bones years ago, but I
>>discovered a new twist -- which purportedly didn't work.

[...see other response directly to Red's question...]

Red Valsen

unread,
Oct 21, 2003, 9:15:38 AM10/21/03
to
Mercy bocoo to the two luminaries of CDI for their replies -- I learned something.

This definitely works without resorting to cat'ing out the script:

echo 'alter table bla add (col1 char(1) not null)' |
su informix -c "dbaccess databasename -"

Always a better way -- and someone who can explain . . .

Jonathan Leffler <jlef...@earthlink.net> wrote in message news:<3F94C5E3...@earthlink.net>...

0 new messages