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 cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||||
struct net_device *dev = info->user_ptr[1];
|
struct net_device *dev = info->user_ptr[1];
|
||||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
struct cfg80211_ap_settings params;
|
struct cfg80211_ap_settings *params;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
|
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)
|
if (wdev->beacon_interval)
|
||||||
return -EALREADY;
|
return -EALREADY;
|
||||||
|
|
||||||
memset(¶ms, 0, sizeof(params));
|
|
||||||
|
|
||||||
/* these are required for START_AP */
|
/* these are required for START_AP */
|
||||||
if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
|
if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
|
||||||
!info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
|
!info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
|
||||||
!info->attrs[NL80211_ATTR_BEACON_HEAD])
|
!info->attrs[NL80211_ATTR_BEACON_HEAD])
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.beacon);
|
params = kzalloc(sizeof(*params), GFP_KERNEL);
|
||||||
if (err)
|
if (!params)
|
||||||
return err;
|
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]);
|
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
|
||||||
params.dtim_period =
|
params->dtim_period =
|
||||||
nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
|
nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
|
||||||
|
|
||||||
err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
|
err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
|
||||||
params.beacon_interval);
|
params->beacon_interval);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In theory, some of these attributes should be required here
|
* 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!
|
* additional information -- drivers must check!
|
||||||
*/
|
*/
|
||||||
if (info->attrs[NL80211_ATTR_SSID]) {
|
if (info->attrs[NL80211_ATTR_SSID]) {
|
||||||
params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
|
params->ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
|
||||||
params.ssid_len =
|
params->ssid_len =
|
||||||
nla_len(info->attrs[NL80211_ATTR_SSID]);
|
nla_len(info->attrs[NL80211_ATTR_SSID]);
|
||||||
if (params.ssid_len == 0)
|
if (params->ssid_len == 0) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
|
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]);
|
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]) {
|
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]);
|
info->attrs[NL80211_ATTR_AUTH_TYPE]);
|
||||||
if (!nl80211_valid_auth_type(rdev, params.auth_type,
|
if (!nl80211_valid_auth_type(rdev, params->auth_type,
|
||||||
NL80211_CMD_START_AP))
|
NL80211_CMD_START_AP)) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
} else
|
} 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);
|
NL80211_MAX_NR_CIPHER_SUITES);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto out;
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
|
if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
|
||||||
if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER))
|
if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER)) {
|
||||||
return -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
params.inactivity_timeout = nla_get_u16(
|
goto out;
|
||||||
|
}
|
||||||
|
params->inactivity_timeout = nla_get_u16(
|
||||||
info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
|
info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
|
if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
|
||||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
|
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
params.p2p_ctwindow =
|
goto out;
|
||||||
|
}
|
||||||
|
params->p2p_ctwindow =
|
||||||
nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
|
nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
|
||||||
if (params.p2p_ctwindow != 0 &&
|
if (params->p2p_ctwindow != 0 &&
|
||||||
!(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
|
!(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
|
if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
|
||||||
u8 tmp;
|
u8 tmp;
|
||||||
|
|
||||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
|
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
|
tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
|
||||||
params.p2p_opp_ps = tmp;
|
params->p2p_opp_ps = tmp;
|
||||||
if (params.p2p_opp_ps != 0 &&
|
if (params->p2p_opp_ps != 0 &&
|
||||||
!(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
|
!(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
|
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)
|
if (err)
|
||||||
return err;
|
goto out;
|
||||||
} else if (wdev->preset_chandef.chan) {
|
} else if (wdev->preset_chandef.chan) {
|
||||||
params.chandef = wdev->preset_chandef;
|
params->chandef = wdev->preset_chandef;
|
||||||
} else if (!nl80211_get_ap_channel(rdev, ¶ms))
|
} else if (!nl80211_get_ap_channel(rdev, params)) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef,
|
if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms->chandef,
|
||||||
wdev->iftype))
|
wdev->iftype)) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_TX_RATES]) {
|
if (info->attrs[NL80211_ATTR_TX_RATES]) {
|
||||||
err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
|
err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
|
||||||
NL80211_ATTR_TX_RATES,
|
NL80211_ATTR_TX_RATES,
|
||||||
¶ms.beacon_rate,
|
¶ms->beacon_rate,
|
||||||
dev, false);
|
dev, false);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto out;
|
||||||
|
|
||||||
err = validate_beacon_tx_rate(rdev, params.chandef.chan->band,
|
err = validate_beacon_tx_rate(rdev, params->chandef.chan->band,
|
||||||
¶ms.beacon_rate);
|
¶ms->beacon_rate);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
|
if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
|
||||||
params.smps_mode =
|
params->smps_mode =
|
||||||
nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
|
nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
|
||||||
switch (params.smps_mode) {
|
switch (params->smps_mode) {
|
||||||
case NL80211_SMPS_OFF:
|
case NL80211_SMPS_OFF:
|
||||||
break;
|
break;
|
||||||
case NL80211_SMPS_STATIC:
|
case NL80211_SMPS_STATIC:
|
||||||
if (!(rdev->wiphy.features &
|
if (!(rdev->wiphy.features &
|
||||||
NL80211_FEATURE_STATIC_SMPS))
|
NL80211_FEATURE_STATIC_SMPS)) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NL80211_SMPS_DYNAMIC:
|
case NL80211_SMPS_DYNAMIC:
|
||||||
if (!(rdev->wiphy.features &
|
if (!(rdev->wiphy.features &
|
||||||
NL80211_FEATURE_DYNAMIC_SMPS))
|
NL80211_FEATURE_DYNAMIC_SMPS)) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
params.smps_mode = NL80211_SMPS_OFF;
|
params->smps_mode = NL80211_SMPS_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
|
params->pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
|
||||||
if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ])
|
if (params->pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
|
||||||
return -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
|
if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
|
||||||
params.acl = parse_acl_data(&rdev->wiphy, info);
|
params->acl = parse_acl_data(&rdev->wiphy, info);
|
||||||
if (IS_ERR(params.acl))
|
if (IS_ERR(params->acl)) {
|
||||||
return PTR_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]);
|
nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
|
if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
|
||||||
err = nl80211_parse_he_obss_pd(
|
err = nl80211_parse_he_obss_pd(
|
||||||
info->attrs[NL80211_ATTR_HE_OBSS_PD],
|
info->attrs[NL80211_ATTR_HE_OBSS_PD],
|
||||||
¶ms.he_obss_pd);
|
¶ms->he_obss_pd);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
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]) {
|
if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
|
||||||
err = nl80211_parse_he_bss_color(
|
err = nl80211_parse_he_bss_color(
|
||||||
info->attrs[NL80211_ATTR_HE_BSS_COLOR],
|
info->attrs[NL80211_ATTR_HE_BSS_COLOR],
|
||||||
¶ms.he_bss_color);
|
¶ms->he_bss_color);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
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]) {
|
if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
|
||||||
err = nl80211_parse_fils_discovery(rdev,
|
err = nl80211_parse_fils_discovery(rdev,
|
||||||
info->attrs[NL80211_ATTR_FILS_DISCOVERY],
|
info->attrs[NL80211_ATTR_FILS_DISCOVERY],
|
||||||
¶ms);
|
params);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
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]) {
|
if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
|
||||||
err = nl80211_parse_unsol_bcast_probe_resp(
|
err = nl80211_parse_unsol_bcast_probe_resp(
|
||||||
rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
|
rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
|
||||||
¶ms);
|
params);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
nl80211_calculate_ap_params(¶ms);
|
nl80211_calculate_ap_params(params);
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
|
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);
|
wdev_lock(wdev);
|
||||||
err = rdev_start_ap(rdev, dev, ¶ms);
|
err = rdev_start_ap(rdev, dev, params);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
wdev->preset_chandef = params.chandef;
|
wdev->preset_chandef = params->chandef;
|
||||||
wdev->beacon_interval = params.beacon_interval;
|
wdev->beacon_interval = params->beacon_interval;
|
||||||
wdev->chandef = params.chandef;
|
wdev->chandef = params->chandef;
|
||||||
wdev->ssid_len = params.ssid_len;
|
wdev->ssid_len = params->ssid_len;
|
||||||
memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
|
memcpy(wdev->ssid, params->ssid, wdev->ssid_len);
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
|
if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
|
||||||
wdev->conn_owner_nlportid = info->snd_portid;
|
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);
|
wdev_unlock(wdev);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(params.acl);
|
kfree(params->acl);
|
||||||
|
kfree(params);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче