Skip to content

Commit

Permalink
wifi: cfg80211: Avoid clashing function prototypes
Browse files Browse the repository at this point in the history
When built with Control Flow Integrity, function prototypes between
caller and function declaration must match. These mismatches are visible
at compile time with the new -Wcast-function-type-strict in Clang[1].

Fix a total of 73 warnings like these:

drivers/net/wireless/intersil/orinoco/wext.c:1379:27: warning: cast from 'int (*)(struct net_device *, struct iw_request_info *, struct iw_param *, char *)' to 'iw_handler' (aka 'int (*)(struct net_device *, struct iw_request_info *, union iwreq_data *, char *)') converts to incompatible function type [-Wcast-function-type-strict]
        IW_HANDLER(SIOCGIWPOWER,        (iw_handler)orinoco_ioctl_getpower),
                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

../net/wireless/wext-compat.c:1607:33: warning: cast from 'int (*)(struct net_device *, struct iw_request_info *, struct iw_point *, char *)' to 'iw_handler' (aka 'int (*)(struct net_device *, struct iw_request_info *, union iwreq_data *, char *)') converts to incompatible function type [-Wcast-function-type-strict]
        [IW_IOCTL_IDX(SIOCSIWGENIE)]    = (iw_handler) cfg80211_wext_siwgenie,
                                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

../drivers/net/wireless/intersil/orinoco/wext.c:1390:27: error: incompatible function pointer types initializing 'const iw_handler' (aka 'int (*const)(struct net_device *, struct iw_request_info *, union iwreq_data *, char *)') with an expression of type 'int (struct net_device *, struct iw_request_info *, struct iw_param *, char *)' [-Wincompatible-function-pointer-types]
        IW_HANDLER(SIOCGIWRETRY,        cfg80211_wext_giwretry),
                                        ^~~~~~~~~~~~~~~~~~~~~~

The cfg80211 Wireless Extension handler callbacks (iw_handler) use a
union for the data argument. Actually use the union and perform explicit
member selection in the function body instead of having a function
prototype mismatch. There are no resulting binary differences
before/after changes.

These changes were made partly manually and partly with the help of
Coccinelle.

Link: https://github.com/KSPP/linux/issues/234
Link: https://reviews.llvm.org/D134831 [1]
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/a68822bf8dd587988131bb6a295280cb4293f05d.1667934775.git.gustavoars@kernel.org
  • Loading branch information
Gustavo A. R. Silva authored and Kalle Valo committed Nov 16, 2022
1 parent 2c0e077 commit 02ae6a7
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 127 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/intel/ipw2x00/ipw2200.c
Original file line number Diff line number Diff line change
Expand Up @@ -9856,7 +9856,7 @@ static int ipw_wx_sw_reset(struct net_device *dev,

/* Rebase the WE IOCTLs to zero for the handler array */
static iw_handler ipw_wx_handlers[] = {
IW_HANDLER(SIOCGIWNAME, (iw_handler)cfg80211_wext_giwname),
IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname),
IW_HANDLER(SIOCSIWFREQ, ipw_wx_set_freq),
IW_HANDLER(SIOCGIWFREQ, ipw_wx_get_freq),
IW_HANDLER(SIOCSIWMODE, ipw_wx_set_mode),
Expand Down
22 changes: 11 additions & 11 deletions drivers/net/wireless/intersil/orinoco/wext.c
Original file line number Diff line number Diff line change
Expand Up @@ -1363,31 +1363,31 @@ static const struct iw_priv_args orinoco_privtab[] = {

static const iw_handler orinoco_handler[] = {
IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit),
IW_HANDLER(SIOCGIWNAME, (iw_handler)cfg80211_wext_giwname),
IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname),
IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq),
IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq),
IW_HANDLER(SIOCSIWMODE, (iw_handler)cfg80211_wext_siwmode),
IW_HANDLER(SIOCGIWMODE, (iw_handler)cfg80211_wext_giwmode),
IW_HANDLER(SIOCSIWMODE, cfg80211_wext_siwmode),
IW_HANDLER(SIOCGIWMODE, cfg80211_wext_giwmode),
IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens),
IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens),
IW_HANDLER(SIOCGIWRANGE, (iw_handler)cfg80211_wext_giwrange),
IW_HANDLER(SIOCGIWRANGE, cfg80211_wext_giwrange),
IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap),
IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap),
IW_HANDLER(SIOCSIWSCAN, (iw_handler)cfg80211_wext_siwscan),
IW_HANDLER(SIOCGIWSCAN, (iw_handler)cfg80211_wext_giwscan),
IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan),
IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan),
IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid),
IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid),
IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate),
IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate),
IW_HANDLER(SIOCSIWRTS, (iw_handler)cfg80211_wext_siwrts),
IW_HANDLER(SIOCGIWRTS, (iw_handler)cfg80211_wext_giwrts),
IW_HANDLER(SIOCSIWFRAG, (iw_handler)cfg80211_wext_siwfrag),
IW_HANDLER(SIOCGIWFRAG, (iw_handler)cfg80211_wext_giwfrag),
IW_HANDLER(SIOCGIWRETRY, (iw_handler)cfg80211_wext_giwretry),
IW_HANDLER(SIOCSIWRTS, cfg80211_wext_siwrts),
IW_HANDLER(SIOCGIWRTS, cfg80211_wext_giwrts),
IW_HANDLER(SIOCSIWFRAG, cfg80211_wext_siwfrag),
IW_HANDLER(SIOCGIWFRAG, cfg80211_wext_giwfrag),
IW_HANDLER(SIOCGIWRETRY, cfg80211_wext_giwretry),
IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode),
IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode),
IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower),
Expand Down
20 changes: 10 additions & 10 deletions include/net/cfg80211-wext.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,34 @@
*/
int cfg80211_wext_giwname(struct net_device *dev,
struct iw_request_info *info,
char *name, char *extra);
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
u32 *mode, char *extra);
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
u32 *mode, char *extra);
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_siwscan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_giwscan(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra);
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_giwrange(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra);
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_siwrts(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rts, char *extra);
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_giwrts(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rts, char *extra);
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_siwfrag(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *frag, char *extra);
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_giwfrag(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *frag, char *extra);
union iwreq_data *wrqu, char *extra);
int cfg80211_wext_giwretry(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *retry, char *extra);
union iwreq_data *wrqu, char *extra);

#endif /* __NET_CFG80211_WEXT_H */
3 changes: 2 additions & 1 deletion net/wireless/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -3229,8 +3229,9 @@ static int ieee80211_scan_results(struct cfg80211_registered_device *rdev,

int cfg80211_wext_giwscan(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra)
union iwreq_data *wrqu, char *extra)
{
struct iw_point *data = &wrqu->data;
struct cfg80211_registered_device *rdev;
int res;

Expand Down
Loading

0 comments on commit 02ae6a7

Please sign in to comment.