I'm announcing the release of the 3.2.93 kernel. All users of the 3.2 kernel series should upgrade. The updated 3.2.y git tree can be found at: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-3.2.y and can be browsed at the normal kernel.org git web browser: https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git The diff from 3.2.92 is attached to this message. Ben. ------------ Makefile | 2 +- arch/alpha/kernel/osf_sys.c | 6 +- arch/mips/include/asm/kprobes.h | 3 +- arch/mips/kernel/entry.S | 3 + arch/powerpc/include/asm/page.h | 12 +++ arch/powerpc/kernel/kprobes.c | 12 +++ arch/powerpc/kernel/setup_64.c | 25 ++++++ arch/x86/kvm/mmu.c | 7 +- arch/x86/kvm/mmu.h | 1 + arch/x86/kvm/x86.c | 53 ++++++++----- crypto/gcm.c | 6 +- drivers/ata/ahci.c | 38 +++++++++ drivers/char/mem.c | 5 ++ drivers/dma/ep93xx_dma.c | 2 + drivers/gpu/drm/radeon/radeon_combios.c | 7 ++ drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 2 + drivers/i2c/busses/i2c-tiny-usb.c | 25 +++++- drivers/input/serio/i8042-x86ia64io.h | 7 ++ drivers/media/rc/ir-raw.c | 13 ++-- drivers/media/video/videobuf2-core.c | 4 +- drivers/net/ethernet/8390/ax88796.c | 7 +- drivers/net/ethernet/ethoc.c | 3 +- drivers/net/irda/irda-usb.c | 2 +- drivers/net/phy/marvell.c | 68 ++++++++-------- drivers/of/fdt.c | 2 + drivers/scsi/qla2xxx/qla_os.c | 8 +- drivers/staging/gma500/psb_intel_lvds.c | 18 +++-- drivers/staging/usbip/vhci_hcd.c | 11 ++- drivers/usb/core/devio.c | 4 +- drivers/usb/core/hcd.c | 4 +- drivers/usb/core/hub.c | 28 +++++-- drivers/usb/gadget/dummy_hcd.c | 6 +- drivers/usb/gadget/f_mass_storage.c | 13 +++- drivers/usb/host/r8a66597-hcd.c | 6 +- drivers/usb/host/xhci-hub.c | 37 +++++++++ drivers/usb/host/xhci-mem.c | 2 +- drivers/usb/host/xhci-pci.c | 16 +++- drivers/usb/host/xhci-ring.c | 37 +++++---- drivers/usb/host/xhci.h | 3 + drivers/usb/misc/iowarrior.c | 2 +- drivers/usb/musb/tusb6010_omap.c | 13 +++- drivers/usb/serial/ftdi_sio.c | 2 +- drivers/usb/serial/io_ti.c | 5 +- drivers/usb/serial/ir-usb.c | 21 ++--- drivers/usb/serial/mct_u232.c | 2 +- drivers/usb/storage/ene_ub6250.c | 90 +++++++++++++--------- drivers/uwb/i1480/dfu/usb.c | 5 +- drivers/watchdog/pcwd_usb.c | 3 + drivers/xen/biomerge.c | 3 +- fs/autofs4/dev-ioctl.c | 2 +- fs/configfs/symlink.c | 3 +- fs/ext4/extents.c | 2 + fs/ext4/inode.c | 31 ++++++-- fs/partitions/check.c | 4 +- fs/proc/array.c | 2 +- fs/proc/base.c | 12 +-- fs/proc/namespaces.c | 4 +- fs/ufs/inode.c | 5 +- fs/ufs/super.c | 18 +++++ fs/ufs/truncate.c | 6 -- fs/ufs/util.h | 10 ++- include/linux/kprobes.h | 4 +- include/linux/ptrace.h | 24 +++++- include/linux/skbuff.h | 1 + include/linux/usb/ch11.h | 3 + include/net/xfrm.h | 10 --- kernel/events/core.c | 2 +- kernel/futex.c | 2 +- kernel/futex_compat.c | 2 +- kernel/kprobes.c | 2 +- kernel/ptrace.c | 39 ++++++++-- kernel/signal.c | 20 +++-- kernel/time/alarmtimer.c | 12 ++- kernel/trace/trace_kprobe.c | 18 +++-- lib/cmdline.c | 6 +- mm/mempolicy.c | 29 ++++--- mm/migrate.c | 45 +++++------ mm/page_cgroup.c | 3 + mm/process_vm_access.c | 2 +- net/ceph/osdmap.c | 1 + net/core/dev.c | 2 +- net/core/rtnetlink.c | 2 + net/core/skbuff.c | 20 +++-- net/ipv4/af_inet.c | 2 +- net/ipv4/tcp.c | 4 + net/ipv4/tcp_input.c | 11 +-- net/ipv6/addrconf.c | 5 +- net/ipv6/af_inet6.c | 4 +- net/ipv6/xfrm6_mode_ro.c | 2 + net/ipv6/xfrm6_mode_transport.c | 2 + net/key/af_key.c | 19 +++-- net/mac80211/rx.c | 3 +- net/netfilter/nf_conntrack_netlink.c | 7 +- net/wireless/util.c | 14 +++- net/xfrm/xfrm_policy.c | 51 ++---------- security/commoncap.c | 7 +- security/keys/keyctl.c | 4 +- security/selinux/hooks.c | 5 +- sound/pci/hda/patch_sigmatel.c | 2 + sound/soc/soc-core.c | 5 +- tools/perf/Documentation/perf-probe.txt | 8 +- tools/perf/Documentation/perf-script-perl.txt | 2 +- tools/perf/Documentation/perf-script-python.txt | 23 +++--- .../util/scripting-engines/trace-event-python.c | 2 +- 104 files changed, 793 insertions(+), 391 deletions(-) Al Viro (4): osf_wait4(): fix infoleak fix ufs_isblockset() ufs: set correct ->s_maxsize excessive checks in ufs_write_failed() and ufs_evict_inode() Alan Stern (2): USB: ene_usb6250: fix DMA to the stack USB: xhci: fix lock-inversion problem Alex Deucher (1): drm/radeon: add a quirk for Toshiba Satellite L20-183 Alexander Sverdlin (1): dmaengine: ep93xx: Always start from BASE0 Alexander Tsoy (1): ALSA: hda - apply STAC_9200_DELL_M22 quirk for Dell Latitude D430 Andrew Lunn (1): net: phy: marvell: Limit errata to 88m1101 Anthony Mallet (1): USB: serial: ftdi_sio: fix setting latency for unprivileged users Ben Hutchings (3): ipv6: xfrm: Handle errors reported by xfrm6_find_1stfragopt() net: add kfree_skb_list() Linux 3.2.93 Chris Brandt (2): usb: r8a66597-hcd: decrease timeout usb: r8a66597-hcd: select a different endpoint on timeout Christoph Lameter (1): mm: fix move/migrate_pages() race on task struct Christophe JAILLET (1): vb2: Fix an off by one error in 'vb2_plane_vaddr' Corentin Labbe (1): usb: xhci: ASMedia ASM1042A chipset need shorts TX quirk Dan Carpenter (5): block: fix an error code in add_partition() libceph: NULL deref on crush_decode() error path drm/vmwgfx: Handle vmalloc() failure in vmw_local_fifo_reserve() xfrm: Oops on error in pfkey_msg2xfrm_state() xfrm: NULL dereference on allocation failure Daniel Drake (1): Input: i8042 - add Fujitsu Lifebook AH544 to notimeout list David S. Miller (1): ipv6: Fix leak in ipv6_gso_segment(). Eric Biggers (1): KEYS: fix dereferencing NULL payload with nonzero length Eric Dumazet (2): net: ping: do not abuse udp_poll() net: prevent sign extension in dev_get_stats() Eric W. Biederman (1): signal: Only reschedule timers on signals timers have sent Felipe Balbi (1): usb: host: xhci: simplify irq handler return Gilad Ben-Yossef (1): crypto: gcm - wait for crypto op not signal safe Gleb Natapov (1): KVM: x86: fix use of uninitialized memory as segment descriptor in emulator. Ilya Matveychikov (1): lib/cmdline.c: fix get_options() overflow while parsing ranges Jan Kara (2): ext4: fix data corruption for mmap writes ext4: fix fdatasync(2) after extent manipulation operations Jann Horn (1): ptrace: use fsuid, fsgid, effective creds for fs access checks Johan Hovold (13): net: irda: irda-usb: fix firmware name on big-endian hosts USB: serial: ir-usb: fix big-endian baud-rate debug printk USB: serial: mct_u232: fix big-endian baud-rate handling USB: serial: io_ti: fix div-by-zero in set_termios uwb: fix device quirk on big-endian hosts USB: iowarrior: fix info ioctl on big-endian hosts USB: gadget: dummy_hcd: fix hub-descriptor removable fields USB: usbip: fix nonconforming hub descriptor USB: hub: fix SS hub-descriptor handling USB: hub: fix non-SS hub-descriptor handling USB: hub: fix SS max number of ports of: fdt: add missing allocation-failure check watchdog: pcwd_usb: fix NULL-deref at probe Johannes Thumshirn (1): scsi: qla2xxx: don't disable a not previously enabled PCI device Julius Werner (2): drivers: char: mem: Check for address space wraparound with mmap() drivers: char: mem: Fix wraparound check to allow mappings up to the end Konstantin Khlebnikov (1): ext4: keep existing extra fields when inode expands Linus Torvalds (1): Sanitize 'move_pages()' permission checks Liping Zhang (1): netfilter: ctnetlink: fix incorrect nf_ct_put during hash resize Marcin Nowakowski (1): MIPS: kprobes: flush_insn_slot should flush only if probe initialised Mathias Nyman (2): xhci: workaround for hosts missing CAS bit xhci: apply PME_STUCK_QUIRK and MISSING_CAS quirk for Denverton Max Filippov (1): net: ethoc: enable NAPI before poll may be scheduled Michael Ellerman (1): powerpc/mm: Fix virt_addr_valid() etc. on 64-bit hash Naveen N. Rao (1): powerpc/kprobes: Pause function_graph tracing during jprobes handling NeilBrown (1): autofs: sanity check status reported with AUTOFS_DEV_IOCTL_FAIL Nicholas Bellinger (1): configfs: Fix race between create_link and configfs_rmdir Nicholas Piggin (1): powerpc/64: Initialise thread_info for emergency stacks Patrik Jakobsson (1): drm/gma500/psb: Actually use VBT mode when it is found Paul Burton (1): MIPS: Fix IRQ tracing & lockdep when rescheduling Paul Moore (1): selinux: fix double free in selinux_parse_opts_str() Peter Chen (1): usb: host: xhci-mem: allocate zeroed Scratchpad Buffer Peter Ujfalusi (1): usb: musb: tusb6010_omap: Do not reset the other direction's packet size Radim Krčmář (1): KVM: x86: zero base3 of unusable segments Rajkumar Manoharan (1): mac80211: strictly check mesh address extension mode Roger Pau Monne (1): xen: fix bio vec merging Russell King (1): net: phy: fix marvell phy status reading Sabrina Dubroca (2): xfrm: fix stack access out of bounds with CONFIG_XFRM_SUB_POLICY tracing/kprobes: Allow to create probe with a module name starting with a digit Sasha Levin (2): mm: fix NULL ptr dereference in migrate_pages mm: fix NULL ptr dereference in move_pages Sean Young (1): rc-core: race condition during ir_raw_event_register() Sebastian Reichel (1): i2c: i2c-tiny-usb: fix buffer not being DMA capable SeongJae Park (6): perf probe: Fix examples section of documentation perf script: Fix outdated comment for perf-trace-python perf script: Fix documentation errors perf script python: Fix wrong code snippets in documentation perf script python: Updated trace_unhandled() signature perf script python: Remove dups in documentation examples Serhey Popovych (1): rtnetlink: add IFLA_GROUP to ifla_policy Soheil Hassas Yeganeh (1): tcp: eliminate negative reordering in tcp_clean_rtx_queue Steffen Klassert (1): af_key: Fix slab-out-of-bounds in pfkey_compile_policy. Sui Chen (1): ahci: Acer SA5-271 SSD Not Detected Fix Takashi Iwai (1): ASoC: Fix use-after-free at card unregistration Thinh Nguyen (1): usb: gadget: f_mass_storage: Serialize wake and sleep execution Thomas Gleixner (3): tracing/kprobes: Enforce kprobes teardown after testing alarmtimer: Prevent overflow of relative timers alarmtimer: Rate limit periodic intervals Uwe Kleine-König (1): net: ethernet: ax88796: don't call free_irq without request_irq first Vamsi Krishna Samavedam (1): USB: core: replace %p with %pK Vladis Dronov (1): xfrm: policy: check policy direction value WANG Cong (1): ipv6: avoid unregistering inet6_dev for loopback Wan Ahmad Zainie (1): usb: xhci: apply XHCI_PME_STUCK_QUIRK to Intel Apollo Lake Wanpeng Li (3): KVM: X86: Fix read out-of-bounds vulnerability in kvm pio emulation KVM: cpuid: Fix read/write out-of-bounds vulnerability in cpuid emulation KVM: async_pf: avoid async pf injection when in guest mode Wei Wang (1): tcp: initialize rcv_mss to TCP_MIN_MSS instead of 0 Yu Zhao (1): swap: cond_resched in swap_cgroup_prepare() Yuchung Cheng (1): tcp: avoid fragmenting peculiar skbs in SACK Zhaowei Yuan (1): vb2: fix plane index sanity check in vb2_plane_cookie() -- Ben Hutchings Kids! Bringing about Armageddon can be dangerous. Do not attempt it in your own home. - Terry Pratchett and Neil Gaiman, `Good Omens'
diff --git a/Makefile b/Makefile index 2e85e1716900..ec64e6f97222 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 2 -SUBLEVEL = 92 +SUBLEVEL = 93 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index b9abe5bb437b..13a99b4988a3 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -1026,8 +1026,10 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) return -EFAULT; - err = 0; - err |= put_user(status, ustatus); + err = put_user(status, ustatus); + if (ret < 0) + return err ? err : ret; + err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h index e6ea4d4d7205..c271e278d723 100644 --- a/arch/mips/include/asm/kprobes.h +++ b/arch/mips/include/asm/kprobes.h @@ -40,7 +40,8 @@ typedef union mips_instruction kprobe_opcode_t; #define flush_insn_slot(p) \ do { \ - flush_icache_range((unsigned long)p->addr, \ + if (p->addr) \ + flush_icache_range((unsigned long)p->addr, \ (unsigned long)p->addr + \ (MAX_INSN_SIZE * sizeof(kprobe_opcode_t))); \ } while (0) diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index 37acfa036d44..5fc7a6475126 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -10,6 +10,7 @@ #include <asm/asm.h> #include <asm/asmmacro.h> +#include <asm/irqflags.h> #include <asm/regdef.h> #include <asm/mipsregs.h> #include <asm/stackframe.h> @@ -145,6 +146,7 @@ FEXPORT(restore_partial) # restore partial frame andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS beqz t0, work_notifysig work_resched: + TRACE_IRQS_OFF jal schedule local_irq_disable # make sure need_resched and @@ -172,6 +174,7 @@ FEXPORT(syscall_exit_work_partial) beqz t0, work_pending # trace bit set? local_irq_enable # could let syscall_trace_leave() # call schedule() instead + TRACE_IRQS_ON move a0, sp jal syscall_trace_leave b resume_userspace diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index 5b0bde2f7dbd..516fadd9fdce 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h @@ -118,7 +118,19 @@ extern phys_addr_t kernstart_addr; #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) + +#ifdef CONFIG_PPC_BOOK3S_64 +/* + * On hash the vmalloc and other regions alias to the kernel region when passed + * through __pa(), which virt_to_pfn() uses. That means virt_addr_valid() can + * return true for some vmalloc addresses, which is incorrect. So explicitly + * check that the address is in the kernel region. + */ +#define virt_addr_valid(kaddr) (REGION_ID(kaddr) == KERNEL_REGION_ID && \ + pfn_valid(__pa(kaddr) >> PAGE_SHIFT)) +#else #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) +#endif /* * On Book-E parts we need __va to parse the device tree and we can't diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index bc47352deb1f..fe3f4efcb849 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -32,6 +32,7 @@ #include <linux/module.h> #include <linux/kdebug.h> #include <linux/slab.h> +#include <linux/ftrace.h> #include <asm/cacheflush.h> #include <asm/sstep.h> #include <asm/uaccess.h> @@ -530,6 +531,15 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) regs->gpr[2] = (unsigned long)(((func_descr_t *)jp->entry)->toc); #endif + /* + * jprobes use jprobe_return() which skips the normal return + * path of the function, and this messes up the accounting of the + * function graph tracer. + * + * Pause function graph tracing while performing the jprobe function. + */ + pause_graph_tracing(); + return 1; } @@ -552,6 +562,8 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) * saved regs... */ memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); + /* It's OK to start function graph tracing again */ + unpause_graph_tracing(); preempt_enable_no_resched(); return 1; } diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 2c8890adcef1..50c959b2a664 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -508,6 +508,23 @@ static void __init exc_lvl_early_init(void) #define exc_lvl_early_init() #endif +/* + * Emergency stacks are used for a range of things, from asynchronous + * NMIs (system reset, machine check) to synchronous, process context. + * We set preempt_count to zero, even though that isn't necessarily correct. To + * get the right value we'd need to copy it from the previous thread_info, but + * doing that might fault causing more problems. + * TODO: what to do with accounting? + */ +static void emerg_stack_init_thread_info(struct thread_info *ti, int cpu) +{ + ti->task = NULL; + ti->cpu = cpu; + ti->preempt_count = 0; + ti->local_flags = 0; + ti->flags = 0; +} + /* * Stack space used when we detect a bad kernel stack pointer, and * early in SMP boots before relocation is enabled. @@ -525,12 +542,20 @@ static void __init emergency_stack_init(void) * Since we use these as temporary stacks during secondary CPU * bringup, we need to get at them in real mode. This means they * must also be within the RMO region. + * + * The IRQ stacks allocated elsewhere in this file are zeroed and + * initialized in kernel/irq.c. These are initialized here in order + * to have emergency stacks available as early as possible. */ limit = min(safe_stack_limit(), ppc64_rma_size); for_each_possible_cpu(i) { unsigned long sp; + struct thread_info *ti; sp = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit); + ti = __va(sp); + memset(ti, 0, THREAD_SIZE); + emerg_stack_init_thread_info(ti, i); sp += THREAD_SIZE; paca[i].emergency_sp = __va(sp); } diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 4a949c7f6423..5b2bf2b4acae 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -3011,12 +3011,15 @@ static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn) return kvm_setup_async_pf(vcpu, gva, gfn, &arch); } -static bool can_do_async_pf(struct kvm_vcpu *vcpu) +bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu) { if (unlikely(!irqchip_in_kernel(vcpu->kvm) || kvm_event_needs_reinjection(vcpu))) return false; + if (is_guest_mode(vcpu)) + return false; + return kvm_x86_ops->interrupt_allowed(vcpu); } @@ -3032,7 +3035,7 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn, put_page(pfn_to_page(*pfn)); - if (!prefault && can_do_async_pf(vcpu)) { + if (!prefault && kvm_can_do_async_pf(vcpu)) { trace_kvm_try_async_get_page(gva, gfn); if (kvm_find_async_pf_gfn(vcpu, gfn)) { trace_kvm_async_pf_doublefault(gva, gfn); diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index e374db9af021..943198e63bdd 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -52,6 +52,7 @@ int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]); void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask); int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct); int kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context); +bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu); static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm) { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index d0284b49317b..c8c3c39f5bf7 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4380,16 +4380,20 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt, static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) { - /* TODO: String I/O for in kernel device */ - int r; + int r = 0, i; - if (vcpu->arch.pio.in) - r = kvm_io_bus_read(vcpu->kvm, KVM_PIO_BUS, vcpu->arch.pio.port, - vcpu->arch.pio.size, pd); - else - r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS, - vcpu->arch.pio.port, vcpu->arch.pio.size, - pd); + for (i = 0; i < vcpu->arch.pio.count; i++) { + if (vcpu->arch.pio.in) + r = kvm_io_bus_read(vcpu->kvm, KVM_PIO_BUS, vcpu->arch.pio.port, + vcpu->arch.pio.size, pd); + else + r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS, + vcpu->arch.pio.port, vcpu->arch.pio.size, + pd); + if (r) + break; + pd += vcpu->arch.pio.size; + } return r; } @@ -4403,6 +4407,8 @@ static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt, if (vcpu->arch.pio.count) goto data_avail; + memset(vcpu->arch.pio_data, 0, size * count); + trace_kvm_pio(0, port, size, count); vcpu->arch.pio.port = port; @@ -4605,8 +4611,12 @@ static bool emulator_get_segment(struct x86_emulate_ctxt *ctxt, u16 *selector, kvm_get_segment(emul_to_vcpu(ctxt), &var, seg); *selector = var.selector; - if (var.unusable) + if (var.unusable) { + memset(desc, 0, sizeof(*desc)); + if (base3) + *base3 = 0; return false; + } if (var.g) var.limit >>= 12; @@ -5440,18 +5450,20 @@ int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt) static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i) { struct kvm_cpuid_entry2 *e = &vcpu->arch.cpuid_entries[i]; - int j, nent = vcpu->arch.cpuid_nent; + struct kvm_cpuid_entry2 *ej; + int j = i; + int nent = vcpu->arch.cpuid_nent; e->flags &= ~KVM_CPUID_FLAG_STATE_READ_NEXT; /* when no next entry is found, the current entry[i] is reselected */ - for (j = i + 1; ; j = (j + 1) % nent) { - struct kvm_cpuid_entry2 *ej = &vcpu->arch.cpuid_entries[j]; - if (ej->function == e->function) { - ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT; - return j; - } - } - return 0; /* silence gcc, even though control never reaches here */ + do { + j = (j + 1) % nent; + ej = &vcpu->arch.cpuid_entries[j]; + } while (ej->function != e->function); + + ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT; + + return j; } /* find an entry with matching function, matching index (if needed), and that @@ -6923,8 +6935,7 @@ bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu) if (!(vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED)) return true; else - return !kvm_event_needs_reinjection(vcpu) && - kvm_x86_ops->interrupt_allowed(vcpu); + return kvm_can_do_async_pf(vcpu); } EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_exit); diff --git a/crypto/gcm.c b/crypto/gcm.c index dd3bf30f260b..9f740857f9f9 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -140,10 +140,8 @@ static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key, err = crypto_ablkcipher_encrypt(&data->req); if (err == -EINPROGRESS || err == -EBUSY) { - err = wait_for_completion_interruptible( - &data->result.completion); - if (!err) - err = data->result.err; + wait_for_completion(&data->result.completion); + err = data->result.err; } if (err) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index baeee8324138..93ace9bbd182 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1268,6 +1268,40 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host) {} #endif +/* + * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected + * as DUMMY, or detected but eventually get a "link down" and never get up + * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the + * port_map may hold a value of 0x00. + * + * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports + * and can significantly reduce the occurrence of the problem. + * + * https://bugzilla.kernel.org/show_bug.cgi?id=189471 + */ +static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv, + struct pci_dev *pdev) +{ + static const struct dmi_system_id sysids[] = { + { + .ident = "Acer Switch Alpha 12", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271") + }, + }, + { } + }; + + if (dmi_check_system(sysids)) { + dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n"); + if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) { + hpriv->port_map = 0x7; + hpriv->cap = 0xC734FF02; + } + } +} + static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { unsigned int board_id = ent->driver_data; @@ -1407,6 +1441,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) "online status unreliable, applying workaround\n"); } + + /* Acer SA5-271 workaround modifies private_data */ + acer_sa5_271_workaround(hpriv, pdev); + /* CAP.NP sometimes indicate the index of the last enabled * port, at other times, that of the last possible port, so * determining the maximum port number requires looking at diff --git a/drivers/char/mem.c b/drivers/char/mem.c index b1ac8d419a73..d78365603952 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -322,6 +322,11 @@ static const struct vm_operations_struct mmap_mem_ops = { static int mmap_mem(struct file *file, struct vm_area_struct *vma) { size_t size = vma->vm_end - vma->vm_start; + phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT; + + /* It's illegal to wrap around the end of the physical address space. */ + if (offset + (phys_addr_t)size - 1 < offset) + return -EINVAL; if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) return -EINVAL; diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index b47e2b803faf..e1612b6069eb 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -300,6 +300,8 @@ static int m2p_hw_setup(struct ep93xx_dma_chan *edmac) | M2P_CONTROL_ENABLE; m2p_set_control(edmac, control); + edmac->buffer = 0; + return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 87a677e91927..9ac606fffc0a 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -3406,6 +3406,13 @@ void radeon_combios_asic_init(struct drm_device *dev) rdev->pdev->subsystem_vendor == 0x103c && rdev->pdev->subsystem_device == 0x280a) return; + /* quirk for rs4xx Toshiba Sattellite L20-183 latop to make it resume + * - it hangs on resume inside the dynclk 1 table. + */ + if (rdev->family == CHIP_RS400 && + rdev->pdev->subsystem_vendor == 0x1179 && + rdev->pdev->subsystem_device == 0xff31) + return; /* DYN CLK 1 */ table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index decca8251bfa..ea9358313b3f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -368,6 +368,8 @@ void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes) return fifo_state->static_buffer; else { fifo_state->dynamic_buffer = vmalloc(bytes); + if (!fifo_state->dynamic_buffer) + goto out_err; return fifo_state->dynamic_buffer; } } diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index d03b04002f0d..8c669d7ec42f 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -159,22 +159,39 @@ static int usb_read(struct i2c_adapter *adapter, int cmd, int value, int index, void *data, int len) { struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data; + void *dmadata = kmalloc(len, GFP_KERNEL); + int ret; + + if (!dmadata) + return -ENOMEM; /* do control transfer */ - return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0), + ret = usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0), cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | - USB_DIR_IN, value, index, data, len, 2000); + USB_DIR_IN, value, index, dmadata, len, 2000); + + memcpy(data, dmadata, len); + kfree(dmadata); + return ret; } static int usb_write(struct i2c_adapter *adapter, int cmd, int value, int index, void *data, int len) { struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data; + void *dmadata = kmemdup(data, len, GFP_KERNEL); + int ret; + + if (!dmadata) + return -ENOMEM; /* do control transfer */ - return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0), + ret = usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0), cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, index, data, len, 2000); + value, index, dmadata, len, 2000); + + kfree(dmadata); + return ret; } static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 8941d8ddd357..961e56b6a7c8 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -673,6 +673,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"), }, }, + { + /* Fujitsu UH554 laptop */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"), + }, + }, { } }; diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c index 2e5cd3100b64..3a5a5b60f1c6 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c @@ -225,7 +225,7 @@ void ir_raw_event_handle(struct rc_dev *dev) { unsigned long flags; - if (!dev->raw) + if (!dev->raw || !dev->raw->thread) return; spin_lock_irqsave(&dev->raw->lock, flags); @@ -252,6 +252,7 @@ int ir_raw_event_register(struct rc_dev *dev) { int rc; struct ir_raw_handler *handler; + struct task_struct *thread; if (!dev) return -EINVAL; @@ -269,14 +270,16 @@ int ir_raw_event_register(struct rc_dev *dev) goto out; spin_lock_init(&dev->raw->lock); - dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw, - "rc%ld", dev->devno); + thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%ld", + dev->devno); - if (IS_ERR(dev->raw->thread)) { - rc = PTR_ERR(dev->raw->thread); + if (IS_ERR(thread)) { + rc = PTR_ERR(thread); goto out; } + dev->raw->thread = thread; + mutex_lock(&ir_raw_handler_lock); list_add_tail(&dev->raw->list, &ir_raw_client_list); list_for_each_entry(handler, &ir_raw_handler_list, list) diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 95a3f5e82aef..92dfe2322d96 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -731,7 +731,7 @@ void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no) { struct vb2_queue *q = vb->vb2_queue; - if (plane_no > vb->num_planes) + if (plane_no >= vb->num_planes) return NULL; return call_memop(q, plane_no, vaddr, vb->planes[plane_no].mem_priv); @@ -754,7 +754,7 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no) { struct vb2_queue *q = vb->vb2_queue; - if (plane_no > vb->num_planes) + if (plane_no >= vb->num_planes) return NULL; return call_memop(q, plane_no, cookie, vb->planes[plane_no].mem_priv); diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c index e9f8432f55b4..fdffd122f5cb 100644 --- a/drivers/net/ethernet/8390/ax88796.c +++ b/drivers/net/ethernet/8390/ax88796.c @@ -769,13 +769,13 @@ static int ax_init_dev(struct net_device *dev) ret = ax_mii_init(dev); if (ret) - goto out_irq; + goto err_out; ax_NS8390_init(dev, 0); ret = register_netdev(dev); if (ret) - goto out_irq; + goto err_out; netdev_info(dev, "%dbit, irq %d, %lx, MAC: %pM\n", ei_local->word16 ? 16 : 8, dev->irq, dev->base_addr, @@ -783,9 +783,6 @@ static int ax_init_dev(struct net_device *dev) return 0; - out_irq: - /* cleanup irq */ - free_irq(dev->irq, dev); err_out: return ret; } diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index b3b22f487b41..ba5c4a997190 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -703,6 +703,8 @@ static int ethoc_open(struct net_device *dev) if (ret) return ret; + napi_enable(&priv->napi); + ethoc_init_ring(priv, dev->mem_start); ethoc_reset(priv); @@ -715,7 +717,6 @@ static int ethoc_open(struct net_device *dev) } phy_start(priv->phy); - napi_enable(&priv->napi); if (netif_msg_ifup(priv)) { dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n", diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index d9267cb98a23..6b4f49ed3690 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1083,7 +1083,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self) * are "42101001.sb" or "42101002.sb" */ sprintf(stir421x_fw_name, "4210%4X.sb", - self->usbdev->descriptor.bcdDevice); + le16_to_cpu(self->usbdev->descriptor.bcdDevice)); ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev); if (ret < 0) return ret; diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index e8b9c53c304b..4915d106f94b 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -126,34 +126,6 @@ static int marvell_config_aneg(struct phy_device *phydev) { int err; - /* The Marvell PHY has an errata which requires - * that certain registers get written in order - * to restart autonegotiation */ - err = phy_write(phydev, MII_BMCR, BMCR_RESET); - - if (err < 0) - return err; - - err = phy_write(phydev, 0x1d, 0x1f); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0x200c); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1d, 0x5); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0x100); - if (err < 0) - return err; - err = phy_write(phydev, MII_M1011_PHY_SCR, MII_M1011_PHY_SCR_AUTO_CROSS); if (err < 0) @@ -188,6 +160,42 @@ static int marvell_config_aneg(struct phy_device *phydev) return 0; } +static int m88e1101_config_aneg(struct phy_device *phydev) +{ + int err; + + /* This Marvell PHY has an errata which requires + * that certain registers get written in order + * to restart autonegotiation + */ + err = phy_write(phydev, MII_BMCR, BMCR_RESET); + + if (err < 0) + return err; + + err = phy_write(phydev, 0x1d, 0x1f); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0x200c); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1d, 0x5); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0x100); + if (err < 0) + return err; + + return marvell_config_aneg(phydev); +} + #ifdef CONFIG_OF_MDIO /* * Set and/or override some configuration registers based on the @@ -653,8 +661,6 @@ static int marvell_read_status(struct phy_device *phydev) if (adv < 0) return adv; - lpa &= adv; - if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) phydev->duplex = DUPLEX_FULL; else @@ -724,7 +730,7 @@ static struct phy_driver marvell_drivers[] = { .name = "Marvell 88E1101", .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, - .config_aneg = &marvell_config_aneg, + .config_aneg = &m88e1101_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &marvell_ack_interrupt, .config_intr = &marvell_config_intr, diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index b77808c4daa8..29f121e9345b 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -388,6 +388,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob, /* Allocate memory for the expanded device tree */ mem = (unsigned long) dt_alloc(size + 4, __alignof__(struct device_node)); + if (!mem) + return NULL; memset((void *)mem, 0, size); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 82a5ca64ca71..6cda887fa797 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1999,10 +1999,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (mem_only) { if (pci_enable_device_mem(pdev)) - goto probe_out; + return ret; } else { if (pci_enable_device(pdev)) - goto probe_out; + return ret; } /* This may fail but that's ok */ @@ -2012,7 +2012,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (!ha) { ql_log_pci(ql_log_fatal, pdev, 0x0009, "Unable to allocate memory for ha.\n"); - goto probe_out; + goto disable_device; } ql_dbg_pci(ql_dbg_init, pdev, 0x000a, "Memory allocated for ha=%p.\n", ha); @@ -2433,7 +2433,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) kfree(ha); ha = NULL; -probe_out: +disable_device: pci_disable_device(pdev); return ret; } diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c index 21022e1a977a..8e2afbb73529 100644 --- a/drivers/staging/gma500/psb_intel_lvds.c +++ b/drivers/staging/gma500/psb_intel_lvds.c @@ -792,20 +792,23 @@ void psb_intel_lvds_init(struct drm_device *dev, if (scan->type & DRM_MODE_TYPE_PREFERRED) { mode_dev->panel_fixed_mode = drm_mode_duplicate(dev, scan); + DRM_DEBUG_KMS("Using mode from DDC\n"); goto out; /* FIXME: check for quirks */ } } /* Failed to get EDID, what about VBT? do we need this? */ - if (mode_dev->vbt_mode) + if (dev_priv->lfp_lvds_vbt_mode) { mode_dev->panel_fixed_mode = - drm_mode_duplicate(dev, mode_dev->vbt_mode); + drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); - if (!mode_dev->panel_fixed_mode) - if (dev_priv->lfp_lvds_vbt_mode) - mode_dev->panel_fixed_mode = - drm_mode_duplicate(dev, - dev_priv->lfp_lvds_vbt_mode); + if (mode_dev->panel_fixed_mode) { + mode_dev->panel_fixed_mode->type |= + DRM_MODE_TYPE_PREFERRED; + DRM_DEBUG_KMS("Using mode from VBT\n"); + goto out; + } + } /* * If we didn't get EDID, try checking if the panel is already turned @@ -822,6 +825,7 @@ void psb_intel_lvds_init(struct drm_device *dev, if (mode_dev->panel_fixed_mode) { mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; + DRM_DEBUG_KMS("Using pre-programmed mode\n"); goto out; /* FIXME: check for quirks */ } } diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index 2ee97e2095b0..68f9af85b9cb 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -248,14 +248,19 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) /* See hub_configure in hub.c */ static inline void hub_descriptor(struct usb_hub_descriptor *desc) { + int width; + memset(desc, 0, sizeof(*desc)); desc->bDescriptorType = 0x29; - desc->bDescLength = 9; desc->wHubCharacteristics = (__force __u16) (__constant_cpu_to_le16(0x0001)); + desc->bNbrPorts = VHCI_NPORTS; - desc->u.hs.DeviceRemovable[0] = 0xff; - desc->u.hs.DeviceRemovable[1] = 0xff; + BUILD_BUG_ON(VHCI_NPORTS > USB_MAXCHILDREN); + width = desc->bNbrPorts / 8 + 1; + desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * width; + memset(&desc->u.hs.DeviceRemovable[0], 0, width); + memset(&desc->u.hs.DeviceRemovable[width], 0xff, width); } static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 45d3007cf86e..6f34a265f9ec 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -325,11 +325,11 @@ static void snoop_urb(struct usb_device *udev, if (userurb) { /* Async */ if (when == SUBMIT) - dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " "length %u\n", userurb, ep, t, d, length); else - dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " "actual_length %u status %d\n", userurb, ep, t, d, length, timeout_or_status); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index eb2c3bd28db0..3cedf914bbab 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1563,7 +1563,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) if (retval == 0) retval = -EINPROGRESS; else if (retval != -EIDRM && retval != -EBUSY) - dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n", + dev_dbg(&udev->dev, "hcd_unlink_urb %pK fail %d\n", urb, retval); usb_put_dev(udev); } @@ -1645,7 +1645,7 @@ void usb_hcd_flush_endpoint(struct usb_device *udev, /* kick hcd */ unlink1(hcd, urb, -ESHUTDOWN); dev_dbg (hcd->self.controller, - "shutdown urb %p ep%d%s%s\n", + "shutdown urb %pK ep%d%s%s\n", urb, usb_endpoint_num(&ep->desc), is_in ? "in" : "out", ({ char *s; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d2c7b4eecb2f..7c5946640888 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -177,7 +177,8 @@ static struct usb_hub *hdev_to_hub(struct usb_device *hdev) } /* USB 2.0 spec Section 11.24.4.5 */ -static int get_hub_descriptor(struct usb_device *hdev, void *data) +static int get_hub_descriptor(struct usb_device *hdev, + struct usb_hub_descriptor *desc) { int i, ret, size; unsigned dtype; @@ -193,10 +194,18 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data) for (i = 0; i < 3; i++) { ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, - dtype << 8, 0, data, size, + dtype << 8, 0, desc, size, USB_CTRL_GET_TIMEOUT); - if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) + if (hub_is_superspeed(hdev)) { + if (ret == size) + return ret; + } else if (ret >= USB_DT_HUB_NONVAR_SIZE + 2) { + /* Make sure we have the DeviceRemovable field. */ + size = USB_DT_HUB_NONVAR_SIZE + desc->bNbrPorts / 8 + 1; + if (ret < size) + return -EMSGSIZE; return ret; + } } return -EINVAL; } @@ -1099,6 +1108,7 @@ static int hub_configure(struct usb_hub *hub, unsigned int pipe; int maxp, ret; char *message = "out of memory"; + unsigned maxchild; hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL); if (!hub->buffer) { @@ -1113,7 +1123,7 @@ static int hub_configure(struct usb_hub *hub, } mutex_init(&hub->status_mutex); - hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); + hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL); if (!hub->descriptor) { ret = -ENOMEM; goto fail; @@ -1121,13 +1131,19 @@ static int hub_configure(struct usb_hub *hub, /* Request the entire hub descriptor. * hub->descriptor can handle USB_MAXCHILDREN ports, - * but the hub can/will return fewer bytes here. + * but a (non-SS) hub can/will return fewer bytes here. */ ret = get_hub_descriptor(hdev, hub->descriptor); if (ret < 0) { message = "can't read hub descriptor"; goto fail; - } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) { + } + + maxchild = USB_MAXCHILDREN; + if (hub_is_superspeed(hdev)) + maxchild = min_t(unsigned, maxchild, USB_SS_MAXPORTS); + + if (hub->descriptor->bNbrPorts > maxchild) { message = "hub has too many ports!"; ret = -ENODEV; goto fail; diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 8e0a1bd92a54..03a9222a03b3 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1770,7 +1770,7 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc) desc->wHubCharacteristics = cpu_to_le16(0x0001); desc->bNbrPorts = 1; desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/ - desc->u.ss.DeviceRemovable = 0xffff; + desc->u.ss.DeviceRemovable = 0; } static inline void @@ -1781,8 +1781,8 @@ hub_descriptor (struct usb_hub_descriptor *desc) desc->bDescLength = 9; desc->wHubCharacteristics = cpu_to_le16(0x0001); desc->bNbrPorts = 1; - desc->u.hs.DeviceRemovable[0] = 0xff; - desc->u.hs.DeviceRemovable[1] = 0xff; + desc->u.hs.DeviceRemovable[0] = 0; + desc->u.hs.DeviceRemovable[1] = 0xff; /* PortPwrCtrlMask */ } static int dummy_hub_control ( diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 8d7fb6bfd617..21472b26b33a 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -512,7 +512,11 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) /* Caller must hold fsg->lock */ static void wakeup_thread(struct fsg_common *common) { - smp_wmb(); /* ensure the write of bh->state is complete */ + /* + * Ensure the reading of thread_wakeup_needed + * and the writing of bh->state are completed + */ + smp_mb(); /* Tell the main thread that something has happened */ common->thread_wakeup_needed = 1; if (common->thread_task) @@ -732,7 +736,12 @@ static int sleep_thread(struct fsg_common *common) } __set_current_state(TASK_RUNNING); common->thread_wakeup_needed = 0; - smp_rmb(); /* ensure the latest bh->state is visible */ + + /* + * Ensure the writing of thread_wakeup_needed + * and the reading of bh->state are completed + */ + smp_mb(); return rc; } diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index e84ca1928dbf..fa5482c2ebab 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1274,7 +1274,7 @@ static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td) time = 30; break; default: - time = 300; + time = 50; break; } @@ -1790,6 +1790,7 @@ static void r8a66597_td_timer(unsigned long _r8a66597) pipe = td->pipe; pipe_stop(r8a66597, pipe); + /* Select a different address or endpoint */ new_td = td; do { list_move_tail(&new_td->queue, @@ -1799,7 +1800,8 @@ static void r8a66597_td_timer(unsigned long _r8a66597) new_td = td; break; } - } while (td != new_td && td->address == new_td->address); + } while (td != new_td && td->address == new_td->address && + td->pipe->info.epnum == new_td->pipe->info.epnum); start_transfer(r8a66597, new_td); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 13bb316e832b..d89b72c86b66 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1036,6 +1036,35 @@ int xhci_bus_suspend(struct usb_hcd *hcd) return 0; } +/* + * Workaround for missing Cold Attach Status (CAS) if device re-plugged in S3. + * warm reset a USB3 device stuck in polling or compliance mode after resume. + * See Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8 + */ +static bool xhci_port_missing_cas_quirk(int port_index, + __le32 __iomem **port_array) +{ + u32 portsc; + + portsc = readl(port_array[port_index]); + + /* if any of these are set we are not stuck */ + if (portsc & (PORT_CONNECT | PORT_CAS)) + return false; + + if (((portsc & PORT_PLS_MASK) != XDEV_POLLING) && + ((portsc & PORT_PLS_MASK) != XDEV_COMP_MODE)) + return false; + + /* clear wakeup/change bits, and do a warm port reset */ + portsc &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS); + portsc |= PORT_WR; + writel(portsc, port_array[port_index]); + /* flush write */ + readl(port_array[port_index]); + return true; +} + int xhci_bus_resume(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); @@ -1070,6 +1099,14 @@ int xhci_bus_resume(struct usb_hcd *hcd) int slot_id; temp = xhci_readl(xhci, port_array[port_index]); + + /* warm reset CAS limited ports stuck in polling/compliance */ + if ((xhci->quirks & XHCI_MISSING_CAS) && + (hcd->speed >= HCD_USB3) && + xhci_port_missing_cas_quirk(port_index, port_array)) { + xhci_dbg(xhci, "reset stuck port %d\n", port_index); + continue; + } if (DEV_SUPERSPEED(temp)) temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS); else diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 337b86695dfc..841eb6878e97 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1591,7 +1591,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) if (!xhci->scratchpad) goto fail_sp; - xhci->scratchpad->sp_array = dma_alloc_coherent(dev, + xhci->scratchpad->sp_array = dma_zalloc_coherent(dev, num_sp * sizeof(u64), &xhci->scratchpad->sp_dma, flags); if (!xhci->scratchpad->sp_array) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index fce63553f397..423700bd310d 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -42,6 +42,8 @@ #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f #define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8 #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI 0x1aa8 +#define PCI_DEVICE_ID_INTEL_APL_XHCI 0x5aa8 +#define PCI_DEVICE_ID_INTEL_DNV_XHCI 0x19d0 static const char hcd_name[] = "xhci_hcd"; @@ -138,9 +140,17 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI)) { + pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) { xhci->quirks |= XHCI_PME_STUCK_QUIRK; } + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) + xhci->quirks |= XHCI_MISSING_CAS; + if (pdev->vendor == PCI_VENDOR_ID_ETRON && pdev->device == PCI_DEVICE_ID_ASROCK_P67) { xhci->quirks |= XHCI_RESET_ON_RESUME; @@ -149,6 +159,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) } if (pdev->vendor == PCI_VENDOR_ID_VIA) xhci->quirks |= XHCI_RESET_ON_RESUME; + + if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && + pdev->device == 0x1142) + xhci->quirks |= XHCI_TRUST_TX_LENGTH; } /* diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 35e1b8461bff..74ed2108ea0f 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2642,29 +2642,31 @@ static int xhci_handle_event(struct xhci_hcd *xhci) irqreturn_t xhci_irq(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); - u32 status; union xhci_trb *trb; - u64 temp_64; union xhci_trb *event_ring_deq; + irqreturn_t ret = IRQ_NONE; + unsigned long flags; dma_addr_t deq; + u64 temp_64; + u32 status; - spin_lock(&xhci->lock); + spin_lock_irqsave(&xhci->lock, flags); trb = xhci->event_ring->dequeue; /* Check if the xHC generated the interrupt, or the irq is shared */ status = xhci_readl(xhci, &xhci->op_regs->status); - if (status == 0xffffffff) - goto hw_died; - - if (!(status & STS_EINT)) { - spin_unlock(&xhci->lock); - return IRQ_NONE; + if (status == 0xffffffff) { + ret = IRQ_HANDLED; + goto out; } + + if (!(status & STS_EINT)) + goto out; + if (status & STS_FATAL) { xhci_warn(xhci, "WARNING: Host System Error\n"); xhci_halt(xhci); -hw_died: - spin_unlock(&xhci->lock); - return IRQ_HANDLED; + ret = IRQ_HANDLED; + goto out; } /* @@ -2694,9 +2696,8 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); - spin_unlock(&xhci->lock); - - return IRQ_HANDLED; + ret = IRQ_HANDLED; + goto out; } event_ring_deq = xhci->event_ring->dequeue; @@ -2721,10 +2722,12 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) /* Clear the event handler busy flag (RW1C); event ring is empty. */ temp_64 |= ERST_EHB; xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue); + ret = IRQ_HANDLED; - spin_unlock(&xhci->lock); +out: + spin_unlock_irqrestore(&xhci->lock, flags); - return IRQ_HANDLED; + return ret; } irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 15f58d1367ba..4453f2a3805e 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -280,6 +280,8 @@ struct xhci_op_regs { #define XDEV_U0 (0x0 << 5) #define XDEV_U2 (0x2 << 5) #define XDEV_U3 (0x3 << 5) +#define XDEV_POLLING (0x7 << 5) +#define XDEV_COMP_MODE (0xa << 5) #define XDEV_RESUME (0xf << 5) /* true: port has power (see HCC_PPC) */ #define PORT_POWER (1 << 9) @@ -1499,6 +1501,7 @@ struct xhci_hcd { #define XHCI_SLOW_SUSPEND (1 << 17) #define XHCI_SPURIOUS_WAKEUP (1 << 18) #define XHCI_PME_STUCK_QUIRK (1 << 20) +#define XHCI_MISSING_CAS (1 << 24) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 878a346d743d..097e4ef04592 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -560,7 +560,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, info.revision = le16_to_cpu(dev->udev->descriptor.bcdDevice); /* 0==UNKNOWN, 1==LOW(usb1.1) ,2=FULL(usb1.1), 3=HIGH(usb2.0) */ - info.speed = le16_to_cpu(dev->udev->speed); + info.speed = dev->udev->speed; info.if_num = dev->interface->cur_altsetting->desc.bInterfaceNumber; info.report_size = dev->report_size; diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index b67b4bc596c1..659960b1a98c 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c @@ -237,6 +237,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, u32 dma_remaining; int src_burst, dst_burst; u16 csr; + u32 psize; int ch; s8 dmareq; s8 sync_dev; @@ -408,15 +409,19 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, if (chdat->tx) { /* Send transfer_packet_sz packets at a time */ - musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, - chdat->transfer_packet_sz); + psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET); + psize &= ~0x7ff; + psize |= chdat->transfer_packet_sz; + musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize); musb_writel(ep_conf, TUSB_EP_TX_OFFSET, TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); } else { /* Receive transfer_packet_sz packets at a time */ - musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, - chdat->transfer_packet_sz << 16); + psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET); + psize &= ~(0x7ff << 16); + psize |= (chdat->transfer_packet_sz << 16); + musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize); musb_writel(ep_conf, TUSB_EP_RX_OFFSET, TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c298c7a05842..a42adabce86a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1543,9 +1543,9 @@ static int set_serial_info(struct tty_struct *tty, (new_serial.flags & ASYNC_FLAGS)); priv->custom_divisor = new_serial.custom_divisor; +check_and_exit: write_latency_timer(port); -check_and_exit: if ((old_priv.flags & ASYNC_SPD_MASK) != (priv->flags & ASYNC_SPD_MASK)) { if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index a4177561d09a..86c8efd49583 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2412,8 +2412,11 @@ static void change_port_settings(struct tty_struct *tty, if (!baud) { /* pick a default, any default... */ baud = 9600; - } else + } else { + /* Avoid a zero divisor. */ + baud = min(baud, 461550); tty_encode_baud_rate(tty, baud, baud); + } edge_port->baud_rate = baud; config->wBaudRate = (__u16)((461550L + baud/2) / baud); diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index ccbce4066d04..b0236abe8f16 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -236,6 +236,7 @@ static u8 ir_xbof_change(u8 xbof) static int ir_startup(struct usb_serial *serial) { struct usb_irda_cs_descriptor *irda_desc; + int rates; irda_desc = irda_usb_find_class_desc(serial->dev, 0); if (!irda_desc) { @@ -244,17 +245,19 @@ static int ir_startup(struct usb_serial *serial) return -ENODEV; } + rates = le16_to_cpu(irda_desc->wBaudRate); + dbg("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s", __func__, - (irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_19200) ? " 19200" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_38400) ? " 38400" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_57600) ? " 57600" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_115200) ? " 115200" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_576000) ? " 576000" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_1152000) ? " 1152000" : "", - (irda_desc->wBaudRate & USB_IRDA_BR_4000000) ? " 4000000" : ""); + (rates & USB_IRDA_BR_2400) ? " 2400" : "", + (rates & USB_IRDA_BR_9600) ? " 9600" : "", + (rates & USB_IRDA_BR_19200) ? " 19200" : "", + (rates & USB_IRDA_BR_38400) ? " 38400" : "", + (rates & USB_IRDA_BR_57600) ? " 57600" : "", + (rates & USB_IRDA_BR_115200) ? " 115200" : "", + (rates & USB_IRDA_BR_576000) ? " 576000" : "", + (rates & USB_IRDA_BR_1152000) ? " 1152000" : "", + (rates & USB_IRDA_BR_4000000) ? " 4000000" : ""); switch (irda_desc->bmAdditionalBOFs) { case USB_IRDA_AB_48: diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 801c697148ef..ed8694b1a0f4 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -251,7 +251,7 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, return -ENOMEM; divisor = mct_u232_calculate_baud_rate(serial, value, &speed); - put_unaligned_le32(cpu_to_le32(divisor), buf); + put_unaligned_le32(divisor, buf); rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCT_U232_SET_BAUD_RATE_REQUEST, MCT_U232_SET_REQUEST_TYPE, diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 9fbe742343c6..8f6fa2d2ec0b 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -431,6 +431,10 @@ struct ms_lib_ctrl { #define SD_BLOCK_LEN 9 struct ene_ub6250_info { + + /* I/O bounce buffer */ + u8 *bbuf; + /* for 6250 code */ struct SD_STATUS SD_Status; struct MS_STATUS MS_Status; @@ -478,8 +482,11 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag); static void ene_ub6250_info_destructor(void *extra) { + struct ene_ub6250_info *info = (struct ene_ub6250_info *) extra; + if (!extra) return; + kfree(info->bbuf); } static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg) @@ -843,8 +850,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; + struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; int result; - u8 ExtBuf[4]; u32 bn = PhyBlockAddr * 0x20 + PageNum; /* printk(KERN_INFO "MS --- MS_ReaderReadPage, @@ -887,7 +895,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, bcb->CDB[2] = (unsigned char)(PhyBlockAddr>>16); bcb->CDB[6] = 0x01; - result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -896,9 +904,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr, ExtraDat->status0 = 0x10; /* Not yet,fireware support */ ExtraDat->status1 = 0x00; /* Not yet,fireware support */ - ExtraDat->ovrflg = ExtBuf[0]; - ExtraDat->mngflg = ExtBuf[1]; - ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]); + ExtraDat->ovrflg = bbuf[0]; + ExtraDat->mngflg = bbuf[1]; + ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]); return USB_STOR_TRANSPORT_GOOD; } @@ -1324,8 +1332,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, u8 PageNum, struct ms_lib_type_extdat *ExtraDat) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; + struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; int result; - u8 ExtBuf[4]; /* printk("MS_LibReadExtra --- PhyBlock = %x, PageNum = %x\n", PhyBlock, PageNum); */ memset(bcb, 0, sizeof(struct bulk_cb_wrap)); @@ -1340,7 +1349,7 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, bcb->CDB[2] = (unsigned char)(PhyBlock>>16); bcb->CDB[6] = 0x01; - result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -1348,9 +1357,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock, ExtraDat->intr = 0x80; /* Not yet, waiting for fireware support */ ExtraDat->status0 = 0x10; /* Not yet, waiting for fireware support */ ExtraDat->status1 = 0x00; /* Not yet, waiting for fireware support */ - ExtraDat->ovrflg = ExtBuf[0]; - ExtraDat->mngflg = ExtBuf[1]; - ExtraDat->logadr = memstick_logaddr(ExtBuf[2], ExtBuf[3]); + ExtraDat->ovrflg = bbuf[0]; + ExtraDat->mngflg = bbuf[1]; + ExtraDat->logadr = memstick_logaddr(bbuf[2], bbuf[3]); return USB_STOR_TRANSPORT_GOOD; } @@ -1554,9 +1563,9 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st) u16 PhyBlock, newblk, i; u16 LogStart, LogEnde; struct ms_lib_type_extdat extdat; - u8 buf[0x200]; u32 count = 0, index = 0; struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) { ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde); @@ -1570,14 +1579,16 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st) } if (count == PhyBlock) { - ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, &buf); + ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, + bbuf); count += 0x80; } index = (PhyBlock % 0x80) * 4; - extdat.ovrflg = buf[index]; - extdat.mngflg = buf[index+1]; - extdat.logadr = memstick_logaddr(buf[index+2], buf[index+3]); + extdat.ovrflg = bbuf[index]; + extdat.mngflg = bbuf[index+1]; + extdat.logadr = memstick_logaddr(bbuf[index+2], + bbuf[index+3]); if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) { ms_lib_setacquired_errorblock(us, PhyBlock); @@ -2066,9 +2077,9 @@ static int ene_ms_init(struct us_data *us) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; int result; - u8 buf[0x200]; u16 MSP_BlockSize, MSP_UserAreaBlocks; struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; printk(KERN_INFO "transport --- ENE_MSInit\n"); @@ -2087,13 +2098,13 @@ static int ene_ms_init(struct us_data *us) bcb->CDB[0] = 0xF1; bcb->CDB[1] = 0x01; - result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) { printk(KERN_ERR "Execution MS Init Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } /* the same part to test ENE */ - info->MS_Status = *(struct MS_STATUS *)&buf[0]; + info->MS_Status = *(struct MS_STATUS *) bbuf; if (info->MS_Status.Insert && info->MS_Status.Ready) { printk(KERN_INFO "Insert = %x\n", info->MS_Status.Insert); @@ -2102,15 +2113,15 @@ static int ene_ms_init(struct us_data *us) printk(KERN_INFO "IsMSPHG = %x\n", info->MS_Status.IsMSPHG); printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP); if (info->MS_Status.IsMSPro) { - MSP_BlockSize = (buf[6] << 8) | buf[7]; - MSP_UserAreaBlocks = (buf[10] << 8) | buf[11]; + MSP_BlockSize = (bbuf[6] << 8) | bbuf[7]; + MSP_UserAreaBlocks = (bbuf[10] << 8) | bbuf[11]; info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks; } else { ms_card_init(us); /* Card is MS (to ms.c)*/ } US_DEBUGP("MS Init Code OK !!\n"); } else { - US_DEBUGP("MS Card Not Ready --- %x\n", buf[0]); + US_DEBUGP("MS Card Not Ready --- %x\n", bbuf[0]); return USB_STOR_TRANSPORT_ERROR; } @@ -2120,9 +2131,9 @@ static int ene_ms_init(struct us_data *us) static int ene_sd_init(struct us_data *us) { int result; - u8 buf[0x200]; struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; + u8 *bbuf = info->bbuf; US_DEBUGP("transport --- ENE_SDInit\n"); /* SD Init Part-1 */ @@ -2156,15 +2167,15 @@ static int ene_sd_init(struct us_data *us) bcb->Flags = 0x80; bcb->CDB[0] = 0xF1; - result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0); + result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0); if (result != USB_STOR_XFER_GOOD) { US_DEBUGP("Execution SD Init Code Fail !!\n"); return USB_STOR_TRANSPORT_ERROR; } - info->SD_Status = *(struct SD_STATUS *)&buf[0]; + info->SD_Status = *(struct SD_STATUS *) bbuf; if (info->SD_Status.Insert && info->SD_Status.Ready) { - ene_get_card_status(us, (unsigned char *)&buf); + ene_get_card_status(us, bbuf); US_DEBUGP("Insert = %x\n", info->SD_Status.Insert); US_DEBUGP("Ready = %x\n", info->SD_Status.Ready); US_DEBUGP("IsMMC = %x\n", info->SD_Status.IsMMC); @@ -2172,7 +2183,7 @@ static int ene_sd_init(struct us_data *us) US_DEBUGP("HiSpeed = %x\n", info->SD_Status.HiSpeed); US_DEBUGP("WtP = %x\n", info->SD_Status.WtP); } else { - US_DEBUGP("SD Card Not Ready --- %x\n", buf[0]); + US_DEBUGP("SD Card Not Ready --- %x\n", bbuf[0]); return USB_STOR_TRANSPORT_ERROR; } return USB_STOR_TRANSPORT_GOOD; @@ -2182,13 +2193,15 @@ static int ene_sd_init(struct us_data *us) static int ene_init(struct us_data *us) { int result; - u8 misc_reg03 = 0; + u8 misc_reg03; struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra); + u8 *bbuf = info->bbuf; - result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); + result = ene_get_card_type(us, REG_CARD_STATUS, bbuf); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; + misc_reg03 = bbuf[0]; if (misc_reg03 & 0x01) { if (!info->SD_Status.Ready) { result = ene_sd_init(us); @@ -2304,8 +2317,9 @@ static int ene_ub6250_probe(struct usb_interface *intf, const struct usb_device_id *id) { int result; - u8 misc_reg03 = 0; + u8 misc_reg03; struct us_data *us; + struct ene_ub6250_info *info; result = usb_stor_probe1(&us, intf, id, (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list); @@ -2313,11 +2327,16 @@ static int ene_ub6250_probe(struct usb_interface *intf, return result; /* FIXME: where should the code alloc extra buf ? */ - if (!us->extra) { - us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); - if (!us->extra) - return -ENOMEM; - us->extra_destructor = ene_ub6250_info_destructor; + us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL); + if (!us->extra) + return -ENOMEM; + us->extra_destructor = ene_ub6250_info_destructor; + + info = (struct ene_ub6250_info *)(us->extra); + info->bbuf = kmalloc(512, GFP_KERNEL); + if (!info->bbuf) { + kfree(us->extra); + return -ENOMEM; } us->transport_name = "ene_ub6250"; @@ -2329,12 +2348,13 @@ static int ene_ub6250_probe(struct usb_interface *intf, return result; /* probe card type */ - result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03); + result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf); if (result != USB_STOR_XFER_GOOD) { usb_stor_disconnect(intf); return USB_STOR_TRANSPORT_ERROR; } + misc_reg03 = info->bbuf[0]; if (!(misc_reg03 & 0x01)) { pr_info("ums_eneub6250: The driver only supports SD/MS card. " "To use SM card, please build driver/staging/keucr\n"); diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c index b71291b5056f..a0102f802abb 100644 --- a/drivers/uwb/i1480/dfu/usb.c +++ b/drivers/uwb/i1480/dfu/usb.c @@ -341,6 +341,7 @@ int i1480_usb_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size) static int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id) { + struct usb_device *udev = interface_to_usbdev(iface); struct i1480_usb *i1480_usb; struct i1480 *i1480; struct device *dev = &iface->dev; @@ -352,8 +353,8 @@ int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id) iface->cur_altsetting->desc.bInterfaceNumber); goto error; } - if (iface->num_altsetting > 1 - && interface_to_usbdev(iface)->descriptor.idProduct == 0xbabe) { + if (iface->num_altsetting > 1 && + le16_to_cpu(udev->descriptor.idProduct) == 0xbabe) { /* Need altsetting #1 [HW QUIRK] or EP1 won't work */ result = usb_set_interface(interface_to_usbdev(iface), 0, 1); if (result < 0) diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index 748a74bd85e7..7da3298a119f 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c @@ -641,6 +641,9 @@ static int usb_pcwd_probe(struct usb_interface *interface, return -ENODEV; } + if (iface_desc->desc.bNumEndpoints < 1) + return -ENODEV; + /* check out the endpoint: it has to be Interrupt & IN */ endpoint = &iface_desc->endpoint[0].desc; diff --git a/drivers/xen/biomerge.c b/drivers/xen/biomerge.c index ba6eda4b5143..0d23e1f5846a 100644 --- a/drivers/xen/biomerge.c +++ b/drivers/xen/biomerge.c @@ -8,6 +8,5 @@ bool xen_biovec_phys_mergeable(const struct bio_vec *vec1, unsigned long mfn1 = pfn_to_mfn(page_to_pfn(vec1->bv_page)); unsigned long mfn2 = pfn_to_mfn(page_to_pfn(vec2->bv_page)); - return __BIOVEC_PHYS_MERGEABLE(vec1, vec2) && - ((mfn1 == mfn2) || ((mfn1+1) == mfn2)); + return mfn1 + PFN_DOWN(vec1->bv_offset + vec1->bv_len) == mfn2; } diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 62d7a6d9a701..38a2f2c512d7 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c @@ -345,7 +345,7 @@ static int autofs_dev_ioctl_fail(struct file *fp, int status; token = (autofs_wqt_t) param->fail.token; - status = param->fail.status ? param->fail.status : -ENOENT; + status = param->fail.status < 0 ? param->fail.status : -ENOENT; return autofs4_wait_release(sbi, token, status); } diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index 0f3eb41d9201..5ffc3f698c53 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c @@ -83,14 +83,13 @@ static int create_link(struct config_item *parent_item, ret = -ENOMEM; sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL); if (sl) { - sl->sl_target = config_item_get(item); spin_lock(&configfs_dirent_lock); if (target_sd->s_type & CONFIGFS_USET_DROPPING) { spin_unlock(&configfs_dirent_lock); - config_item_put(item); kfree(sl); return -ENOENT; } + sl->sl_target = config_item_get(item); list_add(&sl->sl_list, &target_sd->s_links); spin_unlock(&configfs_dirent_lock); ret = configfs_create_link(sl, parent_item->ci_dentry, diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index bb40a70ed412..aa54e82d74c3 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -5023,6 +5023,8 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length) ext4_orphan_del(handle, inode); inode->i_mtime = inode->i_ctime = ext4_current_time(inode); ext4_mark_inode_dirty(handle, inode); + if (err >= 0) + ext4_update_inode_fsync_trans(handle, inode, 1); ext4_journal_stop(handle); return err; } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index f881e3484481..fde77a79d814 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1344,7 +1344,6 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, int ret = 0, err, nr_pages, i; struct inode *inode = mpd->inode; struct address_space *mapping = inode->i_mapping; - loff_t size = i_size_read(inode); unsigned int len, block_start; struct buffer_head *bh, *page_bufs = NULL; int journal_data = ext4_should_journal_data(inode); @@ -1370,6 +1369,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, for (i = 0; i < nr_pages; i++) { int commit_write = 0, skip_page = 0; struct page *page = pvec.pages[i]; + loff_t size = i_size_read(inode); index = page->index; if (index > end) @@ -1443,11 +1443,31 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, if (skip_page) goto skip_page; + clear_page_dirty_for_io(page); + /* + * We have to be very careful here! Nothing protects + * writeback path against i_size changes and the page + * can be writeably mapped into page tables. So an + * application can be growing i_size and writing data + * through mmap while writeback runs. + * clear_page_dirty_for_io() write-protects our page in + * page tables and the page cannot get written to again + * until we release page lock. So only after + * clear_page_dirty_for_io() we are safe to sample + * i_size for ext4_bio_write_page() to zero-out tail of + * the written page. We rely on the barrier provided by + * TestClearPageDirty in clear_page_dirty_for_io() to + * make sure i_size is really sampled only after page + * tables are updated. + */ + if (size != i_size_read(inode)) { + set_page_dirty(page); + goto skip_page; + } + if (commit_write) /* mark the buffer_heads as dirty & uptodate */ block_commit_write(page, 0, len); - - clear_page_dirty_for_io(page); /* * Delalloc doesn't support data journalling, * but eventually maybe we'll lift this @@ -4637,8 +4657,9 @@ static int ext4_expand_extra_isize(struct inode *inode, /* No extended attributes present */ if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) || header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) { - memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0, - new_extra_isize); + memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE + + EXT4_I(inode)->i_extra_isize, 0, + new_extra_isize - EXT4_I(inode)->i_extra_isize); EXT4_I(inode)->i_extra_isize = new_extra_isize; return 0; } diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 18c58e5c7260..66897c9851ab 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -457,8 +457,10 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, if (info) { struct partition_meta_info *pinfo = alloc_part_info(disk); - if (!pinfo) + if (!pinfo) { + err = -ENOMEM; goto out_free_stats; + } memcpy(pinfo, info, sizeof(*info)); p->info = pinfo; } diff --git a/fs/proc/array.c b/fs/proc/array.c index 439b5a1048c9..b83dcbb83d3f 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -380,7 +380,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, state = *get_task_state(task); vsize = eip = esp = 0; - permitted = ptrace_may_access(task, PTRACE_MODE_READ); + permitted = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS); mm = get_task_mm(task); if (mm) { vsize = task_vsize(mm); diff --git a/fs/proc/base.c b/fs/proc/base.c index 2c38a3e4fa51..9bc4643054bf 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -216,7 +216,7 @@ static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) struct mm_struct *mm_for_maps(struct task_struct *task) { - return mm_access(task, PTRACE_MODE_READ); + return mm_access(task, PTRACE_MODE_READ_FSCREDS); } static int proc_pid_cmdline(struct task_struct *task, char * buffer) @@ -288,7 +288,7 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer) wchan = get_wchan(task); if (lookup_symbol_name(wchan, symname) < 0) - if (!ptrace_may_access(task, PTRACE_MODE_READ)) + if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) return 0; else return sprintf(buffer, "%lu", wchan); @@ -302,7 +302,7 @@ static int lock_trace(struct task_struct *task) int err = mutex_lock_killable(&task->signal->cred_guard_mutex); if (err) return err; - if (!ptrace_may_access(task, PTRACE_MODE_ATTACH)) { + if (!ptrace_may_access(task, PTRACE_MODE_ATTACH_FSCREDS)) { mutex_unlock(&task->signal->cred_guard_mutex); return -EPERM; } @@ -544,7 +544,7 @@ static int proc_fd_access_allowed(struct inode *inode) */ task = get_proc_task(inode); if (task) { - allowed = ptrace_may_access(task, PTRACE_MODE_READ); + allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS); put_task_struct(task); } return allowed; @@ -769,7 +769,7 @@ static int mem_open(struct inode* inode, struct file* file) if (!task) return -ESRCH; - mm = mm_access(task, PTRACE_MODE_ATTACH); + mm = mm_access(task, PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS); put_task_struct(task); if (IS_ERR(mm)) @@ -2627,7 +2627,7 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole) if (result) return result; - if (!ptrace_may_access(task, PTRACE_MODE_READ)) { + if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) { result = -EACCES; goto out_unlock; } diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index d6c078ea1489..50de28b0a670 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c @@ -91,7 +91,7 @@ static int proc_ns_dir_readdir(struct file *filp, void *dirent, goto out_no_task; ret = -EPERM; - if (!ptrace_may_access(task, PTRACE_MODE_READ)) + if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) goto out; ret = 0; @@ -154,7 +154,7 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir, goto out_no_task; error = ERR_PTR(-EPERM); - if (!ptrace_may_access(task, PTRACE_MODE_READ)) + if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) goto out; last = &ns_entries[ARRAY_SIZE(ns_entries) - 1]; diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 879b13436fa4..56947d3e0e68 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -890,7 +890,10 @@ void ufs_evict_inode(struct inode * inode) ufs_update_inode(inode, IS_SYNC(inode)); old_i_size = inode->i_size; inode->i_size = 0; - if (inode->i_blocks && ufs_truncate(inode, old_i_size)) + if (inode->i_blocks && + (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode)) && + ufs_truncate(inode, old_i_size)) ufs_warning(inode->i_sb, __func__, "ufs_truncate failed\n"); unlock_ufs(inode->i_sb); } diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 3915ade6f9a8..c7090f5b24b6 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -695,6 +695,23 @@ static void ufs_put_super_internal(struct super_block *sb) UFSD("EXIT\n"); } +static u64 ufs_max_bytes(struct super_block *sb) +{ + struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; + int bits = uspi->s_apbshift; + u64 res; + + if (bits > 21) + res = ~0ULL; + else + res = UFS_NDADDR + (1LL << bits) + (1LL << (2*bits)) + + (1LL << (3*bits)); + + if (res >= (MAX_LFS_FILESIZE >> uspi->s_bshift)) + return MAX_LFS_FILESIZE; + return res << uspi->s_bshift; +} + static int ufs_fill_super(struct super_block *sb, void *data, int silent) { struct ufs_sb_info * sbi; @@ -1157,6 +1174,7 @@ again: "fast symlink size (%u)\n", uspi->s_maxsymlinklen); uspi->s_maxsymlinklen = maxsymlen; } + sb->s_maxbytes = ufs_max_bytes(sb); inode = ufs_iget(sb, UFS_ROOTINO); if (IS_ERR(inode)) { diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 92cde998aead..93bc59c0d598 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c @@ -451,12 +451,6 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) inode->i_ino, (unsigned long long)i_size_read(inode), (unsigned long long)old_i_size); - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return -EINVAL; - if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return -EPERM; - err = ufs_alloc_lastblock(inode); if (err) { diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 954175928240..3f9463f8cf2f 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -473,15 +473,19 @@ static inline unsigned _ubh_find_last_zero_bit_( static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, unsigned begin, unsigned block) { + u8 mask; switch (uspi->s_fpb) { case 8: return (*ubh_get_addr (ubh, begin + block) == 0xff); case 4: - return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2))); + mask = 0x0f << ((block & 0x01) << 2); + return (*ubh_get_addr (ubh, begin + (block >> 1)) & mask) == mask; case 2: - return (*ubh_get_addr (ubh, begin + (block >> 2)) == (0x03 << ((block & 0x03) << 1))); + mask = 0x03 << ((block & 0x03) << 1); + return (*ubh_get_addr (ubh, begin + (block >> 2)) & mask) == mask; case 1: - return (*ubh_get_addr (ubh, begin + (block >> 3)) == (0x01 << (block & 0x07))); + mask = 0x01 << (block & 0x07); + return (*ubh_get_addr (ubh, begin + (block >> 3)) & mask) == mask; } return 0; } diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index dce6e4dbeda7..8e44d7305fef 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -292,7 +292,9 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos); #endif - +extern void wait_for_kprobe_optimizer(void); +#else +static inline void wait_for_kprobe_optimizer(void) { } #endif /* CONFIG_OPTPROBES */ /* Get the kprobe at this addr (if any) - called with preemption disabled */ diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index e49240ba8346..953193651aa8 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -130,9 +130,31 @@ extern void __ptrace_unlink(struct task_struct *child); extern void exit_ptrace(struct task_struct *tracer); #define PTRACE_MODE_READ 1 #define PTRACE_MODE_ATTACH 2 +#define PTRACE_MODE_FSCREDS 0x08 +#define PTRACE_MODE_REALCREDS 0x10 + +/* shorthands for READ/ATTACH and FSCREDS/REALCREDS combinations */ +#define PTRACE_MODE_READ_FSCREDS (PTRACE_MODE_READ | PTRACE_MODE_FSCREDS) +#define PTRACE_MODE_READ_REALCREDS (PTRACE_MODE_READ | PTRACE_MODE_REALCREDS) +#define PTRACE_MODE_ATTACH_FSCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS) +#define PTRACE_MODE_ATTACH_REALCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS) + /* Returns 0 on success, -errno on denial. */ extern int __ptrace_may_access(struct task_struct *task, unsigned int mode); -/* Returns true on success, false on denial. */ +/** + * ptrace_may_access - check whether the caller is permitted to access + * a target task. + * @task: target task + * @mode: selects type of access and caller credentials + * + * Returns true on success, false on denial. + * + * One of the flags PTRACE_MODE_FSCREDS and PTRACE_MODE_REALCREDS must + * be set in @mode to specify whether the access was requested through + * a filesystem syscall (should use effective capabilities and fsuid + * of the caller) or through an explicit syscall such as + * process_vm_writev or ptrace (and should use the real credentials). + */ extern bool ptrace_may_access(struct task_struct *task, unsigned int mode); static inline int ptrace_reparented(struct task_struct *child) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 2af31eb76bd0..42e067bb16c8 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -534,6 +534,7 @@ static inline struct rtable *skb_rtable(const struct sk_buff *skb) } extern void kfree_skb(struct sk_buff *skb); +extern void kfree_skb_list(struct sk_buff *segs); extern void consume_skb(struct sk_buff *skb); extern void __kfree_skb(struct sk_buff *skb); extern struct sk_buff *__alloc_skb(unsigned int size, diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h index 1eb735b53fc4..5c62734112d9 100644 --- a/include/linux/usb/ch11.h +++ b/include/linux/usb/ch11.h @@ -11,6 +11,9 @@ #include <linux/types.h> /* __u8 etc */ +/* See USB 3.1 spec Table 10-5 */ +#define USB_SS_MAXPORTS 15 + /* * Hub request types */ diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 921f6270a20c..9e5f33784ea1 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -925,10 +925,6 @@ struct xfrm_dst { struct flow_cache_object flo; struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; int num_pols, num_xfrms; -#ifdef CONFIG_XFRM_SUB_POLICY - struct flowi *origin; - struct xfrm_selector *partner; -#endif u32 xfrm_genid; u32 policy_genid; u32 route_mtu_cached; @@ -944,12 +940,6 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) dst_release(xdst->route); if (likely(xdst->u.dst.xfrm)) xfrm_state_put(xdst->u.dst.xfrm); -#ifdef CONFIG_XFRM_SUB_POLICY - kfree(xdst->origin); - xdst->origin = NULL; - kfree(xdst->partner); - xdst->partner = NULL; -#endif } #endif diff --git a/kernel/events/core.c b/kernel/events/core.c index cd4f88a39fe1..bc94278e0b45 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3004,7 +3004,7 @@ find_lively_task_by_vpid(pid_t vpid) /* Reuse ptrace permission checks for now. */ err = -EACCES; - if (!ptrace_may_access(task, PTRACE_MODE_READ)) + if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) goto errout; return task; diff --git a/kernel/futex.c b/kernel/futex.c index bbd360110079..3854e754f641 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2627,7 +2627,7 @@ SYSCALL_DEFINE3(get_robust_list, int, pid, } ret = -EPERM; - if (!ptrace_may_access(p, PTRACE_MODE_READ)) + if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) goto err_unlock; head = p->robust_list; diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index a9642d528630..e07b64b465fc 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c @@ -154,7 +154,7 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, } ret = -EPERM; - if (!ptrace_may_access(p, PTRACE_MODE_READ)) + if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) goto err_unlock; head = p->compat_robust_list; diff --git a/kernel/kprobes.c b/kernel/kprobes.c index bc90b875f63a..a4f561a3f27f 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -598,7 +598,7 @@ static __kprobes void kprobe_optimizer(struct work_struct *work) } /* Wait for completing optimization and unoptimization */ -static __kprobes void wait_for_kprobe_optimizer(void) +__kprobes void wait_for_kprobe_optimizer(void) { if (delayed_work_pending(&optimizing_work)) wait_for_completion(&optimizer_comp); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index fd3909b87188..b50cded5b80e 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -220,6 +220,14 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state) int __ptrace_may_access(struct task_struct *task, unsigned int mode) { const struct cred *cred = current_cred(), *tcred; + int dumpable = 0; + uid_t caller_uid; + gid_t caller_gid; + + if (!(mode & PTRACE_MODE_FSCREDS) == !(mode & PTRACE_MODE_REALCREDS)) { + WARN(1, "denying ptrace access check without PTRACE_MODE_*CREDS\n"); + return -EPERM; + } /* May we inspect the given task? * This check is used both for attaching with ptrace @@ -229,19 +237,34 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) * because setting up the necessary parent/child relationship * or halting the specified task is impossible. */ - int dumpable = 0; + /* Don't let security modules deny introspection */ if (same_thread_group(task, current)) return 0; rcu_read_lock(); + if (mode & PTRACE_MODE_FSCREDS) { + caller_uid = cred->fsuid; + caller_gid = cred->fsgid; + } else { + /* + * Using the euid would make more sense here, but something + * in userland might rely on the old behavior, and this + * shouldn't be a security problem since + * PTRACE_MODE_REALCREDS implies that the caller explicitly + * used a syscall that requests access to another process + * (and not a filesystem syscall to procfs). + */ + caller_uid = cred->uid; + caller_gid = cred->gid; + } tcred = __task_cred(task); if (cred->user->user_ns == tcred->user->user_ns && - (cred->uid == tcred->euid && - cred->uid == tcred->suid && - cred->uid == tcred->uid && - cred->gid == tcred->egid && - cred->gid == tcred->sgid && - cred->gid == tcred->gid)) + (caller_uid == tcred->euid && + caller_uid == tcred->suid && + caller_uid == tcred->uid && + caller_gid == tcred->egid && + caller_gid == tcred->sgid && + caller_gid == tcred->gid)) goto ok; if (ns_capable(tcred->user->user_ns, CAP_SYS_PTRACE)) goto ok; @@ -308,7 +331,7 @@ static int ptrace_attach(struct task_struct *task, long request, goto out; task_lock(task); - retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); + retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH_REALCREDS); task_unlock(task); if (retval) goto unlock_creds; diff --git a/kernel/signal.c b/kernel/signal.c index 3ecf57489376..0b864fc208e4 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -535,7 +535,8 @@ unblock_all_signals(void) spin_unlock_irqrestore(¤t->sighand->siglock, flags); } -static void collect_signal(int sig, struct sigpending *list, siginfo_t *info) +static void collect_signal(int sig, struct sigpending *list, siginfo_t *info, + bool *resched_timer) { struct sigqueue *q, *first = NULL; @@ -557,6 +558,12 @@ static void collect_signal(int sig, struct sigpending *list, siginfo_t *info) still_pending: list_del_init(&first->list); copy_siginfo(info, &first->info); + + *resched_timer = + (first->flags & SIGQUEUE_PREALLOC) && + (info->si_code == SI_TIMER) && + (info->si_sys_private); + __sigqueue_free(first); } else { /* @@ -573,7 +580,7 @@ static void collect_signal(int sig, struct sigpending *list, siginfo_t *info) } static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, - siginfo_t *info) + siginfo_t *info, bool *resched_timer) { int sig = next_signal(pending, mask); @@ -587,7 +594,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, } } - collect_signal(sig, pending, info); + collect_signal(sig, pending, info, resched_timer); } return sig; @@ -601,15 +608,16 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, */ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) { + bool resched_timer = false; int signr; /* We only dequeue private signals from ourselves, we don't let * signalfd steal them */ - signr = __dequeue_signal(&tsk->pending, mask, info); + signr = __dequeue_signal(&tsk->pending, mask, info, &resched_timer); if (!signr) { signr = __dequeue_signal(&tsk->signal->shared_pending, - mask, info); + mask, info, &resched_timer); /* * itimer signal ? * @@ -654,7 +662,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) */ current->jobctl |= JOBCTL_STOP_DEQUEUED; } - if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) { + if (resched_timer) { /* * Release the siglock to ensure proper locking order * of timer locks outside of siglocks. Note, we leave diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 7eaf1627803b..c82900ceb599 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -419,7 +419,7 @@ u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval) overrun++; } - alarm->node.expires = ktime_add(alarm->node.expires, interval); + alarm->node.expires = ktime_add_safe(alarm->node.expires, interval); return overrun; } @@ -598,13 +598,21 @@ static int alarm_timer_set(struct k_itimer *timr, int flags, /* start the timer */ timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval); + + /* + * Rate limit to the tick as a hot fix to prevent DOS. Will be + * mopped up later. + */ + if (ktime_to_ns(timr->it.alarm.interval) < TICK_NSEC) + timr->it.alarm.interval = ktime_set(1, 0); + exp = timespec_to_ktime(new_setting->it_value); /* Convert (if necessary) to absolute time */ if (flags != TIMER_ABSTIME) { ktime_t now; now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime(); - exp = ktime_add(now, exp); + exp = ktime_add_safe(now, exp); } alarm_start(&timr->it.alarm.alarmtimer, exp); diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 00d527c945a4..2ec1a389a939 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1225,24 +1225,21 @@ static int create_trace_probe(int argc, char **argv) pr_info("Probe point is not specified.\n"); return -EINVAL; } - if (isdigit(argv[1][0])) { + + /* try to parse an address. if that fails, try to read the + * input as a symbol. */ + if (!strict_strtoul(argv[1], 0, (unsigned long *)&addr)) { if (is_return) { pr_info("Return probe point must be a symbol.\n"); return -EINVAL; } - /* an address specified */ - ret = strict_strtoul(&argv[1][0], 0, (unsigned long *)&addr); - if (ret) { - pr_info("Failed to parse address.\n"); - return ret; - } } else { /* a symbol specified */ symbol = argv[1]; /* TODO: support .init module functions */ ret = split_symbol_offset(symbol, &offset); if (ret) { - pr_info("Failed to parse symbol.\n"); + pr_info("Failed to parse either an address or a symbol.\n"); return ret; } if (offset && is_return) { @@ -2109,6 +2106,11 @@ static __init int kprobe_trace_self_tests_init(void) end: release_all_trace_probes(); + /* + * Wait for the optimizer work to finish. Otherwise it might fiddle + * with probes in already freed __init text. + */ + wait_for_kprobe_optimizer(); if (warn) pr_cont("NG: Some tests are failed. Please check them.\n"); else diff --git a/lib/cmdline.c b/lib/cmdline.c index f5f3ad8b62ff..82c466facfe0 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c @@ -22,14 +22,14 @@ * the values[M, M+1, ..., N] into the ints array in get_options. */ -static int get_range(char **str, int *pint) +static int get_range(char **str, int *pint, int n) { int x, inc_counter, upper_range; (*str)++; upper_range = simple_strtol((*str), NULL, 0); inc_counter = upper_range - *pint; - for (x = *pint; x < upper_range; x++) + for (x = *pint; n && x < upper_range; x++, n--) *pint++ = x; return inc_counter; } @@ -95,7 +95,7 @@ char *get_options(const char *str, int nints, int *ints) break; if (res == 3) { int range_nums; - range_nums = get_range((char **)&str, ints + i); + range_nums = get_range((char **)&str, ints + i, nints - i); if (range_nums < 0) break; /* diff --git a/mm/mempolicy.c b/mm/mempolicy.c index c55593549cc9..c8e4ebe5f78d 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1334,12 +1334,9 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode, err = -ESRCH; goto out; } - mm = get_task_mm(task); - rcu_read_unlock(); + get_task_struct(task); err = -EINVAL; - if (!mm) - goto out; /* * Check if this process has the right to modify the specified @@ -1347,14 +1344,13 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode, * capabilities, superuser privileges or the same * userid as the target process. */ - rcu_read_lock(); tcred = __task_cred(task); if (cred->euid != tcred->suid && cred->euid != tcred->uid && cred->uid != tcred->suid && cred->uid != tcred->uid && !capable(CAP_SYS_NICE)) { rcu_read_unlock(); err = -EPERM; - goto out; + goto out_put; } rcu_read_unlock(); @@ -1362,26 +1358,39 @@ SYSCALL_DEFINE4(migrate_pages, pid_t, pid, unsigned long, maxnode, /* Is the user allowed to access the target nodes? */ if (!nodes_subset(*new, task_nodes) && !capable(CAP_SYS_NICE)) { err = -EPERM; - goto out; + goto out_put; } if (!nodes_subset(*new, node_states[N_HIGH_MEMORY])) { err = -EINVAL; - goto out; + goto out_put; } err = security_task_movememory(task); if (err) + goto out_put; + + mm = get_task_mm(task); + put_task_struct(task); + + if (!mm) { + err = -EINVAL; goto out; + } err = do_migrate_pages(mm, old, new, capable(CAP_SYS_NICE) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE); + + mmput(mm); out: - if (mm) - mmput(mm); NODEMASK_SCRATCH_FREE(scratch); return err; + +out_put: + put_task_struct(task); + goto out; + } diff --git a/mm/migrate.c b/mm/migrate.c index f2d86f2bd203..3f95bab563cb 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -34,6 +34,7 @@ #include <linux/syscalls.h> #include <linux/hugetlb.h> #include <linux/gfp.h> +#include <linux/ptrace.h> #include <asm/tlbflush.h> @@ -1198,20 +1199,17 @@ static int do_move_page_to_node_array(struct mm_struct *mm, * Migrate an array of page address onto an array of nodes and fill * the corresponding array of status. */ -static int do_pages_move(struct mm_struct *mm, struct task_struct *task, +static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes, unsigned long nr_pages, const void __user * __user *pages, const int __user *nodes, int __user *status, int flags) { struct page_to_node *pm; - nodemask_t task_nodes; unsigned long chunk_nr_pages; unsigned long chunk_start; int err; - task_nodes = cpuset_mems_allowed(task); - err = -ENOMEM; pm = (struct page_to_node *)__get_free_page(GFP_KERNEL); if (!pm) @@ -1369,10 +1367,10 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages, const int __user *, nodes, int __user *, status, int, flags) { - const struct cred *cred = current_cred(), *tcred; struct task_struct *task; struct mm_struct *mm; int err; + nodemask_t task_nodes; /* Check flags */ if (flags & ~(MPOL_MF_MOVE|MPOL_MF_MOVE_ALL)) @@ -1388,23 +1386,13 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages, rcu_read_unlock(); return -ESRCH; } - mm = get_task_mm(task); - rcu_read_unlock(); - - if (!mm) - return -EINVAL; + get_task_struct(task); /* * Check if this process has the right to modify the specified - * process. The right exists if the process has administrative - * capabilities, superuser privileges or the same - * userid as the target process. + * process. Use the regular "ptrace_may_access()" checks. */ - rcu_read_lock(); - tcred = __task_cred(task); - if (cred->euid != tcred->suid && cred->euid != tcred->uid && - cred->uid != tcred->suid && cred->uid != tcred->uid && - !capable(CAP_SYS_NICE)) { + if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) { rcu_read_unlock(); err = -EPERM; goto out; @@ -1415,16 +1403,25 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages, if (err) goto out; - if (nodes) { - err = do_pages_move(mm, task, nr_pages, pages, nodes, status, - flags); - } else { + task_nodes = cpuset_mems_allowed(task); + mm = get_task_mm(task); + put_task_struct(task); + + if (!mm) + return -EINVAL; + + if (nodes) + err = do_pages_move(mm, task_nodes, nr_pages, pages, + nodes, status, flags); + else err = do_pages_stat(mm, nr_pages, pages, status); - } -out: mmput(mm); return err; + +out: + put_task_struct(task); + return err; } /* diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 6f4ef535c5af..c7a7e01fffc9 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c @@ -399,6 +399,9 @@ static int swap_cgroup_prepare(int type) if (!page) goto not_enough_page; ctrl->map[idx] = page; + + if (!(idx % SWAP_CLUSTER_MAX)) + cond_resched(); } return 0; not_enough_page: diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index 70e814a4d0b8..88c35c9e4407 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c @@ -299,7 +299,7 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec, } task_lock(task); - if (__ptrace_may_access(task, PTRACE_MODE_ATTACH)) { + if (__ptrace_may_access(task, PTRACE_MODE_ATTACH_REALCREDS)) { task_unlock(task); rc = -EPERM; goto put_task_struct; diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index bb38a3c51912..e31529d9d121 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -268,6 +268,7 @@ static struct crush_map *crush_decode(void *pbyval, void *end) u32 yes; struct crush_rule *r; + err = -EINVAL; ceph_decode_32_safe(p, end, yes, bad); if (!yes) { dout("crush_decode NO rule %d off %x %p to %p\n", diff --git a/net/core/dev.c b/net/core/dev.c index 164958d192a3..bb7a0cc037e9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5942,7 +5942,7 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, } else { netdev_stats_to_stats64(storage, &dev->stats); } - storage->rx_dropped += atomic_long_read(&dev->rx_dropped); + storage->rx_dropped += (unsigned long)atomic_long_read(&dev->rx_dropped); return storage; } EXPORT_SYMBOL(dev_get_stats); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 684b57380b2b..f2007b3d4177 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -791,6 +791,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, + nla_total_size(4) /* IFLA_MASTER */ + nla_total_size(1) /* IFLA_OPERSTATE */ + nla_total_size(1) /* IFLA_LINKMODE */ + + nla_total_size(4) /* IFLA_GROUP */ + nla_total_size(ext_filter_mask & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ @@ -1142,6 +1143,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_PORT_SELF] = { .type = NLA_NESTED }, [IFLA_AF_SPEC] = { .type = NLA_NESTED }, [IFLA_EXT_MASK] = { .type = NLA_U32 }, + [IFLA_GROUP] = { .type = NLA_U32 }, }; EXPORT_SYMBOL(ifla_policy); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b30d9c2fd5bd..847b314b3a70 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -277,15 +277,8 @@ EXPORT_SYMBOL(dev_alloc_skb); static void skb_drop_list(struct sk_buff **listp) { - struct sk_buff *list = *listp; - + kfree_skb_list(*listp); *listp = NULL; - - do { - struct sk_buff *this = list; - list = list->next; - kfree_skb(this); - } while (list); } static inline void skb_drop_fraglist(struct sk_buff *skb) @@ -436,6 +429,17 @@ void kfree_skb(struct sk_buff *skb) } EXPORT_SYMBOL(kfree_skb); +void kfree_skb_list(struct sk_buff *segs) +{ + while (segs) { + struct sk_buff *next = segs->next; + + kfree_skb(segs); + segs = next; + } +} +EXPORT_SYMBOL(kfree_skb_list); + /** * consume_skb - free an skbuff * @skb: buffer to free diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index e2ab9681f53a..19dcfe518cd1 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1032,7 +1032,7 @@ static struct inet_protosw inetsw_array[] = .type = SOCK_DGRAM, .protocol = IPPROTO_ICMP, .prot = &ping_prot, - .ops = &inet_dgram_ops, + .ops = &inet_sockraw_ops, .no_check = UDP_CSUM_DEFAULT, .flags = INET_PROTOSW_REUSE, }, diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 80a9a9710726..9d0a94bfe5dc 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2106,6 +2106,10 @@ int tcp_disconnect(struct sock *sk, int flags) tcp_set_ca_state(sk, TCP_CA_Open); tcp_clear_retrans(tp); inet_csk_delack_init(sk); + /* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0 + * issue in __tcp_select_window() + */ + icsk->icsk_ack.rcv_mss = TCP_MIN_MSS; tcp_init_send_head(sk); memset(&tp->rx_opt, 0, sizeof(tp->rx_opt)); __sk_dst_reset(sk); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index eb7a8fba6f4f..73a4355c7431 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1303,13 +1303,14 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb, */ if (pkt_len > mss) { unsigned int new_len = (pkt_len / mss) * mss; - if (!in_sack && new_len < pkt_len) { + if (!in_sack && new_len < pkt_len) new_len += mss; - if (new_len >= skb->len) - return 0; - } pkt_len = new_len; } + + if (pkt_len >= skb->len && !in_sack) + return 0; + err = tcp_fragment(sk, skb, pkt_len, mss); if (err < 0) return err; @@ -3424,7 +3425,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, int delta; /* Non-retransmitted hole got filled? That's reordering */ - if (reord < prior_fackets) + if (reord < prior_fackets && reord <= tp->fackets_out) tcp_update_reordering(sk, tp->fackets_out - reord, 0); delta = tcp_is_fack(tp) ? pkts_acked : diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 9a851d16beda..cb1de47d8c2c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2633,6 +2633,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, { struct net_device *dev = (struct net_device *) data; struct inet6_dev *idev = __in6_dev_get(dev); + struct net *net = dev_net(dev); int run_pending = 0; int err; @@ -2733,7 +2734,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, * IPV6_MIN_MTU stop IPv6 on this interface. */ if (dev->mtu < IPV6_MIN_MTU) - addrconf_ifdown(dev, 1); + addrconf_ifdown(dev, dev != net->loopback_dev); } break; @@ -2754,6 +2755,8 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, * MTU falled under IPV6_MIN_MTU. * Stop IPv6 on this interface. */ + addrconf_ifdown(dev, dev != net->loopback_dev); + break; case NETDEV_DOWN: case NETDEV_UNREGISTER: diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index b0e4fb8ef93d..70390686633d 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -824,8 +824,10 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, u32 features) sizeof(*ipv6h)); if (proto == IPPROTO_UDP) { int err = ip6_find_1stfragopt(skb, &prevhdr); - if (err < 0) + if (err < 0) { + kfree_skb_list(segs); return ERR_PTR(err); + } fptr = (struct frag_hdr *)(skb_network_header(skb) + err); fptr->frag_off = htons(offset); diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c index 63d5d493098a..bc75be1ea310 100644 --- a/net/ipv6/xfrm6_mode_ro.c +++ b/net/ipv6/xfrm6_mode_ro.c @@ -48,6 +48,8 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb) iph = ipv6_hdr(skb); hdr_len = x->type->hdr_offset(x, skb, &prevhdr); + if (hdr_len < 0) + return hdr_len; skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); skb_set_network_header(skb, -x->props.header_len); skb->transport_header = skb->network_header + hdr_len; diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c index 4e344105b3fd..1d3bbe6e1183 100644 --- a/net/ipv6/xfrm6_mode_transport.c +++ b/net/ipv6/xfrm6_mode_transport.c @@ -28,6 +28,8 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb) iph = ipv6_hdr(skb); hdr_len = x->type->hdr_offset(x, skb, &prevhdr); + if (hdr_len < 0) + return hdr_len; skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); skb_set_network_header(skb, -x->props.header_len); skb->transport_header = skb->network_header + hdr_len; diff --git a/net/key/af_key.c b/net/key/af_key.c index 1b19d6a4646f..35fc5ba2826b 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1152,6 +1152,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, goto out; } + err = -ENOBUFS; key = ext_hdrs[SADB_EXT_KEY_AUTH - 1]; if (sa->sadb_sa_auth) { int keysize = 0; @@ -1163,8 +1164,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, if (key) keysize = (key->sadb_key_bits + 7) / 8; x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL); - if (!x->aalg) + if (!x->aalg) { + err = -ENOMEM; goto out; + } strcpy(x->aalg->alg_name, a->name); x->aalg->alg_key_len = 0; if (key) { @@ -1183,8 +1186,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, goto out; } x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL); - if (!x->calg) + if (!x->calg) { + err = -ENOMEM; goto out; + } strcpy(x->calg->alg_name, a->name); x->props.calgo = sa->sadb_sa_encrypt; } else { @@ -1198,8 +1203,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, if (key) keysize = (key->sadb_key_bits + 7) / 8; x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL); - if (!x->ealg) + if (!x->ealg) { + err = -ENOMEM; goto out; + } strcpy(x->ealg->alg_name, a->name); x->ealg->alg_key_len = 0; if (key) { @@ -1247,8 +1254,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, struct xfrm_encap_tmpl *natt; x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL); - if (!x->encap) + if (!x->encap) { + err = -ENOMEM; goto out; + } natt = x->encap; n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]; @@ -3230,7 +3239,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, p += pol->sadb_x_policy_len*8; sec_ctx = (struct sadb_x_sec_ctx *)p; if (len < pol->sadb_x_policy_len*8 + - sec_ctx->sadb_x_sec_len) { + sec_ctx->sadb_x_sec_len*8) { *dir = -EINVAL; goto out; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 96c34c15b1ea..0cfb95a37540 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1959,7 +1959,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) if (is_multicast_ether_addr(hdr->addr1)) { mpp_addr = hdr->addr3; proxied_addr = mesh_hdr->eaddr1; - } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { + } else if ((mesh_hdr->flags & MESH_FLAGS_AE) == + MESH_FLAGS_AE_A5_A6) { /* has_a4 already checked in ieee80211_rx_mesh_check */ mpp_addr = hdr->addr4; proxied_addr = mesh_hdr->eaddr2; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 73db20f1277a..93bb8ae74537 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -731,8 +731,13 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) } out: spin_unlock_bh(&nf_conntrack_lock); - if (last) + if (last) { + /* nf ct hash resize happened, now clear the leftover. */ + if ((struct nf_conn *)cb->args[1] == last) + cb->args[1] = 0; + nf_ct_put(last); + } return skb->len; } diff --git a/net/wireless/util.c b/net/wireless/util.c index 5fba039ca6dd..870c52dcd384 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -360,12 +360,15 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, if (iftype == NL80211_IFTYPE_MESH_POINT) { struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + u8 mesh_flags; + /* make sure meshdr->flags is on the linear part */ if (!pskb_may_pull(skb, hdrlen + 1)) return -1; - if (meshdr->flags & MESH_FLAGS_AE_A4) + mesh_flags = meshdr->flags & MESH_FLAGS_AE; + if (mesh_flags == MESH_FLAGS_AE_A4) return -1; - if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { + if (mesh_flags == MESH_FLAGS_AE_A5_A6) { skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), dst, ETH_ALEN); @@ -386,12 +389,15 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, if (iftype == NL80211_IFTYPE_MESH_POINT) { struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + u8 mesh_flags; + /* make sure meshdr->flags is on the linear part */ if (!pskb_may_pull(skb, hdrlen + 1)) return -1; - if (meshdr->flags & MESH_FLAGS_AE_A5_A6) + mesh_flags = meshdr->flags & MESH_FLAGS_AE; + if (mesh_flags == MESH_FLAGS_AE_A5_A6) return -1; - if (meshdr->flags & MESH_FLAGS_AE_A4) + if (mesh_flags == MESH_FLAGS_AE_A4) skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), src, ETH_ALEN); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 113d20ef31a4..3ca14dc2ab96 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1530,41 +1530,6 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, goto out; } -static int inline -xfrm_dst_alloc_copy(void **target, const void *src, int size) -{ - if (!*target) { - *target = kmalloc(size, GFP_ATOMIC); - if (!*target) - return -ENOMEM; - } - memcpy(*target, src, size); - return 0; -} - -static int inline -xfrm_dst_update_parent(struct dst_entry *dst, const struct xfrm_selector *sel) -{ -#ifdef CONFIG_XFRM_SUB_POLICY - struct xfrm_dst *xdst = (struct xfrm_dst *)dst; - return xfrm_dst_alloc_copy((void **)&(xdst->partner), - sel, sizeof(*sel)); -#else - return 0; -#endif -} - -static int inline -xfrm_dst_update_origin(struct dst_entry *dst, const struct flowi *fl) -{ -#ifdef CONFIG_XFRM_SUB_POLICY - struct xfrm_dst *xdst = (struct xfrm_dst *)dst; - return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl)); -#else - return 0; -#endif -} - static int xfrm_expand_policies(const struct flowi *fl, u16 family, struct xfrm_policy **pols, int *num_pols, int *num_xfrms) @@ -1636,16 +1601,6 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols, xdst = (struct xfrm_dst *)dst; xdst->num_xfrms = err; - if (num_pols > 1) - err = xfrm_dst_update_parent(dst, &pols[1]->selector); - else - err = xfrm_dst_update_origin(dst, fl); - if (unlikely(err)) { - dst_free(dst); - XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); - return ERR_PTR(err); - } - xdst->num_pols = num_pols; memcpy(xdst->pols, pols, sizeof(struct xfrm_policy*) * num_pols); xdst->policy_genid = atomic_read(&pols[0]->genid); @@ -2942,9 +2897,15 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_state *x_new[XFRM_MAX_DEPTH]; struct xfrm_migrate *mp; + /* Stage 0 - sanity checks */ if ((err = xfrm_migrate_check(m, num_migrate)) < 0) goto out; + if (dir >= XFRM_POLICY_MAX) { + err = -EINVAL; + goto out; + } + /* Stage 1 - find policy */ if ((pol = xfrm_migrate_policy_find(sel, dir, type)) == NULL) { err = -ENOENT; diff --git a/security/commoncap.c b/security/commoncap.c index 12440ee03c31..4f338aba1ddb 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -141,12 +141,17 @@ int cap_ptrace_access_check(struct task_struct *child, unsigned int mode) { int ret = 0; const struct cred *cred, *child_cred; + const kernel_cap_t *caller_caps; rcu_read_lock(); cred = current_cred(); child_cred = __task_cred(child); + if (mode & PTRACE_MODE_FSCREDS) + caller_caps = &cred->cap_effective; + else + caller_caps = &cred->cap_permitted; if (cred->user->user_ns == child_cred->user->user_ns && - cap_issubset(child_cred->cap_permitted, cred->cap_permitted)) + cap_issubset(child_cred->cap_permitted, *caller_caps)) goto out; if (ns_capable(child_cred->user->user_ns, CAP_SYS_PTRACE)) goto out; diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index b9073ebd0817..41525338aa8d 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -85,7 +85,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, payload = NULL; vm = false; - if (_payload) { + if (plen) { ret = -ENOMEM; payload = kmalloc(plen, GFP_KERNEL); if (!payload) { @@ -319,7 +319,7 @@ long keyctl_update_key(key_serial_t id, /* pull the payload in if one was supplied */ payload = NULL; - if (_payload) { + if (plen) { ret = -ENOMEM; payload = kmalloc(plen, GFP_KERNEL); if (!payload) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c279f2f3372d..4c6a34700d49 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -911,10 +911,8 @@ static int selinux_parse_opts_str(char *options, goto out_err; opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC); - if (!opts->mnt_opts_flags) { - kfree(opts->mnt_opts); + if (!opts->mnt_opts_flags) goto out_err; - } if (fscontext) { opts->mnt_opts[num_mnt_opts] = fscontext; @@ -937,6 +935,7 @@ static int selinux_parse_opts_str(char *options, return 0; out_err: + security_free_mnt_opts(opts); kfree(context); kfree(defcontext); kfree(fscontext); diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 9b89822460f3..e6f93b934ec5 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1448,6 +1448,8 @@ static const struct snd_pci_quirk stac9200_cfg_tbl[] = { "Dell Inspiron 1501", STAC_9200_DELL_M26), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6, "unknown Dell", STAC_9200_DELL_M26), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0201, + "Dell Latitude D430", STAC_9200_DELL_M22), /* Panasonic */ SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC), /* Gateway machines needs EAPD to be set on resume */ diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a25fa63ce9a2..ff8dd8b44de4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1574,6 +1574,9 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) flush_delayed_work_sync(&rtd->delayed_work); } + /* free the ALSA card at first; this syncs with pending operations */ + snd_card_free(card->snd_card); + /* remove auxiliary devices */ for (i = 0; i < card->num_aux_devs; i++) soc_remove_aux_dev(card, i); @@ -1590,9 +1593,7 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) snd_soc_dapm_free(&card->dapm); kfree(card->rtd); - snd_card_free(card->snd_card); return 0; - } /* removes a socdev */ diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 2780d9ce48bf..df1254839abe 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt @@ -170,9 +170,13 @@ EXAMPLES or ./perf probe --add='schedule:12 cpu' - this will add one or more probes which has the name start with "schedule". +Add one or more probes which has the name start with "schedule". - Add probes on lines in schedule() function which calls update_rq_clock(). + ./perf probe schedule* + or + ./perf probe --add='schedule*' + +Add probes on lines in schedule() function which calls update_rq_clock(). ./perf probe 'schedule;update_rq_clock*' or diff --git a/tools/perf/Documentation/perf-script-perl.txt b/tools/perf/Documentation/perf-script-perl.txt index 3152cca15501..2bdf2b6aab3a 100644 --- a/tools/perf/Documentation/perf-script-perl.txt +++ b/tools/perf/Documentation/perf-script-perl.txt @@ -39,7 +39,7 @@ EVENT HANDLERS When perf script is invoked using a trace script, a user-defined 'handler function' is called for each event in the trace. If there's no handler function defined for a given event type, the event is -ignored (or passed to a 'trace_handled' function, see below) and the +ignored (or passed to a 'trace_unhandled' function, see below) and the next event is processed. Most of the event's field values are passed as arguments to the diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt index 471022069119..282b0e23965e 100644 --- a/tools/perf/Documentation/perf-script-python.txt +++ b/tools/perf/Documentation/perf-script-python.txt @@ -149,10 +149,8 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu, print "id=%d, args=%s\n" % \ (id, args), -def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs, - common_pid, common_comm): - print_header(event_name, common_cpu, common_secs, common_nsecs, - common_pid, common_comm) +def trace_unhandled(event_name, context, event_fields_dict): + print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) def print_header(event_name, cpu, secs, nsecs, pid, comm): print "%-20s %5u %05u.%09u %8u %-20s " % \ @@ -321,7 +319,7 @@ So those are the essential steps in writing and running a script. The process can be generalized to any tracepoint or set of tracepoints you're interested in - basically find the tracepoint(s) you're interested in by looking at the list of available events shown by -'perf list' and/or look in /sys/kernel/debug/tracing events for +'perf list' and/or look in /sys/kernel/debug/tracing/events/ for detailed event and field info, record the corresponding trace data using 'perf record', passing it the list of interesting events, generate a skeleton script using 'perf script -g python' and modify the @@ -334,7 +332,7 @@ right place, you can have your script listed alongside the other scripts listed by the 'perf script -l' command e.g.: ---- -root@tropicana:~# perf script -l +# perf script -l List of available trace scripts: workqueue-stats workqueue stats (ins/exe/create/destroy) wakeup-latency system-wide min/max/avg wakeup latency @@ -384,8 +382,6 @@ to be located in the perf/scripts/python directory in the kernel ---- # ls -al kernel-source/tools/perf/scripts/python - -root@tropicana:/home/trz/src/tip# ls -al tools/perf/scripts/python total 32 drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 . drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 .. @@ -400,7 +396,7 @@ otherwise your script won't show up at run-time), 'perf script -l' should show a new entry for your script: ---- -root@tropicana:~# perf script -l +# perf script -l List of available trace scripts: workqueue-stats workqueue stats (ins/exe/create/destroy) wakeup-latency system-wide min/max/avg wakeup latency @@ -439,7 +435,7 @@ EVENT HANDLERS When perf script is invoked using a trace script, a user-defined 'handler function' is called for each event in the trace. If there's no handler function defined for a given event type, the event is -ignored (or passed to a 'trace_handled' function, see below) and the +ignored (or passed to a 'trace_unhandled' function, see below) and the next event is processed. Most of the event's field values are passed as arguments to the @@ -534,7 +530,7 @@ Aside from the event handler functions discussed above, every script gives scripts a chance to do setup tasks: ---- -def trace_begin: +def trace_begin(): pass ---- @@ -543,7 +539,7 @@ Aside from the event handler functions discussed above, every script as display results: ---- -def trace_end: +def trace_end(): pass ---- @@ -552,8 +548,7 @@ Aside from the event handler functions discussed above, every script of common arguments are passed into it: ---- -def trace_unhandled(event_name, context, common_cpu, common_secs, - common_nsecs, common_pid, common_comm): +def trace_unhandled(event_name, context, event_fields_dict): pass ---- diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 6ccf70e8d8f2..8173636c9817 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -465,7 +465,7 @@ static int python_generate_script(const char *outfile) fprintf(ofp, "# be retrieved using Python functions of the form " "common_*(context).\n"); - fprintf(ofp, "# See the perf-trace-python Documentation for the list " + fprintf(ofp, "# See the perf-script-python Documentation for the list " "of available functions.\n\n"); fprintf(ofp, "import os\n");
Attachment:
signature.asc
Description: This is a digitally signed message part