aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2016-06-15 16:29:41 -0400
committerJohannes Berg <johannes@sipsolutions.net>2016-06-30 06:06:18 -0400
commitf151d9db4c1e7f7ac202ae75f4cbc62cfc784156 (patch)
treeae01d35c364d904b7a159ccb03911b3b21ad61ad /net/wireless
parentf21e4d8ed16bb9cae27c7f1a07a2e0cd4daab736 (diff)
nl80211: improve nl80211_parse_mesh_config type checking
When building a kernel with W=1, the nl80211.c file causes a number of warnings, all about the same problem: net/wireless/nl80211.c: In function 'nl80211_parse_mesh_config': net/wireless/nl80211.c:5287:103: error: comparison is always false due to limited range of data type [-Werror=type-limits] net/wireless/nl80211.c:5290:96: error: comparison is always false due to limited range of data type [-Werror=type-limits] net/wireless/nl80211.c:5293:124: error: comparison is always false due to limited range of data type [-Werror=type-limits] net/wireless/nl80211.c:5295:148: error: comparison is always false due to limited range of data type [-Werror=type-limits] net/wireless/nl80211.c:5298:106: error: comparison is always false due to limited range of data type [-Werror=type-limits] net/wireless/nl80211.c:5305:116: error: comparison is always false due to limited range of data type [-Werror=type-limits] The problem is that gcc does not notice that the check is generate by a macro, so it complains about comparing an unsigned type against 0. I've tried to come up with a way to rephrase that code in a way that avoids the warnings and otherwise improves the code as well. This uses a set of new helper functions that perform the range checking, and should provide slightly better type safety than the older patch, at the expense of adding 44 lines to the code. Binary code size is basically unchanged though (20 bytes added to 126561 bytes .text). Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c104
1 files changed, 74 insertions, 30 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c503e96bfd5a..244d552d5647 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5287,6 +5287,51 @@ static const struct nla_policy
5287 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG }, 5287 [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
5288}; 5288};
5289 5289
5290static int nl80211_check_bool(const struct nlattr *nla, u8 min, u8 max, bool *out)
5291{
5292 u8 val = nla_get_u8(nla);
5293 if (val < min || val > max)
5294 return -EINVAL;
5295 *out = val;
5296 return 0;
5297}
5298
5299static int nl80211_check_u8(const struct nlattr *nla, u8 min, u8 max, u8 *out)
5300{
5301 u8 val = nla_get_u8(nla);
5302 if (val < min || val > max)
5303 return -EINVAL;
5304 *out = val;
5305 return 0;
5306}
5307
5308static int nl80211_check_u16(const struct nlattr *nla, u16 min, u16 max, u16 *out)
5309{
5310 u16 val = nla_get_u16(nla);
5311 if (val < min || val > max)
5312 return -EINVAL;
5313 *out = val;
5314 return 0;
5315}
5316
5317static int nl80211_check_u32(const struct nlattr *nla, u32 min, u32 max, u32 *out)
5318{
5319 u32 val = nla_get_u32(nla);
5320 if (val < min || val > max)
5321 return -EINVAL;
5322 *out = val;
5323 return 0;
5324}
5325
5326static int nl80211_check_s32(const struct nlattr *nla, s32 min, s32 max, s32 *out)
5327{
5328 s32 val = nla_get_s32(nla);
5329 if (val < min || val > max)
5330 return -EINVAL;
5331 *out = val;
5332 return 0;
5333}
5334
5290static int nl80211_parse_mesh_config(struct genl_info *info, 5335static int nl80211_parse_mesh_config(struct genl_info *info,
5291 struct mesh_config *cfg, 5336 struct mesh_config *cfg,
5292 u32 *mask_out) 5337 u32 *mask_out)
@@ -5297,9 +5342,8 @@ static int nl80211_parse_mesh_config(struct genl_info *info,
5297#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \ 5342#define FILL_IN_MESH_PARAM_IF_SET(tb, cfg, param, min, max, mask, attr, fn) \
5298do { \ 5343do { \
5299 if (tb[attr]) { \ 5344 if (tb[attr]) { \
5300 if (fn(tb[attr]) < min || fn(tb[attr]) > max) \ 5345 if (fn(tb[attr], min, max, &cfg->param)) \
5301 return -EINVAL; \ 5346 return -EINVAL; \
5302 cfg->param = fn(tb[attr]); \
5303 mask |= (1 << (attr - 1)); \ 5347 mask |= (1 << (attr - 1)); \
5304 } \ 5348 } \
5305} while (0) 5349} while (0)
@@ -5318,99 +5362,99 @@ do { \
5318 /* Fill in the params struct */ 5362 /* Fill in the params struct */
5319 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255, 5363 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshRetryTimeout, 1, 255,
5320 mask, NL80211_MESHCONF_RETRY_TIMEOUT, 5364 mask, NL80211_MESHCONF_RETRY_TIMEOUT,
5321 nla_get_u16); 5365 nl80211_check_u16);
5322 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255, 5366 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshConfirmTimeout, 1, 255,
5323 mask, NL80211_MESHCONF_CONFIRM_TIMEOUT, 5367 mask, NL80211_MESHCONF_CONFIRM_TIMEOUT,
5324 nla_get_u16); 5368 nl80211_check_u16);
5325 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255, 5369 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHoldingTimeout, 1, 255,
5326 mask, NL80211_MESHCONF_HOLDING_TIMEOUT, 5370 mask, NL80211_MESHCONF_HOLDING_TIMEOUT,
5327 nla_get_u16); 5371 nl80211_check_u16);
5328 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255, 5372 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxPeerLinks, 0, 255,
5329 mask, NL80211_MESHCONF_MAX_PEER_LINKS, 5373 mask, NL80211_MESHCONF_MAX_PEER_LINKS,
5330 nla_get_u16); 5374 nl80211_check_u16);
5331 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16, 5375 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshMaxRetries, 0, 16,
5332 mask, NL80211_MESHCONF_MAX_RETRIES, 5376 mask, NL80211_MESHCONF_MAX_RETRIES,
5333 nla_get_u8); 5377 nl80211_check_u8);
5334 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255, 5378 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshTTL, 1, 255,
5335 mask, NL80211_MESHCONF_TTL, nla_get_u8); 5379 mask, NL80211_MESHCONF_TTL, nl80211_check_u8);
5336 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255, 5380 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, element_ttl, 1, 255,
5337 mask, NL80211_MESHCONF_ELEMENT_TTL, 5381 mask, NL80211_MESHCONF_ELEMENT_TTL,
5338 nla_get_u8); 5382 nl80211_check_u8);
5339 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 0, 1, 5383 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, 0, 1,
5340 mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, 5384 mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
5341 nla_get_u8); 5385 nl80211_check_bool);
5342 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor, 5386 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor,
5343 1, 255, mask, 5387 1, 255, mask,
5344 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, 5388 NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR,
5345 nla_get_u32); 5389 nl80211_check_u32);
5346 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255, 5390 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, 0, 255,
5347 mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, 5391 mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES,
5348 nla_get_u8); 5392 nl80211_check_u8);
5349 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535, 5393 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, path_refresh_time, 1, 65535,
5350 mask, NL80211_MESHCONF_PATH_REFRESH_TIME, 5394 mask, NL80211_MESHCONF_PATH_REFRESH_TIME,
5351 nla_get_u32); 5395 nl80211_check_u32);
5352 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535, 5396 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, min_discovery_timeout, 1, 65535,
5353 mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, 5397 mask, NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT,
5354 nla_get_u16); 5398 nl80211_check_u16);
5355 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout, 5399 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathTimeout,
5356 1, 65535, mask, 5400 1, 65535, mask,
5357 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, 5401 NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT,
5358 nla_get_u32); 5402 nl80211_check_u32);
5359 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, 5403 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval,
5360 1, 65535, mask, 5404 1, 65535, mask,
5361 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, 5405 NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL,
5362 nla_get_u16); 5406 nl80211_check_u16);
5363 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, 5407 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval,
5364 1, 65535, mask, 5408 1, 65535, mask,
5365 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, 5409 NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
5366 nla_get_u16); 5410 nl80211_check_u16);
5367 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, 5411 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
5368 dot11MeshHWMPnetDiameterTraversalTime, 5412 dot11MeshHWMPnetDiameterTraversalTime,
5369 1, 65535, mask, 5413 1, 65535, mask,
5370 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, 5414 NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
5371 nla_get_u16); 5415 nl80211_check_u16);
5372 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4, 5416 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRootMode, 0, 4,
5373 mask, NL80211_MESHCONF_HWMP_ROOTMODE, 5417 mask, NL80211_MESHCONF_HWMP_ROOTMODE,
5374 nla_get_u8); 5418 nl80211_check_u8);
5375 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535, 5419 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPRannInterval, 1, 65535,
5376 mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL, 5420 mask, NL80211_MESHCONF_HWMP_RANN_INTERVAL,
5377 nla_get_u16); 5421 nl80211_check_u16);
5378 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, 5422 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
5379 dot11MeshGateAnnouncementProtocol, 0, 1, 5423 dot11MeshGateAnnouncementProtocol, 0, 1,
5380 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, 5424 mask, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
5381 nla_get_u8); 5425 nl80211_check_bool);
5382 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1, 5426 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1,
5383 mask, NL80211_MESHCONF_FORWARDING, 5427 mask, NL80211_MESHCONF_FORWARDING,
5384 nla_get_u8); 5428 nl80211_check_bool);
5385 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0, 5429 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,
5386 mask, NL80211_MESHCONF_RSSI_THRESHOLD, 5430 mask, NL80211_MESHCONF_RSSI_THRESHOLD,
5387 nla_get_s32); 5431 nl80211_check_s32);
5388 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16, 5432 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16,
5389 mask, NL80211_MESHCONF_HT_OPMODE, 5433 mask, NL80211_MESHCONF_HT_OPMODE,
5390 nla_get_u16); 5434 nl80211_check_u16);
5391 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout, 5435 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
5392 1, 65535, mask, 5436 1, 65535, mask,
5393 NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, 5437 NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
5394 nla_get_u32); 5438 nl80211_check_u32);
5395 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, 1, 65535, 5439 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMProotInterval, 1, 65535,
5396 mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL, 5440 mask, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
5397 nla_get_u16); 5441 nl80211_check_u16);
5398 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, 5442 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
5399 dot11MeshHWMPconfirmationInterval, 5443 dot11MeshHWMPconfirmationInterval,
5400 1, 65535, mask, 5444 1, 65535, mask,
5401 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, 5445 NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
5402 nla_get_u16); 5446 nl80211_check_u16);
5403 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, 5447 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode,
5404 NL80211_MESH_POWER_ACTIVE, 5448 NL80211_MESH_POWER_ACTIVE,
5405 NL80211_MESH_POWER_MAX, 5449 NL80211_MESH_POWER_MAX,
5406 mask, NL80211_MESHCONF_POWER_MODE, 5450 mask, NL80211_MESHCONF_POWER_MODE,
5407 nla_get_u32); 5451 nl80211_check_u32);
5408 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, 5452 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration,
5409 0, 65535, mask, 5453 0, 65535, mask,
5410 NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16); 5454 NL80211_MESHCONF_AWAKE_WINDOW, nl80211_check_u16);
5411 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 0, 0xffffffff, 5455 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, plink_timeout, 0, 0xffffffff,
5412 mask, NL80211_MESHCONF_PLINK_TIMEOUT, 5456 mask, NL80211_MESHCONF_PLINK_TIMEOUT,
5413 nla_get_u32); 5457 nl80211_check_u32);
5414 if (mask_out) 5458 if (mask_out)
5415 *mask_out = mask; 5459 *mask_out = mask;
5416 5460