From ba83243fd31766a30be5ecd84a010d8ef612b381 Mon Sep 17 00:00:00 2001 From: "Damien F. Katz" Date: Tue, 5 Aug 2008 16:54:45 +0000 Subject: Readded file name checks for open and delete, as an attacker could use relative file names to open/delete otherwise inaccessible db files. Also changed view server shutdown when the parent db shutdowns into a non-normal termination, so that the linked supservisor correctly removes the process from its indexes. git-svn-id: https://svn.apache.org/repos/asf/incubator/couchdb/trunk@682790 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/couch_server.erl | 98 +++++++++++++++++++++++++------------------- src/couchdb/couch_view.erl | 2 +- 2 files changed, 56 insertions(+), 44 deletions(-) (limited to 'src/couchdb') diff --git a/src/couchdb/couch_server.erl b/src/couchdb/couch_server.erl index 86cdb2f8..b89f5abc 100644 --- a/src/couchdb/couch_server.erl +++ b/src/couchdb/couch_server.erl @@ -158,36 +158,43 @@ try_close_lru(StartTime) -> end end. +handle_call(get_server, _From, Server) -> + {reply, Server, Server}; handle_call(get_root, _From, #server{root_dir=Root}=Server) -> {reply, {ok, Root}, Server}; handle_call({open, DbName, Options}, {FromPid,_}, Server) -> - Filepath = get_full_filename(Server, DbName), - LruTime = now(), - case ets:lookup(couch_dbs_by_name, DbName) of - [] -> - case maybe_close_lru_db(Server) of - {ok, Server2} -> - case couch_db:start_link(DbName, Filepath, Options) of - {ok, MainPid} -> - true = ets:insert(couch_dbs_by_name, {DbName, {MainPid, LruTime}}), - true = ets:insert(couch_dbs_by_pid, {MainPid, DbName}), - true = ets:insert(couch_dbs_by_lru, {LruTime, DbName}), - DbsOpen = Server2#server.current_dbs_open + 1, - {reply, - couch_db:open_ref_counted(MainPid, FromPid), - Server2#server{current_dbs_open=DbsOpen}}; + case check_dbname(Server, DbName) of + ok -> + Filepath = get_full_filename(Server, DbName), + LruTime = now(), + case ets:lookup(couch_dbs_by_name, DbName) of + [] -> + case maybe_close_lru_db(Server) of + {ok, Server2} -> + case couch_db:start_link(DbName, Filepath, Options) of + {ok, MainPid} -> + true = ets:insert(couch_dbs_by_name, {DbName, {MainPid, LruTime}}), + true = ets:insert(couch_dbs_by_pid, {MainPid, DbName}), + true = ets:insert(couch_dbs_by_lru, {LruTime, DbName}), + DbsOpen = Server2#server.current_dbs_open + 1, + {reply, + couch_db:open_ref_counted(MainPid, FromPid), + Server2#server{current_dbs_open=DbsOpen}}; + Error -> + {reply, Error, Server2} + end; CloseError -> - {reply, CloseError, Server2} + {reply, CloseError, Server} end; - Error -> - {reply, Error, Server} + [{_, {MainPid, PrevLruTime}}] -> + true = ets:insert(couch_dbs_by_name, {DbName, {MainPid, LruTime}}), + true = ets:delete(couch_dbs_by_lru, PrevLruTime), + true = ets:insert(couch_dbs_by_lru, {LruTime, DbName}), + {reply, couch_db:open_ref_counted(MainPid, FromPid), Server} end; - [{_, {MainPid, PrevLruTime}}] -> - true = ets:insert(couch_dbs_by_name, {DbName, {MainPid, LruTime}}), - true = ets:delete(couch_dbs_by_lru, PrevLruTime), - true = ets:insert(couch_dbs_by_lru, {LruTime, DbName}), - {reply, couch_db:open_ref_counted(MainPid, FromPid), Server} + Error -> + {reply, Error, Server} end; handle_call({create, DbName, Options}, {FromPid,_}, Server) -> case check_dbname(Server, DbName) of @@ -216,27 +223,32 @@ handle_call({create, DbName, Options}, {FromPid,_}, Server) -> {reply, Error, Server} end; handle_call({delete, DbName}, _From, Server) -> - FullFilepath = get_full_filename(Server, DbName), - Server2 = - case ets:lookup(couch_dbs_by_name, DbName) of - [] -> Server; - [{_, {Pid, LruTime}}] -> - exit(Pid, kill), - receive {'EXIT', Pid, _Reason} -> ok end, - true = ets:delete(couch_dbs_by_name, DbName), - true = ets:delete(couch_dbs_by_pid, Pid), - true = ets:delete(couch_dbs_by_lru, LruTime), - DbsOpen = Server#server.current_dbs_open - 1, - Server#server{current_dbs_open=DbsOpen} - end, - case file:delete(FullFilepath) of + case check_dbname(Server, DbName) of ok -> - couch_db_update_notifier:notify({deleted, DbName}), - {reply, ok, Server2}; - {error, enoent} -> - {reply, not_found, Server2}; - Else -> - {reply, Else, Server2} + FullFilepath = get_full_filename(Server, DbName), + Server2 = + case ets:lookup(couch_dbs_by_name, DbName) of + [] -> Server; + [{_, {Pid, LruTime}}] -> + exit(Pid, kill), + receive {'EXIT', Pid, _Reason} -> ok end, + true = ets:delete(couch_dbs_by_name, DbName), + true = ets:delete(couch_dbs_by_pid, Pid), + true = ets:delete(couch_dbs_by_lru, LruTime), + DbsOpen = Server#server.current_dbs_open - 1, + Server#server{current_dbs_open=DbsOpen} + end, + case file:delete(FullFilepath) of + ok -> + couch_db_update_notifier:notify({deleted, DbName}), + {reply, ok, Server2}; + {error, enoent} -> + {reply, not_found, Server2}; + Else -> + {reply, Else, Server2} + end; + Error -> + {reply, Error, Server} end; handle_call(remote_restart, _From, #server{remote_restart=false}=Server) -> {reply, ok, Server}; diff --git a/src/couchdb/couch_view.erl b/src/couchdb/couch_view.erl index a29a809c..3ed51d80 100644 --- a/src/couchdb/couch_view.erl +++ b/src/couchdb/couch_view.erl @@ -426,7 +426,7 @@ get_notify_pids(Wait) -> [Pid | get_notify_pids()]; {'DOWN', _MonitorRef, _Type, _Pid, _Info} -> ?LOG_DEBUG("View monitor received parent db shutdown notification. Shutting down instance.", []), - exit(normal); + exit(db_shutdown); Else -> ?LOG_ERROR("Unexpected message in view updater: ~p", [Else]), exit({error, Else}) -- cgit v1.2.3