apache分析之一、svn:Could not open the requested SVN filesystem
一、问题描述
本来是想测试一下svn的post-commit hook为什么能够实现对于后台任务的同步等待,所以就搭建了一个apache和svn的服务器程序,但是在调试的过程中一直出现文件系统打不开的问题,在apache的错误日志中也可以看到下面的提示内容,
1647 [Sun Oct 14 11:40:41.036210 2012] [:error] [pid 31176:tid 3064986480] (2001 4)Internal error: [client 192.168.203.1:3684] traced call
1648 [Sun Oct 14 11:40:41.036448 2012] [dav:error] [pid 31176:tid 3064986480] [c lient 192.168.203.1:3684] Could not fetch resource information. [500, #0]
1649 [Sun Oct 14 11:40:41.036468 2012] [dav:error] [pid 31176:tid 3064986480] [c lient 192.168.203.1:3684] Could not open the requested SVN filesystem [500 , #13]
1650 [Sun Oct 14 11:40:41.036482 2012] [dav:error] [pid 31176:tid 3064986480] [c lient 192.168.203.1:3684] Could not open the requested SVN filesystem [500 , #13]
1651 [Sun Oct 14 11:40:41.807462 2012] [dav:error] [pid 31176:tid 3054496624] [c lient 192.168.203.1:1050] Could not fetch resource information. [301, #0]
1652 [Sun Oct 14 11:40:41.807514 2012] [dav:error] [pid 31176:tid 3054496624] (2 )No such file or directory: [client 192.168.203.1:1050] Requests for a coll ection must have a trailing slash on the URI. [301, #0]
二、分析过程
由于apache支持调试模式运行,所以在apache启动的过程中,添加-X参数,这样apache就是自己单进程执行,这样便于调试,如果使能了apache的派生模式,我们不会知道是哪个进程执行了这个任务,所以这是一个将问题范围缩小的功能。
在apache的源代码中搜索这个错误提示字符串"Could not open the requested SVN filesystem",可以找到该提示位于httpd-2.4.2\modules\dav\main\mod_dav.c文件的dav_get_resource函数中,在该函数打断点,在错误提示的上一样单步步入
/* resolve the resource */
err = (*conf->provider->repos->get_resource)(r, conf->dir,
label, use_checked_in,
res_p);
if (err != NULL) {
err = dav_push_error(r->pool, err->status, 0,
"Could not fetch resource information.", err);
return err;
}
最后找到出错位置
164 if (perm == APR_OS_DEFAULT) {
(gdb)
165 fd = open(fname, oflags, 0666);
(gdb) bt
#0 apr_file_open (new=0xb61fc02c, fname=0x999bb58 "/home/svnuser", flag=129,
perm=4095, pool=0xa660a6c0) at file_io/unix/open.c:165
#1 0x0806b892 in ap_pcfg_openfile (ret_cfg=0xb61fe07c, p=0xa660a6c0,
name=0x999bb58 "/home/svnuser") at util.c:860
#2 0x00c418f2 in check_password (r=0xa660a700, user=0xa660c108 "tsecer",
password=0xa660c0f7 "tsecer") at mod_authn_file.c:84
#3 0x00145f31 in authenticate_basic_user (r=0xa660a700) at mod_auth_basic.c:241
#4 0x080806c9 in ap_run_check_user_id (r=0xa660a700) at request.c:79
#5 0x0808169b in ap_process_request_internal (r=0xa660a700) at request.c:233
#6 0x080a2c54 in ap_process_async_request (r=0xa660a700) at http_request.c:315
#7 0x0809f3cf in ap_process_http_async_connection (c=0xb6c01c00)
at http_core.c:143
#8 0x0809f5a2 in ap_process_http_connection (c=0xb6c01c00) at http_core.c:228
#9 0x08095ee3 in ap_run_process_connection (c=0xb6c01c00) at connection.c:41
#10 0x080ab9ef in process_socket (thd=0x99bd290, p=0xb6c019c8, sock=0xb6c01a10,
cs=0xb6c01bb8, my_child_num=0, my_thread_num=1) at event.c:917
#11 0x080adb14 in worker_thread (thd=0x99bd290, dummy=0xb6c00468) at event.c:1744
#12 0x009bfe0d in dummy_worker (opaque=0x99bd290) at threadproc/unix/thread.c:142
#13 0x00391925 in start_thread () from /lib/libpthread.so.0
#14 0x002e707e in clone () from /lib/libc.so.6
(gdb)
这里可以看到对于svn文件通过绝对路径打开,并且要求权限是666权限。我们看一下内核中对于绝对路径打开的限制:__link_path_walk-->>
static int exec_permission_lite(struct inode *inode,
struct nameidata *nd)
{
umode_t mode = inode->i_mode;
if (inode->i_op && inode->i_op->permission)
return -EAGAIN;
if (current->fsuid == inode->i_uid)
mode >>= 6;
else if (in_group_p(inode->i_gid))
mode >>= 3;
if (mode & MAY_EXEC)
goto ok;
如果一个文件夹对该用户没有可执行权限,那么该用户是无法打开该文件夹的任意一个文件的。
三、解决办法
为svn建立一个单独的文件,修改该文件夹的权限为可打开权限。
chmod 777 -R /path/to/svn/repos
其实回头看看之前apache的输出日志,其中已经有显示到13这个错误码,在内核中,该错误码的意义为权限不足:
#define EACCES 13 /* Permission denied */
只是说不知道该字段的意义而没有关注
本来是想测试一下svn的post-commit hook为什么能够实现对于后台任务的同步等待,所以就搭建了一个apache和svn的服务器程序,但是在调试的过程中一直出现文件系统打不开的问题,在apache的错误日志中也可以看到下面的提示内容,
1647 [Sun Oct 14 11:40:41.036210 2012] [:error] [pid 31176:tid 3064986480] (2001 4)Internal error: [client 192.168.203.1:3684] traced call
1648 [Sun Oct 14 11:40:41.036448 2012] [dav:error] [pid 31176:tid 3064986480] [c lient 192.168.203.1:3684] Could not fetch resource information. [500, #0]
1649 [Sun Oct 14 11:40:41.036468 2012] [dav:error] [pid 31176:tid 3064986480] [c lient 192.168.203.1:3684] Could not open the requested SVN filesystem [500 , #13]
1650 [Sun Oct 14 11:40:41.036482 2012] [dav:error] [pid 31176:tid 3064986480] [c lient 192.168.203.1:3684] Could not open the requested SVN filesystem [500 , #13]
1651 [Sun Oct 14 11:40:41.807462 2012] [dav:error] [pid 31176:tid 3054496624] [c lient 192.168.203.1:1050] Could not fetch resource information. [301, #0]
1652 [Sun Oct 14 11:40:41.807514 2012] [dav:error] [pid 31176:tid 3054496624] (2 )No such file or directory: [client 192.168.203.1:1050] Requests for a coll ection must have a trailing slash on the URI. [301, #0]
二、分析过程
由于apache支持调试模式运行,所以在apache启动的过程中,添加-X参数,这样apache就是自己单进程执行,这样便于调试,如果使能了apache的派生模式,我们不会知道是哪个进程执行了这个任务,所以这是一个将问题范围缩小的功能。
在apache的源代码中搜索这个错误提示字符串"Could not open the requested SVN filesystem",可以找到该提示位于httpd-2.4.2\modules\dav\main\mod_dav.c文件的dav_get_resource函数中,在该函数打断点,在错误提示的上一样单步步入
/* resolve the resource */
err = (*conf->provider->repos->get_resource)(r, conf->dir,
label, use_checked_in,
res_p);
if (err != NULL) {
err = dav_push_error(r->pool, err->status, 0,
"Could not fetch resource information.", err);
return err;
}
最后找到出错位置
164 if (perm == APR_OS_DEFAULT) {
(gdb)
165 fd = open(fname, oflags, 0666);
(gdb) bt
#0 apr_file_open (new=0xb61fc02c, fname=0x999bb58 "/home/svnuser", flag=129,
perm=4095, pool=0xa660a6c0) at file_io/unix/open.c:165
#1 0x0806b892 in ap_pcfg_openfile (ret_cfg=0xb61fe07c, p=0xa660a6c0,
name=0x999bb58 "/home/svnuser") at util.c:860
#2 0x00c418f2 in check_password (r=0xa660a700, user=0xa660c108 "tsecer",
password=0xa660c0f7 "tsecer") at mod_authn_file.c:84
#3 0x00145f31 in authenticate_basic_user (r=0xa660a700) at mod_auth_basic.c:241
#4 0x080806c9 in ap_run_check_user_id (r=0xa660a700) at request.c:79
#5 0x0808169b in ap_process_request_internal (r=0xa660a700) at request.c:233
#6 0x080a2c54 in ap_process_async_request (r=0xa660a700) at http_request.c:315
#7 0x0809f3cf in ap_process_http_async_connection (c=0xb6c01c00)
at http_core.c:143
#8 0x0809f5a2 in ap_process_http_connection (c=0xb6c01c00) at http_core.c:228
#9 0x08095ee3 in ap_run_process_connection (c=0xb6c01c00) at connection.c:41
#10 0x080ab9ef in process_socket (thd=0x99bd290, p=0xb6c019c8, sock=0xb6c01a10,
cs=0xb6c01bb8, my_child_num=0, my_thread_num=1) at event.c:917
#11 0x080adb14 in worker_thread (thd=0x99bd290, dummy=0xb6c00468) at event.c:1744
#12 0x009bfe0d in dummy_worker (opaque=0x99bd290) at threadproc/unix/thread.c:142
#13 0x00391925 in start_thread () from /lib/libpthread.so.0
#14 0x002e707e in clone () from /lib/libc.so.6
(gdb)
这里可以看到对于svn文件通过绝对路径打开,并且要求权限是666权限。我们看一下内核中对于绝对路径打开的限制:__link_path_walk-->>
static int exec_permission_lite(struct inode *inode,
struct nameidata *nd)
{
umode_t mode = inode->i_mode;
if (inode->i_op && inode->i_op->permission)
return -EAGAIN;
if (current->fsuid == inode->i_uid)
mode >>= 6;
else if (in_group_p(inode->i_gid))
mode >>= 3;
if (mode & MAY_EXEC)
goto ok;
如果一个文件夹对该用户没有可执行权限,那么该用户是无法打开该文件夹的任意一个文件的。
三、解决办法
为svn建立一个单独的文件,修改该文件夹的权限为可打开权限。
chmod 777 -R /path/to/svn/repos
其实回头看看之前apache的输出日志,其中已经有显示到13这个错误码,在内核中,该错误码的意义为权限不足:
#define EACCES 13 /* Permission denied */
只是说不知道该字段的意义而没有关注