@@ -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.
@@ -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
@@ -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 &
Signed-off-by: Chris PeBenito <chpebeni@linux.microsoft.com> --- 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(-)