fopen() calls __open()

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

fopen() calls __open()

Derrell Lipman
Hi all,

I'm on the Samba team, responsible for the client library, which provides
Unix/Linux access to Windows networks.  As an example program for using that
library, I have an LD_PRELOAD library that traps primitive file system calls
and if the path is to /smb/... it maps to the Samba client library; otherwise
to RTLD_NEXT (glibc).  This all works great for most programs.  For the
primitives that are mapped, three versions of each are mapped: 0, 1 and 2
leading underscores (if such functions actually exist in the C library).  For
example, I map open, _open and __open (assuming they exist in the library).

The problem is that some internal non-primitive functions like fopen()
directly call __open(), and (from my read of the source, it appears that)
__open() is aliased to open() such that fopen()'s call to __open() isn't
trapped by my preload library.  This means that if the file
/smb/SERVER/SHARE/filename is open()ed, the file on the remote Windows server
gets properly opened, but if that same file is fopen()ed, no file is found
because the internal __open is called.

I know that I could override fopen() and friends (including any other "high-
level" functions that call internal versions of primitive functions), but
there's a fair amount of code involved in those, and reimplementing or
copying them for the sole purpose of compiling them such that they use the
overridden open() call seems a lot like overkill.

What can I do to cause fopen() in glibc to call the open() or _open() or
__open() in the preload instead of the internal __open?

Thanks in advance for your help!

Derrell
Reply | Threaded
Open this post in threaded view
|

Re: fopen() calls __open()

Ulrich Drepper
[hidden email] wrote:
> What can I do to cause fopen() in glibc to call the open() or _open() or
> __open() in the preload instead of the internal __open?

Nothing.  Once a call enters glibc it won't leave it until it's down.
Exceptions: the malloc functions.  Everything is completely opaque and
that won't change.

--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖


signature.asc (259 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: fopen() calls __open()

Derrell Lipman
Ulrich Drepper <[hidden email]> writes:

> [hidden email] wrote:
>> What can I do to cause fopen() in glibc to call the open() or _open() or
>> __open() in the preload instead of the internal __open?
>
> Nothing.  Once a call enters glibc it won't leave it until it's down.
> Exceptions: the malloc functions.  Everything is completely opaque and
> that won't change.

Ok.  Thanks for the response.

I'm a bit confused as to why certain functions are weak and allowed to be
overridden (e.g. open, __open) but not higher-level functions that use them.
It seems a bit inconsistent, but I assume there's a reason.  If there's some
prior thread that explains this, I'd sure appreciate a pointer to it.
Otherwise, might you be able to explain why primitives can be overridden but
not such that the users of those primitives within the library use the
overridden versions?

Thanks!

Derrell
Reply | Threaded
Open this post in threaded view
|

Re: fopen() calls __open()

Ulrich Drepper
[hidden email] wrote:
> I'm a bit confused as to why certain functions are weak and allowed to be
> overridden (e.g. open, __open)

Forget about weak.  The is no difference in the treatment of weak and
strong symbols when they are defined in DSOs.  They are all the same.
The aspect interesting for you is exported or not.  No internal libc
call except those to the malloc functions references names which are
exported.

--
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖


signature.asc (259 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: fopen() calls __open()

Derrell Lipman
Ulrich Drepper <[hidden email]> writes:

> [hidden email] wrote:
>> I'm a bit confused as to why certain functions are weak and allowed to be
>> overridden (e.g. open, __open)
>
> Forget about weak.  The is no difference in the treatment of weak and
> strong symbols when they are defined in DSOs.  They are all the same.
> The aspect interesting for you is exported or not.  No internal libc
> call except those to the malloc functions references names which are
> exported.

Ok.  So that means that if I want applications running over the Samba wrapper
(smbsh) to be able to call fopen() and have them open files on the remote
Windows server as currently works with open() and __open(), I need to put an
implementation of fopen() and friends into the LD_PRELOAD library as well.
I'm not looking forward to lugging around all that extra code, but it sounds
like that's my only choice.

If you have any other suggestions for me, I'd certainly like to hear them!

Thanks for your help,

Derrell
Reply | Threaded
Open this post in threaded view
|

Re: fopen() calls __open()

Paul Eggert
[hidden email] writes:

> If you have any other suggestions for me, I'd certainly like to hear them!

You're not alone in having this problem.  One approach is to supply a
your own modified libc that addresses the problem.  For an example of
this, you might take a look at Plash <http://plash.beasts.org/>; in
particular see the 2nd FAQ in <http://plash.beasts.org/faq.html>.

An idle thought: perhaps you can even use Plash's libc, or come up
with a slightly-modified libc that both Plash and you can use.
Reply | Threaded
Open this post in threaded view
|

Re: fopen() calls __open()

John Reiser
In reply to this post by Derrell Lipman
[hidden email] wrote:

> If you have any other suggestions for me, I'd certainly like to hear them!

For many particular cases, it is feasible to rewrite (patch) glibc
at runtime.  Disassemble to find the calls of interest, then change them.
Of course this is architecture dependent, and some modes of SELinux aim to
inhibit such modifications.  But on x86, x86_64, and PowerPC it is not
hard to do.

--
Reply | Threaded
Open this post in threaded view
|

Re: fopen() calls __open()

Mike Hearn-3
In reply to this post by Derrell Lipman
On Thu, 27 Apr 2006 13:55:06 -0400, Derrell.Lipman wrote:
> If you have any other suggestions for me, I'd certainly like to hear them!

The alsa AOSS program contains fopen wrapping code you can use.

thanks -mike

Reply | Threaded
Open this post in threaded view
|

Re: fopen() calls __open()

Derrell Lipman
In reply to this post by John Reiser
John Reiser <[hidden email]> writes:

> [hidden email] wrote:
>
>> If you have any other suggestions for me, I'd certainly like to hear them!
>
> For many particular cases, it is feasible to rewrite (patch) glibc
> at runtime.  Disassemble to find the calls of interest, then change them.
> Of course this is architecture dependent, and some modes of SELinux aim to
> inhibit such modifications.  But on x86, x86_64, and PowerPC it is not
> hard to do.

This is an interesting option to consider.  Can you point me to any
open-source applications that actually do this?

Thanks!

Derrell
Reply | Threaded
Open this post in threaded view
|

Re: fopen() calls __open()

John Reiser
[hidden email] wrote:
> John Reiser <[hidden email]> writes:
>>For many particular cases, it is feasible to rewrite (patch) glibc
>>at runtime. ...

> This is an interesting option to consider.  Can you point me to any
> open-source applications that actually do this?

The runtime loader itself (rtld, part of glibc) does patching when a module
is marked with DT_TEXTREL in its ElfXX_Dyn.  So look in the glibc source
for TEXTREL.  Of course one of the important ideas is that the relocation
entries ElfXX_Rel specify exactly _where_ do to the patching, whereas
your case might need a disassembler to find the locations.  The objcopy
module of the binutils project has disassemblers; there are others.

Two other projects which use runtime patching are:
  http://bitwagon.com/rtldi/rtldi.html  indirect runtime loader
  http://bitwagon.com/tub/tub.html      address-space manager

--