netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH net-next 0/9] netlink: strict attribute checking option
@ 2015-10-15 16:39 Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 1/9] netlink: add NLM_F_STRICT for strict attribute checking Jiri Benc
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-15 16:39 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Graf

When sending a netlink request (NLM_F_REQUEST), any unknown attributes are
ignored. This behavior is problematic in some situations. For example if the
user asks for a particular config, the request finishes successfully, yet
the configuraton applied does not work because some of the attributes are
not supported by the kernel (e.g. because it's older than the user space
tool).

We're hitting this when configuring metadata based lwtunnels from user space
applications: it would be surely nice if iproute2 warned about this, as the
resulting tunnel silently won't work with encap routes. Worse, it's quite
crucial for openvswitch and similar programs when deciding what kernel API
(lwtunnel vs. legacy) to use.

This patchset tries to solve this. Everything should be compatible with old
kernels that don't have this patchset.

Before using this new facility, the application should check whether it is
supported by the kernel. This is done by sending a NLMSG_NOOP message with
NLM_F_REQUEST | NLM_F_STRICT | NLM_F_ACK flags set. If the returned message
has NLM_F_STRICT set, the kernel does support NLM_F_STRICT flag; otherwise,
the flag should not be used.

When NLM_F_STRICT is set in a request, the request undergoes stricter
checking for compatibility with the current kernel. Presence of any
attribute unknown to the kernel will mean the message will be rejected and
error returned. In case of success, the request has been performed in the
same way as if NLM_F_STRICT was not set.

However, the sole fact that NLM_F_STRICT is supported by the kernel does not
yet mean it is supported for the particular netlink family and/or message
type. If EPROTO is returned in an error reply, it means that the particular
netlink family/message does not support NLM_F_STRICT (yet). In such case,
the application could fall back to operation without using NLM_F_STRICT
(which is needed for older kernels anyway), possibly warning users that some
options may have been ignored by the kernel, if appropriate.

Another option for using this facility is just set NLM_F_STRICT with
NLM_F_ACK in a request. There are four results that could happen:

1. Request succeeds and NLM_F_STRICT is set in the reply. Everything is good
   and verified in this case.
2. Request succeeds but NLM_F_STRICT is not set in the reply. The request
   was processed but some attributes might (or might not) be ignored because
   the kernel does not understand NLM_F_STRICT. Warn user if appropriate.
3. Request fails with EPROTO. This means NLM_F_STRICT is not supported for
   this request. Depending on the needs of the application, either fail hard
   or try again without NLM_F_STRICT, warning user if appropriate.
4. Request fails with other error code. The request did not succeed.

Applications with hard depency on new kernel features that implement strict
checking may choose to abort if NLM_F_STRICT is not set in the reply to
NLMSG_NOOP, always use NLM_F_STRICT and treat EPROTO as any other error
code.

Note that this RFC patchset is completely untested and may not compile on
all configs. I'd like to get feedback on whether this makes sense. For
example, I'm not thrilled about the EPROTO error code. Suggestions for
a better one are welcome - it needs to be one that is never returned by
any netlink operation, though.

Jiri Benc (9):
  netlink: add NLM_F_STRICT for strict attribute checking
  netlink: remove unnecesary goto's
  netlink: strict attribute parsing
  netlink: strict attribute validation
  rtnetlink: support strict attribute checking
  rtnetlink: add strict parameter to validate callbacks
  rtnetlink: add strict parameter to validate_link_af
  rtnetlink: support strict checking for newlink, setlink and dellink
  veth: validate nested attributes

 crypto/crypto_user.c               |   2 +-
 drivers/infiniband/core/netlink.c  |   2 +-
 drivers/net/bonding/bond_netlink.c |   3 +-
 drivers/net/dummy.c                |   3 +-
 drivers/net/geneve.c               |   3 +-
 drivers/net/ifb.c                  |   3 +-
 drivers/net/ipvlan/ipvlan_main.c   |   3 +-
 drivers/net/macvlan.c              |   3 +-
 drivers/net/nlmon.c                |   3 +-
 drivers/net/team/team.c            |   3 +-
 drivers/net/tun.c                  |   3 +-
 drivers/net/veth.c                 |  13 +++-
 drivers/net/vrf.c                  |   3 +-
 drivers/net/vxlan.c                |   3 +-
 include/net/netlink.h              | 144 ++++++++++++++++++++++++++++++++-----
 include/net/rtnetlink.h            |  37 ++++++++--
 include/uapi/linux/netlink.h       |   1 +
 lib/nlattr.c                       |  56 +++++++++------
 net/8021q/vlan_netlink.c           |  12 ++--
 net/bridge/br_netlink.c            |   3 +-
 net/core/rtnetlink.c               | 143 ++++++++++++++++++++++--------------
 net/core/sock_diag.c               |   2 +-
 net/ieee802154/6lowpan/core.c      |   3 +-
 net/ipv4/devinet.c                 |   6 +-
 net/ipv4/ip_gre.c                  |   8 ++-
 net/ipv4/ip_vti.c                  |   3 +-
 net/ipv6/addrconf.c                |   6 +-
 net/ipv6/ip6_gre.c                 |   8 ++-
 net/ipv6/ip6_tunnel.c              |   3 +-
 net/ipv6/ip6_vti.c                 |   3 +-
 net/ipv6/sit.c                     |   3 +-
 net/netfilter/nfnetlink.c          |   6 +-
 net/netlink/af_netlink.c           |  14 +++-
 net/netlink/genetlink.c            |   2 +-
 net/xfrm/xfrm_user.c               |   2 +-
 35 files changed, 371 insertions(+), 144 deletions(-)

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC PATCH net-next 1/9] netlink: add NLM_F_STRICT for strict attribute checking
  2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
@ 2015-10-15 16:39 ` Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 2/9] netlink: remove unnecesary goto's Jiri Benc
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-15 16:39 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Graf

When NLM_F_STRICT flag is set in a request, the message should undergo
stricter check for compatibility with the current kernel, or EPROTO should
be returned if such check could not be performed. In addition, NLM_F_STRICT
is set in error/ack reply to a request with this flag set.

For now, always return EPROTO.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
---
 crypto/crypto_user.c              |  2 +-
 drivers/infiniband/core/netlink.c |  2 +-
 include/net/netlink.h             |  2 +-
 include/uapi/linux/netlink.h      |  1 +
 net/core/rtnetlink.c              |  2 +-
 net/core/sock_diag.c              |  2 +-
 net/netfilter/nfnetlink.c         |  6 +++++-
 net/netlink/af_netlink.c          | 14 +++++++++++---
 net/netlink/genetlink.c           |  2 +-
 net/xfrm/xfrm_user.c              |  2 +-
 10 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index d94d99ffe8b9..8d46d3b69bee 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -526,7 +526,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 static void crypto_netlink_rcv(struct sk_buff *skb)
 {
 	mutex_lock(&crypto_cfg_mutex);
-	netlink_rcv_skb(skb, &crypto_user_rcv_msg);
+	netlink_rcv_skb(skb, false, &crypto_user_rcv_msg);
 	mutex_unlock(&crypto_cfg_mutex);
 }
 
diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c
index d47df9356779..1429c0cf583b 100644
--- a/drivers/infiniband/core/netlink.c
+++ b/drivers/infiniband/core/netlink.c
@@ -223,7 +223,7 @@ static void ibnl_rcv(struct sk_buff *skb)
 {
 	mutex_lock(&ibnl_mutex);
 	ibnl_rcv_reply_skb(skb);
-	netlink_rcv_skb(skb, &ibnl_rcv_msg);
+	netlink_rcv_skb(skb, false, &ibnl_rcv_msg);
 	mutex_unlock(&ibnl_mutex);
 }
 
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 0e3172751755..160e98cea304 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -228,7 +228,7 @@ struct nl_info {
 	u32			portid;
 };
 
-int netlink_rcv_skb(struct sk_buff *skb,
+int netlink_rcv_skb(struct sk_buff *skb, bool strict_supported,
 		    int (*cb)(struct sk_buff *, struct nlmsghdr *));
 int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
 		 unsigned int group, int report, gfp_t flags);
diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h
index f095155d8749..c001551fcedd 100644
--- a/include/uapi/linux/netlink.h
+++ b/include/uapi/linux/netlink.h
@@ -55,6 +55,7 @@ struct nlmsghdr {
 #define NLM_F_ECHO		8	/* Echo this request 		*/
 #define NLM_F_DUMP_INTR		16	/* Dump was inconsistent due to sequence change */
 #define NLM_F_DUMP_FILTERED	32	/* Dump was filtered as requested */
+#define NLM_F_STRICT		64	/* Fail if an attr is unsupported */
 
 /* Modifiers to GET request */
 #define NLM_F_ROOT	0x100	/* specify tree	root	*/
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 24775953fa68..afb41c7492b4 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -3356,7 +3356,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 static void rtnetlink_rcv(struct sk_buff *skb)
 {
 	rtnl_lock();
-	netlink_rcv_skb(skb, &rtnetlink_rcv_msg);
+	netlink_rcv_skb(skb, false, &rtnetlink_rcv_msg);
 	rtnl_unlock();
 }
 
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index 0c1d58d43f67..3aac827d1d67 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -272,7 +272,7 @@ static DEFINE_MUTEX(sock_diag_mutex);
 static void sock_diag_rcv(struct sk_buff *skb)
 {
 	mutex_lock(&sock_diag_mutex);
-	netlink_rcv_skb(skb, &sock_diag_rcv_msg);
+	netlink_rcv_skb(skb, false, &sock_diag_rcv_msg);
 	mutex_unlock(&sock_diag_mutex);
 }
 
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index f1d9e887f5b1..f7588dec4d23 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -339,6 +339,10 @@ replay:
 			err = -EINVAL;
 			goto ack;
 		}
+		if (nlh->nlmsg_flags & NLM_F_STRICT) {
+			err = -EPROTO;
+			goto ack;
+		}
 
 		type = nlh->nlmsg_type;
 		if (type == NFNL_MSG_BATCH_BEGIN) {
@@ -476,7 +480,7 @@ static void nfnetlink_rcv(struct sk_buff *skb)
 			res_id = ntohs(nfgenmsg->res_id);
 		nfnetlink_rcv_batch(skb, nlh, res_id);
 	} else {
-		netlink_rcv_skb(skb, &nfnetlink_rcv_msg);
+		netlink_rcv_skb(skb, false, &nfnetlink_rcv_msg);
 	}
 }
 
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 8f060d7f9a0e..d59d02038128 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2944,6 +2944,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
 	struct nlmsgerr *errmsg;
 	size_t payload = sizeof(*errmsg);
 	struct netlink_sock *nlk = nlk_sk(NETLINK_CB(in_skb).sk);
+	unsigned int flags = 0;
 
 	/* Error messages get the original request appened, unless the user
 	 * requests to cap the error message.
@@ -2967,8 +2968,10 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
 		return;
 	}
 
+	if (nlh->nlmsg_flags & NLM_F_STRICT)
+		flags |= NLM_F_STRICT;
 	rep = __nlmsg_put(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq,
-			  NLMSG_ERROR, payload, 0);
+			  NLMSG_ERROR, payload, flags);
 	errmsg = nlmsg_data(rep);
 	errmsg->error = err;
 	memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh));
@@ -2976,8 +2979,8 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
 }
 EXPORT_SYMBOL(netlink_ack);
 
-int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
-						     struct nlmsghdr *))
+int netlink_rcv_skb(struct sk_buff *skb, bool strict_supported,
+		    int (*cb)(struct sk_buff *, struct nlmsghdr *))
 {
 	struct nlmsghdr *nlh;
 	int err;
@@ -2995,6 +2998,11 @@ int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
 		if (!(nlh->nlmsg_flags & NLM_F_REQUEST))
 			goto ack;
 
+		if (!strict_supported && (nlh->nlmsg_flags & NLM_F_STRICT)) {
+			err = -EPROTO;
+			goto ack;
+		}
+
 		/* Skip control messages */
 		if (nlh->nlmsg_type < NLMSG_MIN_TYPE)
 			goto ack;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index bc0e504f33a6..d7bf14420c9e 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -667,7 +667,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 static void genl_rcv(struct sk_buff *skb)
 {
 	down_read(&cb_lock);
-	netlink_rcv_skb(skb, &genl_rcv_msg);
+	netlink_rcv_skb(skb, false, &genl_rcv_msg);
 	up_read(&cb_lock);
 }
 
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index a8de9e300200..bcde073f59db 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2491,7 +2491,7 @@ static void xfrm_netlink_rcv(struct sk_buff *skb)
 	struct net *net = sock_net(skb->sk);
 
 	mutex_lock(&net->xfrm.xfrm_cfg_mutex);
-	netlink_rcv_skb(skb, &xfrm_user_rcv_msg);
+	netlink_rcv_skb(skb, false, &xfrm_user_rcv_msg);
 	mutex_unlock(&net->xfrm.xfrm_cfg_mutex);
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH net-next 2/9] netlink: remove unnecesary goto's
  2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 1/9] netlink: add NLM_F_STRICT for strict attribute checking Jiri Benc
@ 2015-10-15 16:39 ` Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 3/9] netlink: strict attribute parsing Jiri Benc
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-15 16:39 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Graf

Jumping to the return makes the code less readable. The compiler will
optimize this just fine.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
---
 lib/nlattr.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/lib/nlattr.c b/lib/nlattr.c
index f5907d23272d..b35c3e6c8e81 100644
--- a/lib/nlattr.c
+++ b/lib/nlattr.c
@@ -128,12 +128,10 @@ int nla_validate(const struct nlattr *head, int len, int maxtype,
 	nla_for_each_attr(nla, head, len, rem) {
 		err = validate_nla(nla, maxtype, policy);
 		if (err < 0)
-			goto errout;
+			return err;
 	}
 
-	err = 0;
-errout:
-	return err;
+	return 0;
 }
 EXPORT_SYMBOL(nla_validate);
 
@@ -194,7 +192,7 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
 			if (policy) {
 				err = validate_nla(nla, maxtype, policy);
 				if (err < 0)
-					goto errout;
+					return err;
 			}
 
 			tb[type] = (struct nlattr *)nla;
@@ -205,9 +203,7 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
 		pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n",
 				    rem, current->comm);
 
-	err = 0;
-errout:
-	return err;
+	return 0;
 }
 EXPORT_SYMBOL(nla_parse);
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH net-next 3/9] netlink: strict attribute parsing
  2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 1/9] netlink: add NLM_F_STRICT for strict attribute checking Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 2/9] netlink: remove unnecesary goto's Jiri Benc
@ 2015-10-15 16:39 ` Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 4/9] netlink: strict attribute validation Jiri Benc
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-15 16:39 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Graf

Enhance the attribute parsing functions to support strict attribute
checking. Keep the semantics of the current nla_parse and nlmsg_parse
functions, it's better then changing hundreds of call sites all around the
kernel.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
---
 include/net/netlink.h | 75 ++++++++++++++++++++++++++++++++++++++++++++-------
 lib/nlattr.c          | 20 +++++++++-----
 2 files changed, 80 insertions(+), 15 deletions(-)

diff --git a/include/net/netlink.h b/include/net/netlink.h
index 160e98cea304..dcca6853913d 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -235,8 +235,9 @@ int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
 
 int nla_validate(const struct nlattr *head, int len, int maxtype,
 		 const struct nla_policy *policy);
-int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
-	      int len, const struct nla_policy *policy);
+int nla_strict_parse(struct nlattr **tb, int maxtype, bool strict,
+		     const struct nlattr *head, int len,
+		     const struct nla_policy *policy);
 int nla_policy_len(const struct nla_policy *, int);
 struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype);
 size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize);
@@ -356,6 +357,30 @@ nlmsg_next(const struct nlmsghdr *nlh, int *remaining)
 }
 
 /**
+ * nlmsg_strict_parse - parse attributes of a netlink message
+ * @nlh: netlink message header
+ * @hdrlen: length of family specific header
+ * @tb: destination array with maxtype+1 elements
+ * @maxtype: maximum attribute type to be expected
+ * @strict: whether to perform strict checking
+ * @policy: validation policy
+ *
+ * See nla_strict_parse().
+ */
+static inline int nlmsg_strict_parse(const struct nlmsghdr *nlh, int hdrlen,
+				     struct nlattr *tb[], int maxtype,
+				     bool strict,
+				     const struct nla_policy *policy)
+{
+	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
+		return -EINVAL;
+
+	return nla_strict_parse(tb, maxtype, strict,
+				nlmsg_attrdata(nlh, hdrlen),
+				nlmsg_attrlen(nlh, hdrlen), policy);
+}
+
+/**
  * nlmsg_parse - parse attributes of a netlink message
  * @nlh: netlink message header
  * @hdrlen: length of family specific header
@@ -363,17 +388,13 @@ nlmsg_next(const struct nlmsghdr *nlh, int *remaining)
  * @maxtype: maximum attribute type to be expected
  * @policy: validation policy
  *
- * See nla_parse()
+ * See nla_strict_parse(). Strict checking is not performed.
  */
 static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
 			      struct nlattr *tb[], int maxtype,
 			      const struct nla_policy *policy)
 {
-	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
-		return -EINVAL;
-
-	return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
-			 nlmsg_attrlen(nlh, hdrlen), policy);
+	return nlmsg_strict_parse(nlh, hdrlen, tb, maxtype, false, policy);
 }
 
 /**
@@ -722,13 +743,49 @@ nla_find_nested(const struct nlattr *nla, int attrtype)
 }
 
 /**
+ * nla_parse - Parse a stream of attributes into a tb buffer
+ * @tb: destination array with maxtype+1 elements
+ * @maxtype: maximum attribute type to be expected
+ * @head: head of attribute stream
+ * @len: length of attribute stream
+ * @policy: validation policy
+ *
+ * See nla_strict_parse(). Strict checking is not performed.
+ */
+static inline int nla_parse(struct nlattr **tb, int maxtype,
+			    const struct nlattr *head, int len,
+			    const struct nla_policy *policy)
+{
+	return nla_strict_parse(tb, maxtype, false, head, len, policy);
+}
+
+/**
+ * nla_strict_parse_nested - parse nested attributes
+ * @tb: destination array with maxtype+1 elements
+ * @maxtype: maximum attribute type to be expected
+ * @strict: whether to perform strict checking
+ * @nla: attribute containing the nested attributes
+ * @policy: validation policy
+ *
+ * See nla_strict_parse(). Strict checking is not performed.
+ */
+static inline int nla_strict_parse_nested(struct nlattr *tb[], int maxtype,
+					  bool strict,
+					  const struct nlattr *nla,
+					  const struct nla_policy *policy)
+{
+	return nla_strict_parse(tb, maxtype, strict, nla_data(nla),
+				nla_len(nla), policy);
+}
+
+/**
  * nla_parse_nested - parse nested attributes
  * @tb: destination array with maxtype+1 elements
  * @maxtype: maximum attribute type to be expected
  * @nla: attribute containing the nested attributes
  * @policy: validation policy
  *
- * See nla_parse()
+ * See nla_strict_parse()
  */
 static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,
 				   const struct nlattr *nla,
diff --git a/lib/nlattr.c b/lib/nlattr.c
index b35c3e6c8e81..2b36388eb3a9 100644
--- a/lib/nlattr.c
+++ b/lib/nlattr.c
@@ -163,9 +163,10 @@ nla_policy_len(const struct nla_policy *p, int n)
 EXPORT_SYMBOL(nla_policy_len);
 
 /**
- * nla_parse - Parse a stream of attributes into a tb buffer
+ * nla_strict_parse - Parse a stream of attributes into a tb buffer
  * @tb: destination array with maxtype+1 elements
  * @maxtype: maximum attribute type to be expected
+ * @strict: whether to perform strict checking
  * @head: head of attribute stream
  * @len: length of attribute stream
  * @policy: validation policy
@@ -173,12 +174,14 @@ EXPORT_SYMBOL(nla_policy_len);
  * Parses a stream of attributes and stores a pointer to each attribute in
  * the tb array accessible via the attribute type. Attributes with a type
  * exceeding maxtype will be silently ignored for backwards compatibility
- * reasons. policy may be set to NULL if no validation is required.
+ * reasons, unless strict is set. policy may be set to NULL if no validation
+ * is required.
  *
  * Returns 0 on success or a negative error code.
  */
-int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
-	      int len, const struct nla_policy *policy)
+int nla_strict_parse(struct nlattr **tb, int maxtype, bool strict,
+		     const struct nlattr *head, int len,
+		     const struct nla_policy *policy)
 {
 	const struct nlattr *nla;
 	int rem, err;
@@ -196,16 +199,21 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
 			}
 
 			tb[type] = (struct nlattr *)nla;
+		} else if (strict) {
+			return -EINVAL;
 		}
 	}
 
-	if (unlikely(rem > 0))
+	if (unlikely(rem > 0)) {
 		pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n",
 				    rem, current->comm);
+		if (strict)
+			return -EINVAL;
+	}
 
 	return 0;
 }
-EXPORT_SYMBOL(nla_parse);
+EXPORT_SYMBOL(nla_strict_parse);
 
 /**
  * nla_find - Find a specific attribute in a stream of attributes
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH net-next 4/9] netlink: strict attribute validation
  2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
                   ` (2 preceding siblings ...)
  2015-10-15 16:39 ` [RFC PATCH net-next 3/9] netlink: strict attribute parsing Jiri Benc
@ 2015-10-15 16:39 ` Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 5/9] rtnetlink: support strict attribute checking Jiri Benc
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-15 16:39 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Graf

