summaryrefslogtreecommitdiffstats
path: root/net/netlink
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlink')
-rw-r--r--net/netlink/diag.c1
-rw-r--r--net/netlink/genetlink.c3
-rw-r--r--net/netlink/policy.c29
3 files changed, 22 insertions, 11 deletions
diff --git a/net/netlink/diag.c b/net/netlink/diag.c
index 9c4f231be2..1eeff94228 100644
--- a/net/netlink/diag.c
+++ b/net/netlink/diag.c
@@ -257,5 +257,6 @@ static void __exit netlink_diag_exit(void)
module_init(netlink_diag_init);
module_exit(netlink_diag_exit);
+MODULE_DESCRIPTION("Netlink-based socket monitoring/diagnostic interface (sock_diag)");
MODULE_LICENSE("GPL");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 16 /* AF_NETLINK */);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index d41c4a936a..9c7ffd10df 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -225,7 +225,8 @@ static void genl_op_from_split(struct genl_op_iter *iter)
}
if (i + cnt < family->n_split_ops &&
- family->split_ops[i + cnt].flags & GENL_CMD_CAP_DUMP) {
+ family->split_ops[i + cnt].flags & GENL_CMD_CAP_DUMP &&
+ (!cnt || family->split_ops[i + cnt].cmd == iter->doit.cmd)) {
iter->dumpit = family->split_ops[i + cnt];
genl_op_fill_in_reject_policy_split(family, &iter->dumpit);
cnt++;
diff --git a/net/netlink/policy.c b/net/netlink/policy.c
index 87e3de0fde..1f8909c16f 100644
--- a/net/netlink/policy.c
+++ b/net/netlink/policy.c
@@ -21,7 +21,7 @@ struct netlink_policy_dump_state {
struct {
const struct nla_policy *policy;
unsigned int maxtype;
- } policies[];
+ } policies[] __counted_by(n_alloc);
};
static int add_policy(struct netlink_policy_dump_state **statep,
@@ -29,7 +29,7 @@ static int add_policy(struct netlink_policy_dump_state **statep,
unsigned int maxtype)
{
struct netlink_policy_dump_state *state = *statep;
- unsigned int n_alloc, i;
+ unsigned int old_n_alloc, n_alloc, i;
if (!policy || !maxtype)
return 0;
@@ -52,12 +52,13 @@ static int add_policy(struct netlink_policy_dump_state **statep,
if (!state)
return -ENOMEM;
- memset(&state->policies[state->n_alloc], 0,
- flex_array_size(state, policies, n_alloc - state->n_alloc));
-
- state->policies[state->n_alloc].policy = policy;
- state->policies[state->n_alloc].maxtype = maxtype;
+ old_n_alloc = state->n_alloc;
state->n_alloc = n_alloc;
+ memset(&state->policies[old_n_alloc], 0,
+ flex_array_size(state, policies, n_alloc - old_n_alloc));
+
+ state->policies[old_n_alloc].policy = policy;
+ state->policies[old_n_alloc].maxtype = maxtype;
*statep = state;
return 0;
@@ -229,6 +230,8 @@ int netlink_policy_dump_attr_size_estimate(const struct nla_policy *pt)
case NLA_S16:
case NLA_S32:
case NLA_S64:
+ case NLA_SINT:
+ case NLA_UINT:
/* maximum is common, u64 min/max with padding */
return common +
2 * (nla_attr_size(0) + nla_attr_size(sizeof(u64)));
@@ -287,6 +290,7 @@ __netlink_policy_dump_write_attr(struct netlink_policy_dump_state *state,
case NLA_U16:
case NLA_U32:
case NLA_U64:
+ case NLA_UINT:
case NLA_MSECS: {
struct netlink_range_validation range;
@@ -296,8 +300,10 @@ __netlink_policy_dump_write_attr(struct netlink_policy_dump_state *state,
type = NL_ATTR_TYPE_U16;
else if (pt->type == NLA_U32)
type = NL_ATTR_TYPE_U32;
- else
+ else if (pt->type == NLA_U64)
type = NL_ATTR_TYPE_U64;
+ else
+ type = NL_ATTR_TYPE_UINT;
if (pt->validation_type == NLA_VALIDATE_MASK) {
if (nla_put_u64_64bit(skb, NL_POLICY_TYPE_ATTR_MASK,
@@ -319,7 +325,8 @@ __netlink_policy_dump_write_attr(struct netlink_policy_dump_state *state,
case NLA_S8:
case NLA_S16:
case NLA_S32:
- case NLA_S64: {
+ case NLA_S64:
+ case NLA_SINT: {
struct netlink_range_validation_signed range;
if (pt->type == NLA_S8)
@@ -328,8 +335,10 @@ __netlink_policy_dump_write_attr(struct netlink_policy_dump_state *state,
type = NL_ATTR_TYPE_S16;
else if (pt->type == NLA_S32)
type = NL_ATTR_TYPE_S32;
- else
+ else if (pt->type == NLA_S64)
type = NL_ATTR_TYPE_S64;
+ else
+ type = NL_ATTR_TYPE_SINT;
nla_get_range_signed(pt, &range);