2.6.32.30-longterm review
Subsystems (48)
cover 2.6.32.30-longterm review
This is the start of the longterm review cycle for the 2.6.32.30 release. There are 68 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let us know. If anyone is a maintainer of the proper subsystem, and wants to add a Signed-off-by: line to the patch, please respond with it.
Responses should be made by Wed, March 2, 16:00:00, 2010, UTC Anything received after that time might be too late.
The whole patch series can be found in one patch at:
kernel.org/pub/linux/kernel/v2.6/longterm-review/patch-2.6.32.30-rc1.gz
and the diffstat can be found below.
thanks,
greg k-h
Makefile | 2 +- arch/arm/kernel/signal.c | 4 +- arch/s390/include/asm/processor.h | 5 - arch/s390/kernel/traps.c | 37 ---- arch/x86/include/asm/acpi.h | 1 + arch/x86/include/asm/pvclock.h | 1 + arch/x86/kernel/acpi/boot.c | 14 +- arch/x86/kernel/early-quirks.c | 16 +- arch/x86/kernel/hpet.c | 12 +- arch/x86/kernel/pvclock.c | 5 + arch/x86/xen/time.c | 2 + drivers/block/pktcdvd.c | 2 +- drivers/isdn/hisax/config.c | 18 ++- drivers/isdn/hisax/hisax.h | 1 + drivers/md/dm-raid1.c | 2 +- drivers/md/dm-region-hash.c | 5 +- drivers/md/md.c | 3 + drivers/media/dvb/ttpci/av7110_ca.c | 2 +- drivers/media/radio/radio-aimslab.c | 1 + drivers/message/fusion/mptctl.c | 8 + drivers/message/fusion/mptscsih.c | 7 +- drivers/net/benet/be.h | 2 + drivers/net/benet/be_main.c | 18 +- drivers/net/bonding/bond_ipv6.c | 9 +- drivers/net/ixgbe/ixgbe_82599.c | 1 + drivers/net/ixgbe/ixgbe_main.c | 3 + drivers/net/ixgbe/ixgbe_type.h | 1 + drivers/net/wireless/p54/p54pci.c | 14 +- drivers/platform/x86/acer-wmi.c | 4 +- drivers/platform/x86/asus_acpi.c | 8 +- drivers/platform/x86/tc1100-wmi.c | 2 +- drivers/scsi/device_handler/scsi_dh_alua.c | 2 + drivers/staging/usbip/vhci.h | 6 +- drivers/staging/usbip/vhci_hcd.c | 54 +++++- drivers/staging/usbip/vhci_rx.c | 15 +- drivers/usb/core/hcd-pci.c | 4 +- drivers/usb/core/quirks.c | 8 + drivers/usb/host/ohci-hcd.c | 9 +- drivers/usb/host/ohci-pci.c | 18 ++ drivers/usb/host/ohci.h | 1 + drivers/usb/host/pci-quirks.c | 18 +- drivers/usb/host/xhci-ring.c | 36 ++-- drivers/usb/musb/omap2430.c | 1 + drivers/usb/serial/sierra.c | 3 + drivers/usb/serial/visor.c | 12 ++ fs/ecryptfs/inode.c | 2 + fs/eventpoll.c | 95 +++++++++ fs/file_table.c | 2 +- fs/gfs2/bmap.c | 2 +- fs/nfs/file.c | 2 +- fs/nfsd/nfs4xdr.c | 8 +- fs/nfsd/vfs.c | 2 +- fs/ocfs2/stack_user.c | 2 +- fs/partitions/ldm.c | 5 + fs/partitions/mac.c | 17 +- fs/proc/array.c | 5 +- fs/read_write.c | 2 - fs/splice.c | 24 ++- fs/xfs/linux-2.6/xfs_export.c | 11 +- fs/xfs/linux-2.6/xfs_ioctl.c | 7 +- fs/xfs/linux-2.6/xfs_ioctl32.c | 15 +- fs/xfs/quota/xfs_qm.c | 18 +- fs/xfs/quota/xfs_qm_syscalls.c | 27 ++-- fs/xfs/xfs_ialloc.c | 150 +++++++++------ fs/xfs/xfs_iget.c | 10 +- fs/xfs/xfs_inode.c | 5 +- fs/xfs/xfs_inode.h | 6 +- fs/xfs/xfs_itable.c | 284 ++++------------------------ fs/xfs/xfs_itable.h | 17 -- fs/xfs/xfs_log_recover.c | 2 +- fs/xfs/xfs_mount.c | 2 +- fs/xfs/xfs_rtalloc.c | 4 +- fs/xfs/xfs_trans_inode.c | 2 +- fs/xfs/xfs_vnodeops.c | 2 +- include/linux/cred.h | 21 +-- kernel/cred.c | 41 ++++- kernel/irq/manage.c | 2 +- kernel/power/snapshot.c | 7 +- net/core/filter.c | 64 ++++--- net/ipv4/tcp.c | 2 +- net/sctp/auth.c | 8 +- net/sunrpc/cache.c | 4 +- net/x25/x25_link.c | 1 + security/selinux/hooks.c | 6 +- sound/pci/hda/hda_intel.c | 1 + sound/usb/caiaq/audio.c | 2 +- sound/usb/caiaq/midi.c | 2 +- 87 files changed, 662 insertions(+), 626 deletions(-)
PATCH 1/68 NFSD: memory corruption due to writing beyond the stat array
2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Konstantin Khorenko <[email protected]>
commit 3aa6e0aa8ab3e64bbfba092c64d42fd1d006b124 upstream.
If nfsd fails to find an exported via NFS file in the readahead cache, it should increment corresponding nfsdstats counter (ra_depth[10]), but due to a bug it may instead write to ra_depth[11], corrupting the following field.
In a kernel with NFSDv4 compiled in the corruption takes the form of an increment of a counter of the number of NFSv4 operation 0's received; since there is no operation 0, this is harmless.
In a kernel with NFSDv4 disabled it corrupts whatever happens to be in the memory beyond nfsdstats.
--- fs/nfsd/vfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/vfs.c +1 -1
@@ -823,7 +823,7 @@ nfsd_get_raparms(dev_t dev, ino_t ino)if (ra->p_count ==0 ) frap = rap; } - depth = nfsdstats.ra_size*11 /10 ; + depth = nfsdstats.ra_size;if (!frap) {spin_unlock (&rab->pb_lock);return NULL ;
PATCH 2/68 mptfusion: mptctl_release is required in mptctl.c
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Kashyap, Desai <[email protected]>
commit 84857c8bf83e8aa87afc57d2956ba01f11d82386 upstream.
Added missing release callback for file_operations mptctl_fops. Without release callback there will be never freed. It remains on mptctl's eent list even after the file is closed and released.
Relavent RHEL bugzilla is 660871
--- drivers/message/fusion/mptctl.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/message/fusion/mptctl.c +8 -0
@@ -577,6 +577,13 @@ mptctl_event_process(MPT_ADAPTER *ioc, E }static int +mptctl_release (struct inode *inode,struct file *filep) +{ +fasync_helper (-1 , filep,0 , &async_queue); +return 0 ; +} + +static int mptctl_fasync (int fd,struct file *filep,int mode) {MPT_ADAPTER *ioc;
@@ -2778,6 +2785,7 @@ static const struct file_operations mptc .llseek = no_llseek, .fasync = mptctl_fasync, .unlocked_ioctl = mptctl_ioctl, + .release = mptctl_release,#ifdef CONFIG_COMPAT .compat_ioctl = compat_mpctl_ioctl,#endif
PATCH 3/68 mptfusion: Fix Incorrect return value in mptscsih_dev_reset
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Kashyap, Desai <[email protected]>
commit bcfe42e98047f1935c5571c8ea77beb2d43ec19d upstream.
There's a branch at the end of this function that is supposed to normalize the return value with what the mid-layer expects. In this one case, we get it wrong.
Also increase the verbosity of the INFO level printk at the end of mptscsih_abort to include the actual return value and the scmd->serial_number. The reason being success or failure is actually determined by the state of
the internal tag list when a TMF is issued, and not the return value of the TMF cmd. The serial_number is also used in this decision, thus it's useful to know for debugging purposes.
--- drivers/message/fusion/mptscsih.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/message/fusion/mptscsih.c +4 -3
@@ -1835,8 +1835,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) } out: -printk (MYIOC_s_INFO_FMT"task abort: %s (sc=%p)\n" , - ioc->name, ((retval ==SUCCESS ) ?"SUCCESS" :"FAILED" ), SCpnt); +printk (MYIOC_s_INFO_FMT"task abort: %s (rv=%04x) (sc=%p) (sn=%ld)\n" , + ioc->name, ((retval ==SUCCESS ) ?"SUCCESS" :"FAILED" ), retval, + SCpnt, SCpnt->serial_number);return retval; }
@@ -1873,7 +1874,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SC vdevice = SCpnt->device->hostdata;if (!vdevice || !vdevice->vtarget) { - retval =SUCCESS ; + retval =0 ; goto out; }
PATCH 4/68 sctp: Fix out-of-bounds reading in sctp_asoc_get_hmac()
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Dan Rosenberg <[email protected]>
commit 51e97a12bef19b7e43199fc153cf9bd5f2140362 upstream.
The sctp_asoc_get_hmac() function iterates through a peer's hmac_ids array and attempts to ensure that only a supported hmac entry is returned. The current code fails to do this properly - if the last id in the array is out of range (greater than SCTP_AUTH_HMAC_ID_MAX), the id integer remains set after exiting the loop, and the address of an out-of-bounds entry will be returned and subsequently used in the parent function, causing potentially ugly memory corruption. This patch resets the id integer to 0 on encountering an invalid id so that NULL will be returned after finishing the loop if no valid ids are found.
--- net/sctp/auth.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
net/sctp/auth.c +6 -2
@@ -542,16 +542,20 @@ struct sctp_hmac *sctp_auth_asoc_get_hma id =ntohs (hmacs->hmac_ids[i]);/* Check the id is in the supported range */ -if (id >SCTP_AUTH_HMAC_ID_MAX ) +if (id >SCTP_AUTH_HMAC_ID_MAX ) { + id =0 ;continue ; + }/* See is we support the id. Supported IDs have name and * length fields set, so that we can allocated and use * them. We can safely just check for name, for without the * name, we can't allocate the TFM. */ -if (!sctp_hmac_list[id].hmac_name) +if (!sctp_hmac_list[id].hmac_name) { + id =0 ;continue ; + }break ; }
PATCH 5/68 ocfs2_connection_find() returns pointer to bad structure
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: dann frazier <[email protected]>
commit 226291aa4641fa13cb5dec3bcb3379faa83009e2 upstream.
If ocfs2_live_connection_list is empty, ocfs2_connection_find() will return a pointer to the LIST_HEAD, cast as a ocfs2_live_connection. This can cause an oops when ocfs2_control_send_down() dereferences c->oc_conn:
Call Trace: [<ffffffffa00c2a3c>] ocfs2_control_message+0x28c/0x2b0 [ocfs2_stack_user] [<ffffffffa00c2a95>] ocfs2_control_write+0x35/0xb0 [ocfs2_stack_user] [<ffffffff81143a88>] vfs_write+0xb8/0x1a0 [<ffffffff8155cc13>] ? do_page_fault+0x153/0x3b0 [<ffffffff811442f1>] sys_write+0x51/0x80 [<ffffffff810121b2>] system_call_fastpath+0x16/0x1b
Fix by explicitly returning NULL if no match is found.
--- fs/ocfs2/stack_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ocfs2/stack_user.c +1 -1
@@ -191,7 +191,7 @@ static struct ocfs2_live_connection *ocfreturn c; } -return c; +return NULL ; }/*
PATCH 6/68 Fix pktcdvd ioctl dev_minor range check
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Dan Rosenberg <[email protected]>
commit 252a52aa4fa22a668f019e55b3aac3ff71ec1c29 upstream.
The PKT_CTRL_CMD_STATUS device ioctl retrieves a pointer to a pktcdvd_device from the global pkt_devs array. The index into this array is provided directly by the user and is a signed integer, so the comparison to ensure that it falls within the bounds of this array will fail when provided with a negative index.
This can be used to read arbitrary kernel memory or cause a crash due to an invalid pointer dereference. This can be exploited by users with permission to open /dev/pktcdvd/control (on many distributions, this is readable by group "cdrom").
--- drivers/block/pktcdvd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/block/pktcdvd.c +1 -1
@@ -2408,7 +2408,7 @@ static void pkt_release_dev(struct pktcdpkt_shrink_pktlist (pd); } -static struct pktcdvd_device *pkt_find_dev_from_minor (int dev_minor) +static struct pktcdvd_device *pkt_find_dev_from_minor (unsigned int dev_minor) {if (dev_minor >=MAX_WRITERS )return NULL ;
PATCH 7/68 filter: make sure filters dont read uninitialized memory
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: David S. Miller <[email protected]>
commit 57fe93b374a6b8711995c2d466c502af9f3a08bb upstream.
There is a possibility malicious users can get limited information about uninitialized stack mem array. Even if sk_run_filter() result is bound to packet length (0 .. 65535), we could imagine this can be used by hostile user.
Initializing mem[] array, like Dan Rosenberg suggested in his patch is expensive since most filters dont even use this array.
Its hard to make the filter validation in sk_chk_filter(), because of the jumps. This might be done later.
In this patch, I use a bitmap (a single long var) so that only filters using mem[] loads/stores pay the price of added security checks.
For other filters, additional cost is a single instruction.
[ Since we access fentry->k a lot now, cache it in a local variable
and mark filter entry pointer as const. -DaveM ]
--- net/core/filter.c | 64 +++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 29 deletions(-)
net/core/filter.c +35 -29
@@ -111,39 +111,41 @@ EXPORT_SYMBOL(sk_filter);*/ unsigned int sk_run_filter (struct sk_buff *skb,struct sock_filter *filter,int flen) { -struct sock_filter *fentry;/* We walk down these */ void *ptr;u32 A =0 ;/* Accumulator */ u32 X =0 ;/* Index Register */ u32 mem[BPF_MEMWORDS ];/* Scratch Memory Store */ +unsigned long memvalid =0 ;u32 tmp;int k;int pc; +BUILD_BUG_ON (BPF_MEMWORDS >BITS_PER_LONG );/* * Process array of filter instructions. */ for (pc =0 ; pc < flen; pc++) { - fentry = &filter[pc]; +const struct sock_filter *fentry = &filter[pc]; +u32 f_k = fentry->k;switch (fentry->code) {case BPF_ALU |BPF_ADD |BPF_X :A +=X ;continue ;case BPF_ALU |BPF_ADD |BPF_K : -A += fentry->k; +A += f_k;continue ;case BPF_ALU |BPF_SUB |BPF_X :A -=X ;continue ;case BPF_ALU |BPF_SUB |BPF_K : -A -= fentry->k; +A -= f_k;continue ;case BPF_ALU |BPF_MUL |BPF_X :A *=X ;continue ;case BPF_ALU |BPF_MUL |BPF_K : -A *= fentry->k; +A *= f_k;continue ;case BPF_ALU |BPF_DIV |BPF_X :if (X ==0 )
@@ -151,49 +153,49 @@ unsigned int sk_run_filter(struct sk_bufA /=X ;continue ;case BPF_ALU |BPF_DIV |BPF_K : -A /= fentry->k; +A /= f_k;continue ;case BPF_ALU |BPF_AND |BPF_X :A &=X ;continue ;case BPF_ALU |BPF_AND |BPF_K : -A &= fentry->k; +A &= f_k;continue ;case BPF_ALU |BPF_OR |BPF_X :A |=X ;continue ;case BPF_ALU |BPF_OR |BPF_K : -A |= fentry->k; +A |= f_k;continue ;case BPF_ALU |BPF_LSH |BPF_X :A <<=X ;continue ;case BPF_ALU |BPF_LSH |BPF_K : -A <<= fentry->k; +A <<= f_k;continue ;case BPF_ALU |BPF_RSH |BPF_X :A >>=X ;continue ;case BPF_ALU |BPF_RSH |BPF_K : -A >>= fentry->k; +A >>= f_k;continue ;case BPF_ALU |BPF_NEG :A = -A ;continue ;case BPF_JMP |BPF_JA : - pc += fentry->k; + pc += f_k;continue ;case BPF_JMP |BPF_JGT |BPF_K : - pc += (A > fentry->k) ? fentry->jt : fentry->jf; + pc += (A > f_k) ? fentry->jt : fentry->jf;continue ;case BPF_JMP |BPF_JGE |BPF_K : - pc += (A >= fentry->k) ? fentry->jt : fentry->jf; + pc += (A >= f_k) ? fentry->jt : fentry->jf;continue ;case BPF_JMP |BPF_JEQ |BPF_K : - pc += (A == fentry->k) ? fentry->jt : fentry->jf; + pc += (A == f_k) ? fentry->jt : fentry->jf;continue ;case BPF_JMP |BPF_JSET |BPF_K : - pc += (A & fentry->k) ? fentry->jt : fentry->jf; + pc += (A & f_k) ? fentry->jt : fentry->jf;continue ;case BPF_JMP |BPF_JGT |BPF_X : pc += (A >X ) ? fentry->jt : fentry->jf;
@@ -208,7 +210,7 @@ unsigned int sk_run_filter(struct sk_buf pc += (A &X ) ? fentry->jt : fentry->jf;continue ;case BPF_LD |BPF_W |BPF_ABS : - k = fentry->k; + k = f_k; load_w: ptr =load_pointer (skb, k,4 , &tmp);if (ptr !=NULL ) {
@@ -217,7 +219,7 @@ load_w: }break ;case BPF_LD |BPF_H |BPF_ABS : - k = fentry->k; + k = f_k; load_h: ptr =load_pointer (skb, k,2 , &tmp);if (ptr !=NULL ) {
@@ -226,7 +228,7 @@ load_h: }break ;case BPF_LD |BPF_B |BPF_ABS : - k = fentry->k; + k = f_k; load_b: ptr =load_pointer (skb, k,1 , &tmp);if (ptr !=NULL ) {
@@ -241,32 +243,34 @@ load_b:X = skb->len;continue ;case BPF_LD |BPF_W |BPF_IND : - k =X + fentry->k; + k =X + f_k; goto load_w;case BPF_LD |BPF_H |BPF_IND : - k =X + fentry->k; + k =X + f_k; goto load_h;case BPF_LD |BPF_B |BPF_IND : - k =X + fentry->k; + k =X + f_k; goto load_b;case BPF_LDX |BPF_B |BPF_MSH : - ptr =load_pointer (skb, fentry->k,1 , &tmp); + ptr =load_pointer (skb, f_k,1 , &tmp);if (ptr !=NULL ) {X = (*(u8 *)ptr &0xf ) <<2 ;continue ; }return 0 ;case BPF_LD |BPF_IMM : -A = fentry->k; +A = f_k;continue ;case BPF_LDX |BPF_IMM : -X = fentry->k; +X = f_k;continue ;case BPF_LD |BPF_MEM : -A = mem[fentry->k]; +A = (memvalid & (1UL << f_k)) ? + mem[f_k] :0 ;continue ;case BPF_LDX |BPF_MEM : -X = mem[fentry->k]; +X = (memvalid & (1UL << f_k)) ? + mem[f_k] :0 ;continue ;case BPF_MISC |BPF_TAX :X =A ;
@@ -275,14 +279,16 @@ load_b:A =X ;continue ;case BPF_RET |BPF_K : -return fentry->k; +return f_k;case BPF_RET |BPF_A :return A ;case BPF_ST : - mem[fentry->k] =A ; + memvalid |=1UL << f_k; + mem[f_k] =A ;continue ;case BPF_STX : - mem[fentry->k] =X ; + memvalid |=1UL << f_k; + mem[f_k] =X ;continue ;default :WARN_ON (1 );
PATCH v3 12/68 av7110: check for negative array offset
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Dan Carpenter <[email protected]>
commit cb26a24ee9706473f31d34cc259f4dcf45cd0644 upstream.
info->num comes from the user. It's type int. If the user passes in a negative value that would cause memory corruption.
--- drivers/media/dvb/ttpci/av7110_ca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/dvb/ttpci/av7110_ca.c +1 -1
@@ -277,7 +277,7 @@ static int dvb_ca_ioctl(struct inode *in {ca_slot_info_t *info=(ca_slot_info_t *)parg; -if (info->num >1 ) +if (info->num <0 || info->num >1 )return -EINVAL ; av7110->ci_slot[info->num].num = info->num; av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
PATCH 8/68 x25: decrement netdev reference counts on unload
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Apollon Oikonomopoulos <[email protected]>
commit 171995e5d82dcc92bea37a7d2a2ecc21068a0f19 upstream.
x25 does not decrement the network device reference counts on module unload. Thus unregistering any pre-existing interface after unloading the x25 module hangs and results in
unregister_netdevice: waiting for tap0 to become free. Usage count = 1
This patch decrements the reference counts of all interfaces in x25_link_free, the way it is already done in x25_link_device_down for NETDEV_DOWN events.
--- net/x25/x25_link.c | 1 + 1 file changed, 1 insertion(+)
net/x25/x25_link.c +1 -0
@@ -393,6 +393,7 @@ void __exit x25_link_free(void)list_for_each_safe (entry, tmp, &x25_neigh_list) { nb = list_entry(entry, struct x25_neigh, node);__x25_remove_neigh (nb); +dev_put (nb->dev); }write_unlock_bh (&x25_neigh_list_lock); }
PATCH 9/68 x86, hpet: Disable per-cpu hpet timer if ARAT is supported
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Shaohua Li <[email protected]>
commit 39fe05e58c5e448601ce46e6b03900d5bf31c4b0 upstream.
If CPU support always running local APIC timer, per-cpu hpet timer could be disabled, which is useless and wasteful in such case. Let's leave the timers to others.
The effect is that we reserve less timers.
LKML-Reference: <[email protected]>
--- arch/x86/kernel/hpet.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
arch/x86/kernel/hpet.c +10 -2
@@ -606,6 +606,8 @@ static void hpet_msi_capability_lookup(uif (hpet_msi_disable)return ; +if (boot_cpu_has (X86_FEATURE_ARAT )) +return ; id =hpet_readl (HPET_ID ); num_timers = ((id &HPET_ID_NUMBER ) >>HPET_ID_NUMBER_SHIFT );
@@ -894,10 +896,8 @@ int __init hpet_enable(void)if (id &HPET_ID_LEGSUP ) {hpet_legacy_clockevent_register (); -hpet_msi_capability_lookup (2 );return 1 ; } -hpet_msi_capability_lookup (0 );return 0 ; out_nohpet:
@@ -930,12 +930,20 @@ static __init int hpet_late_init(void)if (!hpet_virt_address)return -ENODEV ; +if (hpet_readl (HPET_ID ) &HPET_ID_LEGSUP ) +hpet_msi_capability_lookup (2 ); +else +hpet_msi_capability_lookup (0 ); +hpet_reserve_platform_timers (hpet_readl (HPET_ID ));hpet_print_config ();if (hpet_msi_disable)return 0 ; +if (boot_cpu_has (X86_FEATURE_ARAT )) +return 0 ; +for_each_online_cpu (cpu) {hpet_cpuhp_notify (NULL ,CPU_ONLINE , (void *)(long )cpu); }
PATCH 10/68 OHCI: work around for nVidia shutdown problem
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit 3df7169e73fc1d71a39cffeacc969f6840cdf52b upstream.
This patch (as1417) fixes a problem affecting some (or all) nVidia chipsets. When the computer is shut down, the OHCI controllers continue to power the USB buses and evidently they drive a Reset signal out all their ports. This prevents attached devices from going to low power. Mouse LEDs stay on, for example, which is disconcerting for users and a drain on laptop batteries.
The fix involves leaving each OHCI controller in the OPERATIONAL state during system shutdown rather than putting it in the RESET state. Although this nominally means the controller is running, in fact it's not doing very much since all the schedules are all disabled. However there is ongoing DMA to the Host Controller Communications Area, so the patch also disables the bus-master capability of all PCI USB controllers after the shutdown routine runs.
The fix is applied only to nVidia-based PCI OHCI controllers, so it shouldn't cause problems on systems using other hardware. As an added safety measure, in case the kernel encounters one of these running controllers during boot, the patch changes quirk_usb_handoff_ohci() (which runs early on during PCI discovery) to reset the controller before anything bad can happen.
--- drivers/usb/core/hcd-pci.c | 4 +++- drivers/usb/host/ohci-hcd.c | 9 ++++++++- drivers/usb/host/ohci-pci.c | 18 ++++++++++++++++++ drivers/usb/host/ohci.h | 1 + drivers/usb/host/pci-quirks.c | 18 +++++++++++------- 5 files changed, 41 insertions(+), 9 deletions(-)
drivers/usb/core/hcd-pci.c +3 -1
@@ -197,8 +197,10 @@ void usb_hcd_pci_shutdown(struct pci_devif (!hcd)return ; -if (hcd->driver->shutdown) +if (hcd->driver->shutdown) { hcd->driver->shutdown (hcd); +pci_disable_device (dev); + } }EXPORT_SYMBOL_GPL (usb_hcd_pci_shutdown);
drivers/usb/host/ohci-hcd.c +8 -1
@@ -398,7 +398,14 @@ ohci_shutdown (struct usb_hcd *hcd) ohci =hcd_to_ohci (hcd);ohci_writel (ohci,OHCI_INTR_MIE , &ohci->regs->intrdisable); -ohci_usb_reset (ohci); + ohci->hc_control =ohci_readl (ohci, &ohci->regs->control); + +/* If the SHUTDOWN quirk is set, don't put the controller in RESET */ + ohci->hc_control &= (ohci->flags &OHCI_QUIRK_SHUTDOWN ? +OHCI_CTRL_RWC |OHCI_CTRL_HCFS : +OHCI_CTRL_RWC ); +ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); +/* flush the writes */ (void )ohci_readl (ohci, &ohci->regs->control); }
drivers/usb/host/ohci-pci.c +18 -0
@@ -201,6 +201,20 @@ static int ohci_quirk_amd700(struct usb_return 0 ; } +/* nVidia controllers continue to drive Reset signalling on the bus +* even after system shutdown, wasting power. This flag tells the +* shutdown routine to leave the controller OPERATIONAL instead of RESET. +*/ +static int ohci_quirk_nvidia_shutdown (struct usb_hcd *hcd) +{ +struct ohci_hcd *ohci =hcd_to_ohci (hcd); + + ohci->flags |=OHCI_QUIRK_SHUTDOWN ; +ohci_dbg (ohci,"enabled nVidia shutdown quirk\n" ); + +return 0 ; +} +/* * The hardware normally enables the A-link power management feature, which * lets the system lower the power consumption in idle states.
@@ -332,6 +346,10 @@ static const struct pci_device_id ohci_p PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), .driver_data = (unsigned long )ohci_quirk_amd700, }, + { +PCI_DEVICE (PCI_VENDOR_ID_NVIDIA ,PCI_ANY_ID ), + .driver_data = (unsigned long) ohci_quirk_nvidia_shutdown, + },/* FIXME for some of the early AMD 760 southbridges, OHCI * won't work at all. blacklist them.
drivers/usb/host/ohci.h +1 -0
@@ -403,6 +403,7 @@ struct ohci_hcd {#define OHCI_QUIRK_HUB_POWER 0x100/* distrust firmware power/oc setup */ #define OHCI_QUIRK_AMD_ISO 0x200/* ISO transfers*/ #define OHCI_QUIRK_AMD_PREFETCH 0x400/* pre-fetch for ISO transfer */ +#define OHCI_QUIRK_SHUTDOWN 0x800/* nVidia power bug */ // there are also chip quirks/bugs in init logic struct work_struct nec_work;/* Worker for NEC quirk */
drivers/usb/host/pci-quirks.c +11 -7
@@ -169,6 +169,7 @@ static int __devinit mmio_resource_enablstatic void __devinit quirk_usb_handoff_ohci (struct pci_dev *pdev) {void __iomem *base; +u32 control;if (!mmio_resource_enabled (pdev,0 ))return ;
@@ -177,10 +178,14 @@ static void __devinit quirk_usb_handoff_if (base ==NULL )return ; + control =readl (base +OHCI_CONTROL ); +/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ -#ifndef __hppa__ -{ -u32 control =readl (base +OHCI_CONTROL ); +#ifdef __hppa__ +#define OHCI_CTRL_MASK (OHCI_CTRL_RWC | OHCI_CTRL_IR) +#else +#define OHCI_CTRL_MASK OHCI_CTRL_RWC +if (control &OHCI_CTRL_IR ) {int wait_time =500 ;/* arbitrary; 5 seconds */ writel (OHCI_INTR_OC , base +OHCI_INTRENABLE );
@@ -194,13 +199,12 @@ static void __devinit quirk_usb_handoff_dev_warn (&pdev->dev,"OHCI: BIOS handoff failed" " (BIOS bug?) %08x\n" , readl(base + OHCI_CONTROL)); - -/* reset controller, preserving RWC */ - writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL); } -}#endif +/* reset controller, preserving RWC (and possibly IR) */ +writel (control &OHCI_CTRL_MASK , base +OHCI_CONTROL ); +/* * disable interrupts */
PATCH 11/68 x86/pvclock: Zero last_value on resume
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Jeremy Fitzhardinge <[email protected]>
commit e7a3481c0246c8e45e79c629efd63b168e91fcda upstream.
If the guest domain has been suspend/resumed or migrated, then the system clock backing the pvclock clocksource may revert to a smaller value (ie, can be non-monotonic across the migration/save-restore).
Make sure we zero last_value in that case so that the domain continues to see clock updates.
--- arch/x86/include/asm/pvclock.h | 1 + arch/x86/kernel/pvclock.c | 5 +++++ arch/x86/xen/time.c | 2 ++ 3 files changed, 8 insertions(+)
arch/x86/include/asm/pvclock.h +1 -0
@@ -10,5 +10,6 @@ unsigned long pvclock_tsc_khz(struct pvcvoid pvclock_read_wallclock (struct pvclock_wall_clock *wall,struct pvclock_vcpu_time_info *vcpu,struct timespec *ts); +void pvclock_resume (void );#endif /* _ASM_X86_PVCLOCK_H */
arch/x86/kernel/pvclock.c +5 -0
@@ -111,6 +111,11 @@ unsigned long pvclock_tsc_khz(struct pvcstatic atomic64_t last_value =ATOMIC64_INIT (0 ); +void pvclock_resume (void ) +{ +atomic64_set (&last_value,0 ); +} +cycle_t pvclock_clocksource_read (struct pvclock_vcpu_time_info *src) {struct pvclock_shadow_time shadow;
arch/x86/xen/time.c +2 -0
@@ -424,6 +424,8 @@ void xen_timer_resume(void) {int cpu; +pvclock_resume (); +if (xen_clockevent != &xen_vcpuop_clockevent)return ;
PATCH 13/68 CRED: Fix get_task_cred() and task_state() to not resurrect dead credentials
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: David Howells <[email protected]>
commit de09a9771a5346029f4d11e4ac886be7f9bfdd75 upstream.
It's possible for get_task_cred() as it currently stands to 'corrupt' a set of credentials by incrementing their usage count after their replacement by the task being accessed.
What happens is that get_task_cred() can race with commit_creds():
TASK_1 TASK_2 RCU_CLEANER -->get_task_cred(TASK_2) rcu_read_lock() __cred = __task_cred(TASK_2) -->commit_creds() old_cred = TASK_2->real_cred TASK_2->real_cred = ... put_cred(old_cred) call_rcu(old_cred) [__cred->usage == 0] get_cred(__cred) [__cred->usage == 1] rcu_read_unlock() -->put_cred_rcu() [__cred->usage == 1] panic()
However, since a tasks credentials are generally not changed very often, we can reasonably make use of a loop involving reading the creds pointer and using atomic_inc_not_zero() to attempt to increment it if it hasn't already hit zero.
If successful, we can safely return the credentials in the knowledge that, even if the task we're accessing has released them, they haven't gone to the RCU cleanup code.
We then change task_state() in procfs to use get_task_cred() rather than calling get_cred() on the result of __task_cred(), as that suffers from the same problem.
Without this change, a BUG_ON in __put_cred() or in put_cred_rcu() can be tripped when it is noticed that the usage count is not zero as it ought to be, for example:
kernel BUG at kernel/cred.c:168!
invalid opcode: 0000 [#1] SMP
last sysfs file: /sys/kernel/mm/ksm/run
CPU 0
Pid: 2436, comm: master Not tainted 2.6.33.3-85.fc13.x86_64 #1 0HR330/OptiPlex 745
RIP: 0010:[<ffffffff81069881>] [<ffffffff81069881>] __put_cred+0xc/0x45 RSP: 0018:ffff88019e7e9eb8 EFLAGS: 00010202 RAX: 0000000000000001 RBX: ffff880161514480 RCX: 00000000ffffffff RDX: 00000000ffffffff RSI: ffff880140c690c0 RDI: ffff880140c690c0 RBP: ffff88019e7e9eb8 R08: 00000000000000d0 R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000040 R12: ffff880140c690c0 R13: ffff88019e77aea0 R14: 00007fff336b0a5c R15: 0000000000000001 FS: 00007f12f50d97c0(0000) GS:ffff880007400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f8f461bc000 CR3: 00000001b26ce000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process master (pid: 2436, threadinfo ffff88019e7e8000, task ffff88019e77aea0) Stack: ffff88019e7e9ec8 ffffffff810698cd ffff88019e7e9ef8 ffffffff81069b45 <0> ffff880161514180 ffff880161514480 ffff880161514180 0000000000000000 <0> ffff88019e7e9f28 ffffffff8106aace 0000000000000001 0000000000000246 Call Trace: [<ffffffff810698cd>] put_cred+0x13/0x15 [<ffffffff81069b45>] commit_creds+0x16b/0x175 [<ffffffff8106aace>] set_current_groups+0x47/0x4e [<ffffffff8106ac89>] sys_setgroups+0xf6/0x105 [<ffffffff81009b02>] system_call_fastpath+0x16/0x1b Code: 48 8d 71 ff e8 7e 4e 15 00 85 c0 78 0b 8b 75 ec 48 89 df e8 ef 4a 15 00
48 83 c4 18 5b c9 c3 55 8b 07 8b 07 48 89 e5 85 c0 74 04 <0f> 0b eb fe 65 48 8b 04 25 00 cc 00 00 48 3b b8 58 04 00 00 75
RIP [<ffffffff81069881>] __put_cred+0xc/0x45
RSP <ffff88019e7e9eb8>
---[ end trace df391256a100ebdd ]---
--- fs/proc/array.c | 2 +- include/linux/cred.h | 21 +-------------------- kernel/cred.c | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 21 deletions(-)
fs/proc/array.c +1 -1
@@ -172,7 +172,7 @@ static inline void task_state(struct seqif (tracer) tpid =task_pid_nr_ns (tracer, ns); } - cred =get_cred ((struct cred *)__task_cred (p)); + cred =get_task_cred (p);seq_printf (m,"State:\t%s\n" "Tgid:\t%d\n"
include/linux/cred.h +1 -20
@@ -153,6 +153,7 @@ struct cred {extern void __put_cred (struct cred *);extern void exit_creds (struct task_struct *);extern int copy_creds (struct task_struct *,unsigned long ); +extern const struct cred *get_task_cred (struct task_struct *);extern struct cred *cred_alloc_blank (void );extern struct cred *prepare_creds (void );extern struct cred *prepare_exec_creds (void );
@@ -283,26 +284,6 @@ static inline void put_cred(const struct ((const struct cred *)(rcu_dereference ((task)->real_cred)))/** -* get_task_cred - Get another task's objective credentials -* @task: The task to query -* -* Get the objective credentials of a task, pinning them so that they can't go -* away. Accessing a task's credentials directly is not permitted. -* -* The caller must make sure task doesn't go away, either by holding a ref on -* task or by holding tasklist_lock to prevent it from being unlinked. - */ -#define get_task_cred (task) \ -({ \ - struct cred *__cred; \ - rcu_read_lock(); \ - __cred = (struct cred *) __task_cred((task)); \ - get_cred(__cred); \ - rcu_read_unlock(); \ - __cred; \ -}) - -/** * get_current_cred - Get the current task's subjective credentials * * Get the subjective credentials of the current task, pinning them so that
kernel/cred.c +25 -0
@@ -208,6 +208,31 @@ void exit_creds(struct task_struct *tsk) } } +/** +* get_task_cred - Get another task's objective credentials +* @task: The task to query +* +* Get the objective credentials of a task, pinning them so that they can't go +* away. Accessing a task's credentials directly is not permitted. +* +* The caller must also make sure task doesn't get deleted, either by holding a +* ref on task or by holding tasklist_lock to prevent it from being unlinked. +*/ +const struct cred *get_task_cred (struct task_struct *task) +{ +const struct cred *cred; + +rcu_read_lock (); + +do { + cred =__task_cred ((task)); +BUG_ON (!cred); + }while (!atomic_inc_not_zero (&((struct cred *)cred)->usage)); + +rcu_read_unlock (); +return cred; +} +/* * Allocate blank credentials, such that the credentials can be filled in at a * later date without risk of ENOMEM.
PATCH 14/68 bonding/vlan: Avoid mangled NAs on slaves without VLAN tag insertion
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Ben Hutchings <[email protected]>
This is related to commit f88a4a9b65a6f3422b81be995535d0e69df11bb8 upstream, but the bug cannot be properly fixed without the other changes to VLAN tagging in 2.6.37.
bond_na_send() attempts to insert a VLAN tag in between building and sending packets of the respective formats. If the slave does not implement hardware VLAN tag insertion then vlan_put_tag() will mangle the network-layer header because the Ethernet header is not present at this point (unlike in bond_arp_send()).
--- drivers/net/bonding/bond_ipv6.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/net/bonding/bond_ipv6.c +8 -1
@@ -66,6 +66,13 @@ static void bond_na_send(struct net_devi };struct sk_buff *skb; +/* The Ethernet header is built in ndisc_send_skb(), not +* ndisc_build_skb(), so we cannot insert a VLAN tag. Only an +* out-of-line tag inserted by the hardware will work. +*/ +if (vlan_id && !(slave_dev->features &NETIF_F_HW_VLAN_TX )) +return ; + icmp6h.icmp6_router = router; icmp6h.icmp6_solicited =0 ; icmp6h.icmp6_override =1 ;
@@ -84,7 +91,7 @@ static void bond_na_send(struct net_devi }if (vlan_id) { - skb =vlan_put_tag (skb, vlan_id); + skb =__vlan_hwaccel_put_tag (skb, vlan_id);if (!skb) {pr_err (DRV_NAME ": failed to insert VLAN tag\n" );return ;
PATCH 15/68 CRED: Fix kernel panic upon security_file_alloc() failure.
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Tetsuo Handa <[email protected]>
commit 78d2978874e4e10e97dfd4fd79db45bdc0748550 upstream.
In get_empty_filp() since 2.6.29, file_free(f) is called with f->f_cred == NULL when security_file_alloc() returned an error. As a result, kernel will panic() due to put_cred(NULL) call within RCU callback.
Fix this bug by assigning f->f_cred before calling security_file_alloc().
--- fs/file_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/file_table.c +1 -1
@@ -121,13 +121,13 @@ struct file *get_empty_filp(void) goto fail;percpu_counter_inc (&nr_files); + f->f_cred =get_cred (cred);if (security_file_alloc (f)) goto fail_sec;INIT_LIST_HEAD (&f->f_u.fu_list);atomic_long_set (&f->f_count,1 );rwlock_init (&f->f_owner.lock); - f->f_cred =get_cred (cred);spin_lock_init (&f->f_lock);eventpoll_init_file (f);/* f->f_version: 0 */
PATCH 16/68 CRED: Fix BUG() upon security_cred_alloc_blank() failure
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Tetsuo Handa <[email protected]>
commit 2edeaa34a6e3f2c43b667f6c4f7b27944b811695 upstream.
In cred_alloc_blank() since 2.6.32, abort_creds(new) is called with new->security == NULL and new->magic == 0 when security_cred_alloc_blank() returns an error. As a result, BUG() will be triggered if SELinux is enabled or CONFIG_DEBUG_CREDENTIALS=y.
If CONFIG_DEBUG_CREDENTIALS=y, BUG() is called from __invalid_creds() because cred->magic == 0. Failing that, BUG() is called from selinux_cred_free() because selinux_cred_free() is not expecting cred->security == NULL. This does not affect smack_cred_free(), tomoyo_cred_free() or apparmor_cred_free().
Fix these bugs by
(1) Set new->magic before calling security_cred_alloc_blank().
(2) Handle null cred->security in creds_are_invalid() and selinux_cred_free().
--- kernel/cred.c | 12 ++++++++---- security/selinux/hooks.c | 6 +++++- 2 files changed, 13 insertions(+), 5 deletions(-)
kernel/cred.c +8 -4
@@ -255,13 +255,13 @@ struct cred *cred_alloc_blank(void)#endif atomic_set (&new->usage,1 ); +#ifdef CONFIG_DEBUG_CREDENTIALS + new->magic =CRED_MAGIC ; +#endif if (security_cred_alloc_blank (new,GFP_KERNEL ) <0 ) goto error; -#ifdef CONFIG_DEBUG_CREDENTIALS - new->magic =CRED_MAGIC ; -#endif return new; error:
@@ -809,7 +809,11 @@ bool creds_are_invalid(const struct credif (cred->magic !=CRED_MAGIC )return true;#ifdef CONFIG_SECURITY_SELINUX -if (selinux_is_enabled ()) { +/* +* cred->security == NULL if security_cred_alloc_blank() or +* security_prepare_creds() returned an error. +*/ +if (selinux_is_enabled () && cred->security) {if ((unsigned long ) cred->security <PAGE_SIZE )return true; if ((*(u32 *)cred->security & 0xffffff00) ==
security/selinux/hooks.c +5 -1
@@ -3262,7 +3262,11 @@ static void selinux_cred_free(struct cre {struct task_security_struct *tsec = cred->security; -BUG_ON ((unsigned long ) cred->security <PAGE_SIZE ); +/* +* cred->security == NULL if security_cred_alloc_blank() or +* security_prepare_creds() returned an error. +*/ +BUG_ON (cred->security && (unsigned long ) cred->security <PAGE_SIZE ); cred->security = (void *)0x7UL ;kfree (tsec); }
PATCH 17/68 CRED: Fix memory and refcount leaks upon security_prepare_creds() failure
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Tetsuo Handa <[email protected]>
commit fb2b2a1d37f80cc818fd4487b510f4e11816e5e1 upstream.
In prepare_kernel_cred() since 2.6.29, put_cred(new) is called without assigning new->usage when security_prepare_creds() returned an error. As a result, memory for new and refcount for new->{user,group_info,tgcred} are leaked because put_cred(new) won't call __put_cred() unless old->usage == 1.
Fix these leaks by assigning new->usage (and new->subscribers which was added in 2.6.32) before calling security_prepare_creds().
--- kernel/cred.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/cred.c +2 -2
@@ -718,6 +718,8 @@ struct cred *prepare_kernel_cred(structvalidate_creds (old); *new = *old; +atomic_set (&new->usage,1 ); +set_cred_subscribers (new,0 );get_uid (new->user);get_group_info (new->group_info);
@@ -735,8 +737,6 @@ struct cred *prepare_kernel_cred(structif (security_prepare_creds (new, old,GFP_KERNEL ) <0 ) goto error; -atomic_set (&new->usage,1 ); -set_cred_subscribers (new,0 );put_cred (old);validate_creds (new);return new;
PATCH 18/68 sendfile(): check f_op.splice_write() rather than f_op.sendpage()
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Changli Gao <[email protected]>
commit cc56f7de7f00d188c7c4da1e9861581853b9e92f upstream.
sendfile(2) was reworked with the splice infrastructure, but it still checks f_op.sendpage() instead of f_op.splice_write() wrongly. Although if f_op.sendpage() exists, f_op.splice_write() always exists at the same time currently, the assumption will be broken in future silently. This patch also brings a side effect: sendfile(2) can work with any output file. Some security checks related to f_op are added too.
--- fs/read_write.c | 2 -- fs/splice.c | 24 +++++++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-)
fs/read_write.c +0 -2
@@ -826,8 +826,6 @@ static ssize_t do_sendfile(int out_fd, iif (!(out_file->f_mode &FMODE_WRITE )) goto fput_out; retval = -EINVAL ; -if (!out_file->f_op || !out_file->f_op->sendpage) - goto fput_out; in_inode = in_file->f_path.dentry->d_inode; out_inode = out_file->f_path.dentry->d_inode; retval =rw_verify_area (WRITE , out_file, &out_file->f_pos, count);
fs/splice.c +15 -9
@@ -638,9 +638,11 @@ static int pipe_to_sendpage(struct pipe_ ret = buf->ops->confirm (pipe, buf);if (!ret) { more = (sd->flags &SPLICE_F_MORE ) || sd->len < sd->total_len; - - ret = file->f_op->sendpage (file, buf->page, buf->offset, - sd->len, &pos, more); +if (file->f_op && file->f_op->sendpage) + ret = file->f_op->sendpage (file, buf->page, buf->offset, + sd->len, &pos, more); +else + ret = -EINVAL ; }return ret;
@@ -1058,8 +1060,9 @@ static long do_splice_from(struct pipe_iif (unlikely (ret <0 ))return ret; - splice_write = out->f_op->splice_write; -if (!splice_write) +if (out->f_op && out->f_op->splice_write) + splice_write = out->f_op->splice_write; +else splice_write = default_file_splice_write;return splice_write (pipe, out, ppos, len, flags);
@@ -1083,8 +1086,9 @@ static long do_splice_to(struct file *inif (unlikely (ret <0 ))return ret; - splice_read = in->f_op->splice_read; -if (!splice_read) +if (in->f_op && in->f_op->splice_read) + splice_read = in->f_op->splice_read; +else splice_read = default_file_splice_read;return splice_read (in, ppos, pipe, len, flags);
@@ -1306,7 +1310,8 @@ static long do_splice(struct file *in, lif (off_in)return -ESPIPE ;if (off_out) { -if (out->f_op->llseek == no_llseek) +if (!out->f_op || !out->f_op->llseek || + out->f_op->llseek == no_llseek)return -EINVAL ;if (copy_from_user (&offset, off_out,sizeof (loff_t)))return -EFAULT ;
@@ -1326,7 +1331,8 @@ static long do_splice(struct file *in, lif (off_out)return -ESPIPE ;if (off_in) { -if (in->f_op->llseek == no_llseek) +if (!in->f_op || !in->f_op->llseek || + in->f_op->llseek == no_llseek)return -EINVAL ;if (copy_from_user (&offset, off_in,sizeof (loff_t)))return -EFAULT ;
PATCH 19/68 NFS: fix the return value of nfs_file_fsync()
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: J. R. Okajima <[email protected]>
commit 0702099bd86c33c2dcdbd3963433a61f3f503901 upstream.
By the commit af7fa16 2010-08-03 NFS: Fix up the fsync code close(2) became returning the non-zero value even if it went well. nfs_file_fsync() should return 0 when "status" is positive.
--- fs/nfs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfs/file.c +1 -1
@@ -220,7 +220,7 @@ static int nfs_do_fsync(struct nfs_open_ have_error |=test_bit (NFS_CONTEXT_ERROR_WRITE , &ctx->flags);if (have_error) ret =xchg (&ctx->error,0 ); -if (!ret) +if (!ret && status <0 ) ret = status;return ret; }
PATCH 20/68 isdn: hisax: Replace the bogus access to irq stats
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Thomas Gleixner <[email protected]>
commit 40f08a724fcc21285cf3a75aec957aef908605c6 upstream.
Abusing irq stats in a driver for counting interrupts is a horrible idea and not safe with shared interrupts. Replace it by a local interrupt counter.
Noticed by the attempt to remove the irq stats export.
--- drivers/isdn/hisax/config.c | 18 ++++++++++++++---- drivers/isdn/hisax/hisax.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-)
drivers/isdn/hisax/config.c +14 -4
@@ -800,6 +800,16 @@ static void closecard(int cardnr)ll_unload (csta); } +static irqreturn_t card_irq (int intno,void *dev_id) +{ +struct IsdnCardState *cs = dev_id; +irqreturn_t ret = cs->irq_func (intno, cs); + +if (ret ==IRQ_HANDLED ) + cs->irq_cnt++; +return ret; +} +static int init_card (struct IsdnCardState *cs) {int irq_cnt, cnt =3 , ret;
@@ -808,10 +818,10 @@ static int init_card(struct IsdnCardStat ret = cs->cardmsg (cs,CARD_INIT ,NULL );return (ret); } - irq_cnt =kstat_irqs (cs->irq); + irq_cnt = cs->irq_cnt =0 ;printk (KERN_INFO "%s: IRQ %d count %d\n" , CardType[cs->typ], cs->irq, irq_cnt); -if (request_irq (cs->irq, cs->irq_func, cs->irq_flags,"HiSax" , cs)) { +if (request_irq (cs->irq, card_irq, cs->irq_flags,"HiSax" , cs)) {printk (KERN_WARNING "HiSax: couldn't get interrupt %d\n" , cs->irq);return 1 ;
@@ -821,8 +831,8 @@ static int init_card(struct IsdnCardStat/* Timeout 10ms */ msleep (10 );printk (KERN_INFO "%s: IRQ %d count %d\n" , - CardType[cs->typ], cs->irq,kstat_irqs (cs->irq)); -if (kstat_irqs (cs->irq) == irq_cnt) { + CardType[cs->typ], cs->irq, cs->irq_cnt); +if (cs->irq_cnt == irq_cnt) {printk (KERN_WARNING "%s: IRQ(%d) getting no interrupts during init %d\n" , CardType[cs->typ], cs->irq,4 - cnt);
drivers/isdn/hisax/hisax.h +1 -0
@@ -959,6 +959,7 @@ struct IsdnCardState {u_long event;struct work_struct tqueue;struct timer_list dbusytimer; +unsigned int irq_cnt;#ifdef ERROR_STATISTIC int err_crc;int err_tx;
PATCH 21/68 ixgbe: add support for 82599 based Express Module X520-P2
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Don Skidmore <[email protected]>
commit 38ad1c8e8c8debf73b28543a3250a01f799f78ef upstream.
This patch will add the device ID for the 82599-based Ethernet Express Module X520-P2 SFI card.
--- drivers/net/ixgbe/ixgbe_82599.c | 1 + drivers/net/ixgbe/ixgbe_main.c | 2 ++ drivers/net/ixgbe/ixgbe_type.h | 1 + 3 files changed, 4 insertions(+)
drivers/net/ixgbe/ixgbe_82599.c +1 -0
@@ -338,6 +338,7 @@ static enum ixgbe_media_type ixgbe_get_m media_type = ixgbe_media_type_backplane;break ;case IXGBE_DEV_ID_82599_SFP : +case IXGBE_DEV_ID_82599_SFP_EM : media_type = ixgbe_media_type_fiber;break ;case IXGBE_DEV_ID_82599_CX4 :
drivers/net/ixgbe/ixgbe_main.c +2 -0
@@ -100,6 +100,8 @@ static struct pci_device_id ixgbe_pci_tb board_82599 }, {PCI_VDEVICE (INTEL ,IXGBE_DEV_ID_82599_SFP ), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_EM), + board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4_MEZZ), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4),
drivers/net/ixgbe/ixgbe_type.h +1 -0
@@ -53,6 +53,7 @@#define IXGBE_DEV_ID_82599_KR 0x1517#define IXGBE_DEV_ID_82599_CX4 0x10F9#define IXGBE_DEV_ID_82599_SFP 0x10FB +#define IXGBE_DEV_ID_82599_SFP_EM 0x1507#define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC#define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8
PATCH 22/68 ixgbe: prevent speculative processing of descriptors before ready
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Milton Miller <[email protected]>
commit 3c945e5b3719bcc18c6ddd31bbcae8ef94f3d19a upstream.
The PowerPC architecture does not require loads to independent bytes to be ordered without adding an explicit barrier.
In ixgbe_clean_rx_irq we load the status bit then load the packet data. With packet split disabled if these loads go out of order we get a stale packet, but we will notice the bad sequence numbers and drop it.
The problem occurs with packet split enabled where the TCP/IP header and data are in different descriptors. If the reads go out of order we may have data that doesn't match the TCP/IP header. Since we use hardware checksumming this bad data is never verified and it makes it all the way to the application.
This bug was found during stress testing and adding this barrier has been shown to fix it.
--- drivers/net/ixgbe/ixgbe_main.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ixgbe/ixgbe_main.c +1 -0
@@ -793,6 +793,7 @@ static bool ixgbe_clean_rx_irq(struct ixbreak ; (*work_done)++; +rmb ();/* read descriptor and rx_buffer_info after status DD */ if (rx_ring->flags &IXGBE_RING_RX_PS_ENABLED ) { hdr_info =le16_to_cpu (ixgbe_get_hdr_info (rx_desc)); len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >>
Re: [Stable-review] [22/68] ixgbe: prevent speculative processing of descriptors before ready
Quoted 11 lines · Greg KH
2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Milton Miller <[email protected]>
commit
3c945e5b3719bcc18c6ddd31bbcae8ef94f3d19aupstream.The PowerPC architecture does not require loads to independent bytes to be ordered without adding an explicit barrier.
Quoted 8 lines
In
ixgbe_clean_rx_irqwe load the status bit then load the packet data. With packet split disabled if these loads go out of order we get a stale packet, but we will notice the bad sequence numbers and drop it.The problem occurs with packet split enabled where the TCP/IP header and data are in different descriptors. If the reads go out of order we may have data that doesn't match the TCP/IP header. Since we use hardware checksumming this bad data is never verified and it makes it all the way to the application.
[...]
Packet splitting should be completely disabled on the 82599, anyway. Greg, what happened to this patch:
commit a124339ad28389093ed15eca990d39c51c5736cc
Author: Don Skidmore <[email protected]> Date: Tue Jan 18 22:53:47 2011 +0000
ixgbe: fix for 82599 erratum on Header Splitting
We have found a hardware erratum on 82599 hardware that can lead to unpredictable behavior when Header Splitting mode is enabled. So we are no longer enabling this feature on affected hardware.
Please see the 82599 Specification Update for more information.
Ben.
Signature · 2 lines
Ben Hutchings Once a job is fouled up, anything done to improve it makes it worse.
Re: [Stable-review] [22/68] ixgbe: prevent speculative processing of descriptors before ready
Quoted 35 lines · Ben Hutchings
Quoted 11 lines · Greg KH
2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Milton Miller <[email protected]>
commit
3c945e5b3719bcc18c6ddd31bbcae8ef94f3d19aupstream.The PowerPC architecture does not require loads to independent bytes to be ordered without adding an explicit barrier.
Quoted 8 lines
In
ixgbe_clean_rx_irqwe load the status bit then load the packet data. With packet split disabled if these loads go out of order we get a stale packet, but we will notice the bad sequence numbers and drop it.The problem occurs with packet split enabled where the TCP/IP header and data are in different descriptors. If the reads go out of order we may have data that doesn't match the TCP/IP header. Since we use hardware checksumming this bad data is never verified and it makes it all the way to the application.
[...]
Packet splitting should be completely disabled on the 82599, anyway. Greg, what happened to this patch:
commit
a124339ad28389093ed15eca990d39c51c5736ccAuthor: Don Skidmore <[email protected]> Date: Tue Jan 18 22:53:47 2011 +0000ixgbe: fix for 82599 erratum on Header Splitting
We have found a hardware erratum on 82599 hardware that can lead to unpredictable behavior when Header Splitting mode is enabled. So we are no longer enabling this feature on affected hardware.
Quoted 6 lines
Please see the 82599 Specification Update for more information.
Signed-off-by Don Skidmore <[email protected]>Tested-by Stephen Ko <[email protected]>Signed-off-by Jeff Kirsher <[email protected]>
It does not apply to the .32 kernel.
Care to provide a backport if you feel it should be there?
thanks,
greg k-h
Re: [Stable-review] [22/68] ixgbe: prevent speculative processing of descriptors before ready
Quoted 43 lines · Greg KH
Quoted 35 lines · Ben Hutchings
Quoted 11 lines · Greg KH
2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Milton Miller <[email protected]>
commit
3c945e5b3719bcc18c6ddd31bbcae8ef94f3d19aupstream.The PowerPC architecture does not require loads to independent bytes to be ordered without adding an explicit barrier.
Quoted 8 lines
In
ixgbe_clean_rx_irqwe load the status bit then load the packet data. With packet split disabled if these loads go out of order we get a stale packet, but we will notice the bad sequence numbers and drop it.The problem occurs with packet split enabled where the TCP/IP header and data are in different descriptors. If the reads go out of order we may have data that doesn't match the TCP/IP header. Since we use hardware checksumming this bad data is never verified and it makes it all the way to the application.
[...]
Packet splitting should be completely disabled on the 82599, anyway. Greg, what happened to this patch:
commit
a124339ad28389093ed15eca990d39c51c5736ccAuthor: Don Skidmore <[email protected]> Date: Tue Jan 18 22:53:47 2011 +0000ixgbe: fix for 82599 erratum on Header Splitting
We have found a hardware erratum on 82599 hardware that can lead to unpredictable behavior when Header Splitting mode is enabled. So we are no longer enabling this feature on affected hardware.
Quoted 6 lines
Please see the 82599 Specification Update for more information.
Signed-off-by Don Skidmore <[email protected]>Tested-by Stephen Ko <[email protected]>Signed-off-by Jeff Kirsher <[email protected]>
Quoted 7 lines
It does not apply to the .32 kernel.
Care to provide a backport if you feel it should be there?
thanks,
greg k-h
Don is working on patch for .32 kernel, I hope to send it out no later than tomorrow.
PATCH 23/68 scsi_dh_alua: add netapp to dev list
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Mike Christie <[email protected]>
commit cd4a8814d44672bd2c8f04a472121bfbe193809c upstream.
Newer Netapp target software supports ALUA, so this patch adds them to the scsi_dev_alua dev list.
--- drivers/scsi/device_handler/scsi_dh_alua.c | 1 + 1 file changed, 1 insertion(+)
drivers/scsi/device_handler/scsi_dh_alua.c +1 -0
@@ -701,6 +701,7 @@ static const struct scsi_dh_devlist alua {"IBM", "2145" }, {"Pillar", "Axiom" }, {"Intel", "Multi-Flex"}, + {"NETAPP", "LUN"}, {NULL, NULL} };
PATCH 24/68 scsi_dh_alua: Add IBM Power Virtual SCSI ALUA device to dev list
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Brian King <[email protected]>
commit 22963a37b3437a25812cc856afa5a84ad4a3f541 upstream.
Adds IBM Power Virtual SCSI ALUA devices to the ALUA device handler.
--- drivers/scsi/device_handler/scsi_dh_alua.c | 1 + 1 file changed, 1 insertion(+)
drivers/scsi/device_handler/scsi_dh_alua.c +1 -0
@@ -702,6 +702,7 @@ static const struct scsi_dh_devlist alua {"Pillar", "Axiom" }, {"Intel", "Multi-Flex"}, {"NETAPP", "LUN"}, + {"AIX", "NVDISK"}, {NULL, NULL} };
PATCH 25/68 dm raid1: fail writes if errors are not handled and log fails
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Mikulas Patocka <[email protected]>
commit 5528d17de1cf1462f285c40ccaf8e0d0e4c64dc0 upstream.
If the mirror log fails when the handle_errors option was not selected and there is no remaining valid mirror leg, writes return success even though they weren't actually written to any device. This patch completes them with EIO instead.
This code path is taken:do_writes:
bio_list_merge(&ms->failures, &sync); do_failures: if (!get_valid_mirror(ms)) (false) else if (errors_handled(ms)) (false) else bio_endio(bio, 0);
The logic in do_failures is based on presuming that the write was already
tried: if it succeeded at least on one leg (without handle_errors) it is reported as success.
Reference: https://bugzilla.redhat.com/show_bug.cgi?id=555197
--- drivers/md/dm-raid1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/dm-raid1.c +1 -1
@@ -659,7 +659,7 @@ static void do_writes(struct mirror_set/* * Dispatch io. */ -if (unlikely (ms->log_failure)) { +if (unlikely (ms->log_failure) &&errors_handled (ms)) {spin_lock_irq (&ms->lock);bio_list_merge (&ms->failures, &sync);spin_unlock_irq (&ms->lock);
PATCH 26/68 GFS2: Fix bmap allocation corner-case bug
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Steven Whitehouse <[email protected]>
commit 07ccb7bf2c928fef4fea2cda69ba2e23479578db upstream.
This patch solves a corner case during allocation which occurs if both metadata (indirect) and data blocks are required but there is an obstacle in the filesystem (e.g. a resource group header or another allocated block) such that when the allocation is requested only enough blocks for the metadata are returned.
By changing the exit condition of this loop, we ensure that a minimum of one data block will always be returned.
--- fs/gfs2/bmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/gfs2/bmap.c +1 -1
@@ -541,7 +541,7 @@ static int gfs2_bmap_alloc(struct inode *ptr++ =cpu_to_be64 (bn++);break ; } - }while (state !=ALLOC_DATA ); + }while ((state !=ALLOC_DATA ) || !dblock); ip->i_height = height;gfs2_add_inode_blocks (&ip->i_inode, alloced);
PATCH 27/68 dm raid1: fix null pointer dereference in suspend
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Takahiro Yasui <[email protected]>
commit 558569aa9d83e016295bac77d900342908d7fd85 upstream.
When suspending a failed mirror, bios are completed by mirror_end_io() and __rh_lookup() in dm_rh_dec() returns NULL where a non-NULL return value is required by design. Fix this by not changing the state of the recovery failed region from DM_RH_RECOVERING to DM_RH_NOSYNC in dm_rh_recovery_end().
Issue
On 2.6.33-rc1 kernel, I hit the bug when I suspended the failed mirror by dmsetup command.
BUG: unable to handle kernel NULL pointer dereference at 00000020 IP: [<f94f38e2>] dm_rh_dec+0x35/0xa1 [dm_region_hash]
...
EIP: 0060:[<f94f38e2>] EFLAGS: 00010046 CPU: 0
EIP is at dm_rh_dec+0x35/0xa1 [dm_region_hash]
EAX: 00000286 EBX: 00000000 ECX: 00000286 EDX: 00000000
ESI: eff79eac EDI: eff79e80 EBP: f6915cd4 ESP: f6915cc4
DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
Process dmsetup (pid: 2849, ti=f6914000 task=eff03e80 task.ti=f6914000)
...
Call Trace: [<f9530af6>] ? mirror_end_io+0x53/0x1b1 [dm_mirror] [<f9413104>] ? clone_endio+0x4d/0xa2 [dm_mod] [<f9530aa3>] ? mirror_end_io+0x0/0x1b1 [dm_mirror] [<f94130b7>] ? clone_endio+0x0/0xa2 [dm_mod] [<c02d6bcb>] ? bio_endio+0x28/0x2b [<f952f303>] ? hold_bio+0x2d/0x62 [dm_mirror] [<f952f942>] ? mirror_presuspend+0xeb/0xf7 [dm_mirror] [<c02aa3e2>] ? vmap_page_range+0xb/0xd [<f9414c8d>] ? suspend_targets+0x2d/0x3b [dm_mod] [<f9414ca9>] ? dm_table_presuspend_targets+0xe/0x10 [dm_mod] [<f941456f>] ? dm_suspend+0x4d/0x150 [dm_mod] [<f941767d>] ? dev_suspend+0x55/0x18a [dm_mod] [<c0343762>] ? _copy_from_user+0x42/0x56 [<f9417fb0>] ? dm_ctl_ioctl+0x22c/0x281 [dm_mod] [<f9417628>] ? dev_suspend+0x0/0x18a [dm_mod] [<f9417d84>] ? dm_ctl_ioctl+0x0/0x281 [dm_mod] [<c02c3c4b>] ? vfs_ioctl+0x22/0x85 [<c02c422c>] ? do_vfs_ioctl+0x4cb/0x516 [<c02c42b7>] ? sys_ioctl+0x40/0x5a [<c0202858>] ? sysenter_do_call+0x12/0x28
Analysis
When recovery process of a region failed, dm_rh_recovery_end() function changes the state of the region from RM_RH_RECOVERING to DM_RH_NOSYNC. When recovery_complete() is executed between dm_rh_update_states() and dm_writes() in do_mirror(), bios are processed with the region state, DM_RH_NOSYNC. However, the region data is freed without checking its pending count when dm_rh_update_states() is called next time.
When bios are finished by mirror_end_io(), __rh_lookup() in dm_rh_dec() returns NULL even though a valid return value are expected.
Solution
Remove the state change of the recovery failed region from DM_RH_RECOVERING to DM_RH_NOSYNC in dm_rh_recovery_end(). We can remove the state change because:
- If the region data has been released by dm_rh_update_states(), a new region data is created with the state of DM_RH_NOSYNC, and bios are processed according to the DM_RH_NOSYNC state.
- If the region data has not been released by dm_rh_update_states(), a state of the region is DM_RH_RECOVERING and bios are put in the delayed_bio list.
The flag change from DM_RH_RECOVERING to DM_RH_NOSYNC in dm_rh_recovery_end() was added in the following commit:
dm raid1: handle resync failures
author Jonathan Brassow <[email protected]>
Thu, 12 Jul 2007 16:29:04 +0000 (17:29 +0100)
http://git.kernel.org/linus/f44db678edcc6f4c2779ac43f63f0b9dfa28b724
--- drivers/md/dm-region-hash.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/md/dm-region-hash.c +2 -3
@@ -643,10 +643,9 @@ void dm_rh_recovery_end(struct dm_regionspin_lock_irq (&rh->region_lock);if (success)list_add (®->list, ®->rh->recovered_regions); -else { - reg->state =DM_RH_NOSYNC ; +else list_add (®->list, ®->rh->failed_recovered_regions); - } +spin_unlock_irq (&rh->region_lock); rh->wakeup_workers (rh->context);
PATCH 28/68 sunrpc/cache: fix module refcnt leak in a failure path
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Li Zefan <[email protected]>
commit a5990ea1254cd186b38744507aeec3136a0c1c95 upstream.
Don't forget to release the module refcnt if seq_open() returns failure.
--- net/sunrpc/cache.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/sunrpc/cache.c +3 -1
@@ -1234,8 +1234,10 @@ static int content_open(struct inode *inif (!cd || !try_module_get (cd->owner))return -EACCES ; han =__seq_open_private (file, &cache_content_op,sizeof (*han)); -if (han ==NULL ) +if (han ==NULL ) { +module_put (cd->owner);return -ENOMEM ; + } han->cd = cd;return 0 ;
PATCH 29/68 be2net: Maintain tx and rx counters in driver
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Ajit Khaparde <[email protected]>
commit 91992e446cadbbde1a304de6954afd715af5121e upstream.
For certain skews of the BE adapter, H/W Tx and Rx counters could be common for more than one interface. Add Tx and Rx counters in the adapter structure (to maintain stats on a per interfae basis).
--- drivers/net/benet/be.h | 2 ++ drivers/net/benet/be_main.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-)
drivers/net/benet/be.h +2 -0
@@ -165,6 +165,7 @@ struct be_drvr_stats {ulong be_tx_jiffies;u64 be_tx_bytes;u64 be_tx_bytes_prev; +u64 be_tx_pkts;u32 be_tx_rate;u32 cache_barrier[16 ];
@@ -176,6 +177,7 @@ struct be_drvr_stats {ulong be_rx_jiffies;u64 be_rx_bytes;u64 be_rx_bytes_prev; +u64 be_rx_pkts;u32 be_rx_rate;/* number of non ether type II frames dropped where * frame len > length field of Mac Hdr */
drivers/net/benet/be_main.c +9 -9
@@ -146,13 +146,10 @@ void netdev_stats_update(struct be_adaptstruct net_device_stats *dev_stats = &adapter->stats.net_stats;struct be_erx_stats *erx_stats = &hw_stats->erx; - dev_stats->rx_packets = port_stats->rx_total_frames; - dev_stats->tx_packets = port_stats->tx_unicastframes + - port_stats->tx_multicastframes + port_stats->tx_broadcastframes; - dev_stats->rx_bytes = (u64 ) port_stats->rx_bytes_msd <<32 | - (u64 ) port_stats->rx_bytes_lsd; - dev_stats->tx_bytes = (u64 ) port_stats->tx_bytes_msd <<32 | - (u64 ) port_stats->tx_bytes_lsd; + dev_stats->rx_packets =drvr_stats (adapter)->be_rx_pkts; + dev_stats->tx_packets =drvr_stats (adapter)->be_tx_pkts; + dev_stats->rx_bytes =drvr_stats (adapter)->be_rx_bytes; + dev_stats->tx_bytes =drvr_stats (adapter)->be_tx_bytes;/* bad pkts received */ dev_stats->rx_errors = port_stats->rx_crc_errors +
@@ -309,12 +306,13 @@ static void be_tx_rate_update(struct be_ }static void be_tx_stats_update (struct be_adapter *adapter, -u32 wrb_cnt,u32 copied,bool stopped) +u32 wrb_cnt,u32 copied,u32 gso_segs,bool stopped) {struct be_drvr_stats *stats =drvr_stats (adapter); stats->be_tx_reqs++; stats->be_tx_wrbs += wrb_cnt; stats->be_tx_bytes += copied; + stats->be_tx_pkts += (gso_segs ? gso_segs :1 );if (stopped) stats->be_tx_stops++; }
@@ -462,7 +460,8 @@ static netdev_tx_t be_xmit(struct sk_bufbe_txq_notify (adapter, txq->id, wrb_cnt); -be_tx_stats_update (adapter, wrb_cnt, copied, stopped); +be_tx_stats_update (adapter, wrb_cnt, copied, +skb_shinfo (skb)->gso_segs, stopped); }else { txq->head = start;dev_kfree_skb_any (skb);
@@ -605,6 +604,7 @@ static void be_rx_stats_update(struct be stats->be_rx_compl++; stats->be_rx_frags += numfrags; stats->be_rx_bytes += pktsize; + stats->be_rx_pkts++; }static inline bool do_pkt_csum (struct be_eth_rx_compl *rxcp,bool cso)
PATCH 30/68 tcp: Increase TCP_MAXSEG socket option minimum.
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: David S. Miller <[email protected]>
commit 7a1abd08d52fdeddb3e9a5a33f2f15cc6a5674d2 upstream.
As noted by Steve Chen, since commit f5fff5dc8a7a3f395b0525c02ba92c95d42b7390 ("tcp: advertise MSS requested by user") we can end up with a situation where tcp_select_initial_window() does a divide by a zero (or even negative) mss value.
The problem is that sometimes we effectively subtract TCPOLEN_TSTAMP_ALIGNED and/or TCPOLEN_MD5SIG_ALIGNED from the mss.
Fix this by increasing the minimum from 8 to 64.
--- net/ipv4/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/tcp.c +1 -1
@@ -2117,7 +2117,7 @@ static int do_tcp_setsockopt(struct sock/* Values greater than interface MTU won't take effect. However * at the point when this call is done we typically don't yet * know which interface is going to be used */ -if (val <8 || val >MAX_TCP_WINDOW ) { +if (val <64 || val >MAX_TCP_WINDOW ) { err = -EINVAL ;break ; }
PATCH 31/68 tcp: Make TCP_MAXSEG minimum more correct.
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: David S. Miller <[email protected]>
commit c39508d6f118308355468314ff414644115a07f3 upstream.
Use TCP_MIN_MSS instead of constant 64.
--- net/ipv4/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/tcp.c +1 -1
@@ -2117,7 +2117,7 @@ static int do_tcp_setsockopt(struct sock/* Values greater than interface MTU won't take effect. However * at the point when this call is done we typically don't yet * know which interface is going to be used */ -if (val <64 || val >MAX_TCP_WINDOW ) { +if (val <TCP_MIN_MSS || val >MAX_TCP_WINDOW ) { err = -EINVAL ;break ; }
PATCH 32/68 nfsd: correctly handle return value from nfsd_map_name_to_*
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: NeilBrown <[email protected]>
commit 47c85291d3dd1a51501555000b90f8e281a0458e upstream.
These functions return an nfs status, not a host_err. So don't try to convert before returning.
This is a regression introduced by 3c726023402a2f3b28f49b9d90ebf9e71151157d; I fixed up two of the callers, but missed these two.
--- fs/nfsd/nfs4xdr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
fs/nfsd/nfs4xdr.c +4 -4
@@ -323,8 +323,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundREAD_BUF (dummy32); len += (XDR_QUADLEN (dummy32) <<2 );READMEM (buf, dummy32); -if ((host_err =nfsd_map_name_to_uid (argp->rqstp, buf, dummy32, &iattr->ia_uid))) - goto out_nfserr; +if ((status =nfsd_map_name_to_uid (argp->rqstp, buf, dummy32, &iattr->ia_uid))) +return status; iattr->ia_valid |=ATTR_UID ; }if (bmval[1 ] &FATTR4_WORD1_OWNER_GROUP ) {
@@ -334,8 +334,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundREAD_BUF (dummy32); len += (XDR_QUADLEN (dummy32) <<2 );READMEM (buf, dummy32); -if ((host_err =nfsd_map_name_to_gid (argp->rqstp, buf, dummy32, &iattr->ia_gid))) - goto out_nfserr; +if ((status =nfsd_map_name_to_gid (argp->rqstp, buf, dummy32, &iattr->ia_gid))) +return status; iattr->ia_valid |=ATTR_GID ; }if (bmval[1 ] &FATTR4_WORD1_TIME_ACCESS_SET ) {
PATCH 33/68 xfs: always use iget in bulkstat
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Christoph Hellwig <[email protected]>
Upstream commit: 7dce11dbac54fce777eea0f5fb25b2694ccd7900
The non-coherent bulkstat versionsthat look directly at the inode buffers causes various problems with performance optimizations that make increased use of just logging inodes. This patch makes bulkstat always use iget, which should be fast enough for normal use with the radix-tree based inode cache introduced a while ago.
--- fs/xfs/linux-2.6/xfs_ioctl.c | 7 - fs/xfs/linux-2.6/xfs_ioctl32.c | 12 - fs/xfs/quota/xfs_qm.c | 11 - fs/xfs/quota/xfs_qm_syscalls.c | 16 +- fs/xfs/xfs_itable.c | 280 +++++------------------------------------ fs/xfs/xfs_itable.h | 14 -- 6 files changed, 59 insertions(+), 281 deletions(-)
fs/xfs/linux-2.6/xfs_ioctl.c +3 -4
@@ -673,10 +673,9 @@ xfs_ioc_bulkstat( error =xfs_bulkstat_single (mp, &inlast, bulkreq.ubuffer, &done); else /* XFS_IOC_FSBULKSTAT */ - error =xfs_bulkstat (mp, &inlast, &count, - (bulkstat_one_pf )xfs_bulkstat_one,NULL , -sizeof (xfs_bstat_t), bulkreq.ubuffer, -BULKSTAT_FG_QUICK , &done); + error =xfs_bulkstat (mp, &inlast, &count, xfs_bulkstat_one, +sizeof (xfs_bstat_t), bulkreq.ubuffer, + &done);if (error)return -error;
fs/xfs/linux-2.6/xfs_ioctl32.c +4 -8
@@ -235,15 +235,13 @@ xfs_bulkstat_one_compat(xfs_ino_t ino,/* inode number to get data for */ void __user *buffer, /* buffer to place output in */ int ubsize, /* size of buffer */ - void *private_data, /* my private data */ xfs_daddr_t bno, /* starting bno of inode cluster */ int *ubused, /* bytes used by me */ - void *dibuff, /* on-disk inode buffer */ int *stat) /* BULKSTAT_RV_... */ { return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,xfs_bulkstat_one_fmt_compat ,bno , -ubused ,dibuff ,stat ); +ubused ,stat ); }/* copied from xfs_ioctl.c */
@@ -296,13 +294,11 @@ xfs_compat_ioc_bulkstat(int res; error =xfs_bulkstat_one_compat (mp, inlast, bulkreq.ubuffer, -sizeof (compat_xfs_bstat_t), -NULL ,0 ,NULL ,NULL , &res); +sizeof (compat_xfs_bstat_t),0 ,NULL , &res); }else if (cmd ==XFS_IOC_FSBULKSTAT_32 ) { error =xfs_bulkstat (mp, &inlast, &count, - xfs_bulkstat_one_compat,NULL , -sizeof (compat_xfs_bstat_t), bulkreq.ubuffer, -BULKSTAT_FG_QUICK , &done); + xfs_bulkstat_one_compat,sizeof (compat_xfs_bstat_t), + bulkreq.ubuffer, &done); }else error =XFS_ERROR (EINVAL );if (error)
fs/xfs/quota/xfs_qm.c +5 -6
@@ -1606,10 +1606,8 @@ xfs_qm_dqusage_adjust(xfs_ino_t ino,/* inode number to get data for */ void __user *buffer, /* not used */ int ubsize, /* not used */ - void *private_data, /* not used */ xfs_daddr_t bno, /* starting block of inode cluster */ int *ubused, /* not used */ - void *dip, /* on-disk inode pointer (not used) */ int *res) /* result code value */ { xfs_inode_t *ip;
@@ -1766,12 +1764,13 @@ xfs_qm_quotacheck(* Iterate thru all the inodes in the file system, * adjusting the corresponding dquot counters in core. */ -if ((error =xfs_bulkstat (mp, &lastino, &count, - xfs_qm_dqusage_adjust,NULL , - structsz,NULL ,BULKSTAT_FG_IGET , &done))) + error =xfs_bulkstat (mp, &lastino, &count, + xfs_qm_dqusage_adjust, + structsz,NULL , &done); +if (error)break ; - }while (! done); + }while (!done);/* * We've made all the changes that we need to make incore.
fs/xfs/quota/xfs_qm_syscalls.c +7 -9
@@ -1114,10 +1114,8 @@ xfs_qm_internalqcheck_adjust(xfs_ino_t ino,/* inode number to get data for */ void __user *buffer, /* not used */ int ubsize, /* not used */ - void *private_data, /* not used */ xfs_daddr_t bno, /* starting block of inode cluster */ int *ubused, /* not used */ - void *dip, /* not used */ int *res) /* bulkstat result code */ { xfs_inode_t *ip;
@@ -1212,15 +1210,15 @@ xfs_qm_internalqcheck(* Iterate thru all the inodes in the file system, * adjusting the corresponding dquot counters */ -if ((error =xfs_bulkstat (mp, &lastino, &count, - xfs_qm_internalqcheck_adjust,NULL , -0 ,NULL ,BULKSTAT_FG_IGET , &done))) { + error =xfs_bulkstat (mp, &lastino, &count, + xfs_qm_internalqcheck_adjust, +0 ,NULL , &done); +if (error) { +cmn_err (CE_DEBUG ,"Bulkstat returned error 0x%x" , error);break ; } - }while (! done); -if (error) { -cmn_err (CE_DEBUG ,"Bulkstat returned error 0x%x" , error); - } + }while (!done); +cmn_err (CE_DEBUG ,"Checking results against system dquots" );for (i =0 ; i < qmtest_hashmask; i++) { h1 = &qmtest_udqtab[i];
fs/xfs/xfs_itable.c +40 -240
369 lines not on this page · raw message
fs/xfs/xfs_itable.h +0 -14
@@ -27,10 +27,8 @@ typedef int (*bulkstat_one_pf)(struct xfxfs_ino_t ino, void __user *buffer, int ubsize, - void *private_data, xfs_daddr_t bno, int *ubused, - void *dip, int *stat);/*
@@ -41,13 +39,6 @@ typedef int (*bulkstat_one_pf)(struct xf#define BULKSTAT_RV_GIVEUP 2/* -* Values for bulkstat flag argument. -*/ -#define BULKSTAT_FG_IGET 0x1/* Go through the buffer cache */ -#define BULKSTAT_FG_QUICK 0x2/* No iget, walk the dinode cluster */ -#define BULKSTAT_FG_INLINE 0x4/* No iget if inline attrs */ - -/* * Return stat information in bulk (by-inode) for the filesystem. */ int /* error status */
@@ -56,10 +47,8 @@ xfs_bulkstat( xfs_ino_t *lastino,/* last inode returned */ int *count,/* size of buffer/count returned */ bulkstat_one_pf formatter, /* func that'd fill a single buf */ - void *private_data,/* private data for formatter */ size_t statstruct_size,/* sizeof struct that we're filling */ char__user *ubuffer,/* buffer with inode stats */ - int flags, /* flag to control access method */ int *done); /* 1 if there are more stats to get */int
@@ -84,7 +73,6 @@ xfs_bulkstat_one_int(bulkstat_one_fmt_pf formatter, xfs_daddr_t bno, int *ubused, - void *dibuff, int *stat);int
@@ -93,10 +81,8 @@ xfs_bulkstat_one(xfs_ino_t ino, void __user *buffer, int ubsize, - void *private_data, xfs_daddr_t bno, int *ubused, - void *dibuff, int *stat); typedef int (*inumbers_fmt_pf)(
PATCH 34/68 xfs: validate untrusted inode numbers during lookup
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Dave Chinner <[email protected]>
Upstream commit: 7124fe0a5b619d65b739477b3b55a20bf805b06d
When we decode a handle or do a bulkstat lookup, we are using an inode number we cannot trust to be valid. If we are deleting inode chunks from disk (default noikeep mode), then we cannot trust the on disk inode buffer for any given inode number to correctly reflect whether the inode has been unlinked as the di_mode nor the generation number may have been updated on disk.
This is due to the fact that when we delete an inode chunk, we do not write the clusters back to disk when they are removed - instead we mark them stale to avoid them being written back potentially over the top of something that has been subsequently allocated at that location. The result is that we can have locations of disk that look like they contain valid inodes but in reality do not. Hence we cannot simply convert the inode number to a block number and read the location from disk to determine if the inode is valid or not.
As a result, and XFS_IGET_BULKSTAT lookup needs to actually look the inode up in the inode allocation btree to determine if the inode number is valid or not.
It should be noted even on ikeep filesystems, there is the possibility that blocks on disk may look like valid inode clusters. e.g. if there are filesystem images hosted on the filesystem. Hence even for ikeep filesystems we really need to validate that the inode number is valid before issuing the inode buffer read.
--- fs/xfs/xfs_ialloc.c | 125 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 80 insertions(+), 45 deletions(-)
fs/xfs/xfs_ialloc.c +80 -45
@@ -1206,6 +1206,65 @@ error0:return error; } +STATIC int +xfs_imap_lookup ( +struct xfs_mount *mp, +struct xfs_trans *tp, +xfs_agnumber_t agno, +xfs_agino_t agino, +xfs_agblock_t agbno, +xfs_agblock_t *chunk_agbno, +xfs_agblock_t *offset_agbno, +int flags) +{ +struct xfs_inobt_rec_incore rec; +struct xfs_btree_cur *cur; +struct xfs_buf *agbp; +xfs_agino_t startino; +int error; +int i; + +down_read (&mp->m_peraglock); + error =xfs_ialloc_read_agi (mp, tp, agno, &agbp); +up_read (&mp->m_peraglock); +if (error) { +xfs_fs_cmn_err (CE_ALERT , mp,"xfs_imap: " +"xfs_ialloc_read_agi() returned " +"error %d, agno %d" , + error, agno); +return error; + } + +/* +* derive and lookup the exact inode record for the given agino. If the +* record cannot be found, then it's an invalid inode number and we +* should abort. +*/ + cur =xfs_inobt_init_cursor (mp, tp, agbp, agno); + startino = agino & ~(XFS_IALLOC_INODES (mp) -1 ); + error =xfs_inobt_lookup (cur, startino,XFS_LOOKUP_EQ , &i); +if (!error) { +if (i) + error =xfs_inobt_get_rec (cur, &rec, &i); +if (!error && i ==0 ) + error =EINVAL ; + } + +xfs_trans_brelse (tp, agbp); +xfs_btree_del_cursor (cur,XFS_BTREE_NOERROR ); +if (error) +return error; + +/* for untrusted inodes check it is allocated first */ +if ((flags &XFS_IGET_BULKSTAT ) && + (rec.ir_free &XFS_INOBT_MASK (agino - rec.ir_startino))) +return EINVAL ; + + *chunk_agbno =XFS_AGINO_TO_AGBNO (mp, rec.ir_startino); + *offset_agbno = agbno - *chunk_agbno; +return 0 ; +} +/* * Return the location of the inode in imap, for mapping it into a buffer. */
@@ -1266,6 +1325,23 @@ xfs_imap(return XFS_ERROR (EINVAL ); } + blks_per_cluster =XFS_INODE_CLUSTER_SIZE (mp) >> mp->m_sb.sb_blocklog; + +/* +* For bulkstat and handle lookups, we have an untrusted inode number +* that we have to verify is valid. We cannot do this just by reading +* the inode buffer as it may have been unlinked and removed leaving +* inodes in stale state on disk. Hence we have to do a btree lookup +* in all cases where an untrusted inode number is passed. +*/ +if (flags &XFS_IGET_BULKSTAT ) { + error =xfs_imap_lookup (mp, tp, agno, agino, agbno, + &chunk_agbno, &offset_agbno, flags); +if (error) +return error; + goto out_map; + } +/* * If the inode cluster size is the same as the blocksize or * smaller we get to the buffer by simple arithmetics.
@@ -1280,10 +1356,8 @@ xfs_imap(return 0 ; } - blks_per_cluster =XFS_INODE_CLUSTER_SIZE (mp) >> mp->m_sb.sb_blocklog; -/* -* If we get a block number passed from bulkstat we can use it to +* If we get a block number passed we can use it to * find the buffer easily. */ if (imap->im_blkno) {
@@ -1307,52 +1381,13 @@ xfs_imap( offset_agbno = agbno & mp->m_inoalign_mask; chunk_agbno = agbno - offset_agbno; }else { -xfs_btree_cur_t *cur;/* inode btree cursor */ -xfs_inobt_rec_incore_t chunk_rec; -xfs_buf_t *agbp;/* agi buffer */ -int i;/* temp state */ - -down_read (&mp->m_peraglock); - error =xfs_ialloc_read_agi (mp, tp, agno, &agbp); -up_read (&mp->m_peraglock); -if (error) { -xfs_fs_cmn_err (CE_ALERT , mp,"xfs_imap: " -"xfs_ialloc_read_agi() returned " -"error %d, agno %d" , - error, agno); -return error; - } - - cur =xfs_inobt_init_cursor (mp, tp, agbp, agno); - error =xfs_inobt_lookup (cur, agino,XFS_LOOKUP_LE , &i); -if (error) { -xfs_fs_cmn_err (CE_ALERT , mp,"xfs_imap: " -"xfs_inobt_lookup() failed" ); - goto error0; - } - - error =xfs_inobt_get_rec (cur, &chunk_rec, &i); -if (error) { -xfs_fs_cmn_err (CE_ALERT , mp,"xfs_imap: " -"xfs_inobt_get_rec() failed" ); - goto error0; - } -if (i ==0 ) { -#ifdef DEBUG -xfs_fs_cmn_err (CE_ALERT , mp,"xfs_imap: " -"xfs_inobt_get_rec() failed" ); -#endif /* DEBUG */ - error =XFS_ERROR (EINVAL ); - } - error0: -xfs_trans_brelse (tp, agbp); -xfs_btree_del_cursor (cur,XFS_BTREE_NOERROR ); + error =xfs_imap_lookup (mp, tp, agno, agino, agbno, + &chunk_agbno, &offset_agbno, flags);if (error)return error; - chunk_agbno =XFS_AGINO_TO_AGBNO (mp, chunk_rec.ir_startino); - offset_agbno = agbno - chunk_agbno; } +out_map:ASSERT (agbno >= chunk_agbno); cluster_agbno = chunk_agbno + ((offset_agbno / blks_per_cluster) * blks_per_cluster);
PATCH 35/68 xfs: rename XFS_IGET_BULKSTAT to XFS_IGET_UNTRUSTED
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Dave Chinner <[email protected]>
Upstream commit: 1920779e67cbf5ea8afef317777c5bf2b8096188
Inode numbers may come from somewhere external to the filesystem (e.g. file handles, bulkstat information) and so are inherently untrusted. Rename the flag we use for these lookups to make it obvious we are doing a lookup of an untrusted inode number and need to verify it completely before trying to read it from disk.
--- fs/xfs/linux-2.6/xfs_export.c | 9 ++++----- fs/xfs/xfs_ialloc.c | 11 +++++++---- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_inode.h | 2 +- fs/xfs/xfs_itable.c | 2 +- 5 files changed, 14 insertions(+), 12 deletions(-)
fs/xfs/linux-2.6/xfs_export.c +4 -5
@@ -127,12 +127,11 @@ xfs_nfs_get_inode(return ERR_PTR (-ESTALE );/* -* The XFS_IGET_BULKSTAT means that an invalid inode number is just -* fine and not an indication of a corrupted filesystem. Because -* clients can send any kind of invalid file handle, e.g. after -* a restore on the server we have to deal with this case gracefully. +* The XFS_IGET_UNTRUSTED means that an invalid inode number is just +* fine and not an indication of a corrupted filesystem as clients can +* send invalid file handles and we have to handle it gracefully.. */ - error =xfs_iget (mp,NULL , ino,XFS_IGET_BULKSTAT , + error =xfs_iget (mp,NULL , ino,XFS_IGET_UNTRUSTED ,XFS_ILOCK_SHARED , &ip,0 );if (error) {/*
fs/xfs/xfs_ialloc.c +7 -4
@@ -1256,7 +1256,7 @@ xfs_imap_lookup(return error;/* for untrusted inodes check it is allocated first */ -if ((flags &XFS_IGET_BULKSTAT ) && +if ((flags &XFS_IGET_UNTRUSTED ) && (rec.ir_free &XFS_INOBT_MASK (agino - rec.ir_startino)))return EINVAL ;
@@ -1297,8 +1297,11 @@ xfs_imap( if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || ino != XFS_AGINO_TO_INO(mp, agno, agino)) { #ifdef DEBUG - /* no diagnostics for bulkstat, ino comes from userspace */ - if (flags & XFS_IGET_BULKSTAT) + /* + * Don't output diagnostic information for untrusted inodes + * as they can be invalid without implying corruption. + */ + if (flags & XFS_IGET_UNTRUSTED) return XFS_ERROR(EINVAL); if (agno >= mp->m_sb.sb_agcount) { xfs_fs_cmn_err(CE_ALERT, mp,
@@ -1334,7 +1337,7 @@ xfs_imap(* inodes in stale state on disk. Hence we have to do a btree lookup * in all cases where an untrusted inode number is passed. */ -if (flags &XFS_IGET_BULKSTAT ) { +if (flags &XFS_IGET_UNTRUSTED ) { error =xfs_imap_lookup (mp, tp, agno, agino, agbno, &chunk_agbno, &offset_agbno, flags);if (error)
fs/xfs/xfs_inode.c +1 -1
@@ -177,7 +177,7 @@ xfs_imap_to_bp(if (unlikely (XFS_TEST_ERROR (!di_ok, mp,XFS_ERRTAG_ITOBP_INOTOBP ,XFS_RANDOM_ITOBP_INOTOBP ))) { -if (iget_flags &XFS_IGET_BULKSTAT ) { +if (iget_flags &XFS_IGET_UNTRUSTED ) {xfs_trans_brelse (tp, bp);return XFS_ERROR (EINVAL ); }
fs/xfs/xfs_inode.h +1 -1
@@ -558,7 +558,7 @@ do { \* Flags for xfs_iget() */ #define XFS_IGET_CREATE 0x1 -#define XFS_IGET_BULKSTAT 0x2 +#define XFS_IGET_UNTRUSTED 0x2 int xfs_inotobp(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, struct xfs_dinode **,
fs/xfs/xfs_itable.c +1 -1
@@ -80,7 +80,7 @@ xfs_bulkstat_one_int(return XFS_ERROR (ENOMEM ); error =xfs_iget (mp,NULL , ino, -XFS_IGET_BULKSTAT ,XFS_ILOCK_SHARED , &ip, bno); +XFS_IGET_UNTRUSTED ,XFS_ILOCK_SHARED , &ip, bno);if (error) { *stat =BULKSTAT_RV_NOTHING ; goto out_free;
PATCH 36/68 xfs: remove block number from inode lookup code
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Dave Chinner <[email protected]>
Upstream commit: 7b6259e7a83647948fa33a736cc832310c8d85aa
The block number comes from bulkstat based inode lookups to shortcut the mapping calculations. We ar enot able to trust anything from bulkstat, so drop the block number as well so that the correct lookups and mappings are always done.
--- fs/xfs/linux-2.6/xfs_export.c | 2 +- fs/xfs/linux-2.6/xfs_ioctl32.c | 5 ++--- fs/xfs/quota/xfs_qm.c | 7 +++---- fs/xfs/quota/xfs_qm_syscalls.c | 11 +++++------ fs/xfs/xfs_ialloc.c | 16 ---------------- fs/xfs/xfs_iget.c | 10 +++------- fs/xfs/xfs_inode.c | 3 --- fs/xfs/xfs_inode.h | 4 ++-- fs/xfs/xfs_itable.c | 12 ++++-------- fs/xfs/xfs_itable.h | 3 --- fs/xfs/xfs_log_recover.c | 2 +- fs/xfs/xfs_mount.c | 2 +- fs/xfs/xfs_rtalloc.c | 4 ++-- fs/xfs/xfs_trans_inode.c | 2 +- fs/xfs/xfs_vnodeops.c | 2 +- 15 files changed, 26 insertions(+), 59 deletions(-)
fs/xfs/linux-2.6/xfs_export.c +1 -1
@@ -132,7 +132,7 @@ xfs_nfs_get_inode(* send invalid file handles and we have to handle it gracefully.. */ error =xfs_iget (mp,NULL , ino,XFS_IGET_UNTRUSTED , -XFS_ILOCK_SHARED , &ip,0 ); +XFS_ILOCK_SHARED , &ip);if (error) {/* * EINVAL means the inode cluster doesn't exist anymore.
fs/xfs/linux-2.6/xfs_ioctl32.c +2 -3
@@ -235,12 +235,11 @@ xfs_bulkstat_one_compat(xfs_ino_t ino,/* inode number to get data for */ void __user *buffer, /* buffer to place output in */ int ubsize, /* size of buffer */ - xfs_daddr_t bno, /* starting bno of inode cluster */ int *ubused, /* bytes used by me */ int *stat) /* BULKSTAT_RV_... */ { return xfs_bulkstat_one_int(mp, ino, buffer, ubsize, -xfs_bulkstat_one_fmt_compat ,bno , +xfs_bulkstat_one_fmt_compat ,ubused ,stat ); }
@@ -294,7 +293,7 @@ xfs_compat_ioc_bulkstat(int res; error =xfs_bulkstat_one_compat (mp, inlast, bulkreq.ubuffer, -sizeof (compat_xfs_bstat_t),0 ,NULL , &res); +sizeof (compat_xfs_bstat_t),0 , &res); }else if (cmd ==XFS_IOC_FSBULKSTAT_32 ) { error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one_compat, sizeof(compat_xfs_bstat_t),
fs/xfs/quota/xfs_qm.c +3 -4
@@ -1606,7 +1606,6 @@ xfs_qm_dqusage_adjust(xfs_ino_t ino,/* inode number to get data for */ void __user *buffer, /* not used */ int ubsize, /* not used */ - xfs_daddr_t bno, /* starting block of inode cluster */ int *ubused, /* not used */ int *res) /* result code value */ {
@@ -1632,7 +1631,7 @@ xfs_qm_dqusage_adjust(* the case in all other instances. It's OK that we do this because * quotacheck is done only at mount time. */ -if ((error =xfs_iget (mp,NULL , ino,0 ,XFS_ILOCK_EXCL , &ip, bno))) { +if ((error =xfs_iget (mp,NULL , ino,0 ,XFS_ILOCK_EXCL , &ip))) { *res =BULKSTAT_RV_NOTHING ;return error; }
@@ -1858,14 +1857,14 @@ xfs_qm_init_quotainos( mp->m_sb.sb_uquotino != NULLFSINO) {ASSERT (mp->m_sb.sb_uquotino >0 );if ((error =xfs_iget (mp,NULL , mp->m_sb.sb_uquotino, -0 ,0 , &uip,0 ))) +0 ,0 , &uip)))return XFS_ERROR (error); }if (XFS_IS_OQUOTA_ON (mp) && mp->m_sb.sb_gquotino !=NULLFSINO ) {ASSERT (mp->m_sb.sb_gquotino >0 );if ((error =xfs_iget (mp,NULL , mp->m_sb.sb_gquotino, -0 ,0 , &gip,0 ))) { +0 ,0 , &gip))) {if (uip)IRELE (uip);return XFS_ERROR (error);
fs/xfs/quota/xfs_qm_syscalls.c +5 -6
@@ -266,7 +266,7 @@ xfs_qm_scall_trunc_qfiles( }if ((flags &XFS_DQ_USER ) && mp->m_sb.sb_uquotino !=NULLFSINO ) { - error =xfs_iget (mp,NULL , mp->m_sb.sb_uquotino,0 ,0 , &qip,0 ); + error =xfs_iget (mp,NULL , mp->m_sb.sb_uquotino,0 ,0 , &qip);if (!error) { error =xfs_truncate_file (mp, qip);IRELE (qip);
@@ -275,7 +275,7 @@ xfs_qm_scall_trunc_qfiles(if ((flags & (XFS_DQ_GROUP |XFS_DQ_PROJ )) && mp->m_sb.sb_gquotino !=NULLFSINO ) { - error2 =xfs_iget (mp,NULL , mp->m_sb.sb_gquotino,0 ,0 , &qip,0 ); + error2 =xfs_iget (mp,NULL , mp->m_sb.sb_gquotino,0 ,0 , &qip);if (!error2) { error2 =xfs_truncate_file (mp, qip);IRELE (qip);
@@ -420,12 +420,12 @@ xfs_qm_scall_getqstat( }if (!uip && mp->m_sb.sb_uquotino !=NULLFSINO ) {if (xfs_iget (mp,NULL , mp->m_sb.sb_uquotino, -0 ,0 , &uip,0 ) ==0 ) +0 ,0 , &uip) ==0 ) tempuqip =B_TRUE ; }if (!gip && mp->m_sb.sb_gquotino !=NULLFSINO ) {if (xfs_iget (mp,NULL , mp->m_sb.sb_gquotino, -0 ,0 , &gip,0 ) ==0 ) +0 ,0 , &gip) ==0 ) tempgqip =B_TRUE ; }if (uip) {
@@ -1114,7 +1114,6 @@ xfs_qm_internalqcheck_adjust(xfs_ino_t ino,/* inode number to get data for */ void __user *buffer, /* not used */ int ubsize, /* not used */ - xfs_daddr_t bno, /* starting block of inode cluster */ int *ubused, /* not used */ int *res) /* bulkstat result code */ {
@@ -1137,7 +1136,7 @@ xfs_qm_internalqcheck_adjust( ipreleased =B_FALSE ; again: lock_flags =XFS_ILOCK_SHARED ; -if ((error =xfs_iget (mp,NULL , ino,0 , lock_flags, &ip, bno))) { +if ((error =xfs_iget (mp,NULL , ino,0 , lock_flags, &ip))) { *res =BULKSTAT_RV_NOTHING ;return (error); }
fs/xfs/xfs_ialloc.c +0 -16
@@ -1360,22 +1360,6 @@ xfs_imap( }/* -* If we get a block number passed we can use it to -* find the buffer easily. -*/ -if (imap->im_blkno) { - offset =XFS_INO_TO_OFFSET (mp, ino); -ASSERT (offset < mp->m_sb.sb_inopblock); - - cluster_agbno =xfs_daddr_to_agbno (mp, imap->im_blkno); - offset += (agbno - cluster_agbno) * mp->m_sb.sb_inopblock; - - imap->im_len =XFS_FSB_TO_BB (mp, blks_per_cluster); - imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog); -return 0 ; - } - -/* * If the inode chunks are aligned then use simple maths to * find the location. Otherwise we have to do a btree * lookup to find the location.
fs/xfs/xfs_iget.c +3 -7
@@ -295,7 +295,6 @@ xfs_iget_cache_miss( xfs_trans_t *tp, xfs_ino_t ino, struct xfs_inode **ipp, - xfs_daddr_t bno, int flags, int lock_flags) __releases(pag->pag_ici_lock) {
@@ -308,7 +307,7 @@ xfs_iget_cache_miss(if (!ip)return ENOMEM ; - error =xfs_iread (mp, tp, ip, bno, flags); + error =xfs_iread (mp, tp, ip, flags);if (error) goto out_destroy;
@@ -392,8 +391,6 @@ out_destroy:* within the file system for the inode being requested. * lock_flags -- flags indicating how to lock the inode. See the comment * for xfs_ilock() for a list of valid values. -* bno -- the block number starting the buffer containing the inode, -* if known (as by bulkstat), else 0. */ int xfs_iget(
@@ -402,8 +399,7 @@ xfs_iget(xfs_ino_t ino, uint flags, uint lock_flags, - xfs_inode_t **ipp, - xfs_daddr_t bno) + xfs_inode_t **ipp) { xfs_inode_t *ip;int error;
@@ -434,7 +430,7 @@ again:read_unlock (&pag->pag_ici_lock);XFS_STATS_INC (xs_ig_missed); - error =xfs_iget_cache_miss (mp, pag, tp, ino, &ip, bno, + error =xfs_iget_cache_miss (mp, pag, tp, ino, &ip, flags, lock_flags);if (error) goto out_error_or_again;
fs/xfs/xfs_inode.c +0 -3
@@ -787,7 +787,6 @@ xfs_iread( xfs_mount_t *mp, xfs_trans_t *tp, xfs_inode_t *ip, - xfs_daddr_t bno, uint iget_flags) {xfs_buf_t *bp;
@@ -797,11 +796,9 @@ xfs_iread(/* * Fill in the location information in the in-core inode. */ - ip->i_imap.im_blkno = bno; error =xfs_imap (mp, tp, ip->i_ino, &ip->i_imap, iget_flags);if (error)return error; -ASSERT (bno ==0 || bno == ip->i_imap.im_blkno);/* * Get pointers to the on-disk inode and the buffer containing it.
fs/xfs/xfs_inode.h +2 -2
@@ -468,7 +468,7 @@ static inline void xfs_ifunlock(xfs_inod* xfs_iget.c prototypes. */ int xfs_iget (struct xfs_mount *,struct xfs_trans *,xfs_ino_t , -uint ,uint ,xfs_inode_t **,xfs_daddr_t ); +uint ,uint ,xfs_inode_t **);void xfs_iput (xfs_inode_t *,uint );void xfs_iput_new (xfs_inode_t *,uint );void xfs_ilock (xfs_inode_t *,uint );
@@ -567,7 +567,7 @@ int xfs_itobp(struct xfs_mount *, struc struct xfs_inode *, struct xfs_dinode **, struct xfs_buf **, uint);int xfs_iread (struct xfs_mount *,struct xfs_trans *, -struct xfs_inode *,xfs_daddr_t ,uint ); +struct xfs_inode *,uint );void xfs_dinode_to_disk (struct xfs_dinode *,struct xfs_icdinode *);void xfs_idestroy_fork (struct xfs_inode *,int );
fs/xfs/xfs_itable.c +4 -8
@@ -60,7 +60,6 @@ xfs_bulkstat_one_int(void __user *buffer,/* buffer to place output in */ int ubsize, /* size of buffer */ bulkstat_one_fmt_pf formatter, /* formatter, copy to user */ - xfs_daddr_t bno, /* starting bno of cluster */ int *ubused, /* bytes used by me */ int *stat) /* BULKSTAT_RV_... */ {
@@ -80,7 +79,7 @@ xfs_bulkstat_one_int(return XFS_ERROR (ENOMEM ); error =xfs_iget (mp,NULL , ino, -XFS_IGET_UNTRUSTED ,XFS_ILOCK_SHARED , &ip, bno); +XFS_IGET_UNTRUSTED ,XFS_ILOCK_SHARED , &ip);if (error) { *stat =BULKSTAT_RV_NOTHING ; goto out_free;
@@ -178,13 +177,11 @@ xfs_bulkstat_one(xfs_ino_t ino,/* inode number to get data for */ void __user *buffer, /* buffer to place output in */ int ubsize, /* size of buffer */ - xfs_daddr_t bno, /* starting bno of inode cluster */ int *ubused, /* bytes used by me */ int *stat) /* BULKSTAT_RV_... */ { return xfs_bulkstat_one_int(mp, ino, buffer, ubsize, -xfs_bulkstat_one_fmt ,bno , -ubused ,stat ); +xfs_bulkstat_one_fmt ,ubused ,stat ); }#define XFS_BULKSTAT_UBLEFT (ubleft) ((ubleft) >= statstruct_size)
@@ -484,7 +481,7 @@ xfs_bulkstat(* Get the inode and fill in a single buffer. */ ubused = statstruct_size; - error =formatter (mp, ino, ubufp, ubleft, bno, + error =formatter (mp, ino, ubufp, ubleft, &ubused, &fmterror);if (fmterror ==BULKSTAT_RV_NOTHING ) { if (error && error != ENOENT &&
@@ -577,8 +574,7 @@ xfs_bulkstat_single(*/ ino = (xfs_ino_t)*lastinop; - error =xfs_bulkstat_one (mp, ino, buffer,sizeof (xfs_bstat_t), -0 ,NULL , &res); + error =xfs_bulkstat_one (mp, ino, buffer,sizeof (xfs_bstat_t),0 , &res);if (error) {/* * Special case way failed, do it the "long" way
fs/xfs/xfs_itable.h +0 -3
@@ -27,7 +27,6 @@ typedef int (*bulkstat_one_pf)(struct xfxfs_ino_t ino, void __user *buffer, int ubsize, - xfs_daddr_t bno, int *ubused, int *stat);
@@ -71,7 +70,6 @@ xfs_bulkstat_one_int(void __user *buffer, int ubsize, bulkstat_one_fmt_pf formatter, - xfs_daddr_t bno, int *ubused, int *stat);
@@ -81,7 +79,6 @@ xfs_bulkstat_one(xfs_ino_t ino, void __user *buffer, int ubsize, - xfs_daddr_t bno, int *ubused, int *stat);
fs/xfs/xfs_log_recover.c +1 -1
@@ -3209,7 +3209,7 @@ xlog_recover_process_one_iunlink(int error; ino =XFS_AGINO_TO_INO (mp, agno, agino); - error =xfs_iget (mp,NULL , ino,0 ,0 , &ip,0 ); + error =xfs_iget (mp,NULL , ino,0 ,0 , &ip);if (error) goto fail;
fs/xfs/xfs_mount.c +1 -1
@@ -1207,7 +1207,7 @@ xfs_mountfs(* Get and sanity-check the root inode. * Save the pointer to it in the mount structure. */ - error =xfs_iget (mp,NULL , sbp->sb_rootino,0 ,XFS_ILOCK_EXCL , &rip,0 ); + error =xfs_iget (mp,NULL , sbp->sb_rootino,0 ,XFS_ILOCK_EXCL , &rip);if (error) {cmn_err (CE_WARN ,"XFS: failed to read root inode" ); goto out_log_dealloc;
fs/xfs/xfs_rtalloc.c +2 -2
@@ -2274,12 +2274,12 @@ xfs_rtmount_inodes( sbp = &mp->m_sb;if (sbp->sb_rbmino ==NULLFSINO )return 0 ; - error =xfs_iget (mp,NULL , sbp->sb_rbmino,0 ,0 , &mp->m_rbmip,0 ); + error =xfs_iget (mp,NULL , sbp->sb_rbmino,0 ,0 , &mp->m_rbmip);if (error)return error;ASSERT (mp->m_rbmip !=NULL );ASSERT (sbp->sb_rsumino !=NULLFSINO ); - error =xfs_iget (mp,NULL , sbp->sb_rsumino,0 ,0 , &mp->m_rsumip,0 ); + error =xfs_iget (mp,NULL , sbp->sb_rsumino,0 ,0 , &mp->m_rsumip);if (error) {IRELE (mp->m_rbmip);return error;
fs/xfs/xfs_trans_inode.c +1 -1
@@ -62,7 +62,7 @@ xfs_trans_iget( {int error; - error =xfs_iget (mp, tp, ino, flags, lock_flags, ipp,0 ); + error =xfs_iget (mp, tp, ino, flags, lock_flags, ipp);if (!error && tp)xfs_trans_ijoin (tp, *ipp, lock_flags);return error;
fs/xfs/xfs_vnodeops.c +1 -1
@@ -1371,7 +1371,7 @@ xfs_lookup(if (error) goto out; - error =xfs_iget (dp->i_mount,NULL , inum,0 ,0 , ipp,0 ); + error =xfs_iget (dp->i_mount,NULL , inum,0 ,0 , ipp);if (error) goto out_free_name;
PATCH 37/68 xfs: fix untrusted inode number lookup
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Dave Chinner <[email protected]>
Upstream commit: 4536f2ad8b330453d7ebec0746c4374eadd649b1
Commit 7124fe0a5b619d65b739477b3b55a20bf805b06d ("xfs: validate untrusted inode numbers during lookup") changes the inode lookup code to do btree lookups for untrusted inode numbers. This change made an invalid assumption about the alignment of inodes and hence incorrectly calculated the first inode in the cluster. As a result, some inode numbers were being incorrectly considered invalid when they were actually valid.
The issue was not picked up by the xfstests suite because it always runs fsr and dump (the two utilities that utilise the bulkstat interface) on cache hot inodes and hence the lookup code in the cold cache path was not sufficiently exercised to uncover this intermittent problem.
Fix the issue by relaxing the btree lookup criteria and then checking if the record returned contains the inode number we are lookup for. If it we get an incorrect record, then the inode number is invalid.
--- fs/xfs/xfs_ialloc.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
fs/xfs/xfs_ialloc.c +10 -6
@@ -1220,7 +1220,6 @@ xfs_imap_lookup(struct xfs_inobt_rec_incore rec;struct xfs_btree_cur *cur;struct xfs_buf *agbp; -xfs_agino_t startino;int error;int i;
@@ -1236,13 +1235,13 @@ xfs_imap_lookup( }/* -* derive and lookup the exact inode record for the given agino. If the -* record cannot be found, then it's an invalid inode number and we -* should abort. +* Lookup the inode record for the given agino. If the record cannot be +* found, then it's an invalid inode number and we should abort. Once +* we have a record, we need to ensure it contains the inode number +* we are looking up. */ cur =xfs_inobt_init_cursor (mp, tp, agbp, agno); - startino = agino & ~(XFS_IALLOC_INODES (mp) -1 ); - error =xfs_inobt_lookup (cur, startino,XFS_LOOKUP_EQ , &i); + error =xfs_inobt_lookup (cur, agino,XFS_LOOKUP_LE , &i);if (!error) {if (i) error =xfs_inobt_get_rec (cur, &rec, &i);
@@ -1255,6 +1254,11 @@ xfs_imap_lookup(if (error)return error; +/* check that the returned record contains the required inode */ +if (rec.ir_startino > agino || + rec.ir_startino +XFS_IALLOC_INODES (mp) <= agino) +return EINVAL ; +/* for untrusted inodes check it is allocated first */ if ((flags &XFS_IGET_UNTRUSTED ) && (rec.ir_free &XFS_INOBT_MASK (agino - rec.ir_startino)))
PATCH 38/68 s390: remove task_show_regs
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Martin Schwidefsky <[email protected]>
commit 261cd298a8c363d7985e3482946edb4bfedacf98 upstream.
task_show_regs used to be a debugging aid in the early bringup days of Linux on s390. /proc/<pid>/status is a world readable file, it is not a good idea to show the registers of a process. The only correct fix is to remove task_show_regs.
--- arch/s390/include/asm/processor.h | 5 ----- arch/s390/kernel/traps.c | 37 ------------------------------------- fs/proc/array.c | 3 --- 3 files changed, 45 deletions(-)
arch/s390/include/asm/processor.h +0 -5
@@ -150,11 +150,6 @@ extern int kernel_thread(int (*fn)(void*/ extern unsigned long thread_saved_pc (struct task_struct *t); -/* -* Print register of task into buffer. Used in fs/proc/array.c. -*/ -extern void task_show_regs (struct seq_file *m,struct task_struct *task); -extern void show_code (struct pt_regs *regs);unsigned long get_wchan (struct task_struct *p);
arch/s390/kernel/traps.c +0 -37
@@ -243,43 +243,6 @@ void show_regs(struct pt_regs *regs)show_last_breaking_event (regs); } -/* This is called from fs/proc/array.c */ -void task_show_regs (struct seq_file *m,struct task_struct *task) -{ -struct pt_regs *regs; - - regs =task_pt_regs (task); -seq_printf (m,"task: %p, ksp: %p\n" , - task, (void *)task->thread.ksp); -seq_printf (m,"User PSW : %p %p\n" , - (void *) regs->psw.mask, (void *)regs->psw.addr); - -seq_printf (m,"User GPRS: " FOURLONG , - regs->gprs[0 ], regs->gprs[1 ], - regs->gprs[2 ], regs->gprs[3 ]); -seq_printf (m," " FOURLONG , - regs->gprs[4 ], regs->gprs[5 ], - regs->gprs[6 ], regs->gprs[7 ]); -seq_printf (m," " FOURLONG , - regs->gprs[8 ], regs->gprs[9 ], - regs->gprs[10 ], regs->gprs[11 ]); -seq_printf (m," " FOURLONG , - regs->gprs[12 ], regs->gprs[13 ], - regs->gprs[14 ], regs->gprs[15 ]); -seq_printf (m,"User ACRS: %08x %08x %08x %08x\n" , - task->thread.acrs[0 ], task->thread.acrs[1 ], - task->thread.acrs[2 ], task->thread.acrs[3 ]); -seq_printf (m," %08x %08x %08x %08x\n" , - task->thread.acrs[4 ], task->thread.acrs[5 ], - task->thread.acrs[6 ], task->thread.acrs[7 ]); -seq_printf (m," %08x %08x %08x %08x\n" , - task->thread.acrs[8 ], task->thread.acrs[9 ], - task->thread.acrs[10 ], task->thread.acrs[11 ]); -seq_printf (m," %08x %08x %08x %08x\n" , - task->thread.acrs[12 ], task->thread.acrs[13 ], - task->thread.acrs[14 ], task->thread.acrs[15 ]); -} -static DEFINE_SPINLOCK (die_lock);void die (const char * str,struct pt_regs * regs,long err)
fs/proc/array.c +0 -3
@@ -336,9 +336,6 @@ int proc_pid_status(struct seq_file *m,task_sig (m, task);task_cap (m, task);cpuset_task_status_allowed (m, task); -#if defined(CONFIG_S390 ) -task_show_regs (m, task); -#endif task_context_switch_counts (m, task);return 0 ; }
PATCH 39/68 PM / Hibernate: Return error code when alloc_image_page() fails
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Stanislaw Gruszka <[email protected]>
commit 2e725a065b0153f0c449318da1923a120477633d upstream.
Currently we return 0 in swsusp_alloc() when alloc_image_page() fails. Fix that. Also remove unneeded "error" variable since the only useful value of error is -ENOMEM.
[rjw: Fixed up the changelog and changed subject.]
--- kernel/power/snapshot.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
kernel/power/snapshot.c +2 -5
@@ -1466,11 +1466,8 @@ static int swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm, unsigned int nr_pages, unsigned int nr_highmem) { - int error = 0; - if (nr_highmem > 0) { - error =get_highmem_buffer (PG_ANY ); -if (error) + if (get_highmem_buffer(PG_ANY)) goto err_out;if (nr_highmem > alloc_highmem) { nr_highmem -= alloc_highmem;
@@ -1493,7 +1490,7 @@ swsusp_alloc(struct memory_bitmap *orig_ err_out:swsusp_free (); -return error; +return -ENOMEM ; } asmlinkage int swsusp_save(void)
PATCH 40/68 fs/partitions: Validate map_count in Mac partition tables
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Timo Warns <[email protected]>
commit fa7ea87a057958a8b7926c1a60a3ca6d696328ed upstream.
Validate number of blocks in map and remove redundant variable.
--- fs/partitions/mac.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
fs/partitions/mac.c +9 -8
@@ -29,10 +29,9 @@ static inline void mac_fix_string(char *int mac_partition (struct parsed_partitions *state,struct block_device *bdev) { -int slot =1 ;Sector sect;unsigned char *data; -int blk, blocks_in_map; +int slot, blocks_in_map;unsigned secsize;#ifdef CONFIG_PPC_PMAC int found_root =0 ;
@@ -59,10 +58,14 @@ int mac_partition(struct parsed_partitioput_dev_sector (sect);return 0 ;/* not a MacOS disk */ } -printk (" [mac]" ); blocks_in_map =be32_to_cpu (part->map_count); -for (blk =1 ; blk <= blocks_in_map; ++blk) { -int pos = blk * secsize; +if (blocks_in_map <0 || blocks_in_map >=DISK_MAX_PARTS ) { +put_dev_sector (sect); +return 0 ; + } +printk (" [mac]" ); +for (slot =1 ; slot <= blocks_in_map; ++slot) { +int pos = slot * secsize;put_dev_sector (sect); data =read_dev_sector (bdev, pos/512 , §);if (!data)
@@ -113,13 +116,11 @@ int mac_partition(struct parsed_partitio }if (goodness > found_root_goodness) { - found_root = blk; + found_root = slot; found_root_goodness = goodness; } }#endif /* CONFIG_PPC_PMAC */ - - ++slot; }#ifdef CONFIG_PPC_PMAC if (found_root_goodness)
PATCH 41/68 ALSA: HDA: Add position_fix quirk for an Asus device
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: David Henningsson <[email protected]>
commit b540afc2b3d6e4cd1d1f137ef6d9e9c78d67fecd upstream.
The bug reporter claims that position_fix=1 is needed for his microphone to work. The controller PCI vendor-id is [1002:4383] (rev 40).
--- sound/pci/hda/hda_intel.c | 1 + 1 file changed, 1 insertion(+)
sound/pci/hda/hda_intel.c +1 -0
@@ -2236,6 +2236,7 @@ static struct snd_pci_quirk position_fixSND_PCI_QUIRK (0x1043 ,0x813d ,"ASUS P5AD2" ,POS_FIX_LPIB ),SND_PCI_QUIRK (0x1043 ,0x81b3 ,"ASUS" ,POS_FIX_LPIB ),SND_PCI_QUIRK (0x1043 ,0x81e7 ,"ASUS M2V" ,POS_FIX_LPIB ), +SND_PCI_QUIRK (0x1043 ,0x8410 ,"ASUS" ,POS_FIX_LPIB ),SND_PCI_QUIRK (0x104d ,0x9069 ,"Sony VPCS11V9E" ,POS_FIX_LPIB ),SND_PCI_QUIRK (0x1106 ,0x3288 ,"ASUS M2V-MX SE" ,POS_FIX_LPIB ), SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba A100-259", POS_FIX_LPIB),
PATCH 42/68 ALSA: caiaq - Fix possible string-buffer overflow
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Takashi Iwai <[email protected]>
commit eaae55dac6b64c0616046436b294e69fc5311581 upstream.
Use strlcpy() to assure not to overflow the string array sizes by too long USB device name string.
--- sound/usb/caiaq/audio.c | 2 +- sound/usb/caiaq/midi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
sound/usb/caiaq/audio.c +1 -1
@@ -639,7 +639,7 @@ int snd_usb_caiaq_audio_init(struct snd_ } dev->pcm->private_data = dev; -strcpy (dev->pcm->name, dev->product_name); +strlcpy (dev->pcm->name, dev->product_name,sizeof (dev->pcm->name));memset (dev->sub_playback,0 ,sizeof (dev->sub_playback));memset (dev->sub_capture,0 ,sizeof (dev->sub_capture));
sound/usb/caiaq/midi.c +1 -1
@@ -135,7 +135,7 @@ int snd_usb_caiaq_midi_init(struct snd_uif (ret <0 )return ret; -strcpy (rmidi->name, device->product_name); +strlcpy (rmidi->name, device->product_name,sizeof (rmidi->name)); rmidi->info_flags =SNDRV_RAWMIDI_INFO_DUPLEX ; rmidi->private_data = device;
PATCH 43/68 radio-aimslab.c needs #include <linux/delay.h>
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Geert Uytterhoeven <[email protected]>
commit 2400982a2e8a8e4e95f0a0e1517bbe63cc88038f upstream.
Commit e3c92215198cb6aa00ad38db2780faa6b72e0a3f ("[media] radio-aimslab.c: Fix gcc 4.5+ bug") removed the include, but introduced new callers of msleep():
| drivers/media/radio/radio-aimslab.c: In function ‘rt_decvol’:
| drivers/media/radio/radio-aimslab.c:76: error: implicit declaration of function ‘msleep’
--- drivers/media/radio/radio-aimslab.c | 1 + 1 file changed, 1 insertion(+)
drivers/media/radio/radio-aimslab.c +1 -0
@@ -31,6 +31,7 @@#include <linux/module.h> /* Modules */ #include <linux/init.h> /* Initdata */ #include <linux/ioport.h> /* request_region */ +#include <linux/delay.h> /* msleep */ #include <linux/videodev2.h> /* kernel radio structs */ #include <linux/version.h> /* for KERNEL_VERSION MACRO */ #include <linux/io.h> /* outb, outb_p */
PATCH 44/68 ARM: Ensure predictable endian state on signal handler entry
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Russell King <[email protected]>
commit 53399053eb505cf541b2405bd9d9bca5ecfb96fb upstream.
Ensure a predictable endian state when entering signal handlers. This avoids programs which use SETEND to momentarily switch their endian state from having their signal handlers entered with an unpredictable endian state.
--- arch/arm/kernel/signal.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/arm/kernel/signal.c +3 -1
@@ -389,7 +389,9 @@ setup_return(struct pt_regs *regs, strucunsigned long handler = (unsigned long )ka->sa.sa_handler;unsigned long retcode;int thumb =0 ; -unsigned long cpsr = regs->ARM_cpsr & ~PSR_f; +unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f |PSR_E_BIT ); + + cpsr |=PSR_ENDSTATE ;/* * Maybe we need to deliver a 32-bit signal to a 26-bit task.
PATCH 45/68 acer-wmi: Fix capitalisation of GUID
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Matthew Garrett <[email protected]>
commit bbb706079abe955a9e3f208f541de97d99449236 upstream.
6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3 needs to be 6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3 to match the hardware alias.
--- drivers/platform/x86/acer-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/platform/x86/acer-wmi.c +1 -1
@@ -90,7 +90,7 @@ struct acer_quirks {*/ #define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB"#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C" -#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3" +#define WMID_GUID1 "6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A"MODULE_ALIAS ("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB" );
PATCH 46/68 eCryptfs: Copy up lower inode attrs in getattr
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Tyler Hicks <[email protected]>
commit 55f9cf6bbaa682958a7dd2755f883b768270c3ce upstream.
The lower filesystem may do some type of inode revalidation during a getattr call. eCryptfs should take advantage of that by copying the lower inode attributes to the eCryptfs inode after a call to vfs_getattr() on the lower inode.
I originally wrote this fix while working on eCryptfs on nfsv3 support, but discovered it also fixed an eCryptfs on ext4 nanosecond timestamp bug that was reported.
https://bugs.launchpad.net/bugs/613873
--- fs/ecryptfs/inode.c | 2 ++ 1 file changed, 2 insertions(+)
fs/ecryptfs/inode.c +2 -0
@@ -988,6 +988,8 @@ int ecryptfs_getattr(struct vfsmount *mn rc =vfs_getattr (ecryptfs_dentry_to_lower_mnt (dentry),ecryptfs_dentry_to_lower (dentry), &lower_stat);if (!rc) { +fsstack_copy_attr_all (dentry->d_inode, +ecryptfs_inode_to_lower (dentry->d_inode),NULL );generic_fillattr (dentry->d_inode, stat); stat->blocks = lower_stat.blocks; }
PATCH 47/68 platform: x86: acer-wmi: world-writable sysfs threeg file
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Vasiliy Kulikov <[email protected]>
commit b80b168f918bba4b847e884492415546b340e19d upstream.
Don't allow everybody to write to hardware registers.
--- drivers/platform/x86/acer-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/platform/x86/acer-wmi.c +1 -1
@@ -1065,7 +1065,7 @@ static ssize_t set_bool_threeg(struct dereturn -EINVAL ;return count; } -static DEVICE_ATTR(threeg, S_IWUGO | S_IRUGO | S_IWUSR, show_bool_threeg, +static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg, set_bool_threeg); static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
PATCH 48/68 platform: x86: asus_acpi: world-writable procfs files
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Vasiliy Kulikov <[email protected]>
commit 8040835760adf0ef66876c063d47f79f015fb55d upstream.
Don't allow everybody to change ACPI settings. The comment says that it is done deliberatelly, however, the comment before disp_proc_write() says that at least one of these setting is experimental.
--- drivers/platform/x86/asus_acpi.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
drivers/platform/x86/asus_acpi.c +1 -7
@@ -1001,14 +1001,8 @@ static int asus_hotk_add_fs(struct acpi_struct proc_dir_entry *proc;mode_t mode; -/* -* If parameter uid or gid is not changed, keep the default setting for -* our proc entries (-rw-rw-rw-) else, it means we care about security, -* and then set to -rw-rw---- -*/ -if ((asus_uid ==0 ) && (asus_gid ==0 )) { - mode =S_IFREG |S_IRUGO |S_IWUGO ; + mode =S_IFREG |S_IRUGO |S_IWUSR |S_IWGRP ; }else { mode =S_IFREG |S_IRUSR |S_IRGRP |S_IWUSR |S_IWGRP ; printk(KERN_WARNING " asus_uid and asus_gid parameters are "
PATCH 49/68 platform: x86: tc1100-wmi: world-writable sysfs wireless and jogdial files
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Vasiliy Kulikov <[email protected]>
commit 8a6a142c1286797978e4db266d22875a5f424897 upstream.
Don't allow everybody to change WMI settings.
--- drivers/platform/x86/tc1100-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/platform/x86/tc1100-wmi.c +1 -1
@@ -177,7 +177,7 @@ set_bool_##value(struct device *dev, strreturn -EINVAL ; \return count; \ } \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \ +static DEVICE_ATTR(value, S_IRUGO | S_IWUSR, \ show_bool_##value, set_bool_##value);show_set_bool (wireless,TC1100_INSTANCE_WIRELESS );
PATCH 50/68 genirq: Disable the SHIRQ_DEBUG call in request_threaded_irq for now
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Thomas Gleixner <[email protected]>
commit 6d83f94db95cfe65d2a6359cccdf61cf087c2598 upstream.
With CONFIG_SHIRQ_DEBUG=y we call a newly installed interrupt handler in request_threaded_irq().
The original implementation (commit a304e1b8) called the handler _BEFORE_ it was installed, but that caused problems with handlers calling disable_irq_nosync(). See commit 377bf1e4.
It's braindead in the first place to call disable_irq_nosync in shared handlers, but ....
Moving this call after we installed the handler looks innocent, but it is very subtle broken on SMP.
Interrupt handlers rely on the fact, that the irq core prevents reentrancy.
Now this debug call violates that promise because we run the handler w/o the IRQ_INPROGRESS protection - which we cannot apply here because that would result in a possibly forever masked interrupt line.
A concurrent real hardware interrupt on a different CPU results in handler reentrancy and can lead to complete wreckage, which was unfortunately observed in reality and took a fricking long time to debug.
Leave the code here for now. We want this debug feature, but that's not easy to fix. We really should get rid of those disable_irq_nosync() abusers and remove that function completely.
--- kernel/irq/manage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/irq/manage.c +1 -1
@@ -1079,7 +1079,7 @@ int request_threaded_irq(unsigned int irif (retval)kfree (action); -#ifdef CONFIG_DEBUG_SHIRQ +#ifdef CONFIG_DEBUG_SHIRQ_FIXME if (irqflags &IRQF_SHARED ) {/* * It's a shared IRQ -- the driver ought to be prepared for it
PATCH 51/68 usb: musb: omap2430: fix kernel panic on reboot
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Johan Hovold <[email protected]>
commit b193b412e62b134adf69af286c7e7f8e99259350 upstream.
Cancel idle timer in musb_platform_exit.
The idle timer could trigger after clock had been disabled leading to kernel panic when MUSB_DEVCTL is accessed in musb_do_idle on 2.6.37.
The fault below is no longer triggered on 2.6.38-rc4 (clock is disabled later, and only if compiled as a module, and the offending memory access has moved) but the timer should be cancelled nonetheless.
Rebooting... musb_hdrc musb_hdrc: remove, state 4
usb usb1: USB disconnect, address 1musb_hdrc musb_hdrc: USB bus 1 deregistered
Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa0ab060
Internal error: : 1028 [#1] PREEMPT last sysfs file: /sys/kernel/uevent_seqnum Modules linked in: CPU: 0 Not tainted (2.6.37+ #6) PC is at musb_do_idle+0x24/0x138 LR is at musb_do_idle+0x18/0x138 pc : [<c02377d8>] lr : [<c02377cc>] psr: 80000193
sp : cf2bdd80 ip : cf2bdd80 fp : c048a20c
r10: c048a60c r9 : c048a40c r8 : cf85e110
r7 : cf2bc000 r6 : 40000113 r5 : c0489800 r4 : cf85e110 r3 : 00000004 r2 : 00000006 r1 : fa0ab000 r0 : cf8a7000
Flags: Nzcv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user
Control: 10c5387d Table: 8faac019 DAC: 00000015 Process reboot (pid: 769, stack limit = 0xcf2bc2f0)
Stack: (0xcf2bdd80 to 0xcf2be000)
dd80: 00000103 c0489800 c02377b4 c005fa34 00000555 c0071a8c c04a3858 cf2bdda8
dda0: 00000555 c048a00c cf2bdda8 cf2bdda8 1838beb0 00000103 00000004 cf2bc000
ddc0: 00000001 00000001 c04896c8 0000000a 00000000 c005ac14 00000001 c003f32c
dde0: 00000000 00000025 00000000 cf2bc000 00000002 00000001 cf2bc000 00000000
de00: 00000001 c005ad08 cf2bc000 c002e07c c03ec039 ffffffff fa200000 c0033608
de20: 00000001 00000000 cf852c14 cf81f200 c045b714 c045b708 cf2bc000 c04a37e8
de40: c0033c04 cf2bc000 00000000 00000001 cf2bde68 cf2bde68 c01c3abc c004f7d8
de60: 60000013 ffffffff c0033c04 00000000 01234567 fee1dead 00000000 c006627c
de80: 00000001 c00662c8 28121969 c00663ec cfa38c40 cf9f6a00 cf2bded0 cf9f6a0c
dea0: 00000000 cf92f000 00008914 c02cd284 c04a55c8 c028b398 c00715c0 becf24a8
dec0: 30687465 00000000 00000000 00000000 00000002 1301a8c0 00000000 00000000
dee0: 00000002 1301a8c0 00000000 00000000 c0450494 cf527920 00011f10 cf2bdf08
df00: 00011f10 cf2bdf10 00011f10 cf2bdf18 c00f0b44 c004f7e8 cf2bdf18 cf2bdf18
df20: 00011f10 cf2bdf30 00011f10 cf2bdf38 cf401300 cf486100 00000008 c00d2b28
df40: 00011f10 cf401300 00200200 c00d3388 00011f10 cfb63a88 cfb63a80 c00c2f08
df60: 00000000 00000000 cfb63a80 00000000 cf0a3480 00000006 c0033c04 cfb63a80
df80: 00000000 c00c0104 00000003 cf0a3480 cfb63a80 00000000 00000001 00000004
dfa0: 00000058 c0033a80 00000000 00000001 fee1dead 28121969 01234567 00000000
dfc0: 00000000 00000001 00000004 00000058 00000001 00000001 00000000 00000001
dfe0: 4024d200 becf2cb0 00009210 4024d218 60000010 fee1dead 00000000 00000000 [<c02377d8>] (musb_do_idle+0x24/0x138) from [<c005fa34>] (run_timer_softirq+0x1a8/0x26) [<c005fa34>] (run_timer_softirq+0x1a8/0x26c) from [<c005ac14>] (__do_softirq+0x88/0x13) [<c005ac14>] (__do_softirq+0x88/0x138) from [<c005ad08>] (irq_exit+0x44/0x98) [<c005ad08>] (irq_exit+0x44/0x98) from [<c002e07c>] (asm_do_IRQ+0x7c/0xa0) [<c002e07c>] (asm_do_IRQ+0x7c/0xa0) from [<c0033608>] (__irq_svc+0x48/0xa8)
Exception stack(0xcf2bde20 to 0xcf2bde68)
de20: 00000001 00000000 cf852c14 cf81f200 c045b714 c045b708 cf2bc000 c04a37e8
de40: c0033c04 cf2bc000 00000000 00000001 cf2bde68 cf2bde68 c01c3abc c004f7d8
de60: 60000013 ffffffff
[<c0033608>] (__irq_svc+0x48/0xa8) from [<c004f7d8>] (sub_preempt_count+0x0/0xb8)
Code: ebf86030 e5940098 e594108c e5902010 (e5d13060) ---[ end trace 3689c0d808f9bf7c ]--- Kernel panic - not syncing: Fatal exception in interrupt
--- drivers/usb/musb/omap2430.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/musb/omap2430.c +1 -0
@@ -309,6 +309,7 @@ static int musb_platform_resume(struct mint musb_platform_exit (struct musb *musb) { +del_timer_sync (&musb_idle_timer);omap_vbus_power (musb,0 /*off*/ ,1 );
PATCH 52/68 USB: add quirks entry for Keytouch QWERTY Panel
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Alan Stern <[email protected]>
commit 3c18e30f87ac5466bddbb05cf955605efd7db025 upstream.
This patch (as1448) adds a quirks entry for the Keytouch QWERTY Panel firmware, used in the IEC 60945 keyboard. This device crashes during enumeration when the computer asks for its configuration string descriptor.
--- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/core/quirks.c +4 -0
@@ -68,6 +68,10 @@ static const struct usb_device_id usb_qu/* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Keytouch QWERTY Panel keyboard */ + { USB_DEVICE(0x0926, 0x3333), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */ { USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF },
PATCH 53/68 USB: Add Samsung SGH-I500/Android modem ID switch to visor driver
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Maciej Szmigiero <[email protected]>
commit acb52cb1613e1d3c8a8c650717cc51965c60d7d4 upstream.
[USB]Add Samsung SGH-I500/Android modem ID switch to visor driver
Samsung decided to reuse USB ID of its old CDMA phone SGH-I500 for the modem part of some of their Android phones. At least Galaxy Spica is affected.
This modem needs ACM driver and does not work with visor driver which binds the conflicting ID for SGH-I500.
Because SGH-I500 is pretty an old hardware its best to add switch to visor
driver in cause somebody still wants to use that phone with Linux.
Note that this is needed only when using the Android phone as modem, not in USB storage or ADB mode.
--- drivers/usb/serial/visor.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/usb/serial/visor.c +12 -0
@@ -27,6 +27,7 @@#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> +#include <linux/usb/cdc.h> #include "visor.h" /*
@@ -758,6 +759,17 @@ static int visor_probe(struct usb_serialdbg ("%s" , __func__); +/* +* some Samsung Android phones in modem mode have the same ID +* as SPH-I500, but they are ACM devices, so dont bind to them +*/ +if (id->idVendor ==SAMSUNG_VENDOR_ID && + id->idProduct ==SAMSUNG_SPH_I500_ID && + serial->dev->descriptor.bDeviceClass ==USB_CLASS_COMM && + serial->dev->descriptor.bDeviceSubClass == +USB_CDC_SUBCLASS_ACM ) +return -ENODEV ; +if (serial->dev->actconfig->desc.bConfigurationValue !=1 ) {dev_err (&serial->dev->dev,"active config #%d != 1 ??\n" , serial->dev->actconfig->desc.bConfigurationValue);
PATCH 54/68 USB: Add quirk for Samsung Android phone modem
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Maciej Szmigiero <[email protected]>
commit 72a012ce0a02c6c616676a24b40ff81d1aaeafda upstream.
My Galaxy Spica needs this quirk when in modem mode, otherwise it causes endless USB bus resets and is unusable in this mode.
Unfortunately Samsung decided to reuse ID of its old CDMA phone SGH-I500 for the modem part.
That's why in addition to this patch the visor driver must be prevented from binding to SPH-I500 ID, so ACM driver can do that.
--- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/core/quirks.c +4 -0
@@ -48,6 +48,10 @@ static const struct usb_device_id usb_qu { USB_DEVICE(0x04b4, 0x0526), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Samsung Android phone modem - ID conflict with SPH-I500 */ + { USB_DEVICE(0x04e8, 0x6601), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Roland SC-8820 */ { USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },
PATCH 55/68 p54pci: update receive dma buffers before and after processing
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Christian Lamparter <[email protected]>
commit 0bf719dfdecc5552155cbec78e49fa06e531e35c upstream.
Documentation/DMA-API-HOWTO.txt states:
"DMA transfers need to be synced properly in order for the cpu and device to see the most uptodate and correct copy of the DMA buffer."
--- drivers/net/wireless/p54/p54pci.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/net/wireless/p54/p54pci.c +9 -5
@@ -198,6 +198,7 @@ static void p54p_check_rx_ring(struct iewhile (i != idx) {u16 len;struct sk_buff *skb; +dma_addr_t dma_addr; desc = &ring[i]; len =le16_to_cpu (desc->len); skb = rx_buf[i];
@@ -215,17 +216,20 @@ static void p54p_check_rx_ring(struct ie len = priv->common.rx_mtu; } + dma_addr =le32_to_cpu (desc->host_addr); +pci_dma_sync_single_for_cpu (priv->pdev, dma_addr, + priv->common.rx_mtu +32 ,PCI_DMA_FROMDEVICE );skb_put (skb, len);if (p54_rx (dev, skb)) { -pci_unmap_single (priv->pdev, -le32_to_cpu (desc->host_addr), - priv->common.rx_mtu +32 , -PCI_DMA_FROMDEVICE ); +pci_unmap_single (priv->pdev, dma_addr, + priv->common.rx_mtu +32 ,PCI_DMA_FROMDEVICE ); rx_buf[i] =NULL ; - desc->host_addr =0 ; + desc->host_addr =cpu_to_le32 (0 ); }else {skb_trim (skb,0 ); +pci_dma_sync_single_for_device (priv->pdev, dma_addr, + priv->common.rx_mtu +32 ,PCI_DMA_FROMDEVICE ); desc->len =cpu_to_le16 (priv->common.rx_mtu +32 ); }
PATCH 56/68 sierra: add new ID for Airprime/Sierra USB IP modem
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Jon Thomas <[email protected]>
commit e1dc5157c574e7249dc1cd072fde2e48b3011533 upstream.
I picked up a new Sierra usb 308 (At&t Shockwave) on 2/2011 and the vendor code is 0x0f3d
Looking up vendor and product id's I see:
0f3d Airprime, Incorporated
0112 CDMA 1xEVDO PC Card, PC 5220
Sierra and Airprime are somehow related and I'm guessing the At&t usb 308 might be have some common hardware with the AirPrime SL809x.
--- drivers/usb/serial/sierra.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/serial/sierra.c +3 -0
@@ -266,6 +266,9 @@ static struct usb_device_id id_table [] { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, + { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, { } };
PATCH 57/68 staging: usbip: vhci: update reference count for usb_device
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Max Vozeler <[email protected]>
commit 7606ee8aa33287dd3e6eb44c78541b87a413a325 upstream.
This fixes an oops observed when reading status during removal of a device:
[ 1706.648285] general protection fault: 0000 [#1] SMP [ 1706.648294] last sysfs file: /sys/devices/platform/vhci_hcd/status [ 1706.648297] CPU 1 [ 1706.648300] Modules linked in: binfmt_misc microcode fuse loop vhci_hcd(N) usbip(N) usbcore usbip_common_mod(N) rtc_core rtc_lib joydev dm_mirror dm_region_hash dm_log linear dm_snapshot xennet dm_mod ext3 mbcache jbd processor thermal_sys hwmon xenblk cdrom [ 1706.648324] Supported: Yes [ 1706.648327] Pid: 10422, comm: usbip Tainted: G N 2.6.32.12-0.7-xen #1 [ 1706.648330] RIP: e030:[<ffffffff801b10d5>] [<ffffffff801b10d5>] strnlen+0x5/0x40 [ 1706.648340] RSP: e02b:ffff8800a994dd30 EFLAGS: 00010286 [ 1706.648343] RAX: ffffffff80481ec1 RBX: 0000000000000000 RCX: 0000000000000002 [ 1706.648347] RDX: 00200d1d4f1c001c RSI: ffffffffffffffff RDI: 00200d1d4f1c001c [ 1706.648350] RBP: ffff880129a1c0aa R08: ffffffffa01901c4 R09: 0000000000000006 [ 1706.648353] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8800a9a1c0ab [ 1706.648357] R13: 00200d1d4f1c001c R14: 00000000ffffffff R15: ffff880129a1c0aa [ 1706.648363] FS: 00007f2f2e9ca700(0000) GS:ffff880001018000(0000) knlGS:0000000000000000 [ 1706.648367] CS: e033 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1706.648370] CR2: 000000000071b048 CR3: 00000000b4b68000 CR4: 0000000000002660 [ 1706.648374] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1706.648378] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 1706.648381] Process usbip (pid: 10422, threadinfo ffff8800a994c000, task ffff88007b170200) [ 1706.648385] Stack: [ 1706.648387] ffffffff801b28c9 0000000000000002 ffffffffa01901c4 ffff8800a9a1c0ab [ 1706.648391] <0> ffffffffa01901c6 ffff8800a994de08 ffffffff801b339b 0000000000000004 [ 1706.648397] <0> 0000000affffffff ffffffffffffffff 00000000000067c0 0000000000000000 [ 1706.648404] Call Trace: [ 1706.648413] [<ffffffff801b28c9>] string+0x39/0xe0 [ 1706.648419] [<ffffffff801b339b>] vsnprintf+0x1eb/0x620 [ 1706.648423] [<ffffffff801b3813>] sprintf+0x43/0x50 [ 1706.648429] [<ffffffffa018d719>] show_status+0x1b9/0x220 [vhci_hcd] [ 1706.648438] [<ffffffff8024a2b7>] dev_attr_show+0x27/0x60 [ 1706.648445] [<ffffffff80144821>] sysfs_read_file+0x101/0x1d0 [ 1706.648451] [<ffffffff800da4a7>] vfs_read+0xc7/0x130 [ 1706.648457] [<ffffffff800da613>] sys_read+0x53/0xa0 [ 1706.648462] [<ffffffff80007458>] system_call_fastpath+0x16/0x1b [ 1706.648468] [<00007f2f2de40f30>] 0x7f2f2de40f30 [ 1706.648470] Code: 66 0f 1f 44 00 00 48 83 c2 01 80 3a 00 75 f7 48 89 d0 48 29 f8 f3 c3 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 48 85 f6 74 29 <80> 3f 00 74 24 48 8d 56 ff 48 89 f8 eb 0e 0f 1f 44 00 00 48 83 [ 1706.648507] RIP [<ffffffff801b10d5>] strnlen+0x5/0x40 [ 1706.648511] RSP <ffff8800a994dd30> [ 1706.649575] ---[ end trace b4eb72bf2e149593 ]---
--- drivers/staging/usbip/vhci_hcd.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/staging/usbip/vhci_hcd.c +10 -3
@@ -606,7 +606,9 @@ static int vhci_urb_enqueue(struct usb_hdev_info (dev,"SetAddress Request (%d) to port %d\n" , ctrlreq->wValue, vdev->rhport); - vdev->udev = urb->dev; +if (vdev->udev) +usb_put_dev (vdev->udev); + vdev->udev =usb_get_dev (urb->dev);spin_lock (&vdev->ud.lock); vdev->ud.status =VDEV_ST_USED ;
@@ -626,8 +628,9 @@ static int vhci_urb_enqueue(struct usb_h"Get_Descriptor to device 0 " "(get max pipe size)\n"); -/* FIXME: reference count? (usb_get_dev()) */ - vdev->udev = urb->dev; +if (vdev->udev) +usb_put_dev (vdev->udev); + vdev->udev =usb_get_dev (urb->dev); goto out;default :
@@ -886,6 +889,10 @@ static void vhci_device_reset(struct usb vdev->speed =0 ; vdev->devid =0 ; +if (vdev->udev) +usb_put_dev (vdev->udev); + vdev->udev =NULL ; + ud->tcp_socket =NULL ; ud->status =VDEV_ST_NULL ;
PATCH 58/68 staging: usbip: vhci: give back URBs from in-flight unlink requests
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Max Vozeler <[email protected]>
commit b92a5e23737172c52656a090977408a80d7f06d1 upstream.
If we never received a RET_UNLINK because the TCP connection broke the pending URBs still need to be unlinked and given back.
Previously processes would be stuck trying to kill the URB even after the device was detached.
--- drivers/staging/usbip/vhci.h | 3 +++ drivers/staging/usbip/vhci_hcd.c | 24 +++++++++++++++++++++++- drivers/staging/usbip/vhci_rx.c | 15 +++++++++------ 3 files changed, 35 insertions(+), 7 deletions(-)
drivers/staging/usbip/vhci.h +3 -0
@@ -119,6 +119,9 @@ void rh_port_disconnect(int rhport);void vhci_rx_loop (struct usbip_task *ut);void vhci_tx_loop (struct usbip_task *ut); +struct urb *pickup_urb_and_free_priv (struct vhci_device *vdev, +__u32 seqnum); +#define hardware (&the_controller->pdev.dev)static inline struct vhci_device *port_to_vdev (__u32 port)
drivers/staging/usbip/vhci_hcd.c +23 -1
@@ -807,7 +807,6 @@ static int vhci_urb_dequeue(struct usb_hreturn 0 ; } -static void vhci_device_unlink_cleanup (struct vhci_device *vdev) {struct vhci_unlink *unlink, *tmp;
@@ -815,11 +814,34 @@ static void vhci_device_unlink_cleanup(sspin_lock (&vdev->priv_lock);list_for_each_entry_safe (unlink, tmp, &vdev->unlink_tx, list) { +usbip_uinfo ("unlink cleanup tx %lu\n" , unlink->unlink_seqnum);list_del (&unlink->list);kfree (unlink); }list_for_each_entry_safe (unlink, tmp, &vdev->unlink_rx, list) { +struct urb *urb; + +/* give back URB of unanswered unlink request */ +usbip_uinfo ("unlink cleanup rx %lu\n" , unlink->unlink_seqnum); + + urb =pickup_urb_and_free_priv (vdev, unlink->unlink_seqnum); +if (!urb) { +usbip_uinfo ("the urb (seqnum %lu) was already given back\n" , + unlink->unlink_seqnum); +list_del (&unlink->list); +kfree (unlink); +continue ; + } + + urb->status = -ENODEV ; + +spin_lock (&the_controller->lock); +usb_hcd_unlink_urb_from_ep (vhci_to_hcd (the_controller), urb); +spin_unlock (&the_controller->lock); + +usb_hcd_giveback_urb (vhci_to_hcd (the_controller), urb, urb->status); +list_del (&unlink->list);kfree (unlink); }
drivers/staging/usbip/vhci_rx.c +9 -6
@@ -21,16 +21,14 @@#include "vhci.h" -/* get URB from transmitted urb queue */ -static struct urb *pickup_urb_and_free_priv (struct vhci_device *vdev, +/* get URB from transmitted urb queue. caller must hold vdev->priv_lock */ +struct urb *pickup_urb_and_free_priv (struct vhci_device *vdev,__u32 seqnum) {struct vhci_priv *priv, *tmp;struct urb *urb =NULL ;int status; -spin_lock (&vdev->priv_lock); -list_for_each_entry_safe (priv, tmp, &vdev->priv_rx, list) {if (priv->seqnum == seqnum) { urb = priv->urb;
@@ -61,8 +59,6 @@ static struct urb *pickup_urb_and_free_p } } -spin_unlock (&vdev->priv_lock); -return urb; }
@@ -72,9 +68,11 @@ static void vhci_recv_ret_submit(structstruct usbip_device *ud = &vdev->ud;struct urb *urb; +spin_lock (&vdev->priv_lock); urb =pickup_urb_and_free_priv (vdev, pdu->base.seqnum); +spin_unlock (&vdev->priv_lock);if (!urb) { usbip_uerr("cannot find a urb of seqnum %u\n",
@@ -159,7 +157,12 @@ static void vhci_recv_ret_unlink(structreturn ; } +spin_lock (&vdev->priv_lock); + urb =pickup_urb_and_free_priv (vdev, unlink->unlink_seqnum); + +spin_unlock (&vdev->priv_lock); +if (!urb) {/* * I get the result of a unlink request. But, it seems that I
PATCH 59/68 staging: usbip: vhci: refuse to enqueue for dead connections
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Max Vozeler <[email protected]>
commit 6d212153a838354078cc7d96f9bb23b7d1fd3d1b upstream.
There can be requests to enqueue URBs while we are shutting down a connection.
--- drivers/staging/usbip/vhci_hcd.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/staging/usbip/vhci_hcd.c +13 -2
@@ -558,6 +558,7 @@ static int vhci_urb_enqueue(struct usb_hstruct device *dev = &urb->dev->dev;int ret =0 ;unsigned long flags; +struct vhci_device *vdev;usbip_dbg_vhci_hc ("enter, usb_hcd %p urb %p mem_flags %d\n" , hcd, urb, mem_flags);
@@ -573,6 +574,18 @@ static int vhci_urb_enqueue(struct usb_hreturn urb->status; } + vdev =port_to_vdev (the_controller->pending_port); + +/* refuse enqueue for dead connection */ +spin_lock (&vdev->ud.lock); +if (vdev->ud.status ==VDEV_ST_NULL || vdev->ud.status ==VDEV_ST_ERROR ) { +usbip_uerr ("enqueue for inactive port %d\n" , vdev->rhport); +spin_unlock (&vdev->ud.lock); +spin_unlock_irqrestore (&the_controller->lock, flags); +return -ENODEV ; + } +spin_unlock (&vdev->ud.lock); + ret =usb_hcd_link_urb_to_ep (hcd, urb);if (ret) goto no_need_unlink;
@@ -591,8 +604,6 @@ static int vhci_urb_enqueue(struct usb_h__u8 type =usb_pipetype (urb->pipe);struct usb_ctrlrequest *ctrlreq = (struct usb_ctrlrequest *) urb->setup_packet; -struct vhci_device *vdev = -port_to_vdev (the_controller->pending_port);if (type !=PIPE_CONTROL || !ctrlreq) {dev_err (dev,"invalid request to devnum 0\n" );
PATCH 60/68 staging: usbip: vhci: use urb->dev->portnum to find port
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Max Vozeler <[email protected]>
commit 01446ef5af4e8802369bf4d257806e24345a9371 upstream.
The access to pending_port was racy when two devices were being attached at the same time.
--- drivers/staging/usbip/vhci.h | 3 --- drivers/staging/usbip/vhci_hcd.c | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-)
drivers/staging/usbip/vhci.h +0 -3
@@ -100,9 +100,6 @@ struct vhci_hcd {* But, the index of this array begins from 0. */ struct vhci_device vdev[VHCI_NPORTS ]; - -/* vhci_device which has not been assiged its address yet */ -int pending_port; };
drivers/staging/usbip/vhci_hcd.c +1 -3
@@ -137,8 +137,6 @@ void rh_port_connect(int rhport, enum us* the_controller->vdev[rhport].ud.status = VDEV_CONNECT; * spin_unlock(&the_controller->vdev[rhport].ud.lock); */ - the_controller->pending_port = rhport; -spin_unlock_irqrestore (&the_controller->lock, flags);usb_hcd_poll_rh_status (vhci_to_hcd (the_controller));
@@ -574,7 +572,7 @@ static int vhci_urb_enqueue(struct usb_hreturn urb->status; } - vdev =port_to_vdev (the_controller->pending_port); + vdev =port_to_vdev (urb->dev->portnum-1 );/* refuse enqueue for dead connection */ spin_lock (&vdev->ud.lock);
PATCH 61/68 epoll: prevent creating circular epoll structures
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Davide Libenzi <[email protected]>
commit 22bacca48a1755f79b7e0f192ddb9fbb7fc6e64e upstream.
In several places, an epoll fd can call another file's ->f_op->poll() method with ep->mtx held. This is in general unsafe, because that other file could itself be an epoll fd that contains the original epoll fd.
The code defends against this possibility in its own ->poll() method using ep_call_nested, but there are several other unsafe calls to ->poll elsewhere that can be made to deadlock. For example, the following simple program causes the call in ep_insert recursively call the original fd's ->poll, leading to deadlock:
#include <unistd.h>
#include <sys/epoll.h>
int main(void) {
int e1, e2, p[2];
struct epoll_event evt = {
.events = EPOLLIN
};
e1 = epoll_create(1);
e2 = epoll_create(2);
pipe(p);
epoll_ctl(e2, EPOLL_CTL_ADD, e1, &evt);
epoll_ctl(e1, EPOLL_CTL_ADD, p[0], &evt);
write(p[1], p, sizeof p);
epoll_ctl(e1, EPOLL_CTL_ADD, e2, &evt);
return 0;}
On insertion, check whether the inserted file is itself a struct epoll, and if so, do a recursive walk to detect whether inserting this file would create a loop of epoll structures, which could lead to deadlock.
--- fs/eventpoll.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+)
fs/eventpoll.c +95 -0
@@ -63,6 +63,13 @@* cleanup path and it is also acquired by eventpoll_release_file() * if a file has been pushed inside an epoll set and it is then * close()d without a previous call toepoll_ctl(EPOLL_CTL_DEL). +* It is also acquired when inserting an epoll fd onto another epoll +* fd. We do this so that we walk the epoll tree and ensure that this +* insertion does not create a cycle of epoll file descriptors, which +* could lead to deadlock. We need a global mutex to prevent two +* simultaneous inserts (A into B and B into A) from racing and +* constructing a cycle without either insert observing that it is +* going to. * It is possible to drop the "ep->mtx" and to use the global * mutex "epmutex" (together with "ep->lock") to have it working, * but having "ep->mtx" will make the interface more scalable.
@@ -227,6 +234,9 @@ static int max_user_watches __read_mostl*/ static DEFINE_MUTEX (epmutex); +/* Used to check for epoll file descriptor inclusion loops */ +static struct nested_calls poll_loop_ncalls; +/* Used for safe wake up implementation */ static struct nested_calls poll_safewake_ncalls;
@@ -1182,6 +1192,62 @@ retry:return res; } +/** +* ep_loop_check_proc - Callback function to be passed to the @ep_call_nested() +* API, to verify that adding an epoll file inside another +* epoll structure, does not violate the constraints, in +* terms of closed loops, or too deep chains (which can +* result in excessive stack usage). +* +* @priv: Pointer to the epoll file to be currently checked. +* @cookie: Original cookie for this call. This is the top-of-the-chain epoll +* data structure pointer. +* @call_nests: Current dept of the @ep_call_nested() call stack. +* +* Returns: Returns zero if adding the epoll @file inside current epoll +* structure @ep does not violate the constraints, or -1 otherwise. +*/ +static int ep_loop_check_proc (void *priv,void *cookie,int call_nests) +{ +int error =0 ; +struct file *file = priv; +struct eventpoll *ep = file->private_data; +struct rb_node *rbp; +struct epitem *epi; + +mutex_lock (&ep->mtx); +for (rbp =rb_first (&ep->rbr); rbp; rbp =rb_next (rbp)) { + epi = rb_entry(rbp, struct epitem, rbn); +if (unlikely (is_file_epoll (epi->ffd.file))) { + error =ep_call_nested (&poll_loop_ncalls,EP_MAX_NESTS , + ep_loop_check_proc, epi->ffd.file, + epi->ffd.file->private_data, current); +if (error !=0 ) +break ; + } + } +mutex_unlock (&ep->mtx); + +return error; +} + +/** +* ep_loop_check - Performs a check to verify that adding an epoll file (@file) +* another epoll file (represented by @ep) does not create +* closed loops or too deep chains. +* +* @ep: Pointer to the epoll private data structure. +* @file: Pointer to the epoll file to be checked. +* +* Returns: Returns zero if adding the epoll @file inside current epoll +* structure @ep does not violate the constraints, or -1 otherwise. +*/ +static int ep_loop_check (struct eventpoll *ep,struct file *file) +{ +return ep_call_nested (&poll_loop_ncalls,EP_MAX_NESTS , + ep_loop_check_proc, file, ep, current); +} +/* * Open an eventpoll file descriptor. */
@@ -1230,6 +1296,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, in struct epoll_event __user *, event) {int error; +int did_lock_epmutex =0 ;struct file *file, *tfile;struct eventpoll *ep;struct epitem *epi;
@@ -1271,6 +1338,25 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, in*/ ep = file->private_data; +/* +* When we insert an epoll file descriptor, inside another epoll file +* descriptor, there is the change of creating closed loops, which are +* better be handled here, than in more critical paths. +* +* We hold epmutex across the loop check and the insert in this case, in +* order to prevent two separate inserts from racing and each doing the +* insert "at the same time" such that ep_loop_check passes on both +* before either one does the insert, thereby creating a cycle. +*/ +if (unlikely (is_file_epoll (tfile) && op ==EPOLL_CTL_ADD )) { +mutex_lock (&epmutex); + did_lock_epmutex =1 ; + error = -ELOOP ; +if (ep_loop_check (ep, tfile) !=0 ) + goto error_tgt_fput; + } + +mutex_lock (&ep->mtx);/*
@@ -1306,6 +1392,9 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, inmutex_unlock (&ep->mtx); error_tgt_fput: +if (unlikely (did_lock_epmutex)) +mutex_unlock (&epmutex); +fput (tfile); error_fput:fput (file);
@@ -1424,6 +1513,12 @@ static int __init eventpoll_init(void) max_user_watches = (((si.totalram - si.totalhigh) /25 ) <<PAGE_SHIFT ) /EP_ITEM_COST ; +/* +* Initialize the structure used to perform epoll file descriptor +* inclusion loops checks. +*/ +ep_nested_calls_init (&poll_loop_ncalls); +/* Initialize the structure used to perform safe poll wait head wake ups */ ep_nested_calls_init (&poll_safewake_ncalls);
PATCH 62/68 ldm: corrupted partition table can cause kernel oops
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Timo Warns <[email protected]>
commit 294f6cf48666825d23c9372ef37631232746e40d upstream.
The kernel automatically evaluates partition tables of storage devices. The code for evaluating LDM partitions (in fs/partitions/ldm.c) contains a bug that causes a kernel oops on certain corrupted LDM partitions. A kernel subsystem seems to crash, because, after the oops, the kernel no longer recognizes newly connected storage devices.
The patch changes ldm_parse_vmdb() to Validate the value of vblk_size.
--- fs/partitions/ldm.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/partitions/ldm.c +5 -0
@@ -251,6 +251,11 @@ static bool ldm_parse_vmdb (const u8 *da } vm->vblk_size =get_unaligned_be32 (data +0x08 ); +if (vm->vblk_size ==0 ) { +ldm_error ("Illegal VBLK size" ); +return false; + } + vm->vblk_offset =get_unaligned_be32 (data +0x0C ); vm->last_vblk_seq =get_unaligned_be32 (data +0x04 );
PATCH 63/68 md: correctly handle probe of an mdp device.
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: NeilBrown <[email protected]>
commit 8f5f02c460b7ca74ce55ce126ce0c1e58a3f923d upstream.
'mdp' devices are md devices with preallocated device numbers for partitions. As such it is possible to mknod and open a partition before opening the whole device.
this causes md_probe() to be called with a device number of a partition, which in-turn calls mddev_find with such a number.
However mddev_find expects the number of a 'whole device' and does the wrong thing with partition numbers.
So add code to mddev_find to remove the 'partition' part of a device number and just work with the 'whole device'.
This patch addresses https://bugzilla.kernel.org/show_bug.cgi?id=28652
--- drivers/md/md.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/md/md.c +3 -0
@@ -305,6 +305,9 @@ static mddev_t * mddev_find(dev_t unit) {mddev_t *mddev, *new =NULL ; +if (unit &&MAJOR (unit) !=MD_MAJOR ) + unit &= ~((1 <<MdpMinorShift)-1 ); + retry:spin_lock (&all_mddevs_lock);
PATCH 64/68 x86 quirk: Fix polarity for IRQ0 pin2 override on SB800 systems
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Andreas Herrmann <[email protected]>
commit 7f74f8f28a2bd9db9404f7d364e2097a0c42cc12 upstream.
On some SB800 systems polarity for IOAPIC pin2 is wrongly specified as low active by BIOS. This caused system hangs after resume from S3 when HPET was used in one-shot mode on such systems because a timer interrupt was missed (HPET signal is high active).
For more details see:
http://marc.info/?l=linux-kernel&m=129623757413868
LKML-Reference: <[email protected]>
--- arch/x86/include/asm/acpi.h | 1 + arch/x86/kernel/acpi/boot.c | 14 ++++++++++---- arch/x86/kernel/early-quirks.c | 16 +++++++--------- 3 files changed, 18 insertions(+), 13 deletions(-)
arch/x86/include/asm/acpi.h +1 -0
@@ -89,6 +89,7 @@ extern int acpi_ht;extern int acpi_pci_disabled;extern int acpi_skip_timer_override;extern int acpi_use_timer_override; +extern int acpi_fix_pin2_polarity;extern u8 acpi_sci_flags;extern int acpi_sci_override_gsi;
arch/x86/kernel/acpi/boot.c +10 -4
@@ -70,6 +70,7 @@ u8 acpi_sci_flags __initdata;int acpi_sci_override_gsi__initdata ;int acpi_skip_timer_override__initdata ;int acpi_use_timer_override__initdata ; +int acpi_fix_pin2_polarity__initdata ;#ifdef CONFIG_X86_LOCAL_APIC static u64 acpi_lapic_addr__initdata =APIC_DEFAULT_PHYS_BASE ;
@@ -360,10 +361,15 @@ acpi_parse_int_src_ovr(struct acpi_subtareturn 0 ; } -if (acpi_skip_timer_override && - intsrc->source_irq ==0 && intsrc->global_irq ==2 ) { -printk (PREFIX "BIOS IRQ0 pin2 override ignored.\n" ); -return 0 ; +if (intsrc->source_irq ==0 && intsrc->global_irq ==2 ) { +if (acpi_skip_timer_override) { +printk (PREFIX "BIOS IRQ0 pin2 override ignored.\n" ); +return 0 ; + } +if (acpi_fix_pin2_polarity && (intsrc->inti_flags &ACPI_MADT_POLARITY_MASK )) { + intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK ; +printk (PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n" ); + } } mp_override_legacy_irq(intsrc->source_irq,
arch/x86/kernel/early-quirks.c +7 -9
@@ -145,15 +145,10 @@ static void __init ati_bugs(int num, intstatic u32 __init ati_sbx00_rev (int num,int slot,int func) { -u32 old, d; +u32 d; - d =read_pci_config (num, slot, func,0x70 ); - old = d; - d &= ~(1 <<8 ); -write_pci_config (num, slot, func,0x70 , d); d =read_pci_config (num, slot, func,0x8 ); d &=0xff ; -write_pci_config (num, slot, func,0x70 , old);return d; }
@@ -162,13 +157,16 @@ static void __init ati_bugs_contd(int nu {u32 d, rev; -if (acpi_use_timer_override) -return ; - rev =ati_sbx00_rev (num, slot, func); +if (rev >=0x40 ) + acpi_fix_pin2_polarity =1 ; +if (rev >0x13 )return ; +if (acpi_use_timer_override) +return ; +/* check for IRQ0 interrupt swap */ d =read_pci_config (num, slot, func,0x64 );if (!(d & (1 <<14 )))
PATCH 65/68 xhci: Avoid BUG() in interrupt context
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Paul Zimmerman <[email protected]>
commit 68e41c5d032668e2905404afbef75bc58be179d6 upstream.
Change the BUGs in xhci_find_new_dequeue_state() to WARN_ONs, to avoid bringing down the box if one of them is hit
This patch should be queued for stable kernels back to 2.6.31.
--- drivers/usb/host/xhci-ring.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/usb/host/xhci-ring.c +9 -4
@@ -391,8 +391,11 @@ void xhci_find_new_dequeue_state(struct state->new_deq_seg =find_trb_seg (cur_td->start_seg, dev->eps[ep_index].stopped_trb, &state->new_cycle_state); -if (!state->new_deq_seg) -BUG (); +if (!state->new_deq_seg) { +WARN_ON (1 ); +return ; + } +/* Dig out the cycle state saved by the xHC during the stop ep cmd */ xhci_dbg (xhci,"Finding endpoint context\n" ); ep_ctx =xhci_get_ep_ctx (xhci, dev->out_ctx, ep_index);
@@ -403,8 +406,10 @@ void xhci_find_new_dequeue_state(struct state->new_deq_seg =find_trb_seg (state->new_deq_seg, state->new_deq_ptr, &state->new_cycle_state); -if (!state->new_deq_seg) -BUG (); +if (!state->new_deq_seg) { +WARN_ON (1 ); +return ; + } trb = &state->new_deq_ptr->generic; if ((trb->field[3] & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK) &&
PATCH 66/68 xhci: Clarify some expressions in the TRB math
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Paul Zimmerman <[email protected]>
commit a2490187011cc2263117626615a581927d19f1d3 upstream.
This makes it easier to spot some problems, which will be fixed by the next patch in the series. Also change dev_dbg to dev_err in check_trb_math(), so any math errors will be visible even when running with debug disabled.
Note: This patch changes the expressions containing "((1 << TRB_MAX_BUFF_SHIFT) - 1)" to use the equivalent "(TRB_MAX_BUFF_SIZE - 1)". No change in behavior is intended for those expressions.
This patch should be queued for stable kernels back to 2.6.31.
--- drivers/usb/host/xhci-ring.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
drivers/usb/host/xhci-ring.c +9 -10
@@ -1490,7 +1490,7 @@ static unsigned int count_sg_trbs_needed/* Scatter gather list entries may cross 64KB boundaries */ running_total =TRB_MAX_BUFF_SIZE - - (sg_dma_address (sg) & ((1 <<TRB_MAX_BUFF_SHIFT ) -1 )); + (sg_dma_address (sg) & (TRB_MAX_BUFF_SIZE -1 ));if (running_total !=0 ) num_trbs++;
@@ -1520,11 +1520,11 @@ static unsigned int count_sg_trbs_neededstatic void check_trb_math (struct urb *urb,int num_trbs,int running_total) {if (num_trbs !=0 ) -dev_dbg (&urb->dev->dev,"%s - ep %#x - Miscalculated number of " +dev_err (&urb->dev->dev,"%s - ep %#x - Miscalculated number of " "TRBs, %d left\n" , __func__, urb->ep->desc.bEndpointAddress, num_trbs);if (running_total != urb->transfer_buffer_length) - dev_dbg(&urb->dev->dev, "%s - ep %#x - Miscalculated tx length, " + dev_err(&urb->dev->dev, "%s - ep %#x - Miscalculated tx length, " "queued %#x (%d), asked for %#x (%d)\n", __func__, urb->ep->desc.bEndpointAddress,
@@ -1631,8 +1631,7 @@ static int queue_bulk_sg_tx(struct xhci_ sg = urb->sg->sg; addr = (u64 )sg_dma_address (sg); this_sg_len =sg_dma_len (sg); - trb_buff_len =TRB_MAX_BUFF_SIZE - - (addr & ((1 <<TRB_MAX_BUFF_SHIFT ) -1 )); + trb_buff_len =TRB_MAX_BUFF_SIZE - (addr & (TRB_MAX_BUFF_SIZE -1 )); trb_buff_len =min_t (int, trb_buff_len, this_sg_len);if (trb_buff_len > urb->transfer_buffer_length) trb_buff_len = urb->transfer_buffer_length;
@@ -1667,7 +1666,7 @@ static int queue_bulk_sg_tx(struct xhci_ (unsigned int ) (addr +TRB_MAX_BUFF_SIZE ) & ~(TRB_MAX_BUFF_SIZE -1 ), (unsigned int) addr + trb_buff_len);if (TRB_MAX_BUFF_SIZE - - (addr & ((1 <<TRB_MAX_BUFF_SHIFT ) -1 )) < trb_buff_len) { + (addr & (TRB_MAX_BUFF_SIZE -1 )) < trb_buff_len) {xhci_warn (xhci,"WARN: sg dma xfer crosses 64KB boundaries!\n" ); xhci_dbg(xhci, "Next boundary at %#x, end dma = %#x\n", (unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1),
@@ -1705,7 +1704,7 @@ static int queue_bulk_sg_tx(struct xhci_ } trb_buff_len =TRB_MAX_BUFF_SIZE - - (addr & ((1 <<TRB_MAX_BUFF_SHIFT ) -1 )); + (addr & (TRB_MAX_BUFF_SIZE -1 )); trb_buff_len =min_t (int, trb_buff_len, this_sg_len);if (running_total + trb_buff_len > urb->transfer_buffer_length) trb_buff_len =
@@ -1740,7 +1739,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd * num_trbs =0 ;/* How much data is (potentially) left before the 64KB boundary? */ running_total =TRB_MAX_BUFF_SIZE - - (urb->transfer_dma & ((1 <<TRB_MAX_BUFF_SHIFT ) -1 )); + (urb->transfer_dma & (TRB_MAX_BUFF_SIZE -1 ));/* If there's some data on this 64KB chunk, or we have to send a * zero-length transfer, we need at least one TRB
@@ -1779,8 +1778,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd */* How much data is in the first TRB? */ addr = (u64 ) urb->transfer_dma; trb_buff_len =TRB_MAX_BUFF_SIZE - - (urb->transfer_dma & ((1 <<TRB_MAX_BUFF_SHIFT ) -1 )); -if (urb->transfer_buffer_length < trb_buff_len) + (urb->transfer_dma & (TRB_MAX_BUFF_SIZE -1 )); +if (trb_buff_len > urb->transfer_buffer_length) trb_buff_len = urb->transfer_buffer_length; first_trb = true;
PATCH 67/68 xhci: Fix errors in the running total calculations in the TRB math
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Paul Zimmerman <[email protected]>
commit 5807795bd4dececdf553719cc02869e633395787 upstream.
Calculations like
running_total = TRB_MAX_BUFF_SIZE - (sg_dma_address(sg) & (TRB_MAX_BUFF_SIZE - 1)); if (running_total != 0) num_trbs++;
are incorrect, because running_total can never be zero, so the if() expression will never be true. I think the intention was that running_total be in the range of 0 to TRB_MAX_BUFF_SIZE-1, not 1 to TRB_MAX_BUFF_SIZE. So adding a
running_total &= TRB_MAX_BUFF_SIZE - 1;
fixes the problem.
This patch should be queued for stable kernels back to 2.6.31.
--- drivers/usb/host/xhci-ring.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/host/xhci-ring.c +2 -0
@@ -1491,6 +1491,7 @@ static unsigned int count_sg_trbs_needed/* Scatter gather list entries may cross 64KB boundaries */ running_total =TRB_MAX_BUFF_SIZE - (sg_dma_address (sg) & (TRB_MAX_BUFF_SIZE -1 )); + running_total &=TRB_MAX_BUFF_SIZE -1 ;if (running_total !=0 ) num_trbs++;
@@ -1740,6 +1741,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd */* How much data is (potentially) left before the 64KB boundary? */ running_total =TRB_MAX_BUFF_SIZE - (urb->transfer_dma & (TRB_MAX_BUFF_SIZE -1 )); + running_total &=TRB_MAX_BUFF_SIZE -1 ;/* If there's some data on this 64KB chunk, or we have to send a * zero-length transfer, we need at least one TRB
PATCH 68/68 xhci: Fix an error in count_sg_trbs_needed()
In reply to Greg KH2.6.32-longterm review patch. If anyone has any objections, please let us know.
------------------
From: Paul Zimmerman <[email protected]>
commit bcd2fde05341cef0052e49566ec88b406a521cf3 upstream.
The expression
while (running_total < sg_dma_len(sg))
does not take into account that the remaining data length can be less than sg_dma_len(sg). In that case, running_total can end up being greater than the total data length, so an extra TRB is counted. Changing the expression to
while (running_total < sg_dma_len(sg) && running_total < temp)
fixes that.
This patch should be queued for stable kernels back to 2.6.31.
--- drivers/usb/host/xhci-ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/xhci-ring.c +1 -1
@@ -1496,7 +1496,7 @@ static unsigned int count_sg_trbs_needed num_trbs++;/* How many more 64KB chunks to transfer, how many more TRBs? */ -while (running_total <sg_dma_len (sg)) { +while (running_total <sg_dma_len (sg) && running_total < temp) { num_trbs++; running_total +=TRB_MAX_BUFF_SIZE ; }