[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: linking of pam modules



> > >
> > > gcc -shared -Xlinker -x -o pam_securetty.so dynamic/pam_securetty.o -lpam
> > >
> Hmm. Does such kind of linking means that each PAM module will has its own
> copy of functions from libpam? And if a stack of modules has 10 ones then
> 10+1 copies of libpam will be in the memory?

Darn it, I was hoping nobody would ask.

The man page for dlopen says:

       If the same
       library is loaded twice with dlopen(), the same file  han-
       dle is returned.  The dl library maintains link counts for
       dynamic  file  handles,  so  a  dynamic  library  is   not
       deallocated  until  dlclose  has been called on it as many
       times as dlopen has succeeded on it.

The question is, does this include libraries opened by the linker? 

Ok, it may not.  I compiled this program:

#include <dlfcn.h>

void main(int argc, char** argv)
{
    int result;
    dlopen("libpam.so", RTLD_NOW);
    result = (int) dlopen(argv[1], RTLD_NOW);
    if (! result) printf("Doh: %s!\n", dlerror());
    else printf("success\n");
}

I compiled it linked only with libdl.  If I run it on an unmodified pam 
module, I get an error as expected:

% ./a.out /lib/security/pam_shells.so 
./a.out: can't resolve symbol 'pam_get_user'
Doh: Unable to resolve symbol!

And when I run it on my pam_securetty.so, linked with libpam, I get:

% ./a.out /lib/security/pam_securetty.so
success

But the output of strace for this invocation contains:

...
open("/usr/lib/libpam.so", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/lib/libpam.so", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3"..., 4096) = 4096
mmap(0, 24576, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x400d6000
mmap(0x400d6000, 19038, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x400d6000
mmap(0x400db000, 2940, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x4000) = 0x400db000
close(3)                                = 0
...
open("/lib/libpam.so.0.57", O_RDONLY)   = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3"..., 4096) = 4096
mmap(0, 24576, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x400de000
mmap(0x400de000, 19038, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x400de000
mmap(0x400e3000, 2940, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x4000) = 0x400e3000
close(3)                                = 0
...

I guess this means it is loaded twice.  Drat.  (I did another test in 
which I created libfoo with an _init function, and libbar which was linked 
to libfoo.  When I dlopened libfoo, then dlopened libbar, the _init 
function indeed ran twice.  But when I just dlopened libfoo twice, the 
_init only ran once.  So the link count thing mentioned in the man page 
only applies to libs explicitly dlopened, not those linked.)

I think I figured out the correct solution, however.  In the original 
program above, if I open libpam with

    dlopen("libpam.so", RTLD_NOW | RTLD_GLOBAL);

all seems to be well.  I guess I missed this option my first time through 
the man pages.

So perhaps we'd better nix the change to the linking of PAM modules, and 
chalk this up as a learning experience for me ;)

Andrew

PS.  Ironically, this exact issue was just discussed on the perl5-porters 
mailing list, with none other than Larry Wall playing the role of me!



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index] []