X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fselinux-access.c;h=f6389584f75ae4a77bb7fffd9c1a9eaea70eaea1;hp=0ecbdf0be6bb2ae21c2577d1adad83ae4aeadfae;hb=05bae4a60c32e29797597979cee2f3684eb3bc1e;hpb=718db96199eb307751264e4163555662c9a389fa diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c index 0ecbdf0be..f6389584f 100644 --- a/src/core/selinux-access.c +++ b/src/core/selinux-access.c @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef HAVE_AUDIT #include #endif @@ -40,94 +41,19 @@ #include "audit.h" #include "selinux-util.h" #include "audit-fd.h" +#include "strv.h" static bool initialized = false; -struct auditstruct { +struct audit_info { + sd_bus_creds *creds; const char *path; - char *cmdline; - uid_t loginuid; - uid_t uid; - gid_t gid; + const char *cmdline; }; -static int bus_get_selinux_security_context( - sd_bus *bus, - const char *name, - sd_bus_error *error, - char **ret) { - - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - const void *p; - size_t sz; - char *b; - int r; - - assert(bus); - assert(name); - assert(ret); - - r = sd_bus_call_method( - bus, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "GetConnectionSELinuxSecurityContext", - error, &m, - "s", name); - if (r < 0) - return r; - - r = sd_bus_message_read_array(m, 'y', &p, &sz); - if (r < 0) - return r; - - b = strndup(p, sz); - if (!b) - return -ENOMEM; - - *ret = b; - return 0; -} - -static int bus_get_audit_data( - sd_bus *bus, - const char *name, - struct auditstruct *audit) { - - pid_t pid; - int r; - - assert(bus); - assert(name); - assert(audit); - - r = sd_bus_get_owner_pid(bus, name, &pid); - if (r < 0) - return r; - - r = audit_loginuid_from_pid(pid, &audit->loginuid); - if (r < 0) - return r; - - r = get_process_uid(pid, &audit->uid); - if (r < 0) - return r; - - r = get_process_gid(pid, &audit->gid); - if (r < 0) - return r; - - r = get_process_cmdline(pid, 0, true, &audit->cmdline); - if (r < 0) - return r; - - return 0; -} - /* Any time an access gets denied this callback will be called - with the aduit data. We then need to just copy the audit data into the msgbuf. + with the audit data. We then need to just copy the audit data into the msgbuf. */ static int audit_callback( void *auditdata, @@ -135,19 +61,25 @@ static int audit_callback( char *msgbuf, size_t msgbufsize) { - struct auditstruct *audit = (struct auditstruct *) auditdata; + const struct audit_info *audit = auditdata; + uid_t uid = 0, login_uid = 0; + gid_t gid = 0; + char login_uid_buf[DECIMAL_STR_MAX(uid_t)] = "n/a"; + char uid_buf[DECIMAL_STR_MAX(uid_t)] = "n/a"; + char gid_buf[DECIMAL_STR_MAX(gid_t)] = "n/a"; + + if (sd_bus_creds_get_audit_login_uid(audit->creds, &login_uid) >= 0) + snprintf(login_uid_buf, sizeof(login_uid_buf), UID_FMT, login_uid); + if (sd_bus_creds_get_euid(audit->creds, &uid) >= 0) + snprintf(uid_buf, sizeof(uid_buf), UID_FMT, uid); + if (sd_bus_creds_get_egid(audit->creds, &gid) >= 0) + snprintf(gid_buf, sizeof(gid_buf), GID_FMT, gid); snprintf(msgbuf, msgbufsize, - "auid=%d uid=%d gid=%d%s%s%s%s%s%s", - audit->loginuid, - audit->uid, - audit->gid, - (audit->path ? " path=\"" : ""), - strempty(audit->path), - (audit->path ? "\"" : ""), - (audit->cmdline ? " cmdline=\"" : ""), - strempty(audit->cmdline), - (audit->cmdline ? "\"" : "")); + "auid=%s uid=%s gid=%s%s%s%s%s%s%s", + login_uid_buf, uid_buf, gid_buf, + audit->path ? " path=\"" : "", strempty(audit->path), audit->path ? "\"" : "", + audit->cmdline ? " cmdline=\"" : "", strempty(audit->cmdline), audit->cmdline ? "\"" : ""); msgbuf[msgbufsize-1] = 0; @@ -163,13 +95,12 @@ static int audit_callback( _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - #ifdef HAVE_AUDIT if (get_audit_fd() >= 0) { _cleanup_free_ char *buf = NULL; int r; + va_start(ap, fmt); r = vasprintf(&buf, fmt, ap); va_end(ap); @@ -177,11 +108,11 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) { audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0); return 0; } - - va_start(ap, fmt); } #endif - log_metav(LOG_USER | LOG_INFO, __FILE__, __LINE__, __FUNCTION__, fmt, ap); + + va_start(ap, fmt); + log_internalv(LOG_AUTH | LOG_INFO, 0, __FILE__, __LINE__, __FUNCTION__, fmt, ap); va_end(ap); return 0; @@ -195,10 +126,8 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) { static int access_init(void) { int r = 0; - if (avc_open(NULL, 0)) { - log_error("avc_open() failed: %m"); - return -errno; - } + if (avc_open(NULL, 0)) + return log_error_errno(errno, "avc_open() failed: %m"); selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback); selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback); @@ -211,13 +140,13 @@ static int access_init(void) { return r; } -static int selinux_access_init(sd_bus_error *error) { +static int mac_selinux_access_init(sd_bus_error *error) { int r; if (initialized) return 0; - if (!use_selinux()) + if (!mac_selinux_use()) return 0; r = access_init(); @@ -227,84 +156,17 @@ static int selinux_access_init(sd_bus_error *error) { initialized = true; return 0; } +#endif -void selinux_access_free(void) { +void mac_selinux_access_free(void) { +#ifdef HAVE_SELINUX if (!initialized) return; avc_destroy(); initialized = false; -} - -static int get_audit_data( - sd_bus *bus, - sd_bus_message *message, - struct auditstruct *audit) { - - struct ucred ucred; - const char *sender; - socklen_t len; - int r, fd; - - sender = sd_bus_message_get_sender(message); - if (sender) - return bus_get_audit_data(bus, sender, audit); - - fd = sd_bus_get_fd(bus); - if (fd < 0) - return fd; - - len = sizeof(ucred); - r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len); - if (r < 0) - return -errno; - - audit->uid = ucred.uid; - audit->gid = ucred.gid; - - r = audit_loginuid_from_pid(ucred.pid, &audit->loginuid); - if (r < 0) - return r; - - r = get_process_cmdline(ucred.pid, 0, true, &audit->cmdline); - if (r < 0) - return r; - - return 0; -} - -/* - This function returns the security context of the remote end of the dbus - connections. Whether it is on the bus or a local connection. -*/ -static int get_calling_context( - sd_bus *bus, - sd_bus_message *message, - sd_bus_error *error, - security_context_t *ret) { - - const char *sender; - int r, fd; - - /* - If sender exists then - if sender is NULL this indicates a local connection. Grab the fd - from dbus and do an getpeercon to peers process context - */ - sender = sd_bus_message_get_sender(message); - if (sender) - return bus_get_selinux_security_context(bus, sender, error, ret); - - fd = sd_bus_get_fd(bus); - if (fd < 0) - return fd; - - r = getpeercon(fd, ret); - if (r < 0) - return -errno; - - return 0; +#endif } /* @@ -313,36 +175,43 @@ static int get_calling_context( If the machine is in permissive mode it will return ok. Audit messages will still be generated if the access would be denied in enforcing mode. */ -int selinux_access_check( - sd_bus *bus, +int mac_selinux_generic_access_check( sd_bus_message *message, const char *path, const char *permission, sd_bus_error *error) { - security_context_t scon = NULL, fcon = NULL; - const char *tclass = NULL; - struct auditstruct audit; +#ifdef HAVE_SELINUX + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + const char *tclass = NULL, *scon = NULL; + struct audit_info audit_info = {}; + _cleanup_free_ char *cl = NULL; + security_context_t fcon = NULL; + char **cmdline = NULL; int r = 0; - assert(bus); assert(message); assert(permission); assert(error); - if (!use_selinux()) + if (!mac_selinux_use()) return 0; - r = selinux_access_init(error); + r = mac_selinux_access_init(error); if (r < 0) return r; - audit.uid = audit.loginuid = (uid_t) -1; - audit.gid = (gid_t) -1; - audit.cmdline = NULL; - audit.path = path; + r = sd_bus_query_sender_creds( + message, + SD_BUS_CREDS_PID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID| + SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_AUDIT_LOGIN_UID| + SD_BUS_CREDS_SELINUX_CONTEXT| + SD_BUS_CREDS_AUGMENT /* get more bits from /proc */, + &creds); + if (r < 0) + goto finish; - r = get_calling_context(bus, message, error, &scon); + r = sd_bus_creds_get_selinux_context(creds, &scon); if (r < 0) goto finish; @@ -366,41 +235,51 @@ int selinux_access_check( tclass = "system"; } - get_audit_data(bus, message, &audit); + sd_bus_creds_get_cmdline(creds, &cmdline); + cl = strv_join(cmdline, " "); - errno = 0; - r = selinux_check_access(scon, fcon, tclass, permission, &audit); + audit_info.creds = creds; + audit_info.path = path; + audit_info.cmdline = cl; + + r = selinux_check_access((security_context_t) 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, audit.cmdline, r); + 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: - free(audit.cmdline); - freecon(scon); freecon(fcon); - if (r && security_getenforce() != 1) { + if (r < 0 && security_getenforce() != 1) { sd_bus_error_free(error); r = 0; } return r; -} - #else - -int selinux_access_check( - sd_bus *bus, - sd_bus_message *message, - const char *path, - const char *permission, - sd_bus_error *error) { - return 0; +#endif } -void selinux_access_free(void) { -} +int mac_selinux_unit_access_check_strv(char **units, + sd_bus_message *message, + Manager *m, + const char *permission, + sd_bus_error *error) { +#ifdef HAVE_SELINUX + char **i; + Unit *u; + int r; + STRV_FOREACH(i, units) { + u = manager_get_unit(m, *i); + if (u) { + r = mac_selinux_unit_access_check(u, message, permission, error); + if (r < 0) + return r; + } + } #endif + return 0; +}