2020-05-08 14:52:40 +00:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
2020-04-23 20:47:21 +00:00
|
|
|
From: Prarit Bhargava <prarit@redhat.com>
|
|
|
|
Date: Wed, 19 Feb 2020 11:52:16 +0100
|
|
|
|
Subject: [PATCH] redhat: rh_kabi: Add macros to size and extend structs
|
|
|
|
|
|
|
|
RH-Acked-by: Ivan Vecera <ivecera@redhat.com>
|
|
|
|
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
|
|
|
|
RH-Acked-by: Jiri Benc <jbenc@redhat.com>
|
|
|
|
|
|
|
|
Upstream: RHEL-only
|
|
|
|
|
|
|
|
As noted in the reviews, there are some areas of future work:
|
|
|
|
|
|
|
|
1) A further restriction on the access of the extended struct fields
|
|
|
|
would be to require the addition of an accessor function.
|
|
|
|
2) Additional macros to use RH_KABI_EXTEND fields.
|
|
|
|
3) Additional macros to mark extended struts' field for internal kernel
|
|
|
|
versus module use.
|
|
|
|
|
|
|
|
The RHEL7 code contains macros to extend kernel structs. For example, the
|
|
|
|
RH_KABI_EXTEND() can be used to extend a struct when used appropriately.
|
|
|
|
This macro (and others similar to it) has a significant shortcoming as it
|
|
|
|
cannot be used in the case where a struct is known to allocate the struct
|
|
|
|
within a 3rd party module. For example, in RHELX.0, suppose there exists
|
|
|
|
a struct,
|
|
|
|
|
|
|
|
struct in_kernel {
|
|
|
|
int foo0;
|
|
|
|
};
|
|
|
|
|
|
|
|
and an exported function,
|
|
|
|
|
|
|
|
void in_kernel_set_foo(struct in_kernel *ink)
|
|
|
|
{
|
|
|
|
...
|
|
|
|
ink->foo0 = 0xBA5EBA11;
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
Let's also suppose a struct in_kernel is statically defined within a 3rd
|
|
|
|
party module, or dynamically allocated as
|
|
|
|
|
|
|
|
struct in_kernel *3rd_party_ink;
|
|
|
|
...
|
|
|
|
ink = kmalloc(sizeof(*3rd_party_ink), GFP_KERNEL);
|
|
|
|
...
|
|
|
|
|
|
|
|
In RHELX.1, suppose the struct is expanded by
|
|
|
|
|
|
|
|
struct in_kernel {
|
|
|
|
int foo0;
|
|
|
|
RH_KABI_EXTEND(foo1)
|
|
|
|
};
|
|
|
|
|
|
|
|
and the exported function is modified as
|
|
|
|
|
|
|
|
void in_kernel_set_foo(struct in_kernel *ink)
|
|
|
|
{
|
|
|
|
...
|
|
|
|
ink->foo0 = 0xBA5EBA11;
|
|
|
|
ink->foo1 = 0xBA5EBA11;
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
The 3rd party module, compiled against RHELX.0, will not have allocated
|
|
|
|
memory for foo1, and in_kernel_set_foo() will reference garbage in memory.
|
|
|
|
|
|
|
|
To fix this problem, Jiri Benc came up with an great solution that should
|
|
|
|
be unified for all future RHELX.0 expansions of structs. RHEL7 commit
|
|
|
|
e33a3c136b56 ("[net] introduce net_device_ops_extended") adds a size
|
|
|
|
parameter to net_device_ops that can be queried to validate memory
|
|
|
|
accesses. In the patch, net_device_ops is expanded by embedding a
|
|
|
|
net_device_ops_extended struct and addig a size parameter. The size
|
|
|
|
parameter is used to compare the offset of a parameter in the
|
|
|
|
net_device_ops_extended struct to the size of the struct at compile time,
|
|
|
|
and if valid, the memory access can be programmatically allowed to occur.
|
|
|
|
|
|
|
|
I have taken his idea and created several new standard macros that allow
|
|
|
|
structs to be expanded by embedding a new struct or by adding a pointer
|
|
|
|
to a new struct.
|
|
|
|
|
|
|
|
There are, however, some rules that must be followed when using these
|
|
|
|
new macros:
|
|
|
|
|
|
|
|
1. The default name of the extended struct is ##name##_rh. For example,
|
|
|
|
pci_dev_rh, device_rh, net_device_ops_rh, etc.
|
|
|
|
2. _rh structs cannot be shrunk in size as such changes would break the
|
|
|
|
size & offset comparison.
|
|
|
|
3. The size field _must_ be set at the spot of allocation for use. Use of the
|
|
|
|
_rh fields without setting the size field via RH_KABI_SET_SIZE|_PTR() is
|
|
|
|
invalid in the kernel or in a 3rd party module.
|
|
|
|
4. These new macros do not preclude expansions like
|
|
|
|
|
|
|
|
struct in_kernel_rh {
|
|
|
|
};
|
|
|
|
|
|
|
|
struct in_kernel {
|
|
|
|
...
|
|
|
|
RH_KABI_EXTEND(void *ptr1)
|
|
|
|
RH_KABI_EXTEND(void *ptr2)
|
|
|
|
RH_KABI_EXTEND(void *ptr3)
|
|
|
|
RH_KABI_EXTEND(void *ptr4)
|
|
|
|
RH_KABI_SIZE_AND_EXTEND_PTR(in_kernel)
|
|
|
|
};
|
|
|
|
|
|
|
|
These macros are generally intended for pre-KABI freeze use, however,
|
|
|
|
there may be cases where these macros can be used post-KABI freeze.
|
|
|
|
Due to the design of RH_KABI_EXTEND() which embeds __GENKSYMS__ care must
|
|
|
|
be taken when using RH_KABI_SIZE_AND_EXTEND|_PTR() post-KABI freeze to
|
|
|
|
ensure that structs are not embedded within another struct, verifying
|
|
|
|
offsets, etc.
|
|
|
|
|
|
|
|
Add RH_KABI_SIZE_AND_EXTEND(), RH_KABI_SIZE_AND_EXTEND_PTR(), and
|
|
|
|
other macros that allow for safe expansion of structs.
|
|
|
|
|
|
|
|
v2: Cleanup comments.
|
|
|
|
v3: Cleanup comments.
|
|
|
|
|
|
|
|
Upstream Status: RHEL only
|
|
|
|
Signed-off-by: Prarit Bhargava <prarit@redhat.com>
|
|
|
|
Signed-off-by: Jiri Benc <jbenc@redhat.com>
|
|
|
|
---
|
|
|
|
include/linux/rh_kabi.h | 64 +++++++++++++++++++++++++++++++++++++++++
|
|
|
|
1 file changed, 64 insertions(+)
|
|
|
|
|
|
|
|
diff --git a/include/linux/rh_kabi.h b/include/linux/rh_kabi.h
|
|
|
|
index 87f2bd530df7..d551df994583 100644
|
|
|
|
--- a/include/linux/rh_kabi.h
|
|
|
|
+++ b/include/linux/rh_kabi.h
|
|
|
|
@@ -186,4 +186,68 @@
|
2020-04-27 02:15:20 +00:00
|
|
|
|
2020-04-23 20:47:21 +00:00
|
|
|
#define RH_KABI_EXCLUDE(_elem) _RH_KABI_EXCLUDE(_elem);
|
2020-04-27 02:15:20 +00:00
|
|
|
|
2020-04-23 20:47:21 +00:00
|
|
|
+/*
|
|
|
|
+ * RHEL macros to extend structs.
|
|
|
|
+ *
|
|
|
|
+ * base struct: The struct being extended. For example, pci_dev.
|
|
|
|
+ * extended struct: The Red Hat struct being added to the base struct.
|
|
|
|
+ * For example, pci_dev_rh.
|
|
|
|
+ *
|
|
|
|
+ * These macros should be used to extend structs before KABI freeze.
|
|
|
|
+ * They can be used post-KABI freeze in the limited case of the base
|
|
|
|
+ * struct not being embedded in another struct.
|
|
|
|
+ *
|
|
|
|
+ * Extended structs cannot be shrunk in size as changes will break
|
|
|
|
+ * the size & offset comparison.
|
|
|
|
+ *
|
|
|
|
+ * Extended struct elements are not guaranteed for access by modules unless
|
|
|
|
+ * explicitly commented as such in the declaration of the extended struct or
|
|
|
|
+ * the element in the extended struct.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * RH_KABI_SIZE_AND_EXTEND|_PTR() extends a struct by embedding or adding
|
|
|
|
+ * a pointer in a base struct. The name of the new struct is the name
|
|
|
|
+ * of the base struct appended with _rh.
|
|
|
|
+ */
|
|
|
|
+#define RH_KABI_SIZE_AND_EXTEND_PTR(_struct) \
|
|
|
|
+ size_t _struct##_size_rh; \
|
|
|
|
+ RH_KABI_EXCLUDE(struct _struct##_rh *_struct##_rh)
|
|
|
|
+
|
|
|
|
+#define RH_KABI_SIZE_AND_EXTEND(_struct) \
|
|
|
|
+ size_t _struct##_size_rh; \
|
|
|
|
+ RH_KABI_EXCLUDE(struct _struct##_rh _struct##_rh)
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * RH_KABI_SET_SIZE calculates and sets the size of the extended struct and
|
|
|
|
+ * stores it in the size_rh field for structs that are dynamically allocated.
|
|
|
|
+ * This macro MUST be called when expanding a base struct with
|
|
|
|
+ * RH_KABI_SIZE_AND_EXTEND, and it MUST be called from the allocation site
|
|
|
|
+ * regardless of being allocated in the kernel or a module.
|
|
|
|
+ */
|
|
|
|
+#define RH_KABI_SET_SIZE(_name, _struct) ({ \
|
|
|
|
+ _name._struct##_size_rh = sizeof(struct _struct##_rh); \
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * RH_KABI_INIT_SIZE calculates and sets the size of the extended struct and
|
|
|
|
+ * stores it in the size_rh field for structs that are statically allocated.
|
|
|
|
+ * This macro MUST be called when expanding a base struct with
|
|
|
|
+ * RH_KABI_SIZE_AND_EXTEND, and it MUST be called from the declaration site
|
|
|
|
+ * regardless of being allocated in the kernel or a module.
|
|
|
|
+ */
|
|
|
|
+#define RH_KABI_INIT_SIZE(_struct) \
|
|
|
|
+ ._struct##_size_rh = sizeof(struct _struct##_rh),
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * RH_KABI_CHECK_EXT verifies allocated memory exists. This MUST be called to
|
|
|
|
+ * verify that memory in the _rh struct is valid, and can be called
|
|
|
|
+ * regardless if RH_KABI_SIZE_AND_EXTEND or RH_KABI_SIZE_AND_EXTEND_PTR is
|
|
|
|
+ * used.
|
|
|
|
+ */
|
|
|
|
+#define RH_KABI_CHECK_EXT(_ptr, _struct, _field) ({ \
|
|
|
|
+ size_t __off = offsetof(struct _struct##_rh, _field); \
|
|
|
|
+ _ptr->_struct##_size_rh > __off ? true : false; \
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
#endif /* _LINUX_RH_KABI_H */
|
|
|
|
--
|
2020-04-27 02:15:20 +00:00
|
|
|
2.26.2
|
2020-04-23 20:47:21 +00:00
|
|
|
|