mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:27:43 +00:00
ptrace: Report error in PT_PEEK via errno
The syscall wrapper for ptrace needs to return the peeked value when using PT_PEEK. Because of this, the user has to check errno to detect an error in PT_PEEK. This commit changes the actual syscall's interface (only for PT_PEEK) to allow the syscall wrapper to detect an error and change errno.
This commit is contained in:
parent
aae3f7b914
commit
50fd2cabff
3 changed files with 47 additions and 3 deletions
|
@ -92,8 +92,10 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P
|
||||||
|
|
||||||
auto& peer_saved_registers = peer->get_register_dump_from_stack();
|
auto& peer_saved_registers = peer->get_register_dump_from_stack();
|
||||||
// Verify that the saved registers are in usermode context
|
// Verify that the saved registers are in usermode context
|
||||||
if ((peer_saved_registers.cs & 0x03) != 3)
|
if ((peer_saved_registers.cs & 0x03) != 3) {
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
SmapDisabler disabler;
|
SmapDisabler disabler;
|
||||||
PtraceRegisters* regs = reinterpret_cast<PtraceRegisters*>(params.addr);
|
PtraceRegisters* regs = reinterpret_cast<PtraceRegisters*>(params.addr);
|
||||||
|
@ -104,12 +106,24 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P
|
||||||
}
|
}
|
||||||
|
|
||||||
case PT_PEEK: {
|
case PT_PEEK: {
|
||||||
u32* addr = reinterpret_cast<u32*>(params.addr);
|
Kernel::Syscall::SC_ptrace_peek_params peek_params;
|
||||||
return peer->process().peek_user_data(addr);
|
if (!caller.validate_read_and_copy_typed(&peek_params, reinterpret_cast<Kernel::Syscall::SC_ptrace_peek_params*>(params.addr)))
|
||||||
|
return -EFAULT;
|
||||||
|
// read validation is done inside 'peek_user_data'
|
||||||
|
auto result = peer->process().peek_user_data(peek_params.address);
|
||||||
|
if (result.is_error())
|
||||||
|
return -EFAULT;
|
||||||
|
peer->process().validate_write(peek_params.out_data, sizeof(u32));
|
||||||
|
{
|
||||||
|
SmapDisabler disabler;
|
||||||
|
*(peek_params.out_data) = result.value();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PT_POKE: {
|
case PT_POKE: {
|
||||||
u32* addr = reinterpret_cast<u32*>(params.addr);
|
u32* addr = reinterpret_cast<u32*>(params.addr);
|
||||||
|
// write validation is done inside 'poke_user_data'
|
||||||
return peer->process().poke_user_data(addr, params.data);
|
return peer->process().poke_user_data(addr, params.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -432,6 +432,11 @@ struct SC_ptrace_params {
|
||||||
int data;
|
int data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SC_ptrace_peek_params {
|
||||||
|
u32* address;
|
||||||
|
u32* out_data;
|
||||||
|
};
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
int sync();
|
int sync();
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/LogStream.h>
|
||||||
#include <Kernel/Syscall.h>
|
#include <Kernel/Syscall.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
@ -32,6 +33,20 @@ extern "C" {
|
||||||
|
|
||||||
int ptrace(int request, pid_t pid, void* addr, int data)
|
int ptrace(int request, pid_t pid, void* addr, int data)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// PT_PEEK needs special handling since the syscall wrapper
|
||||||
|
// returns the peeked value as an int, which can be negative because of the cast.
|
||||||
|
// When using PT_PEEK, the user can check if an error occured
|
||||||
|
// by looking at errno rather than the return value.
|
||||||
|
|
||||||
|
u32 out_data;
|
||||||
|
Syscall::SC_ptrace_peek_params peek_params;
|
||||||
|
if (request == PT_PEEK) {
|
||||||
|
peek_params.address = reinterpret_cast<u32*>(addr);
|
||||||
|
peek_params.out_data = &out_data;
|
||||||
|
addr = &peek_params;
|
||||||
|
}
|
||||||
|
|
||||||
Syscall::SC_ptrace_params params {
|
Syscall::SC_ptrace_params params {
|
||||||
request,
|
request,
|
||||||
pid,
|
pid,
|
||||||
|
@ -39,6 +54,16 @@ int ptrace(int request, pid_t pid, void* addr, int data)
|
||||||
data
|
data
|
||||||
};
|
};
|
||||||
int rc = syscall(SC_ptrace, ¶ms);
|
int rc = syscall(SC_ptrace, ¶ms);
|
||||||
|
|
||||||
|
if (request == PT_PEEK) {
|
||||||
|
if (rc < 0) {
|
||||||
|
errno = -rc;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
return static_cast<int>(out_data);
|
||||||
|
}
|
||||||
|
|
||||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue