Loading drivers/block/drbd/drbd_int.h +6 −0 Original line number Diff line number Diff line Loading @@ -1407,6 +1407,12 @@ extern bool conn_try_outdate_peer(struct drbd_tconn *tconn); extern void conn_try_outdate_peer_async(struct drbd_tconn *tconn); extern int drbd_khelper(struct drbd_conf *mdev, char *cmd); struct nla_policy; extern int drbd_nla_check_mandatory(int maxtype, struct nlattr *nla); extern int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy); extern struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype); /* drbd_worker.c */ extern int drbd_worker(struct drbd_thread *thi); enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor); Loading drivers/block/drbd/drbd_nl.c +76 −20 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ static struct drbd_config_context { #define VOLUME_UNSPECIFIED (-1U) /* pointer into the request skb, * limited lifetime! */ char *conn_name; char *resource_name; /* reply buffer */ struct sk_buff *reply_skb; Loading Loading @@ -191,15 +191,15 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info, /* and assign stuff to the global adm_ctx */ nla = nested_attr_tb[__nla_type(T_ctx_volume)]; adm_ctx.volume = nla ? nla_get_u32(nla) : VOLUME_UNSPECIFIED; nla = nested_attr_tb[__nla_type(T_ctx_conn_name)]; nla = nested_attr_tb[__nla_type(T_ctx_resource_name)]; if (nla) adm_ctx.conn_name = nla_data(nla); adm_ctx.resource_name = nla_data(nla); } else adm_ctx.volume = VOLUME_UNSPECIFIED; adm_ctx.minor = d_in->minor; adm_ctx.mdev = minor_to_mdev(d_in->minor); adm_ctx.tconn = conn_get_by_name(adm_ctx.conn_name); adm_ctx.tconn = conn_get_by_name(adm_ctx.resource_name); if (!adm_ctx.mdev && (flags & DRBD_ADM_NEED_MINOR)) { drbd_msg_put_info("unknown minor"); Loading @@ -214,7 +214,8 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info, if (adm_ctx.mdev && adm_ctx.tconn && adm_ctx.mdev->tconn != adm_ctx.tconn) { pr_warning("request: minor=%u, conn=%s; but that minor belongs to connection %s\n", adm_ctx.minor, adm_ctx.conn_name, adm_ctx.mdev->tconn->name); adm_ctx.minor, adm_ctx.resource_name, adm_ctx.mdev->tconn->name); drbd_msg_put_info("minor exists in different connection"); return ERR_INVALID_REQUEST; } Loading @@ -239,7 +240,7 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info, static int drbd_adm_finish(struct genl_info *info, int retcode) { struct nlattr *nla; const char *conn_name = NULL; const char *resource_name = NULL; if (adm_ctx.tconn) { kref_put(&adm_ctx.tconn->kref, &conn_destroy); Loading @@ -253,9 +254,10 @@ static int drbd_adm_finish(struct genl_info *info, int retcode) nla = info->attrs[DRBD_NLA_CFG_CONTEXT]; if (nla) { nla = nla_find_nested(nla, __nla_type(T_ctx_conn_name)); if (nla) conn_name = nla_data(nla); int maxtype = ARRAY_SIZE(drbd_cfg_context_nl_policy) - 1; nla = drbd_nla_find_nested(maxtype, nla, __nla_type(T_ctx_resource_name)); if (nla && !IS_ERR(nla)) resource_name = nla_data(nla); } drbd_adm_send_reply(adm_ctx.reply_skb, info); Loading Loading @@ -2526,7 +2528,7 @@ int drbd_adm_outdate(struct sk_buff *skb, struct genl_info *info) return drbd_adm_simple_request_state(skb, info, NS(disk, D_OUTDATED)); } int nla_put_drbd_cfg_context(struct sk_buff *skb, const char *conn_name, unsigned vnr) int nla_put_drbd_cfg_context(struct sk_buff *skb, const char *resource_name, unsigned vnr) { struct nlattr *nla; nla = nla_nest_start(skb, DRBD_NLA_CFG_CONTEXT); Loading @@ -2534,7 +2536,7 @@ int nla_put_drbd_cfg_context(struct sk_buff *skb, const char *conn_name, unsigne goto nla_put_failure; if (vnr != VOLUME_UNSPECIFIED) NLA_PUT_U32(skb, T_ctx_volume, vnr); NLA_PUT_STRING(skb, T_ctx_conn_name, conn_name); NLA_PUT_STRING(skb, T_ctx_resource_name, resource_name); nla_nest_end(skb, nla); return 0; Loading Loading @@ -2778,8 +2780,9 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb) { const unsigned hdrlen = GENL_HDRLEN + GENL_MAGIC_FAMILY_HDRSZ; struct nlattr *nla; const char *conn_name; const char *resource_name; struct drbd_tconn *tconn; int maxtype; /* Is this a followup call? */ if (cb->args[0]) { Loading @@ -2799,12 +2802,15 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb) /* No explicit context given. Dump all. */ if (!nla) goto dump; nla = nla_find_nested(nla, __nla_type(T_ctx_conn_name)); maxtype = ARRAY_SIZE(drbd_cfg_context_nl_policy) - 1; nla = drbd_nla_find_nested(maxtype, nla, __nla_type(T_ctx_resource_name)); if (IS_ERR(nla)) return PTR_ERR(nla); /* context given, but no name present? */ if (!nla) return -EINVAL; conn_name = nla_data(nla); tconn = conn_get_by_name(conn_name); resource_name = nla_data(nla); tconn = conn_get_by_name(resource_name); if (!tconn) return -ENODEV; Loading Loading @@ -2957,16 +2963,16 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info) } static enum drbd_ret_code drbd_check_conn_name(const char *name) drbd_check_resource_name(const char *name) { if (!name || !name[0]) { drbd_msg_put_info("connection name missing"); drbd_msg_put_info("resource name missing"); return ERR_MANDATORY_TAG; } /* if we want to use these in sysfs/configfs/debugfs some day, * we must not allow slashes */ if (strchr(name, '/')) { drbd_msg_put_info("invalid connection name"); drbd_msg_put_info("invalid resource name"); return ERR_INVALID_REQUEST; } return NO_ERROR; Loading @@ -2982,7 +2988,7 @@ int drbd_adm_new_resource(struct sk_buff *skb, struct genl_info *info) if (retcode != NO_ERROR) goto out; retcode = drbd_check_conn_name(adm_ctx.conn_name); retcode = drbd_check_resource_name(adm_ctx.resource_name); if (retcode != NO_ERROR) goto out; Loading @@ -2995,7 +3001,7 @@ int drbd_adm_new_resource(struct sk_buff *skb, struct genl_info *info) goto out; } if (!conn_create(adm_ctx.conn_name)) if (!conn_create(adm_ctx.resource_name)) retcode = ERR_NOMEM; out: drbd_adm_finish(info, retcode); Loading Loading @@ -3213,3 +3219,53 @@ void drbd_bcast_event(struct drbd_conf *mdev, const struct sib_info *sib) "Event seq:%u sib_reason:%u\n", err, seq, sib->sib_reason); } int drbd_nla_check_mandatory(int maxtype, struct nlattr *nla) { struct nlattr *head = nla_data(nla); int len = nla_len(nla); int rem; /* * validate_nla (called from nla_parse_nested) ignores attributes * beyond maxtype, and does not understand the DRBD_GENLA_F_MANDATORY flag. * In order to have it validate attributes with the DRBD_GENLA_F_MANDATORY * flag set also, check and remove that flag before calling * nla_parse_nested. */ nla_for_each_attr(nla, head, len, rem) { if (nla->nla_type & DRBD_GENLA_F_MANDATORY) { nla->nla_type &= ~DRBD_GENLA_F_MANDATORY; if (nla_type(nla) > maxtype) return -EOPNOTSUPP; } } return 0; } int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy) { int err; err = drbd_nla_check_mandatory(maxtype, nla); if (!err) err = nla_parse_nested(tb, maxtype, nla, policy); return err; } struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype) { int err; /* * If any nested attribute has the DRBD_GENLA_F_MANDATORY flag set and * we don't know about that attribute, reject all the nested * attributes. */ err = drbd_nla_check_mandatory(maxtype, nla); if (err) return ERR_PTR(err); return nla_find_nested(nla, attrtype); } include/linux/drbd_genl.h +1 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ GENL_struct(DRBD_NLA_CFG_REPLY, 1, drbd_cfg_reply, * and the volume id within the resource. */ GENL_struct(DRBD_NLA_CFG_CONTEXT, 2, drbd_cfg_context, __u32_field(1, DRBD_GENLA_F_MANDATORY, ctx_volume) __str_field(2, DRBD_GENLA_F_MANDATORY, ctx_conn_name, 128) __str_field(2, DRBD_GENLA_F_MANDATORY, ctx_resource_name, 128) ) GENL_struct(DRBD_NLA_DISK_CONF, 3, disk_conf, Loading include/linux/genl_magic_func.h +0 −37 Original line number Diff line number Diff line Loading @@ -142,43 +142,6 @@ static struct nlattr *nested_attr_tb[128]; #define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); })) #endif static inline int drbd_nla_check_mandatory(int maxtype, struct nlattr *nla) { struct nlattr *head = nla_data(nla); int len = nla_len(nla); int rem; /* * validate_nla (called from nla_parse_nested) ignores attributes * beyond maxtype, and does not understand the DRBD_GENLA_F_MANDATORY flag. * In order to have it validate attributes with the DRBD_GENLA_F_MANDATORY * flag set also, check and remove that flag before calling * nla_parse_nested. */ nla_for_each_attr(nla, head, len, rem) { if (nla->nla_type & DRBD_GENLA_F_MANDATORY) { nla->nla_type &= ~DRBD_GENLA_F_MANDATORY; if (nla_type(nla) > maxtype) return -EOPNOTSUPP; } } return 0; } static inline int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy) { int err; err = drbd_nla_check_mandatory(maxtype, nla); if (!err) err = nla_parse_nested(tb, maxtype, nla, policy); return err; } #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ /* *_from_attrs functions are static, but potentially unused */ \ Loading Loading
drivers/block/drbd/drbd_int.h +6 −0 Original line number Diff line number Diff line Loading @@ -1407,6 +1407,12 @@ extern bool conn_try_outdate_peer(struct drbd_tconn *tconn); extern void conn_try_outdate_peer_async(struct drbd_tconn *tconn); extern int drbd_khelper(struct drbd_conf *mdev, char *cmd); struct nla_policy; extern int drbd_nla_check_mandatory(int maxtype, struct nlattr *nla); extern int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy); extern struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype); /* drbd_worker.c */ extern int drbd_worker(struct drbd_thread *thi); enum drbd_ret_code drbd_resync_after_valid(struct drbd_conf *mdev, int o_minor); Loading
drivers/block/drbd/drbd_nl.c +76 −20 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ static struct drbd_config_context { #define VOLUME_UNSPECIFIED (-1U) /* pointer into the request skb, * limited lifetime! */ char *conn_name; char *resource_name; /* reply buffer */ struct sk_buff *reply_skb; Loading Loading @@ -191,15 +191,15 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info, /* and assign stuff to the global adm_ctx */ nla = nested_attr_tb[__nla_type(T_ctx_volume)]; adm_ctx.volume = nla ? nla_get_u32(nla) : VOLUME_UNSPECIFIED; nla = nested_attr_tb[__nla_type(T_ctx_conn_name)]; nla = nested_attr_tb[__nla_type(T_ctx_resource_name)]; if (nla) adm_ctx.conn_name = nla_data(nla); adm_ctx.resource_name = nla_data(nla); } else adm_ctx.volume = VOLUME_UNSPECIFIED; adm_ctx.minor = d_in->minor; adm_ctx.mdev = minor_to_mdev(d_in->minor); adm_ctx.tconn = conn_get_by_name(adm_ctx.conn_name); adm_ctx.tconn = conn_get_by_name(adm_ctx.resource_name); if (!adm_ctx.mdev && (flags & DRBD_ADM_NEED_MINOR)) { drbd_msg_put_info("unknown minor"); Loading @@ -214,7 +214,8 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info, if (adm_ctx.mdev && adm_ctx.tconn && adm_ctx.mdev->tconn != adm_ctx.tconn) { pr_warning("request: minor=%u, conn=%s; but that minor belongs to connection %s\n", adm_ctx.minor, adm_ctx.conn_name, adm_ctx.mdev->tconn->name); adm_ctx.minor, adm_ctx.resource_name, adm_ctx.mdev->tconn->name); drbd_msg_put_info("minor exists in different connection"); return ERR_INVALID_REQUEST; } Loading @@ -239,7 +240,7 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info, static int drbd_adm_finish(struct genl_info *info, int retcode) { struct nlattr *nla; const char *conn_name = NULL; const char *resource_name = NULL; if (adm_ctx.tconn) { kref_put(&adm_ctx.tconn->kref, &conn_destroy); Loading @@ -253,9 +254,10 @@ static int drbd_adm_finish(struct genl_info *info, int retcode) nla = info->attrs[DRBD_NLA_CFG_CONTEXT]; if (nla) { nla = nla_find_nested(nla, __nla_type(T_ctx_conn_name)); if (nla) conn_name = nla_data(nla); int maxtype = ARRAY_SIZE(drbd_cfg_context_nl_policy) - 1; nla = drbd_nla_find_nested(maxtype, nla, __nla_type(T_ctx_resource_name)); if (nla && !IS_ERR(nla)) resource_name = nla_data(nla); } drbd_adm_send_reply(adm_ctx.reply_skb, info); Loading Loading @@ -2526,7 +2528,7 @@ int drbd_adm_outdate(struct sk_buff *skb, struct genl_info *info) return drbd_adm_simple_request_state(skb, info, NS(disk, D_OUTDATED)); } int nla_put_drbd_cfg_context(struct sk_buff *skb, const char *conn_name, unsigned vnr) int nla_put_drbd_cfg_context(struct sk_buff *skb, const char *resource_name, unsigned vnr) { struct nlattr *nla; nla = nla_nest_start(skb, DRBD_NLA_CFG_CONTEXT); Loading @@ -2534,7 +2536,7 @@ int nla_put_drbd_cfg_context(struct sk_buff *skb, const char *conn_name, unsigne goto nla_put_failure; if (vnr != VOLUME_UNSPECIFIED) NLA_PUT_U32(skb, T_ctx_volume, vnr); NLA_PUT_STRING(skb, T_ctx_conn_name, conn_name); NLA_PUT_STRING(skb, T_ctx_resource_name, resource_name); nla_nest_end(skb, nla); return 0; Loading Loading @@ -2778,8 +2780,9 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb) { const unsigned hdrlen = GENL_HDRLEN + GENL_MAGIC_FAMILY_HDRSZ; struct nlattr *nla; const char *conn_name; const char *resource_name; struct drbd_tconn *tconn; int maxtype; /* Is this a followup call? */ if (cb->args[0]) { Loading @@ -2799,12 +2802,15 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb) /* No explicit context given. Dump all. */ if (!nla) goto dump; nla = nla_find_nested(nla, __nla_type(T_ctx_conn_name)); maxtype = ARRAY_SIZE(drbd_cfg_context_nl_policy) - 1; nla = drbd_nla_find_nested(maxtype, nla, __nla_type(T_ctx_resource_name)); if (IS_ERR(nla)) return PTR_ERR(nla); /* context given, but no name present? */ if (!nla) return -EINVAL; conn_name = nla_data(nla); tconn = conn_get_by_name(conn_name); resource_name = nla_data(nla); tconn = conn_get_by_name(resource_name); if (!tconn) return -ENODEV; Loading Loading @@ -2957,16 +2963,16 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info) } static enum drbd_ret_code drbd_check_conn_name(const char *name) drbd_check_resource_name(const char *name) { if (!name || !name[0]) { drbd_msg_put_info("connection name missing"); drbd_msg_put_info("resource name missing"); return ERR_MANDATORY_TAG; } /* if we want to use these in sysfs/configfs/debugfs some day, * we must not allow slashes */ if (strchr(name, '/')) { drbd_msg_put_info("invalid connection name"); drbd_msg_put_info("invalid resource name"); return ERR_INVALID_REQUEST; } return NO_ERROR; Loading @@ -2982,7 +2988,7 @@ int drbd_adm_new_resource(struct sk_buff *skb, struct genl_info *info) if (retcode != NO_ERROR) goto out; retcode = drbd_check_conn_name(adm_ctx.conn_name); retcode = drbd_check_resource_name(adm_ctx.resource_name); if (retcode != NO_ERROR) goto out; Loading @@ -2995,7 +3001,7 @@ int drbd_adm_new_resource(struct sk_buff *skb, struct genl_info *info) goto out; } if (!conn_create(adm_ctx.conn_name)) if (!conn_create(adm_ctx.resource_name)) retcode = ERR_NOMEM; out: drbd_adm_finish(info, retcode); Loading Loading @@ -3213,3 +3219,53 @@ void drbd_bcast_event(struct drbd_conf *mdev, const struct sib_info *sib) "Event seq:%u sib_reason:%u\n", err, seq, sib->sib_reason); } int drbd_nla_check_mandatory(int maxtype, struct nlattr *nla) { struct nlattr *head = nla_data(nla); int len = nla_len(nla); int rem; /* * validate_nla (called from nla_parse_nested) ignores attributes * beyond maxtype, and does not understand the DRBD_GENLA_F_MANDATORY flag. * In order to have it validate attributes with the DRBD_GENLA_F_MANDATORY * flag set also, check and remove that flag before calling * nla_parse_nested. */ nla_for_each_attr(nla, head, len, rem) { if (nla->nla_type & DRBD_GENLA_F_MANDATORY) { nla->nla_type &= ~DRBD_GENLA_F_MANDATORY; if (nla_type(nla) > maxtype) return -EOPNOTSUPP; } } return 0; } int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy) { int err; err = drbd_nla_check_mandatory(maxtype, nla); if (!err) err = nla_parse_nested(tb, maxtype, nla, policy); return err; } struct nlattr *drbd_nla_find_nested(int maxtype, struct nlattr *nla, int attrtype) { int err; /* * If any nested attribute has the DRBD_GENLA_F_MANDATORY flag set and * we don't know about that attribute, reject all the nested * attributes. */ err = drbd_nla_check_mandatory(maxtype, nla); if (err) return ERR_PTR(err); return nla_find_nested(nla, attrtype); }
include/linux/drbd_genl.h +1 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ GENL_struct(DRBD_NLA_CFG_REPLY, 1, drbd_cfg_reply, * and the volume id within the resource. */ GENL_struct(DRBD_NLA_CFG_CONTEXT, 2, drbd_cfg_context, __u32_field(1, DRBD_GENLA_F_MANDATORY, ctx_volume) __str_field(2, DRBD_GENLA_F_MANDATORY, ctx_conn_name, 128) __str_field(2, DRBD_GENLA_F_MANDATORY, ctx_resource_name, 128) ) GENL_struct(DRBD_NLA_DISK_CONF, 3, disk_conf, Loading
include/linux/genl_magic_func.h +0 −37 Original line number Diff line number Diff line Loading @@ -142,43 +142,6 @@ static struct nlattr *nested_attr_tb[128]; #define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); })) #endif static inline int drbd_nla_check_mandatory(int maxtype, struct nlattr *nla) { struct nlattr *head = nla_data(nla); int len = nla_len(nla); int rem; /* * validate_nla (called from nla_parse_nested) ignores attributes * beyond maxtype, and does not understand the DRBD_GENLA_F_MANDATORY flag. * In order to have it validate attributes with the DRBD_GENLA_F_MANDATORY * flag set also, check and remove that flag before calling * nla_parse_nested. */ nla_for_each_attr(nla, head, len, rem) { if (nla->nla_type & DRBD_GENLA_F_MANDATORY) { nla->nla_type &= ~DRBD_GENLA_F_MANDATORY; if (nla_type(nla) > maxtype) return -EOPNOTSUPP; } } return 0; } static inline int drbd_nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy) { int err; err = drbd_nla_check_mandatory(maxtype, nla); if (!err) err = nla_parse_nested(tb, maxtype, nla, policy); return err; } #undef GENL_struct #define GENL_struct(tag_name, tag_number, s_name, s_fields) \ /* *_from_attrs functions are static, but potentially unused */ \ Loading