2007-11-05 18:12:55

by Greg KH

[permalink] [raw]
Subject: Linux 2.6.22.12

We (the -stable team) are announcing the release of the 2.6.22.12 kernel.
It fixes a number of reported bugs, and any user of the 2.6.22 series is
encouraged to upgrade.

I'll also be replying to this message with a copy of the patch between
2.6.22.11 and 2.6.22.12

The updated 2.6.22.y git tree can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.22.y.git
and can be browsed at the normal kernel.org git web browser:
http://git.kernel.org/?p=linux/kernel/git/stable/linux-2.6.22.y.git;a=summary

thanks,

greg k-h

--------

Makefile | 2 -
arch/i386/kernel/io_apic.c | 7 +++--
arch/x86_64/kernel/io_apic.c | 7 +++--
arch/x86_64/mm/init.c | 5 ---
arch/x86_64/mm/pageattr.c | 9 +++++-
drivers/infiniband/core/uverbs_cmd.c | 8 ++++-
drivers/md/dm-exception-store.c | 48 +++++++++++++++++++++++++++++++----
fs/minix/itree_v1.c | 9 +++++-
fs/minix/itree_v2.c | 9 +++++-
include/linux/bootmem.h | 1
kernel/irq/chip.c | 5 ---
kernel/irq/resend.c | 7 ++++-
kernel/params.c | 8 +++++
mm/sparse.c | 11 --------
14 files changed, 95 insertions(+), 41 deletions(-)

Summary of changes from v2.6.22.11 to v2.6.22.12
================================================

Dave Young (1):
param_sysfs_builtin memchr argument fix

Eric Sandeen (1):
minixfs: limit minixfs printks on corrupted dir i_size (CVE-2006-6058)

Greg Kroah-Hartman (1):
Linux 2.6.22.12

Ingo Molnar (1):
x86: fix global_flush_tlb() bug

Linus Torvalds (1):
Revert "x86_64: allocate sparsemem memmap above 4G"

Milan Broz (1):
dm snapshot: fix invalidation deadlock

Roland Dreier (1):
IB/uverbs: Fix checking of userspace object ownership

Thomas Gleixner (3):
genirq: cleanup mismerge artifact
genirq: suppress resend of level interrupts
genirq: mark io_apic level interrupts to avoid resend


2007-11-05 18:16:21

by Greg KH

[permalink] [raw]
Subject: Re: Linux 2.6.22.12

diff --git a/Makefile b/Makefile
index 8874c9b..b55f9bf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 22
-EXTRAVERSION = .11
+EXTRAVERSION = .12
NAME = Holy Dancing Manatees, Batman!

# *DOCUMENTATION*
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 7f8b7af..97ba305 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -1275,12 +1275,15 @@ static struct irq_chip ioapic_chip;
static void ioapic_register_intr(int irq, int vector, unsigned long trigger)
{
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
- trigger == IOAPIC_LEVEL)
+ trigger == IOAPIC_LEVEL) {
+ irq_desc[irq].status |= IRQ_LEVEL;
set_irq_chip_and_handler_name(irq, &ioapic_chip,
handle_fasteoi_irq, "fasteoi");
- else
+ } else {
+ irq_desc[irq].status &= ~IRQ_LEVEL;
set_irq_chip_and_handler_name(irq, &ioapic_chip,
handle_edge_irq, "edge");
+ }
set_intr_gate(vector, interrupt[irq]);
}

diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 1c6c6f7..34d7cde 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -774,12 +774,15 @@ static struct irq_chip ioapic_chip;

static void ioapic_register_intr(int irq, unsigned long trigger)
{
- if (trigger)
+ if (trigger) {
+ irq_desc[irq].status |= IRQ_LEVEL;
set_irq_chip_and_handler_name(irq, &ioapic_chip,
handle_fasteoi_irq, "fasteoi");
- else
+ } else {
+ irq_desc[irq].status &= ~IRQ_LEVEL;
set_irq_chip_and_handler_name(irq, &ioapic_chip,
handle_edge_irq, "edge");
+ }
}

static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index 9a0e98a..b7e514e 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -769,8 +769,3 @@ int in_gate_area_no_task(unsigned long addr)
return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
}

