Commit 6f267f9c authored by Linus Torvalds's avatar Linus Torvalds

v2.4.6.9 -> v2.4.7

  - me: fix ptrace and /proc issues with new core-dump permissions
  - numerous: IDE tape driver update for completion handlers
  - Ben Collins: ieee1394 GUID cleanups
  - Jacek Stepniewski: nasty deadlock in rename()
parent 7b4d3039
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 7
EXTRAVERSION =-pre9
EXTRAVERSION =
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
......
......@@ -264,32 +264,7 @@ sys_ptrace(long request, long pid, long addr, long data,
if (!child)
goto out_notsk;
if (request == PTRACE_ATTACH) {
ret = -EPERM;
if (child == current)
goto out;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(current->gid != child->gid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)))
&& !capable(CAP_SYS_PTRACE))
goto out;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out;
child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irq(&tasklist_lock);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out;
}
ret = -ESRCH;
......
......@@ -594,32 +594,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out_tsk;
if (request == PTRACE_ATTACH) {
if (child == current)
goto out_tsk;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out_tsk;
child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irq(&tasklist_lock);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out_tsk;
}
ret = -ESRCH;
......
......@@ -115,32 +115,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if (pid == 1) /* you may not mess with init */
goto out_tsk;
if (request == PTRACE_ATTACH) {
if (child == current)
goto out_tsk;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out_tsk;
child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irq(&tasklist_lock);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out_tsk;
}
ret = -ESRCH;
......
......@@ -165,34 +165,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out_tsk;
if (request == PTRACE_ATTACH) {
if (child == current)
goto out_tsk;
if(((current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
rmb();
if (!child->mm->dumpable && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out_tsk;
child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irq(&tasklist_lock);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out_tsk;
}
ret = -ESRCH;
......
......@@ -768,32 +768,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data,
goto out_tsk;
if (request == PTRACE_ATTACH) {
if (child == current)
goto out_tsk;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out_tsk;
child->ptrace |= PT_PTRACED;
if (child->p_pptr != current) {
unsigned long flags;
write_lock_irqsave(&tasklist_lock, flags);
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
write_unlock_irqrestore(&tasklist_lock, flags);
}
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out_tsk;
}
ret = -ESRCH;
......
......@@ -118,32 +118,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out_tsk;
if (request == PTRACE_ATTACH) {
if (child == current)
goto out_tsk;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out_tsk;
child->ptrace |= PT_PTRACED;
write_lock_irqsave(&tasklist_lock, flags);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irqrestore(&tasklist_lock, flags);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out_tsk;
}
ret = -ESRCH;
......
......@@ -66,34 +66,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out;
if (request == PTRACE_ATTACH) {
if (child == current)
goto out_tsk;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(current->gid != child->gid) ||
(!cap_issubset(child->cap_permitted,
current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out_tsk;
child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irq(&tasklist_lock);
send_sig(SIGSTOP, child, 1);
res = 0;
res = ptrace_attach(child);
goto out_tsk;
}
res = -ESRCH;
......
......@@ -62,32 +62,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
goto out_tsk;
if (request == PTRACE_ATTACH) {
if (child == current)
goto out_tsk;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out_tsk;
child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irq(&tasklist_lock);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out_tsk;
}
ret = -ESRCH;
......@@ -336,32 +311,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out;
if (request == PTRACE_ATTACH) {
if (child == current)
goto out_tsk;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out_tsk;
child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irq(&tasklist_lock);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out_tsk;
}
ret = -ESRCH;
......
......@@ -61,32 +61,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data)
goto out_tsk;
if (request == PTRACE_ATTACH) {
if (child == current)
goto out_tsk;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out_tsk;
child->ptrace |= PT_PTRACED;
if (child->p_pptr != current) {
unsigned long flags;
write_lock_irqsave(&tasklist_lock, flags);
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
write_unlock_irqrestore(&tasklist_lock, flags);
}
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out_tsk;
}
ret = -ESRCH;
......
......@@ -118,33 +118,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
goto out_tsk;
if (request == PTRACE_ATTACH) {
if (child == current)
goto out_tsk;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid))
&& !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out_tsk;
child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irq(&tasklist_lock);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out_tsk;
}
ret = -ESRCH;
......
......@@ -233,31 +233,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out;
if (request == PTRACE_ATTACH)
{
if (child == current)
goto out;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid)) && !capable(CAP_SYS_PTRACE))
goto out;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out;
child->ptrace |= PT_PTRACED;
write_lock_irqsave(&tasklist_lock, flags);
if (child->p_pptr != current)
{
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irqrestore(&tasklist_lock, flags);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out;
}
ret = -ESRCH;
......
......@@ -247,31 +247,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out;
if (request == PTRACE_ATTACH)
{
if (child == current)
goto out;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid)) && !capable(CAP_SYS_PTRACE))
goto out;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out;
child->ptrace |= PT_PTRACED;
write_lock_irqsave(&tasklist_lock, flags);
if (child->p_pptr != current)
{
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irqrestore(&tasklist_lock, flags);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out;
}
ret = -ESRCH;
......@@ -433,31 +409,7 @@ asmlinkage int sys32_ptrace(long request, long pid, long addr, s32 data)
goto out;
if (request == PTRACE_ATTACH)
{
if (child == current)
goto out;
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid)) && !capable(CAP_SYS_PTRACE))
goto out;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out;
child->ptrace |= PT_PTRACED;
write_lock_irqsave(&tasklist_lock, flags);
if (child->p_pptr != current)
{
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irqrestore(&tasklist_lock, flags);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out;
}
ret = -ESRCH;
......
......@@ -173,34 +173,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out_tsk;
if (request == PTRACE_ATTACH) {
if (child == tsk)
goto out_tsk;
if(((tsk->uid != child->euid) ||
(tsk->uid != child->suid) ||
(tsk->uid != child->uid) ||
(tsk->gid != child->egid) ||
(tsk->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, tsk->cap_permitted)) ||
(tsk->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out_tsk;
rmb();
if (!child->mm->dumpable && !capable(CAP_SYS_PTRACE))
goto out_tsk;
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED)
goto out_tsk;
child->ptrace |= PT_PTRACED;
write_lock_irq(&tasklist_lock);
if (child->p_pptr != tsk) {
REMOVE_LINKS(child);
child->p_pptr = tsk;
SET_LINKS(child);
}
write_unlock_irq(&tasklist_lock);
send_sig(SIGSTOP, child, 1);
ret = 0;
ret = ptrace_attach(child);
goto out_tsk;
}
ret = -ESRCH;
......
......@@ -320,38 +320,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
|| (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
unsigned long flags;
if(child == current) {
/* Try this under SunOS/Solaris, bwa haha
* You'll never be able to kill the process. ;-)
*/
if (ptrace_attach(child)) {
pt_error_return(regs, EPERM);
goto out_tsk;
}
if((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->uid) ||
(current->uid != child->suid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) {
pt_error_return(regs, EPERM);
goto out_tsk;
}
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED) {
pt_error_return(regs, EPERM);
goto out_tsk;
}
child->ptrace |= PT_PTRACED;
write_lock_irqsave(&tasklist_lock, flags);
if(child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irqrestore(&tasklist_lock, flags);
send_sig(SIGSTOP, child, 1);
pt_succ_return(regs, 0);
goto out_tsk;
}
......
# $Id: config.in,v 1.147 2001/07/18 07:52:34 davem Exp $
# $Id: config.in,v 1.148 2001/07/20 07:10:35 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
......@@ -207,7 +207,9 @@ fi
endmenu
source drivers/fc4/Config.in
source drivers/message/fusion/Config.in
source drivers/ieee1394/Config.in
if [ "$CONFIG_NET" = "y" ]; then
......
......@@ -364,13 +364,23 @@ CONFIG_FUSION_LAN=m
CONFIG_NET_FC=y
#
# IEEE 1394 (FireWire) support
# IEEE 1394 (FireWire) support (EXPERIMENTAL)
#
CONFIG_IEEE1394=m
#
# Device Drivers
#
CONFIG_IEEE1394_PCILYNX=m
# CONFIG_IEEE1394_PCILYNX_LOCALRAM is not set
# CONFIG_IEEE1394_PCILYNX_PORTS is not set
CONFIG_IEEE1394_OHCI1394=m
#
# Protocol Drivers
#
# CONFIG_IEEE1394_VIDEO1394 is not set
CONFIG_IEEE1394_SBP2=m
CONFIG_IEEE1394_RAWIO=m
# CONFIG_IEEE1394_VERBOSEDEBUG is not set
......
......@@ -170,38 +170,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
|| (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
unsigned long flags;
if (child == current) {
/* Try this under SunOS/Solaris, bwa haha
* You'll never be able to kill the process. ;-)
*/
if (ptrace_attach(child)) {
pt_error_return(regs, EPERM);
goto out_tsk;
}
if ((!child->mm->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->uid) ||
(current->uid != child->suid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) {
pt_error_return(regs, EPERM);
goto out_tsk;
}
/* the same process cannot be attached many times */
if (child->ptrace & PT_PTRACED) {
pt_error_return(regs, EPERM);
goto out_tsk;
}
child->ptrace |= PT_PTRACED;
write_lock_irqsave(&tasklist_lock, flags);
if (child->p_pptr != current) {
REMOVE_LINKS(child);
child->p_pptr = current;
SET_LINKS(child);
}
write_unlock_irqrestore(&tasklist_lock, flags);
send_sig(SIGSTOP, child, 1);
pt_succ_return(regs, 0);
goto out_tsk;
}
......
......@@ -419,6 +419,7 @@
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
......@@ -978,7 +979,7 @@ typedef struct {
int logical_blk_num; /* logical block number */
__u16 wrt_pass_cntr; /* write pass counter */
__u32 update_frame_cntr; /* update frame counter */
struct semaphore *sem;
struct completion *waiting;
int onstream_write_error; /* write error recovery active */
int header_ok; /* header frame verified ok */
int linux_media; /* reading linux-specifc media */
......@@ -1886,8 +1887,8 @@ static void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
printk("ide-tape: %s: skipping over config parition..\n", tape->name);
#endif
tape->onstream_write_error = OS_PART_ERROR;
if (tape->sem)
up(tape->sem);
if (tape->waiting)
complete(tape->waiting);
}
}
remove_stage = 1;
......@@ -1903,8 +1904,8 @@ static void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
tape->nr_pending_stages++;
tape->next_stage = tape->first_stage;
rq->current_nr_sectors = rq->nr_sectors;
if (tape->sem)
up(tape->sem);
if (tape->waiting)
complete(tape->waiting);
}
}
} else if (rq->cmd == IDETAPE_READ_RQ) {
......@@ -3064,15 +3065,15 @@ static void idetape_init_stage (ide_drive_t *drive, idetape_stage_t *stage, int
}
/*
* idetape_wait_for_request installs a semaphore in a pending request
* idetape_wait_for_request installs a completion in a pending request
* and sleeps until it is serviced.
*
* The caller should ensure that the request will not be serviced
* before we install the semaphore (usually by disabling interrupts).
* before we install the completion (usually by disabling interrupts).
*/
static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
{
DECLARE_MUTEX_LOCKED(sem);
DECLARE_COMPLETION(wait);
idetape_tape_t *tape = drive->driver_data;
#if IDETAPE_DEBUG_BUGS
......@@ -3081,12 +3082,12 @@ static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
return;
}
#endif /* IDETAPE_DEBUG_BUGS */
rq->sem = &sem;
tape->sem = &sem;
rq->waiting = &wait;
tape->waiting = &wait;
spin_unlock(&tape->spinlock);
down(&sem);
rq->sem = NULL;
tape->sem = NULL;
wait_for_completion(&wait);
rq->waiting = NULL;
tape->waiting = NULL;
spin_lock_irq(&tape->spinlock);
}
......
......@@ -8,7 +8,7 @@ export-objs := ieee1394_syms.o
list-multi := ieee1394.o
ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
highlevel.o csr.o guid.o ieee1394_syms.o
highlevel.o csr.o nodemgr.o ieee1394_syms.o
obj-$(CONFIG_IEEE1394) += ieee1394.o
obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
......@@ -16,8 +16,6 @@ obj-$(CONFIG_IEEE1394_OHCI1394) += ohci1394.o
obj-$(CONFIG_IEEE1394_VIDEO1394) += video1394.o
obj-$(CONFIG_IEEE1394_RAWIO) += raw1394.o
obj-$(CONFIG_IEEE1394_SBP2) += sbp2.o
obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o
obj-$(CONFIG_IEEE1394_IP1394) += ip1394.o
include $(TOPDIR)/Rules.make
......
......@@ -29,7 +29,7 @@
#include "highlevel.h"
#include "ieee1394_transactions.h"
#include "csr.h"
#include "guid.h"
#include "nodemgr.h"
atomic_t hpsb_generation = ATOMIC_INIT(0);
......@@ -782,13 +782,13 @@ static int __init ieee1394_init(void)
{
init_hpsb_highlevel();
init_csr();
init_ieee1394_guid();
init_ieee1394_nodemgr();
return 0;
}
static void __exit ieee1394_cleanup(void)
{
cleanup_ieee1394_guid();
cleanup_ieee1394_nodemgr();
cleanup_csr();
}
......
......@@ -18,7 +18,7 @@
#include "ieee1394_core.h"
#include "ieee1394_transactions.h"
#include "highlevel.h"
#include "guid.h"
#include "nodemgr.h"
EXPORT_SYMBOL(hpsb_register_lowlevel);
EXPORT_SYMBOL(hpsb_unregister_lowlevel);
......@@ -76,5 +76,5 @@ EXPORT_SYMBOL(highlevel_remove_host);
EXPORT_SYMBOL(highlevel_host_reset);
EXPORT_SYMBOL(highlevel_add_one_host);
EXPORT_SYMBOL(hpsb_guid_get_handle);
EXPORT_SYMBOL(hpsb_guid_localhost);
EXPORT_SYMBOL(hpsb_get_host_by_ge);
EXPORT_SYMBOL(hpsb_guid_fill_packet);
/*
* IEEE 1394 for Linux
*
* GUID collection and management
* Node information (ConfigROM) collection and management.
*
* Copyright (C) 2000 Andreas E. Bombe
* 2001 Ben Collins <bcollins@debian.net>
*
* This code is licensed under the GPL. See the file COPYING in the root
* directory of the kernel sources for details.
......@@ -14,6 +13,8 @@
#include <linux/slab.h>
#include <asm/byteorder.h>
#include <asm/atomic.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include "ieee1394_types.h"
#include "ieee1394.h"
......@@ -23,12 +24,37 @@
#include "csr.h"
/* Basically what we do here is start off retrieving the bus_info block.
* From there will fill in some info about the node, verify it is of IEEE
* 1394 type, and the the crc checks out ok. After that we start off with
* the root directory, and subdirectories. To do this, we retrieve the
* quadlet header for a directory, find out the length, and retrieve the
* complete directory entry (be it a leaf or a directory). We then process
* it and add the info to our structure for that particular node.
*
* We verify CRC's along the way for each directory/block/leaf. The
* entire node structure is generic, and simply stores the information in
* a way that's easy to parse by the protocol interface.
*
* XXX: Most of this isn't done yet :) */
static atomic_t outstanding_requests;
static LIST_HEAD(guid_list);
rwlock_t guid_lock = RW_LOCK_UNLOCKED;
static LIST_HEAD(node_list);
rwlock_t node_lock = RW_LOCK_UNLOCKED;
static LIST_HEAD(host_info_list);
spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;
struct guid_entry {
struct host_info {
struct hpsb_host *host;
int pid;
wait_queue_head_t reset_wait;
struct list_head list;
};
struct node_entry {
struct list_head list;
atomic_t refcount;
......@@ -40,21 +66,12 @@ struct guid_entry {
atomic_t generation;
};
struct guid_req {
struct hpsb_packet *pkt;
int retry;
unsigned int hdr_size;
int hdr_ptr;
u32 bus_info[5];
struct tq_struct tq;
};
static struct guid_entry *create_guid_entry(void)
static struct node_entry *create_node_entry(void)
{
struct guid_entry *ge;
struct node_entry *ge;
unsigned long flags;
ge = kmalloc(sizeof(struct guid_entry), SLAB_ATOMIC);
ge = kmalloc(sizeof(struct node_entry), SLAB_ATOMIC);
if (!ge) return NULL;
INIT_LIST_HEAD(&ge->list);
......@@ -64,21 +81,21 @@ static struct guid_entry *create_guid_entry(void)
ge->node_id = 0;
atomic_set(&ge->generation, -1);
write_lock_irqsave(&guid_lock, flags);
list_add_tail(&ge->list, &guid_list);
write_unlock_irqrestore(&guid_lock, flags);
write_lock_irqsave(&node_lock, flags);
list_add_tail(&ge->list, &node_list);
write_unlock_irqrestore(&node_lock, flags);
return ge;
}
static struct guid_entry *find_entry(u64 guid)
static struct node_entry *find_entry(u64 guid)
{
struct list_head *lh;
struct guid_entry *ge;
struct node_entry *ge;
lh = guid_list.next;
while (lh != &guid_list) {
ge = list_entry(lh, struct guid_entry, list);
lh = node_list.next;
while (lh != &node_list) {
ge = list_entry(lh, struct node_entry, list);
if (ge->guid == guid) return ge;
lh = lh->next;
}
......@@ -88,7 +105,7 @@ static struct guid_entry *find_entry(u64 guid)
static void associate_guid(struct hpsb_host *host, nodeid_t nodeid, u64 guid)
{
struct guid_entry *ge;
struct node_entry *ge;
unsigned long flags;
HPSB_DEBUG("Node %d on %s host: GUID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
......@@ -97,11 +114,11 @@ static void associate_guid(struct hpsb_host *host, nodeid_t nodeid, u64 guid)
((u8 *)&guid)[4], ((u8 *)&guid)[5], ((u8 *)&guid)[6],
((u8 *)&guid)[7]);
read_lock_irqsave(&guid_lock, flags);
read_lock_irqsave(&node_lock, flags);
ge = find_entry(guid);
read_unlock_irqrestore(&guid_lock, flags);
read_unlock_irqrestore(&node_lock, flags);
if (!ge) ge = create_guid_entry();
if (!ge) ge = create_node_entry();
if (!ge) return;
ge->host = host;
......@@ -111,102 +128,22 @@ static void associate_guid(struct hpsb_host *host, nodeid_t nodeid, u64 guid)
atomic_set(&ge->generation, get_hpsb_generation());
}
static void pkt_complete(struct guid_req *req)
/* This is where we probe the nodes for their information and provided
* features. */
static void nodemgr_node_probe(struct hpsb_host *host)
{
struct hpsb_packet *pkt = req->pkt;
struct hpsb_host *host = pkt->host;
nodeid_t nodeid = pkt->node_id;
if (hpsb_packet_success (pkt)) {
HPSB_ERR("GUID quadlet transaction error for %d, retry: %d", nodeid,
req->retry);
req->retry++;
if (req->retry > 3)
goto finish;
else
goto retry;
}
/* Copy our received quadlet */
req->bus_info[req->hdr_ptr++] = be32_to_cpu(pkt->header[3]);
/* First quadlet, let's get some info */
if (req->hdr_ptr == 1) {
/* Get the bus_info_length from first quadlet */
req->hdr_size = req->bus_info[0] >> 24;
/* Make sure this isn't one of those minimal proprietary
* ROMs. IMO, we should just barf all over them. We need
* atleast four bus_info quads to get our EUI-64. */
if (req->hdr_size < 4) {
HPSB_INFO("Node %d on %s host has non-standard ROM format (%d quads), "
"cannot parse", nodeid, host->template->name, req->hdr_size);
goto finish;
}
/* Make sure we don't overflow. We have one quad for this
* first bus info block, the other 4 should be part of the
* bus info itself. */
if (req->hdr_size > (sizeof (req->bus_info) >> 2) - 1)
req->hdr_size = (sizeof (req->bus_info) >> 2) - 1;
}
/* We've got all the info we need, so let's check the EUI-64, and
* add it to our list. */
if (req->hdr_ptr >= req->hdr_size + 1) {
associate_guid(pkt->host, pkt->node_id,
((u64)req->bus_info[3] << 32) | req->bus_info[4]);
goto finish;
}
retry:
/* Here, we either retry a failed retrieve, or we have incremented
* our counter, to get the next quad in our header. */
free_tlabel(pkt->host, pkt->node_id, pkt->tlabel);
free_hpsb_packet(pkt);
pkt = hpsb_make_readqpacket(host, nodeid, CSR_REGISTER_BASE +
CSR_CONFIG_ROM + (req->hdr_ptr<<2));
if (!pkt) {
kfree(req);
HPSB_ERR("Out of memory in GUID processing");
return;
}
req->pkt = pkt;
req->retry = 0;
queue_task(&req->tq, &pkt->complete_tq);
if (!hpsb_send_packet(pkt)) {
HPSB_NOTICE("Failed to send GUID request to node %d", nodeid);
goto finish;
}
return;
finish:
free_tlabel(pkt->host, nodeid, pkt->tlabel);
free_hpsb_packet(pkt);
kfree(req);
if (atomic_dec_and_test(&outstanding_requests)) {
/* Do something useful */
}
return;
}
static void host_reset(struct hpsb_host *host)
{
struct guid_req *greq;
struct hpsb_packet *pkt;
struct selfid *sid = (struct selfid *)host->topology_map;
int nodecount = host->node_count;
nodeid_t nodeid = LOCAL_BUS;
quadlet_t buffer[5], quad;
octlet_t base = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
int retval;
/* We need to detect when the ConfigROM's generation has changed,
* so we only update the node's info when it needs to be. */
for (; nodecount; nodecount--, nodeid++, sid++) {
int header_count = 0;
unsigned header_size = 0;
while (sid->extended)
sid++;
if (!sid->link_active)
......@@ -214,65 +151,70 @@ static void host_reset(struct hpsb_host *host)
if (nodeid == host->node_id)
continue;
greq = kmalloc(sizeof(struct guid_req), SLAB_ATOMIC);
if (!greq) {
HPSB_ERR("Out of memory in GUID processing");
return;
}
HPSB_DEBUG("Initiating ConfigROM request for node %d", nodeid & NODE_MASK);
pkt = hpsb_make_readqpacket(host, nodeid, CSR_REGISTER_BASE +
CSR_CONFIG_ROM);
retval = hpsb_read(host, nodeid, base, &quad, 4);
buffer[header_count++] = be32_to_cpu(quad);
if (!pkt) {
kfree(greq);
HPSB_ERR("Out of memory in GUID processing");
return;
}
if (retval) {
HPSB_ERR("ConfigROM quadlet transaction error for %d",
nodeid & NODE_MASK);
continue;
}
INIT_TQUEUE(&greq->tq, (void (*)(void*))pkt_complete, greq);
header_size = buffer[0] >> 24;
greq->hdr_size = 4;
greq->hdr_ptr = 0;
greq->retry = 0;
greq->pkt = pkt;
if (header_size < 4) {
HPSB_INFO("Node %d on %s host has non-standard ROM format (%d quads), "
"cannot parse", nodeid & NODE_MASK, host->template->name,
header_size);
continue;
}
queue_task(&greq->tq, &pkt->complete_tq);
while (header_count <= header_size && (header_count<<2) < sizeof(buffer)) {
retval = hpsb_read(host, nodeid, base + (header_count<<2), &quad, 4);
buffer[header_count++] = be32_to_cpu(quad);
if (!hpsb_send_packet(pkt)) {
free_tlabel(pkt->host, pkt->node_id, pkt->tlabel);
free_hpsb_packet(pkt);
kfree(greq);
HPSB_NOTICE("Failed to send GUID request to node %d", nodeid);
}
if (retval) {
HPSB_ERR("ConfigROM quadlet transaction error for %d",
nodeid & NODE_MASK);
goto failed_read;
}
HPSB_DEBUG("GUID request sent to node %d", nodeid & NODE_MASK);
}
atomic_inc(&outstanding_requests);
associate_guid(host, nodeid, be64_to_cpu(((u64)buffer[3] << 32) | buffer[4]));
failed_read:
continue;
}
/* Need to detect when nodes are no longer associated with
* anything. I believe we can do this using the generation of the
* entries after a reset, compared the the hosts generation. */
}
struct guid_entry *hpsb_guid_get_handle(u64 guid)
struct node_entry *hpsb_guid_get_handle(u64 guid)
{
unsigned long flags;
struct guid_entry *ge;
struct node_entry *ge;
read_lock_irqsave(&guid_lock, flags);
read_lock_irqsave(&node_lock, flags);
ge = find_entry(guid);
if (ge) atomic_inc(&ge->refcount);
read_unlock_irqrestore(&guid_lock, flags);
read_unlock_irqrestore(&node_lock, flags);
return ge;
}
struct hpsb_host *hpsb_guid_localhost(struct guid_entry *ge)
struct hpsb_host *hpsb_get_host_by_ge(struct node_entry *ge)
{
if (atomic_read(&ge->generation) != get_hpsb_generation()) return NULL;
if (ge->node_id == ge->host->node_id) return ge->host;
return NULL;
}
int hpsb_guid_fill_packet(struct guid_entry *ge, struct hpsb_packet *pkt)
int hpsb_guid_fill_packet(struct node_entry *ge, struct hpsb_packet *pkt)
{
if (atomic_read(&ge->generation) != get_hpsb_generation()) return 0;
......@@ -282,24 +224,168 @@ int hpsb_guid_fill_packet(struct guid_entry *ge, struct hpsb_packet *pkt)
return 1;
}
static int nodemgr_reset_handler(void *__hi)
{
struct host_info *hi = (struct host_info *)__hi;
struct hpsb_host *host = hi->host;
/* Standard thread setup */
lock_kernel();
daemonize();
strcpy(current->comm, "NodeMngr");
unlock_kernel();
for (;;) {
if (signal_pending(current))
break;
/* Let's take a short pause to make sure all the devices
* have time to settle. */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ/50);
if (hi && host)
nodemgr_node_probe(host);
/* Wait for the next bus reset */
if (hi && host)
interruptible_sleep_on(&hi->reset_wait);
}
return(0);
}
static void nodemgr_add_host(struct hpsb_host *host)
{
struct host_info *hi = kmalloc (sizeof (struct host_info), GFP_KERNEL);
int flags;
if (!hi) {
HPSB_ERR ("Out of memory in Node Manager");
return;
}
hi->host = host;
INIT_LIST_HEAD(&hi->list);
hi->pid = -1;
init_waitqueue_head(&hi->reset_wait);
spin_lock_irqsave (&host_info_lock, flags);
list_add_tail (&hi->list, &host_info_list);
spin_unlock_irqrestore (&host_info_lock, flags);
return;
}
static void nodemgr_schedule_thread (void *__hi)
{
struct host_info *hi = (struct host_info *)__hi;
hi->pid = kernel_thread(nodemgr_reset_handler, hi,
CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
}
static void nodemgr_host_reset(struct hpsb_host *host)
{
struct list_head *lh;
struct host_info *hi = NULL;
int flags;
spin_lock_irqsave (&host_info_lock, flags);
lh = host_info_list.next;
while (lh != &host_info_list) {
struct host_info *myhi = list_entry(lh, struct host_info, list);
if (myhi->host == host) {
hi = myhi;
break;
}
lh = lh->next;
}
if (hi == NULL) {
HPSB_ERR ("Could not process reset of non-existent host in Node Manager");
goto done_reset_host;
}
if (hi->pid >= 0) {
wake_up(&hi->reset_wait);
} else {
if (in_interrupt()) {
static struct tq_struct task;
memset(&task, 0, sizeof(struct tq_struct));
task.routine = nodemgr_schedule_thread;
task.data = (void*)hi;
if (schedule_task(&task) < 0)
HPSB_ERR ("Failed to schedule Node Manager thread!\n");
} else {
nodemgr_schedule_thread(hi);
}
}
done_reset_host:
spin_unlock_irqrestore (&host_info_lock, flags);
return;
}
static void nodemgr_remove_host(struct hpsb_host *host)
{
struct list_head *lh;
struct host_info *hi = NULL;
int flags;
spin_lock_irqsave (&host_info_lock, flags);
lh = host_info_list.next;
while (lh != &host_info_list) {
struct host_info *myhi = list_entry(lh, struct host_info, list);
if (myhi->host == host) {
hi = myhi;
break;
}
lh = lh->next;
}
if (hi == NULL) {
HPSB_ERR ("Could not remove non-exitent host in Node Manager");
goto done_remove_host;
}
if (hi->pid >= 0)
kill_proc(hi->pid, SIGINT, 1);
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ*2); /* 2 second delay */
kfree (hi);
done_remove_host:
spin_unlock_irqrestore (&host_info_lock, flags);
return;
}
static struct hpsb_highlevel_ops guid_ops = {
host_reset: host_reset,
add_host: nodemgr_add_host,
host_reset: nodemgr_host_reset,
remove_host: nodemgr_remove_host,
};
static struct hpsb_highlevel *hl;
void init_ieee1394_guid(void)
void init_ieee1394_nodemgr(void)
{
atomic_set(&outstanding_requests, 0);
hl = hpsb_register_highlevel("GUID manager", &guid_ops);
hl = hpsb_register_highlevel("Node manager", &guid_ops);
if (!hl) {
HPSB_ERR("out of memory during ieee1394 initialization");
HPSB_ERR("Out of memory during ieee1394 initialization");
}
}
void cleanup_ieee1394_guid(void)
void cleanup_ieee1394_nodemgr(void)
{
hpsb_unregister_highlevel(hl);
}
/*
* Copyright (C) 2000 Andreas E. Bombe
* 2001 Ben Collins <bcollins@debian.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _IEEE1394_GUID_H
#define _IEEE1394_GUID_H
#ifndef _IEEE1394_NODEMGR_H
#define _IEEE1394_NODEMGR_H
/*
......@@ -11,8 +29,8 @@
* associated with current nodes).
*/
struct guid_entry;
typedef struct guid_entry *hpsb_guid_t;
struct node_entry;
typedef struct node_entry *hpsb_guid_t;
/*
......@@ -32,7 +50,7 @@ hpsb_guid_t hpsb_guid_get_handle(u64 guid);
* Note that the local GUID currently isn't collected, so this will always
* return NULL.
*/
struct hpsb_host *hpsb_guid_localhost(hpsb_guid_t handle);
struct hpsb_host *hpsb_get_host_by_ge(hpsb_guid_t handle);
/*
* This will fill in the given, pre-initialised hpsb_packet with the current
......@@ -48,7 +66,7 @@ struct hpsb_host *hpsb_guid_localhost(hpsb_guid_t handle);
int hpsb_guid_fill_packet(hpsb_guid_t handle, struct hpsb_packet *pkt);
void init_ieee1394_guid(void);
void cleanup_ieee1394_guid(void);
void init_ieee1394_nodemgr(void);
void cleanup_ieee1394_nodemgr(void);
#endif /* _IEEE1394_GUID_H */
#endif /* _IEEE1394_NODEMGR_H */
......@@ -178,7 +178,7 @@ static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, ohci1394_pci_tbl);
static char version[] __devinitdata =
"ohci1394.c:v0.50 15/Jul/01 Ben Collins <bcollins@debian.org>";
"v0.50 15/Jul/01 Ben Collins <bcollins@debian.org>";
/* Module Parameters */
MODULE_PARM(attempt_root,"i");
......@@ -216,6 +216,7 @@ static u8 get_phy_reg(struct ti_ohci *ohci, u8 addr)
for (i = 0; i < OHCI_LOOP_COUNT; i++) {
if (reg_read(ohci, OHCI1394_PhyControl) & 0x80000000)
break;
mdelay(1);
}
......@@ -243,6 +244,7 @@ static void set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data)
r = reg_read(ohci, OHCI1394_PhyControl);
if (!(r & 0x00004000))
break;
mdelay(1);
}
......@@ -516,22 +518,6 @@ static int ohci_initialize(struct hpsb_host *host)
/* Set the configuration ROM mapping register */
reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus);
/* Set bus options */
reg_write(ohci, OHCI1394_BusOptions,
cpu_to_be32(ohci->csr_config_rom_cpu[2]));
#if 0
/* Write the GUID into the csr config rom */
ohci->csr_config_rom_cpu[3] =
be32_to_cpu(reg_read(ohci, OHCI1394_GUIDHi));
ohci->csr_config_rom_cpu[4] =
be32_to_cpu(reg_read(ohci, OHCI1394_GUIDLo));
#endif
/* Write the config ROM header */
reg_write(ohci, OHCI1394_ConfigROMhdr,
cpu_to_be32(ohci->csr_config_rom_cpu[0]));
ohci->max_packet_size =
1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);
PRINT(KERN_DEBUG, ohci->id, "Max packet size = %d bytes",
......@@ -725,7 +711,7 @@ static void insert_packet(struct ti_ohci *ohci,
OHCI_DMA_ALLOC("single, block transmit packet");
if (ohci->payload_swap)
block_swab32(packet->data, packet->data_size>>2);
block_swab32(packet->data, packet->data_size >> 2);
d->prg_cpu[idx]->end.branchAddress = 0;
d->prg_cpu[idx]->end.status = 0;
......@@ -1897,6 +1883,9 @@ static void ohci_init_config_rom(struct ti_ohci *ohci)
cf_put_1quad(&cr, reg_read(ohci, OHCI1394_GUIDLo));
cf_unit_end(&cr);
DBGMSG(ohci->id, "GUID: %08x:%08x\n", reg_read(ohci, OHCI1394_GUIDHi),
reg_read(ohci, OHCI1394_GUIDLo));
/* IEEE P1212 suggests the initial ROM header CRC should only
* cover the header itself (and not the entire ROM). Since we use
* this, then we can make our bus_info_len the same as the CRC
......@@ -1991,6 +1980,7 @@ int ohci_compare_swap(struct ti_ohci *ohci, quadlet_t *data,
for (i = 0; i < OHCI_LOOP_COUNT; i++) {
if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000)
break;
mdelay(10);
}
......@@ -2180,7 +2170,7 @@ static int __devinit ohci1394_add_one(struct pci_dev *dev, const struct pci_devi
if (ohci->ir_context == NULL)
FAIL("Failed to allocate IR context");
ohci->ISO_channel_usage= 0;
ohci->ISO_channel_usage = 0;
spin_lock_init(&ohci->IR_channel_lock);
if (!request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ,
......@@ -2191,10 +2181,6 @@ static int __devinit ohci1394_add_one(struct pci_dev *dev, const struct pci_devi
ohci_init_config_rom(ohci);
DBGMSG(ohci->id, "The 1st byte at offset 0x404 is: 0x%02x",
*((char *)ohci->csr_config_rom_cpu+4));
/* Tell the highlevel this host is ready */
highlevel_add_one_host (host);
......
......@@ -1351,6 +1351,7 @@ static int add_card(struct pci_dev *dev)
lynx->id = num_of_cards-1;
lynx->dev = dev;
lynx->host->pdev = dev;
lynx->lock = SPIN_LOCK_UNLOCKED;
lynx->phy_reg_lock = SPIN_LOCK_UNLOCKED;
......
......@@ -1688,6 +1688,10 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
error = -EINVAL;
if (is_subdir(new_dentry, old_dentry))
goto out_unlock;
/* Don't eat your daddy, dear... */
/* This also avoids locking issues */
if (old_dentry->d_parent == new_dentry)
goto out_unlock;
target = new_dentry->d_inode;
if (target) { /* Hastur! Hastur! Hastur! */
triple_down(&old_dir->i_zombie,
......
......@@ -645,6 +645,20 @@ static int proc_base_readdir(struct file * filp,
/* building an inode */
static int task_dumpable(struct task_struct *task)
{
int dumpable = 0;
struct mm_struct *mm;
task_lock(task);
mm = task->mm;
if (mm)
dumpable = mm->dumpable;
task_unlock(task);
return dumpable;
}
static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task, int ino)
{
struct inode * inode;
......@@ -670,7 +684,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
inode->u.proc_i.task = task;
inode->i_uid = 0;
inode->i_gid = 0;
if (ino == PROC_PID_INO || task->mm->dumpable) {
if (ino == PROC_PID_INO || task_dumpable(task)) {
inode->i_uid = task->euid;
inode->i_gid = task->egid;
}
......
......@@ -442,6 +442,7 @@ extern int make_pages_present(unsigned long addr, unsigned long end);
extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len);
extern int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int len);
extern int ptrace_attach(struct task_struct *tsk);
/*
* On a two-level page table, this ends up being trivial. Thus the
......
/* Common Flash Interface structures
* See http://support.intel.com/design/flash/technote/index.htm
* $Id: cfi.h,v 1.21 2001/06/03 01:32:57 nico Exp $
* $Id: cfi.h,v 1.22 2001/07/06 09:29:07 dwmw2 Exp $
*/
#ifndef __MTD_CFI_H__
......@@ -10,6 +10,7 @@
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/mtd/flashchip.h>
#include <linux/mtd/cfi_endian.h>
......
......@@ -45,6 +45,7 @@
#include <linux/fs.h>
#include <linux/tty.h>
#include <linux/in6.h>
#include <linux/completion.h>
#include <asm/checksum.h>
#if defined(CONFIG_PROC_FS)
......@@ -362,6 +363,10 @@ EXPORT_SYMBOL(add_wait_queue);
EXPORT_SYMBOL(add_wait_queue_exclusive);
EXPORT_SYMBOL(remove_wait_queue);
/* completion handling */
EXPORT_SYMBOL(wait_for_completion);
EXPORT_SYMBOL(complete);
/* The notion of irq probe/assignment is foreign to S/390 */
#if !defined(CONFIG_ARCH_S390)
......
......@@ -16,6 +16,51 @@
#include <asm/pgtable.h>
#include <asm/uaccess.h>
int ptrace_attach(struct task_struct *task)
{
task_lock(task);
if (task->pid <= 1)
goto bad;
if (task == current)
goto bad;
if (!task->mm)
goto bad;
if(((current->uid != task->euid) ||
(current->uid != task->suid) ||
(current->uid != task->uid) ||
(current->gid != task->egid) ||
(current->gid != task->sgid) ||
(!cap_issubset(task->cap_permitted, current->cap_permitted)) ||
(current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
goto bad;
rmb();
if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
goto bad;
/* the same process cannot be attached many times */
if (task->ptrace & PT_PTRACED)
goto bad;
/* Go */
task->ptrace |= PT_PTRACED;
task_unlock(task);
write_lock_irq(&tasklist_lock);
if (task->p_pptr != current) {
REMOVE_LINKS(task);
task->p_pptr = current;
SET_LINKS(task);
}
write_unlock_irq(&tasklist_lock);
send_sig(SIGSTOP, task, 1);
return 0;
bad:
task_unlock(task);
return -EPERM;
}
/*
* Access another process' address space, one page at a time.
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment