password (& host?) file lookups, daemons and stray descriptors
Web Server forum
Back To The Forum Home!Search!Private Messaging System

Web Server Talk Web Server Talk > Unix and Linux reviews > Free Unix support > Unix Programming > password (& host?) file lookups, daemons and stray descriptors




  Last Thread   Next Thread Next
  Show Printable Version Email this Page Subscribe to this Thread      Post New Thread    Post A Reply      

    password (& host?) file lookups, daemons and stray descriptors  
Mr. Uh Clem


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
06-23-05 11:00 PM

I've run into a strange problem on an HP11i system involving
a daemon program which

* calls getpwuid() as part of a security check during
initialization

* does the normal daemonization things:
forks, setsid, etc.,
close all descriptors,
redirect 0-2 to /dev/null.

* opens a lockfile and does a lockf on it.

* subsequently calls getpwnam() to obtain a uid.

On this system, the getpwnam() call causes the
lock to be lost on the lockfile.   (We don't seem
to have this problem on our various other *ix
flavors, although that could be a matter of
system configuration: nsswitch.conf, etc.)


Debugging shows that getpwuid leaves a descriptor
open after it is called.  From truss, it looks as
if it creates a socket and leaves it open on fd 3.
It is not hard to believe that Bad Things Happen(tm)
when the daemonizing closes all child fds and the
lockfile winds up with file descriptor 3.   Truss
seems to show the getpwnam() call atempting a sendto()
on fd 3, failing, then doing it's thing on 4 and
closing 4.

Well, I thought I could deal with this by calling
endpwent() after the getwpuid(), but the extra
descriptor does not go away and the problem persists.
This is not the post I thought it would be...


It took a while to figure out how to make it fail
from a simple program, but I finally did:

#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pwd.h>
#include <errno.h>

int check_fds(char *where);

main()
{
struct passwd *pw;
int status, fd;

check_fds("main");

status = getuid();
printf("getuid() is %d\n", status);
if(status == -1)
exit(11);
pw = getpwuid(status);
if (pw == NULL)
exit(12);
printf("user name is %s\n", pw->pw_name);

check_fds("after getpwuid");
endpwent();
check_fds("after endpwent");

/* simulate daemonize */
close(3);
close(4);

fd = open("/tmp/mylock", O_RDWR);
if (fd == -1)
{
perror("open");
exit(1);
}
printf("locfile open on fd %d\n", fd);
status = lockf(fd, F_TLOCK, 0);
if (status == -1)
exit(2);
printf("locked\n");
getc(stdin);

pw = getpwnam("bin");      [ this call seems to lose the lock ]
if (pw == NULL)
exit(3);
check_fds("after getpwnam");
printf("got uid %d\n", pw->pw_uid);
getc(stdin);

printf("exiting\n");
exit(0);
}

int check_fds(char *where)
{
int status, fd;

for (fd = 0; fd < 10; fd++)
{
status = dup(fd);
if (status != -1)
{
printf("%d ", fd);
close(status);
}
}
printf("- %s\n", where);
return(0);
}

# gcc test2.c
# ./a.out
0 1 2 - main
getuid() is 0
user name is root
0 1 2 3 - after getpwuid
0 1 2 3 - after endpwent
locfile open on fd 3
locked
[the file is locked at this point]

0 1 2 3 - after getpwnam
got uid 2
[the file is unlocked at this point]

exiting
#
[instead of here, when the program exits]

If I run under truss, an extra fd
seems to get injected:

execve("./a.out", 0x7b0404a0, 0x7b0404a8)                        = 0
[32-bit]
open("/usr/lib/dld.sl", O_RDONLY, 02204)                         = 4
read(4, "02\v010e0512@ \0\0\0\0\0\0\0\0\0".., 128)               = 128
lseek(4, 128, SEEK_SET)                                          = 128
read(4, "10\0\004\0\0\0( \002e884\0\0\0\0".., 48)                = 48
mmap(NULL, 190596, PROT_READ|PROT_EXEC,
 MAP_SHARED|MAP_SHLIB|MAP_STATICPREDICTIO
N, 4, 0x9000) = 0xc0010000
mmap(NULL, 16104, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_SHLIB,
4, 0x38000) = 0x7b03c000
close(4)                                                         = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, NULL) = 0x7b03a000
sysconf(_SC_CPU_VERSION)                                         = 532
open("/opt/graphics/OpenGL/lib/libogltls.sl", O_RDONLY, 0)       = 4
fstat(4, 0x7b042f98)                                             = 0
read(4, "0210010e0512@ \0\0\0\0\0\0\0\0\0".., 128)               = 128
lseek(4, 128, SEEK_SET)                                          = 128
read(4, "10\0\004\0\0\0( \0\013\ \0\010\0".., 48)                = 48
read(4, "80\0\001\0\0\0  9 2 4 5 ", 12)                          = 12
lseek(4, 8192, SEEK_SET)                                         = 8192
read(4, "058cy 10\0\0\0D \0\002$ \0\0\001".., 112)               = 112
mmap(NULL, 8192, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_SHLIB, 4, 0x2000) =
0xc0005000
mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_SHLIB,
4, 0x4000) = 0x7b039000
close(4)                                                         = 0
open("/usr/lib/libc.2", O_RDONLY, 0)                             = 4
fstat(4, 0x7b043158)                                             = 0
read(4, "0214010e0512@ \0\0\0\0\0\0\0\0\0".., 128)               = 128
lseek(4, 128, SEEK_SET)                                          = 128
read(4, "10\0\004\0\0\0( \013y c4\0\010\0".., 48)                = 48
read(4, "80\0\0\v\0\0\004\0\0\0\0", 12)                          = 12
lseek(4, 430080, SEEK_SET)                                       = 430080
read(4, "058cy 10\0\0\ad \0\0K L \0\0\002".., 112)               = 112
mmap(NULL, 1277952, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_SHLIB, 4,
0x69000) = 0xc0100000
mmap(NULL, 45056, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_SHLIB, -1, NULL) = 0x7b02e000
mmap(0x7b026000, 32768, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_FIXED|MAP_SHLIB, 4, 0x1a1000) = 0x7b026000
mmap(NULL, 16384, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, NULL) = 0x7b022000
close(4)                                                         = 0
open("/usr/lib/libdld.2", O_RDONLY, 0)                           = 4
fstat(4, 0x7b043318)                                             = 0
read(4, "02\v010e0512@ \0\0\0\0\0\0\0\0\0".., 128)               = 128
lseek(4, 128, SEEK_SET)                                          = 128
read(4, "10\0\004\0\0\0( \0\0) \ \0\010\0".., 48)                = 48
read(4, "80\0\0\v\0\0\004\0\0\0\0", 12)                          = 12
lseek(4, 8192, SEEK_SET)                                         = 8192
read(4, "058cy 10\0\0\0\f\0\00214\0\0\001".., 112)               = 112
mmap(NULL, 12288, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_SHLIB, 4, 0x2000)
= 0xc0007000
mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_SHLIB,
4, 0x5000) = 0x7b021000
close(4)                                                         = 0
open("/usr/lib/libc.2", O_RDONLY, 0)                             = 4
fstat(4, 0x7b043498)                                             = 0
close(4)                                                         = 0
mmap(NULL, 16384, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, NULL) = 0x7b01d000
mmap(NULL, 3368, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, NULL) = 0x7b01c000
sigsetreturn(0x7b023f36, 0x6211988, 1392)                        = 0

looks like we start here...

dup(0)                                                           = 4
sysconf(_SC_CPU_VERSION)                                         = 532
brk(0x40001140)                                                  = 0
brk(0x40003134)                                                  = 0
brk(0x40006000)                                                  = 0
ioctl(1, TCGETA, 0x7b040958)                                     = 0
close(4)                                                         = 0
dup(1)                                                           = 4
close(4)                                                         = 0
dup(2)                                                           = 4
close(4)                                                         = 0
dup(3)                                                           = 4
close(4)                                                         = 0
dup(4)                                                           ERR#9 EBADF
dup(5)                                                           ERR#9 EBADF
dup(6)                                                           ERR#9 EBADF
dup(7)                                                           ERR#9 EBADF
dup(8)                                                           ERR#9 EBADF
dup(9)                                                           ERR#9 EBADF
write(1, "0   1   2   3   -   m a i n \n", 15)                   = 15
getuid()                                                         = 0 (0)
write(1, "g e t u i d ( )   i s   0 \n", 14)                     = 14

If I close(3) at the start of the program to get rid of the
extraneous fd truss seems to give, the following winds up on
fd 3.

open("/var/spool/pwgr/status", O_RDONLY, 0)                      = 4
mmap(NULL, 532, PROT_READ,  MAP_SHARED|MAP_VARIABLE|MAP_FILE|MAP_ADD
R32,
4, NULL) = 0xc0057000
close(4)                                                         = 0
socket(AF_UNIX, SOCK_DGRAM, 0)                                   = 4
getpid()                                                         = 19401
(19400)
unlink("/var/spool/sockets/pwgr/client19401")                    ERR#2
ENOENT
bind(4, 0x7b02f580, 38)                                          = 0
fcntl(4, F_SETFD, 1)                                             = 0
time(NULL)                                                       =
1119565603
poll(0x7b041798, 1, 0)                                           = 1
sendto(4, "\0\0\00 \0\0\001\0\0\0\0\0\0\001".., 48, 0, NULL, NULL) = 48
poll(0x7b041798, 1, 1000)                                        = 1
recv(4, "\0\0\03 \0\0\0\0\0\0\0\0\0\0\0# ".., 2064, 0)           = 51
write(1, "u s e r   n a m e   i s   r o o ".., 18)               = 18
dup(0)                                                           = 5
close(5)                                                         = 0
dup(1)                                                           = 5
close(5)                                                         = 0
dup(2)                                                           = 5
close(5)                                                         = 0
dup(3)                                                           = 5
close(5)                                                         = 0
dup(4)                                                           = 5
close(5)                                                         = 0
dup(5)                                                           ERR#9 EBADF
dup(6)                                                           ERR#9 EBADF
dup(7)                                                           ERR#9 EBADF
dup(8)                                                           ERR#9 EBADF
dup(9)                                                           ERR#9 EBADF
write(1, "0   1   2   3   4   -   a f t e ".., 27)               = 27
dup(0)                                                           = 5
close(5)                                                         = 0
dup(1)                                                           = 5
close(5)                                                         = 0
dup(2)                                                           = 5
close(5)                                                         = 0
dup(3)                                                           = 5
close(5)                                                         = 0
dup(4)                                                           = 5
close(5)                                                         = 0
dup(5)                                                           ERR#9 EBADF
dup(6)                                                           ERR#9 EBADF
dup(7)                                                           ERR#9 EBADF
dup(8)                                                           ERR#9 EBADF
dup(9)                                                           ERR#9 EBADF
write(1, "0   1   2   3   4   -   a f t e ".., 27)               = 27
close(3)                                                         = 0
close(4)                                                         = 0
open("/tmp/mylock", O_RDWR, 0160100)                             = 3
write(1, "l o c f i l e   o p e n   o n   ".., 21)               = 21
lockf(3, 0x2, 0)                                                 = 0
write(1, "l o c k e d \n", 7)                                    = 7
brk(0x40008000)                                                  = 0
ioctl(0, TCGETA, 0x7b040718)                                     = 0
read(0, 0x400059a0, 8192)                                        [sleepi
ng]
read(0, "\n", 8192)                                              = 1
getpid()                                                         = 19401
(19400)
poll(0x7b041798, 1, 0)                                           = 1

