diff --git a/Makefile b/Makefile
index fd6884d..9a097de 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 33
-EXTRAVERSION =
+EXTRAVERSION = .7
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 79bb602..ea17eb0 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -237,14 +237,14 @@ static int find_matching_ucodes (void)
}
total_size = get_totalsize(&mc_header);
- if ((cursor + total_size > user_buffer_size) || (total_size < DEFAULT_UCODE_TOTALSIZE)) {
+ if (cursor + total_size > user_buffer_size) {
printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
error = -EINVAL;
goto out;
}
data_size = get_datasize(&mc_header);
- if ((data_size + MC_HEADER_SIZE > total_size) || (data_size < DEFAULT_UCODE_DATASIZE)) {
+ if (data_size + MC_HEADER_SIZE > total_size) {
printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
error = -EINVAL;
goto out;
@@ -438,11 +438,6 @@ static ssize_t microcode_write (struct file *file, const char *buf, size_t len,
{
ssize_t ret;
- if (len < DEFAULT_UCODE_TOTALSIZE) {
- printk(KERN_ERR "microcode: not enough data\n");
- return -EINVAL;
- }
-
if ((len >> PAGE_SHIFT) > num_physpages) {
printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages);
return -EINVAL;
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 34125f6..340a66a 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -1705,6 +1705,8 @@ ppc970_setup_hid:
mfspr r0,SPRN_HID0
li r11,5 /* clear DOZE and SLEEP */
rldimi r0,r11,52,8 /* and set NAP and DPM */
+ li r11,0
+ rldimi r0,r11,32,31 /* clear EN_ATTN */
mtspr SPRN_HID0,r0
mfspr r0,SPRN_HID0
mfspr r0,SPRN_HID0
diff --git a/arch/s390/lib/uaccess.S b/arch/s390/lib/uaccess.S
index 1490bc6..6207032 100644
--- a/arch/s390/lib/uaccess.S
+++ b/arch/s390/lib/uaccess.S
@@ -19,8 +19,8 @@ __copy_from_user_asm:
sacf 512
0: mvcle %r2,%r4,0
jo 0b
-1: sacf 0
lr %r2,%r5
+1: sacf 0
br %r14
2: lhi %r1,-4096
lr %r3,%r4
@@ -28,17 +28,23 @@ __copy_from_user_asm:
nr %r3,%r1 # %r3 = (%r4 + 4096) & -4096
slr %r3,%r4 # %r3 = #bytes to next user page boundary
clr %r5,%r3 # copy crosses next page boundary ?
- jnh 1b # no, this page fauled
+ jnh 4f # no, this page faulted
# The page after the current user page might have faulted.
- # We cant't find out which page because the program check handler
- # might have callled schedule, destroying all lowcore information.
+ # We can't find out which page because the program check handler
+ # might have called schedule, destroying all lowcore information.
# We retry with the shortened length.
3: mvcle %r2,%r4,0
jo 3b
+4: lr %r1,%r5 # pad remaining bytes with 0
+ lr %r3,%r5
+ slr %r5,%r5
+5: mvcle %r2,%r4,0
+ jo 5b
+ lr %r2,%r1
j 1b
.section __ex_table,"a"
.long 0b,2b
- .long 3b,1b
+ .long 3b,4b
.previous
.align 4
diff --git a/arch/s390x/lib/uaccess.S b/arch/s390x/lib/uaccess.S
index 7e90f20..9916621 100644
--- a/arch/s390x/lib/uaccess.S
+++ b/arch/s390x/lib/uaccess.S
@@ -19,8 +19,8 @@ __copy_from_user_asm:
sacf 512
0: mvcle %r2,%r4,0
jo 0b
-1: sacf 0
lgr %r2,%r5
+1: sacf 0
br %r14
2: lghi %r1,-4096
lgr %r3,%r4
@@ -28,17 +28,23 @@ __copy_from_user_asm:
ngr %r3,%r1 # %r3 = (%r4 + 4096) & -4096
slgr %r3,%r4 # %r3 = #bytes to next user page boundary
clgr %r5,%r3 # copy crosses next page boundary ?
- jnh 1b # no, this page fauled
+ jnh 4f # no, this page faulted
# The page after the current user page might have faulted.
- # We cant't find out which page because the program check handler
- # might have callled schedule, destroying all lowcore information.
+ # We can't find out which page because the program check handler
+ # might have called schedule, destroying all lowcore information.
# We retry with the shortened length.
3: mvcle %r2,%r4,0
jo 3b
+4: lgr %r1,%r5 # pad remaining bytes with 0
+ lgr %r3,%r5
+ slgr %r5,%r5
+5: mvcle %r2,%r4,0
+ jo 5b
+ lgr %r2,%r1
j 1b
.section __ex_table,"a"
.quad 0b,2b
- .quad 3b,1b
+ .quad 3b,4b
.previous
.align 4
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 1c08204..f5058fe 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -297,6 +297,7 @@ EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL_NOVERS(memchr);
EXPORT_SYMBOL_NOVERS(__ashrdi3);
EXPORT_SYMBOL_NOVERS(__ashldi3);
EXPORT_SYMBOL_NOVERS(__lshrdi3);
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 0f1f31f..40accab 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -359,6 +359,7 @@ EXPORT_SYMBOL_NOVERS(__ret_efault);
/* No version information on these, as gcc produces such symbols. */
EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memchr);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memmove);
diff --git a/arch/x86_64/lib/delay.c b/arch/x86_64/lib/delay.c
index cc845d2..91345ee 100644
--- a/arch/x86_64/lib/delay.c
+++ b/arch/x86_64/lib/delay.c
@@ -19,7 +19,7 @@
void __delay(unsigned long loops)
{
- unsigned long bclock, now;
+ unsigned bclock, now;
rdtscl(bclock);
do
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 6ab56eb..9b03eda 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -147,6 +147,15 @@ static int ecb_encrypt(struct crypto_tfm *tfm,
ecb_process, 1, NULL);
}
+static int ecb_encrypt_iv(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes, u8 *iv)
+{
+ ecb_encrypt(tfm, dst, src, nbytes);
+ return -ENOSYS;
+}
+
static int ecb_decrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
@@ -157,6 +166,15 @@ static int ecb_decrypt(struct crypto_tfm *tfm,
ecb_process, 1, NULL);
}
+static int ecb_decrypt_iv(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes, u8 *iv)
+{
+ ecb_decrypt(tfm, dst, src, nbytes);
+ return -ENOSYS;
+}
+
static int cbc_encrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
@@ -197,11 +215,20 @@ static int cbc_decrypt_iv(struct crypto_tfm *tfm,
cbc_process, 0, iv);
}
+/*
+ * nocrypt*() zeroize the destination buffer to make sure we don't leak
+ * uninitialized memory contents if the caller ignores the return value.
+ * This is bad since the data in the source buffer is unused and may be
+ * lost, but an infoleak would be even worse. The performance cost of
+ * memset() is irrelevant since a well-behaved caller would not bump into
+ * the error repeatedly.
+ */
static int nocrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
+ memset(dst, 0, nbytes);
return -ENOSYS;
}
@@ -210,6 +237,7 @@ static int nocrypt_iv(struct crypto_tfm *tfm,
struct scatterlist *src,
unsigned int nbytes, u8 *iv)
{
+ memset(dst, 0, nbytes);
return -ENOSYS;
}
@@ -235,6 +263,11 @@ int crypto_init_cipher_ops(struct crypto_tfm *tfm)
case CRYPTO_TFM_MODE_ECB:
ops->cit_encrypt = ecb_encrypt;
ops->cit_decrypt = ecb_decrypt;
+/* These should have been nocrypt_iv, but patch-cryptoloop-jari-2.4.22.0
+ * (and its other revisions) directly calls the *_iv() functions even in
+ * ECB mode and ignores their return value. */
+ ops->cit_encrypt_iv = ecb_encrypt_iv;
+ ops->cit_decrypt_iv = ecb_decrypt_iv;
break;
case CRYPTO_TFM_MODE_CBC:
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index cb5a3bb..085c855 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -49,7 +49,7 @@ static int sendcmd(
unsigned char *scsi3addr );
-int __init cciss_scsi_detect(Scsi_Host_Template *tpnt);
+int cciss_scsi_detect(Scsi_Host_Template *tpnt);
int cciss_scsi_release(struct Scsi_Host *sh);
const char *cciss_scsi_info(struct Scsi_Host *sa);
@@ -777,7 +777,7 @@ complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag)
The scsi mid layer (scsi_register_module) is
called from cciss.c:cciss_init_one(). */
-int __init
+int
cciss_scsi_detect(Scsi_Host_Template *tpnt)
{
int i;
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 3924b24..c259cee 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -575,6 +575,7 @@ static struct request *get_request(request_queue_t *q, int rw)
rq->rq_status = RQ_ACTIVE;
rq->cmd = rw;
rq->special = NULL;
+ rq->io_account = 0;
rq->q = q;
}
@@ -813,6 +814,7 @@ void req_new_io(struct request *req, int merge, int sectors)
struct hd_struct *hd1, *hd2;
locate_hd_struct(req, &hd1, &hd2);
+ req->io_account = 1;
if (hd1)
account_io_start(hd1, req, merge, sectors);
if (hd2)
@@ -823,6 +825,8 @@ void req_merged_io(struct request *req)
{
struct hd_struct *hd1, *hd2;
+ if (unlikely(req->io_account == 0))
+ return;
locate_hd_struct(req, &hd1, &hd2);
if (hd1)
down_ios(hd1);
@@ -834,6 +838,8 @@ void req_finished_io(struct request *req)
{
struct hd_struct *hd1, *hd2;
+ if (unlikely(req->io_account == 0))
+ return;
locate_hd_struct(req, &hd1, &hd2);
if (hd1)
account_io_end(hd1, req);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 777712f..4b1afa6 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -693,12 +693,23 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, kdev_t dev,
set_blocksize(dev, bs);
lo->lo_bh = lo->lo_bhtail = NULL;
- kernel_thread(loop_thread, lo, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- down(&lo->lo_sem);
+ error = kernel_thread(loop_thread, lo,
+ CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ if (error < 0)
+ goto out_clr;
+ down(&lo->lo_sem); /* wait for the thread to start */
fput(file);
return 0;
+ out_clr:
+ lo->lo_backing_file = NULL;
+ lo->lo_device = 0;
+ lo->lo_flags = 0;
+ loop_sizes[lo->lo_number] = 0;
+ inode->i_mapping->gfp_mask = lo->old_gfp_mask;
+ lo->lo_state = Lo_unbound;
+ fput(file); /* yes, have to do it twice */
out_putf:
fput(file);
out:
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index fae3ffb..8c43ddc 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -402,7 +402,8 @@ static inline size_t read_zero_pagealigned(char * buf, size_t size)
count = size;
zap_page_range(mm, addr, count);
- zeromap_page_range(addr, count, PAGE_COPY);
+ if (zeromap_page_range(addr, count, PAGE_COPY))
+ break;
size -= count;
buf += count;
diff --git a/drivers/char/sc1200wdt.c b/drivers/char/sc1200wdt.c
index 73827c7..7c9940c 100644
--- a/drivers/char/sc1200wdt.c
+++ b/drivers/char/sc1200wdt.c
@@ -382,7 +382,7 @@ static int __init sc1200wdt_init(void)
if (io == -1) {
printk(KERN_ERR PFX "io parameter must be specified\n");
ret = -EINVAL;
- goto out_clean;
+ goto out_pnp;
}
if (!request_region(io, io_len, SC1200_MODULE_NAME)) {
diff --git a/drivers/i2c/i2c-elv.c b/drivers/i2c/i2c-elv.c
index 242a02e..96019bc 100644
--- a/drivers/i2c/i2c-elv.c
+++ b/drivers/i2c/i2c-elv.c
@@ -99,7 +99,7 @@ static int bit_elv_init(void)
} else {
outb(0x0c,base+2); /* SLCT auf low */
udelay(400);
- if ( !(inb(base+1) && 0x10) ) {
+ if ( !(inb(base+1) & 0x10) ) {
outb(0x04,base+2);
DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Select was high.\n"));
return -ENODEV;
diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c
index c2f4c30..3155dc8 100644
--- a/drivers/isdn/isdn_common.c
+++ b/drivers/isdn/isdn_common.c
@@ -1058,6 +1058,10 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
len = dev->drv[drvidx]->interface->
readstat(buf, count, 1, drvidx,
isdn_minor2chan(minor));
+ if (len < 0) {
+ retval = len;
+ goto out;
+ }
} else {
len = 0;
}
diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c
index 393ca44..bc3ef28 100644
--- a/drivers/isdn/isdn_ppp.c
+++ b/drivers/isdn/isdn_ppp.c
@@ -2335,6 +2335,7 @@ static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_s
rs->state = CCPResetIdle;
rs->is = is;
rs->id = id;
+ init_timer(&rs->timer);
rs->timer.data = (unsigned long)rs;
rs->timer.function = isdn_ppp_ccp_timer_callback;
is->reset->rs[id] = rs;
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index aa76e61..d01556c 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -510,7 +510,7 @@ static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned
or tells us why it failed. */
dq6 = CMD(1<<6);
dq5 = CMD(1<<5);
- timeo = jiffies + (HZ/1000); /* setting timeout to 1ms for now */
+ timeo = jiffies + (HZ/1000) + 1; /* setting timeout to 1ms for now */
oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
@@ -547,7 +547,7 @@ static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned
printk(KERN_WARNING "Internal flash device timeout occurred or write operation was performed while flash was programming.\n" );
}
} else {
- printk(KERN_WARNING "Waiting for write to complete timed out in do_write_oneword.");
+ printk(KERN_WARNING "Waiting for write to complete timed out in do_write_oneword.\n");
chip->state = FL_READY;
wake_up(&chip->wq);
@@ -825,7 +825,7 @@ static inline int do_erase_chip(struct map_info *map, struct flchip *chip)
chip->state = FL_READY;
wake_up(&chip->wq);
cfi_spin_unlock(chip->mutex);
- printk("waiting for erase to complete timed out.");
+ printk("waiting for erase to complete timed out.\n");
DISABLE_VPP(map);
return -EIO;
}
@@ -963,7 +963,7 @@ static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, u
}
else
{
- printk( "Waiting for erase to complete timed out in do_erase_oneblock.");
+ printk( "Waiting for erase to complete timed out in do_erase_oneblock.\n");
chip->state = FL_READY;
wake_up(&chip->wq);
diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
index f4280a1..9399d4e 100644
--- a/drivers/mtd/devices/blkmtd.c
+++ b/drivers/mtd/devices/blkmtd.c
@@ -195,6 +195,7 @@ static int commit_pages(struct blkmtd_dev *dev)
int err = 0;
iobuf->length = iobuf->nr_pages << PAGE_SHIFT;
+ iobuf->offset = 0; /* all pages are aligned */
iobuf->locked = 1;
if(iobuf->length) {
int i;
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 1953c4a..02d05b3 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -639,6 +639,7 @@ int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
po->chan.hdrlen = (sizeof(struct pppoe_hdr) +
dev->hard_header_len);
+ po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr);
po->chan.private = sk;
po->chan.ops = &pppoe_chan_ops;
diff --git a/drivers/s390/net/qeth.c b/drivers/s390/net/qeth.c
index 22f9444..ea7803a 100644
--- a/drivers/s390/net/qeth.c
+++ b/drivers/s390/net/qeth.c
@@ -6097,7 +6097,7 @@ static void qeth_qdio_input_handler(int irq,unsigned int status,
}
sbalf15=(card->inbound_qdio_buffers[(first_element+count-1)&
QDIO_MAX_BUFFERS_PER_Q].
- element[15].flags)&&0xff;
+ element[15].flags)&0xff;
PRINT_STUPID("inbound qdio transfer error on irq 0x%04x. " \
"qdio_error=0x%x (more than one: %c), " \
"siga_error=0x%x (more than one: %c), " \
diff --git a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c
index b1dda80..c124505 100644
--- a/drivers/scsi/cpqfcTSworker.c
+++ b/drivers/scsi/cpqfcTSworker.c
@@ -1260,7 +1260,7 @@ static void ProcessELS_Request(CPQFCHBA * dev, TachFCHDR_GCMND * fchs)
// Terminate I/O with "retry" potential
cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
} else {
- printk(" Got 3 LOGOuts - terminating comm. with port_id %Xh\n", fchs->s_id && 0xFFFFFF);
+ printk(" Got 3 LOGOuts - terminating comm. with port_id %Xh\n", fchs->s_id & 0xFFFFFF);
GiveUpOnDevice = 1;
}
} else {
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 48a04df..9c816a9 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -3667,7 +3667,7 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
IStatus &= ~0x80;
#ifdef INT_COAL
if (coalesced)
- ha->status = pcs->ext_status && 0xffff;
+ ha->status = pcs->ext_status & 0xffff;
else
#endif
ha->status = gdth_readw(&dp6m_ptr->i960r.status);
@@ -3679,7 +3679,7 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
if (coalesced) {
ha->info = pcs->info0;
ha->info2 = pcs->info1;
- ha->service = (pcs->ext_status >> 16) && 0xffff;
+ ha->service = (pcs->ext_status >> 16) & 0xffff;
} else
#endif
{
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 905b8a0..8b8f281 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1192,7 +1192,7 @@ static int sg_mmap(struct file * filp, struct vm_area_struct *vma)
sg_rb_correct4mmap(rsv_schp, 1); /* do only once per fd lifetime */
sfp->mmap_called = 1;
}
- vma->vm_flags |= (VM_RESERVED | VM_IO);
+ vma->vm_flags |= VM_RESERVED;
vma->vm_private_data = sfp;
vma->vm_ops = &sg_mmap_vm_ops;
return 0;
diff --git a/drivers/usb/host/usb-ohci.c b/drivers/usb/host/usb-ohci.c
index 27fc5fe..82817f5 100644
--- a/drivers/usb/host/usb-ohci.c
+++ b/drivers/usb/host/usb-ohci.c
@@ -2159,7 +2159,7 @@ static int rh_submit_urb (struct urb * urb)
static int rh_unlink_urb (struct urb * urb)
{
ohci_t * ohci = urb->dev->bus->hcpriv;
- unsigned int flags;
+ unsigned long flags;
spin_lock_irqsave(&ohci->ohci_lock, flags);
if (ohci->rh.urb == urb) {
diff --git a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c
index 8b10308..0d013c6 100644
--- a/drivers/usb/pegasus.c
+++ b/drivers/usb/pegasus.c
@@ -147,6 +147,7 @@ static int get_registers(pegasus_t * pegasus, u16 indx, u16 size,
set_current_state(TASK_UNINTERRUPTIBLE);
if ((ret = usb_submit_urb(pegasus->ctrl_urb))) {
+ set_current_state(TASK_RUNNING);
err("%s: BAD CTRLs %d", __FUNCTION__, ret);
goto out;
}
@@ -197,6 +198,7 @@ static int set_registers(pegasus_t * pegasus, u16 indx, u16 size,
set_current_state(TASK_UNINTERRUPTIBLE);
if ((ret = usb_submit_urb(pegasus->ctrl_urb))) {
+ set_current_state(TASK_RUNNING);
err("%s: BAD CTRL %d", __FUNCTION__, ret);
goto out;
}
@@ -244,6 +246,7 @@ static int set_register(pegasus_t * pegasus, u16 indx, u8 data)
set_current_state(TASK_UNINTERRUPTIBLE);
if ((ret = usb_submit_urb(pegasus->ctrl_urb))) {
+ set_current_state(TASK_RUNNING);
err("%s: BAD CTRL %d", __FUNCTION__, ret);
goto out;
}
diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c
index 6d751cd..a0d18a2 100644
--- a/drivers/usb/printer.c
+++ b/drivers/usb/printer.c
@@ -692,6 +692,7 @@ static ssize_t usblp_write(struct file *file, const char *buffer, size_t count,
usblp->wcomplete = 0;
err = usb_submit_urb(usblp->writeurb);
if (err) {
+ usblp->wcomplete = 1;
if (err != -ENOMEM)
count = -EIO;
else
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index 1bc4e4b..0260b4e 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -308,20 +308,9 @@ static inline int port_paranoia_check (struct usb_serial_port *port, const char
return 0;
}
-
-static inline struct usb_serial* get_usb_serial (struct usb_serial_port *port, const char *function)
-{
- /* if no port was specified, or it fails a paranoia check */
- if (!port ||
- port_paranoia_check (port, function) ||
- serial_paranoia_check (port->serial, function)) {
- /* then say that we don't have a valid usb_serial thing, which will
- * end up genrating -ENODEV return values */
- return NULL;
- }
-
- return port->serial;
-}
+#define get_usb_serial(p, f) usb_serial_get_serial(p, f)
+extern struct usb_serial *usb_serial_get_serial(struct usb_serial_port *port,
+ const char *function_name);
static inline void usb_serial_debug_data (const char *file, const char *function, int size, const unsigned char *data)
diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
index 319bb03..ee6ef01 100644
--- a/drivers/usb/serial/usbserial.c
+++ b/drivers/usb/serial/usbserial.c
@@ -408,6 +408,25 @@ static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL
static LIST_HEAD(usb_serial_driver_list);
+struct usb_serial *usb_serial_get_serial(struct usb_serial_port *port,
+ const char *function)
+{
+
+ /* if no port was specified, or it fails a paranoia check */
+ if (!port ||
+ port_paranoia_check (port, function) ||
+ serial_paranoia_check (port->serial, function)) {
+ return NULL;
+ }
+
+ /* disconnected, cut off all operations */
+ if (port->serial->dev == NULL)
+ return NULL;
+
+ return port->serial;
+}
+
+
static struct usb_serial *get_serial_by_minor (unsigned int minor)
{
return serial_table[minor];
@@ -467,6 +486,23 @@ static void return_serial (struct usb_serial *serial)
}
/*
+ * A regular foo_put(), except a) it's open-coded without kref, and
+ * b) it's not the only place which does --serial->ref (due to locking).
+ *
+ * This does not do an equivalent of return_serial() because serial_table[]
+ * has a lifetime from probe to disconnect.
+ */
+static void serial_put(struct usb_serial *serial)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&post_lock, flags);
+ if (--serial->ref == 0)
+ kfree(serial);
+ spin_unlock_irqrestore(&post_lock, flags);
+}
+
+/*
* The post kludge.
*
* Our component drivers are hideously buggy and written by people
@@ -495,7 +531,7 @@ static void post_helper(void *arg)
while (pos != &post_list) {
job = list_entry(pos, struct usb_serial_post_job, link);
port = job->port;
- /* get_usb_serial checks port->tty, so cannot be used */
+ /* get_usb_serial checks serial->dev, so cannot be used */
serial = port->serial;
if (port->write_busy) {
dbg("%s - port %d busy", __FUNCTION__, port->number);
@@ -508,7 +544,7 @@ static void post_helper(void *arg)
down(&port->sem);
dbg("%s - port %d len %d backlog %d", __FUNCTION__,
port->number, job->len, port->write_backlog);
- if (port->tty != NULL) {
+ if (serial->dev != NULL) {
int rc;
int sent = 0;
while (sent < job->len) {
@@ -581,17 +617,25 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
struct usb_serial_port *port;
unsigned int portNumber;
int retval = 0;
-
+ unsigned long flags;
+
dbg("%s", __FUNCTION__);
/* initialize the pointer incase something fails */
tty->driver_data = NULL;
+ /*
+ * In a sane refcounting system, this would've been called serial_get().
+ */
+ spin_lock_irqsave(&post_lock, flags);
/* get the serial object associated with this tty pointer */
serial = get_serial_by_minor (MINOR(tty->device));
-
- if (serial_paranoia_check (serial, __FUNCTION__))
+ if (serial_paranoia_check(serial, __FUNCTION__) || serial->dev == NULL) {
+ spin_unlock_irqrestore(&post_lock, flags);
return -ENODEV;
+ }
+ serial->ref++; /* Protect the port->sem from kfree() */
+ spin_unlock_irqrestore(&post_lock, flags);
/* set up our port structure making the tty driver remember our port object, and us it */
portNumber = MINOR(tty->device) - serial->minor;
@@ -600,7 +644,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
down (&port->sem);
port->tty = tty;
-
+
/* lock this module before we call it */
if (serial->type->owner)
__MOD_INC_USE_COUNT(serial->type->owner);
@@ -622,13 +666,16 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
}
up (&port->sem);
+ if (retval)
+ serial_put(serial);
return retval;
}
static void __serial_close(struct usb_serial_port *port, struct file *filp)
{
+
if (!port->open_count) {
- dbg ("%s - port not opened", __FUNCTION__);
+ err("%s - port %d: not open", __FUNCTION__, port->number);
return;
}
@@ -653,36 +700,33 @@ static void __serial_close(struct usb_serial_port *port, struct file *filp)
static void serial_close(struct tty_struct *tty, struct file * filp)
{
- struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
- struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+ struct usb_serial_port *port;
+ struct usb_serial *serial;
- if (!serial)
+ if ((port = tty->driver_data) == NULL) {
+ /* This happens if someone opened us with O_NDELAY */
return;
-
- down (&port->sem);
+ }
+ if ((serial = port->serial) == NULL) {
+ err("%s - port %d: not open (count %d)", __FUNCTION__, port->number, port->open_count);
+ return;
+ }
dbg("%s - port %d", __FUNCTION__, port->number);
- /* if disconnect beat us to the punch here, there's nothing to do */
- if (tty->driver_data) {
- /*
- * XXX The right thing would be to wait for the output to drain.
- * But we are not sufficiently daring to experiment in 2.4.
- * N.B. If we do wait, no need to run post_helper here.
- * Normall callback mechanism wakes it up just fine.
- */
-#if I_AM_A_DARING_HACKER
- tty->closing = 1;
- up (&port->sem);
- if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->closing_wait);
- down (&port->sem);
- if (!tty->driver_data) /* woopsie, disconnect, now what */ ;
-#endif
- __serial_close(port, filp);
+ tty->closing = 1;
+ if (serial->dev != NULL) {
+ /* In most drivers, this is set with setserial */
+ /** if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) **/
+ tty_wait_until_sent(tty, /** info->closing_wait **/ 30*HZ);
}
+ down (&port->sem);
+ __serial_close(port, filp);
up (&port->sem);
+
+ serial_put(serial);
+ tty->closing = 0;
}
static int __serial_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
@@ -696,7 +740,7 @@ static int __serial_write (struct usb_serial_port *port, int from_user, const un
dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
if (!port->open_count) {
- dbg("%s - port not opened", __FUNCTION__);
+ dbg("%s - port not open", __FUNCTION__);
goto exit;
}
@@ -806,6 +850,9 @@ static int serial_post_one(struct usb_serial_port *port, int from_user,
struct usb_serial_post_job *job;
unsigned long flags;
+ if (!serial)
+ return -ENODEV;
+
dbg("%s - port %d user %d count %d", __FUNCTION__, port->number, from_user, count);
job = kmalloc(sizeof(struct usb_serial_post_job), gfp);
@@ -1239,24 +1286,25 @@ static int generic_chars_in_buffer (struct usb_serial_port *port)
static void generic_read_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+ struct usb_serial *serial = port->serial;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int i;
int result;
- dbg("%s - port %d", __FUNCTION__, port->number);
-
if (!serial) {
- dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+ err("%s - null serial pointer, exiting", __FUNCTION__);
return;
}
if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero read bulk status received: %d, pipe 0x%x",
+ __FUNCTION__, urb->status, urb->pipe);
return;
}
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
tty = port->tty;
@@ -1272,6 +1320,9 @@ static void generic_read_bulk_callback (struct urb *urb)
tty_flip_buffer_push(tty);
}
+ if (serial->dev == NULL)
+ return;
+
/* Continue trying to always read */
usb_fill_bulk_urb (port->read_urb, serial->dev,
usb_rcvbulkpipe (serial->dev,
@@ -1289,18 +1340,12 @@ static void generic_read_bulk_callback (struct urb *urb)
static void generic_write_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
dbg("%s - port %d", __FUNCTION__, port->number);
port->write_busy = 0;
wmb();
- if (!serial) {
- err("%s - null serial pointer, exiting", __FUNCTION__);
- return;
- }
-
if (urb->status) {
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
}
@@ -1658,26 +1703,22 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
{
struct usb_serial *serial = (struct usb_serial *) ptr;
struct usb_serial_port *port;
- unsigned long flags;
int i;
dbg ("%s", __FUNCTION__);
if (serial) {
- /* fail all future close/read/write/ioctl/etc calls */
for (i = 0; i < serial->num_ports; ++i) {
port = &serial->port[i];
down (&port->sem);
if (port->tty != NULL)
- while (port->open_count > 0)
- __serial_close(port, NULL);
+ tty_hangup(port->tty);
up (&port->sem);
}
-
- serial->dev = NULL;
serial_shutdown (serial);
- for (i = 0; i < serial->num_ports; ++i)
- serial->port[i].open_count = 0;
+ /* fail all future close/read/write/ioctl/etc calls */
+ serial->dev = NULL;
+ wmb();
for (i = 0; i < serial->num_bulk_in; ++i) {
port = &serial->port[i];
@@ -1716,10 +1757,7 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
return_serial (serial);
/* free up any memory that we allocated */
- spin_lock_irqsave(&post_lock, flags);
- if (--serial->ref == 0)
- kfree(serial);
- spin_unlock_irqrestore(&post_lock, flags);
+ serial_put (serial);
} else {
info("device disconnected");
@@ -1813,6 +1851,11 @@ static void __exit usb_serial_exit(void)
usb_deregister(&usb_serial_driver);
tty_unregister_driver(&serial_tty_driver);
+
+ while (!list_empty(&usb_serial_driver_list)) {
+ err("%s - module is in use, hanging...", __FUNCTION__);
+ msleep(5000);
+ }
}
@@ -1862,7 +1905,7 @@ EXPORT_SYMBOL(usb_serial_deregister);
EXPORT_SYMBOL(ezusb_writememory);
EXPORT_SYMBOL(ezusb_set_reset);
#endif
-
+EXPORT_SYMBOL(usb_serial_get_serial);
/* Module information */
MODULE_AUTHOR( DRIVER_AUTHOR );
diff --git a/drivers/usb/usbnet.c b/drivers/usb/usbnet.c
index 764be51..f2c46ff 100644
--- a/drivers/usb/usbnet.c
+++ b/drivers/usb/usbnet.c
@@ -1298,12 +1298,12 @@ static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
#define STATUS_CONN_OTHER (1 << 14)
#define STATUS_SUSPEND_OTHER (1 << 13)
#define STATUS_MAILBOX_OTHER (1 << 12)
-#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03)
+#define STATUS_PACKETS_OTHER(n) (((n) >> 8) & 0x03)
#define STATUS_CONN_THIS (1 << 6)
#define STATUS_SUSPEND_THIS (1 << 5)
#define STATUS_MAILBOX_THIS (1 << 4)
-#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03)
+#define STATUS_PACKETS_THIS(n) (((n) >> 0) & 0x03)
#define STATUS_UNSPEC_MASK 0x0c8c
#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK))
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index cf616e1..fac9c73 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -388,7 +388,7 @@ static int fbmem_read_proc(char *buf, char **start, off_t offset,
int clen;
clen = 0;
- for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && len < 4000; fi++)
+ for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && clen < 4000; fi++)
if (*fi)
clen += sprintf(buf + clen, "%d %s\n",
GET_FB_IDX((*fi)->node),
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index b0ad905..32c8ec6 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -77,7 +77,7 @@ static struct linux_binfmt elf_format = {
NULL, THIS_MODULE, load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE
};
-#define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE)
+#define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
static int set_brk(unsigned long start, unsigned long end)
{
@@ -345,7 +345,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
* <= p_memsize so it is only necessary to check p_memsz.
*/
k = load_addr + eppnt->p_vaddr;
- if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz ||
+ if (BAD_ADDR(k) || eppnt->p_filesz > eppnt->p_memsz ||
eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) {
error = -ENOMEM;
goto out_close;
@@ -772,7 +772,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
* allowed task size. Note that p_filesz must always be
* <= p_memsz so it is only necessary to check p_memsz.
*/
- if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
+ if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
elf_ppnt->p_memsz > TASK_SIZE ||
TASK_SIZE - elf_ppnt->p_memsz < k) {
/* set_brk can never work. Avoid overflows. */
@@ -822,10 +822,13 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
interpreter,
&interp_load_addr);
if (BAD_ADDR(elf_entry)) {
- printk(KERN_ERR "Unable to load interpreter %.128s\n",
- elf_interpreter);
+ // FIXME - ratelimit this before re-enabling
+ // printk(KERN_ERR "Unable to load interpreter %.128s\n",
+ // elf_interpreter);
+
force_sig(SIGSEGV, current);
- retval = IS_ERR((void *)elf_entry) ? PTR_ERR((void *)elf_entry) : -ENOEXEC;
+ retval = IS_ERR((void *)elf_entry) ?
+ (int)elf_entry : -EINVAL;
goto out_free_dentry;
}
reloc_func_desc = interp_load_addr;
@@ -833,6 +836,12 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
allow_write_access(interpreter);
fput(interpreter);
kfree(elf_interpreter);
+ } else {
+ if (BAD_ADDR(elf_entry)) {
+ force_sig(SIGSEGV, current);
+ retval = -EINVAL;
+ goto out_free_dentry;
+ }
}
kfree(elf_phdata);
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index d510cc8..4d7c709 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -480,12 +480,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
sb->u.ext2_sb.s_es = es;
sb->s_magic = le16_to_cpu(es->s_magic);
- if (sb->s_magic != EXT2_SUPER_MAGIC) {
- if (!silent)
- printk ("VFS: Can't find ext2 filesystem on dev %s.\n",
- bdevname(dev));
- goto failed_mount;
- }
+ if (sb->s_magic != EXT2_SUPER_MAGIC)
+ goto cantfind_ext2;
if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV &&
(EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
@@ -561,16 +557,19 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
}
sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
le32_to_cpu(es->s_log_frag_size);
- if (sb->u.ext2_sb.s_frag_size)
- sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize /
- sb->u.ext2_sb.s_frag_size;
- else
- sb->s_magic = 0;
+ if (sb->u.ext2_sb.s_frag_size == 0)
+ goto cantfind_ext2;
+ sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize /
+ sb->u.ext2_sb.s_frag_size;
sb->u.ext2_sb.s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
sb->u.ext2_sb.s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
sb->u.ext2_sb.s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
+ if (EXT2_INODE_SIZE(sb) == 0)
+ goto cantfind_ext2;
sb->u.ext2_sb.s_inodes_per_block = sb->s_blocksize /
EXT2_INODE_SIZE(sb);
+ if (sb->u.ext2_sb.s_inodes_per_block == 0)
+ goto cantfind_ext2;
sb->u.ext2_sb.s_itb_per_group = sb->u.ext2_sb.s_inodes_per_group /
sb->u.ext2_sb.s_inodes_per_block;
sb->u.ext2_sb.s_desc_per_block = sb->s_blocksize /
@@ -589,13 +588,10 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
log2 (EXT2_ADDR_PER_BLOCK(sb));
sb->u.ext2_sb.s_desc_per_block_bits =
log2 (EXT2_DESC_PER_BLOCK(sb));
- if (sb->s_magic != EXT2_SUPER_MAGIC) {
- if (!silent)
- printk ("VFS: Can't find an ext2 filesystem on dev "
- "%s.\n",
- bdevname(dev));
- goto failed_mount;
- }
+
+ if (sb->s_magic != EXT2_SUPER_MAGIC)
+ goto cantfind_ext2;
+
if (sb->s_blocksize != bh->b_size) {
if (!silent)
printk ("VFS: Unsupported blocksize on dev "
@@ -625,6 +621,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
goto failed_mount;
}
+ if (EXT2_BLOCKS_PER_GROUP(sb) == 0)
+ goto cantfind_ext2;
sb->u.ext2_sb.s_groups_count = (le32_to_cpu(es->s_blocks_count) -
le32_to_cpu(es->s_first_data_block) +
EXT2_BLOCKS_PER_GROUP(sb) - 1) /
@@ -678,6 +676,11 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
}
ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
return sb;
+cantfind_ext2:
+ if (!silent)
+ printk ("VFS: Can't find ext2 filesystem on dev %s.\n",
+ bdevname(dev));
+ goto failed_mount;
failed_mount2:
for (i = 0; i < db_count; i++)
brelse(sb->u.ext2_sb.s_group_desc[i]);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 33e2f97..c011c50 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -979,13 +979,9 @@ struct super_block * ext3_read_super (struct super_block * sb, void * data,
es = (struct ext3_super_block *) (((char *)bh->b_data) + offset);
sbi->s_es = es;
sb->s_magic = le16_to_cpu(es->s_magic);
- if (sb->s_magic != EXT3_SUPER_MAGIC) {
- if (!silent)
- printk(KERN_ERR
- "VFS: Can't find ext3 filesystem on dev %s.\n",
- bdevname(dev));
- goto failed_mount;
- }
+ if (sb->s_magic != EXT3_SUPER_MAGIC)
+ goto cantfind_ext3;
+
if (le32_to_cpu(es->s_rev_level) == EXT3_GOOD_OLD_REV &&
(EXT3_HAS_COMPAT_FEATURE(sb, ~0U) ||
EXT3_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
@@ -1083,8 +1079,13 @@ struct super_block * ext3_read_super (struct super_block * sb, void * data,
sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
+ if (EXT3_INODE_SIZE(sb) == 0)
+ goto cantfind_ext3;
sbi->s_inodes_per_block = blocksize / EXT3_INODE_SIZE(sb);
- sbi->s_itb_per_group = sbi->s_inodes_per_group /sbi->s_inodes_per_block;
+ if (sbi->s_inodes_per_block == 0)
+ goto cantfind_ext3;
+ sbi->s_itb_per_group = sbi->s_inodes_per_group /
+ sbi->s_inodes_per_block;
sbi->s_desc_per_block = blocksize / sizeof(struct ext3_group_desc);
sbi->s_sbh = bh;
if (sbi->s_resuid == EXT3_DEF_RESUID)
@@ -1114,6 +1115,8 @@ struct super_block * ext3_read_super (struct super_block * sb, void * data,
goto failed_mount;
}
+ if (EXT3_BLOCKS_PER_GROUP(sb) == 0)
+ goto cantfind_ext3;
sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
le32_to_cpu(es->s_first_data_block) +
EXT3_BLOCKS_PER_GROUP(sb) - 1) /
@@ -1240,6 +1243,12 @@ struct super_block * ext3_read_super (struct super_block * sb, void * data,
return sb;
+cantfind_ext3:
+ if (!silent)
+ printk(KERN_ERR
+ "VFS: Can't find ext3 filesystem on dev %s.\n",
+ bdevname(dev));
+ goto failed_mount;
failed_mount3:
journal_destroy(sbi->s_journal);
failed_mount2:
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 48ab5af..30e03c2 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -860,7 +860,10 @@ static int nfs_safe_remove(struct dentry *dentry)
if (inode)
NFS_CACHEINV(inode);
error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
- if (error < 0)
+
+ /* if server returned ENOENT, assume that the dentry is already gone
+ * and update the cache accordingly */
+ if (error < 0 && (error != -ENOENT))
goto out;
if (inode)
inode->i_nlink--;
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 3235723..f99c836 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -204,7 +204,8 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
/*
* Add a partitions details to the devices partition description.
*/
-void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
+void add_gd_partition(struct gendisk *hd, int minor, unsigned int start,
+ unsigned int size)
{
#ifndef CONFIG_DEVFS_FS
char buf[40];
diff --git a/fs/partitions/check.h b/fs/partitions/check.h
index 32d7940..dd93517 100644
--- a/fs/partitions/check.h
+++ b/fs/partitions/check.h
@@ -2,7 +2,8 @@
* add_partition adds a partitions details to the devices partition
* description.
*/
-void add_gd_partition(struct gendisk *hd, int minor, int start, int size);
+void add_gd_partition(struct gendisk *hd, int minor, unsigned int start,
+ unsigned int size);
typedef struct {struct page *v;} Sector;
diff --git a/fs/partitions/sun.c b/fs/partitions/sun.c
index a0ca0b1..cd087ca 100644
--- a/fs/partitions/sun.c
+++ b/fs/partitions/sun.c
@@ -86,7 +86,7 @@ int sun_partition(struct gendisk *hd, struct block_device *bdev, unsigned long f
spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
for (i = 0; i < 8; i++, p++) {
unsigned long st_sector;
- int num_sectors;
+ unsigned int num_sectors;
st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc;
num_sectors = be32_to_cpu(p->num_sectors);
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 3f21822..be975fe 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -311,7 +311,6 @@ parse_options(struct smb_mount_data_kernel *mnt, char *options)
&optopt, &optarg, &flags, &value)) > 0) {
VERBOSE("'%s' -> '%s'\n", optopt, optarg ? optarg : "<none>");
-
switch (c) {
case 1:
/* got a "flag" option */
@@ -326,15 +325,19 @@ parse_options(struct smb_mount_data_kernel *mnt, char *options)
break;
case 'u':
mnt->uid = value;
+ flags |= SMB_MOUNT_UID;
break;
case 'g':
mnt->gid = value;
+ flags |= SMB_MOUNT_GID;
break;
case 'f':
mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;
+ flags |= SMB_MOUNT_FMODE;
break;
case 'd':
mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
+ flags |= SMB_MOUNT_DMODE;
break;
case 'i':
strncpy(mnt->codepage.local_name, optarg,
@@ -375,9 +378,9 @@ smb_show_options(struct seq_file *s, struct vfsmount *m)
if (mnt->flags & opts[i].flag)
seq_printf(s, ",%s", opts[i].name);
- if (mnt->uid != 0)
+ if (mnt->flags & SMB_MOUNT_UID)
seq_printf(s, ",uid=%d", mnt->uid);
- if (mnt->gid != 0)
+ if (mnt->flags & SMB_MOUNT_GID)
seq_printf(s, ",gid=%d", mnt->gid);
if (mnt->mounted_uid != 0)
seq_printf(s, ",mounted_uid=%d", mnt->mounted_uid);
@@ -386,8 +389,10 @@ smb_show_options(struct seq_file *s, struct vfsmount *m)
* Defaults for file_mode and dir_mode are unknown to us; they
* depend on the current umask of the user doing the mount.
*/
- seq_printf(s, ",file_mode=%04o", mnt->file_mode & S_IRWXUGO);
- seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
+ if (mnt->flags & SMB_MOUNT_FMODE)
+ seq_printf(s, ",file_mode=%04o", mnt->file_mode & S_IRWXUGO);
+ if (mnt->flags & SMB_MOUNT_DMODE)
+ seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
if (strcmp(mnt->codepage.local_name, CONFIG_NLS_DEFAULT))
seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
@@ -505,8 +510,13 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
- mnt->flags = (oldmnt->file_mode >> 9);
+ mnt->flags = (oldmnt->file_mode >> 9) | SMB_MOUNT_UID |
+ SMB_MOUNT_GID | SMB_MOUNT_FMODE | SMB_MOUNT_DMODE;
} else {
+ mnt->file_mode = mnt->dir_mode = S_IRWXU | S_IRGRP | S_IXGRP |
+ S_IROTH | S_IXOTH | S_IFREG;
+ mnt->dir_mode = mnt->dir_mode = S_IRWXU | S_IRGRP | S_IXGRP |
+ S_IROTH | S_IXOTH | S_IFDIR;
if (parse_options(mnt, raw_data))
goto out_bad_option;
}
@@ -533,6 +543,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
sb->s_root = d_alloc_root(root_inode);
if (!sb->s_root)
goto out_no_root;
+
smb_new_dentry(sb->s_root);
return sb;
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index eabd99b..7f0794c 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -1946,7 +1946,7 @@ unlock_return:
return result;
}
-void smb_decode_unix_basic(struct smb_fattr *fattr, char *p)
+void smb_decode_unix_basic(struct smb_fattr *fattr, struct smb_sb_info *server, char *p)
{
/* FIXME: verify nls support. all is sent as utf8? */
@@ -1970,8 +1970,17 @@ void smb_decode_unix_basic(struct smb_fattr *fattr, char *p)
fattr->f_ctime = smb_ntutc2unixutc(LVAL(p, 16));
fattr->f_atime = smb_ntutc2unixutc(LVAL(p, 24));
fattr->f_mtime = smb_ntutc2unixutc(LVAL(p, 32));
- fattr->f_uid = LVAL(p, 40);
- fattr->f_gid = LVAL(p, 48);
+
+ if (server->mnt->flags & SMB_MOUNT_UID)
+ fattr->f_uid = server->mnt->uid;
+ else
+ fattr->f_uid = LVAL(p, 40);
+
+ if (server->mnt->flags & SMB_MOUNT_GID)
+ fattr->f_gid = server->mnt->gid;
+ else
+ fattr->f_gid = LVAL(p, 48);
+
fattr->f_mode |= smb_filetype_to_mode(WVAL(p, 56));
if (S_ISBLK(fattr->f_mode) || S_ISCHR(fattr->f_mode)) {
@@ -1980,7 +1989,16 @@ void smb_decode_unix_basic(struct smb_fattr *fattr, char *p)
fattr->f_rdev = MKDEV(major & 0xffffffff, minor & 0xffffffff);
}
+
fattr->f_mode |= LVAL(p, 84);
+
+ if ( (server->mnt->flags & SMB_MOUNT_DMODE) &&
+ (S_ISDIR(fattr->f_mode)) )
+ fattr->f_mode = (server->mnt->dir_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
+ else if ( (server->mnt->flags & SMB_MOUNT_FMODE) &&
+ !(S_ISDIR(fattr->f_mode)) )
+ fattr->f_mode = (server->mnt->file_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
+
}
/*
@@ -2061,7 +2079,7 @@ smb_decode_long_dirent(struct smb_sb_info *server, char *p, int level,
/* FIXME: should we check the length?? */
p += 8;
- smb_decode_unix_basic(fattr, p);
+ smb_decode_unix_basic(fattr, server, p);
VERBOSE("info SMB_FIND_FILE_UNIX at %p, len=%d, name=%.*s\n",
p, len, len, qname->name);
break;
@@ -2686,7 +2704,7 @@ smb_proc_getattr_unix(struct smb_sb_info *server, struct dentry *dir,
goto out;
}
- smb_decode_unix_basic(attr, resp_data);
+ smb_decode_unix_basic(attr, server, resp_data);
result = 0;
out:
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
index 56d528e..6540403 100644
--- a/fs/smbfs/proto.h
+++ b/fs/smbfs/proto.h
@@ -21,7 +21,7 @@ extern int smb_proc_rmdir(struct dentry *dentry);
extern int smb_proc_unlink(struct dentry *dentry);
extern int smb_proc_flush(struct smb_sb_info *server, __u16 fileid);
extern void smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr);
-extern void smb_decode_unix_basic(struct smb_fattr *fattr, char *p);
+extern void smb_decode_unix_basic(struct smb_fattr *fattr, struct smb_sb_info *server, char *p);
extern int smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr);
extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr);
extern int smb_proc_setattr_unix(struct dentry *dentry, struct iattr *attr, unsigned int major, unsigned int minor);
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 9df2fa2..0c5b54e 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1515,7 +1515,7 @@ udf_read_super(struct super_block *sb, void *options, int silent)
iput(inode);
goto error_out;
}
- sb->s_maxbytes = MAX_LFS_FILESIZE;
+ sb->s_maxbytes = 1<<30;
return sb;
error_out:
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index 0ae7e96..0567211 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -182,37 +182,51 @@ void udf_truncate_extents(struct inode * inode)
{
if (offset)
{
- extoffset -= adsize;
- etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
- if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
- {
- extoffset -= adsize;
- elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset);
- udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
+ /*
+ * OK, there is not extent covering inode->i_size and
+ * no extent above inode->i_size => truncate is
+ * extending the file by 'offset'.
+ */
+ if ((!bh && extoffset == udf_file_entry_alloc_offset(inode)) ||
+ (bh && extoffset == sizeof(struct allocExtDesc))) {
+ /* File has no extents at all! */
+ memset(&eloc, 0x00, sizeof(lb_addr));
+ elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
+ udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
}
- else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
- {
- lb_addr neloc = { 0, 0 };
+ else {
extoffset -= adsize;
- nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
- ((elen + offset + inode->i_sb->s_blocksize - 1) &
- ~(inode->i_sb->s_blocksize - 1));
- udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
- udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
- }
- else
- {
- if (elen & (inode->i_sb->s_blocksize - 1))
+ etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
+ if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
+ {
+ extoffset -= adsize;
+ elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset);
+ udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
+ }
+ else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
{
+ lb_addr neloc = { 0, 0 };
extoffset -= adsize;
- elen = EXT_RECORDED_ALLOCATED |
- ((elen + inode->i_sb->s_blocksize - 1) &
+ nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
+ ((elen + offset + inode->i_sb->s_blocksize - 1) &
~(inode->i_sb->s_blocksize - 1));
- udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
+ udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
+ udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
+ }
+ else
+ {
+ if (elen & (inode->i_sb->s_blocksize - 1))
+ {
+ extoffset -= adsize;
+ elen = EXT_RECORDED_ALLOCATED |
+ ((elen + inode->i_sb->s_blocksize - 1) &
+ ~(inode->i_sb->s_blocksize - 1));
+ udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
+ }
+ memset(&eloc, 0x00, sizeof(lb_addr));
+ elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
+ udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
}
- memset(&eloc, 0x00, sizeof(lb_addr));
- elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
- udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
}
}
}
diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h
index 9b6b55e..bb63c10 100644
--- a/include/asm-i386/bitops.h
+++ b/include/asm-i386/bitops.h
@@ -38,7 +38,7 @@ static __inline__ void set_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btsl %1,%0"
:"=m" (ADDR)
- :"Ir" (nr));
+ :"Ir" (nr), "m" (ADDR));
}
/**
@@ -55,7 +55,7 @@ static __inline__ void __set_bit(int nr, volatile void * addr)
__asm__(
"btsl %1,%0"
:"=m" (ADDR)
- :"Ir" (nr));
+ :"Ir" (nr), "m" (ADDR));
}
/**
@@ -73,7 +73,7 @@ static __inline__ void clear_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btrl %1,%0"
:"=m" (ADDR)
- :"Ir" (nr));
+ :"Ir" (nr), "m" (ADDR));
}
#define smp_mb__before_clear_bit() barrier()
#define smp_mb__after_clear_bit() barrier()
@@ -92,7 +92,7 @@ static __inline__ void __change_bit(int nr, volatile void * addr)
__asm__ __volatile__(
"btcl %1,%0"
:"=m" (ADDR)
- :"Ir" (nr));
+ :"Ir" (nr), "m" (ADDR));
}
/**
@@ -109,7 +109,7 @@ static __inline__ void change_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btcl %1,%0"
:"=m" (ADDR)
- :"Ir" (nr));
+ :"Ir" (nr), "m" (ADDR));
}
/**
@@ -127,7 +127,7 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btsl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"Ir" (nr) : "memory");
+ :"Ir" (nr), "m" (ADDR) : "memory");
return oldbit;
}
@@ -147,7 +147,7 @@ static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
__asm__(
"btsl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"Ir" (nr));
+ :"Ir" (nr), "m" (ADDR));
return oldbit;
}
@@ -166,7 +166,7 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"Ir" (nr) : "memory");
+ :"Ir" (nr), "m" (ADDR) : "memory");
return oldbit;
}
@@ -186,7 +186,7 @@ static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
__asm__(
"btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"Ir" (nr));
+ :"Ir" (nr), "m" (ADDR));
return oldbit;
}
@@ -198,7 +198,7 @@ static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
__asm__ __volatile__(
"btcl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"Ir" (nr) : "memory");
+ :"Ir" (nr), "m" (ADDR) : "memory");
return oldbit;
}
@@ -217,7 +217,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btcl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"Ir" (nr) : "memory");
+ :"Ir" (nr), "m" (ADDR) : "memory");
return oldbit;
}
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 90424fd..8b6b3ab 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -41,11 +41,13 @@ typedef struct { unsigned long pte_low, pte_high; } pte_t;
typedef struct { unsigned long long pmd; } pmd_t;
typedef struct { unsigned long long pgd; } pgd_t;
#define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
+#define __pte(x) ({ pte_t __pte = {(x), (x) >> 32}; __pte; })
#else
typedef struct { unsigned long pte_low; } pte_t;
typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pgd; } pgd_t;
#define pte_val(x) ((x).pte_low)
+#define __pte(x) ((pte_t) { (x) } )
#endif
#define PTE_MASK PAGE_MASK
@@ -55,7 +57,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)
-#define __pte(x) ((pte_t) { (x) } )
#define __pmd(x) ((pmd_t) { (x) } )
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 341262e..5e4f341 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -77,13 +77,16 @@ static inline void copy_user_page(void * to, void * from, unsigned long vaddr)
#ifdef CONFIG_CPU_MIPS32
typedef struct { unsigned long pte_low, pte_high; } pte_t;
#define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
+ #define __pte(x) ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; })
#else
typedef struct { unsigned long long pte_low; } pte_t;
#define pte_val(x) ((x).pte_low)
+ #define __pte(x) ((pte_t) { (x) } )
#endif
#else
typedef struct { unsigned long pte_low; } pte_t;
#define pte_val(x) ((x).pte_low)
+#define __pte(x) ((pte_t) { (x) } )
#endif
typedef struct { unsigned long pmd; } pmd_t;
@@ -96,7 +99,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define ptep_buddy(x) ((pte_t *)((unsigned long)(x) ^ sizeof(pte_t)))
-#define __pte(x) ((pte_t) { (x) } )
#define __pmd(x) ((pmd_t) { (x) } )
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
index c8a4749..f6a2a4f 100644
--- a/include/asm-x86_64/bitops.h
+++ b/include/asm-x86_64/bitops.h
@@ -38,7 +38,7 @@ static __inline__ void set_bit(long nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btsq %1,%0"
:"=m" (ADDR)
- :"dIr" (nr));
+ :"dIr" (nr), "m" (ADDR));
}
/**
@@ -55,7 +55,7 @@ static __inline__ void __set_bit(long nr, volatile void * addr)
__asm__(
"btsq %1,%0"
:"=m" (ADDR)
- :"dIr" (nr));
+ :"dIr" (nr), "m" (ADDR));
}
/**
@@ -73,7 +73,7 @@ static __inline__ void clear_bit(long nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btrq %1,%0"
:"=m" (ADDR)
- :"dIr" (nr));
+ :"dIr" (nr), "m" (ADDR));
}
#define smp_mb__before_clear_bit() barrier()
#define smp_mb__after_clear_bit() barrier()
@@ -92,7 +92,7 @@ static __inline__ void __change_bit(long nr, volatile void * addr)
__asm__ __volatile__(
"btcq %1,%0"
:"=m" (ADDR)
- :"dIr" (nr));
+ :"dIr" (nr), "m" (ADDR));
}
/**
@@ -109,7 +109,7 @@ static __inline__ void change_bit(long nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btcq %1,%0"
:"=m" (ADDR)
- :"dIr" (nr));
+ :"dIr" (nr), "m" (ADDR));
}
/**
@@ -127,7 +127,7 @@ static __inline__ int test_and_set_bit(long nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btsq %2,%1\n\tsbbq %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"dIr" (nr) : "memory");
+ :"dIr" (nr), "m" (ADDR) : "memory");
return oldbit;
}
@@ -147,7 +147,7 @@ static __inline__ int __test_and_set_bit(long nr, volatile void * addr)
__asm__(
"btsq %2,%1\n\tsbbq %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"dIr" (nr));
+ :"dIr" (nr), "m" (ADDR));
return oldbit;
}
@@ -166,7 +166,7 @@ static __inline__ int test_and_clear_bit(long nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btrq %2,%1\n\tsbbq %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"dIr" (nr) : "memory");
+ :"dIr" (nr), "m" (ADDR) : "memory");
return oldbit;
}
@@ -186,7 +186,7 @@ static __inline__ int __test_and_clear_bit(long nr, volatile void * addr)
__asm__(
"btrq %2,%1\n\tsbbq %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"dIr" (nr));
+ :"dIr" (nr), "m" (ADDR));
return oldbit;
}
@@ -198,7 +198,7 @@ static __inline__ int __test_and_change_bit(long nr, volatile void * addr)
__asm__ __volatile__(
"btcq %2,%1\n\tsbbq %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"dIr" (nr) : "memory");
+ :"dIr" (nr), "m" (ADDR) : "memory");
return oldbit;
}
@@ -217,7 +217,7 @@ static __inline__ int test_and_change_bit(long nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btcq %2,%1\n\tsbbq %0,%0"
:"=r" (oldbit),"=m" (ADDR)
- :"dIr" (nr) : "memory");
+ :"dIr" (nr), "m" (ADDR) : "memory");
return oldbit;
}
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index fd524f2..57230bf 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -46,6 +46,7 @@ struct request {
struct buffer_head * bh;
struct buffer_head * bhtail;
request_queue_t *q;
+ char io_account;
};
#include <linux/elevator.h>
diff --git a/include/linux/smb_mount.h b/include/linux/smb_mount.h
index f4c049b..632af38 100644
--- a/include/linux/smb_mount.h
+++ b/include/linux/smb_mount.h
@@ -37,6 +37,10 @@ struct smb_mount_data {
#define SMB_MOUNT_OLDATTR 0x0002 /* Use core getattr (Win 95 speedup) */
#define SMB_MOUNT_DIRATTR 0x0004 /* Use find_first for getattr */
#define SMB_MOUNT_CASE 0x0008 /* Be case sensitive */
+#define SMB_MOUNT_UID 0x0020 /* Use user specified uid */
+#define SMB_MOUNT_GID 0x0040 /* Use user specified gid */
+#define SMB_MOUNT_FMODE 0x0080 /* Use user specified file mode */
+#define SMB_MOUNT_DMODE 0x0100 /* Use user specified dir mode */
struct smb_mount_data_kernel {
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 0e01fef..28d25a3 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -410,19 +410,6 @@ static inline int sctp_list_single_entry(struct list_head *head)
return ((head->next != head) && (head->next == head->prev));
}
-/* Calculate the size (in bytes) occupied by the data of an iovec. */
-static inline size_t get_user_iov_size(struct iovec *iov, int iovlen)
-{
- size_t retval = 0;
-
- for (; iovlen > 0; --iovlen) {
- retval += iov->iov_len;
- iov++;
- }
-
- return retval;
-}
-
/* Generate a random jitter in the range of -50% ~ +50% of input RTO. */
static inline __s32 sctp_jitter(__u32 rto)
{
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 5576db5..9052ddd 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -221,8 +221,7 @@ struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *,
const struct sctp_chunk *,
__u32 tsn);
struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *,
- const struct sctp_chunk *,
- const struct msghdr *);
+ const struct msghdr *, size_t msg_len);
struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
const struct sctp_chunk *,
const __u8 *,
diff --git a/mm/filemap.c b/mm/filemap.c
index a31c553..deea109 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1,7 +1,7 @@
/*
* linux/mm/filemap.c
*
- * Copyright (C) 1994-1999 Linus Torvalds
+ * Copyright (C) 1994-2006 Linus Torvalds
*/
/*
@@ -2808,46 +2808,51 @@ static unsigned char mincore_page(struct vm_area_struct * vma,
return present;
}
-static long mincore_vma(struct vm_area_struct * vma,
- unsigned long start, unsigned long end, unsigned char * vec)
+/*
+ * Do a chunk of "sys_mincore()". We've already checked
+ * all the arguments, we hold the mmap semaphore: we should
+ * just return the amount of info we're asked for.
+ */
+static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pages)
{
- long error, i, remaining;
- unsigned char * tmp;
-
- error = -ENOMEM;
- if (!vma->vm_file)
- return error;
+ unsigned long i, nr, pgoff;
+ struct vm_area_struct *vma = find_vma(current->mm, addr);
- start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
- if (end > vma->vm_end)
- end = vma->vm_end;
- end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
-
- error = -EAGAIN;
- tmp = (unsigned char *) __get_free_page(GFP_KERNEL);
- if (!tmp)
- return error;
+ /*
+ * find_vma() didn't find anything above us, or we're
+ * in an unmapped hole in the address space: ENOMEM.
+ */
+ if (!vma || addr < vma->vm_start)
+ return -ENOMEM;
- /* (end - start) is # of pages, and also # of bytes in "vec */
- remaining = (end - start),
+ /*
+ * Ok, got it. But check whether it's a segment we support
+ * mincore() on. Right now, we don't do any anonymous mappings.
+ *
+ * FIXME: This is just stupid. And returning ENOMEM is
+ * stupid too. We should just look at the page tables. But
+ * this is what we've traditionally done, so we'll just
+ * continue doing it.
+ */
+ if (!vma->vm_file)
+ return -ENOMEM;
- error = 0;
- for (i = 0; remaining > 0; remaining -= PAGE_SIZE, i++) {
- int j = 0;
- long thispiece = (remaining < PAGE_SIZE) ?
- remaining : PAGE_SIZE;
+ /*
+ * Calculate how many pages there are left in the vma, and
+ * what the pgoff is for our address.
+ */
+ nr = (vma->vm_end - addr) >> PAGE_SHIFT;
+ if (nr > pages)
+ nr = pages;
- while (j < thispiece)
- tmp[j++] = mincore_page(vma, start++);
+ pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
+ pgoff += vma->vm_pgoff;
- if (copy_to_user(vec + PAGE_SIZE * i, tmp, thispiece)) {
- error = -EFAULT;
- break;
- }
- }
+ /* And then we just fill the sucker in.. */
+ for (i = 0 ; i < nr; i++, pgoff++)
+ vec[i] = mincore_page(vma, pgoff);
- free_page((unsigned long) tmp);
- return error;
+ return nr;
}
/*
@@ -2867,77 +2872,61 @@ static long mincore_vma(struct vm_area_struct * vma,
* return values:
* zero - success
* -EFAULT - vec points to an illegal address
- * -EINVAL - addr is not a multiple of PAGE_CACHE_SIZE,
- * or len has a nonpositive value
+ * -EINVAL - addr is not a multiple of PAGE_CACHE_SIZE
* -ENOMEM - Addresses in the range [addr, addr + len] are
* invalid for the address space of this process, or
* specify one or more pages which are not currently
* mapped
* -EAGAIN - A kernel resource was temporarily unavailable.
*/
-asmlinkage long sys_mincore(unsigned long start, size_t len,
- unsigned char * vec)
+asmlinkage long sys_mincore(unsigned long start, size_t len, unsigned char *vec)
{
- int index = 0;
- unsigned long end;
- struct vm_area_struct * vma;
- int unmapped_error = 0;
- long error = -EINVAL;
+ long retval;
+ unsigned long pages;
+ unsigned char *tmp;
- down_read(¤t->mm->mmap_sem);
+ /* Check the start address: needs to be page-aligned.. */
+ if (start & ~PAGE_CACHE_MASK)
+ return -EINVAL;
- if (start & ~PAGE_CACHE_MASK)
- goto out;
- len = (len + ~PAGE_CACHE_MASK) & PAGE_CACHE_MASK;
- end = start + len;
- if (end < start)
- goto out;
+ /* ..and we need to be passed a valid user-space range */
+ if (!access_ok(VERIFY_READ, (void *) start, len))
+ return -ENOMEM;
- error = 0;
- if (end == start)
- goto out;
+ /* This also avoids any overflows on PAGE_CACHE_ALIGN */
+ pages = len >> PAGE_SHIFT;
+ pages += (len & ~PAGE_MASK) != 0;
- /*
- * If the interval [start,end) covers some unmapped address
- * ranges, just ignore them, but return -ENOMEM at the end.
- */
- vma = find_vma(current->mm, start);
- for (;;) {
- /* Still start < end. */
- error = -ENOMEM;
- if (!vma)
- goto out;
+ if (!access_ok(VERIFY_WRITE, vec, pages))
+ return -EFAULT;
- /* Here start < vma->vm_end. */
- if (start < vma->vm_start) {
- unmapped_error = -ENOMEM;
- start = vma->vm_start;
- }
+ tmp = (void *) __get_free_page(GFP_USER);
+ if (!tmp)
+ return -EAGAIN;
- /* Here vma->vm_start <= start < vma->vm_end. */
- if (end <= vma->vm_end) {
- if (start < end) {
- error = mincore_vma(vma, start, end,
- &vec[index]);
- if (error)
- goto out;
- }
- error = unmapped_error;
- goto out;
- }
+ retval = 0;
+ while (pages) {
+ /*
+ * Do at most PAGE_SIZE entries per iteration, due to
+ * the temporary buffer size.
+ */
+ down_read(¤t->mm->mmap_sem);
+ retval = do_mincore(start, tmp, min(pages, PAGE_SIZE));
+ up_read(¤t->mm->mmap_sem);
- /* Here vma->vm_start <= start < vma->vm_end < end. */
- error = mincore_vma(vma, start, vma->vm_end, &vec[index]);
- if (error)
- goto out;
- index += (vma->vm_end - start) >> PAGE_CACHE_SHIFT;
- start = vma->vm_end;
- vma = vma->vm_next;
+ if (retval <= 0)
+ break;
+ if (copy_to_user(vec, tmp, retval)) {
+ retval = -EFAULT;
+ break;
+ }
+ pages -= retval;
+ vec += retval;
+ start += retval << PAGE_SHIFT;
+ retval = 0;
}
-
-out:
- up_read(¤t->mm->mmap_sem);
- return error;
+ free_page((unsigned long) tmp);
+ return retval;
}
static inline
diff --git a/mm/memory.c b/mm/memory.c
index 9cde424..0df0dd9 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -750,7 +750,7 @@ int unlock_kiovec(int nr, struct kiobuf *iovec[])
return 0;
}
-static inline void zeromap_pte_range(pte_t * pte, unsigned long address,
+static inline int zeromap_pte_range(pte_t * pte, unsigned long address,
unsigned long size, pgprot_t prot)
{
unsigned long end;
@@ -761,12 +761,13 @@ static inline void zeromap_pte_range(pte_t * pte, unsigned long address,
end = PMD_SIZE;
do {
pte_t zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE(address), prot));
- pte_t oldpage = ptep_get_and_clear(pte);
+ if (!pte_none(*pte))
+ return -EEXIST;
set_pte(pte, zero_pte);
- forget_pte(oldpage);
address += PAGE_SIZE;
pte++;
} while (address && (address < end));
+ return 0;
}
static inline int zeromap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address,
@@ -782,7 +783,8 @@ static inline int zeromap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned
pte_t * pte = pte_alloc(mm, pmd, address);
if (!pte)
return -ENOMEM;
- zeromap_pte_range(pte, address, end - address, prot);
+ if (zeromap_pte_range(pte, address, end - address, prot))
+ return -EEXIST;
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address && (address < end));
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 4d2a93a..bda5090 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -293,7 +293,7 @@ void * vmap(struct page **pages, int count,
struct vm_struct *area;
unsigned long size = count << PAGE_SHIFT;
- if (!size || size > (max_mapnr << PAGE_SHIFT))
+ if (count <= 0 || count > max_mapnr)
return NULL;
area = get_vm_area(size, flags);
if (!area) {
diff --git a/net/atm/clip.c b/net/atm/clip.c
index a7ded5b..5905d30 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -489,9 +489,11 @@ static int clip_mkip(struct atm_vcc *vcc,int timeout)
else {
unsigned int len = skb->len;
+ skb_get(skb);
clip_push(vcc,skb);
PRIV(skb->dev)->stats.rx_packets--;
PRIV(skb->dev)->stats.rx_bytes -= len;
+ kfree_skb(skb);
}
return 0;
}
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index cc91b75..6273fe3 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -192,6 +192,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
switch (CAPIMSG_SUBCOMMAND(skb->data)) {
case CAPI_CONF:
+ if (skb->len < CAPI_MSG_BASELEN + 10)
+ break;
+
func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5);
info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8);
@@ -222,6 +225,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;
case CAPI_FUNCTION_GET_PROFILE:
+ if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile))
+ break;
+
controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11);
msgnum = CAPIMSG_MSGID(skb->data);
@@ -242,17 +248,26 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;
case CAPI_FUNCTION_GET_MANUFACTURER:
+ if (skb->len < CAPI_MSG_BASELEN + 15)
+ break;
+
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10);
if (!info && ctrl) {
+ int len = min_t(uint, CAPI_MANUFACTURER_LEN,
+ skb->data[CAPI_MSG_BASELEN + 14]);
+
+ memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
strncpy(ctrl->manu,
- skb->data + CAPI_MSG_BASELEN + 15,
- skb->data[CAPI_MSG_BASELEN + 14]);
+ skb->data + CAPI_MSG_BASELEN + 15, len);
}
break;
case CAPI_FUNCTION_GET_VERSION:
+ if (skb->len < CAPI_MSG_BASELEN + 32)
+ break;
+
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
if (!info && ctrl) {
@@ -265,13 +280,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;
case CAPI_FUNCTION_GET_SERIAL_NUMBER:
+ if (skb->len < CAPI_MSG_BASELEN + 17)
+ break;
+
controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12);
if (!info && ctrl) {
+ int len = min_t(uint, CAPI_SERIAL_LEN,
+ skb->data[CAPI_MSG_BASELEN + 16]);
+
memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
strncpy(ctrl->serial,
- skb->data + CAPI_MSG_BASELEN + 17,
- skb->data[CAPI_MSG_BASELEN + 16]);
+ skb->data + CAPI_MSG_BASELEN + 17, len);
}
break;
@@ -280,14 +300,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
break;
case CAPI_IND:
+ if (skb->len < CAPI_MSG_BASELEN + 6)
+ break;
+
func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3);
if (func == CAPI_FUNCTION_LOOPBACK) {
+ int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6,
+ skb->data[CAPI_MSG_BASELEN + 5]);
appl = CAPIMSG_APPID(skb->data);
msgnum = CAPIMSG_MSGID(skb->data);
cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func,
- skb->data + CAPI_MSG_BASELEN + 6,
- skb->data[CAPI_MSG_BASELEN + 5]);
+ skb->data + CAPI_MSG_BASELEN + 6, len);
}
break;
@@ -305,6 +329,9 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
BT_DBG("session %p skb %p len %d", session, skb, skb->len);
+ if (skb->len < CAPI_MSG_BASELEN)
+ return;
+
if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) {
cmtp_recv_interopmsg(session, skb);
return;
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 5d61475..3de15aa 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -140,8 +140,8 @@ void br_become_root_bridge(struct net_bridge *br)
br->forward_delay = br->bridge_forward_delay;
br_topology_change_detection(br);
br_timer_clear(&br->tcn_timer);
- br_config_bpdu_generation(br);
- br_timer_set(&br->hello_timer, jiffies);
+
+ br_timer_set(&br->hello_timer, jiffies - br->hello_time);
}
/* called under bridge lock */
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 1465093..75cce3f 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -510,6 +510,8 @@ static struct sk_buff *fill_packet(struct net_device *odev, struct pktgen_info*
skb->mac.raw = ((u8 *)iph) - 14;
skb->dev = odev;
skb->pkt_type = PACKET_HOST;
+ skb->nh.iph = iph;
+ skb->h.uh = udph;
if (info->nfrags <= 0) {
pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index 6298d96..645f46d 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -522,13 +522,7 @@ int ip_nat_helper_register(struct ip_nat_helper *me)
static int
kill_helper(struct ip_conntrack *i, void *helper)
{
- int ret;
-
- READ_LOCK(&ip_nat_lock);
- ret = (i->nat.info.helper == helper);
- READ_UNLOCK(&ip_nat_lock);
-
- return ret;
+ return (i->nat.info.helper == helper);
}
void ip_nat_helper_unregister(struct ip_nat_helper *me)
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 9ae7175..4218a97 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -123,6 +123,9 @@ int sctp_rcv(struct sk_buff *skb)
SCTP_INC_STATS_BH(SctpInSCTPPacks);
+ if (skb_linearize(skb, GFP_ATOMIC) != 0)
+ goto discard_it;
+
sh = (struct sctphdr *) skb->h.raw;
/* Pull up the IP and SCTP headers. */
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 556dee6..08fe461 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -798,38 +798,26 @@ no_mem:
/* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */
struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc,
- const struct sctp_chunk *chunk,
- const struct msghdr *msg)
+ const struct msghdr *msg,
+ size_t paylen)
{
struct sctp_chunk *retval;
- void *payload = NULL, *payoff;
- size_t paylen = 0;
- struct iovec *iov = NULL;
- int iovlen = 0;
-
- if (msg) {
- iov = msg->msg_iov;
- iovlen = msg->msg_iovlen;
- paylen = get_user_iov_size(iov, iovlen);
- }
+ void *payload = NULL;
+ int err;
- retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen);
+ retval = sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t) + paylen);
if (!retval)
goto err_chunk;
if (paylen) {
/* Put the msg_iov together into payload. */
- payload = kmalloc(paylen, GFP_ATOMIC);
+ payload = kmalloc(paylen, GFP_KERNEL);
if (!payload)
goto err_payload;
- payoff = payload;
- for (; iovlen > 0; --iovlen) {
- if (copy_from_user(payoff, iov->iov_base,iov->iov_len))
- goto err_copy;
- payoff += iov->iov_len;
- iov++;
- }
+ err = memcpy_fromiovec(payload, msg->msg_iov, paylen);
+ if (err < 0)
+ goto err_copy;
}
sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 542f375..992043f 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3990,18 +3990,12 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
* from its upper layer, but retransmits data to the far end
* if necessary to fill gaps.
*/
- struct msghdr *msg = arg;
- struct sctp_chunk *abort;
+ struct sctp_chunk *abort = arg;
sctp_disposition_t retval;
retval = SCTP_DISPOSITION_CONSUME;
- /* Generate ABORT chunk to send the peer. */
- abort = sctp_make_abort_user(asoc, NULL, msg);
- if (!abort)
- retval = SCTP_DISPOSITION_NOMEM;
- else
- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
/* Even if we can't send the ABORT due to low memory delete the
* TCB. This is a departure from our typical NOMEM handling.
@@ -4123,8 +4117,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
void *arg,
sctp_cmd_seq_t *commands)
{
- struct msghdr *msg = arg;
- struct sctp_chunk *abort;
+ struct sctp_chunk *abort = arg;
sctp_disposition_t retval;
/* Stop T1-init timer */
@@ -4132,12 +4125,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
retval = SCTP_DISPOSITION_CONSUME;
- /* Generate ABORT chunk to send the peer */
- abort = sctp_make_abort_user(asoc, NULL, msg);
- if (!abort)
- retval = SCTP_DISPOSITION_NOMEM;
- else
- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 277b19f..8d13849 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -967,9 +967,13 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
sctp_unhash_established(asoc);
sctp_association_free(asoc);
- } else if (sk->linger && !sk->lingertime)
- sctp_primitive_ABORT(asoc, NULL);
- else
+ } else if (sk->linger && !sk->lingertime) {
+ struct sctp_chunk *chunk;
+
+ chunk = sctp_make_abort_user(asoc, NULL, 0);
+ if (chunk)
+ sctp_primitive_ABORT(asoc, NULL);
+ } else
sctp_primitive_SHUTDOWN(asoc, NULL);
} else
sctp_primitive_SHUTDOWN(asoc, NULL);
@@ -1199,8 +1203,16 @@ SCTP_STATIC int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int msg_len)
goto out_unlock;
}
if (sinfo_flags & MSG_ABORT) {
+ struct sctp_chunk *chunk;
+
+ chunk = sctp_make_abort_user(asoc, msg, msg_len);
+ if (!chunk) {
+ err = -ENOMEM;
+ goto out_unlock;
+ }
+
SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc);
- sctp_primitive_ABORT(asoc, msg);
+ sctp_primitive_ABORT(asoc, chunk);
err = 0;
goto out_unlock;
}
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index b5a1447..fcafbf7 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -807,7 +807,7 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp)
return 0;
}
- if (test_bit(SK_CONN, &svsk->sk_flags)) {
+ if (svsk->sk_sk->state == TCP_LISTEN) {
svc_tcp_accept(svsk);
svc_sock_received(svsk);
return 0;
www.fiveanddime.net