Skip to content

Commit 186e26e

Browse files
committed
Merge branch 'genetlink-per-op-policy-export'
Johannes Berg says: ==================== genetlink per-op policy export Here's a respin, now including Jakub's patch last so that it will do the right thing from the start. The first patch remains the same, of course; the others have mostly some rebasing going on, except for the actual export patch (patch 4) which is adjusted per Jakub's review comments about exporting the policy only if it's actually used for do/dump. To see that, the dump for "nlctrl" (i.e. the generic netlink control) is instructive, because the ops are this: { .cmd = CTRL_CMD_GETFAMILY, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .policy = ctrl_policy_family, .maxattr = ARRAY_SIZE(ctrl_policy_family) - 1, .doit = ctrl_getfamily, .dumpit = ctrl_dumpfamily, }, { .cmd = CTRL_CMD_GETPOLICY, .policy = ctrl_policy_policy, .maxattr = ARRAY_SIZE(ctrl_policy_policy) - 1, .start = ctrl_dumppolicy_start, .dumpit = ctrl_dumppolicy, .done = ctrl_dumppolicy_done, }, So we exercise both "don't have doit" and "GENL_DONT_VALIDATE_DUMP" parts, and get (with the current genl patch): $ genl ctrl policy name nlctrl ID: 0x10 op 3 policies: do=0 ID: 0x10 op 10 policies: dump=1 ID: 0x10 policy[0]:attr[1]: type=U16 range:[0,65535] ID: 0x10 policy[0]:attr[2]: type=NUL_STRING max len:15 ID: 0x10 policy[1]:attr[1]: type=U16 range:[0,65535] ID: 0x10 policy[1]:attr[2]: type=NUL_STRING max len:15 ID: 0x10 policy[1]:attr[10]: type=U32 range:[0,4294967295] ==================== Reviewed-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
2 parents 678cdd4 + e992a6e commit 186e26e

File tree

4 files changed

+247
-40
lines changed

4 files changed

+247
-40
lines changed

include/net/netlink.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,9 +1937,12 @@ void nla_get_range_signed(const struct nla_policy *pt,
19371937

19381938
struct netlink_policy_dump_state;
19391939

1940-
int netlink_policy_dump_start(const struct nla_policy *policy,
1941-
unsigned int maxtype,
1942-
struct netlink_policy_dump_state **state);
1940+
int netlink_policy_dump_add_policy(struct netlink_policy_dump_state **pstate,
1941+
const struct nla_policy *policy,
1942+
unsigned int maxtype);
1943+
int netlink_policy_dump_get_policy_idx(struct netlink_policy_dump_state *state,
1944+
const struct nla_policy *policy,
1945+
unsigned int maxtype);
19431946
bool netlink_policy_dump_loop(struct netlink_policy_dump_state *state);
19441947
int netlink_policy_dump_write(struct sk_buff *skb,
19451948
struct netlink_policy_dump_state *state);

include/uapi/linux/genetlink.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ enum {
6464
CTRL_ATTR_OPS,
6565
CTRL_ATTR_MCAST_GROUPS,
6666
CTRL_ATTR_POLICY,
67+
CTRL_ATTR_OP_POLICY,
68+
CTRL_ATTR_OP,
6769
__CTRL_ATTR_MAX,
6870
};
6971

@@ -85,6 +87,15 @@ enum {
8587
__CTRL_ATTR_MCAST_GRP_MAX,
8688
};
8789

90+
enum {
91+
CTRL_ATTR_POLICY_UNSPEC,
92+
CTRL_ATTR_POLICY_DO,
93+
CTRL_ATTR_POLICY_DUMP,
94+
95+
__CTRL_ATTR_POLICY_DUMP_MAX,
96+
CTRL_ATTR_POLICY_DUMP_MAX = __CTRL_ATTR_POLICY_DUMP_MAX - 1
97+
};
98+
8899
#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1)
89100

90101

net/netlink/genetlink.c

Lines changed: 144 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ static void genl_op_from_full(const struct genl_family *family,
123123
op->policy = family->policy;
124124
}
125125

126-
static int genl_get_cmd_full(u8 cmd, const struct genl_family *family,
126+
static int genl_get_cmd_full(u32 cmd, const struct genl_family *family,
127127
struct genl_ops *op)
128128
{
129129
int i;
@@ -152,7 +152,7 @@ static void genl_op_from_small(const struct genl_family *family,
152152
op->policy = family->policy;
153153
}
154154

155-
static int genl_get_cmd_small(u8 cmd, const struct genl_family *family,
155+
static int genl_get_cmd_small(u32 cmd, const struct genl_family *family,
156156
struct genl_ops *op)
157157
{
158158
int i;
@@ -166,7 +166,7 @@ static int genl_get_cmd_small(u8 cmd, const struct genl_family *family,
166166
return -ENOENT;
167167
}
168168

169-
static int genl_get_cmd(u8 cmd, const struct genl_family *family,
169+
static int genl_get_cmd(u32 cmd, const struct genl_family *family,
170170
struct genl_ops *op)
171171
{
172172
if (!genl_get_cmd_full(cmd, family, op))
@@ -1112,13 +1112,19 @@ static int genl_ctrl_event(int event, const struct genl_family *family,
11121112

11131113
struct ctrl_dump_policy_ctx {
11141114
struct netlink_policy_dump_state *state;
1115+
const struct genl_family *rt;
1116+
unsigned int opidx;
1117+
u32 op;
11151118
u16 fam_id;
1119+
u8 policies:1,
1120+
single_op:1;
11161121
};
11171122

11181123
static const struct nla_policy ctrl_policy_policy[] = {
11191124
[CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
11201125
[CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING,
11211126
.len = GENL_NAMSIZ - 1 },
1127+
[CTRL_ATTR_OP] = { .type = NLA_U32 },
11221128
};
11231129

11241130
static int ctrl_dumppolicy_start(struct netlink_callback *cb)
@@ -1127,6 +1133,8 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb)
11271133
struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
11281134
struct nlattr **tb = info->attrs;
11291135
const struct genl_family *rt;
1136+
struct genl_ops op;
1137+
int err, i;
11301138

11311139
BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
11321140

@@ -1147,29 +1155,149 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb)
11471155
if (!rt)
11481156
return -ENOENT;
11491157

1150-
if (!rt->policy)
1158+
ctx->rt = rt;
1159+
1160+
if (tb[CTRL_ATTR_OP]) {
1161+
ctx->single_op = true;
1162+
ctx->op = nla_get_u32(tb[CTRL_ATTR_OP]);
1163+
1164+
err = genl_get_cmd(ctx->op, rt, &op);
1165+
if (err) {
1166+
NL_SET_BAD_ATTR(cb->extack, tb[CTRL_ATTR_OP]);
1167+
return err;
1168+
}
1169+
1170+
if (!op.policy)
1171+
return -ENODATA;
1172+
1173+
return netlink_policy_dump_add_policy(&ctx->state, op.policy,
1174+
op.maxattr);
1175+
}
1176+
1177+
for (i = 0; i < genl_get_cmd_cnt(rt); i++) {
1178+
genl_get_cmd_by_index(i, rt, &op);
1179+
1180+
if (op.policy) {
1181+
err = netlink_policy_dump_add_policy(&ctx->state,
1182+
op.policy,
1183+
op.maxattr);
1184+
if (err)
1185+
return err;
1186+
}
1187+
}
1188+
1189+
if (!ctx->state)
11511190
return -ENODATA;
1191+
return 0;
1192+
}
11521193

1153-
return netlink_policy_dump_start(rt->policy, rt->maxattr, &ctx->state);
1194+
static void *ctrl_dumppolicy_prep(struct sk_buff *skb,
1195+
struct netlink_callback *cb)
1196+
{
1197+
struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
1198+
void *hdr;
1199+
1200+
hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1201+
cb->nlh->nlmsg_seq, &genl_ctrl,
1202+
NLM_F_MULTI, CTRL_CMD_GETPOLICY);
1203+
if (!hdr)
1204+
return NULL;
1205+
1206+
if (nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, ctx->fam_id))
1207+
return NULL;
1208+
1209+
return hdr;
1210+
}
1211+
1212+
static int ctrl_dumppolicy_put_op(struct sk_buff *skb,
1213+
struct netlink_callback *cb,
1214+
struct genl_ops *op)
1215+
{
1216+
struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
1217+
struct nlattr *nest_pol, *nest_op;
1218+
void *hdr;
1219+
int idx;
1220+
1221+
/* skip if we have nothing to show */
1222+
if (!op->policy)
1223+
return 0;
1224+
if (!op->doit &&
1225+
(!op->dumpit || op->validate & GENL_DONT_VALIDATE_DUMP))
1226+
return 0;
1227+
1228+
hdr = ctrl_dumppolicy_prep(skb, cb);
1229+
if (!hdr)
1230+
return -ENOBUFS;
1231+
1232+
nest_pol = nla_nest_start(skb, CTRL_ATTR_OP_POLICY);
1233+
if (!nest_pol)
1234+
goto err;
1235+
1236+
nest_op = nla_nest_start(skb, op->cmd);
1237+
if (!nest_op)
1238+
goto err;
1239+
1240+
/* for now both do/dump are always the same */
1241+
idx = netlink_policy_dump_get_policy_idx(ctx->state,
1242+
op->policy,
1243+
op->maxattr);
1244+
1245+
if (op->doit && nla_put_u32(skb, CTRL_ATTR_POLICY_DO, idx))
1246+
goto err;
1247+
1248+
if (op->dumpit && !(op->validate & GENL_DONT_VALIDATE_DUMP) &&
1249+
nla_put_u32(skb, CTRL_ATTR_POLICY_DUMP, idx))
1250+
goto err;
1251+
1252+
nla_nest_end(skb, nest_op);
1253+
nla_nest_end(skb, nest_pol);
1254+
genlmsg_end(skb, hdr);
1255+
1256+
return 0;
1257+
err:
1258+
genlmsg_cancel(skb, hdr);
1259+
return -ENOBUFS;
11541260
}
11551261

11561262
static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
11571263
{
11581264
struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
1265+
void *hdr;
1266+
1267+
if (!ctx->policies) {
1268+
while (ctx->opidx < genl_get_cmd_cnt(ctx->rt)) {
1269+
struct genl_ops op;
1270+
1271+
if (ctx->single_op) {
1272+
int err;
1273+
1274+
err = genl_get_cmd(ctx->op, ctx->rt, &op);
1275+
if (WARN_ON(err))
1276+
return skb->len;
1277+
1278+
/* break out of the loop after this one */
1279+
ctx->opidx = genl_get_cmd_cnt(ctx->rt);
1280+
} else {
1281+
genl_get_cmd_by_index(ctx->opidx, ctx->rt, &op);
1282+
}
1283+
1284+
if (ctrl_dumppolicy_put_op(skb, cb, &op))
1285+
return skb->len;
1286+
1287+
ctx->opidx++;
1288+
}
1289+
1290+
/* completed with the per-op policy index list */
1291+
ctx->policies = true;
1292+
}
11591293

11601294
while (netlink_policy_dump_loop(ctx->state)) {
1161-
void *hdr;
11621295
struct nlattr *nest;
11631296

1164-
hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
1165-
cb->nlh->nlmsg_seq, &genl_ctrl,
1166-
NLM_F_MULTI, CTRL_CMD_GETPOLICY);
1297+
hdr = ctrl_dumppolicy_prep(skb, cb);
11671298
if (!hdr)
11681299
goto nla_put_failure;
11691300

1170-
if (nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, ctx->fam_id))
1171-
goto nla_put_failure;
1172-
11731301
nest = nla_nest_start(skb, CTRL_ATTR_POLICY);
11741302
if (!nest)
11751303
goto nla_put_failure;
@@ -1180,14 +1308,13 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
11801308
nla_nest_end(skb, nest);
11811309

11821310
genlmsg_end(skb, hdr);
1183-
continue;
1184-
1185-
nla_put_failure:
1186-
genlmsg_cancel(skb, hdr);
1187-
break;
11881311
}
11891312

11901313
return skb->len;
1314+
1315+
nla_put_failure:
1316+
genlmsg_cancel(skb, hdr);
1317+
return skb->len;
11911318
}
11921319

11931320
static int ctrl_dumppolicy_done(struct netlink_callback *cb)

0 commit comments

Comments
 (0)