diff mbox series

[v2,5/5] setfiles: introduce the -C option for distinguishing file tree walk errors

Message ID 20220503082326.11621-6-lersek@redhat.com (mailing list archive)
State Accepted
Commit 2b6f7e969cf6
Headers show
Series selinux_restorecon(3), setfiles(8): skip relabeling errors | expand

Commit Message

Laszlo Ersek May 3, 2022, 8:23 a.m. UTC
setfiles(8) exits with status 255 if it encounters any error. Introduce
the "-C" option: if the only errors that setfiles(8) encounters are
labeling errors seen during the file tree walk(s), then let setfiles(8)
exit with status 1.

Cc: "Richard W.M. Jones" <rjones@redhat.com>
Cc: Petr Lautrbach <plautrba@redhat.com>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1794518
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
 policycoreutils/setfiles/restore.h  |  4 +++-
 policycoreutils/setfiles/restore.c  |  8 +++++--
 policycoreutils/setfiles/setfiles.c | 19 +++++++++++------
 policycoreutils/setfiles/setfiles.8 | 22 ++++++++++++++++++++
 4 files changed, 44 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/policycoreutils/setfiles/restore.h b/policycoreutils/setfiles/restore.h
index bb35a1db9e34..a5af81fe3bb4 100644
--- a/policycoreutils/setfiles/restore.h
+++ b/policycoreutils/setfiles/restore.h
@@ -35,6 +35,7 @@  struct restore_opts {
 	unsigned int ignore_noent;
 	unsigned int ignore_mounts;
 	unsigned int conflict_error;
+	unsigned int count_errors;
 	/* restorecon_flags holds | of above for restore_init() */
 	unsigned int restorecon_flags;
 	char *rootpath;
@@ -49,7 +50,8 @@  struct restore_opts {
 void restore_init(struct restore_opts *opts);
 void restore_finish(void);
 void add_exclude(const char *directory);
-int process_glob(char *name, struct restore_opts *opts, size_t nthreads);
+int process_glob(char *name, struct restore_opts *opts, size_t nthreads,
+		 long unsigned *skipped_errors);
 extern char **exclude_list;
 
 #endif
diff --git a/policycoreutils/setfiles/restore.c b/policycoreutils/setfiles/restore.c
index e9ae33ad039a..6131f46a7523 100644
--- a/policycoreutils/setfiles/restore.c
+++ b/policycoreutils/setfiles/restore.c
@@ -41,7 +41,8 @@  void restore_init(struct restore_opts *opts)
 			   opts->xdev | opts->abort_on_error |
 			   opts->syslog_changes | opts->log_matches |
 			   opts->ignore_noent | opts->ignore_mounts |
-			   opts->mass_relabel | opts->conflict_error;
+			   opts->mass_relabel | opts->conflict_error |
+			   opts->count_errors;
 
 	/* Use setfiles, restorecon and restorecond own handles */
 	selinux_restorecon_set_sehandle(opts->hnd);
@@ -72,7 +73,8 @@  void restore_finish(void)
 	}
 }
 
-int process_glob(char *name, struct restore_opts *opts, size_t nthreads)
+int process_glob(char *name, struct restore_opts *opts, size_t nthreads,
+		 long unsigned *skipped_errors)
 {
 	glob_t globbuf;
 	size_t i = 0;
@@ -96,6 +98,8 @@  int process_glob(char *name, struct restore_opts *opts, size_t nthreads)
 						 nthreads);
 		if (rc < 0)
 			errors = rc;
+		else if (opts->restorecon_flags & SELINUX_RESTORECON_COUNT_ERRORS)
+			*skipped_errors += selinux_restorecon_get_skipped_errors();
 	}
 
 	globfree(&globbuf);
diff --git a/policycoreutils/setfiles/setfiles.c b/policycoreutils/setfiles/setfiles.c
index aeec1fdcc2ab..4dd0d0dc3835 100644
--- a/policycoreutils/setfiles/setfiles.c
+++ b/policycoreutils/setfiles/setfiles.c
@@ -40,8 +40,8 @@  static __attribute__((__noreturn__)) void usage(const char *const name)
 			name, name);
 	} else {
 		fprintf(stderr,
-			"usage:  %s [-diIDlmnpqvEFWT] [-e excludedir] [-r alt_root_path] [-c policyfile] spec_file pathname...\n"
-			"usage:  %s [-diIDlmnpqvEFWT] [-e excludedir] [-r alt_root_path] [-c policyfile] spec_file -f filename\n"
+			"usage:  %s [-diIDlmnpqvCEFWT] [-e excludedir] [-r alt_root_path] [-c policyfile] spec_file pathname...\n"
+			"usage:  %s [-diIDlmnpqvCEFWT] [-e excludedir] [-r alt_root_path] [-c policyfile] spec_file -f filename\n"
 			"usage:  %s -s [-diIDlmnpqvFWT] spec_file\n",
 			name, name, name);
 	}
@@ -150,9 +150,10 @@  int main(int argc, char **argv)
 	const char *base;
 	int errors = 0;
 	const char *ropts = "e:f:hiIDlmno:pqrsvFRW0xT:";
-	const char *sopts = "c:de:f:hiIDlmno:pqr:svEFR:W0T:";
+	const char *sopts = "c:de:f:hiIDlmno:pqr:svCEFR:W0T:";
 	const char *opts;
 	union selinux_callback cb;
+	long unsigned skipped_errors;
 
 	/* Initialize variables */
 	memset(&r_opts, 0, sizeof(r_opts));
@@ -161,6 +162,7 @@  int main(int argc, char **argv)
 	warn_no_match = 0;
 	request_digest = 0;
 	policyfile = NULL;
+	skipped_errors = 0;
 
 	if (!argv[0]) {
 		fprintf(stderr, "Called without required program name!\n");
@@ -288,6 +290,9 @@  int main(int argc, char **argv)
 			r_opts.syslog_changes =
 					   SELINUX_RESTORECON_SYSLOG_CHANGES;
 			break;
+		case 'C':
+			r_opts.count_errors = SELINUX_RESTORECON_COUNT_ERRORS;
+			break;
 		case 'E':
 			r_opts.conflict_error =
 					   SELINUX_RESTORECON_CONFLICT_ERROR;
@@ -447,13 +452,15 @@  int main(int argc, char **argv)
 			buf[len - 1] = 0;
 			if (!strcmp(buf, "/"))
 				r_opts.mass_relabel = SELINUX_RESTORECON_MASS_RELABEL;
-			errors |= process_glob(buf, &r_opts, nthreads) < 0;
+			errors |= process_glob(buf, &r_opts, nthreads,
+					       &skipped_errors) < 0;
 		}
 		if (strcmp(input_filename, "-") != 0)
 			fclose(f);
 	} else {
 		for (i = optind; i < argc; i++)
-			errors |= process_glob(argv[i], &r_opts, nthreads) < 0;
+			errors |= process_glob(argv[i], &r_opts, nthreads,
+					       &skipped_errors) < 0;
 	}
 
 	maybe_audit_mass_relabel(r_opts.mass_relabel, errors);
@@ -467,5 +474,5 @@  int main(int argc, char **argv)
 	if (r_opts.progress)
 		fprintf(stdout, "\n");
 
-	exit(errors ? -1 : 0);
+	exit(errors ? -1 : skipped_errors ? 1 : 0);
 }
diff --git a/policycoreutils/setfiles/setfiles.8 b/policycoreutils/setfiles/setfiles.8
index 19b59a2cc90d..bf26e161a71d 100644
--- a/policycoreutils/setfiles/setfiles.8
+++ b/policycoreutils/setfiles/setfiles.8
@@ -6,6 +6,7 @@  setfiles \- set SELinux file security contexts.
 .B setfiles
 .RB [ \-c
 .IR policy ]
+.RB [ \-C ]
 .RB [ \-d ]
 .RB [ \-l ]
 .RB [ \-m ]
@@ -58,6 +59,13 @@  option will force a replacement of the entire context.
 .B \-c
 check the validity of the contexts against the specified binary policy.
 .TP
+.B \-C
+If only relabeling errors are encountered during the file tree walks,
+exit with status
+.B 1
+rather than
+.BR 255 .
+.TP
 .B \-d
 show what specification matched each file.
 .TP
@@ -219,6 +227,20 @@  or the
 .B \-s
 option is used.
 
+.SH "EXIT STATUS"
+.B setfiles
+exits with status
+.B 0
+if it encounters no errors. Fatal errors result in status
+.BR 255 .
+Labeling errors encountered during file tree walk(s) result in status
+.B 1
+if the
+.B -C
+option is specified and no other kind of error is encountered, and in status
+.B 255
+otherwise.
+
 .SH "NOTES"
 .IP "1." 4
 .B setfiles