Enhance the attribute validation functions to support strict attribute
checking. Keep the semantics of the current nla_validate and nlmsg_validate
functions.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
---
 include/net/netlink.h | 67 ++++++++++++++++++++++++++++++++++++++++++++-------
 lib/nlattr.c          | 24 +++++++++++-------
 2 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/include/net/netlink.h b/include/net/netlink.h
index dcca6853913d..233a68e1c955 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -233,8 +233,8 @@ int netlink_rcv_skb(struct sk_buff *skb, bool strict_supported,
 int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
 		 unsigned int group, int report, gfp_t flags);
 
-int nla_validate(const struct nlattr *head, int len, int maxtype,
-		 const struct nla_policy *policy);
+int nla_strict_validate(const struct nlattr *head, int len, int maxtype,
+			bool strict, const struct nla_policy *policy);
 int nla_strict_parse(struct nlattr **tb, int maxtype, bool strict,
 		     const struct nlattr *head, int len,
 		     const struct nla_policy *policy);
@@ -413,6 +413,26 @@ static inline struct nlattr *nlmsg_find_attr(const struct nlmsghdr *nlh,
 }
 
 /**
+ * nlmsg_strict_validate - validate a netlink message including attributes
+ * @nlh: netlinket message header
+ * @hdrlen: length of familiy specific header
+ * @maxtype: maximum attribute type to be expected
+ * @strict: whether to perform strict checking
+ * @policy: validation policy
+ */
+static inline int nlmsg_strict_validate(const struct nlmsghdr *nlh,
+					int hdrlen, int maxtype, bool strict,
+					const struct nla_policy *policy)
+{
+	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
+		return -EINVAL;
+
+	return nla_strict_validate(nlmsg_attrdata(nlh, hdrlen),
+				   nlmsg_attrlen(nlh, hdrlen), maxtype,
+				   strict, policy);
+}
+
+/**
  * nlmsg_validate - validate a netlink message including attributes
  * @nlh: netlinket message header
  * @hdrlen: length of familiy specific header
@@ -423,11 +443,7 @@ static inline int nlmsg_validate(const struct nlmsghdr *nlh,
 				 int hdrlen, int maxtype,
 				 const struct nla_policy *policy)
 {
-	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
-		return -EINVAL;
-
-	return nla_validate(nlmsg_attrdata(nlh, hdrlen),
-			    nlmsg_attrlen(nlh, hdrlen), maxtype, policy);
+	return nlmsg_strict_validate(nlh, hdrlen, maxtype, false, policy);
 }
 
 /**
@@ -1270,17 +1286,50 @@ static inline void nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)
 }
 
 /**
- * nla_validate_nested - Validate a stream of nested attributes
+ * nla_validate - Validate a stream of attributes
+ * @head: head of attribute stream
+ * @len: length of attribute stream
+ * @maxtype: maximum attribute type to be expected
+ * @policy: validation policy
+ *
+ * See nla_strict_validate(). Strict checking is not performed.
+ */
+static inline int nla_validate(const struct nlattr *head, int len,
+			       int maxtype, const struct nla_policy *policy)
+{
+	return nla_strict_validate(head, len, maxtype, false, policy);
+}
+
+/**
+ * nla_strict_validate_nested - Validate a stream of nested attributes
  * @start: container attribute
  * @maxtype: maximum attribute type to be expected
+ * @strict: whether to perform strict checking
  * @policy: validation policy
  *
  * Validates all attributes in the nested attribute stream against the
  * specified policy. Attributes with a type exceeding maxtype will be
- * ignored. See documenation of struct nla_policy for more details.
+ * ignored, unless strict is set. See documenation of struct nla_policy for
+ * more details.
  *
  * Returns 0 on success or a negative error code.
  */
