1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
Description: Fix race condition with chdir
Fix /var/www* being accepted as docroot instead of /var/www/*
(the same for public_html* instead of public_html/* )
Author: Stefan Fritsch <sf@debian.org>
Last-Update: 2014-05-29
Bug: https://issues.apache.org/bugzilla/show_bug.cgi?id=44752
--- a/support/suexec.c
+++ b/support/suexec.c
@@ -42,6 +42,7 @@
#if APR_HAVE_UNISTD_H
#include <unistd.h>
#endif
+#include <fcntl.h>
#include <stdio.h>
#include <stdarg.h>
@@ -281,11 +282,12 @@
char *actual_gname; /* actual group name */
char *cmd; /* command to be executed */
char cwd[AP_MAXPATH]; /* current working directory */
- char dwd[AP_MAXPATH]; /* docroot working directory */
+ char dwd[AP_MAXPATH+1]; /* docroot working directory */
struct passwd *pw; /* password entry holder */
struct group *gr; /* group entry holder */
struct stat dir_info; /* directory info holder */
struct stat prg_info; /* program info holder */
+ int cwdh; /* handle to cwd */
/*
* Start with a "clean" environment
@@ -529,11 +531,16 @@
exit(111);
}
+ if ( (cwdh = open(".", O_RDONLY)) == -1 ) {
+ log_err("cannot open current working directory\n");
+ exit(111);
+ }
+
if (userdir) {
if (((chdir(target_homedir)) != 0) ||
((chdir(AP_USERDIR_SUFFIX)) != 0) ||
((getcwd(dwd, AP_MAXPATH)) == NULL) ||
- ((chdir(cwd)) != 0)) {
+ ((fchdir(cwdh)) != 0)) {
log_err("cannot get docroot information (%s)\n", target_homedir);
exit(112);
}
@@ -541,12 +548,16 @@
else {
if (((chdir(AP_DOC_ROOT)) != 0) ||
((getcwd(dwd, AP_MAXPATH)) == NULL) ||
- ((chdir(cwd)) != 0)) {
+ ((fchdir(cwdh)) != 0)) {
log_err("cannot get docroot information (%s)\n", AP_DOC_ROOT);
exit(113);
}
}
+ close(cwdh);
+
+ if (strlen(cwd) > strlen(dwd))
+ strncat(dwd, "/", 1);
if ((strncmp(cwd, dwd, strlen(dwd))) != 0) {
log_err("command not in docroot (%s/%s)\n", cwd, cmd);
exit(114);
|