diff mbox series

[v2,1/2] Add support for arm64 to carry ima measurement log in kexec_file_load

Message ID 20191007185943.1828-2-prsriva@linux.microsoft.com (mailing list archive)
State New, archived
Headers show
Series Add support to carry ima measurement log in kexec_file_load | expand

Commit Message

Prakhar Srivastava Oct. 7, 2019, 6:59 p.m. UTC
During kexec_file_load, carrying forward the ima measurement log allows
a verifying party to get the entire runtime event log since the last
full reboot since that is when PCRs were last reset.

Signed-off-by: Prakhar Srivastava <prsriva@linux.microsoft.com>
---
 arch/Kconfig                           |   6 +-
 arch/arm64/include/asm/ima.h           |  24 +++
 arch/arm64/include/asm/kexec.h         |   5 +
 arch/arm64/kernel/Makefile             |   3 +-
 arch/arm64/kernel/ima_kexec.c          |  78 ++++++++++
 arch/arm64/kernel/machine_kexec_file.c |   6 +
 drivers/of/Kconfig                     |   6 +
 drivers/of/Makefile                    |   1 +
 drivers/of/of_ima.c                    | 204 +++++++++++++++++++++++++
 include/linux/of.h                     |  31 ++++
 10 files changed, 362 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/ima.h
 create mode 100644 arch/arm64/kernel/ima_kexec.c
 create mode 100644 drivers/of/of_ima.c

Comments

Sasha Levin Oct. 8, 2019, 9:22 p.m. UTC | #1
On Mon, Oct 07, 2019 at 11:59:42AM -0700, Prakhar Srivastava wrote:
>During kexec_file_load, carrying forward the ima measurement log allows
>a verifying party to get the entire runtime event log since the last
>full reboot since that is when PCRs were last reset.
>
>Signed-off-by: Prakhar Srivastava <prsriva@linux.microsoft.com>
>---
> arch/Kconfig                           |   6 +-
> arch/arm64/include/asm/ima.h           |  24 +++
> arch/arm64/include/asm/kexec.h         |   5 +
> arch/arm64/kernel/Makefile             |   3 +-
> arch/arm64/kernel/ima_kexec.c          |  78 ++++++++++
> arch/arm64/kernel/machine_kexec_file.c |   6 +
> drivers/of/Kconfig                     |   6 +
> drivers/of/Makefile                    |   1 +
> drivers/of/of_ima.c                    | 204 +++++++++++++++++++++++++
> include/linux/of.h                     |  31 ++++
> 10 files changed, 362 insertions(+), 2 deletions(-)
> create mode 100644 arch/arm64/include/asm/ima.h
> create mode 100644 arch/arm64/kernel/ima_kexec.c
> create mode 100644 drivers/of/of_ima.c
>
>diff --git a/arch/Kconfig b/arch/Kconfig
>index a7b57dd42c26..d53e1596c5b1 100644
>--- a/arch/Kconfig
>+++ b/arch/Kconfig
>@@ -19,7 +19,11 @@ config KEXEC_CORE
> 	bool
>
> config HAVE_IMA_KEXEC
>-	bool
>+	bool "Carry over IMA measurement log during kexec_file_load() syscall"
>+	depends on KEXEC_FILE
>+	help
>+	  Select this option to carry over IMA measurement log during
>+	  kexec_file_load.

This change looks very wrong: HAVE_* config symbols are used to indicate
the availability of certain arch specific capability, rather than act as
a config option. How does this work with CONFIG_IMA_KEXEC ?

Also, please, at the very least verify that basic functionality works on
the architectures we have access to. Trying it on x86:

$ make allmodconfig
scripts/kconfig/conf  --allmodconfig Kconfig
#
# No change to .config
#
$ make
  CALL    scripts/checksyscalls.sh
  CALL    scripts/atomic/check-atomics.sh
  DESCEND  objtool
  CC      security/integrity/ima/ima_fs.o
In file included from security/integrity/ima/ima_fs.c:26:
security/integrity/ima/ima.h:28:10: fatal error: asm/ima.h: No such file or directory
 #include <asm/ima.h>
          ^~~~~~~~~~~
compilation terminated.
make[3]: *** [scripts/Makefile.build:266: security/integrity/ima/ima_fs.o] Error 1
make[2]: *** [scripts/Makefile.build:509: security/integrity/ima] Error 2
make[1]: *** [scripts/Makefile.build:509: security/integrity] Error 2
make: *** [Makefile:1649: security] Error 2