When I close(3) at the start of the program to get rid of the
fd truss gives, this sendto is performed against the lockfile
and results in ENOTSOCK.  In this case, where we don't even
touch 3, the lock STILL gets lost!   I don't see how..

sendto(4, "\0\0\00 \0\0\001\0\0\001\0\0\002".., 48, 0, NULL, NULL) ERR#9
EBADF
open("/etc/nsswitch.conf", O_RDONLY, 0666)                       = 4
brk(0x4000a000)                                                  = 0
ioctl(4, TCGETA, 0x7b041618)                                     ERR#25
ENOTTY
read(4, "# \n#   / e t c / n s s w i t c ".., 8192)              = 376
brk(0x4000b000)                                                  = 0
read(4, 0x40007e58, 8192)                                        = 0
close(4)                                                         = 0
open("/usr/lib/libnss_files.1", O_RDONLY, 0)                     = 4
fstat(4, 0x7b041818)                                             = 0
read(4, "0210010e0512@ \0\0\0\0\0\0\0\0\0".., 128)               = 128
lseek(4, 128, SEEK_SET)                                          = 128
read(4, "10\0\004\0\0\0( \0\0k T \0\010\0".., 48)                = 48
read(4, "80\0\0\v\0\0\004\0\0\0\0", 12)                          = 12
lseek(4, 12288, SEEK_SET)                                        = 12288
read(4, "058cy 10\0\0\0D \0\004f0\0\0\002".., 112)               = 112
mmap(NULL, 28672, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_SHLIB, 4, 0x3000)
= 0xc0058000
mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_SHLIB,
4, 0xa000) = 0x7b01b000
close(4)                                                         = 0
open("/usr/lib/libdld.2", O_RDONLY, 0)                           = 4
fstat(4, 0x7b0419d8)                                             = 0
close(4)                                                         = 0
open("/etc/passwd", O_RDONLY, 0666)                              = 4
brk(0x4000d000)                                                  = 0
ioctl(4, TCGETA, 0x7b041418)                                     ERR#25
ENOTTY
read(4, "r o o t : R e 9 b n r j Y 8 i a ".., 8192)              = 591
lseek(4, 4294966794, SEEK_CUR)                                   = 89
close(4)                                                         = 0
dup(0)                                                           = 4
close(4)                                                         = 0
dup(1)                                                           = 4
close(4)                                                         = 0
dup(2)                                                           = 4
close(4)                                                         = 0
dup(3)                                                           = 4
close(4)                                                         = 0
dup(4)                                                           ERR#9 EBADF
dup(5)                                                           ERR#9 EBADF
dup(6)                                                           ERR#9 EBADF
dup(7)                                                           ERR#9 EBADF
dup(8)                                                           ERR#9 EBADF
dup(9)                                                           ERR#9 EBADF
write(1, "0   1   2   3   -   a f t e r   ".., 25)               = 25
write(1, "g o t   u i d   2 \n", 10)                             = 10
read(0, 0x400059a0, 8192)                                        [sleepi
ng]
read(0, "\n", 8192)                                              = 1
write(1, "e x i t i n g \n", 8)                                  = 8
getpid()                                                         = 19401
(19400)
unlink("/var/spool/sockets/pwgr/client19401")                    = 0
exit(0)
WIFEXITED(0)


What the Fudd is going on ??   I'm stumped.  I'd love
to find out I'm doing Something Stupid(tm).


--
Clem
"If you push something hard enough, it will fall over."
- Fudd's first law of opposition





[ Post a follow-up to this message ]



    Re: password (& host?) file lookups, daemons and stray descriptors  
Alan D Johnson


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
06-24-05 01:48 AM

