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.
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.
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
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?
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 ***
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