@@ -908,8 +908,6 @@ impl Filesystem for OverlayFs {
908908 offset : u64 ,
909909 whence : u32 ,
910910 ) -> Result < ReplyLSeek > {
911- // can this be on dir? FIXME: assume file for now
912- // we need special process if it can be called on dir
913911 let node = self . lookup_node ( req, inode, "" ) . await ?;
914912
915913 if node. whiteout . load ( Ordering :: Relaxed ) {
@@ -918,14 +916,73 @@ impl Filesystem for OverlayFs {
918916
919917 let st = node. stat64 ( req) . await ?;
920918 if utils:: is_dir ( & st. attr . kind ) {
921- error ! ( "lseek on directory" ) ;
922- return Err ( Error :: from_raw_os_error ( libc:: EINVAL ) . into ( ) ) ;
923- }
919+ // Special handling and security restrictions for directory operations
920+ let handles = self . handles . lock ( ) . await ;
921+ let handle_data = handles. get ( & fh) . ok_or_else ( || {
922+ Error :: new ( ErrorKind :: InvalidInput , "Invalid directory handle" )
923+ } ) ?;
924+
925+ // Verify handle type and permissions
926+ if let Some ( ref rh) = handle_data. real_handle {
927+ // Verify that this handle is indeed a directory handle
928+ let handle_stat = if let Ok ( stat) = rh. layer
929+ . getattr ( req, rh. inode , Some ( rh. handle . load ( Ordering :: Relaxed ) ) , 0 )
930+ . await
931+ {
932+ stat
933+ } else {
934+ return Err ( Error :: from_raw_os_error ( libc:: EBADF ) . into ( ) ) ;
935+ } ;
924936
925- let ( layer, real_inode, real_handle) = self . find_real_info_from_handle ( fh) . await ?;
926- layer
927- . lseek ( req, real_inode, real_handle, offset, whence)
928- . await
937+ if !utils:: is_dir ( & handle_stat. attr . kind ) {
938+ return Err ( Error :: from_raw_os_error ( libc:: ENOTDIR ) . into ( ) ) ;
939+ }
940+
941+ match whence {
942+ libc:: SEEK_SET => {
943+ // Validate offset bounds
944+ if offset > i64:: MAX as u64 {
945+ return Err ( Error :: from_raw_os_error ( libc:: EINVAL ) . into ( ) ) ;
946+ }
947+
948+ // Perform the seek operation
949+ rh. layer
950+ . lseek ( req, rh. inode , rh. handle . load ( Ordering :: Relaxed ) , offset, whence)
951+ . await
952+ } ,
953+ libc:: SEEK_CUR => {
954+ // Get current position
955+ let current = if let Ok ( reply) = rh. layer
956+ . lseek ( req, rh. inode , rh. handle . load ( Ordering :: Relaxed ) , 0 , libc:: SEEK_CUR )
957+ . await
958+ {
959+ reply. offset
960+ } else {
961+ return Err ( Error :: from_raw_os_error ( libc:: EINVAL ) . into ( ) ) ;
962+ } ;
963+
964+ // Check for potential overflow
965+ if let Some ( new_offset) = current. checked_add ( offset) {
966+ if new_offset > i64:: MAX as u64 {
967+ return Err ( Error :: from_raw_os_error ( libc:: EINVAL ) . into ( ) ) ;
968+ }
969+ Ok ( ReplyLSeek { offset : new_offset } )
970+ } else {
971+ Err ( Error :: from_raw_os_error ( libc:: EINVAL ) . into ( ) )
972+ }
973+ } ,
974+ _ => Err ( Error :: from_raw_os_error ( libc:: EINVAL ) . into ( ) ) ,
975+ }
976+ } else {
977+ Err ( Error :: new ( ErrorKind :: InvalidInput , "Invalid directory handle" ) . into ( ) )
978+ }
979+ } else {
980+ // Keep the original lseek behavior for regular files
981+ let ( layer, real_inode, real_handle) = self . find_real_info_from_handle ( fh) . await ?;
982+ layer
983+ . lseek ( req, real_inode, real_handle, offset, whence)
984+ . await
985+ }
929986 }
930987
931988 async fn interrupt ( & self , _req : Request , _unique : u64 ) -> Result < ( ) > {
0 commit comments