Mr. Uh Clem wrote:
> I've run into a strange problem on an HP11i system involving
> a daemon program which
>
> * calls getpwuid() as part of a security check during
>   initialization
>
> * does the normal daemonization things:
>    forks, setsid, etc.,
>    close all descriptors,
>    redirect 0-2 to /dev/null.
>
> * opens a lockfile and does a lockf on it.
>
> * subsequently calls getpwnam() to obtain a uid.
>
> On this system, the getpwnam() call causes the
> lock to be lost on the lockfile.   (We don't seem
> to have this problem on our various other *ix
> flavors, although that could be a matter of
> system configuration: nsswitch.conf, etc.)
>
>
> Debugging shows that getpwuid leaves a descriptor
> open after it is called.  From truss, it looks as
> if it creates a socket and leaves it open on fd 3.
> It is not hard to believe that Bad Things Happen(tm)
> when the daemonizing closes all child fds and the
> lockfile winds up with file descriptor 3.   Truss
> seems to show the getpwnam() call atempting a sendto()
> on fd 3, failing, then doing it's thing on 4 and
> closing 4.
>
> Well, I thought I could deal with this by calling
> endpwent() after the getwpuid(), but the extra
> descriptor does not go away and the problem persists.
> This is not the post I thought it would be...
>
>
> It took a while to figure out how to make it fail
> from a simple program, but I finally did:
>
> #include <sys/types.h>
> #include <fcntl.h>
> #include <unistd.h>
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> #include <errno.h>
> #include <pwd.h>
> #include <errno.h>
>
> int check_fds(char *where);
>
> main()
> {
>    struct passwd *pw;
>    int status, fd;
>
>    check_fds("main");
>
>    status = getuid();
>    printf("getuid() is %d\n", status);
>    if(status == -1)
>       exit(11);
>    pw = getpwuid(status);
>    if (pw == NULL)
>       exit(12);
>    printf("user name is %s\n", pw->pw_name);
>
>    check_fds("after getpwuid");
>    endpwent();
>    check_fds("after endpwent");
>
>    /* simulate daemonize */
>    close(3);
>    close(4);
>
>    fd = open("/tmp/mylock", O_RDWR);
>    if (fd == -1)
>       {
>       perror("open");
>       exit(1);
>       }
>    printf("locfile open on fd %d\n", fd);
>    status = lockf(fd, F_TLOCK, 0);
>    if (status == -1)
>       exit(2);
>    printf("locked\n");
>    getc(stdin);
>
>    pw = getpwnam("bin");      [ this call seems to lose the lock ]
>    if (pw == NULL)
>       exit(3);
>    check_fds("after getpwnam");
>    printf("got uid %d\n", pw->pw_uid);
>    getc(stdin);
>
>    printf("exiting\n");
>    exit(0);
> }
>
> int check_fds(char *where)
> {
>    int status, fd;
>
>    for (fd = 0; fd < 10; fd++)
>       {
>       status = dup(fd);
>       if (status != -1)
>          {
>          printf("%d ", fd);
>          close(status);
>          }
>       }
>    printf("- %s\n", where);
>    return(0);
> }
>
> # gcc test2.c
> # ./a.out
> 0 1 2 - main
> getuid() is 0
> user name is root
> 0 1 2 3 - after getpwuid
> 0 1 2 3 - after endpwent
> locfile open on fd 3
> locked
> [the file is locked at this point]
>
> 0 1 2 3 - after getpwnam
> got uid 2
> [the file is unlocked at this point]
>
> exiting
> #
> [instead of here, when the program exits]
>
> If I run under truss, an extra fd
> seems to get injected:
>
> execve("./a.out", 0x7b0404a0, 0x7b0404a8)                        = 0
> [32-bit]
> open("/usr/lib/dld.sl", O_RDONLY, 02204)                         = 4
> read(4, "02\v010e0512@ \0\0\0\0\0\0\0\0\0".., 128)               = 128
> lseek(4, 128, SEEK_SET)                                          = 128
> read(4, "10\0\004\0\0\0( \002e884\0\0\0\0".., 48)                = 48
> mmap(NULL, 190596, PROT_READ|PROT_EXEC,
>  MAP_SHARED|MAP_SHLIB|MAP_STATICPREDICTIO
N, 4, 0x9000) = 0xc0010000
> mmap(NULL, 16104, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_SHLIB,
> 4, 0x38000) = 0x7b03c000
> close(4)                                                         = 0
> mmap(NULL, 8192, PROT_READ|PROT_WRITE|PROT_EXEC,
> MAP_PRIVATE|MAP_ANONYMOUS, -1, NULL) = 0x7b03a000
> sysconf(_SC_CPU_VERSION)                                         = 532
> open("/opt/graphics/OpenGL/lib/libogltls.sl", O_RDONLY, 0)       = 4
> fstat(4, 0x7b042f98)                                             = 0
> read(4, "0210010e0512@ \0\0\0\0\0\0\0\0\0".., 128)               = 128
> lseek(4, 128, SEEK_SET)                                          = 128
> read(4, "10\0\004\0\0\0( \0\013\ \0\010\0".., 48)                = 48
> read(4, "80\0\001\0\0\0  9 2 4 5 ", 12)                          = 12
> lseek(4, 8192, SEEK_SET)                                         = 8192
> read(4, "058cy 10\0\0\0D \0\002$ \0\0\001".., 112)               = 112
> mmap(NULL, 8192, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_SHLIB, 4, 0x2000) =
> 0xc0005000
> mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_SHLIB,
> 4, 0x4000) = 0x7b039000
> close(4)                                                         = 0
> open("/usr/lib/libc.2", O_RDONLY, 0)                             = 4
> fstat(4, 0x7b043158)                                             = 0
> read(4, "0214010e0512@ \0\0\0\0\0\0\0\0\0".., 128)               = 128
> lseek(4, 128, SEEK_SET)                                          = 128
> read(4, "10\0\004\0\0\0( \013y c4\0\010\0".., 48)                = 48
> read(4, "80\0\0\v\0\0\004\0\0\0\0", 12)                          = 12
> lseek(4, 430080, SEEK_SET)                                       = 430080
> read(4, "058cy 10\0\0\ad \0\0K L \0\0\002".., 112)               = 112
> mmap(NULL, 1277952, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_SHLIB, 4,
> 0x69000) = 0xc0100000
> mmap(NULL, 45056, PROT_READ|PROT_WRITE|PROT_EXEC,
> MAP_PRIVATE|MAP_ANONYMOUS|MAP_SHLIB, -1, NULL) = 0x7b02e000
> mmap(0x7b026000, 32768, PROT_READ|PROT_WRITE|PROT_EXEC,
> MAP_PRIVATE|MAP_FIXED|MAP_SHLIB, 4, 0x1a1000) = 0x7b026000
> mmap(NULL, 16384, PROT_READ|PROT_WRITE|PROT_EXEC,
> MAP_PRIVATE|MAP_ANONYMOUS, -1, NULL) = 0x7b022000
> close(4)                                                         = 0
> open("/usr/lib/libdld.2", O_RDONLY, 0)                           = 4
> fstat(4, 0x7b043318)                                             = 0
> read(4, "02\v010e0512@ \0\0\0\0\0\0\0\0\0".., 128)               = 128
> lseek(4, 128, SEEK_SET)                                          = 128
> read(4, "10\0\004\0\0\0( \0\0) \ \0\010\0".., 48)                = 48
> read(4, "80\0\0\v\0\0\004\0\0\0\0", 12)                          = 12
> lseek(4, 8192, SEEK_SET)                                         = 8192
> read(4, "058cy 10\0\0\0\f\0\00214\0\0\001".., 112)               = 112
> mmap(NULL, 12288, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_SHLIB, 4, 0x2000)
> = 0xc0007000
> mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_SHLIB,
> 4, 0x5000) = 0x7b021000
> close(4)                                                         = 0
> open("/usr/lib/libc.2", O_RDONLY, 0)                             = 4
> fstat(4, 0x7b043498)                                             = 0
> close(4)                                                         = 0
> mmap(NULL, 16384, PROT_READ|PROT_WRITE|PROT_EXEC,
> MAP_PRIVATE|MAP_ANONYMOUS, -1, NULL) = 0x7b01d000
> mmap(NULL, 3368, PROT_READ|PROT_WRITE|PROT_EXEC,
> MAP_PRIVATE|MAP_ANONYMOUS, -1, NULL) = 0x7b01c000
> sigsetreturn(0x7b023f36, 0x6211988, 1392)                        = 0
>
> looks like we start here...
>
> dup(0)                                                           = 4
> sysconf(_SC_CPU_VERSION)                                         = 532
> brk(0x40001140)                                                  = 0
> brk(0x40003134)                                                  = 0
> brk(0x40006000)                                                  = 0
> ioctl(1, TCGETA, 0x7b040958)                                     = 0
> close(4)                                                         = 0
> dup(1)                                                           = 4
> close(4)                                                         = 0
> dup(2)                                                           = 4
> close(4)                                                         = 0
> dup(3)                                                           = 4
> close(4)                                                         = 0
> dup(4)                                                           ERR#9
> EBADF
> dup(5)                                                           ERR#9
> EBADF
> dup(6)                                                           ERR#9
> EBADF
> dup(7)                                                           ERR#9
> EBADF
> dup(8)                                                           ERR#9
> EBADF
> dup(9)                                                           ERR#9
> EBADF
> write(1, "0   1   2   3   -   m a i n \n", 15)                   = 15
> getuid()                                                         = 0 (0)
> write(1, "g e t u i d ( )   i s   0 \n", 14)                     = 14
>
> If I close(3) at the start of the program to get rid of the
> extraneous fd truss seems to give, the following winds up on
> fd 3.
>
> open("/var/spool/pwgr/status", O_RDONLY, 0)                      = 4
> mmap(NULL, 532, PROT_READ,  MAP_SHARED|MAP_VARIABLE|MAP_FILE|MAP_ADD
R32,
> 4, NULL) = 0xc0057000
> close(4)                                                         = 0
> socket(AF_UNIX, SOCK_DGRAM, 0)                                   = 4
> getpid()                                                         = 19401
> (19400)
> unlink("/var/spool/sockets/pwgr/client19401")                    ERR#2
> ENOENT
> bind(4, 0x7b02f580, 38)                                          = 0
> fcntl(4, F_SETFD, 1)                                             = 0
> time(NULL)                                                       =
> 1119565603
> poll(0x7b041798, 1, 0)                                           = 1
> sendto(4, "\0\0\00 \0\0\001\0\0\0\0\0\0\001".., 48, 0, NULL, NULL) = 48
> poll(0x7b041798, 1, 1000)                                        = 1
> recv(4, "\0\0\03 \0\0\0\0\0\0\0\0\0\0\0# ".., 2064, 0)           = 51
> write(1, "u s e r   n a m e   i s   r o o ".., 18)               = 18
> dup(0)                                                           = 5
> close(5)                                                         = 0
> dup(1)                                                           = 5
> close(5)                                                         = 0
> dup(2)                                                           = 5
> close(5)                                                         = 0
> dup(3)                                                           = 5
> close(5)                                                         = 0
> dup(4)                                                           = 5
> close(5)                                                         = 0
> dup(5)                                                           ERR#9
> EBADF
> dup(6)                                                           ERR#9
> EBADF
> dup(7)                                                           ERR#9
> EBADF
> dup(8)                                                           ERR#9
> EBADF
> dup(9)                                                           ERR#9
> EBADF
> write(1, "0   1   2   3   4   -   a f t e ".., 27)               = 27
> dup(0)                                                           = 5
> close(5)                                                         = 0
> dup(1)                                                           = 5
> close(5)                                                         = 0
> dup(2)                                                           = 5
> close(5)                                                         = 0
> dup(3)                                                           = 5
> close(5)                                                         = 0
> dup(4)                                                           = 5
> close(5)                                                         = 0
> dup(5)                                                           ERR#9
> EBADF
> dup(6)                                                           ERR#9
> EBADF
> dup(7)                                                           ERR#9
> EBADF
> dup(8)                                                           ERR#9
> EBADF
> dup(9)                                                           ERR#9
> EBADF
> write(1, "0   1   2   3   4   -   a f t e ".., 27)               = 27
> close(3)                                                         = 0
> close(4)                                                         = 0
> open("/tmp/mylock", O_RDWR, 0160100)                             = 3
> write(1, "l o c f i l e   o p e n   o n   ".., 21)               = 21
> lockf(3, 0x2, 0)                                                 = 0
> write(1, "l o c k e d \n", 7)                                    = 7
> brk(0x40008000)                                                  = 0
> ioctl(0, TCGETA, 0x7b040718)                                     = 0
> read(0, 0x400059a0, 8192)                                        [slee
ping]
> read(0, "\n", 8192)                                              = 1
> getpid()                                                         = 19401
> (19400)
> poll(0x7b041798, 1, 0)                                           = 1
>
> When I close(3) at the start of the program to get rid of the
> fd truss gives, this sendto is performed against the lockfile
> and results in ENOTSOCK.  In this case, where we don't even
> touch 3, the lock STILL gets lost!   I don't see how..
>
> sendto(4, "\0\0\00 \0\0\001\0\0\001\0\0\002".., 48, 0, NULL, NULL) ERR#9
> EBADF
> open("/etc/nsswitch.conf", O_RDONLY, 0666)                       = 4
> brk(0x4000a000)                                                  = 0
> ioctl(4, TCGETA, 0x7b041618)                                     ERR#25
> ENOTTY
> read(4, "# \n#   / e t c / n s s w i t c ".., 8192)              = 376
> brk(0x4000b000)                                                  = 0
> read(4, 0x40007e58, 8192)                                        = 0
> close(4)                                                         = 0
> open("/usr/lib/libnss_files.1", O_RDONLY, 0)                     = 4
> fstat(4, 0x7b041818)                                             = 0
> read(4, "0210010e0512@ \0\0\0\0\0\0\0\0\0".., 128)               = 128
> lseek(4, 128, SEEK_SET)                                          = 128
> read(4, "10\0\004\0\0\0( \0\0k T \0\010\0".., 48)                = 48
> read(4, "80\0\0\v\0\0\004\0\0\0\0", 12)                          = 12
> lseek(4, 12288, SEEK_SET)                                        = 12288
> read(4, "058cy 10\0\0\0D \0\004f0\0\0\002".., 112)               = 112
> mmap(NULL, 28672, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_SHLIB, 4, 0x3000)
> = 0xc0058000
> mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_SHLIB,
> 4, 0xa000) = 0x7b01b000
> close(4)                                                         = 0
> open("/usr/lib/libdld.2", O_RDONLY, 0)                           = 4
> fstat(4, 0x7b0419d8)                                             = 0
> close(4)                                                         = 0
> open("/etc/passwd", O_RDONLY, 0666)                              = 4
> brk(0x4000d000)                                                  = 0
> ioctl(4, TCGETA, 0x7b041418)                                     ERR#25
> ENOTTY
> read(4, "r o o t : R e 9 b n r j Y 8 i a ".., 8192)              = 591
> lseek(4, 4294966794, SEEK_CUR)                                   = 89
> close(4)                                                         = 0
> dup(0)                                                           = 4
> close(4)                                                         = 0
> dup(1)                                                           = 4
> close(4)                                                         = 0
> dup(2)                                                           = 4
> close(4)                                                         = 0
> dup(3)                                                           = 4
> close(4)                                                         = 0
> dup(4)                                                           ERR#9
> EBADF
> dup(5)                                                           ERR#9
> EBADF
> dup(6)                                                           ERR#9
> EBADF
> dup(7)                                                           ERR#9
> EBADF
> dup(8)                                                           ERR#9
> EBADF
> dup(9)                                                           ERR#9
> EBADF
> write(1, "0   1   2   3   -   a f t e r   ".., 25)               = 25
> write(1, "g o t   u i d   2 \n", 10)                             = 10
> read(0, 0x400059a0, 8192)                                        [slee
ping]
> read(0, "\n", 8192)                                              = 1
> write(1, "e x i t i n g \n", 8)                                  = 8
> getpid()                                                         = 19401
> (19400)
> unlink("/var/spool/sockets/pwgr/client19401")                    = 0
> exit(0) WIFEXITED(0)
>
>
> What the Fudd is going on ??   I'm stumped.  I'd love
> to find out I'm doing Something Stupid(tm).
>
>
I don't do programing, BUT... are you running on a trusted mode system
or untrusted? There is a big difference, at least in to 11.0.





[ Post a follow-up to this message ]



    Re: password (& host?) file lookups, daemons and stray descriptors  
Mr. Uh Clem


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
06-24-05 01:48 AM

Alan D Johnson wrote:
> Mr. Uh Clem wrote:
>
[snip!]
> I don't do programing, BUT... are you running on a trusted mode system
> or untrusted? There is a big difference, at least in to 11.0.

To be honest, I don't know.  I did not set it up.  I'll have to
check tomorrow.  I'm not sure what that would have to do with
stray descriptors...

Thanks!

--
Clem
"If you push something hard enough, it will fall over."
- Fudd's first law of opposition





[ Post a follow-up to this message ]



    Re: password (& host?) file lookups, daemons and stray descriptors  
Barry Margolin


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
06-24-05 07:48 AM

In article <42bb3ac4$0$5702$9a6e19ea@news.newshosting.com>,
"Mr. Uh Clem" <uhclem@DutchElmSt.invalid> wrote:

> I've run into a strange problem on an HP11i system involving
> a daemon program which
>
> * calls getpwuid() as part of a security check during
>    initialization
>
> * does the normal daemonization things:
>     forks, setsid, etc.,
>     close all descriptors,
>     redirect 0-2 to /dev/null.
>
> * opens a lockfile and does a lockf on it.
>
> * subsequently calls getpwnam() to obtain a uid.
>
> On this system, the getpwnam() call causes the
> lock to be lost on the lockfile.   (We don't seem
> to have this problem on our various other *ix
> flavors, although that could be a matter of
> system configuration: nsswitch.conf, etc.)
>
>
> Debugging shows that getpwuid leaves a descriptor
> open after it is called.  From truss, it looks as
> if it creates a socket and leaves it open on fd 3.
> It is not hard to believe that Bad Things Happen(tm)
> when the daemonizing closes all child fds and the
> lockfile winds up with file descriptor 3.   Truss
> seems to show the getpwnam() call atempting a sendto()
> on fd 3, failing, then doing it's thing on 4 and
> closing 4.

