From: Greg Kroah-Hartman Date: Wed, 29 Apr 2009 20:30:46 +0000 (-0700) Subject: more .28 patches X-Git-Tag: v2.6.27.22~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9fa98e8f3a1430731f471be1746b2bfa8fc1e9be;p=thirdparty%2Fkernel%2Fstable-queue.git more .28 patches --- diff --git a/queue-2.6.28/b44-use-kernel-dma-addresses-for-the-kernel-dma-api.patch b/queue-2.6.28/b44-use-kernel-dma-addresses-for-the-kernel-dma-api.patch new file mode 100644 index 00000000000..0aceff2a5f8 --- /dev/null +++ b/queue-2.6.28/b44-use-kernel-dma-addresses-for-the-kernel-dma-api.patch @@ -0,0 +1,34 @@ +From 37efa239901493694a48f1d6f59f8de17c2c4509 Mon Sep 17 00:00:00 2001 +From: Michael Buesch +Date: Mon, 6 Apr 2009 09:52:27 +0000 +Subject: b44: Use kernel DMA addresses for the kernel DMA API + +From: Michael Buesch + +commit 37efa239901493694a48f1d6f59f8de17c2c4509 upstream. + +We must not use the device DMA addresses for the kernel DMA API, because +device DMA addresses have an additional offset added for the SSB translation. + +Use the original dma_addr_t for the sync operation. + +Cc: stable@kernel.org +Signed-off-by: Michael Buesch +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/b44.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/b44.c ++++ b/drivers/net/b44.c +@@ -750,7 +750,7 @@ static void b44_recycle_rx(struct b44 *b + dest_idx * sizeof(dest_desc), + DMA_BIDIRECTIONAL); + +- ssb_dma_sync_single_for_device(bp->sdev, le32_to_cpu(src_desc->addr), ++ ssb_dma_sync_single_for_device(bp->sdev, dest_map->mapping, + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); + } diff --git a/queue-2.6.28/block-include-empty-disks-in-proc-diskstats.patch b/queue-2.6.28/block-include-empty-disks-in-proc-diskstats.patch new file mode 100644 index 00000000000..3decdbbea6d --- /dev/null +++ b/queue-2.6.28/block-include-empty-disks-in-proc-diskstats.patch @@ -0,0 +1,81 @@ +From 71982a409f12c50d011325a4471aa20666bb908d Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Fri, 17 Apr 2009 08:34:48 +0200 +Subject: block: include empty disks in /proc/diskstats + +From: Tejun Heo + +commit 71982a409f12c50d011325a4471aa20666bb908d upstream. + +/proc/diskstats used to show stats for all disks whether they're +zero-sized or not and their non-zero partitions. Commit +074a7aca7afa6f230104e8e65eba3420263714a5 accidentally changed the +behavior such that it doesn't print out zero sized disks. This patch +implements DISK_PITER_INCL_EMPTY_PART0 flag to partition iterator and +uses it in diskstats_show() such that empty part0 is shown in +/proc/diskstats. + +Reported and bisectd by Dianel Collins. + +Signed-off-by: Tejun Heo +Reported-by: Daniel Collins +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + block/genhd.c | 12 ++++++++---- + include/linux/genhd.h | 1 + + 2 files changed, 9 insertions(+), 4 deletions(-) + +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -98,7 +98,7 @@ void disk_part_iter_init(struct disk_par + + if (flags & DISK_PITER_REVERSE) + piter->idx = ptbl->len - 1; +- else if (flags & DISK_PITER_INCL_PART0) ++ else if (flags & (DISK_PITER_INCL_PART0 | DISK_PITER_INCL_EMPTY_PART0)) + piter->idx = 0; + else + piter->idx = 1; +@@ -134,7 +134,8 @@ struct hd_struct *disk_part_iter_next(st + /* determine iteration parameters */ + if (piter->flags & DISK_PITER_REVERSE) { + inc = -1; +- if (piter->flags & DISK_PITER_INCL_PART0) ++ if (piter->flags & (DISK_PITER_INCL_PART0 | ++ DISK_PITER_INCL_EMPTY_PART0)) + end = -1; + else + end = 0; +@@ -150,7 +151,10 @@ struct hd_struct *disk_part_iter_next(st + part = rcu_dereference(ptbl->part[piter->idx]); + if (!part) + continue; +- if (!(piter->flags & DISK_PITER_INCL_EMPTY) && !part->nr_sects) ++ if (!part->nr_sects && ++ !(piter->flags & DISK_PITER_INCL_EMPTY) && ++ !(piter->flags & DISK_PITER_INCL_EMPTY_PART0 && ++ piter->idx == 0)) + continue; + + get_device(part_to_dev(part)); +@@ -980,7 +984,7 @@ static int diskstats_show(struct seq_fil + "\n\n"); + */ + +- disk_part_iter_init(&piter, gp, DISK_PITER_INCL_PART0); ++ disk_part_iter_init(&piter, gp, DISK_PITER_INCL_EMPTY_PART0); + while ((hd = disk_part_iter_next(&piter))) { + cpu = part_stat_lock(); + part_round_stats(cpu, hd); +--- a/include/linux/genhd.h ++++ b/include/linux/genhd.h +@@ -213,6 +213,7 @@ static inline void disk_put_part(struct + #define DISK_PITER_REVERSE (1 << 0) /* iterate in the reverse direction */ + #define DISK_PITER_INCL_EMPTY (1 << 1) /* include 0-sized parts */ + #define DISK_PITER_INCL_PART0 (1 << 2) /* include partition 0 */ ++#define DISK_PITER_INCL_EMPTY_PART0 (1 << 3) /* include empty partition 0 */ + + struct disk_part_iter { + struct gendisk *disk; diff --git a/queue-2.6.28/crypto-ixp4xx-fix-handling-of-chained-sg-buffers.patch b/queue-2.6.28/crypto-ixp4xx-fix-handling-of-chained-sg-buffers.patch new file mode 100644 index 00000000000..5c0c10808dc --- /dev/null +++ b/queue-2.6.28/crypto-ixp4xx-fix-handling-of-chained-sg-buffers.patch @@ -0,0 +1,390 @@ +From 0d44dc59b2b434b29aafeae581d06f81efac7c83 Mon Sep 17 00:00:00 2001 +From: Christian Hohnstaedt +Date: Fri, 27 Mar 2009 15:09:05 +0800 +Subject: crypto: ixp4xx - Fix handling of chained sg buffers + +From: Christian Hohnstaedt + +commit 0d44dc59b2b434b29aafeae581d06f81efac7c83 upstream. + + - keep dma functions away from chained scatterlists. + Use the existing scatterlist iteration inside the driver + to call dma_map_single() for each chunk and avoid dma_map_sg(). + +Signed-off-by: Christian Hohnstaedt +Tested-By: Karl Hiramoto +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/crypto/ixp4xx_crypto.c | 184 ++++++++++++++--------------------------- + 1 file changed, 64 insertions(+), 120 deletions(-) + +--- a/drivers/crypto/ixp4xx_crypto.c ++++ b/drivers/crypto/ixp4xx_crypto.c +@@ -101,6 +101,7 @@ struct buffer_desc { + u32 phys_addr; + u32 __reserved[4]; + struct buffer_desc *next; ++ enum dma_data_direction dir; + }; + + struct crypt_ctl { +@@ -132,14 +133,10 @@ struct crypt_ctl { + struct ablk_ctx { + struct buffer_desc *src; + struct buffer_desc *dst; +- unsigned src_nents; +- unsigned dst_nents; + }; + + struct aead_ctx { + struct buffer_desc *buffer; +- unsigned short assoc_nents; +- unsigned short src_nents; + struct scatterlist ivlist; + /* used when the hmac is not on one sg entry */ + u8 *hmac_virt; +@@ -312,7 +309,7 @@ static struct crypt_ctl *get_crypt_desc_ + } + } + +-static void free_buf_chain(struct buffer_desc *buf, u32 phys) ++static void free_buf_chain(struct device *dev, struct buffer_desc *buf,u32 phys) + { + while (buf) { + struct buffer_desc *buf1; +@@ -320,6 +317,7 @@ static void free_buf_chain(struct buffer + + buf1 = buf->next; + phys1 = buf->phys_next; ++ dma_unmap_single(dev, buf->phys_next, buf->buf_len, buf->dir); + dma_pool_free(buffer_pool, buf, phys); + buf = buf1; + phys = phys1; +@@ -348,7 +346,6 @@ static void one_packet(dma_addr_t phys) + struct crypt_ctl *crypt; + struct ixp_ctx *ctx; + int failed; +- enum dma_data_direction src_direction = DMA_BIDIRECTIONAL; + + failed = phys & 0x1 ? -EBADMSG : 0; + phys &= ~0x3; +@@ -358,13 +355,8 @@ static void one_packet(dma_addr_t phys) + case CTL_FLAG_PERFORM_AEAD: { + struct aead_request *req = crypt->data.aead_req; + struct aead_ctx *req_ctx = aead_request_ctx(req); +- dma_unmap_sg(dev, req->assoc, req_ctx->assoc_nents, +- DMA_TO_DEVICE); +- dma_unmap_sg(dev, &req_ctx->ivlist, 1, DMA_BIDIRECTIONAL); +- dma_unmap_sg(dev, req->src, req_ctx->src_nents, +- DMA_BIDIRECTIONAL); + +- free_buf_chain(req_ctx->buffer, crypt->src_buf); ++ free_buf_chain(dev, req_ctx->buffer, crypt->src_buf); + if (req_ctx->hmac_virt) { + finish_scattered_hmac(crypt); + } +@@ -374,16 +366,11 @@ static void one_packet(dma_addr_t phys) + case CTL_FLAG_PERFORM_ABLK: { + struct ablkcipher_request *req = crypt->data.ablk_req; + struct ablk_ctx *req_ctx = ablkcipher_request_ctx(req); +- int nents; ++ + if (req_ctx->dst) { +- nents = req_ctx->dst_nents; +- dma_unmap_sg(dev, req->dst, nents, DMA_FROM_DEVICE); +- free_buf_chain(req_ctx->dst, crypt->dst_buf); +- src_direction = DMA_TO_DEVICE; +- } +- nents = req_ctx->src_nents; +- dma_unmap_sg(dev, req->src, nents, src_direction); +- free_buf_chain(req_ctx->src, crypt->src_buf); ++ free_buf_chain(dev, req_ctx->dst, crypt->dst_buf); ++ } ++ free_buf_chain(dev, req_ctx->src, crypt->src_buf); + req->base.complete(&req->base, failed); + break; + } +@@ -748,56 +735,35 @@ static int setup_cipher(struct crypto_tf + return 0; + } + +-static int count_sg(struct scatterlist *sg, int nbytes) +-{ +- int i; +- for (i = 0; nbytes > 0; i++, sg = sg_next(sg)) +- nbytes -= sg->length; +- return i; +-} +- +-static struct buffer_desc *chainup_buffers(struct scatterlist *sg, +- unsigned nbytes, struct buffer_desc *buf, gfp_t flags) ++static struct buffer_desc *chainup_buffers(struct device *dev, ++ struct scatterlist *sg, unsigned nbytes, ++ struct buffer_desc *buf, gfp_t flags, ++ enum dma_data_direction dir) + { +- int nents = 0; +- +- while (nbytes > 0) { ++ for (;nbytes > 0; sg = scatterwalk_sg_next(sg)) { ++ unsigned len = min(nbytes, sg->length); + struct buffer_desc *next_buf; + u32 next_buf_phys; +- unsigned len = min(nbytes, sg_dma_len(sg)); ++ void *ptr; + +- nents++; + nbytes -= len; +- if (!buf->phys_addr) { +- buf->phys_addr = sg_dma_address(sg); +- buf->buf_len = len; +- buf->next = NULL; +- buf->phys_next = 0; +- goto next; +- } +- /* Two consecutive chunks on one page may be handled by the old +- * buffer descriptor, increased by the length of the new one +- */ +- if (sg_dma_address(sg) == buf->phys_addr + buf->buf_len) { +- buf->buf_len += len; +- goto next; +- } ++ ptr = page_address(sg_page(sg)) + sg->offset; + next_buf = dma_pool_alloc(buffer_pool, flags, &next_buf_phys); +- if (!next_buf) +- return NULL; ++ if (!next_buf) { ++ buf = NULL; ++ break; ++ } ++ sg_dma_address(sg) = dma_map_single(dev, ptr, len, dir); + buf->next = next_buf; + buf->phys_next = next_buf_phys; +- + buf = next_buf; +- buf->next = NULL; +- buf->phys_next = 0; ++ + buf->phys_addr = sg_dma_address(sg); + buf->buf_len = len; +-next: +- if (nbytes > 0) { +- sg = sg_next(sg); +- } ++ buf->dir = dir; + } ++ buf->next = NULL; ++ buf->phys_next = 0; + return buf; + } + +@@ -858,12 +824,12 @@ static int ablk_perform(struct ablkciphe + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); + struct ixp_ctx *ctx = crypto_ablkcipher_ctx(tfm); + unsigned ivsize = crypto_ablkcipher_ivsize(tfm); +- int ret = -ENOMEM; + struct ix_sa_dir *dir; + struct crypt_ctl *crypt; +- unsigned int nbytes = req->nbytes, nents; ++ unsigned int nbytes = req->nbytes; + enum dma_data_direction src_direction = DMA_BIDIRECTIONAL; + struct ablk_ctx *req_ctx = ablkcipher_request_ctx(req); ++ struct buffer_desc src_hook; + gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? + GFP_KERNEL : GFP_ATOMIC; + +@@ -876,7 +842,7 @@ static int ablk_perform(struct ablkciphe + + crypt = get_crypt_desc(); + if (!crypt) +- return ret; ++ return -ENOMEM; + + crypt->data.ablk_req = req; + crypt->crypto_ctx = dir->npe_ctx_phys; +@@ -889,53 +855,41 @@ static int ablk_perform(struct ablkciphe + BUG_ON(ivsize && !req->info); + memcpy(crypt->iv, req->info, ivsize); + if (req->src != req->dst) { ++ struct buffer_desc dst_hook; + crypt->mode |= NPE_OP_NOT_IN_PLACE; +- nents = count_sg(req->dst, nbytes); + /* This was never tested by Intel + * for more than one dst buffer, I think. */ +- BUG_ON(nents != 1); +- req_ctx->dst_nents = nents; +- dma_map_sg(dev, req->dst, nents, DMA_FROM_DEVICE); +- req_ctx->dst = dma_pool_alloc(buffer_pool, flags,&crypt->dst_buf); +- if (!req_ctx->dst) +- goto unmap_sg_dest; +- req_ctx->dst->phys_addr = 0; +- if (!chainup_buffers(req->dst, nbytes, req_ctx->dst, flags)) ++ BUG_ON(req->dst->length < nbytes); ++ req_ctx->dst = NULL; ++ if (!chainup_buffers(dev, req->dst, nbytes, &dst_hook, ++ flags, DMA_FROM_DEVICE)) + goto free_buf_dest; + src_direction = DMA_TO_DEVICE; ++ req_ctx->dst = dst_hook.next; ++ crypt->dst_buf = dst_hook.phys_next; + } else { + req_ctx->dst = NULL; +- req_ctx->dst_nents = 0; + } +- nents = count_sg(req->src, nbytes); +- req_ctx->src_nents = nents; +- dma_map_sg(dev, req->src, nents, src_direction); +- +- req_ctx->src = dma_pool_alloc(buffer_pool, flags, &crypt->src_buf); +- if (!req_ctx->src) +- goto unmap_sg_src; +- req_ctx->src->phys_addr = 0; +- if (!chainup_buffers(req->src, nbytes, req_ctx->src, flags)) ++ req_ctx->src = NULL; ++ if (!chainup_buffers(dev, req->src, nbytes, &src_hook, ++ flags, src_direction)) + goto free_buf_src; + ++ req_ctx->src = src_hook.next; ++ crypt->src_buf = src_hook.phys_next; + crypt->ctl_flags |= CTL_FLAG_PERFORM_ABLK; + qmgr_put_entry(SEND_QID, crypt_virt2phys(crypt)); + BUG_ON(qmgr_stat_overflow(SEND_QID)); + return -EINPROGRESS; + + free_buf_src: +- free_buf_chain(req_ctx->src, crypt->src_buf); +-unmap_sg_src: +- dma_unmap_sg(dev, req->src, req_ctx->src_nents, src_direction); ++ free_buf_chain(dev, req_ctx->src, crypt->src_buf); + free_buf_dest: + if (req->src != req->dst) { +- free_buf_chain(req_ctx->dst, crypt->dst_buf); +-unmap_sg_dest: +- dma_unmap_sg(dev, req->src, req_ctx->dst_nents, +- DMA_FROM_DEVICE); ++ free_buf_chain(dev, req_ctx->dst, crypt->dst_buf); + } + crypt->ctl_flags = CTL_FLAG_UNUSED; +- return ret; ++ return -ENOMEM; + } + + static int ablk_encrypt(struct ablkcipher_request *req) +@@ -983,7 +937,7 @@ static int hmac_inconsistent(struct scat + break; + + offset += sg->length; +- sg = sg_next(sg); ++ sg = scatterwalk_sg_next(sg); + } + return (start + nbytes > offset + sg->length); + } +@@ -995,11 +949,10 @@ static int aead_perform(struct aead_requ + struct ixp_ctx *ctx = crypto_aead_ctx(tfm); + unsigned ivsize = crypto_aead_ivsize(tfm); + unsigned authsize = crypto_aead_authsize(tfm); +- int ret = -ENOMEM; + struct ix_sa_dir *dir; + struct crypt_ctl *crypt; +- unsigned int cryptlen, nents; +- struct buffer_desc *buf; ++ unsigned int cryptlen; ++ struct buffer_desc *buf, src_hook; + struct aead_ctx *req_ctx = aead_request_ctx(req); + gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? + GFP_KERNEL : GFP_ATOMIC; +@@ -1020,7 +973,7 @@ static int aead_perform(struct aead_requ + } + crypt = get_crypt_desc(); + if (!crypt) +- return ret; ++ return -ENOMEM; + + crypt->data.aead_req = req; + crypt->crypto_ctx = dir->npe_ctx_phys; +@@ -1039,31 +992,27 @@ static int aead_perform(struct aead_requ + BUG(); /* -ENOTSUP because of my lazyness */ + } + +- req_ctx->buffer = dma_pool_alloc(buffer_pool, flags, &crypt->src_buf); +- if (!req_ctx->buffer) +- goto out; +- req_ctx->buffer->phys_addr = 0; + /* ASSOC data */ +- nents = count_sg(req->assoc, req->assoclen); +- req_ctx->assoc_nents = nents; +- dma_map_sg(dev, req->assoc, nents, DMA_TO_DEVICE); +- buf = chainup_buffers(req->assoc, req->assoclen, req_ctx->buffer,flags); ++ buf = chainup_buffers(dev, req->assoc, req->assoclen, &src_hook, ++ flags, DMA_TO_DEVICE); ++ req_ctx->buffer = src_hook.next; ++ crypt->src_buf = src_hook.phys_next; + if (!buf) +- goto unmap_sg_assoc; ++ goto out; + /* IV */ + sg_init_table(&req_ctx->ivlist, 1); + sg_set_buf(&req_ctx->ivlist, iv, ivsize); +- dma_map_sg(dev, &req_ctx->ivlist, 1, DMA_BIDIRECTIONAL); +- buf = chainup_buffers(&req_ctx->ivlist, ivsize, buf, flags); ++ buf = chainup_buffers(dev, &req_ctx->ivlist, ivsize, buf, flags, ++ DMA_BIDIRECTIONAL); + if (!buf) +- goto unmap_sg_iv; ++ goto free_chain; + if (unlikely(hmac_inconsistent(req->src, cryptlen, authsize))) { + /* The 12 hmac bytes are scattered, + * we need to copy them into a safe buffer */ + req_ctx->hmac_virt = dma_pool_alloc(buffer_pool, flags, + &crypt->icv_rev_aes); + if (unlikely(!req_ctx->hmac_virt)) +- goto unmap_sg_iv; ++ goto free_chain; + if (!encrypt) { + scatterwalk_map_and_copy(req_ctx->hmac_virt, + req->src, cryptlen, authsize, 0); +@@ -1073,33 +1022,28 @@ static int aead_perform(struct aead_requ + req_ctx->hmac_virt = NULL; + } + /* Crypt */ +- nents = count_sg(req->src, cryptlen + authsize); +- req_ctx->src_nents = nents; +- dma_map_sg(dev, req->src, nents, DMA_BIDIRECTIONAL); +- buf = chainup_buffers(req->src, cryptlen + authsize, buf, flags); ++ buf = chainup_buffers(dev, req->src, cryptlen + authsize, buf, flags, ++ DMA_BIDIRECTIONAL); + if (!buf) +- goto unmap_sg_src; ++ goto free_hmac_virt; + if (!req_ctx->hmac_virt) { + crypt->icv_rev_aes = buf->phys_addr + buf->buf_len - authsize; + } ++ + crypt->ctl_flags |= CTL_FLAG_PERFORM_AEAD; + qmgr_put_entry(SEND_QID, crypt_virt2phys(crypt)); + BUG_ON(qmgr_stat_overflow(SEND_QID)); + return -EINPROGRESS; +-unmap_sg_src: +- dma_unmap_sg(dev, req->src, req_ctx->src_nents, DMA_BIDIRECTIONAL); ++free_hmac_virt: + if (req_ctx->hmac_virt) { + dma_pool_free(buffer_pool, req_ctx->hmac_virt, + crypt->icv_rev_aes); + } +-unmap_sg_iv: +- dma_unmap_sg(dev, &req_ctx->ivlist, 1, DMA_BIDIRECTIONAL); +-unmap_sg_assoc: +- dma_unmap_sg(dev, req->assoc, req_ctx->assoc_nents, DMA_TO_DEVICE); +- free_buf_chain(req_ctx->buffer, crypt->src_buf); ++free_chain: ++ free_buf_chain(dev, req_ctx->buffer, crypt->src_buf); + out: + crypt->ctl_flags = CTL_FLAG_UNUSED; +- return ret; ++ return -ENOMEM; + } + + static int aead_setup(struct crypto_aead *tfm, unsigned int authsize) diff --git a/queue-2.6.28/exit_notify-kill-the-wrong-capable-check.patch b/queue-2.6.28/exit_notify-kill-the-wrong-capable-check.patch new file mode 100644 index 00000000000..0aa6ddafa6e --- /dev/null +++ b/queue-2.6.28/exit_notify-kill-the-wrong-capable-check.patch @@ -0,0 +1,38 @@ +From 432870dab85a2f69dc417022646cb9a70acf7f94 Mon Sep 17 00:00:00 2001 +From: Oleg Nesterov +Date: Mon, 6 Apr 2009 16:16:02 +0200 +Subject: exit_notify: kill the wrong capable(CAP_KILL) check (CVE-2009-1337) + +From: Oleg Nesterov + +CVE-2009-1337 + +commit 432870dab85a2f69dc417022646cb9a70acf7f94 upstream. + +The CAP_KILL check in exit_notify() looks just wrong, kill it. + +Whatever logic we have to reset ->exit_signal, the malicious user +can bypass it if it execs the setuid application before exiting. + +Signed-off-by: Oleg Nesterov +Acked-by: Serge Hallyn +Acked-by: Roland McGrath +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/exit.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -942,8 +942,7 @@ static void exit_notify(struct task_stru + */ + if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) && + (tsk->parent_exec_id != tsk->real_parent->self_exec_id || +- tsk->self_exec_id != tsk->parent_exec_id) && +- !capable(CAP_KILL)) ++ tsk->self_exec_id != tsk->parent_exec_id)) + tsk->exit_signal = SIGCHLD; + + signal = tracehook_notify_death(tsk, &cookie, group_dead); diff --git a/queue-2.6.28/fix-ptrace-slowness.patch b/queue-2.6.28/fix-ptrace-slowness.patch new file mode 100644 index 00000000000..ba15e0a285e --- /dev/null +++ b/queue-2.6.28/fix-ptrace-slowness.patch @@ -0,0 +1,63 @@ +From 53da1d9456fe7f87a920a78fdbdcf1225d197cb7 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Mon, 23 Mar 2009 16:07:24 +0100 +Subject: fix ptrace slowness + +From: Miklos Szeredi + +commit 53da1d9456fe7f87a920a78fdbdcf1225d197cb7 upstream. + +This patch fixes bug #12208: + + Bug-Entry : http://bugzilla.kernel.org/show_bug.cgi?id=12208 + Subject : uml is very slow on 2.6.28 host + +This turned out to be not a scheduler regression, but an already +existing problem in ptrace being triggered by subtle scheduler +changes. + +The problem is this: + + - task A is ptracing task B + - task B stops on a trace event + - task A is woken up and preempts task B + - task A calls ptrace on task B, which does ptrace_check_attach() + - this calls wait_task_inactive(), which sees that task B is still on the runq + - task A goes to sleep for a jiffy + - ... + +Since UML does lots of the above sequences, those jiffies quickly add +up to make it slow as hell. + +This patch solves this by not rescheduling in read_unlock() after +ptrace_stop() has woken up the tracer. + +Thanks to Oleg Nesterov and Ingo Molnar for the feedback. + +Signed-off-by: Miklos Szeredi +CC: stable@kernel.org +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/signal.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1552,7 +1552,15 @@ static void ptrace_stop(int exit_code, i + read_lock(&tasklist_lock); + if (may_ptrace_stop()) { + do_notify_parent_cldstop(current, CLD_TRAPPED); ++ /* ++ * Don't want to allow preemption here, because ++ * sys_ptrace() needs this task to be inactive. ++ * ++ * XXX: implement read_unlock_no_resched(). ++ */ ++ preempt_disable(); + read_unlock(&tasklist_lock); ++ preempt_enable_no_resched(); + schedule(); + } else { + /* diff --git a/queue-2.6.28/fs-core-fixes.patch b/queue-2.6.28/fs-core-fixes.patch new file mode 100644 index 00000000000..a490b256c0a --- /dev/null +++ b/queue-2.6.28/fs-core-fixes.patch @@ -0,0 +1,210 @@ +From hugh@veritas.com Wed Apr 29 12:45:48 2009 +From: Hugh Dickins +Date: Sat, 25 Apr 2009 17:52:56 +0100 (BST) +Subject: fs core fixes +To: Chris Wright +Cc: Greg Kroah-Hartman , Oleg Nesterov , Joe Malicki , stable@kernel.org, David Howells , Al Viro , Andrew Morton , Linus Torvalds , Alexey Dobriyan , Roland McGrath +Message-ID: + +From: Hugh Dickins + +Please add the following 4 commits to 2.6.27-stable and 2.6.28-stable. +However, there has been a lot of change here between 2.6.28 and 2.6.29: +in particular, fs/exec.c's unsafe_exec() grew into the more complicated +check_unsafe_exec(). So applying the original patches gives too many +rejects: at the bottom is the diffstat and the combined patch required. + +1 +Commit: 53e9309e01277ec99c38e84e0ca16921287cf470 +Author: Hugh Dickins +Date: Sat, 28 Mar 2009 23:16:03 +0000 (+0000) +Subject: compat_do_execve should unshare_files + +2 +Commit: e426b64c412aaa3e9eb3e4b261dc5be0d5a83e78 +Author: Hugh Dickins +Date: Sat, 28 Mar 2009 23:20:19 +0000 (+0000) +Subject: fix setuid sometimes doesn't + +3 +Commit: 7c2c7d993044cddc5010f6f429b100c63bc7dffb +Author: Hugh Dickins +Date: Sat, 28 Mar 2009 23:21:27 +0000 (+0000) +Subject: fix setuid sometimes wouldn't + +4 +Commit: f1191b50ec11c8e2ca766d6d99eb5bb9d2c084a3 +Author: Al Viro +Date: Mon, 30 Mar 2009 11:35:18 +0000 (-0400) +Subject: check_unsafe_exec() doesn't care about signal handlers sharing + +Signed-off-by: Hugh Dickins +Signed-off-by: Greg Kroah-Hartman + +--- + fs/compat.c | 12 +++++++++++- + fs/exec.c | 4 +--- + fs/proc/base.c | 50 ++++++++++++++++---------------------------------- + 3 files changed, 28 insertions(+), 38 deletions(-) + +--- a/fs/compat.c ++++ b/fs/compat.c +@@ -1386,12 +1386,17 @@ int compat_do_execve(char * filename, + { + struct linux_binprm *bprm; + struct file *file; ++ struct files_struct *displaced; + int retval; + ++ retval = unshare_files(&displaced); ++ if (retval) ++ goto out_ret; ++ + retval = -ENOMEM; + bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); + if (!bprm) +- goto out_ret; ++ goto out_files; + + file = open_exec(filename); + retval = PTR_ERR(file); +@@ -1443,6 +1448,8 @@ int compat_do_execve(char * filename, + security_bprm_free(bprm); + acct_update_integrals(current); + free_bprm(bprm); ++ if (displaced) ++ put_files_struct(displaced); + return retval; + } + +@@ -1463,6 +1470,9 @@ out_file: + out_kfree: + free_bprm(bprm); + ++out_files: ++ if (displaced) ++ reset_files_struct(displaced); + out_ret: + return retval; + } +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1084,9 +1084,7 @@ static int unsafe_exec(struct task_struc + { + int unsafe = tracehook_unsafe_exec(p); + +- if (atomic_read(&p->fs->count) > 1 || +- atomic_read(&p->files->count) > 1 || +- atomic_read(&p->sighand->count) > 1) ++ if (atomic_read(&p->fs->count) > 1) + unsafe |= LSM_UNSAFE_SHARE; + + return unsafe; +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -148,15 +148,22 @@ static unsigned int pid_entry_count_dirs + return count; + } + +-static struct fs_struct *get_fs_struct(struct task_struct *task) ++static int get_fs_path(struct task_struct *task, struct path *path, bool root) + { + struct fs_struct *fs; ++ int result = -ENOENT; ++ + task_lock(task); + fs = task->fs; +- if(fs) +- atomic_inc(&fs->count); ++ if (fs) { ++ read_lock(&fs->lock); ++ *path = root ? fs->root : fs->pwd; ++ path_get(path); ++ read_unlock(&fs->lock); ++ result = 0; ++ } + task_unlock(task); +- return fs; ++ return result; + } + + static int get_nr_threads(struct task_struct *tsk) +@@ -174,42 +181,24 @@ static int get_nr_threads(struct task_st + static int proc_cwd_link(struct inode *inode, struct path *path) + { + struct task_struct *task = get_proc_task(inode); +- struct fs_struct *fs = NULL; + int result = -ENOENT; + + if (task) { +- fs = get_fs_struct(task); ++ result = get_fs_path(task, path, 0); + put_task_struct(task); + } +- if (fs) { +- read_lock(&fs->lock); +- *path = fs->pwd; +- path_get(&fs->pwd); +- read_unlock(&fs->lock); +- result = 0; +- put_fs_struct(fs); +- } + return result; + } + + static int proc_root_link(struct inode *inode, struct path *path) + { + struct task_struct *task = get_proc_task(inode); +- struct fs_struct *fs = NULL; + int result = -ENOENT; + + if (task) { +- fs = get_fs_struct(task); ++ result = get_fs_path(task, path, 1); + put_task_struct(task); + } +- if (fs) { +- read_lock(&fs->lock); +- *path = fs->root; +- path_get(&fs->root); +- read_unlock(&fs->lock); +- result = 0; +- put_fs_struct(fs); +- } + return result; + } + +@@ -567,7 +556,6 @@ static int mounts_open_common(struct ino + struct task_struct *task = get_proc_task(inode); + struct nsproxy *nsp; + struct mnt_namespace *ns = NULL; +- struct fs_struct *fs = NULL; + struct path root; + struct proc_mounts *p; + int ret = -EINVAL; +@@ -581,22 +569,16 @@ static int mounts_open_common(struct ino + get_mnt_ns(ns); + } + rcu_read_unlock(); +- if (ns) +- fs = get_fs_struct(task); ++ if (ns && get_fs_path(task, &root, 1) == 0) ++ ret = 0; + put_task_struct(task); + } + + if (!ns) + goto err; +- if (!fs) ++ if (ret) + goto err_put_ns; + +- read_lock(&fs->lock); +- root = fs->root; +- path_get(&root); +- read_unlock(&fs->lock); +- put_fs_struct(fs); +- + ret = -ENOMEM; + p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); + if (!p) diff --git a/queue-2.6.28/pci-fix-incorrect-mask-of-pm-no_soft_reset-bit.patch b/queue-2.6.28/pci-fix-incorrect-mask-of-pm-no_soft_reset-bit.patch new file mode 100644 index 00000000000..5016a48688f --- /dev/null +++ b/queue-2.6.28/pci-fix-incorrect-mask-of-pm-no_soft_reset-bit.patch @@ -0,0 +1,29 @@ +From 998dd7c719f62dcfa91d7bf7f4eb9c160e03d817 Mon Sep 17 00:00:00 2001 +From: Yu Zhao +Date: Wed, 25 Feb 2009 13:15:52 +0800 +Subject: PCI: fix incorrect mask of PM No_Soft_Reset bit + +From: Yu Zhao + +commit 998dd7c719f62dcfa91d7bf7f4eb9c160e03d817 upstream. + +Reviewed-by: Matthew Wilcox +Signed-off-by: Yu Zhao +Signed-off-by: Jesse Barnes +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/pci_regs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/linux/pci_regs.h ++++ b/include/linux/pci_regs.h +@@ -234,7 +234,7 @@ + #define PCI_PM_CAP_PME_SHIFT 11 /* Start of the PME Mask in PMC */ + #define PCI_PM_CTRL 4 /* PM control and status register */ + #define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */ +-#define PCI_PM_CTRL_NO_SOFT_RESET 0x0004 /* No reset for D3hot->D0 */ ++#define PCI_PM_CTRL_NO_SOFT_RESET 0x0008 /* No reset for D3hot->D0 */ + #define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */ + #define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */ + #define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */ diff --git a/queue-2.6.28/powerpc-sanitize-stack-pointer-in-signal-handling-code.patch b/queue-2.6.28/powerpc-sanitize-stack-pointer-in-signal-handling-code.patch new file mode 100644 index 00000000000..74223f216f8 --- /dev/null +++ b/queue-2.6.28/powerpc-sanitize-stack-pointer-in-signal-handling-code.patch @@ -0,0 +1,126 @@ +From jwboyer@linux.vnet.ibm.com Wed Apr 29 12:31:40 2009 +From: Josh Boyer +Date: Tue, 28 Apr 2009 11:14:01 -0400 +Subject: powerpc: Sanitize stack pointer in signal handling code +To: stable@kernel.org +Cc: benh@kernel.crashing.org +Message-ID: <20090428151401.GB5281@yoda.jdub.homelinux.org> +Content-Disposition: inline + +From: Josh Boyer + +This has been backported to 2.6.28.x from commit efbda86098 in Linus' tree + +On powerpc64 machines running 32-bit userspace, we can get garbage bits in the +stack pointer passed into the kernel. Most places handle this correctly, but +the signal handling code uses the passed value directly for allocating signal +stack frames. + +This fixes the issue by introducing a get_clean_sp function that returns a +sanitized stack pointer. For 32-bit tasks on a 64-bit kernel, the stack +pointer is masked correctly. In all other cases, the stack pointer is simply +returned. + +Additionally, we pass an 'is_32' parameter to get_sigframe now in order to +get the properly sanitized stack. The callers are know to be 32 or 64-bit +statically. + +Signed-off-by: Josh Boyer +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/include/asm/processor.h | 19 +++++++++++++++++++ + arch/powerpc/kernel/signal.c | 4 ++-- + arch/powerpc/kernel/signal.h | 2 +- + arch/powerpc/kernel/signal_32.c | 4 ++-- + arch/powerpc/kernel/signal_64.c | 2 +- + 5 files changed, 25 insertions(+), 6 deletions(-) + +--- a/arch/powerpc/include/asm/processor.h ++++ b/arch/powerpc/include/asm/processor.h +@@ -309,6 +309,25 @@ static inline void prefetchw(const void + #define HAVE_ARCH_PICK_MMAP_LAYOUT + #endif + ++#ifdef CONFIG_PPC64 ++static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32) ++{ ++ unsigned long sp; ++ ++ if (is_32) ++ sp = regs->gpr[1] & 0x0ffffffffUL; ++ else ++ sp = regs->gpr[1]; ++ ++ return sp; ++} ++#else ++static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32) ++{ ++ return regs->gpr[1]; ++} ++#endif ++ + #endif /* __KERNEL__ */ + #endif /* __ASSEMBLY__ */ + #endif /* _ASM_POWERPC_PROCESSOR_H */ +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -836,7 +836,7 @@ int handle_rt_signal32(unsigned long sig + + /* Set up Signal Frame */ + /* Put a Real Time Context onto stack */ +- rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf)); ++ rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf), 1); + addr = rt_sf; + if (unlikely(rt_sf == NULL)) + goto badframe; +@@ -1182,7 +1182,7 @@ int handle_signal32(unsigned long sig, s + unsigned long newsp = 0; + + /* Set up Signal Frame */ +- frame = get_sigframe(ka, regs, sizeof(*frame)); ++ frame = get_sigframe(ka, regs, sizeof(*frame), 1); + if (unlikely(frame == NULL)) + goto badframe; + sc = (struct sigcontext __user *) &frame->sctx; +--- a/arch/powerpc/kernel/signal_64.c ++++ b/arch/powerpc/kernel/signal_64.c +@@ -402,7 +402,7 @@ int handle_rt_signal64(int signr, struct + unsigned long newsp = 0; + long err = 0; + +- frame = get_sigframe(ka, regs, sizeof(*frame)); ++ frame = get_sigframe(ka, regs, sizeof(*frame), 0); + if (unlikely(frame == NULL)) + goto badframe; + +--- a/arch/powerpc/kernel/signal.c ++++ b/arch/powerpc/kernel/signal.c +@@ -26,12 +26,12 @@ int show_unhandled_signals = 0; + * Allocate space for the signal frame + */ + void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, +- size_t frame_size) ++ size_t frame_size, int is_32) + { + unsigned long oldsp, newsp; + + /* Default to using normal stack */ +- oldsp = regs->gpr[1]; ++ oldsp = get_clean_sp(regs, is_32); + + /* Check for alt stack */ + if ((ka->sa.sa_flags & SA_ONSTACK) && +--- a/arch/powerpc/kernel/signal.h ++++ b/arch/powerpc/kernel/signal.h +@@ -15,7 +15,7 @@ + extern void do_signal(struct pt_regs *regs, unsigned long thread_info_flags); + + extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, +- size_t frame_size); ++ size_t frame_size, int is_32); + extern void restore_sigmask(sigset_t *set); + + extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, diff --git a/queue-2.6.28/series b/queue-2.6.28/series index b15f41052e4..24e1f8711fb 100644 --- a/queue-2.6.28/series +++ b/queue-2.6.28/series @@ -76,3 +76,12 @@ kvm-vmx-flush-volatile-msrs-before-emulating-rdmsr.patch ath9k-implement-io-serialization.patch ath9k-ar9280-pci-devices-must-serialize-io-as-well.patch md-fix-deadlock-when-stopping-arrays.patch +block-include-empty-disks-in-proc-diskstats.patch +powerpc-sanitize-stack-pointer-in-signal-handling-code.patch +fs-core-fixes.patch +fix-ptrace-slowness.patch +crypto-ixp4xx-fix-handling-of-chained-sg-buffers.patch +pci-fix-incorrect-mask-of-pm-no_soft_reset-bit.patch +exit_notify-kill-the-wrong-capable-check.patch +b44-use-kernel-dma-addresses-for-the-kernel-dma-api.patch +thinkpad-acpi-fix-led-blinking-through-timer-trigger.patch diff --git a/queue-2.6.28/thinkpad-acpi-fix-led-blinking-through-timer-trigger.patch b/queue-2.6.28/thinkpad-acpi-fix-led-blinking-through-timer-trigger.patch new file mode 100644 index 00000000000..840b2a4865a --- /dev/null +++ b/queue-2.6.28/thinkpad-acpi-fix-led-blinking-through-timer-trigger.patch @@ -0,0 +1,132 @@ +From 75bd3bf2ade9d548be0d2bde60b5ee0fdce0b127 Mon Sep 17 00:00:00 2001 +From: Henrique de Moraes Holschuh +Date: Tue, 14 Apr 2009 02:44:11 +0000 +Subject: thinkpad-acpi: fix LED blinking through timer trigger + +From: Henrique de Moraes Holschuh + +commit 75bd3bf2ade9d548be0d2bde60b5ee0fdce0b127 upstream. + +The set_blink hook code in the LED subdriver would never manage to get +a LED to blink, and instead it would just turn it on. The consequence +of this is that the "timer" trigger would not cause the LED to blink +if given default parameters. + +This problem exists since 2.6.26-rc1. + +To fix it, switch the deferred LED work handling to use the +thinkpad-acpi-specific LED status (off/on/blink) directly. + +This also makes the code easier to read, and to extend later. + +Signed-off-by: Henrique de Moraes Holschuh +Cc: stable@kernel.org +Signed-off-by: Len Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/thinkpad_acpi.c | 41 +++++++++++++++++++---------------------- + 1 file changed, 19 insertions(+), 22 deletions(-) + +--- a/drivers/misc/thinkpad_acpi.c ++++ b/drivers/misc/thinkpad_acpi.c +@@ -281,11 +281,17 @@ static u32 dbg_level; + + static struct workqueue_struct *tpacpi_wq; + ++enum led_status_t { ++ TPACPI_LED_OFF = 0, ++ TPACPI_LED_ON, ++ TPACPI_LED_BLINK, ++}; ++ + /* Special LED class that can defer work */ + struct tpacpi_led_classdev { + struct led_classdev led_classdev; + struct work_struct work; +- enum led_brightness new_brightness; ++ enum led_status_t new_state; + unsigned int led; + }; + +@@ -3489,7 +3495,7 @@ static void light_set_status_worker(stru + container_of(work, struct tpacpi_led_classdev, work); + + if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) +- light_set_status((data->new_brightness != LED_OFF)); ++ light_set_status((data->new_state != TPACPI_LED_OFF)); + } + + static void light_sysfs_set(struct led_classdev *led_cdev, +@@ -3499,7 +3505,8 @@ static void light_sysfs_set(struct led_c + container_of(led_cdev, + struct tpacpi_led_classdev, + led_classdev); +- data->new_brightness = brightness; ++ data->new_state = (brightness != LED_OFF) ? ++ TPACPI_LED_ON : TPACPI_LED_OFF; + queue_work(tpacpi_wq, &data->work); + } + +@@ -4006,12 +4013,6 @@ enum { /* For TPACPI_LED_OLD */ + TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */ + }; + +-enum led_status_t { +- TPACPI_LED_OFF = 0, +- TPACPI_LED_ON, +- TPACPI_LED_BLINK, +-}; +- + static enum led_access_mode led_supported; + + TPACPI_HANDLE(led, ec, "SLED", /* 570 */ +@@ -4105,23 +4106,13 @@ static int led_set_status(const unsigned + return rc; + } + +-static void led_sysfs_set_status(unsigned int led, +- enum led_brightness brightness) +-{ +- led_set_status(led, +- (brightness == LED_OFF) ? +- TPACPI_LED_OFF : +- (tpacpi_led_state_cache[led] == TPACPI_LED_BLINK) ? +- TPACPI_LED_BLINK : TPACPI_LED_ON); +-} +- + static void led_set_status_worker(struct work_struct *work) + { + struct tpacpi_led_classdev *data = + container_of(work, struct tpacpi_led_classdev, work); + + if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) +- led_sysfs_set_status(data->led, data->new_brightness); ++ led_set_status(data->led, data->new_state); + } + + static void led_sysfs_set(struct led_classdev *led_cdev, +@@ -4130,7 +4121,13 @@ static void led_sysfs_set(struct led_cla + struct tpacpi_led_classdev *data = container_of(led_cdev, + struct tpacpi_led_classdev, led_classdev); + +- data->new_brightness = brightness; ++ if (brightness == LED_OFF) ++ data->new_state = TPACPI_LED_OFF; ++ else if (tpacpi_led_state_cache[data->led] != TPACPI_LED_BLINK) ++ data->new_state = TPACPI_LED_ON; ++ else ++ data->new_state = TPACPI_LED_BLINK; ++ + queue_work(tpacpi_wq, &data->work); + } + +@@ -4148,7 +4145,7 @@ static int led_sysfs_blink_set(struct le + } else if ((*delay_on != 500) || (*delay_off != 500)) + return -EINVAL; + +- data->new_brightness = TPACPI_LED_BLINK; ++ data->new_state = TPACPI_LED_BLINK; + queue_work(tpacpi_wq, &data->work); + + return 0;