int __ptrace_may_access(struct task_struct *task, unsigned int mode) { /* May we inspect the given task? * This check is used both for attaching with ptrace * and for allowing access to sensitive information in /proc. * * ptrace_attach denies several cases that /proc allows * because setting up the necessary parent/child relationship * or halting the specified task is impossible. */ int dumpable = 0; /* Don't let security modules deny introspection */ if (task == current) return 0; if (((current->uid != task->euid) || (current->uid != task->suid) || (current->uid != task->uid) || (current->gid != task->egid) || (current->gid != task->sgid) || (current->gid != task->gid)) && !capable_nolog(CAP_SYS_PTRACE)) return -EPERM; smp_rmb(); if (task->mm) dumpable = get_dumpable(task->mm); if (!dumpable && !capable_nolog(CAP_SYS_PTRACE)) return -EPERM; return security_ptrace_may_access(task, mode); }
static int check_syslog_permissions(int type, bool from_file) { /* * If this is from /proc/kmsg and we've already opened it, then we've * already done the capabilities checks at open time. */ if (from_file && type != SYSLOG_ACTION_OPEN) return 0; #ifdef CONFIG_GRKERNSEC_DMESG if (grsec_enable_dmesg && !capable(CAP_SYSLOG) && !capable_nolog(CAP_SYS_ADMIN)) return -EPERM; #endif if (syslog_action_restricted(type)) { if (capable(CAP_SYSLOG)) return 0; /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */ if (capable(CAP_SYS_ADMIN)) { printk_once(KERN_WARNING "%s (%d): " "Attempt to access syslog with CAP_SYS_ADMIN " "but no CAP_SYSLOG (deprecated).\n", current->comm, task_pid_nr(current)); return 0; } return -EPERM; } return 0; }
int ptrace_attach(struct task_struct *task) { int retval; unsigned long flags; audit_ptrace(task); retval = -EPERM; if (same_thread_group(task, current)) goto out; repeat: /* * Nasty, nasty. * * We want to hold both the task-lock and the * tasklist_lock for writing at the same time. * But that's against the rules (tasklist_lock * is taken for reading by interrupts on other * cpu's that may have task_lock). */ task_lock(task); if (!write_trylock_irqsave(&tasklist_lock, flags)) { task_unlock(task); do { cpu_relax(); } while (!write_can_lock(&tasklist_lock)); goto repeat; } if (!task->mm) goto bad; /* the same process cannot be attached many times */ if (task->ptrace & PT_PTRACED) goto bad; retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); if (retval) goto bad; /* Go */ task->ptrace |= PT_PTRACED; if (capable_nolog(CAP_SYS_PTRACE)) task->ptrace |= PT_PTRACE_CAP; __ptrace_link(task, current); send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); bad: write_unlock_irqrestore(&tasklist_lock, flags); task_unlock(task); out: return retval; }
/** * ext4_has_free_blocks() * @sbi: in-core super block structure. * @nblocks: number of needed blocks * * Check if filesystem has nblocks free & available for allocation. * On success return 1, return 0 on failure. */ int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks) { s64 free_blocks, dirty_blocks, root_blocks; struct percpu_counter *fbc = &sbi->s_freeblocks_counter; struct percpu_counter *dbc = &sbi->s_dirtyblocks_counter; free_blocks = percpu_counter_read_positive(fbc); dirty_blocks = percpu_counter_read_positive(dbc); root_blocks = ext4_r_blocks_count(sbi->s_es); if (free_blocks - (nblocks + root_blocks + dirty_blocks) < EXT4_FREEBLOCKS_WATERMARK) { free_blocks = percpu_counter_sum_positive(fbc); dirty_blocks = percpu_counter_sum_positive(dbc); if (dirty_blocks < 0) { printk(KERN_CRIT "Dirty block accounting " "went wrong %lld\n", (long long)dirty_blocks); } } /* Check whether we have space after * accounting for current dirty blocks & root reserved blocks. */ if (free_blocks >= ((root_blocks + nblocks) + dirty_blocks)) return 1; /* Hm, nope. Are (enough) root reserved blocks available? */ if (sbi->s_resuid == current_fsuid() || ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) || capable_nolog(CAP_SYS_RESOURCE)) { if (free_blocks >= (nblocks + dirty_blocks)) return 1; } return 0; }