From 78170628fcbf95a3d33b6214fbb379a138377b18 Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Tue, 2 Dec 2003 19:57:38 -0800 Subject: [RTNETLINK]: Add RTPROT_XORP. --- include/linux/rtnetlink.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index aadba39502cc..4a26f207b5d7 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -138,6 +138,7 @@ enum #define RTPROT_ZEBRA 11 /* Zebra */ #define RTPROT_BIRD 12 /* BIRD */ #define RTPROT_DNROUTED 13 /* DECnet routing daemon */ +#define RTPROT_XORP 14 /* XORP */ /* rtm_scope -- cgit v1.2.3 From a2c72fae694277071dcbab33dfb7f88af5e54954 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 11 Dec 2003 22:20:08 -0800 Subject: Fix subtle bug in "finish_wait()", which can cause kernel stack corruption on SMP because of another CPU still accessing a waitqueue even after it was de-allocated. Use a careful version of the list emptiness check to make sure we don't de-allocate the stack frame before the waitqueue is all done. --- include/linux/list.h | 12 ++++++++++++ kernel/fork.c | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/list.h b/include/linux/list.h index b7d383e6a312..0835011b0ffb 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -208,6 +208,18 @@ static inline int list_empty(const struct list_head *head) return head->next == head; } +/** + * list_empty_careful - tests whether a list is + * empty _and_ checks that no other CPU might be + * in the process of still modifying either member + * @head: the list to test. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + static inline void __list_splice(struct list_head *list, struct list_head *head) { diff --git a/kernel/fork.c b/kernel/fork.c index 80c037b5ac3d..6fa0ce76acc5 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -159,7 +159,20 @@ void finish_wait(wait_queue_head_t *q, wait_queue_t *wait) unsigned long flags; __set_current_state(TASK_RUNNING); - if (!list_empty(&wait->task_list)) { + /* + * We can check for list emptiness outside the lock + * IFF: + * - we use the "careful" check that verifies both + * the next and prev pointers, so that there cannot + * be any half-pending updates in progress on other + * CPU's that we haven't seen yet (and that might + * still change the stack area. + * and + * - all other users take the lock (ie we can only + * have _one_ other CPU that looks at or modifies + * the list). + */ + if (!list_empty_careful(&wait->task_list)) { spin_lock_irqsave(&q->lock, flags); list_del_init(&wait->task_list); spin_unlock_irqrestore(&q->lock, flags); -- cgit v1.2.3 From 5965168e8e5392eded4c40eaf0c7e96be2346529 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 12 Dec 2003 19:42:12 -0800 Subject: [PATCH] no bio unmap on cdb copy failure The previous scsi_ioctl.c patch didn't cleanup the buffer/bio in the error case. Fix it by copying the command data earlier. --- drivers/block/scsi_ioctl.c | 11 +++++------ include/linux/blkdev.h | 4 +++- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index ca1eadb17340..098425adddf0 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -150,6 +150,7 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, struct request *rq; struct bio *bio; char sense[SCSI_SENSE_BUFFERSIZE]; + unsigned char cdb[BLK_MAX_CDB]; void *buffer; if (hdr->interface_id != 'S') @@ -166,6 +167,9 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, if (hdr->dxfer_len > (q->max_sectors << 9)) return -EIO; + if (copy_from_user(cdb, hdr->cmdp, hdr->cmd_len)) + return -EFAULT; + reading = writing = 0; buffer = NULL; bio = NULL; @@ -216,12 +220,7 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, * fill in request structure */ rq->cmd_len = hdr->cmd_len; - - if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) { - blk_put_request(rq); - return -EFAULT; - } - + memcpy(rq->cmd, cdb, hdr->cmd_len); if (sizeof(rq->cmd) != hdr->cmd_len) memset(rq->cmd + hdr->cmd_len, 0, sizeof(rq->cmd) - hdr->cmd_len); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index dcd5911223d0..35e0f0004e87 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -82,6 +82,8 @@ struct request_list { wait_queue_head_t wait[2]; }; +#define BLK_MAX_CDB 16 + /* * try to put the fields that are referenced together in the same cacheline */ @@ -147,7 +149,7 @@ struct request { * when request is used as a packet command carrier */ unsigned int cmd_len; - unsigned char cmd[16]; + unsigned char cmd[BLK_MAX_CDB]; unsigned int data_len; void *data; -- cgit v1.2.3