def do_renameat(self, debugger: Debugger) -> bool: old_path, old_path_error = self.read_path('renameat', debugger, debugger.uarg1) if old_path_error is not None: return old_path_error new_path, new_path_error = self.read_path('renameat', debugger, debugger.uarg3) if new_path_error is not None: return new_path_error if not self._file_access_check(old_path, debugger, is_write=True, is_open=False, dirfd=debugger.uarg0): return ACCESS_EPERM(debugger) if not self._file_access_check(new_path, debugger, is_write=True, is_open=False, dirfd=debugger.uarg2): return ACCESS_EPERM(debugger) return True
def do_utimensat(self, debugger: AdvancedDebugger) -> bool: timespec = struct.Struct({32: '=ii', 64: '=QQ'}[debugger.address_bits]) # Emulate https://github.com/torvalds/linux/blob/v5.14/fs/utimes.c#L152-L161 times_ptr = debugger.uarg2 if times_ptr: try: buffer = debugger.readbytes(times_ptr, timespec.size * 2) except OSError: return ACCESS_EFAULT(debugger) times = list(timespec.iter_unpack(buffer)) if times[0][1] == UTIME_OMIT and times[1][1] == UTIME_OMIT: debugger.syscall = -1 def on_return(): debugger.result = 0 debugger.on_return(on_return) return True # Emulate https://github.com/torvalds/linux/blob/v5.14/fs/utimes.c#L142-L143 if debugger.uarg0 != AT_FDCWD and not debugger.uarg1: path = self._getfd_pid(debugger.tid, debugger.uarg0) return True if self.write_fs_jail.check(path) else ACCESS_EPERM( debugger) return self.check_file_access_at('utimensat')(debugger)
def do_prlimit(self, debugger): return True if debugger.uarg0 in ( 0, debugger.pid) else ACCESS_EPERM(debugger)
def do_kill(self, debugger): # Allow tgkill to execute as long as the target thread group is the debugged process # libstdc++ seems to use this to signal itself, see <https://github.com/DMOJ/judge/issues/183> return True if debugger.uarg0 == debugger.pid else ACCESS_EPERM( debugger)
def do_fchmod(self, debugger: Debugger) -> bool: path = self._getfd_pid(debugger.tid, debugger.uarg0) return True if self.write_fs_jail.check(path) else ACCESS_EPERM( debugger)