@@ -155,7 +155,10 @@ void Machine::setup_linux_system_calls()
155
155
5 , [] (vCPU& cpu) { // FSTAT
156
156
auto & regs = cpu.registers ();
157
157
158
- int fd = cpu.machine ().fds ().translate (regs.rdi );
158
+ int fd = regs.rdi ;
159
+ if (fd > 2 ) {
160
+ fd = cpu.machine ().fds ().translate (regs.rdi );
161
+ }
159
162
struct stat vstat;
160
163
regs.rax = fstat (fd, &vstat);
161
164
if (regs.rax == 0 ) {
@@ -673,6 +676,19 @@ void Machine::setup_linux_system_calls()
673
676
regs.rax );
674
677
cpu.set_registers (regs);
675
678
});
679
+ Machine::install_syscall_handler (
680
+ 79 , [](vCPU& cpu) { // GETCWD
681
+ auto & regs = cpu.registers ();
682
+
683
+ const char fakepath[] = " /" ;
684
+ if (sizeof (fakepath) <= regs.rsi ) {
685
+ cpu.machine ().copy_to_guest (regs.rdi , fakepath, sizeof (fakepath));
686
+ regs.rax = regs.rdi ;
687
+ } else {
688
+ regs.rax = 0 ;
689
+ }
690
+ cpu.set_registers (regs);
691
+ });
676
692
Machine::install_syscall_handler (
677
693
89 , [](vCPU& cpu) { // READLINK
678
694
auto & regs = cpu.registers ();
@@ -761,6 +777,22 @@ void Machine::setup_linux_system_calls()
761
777
SYSPRINT (" sched_getaffinity() = %lld\n " , regs.rax );
762
778
cpu.set_registers (regs);
763
779
});
780
+ Machine::install_syscall_handler (
781
+ 217 , [](vCPU& cpu) { // GETDENTS64
782
+ auto & regs = cpu.registers ();
783
+
784
+ int fd = cpu.machine ().fds ().translate (regs.rdi );
785
+
786
+ char buffer[2048 ];
787
+ regs.rax = syscall (SYS_getdents64, fd, buffer, sizeof (buffer));
788
+ if (regs.rax > 0 )
789
+ {
790
+ cpu.machine ().copy_to_guest (regs.rsi , buffer, regs.rax );
791
+ }
792
+ SYSPRINT (" GETDENTS64 to vfd=%lld, fd=%d, data=0x%llX = %lld\n " ,
793
+ regs.rdi , fd, regs.rsi , regs.rax );
794
+ cpu.set_registers (regs);
795
+ });
764
796
Machine::install_syscall_handler (
765
797
228 , [](vCPU& cpu) { // clock_gettime
766
798
auto & regs = cpu.registers ();
@@ -783,6 +815,104 @@ void Machine::setup_linux_system_calls()
783
815
printf (" Machine exits: _exit(%lld)\n " , regs.rdi );
784
816
#endif
785
817
cpu.stop (); });
818
+ Machine::install_syscall_handler (
819
+ 257 , [] (vCPU& cpu) { // OPENAT
820
+ auto & regs = cpu.registers ();
821
+
822
+ const auto vpath = regs.rsi ;
823
+ const int flags = regs.rdx ;
824
+
825
+ std::string path = cpu.machine ().memcstring (vpath, PATH_MAX);
826
+ bool write_flags = (flags & (O_WRONLY | O_RDWR)) != 0x0 ;
827
+ if (!write_flags)
828
+ {
829
+ try {
830
+ std::string real_path = path;
831
+ if (!cpu.machine ().fds ().is_readable_path (real_path)) {
832
+ throw std::runtime_error (" Path not readable: " + real_path);
833
+ }
834
+
835
+ int fd = openat (AT_FDCWD, real_path.c_str (), flags);
836
+ if (fd > 0 ) {
837
+ regs.rax = cpu.machine ().fds ().manage (fd, false );
838
+ } else {
839
+ regs.rax = -1 ;
840
+ }
841
+ SYSPRINT (" OPENAT fd=%lld path=%s (real_path=%s) = %d (%lld)\n " ,
842
+ regs.rdi , path.c_str (), real_path.c_str (), fd, regs.rax );
843
+ cpu.set_registers (regs);
844
+ return ;
845
+ } catch (...) {
846
+ SYSPRINT (" OPENAT fd=%lld path=%s flags=%X = %d\n " ,
847
+ regs.rdi , path.c_str (), flags, -1 );
848
+ regs.rax = -1 ;
849
+ }
850
+ }
851
+ if (write_flags || regs.rax == (__u64)-1 )
852
+ {
853
+ try {
854
+ std::string real_path = path;
855
+ if (!cpu.machine ().fds ().is_writable_path (real_path)) {
856
+ throw std::runtime_error (" Path not writable: " + real_path);
857
+ }
858
+
859
+ int fd = openat (AT_FDCWD, real_path.c_str (), flags, S_IWUSR | S_IRUSR);
860
+ SYSPRINT (" OPENAT where=%lld path=%s (real_path=%s) flags=%X = fd %d\n " ,
861
+ regs.rdi , path.c_str (), real_path.c_str (), flags, fd);
862
+
863
+ if (fd > 0 ) {
864
+ regs.rax = cpu.machine ().fds ().manage (fd, false );
865
+ } else {
866
+ regs.rax = -1 ;
867
+ }
868
+ } catch (...) {
869
+ regs.rax = -1 ;
870
+ }
871
+ }
872
+ cpu.set_registers (regs);
873
+ });
874
+ Machine::install_syscall_handler (
875
+ 262 , [] (vCPU& cpu) { // NEWFSTATAT
876
+ auto & regs = cpu.registers ();
877
+ const auto vpath = regs.rsi ;
878
+ const auto buffer = regs.rdx ;
879
+ const int flags = regs.r8 ;
880
+ int fd = AT_FDCWD;
881
+ std::string path;
882
+
883
+ try {
884
+ path = cpu.machine ().memcstring (vpath, PATH_MAX);
885
+
886
+ if (regs.rdi != AT_FDCWD) {
887
+ // Use existing vfd
888
+ fd = cpu.machine ().fds ().translate (regs.rdi );
889
+
890
+ struct stat64 vstat;
891
+ // We don't use path here, as a security measure
892
+ regs.rax = fstatat64 (fd, " " , &vstat, flags);
893
+ if (regs.rax == 0 ) {
894
+ cpu.machine ().copy_to_guest (buffer, &vstat, sizeof (vstat));
895
+ }
896
+ } else {
897
+ if (!cpu.machine ().fds ().is_readable_path (path)) {
898
+ regs.rax = -EPERM;
899
+ } else {
900
+ struct stat64 vstat;
901
+ // Path is in allow-list
902
+ regs.rax = fstatat64 (AT_FDCWD, path.c_str (), &vstat, flags);
903
+ if (regs.rax == 0 ) {
904
+ cpu.machine ().copy_to_guest (buffer, &vstat, sizeof (vstat));
905
+ }
906
+ }
907
+ }
908
+ } catch (...) {
909
+ regs.rax = -1 ;
910
+ }
911
+
912
+ SYSPRINT (" NEWFSTATAT to vfd=%lld, vfd=%d, path=%s, data=0x%llX, flags=0x%X = %lld\n " ,
913
+ regs.rdi , fd, path.c_str (), buffer, flags, regs.rax );
914
+ cpu.set_registers (regs);
915
+ });
786
916
Machine::install_syscall_handler (
787
917
273 , [](vCPU& cpu)
788
918
{
@@ -887,147 +1017,6 @@ void Machine::setup_linux_system_calls()
887
1017
g_buf, bytes, flags, regs.rax );
888
1018
cpu.set_registers (regs);
889
1019
});
890
- Machine::install_syscall_handler (
891
- 334 , [](vCPU& cpu) { // faccessat
892
- auto & regs = cpu.registers ();
893
- regs.rax = -ENOSYS;
894
- SYSPRINT (" faccessat(...) = %lld\n " ,
895
- regs.rax );
896
- cpu.set_registers (regs);
897
- });
898
-
899
- // Threads: clone, futex, block/tkill etc.
900
- Machine::setup_multithreading ();
901
- Machine::install_syscall_handler (
902
- 79 , [](vCPU& cpu) { // GETCWD
903
- auto & regs = cpu.registers ();
904
-
905
- const char fakepath[] = " /" ;
906
- if (sizeof (fakepath) <= regs.rsi ) {
907
- cpu.machine ().copy_to_guest (regs.rdi , fakepath, sizeof (fakepath));
908
- regs.rax = regs.rdi ;
909
- } else {
910
- regs.rax = 0 ;
911
- }
912
- cpu.set_registers (regs);
913
- });
914
- Machine::install_syscall_handler (
915
- 217 , [](vCPU& cpu) { // GETDENTS64
916
- auto & regs = cpu.registers ();
917
-
918
- int fd = cpu.machine ().fds ().translate (regs.rdi );
919
-
920
- char buffer[2048 ];
921
- regs.rax = syscall (SYS_getdents64, fd, buffer, sizeof (buffer));
922
- if (regs.rax > 0 )
923
- {
924
- cpu.machine ().copy_to_guest (regs.rsi , buffer, regs.rax );
925
- }
926
- SYSPRINT (" GETDENTS64 to vfd=%lld, fd=%d, data=0x%llX = %lld\n " ,
927
- regs.rdi , fd, regs.rsi , regs.rax );
928
- cpu.set_registers (regs);
929
- });
930
- Machine::install_syscall_handler (
931
- 257 , [] (vCPU& cpu) { // OPENAT
932
- auto & regs = cpu.registers ();
933
-
934
- const auto vpath = regs.rsi ;
935
- const int flags = regs.rdx ;
936
-
937
- std::string path = cpu.machine ().memcstring (vpath, PATH_MAX);
938
- bool write_flags = (flags & (O_WRONLY | O_RDWR)) != 0x0 ;
939
- if (!write_flags)
940
- {
941
- try {
942
- std::string real_path = path;
943
- if (!cpu.machine ().fds ().is_readable_path (real_path)) {
944
- throw std::runtime_error (" Path not readable: " + real_path);
945
- }
946
-
947
- int fd = openat (AT_FDCWD, real_path.c_str (), flags);
948
- if (fd > 0 ) {
949
- regs.rax = cpu.machine ().fds ().manage (fd, false );
950
- } else {
951
- regs.rax = -1 ;
952
- }
953
- SYSPRINT (" OPENAT fd=%lld path=%s (real_path=%s) = %d (%lld)\n " ,
954
- regs.rdi , path.c_str (), real_path.c_str (), fd, regs.rax );
955
- cpu.set_registers (regs);
956
- return ;
957
- } catch (...) {
958
- SYSPRINT (" OPENAT fd=%lld path=%s flags=%X = %d\n " ,
959
- regs.rdi , path.c_str (), flags, -1 );
960
- regs.rax = -1 ;
961
- }
962
- }
963
- if (write_flags || regs.rax == (__u64)-1 )
964
- {
965
- try {
966
- std::string real_path = path;
967
- if (!cpu.machine ().fds ().is_writable_path (real_path)) {
968
- throw std::runtime_error (" Path not writable: " + real_path);
969
- }
970
-
971
- int fd = openat (AT_FDCWD, real_path.c_str (), flags, S_IWUSR | S_IRUSR);
972
- SYSPRINT (" OPENAT where=%lld path=%s (real_path=%s) flags=%X = fd %d\n " ,
973
- regs.rdi , path.c_str (), real_path.c_str (), flags, fd);
974
-
975
- if (fd > 0 ) {
976
- regs.rax = cpu.machine ().fds ().manage (fd, false );
977
- } else {
978
- regs.rax = -1 ;
979
- }
980
- } catch (...) {
981
- regs.rax = -1 ;
982
- }
983
- }
984
- cpu.set_registers (regs);
985
- });
986
- Machine::install_syscall_handler (
987
- 262 , [] (vCPU& cpu) { // NEWFSTATAT
988
- auto & regs = cpu.registers ();
989
- const auto vpath = regs.rsi ;
990
- const auto buffer = regs.rdx ;
991
- const int flags = regs.r8 ;
992
- long fd = AT_FDCWD;
993
- std::string path;
994
-
995
- try {
996
- path = cpu.machine ().memcstring (vpath, PATH_MAX);
997
-
998
- if (regs.rdi != AT_FDCWD) {
999
- // Use existing vfd
1000
- fd = cpu.machine ().fds ().translate (regs.rdi );
1001
-
1002
- struct stat64 vstat;
1003
- // We don't use path here, as a security measure
1004
- regs.rax = fstatat64 (fd, " " , &vstat, flags);
1005
- if (regs.rax == 0 ) {
1006
- cpu.machine ().copy_to_guest (buffer, &vstat, sizeof (vstat));
1007
- }
1008
- } else {
1009
- if (!cpu.machine ().fds ().is_readable_path (path)) {
1010
- regs.rax = -EPERM;
1011
- } else {
1012
- // Translate from vfd when fd != CWD
1013
- if ((long )regs.rdi != fd) fd = cpu.machine ().fds ().translate (regs.rdi );
1014
-
1015
- struct stat64 vstat;
1016
- // Path is sanitized, so we can use it
1017
- regs.rax = fstatat64 (fd, path.c_str (), &vstat, flags);
1018
- if (regs.rax == 0 ) {
1019
- cpu.machine ().copy_to_guest (buffer, &vstat, sizeof (vstat));
1020
- }
1021
- }
1022
- }
1023
- } catch (...) {
1024
- regs.rax = -1 ;
1025
- }
1026
-
1027
- SYSPRINT (" NEWFSTATAT to vfd=%lld, fd=%ld, path=%s, data=0x%llX, flags=0x%X = %lld\n " ,
1028
- regs.rdi , fd, path.c_str (), buffer, flags, regs.rax );
1029
- cpu.set_registers (regs);
1030
- });
1031
1020
Machine::install_syscall_handler (
1032
1021
332 , [] (vCPU& cpu) { // STATX
1033
1022
auto & regs = cpu.registers ();
@@ -1061,6 +1050,17 @@ void Machine::setup_linux_system_calls()
1061
1050
regs.rdi , fd, path.c_str (), buffer, flags, mask, regs.rax );
1062
1051
cpu.set_registers (regs);
1063
1052
});
1053
+ Machine::install_syscall_handler (
1054
+ 334 , [](vCPU& cpu) { // faccessat
1055
+ auto & regs = cpu.registers ();
1056
+ regs.rax = -ENOSYS;
1057
+ SYSPRINT (" faccessat(...) = %lld\n " ,
1058
+ regs.rax );
1059
+ cpu.set_registers (regs);
1060
+ });
1061
+
1062
+ // Threads: clone, futex, block/tkill etc.
1063
+ Machine::setup_multithreading ();
1064
1064
}
1065
1065
1066
1066
} // tinykvm
0 commit comments