-void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
-{
- return __alloc_bootmem_core(pgdat->bdata, size,
- SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0);
-}
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c
index 9148f4a..7cd5254 100644
--- a/arch/x86_64/mm/pageattr.c
+++ b/arch/x86_64/mm/pageattr.c
@@ -227,9 +227,14 @@ void global_flush_tlb(void)
struct page *pg, *next;
struct list_head l;

- down_read(&init_mm.mmap_sem);
+ /*
+ * Write-protect the semaphore, to exclude two contexts
+ * doing a list_replace_init() call in parallel and to
+ * exclude new additions to the deferred_pages list:
+ */
+ down_write(&init_mm.mmap_sem);
list_replace_init(&deferred_pages, &l);
- up_read(&init_mm.mmap_sem);
+ up_write(&init_mm.mmap_sem);

flush_map(&l);

diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 01d7008..495c803 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -147,8 +147,12 @@ static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,

spin_lock(&ib_uverbs_idr_lock);
uobj = idr_find(idr, id);
- if (uobj)
- kref_get(&uobj->ref);
+ if (uobj) {
+ if (uobj->context == context)
+ kref_get(&uobj->ref);
+ else
+ uobj = NULL;
+ }
spin_unlock(&ib_uverbs_idr_lock);

return uobj;
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 4264f69..5c7569c 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -125,6 +125,8 @@ struct pstore {
uint32_t callback_count;
struct commit_callback *callbacks;
struct dm_io_client *io_client;
+
+ struct workqueue_struct *metadata_wq;
};

static inline unsigned int sectors_to_pages(unsigned int sectors)
@@ -156,10 +158,24 @@ static void free_area(struct pstore *ps)
ps->area = NULL;
}

+struct mdata_req {
+ struct io_region *where;
+ struct dm_io_request *io_req;
+ struct work_struct work;
+ int result;
+};
+
+static void do_metadata(struct work_struct *work)
+{
+ struct mdata_req *req = container_of(work, struct mdata_req, work);
+
+ req->result = dm_io(req->io_req, 1, req->where, NULL);
+}
+
/*
* Read or write a chunk aligned and sized block of data from a device.
*/
-static int chunk_io(struct pstore *ps, uint32_t chunk, int rw)
+static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata)
{
struct io_region where = {
.bdev = ps->snap->cow->bdev,
@@ -173,8 +189,23 @@ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw)
.client = ps->io_client,
.notify.fn = NULL,
};
+ struct mdata_req req;
+
+ if (!metadata)
+ return dm_io(&io_req, 1, &where, NULL);

- return dm_io(&io_req, 1, &where, NULL);
+ req.where = &where;
+ req.io_req = &io_req;
+
+ /*
+ * Issue the synchronous I/O from a different thread
+ * to avoid generic_make_request recursion.
+ */
+ INIT_WORK(&req.work, do_metadata);
+ queue_work(ps->metadata_wq, &req.work);
+ flush_workqueue(ps->metadata_wq);
+
+ return req.result;
}

/*
@@ -189,7 +220,7 @@ static int area_io(struct pstore *ps, uint32_t area, int rw)
/* convert a metadata area index to a chunk index */
chunk = 1 + ((ps->exceptions_per_area + 1) * area);

- r = chunk_io(ps, chunk, rw);
+ r = chunk_io(ps, chunk, rw, 0);
if (r)
return r;

@@ -230,7 +261,7 @@ static int read_header(struct pstore *ps, int *new_snapshot)
if (r)
return r;

- r = chunk_io(ps, 0, READ);
+ r = chunk_io(ps, 0, READ, 1);
if (r)
goto bad;

@@ -292,7 +323,7 @@ static int write_header(struct pstore *ps)
dh->version = cpu_to_le32(ps->version);
dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);

- return chunk_io(ps, 0, WRITE);
+ return chunk_io(ps, 0, WRITE, 1);
}

