A flaw was found in the Linux kernels sysfs layer data reporting. A local users with the ability to read files under the /sysfs mount point can create a possible out of bounds write due to a heap buffer overflow. By grooming memory in this 'out of bounds' location, a local attacker could use this write to manipulate the kernel into executing attacker provided code crashing the system or creating possible privilege escalation for attacker controlled userspace code. References: http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2022-20166 https://source.android.com/security/bulletin/pixel/2022-06-01 Fix: https://github.com/torvalds/linux/commit/aa838896d87af561a33ecefea1caa4c15a68bc47
(In reply to Wade Mealing from comment #0) > A flaw was found in the Linux kernels sysfs layer data reporting. A local > users with the ability to read files under the /sysfs mount point can create > a possible out of bounds write due to a heap buffer overflow. By grooming > memory in this 'out of bounds' location, a local attacker could use this > write to manipulate the kernel into executing attacker provided code > crashing the system or creating possible privilege escalation for attacker > controlled userspace code. I find this a little puzzling. I would really like to see a reproducer of this hypothetical case or at least an explanation of how an out of bounds write to a buffer can happen within a file system whose files are all created by in kernel sub-systems and use the seq file interface for reading (which uses a PAGE_SIZE buffer everywhere). I thought we fixed the possible seq file over size buffer allocation ages ago ... if it is possible for kvmalloc() to return success upon failing to get the requested memory in any case then we probably have much bigger problems. Perhaps the problem is the passed in read buffer can be too small and its size isn't checked ... but, based on the suggested fix that doesn't appear to be the problem that's fixed ... Ian
I agree - this is a fairly wide change with no real explanation of why it's needed. note that sysfs_emit doesn't exist in RHEL7, and was only somewhat recently added to RHEL8. The upstream commit was: commit 2efc459d06f1630001e3984854848a5647086232 Author: Joe Perches <joe> Date: Wed Sep 16 13:40:38 2020 -0700 sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output Output defects can exist in sysfs content using sprintf and snprintf. sprintf does not know the PAGE_SIZE maximum of the temporary buffer used for outputting sysfs content and it's possible to overrun the PAGE_SIZE buffer length. Add a generic sysfs_emit function that knows that the size of the temporary buffer and ensures that no overrun is done. Add a generic sysfs_emit_at function that can be used in multiple call situations that also ensures that no overrun is done. Validate the output buffer argument to be page aligned. Validate the offset len argument to be within the PAGE_SIZE buf. Signed-off-by: Joe Perches <joe> Link: https://lore.kernel.org/r/884235202216d464d61ee975f7465332c86f76b2.1600285923.git.joe@perches.com Signed-off-by: Greg Kroah-Hartman <gregkh> which offerrs some clues. Further, although all the child bugs were assigned to filesystem, this really is not a filesystem bug - every change in this commit is under drivers/ so this should probably be a core kernel bug. That said, if failing to use sysfs_emit is a security problem, is it really only drivers/ that is affected?
A couple other thoughts. This is similar to the prior CVE-2021-27365, which only addressed the problem in iscsi. For that CVE, the RHEL7 workaround for lack of sysfs_emit was noted: commit af581fe518f4d6a6f28064f932d9374e0444d706 Author: Chris Leech <cleech> Date: Thu Mar 4 09:57:23 2021 -0800 scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE Bugzilla: http://bugzilla.redhat.com/1930849 CVE: CVE-2021-27363 Conflicts: The sysfs_emit helper doesn't exist for backports, but other than a sanity check on buf it's just a call to scnprintf with a PAGE_SIZE limit. converted with s/sysfs_emit(buf,/scnprintf(buf, PAGE_SIZE,/
(In reply to Ian Kent from comment #7) > > Perhaps the problem is the passed in read buffer can be too small and > its size isn't checked ... but, based on the suggested fix that doesn't > appear to be the problem that's fixed ... Actually, my mistake, the fix does introduce a PAGE_SIZE length check but we would be very hard pressed to find anything in kernel sub-systems using sysfs whose ->show() routine generates output greater than 4k.
(In reply to Ian Kent from comment #10) > Actually, my mistake, the fix does introduce a PAGE_SIZE length check but > we would be very hard pressed to find anything in kernel sub-systems using > sysfs whose ->show() routine generates output greater than 4k. Yeah this seems like the trick here; it's certainly good defensive programming to always have the check. But in RHEL kernels, 1) can anything actually exceed page size today? and 2) do other subsystems using sysfs have similar problems which remain unaddressed by the patch? This seems like a CVE generated for defensive programming goals, not an actual demonstrated flaw.
(In reply to Eric Sandeen from comment #11) > (In reply to Ian Kent from comment #10) > > > Actually, my mistake, the fix does introduce a PAGE_SIZE length check but > > we would be very hard pressed to find anything in kernel sub-systems using > > sysfs whose ->show() routine generates output greater than 4k. > > Yeah this seems like the trick here; it's certainly good defensive > programming to always have the check. > > But in RHEL kernels, > > 1) can anything actually exceed page size today? and Probably, but you would think kernel developers would know what they are outputting and its length since they should know that the seq file system uses a page size buffer for this. > 2) do other subsystems using sysfs have similar problems which remain > unaddressed by the patch? Probably, consider the mount table output, it has paths in some fields for which you don't know the length. I'm pretty sure that uses the seq file interface too. > > This seems like a CVE generated for defensive programming goals, not an > actual demonstrated flaw. The question I still have is how does an attacker arrange for the buffer to overflow. Maybe there are cases where system setup would cause this, IIRC we saw something like that with mount table size ... I'll go through comment #6 and see if I can find some of this info. Ian
(In reply to Ian Kent from comment #12) > (In reply to Eric Sandeen from comment #11) > > (In reply to Ian Kent from comment #10) > > > > > Actually, my mistake, the fix does introduce a PAGE_SIZE length check but > > > we would be very hard pressed to find anything in kernel sub-systems using > > > sysfs whose ->show() routine generates output greater than 4k. > > > > Yeah this seems like the trick here; it's certainly good defensive > > programming to always have the check. > > > > But in RHEL kernels, > > > > 1) can anything actually exceed page size today? and > > Probably, but you would think kernel developers would know what they are > outputting and its length since they should know that the seq file system > uses a page size buffer for this. > > > 2) do other subsystems using sysfs have similar problems which remain > > unaddressed by the patch? > > Probably, consider the mount table output, it has paths in some fields > for which you don't know the length. I'm pretty sure that uses the seq > file interface too. Mmm ... sysfs only half heatedly uses the seq file interface and only for sysfs attributes that aren't binary. The buffer allocated is PAGE_SIZE (seq file norm) so limiting writes to the buffer to that amount isn't a bad idea. Still would be nice to have an example attack scenario as these are created by kernel sub-systems and to load a bogus module requires admin privilege. Ian