Commit 422e3d37 authored by Jason Gunthorpe's avatar Jason Gunthorpe

RDMA/uverbs: Combine MIN_SZ_OR_ZERO with UVERBS_ATTR_STRUCT

After all the rework is done it is now possible to include single flags in
the type macros. Any user of UVERBS_ATTR_STRUCT needs to zero check data
past the end of the known struct to be correct, so make this mandatory,
and get rid of MIN_SZ_OR_ZERO as a user flag.

This changes UVERBS_ATTR_TYPE to refer to a struct of exact size with not
possibility of extension, convert the few users of UVERBS_ATTR_TYPE and
MIN_SZ_OR_ZERO to use UVERBS_ATTR_STRUCT.

The one user of UVERBS_ATTR_STRUCT without MIN_SZ_OR_ZERO is just
confused. There is some padding at the end of that struct, but userspace
always provides it with the padding. The construction doesn't test if the
padding is zero, so it is pointless. Just use UVERBS_ATTR_TYPE.

Finally, rename min_sz_or_zero to zero_trailing to better reflect what it
does and hopefully avoid such mis-uses in the future.
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
parent 540cd692
...@@ -98,14 +98,14 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile, ...@@ -98,14 +98,14 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
* non-zero content, making ABI compat/discovery simpler. * non-zero content, making ABI compat/discovery simpler.
*/ */
if (uattr->len > val_spec->u.ptr.len && if (uattr->len > val_spec->u.ptr.len &&
val_spec->min_sz_or_zero && val_spec->zero_trailing &&
!uverbs_is_attr_cleared(uattr, val_spec->u.ptr.len)) !uverbs_is_attr_cleared(uattr, val_spec->u.ptr.len))
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* fall through */ /* fall through */
case UVERBS_ATTR_TYPE_PTR_OUT: case UVERBS_ATTR_TYPE_PTR_OUT:
if (uattr->len < val_spec->u.ptr.min_len || if (uattr->len < val_spec->u.ptr.min_len ||
(!val_spec->min_sz_or_zero && (!val_spec->zero_trailing &&
uattr->len > val_spec->u.ptr.len)) uattr->len > val_spec->u.ptr.len))
return -EINVAL; return -EINVAL;
......
...@@ -378,7 +378,7 @@ static struct uverbs_method_spec *build_method_with_attrs(const struct uverbs_me ...@@ -378,7 +378,7 @@ static struct uverbs_method_spec *build_method_with_attrs(const struct uverbs_me
"ib_uverbs: Tried to merge attr (%d) but it's an object with new/destroy access but isn't mandatory\n", "ib_uverbs: Tried to merge attr (%d) but it's an object with new/destroy access but isn't mandatory\n",
min_id) || min_id) ||
WARN(IS_ATTR_OBJECT(attr) && WARN(IS_ATTR_OBJECT(attr) &&
attr->min_sz_or_zero, attr->zero_trailing,
"ib_uverbs: Tried to merge attr (%d) but it's an object with min_sz flag\n", "ib_uverbs: Tried to merge attr (%d) but it's an object with min_sz flag\n",
min_id)) { min_id)) {
res = -EINVAL; res = -EINVAL;
......
...@@ -367,8 +367,9 @@ static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY)(struct ib_device ...@@ -367,8 +367,9 @@ static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY)(struct ib_device
static const struct uverbs_attr_spec uverbs_flow_action_esp_keymat[] = { static const struct uverbs_attr_spec uverbs_flow_action_esp_keymat[] = {
[IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = { [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = {
.type = UVERBS_ATTR_TYPE_PTR_IN, .type = UVERBS_ATTR_TYPE_PTR_IN,
UVERBS_ATTR_TYPE(struct ib_uverbs_flow_action_esp_keymat_aes_gcm), UVERBS_ATTR_STRUCT(
UA_MIN_SZ_OR_ZERO struct ib_uverbs_flow_action_esp_keymat_aes_gcm,
aes_key),
}, },
}; };
...@@ -380,8 +381,8 @@ static const struct uverbs_attr_spec uverbs_flow_action_esp_replay[] = { ...@@ -380,8 +381,8 @@ static const struct uverbs_attr_spec uverbs_flow_action_esp_replay[] = {
}, },
[IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = { [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = {
.type = UVERBS_ATTR_TYPE_PTR_IN, .type = UVERBS_ATTR_TYPE_PTR_IN,
UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_replay_bmp, size), UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_replay_bmp,
UA_MIN_SZ_OR_ZERO size),
}, },
}; };
...@@ -394,8 +395,7 @@ DECLARE_UVERBS_NAMED_METHOD( ...@@ -394,8 +395,7 @@ DECLARE_UVERBS_NAMED_METHOD(
UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS, UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS,
UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp, UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp,
hard_limit_pkts), hard_limit_pkts),
UA_MANDATORY, UA_MANDATORY),
UA_MIN_SZ_OR_ZERO),
UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN, UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN,
UVERBS_ATTR_TYPE(__u32), UVERBS_ATTR_TYPE(__u32),
UA_OPTIONAL), UA_OPTIONAL),
...@@ -407,8 +407,7 @@ DECLARE_UVERBS_NAMED_METHOD( ...@@ -407,8 +407,7 @@ DECLARE_UVERBS_NAMED_METHOD(
UA_OPTIONAL), UA_OPTIONAL),
UVERBS_ATTR_PTR_IN( UVERBS_ATTR_PTR_IN(
UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP, UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_encap, UVERBS_ATTR_TYPE(struct ib_uverbs_flow_action_esp_encap),
type),
UA_OPTIONAL)); UA_OPTIONAL));
DECLARE_UVERBS_NAMED_METHOD( DECLARE_UVERBS_NAMED_METHOD(
...@@ -420,8 +419,7 @@ DECLARE_UVERBS_NAMED_METHOD( ...@@ -420,8 +419,7 @@ DECLARE_UVERBS_NAMED_METHOD(
UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS, UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS,
UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp, UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp,
hard_limit_pkts), hard_limit_pkts),
UA_OPTIONAL, UA_OPTIONAL),
UA_MIN_SZ_OR_ZERO),
UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN, UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN,
UVERBS_ATTR_TYPE(__u32), UVERBS_ATTR_TYPE(__u32),
UA_OPTIONAL), UA_OPTIONAL),
...@@ -433,8 +431,7 @@ DECLARE_UVERBS_NAMED_METHOD( ...@@ -433,8 +431,7 @@ DECLARE_UVERBS_NAMED_METHOD(
UA_OPTIONAL), UA_OPTIONAL),
UVERBS_ATTR_PTR_IN( UVERBS_ATTR_PTR_IN(
UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP, UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_encap, UVERBS_ATTR_TYPE(struct ib_uverbs_flow_action_esp_encap),
type),
UA_OPTIONAL)); UA_OPTIONAL));
DECLARE_UVERBS_NAMED_METHOD_DESTROY( DECLARE_UVERBS_NAMED_METHOD_DESTROY(
......
...@@ -67,10 +67,11 @@ struct uverbs_attr_spec { ...@@ -67,10 +67,11 @@ struct uverbs_attr_spec {
u8 type; u8 type;
/* /*
* Support extending attributes by length, validate all * Support extending attributes by length. Allow the user to provide
* unknown size == zero * more bytes than ptr.len, but check that everything after is zero'd
* by the user.
*/ */
u8 min_sz_or_zero:1; u8 zero_trailing:1;
/* /*
* Valid only for PTR_IN. Allocate and copy the data inside * Valid only for PTR_IN. Allocate and copy the data inside
* the parser * the parser
...@@ -200,13 +201,26 @@ struct uverbs_object_tree_def { ...@@ -200,13 +201,26 @@ struct uverbs_object_tree_def {
* ======================================= * =======================================
*/ */
/* Use in the _type parameter for attribute specifications */
#define UVERBS_ATTR_TYPE(_type) \
.u.ptr.min_len = sizeof(_type), .u.ptr.len = sizeof(_type)
#define UVERBS_ATTR_STRUCT(_type, _last) \
.u.ptr.min_len = ((uintptr_t)(&((_type *)0)->_last + 1)), .u.ptr.len = sizeof(_type)
#define UVERBS_ATTR_SIZE(_min_len, _len) \ #define UVERBS_ATTR_SIZE(_min_len, _len) \
.u.ptr.min_len = _min_len, .u.ptr.len = _len .u.ptr.min_len = _min_len, .u.ptr.len = _len
/*
* Specifies a uapi structure that cannot be extended. The user must always
* supply the whole structure and nothing more. The structure must be declared
* in a header under include/uapi/rdma.
*/
#define UVERBS_ATTR_TYPE(_type) \
.u.ptr.min_len = sizeof(_type), .u.ptr.len = sizeof(_type)
/*
* Specifies a uapi structure where the user must provide at least up to
* member 'last'. Anything after last and up until the end of the structure
* can be non-zero, anything longer than the end of the structure must be
* zero. The structure must be declared in a header under include/uapi/rdma.
*/
#define UVERBS_ATTR_STRUCT(_type, _last) \
.zero_trailing = 1, \
UVERBS_ATTR_SIZE(((uintptr_t)(&((_type *)0)->_last + 1)), \
sizeof(_type))
/* /*
* Specifies at least min_len bytes must be passed in, but the amount can be * Specifies at least min_len bytes must be passed in, but the amount can be
* larger, up to the protocol maximum size. No check for zeroing is done. * larger, up to the protocol maximum size. No check for zeroing is done.
...@@ -216,7 +230,6 @@ struct uverbs_object_tree_def { ...@@ -216,7 +230,6 @@ struct uverbs_object_tree_def {
/* Must be used in the '...' of any UVERBS_ATTR */ /* Must be used in the '...' of any UVERBS_ATTR */
#define UA_ALLOC_AND_COPY .alloc_and_copy = 1 #define UA_ALLOC_AND_COPY .alloc_and_copy = 1
#define UA_MANDATORY .mandatory = 1 #define UA_MANDATORY .mandatory = 1
#define UA_MIN_SZ_OR_ZERO .min_sz_or_zero = 1
#define UA_OPTIONAL .mandatory = 0 #define UA_OPTIONAL .mandatory = 0
#define UVERBS_ATTR_IDR(_attr_id, _idr_type, _access, ...) \ #define UVERBS_ATTR_IDR(_attr_id, _idr_type, _access, ...) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment