libselinux: verify file_contexts when using restorecon
PATCH 1/1 libselinux: verify file_contexts when using restorecon
In permissive mode, calling restorecon with a bad label in file_contexts does not verify the label's existence in the loaded policy. This results in any label successfully applying to a file, as long as the file exists.
This issue has two assumptions:
1) file_contexts must be manually updated with the invalid label. Running semanage fcontext will error when attempting to add an invalid label to file_contexts.
2) the system must be in permissive. Although applying an invalid label in enforcing gives an error and fails, successfully labeling a file with a bad label could cause issues during policy development in permissive.
Instead of the current behavior, mimic setfiles' -c flag, and verify the labels against the loaded policy binary.
Behavior before patch:
$ sudo -s $ setenforce 0 $ echo '/test.txt -- system_u:object_r:foo_bar_baz:s0' >> /etc/selinux/targeted/contexts/files/file_contexts $ restorecon -v /test.txt Relabeled /test.txt from system_u:object_r:etc_runtime_t:s0 to system_u:object_r:foo_bar_baz:s0
Behavior after patch:
$ sudo -s $ setenforce 0 $ echo '/test.txt -- system_u:object_r:foo_bar_baz:s0' >> /etc/selinux/targeted/contexts/files/file_contexts $ restorecon -v /test.txt restorecon: /etc/selinux/targeted/contexts/files/file_contexts: line 6123 has invalid context system_u:object_r:foo_bar_baz:s0 Invalid argument
--- policycoreutils/setfiles/setfiles.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
policycoreutils/setfiles/setfiles.c +2 -2
@@ -217,7 +217,7 @@ int main(int argc, char **argv)* Do not abort on errors during the file tree walk, * Do not try to track inode associations for conflict detection, * Follows mounts, -* Does lazy validation of contexts upon use. +* Validates all file contexts at init time. */ if (strcmp (base,RESTORECON )) fprintf(stderr, "Executed with unrecognized name (%s), defaulting to %s behavior.\n",
@@ -230,7 +230,7 @@ int main(int argc, char **argv) r_opts.add_assoc =0 ; r_opts.xdev =0 ; r_opts.ignore_mounts =0 ; - ctx_validate =0 ; + ctx_validate =1 ; opts = ropts;/* restorecon only: silent exit if no SELinux.
Signature · 1 line
2.14.3
Quoted 43 lines · Yuli Khodorkovskiy
In permissive mode, calling restorecon with a bad label in
file_contextsdoes not verify the label's existence in the loaded policy. This results in any label successfully applying to a file, as long as the file exists.This issue has two assumptions:
1)file_contextsmust be manually updated with the invalid label. Runningsemanage fcontextwill error when attempting to add an invalid label tofile_contexts.
2) the system must be in permissive. Although applying an invalid label in enforcing gives an error and fails, successfully labeling a file with a bad label could cause issues during policy development in permissive.Instead of the current behavior, mimic setfiles' -c flag, and verify the labels against the loaded policy binary.
Behavior before patch:
$ sudo -s $ setenforce 0 $ echo '/test.txt -- system_u:object_r:foo_bar_baz:s0' >> /etc/selinux/targeted/contexts/files/file_contexts $ restorecon -v /test.txt Relabeled /test.txt from system_u:object_r:etc_runtime_t:s0 to system_u:object_r:foo_bar_baz:s0Behavior after patch:
$ sudo -s $ setenforce 0 $ echo '/test.txt -- system_u:object_r:foo_bar_baz:s0' >> /etc/selinux/targeted/contexts/files/file_contexts $ restorecon -v /test.txt restorecon: /etc/selinux/targeted/contexts/files/file_contexts: line 6123 has invalid context system_u:object_r:foo_bar_baz:s0 Invalid argumentSigned-off-by Yuli Khodorkovskiy <[email protected]>--- policycoreutils/setfiles/setfiles.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)policycoreutils/setfiles/setfiles.c +0
-0
policycoreutils/setfiles/setfiles.c int main(int argc, char **argv) · line 220
Quoted 5 lines
policycoreutils/setfiles/setfiles.c +1
-1@@ -217,7 +217,7 @@ int main(int argc, char **argv)* Do not abort on errors during the file tree walk, * Do not try to track inode associations for conflict detection, * Follows mounts, -* Does lazy validation of contexts upon use. +* Validates all file contexts at init time.
I think this was intentional; the reason they didn't want to validate all file contexts at init time for restorecon was that they didn't want a single error in file_contexts to prevent restorecon from working at all (e.g. one typo could kill restorecon -R /dev during boot, even if the erroneous entry had nothing to do with /dev). Instead, I think we were doing validation lazily for the context to be used, e.g. matchpathcon() or selabel_lookup() would validate the context before returning it. Looking at the code, we do call compat_validate() in selabel_fini(), which occurs just prior to returning a result from lookup. And this will call selabel_validate() unless the caller has set an invalidcon or canoncon callback (legacy matchpathcon support). And selabel_validate() has a check to see if the individual context has already been validated (contexts->validated), but it also presently returns immediately if the caller did not set validation up front. Meanwhile, process_line() and load_mmap() don't even call selabel_validate() if !rec->validating. I think it is a bug in selabel_validate() that it is returning immediately if !rec->validating. During initialization (i.e. loading of file_contexts or file_contexts.bin by process_line() or load_mmap() respectively), we should only call selabel_validate() if rec->validating (as is presently done). But at lookup, selabel_fini() should call selabel_validate() and that should validate the context unless it has already been validated (based on contexts->validated), irrespective of rec->validating. That's the lazy validation part. Then we get validation before any context gets used but we don't break entirely if there is a single bad entry in file_contexts. Sound reasonable?
Quoted 13 lines
policycoreutils/setfiles/setfiles.c +1
-1*/ if (strcmp (base,RESTORECON )) fprintf(stderr, "Executed with unrecognized name (%s), defaulting to %s behavior.\n",@@ -230,7 +230,7 @@ int main(int argc, char **argv) r_opts.add_assoc =0 ; r_opts.xdev =0 ; r_opts.ignore_mounts =0 ; - ctx_validate =0 ; + ctx_validate =1 ; opts = ropts;/* restorecon only: silent exit if no SELinux.
Quoted 75 lines · Stephen Smalley
Quoted 11 lines · Yuli Khodorkovskiy
In permissive mode, calling restorecon with a bad label in
file_contextsdoes not verify the label's existence in the loaded policy. This results in any label successfully applying to a file, as long as the file exists.This issue has two assumptions:
1)file_contextsmust be manually updated with the invalid label. Runningsemanage fcontextwill error when attempting to add an invalid label tofile_contexts.
2) the system must be in permissive. Although applying an invalid label in enforcing gives an error and fails, successfully labeling a file witha
Quoted 3 lines
bad label could cause issues during policy development in permissive.
Instead of the current behavior, mimic setfiles' -c flag, and verify the
labels
Quoted 7 lines
against the loaded policy binary.
Behavior before patch:
$ sudo -s $ setenforce 0 $ echo '/test.txt -- system_u:object_r:foo_bar_baz:s0' >>
/etc/selinux/targeted/contexts/files/file_contextsQuoted 2 lines
$ restorecon -v /test.txt Relabeled /test.txt from system_u:object_r:etc_runtime_t:s0 tosystem_u:object_r:foo_bar_baz:s0
Quoted 6 lines
Behavior after patch:
$ sudo -s $ setenforce 0 $ echo '/test.txt -- system_u:object_r:foo_bar_baz:s0' >>
/etc/selinux/targeted/contexts/files/file_contextsQuoted 2 lines
$ restorecon -v /test.txt restorecon: /etc/selinux/targeted/contexts/files/file_contexts: line6123 has invalid context system_u:object_r:foo_bar_baz:s0
Review
Quoted 8 lines
Invalid argument
Signed-off-by Yuli Khodorkovskiy <[email protected]>--- policycoreutils/setfiles/setfiles.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)(quoted diff) +0
-0
b/policycoreutils/setfiles/setfiles.cpolicycoreutils/setfiles/setfiles.c int main(int argc, char **argv) · line 218
Quoted 6 lines
index
bc83c27b..ce1e4324100644policycoreutils/setfiles/setfiles.c +0
-0@@ -217,7 +217,7 @@ int main(int argc, char **argv)* Do not abort on errors during the file tree walk, * Do not try to track inode associations for conflict detection,
policycoreutils/setfiles/setfiles.c int main(int argc, char **argv) · line 220
Quoted 3 lines
policycoreutils/setfiles/setfiles.c +1
-1* Follows mounts, -* Does lazy validation of contexts upon use. +* Validates all file contexts at init time. I think this was intentional; the reason they didn't want to validate all file contexts at init time for restorecon was that they didn't want a single error in
file_contextsto prevent restorecon from working at all (e.g. one typo could kill restorecon -R /dev during boot, even if the erroneous entry had nothing to do with /dev). Instead, I think we were doing validation lazily for the context to be used, e.g.matchpathcon()orselabel_lookup()would validate the context before returning it. Looking at the code, we do callcompat_validate()inselabel_fini(), which occurs just prior to returning a result from lookup. And this will callselabel_validate()unless the caller has set an invalidcon or canoncon callback (legacy matchpathcon support). Andselabel_validate()has a check to see if the individual context has already been validated (contexts->validated), but it also presently returns immediately if the caller did not set validation up front. Meanwhile,process_line()andload_mmap()don't even callselabel_validate()if !rec->validating. I think it is a bug inselabel_validate()that it is returning immediately if !rec->validating. During initialization (i.e. loading offile_contextsor
Quoted 9 lines
file_contexts.bin by
process_line()orload_mmap()respectively), we should only callselabel_validate()ifrec->validating(as is presently done). But at lookup,selabel_fini()should callselabel_validate()and that should validate the context unless it has already been validated (based oncontexts->validated), irrespective ofrec->validating. That's the lazy validation part. Then we get validation before any context gets used but we don't break entirely if there is a single bad entry infile_contexts. Sound reasonable?
That makes sense. Thank you for the explanation. I'll send out another version of the patch.
Quoted 17 lines
policycoreutils/setfiles/setfiles.c int main(int argc, char **argv)
Quoted 4 lines
policycoreutils/setfiles/setfiles.c +0
-0*/ if (strcmp (base,RESTORECON )) fprintf(stderr, "Executed with unrecognized name(%s), defaulting to %s behavior.\n",
Quoted 10 lines
policycoreutils/setfiles/setfiles.c +1
-1@@ -230,7 +230,7 @@ int main(int argc, char **argv) r_opts.add_assoc =0 ; r_opts.xdev =0 ; r_opts.ignore_mounts =0 ; - ctx_validate =0 ; + ctx_validate =1 ; opts = ropts;/* restorecon only: silent exit if no SELinux.