summaryrefslogtreecommitdiffstats
path: root/0001-redhat-rh_kabi-Add-macros-to-size-and-extend-structs.patch
diff options
context:
space:
mode:
Diffstat (limited to '0001-redhat-rh_kabi-Add-macros-to-size-and-extend-structs.patch')
-rw-r--r--0001-redhat-rh_kabi-Add-macros-to-size-and-extend-structs.patch201
1 files changed, 201 insertions, 0 deletions
diff --git a/0001-redhat-rh_kabi-Add-macros-to-size-and-extend-structs.patch b/0001-redhat-rh_kabi-Add-macros-to-size-and-extend-structs.patch
new file mode 100644
index 000000000..4561538bf
--- /dev/null
+++ b/0001-redhat-rh_kabi-Add-macros-to-size-and-extend-structs.patch
@@ -0,0 +1,201 @@
+From cedb6dec3b60ec7c9bd8b2c87c4883db9ac53ed8 Mon Sep 17 00:00:00 2001
+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 @@
+
+ #define RH_KABI_EXCLUDE(_elem) _RH_KABI_EXCLUDE(_elem);
+
++/*
++ * 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 */
+--
+2.26.0
+