Merge "Android: binder: check set_context_mgr permission on time." into android-chromeos-dragon-3.18
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
index 111fbe6..2cdcc99 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -1069,14 +1069,17 @@
nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x00000008);
if (show) {
- nv_error(priv, "PBDMA%d:", unit);
- nvkm_bitfield_print(gk104_fifo_pbdma_intr_0, show);
- pr_cont("\n");
- nv_error(priv,
- "PBDMA%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
- unit, chid,
- nvkm_client_name_for_fifo_chid(&priv->base, chid),
- subc, mthd, data);
+ static unsigned long int j;
+ if (printk_timed_ratelimit(&j, 1000)) {
+ nv_error(priv, "PBDMA%d:", unit);
+ nvkm_bitfield_print(gk104_fifo_pbdma_intr_0, show);
+ pr_cont("\n");
+ nv_error(priv,
+ "PBDMA%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",
+ unit, chid,
+ nvkm_client_name_for_fifo_chid(&priv->base, chid),
+ subc, mthd, data);
+ }
nvkm_fifo_eevent(&priv->base, chid,
NOUVEAU_GEM_CHANNEL_PBDMA_ERROR);
}
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index fd03558..c8e39f6 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -8207,6 +8207,7 @@
return err;
}
+#ifdef DHD_ANQPO_SUPPORT
void * dhd_dev_process_anqpo_result(struct net_device *dev,
const void *data, uint32 event, int *send_evt_bytes)
{
@@ -8214,6 +8215,7 @@
return (dhd_pno_process_anqpo_result(&dhd->pub, data, event, send_evt_bytes));
}
+#endif /* DHD_ANQPO_SUPPORT */
#endif /* GSCAN_SUPPORT */
int dhd_dev_set_rssi_monitor_cfg(struct net_device *dev, int start,
diff --git a/drivers/net/wireless/bcmdhd/dhd_msgbuf.c b/drivers/net/wireless/bcmdhd/dhd_msgbuf.c
index 8d7d4bf..e6e2848 100644
--- a/drivers/net/wireless/bcmdhd/dhd_msgbuf.c
+++ b/drivers/net/wireless/bcmdhd/dhd_msgbuf.c
@@ -2493,22 +2493,24 @@
dhdmsgbuf_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
{
dhd_prot_t *prot = dhd->prot;
-
int ret = 0;
- DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-
- /* Respond "bcmerror" and "bcmerrorstr" with local cache */
- if (cmd == WLC_GET_VAR && buf)
- {
- if (!strcmp((char *)buf, "bcmerrorstr"))
- {
- strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), BCME_STRLEN);
+ DHD_TRACE(("%s: Enter\n", __func__));
+ if (!buf || !len) {
+ DHD_ERROR(("%s(): Zero length bailing\n", __func__));
+ ret = BCME_BADARG;
+ goto done;
+ }
+ if (cmd == WLC_GET_VAR) {
+ /* Respond "bcmerror" and "bcmerrorstr" with local cache */
+ if ((len > strlen("bcmerrorstr")) &&
+ !strcmp(buf, "bcmerrorstr")) {
+ strlcpy(buf, bcmerrorstr(dhd->dongle_error), len);
goto done;
- }
- else if (!strcmp((char *)buf, "bcmerror"))
- {
- *(int *)buf = dhd->dongle_error;
+ } else if ((len > strlen("bcmerror")) &&
+ !strcmp(buf, "bcmerror")) {
+ memcpy(buf, &dhd->dongle_error,
+ sizeof(dhd->dongle_error));
goto done;
}
}
diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c
index 049bd71..53c87cb 100644
--- a/drivers/net/wireless/bcmdhd/dhd_pno.c
+++ b/drivers/net/wireless/bcmdhd/dhd_pno.c
@@ -3824,6 +3824,7 @@
return results;
}
+#ifdef DHD_ANQPO_SUPPORT
void *
dhd_pno_process_anqpo_result(dhd_pub_t *dhd, const void *data, uint32 event, int *size)
{
@@ -3874,7 +3875,7 @@
return result;
}
-
+#endif /* DHD_ANQPO_SUPPORT */
void *dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_bytes,
hotlist_type_t type)
diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.h b/drivers/net/wireless/bcmdhd/dhd_pno.h
index 349cee8..ad9e1a8 100644
--- a/drivers/net/wireless/bcmdhd/dhd_pno.h
+++ b/drivers/net/wireless/bcmdhd/dhd_pno.h
@@ -98,7 +98,8 @@
#define CHANNEL_BUCKET_EMPTY_INDEX 0xFFFF
#define GSCAN_RETRY_THRESHOLD 3
#define MAX_EPNO_SSID_NUM 32
-
+#define GSCAN_ANQPO_MAX_HS_LIST_SIZE 16
+#define ANQPO_MAX_HS_NAI_REALM_SIZE 256
#endif /* GSCAN_SUPPORT */
enum scan_status {
@@ -350,10 +351,10 @@
} gscan_results_cache_t;
typedef struct {
- int id; /* identifier of this network block, report this in event */
- char realm[256]; /* null terminated UTF8 encoded realm, 0 if unspecified */
- int64_t roamingConsortiumIds[16]; /* roaming consortium ids to match, 0s if unspecified */
- uint8 plmn[3]; /* mcc/mnc combination as per rules, 0s if unspecified */
+ int id;
+ char realm[ANQPO_MAX_HS_NAI_REALM_SIZE];
+ int64_t roamingConsortiumIds[ANQPO_MAX_PFN_HS];
+ uint8 plmn[ANQPO_MCC_LENGTH];
} wifi_passpoint_network;
typedef struct dhd_pno_gscan_capabilities {
@@ -517,8 +518,10 @@
extern int dhd_dev_wait_batch_results_complete(struct net_device *dev);
extern void * dhd_dev_process_epno_result(struct net_device *dev,
const void *data, uint32 event, int *send_evt_bytes);
+#ifdef DHD_ANQPO_SUPPORT
extern void * dhd_dev_process_anqpo_result(struct net_device *dev,
const void *data, uint32 event, int *send_evt_bytes);
+#endif /* DHD_ANQPO_SUPPORT */
#endif /* GSCAN_SUPPORT */
/* dhd pno fuctions */
extern int dhd_pno_stop_for_ssid(dhd_pub_t *dhd);
@@ -565,7 +568,9 @@
extern int dhd_wait_batch_results_complete(dhd_pub_t *dhd);
extern void * dhd_pno_process_epno_result(dhd_pub_t *dhd, const void *data,
uint32 event, int *size);
+#ifdef DHD_ANQPO_SUPPORT
extern void * dhd_pno_process_anqpo_result(dhd_pub_t *dhd, const void *data, uint32 event, int *size);
+#endif /* DHD_ANQPO_SUPPORT */
#endif /* GSCAN_SUPPORT */
#endif /* PNO_SUPPORT */
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
index 24b71c5..0db69ef 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.c
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -246,11 +246,18 @@
return -1;
if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) {
DHD_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__));
+ } else if (total_len <= ssid.SSID_len) {
+ return -ENOMEM;
} else {
memcpy(command, ssid.SSID, ssid.SSID_len);
bytes_written = ssid.SSID_len;
}
- bytes_written += snprintf(&command[bytes_written], total_len, " rssi %d", rssi);
+ if ((total_len - bytes_written) < (strlen(" rssi -XXX") + 1))
+ return -ENOMEM;
+ bytes_written += scnprintf(&command[bytes_written],
+ total_len - bytes_written, " rssi %d", rssi);
+ command[bytes_written] = '\0';
+
DHD_INFO(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written));
return bytes_written;
}
@@ -1284,10 +1291,13 @@
int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
{
#define PRIVATE_COMMAND_MAX_LEN 8192
+#define PRIVATE_COMMAND_DEF_LEN 4096
+
int ret = 0;
char *command = NULL;
int bytes_written = 0;
android_wifi_priv_cmd priv_cmd;
+ int buf_size = 0;
net_os_wake_lock(net);
@@ -1321,12 +1331,17 @@
goto exit;
}
}
+
if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) {
- DHD_ERROR(("%s: too long priavte command\n", __FUNCTION__));
+ DHD_ERROR(("%s: buf length invalid:%d\n", __FUNCTION__,
+ priv_cmd.total_len));
ret = -EINVAL;
goto exit;
}
- command = kmalloc((priv_cmd.total_len + 1), GFP_KERNEL);
+
+ buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN);
+ command = kmalloc((buf_size + 1), GFP_KERNEL);
+
if (!command)
{
DHD_ERROR(("%s: failed to allocate memory\n", __FUNCTION__));
@@ -1341,6 +1356,41 @@
DHD_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name));
+ bytes_written = wl_handle_private_cmd(net, command, priv_cmd.total_len);
+ if (bytes_written >= 0) {
+ if ((bytes_written == 0) && (priv_cmd.total_len > 0))
+ command[0] = '\0';
+ if (bytes_written >= priv_cmd.total_len) {
+ DHD_ERROR(("%s: err. b_w:%d >= tot:%d\n", __FUNCTION__,
+ bytes_written, priv_cmd.total_len));
+ ret = BCME_BUFTOOSHORT;
+ goto exit;
+ }
+ bytes_written++;
+ priv_cmd.used_len = bytes_written;
+ if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
+ DHD_ERROR(("%s: failed copy to user\n", __FUNCTION__));
+ ret = -EFAULT;
+ }
+ } else {
+ ret = bytes_written;
+ }
+
+exit:
+ net_os_wake_unlock(net);
+ kfree(command);
+ return ret;
+}
+
+int
+wl_handle_private_cmd(struct net_device *net, char *command, u32 buf_size)
+{
+ int bytes_written = 0;
+ android_wifi_priv_cmd priv_cmd;
+
+ bzero(&priv_cmd, sizeof(android_wifi_priv_cmd));
+ priv_cmd.total_len = buf_size;
+
if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) {
DHD_INFO(("%s, Received regular START command\n", __FUNCTION__));
bytes_written = wl_android_wifi_on(net);
@@ -1350,10 +1400,9 @@
}
if (!g_wifi_on) {
- DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface %s is down\n",
- __FUNCTION__, command, ifr->ifr_name));
- ret = 0;
- goto exit;
+ DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface is down\n",
+ __FUNCTION__, command));
+ return 0;
}
if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) {
@@ -1511,36 +1560,10 @@
}
else {
DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
- snprintf(command, 3, "OK");
- bytes_written = strlen("OK");
+ bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL");
}
- if (bytes_written >= 0) {
- if ((bytes_written == 0) && (priv_cmd.total_len > 0))
- command[0] = '\0';
- if (bytes_written >= priv_cmd.total_len) {
- DHD_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written));
- bytes_written = priv_cmd.total_len;
- } else {
- bytes_written++;
- }
- priv_cmd.used_len = bytes_written;
- if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
- DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__));
- ret = -EFAULT;
- }
- }
- else {
- ret = bytes_written;
- }
-
-exit:
- net_os_wake_unlock(net);
- if (command) {
- kfree(command);
- }
-
- return ret;
+ return bytes_written;
}
int wl_android_init(void)
diff --git a/drivers/net/wireless/bcmdhd/wl_android.h b/drivers/net/wireless/bcmdhd/wl_android.h
index 2827132..f62b646 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.h
+++ b/drivers/net/wireless/bcmdhd/wl_android.h
@@ -53,6 +53,7 @@
int wl_android_wifi_on(struct net_device *dev);
int wl_android_wifi_off(struct net_device *dev, bool on_failure);
int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd);
+int wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len);
/* hostap mac mode */
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index 96cceac..8acdfc6 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -9240,6 +9240,7 @@
} else
err = -ENOMEM;
break;
+#ifdef DHD_ANQPO_SUPPORT
case WLC_E_PFN_NET_FOUND:
ptr = dhd_dev_process_anqpo_result(ndev, data, event, &len);
if (ptr) {
@@ -9249,6 +9250,7 @@
} else
err = -ENOMEM;
break;
+#endif /* DHD_ANQPO_SUPPORT */
default:
WL_ERR(("Unknown event %d\n", event));
break;
@@ -9796,7 +9798,9 @@
cfg->evt_handler[WLC_E_PFN_BSSID_NET_FOUND] = wl_notify_gscan_event;
cfg->evt_handler[WLC_E_PFN_BSSID_NET_LOST] = wl_notify_gscan_event;
cfg->evt_handler[WLC_E_PFN_SSID_EXT] = wl_notify_gscan_event;
+#ifdef DHD_ANQPO_SUPPORT
cfg->evt_handler[WLC_E_GAS_FRAGMENT_RX] = wl_notify_gscan_event;
+#endif /* DHD_ANQPO_SUPPORT */
cfg->evt_handler[WLC_E_ROAM_EXP_EVENT] = wl_handle_roam_exp_event;
#endif /* GSCAN_SUPPORT */
cfg->evt_handler[WLC_E_RSSI_LQM] = wl_handle_rssi_monitor_event;
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
index 1000ec9..5622620 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c
@@ -508,23 +508,113 @@
return err;
}
-static int wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy,
- struct wireless_dev *wdev, const void *data, int len)
+static int
+wl_cfgvendor_set_scan_cfg_bucket(const struct nlattr *prev,
+ gscan_scan_params_t *scan_param, int num)
+{
+ struct dhd_pno_gscan_channel_bucket *ch_bucket;
+ int k = 0;
+ int type, err = 0, rem;
+ const struct nlattr *cur, *next;
+
+ nla_for_each_nested(cur, prev, rem) {
+ type = nla_type(cur);
+ ch_bucket = scan_param->channel_bucket;
+ switch (type) {
+ case GSCAN_ATTRIBUTE_BUCKET_ID:
+ break;
+ case GSCAN_ATTRIBUTE_BUCKET_PERIOD:
+ if (nla_len(cur) != sizeof(uint32)) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ ch_bucket[num].bucket_freq_multiple =
+ nla_get_u32(cur) / MSEC_PER_SEC;
+ break;
+ case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS:
+ if (nla_len(cur) != sizeof(uint32)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ ch_bucket[num].num_channels = nla_get_u32(cur);
+ if (ch_bucket[num].num_channels >
+ GSCAN_MAX_CHANNELS_IN_BUCKET) {
+ WL_DBG(("channel range:%d,bucket:%d\n",
+ ch_bucket[num].num_channels,
+ num));
+ err = -EINVAL;
+ goto exit;
+ }
+ break;
+ case GSCAN_ATTRIBUTE_BUCKET_CHANNELS:
+ nla_for_each_nested(next, cur, rem) {
+ if (k >= GSCAN_MAX_CHANNELS_IN_BUCKET)
+ break;
+ if (nla_len(next) != sizeof(uint32)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ ch_bucket[num].chan_list[k] = nla_get_u32(next);
+ k++;
+ }
+ break;
+ case GSCAN_ATTRIBUTE_BUCKETS_BAND:
+ if (nla_len(cur) != sizeof(uint32)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ ch_bucket[num].band = (uint16)nla_get_u32(cur);
+ break;
+ case GSCAN_ATTRIBUTE_REPORT_EVENTS:
+ if (nla_len(cur) != sizeof(uint32)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ ch_bucket[num].report_flag = (uint8)nla_get_u32(cur);
+ break;
+ case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT:
+ if (nla_len(cur) != sizeof(uint32)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ ch_bucket[num].repeat = (uint16)nla_get_u32(cur);
+ break;
+ case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD:
+ if (nla_len(cur) != sizeof(uint32)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ ch_bucket[num].bucket_max_multiple =
+ nla_get_u32(cur) / MSEC_PER_SEC;
+ break;
+ default:
+ WL_DBG(("unknown attr type:%d\n", type));
+ err = -EINVAL;
+ goto exit;
+ }
+ }
+
+exit:
+ return err;
+}
+
+static int
+wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy, struct wireless_dev *wdev,
+ const void *data, int len)
{
int err = 0;
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
gscan_scan_params_t *scan_param;
int j = 0;
- int type, tmp, tmp1, tmp2, k = 0;
- const struct nlattr *iter, *iter1, *iter2;
- struct dhd_pno_gscan_channel_bucket *ch_bucket;
+ int type, tmp;
+ const struct nlattr *iter;
scan_param = kzalloc(sizeof(gscan_scan_params_t), GFP_KERNEL);
if (!scan_param) {
WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n"));
err = -EINVAL;
return err;
-
}
scan_param->scan_fr = PNO_SCAN_MIN_FW_SEC;
@@ -535,77 +625,60 @@
break;
switch (type) {
- case GSCAN_ATTRIBUTE_BASE_PERIOD:
- scan_param->scan_fr = nla_get_u32(iter)/1000;
- break;
- case GSCAN_ATTRIBUTE_NUM_BUCKETS:
- scan_param->nchannel_buckets = nla_get_u32(iter);
- break;
- case GSCAN_ATTRIBUTE_CH_BUCKET_1:
- case GSCAN_ATTRIBUTE_CH_BUCKET_2:
- case GSCAN_ATTRIBUTE_CH_BUCKET_3:
- case GSCAN_ATTRIBUTE_CH_BUCKET_4:
- case GSCAN_ATTRIBUTE_CH_BUCKET_5:
- case GSCAN_ATTRIBUTE_CH_BUCKET_6:
- case GSCAN_ATTRIBUTE_CH_BUCKET_7:
- nla_for_each_nested(iter1, iter, tmp1) {
- type = nla_type(iter1);
- ch_bucket =
- scan_param->channel_bucket;
+ case GSCAN_ATTRIBUTE_BASE_PERIOD:
+ if (nla_len(iter) != sizeof(uint32)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ scan_param->scan_fr = nla_get_u32(iter) / MSEC_PER_SEC;
+ break;
+ case GSCAN_ATTRIBUTE_NUM_BUCKETS:
+ if (nla_len(iter) != sizeof(uint32)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ scan_param->nchannel_buckets = nla_get_u32(iter);
+ if (scan_param->nchannel_buckets >=
+ GSCAN_MAX_CH_BUCKETS) {
+ WL_DBG(("ncha_buck out of range %d\n",
+ scan_param->nchannel_buckets));
+ err = -EINVAL;
+ goto exit;
+ }
+ break;
+ case GSCAN_ATTRIBUTE_CH_BUCKET_1:
+ case GSCAN_ATTRIBUTE_CH_BUCKET_2:
+ case GSCAN_ATTRIBUTE_CH_BUCKET_3:
+ case GSCAN_ATTRIBUTE_CH_BUCKET_4:
+ case GSCAN_ATTRIBUTE_CH_BUCKET_5:
+ case GSCAN_ATTRIBUTE_CH_BUCKET_6:
+ case GSCAN_ATTRIBUTE_CH_BUCKET_7:
+ err = wl_cfgvendor_set_scan_cfg_bucket(iter,
+ scan_param, j);
+ if (err < 0) {
+ WL_DBG(("set_scan_cfg_buck error:%d\n", err));
+ goto exit;
+ }
- switch (type) {
- case GSCAN_ATTRIBUTE_BUCKET_ID:
- break;
- case GSCAN_ATTRIBUTE_BUCKET_PERIOD:
- ch_bucket[j].bucket_freq_multiple =
- nla_get_u32(iter1)/1000;
- break;
- case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS:
- ch_bucket[j].num_channels =
- nla_get_u32(iter1);
- break;
- case GSCAN_ATTRIBUTE_BUCKET_CHANNELS:
- nla_for_each_nested(iter2, iter1, tmp2) {
- if (k >= GSCAN_MAX_CHANNELS_IN_BUCKET)
- break;
- ch_bucket[j].chan_list[k] =
- nla_get_u32(iter2);
- k++;
- }
- k = 0;
- break;
- case GSCAN_ATTRIBUTE_BUCKETS_BAND:
- ch_bucket[j].band = (uint16)
- nla_get_u32(iter1);
- break;
- case GSCAN_ATTRIBUTE_REPORT_EVENTS:
- ch_bucket[j].report_flag = (uint8)
- nla_get_u32(iter1);
- break;
- case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT:
- ch_bucket[j].repeat = (uint16)
- nla_get_u32(iter1);
- break;
- case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD:
- ch_bucket[j].bucket_max_multiple =
- nla_get_u32(iter1)/1000;
- break;
- }
- }
- j++;
- break;
+ j++;
+ break;
+ default:
+ WL_DBG(("Unknown attr type %d\n", type));
+ err = -EINVAL;
+ goto exit;
}
}
- if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
- DHD_PNO_SCAN_CFG_ID, scan_param, 0) < 0) {
- WL_ERR(("Could not set GSCAN scan cfg\n"));
+ err = dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
+ DHD_PNO_SCAN_CFG_ID, scan_param, 0);
+ if (err < 0) {
+ WL_ERR(("Could not set GSCAN scan cfg error %d\n", err));
err = -EINVAL;
}
+exit:
kfree(scan_param);
return err;
-
}
static int wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy,
@@ -615,14 +688,22 @@
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
gscan_hotlist_scan_params_t *hotlist_params;
int tmp, tmp1, tmp2, type, j = 0, dummy;
- const struct nlattr *outer, *inner, *iter;
+ const struct nlattr *outer, *inner = NULL, *iter;
uint8 flush = 0;
struct bssid_t *pbssid;
- hotlist_params = (gscan_hotlist_scan_params_t *)kzalloc(len, GFP_KERNEL);
+ if (len < sizeof(*hotlist_params) || len >= WLC_IOCTL_MAXLEN) {
+ WL_ERR(("buffer length :%d wrong - bail out.\n", len));
+ return -EINVAL;
+ }
+
+ hotlist_params = kzalloc(sizeof(*hotlist_params)
+ + (sizeof(struct bssid_t) * (PFN_SWC_MAX_NUM_APS - 1)),
+ GFP_KERNEL);
+
if (!hotlist_params) {
WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes \n", len));
- return -1;
+ return -ENOMEM;
}
hotlist_params->lost_ap_window = GSCAN_LOST_AP_WINDOW_DEFAULT;
@@ -630,37 +711,78 @@
nla_for_each_attr(iter, data, len, tmp2) {
type = nla_type(iter);
switch (type) {
- case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:
- pbssid = hotlist_params->bssid;
- nla_for_each_nested(outer, iter, tmp) {
- nla_for_each_nested(inner, outer, tmp1) {
- type = nla_type(inner);
+ case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:
+ pbssid = hotlist_params->bssid;
+ nla_for_each_nested(outer, iter, tmp) {
+ nla_for_each_nested(inner, outer, tmp1) {
+ type = nla_type(inner);
- switch (type) {
- case GSCAN_ATTRIBUTE_BSSID:
- memcpy(&(pbssid[j].macaddr),
- nla_data(inner), ETHER_ADDR_LEN);
- break;
- case GSCAN_ATTRIBUTE_RSSI_LOW:
- pbssid[j].rssi_reporting_threshold =
- (int8) nla_get_u8(inner);
- break;
- case GSCAN_ATTRIBUTE_RSSI_HIGH:
- dummy = (int8) nla_get_u8(inner);
- break;
+ switch (type) {
+ case GSCAN_ATTRIBUTE_BSSID:
+ if (nla_len(inner) != sizeof(pbssid[j].macaddr)) {
+ WL_DBG(("type:%d length:%d not matching.\n",
+ type, nla_len(inner)));
+ err = -EINVAL;
+ goto exit;
}
+ memcpy(
+ &pbssid[j].macaddr,
+ nla_data(inner),
+ sizeof(pbssid[j].macaddr));
+ break;
+ case GSCAN_ATTRIBUTE_RSSI_LOW:
+ if (nla_len(inner) != sizeof(uint8)) {
+ WL_DBG(("type:%d length:%d not matching.\n",
+ type, nla_len(inner)));
+ err = -EINVAL;
+ goto exit;
+ }
+ pbssid[j].rssi_reporting_threshold =
+ (int8)nla_get_u8(inner);
+ break;
+ case GSCAN_ATTRIBUTE_RSSI_HIGH:
+ if (nla_len(inner) != sizeof(uint8)) {
+ WL_DBG(("type:%d length:%d not matching.\n",
+ type, nla_len(inner)));
+ err = -EINVAL;
+ goto exit;
+ }
+ dummy = (int8)nla_get_u8(inner);
+ break;
}
- j++;
+ }
+ if (++j > PFN_SWC_MAX_NUM_APS) {
+ WL_DBG(("nbssid:%d exeed limit.\n",
+ hotlist_params->nbssid));
+ err = -EINVAL;
+ goto exit;
}
hotlist_params->nbssid = j;
- break;
- case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
- flush = nla_get_u8(iter);
- break;
- case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
- hotlist_params->lost_ap_window = nla_get_u32(iter);
- break;
}
+ break;
+ case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
+ if (nla_len(iter) != sizeof(uint8)) {
+ WL_DBG(("type:%d length:%d not matching.\n",
+ type, nla_len(inner)));
+ err = -EINVAL;
+ goto exit;
+ }
+ flush = nla_get_u8(iter);
+ break;
+ case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
+ if (nla_len(iter) != sizeof(uint32)) {
+ WL_DBG(("type:%d length:%d not matching.\n",
+ type, nla_len(inner)));
+ err = -EINVAL;
+ goto exit;
+ }
+ hotlist_params->lost_ap_window = (uint16)nla_get_u32(iter);
+ break;
+ default:
+ WL_DBG(("Unknown type %d\n", type));
+ err = -EINVAL;
+ goto exit;
+ }
}
@@ -766,10 +888,13 @@
return err;
}
+#ifdef DHD_ANQPO_SUPPORT
static int wl_cfgvendor_gscan_anqpo_config(struct wiphy *wiphy,
struct wireless_dev *wdev, const void *data, int len)
{
- int err = BCME_ERROR, rem, type, hs_list_size = 0, malloc_size, i = 0, j, k, num_oi, oi_len;
+ int err = BCME_ERROR, rem, type, malloc_size, i = 0;
+ uint32 hs_list_size = 0;
+ int j, k, num_oi, oi_len;
wifi_passpoint_network *hs_list = NULL, *src_hs;
wl_anqpo_pfn_hs_list_t *anqpo_hs_list;
wl_anqpo_pfn_hs_t *dst_hs;
@@ -780,52 +905,100 @@
char *rcid;
nla_for_each_attr(iter, data, len, rem) {
- type = nla_type(iter);
- switch (type) {
- case GSCAN_ATTRIBUTE_ANQPO_HS_LIST:
- if (hs_list_size > 0) {
- hs_list = kmalloc(hs_list_size*sizeof(wifi_passpoint_network), GFP_KERNEL);
- if (hs_list == NULL) {
- WL_ERR(("failed to allocate hs_list\n"));
- return -ENOMEM;
- }
- }
- nla_for_each_nested(outer, iter, tmp) {
- nla_for_each_nested(inner, outer, tmp1) {
- type = nla_type(inner);
-
- switch (type) {
- case GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID:
- hs_list[i].id = nla_get_u32(inner);
- WL_ERR(("%s: net id: %d\n", __func__, hs_list[i].id));
- break;
- case GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM:
- memcpy(hs_list[i].realm,
- nla_data(inner), 256);
- WL_ERR(("%s: realm: %s\n", __func__, hs_list[i].realm));
- break;
- case GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID:
- memcpy(hs_list[i].roamingConsortiumIds,
- nla_data(inner), 128);
- break;
- case GSCAN_ATTRIBUTE_ANQPO_HS_PLMN:
- memcpy(hs_list[i].plmn,
- nla_data(inner), 3);
- WL_ERR(("%s: plmn: %c %c %c\n", __func__, hs_list[i].plmn[0], hs_list[i].plmn[1], hs_list[i].plmn[2]));
- break;
- }
- }
- i++;
- }
- break;
- case GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE:
- hs_list_size = nla_get_u32(iter);
- WL_ERR(("%s: ANQPO: %d\n", __func__, hs_list_size));
- break;
- default:
- WL_ERR(("Unknown type: %d\n", type));
- return err;
+ type = nla_type(iter);
+ switch (type) {
+ case GSCAN_ATTRIBUTE_ANQPO_HS_LIST:
+ if (hs_list) {
+ err = -EINVAL;
+ goto exit;
}
+ if (hs_list_size > GSCAN_ANQPO_MAX_HS_LIST_SIZE) {
+ err = -EINVAL;
+ goto exit;
+ }
+ if (hs_list_size > 0) {
+ hs_list = kzalloc(hs_list_size *
+ sizeof(wifi_passpoint_network), GFP_KERNEL);
+ if (!hs_list) {
+ WL_ERR(("failed to allocate hs_list\n"));
+ return -ENOMEM;
+ }
+ }
+ nla_for_each_nested(outer, iter, tmp) {
+ if (i == hs_list_size)
+ break;
+ nla_for_each_nested(inner, outer, tmp1) {
+ type = nla_type(inner);
+
+ switch (type) {
+ case GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID:
+ if (nla_len(inner) != sizeof(hs_list[i].id)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ hs_list[i].id = nla_get_u32(inner);
+ WL_DBG(("%s: net id: %d\n",
+ __func__, hs_list[i].id));
+ break;
+ case GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM:
+ if (nla_len(inner) !=
+ sizeof(hs_list[i].realm)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ memcpy(hs_list[i].realm, nla_data(inner),
+ sizeof(hs_list[i].realm));
+ WL_DBG(("%s: realm: %s\n",
+ __func__, hs_list[i].realm));
+ break;
+ case GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID:
+ if (nla_len(inner) != sizeof(hs_list[i].
+ roamingConsortiumIds)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ memcpy(hs_list[i].roamingConsortiumIds,
+ nla_data(inner),
+ sizeof(hs_list[i].roamingConsortiumIds));
+ break;
+ case GSCAN_ATTRIBUTE_ANQPO_HS_PLMN:
+ if (nla_len(inner) != sizeof(hs_list[i].plmn)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ memcpy(hs_list[i].plmn,
+ nla_data(inner),
+ sizeof(hs_list[i].plmn));
+ WL_DBG(("%s: plmn: %c %c %c\n",
+ __func__, hs_list[i].plmn[0],
+ hs_list[i].plmn[1],
+ hs_list[i].plmn[2]));
+ break;
+ }
+ }
+ i++;
+ }
+ break;
+ case GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE:
+ if (nla_len(iter) != sizeof(hs_list_size)) {
+ err = -EINVAL;
+ goto exit;
+ }
+ hs_list_size = nla_get_u32(iter);
+ if ((hs_list_size == 0) ||
+ (hs_list_size > GSCAN_ANQPO_MAX_HS_LIST_SIZE)) {
+ WL_ERR(("%s: ANQPO: %d\n", __func__, hs_list_size));
+ err = -EINVAL;
+ goto exit;
+ }
+ WL_DBG(("%s: ANQPO: %d\n", __func__, hs_list_size));
+ break;
+ default:
+ WL_ERR(("Unknown type: %d\n", type));
+ err = -EINVAL;
+ goto exit;
+ }
+
}
malloc_size = OFFSETOF(wl_anqpo_pfn_hs_list_t, hs) +
@@ -873,7 +1046,7 @@
kfree(hs_list);
return err;
}
-
+#endif /* DHD_ANQPO_SUPPORT */
static int wl_cfgvendor_set_batch_scan_cfg(struct wiphy *wiphy,
struct wireless_dev *wdev, const void *data, int len)
{
@@ -1413,13 +1586,18 @@
}
memset(&rtt_param, 0, sizeof(rtt_param));
+ if (len <= 0) {
+ err = BCME_ERROR;
+ goto exit;
+ }
nla_for_each_attr(iter, data, len, rem) {
type = nla_type(iter);
switch (type) {
case RTT_ATTRIBUTE_TARGET_CNT:
target_cnt = nla_get_u8(iter);
- if (rtt_param.rtt_target_cnt > RTT_MAX_TARGET_CNT) {
- WL_ERR(("exceed max target count : %d\n",
+ if ((target_cnt <= 0) ||
+ (target_cnt > RTT_MAX_TARGET_CNT)) {
+ WL_ERR(("target_cnt is not valid: %d",
target_cnt));
err = BCME_RANGE;
goto exit;
@@ -1433,6 +1611,13 @@
}
break;
case RTT_ATTRIBUTE_TARGET_INFO:
+ /* Added this variable for safe check to avoid crash
+ * incase the caller did not respect the order
+ */
+ if (!rtt_param.target_info) {
+ err = BCME_NOMEM;
+ goto exit;
+ }
rtt_target = rtt_param.target_info;
nla_for_each_nested(iter1, iter, rem1) {
nla_for_each_nested(iter2, iter1, rem2) {
@@ -1553,6 +1738,7 @@
exit:
/* free the target info list */
kfree(rtt_param.target_info);
+ rtt_param.target_info = NULL;
return err;
}
@@ -1561,46 +1747,63 @@
const void *data, int len)
{
int err = 0, rem, type, target_cnt = 0;
- int target_cnt_chk = 0;
+ int target_idx = 0;
const struct nlattr *iter;
- struct ether_addr *mac_list = NULL, *mac_addr = NULL;
+ struct ether_addr *mac_list = NULL;
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+ if (len <= 0) {
+ err = -EINVAL;
+ goto exit;
+ }
nla_for_each_attr(iter, data, len, rem) {
type = nla_type(iter);
switch (type) {
case RTT_ATTRIBUTE_TARGET_CNT:
if (mac_list != NULL) {
WL_ERR(("mac_list is not NULL\n"));
+ err = -EINVAL;
goto exit;
}
target_cnt = nla_get_u8(iter);
- if (target_cnt > 0) {
+ if ((target_cnt > 0) &&
+ (target_cnt < RTT_MAX_TARGET_CNT)) {
mac_list = (struct ether_addr *)kzalloc(target_cnt * ETHER_ADDR_LEN,
GFP_KERNEL);
if (mac_list == NULL) {
WL_ERR(("failed to allocate mem for mac list\n"));
+ err = -EINVAL;
goto exit;
}
- mac_addr = &mac_list[0];
} else {
/* cancel the current whole RTT process */
goto cancel;
}
break;
case RTT_ATTRIBUTE_TARGET_MAC:
- if (mac_addr) {
- memcpy(mac_addr++, nla_data(iter), ETHER_ADDR_LEN);
- target_cnt_chk++;
- if (target_cnt_chk > target_cnt) {
- WL_ERR(("over target count\n"));
- goto exit;
- }
- break;
- } else {
- WL_ERR(("mac_list is NULL\n"));
+ if (!mac_list) {
+ err = -EINVAL;
goto exit;
}
+
+ if (target_idx >= target_cnt) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ if (nla_len(iter) != ETHER_ADDR_LEN) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ memcpy(&mac_list[target_idx], nla_data(iter),
+ ETHER_ADDR_LEN);
+ target_idx++;
+ break;
+
+ default:
+ err = -EINVAL;
+ goto exit;
}
}
cancel:
@@ -2468,6 +2671,7 @@
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = wl_cfgvendor_set_bssid_blacklist
},
+#ifdef DHD_ANQPO_SUPPORT
{
{
.vendor_id = OUI_GOOGLE,
@@ -2476,6 +2680,7 @@
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
.doit = wl_cfgvendor_gscan_anqpo_config
},
+#endif /* DHD_ANQPO_SUPPORT */
#endif /* GSCAN_SUPPORT */
{
{
@@ -2582,7 +2787,9 @@
{ OUI_GOOGLE, GOOGLE_SCAN_EPNO_EVENT },
{ OUI_GOOGLE, GOOGLE_DEBUG_RING_EVENT },
{ OUI_GOOGLE, GOOGLE_FW_DUMP_EVENT },
+#ifdef DHD_ANQPO_SUPPORT
{ OUI_GOOGLE, GOOGLE_PNO_HOTSPOT_FOUND_EVENT },
+#endif /* DHD_ANQPO_SUPPORT */
{ OUI_GOOGLE, GOOGLE_RSSI_MONITOR_EVENT },
{ OUI_GOOGLE, GOOGLE_MKEEP_ALIVE_EVENT }
};
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 3890c98..eb1508e 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -159,16 +159,16 @@
int g;
struct fdtable *fdt = NULL;
const struct cred *cred;
- pid_t ppid, tpid;
+ pid_t ppid = 0, tpid = 0;
+ struct task_struct *leader = NULL;
rcu_read_lock();
- ppid = pid_alive(p) ?
- task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
- tpid = 0;
if (pid_alive(p)) {
struct task_struct *tracer = ptrace_parent(p);
if (tracer)
tpid = task_pid_nr_ns(tracer, ns);
+ ppid = task_tgid_nr_ns(rcu_dereference(p->real_parent), ns);
+ leader = p->group_leader;
}
cred = get_task_cred(p);
seq_printf(m,
@@ -210,12 +210,13 @@
seq_printf(m, "%d ",
from_kgid_munged(user_ns, GROUP_AT(group_info, g)));
put_cred(cred);
-
#ifdef CONFIG_PID_NS
- seq_puts(m, "\nNStgid:");
- for (g = ns->level; g <= pid->level; g++)
- seq_printf(m, "\t%d",
- task_tgid_nr_ns(p, pid->numbers[g].ns));
+ if (leader) {
+ seq_puts(m, "\nNStgid:");
+ for (g = ns->level; g <= pid->level; g++)
+ seq_printf(m, "\t%d",
+ task_pid_nr_ns(leader, pid->numbers[g].ns));
+ }
seq_puts(m, "\nNSpid:");
for (g = ns->level; g <= pid->level; g++)
seq_printf(m, "\t%d",
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 2cc2136..dccbd2c 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1448,10 +1448,17 @@
* If this was a group event with sibling events then
* upgrade the siblings to singleton events by adding them
* to whatever list we are on.
+ * If this isn't on a list, make sure we still remove the sibling's
+ * group_entry from this sibling_list; otherwise, when that sibling
+ * is later deallocated, it will try to remove itself from this
+ * sibling_list, which may well have been deallocated already,
+ * resulting in a use-after-free.
*/
list_for_each_entry_safe(sibling, tmp, &event->sibling_list, group_entry) {
if (list)
list_move_tail(&sibling->group_entry, list);
+ else
+ list_del_init(&sibling->group_entry);
sibling->group_leader = sibling;
/* Inherit group flags from the previous leader */
diff --git a/mm/memory.c b/mm/memory.c
index d5f2ae9..04979a2 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2636,6 +2636,10 @@
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_SIGBUS;
@@ -3040,6 +3044,9 @@
- 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);
@@ -3205,11 +3212,10 @@
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);
}