/*
@@ -409,6 +440,7 @@ static void persistent_destroy(struct exception_store *store)
{
struct pstore *ps = get_info(store);

+ destroy_workqueue(ps->metadata_wq);
dm_io_client_destroy(ps->io_client);
vfree(ps->callbacks);
free_area(ps);
@@ -589,6 +621,12 @@ int dm_create_persistent(struct exception_store *store)
atomic_set(&ps->pending_count, 0);
ps->callbacks = NULL;

+ ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
+ if (!ps->metadata_wq) {
+ DMERR("couldn't start header metadata update thread");
+ return -ENOMEM;
+ }
+
store->destroy = persistent_destroy;
store->read_metadata = persistent_read_metadata;
store->prepare_exception = persistent_prepare;
diff --git a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c
index 1a5f3bf..82d6554 100644
--- a/fs/minix/itree_v1.c
+++ b/fs/minix/itree_v1.c
@@ -23,11 +23,16 @@ static inline block_t *i_data(struct inode *inode)
static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
{
int n = 0;
+ char b[BDEVNAME_SIZE];

if (block < 0) {
- printk("minix_bmap: block<0\n");
+ printk("MINIX-fs: block_to_path: block %ld < 0 on dev %s\n",
+ block, bdevname(inode->i_sb->s_bdev, b));
} else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) {
- printk("minix_bmap: block>big\n");
+ if (printk_ratelimit())
+ printk("MINIX-fs: block_to_path: "
+ "block %ld too big on dev %s\n",
+ block, bdevname(inode->i_sb->s_bdev, b));
} else if (block < 7) {
offsets[n++] = block;
} else if ((block -= 7) < 512) {
diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c
index ad8f0de..f230109 100644
--- a/fs/minix/itree_v2.c
+++ b/fs/minix/itree_v2.c
@@ -23,12 +23,17 @@ static inline block_t *i_data(struct inode *inode)
static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
{
int n = 0;
+ char b[BDEVNAME_SIZE];
struct super_block *sb = inode->i_sb;

if (block < 0) {
- printk("minix_bmap: block<0\n");
+ printk("MINIX-fs: block_to_path: block %ld < 0 on dev %s\n",
+ block, bdevname(sb->s_bdev, b));
} else if (block >= (minix_sb(inode->i_sb)->s_max_size/sb->s_blocksize)) {
- printk("minix_bmap: block>big\n");
+ if (printk_ratelimit())
+ printk("MINIX-fs: block_to_path: "
+ "block %ld too big on dev %s\n",
+ block, bdevname(sb->s_bdev, b));
} else if (block < 7) {
offsets[n++] = block;
} else if ((block -= 7) < 256) {
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index c83534e..0365ec9 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -59,7 +59,6 @@ extern void *__alloc_bootmem_core(struct bootmem_data *bdata,
unsigned long align,
unsigned long goal,
unsigned long limit);
-extern void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size);

#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
extern void reserve_bootmem(unsigned long addr, unsigned long size);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 615ce97..f1a73f0 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -352,13 +352,10 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
* keep it masked and get out of here
*/
action = desc->action;
- if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
- desc->status |= IRQ_PENDING;
+ if (unlikely(!action || (desc->status & IRQ_DISABLED)))
goto out_unlock;
- }

desc->status |= IRQ_INPROGRESS;
- desc->status &= ~IRQ_PENDING;
spin_unlock(&desc->lock);

action_ret = handle_IRQ_event(irq, action);
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index 5bfeaed..a804679 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -62,7 +62,12 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq)
*/
desc->chip->enable(irq);

