From: Jim Jagielski Date: Thu, 12 Dec 2002 16:09:52 +0000 (+0000) Subject: Where the OS allows, we now proactively use the various _ex and X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=757b56d928cb7779b5055aa7a74603ef5e89f524;p=thirdparty%2Fapache%2Fhttpd.git Where the OS allows, we now proactively use the various _ex and magic cleanups to close fds (lock files, log files and sockets) to prevent them from leaking into 3rd party modules that don't call ap_cleanup_for_exec() before forking off subprocesses. Expect some possible fine-tuning. Obtained from: Submitted by: Reviewed by: git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@97896 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/CHANGES b/src/CHANGES index 8924db7f736..8281ab2fe06 100644 --- a/src/CHANGES +++ b/src/CHANGES @@ -1,5 +1,14 @@ Changes with Apache 1.3.28 + *) Certain 3rd party modules would bypass the Apache API and not + invoke ap_cleanup_for_exec() before creating sub-processes. + To such a child process, Apache's file descriptors (lock + fd's, log files, sockets) were accessible, allowing them + direct access to Apache log file etc. Where the OS allows, + we now add proactive close functions to prevent these file + descriptors from leaking to the child processes. + [Jim Jagielski, Martin Kraemer] + *) Prevent obscenely large values of precision in ap_vformatter from clobbering a buffer. [Sander Striker, Jim Jagielski] diff --git a/src/include/ap_alloc.h b/src/include/ap_alloc.h index 738f9d441bb..cb284c526d5 100644 --- a/src/include/ap_alloc.h +++ b/src/include/ap_alloc.h @@ -337,6 +337,8 @@ API_EXPORT(void) ap_unblock_alarms(void); API_EXPORT(FILE *) ap_pfopen(struct pool *, const char *name, const char *fmode); API_EXPORT(FILE *) ap_pfdopen(struct pool *, int fd, const char *fmode); API_EXPORT(int) ap_popenf(struct pool *, const char *name, int flg, int mode); +API_EXPORT(int) ap_popenf_ex(struct pool *, const char *name, int flg, + int mode, int domagic); API_EXPORT(void) ap_note_cleanups_for_file(pool *, FILE *); API_EXPORT(void) ap_note_cleanups_for_file_ex(pool *, FILE *, int); @@ -351,6 +353,7 @@ API_EXPORT(void) ap_note_cleanups_for_socket(pool *, int); API_EXPORT(void) ap_note_cleanups_for_socket_ex(pool *, int, int); API_EXPORT(void) ap_kill_cleanups_for_socket(pool *p, int sock); API_EXPORT(int) ap_psocket(pool *p, int, int, int); +API_EXPORT(int) ap_psocket_ex(pool *p, int, int, int, int); API_EXPORT(int) ap_pclosesocket(pool *a, int sock); API_EXPORT(regex_t *) ap_pregcomp(pool *p, const char *pattern, int cflags); diff --git a/src/include/ap_mmn.h b/src/include/ap_mmn.h index 1043634d0f1..81ca8fa45fc 100644 --- a/src/include/ap_mmn.h +++ b/src/include/ap_mmn.h @@ -239,8 +239,9 @@ * 19990320.13 - add ap_strtol() * 19990320.14 - add ap_register_cleanup_ex(), * ap_note_cleanups_for_fd_ex(), - * ap_note_cleanups_for_socket_ex() and - * ap_note_cleanups_for_file_ex() + * ap_note_cleanups_for_socket_ex(), + * ap_note_cleanups_for_file_ex(), + * ap_popenf_ex() and ap_psocket_ex(). */ #define MODULE_MAGIC_COOKIE 0x41503133UL /* "AP13" */ diff --git a/src/main/alloc.c b/src/main/alloc.c index 3b7165aa880..94bb6d0c36e 100644 --- a/src/main/alloc.c +++ b/src/main/alloc.c @@ -1687,14 +1687,19 @@ API_EXPORT(void) ap_register_cleanup_ex(pool *p, void *data, void (*child_cleanup) (void *), int (*magic_cleanup) (void *)) { - struct cleanup *c = (struct cleanup *) ap_palloc(p, sizeof(struct cleanup)); - c->data = data; - c->plain_cleanup = plain_cleanup; - c->child_cleanup = child_cleanup; - c->next = p->cleanups; - p->cleanups = c; - if(magic_cleanup) { - if(!magic_cleanup(data)) + struct cleanup *c; + if (p) { + c = (struct cleanup *) ap_palloc(p, sizeof(struct cleanup)); + c->data = data; + c->plain_cleanup = plain_cleanup; + c->child_cleanup = child_cleanup; + c->next = p->cleanups; + p->cleanups = c; + } + /* attempt to do magic even if not passed a pool. Allows us + * to perform the magic, therefore, "whenever" we want/need */ + if (magic_cleanup) { + if (!magic_cleanup(data)) ap_log_error(APLOG_MARK, APLOG_WARNING, NULL, "exec() may not be safe"); } @@ -1827,7 +1832,8 @@ API_EXPORT(void) ap_kill_cleanups_for_fd(pool *p, int fd) ap_kill_cleanup(p, (void *) (long) fd, fd_cleanup); } -API_EXPORT(int) ap_popenf(pool *a, const char *name, int flg, int mode) +API_EXPORT(int) ap_popenf_ex(pool *a, const char *name, int flg, int mode, + int domagic) { int fd; int save_errno; @@ -1837,13 +1843,18 @@ API_EXPORT(int) ap_popenf(pool *a, const char *name, int flg, int mode) save_errno = errno; if (fd >= 0) { fd = ap_slack(fd, AP_SLACK_HIGH); - ap_note_cleanups_for_fd(a, fd); + ap_note_cleanups_for_fd_ex(a, fd, domagic); } ap_unblock_alarms(); errno = save_errno; return fd; } +API_EXPORT(int) ap_popenf(pool *a, const char *name, int flg, int mode) +{ + return ap_popenf_ex(a, name, flg, mode, 0); +} + API_EXPORT(int) ap_pclosef(pool *a, int fd) { int res; @@ -2047,7 +2058,8 @@ API_EXPORT(void) ap_kill_cleanups_for_socket(pool *p, int sock) ap_kill_cleanup(p, (void *) (long) sock, socket_cleanup); } -API_EXPORT(int) ap_psocket(pool *p, int domain, int type, int protocol) +API_EXPORT(int) ap_psocket_ex(pool *p, int domain, int type, int protocol, + int domagic) { int fd; @@ -2059,11 +2071,16 @@ API_EXPORT(int) ap_psocket(pool *p, int domain, int type, int protocol) errno = save_errno; return -1; } - ap_note_cleanups_for_socket(p, fd); + ap_note_cleanups_for_socket_ex(p, fd, domagic); ap_unblock_alarms(); return fd; } +API_EXPORT(int) ap_psocket(pool *p, int domain, int type, int protocol) +{ + return ap_psocket_ex(p, domain, type, protocol, 0); +} + API_EXPORT(int) ap_pclosesocket(pool *a, int sock) { int res; diff --git a/src/main/http_main.c b/src/main/http_main.c index 34e7d6d7396..50bad3cdcbb 100644 --- a/src/main/http_main.c +++ b/src/main/http_main.c @@ -876,7 +876,7 @@ static void accept_mutex_init_fcntl(pool *p) unlock_it.l_pid = 0; /* pid not actually interesting */ expand_lock_fname(p); - lock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0644); + lock_fd = ap_popenf_ex(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0644, 1); if (lock_fd == -1) { perror("open"); fprintf(stderr, "Cannot open lock file: %s\n", ap_lock_fname); @@ -943,7 +943,7 @@ static void accept_mutex_cleanup_flock(void *foo) static void accept_mutex_child_init_flock(pool *p) { - flock_fd = ap_popenf(p, ap_lock_fname, O_WRONLY, 0600); + flock_fd = ap_popenf_ex(p, ap_lock_fname, O_WRONLY, 0600, 1); if (flock_fd == -1) { ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "Child cannot open lock file: %s", ap_lock_fname); @@ -959,7 +959,7 @@ static void accept_mutex_init_flock(pool *p) { expand_lock_fname(p); unlink(ap_lock_fname); - flock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600); + flock_fd = ap_popenf_ex(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600, 1); if (flock_fd == -1) { ap_log_error(APLOG_MARK, APLOG_EMERG, server_conf, "Parent cannot open lock file: %s", ap_lock_fname); @@ -2457,7 +2457,7 @@ void reopen_scoreboard(pool *p) #ifdef TPF ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname); #endif /* TPF */ - scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0666); + scoreboard_fd = ap_popenf_ex(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0666, 1); if (scoreboard_fd == -1) { perror(ap_scoreboard_fname); fprintf(stderr, "Cannot open scoreboard file:\n"); @@ -2483,7 +2483,7 @@ static void reinit_scoreboard(pool *p) ap_scoreboard_image = &_scoreboard_image; ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname); - scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0644); + scoreboard_fd = ap_popenf_ex(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0644, 1); if (scoreboard_fd == -1) { perror(ap_scoreboard_fname); fprintf(stderr, "Cannot open scoreboard file:\n"); @@ -3655,7 +3655,7 @@ static int make_sock(pool *p, const struct sockaddr_in *server) s = ap_slack(s, AP_SLACK_HIGH); #endif - ap_note_cleanups_for_socket(p, s); /* arrange to close on exec or restart */ + ap_note_cleanups_for_socket_ex(p, s, 1); /* arrange to close on exec or restart */ #ifdef TPF os_note_additional_cleanups(p, s); #endif /* TPF */ @@ -3796,7 +3796,7 @@ static int make_sock(pool *p, const struct sockaddr_in *server) #ifdef WORKAROUND_SOLARIS_BUG s = ap_slack(s, AP_SLACK_HIGH); - ap_note_cleanups_for_socket(p, s); /* arrange to close on exec or restart */ + ap_note_cleanups_for_socket_ex(p, s, 1); /* arrange to close on exec or restart */ #endif ap_unblock_alarms(); @@ -3903,7 +3903,7 @@ static void setup_listeners(pool *p) fd = make_sock(p, &lr->local_addr); } else { - ap_note_cleanups_for_socket(p, fd); + ap_note_cleanups_for_socket_ex(p, fd, 1); } /* if we get here, (fd >= 0) && (fd < FD_SETSIZE) */ FD_SET(fd, &listenfds); @@ -4517,7 +4517,7 @@ static void child_main(int child_num_arg) */ signal(SIGUSR1, SIG_IGN); - ap_note_cleanups_for_socket(ptrans, csd); + ap_note_cleanups_for_socket_ex(ptrans, csd, 1); /* protect various fd_sets */ #ifdef CHECK_FD_SETSIZE @@ -4565,7 +4565,7 @@ static void child_main(int child_num_arg) "dup: couldn't duplicate csd"); dupped_csd = csd; /* Oh well... */ } - ap_note_cleanups_for_socket(ptrans, dupped_csd); + ap_note_cleanups_for_socket_ex(ptrans, dupped_csd, 1); /* protect various fd_sets */ #ifdef CHECK_FD_SETSIZE @@ -5092,7 +5092,7 @@ static void standalone_main(int argc, char **argv) #ifdef SCOREBOARD_FILE else { ap_scoreboard_fname = ap_server_root_relative(pconf, ap_scoreboard_fname); - ap_note_cleanups_for_fd(pconf, scoreboard_fd); + ap_note_cleanups_for_fd_ex(pconf, scoreboard_fd, 1); /* close on exec */ } #endif @@ -5892,7 +5892,7 @@ static void child_sub_main(int child_num) requests_this_child++; - ap_note_cleanups_for_socket(ptrans, csd); + ap_note_cleanups_for_socket_ex(ptrans, csd, 1); /* * We now have a connection, so set it up with the appropriate @@ -5924,7 +5924,7 @@ static void child_sub_main(int child_num) "dup: couldn't duplicate csd"); dupped_csd = csd; /* Oh well... */ } - ap_note_cleanups_for_socket(ptrans, dupped_csd); + ap_note_cleanups_for_socket_ex(ptrans, dupped_csd, 1); #endif ap_bpushfd(conn_io, csd, dupped_csd); @@ -6140,7 +6140,7 @@ static void setup_inherited_listeners(pool *p) if (fd > listenmaxfd) listenmaxfd = fd; } - ap_note_cleanups_for_socket(p, fd); + ap_note_cleanups_for_socket_ex(p, fd, 1); lr->fd = fd; if (lr->next == NULL) { /* turn the list into a ring */ diff --git a/src/main/rfc1413.c b/src/main/rfc1413.c index e115d0e3978..628bec7bac2 100644 --- a/src/main/rfc1413.c +++ b/src/main/rfc1413.c @@ -243,7 +243,7 @@ API_EXPORT(char *) ap_rfc1413(conn_rec *conn, server_rec *srv) result = FROM_UNKNOWN; - sock = ap_psocket(conn->pool, AF_INET, SOCK_STREAM, IPPROTO_TCP); + sock = ap_psocket_ex(conn->pool, AF_INET, SOCK_STREAM, IPPROTO_TCP, 1); if (sock < 0) { ap_log_error(APLOG_MARK, APLOG_CRIT, srv, "socket: rfc1413: error creating socket"); diff --git a/src/modules/proxy/proxy_connect.c b/src/modules/proxy/proxy_connect.c index 9b955d51776..7ae9af9ee9a 100644 --- a/src/modules/proxy/proxy_connect.c +++ b/src/modules/proxy/proxy_connect.c @@ -182,7 +182,7 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url, return ap_proxyerror(r, proxyhost ? HTTP_BAD_GATEWAY : HTTP_INTERNAL_SERVER_ERROR, err); - sock = ap_psocket(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP); + sock = ap_psocket_ex(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1); if (sock == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: error creating socket"); return HTTP_INTERNAL_SERVER_ERROR; diff --git a/src/modules/proxy/proxy_ftp.c b/src/modules/proxy/proxy_ftp.c index 076d23b00a7..f01b890d6bb 100644 --- a/src/modules/proxy/proxy_ftp.c +++ b/src/modules/proxy/proxy_ftp.c @@ -665,7 +665,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) if (err != NULL) return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err); - sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1); if (sock == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: error creating socket"); @@ -944,7 +944,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) } /* try to set up PASV data connection first */ - dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + dsock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1); if (dsock == -1) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, @@ -1032,7 +1032,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) "proxy: error getting socket address")); } - dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + dsock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1); if (dsock == -1) { return ftp_cleanup_and_return(r, ctrl, data, sock, dsock, ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, diff --git a/src/modules/proxy/proxy_http.c b/src/modules/proxy/proxy_http.c index a11688d8a8c..db6ce82910e 100644 --- a/src/modules/proxy/proxy_http.c +++ b/src/modules/proxy/proxy_http.c @@ -241,7 +241,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, * we have worked out who exactly we are going to connect to, now make * that connection... */ - sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1); if (sock == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: error creating socket"); diff --git a/src/modules/standard/mod_log_agent.c b/src/modules/standard/mod_log_agent.c index fde6b917eb4..ac7e6ca739d 100644 --- a/src/modules/standard/mod_log_agent.c +++ b/src/modules/standard/mod_log_agent.c @@ -125,7 +125,8 @@ static void open_agent_log(server_rec *s, pool *p) cls->agent_fd = ap_piped_log_write_fd(pl); } else if (*cls->fname != '\0') { - if ((cls->agent_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) { + if ((cls->agent_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1)) + < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "could not open agent log file %s.", fname); exit(1); diff --git a/src/modules/standard/mod_log_config.c b/src/modules/standard/mod_log_config.c index 078a060253d..ceeffc3333d 100644 --- a/src/modules/standard/mod_log_config.c +++ b/src/modules/standard/mod_log_config.c @@ -1069,7 +1069,8 @@ static config_log_state *open_config_log(server_rec *s, pool *p, } else { char *fname = ap_server_root_relative(p, cls->fname); - if ((cls->log_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) { + if ((cls->log_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1)) + < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "could not open transfer log file %s.", fname); exit(1); diff --git a/src/modules/standard/mod_log_referer.c b/src/modules/standard/mod_log_referer.c index 733fd18a2d6..fbec82ab9b0 100644 --- a/src/modules/standard/mod_log_referer.c +++ b/src/modules/standard/mod_log_referer.c @@ -142,7 +142,8 @@ static void open_referer_log(server_rec *s, pool *p) cls->referer_fd = ap_piped_log_write_fd(pl); } else if (*cls->fname != '\0') { - if ((cls->referer_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) { + if ((cls->referer_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1)) + < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "could not open referer log file %s.", fname); exit(1); diff --git a/src/modules/standard/mod_rewrite.c b/src/modules/standard/mod_rewrite.c index 4dee75c5a53..a25ca73dc59 100644 --- a/src/modules/standard/mod_rewrite.c +++ b/src/modules/standard/mod_rewrite.c @@ -3105,8 +3105,8 @@ static void open_rewritelog(server_rec *s, pool *p) conf->rewritelogfp = ap_piped_log_write_fd(pl); } else if (*conf->rewritelogfile != '\0') { - if ((conf->rewritelogfp = ap_popenf(p, fname, rewritelog_flags, - rewritelog_mode)) < 0) { + if ((conf->rewritelogfp = ap_popenf_ex(p, fname, rewritelog_flags, + rewritelog_mode, 1)) < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "mod_rewrite: could not open RewriteLog " @@ -3253,8 +3253,8 @@ static void rewritelock_create(server_rec *s, pool *p) /* create the lockfile */ unlink(lockname); - if ((lockfd = ap_popenf(p, lockname, O_WRONLY|O_CREAT, - REWRITELOCK_MODE)) < 0) { + if ((lockfd = ap_popenf_ex(p, lockname, O_WRONLY|O_CREAT, + REWRITELOCK_MODE, 1)) < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "mod_rewrite: Parent could not create RewriteLock " "file %s", lockname); @@ -3281,8 +3281,8 @@ static void rewritelock_open(server_rec *s, pool *p) } /* open the lockfile (once per child) to get a unique fd */ - if ((lockfd = ap_popenf(p, lockname, O_WRONLY, - REWRITELOCK_MODE)) < 0) { + if ((lockfd = ap_popenf_ex(p, lockname, O_WRONLY, + REWRITELOCK_MODE, 1)) < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "mod_rewrite: Child could not open RewriteLock " "file %s", lockname); diff --git a/src/os/netware/mod_log_nw.c b/src/os/netware/mod_log_nw.c index f5718746f13..69febd1dce7 100644 --- a/src/os/netware/mod_log_nw.c +++ b/src/os/netware/mod_log_nw.c @@ -1161,7 +1161,7 @@ static config_log_state *open_config_log(server_rec *s, pool *p, fname = ap_server_root_relative(p, cls->fname); } - if ((cls->log_fd = ap_popenf(p, fname, xfer_flags, xfer_mode)) < 0) { + if ((cls->log_fd = ap_popenf_ex(p, fname, xfer_flags, xfer_mode, 1)) < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "could not open transfer log file %s.", fname); exit(1);