OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [kernel/] [ptrace.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/kernel/ptrace.c
3
 *
4
 * (C) Copyright 1999 Linus Torvalds
5
 *
6
 * Common interfaces for "ptrace()" which we do not want
7
 * to continually duplicate across every architecture.
8
 */
9
 
10
#include <linux/sched.h>
11
#include <linux/errno.h>
12
#include <linux/mm.h>
13
#include <linux/highmem.h>
14
#include <linux/smp_lock.h>
15
 
16
#include <asm/pgtable.h>
17
#include <asm/uaccess.h>
18
 
19
/*
20
 * Check that we have indeed attached to the thing..
21
 */
22
int ptrace_check_attach(struct task_struct *child, int kill)
23
{
24
 
25
        if (!(child->ptrace & PT_PTRACED))
26
                return -ESRCH;
27
 
28
        if (child->p_pptr != current)
29
                return -ESRCH;
30
 
31
        if (!kill) {
32
                if (child->state != TASK_STOPPED)
33
                        return -ESRCH;
34
#ifdef CONFIG_SMP
35
                /* Make sure the child gets off its CPU.. */
36
                for (;;) {
37
                        task_lock(child);
38
                        if (!task_has_cpu(child))
39
                                break;
40
                        task_unlock(child);
41
                        do {
42
                                if (child->state != TASK_STOPPED)
43
                                        return -ESRCH;
44
                                barrier();
45
                                cpu_relax();
46
                        } while (task_has_cpu(child));
47
                }
48
                task_unlock(child);
49
#endif          
50
        }
51
 
52
        /* All systems go.. */
53
        return 0;
54
}
55
 
56
int ptrace_attach(struct task_struct *task)
57
{
58
        task_lock(task);
59
        if (task->pid <= 1)
60
                goto bad;
61
        if (task == current)
62
                goto bad;
63
        if (!task->mm)
64
                goto bad;
65
        if(((current->uid != task->euid) ||
66
            (current->uid != task->suid) ||
67
            (current->uid != task->uid) ||
68
            (current->gid != task->egid) ||
69
            (current->gid != task->sgid) ||
70
            (!cap_issubset(task->cap_permitted, current->cap_permitted)) ||
71
            (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
72
                goto bad;
73
        rmb();
74
        if (!is_dumpable(task) && !capable(CAP_SYS_PTRACE))
75
                goto bad;
76
        /* the same process cannot be attached many times */
77
        if (task->ptrace & PT_PTRACED)
78
                goto bad;
79
 
80
        /* Go */
81
        task->ptrace |= PT_PTRACED;
82
        if (capable(CAP_SYS_PTRACE))
83
                task->ptrace |= PT_PTRACE_CAP;
84
        task_unlock(task);
85
 
86
        write_lock_irq(&tasklist_lock);
87
        if (task->p_pptr != current) {
88
                REMOVE_LINKS(task);
89
                task->p_pptr = current;
90
                SET_LINKS(task);
91
        }
92
        write_unlock_irq(&tasklist_lock);
93
 
94
        send_sig(SIGSTOP, task, 1);
95
        return 0;
96
 
97
bad:
98
        task_unlock(task);
99
        return -EPERM;
100
}
101
 
102
int ptrace_detach(struct task_struct *child, unsigned int data)
103
{
104
        if ((unsigned long) data > _NSIG)
105
                return  -EIO;
106
 
107
        /* Architecture-specific hardware disable .. */
108
        ptrace_disable(child);
109
 
110
        /* .. re-parent .. */
111
        child->ptrace = 0;
112
        child->exit_code = data;
113
        write_lock_irq(&tasklist_lock);
114
        REMOVE_LINKS(child);
115
        child->p_pptr = child->p_opptr;
116
        SET_LINKS(child);
117
        write_unlock_irq(&tasklist_lock);
118
 
119
        /* .. and wake it up. */
120
        wake_up_process(child);
121
        return 0;
122
}
123
 
124
/*
125
 * Access another process' address space.
126
 * Source/target buffer must be kernel space,
127
 * Do not walk the page table directly, use get_user_pages
128
 */
129
 
130
int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
131
{
132
        struct mm_struct *mm;
133
        struct vm_area_struct *vma;
134
        struct page *page;
135
        void *old_buf = buf;
136
 
137
        /* Worry about races with exit() */
138
        task_lock(tsk);
139
        mm = tsk->mm;
140
        if (mm)
141
                atomic_inc(&mm->mm_users);
142
        task_unlock(tsk);
143
        if (!mm)
144
                return 0;
145
 
146
        down_read(&mm->mmap_sem);
147
        /* ignore errors, just check how much was sucessfully transfered */
148
        while (len) {
149
                int bytes, ret, offset;
150
                void *maddr;
151
 
152
                ret = get_user_pages(current, mm, addr, 1,
153
                                write, 1, &page, &vma);
154
                if (ret <= 0)
155
                        break;
156
 
157
                bytes = len;
158
                offset = addr & (PAGE_SIZE-1);
159
                if (bytes > PAGE_SIZE-offset)
160
                        bytes = PAGE_SIZE-offset;
161
 
162
                flush_cache_page(vma, addr);
163
 
164
                maddr = kmap(page);
165
                if (write) {
166
                        memcpy(maddr + offset, buf, bytes);
167
                        flush_page_to_ram(page);
168
                        flush_icache_user_range(vma, page, addr, len);
169
                        set_page_dirty(page);
170
                } else {
171
                        memcpy(buf, maddr + offset, bytes);
172
                        flush_page_to_ram(page);
173
                }
174
                kunmap(page);
175
                put_page(page);
176
                len -= bytes;
177
                buf += bytes;
178
                addr += bytes;
179
        }
180
        up_read(&mm->mmap_sem);
181
        mmput(mm);
182
 
183
        return buf - old_buf;
184
}
185
 
186
int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len)
187
{
188
        int copied = 0;
189
 
190
        while (len > 0) {
191
                char buf[128];
192
                int this_len, retval;
193
 
194
                this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
195
                retval = access_process_vm(tsk, src, buf, this_len, 0);
196
                if (!retval) {
197
                        if (copied)
198
                                break;
199
                        return -EIO;
200
                }
201
                if (copy_to_user(dst, buf, retval))
202
                        return -EFAULT;
203
                copied += retval;
204
                src += retval;
205
                dst += retval;
206
                len -= retval;
207
        }
208
        return copied;
209
}
210
 
211
int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int len)
212
{
213
        int copied = 0;
214
 
215
        while (len > 0) {
216
                char buf[128];
217
                int this_len, retval;
218
 
219
                this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
220
                if (copy_from_user(buf, src, this_len))
221
                        return -EFAULT;
222
                retval = access_process_vm(tsk, dst, buf, this_len, 1);
223
                if (!retval) {
224
                        if (copied)
225
                                break;
226
                        return -EIO;
227
                }
228
                copied += retval;
229
                src += retval;
230
                dst += retval;
231
                len -= retval;
232
        }
233
        return copied;
234
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.