2009-09-10 18:54:35 +00:00
|
|
|
#include "restore.h"
|
2008-08-19 19:30:36 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio_ext.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <regex.h>
|
|
|
|
#include <sys/vfs.h>
|
|
|
|
#include <libgen.h>
|
|
|
|
#ifdef USE_AUDIT
|
|
|
|
#include <libaudit.h>
|
|
|
|
|
|
|
|
#ifndef AUDIT_FS_RELABEL
|
|
|
|
#define AUDIT_FS_RELABEL 2309
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2016-07-26 08:44:44 +00:00
|
|
|
static char *policyfile;
|
|
|
|
static int warn_no_match;
|
|
|
|
static int null_terminated;
|
2016-09-25 14:49:32 +00:00
|
|
|
static int request_digest;
|
2009-09-10 18:54:35 +00:00
|
|
|
static struct restore_opts r_opts;
|
2016-07-26 08:44:44 +00:00
|
|
|
static int nerr;
|
2009-09-10 18:54:35 +00:00
|
|
|
|
|
|
|
#define STAT_BLOCK_SIZE 1
|
|
|
|
|
2012-08-22 07:13:43 +00:00
|
|
|
/* setfiles will abort its operation after reaching the
|
|
|
|
* following number of errors (e.g. invalid contexts),
|
|
|
|
* unless it is used in "debug" mode (-d option).
|
|
|
|
*/
|
|
|
|
#ifndef ABORT_ON_ERRORS
|
|
|
|
#define ABORT_ON_ERRORS 10
|
|
|
|
#endif
|
2008-08-19 19:30:36 +00:00
|
|
|
|
|
|
|
#define SETFILES "setfiles"
|
|
|
|
#define RESTORECON "restorecon"
|
|
|
|
static int iamrestorecon;
|
|
|
|
|
|
|
|
/* Behavior flags determined based on setfiles vs. restorecon */
|
|
|
|
static int ctx_validate; /* Validate contexts */
|
|
|
|
static const char *altpath; /* Alternate path to file_contexts */
|
|
|
|
|
2017-03-05 17:13:05 +00:00
|
|
|
static __attribute__((__noreturn__)) void usage(const char *const name)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
if (iamrestorecon) {
|
|
|
|
fprintf(stderr,
|
2016-09-25 14:49:32 +00:00
|
|
|
"usage: %s [-iIDFmnprRv0] [-e excludedir] pathname...\n"
|
|
|
|
"usage: %s [-iIDFmnprRv0] [-e excludedir] -f filename\n",
|
2012-08-22 07:13:43 +00:00
|
|
|
name, name);
|
2008-08-19 19:30:36 +00:00
|
|
|
} else {
|
|
|
|
fprintf(stderr,
|
2016-09-25 14:49:32 +00:00
|
|
|
"usage: %s [-diIDlmnpqvFW] [-e excludedir] [-r alt_root_path] spec_file pathname...\n"
|
|
|
|
"usage: %s [-diIDlmnpqvFW] [-e excludedir] [-r alt_root_path] spec_file -f filename\n"
|
|
|
|
"usage: %s -s [-diIDlmnpqvFW] spec_file\n"
|
2012-08-22 07:13:43 +00:00
|
|
|
"usage: %s -c policyfile spec_file\n",
|
|
|
|
name, name, name, name);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
2013-10-11 14:37:44 +00:00
|
|
|
exit(-1);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
|
2014-09-14 21:41:49 +00:00
|
|
|
void inc_err(void)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
nerr++;
|
2012-08-22 07:13:43 +00:00
|
|
|
if (nerr > ABORT_ON_ERRORS - 1 && !r_opts.debug) {
|
|
|
|
fprintf(stderr, "Exiting after %d errors.\n", ABORT_ON_ERRORS);
|
2013-10-11 14:37:44 +00:00
|
|
|
exit(-1);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_rootpath(const char *arg)
|
|
|
|
{
|
2016-07-26 08:44:44 +00:00
|
|
|
if (strlen(arg) == 1 && strncmp(arg, "/", 1) == 0) {
|
|
|
|
fprintf(stderr, "%s: invalid alt_rootpath: %s\n",
|
|
|
|
r_opts.progname, arg);
|
|
|
|
exit(-1);
|
|
|
|
}
|
2008-08-19 19:30:36 +00:00
|
|
|
|
2009-09-10 18:54:35 +00:00
|
|
|
r_opts.rootpath = strdup(arg);
|
2016-07-26 08:44:44 +00:00
|
|
|
if (!r_opts.rootpath) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: insufficient memory for r_opts.rootpath\n",
|
2009-09-10 18:54:35 +00:00
|
|
|
r_opts.progname);
|
2013-10-11 14:37:44 +00:00
|
|
|
exit(-1);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int canoncon(char **contextp)
|
|
|
|
{
|
|
|
|
char *context = *contextp, *tmpcon;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (policyfile) {
|
|
|
|
if (sepol_check_context(context) < 0) {
|
|
|
|
fprintf(stderr, "invalid context %s\n", context);
|
2013-10-11 14:37:44 +00:00
|
|
|
exit(-1);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
} else if (security_canonicalize_context_raw(context, &tmpcon) == 0) {
|
|
|
|
free(context);
|
|
|
|
*contextp = tmpcon;
|
|
|
|
} else if (errno != ENOENT) {
|
|
|
|
rc = -1;
|
|
|
|
inc_err();
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef USE_AUDIT
|
2011-07-10 15:32:14 +00:00
|
|
|
static void maybe_audit_mass_relabel(int mass_relabel __attribute__((unused)),
|
2016-07-26 08:44:44 +00:00
|
|
|
int mass_relabel_errs __attribute__((unused)))
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
#else
|
2011-07-10 15:32:14 +00:00
|
|
|
static void maybe_audit_mass_relabel(int mass_relabel, int mass_relabel_errs)
|
2008-08-19 19:30:36 +00:00
|
|
|
{
|
|
|
|
int audit_fd = -1;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (!mass_relabel) /* only audit a forced full relabel */
|
|
|
|
return;
|
|
|
|
|
|
|
|
audit_fd = audit_open();
|
|
|
|
|
|
|
|
if (audit_fd < 0) {
|
|
|
|
fprintf(stderr, "Error connecting to audit system.\n");
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = audit_log_user_message(audit_fd, AUDIT_FS_RELABEL,
|
2016-07-26 08:44:44 +00:00
|
|
|
"op=mass relabel",
|
|
|
|
NULL, NULL, NULL, !mass_relabel_errs);
|
2008-08-19 19:30:36 +00:00
|
|
|
if (rc <= 0) {
|
|
|
|
fprintf(stderr, "Error sending audit message: %s.\n",
|
|
|
|
strerror(errno));
|
2016-07-26 08:44:44 +00:00
|
|
|
/* exit(-1); -- don't exit atm. as fix for eff_cap isn't
|
|
|
|
* in most kernels.
|
|
|
|
*/
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
audit_close(audit_fd);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-01-24 19:34:17 +00:00
|
|
|
static int __attribute__ ((format(printf, 2, 3)))
|
|
|
|
log_callback(int type, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
int rc;
|
2017-03-26 16:22:43 +00:00
|
|
|
FILE *out;
|
2017-01-24 19:34:17 +00:00
|
|
|
va_list ap;
|
2017-03-26 16:22:43 +00:00
|
|
|
|
|
|
|
if (type == SELINUX_INFO) {
|
|
|
|
out = stdout;
|
|
|
|
} else {
|
|
|
|
out = stderr;
|
2017-03-26 16:22:44 +00:00
|
|
|
fflush(stdout);
|
2017-03-26 16:22:43 +00:00
|
|
|
fprintf(out, "%s: ", r_opts.progname);
|
|
|
|
}
|
2017-01-24 19:34:17 +00:00
|
|
|
va_start(ap, fmt);
|
|
|
|
rc = vfprintf(out, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2008-08-19 19:30:36 +00:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
int opt, i = 0;
|
2014-09-14 21:41:48 +00:00
|
|
|
const char *input_filename = NULL;
|
2008-08-19 19:30:36 +00:00
|
|
|
int use_input_file = 0;
|
|
|
|
char *buf = NULL;
|
|
|
|
size_t buf_len;
|
2014-09-14 21:41:48 +00:00
|
|
|
const char *base;
|
2017-01-27 12:47:49 +00:00
|
|
|
int errors = 0;
|
2016-09-25 14:49:32 +00:00
|
|
|
const char *ropts = "e:f:hiIDlmno:pqrsvFRW0";
|
|
|
|
const char *sopts = "c:de:f:hiIDlmno:pqr:svFR:W0";
|
2015-04-16 15:22:22 +00:00
|
|
|
const char *opts;
|
2017-01-24 19:34:17 +00:00
|
|
|
union selinux_callback cb;
|
2009-09-10 18:54:35 +00:00
|
|
|
|
|
|
|
/* Initialize variables */
|
2016-07-26 08:44:44 +00:00
|
|
|
memset(&r_opts, 0, sizeof(r_opts));
|
2008-08-19 19:30:36 +00:00
|
|
|
altpath = NULL;
|
2016-07-26 08:44:44 +00:00
|
|
|
null_terminated = 0;
|
|
|
|
warn_no_match = 0;
|
2016-09-30 15:03:06 +00:00
|
|
|
request_digest = 0;
|
2016-07-26 08:44:44 +00:00
|
|
|
policyfile = NULL;
|
|
|
|
nerr = 0;
|
2008-08-19 19:30:36 +00:00
|
|
|
|
2009-09-10 18:54:35 +00:00
|
|
|
r_opts.progname = strdup(argv[0]);
|
|
|
|
if (!r_opts.progname) {
|
2008-08-19 19:30:36 +00:00
|
|
|
fprintf(stderr, "%s: Out of memory!\n", argv[0]);
|
2013-10-11 14:37:44 +00:00
|
|
|
exit(-1);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
2009-09-10 18:54:35 +00:00
|
|
|
base = basename(r_opts.progname);
|
2016-07-26 08:44:44 +00:00
|
|
|
|
2008-08-19 19:30:36 +00:00
|
|
|
if (!strcmp(base, SETFILES)) {
|
2016-07-26 08:44:44 +00:00
|
|
|
/*
|
|
|
|
* setfiles:
|
2008-08-19 19:30:36 +00:00
|
|
|
* Recursive descent,
|
2016-07-26 08:44:44 +00:00
|
|
|
* Does not expand paths via realpath,
|
|
|
|
* Aborts on errors during the file tree walk,
|
2008-08-19 19:30:36 +00:00
|
|
|
* Try to track inode associations for conflict detection,
|
2016-07-26 08:44:44 +00:00
|
|
|
* Does not follow mounts (sets SELINUX_RESTORECON_XDEV),
|
|
|
|
* Validates all file contexts at init time.
|
2008-08-19 19:30:36 +00:00
|
|
|
*/
|
|
|
|
iamrestorecon = 0;
|
2016-07-26 08:44:44 +00:00
|
|
|
r_opts.recurse = SELINUX_RESTORECON_RECURSE;
|
|
|
|
r_opts.userealpath = 0; /* SELINUX_RESTORECON_REALPATH */
|
|
|
|
r_opts.abort_on_error = SELINUX_RESTORECON_ABORT_ON_ERROR;
|
|
|
|
r_opts.add_assoc = SELINUX_RESTORECON_ADD_ASSOC;
|
|
|
|
/* FTS_PHYSICAL and FTS_NOCHDIR are always set by selinux_restorecon(3) */
|
|
|
|
r_opts.xdev = SELINUX_RESTORECON_XDEV;
|
|
|
|
r_opts.ignore_mounts = 0; /* SELINUX_RESTORECON_IGNORE_MOUNTS */
|
2008-08-19 19:30:36 +00:00
|
|
|
ctx_validate = 1;
|
2015-04-16 15:22:22 +00:00
|
|
|
opts = sopts;
|
2008-08-19 19:30:36 +00:00
|
|
|
} else {
|
|
|
|
/*
|
2016-07-26 08:44:44 +00:00
|
|
|
* restorecon:
|
2008-08-19 19:30:36 +00:00
|
|
|
* No recursive descent unless -r/-R,
|
2016-07-26 08:44:44 +00:00
|
|
|
* Expands paths via realpath,
|
2008-08-19 19:30:36 +00:00
|
|
|
* Do not abort on errors during the file tree walk,
|
|
|
|
* Do not try to track inode associations for conflict detection,
|
|
|
|
* Follows mounts,
|
2016-07-26 08:44:44 +00:00
|
|
|
* Does lazy validation of contexts upon use.
|
2008-08-19 19:30:36 +00:00
|
|
|
*/
|
2016-07-26 08:44:44 +00:00
|
|
|
if (strcmp(base, RESTORECON))
|
|
|
|
fprintf(stderr, "Executed with unrecognized name (%s), defaulting to %s behavior.\n",
|
|
|
|
base, RESTORECON);
|
|
|
|
|
2008-08-19 19:30:36 +00:00
|
|
|
iamrestorecon = 1;
|
2016-07-26 08:44:44 +00:00
|
|
|
r_opts.recurse = 0;
|
|
|
|
r_opts.userealpath = SELINUX_RESTORECON_REALPATH;
|
2009-09-10 18:54:35 +00:00
|
|
|
r_opts.abort_on_error = 0;
|
|
|
|
r_opts.add_assoc = 0;
|
2016-07-26 08:44:44 +00:00
|
|
|
r_opts.xdev = 0;
|
|
|
|
r_opts.ignore_mounts = 0;
|
2008-08-19 19:30:36 +00:00
|
|
|
ctx_validate = 0;
|
2015-04-16 15:22:22 +00:00
|
|
|
opts = ropts;
|
2008-08-19 19:30:36 +00:00
|
|
|
|
|
|
|
/* restorecon only: silent exit if no SELinux.
|
2016-07-26 08:44:44 +00:00
|
|
|
* Allows unconditional execution by scripts.
|
|
|
|
*/
|
2008-08-19 19:30:36 +00:00
|
|
|
if (is_selinux_enabled() <= 0)
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Process any options. */
|
2015-04-16 15:22:22 +00:00
|
|
|
while ((opt = getopt(argc, argv, opts)) > 0) {
|
2008-08-19 19:30:36 +00:00
|
|
|
switch (opt) {
|
|
|
|
case 'c':
|
|
|
|
{
|
|
|
|
FILE *policystream;
|
|
|
|
|
|
|
|
if (iamrestorecon)
|
|
|
|
usage(argv[0]);
|
|
|
|
|
|
|
|
policyfile = optarg;
|
|
|
|
|
|
|
|
policystream = fopen(policyfile, "r");
|
|
|
|
if (!policystream) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error opening %s: %s\n",
|
|
|
|
policyfile, strerror(errno));
|
2013-10-11 14:37:44 +00:00
|
|
|
exit(-1);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
__fsetlocking(policystream,
|
|
|
|
FSETLOCKING_BYCALLER);
|
|
|
|
|
2016-07-26 08:44:44 +00:00
|
|
|
if (sepol_set_policydb_from_file(policystream)
|
|
|
|
< 0) {
|
2008-08-19 19:30:36 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"Error reading policy %s: %s\n",
|
|
|
|
policyfile, strerror(errno));
|
2013-10-11 14:37:44 +00:00
|
|
|
exit(-1);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
fclose(policystream);
|
|
|
|
|
|
|
|
ctx_validate = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 'e':
|
Patch setfiles to only warn if add_remove fails to lstat on user initiated excludes.
On Tue, 2009-08-11 at 08:12 -0400, Daniel J Walsh wrote:
> On 08/10/2009 04:12 PM, Stephen Smalley wrote:
> > On Mon, 2009-08-10 at 16:03 -0400, Stephen Smalley wrote:
> >> On Mon, 2009-08-10 at 11:13 -0400, Daniel J Walsh wrote:
> >>> Currently in F12 if you have file systems that root can not read
> >>>
> >>> # restorecon -R -v /var/lib/libvirt/
> >>> Can't stat directory "/home/dwalsh/.gvfs", Permission denied.
> >>> Can't stat directory "/home/dwalsh/redhat", Permission denied.
> >>>
> >>> After patch
> >>>
> >>> # ./restorecon -R -v /var/lib/libvirt/
> >>
> >> But if you were to run
> >> ./restorecon -R /home/dwalsh
> >> that would try to descend into .gvfs and redhat, right?
> >>
> >> I think you want instead to ignore the lstat error if the error was
> >> permission denied and add the entry to the exclude list so that
> >> restorecon will not try to descend into it. It is ok to exclude a
> >> directory to which you lack permission. Try this:
> >
> > Also, why limit -e to only directories? Why not let the user exclude
> > individual files if they choose to do so? In which case we could drop
> > the mode test altogether, and possibly drop the lstat() call altogether?
> > Or if you truly want to warn the user about non-existent paths, then
> > take the lstat() and warning to the 'e' option processing in main()
> > instead of doing it inside of add_exclude().
> >
> I agree lets remove the directory check and warn on non existing files.
Does this handle it correctly for you?
Remove the directory check for the -e option and only apply the
existence test to user-specified entries. Also ignore permission denied
errors as it is ok to exclude a directory or file to which the caller
lacks permission.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
2009-08-11 13:33:29 +00:00
|
|
|
if (lstat(optarg, &sb) < 0 && errno != EACCES) {
|
|
|
|
fprintf(stderr, "Can't stat exclude path \"%s\", %s - ignoring.\n",
|
|
|
|
optarg, strerror(errno));
|
|
|
|
break;
|
|
|
|
}
|
2016-07-26 08:44:44 +00:00
|
|
|
add_exclude(optarg);
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
use_input_file = 1;
|
|
|
|
input_filename = optarg;
|
2016-07-26 08:44:44 +00:00
|
|
|
break;
|
2008-08-19 19:30:36 +00:00
|
|
|
case 'd':
|
2012-08-22 07:13:43 +00:00
|
|
|
if (iamrestorecon)
|
|
|
|
usage(argv[0]);
|
2009-09-10 18:54:35 +00:00
|
|
|
r_opts.debug = 1;
|
2016-07-26 08:44:44 +00:00
|
|
|
r_opts.log_matches =
|
|
|
|
SELINUX_RESTORECON_LOG_MATCHES;
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 'i':
|
2016-07-26 08:44:44 +00:00
|
|
|
r_opts.ignore_noent =
|
|
|
|
SELINUX_RESTORECON_IGNORE_NOENTRY;
|
|
|
|
break;
|
|
|
|
case 'I': /* Force label check by ignoring directory digest. */
|
|
|
|
r_opts.ignore_digest =
|
|
|
|
SELINUX_RESTORECON_IGNORE_DIGEST;
|
2016-09-30 16:12:28 +00:00
|
|
|
request_digest = 1;
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
2016-09-25 14:49:32 +00:00
|
|
|
case 'D': /*
|
2016-09-30 15:03:06 +00:00
|
|
|
* Request file_contexts digest in selabel_open
|
|
|
|
* This will effectively enable usage of the
|
2016-09-25 14:49:32 +00:00
|
|
|
* security.restorecon_last extended attribute.
|
|
|
|
*/
|
2016-09-30 15:03:06 +00:00
|
|
|
request_digest = 1;
|
|
|
|
break;
|
2008-08-19 19:30:36 +00:00
|
|
|
case 'l':
|
2016-07-26 08:44:44 +00:00
|
|
|
r_opts.syslog_changes =
|
|
|
|
SELINUX_RESTORECON_SYSLOG_CHANGES;
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 'F':
|
2016-07-26 08:44:44 +00:00
|
|
|
r_opts.set_specctx =
|
|
|
|
SELINUX_RESTORECON_SET_SPECFILE_CTX;
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
r_opts.ignore_mounts =
|
|
|
|
SELINUX_RESTORECON_IGNORE_MOUNTS;
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 'n':
|
2016-07-26 08:44:44 +00:00
|
|
|
r_opts.nochange = SELINUX_RESTORECON_NOCHANGE;
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
2016-07-26 08:44:44 +00:00
|
|
|
case 'o': /* Deprecated */
|
2017-01-27 12:47:49 +00:00
|
|
|
fprintf(stderr, "%s: -o option no longer supported\n",
|
|
|
|
r_opts.progname);
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 'q':
|
2016-07-26 08:44:44 +00:00
|
|
|
/* Deprecated - Was only used to say whether print
|
|
|
|
* filespec_eval() params. Now uses verbose flag.
|
|
|
|
*/
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 'R':
|
|
|
|
case 'r':
|
|
|
|
if (iamrestorecon) {
|
2016-07-26 08:44:44 +00:00
|
|
|
r_opts.recurse = SELINUX_RESTORECON_RECURSE;
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
}
|
2016-07-26 08:44:44 +00:00
|
|
|
|
|
|
|
if (lstat(optarg, &sb) < 0 && errno != EACCES) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Can't stat alt_root_path \"%s\", %s\n",
|
|
|
|
optarg, strerror(errno));
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r_opts.rootpath) {
|
2008-08-19 19:30:36 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"%s: only one -r can be specified\n",
|
|
|
|
argv[0]);
|
2013-10-11 14:37:44 +00:00
|
|
|
exit(-1);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
2015-04-16 15:22:22 +00:00
|
|
|
set_rootpath(optarg);
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
use_input_file = 1;
|
|
|
|
input_filename = "-";
|
2009-09-10 18:54:35 +00:00
|
|
|
r_opts.add_assoc = 0;
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 'v':
|
2009-09-10 18:54:35 +00:00
|
|
|
if (r_opts.progress) {
|
2008-08-19 19:30:36 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"Progress and Verbose mutually exclusive\n");
|
2016-07-26 08:44:44 +00:00
|
|
|
usage(argv[0]);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
2016-07-26 08:44:44 +00:00
|
|
|
r_opts.verbose = SELINUX_RESTORECON_VERBOSE;
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 'p':
|
2009-09-10 18:54:35 +00:00
|
|
|
if (r_opts.verbose) {
|
2008-08-19 19:30:36 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"Progress and Verbose mutually exclusive\n");
|
|
|
|
usage(argv[0]);
|
|
|
|
}
|
2016-07-26 08:44:44 +00:00
|
|
|
r_opts.progress = SELINUX_RESTORECON_PROGRESS;
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case 'W':
|
2016-07-26 08:44:44 +00:00
|
|
|
warn_no_match = 1; /* Print selabel_stats() */
|
2008-08-19 19:30:36 +00:00
|
|
|
break;
|
|
|
|
case '0':
|
|
|
|
null_terminated = 1;
|
|
|
|
break;
|
2012-08-22 07:13:43 +00:00
|
|
|
case 'h':
|
2008-08-19 19:30:36 +00:00
|
|
|
case '?':
|
|
|
|
usage(argv[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-03 16:56:39 +00:00
|
|
|
for (i = optind; i < argc; i++) {
|
2016-07-26 08:44:44 +00:00
|
|
|
if (!strcmp(argv[i], "/"))
|
2017-01-27 12:47:49 +00:00
|
|
|
r_opts.mass_relabel = SELINUX_RESTORECON_MASS_RELABEL;
|
2012-02-03 16:56:39 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 19:34:17 +00:00
|
|
|
cb.func_log = log_callback;
|
|
|
|
selinux_set_callback(SELINUX_CB_LOG, cb);
|
|
|
|
|
2008-08-19 19:30:36 +00:00
|
|
|
if (!iamrestorecon) {
|
|
|
|
if (policyfile) {
|
|
|
|
if (optind != (argc - 1))
|
|
|
|
usage(argv[0]);
|
|
|
|
} else if (use_input_file) {
|
|
|
|
if (optind != (argc - 1)) {
|
|
|
|
/* Cannot mix with pathname arguments. */
|
|
|
|
usage(argv[0]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (optind > (argc - 2))
|
|
|
|
usage(argv[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Use our own invalid context checking function so that
|
2016-07-26 08:44:44 +00:00
|
|
|
* we can support either checking against the active policy or
|
|
|
|
* checking against a binary policy file.
|
|
|
|
*/
|
2017-01-24 19:34:17 +00:00
|
|
|
cb.func_validate = canoncon;
|
|
|
|
selinux_set_callback(SELINUX_CB_VALIDATE, cb);
|
2008-08-19 19:30:36 +00:00
|
|
|
|
|
|
|
if (stat(argv[optind], &sb) < 0) {
|
|
|
|
perror(argv[optind]);
|
2013-10-11 14:37:44 +00:00
|
|
|
exit(-1);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
if (!S_ISREG(sb.st_mode)) {
|
|
|
|
fprintf(stderr, "%s: spec file %s is not a regular file.\n",
|
|
|
|
argv[0], argv[optind]);
|
2013-10-11 14:37:44 +00:00
|
|
|
exit(-1);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
altpath = argv[optind];
|
|
|
|
optind++;
|
2012-08-22 07:13:43 +00:00
|
|
|
} else if (argc == 1)
|
|
|
|
usage(argv[0]);
|
2008-08-19 19:30:36 +00:00
|
|
|
|
2016-09-25 14:49:32 +00:00
|
|
|
/* Set selabel_open options. */
|
2009-09-10 18:54:35 +00:00
|
|
|
r_opts.selabel_opt_validate = (ctx_validate ? (char *)1 : NULL);
|
2016-09-25 14:49:32 +00:00
|
|
|
r_opts.selabel_opt_digest = (request_digest ? (char *)1 : NULL);
|
2009-09-10 18:54:35 +00:00
|
|
|
r_opts.selabel_opt_path = altpath;
|
2008-08-19 19:30:36 +00:00
|
|
|
|
|
|
|
if (nerr)
|
2013-10-11 14:37:44 +00:00
|
|
|
exit(-1);
|
2008-08-19 19:30:36 +00:00
|
|
|
|
2009-09-10 18:54:35 +00:00
|
|
|
restore_init(&r_opts);
|
2016-07-26 08:44:44 +00:00
|
|
|
|
2008-08-19 19:30:36 +00:00
|
|
|
if (use_input_file) {
|
|
|
|
FILE *f = stdin;
|
|
|
|
ssize_t len;
|
|
|
|
int delim;
|
2016-07-26 08:44:44 +00:00
|
|
|
|
2008-08-19 19:30:36 +00:00
|
|
|
if (strcmp(input_filename, "-") != 0)
|
|
|
|
f = fopen(input_filename, "r");
|
2016-07-26 08:44:44 +00:00
|
|
|
|
2008-08-19 19:30:36 +00:00
|
|
|
if (f == NULL) {
|
2016-07-26 08:44:44 +00:00
|
|
|
fprintf(stderr, "Unable to open %s: %s\n",
|
|
|
|
input_filename,
|
2008-08-19 19:30:36 +00:00
|
|
|
strerror(errno));
|
|
|
|
usage(argv[0]);
|
|
|
|
}
|
|
|
|
__fsetlocking(f, FSETLOCKING_BYCALLER);
|
|
|
|
|
|
|
|
delim = (null_terminated != 0) ? '\0' : '\n';
|
|
|
|
while ((len = getdelim(&buf, &buf_len, delim, f)) > 0) {
|
|
|
|
buf[len - 1] = 0;
|
2009-09-10 18:54:35 +00:00
|
|
|
if (!strcmp(buf, "/"))
|
2017-01-27 12:47:49 +00:00
|
|
|
r_opts.mass_relabel = SELINUX_RESTORECON_MASS_RELABEL;
|
2016-07-26 08:44:44 +00:00
|
|
|
errors |= process_glob(buf, &r_opts) < 0;
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
|
|
|
if (strcmp(input_filename, "-") != 0)
|
|
|
|
fclose(f);
|
|
|
|
} else {
|
2012-02-03 16:56:39 +00:00
|
|
|
for (i = optind; i < argc; i++)
|
2016-07-26 08:44:44 +00:00
|
|
|
errors |= process_glob(argv[i], &r_opts) < 0;
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|
2016-07-26 08:44:44 +00:00
|
|
|
|
2017-01-27 12:47:49 +00:00
|
|
|
maybe_audit_mass_relabel(r_opts.mass_relabel, errors);
|
2008-08-19 19:30:36 +00:00
|
|
|
|
|
|
|
if (warn_no_match)
|
2009-09-10 18:54:35 +00:00
|
|
|
selabel_stats(r_opts.hnd);
|
2008-08-19 19:30:36 +00:00
|
|
|
|
2009-09-10 18:54:35 +00:00
|
|
|
selabel_close(r_opts.hnd);
|
|
|
|
restore_finish();
|
2008-08-19 19:30:36 +00:00
|
|
|
|
2017-01-27 12:47:49 +00:00
|
|
|
if (r_opts.progress)
|
|
|
|
fprintf(stdout, "\n");
|
2008-08-19 19:30:36 +00:00
|
|
|
|
2016-07-26 08:44:44 +00:00
|
|
|
exit(errors ? -1 : 0);
|
2008-08-19 19:30:36 +00:00
|
|
|
}
|