Skip to content

Commit 368e472

Browse files
committed
PR 45959
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@733754 13f79535-47bb-0310-9956-ffa450edef68
1 parent 19fec94 commit 368e472

2 files changed

Lines changed: 56 additions & 10 deletions

File tree

STATUS

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
130130
http://svn.apache.org/viewvc?view=rev&revision=732504
131131
+1: niq, rpluem, jim
132132

133-
* core: fix symlink checking in directory walk
134-
PR 45959
135-
trunk:
136-
r423886, r425057, r425394, r490920, r491297
137-
2.2.x:
138-
http://people.apache.org/~niq/patches/45959
139-
+1: niq, rpluem, jim
140-
141133

142134
PATCHES PROPOSED TO BACKPORT FROM TRUNK:
143135
[ New proposals should be added at the end of the list ]

server/request.c

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -558,17 +558,71 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r)
558558
&& (!r->path_info || !*r->path_info)))
559559
&& (cache->dir_conf_tested == sec_ent)
560560
&& (strcmp(entry_dir, cache->cached) == 0)) {
561+
562+
int familiar = 0;
563+
561564
/* Well this looks really familiar! If our end-result (per_dir_result)
562565
* didn't change, we have absolutely nothing to do :)
563566
* Otherwise (as is the case with most dir_merged/file_merged requests)
564567
* we must merge our dir_conf_merged onto this new r->per_dir_config.
565568
*/
566569
if (r->per_dir_config == cache->per_dir_result) {
567-
return OK;
570+
familiar = 1;
568571
}
569572

570-
if (r->per_dir_config == cache->dir_conf_merged) {
573+
else if (r->per_dir_config == cache->dir_conf_merged) {
571574
r->per_dir_config = cache->per_dir_result;
575+
familiar = 1;
576+
}
577+
if (familiar) {
578+
apr_finfo_t thisinfo;
579+
int res;
580+
allow_options_t opts;
581+
core_dir_config *this_dir;
582+
583+
this_dir = ap_get_module_config(r->per_dir_config, &core_module);
584+
opts = this_dir->opts;
585+
/*
586+
* If Symlinks are allowed in general we do not need the following
587+
* check.
588+
*/
589+
if (!(opts & OPT_SYM_LINKS)) {
590+
rv = apr_stat(&thisinfo, r->filename,
591+
APR_FINFO_MIN | APR_FINFO_NAME | APR_FINFO_LINK,
592+
r->pool);
593+
/*
594+
* APR_INCOMPLETE is as fine as result as APR_SUCCESS as we
595+
* have added APR_FINFO_NAME to the wanted parameter of
596+
* apr_stat above. On Unix platforms this means that apr_stat
597+
* is always going to return APR_INCOMPLETE in the case that
598+
* the call to the native stat / lstat did not fail.
599+
*/
600+
if ((rv != APR_INCOMPLETE) && (rv != APR_SUCCESS)) {
601+
/*
602+
* This should never happen, because we did a stat on the
603+
* same file, resolving a possible symlink several lines
604+
* above. Therefore do not make a detailed analysis of rv
605+
* in this case for the reason of the failure, just bail out
606+
* with a HTTP_FORBIDDEN in case we hit a race condition
607+
* here.
608+
*/
609+
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
610+
"access to %s failed; stat of '%s' failed.",
611+
r->uri, r->filename);
612+
return r->status = HTTP_FORBIDDEN;
613+
}
614+
if (thisinfo.filetype == APR_LNK) {
615+
/* Is this a possibly acceptable symlink? */
616+
if ((res = resolve_symlink(r->filename, &thisinfo,
617+
opts, r->pool)) != OK) {
618+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
619+
"Symbolic link not allowed "
620+
"or link target not accessible: %s",
621+
r->filename);
622+
return r->status = res;
623+
}
624+
}
625+
}
572626
return OK;
573627
}
574628

0 commit comments

Comments
 (0)