aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-11-19 09:19:39 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-19 16:39:06 -0500
commit2a94fe48f32ccf7321450a2cc07f2b724a444e5b (patch)
treee5a066d8f83d8822d448421019a4503f361295f9 /include
parent68eb55031da7c967d954e5f9415cd05f4abdb692 (diff)
genetlink: make multicast groups const, prevent abuse
Register generic netlink multicast groups as an array with the family and give them contiguous group IDs. Then instead of passing the global group ID to the various functions that send messages, pass the ID relative to the family - for most families that's just 0 because the only have one group. This avoids the list_head and ID in each group, adding a new field for the mcast group ID offset to the family. At the same time, this allows us to prevent abusing groups again like the quota and dropmon code did, since we can now check that a family only uses a group it owns. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/linux/genl_magic_func.h49
-rw-r--r--include/net/genetlink.h48
2 files changed, 51 insertions, 46 deletions
diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h
index 5b9b8ae6748b..c0894dd8827b 100644
--- a/include/linux/genl_magic_func.h
+++ b/include/linux/genl_magic_func.h
@@ -273,49 +273,40 @@ static struct genl_family ZZZ_genl_family __read_mostly = {
273 * Magic: define multicast groups 273 * Magic: define multicast groups
274 * Magic: define multicast group registration helper 274 * Magic: define multicast group registration helper
275 */ 275 */
276#define ZZZ_genl_mcgrps CONCAT_(GENL_MAGIC_FAMILY, _genl_mcgrps)
277static const struct genl_multicast_group ZZZ_genl_mcgrps[] = {
278#undef GENL_mc_group
279#define GENL_mc_group(group) { .name = #group, },
280#include GENL_MAGIC_INCLUDE_FILE
281};
282
283enum CONCAT_(GENL_MAGIC_FAMILY, group_ids) {
284#undef GENL_mc_group
285#define GENL_mc_group(group) CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group),
286#include GENL_MAGIC_INCLUDE_FILE
287};
288
276#undef GENL_mc_group 289#undef GENL_mc_group
277#define GENL_mc_group(group) \ 290#define GENL_mc_group(group) \
278static struct genl_multicast_group \
279CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group) __read_mostly = { \
280 .name = #group, \
281}; \
282static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \ 291static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \
283 struct sk_buff *skb, gfp_t flags) \ 292 struct sk_buff *skb, gfp_t flags) \
284{ \ 293{ \
285 unsigned int group_id = \ 294 unsigned int group_id = \
286 CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id; \ 295 CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group); \
287 if (!group_id) \
288 return -EINVAL; \
289 return genlmsg_multicast(&ZZZ_genl_family, skb, 0, \ 296 return genlmsg_multicast(&ZZZ_genl_family, skb, 0, \
290 group_id, flags); \ 297 group_id, flags); \
291} 298}
292 299
293#include GENL_MAGIC_INCLUDE_FILE 300#include GENL_MAGIC_INCLUDE_FILE
294 301
295int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
296{
297 int err = genl_register_family_with_ops(&ZZZ_genl_family, ZZZ_genl_ops);
298 if (err)
299 return err;
300#undef GENL_mc_group
301#define GENL_mc_group(group) \
302 err = genl_register_mc_group(&ZZZ_genl_family, \
303 &CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group)); \
304 if (err) \
305 goto fail; \
306 else \
307 pr_info("%s: mcg %s: %u\n", #group, \
308 __stringify(GENL_MAGIC_FAMILY), \
309 CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id);
310
311#include GENL_MAGIC_INCLUDE_FILE
312
313#undef GENL_mc_group 302#undef GENL_mc_group
314#define GENL_mc_group(group) 303#define GENL_mc_group(group)
315 return 0; 304
316fail: 305int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
317 genl_unregister_family(&ZZZ_genl_family); 306{
318 return err; 307 return genl_register_family_with_ops_groups(&ZZZ_genl_family, \
308 ZZZ_genl_ops, \
309 ZZZ_genl_mcgrps);
319} 310}
320 311
321void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void) 312void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void)
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 60aef0df386b..ace4abf118d7 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -10,14 +10,9 @@
10/** 10/**
11 * struct genl_multicast_group - generic netlink multicast group 11 * struct genl_multicast_group - generic netlink multicast group
12 * @name: name of the multicast group, names are per-family 12 * @name: name of the multicast group, names are per-family
13 * @id: multicast group ID, assigned by the core, to use with
14 * genlmsg_multicast().
15 * @list: list entry for linking
16 */ 13 */
17struct genl_multicast_group { 14struct genl_multicast_group {
18 struct list_head list; /* private */
19 char name[GENL_NAMSIZ]; 15 char name[GENL_NAMSIZ];
20 u32 id;
21}; 16};
22 17
23struct genl_ops; 18struct genl_ops;
@@ -38,7 +33,9 @@ struct genl_info;
38 * undo operations done by pre_doit, for example release locks 33 * undo operations done by pre_doit, for example release locks
39 * @attrbuf: buffer to store parsed attributes 34 * @attrbuf: buffer to store parsed attributes
40 * @family_list: family list 35 * @family_list: family list
41 * @mcast_groups: multicast groups list 36 * @mcgrps: multicast groups used by this family (private)
37 * @n_mcgrps: number of multicast groups (private)
38 * @mcgrp_offset: starting number of multicast group IDs in this family
42 * @ops: the operations supported by this family (private) 39 * @ops: the operations supported by this family (private)
43 * @n_ops: number of operations supported by this family (private) 40 * @n_ops: number of operations supported by this family (private)
44 */ 41 */
@@ -58,9 +55,11 @@ struct genl_family {
58 struct genl_info *info); 55 struct genl_info *info);
59 struct nlattr ** attrbuf; /* private */ 56 struct nlattr ** attrbuf; /* private */
60 const struct genl_ops * ops; /* private */ 57 const struct genl_ops * ops; /* private */
58 const struct genl_multicast_group *mcgrps; /* private */
61 unsigned int n_ops; /* private */ 59 unsigned int n_ops; /* private */
60 unsigned int n_mcgrps; /* private */
61 unsigned int mcgrp_offset; /* private */
62 struct list_head family_list; /* private */ 62 struct list_head family_list; /* private */
63 struct list_head mcast_groups; /* private */
64 struct module *module; 63 struct module *module;
65}; 64};
66 65
@@ -150,22 +149,30 @@ static inline int genl_register_family(struct genl_family *family)
150 * 149 *
151 * Return 0 on success or a negative error code. 150 * Return 0 on success or a negative error code.
152 */ 151 */
153static inline int _genl_register_family_with_ops(struct genl_family *family, 152static inline int
154 const struct genl_ops *ops, 153_genl_register_family_with_ops_grps(struct genl_family *family,
155 size_t n_ops) 154 const struct genl_ops *ops, size_t n_ops,
155 const struct genl_multicast_group *mcgrps,
156 size_t n_mcgrps)
156{ 157{
157 family->module = THIS_MODULE; 158 family->module = THIS_MODULE;
158 family->ops = ops; 159 family->ops = ops;
159 family->n_ops = n_ops; 160 family->n_ops = n_ops;
161 family->mcgrps = mcgrps;
162 family->n_mcgrps = n_mcgrps;
160 return __genl_register_family(family); 163 return __genl_register_family(family);
161} 164}
162 165
163#define genl_register_family_with_ops(family, ops) \ 166#define genl_register_family_with_ops(family, ops) \
164 _genl_register_family_with_ops((family), (ops), ARRAY_SIZE(ops)) 167 _genl_register_family_with_ops_grps((family), \
168 (ops), ARRAY_SIZE(ops), \
169 NULL, 0)
170#define genl_register_family_with_ops_groups(family, ops, grps) \
171 _genl_register_family_with_ops_grps((family), \
172 (ops), ARRAY_SIZE(ops), \
173 (grps), ARRAY_SIZE(grps))
165 174
166int genl_unregister_family(struct genl_family *family); 175int genl_unregister_family(struct genl_family *family);
167int genl_register_mc_group(struct genl_family *family,
168 struct genl_multicast_group *grp);
169void genl_notify(struct genl_family *family, 176void genl_notify(struct genl_family *family,
170 struct sk_buff *skb, struct net *net, u32 portid, 177 struct sk_buff *skb, struct net *net, u32 portid,
171 u32 group, struct nlmsghdr *nlh, gfp_t flags); 178 u32 group, struct nlmsghdr *nlh, gfp_t flags);
@@ -251,13 +258,16 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
251 * @net: the net namespace 258 * @net: the net namespace
252 * @skb: netlink message as socket buffer 259 * @skb: netlink message as socket buffer
253 * @portid: own netlink portid to avoid sending to yourself 260 * @portid: own netlink portid to avoid sending to yourself
254 * @group: multicast group id 261 * @group: offset of multicast group in groups array
255 * @flags: allocation flags 262 * @flags: allocation flags
256 */ 263 */
257static inline int genlmsg_multicast_netns(struct genl_family *family, 264static inline int genlmsg_multicast_netns(struct genl_family *family,
258 struct net *net, struct sk_buff *skb, 265 struct net *net, struct sk_buff *skb,
259 u32 portid, unsigned int group, gfp_t flags) 266 u32 portid, unsigned int group, gfp_t flags)
260{ 267{
268 if (group >= family->n_mcgrps)
269 return -EINVAL;
270 group = family->mcgrp_offset + group;
261 return nlmsg_multicast(net->genl_sock, skb, portid, group, flags); 271 return nlmsg_multicast(net->genl_sock, skb, portid, group, flags);
262} 272}
263 273
@@ -266,13 +276,16 @@ static inline int genlmsg_multicast_netns(struct genl_family *family,
266 * @family: the generic netlink family 276 * @family: the generic netlink family
267 * @skb: netlink message as socket buffer 277 * @skb: netlink message as socket buffer
268 * @portid: own netlink portid to avoid sending to yourself 278 * @portid: own netlink portid to avoid sending to yourself
269 * @group: multicast group id 279 * @group: offset of multicast group in groups array
270 * @flags: allocation flags 280 * @flags: allocation flags
271 */ 281 */
272static inline int genlmsg_multicast(struct genl_family *family, 282static inline int genlmsg_multicast(struct genl_family *family,
273 struct sk_buff *skb, u32 portid, 283 struct sk_buff *skb, u32 portid,
274 unsigned int group, gfp_t flags) 284 unsigned int group, gfp_t flags)
275{ 285{
286 if (group >= family->n_mcgrps)
287 return -EINVAL;
288 group = family->mcgrp_offset + group;
276 return genlmsg_multicast_netns(family, &init_net, skb, 289 return genlmsg_multicast_netns(family, &init_net, skb,
277 portid, group, flags); 290 portid, group, flags);
278} 291}
@@ -282,7 +295,7 @@ static inline int genlmsg_multicast(struct genl_family *family,
282 * @family: the generic netlink family 295 * @family: the generic netlink family
283 * @skb: netlink message as socket buffer 296 * @skb: netlink message as socket buffer
284 * @portid: own netlink portid to avoid sending to yourself 297 * @portid: own netlink portid to avoid sending to yourself
285 * @group: multicast group id 298 * @group: offset of multicast group in groups array
286 * @flags: allocation flags 299 * @flags: allocation flags
287 * 300 *
288 * This function must hold the RTNL or rcu_read_lock(). 301 * This function must hold the RTNL or rcu_read_lock().
@@ -365,6 +378,7 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
365 * @net: the network namespace to report the error to 378 * @net: the network namespace to report the error to
366 * @portid: the PORTID of a process that we want to skip (if any) 379 * @portid: the PORTID of a process that we want to skip (if any)
367 * @group: the broadcast group that will notice the error 380 * @group: the broadcast group that will notice the error
381 * (this is the offset of the multicast group in the groups array)
368 * @code: error code, must be negative (as usual in kernelspace) 382 * @code: error code, must be negative (as usual in kernelspace)
369 * 383 *
370 * This function returns the number of broadcast listeners that have set the 384 * This function returns the number of broadcast listeners that have set the