I think the solution is obvious: don't close all file descriptors, just
redirect 0-2 to /dev/null.  You shouldn't close random descriptors
because you have no idea whether they're still in use by some library
routines.  You have to assume that if a descriptor was left open, it was
for a reason.

What you may want to do is set the close-on-exec flag on all the
descriptors, if your daemon execs other programs.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***





[ Post a follow-up to this message ]



    Re: password (& host?) file lookups, daemons and stray descriptors  
Mr. Uh Clem


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
06-24-05 11:00 PM

Barry Margolin wrote:
> In article <42bb3ac4$0$5702$9a6e19ea@news.newshosting.com>,
>  "Mr. Uh Clem" <uhclem@DutchElmSt.invalid> wrote:
>
> 
>
>
> I think the solution is obvious: don't close all file descriptors, just
> redirect 0-2 to /dev/null.  You shouldn't close random descriptors
> because you have no idea whether they're still in use by some library
> routines.  You have to assume that if a descriptor was left open, it
> was for a reason.

Yeah, I guess so, but this is contrary to all I've ever
seen on how to do a daemon.  Consider these early hits
from Googling for [unix daemon process] :

http://www.enderunix.org/docs/eng/daemon.php
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
http://www.unix.com/archive/index.php/t-3736.html

I've never seen any cautionary text regarding fds from
called routines which must be handled with care:
Preserved across forks because there may be static
references to them in the library routines, but
can be closed on exec, because after the exec,
the fds would be forgotten?