+static inline int nla_strict_validate_nested(const struct nlattr *start,
+					     int maxtype, bool strict,
+					     const struct nla_policy *policy)
+{
+	return nla_strict_validate(nla_data(start), nla_len(start), maxtype,
+				   strict, policy);
+}
+
+/**
+ * nla_validate_nested - Validate a stream of nested attributes
+ * @start: container attribute
+ * @maxtype: maximum attribute type to be expected
+ * @policy: validation policy
+ *
+ * See nla_strict_validate_nested(). Strict checking is not performed.
+ */
 static inline int nla_validate_nested(const struct nlattr *start, int maxtype,
 				      const struct nla_policy *policy)
 {
diff --git a/lib/nlattr.c b/lib/nlattr.c
index 2b36388eb3a9..86bc0662caee 100644
--- a/lib/nlattr.c
+++ b/lib/nlattr.c
@@ -27,14 +27,17 @@ static const u16 nla_attr_minlen[NLA_TYPE_MAX+1] = {
 	[NLA_S64]	= sizeof(s64),
 };
 
-static int validate_nla(const struct nlattr *nla, int maxtype,
+static int validate_nla(const struct nlattr *nla, int maxtype, bool strict,
 			const struct nla_policy *policy)
 {
 	const struct nla_policy *pt;
 	int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
 
-	if (type <= 0 || type > maxtype)
+	if (type <= 0 || type > maxtype) {
+		if (strict)
+			return -EINVAL;
 		return 0;
+	}
 
 	pt = &policy[type];
 
@@ -107,33 +110,35 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
 }
 
 /**
- * nla_validate - Validate a stream of attributes
+ * nla_strict_validate - Validate a stream of attributes
  * @head: head of attribute stream
  * @len: length of attribute stream
  * @maxtype: maximum attribute type to be expected
+ * @strict: whether to perform strict checking
  * @policy: validation policy
  *
  * Validates all attributes in the specified attribute stream against the
  * specified policy. Attributes with a type exceeding maxtype will be
- * ignored. See documenation of struct nla_policy for more details.
+ * ignored, unless strict is set. See documenation of struct nla_policy for
+ * more details.
  *
  * Returns 0 on success or a negative error code.
  */
-int nla_validate(const struct nlattr *head, int len, int maxtype,
-		 const struct nla_policy *policy)
+int nla_strict_validate(const struct nlattr *head, int len, int maxtype,
+			bool strict, const struct nla_policy *policy)
 {
 	const struct nlattr *nla;
 	int rem, err;
 
 	nla_for_each_attr(nla, head, len, rem) {
-		err = validate_nla(nla, maxtype, policy);
+		err = validate_nla(nla, maxtype, strict, policy);
 		if (err < 0)
 			return err;
 	}
 
 	return 0;
 }
-EXPORT_SYMBOL(nla_validate);
+EXPORT_SYMBOL(nla_strict_validate);
 
 /**
  * nla_policy_len - Determin the max. length of a policy
@@ -193,7 +198,8 @@ int nla_strict_parse(struct nlattr **tb, int maxtype, bool strict,
 
 		if (type > 0 && type <= maxtype) {
 			if (policy) {
-				err = validate_nla(nla, maxtype, policy);
+				err = validate_nla(nla, maxtype, strict,
+						   policy);
 				if (err < 0)
 					return err;
 			}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH net-next 5/9] rtnetlink: support strict attribute checking
  2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
                   ` (3 preceding siblings ...)
  2015-10-15 16:39 ` [RFC PATCH net-next 4/9] netlink: strict attribute validation Jiri Benc
@ 2015-10-15 16:39 ` Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 6/9] rtnetlink: add strict parameter to validate callbacks Jiri Benc
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-15 16:39 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Graf

Allow rtnl callbacks to support strict attribute checking. They can do so by
passing new RTNL_F_STRICT flag to rtnl_register_flags. The semantics of the
current rtnl_register and __rtnl_register functions were preserved in order
not to change almost hundred of the call sites.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
---
 include/net/rtnetlink.h | 27 ++++++++++++++++++++++----
 net/core/rtnetlink.c    | 51 +++++++++++++++++++++++++++++++------------------
 2 files changed, 55 insertions(+), 23 deletions(-)

diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index aff6ceb891a9..58bf1f5ad6a1 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -8,13 +8,32 @@ typedef int (*rtnl_doit_func)(struct sk_buff *, struct nlmsghdr *);
 typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *);
 typedef u16 (*rtnl_calcit_func)(struct sk_buff *, struct nlmsghdr *);
 
-int __rtnl_register(int protocol, int msgtype,
-		    rtnl_doit_func, rtnl_dumpit_func, rtnl_calcit_func);
-void rtnl_register(int protocol, int msgtype,
-		   rtnl_doit_func, rtnl_dumpit_func, rtnl_calcit_func);
+#define RTNL_F_STRICT	1
+
+int __rtnl_register_flags(int protocol, int msgtype,
+			  rtnl_doit_func, rtnl_dumpit_func, rtnl_calcit_func,
+			  unsigned int flags);
+void rtnl_register_flags(int protocol, int msgtype,
+			 rtnl_doit_func, rtnl_dumpit_func, rtnl_calcit_func,
+			 unsigned int flags);
 int rtnl_unregister(int protocol, int msgtype);
 void rtnl_unregister_all(int protocol);
 
+static inline int __rtnl_register(int protocol, int msgtype,
+				  rtnl_doit_func doit, rtnl_dumpit_func dumpit,
+				  rtnl_calcit_func calcit)
+{
+	return __rtnl_register_flags(protocol, msgtype,
+				     doit, dumpit, calcit, 0);
+}
+
+static inline void rtnl_register(int protocol, int msgtype,
+				 rtnl_doit_func doit, rtnl_dumpit_func dumpit,
+				 rtnl_calcit_func calcit)
+{
+	rtnl_register_flags(protocol, msgtype, doit, dumpit, calcit, 0);
+}
+
 static inline int rtnl_msg_family(const struct nlmsghdr *nlh)
 {
 	if (nlmsg_len(nlh) >= sizeof(struct rtgenmsg))
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index afb41c7492b4..dedc539b960c 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -61,6 +61,7 @@ struct rtnl_link {
 	rtnl_doit_func		doit;
 	rtnl_dumpit_func	dumpit;
 	rtnl_calcit_func 	calcit;
+	unsigned int		flags;
 };
 
 static DEFINE_MUTEX(rtnl_mutex);
@@ -119,7 +120,8 @@ static inline int rtm_msgindex(int msgtype)
 	return msgindex;
 }
 
-static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex)
+static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex,
+				    unsigned int *flags)
 {
 	struct rtnl_link *tab;
 
@@ -131,6 +133,7 @@ static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex)
 	if (tab == NULL || tab[msgindex].doit == NULL)
 		tab = rtnl_msg_handlers[PF_UNSPEC];
 
+	*flags = tab[msgindex].flags;
 	return tab[msgindex].doit;
 }
 
@@ -165,12 +168,13 @@ static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
 }
 
 /**
- * __rtnl_register - Register a rtnetlink message type
+ * __rtnl_register_flags - Register a rtnetlink message type
  * @protocol: Protocol family or PF_UNSPEC
  * @msgtype: rtnetlink message type
  * @doit: Function pointer called for each request message
  * @dumpit: Function pointer called for each dump request (NLM_F_DUMP) message
  * @calcit: Function pointer to calc size of dump message
+ * @flags: RTNL_F_ flags
  *
  * Registers the specified function pointers (at least one of them has
  * to be non-NULL) to be called whenever a request message for the
@@ -182,9 +186,9 @@ static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
  *
  * Returns 0 on success or a negative error code.
  */
-int __rtnl_register(int protocol, int msgtype,
-		    rtnl_doit_func doit, rtnl_dumpit_func dumpit,
-		    rtnl_calcit_func calcit)
+int __rtnl_register_flags(int protocol, int msgtype,
+			  rtnl_doit_func doit, rtnl_dumpit_func dumpit,
+			  rtnl_calcit_func calcit, unsigned int flags)
 {
 	struct rtnl_link *tab;
 	int msgindex;
@@ -210,29 +214,32 @@ int __rtnl_register(int protocol, int msgtype,
 	if (calcit)
 		tab[msgindex].calcit = calcit;
 
+	tab[msgindex].flags = flags;
+
 	return 0;
 }
-EXPORT_SYMBOL_GPL(__rtnl_register);
+EXPORT_SYMBOL_GPL(__rtnl_register_flags);
 
 /**
- * rtnl_register - Register a rtnetlink message type
+ * rtnl_register_flags - Register a rtnetlink message type
  *
- * Identical to __rtnl_register() but panics on failure. This is useful
- * as failure of this function is very unlikely, it can only happen due
- * to lack of memory when allocating the chain to store all message
- * handlers for a protocol. Meant for use in init functions where lack
- * of memory implies no sense in continuing.
+ * Identical to __rtnl_register_flags() but panics on failure. This is
+ * useful as failure of this function is very unlikely, it can only happen
+ * due to lack of memory when allocating the chain to store all message
+ * handlers for a protocol. Meant for use in init functions where lack of
+ * memory implies no sense in continuing.
  */
-void rtnl_register(int protocol, int msgtype,
-		   rtnl_doit_func doit, rtnl_dumpit_func dumpit,
-		   rtnl_calcit_func calcit)
+void rtnl_register_flags(int protocol, int msgtype,
+			 rtnl_doit_func doit, rtnl_dumpit_func dumpit,
+			 rtnl_calcit_func calcit, unsigned int flags)
 {
-	if (__rtnl_register(protocol, msgtype, doit, dumpit, calcit) < 0)
+	if (__rtnl_register_flags(protocol, msgtype, doit, dumpit, calcit,
+				  flags) < 0)
 		panic("Unable to register rtnetlink message handler, "
 		      "protocol = %d, message type = %d\n",
 		      protocol, msgtype);
 }
-EXPORT_SYMBOL_GPL(rtnl_register);
+EXPORT_SYMBOL_GPL(rtnl_register_flags);
 
 /**
  * rtnl_unregister - Unregister a rtnetlink message type
@@ -3298,6 +3305,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
 	rtnl_doit_func doit;
+	unsigned int flags;
 	int sz_idx, kind;
 	int family;
 	int type;
@@ -3326,6 +3334,9 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		rtnl_calcit_func calcit;
 		u16 min_dump_alloc = 0;
 
+		if (nlh->nlmsg_flags & NLM_F_STRICT)
+			return -EPROTO;
+
 		dumpit = rtnl_get_dumpit(family, type);
 		if (dumpit == NULL)
 			return -EOPNOTSUPP;
@@ -3346,9 +3357,11 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		return err;
 	}
 
-	doit = rtnl_get_doit(family, type);
+	doit = rtnl_get_doit(family, type, &flags);
 	if (doit == NULL)
 		return -EOPNOTSUPP;
+	if (!(flags & RTNL_F_STRICT) && (nlh->nlmsg_flags & NLM_F_STRICT))
+		return -EPROTO;
 
 	return doit(skb, nlh);
 }
@@ -3356,7 +3369,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 static void rtnetlink_rcv(struct sk_buff *skb)
 {
 	rtnl_lock();
-	netlink_rcv_skb(skb, false, &rtnetlink_rcv_msg);
+	netlink_rcv_skb(skb, true, &rtnetlink_rcv_msg);
 	rtnl_unlock();
 }
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH net-next 6/9] rtnetlink: add strict parameter to validate callbacks
  2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
                   ` (4 preceding siblings ...)
  2015-10-15 16:39 ` [RFC PATCH net-next 5/9] rtnetlink: support strict attribute checking Jiri Benc
@ 2015-10-15 16:39 ` Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 7/9] rtnetlink: add strict parameter to validate_link_af Jiri Benc
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-15 16:39 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Graf

This is in preparation for rtnetlink to be able to handle strict attribute
checking.

The only rtnl_link_ops users that can have nested attributes (and thus need
to know whether we're in strict validation mode or not) are 8021q and veth.
veth will be handled in a separate patch. 8021q is trivial, it just passes
the parameter through to nla_strict_validate_nested.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
---
 drivers/net/bonding/bond_netlink.c |  3 ++-
 drivers/net/dummy.c                |  3 ++-
 drivers/net/geneve.c               |  3 ++-
 drivers/net/ifb.c                  |  3 ++-
 drivers/net/ipvlan/ipvlan_main.c   |  3 ++-
 drivers/net/macvlan.c              |  3 ++-
 drivers/net/nlmon.c                |  3 ++-
 drivers/net/team/team.c            |  3 ++-
 drivers/net/tun.c                  |  3 ++-
 drivers/net/veth.c                 |  5 +++--
 drivers/net/vrf.c                  |  3 ++-
 drivers/net/vxlan.c                |  3 ++-
 include/net/rtnetlink.h            |  6 ++++--
 net/8021q/vlan_netlink.c           | 12 +++++++-----
 net/bridge/br_netlink.c            |  3 ++-
 net/core/rtnetlink.c               |  5 +++--
 net/ieee802154/6lowpan/core.c      |  3 ++-
 net/ipv4/ip_gre.c                  |  8 +++++---
 net/ipv4/ip_vti.c                  |  3 ++-
 net/ipv6/ip6_gre.c                 |  8 +++++---
 net/ipv6/ip6_tunnel.c              |  3 ++-
 net/ipv6/ip6_vti.c                 |  3 ++-
 net/ipv6/sit.c                     |  3 ++-
 23 files changed, 61 insertions(+), 34 deletions(-)

diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index db760e84119f..71c7bfeb96f3 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -118,7 +118,8 @@ static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {
 	[IFLA_BOND_SLAVE_QUEUE_ID]	= { .type = NLA_U16 },
 };
 
-static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
+static int bond_validate(struct nlattr *tb[], struct nlattr *data[],
+			 bool strict)
 {
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 815eb94990f5..45601fb973e3 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -152,7 +152,8 @@ static void dummy_setup(struct net_device *dev)
 	eth_hw_addr_random(dev);
 }
 
-static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
+static int dummy_validate(struct nlattr *tb[], struct nlattr *data[],
+			  bool strict)
 {
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 8f5c02eed47d..1b3e7bc649c7 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -765,7 +765,8 @@ static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = {
 	[IFLA_GENEVE_COLLECT_METADATA]	= { .type = NLA_FLAG },
 };
 
-static int geneve_validate(struct nlattr *tb[], struct nlattr *data[])
+static int geneve_validate(struct nlattr *tb[], struct nlattr *data[],
+			   bool strict)
 {
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index cc56fac3c3f8..ae2636e9cd7a 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -276,7 +276,8 @@ static int ifb_open(struct net_device *dev)
 	return 0;
 }
 
-static int ifb_validate(struct nlattr *tb[], struct nlattr *data[])
+static int ifb_validate(struct nlattr *tb[], struct nlattr *data[],
+			bool strict)
 {
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index a9268db4e349..51e9353d0459 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -404,7 +404,8 @@ static size_t ipvlan_nl_getsize(const struct net_device *dev)
 		);
 }
 
-static int ipvlan_nl_validate(struct nlattr *tb[], struct nlattr *data[])
+static int ipvlan_nl_validate(struct nlattr *tb[], struct nlattr *data[],
+			      bool strict)
 {
 	if (data && data[IFLA_IPVLAN_MODE]) {
 		u16 mode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 86f6c6292c27..60b3fb556144 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1121,7 +1121,8 @@ static void macvlan_port_destroy(struct net_device *dev)
 	kfree_rcu(port, rcu);
 }
 
-static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
+static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[],
+			    bool strict)
 {
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c
index 7b7c70e2341e..3dd893cd0291 100644
--- a/drivers/net/nlmon.c
+++ b/drivers/net/nlmon.c
@@ -147,7 +147,8 @@ static void nlmon_setup(struct net_device *dev)
 	dev->mtu = NLMSG_GOODSIZE;
 }
 
-static int nlmon_validate(struct nlattr *tb[], struct nlattr *data[])
+static int nlmon_validate(struct nlattr *tb[], struct nlattr *data[],
+			  bool strict)
 {
 	if (tb[IFLA_ADDRESS])
 		return -EINVAL;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 651d35ea22c5..e36e14db6f48 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2086,7 +2086,8 @@ static int team_newlink(struct net *src_net, struct net_device *dev,
 	return register_netdevice(dev);
 }
 
-static int team_validate(struct nlattr *tb[], struct nlattr *data[])
+static int team_validate(struct nlattr *tb[], struct nlattr *data[],
+			 bool strict)
 {
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index b1878faea397..610bafb3b1c2 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1468,7 +1468,8 @@ static void tun_setup(struct net_device *dev)
 /* Trivial set of netlink ops to allow deleting tun or tap
  * device with netlink.
  */
-static int tun_validate(struct nlattr *tb[], struct nlattr *data[])
+static int tun_validate(struct nlattr *tb[], struct nlattr *data[],
+			bool strict)
 {
 	return -EINVAL;
 }
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 0ef4a5ad5557..af0bf39147ba 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -327,7 +327,8 @@ static void veth_setup(struct net_device *dev)
  * netlink interface
  */
 
-static int veth_validate(struct nlattr *tb[], struct nlattr *data[])
+static int veth_validate(struct nlattr *tb[], struct nlattr *data[],
+			 bool strict)
 {
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
@@ -370,7 +371,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
 		if (err < 0)
 			return err;
 
-		err = veth_validate(peer_tb, NULL);
+		err = veth_validate(peer_tb, NULL, false);
 		if (err < 0)
 			return err;
 
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 92fa3e1ea65c..a3f9b4703a93 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -887,7 +887,8 @@ static void vrf_setup(struct net_device *dev)
 	dev->features |= NETIF_F_NETNS_LOCAL;
 }
 
-static int vrf_validate(struct nlattr *tb[], struct nlattr *data[])
+static int vrf_validate(struct nlattr *tb[], struct nlattr *data[],
+			bool strict)
 {
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index ce704df7681b..764eaac91c97 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2478,7 +2478,8 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
 	[IFLA_VXLAN_REMCSUM_NOPARTIAL]	= { .type = NLA_FLAG },
 };
 
-static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
+static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
+			  bool strict)
 {
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 58bf1f5ad6a1..9f730f2395de 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -78,7 +78,8 @@ struct rtnl_link_ops {
 	int			maxtype;
 	const struct nla_policy	*policy;
 	int			(*validate)(struct nlattr *tb[],
-					    struct nlattr *data[]);
+					    struct nlattr *data[],
+					    bool strict);
 
 	int			(*newlink)(struct net *src_net,
 					   struct net_device *dev,
@@ -103,7 +104,8 @@ struct rtnl_link_ops {
 	int			slave_maxtype;
 	const struct nla_policy	*slave_policy;
 	int			(*slave_validate)(struct nlattr *tb[],
-						  struct nlattr *data[]);
+						  struct nlattr *data[],
+						  bool strict);
 	int			(*slave_changelink)(struct net_device *dev,
 						    struct net_device *slave_dev,
 						    struct nlattr *tb[],
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index c92b52f37d38..ba69c408312d 100644
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -31,14 +31,16 @@ static const struct nla_policy vlan_map_policy[IFLA_VLAN_QOS_MAX + 1] = {
 };
 
 
-static inline int vlan_validate_qos_map(struct nlattr *attr)
+static inline int vlan_validate_qos_map(struct nlattr *attr, bool strict)
 {
 	if (!attr)
 		return 0;
-	return nla_validate_nested(attr, IFLA_VLAN_QOS_MAX, vlan_map_policy);
+	return nla_strict_validate_nested(attr, IFLA_VLAN_QOS_MAX, strict,
+					  vlan_map_policy);
 }
 
-static int vlan_validate(struct nlattr *tb[], struct nlattr *data[])
+static int vlan_validate(struct nlattr *tb[], struct nlattr *data[],
+			 bool strict)
 {
 	struct ifla_vlan_flags *flags;
 	u16 id;
@@ -77,10 +79,10 @@ static int vlan_validate(struct nlattr *tb[], struct nlattr *data[])
 			return -EINVAL;
 	}
 
-	err = vlan_validate_qos_map(data[IFLA_VLAN_INGRESS_QOS]);
+	err = vlan_validate_qos_map(data[IFLA_VLAN_INGRESS_QOS], strict);
 	if (err < 0)
 		return err;
-	err = vlan_validate_qos_map(data[IFLA_VLAN_EGRESS_QOS]);
+	err = vlan_validate_qos_map(data[IFLA_VLAN_EGRESS_QOS], strict);
 	if (err < 0)
 		return err;
 	return 0;
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 94b4de8c4646..f144344a3f38 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -746,7 +746,8 @@ int br_dellink(struct net_device *dev, struct nlmsghdr *nlh, u16 flags)
 
 	return err;
 }
-static int br_validate(struct nlattr *tb[], struct nlattr *data[])
+static int br_validate(struct nlattr *tb[], struct nlattr *data[],
+		       bool strict)
 {
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index dedc539b960c..205b7acbd6bf 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2197,7 +2197,7 @@ replay:
 				data = attr;
 			}
 			if (ops->validate) {
-				err = ops->validate(tb, data);
+				err = ops->validate(tb, data, false);
 				if (err < 0)
 					return err;
 			}
@@ -2215,7 +2215,8 @@ replay:
 				slave_data = slave_attr;
 			}
 			if (m_ops->slave_validate) {
-				err = m_ops->slave_validate(tb, slave_data);
+				err = m_ops->slave_validate(tb, slave_data,
+							    false);
 				if (err < 0)
 					return err;
 			}
diff --git a/net/ieee802154/6lowpan/core.c b/net/ieee802154/6lowpan/core.c
index 20c49c724ba0..145c1d4256e1 100644
--- a/net/ieee802154/6lowpan/core.c
+++ b/net/ieee802154/6lowpan/core.c
@@ -112,7 +112,8 @@ static void lowpan_setup(struct net_device *ldev)
 	ldev->features		|= NETIF_F_NETNS_LOCAL;
 }
 
-static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[])
+static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[],
+			   bool strict)
 {
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != IEEE802154_ADDR_LEN)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index bd0679d90519..dd2b9801ed7a 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -881,7 +881,8 @@ static struct pernet_operations ipgre_net_ops = {
 	.size = sizeof(struct ip_tunnel_net),
 };
 
