Merge branch 'android-msm-bullhead-3.10-oc' into android-msm-bullhead-3.10
January 2018.1
Bug: 68996203
Change-Id: I8d8fde2ad141ecfc2ecf072b32aa4299c4935b80
Signed-off-by: Patrick Tjin <pattjin@google.com>
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
index 3f35e2d..7f264c5 100644
--- a/Documentation/printk-formats.txt
+++ b/Documentation/printk-formats.txt
@@ -62,11 +62,12 @@
Physical addresses:
- %pa 0x01234567 or 0x0123456789abcdef
+ %pa[P] 0x01234567 or 0x0123456789abcdef
For printing a phys_addr_t type (and its derivatives, such as
resource_size_t) which can vary based on build options, regardless of
- the width of the CPU data path. Passed by reference.
+ the width of the CPU data path. Passed by reference. Use the trailing
+ 'P' if it needs to be always shown.
Raw buffer as a hex string:
%*ph 00 01 02 ... 3f
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index 7558775..62162bf 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -28,4 +28,11 @@
#define perf_misc_flags(regs) perf_misc_flags(regs)
#endif
+#define perf_arch_fetch_caller_regs(regs, __ip) { \
+ (regs)->ARM_pc = (__ip); \
+ (regs)->ARM_fp = (unsigned long) __builtin_frame_address(0); \
+ (regs)->ARM_sp = current_stack_pointer; \
+ (regs)->ARM_cpsr = SVC_MODE; \
+}
+
#endif /* __ARM_PERF_EVENT_H__ */
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 214d415..b3a1156 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -89,6 +89,11 @@
#define init_stack (init_thread_union.stack)
/*
+ * how to get the current stack pointer in C
+ */
+register unsigned long current_stack_pointer asm ("sp");
+
+/*
* how to get the thread information struct from C
*/
static inline struct thread_info *current_thread_info(void) __attribute_const__;
diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h
index 547d4f9..227ac1f 100644
--- a/arch/arm64/include/asm/perf_event.h
+++ b/arch/arm64/include/asm/perf_event.h
@@ -41,4 +41,11 @@
{ }
#endif
+#define perf_arch_fetch_caller_regs(regs, __ip) { \
+ (regs)->pc = (__ip); \
+ (regs)->regs[29] = (unsigned long) __builtin_frame_address(0); \
+ (regs)->sp = current_stack_pointer; \
+ (regs)->pstate = PSR_MODE_EL1h; \
+}
+
#endif
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index f4091da..c3216a60d 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -69,6 +69,11 @@
#define init_stack (init_thread_union.stack)
/*
+ * how to get the current stack pointer from C
+ */
+register unsigned long current_stack_pointer asm ("sp");
+
+/*
* how to get the thread information struct from C
*/
static inline struct thread_info *current_thread_info(void) __attribute_const__;
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index f220e18..efa2123 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -499,7 +499,8 @@
"idivt",
"vfpd32",
"lpae",
- "evtstrm"
+ "evtstrm",
+ NULL
};
static const char *compat_hwcap2_str[] = {
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index a1251a6..7cedd4f 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -82,6 +82,11 @@
require userspace firmware loading support, but a module built
out-of-tree does.
+config FW_CACHE
+ bool "Enable firmware caching during suspend"
+ depends on PM_SLEEP
+ default n
+
config FIRMWARE_IN_KERNEL
bool "Include in-kernel firmware blobs in kernel binary"
depends on FW_LOADER
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4fac81b..bb36eb1 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -236,6 +236,7 @@
return tmp ? 0 : -ENOMEM;
}
+#ifdef CONFIG_FW_CACHE
static struct firmware_buf *fw_lookup_buf(const char *fw_name)
{
struct firmware_buf *tmp;
@@ -247,6 +248,7 @@
return tmp;
}
+#endif
static void __fw_free_buf(struct kref *ref)
{
@@ -1448,6 +1450,9 @@
map_data);
}
+#ifdef CONFIG_FW_CACHE
+static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
+
/**
* cache_firmware - cache one firmware image in kernel memory space
* @fw_name: the firmware image name
@@ -1508,9 +1513,6 @@
return -EINVAL;
}
-#ifdef CONFIG_PM_SLEEP
-static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
-
static struct fw_cache_entry *alloc_fw_cache_entry(const char *name)
{
struct fw_cache_entry *fce;
@@ -1774,7 +1776,7 @@
INIT_LIST_HEAD(&fw_cache.head);
fw_cache.state = FW_LOADER_NO_CACHE;
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
spin_lock_init(&fw_cache.name_lock);
INIT_LIST_HEAD(&fw_cache.fw_names);
@@ -1800,7 +1802,7 @@
static void __exit firmware_class_exit(void)
{
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
unregister_syscore_ops(&fw_syscore_ops);
unregister_pm_notifier(&fw_cache.pm_notify);
#endif
@@ -1815,5 +1817,7 @@
EXPORT_SYMBOL(release_firmware);
EXPORT_SYMBOL(request_firmware);
EXPORT_SYMBOL(request_firmware_nowait);
+#ifdef CONFIG_FW_CACHE
EXPORT_SYMBOL_GPL(cache_firmware);
EXPORT_SYMBOL_GPL(uncache_firmware);
+#endif
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index f8baf28..cfbd7a9 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -63,6 +63,7 @@
static DEFINE_MUTEX(send_cmd_lock);
static DEFINE_MUTEX(qcedev_sent_bw_req);
+static DEFINE_MUTEX(hash_access_lock);
static void qcedev_ce_high_bw_req(struct qcedev_control *podev,
bool high_bw_req)
@@ -1651,12 +1652,18 @@
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
- if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+ mutex_lock(&hash_access_lock);
+ if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
+ }
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
err = qcedev_hash_init(&qcedev_areq, handle, &sg_src);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
+ mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1674,32 +1681,42 @@
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
- if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+ mutex_lock(&hash_access_lock);
+ if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
+ }
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
if (qcedev_areq.sha_op_req.alg == QCEDEV_ALG_AES_CMAC) {
err = qcedev_hash_cmac(&qcedev_areq, handle, &sg_src);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
} else {
if (handle->sha_ctxt.init_done == false) {
pr_err("%s Init was not called\n", __func__);
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
}
err = qcedev_hash_update(&qcedev_areq, handle, &sg_src);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
}
if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
pr_err("Invalid sha_ctxt.diglen %d\n",
handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
}
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1716,22 +1733,29 @@
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
- if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+ mutex_lock(&hash_access_lock);
+ if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
+ }
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
err = qcedev_hash_final(&qcedev_areq, handle);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
pr_err("Invalid sha_ctxt.diglen %d\n",
handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
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],
handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1746,26 +1770,35 @@
(void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
- if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev))
+ mutex_lock(&hash_access_lock);
+ if (qcedev_check_sha_params(&qcedev_areq.sha_op_req, podev)) {
+ mutex_unlock(&hash_access_lock);
return -EINVAL;
+ }
qcedev_areq.op_type = QCEDEV_CRYPTO_OPER_SHA;
qcedev_hash_init(&qcedev_areq, handle, &sg_src);
err = qcedev_hash_update(&qcedev_areq, handle, &sg_src);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
err = qcedev_hash_final(&qcedev_areq, handle);
- if (err)
+ if (err) {
+ mutex_unlock(&hash_access_lock);
return err;
+ }
if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
pr_err("Invalid sha_ctxt.diglen %d\n",
handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
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],
handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
if (copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 0bfec8b..d167443 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -26,6 +26,7 @@
#include "adreno.h"
#include "adreno_pm4types.h"
#include "adreno_ringbuffer.h"
+#include "adreno_trace.h"
#include "a3xx_reg.h"
@@ -100,6 +101,9 @@
else
time->ticks = 0;
+ /* Trace the GPU time to create a mapping to ftrace time */
+ trace_adreno_cmdbatch_sync(rb->drawctxt_active, time->ticks);
+
/* Get the kernel clock for time since boot */
time->ktime = local_clock();
diff --git a/drivers/gpu/msm/adreno_trace.h b/drivers/gpu/msm/adreno_trace.h
index 4d14c27..3425971 100644
--- a/drivers/gpu/msm/adreno_trace.h
+++ b/drivers/gpu/msm/adreno_trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, 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
@@ -115,6 +115,29 @@
)
);
+TRACE_EVENT(adreno_cmdbatch_sync,
+ TP_PROTO(struct adreno_context *drawctxt,
+ uint64_t ticks),
+ TP_ARGS(drawctxt, ticks),
+ TP_STRUCT__entry(
+ __field(unsigned int, id)
+ __field(unsigned int, timestamp)
+ __field(uint64_t, ticks)
+ __field(int, prio)
+ ),
+ TP_fast_assign(
+ __entry->id = drawctxt->base.id;
+ __entry->timestamp = drawctxt->timestamp;
+ __entry->ticks = ticks;
+ __entry->prio = drawctxt->base.priority;
+ ),
+ TP_printk(
+ "ctx=%u ctx_prio=%d ts=%u ticks=%lld",
+ __entry->id, __entry->prio, __entry->timestamp,
+ __entry->ticks
+ )
+);
+
TRACE_EVENT(adreno_cmdbatch_fault,
TP_PROTO(struct kgsl_cmdbatch *cmdbatch, unsigned int fault),
TP_ARGS(cmdbatch, fault),
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c
index 49c0c3e..21ce1cf 100644
--- a/drivers/input/misc/powermate.c
+++ b/drivers/input/misc/powermate.c
@@ -308,6 +308,9 @@
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;
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 38eca8c..ef65db3 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -756,7 +756,8 @@
* dm-bufio is resistant to allocation failures (it just keeps
* one buffer reserved in cases all the allocations fail).
* So set flags to not try too hard:
- * GFP_NOIO: don't recurse into the I/O layer
+ * GFP_NOWAIT: don't wait; if we need to sleep we'll release our
+ * mutex and wait ourselves.
* __GFP_NORETRY: don't retry and rather return failure
* __GFP_NOMEMALLOC: don't use emergency reserves
* __GFP_NOWARN: don't print a warning in case of failure
@@ -766,7 +767,7 @@
*/
while (1) {
if (dm_bufio_cache_size_latch != 1) {
- b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
+ b = alloc_buffer(c, GFP_NOWAIT | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
if (b)
return b;
}
@@ -1442,20 +1443,20 @@
unsigned long r;
unsigned long nr_to_scan = sc->nr_to_scan;
- if (sc->gfp_mask & __GFP_IO)
- dm_bufio_lock(c);
- else if (!dm_bufio_trylock(c))
- return !nr_to_scan ? 0 : -1;
+ if (nr_to_scan) {
+ if (sc->gfp_mask & __GFP_IO)
+ dm_bufio_lock(c);
+ else if (!dm_bufio_trylock(c))
+ return -1;
- if (nr_to_scan)
__scan(c, nr_to_scan, sc);
+ dm_bufio_unlock(c);
+ }
- r = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];
+ r = ACCESS_ONCE(c->n_buffers[LIST_CLEAN]) + ACCESS_ONCE(c->n_buffers[LIST_DIRTY]);
if (r > INT_MAX)
r = INT_MAX;
- dm_bufio_unlock(c);
-
return r;
}
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 81a79b7..f21bc46 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1767,7 +1767,7 @@
if (r)
goto out;
- param->data_size = sizeof(*param);
+ param->data_size = offsetof(struct dm_ioctl, data);
r = fn(param, input_param_size);
if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) &&
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 490ab13..54e79f9 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
@@ -795,6 +795,12 @@
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);
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 6f5334a..5296b00 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -313,7 +313,7 @@
ispif->base + ISPIF_VFE_m_INTF_CMD_0(i));
msm_camera_io_w(ISPIF_STOP_INTF_IMMEDIATELY,
ispif->base + ISPIF_VFE_m_INTF_CMD_1(i));
- pr_debug("%s: base %lx", __func__, (unsigned long)ispif->base);
+ pr_debug("%s: base %pK", __func__, ispif->base);
msm_camera_io_w(0, ispif->base +
ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0));
msm_camera_io_w(0, ispif->base +
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 073b129..5b077c9 100755
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -1292,7 +1292,7 @@
{
struct msm_actuator_cfg_data *cdata =
(struct msm_actuator_cfg_data *)argp;
- int32_t rc = 0;
+ int32_t rc = -EINVAL;
mutex_lock(a_ctrl->actuator_mutex);
CDBG("Enter\n");
CDBG("%s type %d\n", __func__, cdata->cfgtype);
@@ -1305,6 +1305,7 @@
case CFG_GET_ACTUATOR_INFO:
cdata->is_af_supported = 1;
cdata->cfg.cam_name = a_ctrl->cam_name;
+ rc = 0;
break;
case CFG_SET_ACTUATOR_INFO:
@@ -1314,15 +1315,19 @@
break;
case CFG_SET_DEFAULT_FOCUS:
- rc = a_ctrl->func_tbl->actuator_set_default_focus(a_ctrl,
- &cdata->cfg.move);
+ if (a_ctrl->func_tbl &&
+ a_ctrl->func_tbl->actuator_set_default_focus)
+ rc = a_ctrl->func_tbl->actuator_set_default_focus(
+ a_ctrl, &cdata->cfg.move);
if (rc < 0)
pr_err("move focus failed %d\n", rc);
break;
case CFG_MOVE_FOCUS:
- rc = a_ctrl->func_tbl->actuator_move_focus(a_ctrl,
- &cdata->cfg.move);
+ if (a_ctrl->func_tbl &&
+ a_ctrl->func_tbl->actuator_move_focus)
+ rc = a_ctrl->func_tbl->actuator_move_focus(a_ctrl,
+ &cdata->cfg.move);
if (rc < 0)
pr_err("move focus failed %d\n", rc);
break;
@@ -1333,8 +1338,10 @@
break;
case CFG_SET_POSITION:
- rc = a_ctrl->func_tbl->actuator_set_position(a_ctrl,
- &cdata->cfg.setpos);
+ if (a_ctrl->func_tbl &&
+ a_ctrl->func_tbl->actuator_set_position)
+ rc = a_ctrl->func_tbl->actuator_set_position(a_ctrl,
+ &cdata->cfg.setpos);
if (rc < 0)
pr_err("actuator_set_position failed %d\n", rc);
break;
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 0c757b7..d496ff58f 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -42,6 +42,8 @@
#include "binder.h"
#include "binder_trace.h"
+#define BINDER_MIN_ALLOC (1 * PAGE_SIZE)
+
static DEFINE_MUTEX(binder_main_lock);
static DEFINE_MUTEX(binder_deferred_lock);
static DEFINE_MUTEX(binder_mmap_lock);
@@ -121,6 +123,7 @@
struct kernel_param *kp)
{
int ret;
+
ret = param_set_int(val, kp);
if (binder_stop_on_user_error < 2)
wake_up(&binder_user_error_wait);
@@ -209,6 +212,7 @@
struct binder_transaction_log *log)
{
struct binder_transaction_log_entry *e;
+
e = &log->entry[log->next];
memset(e, 0, sizeof(*e));
log->next++;
@@ -304,7 +308,7 @@
size_t data_size;
size_t offsets_size;
size_t extra_buffers_size;
- uint8_t data[0];
+ void *data;
};
enum binder_deferred_state {
@@ -524,6 +528,7 @@
static void binder_set_nice(long nice)
{
long min_nice;
+
if (can_nice(current, nice)) {
set_user_nice(current, nice);
return;
@@ -538,14 +543,23 @@
binder_user_error("%d RLIMIT_NICE not set\n", current->pid);
}
+static struct binder_buffer *binder_buffer_next(struct binder_buffer *buffer)
+{
+ return list_entry(buffer->entry.next, struct binder_buffer, entry);
+}
+
+static struct binder_buffer *binder_buffer_prev(struct binder_buffer *buffer)
+{
+ return list_entry(buffer->entry.prev, struct binder_buffer, entry);
+}
+
static size_t binder_buffer_size(struct binder_proc *proc,
struct binder_buffer *buffer)
{
if (list_is_last(&buffer->entry, &proc->buffers))
- return proc->buffer + proc->buffer_size - (void *)buffer->data;
- else
- return (size_t)list_entry(buffer->entry.next,
- struct binder_buffer, entry) - (size_t)buffer->data;
+ return (u8 *)proc->buffer +
+ proc->buffer_size - (u8 *)buffer->data;
+ return (u8 *)binder_buffer_next(buffer)->data - (u8 *)buffer->data;
}
static void binder_insert_free_buffer(struct binder_proc *proc,
@@ -595,9 +609,9 @@
buffer = rb_entry(parent, struct binder_buffer, rb_node);
BUG_ON(buffer->free);
- if (new_buffer < buffer)
+ if (new_buffer->data < buffer->data)
p = &parent->rb_left;
- else if (new_buffer > buffer)
+ else if (new_buffer->data > buffer->data)
p = &parent->rb_right;
else
BUG();
@@ -611,18 +625,17 @@
{
struct rb_node *n = proc->allocated_buffers.rb_node;
struct binder_buffer *buffer;
- struct binder_buffer *kern_ptr;
+ void *kern_ptr;
- kern_ptr = (struct binder_buffer *)(user_ptr - proc->user_buffer_offset
- - offsetof(struct binder_buffer, data));
+ kern_ptr = (void *)(user_ptr - proc->user_buffer_offset);
while (n) {
buffer = rb_entry(n, struct binder_buffer, rb_node);
BUG_ON(buffer->free);
- if (kern_ptr < buffer)
+ if (kern_ptr < buffer->data)
n = n->rb_left;
- else if (kern_ptr > buffer)
+ else if (kern_ptr > buffer->data)
n = n->rb_right;
else
return buffer;
@@ -630,9 +643,9 @@
return NULL;
}
-static int binder_update_page_range(struct binder_proc *proc, int allocate,
- void *start, void *end,
- struct vm_area_struct *vma)
+static int __binder_update_page_range(struct binder_proc *proc, int allocate,
+ void *start, void *end,
+ struct vm_area_struct *vma)
{
void *page_addr;
unsigned long user_page_addr;
@@ -678,6 +691,7 @@
for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {
int ret;
struct page **page_array_ptr;
+
page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
BUG_ON(*page);
@@ -741,6 +755,20 @@
return -ENOMEM;
}
+static int binder_update_page_range(struct binder_proc *proc, int allocate,
+ void *start, void *end,
+ struct vm_area_struct *vma)
+{
+ /*
+ * For regular updates, move up start if needed since MIN_ALLOC pages
+ * are always mapped
+ */
+ if (start - proc->buffer < BINDER_MIN_ALLOC)
+ start = proc->buffer + BINDER_MIN_ALLOC;
+
+ return __binder_update_page_range(proc, allocate, start, end, vma);
+}
+
static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
size_t data_size,
size_t offsets_size,
@@ -783,6 +811,9 @@
return NULL;
}
+ /* Pad 0-size buffers so they get assigned unique addresses */
+ size = max(size, sizeof(void *));
+
while (n) {
buffer = rb_entry(n, struct binder_buffer, rb_node);
BUG_ON(!buffer->free);
@@ -814,29 +845,32 @@
has_page_addr =
(void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK);
- if (n == NULL) {
- if (size + sizeof(struct binder_buffer) + 4 >= buffer_size)
- buffer_size = size; /* no room for other buffers */
- else
- buffer_size = size + sizeof(struct binder_buffer);
- }
+ WARN_ON(n && buffer_size != size);
end_page_addr =
- (void *)PAGE_ALIGN((uintptr_t)buffer->data + buffer_size);
+ (void *)PAGE_ALIGN((uintptr_t)buffer->data + size);
if (end_page_addr > has_page_addr)
end_page_addr = has_page_addr;
if (binder_update_page_range(proc, 1,
(void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL))
return NULL;
-
- rb_erase(best_fit, &proc->free_buffers);
- buffer->free = 0;
- binder_insert_allocated_buffer(proc, buffer);
if (buffer_size != size) {
- struct binder_buffer *new_buffer = (void *)buffer->data + size;
+ struct binder_buffer *new_buffer;
+
+ new_buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+ if (!new_buffer) {
+ pr_err("%s: %d failed to alloc new buffer struct\n",
+ __func__, proc->pid);
+ goto err_alloc_buf_struct_failed;
+ }
+ new_buffer->data = (u8 *)buffer->data + size;
list_add(&new_buffer->entry, &buffer->entry);
new_buffer->free = 1;
binder_insert_free_buffer(proc, new_buffer);
}
+
+ rb_erase(best_fit, &proc->free_buffers);
+ buffer->free = 0;
+ binder_insert_allocated_buffer(proc, buffer);
binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: binder_alloc_buf size %zd got %pK\n",
proc->pid, size, buffer);
@@ -852,61 +886,69 @@
}
return buffer;
+
+err_alloc_buf_struct_failed:
+ binder_update_page_range(proc, 0,
+ (void *)PAGE_ALIGN((uintptr_t)buffer->data),
+ end_page_addr, NULL);
+ return NULL;
}
static void *buffer_start_page(struct binder_buffer *buffer)
{
- return (void *)((uintptr_t)buffer & PAGE_MASK);
+ return (void *)((uintptr_t)buffer->data & PAGE_MASK);
}
-static void *buffer_end_page(struct binder_buffer *buffer)
+static void *prev_buffer_end_page(struct binder_buffer *buffer)
{
- return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK);
+ return (void *)(((uintptr_t)(buffer->data) - 1) & PAGE_MASK);
}
static void binder_delete_free_buffer(struct binder_proc *proc,
struct binder_buffer *buffer)
{
struct binder_buffer *prev, *next = NULL;
- int free_page_end = 1;
- int free_page_start = 1;
-
+ bool to_free = true;
BUG_ON(proc->buffers.next == &buffer->entry);
- prev = list_entry(buffer->entry.prev, struct binder_buffer, entry);
+ prev = binder_buffer_prev(buffer);
BUG_ON(!prev->free);
- if (buffer_end_page(prev) == buffer_start_page(buffer)) {
- free_page_start = 0;
- if (buffer_end_page(prev) == buffer_end_page(buffer))
- free_page_end = 0;
+ if (prev_buffer_end_page(prev) == buffer_start_page(buffer)) {
+ to_free = false;
binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: merge free, buffer %pK share page with %pK\n",
- proc->pid, buffer, prev);
+ proc->pid, buffer->data, prev->data);
}
if (!list_is_last(&buffer->entry, &proc->buffers)) {
- next = list_entry(buffer->entry.next,
- struct binder_buffer, entry);
- if (buffer_start_page(next) == buffer_end_page(buffer)) {
- free_page_end = 0;
- if (buffer_start_page(next) ==
- buffer_start_page(buffer))
- free_page_start = 0;
+ next = binder_buffer_next(buffer);
+ if (buffer_start_page(next) == buffer_start_page(buffer)) {
+ to_free = false;
binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: merge free, buffer %pK share page with %pK\n",
- proc->pid, buffer, prev);
+ proc->pid,
+ buffer->data,
+ next->data);
}
}
- list_del(&buffer->entry);
- if (free_page_start || free_page_end) {
+
+ if (PAGE_ALIGNED(buffer->data)) {
binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
- "%d: merge free, buffer %pK do not share page%s%s with %pK or %pK\n",
- proc->pid, buffer, free_page_start ? "" : " end",
- free_page_end ? "" : " start", prev, next);
- binder_update_page_range(proc, 0, free_page_start ?
- buffer_start_page(buffer) : buffer_end_page(buffer),
- (free_page_end ? buffer_end_page(buffer) :
- buffer_start_page(buffer)) + PAGE_SIZE, NULL);
+ "%d: merge free, buffer start %pK is page aligned\n",
+ proc->pid, buffer->data);
+ to_free = false;
}
+
+ if (to_free) {
+ binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
+ "%d: merge free, buffer %pK do not share page with %pK or %pK\n",
+ proc->pid, buffer->data,
+ prev->data, next->data);
+ binder_update_page_range(proc, 0, buffer_start_page(buffer),
+ buffer_start_page(buffer) + PAGE_SIZE,
+ NULL);
+ }
+ list_del(&buffer->entry);
+ kfree(buffer);
}
static void binder_free_buf(struct binder_proc *proc,
@@ -927,8 +969,8 @@
BUG_ON(buffer->free);
BUG_ON(size > buffer_size);
BUG_ON(buffer->transaction != NULL);
- BUG_ON((void *)buffer < proc->buffer);
- BUG_ON((void *)buffer > proc->buffer + proc->buffer_size);
+ BUG_ON(buffer->data < proc->buffer);
+ BUG_ON(buffer->data > proc->buffer + proc->buffer_size);
if (buffer->async_transaction) {
proc->free_async_space += size + sizeof(struct binder_buffer);
@@ -945,16 +987,16 @@
rb_erase(&buffer->rb_node, &proc->allocated_buffers);
buffer->free = 1;
if (!list_is_last(&buffer->entry, &proc->buffers)) {
- struct binder_buffer *next = list_entry(buffer->entry.next,
- struct binder_buffer, entry);
+ struct binder_buffer *next = binder_buffer_next(buffer);
+
if (next->free) {
rb_erase(&next->rb_node, &proc->free_buffers);
binder_delete_free_buffer(proc, next);
}
}
if (proc->buffers.next != &buffer->entry) {
- struct binder_buffer *prev = list_entry(buffer->entry.prev,
- struct binder_buffer, entry);
+ struct binder_buffer *prev = binder_buffer_prev(buffer);
+
if (prev->free) {
binder_delete_free_buffer(proc, buffer);
rb_erase(&prev->rb_node, &proc->free_buffers);
@@ -1223,6 +1265,7 @@
struct list_head *target_list)
{
int ret;
+
if (strong) {
if (ref->strong == 0) {
ret = binder_inc_node(ref->node, 1, 1, target_list);
@@ -1255,6 +1298,7 @@
ref->strong--;
if (ref->strong == 0) {
int ret;
+
ret = binder_dec_node(ref->node, strong, 1);
if (ret)
return ret;
@@ -1296,6 +1340,7 @@
uint32_t error_code)
{
struct binder_thread *target_thread;
+
BUG_ON(t->flags & TF_ONE_WAY);
while (1) {
target_thread = t->from;
@@ -1960,6 +2005,7 @@
} else {
if (tr->target.handle) {
struct binder_ref *ref;
+
ref = binder_get_ref(proc, tr->target.handle, true);
if (ref == NULL) {
binder_user_error("%d:%d got transaction to invalid handle\n",
@@ -1987,6 +2033,7 @@
}
if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
struct binder_transaction *tmp;
+
tmp = thread->transaction_stack;
if (tmp->to_thread != thread) {
binder_user_error("%d:%d got new transaction with bad transaction stack, transaction %d has target %d:%d\n",
@@ -2299,6 +2346,7 @@
{
struct binder_transaction_log_entry *fe;
+
fe = binder_transaction_log_add(&binder_transaction_log_failed);
*fe = *e;
}
@@ -2650,12 +2698,14 @@
struct binder_work *w;
binder_uintptr_t cookie;
struct binder_ref_death *death = NULL;
+
if (get_user_preempt_disabled(cookie, (binder_uintptr_t __user *)ptr))
return -EFAULT;
ptr += sizeof(void *);
list_for_each_entry(w, &proc->delivered_death, entry) {
struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
+
if (tmp_death->cookie == cookie) {
death = tmp_death;
break;
@@ -2841,6 +2891,7 @@
const char *cmd_name;
int strong = node->internal_strong_refs || node->local_strong_refs;
int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong;
+
if (weak && !node->has_weak_ref) {
cmd = BR_INCREFS;
cmd_name = "BR_INCREFS";
@@ -2943,6 +2994,7 @@
BUG_ON(t->buffer == NULL);
if (t->buffer->target_node) {
struct binder_node *target_node = t->buffer->target_node;
+
tr.target.ptr = target_node->ptr;
tr.cookie = target_node->cookie;
t->saved_priority = task_nice(current);
@@ -2964,6 +3016,7 @@
if (t->from) {
struct task_struct *sender = t->from->proc->tsk;
+
tr.sender_pid = task_tgid_nr_ns(sender,
task_active_pid_ns(current));
} else {
@@ -3034,6 +3087,7 @@
static void binder_release_work(struct list_head *list)
{
struct binder_work *w;
+
while (!list_empty(list)) {
w = list_first_entry(list, struct binder_work, entry);
list_del_init(&w->entry);
@@ -3215,6 +3269,7 @@
switch (cmd) {
case BINDER_WRITE_READ: {
struct binder_write_read bwr;
+
if (size != sizeof(struct binder_write_read)) {
ret = -EINVAL;
goto err;
@@ -3334,6 +3389,7 @@
static void binder_vma_open(struct vm_area_struct *vma)
{
struct binder_proc *proc = vma->vm_private_data;
+
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
"%d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
proc->pid, vma->vm_start, vma->vm_end,
@@ -3344,6 +3400,7 @@
static void binder_vma_close(struct vm_area_struct *vma)
{
struct binder_proc *proc = vma->vm_private_data;
+
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
"%d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n",
proc->pid, vma->vm_start, vma->vm_end,
@@ -3429,17 +3486,24 @@
vma->vm_ops = &binder_vm_ops;
vma->vm_private_data = proc;
+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+ if (!buffer) {
+ ret = -ENOMEM;
+ failure_string = "alloc buffer struct";
+ goto err_alloc_buf_struct_failed;
+ }
+
/* binder_update_page_range assumes preemption is disabled */
preempt_disable();
- ret = binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma);
+ ret = __binder_update_page_range(proc, 1, proc->buffer,
+ proc->buffer + BINDER_MIN_ALLOC, vma);
preempt_enable_no_resched();
if (ret) {
ret = -ENOMEM;
failure_string = "alloc small buf";
goto err_alloc_small_buf_failed;
}
- buffer = proc->buffer;
- INIT_LIST_HEAD(&proc->buffers);
+ buffer->data = proc->buffer;
list_add(&buffer->entry, &proc->buffers);
buffer->free = 1;
binder_insert_free_buffer(proc, buffer);
@@ -3454,6 +3518,8 @@
return 0;
err_alloc_small_buf_failed:
+ kfree(buffer);
+err_alloc_buf_struct_failed:
kfree(proc->pages);
proc->pages = NULL;
err_alloc_pages_failed:
@@ -3488,6 +3554,7 @@
binder_dev = container_of(filp->private_data, struct binder_device,
miscdev);
proc->context = &binder_dev->context;
+ INIT_LIST_HEAD(&proc->buffers);
binder_lock(__func__);
@@ -3501,6 +3568,7 @@
if (binder_debugfs_dir_entry_proc) {
char strbuf[11];
+
snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
/*
* proc debug entries are shared between contexts, so
@@ -3531,8 +3599,10 @@
{
struct rb_node *n;
int wake_count = 0;
+
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
+
thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
if (thread->looper & BINDER_LOOPER_STATE_WAITING) {
wake_up_interruptible(&thread->wait);
@@ -3549,6 +3619,7 @@
static int binder_release(struct inode *nodp, struct file *filp)
{
struct binder_proc *proc = filp->private_data;
+
debugfs_remove(proc->debugfs_entry);
binder_defer_work(proc, BINDER_DEFERRED_RELEASE);
@@ -3604,6 +3675,7 @@
struct binder_transaction *t;
struct binder_context *context = proc->context;
struct rb_node *n;
+ struct binder_buffer *buffer;
int threads, nodes, incoming_refs, outgoing_refs, buffers,
active_transactions, page_count;
@@ -3655,8 +3727,6 @@
buffers = 0;
while ((n = rb_first(&proc->allocated_buffers))) {
- struct binder_buffer *buffer;
-
buffer = rb_entry(n, struct binder_buffer, rb_node);
t = buffer->transaction;
@@ -3674,6 +3744,16 @@
binder_stats_deleted(BINDER_STAT_PROC);
+ while (!list_empty(&proc->buffers)) {
+ buffer = list_first_entry(&proc->buffers,
+ struct binder_buffer, entry);
+ WARN_ON(!buffer->free);
+
+ list_del(&buffer->entry);
+ WARN_ON_ONCE(!list_empty(&proc->buffers));
+ kfree(buffer);
+ }
+
page_count = 0;
if (proc->pages) {
int i;
@@ -3712,6 +3792,7 @@
struct files_struct *files;
int defer;
+
do {
trace_binder_lock(__func__);
mutex_lock(&binder_main_lock);
diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h
index 23d9680..f93fc8a 100644
--- a/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h
+++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h
@@ -42,9 +42,9 @@
#define QWLAN_VERSION_MINOR 4
#define QWLAN_VERSION_PATCH 23
#define QWLAN_VERSION_EXTRA ""
-#define QWLAN_VERSION_BUILD 20
+#define QWLAN_VERSION_BUILD 21
-#define QWLAN_VERSIONSTR "4.4.23.020"
+#define QWLAN_VERSIONSTR "4.4.23.021"
#define AR6320_REV1_VERSION 0x5000000
diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h
index c5d8ad5..280020f 100644
--- a/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h
+++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirMacProtDef.h
@@ -587,6 +587,10 @@
#define SIR_MAC_AUTH_CHALLENGE_LENGTH 253
#define SIR_MAC_WEP_IV_LENGTH 4
#define SIR_MAC_WEP_ICV_LENGTH 4
+#define SIR_MAC_CHALLENGE_ID_LEN 2
+
+/* 2 bytes each for auth algo number, transaction number and status code */
+#define SIR_MAC_AUTH_FRAME_INFO_LEN 6
/// MAX key length when ULA is used
#define SIR_MAC_MAX_KEY_LENGTH 32
diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAuthFrame.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAuthFrame.c
index 61028ec..921a944 100644
--- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAuthFrame.c
+++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAuthFrame.c
@@ -147,8 +147,8 @@
{
tANI_U8 *pBody, keyId, cfgPrivacyOptImp,
defaultKey[SIR_MAC_KEY_LENGTH],
- encrAuthFrame[LIM_ENCR_AUTH_BODY_LEN],
- plainBody[256];
+ *encrAuthFrame = NULL,
+ plainBody[LIM_ENCR_AUTH_BODY_LEN];
tANI_U16 frameLen;
tANI_U32 maxNumPreAuth, val;
tSirMacAuthFrameBody *pRxAuthFrameBody, rxAuthFrame, authFrame;
@@ -1280,10 +1280,18 @@
sirSwapU16ifNeeded((tANI_U16) (pRxAuthFrameBody->authTransactionSeqNumber + 1));
((tpSirMacAuthFrameBody) plainBody)->authStatusCode = eSIR_MAC_SUCCESS_STATUS;
((tpSirMacAuthFrameBody) plainBody)->type = SIR_MAC_CHALLENGE_TEXT_EID;
- ((tpSirMacAuthFrameBody) plainBody)->length = SIR_MAC_AUTH_CHALLENGE_LENGTH;
+ ((tpSirMacAuthFrameBody) plainBody)->length = pRxAuthFrameBody->length;
vos_mem_copy((tANI_U8 *) ((tpSirMacAuthFrameBody) plainBody)->challengeText,
pRxAuthFrameBody->challengeText,
- SIR_MAC_AUTH_CHALLENGE_LENGTH);
+ pRxAuthFrameBody->length);
+ encrAuthFrame = vos_mem_malloc(pRxAuthFrameBody->length +
+ LIM_ENCR_AUTH_INFO_LEN);
+ if (!encrAuthFrame) {
+ limLog(pMac, LOGE, FL("failed to allocate memory"));
+ goto free;
+ }
+ vos_mem_set(encrAuthFrame, pRxAuthFrameBody->length +
+ LIM_ENCR_AUTH_INFO_LEN, 0);
limEncryptAuthFrame(pMac, 0,
pKeyMapEntry->key,
@@ -1296,7 +1304,7 @@
limSendAuthMgmtFrame(pMac,
(tpSirMacAuthFrameBody) encrAuthFrame,
pHdr->sa,
- LIM_WEP_IN_FC,
+ pRxAuthFrameBody->length,
psessionEntry,
eSIR_FALSE);
@@ -1357,10 +1365,19 @@
sirSwapU16ifNeeded((tANI_U16) (pRxAuthFrameBody->authTransactionSeqNumber + 1));
((tpSirMacAuthFrameBody) plainBody)->authStatusCode = eSIR_MAC_SUCCESS_STATUS;
((tpSirMacAuthFrameBody) plainBody)->type = SIR_MAC_CHALLENGE_TEXT_EID;
- ((tpSirMacAuthFrameBody) plainBody)->length = SIR_MAC_AUTH_CHALLENGE_LENGTH;
+ ((tpSirMacAuthFrameBody) plainBody)->length = pRxAuthFrameBody->length;
vos_mem_copy((tANI_U8 *) ((tpSirMacAuthFrameBody) plainBody)->challengeText,
pRxAuthFrameBody->challengeText,
- SIR_MAC_AUTH_CHALLENGE_LENGTH);
+ pRxAuthFrameBody->length);
+
+ encrAuthFrame = vos_mem_malloc(pRxAuthFrameBody->length +
+ LIM_ENCR_AUTH_INFO_LEN);
+ if (!encrAuthFrame) {
+ limLog(pMac, LOGE, FL("failed to allocate memory"));
+ goto free;
+ }
+ vos_mem_set(encrAuthFrame, pRxAuthFrameBody->length +
+ LIM_ENCR_AUTH_INFO_LEN, 0);
limEncryptAuthFrame(pMac, keyId,
defaultKey,
@@ -1374,7 +1391,7 @@
limSendAuthMgmtFrame(pMac,
(tpSirMacAuthFrameBody) encrAuthFrame,
pHdr->sa,
- LIM_WEP_IN_FC,
+ pRxAuthFrameBody->length,
psessionEntry,
eSIR_FALSE);
@@ -1754,6 +1771,9 @@
break;
} // end switch (pRxAuthFrameBody->authTransactionSeqNumber)
+free:
+ if (encrAuthFrame)
+ vos_mem_free(encrAuthFrame);
} /*** end limProcessAuthFrame() ***/
diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c
index 049c86a..4849eb2 100644
--- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c
+++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.c
@@ -534,8 +534,6 @@
(tANI_U32 *) &mlmAuthCnf);
} /*** end limRestoreFromAuthState() ***/
-
-
/**
* limLookUpKeyMappings()
*
@@ -595,7 +593,10 @@
tANI_U8 *pEncrBody, tANI_U32 keyLength)
{
tANI_U8 seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH];
+ tANI_U16 framelen;
+ framelen = ((tpSirMacAuthFrameBody)pPlainText)->length +
+ SIR_MAC_AUTH_FRAME_INFO_LEN + SIR_MAC_CHALLENGE_ID_LEN;
keyLength += 3;
// Bytes 0-2 of seed is IV
@@ -606,15 +607,15 @@
vos_mem_copy((tANI_U8 *) &seed[3], pKey, keyLength - 3);
// Compute CRC-32 and place them in last 4 bytes of plain text
- limComputeCrc32(icv, pPlainText, sizeof(tSirMacAuthFrameBody));
+ limComputeCrc32(icv, pPlainText, framelen);
- vos_mem_copy( pPlainText + sizeof(tSirMacAuthFrameBody),
+ vos_mem_copy( pPlainText + framelen,
icv, SIR_MAC_WEP_ICV_LENGTH);
// Run RC4 on plain text with the seed
limRC4(pEncrBody + SIR_MAC_WEP_IV_LENGTH,
(tANI_U8 *) pPlainText, seed, keyLength,
- LIM_ENCR_AUTH_BODY_LEN - SIR_MAC_WEP_IV_LENGTH);
+ framelen + SIR_MAC_WEP_IV_LENGTH);
// Prepare IV
pEncrBody[0] = seed[0];
@@ -734,7 +735,7 @@
{
tANI_U8 i = ctx.i;
tANI_U8 j = ctx.j;
- tANI_U8 len = (tANI_U8) frameLen;
+ tANI_U16 len = frameLen;
while (len-- > 0)
{
@@ -816,7 +817,7 @@
// Compute CRC-32 and place them in last 4 bytes of encrypted body
limComputeCrc32(icv,
(tANI_U8 *) pPlainBody,
- (tANI_U8) (frameLen - SIR_MAC_WEP_ICV_LENGTH));
+ (frameLen - SIR_MAC_WEP_ICV_LENGTH));
// Compare RX_ICV with computed ICV
for (i = 0; i < SIR_MAC_WEP_ICV_LENGTH; i++)
diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h
index 9139ce2..4fb961c 100644
--- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h
+++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSecurityUtils.h
@@ -42,6 +42,12 @@
#define LIM_ENCR_AUTH_BODY_LEN (sizeof(tSirMacAuthFrameBody) + \
SIR_MAC_WEP_IV_LENGTH + \
SIR_MAC_WEP_ICV_LENGTH)
+
+#define LIM_ENCR_AUTH_INFO_LEN (SIR_MAC_AUTH_FRAME_INFO_LEN +\
+ SIR_MAC_WEP_IV_LENGTH + \
+ SIR_MAC_WEP_ICV_LENGTH + \
+ SIR_MAC_CHALLENGE_ID_LEN)
+
struct tLimPreAuthNode;
tANI_U8 limIsAuthAlgoSupported(tpAniSirGlobal, tAniAuthType, tpPESession);
diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c
index 60e1632..aaa8803 100644
--- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c
+++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c
@@ -3328,7 +3328,7 @@
limSendAuthMgmtFrame(tpAniSirGlobal pMac,
tpSirMacAuthFrameBody pAuthFrameBody,
tSirMacAddr peerMacAddr,
- tANI_U8 wepBit,
+ tANI_U8 wep_challenge_len,
tpPESession psessionEntry,
tAniBool waitForAck)
{
@@ -3355,7 +3355,7 @@
pAuthFrameBody->authStatusCode,
(pAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS),
MAC_ADDR_ARRAY(peerMacAddr));
- if (wepBit == LIM_WEP_IN_FC)
+ if (wep_challenge_len)
{
/// Auth frame3 to be sent with encrypted framebody
/**
@@ -3366,9 +3366,9 @@
* IV & ICV.
*/
- frameLen = sizeof(tSirMacMgmtHdr) + LIM_ENCR_AUTH_BODY_LEN;
+ bodyLen = wep_challenge_len + LIM_ENCR_AUTH_INFO_LEN;
+ frameLen = sizeof(tSirMacMgmtHdr) + bodyLen;
- bodyLen = LIM_ENCR_AUTH_BODY_LEN;
} // if (wepBit == LIM_WEP_IN_FC)
else
{
@@ -3499,7 +3499,10 @@
}
pMacHdr = ( tpSirMacMgmtHdr ) pFrame;
- pMacHdr->fc.wep = wepBit;
+ if (wep_challenge_len)
+ pMacHdr->fc.wep = LIM_WEP_IN_FC;
+ else
+ pMacHdr->fc.wep = LIM_NO_WEP_IN_FC;
// Prepare BSSId
if (LIM_IS_AP_ROLE(psessionEntry) ||
@@ -3512,7 +3515,7 @@
/// Prepare Authentication frame body
pBody = pFrame + sizeof(tSirMacMgmtHdr);
- if (wepBit == LIM_WEP_IN_FC)
+ if (wep_challenge_len)
{
vos_mem_copy(pBody, (tANI_U8 *) pAuthFrameBody, bodyLen);
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 11b96af..16dc788 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -461,11 +461,15 @@
int usb_driver_claim_interface(struct usb_driver *driver,
struct usb_interface *iface, void *priv)
{
- struct device *dev = &iface->dev;
+ struct device *dev;
struct usb_device *udev;
int retval = 0;
int lpm_disable_error;
+ if (!iface)
+ return -ENODEV;
+
+ dev = &iface->dev;
if (dev->driver)
return -EBUSY;
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index d36f34e..4c24ba0 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -792,6 +792,12 @@
iface_desc = interface->cur_altsetting;
dev->product_id = le16_to_cpu(udev->descriptor.idProduct);
+ if (iface_desc->desc.bNumEndpoints < 1) {
+ dev_err(&interface->dev, "Invalid number of endpoints\n");
+ retval = -EINVAL;
+ goto error;
+ }
+
/* set up the endpoint information */
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 0821201..09f0f63 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -449,6 +449,11 @@
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 @@
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,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 6a15adf..c14c29f 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -377,14 +377,21 @@
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);
diff --git a/fs/namespace.c b/fs/namespace.c
index b015932..d7e655a 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -188,6 +188,7 @@
mnt->mnt_count = 1;
mnt->mnt_writers = 0;
#endif
+ mnt->mnt.data = NULL;
INIT_LIST_HEAD(&mnt->mnt_hash);
INIT_LIST_HEAD(&mnt->mnt_child);
@@ -785,7 +786,6 @@
if (!mnt)
return ERR_PTR(-ENOMEM);
- mnt->mnt.data = NULL;
if (type->alloc_mnt_data) {
mnt->mnt.data = type->alloc_mnt_data();
if (!mnt->mnt.data) {
@@ -799,7 +799,6 @@
root = mount_fs(type, flags, name, &mnt->mnt, data);
if (IS_ERR(root)) {
- kfree(mnt->mnt.data);
free_vfsmnt(mnt);
return ERR_CAST(root);
}
@@ -897,7 +896,6 @@
return mnt;
out_free:
- kfree(mnt->mnt.data);
free_vfsmnt(mnt);
return ERR_PTR(err);
}
diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c
index 8a42e01..5ee3dab 100755
--- a/fs/sdcardfs/derived_perm.c
+++ b/fs/sdcardfs/derived_perm.c
@@ -175,6 +175,9 @@
gid_t gid = sbi->options.fs_low_gid;
struct iattr newattrs;
+ if (!sbi->options.gid_derivation)
+ return;
+
info = SDCARDFS_I(dentry->d_inode);
info_d = info->data;
perm = info_d->perm;
diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c
index f4d6c08..c7fe86f8 100755
--- a/fs/sdcardfs/inode.c
+++ b/fs/sdcardfs/inode.c
@@ -34,10 +34,14 @@
if (!cred)
return NULL;
- if (data->under_obb)
- uid = AID_MEDIA_OBB;
- else
- uid = multiuser_get_uid(data->userid, sbi->options.fs_low_uid);
+ if (sbi->options.gid_derivation) {
+ if (data->under_obb)
+ uid = AID_MEDIA_OBB;
+ else
+ uid = multiuser_get_uid(data->userid, sbi->options.fs_low_uid);
+ } else {
+ uid = sbi->options.fs_low_uid;
+ }
cred->fsuid = uid;
cred->fsgid = sbi->options.fs_low_gid;
@@ -778,13 +782,9 @@
* afterwards in the other cases: we fsstack_copy_inode_size from
* the lower level.
*/
- if (current->mm)
- down_write(¤t->mm->mmap_sem);
if (ia->ia_valid & ATTR_SIZE) {
err = inode_newsize_ok(&tmp, ia->ia_size);
if (err) {
- if (current->mm)
- up_write(¤t->mm->mmap_sem);
goto out;
}
truncate_setsize(inode, ia->ia_size);
@@ -807,8 +807,6 @@
err = notify_change2(lower_mnt, lower_dentry, &lower_ia); /* note: lower_ia */
mutex_unlock(&lower_dentry->d_inode->i_mutex);
- if (current->mm)
- up_write(¤t->mm->mmap_sem);
if (err)
goto out;
diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c
index 129d98e..2a75f74 100755
--- a/fs/sdcardfs/main.c
+++ b/fs/sdcardfs/main.c
@@ -32,6 +32,7 @@
Opt_multiuser,
Opt_userid,
Opt_reserved_mb,
+ Opt_gid_derivation,
Opt_err,
};
@@ -43,6 +44,7 @@
{Opt_mask, "mask=%u"},
{Opt_userid, "userid=%d"},
{Opt_multiuser, "multiuser"},
+ {Opt_gid_derivation, "derive_gid"},
{Opt_reserved_mb, "reserved_mb=%u"},
{Opt_err, NULL}
};
@@ -64,6 +66,8 @@
vfsopts->gid = 0;
/* by default, 0MB is reserved */
opts->reserved_mb = 0;
+ /* by default, gid derivation is off */
+ opts->gid_derivation = false;
*debug = 0;
@@ -115,6 +119,9 @@
return 0;
opts->reserved_mb = option;
break;
+ case Opt_gid_derivation:
+ opts->gid_derivation = true;
+ break;
/* unknown option */
default:
if (!silent)
diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h
index 3874d40..9389f73 100755
--- a/fs/sdcardfs/sdcardfs.h
+++ b/fs/sdcardfs/sdcardfs.h
@@ -217,6 +217,7 @@
gid_t fs_low_gid;
userid_t fs_user_id;
bool multiuser;
+ bool gid_derivation;
unsigned int reserved_mb;
};
diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c
index 7f4539b..b89947d 100755
--- a/fs/sdcardfs/super.c
+++ b/fs/sdcardfs/super.c
@@ -302,6 +302,8 @@
seq_printf(m, ",mask=%u", vfsopts->mask);
if (opts->fs_user_id)
seq_printf(m, ",userid=%u", opts->fs_user_id);
+ if (opts->gid_derivation)
+ seq_puts(m, ",derive_gid");
if (opts->reserved_mb != 0)
seq_printf(m, ",reserved=%uMB", opts->reserved_mb);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index fb3b142..fab7c07 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -70,6 +70,9 @@
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)
+/* test whether an address (unsigned long or pointer) is aligned to PAGE_SIZE */
+#define PAGE_ALIGNED(addr) IS_ALIGNED((unsigned long)addr, PAGE_SIZE)
+
/*
* Linux kernel virtual memory manager primitives.
* The idea being to have a "virtual" mm in the same way
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 7f5a08b..e7dd9469 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1153,13 +1153,15 @@
break;
case 'a':
{
- unsigned long long addr = *((phys_addr_t *)ptr);
+ unsigned long long addr;
+ if (fmt[1] != 'P' && kptr_restrict_cleanse_addresses())
+ addr = 0;
+ else
+ addr = *((phys_addr_t *)ptr);
spec.flags |= SPECIAL | SMALL | ZEROPAD;
spec.field_width = sizeof(phys_addr_t) * 2 + 2;
spec.base = 16;
- return number(buf, end,
- kptr_restrict_cleanse_addresses() ? 0UL : addr,
- spec);
+ return number(buf, end, addr, spec);
}
case 'P':
/*
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 4ec3427..8ff6a99 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -338,7 +338,8 @@
be32_to_cpu(tunnel->parms.o_key), RT_TOS(tos),
RT_SCOPE_UNIVERSE,
IPPROTO_IPIP, 0,
- dst, tiph->saddr, 0, 0);
+ dst, tiph->saddr, 0, 0,
+ sock_net_uid(dev_net(dev), NULL));
rt = ip_route_output_key(dev_net(dev), &fl4);
if (IS_ERR(rt)) {
dev->stats.tx_carrier_errors++;
@@ -405,7 +406,8 @@
be32_to_cpu(tunnel->parms.i_key),
RT_TOS(iph->tos), RT_SCOPE_UNIVERSE,
IPPROTO_IPIP, 0,
- iph->daddr, iph->saddr, 0, 0);
+ iph->daddr, iph->saddr, 0, 0,
+ sock_net_uid(dev_net(dev), NULL));
rt = ip_route_output_key(dev_net(dev), &fl4);
if (!IS_ERR(rt)) {
tdev = rt->dst.dev;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index bbb634c..5482090 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -65,6 +65,10 @@
} dump;
};
+static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
+ xfrm_address_t *saddr, xfrm_address_t *daddr,
+ u16 *family);
+
static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
{
return (struct pfkey_sock *)sk;
@@ -1900,19 +1904,14 @@
/* addresses present only in tunnel mode */
if (t->mode == XFRM_MODE_TUNNEL) {
- u8 *sa = (u8 *) (rq + 1);
- int family, socklen;
+ int err;
- family = pfkey_sockaddr_extract((struct sockaddr *)sa,
- &t->saddr);
- if (!family)
- return -EINVAL;
-
- socklen = pfkey_sockaddr_len(family);
- if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen),
- &t->id.daddr) != family)
- return -EINVAL;
- t->encap_family = family;
+ err = parse_sockaddr_pair(
+ (struct sockaddr *)(rq + 1),
+ rq->sadb_x_ipsecrequest_len - sizeof(*rq),
+ &t->saddr, &t->id.daddr, &t->encap_family);
+ if (err)
+ return err;
} else
t->encap_family = xp->family;
@@ -1932,7 +1931,11 @@
if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy))
return -EINVAL;
- while (len >= sizeof(struct sadb_x_ipsecrequest)) {
+ while (len >= sizeof(*rq)) {
+ if (len < rq->sadb_x_ipsecrequest_len ||
+ rq->sadb_x_ipsecrequest_len < sizeof(*rq))
+ return -EINVAL;
+
if ((err = parse_ipsecrequest(xp, rq)) < 0)
return err;
len -= rq->sadb_x_ipsecrequest_len;
@@ -2403,7 +2406,6 @@
return err;
}
-#ifdef CONFIG_NET_KEY_MIGRATE
static int pfkey_sockaddr_pair_size(sa_family_t family)
{
return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2);
@@ -2415,7 +2417,7 @@
{
int af, socklen;
- if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
+ if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
return -EINVAL;
af = pfkey_sockaddr_extract(sa, saddr);
@@ -2431,6 +2433,7 @@
return 0;
}
+#ifdef CONFIG_NET_KEY_MIGRATE
static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
struct xfrm_migrate *m)
{
@@ -2438,13 +2441,14 @@
struct sadb_x_ipsecrequest *rq2;
int mode;
- if (len <= sizeof(struct sadb_x_ipsecrequest) ||
- len < rq1->sadb_x_ipsecrequest_len)
+ if (len < sizeof(*rq1) ||
+ len < rq1->sadb_x_ipsecrequest_len ||
+ rq1->sadb_x_ipsecrequest_len < sizeof(*rq1))
return -EINVAL;
/* old endoints */
err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1),
- rq1->sadb_x_ipsecrequest_len,
+ rq1->sadb_x_ipsecrequest_len - sizeof(*rq1),
&m->old_saddr, &m->old_daddr,
&m->old_family);
if (err)
@@ -2453,13 +2457,14 @@
rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len);
len -= rq1->sadb_x_ipsecrequest_len;
- if (len <= sizeof(struct sadb_x_ipsecrequest) ||
- len < rq2->sadb_x_ipsecrequest_len)
+ if (len <= sizeof(*rq2) ||
+ len < rq2->sadb_x_ipsecrequest_len ||
+ rq2->sadb_x_ipsecrequest_len < sizeof(*rq2))
return -EINVAL;
/* new endpoints */
err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1),
- rq2->sadb_x_ipsecrequest_len,
+ rq2->sadb_x_ipsecrequest_len - sizeof(*rq2),
&m->new_saddr, &m->new_daddr,
&m->new_family);
if (err)
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index 0642f32..3de070c 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -1652,6 +1652,7 @@
struct sock *sk;
uid_t sock_uid;
bool res;
+ bool set_sk_callback_lock = false;
/*
* TODO: unhack how to force just accounting.
* For now we only do tag stats when the uid-owner is not requested
@@ -1713,16 +1714,9 @@
}
MT_DEBUG("qtaguid[%d]: sk=%p got_sock=%d fam=%d proto=%d\n",
par->hooknum, sk, got_sock, par->family, ipx_proto(skb, par));
- if (sk != NULL) {
- MT_DEBUG("qtaguid[%d]: sk=%p->sk_socket=%p->file=%p\n",
- par->hooknum, sk, sk->sk_socket,
- sk->sk_socket ? sk->sk_socket->file : (void *)-1LL);
- filp = sk->sk_socket ? sk->sk_socket->file : NULL;
- MT_DEBUG("qtaguid[%d]: filp...uid=%u\n",
- par->hooknum, filp ? filp->f_cred->fsuid : -1);
- }
- if (sk == NULL || sk->sk_socket == NULL) {
+
+ if (sk == NULL) {
/*
* Here, the qtaguid_find_sk() using connection tracking
* couldn't find the owner, so for now we just count them
@@ -1730,9 +1724,7 @@
*/
if (do_tag_stat)
account_for_uid(skb, sk, 0, par);
- MT_DEBUG("qtaguid[%d]: leaving (sk?sk->sk_socket)=%p\n",
- par->hooknum,
- sk ? sk->sk_socket : NULL);
+ MT_DEBUG("qtaguid[%d]: leaving (sk=NULL)\n", par->hooknum);
res = (info->match ^ info->invert) == 0;
atomic64_inc(&qtu_events.match_no_sk);
goto put_sock_ret_res;
@@ -1740,19 +1732,10 @@
res = false;
goto put_sock_ret_res;
}
- filp = sk->sk_socket->file;
- if (filp == NULL) {
- MT_DEBUG("qtaguid[%d]: leaving filp=NULL\n", par->hooknum);
- if (do_tag_stat)
- account_for_uid(skb, sk, 0, par);
- res = ((info->match ^ info->invert) &
- (XT_QTAGUID_UID | XT_QTAGUID_GID)) == 0;
- atomic64_inc(&qtu_events.match_no_sk_file);
- goto put_sock_ret_res;
- }
- sock_uid = filp->f_cred->fsuid;
+ sock_uid = sk->sk_uid;
if (do_tag_stat)
- account_for_uid(skb, sk, sock_uid, par);
+ account_for_uid(skb, sk, from_kuid(&init_user_ns, sock_uid),
+ par);
/*
* The following two tests fail the match when:
@@ -1760,31 +1743,54 @@
* or id in range AND inverted condition requested
* Thus (!a && b) || (a && !b) == a ^ b
*/
- if (info->match & XT_QTAGUID_UID)
- if ((filp->f_cred->fsuid >= info->uid_min &&
- filp->f_cred->fsuid <= info->uid_max) ^
+ if (info->match & XT_QTAGUID_UID) {
+ kuid_t uid_min = make_kuid(&init_user_ns, info->uid_min);
+ kuid_t uid_max = make_kuid(&init_user_ns, info->uid_max);
+
+ if ((uid_gte(sk->sk_uid, uid_min) &&
+ uid_lte(sk->sk_uid, uid_max)) ^
!(info->invert & XT_QTAGUID_UID)) {
MT_DEBUG("qtaguid[%d]: leaving uid not matching\n",
par->hooknum);
res = false;
goto put_sock_ret_res;
}
- if (info->match & XT_QTAGUID_GID)
- if ((filp->f_cred->fsgid >= info->gid_min &&
- filp->f_cred->fsgid <= info->gid_max) ^
+ }
+ if (info->match & XT_QTAGUID_GID) {
+ kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min);
+ kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max);
+ set_sk_callback_lock = true;
+ read_lock_bh(&sk->sk_callback_lock);
+ MT_DEBUG("qtaguid[%d]: sk=%p->sk_socket=%p->file=%p\n",
+ par->hooknum, sk, sk->sk_socket,
+ sk->sk_socket ? sk->sk_socket->file : (void *)-1LL);
+ filp = sk->sk_socket ? sk->sk_socket->file : NULL;
+ if (!filp) {
+ res = ((info->match ^ info->invert) &
+ XT_QTAGUID_GID) == 0;
+ atomic64_inc(&qtu_events.match_no_sk_gid);
+ goto put_sock_ret_res;
+ }
+ MT_DEBUG("qtaguid[%d]: filp...uid=%u\n",
+ par->hooknum, filp ?
+ from_kuid(&init_user_ns, filp->f_cred->fsuid) : -1);
+ if ((gid_gte(filp->f_cred->fsgid, gid_min) &&
+ gid_lte(filp->f_cred->fsgid, gid_max)) ^
!(info->invert & XT_QTAGUID_GID)) {
MT_DEBUG("qtaguid[%d]: leaving gid not matching\n",
par->hooknum);
res = false;
goto put_sock_ret_res;
}
-
+ }
MT_DEBUG("qtaguid[%d]: leaving matched\n", par->hooknum);
res = true;
put_sock_ret_res:
if (got_sock)
xt_socket_put_sk(sk);
+ if (set_sk_callback_lock)
+ read_unlock_bh(&sk->sk_callback_lock);
ret_res:
MT_DEBUG("qtaguid[%d]: left %d\n", par->hooknum, res);
return res;
@@ -1939,7 +1945,7 @@
"match_found_sk_in_ct=%llu "
"match_found_no_sk_in_ct=%llu "
"match_no_sk=%llu "
- "match_no_sk_file=%llu\n",
+ "match_no_sk_gid=%llu\n",
(u64)atomic64_read(&qtu_events.sockets_tagged),
(u64)atomic64_read(&qtu_events.sockets_untagged),
(u64)atomic64_read(&qtu_events.counter_set_changes),
@@ -1951,7 +1957,7 @@
(u64)atomic64_read(&qtu_events.match_found_sk_in_ct),
(u64)atomic64_read(&qtu_events.match_found_no_sk_in_ct),
(u64)atomic64_read(&qtu_events.match_no_sk),
- (u64)atomic64_read(&qtu_events.match_no_sk_file));
+ (u64)atomic64_read(&qtu_events.match_no_sk_gid));
/* Count the following as part of the last item_index. No need
* to lock the sock_tag_list here since it is already locked when
diff --git a/net/netfilter/xt_qtaguid_internal.h b/net/netfilter/xt_qtaguid_internal.h
index 8178fbd..c705270 100644
--- a/net/netfilter/xt_qtaguid_internal.h
+++ b/net/netfilter/xt_qtaguid_internal.h
@@ -289,10 +289,10 @@
*/
atomic64_t match_no_sk;
/*
- * The file ptr in the sk_socket wasn't there.
+ * The file ptr in the sk_socket wasn't there and we couldn't get GID.
* This might happen for traffic while the socket is being closed.
*/
- atomic64_t match_no_sk_file;
+ atomic64_t match_no_sk_gid;
};
/* Track the set active_set for the given tag. */