umode_t gr_acl_umask(void) { if (unlikely(!gr_acl_is_enabled())) return 0; return current->role->umask; }
static int gr_log_start(int audit) { char *loglevel = (audit == GR_DO_AUDIT) ? KERN_INFO : KERN_ALERT; char *fmt = (audit == GR_DO_AUDIT) ? gr_audit_log_fmt : gr_alert_log_fmt; char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf; #if (CONFIG_GRKERNSEC_FLOODTIME > 0 && CONFIG_GRKERNSEC_FLOODBURST > 0) unsigned long curr_secs = get_seconds(); if (audit == GR_DO_AUDIT) goto set_fmt; if (!grsec_alert_wtime || time_after(curr_secs, grsec_alert_wtime + CONFIG_GRKERNSEC_FLOODTIME)) { grsec_alert_wtime = curr_secs; grsec_alert_fyet = 0; } else if (time_before_eq(curr_secs, grsec_alert_wtime + CONFIG_GRKERNSEC_FLOODTIME) && (grsec_alert_fyet < CONFIG_GRKERNSEC_FLOODBURST)) { grsec_alert_fyet++; } else if (grsec_alert_fyet == CONFIG_GRKERNSEC_FLOODBURST) { grsec_alert_wtime = curr_secs; grsec_alert_fyet++; printk(KERN_ALERT "grsec: more alerts, logging disabled for %d seconds\n", CONFIG_GRKERNSEC_FLOODTIME); return FLOODING; } else return FLOODING; set_fmt: #endif memset(buf, 0, PAGE_SIZE); if (current->signal->curr_ip && gr_acl_is_enabled()) { sprintf(fmt, "%s%s", loglevel, "grsec: From %pI4: (%.64s:%c:%.950s) "); snprintf(buf, PAGE_SIZE - 1, fmt, ¤t->signal->curr_ip, current->role->rolename, gr_roletype_to_char(), current->acl->filename); } else if (current->signal->curr_ip) { sprintf(fmt, "%s%s", loglevel, "grsec: From %pI4: "); snprintf(buf, PAGE_SIZE - 1, fmt, ¤t->signal->curr_ip); } else if (gr_acl_is_enabled()) { sprintf(fmt, "%s%s", loglevel, "grsec: (%.64s:%c:%.950s) "); snprintf(buf, PAGE_SIZE - 1, fmt, current->role->rolename, gr_roletype_to_char(), current->acl->filename); } else { sprintf(fmt, "%s%s", loglevel, "grsec: "); strcpy(buf, fmt); } return NO_FLOODING; }
int gr_acl_handle_rename(struct dentry *new_dentry, struct dentry *parent_dentry, const struct vfsmount *parent_mnt, struct dentry *old_dentry, struct inode *old_parent_inode, struct vfsmount *old_mnt, const struct filename *newname, unsigned int flags) { __u32 comp1, comp2; int error = 0; if (unlikely(!gr_acl_is_enabled())) return 0; if (flags & RENAME_EXCHANGE) { comp1 = gr_search_file(new_dentry, GR_READ | GR_WRITE | GR_AUDIT_READ | GR_AUDIT_WRITE | GR_SUPPRESS, parent_mnt); comp2 = gr_search_file(old_dentry, GR_READ | GR_WRITE | GR_AUDIT_READ | GR_AUDIT_WRITE | GR_SUPPRESS, old_mnt); } else if (d_is_negative(new_dentry)) { comp1 = gr_check_create(new_dentry, parent_dentry, parent_mnt, GR_READ | GR_WRITE | GR_CREATE | GR_AUDIT_READ | GR_AUDIT_WRITE | GR_AUDIT_CREATE | GR_SUPPRESS); comp2 = gr_search_file(old_dentry, GR_READ | GR_WRITE | GR_DELETE | GR_AUDIT_DELETE | GR_AUDIT_READ | GR_AUDIT_WRITE | GR_SUPPRESS, old_mnt); } else { comp1 = gr_search_file(new_dentry, GR_READ | GR_WRITE | GR_CREATE | GR_DELETE | GR_AUDIT_CREATE | GR_AUDIT_DELETE | GR_AUDIT_READ | GR_AUDIT_WRITE | GR_SUPPRESS, parent_mnt); comp2 = gr_search_file(old_dentry, GR_READ | GR_WRITE | GR_AUDIT_READ | GR_DELETE | GR_AUDIT_DELETE | GR_AUDIT_WRITE | GR_SUPPRESS, old_mnt); } if (RENAME_CHECK_SUCCESS(comp1, comp2) && ((comp1 & GR_AUDITS) || (comp2 & GR_AUDITS))) gr_log_fs_rbac_str(GR_DO_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname->name); else if (!RENAME_CHECK_SUCCESS(comp1, comp2) && !(comp1 & GR_SUPPRESS) && !(comp2 & GR_SUPPRESS)) { gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname->name); error = -EACCES; } else if (unlikely(!RENAME_CHECK_SUCCESS(comp1, comp2))) error = -EACCES; return error; }
int gr_acl_handle_procpidmem(const struct task_struct *task) { if (unlikely(!gr_acl_is_enabled())) return 0; if (task != current && task->acl->mode & GR_PROTPROCFD) return -EACCES; return 0; }
static int gr_log_start(int audit) { char *loglevel = (audit == GR_DO_AUDIT) ? KERN_INFO : KERN_ALERT; char *fmt = (audit == GR_DO_AUDIT) ? gr_audit_log_fmt : gr_alert_log_fmt; char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf; if (audit == GR_DO_AUDIT) goto set_fmt; if (!grsec_alert_wtime || jiffies - grsec_alert_wtime > CONFIG_GRKERNSEC_FLOODTIME * HZ) { grsec_alert_wtime = jiffies; grsec_alert_fyet = 0; } else if ((jiffies - grsec_alert_wtime < CONFIG_GRKERNSEC_FLOODTIME * HZ) && (grsec_alert_fyet < CONFIG_GRKERNSEC_FLOODBURST)) { grsec_alert_fyet++; } else if (grsec_alert_fyet == CONFIG_GRKERNSEC_FLOODBURST) { grsec_alert_wtime = jiffies; grsec_alert_fyet++; printk(KERN_ALERT "grsec: more alerts, logging disabled for %d seconds\n", CONFIG_GRKERNSEC_FLOODTIME); return FLOODING; } else return FLOODING; set_fmt: memset(buf, 0, PAGE_SIZE); if (current->signal->curr_ip && gr_acl_is_enabled()) { sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: (%.64s:%c:%.950s) "); snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip), current->role->rolename, gr_roletype_to_char(), current->acl->filename); } else if (current->signal->curr_ip) { sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: "); snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip)); } else if (gr_acl_is_enabled()) { sprintf(fmt, "%s%s", loglevel, "grsec: (%.64s:%c:%.950s) "); snprintf(buf, PAGE_SIZE - 1, fmt, current->role->rolename, gr_roletype_to_char(), current->acl->filename); } else { sprintf(fmt, "%s%s", loglevel, "grsec: "); strcpy(buf, fmt); } return NO_FLOODING; }
int gr_acl_handle_procpidmem(const struct task_struct *task) { if (unlikely(!gr_acl_is_enabled())) return 0; if (task != current && (task->acl->mode & GR_PROTPROCFD) && !(current->acl->mode & GR_POVERRIDE) && !(current->role->roletype & GR_ROLE_GOD)) return -EACCES; return 0; }
void gr_handle_crash(struct task_struct *task, const int sig) { struct acl_subject_label *curr; struct acl_subject_label *curr2; struct task_struct *tsk, *tsk2; const struct cred *cred; const struct cred *cred2; if (sig != SIGSEGV && sig != SIGKILL && sig != SIGBUS && sig != SIGILL) return; if (unlikely(!gr_acl_is_enabled())) return; curr = task->acl; if (!(curr->resmask & (1 << GR_CRASH_RES))) return; if (time_before_eq(curr->expires, get_seconds())) { curr->expires = 0; curr->crashes = 0; } curr->crashes++; if (!curr->expires) curr->expires = get_seconds() + curr->res[GR_CRASH_RES].rlim_max; if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) && time_after(curr->expires, get_seconds())) { rcu_read_lock(); cred = __task_cred(task); if (cred->uid && proc_is_setxid(cred)) { gr_log_crash1(GR_DONT_AUDIT, GR_SEGVSTART_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max); spin_lock(&gr_uid_lock); gr_insert_uid(cred->uid, curr->expires); spin_unlock(&gr_uid_lock); curr->expires = 0; curr->crashes = 0; read_lock(&tasklist_lock); do_each_thread(tsk2, tsk) { cred2 = __task_cred(tsk); if (tsk != task && cred2->uid == cred->uid) gr_fake_force_sig(SIGKILL, tsk); } while_each_thread(tsk2, tsk);
void gr_acl_handle_exit(void) { u16 id; char *rolename; if (unlikely(current->acl_sp_role && gr_acl_is_enabled() && !(current->role->roletype & GR_ROLE_PERSIST))) { id = current->acl_role_id; rolename = current->role->rolename; gr_set_acls(1); gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLEL_ACL_MSG, rolename, id); } gr_put_exec_file(current); return; }
void gr_log_resource(const struct task_struct *task, const int res, const unsigned long wanted, const int gt) { const struct cred *cred; unsigned long rlim; if (!gr_acl_is_enabled() && !grsec_resource_logging) return; // not yet supported resource if (unlikely(!restab_log[res])) return; if (res == RLIMIT_CPU || res == RLIMIT_RTTIME) rlim = task->signal->rlim[res].rlim_max; else rlim = task->signal->rlim[res].rlim_cur; if (likely((rlim == RLIM_INFINITY) || (gt && wanted <= rlim) || (!gt && wanted < rlim))) return; rcu_read_lock(); cred = __task_cred(task); if (res == RLIMIT_NPROC && (cap_raised(cred->cap_effective, CAP_SYS_ADMIN) || cap_raised(cred->cap_effective, CAP_SYS_RESOURCE))) goto out_rcu_unlock; else if (res == RLIMIT_MEMLOCK && cap_raised(cred->cap_effective, CAP_IPC_LOCK)) goto out_rcu_unlock; else if (res == RLIMIT_NICE && cap_raised(cred->cap_effective, CAP_SYS_NICE)) goto out_rcu_unlock; rcu_read_unlock(); gr_log_res_ulong2_str(GR_DONT_AUDIT, GR_RESOURCE_MSG, task, wanted, restab_log[res], rlim); return; out_rcu_unlock: rcu_read_unlock(); return; }
void gr_acl_handle_exit(void) { u16 id; char *rolename; struct file *exec_file; if (unlikely(current->acl_sp_role && gr_acl_is_enabled())) { id = current->acl_role_id; rolename = current->role->rolename; gr_set_acls(1); gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLEL_ACL_MSG, rolename, id); } write_lock(&grsec_exec_file_lock); exec_file = current->exec_file; current->exec_file = NULL; write_unlock(&grsec_exec_file_lock); if (exec_file) fput(exec_file); }
int gr_check_crash_uid(const uid_t uid) { int loc; int ret = 0; if (unlikely(!gr_acl_is_enabled())) return 0; spin_lock(&gr_uid_lock); loc = gr_find_uid(uid); if (loc < 0) goto out_unlock; if (time_before_eq(uid_set[loc].expires, get_seconds())) gr_remove_uid(loc); else ret = 1; out_unlock: spin_unlock(&gr_uid_lock); return ret; }