-static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
+static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
+				 bool strict)
 {
 	__be16 flags;
 
@@ -899,7 +900,8 @@ static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
 	return 0;
 }
 
-static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
+static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
+			      bool strict)
 {
 	__be32 daddr;
 
@@ -920,7 +922,7 @@ static int ipgre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
 	}
 
 out:
-	return ipgre_tunnel_validate(tb, data);
+	return ipgre_tunnel_validate(tb, data, strict);
 }
 
 static void ipgre_netlink_parms(struct net_device *dev,
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 4d8f0b698777..1e48c1fd74db 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -435,7 +435,8 @@ static struct pernet_operations vti_net_ops = {
 	.size = sizeof(struct ip_tunnel_net),
 };
 
-static int vti_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
+static int vti_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
+			       bool strict)
 {
 	return 0;
 }
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 3c7b9310b33f..58281ec6cc27 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1392,7 +1392,8 @@ static struct pernet_operations ip6gre_net_ops = {
 	.size = sizeof(struct ip6gre_net),
 };
 
-static int ip6gre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
+static int ip6gre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[],
+				  bool strict)
 {
 	__be16 flags;
 
@@ -1410,7 +1411,8 @@ static int ip6gre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[])
 	return 0;
 }
 
-static int ip6gre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
+static int ip6gre_tap_validate(struct nlattr *tb[], struct nlattr *data[],
+			       bool strict)
 {
 	struct in6_addr daddr;
 
@@ -1431,7 +1433,7 @@ static int ip6gre_tap_validate(struct nlattr *tb[], struct nlattr *data[])
 	}
 
 out:
-	return ip6gre_tunnel_validate(tb, data);
+	return ip6gre_tunnel_validate(tb, data, strict);
 }
 
 
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index eabffbb89795..3fb0fcc50b47 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1683,7 +1683,8 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev)
 	return 0;
 }
 
-static int ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[])
+static int ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[],
+			    bool strict)
 {
 	u8 proto;
 
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 0a8610b33d79..abde61ddf9fa 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -899,7 +899,8 @@ static int __net_init vti6_fb_tnl_dev_init(struct net_device *dev)
 	return 0;
 }
 
-static int vti6_validate(struct nlattr *tb[], struct nlattr *data[])
+static int vti6_validate(struct nlattr *tb[], struct nlattr *data[],
+			 bool strict)
 {
 	return 0;
 }
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 94428fd85b2f..10b858a80183 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1424,7 +1424,8 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
 	return 0;
 }
 
-static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[])
+static int ipip6_validate(struct nlattr *tb[], struct nlattr *data[],
+			  bool strict)
 {
 	u8 proto;
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH net-next 7/9] rtnetlink: add strict parameter to validate_link_af
  2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
                   ` (5 preceding siblings ...)
  2015-10-15 16:39 ` [RFC PATCH net-next 6/9] rtnetlink: add strict parameter to validate callbacks Jiri Benc
