Signed-off-by: Chris PeBenito <chpebeni@xxxxxxxxxxxxxxxxxxx> --- libselinux/include/selinux/restorecon.h | 37 ++++++++++++++---------- libselinux/man/man3/selinux_restorecon.3 | 4 +++ libselinux/src/selinux_restorecon.c | 13 +++++++-- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/libselinux/include/selinux/restorecon.h b/libselinux/include/selinux/restorecon.h index 754b8645..466de39a 100644 --- a/libselinux/include/selinux/restorecon.h +++ b/libselinux/include/selinux/restorecon.h @@ -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. diff --git a/libselinux/man/man3/selinux_restorecon.3 b/libselinux/man/man3/selinux_restorecon.3 index f6e5f2d7..ad637406 100644 --- a/libselinux/man/man3/selinux_restorecon.3 +++ b/libselinux/man/man3/selinux_restorecon.3 @@ -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 diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c index 028d8924..91dfeb66 100644 --- a/libselinux/src/selinux_restorecon.c +++ b/libselinux/src/selinux_restorecon.c @@ -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 & -- 2.21.1