--
Thanks,
Sasha
Prakhar Srivastava Oct. 9, 2019, 8:49 p.m. UTC | #2
On 10/8/19 2:22 PM, Sasha Levin wrote:
> On Mon, Oct 07, 2019 at 11:59:42AM -0700, Prakhar Srivastava wrote:
>> During kexec_file_load, carrying forward the ima measurement log allows
>> a verifying party to get the entire runtime event log since the last
>> full reboot since that is when PCRs were last reset.
>>
>> Signed-off-by: Prakhar Srivastava <prsriva@linux.microsoft.com>
>> ---
>> arch/Kconfig                           |   6 +-
>> arch/arm64/include/asm/ima.h           |  24 +++
>> arch/arm64/include/asm/kexec.h         |   5 +
>> arch/arm64/kernel/Makefile             |   3 +-
>> arch/arm64/kernel/ima_kexec.c          |  78 ++++++++++
>> arch/arm64/kernel/machine_kexec_file.c |   6 +
>> drivers/of/Kconfig                     |   6 +
>> drivers/of/Makefile                    |   1 +
>> drivers/of/of_ima.c                    | 204 +++++++++++++++++++++++++
>> include/linux/of.h                     |  31 ++++
>> 10 files changed, 362 insertions(+), 2 deletions(-)
>> create mode 100644 arch/arm64/include/asm/ima.h
>> create mode 100644 arch/arm64/kernel/ima_kexec.c
>> create mode 100644 drivers/of/of_ima.c
>>
>> diff --git a/arch/Kconfig b/arch/Kconfig
>> index a7b57dd42c26..d53e1596c5b1 100644
>> --- a/arch/Kconfig
>> +++ b/arch/Kconfig
>> @@ -19,7 +19,11 @@ config KEXEC_CORE
>>     bool
>>
>> config HAVE_IMA_KEXEC
>> -    bool
>> +    bool "Carry over IMA measurement log during kexec_file_load() 
>> syscall"
>> +    depends on KEXEC_FILE
>> +    help
>> +      Select this option to carry over IMA measurement log during
>> +      kexec_file_load.
> 
> This change looks very wrong: HAVE_* config symbols are used to indicate
> the availability of certain arch specific capability, rather than act as
> a config option. How does this work with CONFIG_IMA_KEXEC ?
> 
Thanks for pointing this out. My attempt was to move this out of arch 
dependent config. I will fix the CONFIG.

> Also, please, at the very least verify that basic functionality works on
> the architectures we have access to. Trying it on x86:
> 

Let me fix the build issues for other archs.
I have tested these changes for arm64.

> $ make allmodconfig
> scripts/kconfig/conf  --allmodconfig Kconfig
> #
> # No change to .config
> #
> $ make
>   CALL    scripts/checksyscalls.sh
>   CALL    scripts/atomic/check-atomics.sh
>   DESCEND  objtool
>   CC      security/integrity/ima/ima_fs.o
> In file included from security/integrity/ima/ima_fs.c:26:
> security/integrity/ima/ima.h:28:10: fatal error: asm/ima.h: No such file 
> or directory
> #include <asm/ima.h>
>           ^~~~~~~~~~~
> compilation terminated.
> make[3]: *** [scripts/Makefile.build:266: 
> security/integrity/ima/ima_fs.o] Error 1
> make[2]: *** [scripts/Makefile.build:509: security/integrity/ima] Error 2
> make[1]: *** [scripts/Makefile.build:509: security/integrity] Error 2
> make: *** [Makefile:1649: security] Error 2
> 
> -- 
> Thanks,
> Sasha
diff mbox series

Patch

diff --git a/arch/Kconfig b/arch/Kconfig
index a7b57dd42c26..d53e1596c5b1 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -19,7 +19,11 @@  config KEXEC_CORE
 	bool
 
 config HAVE_IMA_KEXEC
-	bool
+	bool "Carry over IMA measurement log during kexec_file_load() syscall"
+	depends on KEXEC_FILE
+	help
+	  Select this option to carry over IMA measurement log during
+	  kexec_file_load.
 
 config HOTPLUG_SMT
 	bool
