Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
b8fc4428
Commit
b8fc4428
authored
Feb 06, 2003
by
Daniel Jacobowitz
Browse files
Options
Browse Files
Download
Plain Diff
Hand-merge with Ingo's changes
parents
3fa327f8
a866697c
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
82 additions
and
9 deletions
+82
-9
include/linux/ptrace.h
include/linux/ptrace.h
+6
-0
include/linux/sched.h
include/linux/sched.h
+3
-0
kernel/exit.c
kernel/exit.c
+27
-5
kernel/fork.c
kernel/fork.c
+4
-2
kernel/ptrace.c
kernel/ptrace.c
+35
-1
kernel/signal.c
kernel/signal.c
+7
-1
No files found.
include/linux/ptrace.h
View file @
b8fc4428
...
...
@@ -26,6 +26,8 @@
/* 0x4200-0x4300 are reserved for architecture-independent additions. */
#define PTRACE_SETOPTIONS 0x4200
#define PTRACE_GETEVENTMSG 0x4201
#define PTRACE_GETSIGINFO 0x4202
#define PTRACE_SETSIGINFO 0x4203
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
...
...
@@ -33,12 +35,16 @@
#define PTRACE_O_TRACEVFORK 0x00000004
#define PTRACE_O_TRACECLONE 0x00000008
#define PTRACE_O_TRACEEXEC 0x00000010
#define PTRACE_O_TRACEVFORKDONE 0x00000020
#define PTRACE_O_TRACEEXIT 0x00000040
/* Wait extended result codes for the above trace options. */
#define PTRACE_EVENT_FORK 1
#define PTRACE_EVENT_VFORK 2
#define PTRACE_EVENT_CLONE 3
#define PTRACE_EVENT_EXEC 4
#define PTRACE_EVENT_VFORK_DONE 5
#define PTRACE_EVENT_EXIT 6
#include <asm/ptrace.h>
#include <linux/sched.h>
...
...
include/linux/sched.h
View file @
b8fc4428
...
...
@@ -405,6 +405,7 @@ struct task_struct {
struct
backing_dev_info
*
backing_dev_info
;
unsigned
long
ptrace_message
;
siginfo_t
*
last_siginfo
;
/* For ptrace use. */
};
extern
void
__put_task_struct
(
struct
task_struct
*
tsk
);
...
...
@@ -445,6 +446,8 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
#define PT_TRACE_VFORK 0x00000020
#define PT_TRACE_CLONE 0x00000040
#define PT_TRACE_EXEC 0x00000080
#define PT_TRACE_VFORK_DONE 0x00000100
#define PT_TRACE_EXIT 0x00000200
#if CONFIG_SMP
extern
void
set_cpus_allowed
(
task_t
*
p
,
unsigned
long
new_mask
);
...
...
kernel/exit.c
View file @
b8fc4428
...
...
@@ -198,6 +198,17 @@ static inline int has_stopped_jobs(int pgrp)
for_each_task_pid
(
pgrp
,
PIDTYPE_PGID
,
p
,
l
,
pid
)
{
if
(
p
->
state
!=
TASK_STOPPED
)
continue
;
/* If p is stopped by a debugger on a signal that won't
stop it, then don't count p as stopped. This isn't
perfect but it's a good approximation. */
if
(
unlikely
(
p
->
ptrace
)
&&
p
->
exit_code
!=
SIGSTOP
&&
p
->
exit_code
!=
SIGTSTP
&&
p
->
exit_code
!=
SIGTTOU
&&
p
->
exit_code
!=
SIGTTIN
)
continue
;
retval
=
1
;
break
;
}
...
...
@@ -570,7 +581,7 @@ static void exit_notify(void)
* is about to become orphaned.
*/
t
=
current
->
parent
;
t
=
current
->
real_
parent
;
if
((
t
->
pgrp
!=
current
->
pgrp
)
&&
(
t
->
session
==
current
->
session
)
&&
...
...
@@ -603,8 +614,16 @@ static void exit_notify(void)
current
->
exit_signal
=
SIGCHLD
;
if
(
current
->
exit_signal
!=
-
1
)
do_notify_parent
(
current
,
current
->
exit_signal
);
/* If something other than our normal parent is ptracing us, then
* send it a SIGCHLD instead of honoring exit_signal. exit_signal
* only has special meaning to our real parent.
*/
if
(
current
->
exit_signal
!=
-
1
)
{
if
(
current
->
parent
==
current
->
real_parent
)
do_notify_parent
(
current
,
current
->
exit_signal
);
else
do_notify_parent
(
current
,
SIGCHLD
);
}
current
->
state
=
TASK_ZOMBIE
;
/*
...
...
@@ -637,6 +656,9 @@ NORET_TYPE void do_exit(long code)
profile_exit_task
(
tsk
);
if
(
unlikely
(
current
->
ptrace
&
PT_TRACE_EXIT
))
ptrace_notify
((
PTRACE_EVENT_EXIT
<<
8
)
|
SIGTRAP
);
fake_volatile:
acct_process
(
code
);
__exit_mm
(
tsk
);
...
...
@@ -953,10 +975,10 @@ asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struc
write_lock_irq
(
&
tasklist_lock
);
/* Double-check with lock held. */
if
(
p
->
real_parent
!=
p
->
parent
)
{
__ptrace_unlink
(
p
);
__ptrace_unlink
(
p
);
do_notify_parent
(
p
,
p
->
exit_signal
);
p
->
state
=
TASK_ZOMBIE
;
p
->
state
=
TASK_ZOMBIE
;
p
=
NULL
;
}
write_unlock_irq
(
&
tasklist_lock
);
...
...
kernel/fork.c
View file @
b8fc4428
...
...
@@ -1065,9 +1065,11 @@ struct task_struct *do_fork(unsigned long clone_flags,
ptrace_notify
((
trace
<<
8
)
|
SIGTRAP
);
}
if
(
clone_flags
&
CLONE_VFORK
)
if
(
clone_flags
&
CLONE_VFORK
)
{
wait_for_completion
(
&
vfork
);
else
if
(
unlikely
(
current
->
ptrace
&
PT_TRACE_VFORK_DONE
))
ptrace_notify
((
PTRACE_EVENT_VFORK_DONE
<<
8
)
|
SIGTRAP
);
}
else
/*
* Let the child process run first, to avoid most of the
* COW overhead when the child exec()s afterwards.
...
...
kernel/ptrace.c
View file @
b8fc4428
...
...
@@ -277,15 +277,43 @@ static int ptrace_setoptions(struct task_struct *child, long data)
else
child
->
ptrace
&=
~
PT_TRACE_EXEC
;
if
(
data
&
PTRACE_O_TRACEVFORKDONE
)
child
->
ptrace
|=
PT_TRACE_VFORK_DONE
;
else
child
->
ptrace
&=
~
PT_TRACE_VFORK_DONE
;
if
(
data
&
PTRACE_O_TRACEEXIT
)
child
->
ptrace
|=
PT_TRACE_EXIT
;
else
child
->
ptrace
&=
~
PT_TRACE_EXIT
;
if
((
data
&
(
PTRACE_O_TRACESYSGOOD
|
PTRACE_O_TRACEFORK
|
PTRACE_O_TRACEVFORK
|
PTRACE_O_TRACECLONE
|
PTRACE_O_TRACEEXEC
))
|
PTRACE_O_TRACEEXEC
|
PTRACE_O_TRACEEXIT
|
PTRACE_O_TRACEVFORKDONE
))
!=
data
)
return
-
EINVAL
;
return
0
;
}
static
int
ptrace_getsiginfo
(
struct
task_struct
*
child
,
long
data
)
{
if
(
child
->
last_siginfo
==
NULL
)
return
-
EINVAL
;
return
copy_siginfo_to_user
((
siginfo_t
*
)
data
,
child
->
last_siginfo
);
}
static
int
ptrace_setsiginfo
(
struct
task_struct
*
child
,
long
data
)
{
if
(
child
->
last_siginfo
==
NULL
)
return
-
EINVAL
;
if
(
copy_from_user
(
child
->
last_siginfo
,
(
siginfo_t
*
)
data
,
sizeof
(
siginfo_t
))
!=
0
)
return
-
EFAULT
;
return
0
;
}
int
ptrace_request
(
struct
task_struct
*
child
,
long
request
,
long
addr
,
long
data
)
{
...
...
@@ -301,6 +329,12 @@ int ptrace_request(struct task_struct *child, long request,
case
PTRACE_GETEVENTMSG
:
ret
=
put_user
(
child
->
ptrace_message
,
(
unsigned
long
*
)
data
);
break
;
case
PTRACE_GETSIGINFO
:
ret
=
ptrace_getsiginfo
(
child
,
data
);
break
;
case
PTRACE_SETSIGINFO
:
ret
=
ptrace_setsiginfo
(
child
,
data
);
break
;
default:
break
;
}
...
...
kernel/signal.c
View file @
b8fc4428
...
...
@@ -1404,17 +1404,23 @@ int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs)
/* Let the debugger run. */
current
->
exit_code
=
signr
;
current
->
last_siginfo
=
info
;
set_current_state
(
TASK_STOPPED
);
notify_parent
(
current
,
SIGCHLD
);
schedule
();
current
->
last_siginfo
=
NULL
;
/* We're back. Did the debugger cancel the sig? */
signr
=
current
->
exit_code
;
if
(
signr
==
0
)
continue
;
current
->
exit_code
=
0
;
/* Update the siginfo structure. Is this good? */
/* Update the siginfo structure if the signal has
changed. If the debugger wanted something
specific in the siginfo structure then it should
have updated *info via PTRACE_SETSIGINFO. */
if
(
signr
!=
info
->
si_signo
)
{
info
->
si_signo
=
signr
;
info
->
si_errno
=
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment