aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-11-24 15:09:26 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-28 18:26:30 -0500
commit5e53e689b737526308db2b5c9f56e9d0371a1676 (patch)
tree933490eed9b4751978bb9d469d6afb6013646a8d
parent0f0e2159c0c101426b705d70f43b9f423d51c869 (diff)
genetlink/pmcraid: use proper genetlink multicast API
The pmcraid driver is abusing the genetlink API and is using its family ID as the multicast group ID, which is invalid and may belong to somebody else (and likely will.) Make it use the correct API, but since this may already be used as-is by userspace, reserve a family ID for this code and also reserve that group ID to not break userspace assumptions. My previous patch broke event delivery in the driver as I missed that it wasn't using the right API and forgot to update it later in my series. While changing this, I noticed that the genetlink code could use the static group ID instead of a strcmp(), so also do that for the VFS_DQUOT family. Cc: Anil Ravindranath <anil_ravindranath@pmc-sierra.com> Cc: "James E.J. Bottomley" <JBottomley@parallels.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/scsi/pmcraid.c20
-rw-r--r--include/uapi/linux/genetlink.h1
-rw-r--r--net/netlink/genetlink.c11
3 files changed, 25 insertions, 7 deletions
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index bd6f743d87a7..892ea6161376 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -1404,11 +1404,22 @@ enum {
1404}; 1404};
1405#define PMCRAID_AEN_CMD_MAX (__PMCRAID_AEN_CMD_MAX - 1) 1405#define PMCRAID_AEN_CMD_MAX (__PMCRAID_AEN_CMD_MAX - 1)
1406 1406
1407static struct genl_multicast_group pmcraid_mcgrps[] = {
1408 { .name = "events", /* not really used - see ID discussion below */ },
1409};
1410
1407static struct genl_family pmcraid_event_family = { 1411static struct genl_family pmcraid_event_family = {
1408 .id = GENL_ID_GENERATE, 1412 /*
1413 * Due to prior multicast group abuse (the code having assumed that
1414 * the family ID can be used as a multicast group ID) we need to
1415 * statically allocate a family (and thus group) ID.
1416 */
1417 .id = GENL_ID_PMCRAID,
1409 .name = "pmcraid", 1418 .name = "pmcraid",
1410 .version = 1, 1419 .version = 1,
1411 .maxattr = PMCRAID_AEN_ATTR_MAX 1420 .maxattr = PMCRAID_AEN_ATTR_MAX,
1421 .mcgrps = pmcraid_mcgrps,
1422 .n_mcgrps = ARRAY_SIZE(pmcraid_mcgrps),
1412}; 1423};
1413 1424
1414/** 1425/**
@@ -1511,9 +1522,8 @@ static int pmcraid_notify_aen(
1511 return result; 1522 return result;
1512 } 1523 }
1513 1524
1514 result = 1525 result = genlmsg_multicast(&pmcraid_event_family, skb,
1515 genlmsg_multicast(&pmcraid_event_family, skb, 0, 1526 0, 0, GFP_ATOMIC);
1516 pmcraid_event_family.id, GFP_ATOMIC);
1517 1527
1518 /* If there are no listeners, genlmsg_multicast may return non-zero 1528 /* If there are no listeners, genlmsg_multicast may return non-zero
1519 * value. 1529 * value.
diff --git a/include/uapi/linux/genetlink.h b/include/uapi/linux/genetlink.h
index 1af72d8228e0..c3363ba1ae05 100644
--- a/include/uapi/linux/genetlink.h
+++ b/include/uapi/linux/genetlink.h
@@ -28,6 +28,7 @@ struct genlmsghdr {
28#define GENL_ID_GENERATE 0 28#define GENL_ID_GENERATE 0
29#define GENL_ID_CTRL NLMSG_MIN_TYPE 29#define GENL_ID_CTRL NLMSG_MIN_TYPE
30#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1) 30#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1)
31#define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2)
31 32
32/************************************************************************** 33/**************************************************************************
33 * Controller 34 * Controller
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 803206e82450..713671ae45af 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -74,9 +74,12 @@ static struct list_head family_ht[GENL_FAM_TAB_SIZE];
74 * Bit 17 is marked as already used since the VFS quota code 74 * Bit 17 is marked as already used since the VFS quota code
75 * also abused this API and relied on family == group ID, we 75 * also abused this API and relied on family == group ID, we
76 * cater to that by giving it a static family and group ID. 76 * cater to that by giving it a static family and group ID.
77 * Bit 18 is marked as already used since the PMCRAID driver
78 * did the same thing as the VFS quota code (maybe copied?)
77 */ 79 */
78static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) | 80static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
79 BIT(GENL_ID_VFS_DQUOT); 81 BIT(GENL_ID_VFS_DQUOT) |
82 BIT(GENL_ID_PMCRAID);
80static unsigned long *mc_groups = &mc_group_start; 83static unsigned long *mc_groups = &mc_group_start;
81static unsigned long mc_groups_longs = 1; 84static unsigned long mc_groups_longs = 1;
82 85
@@ -139,6 +142,7 @@ static u16 genl_generate_id(void)
139 142
140 for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) { 143 for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) {
141 if (id_gen_idx != GENL_ID_VFS_DQUOT && 144 if (id_gen_idx != GENL_ID_VFS_DQUOT &&
145 id_gen_idx != GENL_ID_PMCRAID &&
142 !genl_family_find_byid(id_gen_idx)) 146 !genl_family_find_byid(id_gen_idx))
143 return id_gen_idx; 147 return id_gen_idx;
144 if (++id_gen_idx > GENL_MAX_ID) 148 if (++id_gen_idx > GENL_MAX_ID)
@@ -236,9 +240,12 @@ static int genl_validate_assign_mc_groups(struct genl_family *family)
236 } else if (strcmp(family->name, "NET_DM") == 0) { 240 } else if (strcmp(family->name, "NET_DM") == 0) {
237 first_id = 1; 241 first_id = 1;
238 BUG_ON(n_groups != 1); 242 BUG_ON(n_groups != 1);
239 } else if (strcmp(family->name, "VFS_DQUOT") == 0) { 243 } else if (family->id == GENL_ID_VFS_DQUOT) {
240 first_id = GENL_ID_VFS_DQUOT; 244 first_id = GENL_ID_VFS_DQUOT;
241 BUG_ON(n_groups != 1); 245 BUG_ON(n_groups != 1);
246 } else if (family->id == GENL_ID_PMCRAID) {
247 first_id = GENL_ID_PMCRAID;
248 BUG_ON(n_groups != 1);
242 } else { 249 } else {
243 groups_allocated = true; 250 groups_allocated = true;
244 err = genl_allocate_reserve_groups(n_groups, &first_id); 251 err = genl_allocate_reserve_groups(n_groups, &first_id);