diff --git a/arch/arm64/include/asm/ima.h b/arch/arm64/include/asm/ima.h
new file mode 100644
index 000000000000..287dbcefd15e
--- /dev/null
+++ b/arch/arm64/include/asm/ima.h
@@ -0,0 +1,24 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM64_IMA_H
+#define _ASM_ARM64_IMA_H
+
+struct kimage;
+
+int ima_get_kexec_buffer(void **addr, size_t *size);
+int ima_free_kexec_buffer(void);
+void remove_ima_buffer(void *fdt, int chosen_node);
+
+#ifdef CONFIG_IMA_KEXEC
+int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
+			      size_t size);
+
+int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node);
+#else
+static inline int setup_ima_buffer(const struct kimage *image, void *fdt,
+				   int chosen_node)
+{
+	remove_ima_buffer(fdt, chosen_node);
+	return 0;
+}
+#endif /* CONFIG_IMA_KEXEC */
+#endif /* _ASM_ARM64_IMA_H */
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 12a561a54128..e8d2412066e7 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -96,6 +96,11 @@  static inline void crash_post_resume(void) {}
 struct kimage_arch {
 	void *dtb;
 	unsigned long dtb_mem;
+
+#ifdef CONFIG_IMA_KEXEC
+	phys_addr_t ima_buffer_addr;
+	size_t ima_buffer_size;
+#endif
 };
 
 extern const struct kexec_file_ops kexec_image_ops;
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 478491f07b4f..580238f2e9a7 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -55,7 +55,8 @@  obj-$(CONFIG_RANDOMIZE_BASE)		+= kaslr.o
 obj-$(CONFIG_HIBERNATION)		+= hibernate.o hibernate-asm.o
 obj-$(CONFIG_KEXEC_CORE)		+= machine_kexec.o relocate_kernel.o	\
 					   cpu-reset.o
-obj-$(CONFIG_KEXEC_FILE)		+= machine_kexec_file.o kexec_image.o
+obj-$(CONFIG_KEXEC_FILE)		+= machine_kexec_file.o kexec_image.o	\
+					   ima_kexec.o
 obj-$(CONFIG_ARM64_RELOC_TEST)		+= arm64-reloc-test.o
 arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o
 obj-$(CONFIG_CRASH_DUMP)		+= crash_dump.o
diff --git a/arch/arm64/kernel/ima_kexec.c b/arch/arm64/kernel/ima_kexec.c
new file mode 100644
index 000000000000..c2450aaa42c8
--- /dev/null
+++ b/arch/arm64/kernel/ima_kexec.c
@@ -0,0 +1,78 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ *
+ * Authors:
+ * Prakhar Srivastava <prsriva@linux.microsoft.com>
+ */
+
+#include <linux/kexec.h>
+#include <linux/of.h>
+
+/**
+ * remove_ima_buffer - remove the IMA buffer property and reservation from @fdt
+ * The IMA measurement buffer once read needs to be freed.
+ */
+void remove_ima_buffer(void *fdt, int chosen_node)
+{
+	fdt_remove_ima_buffer(fdt, chosen_node);
+}
+
+/**
+ * ima_get_kexec_buffer - get IMA buffer from the previous kernel
+ * @addr:	On successful return, set to point to the buffer contents.
+ * @size:	On successful return, set to the buffer size.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int ima_get_kexec_buffer(void **addr, size_t *size)
+{
+	return of_get_ima_buffer(addr, size);
+}
+
+/**
+ * ima_free_kexec_buffer - free memory used by the IMA buffer
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int ima_free_kexec_buffer(void)
+{
+	return of_remove_ima_buffer();
+}
+
+#ifdef CONFIG_IMA_KEXEC
+/**
+ * arch_ima_add_kexec_buffer - do arch-specific steps to add the IMA
+ *	measurement log.
+ * @image: - pointer to the kimage, to store the address and size of the
+ *	IMA measurement log.
+ * @load_addr: - the address where the IMA measurement log is stored.
+ * @size - size of the IMA measurement log.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
+			      size_t size)
+{
+	image->arch.ima_buffer_addr = load_addr;
+	image->arch.ima_buffer_size = size;
+	return 0;
+}
+
+/**
+ * setup_ima_buffer - update the fdt to contain the ima mesasurement log
+ * @image: - pointer to the kimage, containing the address and size of
+ *	     the IMA measurement log.
+ * @fdt: - pointer to the fdt.
+ * @chosen_node: - node under which property is to be defined.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node)
+{
+	return fdt_setup_ima_buffer(image->arch.ima_buffer_addr,
+				    image->arch.ima_buffer_size,
+				    fdt, chosen_node);
+
+}
+#endif /* CONFIG_IMA_KEXEC */
diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c
index 58871333737a..86d57198d739 100644
--- a/arch/arm64/kernel/machine_kexec_file.c
+++ b/arch/arm64/kernel/machine_kexec_file.c
@@ -21,6 +21,7 @@ 
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 #include <asm/byteorder.h>
+#include <asm/ima.h>
 
 /* relevant device tree properties */
 #define FDT_PROP_INITRD_START	"linux,initrd-start"
@@ -85,6 +86,11 @@  static int setup_dtb(struct kimage *image,
 			goto out;
 	}
 