- if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+ /*
+ * We do not resend level type interrupts. Level type
+ * interrupts are resent by hardware when they are still
+ * active.
+ */
+ if ((status & (IRQ_LEVEL | IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
desc->status = (status & ~IRQ_PENDING) | IRQ_REPLAY;

if (!desc->chip || !desc->chip->retrigger ||
diff --git a/kernel/params.c b/kernel/params.c
index e61c46c..8e8ca8f 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -591,11 +591,17 @@ static void __init param_sysfs_builtin(void)

for (i=0; i < __stop___param - __start___param; i++) {
char *dot;
+ size_t kplen;

kp = &__start___param[i];
+ kplen = strlen(kp->name);

/* We do not handle args without periods. */
- dot = memchr(kp->name, '.', MAX_KBUILD_MODNAME);
+ if (kplen > MAX_KBUILD_MODNAME) {
+ DEBUGP("kernel parameter name is too long: %s\n", kp->name);
+ continue;
+ }
+ dot = memchr(kp->name, '.', kplen);
if (!dot) {
DEBUGP("couldn't find period in %s\n", kp->name);
continue;
diff --git a/mm/sparse.c b/mm/sparse.c
index e03b39f..fdc1454 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -209,12 +209,6 @@ static int __meminit sparse_init_one_section(struct mem_section *ms,
return 1;
}

-__attribute__((weak))
-void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
-{
- return NULL;
-}
-
static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
{
struct page *map;
@@ -225,11 +219,6 @@ static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
if (map)
return map;

- map = alloc_bootmem_high_node(NODE_DATA(nid),
- sizeof(struct page) * PAGES_PER_SECTION);
- if (map)
- return map;
-
map = alloc_bootmem_node(NODE_DATA(nid),
sizeof(struct page) * PAGES_PER_SECTION);
if (map)

2007-11-21 03:45:27

by Tomasz Kłoczko

[permalink] [raw]
Subject: null pointer dereference during restart autofs (was: Linux 2.6.22.12)


BUG: unable to handle kernel NULL pointer dereference at virtual address 00000014
printing eip:
c047102c
*pdpt = 0000000024e2c001
*pde = 0000000000000000
Oops: 0002 [#1]
SMP
Modules linked in: nfsd exportfs iptable_mangle iptable_nat nf_nat nf_conntrack_ipv4 ipt_LOG ipt_connlimit nf_conntrack nfnetlink xt_tcpudp iptable_filter ip_tables x_tables nfs lockd nfs_acl ipv6 autofs4 sunrpc binfmt_misc quota_v2 dm_mirror dm_mod video sbs button dock battery ac parport_pc lp parport floppy nvram sr_mod cdrom joydev ata_generic sg e752x_edac edac_mc ata_piix pata_sil680 ehci_hcd libata iTCO_wdt iTCO_vendor_support e1000 uhci_hcd rtc_cmos rtc_core serio_raw rtc_lib scsi_wait_scan megaraid_mbox megaraid_mm sd_mod scsi_mod ext3 jbd mbcache
CPU: 1
EIP: 0060:[<c047102c>] Not tainted VLI
EFLAGS: 00010246 (2.6.22.12-1 #1)
EIP is at fput+0x2/0x15
eax: 00000000 ebx: 00000000 ecx: 00009362 edx: 00000000
esi: 00000000 edi: cc6c0dc0 ebp: e342b480 esp: cf231f30
ds: 007b es: 007b fs: 00d8 gs: 0033 ss: 0068
Process automount (pid: 15112, ti=cf230000 task=dff84870 task.ti=cf230000)
Stack: f8b60885 80049370 00000000 00000000 cc6c0dc0 f8b5f99f f625f588 f8b5f896
e342b480 f8b5f896 00000000 c047a48f 00000000 00000000 00000000 00009362
00000000 e342b480 00000000 00000004 c047a6de 00000002 c047a014 00000000
Call Trace:
[<f8b60885>] autofs4_catatonic_mode+0x5a/0x66 [autofs4]
[<f8b5f99f>] autofs4_root_ioctl+0x109/0x226 [autofs4]
[<f8b5f896>] autofs4_root_ioctl+0x0/0x226 [autofs4]
[<f8b5f896>] autofs4_root_ioctl+0x0/0x226 [autofs4]
[<c047a48f>] do_ioctl+0x87/0x9f
[<c047a6de>] vfs_ioctl+0x237/0x249
[<c047a014>] do_fcntl+0xd2/0x249
[<c047a73c>] sys_ioctl+0x4c/0x64
[<c0404cc2>] sysenter_past_esp+0x5f/0x85
=======================
Code: 7c 24 08 00 74 1b 8b 44 24 08 c7 40 64 00 00 00 00 8b 44 24 08 83 c4
0c 5b 5e 5f 5d e9 7c 16 01 00 83 c4 0c 5b 5e 5f 5d c3 89 c2 <f0> ff 48 14
0f 94 c0 84 c0 74 07 89 d0 e9 9c fe ff ff c3 56 85
EIP: [<c047102c>] fput+0x2/0x15 SS:ESP 0068:cf231f30

kloczek
--
-----------------------------------------------------------
*Ludzie nie maj? problem?w, tylko sobie sami je stwarzaj?*
-----------------------------------------------------------
Tomasz K?oczko | *e-mail: [email protected]*

2007-11-22 00:52:00

by Greg KH

[permalink] [raw]
Subject: Re: [stable] null pointer dereference during restart autofs (was: Linux 2.6.22.12)

On Wed, Nov 21, 2007 at 04:45:10AM +0100, Tomasz K?oczko wrote:
>
> BUG: unable to handle kernel NULL pointer dereference at virtual address
> 00000014

Did this happen with older versions of 2.6.22.y?

Have you asked the autofs people about this?

thanks,

greg k-h