Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.
RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.

Bug 2124867

Summary: oscap complains with "E: oscap: Failed to check available memory", which is confusing for the user
Product: Red Hat Enterprise Linux 8 Reporter: Renaud Métrich <rmetrich>
Component: openscapAssignee: Jan Černý <jcerny>
Status: CLOSED DUPLICATE QA Contact: BaseOS QE Security Team <qe-baseos-security>
Severity: medium Docs Contact:
Priority: medium    
Version: 8.6CC: amepatil, ekolesni, jcerny, matyc, mhaicman, mmarhefk, tmihinto
Target Milestone: rcFlags: pm-rhel: mirror+
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
OpenSCAP doesn't produce errors when checking available memory When evaluating some XCCDF rules, OpenSCAP showed error message "Failed to check available memory" and could produce invalid scan results. It manifested for example during evaluation rules accounts_user_dot_no_world_writable_programs, accounts_user_dot_group_ownership or accounts_users_home_files_permissions. The problem was caused by wrong error handling in the OpenSCAP code and the error message was incorrect. The bug in error handling has been fixed and the message "Failed to check available memory" will appear only in the event of a real failure.
Story Points: ---
Clone Of: Environment:
Last Closed: 2022-09-08 11:04:51 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Renaud Métrich 2022-09-07 10:19:30 UTC
Description of problem:

Some rules processing a lot of items can see the following error message appearing multiple times:
~~~
Title   Ensure All Files Are Owned by a User
Rule    xccdf_org.ssgproject.content_rule_no_files_unowned_by_user
Ident   CCE-83499-4
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
E: oscap:     Failed to check available memory
Result  fail
~~~

This is confusing for the user since he may believe the result of the rule is a failure due to having these error messages, whereas it's not the case actually.

Troubleshooting this with the help from the customer (I couldn't reproduce myself yet), the root cause is relying on `/proc/self/status` and `/proc/meminfo` for computing the memory currently in use by oscap process:
~~~
 94 static int read_status(const char *source, void *base, struct stat_parser *spt, size_t spt_size)
 95 {
 :
113         fp = fopen(source, "r");
114 
115         if (fp == NULL)
116                 return -1;    <<<< NOT THIS ONE SINCE FILE COULD BE OPENED
 :
124                 while (fgets(linebuf, sizeof linebuf - 1, fp) != NULL) {
125                         strval = strchr(linebuf, ':');
126 
127                         if (strval == NULL) {
128                                 fclose (fp);
129                                 return (-1);    <<<< NOT THIS ONE SINCE ALL LINES HAVE A SEMI-COLON (from the strace)
130                         }
131    
132                         *strval++ = '\0';
 :
150                         /* line is too long, somthing is wrong */
151                         if (strchr(strval, '\n') == NULL) {
152                                 dE("value for %s key is too long", linebuf);
153                                 fclose(fp);
154                                 return (-1);    <<<< NOT THIS ONE SINCE THIS WOULD PRINT A ERROR MESSAGE
155                         }
156 
157                         if (sp->storval((void *)((uintptr_t)(base) + sp->offset), strval) != 0) {
158                                 fclose (fp);
159                                 return (-1);    <<<< MUST BE THIS ONE THEN!
160                         }
 :
~~~

Here above, the code relies on fopen("/proc/self/status") then fgets(linebuf).
When a refresh of "/proc/self/status", it's possible that fgets() reads some invalid data, as shown with a coredump taken while instrumenting line 158 to make the process die on failure:
~~~
(gdb) f 2
#2  0x00007f1e917fb049 in read_status (source=<optimized out>, base=0x7f1e3b7f45c0, 
    spt=0x7f1e91af7020 <__proc_stat_ptable>, spt_size=7)
    at /usr/src/debug/openscap-1.3.6-3.el8_6.rhcase_03304876.2.x86_64/src/common/memusage.c:158

(gdb) p strval
$1 = 0x7f1e3b7f445e "0"
(gdb) p linebuf 
$2 = "VmLck\000\t       0\000kB\n\000\000\000\000\000\300X\177;\036\177\000\000\n4\213\221\036\177\000\000\f\000\000\000\000\000\000\000\000\030\372h\036\177\000\000 s\212\221\036\177\000\000\v\000\000\000\000\000\000\000\060c\001h\036\177\000\000v@\213\221\036\177\000\000\v\000\000\000\000\000\000\000@K\371h\036\177\000\000n@\213\221\036\177\000\000\v\000\000\000\000\000\000\000 \305\004h\036\177\000\000g@\213\221\036\177\000\000\v\000\000\000\000\000\000\000\360F\177;\036\177\000\000\223G\213\221\036\177\000\000\003\000\000\000\000\000\000\000\200\022\000h\036\177\000\000\000G\177;\036\177\000\000\342\267\207\221\036\177\000\000\020G\177;\036\177\000\000"...
~~~

In the example above, we have `VmLck` property, then a colon (overwritten by a "\0" on line 132), then the value ("0").
It should be followed by a space and "kB", but the space has been replaced by a "\0", leading to failure.
This is likely due to the memory being replaced because "/proc/self/status" got "refreshed".

I don't know what is the exact solution here, I see 2 possibilities:

1. either don't print an error at all or retry until it's a success
2. or read whole content of "/proc/self/status" in one shot and parse the buffer line by line, instead of using fopen()/fgets()


Version-Release number of selected component (if applicable):

openscap-1.3.6-3.el8_6

How reproducible:

Always on customer system, couldn't reproduce internally yet.

Steps to Reproduce:
1. Execute above rule with having many unowned files to trigger the memory check (more than 1000)

Actual results:

Error message printed multiple times

Expected results:

No error message

Comment 1 Jan Černý 2022-09-08 09:09:34 UTC
Hi Renaud,

Thanks for excellent debugging!

Although I don't have a solution, I have some more insights.

You identified the `sp->storval` callback that as the condition that causes read_status to return -1 and therefore causes printing the error message. This callback is always the `read_common_sizet` function (memusage.c). This function overwrites some data in its `strval` parameter by zeros. And the `strval` points to the same memory as `linebuf`. So I think that the corrupt `linebuf` can be also caused by the `read_common_sizet` function and it doesn't need to be a "file refresh".

Also, recently, we had a bug in the very same function `read_common_sizet` which also manifested by the "Failed to check available memory" message: https://bugzilla.redhat.com/show_bug.cgi?id=2111040
It was caused by wrong usage of errno. Theoretically, it might be the same problem and this BZ could be a duplicate. The https://bugzilla.redhat.com/show_bug.cgi?id=2111040 is fixed in RHEL 8.7. Would it be possible to try if this problem would fixed the customer problem with the RHEL 8.7 version?

Comment 2 Renaud Métrich 2022-09-08 11:04:51 UTC
Customer confirmed that BZ #2111040 fixes the issue.
Regarding stability of "/proc" nodes, I was probably wrong, some testing (on "/proc/self/mountinfo" because it's more convenient) showed processing the file while it gets updated doesn't break.

*** This bug has been marked as a duplicate of bug 2111040 ***