iconv_open fails when suid bit is on [SOLVED]

iconv_open fails when suid bit is on [SOLVED]

Elazar Leibovich elazarl at gmail.com
Mon Feb 13 14:56:28 IST 2012


On Mon, Feb 13, 2012 at 12:22 PM, Yedidyah Bar-David <
linux-il at didi.bardavid.org> wrote:

>
> Indeed, and to strace programs that do this, I do something like that:
>

Thanks! Worked like a charm. Here's the trouble:

[pid 31526] open("$ORIGIN/tls/i686/sse2/libKSC.so", O_RDONLY) = -1 ENOENT
(No such file or directory)
[pid 31526] open("$ORIGIN/tls/i686/libKSC.so", O_RDONLY) = -1 ENOENT (No
such file or directory)
[pid 31526] open("$ORIGIN/tls/sse2/libKSC.so", O_RDONLY) = -1 ENOENT (No
such file or directory)
[pid 31526] open("$ORIGIN/tls/libKSC.so", O_RDONLY) = -1 ENOENT (No such
file or directory)
[pid 31526] open("$ORIGIN/i686/sse2/libKSC.so", O_RDONLY) = -1 ENOENT (No
such file or directory)
[pid 31526] open("$ORIGIN/i686/libKSC.so", O_RDONLY) = -1 ENOENT (No such
file or directory)
[pid 31526] open("$ORIGIN/sse2/libKSC.so", O_RDONLY) = -1 ENOENT (No such
file or directory)
[pid 31526] open("$ORIGIN/libKSC.so", O_RDONLY) = -1 ENOENT (No such file
or directory)
... (fallback to other library locations)

vs a good run of
open("/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = 3
open("/usr/lib/gconv/UHC.so", O_RDONLY) = 3
open("/usr/lib/gconv/tls/i686/sse2/libKSC.so", O_RDONLY) = -1 ENOENT (No
such file or directory)
open("/usr/lib/gconv/tls/i686/libKSC.so", O_RDONLY) = -1 ENOENT (No such
file or directory)
open("/usr/lib/gconv/tls/sse2/libKSC.so", O_RDONLY) = -1 ENOENT (No such
file or directory)
open("/usr/lib/gconv/tls/libKSC.so", O_RDONLY) = -1 ENOENT (No such file or
directory)
open("/usr/lib/gconv/i686/sse2/libKSC.so", O_RDONLY) = -1 ENOENT (No such
file or directory)
open("/usr/lib/gconv/i686/libKSC.so", O_RDONLY) = -1 ENOENT (No such file
or directory)
open("/usr/lib/gconv/sse2/libKSC.so", O_RDONLY) = -1 ENOENT (No such file
or directory)
open("/usr/lib/gconv/libKSC.so", O_RDONLY) = 3

Some googling lead me to another software having this problem:

   54 #ifdef SECURE_MAN_UID   55 	/* iconv_open may not work correctly
in setuid processes; in GNU   56 	 * libc, gconv modules may be linked
against other gconv modules and   57 	 * rely on RPATH $ORIGIN to load
those modules from the correct   58 	 * path, but $ORIGIN is disabled
in setuid processes.  It is   59 	 * impossible to reset libc's idea
of setuidness without creating a   60 	 * whole new process image.
Therefore, if the calling process is   61 	 * setuid, we must drop
privileges and execute manconv.   62 	 *   63 	 * If dropping
privileges fails, fall through to the in-process   64 	 * code, as in
some situations it may actually manage to work.   65 	 */

Alas, complexity<http://neugierig.org/software/blog/2011/04/complexity.html>is
indeed a problem.

To make a long story short:

1) The linux linker let you add to rpath (so search path for a specific
binary) the symbol $ORIGIN, which is resolved in runtime to the binaries'
path.

2) iconv_open uses this feature to locate additional library at run time
(at least in my version).

3) This feature doesn't work when running suid binaries (at least in my
CentOS specific version) for security
reasons<http://seclists.org/fulldisclosure/2010/Oct/257>
.

4) Thus iconv_open don't find it's library path, assumes that no such
encoding exist on the system, and fails with "illegal argument" errno.

A possible workaround is to create symbolic links to all files in
/usr/lib/gconv in the ldd path, enabling iconv to find them even without
using the $ORIGIN ldd feature.

For the record, my glibc version is glibc-2.5-49.el5_5.7.

Thanks!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.cs.huji.ac.il/pipermail/linux-il/attachments/20120213/6b416a30/attachment.html>


More information about the Linux-il mailing list