Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
K
kernel
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
redox-os
kernel
Commits
0e2b0d0f
Verified
Commit
0e2b0d0f
authored
5 years ago
by
jD91mZM2
Browse files
Options
Downloads
Patches
Plain Diff
Fix a few details
parent
3ac1416d
No related branches found
No related tags found
1 merge request
!107
Ptrace overhaul & bitflags
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
src/arch/x86_64/interrupt/syscall.rs
+5
-4
5 additions, 4 deletions
src/arch/x86_64/interrupt/syscall.rs
src/ptrace.rs
+13
-6
13 additions, 6 deletions
src/ptrace.rs
src/scheme/proc.rs
+66
-53
66 additions, 53 deletions
src/scheme/proc.rs
syscall
+1
-1
1 addition, 1 deletion
syscall
with
85 additions
and
64 deletions
src/arch/x86_64/interrupt/syscall.rs
+
5
−
4
View file @
0e2b0d0f
...
...
@@ -22,15 +22,16 @@ macro_rules! with_interrupt_stack {
unsafe
fn
$wrapped
(
stack
:
*
mut
InterruptStack
)
{
let
_guard
=
ptrace
::
set_process_regs
(
stack
);
ptrace
::
breakpoint_callback
(
PTRACE_STOP_PRE_SYSCALL
,
None
);
let
not_sysemu
=
ptrace
::
next_breakpoint
()
.map
(|
b
|
b
&
PTRACE_FLAG_SYSEMU
!=
PTRACE_FLAG_SYSEMU
);
let
not_sysemu
=
ptrace
::
breakpoint_callback
(
PTRACE_STOP_PRE_SYSCALL
,
None
)
.and_then
(|
_
|
ptrace
::
next_breakpoint
()
.map
(|
b
|
b
&
PTRACE_FLAG_SYSEMU
!=
PTRACE_FLAG_SYSEMU
));
if
not_sysemu
.unwrap_or
(
true
)
{
// If not on a sysemu breakpoint
let
$stack
=
&
mut
*
stack
;
$stack
.scratch.rax
=
$code
;
ptrace
::
breakpoint_callback
(
PTRACE_STOP_POST_SYSCALL
,
None
);
}
ptrace
::
breakpoint_callback
(
PTRACE_STOP_POST_SYSCALL
,
None
);
}
}
}
...
...
This diff is collapsed.
Click to expand it.
src/ptrace.rs
+
13
−
6
View file @
0e2b0d0f
...
...
@@ -133,6 +133,11 @@ pub fn send_event(event: PtraceEvent) -> Option<()> {
let
mut
sessions
=
sessions_mut
();
let
session
=
sessions
.get_mut
(
&
context
.id
)
?
;
let
breakpoint
=
session
.breakpoint
.as_ref
()
?
;
if
event
.cause
&
breakpoint
.flags
!=
event
.cause
{
return
None
;
}
session
.events
.push_back
(
event
);
...
...
@@ -209,8 +214,8 @@ pub fn wait(pid: ContextId) -> Result<Option<PtraceEvent>> {
let
sessions
=
sessions
();
match
sessions
.get
(
&
pid
)
{
Some
(
session
)
if
session
.breakpoint
.as_ref
()
.map
(|
b
|
!
b
.reached
)
.unwrap_or
(
true
)
=>
{
if
let
Some
(
event
)
=
session
.events
.
front
()
{
return
Ok
(
Some
(
event
.clone
())
);
if
!
session
.events
.
is_empty
()
{
return
Ok
(
None
);
}
Arc
::
clone
(
&
session
.tracer
)
},
...
...
@@ -252,21 +257,23 @@ pub fn breakpoint_callback(match_flags: u64, event: Option<PtraceEvent>) -> Opti
let
session
=
sessions
.get_mut
(
&
context
.id
)
?
;
let
breakpoint
=
session
.breakpoint
.as_mut
()
?
;
// TODO: How should singlesteps interact with syscalls? How
// does Linux handle this?
if
breakpoint
.flags
&
match_flags
!=
match_flags
{
return
None
;
}
session
.events
.push_back
(
event
.unwrap_or
(
ptrace_event!
(
match_flags
)));
// Notify nonblocking tracers
if
session
.events
.len
()
==
1
{
// If the list of events was previously empty, alert now
proc_trigger_event
(
session
.file_id
,
EVENT_READ
);
}
// In case no tracer is waiting, make sure the next one gets
// the memo
breakpoint
.reached
=
true
;
session
.tracer
.notify
();
proc_trigger_event
(
session
.file_id
,
EVENT_WRITE
);
(
Arc
::
clone
(
&
session
.tracee
),
...
...
This diff is collapsed.
Click to expand it.
src/scheme/proc.rs
+
66
−
53
View file @
0e2b0d0f
...
...
@@ -15,13 +15,14 @@ use crate::{
use
alloc
::{
collections
::
BTreeMap
,
sync
::
Arc
sync
::
Arc
,
vec
::
Vec
};
use
core
::{
cmp
,
mem
,
slice
,
sync
::
atomic
::{
AtomicUsize
,
Ordering
}
sync
::
atomic
::{
AtomicUsize
,
Ordering
}
,
};
use
spin
::{
Mutex
,
RwLock
};
...
...
@@ -30,12 +31,12 @@ enum RegsKind {
Float
,
Int
}
#[derive(Clone
,
Copy
)]
#[derive(Clone)]
enum
Operation
{
Memory
(
VirtualAddress
),
Regs
(
RegsKind
),
Trace
{
new_child
:
Option
<
ContextId
>
clones
:
Vec
<
ContextId
>
}
}
...
...
@@ -101,24 +102,30 @@ fn try_stop_context<F, T>(pid: ContextId, restart_after: bool, mut callback: F)
}
#[derive(Clone,
Copy)]
struct
Handle
{
flags
:
usize
,
struct
Info
{
pid
:
ContextId
,
flags
:
usize
,
}
struct
Handle
{
info
:
Info
,
operation
:
Operation
}
impl
Handle
{
fn
continue_ignored_child
(
&
mut
self
)
->
Option
<
()
>
{
let
pid
=
match
self
.operation
{
Operation
::
Trace
{
ref
mut
new_child
}
=>
new_child
.take
()
?
,
fn
continue_ignored_child
ren
(
&
mut
self
)
->
Option
<
()
>
{
let
clones
=
match
self
.operation
{
Operation
::
Trace
{
ref
mut
clones
}
=>
clones
,
_
=>
return
None
};
if
ptrace
::
is_traced
(
pid
)
{
return
None
;
}
let
contexts
=
context
::
contexts
();
let
context
=
contexts
.get
(
pid
)
?
;
let
mut
context
=
context
.write
();
context
.ptrace_stop
=
false
;
for
pid
in
clones
.drain
(
..
)
{
if
ptrace
::
is_traced
(
pid
)
{
return
None
;
}
if
let
Some
(
context
)
=
contexts
.get
(
pid
)
{
let
mut
context
=
context
.write
();
context
.ptrace_stop
=
false
;
}
}
Some
(())
}
}
...
...
@@ -154,7 +161,7 @@ impl Scheme for ProcScheme {
Some
(
"regs/float"
)
=>
Operation
::
Regs
(
RegsKind
::
Float
),
Some
(
"regs/int"
)
=>
Operation
::
Regs
(
RegsKind
::
Int
),
Some
(
"trace"
)
=>
Operation
::
Trace
{
new_child
:
None
clones
:
Vec
::
new
()
},
_
=>
return
Err
(
Error
::
new
(
EINVAL
))
};
...
...
@@ -209,9 +216,11 @@ impl Scheme for ProcScheme {
}
self
.handles
.write
()
.insert
(
id
,
Arc
::
new
(
Mutex
::
new
(
Handle
{
flags
,
pid
,
operation
info
:
Info
{
flags
,
pid
,
},
operation
,
})));
Ok
(
id
)
}
...
...
@@ -224,14 +233,14 @@ impl Scheme for ProcScheme {
/// let regs = syscall::dup(trace, "regs/int")?;
/// ```
fn
dup
(
&
self
,
old_id
:
usize
,
buf
:
&
[
u8
])
->
Result
<
usize
>
{
let
handle
=
{
let
info
=
{
let
handles
=
self
.handles
.read
();
let
handle
=
handles
.get
(
&
old_id
)
.ok_or
(
Error
::
new
(
EBADF
))
?
;
let
handle
=
handle
.lock
();
*
handle
handle
.info
};
let
mut
path
=
format!
(
"{}/"
,
handle
.pid
.into
())
.into_bytes
();
let
mut
path
=
format!
(
"{}/"
,
info
.pid
.into
())
.into_bytes
();
path
.extend_from_slice
(
buf
);
let
(
uid
,
gid
)
=
{
...
...
@@ -241,7 +250,7 @@ impl Scheme for ProcScheme {
(
context
.euid
,
context
.egid
)
};
self
.open
(
&
path
,
handle
.flags
,
uid
,
gid
)
self
.open
(
&
path
,
info
.flags
,
uid
,
gid
)
}
fn
seek
(
&
self
,
id
:
usize
,
pos
:
usize
,
whence
:
usize
)
->
Result
<
usize
>
{
...
...
@@ -269,14 +278,13 @@ impl Scheme for ProcScheme {
let
handles
=
self
.handles
.read
();
Arc
::
clone
(
handles
.get
(
&
id
)
.ok_or
(
Error
::
new
(
EBADF
))
?
)
};
// TODO: Make sure handle can't deadlock
let
mut
handle
=
handle
.lock
();
let
pid
=
handle
.
pid
;
let
info
=
handle
.
info
;
match
handle
.operation
{
Operation
::
Memory
(
ref
mut
offset
)
=>
{
let
contexts
=
context
::
contexts
();
let
context
=
contexts
.get
(
pid
)
.ok_or
(
Error
::
new
(
ESRCH
))
?
;
let
context
=
contexts
.get
(
info
.
pid
)
.ok_or
(
Error
::
new
(
ESRCH
))
?
;
let
context
=
context
.read
();
ptrace
::
with_context_memory
(
&
context
,
*
offset
,
buf
.len
(),
|
ptr
|
{
...
...
@@ -294,7 +302,7 @@ impl Scheme for ProcScheme {
}
let
(
output
,
size
)
=
match
kind
{
RegsKind
::
Float
=>
with_context
(
handle
.pid
,
|
context
|
{
RegsKind
::
Float
=>
with_context
(
info
.pid
,
|
context
|
{
// NOTE: The kernel will never touch floats
// In the rare case of not having floating
...
...
@@ -303,7 +311,7 @@ impl Scheme for ProcScheme {
let
fx
=
context
.arch
.get_fx_regs
()
.unwrap_or_default
();
Ok
((
Output
{
float
:
fx
},
mem
::
size_of
::
<
FloatRegisters
>
()))
})
?
,
RegsKind
::
Int
=>
try_stop_context
(
handle
.pid
,
true
,
|
context
|
match
unsafe
{
ptrace
::
regs_for
(
&
context
)
}
{
RegsKind
::
Int
=>
try_stop_context
(
info
.pid
,
true
,
|
context
|
match
unsafe
{
ptrace
::
regs_for
(
&
context
)
}
{
None
=>
{
println!
(
"{}:{}: Couldn't read registers from stopped process"
,
file!
(),
line!
());
Err
(
Error
::
new
(
ENOTRECOVERABLE
))
...
...
@@ -325,7 +333,7 @@ impl Scheme for ProcScheme {
Ok
(
len
)
},
Operation
::
Trace
{
..
}
=>
{
let
read
=
ptrace
::
recv_events
(
handle
.pid
,
unsafe
{
let
read
=
ptrace
::
recv_events
(
info
.pid
,
unsafe
{
slice
::
from_raw_parts_mut
(
buf
.as_mut_ptr
()
as
*
mut
PtraceEvent
,
buf
.len
()
/
mem
::
size_of
::
<
PtraceEvent
>
()
...
...
@@ -344,16 +352,13 @@ impl Scheme for ProcScheme {
Arc
::
clone
(
handles
.get
(
&
id
)
.ok_or
(
Error
::
new
(
EBADF
))
?
)
};
let
mut
handle
=
handle
.lock
();
handle
.continue_ignored_child
();
// Some operations borrow Operation:: mutably
let
pid
=
handle
.pid
;
let
flags
=
handle
.flags
;
let
info
=
handle
.info
;
handle
.continue_ignored_children
();
match
handle
.operation
{
Operation
::
Memory
(
ref
mut
offset
)
=>
{
let
contexts
=
context
::
contexts
();
let
context
=
contexts
.get
(
pid
)
.ok_or
(
Error
::
new
(
ESRCH
))
?
;
let
context
=
contexts
.get
(
info
.
pid
)
.ok_or
(
Error
::
new
(
ESRCH
))
?
;
let
context
=
context
.read
();
ptrace
::
with_context_memory
(
&
context
,
*
offset
,
buf
.len
(),
|
ptr
|
{
...
...
@@ -373,7 +378,7 @@ impl Scheme for ProcScheme {
*
(
buf
as
*
const
_
as
*
const
FloatRegisters
)
};
with_context_mut
(
pid
,
|
context
|
{
with_context_mut
(
info
.
pid
,
|
context
|
{
// NOTE: The kernel will never touch floats
// Ignore the rare case of floating point
...
...
@@ -391,7 +396,7 @@ impl Scheme for ProcScheme {
*
(
buf
as
*
const
_
as
*
const
IntRegisters
)
};
try_stop_context
(
handle
.pid
,
true
,
|
context
|
match
unsafe
{
ptrace
::
regs_for_mut
(
context
)
}
{
try_stop_context
(
info
.pid
,
true
,
|
context
|
match
unsafe
{
ptrace
::
regs_for_mut
(
context
)
}
{
None
=>
{
println!
(
"{}:{}: Couldn't read registers from stopped process"
,
file!
(),
line!
());
Err
(
Error
::
new
(
ENOTRECOVERABLE
))
...
...
@@ -404,7 +409,7 @@ impl Scheme for ProcScheme {
})
}
},
Operation
::
Trace
{
ref
mut
new_child
}
=>
{
Operation
::
Trace
{
ref
mut
clones
}
=>
{
if
buf
.len
()
<
mem
::
size_of
::
<
u64
>
()
{
return
Ok
(
0
);
}
...
...
@@ -415,14 +420,16 @@ impl Scheme for ProcScheme {
let
op
=
u64
::
from_ne_bytes
(
bytes
);
if
op
&
PTRACE_FLAG_WAIT
!=
PTRACE_FLAG_WAIT
||
op
&
PTRACE_STOP_MASK
!=
0
{
ptrace
::
cont
(
pid
);
ptrace
::
cont
(
info
.
pid
);
}
if
op
&
PTRACE_STOP_MASK
!=
0
{
ptrace
::
set_breakpoint
(
pid
,
op
);
ptrace
::
set_breakpoint
(
info
.
pid
,
op
);
}
if
op
&
PTRACE_STOP_SINGLESTEP
==
PTRACE_STOP_SINGLESTEP
{
try_stop_context
(
pid
,
false
,
|
context
|
{
// try_stop_context with `false` will
// automatically disable ptrace_stop
try_stop_context
(
info
.pid
,
false
,
|
context
|
{
match
unsafe
{
ptrace
::
regs_for_mut
(
context
)
}
{
// If another CPU is running this process,
// await for it to be stopped and in such
...
...
@@ -437,12 +444,18 @@ impl Scheme for ProcScheme {
}
}
})
?
;
}
else
{
// disable ptrace stop
with_context_mut
(
info
.pid
,
|
context
|
{
context
.ptrace_stop
=
false
;
Ok
(())
})
?
;
}
if
op
&
PTRACE_FLAG_WAIT
==
PTRACE_FLAG_WAIT
||
flags
&
O_NONBLOCK
!=
O_NONBLOCK
{
if
let
Some
(
event
)
=
ptrace
::
wait
(
pid
)
?
{
if
op
&
PTRACE_FLAG_WAIT
==
PTRACE_FLAG_WAIT
||
info
.
flags
&
O_NONBLOCK
!=
O_NONBLOCK
{
if
let
Some
(
event
)
=
ptrace
::
wait
(
info
.
pid
)
?
{
if
event
.cause
==
PTRACE_EVENT_CLONE
{
*
new_child
=
Some
(
ContextId
::
from
(
event
.a
));
clones
.push
(
ContextId
::
from
(
event
.a
));
}
}
}
...
...
@@ -458,8 +471,8 @@ impl Scheme for ProcScheme {
let
mut
handle
=
handle
.lock
();
match
cmd
{
F_SETFL
=>
{
handle
.flags
=
arg
;
Ok
(
0
)
},
F_GETFL
=>
return
Ok
(
handle
.flags
),
F_SETFL
=>
{
handle
.
info.
flags
=
arg
;
Ok
(
0
)
},
F_GETFL
=>
return
Ok
(
handle
.
info.
flags
),
_
=>
return
Err
(
Error
::
new
(
EINVAL
))
}
}
...
...
@@ -469,7 +482,7 @@ impl Scheme for ProcScheme {
let
handle
=
handles
.get
(
&
id
)
.ok_or
(
Error
::
new
(
EBADF
))
?
;
let
handle
=
handle
.lock
();
Ok
(
ptrace
::
session_fevent_flags
(
handle
.pid
)
.expect
(
"proc (fevent): invalid session"
))
Ok
(
ptrace
::
session_fevent_flags
(
handle
.
info.
pid
)
.expect
(
"proc (fevent): invalid session"
))
}
fn
fpath
(
&
self
,
id
:
usize
,
buf
:
&
mut
[
u8
])
->
Result
<
usize
>
{
...
...
@@ -477,7 +490,7 @@ impl Scheme for ProcScheme {
let
handle
=
handles
.get
(
&
id
)
.ok_or
(
Error
::
new
(
EBADF
))
?
;
let
handle
=
handle
.lock
();
let
path
=
format!
(
"proc:{}/{}"
,
handle
.pid
.into
(),
match
handle
.operation
{
let
path
=
format!
(
"proc:{}/{}"
,
handle
.
info.
pid
.into
(),
match
handle
.operation
{
Operation
::
Memory
(
_
)
=>
"mem"
,
Operation
::
Regs
(
RegsKind
::
Float
)
=>
"regs/float"
,
Operation
::
Regs
(
RegsKind
::
Int
)
=>
"regs/int"
,
...
...
@@ -493,16 +506,16 @@ impl Scheme for ProcScheme {
fn
close
(
&
self
,
id
:
usize
)
->
Result
<
usize
>
{
let
handle
=
self
.handles
.write
()
.remove
(
&
id
)
.ok_or
(
Error
::
new
(
EBADF
))
?
;
let
mut
handle
=
handle
.lock
();
handle
.continue_ignored_child
();
handle
.continue_ignored_child
ren
();
if
let
Operation
::
Trace
{
..
}
=
handle
.operation
{
ptrace
::
close_session
(
handle
.pid
);
ptrace
::
close_session
(
handle
.
info.
pid
);
if
handle
.flags
&
O_EXCL
==
O_EXCL
{
syscall
::
kill
(
handle
.pid
,
SIGKILL
)
?
;
if
handle
.
info.
flags
&
O_EXCL
==
O_EXCL
{
syscall
::
kill
(
handle
.
info.
pid
,
SIGKILL
)
?
;
}
else
{
let
contexts
=
context
::
contexts
();
if
let
Some
(
context
)
=
contexts
.get
(
handle
.pid
)
{
if
let
Some
(
context
)
=
contexts
.get
(
handle
.
info.
pid
)
{
let
mut
context
=
context
.write
();
context
.ptrace_stop
=
false
;
}
...
...
This diff is collapsed.
Click to expand it.
syscall
@
edf3c008
Compare
52441c28
...
edf3c008
Subproject commit
52441c28b1daa6f9febf1bc6588b625b167bd2c3
Subproject commit
edf3c008dc0a68245a255945d9a70b02c71991a5
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment