diff options
author | Andrew Bartlett <abartlet@samba.org> | 2002-09-07 05:41:23 +0000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2002-09-07 05:41:23 +0000 |
commit | 442eb39657b98f67cd229ed3110b63aae8bf4e3c (patch) | |
tree | d03dc2505ce1c626694e003684a30293ad1cad1a /source/nsswitch/wb_common.c | |
parent | 29b4b9a2b5a0347d227b1a30e3f34bf40afa6de4 (diff) | |
download | samba-442eb39657b98f67cd229ed3110b63aae8bf4e3c.tar.gz samba-442eb39657b98f67cd229ed3110b63aae8bf4e3c.tar.xz samba-442eb39657b98f67cd229ed3110b63aae8bf4e3c.zip |
Winbind client-side cleanups.
The global winbind file descriptor can cause havoc in some situations -
particulary when it becomes 0, 1 or 2. This patch (based on some very nice
work by Hannes Schmidt <mail@schmidt-net.via.t-online.de>) starts to recitfy
the problem by ensuring that the close-on-exec flag is set, and that we move
above 3 in the file descriptor table.
I've also decided that the PAM module can close it's pipe handle on every
request - this isn't performance-critical code.
The next step is to do the same for nss_winbind. (But things like getent()
might get in our way there).
This also cleans up some function prototypes, puts them in just one place.
Andrew Bartlett
Diffstat (limited to 'source/nsswitch/wb_common.c')
-rw-r--r-- | source/nsswitch/wb_common.c | 73 |
1 files changed, 69 insertions, 4 deletions
diff --git a/source/nsswitch/wb_common.c b/source/nsswitch/wb_common.c index 9bc9faafb50..0d1be4d5d1f 100644 --- a/source/nsswitch/wb_common.c +++ b/source/nsswitch/wb_common.c @@ -5,6 +5,8 @@ Copyright (C) Tim Potter 2000 Copyright (C) Andrew Tridgell 2000 + Copyright (C) Andrew Bartlett 2002 + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -75,7 +77,7 @@ void init_response(struct winbindd_response *response) /* Close established socket */ -static void close_sock(void) +void close_sock(void) { if (winbindd_fd != -1) { close(winbindd_fd); @@ -83,6 +85,64 @@ static void close_sock(void) } } +/* Make sure socket handle isn't stdin, stdout or stderr */ +#define RECURSION_LIMIT 3 + +static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */) +{ + int new_fd; + if (fd >= 0 && fd <= 2) { +#ifdef F_DUPFD + if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) { + return -1; + } + /* Parinoia */ + if (new_fd < 3) { + return -1; + } + close(fd); + return new_fd; +#else + if (limit <= 0) + return -1; + + new_fd = dup(fd); + if (new_fd == -1) + return -1; + + /* use the program stack to hold our list of FDs to close */ + new_fd = make_nonstd_fd_internals(new_fd, limit - 1); + close(fd); + return new_fd; +#endif + } + return fd; +} + +static int make_safe_fd(int fd) +{ + int result, flags; + int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT); + if (new_fd == -1) { + close(fd); + return -1; + } + /* Socket should be closed on exec() */ + +#ifdef FD_CLOEXEC + result = flags = fcntl(new_fd, F_GETFD, 0); + if (flags >= 0) { + flags |= FD_CLOEXEC; + result = fcntl( new_fd, F_SETFD, flags ); + } + if (result < 0) { + close(new_fd); + return -1; + } +#endif + return new_fd; +} + /* Connect to winbindd socket */ int winbind_open_pipe_sock(void) @@ -91,6 +151,7 @@ int winbind_open_pipe_sock(void) static pid_t our_pid; struct stat st; pstring path; + int fd; if (our_pid != getpid()) { close_sock(); @@ -144,9 +205,13 @@ int winbind_open_pipe_sock(void) /* Connect to socket */ - if ((winbindd_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { return -1; } + + if ((winbindd_fd = make_safe_fd( fd)) == -1) { + return winbindd_fd; + } if (connect(winbindd_fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { @@ -366,8 +431,8 @@ NSS_STATUS winbindd_get_response(struct winbindd_response *response) /* Handle simple types of requests */ NSS_STATUS winbindd_request(int req_type, - struct winbindd_request *request, - struct winbindd_response *response) + struct winbindd_request *request, + struct winbindd_response *response) { NSS_STATUS status; |