_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
const char *tclass, *scon;
- struct audit_info audit_info = {};
_cleanup_free_ char *cl = NULL;
- char *fcon = NULL;
+ _cleanup_freecon_ char *fcon = NULL;
char **cmdline = NULL;
+ bool enforce = false; /* Will be set to the real value later if needed */
int r = 0;
assert(message);
SD_BUS_CREDS_AUGMENT /* get more bits from /proc */,
&creds);
if (r < 0)
- goto finish;
+ return r;
/* The SELinux context is something we really should have
* gotten directly from the message or sender, and not be an
r = sd_bus_creds_get_selinux_context(creds, &scon);
if (r < 0)
- goto finish;
+ return r;
if (path) {
/* Get the file context of the unit file */
- r = getfilecon_raw(path, &fcon);
- if (r < 0) {
- log_warning_errno(errno, "SELinux getfilecon_raw on '%s' failed (perm=%s): %m", path, permission);
- r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
- goto finish;
+ if (getfilecon_raw(path, &fcon) < 0) {
+ r = -errno;
+ enforce = security_getenforce() > 0;
+
+ log_warning_errno(r, "SELinux getfilecon_raw on '%s' failed%s (perm=%s): %m",
+ path,
+ enforce ? "" : ", ignoring",
+ permission);
+ if (!enforce)
+ return 0;
+
+ return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
}
tclass = "service";
+
} else {
- r = getcon_raw(&fcon);
- if (r < 0) {
- log_warning_errno(errno, "SELinux getcon_raw failed (perm=%s): %m", permission);
- r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
- goto finish;
+ if (getcon_raw(&fcon) < 0) {
+ r = -errno;
+ enforce = security_getenforce() > 0;
+
+ log_warning_errno(r, "SELinux getcon_raw failed%s (perm=%s): %m",
+ enforce ? "" : ", ignoring",
+ permission);
+ if (!enforce)
+ return 0;
+
+ return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
}
tclass = "system";
sd_bus_creds_get_cmdline(creds, &cmdline);
cl = strv_join(cmdline, " ");
- audit_info.creds = creds;
- audit_info.path = path;
- audit_info.cmdline = cl;
+ struct audit_info audit_info = {
+ .creds = creds,
+ .path = path,
+ .cmdline = cl,
+ };
r = selinux_check_access(scon, fcon, tclass, permission, &audit_info);
- if (r < 0)
- r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
-
- log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, cl, r);
-
-finish:
- freecon(fcon);
+ if (r < 0) {
+ r = errno_or_else(EPERM);
+ enforce = security_getenforce() > 0;
- if (r < 0 && security_getenforce() != 1) {
- sd_bus_error_free(error);
- r = 0;
+ if (enforce)
+ sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
}
- return r;
+ log_debug_errno(r, "SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %m",
+ scon, fcon, tclass, permission, path, cl);
+ return enforce ? r : 0;
}
#else