Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fortify error with a stable/released UTS_RELEASE #1496

Closed
nathanchance opened this issue Nov 1, 2021 · 3 comments
Closed

Fortify error with a stable/released UTS_RELEASE #1496

nathanchance opened this issue Nov 1, 2021 · 3 comments
Labels
[BUG] linux A bug that should be fixed in the mainline kernel. [BUG] linux-stable A bug that is present in linux-stable and not mainline. [FIXED][LINUX] 5.16 This bug was fixed in Linux 5.16

Comments

@nathanchance
Copy link
Member

Initially reported with CI: https://github.com/ClangBuiltLinux/continuous-integration2/runs/4068475993?check_suite_focus=true

$ make -skj"$(nproc)" LLVM=1 distclean defconfig

$ scripts/config -e CONFIGFS_FS -e FORTIFY_SOURCE -e NVME_TARGET

$ make -skj"$(nproc)" LLVM=1 olddefconfig drivers/nvme/target/discovery.o
In file included from drivers/nvme/target/discovery.c:7:
In file included from ./include/linux/slab.h:15:
In file included from ./include/linux/gfp.h:6:
In file included from ./include/linux/mmzone.h:8:
In file included from ./include/linux/spinlock.h:55:
In file included from ./include/linux/preempt.h:78:
In file included from ./arch/x86/include/asm/preempt.h:7:
In file included from ./include/linux/thread_info.h:60:
In file included from ./arch/x86/include/asm/thread_info.h:53:
In file included from ./arch/x86/include/asm/cpufeature.h:5:
In file included from ./arch/x86/include/asm/processor.h:22:
In file included from ./arch/x86/include/asm/msr.h:11:
In file included from ./arch/x86/include/asm/cpumask.h:5:
In file included from ./include/linux/cpumask.h:12:
In file included from ./include/linux/bitmap.h:10:
In file included from ./include/linux/string.h:262:
./include/linux/fortify-string.h:187:4: error: call to __read_overflow2 declared with 'error' attribute: detected read beyond size of object passed as 2nd parameter
                        __read_overflow2();
                        ^
1 error generated.

This only occurs when UTS_RELEASE is a standard release version (i.e. 5.15.0 versus 5.15.0-rc7). This can be hacked up with something like:

$ sed -i 's/KERNELRELEASE =.*/KERNELRELEASE = 5.15.0/g' Makefile`

$ git diff HEAD
diff --git a/Makefile b/Makefile
index ed6e7ec60eff..a6baf6fec919 100644
--- a/Makefile
+++ b/Makefile
@@ -357,7 +357,7 @@ else # !mixed-build
 include $(srctree)/scripts/Kbuild.include

 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
-KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
+KERNELRELEASE = 5.15.0
 KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
 export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION

This appears to be an issue with GCC in certain configuration:

https://lore.kernel.org/r/20211101002346.GA304515@roeck-us.net/
https://lore.kernel.org/r/CAMuHMdX365qmWiii=gQLADpW49EMkdDrVJDPWNBpAZuZM0WQFQ@mail.gmail.com/

Standalone reproducer

#define UTS_RELEASE_1 "5.15.0"
#define UTS_RELEASE_2 "5.15.0-rc1"

typedef unsigned long __kernel_size_t;
typedef long ssize_t;
typedef unsigned long size_t;

#define __cold                   __attribute__((__cold__))
#define __compiletime_error(msg) __attribute__((__error__(msg)))
#define __noreturn               __attribute__((__noreturn__))

void fortify_panic(const char *name) __noreturn __cold;
void __read_overflow(void) __compiletime_error("detected read beyond size of object passed as 1st parameter");
void __read_overflow2(void) __compiletime_error("detected read beyond size of object passed as 2nd parameter");
void __read_overflow3(void) __compiletime_error("detected read beyond size of object passed as 3rd parameter");
void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");

#define __FORTIFY_INLINE extern inline __attribute__((__always_inline__)) __attribute__((gnu_inline))

extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __asm__("strnlen");
__FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen)
{
	size_t p_size = __builtin_object_size(p, 1);
	__kernel_size_t ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);

	if (p_size <= ret && maxlen != ret)
		fortify_panic(__func__);
	return ret;
}

__FORTIFY_INLINE __kernel_size_t strlen(const char *p)
{
	__kernel_size_t ret;
	size_t p_size = __builtin_object_size(p, 1);

	/* Work around gcc excess stack consumption issue */
	if (p_size == (size_t)-1 ||
		(__builtin_constant_p(p[p_size - 1]) && p[p_size - 1] == '\0'))
		return __builtin_strlen(p);
	ret = strnlen(p, p_size);
	if (p_size <= ret)
		fortify_panic(__func__);
	return ret;
}

__FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size)
{
	size_t p_size = __builtin_object_size(p, 0);
	size_t q_size = __builtin_object_size(q, 0);

	if (__builtin_constant_p(size)) {
		if (p_size < size)
			__write_overflow();
		if (q_size < size)
			__read_overflow2();
	}
	if (p_size < size || q_size < size)
		fortify_panic(__func__);
	return __builtin_memcpy(p, q, size);
}

__FORTIFY_INLINE void *memset(void *p, int c, __kernel_size_t size)
{
	size_t p_size = __builtin_object_size(p, 0);

	if (__builtin_constant_p(size) && p_size < size)
		__write_overflow();
	if (p_size < size)
		fortify_panic(__func__);
	return __builtin_memset(p, c, size);
}

static inline void memcpy_and_pad(void *dest, size_t dest_len,
				  const void *src, size_t count, int pad)
{
	if (dest_len > count) {
		memcpy(dest, src, count);
		memset(dest + count, pad,  dest_len - count);
	} else
		memcpy(dest, src, dest_len);
}

char fr[8];
void foo(void)
{
    memcpy_and_pad(fr, sizeof(fr), UTS_RELEASE_1, strlen(UTS_RELEASE_1), ' ');
}

void bar(void)
{
    memcpy_and_pad(fr, sizeof(fr), UTS_RELEASE_2, strlen(UTS_RELEASE_2), ' ');
}

Godbolt: https://godbolt.org/z/sMrTzb4WY

This appears in 5.15.0 but not 5.14.0, only because 5.14.0 does not have the commit that add support for. __attribute__((__error__)), which is required to reproduce this. I don't know if @kees's series to fix CONFIG_FORTIFY_SOURCE with clang resolves this.

@nathanchance nathanchance added the [BUG] Untriaged Something isn't working label Nov 1, 2021
@kees
Copy link

kees commented Nov 1, 2021

@nathanchance
Copy link
Member Author

I have requested a52f8a5 be applied to 4.19+ to resolve this: https://lore.kernel.org/r/YZKpVkYpYfYfHD50@archlinux-ax161/

@nathanchance
Copy link
Member Author

https://git.kernel.org/linus/a52f8a59aef46b59753e583bf4b28fccb069ce64 has been applied to stable kernels 4.19+ so this is resolved for now. If it comes back after @kees's fortify series, I will reopen.

@nathanchance nathanchance added [BUG] linux A bug that should be fixed in the mainline kernel. [BUG] linux-stable A bug that is present in linux-stable and not mainline. [FIXED][LINUX] 5.16 This bug was fixed in Linux 5.16 and removed [BUG] Untriaged Something isn't working labels Nov 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[BUG] linux A bug that should be fixed in the mainline kernel. [BUG] linux-stable A bug that is present in linux-stable and not mainline. [FIXED][LINUX] 5.16 This bug was fixed in Linux 5.16
Projects
None yet
Development

No branches or pull requests

2 participants