cfg80211: clear nl80211 messages carrying keys after processing
authorJohannes Berg <johannes.berg@intel.com>
Wed, 10 Sep 2014 12:00:16 +0000 (15:00 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 11 Sep 2014 10:07:39 +0000 (12:07 +0200)
Clear any nl80211 messages that might contain keys after
processing them to avoid leaving their data in memory
"forever" after they've been freed.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/wireless/nl80211.c

index bebdf3d..e9fbd4f 100644 (file)
@@ -9400,6 +9400,7 @@ static int nl80211_set_qos_map(struct sk_buff *skb,
 /* If a netdev is associated, it must be UP, P2P must be started */
 #define NL80211_FLAG_NEED_WDEV_UP      (NL80211_FLAG_NEED_WDEV |\
                                         NL80211_FLAG_CHECK_NETDEV_UP)
+#define NL80211_FLAG_CLEAR_SKB         0x20
 
 static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
                            struct genl_info *info)
@@ -9483,8 +9484,20 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
                        dev_put(info->user_ptr[1]);
                }
        }
+
        if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
                rtnl_unlock();
+
+       /* If needed, clear the netlink message payload from the SKB
+        * as it might contain key data that shouldn't stick around on
+        * the heap after the SKB is freed. The netlink message header
+        * is still needed for further processing, so leave it intact.
+        */
+       if (ops->internal_flags & NL80211_FLAG_CLEAR_SKB) {
+               struct nlmsghdr *nlh = nlmsg_hdr(skb);
+
+               memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
+       }
 }
 
 static const struct genl_ops nl80211_ops[] = {
@@ -9552,7 +9565,8 @@ static const struct genl_ops nl80211_ops[] = {
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
-                                 NL80211_FLAG_NEED_RTNL,
+                                 NL80211_FLAG_NEED_RTNL |
+                                 NL80211_FLAG_CLEAR_SKB,
        },
        {
                .cmd = NL80211_CMD_NEW_KEY,
@@ -9560,7 +9574,8 @@ static const struct genl_ops nl80211_ops[] = {
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
-                                 NL80211_FLAG_NEED_RTNL,
+                                 NL80211_FLAG_NEED_RTNL |
+                                 NL80211_FLAG_CLEAR_SKB,
        },
        {
                .cmd = NL80211_CMD_DEL_KEY,
@@ -9738,7 +9753,8 @@ static const struct genl_ops nl80211_ops[] = {
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
-                                 NL80211_FLAG_NEED_RTNL,
+                                 NL80211_FLAG_NEED_RTNL |
+                                 NL80211_FLAG_CLEAR_SKB,
        },
        {
                .cmd = NL80211_CMD_ASSOCIATE,
@@ -9972,7 +9988,8 @@ static const struct genl_ops nl80211_ops[] = {
                .policy = nl80211_policy,
                .flags = GENL_ADMIN_PERM,
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
-                                 NL80211_FLAG_NEED_RTNL,
+                                 NL80211_FLAG_NEED_RTNL |
+                                 NL80211_FLAG_CLEAR_SKB,
        },
        {
                .cmd = NL80211_CMD_TDLS_MGMT,