nl80211: don't put struct cfg80211_ap_settings on stack
This struct has grown quite a bit, so dynamically allocate it instead of putting it on the stack. Link: https://lore.kernel.org/r/20210923161836.5813d881eae3.I0fc0f83905b0bfa332c4f1505e00c13abfca3545@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Родитель
5d24828d05
Коммит
9e263e193a
|
@ -5323,7 +5323,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_ap_settings params;
|
||||
struct cfg80211_ap_settings *params;
|
||||
int err;
|
||||
|
||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
|
||||
|
@ -5336,27 +5336,29 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
if (wdev->beacon_interval)
|
||||
return -EALREADY;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
/* these are required for START_AP */
|
||||
if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
|
||||
!info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
|
||||
!info->attrs[NL80211_ATTR_BEACON_HEAD])
|
||||
return -EINVAL;
|
||||
|
||||
err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon);
|
||||
if (err)
|
||||
return err;
|
||||
params = kzalloc(sizeof(*params), GFP_KERNEL);
|
||||
if (!params)
|
||||
return -ENOMEM;
|
||||
|
||||
params.beacon_interval =
|
||||
err = nl80211_parse_beacon(rdev, info->attrs, ¶ms->beacon);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
params->beacon_interval =
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
|
||||
params.dtim_period =
|
||||
params->dtim_period =
|
||||
nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
|
||||
|
||||
err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
|
||||
params.beacon_interval);
|
||||
params->beacon_interval);
|
||||
if (err)
|
||||
return err;
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* In theory, some of these attributes should be required here
|
||||
|
@ -5366,129 +5368,156 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
* additional information -- drivers must check!
|
||||
*/
|
||||
if (info->attrs[NL80211_ATTR_SSID]) {
|
||||
params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
|
||||
params.ssid_len =
|
||||
params->ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
|
||||
params->ssid_len =
|
||||
nla_len(info->attrs[NL80211_ATTR_SSID]);
|
||||
if (params.ssid_len == 0)
|
||||
return -EINVAL;
|
||||
if (params->ssid_len == 0) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
|
||||
params.hidden_ssid = nla_get_u32(
|
||||
params->hidden_ssid = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_HIDDEN_SSID]);
|
||||
|
||||
params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
|
||||
params->privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
|
||||
|
||||
if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
|
||||
params.auth_type = nla_get_u32(
|
||||
params->auth_type = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_AUTH_TYPE]);
|
||||
if (!nl80211_valid_auth_type(rdev, params.auth_type,
|
||||
NL80211_CMD_START_AP))
|
||||
return -EINVAL;
|
||||
if (!nl80211_valid_auth_type(rdev, params->auth_type,
|
||||
NL80211_CMD_START_AP)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
||||
params->auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
||||
|
||||
err = nl80211_crypto_settings(rdev, info, ¶ms.crypto,
|
||||
err = nl80211_crypto_settings(rdev, info, ¶ms->crypto,
|
||||
NL80211_MAX_NR_CIPHER_SUITES);
|
||||
if (err)
|
||||
return err;
|
||||
goto out;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
|
||||
if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER))
|
||||
return -EOPNOTSUPP;
|
||||
params.inactivity_timeout = nla_get_u16(
|
||||
if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
params->inactivity_timeout = nla_get_u16(
|
||||
info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
|
||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
|
||||
return -EINVAL;
|
||||
params.p2p_ctwindow =
|
||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
params->p2p_ctwindow =
|
||||
nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
|
||||
if (params.p2p_ctwindow != 0 &&
|
||||
!(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
|
||||
return -EINVAL;
|
||||
if (params->p2p_ctwindow != 0 &&
|
||||
!(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
|
||||
u8 tmp;
|
||||
|
||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
|
||||
return -EINVAL;
|
||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
|
||||
params.p2p_opp_ps = tmp;
|
||||
if (params.p2p_opp_ps != 0 &&
|
||||
!(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
|
||||
return -EINVAL;
|
||||
params->p2p_opp_ps = tmp;
|
||||
if (params->p2p_opp_ps != 0 &&
|
||||
!(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
|
||||
err = nl80211_parse_chandef(rdev, info, ¶ms.chandef);
|
||||
err = nl80211_parse_chandef(rdev, info, ¶ms->chandef);
|
||||
if (err)
|
||||
return err;
|
||||
goto out;
|
||||
} else if (wdev->preset_chandef.chan) {
|
||||
params.chandef = wdev->preset_chandef;
|
||||
} else if (!nl80211_get_ap_channel(rdev, ¶ms))
|
||||
return -EINVAL;
|
||||
params->chandef = wdev->preset_chandef;
|
||||
} else if (!nl80211_get_ap_channel(rdev, params)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef,
|
||||
wdev->iftype))
|
||||
return -EINVAL;
|
||||
if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms->chandef,
|
||||
wdev->iftype)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_TX_RATES]) {
|
||||
err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
|
||||
NL80211_ATTR_TX_RATES,
|
||||
¶ms.beacon_rate,
|
||||
¶ms->beacon_rate,
|
||||
dev, false);
|
||||
if (err)
|
||||
return err;
|
||||
goto out;
|
||||
|
||||
err = validate_beacon_tx_rate(rdev, params.chandef.chan->band,
|
||||
¶ms.beacon_rate);
|
||||
err = validate_beacon_tx_rate(rdev, params->chandef.chan->band,
|
||||
¶ms->beacon_rate);
|
||||
if (err)
|
||||
return err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
|
||||
params.smps_mode =
|
||||
params->smps_mode =
|
||||
nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
|
||||
switch (params.smps_mode) {
|
||||
switch (params->smps_mode) {
|
||||
case NL80211_SMPS_OFF:
|
||||
break;
|
||||
case NL80211_SMPS_STATIC:
|
||||
if (!(rdev->wiphy.features &
|
||||
NL80211_FEATURE_STATIC_SMPS))
|
||||
return -EINVAL;
|
||||
NL80211_FEATURE_STATIC_SMPS)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case NL80211_SMPS_DYNAMIC:
|
||||
if (!(rdev->wiphy.features &
|
||||
NL80211_FEATURE_DYNAMIC_SMPS))
|
||||
return -EINVAL;
|
||||
NL80211_FEATURE_DYNAMIC_SMPS)) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
params.smps_mode = NL80211_SMPS_OFF;
|
||||
params->smps_mode = NL80211_SMPS_OFF;
|
||||
}
|
||||
|
||||
params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
|
||||
if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ])
|
||||
return -EOPNOTSUPP;
|
||||
params->pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
|
||||
if (params->pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
|
||||
params.acl = parse_acl_data(&rdev->wiphy, info);
|
||||
if (IS_ERR(params.acl))
|
||||
return PTR_ERR(params.acl);
|
||||
params->acl = parse_acl_data(&rdev->wiphy, info);
|
||||
if (IS_ERR(params->acl)) {
|
||||
err = PTR_ERR(params->acl);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
params.twt_responder =
|
||||
params->twt_responder =
|
||||
nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
|
||||
err = nl80211_parse_he_obss_pd(
|
||||
info->attrs[NL80211_ATTR_HE_OBSS_PD],
|
||||
¶ms.he_obss_pd);
|
||||
¶ms->he_obss_pd);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
@ -5496,7 +5525,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
|
||||
err = nl80211_parse_he_bss_color(
|
||||
info->attrs[NL80211_ATTR_HE_BSS_COLOR],
|
||||
¶ms.he_bss_color);
|
||||
¶ms->he_bss_color);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
@ -5504,7 +5533,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
|
||||
err = nl80211_parse_fils_discovery(rdev,
|
||||
info->attrs[NL80211_ATTR_FILS_DISCOVERY],
|
||||
¶ms);
|
||||
params);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
@ -5512,24 +5541,24 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
|
||||
err = nl80211_parse_unsol_bcast_probe_resp(
|
||||
rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
|
||||
¶ms);
|
||||
params);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
nl80211_calculate_ap_params(¶ms);
|
||||
nl80211_calculate_ap_params(params);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
|
||||
params.flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
|
||||
params->flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
|
||||
|
||||
wdev_lock(wdev);
|
||||
err = rdev_start_ap(rdev, dev, ¶ms);
|
||||
err = rdev_start_ap(rdev, dev, params);
|
||||
if (!err) {
|
||||
wdev->preset_chandef = params.chandef;
|
||||
wdev->beacon_interval = params.beacon_interval;
|
||||
wdev->chandef = params.chandef;
|
||||
wdev->ssid_len = params.ssid_len;
|
||||
memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
|
||||
wdev->preset_chandef = params->chandef;
|
||||
wdev->beacon_interval = params->beacon_interval;
|
||||
wdev->chandef = params->chandef;
|
||||
wdev->ssid_len = params->ssid_len;
|
||||
memcpy(wdev->ssid, params->ssid, wdev->ssid_len);
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
|
||||
wdev->conn_owner_nlportid = info->snd_portid;
|
||||
|
@ -5537,7 +5566,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|||
wdev_unlock(wdev);
|
||||
|
||||
out:
|
||||
kfree(params.acl);
|
||||
kfree(params->acl);
|
||||
kfree(params);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче