@@ -330,19 +330,24 @@ handle_op(?SSH_FXP_INIT, Version, B, State) when is_binary(B) ->
330330 ssh_xfer :xf_send_reply (XF1 , ? SSH_FXP_VERSION , <<? UINT32 (Vsn )>>),
331331 State # state {xf = XF1 };
332332handle_op (? SSH_FXP_REALPATH , ReqId ,
333- <<? UINT32 (RLen ), RPath :RLen /binary >>,
334- State0 ) ->
333+ <<? UINT32 (RLen ), RPath :RLen /binary >>,
334+ State0 ) ->
335335 RelPath = relate_file_name (RPath , State0 , _Canonicalize = false ),
336- {Res , State } = resolve_symlinks (RelPath , State0 ),
336+ {Res , # state { root = Root } = State } = resolve_symlinks (RelPath , State0 ),
337337 case Res of
338- {ok , AbsPath } ->
339- NewAbsPath = chroot_filename (AbsPath , State ),
340- XF = State # state .xf ,
341- Attr = # ssh_xfer_attr {type = directory },
342- ssh_xfer :xf_send_name (XF , ReqId , NewAbsPath , Attr ),
343- State ;
344- {error , _ } = Error ->
345- send_status (Error , ReqId , State )
338+ {ok , AbsPath } ->
339+ case Root =:= " " orelse is_within_root (Root , AbsPath ) of
340+ true ->
341+ NewAbsPath = chroot_filename (AbsPath , State ),
342+ XF = State # state .xf ,
343+ Attr = # ssh_xfer_attr {type = directory },
344+ ssh_xfer :xf_send_name (XF , ReqId , NewAbsPath , Attr ),
345+ State ;
346+ false ->
347+ send_status ({error , enoent }, ReqId , State )
348+ end ;
349+ {error , _ } = Error ->
350+ send_status (Error , ReqId , State )
346351 end ;
347352handle_op (? SSH_FXP_OPENDIR , ReqId ,
348353 <<? UINT32 (RLen ), RPath :RLen /binary >>,
0 commit comments