libselinux: Add selinux_restorecon option to treat conflicting specifications as an error.

Signed-off-by: Chris PeBenito <chpebeni@linux.microsoft.com>
This commit is contained in:
Chris PeBenito 2020-04-02 11:45:08 -04:00 committed by Nicolas Iooss
parent aa40067b7b
commit ec85260057
No known key found for this signature in database
GPG Key ID: C191415F340DAAA0
3 changed files with 36 additions and 18 deletions

View File

@ -30,77 +30,82 @@ extern int selinux_restorecon(const char *pathname,
* Force the checking of labels even if the stored SHA1 digest
* matches the specfiles SHA1 digest (requires CAP_SYS_ADMIN).
*/
#define SELINUX_RESTORECON_IGNORE_DIGEST 0x0001
#define SELINUX_RESTORECON_IGNORE_DIGEST 0x00001
/*
* Do not change file labels.
*/
#define SELINUX_RESTORECON_NOCHANGE 0x0002
#define SELINUX_RESTORECON_NOCHANGE 0x00002
/*
* If set, change file label to that in spec file.
* If not, only change type component to that in spec file.
*/
#define SELINUX_RESTORECON_SET_SPECFILE_CTX 0x0004
#define SELINUX_RESTORECON_SET_SPECFILE_CTX 0x00004
/*
* Recursively descend directories.
*/
#define SELINUX_RESTORECON_RECURSE 0x0008
#define SELINUX_RESTORECON_RECURSE 0x00008
/*
* Log changes to selinux log. Note that if VERBOSE and
* PROGRESS are set, then PROGRESS will take precedence.
*/
#define SELINUX_RESTORECON_VERBOSE 0x0010
#define SELINUX_RESTORECON_VERBOSE 0x00010
/*
* If SELINUX_RESTORECON_PROGRESS is true and
* SELINUX_RESTORECON_MASS_RELABEL is true, then output approx % complete,
* else output the number of files in 1k blocks processed to stdout.
*/
#define SELINUX_RESTORECON_PROGRESS 0x0020
#define SELINUX_RESTORECON_PROGRESS 0x00020
/*
* Convert passed-in pathname to canonical pathname.
*/
#define SELINUX_RESTORECON_REALPATH 0x0040
#define SELINUX_RESTORECON_REALPATH 0x00040
/*
* Prevent descending into directories that have a different
* device number than the pathname from which the descent began.
*/
#define SELINUX_RESTORECON_XDEV 0x0080
#define SELINUX_RESTORECON_XDEV 0x00080
/*
* Attempt to add an association between an inode and a specification.
* If there is already an association for the inode and it conflicts
* with the specification, then use the last matching specification.
*/
#define SELINUX_RESTORECON_ADD_ASSOC 0x0100
#define SELINUX_RESTORECON_ADD_ASSOC 0x00100
/*
* Abort on errors during the file tree walk.
*/
#define SELINUX_RESTORECON_ABORT_ON_ERROR 0x0200
#define SELINUX_RESTORECON_ABORT_ON_ERROR 0x00200
/*
* Log any label changes to syslog.
*/
#define SELINUX_RESTORECON_SYSLOG_CHANGES 0x0400
#define SELINUX_RESTORECON_SYSLOG_CHANGES 0x00400
/*
* Log what spec matched each file.
*/
#define SELINUX_RESTORECON_LOG_MATCHES 0x0800
#define SELINUX_RESTORECON_LOG_MATCHES 0x00800
/*
* Ignore files that do not exist.
*/
#define SELINUX_RESTORECON_IGNORE_NOENTRY 0x1000
#define SELINUX_RESTORECON_IGNORE_NOENTRY 0x01000
/*
* Do not read /proc/mounts to obtain a list of non-seclabel
* mounts to be excluded from relabeling checks.
*/
#define SELINUX_RESTORECON_IGNORE_MOUNTS 0x2000
#define SELINUX_RESTORECON_IGNORE_MOUNTS 0x02000
/*
* Set if there is a mass relabel required.
* See SELINUX_RESTORECON_PROGRESS flag for details.
*/
#define SELINUX_RESTORECON_MASS_RELABEL 0x4000
#define SELINUX_RESTORECON_MASS_RELABEL 0x04000
/*
* Set if no digest is to be read or written (as only processes
* running with CAP_SYS_ADMIN can read/write digests).
*/
#define SELINUX_RESTORECON_SKIP_DIGEST 0x8000
#define SELINUX_RESTORECON_SKIP_DIGEST 0x08000
/*
* Set to treat conflicting specifications as errors.
*/
#define SELINUX_RESTORECON_CONFLICT_ERROR 0x10000
/**
* selinux_restorecon_set_sehandle - Set the global fc handle.

View File

@ -152,6 +152,10 @@ Setting
.B SELINUX_RESTORECON_IGNORE_MOUNTS
is useful where there is a non-seclabel fs mounted with a seclabel fs mounted
on a directory below this.
.sp
.B SELINUX_RESTORECON_CONFLICT_ERROR
to treat conflicting specifications, such as where two hardlinks for the
same inode have different contexts, as errors.
.RE
.sp
The behavior regarding the checking and updating of the SHA1 digest described

View File

@ -81,6 +81,7 @@ struct rest_flags {
bool log_matches;
bool ignore_noent;
bool warnonnomatch;
bool conflicterror;
};
static void restorecon_init(void)
@ -418,7 +419,8 @@ static file_spec_t *fl_head;
* different context that matched the inode, then use the first context
* that matched.
*/
static int filespec_add(ino_t ino, const char *con, const char *file)
static int filespec_add(ino_t ino, const char *con, const char *file,
struct rest_flags *flags)
{
file_spec_t *prevfl, *fl;
int h, ret;
@ -458,6 +460,11 @@ static int filespec_add(ino_t ino, const char *con, const char *file)
fl->file = strdup(file);
if (!fl->file)
goto oom;
if (flags->conflicterror) {
selinux_log(SELINUX_ERROR,
"treating conflicting specifications as an error.\n");
return -1;
}
return 1;
}
@ -645,7 +652,7 @@ static int restorecon_sb(const char *pathname, const struct stat *sb,
}
if (flags->add_assoc) {
rc = filespec_add(sb->st_ino, newcon, pathname);
rc = filespec_add(sb->st_ino, newcon, pathname, flags);
if (rc < 0) {
selinux_log(SELINUX_ERROR,
@ -833,6 +840,8 @@ int selinux_restorecon(const char *pathname_orig,
flags.ignore_noent = (restorecon_flags &
SELINUX_RESTORECON_IGNORE_NOENTRY) ? true : false;
flags.warnonnomatch = true;
flags.conflicterror = (restorecon_flags &
SELINUX_RESTORECON_CONFLICT_ERROR) ? true : false;
ignore_mounts = (restorecon_flags &
SELINUX_RESTORECON_IGNORE_MOUNTS) ? true : false;
bool ignore_digest = (restorecon_flags &