@ 2015-10-15 16:39 ` Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 8/9] rtnetlink: support strict checking for newlink, setlink and dellink Jiri Benc
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-15 16:39 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Graf

This is in preparation for rtnetlink to be able to handle strict
attribute checking.

Nothing complicated here, just pass the parameter through.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
---
 include/net/rtnetlink.h | 3 ++-
 net/core/rtnetlink.c    | 3 ++-
 net/ipv4/devinet.c      | 6 ++++--
 net/ipv6/addrconf.c     | 6 ++++--
 4 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 9f730f2395de..71c49f5af9a0 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -148,7 +148,8 @@ struct rtnl_af_ops {
 	size_t			(*get_link_af_size)(const struct net_device *dev);
 
 	int			(*validate_link_af)(const struct net_device *dev,
-						    const struct nlattr *attr);
+						    const struct nlattr *attr,
+						    bool strict);
 	int			(*set_link_af)(struct net_device *dev,
 					       const struct nlattr *attr);
 };
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 205b7acbd6bf..9d08ad6ee5c3 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1491,7 +1491,8 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
 				return -EOPNOTSUPP;
 
 			if (af_ops->validate_link_af) {
-				err = af_ops->validate_link_af(dev, af);
+				err = af_ops->validate_link_af(dev, af,
+							       false);
 				if (err < 0)
 					return err;
 			}
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 735008472844..9ea6bc6683ec 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1679,7 +1679,8 @@ static const struct nla_policy inet_af_policy[IFLA_INET_MAX+1] = {
 };
 
 static int inet_validate_link_af(const struct net_device *dev,
-				 const struct nlattr *nla)
+				 const struct nlattr *nla,
+				 bool strict)
 {
 	struct nlattr *a, *tb[IFLA_INET_MAX+1];
 	int err, rem;
@@ -1687,7 +1688,8 @@ static int inet_validate_link_af(const struct net_device *dev,
 	if (dev && !__in_dev_get_rtnl(dev))
 		return -EAFNOSUPPORT;
 
-	err = nla_parse_nested(tb, IFLA_INET_MAX, nla, inet_af_policy);
+	err = nla_strict_parse_nested(tb, IFLA_INET_MAX, strict, nla,
+				      inet_af_policy);
 	if (err < 0)
 		return err;
 
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index f0326aae7a02..b29f117cde72 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4876,14 +4876,16 @@ static const struct nla_policy inet6_af_policy[IFLA_INET6_MAX + 1] = {
 };
 
 static int inet6_validate_link_af(const struct net_device *dev,
-				  const struct nlattr *nla)
+				  const struct nlattr *nla,
+				  bool strict)
 {
 	struct nlattr *tb[IFLA_INET6_MAX + 1];
 
 	if (dev && !__in6_dev_get(dev))
 		return -EAFNOSUPPORT;
 
-	return nla_parse_nested(tb, IFLA_INET6_MAX, nla, inet6_af_policy);
+	return nla_strict_parse_nested(tb, IFLA_INET6_MAX, strict, nla,
+				       inet6_af_policy);
 }
 
 static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH net-next 8/9] rtnetlink: support strict checking for newlink, setlink and dellink
  2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
                   ` (6 preceding siblings ...)
  2015-10-15 16:39 ` [RFC PATCH net-next 7/9] rtnetlink: add strict parameter to validate_link_af Jiri Benc
@ 2015-10-15 16:39 ` Jiri Benc
  2015-10-15 16:39 ` [RFC PATCH net-next 9/9] veth: validate nested attributes Jiri Benc
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-15 16:39 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Graf

Signed-off-by: Jiri Benc <jbenc@redhat.com>
---
 net/core/rtnetlink.c | 84 +++++++++++++++++++++++++++++++---------------------
 1 file changed, 51 insertions(+), 33 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 9d08ad6ee5c3..1af929e468cf 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1465,7 +1465,8 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
 }
 EXPORT_SYMBOL(rtnl_link_get_net);
 
-static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
+static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[],
+			    bool strict)
 {
 	if (dev) {
 		if (tb[IFLA_ADDRESS] &&
@@ -1492,7 +1493,7 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[])
 
 			if (af_ops->validate_link_af) {
 				err = af_ops->validate_link_af(dev, af,
-							       false);
+							       strict);
 				if (err < 0)
 					return err;
 			}
@@ -1637,7 +1638,8 @@ static int do_set_master(struct net_device *dev, int ifindex)
 #define DO_SETLINK_NOTIFY	0x03
 static int do_setlink(const struct sk_buff *skb,
 		      struct net_device *dev, struct ifinfomsg *ifm,
-		      struct nlattr **tb, char *ifname, int status)
+		      struct nlattr **tb, char *ifname, int status,
+		      bool strict)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
 	int err;
@@ -1799,8 +1801,9 @@ static int do_setlink(const struct sk_buff *skb,
 				err = -EINVAL;
 				goto errout;
 			}
-			err = nla_parse_nested(vfinfo, IFLA_VF_MAX, attr,
-					       ifla_vf_policy);
+			err = nla_strict_parse_nested(vfinfo, IFLA_VF_MAX,
+						      strict, attr,
+						      ifla_vf_policy);
 			if (err < 0)
 				goto errout;
 			err = do_setvfinfo(dev, vfinfo);
@@ -1827,8 +1830,9 @@ static int do_setlink(const struct sk_buff *skb,
 				err = -EINVAL;
 				goto errout;
 			}
-			err = nla_parse_nested(port, IFLA_PORT_MAX, attr,
-					       ifla_port_policy);
+			err = nla_strict_parse_nested(port, IFLA_PORT_MAX,
+						      strict, attr,
+						      ifla_port_policy);
 			if (err < 0)
 				goto errout;
 			if (!port[IFLA_PORT_VF]) {
@@ -1847,8 +1851,9 @@ static int do_setlink(const struct sk_buff *skb,
 	if (tb[IFLA_PORT_SELF]) {
 		struct nlattr *port[IFLA_PORT_MAX+1];
 
-		err = nla_parse_nested(port, IFLA_PORT_MAX,
-			tb[IFLA_PORT_SELF], ifla_port_policy);
+		err = nla_strict_parse_nested(port, IFLA_PORT_MAX, strict,
+					      tb[IFLA_PORT_SELF],
+					      ifla_port_policy);
 		if (err < 0)
 			goto errout;
 
@@ -1908,8 +1913,10 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh)
 	int err;
 	struct nlattr *tb[IFLA_MAX+1];
 	char ifname[IFNAMSIZ];
+	bool strict = nlh->nlmsg_flags & NLM_F_STRICT;
 
-	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+	err = nlmsg_strict_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, strict,
+				 ifla_policy);
 	if (err < 0)
 		goto errout;
 
@@ -1932,11 +1939,11 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh)
 		goto errout;
 	}
 
-	err = validate_linkmsg(dev, tb);
+	err = validate_linkmsg(dev, tb, strict);
 	if (err < 0)
 		goto errout;
 
-	err = do_setlink(skb, dev, ifm, tb, ifname, 0);
+	err = do_setlink(skb, dev, ifm, tb, ifname, 0, strict);
 errout:
 	return err;
 }
@@ -2000,9 +2007,11 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh)
 	struct ifinfomsg *ifm;
 	char ifname[IFNAMSIZ];
 	struct nlattr *tb[IFLA_MAX+1];
+	bool strict = nlh->nlmsg_flags & NLM_F_STRICT;
 	int err;
 
-	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+	err = nlmsg_strict_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, strict,
+				 ifla_policy);
 	if (err < 0)
 		return err;
 
@@ -2102,14 +2111,14 @@ EXPORT_SYMBOL(rtnl_create_link);
 static int rtnl_group_changelink(const struct sk_buff *skb,
 		struct net *net, int group,
 		struct ifinfomsg *ifm,
-		struct nlattr **tb)
+		struct nlattr **tb, bool strict)
 {
 	struct net_device *dev, *aux;
 	int err;
 
 	for_each_netdev_safe(net, dev, aux) {
 		if (dev->group == group) {
-			err = do_setlink(skb, dev, ifm, tb, NULL, 0);
+			err = do_setlink(skb, dev, ifm, tb, NULL, 0, strict);
 			if (err < 0)
 				return err;
 		}
@@ -2131,12 +2140,14 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
 	struct nlattr *tb[IFLA_MAX+1];
 	struct nlattr *linkinfo[IFLA_INFO_MAX+1];
 	unsigned char name_assign_type = NET_NAME_USER;
+	bool strict = nlh->nlmsg_flags & NLM_F_STRICT;
 	int err;
 
 #ifdef CONFIG_MODULES
 replay:
 #endif
-	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+	err = nlmsg_strict_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, strict,
+				 ifla_policy);
 	if (err < 0)
 		return err;
 
@@ -2161,13 +2172,14 @@ replay:
 			m_ops = master_dev->rtnl_link_ops;
 	}
 
-	err = validate_linkmsg(dev, tb);
+	err = validate_linkmsg(dev, tb, strict);
 	if (err < 0)
 		return err;
 
 	if (tb[IFLA_LINKINFO]) {
-		err = nla_parse_nested(linkinfo, IFLA_INFO_MAX,
-				       tb[IFLA_LINKINFO], ifla_info_policy);
+		err = nla_strict_parse_nested(linkinfo, IFLA_INFO_MAX,
+					      strict, tb[IFLA_LINKINFO],
+					      ifla_info_policy);
 		if (err < 0)
 			return err;
 	} else
@@ -2190,15 +2202,16 @@ replay:
 
 		if (ops) {
 			if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) {
-				err = nla_parse_nested(attr, ops->maxtype,
-						       linkinfo[IFLA_INFO_DATA],
-						       ops->policy);
+				err = nla_strict_parse_nested(attr, ops->maxtype,
+							      strict,
+							      linkinfo[IFLA_INFO_DATA],
+							      ops->policy);
 				if (err < 0)
 					return err;
 				data = attr;
 			}
 			if (ops->validate) {
-				err = ops->validate(tb, data, false);
+				err = ops->validate(tb, data, strict);
 				if (err < 0)
 					return err;
 			}
@@ -2207,17 +2220,18 @@ replay:
 		if (m_ops) {
 			if (m_ops->slave_maxtype &&
 			    linkinfo[IFLA_INFO_SLAVE_DATA]) {
-				err = nla_parse_nested(slave_attr,
-						       m_ops->slave_maxtype,
-						       linkinfo[IFLA_INFO_SLAVE_DATA],
-						       m_ops->slave_policy);
+				err = nla_strict_parse_nested(slave_attr,
+							      m_ops->slave_maxtype,
+							      strict,
+							      linkinfo[IFLA_INFO_SLAVE_DATA],
+							      m_ops->slave_policy);
 				if (err < 0)
 					return err;
 				slave_data = slave_attr;
 			}
 			if (m_ops->slave_validate) {
 				err = m_ops->slave_validate(tb, slave_data,
-							    false);
+							    strict);
 				if (err < 0)
 					return err;
 			}
@@ -2253,14 +2267,15 @@ replay:
 				status |= DO_SETLINK_NOTIFY;
 			}
 
-			return do_setlink(skb, dev, ifm, tb, ifname, status);
+			return do_setlink(skb, dev, ifm, tb, ifname, status,
+					  strict);
 		}
 
 		if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
 			if (ifm->ifi_index == 0 && tb[IFLA_GROUP])
 				return rtnl_group_changelink(skb, net,
 						nla_get_u32(tb[IFLA_GROUP]),
-						ifm, tb);
+						ifm, tb, strict);
 			return -ENODEV;
 		}
 
@@ -3443,9 +3458,12 @@ void __init rtnetlink_init(void)
 
 	rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink,
 		      rtnl_dump_ifinfo, rtnl_calcit);
-	rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL);
-	rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL);
-	rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL);
+	rtnl_register_flags(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL, NULL,
+			    RTNL_F_STRICT);
+	rtnl_register_flags(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL, NULL,
+			    RTNL_F_STRICT);
+	rtnl_register_flags(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, NULL,
+			    RTNL_F_STRICT);
 
 	rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL);
 	rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH net-next 9/9] veth: validate nested attributes
  2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
                   ` (7 preceding siblings ...)
  2015-10-15 16:39 ` [RFC PATCH net-next 8/9] rtnetlink: support strict checking for newlink, setlink and dellink Jiri Benc
@ 2015-10-15 16:39 ` Jiri Benc
  2015-10-15 22:07 ` [RFC PATCH net-next 0/9] netlink: strict attribute checking option Hannes Frederic Sowa
  2015-10-16  6:50 ` David Miller
  10 siblings, 0 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-15 16:39 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Graf

For strict attribute checking, it's necessary to validate nested attributes
in the validate rtnl_link_ops callback.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
---
 drivers/net/veth.c      | 8 ++++++++
 include/net/rtnetlink.h | 1 +
 net/core/rtnetlink.c    | 6 ++++++
 3 files changed, 15 insertions(+)

diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index af0bf39147ba..86a68bd191b6 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -340,6 +340,14 @@ static int veth_validate(struct nlattr *tb[], struct nlattr *data[],
 		if (!is_valid_veth_mtu(nla_get_u32(tb[IFLA_MTU])))
 			return -EINVAL;
 	}
+	if (data != NULL && data[VETH_INFO_PEER] != NULL) {
+		struct nlattr *nla_peer = data[VETH_INFO_PEER];
+
+		return rtnl_nla_validate_ifla(
+				nla_data(nla_peer) + sizeof(struct ifinfomsg),
+				nla_len(nla_peer) - sizeof(struct ifinfomsg),
+				strict);
+	}
 	return 0;
 }
 
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 71c49f5af9a0..be75457e4cc5 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -168,6 +168,7 @@ int rtnl_delete_link(struct net_device *dev);
 int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm);
 
 int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len);
+int rtnl_nla_validate_ifla(const struct nlattr *head, int len, bool strict);
 
 #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
 
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 1af929e468cf..89e7f0a6da44 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1449,6 +1449,12 @@ int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len)
 }
 EXPORT_SYMBOL(rtnl_nla_parse_ifla);
 
+int rtnl_nla_validate_ifla(const struct nlattr *head, int len, bool strict)
+{
+	return nla_strict_validate(head, len, IFLA_MAX, strict, ifla_policy);
+}
+EXPORT_SYMBOL(rtnl_nla_validate_ifla);
+
 struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
 {
 	struct net *net;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
                   ` (8 preceding siblings ...)
  2015-10-15 16:39 ` [RFC PATCH net-next 9/9] veth: validate nested attributes Jiri Benc
@ 2015-10-15 22:07 ` Hannes Frederic Sowa
  2015-10-16  7:49   ` Jiri Benc
  2015-10-16  6:50 ` David Miller
  10 siblings, 1 reply; 23+ messages in thread
From: Hannes Frederic Sowa @ 2015-10-15 22:07 UTC (permalink / raw)
  To: Jiri Benc, netdev; +Cc: Thomas Graf

Jiri Benc <jbenc@redhat.com> writes:

> Before using this new facility, the application should check whether it is
> supported by the kernel. This is done by sending a NLMSG_NOOP message with
> NLM_F_REQUEST | NLM_F_STRICT | NLM_F_ACK flags set. If the returned message
> has NLM_F_STRICT set, the kernel does support NLM_F_STRICT flag; otherwise,
> the flag should not be used.

Do you plan to update rfc3549, too? :}

Bye,
Hannes

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
                   ` (9 preceding siblings ...)
  2015-10-15 22:07 ` [RFC PATCH net-next 0/9] netlink: strict attribute checking option Hannes Frederic Sowa
@ 2015-10-16  6:50 ` David Miller
  2015-10-16  7:39   ` Jiri Benc
  10 siblings, 1 reply; 23+ messages in thread
From: David Miller @ 2015-10-16  6:50 UTC (permalink / raw)
  To: jbenc; +Cc: netdev, tgraf

From: Jiri Benc <jbenc@redhat.com>
Date: Thu, 15 Oct 2015 18:39:05 +0200

> When sending a netlink request (NLM_F_REQUEST), any unknown attributes are
> ignored. This behavior is problematic in some situations. For example if the
> user asks for a particular config, the request finishes successfully, yet
> the configuraton applied does not work because some of the attributes are
> not supported by the kernel (e.g. because it's older than the user space
> tool).

Although we are probably stuck with this, it was probably a bad idea
to have this behavior as the default.

Better would have been to always error on unrecognized attributes, and
in the ACK give some indication of which attribute was problematic.

But anyhow we are stuck with what we have.  However, I will say I am
disappointed that it is so hard to simply detect that lwtunnel support
is present, which as I understand is what this patch set is trying to
accomplish.

And this is quite an intrusive patch series, and therefore not
suitable for -stable backports.  And that's exactly where you actually
are going to need these changes right?  Older kernels that lack
lwtunnel support.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-16  6:50 ` David Miller
@ 2015-10-16  7:39   ` Jiri Benc
  2015-10-16  8:06     ` David Miller
  0 siblings, 1 reply; 23+ messages in thread
From: Jiri Benc @ 2015-10-16  7:39 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, tgraf

On Thu, 15 Oct 2015 23:50:07 -0700 (PDT), David Miller wrote:
> Although we are probably stuck with this, it was probably a bad idea
> to have this behavior as the default.

I agree. But we have what we have.

> Better would have been to always error on unrecognized attributes, and
> in the ACK give some indication of which attribute was problematic.

Should I try to extend the patches to return such information back to
the user? It would mean more intrusiveness, as there's no space in ack
to store such information (it would have been better to use attributes
even in the error responses instead of a fixed structure...).

> But anyhow we are stuck with what we have.  However, I will say I am
> disappointed that it is so hard to simply detect that lwtunnel support
> is present, which as I understand is what this patch set is trying to
> accomplish.

Yes, main motivation is lwtunnel support. However, I'd say this is
useful outside of it, too.

> And this is quite an intrusive patch series, and therefore not
> suitable for -stable backports.  And that's exactly where you actually
> are going to need these changes right?  Older kernels that lack
> lwtunnel support.

I'm targeting net-next only and don't intend to bring this to older
kernels. The patchset is designed in the way that it's possible to
detect that the kernel does not support strict attribute checking. When
this is detected, the tools will just assume that lwtunnel support is
not there. That's completely okay, it will just mean that the 4.3
kernel will be treated as not having lwtunnel support; everything will
work correctly, including openvswitch (which will use its compat code).

 Jiri

-- 
Jiri Benc

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-15 22:07 ` [RFC PATCH net-next 0/9] netlink: strict attribute checking option Hannes Frederic Sowa
@ 2015-10-16  7:49   ` Jiri Benc
  2015-10-16  8:08     ` David Miller
  0 siblings, 1 reply; 23+ messages in thread
From: Jiri Benc @ 2015-10-16  7:49 UTC (permalink / raw)
  To: Hannes Frederic Sowa; +Cc: netdev, Thomas Graf

On Fri, 16 Oct 2015 00:07:12 +0200, Hannes Frederic Sowa wrote:
> Do you plan to update rfc3549, too? :}

No.

While I think we need to have a detailed documentation on netlink,
I believe it should reside in Documentation/ inside the kernel tree to
be easily updated, not in an outside document collection with much more
heavyweight processes around getting something updated.

I would offer taking the RFC 3549 into the kernel tree and extending it
but my understanding of the license is that I'm not allowed to do that
(as I would modify the "document itself").

 Jiri

-- 
Jiri Benc

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-16  8:06     ` David Miller
@ 2015-10-16  8:02       ` Jiri Benc
  2015-10-16  8:09         ` Thomas Graf
  2015-10-16 15:57         ` David Ahern
  0 siblings, 2 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-16  8:02 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, tgraf

On Fri, 16 Oct 2015 01:06:44 -0700 (PDT), David Miller wrote:
> No, it's definitely not OK, because lwtunnel support exists in
> Linus's tree.
> 
> And tools should be able to work on all kernels where lwtunnel support
> is available.

You can consider the lwtunnels feature as not finished in the current
Linus's tree. It works, it won't change (thus anything using it in its
current form will continue to work in all the future kernels), but
mainstream tools won't make use of it until a kernel version later
which will get some additional support.

I don't think it's much of a problem and I don't think it is the first
time this would happen.

I'm afraid I don't have any solution that could do better.

 Jiri

-- 
Jiri Benc

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-16  7:39   ` Jiri Benc
@ 2015-10-16  8:06     ` David Miller
  2015-10-16  8:02       ` Jiri Benc
  0 siblings, 1 reply; 23+ messages in thread
From: David Miller @ 2015-10-16  8:06 UTC (permalink / raw)
  To: jbenc; +Cc: netdev, tgraf

From: Jiri Benc <jbenc@redhat.com>
Date: Fri, 16 Oct 2015 09:39:45 +0200

> I'm targeting net-next only and don't intend to bring this to older
> kernels. The patchset is designed in the way that it's possible to
> detect that the kernel does not support strict attribute checking. When
> this is detected, the tools will just assume that lwtunnel support is
> not there.

No, it's definitely not OK, because lwtunnel support exists in
Linus's tree.

And tools should be able to work on all kernels where lwtunnel support
is available.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-16  7:49   ` Jiri Benc
@ 2015-10-16  8:08     ` David Miller
  2015-10-16  8:08       ` Jiri Benc
  0 siblings, 1 reply; 23+ messages in thread
From: David Miller @ 2015-10-16  8:08 UTC (permalink / raw)
  To: jbenc; +Cc: hannes, netdev, tgraf

From: Jiri Benc <jbenc@redhat.com>
Date: Fri, 16 Oct 2015 09:49:51 +0200

> On Fri, 16 Oct 2015 00:07:12 +0200, Hannes Frederic Sowa wrote:
>> Do you plan to update rfc3549, too? :}
> 
> No.
> 
> While I think we need to have a detailed documentation on netlink,
> I believe it should reside in Documentation/ inside the kernel tree to
> be easily updated, not in an outside document collection with much more
> heavyweight processes around getting something updated.

I think his point is that you'll be making changes to an RFC specified
protocol.

But I think we need a better solution to this.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-16  8:08     ` David Miller
@ 2015-10-16  8:08       ` Jiri Benc
  2015-10-16  9:40         ` Hannes Frederic Sowa
  0 siblings, 1 reply; 23+ messages in thread
From: Jiri Benc @ 2015-10-16  8:08 UTC (permalink / raw)
  To: David Miller; +Cc: hannes, netdev, tgraf

On Fri, 16 Oct 2015 01:08:26 -0700 (PDT), David Miller wrote:
> I think his point is that you'll be making changes to an RFC specified
> protocol.

The RFC is only informational, it has never became an Internet
standard (under the RFC terms). And no other OS picked it up. Keeping
kernel uAPI documentation in IETF database sounds rather inefficient.

> But I think we need a better solution to this.

I'm not opposed to a better solution. I just don't see any that's not
a gross hack. Suggestions are welcome.

 Jiri

-- 
Jiri Benc

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-16  8:02       ` Jiri Benc
@ 2015-10-16  8:09         ` Thomas Graf
  2015-10-16 15:57         ` David Ahern
  1 sibling, 0 replies; 23+ messages in thread
From: Thomas Graf @ 2015-10-16  8:09 UTC (permalink / raw)
  To: Jiri Benc; +Cc: David Miller, netdev

On 10/16/15 at 10:02am, Jiri Benc wrote:
> On Fri, 16 Oct 2015 01:06:44 -0700 (PDT), David Miller wrote:
> > No, it's definitely not OK, because lwtunnel support exists in
> > Linus's tree.
> > 
> > And tools should be able to work on all kernels where lwtunnel support
> > is available.
> 
> You can consider the lwtunnels feature as not finished in the current
> Linus's tree. It works, it won't change (thus anything using it in its
> current form will continue to work in all the future kernels), but
> mainstream tools won't make use of it until a kernel version later
> which will get some additional support.
> 
> I don't think it's much of a problem and I don't think it is the first
> time this would happen.
> 
> I'm afraid I don't have any solution that could do better.

Maybe we should be more precise here. The detection mechanism is only
for tools which want to know whether lwt or another feature is supported
without going through the pain of creating an object, checking its
attributes and then deleting the object again if no full support was
detected. The existing flow of configuration through iproute2 will be
supported just like for any other new feature that we have introduced.

Therefore, I consider this a future optimization.

This is very much related to the offload problematic we had or still
have of "only program in HW if you can do the full thing vs best effort"
so this flag will be of use in a wider context.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-16  8:08       ` Jiri Benc
@ 2015-10-16  9:40         ` Hannes Frederic Sowa
  2015-10-16 10:00           ` Jiri Benc
  0 siblings, 1 reply; 23+ messages in thread
From: Hannes Frederic Sowa @ 2015-10-16  9:40 UTC (permalink / raw)
  To: Jiri Benc, David Miller; +Cc: netdev, tgraf

Hi,

On Fri, Oct 16, 2015, at 10:08, Jiri Benc wrote:
> On Fri, 16 Oct 2015 01:08:26 -0700 (PDT), David Miller wrote:
> > I think his point is that you'll be making changes to an RFC specified
> > protocol.
> 
> The RFC is only informational, it has never became an Internet
> standard (under the RFC terms). And no other OS picked it up. Keeping
> kernel uAPI documentation in IETF database sounds rather inefficient.

I would suggest you simply add a description to the rfc via the errata
process here: <https://www.rfc-editor.org/errata_report.php>

The original cover letter should be enough to post there. I am also not
sure if people do really implement this spec, at least they have a
pointer to it, then. AFAIK the IESG will look into that then and even
non-approved erratas will be listed on the rfc page.

Bye,
Hannes

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-16  9:40         ` Hannes Frederic Sowa
@ 2015-10-16 10:00           ` Jiri Benc
  0 siblings, 0 replies; 23+ messages in thread
From: Jiri Benc @ 2015-10-16 10:00 UTC (permalink / raw)
  To: Hannes Frederic Sowa; +Cc: David Miller, netdev, tgraf

On Fri, 16 Oct 2015 11:40:11 +0200, Hannes Frederic Sowa wrote:
> I would suggest you simply add a description to the rfc via the errata
> process here: <https://www.rfc-editor.org/errata_report.php>
> 
> The original cover letter should be enough to post there. I am also not
> sure if people do really implement this spec, at least they have a
> pointer to it, then. AFAIK the IESG will look into that then and even
> non-approved erratas will be listed on the rfc page.

Okay, we may do that. But let's postpone this discussion after we
decide what route we'll go. We'll definitely need some form of
documentation but it's preliminary to discuss what exact form when we
haven't decided whether we'll implement something like this at all.

 Jiri

-- 
Jiri Benc

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-16  8:02       ` Jiri Benc
  2015-10-16  8:09         ` Thomas Graf
@ 2015-10-16 15:57         ` David Ahern
  2015-10-19  2:29           ` David Miller
  1 sibling, 1 reply; 23+ messages in thread
From: David Ahern @ 2015-10-16 15:57 UTC (permalink / raw)
  To: Jiri Benc, David Miller; +Cc: netdev, tgraf

On 10/16/15 2:02 AM, Jiri Benc wrote:
> On Fri, 16 Oct 2015 01:06:44 -0700 (PDT), David Miller wrote:
>> No, it's definitely not OK, because lwtunnel support exists in
>> Linus's tree.
>>
>> And tools should be able to work on all kernels where lwtunnel support
>> is available.
>
> You can consider the lwtunnels feature as not finished in the current
> Linus's tree. It works, it won't change (thus anything using it in its
> current form will continue to work in all the future kernels), but
> mainstream tools won't make use of it until a kernel version later
> which will get some additional support.
>
> I don't think it's much of a problem and I don't think it is the first
> time this would happen.
>
> I'm afraid I don't have any solution that could do better.

What about a flag that requests the version from the relevant kernel 
subsystem?

Generate the same initial netlink message -- e.g., type set to 
RTM_NEWROUTE for example -- but with no attributes and the NLM_F_VERSION 
flag set. Send the message using whatever socket protocol is relevant 
for the command/query.

Then kernel side the message makes its way to the relevant handler, the 
handler sees the flag asking for version and responds with its version. 
The version would be local to the handler and is a means for telling 
userspace what attributes it understands.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH net-next 0/9] netlink: strict attribute checking option
  2015-10-16 15:57         ` David Ahern
@ 2015-10-19  2:29           ` David Miller
  0 siblings, 0 replies; 23+ messages in thread
