Merge tag 'tomoyo-pr-20210215' of git://git.osdn.net/gitroot/tomoyo/tomoyo-test1
[linux-2.6-microblaze.git] / net / netlink / af_netlink.c
index d2d1448..dd48893 100644 (file)
@@ -67,6 +67,8 @@
 #include <net/sock.h>
 #include <net/scm.h>
 #include <net/netlink.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/netlink.h>
 
 #include "af_netlink.h"
 
@@ -147,6 +149,12 @@ static BLOCKING_NOTIFIER_HEAD(netlink_chain);
 
 static const struct rhashtable_params netlink_rhashtable_params;
 
+void do_trace_netlink_extack(const char *msg)
+{
+       trace_netlink_extack(msg);
+}
+EXPORT_SYMBOL(do_trace_netlink_extack);
+
 static inline u32 netlink_group_mask(u32 group)
 {
        return group ? 1 << (group - 1) : 0;
@@ -848,7 +856,7 @@ retry:
  *
  * Test to see if the opener of the socket we received the message
  * from had when the netlink socket was created and the sender of the
- * message has has the capability @cap in the user namespace @user_ns.
+ * message has the capability @cap in the user namespace @user_ns.
  */
 bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
                        struct user_namespace *user_ns, int cap)
@@ -867,7 +875,7 @@ EXPORT_SYMBOL(__netlink_ns_capable);
  *
  * Test to see if the opener of the socket we received the message
  * from had when the netlink socket was created and the sender of the
- * message has has the capability @cap in the user namespace @user_ns.
+ * message has the capability @cap in the user namespace @user_ns.
  */
 bool netlink_ns_capable(const struct sk_buff *skb,
                        struct user_namespace *user_ns, int cap)
@@ -883,7 +891,7 @@ EXPORT_SYMBOL(netlink_ns_capable);
  *
  * Test to see if the opener of the socket we received the message
  * from had when the netlink socket was created and the sender of the
- * message has has the capability @cap in all user namespaces.
+ * message has the capability @cap in all user namespaces.
  */
 bool netlink_capable(const struct sk_buff *skb, int cap)
 {
@@ -898,7 +906,7 @@ EXPORT_SYMBOL(netlink_capable);
  *
  * Test to see if the opener of the socket we received the message
  * from had when the netlink socket was created and the sender of the
- * message has has the capability @cap over the network namespace of
+ * message has the capability @cap over the network namespace of
  * the socket we received the message from.
  */
 bool netlink_net_capable(const struct sk_buff *skb, int cap)
@@ -1853,7 +1861,7 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
        struct scm_cookie scm;
        u32 netlink_skb_flags = 0;
 
-       if (msg->msg_flags&MSG_OOB)
+       if (msg->msg_flags & MSG_OOB)
                return -EOPNOTSUPP;
 
        err = scm_send(sock, msg, &scm, true);
@@ -1916,7 +1924,7 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
                refcount_inc(&skb->users);
                netlink_broadcast(sk, skb, dst_portid, dst_group, GFP_KERNEL);
        }
-       err = netlink_unicast(sk, skb, dst_portid, msg->msg_flags&MSG_DONTWAIT);
+       err = netlink_unicast(sk, skb, dst_portid, msg->msg_flags & MSG_DONTWAIT);
 
 out:
        scm_destroy(&scm);
@@ -1929,12 +1937,12 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
        struct scm_cookie scm;
        struct sock *sk = sock->sk;
        struct netlink_sock *nlk = nlk_sk(sk);
-       int noblock = flags&MSG_DONTWAIT;
+       int noblock = flags & MSG_DONTWAIT;
        size_t copied;
        struct sk_buff *skb, *data_skb;
        int err, ret;
 
-       if (flags&MSG_OOB)
+       if (flags & MSG_OOB)
                return -EOPNOTSUPP;
 
        copied = 0;
@@ -2186,13 +2194,35 @@ EXPORT_SYMBOL(__nlmsg_put);
  * It would be better to create kernel thread.
  */
 
+static int netlink_dump_done(struct netlink_sock *nlk, struct sk_buff *skb,
+                            struct netlink_callback *cb,
+                            struct netlink_ext_ack *extack)
+{
+       struct nlmsghdr *nlh;
+
+       nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, sizeof(nlk->dump_done_errno),
+                              NLM_F_MULTI | cb->answer_flags);
+       if (WARN_ON(!nlh))
+               return -ENOBUFS;
+
+       nl_dump_check_consistent(cb, nlh);
+       memcpy(nlmsg_data(nlh), &nlk->dump_done_errno, sizeof(nlk->dump_done_errno));
+
+       if (extack->_msg && nlk->flags & NETLINK_F_EXT_ACK) {
+               nlh->nlmsg_flags |= NLM_F_ACK_TLVS;
+               if (!nla_put_string(skb, NLMSGERR_ATTR_MSG, extack->_msg))
+                       nlmsg_end(skb, nlh);
+       }
+
+       return 0;
+}
+
 static int netlink_dump(struct sock *sk)
 {
        struct netlink_sock *nlk = nlk_sk(sk);
        struct netlink_ext_ack extack = {};
        struct netlink_callback *cb;
        struct sk_buff *skb = NULL;
-       struct nlmsghdr *nlh;
        struct module *module;
        int err = -ENOBUFS;
        int alloc_min_size;
@@ -2258,22 +2288,19 @@ static int netlink_dump(struct sock *sk)
                return 0;
        }
 
-       nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE,
-                              sizeof(nlk->dump_done_errno),
-                              NLM_F_MULTI | cb->answer_flags);
-       if (WARN_ON(!nlh))
+       if (netlink_dump_done(nlk, skb, cb, &extack))
                goto errout_skb;
 
-       nl_dump_check_consistent(cb, nlh);
-
-       memcpy(nlmsg_data(nlh), &nlk->dump_done_errno,
-              sizeof(nlk->dump_done_errno));
-
-       if (extack._msg && nlk->flags & NETLINK_F_EXT_ACK) {
-               nlh->nlmsg_flags |= NLM_F_ACK_TLVS;
-               if (!nla_put_string(skb, NLMSGERR_ATTR_MSG, extack._msg))
-                       nlmsg_end(skb, nlh);
+#ifdef CONFIG_COMPAT_NETLINK_MESSAGES
+       /* frag_list skb's data is used for compat tasks
+        * and the regular skb's data for normal (non-compat) tasks.
+        * See netlink_recvmsg().
+        */
+       if (unlikely(skb_shinfo(skb)->frag_list)) {
+               if (netlink_dump_done(nlk, skb_shinfo(skb)->frag_list, cb, &extack))
+                       goto errout_skb;
        }
+#endif
 
        if (sk_filter(sk, skb))
                kfree_skb(skb);
@@ -2401,6 +2428,8 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
                tlvlen += nla_total_size(sizeof(u32));
        if (nlk_has_extack && extack && extack->cookie_len)
                tlvlen += nla_total_size(extack->cookie_len);
+       if (err && nlk_has_extack && extack && extack->policy)
+               tlvlen += netlink_policy_dump_attr_size_estimate(extack->policy);
 
        if (tlvlen)
                flags |= NLM_F_ACK_TLVS;
@@ -2433,6 +2462,9 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
                if (extack->cookie_len)
                        WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE,
                                        extack->cookie_len, extack->cookie));
+               if (extack->policy)
+                       netlink_policy_dump_write_attr(skb, extack->policy,
+                                                      NLMSGERR_ATTR_POLICY);
        }
 
        nlmsg_end(skb, rep);