static int audit_set_enabled(int state, uid_t loginuid, u32 sid) { int old = audit_enabled; if (state != 0 && state != 1) return -EINVAL; if (sid) { char *ctx = NULL; u32 len; int rc; if ((rc = selinux_ctxid_to_string(sid, &ctx, &len))) return rc; else audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_enabled=%d old=%d by auid=%u subj=%s", state, old, loginuid, ctx); kfree(ctx); } else audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_enabled=%d old=%d by auid=%u", state, old, loginuid); audit_enabled = state; return 0; }
static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid) { int res, rc = 0, old = audit_backlog_limit; /* check if we are locked */ if (audit_enabled == 2) res = 0; else res = 1; if (sid) { char *ctx = NULL; u32 len; if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_backlog_limit=%d old=%d by auid=%u" " subj=%s res=%d", limit, old, loginuid, ctx, res); kfree(ctx); } else res = 0; /* Something weird, deny request */ } audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_backlog_limit=%d old=%d by auid=%u res=%d", limit, old, loginuid, res); /* If we are allowed, make the change */ if (res == 1) audit_backlog_limit = limit; /* Not allowed, update reason */ else if (rc == 0) rc = -EPERM; return rc; }
static int audit_set_failure(int state, uid_t loginuid, u32 sid) { int old = audit_failure; if (state != AUDIT_FAIL_SILENT && state != AUDIT_FAIL_PRINTK && state != AUDIT_FAIL_PANIC) return -EINVAL; if (sid) { char *ctx = NULL; u32 len; int rc; if ((rc = selinux_ctxid_to_string(sid, &ctx, &len))) return rc; else audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_failure=%d old=%d by auid=%u subj=%s", state, old, loginuid, ctx); kfree(ctx); } else audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_failure=%d old=%d by auid=%u", state, old, loginuid); audit_failure = state; return 0; }
/* Initialize audit support at boot time. */ static int __init audit_init(void) { int i; printk(KERN_INFO "audit: initializing netlink socket (%s)\n", audit_default ? "enabled" : "disabled"); audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive, THIS_MODULE); if (!audit_sock) audit_panic("cannot initialize netlink socket"); else audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; skb_queue_head_init(&audit_skb_queue); audit_initialized = 1; audit_enabled = audit_default; /* Register the callback with selinux. This callback will be invoked * when a new policy is loaded. */ selinux_audit_set_callback(&selinux_audit_rule_update); audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); #ifdef CONFIG_AUDITSYSCALL audit_ih = inotify_init(&audit_inotify_ops); if (IS_ERR(audit_ih)) audit_panic("cannot initialize inotify handle"); #endif for (i = 0; i < AUDIT_INODE_BUCKETS; i++) INIT_LIST_HEAD(&audit_inode_hash[i]); return 0; }
static ssize_t sel_write_load(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { ssize_t length; void *data = NULL; mutex_lock(&sel_mutex); length = task_has_security(current, SECURITY__LOAD_POLICY); if (length) goto out; /* No partial writes. */ length = -EINVAL; if (*ppos != 0) goto out; length = -EFBIG; if (count > 64 * 1024 * 1024) goto out; length = -ENOMEM; data = vmalloc(count); if (!data) goto out; length = -EFAULT; if (copy_from_user(data, buf, count) != 0) goto out; length = security_load_policy(data, count); if (length) goto out; length = sel_make_bools(); if (length) goto out1; length = sel_make_classes(); if (length) goto out1; length = sel_make_policycap(); if (length) goto out1; length = count; out1: audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, "policy loaded auid=%u ses=%u", audit_get_loginuid(current), audit_get_sessionid(current)); out: mutex_unlock(&sel_mutex); vfree(data); return length; }
int audit_set_backlog_limit(int limit) { int old = audit_backlog_limit; audit_backlog_limit = limit; audit_log(current->audit_context, "audit_backlog_limit=%d old=%d", audit_backlog_limit, old); return old; }
static int audit_set_backlog_limit(int limit, uid_t loginuid) { int old = audit_backlog_limit; audit_backlog_limit = limit; audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_backlog_limit=%d old=%d by auid=%u", audit_backlog_limit, old, loginuid); return old; }
int audit_set_enabled(int state) { int old = audit_enabled; if (state != 0 && state != 1) return -EINVAL; audit_enabled = state; audit_log(current->audit_context, "audit_enabled=%d old=%d", audit_enabled, old); return old; }
static int audit_set_enabled(int state, uid_t loginuid) { int old = audit_enabled; if (state != 0 && state != 1) return -EINVAL; audit_enabled = state; audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_enabled=%d old=%d by auid=%u", audit_enabled, old, loginuid); return old; }
/* Initialize audit support at boot time. */ int __init audit_init(void) { printk(KERN_INFO "audit: initializing WITHOUT netlink support\n"); audit_sock = NULL; audit_pid = 0; audit_initialized = 1; audit_enabled = audit_default; audit_log(NULL, "initialized"); return 0; }
int audit_set_failure(int state) { int old = audit_failure; if (state != AUDIT_FAIL_SILENT && state != AUDIT_FAIL_PRINTK && state != AUDIT_FAIL_PANIC) return -EINVAL; audit_failure = state; audit_log(current->audit_context, "audit_failure=%d old=%d", audit_failure, old); return old; }
static ssize_t sel_write_enforce(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char *page = NULL; ssize_t length; int new_value; length = -ENOMEM; if (count >= PAGE_SIZE) goto out; /* No partial writes. */ length = -EINVAL; if (*ppos != 0) goto out; length = -ENOMEM; page = (char *)get_zeroed_page(GFP_KERNEL); if (!page) goto out; length = -EFAULT; if (copy_from_user(page, buf, count)) goto out; length = -EINVAL; if (sscanf(page, "%d", &new_value) != 1) goto out; new_value = 0; if (new_value != selinux_enforcing) { length = task_has_security(current, SECURITY__SETENFORCE); if (length) goto out; audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, "enforcing=%d old_enforcing=%d auid=%u ses=%u", new_value, selinux_enforcing, from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); selinux_enforcing = new_value; if (selinux_enforcing) avc_ss_reset(0); selnl_notify_setenforce(selinux_enforcing); selinux_status_update_setenforce(selinux_enforcing); } length = count; out: free_page((unsigned long) page); return length; }
/* Initialize audit support at boot time. */ int __init audit_init(void) { printk(KERN_INFO "audit: initializing netlink socket (%s)\n", audit_default ? "enabled" : "disabled"); audit_sock = netlink_kernel_create(NETLINK_AUDIT, audit_receive); if (!audit_sock) audit_panic("cannot initialize netlink socket"); audit_initialized = 1; audit_enabled = audit_default; audit_log(NULL, "initialized"); return 0; }
static int audit_set_failure(int state, uid_t loginuid, u32 sid) { int res, rc = 0, old = audit_failure; if (state != AUDIT_FAIL_SILENT && state != AUDIT_FAIL_PRINTK && state != AUDIT_FAIL_PANIC) return -EINVAL; /* check if we are locked */ if (audit_enabled == 2) res = 0; else res = 1; if (sid) { char *ctx = NULL; u32 len; if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_failure=%d old=%d by auid=%u" " subj=%s res=%d", state, old, loginuid, ctx, res); kfree(ctx); } else res = 0; /* Something weird, deny request */ } audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_failure=%d old=%d by auid=%u res=%d", state, old, loginuid, res); /* If we are allowed, make the change */ if (res == 1) audit_failure = state; /* Not allowed, update reason */ else if (rc == 0) rc = -EPERM; return rc; }
static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid) { int old = audit_backlog_limit; if (sid) { char *ctx = NULL; u32 len; int rc; if ((rc = selinux_ctxid_to_string(sid, &ctx, &len))) return rc; else audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_backlog_limit=%d old=%d by auid=%u subj=%s", limit, old, loginuid, ctx); kfree(ctx); } else audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_backlog_limit=%d old=%d by auid=%u", limit, old, loginuid); audit_backlog_limit = limit; return 0; }
static int audit_set_failure(int state, uid_t loginuid) { int old = audit_failure; if (state != AUDIT_FAIL_SILENT && state != AUDIT_FAIL_PRINTK && state != AUDIT_FAIL_PANIC) return -EINVAL; audit_failure = state; audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_failure=%d old=%d by auid=%u", audit_failure, old, loginuid); return old; }
/* Initialize audit support at boot time. */ int __init audit_init(void) { printk(KERN_INFO "audit: initializing netlink socket (%s)\n", audit_default ? "enabled" : "disabled"); audit_sock = netlink_kernel_create(NETLINK_AUDIT, audit_receive); if (!audit_sock) audit_panic("cannot initialize netlink socket"); audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; skb_queue_head_init(&audit_skb_queue); audit_initialized = 1; audit_enabled = audit_default; audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized"); return 0; }
/** * avc_init - Initialize the AVC. * * Initialize the access vector cache. */ void __init avc_init(void) { int i; for (i = 0; i < AVC_CACHE_SLOTS; i++) { INIT_HLIST_HEAD(&avc_cache.slots[i]); spin_lock_init(&avc_cache.slots_lock[i]); } atomic_set(&avc_cache.active_nodes, 0); atomic_set(&avc_cache.lru_hint, 0); avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node), 0, SLAB_PANIC, NULL); audit_log(current->audit_context, GFP_KERNEL, AUDIT_KERNEL, "AVC INITIALIZED\n"); }
static ssize_t sel_write_enforce(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char *page = NULL; ssize_t length; int new_value; if (count >= PAGE_SIZE) return -ENOMEM; /* No partial writes. */ if (*ppos != 0) return -EINVAL; page = memdup_user_nul(buf, count); if (IS_ERR(page)) return PTR_ERR(page); length = -EINVAL; if (sscanf(page, "%d", &new_value) != 1) goto out; new_value = !!new_value; if (new_value != selinux_enforcing) { length = avc_has_perm(current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__SETENFORCE, NULL); if (length) goto out; audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, "enforcing=%d old_enforcing=%d auid=%u ses=%u", new_value, selinux_enforcing, from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); selinux_enforcing = new_value; if (selinux_enforcing) avc_ss_reset(0); selnl_notify_setenforce(selinux_enforcing); selinux_status_update_setenforce(selinux_enforcing); } length = count; out: kfree(page); return length; }
static ssize_t sel_write_disable(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char *page = NULL; ssize_t length; int new_value; extern int selinux_disable(void); length = -ENOMEM; if (count >= PAGE_SIZE) goto out; /* No partial writes. */ length = -EINVAL; if (*ppos != 0) goto out; length = -ENOMEM; page = (char *)get_zeroed_page(GFP_KERNEL); if (!page) goto out; length = -EFAULT; if (copy_from_user(page, buf, count)) goto out; length = -EINVAL; if (sscanf(page, "%d", &new_value) != 1) goto out; if (new_value) { length = selinux_disable(); if (length) goto out; audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, "selinux=0 auid=%u ses=%u", audit_get_loginuid(current), audit_get_sessionid(current)); } length = count; out: free_page((unsigned long) page); return length; }
static ssize_t sel_write_disable(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char *page; ssize_t length; int new_value; if (count >= PAGE_SIZE) return -ENOMEM; /* No partial writes. */ if (*ppos != 0) return -EINVAL; page = memdup_user_nul(buf, count); if (IS_ERR(page)) return PTR_ERR(page); length = -EINVAL; if (sscanf(page, "%d", &new_value) != 1) goto out; if (new_value) { length = selinux_disable(); if (length) goto out; audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, "selinux=0 auid=%u ses=%u", from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); } length = count; out: kfree(page); return length; }
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { u32 uid, pid, seq, sid; void *data; struct audit_status *status_get, status_set; int err; struct audit_buffer *ab; u16 msg_type = nlh->nlmsg_type; uid_t loginuid; /* loginuid of sender */ struct audit_sig_info *sig_data; char *ctx; u32 len; err = audit_netlink_ok(skb, msg_type); if (err) return err; /* As soon as there's any sign of userspace auditd, * start kauditd to talk to it */ if (!kauditd_task) kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd"); if (IS_ERR(kauditd_task)) { err = PTR_ERR(kauditd_task); kauditd_task = NULL; return err; } pid = NETLINK_CREDS(skb)->pid; uid = NETLINK_CREDS(skb)->uid; loginuid = NETLINK_CB(skb).loginuid; sid = NETLINK_CB(skb).sid; seq = nlh->nlmsg_seq; data = NLMSG_DATA(nlh); switch (msg_type) { case AUDIT_GET: status_set.enabled = audit_enabled; status_set.failure = audit_failure; status_set.pid = audit_pid; status_set.rate_limit = audit_rate_limit; status_set.backlog_limit = audit_backlog_limit; status_set.lost = atomic_read(&audit_lost); status_set.backlog = skb_queue_len(&audit_skb_queue); audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0, &status_set, sizeof(status_set)); break; case AUDIT_SET: if (nlh->nlmsg_len < sizeof(struct audit_status)) return -EINVAL; status_get = (struct audit_status *)data; if (status_get->mask & AUDIT_STATUS_ENABLED) { err = audit_set_enabled(status_get->enabled, loginuid, sid); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_FAILURE) { err = audit_set_failure(status_get->failure, loginuid, sid); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_PID) { int old = audit_pid; if (sid) { if ((err = selinux_sid_to_string( sid, &ctx, &len))) return err; else audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_pid=%d old=%d by auid=%u subj=%s", status_get->pid, old, loginuid, ctx); kfree(ctx); } else audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_pid=%d old=%d by auid=%u", status_get->pid, old, loginuid); audit_pid = status_get->pid; } if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) err = audit_set_rate_limit(status_get->rate_limit, loginuid, sid); if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) err = audit_set_backlog_limit(status_get->backlog_limit, loginuid, sid); break; case AUDIT_USER: case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2: if (!audit_enabled && msg_type != AUDIT_USER_AVC) return 0; err = audit_filter_user(&NETLINK_CB(skb), msg_type); if (err == 1) { err = 0; ab = audit_log_start(NULL, GFP_KERNEL, msg_type); if (ab) { audit_log_format(ab, "user pid=%d uid=%u auid=%u", pid, uid, loginuid); if (sid) { if (selinux_sid_to_string( sid, &ctx, &len)) { audit_log_format(ab, " ssid=%u", sid); /* Maybe call audit_panic? */ } else audit_log_format(ab, " subj=%s", ctx); kfree(ctx); } audit_log_format(ab, " msg='%.1024s'", (char *)data); audit_set_pid(ab, pid); audit_log_end(ab); } } break; case AUDIT_ADD: case AUDIT_DEL: if (nlmsg_len(nlh) < sizeof(struct audit_rule)) return -EINVAL; if (audit_enabled == 2) { ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (ab) { audit_log_format(ab, "pid=%d uid=%u auid=%u", pid, uid, loginuid); if (sid) { if (selinux_sid_to_string( sid, &ctx, &len)) { audit_log_format(ab, " ssid=%u", sid); /* Maybe call audit_panic? */ } else audit_log_format(ab, " subj=%s", ctx); kfree(ctx); } audit_log_format(ab, " audit_enabled=%d res=0", audit_enabled); audit_log_end(ab); } return -EPERM; } /* fallthrough */ case AUDIT_LIST: err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, uid, seq, data, nlmsg_len(nlh), loginuid, sid); break; case AUDIT_ADD_RULE: case AUDIT_DEL_RULE: if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) return -EINVAL; if (audit_enabled == 2) { ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (ab) { audit_log_format(ab, "pid=%d uid=%u auid=%u", pid, uid, loginuid); if (sid) { if (selinux_sid_to_string( sid, &ctx, &len)) { audit_log_format(ab, " ssid=%u", sid); /* Maybe call audit_panic? */ } else audit_log_format(ab, " subj=%s", ctx); kfree(ctx); } audit_log_format(ab, " audit_enabled=%d res=0", audit_enabled); audit_log_end(ab); } return -EPERM; } /* fallthrough */ case AUDIT_LIST_RULES: err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, uid, seq, data, nlmsg_len(nlh), loginuid, sid); break; case AUDIT_SIGNAL_INFO: err = selinux_sid_to_string(audit_sig_sid, &ctx, &len); if (err) return err; sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL); if (!sig_data) { kfree(ctx); return -ENOMEM; } sig_data->uid = audit_sig_uid; sig_data->pid = audit_sig_pid; memcpy(sig_data->ctx, ctx, len); kfree(ctx); audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 0, 0, sig_data, sizeof(*sig_data) + len); kfree(sig_data); break; default: err = -EINVAL; break; } return err < 0 ? err : 0; }
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { u32 uid, pid, seq; void *data; struct audit_status *status_get, status_set; struct audit_login *login; int err = 0; struct audit_buffer *ab; pid = NETLINK_CREDS(skb)->pid; uid = NETLINK_CREDS(skb)->uid; seq = nlh->nlmsg_seq; data = NLMSG_DATA(nlh); switch (nlh->nlmsg_type) { case AUDIT_GET: status_set.enabled = audit_enabled; status_set.failure = audit_failure; status_set.pid = audit_pid; status_set.rate_limit = audit_rate_limit; status_set.backlog_limit = audit_backlog_limit; status_set.lost = atomic_read(&audit_lost); status_set.backlog = atomic_read(&audit_backlog); audit_send_reply(pid, seq, AUDIT_GET, 0, 0, &status_set, sizeof(status_set)); break; case AUDIT_SET: if (!capable(CAP_SYS_ADMIN)) return -EPERM; status_get = (struct audit_status *)data; if (status_get->mask & AUDIT_STATUS_ENABLED) { err = audit_set_enabled(status_get->enabled); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_FAILURE) { err = audit_set_failure(status_get->failure); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_PID) { int old = audit_pid; audit_pid = status_get->pid; audit_log(current->audit_context, "audit_pid=%d old=%d", audit_pid, old); } if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) audit_set_rate_limit(status_get->rate_limit); if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) audit_set_backlog_limit(status_get->backlog_limit); break; case AUDIT_USER: ab = audit_log_start(NULL); if (!ab) break; /* audit_panic has been called */ audit_log_format(ab, "user pid=%d uid=%d length=%d msg='%.1024s'", pid, uid, (int)(nlh->nlmsg_len - ((char *)data - (char *)nlh)), (char *)data); ab->type = AUDIT_USER; ab->pid = pid; audit_log_end(ab); break; case AUDIT_LOGIN: if (!capable(CAP_SYS_ADMIN)) return -EPERM; login = (struct audit_login *)data; ab = audit_log_start(NULL); if (ab) { audit_log_format(ab, "login pid=%d uid=%d loginuid=%d" " length=%d msg='%.1024s'", pid, uid, login->loginuid, login->msglen, login->msg); ab->type = AUDIT_LOGIN; ab->pid = pid; audit_log_end(ab); } #ifdef CONFIG_AUDITSYSCALL err = audit_set_loginuid(current->audit_context, login->loginuid); #endif break; case AUDIT_LIST: case AUDIT_ADD: case AUDIT_DEL: #ifdef CONFIG_AUDITSYSCALL err = audit_receive_filter(nlh->nlmsg_type, pid, uid, seq, data); #else err = -EOPNOTSUPP; #endif break; default: err = -EINVAL; break; } return err < 0 ? err : 0; }
static ssize_t sel_write_enforce(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char *page = NULL; ssize_t length; int new_value; length = -ENOMEM; if (count >= PAGE_SIZE) goto out; /* No partial writes. */ length = EINVAL; if (*ppos != 0) goto out; length = -ENOMEM; page = (char *)get_zeroed_page(GFP_KERNEL); if (!page) goto out; length = -EFAULT; if (copy_from_user(page, buf, count)) goto out; length = -EINVAL; if (sscanf(page, "%d", &new_value) != 1) goto out; #ifdef CONFIG_ALWAYS_ENFORCE // If build is user build and enforce option is set, selinux is always enforcing new_value = 1; length = task_has_security(current, SECURITY__SETENFORCE); audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, "config_always_enforce - true; enforcing=%d old_enforcing=%d auid=%u ses=%u", new_value, selinux_enforcing, from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); selinux_enforcing = new_value; avc_ss_reset(0); selnl_notify_setenforce(new_value); selinux_status_update_setenforce(new_value); #else new_value = 0; /* Bye NSA! Nobody invited you here, so go back into reclusion and be permissive */ if (new_value != selinux_enforcing) { length = task_has_security(current, SECURITY__SETENFORCE); if (length) goto out; audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, "enforcing=%d old_enforcing=%d auid=%u ses=%u", new_value, selinux_enforcing, from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); selinux_enforcing = new_value; if (selinux_enforcing) avc_ss_reset(0); selnl_notify_setenforce(selinux_enforcing); selinux_status_update_setenforce(selinux_enforcing); } #endif length = count; out: free_page((unsigned long) page); return length; }
static ssize_t sel_write_load(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { ssize_t length; void *data = NULL; mutex_lock(&sel_mutex); length = avc_has_perm(current_sid(), SECINITSID_SECURITY, SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL); if (length) goto out; /* No partial writes. */ length = -EINVAL; if (*ppos != 0) goto out; length = -EFBIG; if (count > 64 * 1024 * 1024) goto out; length = -ENOMEM; data = vmalloc(count); if (!data) goto out; length = -EFAULT; if (copy_from_user(data, buf, count) != 0) goto out; length = security_load_policy(data, count); if (length) { pr_warn_ratelimited("SELinux: failed to load policy\n"); goto out; } length = sel_make_bools(); if (length) { pr_err("SELinux: failed to load policy booleans\n"); goto out1; } length = sel_make_classes(); if (length) { pr_err("SELinux: failed to load policy classes\n"); goto out1; } length = sel_make_policycap(); if (length) { pr_err("SELinux: failed to load policy capabilities\n"); goto out1; } length = count; out1: audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, "policy loaded auid=%u ses=%u", from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); out: mutex_unlock(&sel_mutex); vfree(data); return length; }
/* Perform an encrypt operation. Encrypt the data received on DATA-FD and write it to OUT_FP. The recipients are take from the certificate given in recplist; if this is NULL it will be encrypted for a default recipient */ int gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp) { int rc = 0; Base64Context b64writer = NULL; gpg_error_t err; ksba_writer_t writer; ksba_reader_t reader = NULL; ksba_cms_t cms = NULL; ksba_stop_reason_t stopreason; KEYDB_HANDLE kh = NULL; struct encrypt_cb_parm_s encparm; DEK dek = NULL; int recpno; FILE *data_fp = NULL; certlist_t cl; int count; memset (&encparm, 0, sizeof encparm); audit_set_type (ctrl->audit, AUDIT_TYPE_ENCRYPT); /* Check that the certificate list is not empty and that at least one certificate is not flagged as encrypt_to; i.e. is a real recipient. */ for (cl = recplist; cl; cl = cl->next) if (!cl->is_encrypt_to) break; if (!cl) { log_error(_("no valid recipients given\n")); gpgsm_status (ctrl, STATUS_NO_RECP, "0"); audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, 0); rc = gpg_error (GPG_ERR_NO_PUBKEY); goto leave; } for (count = 0, cl = recplist; cl; cl = cl->next) count++; audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, count); kh = keydb_new (0); if (!kh) { log_error (_("failed to allocated keyDB handle\n")); rc = gpg_error (GPG_ERR_GENERAL); goto leave; } data_fp = fdopen ( dup (data_fd), "rb"); if (!data_fp) { rc = gpg_error (gpg_err_code_from_errno (errno)); log_error ("fdopen() failed: %s\n", strerror (errno)); goto leave; } err = ksba_reader_new (&reader); if (err) rc = err; if (!rc) rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm); if (rc) goto leave; encparm.fp = data_fp; ctrl->pem_name = "ENCRYPTED MESSAGE"; rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer); if (rc) { log_error ("can't create writer: %s\n", gpg_strerror (rc)); goto leave; } err = ksba_cms_new (&cms); if (err) { rc = err; goto leave; } err = ksba_cms_set_reader_writer (cms, reader, writer); if (err) { log_debug ("ksba_cms_set_reader_writer failed: %s\n", gpg_strerror (err)); rc = err; goto leave; } audit_log (ctrl->audit, AUDIT_GOT_DATA); /* We are going to create enveloped data with uninterpreted data as inner content */ err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA); if (!err) err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA); if (err) { log_debug ("ksba_cms_set_content_type failed: %s\n", gpg_strerror (err)); rc = err; goto leave; } /* Create a session key */ dek = xtrycalloc_secure (1, sizeof *dek); if (!dek) rc = out_of_core (); else { dek->algoid = opt.def_cipher_algoid; rc = init_dek (dek); } if (rc) { log_error ("failed to create the session key: %s\n", gpg_strerror (rc)); goto leave; } err = ksba_cms_set_content_enc_algo (cms, dek->algoid, dek->iv, dek->ivlen); if (err) { log_error ("ksba_cms_set_content_enc_algo failed: %s\n", gpg_strerror (err)); rc = err; goto leave; } encparm.dek = dek; /* Use a ~8k (AES) or ~4k (3DES) buffer */ encparm.bufsize = 500 * dek->ivlen; encparm.buffer = xtrymalloc (encparm.bufsize); if (!encparm.buffer) { rc = out_of_core (); goto leave; } audit_log_s (ctrl->audit, AUDIT_SESSION_KEY, dek->algoid); /* Gather certificates of recipients, encrypt the session key for each and store them in the CMS object */ for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next) { unsigned char *encval; rc = encrypt_dek (dek, cl->cert, &encval); if (rc) { audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, rc); log_error ("encryption failed for recipient no. %d: %s\n", recpno, gpg_strerror (rc)); goto leave; } err = ksba_cms_add_recipient (cms, cl->cert); if (err) { audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err); log_error ("ksba_cms_add_recipient failed: %s\n", gpg_strerror (err)); rc = err; xfree (encval); goto leave; } err = ksba_cms_set_enc_val (cms, recpno, encval); xfree (encval); audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err); if (err) { log_error ("ksba_cms_set_enc_val failed: %s\n", gpg_strerror (err)); rc = err; goto leave; } } /* Main control loop for encryption. */ recpno = 0; do { err = ksba_cms_build (cms, &stopreason); if (err) { log_debug ("ksba_cms_build failed: %s\n", gpg_strerror (err)); rc = err; goto leave; } } while (stopreason != KSBA_SR_READY); if (encparm.readerror) { log_error ("error reading input: %s\n", strerror (encparm.readerror)); rc = gpg_error (gpg_err_code_from_errno (encparm.readerror)); goto leave; } rc = gpgsm_finish_writer (b64writer); if (rc) { log_error ("write failed: %s\n", gpg_strerror (rc)); goto leave; } audit_log (ctrl->audit, AUDIT_ENCRYPTION_DONE); log_info ("encrypted data created\n"); leave: ksba_cms_release (cms); gpgsm_destroy_writer (b64writer); ksba_reader_release (reader); keydb_release (kh); xfree (dek); if (data_fp) fclose (data_fp); xfree (encparm.buffer); return rc; }
/* Perform a verify operation. To verify detached signatures, data_fd must be different than -1. With OUT_FP given and a non-detached signature, the signed material is written to that stream. */ int gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp) { int i, rc; Base64Context b64reader = NULL; Base64Context b64writer = NULL; ksba_reader_t reader; ksba_writer_t writer = NULL; ksba_cms_t cms = NULL; ksba_stop_reason_t stopreason; ksba_cert_t cert; KEYDB_HANDLE kh; gcry_md_hd_t data_md = NULL; int signer; const char *algoid; int algo; int is_detached; FILE *fp = NULL; char *p; audit_set_type (ctrl->audit, AUDIT_TYPE_VERIFY); kh = keydb_new (0); if (!kh) { log_error (_("failed to allocated keyDB handle\n")); rc = gpg_error (GPG_ERR_GENERAL); goto leave; } fp = fdopen ( dup (in_fd), "rb"); if (!fp) { rc = gpg_error (gpg_err_code_from_errno (errno)); log_error ("fdopen() failed: %s\n", strerror (errno)); goto leave; } rc = gpgsm_create_reader (&b64reader, ctrl, fp, 0, &reader); if (rc) { log_error ("can't create reader: %s\n", gpg_strerror (rc)); goto leave; } if (out_fp) { rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer); if (rc) { log_error ("can't create writer: %s\n", gpg_strerror (rc)); goto leave; } } rc = ksba_cms_new (&cms); if (rc) goto leave; rc = ksba_cms_set_reader_writer (cms, reader, writer); if (rc) { log_error ("ksba_cms_set_reader_writer failed: %s\n", gpg_strerror (rc)); goto leave; } rc = gcry_md_open (&data_md, 0, 0); if (rc) { log_error ("md_open failed: %s\n", gpg_strerror (rc)); goto leave; } if (DBG_HASHING) gcry_md_start_debug (data_md, "vrfy.data"); audit_log (ctrl->audit, AUDIT_SETUP_READY); is_detached = 0; do { rc = ksba_cms_parse (cms, &stopreason); if (rc) { log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc)); goto leave; } if (stopreason == KSBA_SR_NEED_HASH) { is_detached = 1; audit_log (ctrl->audit, AUDIT_DETACHED_SIGNATURE); if (opt.verbose) log_info ("detached signature\n"); } if (stopreason == KSBA_SR_NEED_HASH || stopreason == KSBA_SR_BEGIN_DATA) { audit_log (ctrl->audit, AUDIT_GOT_DATA); /* We are now able to enable the hash algorithms */ for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++) { algo = gcry_md_map_name (algoid); if (!algo) { log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?"); if (algoid && ( !strcmp (algoid, "1.2.840.113549.1.1.2") ||!strcmp (algoid, "1.2.840.113549.2.2"))) log_info (_("(this is the MD2 algorithm)\n")); audit_log_s (ctrl->audit, AUDIT_BAD_DATA_HASH_ALGO, algoid); } else { if (DBG_X509) log_debug ("enabling hash algorithm %d (%s)\n", algo, algoid? algoid:""); gcry_md_enable (data_md, algo); audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo); } } if (opt.extra_digest_algo) { if (DBG_X509) log_debug ("enabling extra hash algorithm %d\n", opt.extra_digest_algo); gcry_md_enable (data_md, opt.extra_digest_algo); audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, opt.extra_digest_algo); } if (is_detached) { if (data_fd == -1) { log_info ("detached signature w/o data " "- assuming certs-only\n"); audit_log (ctrl->audit, AUDIT_CERT_ONLY_SIG); } else audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING, hash_data (data_fd, data_md)); } else { ksba_cms_set_hash_function (cms, HASH_FNC, data_md); } } else if (stopreason == KSBA_SR_END_DATA) { /* The data bas been hashed */ audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING, 0); } } while (stopreason != KSBA_SR_READY); if (b64writer) { rc = gpgsm_finish_writer (b64writer); if (rc) { log_error ("write failed: %s\n", gpg_strerror (rc)); audit_log_ok (ctrl->audit, AUDIT_WRITE_ERROR, rc); goto leave; } } if (data_fd != -1 && !is_detached) { log_error ("data given for a non-detached signature\n"); rc = gpg_error (GPG_ERR_CONFLICT); audit_log (ctrl->audit, AUDIT_USAGE_ERROR); goto leave; } for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++) { /* Fixme: it might be better to check the validity of the certificate first before entering it into the DB. This way we would avoid cluttering the DB with invalid certificates. */ audit_log_cert (ctrl->audit, AUDIT_SAVE_CERT, cert, keydb_store_cert (cert, 0, NULL)); ksba_cert_release (cert); } cert = NULL; for (signer=0; ; signer++) { char *issuer = NULL; ksba_sexp_t sigval = NULL; ksba_isotime_t sigtime, keyexptime; ksba_sexp_t serial; char *msgdigest = NULL; size_t msgdigestlen; char *ctattr; int sigval_hash_algo; int info_pkalgo; unsigned int verifyflags; rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial); if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA && data_fd == -1 && is_detached) { log_info ("certs-only message accepted\n"); rc = 0; break; } if (rc) { if (signer && rc == -1) rc = 0; break; } gpgsm_status (ctrl, STATUS_NEWSIG, NULL); audit_log_i (ctrl->audit, AUDIT_NEW_SIG, signer); if (DBG_X509) { log_debug ("signer %d - issuer: `%s'\n", signer, issuer? issuer:"[NONE]"); log_debug ("signer %d - serial: ", signer); gpgsm_dump_serial (serial); log_printf ("\n"); } if (ctrl->audit) { char *tmpstr = gpgsm_format_sn_issuer (serial, issuer); audit_log_s (ctrl->audit, AUDIT_SIG_NAME, tmpstr); xfree (tmpstr); } rc = ksba_cms_get_signing_time (cms, signer, sigtime); if (gpg_err_code (rc) == GPG_ERR_NO_DATA) *sigtime = 0; else if (rc) { log_error ("error getting signing time: %s\n", gpg_strerror (rc)); *sigtime = 0; /* (we can't encode an error in the time string.) */ } rc = ksba_cms_get_message_digest (cms, signer, &msgdigest, &msgdigestlen); if (!rc) { size_t is_enabled; algoid = ksba_cms_get_digest_algo (cms, signer); algo = gcry_md_map_name (algoid); if (DBG_X509) log_debug ("signer %d - digest algo: %d\n", signer, algo); is_enabled = sizeof algo; if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED, &algo, &is_enabled) || !is_enabled) { log_error ("digest algo %d (%s) has not been enabled\n", algo, algoid?algoid:""); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "unsupported"); goto next_signer; } } else if (gpg_err_code (rc) == GPG_ERR_NO_DATA) { assert (!msgdigest); rc = 0; algoid = NULL; algo = 0; } else /* real error */ { audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error"); break; } rc = ksba_cms_get_sigattr_oids (cms, signer, "1.2.840.113549.1.9.3", &ctattr); if (!rc) { const char *s; if (DBG_X509) log_debug ("signer %d - content-type attribute: %s", signer, ctattr); s = ksba_cms_get_content_oid (cms, 1); if (!s || strcmp (ctattr, s)) { log_error ("content-type attribute does not match " "actual content-type\n"); ksba_free (ctattr); ctattr = NULL; audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } ksba_free (ctattr); ctattr = NULL; } else if (rc != -1) { log_error ("error getting content-type attribute: %s\n", gpg_strerror (rc)); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } rc = 0; sigval = ksba_cms_get_sig_val (cms, signer); if (!sigval) { log_error ("no signature value available\n"); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } sigval_hash_algo = hash_algo_from_sigval (sigval); if (DBG_X509) { log_debug ("signer %d - signature available (sigval hash=%d)", signer, sigval_hash_algo); /* log_printhex ("sigval ", sigval, */ /* gcry_sexp_canon_len (sigval, 0, NULL, NULL)); */ } if (!sigval_hash_algo) sigval_hash_algo = algo; /* Fallback used e.g. with old libksba. */ /* Find the certificate of the signer */ keydb_search_reset (kh); rc = keydb_search_issuer_sn (kh, issuer, serial); if (rc) { if (rc == -1) { log_error ("certificate not found\n"); rc = gpg_error (GPG_ERR_NO_PUBKEY); } else log_error ("failed to find the certificate: %s\n", gpg_strerror(rc)); { char numbuf[50]; sprintf (numbuf, "%d", rc); gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey", numbuf, NULL); } audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "no-cert"); goto next_signer; } rc = keydb_get_cert (kh, &cert); if (rc) { log_error ("failed to get cert: %s\n", gpg_strerror (rc)); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error"); goto next_signer; } log_info (_("Signature made ")); if (*sigtime) dump_isotime (sigtime); else log_printf (_("[date not given]")); log_printf (_(" using certificate ID 0x%08lX\n"), gpgsm_get_short_fingerprint (cert, NULL)); audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo); if (msgdigest) { /* Signed attributes are available. */ gcry_md_hd_t md; unsigned char *s; /* Check that the message digest in the signed attributes matches the one we calculated on the data. */ s = gcry_md_read (data_md, algo); if ( !s || !msgdigestlen || gcry_md_get_algo_dlen (algo) != msgdigestlen || !s || memcmp (s, msgdigest, msgdigestlen) ) { char *fpr; log_error (_("invalid signature: message digest attribute " "does not match computed one\n")); if (DBG_X509) { if (msgdigest) log_printhex ("message: ", msgdigest, msgdigestlen); if (s) log_printhex ("computed: ", s, gcry_md_get_algo_dlen (algo)); } fpr = gpgsm_fpr_and_name_for_status (cert); gpgsm_status (ctrl, STATUS_BADSIG, fpr); xfree (fpr); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } audit_log_i (ctrl->audit, AUDIT_ATTR_HASH_ALGO, sigval_hash_algo); rc = gcry_md_open (&md, sigval_hash_algo, 0); if (rc) { log_error ("md_open failed: %s\n", gpg_strerror (rc)); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error"); goto next_signer; } if (DBG_HASHING) gcry_md_start_debug (md, "vrfy.attr"); ksba_cms_set_hash_function (cms, HASH_FNC, md); rc = ksba_cms_hash_signed_attrs (cms, signer); if (rc) { log_error ("hashing signed attrs failed: %s\n", gpg_strerror (rc)); gcry_md_close (md); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error"); goto next_signer; } rc = gpgsm_check_cms_signature (cert, sigval, md, sigval_hash_algo, &info_pkalgo); gcry_md_close (md); } else { rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo, &info_pkalgo); } if (rc) { char *fpr; log_error ("invalid signature: %s\n", gpg_strerror (rc)); fpr = gpgsm_fpr_and_name_for_status (cert); gpgsm_status (ctrl, STATUS_BADSIG, fpr); xfree (fpr); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/ if (rc) { gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage", gpg_err_code (rc)); rc = 0; } if (DBG_X509) log_debug ("signature okay - checking certs\n"); audit_log (ctrl->audit, AUDIT_VALIDATE_CHAIN); rc = gpgsm_validate_chain (ctrl, cert, *sigtime? sigtime : "19700101T000000", keyexptime, 0, NULL, 0, &verifyflags); { char *fpr, *buf, *tstr; fpr = gpgsm_fpr_and_name_for_status (cert); if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED) { gpgsm_status (ctrl, STATUS_EXPKEYSIG, fpr); rc = 0; } else gpgsm_status (ctrl, STATUS_GOODSIG, fpr); xfree (fpr); fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); tstr = strtimestamp_r (sigtime); buf = xasprintf ("%s %s %s %s 0 0 %d %d 00", fpr, tstr, *sigtime? sigtime : "0", *keyexptime? keyexptime : "0", info_pkalgo, algo); xfree (tstr); xfree (fpr); gpgsm_status (ctrl, STATUS_VALIDSIG, buf); xfree (buf); } audit_log_ok (ctrl->audit, AUDIT_CHAIN_STATUS, rc); if (rc) /* of validate_chain */ { log_error ("invalid certification chain: %s\n", gpg_strerror (rc)); if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN || gpg_err_code (rc) == GPG_ERR_BAD_CERT || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED) gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL, gpg_err_code (rc)); else gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL, gpg_err_code (rc)); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "good"); for (i=0; (p = ksba_cert_get_subject (cert, i)); i++) { log_info (!i? _("Good signature from") : _(" aka")); log_printf (" \""); gpgsm_print_name (log_get_stream (), p); log_printf ("\"\n"); ksba_free (p); } /* Print a note if this is a qualified signature. */ { size_t qualbuflen; char qualbuffer[1]; rc = ksba_cert_get_user_data (cert, "is_qualified", &qualbuffer, sizeof (qualbuffer), &qualbuflen); if (!rc && qualbuflen) { if (*qualbuffer) { log_info (_("This is a qualified signature\n")); if (!opt.qualsig_approval) log_info (_("Note, that this software is not officially approved " "to create or verify such signatures.\n")); } } else if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND) log_error ("get_user_data(is_qualified) failed: %s\n", gpg_strerror (rc)); } gpgsm_status (ctrl, STATUS_TRUST_FULLY, (verifyflags & VALIDATE_FLAG_CHAIN_MODEL)? "0 chain": "0 shell"); next_signer: rc = 0; xfree (issuer); xfree (serial); xfree (sigval); xfree (msgdigest); ksba_cert_release (cert); cert = NULL; } rc = 0; leave: ksba_cms_release (cms); gpgsm_destroy_reader (b64reader); gpgsm_destroy_writer (b64writer); keydb_release (kh); gcry_md_close (data_md); if (fp) fclose (fp); if (rc) { char numbuf[50]; sprintf (numbuf, "%d", rc ); gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave", numbuf, NULL); } return rc; }
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { u32 uid, pid, seq; void *data; struct audit_status *status_get, status_set; int err; struct audit_buffer *ab; u16 msg_type = nlh->nlmsg_type; uid_t loginuid; /* loginuid of sender */ struct audit_sig_info sig_data; err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type); if (err) return err; /* As soon as there's any sign of userspace auditd, start kauditd to talk to it */ if (!kauditd_task) kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd"); if (IS_ERR(kauditd_task)) { err = PTR_ERR(kauditd_task); kauditd_task = NULL; return err; } pid = NETLINK_CREDS(skb)->pid; uid = NETLINK_CREDS(skb)->uid; loginuid = NETLINK_CB(skb).loginuid; seq = nlh->nlmsg_seq; data = NLMSG_DATA(nlh); switch (msg_type) { case AUDIT_GET: status_set.enabled = audit_enabled; status_set.failure = audit_failure; status_set.pid = audit_pid; status_set.rate_limit = audit_rate_limit; status_set.backlog_limit = audit_backlog_limit; status_set.lost = atomic_read(&audit_lost); status_set.backlog = skb_queue_len(&audit_skb_queue); audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0, &status_set, sizeof(status_set)); break; case AUDIT_SET: if (nlh->nlmsg_len < sizeof(struct audit_status)) return -EINVAL; status_get = (struct audit_status *)data; if (status_get->mask & AUDIT_STATUS_ENABLED) { err = audit_set_enabled(status_get->enabled, loginuid); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_FAILURE) { err = audit_set_failure(status_get->failure, loginuid); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_PID) { int old = audit_pid; audit_pid = status_get->pid; audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_pid=%d old=%d by auid=%u", audit_pid, old, loginuid); } if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) audit_set_rate_limit(status_get->rate_limit, loginuid); if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) audit_set_backlog_limit(status_get->backlog_limit, loginuid); break; case AUDIT_USER: case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: if (!audit_enabled && msg_type != AUDIT_USER_AVC) return 0; err = audit_filter_user(&NETLINK_CB(skb), msg_type); if (err == 1) { err = 0; ab = audit_log_start(NULL, GFP_KERNEL, msg_type); if (ab) { audit_log_format(ab, "user pid=%d uid=%u auid=%u msg='%.1024s'", pid, uid, loginuid, (char *)data); audit_set_pid(ab, pid); audit_log_end(ab); } } break; case AUDIT_ADD: case AUDIT_DEL: if (nlh->nlmsg_len < sizeof(struct audit_rule)) return -EINVAL; /* fallthrough */ case AUDIT_LIST: err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, uid, seq, data, loginuid); break; case AUDIT_SIGNAL_INFO: sig_data.uid = audit_sig_uid; sig_data.pid = audit_sig_pid; audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 0, 0, &sig_data, sizeof(sig_data)); break; default: err = -EINVAL; break; } return err < 0 ? err : 0; }