I'm also rather surprised that the man pages for
routines such as getpwuid() are silent on their
creation of fds and the handling required. (And
I still don't see anything in the truss which
explains the lost lock.)   I'm also surprised
it is not possible to properly close such open
fds, with routines such as endpwent().

> What you may want to do is set the close-on-exec flag on all the
> descriptors, if your daemon execs other programs.

So generic daemonizing might be something like:

- close all fds above 2 at the start of main (?)

- fork; setsid; fork; chdir("/" or other safe place);
close 0-2 and redirect (typically to /dev/null);
set close-on-exec for fds above 2

Thanks!

--
Clem
"If you push something hard enough, it will fall over."
- Fudd's first law of opposition





[ Post a follow-up to this message ]



    Re: password (& host?) file lookups, daemons and stray descriptors  
Barry Margolin


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
06-25-05 07:49 AM

In article <42bc1ccc$0$5791$9a6e19ea@news.newshosting.com>,
"Mr. Uh Clem" <uhclem@DutchElmSt.invalid> wrote:

> Yeah, I guess so, but this is contrary to all I've ever
> seen on how to do a daemon.  Consider these early hits
> from Googling for [unix daemon process] :
>
> http://www.enderunix.org/docs/eng/daemon.php
> http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
> http://www.unix.com/archive/index.php/t-3736.html
>
> I've never seen any cautionary text regarding fds from
> called routines which must be handled with care:

