selinux-access.c revision 8fd00193803fd20bed163832ec4d0d5ba2958b87
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering This file is part of systemd.
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering Copyright 2012 Dan Walsh
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering systemd is free software; you can redistribute it and/or modify it
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering under the terms of the GNU Lesser General Public License as published by
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering (at your option) any later version.
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering systemd is distributed in the hope that it will be useful, but
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering Lesser General Public License for more details.
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering You should have received a copy of the GNU Lesser General Public License
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic bool initialized = false;
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering Any time an access gets denied this callback will be called
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering with the audit data. We then need to just copy the audit data into the msgbuf.
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering const struct audit_info *audit = auditdata;
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering char login_uid_buf[DECIMAL_STR_MAX(uid_t)] = "n/a";
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering char uid_buf[DECIMAL_STR_MAX(uid_t)] = "n/a";
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering char gid_buf[DECIMAL_STR_MAX(gid_t)] = "n/a";
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (sd_bus_creds_get_audit_login_uid(audit->creds, &login_uid) >= 0)
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering snprintf(login_uid_buf, sizeof(login_uid_buf), UID_FMT, login_uid);
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (sd_bus_creds_get_uid(audit->creds, &uid) >= 0)
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering snprintf(uid_buf, sizeof(uid_buf), UID_FMT, uid);
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (sd_bus_creds_get_gid(audit->creds, &gid) >= 0)
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering snprintf(gid_buf, sizeof(gid_buf), GID_FMT, gid);
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering "auid=%s uid=%s gid=%s%s%s%s%s%s%s",
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering audit->path ? " path=\"" : "", strempty(audit->path), audit->path ? "\"" : "",
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering audit->cmdline ? " cmdline=\"" : "", strempty(audit->cmdline), audit->cmdline ? "\"" : "");
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering Any time an access gets denied this callback will be called
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering code copied from dbus. If audit is turned on the messages will go as
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering user_avc's into the /var/log/audit/audit.log, otherwise they will be
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering sent to syslog.
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering_printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0);
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering log_metav(LOG_USER | LOG_INFO, __FILE__, __LINE__, __FUNCTION__, fmt, ap);
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering Function must be called once to initialize the SELinux AVC environment.
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering Sets up callbacks.
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering If you want to cleanup memory you should need to call selinux_access_finish.
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int access_init(void) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback);
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback);
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int mac_selinux_access_init(sd_bus_error *error) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to initialize SELinux.");
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering This function communicates with the kernel to check whether or not it should
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering allow the access.
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering If the machine is in permissive mode it will return ok. Audit messages will
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering still be generated if the access would be denied in enforcing mode.
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_AUDIT_LOGIN_UID|
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering SD_BUS_CREDS_AUGMENT /* get more bits from /proc */,
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek r = sd_bus_creds_get_selinux_context(creds, &scon);
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek /* Get the file context of the unit file */
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering sd_bus_creds_get_cmdline(creds, &cmdline);
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek r = selinux_check_access((security_context_t) scon, fcon, tclass, permission, &audit_info);
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering 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);
be3f52f4ed02a9256b1577719677b32a17b525acLennart Poettering if (r < 0 && security_getenforce() != 1) {
be3f52f4ed02a9256b1577719677b32a17b525acLennart Poetteringint mac_selinux_unit_access_check_strv(char **units,