From: David Miller @ 2015-10-19  2:29 UTC (permalink / raw)
  To: dsa; +Cc: jbenc, netdev, tgraf

From: David Ahern <dsa@cumulusnetworks.com>
Date: Fri, 16 Oct 2015 09:57:33 -0600

> On 10/16/15 2:02 AM, Jiri Benc wrote:
>> On Fri, 16 Oct 2015 01:06:44 -0700 (PDT), David Miller wrote:
>>> No, it's definitely not OK, because lwtunnel support exists in
>>> Linus's tree.
>>>
>>> And tools should be able to work on all kernels where lwtunnel support
>>> is available.
>>
>> You can consider the lwtunnels feature as not finished in the current
>> Linus's tree. It works, it won't change (thus anything using it in its
>> current form will continue to work in all the future kernels), but
>> mainstream tools won't make use of it until a kernel version later
>> which will get some additional support.
>>
>> I don't think it's much of a problem and I don't think it is the first
>> time this would happen.
>>
>> I'm afraid I don't have any solution that could do better.
> 
> What about a flag that requests the version from the relevant kernel
> subsystem?

The whole point of having an easily extensible protocol like netlink
with attributes and whatnot was to avoid messy schemes like
versioning.

The big mistake was ignoring unknown attributes.  I mean seriously,
think about it, what if the new attribute specified by the user was
some security setting or something?  I'm sure even more dangerous
examples can be imagined.

I'm beginning to wonder if we can just change this unilaterally to
not ignore unrecognized attributes.

I am increasingly certain that things that would "break" we wouldn't
want to succeed anyways.

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2015-10-19  2:13 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-15 16:39 [RFC PATCH net-next 0/9] netlink: strict attribute checking option Jiri Benc
2015-10-15 16:39 ` [RFC PATCH net-next 1/9] netlink: add NLM_F_STRICT for strict attribute checking Jiri Benc
2015-10-15 16:39 ` [RFC PATCH net-next 2/9] netlink: remove unnecesary goto's Jiri Benc
2015-10-15 16:39 ` [RFC PATCH net-next 3/9] netlink: strict attribute parsing Jiri Benc
2015-10-15 16:39 ` [RFC PATCH net-next 4/9] netlink: strict attribute validation Jiri Benc
2015-10-15 16:39 ` [RFC PATCH net-next 5/9] rtnetlink: support strict attribute checking Jiri Benc
2015-10-15 16:39 ` [RFC PATCH net-next 6/9] rtnetlink: add strict parameter to validate callbacks Jiri Benc
2015-10-15 16:39 ` [RFC PATCH net-next 7/9] rtnetlink: add strict parameter to validate_link_af Jiri Benc
2015-10-15 16:39 ` [RFC PATCH net-next 8/9] rtnetlink: support strict checking for newlink, setlink and dellink Jiri Benc
2015-10-15 16:39 ` [RFC PATCH net-next 9/9] veth: validate nested attributes Jiri Benc
2015-10-15 22:07 ` [RFC PATCH net-next 0/9] netlink: strict attribute checking option Hannes Frederic Sowa
2015-10-16  7:49   ` Jiri Benc
2015-10-16  8:08     ` David Miller
2015-10-16  8:08       ` Jiri Benc
2015-10-16  9:40         ` Hannes Frederic Sowa
2015-10-16 10:00           ` Jiri Benc
2015-10-16  6:50 ` David Miller
2015-10-16  7:39   ` Jiri Benc
2015-10-16  8:06     ` David Miller
2015-10-16  8:02       ` Jiri Benc
2015-10-16  8:09         ` Thomas Graf
2015-10-16 15:57         ` David Ahern
2015-10-19  2:29           ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).