CRED: Use RCU to access another task's creds and to release a task's own creds
Use RCU to access another task's creds and to release a task's own creds. This means that it will be possible for the credentials of a task to be replaced without another task (a) requiring a full lock to read them, and (b) seeing deallocated memory. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: James Morris <jmorris@namei.org> Acked-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:

committed by
James Morris

parent
86a264abe5
commit
c69e8d9c01
@@ -447,7 +447,7 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||
struct audit_names *name,
|
||||
enum audit_state *state)
|
||||
{
|
||||
struct cred *cred = tsk->cred;
|
||||
const struct cred *cred = get_task_cred(tsk);
|
||||
int i, j, need_sid = 1;
|
||||
u32 sid;
|
||||
|
||||
@@ -642,8 +642,10 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!result)
|
||||
if (!result) {
|
||||
put_cred(cred);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (rule->filterkey && ctx)
|
||||
ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
|
||||
@@ -651,6 +653,7 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||
case AUDIT_NEVER: *state = AUDIT_DISABLED; break;
|
||||
case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break;
|
||||
}
|
||||
put_cred(cred);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1229,7 +1232,7 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
|
||||
|
||||
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
|
||||
{
|
||||
struct cred *cred = tsk->cred;
|
||||
const struct cred *cred;
|
||||
int i, call_panic = 0;
|
||||
struct audit_buffer *ab;
|
||||
struct audit_aux_data *aux;
|
||||
@@ -1239,13 +1242,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
|
||||
context->pid = tsk->pid;
|
||||
if (!context->ppid)
|
||||
context->ppid = sys_getppid();
|
||||
context->uid = cred->uid;
|
||||
context->gid = cred->gid;
|
||||
context->euid = cred->euid;
|
||||
context->suid = cred->suid;
|
||||
cred = current_cred();
|
||||
context->uid = cred->uid;
|
||||
context->gid = cred->gid;
|
||||
context->euid = cred->euid;
|
||||
context->suid = cred->suid;
|
||||
context->fsuid = cred->fsuid;
|
||||
context->egid = cred->egid;
|
||||
context->sgid = cred->sgid;
|
||||
context->egid = cred->egid;
|
||||
context->sgid = cred->sgid;
|
||||
context->fsgid = cred->fsgid;
|
||||
context->personality = tsk->personality;
|
||||
|
||||
@@ -2088,7 +2092,7 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
|
||||
audit_log_format(ab, "login pid=%d uid=%u "
|
||||
"old auid=%u new auid=%u"
|
||||
" old ses=%u new ses=%u",
|
||||
task->pid, task->cred->uid,
|
||||
task->pid, task_uid(task),
|
||||
task->loginuid, loginuid,
|
||||
task->sessionid, sessionid);
|
||||
audit_log_end(ab);
|
||||
@@ -2471,7 +2475,7 @@ void __audit_ptrace(struct task_struct *t)
|
||||
|
||||
context->target_pid = t->pid;
|
||||
context->target_auid = audit_get_loginuid(t);
|
||||
context->target_uid = t->cred->uid;
|
||||
context->target_uid = task_uid(t);
|
||||
context->target_sessionid = audit_get_sessionid(t);
|
||||
security_task_getsecid(t, &context->target_sid);
|
||||
memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
|
||||
@@ -2490,6 +2494,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
|
||||
struct audit_aux_data_pids *axp;
|
||||
struct task_struct *tsk = current;
|
||||
struct audit_context *ctx = tsk->audit_context;
|
||||
uid_t uid = current_uid(), t_uid = task_uid(t);
|
||||
|
||||
if (audit_pid && t->tgid == audit_pid) {
|
||||
if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) {
|
||||
@@ -2497,7 +2502,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
|
||||
if (tsk->loginuid != -1)
|
||||
audit_sig_uid = tsk->loginuid;
|
||||
else
|
||||
audit_sig_uid = tsk->cred->uid;
|
||||
audit_sig_uid = uid;
|
||||
security_task_getsecid(tsk, &audit_sig_sid);
|
||||
}
|
||||
if (!audit_signals || audit_dummy_context())
|
||||
@@ -2509,7 +2514,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
|
||||
if (!ctx->target_pid) {
|
||||
ctx->target_pid = t->tgid;
|
||||
ctx->target_auid = audit_get_loginuid(t);
|
||||
ctx->target_uid = t->cred->uid;
|
||||
ctx->target_uid = t_uid;
|
||||
ctx->target_sessionid = audit_get_sessionid(t);
|
||||
security_task_getsecid(t, &ctx->target_sid);
|
||||
memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
|
||||
@@ -2530,7 +2535,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
|
||||
|
||||
axp->target_pid[axp->pid_count] = t->tgid;
|
||||
axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
|
||||
axp->target_uid[axp->pid_count] = t->cred->uid;
|
||||
axp->target_uid[axp->pid_count] = t_uid;
|
||||
axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
|
||||
security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
|
||||
memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
|
||||
|
@@ -1279,7 +1279,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
|
||||
static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
|
||||
{
|
||||
struct task_struct *tsk;
|
||||
uid_t euid;
|
||||
const struct cred *cred = current_cred(), *tcred;
|
||||
int ret;
|
||||
|
||||
if (pid) {
|
||||
@@ -1289,16 +1289,16 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
|
||||
rcu_read_unlock();
|
||||
return -ESRCH;
|
||||
}
|
||||
get_task_struct(tsk);
|
||||
rcu_read_unlock();
|
||||
|
||||
euid = current_euid();
|
||||
if (euid &&
|
||||
euid != tsk->cred->uid &&
|
||||
euid != tsk->cred->suid) {
|
||||
put_task_struct(tsk);
|
||||
tcred = __task_cred(tsk);
|
||||
if (cred->euid &&
|
||||
cred->euid != tcred->uid &&
|
||||
cred->euid != tcred->suid) {
|
||||
rcu_read_unlock();
|
||||
return -EACCES;
|
||||
}
|
||||
get_task_struct(tsk);
|
||||
rcu_read_unlock();
|
||||
} else {
|
||||
tsk = current;
|
||||
get_task_struct(tsk);
|
||||
|
@@ -160,7 +160,10 @@ void release_task(struct task_struct * p)
|
||||
int zap_leader;
|
||||
repeat:
|
||||
tracehook_prepare_release_task(p);
|
||||
atomic_dec(&p->cred->user->processes);
|
||||
/* don't need to get the RCU readlock here - the process is dead and
|
||||
* can't be modifying its own credentials */
|
||||
atomic_dec(&__task_cred(p)->user->processes);
|
||||
|
||||
proc_flush_task(p);
|
||||
write_lock_irq(&tasklist_lock);
|
||||
tracehook_finish_release_task(p);
|
||||
@@ -1267,12 +1270,12 @@ static int wait_task_zombie(struct task_struct *p, int options,
|
||||
unsigned long state;
|
||||
int retval, status, traced;
|
||||
pid_t pid = task_pid_vnr(p);
|
||||
uid_t uid = __task_cred(p)->uid;
|
||||
|
||||
if (!likely(options & WEXITED))
|
||||
return 0;
|
||||
|
||||
if (unlikely(options & WNOWAIT)) {
|
||||
uid_t uid = p->cred->uid;
|
||||
int exit_code = p->exit_code;
|
||||
int why, status;
|
||||
|
||||
@@ -1393,7 +1396,7 @@ static int wait_task_zombie(struct task_struct *p, int options,
|
||||
if (!retval && infop)
|
||||
retval = put_user(pid, &infop->si_pid);
|
||||
if (!retval && infop)
|
||||
retval = put_user(p->cred->uid, &infop->si_uid);
|
||||
retval = put_user(uid, &infop->si_uid);
|
||||
if (!retval)
|
||||
retval = pid;
|
||||
|
||||
@@ -1458,7 +1461,8 @@ static int wait_task_stopped(int ptrace, struct task_struct *p,
|
||||
if (!unlikely(options & WNOWAIT))
|
||||
p->exit_code = 0;
|
||||
|
||||
uid = p->cred->uid;
|
||||
/* don't need the RCU readlock here as we're holding a spinlock */
|
||||
uid = __task_cred(p)->uid;
|
||||
unlock_sig:
|
||||
spin_unlock_irq(&p->sighand->siglock);
|
||||
if (!exit_code)
|
||||
@@ -1532,10 +1536,10 @@ static int wait_task_continued(struct task_struct *p, int options,
|
||||
}
|
||||
if (!unlikely(options & WNOWAIT))
|
||||
p->signal->flags &= ~SIGNAL_STOP_CONTINUED;
|
||||
uid = __task_cred(p)->uid;
|
||||
spin_unlock_irq(&p->sighand->siglock);
|
||||
|
||||
pid = task_pid_vnr(p);
|
||||
uid = p->cred->uid;
|
||||
get_task_struct(p);
|
||||
read_unlock(&tasklist_lock);
|
||||
|
||||
|
@@ -439,15 +439,20 @@ static void free_pi_state(struct futex_pi_state *pi_state)
|
||||
static struct task_struct * futex_find_get_task(pid_t pid)
|
||||
{
|
||||
struct task_struct *p;
|
||||
uid_t euid = current_euid();
|
||||
const struct cred *cred = current_cred(), *pcred;
|
||||
|
||||
rcu_read_lock();
|
||||
p = find_task_by_vpid(pid);
|
||||
if (!p || (euid != p->cred->euid &&
|
||||
euid != p->cred->uid))
|
||||
if (!p) {
|
||||
p = ERR_PTR(-ESRCH);
|
||||
else
|
||||
get_task_struct(p);
|
||||
} else {
|
||||
pcred = __task_cred(p);
|
||||
if (cred->euid != pcred->euid &&
|
||||
cred->euid != pcred->uid)
|
||||
p = ERR_PTR(-ESRCH);
|
||||
else
|
||||
get_task_struct(p);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
@@ -1831,7 +1836,7 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
|
||||
{
|
||||
struct robust_list_head __user *head;
|
||||
unsigned long ret;
|
||||
uid_t euid = current_euid();
|
||||
const struct cred *cred = current_cred(), *pcred;
|
||||
|
||||
if (!futex_cmpxchg_enabled)
|
||||
return -ENOSYS;
|
||||
@@ -1847,8 +1852,9 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
|
||||
if (!p)
|
||||
goto err_unlock;
|
||||
ret = -EPERM;
|
||||
if (euid != p->cred->euid &&
|
||||
euid != p->cred->uid &&
|
||||
pcred = __task_cred(p);
|
||||
if (cred->euid != pcred->euid &&
|
||||
cred->euid != pcred->uid &&
|
||||
!capable(CAP_SYS_PTRACE))
|
||||
goto err_unlock;
|
||||
head = p->robust_list;
|
||||
|
@@ -135,7 +135,7 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
|
||||
{
|
||||
struct compat_robust_list_head __user *head;
|
||||
unsigned long ret;
|
||||
uid_t euid = current_euid();
|
||||
const struct cred *cred = current_cred(), *pcred;
|
||||
|
||||
if (!futex_cmpxchg_enabled)
|
||||
return -ENOSYS;
|
||||
@@ -151,8 +151,9 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
|
||||
if (!p)
|
||||
goto err_unlock;
|
||||
ret = -EPERM;
|
||||
if (euid != p->cred->euid &&
|
||||
euid != p->cred->uid &&
|
||||
pcred = __task_cred(p);
|
||||
if (cred->euid != pcred->euid &&
|
||||
cred->euid != pcred->uid &&
|
||||
!capable(CAP_SYS_PTRACE))
|
||||
goto err_unlock;
|
||||
head = p->compat_robust_list;
|
||||
|
@@ -115,7 +115,7 @@ int ptrace_check_attach(struct task_struct *child, int kill)
|
||||
|
||||
int __ptrace_may_access(struct task_struct *task, unsigned int mode)
|
||||
{
|
||||
struct cred *cred = current->cred, *tcred = task->cred;
|
||||
const struct cred *cred = current_cred(), *tcred;
|
||||
|
||||
/* May we inspect the given task?
|
||||
* This check is used both for attaching with ptrace
|
||||
@@ -125,19 +125,23 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
|
||||
* because setting up the necessary parent/child relationship
|
||||
* or halting the specified task is impossible.
|
||||
*/
|
||||
uid_t uid = cred->uid;
|
||||
gid_t gid = cred->gid;
|
||||
int dumpable = 0;
|
||||
/* Don't let security modules deny introspection */
|
||||
if (task == current)
|
||||
return 0;
|
||||
if ((uid != tcred->euid ||
|
||||
uid != tcred->suid ||
|
||||
uid != tcred->uid ||
|
||||
gid != tcred->egid ||
|
||||
gid != tcred->sgid ||
|
||||
gid != tcred->gid) && !capable(CAP_SYS_PTRACE))
|
||||
rcu_read_lock();
|
||||
tcred = __task_cred(task);
|
||||
if ((cred->uid != tcred->euid ||
|
||||
cred->uid != tcred->suid ||
|
||||
cred->uid != tcred->uid ||
|
||||
cred->gid != tcred->egid ||
|
||||
cred->gid != tcred->sgid ||
|
||||
cred->gid != tcred->gid) &&
|
||||
!capable(CAP_SYS_PTRACE)) {
|
||||
rcu_read_unlock();
|
||||
return -EPERM;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
smp_rmb();
|
||||
if (task->mm)
|
||||
dumpable = get_dumpable(task->mm);
|
||||
|
@@ -345,7 +345,9 @@ static inline struct task_group *task_group(struct task_struct *p)
|
||||
struct task_group *tg;
|
||||
|
||||
#ifdef CONFIG_USER_SCHED
|
||||
tg = p->cred->user->tg;
|
||||
rcu_read_lock();
|
||||
tg = __task_cred(p)->user->tg;
|
||||
rcu_read_unlock();
|
||||
#elif defined(CONFIG_CGROUP_SCHED)
|
||||
tg = container_of(task_subsys_state(p, cpu_cgroup_subsys_id),
|
||||
struct task_group, css);
|
||||
@@ -5121,6 +5123,22 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
|
||||
set_load_weight(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* check the target process has a UID that matches the current process's
|
||||
*/
|
||||
static bool check_same_owner(struct task_struct *p)
|
||||
{
|
||||
const struct cred *cred = current_cred(), *pcred;
|
||||
bool match;
|
||||
|
||||
rcu_read_lock();
|
||||
pcred = __task_cred(p);
|
||||
match = (cred->euid == pcred->euid ||
|
||||
cred->euid == pcred->uid);
|
||||
rcu_read_unlock();
|
||||
return match;
|
||||
}
|
||||
|
||||
static int __sched_setscheduler(struct task_struct *p, int policy,
|
||||
struct sched_param *param, bool user)
|
||||
{
|
||||
@@ -5128,7 +5146,6 @@ static int __sched_setscheduler(struct task_struct *p, int policy,
|
||||
unsigned long flags;
|
||||
const struct sched_class *prev_class = p->sched_class;
|
||||
struct rq *rq;
|
||||
uid_t euid;
|
||||
|
||||
/* may grab non-irq protected spin_locks */
|
||||
BUG_ON(in_interrupt());
|
||||
@@ -5181,9 +5198,7 @@ recheck:
|
||||
return -EPERM;
|
||||
|
||||
/* can't change other user's priorities */
|
||||
euid = current_euid();
|
||||
if (euid != p->cred->euid &&
|
||||
euid != p->cred->uid)
|
||||
if (!check_same_owner(p))
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
@@ -5394,7 +5409,6 @@ long sched_setaffinity(pid_t pid, const cpumask_t *in_mask)
|
||||
cpumask_t cpus_allowed;
|
||||
cpumask_t new_mask = *in_mask;
|
||||
struct task_struct *p;
|
||||
uid_t euid;
|
||||
int retval;
|
||||
|
||||
get_online_cpus();
|
||||
@@ -5415,11 +5429,8 @@ long sched_setaffinity(pid_t pid, const cpumask_t *in_mask)
|
||||
get_task_struct(p);
|
||||
read_unlock(&tasklist_lock);
|
||||
|
||||
euid = current_euid();
|
||||
retval = -EPERM;
|
||||
if (euid != p->cred->euid &&
|
||||
euid != p->cred->uid &&
|
||||
!capable(CAP_SYS_NICE))
|
||||
if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
|
||||
goto out_unlock;
|
||||
|
||||
retval = security_task_setscheduler(p, 0, NULL);
|
||||
|
@@ -177,6 +177,11 @@ int next_signal(struct sigpending *pending, sigset_t *mask)
|
||||
return sig;
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate a new signal queue record
|
||||
* - this may be called without locks if and only if t == current, otherwise an
|
||||
* appopriate lock must be held to protect t's user_struct
|
||||
*/
|
||||
static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
|
||||
int override_rlimit)
|
||||
{
|
||||
@@ -184,11 +189,12 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
|
||||
struct user_struct *user;
|
||||
|
||||
/*
|
||||
* In order to avoid problems with "switch_user()", we want to make
|
||||
* sure that the compiler doesn't re-load "t->user"
|
||||
* We won't get problems with the target's UID changing under us
|
||||
* because changing it requires RCU be used, and if t != current, the
|
||||
* caller must be holding the RCU readlock (by way of a spinlock) and
|
||||
* we use RCU protection here
|
||||
*/
|
||||
user = t->cred->user;
|
||||
barrier();
|
||||
user = __task_cred(t)->user;
|
||||
atomic_inc(&user->sigpending);
|
||||
if (override_rlimit ||
|
||||
atomic_read(&user->sigpending) <=
|
||||
@@ -562,12 +568,13 @@ static int rm_from_queue(unsigned long mask, struct sigpending *s)
|
||||
|
||||
/*
|
||||
* Bad permissions for sending the signal
|
||||
* - the caller must hold at least the RCU read lock
|
||||
*/
|
||||
static int check_kill_permission(int sig, struct siginfo *info,
|
||||
struct task_struct *t)
|
||||
{
|
||||
const struct cred *cred = current_cred(), *tcred;
|
||||
struct pid *sid;
|
||||
uid_t uid, euid;
|
||||
int error;
|
||||
|
||||
if (!valid_signal(sig))
|
||||
@@ -580,10 +587,11 @@ static int check_kill_permission(int sig, struct siginfo *info,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
uid = current_uid();
|
||||
euid = current_euid();
|
||||
if ((euid ^ t->cred->suid) && (euid ^ t->cred->uid) &&
|
||||
(uid ^ t->cred->suid) && (uid ^ t->cred->uid) &&
|
||||
tcred = __task_cred(t);
|
||||
if ((cred->euid ^ tcred->suid) &&
|
||||
(cred->euid ^ tcred->uid) &&
|
||||
(cred->uid ^ tcred->suid) &&
|
||||
(cred->uid ^ tcred->uid) &&
|
||||
!capable(CAP_KILL)) {
|
||||
switch (sig) {
|
||||
case SIGCONT:
|
||||
@@ -1011,6 +1019,10 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long
|
||||
return sighand;
|
||||
}
|
||||
|
||||
/*
|
||||
* send signal info to all the members of a group
|
||||
* - the caller must hold the RCU read lock at least
|
||||
*/
|
||||
int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
|
||||
{
|
||||
unsigned long flags;
|
||||
@@ -1032,8 +1044,8 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
|
||||
/*
|
||||
* __kill_pgrp_info() sends a signal to a process group: this is what the tty
|
||||
* control characters do (^C, ^Z etc)
|
||||
* - the caller must hold at least a readlock on tasklist_lock
|
||||
*/
|
||||
|
||||
int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp)
|
||||
{
|
||||
struct task_struct *p = NULL;
|
||||
@@ -1089,6 +1101,7 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
struct task_struct *p;
|
||||
const struct cred *pcred;
|
||||
|
||||
if (!valid_signal(sig))
|
||||
return ret;
|
||||
@@ -1099,9 +1112,11 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
|
||||
ret = -ESRCH;
|
||||
goto out_unlock;
|
||||
}
|
||||
if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
|
||||
&& (euid != p->cred->suid) && (euid != p->cred->uid)
|
||||
&& (uid != p->cred->suid) && (uid != p->cred->uid)) {
|
||||
pcred = __task_cred(p);
|
||||
if ((info == SEND_SIG_NOINFO ||
|
||||
(!is_si_special(info) && SI_FROMUSER(info))) &&
|
||||
euid != pcred->suid && euid != pcred->uid &&
|
||||
uid != pcred->suid && uid != pcred->uid) {
|
||||
ret = -EPERM;
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -1372,10 +1387,9 @@ int do_notify_parent(struct task_struct *tsk, int sig)
|
||||
*/
|
||||
rcu_read_lock();
|
||||
info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
|
||||
info.si_uid = __task_cred(tsk)->uid;
|
||||
rcu_read_unlock();
|
||||
|
||||
info.si_uid = tsk->cred->uid;
|
||||
|
||||
thread_group_cputime(tsk, &cputime);
|
||||
info.si_utime = cputime_to_jiffies(cputime.utime);
|
||||
info.si_stime = cputime_to_jiffies(cputime.stime);
|
||||
@@ -1443,10 +1457,9 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
|
||||
*/
|
||||
rcu_read_lock();
|
||||
info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
|
||||
info.si_uid = __task_cred(tsk)->uid;
|
||||
rcu_read_unlock();
|
||||
|
||||
info.si_uid = tsk->cred->uid;
|
||||
|
||||
info.si_utime = cputime_to_clock_t(tsk->utime);
|
||||
info.si_stime = cputime_to_clock_t(tsk->stime);
|
||||
|
||||
@@ -1713,7 +1726,7 @@ static int ptrace_signal(int signr, siginfo_t *info,
|
||||
info->si_errno = 0;
|
||||
info->si_code = SI_USER;
|
||||
info->si_pid = task_pid_vnr(current->parent);
|
||||
info->si_uid = current->parent->cred->uid;
|
||||
info->si_uid = task_uid(current->parent);
|
||||
}
|
||||
|
||||
/* If the (new) signal is now blocked, requeue it. */
|
||||
|
11
kernel/sys.c
11
kernel/sys.c
@@ -112,14 +112,17 @@ EXPORT_SYMBOL(cad_pid);
|
||||
|
||||
void (*pm_power_off_prepare)(void);
|
||||
|
||||
/*
|
||||
* set the priority of a task
|
||||
* - the caller must hold the RCU read lock
|
||||
*/
|
||||
static int set_one_prio(struct task_struct *p, int niceval, int error)
|
||||
{
|
||||
uid_t euid = current_euid();
|
||||
const struct cred *cred = current_cred(), *pcred = __task_cred(p);
|
||||
int no_nice;
|
||||
|
||||
if (p->cred->uid != euid &&
|
||||
p->cred->euid != euid &&
|
||||
!capable(CAP_SYS_NICE)) {
|
||||
if (pcred->uid != cred->euid &&
|
||||
pcred->euid != cred->euid && !capable(CAP_SYS_NICE)) {
|
||||
error = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@
|
||||
*/
|
||||
void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
|
||||
{
|
||||
const struct cred *tcred;
|
||||
struct timespec uptime, ts;
|
||||
u64 ac_etime;
|
||||
|
||||
@@ -53,10 +54,11 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk)
|
||||
stats->ac_flag |= AXSIG;
|
||||
stats->ac_nice = task_nice(tsk);
|
||||
stats->ac_sched = tsk->policy;
|
||||
stats->ac_uid = tsk->cred->uid;
|
||||
stats->ac_gid = tsk->cred->gid;
|
||||
stats->ac_pid = tsk->pid;
|
||||
rcu_read_lock();
|
||||
tcred = __task_cred(tsk);
|
||||
stats->ac_uid = tcred->uid;
|
||||
stats->ac_gid = tcred->gid;
|
||||
stats->ac_ppid = pid_alive(tsk) ?
|
||||
rcu_dereference(tsk->real_parent)->tgid : 0;
|
||||
rcu_read_unlock();
|
||||
|
Reference in New Issue
Block a user