diff options
-rw-r--r-- | drivers/android/binder.c | 127 | ||||
-rw-r--r-- | drivers/android/binder_alloc.c | 14 | ||||
-rw-r--r-- | drivers/android/binder_alloc.h | 3 | ||||
-rw-r--r-- | drivers/media/platform/msm/vidc/venus_hfi.c | 10 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-dvb.c | 3 | ||||
-rw-r--r-- | drivers/staging/qcacld-3.0/core/cds/src/cds_concurrency.c | 8 | ||||
-rw-r--r-- | drivers/staging/qcacld-3.0/core/dp/htt/htt_rx.c | 9 | ||||
-rw-r--r-- | drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_scan.c | 7 | ||||
-rw-r--r-- | drivers/staging/qcacld-3.0/core/wma/src/wma_features.c | 2 | ||||
-rw-r--r-- | drivers/staging/qcacld-3.0/core/wma/src/wma_nan_datapath.c | 33 | ||||
-rw-r--r-- | drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c | 8 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 3 | ||||
-rw-r--r-- | fs/ext4/inline.c | 38 | ||||
-rw-r--r-- | fs/ext4/xattr.c | 18 | ||||
-rw-r--r-- | include/uapi/linux/android/binder.h | 19 | ||||
-rw-r--r-- | net/key/af_key.c | 40 |
16 files changed, 205 insertions, 137 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index c0dd1f6efa46..9287979171b0 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -361,6 +361,8 @@ struct binder_error { * (invariant after initialized) * @inherit_rt: inherit RT scheduling policy from caller * (invariant after initialized) + * @txn_security_ctx: require sender's security context + * (invariant after initialized) * @async_todo: list of async work items * (protected by @proc->inner_lock) * @@ -399,6 +401,7 @@ struct binder_node { u8 sched_policy:2; u8 inherit_rt:1; u8 accept_fds:1; + u8 txn_security_ctx:1; u8 min_priority; }; bool has_async_transaction; @@ -659,6 +662,7 @@ struct binder_transaction { struct binder_priority saved_priority; bool set_priority_called; kuid_t sender_euid; + binder_uintptr_t security_ctx; /** * @lock: protects @from, @to_proc, and @to_thread * @@ -1368,6 +1372,7 @@ static struct binder_node *binder_init_node_ilocked( node->min_priority = to_kernel_prio(node->sched_policy, priority); node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS); node->inherit_rt = !!(flags & FLAT_BINDER_FLAG_INHERIT_RT); + node->txn_security_ctx = !!(flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX); spin_lock_init(&node->lock); INIT_LIST_HEAD(&node->work.entry); INIT_LIST_HEAD(&node->async_todo); @@ -2938,6 +2943,8 @@ static void binder_transaction(struct binder_proc *proc, binder_size_t last_fixup_min_off = 0; struct binder_context *context = proc->context; int t_debug_id = atomic_inc_return(&binder_last_id); + char *secctx = NULL; + u32 secctx_sz = 0; e = binder_transaction_log_add(&binder_transaction_log); e->debug_id = t_debug_id; @@ -3153,6 +3160,20 @@ static void binder_transaction(struct binder_proc *proc, t->priority = target_proc->default_priority; } + if (target_node && target_node->txn_security_ctx) { + u32 secid; + + security_task_getsecid(proc->tsk, &secid); + ret = security_secid_to_secctx(secid, &secctx, &secctx_sz); + if (ret) { + return_error = BR_FAILED_REPLY; + return_error_param = ret; + return_error_line = __LINE__; + goto err_get_secctx_failed; + } + extra_buffers_size += ALIGN(secctx_sz, sizeof(u64)); + } + trace_binder_transaction(reply, t, target_node); t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size, @@ -3169,7 +3190,19 @@ static void binder_transaction(struct binder_proc *proc, t->buffer = NULL; goto err_binder_alloc_buf_failed; } - t->buffer->allow_user_free = 0; + if (secctx) { + size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) + + ALIGN(tr->offsets_size, sizeof(void *)) + + ALIGN(extra_buffers_size, sizeof(void *)) - + ALIGN(secctx_sz, sizeof(u64)); + char *kptr = t->buffer->data + buf_offset; + + t->security_ctx = (binder_uintptr_t)kptr + + binder_alloc_get_user_buffer_offset(&target_proc->alloc); + memcpy(kptr, secctx, secctx_sz); + security_release_secctx(secctx, secctx_sz); + secctx = NULL; + } t->buffer->debug_id = t->debug_id; t->buffer->transaction = t; t->buffer->target_node = target_node; @@ -3433,6 +3466,9 @@ err_copy_data_failed: t->buffer->transaction = NULL; binder_alloc_free_buf(&target_proc->alloc, t->buffer); err_binder_alloc_buf_failed: + if (secctx) + security_release_secctx(secctx, secctx_sz); +err_get_secctx_failed: kfree(tcomplete); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); err_alloc_tcomplete_failed: @@ -3658,14 +3694,18 @@ static int binder_thread_write(struct binder_proc *proc, buffer = binder_alloc_prepare_to_free(&proc->alloc, data_ptr); - if (buffer == NULL) { - binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n", - proc->pid, thread->pid, (u64)data_ptr); - break; - } - if (!buffer->allow_user_free) { - binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n", - proc->pid, thread->pid, (u64)data_ptr); + if (IS_ERR_OR_NULL(buffer)) { + if (PTR_ERR(buffer) == -EPERM) { + binder_user_error( + "%d:%d BC_FREE_BUFFER u%016llx matched unreturned or currently freeing buffer\n", + proc->pid, thread->pid, + (u64)data_ptr); + } else { + binder_user_error( + "%d:%d BC_FREE_BUFFER u%016llx no match\n", + proc->pid, thread->pid, + (u64)data_ptr); + } break; } binder_debug(BINDER_DEBUG_FREE_BUFFER, @@ -4075,11 +4115,13 @@ retry: while (1) { uint32_t cmd; - struct binder_transaction_data tr; + struct binder_transaction_data_secctx tr; + struct binder_transaction_data *trd = &tr.transaction_data; struct binder_work *w = NULL; struct list_head *list = NULL; struct binder_transaction *t = NULL; struct binder_thread *t_from; + size_t trsize = sizeof(*trd); binder_inner_proc_lock(proc); if (!binder_worklist_empty_ilocked(&thread->todo)) @@ -4274,41 +4316,47 @@ retry: struct binder_node *target_node = t->buffer->target_node; struct binder_priority node_prio; - tr.target.ptr = target_node->ptr; - tr.cookie = target_node->cookie; + trd->target.ptr = target_node->ptr; + trd->cookie = target_node->cookie; node_prio.sched_policy = target_node->sched_policy; node_prio.prio = target_node->min_priority; binder_transaction_priority(current, t, node_prio, target_node->inherit_rt); cmd = BR_TRANSACTION; } else { - tr.target.ptr = 0; - tr.cookie = 0; + trd->target.ptr = 0; + trd->cookie = 0; cmd = BR_REPLY; } - tr.code = t->code; - tr.flags = t->flags; - tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid); + trd->code = t->code; + trd->flags = t->flags; + trd->sender_euid = from_kuid(current_user_ns(), t->sender_euid); t_from = binder_get_txn_from(t); if (t_from) { struct task_struct *sender = t_from->proc->tsk; - tr.sender_pid = task_tgid_nr_ns(sender, - task_active_pid_ns(current)); + trd->sender_pid = + task_tgid_nr_ns(sender, + task_active_pid_ns(current)); } else { - tr.sender_pid = 0; + trd->sender_pid = 0; } - tr.data_size = t->buffer->data_size; - tr.offsets_size = t->buffer->offsets_size; - tr.data.ptr.buffer = (binder_uintptr_t) + trd->data_size = t->buffer->data_size; + trd->offsets_size = t->buffer->offsets_size; + trd->data.ptr.buffer = (binder_uintptr_t) ((uintptr_t)t->buffer->data + binder_alloc_get_user_buffer_offset(&proc->alloc)); - tr.data.ptr.offsets = tr.data.ptr.buffer + + trd->data.ptr.offsets = trd->data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *)); + if (t->security_ctx) { + cmd = BR_TRANSACTION_SEC_CTX; + tr.secctx = t->security_ctx; + trsize = sizeof(tr); + } if (put_user(cmd, (uint32_t __user *)ptr)) { if (t_from) binder_thread_dec_tmpref(t_from); @@ -4319,7 +4367,7 @@ retry: return -EFAULT; } ptr += sizeof(uint32_t); - if (copy_to_user(ptr, &tr, sizeof(tr))) { + if (copy_to_user(ptr, &tr, trsize)) { if (t_from) binder_thread_dec_tmpref(t_from); @@ -4328,7 +4376,7 @@ retry: return -EFAULT; } - ptr += sizeof(tr); + ptr += trsize; trace_binder_transaction_received(t); binder_stat_br(proc, thread, cmd); @@ -4336,16 +4384,18 @@ retry: "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n", proc->pid, thread->pid, (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" : - "BR_REPLY", + (cmd == BR_TRANSACTION_SEC_CTX) ? + "BR_TRANSACTION_SEC_CTX" : "BR_REPLY", t->debug_id, t_from ? t_from->proc->pid : 0, t_from ? t_from->pid : 0, cmd, t->buffer->data_size, t->buffer->offsets_size, - (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets); + (u64)trd->data.ptr.buffer, + (u64)trd->data.ptr.offsets); if (t_from) binder_thread_dec_tmpref(t_from); t->buffer->allow_user_free = 1; - if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) { + if (cmd != BR_REPLY && !(t->flags & TF_ONE_WAY)) { binder_inner_proc_lock(thread->proc); t->to_parent = thread->transaction_stack; t->to_thread = thread; @@ -4669,7 +4719,8 @@ out: return ret; } -static int binder_ioctl_set_ctx_mgr(struct file *filp) +static int binder_ioctl_set_ctx_mgr(struct file *filp, + struct flat_binder_object *fbo) { int ret = 0; struct binder_proc *proc = filp->private_data; @@ -4698,7 +4749,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp) } else { context->binder_context_mgr_uid = curr_euid; } - new_node = binder_new_node(proc, NULL); + new_node = binder_new_node(proc, fbo); if (!new_node) { ret = -ENOMEM; goto out; @@ -4784,8 +4835,20 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) binder_inner_proc_unlock(proc); break; } + case BINDER_SET_CONTEXT_MGR_EXT: { + struct flat_binder_object fbo; + + if (copy_from_user(&fbo, ubuf, sizeof(fbo))) { + ret = -EINVAL; + goto err; + } + ret = binder_ioctl_set_ctx_mgr(filp, &fbo); + if (ret) + goto err; + break; + } case BINDER_SET_CONTEXT_MGR: - ret = binder_ioctl_set_ctx_mgr(filp); + ret = binder_ioctl_set_ctx_mgr(filp, NULL); if (ret) goto err; break; diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index bb88231258fb..f13def03ca5b 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -149,14 +149,12 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked( else { /* * Guard against user threads attempting to - * free the buffer twice + * free the buffer when in use by kernel or + * after it's already been freed. */ - if (buffer->free_in_progress) { - pr_err("%d:%d FREE_BUFFER u%016llx user freed buffer twice\n", - alloc->pid, current->pid, (u64)user_ptr); - return NULL; - } - buffer->free_in_progress = 1; + if (!buffer->allow_user_free) + return ERR_PTR(-EPERM); + buffer->allow_user_free = 0; return buffer; } } @@ -462,7 +460,7 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, rb_erase(best_fit, &alloc->free_buffers); buffer->free = 0; - buffer->free_in_progress = 0; + buffer->allow_user_free = 0; binder_insert_allocated_buffer_locked(alloc, buffer); binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd got %pK\n", diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 8bf548d80a1d..66efb16ab9b1 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -50,8 +50,7 @@ struct binder_buffer { unsigned free:1; unsigned allow_user_free:1; unsigned async_transaction:1; - unsigned free_in_progress:1; - unsigned debug_id:28; + unsigned debug_id:29; struct binder_transaction *transaction; diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 4489adb572c0..a2eb4045e6a0 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.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 @@ -1616,7 +1616,7 @@ static int __iface_cmdq_write_relaxed(struct venus_hfi_device *device, __strict_check(device); if (!__core_in_valid_state(device)) { - dprintk(VIDC_DBG, "%s - fw not in init state\n", __func__); + dprintk(VIDC_ERR, "%s - fw not in init state\n", __func__); result = -EINVAL; goto err_q_null; } @@ -3342,8 +3342,6 @@ static void __process_sys_error(struct venus_hfi_device *device) { struct hfi_sfr_struct *vsfr = NULL; - __set_state(device, VENUS_STATE_DEINIT); - /* Once SYS_ERROR received from HW, it is safe to halt the AXI. * With SYS_ERROR, Venus FW may have crashed and HW might be * active and causing unnecessary transactions. Hence it is @@ -3590,6 +3588,10 @@ static int __response_handler(struct venus_hfi_device *device) "Too many packets in message queue to handle at once, deferring read\n"); break; } + + /* do not read packets after sys error packet */ + if (info->response_type == HAL_SYS_ERROR) + break; } if (requeue_pm_work && device->res->sw_power_collapsible) { diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 357be76c7a55..5502a0fb94fd 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1806,6 +1806,8 @@ static int em28xx_dvb_fini(struct em28xx *dev) } } + em28xx_unregister_dvb(dvb); + /* remove I2C SEC */ client = dvb->i2c_client_sec; if (client) { @@ -1827,7 +1829,6 @@ static int em28xx_dvb_fini(struct em28xx *dev) i2c_unregister_device(client); } - em28xx_unregister_dvb(dvb); kfree(dvb); dev->dvb = NULL; kref_put(&dev->ref, em28xx_free_device); diff --git a/drivers/staging/qcacld-3.0/core/cds/src/cds_concurrency.c b/drivers/staging/qcacld-3.0/core/cds/src/cds_concurrency.c index 67481b33ebd8..1cec39b9e835 100644 --- a/drivers/staging/qcacld-3.0/core/cds/src/cds_concurrency.c +++ b/drivers/staging/qcacld-3.0/core/cds/src/cds_concurrency.c @@ -5543,8 +5543,8 @@ static QDF_STATUS cds_modify_pcl_based_on_enabled_channels( } } - qdf_mem_zero(pcl_list_org, QDF_ARRAY_SIZE(pcl_list_org)); - qdf_mem_zero(weight_list_org, QDF_ARRAY_SIZE(weight_list_org)); + qdf_mem_zero(pcl_list_org, *pcl_len_org); + qdf_mem_zero(weight_list_org, *pcl_len_org); qdf_mem_copy(pcl_list_org, pcl_list, pcl_len); qdf_mem_copy(weight_list_org, weight_list, pcl_len); *pcl_len_org = pcl_len; @@ -10035,8 +10035,8 @@ QDF_STATUS cds_modify_sap_pcl_based_on_mandatory_channel(uint8_t *pcl_list_org, } } - qdf_mem_zero(pcl_list_org, QDF_ARRAY_SIZE(pcl_list_org)); - qdf_mem_zero(weight_list_org, QDF_ARRAY_SIZE(weight_list_org)); + qdf_mem_zero(pcl_list_org, *pcl_len_org); + qdf_mem_zero(weight_list_org, *pcl_len_org); qdf_mem_copy(pcl_list_org, pcl_list, pcl_len); qdf_mem_copy(weight_list_org, weight_list, pcl_len); *pcl_len_org = pcl_len; diff --git a/drivers/staging/qcacld-3.0/core/dp/htt/htt_rx.c b/drivers/staging/qcacld-3.0/core/dp/htt/htt_rx.c index 56c2ca10427b..d2e414f47e18 100644 --- a/drivers/staging/qcacld-3.0/core/dp/htt/htt_rx.c +++ b/drivers/staging/qcacld-3.0/core/dp/htt/htt_rx.c @@ -519,6 +519,15 @@ static int htt_rx_ring_fill_n(struct htt_pdev_t *pdev, int num) int num_alloc = 0; idx = *(pdev->rx_ring.alloc_idx.vaddr); + + if ((idx < 0) || (idx > pdev->rx_ring.size_mask) || + (num > pdev->rx_ring.size)) { + QDF_TRACE(QDF_MODULE_ID_HTT, + QDF_TRACE_LEVEL_ERROR, + "%s:rx refill failed!", __func__); + return filled; + } + if (qdf_mem_smmu_s1_enabled(pdev->osdev) && pdev->is_ipa_uc_enabled) { mem_map_table = qdf_mem_map_table_alloc(num); if (!mem_map_table) { diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_scan.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_scan.c index 990b35a055b1..d24cd6440566 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_scan.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_scan.c @@ -7861,6 +7861,13 @@ QDF_STATUS csr_scan_save_preferred_network_found(tpAniSirGlobal pMac, uLen = pPrefNetworkFoundInd->frameLength - (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); } + + if (uLen > (UINT_MAX - sizeof(struct tag_csrscan_result))) { + sme_err("Incorrect len: %d, may leads to int overflow, uLen %d", + pPrefNetworkFoundInd->frameLength, uLen); + qdf_mem_free(parsed_frm); + return QDF_STATUS_E_FAILURE; + } pScanResult = qdf_mem_malloc(sizeof(struct tag_csrscan_result) + uLen); if (NULL == pScanResult) { sme_err("fail to allocate memory for frame"); diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c index 73d42db329c6..bc7d1d6c2773 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c @@ -1859,7 +1859,7 @@ int wma_nan_rsp_event_handler(void *handle, uint8_t *event_buf, alloc_len = sizeof(tSirNanEvent); alloc_len += nan_rsp_event_hdr->data_len; if (nan_rsp_event_hdr->data_len > ((WMI_SVC_MSG_MAX_SIZE - - sizeof(*nan_rsp_event_hdr)) / sizeof(uint8_t)) || + WMI_TLV_HDR_SIZE - sizeof(*nan_rsp_event_hdr)) / sizeof(uint8_t)) || nan_rsp_event_hdr->data_len > param_buf->num_data) { WMA_LOGE("excess data length:%d, num_data:%d", nan_rsp_event_hdr->data_len, param_buf->num_data); diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_nan_datapath.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_nan_datapath.c index 720b627008be..b3f7fbdc795e 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_nan_datapath.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_nan_datapath.c @@ -464,6 +464,7 @@ static int wma_ndp_indication_event_handler(void *handle, uint8_t *event_info, wmi_ndp_indication_event_fixed_param *fixed_params; struct ndp_indication_event ind_event = {0}; tp_wma_handle wma_handle = handle; + size_t total_array_len; event = (WMI_NDP_INDICATION_EVENTID_param_tlvs *)event_info; fixed_params = @@ -482,6 +483,38 @@ static int wma_ndp_indication_event_handler(void *handle, uint8_t *event_info, return -EINVAL; } + if (fixed_params->nan_scid_len > event->num_ndp_scid) { + WMA_LOGE(FL("Invalid nan_scid_len: %d"), + fixed_params->nan_scid_len); + return -EINVAL; + } + + if (fixed_params->ndp_cfg_len > + (WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_params))) { + WMA_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", + __func__, fixed_params->ndp_cfg_len); + return -EINVAL; + } + + total_array_len = fixed_params->ndp_cfg_len + + sizeof(*fixed_params); + + if (fixed_params->ndp_app_info_len > + (WMI_SVC_MSG_MAX_SIZE - total_array_len)) { + WMA_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", + __func__, fixed_params->ndp_app_info_len); + return -EINVAL; + } + + total_array_len += fixed_params->ndp_app_info_len; + + if (fixed_params->nan_scid_len > + (WMI_SVC_MSG_MAX_SIZE - total_array_len)) { + WMA_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", + __func__, fixed_params->nan_scid_len); + return -EINVAL; + } + ind_event.vdev_id = fixed_params->vdev_id; ind_event.service_instance_id = fixed_params->service_instance_id; ind_event.ndp_instance_id = fixed_params->ndp_instance_id; diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c index 06dd6698f624..a79765e32b57 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c @@ -461,8 +461,8 @@ int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf, alloc_len += stats_ext_info->data_len; if (stats_ext_info->data_len > (WMI_SVC_MSG_MAX_SIZE - - sizeof(*stats_ext_info)) || stats_ext_info->data_len > - param_buf->num_data) { + WMI_TLV_HDR_SIZE - sizeof(*stats_ext_info)) || + stats_ext_info->data_len > param_buf->num_data) { WMA_LOGE("Excess data_len:%d, num_data:%d", stats_ext_info->data_len, param_buf->num_data); return -EINVAL; @@ -1280,7 +1280,7 @@ static int wma_unified_link_peer_stats_event_handler(void *handle, size_t peer_info_size, peer_stats_size, rate_stats_size; size_t link_stats_results_size; bool excess_data = false; - uint32_t buf_len; + uint32_t buf_len = 0; tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE); @@ -1349,7 +1349,7 @@ static int wma_unified_link_peer_stats_event_handler(void *handle, } while (0); if (excess_data || - (sizeof(*fixed_param) > WMI_SVC_MSG_MAX_SIZE - buf_len)) { + (buf_len > WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_param))) { WMA_LOGE("excess wmi buffer: rates:%d, peers:%d", peer_stats->num_rates, fixed_param->num_peers); return -EINVAL; diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 712d9388264e..6f4557d4feb8 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -3053,9 +3053,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, __u64 start, __u64 len); -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 4aca27940b44..2e005ceaf84c 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -902,11 +902,11 @@ retry_journal: flags |= AOP_FLAG_NOFS; 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; @@ -1877,42 +1877,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 cfb546ebf294..4e97aba4fa89 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1070,22 +1070,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); diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h index 5539933b3491..993bb463ef96 100644 --- a/include/uapi/linux/android/binder.h +++ b/include/uapi/linux/android/binder.h @@ -87,6 +87,14 @@ enum flat_binder_object_flags { * scheduling policy from the caller (for synchronous transactions). */ FLAT_BINDER_FLAG_INHERIT_RT = 0x800, + + /** + * @FLAT_BINDER_FLAG_TXN_SECURITY_CTX: request security contexts + * + * Only when set, causes senders to include their security + * context + */ + FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000, }; #ifdef BINDER_IPC_32BIT @@ -254,6 +262,7 @@ struct binder_node_debug_info { #define BINDER_THREAD_EXIT _IOW('b', 8, __s32) #define BINDER_VERSION _IOWR('b', 9, struct binder_version) #define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info) +#define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object) /* * NOTE: Two special error codes you should check for when calling @@ -312,6 +321,11 @@ struct binder_transaction_data { } data; }; +struct binder_transaction_data_secctx { + struct binder_transaction_data transaction_data; + binder_uintptr_t secctx; +}; + struct binder_transaction_data_sg { struct binder_transaction_data transaction_data; binder_size_t buffers_size; @@ -347,6 +361,11 @@ enum binder_driver_return_protocol { BR_OK = _IO('r', 1), /* No parameters! */ + BR_TRANSACTION_SEC_CTX = _IOR('r', 2, + struct binder_transaction_data_secctx), + /* + * binder_transaction_data_secctx: the received command. + */ BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data), BR_REPLY = _IOR('r', 3, struct binder_transaction_data), /* diff --git a/net/key/af_key.c b/net/key/af_key.c index 3ba903ff2bb0..58c045d027fc 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -196,30 +196,22 @@ static int pfkey_release(struct socket *sock) return 0; } -static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, - gfp_t allocation, struct sock *sk) +static int pfkey_broadcast_one(struct sk_buff *skb, gfp_t allocation, + struct sock *sk) { int err = -ENOBUFS; - sock_hold(sk); - if (*skb2 == NULL) { - if (atomic_read(&skb->users) != 1) { - *skb2 = skb_clone(skb, allocation); - } else { - *skb2 = skb; - atomic_inc(&skb->users); - } - } - if (*skb2 != NULL) { - if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) { - skb_set_owner_r(*skb2, sk); - skb_queue_tail(&sk->sk_receive_queue, *skb2); - sk->sk_data_ready(sk); - *skb2 = NULL; - err = 0; - } + if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) + return err; + + skb = skb_clone(skb, allocation); + + if (skb) { + skb_set_owner_r(skb, sk); + skb_queue_tail(&sk->sk_receive_queue, skb); + sk->sk_data_ready(sk); + err = 0; } - sock_put(sk); return err; } @@ -234,7 +226,6 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, { struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); struct sock *sk; - struct sk_buff *skb2 = NULL; int err = -ESRCH; /* XXX Do we need something like netlink_overrun? I think @@ -253,7 +244,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, * socket. */ if (pfk->promisc) - pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk); + pfkey_broadcast_one(skb, GFP_ATOMIC, sk); /* the exact target will be processed later */ if (sk == one_sk) @@ -268,7 +259,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, continue; } - err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk); + err2 = pfkey_broadcast_one(skb, GFP_ATOMIC, sk); /* Error is cleared after successful sending to at least one * registered KM */ @@ -278,9 +269,8 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, rcu_read_unlock(); if (one_sk != NULL) - err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk); + err = pfkey_broadcast_one(skb, allocation, one_sk); - kfree_skb(skb2); kfree_skb(skb); return err; } |