I think everyone may assume that you do this so early in your program
that nothing would have already opened fd's.  Notice that the first page
you referenced above refers to these as "inherited" fd's -- the
expectation is that any fd's that are open were inherited from the
calling process, not opened by this process.  But when you call library
routines, and they may have opened descriptors and stored them in static
variables, this assumption is no longer valid.

> I'm also rather surprised that the man pages for
> routines such as getpwuid() are silent on their
> creation of fds and the handling required. (And

These fd's are internal implementation details, and the caller is not
expected to "handle" them.  They might change from release to release,
and programs should not depend on them.

> I still don't see anything in the truss which
> explains the lost lock.)   I'm also surprised
> it is not possible to properly close such open
> fds, with routines such as endpwent().

Since it's a network socket, I think it's probably part of the NIS
library, not anything specific to password lookup.  Endpwent() doesn't
have any way to make NIS discard the socket it uses to talk to the
server.

> 
>
> So generic daemonizing might be something like:
>
> - close all fds above 2 at the start of main (?)

Right.  Then you can call getpwuid() to perform your validity check.
Since stderr is still pointing to its original location, you can report
an error.

>
> - fork; setsid; fork; chdir("/" or other safe place);
>    close 0-2 and redirect (typically to /dev/null);
>    set close-on-exec for fds above 2

Seems right to me.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***





[ Post a follow-up to this message ]



    Re: password (& host?) file lookups, daemons and stray descriptors  
Mr. Uh Clem


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
06-25-05 10:50 PM

Barry Margolin wrote:

> In article <42bc1ccc$0$5791$9a6e19ea@news.newshosting.com>,
>  "Mr. Uh Clem" <uhclem@DutchElmSt.invalid> wrote:
...
> These fd's are internal implementation details, and the caller is not
> expected to "handle" them.  They might change from release to release,
> and programs should not depend on them.

I agree in the sense that they are not part of the API.
But they do consume a resource and can cause unexpected
side effects.  If many implementations commonly open a
descriptor, perhaps the standards man pages should say
that they _may_ do so in the Notes section.  Makes even
more sense in the man pages of specific implementations.
[vbcol=seagreen] 

Hmm, I wonder if library routines have already done this.
It would be the right thing to do.  I'll have to look.

THANKS!

--
Clem
"If you push something hard enough, it will fall over."
- Fudd's first law of opposition





[ Post a follow-up to this message ]



    Re: password (& host?) file lookups, daemons and stray descriptors  
Barry Margolin


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
06-26-05 01:47 AM

In article <42bdca81$0$5795$9a6e19ea@news.newshosting.com>,
"Mr. Uh Clem" <uhclem@DutchElmSt.invalid> wrote:

> Barry Margolin wrote:
> 
> ... 
>
> I agree in the sense that they are not part of the API.
> But they do consume a resource and can cause unexpected
> side effects.

Static memory use also consumes a shared resource, but library functions
don't normally document this, either.

In general, library function documentation only describes behavior that
the caller *needs* to be aware of.  File descriptors that are used
behind the scenes don't generally fall into that.

BTW, does your fopen(3) man page mention that it leaves a file
descriptor open?

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***





[ Post a follow-up to this message ]



    Re: password (& host?) file lookups, daemons and stray descriptors  
Rick Jones


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
06-27-05 10:53 PM

In comp.sys.hp.hpux Mr. Uh Clem <uhclem@dutchelmst.invalid> wrote:

> open("/var/spool/pwgr/status", O_RDONLY, 0)                      = 4
> mmap(NULL, 532, PROT_READ,  MAP_SHARED|MAP_VARIABLE|MAP_FILE|MAP_ADD
R32,
> 4, NULL) = 0xc0057000
> close(4)                                                         = 0
> socket(AF_UNIX, SOCK_DGRAM, 0)                                   = 4

Notice that this is an AF_UNIX socket, rather than AF_INET.

> getpid()                                                         = 19401
> (19400)
> unlink("/var/spool/sockets/pwgr/client19401")                    ERR#2
> ENOENT
> bind(4, 0x7b02f580, 38)                                          = 0

Move verbosity would help here, but I believe this is the code's
attempt to associate the socket with a daemon meant to "accelerate"
lookups in the files - it builds (IIRC) some little internal DB rather
than having the process go thgrough the files linearly all the time.

Man pwgrd may have more details.  Say on how to disable its use.

I would have expected there to be some sort of setup to allow the
connection to the daemon to be undone for the child of a fork.  Might
be time to ring the Response Centre and submit a defect - or peruse
the patch listings at irtc.hp.com.

rick jones
--
oxymoron n, Hummer H2 with California Save Our Coasts and Oceans plates
these opinions are mine, all mine; HP might not want them anyway... 
feel free to post, OR email to rick.jones2 in hp.com but NOT BOTH...





[ Post a follow-up to this message ]



    Sponsored Links  




 





   All times are GMT. The time now is 09:52 PM.      Post New Thread    Post A Reply      
  Last Thread   Next Thread Next


Most Popular forums 

Forum Jump:
Rate This Thread:

Forum Rules:
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is OFF
vB code is ON
Smilies are ON
[IMG] code is OFF
 
Medical and Health forum | Computer Games Reviews | Graphics design forum