+	/* add ima measuremnet log buffer */
+	ret = setup_ima_buffer(image, dtb, off);
+	if (ret < 0)
+		goto out;
+
 	/* add kaslr-seed */
 	ret = fdt_delprop(dtb, off, FDT_PROP_KASLR_SEED);
 	if  (ret == -FDT_ERR_NOTFOUND)
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 37c2ccbefecd..167c6ecb64aa 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -103,4 +103,10 @@  config OF_OVERLAY
 config OF_NUMA
 	bool
 
+config OF_IMA
+	def_bool y
+	help
+	  IMA related wrapper functions to add/remove ima measurement logs during
+	  kexec_file_load call.
+
 endif # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 663a4af0cccd..b4caf083df4e 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -14,5 +14,6 @@  obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
 obj-$(CONFIG_OF_RESOLVE)  += resolver.o
 obj-$(CONFIG_OF_OVERLAY) += overlay.o
 obj-$(CONFIG_OF_NUMA) += of_numa.o
+obj-$(CONFIG_OF_IMA) += of_ima.o
 
 obj-$(CONFIG_OF_UNITTEST) += unittest-data/
diff --git a/drivers/of/of_ima.c b/drivers/of/of_ima.c
new file mode 100644
index 000000000000..cfc3cb4522b0
--- /dev/null
+++ b/drivers/of/of_ima.c
@@ -0,0 +1,204 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Microsoft Corporation.
+ */
+
+#include <linux/slab.h>
+#include <linux/kexec.h>
+#include <linux/of.h>
+#include <linux/memblock.h>
+#include <linux/libfdt.h>
+
+/**
+ * delete_fdt_mem_rsv - delete memory reservation with given address and size
+ * @fdt - pointer to the fdt.
+ * @start - start address of the memory.
+ * @size - number of cells to be deletd.
+ *
+ * Return: 0 on success, or negative errno on error.
+ */
+int fdt_delete_mem_rsv(void *fdt, unsigned long start, unsigned long size)
+{
+	int i, ret, num_rsvs = fdt_num_mem_rsv(fdt);
+
+	for (i = 0; i < num_rsvs; i++) {
+		uint64_t rsv_start, rsv_size;
+
+		ret = fdt_get_mem_rsv(fdt, i, &rsv_start, &rsv_size);
+		if (ret < 0) {
+			pr_err("Malformed device tree\n");
+			return ret;
+		}
+
+		if (rsv_start == start && rsv_size == size) {
+			ret = fdt_del_mem_rsv(fdt, i);
+			if (ret < 0) {
+				pr_err("Error deleting device tree reservation\n");
+				return ret;
+			}
+
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+/**
+ * of_get_ima_buffer_properties - get the properties for ima buffer
+ * @ima_buf_start - start of the ima buffer
+ * @ima_buf_end - end of the ima buffer
+ *	If any one of the properties is not found. The device tree
+ *	is malformed or something went wrong.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int of_get_ima_buffer_properties(void **ima_buf_start, void **ima_buf_end)
+{
+	struct property *pproperty;
+
+	pproperty = of_find_property(of_chosen, "linux,ima-kexec-buffer",
+				    NULL);
+	*ima_buf_start = pproperty ? pproperty->value : NULL;
+
+	pproperty = of_find_property(of_chosen, "linux,ima-kexec-buffer-end",
+				    NULL);
+	*ima_buf_end = pproperty ? pproperty->value : NULL;
+
+	if (!*ima_buf_start || !*ima_buf_end)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * of_remove_ima_buffer - free memory used by the IMA buffer
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int of_remove_ima_buffer(void)
+{
+	int ret;
+	void *ima_buf_start, *ima_buf_end;
+	uint64_t buf_start, buf_end;
+
+	ret = of_get_ima_buffer_properties(&ima_buf_start, &ima_buf_end);
+	if (ret < 0)
+		return ret;
+
+	buf_start = fdt64_to_cpu(*((const fdt64_t *) ima_buf_start));
+	buf_end = fdt64_to_cpu(*((const fdt64_t *) ima_buf_end));
+
+	ret = of_remove_property(of_chosen, ima_buf_start);
+	if (ret < 0)
+		return ret;
+
+	ret = of_remove_property(of_chosen, ima_buf_end);
+	if (ret < 0)
+		return ret;
+
+	return memblock_free(buf_start, buf_end - buf_start);
+}
+
+/**
+ * of_get_ima_buffer - get IMA buffer from the previous kernel
+ * @addr:	On successful return, set to point to the buffer contents.
+ * @size:	On successful return, set to the buffer size.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int of_get_ima_buffer(void **addr, size_t *size)
+{
+	int ret;
+	void *ima_buf_start, *ima_buf_end;
+	uint64_t buf_start, buf_end;
+
+	ret = of_get_ima_buffer_properties(&ima_buf_start, &ima_buf_end);
+	if (ret < 0)
+		return ret;
+
+	buf_start = fdt64_to_cpu(*((const fdt64_t *) ima_buf_start));
+	buf_end = fdt64_to_cpu(*((const fdt64_t *) ima_buf_end));
+
+	*addr = __va(buf_start);
+	*size = buf_end - buf_start;
+
+	return 0;
+}
+
+/**
+ * fdt_remove_ima_buffer - remove the IMA buffer property and reservation
+ * @fdt - pointer the fdt.
+ * @chosen_node - node under which property can be found.
+ *
+ * The IMA measurement buffer is either read by now and freeed or a kexec call
+ * needs to replace the ima measurement buffer, clear the property and memory
+ * reservation.
+ */
+void fdt_remove_ima_buffer(void *fdt, int chosen_node)
+{
+	int ret, len;
+	const void *prop;
+	uint64_t tmp_start, tmp_end;
+
+	prop = fdt_getprop(fdt, chosen_node, "linux,ima-kexec-buffer", &len);
+	if (prop) {
+		tmp_start = fdt64_to_cpu(*((const fdt64_t *) prop));
+
+		prop = fdt_getprop(fdt, chosen_node,
+				   "linux,ima-kexec-buffer-end", &len);
+		if (!prop)
+			return;
+
+		tmp_end = fdt64_to_cpu(*((const fdt64_t *) prop));
+
+		ret = fdt_delete_mem_rsv(fdt, tmp_start, tmp_end - tmp_start);
+
+		if (ret == 0)
+			pr_debug("Removed old IMA buffer reservation.\n");
+		else if (ret != -ENOENT)
+			return;
+
+		fdt_delprop(fdt, chosen_node, "linux,ima-kexec-buffer");
+		fdt_delprop(fdt, chosen_node, "linux,ima-kexec-buffer-end");
+	}
+}
+
+/**
+ * fdt_setup_ima_buffer - update the fdt to contain the ima mesasurement log
+ * @image: - pointer to the kimage, containing the address and size of
+ *	     the IMA measurement log.
+ * @fdt: - pointer to the fdt.
+ * @chosen_node: - node under which property is to be defined.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int fdt_setup_ima_buffer(const phys_addr_t ima_buffer_addr,
+	const size_t ima_buffer_size,
+	void *fdt, int chosen_node)
+{
+	int ret;
+
+	fdt_remove_ima_buffer(fdt, chosen_node);
+
+	if (!ima_buffer_addr)
+		return 0;
+
+	ret = fdt_setprop_u64(fdt, chosen_node, "linux,ima-kexec-buffer",
+			      ima_buffer_addr);
+	if (ret < 0)
+		return ret;
+
+	ret = fdt_setprop_u64(fdt, chosen_node, "linux,ima-kexec-buffer-end",
+			      ima_buffer_addr +
+			      ima_buffer_size);
+	if (ret < 0)
+		return ret;
+
+	ret = fdt_add_mem_rsv(fdt, ima_buffer_addr,
+			      ima_buffer_size);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
diff --git a/include/linux/of.h b/include/linux/of.h
index 844f89e1b039..7831c2972178 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -1477,4 +1477,35 @@  static inline int of_overlay_notifier_unregister(struct notifier_block *nb)
 
 #endif
 
+#ifdef CONFIG_OF_IMA
+int of_remove_ima_buffer(void);
+int of_get_ima_buffer(void **addr, size_t *size);
+void fdt_remove_ima_buffer(void *fdt, int chosen_node);
+int fdt_setup_ima_buffer(const phys_addr_t ima_buffer_addr,
+	const size_t ima_buffer_size,
+	void *fdt, int chosen_node);
+#else
+static inline int of_remove_ima_buffer(void)
+{
+	return -ENOTSUPP;
+};
+
+static inline int of_get_ima_buffer(void **addr, size_t *size)
+{
+	return -ENOTSUPP;
+};
+
+static inline void fdt_remove_ima_buffer(void *fdt, int chosen_node)
+{
+	return -ENOTSUPP;
+};
+
+static inline int fdt_setup_ima_buffer(const phys_addr_t ima_buffer_addr,
+	const size_t ima_buffer_size, void *fdt, int chosen_node)
+{
+	return -ENOTSUPP;
+};
+
+#endif
+
 #endif /* _LINUX_OF_H */